From 1a251ad885af27a5409bfeb71b2fa9577d586b97 Mon Sep 17 00:00:00 2001 From: Junyi Hou Date: Mon, 8 Dec 2025 01:38:15 +0800 Subject: [PATCH 1/2] chore: disable beta feature --- webapp/_webapp/src/views/settings/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/_webapp/src/views/settings/index.tsx b/webapp/_webapp/src/views/settings/index.tsx index dcb676f5..102c7a42 100644 --- a/webapp/_webapp/src/views/settings/index.tsx +++ b/webapp/_webapp/src/views/settings/index.tsx @@ -32,7 +32,7 @@ export const Settings = () => {
- + {/* */} {enableUserDeveloperTools && } From e3e65a6ea453d3590b1d1e3c13e8c7fe1a3c72b6 Mon Sep 17 00:00:00 2001 From: Junyi Hou Date: Mon, 8 Dec 2025 01:40:58 +0800 Subject: [PATCH 2/2] fix: build & format --- .../src/components/loading-indicator.tsx | 3 +- .../message-entry-container/tools/jsonrpc.tsx | 26 ++-- .../message-entry-container/tools/tools.tsx | 13 +- .../tools/utils/common.tsx | 140 +++++++++--------- webapp/_webapp/src/index.css | 1 - webapp/_webapp/src/libs/overleaf-socket.ts | 2 +- webapp/_webapp/src/views/login/index.tsx | 21 +-- webapp/_webapp/src/views/settings/index.tsx | 2 - 8 files changed, 111 insertions(+), 97 deletions(-) diff --git a/webapp/_webapp/src/components/loading-indicator.tsx b/webapp/_webapp/src/components/loading-indicator.tsx index 6b3a1498..5198ad9a 100644 --- a/webapp/_webapp/src/components/loading-indicator.tsx +++ b/webapp/_webapp/src/components/loading-indicator.tsx @@ -113,7 +113,8 @@ export const LoadingIndicator = ({ text = "Thinking", estimatedSeconds = 0, erro // Get status message based on phase const getStatusMessage = () => { - if (isTimeout) return "Sorry — this request took too long to complete. We're working on improving reliability. You can try waiting a bit longer or refreshing the page. Thanks for your patience."; + if (isTimeout) + return "Sorry — this request took too long to complete. We're working on improving reliability. You can try waiting a bit longer or refreshing the page. Thanks for your patience."; if (phase === "orange") return "Synthesizing..."; if (phase === "red") return "Just a moment..."; if (errorMessage && errorMessage.length > 0) return errorMessage; diff --git a/webapp/_webapp/src/components/message-entry-container/tools/jsonrpc.tsx b/webapp/_webapp/src/components/message-entry-container/tools/jsonrpc.tsx index 5a1481b7..d5603785 100644 --- a/webapp/_webapp/src/components/message-entry-container/tools/jsonrpc.tsx +++ b/webapp/_webapp/src/components/message-entry-container/tools/jsonrpc.tsx @@ -39,7 +39,7 @@ export const JsonRpc = ({ functionName, jsonRpcResult, preparing, animated }: Js >
- -
+ +
{jsonRpcResult.result && (
- {jsonRpcResult.result.content?.map((content) => content.text).join("\n") || ""} - -
- )} - - {jsonRpcResult.error && ( -
- {jsonRpcResult.error.message} + {jsonRpcResult.result.content?.map((content) => content.text).join("\n") || ""} +
)} + + {jsonRpcResult.error &&
{jsonRpcResult.error.message}
}
); diff --git a/webapp/_webapp/src/components/message-entry-container/tools/tools.tsx b/webapp/_webapp/src/components/message-entry-container/tools/tools.tsx index c55af294..3357c169 100644 --- a/webapp/_webapp/src/components/message-entry-container/tools/tools.tsx +++ b/webapp/_webapp/src/components/message-entry-container/tools/tools.tsx @@ -46,12 +46,21 @@ export default function Tools({ messageId, functionName, message, error, prepari } else if (functionName === "always_exception") { return ; } else if (XTRA_MCP_TOOL_NAMES.includes(functionName)) { - return ; + return ( + + ); } // fallback to unknown tool card if the json rpc result is not defined if (jsonRpcResult) { - return ; + return ( + + ); } else { return ; } diff --git a/webapp/_webapp/src/components/message-entry-container/tools/utils/common.tsx b/webapp/_webapp/src/components/message-entry-container/tools/utils/common.tsx index 4a455dc5..92e09f2c 100644 --- a/webapp/_webapp/src/components/message-entry-container/tools/utils/common.tsx +++ b/webapp/_webapp/src/components/message-entry-container/tools/utils/common.tsx @@ -1,83 +1,91 @@ export type JsonRpcResult = { - jsonrpc: string; - id: number; - result?: { - content: Array<{ - type: string; - text: string; - }>; - }; - error?: { - code: number; - message: string; - } -} + jsonrpc: string; + id: number; + result?: { + content: Array<{ + type: string; + text: string; + }>; + }; + error?: { + code: number; + message: string; + }; +}; export const UNKNOWN_JSONRPC_RESULT: JsonRpcResult = { - jsonrpc: "2.0", - id: -1, - error: { - code: -1, - message: "Unknown JSONRPC result", - }, -} + jsonrpc: "2.0", + id: -1, + error: { + code: -1, + message: "Unknown JSONRPC result", + }, +}; const isValidJsonRpcResult = (obj: any): obj is JsonRpcResult => { - // Check if obj is an object and not null - if (typeof obj !== 'object' || obj === null) { - return false; - } + // Check if obj is an object and not null + if (typeof obj !== "object" || obj === null) { + return false; + } - // Check required properties - if (typeof obj.jsonrpc !== 'string' || typeof obj.id !== 'number') { - return false; - } + // Check required properties + if (typeof obj.jsonrpc !== "string" || typeof obj.id !== "number") { + return false; + } - // Check that either result or error is present (but not both required) - const hasResult = obj.result !== undefined; - const hasError = obj.error !== undefined; + // Check that either result or error is present (but not both required) + const hasResult = obj.result !== undefined; + const hasError = obj.error !== undefined; - // Validate result structure if present - if (hasResult) { - if (typeof obj.result !== 'object' || obj.result === null) { - return false; - } - if (obj.result.content !== undefined) { - if (!Array.isArray(obj.result.content)) { - return false; - } - // Validate each content item - for (const item of obj.result.content) { - if (typeof item !== 'object' || item === null || - typeof item.type !== 'string' || typeof item.text !== 'string') { - return false; - } - } + // Validate result structure if present + if (hasResult) { + if (typeof obj.result !== "object" || obj.result === null) { + return false; + } + if (obj.result.content !== undefined) { + if (!Array.isArray(obj.result.content)) { + return false; + } + // Validate each content item + for (const item of obj.result.content) { + if ( + typeof item !== "object" || + item === null || + typeof item.type !== "string" || + typeof item.text !== "string" + ) { + return false; } + } } + } - // Validate error structure if present - if (hasError) { - if (typeof obj.error !== 'object' || obj.error === null || - typeof obj.error.code !== 'number' || typeof obj.error.message !== 'string') { - return false; - } + // Validate error structure if present + if (hasError) { + if ( + typeof obj.error !== "object" || + obj.error === null || + typeof obj.error.code !== "number" || + typeof obj.error.message !== "string" + ) { + return false; } + } - return true; + return true; }; export const parseJsonRpcResult = (message: string): JsonRpcResult | undefined => { - try { - const json = JSON.parse(message); - - // Validate the structure before casting - if (isValidJsonRpcResult(json)) { - return json; - } - - return undefined; - } catch (error) { - return undefined; + try { + const json = JSON.parse(message); + + // Validate the structure before casting + if (isValidJsonRpcResult(json)) { + return json; } -} \ No newline at end of file + + return undefined; + } catch (error) { + return undefined; + } +}; diff --git a/webapp/_webapp/src/index.css b/webapp/_webapp/src/index.css index dc240301..9ea01888 100644 --- a/webapp/_webapp/src/index.css +++ b/webapp/_webapp/src/index.css @@ -109,7 +109,6 @@ body { @apply font-medium text-gray-500; } - /* 相邻 tool-card 的样式处理 */ .tool-card + .tool-card { /* 相邻的第二个卡片:移除上边框,调整上圆角,减少上边距,减少上 padding */ diff --git a/webapp/_webapp/src/libs/overleaf-socket.ts b/webapp/_webapp/src/libs/overleaf-socket.ts index 48c254c2..786d1fd5 100644 --- a/webapp/_webapp/src/libs/overleaf-socket.ts +++ b/webapp/_webapp/src/libs/overleaf-socket.ts @@ -245,7 +245,7 @@ export async function wsConnect( const wsUrl = import.meta.env.DEV ? "ws://localhost:3000" : "wss://" + currentDomain; const data = await res.text(); const sessionId = data.split(":")[0]; - + // Set cookies for WebSocket connection document.cookie = `overleaf_session2=${overleafAuth.cookieOverleafSession2}; path=/; domain=${import.meta.env.DEV ? "localhost" : currentDomain}`; document.cookie = `GCLB=${overleafAuth.cookieGCLB}; path=/; domain=${import.meta.env.DEV ? "localhost" : currentDomain}`; diff --git a/webapp/_webapp/src/views/login/index.tsx b/webapp/_webapp/src/views/login/index.tsx index a339e051..4baf3d2b 100644 --- a/webapp/_webapp/src/views/login/index.tsx +++ b/webapp/_webapp/src/views/login/index.tsx @@ -14,20 +14,21 @@ export const Login = () => { return (
- {!showEndpointSettings && <> - -
-

Welcome to

-
- Paper - Debugger + {!showEndpointSettings && ( + <> + +
+

Welcome to

+
+ Paper + Debugger +
-
- } + + )} {showEndpointSettings && }
- {
- {/* */} {enableUserDeveloperTools && }