@parall/codex-agent 1.29.0 → 1.29.1
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/dispatch.d.ts +4 -0
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +77 -4
- package/package.json +4 -4
- package/src/dispatch.ts +76 -4
package/dist/dispatch.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export declare class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
14
14
|
private initialized;
|
|
15
15
|
private startPromise;
|
|
16
16
|
private readonly activeTurns;
|
|
17
|
+
private readonly activeTurnIds;
|
|
18
|
+
private readonly pendingInjections;
|
|
17
19
|
private readonly resumedThreadIds;
|
|
18
20
|
private stopping;
|
|
19
21
|
/**
|
|
@@ -30,6 +32,8 @@ export declare class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
30
32
|
model?: string | null;
|
|
31
33
|
reasoningEffort?: string | null;
|
|
32
34
|
}): void;
|
|
35
|
+
enqueueDuringDispatch(sessionKey: string, body: string): Promise<boolean>;
|
|
36
|
+
hasPendingInjections(sessionKey: string): boolean;
|
|
33
37
|
dispatch({ event, bodyForAgent, sessionKey, context }: DispatchOpts): AsyncIterable<RuntimeEvent>;
|
|
34
38
|
getBranchPoint(_sessionKey: string): string | undefined;
|
|
35
39
|
forkSession({ sessionKey: parentSessionKey }: ForkOpts): Promise<ForkSessionHandle | null>;
|
package/dist/dispatch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,KAAK,4BAA4B,GAAG,IAAI,CACtC,gBAAgB,EACd,gBAAgB,GAChB,UAAU,GACV,WAAW,GACX,OAAO,GACP,iBAAiB,GACjB,SAAS,GACT,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,mBAAmB,CAAC;IACpC,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAmCF,qBAAa,qBAAsB,YAAW,eAAe;
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,KAAK,4BAA4B,GAAG,IAAI,CACtC,gBAAgB,EACd,gBAAgB,GAChB,UAAU,GACV,WAAW,GACX,OAAO,GACP,iBAAiB,GACjB,SAAS,GACT,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,mBAAmB,CAAC;IACpC,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAmCF,qBAAa,qBAAsB,YAAW,eAAe;IA+B/C,OAAO,CAAC,QAAQ,CAAC,IAAI;IA9BjC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,IAAI,CAA+C;IAC3D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAC/D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;gBAYQ,IAAI,EAAE,4BAA4B;IAE/D,YAAY,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAKhF,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB/E,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI1C,QAAQ,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IA6NxG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMjD,WAAW,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IA+BhG,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe;IAIrC,OAAO,CAAC,cAAc;IAKhB,IAAI;YAiBI,aAAa;YA2Bb,OAAO;IAyErB,OAAO,CAAC,qBAAqB;YAmCf,UAAU;IA2CxB,OAAO,CAAC,iBAAiB;CA4B1B"}
|
package/dist/dispatch.js
CHANGED
|
@@ -41,6 +41,8 @@ export class CodexAppServerAdapter {
|
|
|
41
41
|
initialized = false;
|
|
42
42
|
startPromise = null;
|
|
43
43
|
activeTurns = new Map();
|
|
44
|
+
activeTurnIds = new Map();
|
|
45
|
+
pendingInjections = new Map();
|
|
44
46
|
resumedThreadIds = new Set();
|
|
45
47
|
stopping = false;
|
|
46
48
|
/**
|
|
@@ -69,7 +71,49 @@ export class CodexAppServerAdapter {
|
|
|
69
71
|
if (config.reasoningEffort !== undefined)
|
|
70
72
|
this.opts.reasoningEffort = config.reasoningEffort ?? undefined;
|
|
71
73
|
}
|
|
74
|
+
async enqueueDuringDispatch(sessionKey, body) {
|
|
75
|
+
const client = this.client;
|
|
76
|
+
if (!client || client.isDisposed())
|
|
77
|
+
return false;
|
|
78
|
+
const threadId = this.opts.sessionManager.getThreadId(sessionKey);
|
|
79
|
+
if (!threadId)
|
|
80
|
+
return false;
|
|
81
|
+
const turnId = this.activeTurnIds.get(threadId);
|
|
82
|
+
if (!turnId)
|
|
83
|
+
return false;
|
|
84
|
+
try {
|
|
85
|
+
await client.sendRequest("turn/steer", {
|
|
86
|
+
threadId,
|
|
87
|
+
expectedTurnId: turnId,
|
|
88
|
+
input: buildTurnInput(body, []),
|
|
89
|
+
});
|
|
90
|
+
this.pendingInjections.set(sessionKey, (this.pendingInjections.get(sessionKey) ?? 0) + 1);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
this.opts.log?.warn?.(`codex-agent: turn/steer failed: ${errToString(err)}`);
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
hasPendingInjections(sessionKey) {
|
|
99
|
+
return (this.pendingInjections.get(sessionKey) ?? 0) > 0;
|
|
100
|
+
}
|
|
72
101
|
async *dispatch({ event, bodyForAgent, sessionKey, context }) {
|
|
102
|
+
const pending = this.pendingInjections.get(sessionKey) ?? 0;
|
|
103
|
+
if (pending > 0) {
|
|
104
|
+
this.pendingInjections.delete(sessionKey);
|
|
105
|
+
const threadId = this.opts.sessionManager.getThreadId(sessionKey);
|
|
106
|
+
if (threadId && this.client && !this.client.isDisposed()) {
|
|
107
|
+
(this.opts.log ?? context.log)?.info?.(`codex-agent[${context.accountId}]: ${pending} steer injection(s) already sent; skipping turn/start`);
|
|
108
|
+
yield {
|
|
109
|
+
type: "runtime_session",
|
|
110
|
+
runtimeSessionId: threadId,
|
|
111
|
+
runtimeLaneKey: sessionKey,
|
|
112
|
+
};
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
(this.opts.log ?? context.log)?.warn?.(`codex-agent[${context.accountId}]: pending steer invalidated (subprocess died); falling through to normal dispatch`);
|
|
116
|
+
}
|
|
73
117
|
await this.ensureStarted(context.log);
|
|
74
118
|
// After ensureStarted resolves the subprocess could still die before we
|
|
75
119
|
// capture the client (handleSubprocessClose nulls this.client). Yield a
|
|
@@ -224,7 +268,9 @@ export class CodexAppServerAdapter {
|
|
|
224
268
|
this.resumedThreadIds.add(freshThreadId);
|
|
225
269
|
threadId = freshThreadId;
|
|
226
270
|
}
|
|
227
|
-
|
|
271
|
+
const turnId = extractTurnId(turnStartResult);
|
|
272
|
+
if (turnId)
|
|
273
|
+
this.activeTurnIds.set(threadId, turnId);
|
|
228
274
|
yield {
|
|
229
275
|
type: "runtime_session",
|
|
230
276
|
runtimeSessionId: threadId,
|
|
@@ -264,8 +310,8 @@ export class CodexAppServerAdapter {
|
|
|
264
310
|
finally {
|
|
265
311
|
releasePreparedAttachments();
|
|
266
312
|
this.activeTurns.delete(threadId);
|
|
313
|
+
this.activeTurnIds.delete(threadId);
|
|
267
314
|
if (!sawTurnEnd) {
|
|
268
|
-
// Defensive: if we bailed early, make sure we leave no dangling sink.
|
|
269
315
|
sink.close();
|
|
270
316
|
}
|
|
271
317
|
}
|
|
@@ -284,10 +330,19 @@ export class CodexAppServerAdapter {
|
|
|
284
330
|
return null;
|
|
285
331
|
const handle = this.opts.sessionManager.createForkSessionKey();
|
|
286
332
|
try {
|
|
287
|
-
const
|
|
333
|
+
const forkParams = {
|
|
288
334
|
threadId: parentThreadId,
|
|
289
335
|
ephemeral: true,
|
|
290
|
-
}
|
|
336
|
+
};
|
|
337
|
+
if (this.opts.useParallProvider) {
|
|
338
|
+
forkParams.modelProvider = "parall";
|
|
339
|
+
}
|
|
340
|
+
if (this.opts.model)
|
|
341
|
+
forkParams.model = this.opts.model;
|
|
342
|
+
if (this.opts.reasoningEffort) {
|
|
343
|
+
forkParams.config = { modelReasoningEffort: this.opts.reasoningEffort };
|
|
344
|
+
}
|
|
345
|
+
const result = await client.sendRequest("thread/fork", forkParams);
|
|
291
346
|
const forkedThreadId = extractThreadId(result);
|
|
292
347
|
if (!forkedThreadId) {
|
|
293
348
|
this.opts.log?.warn?.("codex-agent: thread/fork returned no thread id");
|
|
@@ -314,6 +369,8 @@ export class CodexAppServerAdapter {
|
|
|
314
369
|
this.proc = null;
|
|
315
370
|
this.client = null;
|
|
316
371
|
this.initialized = false;
|
|
372
|
+
this.activeTurnIds.clear();
|
|
373
|
+
this.pendingInjections.clear();
|
|
317
374
|
if (client)
|
|
318
375
|
client.dispose(new Error("adapter stopped"));
|
|
319
376
|
if (proc && proc.exitCode === null && proc.signalCode === null) {
|
|
@@ -329,6 +386,8 @@ export class CodexAppServerAdapter {
|
|
|
329
386
|
activeSink.close();
|
|
330
387
|
}
|
|
331
388
|
this.activeTurns.clear();
|
|
389
|
+
this.activeTurnIds.clear();
|
|
390
|
+
this.pendingInjections.clear();
|
|
332
391
|
this.client = null;
|
|
333
392
|
this.proc = null;
|
|
334
393
|
this.initialized = false;
|
|
@@ -437,6 +496,8 @@ export class CodexAppServerAdapter {
|
|
|
437
496
|
activeSink.close();
|
|
438
497
|
}
|
|
439
498
|
this.activeTurns.clear();
|
|
499
|
+
this.activeTurnIds.clear();
|
|
500
|
+
this.pendingInjections.clear();
|
|
440
501
|
this.resumedThreadIds.clear();
|
|
441
502
|
this.client = null;
|
|
442
503
|
this.proc = null;
|
|
@@ -502,6 +563,7 @@ export class CodexAppServerAdapter {
|
|
|
502
563
|
sink.push({ kind: "runtime", event });
|
|
503
564
|
}
|
|
504
565
|
if (method === "turn/completed") {
|
|
566
|
+
this.activeTurnIds.delete(threadId);
|
|
505
567
|
sink.push({ kind: "turn_end", threadId });
|
|
506
568
|
}
|
|
507
569
|
}
|
|
@@ -592,6 +654,17 @@ function extractThreadId(result) {
|
|
|
592
654
|
return thread.id;
|
|
593
655
|
return undefined;
|
|
594
656
|
}
|
|
657
|
+
function extractTurnId(result) {
|
|
658
|
+
if (!result || typeof result !== "object")
|
|
659
|
+
return undefined;
|
|
660
|
+
const r = result;
|
|
661
|
+
if (typeof r.turnId === "string")
|
|
662
|
+
return r.turnId;
|
|
663
|
+
const turn = r.turn;
|
|
664
|
+
if (turn && typeof turn.id === "string")
|
|
665
|
+
return turn.id;
|
|
666
|
+
return undefined;
|
|
667
|
+
}
|
|
595
668
|
function extractThreadIdFromNotification(params) {
|
|
596
669
|
if (!params || typeof params !== "object")
|
|
597
670
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/codex-agent",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.1",
|
|
4
4
|
"description": "Codex CLI bridge runtime for self-hosted Parall agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"smol-toml": "^1.6.1",
|
|
29
|
-
"@parall/agent-core": "1.29.
|
|
30
|
-
"@parall/cli": "1.29.
|
|
31
|
-
"@parall/sdk": "1.29.
|
|
29
|
+
"@parall/agent-core": "1.29.1",
|
|
30
|
+
"@parall/cli": "1.29.1",
|
|
31
|
+
"@parall/sdk": "1.29.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^22.0.0",
|
package/src/dispatch.ts
CHANGED
|
@@ -77,6 +77,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
77
77
|
private initialized = false;
|
|
78
78
|
private startPromise: Promise<void> | null = null;
|
|
79
79
|
private readonly activeTurns = new Map<string, TurnSink>();
|
|
80
|
+
private readonly activeTurnIds = new Map<string, string>();
|
|
81
|
+
private readonly pendingInjections = new Map<string, number>();
|
|
80
82
|
private readonly resumedThreadIds = new Set<string>();
|
|
81
83
|
private stopping = false;
|
|
82
84
|
|
|
@@ -107,7 +109,52 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
107
109
|
if (config.reasoningEffort !== undefined) this.opts.reasoningEffort = config.reasoningEffort ?? undefined;
|
|
108
110
|
}
|
|
109
111
|
|
|
112
|
+
async enqueueDuringDispatch(sessionKey: string, body: string): Promise<boolean> {
|
|
113
|
+
const client = this.client;
|
|
114
|
+
if (!client || client.isDisposed()) return false;
|
|
115
|
+
const threadId = this.opts.sessionManager.getThreadId(sessionKey);
|
|
116
|
+
if (!threadId) return false;
|
|
117
|
+
const turnId = this.activeTurnIds.get(threadId);
|
|
118
|
+
if (!turnId) return false;
|
|
119
|
+
try {
|
|
120
|
+
await client.sendRequest("turn/steer", {
|
|
121
|
+
threadId,
|
|
122
|
+
expectedTurnId: turnId,
|
|
123
|
+
input: buildTurnInput(body, []),
|
|
124
|
+
});
|
|
125
|
+
this.pendingInjections.set(sessionKey, (this.pendingInjections.get(sessionKey) ?? 0) + 1);
|
|
126
|
+
return true;
|
|
127
|
+
} catch (err) {
|
|
128
|
+
this.opts.log?.warn?.(`codex-agent: turn/steer failed: ${errToString(err)}`);
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
hasPendingInjections(sessionKey: string): boolean {
|
|
134
|
+
return (this.pendingInjections.get(sessionKey) ?? 0) > 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
110
137
|
async *dispatch({ event, bodyForAgent, sessionKey, context }: DispatchOpts): AsyncIterable<RuntimeEvent> {
|
|
138
|
+
const pending = this.pendingInjections.get(sessionKey) ?? 0;
|
|
139
|
+
if (pending > 0) {
|
|
140
|
+
this.pendingInjections.delete(sessionKey);
|
|
141
|
+
const threadId = this.opts.sessionManager.getThreadId(sessionKey);
|
|
142
|
+
if (threadId && this.client && !this.client.isDisposed()) {
|
|
143
|
+
(this.opts.log ?? context.log)?.info?.(
|
|
144
|
+
`codex-agent[${context.accountId}]: ${pending} steer injection(s) already sent; skipping turn/start`,
|
|
145
|
+
);
|
|
146
|
+
yield {
|
|
147
|
+
type: "runtime_session",
|
|
148
|
+
runtimeSessionId: threadId,
|
|
149
|
+
runtimeLaneKey: sessionKey,
|
|
150
|
+
};
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
(this.opts.log ?? context.log)?.warn?.(
|
|
154
|
+
`codex-agent[${context.accountId}]: pending steer invalidated (subprocess died); falling through to normal dispatch`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
111
158
|
await this.ensureStarted(context.log);
|
|
112
159
|
// After ensureStarted resolves the subprocess could still die before we
|
|
113
160
|
// capture the client (handleSubprocessClose nulls this.client). Yield a
|
|
@@ -260,7 +307,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
260
307
|
threadId = freshThreadId;
|
|
261
308
|
}
|
|
262
309
|
|
|
263
|
-
|
|
310
|
+
const turnId = extractTurnId(turnStartResult);
|
|
311
|
+
if (turnId) this.activeTurnIds.set(threadId, turnId);
|
|
264
312
|
yield {
|
|
265
313
|
type: "runtime_session",
|
|
266
314
|
runtimeSessionId: threadId,
|
|
@@ -300,8 +348,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
300
348
|
} finally {
|
|
301
349
|
releasePreparedAttachments();
|
|
302
350
|
this.activeTurns.delete(threadId!);
|
|
351
|
+
this.activeTurnIds.delete(threadId!);
|
|
303
352
|
if (!sawTurnEnd) {
|
|
304
|
-
// Defensive: if we bailed early, make sure we leave no dangling sink.
|
|
305
353
|
sink.close();
|
|
306
354
|
}
|
|
307
355
|
}
|
|
@@ -320,10 +368,18 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
320
368
|
if (!parentThreadId) return null;
|
|
321
369
|
const handle = this.opts.sessionManager.createForkSessionKey();
|
|
322
370
|
try {
|
|
323
|
-
const
|
|
371
|
+
const forkParams: Record<string, unknown> = {
|
|
324
372
|
threadId: parentThreadId,
|
|
325
373
|
ephemeral: true,
|
|
326
|
-
}
|
|
374
|
+
};
|
|
375
|
+
if (this.opts.useParallProvider) {
|
|
376
|
+
forkParams.modelProvider = "parall";
|
|
377
|
+
}
|
|
378
|
+
if (this.opts.model) forkParams.model = this.opts.model;
|
|
379
|
+
if (this.opts.reasoningEffort) {
|
|
380
|
+
forkParams.config = { modelReasoningEffort: this.opts.reasoningEffort };
|
|
381
|
+
}
|
|
382
|
+
const result = await client.sendRequest("thread/fork", forkParams);
|
|
327
383
|
const forkedThreadId = extractThreadId(result);
|
|
328
384
|
if (!forkedThreadId) {
|
|
329
385
|
this.opts.log?.warn?.("codex-agent: thread/fork returned no thread id");
|
|
@@ -352,6 +408,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
352
408
|
this.proc = null;
|
|
353
409
|
this.client = null;
|
|
354
410
|
this.initialized = false;
|
|
411
|
+
this.activeTurnIds.clear();
|
|
412
|
+
this.pendingInjections.clear();
|
|
355
413
|
if (client) client.dispose(new Error("adapter stopped"));
|
|
356
414
|
if (proc && proc.exitCode === null && proc.signalCode === null) {
|
|
357
415
|
if (!IS_WIN32 || !proc.pid || !killWin32Tree(proc.pid)) {
|
|
@@ -367,6 +425,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
367
425
|
activeSink.close();
|
|
368
426
|
}
|
|
369
427
|
this.activeTurns.clear();
|
|
428
|
+
this.activeTurnIds.clear();
|
|
429
|
+
this.pendingInjections.clear();
|
|
370
430
|
this.client = null;
|
|
371
431
|
this.proc = null;
|
|
372
432
|
this.initialized = false;
|
|
@@ -485,6 +545,8 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
485
545
|
activeSink.close();
|
|
486
546
|
}
|
|
487
547
|
this.activeTurns.clear();
|
|
548
|
+
this.activeTurnIds.clear();
|
|
549
|
+
this.pendingInjections.clear();
|
|
488
550
|
this.resumedThreadIds.clear();
|
|
489
551
|
this.client = null;
|
|
490
552
|
this.proc = null;
|
|
@@ -557,6 +619,7 @@ export class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
557
619
|
sink.push({ kind: "runtime", event });
|
|
558
620
|
}
|
|
559
621
|
if (method === "turn/completed") {
|
|
622
|
+
this.activeTurnIds.delete(threadId);
|
|
560
623
|
sink.push({ kind: "turn_end", threadId });
|
|
561
624
|
}
|
|
562
625
|
}
|
|
@@ -653,6 +716,15 @@ function extractThreadId(result: unknown): string | undefined {
|
|
|
653
716
|
return undefined;
|
|
654
717
|
}
|
|
655
718
|
|
|
719
|
+
function extractTurnId(result: unknown): string | undefined {
|
|
720
|
+
if (!result || typeof result !== "object") return undefined;
|
|
721
|
+
const r = result as Record<string, unknown>;
|
|
722
|
+
if (typeof r.turnId === "string") return r.turnId;
|
|
723
|
+
const turn = r.turn as Record<string, unknown> | undefined;
|
|
724
|
+
if (turn && typeof turn.id === "string") return turn.id;
|
|
725
|
+
return undefined;
|
|
726
|
+
}
|
|
727
|
+
|
|
656
728
|
function extractThreadIdFromNotification(params: unknown): string | undefined {
|
|
657
729
|
if (!params || typeof params !== "object") return undefined;
|
|
658
730
|
const p = params as Record<string, unknown>;
|