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