@jingyi0605/codingns 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/public/assets/{AdaptiveButlerPage-SffCV4Vb.js → AdaptiveButlerPage-uFwDdN-F.js} +3 -3
- package/dist/public/assets/App-BZvapsi8.js +30 -0
- package/dist/public/assets/App-CcDXqFl1.css +1 -0
- package/dist/public/assets/{BootstrapPage--zExdgfM.js → BootstrapPage-gHSoa4JN.js} +1 -1
- package/dist/public/assets/ConversationPage-z3sXtKZ7.js +4 -0
- package/dist/public/assets/{DesktopDetachPreviewPage-DvI9CIKi.js → DesktopDetachPreviewPage-4eMRxiBW.js} +1 -1
- package/dist/public/assets/DesktopWindowPage-CZcoGApB.js +2 -0
- package/dist/public/assets/FileContextPanel-C3qex8bb.js +1 -0
- package/dist/public/assets/GitSidebar-BK6H16XU.js +6 -0
- package/dist/public/assets/{MobileCreateSessionSheet-CXSKMnYn.js → MobileCreateSessionSheet-BYfbvK8o.js} +1 -1
- package/dist/public/assets/MobileSheet-Ckug8hTb.js +1 -0
- package/dist/public/assets/{MobileTopHeaderFrame-BWorAJ1C.js → MobileTopHeaderFrame-Bwv8Ovm_.js} +1 -1
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-RqWrBdn2.js +1 -0
- package/dist/public/assets/RelayConnectEntryPage-D_4YL-YH.js +1 -0
- package/dist/public/assets/ServerSettingsModal-CMSm3BZU.js +1 -0
- package/dist/public/assets/SessionIndexPage-DuK10DL5.js +1 -0
- package/dist/public/assets/SettingsPage-fyD-xaHL.js +1 -0
- package/dist/public/assets/TerminalManagerPanel-CCLr1Ypk.js +1 -0
- package/dist/public/assets/{TerminalPage-CvnHXBhw.js → TerminalPage-DaooFaJ4.js} +19 -19
- package/dist/public/assets/{TerminalRuntimeFallbackModal-D7Aq186N.js → TerminalRuntimeFallbackModal-aUzjEBwP.js} +1 -1
- package/dist/public/assets/ToolFilesPage-CGxBvYG0.js +1 -0
- package/dist/public/assets/ToolGitPage-C264yjS9.js +1 -0
- package/dist/public/assets/ToolProcessesPage-BOP4A1cb.js +1 -0
- package/dist/public/assets/ToolsHomePage-CQxGiKQA.js +1 -0
- package/dist/public/assets/WorkbenchLandingPage-CvAY68ca.js +1 -0
- package/dist/public/assets/WorkbenchLayout-DGm8Tc5M.js +3 -0
- package/dist/public/assets/{WorkbenchModal-B09hC9b5.js → WorkbenchModal-0tPIIhca.js} +1 -1
- package/dist/public/assets/{WorkbenchShellRoute-DsW4mBTX.css → WorkbenchShellRoute-BF0nHWOk.css} +1 -1
- package/dist/public/assets/WorkbenchShellRoute-DBBOsJo9.js +1 -0
- package/dist/public/assets/WorkspaceDebugDetailPage-CDerFYd2.js +1 -0
- package/dist/public/assets/WorkspaceDetailPage-BlJc1CHE.js +1 -0
- package/dist/public/assets/WorkspaceHomePage-BUsKJ3lv.js +1 -0
- package/dist/public/assets/client-runtime-manager-BZpL17fc.js +1 -0
- package/dist/public/assets/{default-session-permission-mode-D0wZ9Jek.js → default-session-permission-mode-DT4SGiwp.js} +1 -1
- package/dist/public/assets/file-tree-icon-Db5LXC8h.js +31 -0
- package/dist/public/assets/index-BZLcEHW3.js +42 -0
- package/dist/public/assets/index-BbspQPC2.css +1 -0
- package/dist/public/assets/login-direct-candidate-resolver-1mxe_Oh8.js +1 -0
- package/dist/public/assets/{preferences-service-gOt2ZjKZ.js → preferences-service-DWnzl5a0.js} +1 -1
- package/dist/public/assets/relay-entry-C5_Iay0I.js +1 -0
- package/dist/public/assets/session-runtime-machine-DdLeDqQr.js +17 -0
- package/dist/public/assets/{styles-BWPBZvze.css → styles-CsEMfdaS.css} +1 -1
- package/dist/public/assets/{terminal-runtime-meta-BMT-rSEe.js → terminal-runtime-meta-cdtWVfCm.js} +1 -1
- package/dist/public/assets/{useRegisteredDebugTemplates-zMcEOGca.js → useRegisteredDebugTemplates-oFAQNIqh.js} +1 -1
- package/dist/public/assets/window-BVUB8gMK.js +1 -0
- package/dist/public/index.html +2 -2
- package/dist/server/config/env.d.ts +2 -0
- package/dist/server/config/env.js +39 -0
- package/dist/server/config/env.js.map +1 -1
- package/dist/server/modules/client/npm-global-package-service.d.ts +7 -1
- package/dist/server/modules/client/npm-global-package-service.js +149 -43
- package/dist/server/modules/client/npm-global-package-service.js.map +1 -1
- package/dist/server/modules/client/service-update-task-service.js +6 -2
- package/dist/server/modules/client/service-update-task-service.js.map +1 -1
- package/dist/server/modules/client/service-update-types.d.ts +2 -0
- package/dist/server/modules/git/git-controller.d.ts +3 -0
- package/dist/server/modules/git/git-controller.js +3 -0
- package/dist/server/modules/git/git-controller.js.map +1 -1
- package/dist/server/modules/git/git-read-service.js +47 -1
- package/dist/server/modules/git/git-read-service.js.map +1 -1
- package/dist/server/modules/git/git-write-service.d.ts +4 -0
- package/dist/server/modules/git/git-write-service.js +24 -0
- package/dist/server/modules/git/git-write-service.js.map +1 -1
- package/dist/server/modules/git/types.d.ts +1 -0
- package/dist/server/modules/git/workspace-repo-guard.d.ts +2 -0
- package/dist/server/modules/git/workspace-repo-guard.js +24 -10
- package/dist/server/modules/git/workspace-repo-guard.js.map +1 -1
- package/dist/server/modules/parallel-sessions/parallel-session-controller.d.ts +53 -0
- package/dist/server/modules/parallel-sessions/parallel-session-controller.js +70 -0
- package/dist/server/modules/parallel-sessions/parallel-session-controller.js.map +1 -0
- package/dist/server/modules/parallel-sessions/parallel-session-group-service.d.ts +83 -0
- package/dist/server/modules/parallel-sessions/parallel-session-group-service.js +591 -0
- package/dist/server/modules/parallel-sessions/parallel-session-group-service.js.map +1 -0
- package/dist/server/modules/parallel-sessions/session-isolated-workspace-service.d.ts +56 -0
- package/dist/server/modules/parallel-sessions/session-isolated-workspace-service.js +483 -0
- package/dist/server/modules/parallel-sessions/session-isolated-workspace-service.js.map +1 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.d.ts +16 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js.map +1 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.d.ts +2 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js +18 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-candidate-endpoints.d.ts +2 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-candidate-endpoints.js +129 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-candidate-endpoints.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-client-context.d.ts +13 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-client-context.js +2 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-client-context.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.d.ts +6 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +110 -10
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.d.ts +16 -4
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js +220 -102
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.d.ts +4 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +257 -162
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +3 -0
- package/dist/server/modules/sessions/codex-app-server-helper-client.js +56 -45
- package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-process.js +21 -2
- package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
- package/dist/server/modules/sessions/session-activity-inspector.js +6 -8
- package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +11 -1
- package/dist/server/modules/sessions/session-history-service.js +204 -21
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +8 -0
- package/dist/server/modules/sessions/session-live-runtime-service.js +208 -25
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/workbench/codex-archive-watcher.d.ts +16 -0
- package/dist/server/modules/workbench/codex-archive-watcher.js +50 -0
- package/dist/server/modules/workbench/codex-archive-watcher.js.map +1 -0
- package/dist/server/modules/workbench/workbench-service.d.ts +43 -4
- package/dist/server/modules/workbench/workbench-service.js +72 -9
- package/dist/server/modules/workbench/workbench-service.js.map +1 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +1 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +26 -3
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
- package/dist/server/modules/workspace/workspace-service.d.ts +3 -1
- package/dist/server/modules/workspace/workspace-service.js +10 -2
- package/dist/server/modules/workspace/workspace-service.js.map +1 -1
- package/dist/server/modules/worktree/worktree-base-ref-resolver.d.ts +20 -0
- package/dist/server/modules/worktree/worktree-base-ref-resolver.js +111 -0
- package/dist/server/modules/worktree/worktree-base-ref-resolver.js.map +1 -0
- package/dist/server/modules/worktree/worktree-cleanup-service.js +9 -3
- package/dist/server/modules/worktree/worktree-cleanup-service.js.map +1 -1
- package/dist/server/modules/worktree/worktree-manager.d.ts +0 -1
- package/dist/server/modules/worktree/worktree-manager.js +14 -20
- package/dist/server/modules/worktree/worktree-manager.js.map +1 -1
- package/dist/server/routes/git.js +1 -0
- package/dist/server/routes/git.js.map +1 -1
- package/dist/server/routes/parallel-groups.d.ts +3 -0
- package/dist/server/routes/parallel-groups.js +9 -0
- package/dist/server/routes/parallel-groups.js.map +1 -0
- package/dist/server/server/create-server.d.ts +8 -0
- package/dist/server/server/create-server.js +48 -9
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/server/workbench-runtime-terminal-sync.d.ts +14 -0
- package/dist/server/server/workbench-runtime-terminal-sync.js +17 -0
- package/dist/server/server/workbench-runtime-terminal-sync.js.map +1 -0
- package/dist/server/storage/repositories/parallel-session-group-repository.d.ts +11 -0
- package/dist/server/storage/repositories/parallel-session-group-repository.js +131 -0
- package/dist/server/storage/repositories/parallel-session-group-repository.js.map +1 -0
- package/dist/server/storage/repositories/parallel-session-member-repository.d.ts +12 -0
- package/dist/server/storage/repositories/parallel-session-member-repository.js +150 -0
- package/dist/server/storage/repositories/parallel-session-member-repository.js.map +1 -0
- package/dist/server/storage/repositories/session-isolated-workspace-repository.d.ts +15 -0
- package/dist/server/storage/repositories/session-isolated-workspace-repository.js +230 -0
- package/dist/server/storage/repositories/session-isolated-workspace-repository.js.map +1 -0
- package/dist/server/storage/sqlite/schema.sql +73 -0
- package/dist/server/types/domain.d.ts +72 -0
- package/dist/server/ws/workbench-ws-hub.d.ts +3 -1
- package/dist/server/ws/workbench-ws-hub.js +189 -20
- package/dist/server/ws/workbench-ws-hub.js.map +1 -1
- package/dist/server/ws/ws-server.js +141 -8
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +67 -6
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +3 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +46 -22
- package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +558 -309
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js +29 -5
- package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js.map +1 -1
- package/package.json +1 -1
- package/dist/public/assets/App-DUAg5urj.css +0 -1
- package/dist/public/assets/App-WOLwMld_.js +0 -30
- package/dist/public/assets/ConversationPage-D9pzRmOg.js +0 -2
- package/dist/public/assets/DesktopWindowPage-D8FpOSLE.js +0 -2
- package/dist/public/assets/FileContextPanel-C8T7oqRN.js +0 -1
- package/dist/public/assets/GitSidebar-Bze7DNnc.js +0 -6
- package/dist/public/assets/MobileSheet-Gzc14EpR.js +0 -1
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-DOr4pTUq.js +0 -1
- package/dist/public/assets/ServerSettingsModal-BYB0GvTl.js +0 -1
- package/dist/public/assets/SessionIndexPage-CR3IARXX.js +0 -1
- package/dist/public/assets/SettingsPage-B_BQtnwE.js +0 -1
- package/dist/public/assets/TerminalManagerPanel-PQ-EM64j.js +0 -1
- package/dist/public/assets/ToolFilesPage-Qzkc6K2I.js +0 -1
- package/dist/public/assets/ToolGitPage-BdNDN-cV.js +0 -1
- package/dist/public/assets/ToolProcessesPage-EXJ9DHWI.js +0 -1
- package/dist/public/assets/ToolsHomePage-CjF3CWzR.js +0 -1
- package/dist/public/assets/WorkbenchLandingPage-DZPk4SmX.js +0 -1
- package/dist/public/assets/WorkbenchLayout-rwQib5In.js +0 -3
- package/dist/public/assets/WorkbenchShellRoute-Cerk5uK7.js +0 -1
- package/dist/public/assets/WorkspaceDebugDetailPage-Bcq8s-Ma.js +0 -1
- package/dist/public/assets/WorkspaceDetailPage-DNAa8pKr.js +0 -1
- package/dist/public/assets/WorkspaceHomePage-BoiLuACV.js +0 -1
- package/dist/public/assets/client-runtime-manager-CRQ-F5d2.js +0 -1
- package/dist/public/assets/file-tree-icon-Dp_xhVfD.js +0 -31
- package/dist/public/assets/index-C2G8Gmf1.js +0 -42
- package/dist/public/assets/index-CpPTUeA3.css +0 -1
- package/dist/public/assets/session-runtime-machine-Dq3pW-UF.js +0 -17
- package/dist/public/assets/window-BWqRixxq.js +0 -1
- /package/dist/public/assets/{styles-CSUx5LGe.js → styles-DRVvx_kv.js} +0 -0
|
@@ -12,6 +12,7 @@ import { buildApplyPatchFromFileChangeList, extractApplyPatchTargetPathsFromTool
|
|
|
12
12
|
import { loadDatabaseSync } from "../sqlite/node-sqlite.js";
|
|
13
13
|
import { createCodexThreadPermissionOptions } from "./codex-permissions.js";
|
|
14
14
|
const CODEX_RUNTIME_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_PERF_DEBUG?.trim() ?? "");
|
|
15
|
+
const CODEX_APP_SERVER_REQUEST_TIMEOUT_MS = 20_000;
|
|
15
16
|
function logCodexRuntimeStep(scope, startedAtMs, detail = {}) {
|
|
16
17
|
if (!CODEX_RUNTIME_DEBUG_ENABLED) {
|
|
17
18
|
return;
|
|
@@ -61,123 +62,115 @@ export class CodexRuntimeAdapter {
|
|
|
61
62
|
const transport = this.options.transportFactory
|
|
62
63
|
? this.options.transportFactory()
|
|
63
64
|
: createCodexAppServerTransport(this.options);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
65
|
+
try {
|
|
66
|
+
const initializeStartedAtMs = performance.now();
|
|
67
|
+
await transport.initialize();
|
|
68
|
+
logCodexRuntimeStep("start_session.initialize", initializeStartedAtMs, {
|
|
69
|
+
sessionId: request.sessionId,
|
|
70
|
+
workspacePath: request.workspacePath
|
|
71
|
+
});
|
|
72
|
+
const abortController = new AbortController();
|
|
73
|
+
const eventQueue = createAsyncEventQueue();
|
|
74
|
+
const translateNotification = createCodexAppServerNotificationTranslator();
|
|
75
|
+
const forwardTranslatedNotification = createCodexTranslatedNotificationForwarder(eventQueue);
|
|
76
|
+
const resumedSyntheticSession = await this.resumeSyntheticThreadFromHistory(transport, request);
|
|
77
|
+
const startedSession = resumedSyntheticSession ??
|
|
78
|
+
await (async () => {
|
|
79
|
+
const startThreadStartedAtMs = performance.now();
|
|
80
|
+
const started = await transport.startThread(request);
|
|
81
|
+
logCodexRuntimeStep("start_session.thread_start", startThreadStartedAtMs, {
|
|
82
|
+
sessionId: request.sessionId,
|
|
83
|
+
providerSessionId: started.providerSessionId
|
|
84
|
+
});
|
|
85
|
+
return started;
|
|
86
|
+
})();
|
|
87
|
+
const providerSessionId = startedSession.providerSessionId;
|
|
88
|
+
const syntheticRawStoreRef = buildRuntimeRawStoreRef(resolveRuntimeStoreKey(providerSessionId, request.sessionId));
|
|
89
|
+
const rawStoreRef = pickAvailableCodexRawStoreRef(providerSessionId, resumedSyntheticSession
|
|
90
|
+
? [resumedSyntheticSession.rawStoreRef]
|
|
91
|
+
: [startedSession.rawStoreRef, request.rawStoreRef], syntheticRawStoreRef);
|
|
92
|
+
logCodexRuntimeStep("start_session.raw_store_ref_ready", launchPerfStartedAtMs, {
|
|
93
|
+
sessionId: request.sessionId,
|
|
94
|
+
providerSessionId,
|
|
95
|
+
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
96
|
+
hasProviderRawStoreRef: Boolean(startedSession.rawStoreRef),
|
|
97
|
+
providerRawStoreRefExists: Boolean(startedSession.rawStoreRef && existsSync(startedSession.rawStoreRef))
|
|
98
|
+
});
|
|
99
|
+
sink.updateSessionBinding({
|
|
100
|
+
providerSessionId,
|
|
101
|
+
rawStoreRef
|
|
102
|
+
});
|
|
103
|
+
let firstNotificationLogged = false;
|
|
104
|
+
transport.setNotificationHandler(async (notification) => {
|
|
105
|
+
if (!firstNotificationLogged) {
|
|
106
|
+
firstNotificationLogged = true;
|
|
107
|
+
logCodexRuntimeStep("start_session.first_notification", launchPerfStartedAtMs, {
|
|
108
|
+
sessionId: request.sessionId,
|
|
109
|
+
providerSessionId,
|
|
110
|
+
method: ensureText(notification.method).trim() || null
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const translated = translateNotification(notification);
|
|
114
|
+
forwardTranslatedNotification(translated);
|
|
115
|
+
});
|
|
116
|
+
transport.setServerRequestHandler(async (serverRequest) => {
|
|
117
|
+
if (!this.options.handleServerRequest) {
|
|
118
|
+
throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
|
|
119
|
+
}
|
|
120
|
+
return this.options.handleServerRequest({
|
|
104
121
|
sessionId: request.sessionId,
|
|
105
122
|
providerSessionId,
|
|
106
|
-
|
|
123
|
+
request: serverRequest
|
|
107
124
|
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
125
|
+
});
|
|
126
|
+
transport.setOnClose((error) => {
|
|
127
|
+
if (error) {
|
|
128
|
+
eventQueue.push({
|
|
129
|
+
type: "turn.failed",
|
|
130
|
+
timestamp: nextTimestamp(),
|
|
131
|
+
error: error.message
|
|
132
|
+
});
|
|
133
|
+
}
|
|
117
134
|
eventQueue.close();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
135
|
+
});
|
|
136
|
+
const startTurnStartedAtMs = performance.now();
|
|
137
|
+
const startTurnResult = await transport.startTurn(request, providerSessionId);
|
|
138
|
+
const startTurnNotification = startTurnResult?.notification ?? null;
|
|
139
|
+
if (startTurnNotification) {
|
|
140
|
+
const translated = translateNotification(startTurnNotification);
|
|
141
|
+
forwardTranslatedNotification(translated);
|
|
142
|
+
}
|
|
143
|
+
logCodexRuntimeStep("start_session.turn_start", startTurnStartedAtMs, {
|
|
125
144
|
sessionId: request.sessionId,
|
|
126
|
-
providerSessionId
|
|
127
|
-
request: serverRequest
|
|
145
|
+
providerSessionId
|
|
128
146
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
147
|
+
logCodexRuntimeStep("start_session.ready", launchPerfStartedAtMs, {
|
|
148
|
+
sessionId: request.sessionId,
|
|
149
|
+
providerSessionId
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
providerSessionId,
|
|
153
|
+
rawStoreRef,
|
|
154
|
+
submitDuringRun: async (options) => {
|
|
155
|
+
await transport.steerTurn(options);
|
|
156
|
+
},
|
|
157
|
+
interrupt: async () => {
|
|
158
|
+
abortController.abort();
|
|
159
|
+
await transport.interruptTurn().catch(() => {
|
|
160
|
+
return;
|
|
161
|
+
});
|
|
162
|
+
transport.close();
|
|
163
|
+
},
|
|
164
|
+
isAlive: () => transport.isClosed() === false,
|
|
165
|
+
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs).finally(() => {
|
|
166
|
+
transport.close();
|
|
167
|
+
})
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
transport.close();
|
|
172
|
+
throw error;
|
|
154
173
|
}
|
|
155
|
-
logCodexRuntimeStep("start_session.turn_start", startTurnStartedAtMs, {
|
|
156
|
-
sessionId: request.sessionId,
|
|
157
|
-
providerSessionId
|
|
158
|
-
});
|
|
159
|
-
logCodexRuntimeStep("start_session.ready", launchPerfStartedAtMs, {
|
|
160
|
-
sessionId: request.sessionId,
|
|
161
|
-
providerSessionId
|
|
162
|
-
});
|
|
163
|
-
return {
|
|
164
|
-
providerSessionId,
|
|
165
|
-
rawStoreRef,
|
|
166
|
-
submitDuringRun: async (options) => {
|
|
167
|
-
await transport.steerTurn(options);
|
|
168
|
-
},
|
|
169
|
-
interrupt: async () => {
|
|
170
|
-
abortController.abort();
|
|
171
|
-
await transport.interruptTurn().catch(() => {
|
|
172
|
-
return;
|
|
173
|
-
});
|
|
174
|
-
transport.close();
|
|
175
|
-
},
|
|
176
|
-
isAlive: () => transport.isClosed() === false,
|
|
177
|
-
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs).finally(() => {
|
|
178
|
-
transport.close();
|
|
179
|
-
})
|
|
180
|
-
};
|
|
181
174
|
}
|
|
182
175
|
async resumeSyntheticThreadFromHistory(transport, request) {
|
|
183
176
|
const history = buildSyntheticResumeHistory(request.rawStoreRef);
|
|
@@ -206,152 +199,144 @@ export class CodexRuntimeAdapter {
|
|
|
206
199
|
const transport = this.options.transportFactory
|
|
207
200
|
? this.options.transportFactory()
|
|
208
201
|
: createCodexAppServerTransport(this.options);
|
|
209
|
-
const runtimeStartedAtMs = performance.now();
|
|
210
|
-
const initializeStartedAtMs = performance.now();
|
|
211
|
-
await transport.initialize();
|
|
212
|
-
logCodexRuntimeStep("continue_session.initialize", initializeStartedAtMs, {
|
|
213
|
-
sessionId: request.sessionId,
|
|
214
|
-
providerSessionId
|
|
215
|
-
});
|
|
216
|
-
const syntheticRawStoreRef = buildRuntimeRawStoreRef(providerSessionId);
|
|
217
|
-
let resolvedSessionId = providerSessionId;
|
|
218
|
-
let resolvedFallbackHistoryRawStoreRef = null;
|
|
219
|
-
const resumeThreadStartedAtMs = performance.now();
|
|
220
|
-
let resumed;
|
|
221
202
|
try {
|
|
222
|
-
|
|
223
|
-
|
|
203
|
+
const runtimeStartedAtMs = performance.now();
|
|
204
|
+
const initializeStartedAtMs = performance.now();
|
|
205
|
+
await transport.initialize();
|
|
206
|
+
logCodexRuntimeStep("continue_session.initialize", initializeStartedAtMs, {
|
|
224
207
|
sessionId: request.sessionId,
|
|
225
|
-
providerSessionId
|
|
226
|
-
fallback: false
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
catch (error) {
|
|
230
|
-
const fallbackHistorySource = await this.resolveContinueFallbackHistorySource({
|
|
231
|
-
providerSessionId,
|
|
232
|
-
rawStoreRef: request.rawStoreRef,
|
|
233
|
-
workspacePath: request.workspacePath
|
|
234
|
-
});
|
|
235
|
-
const resumeHistory = fallbackHistorySource?.history ?? [];
|
|
236
|
-
if (!shouldFallbackCodexContinueFromHistory(error, resumeHistory)) {
|
|
237
|
-
throw error;
|
|
238
|
-
}
|
|
239
|
-
resolvedFallbackHistoryRawStoreRef = fallbackHistorySource?.rawStoreRef ?? null;
|
|
240
|
-
const resumeFallbackStartedAtMs = performance.now();
|
|
241
|
-
resumed = await transport.resumeThreadFromHistory({
|
|
242
|
-
providerSessionId: null,
|
|
243
|
-
workspacePath: request.workspacePath,
|
|
244
|
-
history: resumeHistory,
|
|
245
|
-
model: request.options.model
|
|
246
|
-
});
|
|
247
|
-
resolvedSessionId = resumed.providerSessionId;
|
|
248
|
-
logCodexRuntimeStep("continue_session.thread_resume_from_history_fallback", resumeFallbackStartedAtMs, {
|
|
249
|
-
sessionId: request.sessionId,
|
|
250
|
-
requestedProviderSessionId: providerSessionId,
|
|
251
|
-
providerSessionId: resolvedSessionId,
|
|
252
|
-
historyLength: resumeHistory.length
|
|
208
|
+
providerSessionId
|
|
253
209
|
});
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
sessionId: request.sessionId,
|
|
263
|
-
providerSessionId: resolvedSessionId,
|
|
264
|
-
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
265
|
-
hasResumedRawStoreRef: Boolean(resumed.rawStoreRef),
|
|
266
|
-
hasRequestRawStoreRef: Boolean(request.rawStoreRef),
|
|
267
|
-
resumedRawStoreRefExists: Boolean(resumed.rawStoreRef && existsSync(resumed.rawStoreRef))
|
|
268
|
-
});
|
|
269
|
-
sink.updateSessionBinding({
|
|
270
|
-
providerSessionId: resolvedSessionId,
|
|
271
|
-
rawStoreRef
|
|
272
|
-
});
|
|
273
|
-
let firstNotificationLogged = false;
|
|
274
|
-
transport.setNotificationHandler(async (notification) => {
|
|
275
|
-
if (!firstNotificationLogged) {
|
|
276
|
-
firstNotificationLogged = true;
|
|
277
|
-
logCodexRuntimeStep("continue_session.first_notification", runtimeStartedAtMs, {
|
|
210
|
+
const syntheticRawStoreRef = buildRuntimeRawStoreRef(providerSessionId);
|
|
211
|
+
let resolvedSessionId = providerSessionId;
|
|
212
|
+
let resolvedFallbackHistoryRawStoreRef = null;
|
|
213
|
+
const resumeThreadStartedAtMs = performance.now();
|
|
214
|
+
let resumed;
|
|
215
|
+
try {
|
|
216
|
+
resumed = await transport.resumeThread(request, resolvedSessionId);
|
|
217
|
+
logCodexRuntimeStep("continue_session.thread_resume", resumeThreadStartedAtMs, {
|
|
278
218
|
sessionId: request.sessionId,
|
|
279
219
|
providerSessionId: resolvedSessionId,
|
|
280
|
-
|
|
220
|
+
fallback: false
|
|
281
221
|
});
|
|
282
222
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
223
|
+
catch (error) {
|
|
224
|
+
const fallbackHistorySource = await this.resolveContinueFallbackHistorySource({
|
|
225
|
+
providerSessionId,
|
|
226
|
+
rawStoreRef: request.rawStoreRef,
|
|
227
|
+
workspacePath: request.workspacePath
|
|
228
|
+
});
|
|
229
|
+
const resumeHistory = fallbackHistorySource?.history ?? [];
|
|
230
|
+
if (!shouldFallbackCodexContinueFromHistory(error, resumeHistory)) {
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
resolvedFallbackHistoryRawStoreRef = fallbackHistorySource?.rawStoreRef ?? null;
|
|
234
|
+
const resumeFallbackStartedAtMs = performance.now();
|
|
235
|
+
resumed = await transport.resumeThreadFromHistory({
|
|
236
|
+
providerSessionId: null,
|
|
237
|
+
workspacePath: request.workspacePath,
|
|
238
|
+
history: resumeHistory,
|
|
239
|
+
model: request.options.model
|
|
240
|
+
});
|
|
241
|
+
resolvedSessionId = resumed.providerSessionId;
|
|
242
|
+
logCodexRuntimeStep("continue_session.thread_resume_from_history_fallback", resumeFallbackStartedAtMs, {
|
|
243
|
+
sessionId: request.sessionId,
|
|
244
|
+
requestedProviderSessionId: providerSessionId,
|
|
245
|
+
providerSessionId: resolvedSessionId,
|
|
246
|
+
historyLength: resumeHistory.length
|
|
247
|
+
});
|
|
297
248
|
}
|
|
298
|
-
|
|
249
|
+
const pickedRawStoreRef = pickAvailableCodexRawStoreRef(resolvedSessionId, [resolvedFallbackHistoryRawStoreRef, request.rawStoreRef, resumed.rawStoreRef], syntheticRawStoreRef);
|
|
250
|
+
const rawStoreRef = !resumed.rawStoreRef?.trim() && resolvedFallbackHistoryRawStoreRef
|
|
251
|
+
? resolvedFallbackHistoryRawStoreRef
|
|
252
|
+
: pickedRawStoreRef;
|
|
253
|
+
const abortController = new AbortController();
|
|
254
|
+
const eventQueue = createAsyncEventQueue();
|
|
255
|
+
const translateNotification = createCodexAppServerNotificationTranslator();
|
|
256
|
+
const forwardTranslatedNotification = createCodexTranslatedNotificationForwarder(eventQueue);
|
|
257
|
+
logCodexRuntimeStep("continue_session.raw_store_ref_ready", runtimeStartedAtMs, {
|
|
299
258
|
sessionId: request.sessionId,
|
|
300
259
|
providerSessionId: resolvedSessionId,
|
|
301
|
-
|
|
260
|
+
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
261
|
+
hasResumedRawStoreRef: Boolean(resumed.rawStoreRef),
|
|
262
|
+
hasRequestRawStoreRef: Boolean(request.rawStoreRef),
|
|
263
|
+
resumedRawStoreRefExists: Boolean(resumed.rawStoreRef && existsSync(resumed.rawStoreRef))
|
|
302
264
|
});
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
265
|
+
sink.updateSessionBinding({
|
|
266
|
+
providerSessionId: resolvedSessionId,
|
|
267
|
+
rawStoreRef
|
|
268
|
+
});
|
|
269
|
+
let firstNotificationLogged = false;
|
|
270
|
+
transport.setNotificationHandler(async (notification) => {
|
|
271
|
+
if (!firstNotificationLogged) {
|
|
272
|
+
firstNotificationLogged = true;
|
|
273
|
+
logCodexRuntimeStep("continue_session.first_notification", runtimeStartedAtMs, {
|
|
274
|
+
sessionId: request.sessionId,
|
|
275
|
+
providerSessionId: resolvedSessionId,
|
|
276
|
+
method: ensureText(notification.method).trim() || null
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const translated = translateNotification(notification);
|
|
280
|
+
forwardTranslatedNotification(translated);
|
|
281
|
+
});
|
|
282
|
+
transport.setServerRequestHandler(async (serverRequest) => {
|
|
283
|
+
if (!this.options.handleServerRequest) {
|
|
284
|
+
throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
|
|
285
|
+
}
|
|
286
|
+
return this.options.handleServerRequest({
|
|
287
|
+
sessionId: request.sessionId,
|
|
288
|
+
providerSessionId: resolvedSessionId,
|
|
289
|
+
request: serverRequest
|
|
310
290
|
});
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
eventQueue.setTurnId(translated.turnId);
|
|
321
|
-
}
|
|
322
|
-
for (const event of translated.events) {
|
|
323
|
-
eventQueue.push(event);
|
|
324
|
-
}
|
|
325
|
-
if (translated.terminal) {
|
|
291
|
+
});
|
|
292
|
+
transport.setOnClose((error) => {
|
|
293
|
+
if (error) {
|
|
294
|
+
eventQueue.push({
|
|
295
|
+
type: "turn.failed",
|
|
296
|
+
timestamp: nextTimestamp(),
|
|
297
|
+
error: error.message
|
|
298
|
+
});
|
|
299
|
+
}
|
|
326
300
|
eventQueue.close();
|
|
327
|
-
}
|
|
301
|
+
});
|
|
302
|
+
const startTurnStartedAtMs = performance.now();
|
|
303
|
+
const startTurnResult = await transport.startTurn(request, resolvedSessionId);
|
|
304
|
+
const startTurnNotification = startTurnResult?.notification ?? null;
|
|
305
|
+
if (startTurnNotification) {
|
|
306
|
+
const translated = translateNotification(startTurnNotification);
|
|
307
|
+
forwardTranslatedNotification(translated);
|
|
308
|
+
}
|
|
309
|
+
logCodexRuntimeStep("continue_session.turn_start", startTurnStartedAtMs, {
|
|
310
|
+
sessionId: request.sessionId,
|
|
311
|
+
providerSessionId: resolvedSessionId
|
|
312
|
+
});
|
|
313
|
+
logCodexRuntimeStep("continue_session.ready", runtimeStartedAtMs, {
|
|
314
|
+
sessionId: request.sessionId,
|
|
315
|
+
providerSessionId: resolvedSessionId
|
|
316
|
+
});
|
|
317
|
+
return {
|
|
318
|
+
providerSessionId: resolvedSessionId,
|
|
319
|
+
rawStoreRef,
|
|
320
|
+
submitDuringRun: async (options) => {
|
|
321
|
+
await transport.steerTurn(options);
|
|
322
|
+
},
|
|
323
|
+
interrupt: async () => {
|
|
324
|
+
abortController.abort();
|
|
325
|
+
await transport.interruptTurn().catch(() => {
|
|
326
|
+
return;
|
|
327
|
+
});
|
|
328
|
+
transport.close();
|
|
329
|
+
},
|
|
330
|
+
isAlive: () => transport.isClosed() === false,
|
|
331
|
+
completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now()).finally(() => {
|
|
332
|
+
transport.close();
|
|
333
|
+
})
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
transport.close();
|
|
338
|
+
throw error;
|
|
328
339
|
}
|
|
329
|
-
logCodexRuntimeStep("continue_session.turn_start", startTurnStartedAtMs, {
|
|
330
|
-
sessionId: request.sessionId,
|
|
331
|
-
providerSessionId: resolvedSessionId
|
|
332
|
-
});
|
|
333
|
-
logCodexRuntimeStep("continue_session.ready", runtimeStartedAtMs, {
|
|
334
|
-
sessionId: request.sessionId,
|
|
335
|
-
providerSessionId: resolvedSessionId
|
|
336
|
-
});
|
|
337
|
-
return {
|
|
338
|
-
providerSessionId: resolvedSessionId,
|
|
339
|
-
rawStoreRef,
|
|
340
|
-
submitDuringRun: async (options) => {
|
|
341
|
-
await transport.steerTurn(options);
|
|
342
|
-
},
|
|
343
|
-
interrupt: async () => {
|
|
344
|
-
abortController.abort();
|
|
345
|
-
await transport.interruptTurn().catch(() => {
|
|
346
|
-
return;
|
|
347
|
-
});
|
|
348
|
-
transport.close();
|
|
349
|
-
},
|
|
350
|
-
isAlive: () => transport.isClosed() === false,
|
|
351
|
-
completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now()).finally(() => {
|
|
352
|
-
transport.close();
|
|
353
|
-
})
|
|
354
|
-
};
|
|
355
340
|
}
|
|
356
341
|
async resolveContinueFallbackHistorySource(input) {
|
|
357
342
|
const candidates = [];
|
|
@@ -1188,110 +1173,357 @@ function createAsyncEventQueue() {
|
|
|
1188
1173
|
}
|
|
1189
1174
|
};
|
|
1190
1175
|
}
|
|
1191
|
-
function
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
...itemEvents,
|
|
1209
|
-
{
|
|
1210
|
-
type: "turn.failed",
|
|
1211
|
-
timestamp: nextTimestamp(),
|
|
1212
|
-
error: ensureText(readProp(turn?.error, "message")).trim() || "codex turn failed"
|
|
1176
|
+
function createCodexTranslatedNotificationForwarder(eventQueue) {
|
|
1177
|
+
const seenReplayKeys = new Set();
|
|
1178
|
+
return (translated) => {
|
|
1179
|
+
if (translated.turnId) {
|
|
1180
|
+
eventQueue.setTurnId(translated.turnId);
|
|
1181
|
+
}
|
|
1182
|
+
for (const event of translated.events) {
|
|
1183
|
+
const replayKey = buildCodexTranslatedReplayKey(event);
|
|
1184
|
+
if (replayKey) {
|
|
1185
|
+
if (seenReplayKeys.has(replayKey)) {
|
|
1186
|
+
continue;
|
|
1187
|
+
}
|
|
1188
|
+
seenReplayKeys.add(replayKey);
|
|
1189
|
+
while (seenReplayKeys.size > 1024) {
|
|
1190
|
+
const oldest = seenReplayKeys.keys().next().value;
|
|
1191
|
+
if (typeof oldest !== "string") {
|
|
1192
|
+
break;
|
|
1213
1193
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1194
|
+
seenReplayKeys.delete(oldest);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
eventQueue.push(event);
|
|
1198
|
+
}
|
|
1199
|
+
if (translated.terminal) {
|
|
1200
|
+
eventQueue.close();
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function buildCodexTranslatedReplayKey(event) {
|
|
1205
|
+
const eventType = ensureText(event.type).trim();
|
|
1206
|
+
if (!eventType) {
|
|
1207
|
+
return null;
|
|
1208
|
+
}
|
|
1209
|
+
if (eventType === "turn.completed" || eventType === "turn.failed" || eventType === "turn.interrupted") {
|
|
1210
|
+
return `${eventType}:${ensureText(readProp(event, "turnId")).trim() || ""}`;
|
|
1211
|
+
}
|
|
1212
|
+
if (!eventType.startsWith("item.")) {
|
|
1213
|
+
return null;
|
|
1214
|
+
}
|
|
1215
|
+
const item = toRecord(readProp(event, "item"));
|
|
1216
|
+
if (!item) {
|
|
1217
|
+
return null;
|
|
1218
|
+
}
|
|
1219
|
+
return JSON.stringify({
|
|
1220
|
+
eventType,
|
|
1221
|
+
itemType: ensureText(item.type).trim(),
|
|
1222
|
+
id: ensureText(item.id).trim(),
|
|
1223
|
+
status: ensureText(item.status).trim(),
|
|
1224
|
+
text: ensureText(item.text).trim(),
|
|
1225
|
+
summary: normalizeReplayKeyText(readProp(item, "summary")),
|
|
1226
|
+
content: normalizeReplayKeyText(readProp(item, "content")),
|
|
1227
|
+
command: normalizeReplayKeyText(readProp(item, "command")),
|
|
1228
|
+
result: normalizeReplayKeyText(readProp(item, "result")),
|
|
1229
|
+
output: normalizeReplayKeyText(readProp(item, "output")),
|
|
1230
|
+
aggregatedOutput: normalizeReplayKeyText(readProp(item, "aggregated_output")),
|
|
1231
|
+
error: normalizeReplayKeyText(readProp(item, "error"))
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
function normalizeReplayKeyText(value) {
|
|
1235
|
+
if (Array.isArray(value)) {
|
|
1236
|
+
return value.map((entry) => normalizeReplayKeyText(entry)).join("\n");
|
|
1237
|
+
}
|
|
1238
|
+
if (value && typeof value === "object") {
|
|
1239
|
+
try {
|
|
1240
|
+
return JSON.stringify(value);
|
|
1241
|
+
}
|
|
1242
|
+
catch {
|
|
1243
|
+
return String(value);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
return ensureText(value).trim();
|
|
1247
|
+
}
|
|
1248
|
+
function createCodexAppServerNotificationTranslator() {
|
|
1249
|
+
const agentMessageTextById = new Map();
|
|
1250
|
+
const reasoningSummaryPartsById = new Map();
|
|
1251
|
+
const reasoningContentPartsById = new Map();
|
|
1252
|
+
const resetStreamState = () => {
|
|
1253
|
+
agentMessageTextById.clear();
|
|
1254
|
+
reasoningSummaryPartsById.clear();
|
|
1255
|
+
reasoningContentPartsById.clear();
|
|
1256
|
+
};
|
|
1257
|
+
const ensureIndexedTextPart = (store, itemId, index) => {
|
|
1258
|
+
if (!itemId || !Number.isInteger(index) || index < 0) {
|
|
1259
|
+
return null;
|
|
1218
1260
|
}
|
|
1219
|
-
|
|
1261
|
+
const existing = store.get(itemId) ?? [];
|
|
1262
|
+
while (existing.length <= index) {
|
|
1263
|
+
existing.push("");
|
|
1264
|
+
}
|
|
1265
|
+
store.set(itemId, existing);
|
|
1266
|
+
return existing;
|
|
1267
|
+
};
|
|
1268
|
+
const buildReasoningSyntheticItem = (itemId) => {
|
|
1269
|
+
// 这里必须复制一份快照,不能把可变数组引用直接塞进事件队列。
|
|
1270
|
+
// 否则后续 delta 继续追加时,前一帧事件里的 summary/content 也会被同步改掉,
|
|
1271
|
+
// 最终所有帧都会看起来像“最后一帧”,下游稳定消息去重就会把中间增量吃掉。
|
|
1272
|
+
const summary = [...(reasoningSummaryPartsById.get(itemId) ?? [])];
|
|
1273
|
+
const content = [...(reasoningContentPartsById.get(itemId) ?? [])];
|
|
1274
|
+
return {
|
|
1275
|
+
type: "reasoning",
|
|
1276
|
+
id: itemId,
|
|
1277
|
+
summary,
|
|
1278
|
+
content
|
|
1279
|
+
};
|
|
1280
|
+
};
|
|
1281
|
+
const translateAgentMessageDelta = (params) => {
|
|
1282
|
+
const itemId = ensureText(params.itemId).trim();
|
|
1283
|
+
const delta = ensureText(params.delta);
|
|
1284
|
+
if (!itemId || delta.length === 0) {
|
|
1220
1285
|
return {
|
|
1221
|
-
events: [
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
type: "turn.interrupted",
|
|
1225
|
-
timestamp: nextTimestamp()
|
|
1226
|
-
}
|
|
1227
|
-
],
|
|
1228
|
-
terminal: true,
|
|
1229
|
-
turnId: ensureText(turn?.id).trim() || null
|
|
1286
|
+
events: [],
|
|
1287
|
+
terminal: false,
|
|
1288
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1230
1289
|
};
|
|
1231
1290
|
}
|
|
1291
|
+
const nextText = `${agentMessageTextById.get(itemId) ?? ""}${delta}`;
|
|
1292
|
+
agentMessageTextById.set(itemId, nextText);
|
|
1232
1293
|
return {
|
|
1233
1294
|
events: [
|
|
1234
|
-
...itemEvents,
|
|
1235
1295
|
{
|
|
1236
|
-
type: "
|
|
1296
|
+
type: "item.updated",
|
|
1297
|
+
item: {
|
|
1298
|
+
type: "agent_message",
|
|
1299
|
+
id: itemId,
|
|
1300
|
+
text: nextText
|
|
1301
|
+
},
|
|
1237
1302
|
timestamp: nextTimestamp()
|
|
1238
1303
|
}
|
|
1239
1304
|
],
|
|
1240
|
-
terminal:
|
|
1241
|
-
turnId: ensureText(
|
|
1305
|
+
terminal: false,
|
|
1306
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1242
1307
|
};
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
const
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1308
|
+
};
|
|
1309
|
+
const translateReasoningSummaryPartAdded = (params) => {
|
|
1310
|
+
const itemId = ensureText(params.itemId).trim();
|
|
1311
|
+
const summaryIndex = Math.trunc(Number(params.summaryIndex));
|
|
1312
|
+
ensureIndexedTextPart(reasoningSummaryPartsById, itemId, summaryIndex);
|
|
1313
|
+
return {
|
|
1314
|
+
events: [],
|
|
1315
|
+
terminal: false,
|
|
1316
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1317
|
+
};
|
|
1318
|
+
};
|
|
1319
|
+
const translateReasoningSummaryTextDelta = (params) => {
|
|
1320
|
+
const itemId = ensureText(params.itemId).trim();
|
|
1321
|
+
const summaryIndex = Math.trunc(Number(params.summaryIndex));
|
|
1322
|
+
const delta = ensureText(params.delta);
|
|
1323
|
+
const parts = ensureIndexedTextPart(reasoningSummaryPartsById, itemId, summaryIndex);
|
|
1324
|
+
if (!parts || delta.length === 0) {
|
|
1248
1325
|
return {
|
|
1249
1326
|
events: [],
|
|
1250
1327
|
terminal: false,
|
|
1251
1328
|
turnId: ensureText(params.turnId).trim() || null
|
|
1252
1329
|
};
|
|
1253
1330
|
}
|
|
1331
|
+
parts[summaryIndex] = `${parts[summaryIndex] ?? ""}${delta}`;
|
|
1254
1332
|
return {
|
|
1255
1333
|
events: [
|
|
1256
1334
|
{
|
|
1257
|
-
type: "
|
|
1258
|
-
|
|
1259
|
-
|
|
1335
|
+
type: "item.updated",
|
|
1336
|
+
item: buildReasoningSyntheticItem(itemId),
|
|
1337
|
+
timestamp: nextTimestamp()
|
|
1260
1338
|
}
|
|
1261
1339
|
],
|
|
1262
|
-
terminal:
|
|
1340
|
+
terminal: false,
|
|
1263
1341
|
turnId: ensureText(params.turnId).trim() || null
|
|
1264
1342
|
};
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1343
|
+
};
|
|
1344
|
+
const translateReasoningTextDelta = (params) => {
|
|
1345
|
+
const itemId = ensureText(params.itemId).trim();
|
|
1346
|
+
const contentIndex = Math.trunc(Number(params.contentIndex));
|
|
1347
|
+
const delta = ensureText(params.delta);
|
|
1348
|
+
const parts = ensureIndexedTextPart(reasoningContentPartsById, itemId, contentIndex);
|
|
1349
|
+
if (!parts || delta.length === 0) {
|
|
1269
1350
|
return {
|
|
1270
1351
|
events: [],
|
|
1271
1352
|
terminal: false,
|
|
1272
|
-
turnId: null
|
|
1353
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1273
1354
|
};
|
|
1274
1355
|
}
|
|
1356
|
+
parts[contentIndex] = `${parts[contentIndex] ?? ""}${delta}`;
|
|
1275
1357
|
return {
|
|
1276
1358
|
events: [
|
|
1277
1359
|
{
|
|
1278
|
-
type:
|
|
1279
|
-
|
|
1280
|
-
: method === "item/updated"
|
|
1281
|
-
? "item.updated"
|
|
1282
|
-
: "item.completed",
|
|
1283
|
-
item,
|
|
1360
|
+
type: "item.updated",
|
|
1361
|
+
item: buildReasoningSyntheticItem(itemId),
|
|
1284
1362
|
timestamp: nextTimestamp()
|
|
1285
1363
|
}
|
|
1286
1364
|
],
|
|
1287
1365
|
terminal: false,
|
|
1366
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1367
|
+
};
|
|
1368
|
+
};
|
|
1369
|
+
return (notification) => {
|
|
1370
|
+
const method = ensureText(notification.method).trim();
|
|
1371
|
+
const params = toRecord(notification.params) ?? {};
|
|
1372
|
+
if (method === "turn/started") {
|
|
1373
|
+
return {
|
|
1374
|
+
events: [],
|
|
1375
|
+
terminal: false,
|
|
1376
|
+
turnId: ensureText(readProp(readProp(params, "turn"), "id")).trim() || null
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
if (method === "turn/completed") {
|
|
1380
|
+
const turn = toRecord(params.turn);
|
|
1381
|
+
const status = ensureText(turn?.status).trim();
|
|
1382
|
+
const itemEvents = translateCodexAppServerTurnItems(turn, "item.completed");
|
|
1383
|
+
resetStreamState();
|
|
1384
|
+
if (status === "failed") {
|
|
1385
|
+
return {
|
|
1386
|
+
events: [
|
|
1387
|
+
...itemEvents,
|
|
1388
|
+
{
|
|
1389
|
+
type: "turn.failed",
|
|
1390
|
+
timestamp: nextTimestamp(),
|
|
1391
|
+
error: ensureText(readProp(turn?.error, "message")).trim() || "codex turn failed"
|
|
1392
|
+
}
|
|
1393
|
+
],
|
|
1394
|
+
terminal: true,
|
|
1395
|
+
turnId: ensureText(turn?.id).trim() || null
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
if (status === "interrupted") {
|
|
1399
|
+
return {
|
|
1400
|
+
events: [
|
|
1401
|
+
...itemEvents,
|
|
1402
|
+
{
|
|
1403
|
+
type: "turn.interrupted",
|
|
1404
|
+
timestamp: nextTimestamp()
|
|
1405
|
+
}
|
|
1406
|
+
],
|
|
1407
|
+
terminal: true,
|
|
1408
|
+
turnId: ensureText(turn?.id).trim() || null
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
return {
|
|
1412
|
+
events: [
|
|
1413
|
+
...itemEvents,
|
|
1414
|
+
{
|
|
1415
|
+
type: "turn.completed",
|
|
1416
|
+
timestamp: nextTimestamp()
|
|
1417
|
+
}
|
|
1418
|
+
],
|
|
1419
|
+
terminal: true,
|
|
1420
|
+
turnId: ensureText(turn?.id).trim() || null
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
if (method === "error") {
|
|
1424
|
+
const error = toRecord(params.error);
|
|
1425
|
+
const detail = buildCodexAppServerErrorDetail(error);
|
|
1426
|
+
if (params.willRetry === true) {
|
|
1427
|
+
return {
|
|
1428
|
+
events: [],
|
|
1429
|
+
terminal: false,
|
|
1430
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
resetStreamState();
|
|
1434
|
+
return {
|
|
1435
|
+
events: [
|
|
1436
|
+
{
|
|
1437
|
+
type: "turn.failed",
|
|
1438
|
+
timestamp: nextTimestamp(),
|
|
1439
|
+
error: detail
|
|
1440
|
+
}
|
|
1441
|
+
],
|
|
1442
|
+
terminal: true,
|
|
1443
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
if (method === "item/agentMessage/delta") {
|
|
1447
|
+
return translateAgentMessageDelta(params);
|
|
1448
|
+
}
|
|
1449
|
+
if (method === "item/reasoning/summaryPartAdded") {
|
|
1450
|
+
return translateReasoningSummaryPartAdded(params);
|
|
1451
|
+
}
|
|
1452
|
+
if (method === "item/reasoning/summaryTextDelta") {
|
|
1453
|
+
return translateReasoningSummaryTextDelta(params);
|
|
1454
|
+
}
|
|
1455
|
+
if (method === "item/reasoning/textDelta") {
|
|
1456
|
+
return translateReasoningTextDelta(params);
|
|
1457
|
+
}
|
|
1458
|
+
if (method === "item/started" || method === "item/updated" || method === "item/completed") {
|
|
1459
|
+
const item = translateCodexAppServerItem(toRecord(params.item));
|
|
1460
|
+
if (!item) {
|
|
1461
|
+
return {
|
|
1462
|
+
events: [],
|
|
1463
|
+
terminal: false,
|
|
1464
|
+
turnId: null
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1467
|
+
if (ensureText(item.type).trim() === "agent_message") {
|
|
1468
|
+
const itemId = ensureText(item.id).trim();
|
|
1469
|
+
const itemText = ensureText(item.text);
|
|
1470
|
+
if (itemId) {
|
|
1471
|
+
if (itemText.length > 0) {
|
|
1472
|
+
agentMessageTextById.set(itemId, itemText);
|
|
1473
|
+
}
|
|
1474
|
+
else if (method === "item/completed") {
|
|
1475
|
+
agentMessageTextById.delete(itemId);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
if (ensureText(item.type).trim() === "reasoning") {
|
|
1480
|
+
const itemId = ensureText(item.id).trim();
|
|
1481
|
+
if (itemId) {
|
|
1482
|
+
const summary = Array.isArray(item.summary)
|
|
1483
|
+
? item.summary.map((entry) => ensureText(entry))
|
|
1484
|
+
: ensureText(item.summary).trim()
|
|
1485
|
+
? [ensureText(item.summary)]
|
|
1486
|
+
: [];
|
|
1487
|
+
const content = Array.isArray(item.content)
|
|
1488
|
+
? item.content.map((entry) => ensureText(entry))
|
|
1489
|
+
: ensureText(item.text).trim()
|
|
1490
|
+
? [ensureText(item.text)]
|
|
1491
|
+
: [];
|
|
1492
|
+
if (summary.length > 0) {
|
|
1493
|
+
reasoningSummaryPartsById.set(itemId, summary);
|
|
1494
|
+
}
|
|
1495
|
+
else if (method === "item/completed") {
|
|
1496
|
+
reasoningSummaryPartsById.delete(itemId);
|
|
1497
|
+
}
|
|
1498
|
+
if (content.length > 0) {
|
|
1499
|
+
reasoningContentPartsById.set(itemId, content);
|
|
1500
|
+
}
|
|
1501
|
+
else if (method === "item/completed") {
|
|
1502
|
+
reasoningContentPartsById.delete(itemId);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
return {
|
|
1507
|
+
events: [
|
|
1508
|
+
{
|
|
1509
|
+
type: method === "item/started"
|
|
1510
|
+
? "item.started"
|
|
1511
|
+
: method === "item/updated"
|
|
1512
|
+
? "item.updated"
|
|
1513
|
+
: "item.completed",
|
|
1514
|
+
item,
|
|
1515
|
+
timestamp: nextTimestamp()
|
|
1516
|
+
}
|
|
1517
|
+
],
|
|
1518
|
+
terminal: false,
|
|
1519
|
+
turnId: null
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
return {
|
|
1523
|
+
events: [],
|
|
1524
|
+
terminal: false,
|
|
1288
1525
|
turnId: null
|
|
1289
1526
|
};
|
|
1290
|
-
}
|
|
1291
|
-
return {
|
|
1292
|
-
events: [],
|
|
1293
|
-
terminal: false,
|
|
1294
|
-
turnId: null
|
|
1295
1527
|
};
|
|
1296
1528
|
}
|
|
1297
1529
|
function translateCodexAppServerTurnItems(turn, eventType) {
|
|
@@ -1754,7 +1986,20 @@ function writeJsonRpcMessage(child, payload) {
|
|
|
1754
1986
|
function sendJsonRpcRequest(child, pendingResponses, createRequestId, input) {
|
|
1755
1987
|
const id = createRequestId();
|
|
1756
1988
|
return new Promise((resolve, reject) => {
|
|
1757
|
-
|
|
1989
|
+
const timeout = setTimeout(() => {
|
|
1990
|
+
pendingResponses.delete(id);
|
|
1991
|
+
reject(new Error("SERVER_TIMEOUT"));
|
|
1992
|
+
}, CODEX_APP_SERVER_REQUEST_TIMEOUT_MS);
|
|
1993
|
+
pendingResponses.set(id, {
|
|
1994
|
+
resolve: (value) => {
|
|
1995
|
+
clearTimeout(timeout);
|
|
1996
|
+
resolve(value);
|
|
1997
|
+
},
|
|
1998
|
+
reject: (error) => {
|
|
1999
|
+
clearTimeout(timeout);
|
|
2000
|
+
reject(error);
|
|
2001
|
+
}
|
|
2002
|
+
});
|
|
1758
2003
|
try {
|
|
1759
2004
|
writeJsonRpcMessage(child, {
|
|
1760
2005
|
jsonrpc: "2.0",
|
|
@@ -1764,6 +2009,7 @@ function sendJsonRpcRequest(child, pendingResponses, createRequestId, input) {
|
|
|
1764
2009
|
});
|
|
1765
2010
|
}
|
|
1766
2011
|
catch (error) {
|
|
2012
|
+
clearTimeout(timeout);
|
|
1767
2013
|
pendingResponses.delete(id);
|
|
1768
2014
|
reject(error instanceof Error ? error : new Error("CODEX_APP_SERVER_REQUEST_WRITE_FAILED"));
|
|
1769
2015
|
}
|
|
@@ -1801,7 +2047,7 @@ function shouldFallbackCodexContinueFromHistory(error, history) {
|
|
|
1801
2047
|
if (history.length === 0) {
|
|
1802
2048
|
return false;
|
|
1803
2049
|
}
|
|
1804
|
-
return isCodexThreadLoadError(error);
|
|
2050
|
+
return isCodexThreadLoadError(error) || isCodexRequestTimeoutError(error);
|
|
1805
2051
|
}
|
|
1806
2052
|
function isCodexThreadLoadError(error) {
|
|
1807
2053
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1809,6 +2055,9 @@ function isCodexThreadLoadError(error) {
|
|
|
1809
2055
|
return (normalized.includes("thread not loaded") ||
|
|
1810
2056
|
normalized.includes("no rollout found for thread id"));
|
|
1811
2057
|
}
|
|
2058
|
+
function isCodexRequestTimeoutError(error) {
|
|
2059
|
+
return error instanceof Error && error.message === "SERVER_TIMEOUT";
|
|
2060
|
+
}
|
|
1812
2061
|
function readProp(value, key) {
|
|
1813
2062
|
if (!value || typeof value !== "object") {
|
|
1814
2063
|
return null;
|