From 123f79ce4da5aa6473a6a2f49a8e5e0a9d5ea58d Mon Sep 17 00:00:00 2001 From: Huarch Date: Tue, 30 Jun 2026 19:59:34 +0800 Subject: [PATCH] fix(agent): resolve question call id replies --- .opencode/package-lock.json | 361 ++++++++++++++++++++++++++++ src/routes/chatInteractionRoutes.ts | 59 +++-- 2 files changed, 402 insertions(+), 18 deletions(-) create mode 100644 .opencode/package-lock.json diff --git a/.opencode/package-lock.json b/.opencode/package-lock.json new file mode 100644 index 0000000..52e7dc2 --- /dev/null +++ b/.opencode/package-lock.json @@ -0,0 +1,361 @@ +{ + "name": ".opencode", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@opencode-ai/plugin": "^1.16.2" + }, + "devDependencies": { + "@types/node": "^24.7.2", + "typescript": "^5.9.3" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", + "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", + "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", + "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", + "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.4", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", + "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@opencode-ai/plugin": { + "version": "1.16.2", + "license": "MIT", + "dependencies": { + "@opencode-ai/sdk": "1.16.2", + "effect": "4.0.0-beta.74", + "zod": "4.1.8" + }, + "peerDependencies": { + "@opentui/core": ">=0.3.2", + "@opentui/keymap": ">=0.3.2", + "@opentui/solid": ">=0.3.2" + }, + "peerDependenciesMeta": { + "@opentui/core": { + "optional": true + }, + "@opentui/keymap": { + "optional": true + }, + "@opentui/solid": { + "optional": true + } + } + }, + "node_modules/@opencode-ai/sdk": { + "version": "1.16.2", + "license": "MIT", + "dependencies": { + "cross-spawn": "7.0.6" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.12.4", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/effect": { + "version": "4.0.0-beta.74", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "fast-check": "^4.8.0", + "find-my-way-ts": "^0.1.6", + "ini": "^7.0.0", + "kubernetes-types": "^1.30.0", + "msgpackr": "^2.0.1", + "multipasta": "^0.2.7", + "toml": "^4.1.1", + "uuid": "^14.0.0", + "yaml": "^2.9.0" + } + }, + "node_modules/fast-check": { + "version": "4.8.0", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^8.0.0" + }, + "engines": { + "node": ">=12.17.0" + } + }, + "node_modules/find-my-way-ts": { + "version": "0.1.6", + "license": "MIT" + }, + "node_modules/ini": { + "version": "7.0.0", + "license": "ISC", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/kubernetes-types": { + "version": "1.30.0", + "license": "Apache-2.0" + }, + "node_modules/msgpackr": { + "version": "2.0.2", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.4" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.4", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" + } + }, + "node_modules/multipasta": { + "version": "0.2.7", + "license": "MIT" + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pure-rand": { + "version": "8.4.0", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/toml": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "14.0.0", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/zod": { + "version": "4.1.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/src/routes/chatInteractionRoutes.ts b/src/routes/chatInteractionRoutes.ts index d9a18a0..313e434 100644 --- a/src/routes/chatInteractionRoutes.ts +++ b/src/routes/chatInteractionRoutes.ts @@ -36,10 +36,33 @@ type RegisterInteractionRoutesOptions = { sessionUiStateStore: SessionUiStateStore; }; +type ResolvedPendingQuestion = { + requestId: string; + question: NonNullable>; +}; + const toSessionUiStateContext = (sessionId: string) => ({ sessionId, }); +const resolvePendingQuestion = ( + run: ActiveRun, + requestId: string, +): ResolvedPendingQuestion | null => { + const exactQuestion = run.pendingQuestions.get(requestId); + if (exactQuestion) { + return { requestId, question: exactQuestion }; + } + + for (const [pendingRequestId, question] of run.pendingQuestions.entries()) { + if (question.tool?.callID === requestId) { + return { requestId: pendingRequestId, question }; + } + } + + return null; +}; + export const registerChatInteractionRoutes = ( chatRouter: Router, { @@ -210,7 +233,7 @@ export const registerChatInteractionRoutes = ( return; } - const pendingQuestion = run.pendingQuestions.get(requestId); + const pendingQuestion = resolvePendingQuestion(run, requestId); if (!pendingQuestion) { res.status(404).json({ message: "question request not found" }); return; @@ -228,14 +251,14 @@ export const registerChatInteractionRoutes = ( try { await runtime.replyQuestion({ - requestId, + requestId: pendingQuestion.requestId, sessionId: sessionRecord.sessionId, answers: parsed.data.answers, }); } catch (error) { run.messages = updateLastAssistantQuestion( run.messages, - requestId, + pendingQuestion.requestId, (question) => ({ ...question, status: "error", @@ -258,10 +281,10 @@ export const registerChatInteractionRoutes = ( return; } - run.pendingQuestions.delete(requestId); + run.pendingQuestions.delete(pendingQuestion.requestId); run.messages = updateLastAssistantQuestion( run.messages, - requestId, + pendingQuestion.requestId, (question) => ({ ...question, status: "answered", @@ -278,8 +301,8 @@ export const registerChatInteractionRoutes = ( }); for (const subscriber of run.subscribers) { subscriber.write("question_response", { - session_id: pendingQuestion.session_id, - request_id: requestId, + session_id: pendingQuestion.question.session_id, + request_id: pendingQuestion.requestId, answers: parsed.data.answers, }); } @@ -292,8 +315,8 @@ export const registerChatInteractionRoutes = ( } res.status(202).json({ - session_id: pendingQuestion.session_id, - request_id: requestId, + session_id: pendingQuestion.question.session_id, + request_id: pendingQuestion.requestId, answers: parsed.data.answers, }); } catch (error) { @@ -342,7 +365,7 @@ export const registerChatInteractionRoutes = ( return; } - const pendingQuestion = run.pendingQuestions.get(requestId); + const pendingQuestion = resolvePendingQuestion(run, requestId); if (!pendingQuestion) { res.status(404).json({ message: "question request not found" }); return; @@ -360,13 +383,13 @@ export const registerChatInteractionRoutes = ( try { await runtime.rejectQuestion({ - requestId, + requestId: pendingQuestion.requestId, sessionId: sessionRecord.sessionId, }); } catch (error) { run.messages = updateLastAssistantQuestion( run.messages, - requestId, + pendingQuestion.requestId, (question) => ({ ...question, status: "error", @@ -389,10 +412,10 @@ export const registerChatInteractionRoutes = ( return; } - run.pendingQuestions.delete(requestId); + run.pendingQuestions.delete(pendingQuestion.requestId); run.messages = updateLastAssistantQuestion( run.messages, - requestId, + pendingQuestion.requestId, (question) => ({ ...question, status: "rejected", @@ -408,8 +431,8 @@ export const registerChatInteractionRoutes = ( }); for (const subscriber of run.subscribers) { subscriber.write("question_response", { - session_id: pendingQuestion.session_id, - request_id: requestId, + session_id: pendingQuestion.question.session_id, + request_id: pendingQuestion.requestId, rejected: true, }); } @@ -422,8 +445,8 @@ export const registerChatInteractionRoutes = ( } res.status(202).json({ - session_id: pendingQuestion.session_id, - request_id: requestId, + session_id: pendingQuestion.question.session_id, + request_id: pendingQuestion.requestId, rejected: true, }); } catch (error) {