@cairnvibe/sdk 0.2.13 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-loop.d.ts +113 -0
- package/dist/agent-loop.js +128 -0
- package/dist/cairn-widget.js +2 -2
- package/dist/element-ladder.d.ts +71 -0
- package/dist/element-ladder.js +168 -0
- package/dist/index.d.ts +79 -1
- package/dist/index.js +864 -89
- package/dist/key-rotator.d.ts +28 -0
- package/dist/key-rotator.js +57 -3
- package/dist/memory-sqlite.d.ts +86 -0
- package/dist/memory-sqlite.js +230 -0
- package/dist/realtime-cli.js +22 -1
- package/dist/realtime-server.d.ts +83 -2
- package/dist/realtime-server.js +549 -120
- package/dist/server.d.ts +249 -5
- package/dist/server.js +984 -77
- package/dist/skill-store.d.ts +17 -0
- package/dist/skill-store.js +78 -0
- package/dist/tts-stream.d.ts +25 -0
- package/dist/tts-stream.js +32 -0
- package/dist/vad.d.ts +27 -0
- package/dist/vad.js +128 -0
- package/dist/verb-executor.d.ts +32 -11
- package/dist/verb-executor.js +224 -16
- package/dist/webmcp-client.d.ts +14 -1
- package/dist/webmcp-client.js +22 -1
- package/package.json +3 -1
- package/src/agent-loop.ts +222 -0
- package/src/element-ladder.ts +170 -0
- package/src/index.tsx +914 -93
- package/src/key-rotator.ts +57 -2
- package/src/memory-sqlite.ts +283 -0
- package/src/realtime-cli.ts +24 -1
- package/src/realtime-server.ts +655 -122
- package/src/server.ts +1077 -77
- package/src/skill-store.ts +88 -0
- package/src/tts-stream.ts +30 -0
- package/src/vad.ts +153 -0
- package/src/verb-executor.ts +243 -22
- package/src/web-component.ts +82 -17
- package/src/webmcp-client.ts +30 -2
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type HistoryTurn, type LiveElement, type Manifest, type VerbResponse, type WebMcpTool } from "@cairnvibe/core";
|
|
1
|
+
import { type CriticVerdict, type HistoryTurn, type LiveElement, type Manifest, type Plan, type Skill, type SkillSummary, type Task, type UiPatternId, type VerbResponse, type WebMcpTool } from "@cairnvibe/core";
|
|
2
|
+
import { type MemoryStore } from "./memory-sqlite";
|
|
2
3
|
import { KeyRotator } from "./key-rotator";
|
|
4
|
+
import type { SkillStore } from "./skill-store";
|
|
3
5
|
/**
|
|
4
6
|
* What the agent is allowed to do, independent of which specific "do"
|
|
5
7
|
* actions are registered:
|
|
@@ -17,10 +19,50 @@ export interface CreateCopilotHandlerOptions {
|
|
|
17
19
|
model?: string;
|
|
18
20
|
/** Action ids this deployment actually supports. "do" is refused for anything else. */
|
|
19
21
|
registeredActions?: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Phase 4, layer 5 — real, human-written descriptions for `registeredActions`
|
|
24
|
+
* ids, e.g. `{ archiveInvoice: "Archives the invoice; cannot be undone." }`.
|
|
25
|
+
* Optional and purely additive: an id with no entry here still works
|
|
26
|
+
* exactly as before (rendered bare, no description) — this was the
|
|
27
|
+
* weakest-typed of Cairn's three action-invocation mechanisms (a
|
|
28
|
+
* registered action id carried literally zero server-visible metadata,
|
|
29
|
+
* unlike a WebMCP tool's own description or an element's `does` text);
|
|
30
|
+
* this closes that gap without changing what the model must echo back
|
|
31
|
+
* in "action" (still the bare id — see renderRegisteredActions).
|
|
32
|
+
*/
|
|
33
|
+
actionDescriptions?: Record<string, string>;
|
|
20
34
|
/** What the agent is allowed to do at all. Defaults to "act". See `CapabilityTier`. */
|
|
21
35
|
capability?: CapabilityTier;
|
|
22
36
|
/** Display name / identity for the agent, woven into its system prompt and shown in the widget. Defaults to "Cairn". */
|
|
23
37
|
persona?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Phase 5 step 4 — real cross-session memory for the typed/HTTP
|
|
40
|
+
* transport (packages/sdk/src/memory-sqlite.ts, or any store
|
|
41
|
+
* implementing the same interface). Optional — omitting it keeps
|
|
42
|
+
* every request exactly as memory-less as before this existed.
|
|
43
|
+
* Scoped by whatever `scopeId` string the request itself carries
|
|
44
|
+
* (`CopilotRequestSchema.scopeId`) — this SDK invents no identity of
|
|
45
|
+
* its own. Unlike the realtime relay (one persistent connection
|
|
46
|
+
* remembers a scopeId once), this transport is stateless per
|
|
47
|
+
* request: `resolveVerb`'s own callers seed from memory only when the
|
|
48
|
+
* REQUEST's own `history` arrives empty (a genuinely fresh session —
|
|
49
|
+
* see `createCopilotHandlerWithLLM`), never on every request, so a
|
|
50
|
+
* session already accumulating its own history client-side isn't
|
|
51
|
+
* re-seeded on top of itself.
|
|
52
|
+
*/
|
|
53
|
+
memory?: MemoryStore;
|
|
54
|
+
/**
|
|
55
|
+
* Architecture Pillar 3 (Skill half) — real, per-deployment Skill
|
|
56
|
+
* storage (packages/sdk/src/skill-store.ts). A DIFFERENT scope axis
|
|
57
|
+
* than `memory` above — see skill-store.ts's own doc comment. Optional;
|
|
58
|
+
* omitting it keeps every request exactly as it was before this
|
|
59
|
+
* existed. Consumed by `createPlanHandler` (retrieval — a matching
|
|
60
|
+
* Skill's full instructions get surfaced to the Planner) and
|
|
61
|
+
* `createSkillSaveHandler` (the Formulator's own save side).
|
|
62
|
+
*/
|
|
63
|
+
skills?: SkillStore;
|
|
64
|
+
/** The deployment-wide scope Skills are stored/looked up under when `skills` is configured. Defaults to "default" when omitted. */
|
|
65
|
+
skillsScopeId?: string;
|
|
24
66
|
}
|
|
25
67
|
export interface CopilotHandlerResult {
|
|
26
68
|
status: number;
|
|
@@ -52,6 +94,8 @@ export declare function createCopilotHandlerWithLLM(manifest: Manifest, llm: Ver
|
|
|
52
94
|
registeredActions?: string[];
|
|
53
95
|
capability?: CapabilityTier;
|
|
54
96
|
persona?: string;
|
|
97
|
+
actionDescriptions?: Record<string, string>;
|
|
98
|
+
memory?: MemoryStore;
|
|
55
99
|
}): CopilotHandler;
|
|
56
100
|
/**
|
|
57
101
|
* The safety-critical core, shared by the HTTP handler above and the
|
|
@@ -67,15 +111,184 @@ export declare function resolveVerb(llm: VerbLLM, systemPrompt: string, manifest
|
|
|
67
111
|
liveElements?: LiveElement[];
|
|
68
112
|
webMcpTools?: WebMcpTool[];
|
|
69
113
|
}): Promise<VerbResponse>;
|
|
114
|
+
/**
|
|
115
|
+
* Phase 3, step 2 (see DEVELOPMENT.md/the plan file) — the Planner half
|
|
116
|
+
* of the Planner/Executor/Critic/Talker redesign. Decomposes a real end
|
|
117
|
+
* goal into an ordered task list BEFORE any execution happens, mirroring
|
|
118
|
+
* resolveVerb's own resilience discipline: never throws to the caller,
|
|
119
|
+
* degrades to a real, usable single-task fallback plan on any failure
|
|
120
|
+
* (a bad LLM response, a schema mismatch, a network error) rather than
|
|
121
|
+
* blocking the turn on a Planner hiccup. `version`/each task's `status`
|
|
122
|
+
* are harness-owned, not asked of the model (PlannerOutputSchema's own
|
|
123
|
+
* doc comment) — assembled here around the model's raw output.
|
|
124
|
+
*
|
|
125
|
+
* Deliberately does NOT yet change what the loop actually does with the
|
|
126
|
+
* result — step 2's own scope is observability only (see the doc comment
|
|
127
|
+
* on this function's call site in realtime-server.ts). The Critic (step
|
|
128
|
+
* 3) is what makes a Plan's tasks/doneContracts actually drive behavior.
|
|
129
|
+
*/
|
|
130
|
+
export declare function resolvePlan(llm: VerbLLM, goal: string, version?: number, manifest?: Manifest, actionsText?: string, skills?: {
|
|
131
|
+
summariesText?: string;
|
|
132
|
+
suggestedInstructions?: string;
|
|
133
|
+
}): Promise<Plan>;
|
|
134
|
+
/** The real, single-task plan used when the Planner call itself fails —
|
|
135
|
+
* "do the whole goal as one task" is always a valid (if unstructured)
|
|
136
|
+
* plan, so a Planner hiccup degrades the redesign back to today's
|
|
137
|
+
* behavior instead of blocking the turn. Exported so every caller that
|
|
138
|
+
* needs "a plan, even a trivial one, right now" (e.g. a Critic call that
|
|
139
|
+
* fires before a real Planner result has come back) builds the exact
|
|
140
|
+
* same shape instead of hand-rolling a duplicate literal — realtime-
|
|
141
|
+
* server.ts's own finalizeTurn and index.tsx's runTypedAgentLoop both do
|
|
142
|
+
* this, for the same reason. */
|
|
143
|
+
export declare function fallbackPlan(goal: string, version: number): Plan;
|
|
144
|
+
/**
|
|
145
|
+
* Phase 3, step 3 — the Critic. A genuinely SEPARATE pass over the
|
|
146
|
+
* step's real observation, decoupled from the Executor/model's own
|
|
147
|
+
* self-report — this is the direct fix for the diagnosed bug (a batch
|
|
148
|
+
* of 2 clicks succeeded, and the model kept looping 4 more iterations
|
|
149
|
+
* before giving up, never recognizing its own success). Mirrors
|
|
150
|
+
* packages/evals/src/judge.ts's own judgeScenario shape on purpose (a
|
|
151
|
+
* separate model looking at real state, forced tool call, structured
|
|
152
|
+
* verdict) — same real precedent already proven and tested in this repo,
|
|
153
|
+
* not a new pattern invented for this. Same resilience discipline as
|
|
154
|
+
* resolveVerb/resolvePlan: never throws, degrades to a real "continue"
|
|
155
|
+
* verdict (harmless — the loop just behaves as if the Critic weren't
|
|
156
|
+
* there for this one step) on any failure.
|
|
157
|
+
*/
|
|
158
|
+
export declare function resolveCritic(llm: VerbLLM, task: Task, goal: string, verb: VerbResponse, observation: string | null | undefined): Promise<CriticVerdict>;
|
|
159
|
+
/** Same real rotation/model-selection logic as createVerbLLM/createPlanLLM,
|
|
160
|
+
* configured for the Critic's own tool instead — see resolveCritic. */
|
|
161
|
+
export declare function createCriticLLM(options?: CreateCopilotHandlerOptions): VerbLLM;
|
|
70
162
|
/** Builds the provider-appropriate VerbLLM from the same options createCopilotHandler accepts — reused by the realtime relay. */
|
|
71
163
|
export declare function createVerbLLM(options?: CreateCopilotHandlerOptions): VerbLLM;
|
|
164
|
+
/** Same real rotation/model-selection logic as createVerbLLM, configured
|
|
165
|
+
* for the Planner's own tool instead — see resolvePlan. */
|
|
166
|
+
export declare function createPlanLLM(options?: CreateCopilotHandlerOptions): VerbLLM;
|
|
167
|
+
/**
|
|
168
|
+
* Architecture Pillar 3 (Skill half) — the Formulator. Runs once a task
|
|
169
|
+
* genuinely completes (not per-step — cheap on purpose, matching the plan
|
|
170
|
+
* file's own framing), compiling whatever real, Critic-verified
|
|
171
|
+
* `learnedFact`s were collected along the way (CriticVerdictSchema's own
|
|
172
|
+
* doc comment is the enforcement point for "never user data") into one
|
|
173
|
+
* Skill. Deliberately DETERMINISTIC, not a fourth kind of real LLM call —
|
|
174
|
+
* every fact it compiles already passed through the Critic's own
|
|
175
|
+
* verification, so there's nothing left to "figure out" that would
|
|
176
|
+
* justify the added cost/latency/failure surface of another model round
|
|
177
|
+
* trip; see DEVELOPMENT.md's own entry for the real cost reasoning
|
|
178
|
+
* (this session already hit genuine Groq quota exhaustion more than once
|
|
179
|
+
* from cumulative call volume). Returns null when nothing was learned —
|
|
180
|
+
* the common case, not an error; a caller should simply not save anything.
|
|
181
|
+
*/
|
|
182
|
+
export declare function compileSkill(goal: string, learnedFacts: string[], pattern?: UiPatternId): Skill | null;
|
|
183
|
+
/**
|
|
184
|
+
* Architecture Pillar 3 (Skill half) — the retrieval side. A cheap,
|
|
185
|
+
* deterministic keyword-overlap match against a NEW goal (never another
|
|
186
|
+
* real LLM call, same reasoning as compileSkill above) — real progressive
|
|
187
|
+
* disclosure: every Skill's summary is cheap enough to always list (see
|
|
188
|
+
* SkillStore's own doc comment), but only the ONE Skill whose own name
|
|
189
|
+
* shares real, significant words with the current goal gets its full
|
|
190
|
+
* instructions loaded. A caller still needs its own SkillStore.getSkill
|
|
191
|
+
* call to fetch those full instructions for whatever this returns — this
|
|
192
|
+
* function only ever sees cheap summaries, never a full Skill.
|
|
193
|
+
*/
|
|
194
|
+
export declare function matchSkillByGoal(summaries: SkillSummary[], goal: string): SkillSummary | null;
|
|
195
|
+
/** Same rendering discipline as renderRegisteredActions — "id (description)" per Skill, for the Planner's own userMessage. */
|
|
196
|
+
export declare function renderSkillSummaries(summaries: SkillSummary[]): string;
|
|
197
|
+
export type PlanHandler = (body: unknown) => Promise<{
|
|
198
|
+
status: number;
|
|
199
|
+
body: Plan | {
|
|
200
|
+
error: string;
|
|
201
|
+
};
|
|
202
|
+
}>;
|
|
203
|
+
export type CriticHandler = (body: unknown) => Promise<{
|
|
204
|
+
status: number;
|
|
205
|
+
body: CriticVerdict | {
|
|
206
|
+
error: string;
|
|
207
|
+
};
|
|
208
|
+
}>;
|
|
209
|
+
/**
|
|
210
|
+
* Architecture Pillar 4 — the typed/HTTP transport's own real Planner
|
|
211
|
+
* endpoint, closing the gap the plan file names directly: "the typed/
|
|
212
|
+
* HTTP path (index.tsx's runTypedAgentLoop) has zero Planner/Critic
|
|
213
|
+
* wiring at all... today explicitly realtime-only by deferral, not by
|
|
214
|
+
* decision." A thin HTTP wrapper around the exact same resolvePlan the
|
|
215
|
+
* realtime relay already calls in-process — the LLM call itself only
|
|
216
|
+
* ever needs to happen server-side (it holds the real API key), so a
|
|
217
|
+
* client-side caller (index.tsx) reaches it over a real request instead
|
|
218
|
+
* of importing resolvePlan directly, same reasoning as createCopilotHandler
|
|
219
|
+
* itself.
|
|
220
|
+
*/
|
|
221
|
+
export declare function createPlanHandler(manifest: Manifest, options?: CreateCopilotHandlerOptions): PlanHandler;
|
|
222
|
+
/** Same as createPlanHandler, but with the LLM injected — used by tests to fake it, same pattern as createCopilotHandlerWithLLM. */
|
|
223
|
+
export declare function createPlanHandlerWithLLM(manifest: Manifest, planLLM: VerbLLM, options?: {
|
|
224
|
+
registeredActions?: string[];
|
|
225
|
+
actionDescriptions?: Record<string, string>;
|
|
226
|
+
skills?: SkillStore;
|
|
227
|
+
skillsScopeId?: string;
|
|
228
|
+
}): PlanHandler;
|
|
229
|
+
/** Architecture Pillar 4's Critic counterpart to createPlanHandler — see
|
|
230
|
+
* its own doc comment. A thin HTTP wrapper around the same resolveCritic
|
|
231
|
+
* the realtime relay already calls in-process. */
|
|
232
|
+
export declare function createCriticHandler(options?: CreateCopilotHandlerOptions): CriticHandler;
|
|
233
|
+
/** Same as createCriticHandler, but with the LLM injected — used by tests to fake it. */
|
|
234
|
+
export declare function createCriticHandlerWithLLM(criticLLM: VerbLLM): CriticHandler;
|
|
235
|
+
export type SkillSaveHandler = (body: unknown) => Promise<{
|
|
236
|
+
status: number;
|
|
237
|
+
body: {
|
|
238
|
+
saved: boolean;
|
|
239
|
+
} | {
|
|
240
|
+
error: string;
|
|
241
|
+
};
|
|
242
|
+
}>;
|
|
243
|
+
/**
|
|
244
|
+
* Architecture Pillar 3 (Skill half) — the typed transport's own save
|
|
245
|
+
* side (the Formulator's HTTP counterpart to realtime-server.ts's own
|
|
246
|
+
* in-process `compileSkill`+`saveSkill` call at the end of `finalizeTurn`).
|
|
247
|
+
* No LLM involved — `compileSkill` is deterministic (see its own doc
|
|
248
|
+
* comment for why) — so this needs no `-WithLLM` variant; it's real
|
|
249
|
+
* client-callable storage access, nothing more. The caller (index.tsx's
|
|
250
|
+
* runTypedAgentLoop) accumulates `learnedFacts` from its own Critic calls
|
|
251
|
+
* across one whole turn and posts here exactly once, after the turn
|
|
252
|
+
* concludes — never per-step, matching the Formulator's own "cheap on
|
|
253
|
+
* purpose" framing.
|
|
254
|
+
*/
|
|
255
|
+
export declare function createSkillSaveHandler(skills: SkillStore, skillsScopeId?: string): SkillSaveHandler;
|
|
256
|
+
/**
|
|
257
|
+
* Phase 2 step 1 — a genuinely UNSTRUCTURED, streamed call: no tools, no
|
|
258
|
+
* forced choice, just the model's plain spoken answer to the user's
|
|
259
|
+
* question, delivered incrementally. Exists because a real, live spike
|
|
260
|
+
* against Groq's actual API (see DEVELOPMENT.md/the plan file's Phase 2
|
|
261
|
+
* entry) found that a FORCED tool call never streams at the field level
|
|
262
|
+
* even with stream:true — the whole structured object arrives in one
|
|
263
|
+
* chunk. Plain, unforced generation genuinely streams token-by-token on
|
|
264
|
+
* both providers, and finishes faster besides — this is what makes "LLM
|
|
265
|
+
* tokens streamed straight into TTS" possible at all.
|
|
266
|
+
*/
|
|
267
|
+
export interface StreamingTextLLM {
|
|
268
|
+
respondStreamed(systemPrompt: string, userMessage: string, onChunk: (delta: string) => void): Promise<string>;
|
|
269
|
+
}
|
|
72
270
|
export declare class AnthropicVerbLLM implements VerbLLM {
|
|
73
271
|
private client;
|
|
74
272
|
private model;
|
|
75
273
|
private toolSchema;
|
|
76
|
-
|
|
274
|
+
private toolName;
|
|
275
|
+
private toolDescription;
|
|
276
|
+
constructor(client: MessagesClient, model: string, toolSchema: Record<string, unknown>, toolName?: string, toolDescription?: string);
|
|
77
277
|
respond(systemPrompt: string, userMessage: string): Promise<unknown>;
|
|
78
278
|
}
|
|
279
|
+
/** Minimal shape AnthropicStreamingTextLLM needs — narrow enough to fake in tests (a plain async generator, no real SDK stream class). */
|
|
280
|
+
export interface StreamingMessagesClient {
|
|
281
|
+
messages: {
|
|
282
|
+
create: (params: any) => Promise<AsyncIterable<any>>;
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/** No tools, no tool_choice — see StreamingTextLLM's own doc comment for why plain, unforced generation is what streams. */
|
|
286
|
+
export declare class AnthropicStreamingTextLLM implements StreamingTextLLM {
|
|
287
|
+
private client;
|
|
288
|
+
private model;
|
|
289
|
+
constructor(client: StreamingMessagesClient, model: string);
|
|
290
|
+
respondStreamed(systemPrompt: string, userMessage: string, onChunk: (delta: string) => void): Promise<string>;
|
|
291
|
+
}
|
|
79
292
|
/** Minimal shape GroqVerbLLM needs — narrow enough to fake in tests. */
|
|
80
293
|
export interface GroqLikeClient {
|
|
81
294
|
chat: {
|
|
@@ -91,11 +304,42 @@ export declare class GroqVerbLLM implements VerbLLM {
|
|
|
91
304
|
private model;
|
|
92
305
|
private toolSchema;
|
|
93
306
|
private clientFactory;
|
|
94
|
-
|
|
307
|
+
private toolName;
|
|
308
|
+
private toolDescription;
|
|
309
|
+
constructor(keys: KeyRotator, model: string, toolSchema: Record<string, unknown>, clientFactory?: (apiKey: string) => GroqLikeClient, toolName?: string, toolDescription?: string);
|
|
95
310
|
respond(systemPrompt: string, userMessage: string): Promise<unknown>;
|
|
96
311
|
private attemptRespond;
|
|
97
312
|
}
|
|
98
|
-
|
|
313
|
+
/** Minimal shape GroqStreamingTextLLM needs — narrow enough to fake in tests (a plain async generator, no real SDK stream class). */
|
|
314
|
+
export interface GroqLikeStreamingClient {
|
|
315
|
+
chat: {
|
|
316
|
+
completions: {
|
|
317
|
+
create: (params: any) => Promise<AsyncIterable<any>>;
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/** No tools, no tool_choice — see StreamingTextLLM's own doc comment for why plain, unforced generation is what streams. No retry-on-hallucinated-tool-name logic here (GroqVerbLLM's own real, live-found bug) — there's no tool to hallucinate the name of. */
|
|
322
|
+
export declare class GroqStreamingTextLLM implements StreamingTextLLM {
|
|
323
|
+
private keys;
|
|
324
|
+
private model;
|
|
325
|
+
private clientFactory;
|
|
326
|
+
constructor(keys: KeyRotator, model: string, clientFactory?: (apiKey: string) => GroqLikeStreamingClient);
|
|
327
|
+
respondStreamed(systemPrompt: string, userMessage: string, onChunk: (delta: string) => void): Promise<string>;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Phase 4, layer 5 — the ONE place a registered action id is rendered
|
|
331
|
+
* with its (optional) real description, shared by buildVerbToolSchema,
|
|
332
|
+
* buildSystemPrompt's own do-verb text, and resolvePlan's userMessage —
|
|
333
|
+
* so the Executor and the Planner describe the exact same capability the
|
|
334
|
+
* exact same way, and there's no risk of the three drifting out of sync.
|
|
335
|
+
* Deliberately renders "id (description)" rather than baking the
|
|
336
|
+
* description into what the model must echo back — resolveVerb's own
|
|
337
|
+
* `registeredActions.includes(parsedVerb.data.action)` check (server.ts)
|
|
338
|
+
* needs the RAW id back, verbatim, or a real registered action would
|
|
339
|
+
* silently stop being recognized.
|
|
340
|
+
*/
|
|
341
|
+
export declare function renderRegisteredActions(registeredActions: string[], actionDescriptions?: Record<string, string>): string;
|
|
342
|
+
export declare function buildVerbToolSchema(registeredActions: string[], actionDescriptions?: Record<string, string>): Record<string, unknown>;
|
|
99
343
|
/**
|
|
100
344
|
* A compact route directory — NOT every element on every page. Found live
|
|
101
345
|
* and necessary, not theoretical: a real 17-page production app's full
|
|
@@ -111,4 +355,4 @@ export declare function buildVerbToolSchema(registeredActions: string[]): Record
|
|
|
111
355
|
* element detail is attached separately, per request, in resolveVerb —
|
|
112
356
|
* see buildPageElements.
|
|
113
357
|
*/
|
|
114
|
-
export declare function buildSystemPrompt(manifest: Manifest, registeredActions: string[], persona?: string): string;
|
|
358
|
+
export declare function buildSystemPrompt(manifest: Manifest, registeredActions: string[], persona?: string, actionDescriptions?: Record<string, string>): string;
|