@lunora/agent 0.0.0 → 1.0.0-alpha.2
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/LICENSE.md +105 -0
- package/README.md +38 -31
- package/dist/channels.d.mts +66 -0
- package/dist/channels.d.ts +66 -0
- package/dist/channels.mjs +181 -0
- package/dist/component.d.mts +115 -0
- package/dist/component.d.ts +115 -0
- package/dist/component.mjs +407 -0
- package/dist/inbound.d.mts +34 -0
- package/dist/inbound.d.ts +34 -0
- package/dist/inbound.mjs +32 -0
- package/dist/index.d.mts +848 -0
- package/dist/index.d.ts +848 -0
- package/dist/index.mjs +18 -0
- package/dist/naming.d.mts +30 -0
- package/dist/naming.d.ts +30 -0
- package/dist/naming.mjs +8 -0
- package/dist/packem_shared/AGENT_MODULE-Dnt_-AAT.mjs +24 -0
- package/dist/packem_shared/VoiceSessionDO-DLoXsHGF.mjs +297 -0
- package/dist/packem_shared/adaptMcpResult-wtNMvLoP.mjs +65 -0
- package/dist/packem_shared/agentAsTool-Dt8NlU6k.mjs +94 -0
- package/dist/packem_shared/base64-BVwtgRJV.mjs +18 -0
- package/dist/packem_shared/braintrustTelemetry-wuGDErob.mjs +47 -0
- package/dist/packem_shared/buildModelMessages-BWFigaoo.mjs +69 -0
- package/dist/packem_shared/codeTool-CjgJOC9t.mjs +122 -0
- package/dist/packem_shared/collectAgenticMemoryTools-QrzpV-WX.mjs +97 -0
- package/dist/packem_shared/combineTelemetry-DCyaaWAI.mjs +43 -0
- package/dist/packem_shared/common-DAeFCot5.mjs +61 -0
- package/dist/packem_shared/compileAgentWorkflow-BxJjHgtD.mjs +55 -0
- package/dist/packem_shared/consoleTelemetry-z2MiP1jt.mjs +93 -0
- package/dist/packem_shared/createAgentContext-4xJGXNR4.mjs +50 -0
- package/dist/packem_shared/createAgentGenerate-BQv9YJ01.mjs +192 -0
- package/dist/packem_shared/createDispatchRunner-DSbp_dph-ZHTtxy3f.mjs +69 -0
- package/dist/packem_shared/defineAgent-D6maSbVc.mjs +148 -0
- package/dist/packem_shared/defineSkill-Ctf_S-rz.mjs +22 -0
- package/dist/packem_shared/functionTool-D6lCa2jB.mjs +20 -0
- package/dist/packem_shared/graph-component-aoUwO-f0.mjs +216 -0
- package/dist/packem_shared/memory-D4FPcBsX.mjs +12 -0
- package/dist/packem_shared/normalizeEntityName-CyEEWFkR.mjs +3 -0
- package/dist/packem_shared/runAgentLoop-Dhg4ZNvw.mjs +493 -0
- package/dist/packem_shared/runVoiceTurn-LnqLvCRR.mjs +211 -0
- package/dist/packem_shared/sandboxComponent-DR3pTwBL.mjs +194 -0
- package/dist/packem_shared/sentryTelemetry-CgqFJyLO.mjs +36 -0
- package/dist/packem_shared/types.d-BhJFTvz_.d.mts +1114 -0
- package/dist/packem_shared/types.d-BhJFTvz_.d.ts +1114 -0
- package/dist/sandbox.d.mts +200 -0
- package/dist/sandbox.d.ts +200 -0
- package/dist/sandbox.mjs +109 -0
- package/dist/telemetry/index.d.mts +173 -0
- package/dist/telemetry/index.d.ts +173 -0
- package/dist/telemetry/index.mjs +4 -0
- package/package.json +88 -7
|
@@ -0,0 +1,1114 @@
|
|
|
1
|
+
import { InboundEmail } from '@lunora/mail/inbound';
|
|
2
|
+
import { FlexibleSchema, LanguageModel, ModelMessage, ToolSet, ToolChoice, ToolCallRepairFunction, StopCondition, TelemetryOptions } from 'ai';
|
|
3
|
+
/**
|
|
4
|
+
* Structural mirror of the Lunora function reference (`{ __lunoraRef }`).
|
|
5
|
+
* Declared locally so the loop can mint references to the agent runtime
|
|
6
|
+
* functions by path without importing `@lunora/dispatch`.
|
|
7
|
+
* @experimental
|
|
8
|
+
*/
|
|
9
|
+
interface AgentFunctionReference {
|
|
10
|
+
__lunoraRef: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* `ctx.run`-shaped dispatcher the loop uses to call Lunora functions.
|
|
14
|
+
* @experimental
|
|
15
|
+
*/
|
|
16
|
+
type AgentRunFunction = (reference: AgentFunctionReference, args?: Record<string, unknown>) => Promise<unknown>;
|
|
17
|
+
/**
|
|
18
|
+
* Structural subset of the Cloudflare Workflows durable-step API the loop needs.
|
|
19
|
+
* @experimental
|
|
20
|
+
*/
|
|
21
|
+
interface AgentStepLike {
|
|
22
|
+
do: <T>(name: string, callback: () => Promise<T>) => Promise<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Durably hibernate until an external event of `type` arrives, then return
|
|
25
|
+
* its payload. Used for human-in-the-loop approvals: a run pauses on
|
|
26
|
+
* `approval:<toolCallId>` until a client resolves it. Like `do`, a resolved
|
|
27
|
+
* wait is memoized — a replay returns the recorded decision without pausing
|
|
28
|
+
* again. Signature mirrors `@lunora/workflow`'s `WorkflowStepLike`.
|
|
29
|
+
*/
|
|
30
|
+
waitForEvent: <T = unknown>(name: string, options: {
|
|
31
|
+
timeout?: number | string;
|
|
32
|
+
type: string;
|
|
33
|
+
}) => Promise<{
|
|
34
|
+
payload: Readonly<T>;
|
|
35
|
+
type: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The context handed to an agent tool's `execute`. Beyond the model-provided
|
|
40
|
+
* input, a tool sees who it runs for (`threadKey`), how to call back into the
|
|
41
|
+
* app (`run` — dispatches Lunora queries/mutations/actions), and its
|
|
42
|
+
* `idempotencyKey`.
|
|
43
|
+
*
|
|
44
|
+
* The `idempotencyKey` is the deterministic durable-step name
|
|
45
|
+
* (`tool:<name>:<toolCallId>`). A COMPLETED tool step is never re-run on a
|
|
46
|
+
* workflow replay (native step memoization) — but a step that FAILS mid-body
|
|
47
|
+
* is retried at-least-once, so a side-effecting tool (charge a card, send a
|
|
48
|
+
* mail) must dedupe on this key itself.
|
|
49
|
+
* @experimental
|
|
50
|
+
*/
|
|
51
|
+
interface AgentToolContext {
|
|
52
|
+
/** The Worker environment bindings. */
|
|
53
|
+
env: Record<string, unknown>;
|
|
54
|
+
/**
|
|
55
|
+
* Read the thread's synced state — dispatches the public owner-gated
|
|
56
|
+
* `agents:agentState` query through {@link AgentToolContext.run} (the same
|
|
57
|
+
* admin-dispatch path the loop reads history with), so it inherits the
|
|
58
|
+
* thread's identity/owner gate. Returns `undefined` before any state was
|
|
59
|
+
* seeded (`defineAgent({ initialState })`) or written.
|
|
60
|
+
*
|
|
61
|
+
* NOT replay-stable: on an at-least-once step retry this reflects whatever a
|
|
62
|
+
* prior attempt already wrote via {@link AgentToolContext.setState} (a real
|
|
63
|
+
* committed write, not rolled back), so a value *derived* from it is not
|
|
64
|
+
* safe to pass straight back to `setState` — see its doc for the
|
|
65
|
+
* read-modify-write hazard and the `idempotencyKey` dedupe fix.
|
|
66
|
+
*/
|
|
67
|
+
getState: () => Promise<Record<string, unknown> | undefined>;
|
|
68
|
+
/** Deterministic idempotency key — the tool's durable-step name. */
|
|
69
|
+
idempotencyKey: string;
|
|
70
|
+
/**
|
|
71
|
+
* Emit an EPHEMERAL progress event for this tool call on the agent's live
|
|
72
|
+
* channel — the same live-only sink the streamed token deltas ride. NOT
|
|
73
|
+
* persisted and NEVER replayed: it fires only while `execute` runs inside the
|
|
74
|
+
* tool's memoized durable step, so a COMPLETED step is served from the memo on
|
|
75
|
+
* replay without re-emitting. A safe no-op when the runtime wired no live sink
|
|
76
|
+
* (the durable path's default), exactly as `streamingText` stays empty then.
|
|
77
|
+
* Surfaced on the client by `useAgentToolEvents`, correlated to this call by
|
|
78
|
+
* {@link AgentToolContext.toolCallId}. `data` must be JSON-serializable.
|
|
79
|
+
*/
|
|
80
|
+
reportProgress: (data: unknown) => void;
|
|
81
|
+
/** Dispatch a Lunora function (the workflow `ctx.run`). */
|
|
82
|
+
run: AgentRunFunction;
|
|
83
|
+
/**
|
|
84
|
+
* Replace the thread's synced state — dispatches the internal
|
|
85
|
+
* `agents:agentSetState` mutation (absolute REPLACE of the whole object) and
|
|
86
|
+
* broadcasts to every `useAgentState` subscriber over the existing reactive
|
|
87
|
+
* channel. Runs inside the tool's memoized durable step, so a COMPLETED step
|
|
88
|
+
* is served from the memo on replay without re-dispatching.
|
|
89
|
+
*
|
|
90
|
+
* REPLAY-SAFETY CONTRACT — the *value* you pass must be REPLAY-STABLE: a
|
|
91
|
+
* constant or derived purely from the replay-stable tool `input` (never
|
|
92
|
+
* `Date.now()`/`Math.random()`). A step that FAILS mid-body is retried
|
|
93
|
+
* at-least-once, and the retry re-runs the whole `execute` against state a
|
|
94
|
+
* prior attempt may already have written (the dispatch is a real committed
|
|
95
|
+
* mutation, not rolled back). Re-applying a replay-stable value is a no-op,
|
|
96
|
+
* so the absolute set converges. A value derived from
|
|
97
|
+
* {@link AgentToolContext.getState} is NOT replay-stable — a naive
|
|
98
|
+
* read-modify-write (`setState({ count: (await getState()).count + 1 })`)
|
|
99
|
+
* DOUBLE-ADVANCES on a retry because the retry re-reads the already-written
|
|
100
|
+
* value. For a read-modify-write, make the tool idempotent on
|
|
101
|
+
* {@link AgentToolContext.idempotencyKey}: record the key in the state and
|
|
102
|
+
* skip the write when it is already present.
|
|
103
|
+
*/
|
|
104
|
+
setState: (state: Record<string, unknown>) => Promise<void>;
|
|
105
|
+
/** The thread this tool call belongs to. */
|
|
106
|
+
threadKey: string;
|
|
107
|
+
/** The provider-issued tool-call id. */
|
|
108
|
+
toolCallId: string;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* An agent tool. Unlike a raw AI SDK tool, `execute` is NOT handed to the
|
|
112
|
+
* model call — the loop runs it itself inside a named durable step so a
|
|
113
|
+
* completed call never re-runs on replay, and passes the
|
|
114
|
+
* {@link AgentToolContext} alongside the input.
|
|
115
|
+
* @experimental
|
|
116
|
+
*/
|
|
117
|
+
interface AgentToolDefinition<Input = unknown, Output = unknown> {
|
|
118
|
+
/** What the tool does — shown to the model. */
|
|
119
|
+
description: string;
|
|
120
|
+
/** Run the tool. The returned value is persisted as the tool message content. */
|
|
121
|
+
execute: (input: Input, context: AgentToolContext) => Promise<Output> | Output;
|
|
122
|
+
/** The input schema shown to the model (a zod schema or `jsonSchema(...)`). */
|
|
123
|
+
inputSchema: FlexibleSchema<Input>;
|
|
124
|
+
/** Runtime brand. */
|
|
125
|
+
isLunoraAgentTool: true;
|
|
126
|
+
/**
|
|
127
|
+
* Gate the tool behind a human approval (mirrors the AI SDK's
|
|
128
|
+
* `needsApproval`). When it resolves truthy the durable run PAUSES — the
|
|
129
|
+
* thread moves to `"awaiting_input"` and the workflow hibernates on
|
|
130
|
+
* `approval:<toolCallId>` — until a client calls `agents:agentResolveApproval`.
|
|
131
|
+
* On approve the tool runs exactly as normal; on reject it is skipped and a
|
|
132
|
+
* tool result explaining the rejection is persisted so the next turn recovers.
|
|
133
|
+
* A boolean gates statically; a function gates per input. Default: `false`
|
|
134
|
+
* (unchanged behavior). Evaluated from replay-stable input OUTSIDE the
|
|
135
|
+
* durable step (it re-runs on every replay), so it must be a PURE predicate:
|
|
136
|
+
* deterministic (no `Date.now()`/`Math.random()`) and free of side effects —
|
|
137
|
+
* never call {@link AgentToolContext.setState}/`getState` or a mutating `run`
|
|
138
|
+
* here; state writes belong only in `execute`, inside the memoized step.
|
|
139
|
+
*/
|
|
140
|
+
needsApproval?: ((input: Input, context: AgentToolContext) => boolean | Promise<boolean>) | boolean;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Author-supplied tool config (see {@link AgentToolDefinition}).
|
|
144
|
+
* @experimental
|
|
145
|
+
*/
|
|
146
|
+
type AgentToolConfig<Input = unknown, Output = unknown> = Omit<AgentToolDefinition<Input, Output>, "isLunoraAgentTool">;
|
|
147
|
+
/**
|
|
148
|
+
* Generic-erased tool for tool maps. `Input` sits in both a covariant
|
|
149
|
+
* (`inputSchema`) and a contravariant (`execute`) position, so no single
|
|
150
|
+
* non-`any` instantiation admits every concrete tool — the same reason the AI
|
|
151
|
+
* SDK's `ToolSet` erases its generics.
|
|
152
|
+
* @experimental
|
|
153
|
+
*/
|
|
154
|
+
type AnyAgentTool = AgentToolDefinition<any, any>;
|
|
155
|
+
/**
|
|
156
|
+
* The model an agent runs on: a Workers AI model id (resolved via `env.AI`),
|
|
157
|
+
* a prebuilt AI SDK {@link LanguageModel}, or a thunk building one from the
|
|
158
|
+
* Worker env (for providers that need API keys off `env`).
|
|
159
|
+
* @experimental
|
|
160
|
+
*/
|
|
161
|
+
type AgentModelInput = LanguageModel | ((env: Record<string, unknown>) => LanguageModel);
|
|
162
|
+
/**
|
|
163
|
+
* Memory wiring: the path (or reference) of an app **action** taking
|
|
164
|
+
* `{ query: string }` and returning `@lunora/ai/rag`'s `RetrieveResult`
|
|
165
|
+
* (`{ context, chunks, sources }`) — typically three lines over
|
|
166
|
+
* `defineRag(...)(ctx).retrieve`. Dispatching to a real action (instead of
|
|
167
|
+
* embedding vector plumbing here) keeps retrieval inside a fully wired ctx:
|
|
168
|
+
* codegen-resolved vector bindings, RLS, observability.
|
|
169
|
+
*
|
|
170
|
+
* Two retrieval MODES. `"inject"` (default) runs the action as a durable step at
|
|
171
|
+
* turn start and injects `.context` as one system message (one-shot top-k).
|
|
172
|
+
* `"agentic"` skips auto-injection; the source instead mints a `searchMemory`
|
|
173
|
+
* tool the MODEL calls mid-reasoning (Recursive-LM / "read what you need") — each
|
|
174
|
+
* call a memoized durable step, so multi-hop retrieval is crash-safe for free.
|
|
175
|
+
* @experimental
|
|
176
|
+
*/
|
|
177
|
+
interface AgentMemoryOptions {
|
|
178
|
+
/**
|
|
179
|
+
* Episodic-tier options — read only when {@link AgentMemoryOptions.kind} is
|
|
180
|
+
* `"episodic"`. `recall` bounds how many recent episodes are injected per run
|
|
181
|
+
* (default 5, capped at 20); `extractionModel` overrides the (optionally
|
|
182
|
+
* cheaper) model that summarizes each run into an episode (defaults to the
|
|
183
|
+
* agent's own model).
|
|
184
|
+
*/
|
|
185
|
+
episodic?: {
|
|
186
|
+
/** Model for the run-end episode-summary step (defaults to the agent's model). */
|
|
187
|
+
extractionModel?: AgentModelInput;
|
|
188
|
+
/** Max recent episodes recalled per run (default 5, max 20). */
|
|
189
|
+
recall?: number;
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* Graph-tier bounds and extraction model — read only when
|
|
193
|
+
* {@link AgentMemoryOptions.kind} is `"graph"`. `depth`/`maxSeeds`/`fanOut`/
|
|
194
|
+
* `maxNodes` bound the run-time BFS traversal; `extractionModel` overrides the
|
|
195
|
+
* (optionally cheaper) model used for the run-end entity/relation extraction
|
|
196
|
+
* step (defaults to the agent's own model).
|
|
197
|
+
*/
|
|
198
|
+
graph?: {
|
|
199
|
+
/** Max BFS hops from a seed entity (default 2). */
|
|
200
|
+
depth?: number;
|
|
201
|
+
/** Model for the run-end extraction step (defaults to the agent's model). */
|
|
202
|
+
extractionModel?: AgentModelInput;
|
|
203
|
+
/** Max edges expanded per visited node (default 8). */
|
|
204
|
+
fanOut?: number;
|
|
205
|
+
/** Max entities visited across the whole traversal (default 32). */
|
|
206
|
+
maxNodes?: number;
|
|
207
|
+
/** Max seed entities matched from the query (default 4). */
|
|
208
|
+
maxSeeds?: number;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* `"semantic"` (default) is vector RAG over {@link AgentMemoryOptions.source}.
|
|
212
|
+
* `"graph"` traverses the owner-scoped entity/relation graph (auto-extracted
|
|
213
|
+
* on write, keyed by the thread's `owner`) via the built-in traverse function
|
|
214
|
+
* and ignores `source`. `"episodic"` recalls a recency-ordered timeline of the
|
|
215
|
+
* owner's past runs (each summarized at run end); it also ignores `source`.
|
|
216
|
+
* See {@link AgentMemoryOptions}.
|
|
217
|
+
*/
|
|
218
|
+
kind?: "episodic" | "graph" | "semantic";
|
|
219
|
+
/**
|
|
220
|
+
* `"inject"` (default) auto-injects one top-k context system message per
|
|
221
|
+
* run; `"agentic"` skips injection and mints a `searchMemory` tool the model
|
|
222
|
+
* drives itself. Applies to `"semantic"` kind only. See
|
|
223
|
+
* {@link AgentMemoryOptions}.
|
|
224
|
+
*/
|
|
225
|
+
mode?: "agentic" | "inject";
|
|
226
|
+
/**
|
|
227
|
+
* Agentic-only. An optional fetch-by-id **action** `{ id: string } -> string`
|
|
228
|
+
* that mints a companion `readMemory` tool so the model can pull a full
|
|
229
|
+
* document after `searchMemory` surfaces its id (typically a ~3-line action
|
|
230
|
+
* mapping `${sourceId}#${n}` → text). Ignored in `"inject"` mode.
|
|
231
|
+
*/
|
|
232
|
+
read?: AgentFunctionReference | string;
|
|
233
|
+
/**
|
|
234
|
+
* Agentic-only. Per-result snippet truncation (chars) applied to each
|
|
235
|
+
* `searchMemory` hit for token economy. Default 240. Ignored in `"inject"`
|
|
236
|
+
* mode.
|
|
237
|
+
*/
|
|
238
|
+
snippetChars?: number;
|
|
239
|
+
/**
|
|
240
|
+
* The memory action: a function path (`"rag:searchDocs"`) or reference.
|
|
241
|
+
* Required for `"semantic"` kind (enforced at `defineAgent`); ignored — and
|
|
242
|
+
* therefore optional — for `"graph"` kind, which dispatches the built-in
|
|
243
|
+
* traverse function instead.
|
|
244
|
+
*/
|
|
245
|
+
source?: AgentFunctionReference | string;
|
|
246
|
+
/** Retrieval depth forwarded to the action as `topK`. */
|
|
247
|
+
topK?: number;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* One keyed memory-retrieval source the loop dispatches per run. `defineAgent`
|
|
251
|
+
* folds them onto {@link AgentDefinition.memorySources}: the default source
|
|
252
|
+
* (`key: "default"`) from {@link AgentConfig.memory}, then one per skill that
|
|
253
|
+
* carries `knowledge` (keyed by the skill's name). The key names the durable
|
|
254
|
+
* step — the default source keeps the historic `"memory:retrieve"`, a skill
|
|
255
|
+
* source uses `"memory:retrieve:<key>"` — so replay stays deterministic.
|
|
256
|
+
* @experimental
|
|
257
|
+
*/
|
|
258
|
+
interface AgentMemorySource extends AgentMemoryOptions {
|
|
259
|
+
/** Stable source key: `"default"` for `memory`, else the contributing skill's name. */
|
|
260
|
+
key: string;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Cumulative or per-turn token usage — AI SDK `LanguageModelUsage` field names.
|
|
264
|
+
* @experimental
|
|
265
|
+
*/
|
|
266
|
+
interface AgentUsage {
|
|
267
|
+
/** Prompt (input) tokens. */
|
|
268
|
+
inputTokens?: number;
|
|
269
|
+
/** Completion (output) tokens. */
|
|
270
|
+
outputTokens?: number;
|
|
271
|
+
/** Input + output tokens. */
|
|
272
|
+
totalTokens?: number;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Context handed to a dynamic {@link AgentConfig.instructions} function.
|
|
276
|
+
* @experimental
|
|
277
|
+
*/
|
|
278
|
+
interface AgentInstructionsContext {
|
|
279
|
+
/** The Worker environment bindings. */
|
|
280
|
+
env: Record<string, unknown>;
|
|
281
|
+
/** The user message that started this run. */
|
|
282
|
+
input: string;
|
|
283
|
+
/** The thread this run belongs to. */
|
|
284
|
+
threadKey: string;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Author-supplied config for {@link SkillDefinition} — a reusable bundle of
|
|
288
|
+
* expertise (an instruction fragment, tools, and retrieval knowledge) an agent
|
|
289
|
+
* composes in via `defineAgent({ skills: [...] })`. Reuse-first: `tools` carry
|
|
290
|
+
* the SAME {@link AnyAgentTool} shape agents already use
|
|
291
|
+
* (`functionTool`/`mcpTools`/`agentAsTool`), and `knowledge` reuses the
|
|
292
|
+
* {@link AgentMemoryOptions} retrieval verbatim.
|
|
293
|
+
* @experimental
|
|
294
|
+
*/
|
|
295
|
+
interface SkillConfig {
|
|
296
|
+
/**
|
|
297
|
+
* An instruction fragment merged into the agent's system prompt — a static
|
|
298
|
+
* string or a thunk over the run context (same shape as
|
|
299
|
+
* {@link AgentConfig.instructions}). Fragments compose in order: the agent's
|
|
300
|
+
* own instructions first, then each skill's in `skills` array order.
|
|
301
|
+
*/
|
|
302
|
+
instructions?: string | ((context: AgentInstructionsContext) => string);
|
|
303
|
+
/**
|
|
304
|
+
* Retrieval-augmented knowledge for this skill — see
|
|
305
|
+
* {@link AgentMemoryOptions}. Retrieved as its own durable step at run start
|
|
306
|
+
* (keyed by the skill `name`) and injected alongside the agent's `memory`.
|
|
307
|
+
*/
|
|
308
|
+
knowledge?: AgentMemoryOptions;
|
|
309
|
+
/**
|
|
310
|
+
* The skill's identifier — namespaces this skill's `knowledge` memory source
|
|
311
|
+
* (the durable step `memory:retrieve:<name>`). Must be identifier-shaped.
|
|
312
|
+
*/
|
|
313
|
+
name: string;
|
|
314
|
+
/**
|
|
315
|
+
* Tools this skill contributes, merged into the agent's FLAT tool namespace.
|
|
316
|
+
* A name collision with the agent's own tools (or another skill's) is an
|
|
317
|
+
* error at `defineAgent` — the agent owns the model-facing namespace.
|
|
318
|
+
*/
|
|
319
|
+
tools?: Record<string, AnyAgentTool>;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* A `defineSkill` result — config plus the brand the agent merge checks.
|
|
323
|
+
* @experimental
|
|
324
|
+
*/
|
|
325
|
+
interface SkillDefinition extends SkillConfig {
|
|
326
|
+
/** Runtime brand check (see `isSkillDefinition`). */
|
|
327
|
+
readonly isLunoraSkill: true;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* One prior turn, as {@link AgentConfig.prepareStep} and `stopWhen` observe it.
|
|
331
|
+
* @experimental
|
|
332
|
+
*/
|
|
333
|
+
interface AgentStepInfo {
|
|
334
|
+
/** The assistant text of the turn. */
|
|
335
|
+
text: string;
|
|
336
|
+
/** The tool calls the turn issued (AI SDK `StepResult.toolCalls` shape). */
|
|
337
|
+
toolCalls: ReadonlyArray<{
|
|
338
|
+
input: unknown;
|
|
339
|
+
toolCallId: string;
|
|
340
|
+
toolName: string;
|
|
341
|
+
}>;
|
|
342
|
+
/** The turn's token usage, when the model reported it. */
|
|
343
|
+
usage?: AgentUsage;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* The turn summary handed to {@link AgentConfig.onStepFinish}.
|
|
347
|
+
* @experimental
|
|
348
|
+
*/
|
|
349
|
+
interface AgentStepFinishInfo {
|
|
350
|
+
/** The assistant text produced this turn. */
|
|
351
|
+
text: string;
|
|
352
|
+
/** The tool calls issued this turn (empty on the final answer). */
|
|
353
|
+
toolCalls: ReadonlyArray<AgentToolCall>;
|
|
354
|
+
/** The zero-based turn index. */
|
|
355
|
+
turn: number;
|
|
356
|
+
/** The turn's token usage, when the model reported it. */
|
|
357
|
+
usage?: AgentUsage;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Called after each LLM turn with that turn's text, tool calls, and usage. Runs
|
|
361
|
+
* inside a named durable step (`agent:step-finish:<turn>`) so it fires exactly
|
|
362
|
+
* once per turn even across a workflow replay.
|
|
363
|
+
* @experimental
|
|
364
|
+
*/
|
|
365
|
+
type AgentOnStepFinish = (info: AgentStepFinishInfo) => Promise<void> | void;
|
|
366
|
+
/**
|
|
367
|
+
* The input {@link AgentConfig.prepareStep} sees before a turn runs.
|
|
368
|
+
* @experimental
|
|
369
|
+
*/
|
|
370
|
+
interface AgentPrepareStepInput {
|
|
371
|
+
/** The messages assembled for this turn (instructions + memory + history). */
|
|
372
|
+
messages: ReadonlyArray<ModelMessage>;
|
|
373
|
+
/** The zero-based index of the turn about to run. */
|
|
374
|
+
stepNumber: number;
|
|
375
|
+
/** The turns already completed this run. */
|
|
376
|
+
steps: ReadonlyArray<AgentStepInfo>;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Per-turn overrides {@link AgentConfig.prepareStep} may return. A returned
|
|
380
|
+
* `messages` array **replaces** the assembled history for that turn — the seam
|
|
381
|
+
* where history compaction lives.
|
|
382
|
+
* @experimental
|
|
383
|
+
*/
|
|
384
|
+
interface AgentPrepareStepResult {
|
|
385
|
+
/** Restrict the tools exposed to the model this turn (by name). */
|
|
386
|
+
activeTools?: ReadonlyArray<string>;
|
|
387
|
+
/** Replace the assembled messages for this turn (history compaction). */
|
|
388
|
+
messages?: ReadonlyArray<ModelMessage>;
|
|
389
|
+
/** Swap the model for this turn. */
|
|
390
|
+
model?: AgentModelInput;
|
|
391
|
+
/** Prepend a system message for this turn. */
|
|
392
|
+
system?: string;
|
|
393
|
+
/** Override the tool-choice strategy for this turn. */
|
|
394
|
+
toolChoice?: ToolChoice<ToolSet>;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Adjust the next turn before it runs — mirrors AI SDK's `prepareStep`. Invoked
|
|
398
|
+
* inside the turn's durable step so its effect is memoized on replay.
|
|
399
|
+
* @experimental
|
|
400
|
+
*/
|
|
401
|
+
type AgentPrepareStep = (input: AgentPrepareStepInput) => AgentPrepareStepResult | Promise<AgentPrepareStepResult | undefined> | undefined;
|
|
402
|
+
/**
|
|
403
|
+
* The subset of {@link AgentRunInput} an {@link AgentEmailMapper} returns to
|
|
404
|
+
* start a run from an inbound email.
|
|
405
|
+
* @experimental
|
|
406
|
+
*/
|
|
407
|
+
interface AgentEmailRun {
|
|
408
|
+
/** The user message that starts (or continues) the thread — the model's prompt. */
|
|
409
|
+
input: string;
|
|
410
|
+
/**
|
|
411
|
+
* Verified owner of the thread (its RLS scope). SECURITY: inbound `from` is
|
|
412
|
+
* spoofable and the run dispatches RLS-bypassed — derive this from a verified
|
|
413
|
+
* signal (a DKIM-checked address, a mapped account), never blindly from
|
|
414
|
+
* `email.from`.
|
|
415
|
+
*/
|
|
416
|
+
owner?: string;
|
|
417
|
+
/** The thread key — reuse to continue a conversation (e.g. a ticket id parsed from the subject). */
|
|
418
|
+
threadKey: string;
|
|
419
|
+
/** Optional thread title, set on first creation. */
|
|
420
|
+
title?: string;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Map an inbound email into an agent run, or `null`/`undefined` to DROP it (a
|
|
424
|
+
* failed DKIM/SPF/DMARC check, or a message not addressed to this agent). Wired
|
|
425
|
+
* by codegen onto the worker's top-level `email()` handler when set — see
|
|
426
|
+
* `@lunora/agent/inbound`.
|
|
427
|
+
*
|
|
428
|
+
* SECURITY: the parsed `from`/`subject`/body are attacker-controlled and the run
|
|
429
|
+
* is dispatched with RLS bypassed. Gate on `email.authentication` (DKIM/SPF/DMARC
|
|
430
|
+
* verdicts) here before returning a run, and treat every returned field as
|
|
431
|
+
* untrusted input.
|
|
432
|
+
* @experimental
|
|
433
|
+
*/
|
|
434
|
+
type AgentEmailMapper = (email: InboundEmail) => AgentEmailRun | null | Promise<AgentEmailRun | null | undefined> | undefined;
|
|
435
|
+
/** The inbound webhook channels an agent can be triggered from — see `@lunora/agent/channels`. */
|
|
436
|
+
type AgentInboundChannelKind = "discord" | "github" | "slack";
|
|
437
|
+
/** The run-input an inbound-channel mapper returns — the same shape as {@link AgentEmailRun}. */
|
|
438
|
+
type AgentChannelRun = AgentEmailRun;
|
|
439
|
+
/**
|
|
440
|
+
* The verified, parsed webhook event handed to an {@link AgentInboundChannel.map} mapper.
|
|
441
|
+
* @experimental
|
|
442
|
+
*/
|
|
443
|
+
interface InboundChannelEvent {
|
|
444
|
+
/** Which channel delivered it. */
|
|
445
|
+
channel: AgentInboundChannelKind;
|
|
446
|
+
/** The raw request headers. */
|
|
447
|
+
headers: Headers;
|
|
448
|
+
/** Parse the body as JSON (throws on malformed JSON). */
|
|
449
|
+
json: () => unknown;
|
|
450
|
+
/** The raw (verified) request body. */
|
|
451
|
+
rawBody: string;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Map a VERIFIED inbound channel event into an agent run, or `null`/`undefined`
|
|
455
|
+
* to DECLINE it. Runs only AFTER the channel signature check passes.
|
|
456
|
+
*
|
|
457
|
+
* SECURITY: the payload is attacker-controlled and the run dispatches RLS
|
|
458
|
+
* bypassed. Derive the run `owner` from the verified channel identity (the
|
|
459
|
+
* workspace/installation the signing secret belongs to), never from an arbitrary
|
|
460
|
+
* payload field, and treat every returned field as untrusted input.
|
|
461
|
+
*/
|
|
462
|
+
type AgentChannelMapper = (event: InboundChannelEvent) => AgentChannelRun | null | Promise<AgentChannelRun | null | undefined> | undefined;
|
|
463
|
+
/**
|
|
464
|
+
* Trigger an agent from a verified inbound webhook. Codegen wires the developer's
|
|
465
|
+
* chosen HTTP route to `dispatchAgentChannel(...)` (from `@lunora/agent/channels`),
|
|
466
|
+
* which verifies the channel signature over the raw body before calling `map`.
|
|
467
|
+
*/
|
|
468
|
+
interface AgentInboundChannel {
|
|
469
|
+
/** Which channel this agent listens on (selects the signature scheme). */
|
|
470
|
+
channel: AgentInboundChannelKind;
|
|
471
|
+
/** Map a verified event to a run (or `null` to decline). */
|
|
472
|
+
map: AgentChannelMapper;
|
|
473
|
+
/**
|
|
474
|
+
* The verification credential, from `env`: an env-var NAME (string) or an
|
|
475
|
+
* `(env) => value` resolver. Slack → signing secret; GitHub → webhook secret;
|
|
476
|
+
* Discord → the application's Ed25519 public key (hex).
|
|
477
|
+
*/
|
|
478
|
+
secret: string | ((env: Record<string, unknown>) => string | undefined);
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* `AgentConfig` is part of the experimental `@lunora/agent` API and may change without a major version bump.
|
|
482
|
+
* @experimental
|
|
483
|
+
*/
|
|
484
|
+
interface AgentConfig {
|
|
485
|
+
/** Restrict the tools the model may call, by name. Default: all tools. */
|
|
486
|
+
activeTools?: ReadonlyArray<string>;
|
|
487
|
+
/**
|
|
488
|
+
* Automatic thread-history compaction. When the persisted history exceeds
|
|
489
|
+
* `maxMessages`, the loop summarizes the older messages (all but the most
|
|
490
|
+
* recent `keepRecent`, default `ceil(maxMessages / 2)`) into one system-message
|
|
491
|
+
* brief and prompts the model with that brief plus the recent tail — keeping
|
|
492
|
+
* the context bounded as a conversation grows. The summary is produced inside
|
|
493
|
+
* the turn's memoized durable step (replay-safe) by `model` (a cheaper model
|
|
494
|
+
* may be set, else the agent's). Absent (the default) disables compaction —
|
|
495
|
+
* the full history is sent every turn, exactly as before. A manual
|
|
496
|
+
* {@link AgentConfig.prepareStep} still runs after and can override further.
|
|
497
|
+
*/
|
|
498
|
+
compaction?: {
|
|
499
|
+
/** How many most-recent messages to keep verbatim (default `ceil(maxMessages / 2)`). */
|
|
500
|
+
keepRecent?: number;
|
|
501
|
+
/** Compact once history exceeds this many messages. */
|
|
502
|
+
maxMessages: number;
|
|
503
|
+
/** Model for the summarization step (defaults to the agent's model). */
|
|
504
|
+
model?: AgentModelInput;
|
|
505
|
+
};
|
|
506
|
+
/**
|
|
507
|
+
* Seed the thread's synced state — a static, JSON-serializable object set on
|
|
508
|
+
* the thread row at creation only (first writer wins, like `owner`/`title`),
|
|
509
|
+
* so a `useAgentState` client sees it immediately. Keep it DETERMINISTIC (no
|
|
510
|
+
* `Date.now()`/`Math.random()`); it is written once by the durable bootstrap.
|
|
511
|
+
* Runtime-only config — invisible to codegen (agent-free and agent-ful
|
|
512
|
+
* `_generated/*` output is unchanged by its presence).
|
|
513
|
+
*/
|
|
514
|
+
initialState?: Record<string, unknown>;
|
|
515
|
+
/**
|
|
516
|
+
* System prompt prepended to every model call — a static string or a thunk
|
|
517
|
+
* derived from the run context (dynamic instructions).
|
|
518
|
+
*/
|
|
519
|
+
instructions?: string | ((context: AgentInstructionsContext) => string);
|
|
520
|
+
/** Cap the tokens generated per turn (AI SDK `maxOutputTokens`). */
|
|
521
|
+
maxOutputTokens?: number;
|
|
522
|
+
/**
|
|
523
|
+
* Cost/step cap: maximum LLM turns per run. Default 8. Composes with
|
|
524
|
+
* {@link AgentConfig.stopWhen} — the loop ends when EITHER triggers.
|
|
525
|
+
*/
|
|
526
|
+
maxTurns?: number;
|
|
527
|
+
/** Retrieval-augmented memory — see {@link AgentMemoryOptions}. */
|
|
528
|
+
memory?: AgentMemoryOptions;
|
|
529
|
+
/** The model — see {@link AgentModelInput}. */
|
|
530
|
+
model: AgentModelInput;
|
|
531
|
+
/**
|
|
532
|
+
* Optional override for the deployed workflow name (`wrangler.jsonc`
|
|
533
|
+
* `workflows[].name`). Defaults to `agent-<kebab-cased export name>`. Does
|
|
534
|
+
* NOT change the binding name, which is always derived from the export
|
|
535
|
+
* name (`support` → `AGENT_SUPPORT`).
|
|
536
|
+
*/
|
|
537
|
+
name?: string;
|
|
538
|
+
/**
|
|
539
|
+
* Policy when a run starts on a thread that already has a DIFFERENT run in
|
|
540
|
+
* flight (the thread's `status` is `"running"` under another workflow
|
|
541
|
+
* instance) — the guard that stops two runs from interleaving messages on
|
|
542
|
+
* the shared per-thread seq counter:
|
|
543
|
+
*
|
|
544
|
+
* - `"reject"` (default) — fail the new run fast with a `CONFLICT` error.
|
|
545
|
+
* - `"replace"` — terminate the in-flight instance and take the thread over.
|
|
546
|
+
* - `"queue"` — reserved for a future durable queue; currently degrades to `"reject"` (no queue exists yet), tracked as a follow-up.
|
|
547
|
+
*
|
|
548
|
+
* A workflow REPLAY re-enters the bootstrap under the SAME instance id and
|
|
549
|
+
* is never a concurrent run (the guard compares the stored instance id).
|
|
550
|
+
*/
|
|
551
|
+
onConcurrentRun?: "queue" | "reject" | "replace";
|
|
552
|
+
/**
|
|
553
|
+
* Map an inbound email into an agent run — see {@link AgentEmailMapper}.
|
|
554
|
+
* When set, codegen wires this agent onto the worker's top-level `email()`
|
|
555
|
+
* handler (via `@lunora/agent/inbound`) so a received message starts a
|
|
556
|
+
* durable run. Return `null`/`undefined` to drop the message.
|
|
557
|
+
*/
|
|
558
|
+
onEmail?: AgentEmailMapper;
|
|
559
|
+
/**
|
|
560
|
+
* Trigger this agent from a verified inbound webhook (Slack / GitHub /
|
|
561
|
+
* Discord) — see {@link AgentInboundChannel}. Mount `dispatchAgentChannel(...)`
|
|
562
|
+
* (from `@lunora/agent/channels`) on an HTTP route; it verifies the channel
|
|
563
|
+
* signature over the raw body before calling `map`.
|
|
564
|
+
*/
|
|
565
|
+
onInbound?: AgentInboundChannel;
|
|
566
|
+
/** Called after each LLM turn — see {@link AgentOnStepFinish}. */
|
|
567
|
+
onStepFinish?: AgentOnStepFinish;
|
|
568
|
+
/**
|
|
569
|
+
* Structured final answer: a zod schema or `jsonSchema(...)`. When set the
|
|
570
|
+
* loop runs the model with AI SDK `Output.object({ schema })` and returns
|
|
571
|
+
* the parsed object in {@link AgentRunResult.output}.
|
|
572
|
+
*/
|
|
573
|
+
output?: FlexibleSchema<unknown>;
|
|
574
|
+
/** Adjust the next turn before it runs — see {@link AgentPrepareStep}. */
|
|
575
|
+
prepareStep?: AgentPrepareStep;
|
|
576
|
+
/**
|
|
577
|
+
* Opt this agent into being STARTED over the public RPC boundary — i.e. via
|
|
578
|
+
* the auto-registered `agents:agentRun` mutation an HTTP-only client (e.g.
|
|
579
|
+
* the `@lunora/mcp` server) calls. Default `false`: an agent is startable
|
|
580
|
+
* only from server-side app code (`ctx.agents.<name>.run(...)`), so declaring
|
|
581
|
+
* an agent does NOT expose it to arbitrary RPC callers. Fail-closed — the run
|
|
582
|
+
* mutation refuses an agent that has not opted in, regardless of any MCP-side
|
|
583
|
+
* `allowAgents` configuration. A started thread is still owner-scoped to
|
|
584
|
+
* `ctx.auth.userId`. Deploy configuration codegen reads STATICALLY (a boolean
|
|
585
|
+
* literal), so it must be inline in the `defineAgent({ ... })` object literal.
|
|
586
|
+
*/
|
|
587
|
+
publicRun?: boolean;
|
|
588
|
+
/**
|
|
589
|
+
* Repair a malformed tool call the model emits (AI SDK
|
|
590
|
+
* `experimental_repairToolCall`): given the failing `{ toolCall, error, tools,
|
|
591
|
+
* inputSchema, messages, system }`, return a corrected tool call or `null` to
|
|
592
|
+
* give up. Runs inside the model turn, so keep it deterministic (it re-runs on
|
|
593
|
+
* a replay). Unset (the default) leaves the loop's existing
|
|
594
|
+
* unknown-tool-name recovery as the only repair path.
|
|
595
|
+
*/
|
|
596
|
+
repairToolCall?: ToolCallRepairFunction<ToolSet>;
|
|
597
|
+
/**
|
|
598
|
+
* Reusable {@link SkillDefinition}s to compose in — each contributes an
|
|
599
|
+
* instruction fragment, tools (merged into the flat namespace; collisions
|
|
600
|
+
* throw), and retrieval `knowledge` (its own keyed memory source). Folded at
|
|
601
|
+
* declaration time; the tool namespace and memory sources on the returned
|
|
602
|
+
* {@link AgentDefinition} already reflect the merge.
|
|
603
|
+
*/
|
|
604
|
+
skills?: ReadonlyArray<SkillDefinition>;
|
|
605
|
+
/**
|
|
606
|
+
* Extra loop-stop conditions (AI SDK `StopCondition`s). Composes with
|
|
607
|
+
* {@link AgentConfig.maxTurns} — the loop ends when EITHER triggers.
|
|
608
|
+
*/
|
|
609
|
+
stopWhen?: ReadonlyArray<StopCondition<ToolSet>> | StopCondition<ToolSet>;
|
|
610
|
+
/** Passed to `generateText` as its stable `telemetry` option. */
|
|
611
|
+
telemetry?: TelemetryOptions;
|
|
612
|
+
/** Sampling temperature forwarded to the model. */
|
|
613
|
+
temperature?: number;
|
|
614
|
+
/** Tool-choice strategy (AI SDK `ToolChoice`). Default: `"auto"`. */
|
|
615
|
+
toolChoice?: ToolChoice<ToolSet>;
|
|
616
|
+
/** The tools the model may call, by name. */
|
|
617
|
+
tools?: Record<string, AnyAgentTool>;
|
|
618
|
+
/**
|
|
619
|
+
* Opt into a real-time voice session — see {@link AgentVoiceConfig}. Its mere
|
|
620
|
+
* presence tells codegen to emit the `VOICE_...` hibernatable-WebSocket DO
|
|
621
|
+
* (`VoiceSessionDO` subclass) and the `api.agents.{name}Voice` client
|
|
622
|
+
* reference; an agent without it is byte-identical to before. Runtime config
|
|
623
|
+
* for the in-DO pipeline (models/voice) rides the same object.
|
|
624
|
+
*/
|
|
625
|
+
voice?: AgentVoiceConfig;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Opt an agent into a real-time VOICE session — a dedicated hibernatable-
|
|
629
|
+
* WebSocket Durable Object (`VoiceSessionDO`) that runs a per-turn
|
|
630
|
+
* STT→LLM→TTS pipeline IN-DO and SHARES the agent's existing thread tables
|
|
631
|
+
* (`agent_threads`/`agent_messages`) via the runtime dispatch seam. Presence of
|
|
632
|
+
* this block is what codegen keys on to emit the `VOICE_...` DO class + the
|
|
633
|
+
* `api.agents.{name}Voice` client reference; agents without it are byte-
|
|
634
|
+
* identical.
|
|
635
|
+
*
|
|
636
|
+
* v1 slice: conversational turns only. In-DO voice turns are NOT replay-durable
|
|
637
|
+
* and get NO Workflow tool-loop — tool calls are deferred. All fields are
|
|
638
|
+
* optional; the defaults target Workers AI (`@cf/openai/whisper-large-v3-turbo`
|
|
639
|
+
* for STT, `@cf/deepgram/aura-1` for TTS).
|
|
640
|
+
* @experimental
|
|
641
|
+
*/
|
|
642
|
+
interface AgentVoiceConfig {
|
|
643
|
+
/**
|
|
644
|
+
* Server→client audio container. `"mp3"` (default) matches the TTS model's
|
|
645
|
+
* native stream; carried to the client so it decodes the returned frames
|
|
646
|
+
* with the right codec.
|
|
647
|
+
*/
|
|
648
|
+
audioFormat?: "mp3" | "wav";
|
|
649
|
+
/**
|
|
650
|
+
* Spoken on connect before the first user turn — a fixed greeting synthesized
|
|
651
|
+
* through the TTS model. Omit for a silent-until-spoken-to session.
|
|
652
|
+
*/
|
|
653
|
+
greeting?: string;
|
|
654
|
+
/**
|
|
655
|
+
* TTS voice/speaker id forwarded to the TTS model (e.g. a Deepgram Aura voice
|
|
656
|
+
* like `"aura-asteria-en"`). Model-specific; omitted when unset so the model
|
|
657
|
+
* uses its own default voice.
|
|
658
|
+
*/
|
|
659
|
+
speaker?: string;
|
|
660
|
+
/**
|
|
661
|
+
* Speech-to-text model id (a Workers AI id, resolved via `env.AI`). Defaults
|
|
662
|
+
* to `@cf/openai/whisper-large-v3-turbo` — batch per-utterance transcription
|
|
663
|
+
* (the client marks utterance boundaries; continuous STT is deferred).
|
|
664
|
+
*/
|
|
665
|
+
stt?: string;
|
|
666
|
+
/**
|
|
667
|
+
* Text-to-speech model id (a Workers AI id, resolved via `env.AI`). Defaults
|
|
668
|
+
* to `@cf/deepgram/aura-1` — streamed MP3 synthesized sentence-by-sentence
|
|
669
|
+
* from the LLM's token stream.
|
|
670
|
+
*/
|
|
671
|
+
tts?: string;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* The input the parent model provides when delegating to a sub-agent tool.
|
|
675
|
+
* @experimental
|
|
676
|
+
*/
|
|
677
|
+
interface AgentSubToolInput {
|
|
678
|
+
/** The task or question to hand to the sub-agent. */
|
|
679
|
+
prompt: string;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Options for {@link AgentDefinition.asTool} (`agent.asTool(...)`).
|
|
683
|
+
* @experimental
|
|
684
|
+
*/
|
|
685
|
+
interface AgentAsToolOptions {
|
|
686
|
+
/** What the sub-agent does — shown to the parent's model (it decides from it). */
|
|
687
|
+
description: string;
|
|
688
|
+
/** Cap on child-run status polls before giving up. Default 120. */
|
|
689
|
+
maxPolls?: number;
|
|
690
|
+
/**
|
|
691
|
+
* The child agent's export name — selects its `AGENT_<NAME>` Workflow
|
|
692
|
+
* binding (e.g. `"researcher"` → `AGENT_RESEARCHER`). The model-facing tool
|
|
693
|
+
* name is the KEY assigned in the parent's `tools` map, not this.
|
|
694
|
+
*/
|
|
695
|
+
name: string;
|
|
696
|
+
/** Delay (ms) between child-run status polls. Default 500. */
|
|
697
|
+
pollIntervalMs?: number;
|
|
698
|
+
/**
|
|
699
|
+
* Test seam replacing the between-poll wait. Production uses a real timer;
|
|
700
|
+
* tests inject an immediate resolve so polling runs without wall-clock delay.
|
|
701
|
+
*/
|
|
702
|
+
wait?: (ms: number) => Promise<void>;
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* A `defineAgent` result — config plus the brand codegen discovers.
|
|
706
|
+
* @experimental
|
|
707
|
+
*/
|
|
708
|
+
interface AgentDefinition extends AgentConfig {
|
|
709
|
+
/**
|
|
710
|
+
* Adapt this agent into a tool a PARENT agent can call: the returned tool's
|
|
711
|
+
* `execute` starts a durable child run on the named agent's Workflow binding
|
|
712
|
+
* and returns its final answer. Mirrors `@lunora/ai/rag`'s `asTool()`. The
|
|
713
|
+
* child run is correlated by a replay-stable `threadKey` derived from the
|
|
714
|
+
* parent's `toolCallId`, so a retried step reuses the same sub-run.
|
|
715
|
+
*/
|
|
716
|
+
asTool: (options: AgentAsToolOptions) => AgentToolDefinition<AgentSubToolInput, string>;
|
|
717
|
+
/** Runtime brand check (see `isAgentDefinition`). */
|
|
718
|
+
readonly isLunoraAgent: true;
|
|
719
|
+
/**
|
|
720
|
+
* The keyed memory sources the loop dispatches per run — the merge of
|
|
721
|
+
* {@link AgentConfig.memory} (as `key: "default"`) and each skill's
|
|
722
|
+
* `knowledge`. Populated by `defineAgent`; `memory` stays on the config for
|
|
723
|
+
* back-compat and direct authoring. When absent the loop falls back to
|
|
724
|
+
* `memory` alone (preserving the historic `"memory:retrieve"` step).
|
|
725
|
+
*/
|
|
726
|
+
memorySources?: ReadonlyArray<AgentMemorySource>;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Params of one agent run (the compiled workflow's payload).
|
|
730
|
+
* @experimental
|
|
731
|
+
*/
|
|
732
|
+
interface AgentRunInput {
|
|
733
|
+
/** The user message that starts (or continues) the thread. */
|
|
734
|
+
input: string;
|
|
735
|
+
/**
|
|
736
|
+
* Verified identity of the thread owner — pass `ctx.auth.userId` from the
|
|
737
|
+
* mutation/action starting the run. An owned thread's public queries
|
|
738
|
+
* (`agents:agentThread` / `agents:agentMessages`) only answer for this
|
|
739
|
+
* identity; omitting it leaves the thread readable by anyone who knows the
|
|
740
|
+
* key (only appropriate for single-tenant/anonymous apps). Immutable after
|
|
741
|
+
* the first run.
|
|
742
|
+
*/
|
|
743
|
+
owner?: string;
|
|
744
|
+
/** The thread key — reuse to continue a conversation. */
|
|
745
|
+
threadKey: string;
|
|
746
|
+
/** Optional thread title, set on first creation. */
|
|
747
|
+
title?: string;
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Output of one agent run (the compiled workflow's return value).
|
|
751
|
+
* @experimental
|
|
752
|
+
*/
|
|
753
|
+
interface AgentRunResult {
|
|
754
|
+
/** The parsed structured answer, when {@link AgentConfig.output} is set. */
|
|
755
|
+
output?: unknown;
|
|
756
|
+
/**
|
|
757
|
+
* Why the run ended: a final answer, a `stopWhen` condition, or the
|
|
758
|
+
* `maxTurns` cap.
|
|
759
|
+
*/
|
|
760
|
+
stopped: "final" | "maxTurns" | "stopCondition";
|
|
761
|
+
/** The final assistant text (absent when stopped by `maxTurns`). */
|
|
762
|
+
text?: string;
|
|
763
|
+
/** LLM turns consumed. */
|
|
764
|
+
turns: number;
|
|
765
|
+
/** Cumulative token usage across the run's turns, when the model reported it. */
|
|
766
|
+
usage?: AgentUsage;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Function paths of the agent runtime functions (the `agentComponent()`
|
|
770
|
+
* functions the app re-exports from `lunora/agents.ts`, so codegen registers
|
|
771
|
+
* them under the `agents:` namespace).
|
|
772
|
+
* @experimental
|
|
773
|
+
*/
|
|
774
|
+
interface AgentFunctionPaths {
|
|
775
|
+
appendMessage: string;
|
|
776
|
+
ensureThread: string;
|
|
777
|
+
/** The internal `agents:agentEpisodeRecall` query the loop dispatches for an episodic-kind read. */
|
|
778
|
+
episodeRecall: string;
|
|
779
|
+
/** The internal `agents:agentEpisodeUpsert` mutation the loop dispatches on run-end episode extraction. */
|
|
780
|
+
episodeUpsert: string;
|
|
781
|
+
/** The internal `agents:agentGraphTraverse` query the loop dispatches for a graph-kind read. */
|
|
782
|
+
graphTraverse: string;
|
|
783
|
+
/** The internal `agents:agentGraphUpsert` mutation the loop dispatches on run-end graph extraction. */
|
|
784
|
+
graphUpsert: string;
|
|
785
|
+
listMessages: string;
|
|
786
|
+
patchThread: string;
|
|
787
|
+
/**
|
|
788
|
+
* The public `agents:agentRun` mutation an HTTP-only client (e.g. the
|
|
789
|
+
* `@lunora/mcp` server) calls to START a durable run — owner-scoped to
|
|
790
|
+
* `ctx.auth.userId`, deterministic (the caller supplies `threadKey`).
|
|
791
|
+
*/
|
|
792
|
+
run: string;
|
|
793
|
+
/** The internal `agents:agentSetState` mutation the loop dispatches for `setState`. */
|
|
794
|
+
setState: string;
|
|
795
|
+
/** The public owner-gated `agents:agentState` query (`getState` + `useAgentState`). */
|
|
796
|
+
state: string;
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Approval lifecycle marker on a message: `"awaiting_approval"` on the
|
|
800
|
+
* placeholder written while a run pauses on a gated tool, then `"approved"` /
|
|
801
|
+
* `"rejected"` on the tool result once a client resolves it. Absent on ordinary
|
|
802
|
+
* messages. `"awaiting_approval"` rows are filtered out of the model prompt.
|
|
803
|
+
* @experimental
|
|
804
|
+
*/
|
|
805
|
+
type AgentMessageStatus = "approved" | "awaiting_approval" | "rejected";
|
|
806
|
+
/**
|
|
807
|
+
* One persisted thread message, as the loop reads it back.
|
|
808
|
+
* @experimental
|
|
809
|
+
*/
|
|
810
|
+
interface AgentMessageRow {
|
|
811
|
+
content: string;
|
|
812
|
+
role: "assistant" | "system" | "tool" | "user";
|
|
813
|
+
seq: number;
|
|
814
|
+
/** Approval lifecycle marker — see {@link AgentMessageStatus}. */
|
|
815
|
+
status?: AgentMessageStatus;
|
|
816
|
+
toolCallId?: string;
|
|
817
|
+
toolCalls?: ReadonlyArray<AgentToolCall>;
|
|
818
|
+
toolName?: string;
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* One model-issued tool call.
|
|
822
|
+
* @experimental
|
|
823
|
+
*/
|
|
824
|
+
interface AgentToolCall {
|
|
825
|
+
id: string;
|
|
826
|
+
input: unknown;
|
|
827
|
+
name: string;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Normalized result of one LLM turn (the `generate` seam's return value).
|
|
831
|
+
* @experimental
|
|
832
|
+
*/
|
|
833
|
+
interface AgentGenerateResult {
|
|
834
|
+
/** The parsed structured answer, when {@link AgentConfig.output} is set. */
|
|
835
|
+
output?: unknown;
|
|
836
|
+
text: string;
|
|
837
|
+
toolCalls: ReadonlyArray<AgentToolCall>;
|
|
838
|
+
/** Token usage the model reported for this turn. */
|
|
839
|
+
usage?: AgentUsage;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Options passed to the {@link AgentGenerate} seam for one LLM turn.
|
|
843
|
+
* @experimental
|
|
844
|
+
*/
|
|
845
|
+
interface AgentGenerateOptions {
|
|
846
|
+
/** Restrict the tools exposed to the model this turn (by name). */
|
|
847
|
+
activeTools?: ReadonlyArray<string>;
|
|
848
|
+
/** The assembled conversation for this turn. */
|
|
849
|
+
messages: ReadonlyArray<unknown>;
|
|
850
|
+
/** A per-turn model override (from {@link AgentConfig.prepareStep}). */
|
|
851
|
+
model?: LanguageModel;
|
|
852
|
+
/**
|
|
853
|
+
* Abort the in-flight turn (the streaming seam forwards it to `streamText`'s
|
|
854
|
+
* `abortSignal`). On abort the streaming seam returns the text streamed so
|
|
855
|
+
* far rather than rejecting, so a barge-in can persist the spoken prefix.
|
|
856
|
+
* The durable (non-streaming) loop never sets it.
|
|
857
|
+
*/
|
|
858
|
+
signal?: AbortSignal;
|
|
859
|
+
/** A per-turn tool-choice override. */
|
|
860
|
+
toolChoice?: ToolChoice<ToolSet>;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* The LLM-turn seam: given the assembled conversation, return the model's
|
|
864
|
+
* decision. Production wires AI SDK `generateText`; tests inject a script.
|
|
865
|
+
* @experimental
|
|
866
|
+
*/
|
|
867
|
+
type AgentGenerate = (options: AgentGenerateOptions) => Promise<AgentGenerateResult>;
|
|
868
|
+
/**
|
|
869
|
+
* The entities and relations extracted from one run's exchange, upserted into
|
|
870
|
+
* the owner-scoped graph. Endpoint names in `relations` reference entities by
|
|
871
|
+
* name (normalized on write); `confidence` (0..1) seeds an edge's weight.
|
|
872
|
+
*/
|
|
873
|
+
interface AgentGraphExtraction {
|
|
874
|
+
entities: ReadonlyArray<{
|
|
875
|
+
name: string;
|
|
876
|
+
type?: string;
|
|
877
|
+
}>;
|
|
878
|
+
relations: ReadonlyArray<{
|
|
879
|
+
confidence?: number;
|
|
880
|
+
dst: string;
|
|
881
|
+
label: string;
|
|
882
|
+
src: string;
|
|
883
|
+
}>;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* The run-end graph-extraction seam: given the run's exchange (user input +
|
|
887
|
+
* final answer) and the model to run it on, return the extracted entities and
|
|
888
|
+
* relations. Production wires AI SDK `generateObject` over a fixed schema
|
|
889
|
+
* (`createGraphExtract`); the durable loop calls it inside a memoized
|
|
890
|
+
* `memory:extract` step so the model never re-runs on replay. Absent (the
|
|
891
|
+
* default) disables extraction, so an agent with no graph memory — and every
|
|
892
|
+
* unit test that doesn't opt in — is byte-identical.
|
|
893
|
+
*/
|
|
894
|
+
type AgentGraphExtract = (input: {
|
|
895
|
+
/** The run's final assistant answer. */
|
|
896
|
+
assistantText: string;
|
|
897
|
+
/** The Worker env, for resolving a Workers AI model id. */
|
|
898
|
+
env: Record<string, unknown>;
|
|
899
|
+
/** The extraction model (the source's `extractionModel`, else the agent's). */
|
|
900
|
+
model: AgentModelInput;
|
|
901
|
+
/** The user message that started the run. */
|
|
902
|
+
userInput: string;
|
|
903
|
+
}) => Promise<AgentGraphExtraction>;
|
|
904
|
+
/**
|
|
905
|
+
* The history-compaction seam: given the OLDER model messages to condense (and
|
|
906
|
+
* the model to run it on), return a summary brief. Production wires AI SDK
|
|
907
|
+
* `generateText` (`createCompact`); the loop calls it INSIDE the turn's memoized
|
|
908
|
+
* `llm:turn:N` step so the summarization is replay-safe. Absent (the default)
|
|
909
|
+
* disables compaction, so an agent with no `compaction` config — and every unit
|
|
910
|
+
* test that doesn't opt in — is byte-identical.
|
|
911
|
+
*/
|
|
912
|
+
type AgentCompact = (input: {
|
|
913
|
+
/** The Worker env, for resolving a Workers AI model id. */
|
|
914
|
+
env: Record<string, unknown>;
|
|
915
|
+
/** The older conversation messages to summarize (already assembled). */
|
|
916
|
+
messages: ModelMessage[];
|
|
917
|
+
/** The compaction model (the config's `model`, else the agent's). */
|
|
918
|
+
model: AgentModelInput;
|
|
919
|
+
}) => Promise<string>;
|
|
920
|
+
/** The one-line summary an episodic-memory run records for later recency recall. */
|
|
921
|
+
interface AgentEpisodeExtraction {
|
|
922
|
+
summary: string;
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* The run-end episode-extraction seam: given the run's exchange and the model to
|
|
926
|
+
* run it on, return a one/two-sentence summary. Production wires AI SDK
|
|
927
|
+
* `generateText` (`createEpisodeExtract`); the durable loop calls it inside a
|
|
928
|
+
* memoized `memory:episode` step so the model never re-runs on replay. Absent
|
|
929
|
+
* (the default) disables extraction, so an agent with no episodic memory — and
|
|
930
|
+
* every unit test that doesn't opt in — is byte-identical.
|
|
931
|
+
*/
|
|
932
|
+
type AgentEpisodeExtract = (input: {
|
|
933
|
+
/** The run's final assistant answer. */
|
|
934
|
+
assistantText: string;
|
|
935
|
+
/** The Worker env, for resolving a Workers AI model id. */
|
|
936
|
+
env: Record<string, unknown>;
|
|
937
|
+
/** The extraction model (the source's `extractionModel`, else the agent's). */
|
|
938
|
+
model: AgentModelInput;
|
|
939
|
+
/** The user message that started the run. */
|
|
940
|
+
userInput: string;
|
|
941
|
+
}) => Promise<AgentEpisodeExtraction>;
|
|
942
|
+
/**
|
|
943
|
+
* A live token delta produced while a turn streams. Ephemeral — deltas are
|
|
944
|
+
* pushed to the sink as the model generates and are NEVER replayed (the
|
|
945
|
+
* persisted assistant message is the single source of truth). Keyed by
|
|
946
|
+
* `threadKey` + the zero-based `turn` so a client can correlate a delta to the
|
|
947
|
+
* in-flight turn.
|
|
948
|
+
* @experimental
|
|
949
|
+
*/
|
|
950
|
+
interface AgentTokenDelta {
|
|
951
|
+
/**
|
|
952
|
+
* Discriminates the token arm of {@link AgentLiveEvent}. Optional and left
|
|
953
|
+
* unset on the wire (a token is the default) so the existing emit site and
|
|
954
|
+
* its structural test assertions stay byte-identical; narrow the union with
|
|
955
|
+
* `event.kind === "progress"` to isolate the {@link AgentProgressEvent} arm.
|
|
956
|
+
*/
|
|
957
|
+
kind?: "token";
|
|
958
|
+
/** The incremental text chunk the model just produced. */
|
|
959
|
+
text: string;
|
|
960
|
+
/** The thread this delta belongs to. */
|
|
961
|
+
threadKey: string;
|
|
962
|
+
/** The zero-based index of the turn producing the delta. */
|
|
963
|
+
turn: number;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* A live, ephemeral progress event a tool emits via
|
|
967
|
+
* {@link AgentToolContext.reportProgress} while its durable step runs. Rides the
|
|
968
|
+
* SAME live-only sink as {@link AgentTokenDelta} — NEVER persisted, NEVER
|
|
969
|
+
* replayed. Correlated to the in-flight tool call (and its persisted tool row)
|
|
970
|
+
* by `toolCallId` rather than a turn index, since a single turn can fan out many
|
|
971
|
+
* tool calls.
|
|
972
|
+
* @experimental
|
|
973
|
+
*/
|
|
974
|
+
interface AgentProgressEvent {
|
|
975
|
+
/** The arbitrary, JSON-serializable payload the tool reported. */
|
|
976
|
+
data: unknown;
|
|
977
|
+
/** Discriminates the progress arm of {@link AgentLiveEvent}. */
|
|
978
|
+
kind: "progress";
|
|
979
|
+
/** The thread this event belongs to. */
|
|
980
|
+
threadKey: string;
|
|
981
|
+
/** The tool call this progress belongs to (correlates with the persisted tool row). */
|
|
982
|
+
toolCallId: string;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* A single event on the agent's live-only channel: either a streamed token
|
|
986
|
+
* {@link AgentTokenDelta} (turn-keyed) or a tool {@link AgentProgressEvent}
|
|
987
|
+
* (`toolCallId`-keyed). Both are ephemeral and never replayed — the persisted
|
|
988
|
+
* thread messages remain the single source of truth. Discriminate on `kind`
|
|
989
|
+
* (`"progress"` for the progress arm; token deltas leave it unset).
|
|
990
|
+
* @experimental
|
|
991
|
+
*/
|
|
992
|
+
type AgentLiveEvent = AgentProgressEvent | AgentTokenDelta;
|
|
993
|
+
/**
|
|
994
|
+
* A live-only sink for the agent's ephemeral channel — streamed token deltas
|
|
995
|
+
* ({@link AgentTokenDelta}) and tool progress events
|
|
996
|
+
* ({@link AgentProgressEvent}). The runtime provides it (teeing to the existing
|
|
997
|
+
* stream transport); tests capture it. Invoked ONLY on the first execution of a
|
|
998
|
+
* turn's / tool's durable step — a workflow replay serves the memoized result
|
|
999
|
+
* without re-running the body, so no event is re-emitted.
|
|
1000
|
+
*
|
|
1001
|
+
* At-least-once caveat: if a turn's step *fails mid-stream* (before it commits)
|
|
1002
|
+
* the workflow retries the not-yet-memoized step and re-tees that turn's deltas
|
|
1003
|
+
* from scratch. This is the standard durable-step retry contract, not a replay
|
|
1004
|
+
* of a completed turn. Consumers should therefore reset/dedupe accumulated text
|
|
1005
|
+
* per `threadKey`+`turn` boundary so a step retry cannot visually double-append;
|
|
1006
|
+
* the persisted assistant message remains the single source of truth.
|
|
1007
|
+
* @experimental
|
|
1008
|
+
*/
|
|
1009
|
+
type AgentTokenSink = (event: AgentLiveEvent) => void;
|
|
1010
|
+
/**
|
|
1011
|
+
* The streaming LLM-turn seam: like {@link AgentGenerate} but tees each text
|
|
1012
|
+
* delta to `onDelta` as the model produces it, then resolves the SAME
|
|
1013
|
+
* {@link AgentGenerateResult} the non-streaming seam returns — so the value the
|
|
1014
|
+
* durable `llm:turn:N` step memoizes (and persists) is identical whether the
|
|
1015
|
+
* turn streamed or not. Production wires AI SDK `streamText`; tests inject a
|
|
1016
|
+
* script. Deltas are live-only — a workflow replay never re-invokes the seam.
|
|
1017
|
+
* @experimental
|
|
1018
|
+
*/
|
|
1019
|
+
type AgentStreamGenerate = (options: AgentGenerateOptions, onDelta: (text: string) => void) => Promise<AgentGenerateResult>;
|
|
1020
|
+
/**
|
|
1021
|
+
* Spec entry codegen emits per agent: `{ binding: "AGENT_SUPPORT", exportName: "support" }`.
|
|
1022
|
+
* @experimental
|
|
1023
|
+
*/
|
|
1024
|
+
interface AgentBindingSpec {
|
|
1025
|
+
binding: string;
|
|
1026
|
+
exportName: string;
|
|
1027
|
+
/**
|
|
1028
|
+
* Whether the app author opted this agent into public run-starts (via
|
|
1029
|
+
* `defineAgent({ publicRun: true })`) — codegen emits it only when `true`.
|
|
1030
|
+
* Carried onto the {@link AgentHandle} so the public `agents:agentRun`
|
|
1031
|
+
* mutation gates on it fail-closed: an agent without it can be started only
|
|
1032
|
+
* from server-side app code, never by an external RPC client.
|
|
1033
|
+
*/
|
|
1034
|
+
publicRun?: boolean;
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* The lifecycle status stored on an agent thread: `"running"` while a run is in
|
|
1038
|
+
* flight, `"idle"` after it finishes (or stops on a condition), `"error"` on a
|
|
1039
|
+
* terminal failure, `"cancelled"` when a run was terminated via
|
|
1040
|
+
* {@link AgentHandle.cancel}, and `"awaiting_input"` while the run is paused on
|
|
1041
|
+
* a human-in-the-loop tool approval. Mirrored by the `status` `v.union` in
|
|
1042
|
+
* `component.ts`.
|
|
1043
|
+
* @experimental
|
|
1044
|
+
*/
|
|
1045
|
+
type AgentThreadStatus = "awaiting_input" | "cancelled" | "error" | "idle" | "running";
|
|
1046
|
+
/**
|
|
1047
|
+
* Structural subset of a Cloudflare Workflow instance the producer surface needs.
|
|
1048
|
+
* @experimental
|
|
1049
|
+
*/
|
|
1050
|
+
interface AgentWorkflowInstanceLike {
|
|
1051
|
+
/** Deliver an external event to the running instance (resumes a `waitForEvent`). */
|
|
1052
|
+
sendEvent: (event: {
|
|
1053
|
+
payload: unknown;
|
|
1054
|
+
type: string;
|
|
1055
|
+
}) => Promise<void>;
|
|
1056
|
+
status: () => Promise<unknown>;
|
|
1057
|
+
terminate: () => Promise<void>;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Structural subset of a Cloudflare Workflow binding the producer surface needs.
|
|
1061
|
+
* @experimental
|
|
1062
|
+
*/
|
|
1063
|
+
interface AgentWorkflowBindingLike {
|
|
1064
|
+
create: (options?: {
|
|
1065
|
+
id?: string;
|
|
1066
|
+
params?: unknown;
|
|
1067
|
+
}) => Promise<{
|
|
1068
|
+
id: string;
|
|
1069
|
+
}>;
|
|
1070
|
+
get: (id: string) => Promise<AgentWorkflowInstanceLike>;
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* A started agent run (a workflow instance).
|
|
1074
|
+
* @experimental
|
|
1075
|
+
*/
|
|
1076
|
+
interface AgentRunHandle {
|
|
1077
|
+
/** The workflow instance id. */
|
|
1078
|
+
id: string;
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* The `ctx.agents.<name>` producer handle.
|
|
1082
|
+
* @experimental
|
|
1083
|
+
*/
|
|
1084
|
+
interface AgentHandle {
|
|
1085
|
+
/**
|
|
1086
|
+
* Cancel a run by its workflow instance id: terminate the instance and mark
|
|
1087
|
+
* its thread `"cancelled"`. Safe to call on an already-finished run.
|
|
1088
|
+
*/
|
|
1089
|
+
cancel: (id: string) => Promise<void>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Whether this agent may be started over the PUBLIC `agents:agentRun`
|
|
1092
|
+
* mutation (the `defineAgent({ publicRun: true })` opt-in, carried from the
|
|
1093
|
+
* codegen wiring spec). `false` by default — the run mutation refuses it
|
|
1094
|
+
* fail-closed, so declaring an agent never exposes it to arbitrary RPC
|
|
1095
|
+
* callers. Does not affect the server-side `run(...)` path below.
|
|
1096
|
+
*/
|
|
1097
|
+
publicRun: boolean;
|
|
1098
|
+
/** Start a durable agent run for a thread. */
|
|
1099
|
+
run: (input: AgentRunInput, options?: {
|
|
1100
|
+
id?: string;
|
|
1101
|
+
}) => Promise<AgentRunHandle>;
|
|
1102
|
+
/**
|
|
1103
|
+
* Deliver an external event to a run by its workflow instance id — the path
|
|
1104
|
+
* `agents:agentResolveApproval` uses to resume a run paused on a
|
|
1105
|
+
* human-in-the-loop tool approval.
|
|
1106
|
+
*/
|
|
1107
|
+
sendEvent: (id: string, event: {
|
|
1108
|
+
payload: unknown;
|
|
1109
|
+
type: string;
|
|
1110
|
+
}) => Promise<void>;
|
|
1111
|
+
/** Read a run's workflow status by instance id. */
|
|
1112
|
+
status: (id: string) => Promise<unknown>;
|
|
1113
|
+
}
|
|
1114
|
+
export { AgentDefinition as A, AgentGenerateOptions as B, AgentGenerateResult as C, AgentInstructionsContext as D, AgentLiveEvent as E, AgentMemoryOptions as F, AgentMemorySource as G, AgentMessageStatus as H, InboundChannelEvent as I, AgentOnStepFinish as J, AgentPrepareStep as K, AgentPrepareStepInput as L, AgentPrepareStepResult as M, AgentProgressEvent as N, AgentRunHandle as O, AgentStepFinishInfo as P, AgentStepInfo as Q, AgentThreadStatus as R, SkillDefinition as S, AgentTokenDelta as T, AgentToolCall as U, AgentUsage as V, AgentVoiceConfig as W, AgentWorkflowBindingLike as X, AgentWorkflowInstanceLike as Y, AgentToolContext as a, AgentToolDefinition as b, AgentCompact as c, AgentEpisodeExtract as d, AgentGraphExtract as e, AgentGenerate as f, AgentTokenSink as g, AgentRunInput as h, AgentFunctionPaths as i, AgentRunFunction as j, AgentStepLike as k, AgentStreamGenerate as l, AgentRunResult as m, AgentMessageRow as n, AgentConfig as o, AnyAgentTool as p, AgentAsToolOptions as q, AgentSubToolInput as r, AgentBindingSpec as s, AgentHandle as t, AgentToolConfig as u, AgentFunctionReference as v, AgentModelInput as w, SkillConfig as x, AgentEmailMapper as y, AgentEmailRun as z };
|