@anvia/client 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/durable-chat.d.ts +51 -0
- package/dist/durable-chat.d.ts.map +1 -0
- package/dist/durable-chat.js +933 -0
- package/dist/durable-chat.js.map +1 -0
- package/dist/durable.d.ts +71 -65
- package/dist/durable.d.ts.map +1 -0
- package/dist/durable.js +213 -253
- package/dist/durable.js.map +1 -1
- package/dist/event-transport-CcP1zaST.js +103 -0
- package/dist/event-transport-CcP1zaST.js.map +1 -0
- package/dist/event-transport-rXxwo4BK.d.ts +88 -0
- package/dist/event-transport-rXxwo4BK.d.ts.map +1 -0
- package/dist/index.d.ts +62 -415
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1968 -2382
- package/dist/index.js.map +1 -1
- package/dist/streams-BXxF27Hp.js +156 -0
- package/dist/streams-BXxF27Hp.js.map +1 -0
- package/dist/transport/index.d.ts +2 -91
- package/dist/transport/index.js +3 -23
- package/dist/types-Bt4tUcST.d.ts +348 -0
- package/dist/types-Bt4tUcST.d.ts.map +1 -0
- package/dist/types-CqJxMo_1.js +466 -0
- package/dist/types-CqJxMo_1.js.map +1 -0
- package/package.json +11 -7
- package/dist/chunk-PD72KNCV.js +0 -150
- package/dist/chunk-PD72KNCV.js.map +0 -1
- package/dist/chunk-RK5U6WVJ.js +0 -127
- package/dist/chunk-RK5U6WVJ.js.map +0 -1
- package/dist/transport/index.js.map +0 -1
|
@@ -0,0 +1,933 @@
|
|
|
1
|
+
import { DurableHttpError } from "./durable.js";
|
|
2
|
+
import { n as createClientId, t as CLIENT_STREAM_PROTOCOL } from "./types-CqJxMo_1.js";
|
|
3
|
+
import { isJsonValue } from "@anvia/core/completion";
|
|
4
|
+
// src/durable-chat-map.ts
|
|
5
|
+
function createDurableChatMapState(sequence = 0) {
|
|
6
|
+
return {
|
|
7
|
+
sequence,
|
|
8
|
+
openedOperations: /* @__PURE__ */ new Set(),
|
|
9
|
+
openedParts: /* @__PURE__ */ new Set(),
|
|
10
|
+
tools: /* @__PURE__ */ new Map(),
|
|
11
|
+
runOpened: false
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Map one durable event. Events at or before the applied cursor produce nothing, so a reconnect
|
|
16
|
+
* that overlaps the stored sequence does not double-apply.
|
|
17
|
+
*/
|
|
18
|
+
function mapDurableChatEvent(event, state) {
|
|
19
|
+
if (!Number.isSafeInteger(event.sequence) || event.sequence <= state.sequence) return {
|
|
20
|
+
events: [],
|
|
21
|
+
state
|
|
22
|
+
};
|
|
23
|
+
const draft = fork(state, event.sequence);
|
|
24
|
+
return {
|
|
25
|
+
events: project(event, draft),
|
|
26
|
+
state: draft
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* One assistant message per model operation. Retries keep the identity and reset its parts, so a
|
|
31
|
+
* streamed journal never leaves the empty placeholders that per-attempt ids would create.
|
|
32
|
+
*/
|
|
33
|
+
function durableChatMessageId(runId, operationId) {
|
|
34
|
+
return `${runId}:${operationId}`;
|
|
35
|
+
}
|
|
36
|
+
function project(event, state) {
|
|
37
|
+
const data = asRecord(event.data);
|
|
38
|
+
switch (event.type) {
|
|
39
|
+
case "submitted": return openRun(event.runId, state);
|
|
40
|
+
case "status": return mapStatus(event, data, state);
|
|
41
|
+
case "model_started": return mapModelStarted(event, data, state);
|
|
42
|
+
case "model_attempt_started": return mapAttemptStarted(event, data, state);
|
|
43
|
+
case "model_delta": return mapModelDelta(event, data, state);
|
|
44
|
+
case "model_attempt_failed": return mapAttemptFailed(event, data, state);
|
|
45
|
+
case "model_completed": return mapModelCompleted(event, data, state);
|
|
46
|
+
case "tool_started": return mapToolStarted(event, data, state);
|
|
47
|
+
case "tool_completed": return mapToolCompleted(event, data, state);
|
|
48
|
+
case "compaction_completed": return mapCompaction(event, data);
|
|
49
|
+
case "steering_queued":
|
|
50
|
+
case "steering_applied": return [located(event, {
|
|
51
|
+
type: "data",
|
|
52
|
+
name: event.type,
|
|
53
|
+
data: data ?? {},
|
|
54
|
+
transient: true
|
|
55
|
+
})];
|
|
56
|
+
default: return [];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function mapStatus(event, data, state) {
|
|
60
|
+
const status = text(data, "status");
|
|
61
|
+
if (status === "needs_attention") return needsAttention(event, data);
|
|
62
|
+
if (status === "failed") return failed(event, data);
|
|
63
|
+
if (status === "cancelled") return [located(event, {
|
|
64
|
+
type: "run_end",
|
|
65
|
+
status: "cancelled"
|
|
66
|
+
})];
|
|
67
|
+
if (status === "waiting" || status === "completed") return settled(event, data, status);
|
|
68
|
+
if (!state.runOpened && (status === "queued" || status === "pending" || status === "running")) return openRun(event.runId, state);
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
function openRun(runId, state) {
|
|
72
|
+
state.runOpened = true;
|
|
73
|
+
return [{
|
|
74
|
+
type: "run_start",
|
|
75
|
+
source: "agent",
|
|
76
|
+
runId
|
|
77
|
+
}];
|
|
78
|
+
}
|
|
79
|
+
function mapModelStarted(event, data, state) {
|
|
80
|
+
const operationId = text(data, "operationId") ?? "model";
|
|
81
|
+
const messageId = durableChatMessageId(event.runId, operationId);
|
|
82
|
+
state.openedOperations.add(operationId);
|
|
83
|
+
state.messageId = messageId;
|
|
84
|
+
const generation = {
|
|
85
|
+
type: "generation_start",
|
|
86
|
+
runId: event.runId
|
|
87
|
+
};
|
|
88
|
+
const model = modelOf(data);
|
|
89
|
+
if (model !== void 0) generation.model = model;
|
|
90
|
+
const events = [];
|
|
91
|
+
if (!state.runOpened) events.push({
|
|
92
|
+
type: "run_start",
|
|
93
|
+
source: "agent",
|
|
94
|
+
runId: event.runId
|
|
95
|
+
});
|
|
96
|
+
state.runOpened = true;
|
|
97
|
+
events.push({
|
|
98
|
+
type: "turn_start",
|
|
99
|
+
runId: event.runId
|
|
100
|
+
}, generation, {
|
|
101
|
+
type: "message_start",
|
|
102
|
+
messageId,
|
|
103
|
+
role: "assistant",
|
|
104
|
+
runId: event.runId
|
|
105
|
+
});
|
|
106
|
+
return events;
|
|
107
|
+
}
|
|
108
|
+
function mapAttemptStarted(event, data, state) {
|
|
109
|
+
const operationId = text(data, "operationId");
|
|
110
|
+
if (operationId === void 0) return [];
|
|
111
|
+
const attempt = number(data, "attempt");
|
|
112
|
+
const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);
|
|
113
|
+
const opened = state.openedOperations.has(operationId);
|
|
114
|
+
const retried = opened && (attempt === void 0 || attempt > 1);
|
|
115
|
+
const events = [];
|
|
116
|
+
if (retried && state.messageId !== void 0) events.push({
|
|
117
|
+
type: "message_reset",
|
|
118
|
+
messageId: state.messageId,
|
|
119
|
+
runId: event.runId
|
|
120
|
+
});
|
|
121
|
+
else if (!opened) events.push({
|
|
122
|
+
type: "message_start",
|
|
123
|
+
messageId,
|
|
124
|
+
role: "assistant",
|
|
125
|
+
runId: event.runId
|
|
126
|
+
});
|
|
127
|
+
state.openedOperations.add(operationId);
|
|
128
|
+
state.messageId = messageId;
|
|
129
|
+
return events;
|
|
130
|
+
}
|
|
131
|
+
function mapModelDelta(event, data, state) {
|
|
132
|
+
const nested = asRecord(data?.event);
|
|
133
|
+
const kind = text(nested, "type");
|
|
134
|
+
if (nested === void 0 || kind === void 0) return [];
|
|
135
|
+
const operationId = text(data, "operationId") ?? "model";
|
|
136
|
+
const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);
|
|
137
|
+
state.messageId = messageId;
|
|
138
|
+
const turn = number(nested, "turn");
|
|
139
|
+
if (kind === "text_delta") {
|
|
140
|
+
const delta = text(nested, "delta");
|
|
141
|
+
if (delta === void 0) return [];
|
|
142
|
+
return withStart(state, messageId, "text", void 0, event.runId, turn, (partId, started) => {
|
|
143
|
+
const events = [];
|
|
144
|
+
if (!started) events.push(part(event.runId, turn, {
|
|
145
|
+
type: "text_start",
|
|
146
|
+
messageId,
|
|
147
|
+
partId
|
|
148
|
+
}));
|
|
149
|
+
events.push(part(event.runId, turn, {
|
|
150
|
+
type: "text_delta",
|
|
151
|
+
messageId,
|
|
152
|
+
partId,
|
|
153
|
+
delta
|
|
154
|
+
}));
|
|
155
|
+
return events;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (kind === "reasoning_delta") {
|
|
159
|
+
const delta = text(nested, "delta");
|
|
160
|
+
if (delta === void 0) return [];
|
|
161
|
+
const reasoningId = text(nested, "id");
|
|
162
|
+
return withStart(state, messageId, "reasoning", reasoningId ?? "default", event.runId, turn, (partId, started) => {
|
|
163
|
+
const events = [];
|
|
164
|
+
if (!started) {
|
|
165
|
+
const start = part(event.runId, turn, {
|
|
166
|
+
type: "reasoning_start",
|
|
167
|
+
messageId,
|
|
168
|
+
partId
|
|
169
|
+
});
|
|
170
|
+
if (reasoningId !== void 0 && start.type === "reasoning_start") start.reasoningId = reasoningId;
|
|
171
|
+
events.push(start);
|
|
172
|
+
}
|
|
173
|
+
const deltaEvent = part(event.runId, turn, {
|
|
174
|
+
type: "reasoning_delta",
|
|
175
|
+
messageId,
|
|
176
|
+
partId,
|
|
177
|
+
delta
|
|
178
|
+
});
|
|
179
|
+
const contentType = reasoningType(text(nested, "contentType"));
|
|
180
|
+
const signature = text(nested, "signature");
|
|
181
|
+
if (deltaEvent.type === "reasoning_delta") {
|
|
182
|
+
if (contentType !== void 0) deltaEvent.contentType = contentType;
|
|
183
|
+
if (signature !== void 0) deltaEvent.signature = signature;
|
|
184
|
+
}
|
|
185
|
+
events.push(deltaEvent);
|
|
186
|
+
return events;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (kind === "tool_call_delta") {
|
|
190
|
+
const toolCallId = text(nested, "id");
|
|
191
|
+
if (toolCallId === void 0) return [];
|
|
192
|
+
return withStart(state, messageId, "tool", toolCallId, event.runId, turn, (partId, started) => {
|
|
193
|
+
const events = [];
|
|
194
|
+
const callId = text(nested, "callId");
|
|
195
|
+
const toolName = text(nested, "name");
|
|
196
|
+
if (!started) {
|
|
197
|
+
const start = part(event.runId, turn, {
|
|
198
|
+
type: "tool_call_start",
|
|
199
|
+
messageId,
|
|
200
|
+
partId,
|
|
201
|
+
toolCallId
|
|
202
|
+
});
|
|
203
|
+
if (start.type === "tool_call_start") {
|
|
204
|
+
if (callId !== void 0) start.callId = callId;
|
|
205
|
+
if (toolName !== void 0) start.toolName = toolName;
|
|
206
|
+
}
|
|
207
|
+
events.push(start);
|
|
208
|
+
}
|
|
209
|
+
const delta = text(nested, "argumentsDelta");
|
|
210
|
+
if (delta === void 0) return events;
|
|
211
|
+
const tool = part(event.runId, turn, {
|
|
212
|
+
type: "tool_call_delta",
|
|
213
|
+
messageId,
|
|
214
|
+
partId,
|
|
215
|
+
toolCallId,
|
|
216
|
+
delta,
|
|
217
|
+
mode: nested.argumentsMode === "replace" ? "replace" : "append"
|
|
218
|
+
});
|
|
219
|
+
if (tool.type === "tool_call_delta") {
|
|
220
|
+
if (callId !== void 0) tool.callId = callId;
|
|
221
|
+
if (toolName !== void 0) tool.toolName = toolName;
|
|
222
|
+
const signature = text(nested, "signature");
|
|
223
|
+
if (signature !== void 0) tool.signature = signature;
|
|
224
|
+
}
|
|
225
|
+
events.push(tool);
|
|
226
|
+
return events;
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (kind === "tool_call") {
|
|
230
|
+
const call = asToolCall(nested.toolCall);
|
|
231
|
+
return call === void 0 ? [] : [toolCallEnd(event.runId, messageId, call, turn)];
|
|
232
|
+
}
|
|
233
|
+
if (kind === "source") {
|
|
234
|
+
const source = asSource(nested.source);
|
|
235
|
+
if (source === void 0) return [];
|
|
236
|
+
return [part(event.runId, turn, {
|
|
237
|
+
type: "source",
|
|
238
|
+
messageId,
|
|
239
|
+
partId: partId(messageId, "source", JSON.stringify(source)),
|
|
240
|
+
source
|
|
241
|
+
})];
|
|
242
|
+
}
|
|
243
|
+
if (kind === "provider_tool_call") {
|
|
244
|
+
const toolCall = asProviderToolCall(nested.toolCall);
|
|
245
|
+
return toolCall === void 0 ? [] : [part(event.runId, turn, {
|
|
246
|
+
type: "provider_tool_call",
|
|
247
|
+
toolCall
|
|
248
|
+
})];
|
|
249
|
+
}
|
|
250
|
+
return [];
|
|
251
|
+
}
|
|
252
|
+
function mapAttemptFailed(event, data, state) {
|
|
253
|
+
const attemptId = text(data, "attemptId");
|
|
254
|
+
return [located(event, {
|
|
255
|
+
type: "data",
|
|
256
|
+
name: "durable_model_attempt_failed",
|
|
257
|
+
data: {
|
|
258
|
+
operationId: text(data, "operationId") ?? null,
|
|
259
|
+
attemptId: attemptId ?? null,
|
|
260
|
+
messageId: state.messageId ?? null,
|
|
261
|
+
error: text(data, "error") ?? "Durable model attempt failed."
|
|
262
|
+
},
|
|
263
|
+
transient: true
|
|
264
|
+
})];
|
|
265
|
+
}
|
|
266
|
+
function mapModelCompleted(event, data, state) {
|
|
267
|
+
const operationId = text(data, "operationId") ?? "model";
|
|
268
|
+
const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);
|
|
269
|
+
state.messageId = messageId;
|
|
270
|
+
const result = asRecord(data?.result);
|
|
271
|
+
const choice = assistantParts(result?.choice);
|
|
272
|
+
const events = [];
|
|
273
|
+
const texts = choice.filter((part) => part.type === "text");
|
|
274
|
+
const textJoined = texts.map((part) => part.text).join("");
|
|
275
|
+
const textPartId = partId(messageId, "text");
|
|
276
|
+
if (textJoined.length > 0 || state.openedParts.has(textPartId)) {
|
|
277
|
+
if (!state.openedParts.has(textPartId)) {
|
|
278
|
+
state.openedParts.add(textPartId);
|
|
279
|
+
events.push({
|
|
280
|
+
type: "text_start",
|
|
281
|
+
messageId,
|
|
282
|
+
partId: textPartId,
|
|
283
|
+
runId: event.runId
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const end = {
|
|
287
|
+
type: "text_end",
|
|
288
|
+
messageId,
|
|
289
|
+
partId: textPartId,
|
|
290
|
+
text: textJoined,
|
|
291
|
+
runId: event.runId
|
|
292
|
+
};
|
|
293
|
+
const signature = texts.length === 1 ? texts[0]?.signature : void 0;
|
|
294
|
+
if (signature !== void 0 && end.type === "text_end") end.signature = signature;
|
|
295
|
+
events.push(end);
|
|
296
|
+
}
|
|
297
|
+
for (const content of choice) {
|
|
298
|
+
if (content.type === "reasoning") events.push(reasoningEnd(event.runId, messageId, content, state));
|
|
299
|
+
if (content.type === "tool-call") events.push(toolCallEnd(event.runId, messageId, content));
|
|
300
|
+
}
|
|
301
|
+
const messageEnd = {
|
|
302
|
+
type: "message_end",
|
|
303
|
+
messageId,
|
|
304
|
+
runId: event.runId
|
|
305
|
+
};
|
|
306
|
+
const usage = asUsage(result?.usage);
|
|
307
|
+
const contextUsage = asContextUsage(result?.contextUsage);
|
|
308
|
+
if (usage !== void 0 && messageEnd.type === "message_end") messageEnd.usage = usage;
|
|
309
|
+
if (contextUsage !== void 0 && messageEnd.type === "message_end") messageEnd.contextUsage = contextUsage;
|
|
310
|
+
if (typeof result?.messageId === "string" && messageEnd.type === "message_end") messageEnd.modelMessageId = result.messageId;
|
|
311
|
+
events.push(messageEnd);
|
|
312
|
+
return events;
|
|
313
|
+
}
|
|
314
|
+
function mapToolStarted(event, data, state) {
|
|
315
|
+
const operationId = text(data, "operationId");
|
|
316
|
+
const call = asToolCall(asRecord(data?.input)?.toolCall);
|
|
317
|
+
if (operationId === void 0 || call === void 0) return [];
|
|
318
|
+
state.tools.set(operationId, call);
|
|
319
|
+
const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId);
|
|
320
|
+
return [toolCallEnd(event.runId, messageId, call)];
|
|
321
|
+
}
|
|
322
|
+
function mapToolCompleted(event, data, state) {
|
|
323
|
+
const operationId = text(data, "operationId");
|
|
324
|
+
const call = operationId === void 0 ? void 0 : state.tools.get(operationId);
|
|
325
|
+
const saved = asRecord(data?.result);
|
|
326
|
+
const output = asToolOutput(saved?.output);
|
|
327
|
+
if (output === void 0) return [];
|
|
328
|
+
const messageId = state.messageId ?? durableChatMessageId(event.runId, operationId ?? "tools");
|
|
329
|
+
const toolCallId = call?.toolCallId ?? operationId ?? "tool";
|
|
330
|
+
const failed = saved?.failed === true;
|
|
331
|
+
const result = {
|
|
332
|
+
type: "tool_result",
|
|
333
|
+
messageId,
|
|
334
|
+
partId: partId(messageId, "tool", toolCallId),
|
|
335
|
+
toolCallId,
|
|
336
|
+
toolName: call?.toolName ?? "tool",
|
|
337
|
+
input: call?.input ?? null,
|
|
338
|
+
runId: event.runId,
|
|
339
|
+
result: failed ? {
|
|
340
|
+
status: "error",
|
|
341
|
+
error: {
|
|
342
|
+
message: text(saved, "error") ?? "Tool failed.",
|
|
343
|
+
retryable: false
|
|
344
|
+
}
|
|
345
|
+
} : {
|
|
346
|
+
status: "success",
|
|
347
|
+
output: toolOutputValue(output)
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
if (call?.callId !== void 0 && result.type === "tool_result") result.callId = call.callId;
|
|
351
|
+
return [result];
|
|
352
|
+
}
|
|
353
|
+
function mapCompaction(event, data) {
|
|
354
|
+
const info = asCompaction(data);
|
|
355
|
+
return info === void 0 ? [] : [located(event, {
|
|
356
|
+
type: "memory_compaction",
|
|
357
|
+
...info
|
|
358
|
+
})];
|
|
359
|
+
}
|
|
360
|
+
function needsAttention(event, data) {
|
|
361
|
+
const operationId = text(data, "blockedOperation");
|
|
362
|
+
const details = { retryable: true };
|
|
363
|
+
if (operationId !== void 0) details.operationId = operationId;
|
|
364
|
+
return [located(event, {
|
|
365
|
+
type: "error",
|
|
366
|
+
error: {
|
|
367
|
+
name: "DurableNeedsAttention",
|
|
368
|
+
message: text(data, "error") ?? "Durable run needs attention.",
|
|
369
|
+
code: "needs_attention",
|
|
370
|
+
retryable: true,
|
|
371
|
+
details
|
|
372
|
+
}
|
|
373
|
+
}), located(event, {
|
|
374
|
+
type: "run_end",
|
|
375
|
+
status: "error"
|
|
376
|
+
})];
|
|
377
|
+
}
|
|
378
|
+
function failed(event, data) {
|
|
379
|
+
const outcome = asRecord(data?.outcome);
|
|
380
|
+
const error = located(event, {
|
|
381
|
+
type: "error",
|
|
382
|
+
error: {
|
|
383
|
+
name: "DurableRunError",
|
|
384
|
+
message: text(data, "error") ?? "Durable run failed.",
|
|
385
|
+
code: "failed",
|
|
386
|
+
retryable: false
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
const usage = asUsage(outcome?.usage);
|
|
390
|
+
if (usage !== void 0 && error.type === "error") error.usage = usage;
|
|
391
|
+
return [error, runEnd(event, outcome, "error")];
|
|
392
|
+
}
|
|
393
|
+
function settled(event, data, status) {
|
|
394
|
+
const outcome = asRecord(data?.outcome);
|
|
395
|
+
const outcomeType = text(outcome, "type");
|
|
396
|
+
if (status === "waiting" || outcomeType === "interaction") {
|
|
397
|
+
const interaction = asInteraction(outcome?.interaction);
|
|
398
|
+
const events = [];
|
|
399
|
+
if (interaction !== void 0) events.push(located(event, {
|
|
400
|
+
type: "interaction",
|
|
401
|
+
interaction
|
|
402
|
+
}));
|
|
403
|
+
events.push(runEnd(event, outcome, "suspended"));
|
|
404
|
+
return events;
|
|
405
|
+
}
|
|
406
|
+
if (outcomeType === "blocked") return [runEnd(event, outcome, "blocked")];
|
|
407
|
+
return [runEnd(event, outcome, "completed")];
|
|
408
|
+
}
|
|
409
|
+
function runEnd(event, outcome, status) {
|
|
410
|
+
const end = located(event, {
|
|
411
|
+
type: "run_end",
|
|
412
|
+
status
|
|
413
|
+
});
|
|
414
|
+
if (end.type !== "run_end") return end;
|
|
415
|
+
const value = text(outcome, "text");
|
|
416
|
+
const usage = asUsage(outcome?.usage);
|
|
417
|
+
const contextUsage = asContextUsage(outcome?.contextUsage);
|
|
418
|
+
const trace = asTrace(outcome?.trace);
|
|
419
|
+
const compaction = asCompaction(asRecord(outcome?.memoryCompaction));
|
|
420
|
+
if (value !== void 0) end.text = value;
|
|
421
|
+
if (outcome?.output !== void 0 && isJsonValue(outcome.output)) end.output = outcome.output;
|
|
422
|
+
if (usage !== void 0) end.usage = usage;
|
|
423
|
+
if (contextUsage !== void 0) end.contextUsage = contextUsage;
|
|
424
|
+
if (trace !== void 0) end.trace = trace;
|
|
425
|
+
if (compaction !== void 0) end.memoryCompaction = compaction;
|
|
426
|
+
return end;
|
|
427
|
+
}
|
|
428
|
+
function reasoningEnd(runId, messageId, content, state) {
|
|
429
|
+
const id = partId(messageId, "reasoning", content.id ?? "default");
|
|
430
|
+
const end = {
|
|
431
|
+
type: "reasoning_end",
|
|
432
|
+
messageId,
|
|
433
|
+
partId: id,
|
|
434
|
+
text: content.text,
|
|
435
|
+
runId
|
|
436
|
+
};
|
|
437
|
+
if (!state.openedParts.has(id)) state.openedParts.add(id);
|
|
438
|
+
if (content.details !== void 0 && end.type === "reasoning_end") end.content = content.details;
|
|
439
|
+
return end;
|
|
440
|
+
}
|
|
441
|
+
function toolCallEnd(runId, messageId, call, turn) {
|
|
442
|
+
const event = part(runId, turn, {
|
|
443
|
+
type: "tool_call_end",
|
|
444
|
+
messageId,
|
|
445
|
+
partId: partId(messageId, "tool", call.toolCallId),
|
|
446
|
+
toolCallId: call.toolCallId,
|
|
447
|
+
toolName: call.toolName,
|
|
448
|
+
input: call.input
|
|
449
|
+
});
|
|
450
|
+
if (event.type !== "tool_call_end") return event;
|
|
451
|
+
if (call.callId !== void 0) event.callId = call.callId;
|
|
452
|
+
if (call.signature !== void 0) event.signature = call.signature;
|
|
453
|
+
return event;
|
|
454
|
+
}
|
|
455
|
+
function withStart(state, messageId, kind, suffix, runId, turn, build) {
|
|
456
|
+
const id = partId(messageId, kind, suffix);
|
|
457
|
+
const started = state.openedParts.has(id);
|
|
458
|
+
if (!started) state.openedParts.add(id);
|
|
459
|
+
return build(id, started);
|
|
460
|
+
}
|
|
461
|
+
function part(runId, turn, event) {
|
|
462
|
+
const locatedEvent = {
|
|
463
|
+
...event,
|
|
464
|
+
runId
|
|
465
|
+
};
|
|
466
|
+
if (turn !== void 0 && "turn" in locatedEvent) locatedEvent.turn = turn;
|
|
467
|
+
else if (turn !== void 0) return {
|
|
468
|
+
...locatedEvent,
|
|
469
|
+
turn
|
|
470
|
+
};
|
|
471
|
+
return locatedEvent;
|
|
472
|
+
}
|
|
473
|
+
function located(event, fields) {
|
|
474
|
+
return {
|
|
475
|
+
...fields,
|
|
476
|
+
runId: event.runId
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function fork(state, sequence) {
|
|
480
|
+
return {
|
|
481
|
+
messageId: state.messageId,
|
|
482
|
+
sequence,
|
|
483
|
+
openedOperations: new Set(state.openedOperations),
|
|
484
|
+
openedParts: new Set(state.openedParts),
|
|
485
|
+
tools: new Map(state.tools),
|
|
486
|
+
runOpened: state.runOpened
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function partId(messageId, kind, suffix) {
|
|
490
|
+
return suffix === void 0 ? `${messageId}:${kind}` : `${messageId}:${kind}:${suffix}`;
|
|
491
|
+
}
|
|
492
|
+
function asRecord(value) {
|
|
493
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || !isJsonValue(value)) return;
|
|
494
|
+
return value;
|
|
495
|
+
}
|
|
496
|
+
function text(value, key) {
|
|
497
|
+
const field = value?.[key];
|
|
498
|
+
return typeof field === "string" ? field : void 0;
|
|
499
|
+
}
|
|
500
|
+
function number(value, key) {
|
|
501
|
+
const field = value?.[key];
|
|
502
|
+
return typeof field === "number" && Number.isFinite(field) ? field : void 0;
|
|
503
|
+
}
|
|
504
|
+
function modelOf(data) {
|
|
505
|
+
const input = asRecord(data?.input);
|
|
506
|
+
const provider = text(input, "provider");
|
|
507
|
+
const modelId = text(input, "modelId");
|
|
508
|
+
return provider === void 0 || modelId === void 0 ? void 0 : {
|
|
509
|
+
provider,
|
|
510
|
+
modelId
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
const REASONING = [
|
|
514
|
+
"text",
|
|
515
|
+
"summary",
|
|
516
|
+
"encrypted",
|
|
517
|
+
"redacted"
|
|
518
|
+
];
|
|
519
|
+
function reasoningType(value) {
|
|
520
|
+
return REASONING.find((type) => type === value);
|
|
521
|
+
}
|
|
522
|
+
function asToolCall(value) {
|
|
523
|
+
const call = asRecord(value);
|
|
524
|
+
if (call?.type !== "tool-call") return void 0;
|
|
525
|
+
const toolCallId = text(call, "toolCallId");
|
|
526
|
+
const toolName = text(call, "toolName");
|
|
527
|
+
if (toolCallId === void 0 || toolName === void 0 || !isJsonValue(call.input)) return void 0;
|
|
528
|
+
const parsed = {
|
|
529
|
+
type: "tool-call",
|
|
530
|
+
toolCallId,
|
|
531
|
+
toolName,
|
|
532
|
+
input: call.input
|
|
533
|
+
};
|
|
534
|
+
const callId = text(call, "callId");
|
|
535
|
+
const signature = text(call, "signature");
|
|
536
|
+
if (callId === void 0) return signature === void 0 ? parsed : {
|
|
537
|
+
...parsed,
|
|
538
|
+
signature
|
|
539
|
+
};
|
|
540
|
+
if (signature === void 0) return {
|
|
541
|
+
...parsed,
|
|
542
|
+
callId
|
|
543
|
+
};
|
|
544
|
+
return {
|
|
545
|
+
...parsed,
|
|
546
|
+
callId,
|
|
547
|
+
signature
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function asSource(value) {
|
|
551
|
+
return asRecord(value);
|
|
552
|
+
}
|
|
553
|
+
function asProviderToolCall(value) {
|
|
554
|
+
const call = asRecord(value);
|
|
555
|
+
return call === void 0 ? void 0 : call;
|
|
556
|
+
}
|
|
557
|
+
function assistantParts(value) {
|
|
558
|
+
if (!Array.isArray(value)) return [];
|
|
559
|
+
return value.flatMap((item) => {
|
|
560
|
+
const part = assistantPart(item);
|
|
561
|
+
return part === void 0 ? [] : [part];
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
function assistantPart(value) {
|
|
565
|
+
const part = asRecord(value);
|
|
566
|
+
const type = text(part, "type");
|
|
567
|
+
if (part === void 0 || type === void 0) return void 0;
|
|
568
|
+
if (type === "text" && typeof part.text === "string") return typeof part.signature === "string" ? {
|
|
569
|
+
type: "text",
|
|
570
|
+
text: part.text,
|
|
571
|
+
signature: part.signature
|
|
572
|
+
} : {
|
|
573
|
+
type: "text",
|
|
574
|
+
text: part.text
|
|
575
|
+
};
|
|
576
|
+
if (type === "reasoning" && typeof part.text === "string") {
|
|
577
|
+
const details = asReasoningDetails(part.details);
|
|
578
|
+
const base = {
|
|
579
|
+
type: "reasoning",
|
|
580
|
+
text: part.text
|
|
581
|
+
};
|
|
582
|
+
if (typeof part.id !== "string") return details === void 0 ? base : {
|
|
583
|
+
...base,
|
|
584
|
+
details
|
|
585
|
+
};
|
|
586
|
+
return details === void 0 ? {
|
|
587
|
+
...base,
|
|
588
|
+
id: part.id
|
|
589
|
+
} : {
|
|
590
|
+
...base,
|
|
591
|
+
id: part.id,
|
|
592
|
+
details
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
if (type === "tool-call") return asToolCall(part);
|
|
596
|
+
}
|
|
597
|
+
function asReasoningDetails(value) {
|
|
598
|
+
if (!Array.isArray(value) || !isJsonValue(value)) return void 0;
|
|
599
|
+
return value;
|
|
600
|
+
}
|
|
601
|
+
function asUsage(value) {
|
|
602
|
+
const usage = asRecord(value);
|
|
603
|
+
if (usage === void 0) return void 0;
|
|
604
|
+
const keys = [
|
|
605
|
+
"inputTokens",
|
|
606
|
+
"outputTokens",
|
|
607
|
+
"totalTokens",
|
|
608
|
+
"cachedInputTokens",
|
|
609
|
+
"cacheCreationInputTokens"
|
|
610
|
+
];
|
|
611
|
+
const counts = {};
|
|
612
|
+
for (const key of keys) {
|
|
613
|
+
const count = number(usage, key);
|
|
614
|
+
if (count === void 0) return void 0;
|
|
615
|
+
counts[key] = count;
|
|
616
|
+
}
|
|
617
|
+
const parsed = counts;
|
|
618
|
+
const details = asRecord(usage.details);
|
|
619
|
+
if (details !== void 0 && Object.values(details).every((item) => typeof item === "number")) parsed.details = details;
|
|
620
|
+
return parsed;
|
|
621
|
+
}
|
|
622
|
+
function asContextUsage(value) {
|
|
623
|
+
const usage = asRecord(value);
|
|
624
|
+
const model = asRecord(usage?.model);
|
|
625
|
+
const context = asRecord(model?.context);
|
|
626
|
+
if (usage === void 0 || typeof model?.modelId !== "string" || context === void 0) return void 0;
|
|
627
|
+
const contextWindow = number(context, "contextWindow");
|
|
628
|
+
const usedTokens = number(usage, "usedTokens");
|
|
629
|
+
const remainingTokens = number(usage, "remainingTokens");
|
|
630
|
+
const usedPercent = number(usage, "usedPercent");
|
|
631
|
+
const remainingPercent = number(usage, "remainingPercent");
|
|
632
|
+
if (contextWindow === void 0 || usedTokens === void 0 || remainingTokens === void 0 || usedPercent === void 0 || remainingPercent === void 0) return;
|
|
633
|
+
const parsed = {
|
|
634
|
+
model: {
|
|
635
|
+
modelId: model.modelId,
|
|
636
|
+
context: { contextWindow }
|
|
637
|
+
},
|
|
638
|
+
usedTokens,
|
|
639
|
+
remainingTokens,
|
|
640
|
+
usedPercent,
|
|
641
|
+
remainingPercent
|
|
642
|
+
};
|
|
643
|
+
const maxInputTokens = number(context, "maxInputTokens");
|
|
644
|
+
const maxOutputTokens = number(context, "maxOutputTokens");
|
|
645
|
+
if (maxInputTokens !== void 0) parsed.model.context.maxInputTokens = maxInputTokens;
|
|
646
|
+
if (maxOutputTokens !== void 0) parsed.model.context.maxOutputTokens = maxOutputTokens;
|
|
647
|
+
return parsed;
|
|
648
|
+
}
|
|
649
|
+
function asTrace(value) {
|
|
650
|
+
const trace = asRecord(value);
|
|
651
|
+
const observer = text(trace, "observer");
|
|
652
|
+
if (observer === void 0) return void 0;
|
|
653
|
+
const parsed = { observer };
|
|
654
|
+
const traceId = text(trace, "traceId");
|
|
655
|
+
const observationId = text(trace, "observationId");
|
|
656
|
+
if (traceId !== void 0) parsed.traceId = traceId;
|
|
657
|
+
if (observationId !== void 0) parsed.observationId = observationId;
|
|
658
|
+
return parsed;
|
|
659
|
+
}
|
|
660
|
+
function asCompaction(value) {
|
|
661
|
+
if (value === void 0) return void 0;
|
|
662
|
+
const keys = [
|
|
663
|
+
"originalMessageCount",
|
|
664
|
+
"compactedMessageCount",
|
|
665
|
+
"retainedMessageCount",
|
|
666
|
+
"originalTokenCount",
|
|
667
|
+
"compactedTokenCount",
|
|
668
|
+
"retainedTokenCount",
|
|
669
|
+
"resultTokenCount",
|
|
670
|
+
"attempts"
|
|
671
|
+
];
|
|
672
|
+
const info = {};
|
|
673
|
+
for (const key of keys) {
|
|
674
|
+
const count = number(value, key);
|
|
675
|
+
if (count === void 0) return void 0;
|
|
676
|
+
info[key] = count;
|
|
677
|
+
}
|
|
678
|
+
const usage = asUsage(value.usage);
|
|
679
|
+
if (usage === void 0) return void 0;
|
|
680
|
+
return {
|
|
681
|
+
...info,
|
|
682
|
+
usage
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
function asInteraction(value) {
|
|
686
|
+
const request = asRecord(value);
|
|
687
|
+
const type = text(request, "type");
|
|
688
|
+
const id = text(request, "id");
|
|
689
|
+
const toolName = text(request, "toolName");
|
|
690
|
+
const toolCallId = text(request, "toolCallId");
|
|
691
|
+
const internalCallId = text(request, "internalCallId");
|
|
692
|
+
if (request === void 0 || id === void 0 || toolName === void 0 || toolCallId === void 0 || internalCallId === void 0) return;
|
|
693
|
+
const callId = text(request, "callId");
|
|
694
|
+
const base = {
|
|
695
|
+
id,
|
|
696
|
+
toolName,
|
|
697
|
+
toolCallId,
|
|
698
|
+
internalCallId
|
|
699
|
+
};
|
|
700
|
+
if (callId !== void 0) base.callId = callId;
|
|
701
|
+
if (type === "tool-approval" && isJsonValue(request.input)) {
|
|
702
|
+
const approval = {
|
|
703
|
+
...base,
|
|
704
|
+
type: "tool-approval",
|
|
705
|
+
input: request.input
|
|
706
|
+
};
|
|
707
|
+
const reason = text(request, "reason");
|
|
708
|
+
return reason === void 0 ? approval : {
|
|
709
|
+
...approval,
|
|
710
|
+
reason
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
if (type === "tool-question" && Array.isArray(request.questions) && isJsonValue(request.questions)) return {
|
|
714
|
+
...base,
|
|
715
|
+
type,
|
|
716
|
+
questions: request.questions
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function asToolOutput(value) {
|
|
720
|
+
const output = asRecord(value);
|
|
721
|
+
const type = text(output, "type");
|
|
722
|
+
if (output === void 0 || type === void 0) return void 0;
|
|
723
|
+
if ((type === "text" || type === "error-text") && typeof output.value === "string") return {
|
|
724
|
+
type,
|
|
725
|
+
value: output.value
|
|
726
|
+
};
|
|
727
|
+
if ((type === "json" || type === "error-json") && isJsonValue(output.value)) return {
|
|
728
|
+
type,
|
|
729
|
+
value: output.value
|
|
730
|
+
};
|
|
731
|
+
if (type === "execution-denied") {
|
|
732
|
+
const reason = text(output, "reason");
|
|
733
|
+
return reason === void 0 ? { type } : {
|
|
734
|
+
type,
|
|
735
|
+
reason
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
if (type === "content" && Array.isArray(output.value) && isJsonValue(output.value)) return {
|
|
739
|
+
type,
|
|
740
|
+
value: output.value
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
function toolOutputValue(output) {
|
|
744
|
+
if (output.type === "execution-denied") return output.reason === void 0 ? { type: output.type } : {
|
|
745
|
+
type: output.type,
|
|
746
|
+
reason: output.reason
|
|
747
|
+
};
|
|
748
|
+
return output.value;
|
|
749
|
+
}
|
|
750
|
+
// src/durable-chat.ts
|
|
751
|
+
/**
|
|
752
|
+
* Thrown when a submission is rejected because the session already has unfinished work (HTTP 409).
|
|
753
|
+
* `runId` is that run when it could be read back from the session; `undefined` when the lookup
|
|
754
|
+
* failed. Reattach to `runId` instead of submitting again. Aborting a stream never raises this.
|
|
755
|
+
*/
|
|
756
|
+
var DurableBusyError = class extends Error {
|
|
757
|
+
runId;
|
|
758
|
+
code = "session_busy";
|
|
759
|
+
constructor(runId, message = "Session already has unfinished work.") {
|
|
760
|
+
super(message);
|
|
761
|
+
this.runId = runId;
|
|
762
|
+
this.name = "DurableBusyError";
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
const UNFINISHED = /* @__PURE__ */ new Set([
|
|
766
|
+
"queued",
|
|
767
|
+
"retry_wait",
|
|
768
|
+
"pending",
|
|
769
|
+
"running",
|
|
770
|
+
"waiting",
|
|
771
|
+
"needs_attention"
|
|
772
|
+
]);
|
|
773
|
+
/**
|
|
774
|
+
* Transport `useChat` can pass to talk to `@anvia/durable`.
|
|
775
|
+
*
|
|
776
|
+
* Only the last user message of a `messages` request is submitted; durable keeps the transcript,
|
|
777
|
+
* so the rest of the client history is discarded. An `interaction_response` is delivered to the
|
|
778
|
+
* remembered run and then the stream resumes from the last applied sequence. Abort detaches the
|
|
779
|
+
* SSE subscription and does not cancel the run.
|
|
780
|
+
*/
|
|
781
|
+
function createDurableChatTransport(options) {
|
|
782
|
+
const session = {
|
|
783
|
+
cursor: 0,
|
|
784
|
+
map: createDurableChatMapState()
|
|
785
|
+
};
|
|
786
|
+
return {
|
|
787
|
+
controller: {
|
|
788
|
+
get activeRunId() {
|
|
789
|
+
return session.activeRunId;
|
|
790
|
+
},
|
|
791
|
+
reattach(runId, after = 0) {
|
|
792
|
+
assertCursor(after);
|
|
793
|
+
session.activeRunId = requireId(runId, "runId");
|
|
794
|
+
session.cursor = after;
|
|
795
|
+
session.map = createDurableChatMapState(after);
|
|
796
|
+
},
|
|
797
|
+
cancel(runId) {
|
|
798
|
+
return options.client.cancel(resolveRun(session, runId));
|
|
799
|
+
},
|
|
800
|
+
retry(runId) {
|
|
801
|
+
return options.client.retry(resolveRun(session, runId));
|
|
802
|
+
},
|
|
803
|
+
resolveTool(operationId, output, runId) {
|
|
804
|
+
return options.client.resolveTool(resolveRun(session, runId), operationId, output);
|
|
805
|
+
}
|
|
806
|
+
},
|
|
807
|
+
async *send(send) {
|
|
808
|
+
const target = await begin(options, session, send);
|
|
809
|
+
if (session.activeRunId !== target.runId || target.after < session.cursor) session.map = createDurableChatMapState(target.after);
|
|
810
|
+
session.activeRunId = target.runId;
|
|
811
|
+
session.cursor = target.after;
|
|
812
|
+
yield* streamFrames(options.client, session, target.runId, send.abortSignal);
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
async function begin(options, session, send) {
|
|
817
|
+
const resume = send.resume ?? send.request.resume;
|
|
818
|
+
if (resume !== void 0) {
|
|
819
|
+
assertCursor(resume.after);
|
|
820
|
+
return {
|
|
821
|
+
runId: requireId(resume.streamId, "streamId"),
|
|
822
|
+
after: resume.after
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
if (send.request.type === "interaction_response") {
|
|
826
|
+
if (session.activeRunId === void 0) throw new Error("No active durable run to receive the interaction response.");
|
|
827
|
+
await options.client.respond(session.activeRunId, send.request.interactionId, send.request.response, send.abortSignal === void 0 ? {} : { abortSignal: send.abortSignal });
|
|
828
|
+
return {
|
|
829
|
+
runId: session.activeRunId,
|
|
830
|
+
after: session.cursor
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
return {
|
|
834
|
+
runId: await submitPrompt(options, send),
|
|
835
|
+
after: 0
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
async function submitPrompt(options, send) {
|
|
839
|
+
if (send.request.type !== "messages") throw new TypeError("Unsupported durable chat request.");
|
|
840
|
+
const prompt = lastUserPrompt(send.request.messages);
|
|
841
|
+
const requestId = options.requestId?.() ?? createClientId("durable");
|
|
842
|
+
const requestOptions = { enqueue: options.enqueue ?? true };
|
|
843
|
+
if (send.abortSignal !== void 0) requestOptions.abortSignal = send.abortSignal;
|
|
844
|
+
try {
|
|
845
|
+
return (await options.client.submit({
|
|
846
|
+
agentId: options.agentId,
|
|
847
|
+
sessionId: options.sessionId,
|
|
848
|
+
requestId,
|
|
849
|
+
prompt
|
|
850
|
+
}, requestOptions)).run.id;
|
|
851
|
+
} catch (error) {
|
|
852
|
+
if (!isSessionBusy(error)) throw error;
|
|
853
|
+
throw new DurableBusyError(await findBusyRun(options, send.abortSignal), error.message);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
async function* streamFrames(client, session, runId, abortSignal) {
|
|
857
|
+
yield {
|
|
858
|
+
type: "stream_start",
|
|
859
|
+
protocol: CLIENT_STREAM_PROTOCOL,
|
|
860
|
+
streamId: runId,
|
|
861
|
+
eventId: 0,
|
|
862
|
+
resumable: true
|
|
863
|
+
};
|
|
864
|
+
let lastEventId = session.cursor;
|
|
865
|
+
const streamOptions = abortSignal === void 0 ? { after: session.cursor } : {
|
|
866
|
+
after: session.cursor,
|
|
867
|
+
abortSignal
|
|
868
|
+
};
|
|
869
|
+
try {
|
|
870
|
+
for await (const event of client.stream(runId, streamOptions)) {
|
|
871
|
+
const mapped = mapDurableChatEvent(event, session.map);
|
|
872
|
+
session.map = mapped.state;
|
|
873
|
+
session.cursor = mapped.state.sequence;
|
|
874
|
+
lastEventId = mapped.state.sequence;
|
|
875
|
+
for (const clientEvent of mapped.events) yield {
|
|
876
|
+
type: "stream_event",
|
|
877
|
+
streamId: runId,
|
|
878
|
+
eventId: event.sequence,
|
|
879
|
+
event: clientEvent
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
} catch (error) {
|
|
883
|
+
if (!isAbort(error, abortSignal)) yield {
|
|
884
|
+
type: "stream_end",
|
|
885
|
+
streamId: runId,
|
|
886
|
+
eventId: lastEventId,
|
|
887
|
+
status: "error"
|
|
888
|
+
};
|
|
889
|
+
throw error;
|
|
890
|
+
}
|
|
891
|
+
yield {
|
|
892
|
+
type: "stream_end",
|
|
893
|
+
streamId: runId,
|
|
894
|
+
eventId: lastEventId,
|
|
895
|
+
status: "completed"
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
function lastUserPrompt(messages) {
|
|
899
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
900
|
+
const message = messages[index];
|
|
901
|
+
if (message?.role === "user") return message;
|
|
902
|
+
}
|
|
903
|
+
throw new TypeError("Durable chat requires a user message to submit.");
|
|
904
|
+
}
|
|
905
|
+
function isSessionBusy(error) {
|
|
906
|
+
return error instanceof DurableHttpError && error.status === 409;
|
|
907
|
+
}
|
|
908
|
+
async function findBusyRun(options, abortSignal) {
|
|
909
|
+
try {
|
|
910
|
+
return (await options.client.listRuns({
|
|
911
|
+
sessionId: options.sessionId,
|
|
912
|
+
limit: 100
|
|
913
|
+
}, abortSignal === void 0 ? {} : { abortSignal })).runs.find((run) => UNFINISHED.has(run.status))?.id;
|
|
914
|
+
} catch {
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
function resolveRun(session, runId) {
|
|
919
|
+
return requireId(runId ?? session.activeRunId, "run");
|
|
920
|
+
}
|
|
921
|
+
function requireId(value, label) {
|
|
922
|
+
if (value === void 0 || value.trim().length === 0) throw new Error(label === "run" ? "No active durable run." : `${label} must not be empty.`);
|
|
923
|
+
return value;
|
|
924
|
+
}
|
|
925
|
+
function assertCursor(after) {
|
|
926
|
+
if (!Number.isSafeInteger(after) || after < 0) throw new TypeError("Invalid durable resume cursor.");
|
|
927
|
+
}
|
|
928
|
+
function isAbort(error, signal) {
|
|
929
|
+
return signal?.aborted === true || error instanceof Error && error.name === "AbortError";
|
|
930
|
+
}
|
|
931
|
+
export { DurableBusyError, createDurableChatTransport };
|
|
932
|
+
|
|
933
|
+
//# sourceMappingURL=durable-chat.js.map
|