@pasko70/pibo 2.5.1 → 3.0.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/context/pibo-native-tooling.md +1 -0
- package/dist/agent-runtime/contract.js +2 -1
- package/dist/agent-runtime/history.js +53 -1
- package/dist/agent-runtime/routed-session.js +100 -26
- package/dist/agent-runtimes/codex-native/adapter.js +307 -31
- package/dist/agent-runtimes/codex-native/client.js +22 -3
- package/dist/agent-runtimes/codex-native/first-use.js +294 -0
- package/dist/agent-runtimes/codex-native/history.js +26 -7
- package/dist/agent-runtimes/codex-native/models.js +48 -1
- package/dist/agent-runtimes/codex-native/process.js +15 -1
- package/dist/agent-runtimes/codex-native/thread.js +75 -31
- package/dist/agent-runtimes/codex-native/turn.js +30 -0
- package/dist/agent-runtimes/history-proof.js +8 -0
- package/dist/agent-runtimes/omp/adapter.js +61 -14
- package/dist/agent-runtimes/omp/history.js +189 -34
- package/dist/agent-runtimes/omp/thread.js +82 -36
- package/dist/agent-runtimes/pi/adapter.js +30 -3
- package/dist/agent-runtimes/pi/history.js +66 -5
- package/dist/agent-runtimes/pi/openai-response-observer.js +102 -0
- package/dist/agent-runtimes/pi/routed-session.js +344 -37
- package/dist/apps/chat/agent-store.js +3 -0
- package/dist/apps/chat/chat-api-routes.js +1 -1
- package/dist/apps/chat/chat-files.js +130 -9
- package/dist/apps/chat/chat-request-normalizers.js +6 -0
- package/dist/apps/chat/chat-settings-routes.js +27 -2
- package/dist/apps/chat/chat-speech.js +100 -0
- package/dist/apps/chat/data/chat-data-mappers.js +25 -5
- package/dist/apps/chat/data/timeline-query-service.js +89 -1
- package/dist/apps/chat/trace-v2.js +210 -8
- package/dist/apps/chat/trace.js +3 -0
- package/dist/apps/chat/web-app.js +108 -3
- package/dist/apps/chat-ui/assets/{dist-GS8xUdfg.js → dist-BBDMeU5-.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BpVSf6ZV.js → dist-BDIATCQt.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CRv7fzi3.js → dist-JnW4v8UE.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CbBXbGVi.js → dist-lRiLP9rr.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-HC0xQ92C.js → dist-mqCviI-c.js} +1 -1
- package/dist/apps/chat-ui/assets/index-0XOOVxLP.js +228 -0
- package/dist/apps/chat-ui/assets/index-DV7_CgsC.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-vscode-web/assets/index-Dtw2Z7jz.js +43 -0
- package/dist/apps/chat-vscode-web/assets/{index-CF1-9PKU.css → index-SluZr_-r.css} +1 -1
- package/dist/apps/chat-vscode-web/index.html +2 -2
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-3.0.0.vsix +0 -0
- package/dist/cli.js +49 -5
- package/dist/config/config.js +59 -8
- package/dist/core/preview-server-settings.js +20 -0
- package/dist/core/profiles.js +1 -0
- package/dist/core/session-router.js +476 -44
- package/dist/core/user-settings.js +10 -0
- package/dist/data/payload-store.js +57 -1
- package/dist/data/schema.js +18 -1
- package/dist/debug/trace.js +5 -0
- package/dist/gateway/client.js +368 -65
- package/dist/gateway/protocol.js +2 -0
- package/dist/gateway/server.js +8 -0
- package/dist/gateway/web.js +2 -0
- package/dist/index.js +1 -1
- package/dist/loops/store.js +6 -4
- package/dist/mcp/config.js +89 -17
- package/dist/mcp/daemon-client.js +473 -153
- package/dist/mcp/daemon.js +401 -37
- package/dist/plugins/builtin.js +2 -2
- package/dist/plugins/codex-native.js +2 -0
- package/dist/plugins/registry.js +260 -1
- package/dist/previews/cli.js +345 -0
- package/dist/previews/config.js +61 -0
- package/dist/previews/manager.js +644 -0
- package/dist/previews/network.js +198 -0
- package/dist/previews/plugin.js +11 -0
- package/dist/previews/process-supervisor.js +38 -0
- package/dist/previews/proxy.js +387 -0
- package/dist/previews/store.js +750 -0
- package/dist/previews/types.js +1 -0
- package/dist/previews/web-app.js +446 -0
- package/dist/runs/registry.js +22 -0
- package/dist/runs/tools.js +46 -7
- package/dist/session-ui/terminalRows.js +187 -13
- package/dist/sessions/pibo-data-store.js +37 -0
- package/dist/sessions/runtime-binding-persistence.js +34 -0
- package/dist/sessions/runtime-binding.js +6 -0
- package/dist/sessions/sqlite-store.js +37 -0
- package/dist/shared/trace-engine.js +12 -64
- package/dist/shared/trace-event-projection.js +16 -0
- package/dist/shared/trace-history.js +684 -184
- package/dist/shared/trace-limits.js +7 -0
- package/dist/shared/trace-live-patch.js +61 -0
- package/dist/shared/trace-tool-identity.js +43 -0
- package/dist/speech/openai-codex-realtime-call-proxy.js +248 -0
- package/dist/speech/openai-codex.js +407 -0
- package/dist/speech/types.js +8 -0
- package/dist/subagents/context.js +5 -3
- package/dist/subagents/observations.js +94 -6
- package/dist/subagents/tool.js +103 -20
- package/dist/tools/codex-image-artifacts.js +24 -0
- package/dist/tools/codex-image-generation.js +4 -22
- package/dist/web/channel.js +88 -4
- package/dist/web/http.js +2 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/apps/chat-ui/assets/index-0WZI2phJ.css +0 -1
- package/dist/apps/chat-ui/assets/index-DT5jCQBP.js +0 -228
- package/dist/apps/chat-vscode-web/assets/index-DvTSSvzN.js +0 -43
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-2.5.1.vsix +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { unsupportedAgentRuntimeCapability, } from "../../agent-runtime/capabilities.js";
|
|
3
3
|
import { AgentRuntimeBindingMissingError, AgentRuntimeUnavailableError, } from "../../agent-runtime/errors.js";
|
|
4
|
+
import { isAgentRuntimeBindingPersistence } from "../../sessions/runtime-binding-persistence.js";
|
|
5
|
+
import { PENDING_NATIVE_SESSION_METADATA_KEY } from "../../sessions/runtime-binding.js";
|
|
4
6
|
import { selectRequestedFastMode, selectRequestedModelProfile, selectRequestedThinkingLevel, } from "../../core/model-defaults.js";
|
|
5
7
|
import { CODEX_NATIVE_RUNTIME_CONFIG_SCHEMA, defaultCodexNativeRuntimeConfig, parseCodexNativeRuntimeConfig, } from "./config.js";
|
|
6
8
|
import { diagnoseCodexNativeRuntime, startCodexNativeAppServer, } from "./process.js";
|
|
7
9
|
import { inspectCodexThreadHistory, pageCodexThreadHistory, unavailableCodexThreadHistoryInspection, } from "./history.js";
|
|
10
|
+
import { historyReconciliationDigest, } from "../../agent-runtime/history.js";
|
|
8
11
|
import { CODEX_NATIVE_ADAPTER_ID, CodexNativeThreadController, CodexNativeThreadMissingError, } from "./thread.js";
|
|
9
12
|
import { CODEX_APP_SERVER_PROTOCOL_NAME, CODEX_APP_SERVER_SUPPORTED_RANGE, CODEX_APP_SERVER_VERSION, } from "./protocol-version.js";
|
|
10
13
|
import { CodexNativeTurnController } from "./turn.js";
|
|
@@ -13,8 +16,69 @@ import { CodexNativeResourceDelivery } from "./resource-delivery.js";
|
|
|
13
16
|
import { CODEX_NATIVE_MODEL_OPTIONS_SCHEMA, CODEX_NATIVE_MODEL_PROVIDER_ID, CODEX_NATIVE_REASONING_VALUES, CodexNativeSessionSettingsController, parseCodexNativeProfileOptions, readCodexNativeModelCatalog, readCodexNativePersistedSettings, toAgentRuntimeModelCatalog, } from "./models.js";
|
|
14
17
|
import { CodexNativeAuthController } from "./auth.js";
|
|
15
18
|
import { injectPortableHistoryIntoCodex } from "./portable-history.js";
|
|
19
|
+
import { CODEX_FIRST_USE_METADATA_KEY, CODEX_FIRST_USE_METADATA_VERSION, assertCodexNativeFirstUseMessageId, assertCodexNativeFirstUseDeliveryReceiptTurn, assertCodexNativePendingFirstUseRequest, assertCodexNativePendingFirstUseTurn, beginCodexNativeFirstUseAttempt, codexNativeFirstUseDeliveryReceipt, codexNativePendingFirstUseOwnerLiveness, endCodexNativeFirstUseAttempt, hashCanonicalCodexNativeFirstUsePrompt, isExactCodexNativeFirstUseDeliveryReplay, readCodexNativeFirstUseDeliveryReceipt, readCodexNativePendingFirstUse, } from "./first-use.js";
|
|
16
20
|
export { CODEX_NATIVE_ADAPTER_ID } from "./thread.js";
|
|
17
21
|
export const CODEX_NATIVE_ADAPTER_VERSION = "1.0.0";
|
|
22
|
+
function readPendingFirstUse(binding) {
|
|
23
|
+
try {
|
|
24
|
+
return readCodexNativePendingFirstUse(binding);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new AgentRuntimeUnavailableError(binding.runtimeInstanceId, error instanceof Error ? error.message : "The pending native Codex first-use metadata is invalid.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function readFirstUseDeliveryReceipt(binding) {
|
|
31
|
+
try {
|
|
32
|
+
return readCodexNativeFirstUseDeliveryReceipt(binding);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw new AgentRuntimeUnavailableError(binding.runtimeInstanceId, error instanceof Error ? error.message : "The delivered native Codex first-use receipt is invalid.");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function deliveryReceiptForBinding(binding) {
|
|
39
|
+
if (binding.metadata?.[CODEX_FIRST_USE_METADATA_KEY] === undefined)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (binding.state === "unbound") {
|
|
42
|
+
const pending = readPendingFirstUse(binding);
|
|
43
|
+
return pending ? codexNativeFirstUseDeliveryReceipt(pending) : undefined;
|
|
44
|
+
}
|
|
45
|
+
return readFirstUseDeliveryReceipt(binding);
|
|
46
|
+
}
|
|
47
|
+
function pendingFirstUseBinding(binding, threadId, messageId, promptHash, owner) {
|
|
48
|
+
return {
|
|
49
|
+
...structuredClone(binding),
|
|
50
|
+
nativeSessionId: threadId,
|
|
51
|
+
state: "unbound",
|
|
52
|
+
protocol: CODEX_APP_SERVER_PROTOCOL_NAME,
|
|
53
|
+
protocolVersion: CODEX_APP_SERVER_VERSION,
|
|
54
|
+
adapterVersion: CODEX_NATIVE_ADAPTER_VERSION,
|
|
55
|
+
locator: { kind: "adapter-resolved" },
|
|
56
|
+
metadata: {
|
|
57
|
+
...(binding.metadata ?? {}),
|
|
58
|
+
[PENDING_NATIVE_SESSION_METADATA_KEY]: true,
|
|
59
|
+
[CODEX_FIRST_USE_METADATA_KEY]: {
|
|
60
|
+
version: CODEX_FIRST_USE_METADATA_VERSION,
|
|
61
|
+
state: "pending",
|
|
62
|
+
threadId,
|
|
63
|
+
messageId,
|
|
64
|
+
promptHash,
|
|
65
|
+
...owner,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function clearPendingFirstUse(binding) {
|
|
71
|
+
const metadata = { ...(binding.metadata ?? {}) };
|
|
72
|
+
delete metadata[CODEX_FIRST_USE_METADATA_KEY];
|
|
73
|
+
delete metadata[PENDING_NATIVE_SESSION_METADATA_KEY];
|
|
74
|
+
return {
|
|
75
|
+
...structuredClone(binding),
|
|
76
|
+
nativeSessionId: undefined,
|
|
77
|
+
state: "unbound",
|
|
78
|
+
locator: undefined,
|
|
79
|
+
metadata,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
18
82
|
function codexNativeCapabilities(structuredUserInput) {
|
|
19
83
|
return {
|
|
20
84
|
lifecycle: {
|
|
@@ -111,8 +175,10 @@ export const CODEX_NATIVE_THREAD_CAPABILITIES = codexNativeCapabilities(false);
|
|
|
111
175
|
function timestamp(seconds) {
|
|
112
176
|
return new Date(seconds * 1_000).toISOString();
|
|
113
177
|
}
|
|
114
|
-
function safeThreadMetadata(thread, previous = {}, settings = {}) {
|
|
178
|
+
function safeThreadMetadata(thread, previous = {}, settings = {}, deliveryReceipt) {
|
|
115
179
|
const { diagnosticCode: _diagnosticCode, diagnosticMessage: _diagnosticMessage, ...metadata } = previous;
|
|
180
|
+
delete metadata[CODEX_FIRST_USE_METADATA_KEY];
|
|
181
|
+
delete metadata[PENDING_NATIVE_SESSION_METADATA_KEY];
|
|
116
182
|
return {
|
|
117
183
|
...metadata,
|
|
118
184
|
...settings,
|
|
@@ -122,9 +188,11 @@ function safeThreadMetadata(thread, previous = {}, settings = {}) {
|
|
|
122
188
|
threadUpdatedAt: timestamp(thread.updatedAt),
|
|
123
189
|
threadStatus: thread.status.type,
|
|
124
190
|
modelProvider: thread.modelProvider,
|
|
191
|
+
...(deliveryReceipt ? { [CODEX_FIRST_USE_METADATA_KEY]: deliveryReceipt } : {}),
|
|
125
192
|
};
|
|
126
193
|
}
|
|
127
194
|
function bindingForThread(input) {
|
|
195
|
+
const deliveryReceipt = input.previous ? deliveryReceiptForBinding(input.previous) : undefined;
|
|
128
196
|
return {
|
|
129
197
|
...(input.previous ? structuredClone(input.previous) : {}),
|
|
130
198
|
piboSessionId: input.piboSessionId,
|
|
@@ -136,7 +204,7 @@ function bindingForThread(input) {
|
|
|
136
204
|
protocolVersion: CODEX_APP_SERVER_VERSION,
|
|
137
205
|
adapterVersion: CODEX_NATIVE_ADAPTER_VERSION,
|
|
138
206
|
locator: { kind: "adapter-resolved" },
|
|
139
|
-
metadata: safeThreadMetadata(input.thread, input.previous?.metadata, input.settings),
|
|
207
|
+
metadata: safeThreadMetadata(input.thread, input.previous?.metadata, input.settings, deliveryReceipt),
|
|
140
208
|
};
|
|
141
209
|
}
|
|
142
210
|
function validateOpenBinding(input, runtimeInstanceId) {
|
|
@@ -163,8 +231,31 @@ function validateOpenBinding(input, runtimeInstanceId) {
|
|
|
163
231
|
if (binding.state === "bound" && !binding.nativeSessionId) {
|
|
164
232
|
throw new AgentRuntimeUnavailableError(runtimeInstanceId, "The persisted Codex binding has no native thread id.");
|
|
165
233
|
}
|
|
234
|
+
if (binding.state === "bound")
|
|
235
|
+
readFirstUseDeliveryReceipt(binding);
|
|
166
236
|
if (binding.state === "unbound" && binding.nativeSessionId) {
|
|
167
|
-
|
|
237
|
+
const pending = readPendingFirstUse(binding);
|
|
238
|
+
const hasCurrentPendingMarker = binding.metadata?.[PENDING_NATIVE_SESSION_METADATA_KEY] === true;
|
|
239
|
+
const isExactParentLegacyPending = pending?.version === 1
|
|
240
|
+
&& binding.metadata?.[PENDING_NATIVE_SESSION_METADATA_KEY] === undefined;
|
|
241
|
+
if (!pending
|
|
242
|
+
|| pending.threadId !== binding.nativeSessionId
|
|
243
|
+
|| (!hasCurrentPendingMarker && !isExactParentLegacyPending)
|
|
244
|
+
|| input.piboSession.kind !== "branch") {
|
|
245
|
+
throw new AgentRuntimeUnavailableError(runtimeInstanceId, "An unbound Codex binding contains an invalid pending native thread identity.");
|
|
246
|
+
}
|
|
247
|
+
if (isExactParentLegacyPending) {
|
|
248
|
+
return {
|
|
249
|
+
...binding,
|
|
250
|
+
metadata: {
|
|
251
|
+
...(binding.metadata ?? {}),
|
|
252
|
+
[PENDING_NATIVE_SESSION_METADATA_KEY]: true,
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
else if (binding.state === "unbound" && binding.metadata?.[CODEX_FIRST_USE_METADATA_KEY] !== undefined) {
|
|
258
|
+
throw new AgentRuntimeUnavailableError(runtimeInstanceId, "An unbound Codex binding contains pending metadata without a native thread identity.");
|
|
168
259
|
}
|
|
169
260
|
return binding;
|
|
170
261
|
}
|
|
@@ -177,6 +268,8 @@ export class CodexNativeThreadSession {
|
|
|
177
268
|
structuredUserInput;
|
|
178
269
|
reloadProcess;
|
|
179
270
|
productContext;
|
|
271
|
+
bindingPersistence;
|
|
272
|
+
firstUseTestFailpoints;
|
|
180
273
|
adapterId = CODEX_NATIVE_ADAPTER_ID;
|
|
181
274
|
cwd;
|
|
182
275
|
capabilities;
|
|
@@ -198,12 +291,14 @@ export class CodexNativeThreadSession {
|
|
|
198
291
|
selectedToolNames = new Set();
|
|
199
292
|
observedToolNames = new Set();
|
|
200
293
|
toolInventoryWarning;
|
|
201
|
-
constructor(runtimeInstanceId, process, threads, settings, resourceDelivery, binding, structuredUserInput, reloadProcess, productContext) {
|
|
294
|
+
constructor(runtimeInstanceId, process, threads, settings, resourceDelivery, binding, structuredUserInput, reloadProcess, productContext, bindingPersistence, firstUseTestFailpoints) {
|
|
202
295
|
this.runtimeInstanceId = runtimeInstanceId;
|
|
203
296
|
this.settings = settings;
|
|
204
297
|
this.structuredUserInput = structuredUserInput;
|
|
205
298
|
this.reloadProcess = reloadProcess;
|
|
206
299
|
this.productContext = productContext;
|
|
300
|
+
this.bindingPersistence = bindingPersistence;
|
|
301
|
+
this.firstUseTestFailpoints = firstUseTestFailpoints;
|
|
207
302
|
this.process = process;
|
|
208
303
|
this.threads = threads;
|
|
209
304
|
this.resourceDelivery = resourceDelivery;
|
|
@@ -219,14 +314,16 @@ export class CodexNativeThreadSession {
|
|
|
219
314
|
getForkCandidates: () => this.threads.getForkCandidates(),
|
|
220
315
|
forkSession: async (entryId) => await this.runIdleOperation(async () => {
|
|
221
316
|
const result = await this.threads.fork(this.runtimeInstanceId, this.cwd, entryId, async (threadId) => await this.resourceDelivery.verifyThread(this.process.client, threadId));
|
|
222
|
-
|
|
223
|
-
|
|
317
|
+
if (result.current.nativeSessionId) {
|
|
318
|
+
this.settings.attachThread(this.threads.thread.id, this.threads.configuration);
|
|
319
|
+
this.promoteBindingFromCurrentThread();
|
|
320
|
+
}
|
|
224
321
|
return result;
|
|
225
322
|
}),
|
|
226
323
|
cloneSession: async () => await this.runIdleOperation(async () => {
|
|
227
324
|
const result = await this.threads.clone(this.runtimeInstanceId, this.cwd, async (threadId) => await this.resourceDelivery.verifyThread(this.process.client, threadId));
|
|
228
325
|
this.settings.attachThread(this.threads.thread.id, this.threads.configuration);
|
|
229
|
-
this.
|
|
326
|
+
this.promoteBindingFromCurrentThread();
|
|
230
327
|
return result;
|
|
231
328
|
}),
|
|
232
329
|
getReasoning: () => this.settings.reasoning,
|
|
@@ -256,7 +353,7 @@ export class CodexNativeThreadSession {
|
|
|
256
353
|
});
|
|
257
354
|
}
|
|
258
355
|
await this.turns.compact();
|
|
259
|
-
this.
|
|
356
|
+
this.refreshBoundBindingFromCurrentThread();
|
|
260
357
|
return {
|
|
261
358
|
native: true,
|
|
262
359
|
method: "thread/compact/start",
|
|
@@ -281,7 +378,7 @@ export class CodexNativeThreadSession {
|
|
|
281
378
|
return this.requests.pendingUserInputs;
|
|
282
379
|
}
|
|
283
380
|
getBinding() {
|
|
284
|
-
this.
|
|
381
|
+
this.refreshBoundBindingFromCurrentThread();
|
|
285
382
|
return structuredClone(this.binding);
|
|
286
383
|
}
|
|
287
384
|
subscribe(listener) {
|
|
@@ -292,12 +389,25 @@ export class CodexNativeThreadSession {
|
|
|
292
389
|
async prompt(input) {
|
|
293
390
|
this.assertActive();
|
|
294
391
|
await this.ensureFreshResourcesForTurn();
|
|
392
|
+
this.assertIdle();
|
|
295
393
|
this.operationInFlight = true;
|
|
394
|
+
let ownedFirstUseAttempt;
|
|
296
395
|
try {
|
|
297
|
-
await this.
|
|
298
|
-
|
|
396
|
+
const firstUse = await this.acquirePendingFirstUse(this.productContext?.getActiveMessage?.()?.id ?? randomUUID(), input.text);
|
|
397
|
+
ownedFirstUseAttempt = firstUse.attemptId;
|
|
398
|
+
if (!firstUse.startTurn)
|
|
399
|
+
return;
|
|
400
|
+
await this.firstUseTestFailpoints?.afterPendingBindingPersisted?.();
|
|
401
|
+
await this.turns.start(input.text, firstUse.messageId, this.settings.turnOptions);
|
|
402
|
+
await this.firstUseTestFailpoints?.afterNativeTerminalDurable?.();
|
|
403
|
+
const pending = this.binding.state === "unbound" ? readPendingFirstUse(this.binding) : undefined;
|
|
404
|
+
if (pending)
|
|
405
|
+
assertCodexNativePendingFirstUseTurn(pending, this.threads.thread);
|
|
406
|
+
this.promoteBindingFromCurrentThread();
|
|
299
407
|
}
|
|
300
408
|
finally {
|
|
409
|
+
if (ownedFirstUseAttempt)
|
|
410
|
+
endCodexNativeFirstUseAttempt(ownedFirstUseAttempt);
|
|
301
411
|
this.operationInFlight = false;
|
|
302
412
|
if (this.recycleProcessAfterInterruptedTurn && !this.disposed) {
|
|
303
413
|
this.recycleProcessAfterInterruptedTurn = false;
|
|
@@ -531,7 +641,7 @@ export class CodexNativeThreadSession {
|
|
|
531
641
|
this.requests = this.createRequestController(next.process);
|
|
532
642
|
previousRequests.dispose();
|
|
533
643
|
previousTurns.dispose();
|
|
534
|
-
this.
|
|
644
|
+
this.refreshBoundBindingFromCurrentThread();
|
|
535
645
|
this.resourceProcessUnavailable = false;
|
|
536
646
|
this.resourceWarning = undefined;
|
|
537
647
|
next = undefined;
|
|
@@ -574,7 +684,65 @@ export class CodexNativeThreadSession {
|
|
|
574
684
|
}
|
|
575
685
|
}
|
|
576
686
|
}
|
|
577
|
-
|
|
687
|
+
refreshBoundBindingFromCurrentThread() {
|
|
688
|
+
if (this.binding.state !== "bound")
|
|
689
|
+
return;
|
|
690
|
+
this.promoteBindingFromCurrentThread();
|
|
691
|
+
}
|
|
692
|
+
async acquirePendingFirstUse(messageId, prompt) {
|
|
693
|
+
if (this.binding.state !== "unbound") {
|
|
694
|
+
const receipt = readFirstUseDeliveryReceipt(this.binding);
|
|
695
|
+
if (!receipt || !isExactCodexNativeFirstUseDeliveryReplay(receipt, messageId, prompt)) {
|
|
696
|
+
return { messageId, startTurn: true };
|
|
697
|
+
}
|
|
698
|
+
const firstTurn = assertCodexNativeFirstUseDeliveryReceiptTurn(receipt, this.threads.thread);
|
|
699
|
+
this.turns.replayTerminalTurn(firstTurn);
|
|
700
|
+
return { messageId: receipt.messageId, startTurn: false };
|
|
701
|
+
}
|
|
702
|
+
assertCodexNativeFirstUseMessageId(messageId);
|
|
703
|
+
const promptHash = hashCanonicalCodexNativeFirstUsePrompt(prompt);
|
|
704
|
+
const currentPending = readPendingFirstUse(this.binding);
|
|
705
|
+
if (currentPending && this.threads.thread.turns.length > 0) {
|
|
706
|
+
assertCodexNativePendingFirstUseTurn(currentPending, this.threads.thread);
|
|
707
|
+
assertCodexNativePendingFirstUseRequest(currentPending, messageId, prompt);
|
|
708
|
+
this.promoteBindingFromCurrentThread();
|
|
709
|
+
return { messageId: currentPending.messageId, startTurn: false };
|
|
710
|
+
}
|
|
711
|
+
if (currentPending) {
|
|
712
|
+
const ownerLiveness = codexNativePendingFirstUseOwnerLiveness(currentPending);
|
|
713
|
+
if (ownerLiveness === "active") {
|
|
714
|
+
throw new Error("Native Codex first use is already owned by another live router.");
|
|
715
|
+
}
|
|
716
|
+
if (ownerLiveness === "ambiguous") {
|
|
717
|
+
throw new Error("Native Codex first-use ownership is ambiguous and cannot be replaced safely.");
|
|
718
|
+
}
|
|
719
|
+
assertCodexNativePendingFirstUseRequest(currentPending, messageId, prompt);
|
|
720
|
+
}
|
|
721
|
+
if (!isAgentRuntimeBindingPersistence(this.bindingPersistence)) {
|
|
722
|
+
throw new Error("Native Codex first use requires audited durable cross-process atomic runtime-binding CAS before turn/start.");
|
|
723
|
+
}
|
|
724
|
+
const owner = beginCodexNativeFirstUseAttempt();
|
|
725
|
+
const proposed = pendingFirstUseBinding(this.binding, this.threads.thread.id, messageId, promptHash, owner);
|
|
726
|
+
try {
|
|
727
|
+
const expectedRevision = this.binding.revision ?? 1;
|
|
728
|
+
const persisted = await this.bindingPersistence.compareAndSet(proposed, expectedRevision);
|
|
729
|
+
const pending = readPendingFirstUse(persisted);
|
|
730
|
+
if (persisted.revision !== expectedRevision + 1
|
|
731
|
+
|| persisted.state !== "unbound"
|
|
732
|
+
|| persisted.nativeSessionId !== proposed.nativeSessionId
|
|
733
|
+
|| !pending
|
|
734
|
+
|| JSON.stringify(pending) !== JSON.stringify(readPendingFirstUse(proposed))) {
|
|
735
|
+
throw new Error("Runtime-binding persistence returned an inconsistent Codex first-use claim.");
|
|
736
|
+
}
|
|
737
|
+
this.binding = structuredClone(persisted);
|
|
738
|
+
return { attemptId: owner.attemptId, messageId, startTurn: true };
|
|
739
|
+
}
|
|
740
|
+
catch (error) {
|
|
741
|
+
endCodexNativeFirstUseAttempt(owner.attemptId);
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
promoteBindingFromCurrentThread() {
|
|
578
746
|
this.binding = bindingForThread({
|
|
579
747
|
piboSessionId: this.binding.piboSessionId,
|
|
580
748
|
runtimeInstanceId: this.runtimeInstanceId,
|
|
@@ -589,12 +757,38 @@ export class CodexNativeThreadSession {
|
|
|
589
757
|
}
|
|
590
758
|
assertIdle() {
|
|
591
759
|
this.assertActive();
|
|
592
|
-
if (this.turns.streaming || this.resourceRefresh || this.resourceProcessUnavailable) {
|
|
760
|
+
if (this.operationInFlight || this.turns.streaming || this.resourceRefresh || this.resourceProcessUnavailable) {
|
|
593
761
|
throw new Error("Codex runtime controls can only change while the session is idle.");
|
|
594
762
|
}
|
|
595
763
|
}
|
|
596
764
|
}
|
|
597
|
-
|
|
765
|
+
const codexNativeCompleteHistoryProofs = new WeakMap();
|
|
766
|
+
const codexNativeHistoryReaders = new WeakMap();
|
|
767
|
+
const startCodexNativeHistoryProcess = startCodexNativeAppServer;
|
|
768
|
+
const readCodexNativeHistoryThread = CodexNativeThreadController.read;
|
|
769
|
+
function bindCodexNativeCompleteHistoryProof(page) {
|
|
770
|
+
const claim = page.reconciliationProof;
|
|
771
|
+
if (!claim?.complete)
|
|
772
|
+
return page;
|
|
773
|
+
const entries = Object.freeze([...claim.entries]);
|
|
774
|
+
const fullScope = Object.freeze({ entryCount: entries.length, digest: historyReconciliationDigest(entries) });
|
|
775
|
+
const proof = Object.freeze({
|
|
776
|
+
complete: true,
|
|
777
|
+
...(claim.scopeId ? { scopeId: claim.scopeId } : {}),
|
|
778
|
+
fullScope,
|
|
779
|
+
entries,
|
|
780
|
+
});
|
|
781
|
+
codexNativeCompleteHistoryProofs.set(proof, { ...(claim.scopeId ? { scopeId: claim.scopeId } : {}), fullScope });
|
|
782
|
+
return { ...page, reconciliationProof: proof };
|
|
783
|
+
}
|
|
784
|
+
export function isCodexNativeBuiltInHistoryReconciliationProof(proof) {
|
|
785
|
+
const bound = codexNativeCompleteHistoryProofs.get(proof);
|
|
786
|
+
return proof.complete
|
|
787
|
+
&& bound !== undefined
|
|
788
|
+
&& proof.scopeId === bound.scopeId
|
|
789
|
+
&& proof.fullScope === bound.fullScope;
|
|
790
|
+
}
|
|
791
|
+
class CodexNativeAgentRuntimeAdapter {
|
|
598
792
|
instanceId;
|
|
599
793
|
descriptor;
|
|
600
794
|
config;
|
|
@@ -611,6 +805,24 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
611
805
|
};
|
|
612
806
|
this.displayName = displayName ?? this.descriptor.displayName;
|
|
613
807
|
this.enabled = enabled;
|
|
808
|
+
const historyConfig = structuredClone(this.config);
|
|
809
|
+
const historyInstanceId = this.instanceId;
|
|
810
|
+
codexNativeHistoryReaders.set(this, async (piboSessionId, workspace, threadId, includeTurns) => {
|
|
811
|
+
const process = await startCodexNativeHistoryProcess({
|
|
812
|
+
config: historyConfig,
|
|
813
|
+
runtimeInstanceId: historyInstanceId,
|
|
814
|
+
piboSessionId,
|
|
815
|
+
sessionGeneration: `history-${randomUUID()}`,
|
|
816
|
+
workspace,
|
|
817
|
+
clientVersion: CODEX_NATIVE_ADAPTER_VERSION,
|
|
818
|
+
});
|
|
819
|
+
try {
|
|
820
|
+
return await readCodexNativeHistoryThread(process.client, threadId, includeTurns);
|
|
821
|
+
}
|
|
822
|
+
finally {
|
|
823
|
+
await process.close();
|
|
824
|
+
}
|
|
825
|
+
});
|
|
614
826
|
this.authController = new CodexNativeAuthController({
|
|
615
827
|
config: this.config,
|
|
616
828
|
startProcess: async (sessionGeneration) => await startCodexNativeAppServer({
|
|
@@ -724,6 +936,14 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
724
936
|
}
|
|
725
937
|
async openSession(input) {
|
|
726
938
|
const binding = validateOpenBinding(input, this.instanceId);
|
|
939
|
+
const activeFirstMessage = input.productContext.getActiveMessage?.();
|
|
940
|
+
const messageStartsLazyFirstUse = binding.state === "unbound"
|
|
941
|
+
&& input.piboSession.kind === "branch"
|
|
942
|
+
&& input.historyHandoff?.mode !== "import"
|
|
943
|
+
&& Boolean(activeFirstMessage?.id);
|
|
944
|
+
if (messageStartsLazyFirstUse && !isAgentRuntimeBindingPersistence(input.services?.runtimeBindingPersistence)) {
|
|
945
|
+
throw new AgentRuntimeUnavailableError(this.instanceId, "Native Codex first use requires audited durable cross-process atomic runtime-binding CAS before thread/start.");
|
|
946
|
+
}
|
|
727
947
|
const sessionGeneration = input.services?.resources?.sessionGeneration
|
|
728
948
|
?? input.services?.portableTools?.sessionGeneration
|
|
729
949
|
?? randomUUID();
|
|
@@ -733,6 +953,7 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
733
953
|
resources: input.services?.resources,
|
|
734
954
|
nativeSubagentsEnabled: input.profile.nativeSubagents,
|
|
735
955
|
};
|
|
956
|
+
const profileOptions = parseCodexNativeProfileOptions(input.profile.runtimeOptions);
|
|
736
957
|
const startProcessBundle = async (processGeneration) => {
|
|
737
958
|
let delivery;
|
|
738
959
|
let ownedProcess;
|
|
@@ -745,6 +966,7 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
745
966
|
sessionGeneration: processGeneration,
|
|
746
967
|
workspace: input.workspace,
|
|
747
968
|
clientVersion: CODEX_NATIVE_ADAPTER_VERSION,
|
|
969
|
+
experimentalApi: profileOptions.permissionMode === "plan",
|
|
748
970
|
resourceEnvironment: delivery.environment,
|
|
749
971
|
});
|
|
750
972
|
await delivery.configureProcess(ownedProcess.client, input.workspace);
|
|
@@ -765,7 +987,6 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
765
987
|
process = initial.process;
|
|
766
988
|
const compatibility = input.services?.compatibility;
|
|
767
989
|
const catalog = await this.loadModelCatalog(process.client);
|
|
768
|
-
const profileOptions = parseCodexNativeProfileOptions(input.profile.runtimeOptions);
|
|
769
990
|
const persisted = binding.state === "bound"
|
|
770
991
|
? readCodexNativePersistedSettings(binding.metadata)
|
|
771
992
|
: { profileOptions: {} };
|
|
@@ -790,6 +1011,7 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
790
1011
|
reasoningSummary: Object.hasOwn(persistedOptions, "reasoningSummary")
|
|
791
1012
|
? persistedOptions.reasoningSummary
|
|
792
1013
|
: profileOptions.reasoningSummary,
|
|
1014
|
+
permissionMode: profileOptions.permissionMode,
|
|
793
1015
|
},
|
|
794
1016
|
});
|
|
795
1017
|
const threadSelection = {
|
|
@@ -799,16 +1021,50 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
799
1021
|
? { developerInstructions: resourceDelivery.developerInstructions }
|
|
800
1022
|
: {}),
|
|
801
1023
|
};
|
|
1024
|
+
const pendingFirstUse = binding.state === "unbound" ? readPendingFirstUse(binding) : undefined;
|
|
1025
|
+
const deliveryReceipt = binding.state === "bound" ? readFirstUseDeliveryReceipt(binding) : undefined;
|
|
1026
|
+
let sessionBinding = binding;
|
|
1027
|
+
let pendingTerminalVerified = false;
|
|
802
1028
|
let threads;
|
|
803
1029
|
try {
|
|
804
|
-
threads = binding.state === "bound"
|
|
1030
|
+
threads = binding.state === "bound" || pendingFirstUse
|
|
805
1031
|
? await CodexNativeThreadController.resume(process.client, binding.nativeSessionId, input.workspace, threadSelection)
|
|
806
1032
|
: await CodexNativeThreadController.start(process.client, input.workspace, threadSelection);
|
|
807
1033
|
}
|
|
808
1034
|
catch (error) {
|
|
809
|
-
if (error instanceof CodexNativeThreadMissingError
|
|
810
|
-
|
|
811
|
-
|
|
1035
|
+
if (pendingFirstUse && error instanceof CodexNativeThreadMissingError) {
|
|
1036
|
+
const ownerLiveness = codexNativePendingFirstUseOwnerLiveness(pendingFirstUse);
|
|
1037
|
+
if (ownerLiveness === "active") {
|
|
1038
|
+
throw new AgentRuntimeUnavailableError(this.instanceId, "Native Codex first use is owned by another live router and is not yet restart-reconcilable.");
|
|
1039
|
+
}
|
|
1040
|
+
if (ownerLiveness === "ambiguous") {
|
|
1041
|
+
throw new AgentRuntimeUnavailableError(this.instanceId, "Native Codex first-use ownership is ambiguous; the pending identity was retained.");
|
|
1042
|
+
}
|
|
1043
|
+
threads = await CodexNativeThreadController.start(process.client, input.workspace, threadSelection);
|
|
1044
|
+
sessionBinding = clearPendingFirstUse(binding);
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
if (error instanceof CodexNativeThreadMissingError || !resourceDelivery.hasMcpServers)
|
|
1048
|
+
throw error;
|
|
1049
|
+
throw new Error("Codex could not initialize every selected MCP server.");
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
if (pendingFirstUse && threads.thread.turns.length > 0) {
|
|
1053
|
+
try {
|
|
1054
|
+
assertCodexNativePendingFirstUseTurn(pendingFirstUse, threads.thread);
|
|
1055
|
+
pendingTerminalVerified = true;
|
|
1056
|
+
}
|
|
1057
|
+
catch (error) {
|
|
1058
|
+
throw new AgentRuntimeUnavailableError(this.instanceId, error instanceof Error ? error.message : "The pending native Codex first turn cannot be verified.");
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
if (deliveryReceipt) {
|
|
1062
|
+
try {
|
|
1063
|
+
assertCodexNativeFirstUseDeliveryReceiptTurn(deliveryReceipt, threads.thread);
|
|
1064
|
+
}
|
|
1065
|
+
catch (error) {
|
|
1066
|
+
throw new AgentRuntimeUnavailableError(this.instanceId, error instanceof Error ? error.message : "The delivered native Codex first turn cannot be verified.");
|
|
1067
|
+
}
|
|
812
1068
|
}
|
|
813
1069
|
if (input.historyHandoff?.mode === "import") {
|
|
814
1070
|
if (binding.state === "bound") {
|
|
@@ -818,13 +1074,27 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
818
1074
|
}
|
|
819
1075
|
settings.attachThread(threads.thread.id, threads.configuration);
|
|
820
1076
|
await resourceDelivery.verifyThread(process.client, threads.thread.id);
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1077
|
+
const lazyFirstMessageBranch = sessionBinding.state === "unbound"
|
|
1078
|
+
&& input.piboSession.kind === "branch"
|
|
1079
|
+
&& input.historyHandoff?.mode !== "import";
|
|
1080
|
+
const openedBinding = lazyFirstMessageBranch
|
|
1081
|
+
? pendingTerminalVerified
|
|
1082
|
+
? bindingForThread({
|
|
1083
|
+
piboSessionId: input.piboSession.id,
|
|
1084
|
+
runtimeInstanceId: this.instanceId,
|
|
1085
|
+
previous: sessionBinding,
|
|
1086
|
+
thread: threads.thread,
|
|
1087
|
+
settings: settings.bindingMetadata,
|
|
1088
|
+
})
|
|
1089
|
+
: sessionBinding
|
|
1090
|
+
: bindingForThread({
|
|
1091
|
+
piboSessionId: input.piboSession.id,
|
|
1092
|
+
runtimeInstanceId: this.instanceId,
|
|
1093
|
+
previous: sessionBinding,
|
|
1094
|
+
thread: threads.thread,
|
|
1095
|
+
settings: settings.bindingMetadata,
|
|
1096
|
+
});
|
|
1097
|
+
return new CodexNativeThreadSession(this.instanceId, process, threads, settings, resourceDelivery, openedBinding, this.config.experimentalUserInput, async () => await startProcessBundle(`${sessionGeneration}-credential-${randomUUID()}`), input.productContext, input.services?.runtimeBindingPersistence, compatibility?.testOnlyFirstUseFailpoints);
|
|
828
1098
|
}
|
|
829
1099
|
catch (error) {
|
|
830
1100
|
settings?.dispose();
|
|
@@ -842,7 +1112,10 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
842
1112
|
return unavailableCodexThreadHistoryInspection(this.instanceId, input.binding, "codex_native_history_thread_id_missing", "The Codex runtime binding has no native thread id for history lookup.");
|
|
843
1113
|
}
|
|
844
1114
|
try {
|
|
845
|
-
const
|
|
1115
|
+
const readHistory = codexNativeHistoryReaders.get(this);
|
|
1116
|
+
if (!readHistory)
|
|
1117
|
+
throw new Error("Codex built-in history reader is unavailable.");
|
|
1118
|
+
const thread = await readHistory(input.binding.piboSessionId, input.workspace, threadId, false);
|
|
846
1119
|
return inspectCodexThreadHistory(this.instanceId, input.binding, thread);
|
|
847
1120
|
}
|
|
848
1121
|
catch (error) {
|
|
@@ -865,15 +1138,18 @@ export class CodexNativeAgentRuntimeAdapter {
|
|
|
865
1138
|
};
|
|
866
1139
|
}
|
|
867
1140
|
try {
|
|
868
|
-
const
|
|
869
|
-
|
|
1141
|
+
const readHistory = codexNativeHistoryReaders.get(this);
|
|
1142
|
+
if (!readHistory)
|
|
1143
|
+
throw new Error("Codex built-in history reader is unavailable.");
|
|
1144
|
+
const thread = await readHistory(input.binding.piboSessionId, input.workspace, threadId, true);
|
|
1145
|
+
return bindCodexNativeCompleteHistoryProof(pageCodexThreadHistory({
|
|
870
1146
|
runtimeInstanceId: this.instanceId,
|
|
871
1147
|
binding: input.binding,
|
|
872
1148
|
thread,
|
|
873
1149
|
cursor: input.cursor,
|
|
874
1150
|
beforeTimestamp: input.beforeTimestamp,
|
|
875
1151
|
limit: input.limit,
|
|
876
|
-
});
|
|
1152
|
+
}));
|
|
877
1153
|
}
|
|
878
1154
|
catch (error) {
|
|
879
1155
|
if (error instanceof CodexNativeThreadMissingError) {
|
|
@@ -142,19 +142,28 @@ function serializeMessage(message, maxMessageBytes) {
|
|
|
142
142
|
function timeoutError(label) {
|
|
143
143
|
return new CodexAppServerClientError("timeout", `${label} timed out`);
|
|
144
144
|
}
|
|
145
|
-
async function waitWithTimeout(promise, timeoutMs, label) {
|
|
145
|
+
async function waitWithTimeout(promise, timeoutMs, label, signal) {
|
|
146
|
+
if (signal?.aborted)
|
|
147
|
+
throw new CodexAppServerClientError("aborted", `${label} was aborted`);
|
|
146
148
|
let timer;
|
|
149
|
+
let onAbort;
|
|
147
150
|
try {
|
|
148
151
|
return await Promise.race([
|
|
149
152
|
promise,
|
|
150
153
|
new Promise((_resolve, reject) => {
|
|
151
154
|
timer = setTimeout(() => reject(timeoutError(label)), timeoutMs);
|
|
152
155
|
}),
|
|
156
|
+
...(signal ? [new Promise((_resolve, reject) => {
|
|
157
|
+
onAbort = () => reject(new CodexAppServerClientError("aborted", `${label} was aborted`));
|
|
158
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
159
|
+
})] : []),
|
|
153
160
|
]);
|
|
154
161
|
}
|
|
155
162
|
finally {
|
|
156
163
|
if (timer)
|
|
157
164
|
clearTimeout(timer);
|
|
165
|
+
if (onAbort)
|
|
166
|
+
signal?.removeEventListener("abort", onAbort);
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
169
|
async function sleep(delayMs, signal) {
|
|
@@ -231,6 +240,8 @@ export class CodexAppServerClient {
|
|
|
231
240
|
}
|
|
232
241
|
static async start(options) {
|
|
233
242
|
validateClientOptions(options);
|
|
243
|
+
if (options.signal?.aborted)
|
|
244
|
+
throw new CodexAppServerClientError("aborted", "Codex App Server startup was aborted");
|
|
234
245
|
let previousMask;
|
|
235
246
|
if (options.fileCreationMask !== undefined && globalThis.process.platform !== "win32") {
|
|
236
247
|
previousMask = globalThis.process.umask(options.fileCreationMask);
|
|
@@ -255,9 +266,13 @@ export class CodexAppServerClient {
|
|
|
255
266
|
};
|
|
256
267
|
const client = new CodexAppServerClient(process, options, placeholder);
|
|
257
268
|
client.attachProcessListeners();
|
|
269
|
+
const onAbort = () => {
|
|
270
|
+
void client.stopProcess(false).catch(() => { });
|
|
271
|
+
};
|
|
272
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
258
273
|
const deadline = Date.now() + client.startupTimeoutMs;
|
|
259
274
|
try {
|
|
260
|
-
await waitWithTimeout(client.spawned.promise, client.startupTimeoutMs, "Codex App Server spawn");
|
|
275
|
+
await waitWithTimeout(client.spawned.promise, client.startupTimeoutMs, "Codex App Server spawn", options.signal);
|
|
261
276
|
client.state = "initializing";
|
|
262
277
|
const initializeResult = await client.requestWithRetry("initialize", {
|
|
263
278
|
clientInfo: { ...options.clientInfo },
|
|
@@ -265,11 +280,12 @@ export class CodexAppServerClient {
|
|
|
265
280
|
}, {
|
|
266
281
|
timeoutMs: Math.max(1, deadline - Date.now()),
|
|
267
282
|
retryOverloaded: true,
|
|
283
|
+
signal: options.signal,
|
|
268
284
|
}, true);
|
|
269
285
|
const initializeResponse = validateInitializeResponse(initializeResult);
|
|
270
286
|
Object.assign(client.initializeResponse, initializeResponse);
|
|
271
287
|
Object.freeze(client.initializeResponse);
|
|
272
|
-
await waitWithTimeout(client.writeMessage({ method: "initialized" }, true), Math.max(1, deadline - Date.now()), "Codex App Server initialized notification");
|
|
288
|
+
await waitWithTimeout(client.writeMessage({ method: "initialized" }, true), Math.max(1, deadline - Date.now()), "Codex App Server initialized notification", options.signal);
|
|
273
289
|
client.state = "ready";
|
|
274
290
|
return client;
|
|
275
291
|
}
|
|
@@ -279,6 +295,9 @@ export class CodexAppServerClient {
|
|
|
279
295
|
await client.stopProcess(false).catch(() => { });
|
|
280
296
|
throw normalized;
|
|
281
297
|
}
|
|
298
|
+
finally {
|
|
299
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
300
|
+
}
|
|
282
301
|
}
|
|
283
302
|
get snapshot() {
|
|
284
303
|
return {
|