@coder/ai-sdk-agent 0.8.0 → 0.9.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/README.md +61 -16
- package/dist/index.d.ts +168 -13
- package/dist/index.js +242 -83
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -321,7 +321,9 @@ await agent.generate({ prompt: "…" });
|
|
|
321
321
|
// e.g. attribute where the turn spent its time:
|
|
322
322
|
for (const ev of events) {
|
|
323
323
|
if (ev.type === "http:response")
|
|
324
|
-
console.log(
|
|
324
|
+
console.log(
|
|
325
|
+
`${ev.op}: ${ev.method} ${ev.path} → ${ev.status} in ${ev.durationMs.toFixed(0)}ms`,
|
|
326
|
+
);
|
|
325
327
|
if (ev.type === "ws:event" && ev.event.type === "action_required")
|
|
326
328
|
console.log(`tool calls arrived at +${ev.timestamp - events[0]!.timestamp}ms`);
|
|
327
329
|
if (ev.type === "segment:settle")
|
|
@@ -335,12 +337,12 @@ such as a message's `created_at`, for delivery‑lag measurements):
|
|
|
335
337
|
|
|
336
338
|
| event | when | payload (besides `timestamp`) |
|
|
337
339
|
| ---------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
338
|
-
| `http:request` | a REST request is sent | `id` (correlates the pair), `method`, `path`
|
|
339
|
-
| `http:response` | response headers arrive (incl. non‑2xx, `ok:false`) | `id`, `method`, `path`, `status`, `ok`, `durationMs`
|
|
340
|
-
| `http:error` | the fetch itself rejects (network failure, abort) | `id`, `method`, `path`, `message`, `durationMs`
|
|
340
|
+
| `http:request` | a REST request is sent | `id` (correlates the pair), `op` (the client operation, e.g. `"createChatMessage"`), `method`, `path` |
|
|
341
|
+
| `http:response` | response headers arrive (incl. non‑2xx, `ok:false`) | `id`, `op`, `method`, `path`, `status`, `ok`, `durationMs` |
|
|
342
|
+
| `http:error` | the fetch itself rejects (network failure, abort) | `id`, `op`, `method`, `path`, `message`, `durationMs` |
|
|
341
343
|
| `ws:dial` | a stream connection attempt starts | `chatId`, `reader` (identifies the `streamChatEvents` call), `attempt` (1‑based per reader, increments per redial), `url` |
|
|
342
344
|
| `ws:open` | the WebSocket handshake completes | `chatId`, `reader`, `attempt` |
|
|
343
|
-
| `ws:event` | a decoded stream event arrives | `chatId`, `reader`, `attempt`, `event` (the decoded `ChatStreamEvent`, by reference — don't mutate)
|
|
345
|
+
| `ws:event` | a decoded stream event arrives | `chatId`, `reader`, `attempt`, `event` (the decoded `ChatStreamEvent`, by reference — don't mutate), `forwarded` (the reader's replay verdict) |
|
|
344
346
|
| `ws:close` | the connection ends (exactly one per dial) | `chatId`, `reader`, `attempt`, `code`/`reason` when the server/network closed it; absent when the reader closed it (settle, teardown, redial) |
|
|
345
347
|
| `ws:error` | a socket error or unparseable frame | `chatId`, `reader`, `attempt`, `message` |
|
|
346
348
|
| `ws:redial` | a dropped connection is about to be redialed | `chatId`, `reader`, `attempt` (the ended connection), `consecutiveFailures`, `maxConsecutiveFailures`, `backoffMs` |
|
|
@@ -356,9 +358,24 @@ Semantics worth knowing:
|
|
|
356
358
|
- **No secrets** — events carry no headers and no tokens (auth travels in the
|
|
357
359
|
`Coder-Session-Token` header, which is deliberately excluded); `path`/`url`
|
|
358
360
|
never contain credentials.
|
|
359
|
-
- `
|
|
360
|
-
|
|
361
|
-
|
|
361
|
+
- `http:*` events name their operation: `op` is the public `CoderChatClient`
|
|
362
|
+
method performing the exchange (`"createChat"`, `"createChatMessage"`,
|
|
363
|
+
`"getMessages"`, `"submitToolResults"`, … — the `CoderClientOperation`
|
|
364
|
+
union), so per‑operation classification never has to reverse‑engineer
|
|
365
|
+
`path`. `method`/`path` stay for generic consumers; `archiveChat` stamps its
|
|
366
|
+
own `op` even though it issues the same `PATCH` as `updateChat`.
|
|
367
|
+
- `ws:event` fires at arrival: after a redial, chatd's replay of the
|
|
368
|
+
in‑progress episode is visible here (correlate with `reader`/`attempt`),
|
|
369
|
+
stamped with the reader's own replay verdict — `forwarded: false` exactly on
|
|
370
|
+
the duplicate deltas the reader suppresses from the turn, so subscribers
|
|
371
|
+
never re‑derive the episode filter.
|
|
372
|
+
- `forwarded` does **not** reflect snapshot dedup: repeated or revised
|
|
373
|
+
`message` snapshots are always `forwarded: true`, because reconciling them
|
|
374
|
+
is deliberately the consumer's job past the transport layer —
|
|
375
|
+
`TurnTranslator`'s per‑message ledger decides what a revision re‑emits, and
|
|
376
|
+
that disposition is not stamped on transport frames. Use `ws:event` for
|
|
377
|
+
span pairing and replay accounting; subscribers needing content fidelity
|
|
378
|
+
must consume model output (or `TurnTranslator`), not transport frames.
|
|
362
379
|
- Every `ws:*` event carries `reader` — a monotonic id for the
|
|
363
380
|
`streamChatEvents` call (reader) behind the connection, allocated from one
|
|
364
381
|
process‑wide counter so it stays unique across model and client instances.
|
|
@@ -436,6 +453,25 @@ for a few seconds, during which archiving 409s — `archive()` retries those 409
|
|
|
436
453
|
`settleRetryDelayMs`) and rethrows the last one if the chat never settles. Any
|
|
437
454
|
other failure, including your own abort, rethrows immediately.
|
|
438
455
|
|
|
456
|
+
`archive()` and `interrupt()` target the session's chat — or, after the session
|
|
457
|
+
was dropped (`resetSession()`, or the automatic discard after a fresh‑chat
|
|
458
|
+
stream failure — see [Handling errors](#handling-errors)), the **last‑known
|
|
459
|
+
chat id** (`agent.lastKnownChatId`), so a stranded chat is still cleaned up
|
|
460
|
+
instead of leaking. Generation never uses the last‑known id: a turn after a
|
|
461
|
+
drop creates a fresh chat as always. Every chat stranded by an _automatic_
|
|
462
|
+
discard is also recorded on a ledger (`agent.strandedChatIds`, oldest first) —
|
|
463
|
+
with `maxRetries` several failed attempts can strand one chat each while only
|
|
464
|
+
the final attempt's error surfaces — and one `archive()` retires them all,
|
|
465
|
+
oldest first, alongside its primary target. Both methods report what they
|
|
466
|
+
acted on instead of silently no‑oping: `archive()` resolves
|
|
467
|
+
`{ archived: true, chatId, archivedChatIds }` (each archived id is cleared as
|
|
468
|
+
a cleanup target) or `{ archived: false }` when no chat exists at all;
|
|
469
|
+
`interrupt()` resolves `{ interrupted: true, chatId }` /
|
|
470
|
+
`{ interrupted: false }` the same way. Deliberate abandonment is different:
|
|
471
|
+
`resetSession()` does **not** add to the ledger (you may want that chat kept),
|
|
472
|
+
so after a manual reset the old chat is targetable only until a new chat
|
|
473
|
+
supersedes `lastKnownChatId`.
|
|
474
|
+
|
|
439
475
|
To make cleanup ride scope exit instead of a `finally` you have to remember, the
|
|
440
476
|
agent is an **async disposable**:
|
|
441
477
|
|
|
@@ -469,7 +505,11 @@ carry structured detail you can branch on:
|
|
|
469
505
|
repeat (workspace/MCP tooling, fresh attachment uploads); otherwise it is
|
|
470
506
|
`false` — a retry would resubmit the prompt as a new user turn and could
|
|
471
507
|
duplicate those effects. A failure mid‑`stream()` surfaces on the stream,
|
|
472
|
-
outside the retry wrapper. The last transport failure is in `cause
|
|
508
|
+
outside the retry wrapper. The last transport failure is in `cause`, and
|
|
509
|
+
`chatId` names the chat the failed turn had created or attached to (absent
|
|
510
|
+
when it failed before a chat existed) — after the fresh‑chat discard the
|
|
511
|
+
chat still exists server‑side, and `archive()` keeps targeting it via
|
|
512
|
+
`agent.lastKnownChatId` ([Cleanup](#cleanup)).
|
|
473
513
|
|
|
474
514
|
```ts
|
|
475
515
|
import { CoderApiError, CoderChatError } from "@coder/ai-sdk-agent";
|
|
@@ -946,7 +986,9 @@ export async function runTurn(workflowId: string, prompt: string): Promise<strin
|
|
|
946
986
|
// still persist the id, or the retried step orphans a live chat and its
|
|
947
987
|
// partial effects. Exception: after an exhausted stream failure on a
|
|
948
988
|
// chat this very call created, the SDK has already discarded the dead
|
|
949
|
-
// session (agent.chatId is undefined) and nothing is written —
|
|
989
|
+
// session (agent.chatId is undefined) and nothing is written — the thrown
|
|
990
|
+
// CoderStreamError's chatId still names the stranded chat, and
|
|
991
|
+
// agent.archive() retires it via agent.lastKnownChatId — see the
|
|
950
992
|
// CoderStreamError notes below for what retrying means then.
|
|
951
993
|
if (agent.chatId) await checkpoints.set(workflowId, agent.chatId);
|
|
952
994
|
}
|
|
@@ -1063,12 +1105,15 @@ try {
|
|
|
1063
1105
|
the dead session so a retry — `maxRetries` or a re‑run step — starts clean
|
|
1064
1106
|
on a fresh chat. The discard happens for _every_ chat the failed turn
|
|
1065
1107
|
itself created — **including the effectful, `isRetryable: false` case**:
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1108
|
+
`agent.chatId` is `undefined` and the `finally` checkpoint writes nothing —
|
|
1109
|
+
but the stranded chat is not nameless: the error's **`chatId`** field names
|
|
1110
|
+
it, and `interrupt()`/`archive()` keep targeting it via
|
|
1111
|
+
`agent.lastKnownChatId` ([Cleanup](#cleanup)), so the step's error path can
|
|
1112
|
+
retire the orphan directly — or checkpoint `err.chatId` for the
|
|
1113
|
+
reconciliation sweep (below) when its workspace/MCP effects need
|
|
1114
|
+
reconciling first. A retried step then starts a fresh chat that has _not_
|
|
1115
|
+
seen the orphan's effects: gate that retry on the same idempotency judgment
|
|
1116
|
+
as any re‑submission. **On a resumed chat it is always `isRetryable: false`:**
|
|
1072
1117
|
re‑running the step resubmits the same prompt as a _new user turn_, with the
|
|
1073
1118
|
failed attempt's partial output still in history (usually fine — the model
|
|
1074
1119
|
sees its own aborted attempt), and any workspace/MCP tool effects that ran
|
package/dist/index.d.ts
CHANGED
|
@@ -344,12 +344,27 @@ interface TransportEventBase {
|
|
|
344
344
|
/** Wall-clock observation time in ms since epoch (`Date.now()`). */
|
|
345
345
|
timestamp: number;
|
|
346
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Names the `CoderChatClient` operation performing an HTTP exchange (issue
|
|
349
|
+
* #112). The public client method names are the stable vocabulary, so
|
|
350
|
+
* subscribers can classify per-operation timings without reverse-engineering
|
|
351
|
+
* `path` (whose API prefix is private and may change). New client methods
|
|
352
|
+
* extend this union; treat unrecognized values as "some other operation"
|
|
353
|
+
* rather than matching exhaustively.
|
|
354
|
+
*/
|
|
355
|
+
type CoderClientOperation = "listModelConfigs" | "resolveModelConfigId" | "createChat" | "getChat" | "createChatMessage" | "getMessages" | "submitToolResults" | "interruptChat" | "updateChat" | "archiveChat" | "uploadChatFile" | "getChatFile";
|
|
347
356
|
interface HttpTransportEventBase extends TransportEventBase {
|
|
348
357
|
/**
|
|
349
358
|
* Correlates a request with its response/error. Monotonically increasing
|
|
350
359
|
* per client instance.
|
|
351
360
|
*/
|
|
352
361
|
id: number;
|
|
362
|
+
/**
|
|
363
|
+
* The client operation performing this exchange — the public
|
|
364
|
+
* `CoderChatClient` method name. `archiveChat` stamps its own operation
|
|
365
|
+
* even though it issues the same `PATCH` as `updateChat`.
|
|
366
|
+
*/
|
|
367
|
+
op: CoderClientOperation;
|
|
353
368
|
/** HTTP method, e.g. `POST`. */
|
|
354
369
|
method: string;
|
|
355
370
|
/**
|
|
@@ -415,14 +430,31 @@ interface StreamOpenTransportEvent extends StreamTransportEventBase {
|
|
|
415
430
|
}
|
|
416
431
|
/**
|
|
417
432
|
* A decoded stream event arrived on the wire. Emitted at arrival time for
|
|
418
|
-
* every event in a frame batch
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
433
|
+
* every event in a frame batch — after a redial, chatd's replay of the
|
|
434
|
+
* in-progress episode is still visible here, stamped with the reader's own
|
|
435
|
+
* replay verdict (`forwarded`). `event` is the decoded object by reference
|
|
436
|
+
* (no copy): do not mutate it.
|
|
422
437
|
*/
|
|
423
438
|
interface StreamEventTransportEvent extends StreamTransportEventBase {
|
|
424
439
|
type: "ws:event";
|
|
425
440
|
event: ChatStreamEvent;
|
|
441
|
+
/**
|
|
442
|
+
* The reader's replay disposition for this frame (issue #111): `false`
|
|
443
|
+
* exactly when the episode filter suppresses it from the consumption path —
|
|
444
|
+
* a redial's replay of an in-progress delta at or below the last yielded
|
|
445
|
+
* `seq` of the same episode — and `true` when the reader forwards it to its
|
|
446
|
+
* consumer. It is a dedup verdict, not a delivery receipt: a consumer
|
|
447
|
+
* tearing down mid-queue can still discard a forwarded frame.
|
|
448
|
+
*
|
|
449
|
+
* Snapshot dedup is deliberately NOT reflected here: repeated or revised
|
|
450
|
+
* `message` snapshots are always `forwarded: true`, because reconciling
|
|
451
|
+
* them is the consumer's job past the transport layer — TurnTranslator's
|
|
452
|
+
* per-message emitted-content ledger decides what a revision re-emits.
|
|
453
|
+
* That disposition is not stamped on transport frames; subscribers needing
|
|
454
|
+
* content fidelity must consume model output (or TurnTranslator), not
|
|
455
|
+
* `ws:event`.
|
|
456
|
+
*/
|
|
457
|
+
forwarded: boolean;
|
|
426
458
|
}
|
|
427
459
|
/**
|
|
428
460
|
* The connection ended. Exactly one per dial: carries `code`/`reason` when
|
|
@@ -586,7 +618,10 @@ interface StreamChatEventsOptions {
|
|
|
586
618
|
* in-progress generation attempt's `message_part` deltas from `seq` 1, so
|
|
587
619
|
* parts of an episode
|
|
588
620
|
* (`history_version`, `generation_attempt`) at or below the last yielded `seq`
|
|
589
|
-
* are suppressed here rather than double-yielded.
|
|
621
|
+
* are suppressed here rather than double-yielded. That episode filter runs at
|
|
622
|
+
* frame arrival (not at consumption), so each frame's `ws:event` can carry
|
|
623
|
+
* the reader's own verdict as `forwarded` (issue #111) while `timestamp`
|
|
624
|
+
* keeps meaning arrival time. The iteration ends in five
|
|
590
625
|
* ways: `signal` aborting (clean return), a non-transient 4xx upgrade
|
|
591
626
|
* rejection (terminal {@link CoderApiError} — bad/expired token or a deleted
|
|
592
627
|
* chat cannot succeed on retry, while 408/425/429 consume the redial budget),
|
|
@@ -815,6 +850,37 @@ interface ChatAttachment extends UploadedChatFile {
|
|
|
815
850
|
*/
|
|
816
851
|
toFilePart(): FilePart;
|
|
817
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* Result of {@link CoderAgent.interrupt}: `interrupted: false` means there was
|
|
855
|
+
* no chat to interrupt (neither a live session nor a
|
|
856
|
+
* {@link CoderAgent.lastKnownChatId}) and no server call was made.
|
|
857
|
+
*/
|
|
858
|
+
type CoderInterruptResult = {
|
|
859
|
+
interrupted: true;
|
|
860
|
+
chatId: string;
|
|
861
|
+
} | {
|
|
862
|
+
interrupted: false;
|
|
863
|
+
chatId?: undefined;
|
|
864
|
+
};
|
|
865
|
+
/**
|
|
866
|
+
* Result of {@link CoderAgent.archive}: `archived: false` means there was no
|
|
867
|
+
* chat to archive (neither a live session nor a
|
|
868
|
+
* {@link CoderAgent.lastKnownChatId}) and no server call was made. Failures
|
|
869
|
+
* still throw — see {@link CoderAgent.archive}. `chatId` is the primary
|
|
870
|
+
* target (the session's or last-known chat); `archivedChatIds` additionally
|
|
871
|
+
* lists every chat archived by the call, oldest first — more than one when
|
|
872
|
+
* earlier stranded chats ({@link CoderAgent.strandedChatIds}) were retired
|
|
873
|
+
* alongside it.
|
|
874
|
+
*/
|
|
875
|
+
type CoderArchiveResult = {
|
|
876
|
+
archived: true;
|
|
877
|
+
chatId: string;
|
|
878
|
+
archivedChatIds: string[];
|
|
879
|
+
} | {
|
|
880
|
+
archived: false;
|
|
881
|
+
chatId?: undefined;
|
|
882
|
+
archivedChatIds?: undefined;
|
|
883
|
+
};
|
|
818
884
|
interface CoderAgentSettings<TOOLS extends ToolSet = {}> {
|
|
819
885
|
/**
|
|
820
886
|
* A pre-built {@link CoderChatClient}, used instead of constructing one from
|
|
@@ -964,6 +1030,25 @@ declare class CoderAgent<TOOLS extends ToolSet = {}> implements Agent<never, TOO
|
|
|
964
1030
|
get client(): CoderChatClient;
|
|
965
1031
|
/** The current chatd chat id, once a turn has started. */
|
|
966
1032
|
get chatId(): string | undefined;
|
|
1033
|
+
/**
|
|
1034
|
+
* The last chat id this agent created or attached to, retained for CLEANUP
|
|
1035
|
+
* even after the session was dropped — a fresh-chat stream failure discards
|
|
1036
|
+
* the session ({@link CoderAgent.chatId} becomes `undefined`, so a retry
|
|
1037
|
+
* starts fresh), but the failed chat still exists server-side.
|
|
1038
|
+
* {@link CoderAgent.archive} and {@link CoderAgent.interrupt} fall back to
|
|
1039
|
+
* this id; generation never does. Superseded when a later turn creates or
|
|
1040
|
+
* attaches to another chat; cleared once {@link CoderAgent.archive}
|
|
1041
|
+
* succeeds against it.
|
|
1042
|
+
*/
|
|
1043
|
+
get lastKnownChatId(): string | undefined;
|
|
1044
|
+
/**
|
|
1045
|
+
* Chat ids stranded by automatic session discards and not yet cleaned up,
|
|
1046
|
+
* oldest first. Each retryable fresh-chat stream failure strands one chat,
|
|
1047
|
+
* so with `maxRetries` > 0 several can accumulate while only the final
|
|
1048
|
+
* attempt's error (and {@link CoderAgent.lastKnownChatId}) names the
|
|
1049
|
+
* newest. {@link CoderAgent.archive} retires all of them.
|
|
1050
|
+
*/
|
|
1051
|
+
get strandedChatIds(): string[];
|
|
967
1052
|
generate(options: Parameters<InnerAgent<TOOLS>["generate"]>[0]): ReturnType<InnerAgent<TOOLS>["generate"]>;
|
|
968
1053
|
stream(options: Parameters<InnerAgent<TOOLS>["stream"]>[0]): ReturnType<InnerAgent<TOOLS>["stream"]>;
|
|
969
1054
|
/**
|
|
@@ -972,33 +1057,61 @@ declare class CoderAgent<TOOLS extends ToolSet = {}> implements Agent<never, TOO
|
|
|
972
1057
|
* `id`, `provider`/`model`, or `display_name`.
|
|
973
1058
|
*/
|
|
974
1059
|
listModels(signal?: AbortSignal): Promise<ChatModelConfig[]>;
|
|
975
|
-
/**
|
|
1060
|
+
/**
|
|
1061
|
+
* Start a fresh chatd chat on the next turn. The dropped chat still exists
|
|
1062
|
+
* server-side: {@link CoderAgent.archive} / {@link CoderAgent.interrupt}
|
|
1063
|
+
* keep targeting it (via {@link CoderAgent.lastKnownChatId}) until a new
|
|
1064
|
+
* chat supersedes it or an archive succeeds against it.
|
|
1065
|
+
*/
|
|
976
1066
|
resetSession(): void;
|
|
977
1067
|
/**
|
|
978
1068
|
* Interrupt the in-flight generation, if any. Resolves as soon as the server
|
|
979
1069
|
* acknowledges the interrupt — the run keeps winding down asynchronously for
|
|
980
1070
|
* a few seconds afterwards (see {@link CoderAgent.archive}).
|
|
1071
|
+
*
|
|
1072
|
+
* Targets the session's chat, or — after the session was dropped (a
|
|
1073
|
+
* fresh-chat stream failure, or {@link CoderAgent.resetSession}) — the
|
|
1074
|
+
* {@link CoderAgent.lastKnownChatId}, whose run may still be winding down
|
|
1075
|
+
* server-side. With neither, there is nothing to interrupt and it resolves
|
|
1076
|
+
* `{ interrupted: false }` without a server call (inspect the result rather
|
|
1077
|
+
* than relying on a silent no-op).
|
|
981
1078
|
*/
|
|
982
1079
|
interrupt(opts?: {
|
|
983
1080
|
signal?: AbortSignal;
|
|
984
|
-
}): Promise<
|
|
1081
|
+
}): Promise<CoderInterruptResult>;
|
|
985
1082
|
/**
|
|
986
1083
|
* Archive the underlying chat (safe cleanup; hides it from listings).
|
|
987
1084
|
*
|
|
1085
|
+
* Targets the session's chat, or — after the session was dropped (a
|
|
1086
|
+
* fresh-chat stream failure, or {@link CoderAgent.resetSession}) — the
|
|
1087
|
+
* {@link CoderAgent.lastKnownChatId}, so the stranded chat is still cleaned
|
|
1088
|
+
* up; chats stranded by EARLIER automatic discards
|
|
1089
|
+
* ({@link CoderAgent.strandedChatIds} — `maxRetries` can accumulate several)
|
|
1090
|
+
* are retired in the same call. On success each archived id is cleared as a
|
|
1091
|
+
* cleanup target; with no id at all, there is nothing to archive and it
|
|
1092
|
+
* resolves `{ archived: false }` without a server call (inspect the result
|
|
1093
|
+
* rather than relying on a silent no-op).
|
|
1094
|
+
*
|
|
988
1095
|
* A freshly interrupted/settled chat can keep winding down server-side for a
|
|
989
1096
|
* few seconds, during which the server rejects archiving with a 409. Those
|
|
990
|
-
* 409s are retried (~1s apart
|
|
991
|
-
* `
|
|
992
|
-
*
|
|
1097
|
+
* 409s are retried (~1s apart — see `settleRetryDelayMs`) inside ONE
|
|
1098
|
+
* `settleDeadlineMs` window (~15s) shared by the whole call — however many
|
|
1099
|
+
* chats it archives — and the last 409 is rethrown if the window closes
|
|
1100
|
+
* first; any other failure, including a caller abort, rethrows immediately.
|
|
1101
|
+
* Chats are archived oldest first, each id cleared as its archive succeeds —
|
|
1102
|
+
* a mid-list failure rethrows and leaves the remaining ids targetable by a
|
|
1103
|
+
* later retry.
|
|
993
1104
|
*/
|
|
994
1105
|
archive(opts?: {
|
|
995
1106
|
signal?: AbortSignal;
|
|
996
|
-
}): Promise<
|
|
1107
|
+
}): Promise<CoderArchiveResult>;
|
|
997
1108
|
/**
|
|
998
1109
|
* Clean up the chat when the agent leaves an `await using` scope, so cleanup
|
|
999
1110
|
* rides scope exit instead of a separate call you have to remember in a
|
|
1000
1111
|
* `finally`. Interrupts any in-flight server run, then archives the chat
|
|
1001
|
-
* (retrying while the interrupted run settles)
|
|
1112
|
+
* (retrying while the interrupted run settles) — including a chat stranded
|
|
1113
|
+
* by a session discard (see {@link CoderAgent.lastKnownChatId}), which a
|
|
1114
|
+
* failed `generate()` would otherwise leak. Best-effort and bounded
|
|
1002
1115
|
* (~15s overall): disposal errors are swallowed after the bounded attempts
|
|
1003
1116
|
* so they can't mask the scope's own error — call {@link CoderAgent.archive}
|
|
1004
1117
|
* directly when you need guaranteed cleanup.
|
|
@@ -1128,10 +1241,42 @@ declare class CoderLanguageModel implements LanguageModelV4 {
|
|
|
1128
1241
|
readonly supportedUrls: Record<string, RegExp[]>;
|
|
1129
1242
|
constructor(config: CoderLanguageModelConfig);
|
|
1130
1243
|
get chatId(): string | undefined;
|
|
1244
|
+
/**
|
|
1245
|
+
* The last chat id this model created or attached to, for CLEANUP targeting
|
|
1246
|
+
* only — generation always targets {@link chatId}. It survives
|
|
1247
|
+
* {@link resetSession} (including the automatic session discard after a
|
|
1248
|
+
* fresh-chat stream failure, which clears {@link chatId} so a retry starts
|
|
1249
|
+
* fresh while the failed chat still exists server-side), is superseded when
|
|
1250
|
+
* a later turn creates or attaches to another chat, and is cleared via
|
|
1251
|
+
* {@link noteChatCleanedUp} once cleanup actually succeeded against it.
|
|
1252
|
+
*/
|
|
1253
|
+
get lastKnownChatId(): string | undefined;
|
|
1254
|
+
/**
|
|
1255
|
+
* Chat ids stranded by automatic session discards and not yet cleaned up,
|
|
1256
|
+
* oldest first. Each retryable fresh-chat stream failure strands one chat;
|
|
1257
|
+
* under AI-SDK `maxRetries` several can accumulate while only the final
|
|
1258
|
+
* attempt's error (and {@link lastKnownChatId}) names the newest —
|
|
1259
|
+
* `CoderAgent.archive()` retires all of them. Ids leave the list only via
|
|
1260
|
+
* {@link noteChatCleanedUp}.
|
|
1261
|
+
*/
|
|
1262
|
+
get strandedChatIds(): string[];
|
|
1263
|
+
/**
|
|
1264
|
+
* Forgets `chatId` as a cleanup target — call it only after cleanup
|
|
1265
|
+
* actually succeeded against that chat (e.g. `CoderAgent.archive()`
|
|
1266
|
+
* archived it), so later cleanup calls don't re-target an already-archived
|
|
1267
|
+
* chat: removes it from {@link strandedChatIds} and, when it is the
|
|
1268
|
+
* last-known id, clears {@link lastKnownChatId} (match-guarded: a stale
|
|
1269
|
+
* completion must not erase a newer chat's id). The session field
|
|
1270
|
+
* ({@link chatId}) is deliberately untouched — archiving does not reset the
|
|
1271
|
+
* session.
|
|
1272
|
+
*/
|
|
1273
|
+
noteChatCleanedUp(chatId: string): void;
|
|
1131
1274
|
/**
|
|
1132
1275
|
* Drops the current session so the next turn creates a fresh chat. Also
|
|
1133
1276
|
* closes the retained event stream, if any (fire-and-forget — a sync reset
|
|
1134
1277
|
* must not wait on socket teardown, and `close()` never rejects).
|
|
1278
|
+
* {@link lastKnownChatId} deliberately survives the reset: the dropped chat
|
|
1279
|
+
* still exists server-side and cleanup must still be able to target it.
|
|
1135
1280
|
*/
|
|
1136
1281
|
resetSession(): void;
|
|
1137
1282
|
/**
|
|
@@ -1340,11 +1485,21 @@ declare class CoderApiError extends CoderAgentError {
|
|
|
1340
1485
|
*/
|
|
1341
1486
|
declare class CoderStreamError extends APICallError {
|
|
1342
1487
|
name: string;
|
|
1488
|
+
/**
|
|
1489
|
+
* The chatd chat id the failed turn had created or attached to, when known.
|
|
1490
|
+
* A fresh-chat stream failure discards the session so a retry starts on a
|
|
1491
|
+
* fresh chat (`CoderAgent.chatId` becomes `undefined`), but the failed chat
|
|
1492
|
+
* still exists server-side — this field names it so callers can clean it up
|
|
1493
|
+
* (`CoderAgent.archive()` also retains it as the last-known cleanup target).
|
|
1494
|
+
* `undefined` when the failure happened before any chat existed.
|
|
1495
|
+
*/
|
|
1496
|
+
readonly chatId: string | undefined;
|
|
1343
1497
|
constructor(args: {
|
|
1344
1498
|
message: string;
|
|
1345
1499
|
url: string;
|
|
1346
1500
|
cause?: unknown;
|
|
1347
1501
|
isRetryable?: boolean;
|
|
1502
|
+
chatId?: string;
|
|
1348
1503
|
});
|
|
1349
1504
|
}
|
|
1350
1505
|
/** A chat generation ended in an error status. */
|
|
@@ -1357,4 +1512,4 @@ declare class CoderChatError extends CoderAgentError {
|
|
|
1357
1512
|
constructor(payload: ChatErrorPayload);
|
|
1358
1513
|
}
|
|
1359
1514
|
|
|
1360
|
-
export { CHAT_ATTACHMENT_MEDIA_TYPES, CODER_PROVIDER_OPTIONS, type Chat, type ChatAttachment, type ChatAttachmentMediaType, type ChatBusyBehavior, type ChatClientType, type ChatErrorPayload, type ChatFileInput, type ChatInputPart, type ChatInputPartType, type ChatMessage, type ChatMessagePart, type ChatMessagePartType, type ChatMessageRole, type ChatMessageUsage, type ChatMessagesResponse, type ChatMessagesToUIMessagesOptions, type ChatModelConfig, type ChatPlanMode, type ChatQueuedMessage, type ChatStatus, type ChatStreamActionRequired, type ChatStreamEvent, type ChatStreamEventType, type ChatStreamMessagePart, type ChatStreamRetry, type ChatStreamStatus, type ChatStreamToolCall, type ChatWatchEvent, type ChatWatchEventKind, CoderAgent, CoderAgentError, type CoderAgentSettings, CoderApiError, CoderChatClient, type CoderChatClientOptions, CoderChatError, type CoderFileProviderOptions, CoderLanguageModel, type CoderLanguageModelConfig, CoderStreamError, type CoderTransportEvent, type CreateChatMessageRequest, type CreateChatMessageResponse, type CreateChatRequest, type DynamicTool, type FileContent, type FilePartUploader, type HttpErrorTransportEvent, type HttpRequestTransportEvent, type HttpResponseTransportEvent, MAX_CHAT_FILE_SIZE_BYTES, type PreviewShareLevel, type ResolvedFile, type SegmentSettleTransportEvent, type SegmentStartTransportEvent, type SharePreviewOptions, type SharedWorkspacePreview, type StreamCloseTransportEvent, type StreamDialTransportEvent, type StreamErrorTransportEvent, type StreamEventTransportEvent, type StreamOpenTransportEvent, type StreamRedialTransportEvent, type SubmitToolResultsRequest, TERMINAL_STATUSES, type ToolResult, type TransportEventHandler, type TurnAction, TurnTranslator, type UpdateChatRequest, type UploadChatFileResponse, type UploadedChatFile, type UserContent, type WatchChatEventsOptions, type WebSocketFactory, type WebSocketLike, type WorkspaceFileStore, type WorkspacePlacement, type WorkspacePreview, type WorkspacePreviewOptions, chatMessagesToUIMessages, classifyTurnAction, dataContentToFileContent, dynamicToolNames, extractSystemPrompt, resolveFileContent, streamChatEvents, toolsToDynamicTools, userContentToInputParts, watchChatEvents };
|
|
1515
|
+
export { CHAT_ATTACHMENT_MEDIA_TYPES, CODER_PROVIDER_OPTIONS, type Chat, type ChatAttachment, type ChatAttachmentMediaType, type ChatBusyBehavior, type ChatClientType, type ChatErrorPayload, type ChatFileInput, type ChatInputPart, type ChatInputPartType, type ChatMessage, type ChatMessagePart, type ChatMessagePartType, type ChatMessageRole, type ChatMessageUsage, type ChatMessagesResponse, type ChatMessagesToUIMessagesOptions, type ChatModelConfig, type ChatPlanMode, type ChatQueuedMessage, type ChatStatus, type ChatStreamActionRequired, type ChatStreamEvent, type ChatStreamEventType, type ChatStreamMessagePart, type ChatStreamRetry, type ChatStreamStatus, type ChatStreamToolCall, type ChatWatchEvent, type ChatWatchEventKind, CoderAgent, CoderAgentError, type CoderAgentSettings, CoderApiError, type CoderArchiveResult, CoderChatClient, type CoderChatClientOptions, CoderChatError, type CoderClientOperation, type CoderFileProviderOptions, type CoderInterruptResult, CoderLanguageModel, type CoderLanguageModelConfig, CoderStreamError, type CoderTransportEvent, type CreateChatMessageRequest, type CreateChatMessageResponse, type CreateChatRequest, type DynamicTool, type FileContent, type FilePartUploader, type HttpErrorTransportEvent, type HttpRequestTransportEvent, type HttpResponseTransportEvent, MAX_CHAT_FILE_SIZE_BYTES, type PreviewShareLevel, type ResolvedFile, type SegmentSettleTransportEvent, type SegmentStartTransportEvent, type SharePreviewOptions, type SharedWorkspacePreview, type StreamCloseTransportEvent, type StreamDialTransportEvent, type StreamErrorTransportEvent, type StreamEventTransportEvent, type StreamOpenTransportEvent, type StreamRedialTransportEvent, type SubmitToolResultsRequest, TERMINAL_STATUSES, type ToolResult, type TransportEventHandler, type TurnAction, TurnTranslator, type UpdateChatRequest, type UploadChatFileResponse, type UploadedChatFile, type UserContent, type WatchChatEventsOptions, type WebSocketFactory, type WebSocketLike, type WorkspaceFileStore, type WorkspacePlacement, type WorkspacePreview, type WorkspacePreviewOptions, chatMessagesToUIMessages, classifyTurnAction, dataContentToFileContent, dynamicToolNames, extractSystemPrompt, resolveFileContent, streamChatEvents, toolsToDynamicTools, userContentToInputParts, watchChatEvents };
|