@nightowlsdev/core 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/LICENSE +21 -0
- package/dist/index.cjs +1588 -0
- package/dist/index.d.cts +814 -0
- package/dist/index.d.ts +814 -0
- package/dist/index.js +1534 -0
- package/dist/test-utils.cjs +75 -0
- package/dist/test-utils.d.cts +87 -0
- package/dist/test-utils.d.ts +87 -0
- package/dist/test-utils.js +44 -0
- package/package.json +58 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,814 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
interface SwarmContext {
|
|
4
|
+
tenantId: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
agentSlug: string;
|
|
7
|
+
agentVersion?: number;
|
|
8
|
+
runId: string;
|
|
9
|
+
threadId: string;
|
|
10
|
+
}
|
|
11
|
+
interface AuthContext {
|
|
12
|
+
tenantId: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
capabilities?: string[];
|
|
15
|
+
}
|
|
16
|
+
interface AuthProvider {
|
|
17
|
+
authenticate(req: Request): Promise<AuthContext | null>;
|
|
18
|
+
can?(ctx: AuthContext, capability: string): boolean | Promise<boolean>;
|
|
19
|
+
}
|
|
20
|
+
interface SecretResolver {
|
|
21
|
+
resolve(ref: string, ctx: SwarmContext): Promise<string>;
|
|
22
|
+
}
|
|
23
|
+
/** An optional rich input the asking agent CONSTRUCTS for a HITL `ask`, so the UI can render a fitting
|
|
24
|
+
* widget instead of a bare text box. Omitted ⇒ a plain text input. Answer shape by kind: confirm→boolean,
|
|
25
|
+
* buttons/select→the chosen `value`, multiselect→`value[]`, number→number, text/textarea→string. */
|
|
26
|
+
interface AskFieldOption {
|
|
27
|
+
label: string;
|
|
28
|
+
value: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
}
|
|
31
|
+
interface AskField {
|
|
32
|
+
kind: "confirm" | "buttons" | "select" | "multiselect" | "number" | "text" | "textarea";
|
|
33
|
+
/** buttons | select | multiselect */
|
|
34
|
+
options?: AskFieldOption[];
|
|
35
|
+
/** number */
|
|
36
|
+
min?: number;
|
|
37
|
+
max?: number;
|
|
38
|
+
step?: number;
|
|
39
|
+
unit?: string;
|
|
40
|
+
/** text | textarea */
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
rows?: number;
|
|
43
|
+
/** confirm */
|
|
44
|
+
confirmLabel?: string;
|
|
45
|
+
rejectLabel?: string;
|
|
46
|
+
/** any kind with a submit action */
|
|
47
|
+
submitLabel?: string;
|
|
48
|
+
/** prefilled value */
|
|
49
|
+
default?: unknown;
|
|
50
|
+
}
|
|
51
|
+
interface EvBase {
|
|
52
|
+
runId: string;
|
|
53
|
+
agentSlug: string;
|
|
54
|
+
ts: number;
|
|
55
|
+
seq?: number;
|
|
56
|
+
schemaVersion: 1;
|
|
57
|
+
}
|
|
58
|
+
type SwarmEvent = (EvBase & {
|
|
59
|
+
type: "swarm.status";
|
|
60
|
+
data: {
|
|
61
|
+
state: "thinking" | "delegating" | "waiting" | "tool" | "done" | "blocked";
|
|
62
|
+
note?: string;
|
|
63
|
+
position?: number;
|
|
64
|
+
};
|
|
65
|
+
}) | (EvBase & {
|
|
66
|
+
type: "swarm.message";
|
|
67
|
+
data: {
|
|
68
|
+
role: "assistant";
|
|
69
|
+
delta?: string;
|
|
70
|
+
text?: string;
|
|
71
|
+
};
|
|
72
|
+
}) | (EvBase & {
|
|
73
|
+
type: "swarm.handoff";
|
|
74
|
+
data: {
|
|
75
|
+
from: string;
|
|
76
|
+
to: string;
|
|
77
|
+
task: string;
|
|
78
|
+
};
|
|
79
|
+
}) | (EvBase & {
|
|
80
|
+
type: "swarm.tool_call";
|
|
81
|
+
data: {
|
|
82
|
+
toolCallId: string;
|
|
83
|
+
name: string;
|
|
84
|
+
args: unknown;
|
|
85
|
+
needsApproval: boolean;
|
|
86
|
+
};
|
|
87
|
+
}) | (EvBase & {
|
|
88
|
+
type: "swarm.tool_result";
|
|
89
|
+
data: {
|
|
90
|
+
toolCallId: string;
|
|
91
|
+
ok: boolean;
|
|
92
|
+
result?: unknown;
|
|
93
|
+
error?: string;
|
|
94
|
+
};
|
|
95
|
+
}) | (EvBase & {
|
|
96
|
+
type: "swarm.question";
|
|
97
|
+
data: {
|
|
98
|
+
followupId: string;
|
|
99
|
+
toolCallId: string;
|
|
100
|
+
to: "user" | string;
|
|
101
|
+
from?: string;
|
|
102
|
+
prompt: string;
|
|
103
|
+
field?: AskField;
|
|
104
|
+
schema?: unknown;
|
|
105
|
+
};
|
|
106
|
+
}) | (EvBase & {
|
|
107
|
+
type: "swarm.answer";
|
|
108
|
+
data: {
|
|
109
|
+
followupId: string;
|
|
110
|
+
from: "user" | string;
|
|
111
|
+
answer: unknown;
|
|
112
|
+
};
|
|
113
|
+
}) | (EvBase & {
|
|
114
|
+
type: "swarm.run_failed";
|
|
115
|
+
data: {
|
|
116
|
+
stage: string;
|
|
117
|
+
message: string;
|
|
118
|
+
retryable: boolean;
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
interface AgentVersion {
|
|
122
|
+
slug: string;
|
|
123
|
+
version: number;
|
|
124
|
+
role: "orchestrator" | "specialist";
|
|
125
|
+
personality: string;
|
|
126
|
+
capabilities: string[];
|
|
127
|
+
skillNames: string[];
|
|
128
|
+
delegateSlugs: string[];
|
|
129
|
+
modelId: string;
|
|
130
|
+
/** Per-agent memory OPTIONS override (R9), merged over the swarm MemoryConfig. Infra stays swarm-wide. */
|
|
131
|
+
memory?: AgentMemoryOverride;
|
|
132
|
+
}
|
|
133
|
+
/** A per-agent override of the swarm memory OPTIONS (R9) — never the infra (store/vector/embedder). */
|
|
134
|
+
interface AgentMemoryOverride {
|
|
135
|
+
lastMessages?: number;
|
|
136
|
+
workingMemory?: boolean | {
|
|
137
|
+
template?: string;
|
|
138
|
+
};
|
|
139
|
+
semanticRecall?: boolean | {
|
|
140
|
+
topK?: number;
|
|
141
|
+
messageRange?: number;
|
|
142
|
+
};
|
|
143
|
+
observationalMemory?: boolean | Record<string, unknown>;
|
|
144
|
+
}
|
|
145
|
+
interface AgentDef {
|
|
146
|
+
slug: string;
|
|
147
|
+
head: AgentVersion;
|
|
148
|
+
/**
|
|
149
|
+
* The concrete skill handles this agent was defined with. Carried on the def
|
|
150
|
+
* (not a module global) so `defineSwarm` can build a per-swarm skill registry —
|
|
151
|
+
* avoids cross-swarm leakage. `SwarmSkill` lives in define.ts; typed loosely
|
|
152
|
+
* here to keep types.ts free of a back-edge import.
|
|
153
|
+
*/
|
|
154
|
+
skills?: {
|
|
155
|
+
name: string;
|
|
156
|
+
}[];
|
|
157
|
+
}
|
|
158
|
+
interface RunRow {
|
|
159
|
+
runId: string;
|
|
160
|
+
tenantId: string;
|
|
161
|
+
userId: string;
|
|
162
|
+
threadId: string;
|
|
163
|
+
status: RunStatus;
|
|
164
|
+
agentSlug: string;
|
|
165
|
+
}
|
|
166
|
+
type RunStatus = "running" | "suspended" | "done" | "failed";
|
|
167
|
+
interface ActiveRun {
|
|
168
|
+
runId: string;
|
|
169
|
+
threadId: string;
|
|
170
|
+
agentSlug: string;
|
|
171
|
+
status: RunStatus;
|
|
172
|
+
}
|
|
173
|
+
interface NewRun {
|
|
174
|
+
runId: string;
|
|
175
|
+
tenantId: string;
|
|
176
|
+
userId: string;
|
|
177
|
+
threadId: string;
|
|
178
|
+
agentSlug: string;
|
|
179
|
+
}
|
|
180
|
+
interface SwarmMessage {
|
|
181
|
+
threadId: string;
|
|
182
|
+
role: "user" | "assistant";
|
|
183
|
+
text: string;
|
|
184
|
+
ts: number;
|
|
185
|
+
/** Speaker of an assistant turn on a shared (multi-agent) thread, decoded from the engine's persisted
|
|
186
|
+
* "[<slug>] " prefix. Undefined for user turns and for single-agent threads with no prefix. Lets the
|
|
187
|
+
* group-chat history render per-message speaker labels (live turns get the speaker from `nightowls.events`). */
|
|
188
|
+
agentSlug?: string;
|
|
189
|
+
/** Sender of a USER turn on a shared (multi-user) thread (R14), decoded from the engine's trusted
|
|
190
|
+
* "[user:<id>] " prefix. Undefined for assistant turns and single-user threads with no prefix. */
|
|
191
|
+
userId?: string;
|
|
192
|
+
}
|
|
193
|
+
/** Wall-safe summary of one of a user's conversations (powers the threads-list sidebar). Built by
|
|
194
|
+
* `engine.listThreads` from the engine's Memory — no engine-vendor type in the shape. */
|
|
195
|
+
interface ThreadSummary {
|
|
196
|
+
threadId: string;
|
|
197
|
+
title: string;
|
|
198
|
+
lastActivityAt: number;
|
|
199
|
+
}
|
|
200
|
+
/** Wall-safe roster entry for a swarm's agent (no vendor type). Powers the multi-agent pile/@mention UI. */
|
|
201
|
+
interface AgentSummary {
|
|
202
|
+
slug: string;
|
|
203
|
+
/** Display name — title-cased from the slug (agents have no separate name field). */
|
|
204
|
+
name: string;
|
|
205
|
+
role: string;
|
|
206
|
+
/** Slugs this agent can delegate to (the addressable graph). */
|
|
207
|
+
delegateSlugs: string[];
|
|
208
|
+
}
|
|
209
|
+
interface EventStore {
|
|
210
|
+
append(e: SwarmEvent): Promise<number>;
|
|
211
|
+
/** Tenant-scoped (R11): a forged cross-org runId returns []. The store enforces tenancy, not just the caller. */
|
|
212
|
+
list(tenantId: string, runId: string, sinceSeq: number): Promise<SwarmEvent[]>;
|
|
213
|
+
subscribe(runId: string): AsyncIterable<SwarmEvent>;
|
|
214
|
+
}
|
|
215
|
+
interface RunStore {
|
|
216
|
+
create(run: NewRun): Promise<void>;
|
|
217
|
+
setStatus(runId: string, status: RunStatus, patch?: Partial<RunRow>): Promise<void>;
|
|
218
|
+
saveSnapshot(runId: string, snapshot: unknown): Promise<void>;
|
|
219
|
+
/** Tenant-scoped (R11): a cross-org runId returns null (defense-in-depth; resume also gates via findSuspended). */
|
|
220
|
+
loadSnapshot(tenantId: string, runId: string): Promise<unknown | null>;
|
|
221
|
+
findSuspended(tenantId: string, followupId: string): Promise<{
|
|
222
|
+
runId: string;
|
|
223
|
+
toolCallId: string;
|
|
224
|
+
} | null>;
|
|
225
|
+
get(runId: string): Promise<RunRow | null>;
|
|
226
|
+
/** In-flight runs (running|suspended) for a container thread + its lane threads. Powers cross-lane presence (E5). */
|
|
227
|
+
listActive(tenantId: string, container: string): Promise<ActiveRun[]>;
|
|
228
|
+
/** Distinct container threadIds the user has a run in, most-recently-active first (R14: participation-based
|
|
229
|
+
* `listThreads` — under thread-scoped `resourceId`, a user's threads are the ones they participated in, not
|
|
230
|
+
* a resourceId filter). `container` = the threadId before any `:lane`. Tenant-scoped. Optional: an adapter
|
|
231
|
+
* that omits it leaves `engine.listThreads` on the degraded single-container fallback. */
|
|
232
|
+
listUserContainers?(tenantId: string, userId: string, limit?: number): Promise<string[]>;
|
|
233
|
+
/** Authorization gate for the read endpoints (R14 security): may this user read this container? True iff the
|
|
234
|
+
* container has NO runs yet (a brand-new/empty thread — nothing to protect) OR the user has a run in it (a
|
|
235
|
+
* participant). Blocks a same-tenant non-participant from reading another user's populated thread once
|
|
236
|
+
* `resourceId` is thread-scoped. Tenant-scoped. Optional: an adapter that omits it leaves the endpoints
|
|
237
|
+
* ungated (the prior behavior) — the shipped adapters implement it. */
|
|
238
|
+
canAccessContainer?(tenantId: string, userId: string, container: string): Promise<boolean>;
|
|
239
|
+
/** Durable-runner only (background): persist the vendor waitpoint token id for a followup. Optional. */
|
|
240
|
+
attachWaitpoint?(followupId: string, token: string, kind: "trigger" | "vercel"): Promise<void>;
|
|
241
|
+
/** Durable-runner only: read the waitpoint token id back (for completeWaitpoint). Optional. */
|
|
242
|
+
getWaitpoint?(followupId: string): Promise<string | null>;
|
|
243
|
+
}
|
|
244
|
+
interface MessageStore {
|
|
245
|
+
append(m: SwarmMessage): Promise<void>;
|
|
246
|
+
/** Tenant-scoped (R11). NOTE: currently no production caller — the runner's history endpoint goes through
|
|
247
|
+
* `engine.history` (Mastra recall, scoped by resourceId=tenant:user). Kept for contract consistency. */
|
|
248
|
+
history(tenantId: string, threadId: string, limit?: number): Promise<SwarmMessage[]>;
|
|
249
|
+
}
|
|
250
|
+
/** Scratchpad caps (intentionally lossy — working memory, not a system of record). */
|
|
251
|
+
declare const SCRATCHPAD_MAX_ENTRY_CHARS = 4000;
|
|
252
|
+
declare const SCRATCHPAD_MAX_KEYS = 64;
|
|
253
|
+
interface ScratchpadEntry {
|
|
254
|
+
section: "public" | "meta";
|
|
255
|
+
key: string;
|
|
256
|
+
author: string;
|
|
257
|
+
requestedBy: string;
|
|
258
|
+
content: string;
|
|
259
|
+
updatedAt: number;
|
|
260
|
+
}
|
|
261
|
+
interface ScratchpadStore {
|
|
262
|
+
/** Upsert one keyed entry — different keys never collide; same key revises in place. Concurrent-safe.
|
|
263
|
+
* `by` carries attribution + an optional per-write `maxKeys` cap (L3): the store keeps only the newest
|
|
264
|
+
* `maxKeys` keys per section, defaulting to `SCRATCHPAD_MAX_KEYS` when omitted. */
|
|
265
|
+
write(tenantId: string, container: string, section: "public" | "meta", key: string, content: string, by: {
|
|
266
|
+
agentSlug: string;
|
|
267
|
+
userId: string;
|
|
268
|
+
requestedBy: string;
|
|
269
|
+
maxKeys?: number;
|
|
270
|
+
}): Promise<void>;
|
|
271
|
+
/** All entries for a container (both sections). Empty array when none. Never throws. */
|
|
272
|
+
list(tenantId: string, container: string): Promise<ScratchpadEntry[]>;
|
|
273
|
+
}
|
|
274
|
+
interface AgentRepo {
|
|
275
|
+
head(tenantId: string, slug: string): Promise<AgentVersion | null>;
|
|
276
|
+
getVersion(tenantId: string, slug: string, version: number): Promise<AgentVersion | null>;
|
|
277
|
+
listSlugs(tenantId: string): Promise<string[]>;
|
|
278
|
+
}
|
|
279
|
+
interface StorageAdapter {
|
|
280
|
+
agents: AgentRepo;
|
|
281
|
+
runs: RunStore;
|
|
282
|
+
events: EventStore;
|
|
283
|
+
messages: MessageStore;
|
|
284
|
+
/** Opt-in container scratchpad (Part D). Optional so existing adapters keep compiling. */
|
|
285
|
+
scratchpad?: ScratchpadStore;
|
|
286
|
+
/**
|
|
287
|
+
* Record a suspended run in the tenant-scoped followup index so a later `resume` can authorize it
|
|
288
|
+
* (the runner's `findSuspended(tenantId, followupId)` gate). Called by the engine on every `ask`
|
|
289
|
+
* suspend (incl. a sub-agent's `ask` bubbling up through a delegation). REQUIRED for human-in-the-loop
|
|
290
|
+
* resume to work — an adapter that omits it leaves `findSuspended` empty and every resume is forbidden.
|
|
291
|
+
* Awaited by the engine so the row commits before the run is marked suspended.
|
|
292
|
+
*/
|
|
293
|
+
recordSuspend?(runId: string, tenantId: string, followupId: string, toolCallId: string): void | Promise<void>;
|
|
294
|
+
/**
|
|
295
|
+
* Mark a followup as answered so it can no longer be resumed (the engine calls this when a `resume`
|
|
296
|
+
* begins). Closes a replay hole: without it, `findSuspended` keeps returning the followup and the same
|
|
297
|
+
* answer can be replayed indefinitely. Idempotent; tenant-scoped. Awaited by the engine.
|
|
298
|
+
*/
|
|
299
|
+
markFollowupAnswered?(followupId: string, tenantId: string): void | Promise<void>;
|
|
300
|
+
/**
|
|
301
|
+
* Cross-process cache invalidation (R12). Subscribe to agent-republish notifications so an engine on ANY
|
|
302
|
+
* instance can evict its agent-row cache immediately instead of waiting out the TTL. `onInvalidate` receives
|
|
303
|
+
* the cache key (`tenantId:slug`). Returns an unsubscribe. Optional — single-process stores omit it (the TTL
|
|
304
|
+
* is the only staleness bound there). The supabase adapter uses Postgres LISTEN/NOTIFY.
|
|
305
|
+
*/
|
|
306
|
+
subscribeInvalidations?(onInvalidate: (key: string) => void): () => void;
|
|
307
|
+
}
|
|
308
|
+
interface ModelProvider {
|
|
309
|
+
resolve(modelId: string, ctx: {
|
|
310
|
+
tenantId: string;
|
|
311
|
+
}): Promise<string> | string;
|
|
312
|
+
}
|
|
313
|
+
interface SwarmSpan {
|
|
314
|
+
name: string;
|
|
315
|
+
kind: "run" | "delegation" | "tool" | "generation" | "event" | "recall";
|
|
316
|
+
traceId: string;
|
|
317
|
+
attributes: Record<string, unknown>;
|
|
318
|
+
startedAt: number;
|
|
319
|
+
endedAt?: number;
|
|
320
|
+
}
|
|
321
|
+
interface TelemetryExporter {
|
|
322
|
+
export(spans: SwarmSpan[]): Promise<void>;
|
|
323
|
+
}
|
|
324
|
+
/** Opt-in conversational memory (Mastra-backed). Mastra handles are `unknown` to keep the engine wall
|
|
325
|
+
* intact — the same pattern as `mastraStore`. Omit `memory` entirely for today's stateless behavior. */
|
|
326
|
+
interface MemoryConfig {
|
|
327
|
+
/** Mastra memory storage. Pass `createMastraPgStore({ dbUrl })` from @nightowlsdev/storage-supabase. REQUIRED. */
|
|
328
|
+
store: unknown;
|
|
329
|
+
/** Mastra vector store. Pass `createMastraVectorStore({ dbUrl })`. REQUIRED when `semanticRecall` is set. */
|
|
330
|
+
vector?: unknown;
|
|
331
|
+
/** AI-SDK embedding model (host-provided). REQUIRED when `semanticRecall` is set. */
|
|
332
|
+
embedder?: unknown;
|
|
333
|
+
/** Recent messages included each turn. Default 20. */
|
|
334
|
+
lastMessages?: number;
|
|
335
|
+
/** Working-memory scratchpad. Thread-scoped: shared by every participant in a thread, never across a
|
|
336
|
+
* user's other threads. Default off. */
|
|
337
|
+
workingMemory?: boolean | {
|
|
338
|
+
template?: string;
|
|
339
|
+
};
|
|
340
|
+
/** Vector recall over older messages. Thread-scoped: only ever recalls from the current thread, never
|
|
341
|
+
* from the user's other threads. Default off. Requires `vector` + `embedder`. */
|
|
342
|
+
semanticRecall?: boolean | {
|
|
343
|
+
topK?: number;
|
|
344
|
+
messageRange?: number;
|
|
345
|
+
};
|
|
346
|
+
/** Opt-in observational memory (R10): Mastra's built-in LLM observation/reflection — compacts the conversation
|
|
347
|
+
* into durable observations so context isn't lost beyond the recent window. `true` for defaults, or pass
|
|
348
|
+
* Mastra's `observationalMemory` options object (opaque — see Mastra docs). Default off. */
|
|
349
|
+
observationalMemory?: boolean | Record<string, unknown>;
|
|
350
|
+
}
|
|
351
|
+
interface RunInput {
|
|
352
|
+
message: string;
|
|
353
|
+
/**
|
|
354
|
+
* Opt-in, host-supplied page context. UNTRUSTED and advisory only — it is data the host page
|
|
355
|
+
* volunteered (e.g. the current route, selection, or visible records) for the agent to optionally
|
|
356
|
+
* pull via the `get_page_context` tool. NEVER use it for identity, authorization, or tenancy
|
|
357
|
+
* (those come from `SwarmContext`); treat its contents as opaque, attacker-controllable input.
|
|
358
|
+
*/
|
|
359
|
+
context?: Record<string, unknown>;
|
|
360
|
+
}
|
|
361
|
+
interface Runner {
|
|
362
|
+
run(input: RunInput, ctx: SwarmContext): AsyncIterable<SwarmEvent>;
|
|
363
|
+
enqueue(input: RunInput, ctx: SwarmContext): Promise<{
|
|
364
|
+
runId: string;
|
|
365
|
+
}>;
|
|
366
|
+
resume(args: {
|
|
367
|
+
runId: string;
|
|
368
|
+
toolCallId: string;
|
|
369
|
+
followupId: string;
|
|
370
|
+
answer: unknown;
|
|
371
|
+
}, ctx: SwarmContext): AsyncIterable<SwarmEvent>;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
type ByType<T extends SwarmEvent["type"]> = Extract<SwarmEvent, {
|
|
375
|
+
type: T;
|
|
376
|
+
}>;
|
|
377
|
+
declare function ev<T extends SwarmEvent["type"]>(type: T, base: {
|
|
378
|
+
runId: string;
|
|
379
|
+
agentSlug: string;
|
|
380
|
+
ts: number;
|
|
381
|
+
seq?: number;
|
|
382
|
+
}, data: ByType<T>["data"]): ByType<T>;
|
|
383
|
+
declare function isEvent<T extends SwarmEvent["type"]>(e: SwarmEvent, type: T): e is ByType<T>;
|
|
384
|
+
|
|
385
|
+
/** Identifies who holds (or is queued for) a container's floor — surfaced in the "waiting for X" indicator. */
|
|
386
|
+
interface FloorHolder {
|
|
387
|
+
/** Display name of the holding run's lane agent, e.g. "Coordinator". */
|
|
388
|
+
label: string;
|
|
389
|
+
/** The holding run's id (telemetry / debugging). */
|
|
390
|
+
runId: string;
|
|
391
|
+
}
|
|
392
|
+
/** A release fn — idempotent (calling it more than once is a no-op). */
|
|
393
|
+
type Release = () => void | Promise<void>;
|
|
394
|
+
interface ContainerFloor {
|
|
395
|
+
/** Take the floor synchronously if free; returns a release fn, or null if currently held. */
|
|
396
|
+
tryAcquire(container: string, who: FloorHolder): Promise<Release | null>;
|
|
397
|
+
/** Wait for the floor (FIFO). Resolves immediately if free. If `signal` aborts while queued, the waiter
|
|
398
|
+
* is dropped and the resolved release is a no-op; if it aborts after the grant, the floor is released. */
|
|
399
|
+
acquire(container: string, who: FloorHolder, signal?: AbortSignal): Promise<Release>;
|
|
400
|
+
/** The current holder of a container's floor, or null if free. */
|
|
401
|
+
holder(container: string): Promise<FloorHolder | null>;
|
|
402
|
+
/** Number of live (non-cancelled) waiters currently queued for this container's floor. */
|
|
403
|
+
queueDepth(container: string): Promise<number>;
|
|
404
|
+
}
|
|
405
|
+
/** In-memory, single-process container floor. Process-wide via the `containerFloor` singleton.
|
|
406
|
+
* NOT shared across serverless instances — see the spec's "in-memory, single-process" tradeoff. */
|
|
407
|
+
declare class InMemoryContainerFloor implements ContainerFloor {
|
|
408
|
+
private readonly maxHoldMs;
|
|
409
|
+
private slots;
|
|
410
|
+
/** @param maxHoldMs force-release backstop for a hung grant (a run that never releases). */
|
|
411
|
+
constructor(maxHoldMs?: number);
|
|
412
|
+
private slot;
|
|
413
|
+
holder(container: string): Promise<FloorHolder | null>;
|
|
414
|
+
queueDepth(container: string): Promise<number>;
|
|
415
|
+
tryAcquire(container: string, who: FloorHolder): Promise<Release | null>;
|
|
416
|
+
acquire(container: string, who: FloorHolder, signal?: AbortSignal): Promise<Release>;
|
|
417
|
+
/** Take the floor for `who`, arm the backstop, and return an idempotent release that hands off FIFO. */
|
|
418
|
+
private grant;
|
|
419
|
+
/** Release `who`'s hold (if still current) and grant the next live FIFO waiter, or free the floor. */
|
|
420
|
+
private release;
|
|
421
|
+
}
|
|
422
|
+
/** Process-wide singleton. In-memory → single-process only (serverless instances don't share it). */
|
|
423
|
+
declare const containerFloor: ContainerFloor;
|
|
424
|
+
|
|
425
|
+
interface Price {
|
|
426
|
+
inUsdPerMtok: number;
|
|
427
|
+
outUsdPerMtok: number;
|
|
428
|
+
}
|
|
429
|
+
declare const PRICE_TABLE: Record<string, Price>;
|
|
430
|
+
declare class CostGovernor {
|
|
431
|
+
private opts;
|
|
432
|
+
private steps;
|
|
433
|
+
private usd;
|
|
434
|
+
private prices;
|
|
435
|
+
constructor(opts: {
|
|
436
|
+
maxSteps: number;
|
|
437
|
+
maxCostUsd: number;
|
|
438
|
+
prices?: Record<string, Price>;
|
|
439
|
+
});
|
|
440
|
+
step(): void;
|
|
441
|
+
/** Price a single usage WITHOUT accumulating it (for per-generation telemetry cost). */
|
|
442
|
+
priceOf(modelId: string, u: {
|
|
443
|
+
inputTokens: number;
|
|
444
|
+
outputTokens: number;
|
|
445
|
+
}): number;
|
|
446
|
+
addUsage(modelId: string, u: {
|
|
447
|
+
inputTokens: number;
|
|
448
|
+
outputTokens: number;
|
|
449
|
+
}): void;
|
|
450
|
+
costUsd(): number;
|
|
451
|
+
shouldStop(): {
|
|
452
|
+
stop: boolean;
|
|
453
|
+
reason?: string;
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Per-delegate USD sub-budgets (R5). The global `cost.maxCostUsd` bounds the WHOLE turn; this adds an
|
|
458
|
+
* optional ceiling applied to EACH delegate (sub-agent) so one runaway sub-agent can't burn the entire
|
|
459
|
+
* turn before the global cap notices. `maxCostUsd` is the default ceiling for every delegate; `bySlug`
|
|
460
|
+
* overrides it per delegate slug (a slug listed there is capped even if there is no default). The run's
|
|
461
|
+
* root orchestrator is NOT a delegate and is never capped here — the global cap already covers it.
|
|
462
|
+
*/
|
|
463
|
+
interface PerDelegateBudget {
|
|
464
|
+
/** Default USD ceiling per delegate. Omit to cap only the slugs named in `bySlug`. */
|
|
465
|
+
maxCostUsd?: number;
|
|
466
|
+
/** Per-slug overrides of `maxCostUsd`. */
|
|
467
|
+
bySlug?: Record<string, {
|
|
468
|
+
maxCostUsd?: number;
|
|
469
|
+
}>;
|
|
470
|
+
}
|
|
471
|
+
/** Tracks per-delegate USD spend and reports the first delegate to exceed its budget. Priced from the same
|
|
472
|
+
* table as CostGovernor (via the shared `priceUsage`) so the global and per-delegate caps agree. Usage
|
|
473
|
+
* attributed to the root orchestrator slug is ignored. */
|
|
474
|
+
declare class DelegateBudgets {
|
|
475
|
+
private cfg;
|
|
476
|
+
private rootSlug;
|
|
477
|
+
private usd;
|
|
478
|
+
private prices;
|
|
479
|
+
constructor(cfg: PerDelegateBudget, rootSlug: string, prices?: Record<string, Price>);
|
|
480
|
+
/** The USD cap for a delegate: its `bySlug` override if present, else the default. `undefined` → uncapped. */
|
|
481
|
+
private capFor;
|
|
482
|
+
/** Accumulate one generation's usage against a delegate. No-op for the root orchestrator (not a delegate). */
|
|
483
|
+
addUsage(slug: string, modelId: string, u: {
|
|
484
|
+
inputTokens: number;
|
|
485
|
+
outputTokens: number;
|
|
486
|
+
}): void;
|
|
487
|
+
/** The first delegate that has met or exceeded its USD cap, or null. */
|
|
488
|
+
exceeded(): {
|
|
489
|
+
slug: string;
|
|
490
|
+
reason: string;
|
|
491
|
+
} | null;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
interface EngineOpts {
|
|
495
|
+
storage: StorageAdapter;
|
|
496
|
+
model: ModelProvider;
|
|
497
|
+
modelFactory: (modelId: string, agentSlug?: string) => unknown;
|
|
498
|
+
/** Global per-run caps + optional per-delegate sub-budgets (R5: `perDelegate` stops one runaway sub-agent
|
|
499
|
+
* from burning the whole turn before the global `maxCostUsd` notices). */
|
|
500
|
+
cost: {
|
|
501
|
+
maxSteps: number;
|
|
502
|
+
maxCostUsd: number;
|
|
503
|
+
perDelegate?: PerDelegateBudget;
|
|
504
|
+
};
|
|
505
|
+
/** Per-swarm skill resolver. When omitted, agents expose only built-in tools. */
|
|
506
|
+
resolveSkill?: (name: string) => SwarmSkill | undefined;
|
|
507
|
+
/**
|
|
508
|
+
* Mastra storage backend for suspend/resume snapshots. Resume is storage-gated
|
|
509
|
+
* (SPIKE-FINDINGS item 5): the in-memory default cannot survive process death.
|
|
510
|
+
* Inject a durable store (e.g. `@nightowlsdev/storage-supabase`'s `createMastraPgStore`)
|
|
511
|
+
* to make `ask`-suspend/`resumeStream` cross-process. Falls back to InMemoryStore.
|
|
512
|
+
*/
|
|
513
|
+
mastraStore?: unknown;
|
|
514
|
+
/**
|
|
515
|
+
* Optional telemetry exporter. When set, `run`/`resume` collect `run`/`generation`/`tool`
|
|
516
|
+
* SwarmSpans and batch-export them once in a `finally` (best-effort — a throwing exporter
|
|
517
|
+
* never breaks the run). When null/omitted, span collection is skipped (no-op).
|
|
518
|
+
*/
|
|
519
|
+
telemetry?: TelemetryExporter | null;
|
|
520
|
+
/** Opt-in conversational memory. When set, later tasks build+attach a Mastra Memory and pass ids to
|
|
521
|
+
* stream/resumeStream. Omitted => stateless (unchanged). */
|
|
522
|
+
memory?: MemoryConfig;
|
|
523
|
+
/** Opt-in page-context channel. Default false. When true, a later task exposes a `get_page_context`
|
|
524
|
+
* tool the agent can pull the host page's untrusted, advisory `RunInput.context` from. */
|
|
525
|
+
pageContext?: boolean;
|
|
526
|
+
/** Opt-in shared scratchpad (Part D). Requires `storage.scratchpad`. `true` uses default caps; pass an object
|
|
527
|
+
* to override the per-entry char cap and/or per-section key cap (L3). */
|
|
528
|
+
scratchpad?: boolean | {
|
|
529
|
+
maxEntryChars?: number;
|
|
530
|
+
maxKeys?: number;
|
|
531
|
+
};
|
|
532
|
+
/** Opt-in `recall_lane` tool (Part E). Read-only peer-lane transcript read. */
|
|
533
|
+
recallLane?: boolean;
|
|
534
|
+
/** Injectable per-lane floor (Part C / E3). Default: the in-memory process singleton. Pass a Postgres-backed
|
|
535
|
+
* floor (createPostgresFloor) for serverless / multi-instance deploys. */
|
|
536
|
+
floor?: ContainerFloor;
|
|
537
|
+
}
|
|
538
|
+
declare class SwarmEngine {
|
|
539
|
+
private opts;
|
|
540
|
+
private mastra;
|
|
541
|
+
private rowCache;
|
|
542
|
+
private memory;
|
|
543
|
+
private floor;
|
|
544
|
+
constructor(opts: EngineOpts);
|
|
545
|
+
/** Cached agent-row load shared by the three dynamic agent fns AND run/resume. */
|
|
546
|
+
private loadRow;
|
|
547
|
+
private agent;
|
|
548
|
+
private requestContext;
|
|
549
|
+
/** Per-call Mastra memory ids + delegation, only when memory is configured (else stream is unchanged). */
|
|
550
|
+
private memoryOpts;
|
|
551
|
+
/**
|
|
552
|
+
* Read a thread's persisted conversation from the engine's Memory and return it as wall-safe
|
|
553
|
+
* `SwarmMessage[]` (no engine-vendor type in the signature or the result — powers "reload keeps the chat").
|
|
554
|
+
*
|
|
555
|
+
* Shapes are spike-proven against the Mastra memory surface (`memory.recall`, NOT `memory.query`): each
|
|
556
|
+
* recalled row is a MastraDBMessage whose text lives in `content.parts[]` (NOT a flat `m.text`/string
|
|
557
|
+
* `m.content`). The vendor value is cast THROUGH a local structural type so no vendor type leaks to the
|
|
558
|
+
* public `.d.ts` (engine wall). Returns `[]` when the engine is stateless (no memory configured).
|
|
559
|
+
*/
|
|
560
|
+
history(threadId: string, ctx: SwarmContext, opts?: {
|
|
561
|
+
limit?: number;
|
|
562
|
+
}): Promise<SwarmMessage[]>;
|
|
563
|
+
/**
|
|
564
|
+
* R4: emit a single `recall` telemetry span for a `history` recall, best-effort. Fire-and-forget — a
|
|
565
|
+
* throwing/slow exporter must never delay or break a history read, so we don't await it and swallow errors.
|
|
566
|
+
* traceId is the invoking ctx's runId so a recall inside a run (via `recall_lane`) joins that run's trace.
|
|
567
|
+
*/
|
|
568
|
+
private emitRecallSpan;
|
|
569
|
+
/**
|
|
570
|
+
* Multi-agent shared-thread attribution (the persist boundary). Mastra recall carries NO per-message
|
|
571
|
+
* author field (spike-proven), so on a thread several agents share, a later agent can't tell who said an
|
|
572
|
+
* earlier assistant turn. After a run drains, this PREFIXES that run's just-persisted assistant turn(s)
|
|
573
|
+
* with `"[<slug>] "` — the only place the speaker survives in Mastra memory — so a subsequent agent's
|
|
574
|
+
* recall sees it inline; `history` decodes + strips it for display. Best-effort: never throws into the
|
|
575
|
+
* run, and no-op when the engine is stateless. Idempotent (skips an already-prefixed turn) and bounded to
|
|
576
|
+
* THIS run's responses (only assistant turns AFTER the most-recent user message) so a wide recall window
|
|
577
|
+
* can never re-stamp an older agent's turn with the wrong slug.
|
|
578
|
+
*/
|
|
579
|
+
private attributeRun;
|
|
580
|
+
/**
|
|
581
|
+
* Part B — mirror a delegation into the sub-agent's LANE thread. A delegation runs the sub-agent as a
|
|
582
|
+
* Mastra `agent-<slug>` tool inside the orchestrator's turn, so its work lands in the orchestrator's
|
|
583
|
+
* thread, not the sub-agent's lane (`<container>:<slug>`). After the run drains, this recalls THIS run's
|
|
584
|
+
* assistant turn(s) and, for each `agent-<slug>` tool-invocation part (which carries BOTH the task =
|
|
585
|
+
* `args.prompt` and the answer = `result.text`), `saveMessages` the pair into the sub-agent's lane thread
|
|
586
|
+
* — so switching to that agent's lane shows the delegated task + result, durably. Best-effort; Mastra-only
|
|
587
|
+
* (no nightowls.runs row ⇒ no thread-backing FK). Bounded to this run's turns ⇒ each run mirrors once.
|
|
588
|
+
*/
|
|
589
|
+
private mirrorDelegations;
|
|
590
|
+
/**
|
|
591
|
+
* List the user's conversations from the engine's Memory and return them as wall-safe
|
|
592
|
+
* `ThreadSummary[]` (no engine-vendor type in the signature or the result — powers a threads-list
|
|
593
|
+
* sidebar). Returns `[]` when the engine is stateless (no memory configured).
|
|
594
|
+
*
|
|
595
|
+
* Shape is spike-proven against the Mastra memory surface (`memory.listThreads`, NOT the
|
|
596
|
+
* non-existent `getThreadsByResourceId`): resourceId goes under `filter`, the envelope is
|
|
597
|
+
* `{ threads }`, and each thread row carries `{ id, title?, createdAt, updatedAt }` (see the
|
|
598
|
+
* threads-spike SPIKE-FINDINGS). The vendor value is cast THROUGH a local structural type so no
|
|
599
|
+
* vendor type leaks to the public `.d.ts` (engine wall). Already DESC by `updatedAt`, so the
|
|
600
|
+
* newest-active thread is first; no per-thread recall (avoids N+1) — the engine auto-titles threads.
|
|
601
|
+
*/
|
|
602
|
+
listThreads(ctx: SwarmContext, opts?: {
|
|
603
|
+
limit?: number;
|
|
604
|
+
}): Promise<ThreadSummary[]>;
|
|
605
|
+
/** The PUBLIC entries of a conversation's scratchpad (empty array when the feature is off or unset). */
|
|
606
|
+
scratchpadPublic(container: string, ctx: SwarmContext): Promise<ScratchpadEntry[]>;
|
|
607
|
+
/** In-flight runs (running|suspended) for a container + its lanes — powers cross-lane background presence (E5). */
|
|
608
|
+
activeRuns(container: string, ctx: SwarmContext): Promise<ActiveRun[]>;
|
|
609
|
+
/** The tenant's agent roster (slug, title-cased display name, role, delegate graph) as wall-safe
|
|
610
|
+
* AgentSummary[]. Sourced from the agent rows; no vendor type in the signature or result. Powers
|
|
611
|
+
* the multi-agent pile / @mention UI. */
|
|
612
|
+
listAgents(ctx: SwarmContext): Promise<AgentSummary[]>;
|
|
613
|
+
run(input: RunInput, ctx: SwarmContext): AsyncIterable<SwarmEvent>;
|
|
614
|
+
resume(args: {
|
|
615
|
+
runId: string;
|
|
616
|
+
toolCallId: string;
|
|
617
|
+
followupId: string;
|
|
618
|
+
answer: unknown;
|
|
619
|
+
context?: Record<string, unknown>;
|
|
620
|
+
}, ctx: SwarmContext): AsyncIterable<SwarmEvent>;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
interface ToolSpec<I, O> {
|
|
624
|
+
name: string;
|
|
625
|
+
description?: string;
|
|
626
|
+
inputSchema: z.ZodType<I>;
|
|
627
|
+
outputSchema?: z.ZodType<O>;
|
|
628
|
+
needsApproval?: boolean;
|
|
629
|
+
origin?: "first-party" | "mcp";
|
|
630
|
+
execute: (input: I, ctx: SwarmToolContext) => Promise<O>;
|
|
631
|
+
}
|
|
632
|
+
interface SwarmToolContext {
|
|
633
|
+
tenantId: string;
|
|
634
|
+
userId: string;
|
|
635
|
+
runId: string;
|
|
636
|
+
secrets?: {
|
|
637
|
+
resolve(ref: string): Promise<string>;
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
interface SwarmTool {
|
|
641
|
+
name: string;
|
|
642
|
+
needsApproval: boolean;
|
|
643
|
+
origin: "first-party" | "mcp";
|
|
644
|
+
}
|
|
645
|
+
type SwarmSkill = SwarmTool;
|
|
646
|
+
declare function defineTool<I, O>(spec: ToolSpec<I, O>): SwarmTool;
|
|
647
|
+
declare function defineSkill(tool: SwarmTool): SwarmSkill;
|
|
648
|
+
interface AgentSpec {
|
|
649
|
+
slug: string;
|
|
650
|
+
role?: "orchestrator" | "specialist";
|
|
651
|
+
personality: string;
|
|
652
|
+
capabilities?: string[];
|
|
653
|
+
skills?: SwarmSkill[];
|
|
654
|
+
delegates?: string[];
|
|
655
|
+
modelId?: string;
|
|
656
|
+
/** Per-agent memory OPTIONS override (R9), merged over the swarm `memory` config. Infra stays swarm-wide. */
|
|
657
|
+
memory?: AgentMemoryOverride;
|
|
658
|
+
}
|
|
659
|
+
declare function defineAgent(spec: AgentSpec): AgentDef;
|
|
660
|
+
/** Build a per-swarm skill resolver from the agents' attached skill handles. */
|
|
661
|
+
declare function buildSkillResolver(agents: AgentDef[]): (name: string) => SwarmSkill | undefined;
|
|
662
|
+
declare const ASK_TOOL_NAME = "ask";
|
|
663
|
+
interface SwarmConfig {
|
|
664
|
+
storage: StorageAdapter;
|
|
665
|
+
agents: AgentDef[];
|
|
666
|
+
models: {
|
|
667
|
+
allow: string[];
|
|
668
|
+
};
|
|
669
|
+
modelFactory: (modelId: string, agentSlug?: string) => unknown;
|
|
670
|
+
cost: {
|
|
671
|
+
maxSteps: number;
|
|
672
|
+
maxCostUsd: number;
|
|
673
|
+
perDelegate?: PerDelegateBudget;
|
|
674
|
+
};
|
|
675
|
+
/**
|
|
676
|
+
* Telemetry exporter(s). One or many — many are composed best-effort
|
|
677
|
+
* (`compositeTelemetry`: a throwing exporter never breaks a run). Spans are
|
|
678
|
+
* batch-exported once per run in a `finally`. Omit for a no-op.
|
|
679
|
+
*/
|
|
680
|
+
telemetry?: TelemetryExporter | TelemetryExporter[];
|
|
681
|
+
/**
|
|
682
|
+
* Durable Mastra snapshot store for `ask`-suspend / `resume`. REQUIRED for human-in-the-loop resume
|
|
683
|
+
* to survive across requests/processes (each HTTP request — chat vs resume — is a fresh route
|
|
684
|
+
* invocation; serverless has no shared memory). Pass `createMastraPgStore({ dbUrl })` from
|
|
685
|
+
* `@nightowlsdev/storage-supabase`. Omit and the engine falls back to an in-memory store: resume then only
|
|
686
|
+
* works within a single live process (fine for unit tests, NOT for a deployed app).
|
|
687
|
+
*/
|
|
688
|
+
mastraStore?: unknown;
|
|
689
|
+
/** Opt-in conversational memory. Omit for stateless turns (today's behavior). See MemoryConfig. */
|
|
690
|
+
memory?: MemoryConfig;
|
|
691
|
+
/** Opt-in page-context channel. Default false. When true, a later task exposes a `get_page_context`
|
|
692
|
+
* tool the agent can pull the host page's untrusted, advisory `RunInput.context` from. */
|
|
693
|
+
pageContext?: boolean;
|
|
694
|
+
/** Opt-in shared scratchpad (Part D). Default false. When true, agents get a `scratchpad_write` tool and
|
|
695
|
+
* the conversation's shared doc is injected into every agent's context. Requires a StorageAdapter with a
|
|
696
|
+
* `scratchpad` store. Pass an object to override the caps (L3): `{ maxEntryChars?, maxKeys? }`. */
|
|
697
|
+
scratchpad?: boolean | {
|
|
698
|
+
maxEntryChars?: number;
|
|
699
|
+
maxKeys?: number;
|
|
700
|
+
};
|
|
701
|
+
/** Opt-in `recall_lane` tool (Part E): lets an agent read a peer agent's lane transcript in the same
|
|
702
|
+
* conversation. Read-only; reuses the engine's history (best-effort — empty without memory). */
|
|
703
|
+
recallLane?: boolean;
|
|
704
|
+
}
|
|
705
|
+
interface Swarm {
|
|
706
|
+
engine: SwarmEngine;
|
|
707
|
+
}
|
|
708
|
+
declare function defineSwarm(cfg: SwarmConfig): Swarm;
|
|
709
|
+
|
|
710
|
+
declare function allowListModelProvider(opts: {
|
|
711
|
+
allow: string[];
|
|
712
|
+
}): ModelProvider;
|
|
713
|
+
|
|
714
|
+
/** Wrap a plain function into a TelemetryExporter. */
|
|
715
|
+
declare function customTelemetry(fn: (spans: SwarmSpan[]) => Promise<void> | void): TelemetryExporter;
|
|
716
|
+
/**
|
|
717
|
+
* Fan out to many exporters. Best-effort: one failing exporter never blocks the others or the run
|
|
718
|
+
* (Promise.allSettled), and the composite's export() never rejects.
|
|
719
|
+
*/
|
|
720
|
+
declare function compositeTelemetry(exporters: TelemetryExporter[]): TelemetryExporter;
|
|
721
|
+
/** Normalize the SwarmConfig.telemetry field (one | many | none) into a single exporter or null. */
|
|
722
|
+
declare function resolveTelemetry(t: TelemetryExporter | TelemetryExporter[] | undefined): TelemetryExporter | null;
|
|
723
|
+
/** Test/no-op exporter that records spans in memory. */
|
|
724
|
+
declare class CapturingExporter implements TelemetryExporter {
|
|
725
|
+
spans: SwarmSpan[];
|
|
726
|
+
export(spans: SwarmSpan[]): Promise<void>;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Collects SwarmSpans during a single run/resume. The engine drives it from its chunk loop:
|
|
730
|
+
* one root `run` span; one `generation` span per model call (opened lazily on first model activity,
|
|
731
|
+
* closed on that call's `step-finish` with the step's own usage + per-generation cost); one `tool`
|
|
732
|
+
* span per tool_call→tool_result pair. Each generation's `costUsd` is the per-call cost (priced
|
|
733
|
+
* directly from that step's usage — NOT a running cumulative total), so multi-step runs never
|
|
734
|
+
* double-count. Times come from the engine's own clock (`now`) so they align with event ts and
|
|
735
|
+
* stay deterministic in tests.
|
|
736
|
+
*/
|
|
737
|
+
declare class SpanCollector {
|
|
738
|
+
private traceId;
|
|
739
|
+
private now;
|
|
740
|
+
private spans;
|
|
741
|
+
private runSpan;
|
|
742
|
+
private gen;
|
|
743
|
+
private tools;
|
|
744
|
+
constructor(traceId: string, now: () => number, runName: string, runAttrs?: Record<string, unknown>);
|
|
745
|
+
/** Ensure a generation span is open (lazy — first model activity in this step). */
|
|
746
|
+
openGeneration(modelId: string): void;
|
|
747
|
+
/**
|
|
748
|
+
* Close the open generation with this step's usage + its own per-call cost (already priced from
|
|
749
|
+
* the step usage by the engine). `costUsd` is per-generation — never a cumulative running total.
|
|
750
|
+
*/
|
|
751
|
+
closeGeneration(usage: {
|
|
752
|
+
inputTokens: number;
|
|
753
|
+
outputTokens: number;
|
|
754
|
+
}, costUsd: number): void;
|
|
755
|
+
openTool(toolCallId: string, name: string): void;
|
|
756
|
+
closeTool(toolCallId: string, ok: boolean): void;
|
|
757
|
+
/**
|
|
758
|
+
* Seal: close the run span and any dangling open spans, return the batch. A run that suspends
|
|
759
|
+
* mid-step (e.g. an `ask` tool-call → `tool-call-suspended` with no `step-finish`) leaves the
|
|
760
|
+
* generation/tool spans open with no usage/result — those are tagged `incomplete:true` so
|
|
761
|
+
* downstream consumers don't mistake a sealed-but-unfinished span for a completed one.
|
|
762
|
+
*/
|
|
763
|
+
finish(): SwarmSpan[];
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
declare class RowCache<V> {
|
|
767
|
+
private opts;
|
|
768
|
+
private map;
|
|
769
|
+
constructor(opts: {
|
|
770
|
+
max: number;
|
|
771
|
+
ttlMs: number;
|
|
772
|
+
now?: () => number;
|
|
773
|
+
});
|
|
774
|
+
private now;
|
|
775
|
+
get(key: string, load: () => Promise<V>): Promise<V>;
|
|
776
|
+
/** Synchronous read of an already-cached, unexpired value (no load, no LRU touch). */
|
|
777
|
+
peek(key: string): V | undefined;
|
|
778
|
+
invalidate(key: string): void;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
declare class InMemoryStorage implements StorageAdapter {
|
|
782
|
+
private evts;
|
|
783
|
+
private seq;
|
|
784
|
+
private runRows;
|
|
785
|
+
private snapshots;
|
|
786
|
+
private suspends;
|
|
787
|
+
private waitpoints;
|
|
788
|
+
private msgs;
|
|
789
|
+
private agentRows;
|
|
790
|
+
private heads;
|
|
791
|
+
private pads;
|
|
792
|
+
seedAgent(v: AgentVersion, tenantId?: string): void;
|
|
793
|
+
recordSuspend(runId: string, tenantId: string, followupId: string, toolCallId: string): void;
|
|
794
|
+
markFollowupAnswered(followupId: string, tenantId: string): void;
|
|
795
|
+
/** Test/host helper: read a run row (the RunStore interface is write-mostly). */
|
|
796
|
+
getRun(runId: string): RunRow | undefined;
|
|
797
|
+
events: EventStore;
|
|
798
|
+
runs: RunStore;
|
|
799
|
+
messages: MessageStore;
|
|
800
|
+
scratchpad: ScratchpadStore;
|
|
801
|
+
agents: AgentRepo;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
declare const GUARDRAILS: string;
|
|
805
|
+
declare function composeSystemPrompt(row: AgentVersion): {
|
|
806
|
+
role: "system";
|
|
807
|
+
content: string;
|
|
808
|
+
}[];
|
|
809
|
+
|
|
810
|
+
declare const customAuth: (fn: AuthProvider["authenticate"]) => AuthProvider;
|
|
811
|
+
|
|
812
|
+
declare const VERSION = "0.0.0";
|
|
813
|
+
|
|
814
|
+
export { ASK_TOOL_NAME, type ActiveRun, type AgentDef, type AgentMemoryOverride, type AgentRepo, type AgentSpec, type AgentSummary, type AgentVersion, type AskField, type AskFieldOption, type AuthContext, type AuthProvider, CapturingExporter, type ContainerFloor, CostGovernor, DelegateBudgets, type EngineOpts, type EventStore, type FloorHolder, GUARDRAILS, InMemoryContainerFloor, InMemoryStorage, type MemoryConfig, type MessageStore, type ModelProvider, type NewRun, PRICE_TABLE, type PerDelegateBudget, type Price, type Release, RowCache, type RunInput, type RunRow, type RunStatus, type RunStore, type Runner, SCRATCHPAD_MAX_ENTRY_CHARS, SCRATCHPAD_MAX_KEYS, type ScratchpadEntry, type ScratchpadStore, type SecretResolver, SpanCollector, type StorageAdapter, type Swarm, type SwarmConfig, type SwarmContext, SwarmEngine, type SwarmEvent, type SwarmMessage, type SwarmSkill, type SwarmSpan, type SwarmTool, type SwarmToolContext, type TelemetryExporter, type ThreadSummary, type ToolSpec, VERSION, allowListModelProvider, buildSkillResolver, composeSystemPrompt, compositeTelemetry, containerFloor, customAuth, customTelemetry, defineAgent, defineSkill, defineSwarm, defineTool, ev, isEvent, resolveTelemetry };
|