@lunora/agent 1.0.0-alpha.4 → 1.0.0-alpha.6
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/dist/channels.d.mts +36 -36
- package/dist/channels.d.ts +36 -36
- package/dist/component.d.mts +57 -68
- package/dist/component.d.ts +57 -68
- package/dist/inbound.d.mts +20 -20
- package/dist/inbound.d.ts +20 -20
- package/dist/index.d.mts +474 -490
- package/dist/index.d.ts +474 -490
- package/dist/naming.d.mts +19 -19
- package/dist/naming.d.ts +19 -19
- package/dist/packem_shared/types.d-boAM2Yi1.d.mts +1114 -0
- package/dist/packem_shared/types.d-boAM2Yi1.d.ts +1114 -0
- package/dist/sandbox.d.mts +126 -126
- package/dist/sandbox.d.ts +126 -126
- package/dist/telemetry/index.d.mts +103 -103
- package/dist/telemetry/index.d.ts +103 -103
- package/package.json +8 -8
- package/dist/packem_shared/types.d-BhJFTvz_.d.mts +0 -1114
- package/dist/packem_shared/types.d-BhJFTvz_.d.ts +0 -1114
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentDefinition, c as AgentCompact, d as AgentEpisodeExtract, e as AgentGraphExtract, f as AgentGenerate, g as AgentTokenSink, h as AgentRunInput, i as AgentFunctionPaths, j as AgentRunFunction, k as AgentStepLike, l as AgentStreamGenerate, m as AgentRunResult, n as AgentMessageRow, o as AgentConfig, S as SkillDefinition, p as AnyAgentTool, q as AgentAsToolOptions, r as AgentSubToolInput, b as AgentToolDefinition, s as AgentBindingSpec, t as AgentHandle, u as AgentToolConfig, v as AgentFunctionReference, w as AgentModelInput, x as SkillConfig } from "./packem_shared/types.d-
|
|
2
|
-
export type { y as AgentEmailMapper, z as AgentEmailRun, B as AgentGenerateOptions, C as AgentGenerateResult, D as AgentInstructionsContext, E as AgentLiveEvent, F as AgentMemoryOptions, G as AgentMemorySource, H as AgentMessageStatus, J as AgentOnStepFinish, K as AgentPrepareStep, L as AgentPrepareStepInput, M as AgentPrepareStepResult, N as AgentProgressEvent, O as AgentRunHandle, P as AgentStepFinishInfo, Q as AgentStepInfo, R as AgentThreadStatus, T as AgentTokenDelta, U as AgentToolCall, a as AgentToolContext, V as AgentUsage, W as AgentVoiceConfig, X as AgentWorkflowBindingLike, Y as AgentWorkflowInstanceLike } from "./packem_shared/types.d-
|
|
1
|
+
import { A as AgentDefinition, c as AgentCompact, d as AgentEpisodeExtract, e as AgentGraphExtract, f as AgentGenerate, g as AgentTokenSink, h as AgentRunInput, i as AgentFunctionPaths, j as AgentRunFunction, k as AgentStepLike, l as AgentStreamGenerate, m as AgentRunResult, n as AgentMessageRow, o as AgentConfig, S as SkillDefinition, p as AnyAgentTool, q as AgentAsToolOptions, r as AgentSubToolInput, b as AgentToolDefinition, s as AgentBindingSpec, t as AgentHandle, u as AgentToolConfig, v as AgentFunctionReference, w as AgentModelInput, x as SkillConfig } from "./packem_shared/types.d-boAM2Yi1.js";
|
|
2
|
+
export type { y as AgentEmailMapper, z as AgentEmailRun, B as AgentGenerateOptions, C as AgentGenerateResult, D as AgentInstructionsContext, E as AgentLiveEvent, F as AgentMemoryOptions, G as AgentMemorySource, H as AgentMessageStatus, J as AgentOnStepFinish, K as AgentPrepareStep, L as AgentPrepareStepInput, M as AgentPrepareStepResult, N as AgentProgressEvent, O as AgentRunHandle, P as AgentStepFinishInfo, Q as AgentStepInfo, R as AgentThreadStatus, T as AgentTokenDelta, U as AgentToolCall, a as AgentToolContext, V as AgentUsage, W as AgentVoiceConfig, X as AgentWorkflowBindingLike, Y as AgentWorkflowInstanceLike } from "./packem_shared/types.d-boAM2Yi1.js";
|
|
3
3
|
export { type AgentComponent, agentComponent, agentExtension } from "./component.js";
|
|
4
4
|
import { FlexibleSchema, LanguageModel, ModelMessage } from 'ai';
|
|
5
5
|
export { agentBindingName, agentClassName, agentDefaultName, voiceBindingName, voiceClassName } from "./naming.js";
|
|
@@ -9,95 +9,95 @@ import { WorkflowDefinition } from '@lunora/workflow';
|
|
|
9
9
|
import '@lunora/mail/inbound';
|
|
10
10
|
import '@lunora/server';
|
|
11
11
|
/**
|
|
12
|
-
* `AgentLoopOptions` is part of the experimental `@lunora/agent` API and may change without a major version bump.
|
|
13
|
-
* @experimental
|
|
14
|
-
*/
|
|
12
|
+
* `AgentLoopOptions` is part of the experimental `@lunora/agent` API and may change without a major version bump.
|
|
13
|
+
* @experimental
|
|
14
|
+
*/
|
|
15
15
|
interface AgentLoopOptions {
|
|
16
16
|
agent: AgentDefinition;
|
|
17
17
|
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
* The history-compaction seam — production wires AI SDK `generateText`.
|
|
19
|
+
* Absent (the default) disables compaction, so an agent with no `compaction`
|
|
20
|
+
* config, and every unit test that doesn't opt in, is byte-identical.
|
|
21
|
+
*/
|
|
22
22
|
compact?: AgentCompact;
|
|
23
23
|
env: Record<string, unknown>;
|
|
24
24
|
/** The agent's `lunora/agents.ts` export name (thread attribution). */
|
|
25
25
|
exportName: string;
|
|
26
26
|
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
* The run-end episode-summary seam — production wires AI SDK `generateText`.
|
|
28
|
+
* Absent (the default) disables episode recording, so an agent with no
|
|
29
|
+
* episodic memory, and every unit test that doesn't opt in, is byte-identical.
|
|
30
|
+
*/
|
|
31
31
|
extractEpisode?: AgentEpisodeExtract;
|
|
32
32
|
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
* The run-end graph-extraction seam — production wires AI SDK `generateText`
|
|
34
|
+
* with a structured `Output.object`. Absent (the default) disables
|
|
35
|
+
* extraction, so an agent with no graph memory, and every unit test that
|
|
36
|
+
* doesn't opt in, is byte-identical.
|
|
37
|
+
*/
|
|
38
38
|
extractGraph?: AgentGraphExtract;
|
|
39
39
|
/** The LLM-turn seam — production wires AI SDK `generateText`. */
|
|
40
40
|
generate: AgentGenerate;
|
|
41
41
|
/** The workflow instance id — the deterministic per-run message-key prefix. */
|
|
42
42
|
instanceId: string;
|
|
43
43
|
/**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
* Live-only sink for streamed token deltas. Supplied by the runtime (tees to
|
|
45
|
+
* the existing stream transport); when present together with
|
|
46
|
+
* {@link AgentLoopOptions.streamGenerate} each turn streams its deltas here
|
|
47
|
+
* instead of a single non-streaming `generate` call. Absent (the default)
|
|
48
|
+
* keeps the byte-identical non-streaming path. Never fired on a replay — the
|
|
49
|
+
* memoized turn skips the step body that would emit deltas.
|
|
50
|
+
*/
|
|
51
51
|
onTokenDelta?: AgentTokenSink;
|
|
52
52
|
params: AgentRunInput;
|
|
53
53
|
paths: AgentFunctionPaths;
|
|
54
54
|
run: AgentRunFunction;
|
|
55
55
|
step: AgentStepLike;
|
|
56
56
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
* The streaming LLM-turn seam — production wires AI SDK `streamText`. Used
|
|
58
|
+
* only when {@link AgentLoopOptions.onTokenDelta} is also present; otherwise
|
|
59
|
+
* the loop falls back to {@link AgentLoopOptions.generate} unchanged.
|
|
60
|
+
*/
|
|
61
61
|
streamGenerate?: AgentStreamGenerate;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* Decide the compaction split for a turn: when `compaction` is configured and the
|
|
65
|
-
* history exceeds `maxMessages`, return the `older` messages to summarize and the
|
|
66
|
-
* `recent` tail to keep verbatim (the most recent `keepRecent`, default
|
|
67
|
-
* `ceil(maxMessages / 2)`). Returns `undefined` when compaction is unset, the
|
|
68
|
-
* history is short enough, or the tail would be the whole history — a PURE
|
|
69
|
-
* decision (no I/O), unit-testable in isolation.
|
|
70
|
-
* @experimental
|
|
71
|
-
*/
|
|
64
|
+
* Decide the compaction split for a turn: when `compaction` is configured and the
|
|
65
|
+
* history exceeds `maxMessages`, return the `older` messages to summarize and the
|
|
66
|
+
* `recent` tail to keep verbatim (the most recent `keepRecent`, default
|
|
67
|
+
* `ceil(maxMessages / 2)`). Returns `undefined` when compaction is unset, the
|
|
68
|
+
* history is short enough, or the tail would be the whole history — a PURE
|
|
69
|
+
* decision (no I/O), unit-testable in isolation.
|
|
70
|
+
* @experimental
|
|
71
|
+
*/
|
|
72
72
|
declare const splitForCompaction: (history: ReadonlyArray<AgentMessageRow>, compaction: AgentConfig["compaction"]) => {
|
|
73
73
|
older: AgentMessageRow[];
|
|
74
74
|
recent: AgentMessageRow[];
|
|
75
75
|
} | undefined;
|
|
76
76
|
/**
|
|
77
|
-
* The durable tool-loop. Correctness rests on two invariants:
|
|
78
|
-
*
|
|
79
|
-
* 1. **Deterministic step names.** Each LLM turn is `llm:turn:N` (`N` = the
|
|
80
|
-
* loop index, replay-stable) and each tool call is `tool:NAME:CALL_ID`
|
|
81
|
-
* (`CALL_ID` = the provider's stable id, itself replayed from the memoized LLM
|
|
82
|
-
* step). Native `step.do` memoization then guarantees a COMPLETED step is
|
|
83
|
-
* never re-run on replay — a resumed run cannot double-charge a card. A step
|
|
84
|
-
* that FAILS mid-body is retried at-least-once; the tool receives its step
|
|
85
|
-
* name as `idempotencyKey` to dedupe on.
|
|
86
|
-
*
|
|
87
|
-
* 2. **Idempotent persistence.** Every message write is keyed
|
|
88
|
-
* `INSTANCE:ROLE:POSITION` and the append mutation dedupes on it, so a
|
|
89
|
-
* replayed persist is a no-op — the thread never duplicates.
|
|
90
|
-
*
|
|
91
|
-
* Loop control derives ONLY from persisted step outputs (never fresh
|
|
92
|
-
* `Date.now()`/`Math.random()` at the top level), so replays walk the same
|
|
93
|
-
* step-name sequence.
|
|
94
|
-
* @experimental
|
|
95
|
-
*/
|
|
77
|
+
* The durable tool-loop. Correctness rests on two invariants:
|
|
78
|
+
*
|
|
79
|
+
* 1. **Deterministic step names.** Each LLM turn is `llm:turn:N` (`N` = the
|
|
80
|
+
* loop index, replay-stable) and each tool call is `tool:NAME:CALL_ID`
|
|
81
|
+
* (`CALL_ID` = the provider's stable id, itself replayed from the memoized LLM
|
|
82
|
+
* step). Native `step.do` memoization then guarantees a COMPLETED step is
|
|
83
|
+
* never re-run on replay — a resumed run cannot double-charge a card. A step
|
|
84
|
+
* that FAILS mid-body is retried at-least-once; the tool receives its step
|
|
85
|
+
* name as `idempotencyKey` to dedupe on.
|
|
86
|
+
*
|
|
87
|
+
* 2. **Idempotent persistence.** Every message write is keyed
|
|
88
|
+
* `INSTANCE:ROLE:POSITION` and the append mutation dedupes on it, so a
|
|
89
|
+
* replayed persist is a no-op — the thread never duplicates.
|
|
90
|
+
*
|
|
91
|
+
* Loop control derives ONLY from persisted step outputs (never fresh
|
|
92
|
+
* `Date.now()`/`Math.random()` at the top level), so replays walk the same
|
|
93
|
+
* step-name sequence.
|
|
94
|
+
* @experimental
|
|
95
|
+
*/
|
|
96
96
|
declare const runAgentLoop: (options: AgentLoopOptions) => Promise<AgentRunResult>;
|
|
97
97
|
/**
|
|
98
|
-
* Input the model provides to a minted `searchMemory` tool.
|
|
99
|
-
* @experimental
|
|
100
|
-
*/
|
|
98
|
+
* Input the model provides to a minted `searchMemory` tool.
|
|
99
|
+
* @experimental
|
|
100
|
+
*/
|
|
101
101
|
interface AgentMemorySearchInput {
|
|
102
102
|
/** The natural-language query. */
|
|
103
103
|
query: string;
|
|
@@ -105,17 +105,17 @@ interface AgentMemorySearchInput {
|
|
|
105
105
|
topK?: number;
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
|
-
* Input the model provides to a minted `readMemory` tool.
|
|
109
|
-
* @experimental
|
|
110
|
-
*/
|
|
108
|
+
* Input the model provides to a minted `readMemory` tool.
|
|
109
|
+
* @experimental
|
|
110
|
+
*/
|
|
111
111
|
interface AgentMemoryReadInput {
|
|
112
112
|
/** The chunk/document id from a `searchMemory` hit. */
|
|
113
113
|
id: string;
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
|
-
* One ranked hit in a {@link AgentMemorySearchResult}.
|
|
117
|
-
* @experimental
|
|
118
|
-
*/
|
|
116
|
+
* One ranked hit in a {@link AgentMemorySearchResult}.
|
|
117
|
+
* @experimental
|
|
118
|
+
*/
|
|
119
119
|
interface AgentMemorySearchHit {
|
|
120
120
|
id: string;
|
|
121
121
|
score: number;
|
|
@@ -124,62 +124,62 @@ interface AgentMemorySearchHit {
|
|
|
124
124
|
sourceId: string;
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
|
-
* The compact shape a minted `searchMemory` tool returns to the model: ranked
|
|
128
|
-
* hits plus deduped source refs, with the giant joined `.context` string
|
|
129
|
-
* DROPPED — the model reads snippets and decides what (if anything) to pull with
|
|
130
|
-
* `readMemory`, which is the whole point of agentic (vs inject) retrieval.
|
|
131
|
-
* @experimental
|
|
132
|
-
*/
|
|
127
|
+
* The compact shape a minted `searchMemory` tool returns to the model: ranked
|
|
128
|
+
* hits plus deduped source refs, with the giant joined `.context` string
|
|
129
|
+
* DROPPED — the model reads snippets and decides what (if anything) to pull with
|
|
130
|
+
* `readMemory`, which is the whole point of agentic (vs inject) retrieval.
|
|
131
|
+
* @experimental
|
|
132
|
+
*/
|
|
133
133
|
interface AgentMemorySearchResult {
|
|
134
134
|
results: AgentMemorySearchHit[];
|
|
135
135
|
sources: ReadonlyArray<unknown>;
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
|
-
* Project a `@lunora/ai/rag` `RetrieveResult` into the compact
|
|
139
|
-
* {@link AgentMemorySearchResult} a minted `searchMemory` tool returns. Defensive
|
|
140
|
-
* against a source action that returns a differently-shaped value (the dispatch
|
|
141
|
-
* boundary is untyped): a missing `chunks`/`sources` degrades to empty.
|
|
142
|
-
* @experimental
|
|
143
|
-
*/
|
|
138
|
+
* Project a `@lunora/ai/rag` `RetrieveResult` into the compact
|
|
139
|
+
* {@link AgentMemorySearchResult} a minted `searchMemory` tool returns. Defensive
|
|
140
|
+
* against a source action that returns a differently-shaped value (the dispatch
|
|
141
|
+
* boundary is untyped): a missing `chunks`/`sources` degrades to empty.
|
|
142
|
+
* @experimental
|
|
143
|
+
*/
|
|
144
144
|
declare const toSearchResults: (retrieved: unknown, snippetChars: number) => AgentMemorySearchResult;
|
|
145
145
|
/**
|
|
146
|
-
* Mint the model-facing tools for every `mode: "agentic"` memory source — the
|
|
147
|
-
* agent's own `memory` (keyed `"default"` → `searchMemory`/`readMemory`) and
|
|
148
|
-
* each skill's `knowledge` (keyed by the skill name → `search_KEY`/`read_KEY`).
|
|
149
|
-
* An `"inject"`-mode source contributes NO tool (it stays on the auto-injection
|
|
150
|
-
* path). The returned map is folded into the agent's flat tool namespace by
|
|
151
|
-
* `defineAgent`, where a collision with a real tool throws.
|
|
152
|
-
*
|
|
153
|
-
* Walks the same two source origins as `collectMemorySources` so the two stay in
|
|
154
|
-
* lockstep; the split is deliberate — inject sources feed retrieval, agentic
|
|
155
|
-
* sources feed tools, and no source is ever on both paths.
|
|
156
|
-
* @experimental
|
|
157
|
-
*/
|
|
146
|
+
* Mint the model-facing tools for every `mode: "agentic"` memory source — the
|
|
147
|
+
* agent's own `memory` (keyed `"default"` → `searchMemory`/`readMemory`) and
|
|
148
|
+
* each skill's `knowledge` (keyed by the skill name → `search_KEY`/`read_KEY`).
|
|
149
|
+
* An `"inject"`-mode source contributes NO tool (it stays on the auto-injection
|
|
150
|
+
* path). The returned map is folded into the agent's flat tool namespace by
|
|
151
|
+
* `defineAgent`, where a collision with a real tool throws.
|
|
152
|
+
*
|
|
153
|
+
* Walks the same two source origins as `collectMemorySources` so the two stay in
|
|
154
|
+
* lockstep; the split is deliberate — inject sources feed retrieval, agentic
|
|
155
|
+
* sources feed tools, and no source is ever on both paths.
|
|
156
|
+
* @experimental
|
|
157
|
+
*/
|
|
158
158
|
declare const collectAgenticMemoryTools: (config: AgentConfig, skills: ReadonlyArray<SkillDefinition>) => Record<string, AnyAgentTool>;
|
|
159
159
|
/**
|
|
160
|
-
* Adapt a declared agent into a tool the parent's model can call: `execute`
|
|
161
|
-
* starts a CHILD run on the child agent's Workflow binding, waits for it to
|
|
162
|
-
* finish, and returns its final answer — so a supervisor agent can delegate to
|
|
163
|
-
* specialists.
|
|
164
|
-
*
|
|
165
|
-
* Replay-safety: the whole `execute` runs inside the loop's `tool:NAME:CALL_ID`
|
|
166
|
-
* durable step, so a completed sub-run is memoized and never re-run. The child
|
|
167
|
-
* `threadKey` and Workflow instance id both DERIVE from the parent's
|
|
168
|
-
* (replay-stable) `threadKey` + `toolCallId`, so a retried step reuses the same
|
|
169
|
-
* child run rather than forking a new one (idempotent create-or-get). No
|
|
170
|
-
* `Date.now()`/`Math.random()`.
|
|
171
|
-
*
|
|
172
|
-
* The child's completion is observed by POLLING `instance.status()` (Cloudflare
|
|
173
|
-
* Workflows has no in-step await-instance primitive), and the answer is read
|
|
174
|
-
* back from the child's persisted thread — the single source of truth — via the
|
|
175
|
-
* shared `agents:agentMessages` runtime function.
|
|
176
|
-
* @experimental
|
|
177
|
-
*/
|
|
160
|
+
* Adapt a declared agent into a tool the parent's model can call: `execute`
|
|
161
|
+
* starts a CHILD run on the child agent's Workflow binding, waits for it to
|
|
162
|
+
* finish, and returns its final answer — so a supervisor agent can delegate to
|
|
163
|
+
* specialists.
|
|
164
|
+
*
|
|
165
|
+
* Replay-safety: the whole `execute` runs inside the loop's `tool:NAME:CALL_ID`
|
|
166
|
+
* durable step, so a completed sub-run is memoized and never re-run. The child
|
|
167
|
+
* `threadKey` and Workflow instance id both DERIVE from the parent's
|
|
168
|
+
* (replay-stable) `threadKey` + `toolCallId`, so a retried step reuses the same
|
|
169
|
+
* child run rather than forking a new one (idempotent create-or-get). No
|
|
170
|
+
* `Date.now()`/`Math.random()`.
|
|
171
|
+
*
|
|
172
|
+
* The child's completion is observed by POLLING `instance.status()` (Cloudflare
|
|
173
|
+
* Workflows has no in-step await-instance primitive), and the answer is read
|
|
174
|
+
* back from the child's persisted thread — the single source of truth — via the
|
|
175
|
+
* shared `agents:agentMessages` runtime function.
|
|
176
|
+
* @experimental
|
|
177
|
+
*/
|
|
178
178
|
declare const agentAsTool: (options: AgentAsToolOptions) => AgentToolDefinition<AgentSubToolInput, string>;
|
|
179
179
|
/**
|
|
180
|
-
* One step of a tool-composition script — call `tool` with `input`, bind the result to `id`.
|
|
181
|
-
* @experimental
|
|
182
|
-
*/
|
|
180
|
+
* One step of a tool-composition script — call `tool` with `input`, bind the result to `id`.
|
|
181
|
+
* @experimental
|
|
182
|
+
*/
|
|
183
183
|
interface ToolScriptStep {
|
|
184
184
|
/** A stable name later steps reference the output by. */
|
|
185
185
|
id: string;
|
|
@@ -189,16 +189,16 @@ interface ToolScriptStep {
|
|
|
189
189
|
tool: string;
|
|
190
190
|
}
|
|
191
191
|
/**
|
|
192
|
-
* The model-provided input to a {@link codeTool} call.
|
|
193
|
-
* @experimental
|
|
194
|
-
*/
|
|
192
|
+
* The model-provided input to a {@link codeTool} call.
|
|
193
|
+
* @experimental
|
|
194
|
+
*/
|
|
195
195
|
interface ToolScript {
|
|
196
196
|
steps: ToolScriptStep[];
|
|
197
197
|
}
|
|
198
198
|
/**
|
|
199
|
-
* The result of running a {@link ToolScript}: each step's output plus the last one.
|
|
200
|
-
* @experimental
|
|
201
|
-
*/
|
|
199
|
+
* The result of running a {@link ToolScript}: each step's output plus the last one.
|
|
200
|
+
* @experimental
|
|
201
|
+
*/
|
|
202
202
|
interface ToolScriptResult {
|
|
203
203
|
final: unknown;
|
|
204
204
|
results: ReadonlyArray<{
|
|
@@ -207,121 +207,114 @@ interface ToolScriptResult {
|
|
|
207
207
|
}>;
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
* Author-supplied config for {@link codeTool}.
|
|
211
|
-
* @experimental
|
|
212
|
-
*/
|
|
210
|
+
* Author-supplied config for {@link codeTool}.
|
|
211
|
+
* @experimental
|
|
212
|
+
*/
|
|
213
213
|
interface CodeToolOptions {
|
|
214
214
|
/** Override the model-facing description (the default lists the available tools). */
|
|
215
215
|
description?: string;
|
|
216
216
|
/** Max steps per script (default 16). */
|
|
217
217
|
maxSteps?: number;
|
|
218
218
|
/**
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
219
|
+
* Gate a whole script behind a human approval. Default: unattended. Note the
|
|
220
|
+
* COMPOSED tools cannot carry their own approval gate — `codeTool` rejects any
|
|
221
|
+
* tool with a `needsApproval`, because a code-mode script runs its steps in one
|
|
222
|
+
* shot and can't pause mid-script to hibernate for HITL. Gate the whole script
|
|
223
|
+
* here instead. Evaluated from replay-stable input, so keep it deterministic.
|
|
224
|
+
*/
|
|
225
225
|
needsApproval?: ((input: ToolScript) => boolean) | boolean;
|
|
226
226
|
}
|
|
227
227
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
|
|
258
|
-
* }),
|
|
259
|
-
* },
|
|
260
|
-
* });
|
|
261
|
-
* // The model can now, in one turn, `findUser` then feed `{ "$from": "u", "$path": "id" }` into `recentOrders`.
|
|
262
|
-
* ```
|
|
263
|
-
* @experimental
|
|
264
|
-
*/
|
|
228
|
+
* A "code mode" tool: instead of the model calling one tool per turn, it writes a
|
|
229
|
+
* SCRIPT that composes several of the tools you hand `codeTool` — chaining a
|
|
230
|
+
* later call's input to an earlier call's output — and the whole thing runs in a
|
|
231
|
+
* single turn. This is a SAFE interpreted data-flow between whitelisted tools
|
|
232
|
+
* (no `eval`, no isolate), so it runs natively in workerd; arbitrary-code
|
|
233
|
+
* execution (the Cloudflare Worker Loader path) is a separate future mode.
|
|
234
|
+
*
|
|
235
|
+
* Each composed tool dispatches through the same durable context a normal call
|
|
236
|
+
* gets (inheriting RLS), with a per-step idempotency key. A code-mode script runs
|
|
237
|
+
* its steps in one shot and CANNOT pause mid-script for a human approval, so
|
|
238
|
+
* `codeTool` REJECTS at construction any tool carrying a `needsApproval` gate —
|
|
239
|
+
* keep approval-gated tools as normal top-level tools. Gate the whole script via
|
|
240
|
+
* `opts.needsApproval` instead.
|
|
241
|
+
*
|
|
242
|
+
* ```ts
|
|
243
|
+
* import { codeTool, defineAgent, functionTool } from "@lunora/agent";
|
|
244
|
+
*
|
|
245
|
+
* export const analyst = defineAgent({
|
|
246
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
247
|
+
* tools: {
|
|
248
|
+
* run: codeTool({
|
|
249
|
+
* findUser: functionTool("users:byEmail", { description: "Look up a user by email.", inputSchema }),
|
|
250
|
+
* recentOrders: functionTool("orders:recent", { description: "List a user's recent orders.", inputSchema }),
|
|
251
|
+
* }),
|
|
252
|
+
* },
|
|
253
|
+
* });
|
|
254
|
+
* // The model can now, in one turn, `findUser` then feed `{ "$from": "u", "$path": "id" }` into `recentOrders`.
|
|
255
|
+
* ```
|
|
256
|
+
* @experimental
|
|
257
|
+
*/
|
|
265
258
|
declare const codeTool: (tools: Record<string, AnyAgentTool>, options?: CodeToolOptions) => AgentToolDefinition<ToolScript, ToolScriptResult>;
|
|
266
259
|
/**
|
|
267
|
-
* Build the `ctx.agents` producer surface from the codegen-emitted spec list
|
|
268
|
-
* (`LUNORA_AGENTS`), mirroring the `ctx.queues` property-access pattern: each
|
|
269
|
-
* declared agent resolves its `AGENT_*` Workflow binding off `env` lazily, so
|
|
270
|
-
* a missing binding only errors when that agent is actually started.
|
|
271
|
-
*
|
|
272
|
-
* `cancel` also needs to write the thread's status, so it dispatches the agent
|
|
273
|
-
* runtime's `agentPatchThread` mutation. Production leaves `dispatch` undefined
|
|
274
|
-
* and the env-backed `createDispatchRunner` (the same runner the workflow body
|
|
275
|
-
* uses — it POSTs to `/_lunora/scheduler/dispatch`) is built on demand; tests
|
|
276
|
-
* inject a `dispatch` double.
|
|
277
|
-
* @experimental
|
|
278
|
-
*/
|
|
260
|
+
* Build the `ctx.agents` producer surface from the codegen-emitted spec list
|
|
261
|
+
* (`LUNORA_AGENTS`), mirroring the `ctx.queues` property-access pattern: each
|
|
262
|
+
* declared agent resolves its `AGENT_*` Workflow binding off `env` lazily, so
|
|
263
|
+
* a missing binding only errors when that agent is actually started.
|
|
264
|
+
*
|
|
265
|
+
* `cancel` also needs to write the thread's status, so it dispatches the agent
|
|
266
|
+
* runtime's `agentPatchThread` mutation. Production leaves `dispatch` undefined
|
|
267
|
+
* and the env-backed `createDispatchRunner` (the same runner the workflow body
|
|
268
|
+
* uses — it POSTs to `/_lunora/scheduler/dispatch`) is built on demand; tests
|
|
269
|
+
* inject a `dispatch` double.
|
|
270
|
+
* @experimental
|
|
271
|
+
*/
|
|
279
272
|
declare const createAgentContext: (env: Record<string, unknown>, specs: ReadonlyArray<AgentBindingSpec>, dispatch?: AgentRunFunction) => Record<string, AgentHandle>;
|
|
280
273
|
/**
|
|
281
|
-
* Declare a durable agent. The definition compiles onto a Cloudflare Workflow
|
|
282
|
-
* (each LLM turn and each tool call a named durable step; thread messages
|
|
283
|
-
* persisted idempotently in DO SQLite), invoked from mutations/actions via
|
|
284
|
-
* `ctx.agents.NAME.run(...)` and observed live by subscribing to the
|
|
285
|
-
* `agents:agentMessages` query.
|
|
286
|
-
*
|
|
287
|
-
* ```ts
|
|
288
|
-
* // lunora/agents.ts
|
|
289
|
-
* import { defineAgent, defineAgentTool } from "@lunora/agent";
|
|
290
|
-
*
|
|
291
|
-
* export const support = defineAgent({
|
|
292
|
-
* instructions: "You are a helpful support agent.",
|
|
293
|
-
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
294
|
-
* tools: {
|
|
295
|
-
* getWeather: defineAgentTool({
|
|
296
|
-
* description: "Look up the current weather for a city.",
|
|
297
|
-
* execute: async ({ city }, { run }) => run(api.weather.lookup, { city }),
|
|
298
|
-
* inputSchema: jsonSchema({ properties: { city: { type: "string" } }, required: ["city"], type: "object" }),
|
|
299
|
-
* }),
|
|
300
|
-
* },
|
|
301
|
-
* });
|
|
302
|
-
* ```
|
|
303
|
-
*
|
|
304
|
-
* Declaring an agent is enough — codegen auto-registers the `agents:*` runtime
|
|
305
|
-
* functions (from `agentComponent()`) and the `ctx.agents` producer surface.
|
|
306
|
-
* @experimental
|
|
307
|
-
*/
|
|
274
|
+
* Declare a durable agent. The definition compiles onto a Cloudflare Workflow
|
|
275
|
+
* (each LLM turn and each tool call a named durable step; thread messages
|
|
276
|
+
* persisted idempotently in DO SQLite), invoked from mutations/actions via
|
|
277
|
+
* `ctx.agents.NAME.run(...)` and observed live by subscribing to the
|
|
278
|
+
* `agents:agentMessages` query.
|
|
279
|
+
*
|
|
280
|
+
* ```ts
|
|
281
|
+
* // lunora/agents.ts
|
|
282
|
+
* import { defineAgent, defineAgentTool } from "@lunora/agent";
|
|
283
|
+
*
|
|
284
|
+
* export const support = defineAgent({
|
|
285
|
+
* instructions: "You are a helpful support agent.",
|
|
286
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
287
|
+
* tools: {
|
|
288
|
+
* getWeather: defineAgentTool({
|
|
289
|
+
* description: "Look up the current weather for a city.",
|
|
290
|
+
* execute: async ({ city }, { run }) => run(api.weather.lookup, { city }),
|
|
291
|
+
* inputSchema: jsonSchema({ properties: { city: { type: "string" } }, required: ["city"], type: "object" }),
|
|
292
|
+
* }),
|
|
293
|
+
* },
|
|
294
|
+
* });
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
297
|
+
* Declaring an agent is enough — codegen auto-registers the `agents:*` runtime
|
|
298
|
+
* functions (from `agentComponent()`) and the `ctx.agents` producer surface.
|
|
299
|
+
* @experimental
|
|
300
|
+
*/
|
|
308
301
|
declare const defineAgent: (config: AgentConfig) => AgentDefinition;
|
|
309
302
|
/**
|
|
310
|
-
* Runtime brand check for a {@link AgentDefinition}.
|
|
311
|
-
* @experimental
|
|
312
|
-
*/
|
|
303
|
+
* Runtime brand check for a {@link AgentDefinition}.
|
|
304
|
+
* @experimental
|
|
305
|
+
*/
|
|
313
306
|
declare const isAgentDefinition: (value: unknown) => value is AgentDefinition;
|
|
314
307
|
/**
|
|
315
|
-
* Declare an agent tool — see `AgentToolDefinition` for why `execute` runs in
|
|
316
|
-
* the loop's durable step (with an `AgentToolContext`) rather than inside the
|
|
317
|
-
* model call.
|
|
318
|
-
* @experimental
|
|
319
|
-
*/
|
|
308
|
+
* Declare an agent tool — see `AgentToolDefinition` for why `execute` runs in
|
|
309
|
+
* the loop's durable step (with an `AgentToolContext`) rather than inside the
|
|
310
|
+
* model call.
|
|
311
|
+
* @experimental
|
|
312
|
+
*/
|
|
320
313
|
declare const defineAgentTool: <Input, Output>(config: AgentToolConfig<Input, Output>) => AgentToolDefinition<Input, Output>;
|
|
321
314
|
/**
|
|
322
|
-
* Author-supplied config for {@link functionTool}.
|
|
323
|
-
* @experimental
|
|
324
|
-
*/
|
|
315
|
+
* Author-supplied config for {@link functionTool}.
|
|
316
|
+
* @experimental
|
|
317
|
+
*/
|
|
325
318
|
interface FunctionToolOptions<Input> {
|
|
326
319
|
/** What the tool does — shown to the model (the model decides from it). */
|
|
327
320
|
description: string;
|
|
@@ -329,106 +322,100 @@ interface FunctionToolOptions<Input> {
|
|
|
329
322
|
inputSchema: FlexibleSchema<Input>;
|
|
330
323
|
}
|
|
331
324
|
/**
|
|
332
|
-
* Expose any Lunora query/mutation/action as an agent tool. The returned
|
|
333
|
-
* definition's `execute` dispatches the referenced function through the loop's
|
|
334
|
-
* existing `run` seam (the workflow `ctx.run`) — so there is no bespoke wrapper
|
|
335
|
-
* per tool, and the call runs inside the loop's named durable step exactly like
|
|
336
|
-
* any other tool.
|
|
337
|
-
*
|
|
338
|
-
* ```ts
|
|
339
|
-
* import { functionTool } from "@lunora/agent";
|
|
340
|
-
* import { api } from "./_generated/api";
|
|
341
|
-
*
|
|
342
|
-
* export const support = defineAgent({
|
|
343
|
-
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
344
|
-
* tools: {
|
|
345
|
-
* lookupOrder: functionTool(api.orders.byId, {
|
|
346
|
-
* description: "Look up an order by its id.",
|
|
347
|
-
* inputSchema: jsonSchema({ properties: { id: { type: "string" } }, required: ["id"], type: "object" }),
|
|
348
|
-
* }),
|
|
349
|
-
* },
|
|
350
|
-
* });
|
|
351
|
-
* ```
|
|
352
|
-
*
|
|
353
|
-
* The function reference may be a typed `api.*` reference or a `"module:name"`
|
|
354
|
-
* path. The model-provided input is passed verbatim as the function's args, so
|
|
355
|
-
* `inputSchema` should mirror the referenced function's argument validator.
|
|
356
|
-
* @experimental
|
|
357
|
-
*/
|
|
325
|
+
* Expose any Lunora query/mutation/action as an agent tool. The returned
|
|
326
|
+
* definition's `execute` dispatches the referenced function through the loop's
|
|
327
|
+
* existing `run` seam (the workflow `ctx.run`) — so there is no bespoke wrapper
|
|
328
|
+
* per tool, and the call runs inside the loop's named durable step exactly like
|
|
329
|
+
* any other tool.
|
|
330
|
+
*
|
|
331
|
+
* ```ts
|
|
332
|
+
* import { functionTool } from "@lunora/agent";
|
|
333
|
+
* import { api } from "./_generated/api";
|
|
334
|
+
*
|
|
335
|
+
* export const support = defineAgent({
|
|
336
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
337
|
+
* tools: {
|
|
338
|
+
* lookupOrder: functionTool(api.orders.byId, {
|
|
339
|
+
* description: "Look up an order by its id.",
|
|
340
|
+
* inputSchema: jsonSchema({ properties: { id: { type: "string" } }, required: ["id"], type: "object" }),
|
|
341
|
+
* }),
|
|
342
|
+
* },
|
|
343
|
+
* });
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* The function reference may be a typed `api.*` reference or a `"module:name"`
|
|
347
|
+
* path. The model-provided input is passed verbatim as the function's args, so
|
|
348
|
+
* `inputSchema` should mirror the referenced function's argument validator.
|
|
349
|
+
* @experimental
|
|
350
|
+
*/
|
|
358
351
|
declare const functionTool: <Input extends Record<string, unknown> = Record<string, unknown>, Output = unknown>(reference: AgentFunctionReference | string, options: FunctionToolOptions<Input>) => AgentToolDefinition<Input, Output>;
|
|
359
352
|
/**
|
|
360
|
-
* Resolve the configured model against the Worker env (see `AgentModelInput`).
|
|
361
|
-
* @experimental
|
|
362
|
-
*/
|
|
353
|
+
* Resolve the configured model against the Worker env (see `AgentModelInput`).
|
|
354
|
+
* @experimental
|
|
355
|
+
*/
|
|
363
356
|
declare const resolveAgentModel: (model: AgentModelInput, env: Record<string, unknown>) => LanguageModel;
|
|
364
357
|
/**
|
|
365
|
-
* Build the production LLM-turn seam over AI SDK `generateText`. The agent's
|
|
366
|
-
* tools are exposed to the model schema-only (NO `execute`) — the model can
|
|
367
|
-
* decide to call them, but execution happens back in the loop as named
|
|
368
|
-
* durable steps, never inside the model call.
|
|
369
|
-
*
|
|
370
|
-
* The static generation settings (`temperature`, `maxOutputTokens`,
|
|
371
|
-
* `toolChoice`, `output`, `telemetry`) come off the agent config; the per-turn
|
|
372
|
-
* `activeTools` / `toolChoice` / `model` overrides (from `prepareStep`) arrive
|
|
373
|
-
* on each call. When `output` is set the model runs with `Output.object` and
|
|
374
|
-
* the parsed answer is returned alongside the text.
|
|
375
|
-
* @experimental
|
|
376
|
-
*/
|
|
358
|
+
* Build the production LLM-turn seam over AI SDK `generateText`. The agent's
|
|
359
|
+
* tools are exposed to the model schema-only (NO `execute`) — the model can
|
|
360
|
+
* decide to call them, but execution happens back in the loop as named
|
|
361
|
+
* durable steps, never inside the model call.
|
|
362
|
+
*
|
|
363
|
+
* The static generation settings (`temperature`, `maxOutputTokens`,
|
|
364
|
+
* `toolChoice`, `output`, `telemetry`) come off the agent config; the per-turn
|
|
365
|
+
* `activeTools` / `toolChoice` / `model` overrides (from `prepareStep`) arrive
|
|
366
|
+
* on each call. When `output` is set the model runs with `Output.object` and
|
|
367
|
+
* the parsed answer is returned alongside the text.
|
|
368
|
+
* @experimental
|
|
369
|
+
*/
|
|
377
370
|
declare const createAgentGenerate: (agent: AgentDefinition, env: Record<string, unknown>) => AgentGenerate;
|
|
378
371
|
/**
|
|
379
|
-
* The streaming counterpart of {@link createAgentGenerate} over AI SDK
|
|
380
|
-
* `streamText`. It tees each text delta to `onDelta` as the model produces it,
|
|
381
|
-
* then resolves the SAME {@link AgentGenerate} result the non-streaming seam
|
|
382
|
-
* returns — identical `{ text, toolCalls, usage, output }` — so the value the
|
|
383
|
-
* durable `llm:turn:N` step memoizes (and persists) is byte-for-byte unchanged
|
|
384
|
-
* whether the turn streamed or not.
|
|
385
|
-
*
|
|
386
|
-
* Deltas are live-only: the seam runs inside the turn's durable step, so a
|
|
387
|
-
* workflow replay serves the memoized final value without re-invoking it — no
|
|
388
|
-
* delta is ever re-emitted. The persisted assistant message stays the single
|
|
389
|
-
* source of truth.
|
|
390
|
-
* @experimental
|
|
391
|
-
*/
|
|
372
|
+
* The streaming counterpart of {@link createAgentGenerate} over AI SDK
|
|
373
|
+
* `streamText`. It tees each text delta to `onDelta` as the model produces it,
|
|
374
|
+
* then resolves the SAME {@link AgentGenerate} result the non-streaming seam
|
|
375
|
+
* returns — identical `{ text, toolCalls, usage, output }` — so the value the
|
|
376
|
+
* durable `llm:turn:N` step memoizes (and persists) is byte-for-byte unchanged
|
|
377
|
+
* whether the turn streamed or not.
|
|
378
|
+
*
|
|
379
|
+
* Deltas are live-only: the seam runs inside the turn's durable step, so a
|
|
380
|
+
* workflow replay serves the memoized final value without re-invoking it — no
|
|
381
|
+
* delta is ever re-emitted. The persisted assistant message stays the single
|
|
382
|
+
* source of truth.
|
|
383
|
+
* @experimental
|
|
384
|
+
*/
|
|
392
385
|
declare const createStreamGenerate: (agent: AgentDefinition, env: Record<string, unknown>) => AgentStreamGenerate;
|
|
393
386
|
/**
|
|
394
|
-
* Build the production run-end graph-extraction seam over AI SDK `generateText`
|
|
395
|
-
* with an `Output.object` setting (the non-deprecated replacement for
|
|
396
|
-
* `generateObject`, and the same structured-output path the turn seams use). It
|
|
397
|
-
* resolves the (optionally cheaper) extraction model against the env, runs the
|
|
398
|
-
* model over {@link GRAPH_EXTRACTION_SCHEMA}, and returns the parsed
|
|
399
|
-
* `{ entities, relations }`. Wired by `compileAgentWorkflow` and called inside
|
|
400
|
-
* the loop's memoized `memory:extract` step.
|
|
401
|
-
* @experimental
|
|
402
|
-
*/
|
|
387
|
+
* Build the production run-end graph-extraction seam over AI SDK `generateText`
|
|
388
|
+
* with an `Output.object` setting (the non-deprecated replacement for
|
|
389
|
+
* `generateObject`, and the same structured-output path the turn seams use). It
|
|
390
|
+
* resolves the (optionally cheaper) extraction model against the env, runs the
|
|
391
|
+
* model over {@link GRAPH_EXTRACTION_SCHEMA}, and returns the parsed
|
|
392
|
+
* `{ entities, relations }`. Wired by `compileAgentWorkflow` and called inside
|
|
393
|
+
* the loop's memoized `memory:extract` step.
|
|
394
|
+
* @experimental
|
|
395
|
+
*/
|
|
403
396
|
declare const createGraphExtract: () => AgentGraphExtract;
|
|
404
397
|
/**
|
|
405
|
-
* Build the production run-end episode-extraction seam over AI SDK `generateText`.
|
|
406
|
-
* Unlike the graph extractor this needs no structured schema — an episode is a
|
|
407
|
-
* single natural-language summary — so it returns the trimmed model text. Wired
|
|
408
|
-
* by `compileAgentWorkflow` and called inside the loop's memoized
|
|
409
|
-
* `memory:episode` step.
|
|
410
|
-
* @experimental
|
|
411
|
-
*/
|
|
398
|
+
* Build the production run-end episode-extraction seam over AI SDK `generateText`.
|
|
399
|
+
* Unlike the graph extractor this needs no structured schema — an episode is a
|
|
400
|
+
* single natural-language summary — so it returns the trimmed model text. Wired
|
|
401
|
+
* by `compileAgentWorkflow` and called inside the loop's memoized
|
|
402
|
+
* `memory:episode` step.
|
|
403
|
+
* @experimental
|
|
404
|
+
*/
|
|
412
405
|
declare const createEpisodeExtract: () => AgentEpisodeExtract;
|
|
413
406
|
/**
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
|
|
417
|
-
* memoized `llm:turn:N` step so the summarization is replay-safe.
|
|
418
|
-
*/
|
|
419
|
-
/**
|
|
420
|
-
* One text/image/… content part of an MCP `CallToolResult`.
|
|
421
|
-
* @experimental
|
|
422
|
-
*/
|
|
407
|
+
* One text/image/… content part of an MCP `CallToolResult`.
|
|
408
|
+
* @experimental
|
|
409
|
+
*/
|
|
423
410
|
interface McpContentPart {
|
|
424
411
|
[key: string]: unknown;
|
|
425
412
|
text?: string;
|
|
426
413
|
type: string;
|
|
427
414
|
}
|
|
428
415
|
/**
|
|
429
|
-
* The result of an MCP `tools/call` — the structural subset the adapter reads.
|
|
430
|
-
* @experimental
|
|
431
|
-
*/
|
|
416
|
+
* The result of an MCP `tools/call` — the structural subset the adapter reads.
|
|
417
|
+
* @experimental
|
|
418
|
+
*/
|
|
432
419
|
interface McpCallResult {
|
|
433
420
|
[key: string]: unknown;
|
|
434
421
|
content?: ReadonlyArray<McpContentPart>;
|
|
@@ -436,9 +423,9 @@ interface McpCallResult {
|
|
|
436
423
|
structuredContent?: unknown;
|
|
437
424
|
}
|
|
438
425
|
/**
|
|
439
|
-
* One entry of an MCP `tools/list` — the structural subset the adapter reads.
|
|
440
|
-
* @experimental
|
|
441
|
-
*/
|
|
426
|
+
* One entry of an MCP `tools/list` — the structural subset the adapter reads.
|
|
427
|
+
* @experimental
|
|
428
|
+
*/
|
|
442
429
|
interface McpToolInfo {
|
|
443
430
|
description?: string;
|
|
444
431
|
inputSchema: {
|
|
@@ -450,11 +437,11 @@ interface McpToolInfo {
|
|
|
450
437
|
name: string;
|
|
451
438
|
}
|
|
452
439
|
/**
|
|
453
|
-
* Structural subset of `@modelcontextprotocol/sdk`'s `Client` the adapter uses.
|
|
454
|
-
* Declaring it locally lets tests inject a mock without the real SDK (and its
|
|
455
|
-
* transport) and keeps the heavy dependency behind a lazy dynamic import.
|
|
456
|
-
* @experimental
|
|
457
|
-
*/
|
|
440
|
+
* Structural subset of `@modelcontextprotocol/sdk`'s `Client` the adapter uses.
|
|
441
|
+
* Declaring it locally lets tests inject a mock without the real SDK (and its
|
|
442
|
+
* transport) and keeps the heavy dependency behind a lazy dynamic import.
|
|
443
|
+
* @experimental
|
|
444
|
+
*/
|
|
458
445
|
interface McpClientLike {
|
|
459
446
|
callTool: (params: {
|
|
460
447
|
arguments?: Record<string, unknown>;
|
|
@@ -467,20 +454,20 @@ interface McpClientLike {
|
|
|
467
454
|
}>;
|
|
468
455
|
}
|
|
469
456
|
/**
|
|
470
|
-
* Options for {@link mcpTools}.
|
|
471
|
-
* @experimental
|
|
472
|
-
*/
|
|
457
|
+
* Options for {@link mcpTools}.
|
|
458
|
+
* @experimental
|
|
459
|
+
*/
|
|
473
460
|
interface McpToolsOptions {
|
|
474
461
|
/**
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
462
|
+
* A pre-built (already-connected) MCP client. Takes precedence over `url` —
|
|
463
|
+
* the seam tests inject, and the escape hatch for a custom transport.
|
|
464
|
+
*/
|
|
478
465
|
client?: McpClientLike;
|
|
479
466
|
/**
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
467
|
+
* A stdio command. NOT supported in the Workers runtime (stdio transports
|
|
468
|
+
* cannot run in workerd) — passing it throws unless a `client` is injected.
|
|
469
|
+
* Present so the intent is explicit rather than silently unsupported.
|
|
470
|
+
*/
|
|
484
471
|
command?: string;
|
|
485
472
|
/** Identify this client to the server on connect. Default `"lunora-agent"`. */
|
|
486
473
|
name?: string;
|
|
@@ -496,43 +483,43 @@ interface McpToolsOptions {
|
|
|
496
483
|
version?: string;
|
|
497
484
|
}
|
|
498
485
|
/**
|
|
499
|
-
* Reduce an MCP tool result to the value persisted as the tool message. A
|
|
500
|
-
* server's `structuredContent` is returned as-is; otherwise the text parts are
|
|
501
|
-
* joined. An `isError` result is returned as an error STRING (not thrown) so
|
|
502
|
-
* the next LLM turn can recover, consistent with the loop's unknown-tool path.
|
|
503
|
-
* @experimental
|
|
504
|
-
*/
|
|
486
|
+
* Reduce an MCP tool result to the value persisted as the tool message. A
|
|
487
|
+
* server's `structuredContent` is returned as-is; otherwise the text parts are
|
|
488
|
+
* joined. An `isError` result is returned as an error STRING (not thrown) so
|
|
489
|
+
* the next LLM turn can recover, consistent with the loop's unknown-tool path.
|
|
490
|
+
* @experimental
|
|
491
|
+
*/
|
|
505
492
|
declare const adaptMcpResult: (result: McpCallResult) => unknown;
|
|
506
493
|
/**
|
|
507
|
-
* Connect to an external MCP server, list its tools, and adapt each into an
|
|
508
|
-
* {@link AgentToolDefinition} — a record you spread into an agent's `tools`.
|
|
509
|
-
* Each adapted tool's `execute` calls the MCP tool through the client, and runs
|
|
510
|
-
* inside the loop's named durable step like any other tool (so a completed call
|
|
511
|
-
* is never re-run on a workflow replay).
|
|
512
|
-
*
|
|
513
|
-
* ```ts
|
|
514
|
-
* export const support = defineAgent({
|
|
515
|
-
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
516
|
-
* tools: {
|
|
517
|
-
* ...(await mcpTools({ url: "https://mcp.example.com/mcp" })),
|
|
518
|
-
* },
|
|
519
|
-
* });
|
|
520
|
-
* ```
|
|
521
|
-
*
|
|
522
|
-
* The connection is made at build time (listing tools needs it), then reused by
|
|
523
|
-
* every call. In the Workers runtime only the HTTP/SSE transports run (stdio
|
|
524
|
-
* does not) — pass `url`, or inject an already-connected `client` for a custom
|
|
525
|
-
* transport (also the test seam).
|
|
526
|
-
* @experimental
|
|
527
|
-
*/
|
|
494
|
+
* Connect to an external MCP server, list its tools, and adapt each into an
|
|
495
|
+
* {@link AgentToolDefinition} — a record you spread into an agent's `tools`.
|
|
496
|
+
* Each adapted tool's `execute` calls the MCP tool through the client, and runs
|
|
497
|
+
* inside the loop's named durable step like any other tool (so a completed call
|
|
498
|
+
* is never re-run on a workflow replay).
|
|
499
|
+
*
|
|
500
|
+
* ```ts
|
|
501
|
+
* export const support = defineAgent({
|
|
502
|
+
* model: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
503
|
+
* tools: {
|
|
504
|
+
* ...(await mcpTools({ url: "https://mcp.example.com/mcp" })),
|
|
505
|
+
* },
|
|
506
|
+
* });
|
|
507
|
+
* ```
|
|
508
|
+
*
|
|
509
|
+
* The connection is made at build time (listing tools needs it), then reused by
|
|
510
|
+
* every call. In the Workers runtime only the HTTP/SSE transports run (stdio
|
|
511
|
+
* does not) — pass `url`, or inject an already-connected `client` for a custom
|
|
512
|
+
* transport (also the test seam).
|
|
513
|
+
* @experimental
|
|
514
|
+
*/
|
|
528
515
|
declare const mcpTools: (options: McpToolsOptions) => Promise<Record<string, AgentToolDefinition<Record<string, unknown>>>>;
|
|
529
516
|
/**
|
|
530
|
-
* Assemble the AI SDK conversation for one LLM turn: instructions, then the
|
|
531
|
-
* retrieved memory context (when any), then the persisted thread history with
|
|
532
|
-
* tool calls/results correlated the way providers expect (assistant tool-call
|
|
533
|
-
* parts answered by tool-result parts sharing the `toolCallId`).
|
|
534
|
-
* @experimental
|
|
535
|
-
*/
|
|
517
|
+
* Assemble the AI SDK conversation for one LLM turn: instructions, then the
|
|
518
|
+
* retrieved memory context (when any), then the persisted thread history with
|
|
519
|
+
* tool calls/results correlated the way providers expect (assistant tool-call
|
|
520
|
+
* parts answered by tool-result parts sharing the `toolCallId`).
|
|
521
|
+
* @experimental
|
|
522
|
+
*/
|
|
536
523
|
declare const buildModelMessages: (options: {
|
|
537
524
|
history: ReadonlyArray<AgentMessageRow>;
|
|
538
525
|
instructions?: string;
|
|
@@ -540,79 +527,79 @@ declare const buildModelMessages: (options: {
|
|
|
540
527
|
summary?: string;
|
|
541
528
|
}) => ModelMessage[];
|
|
542
529
|
/**
|
|
543
|
-
* The namespace the agent runtime functions register under. Codegen
|
|
544
|
-
* auto-registers `agentComponent().functions` here whenever `lunora/agents.ts`
|
|
545
|
-
* declares an agent, so the loop's dispatch paths below hold by construction.
|
|
546
|
-
* @experimental
|
|
547
|
-
*/
|
|
530
|
+
* The namespace the agent runtime functions register under. Codegen
|
|
531
|
+
* auto-registers `agentComponent().functions` here whenever `lunora/agents.ts`
|
|
532
|
+
* declares an agent, so the loop's dispatch paths below hold by construction.
|
|
533
|
+
* @experimental
|
|
534
|
+
*/
|
|
548
535
|
declare const AGENT_MODULE = "agents";
|
|
549
536
|
/**
|
|
550
|
-
* The namespace + name the batteries-included sandbox dispatcher registers
|
|
551
|
-
* under. Codegen auto-registers `sandboxComponent().invoke` here whenever
|
|
552
|
-
* `lunora/` imports a sandbox tool (`browserTool`/`containerTool`), so the
|
|
553
|
-
* tools' `execute` can dispatch to it through the loop's `run` seam.
|
|
554
|
-
* @experimental
|
|
555
|
-
*/
|
|
537
|
+
* The namespace + name the batteries-included sandbox dispatcher registers
|
|
538
|
+
* under. Codegen auto-registers `sandboxComponent().invoke` here whenever
|
|
539
|
+
* `lunora/` imports a sandbox tool (`browserTool`/`containerTool`), so the
|
|
540
|
+
* tools' `execute` can dispatch to it through the loop's `run` seam.
|
|
541
|
+
* @experimental
|
|
542
|
+
*/
|
|
556
543
|
declare const SANDBOX_MODULE = "sandbox";
|
|
557
544
|
/**
|
|
558
|
-
* The dispatch path of the sandbox runtime action (an internal action).
|
|
559
|
-
* @experimental
|
|
560
|
-
*/
|
|
545
|
+
* The dispatch path of the sandbox runtime action (an internal action).
|
|
546
|
+
* @experimental
|
|
547
|
+
*/
|
|
561
548
|
declare const SANDBOX_INVOKE_PATH: "sandbox:invoke";
|
|
562
549
|
/**
|
|
563
|
-
* Default dispatch paths of the agent runtime functions.
|
|
564
|
-
* @experimental
|
|
565
|
-
*/
|
|
550
|
+
* Default dispatch paths of the agent runtime functions.
|
|
551
|
+
* @experimental
|
|
552
|
+
*/
|
|
566
553
|
declare const DEFAULT_AGENT_FUNCTION_PATHS: AgentFunctionPaths;
|
|
567
554
|
/**
|
|
568
|
-
* Mint a dispatchable function reference from a path (or pass one through).
|
|
569
|
-
* @experimental
|
|
570
|
-
*/
|
|
555
|
+
* Mint a dispatchable function reference from a path (or pass one through).
|
|
556
|
+
* @experimental
|
|
557
|
+
*/
|
|
571
558
|
declare const toFunctionReference: (source: AgentFunctionReference | string) => AgentFunctionReference;
|
|
572
559
|
/**
|
|
573
|
-
* Declare a reusable skill: a bundle of expertise — an instruction fragment,
|
|
574
|
-
* tools, and retrieval `knowledge` — an agent composes in via
|
|
575
|
-
* `defineAgent({ skills: [...] })`. Reuse-first: a skill's `tools` carry the
|
|
576
|
-
* SAME `AnyAgentTool` shape agents already use (`functionTool` / `mcpTools` /
|
|
577
|
-
* `agentAsTool`), and `knowledge` reuses `memory`'s `AgentMemoryOptions`
|
|
578
|
-
* retrieval verbatim.
|
|
579
|
-
*
|
|
580
|
-
* ```ts
|
|
581
|
-
* import { defineSkill, functionTool } from "@lunora/agent";
|
|
582
|
-
*
|
|
583
|
-
* export const billing = defineSkill({
|
|
584
|
-
* name: "billing",
|
|
585
|
-
* instructions: "When asked about invoices, cite the invoice id.",
|
|
586
|
-
* knowledge: { source: "rag:searchBillingDocs", topK: 4 },
|
|
587
|
-
* tools: {
|
|
588
|
-
* lookupInvoice: functionTool(api.billing.invoiceById, {
|
|
589
|
-
* description: "Look up an invoice by id.",
|
|
590
|
-
* inputSchema: jsonSchema({ properties: { id: { type: "string" } }, required: ["id"], type: "object" }),
|
|
591
|
-
* }),
|
|
592
|
-
* },
|
|
593
|
-
* });
|
|
594
|
-
* ```
|
|
595
|
-
*
|
|
596
|
-
* The merge into the agent's flat namespace (tool-name collisions, instruction
|
|
597
|
-
* ordering, per-skill knowledge retrieval) happens in `defineAgent` — a skill
|
|
598
|
-
* only validates its own `name`; tool-name validation is deferred to the merge,
|
|
599
|
-
* which owns the flat model-facing namespace.
|
|
600
|
-
* @experimental
|
|
601
|
-
*/
|
|
560
|
+
* Declare a reusable skill: a bundle of expertise — an instruction fragment,
|
|
561
|
+
* tools, and retrieval `knowledge` — an agent composes in via
|
|
562
|
+
* `defineAgent({ skills: [...] })`. Reuse-first: a skill's `tools` carry the
|
|
563
|
+
* SAME `AnyAgentTool` shape agents already use (`functionTool` / `mcpTools` /
|
|
564
|
+
* `agentAsTool`), and `knowledge` reuses `memory`'s `AgentMemoryOptions`
|
|
565
|
+
* retrieval verbatim.
|
|
566
|
+
*
|
|
567
|
+
* ```ts
|
|
568
|
+
* import { defineSkill, functionTool } from "@lunora/agent";
|
|
569
|
+
*
|
|
570
|
+
* export const billing = defineSkill({
|
|
571
|
+
* name: "billing",
|
|
572
|
+
* instructions: "When asked about invoices, cite the invoice id.",
|
|
573
|
+
* knowledge: { source: "rag:searchBillingDocs", topK: 4 },
|
|
574
|
+
* tools: {
|
|
575
|
+
* lookupInvoice: functionTool(api.billing.invoiceById, {
|
|
576
|
+
* description: "Look up an invoice by id.",
|
|
577
|
+
* inputSchema: jsonSchema({ properties: { id: { type: "string" } }, required: ["id"], type: "object" }),
|
|
578
|
+
* }),
|
|
579
|
+
* },
|
|
580
|
+
* });
|
|
581
|
+
* ```
|
|
582
|
+
*
|
|
583
|
+
* The merge into the agent's flat namespace (tool-name collisions, instruction
|
|
584
|
+
* ordering, per-skill knowledge retrieval) happens in `defineAgent` — a skill
|
|
585
|
+
* only validates its own `name`; tool-name validation is deferred to the merge,
|
|
586
|
+
* which owns the flat model-facing namespace.
|
|
587
|
+
* @experimental
|
|
588
|
+
*/
|
|
602
589
|
declare const defineSkill: (config: SkillConfig) => SkillDefinition;
|
|
603
590
|
/**
|
|
604
|
-
* Runtime brand check for a {@link SkillDefinition}.
|
|
605
|
-
* @experimental
|
|
606
|
-
*/
|
|
591
|
+
* Runtime brand check for a {@link SkillDefinition}.
|
|
592
|
+
* @experimental
|
|
593
|
+
*/
|
|
607
594
|
declare const isSkillDefinition: (value: unknown) => value is SkillDefinition;
|
|
608
595
|
/**
|
|
609
|
-
* A control frame the server sends the client as a JSON text message (audio
|
|
610
|
-
* rides separate binary frames). `ready` announces the negotiated codec on
|
|
611
|
-
* connect; `user_transcript` carries the STT result; `assistant_delta` streams
|
|
612
|
-
* the live LLM text; `assistant_done` is the final turn text; `interrupted`
|
|
613
|
-
* acks a barge-in; `error` reports a non-fatal turn failure.
|
|
614
|
-
* @experimental
|
|
615
|
-
*/
|
|
596
|
+
* A control frame the server sends the client as a JSON text message (audio
|
|
597
|
+
* rides separate binary frames). `ready` announces the negotiated codec on
|
|
598
|
+
* connect; `user_transcript` carries the STT result; `assistant_delta` streams
|
|
599
|
+
* the live LLM text; `assistant_done` is the final turn text; `interrupted`
|
|
600
|
+
* acks a barge-in; `error` reports a non-fatal turn failure.
|
|
601
|
+
* @experimental
|
|
602
|
+
*/
|
|
616
603
|
type VoiceServerFrame = {
|
|
617
604
|
audioFormat: "mp3" | "wav";
|
|
618
605
|
type: "ready";
|
|
@@ -632,9 +619,9 @@ type VoiceServerFrame = {
|
|
|
632
619
|
type: "interrupted";
|
|
633
620
|
};
|
|
634
621
|
/**
|
|
635
|
-
* A control frame the client sends the server (audio rides separate binary frames).
|
|
636
|
-
* @experimental
|
|
637
|
-
*/
|
|
622
|
+
* A control frame the client sends the server (audio rides separate binary frames).
|
|
623
|
+
* @experimental
|
|
624
|
+
*/
|
|
638
625
|
type VoiceClientFrame = {
|
|
639
626
|
text: string;
|
|
640
627
|
type: "text";
|
|
@@ -644,34 +631,34 @@ type VoiceClientFrame = {
|
|
|
644
631
|
type: "interrupt";
|
|
645
632
|
};
|
|
646
633
|
/**
|
|
647
|
-
* A synthesized-audio source the TTS seam yields — normalized to bytes by {@link toByteIterable}.
|
|
648
|
-
* @experimental
|
|
649
|
-
*/
|
|
634
|
+
* A synthesized-audio source the TTS seam yields — normalized to bytes by {@link toByteIterable}.
|
|
635
|
+
* @experimental
|
|
636
|
+
*/
|
|
650
637
|
type VoiceAudioSource = AsyncIterable<Uint8Array> | ReadableStream<Uint8Array> | Uint8Array;
|
|
651
638
|
/**
|
|
652
|
-
* Transcribe one buffered utterance (16kHz mono 16-bit PCM) to text.
|
|
653
|
-
* @experimental
|
|
654
|
-
*/
|
|
639
|
+
* Transcribe one buffered utterance (16kHz mono 16-bit PCM) to text.
|
|
640
|
+
* @experimental
|
|
641
|
+
*/
|
|
655
642
|
type VoiceTranscribe = (pcm: Uint8Array) => Promise<string>;
|
|
656
643
|
/**
|
|
657
|
-
* Synthesize one sentence to an audio byte stream; honors `signal` for barge-in.
|
|
658
|
-
* @experimental
|
|
659
|
-
*/
|
|
644
|
+
* Synthesize one sentence to an audio byte stream; honors `signal` for barge-in.
|
|
645
|
+
* @experimental
|
|
646
|
+
*/
|
|
660
647
|
type VoiceSynthesize = (text: string, signal: AbortSignal) => Promise<VoiceAudioSource>;
|
|
661
648
|
/**
|
|
662
|
-
* Send a JSON control frame to the client.
|
|
663
|
-
* @experimental
|
|
664
|
-
*/
|
|
649
|
+
* Send a JSON control frame to the client.
|
|
650
|
+
* @experimental
|
|
651
|
+
*/
|
|
665
652
|
type VoiceSend = (frame: VoiceServerFrame) => void;
|
|
666
653
|
/**
|
|
667
|
-
* Send a binary audio frame to the client.
|
|
668
|
-
* @experimental
|
|
669
|
-
*/
|
|
654
|
+
* Send a binary audio frame to the client.
|
|
655
|
+
* @experimental
|
|
656
|
+
*/
|
|
670
657
|
type VoiceSendAudio = (bytes: Uint8Array) => void;
|
|
671
658
|
/**
|
|
672
|
-
* The outcome of one voice turn.
|
|
673
|
-
* @experimental
|
|
674
|
-
*/
|
|
659
|
+
* The outcome of one voice turn.
|
|
660
|
+
* @experimental
|
|
661
|
+
*/
|
|
675
662
|
interface VoiceTurnResult {
|
|
676
663
|
/** The final assistant text (may be partial if `interrupted`). */
|
|
677
664
|
assistantText: string;
|
|
@@ -681,9 +668,9 @@ interface VoiceTurnResult {
|
|
|
681
668
|
userText: string;
|
|
682
669
|
}
|
|
683
670
|
/**
|
|
684
|
-
* Options for one {@link runVoiceTurn}.
|
|
685
|
-
* @experimental
|
|
686
|
-
*/
|
|
671
|
+
* Options for one {@link runVoiceTurn}.
|
|
672
|
+
* @experimental
|
|
673
|
+
*/
|
|
687
674
|
interface RunVoiceTurnOptions {
|
|
688
675
|
/** The agent whose thread + models back this session. */
|
|
689
676
|
agent: AgentDefinition;
|
|
@@ -722,24 +709,21 @@ interface RunVoiceTurnOptions {
|
|
|
722
709
|
/** Optional outbound-audio backpressure: awaited before each audio frame so a slow client can't balloon DO memory. Never throws. */
|
|
723
710
|
waitForDrain?: () => Promise<void>;
|
|
724
711
|
}
|
|
725
|
-
/**
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
*
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
738
|
-
|
|
739
|
-
* @experimental
|
|
740
|
-
*/
|
|
712
|
+
/**
|
|
713
|
+
* Run one conversational voice turn IN-DO: transcribe the utterance (or take the
|
|
714
|
+
* typed text), persist the user turn onto the SHARED agent thread, stream the
|
|
715
|
+
* assistant reply, and synthesize it sentence-by-sentence back to the client —
|
|
716
|
+
* TTS overlapping generation, both cancellable by a barge-in `signal`.
|
|
717
|
+
*
|
|
718
|
+
* This is NOT the replay-durable Workflow tool-loop: a voice turn is
|
|
719
|
+
* conversational only (no tools in v1) and not replay-safe. Persistence stays
|
|
720
|
+
* idempotent by `voice:{connectionId}:{turn}:{role}` message keys so a resent
|
|
721
|
+
* frame never duplicates a row; the thread tables are the same ones the durable
|
|
722
|
+
* agent loop and `useAgentChat` read, so a voice session and a text session on
|
|
723
|
+
* the same `threadKey` share one history.
|
|
724
|
+
* @experimental
|
|
725
|
+
*/
|
|
741
726
|
declare const runVoiceTurn: (options: RunVoiceTurnOptions) => Promise<VoiceTurnResult>;
|
|
742
|
-
/** Parse the JSON identity envelope forwarded on the `x-lunora-identity` upgrade header. */
|
|
743
727
|
/** Structural subset of `DurableObjectState` the voice DO needs (typed locally for unit doubles). */
|
|
744
728
|
interface VoiceSessionState {
|
|
745
729
|
acceptWebSocket: (ws: WebSocket, tags?: string[]) => void;
|
|
@@ -747,21 +731,21 @@ interface VoiceSessionState {
|
|
|
747
731
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
748
732
|
}
|
|
749
733
|
/**
|
|
750
|
-
* A hibernatable-WebSocket Durable Object that runs an agent's real-time VOICE
|
|
751
|
-
* session. One instance per `threadKey`: the client opens a WebSocket, streams
|
|
752
|
-
* 16kHz mono PCM as binary frames, and marks utterance boundaries with a JSON
|
|
753
|
-
* `{ type: "commit" }` control frame; the DO transcribes the utterance, streams
|
|
754
|
-
* the agent's reply through the LLM, and synthesizes it back as MP3 binary
|
|
755
|
-
* frames — all IN-DO. It SHARES the agent's `agent_threads`/`agent_messages`
|
|
756
|
-
* tables through the same runtime dispatch seam the durable loop uses, so voice
|
|
757
|
-
* and text turns interleave on one history.
|
|
758
|
-
*
|
|
759
|
-
* Codegen emits a thin subclass per voice-enabled agent (e.g.
|
|
760
|
-
* `SupportVoiceDO extends VoiceSessionDO`, constructed with the agent
|
|
761
|
-
* definition + its export name) bound under the agent's `VOICE_...` Durable
|
|
762
|
-
* Object binding.
|
|
763
|
-
* @experimental
|
|
764
|
-
*/
|
|
734
|
+
* A hibernatable-WebSocket Durable Object that runs an agent's real-time VOICE
|
|
735
|
+
* session. One instance per `threadKey`: the client opens a WebSocket, streams
|
|
736
|
+
* 16kHz mono PCM as binary frames, and marks utterance boundaries with a JSON
|
|
737
|
+
* `{ type: "commit" }` control frame; the DO transcribes the utterance, streams
|
|
738
|
+
* the agent's reply through the LLM, and synthesizes it back as MP3 binary
|
|
739
|
+
* frames — all IN-DO. It SHARES the agent's `agent_threads`/`agent_messages`
|
|
740
|
+
* tables through the same runtime dispatch seam the durable loop uses, so voice
|
|
741
|
+
* and text turns interleave on one history.
|
|
742
|
+
*
|
|
743
|
+
* Codegen emits a thin subclass per voice-enabled agent (e.g.
|
|
744
|
+
* `SupportVoiceDO extends VoiceSessionDO`, constructed with the agent
|
|
745
|
+
* definition + its export name) bound under the agent's `VOICE_...` Durable
|
|
746
|
+
* Object binding.
|
|
747
|
+
* @experimental
|
|
748
|
+
*/
|
|
765
749
|
declare class VoiceSessionDO {
|
|
766
750
|
protected readonly agent: AgentDefinition;
|
|
767
751
|
protected readonly ai: ReturnType<typeof createAi>;
|
|
@@ -785,11 +769,11 @@ declare class VoiceSessionDO {
|
|
|
785
769
|
/** Abort any in-flight turn + free the socket's buffers on error. Never throws. */
|
|
786
770
|
webSocketError(ws: WebSocket): void;
|
|
787
771
|
/**
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
772
|
+
* The runtime dispatch seam reaching the shared agent thread functions. When
|
|
773
|
+
* the socket carries a verified identity it is forwarded so the `agents:*`
|
|
774
|
+
* thread writes are attributed to the caller (RLS / row ownership) rather
|
|
775
|
+
* than the anonymous system dispatch.
|
|
776
|
+
*/
|
|
793
777
|
protected resolveRun(userId?: string, claims?: Record<string, unknown>): AgentRunFunction;
|
|
794
778
|
/** Production STT seam: WAV-wrap the utterance and run the batch transcription model. */
|
|
795
779
|
protected transcribe(pcm: Uint8Array): Promise<string>;
|
|
@@ -814,34 +798,34 @@ declare class VoiceSessionDO {
|
|
|
814
798
|
/** Send a binary audio frame, swallowing a closed-socket error. */
|
|
815
799
|
private sendAudio;
|
|
816
800
|
/**
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
801
|
+
* Outbound backpressure: if the socket exposes `bufferedAmount`, yield in
|
|
802
|
+
* short polls until the send buffer drains below the cap so a slow client
|
|
803
|
+
* can't balloon DO memory. Bounded by {@link MAX_DRAIN_WAIT_MS} so a stuck
|
|
804
|
+
* socket never blocks a turn forever, and never throws (a socket without
|
|
805
|
+
* `bufferedAmount` resolves immediately).
|
|
806
|
+
*/
|
|
823
807
|
private waitForSocketDrain;
|
|
824
808
|
}
|
|
825
809
|
/**
|
|
826
|
-
* Compile a `defineAgent` definition into the workflow the generated
|
|
827
|
-
* `<Name>AgentWorkflow` entrypoint class runs. Codegen emits, per agent:
|
|
828
|
-
*
|
|
829
|
-
* ```ts
|
|
830
|
-
* import LunoraWorkflow from "@lunora/workflow/do";
|
|
831
|
-
* import { compileAgentWorkflow } from "@lunora/agent";
|
|
832
|
-
* import { support } from "../agents.js";
|
|
833
|
-
*
|
|
834
|
-
* export class SupportAgentWorkflow extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
835
|
-
* public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
836
|
-
* super(ctx, env, compileAgentWorkflow(support, "support"), "support");
|
|
837
|
-
* }
|
|
838
|
-
* }
|
|
839
|
-
* ```
|
|
840
|
-
*
|
|
841
|
-
* The workflow ctx supplies durability (`step.do`) and the Lunora dispatcher
|
|
842
|
-
* (`run`); the loop supplies determinism (step naming + idempotent persists).
|
|
843
|
-
* @experimental
|
|
844
|
-
*/
|
|
810
|
+
* Compile a `defineAgent` definition into the workflow the generated
|
|
811
|
+
* `<Name>AgentWorkflow` entrypoint class runs. Codegen emits, per agent:
|
|
812
|
+
*
|
|
813
|
+
* ```ts
|
|
814
|
+
* import LunoraWorkflow from "@lunora/workflow/do";
|
|
815
|
+
* import { compileAgentWorkflow } from "@lunora/agent";
|
|
816
|
+
* import { support } from "../agents.js";
|
|
817
|
+
*
|
|
818
|
+
* export class SupportAgentWorkflow extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
819
|
+
* public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
820
|
+
* super(ctx, env, compileAgentWorkflow(support, "support"), "support");
|
|
821
|
+
* }
|
|
822
|
+
* }
|
|
823
|
+
* ```
|
|
824
|
+
*
|
|
825
|
+
* The workflow ctx supplies durability (`step.do`) and the Lunora dispatcher
|
|
826
|
+
* (`run`); the loop supplies determinism (step naming + idempotent persists).
|
|
827
|
+
* @experimental
|
|
828
|
+
*/
|
|
845
829
|
declare const compileAgentWorkflow: (agent: AgentDefinition, exportName: string, options?: {
|
|
846
830
|
paths?: AgentFunctionPaths;
|
|
847
831
|
}) => WorkflowDefinition<AgentRunInput, AgentRunResult>;
|