@anvia/client 1.7.0 → 1.8.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.
@@ -12,7 +12,7 @@ export declare class DurableBusyError extends Error {
12
12
  constructor(runId: string | undefined, message?: string);
13
13
  }
14
14
  /** Methods the adapter needs. A structural subset of `DurableClient`, so tests can fake it. */
15
- export type DurableChatClient = Pick<DurableClient, "submit" | "stream" | "respond" | "resolveTool" | "retry" | "cancel" | "listRuns">;
15
+ export type DurableChatClient = Pick<DurableClient, "submit" | "stream" | "snapshot" | "respond" | "resolveTool" | "retry" | "cancel" | "listRuns"> & Partial<Pick<DurableClient, "resolveMemoryWrite">>;
16
16
  /**
17
17
  * Run controls that `useChat` does not expose. `stop()` only aborts the subscription; cancellation
18
18
  * is always this explicit `cancel()`.
@@ -25,6 +25,8 @@ export type DurableChatController = {
25
25
  cancel(runId?: string): Promise<void>;
26
26
  retry(runId?: string): Promise<void>;
27
27
  resolveTool(operationId: string, output: ToolResultOutput, runId?: string): Promise<void>;
28
+ /** Settle a blocked recorded memory write: `applied` says the store holds it, `discarded` drops it. */
29
+ resolveMemoryWrite(operationKey: string, resolution: "applied" | "discarded", runId?: string): Promise<void>;
28
30
  };
29
31
  export type CreateDurableChatTransportOptions = {
30
32
  client: DurableChatClient;
@@ -1 +1 @@
1
- {"version":3,"file":"durable-chat.d.ts","names":[],"sources":["../src/durable-chat.ts"],"mappings":";;;;;;;;qBAuBa,yBAAyB;WAIzB;WAHF;EAGE,YAAA,2BACT;;;YAiBQ,oBAAoB,KAC9B;;;;;YAQU;;WAED;;EAET,SAAS,eAAe;EACxB,OAAO,iBAAiB;EACxB,MAAM,iBAAiB;EACvB,YAAY,qBAAqB,QAAQ,kBAAkB,iBAAiB;;YAGlE;EACV,QAAQ;EACR;EACA;;EAEA;;EAEA;;YAGU,uBAAuB,gBAAgB;WACxC,YAAY;;;;;;;;;;wBAkBP,2BACd,SAAS,oCACR"}
1
+ {"version":3,"file":"durable-chat.d.ts","names":[],"sources":["../src/durable-chat.ts"],"mappings":";;;;;;;;qBA2Ba,yBAAyB;WAIzB;WAHF;EAGE,YAAA,2BACT;;;YAiBQ,oBAAoB,KAC9B,iHAIA,QAAQ,KAAK;;;;;YAMH;;WAED;;EAET,SAAS,eAAe;EACxB,OAAO,iBAAiB;EACxB,MAAM,iBAAiB;EACvB,YAAY,qBAAqB,QAAQ,kBAAkB,iBAAiB;;EAE5E,mBACE,sBACA,qCACA,iBACC;;YAGO;EACV,QAAQ;EACR;EACA;;EAEA;;EAEA;;YAGU,uBAAuB,gBAAgB;WACxC,YAAY;;;;;;;;;;wBAkBP,2BACd,SAAS,oCACR"}
@@ -15,29 +15,45 @@ function createDurableChatMapState(sequence = 0) {
15
15
  * Map one durable event. Events at or before the applied cursor produce nothing, so a reconnect
16
16
  * that overlaps the stored sequence does not double-apply.
17
17
  */
18
- function mapDurableChatEvent(event, state) {
18
+ function mapDurableChatEvent(event, state, settledOutcome) {
19
19
  if (!Number.isSafeInteger(event.sequence) || event.sequence <= state.sequence) return {
20
20
  events: [],
21
21
  state
22
22
  };
23
23
  const draft = fork(state, event.sequence);
24
24
  return {
25
- events: project(event, draft),
25
+ events: project(event, draft, settledOutcome),
26
26
  state: draft
27
27
  };
28
28
  }
29
29
  /**
30
+ * True when a status event needs the run's outcome, which the event itself no longer carries
31
+ * (DUR-07). The caller reads it from the run snapshot and passes it to `mapDurableChatEvent`.
32
+ * Journals written before the change still carry `data.outcome`, so nothing is fetched for them.
33
+ */
34
+ function needsSettledOutcome(event) {
35
+ if (event.type !== "status") return false;
36
+ const data = asRecord(event.data);
37
+ if (data === void 0 || data.outcome !== void 0) return false;
38
+ const status = text(data, "status");
39
+ return status === "completed" || status === "waiting" || status === "failed";
40
+ }
41
+ /** The status a status event reports, so a caller can check a snapshot is still at that point. */
42
+ function statusEventStatus(event) {
43
+ return event.type === "status" ? text(asRecord(event.data), "status") : void 0;
44
+ }
45
+ /**
30
46
  * One assistant message per model operation. Retries keep the identity and reset its parts, so a
31
47
  * streamed journal never leaves the empty placeholders that per-attempt ids would create.
32
48
  */
33
49
  function durableChatMessageId(runId, operationId) {
34
50
  return `${runId}:${operationId}`;
35
51
  }
36
- function project(event, state) {
52
+ function project(event, state, settledOutcome) {
37
53
  const data = asRecord(event.data);
38
54
  switch (event.type) {
39
55
  case "submitted": return openRun(event.runId, state);
40
- case "status": return mapStatus(event, data, state);
56
+ case "status": return mapStatus(event, data, state, settledOutcome);
41
57
  case "model_started": return mapModelStarted(event, data, state);
42
58
  case "model_attempt_started": return mapAttemptStarted(event, data, state);
43
59
  case "model_delta": return mapModelDelta(event, data, state);
@@ -56,15 +72,16 @@ function project(event, state) {
56
72
  default: return [];
57
73
  }
58
74
  }
59
- function mapStatus(event, data, state) {
75
+ function mapStatus(event, data, state, settledOutcome) {
60
76
  const status = text(data, "status");
77
+ const outcome = asRecord(data?.outcome) ?? settledOutcome;
61
78
  if (status === "needs_attention") return needsAttention(event, data);
62
- if (status === "failed") return failed(event, data);
79
+ if (status === "failed") return failed(event, data, outcome);
63
80
  if (status === "cancelled") return [located(event, {
64
81
  type: "run_end",
65
82
  status: "cancelled"
66
83
  })];
67
- if (status === "waiting" || status === "completed") return settled(event, data, status);
84
+ if (status === "waiting" || status === "completed") return settled(event, outcome, status);
68
85
  if (!state.runOpened && (status === "queued" || status === "pending" || status === "running")) return openRun(event.runId, state);
69
86
  return [];
70
87
  }
@@ -375,8 +392,7 @@ function needsAttention(event, data) {
375
392
  status: "error"
376
393
  })];
377
394
  }
378
- function failed(event, data) {
379
- const outcome = asRecord(data?.outcome);
395
+ function failed(event, data, outcome) {
380
396
  const error = located(event, {
381
397
  type: "error",
382
398
  error: {
@@ -390,8 +406,7 @@ function failed(event, data) {
390
406
  if (usage !== void 0 && error.type === "error") error.usage = usage;
391
407
  return [error, runEnd(event, outcome, "error")];
392
408
  }
393
- function settled(event, data, status) {
394
- const outcome = asRecord(data?.outcome);
409
+ function settled(event, outcome, status) {
395
410
  const outcomeType = text(outcome, "type");
396
411
  if (status === "waiting" || outcomeType === "interaction") {
397
412
  const interaction = asInteraction(outcome?.interaction);
@@ -802,6 +817,11 @@ function createDurableChatTransport(options) {
802
817
  },
803
818
  resolveTool(operationId, output, runId) {
804
819
  return options.client.resolveTool(resolveRun(session, runId), operationId, output);
820
+ },
821
+ resolveMemoryWrite(operationKey, resolution, runId) {
822
+ const resolve = options.client.resolveMemoryWrite;
823
+ if (resolve === void 0) return Promise.reject(/* @__PURE__ */ new TypeError("The durable client does not support resolveMemoryWrite."));
824
+ return resolve.call(options.client, resolveRun(session, runId), operationKey, resolution);
805
825
  }
806
826
  },
807
827
  async *send(send) {
@@ -868,7 +888,8 @@ async function* streamFrames(client, session, runId, abortSignal) {
868
888
  };
869
889
  try {
870
890
  for await (const event of client.stream(runId, streamOptions)) {
871
- const mapped = mapDurableChatEvent(event, session.map);
891
+ const settled = needsSettledOutcome(event) ? await snapshotOutcome(client, runId, event, abortSignal) : void 0;
892
+ const mapped = mapDurableChatEvent(event, session.map, settled);
872
893
  session.map = mapped.state;
873
894
  session.cursor = mapped.state.sequence;
874
895
  lastEventId = mapped.state.sequence;
@@ -895,6 +916,17 @@ async function* streamFrames(client, session, runId, abortSignal) {
895
916
  status: "completed"
896
917
  };
897
918
  }
919
+ /**
920
+ * The outcome for a settled status event, read from the run snapshot (DUR-07 keeps it out of the
921
+ * event). If the run has moved past that status, the snapshot describes a later point, so nothing
922
+ * is returned and the event maps without its outcome.
923
+ */
924
+ async function snapshotOutcome(client, runId, event, abortSignal) {
925
+ const snapshot = await client.snapshot(runId, abortSignal === void 0 ? {} : { abortSignal });
926
+ if (snapshot.run.status !== statusEventStatus(event)) return void 0;
927
+ const outcome = snapshot.run.outcome;
928
+ return typeof outcome === "object" && outcome !== null && !Array.isArray(outcome) && isJsonValue(outcome) ? outcome : void 0;
929
+ }
898
930
  function lastUserPrompt(messages) {
899
931
  for (let index = messages.length - 1; index >= 0; index -= 1) {
900
932
  const message = messages[index];
@@ -1 +1 @@
1
- {"version":3,"file":"durable-chat.js","names":[],"sources":["../src/durable-chat-map.ts","../src/durable-chat.ts"],"sourcesContent":["import type { AgentInteractionRequest } from \"@anvia/core/agent/interactions\";\nimport type {\n AssistantContentPart,\n ContextUsage,\n JsonObject,\n JsonValue,\n ProviderToolCall,\n ReasoningContentType,\n ReasoningDetail,\n ToolCallPart,\n ToolResultContentPart,\n ToolResultOutput,\n Usage,\n} from \"@anvia/core/completion\";\nimport { isJsonValue } from \"@anvia/core/completion\";\nimport type { CompletionSource } from \"@anvia/core/completion\";\nimport type { MemoryCompactionInfo } from \"@anvia/core/memory\";\nimport type { DurableEvent } from \"@anvia/durable/protocol\";\nimport type { ClientStreamEvent } from \"./types\";\n\n/**\n * Pure projection from durable journal events to `anvia.client.v3` stream events.\n *\n * Durable `sequence` values are a global autoincrement across every run in the store, so they\n * are not contiguous inside one chat stream. `validateFrameSequence` (client-transport.ts)\n * requires each `eventId` to be exactly `last + 1` and would reject a replay, a resume cursor,\n * or any stream that shares the database with other runs. This mapper therefore uses the durable\n * sequence itself as the event id, which is also the cursor `stream({ after })` expects. Callers\n * must not wrap the resulting frames in the standard contiguous frame validator.\n *\n * Message ids are one per model operation (`${runId}:${operationId}`); part ids add a suffix.\n * Replaying the same journal on reconnect assigns the same identities.\n */\nexport type DurableChatMapState = {\n /** Assistant message open for the model operation currently streaming. */\n messageId?: string | undefined;\n /** Last durable sequence applied. The next resume starts after this cursor. */\n sequence: number;\n /** Model operations that already opened a message, so a later attempt resets it. */\n openedOperations: Set<string>;\n /** Parts that already emitted their `*_start`, so a replay of one event does not repeat it. */\n openedParts: Set<string>;\n /** Tool calls seen on `tool_started`, keyed by operation id, so `tool_completed` can match them. */\n tools: Map<string, ToolCallPart>;\n /** True once `run_start` has been emitted for this projection. */\n runOpened: boolean;\n};\n\n/** `Omit` over a union collapses to common keys; this distributes over every event variant. */\ntype WithoutRunId<T> = T extends unknown ? Omit<T, \"runId\"> : never;\n\nexport function createDurableChatMapState(sequence = 0): DurableChatMapState {\n return {\n sequence,\n openedOperations: new Set(),\n openedParts: new Set(),\n tools: new Map(),\n runOpened: false,\n };\n}\n\nexport type DurableChatMapped = {\n events: readonly ClientStreamEvent[];\n state: DurableChatMapState;\n};\n\n/**\n * Map one durable event. Events at or before the applied cursor produce nothing, so a reconnect\n * that overlaps the stored sequence does not double-apply.\n */\nexport function mapDurableChatEvent(\n event: DurableEvent,\n state: DurableChatMapState,\n): DurableChatMapped {\n if (!Number.isSafeInteger(event.sequence) || event.sequence <= state.sequence) {\n return { events: [], state };\n }\n const draft = fork(state, event.sequence);\n const events = project(event, draft);\n return { events, state: draft };\n}\n\n/**\n * One assistant message per model operation. Retries keep the identity and reset its parts, so a\n * streamed journal never leaves the empty placeholders that per-attempt ids would create.\n */\nexport function durableChatMessageId(runId: string, operationId: string): string {\n return `${runId}:${operationId}`;\n}\n\nfunction project(event: DurableEvent, state: DurableChatMapState): ClientStreamEvent[] {\n const data = asRecord(event.data);\n switch (event.type) {\n case \"submitted\":\n return openRun(event.runId, state);\n case \"status\":\n return mapStatus(event, data, state);\n case \"model_started\":\n return mapModelStarted(event, data, state);\n case \"model_attempt_started\":\n return mapAttemptStarted(event, data, state);\n case \"model_delta\":\n return mapModelDelta(event, data, state);\n case \"model_attempt_failed\":\n return mapAttemptFailed(event, data, state);\n case \"model_completed\":\n return mapModelCompleted(event, data, state);\n case \"tool_started\":\n return mapToolStarted(event, data, state);\n case \"tool_completed\":\n return mapToolCompleted(event, data, state);\n case \"compaction_completed\":\n return mapCompaction(event, data);\n case \"steering_queued\":\n case \"steering_applied\":\n return [\n located(event, { type: \"data\", name: event.type, data: data ?? {}, transient: true }),\n ];\n default:\n return [];\n }\n}\n\nfunction mapStatus(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const status = text(data, \"status\");\n if (status === \"needs_attention\") return needsAttention(event, data);\n if (status === \"failed\") return failed(event, data);\n if (status === \"cancelled\") return [located(event, { type: \"run_end\", status: \"cancelled\" })];\n if (status === \"waiting\" || status === \"completed\") return settled(event, data, status);\n // The first non-terminal status stands in for `submitted` when a replay starts mid-journal.\n if (!state.runOpened && (status === \"queued\" || status === \"pending\" || status === \"running\")) {\n return openRun(event.runId, state);\n }\n return [];\n}\n\nfunction openRun(runId: string, state: DurableChatMapState): ClientStreamEvent[] {\n state.runOpened = true;\n // The first model operation opens the assistant message; opening one here would leave an\n // empty message ahead of the real one on every turn.\n return [{ type: \"run_start\", source: \"agent\", runId }];\n}\n\nfunction mapModelStarted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\") ?? \"model\";\n const messageId = durableChatMessageId(event.runId, operationId);\n state.openedOperations.add(operationId);\n state.messageId = messageId;\n const generation: ClientStreamEvent = { type: \"generation_start\", runId: event.runId };\n const model = modelOf(data);\n if (model !== undefined) generation.model = model;\n // `run_start` belongs to submitted / the first status. Repeat it only when this event is the\n // first one the projection has seen, so a normal journal does not open the run twice.\n const events: ClientStreamEvent[] = [];\n if (!state.runOpened) events.push({ type: \"run_start\", source: \"agent\", runId: event.runId });\n state.runOpened = true;\n events.push({ type: \"turn_start\", runId: event.runId }, generation, {\n type: \"message_start\",\n messageId,\n role: \"assistant\",\n runId: event.runId,\n });\n return events;\n}\n\nfunction mapAttemptStarted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\");\n if (operationId === undefined) return [];\n const attempt = number(data, \"attempt\");\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n const opened = state.openedOperations.has(operationId);\n const retried = opened && (attempt === undefined || attempt > 1);\n const events: ClientStreamEvent[] = [];\n if (retried && state.messageId !== undefined) {\n // Discard the partial attempt but keep the message identity the reducer already holds.\n events.push({ type: \"message_reset\", messageId: state.messageId, runId: event.runId });\n } else if (!opened) {\n // A replay can start at the attempt rather than at `model_started`.\n events.push({ type: \"message_start\", messageId, role: \"assistant\", runId: event.runId });\n }\n state.openedOperations.add(operationId);\n state.messageId = messageId;\n return events;\n}\n\nfunction mapModelDelta(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const nested = asRecord(data?.event);\n const kind = text(nested, \"type\");\n if (nested === undefined || kind === undefined) return [];\n const operationId = text(data, \"operationId\") ?? \"model\";\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n state.messageId = messageId;\n const turn = number(nested, \"turn\");\n\n if (kind === \"text_delta\") {\n const delta = text(nested, \"delta\");\n if (delta === undefined) return [];\n return withStart(state, messageId, \"text\", undefined, event.runId, turn, (partId, started) => {\n const events: ClientStreamEvent[] = [];\n if (!started) events.push(part(event.runId, turn, { type: \"text_start\", messageId, partId }));\n events.push(part(event.runId, turn, { type: \"text_delta\", messageId, partId, delta }));\n return events;\n });\n }\n\n if (kind === \"reasoning_delta\") {\n const delta = text(nested, \"delta\");\n if (delta === undefined) return [];\n const reasoningId = text(nested, \"id\");\n return withStart(\n state,\n messageId,\n \"reasoning\",\n reasoningId ?? \"default\",\n event.runId,\n turn,\n (partId, started) => {\n const events: ClientStreamEvent[] = [];\n if (!started) {\n const start = part(event.runId, turn, { type: \"reasoning_start\", messageId, partId });\n if (reasoningId !== undefined && start.type === \"reasoning_start\") {\n start.reasoningId = reasoningId;\n }\n events.push(start);\n }\n const deltaEvent = part(event.runId, turn, {\n type: \"reasoning_delta\",\n messageId,\n partId,\n delta,\n });\n const contentType = reasoningType(text(nested, \"contentType\"));\n const signature = text(nested, \"signature\");\n if (deltaEvent.type === \"reasoning_delta\") {\n if (contentType !== undefined) deltaEvent.contentType = contentType;\n if (signature !== undefined) deltaEvent.signature = signature;\n }\n events.push(deltaEvent);\n return events;\n },\n );\n }\n\n if (kind === \"tool_call_delta\") {\n const toolCallId = text(nested, \"id\");\n if (toolCallId === undefined) return [];\n return withStart(state, messageId, \"tool\", toolCallId, event.runId, turn, (partId, started) => {\n const events: ClientStreamEvent[] = [];\n const callId = text(nested, \"callId\");\n const toolName = text(nested, \"name\");\n if (!started) {\n const start = part(event.runId, turn, {\n type: \"tool_call_start\",\n messageId,\n partId,\n toolCallId,\n });\n if (start.type === \"tool_call_start\") {\n if (callId !== undefined) start.callId = callId;\n if (toolName !== undefined) start.toolName = toolName;\n }\n events.push(start);\n }\n const delta = text(nested, \"argumentsDelta\");\n if (delta === undefined) return events;\n const tool = part(event.runId, turn, {\n type: \"tool_call_delta\",\n messageId,\n partId,\n toolCallId,\n delta,\n mode: nested.argumentsMode === \"replace\" ? \"replace\" : \"append\",\n });\n if (tool.type === \"tool_call_delta\") {\n if (callId !== undefined) tool.callId = callId;\n if (toolName !== undefined) tool.toolName = toolName;\n const signature = text(nested, \"signature\");\n if (signature !== undefined) tool.signature = signature;\n }\n events.push(tool);\n return events;\n });\n }\n\n if (kind === \"tool_call\") {\n const call = asToolCall(nested.toolCall);\n return call === undefined ? [] : [toolCallEnd(event.runId, messageId, call, turn)];\n }\n if (kind === \"source\") {\n const source = asSource(nested.source);\n if (source === undefined) return [];\n return [\n part(event.runId, turn, {\n type: \"source\",\n messageId,\n partId: partId(messageId, \"source\", JSON.stringify(source)),\n source,\n }),\n ];\n }\n if (kind === \"provider_tool_call\") {\n const toolCall = asProviderToolCall(nested.toolCall);\n return toolCall === undefined\n ? []\n : [part(event.runId, turn, { type: \"provider_tool_call\", toolCall })];\n }\n return [];\n}\n\nfunction mapAttemptFailed(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n // A failed attempt is not a failed run: `retry_wait` may follow. Emit a transient data\n // event instead of `error`, which would leave `useChat` in a sticky error state even when\n // the next attempt succeeds. The next `message_reset` clears the partial attempt.\n const attemptId = text(data, \"attemptId\");\n return [\n located(event, {\n type: \"data\",\n name: \"durable_model_attempt_failed\",\n data: {\n operationId: text(data, \"operationId\") ?? null,\n attemptId: attemptId ?? null,\n messageId: state.messageId ?? null,\n error: text(data, \"error\") ?? \"Durable model attempt failed.\",\n },\n transient: true,\n }),\n ];\n}\n\nfunction mapModelCompleted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\") ?? \"model\";\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n state.messageId = messageId;\n const result = asRecord(data?.result);\n const choice = assistantParts(result?.choice);\n const events: ClientStreamEvent[] = [];\n const texts = choice.filter((part) => part.type === \"text\");\n const textJoined = texts.map((part) => part.text).join(\"\");\n const textPartId = partId(messageId, \"text\");\n if (textJoined.length > 0 || state.openedParts.has(textPartId)) {\n if (!state.openedParts.has(textPartId)) {\n state.openedParts.add(textPartId);\n events.push({ type: \"text_start\", messageId, partId: textPartId, runId: event.runId });\n }\n const end: ClientStreamEvent = {\n type: \"text_end\",\n messageId,\n partId: textPartId,\n text: textJoined,\n runId: event.runId,\n };\n const signature = texts.length === 1 ? texts[0]?.signature : undefined;\n if (signature !== undefined && end.type === \"text_end\") end.signature = signature;\n events.push(end);\n }\n for (const content of choice) {\n if (content.type === \"reasoning\")\n events.push(reasoningEnd(event.runId, messageId, content, state));\n if (content.type === \"tool-call\") events.push(toolCallEnd(event.runId, messageId, content));\n }\n const messageEnd: ClientStreamEvent = { type: \"message_end\", messageId, runId: event.runId };\n const usage = asUsage(result?.usage);\n const contextUsage = asContextUsage(result?.contextUsage);\n if (usage !== undefined && messageEnd.type === \"message_end\") messageEnd.usage = usage;\n if (contextUsage !== undefined && messageEnd.type === \"message_end\") {\n messageEnd.contextUsage = contextUsage;\n }\n if (typeof result?.messageId === \"string\" && messageEnd.type === \"message_end\") {\n messageEnd.modelMessageId = result.messageId;\n }\n events.push(messageEnd);\n return events;\n}\n\nfunction mapToolStarted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\");\n const call = asToolCall(asRecord(data?.input)?.toolCall);\n if (operationId === undefined || call === undefined) return [];\n state.tools.set(operationId, call);\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n return [toolCallEnd(event.runId, messageId, call)];\n}\n\nfunction mapToolCompleted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\");\n // `tool_completed` carries only the result; the call was recorded by `tool_started`.\n const call = operationId === undefined ? undefined : state.tools.get(operationId);\n const saved = asRecord(data?.result);\n const output = asToolOutput(saved?.output);\n if (output === undefined) return [];\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId ?? \"tools\");\n const toolCallId = call?.toolCallId ?? operationId ?? \"tool\";\n const failed = saved?.failed === true;\n const result: ClientStreamEvent = {\n type: \"tool_result\",\n messageId,\n partId: partId(messageId, \"tool\", toolCallId),\n toolCallId,\n toolName: call?.toolName ?? \"tool\",\n input: call?.input ?? null,\n runId: event.runId,\n result: failed\n ? {\n status: \"error\",\n error: { message: text(saved, \"error\") ?? \"Tool failed.\", retryable: false },\n }\n : { status: \"success\", output: toolOutputValue(output) },\n };\n if (call?.callId !== undefined && result.type === \"tool_result\") result.callId = call.callId;\n return [result];\n}\n\nfunction mapCompaction(event: DurableEvent, data: JsonObject | undefined): ClientStreamEvent[] {\n const info = asCompaction(data);\n return info === undefined ? [] : [located(event, { type: \"memory_compaction\", ...info })];\n}\n\nfunction needsAttention(event: DurableEvent, data: JsonObject | undefined): ClientStreamEvent[] {\n const operationId = text(data, \"blockedOperation\");\n const details: JsonObject = { retryable: true };\n if (operationId !== undefined) details.operationId = operationId;\n return [\n located(event, {\n type: \"error\",\n error: {\n name: \"DurableNeedsAttention\",\n message: text(data, \"error\") ?? \"Durable run needs attention.\",\n code: \"needs_attention\",\n retryable: true,\n details,\n },\n }),\n located(event, { type: \"run_end\", status: \"error\" }),\n ];\n}\n\nfunction failed(event: DurableEvent, data: JsonObject | undefined): ClientStreamEvent[] {\n const outcome = asRecord(data?.outcome);\n const error = located(event, {\n type: \"error\",\n error: {\n name: \"DurableRunError\",\n message: text(data, \"error\") ?? \"Durable run failed.\",\n code: \"failed\",\n retryable: false,\n },\n });\n const usage = asUsage(outcome?.usage);\n if (usage !== undefined && error.type === \"error\") error.usage = usage;\n return [error, runEnd(event, outcome, \"error\")];\n}\n\nfunction settled(\n event: DurableEvent,\n data: JsonObject | undefined,\n status: \"waiting\" | \"completed\",\n): ClientStreamEvent[] {\n const outcome = asRecord(data?.outcome);\n const outcomeType = text(outcome, \"type\");\n if (status === \"waiting\" || outcomeType === \"interaction\") {\n const interaction = asInteraction(outcome?.interaction);\n const events: ClientStreamEvent[] = [];\n if (interaction !== undefined)\n events.push(located(event, { type: \"interaction\", interaction }));\n events.push(runEnd(event, outcome, \"suspended\"));\n return events;\n }\n if (outcomeType === \"blocked\") return [runEnd(event, outcome, \"blocked\")];\n return [runEnd(event, outcome, \"completed\")];\n}\n\nfunction runEnd(\n event: DurableEvent,\n outcome: JsonObject | undefined,\n status: \"completed\" | \"blocked\" | \"suspended\" | \"error\",\n): ClientStreamEvent {\n const end = located(event, { type: \"run_end\", status });\n if (end.type !== \"run_end\") return end;\n const value = text(outcome, \"text\");\n const usage = asUsage(outcome?.usage);\n const contextUsage = asContextUsage(outcome?.contextUsage);\n const trace = asTrace(outcome?.trace);\n const compaction = asCompaction(asRecord(outcome?.memoryCompaction));\n if (value !== undefined) end.text = value;\n if (outcome?.output !== undefined && isJsonValue(outcome.output)) end.output = outcome.output;\n if (usage !== undefined) end.usage = usage;\n if (contextUsage !== undefined) end.contextUsage = contextUsage;\n if (trace !== undefined) end.trace = trace;\n if (compaction !== undefined) end.memoryCompaction = compaction;\n return end;\n}\n\nfunction reasoningEnd(\n runId: string,\n messageId: string,\n content: Extract<AssistantContentPart, { type: \"reasoning\" }>,\n state: DurableChatMapState,\n): ClientStreamEvent {\n const id = partId(messageId, \"reasoning\", content.id ?? \"default\");\n const end: ClientStreamEvent = {\n type: \"reasoning_end\",\n messageId,\n partId: id,\n text: content.text,\n runId,\n };\n if (!state.openedParts.has(id)) state.openedParts.add(id);\n if (content.details !== undefined && end.type === \"reasoning_end\") end.content = content.details;\n return end;\n}\n\nfunction toolCallEnd(\n runId: string,\n messageId: string,\n call: ToolCallPart,\n turn?: number,\n): ClientStreamEvent {\n const event = part(runId, turn, {\n type: \"tool_call_end\",\n messageId,\n partId: partId(messageId, \"tool\", call.toolCallId),\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n input: call.input,\n });\n if (event.type !== \"tool_call_end\") return event;\n if (call.callId !== undefined) event.callId = call.callId;\n if (call.signature !== undefined) event.signature = call.signature;\n return event;\n}\n\nfunction withStart(\n state: DurableChatMapState,\n messageId: string,\n kind: string,\n suffix: string | undefined,\n runId: string,\n turn: number | undefined,\n build: (partId: string, started: boolean) => ClientStreamEvent[],\n): ClientStreamEvent[] {\n void runId;\n void turn;\n const id = partId(messageId, kind, suffix);\n const started = state.openedParts.has(id);\n if (!started) state.openedParts.add(id);\n return build(id, started);\n}\n\nfunction part(\n runId: string,\n turn: number | undefined,\n event: WithoutRunId<ClientStreamEvent>,\n): ClientStreamEvent {\n const locatedEvent = { ...event, runId } as ClientStreamEvent;\n if (turn !== undefined && \"turn\" in locatedEvent) locatedEvent.turn = turn;\n else if (turn !== undefined) return { ...locatedEvent, turn };\n return locatedEvent;\n}\n\nfunction located(event: DurableEvent, fields: WithoutRunId<ClientStreamEvent>): ClientStreamEvent {\n return { ...fields, runId: event.runId } as ClientStreamEvent;\n}\n\nfunction fork(state: DurableChatMapState, sequence: number): DurableChatMapState {\n return {\n messageId: state.messageId,\n sequence,\n openedOperations: new Set(state.openedOperations),\n openedParts: new Set(state.openedParts),\n tools: new Map(state.tools),\n runOpened: state.runOpened,\n };\n}\n\nfunction partId(messageId: string, kind: string, suffix?: string): string {\n return suffix === undefined ? `${messageId}:${kind}` : `${messageId}:${kind}:${suffix}`;\n}\n\nfunction asRecord(value: unknown): JsonObject | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value) || !isJsonValue(value)) {\n return undefined;\n }\n return value as JsonObject;\n}\n\nfunction text(value: JsonObject | undefined, key: string): string | undefined {\n const field = value?.[key];\n return typeof field === \"string\" ? field : undefined;\n}\n\nfunction number(value: JsonObject | undefined, key: string): number | undefined {\n const field = value?.[key];\n return typeof field === \"number\" && Number.isFinite(field) ? field : undefined;\n}\n\nfunction modelOf(data: JsonObject | undefined): { provider: string; modelId: string } | undefined {\n const input = asRecord(data?.input);\n const provider = text(input, \"provider\");\n const modelId = text(input, \"modelId\");\n return provider === undefined || modelId === undefined ? undefined : { provider, modelId };\n}\n\nconst REASONING: readonly ReasoningContentType[] = [\"text\", \"summary\", \"encrypted\", \"redacted\"];\n\nfunction reasoningType(value: string | undefined): ReasoningContentType | undefined {\n return REASONING.find((type) => type === value);\n}\n\nfunction asToolCall(value: unknown): ToolCallPart | undefined {\n const call = asRecord(value);\n if (call?.type !== \"tool-call\") return undefined;\n const toolCallId = text(call, \"toolCallId\");\n const toolName = text(call, \"toolName\");\n if (toolCallId === undefined || toolName === undefined || !isJsonValue(call.input))\n return undefined;\n const parsed: ToolCallPart = { type: \"tool-call\", toolCallId, toolName, input: call.input };\n const callId = text(call, \"callId\");\n const signature = text(call, \"signature\");\n if (callId === undefined) {\n return signature === undefined ? parsed : { ...parsed, signature };\n }\n if (signature === undefined) return { ...parsed, callId };\n return { ...parsed, callId, signature };\n}\n\nfunction asSource(value: unknown): CompletionSource | undefined {\n return asRecord(value) as CompletionSource | undefined;\n}\n\nfunction asProviderToolCall(value: unknown): ProviderToolCall | undefined {\n const call = asRecord(value);\n return call === undefined ? undefined : (call as ProviderToolCall);\n}\n\nfunction assistantParts(value: unknown): AssistantContentPart[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((item) => {\n const part = assistantPart(item);\n return part === undefined ? [] : [part];\n });\n}\n\nfunction assistantPart(value: unknown): AssistantContentPart | undefined {\n const part = asRecord(value);\n const type = text(part, \"type\");\n if (part === undefined || type === undefined) return undefined;\n if (type === \"text\" && typeof part.text === \"string\") {\n return typeof part.signature === \"string\"\n ? { type: \"text\", text: part.text, signature: part.signature }\n : { type: \"text\", text: part.text };\n }\n if (type === \"reasoning\" && typeof part.text === \"string\") {\n const details = asReasoningDetails(part.details);\n const base = { type: \"reasoning\" as const, text: part.text };\n if (typeof part.id !== \"string\") return details === undefined ? base : { ...base, details };\n return details === undefined ? { ...base, id: part.id } : { ...base, id: part.id, details };\n }\n if (type === \"tool-call\") return asToolCall(part);\n return undefined;\n}\n\nfunction asReasoningDetails(value: unknown): readonly ReasoningDetail[] | undefined {\n if (!Array.isArray(value) || !isJsonValue(value)) return undefined;\n return value as readonly ReasoningDetail[];\n}\n\nfunction asUsage(value: unknown): Usage | undefined {\n const usage = asRecord(value);\n if (usage === undefined) return undefined;\n const keys = [\n \"inputTokens\",\n \"outputTokens\",\n \"totalTokens\",\n \"cachedInputTokens\",\n \"cacheCreationInputTokens\",\n ] as const;\n const counts: Partial<Usage> = {};\n for (const key of keys) {\n const count = number(usage, key);\n if (count === undefined) return undefined;\n counts[key] = count;\n }\n const parsed = counts as Usage;\n const details = asRecord(usage.details);\n if (details !== undefined && Object.values(details).every((item) => typeof item === \"number\")) {\n parsed.details = details as Record<string, number>;\n }\n return parsed;\n}\n\nfunction asContextUsage(value: unknown): ContextUsage | undefined {\n const usage = asRecord(value);\n const model = asRecord(usage?.model);\n const context = asRecord(model?.context);\n if (usage === undefined || typeof model?.modelId !== \"string\" || context === undefined)\n return undefined;\n const contextWindow = number(context, \"contextWindow\");\n const usedTokens = number(usage, \"usedTokens\");\n const remainingTokens = number(usage, \"remainingTokens\");\n const usedPercent = number(usage, \"usedPercent\");\n const remainingPercent = number(usage, \"remainingPercent\");\n if (\n contextWindow === undefined ||\n usedTokens === undefined ||\n remainingTokens === undefined ||\n usedPercent === undefined ||\n remainingPercent === undefined\n ) {\n return undefined;\n }\n const parsed: ContextUsage = {\n model: { modelId: model.modelId, context: { contextWindow } },\n usedTokens,\n remainingTokens,\n usedPercent,\n remainingPercent,\n };\n const maxInputTokens = number(context, \"maxInputTokens\");\n const maxOutputTokens = number(context, \"maxOutputTokens\");\n if (maxInputTokens !== undefined) parsed.model.context.maxInputTokens = maxInputTokens;\n if (maxOutputTokens !== undefined) parsed.model.context.maxOutputTokens = maxOutputTokens;\n return parsed;\n}\n\nfunction asTrace(\n value: unknown,\n): { observer: string; traceId?: string; observationId?: string } | undefined {\n const trace = asRecord(value);\n const observer = text(trace, \"observer\");\n if (observer === undefined) return undefined;\n const parsed: { observer: string; traceId?: string; observationId?: string } = { observer };\n const traceId = text(trace, \"traceId\");\n const observationId = text(trace, \"observationId\");\n if (traceId !== undefined) parsed.traceId = traceId;\n if (observationId !== undefined) parsed.observationId = observationId;\n return parsed;\n}\n\nfunction asCompaction(value: JsonObject | undefined): MemoryCompactionInfo | undefined {\n if (value === undefined) return undefined;\n const keys = [\n \"originalMessageCount\",\n \"compactedMessageCount\",\n \"retainedMessageCount\",\n \"originalTokenCount\",\n \"compactedTokenCount\",\n \"retainedTokenCount\",\n \"resultTokenCount\",\n \"attempts\",\n ] as const;\n const info: Partial<Record<(typeof keys)[number], number>> = {};\n for (const key of keys) {\n const count = number(value, key);\n if (count === undefined) return undefined;\n info[key] = count;\n }\n const usage = asUsage(value.usage);\n if (usage === undefined) return undefined;\n return { ...(info as Omit<MemoryCompactionInfo, \"usage\">), usage };\n}\n\nfunction asInteraction(value: unknown): AgentInteractionRequest | undefined {\n const request = asRecord(value);\n const type = text(request, \"type\");\n const id = text(request, \"id\");\n const toolName = text(request, \"toolName\");\n const toolCallId = text(request, \"toolCallId\");\n const internalCallId = text(request, \"internalCallId\");\n if (\n request === undefined ||\n id === undefined ||\n toolName === undefined ||\n toolCallId === undefined ||\n internalCallId === undefined\n ) {\n return undefined;\n }\n const callId = text(request, \"callId\");\n const base: {\n id: string;\n toolName: string;\n toolCallId: string;\n internalCallId: string;\n callId?: string;\n } = { id, toolName, toolCallId, internalCallId };\n if (callId !== undefined) base.callId = callId;\n if (type === \"tool-approval\" && isJsonValue(request.input)) {\n const approval = { ...base, type: \"tool-approval\" as const, input: request.input };\n const reason = text(request, \"reason\");\n return reason === undefined ? approval : { ...approval, reason };\n }\n if (\n type === \"tool-question\" &&\n Array.isArray(request.questions) &&\n isJsonValue(request.questions)\n ) {\n return {\n ...base,\n type,\n questions: request.questions as Extract<\n AgentInteractionRequest,\n { type: \"tool-question\" }\n >[\"questions\"],\n };\n }\n return undefined;\n}\n\nfunction asToolOutput(value: unknown): ToolResultOutput | undefined {\n const output = asRecord(value);\n const type = text(output, \"type\");\n if (output === undefined || type === undefined) return undefined;\n if ((type === \"text\" || type === \"error-text\") && typeof output.value === \"string\") {\n return { type, value: output.value };\n }\n if ((type === \"json\" || type === \"error-json\") && isJsonValue(output.value)) {\n return { type, value: output.value };\n }\n if (type === \"execution-denied\") {\n const reason = text(output, \"reason\");\n return reason === undefined ? { type } : { type, reason };\n }\n if (type === \"content\" && Array.isArray(output.value) && isJsonValue(output.value)) {\n return { type, value: output.value as readonly ToolResultContentPart[] };\n }\n return undefined;\n}\n\nfunction toolOutputValue(output: ToolResultOutput): JsonValue {\n if (output.type === \"execution-denied\") {\n return output.reason === undefined\n ? { type: output.type }\n : { type: output.type, reason: output.reason };\n }\n return output.value as JsonValue;\n}\n","import type { AgentPrompt } from \"@anvia/core/agent\";\nimport type { Message, ToolResultOutput } from \"@anvia/core/completion\";\nimport { DurableHttpError, type DurableClient } from \"./durable\";\nimport {\n createDurableChatMapState,\n mapDurableChatEvent,\n type DurableChatMapState,\n} from \"./durable-chat-map\";\nimport { createClientId } from \"./messages\";\nimport {\n CLIENT_STREAM_PROTOCOL,\n type ClientStreamCursor,\n type ClientStreamFrame,\n type ClientStreamRequest,\n type ClientTransport,\n type ClientTransportSendOptions,\n} from \"./types\";\n\n/**\n * Thrown when a submission is rejected because the session already has unfinished work (HTTP 409).\n * `runId` is that run when it could be read back from the session; `undefined` when the lookup\n * failed. Reattach to `runId` instead of submitting again. Aborting a stream never raises this.\n */\nexport class DurableBusyError extends Error {\n readonly code = \"session_busy\" as const;\n\n constructor(\n readonly runId: string | undefined,\n message = \"Session already has unfinished work.\",\n ) {\n super(message);\n this.name = \"DurableBusyError\";\n }\n}\n\nconst UNFINISHED = new Set([\n \"queued\",\n \"retry_wait\",\n \"pending\",\n \"running\",\n \"waiting\",\n \"needs_attention\",\n]);\n\n/** Methods the adapter needs. A structural subset of `DurableClient`, so tests can fake it. */\nexport type DurableChatClient = Pick<\n DurableClient,\n \"submit\" | \"stream\" | \"respond\" | \"resolveTool\" | \"retry\" | \"cancel\" | \"listRuns\"\n>;\n\n/**\n * Run controls that `useChat` does not expose. `stop()` only aborts the subscription; cancellation\n * is always this explicit `cancel()`.\n */\nexport type DurableChatController = {\n /** Run last submitted or reattached. Undefined before the first successful send. */\n readonly activeRunId: string | undefined;\n /** Point later interaction responses and `send({ resume })` at an existing run. */\n reattach(runId: string, after?: number): void;\n cancel(runId?: string): Promise<void>;\n retry(runId?: string): Promise<void>;\n resolveTool(operationId: string, output: ToolResultOutput, runId?: string): Promise<void>;\n};\n\nexport type CreateDurableChatTransportOptions = {\n client: DurableChatClient;\n agentId: string;\n sessionId: string;\n /** Defaults to a UUID per submission. Return a stable id to deduplicate one prompt. */\n requestId?: () => string;\n /** Queue behind unfinished session work instead of failing. Defaults to true. */\n enqueue?: boolean;\n};\n\nexport type DurableChatTransport = ClientTransport<ClientStreamRequest> & {\n readonly controller: DurableChatController;\n};\n\ntype Session = {\n activeRunId?: string;\n /** Durable sequence last applied for `activeRunId`. Interaction responses resume after it. */\n cursor: number;\n map: DurableChatMapState;\n};\n\n/**\n * Transport `useChat` can pass to talk to `@anvia/durable`.\n *\n * Only the last user message of a `messages` request is submitted; durable keeps the transcript,\n * so the rest of the client history is discarded. An `interaction_response` is delivered to the\n * remembered run and then the stream resumes from the last applied sequence. Abort detaches the\n * SSE subscription and does not cancel the run.\n */\nexport function createDurableChatTransport(\n options: CreateDurableChatTransportOptions,\n): DurableChatTransport {\n const session: Session = { cursor: 0, map: createDurableChatMapState() };\n\n const controller: DurableChatController = {\n get activeRunId() {\n return session.activeRunId;\n },\n reattach(runId, after = 0) {\n assertCursor(after);\n session.activeRunId = requireId(runId, \"runId\");\n session.cursor = after;\n session.map = createDurableChatMapState(after);\n },\n cancel(runId) {\n return options.client.cancel(resolveRun(session, runId));\n },\n retry(runId) {\n return options.client.retry(resolveRun(session, runId));\n },\n resolveTool(operationId, output, runId) {\n return options.client.resolveTool(resolveRun(session, runId), operationId, output);\n },\n };\n\n return {\n controller,\n async *send(send) {\n const target = await begin(options, session, send);\n // A new run, or a resume behind the applied cursor, needs a fresh projection. Reusing the\n // run's existing projection keeps `run_start` and open messages from being emitted twice.\n if (session.activeRunId !== target.runId || target.after < session.cursor) {\n session.map = createDurableChatMapState(target.after);\n }\n session.activeRunId = target.runId;\n session.cursor = target.after;\n yield* streamFrames(options.client, session, target.runId, send.abortSignal);\n },\n };\n}\n\nasync function begin(\n options: CreateDurableChatTransportOptions,\n session: Session,\n send: ClientTransportSendOptions<ClientStreamRequest>,\n): Promise<{ runId: string; after: number }> {\n const resume = send.resume ?? send.request.resume;\n if (resume !== undefined) {\n assertCursor(resume.after);\n return { runId: requireId(resume.streamId, \"streamId\"), after: resume.after };\n }\n if (send.request.type === \"interaction_response\") {\n if (session.activeRunId === undefined) {\n throw new Error(\"No active durable run to receive the interaction response.\");\n }\n await options.client.respond(\n session.activeRunId,\n send.request.interactionId,\n send.request.response,\n send.abortSignal === undefined ? {} : { abortSignal: send.abortSignal },\n );\n return { runId: session.activeRunId, after: session.cursor };\n }\n const snapshot = await submitPrompt(options, send);\n return { runId: snapshot, after: 0 };\n}\n\nasync function submitPrompt(\n options: CreateDurableChatTransportOptions,\n send: ClientTransportSendOptions<ClientStreamRequest>,\n): Promise<string> {\n if (send.request.type !== \"messages\") {\n throw new TypeError(\"Unsupported durable chat request.\");\n }\n const prompt = lastUserPrompt(send.request.messages);\n const requestId = options.requestId?.() ?? createClientId(\"durable\");\n const requestOptions: { enqueue: boolean; abortSignal?: AbortSignal } = {\n enqueue: options.enqueue ?? true,\n };\n if (send.abortSignal !== undefined) requestOptions.abortSignal = send.abortSignal;\n try {\n const snapshot = await options.client.submit(\n { agentId: options.agentId, sessionId: options.sessionId, requestId, prompt },\n requestOptions,\n );\n return snapshot.run.id;\n } catch (error) {\n if (!isSessionBusy(error)) throw error;\n throw new DurableBusyError(await findBusyRun(options, send.abortSignal), error.message);\n }\n}\n\nasync function* streamFrames(\n client: DurableChatClient,\n session: Session,\n runId: string,\n abortSignal: AbortSignal | undefined,\n): AsyncIterable<ClientStreamFrame> {\n // The event id is the durable sequence, which is not contiguous per stream. See the note in\n // durable-chat-map.ts for why validateFrameSequence must not wrap this generator.\n yield {\n type: \"stream_start\",\n protocol: CLIENT_STREAM_PROTOCOL,\n streamId: runId,\n eventId: 0,\n resumable: true,\n };\n let lastEventId = session.cursor;\n const streamOptions =\n abortSignal === undefined ? { after: session.cursor } : { after: session.cursor, abortSignal };\n try {\n for await (const event of client.stream(runId, streamOptions)) {\n const mapped = mapDurableChatEvent(event, session.map);\n session.map = mapped.state;\n session.cursor = mapped.state.sequence;\n lastEventId = mapped.state.sequence;\n for (const clientEvent of mapped.events) {\n yield {\n type: \"stream_event\",\n streamId: runId,\n eventId: event.sequence,\n event: clientEvent,\n };\n }\n }\n } catch (error) {\n if (!isAbort(error, abortSignal)) {\n yield { type: \"stream_end\", streamId: runId, eventId: lastEventId, status: \"error\" };\n }\n throw error;\n }\n yield { type: \"stream_end\", streamId: runId, eventId: lastEventId, status: \"completed\" };\n}\n\nfunction lastUserPrompt(messages: readonly Message[]): AgentPrompt {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message?.role === \"user\") return message;\n }\n throw new TypeError(\"Durable chat requires a user message to submit.\");\n}\n\nfunction isSessionBusy(error: unknown): error is DurableHttpError {\n // A submit conflict means this session already has an unfinished run.\n return error instanceof DurableHttpError && error.status === 409;\n}\n\nasync function findBusyRun(\n options: CreateDurableChatTransportOptions,\n abortSignal: AbortSignal | undefined,\n): Promise<string | undefined> {\n try {\n const page = await options.client.listRuns(\n { sessionId: options.sessionId, limit: 100 },\n abortSignal === undefined ? {} : { abortSignal },\n );\n return page.runs.find((run) => UNFINISHED.has(run.status))?.id;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveRun(session: Session, runId: string | undefined): string {\n return requireId(runId ?? session.activeRunId, \"run\");\n}\n\nfunction requireId(value: string | undefined, label: string): string {\n if (value === undefined || value.trim().length === 0) {\n throw new Error(label === \"run\" ? \"No active durable run.\" : `${label} must not be empty.`);\n }\n return value;\n}\n\nfunction assertCursor(after: number): void {\n if (!Number.isSafeInteger(after) || after < 0)\n throw new TypeError(\"Invalid durable resume cursor.\");\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal | undefined): boolean {\n return signal?.aborted === true || (error instanceof Error && error.name === \"AbortError\");\n}\n\nexport type { ClientStreamCursor };\n"],"mappings":"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"}
1
+ {"version":3,"file":"durable-chat.js","names":[],"sources":["../src/durable-chat-map.ts","../src/durable-chat.ts"],"sourcesContent":["import type { AgentInteractionRequest } from \"@anvia/core/agent/interactions\";\nimport type {\n AssistantContentPart,\n ContextUsage,\n JsonObject,\n JsonValue,\n ProviderToolCall,\n ReasoningContentType,\n ReasoningDetail,\n ToolCallPart,\n ToolResultContentPart,\n ToolResultOutput,\n Usage,\n} from \"@anvia/core/completion\";\nimport { isJsonValue } from \"@anvia/core/completion\";\nimport type { CompletionSource } from \"@anvia/core/completion\";\nimport type { MemoryCompactionInfo } from \"@anvia/core/memory\";\nimport type { DurableEvent } from \"@anvia/durable/protocol\";\nimport type { ClientStreamEvent } from \"./types\";\n\n/**\n * Pure projection from durable journal events to `anvia.client.v3` stream events.\n *\n * Durable `sequence` values are a global autoincrement across every run in the store, so they\n * are not contiguous inside one chat stream. `validateFrameSequence` (client-transport.ts)\n * requires each `eventId` to be exactly `last + 1` and would reject a replay, a resume cursor,\n * or any stream that shares the database with other runs. This mapper therefore uses the durable\n * sequence itself as the event id, which is also the cursor `stream({ after })` expects. Callers\n * must not wrap the resulting frames in the standard contiguous frame validator.\n *\n * Message ids are one per model operation (`${runId}:${operationId}`); part ids add a suffix.\n * Replaying the same journal on reconnect assigns the same identities.\n */\nexport type DurableChatMapState = {\n /** Assistant message open for the model operation currently streaming. */\n messageId?: string | undefined;\n /** Last durable sequence applied. The next resume starts after this cursor. */\n sequence: number;\n /** Model operations that already opened a message, so a later attempt resets it. */\n openedOperations: Set<string>;\n /** Parts that already emitted their `*_start`, so a replay of one event does not repeat it. */\n openedParts: Set<string>;\n /** Tool calls seen on `tool_started`, keyed by operation id, so `tool_completed` can match them. */\n tools: Map<string, ToolCallPart>;\n /** True once `run_start` has been emitted for this projection. */\n runOpened: boolean;\n};\n\n/** `Omit` over a union collapses to common keys; this distributes over every event variant. */\ntype WithoutRunId<T> = T extends unknown ? Omit<T, \"runId\"> : never;\n\nexport function createDurableChatMapState(sequence = 0): DurableChatMapState {\n return {\n sequence,\n openedOperations: new Set(),\n openedParts: new Set(),\n tools: new Map(),\n runOpened: false,\n };\n}\n\nexport type DurableChatMapped = {\n events: readonly ClientStreamEvent[];\n state: DurableChatMapState;\n};\n\n/**\n * Map one durable event. Events at or before the applied cursor produce nothing, so a reconnect\n * that overlaps the stored sequence does not double-apply.\n */\nexport function mapDurableChatEvent(\n event: DurableEvent,\n state: DurableChatMapState,\n settledOutcome?: JsonObject,\n): DurableChatMapped {\n if (!Number.isSafeInteger(event.sequence) || event.sequence <= state.sequence) {\n return { events: [], state };\n }\n const draft = fork(state, event.sequence);\n const events = project(event, draft, settledOutcome);\n return { events, state: draft };\n}\n\n/**\n * True when a status event needs the run's outcome, which the event itself no longer carries\n * (DUR-07). The caller reads it from the run snapshot and passes it to `mapDurableChatEvent`.\n * Journals written before the change still carry `data.outcome`, so nothing is fetched for them.\n */\nexport function needsSettledOutcome(event: DurableEvent): boolean {\n if (event.type !== \"status\") return false;\n const data = asRecord(event.data);\n if (data === undefined || data.outcome !== undefined) return false;\n const status = text(data, \"status\");\n return status === \"completed\" || status === \"waiting\" || status === \"failed\";\n}\n\n/** The status a status event reports, so a caller can check a snapshot is still at that point. */\nexport function statusEventStatus(event: DurableEvent): string | undefined {\n return event.type === \"status\" ? text(asRecord(event.data), \"status\") : undefined;\n}\n\n/**\n * One assistant message per model operation. Retries keep the identity and reset its parts, so a\n * streamed journal never leaves the empty placeholders that per-attempt ids would create.\n */\nexport function durableChatMessageId(runId: string, operationId: string): string {\n return `${runId}:${operationId}`;\n}\n\nfunction project(\n event: DurableEvent,\n state: DurableChatMapState,\n settledOutcome: JsonObject | undefined,\n): ClientStreamEvent[] {\n const data = asRecord(event.data);\n switch (event.type) {\n case \"submitted\":\n return openRun(event.runId, state);\n case \"status\":\n return mapStatus(event, data, state, settledOutcome);\n case \"model_started\":\n return mapModelStarted(event, data, state);\n case \"model_attempt_started\":\n return mapAttemptStarted(event, data, state);\n case \"model_delta\":\n return mapModelDelta(event, data, state);\n case \"model_attempt_failed\":\n return mapAttemptFailed(event, data, state);\n case \"model_completed\":\n return mapModelCompleted(event, data, state);\n case \"tool_started\":\n return mapToolStarted(event, data, state);\n case \"tool_completed\":\n return mapToolCompleted(event, data, state);\n case \"compaction_completed\":\n return mapCompaction(event, data);\n case \"steering_queued\":\n case \"steering_applied\":\n return [\n located(event, { type: \"data\", name: event.type, data: data ?? {}, transient: true }),\n ];\n default:\n return [];\n }\n}\n\nfunction mapStatus(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n settledOutcome: JsonObject | undefined,\n): ClientStreamEvent[] {\n const status = text(data, \"status\");\n // Older journals embed the outcome in the event; newer ones rely on the caller's snapshot.\n const outcome = asRecord(data?.outcome) ?? settledOutcome;\n if (status === \"needs_attention\") return needsAttention(event, data);\n if (status === \"failed\") return failed(event, data, outcome);\n if (status === \"cancelled\") return [located(event, { type: \"run_end\", status: \"cancelled\" })];\n if (status === \"waiting\" || status === \"completed\") return settled(event, outcome, status);\n // The first non-terminal status stands in for `submitted` when a replay starts mid-journal.\n if (!state.runOpened && (status === \"queued\" || status === \"pending\" || status === \"running\")) {\n return openRun(event.runId, state);\n }\n return [];\n}\n\nfunction openRun(runId: string, state: DurableChatMapState): ClientStreamEvent[] {\n state.runOpened = true;\n // The first model operation opens the assistant message; opening one here would leave an\n // empty message ahead of the real one on every turn.\n return [{ type: \"run_start\", source: \"agent\", runId }];\n}\n\nfunction mapModelStarted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\") ?? \"model\";\n const messageId = durableChatMessageId(event.runId, operationId);\n state.openedOperations.add(operationId);\n state.messageId = messageId;\n const generation: ClientStreamEvent = { type: \"generation_start\", runId: event.runId };\n const model = modelOf(data);\n if (model !== undefined) generation.model = model;\n // `run_start` belongs to submitted / the first status. Repeat it only when this event is the\n // first one the projection has seen, so a normal journal does not open the run twice.\n const events: ClientStreamEvent[] = [];\n if (!state.runOpened) events.push({ type: \"run_start\", source: \"agent\", runId: event.runId });\n state.runOpened = true;\n events.push({ type: \"turn_start\", runId: event.runId }, generation, {\n type: \"message_start\",\n messageId,\n role: \"assistant\",\n runId: event.runId,\n });\n return events;\n}\n\nfunction mapAttemptStarted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\");\n if (operationId === undefined) return [];\n const attempt = number(data, \"attempt\");\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n const opened = state.openedOperations.has(operationId);\n const retried = opened && (attempt === undefined || attempt > 1);\n const events: ClientStreamEvent[] = [];\n if (retried && state.messageId !== undefined) {\n // Discard the partial attempt but keep the message identity the reducer already holds.\n events.push({ type: \"message_reset\", messageId: state.messageId, runId: event.runId });\n } else if (!opened) {\n // A replay can start at the attempt rather than at `model_started`.\n events.push({ type: \"message_start\", messageId, role: \"assistant\", runId: event.runId });\n }\n state.openedOperations.add(operationId);\n state.messageId = messageId;\n return events;\n}\n\nfunction mapModelDelta(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const nested = asRecord(data?.event);\n const kind = text(nested, \"type\");\n if (nested === undefined || kind === undefined) return [];\n const operationId = text(data, \"operationId\") ?? \"model\";\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n state.messageId = messageId;\n const turn = number(nested, \"turn\");\n\n if (kind === \"text_delta\") {\n const delta = text(nested, \"delta\");\n if (delta === undefined) return [];\n return withStart(state, messageId, \"text\", undefined, event.runId, turn, (partId, started) => {\n const events: ClientStreamEvent[] = [];\n if (!started) events.push(part(event.runId, turn, { type: \"text_start\", messageId, partId }));\n events.push(part(event.runId, turn, { type: \"text_delta\", messageId, partId, delta }));\n return events;\n });\n }\n\n if (kind === \"reasoning_delta\") {\n const delta = text(nested, \"delta\");\n if (delta === undefined) return [];\n const reasoningId = text(nested, \"id\");\n return withStart(\n state,\n messageId,\n \"reasoning\",\n reasoningId ?? \"default\",\n event.runId,\n turn,\n (partId, started) => {\n const events: ClientStreamEvent[] = [];\n if (!started) {\n const start = part(event.runId, turn, { type: \"reasoning_start\", messageId, partId });\n if (reasoningId !== undefined && start.type === \"reasoning_start\") {\n start.reasoningId = reasoningId;\n }\n events.push(start);\n }\n const deltaEvent = part(event.runId, turn, {\n type: \"reasoning_delta\",\n messageId,\n partId,\n delta,\n });\n const contentType = reasoningType(text(nested, \"contentType\"));\n const signature = text(nested, \"signature\");\n if (deltaEvent.type === \"reasoning_delta\") {\n if (contentType !== undefined) deltaEvent.contentType = contentType;\n if (signature !== undefined) deltaEvent.signature = signature;\n }\n events.push(deltaEvent);\n return events;\n },\n );\n }\n\n if (kind === \"tool_call_delta\") {\n const toolCallId = text(nested, \"id\");\n if (toolCallId === undefined) return [];\n return withStart(state, messageId, \"tool\", toolCallId, event.runId, turn, (partId, started) => {\n const events: ClientStreamEvent[] = [];\n const callId = text(nested, \"callId\");\n const toolName = text(nested, \"name\");\n if (!started) {\n const start = part(event.runId, turn, {\n type: \"tool_call_start\",\n messageId,\n partId,\n toolCallId,\n });\n if (start.type === \"tool_call_start\") {\n if (callId !== undefined) start.callId = callId;\n if (toolName !== undefined) start.toolName = toolName;\n }\n events.push(start);\n }\n const delta = text(nested, \"argumentsDelta\");\n if (delta === undefined) return events;\n const tool = part(event.runId, turn, {\n type: \"tool_call_delta\",\n messageId,\n partId,\n toolCallId,\n delta,\n mode: nested.argumentsMode === \"replace\" ? \"replace\" : \"append\",\n });\n if (tool.type === \"tool_call_delta\") {\n if (callId !== undefined) tool.callId = callId;\n if (toolName !== undefined) tool.toolName = toolName;\n const signature = text(nested, \"signature\");\n if (signature !== undefined) tool.signature = signature;\n }\n events.push(tool);\n return events;\n });\n }\n\n if (kind === \"tool_call\") {\n const call = asToolCall(nested.toolCall);\n return call === undefined ? [] : [toolCallEnd(event.runId, messageId, call, turn)];\n }\n if (kind === \"source\") {\n const source = asSource(nested.source);\n if (source === undefined) return [];\n return [\n part(event.runId, turn, {\n type: \"source\",\n messageId,\n partId: partId(messageId, \"source\", JSON.stringify(source)),\n source,\n }),\n ];\n }\n if (kind === \"provider_tool_call\") {\n const toolCall = asProviderToolCall(nested.toolCall);\n return toolCall === undefined\n ? []\n : [part(event.runId, turn, { type: \"provider_tool_call\", toolCall })];\n }\n return [];\n}\n\nfunction mapAttemptFailed(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n // A failed attempt is not a failed run: `retry_wait` may follow. Emit a transient data\n // event instead of `error`, which would leave `useChat` in a sticky error state even when\n // the next attempt succeeds. The next `message_reset` clears the partial attempt.\n const attemptId = text(data, \"attemptId\");\n return [\n located(event, {\n type: \"data\",\n name: \"durable_model_attempt_failed\",\n data: {\n operationId: text(data, \"operationId\") ?? null,\n attemptId: attemptId ?? null,\n messageId: state.messageId ?? null,\n error: text(data, \"error\") ?? \"Durable model attempt failed.\",\n },\n transient: true,\n }),\n ];\n}\n\nfunction mapModelCompleted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\") ?? \"model\";\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n state.messageId = messageId;\n const result = asRecord(data?.result);\n const choice = assistantParts(result?.choice);\n const events: ClientStreamEvent[] = [];\n const texts = choice.filter((part) => part.type === \"text\");\n const textJoined = texts.map((part) => part.text).join(\"\");\n const textPartId = partId(messageId, \"text\");\n if (textJoined.length > 0 || state.openedParts.has(textPartId)) {\n if (!state.openedParts.has(textPartId)) {\n state.openedParts.add(textPartId);\n events.push({ type: \"text_start\", messageId, partId: textPartId, runId: event.runId });\n }\n const end: ClientStreamEvent = {\n type: \"text_end\",\n messageId,\n partId: textPartId,\n text: textJoined,\n runId: event.runId,\n };\n const signature = texts.length === 1 ? texts[0]?.signature : undefined;\n if (signature !== undefined && end.type === \"text_end\") end.signature = signature;\n events.push(end);\n }\n for (const content of choice) {\n if (content.type === \"reasoning\")\n events.push(reasoningEnd(event.runId, messageId, content, state));\n if (content.type === \"tool-call\") events.push(toolCallEnd(event.runId, messageId, content));\n }\n const messageEnd: ClientStreamEvent = { type: \"message_end\", messageId, runId: event.runId };\n const usage = asUsage(result?.usage);\n const contextUsage = asContextUsage(result?.contextUsage);\n if (usage !== undefined && messageEnd.type === \"message_end\") messageEnd.usage = usage;\n if (contextUsage !== undefined && messageEnd.type === \"message_end\") {\n messageEnd.contextUsage = contextUsage;\n }\n if (typeof result?.messageId === \"string\" && messageEnd.type === \"message_end\") {\n messageEnd.modelMessageId = result.messageId;\n }\n events.push(messageEnd);\n return events;\n}\n\nfunction mapToolStarted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\");\n const call = asToolCall(asRecord(data?.input)?.toolCall);\n if (operationId === undefined || call === undefined) return [];\n state.tools.set(operationId, call);\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);\n return [toolCallEnd(event.runId, messageId, call)];\n}\n\nfunction mapToolCompleted(\n event: DurableEvent,\n data: JsonObject | undefined,\n state: DurableChatMapState,\n): ClientStreamEvent[] {\n const operationId = text(data, \"operationId\");\n // `tool_completed` carries only the result; the call was recorded by `tool_started`.\n const call = operationId === undefined ? undefined : state.tools.get(operationId);\n const saved = asRecord(data?.result);\n const output = asToolOutput(saved?.output);\n if (output === undefined) return [];\n const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId ?? \"tools\");\n const toolCallId = call?.toolCallId ?? operationId ?? \"tool\";\n const failed = saved?.failed === true;\n const result: ClientStreamEvent = {\n type: \"tool_result\",\n messageId,\n partId: partId(messageId, \"tool\", toolCallId),\n toolCallId,\n toolName: call?.toolName ?? \"tool\",\n input: call?.input ?? null,\n runId: event.runId,\n result: failed\n ? {\n status: \"error\",\n error: { message: text(saved, \"error\") ?? \"Tool failed.\", retryable: false },\n }\n : { status: \"success\", output: toolOutputValue(output) },\n };\n if (call?.callId !== undefined && result.type === \"tool_result\") result.callId = call.callId;\n return [result];\n}\n\nfunction mapCompaction(event: DurableEvent, data: JsonObject | undefined): ClientStreamEvent[] {\n const info = asCompaction(data);\n return info === undefined ? [] : [located(event, { type: \"memory_compaction\", ...info })];\n}\n\nfunction needsAttention(event: DurableEvent, data: JsonObject | undefined): ClientStreamEvent[] {\n const operationId = text(data, \"blockedOperation\");\n const details: JsonObject = { retryable: true };\n if (operationId !== undefined) details.operationId = operationId;\n return [\n located(event, {\n type: \"error\",\n error: {\n name: \"DurableNeedsAttention\",\n message: text(data, \"error\") ?? \"Durable run needs attention.\",\n code: \"needs_attention\",\n retryable: true,\n details,\n },\n }),\n located(event, { type: \"run_end\", status: \"error\" }),\n ];\n}\n\nfunction failed(\n event: DurableEvent,\n data: JsonObject | undefined,\n outcome: JsonObject | undefined,\n): ClientStreamEvent[] {\n const error = located(event, {\n type: \"error\",\n error: {\n name: \"DurableRunError\",\n message: text(data, \"error\") ?? \"Durable run failed.\",\n code: \"failed\",\n retryable: false,\n },\n });\n const usage = asUsage(outcome?.usage);\n if (usage !== undefined && error.type === \"error\") error.usage = usage;\n return [error, runEnd(event, outcome, \"error\")];\n}\n\nfunction settled(\n event: DurableEvent,\n outcome: JsonObject | undefined,\n status: \"waiting\" | \"completed\",\n): ClientStreamEvent[] {\n const outcomeType = text(outcome, \"type\");\n if (status === \"waiting\" || outcomeType === \"interaction\") {\n const interaction = asInteraction(outcome?.interaction);\n const events: ClientStreamEvent[] = [];\n if (interaction !== undefined)\n events.push(located(event, { type: \"interaction\", interaction }));\n events.push(runEnd(event, outcome, \"suspended\"));\n return events;\n }\n if (outcomeType === \"blocked\") return [runEnd(event, outcome, \"blocked\")];\n return [runEnd(event, outcome, \"completed\")];\n}\n\nfunction runEnd(\n event: DurableEvent,\n outcome: JsonObject | undefined,\n status: \"completed\" | \"blocked\" | \"suspended\" | \"error\",\n): ClientStreamEvent {\n const end = located(event, { type: \"run_end\", status });\n if (end.type !== \"run_end\") return end;\n const value = text(outcome, \"text\");\n const usage = asUsage(outcome?.usage);\n const contextUsage = asContextUsage(outcome?.contextUsage);\n const trace = asTrace(outcome?.trace);\n const compaction = asCompaction(asRecord(outcome?.memoryCompaction));\n if (value !== undefined) end.text = value;\n if (outcome?.output !== undefined && isJsonValue(outcome.output)) end.output = outcome.output;\n if (usage !== undefined) end.usage = usage;\n if (contextUsage !== undefined) end.contextUsage = contextUsage;\n if (trace !== undefined) end.trace = trace;\n if (compaction !== undefined) end.memoryCompaction = compaction;\n return end;\n}\n\nfunction reasoningEnd(\n runId: string,\n messageId: string,\n content: Extract<AssistantContentPart, { type: \"reasoning\" }>,\n state: DurableChatMapState,\n): ClientStreamEvent {\n const id = partId(messageId, \"reasoning\", content.id ?? \"default\");\n const end: ClientStreamEvent = {\n type: \"reasoning_end\",\n messageId,\n partId: id,\n text: content.text,\n runId,\n };\n if (!state.openedParts.has(id)) state.openedParts.add(id);\n if (content.details !== undefined && end.type === \"reasoning_end\") end.content = content.details;\n return end;\n}\n\nfunction toolCallEnd(\n runId: string,\n messageId: string,\n call: ToolCallPart,\n turn?: number,\n): ClientStreamEvent {\n const event = part(runId, turn, {\n type: \"tool_call_end\",\n messageId,\n partId: partId(messageId, \"tool\", call.toolCallId),\n toolCallId: call.toolCallId,\n toolName: call.toolName,\n input: call.input,\n });\n if (event.type !== \"tool_call_end\") return event;\n if (call.callId !== undefined) event.callId = call.callId;\n if (call.signature !== undefined) event.signature = call.signature;\n return event;\n}\n\nfunction withStart(\n state: DurableChatMapState,\n messageId: string,\n kind: string,\n suffix: string | undefined,\n runId: string,\n turn: number | undefined,\n build: (partId: string, started: boolean) => ClientStreamEvent[],\n): ClientStreamEvent[] {\n void runId;\n void turn;\n const id = partId(messageId, kind, suffix);\n const started = state.openedParts.has(id);\n if (!started) state.openedParts.add(id);\n return build(id, started);\n}\n\nfunction part(\n runId: string,\n turn: number | undefined,\n event: WithoutRunId<ClientStreamEvent>,\n): ClientStreamEvent {\n const locatedEvent = { ...event, runId } as ClientStreamEvent;\n if (turn !== undefined && \"turn\" in locatedEvent) locatedEvent.turn = turn;\n else if (turn !== undefined) return { ...locatedEvent, turn };\n return locatedEvent;\n}\n\nfunction located(event: DurableEvent, fields: WithoutRunId<ClientStreamEvent>): ClientStreamEvent {\n return { ...fields, runId: event.runId } as ClientStreamEvent;\n}\n\nfunction fork(state: DurableChatMapState, sequence: number): DurableChatMapState {\n return {\n messageId: state.messageId,\n sequence,\n openedOperations: new Set(state.openedOperations),\n openedParts: new Set(state.openedParts),\n tools: new Map(state.tools),\n runOpened: state.runOpened,\n };\n}\n\nfunction partId(messageId: string, kind: string, suffix?: string): string {\n return suffix === undefined ? `${messageId}:${kind}` : `${messageId}:${kind}:${suffix}`;\n}\n\nfunction asRecord(value: unknown): JsonObject | undefined {\n if (typeof value !== \"object\" || value === null || Array.isArray(value) || !isJsonValue(value)) {\n return undefined;\n }\n return value as JsonObject;\n}\n\nfunction text(value: JsonObject | undefined, key: string): string | undefined {\n const field = value?.[key];\n return typeof field === \"string\" ? field : undefined;\n}\n\nfunction number(value: JsonObject | undefined, key: string): number | undefined {\n const field = value?.[key];\n return typeof field === \"number\" && Number.isFinite(field) ? field : undefined;\n}\n\nfunction modelOf(data: JsonObject | undefined): { provider: string; modelId: string } | undefined {\n const input = asRecord(data?.input);\n const provider = text(input, \"provider\");\n const modelId = text(input, \"modelId\");\n return provider === undefined || modelId === undefined ? undefined : { provider, modelId };\n}\n\nconst REASONING: readonly ReasoningContentType[] = [\"text\", \"summary\", \"encrypted\", \"redacted\"];\n\nfunction reasoningType(value: string | undefined): ReasoningContentType | undefined {\n return REASONING.find((type) => type === value);\n}\n\nfunction asToolCall(value: unknown): ToolCallPart | undefined {\n const call = asRecord(value);\n if (call?.type !== \"tool-call\") return undefined;\n const toolCallId = text(call, \"toolCallId\");\n const toolName = text(call, \"toolName\");\n if (toolCallId === undefined || toolName === undefined || !isJsonValue(call.input))\n return undefined;\n const parsed: ToolCallPart = { type: \"tool-call\", toolCallId, toolName, input: call.input };\n const callId = text(call, \"callId\");\n const signature = text(call, \"signature\");\n if (callId === undefined) {\n return signature === undefined ? parsed : { ...parsed, signature };\n }\n if (signature === undefined) return { ...parsed, callId };\n return { ...parsed, callId, signature };\n}\n\nfunction asSource(value: unknown): CompletionSource | undefined {\n return asRecord(value) as CompletionSource | undefined;\n}\n\nfunction asProviderToolCall(value: unknown): ProviderToolCall | undefined {\n const call = asRecord(value);\n return call === undefined ? undefined : (call as ProviderToolCall);\n}\n\nfunction assistantParts(value: unknown): AssistantContentPart[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((item) => {\n const part = assistantPart(item);\n return part === undefined ? [] : [part];\n });\n}\n\nfunction assistantPart(value: unknown): AssistantContentPart | undefined {\n const part = asRecord(value);\n const type = text(part, \"type\");\n if (part === undefined || type === undefined) return undefined;\n if (type === \"text\" && typeof part.text === \"string\") {\n return typeof part.signature === \"string\"\n ? { type: \"text\", text: part.text, signature: part.signature }\n : { type: \"text\", text: part.text };\n }\n if (type === \"reasoning\" && typeof part.text === \"string\") {\n const details = asReasoningDetails(part.details);\n const base = { type: \"reasoning\" as const, text: part.text };\n if (typeof part.id !== \"string\") return details === undefined ? base : { ...base, details };\n return details === undefined ? { ...base, id: part.id } : { ...base, id: part.id, details };\n }\n if (type === \"tool-call\") return asToolCall(part);\n return undefined;\n}\n\nfunction asReasoningDetails(value: unknown): readonly ReasoningDetail[] | undefined {\n if (!Array.isArray(value) || !isJsonValue(value)) return undefined;\n return value as readonly ReasoningDetail[];\n}\n\nfunction asUsage(value: unknown): Usage | undefined {\n const usage = asRecord(value);\n if (usage === undefined) return undefined;\n const keys = [\n \"inputTokens\",\n \"outputTokens\",\n \"totalTokens\",\n \"cachedInputTokens\",\n \"cacheCreationInputTokens\",\n ] as const;\n const counts: Partial<Usage> = {};\n for (const key of keys) {\n const count = number(usage, key);\n if (count === undefined) return undefined;\n counts[key] = count;\n }\n const parsed = counts as Usage;\n const details = asRecord(usage.details);\n if (details !== undefined && Object.values(details).every((item) => typeof item === \"number\")) {\n parsed.details = details as Record<string, number>;\n }\n return parsed;\n}\n\nfunction asContextUsage(value: unknown): ContextUsage | undefined {\n const usage = asRecord(value);\n const model = asRecord(usage?.model);\n const context = asRecord(model?.context);\n if (usage === undefined || typeof model?.modelId !== \"string\" || context === undefined)\n return undefined;\n const contextWindow = number(context, \"contextWindow\");\n const usedTokens = number(usage, \"usedTokens\");\n const remainingTokens = number(usage, \"remainingTokens\");\n const usedPercent = number(usage, \"usedPercent\");\n const remainingPercent = number(usage, \"remainingPercent\");\n if (\n contextWindow === undefined ||\n usedTokens === undefined ||\n remainingTokens === undefined ||\n usedPercent === undefined ||\n remainingPercent === undefined\n ) {\n return undefined;\n }\n const parsed: ContextUsage = {\n model: { modelId: model.modelId, context: { contextWindow } },\n usedTokens,\n remainingTokens,\n usedPercent,\n remainingPercent,\n };\n const maxInputTokens = number(context, \"maxInputTokens\");\n const maxOutputTokens = number(context, \"maxOutputTokens\");\n if (maxInputTokens !== undefined) parsed.model.context.maxInputTokens = maxInputTokens;\n if (maxOutputTokens !== undefined) parsed.model.context.maxOutputTokens = maxOutputTokens;\n return parsed;\n}\n\nfunction asTrace(\n value: unknown,\n): { observer: string; traceId?: string; observationId?: string } | undefined {\n const trace = asRecord(value);\n const observer = text(trace, \"observer\");\n if (observer === undefined) return undefined;\n const parsed: { observer: string; traceId?: string; observationId?: string } = { observer };\n const traceId = text(trace, \"traceId\");\n const observationId = text(trace, \"observationId\");\n if (traceId !== undefined) parsed.traceId = traceId;\n if (observationId !== undefined) parsed.observationId = observationId;\n return parsed;\n}\n\nfunction asCompaction(value: JsonObject | undefined): MemoryCompactionInfo | undefined {\n if (value === undefined) return undefined;\n const keys = [\n \"originalMessageCount\",\n \"compactedMessageCount\",\n \"retainedMessageCount\",\n \"originalTokenCount\",\n \"compactedTokenCount\",\n \"retainedTokenCount\",\n \"resultTokenCount\",\n \"attempts\",\n ] as const;\n const info: Partial<Record<(typeof keys)[number], number>> = {};\n for (const key of keys) {\n const count = number(value, key);\n if (count === undefined) return undefined;\n info[key] = count;\n }\n const usage = asUsage(value.usage);\n if (usage === undefined) return undefined;\n return { ...(info as Omit<MemoryCompactionInfo, \"usage\">), usage };\n}\n\nfunction asInteraction(value: unknown): AgentInteractionRequest | undefined {\n const request = asRecord(value);\n const type = text(request, \"type\");\n const id = text(request, \"id\");\n const toolName = text(request, \"toolName\");\n const toolCallId = text(request, \"toolCallId\");\n const internalCallId = text(request, \"internalCallId\");\n if (\n request === undefined ||\n id === undefined ||\n toolName === undefined ||\n toolCallId === undefined ||\n internalCallId === undefined\n ) {\n return undefined;\n }\n const callId = text(request, \"callId\");\n const base: {\n id: string;\n toolName: string;\n toolCallId: string;\n internalCallId: string;\n callId?: string;\n } = { id, toolName, toolCallId, internalCallId };\n if (callId !== undefined) base.callId = callId;\n if (type === \"tool-approval\" && isJsonValue(request.input)) {\n const approval = { ...base, type: \"tool-approval\" as const, input: request.input };\n const reason = text(request, \"reason\");\n return reason === undefined ? approval : { ...approval, reason };\n }\n if (\n type === \"tool-question\" &&\n Array.isArray(request.questions) &&\n isJsonValue(request.questions)\n ) {\n return {\n ...base,\n type,\n questions: request.questions as Extract<\n AgentInteractionRequest,\n { type: \"tool-question\" }\n >[\"questions\"],\n };\n }\n return undefined;\n}\n\nfunction asToolOutput(value: unknown): ToolResultOutput | undefined {\n const output = asRecord(value);\n const type = text(output, \"type\");\n if (output === undefined || type === undefined) return undefined;\n if ((type === \"text\" || type === \"error-text\") && typeof output.value === \"string\") {\n return { type, value: output.value };\n }\n if ((type === \"json\" || type === \"error-json\") && isJsonValue(output.value)) {\n return { type, value: output.value };\n }\n if (type === \"execution-denied\") {\n const reason = text(output, \"reason\");\n return reason === undefined ? { type } : { type, reason };\n }\n if (type === \"content\" && Array.isArray(output.value) && isJsonValue(output.value)) {\n return { type, value: output.value as readonly ToolResultContentPart[] };\n }\n return undefined;\n}\n\nfunction toolOutputValue(output: ToolResultOutput): JsonValue {\n if (output.type === \"execution-denied\") {\n return output.reason === undefined\n ? { type: output.type }\n : { type: output.type, reason: output.reason };\n }\n return output.value as JsonValue;\n}\n","import type { AgentPrompt } from \"@anvia/core/agent\";\nimport type { JsonObject, Message, ToolResultOutput } from \"@anvia/core/completion\";\nimport { isJsonValue } from \"@anvia/core/completion\";\nimport type { DurableEvent } from \"@anvia/durable/protocol\";\nimport { DurableHttpError, type DurableClient } from \"./durable\";\nimport {\n createDurableChatMapState,\n mapDurableChatEvent,\n needsSettledOutcome,\n statusEventStatus,\n type DurableChatMapState,\n} from \"./durable-chat-map\";\nimport { createClientId } from \"./messages\";\nimport {\n CLIENT_STREAM_PROTOCOL,\n type ClientStreamCursor,\n type ClientStreamFrame,\n type ClientStreamRequest,\n type ClientTransport,\n type ClientTransportSendOptions,\n} from \"./types\";\n\n/**\n * Thrown when a submission is rejected because the session already has unfinished work (HTTP 409).\n * `runId` is that run when it could be read back from the session; `undefined` when the lookup\n * failed. Reattach to `runId` instead of submitting again. Aborting a stream never raises this.\n */\nexport class DurableBusyError extends Error {\n readonly code = \"session_busy\" as const;\n\n constructor(\n readonly runId: string | undefined,\n message = \"Session already has unfinished work.\",\n ) {\n super(message);\n this.name = \"DurableBusyError\";\n }\n}\n\nconst UNFINISHED = new Set([\n \"queued\",\n \"retry_wait\",\n \"pending\",\n \"running\",\n \"waiting\",\n \"needs_attention\",\n]);\n\n/** Methods the adapter needs. A structural subset of `DurableClient`, so tests can fake it. */\nexport type DurableChatClient = Pick<\n DurableClient,\n \"submit\" | \"stream\" | \"snapshot\" | \"respond\" | \"resolveTool\" | \"retry\" | \"cancel\" | \"listRuns\"\n> &\n // Optional so a client written before this method existed still satisfies the type.\n Partial<Pick<DurableClient, \"resolveMemoryWrite\">>;\n\n/**\n * Run controls that `useChat` does not expose. `stop()` only aborts the subscription; cancellation\n * is always this explicit `cancel()`.\n */\nexport type DurableChatController = {\n /** Run last submitted or reattached. Undefined before the first successful send. */\n readonly activeRunId: string | undefined;\n /** Point later interaction responses and `send({ resume })` at an existing run. */\n reattach(runId: string, after?: number): void;\n cancel(runId?: string): Promise<void>;\n retry(runId?: string): Promise<void>;\n resolveTool(operationId: string, output: ToolResultOutput, runId?: string): Promise<void>;\n /** Settle a blocked recorded memory write: `applied` says the store holds it, `discarded` drops it. */\n resolveMemoryWrite(\n operationKey: string,\n resolution: \"applied\" | \"discarded\",\n runId?: string,\n ): Promise<void>;\n};\n\nexport type CreateDurableChatTransportOptions = {\n client: DurableChatClient;\n agentId: string;\n sessionId: string;\n /** Defaults to a UUID per submission. Return a stable id to deduplicate one prompt. */\n requestId?: () => string;\n /** Queue behind unfinished session work instead of failing. Defaults to true. */\n enqueue?: boolean;\n};\n\nexport type DurableChatTransport = ClientTransport<ClientStreamRequest> & {\n readonly controller: DurableChatController;\n};\n\ntype Session = {\n activeRunId?: string;\n /** Durable sequence last applied for `activeRunId`. Interaction responses resume after it. */\n cursor: number;\n map: DurableChatMapState;\n};\n\n/**\n * Transport `useChat` can pass to talk to `@anvia/durable`.\n *\n * Only the last user message of a `messages` request is submitted; durable keeps the transcript,\n * so the rest of the client history is discarded. An `interaction_response` is delivered to the\n * remembered run and then the stream resumes from the last applied sequence. Abort detaches the\n * SSE subscription and does not cancel the run.\n */\nexport function createDurableChatTransport(\n options: CreateDurableChatTransportOptions,\n): DurableChatTransport {\n const session: Session = { cursor: 0, map: createDurableChatMapState() };\n\n const controller: DurableChatController = {\n get activeRunId() {\n return session.activeRunId;\n },\n reattach(runId, after = 0) {\n assertCursor(after);\n session.activeRunId = requireId(runId, \"runId\");\n session.cursor = after;\n session.map = createDurableChatMapState(after);\n },\n cancel(runId) {\n return options.client.cancel(resolveRun(session, runId));\n },\n retry(runId) {\n return options.client.retry(resolveRun(session, runId));\n },\n resolveTool(operationId, output, runId) {\n return options.client.resolveTool(resolveRun(session, runId), operationId, output);\n },\n resolveMemoryWrite(operationKey, resolution, runId) {\n const resolve = options.client.resolveMemoryWrite;\n if (resolve === undefined)\n return Promise.reject(\n new TypeError(\"The durable client does not support resolveMemoryWrite.\"),\n );\n return resolve.call(options.client, resolveRun(session, runId), operationKey, resolution);\n },\n };\n\n return {\n controller,\n async *send(send) {\n const target = await begin(options, session, send);\n // A new run, or a resume behind the applied cursor, needs a fresh projection. Reusing the\n // run's existing projection keeps `run_start` and open messages from being emitted twice.\n if (session.activeRunId !== target.runId || target.after < session.cursor) {\n session.map = createDurableChatMapState(target.after);\n }\n session.activeRunId = target.runId;\n session.cursor = target.after;\n yield* streamFrames(options.client, session, target.runId, send.abortSignal);\n },\n };\n}\n\nasync function begin(\n options: CreateDurableChatTransportOptions,\n session: Session,\n send: ClientTransportSendOptions<ClientStreamRequest>,\n): Promise<{ runId: string; after: number }> {\n const resume = send.resume ?? send.request.resume;\n if (resume !== undefined) {\n assertCursor(resume.after);\n return { runId: requireId(resume.streamId, \"streamId\"), after: resume.after };\n }\n if (send.request.type === \"interaction_response\") {\n if (session.activeRunId === undefined) {\n throw new Error(\"No active durable run to receive the interaction response.\");\n }\n await options.client.respond(\n session.activeRunId,\n send.request.interactionId,\n send.request.response,\n send.abortSignal === undefined ? {} : { abortSignal: send.abortSignal },\n );\n return { runId: session.activeRunId, after: session.cursor };\n }\n const snapshot = await submitPrompt(options, send);\n return { runId: snapshot, after: 0 };\n}\n\nasync function submitPrompt(\n options: CreateDurableChatTransportOptions,\n send: ClientTransportSendOptions<ClientStreamRequest>,\n): Promise<string> {\n if (send.request.type !== \"messages\") {\n throw new TypeError(\"Unsupported durable chat request.\");\n }\n const prompt = lastUserPrompt(send.request.messages);\n const requestId = options.requestId?.() ?? createClientId(\"durable\");\n const requestOptions: { enqueue: boolean; abortSignal?: AbortSignal } = {\n enqueue: options.enqueue ?? true,\n };\n if (send.abortSignal !== undefined) requestOptions.abortSignal = send.abortSignal;\n try {\n const snapshot = await options.client.submit(\n { agentId: options.agentId, sessionId: options.sessionId, requestId, prompt },\n requestOptions,\n );\n return snapshot.run.id;\n } catch (error) {\n if (!isSessionBusy(error)) throw error;\n throw new DurableBusyError(await findBusyRun(options, send.abortSignal), error.message);\n }\n}\n\nasync function* streamFrames(\n client: DurableChatClient,\n session: Session,\n runId: string,\n abortSignal: AbortSignal | undefined,\n): AsyncIterable<ClientStreamFrame> {\n // The event id is the durable sequence, which is not contiguous per stream. See the note in\n // durable-chat-map.ts for why validateFrameSequence must not wrap this generator.\n yield {\n type: \"stream_start\",\n protocol: CLIENT_STREAM_PROTOCOL,\n streamId: runId,\n eventId: 0,\n resumable: true,\n };\n let lastEventId = session.cursor;\n const streamOptions =\n abortSignal === undefined ? { after: session.cursor } : { after: session.cursor, abortSignal };\n try {\n for await (const event of client.stream(runId, streamOptions)) {\n const settled = needsSettledOutcome(event)\n ? await snapshotOutcome(client, runId, event, abortSignal)\n : undefined;\n const mapped = mapDurableChatEvent(event, session.map, settled);\n session.map = mapped.state;\n session.cursor = mapped.state.sequence;\n lastEventId = mapped.state.sequence;\n for (const clientEvent of mapped.events) {\n yield {\n type: \"stream_event\",\n streamId: runId,\n eventId: event.sequence,\n event: clientEvent,\n };\n }\n }\n } catch (error) {\n if (!isAbort(error, abortSignal)) {\n yield { type: \"stream_end\", streamId: runId, eventId: lastEventId, status: \"error\" };\n }\n throw error;\n }\n yield { type: \"stream_end\", streamId: runId, eventId: lastEventId, status: \"completed\" };\n}\n\n/**\n * The outcome for a settled status event, read from the run snapshot (DUR-07 keeps it out of the\n * event). If the run has moved past that status, the snapshot describes a later point, so nothing\n * is returned and the event maps without its outcome.\n */\nasync function snapshotOutcome(\n client: DurableChatClient,\n runId: string,\n event: DurableEvent,\n abortSignal: AbortSignal | undefined,\n): Promise<JsonObject | undefined> {\n const snapshot = await client.snapshot(runId, abortSignal === undefined ? {} : { abortSignal });\n if (snapshot.run.status !== statusEventStatus(event)) return undefined;\n const outcome: unknown = snapshot.run.outcome;\n return typeof outcome === \"object\" &&\n outcome !== null &&\n !Array.isArray(outcome) &&\n isJsonValue(outcome)\n ? (outcome as JsonObject)\n : undefined;\n}\n\nfunction lastUserPrompt(messages: readonly Message[]): AgentPrompt {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message?.role === \"user\") return message;\n }\n throw new TypeError(\"Durable chat requires a user message to submit.\");\n}\n\nfunction isSessionBusy(error: unknown): error is DurableHttpError {\n // A submit conflict means this session already has an unfinished run.\n return error instanceof DurableHttpError && error.status === 409;\n}\n\nasync function findBusyRun(\n options: CreateDurableChatTransportOptions,\n abortSignal: AbortSignal | undefined,\n): Promise<string | undefined> {\n try {\n const page = await options.client.listRuns(\n { sessionId: options.sessionId, limit: 100 },\n abortSignal === undefined ? {} : { abortSignal },\n );\n return page.runs.find((run) => UNFINISHED.has(run.status))?.id;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveRun(session: Session, runId: string | undefined): string {\n return requireId(runId ?? session.activeRunId, \"run\");\n}\n\nfunction requireId(value: string | undefined, label: string): string {\n if (value === undefined || value.trim().length === 0) {\n throw new Error(label === \"run\" ? \"No active durable run.\" : `${label} must not be empty.`);\n }\n return value;\n}\n\nfunction assertCursor(after: number): void {\n if (!Number.isSafeInteger(after) || after < 0)\n throw new TypeError(\"Invalid durable resume cursor.\");\n}\n\nfunction isAbort(error: unknown, signal: AbortSignal | undefined): boolean {\n return signal?.aborted === true || (error instanceof Error && error.name === \"AbortError\");\n}\n\nexport type { ClientStreamCursor };\n"],"mappings":"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"}
package/dist/durable.d.ts CHANGED
@@ -18,11 +18,15 @@ export declare class DurableHttpError extends Error {
18
18
  readonly code?: string | undefined;
19
19
  /** Server-provided field name that exceeded a limit. */
20
20
  readonly field?: string | undefined;
21
+ /** Seconds from the `Retry-After` header on a rejection, when the server sent one. */
22
+ readonly retryAfterSeconds?: number | undefined;
21
23
  constructor(status: number,
22
24
  /** Server-provided machine-readable code, such as `payload_too_large`. */
23
25
  code?: string | undefined,
24
26
  /** Server-provided field name that exceeded a limit. */
25
- field?: string | undefined, message?: string);
27
+ field?: string | undefined, message?: string,
28
+ /** Seconds from the `Retry-After` header on a rejection, when the server sent one. */
29
+ retryAfterSeconds?: number | undefined);
26
30
  }
27
31
  /** Browser-safe HTTP client. Reconnect explicitly using a snapshot or last applied event cursor. */
28
32
  export declare class DurableClient {
@@ -67,6 +71,7 @@ export declare class DurableClient {
67
71
  steer(runId: string, input: AgentSteerInput, options?: DurableSteerOptions & DurableRequestOptions): Promise<AgentSteerReceipt>;
68
72
  respond(runId: string, interactionId: string, response: AgentInteractionResponse, options?: DurableRequestOptions): Promise<void>;
69
73
  resolveTool(runId: string, operationId: string, output: ToolResultOutput, options?: DurableRequestOptions): Promise<void>;
74
+ resolveMemoryWrite(runId: string, operationKey: string, resolution: "applied" | "discarded", options?: DurableRequestOptions): Promise<void>;
70
75
  retry(runId: string, options?: DurableRequestOptions): Promise<void>;
71
76
  cancel(runId: string, options?: DurableRequestOptions): Promise<void>;
72
77
  private graphPath;
@@ -1 +1 @@
1
- {"version":3,"file":"durable.d.ts","names":[],"sources":["../src/durable.ts"],"mappings":";;;;YAsCY;EAA0B,cAAc;;YACxC;;EAEV;EACA,eAAe;EACf,UAAU,qBAAqB,cAAc,QAAQ;EACrD,cAAc;;qBAEH,yBAAyB;WAEzB;;WAEA;;WAEA;EAJA,YAAA;;EAEA;;EAEA,4BACT;;;qBAkCS;mBAEkB;mBADZ;EACY,YAAA,SAAS;EAehC;;EAEJ,YAAY,KAAK,0BACjB,UAAS,wBACR,QAAQ;EAKL,aAAa,YAAY,UAAS,wBAA6B,QAAQ;EAOvE,UAAU,YAAY,UAAS,wBAA6B,QAAQ;EAQpE,UACJ,QAAQ;IAAoB;KAC5B,UAAS,wBACR,QAAQ;EAQL,WACJ,YACA,cACA,mBACA,OAAO,WACP,UAAS,wBACR;EAGG,cACJ,YACA,aACA,OAAO,WACP,UAAS,wBACR;EAGG,UAAU,YAAY,UAAS,wBAA6B;EAG5D,WAAW,YAAY,UAAS,wBAA6B;EAG5D,WACL,YACA,UAAS;IAA0B;MAClC,cAAc;UAwBT;EAKF,YACJ,YAAY,wBACZ,UAAS,wBACR,QAAQ;EAKL,cACJ,iBACA,UAAS,wBACR,QAAQ;EAOL,WACJ,QAAQ;IAA4B;KACpC,UAAS,wBACR,QAAQ;EAQL,YAAY,iBAAiB,UAAS,wBAA6B;EAGlE,YACL,iBACA,UAAS;IAA0B;MAClC,cAAc;EAwBX;;EAEJ,YAAY,KAAK,6BACjB,UAAS,uBAAuB,wBAC/B,QAAQ;EAYL,SACJ,QAAQ;IAAuB;KAC/B,UAAS,wBACR,QAAQ;EAQL,SAAS,eAAe,UAAS,wBAA6B,QAAQ;EAOrE,OACL,eACA,UAAS;IAA0B;MAClC,cAAc;EAuBX,MACJ,eACA,OAAO,iBACP,UAAS,sBAAsB,wBAC9B,QAAQ;EAaL,QACJ,eACA,uBACA,UAAU,0BACV,UAAS,wBACR;EAGG,YACJ,eACA,qBACA,QAAQ,kBACR,UAAS,wBACR;EAQG,MAAM,eAAe,UAAS,wBAA6B;EAG3D,OAAO,eAAe,UAAS,wBAA6B;UAI1D;UAKA;UAIM"}
1
+ {"version":3,"file":"durable.d.ts","names":[],"sources":["../src/durable.ts"],"mappings":";;;;YAsCY;EAA0B,cAAc;;YACxC;;EAEV;EACA,eAAe;EACf,UAAU,qBAAqB,cAAc,QAAQ;EACrD,cAAc;;qBAEH,yBAAyB;WAEzB;;WAEA;;WAEA;;WAGA;EAPA,YAAA;;EAEA;;EAEA,4BACT;;EAES;;;qBA2CA;mBAEkB;mBADZ;EACY,YAAA,SAAS;EAehC;;EAEJ,YAAY,KAAK,0BACjB,UAAS,wBACR,QAAQ;EAKL,aAAa,YAAY,UAAS,wBAA6B,QAAQ;EAOvE,UAAU,YAAY,UAAS,wBAA6B,QAAQ;EAQpE,UACJ,QAAQ;IAAoB;KAC5B,UAAS,wBACR,QAAQ;EAQL,WACJ,YACA,cACA,mBACA,OAAO,WACP,UAAS,wBACR;EAGG,cACJ,YACA,aACA,OAAO,WACP,UAAS,wBACR;EAGG,UAAU,YAAY,UAAS,wBAA6B;EAG5D,WAAW,YAAY,UAAS,wBAA6B;EAG5D,WACL,YACA,UAAS;IAA0B;MAClC,cAAc;UAwBT;EAKF,YACJ,YAAY,wBACZ,UAAS,wBACR,QAAQ;EAKL,cACJ,iBACA,UAAS,wBACR,QAAQ;EAOL,WACJ,QAAQ;IAA4B;KACpC,UAAS,wBACR,QAAQ;EAQL,YAAY,iBAAiB,UAAS,wBAA6B;EAGlE,YACL,iBACA,UAAS;IAA0B;MAClC,cAAc;EAwBX;;EAEJ,YAAY,KAAK,6BACjB,UAAS,uBAAuB,wBAC/B,QAAQ;EAYL,SACJ,QAAQ;IAAuB;KAC/B,UAAS,wBACR,QAAQ;EAQL,SAAS,eAAe,UAAS,wBAA6B,QAAQ;EAOrE,OACL,eACA,UAAS;IAA0B;MAClC,cAAc;EAuBX,MACJ,eACA,OAAO,iBACP,UAAS,sBAAsB,wBAC9B,QAAQ;EAaL,QACJ,eACA,uBACA,UAAU,0BACV,UAAS,wBACR;EAGG,YACJ,eACA,qBACA,QAAQ,kBACR,UAAS,wBACR;EAQG,mBACJ,eACA,sBACA,qCACA,UAAS,wBACR;EAQG,MAAM,eAAe,UAAS,wBAA6B;EAG3D,OAAO,eAAe,UAAS,wBAA6B;UAI1D;UAKA;UAIM"}
package/dist/durable.js CHANGED
@@ -5,14 +5,22 @@ var DurableHttpError = class extends Error {
5
5
  status;
6
6
  code;
7
7
  field;
8
- constructor(status, code, field, message) {
8
+ retryAfterSeconds;
9
+ constructor(status, code, field, message, retryAfterSeconds) {
9
10
  super(message ?? `Durable request failed with HTTP ${status}.`);
10
11
  this.status = status;
11
12
  this.code = code;
12
13
  this.field = field;
14
+ this.retryAfterSeconds = retryAfterSeconds;
13
15
  this.name = "DurableHttpError";
14
16
  }
15
17
  };
18
+ /** Parses an integer-seconds `Retry-After` value. HTTP-date values are ignored. */
19
+ function parseRetryAfter(value) {
20
+ if (value === null || !/^\d+$/.test(value.trim())) return void 0;
21
+ const seconds = Number(value.trim());
22
+ return Number.isSafeInteger(seconds) ? seconds : void 0;
23
+ }
16
24
  /** Error bodies are best-effort: a non-JSON or oversized body must not mask the status. */
17
25
  async function durableErrorBody(response) {
18
26
  let text;
@@ -32,6 +40,7 @@ async function durableErrorBody(response) {
32
40
  const record = body;
33
41
  const details = {};
34
42
  if (typeof record.error === "string") details.message = record.error;
43
+ else if (typeof record.message === "string") details.message = record.message;
35
44
  if (typeof record.code === "string") details.code = record.code;
36
45
  if (typeof record.field === "string") details.field = record.field;
37
46
  return details;
@@ -178,6 +187,12 @@ var DurableClient = class {
178
187
  output
179
188
  }, options);
180
189
  }
190
+ async resolveMemoryWrite(runId, operationKey, resolution, options = {}) {
191
+ await this.request(`${this.path(runId)}/resolve-memory-write`, "POST", {
192
+ operationKey,
193
+ resolution
194
+ }, options);
195
+ }
181
196
  async retry(runId, options = {}) {
182
197
  await this.request(`${this.path(runId)}/retry`, "POST", void 0, options);
183
198
  }
@@ -209,7 +224,7 @@ var DurableClient = class {
209
224
  const response = await fetch(url, init);
210
225
  if (!response.ok) {
211
226
  const details = await durableErrorBody(response);
212
- throw new DurableHttpError(response.status, details.code, details.field, details.message);
227
+ throw new DurableHttpError(response.status, details.code, details.field, details.message, parseRetryAfter(response.headers.get("retry-after")));
213
228
  }
214
229
  return response;
215
230
  }
@@ -1 +1 @@
1
- {"version":3,"file":"durable.js","names":[],"sources":["../src/durable.ts"],"sourcesContent":["import {\n parseTaskSnapshot,\n parseTaskGraph,\n parseTaskPage,\n parseTaskEvent,\n type TaskSubmission,\n type TaskSnapshot,\n type TaskGraphSnapshot,\n type TaskPage,\n type TaskListOptions,\n type TaskEvent,\n} from \"@anvia/durable/protocol\";\nimport type { AgentSteerInput, AgentSteerReceipt } from \"@anvia/core/agent\";\nimport type { AgentInteractionResponse } from \"@anvia/core/agent/interactions\";\nimport type { JsonValue, ToolResultOutput } from \"@anvia/core/completion\";\nimport {\n parseDurableEvent,\n parseDurableSteerReceipt,\n type DurableSteerOptions,\n parseDurableGraphSnapshot,\n parseDurableGraphEvent,\n parseDurableGraphPage,\n type DurableGraphSubmission,\n type DurableGraphSnapshot,\n type DurableGraphListOptions,\n type DurableGraphPage,\n type DurableGraphEvent,\n parseDurableRunPage,\n parseDurableSnapshot,\n type DurableEvent,\n type DurableListOptions,\n type DurableRunPage,\n type DurableSnapshot,\n type DurableSubmission,\n type DurableSubmitOptions,\n} from \"@anvia/durable/protocol\";\nimport { readSseStream } from \"./transport/streams\";\n\nexport type DurableRequestOptions = { abortSignal?: AbortSignal };\nexport type DurableClientOptions = {\n /** Absolute HTTP(S) URL matching the server handler's basePath. */\n endpoint: string;\n fetch?: typeof fetch;\n headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);\n credentials?: RequestCredentials;\n};\nexport class DurableHttpError extends Error {\n constructor(\n readonly status: number,\n /** Server-provided machine-readable code, such as `payload_too_large`. */\n readonly code?: string,\n /** Server-provided field name that exceeded a limit. */\n readonly field?: string,\n message?: string,\n ) {\n super(message ?? `Durable request failed with HTTP ${status}.`);\n this.name = \"DurableHttpError\";\n }\n}\n\n/** Error bodies are best-effort: a non-JSON or oversized body must not mask the status. */\nasync function durableErrorBody(\n response: Response,\n): Promise<{ message?: string; code?: string; field?: string }> {\n let text: string;\n try {\n text = await response.text();\n } catch {\n return {};\n }\n if (text.length === 0 || text.length > 8_192) return {};\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n return {};\n }\n if (typeof body !== \"object\" || body === null) return {};\n const record = body as Record<string, unknown>;\n const details: { message?: string; code?: string; field?: string } = {};\n if (typeof record.error === \"string\") details.message = record.error;\n if (typeof record.code === \"string\") details.code = record.code;\n if (typeof record.field === \"string\") details.field = record.field;\n return details;\n}\n\n/** Browser-safe HTTP client. Reconnect explicitly using a snapshot or last applied event cursor. */\nexport class DurableClient {\n private readonly endpoint: string;\n constructor(private readonly options: DurableClientOptions) {\n const endpoint = new URL(options.endpoint);\n if (\n ![\"http:\", \"https:\"].includes(endpoint.protocol) ||\n endpoint.search ||\n endpoint.hash ||\n endpoint.username ||\n endpoint.password\n )\n throw new TypeError(\n \"endpoint must be an HTTP(S) base URL without credentials, query, or fragment.\",\n );\n this.endpoint = endpoint.href.replace(/\\/$/, \"\");\n }\n\n async submitTask(\n /** Trace context is set by the server's `trace` hook. */\n submission: Omit<TaskSubmission, \"trace\">,\n options: DurableRequestOptions = {},\n ): Promise<TaskSnapshot> {\n return parseTaskSnapshot(\n await (await this.request(\"/tasks\", \"POST\", submission, options)).json(),\n );\n }\n async taskSnapshot(id: string, options: DurableRequestOptions = {}): Promise<TaskSnapshot> {\n const snapshot = parseTaskSnapshot(\n await (await this.request(this.taskPath(id), \"GET\", undefined, options)).json(),\n );\n if (snapshot.task.id !== id) throw new TypeError(\"Snapshot belongs to another task.\");\n return snapshot;\n }\n async taskGraph(id: string, options: DurableRequestOptions = {}): Promise<TaskGraphSnapshot> {\n const graph = parseTaskGraph(\n await (await this.request(`${this.taskPath(id)}/graph`, \"GET\", undefined, options)).json(),\n );\n if (!graph.nodes.some((task) => task.id === id))\n throw new TypeError(\"Graph belongs to another task.\");\n return graph;\n }\n async listTasks(\n filter: TaskListOptions & { sessionId: string },\n options: DurableRequestOptions = {},\n ): Promise<TaskPage> {\n const query = new URLSearchParams();\n for (const [key, value] of Object.entries(filter))\n if (value !== undefined) query.set(key, String(value));\n return parseTaskPage(\n await (await this.request(`/tasks?${query}`, \"GET\", undefined, options)).json(),\n );\n }\n async signalTask(\n id: string,\n name: string,\n requestId: string,\n value: JsonValue,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(`${this.taskPath(id)}/signal`, \"POST\", { name, requestId, value }, options);\n }\n async resolveEffect(\n id: string,\n key: string,\n value: JsonValue,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(`${this.taskPath(id)}/resolve-effect`, \"POST\", { key, value }, options);\n }\n async retryTask(id: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.taskPath(id)}/retry`, \"POST\", undefined, options);\n }\n async cancelTask(id: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.taskPath(id)}/cancel`, \"POST\", undefined, options);\n }\n async *streamTask(\n id: string,\n options: DurableRequestOptions & { after?: number } = {},\n ): AsyncIterable<TaskEvent> {\n let cursor = options.after ?? 0;\n if (!Number.isSafeInteger(cursor) || cursor < 0) throw new TypeError(\"Invalid task cursor.\");\n const snapshot = await this.taskSnapshot(id, options);\n const response = await this.request(\n `${this.taskPath(id)}/events?after=${cursor}`,\n \"GET\",\n undefined,\n options,\n );\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\") ||\n response.body === null\n )\n throw new TypeError(\"Expected a task SSE response.\");\n for await (const value of readSseStream<unknown>(response.body, { strict: true })) {\n options.abortSignal?.throwIfAborted();\n const event = parseTaskEvent(value);\n if (event.rootId !== snapshot.task.rootId || event.sequence <= cursor)\n throw new TypeError(\"Invalid task event order or root ID.\");\n cursor = event.sequence;\n yield event;\n }\n }\n private taskPath(id: string): string {\n if (id.trim().length === 0 || id === \".\" || id === \"..\") throw new TypeError(\"Invalid taskId.\");\n return `/tasks/${encodeURIComponent(id)}`;\n }\n\n async submitGraph(\n submission: DurableGraphSubmission,\n options: DurableRequestOptions = {},\n ): Promise<DurableGraphSnapshot> {\n return parseDurableGraphSnapshot(\n await (await this.request(\"/graphs\", \"POST\", submission, options)).json(),\n );\n }\n async graphSnapshot(\n graphId: string,\n options: DurableRequestOptions = {},\n ): Promise<DurableGraphSnapshot> {\n const snapshot = parseDurableGraphSnapshot(\n await (await this.request(this.graphPath(graphId), \"GET\", undefined, options)).json(),\n );\n if (snapshot.id !== graphId) throw new TypeError(\"Snapshot belongs to another graph.\");\n return snapshot;\n }\n async listGraphs(\n filter: DurableGraphListOptions & { sessionId: string },\n options: DurableRequestOptions = {},\n ): Promise<DurableGraphPage> {\n const query = new URLSearchParams();\n for (const [key, value] of Object.entries(filter))\n if (value !== undefined) query.set(key, String(value));\n return parseDurableGraphPage(\n await (await this.request(`/graphs?${query}`, \"GET\", undefined, options)).json(),\n );\n }\n async cancelGraph(graphId: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.graphPath(graphId)}/cancel`, \"POST\", undefined, options);\n }\n async *streamGraph(\n graphId: string,\n options: DurableRequestOptions & { after?: number } = {},\n ): AsyncIterable<DurableGraphEvent> {\n let cursor = options.after ?? 0;\n if (!Number.isSafeInteger(cursor) || cursor < 0) throw new TypeError(\"Invalid graph cursor.\");\n const response = await this.request(\n `${this.graphPath(graphId)}/events?after=${cursor}`,\n \"GET\",\n undefined,\n options,\n );\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\") ||\n response.body === null\n )\n throw new TypeError(\"Expected a graph SSE response.\");\n for await (const value of readSseStream<unknown>(response.body, { strict: true })) {\n options.abortSignal?.throwIfAborted();\n const event = parseDurableGraphEvent(value);\n if (event.graphId !== graphId || event.sequence <= cursor)\n throw new TypeError(\"Invalid graph event order or ID.\");\n cursor = event.sequence;\n yield event;\n }\n }\n\n async submit(\n /** Trace context is set by the server's `trace` hook. */\n submission: Omit<DurableSubmission, \"trace\">,\n options: DurableSubmitOptions & DurableRequestOptions = {},\n ): Promise<DurableSnapshot> {\n const body: Omit<DurableSubmission, \"trace\"> & DurableSubmitOptions = { ...submission };\n\n if (options.enqueue !== undefined) {\n body.enqueue = options.enqueue;\n }\n\n const response = await this.request(\"/runs\", \"POST\", body, options);\n\n return parseDurableSnapshot(await response.json());\n }\n\n async listRuns(\n filter: DurableListOptions & { sessionId: string },\n options: DurableRequestOptions = {},\n ): Promise<DurableRunPage> {\n const query = new URLSearchParams();\n for (const [key, value] of Object.entries(filter))\n if (value !== undefined) query.set(key, String(value));\n return parseDurableRunPage(\n await (await this.request(`/runs?${query}`, \"GET\", undefined, options)).json(),\n );\n }\n async snapshot(runId: string, options: DurableRequestOptions = {}): Promise<DurableSnapshot> {\n const snapshot = parseDurableSnapshot(\n await (await this.request(this.path(runId), \"GET\", undefined, options)).json(),\n );\n if (snapshot.run.id !== runId) throw new TypeError(\"Durable snapshot belongs to another run.\");\n return snapshot;\n }\n async *stream(\n runId: string,\n options: DurableRequestOptions & { after?: number } = {},\n ): AsyncIterable<DurableEvent> {\n let cursor = options.after ?? 0;\n if (!Number.isSafeInteger(cursor) || cursor < 0) throw new TypeError(\"Invalid event cursor.\");\n const response = await this.request(\n `${this.path(runId)}/events?after=${cursor}`,\n \"GET\",\n undefined,\n options,\n );\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\") ||\n response.body === null\n )\n throw new TypeError(\"Expected a durable SSE response.\");\n for await (const value of readSseStream<unknown>(response.body, { strict: true })) {\n options.abortSignal?.throwIfAborted();\n const event = parseDurableEvent(value);\n if (event.runId !== runId || event.sequence <= cursor)\n throw new TypeError(\"Invalid durable event order or run ID.\");\n cursor = event.sequence;\n yield event;\n }\n }\n async steer(\n runId: string,\n input: AgentSteerInput,\n options: DurableSteerOptions & DurableRequestOptions = {},\n ): Promise<AgentSteerReceipt> {\n const path = `${this.path(runId)}/steer`;\n const body: { input: AgentSteerInput; requestId?: string } = { input };\n\n if (options.requestId !== undefined) {\n body.requestId = options.requestId;\n }\n\n const response = await this.request(path, \"POST\", body, options);\n\n return parseDurableSteerReceipt(await response.json());\n }\n\n async respond(\n runId: string,\n interactionId: string,\n response: AgentInteractionResponse,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(`${this.path(runId)}/respond`, \"POST\", { interactionId, response }, options);\n }\n async resolveTool(\n runId: string,\n operationId: string,\n output: ToolResultOutput,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(\n `${this.path(runId)}/resolve-tool`,\n \"POST\",\n { operationId, output },\n options,\n );\n }\n async retry(runId: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.path(runId)}/retry`, \"POST\", undefined, options);\n }\n async cancel(runId: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.path(runId)}/cancel`, \"POST\", undefined, options);\n }\n\n private graphPath(id: string): string {\n if (id.trim().length === 0 || id === \".\" || id === \"..\")\n throw new TypeError(\"Invalid graphId.\");\n return `/graphs/${encodeURIComponent(id)}`;\n }\n private path(id: string): string {\n if (id.trim().length === 0) throw new TypeError(\"runId must not be empty.\");\n return `/runs/${encodeURIComponent(id)}`;\n }\n private async request(\n path: string,\n method: string,\n body: unknown,\n options: DurableRequestOptions,\n ): Promise<Response> {\n options.abortSignal?.throwIfAborted();\n const supplied =\n typeof this.options.headers === \"function\"\n ? await this.options.headers()\n : this.options.headers;\n const headers = new Headers(supplied);\n if (body !== undefined) headers.set(\"content-type\", \"application/json\");\n\n const fetch = this.options.fetch ?? globalThis.fetch;\n const url = `${this.endpoint}${path}`;\n const init: RequestInit = {\n method,\n headers,\n };\n\n if (body !== undefined) {\n init.body = JSON.stringify(body);\n }\n\n if (options.abortSignal !== undefined) {\n init.signal = options.abortSignal;\n }\n\n if (this.options.credentials !== undefined) {\n init.credentials = this.options.credentials;\n }\n\n const response = await fetch(url, init);\n if (!response.ok) {\n const details = await durableErrorBody(response);\n throw new DurableHttpError(response.status, details.code, details.field, details.message);\n }\n return response;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"durable.js","names":[],"sources":["../src/durable.ts"],"sourcesContent":["import {\n parseTaskSnapshot,\n parseTaskGraph,\n parseTaskPage,\n parseTaskEvent,\n type TaskSubmission,\n type TaskSnapshot,\n type TaskGraphSnapshot,\n type TaskPage,\n type TaskListOptions,\n type TaskEvent,\n} from \"@anvia/durable/protocol\";\nimport type { AgentSteerInput, AgentSteerReceipt } from \"@anvia/core/agent\";\nimport type { AgentInteractionResponse } from \"@anvia/core/agent/interactions\";\nimport type { JsonValue, ToolResultOutput } from \"@anvia/core/completion\";\nimport {\n parseDurableEvent,\n parseDurableSteerReceipt,\n type DurableSteerOptions,\n parseDurableGraphSnapshot,\n parseDurableGraphEvent,\n parseDurableGraphPage,\n type DurableGraphSubmission,\n type DurableGraphSnapshot,\n type DurableGraphListOptions,\n type DurableGraphPage,\n type DurableGraphEvent,\n parseDurableRunPage,\n parseDurableSnapshot,\n type DurableEvent,\n type DurableListOptions,\n type DurableRunPage,\n type DurableSnapshot,\n type DurableSubmission,\n type DurableSubmitOptions,\n} from \"@anvia/durable/protocol\";\nimport { readSseStream } from \"./transport/streams\";\n\nexport type DurableRequestOptions = { abortSignal?: AbortSignal };\nexport type DurableClientOptions = {\n /** Absolute HTTP(S) URL matching the server handler's basePath. */\n endpoint: string;\n fetch?: typeof fetch;\n headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);\n credentials?: RequestCredentials;\n};\nexport class DurableHttpError extends Error {\n constructor(\n readonly status: number,\n /** Server-provided machine-readable code, such as `payload_too_large`. */\n readonly code?: string,\n /** Server-provided field name that exceeded a limit. */\n readonly field?: string,\n message?: string,\n /** Seconds from the `Retry-After` header on a rejection, when the server sent one. */\n readonly retryAfterSeconds?: number,\n ) {\n super(message ?? `Durable request failed with HTTP ${status}.`);\n this.name = \"DurableHttpError\";\n }\n}\n\n/** Parses an integer-seconds `Retry-After` value. HTTP-date values are ignored. */\nfunction parseRetryAfter(value: string | null): number | undefined {\n if (value === null || !/^\\d+$/.test(value.trim())) return undefined;\n const seconds = Number(value.trim());\n return Number.isSafeInteger(seconds) ? seconds : undefined;\n}\n\n/** Error bodies are best-effort: a non-JSON or oversized body must not mask the status. */\nasync function durableErrorBody(\n response: Response,\n): Promise<{ message?: string; code?: string; field?: string }> {\n let text: string;\n try {\n text = await response.text();\n } catch {\n return {};\n }\n if (text.length === 0 || text.length > 8_192) return {};\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n return {};\n }\n if (typeof body !== \"object\" || body === null) return {};\n const record = body as Record<string, unknown>;\n const details: { message?: string; code?: string; field?: string } = {};\n // Gateways and proxies often send their text as `message`; `error` is Anvia's own field.\n if (typeof record.error === \"string\") details.message = record.error;\n else if (typeof record.message === \"string\") details.message = record.message;\n if (typeof record.code === \"string\") details.code = record.code;\n if (typeof record.field === \"string\") details.field = record.field;\n return details;\n}\n\n/** Browser-safe HTTP client. Reconnect explicitly using a snapshot or last applied event cursor. */\nexport class DurableClient {\n private readonly endpoint: string;\n constructor(private readonly options: DurableClientOptions) {\n const endpoint = new URL(options.endpoint);\n if (\n ![\"http:\", \"https:\"].includes(endpoint.protocol) ||\n endpoint.search ||\n endpoint.hash ||\n endpoint.username ||\n endpoint.password\n )\n throw new TypeError(\n \"endpoint must be an HTTP(S) base URL without credentials, query, or fragment.\",\n );\n this.endpoint = endpoint.href.replace(/\\/$/, \"\");\n }\n\n async submitTask(\n /** Trace context is set by the server's `trace` hook. */\n submission: Omit<TaskSubmission, \"trace\">,\n options: DurableRequestOptions = {},\n ): Promise<TaskSnapshot> {\n return parseTaskSnapshot(\n await (await this.request(\"/tasks\", \"POST\", submission, options)).json(),\n );\n }\n async taskSnapshot(id: string, options: DurableRequestOptions = {}): Promise<TaskSnapshot> {\n const snapshot = parseTaskSnapshot(\n await (await this.request(this.taskPath(id), \"GET\", undefined, options)).json(),\n );\n if (snapshot.task.id !== id) throw new TypeError(\"Snapshot belongs to another task.\");\n return snapshot;\n }\n async taskGraph(id: string, options: DurableRequestOptions = {}): Promise<TaskGraphSnapshot> {\n const graph = parseTaskGraph(\n await (await this.request(`${this.taskPath(id)}/graph`, \"GET\", undefined, options)).json(),\n );\n if (!graph.nodes.some((task) => task.id === id))\n throw new TypeError(\"Graph belongs to another task.\");\n return graph;\n }\n async listTasks(\n filter: TaskListOptions & { sessionId: string },\n options: DurableRequestOptions = {},\n ): Promise<TaskPage> {\n const query = new URLSearchParams();\n for (const [key, value] of Object.entries(filter))\n if (value !== undefined) query.set(key, String(value));\n return parseTaskPage(\n await (await this.request(`/tasks?${query}`, \"GET\", undefined, options)).json(),\n );\n }\n async signalTask(\n id: string,\n name: string,\n requestId: string,\n value: JsonValue,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(`${this.taskPath(id)}/signal`, \"POST\", { name, requestId, value }, options);\n }\n async resolveEffect(\n id: string,\n key: string,\n value: JsonValue,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(`${this.taskPath(id)}/resolve-effect`, \"POST\", { key, value }, options);\n }\n async retryTask(id: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.taskPath(id)}/retry`, \"POST\", undefined, options);\n }\n async cancelTask(id: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.taskPath(id)}/cancel`, \"POST\", undefined, options);\n }\n async *streamTask(\n id: string,\n options: DurableRequestOptions & { after?: number } = {},\n ): AsyncIterable<TaskEvent> {\n let cursor = options.after ?? 0;\n if (!Number.isSafeInteger(cursor) || cursor < 0) throw new TypeError(\"Invalid task cursor.\");\n const snapshot = await this.taskSnapshot(id, options);\n const response = await this.request(\n `${this.taskPath(id)}/events?after=${cursor}`,\n \"GET\",\n undefined,\n options,\n );\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\") ||\n response.body === null\n )\n throw new TypeError(\"Expected a task SSE response.\");\n for await (const value of readSseStream<unknown>(response.body, { strict: true })) {\n options.abortSignal?.throwIfAborted();\n const event = parseTaskEvent(value);\n if (event.rootId !== snapshot.task.rootId || event.sequence <= cursor)\n throw new TypeError(\"Invalid task event order or root ID.\");\n cursor = event.sequence;\n yield event;\n }\n }\n private taskPath(id: string): string {\n if (id.trim().length === 0 || id === \".\" || id === \"..\") throw new TypeError(\"Invalid taskId.\");\n return `/tasks/${encodeURIComponent(id)}`;\n }\n\n async submitGraph(\n submission: DurableGraphSubmission,\n options: DurableRequestOptions = {},\n ): Promise<DurableGraphSnapshot> {\n return parseDurableGraphSnapshot(\n await (await this.request(\"/graphs\", \"POST\", submission, options)).json(),\n );\n }\n async graphSnapshot(\n graphId: string,\n options: DurableRequestOptions = {},\n ): Promise<DurableGraphSnapshot> {\n const snapshot = parseDurableGraphSnapshot(\n await (await this.request(this.graphPath(graphId), \"GET\", undefined, options)).json(),\n );\n if (snapshot.id !== graphId) throw new TypeError(\"Snapshot belongs to another graph.\");\n return snapshot;\n }\n async listGraphs(\n filter: DurableGraphListOptions & { sessionId: string },\n options: DurableRequestOptions = {},\n ): Promise<DurableGraphPage> {\n const query = new URLSearchParams();\n for (const [key, value] of Object.entries(filter))\n if (value !== undefined) query.set(key, String(value));\n return parseDurableGraphPage(\n await (await this.request(`/graphs?${query}`, \"GET\", undefined, options)).json(),\n );\n }\n async cancelGraph(graphId: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.graphPath(graphId)}/cancel`, \"POST\", undefined, options);\n }\n async *streamGraph(\n graphId: string,\n options: DurableRequestOptions & { after?: number } = {},\n ): AsyncIterable<DurableGraphEvent> {\n let cursor = options.after ?? 0;\n if (!Number.isSafeInteger(cursor) || cursor < 0) throw new TypeError(\"Invalid graph cursor.\");\n const response = await this.request(\n `${this.graphPath(graphId)}/events?after=${cursor}`,\n \"GET\",\n undefined,\n options,\n );\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\") ||\n response.body === null\n )\n throw new TypeError(\"Expected a graph SSE response.\");\n for await (const value of readSseStream<unknown>(response.body, { strict: true })) {\n options.abortSignal?.throwIfAborted();\n const event = parseDurableGraphEvent(value);\n if (event.graphId !== graphId || event.sequence <= cursor)\n throw new TypeError(\"Invalid graph event order or ID.\");\n cursor = event.sequence;\n yield event;\n }\n }\n\n async submit(\n /** Trace context is set by the server's `trace` hook. */\n submission: Omit<DurableSubmission, \"trace\">,\n options: DurableSubmitOptions & DurableRequestOptions = {},\n ): Promise<DurableSnapshot> {\n const body: Omit<DurableSubmission, \"trace\"> & DurableSubmitOptions = { ...submission };\n\n if (options.enqueue !== undefined) {\n body.enqueue = options.enqueue;\n }\n\n const response = await this.request(\"/runs\", \"POST\", body, options);\n\n return parseDurableSnapshot(await response.json());\n }\n\n async listRuns(\n filter: DurableListOptions & { sessionId: string },\n options: DurableRequestOptions = {},\n ): Promise<DurableRunPage> {\n const query = new URLSearchParams();\n for (const [key, value] of Object.entries(filter))\n if (value !== undefined) query.set(key, String(value));\n return parseDurableRunPage(\n await (await this.request(`/runs?${query}`, \"GET\", undefined, options)).json(),\n );\n }\n async snapshot(runId: string, options: DurableRequestOptions = {}): Promise<DurableSnapshot> {\n const snapshot = parseDurableSnapshot(\n await (await this.request(this.path(runId), \"GET\", undefined, options)).json(),\n );\n if (snapshot.run.id !== runId) throw new TypeError(\"Durable snapshot belongs to another run.\");\n return snapshot;\n }\n async *stream(\n runId: string,\n options: DurableRequestOptions & { after?: number } = {},\n ): AsyncIterable<DurableEvent> {\n let cursor = options.after ?? 0;\n if (!Number.isSafeInteger(cursor) || cursor < 0) throw new TypeError(\"Invalid event cursor.\");\n const response = await this.request(\n `${this.path(runId)}/events?after=${cursor}`,\n \"GET\",\n undefined,\n options,\n );\n if (\n !response.headers.get(\"content-type\")?.startsWith(\"text/event-stream\") ||\n response.body === null\n )\n throw new TypeError(\"Expected a durable SSE response.\");\n for await (const value of readSseStream<unknown>(response.body, { strict: true })) {\n options.abortSignal?.throwIfAborted();\n const event = parseDurableEvent(value);\n if (event.runId !== runId || event.sequence <= cursor)\n throw new TypeError(\"Invalid durable event order or run ID.\");\n cursor = event.sequence;\n yield event;\n }\n }\n async steer(\n runId: string,\n input: AgentSteerInput,\n options: DurableSteerOptions & DurableRequestOptions = {},\n ): Promise<AgentSteerReceipt> {\n const path = `${this.path(runId)}/steer`;\n const body: { input: AgentSteerInput; requestId?: string } = { input };\n\n if (options.requestId !== undefined) {\n body.requestId = options.requestId;\n }\n\n const response = await this.request(path, \"POST\", body, options);\n\n return parseDurableSteerReceipt(await response.json());\n }\n\n async respond(\n runId: string,\n interactionId: string,\n response: AgentInteractionResponse,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(`${this.path(runId)}/respond`, \"POST\", { interactionId, response }, options);\n }\n async resolveTool(\n runId: string,\n operationId: string,\n output: ToolResultOutput,\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(\n `${this.path(runId)}/resolve-tool`,\n \"POST\",\n { operationId, output },\n options,\n );\n }\n async resolveMemoryWrite(\n runId: string,\n operationKey: string,\n resolution: \"applied\" | \"discarded\",\n options: DurableRequestOptions = {},\n ): Promise<void> {\n await this.request(\n `${this.path(runId)}/resolve-memory-write`,\n \"POST\",\n { operationKey, resolution },\n options,\n );\n }\n async retry(runId: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.path(runId)}/retry`, \"POST\", undefined, options);\n }\n async cancel(runId: string, options: DurableRequestOptions = {}): Promise<void> {\n await this.request(`${this.path(runId)}/cancel`, \"POST\", undefined, options);\n }\n\n private graphPath(id: string): string {\n if (id.trim().length === 0 || id === \".\" || id === \"..\")\n throw new TypeError(\"Invalid graphId.\");\n return `/graphs/${encodeURIComponent(id)}`;\n }\n private path(id: string): string {\n if (id.trim().length === 0) throw new TypeError(\"runId must not be empty.\");\n return `/runs/${encodeURIComponent(id)}`;\n }\n private async request(\n path: string,\n method: string,\n body: unknown,\n options: DurableRequestOptions,\n ): Promise<Response> {\n options.abortSignal?.throwIfAborted();\n const supplied =\n typeof this.options.headers === \"function\"\n ? await this.options.headers()\n : this.options.headers;\n const headers = new Headers(supplied);\n if (body !== undefined) headers.set(\"content-type\", \"application/json\");\n\n const fetch = this.options.fetch ?? globalThis.fetch;\n const url = `${this.endpoint}${path}`;\n const init: RequestInit = {\n method,\n headers,\n };\n\n if (body !== undefined) {\n init.body = JSON.stringify(body);\n }\n\n if (options.abortSignal !== undefined) {\n init.signal = options.abortSignal;\n }\n\n if (this.options.credentials !== undefined) {\n init.credentials = this.options.credentials;\n }\n\n const response = await fetch(url, init);\n if (!response.ok) {\n const details = await durableErrorBody(response);\n throw new DurableHttpError(\n response.status,\n details.code,\n details.field,\n details.message,\n parseRetryAfter(response.headers.get(\"retry-after\")),\n );\n }\n return response;\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anvia/client",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Framework-neutral client protocol, transports, and UI message state for Anvia.",
5
5
  "author": "anvia",
6
6
  "license": "MIT",
@@ -41,12 +41,12 @@
41
41
  "tsdown": "^0.23.4",
42
42
  "typescript": "^5.9.3",
43
43
  "vitest": "^4.1.11",
44
- "@anvia/core": "1.17.3",
45
- "@anvia/durable": "0.13.0"
44
+ "@anvia/core": "1.19.1",
45
+ "@anvia/durable": "0.16.0"
46
46
  },
47
47
  "peerDependencies": {
48
- "@anvia/durable": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0",
49
- "@anvia/core": "^1.17.3"
48
+ "@anvia/durable": ">=0.8.0 <1.0.0",
49
+ "@anvia/core": "^1.19.1"
50
50
  },
51
51
  "peerDependenciesMeta": {
52
52
  "@anvia/durable": {