veryfront 0.1.292 → 0.1.294
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/esm/deno.d.ts +1 -0
- package/esm/deno.js +3 -2
- package/esm/src/chat/conversation.d.ts +4 -0
- package/esm/src/chat/conversation.d.ts.map +1 -1
- package/esm/src/chat/conversation.js +123 -0
- package/esm/src/chat/index.d.ts +1 -0
- package/esm/src/chat/index.d.ts.map +1 -1
- package/esm/src/chat/index.js +1 -0
- package/esm/src/chat/stream-watchdog.d.ts +34 -0
- package/esm/src/chat/stream-watchdog.d.ts.map +1 -0
- package/esm/src/chat/stream-watchdog.js +142 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +5 -1
- package/src/deno.js +3 -2
- package/src/src/chat/conversation.ts +151 -0
- package/src/src/chat/index.ts +14 -0
- package/src/src/chat/stream-watchdog.ts +222 -0
- package/src/src/utils/version-constant.ts +1 -1
package/esm/deno.d.ts
CHANGED
package/esm/deno.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.294",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"nodeModulesDir": "auto",
|
|
6
6
|
"workspace": [
|
|
@@ -67,7 +67,8 @@ export default {
|
|
|
67
67
|
"./chat/conversation": "./src/chat/conversation.ts",
|
|
68
68
|
"./chat/message-prep": "./src/chat/message-prep.ts",
|
|
69
69
|
"./chat/final-step-fallback": "./src/chat/final-step-fallback.ts",
|
|
70
|
-
"./chat/provider-errors": "./src/chat/provider-errors.ts"
|
|
70
|
+
"./chat/provider-errors": "./src/chat/provider-errors.ts",
|
|
71
|
+
"./chat/stream-watchdog": "./src/chat/stream-watchdog.ts"
|
|
71
72
|
},
|
|
72
73
|
"imports": {
|
|
73
74
|
"veryfront/head": "./src/react/runtime/core.ts",
|
|
@@ -226,6 +226,10 @@ export declare function pushToolParts(parts: MessagePart[], toolName: string, to
|
|
|
226
226
|
output?: unknown;
|
|
227
227
|
errorText?: unknown;
|
|
228
228
|
}): void;
|
|
229
|
+
export declare function toConversationPartsFromUiMessage(message: ChatUiMessage): MessagePart[];
|
|
230
|
+
export declare function hasIncompleteToolParts(message: ChatUiMessage): boolean;
|
|
231
|
+
export declare function markIncompleteToolPartsAsStopped(message: ChatUiMessage): ChatUiMessage;
|
|
232
|
+
export declare function markIncompleteToolPartsAsErrored(message: ChatUiMessage, errorText: string): ChatUiMessage;
|
|
229
233
|
export declare function isToolCallPart(value: unknown): value is ToolCallLike;
|
|
230
234
|
export declare function isToolResultPart(value: unknown): value is ToolResultLike;
|
|
231
235
|
export declare function isTextPart(value: unknown): value is TextPartLike;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/src/chat/conversation.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/src/chat/conversation.ts"],"names":[],"mappings":"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"}
|
|
@@ -214,6 +214,129 @@ export function pushToolParts(parts, toolName, toolCallId, state, part) {
|
|
|
214
214
|
state: mapToolState(state),
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
|
+
function pushFileConversationPart(parts, part) {
|
|
218
|
+
const uploadId = part.uploadId ?? extractUploadId(part.url);
|
|
219
|
+
if (!uploadId)
|
|
220
|
+
return;
|
|
221
|
+
if (part.mediaType.startsWith("image/")) {
|
|
222
|
+
parts.push({
|
|
223
|
+
type: "image",
|
|
224
|
+
upload_id: uploadId,
|
|
225
|
+
media_type: part.mediaType,
|
|
226
|
+
...(part.url ? { url: part.url } : {}),
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
parts.push({
|
|
231
|
+
type: "file",
|
|
232
|
+
upload_id: uploadId,
|
|
233
|
+
media_type: part.mediaType,
|
|
234
|
+
...(part.url ? { url: part.url } : {}),
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
export function toConversationPartsFromUiMessage(message) {
|
|
238
|
+
const parts = [];
|
|
239
|
+
for (const part of message.parts) {
|
|
240
|
+
if (part.type === "text") {
|
|
241
|
+
parts.push({ type: "text", text: part.text });
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (part.type === "reasoning") {
|
|
245
|
+
parts.push({ type: "reasoning", text: part.text });
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (part.type === "step-start") {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (part.type === "source-url") {
|
|
252
|
+
parts.push({
|
|
253
|
+
type: "citation",
|
|
254
|
+
source_id: part.sourceId,
|
|
255
|
+
title: part.title,
|
|
256
|
+
url: part.url,
|
|
257
|
+
});
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (part.type === "source-document") {
|
|
261
|
+
parts.push({
|
|
262
|
+
type: "citation",
|
|
263
|
+
source_id: part.sourceId,
|
|
264
|
+
title: part.title,
|
|
265
|
+
});
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (part.type === "file") {
|
|
269
|
+
pushFileConversationPart(parts, part);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (isDataUiPart(part)) {
|
|
273
|
+
const name = part.type.replace(/^data-/, "");
|
|
274
|
+
if (name.length > 0) {
|
|
275
|
+
parts.push({
|
|
276
|
+
type: "data",
|
|
277
|
+
name,
|
|
278
|
+
value: part.data,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (isToolUiPart(part)) {
|
|
284
|
+
const toolName = getUiToolName(part);
|
|
285
|
+
if (!toolName) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
pushToolParts(parts, toolName, part.toolCallId, part.state, part);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return parts.filter((part) => messagePartSchema.safeParse(part).success);
|
|
292
|
+
}
|
|
293
|
+
function isToolComplete(part) {
|
|
294
|
+
return part.state === "output-available" || part.state === "output-error" ||
|
|
295
|
+
part.state === "output-denied";
|
|
296
|
+
}
|
|
297
|
+
export function hasIncompleteToolParts(message) {
|
|
298
|
+
return message.parts.some((part) => isToolUiPart(part) && !isToolComplete(part));
|
|
299
|
+
}
|
|
300
|
+
export function markIncompleteToolPartsAsStopped(message) {
|
|
301
|
+
return markIncompleteToolPartsAsErrored(message, "Stopped by user");
|
|
302
|
+
}
|
|
303
|
+
export function markIncompleteToolPartsAsErrored(message, errorText) {
|
|
304
|
+
let mutated = false;
|
|
305
|
+
const parts = message.parts.map((part) => {
|
|
306
|
+
if (!isToolUiPart(part) || isToolComplete(part)) {
|
|
307
|
+
return part;
|
|
308
|
+
}
|
|
309
|
+
mutated = true;
|
|
310
|
+
return markToolPartAsErrored(part, errorText);
|
|
311
|
+
});
|
|
312
|
+
return mutated ? { ...message, parts } : message;
|
|
313
|
+
}
|
|
314
|
+
function markToolPartAsErrored(part, errorText) {
|
|
315
|
+
if (part.type === "dynamic-tool") {
|
|
316
|
+
return {
|
|
317
|
+
type: "dynamic-tool",
|
|
318
|
+
toolName: part.toolName,
|
|
319
|
+
toolCallId: part.toolCallId,
|
|
320
|
+
...(part.title ? { title: part.title } : {}),
|
|
321
|
+
...(part.providerExecuted !== undefined ? { providerExecuted: part.providerExecuted } : {}),
|
|
322
|
+
...(part.callProviderMetadata ? { callProviderMetadata: part.callProviderMetadata } : {}),
|
|
323
|
+
input: part.input,
|
|
324
|
+
state: "output-error",
|
|
325
|
+
errorText,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
type: part.type,
|
|
330
|
+
toolCallId: part.toolCallId,
|
|
331
|
+
...(part.toolName ? { toolName: part.toolName } : {}),
|
|
332
|
+
...(part.title ? { title: part.title } : {}),
|
|
333
|
+
...(part.providerExecuted !== undefined ? { providerExecuted: part.providerExecuted } : {}),
|
|
334
|
+
...(part.callProviderMetadata ? { callProviderMetadata: part.callProviderMetadata } : {}),
|
|
335
|
+
input: part.input,
|
|
336
|
+
state: "output-error",
|
|
337
|
+
errorText,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
217
340
|
export function isToolCallPart(value) {
|
|
218
341
|
return (isRecord(value) &&
|
|
219
342
|
value.type === "tool-call" &&
|
package/esm/src/chat/index.d.ts
CHANGED
|
@@ -63,4 +63,5 @@ export { type HostedStreamPartForUiChunkMapping, type HostedUiChunkMappingOption
|
|
|
63
63
|
export { useCompletion, type UseCompletionOptions, type UseCompletionResult, } from "../agent/react/use-completion.js";
|
|
64
64
|
export { useStreaming, type UseStreamingOptions, type UseStreamingResult, } from "../agent/react/use-streaming.js";
|
|
65
65
|
export { useVoiceInput, type UseVoiceInputOptions, type UseVoiceInputResult, } from "../agent/react/use-voice-input.js";
|
|
66
|
+
export { ChatStreamIdleTimeoutError, type ChatStreamWatchdogOptions, type ChatStreamWatchdogPhase, type ChatStreamWatchdogState, createChatStreamWatchdog, createChatStreamWatchdogState, DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS, getNextChatStreamWatchdogState, isHeartbeatOnlyMetadataChunk, isLongRunningToolRunning, } from "./stream-watchdog.js";
|
|
66
67
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/chat/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/chat/index.ts"],"names":[],"mappings":"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"}
|
package/esm/src/chat/index.js
CHANGED
|
@@ -61,3 +61,4 @@ export { mapHostedStreamPartToChatUiChunks, } from "./hosted-ui-chunk-mapping.js
|
|
|
61
61
|
export { useCompletion, } from "../agent/react/use-completion.js";
|
|
62
62
|
export { useStreaming, } from "../agent/react/use-streaming.js";
|
|
63
63
|
export { useVoiceInput, } from "../agent/react/use-voice-input.js";
|
|
64
|
+
export { ChatStreamIdleTimeoutError, createChatStreamWatchdog, createChatStreamWatchdogState, DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS, getNextChatStreamWatchdogState, isHeartbeatOnlyMetadataChunk, isLongRunningToolRunning, } from "./stream-watchdog.js";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import "../../_dnt.polyfills.js";
|
|
2
|
+
import type { ChatUiMessageChunk, MessageMetadata } from "./types.js";
|
|
3
|
+
export declare const DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS = 120000;
|
|
4
|
+
export declare const DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS = 300000;
|
|
5
|
+
export type ChatStreamWatchdogPhase = "response_pending" | "tool_input_streaming" | "tool_running" | "post_tool_idle";
|
|
6
|
+
export type ChatStreamWatchdogState = {
|
|
7
|
+
phase: ChatStreamWatchdogPhase;
|
|
8
|
+
timeoutMs: number;
|
|
9
|
+
toolCallId?: string;
|
|
10
|
+
toolName?: string;
|
|
11
|
+
};
|
|
12
|
+
export type ChatStreamWatchdogOptions = {
|
|
13
|
+
idleTimeoutMs?: number;
|
|
14
|
+
toolRunningTimeoutMs?: number;
|
|
15
|
+
longRunningToolNames?: Iterable<string>;
|
|
16
|
+
};
|
|
17
|
+
export declare class ChatStreamIdleTimeoutError extends Error {
|
|
18
|
+
readonly state: ChatStreamWatchdogState;
|
|
19
|
+
constructor(state: ChatStreamWatchdogState);
|
|
20
|
+
}
|
|
21
|
+
export declare function createChatStreamWatchdogState(phase: ChatStreamWatchdogPhase, metadata?: {
|
|
22
|
+
toolCallId?: string;
|
|
23
|
+
toolName?: string;
|
|
24
|
+
}, options?: Pick<Required<ChatStreamWatchdogOptions>, "idleTimeoutMs" | "toolRunningTimeoutMs">): ChatStreamWatchdogState;
|
|
25
|
+
export declare function isLongRunningToolRunning(current: ChatStreamWatchdogState, longRunningToolNames: ReadonlySet<string>): boolean;
|
|
26
|
+
export declare function getNextChatStreamWatchdogState(currentState: ChatStreamWatchdogState, chunk: ChatUiMessageChunk<MessageMetadata>, options?: ChatStreamWatchdogOptions): ChatStreamWatchdogState;
|
|
27
|
+
export declare function isHeartbeatOnlyMetadataChunk(chunk: ChatUiMessageChunk<MessageMetadata>): boolean;
|
|
28
|
+
export declare function createChatStreamWatchdog(options?: ChatStreamWatchdogOptions): {
|
|
29
|
+
signal: AbortSignal;
|
|
30
|
+
readonly lastTimeoutState: ChatStreamWatchdogState | null;
|
|
31
|
+
observe(chunk: ChatUiMessageChunk<MessageMetadata>): void;
|
|
32
|
+
dispose(): void;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=stream-watchdog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-watchdog.d.ts","sourceRoot":"","sources":["../../../src/src/chat/stream-watchdog.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtE,eAAO,MAAM,mCAAmC,SAAU,CAAC;AAC3D,eAAO,MAAM,2CAA2C,SAAU,CAAC;AAEnE,MAAM,MAAM,uBAAuB,GAC/B,kBAAkB,GAClB,sBAAsB,GACtB,cAAc,GACd,gBAAgB,CAAC;AAErB,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,uBAAuB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACzC,CAAC;AAEF,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAC;gBAE5B,KAAK,EAAE,uBAAuB;CAU3C;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,CAAC,EAAE;IACT,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,EACD,OAAO,GAAE,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,eAAe,GAAG,sBAAsB,CAG1F,GACA,uBAAuB,CAOzB;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,uBAAuB,EAChC,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,GACxC,OAAO,CAMT;AAED,wBAAgB,8BAA8B,CAC5C,YAAY,EAAE,uBAAuB,EACrC,KAAK,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAC1C,OAAO,CAAC,EAAE,yBAAyB,GAClC,uBAAuB,CA+DzB;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,kBAAkB,CAAC,eAAe,CAAC,GAAG,OAAO,CAEhG;AAED,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,yBAAyB;;+BAsChD,uBAAuB,GAAG,IAAI;mBAGvC,kBAAkB,CAAC,eAAe,CAAC;;EAgBrD"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import "../../_dnt.polyfills.js";
|
|
2
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
3
|
+
export const DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS = 120_000;
|
|
4
|
+
export const DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS = 300_000;
|
|
5
|
+
export class ChatStreamIdleTimeoutError extends Error {
|
|
6
|
+
state;
|
|
7
|
+
constructor(state) {
|
|
8
|
+
const toolLabel = typeof state.toolName === "string" && state.toolName.length > 0
|
|
9
|
+
? ` for ${state.toolName}${state.toolCallId ? ` (${state.toolCallId})` : ""}`
|
|
10
|
+
: state.toolCallId
|
|
11
|
+
? ` for ${state.toolCallId}`
|
|
12
|
+
: "";
|
|
13
|
+
super(`Chat stream idle timeout after ${state.timeoutMs}ms during ${state.phase}${toolLabel}`);
|
|
14
|
+
this.name = "ChatStreamIdleTimeoutError";
|
|
15
|
+
this.state = state;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function createChatStreamWatchdogState(phase, metadata, options = {
|
|
19
|
+
idleTimeoutMs: DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS,
|
|
20
|
+
toolRunningTimeoutMs: DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS,
|
|
21
|
+
}) {
|
|
22
|
+
return {
|
|
23
|
+
phase,
|
|
24
|
+
timeoutMs: phase === "tool_running" ? options.toolRunningTimeoutMs : options.idleTimeoutMs,
|
|
25
|
+
...(metadata?.toolCallId ? { toolCallId: metadata.toolCallId } : {}),
|
|
26
|
+
...(metadata?.toolName ? { toolName: metadata.toolName } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function isLongRunningToolRunning(current, longRunningToolNames) {
|
|
30
|
+
return (current.phase === "tool_running" &&
|
|
31
|
+
typeof current.toolName === "string" &&
|
|
32
|
+
longRunningToolNames.has(current.toolName));
|
|
33
|
+
}
|
|
34
|
+
export function getNextChatStreamWatchdogState(currentState, chunk, options) {
|
|
35
|
+
const resolvedOptions = resolveChatStreamWatchdogOptions(options);
|
|
36
|
+
switch (chunk.type) {
|
|
37
|
+
case "tool-input-start":
|
|
38
|
+
return createChatStreamWatchdogState("tool_input_streaming", {
|
|
39
|
+
toolCallId: chunk.toolCallId,
|
|
40
|
+
toolName: chunk.toolName,
|
|
41
|
+
}, resolvedOptions);
|
|
42
|
+
case "tool-input-delta":
|
|
43
|
+
return createChatStreamWatchdogState("tool_input_streaming", {
|
|
44
|
+
toolCallId: chunk.toolCallId,
|
|
45
|
+
toolName: currentState.toolCallId === chunk.toolCallId
|
|
46
|
+
? currentState.toolName
|
|
47
|
+
: undefined,
|
|
48
|
+
}, resolvedOptions);
|
|
49
|
+
case "tool-input-available":
|
|
50
|
+
return createChatStreamWatchdogState("tool_running", {
|
|
51
|
+
toolCallId: chunk.toolCallId,
|
|
52
|
+
toolName: chunk.toolName,
|
|
53
|
+
}, resolvedOptions);
|
|
54
|
+
case "tool-output-available":
|
|
55
|
+
case "tool-output-error":
|
|
56
|
+
case "tool-output-denied":
|
|
57
|
+
return createChatStreamWatchdogState("post_tool_idle", {
|
|
58
|
+
toolCallId: chunk.toolCallId,
|
|
59
|
+
toolName: currentState.toolCallId === chunk.toolCallId
|
|
60
|
+
? currentState.toolName
|
|
61
|
+
: undefined,
|
|
62
|
+
}, resolvedOptions);
|
|
63
|
+
case "message-metadata":
|
|
64
|
+
return isLongRunningToolRunning(currentState, resolvedOptions.longRunningToolNames)
|
|
65
|
+
? currentState
|
|
66
|
+
: createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
67
|
+
case "finish":
|
|
68
|
+
return createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
69
|
+
default:
|
|
70
|
+
return isLongRunningToolRunning(currentState, resolvedOptions.longRunningToolNames)
|
|
71
|
+
? currentState
|
|
72
|
+
: createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function isHeartbeatOnlyMetadataChunk(chunk) {
|
|
76
|
+
return chunk.type === "message-metadata" && Object.keys(chunk.messageMetadata ?? {}).length === 0;
|
|
77
|
+
}
|
|
78
|
+
export function createChatStreamWatchdog(options) {
|
|
79
|
+
const resolvedOptions = resolveChatStreamWatchdogOptions(options);
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
let state = createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
82
|
+
let timer = null;
|
|
83
|
+
let lastTimeoutState = null;
|
|
84
|
+
const clearTimer = () => {
|
|
85
|
+
if (timer !== null) {
|
|
86
|
+
clearTimeout(timer);
|
|
87
|
+
timer = null;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const arm = () => {
|
|
91
|
+
if (controller.signal.aborted) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
clearTimer();
|
|
95
|
+
if (isLongRunningToolRunning(state, resolvedOptions.longRunningToolNames)) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
timer = dntShim.setTimeout(() => {
|
|
99
|
+
lastTimeoutState = state;
|
|
100
|
+
controller.abort(new DOMException(new ChatStreamIdleTimeoutError(state).message, "AbortError"));
|
|
101
|
+
}, state.timeoutMs);
|
|
102
|
+
maybeUnrefTimer(timer);
|
|
103
|
+
};
|
|
104
|
+
arm();
|
|
105
|
+
return {
|
|
106
|
+
signal: controller.signal,
|
|
107
|
+
get lastTimeoutState() {
|
|
108
|
+
return lastTimeoutState;
|
|
109
|
+
},
|
|
110
|
+
observe(chunk) {
|
|
111
|
+
if (isHeartbeatOnlyMetadataChunk(chunk)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
state = getNextChatStreamWatchdogState(state, chunk, resolvedOptions);
|
|
115
|
+
if (chunk.type === "finish") {
|
|
116
|
+
clearTimer();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
arm();
|
|
120
|
+
},
|
|
121
|
+
dispose() {
|
|
122
|
+
clearTimer();
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function resolveChatStreamWatchdogOptions(options) {
|
|
127
|
+
return {
|
|
128
|
+
idleTimeoutMs: options?.idleTimeoutMs ?? DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS,
|
|
129
|
+
toolRunningTimeoutMs: options?.toolRunningTimeoutMs ??
|
|
130
|
+
DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS,
|
|
131
|
+
longRunningToolNames: new Set(options?.longRunningToolNames ?? ["invoke_agent"]),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function maybeUnrefTimer(timer) {
|
|
135
|
+
if (typeof timer !== "object" || timer === null || !("unref" in timer)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const timerWithUnref = timer;
|
|
139
|
+
if (typeof timerWithUnref.unref === "function") {
|
|
140
|
+
timerWithUnref.unref();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.294";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.294",
|
|
4
4
|
"description": "The simplest way to build AI-powered apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -193,6 +193,10 @@
|
|
|
193
193
|
"import": "./esm/src/chat/provider-errors.js",
|
|
194
194
|
"types": "./esm/src/chat/provider-errors.d.ts"
|
|
195
195
|
},
|
|
196
|
+
"./chat/stream-watchdog": {
|
|
197
|
+
"import": "./esm/src/chat/stream-watchdog.js",
|
|
198
|
+
"types": "./esm/src/chat/stream-watchdog.d.ts"
|
|
199
|
+
},
|
|
196
200
|
"./tsconfig.json": "./tsconfig.json"
|
|
197
201
|
},
|
|
198
202
|
"scripts": {},
|
package/src/deno.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"name": "veryfront",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.294",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"nodeModulesDir": "auto",
|
|
6
6
|
"workspace": [
|
|
@@ -67,7 +67,8 @@ export default {
|
|
|
67
67
|
"./chat/conversation": "./src/chat/conversation.ts",
|
|
68
68
|
"./chat/message-prep": "./src/chat/message-prep.ts",
|
|
69
69
|
"./chat/final-step-fallback": "./src/chat/final-step-fallback.ts",
|
|
70
|
-
"./chat/provider-errors": "./src/chat/provider-errors.ts"
|
|
70
|
+
"./chat/provider-errors": "./src/chat/provider-errors.ts",
|
|
71
|
+
"./chat/stream-watchdog": "./src/chat/stream-watchdog.ts"
|
|
71
72
|
},
|
|
72
73
|
"imports": {
|
|
73
74
|
"veryfront/head": "./src/react/runtime/core.ts",
|
|
@@ -293,6 +293,157 @@ export function pushToolParts(
|
|
|
293
293
|
});
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
+
function pushFileConversationPart(
|
|
297
|
+
parts: MessagePart[],
|
|
298
|
+
part: Extract<ChatUiMessagePart, { type: "file" }>,
|
|
299
|
+
): void {
|
|
300
|
+
const uploadId = part.uploadId ?? extractUploadId(part.url);
|
|
301
|
+
if (!uploadId) return;
|
|
302
|
+
|
|
303
|
+
if (part.mediaType.startsWith("image/")) {
|
|
304
|
+
parts.push({
|
|
305
|
+
type: "image",
|
|
306
|
+
upload_id: uploadId,
|
|
307
|
+
media_type: part.mediaType,
|
|
308
|
+
...(part.url ? { url: part.url } : {}),
|
|
309
|
+
});
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
parts.push({
|
|
314
|
+
type: "file",
|
|
315
|
+
upload_id: uploadId,
|
|
316
|
+
media_type: part.mediaType,
|
|
317
|
+
...(part.url ? { url: part.url } : {}),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function toConversationPartsFromUiMessage(message: ChatUiMessage): MessagePart[] {
|
|
322
|
+
const parts: MessagePart[] = [];
|
|
323
|
+
|
|
324
|
+
for (const part of message.parts) {
|
|
325
|
+
if (part.type === "text") {
|
|
326
|
+
parts.push({ type: "text", text: part.text });
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (part.type === "reasoning") {
|
|
331
|
+
parts.push({ type: "reasoning", text: part.text });
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (part.type === "step-start") {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (part.type === "source-url") {
|
|
340
|
+
parts.push({
|
|
341
|
+
type: "citation",
|
|
342
|
+
source_id: part.sourceId,
|
|
343
|
+
title: part.title,
|
|
344
|
+
url: part.url,
|
|
345
|
+
});
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (part.type === "source-document") {
|
|
350
|
+
parts.push({
|
|
351
|
+
type: "citation",
|
|
352
|
+
source_id: part.sourceId,
|
|
353
|
+
title: part.title,
|
|
354
|
+
});
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (part.type === "file") {
|
|
359
|
+
pushFileConversationPart(parts, part);
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (isDataUiPart(part)) {
|
|
364
|
+
const name = part.type.replace(/^data-/, "");
|
|
365
|
+
if (name.length > 0) {
|
|
366
|
+
parts.push({
|
|
367
|
+
type: "data",
|
|
368
|
+
name,
|
|
369
|
+
value: part.data,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (isToolUiPart(part)) {
|
|
376
|
+
const toolName = getUiToolName(part);
|
|
377
|
+
if (!toolName) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
pushToolParts(parts, toolName, part.toolCallId, part.state, part);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return parts.filter((part) => messagePartSchema.safeParse(part).success);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function isToolComplete(part: ToolUiPart): boolean {
|
|
389
|
+
return part.state === "output-available" || part.state === "output-error" ||
|
|
390
|
+
part.state === "output-denied";
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function hasIncompleteToolParts(message: ChatUiMessage): boolean {
|
|
394
|
+
return message.parts.some((part) => isToolUiPart(part) && !isToolComplete(part));
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export function markIncompleteToolPartsAsStopped(message: ChatUiMessage): ChatUiMessage {
|
|
398
|
+
return markIncompleteToolPartsAsErrored(message, "Stopped by user");
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export function markIncompleteToolPartsAsErrored(
|
|
402
|
+
message: ChatUiMessage,
|
|
403
|
+
errorText: string,
|
|
404
|
+
): ChatUiMessage {
|
|
405
|
+
let mutated = false;
|
|
406
|
+
|
|
407
|
+
const parts = message.parts.map((part) => {
|
|
408
|
+
if (!isToolUiPart(part) || isToolComplete(part)) {
|
|
409
|
+
return part;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
mutated = true;
|
|
413
|
+
return markToolPartAsErrored(part, errorText);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
return mutated ? { ...message, parts } : message;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function markToolPartAsErrored(part: ToolUiPart, errorText: string): ChatUiMessagePart {
|
|
420
|
+
if (part.type === "dynamic-tool") {
|
|
421
|
+
return {
|
|
422
|
+
type: "dynamic-tool",
|
|
423
|
+
toolName: part.toolName,
|
|
424
|
+
toolCallId: part.toolCallId,
|
|
425
|
+
...(part.title ? { title: part.title } : {}),
|
|
426
|
+
...(part.providerExecuted !== undefined ? { providerExecuted: part.providerExecuted } : {}),
|
|
427
|
+
...(part.callProviderMetadata ? { callProviderMetadata: part.callProviderMetadata } : {}),
|
|
428
|
+
input: part.input,
|
|
429
|
+
state: "output-error",
|
|
430
|
+
errorText,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
type: part.type,
|
|
436
|
+
toolCallId: part.toolCallId,
|
|
437
|
+
...(part.toolName ? { toolName: part.toolName } : {}),
|
|
438
|
+
...(part.title ? { title: part.title } : {}),
|
|
439
|
+
...(part.providerExecuted !== undefined ? { providerExecuted: part.providerExecuted } : {}),
|
|
440
|
+
...(part.callProviderMetadata ? { callProviderMetadata: part.callProviderMetadata } : {}),
|
|
441
|
+
input: part.input,
|
|
442
|
+
state: "output-error",
|
|
443
|
+
errorText,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
296
447
|
export function isToolCallPart(value: unknown): value is ToolCallLike {
|
|
297
448
|
return (
|
|
298
449
|
isRecord(value) &&
|
package/src/src/chat/index.ts
CHANGED
|
@@ -259,3 +259,17 @@ export {
|
|
|
259
259
|
type UseVoiceInputOptions,
|
|
260
260
|
type UseVoiceInputResult,
|
|
261
261
|
} from "../agent/react/use-voice-input.js";
|
|
262
|
+
|
|
263
|
+
export {
|
|
264
|
+
ChatStreamIdleTimeoutError,
|
|
265
|
+
type ChatStreamWatchdogOptions,
|
|
266
|
+
type ChatStreamWatchdogPhase,
|
|
267
|
+
type ChatStreamWatchdogState,
|
|
268
|
+
createChatStreamWatchdog,
|
|
269
|
+
createChatStreamWatchdogState,
|
|
270
|
+
DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS,
|
|
271
|
+
DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS,
|
|
272
|
+
getNextChatStreamWatchdogState,
|
|
273
|
+
isHeartbeatOnlyMetadataChunk,
|
|
274
|
+
isLongRunningToolRunning,
|
|
275
|
+
} from "./stream-watchdog.js";
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import "../../_dnt.polyfills.js";
|
|
2
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
3
|
+
import type { ChatUiMessageChunk, MessageMetadata } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS = 120_000;
|
|
6
|
+
export const DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS = 300_000;
|
|
7
|
+
|
|
8
|
+
export type ChatStreamWatchdogPhase =
|
|
9
|
+
| "response_pending"
|
|
10
|
+
| "tool_input_streaming"
|
|
11
|
+
| "tool_running"
|
|
12
|
+
| "post_tool_idle";
|
|
13
|
+
|
|
14
|
+
export type ChatStreamWatchdogState = {
|
|
15
|
+
phase: ChatStreamWatchdogPhase;
|
|
16
|
+
timeoutMs: number;
|
|
17
|
+
toolCallId?: string;
|
|
18
|
+
toolName?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type ChatStreamWatchdogOptions = {
|
|
22
|
+
idleTimeoutMs?: number;
|
|
23
|
+
toolRunningTimeoutMs?: number;
|
|
24
|
+
longRunningToolNames?: Iterable<string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class ChatStreamIdleTimeoutError extends Error {
|
|
28
|
+
readonly state: ChatStreamWatchdogState;
|
|
29
|
+
|
|
30
|
+
constructor(state: ChatStreamWatchdogState) {
|
|
31
|
+
const toolLabel = typeof state.toolName === "string" && state.toolName.length > 0
|
|
32
|
+
? ` for ${state.toolName}${state.toolCallId ? ` (${state.toolCallId})` : ""}`
|
|
33
|
+
: state.toolCallId
|
|
34
|
+
? ` for ${state.toolCallId}`
|
|
35
|
+
: "";
|
|
36
|
+
super(`Chat stream idle timeout after ${state.timeoutMs}ms during ${state.phase}${toolLabel}`);
|
|
37
|
+
this.name = "ChatStreamIdleTimeoutError";
|
|
38
|
+
this.state = state;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function createChatStreamWatchdogState(
|
|
43
|
+
phase: ChatStreamWatchdogPhase,
|
|
44
|
+
metadata?: {
|
|
45
|
+
toolCallId?: string;
|
|
46
|
+
toolName?: string;
|
|
47
|
+
},
|
|
48
|
+
options: Pick<Required<ChatStreamWatchdogOptions>, "idleTimeoutMs" | "toolRunningTimeoutMs"> = {
|
|
49
|
+
idleTimeoutMs: DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS,
|
|
50
|
+
toolRunningTimeoutMs: DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS,
|
|
51
|
+
},
|
|
52
|
+
): ChatStreamWatchdogState {
|
|
53
|
+
return {
|
|
54
|
+
phase,
|
|
55
|
+
timeoutMs: phase === "tool_running" ? options.toolRunningTimeoutMs : options.idleTimeoutMs,
|
|
56
|
+
...(metadata?.toolCallId ? { toolCallId: metadata.toolCallId } : {}),
|
|
57
|
+
...(metadata?.toolName ? { toolName: metadata.toolName } : {}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function isLongRunningToolRunning(
|
|
62
|
+
current: ChatStreamWatchdogState,
|
|
63
|
+
longRunningToolNames: ReadonlySet<string>,
|
|
64
|
+
): boolean {
|
|
65
|
+
return (
|
|
66
|
+
current.phase === "tool_running" &&
|
|
67
|
+
typeof current.toolName === "string" &&
|
|
68
|
+
longRunningToolNames.has(current.toolName)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function getNextChatStreamWatchdogState(
|
|
73
|
+
currentState: ChatStreamWatchdogState,
|
|
74
|
+
chunk: ChatUiMessageChunk<MessageMetadata>,
|
|
75
|
+
options?: ChatStreamWatchdogOptions,
|
|
76
|
+
): ChatStreamWatchdogState {
|
|
77
|
+
const resolvedOptions = resolveChatStreamWatchdogOptions(options);
|
|
78
|
+
|
|
79
|
+
switch (chunk.type) {
|
|
80
|
+
case "tool-input-start":
|
|
81
|
+
return createChatStreamWatchdogState(
|
|
82
|
+
"tool_input_streaming",
|
|
83
|
+
{
|
|
84
|
+
toolCallId: chunk.toolCallId,
|
|
85
|
+
toolName: chunk.toolName,
|
|
86
|
+
},
|
|
87
|
+
resolvedOptions,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
case "tool-input-delta":
|
|
91
|
+
return createChatStreamWatchdogState(
|
|
92
|
+
"tool_input_streaming",
|
|
93
|
+
{
|
|
94
|
+
toolCallId: chunk.toolCallId,
|
|
95
|
+
toolName: currentState.toolCallId === chunk.toolCallId
|
|
96
|
+
? currentState.toolName
|
|
97
|
+
: undefined,
|
|
98
|
+
},
|
|
99
|
+
resolvedOptions,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
case "tool-input-available":
|
|
103
|
+
return createChatStreamWatchdogState(
|
|
104
|
+
"tool_running",
|
|
105
|
+
{
|
|
106
|
+
toolCallId: chunk.toolCallId,
|
|
107
|
+
toolName: chunk.toolName,
|
|
108
|
+
},
|
|
109
|
+
resolvedOptions,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
case "tool-output-available":
|
|
113
|
+
case "tool-output-error":
|
|
114
|
+
case "tool-output-denied":
|
|
115
|
+
return createChatStreamWatchdogState(
|
|
116
|
+
"post_tool_idle",
|
|
117
|
+
{
|
|
118
|
+
toolCallId: chunk.toolCallId,
|
|
119
|
+
toolName: currentState.toolCallId === chunk.toolCallId
|
|
120
|
+
? currentState.toolName
|
|
121
|
+
: undefined,
|
|
122
|
+
},
|
|
123
|
+
resolvedOptions,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
case "message-metadata":
|
|
127
|
+
return isLongRunningToolRunning(currentState, resolvedOptions.longRunningToolNames)
|
|
128
|
+
? currentState
|
|
129
|
+
: createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
130
|
+
|
|
131
|
+
case "finish":
|
|
132
|
+
return createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
133
|
+
|
|
134
|
+
default:
|
|
135
|
+
return isLongRunningToolRunning(currentState, resolvedOptions.longRunningToolNames)
|
|
136
|
+
? currentState
|
|
137
|
+
: createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function isHeartbeatOnlyMetadataChunk(chunk: ChatUiMessageChunk<MessageMetadata>): boolean {
|
|
142
|
+
return chunk.type === "message-metadata" && Object.keys(chunk.messageMetadata ?? {}).length === 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function createChatStreamWatchdog(options?: ChatStreamWatchdogOptions) {
|
|
146
|
+
const resolvedOptions = resolveChatStreamWatchdogOptions(options);
|
|
147
|
+
const controller = new AbortController();
|
|
148
|
+
let state = createChatStreamWatchdogState("response_pending", undefined, resolvedOptions);
|
|
149
|
+
let timer: ReturnType<typeof dntShim.setTimeout> | null = null;
|
|
150
|
+
let lastTimeoutState: ChatStreamWatchdogState | null = null;
|
|
151
|
+
|
|
152
|
+
const clearTimer = () => {
|
|
153
|
+
if (timer !== null) {
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
timer = null;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const arm = () => {
|
|
160
|
+
if (controller.signal.aborted) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
clearTimer();
|
|
165
|
+
|
|
166
|
+
if (isLongRunningToolRunning(state, resolvedOptions.longRunningToolNames)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
timer = dntShim.setTimeout(() => {
|
|
171
|
+
lastTimeoutState = state;
|
|
172
|
+
controller.abort(
|
|
173
|
+
new DOMException(new ChatStreamIdleTimeoutError(state).message, "AbortError"),
|
|
174
|
+
);
|
|
175
|
+
}, state.timeoutMs);
|
|
176
|
+
maybeUnrefTimer(timer);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
arm();
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
signal: controller.signal,
|
|
183
|
+
get lastTimeoutState(): ChatStreamWatchdogState | null {
|
|
184
|
+
return lastTimeoutState;
|
|
185
|
+
},
|
|
186
|
+
observe(chunk: ChatUiMessageChunk<MessageMetadata>) {
|
|
187
|
+
if (isHeartbeatOnlyMetadataChunk(chunk)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
state = getNextChatStreamWatchdogState(state, chunk, resolvedOptions);
|
|
192
|
+
if (chunk.type === "finish") {
|
|
193
|
+
clearTimer();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
arm();
|
|
197
|
+
},
|
|
198
|
+
dispose() {
|
|
199
|
+
clearTimer();
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function resolveChatStreamWatchdogOptions(options?: ChatStreamWatchdogOptions) {
|
|
205
|
+
return {
|
|
206
|
+
idleTimeoutMs: options?.idleTimeoutMs ?? DEFAULT_CHAT_STREAM_IDLE_TIMEOUT_MS,
|
|
207
|
+
toolRunningTimeoutMs: options?.toolRunningTimeoutMs ??
|
|
208
|
+
DEFAULT_CHAT_STREAM_TOOL_RUNNING_TIMEOUT_MS,
|
|
209
|
+
longRunningToolNames: new Set(options?.longRunningToolNames ?? ["invoke_agent"]),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function maybeUnrefTimer(timer: ReturnType<typeof dntShim.setTimeout>): void {
|
|
214
|
+
if (typeof timer !== "object" || timer === null || !("unref" in timer)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const timerWithUnref: { unref?: unknown } = timer;
|
|
219
|
+
if (typeof timerWithUnref.unref === "function") {
|
|
220
|
+
timerWithUnref.unref();
|
|
221
|
+
}
|
|
222
|
+
}
|