agents 0.25.0 → 0.27.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 +8 -9
- package/dist/{agent-routing-0DR0Tk2v.d.ts → agent-routing-Bhdbvf7s.d.ts} +13 -8
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-YrATZJu2.d.ts → agent-tools-bJZwBMfq.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/ai-sdk-OoGkFy3s.js +2444 -0
- package/dist/ai-sdk-OoGkFy3s.js.map +1 -0
- package/dist/apply-chunks-1FheRb9W.js +99 -0
- package/dist/apply-chunks-1FheRb9W.js.map +1 -0
- package/dist/broadcast-state-CEyI4uAK.js +69 -0
- package/dist/broadcast-state-CEyI4uAK.js.map +1 -0
- package/dist/browser/ai-sdk.d.ts +1 -1
- package/dist/browser/ai-sdk.js +2 -2
- package/dist/browser/ai-sdk.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/tanstack-ai.d.ts +1 -1
- package/dist/browser/tanstack-ai.js +1 -1
- package/dist/{browser-DE3d-RLk.d.ts → browser-tmkcAAI3.d.ts} +2 -2
- package/dist/{browser-tool-DuNdlwZ9.d.ts → browser-tool-Bn-nzJQI.d.ts} +3 -3
- package/dist/{browser-tool-CQ10e6Kj.js → browser-tool-CBqs6hqa.js} +58 -18
- package/dist/browser-tool-CBqs6hqa.js.map +1 -0
- package/dist/capability-B4WbF81e.js.map +1 -1
- package/dist/{capability-runner-DBAnGr6L.d.ts → capability-runner-O5VbQzqg.d.ts} +9 -1
- package/dist/channel-Bak_6zDP.d.ts +333 -0
- package/dist/chat/index.d.ts +11 -9
- package/dist/chat/index.js +5 -194
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +2 -4
- package/dist/chat/react.js +3 -1
- package/dist/chat/react.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/chat-sdk/index.js +1 -1
- package/dist/cli.js +144 -0
- package/dist/{client-fyQrLGkD.js → client-1tEQ1Oqz.js} +27 -2
- package/dist/{client-fyQrLGkD.js.map → client-1tEQ1Oqz.js.map} +1 -1
- package/dist/{client-je3koD9Z.d.ts → client-DS3Dz9l0.d.ts} +2 -2
- package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
- package/dist/client.d.ts +1 -1
- package/dist/conversations-DH0ut_8n.d.ts +192 -0
- package/dist/{current-agent-vAk_5JMt.d.ts → current-agent-C07C5o5Y.d.ts} +3 -3
- package/dist/daemon-core-Buubj-y1.js +481 -0
- package/dist/daemon-core-Buubj-y1.js.map +1 -0
- package/dist/daemon-core-CbohVPAu.d.ts +132 -0
- package/dist/{do-oauth-client-provider-Tmf1vgKz.d.ts → do-oauth-client-provider-DfsUcpc3.d.ts} +7 -1
- package/dist/{durable-object-lifecycle-HhgOMWq9.d.ts → durable-object-lifecycle-DRqp475_.d.ts} +2 -2
- package/dist/{channels/email.d.ts → experimental/channels/email/index.d.ts} +25 -12
- package/dist/{channels/email.js → experimental/channels/email/index.js} +13 -35
- package/dist/experimental/channels/email/index.js.map +1 -0
- package/dist/experimental/channels/index.d.ts +270 -0
- package/dist/experimental/channels/index.js +1186 -0
- package/dist/experimental/channels/index.js.map +1 -0
- package/dist/{channels/slack.d.ts → experimental/channels/slack/index.d.ts} +19 -9
- package/dist/experimental/channels/slack/index.js +267 -0
- package/dist/experimental/channels/slack/index.js.map +1 -0
- package/dist/{channels/telegram.d.ts → experimental/channels/telegram/index.d.ts} +19 -9
- package/dist/experimental/channels/telegram/index.js +198 -0
- package/dist/experimental/channels/telegram/index.js.map +1 -0
- package/dist/experimental/channels/web/ai-sdk.d.ts +55 -0
- package/dist/experimental/channels/web/ai-sdk.js +266 -0
- package/dist/experimental/channels/web/ai-sdk.js.map +1 -0
- package/dist/experimental/channels/web/client.d.ts +97 -0
- package/dist/experimental/channels/web/client.js +349 -0
- package/dist/experimental/channels/web/client.js.map +1 -0
- package/dist/experimental/channels/web/index.d.ts +189 -0
- package/dist/experimental/channels/web/index.js +332 -0
- package/dist/experimental/channels/web/index.js.map +1 -0
- package/dist/gateway-BDC07gYO.d.ts +100 -0
- package/dist/handle-zAzh0UW2.d.ts +460 -0
- package/dist/harness/ai-sdk/index.d.ts +175 -0
- package/dist/harness/ai-sdk/index.js +605 -0
- package/dist/harness/ai-sdk/index.js.map +1 -0
- package/dist/harness/container/daemon/index.d.ts +76 -0
- package/dist/harness/container/daemon/index.js +3 -0
- package/dist/harness/container/index.d.ts +740 -0
- package/dist/harness/container/index.js +2152 -0
- package/dist/harness/container/index.js.map +1 -0
- package/dist/harness/container/runtime/index.d.ts +144 -0
- package/dist/harness/container/runtime/index.js +1082 -0
- package/dist/harness/container/runtime/index.js.map +1 -0
- package/dist/harness/opencode/index.d.ts +369 -0
- package/dist/harness/opencode/index.js +1072 -0
- package/dist/harness/opencode/index.js.map +1 -0
- package/dist/{harnesses → harness}/pi/index.d.ts +85 -88
- package/dist/{harnesses → harness}/pi/index.js +196 -77
- package/dist/harness/pi/index.js.map +1 -0
- package/dist/harness/store/index.d.ts +24 -0
- package/dist/harness/store/index.js +2 -0
- package/dist/harness/think/index.d.ts +821 -0
- package/dist/harness/think/index.js +2529 -0
- package/dist/harness/think/index.js.map +1 -0
- package/dist/harness-B6B9S3rb.d.ts +203 -0
- package/dist/{images-iiTDSyRu.js → images-Ce9SCu3X.js} +2 -248
- package/dist/images-Ce9SCu3X.js.map +1 -0
- package/dist/{index-BreL0YrQ.d.ts → index-D0A5tbWu.d.ts} +2 -2
- package/dist/index-Ib_4dwOo.d.ts +200 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/ingress-EFbrS547.js +9 -0
- package/dist/ingress-EFbrS547.js.map +1 -0
- package/dist/input-schema-DNrpTu49.js +23 -0
- package/dist/input-schema-DNrpTu49.js.map +1 -0
- package/dist/internal-kmw70xwR.js +46 -0
- package/dist/internal-kmw70xwR.js.map +1 -0
- package/dist/internal_context.d.ts +1 -1
- package/dist/lifecycle/index.d.ts +3 -3
- package/dist/mcp/client/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/client/do-oauth-client-provider.js +9 -0
- package/dist/mcp/client/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/client/index.d.ts +1 -1
- package/dist/mcp/client/index.js +1 -1
- package/dist/mcp/client/x402.d.ts +35 -4
- package/dist/mcp/client/x402.js +24 -3
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/models/ai-sdk/index.d.ts +16 -14
- package/dist/models/ai-sdk/index.js +1 -2442
- package/dist/models/opencode/index.d.ts +65 -0
- package/dist/models/opencode/index.js +285 -0
- package/dist/models/opencode/index.js.map +1 -0
- package/dist/models/pi-ai/index.d.ts +23 -21
- package/dist/models/pi-ai/index.js +7 -6
- package/dist/models/pi-ai/index.js.map +1 -1
- package/dist/options-pwTNq9z6.d.ts +134 -0
- package/dist/protocol-BEgrJYC5.d.ts +331 -0
- package/dist/protocol-CukuI73M.d.ts +386 -0
- package/dist/protocol-cOklVBBD.js +227 -0
- package/dist/protocol-cOklVBBD.js.map +1 -0
- package/dist/{protocol-kHsr-f0X.js → protocol-eXeJxhgu.js} +2 -67
- package/dist/protocol-eXeJxhgu.js.map +1 -0
- package/dist/protocol-y2sSY584.js +148 -0
- package/dist/protocol-y2sSY584.js.map +1 -0
- package/dist/queue/index.d.ts +1 -1
- package/dist/react.d.ts +2 -2
- package/dist/routing/index.d.ts +2 -2
- package/dist/{scheduler-RdACNXDP.d.ts → scheduler-CrFCnv_J.d.ts} +2 -2
- package/dist/schedules/index.d.ts +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sessions/index.d.ts +11 -434
- package/dist/sessions/index.js +1 -2271
- package/dist/sessions-B9pNuxdT.js +2272 -0
- package/dist/sessions-B9pNuxdT.js.map +1 -0
- package/dist/settings-C45hDliX.js +253 -0
- package/dist/settings-C45hDliX.js.map +1 -0
- package/dist/{transport-PfFnt-Ld.d.ts → settings-NgGwF7Qt.d.ts} +14 -208
- package/dist/{src-BZeu-SCD.js → src-DgCbZtIR.js} +4 -4
- package/dist/{src-BZeu-SCD.js.map → src-DgCbZtIR.js.map} +1 -1
- package/dist/stall-watchdog-BpRF2uwG.js +195 -0
- package/dist/stall-watchdog-BpRF2uwG.js.map +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/store-DLeqKuj3.d.ts +310 -0
- package/dist/store-vgcPYo8K.js +432 -0
- package/dist/store-vgcPYo8K.js.map +1 -0
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/{streams-DW-UCOUc.js → streams-CITClVer.js} +16 -3
- package/dist/streams-CITClVer.js.map +1 -0
- package/dist/{streams-Cmkj9QfW.d.ts → streams-fbG61qM8.d.ts} +2 -2
- package/dist/sub-routing.d.ts +1 -1
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/{tasks-68DESxf0.js → tasks-CkTZNaV1.js} +2 -1
- package/dist/tasks-CkTZNaV1.js.map +1 -0
- package/dist/{tasks-9YxYtByh.d.ts → tasks-PtlB4Uyn.d.ts} +2 -2
- package/dist/tool-3PA8xjB_.js +421 -0
- package/dist/tool-3PA8xjB_.js.map +1 -0
- package/dist/tool-BPJEbwaX.d.ts +278 -0
- package/dist/transport-k2mFrtL8.d.ts +200 -0
- package/dist/turns-DCV3ycDl.js +317 -0
- package/dist/turns-DCV3ycDl.js.map +1 -0
- package/dist/voice/client.js +1 -1
- package/dist/voice/index.d.ts +2 -2
- package/dist/voice/index.js +1 -1
- package/dist/websearch/index.d.ts +58 -0
- package/dist/websearch/index.js +2 -0
- package/dist/websearch/tools/ai-sdk.d.ts +77 -0
- package/dist/websearch/tools/ai-sdk.js +46 -0
- package/dist/websearch/tools/ai-sdk.js.map +1 -0
- package/dist/websearch/tools/pi.d.ts +82 -0
- package/dist/websearch/tools/pi.js +89 -0
- package/dist/websearch/tools/pi.js.map +1 -0
- package/dist/websearch/tools/tanstack-ai.d.ts +71 -0
- package/dist/websearch/tools/tanstack-ai.js +46 -0
- package/dist/websearch/tools/tanstack-ai.js.map +1 -0
- package/dist/websockets/index.d.ts +12 -296
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-Ci-LZFHH.js → websockets-CmENGb-Z.js} +18 -4
- package/dist/websockets-CmENGb-Z.js.map +1 -0
- package/dist/{wire-types-CrjKvDyi.d.ts → wire-types-Cv0iwjk5.d.ts} +3 -51
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.js +1 -1
- package/docs/browse-the-web.md +3 -0
- package/docs/harnesses/pi.md +114 -32
- package/docs/harnesses/think.md +215 -0
- package/docs/index.md +4 -3
- package/docs/lifecycle.md +40 -0
- package/docs/models-pi-ai.md +5 -5
- package/docs/search-the-web.md +133 -0
- package/package.json +126 -47
- package/dist/browser-tool-CQ10e6Kj.js.map +0 -1
- package/dist/channel-Bnm4S7T2.d.ts +0 -491
- package/dist/channels/ai-sdk.d.ts +0 -46
- package/dist/channels/ai-sdk.js +0 -120
- package/dist/channels/ai-sdk.js.map +0 -1
- package/dist/channels/email.js.map +0 -1
- package/dist/channels/index.d.ts +0 -233
- package/dist/channels/index.js +0 -608
- package/dist/channels/index.js.map +0 -1
- package/dist/channels/slack.js +0 -614
- package/dist/channels/slack.js.map +0 -1
- package/dist/channels/tanstack-ai.d.ts +0 -39
- package/dist/channels/tanstack-ai.js +0 -17
- package/dist/channels/tanstack-ai.js.map +0 -1
- package/dist/channels/telegram.js +0 -427
- package/dist/channels/telegram.js.map +0 -1
- package/dist/channels/voice.d.ts +0 -45
- package/dist/channels/voice.js +0 -122
- package/dist/channels/voice.js.map +0 -1
- package/dist/harnesses/pi/index.js.map +0 -1
- package/dist/images-iiTDSyRu.js.map +0 -1
- package/dist/index-BB0kqhIz.d.ts +0 -101
- package/dist/ingress-BfetZbMO.js +0 -83
- package/dist/ingress-BfetZbMO.js.map +0 -1
- package/dist/internal-CYlgHl1l.js +0 -59
- package/dist/internal-CYlgHl1l.js.map +0 -1
- package/dist/models/ai-sdk/index.js.map +0 -1
- package/dist/protocol-kHsr-f0X.js.map +0 -1
- package/dist/sessions/index.js.map +0 -1
- package/dist/streams-DW-UCOUc.js.map +0 -1
- package/dist/surface-bZZJqBka.js +0 -17
- package/dist/surface-bZZJqBka.js.map +0 -1
- package/dist/tasks-68DESxf0.js.map +0 -1
- package/dist/tool-schema-CBjGPrsQ.js +0 -31
- package/dist/tool-schema-CBjGPrsQ.js.map +0 -1
- package/dist/websockets-Ci-LZFHH.js.map +0 -1
- package/docs/channels.md +0 -323
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { t as CHAT_MESSAGE_TYPES } from "./protocol-eXeJxhgu.js";
|
|
2
|
+
import { jsonSchema, tool } from "ai";
|
|
3
|
+
//#region src/chat/client-tools.ts
|
|
4
|
+
/**
|
|
5
|
+
* Converts client tool schemas to AI SDK tool format.
|
|
6
|
+
*
|
|
7
|
+
* By default these tools have no `execute` function — when the AI model calls
|
|
8
|
+
* them, the tool call is sent back to the client for execution.
|
|
9
|
+
*
|
|
10
|
+
* When `options.execute` is provided, each tool is built WITH an `execute` that
|
|
11
|
+
* delegates to it. This is used by the RPC path (e.g. a parent agent driving a
|
|
12
|
+
* Think sub-agent) so the model's client-tool call is resolved inline within
|
|
13
|
+
* the same turn.
|
|
14
|
+
*
|
|
15
|
+
* @param clientTools - Array of tool schemas from the client
|
|
16
|
+
* @param options - Optional `execute` delegate to run the tools inline
|
|
17
|
+
* @returns Record of AI SDK tools that can be spread into your tools object
|
|
18
|
+
*/
|
|
19
|
+
function createToolsFromClientSchemas(clientTools, options) {
|
|
20
|
+
if (!clientTools || clientTools.length === 0) return {};
|
|
21
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
22
|
+
for (const t of clientTools) {
|
|
23
|
+
if (seenNames.has(t.name)) console.warn(`[createToolsFromClientSchemas] Duplicate tool name "${t.name}" found. Later definitions will override earlier ones.`);
|
|
24
|
+
seenNames.add(t.name);
|
|
25
|
+
}
|
|
26
|
+
const execute = options?.execute;
|
|
27
|
+
const createTool = tool;
|
|
28
|
+
return Object.fromEntries(clientTools.map((t) => [t.name, createTool({
|
|
29
|
+
description: typeof t.description === "function" ? "" : t.description ?? "",
|
|
30
|
+
inputSchema: jsonSchema(t.parameters ?? { type: "object" }),
|
|
31
|
+
...execute ? { execute: (input, executeOptions) => execute({
|
|
32
|
+
toolName: t.name,
|
|
33
|
+
input,
|
|
34
|
+
toolCallId: executeOptions?.toolCallId ?? ""
|
|
35
|
+
}) } : {}
|
|
36
|
+
})]));
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/chat/parse-protocol.ts
|
|
40
|
+
/**
|
|
41
|
+
* Protocol Message Parser — typed parsing of cf_agent_chat_* WebSocket messages.
|
|
42
|
+
*
|
|
43
|
+
* Parses raw WebSocket messages into a discriminated union of protocol events.
|
|
44
|
+
* Both AIChatAgent and Think can use this instead of manual JSON.parse + type checking.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* Parse a raw WebSocket message string into a typed protocol event.
|
|
48
|
+
*
|
|
49
|
+
* Returns `null` if the message is not valid JSON or not a recognized
|
|
50
|
+
* protocol message type. Callers should fall through to the user's
|
|
51
|
+
* `onMessage` handler when `null` is returned.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const event = parseProtocolMessage(rawMessage);
|
|
56
|
+
* if (!event) return userOnMessage(connection, rawMessage);
|
|
57
|
+
*
|
|
58
|
+
* switch (event.type) {
|
|
59
|
+
* case "chat-request": { ... }
|
|
60
|
+
* case "clear": { ... }
|
|
61
|
+
* case "tool-result": { ... }
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
function parseProtocolMessage(raw) {
|
|
66
|
+
let data;
|
|
67
|
+
try {
|
|
68
|
+
data = JSON.parse(raw);
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const wireType = data.type;
|
|
73
|
+
if (!wireType) return null;
|
|
74
|
+
switch (wireType) {
|
|
75
|
+
case CHAT_MESSAGE_TYPES.USE_CHAT_REQUEST: return {
|
|
76
|
+
type: "chat-request",
|
|
77
|
+
id: data.id,
|
|
78
|
+
init: data.init ?? {}
|
|
79
|
+
};
|
|
80
|
+
case CHAT_MESSAGE_TYPES.CHAT_CLEAR: return { type: "clear" };
|
|
81
|
+
case CHAT_MESSAGE_TYPES.CHAT_REQUEST_CANCEL: return {
|
|
82
|
+
type: "cancel",
|
|
83
|
+
id: data.id
|
|
84
|
+
};
|
|
85
|
+
case CHAT_MESSAGE_TYPES.TOOL_RESULT: return {
|
|
86
|
+
type: "tool-result",
|
|
87
|
+
toolCallId: data.toolCallId,
|
|
88
|
+
toolName: data.toolName ?? "",
|
|
89
|
+
output: data.output,
|
|
90
|
+
state: data.state,
|
|
91
|
+
errorText: data.errorText,
|
|
92
|
+
autoContinue: data.autoContinue,
|
|
93
|
+
clientTools: data.clientTools
|
|
94
|
+
};
|
|
95
|
+
case CHAT_MESSAGE_TYPES.TOOL_APPROVAL: return {
|
|
96
|
+
type: "tool-approval",
|
|
97
|
+
toolCallId: data.toolCallId,
|
|
98
|
+
approved: data.approved,
|
|
99
|
+
autoContinue: data.autoContinue
|
|
100
|
+
};
|
|
101
|
+
case CHAT_MESSAGE_TYPES.STREAM_RESUME_REQUEST: return {
|
|
102
|
+
type: "stream-resume-request",
|
|
103
|
+
...typeof data.probeId === "string" ? { probeId: data.probeId } : {}
|
|
104
|
+
};
|
|
105
|
+
case CHAT_MESSAGE_TYPES.STREAM_RESUME_ACK: return {
|
|
106
|
+
type: "stream-resume-ack",
|
|
107
|
+
id: data.id
|
|
108
|
+
};
|
|
109
|
+
case CHAT_MESSAGE_TYPES.CHAT_MESSAGES: return {
|
|
110
|
+
type: "messages",
|
|
111
|
+
messages: data.messages ?? []
|
|
112
|
+
};
|
|
113
|
+
default: return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/chat/stall-watchdog.ts
|
|
118
|
+
/**
|
|
119
|
+
* Shared inactivity watchdog for UI-message streams.
|
|
120
|
+
*
|
|
121
|
+
* A model/transport stream can park indefinitely without ever throwing (a hung
|
|
122
|
+
* provider, a wedged transport). Left unguarded, the consumer read-loop waits
|
|
123
|
+
* forever. {@link iterateWithStallWatchdog} wraps such a stream so that a gap of
|
|
124
|
+
* `timeoutMs` between chunks aborts the upstream and throws
|
|
125
|
+
* {@link ChatStreamStalledError}, letting the consumer route the stall into
|
|
126
|
+
* bounded recovery (#1626) — a transient hang is retried within the existing
|
|
127
|
+
* recovery budget — while genuine in-band errors stay terminal.
|
|
128
|
+
*
|
|
129
|
+
* @internal Sibling-package support for `@cloudflare/ai-chat` and
|
|
130
|
+
* `@cloudflare/think`, not a public API. See
|
|
131
|
+
* `design/rfc-chat-recovery-foundation.md`.
|
|
132
|
+
*/
|
|
133
|
+
/**
|
|
134
|
+
* Thrown by {@link iterateWithStallWatchdog} when the inactivity watchdog fires
|
|
135
|
+
* (a model/transport stream that parks without ever throwing). Distinct from
|
|
136
|
+
* in-band model/stream errors so the read-loop catch can route a stall into
|
|
137
|
+
* bounded recovery (#1626) — a transient hang is retried within the existing
|
|
138
|
+
* recovery budget — while genuine errors stay terminal.
|
|
139
|
+
*/
|
|
140
|
+
var ChatStreamStalledError = class extends Error {
|
|
141
|
+
constructor(message) {
|
|
142
|
+
super(message);
|
|
143
|
+
this.isChatStreamStall = true;
|
|
144
|
+
this.name = "ChatStreamStalledError";
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Wrap a UI-message stream with an inactivity watchdog. If no chunk arrives
|
|
149
|
+
* within `timeoutMs`, `onStall` runs (aborting the upstream model stream) and
|
|
150
|
+
* the iterator throws, so the consumer loop exits with a terminal error
|
|
151
|
+
* instead of parking forever on a hung provider/transport. `timeoutMs <= 0`
|
|
152
|
+
* passes the source through untouched.
|
|
153
|
+
*/
|
|
154
|
+
async function* iterateWithStallWatchdog(source, timeoutMs, onStall) {
|
|
155
|
+
if (!(timeoutMs > 0)) {
|
|
156
|
+
yield* source;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
160
|
+
let selfAborted = false;
|
|
161
|
+
try {
|
|
162
|
+
while (true) {
|
|
163
|
+
let timer;
|
|
164
|
+
let stalled = false;
|
|
165
|
+
const stall = new Promise((_, reject) => {
|
|
166
|
+
timer = setTimeout(() => {
|
|
167
|
+
stalled = true;
|
|
168
|
+
reject(new ChatStreamStalledError(`Chat stream stalled: no activity for ${timeoutMs}ms; the turn was aborted by the stall watchdog.`));
|
|
169
|
+
}, timeoutMs);
|
|
170
|
+
});
|
|
171
|
+
const nextPromise = iterator.next();
|
|
172
|
+
nextPromise.catch(() => {});
|
|
173
|
+
let next;
|
|
174
|
+
try {
|
|
175
|
+
next = await Promise.race([nextPromise, stall]);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
if (stalled) {
|
|
178
|
+
selfAborted = true;
|
|
179
|
+
onStall();
|
|
180
|
+
}
|
|
181
|
+
throw err;
|
|
182
|
+
} finally {
|
|
183
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
184
|
+
}
|
|
185
|
+
if (next.done) return;
|
|
186
|
+
yield next.value;
|
|
187
|
+
}
|
|
188
|
+
} finally {
|
|
189
|
+
if (!selfAborted) await iterator.return?.(void 0).catch(() => {});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
export { createToolsFromClientSchemas as i, iterateWithStallWatchdog as n, parseProtocolMessage as r, ChatStreamStalledError as t };
|
|
194
|
+
|
|
195
|
+
//# sourceMappingURL=stall-watchdog-BpRF2uwG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stall-watchdog-BpRF2uwG.js","names":[],"sources":["../src/chat/client-tools.ts","../src/chat/parse-protocol.ts","../src/chat/stall-watchdog.ts"],"sourcesContent":["/**\n * Client tool schema handling for the cf_agent_chat protocol.\n *\n * Converts client-provided tool schemas (JSON wire format) into AI SDK\n * tool definitions. By default these tools have no `execute` function —\n * when the model calls them, the tool call is sent back to the client.\n *\n * When an `execute` delegate is supplied (e.g. a parent agent that drives a\n * Think sub-agent over RPC and can run the client tools itself), the tools are\n * built WITH an `execute` so the model's call is resolved inline within the\n * same turn instead of being surfaced as a dangling tool call.\n *\n * Used by both @cloudflare/ai-chat and @cloudflare/think.\n */\n\nimport type { JSONSchema7, Tool, ToolSet } from \"ai\";\nimport { tool, jsonSchema } from \"ai\";\n\n/**\n * Wire-format tool schema sent from the client.\n * Uses `parameters` (JSONSchema7) rather than AI SDK's `inputSchema`\n * because Zod schemas cannot be serialized over the wire.\n */\nexport type ClientToolSchema = {\n /** Unique name for the tool */\n name: string;\n /** Human-readable description of what the tool does */\n description?: Tool[\"description\"];\n /** JSON Schema defining the tool's input parameters */\n parameters?: JSONSchema7;\n};\n\n/**\n * Executes a client-defined tool and returns its output.\n *\n * Used for the RPC path (e.g. a parent agent delegating to a Think sub-agent)\n * where the caller can run the client tools itself, rather than the\n * browser/WebSocket path where results are sent back asynchronously.\n */\nexport type ClientToolExecutor = (call: {\n /** The name of the client tool the model called. */\n toolName: string;\n /** The model-generated input for the tool call. */\n input: unknown;\n /** The AI SDK tool-call id for the invocation. */\n toolCallId: string;\n}) => unknown | Promise<unknown>;\n\n/**\n * Converts client tool schemas to AI SDK tool format.\n *\n * By default these tools have no `execute` function — when the AI model calls\n * them, the tool call is sent back to the client for execution.\n *\n * When `options.execute` is provided, each tool is built WITH an `execute` that\n * delegates to it. This is used by the RPC path (e.g. a parent agent driving a\n * Think sub-agent) so the model's client-tool call is resolved inline within\n * the same turn.\n *\n * @param clientTools - Array of tool schemas from the client\n * @param options - Optional `execute` delegate to run the tools inline\n * @returns Record of AI SDK tools that can be spread into your tools object\n */\nexport function createToolsFromClientSchemas(\n clientTools?: ClientToolSchema[],\n options?: { execute?: ClientToolExecutor }\n): ToolSet {\n if (!clientTools || clientTools.length === 0) {\n return {};\n }\n\n const seenNames = new Set<string>();\n for (const t of clientTools) {\n if (seenNames.has(t.name)) {\n console.warn(\n `[createToolsFromClientSchemas] Duplicate tool name \"${t.name}\" found. Later definitions will override earlier ones.`\n );\n }\n seenNames.add(t.name);\n }\n\n const execute = options?.execute;\n // The AI SDK's `tool()` overloads infer the input type as `never` when an\n // `execute` is combined with a runtime `jsonSchema(...)`. Cast to a\n // permissive signature (same approach as `agentTool()`), since the wire\n // schema is untyped JSON.\n const createTool = tool as unknown as (config: {\n description: string | ((options: unknown) => string);\n inputSchema: ReturnType<typeof jsonSchema>;\n execute?: (\n input: unknown,\n executeOptions?: { toolCallId?: string }\n ) => unknown | Promise<unknown>;\n }) => Tool;\n\n return Object.fromEntries(\n clientTools.map((t) => [\n t.name,\n createTool({\n description:\n typeof t.description === \"function\" ? \"\" : (t.description ?? \"\"),\n inputSchema: jsonSchema(t.parameters ?? { type: \"object\" }),\n ...(execute\n ? {\n execute: (\n input: unknown,\n executeOptions?: { toolCallId?: string }\n ) =>\n execute({\n toolName: t.name,\n input,\n toolCallId: executeOptions?.toolCallId ?? \"\"\n })\n }\n : {})\n })\n ])\n );\n}\n","/**\n * Protocol Message Parser — typed parsing of cf_agent_chat_* WebSocket messages.\n *\n * Parses raw WebSocket messages into a discriminated union of protocol events.\n * Both AIChatAgent and Think can use this instead of manual JSON.parse + type checking.\n */\n\nimport { CHAT_MESSAGE_TYPES } from \"./protocol\";\n\n/**\n * Discriminated union of all incoming chat protocol events.\n *\n * Each agent handles the events it cares about and ignores the rest.\n * Returns `null` for non-JSON messages or unrecognized types.\n */\nexport type ChatProtocolEvent =\n | {\n type: \"chat-request\";\n id: string;\n init: { method?: string; body?: string; [key: string]: unknown };\n }\n | { type: \"clear\" }\n | { type: \"cancel\"; id: string }\n | {\n type: \"tool-result\";\n toolCallId: string;\n toolName: string;\n output: unknown;\n state?: string;\n errorText?: string;\n autoContinue?: boolean;\n clientTools?: Array<{\n name: string;\n description?: string;\n parameters?: unknown;\n }>;\n }\n | {\n type: \"tool-approval\";\n toolCallId: string;\n approved: boolean;\n autoContinue?: boolean;\n }\n | { type: \"stream-resume-request\"; probeId?: string }\n | { type: \"stream-resume-ack\"; id: string }\n | { type: \"messages\"; messages: unknown[] };\n\n/**\n * Parse a raw WebSocket message string into a typed protocol event.\n *\n * Returns `null` if the message is not valid JSON or not a recognized\n * protocol message type. Callers should fall through to the user's\n * `onMessage` handler when `null` is returned.\n *\n * @example\n * ```typescript\n * const event = parseProtocolMessage(rawMessage);\n * if (!event) return userOnMessage(connection, rawMessage);\n *\n * switch (event.type) {\n * case \"chat-request\": { ... }\n * case \"clear\": { ... }\n * case \"tool-result\": { ... }\n * }\n * ```\n */\nexport function parseProtocolMessage(raw: string): ChatProtocolEvent | null {\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return null;\n }\n\n const wireType = data.type as string | undefined;\n if (!wireType) return null;\n\n switch (wireType) {\n case CHAT_MESSAGE_TYPES.USE_CHAT_REQUEST:\n return {\n type: \"chat-request\",\n id: data.id as string,\n init: (data.init as { method?: string; body?: string }) ?? {}\n };\n\n case CHAT_MESSAGE_TYPES.CHAT_CLEAR:\n return { type: \"clear\" };\n\n case CHAT_MESSAGE_TYPES.CHAT_REQUEST_CANCEL:\n return { type: \"cancel\", id: data.id as string };\n\n case CHAT_MESSAGE_TYPES.TOOL_RESULT:\n return {\n type: \"tool-result\",\n toolCallId: data.toolCallId as string,\n toolName: (data.toolName as string) ?? \"\",\n output: data.output,\n state: data.state as string | undefined,\n errorText: data.errorText as string | undefined,\n autoContinue: data.autoContinue as boolean | undefined,\n clientTools: data.clientTools as\n | Array<{\n name: string;\n description?: string;\n parameters?: unknown;\n }>\n | undefined\n };\n\n case CHAT_MESSAGE_TYPES.TOOL_APPROVAL:\n return {\n type: \"tool-approval\",\n toolCallId: data.toolCallId as string,\n approved: data.approved as boolean,\n autoContinue: data.autoContinue as boolean | undefined\n };\n\n case CHAT_MESSAGE_TYPES.STREAM_RESUME_REQUEST:\n return {\n type: \"stream-resume-request\",\n ...(typeof data.probeId === \"string\" ? { probeId: data.probeId } : {})\n };\n\n case CHAT_MESSAGE_TYPES.STREAM_RESUME_ACK:\n return {\n type: \"stream-resume-ack\",\n id: data.id as string\n };\n\n case CHAT_MESSAGE_TYPES.CHAT_MESSAGES:\n return {\n type: \"messages\",\n messages: (data.messages as unknown[]) ?? []\n };\n\n default:\n return null;\n }\n}\n","/**\n * Shared inactivity watchdog for UI-message streams.\n *\n * A model/transport stream can park indefinitely without ever throwing (a hung\n * provider, a wedged transport). Left unguarded, the consumer read-loop waits\n * forever. {@link iterateWithStallWatchdog} wraps such a stream so that a gap of\n * `timeoutMs` between chunks aborts the upstream and throws\n * {@link ChatStreamStalledError}, letting the consumer route the stall into\n * bounded recovery (#1626) — a transient hang is retried within the existing\n * recovery budget — while genuine in-band errors stay terminal.\n *\n * @internal Sibling-package support for `@cloudflare/ai-chat` and\n * `@cloudflare/think`, not a public API. See\n * `design/rfc-chat-recovery-foundation.md`.\n */\n\n/**\n * Thrown by {@link iterateWithStallWatchdog} when the inactivity watchdog fires\n * (a model/transport stream that parks without ever throwing). Distinct from\n * in-band model/stream errors so the read-loop catch can route a stall into\n * bounded recovery (#1626) — a transient hang is retried within the existing\n * recovery budget — while genuine errors stay terminal.\n */\nexport class ChatStreamStalledError extends Error {\n readonly isChatStreamStall = true;\n constructor(message: string) {\n super(message);\n this.name = \"ChatStreamStalledError\";\n }\n}\n\n/**\n * Wrap a UI-message stream with an inactivity watchdog. If no chunk arrives\n * within `timeoutMs`, `onStall` runs (aborting the upstream model stream) and\n * the iterator throws, so the consumer loop exits with a terminal error\n * instead of parking forever on a hung provider/transport. `timeoutMs <= 0`\n * passes the source through untouched.\n */\nexport async function* iterateWithStallWatchdog<T>(\n source: AsyncIterable<T>,\n timeoutMs: number,\n onStall: () => void\n): AsyncGenerator<T> {\n if (!(timeoutMs > 0)) {\n yield* source;\n return;\n }\n const iterator = source[Symbol.asyncIterator]();\n // Tracks whether the watchdog itself aborted the upstream. In that case we\n // must NOT also `iterator.return()` it: cancelling the readable after the\n // abort makes the AI SDK pipeline write to an already-cancelled readable\n // (\"readable side is no longer readable\"). Letting the abort error the\n // stream is the clean path.\n let selfAborted = false;\n try {\n while (true) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let stalled = false;\n const stall = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n stalled = true;\n reject(\n new ChatStreamStalledError(\n `Chat stream stalled: no activity for ${timeoutMs}ms; the turn was aborted by the stall watchdog.`\n )\n );\n }, timeoutMs);\n });\n const nextPromise = iterator.next();\n // If the watchdog wins the race we abandon this read; aborting the\n // upstream stream makes it reject later, so pre-attach a no-op catch to\n // keep that abandoned rejection from surfacing as an unhandled rejection.\n nextPromise.catch(() => {});\n let next: IteratorResult<T>;\n try {\n next = await Promise.race([nextPromise, stall]);\n } catch (err) {\n if (stalled) {\n selfAborted = true;\n onStall();\n }\n throw err;\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n if (next.done) return;\n yield next.value;\n }\n } finally {\n // Forward early termination (consumer `break`/`throw`, e.g. an in-band\n // stream error where the abort signal is NOT set) to the source so its\n // reader is cancelled — otherwise the wrapped source would leak when the\n // consumer stops reading mid-stream. Skipped after a watchdog stall, which\n // already aborted the upstream (see `selfAborted` above).\n if (!selfAborted) {\n await iterator.return?.(undefined as never).catch(() => {});\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+DA,SAAgB,6BACd,aACA,SACS;CACT,IAAI,CAAC,eAAe,YAAY,WAAW,GACzC,OAAO,CAAC;CAGV,MAAM,4BAAY,IAAI,IAAY;CAClC,KAAK,MAAM,KAAK,aAAa;EAC3B,IAAI,UAAU,IAAI,EAAE,IAAI,GACtB,QAAQ,KACN,uDAAuD,EAAE,KAAK,uDAChE;EAEF,UAAU,IAAI,EAAE,IAAI;CACtB;CAEA,MAAM,UAAU,SAAS;CAKzB,MAAM,aAAa;CASnB,OAAO,OAAO,YACZ,YAAY,KAAK,MAAM,CACrB,EAAE,MACF,WAAW;EACT,aACE,OAAO,EAAE,gBAAgB,aAAa,KAAM,EAAE,eAAe;EAC/D,aAAa,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;EAC1D,GAAI,UACA,EACE,UACE,OACA,mBAEA,QAAQ;GACN,UAAU,EAAE;GACZ;GACA,YAAY,gBAAgB,cAAc;EAC5C,CAAC,EACL,IACA,CAAC;CACP,CAAC,CACH,CAAC,CACH;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpDA,SAAgB,qBAAqB,KAAuC;CAC1E,IAAI;CACJ,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;CAEA,MAAM,WAAW,KAAK;CACtB,IAAI,CAAC,UAAU,OAAO;CAEtB,QAAQ,UAAR;EACE,KAAK,mBAAmB,kBACtB,OAAO;GACL,MAAM;GACN,IAAI,KAAK;GACT,MAAO,KAAK,QAA+C,CAAC;EAC9D;EAEF,KAAK,mBAAmB,YACtB,OAAO,EAAE,MAAM,QAAQ;EAEzB,KAAK,mBAAmB,qBACtB,OAAO;GAAE,MAAM;GAAU,IAAI,KAAK;EAAa;EAEjD,KAAK,mBAAmB,aACtB,OAAO;GACL,MAAM;GACN,YAAY,KAAK;GACjB,UAAW,KAAK,YAAuB;GACvC,QAAQ,KAAK;GACb,OAAO,KAAK;GACZ,WAAW,KAAK;GAChB,cAAc,KAAK;GACnB,aAAa,KAAK;EAOpB;EAEF,KAAK,mBAAmB,eACtB,OAAO;GACL,MAAM;GACN,YAAY,KAAK;GACjB,UAAU,KAAK;GACf,cAAc,KAAK;EACrB;EAEF,KAAK,mBAAmB,uBACtB,OAAO;GACL,MAAM;GACN,GAAI,OAAO,KAAK,YAAY,WAAW,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EACtE;EAEF,KAAK,mBAAmB,mBACtB,OAAO;GACL,MAAM;GACN,IAAI,KAAK;EACX;EAEF,KAAK,mBAAmB,eACtB,OAAO;GACL,MAAM;GACN,UAAW,KAAK,YAA0B,CAAC;EAC7C;EAEF,SACE,OAAO;CACX;AACF;;;;;;;;;;;;;;;;;;;;;;;;;ACnHA,IAAa,yBAAb,cAA4C,MAAM;CAEhD,YAAY,SAAiB;EAC3B,MAAM,OAAO;EAFf,KAAS,oBAAoB;EAG3B,KAAK,OAAO;CACd;AACF;;;;;;;;AASA,gBAAuB,yBACrB,QACA,WACA,SACmB;CACnB,IAAI,EAAE,YAAY,IAAI;EACpB,OAAO;EACP;CACF;CACA,MAAM,WAAW,OAAO,OAAO,cAAc,CAAC;CAM9C,IAAI,cAAc;CAClB,IAAI;EACF,OAAO,MAAM;GACX,IAAI;GACJ,IAAI,UAAU;GACd,MAAM,QAAQ,IAAI,SAAgB,GAAG,WAAW;IAC9C,QAAQ,iBAAiB;KACvB,UAAU;KACV,OACE,IAAI,uBACF,wCAAwC,UAAU,gDACpD,CACF;IACF,GAAG,SAAS;GACd,CAAC;GACD,MAAM,cAAc,SAAS,KAAK;GAIlC,YAAY,YAAY,CAAC,CAAC;GAC1B,IAAI;GACJ,IAAI;IACF,OAAO,MAAM,QAAQ,KAAK,CAAC,aAAa,KAAK,CAAC;GAChD,SAAS,KAAK;IACZ,IAAI,SAAS;KACX,cAAc;KACd,QAAQ;IACV;IACA,MAAM;GACR,UAAU;IACR,IAAI,UAAU,KAAA,GAAW,aAAa,KAAK;GAC7C;GACA,IAAI,KAAK,MAAM;GACf,MAAM,KAAK;EACb;CACF,UAAU;EAMR,IAAI,CAAC,aACH,MAAM,SAAS,SAAS,KAAA,CAAkB,CAAC,CAAC,YAAY,CAAC,CAAC;CAE9D;AACF"}
|
package/dist/state/index.d.ts
CHANGED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
//#region src/harness/store/store.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* A session store for harnesses, on a Durable Object's SQLite database.
|
|
4
|
+
*
|
|
5
|
+
* Any harness that runs its agent somewhere other than the object (a
|
|
6
|
+
* container, a sandbox, a remote process) needs the same few things kept
|
|
7
|
+
* durably next to it: which sessions exist, which operations were submitted
|
|
8
|
+
* and how each one ended, and the session's history in whatever format the
|
|
9
|
+
* harness speaks. This store keeps those and nothing more. It knows no
|
|
10
|
+
* message format, no event vocabulary and no runtime: inputs, results,
|
|
11
|
+
* session state and log entries are opaque JSON that the harness parses.
|
|
12
|
+
*
|
|
13
|
+
* Three record kinds:
|
|
14
|
+
*
|
|
15
|
+
* - **Sessions**: an id, an optional parent (a fork), and one JSON state
|
|
16
|
+
* value the harness owns (model, cursors, resume handles).
|
|
17
|
+
* - **Operations**: one row per submitted operation, keyed by an
|
|
18
|
+
* idempotency id within its session, moving `queued` → `running` →
|
|
19
|
+
* `done` | `unanswered`. Transitions are guarded in SQL, so a duplicate or
|
|
20
|
+
* late transition is a no-op rather than a regression.
|
|
21
|
+
* - **Logs**: named, append-ordered streams of JSON entries per session
|
|
22
|
+
* (`"messages"`, `"engine"`, …). An entry may carry an id, and an entry
|
|
23
|
+
* written again under the same id replaces the old one in place. Entries
|
|
24
|
+
* larger than one SQLite row are split across continuation rows.
|
|
25
|
+
*
|
|
26
|
+
* The store is synchronous, like the SQL API under it, so a harness can
|
|
27
|
+
* group several writes in `transaction()` without awaiting.
|
|
28
|
+
*
|
|
29
|
+
* @experimental The API may change before it stabilizes.
|
|
30
|
+
*/
|
|
31
|
+
/** A JSON value, as the store keeps it. */
|
|
32
|
+
type JsonValue =
|
|
33
|
+
| string
|
|
34
|
+
| number
|
|
35
|
+
| boolean
|
|
36
|
+
| null
|
|
37
|
+
| readonly JsonValue[]
|
|
38
|
+
| {
|
|
39
|
+
readonly [key: string]: JsonValue;
|
|
40
|
+
};
|
|
41
|
+
/** Where an operation is in its life. */
|
|
42
|
+
type OperationStatus = "queued" | "running" | "done" | "unanswered";
|
|
43
|
+
/** A session, as stored. */
|
|
44
|
+
type SessionRecord = {
|
|
45
|
+
readonly id: string /** The session this one was forked from. */;
|
|
46
|
+
readonly parent:
|
|
47
|
+
| string
|
|
48
|
+
| undefined /** Harness-owned state. `null` until the harness writes some. */;
|
|
49
|
+
readonly state: JsonValue;
|
|
50
|
+
readonly createdAt: number;
|
|
51
|
+
readonly updatedAt: number;
|
|
52
|
+
};
|
|
53
|
+
/** One operation, as stored. */
|
|
54
|
+
type OperationRecord = {
|
|
55
|
+
readonly session: string /** The idempotency key, unique within the session. */;
|
|
56
|
+
readonly id: string /** Submission order within the whole store. */;
|
|
57
|
+
readonly seq: number;
|
|
58
|
+
readonly status: OperationStatus /** What was submitted, in the harness's format. */;
|
|
59
|
+
readonly input: JsonValue /** Harness-owned submission options and bookkeeping. */;
|
|
60
|
+
readonly meta: JsonValue /** The harness's result for a `done` operation, else `null`. */;
|
|
61
|
+
readonly result: JsonValue /** Why an `unanswered` operation ended. */;
|
|
62
|
+
readonly reason: string | undefined;
|
|
63
|
+
readonly createdAt: number;
|
|
64
|
+
readonly settledAt: number | undefined;
|
|
65
|
+
};
|
|
66
|
+
/** One log entry, as stored. */
|
|
67
|
+
type LogEntry = {
|
|
68
|
+
/** Position in the log. Stable when the entry is replaced by id. */ readonly seq: number;
|
|
69
|
+
readonly id: string | undefined;
|
|
70
|
+
readonly data: JsonValue;
|
|
71
|
+
readonly createdAt: number;
|
|
72
|
+
};
|
|
73
|
+
/** One entry to append. */
|
|
74
|
+
type LogAppend = {
|
|
75
|
+
/** Replace an existing entry with this id in place, instead of appending. */ readonly id?: string;
|
|
76
|
+
readonly data: JsonValue;
|
|
77
|
+
};
|
|
78
|
+
/** How an operation ended. */
|
|
79
|
+
type OperationOutcome =
|
|
80
|
+
| {
|
|
81
|
+
readonly status: "done";
|
|
82
|
+
readonly result: JsonValue;
|
|
83
|
+
}
|
|
84
|
+
| {
|
|
85
|
+
readonly status: "unanswered";
|
|
86
|
+
readonly reason: string;
|
|
87
|
+
};
|
|
88
|
+
/** `openHarnessStore`'s options. */
|
|
89
|
+
type HarnessStoreOptions = {
|
|
90
|
+
/**
|
|
91
|
+
* Prefix for the store's tables. Two harnesses in one object use two
|
|
92
|
+
* prefixes. Must not start with `_cf_`, which Durable Objects reserve.
|
|
93
|
+
* Default `harness_`.
|
|
94
|
+
*/
|
|
95
|
+
readonly prefix?: string;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Open the store over this object's SQLite database, creating its tables on
|
|
99
|
+
* first use. Cheap: call it once per isolate and keep the result.
|
|
100
|
+
*
|
|
101
|
+
* @param storage - The Durable Object's storage.
|
|
102
|
+
* @param options - Table prefix.
|
|
103
|
+
* @returns The store.
|
|
104
|
+
*/
|
|
105
|
+
declare function openHarnessStore(
|
|
106
|
+
storage: DurableObjectStorage,
|
|
107
|
+
options?: HarnessStoreOptions
|
|
108
|
+
): HarnessStore;
|
|
109
|
+
/**
|
|
110
|
+
* The store. Construct it with `openHarnessStore`.
|
|
111
|
+
*
|
|
112
|
+
* @experimental The API may change before it stabilizes.
|
|
113
|
+
*/
|
|
114
|
+
declare class HarnessStore {
|
|
115
|
+
#private;
|
|
116
|
+
/**
|
|
117
|
+
* @param storage - The Durable Object's storage.
|
|
118
|
+
* @param options - Table prefix.
|
|
119
|
+
*/
|
|
120
|
+
constructor(storage: DurableObjectStorage, options: HarnessStoreOptions);
|
|
121
|
+
/**
|
|
122
|
+
* Run `fn` in one storage transaction. Writes inside it commit together or
|
|
123
|
+
* not at all.
|
|
124
|
+
*
|
|
125
|
+
* @template T - What `fn` returns.
|
|
126
|
+
* @param fn - Synchronous work against this store.
|
|
127
|
+
* @returns What `fn` returned.
|
|
128
|
+
*/
|
|
129
|
+
transaction<T>(fn: () => T): T;
|
|
130
|
+
/**
|
|
131
|
+
* Create a session, or return the existing one with this id unchanged.
|
|
132
|
+
*
|
|
133
|
+
* @param input - The id, an optional parent, and the initial state.
|
|
134
|
+
* @returns The stored session.
|
|
135
|
+
*/
|
|
136
|
+
createSession(input: {
|
|
137
|
+
readonly id: string;
|
|
138
|
+
readonly parent?: string;
|
|
139
|
+
readonly state?: JsonValue;
|
|
140
|
+
}): SessionRecord;
|
|
141
|
+
/**
|
|
142
|
+
* Read one session.
|
|
143
|
+
*
|
|
144
|
+
* @param id - The session id.
|
|
145
|
+
* @returns The session, or `undefined` when there is none.
|
|
146
|
+
*/
|
|
147
|
+
session(id: string): SessionRecord | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* Every session, oldest first.
|
|
150
|
+
*
|
|
151
|
+
* @returns The sessions.
|
|
152
|
+
*/
|
|
153
|
+
sessions(): SessionRecord[];
|
|
154
|
+
/**
|
|
155
|
+
* Replace a session's harness-owned state.
|
|
156
|
+
*
|
|
157
|
+
* @param id - The session id.
|
|
158
|
+
* @param state - The new state.
|
|
159
|
+
* @returns False when there is no such session.
|
|
160
|
+
*/
|
|
161
|
+
setSessionState(id: string, state: JsonValue): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Delete a session with its operations and logs.
|
|
164
|
+
*
|
|
165
|
+
* @param id - The session id.
|
|
166
|
+
* @returns False when there was no such session.
|
|
167
|
+
*/
|
|
168
|
+
deleteSession(id: string): boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Durably queue an operation. Idempotent on `(session, id)`: a second
|
|
171
|
+
* enqueue with the same id stores nothing and returns the first record.
|
|
172
|
+
*
|
|
173
|
+
* @param input - The session, the idempotency id, the input and options.
|
|
174
|
+
* @returns The stored record, and whether this call created it.
|
|
175
|
+
*/
|
|
176
|
+
enqueue(input: {
|
|
177
|
+
readonly session: string;
|
|
178
|
+
readonly id: string;
|
|
179
|
+
readonly input: JsonValue;
|
|
180
|
+
readonly meta?: JsonValue;
|
|
181
|
+
}): {
|
|
182
|
+
readonly record: OperationRecord;
|
|
183
|
+
readonly accepted: boolean;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Read one operation.
|
|
187
|
+
*
|
|
188
|
+
* @param session - The session id.
|
|
189
|
+
* @param id - The operation id.
|
|
190
|
+
* @returns The operation, or `undefined` when there is none.
|
|
191
|
+
*/
|
|
192
|
+
operation(session: string, id: string): OperationRecord | undefined;
|
|
193
|
+
/**
|
|
194
|
+
* Operations in submission order, optionally narrowed to one session and
|
|
195
|
+
* to some statuses.
|
|
196
|
+
*
|
|
197
|
+
* @param filter - The session and statuses to keep. Default: all.
|
|
198
|
+
* @returns The matching operations, oldest first.
|
|
199
|
+
*/
|
|
200
|
+
operations(filter?: {
|
|
201
|
+
readonly session?: string;
|
|
202
|
+
readonly status?: readonly OperationStatus[];
|
|
203
|
+
}): OperationRecord[];
|
|
204
|
+
/**
|
|
205
|
+
* Move a queued operation to `running`.
|
|
206
|
+
*
|
|
207
|
+
* @param session - The session id.
|
|
208
|
+
* @param id - The operation id.
|
|
209
|
+
* @returns False when it was not queued.
|
|
210
|
+
*/
|
|
211
|
+
start(session: string, id: string): boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Move a running operation back to `queued`, to run it again.
|
|
214
|
+
*
|
|
215
|
+
* @param session - The session id.
|
|
216
|
+
* @param id - The operation id.
|
|
217
|
+
* @returns False when it was not running.
|
|
218
|
+
*/
|
|
219
|
+
requeue(session: string, id: string): boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Settle a queued or running operation.
|
|
222
|
+
*
|
|
223
|
+
* @param session - The session id.
|
|
224
|
+
* @param id - The operation id.
|
|
225
|
+
* @param outcome - How it ended.
|
|
226
|
+
* @returns False when it had already settled or does not exist.
|
|
227
|
+
*/
|
|
228
|
+
settle(session: string, id: string, outcome: OperationOutcome): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Replace an operation's harness-owned bookkeeping.
|
|
231
|
+
*
|
|
232
|
+
* @param session - The session id.
|
|
233
|
+
* @param id - The operation id.
|
|
234
|
+
* @param meta - The new value.
|
|
235
|
+
* @returns False when there is no such operation.
|
|
236
|
+
*/
|
|
237
|
+
setOperationMeta(session: string, id: string, meta: JsonValue): boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Append entries to a session's log. An entry with an id that is already
|
|
240
|
+
* in the log replaces that entry in place, keeping its position.
|
|
241
|
+
*
|
|
242
|
+
* @param session - The session id.
|
|
243
|
+
* @param log - The log's name, such as `"messages"`.
|
|
244
|
+
* @param entries - The entries, in order.
|
|
245
|
+
* @returns The position of the last entry written, or of the log's end.
|
|
246
|
+
*/
|
|
247
|
+
append(session: string, log: string, entries: readonly LogAppend[]): number;
|
|
248
|
+
/**
|
|
249
|
+
* Read a session's log in order.
|
|
250
|
+
*
|
|
251
|
+
* @param session - The session id.
|
|
252
|
+
* @param log - The log's name.
|
|
253
|
+
* @param range - Entries after position `after` (exclusive), at most `limit`.
|
|
254
|
+
* @returns The entries.
|
|
255
|
+
*/
|
|
256
|
+
read(
|
|
257
|
+
session: string,
|
|
258
|
+
log: string,
|
|
259
|
+
range?: {
|
|
260
|
+
readonly after?: number;
|
|
261
|
+
readonly limit?: number;
|
|
262
|
+
}
|
|
263
|
+
): LogEntry[];
|
|
264
|
+
/**
|
|
265
|
+
* One entry by id.
|
|
266
|
+
*
|
|
267
|
+
* @param session - The session id.
|
|
268
|
+
* @param log - The log's name.
|
|
269
|
+
* @param id - The entry id.
|
|
270
|
+
* @returns The entry, or `undefined`.
|
|
271
|
+
*/
|
|
272
|
+
entry(session: string, log: string, id: string): LogEntry | undefined;
|
|
273
|
+
/**
|
|
274
|
+
* The position of a log's last entry.
|
|
275
|
+
*
|
|
276
|
+
* @param session - The session id.
|
|
277
|
+
* @param log - The log's name.
|
|
278
|
+
* @returns The position, or 0 for an empty log.
|
|
279
|
+
*/
|
|
280
|
+
end(session: string, log: string): number;
|
|
281
|
+
/**
|
|
282
|
+
* Empty a session's log.
|
|
283
|
+
*
|
|
284
|
+
* @param session - The session id.
|
|
285
|
+
* @param log - The log's name.
|
|
286
|
+
*/
|
|
287
|
+
clear(session: string, log: string): void;
|
|
288
|
+
/**
|
|
289
|
+
* Copy one session's log onto the end of another's, keeping entry ids.
|
|
290
|
+
*
|
|
291
|
+
* @param from - The source session.
|
|
292
|
+
* @param to - The target session.
|
|
293
|
+
* @param log - The log's name.
|
|
294
|
+
*/
|
|
295
|
+
copy(from: string, to: string, log: string): void;
|
|
296
|
+
}
|
|
297
|
+
//#endregion
|
|
298
|
+
export {
|
|
299
|
+
LogEntry as a,
|
|
300
|
+
OperationStatus as c,
|
|
301
|
+
LogAppend as i,
|
|
302
|
+
SessionRecord as l,
|
|
303
|
+
HarnessStoreOptions as n,
|
|
304
|
+
OperationOutcome as o,
|
|
305
|
+
JsonValue as r,
|
|
306
|
+
OperationRecord as s,
|
|
307
|
+
HarnessStore as t,
|
|
308
|
+
openHarnessStore as u
|
|
309
|
+
};
|
|
310
|
+
//# sourceMappingURL=store-DLeqKuj3.d.ts.map
|