@jingyi0605/codingns 0.5.5 → 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-CUyNL98E.js → AdaptiveButlerPage-uFwDdN-F.js} +3 -3
- package/dist/public/assets/{App-BFP7LCSC.js → App-BZvapsi8.js} +3 -3
- package/dist/public/assets/App-CcDXqFl1.css +1 -0
- package/dist/public/assets/{BootstrapPage-G74dX2Us.js → BootstrapPage-gHSoa4JN.js} +1 -1
- package/dist/public/assets/ConversationPage-z3sXtKZ7.js +4 -0
- package/dist/public/assets/{DesktopDetachPreviewPage-IV7oEdOX.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-DqVwz_Hp.js → MobileCreateSessionSheet-BYfbvK8o.js} +1 -1
- package/dist/public/assets/MobileSheet-Ckug8hTb.js +1 -0
- package/dist/public/assets/{MobileTopHeaderFrame-COTc7cRr.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-DpsvQQVR.js → TerminalPage-DaooFaJ4.js} +19 -19
- package/dist/public/assets/{TerminalRuntimeFallbackModal-CNzOt5v5.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-CbDxaCOR.js → WorkbenchModal-0tPIIhca.js} +1 -1
- package/dist/public/assets/{WorkbenchShellRoute-BMcnFadA.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-Cu5SreTG.js → default-session-permission-mode-DT4SGiwp.js} +1 -1
- package/dist/public/assets/{file-tree-icon-BMKuc5pw.js → file-tree-icon-Db5LXC8h.js} +7 -7
- 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-gv_9vGKz.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-B9xJGY__.js → terminal-runtime-meta-cdtWVfCm.js} +1 -1
- package/dist/public/assets/{useRegisteredDebugTemplates-CDfl54Wt.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 +1 -0
- package/dist/server/config/env.js +3 -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/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-runtime-adapter.js +12 -9
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +1 -128
- 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-history-service.d.ts +10 -1
- package/dist/server/modules/sessions/session-history-service.js +142 -14
- 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 +11 -2
- package/dist/server/modules/workbench/workbench-service.js +37 -8
- 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 +38 -4
- 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 +23 -4
- package/dist/server/ws/workbench-ws-hub.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 +34 -0
- 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 +488 -281
- 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/ConversationPage-Bz0_tvvM.js +0 -2
- package/dist/public/assets/DesktopWindowPage-BBmHyRg5.js +0 -2
- package/dist/public/assets/FileContextPanel--FVTxDrq.js +0 -1
- package/dist/public/assets/GitSidebar-DAiSi9oc.js +0 -6
- package/dist/public/assets/MobileSheet-D1lMrcvD.js +0 -1
- package/dist/public/assets/MobileWorkspaceSwitcherHeader-DJPV9ym2.js +0 -1
- package/dist/public/assets/RelayConnectEntryPage-dSwU8VzK.js +0 -1
- package/dist/public/assets/ServerSettingsModal-B34ms3ze.js +0 -1
- package/dist/public/assets/SessionIndexPage-D3tG1gmM.js +0 -1
- package/dist/public/assets/SettingsPage-B3-6-5GL.js +0 -1
- package/dist/public/assets/TerminalManagerPanel-DhuTEdzV.js +0 -1
- package/dist/public/assets/ToolFilesPage-BX9QDi9Y.js +0 -1
- package/dist/public/assets/ToolGitPage-4VtFox3p.js +0 -1
- package/dist/public/assets/ToolProcessesPage-DZJC6Qnt.js +0 -1
- package/dist/public/assets/ToolsHomePage-D7JbrAWv.js +0 -1
- package/dist/public/assets/WorkbenchLandingPage-C0yqnzqh.js +0 -1
- package/dist/public/assets/WorkbenchLayout-Brlj8K3i.js +0 -3
- package/dist/public/assets/WorkbenchShellRoute-puGpdDFY.js +0 -1
- package/dist/public/assets/WorkspaceDebugDetailPage-fTGweC9N.js +0 -1
- package/dist/public/assets/WorkspaceDetailPage-BtaIzSDB.js +0 -1
- package/dist/public/assets/WorkspaceHomePage-CUmmYDrM.js +0 -1
- package/dist/public/assets/client-runtime-manager-RHFa_iWo.js +0 -1
- package/dist/public/assets/index-Cq3ue0za.css +0 -1
- package/dist/public/assets/index-DEbFT-Aq.js +0 -42
- package/dist/public/assets/session-runtime-machine-Bfnxkk9B.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,108 +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
|
-
await (
|
|
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
|
-
|
|
104
|
-
|
|
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({
|
|
105
121
|
sessionId: request.sessionId,
|
|
106
122
|
providerSessionId,
|
|
107
|
-
|
|
123
|
+
request: serverRequest
|
|
108
124
|
});
|
|
125
|
+
});
|
|
126
|
+
transport.setOnClose((error) => {
|
|
127
|
+
if (error) {
|
|
128
|
+
eventQueue.push({
|
|
129
|
+
type: "turn.failed",
|
|
130
|
+
timestamp: nextTimestamp(),
|
|
131
|
+
error: error.message
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
eventQueue.close();
|
|
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);
|
|
109
142
|
}
|
|
110
|
-
|
|
111
|
-
forwardTranslatedNotification(translated);
|
|
112
|
-
});
|
|
113
|
-
transport.setServerRequestHandler(async (serverRequest) => {
|
|
114
|
-
if (!this.options.handleServerRequest) {
|
|
115
|
-
throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
|
|
116
|
-
}
|
|
117
|
-
return this.options.handleServerRequest({
|
|
143
|
+
logCodexRuntimeStep("start_session.turn_start", startTurnStartedAtMs, {
|
|
118
144
|
sessionId: request.sessionId,
|
|
119
|
-
providerSessionId
|
|
120
|
-
request: serverRequest
|
|
145
|
+
providerSessionId
|
|
121
146
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
providerSessionId,
|
|
150
|
-
rawStoreRef,
|
|
151
|
-
submitDuringRun: async (options) => {
|
|
152
|
-
await transport.steerTurn(options);
|
|
153
|
-
},
|
|
154
|
-
interrupt: async () => {
|
|
155
|
-
abortController.abort();
|
|
156
|
-
await transport.interruptTurn().catch(() => {
|
|
157
|
-
return;
|
|
158
|
-
});
|
|
159
|
-
transport.close();
|
|
160
|
-
},
|
|
161
|
-
isAlive: () => transport.isClosed() === false,
|
|
162
|
-
completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs, launchPerfStartedAtMs).finally(() => {
|
|
163
|
-
transport.close();
|
|
164
|
-
})
|
|
165
|
-
};
|
|
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;
|
|
173
|
+
}
|
|
166
174
|
}
|
|
167
175
|
async resumeSyntheticThreadFromHistory(transport, request) {
|
|
168
176
|
const history = buildSyntheticResumeHistory(request.rawStoreRef);
|
|
@@ -191,137 +199,144 @@ export class CodexRuntimeAdapter {
|
|
|
191
199
|
const transport = this.options.transportFactory
|
|
192
200
|
? this.options.transportFactory()
|
|
193
201
|
: createCodexAppServerTransport(this.options);
|
|
194
|
-
const runtimeStartedAtMs = performance.now();
|
|
195
|
-
const initializeStartedAtMs = performance.now();
|
|
196
|
-
await transport.initialize();
|
|
197
|
-
logCodexRuntimeStep("continue_session.initialize", initializeStartedAtMs, {
|
|
198
|
-
sessionId: request.sessionId,
|
|
199
|
-
providerSessionId
|
|
200
|
-
});
|
|
201
|
-
const syntheticRawStoreRef = buildRuntimeRawStoreRef(providerSessionId);
|
|
202
|
-
let resolvedSessionId = providerSessionId;
|
|
203
|
-
let resolvedFallbackHistoryRawStoreRef = null;
|
|
204
|
-
const resumeThreadStartedAtMs = performance.now();
|
|
205
|
-
let resumed;
|
|
206
202
|
try {
|
|
207
|
-
|
|
208
|
-
|
|
203
|
+
const runtimeStartedAtMs = performance.now();
|
|
204
|
+
const initializeStartedAtMs = performance.now();
|
|
205
|
+
await transport.initialize();
|
|
206
|
+
logCodexRuntimeStep("continue_session.initialize", initializeStartedAtMs, {
|
|
209
207
|
sessionId: request.sessionId,
|
|
210
|
-
providerSessionId
|
|
211
|
-
fallback: false
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
const fallbackHistorySource = await this.resolveContinueFallbackHistorySource({
|
|
216
|
-
providerSessionId,
|
|
217
|
-
rawStoreRef: request.rawStoreRef,
|
|
218
|
-
workspacePath: request.workspacePath
|
|
219
|
-
});
|
|
220
|
-
const resumeHistory = fallbackHistorySource?.history ?? [];
|
|
221
|
-
if (!shouldFallbackCodexContinueFromHistory(error, resumeHistory)) {
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
resolvedFallbackHistoryRawStoreRef = fallbackHistorySource?.rawStoreRef ?? null;
|
|
225
|
-
const resumeFallbackStartedAtMs = performance.now();
|
|
226
|
-
resumed = await transport.resumeThreadFromHistory({
|
|
227
|
-
providerSessionId: null,
|
|
228
|
-
workspacePath: request.workspacePath,
|
|
229
|
-
history: resumeHistory,
|
|
230
|
-
model: request.options.model
|
|
231
|
-
});
|
|
232
|
-
resolvedSessionId = resumed.providerSessionId;
|
|
233
|
-
logCodexRuntimeStep("continue_session.thread_resume_from_history_fallback", resumeFallbackStartedAtMs, {
|
|
234
|
-
sessionId: request.sessionId,
|
|
235
|
-
requestedProviderSessionId: providerSessionId,
|
|
236
|
-
providerSessionId: resolvedSessionId,
|
|
237
|
-
historyLength: resumeHistory.length
|
|
208
|
+
providerSessionId
|
|
238
209
|
});
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
logCodexRuntimeStep("continue_session.raw_store_ref_ready", runtimeStartedAtMs, {
|
|
248
|
-
sessionId: request.sessionId,
|
|
249
|
-
providerSessionId: resolvedSessionId,
|
|
250
|
-
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
251
|
-
hasResumedRawStoreRef: Boolean(resumed.rawStoreRef),
|
|
252
|
-
hasRequestRawStoreRef: Boolean(request.rawStoreRef),
|
|
253
|
-
resumedRawStoreRefExists: Boolean(resumed.rawStoreRef && existsSync(resumed.rawStoreRef))
|
|
254
|
-
});
|
|
255
|
-
sink.updateSessionBinding({
|
|
256
|
-
providerSessionId: resolvedSessionId,
|
|
257
|
-
rawStoreRef
|
|
258
|
-
});
|
|
259
|
-
let firstNotificationLogged = false;
|
|
260
|
-
transport.setNotificationHandler(async (notification) => {
|
|
261
|
-
if (!firstNotificationLogged) {
|
|
262
|
-
firstNotificationLogged = true;
|
|
263
|
-
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, {
|
|
264
218
|
sessionId: request.sessionId,
|
|
265
219
|
providerSessionId: resolvedSessionId,
|
|
266
|
-
|
|
220
|
+
fallback: false
|
|
267
221
|
});
|
|
268
222
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
+
});
|
|
275
248
|
}
|
|
276
|
-
|
|
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, {
|
|
277
258
|
sessionId: request.sessionId,
|
|
278
259
|
providerSessionId: resolvedSessionId,
|
|
279
|
-
|
|
260
|
+
synthetic: isSyntheticRawStoreRef(rawStoreRef),
|
|
261
|
+
hasResumedRawStoreRef: Boolean(resumed.rawStoreRef),
|
|
262
|
+
hasRequestRawStoreRef: Boolean(request.rawStoreRef),
|
|
263
|
+
resumedRawStoreRefExists: Boolean(resumed.rawStoreRef && existsSync(resumed.rawStoreRef))
|
|
280
264
|
});
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
|
288
290
|
});
|
|
291
|
+
});
|
|
292
|
+
transport.setOnClose((error) => {
|
|
293
|
+
if (error) {
|
|
294
|
+
eventQueue.push({
|
|
295
|
+
type: "turn.failed",
|
|
296
|
+
timestamp: nextTimestamp(),
|
|
297
|
+
error: error.message
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
eventQueue.close();
|
|
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);
|
|
289
308
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now()).finally(() => {
|
|
322
|
-
transport.close();
|
|
323
|
-
})
|
|
324
|
-
};
|
|
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;
|
|
339
|
+
}
|
|
325
340
|
}
|
|
326
341
|
async resolveContinueFallbackHistorySource(input) {
|
|
327
342
|
const candidates = [];
|
|
@@ -1230,110 +1245,285 @@ function normalizeReplayKeyText(value) {
|
|
|
1230
1245
|
}
|
|
1231
1246
|
return ensureText(value).trim();
|
|
1232
1247
|
}
|
|
1233
|
-
function
|
|
1234
|
-
const
|
|
1235
|
-
const
|
|
1236
|
-
|
|
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;
|
|
1260
|
+
}
|
|
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) ?? [])];
|
|
1237
1274
|
return {
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1275
|
+
type: "reasoning",
|
|
1276
|
+
id: itemId,
|
|
1277
|
+
summary,
|
|
1278
|
+
content
|
|
1241
1279
|
};
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
const
|
|
1245
|
-
const
|
|
1246
|
-
|
|
1247
|
-
if (status === "failed") {
|
|
1248
|
-
return {
|
|
1249
|
-
events: [
|
|
1250
|
-
...itemEvents,
|
|
1251
|
-
{
|
|
1252
|
-
type: "turn.failed",
|
|
1253
|
-
timestamp: nextTimestamp(),
|
|
1254
|
-
error: ensureText(readProp(turn?.error, "message")).trim() || "codex turn failed"
|
|
1255
|
-
}
|
|
1256
|
-
],
|
|
1257
|
-
terminal: true,
|
|
1258
|
-
turnId: ensureText(turn?.id).trim() || null
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
if (status === "interrupted") {
|
|
1280
|
+
};
|
|
1281
|
+
const translateAgentMessageDelta = (params) => {
|
|
1282
|
+
const itemId = ensureText(params.itemId).trim();
|
|
1283
|
+
const delta = ensureText(params.delta);
|
|
1284
|
+
if (!itemId || delta.length === 0) {
|
|
1262
1285
|
return {
|
|
1263
|
-
events: [
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
type: "turn.interrupted",
|
|
1267
|
-
timestamp: nextTimestamp()
|
|
1268
|
-
}
|
|
1269
|
-
],
|
|
1270
|
-
terminal: true,
|
|
1271
|
-
turnId: ensureText(turn?.id).trim() || null
|
|
1286
|
+
events: [],
|
|
1287
|
+
terminal: false,
|
|
1288
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1272
1289
|
};
|
|
1273
1290
|
}
|
|
1291
|
+
const nextText = `${agentMessageTextById.get(itemId) ?? ""}${delta}`;
|
|
1292
|
+
agentMessageTextById.set(itemId, nextText);
|
|
1274
1293
|
return {
|
|
1275
1294
|
events: [
|
|
1276
|
-
...itemEvents,
|
|
1277
1295
|
{
|
|
1278
|
-
type: "
|
|
1296
|
+
type: "item.updated",
|
|
1297
|
+
item: {
|
|
1298
|
+
type: "agent_message",
|
|
1299
|
+
id: itemId,
|
|
1300
|
+
text: nextText
|
|
1301
|
+
},
|
|
1279
1302
|
timestamp: nextTimestamp()
|
|
1280
1303
|
}
|
|
1281
1304
|
],
|
|
1282
|
-
terminal:
|
|
1283
|
-
turnId: ensureText(
|
|
1305
|
+
terminal: false,
|
|
1306
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1284
1307
|
};
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
const
|
|
1288
|
-
const
|
|
1289
|
-
|
|
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) {
|
|
1290
1325
|
return {
|
|
1291
1326
|
events: [],
|
|
1292
1327
|
terminal: false,
|
|
1293
1328
|
turnId: ensureText(params.turnId).trim() || null
|
|
1294
1329
|
};
|
|
1295
1330
|
}
|
|
1331
|
+
parts[summaryIndex] = `${parts[summaryIndex] ?? ""}${delta}`;
|
|
1296
1332
|
return {
|
|
1297
1333
|
events: [
|
|
1298
1334
|
{
|
|
1299
|
-
type: "
|
|
1300
|
-
|
|
1301
|
-
|
|
1335
|
+
type: "item.updated",
|
|
1336
|
+
item: buildReasoningSyntheticItem(itemId),
|
|
1337
|
+
timestamp: nextTimestamp()
|
|
1302
1338
|
}
|
|
1303
1339
|
],
|
|
1304
|
-
terminal:
|
|
1340
|
+
terminal: false,
|
|
1305
1341
|
turnId: ensureText(params.turnId).trim() || null
|
|
1306
1342
|
};
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
const
|
|
1310
|
-
|
|
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) {
|
|
1311
1350
|
return {
|
|
1312
1351
|
events: [],
|
|
1313
1352
|
terminal: false,
|
|
1314
|
-
turnId: null
|
|
1353
|
+
turnId: ensureText(params.turnId).trim() || null
|
|
1315
1354
|
};
|
|
1316
1355
|
}
|
|
1356
|
+
parts[contentIndex] = `${parts[contentIndex] ?? ""}${delta}`;
|
|
1317
1357
|
return {
|
|
1318
1358
|
events: [
|
|
1319
1359
|
{
|
|
1320
|
-
type:
|
|
1321
|
-
|
|
1322
|
-
: method === "item/updated"
|
|
1323
|
-
? "item.updated"
|
|
1324
|
-
: "item.completed",
|
|
1325
|
-
item,
|
|
1360
|
+
type: "item.updated",
|
|
1361
|
+
item: buildReasoningSyntheticItem(itemId),
|
|
1326
1362
|
timestamp: nextTimestamp()
|
|
1327
1363
|
}
|
|
1328
1364
|
],
|
|
1329
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,
|
|
1330
1525
|
turnId: null
|
|
1331
1526
|
};
|
|
1332
|
-
}
|
|
1333
|
-
return {
|
|
1334
|
-
events: [],
|
|
1335
|
-
terminal: false,
|
|
1336
|
-
turnId: null
|
|
1337
1527
|
};
|
|
1338
1528
|
}
|
|
1339
1529
|
function translateCodexAppServerTurnItems(turn, eventType) {
|
|
@@ -1796,7 +1986,20 @@ function writeJsonRpcMessage(child, payload) {
|
|
|
1796
1986
|
function sendJsonRpcRequest(child, pendingResponses, createRequestId, input) {
|
|
1797
1987
|
const id = createRequestId();
|
|
1798
1988
|
return new Promise((resolve, reject) => {
|
|
1799
|
-
|
|
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
|
+
});
|
|
1800
2003
|
try {
|
|
1801
2004
|
writeJsonRpcMessage(child, {
|
|
1802
2005
|
jsonrpc: "2.0",
|
|
@@ -1806,6 +2009,7 @@ function sendJsonRpcRequest(child, pendingResponses, createRequestId, input) {
|
|
|
1806
2009
|
});
|
|
1807
2010
|
}
|
|
1808
2011
|
catch (error) {
|
|
2012
|
+
clearTimeout(timeout);
|
|
1809
2013
|
pendingResponses.delete(id);
|
|
1810
2014
|
reject(error instanceof Error ? error : new Error("CODEX_APP_SERVER_REQUEST_WRITE_FAILED"));
|
|
1811
2015
|
}
|
|
@@ -1843,7 +2047,7 @@ function shouldFallbackCodexContinueFromHistory(error, history) {
|
|
|
1843
2047
|
if (history.length === 0) {
|
|
1844
2048
|
return false;
|
|
1845
2049
|
}
|
|
1846
|
-
return isCodexThreadLoadError(error);
|
|
2050
|
+
return isCodexThreadLoadError(error) || isCodexRequestTimeoutError(error);
|
|
1847
2051
|
}
|
|
1848
2052
|
function isCodexThreadLoadError(error) {
|
|
1849
2053
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1851,6 +2055,9 @@ function isCodexThreadLoadError(error) {
|
|
|
1851
2055
|
return (normalized.includes("thread not loaded") ||
|
|
1852
2056
|
normalized.includes("no rollout found for thread id"));
|
|
1853
2057
|
}
|
|
2058
|
+
function isCodexRequestTimeoutError(error) {
|
|
2059
|
+
return error instanceof Error && error.message === "SERVER_TIMEOUT";
|
|
2060
|
+
}
|
|
1854
2061
|
function readProp(value, key) {
|
|
1855
2062
|
if (!value || typeof value !== "object") {
|
|
1856
2063
|
return null;
|