@adecore/agents 0.22.0 → 0.23.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.
@@ -12,6 +12,7 @@ export declare class CodexBackend implements ChatBackend {
12
12
  private readonly protocol;
13
13
  private readonly client;
14
14
  private promptId;
15
+ private nativePrompt;
15
16
  private imageWrites;
16
17
  private transport;
17
18
  private threadId;
@@ -42,6 +42,7 @@ export class CodexBackend {
42
42
  protocol;
43
43
  client;
44
44
  promptId = null;
45
+ nativePrompt = null;
45
46
  imageWrites = null;
46
47
  transport = null;
47
48
  threadId = '';
@@ -350,13 +351,24 @@ export class CodexBackend {
350
351
  if (frame.id !== undefined && events.length === 0 && (typeof frame.id === 'number' || typeof frame.id === 'string')) {
351
352
  transport.respondError(frame.id, -32601, `${this.client.title} does not handle ${String(frame.method)}`);
352
353
  }
353
- if (frame.method === 'turn/started' && this.protocol.turnId !== null) {
354
+ const nativeTurnId = frame.method === 'turn/started' && isRecord(frame.params) && frame.params.threadId === this.threadId ? this.protocol.turnId : null;
355
+ if (nativeTurnId !== null) {
356
+ if (this.turnUnnamed && this.promptId !== null) {
357
+ this.nativePrompt = { turnId: nativeTurnId, promptId: this.promptId };
358
+ }
354
359
  this.acceptPrompt(this.promptId ?? undefined);
355
360
  }
356
361
  for (const event of events) {
357
- this.emit(event);
362
+ if (event.type === 'turn.done' && this.nativePrompt !== null && event.native?.turnId === this.nativePrompt.turnId) {
363
+ const promptId = this.nativePrompt.promptId;
364
+ this.nativePrompt = null;
365
+ this.emit({ ...event, promptId });
366
+ }
367
+ else {
368
+ this.emit(event);
369
+ }
358
370
  }
359
- if (this.turnUnnamed && this.protocol.turnId !== null) {
371
+ if (this.turnUnnamed && nativeTurnId !== null) {
360
372
  this.turnUnnamed = false;
361
373
  if (this.interruptOwed) {
362
374
  this.interruptOwed = false;
@@ -373,11 +385,12 @@ export class CodexBackend {
373
385
  this.emit({ type: 'exit', exitCode, ...(stderr === null ? {} : { stderr }) });
374
386
  }
375
387
  emit(event) {
376
- // A turn that ended or never started leaves no stop for the next one to take.
377
- if (event.type === 'turn.done' || event.type === 'failed' || event.type === 'exit') {
388
+ // An older autonomous turn can finish while the next prompt still waits for its own turn/started.
389
+ if ((event.type === 'turn.done' && (!this.turnUnnamed || event.promptId !== undefined)) || event.type === 'failed' || event.type === 'exit') {
378
390
  this.turnUnnamed = false;
379
391
  this.interruptOwed = false;
380
392
  this.promptId = null;
393
+ this.nativePrompt = null;
381
394
  }
382
395
  if (event.type === 'image.generated' || this.imageWrites !== null) {
383
396
  const pending = (this.imageWrites ?? Promise.resolve()).then(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adecore/agents",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Node-compatible agent chat hosts, providers, accounts, usage and durable task coordination.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,8 +20,8 @@
20
20
  "test": "bun --conditions=source test"
21
21
  },
22
22
  "dependencies": {
23
- "@adecore/agent-contracts": "0.22.0",
24
- "@adecore/intelligent-ui": "0.22.0",
23
+ "@adecore/agent-contracts": "0.23.0",
24
+ "@adecore/intelligent-ui": "0.23.0",
25
25
  "zod": "^4.6.5"
26
26
  },
27
27
  "devDependencies": {
@@ -51,6 +51,7 @@ export class CodexBackend implements ChatBackend {
51
51
  private readonly protocol: CodexProtocol;
52
52
  private readonly client: CodexClientInfo;
53
53
  private promptId: string | null = null;
54
+ private nativePrompt: { turnId: string; promptId: string } | null = null;
54
55
  private imageWrites: Promise<void> | null = null;
55
56
  private transport: CodexTransport | null = null;
56
57
  private threadId = '';
@@ -382,13 +383,23 @@ export class CodexBackend implements ChatBackend {
382
383
  if (frame.id !== undefined && events.length === 0 && (typeof frame.id === 'number' || typeof frame.id === 'string')) {
383
384
  transport.respondError(frame.id, -32601, `${this.client.title} does not handle ${String(frame.method)}`);
384
385
  }
385
- if (frame.method === 'turn/started' && this.protocol.turnId !== null) {
386
+ const nativeTurnId = frame.method === 'turn/started' && isRecord(frame.params) && frame.params.threadId === this.threadId ? this.protocol.turnId : null;
387
+ if (nativeTurnId !== null) {
388
+ if (this.turnUnnamed && this.promptId !== null) {
389
+ this.nativePrompt = { turnId: nativeTurnId, promptId: this.promptId };
390
+ }
386
391
  this.acceptPrompt(this.promptId ?? undefined);
387
392
  }
388
393
  for (const event of events) {
389
- this.emit(event);
394
+ if (event.type === 'turn.done' && this.nativePrompt !== null && event.native?.turnId === this.nativePrompt.turnId) {
395
+ const promptId = this.nativePrompt.promptId;
396
+ this.nativePrompt = null;
397
+ this.emit({ ...event, promptId });
398
+ } else {
399
+ this.emit(event);
400
+ }
390
401
  }
391
- if (this.turnUnnamed && this.protocol.turnId !== null) {
402
+ if (this.turnUnnamed && nativeTurnId !== null) {
392
403
  this.turnUnnamed = false;
393
404
  if (this.interruptOwed) {
394
405
  this.interruptOwed = false;
@@ -407,11 +418,12 @@ export class CodexBackend implements ChatBackend {
407
418
  }
408
419
 
409
420
  private emit(event: BackendEvent): void {
410
- // A turn that ended or never started leaves no stop for the next one to take.
411
- if (event.type === 'turn.done' || event.type === 'failed' || event.type === 'exit') {
421
+ // An older autonomous turn can finish while the next prompt still waits for its own turn/started.
422
+ if ((event.type === 'turn.done' && (!this.turnUnnamed || event.promptId !== undefined)) || event.type === 'failed' || event.type === 'exit') {
412
423
  this.turnUnnamed = false;
413
424
  this.interruptOwed = false;
414
425
  this.promptId = null;
426
+ this.nativePrompt = null;
415
427
  }
416
428
  if (event.type === 'image.generated' || this.imageWrites !== null) {
417
429
  const pending = (this.imageWrites ?? Promise.resolve()).then(async () => {