@orkestrel/agent 0.0.19 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/src/core/index.cjs +1176 -836
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +1210 -783
- package/dist/src/core/index.d.ts +1210 -783
- package/dist/src/core/index.js +1162 -837
- package/dist/src/core/index.js.map +1 -1
- package/package.json +19 -20
package/dist/src/core/index.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ import { DriverInterface } from '@orkestrel/database';
|
|
|
4
4
|
import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
5
5
|
import { EmitterHooks } from '@orkestrel/emitter';
|
|
6
6
|
import { EmitterInterface } from '@orkestrel/emitter';
|
|
7
|
+
import { FileInterface } from '@orkestrel/workspace';
|
|
7
8
|
import { JSONValue } from '@orkestrel/contract';
|
|
8
|
-
import {
|
|
9
|
+
import { QueueContext } from '@orkestrel/queue';
|
|
9
10
|
import { QueueInterface } from '@orkestrel/queue';
|
|
10
11
|
import { QueueStoreInterface } from '@orkestrel/queue';
|
|
11
12
|
import { RunnerInterface } from '@orkestrel/workflow';
|
|
@@ -20,15 +21,15 @@ import { ToolResult } from '@orkestrel/tool';
|
|
|
20
21
|
import { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
24
|
+
* Composes a {@link ProviderInterface}, an {@link AgentContext}, and a
|
|
25
|
+
* {@link ToolManagerInterface} into a bounded context → provider → tools → repeat
|
|
25
26
|
* turn, exposed as both a one-shot `generate` and a live `stream`.
|
|
26
27
|
*
|
|
27
28
|
* @remarks
|
|
28
29
|
* - **One loop, two faces.** A single private async generator (`#run`) drives the
|
|
29
30
|
* whole turn. `stream` kicks off an eager pump that iterates `#run` into a private
|
|
30
31
|
* {@link Channel}, settling `result` from the run's outcome — so `result` settles
|
|
31
|
-
* whether or not the live `events` are drained; `generate`
|
|
32
|
+
* whether or not the live `events` are drained; `generate` awaits that same
|
|
32
33
|
* settled `result` — so the two can never diverge.
|
|
33
34
|
* - **The turn.** `#run` builds the provider input once (`context.build()` into a
|
|
34
35
|
* working array) then loops up to `limit`: drive `provider.stream(...)` accumulating
|
|
@@ -37,7 +38,7 @@ import { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
|
37
38
|
* tools, append the assistant turn, `execute` them, yield a `tool` chunk per call,
|
|
38
39
|
* append each tool result message, and continue; otherwise append the final
|
|
39
40
|
* assistant message and stop.
|
|
40
|
-
* - **Bounded.** Each run arms one cancel
|
|
41
|
+
* - **Bounded.** Each run arms one cancel through `createAbort({ signal: AbortSignal.any([
|
|
41
42
|
* …]) })` folding the external `signal`, the `timeout` deadline, and the `budget`
|
|
42
43
|
* signal; `abort()` fires it. Any trip stops the loop and commits a PARTIAL result
|
|
43
44
|
* (the `result` promise RESOLVES, never rejects, on a cancel) — only a genuine
|
|
@@ -61,8 +62,8 @@ import { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
|
61
62
|
*/
|
|
62
63
|
export declare class Agent implements AgentInterface {
|
|
63
64
|
#private;
|
|
64
|
-
readonly id: string;
|
|
65
65
|
constructor(provider: ProviderInterface, options?: AgentOptions);
|
|
66
|
+
get id(): string;
|
|
66
67
|
get emitter(): EmitterInterface<AgentEventMap>;
|
|
67
68
|
get status(): AgentStatus;
|
|
68
69
|
get context(): AgentContextInterface;
|
|
@@ -72,8 +73,8 @@ export declare class Agent implements AgentInterface {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
76
|
+
* Represents a streamed step of an agent turn — the union the loop yields as it runs, discriminated
|
|
77
|
+
* by the `category` of step it carries.
|
|
77
78
|
*
|
|
78
79
|
* @remarks
|
|
79
80
|
* - `token` — a content delta the provider streamed (the `'content'`
|
|
@@ -89,23 +90,23 @@ export declare class Agent implements AgentInterface {
|
|
|
89
90
|
* provider response that reported it (folded into the running total + any budget).
|
|
90
91
|
*/
|
|
91
92
|
export declare type AgentChunk = {
|
|
92
|
-
readonly
|
|
93
|
+
readonly category: 'token';
|
|
93
94
|
readonly content: string;
|
|
94
95
|
} | {
|
|
95
|
-
readonly
|
|
96
|
+
readonly category: 'think';
|
|
96
97
|
readonly content: string;
|
|
97
98
|
} | {
|
|
98
|
-
readonly
|
|
99
|
+
readonly category: 'tool';
|
|
99
100
|
readonly call: ToolCall;
|
|
100
101
|
readonly result: ToolResult;
|
|
101
102
|
} | {
|
|
102
|
-
readonly
|
|
103
|
+
readonly category: 'usage';
|
|
103
104
|
readonly usage: TokenUsage;
|
|
104
105
|
};
|
|
105
106
|
|
|
106
107
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
108
|
+
* Assembles a provider request from the richer turn context — the optional system prompt, the
|
|
109
|
+
* observable context managers (instructions / workspaces), the
|
|
109
110
|
* {@link ConversationManagerInterface} message source (whose active conversation IS `messages`),
|
|
110
111
|
* the {@link ToolManagerInterface} registry, and an active {@link ScopeInterface} changed through
|
|
111
112
|
* {@link AgentContextInterface.apply}.
|
|
@@ -126,7 +127,7 @@ export declare type AgentChunk = {
|
|
|
126
127
|
* {@link MessageManagerInterface} structurally — the same reference, no duplication), and
|
|
127
128
|
* `build()` folds that conversation's `view()` (its per-section summaries + live tail) as the
|
|
128
129
|
* AUTHORITATIVE message inclusion — the scope does NOT filter the conversation (it owns inclusion
|
|
129
|
-
*
|
|
130
|
+
* through compaction; scope filters only instructions / tools / workspace files). Because `messages`
|
|
130
131
|
* is read dynamically, an agent SWITCHES the active
|
|
131
132
|
* conversation BETWEEN runs (`conversations.switch(id)`) to serve MANY threads (the real
|
|
132
133
|
* multi-conversation pattern); switch between runs, not during a run, and use separate agents
|
|
@@ -136,31 +137,31 @@ export declare type AgentChunk = {
|
|
|
136
137
|
* (each as a block: the section's resolved `open` text, each item's resolved rendering, then
|
|
137
138
|
* any resolved `close` text) into ONE leading `system` message (prepended only when at least
|
|
138
139
|
* one part exists), then appends the ACTIVE conversation's `view()` (the conversation owns
|
|
139
|
-
* message inclusion
|
|
140
|
+
* message inclusion through compaction — the scope does NOT filter the conversation). Each
|
|
140
141
|
* `open` / item / `close`
|
|
141
142
|
* resolves INDEPENDENTLY, MOST-SPECIFIC-FIRST — `build()`'s optional `format` (a provider's
|
|
142
143
|
* per-section default) is the PROVIDER level: `open` = manager-options-override > provider >
|
|
143
144
|
* built-in; per item = item-override > manager-options-override > provider > built-in; `close` =
|
|
144
145
|
* manager-options-override > provider (NO built-in ⇒ no closing line when unset) (see
|
|
145
146
|
* {@link AgentContextInterface.build}). Passing NO `format` (and with no overrides / no per-item
|
|
146
|
-
*
|
|
147
|
-
* items, no closing line). The active workspace's scoped-in image files' `
|
|
147
|
+
* override) reproduces the built-in framing byte-for-byte (each section is its built-in header +
|
|
148
|
+
* items, no closing line). The active workspace's scoped-in image files' `base64` payload is attached to
|
|
148
149
|
* the LAST user message (a vision provider reads images off a user turn); when no user message
|
|
149
150
|
* exists the attachment is skipped. Built fresh each call (recomputed, never cached), so it
|
|
150
151
|
* always reflects the current managers / messages / scope / active workspace; it never mutates a
|
|
151
152
|
* manager or the stored messages.
|
|
152
153
|
* - **The ACTIVE workspace, rendered BY CARRIER — the SOLE document/image context.**
|
|
153
|
-
* `workspaces.active` (when set) has its {@link FileInterface}s scope-filtered by `scope.files`,
|
|
154
|
+
* `workspaces.active` (when set) has its {@link import('@orkestrel/workspace').FileInterface}s scope-filtered by `scope.files`,
|
|
154
155
|
* then split: TEXT files fold into a dedicated `## Workspace` system section (fenced reference
|
|
155
|
-
* blocks — placed right after the instructions section), and IMAGE files' base64
|
|
156
|
+
* blocks — placed right after the instructions section), and IMAGE files' `base64` payload attaches
|
|
156
157
|
* to the last user message. ACTIVE-ONLY — never the other registered workspaces; with no active
|
|
157
158
|
* workspace nothing renders for workspaces. `build()` OWNS this render (a `Workspace` /
|
|
158
159
|
* `WorkspaceManager` stays file-focused).
|
|
159
160
|
* - **Tools are structural, not in the prompt.** The registry is advertised to the provider
|
|
160
|
-
*
|
|
161
|
+
* through `tools.definitions()` (scope-filtered by the loop), NEVER serialized into the
|
|
161
162
|
* message array — so `build()`'s output carries no tool content, scoped or not.
|
|
162
163
|
* - **Event-free context; observable managers.** The context itself owns no Emitter; the
|
|
163
|
-
* context managers each carry their own (the
|
|
164
|
+
* context managers each carry their own (the push observation surface).
|
|
164
165
|
*
|
|
165
166
|
* @example
|
|
166
167
|
* ```ts
|
|
@@ -181,7 +182,7 @@ export declare class AgentContext implements AgentContextInterface {
|
|
|
181
182
|
get tools(): ToolManagerInterface;
|
|
182
183
|
get scope(): ScopeInterface | undefined;
|
|
183
184
|
apply(scope: ScopeInterface | undefined): void;
|
|
184
|
-
build(format?:
|
|
185
|
+
build(format?: ContextFormat): readonly Message[];
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
/**
|
|
@@ -193,12 +194,12 @@ export declare class AgentContext implements AgentContextInterface {
|
|
|
193
194
|
* (`instructions` / `workspaces` / `conversations`), `messages` (the active
|
|
194
195
|
* conversation's live tail, satisfying {@link MessageManagerInterface}), and the current `scope`
|
|
195
196
|
* (the active {@link ScopeInterface} filter, or `undefined` for no filtering). `build()` folds the
|
|
196
|
-
* scoped instructions into ONE leading `system` message (under the manager's `
|
|
197
|
-
* each item
|
|
197
|
+
* scoped instructions into ONE leading `system` message (under the manager's `open`,
|
|
198
|
+
* each item through its `render`) — PLUS the ACTIVE workspace's scope-filtered text files
|
|
198
199
|
* (rendered as fenced reference blocks) — and appends the ACTIVE conversation's `view()`, attaching
|
|
199
|
-
* the active workspace's scope-filtered image files' base64
|
|
200
|
+
* the active workspace's scope-filtered image files' `base64` payload to the LAST user message. The
|
|
200
201
|
* active workspace is the SOLE document/image context. Tools are advertised to the provider
|
|
201
|
-
* STRUCTURALLY (
|
|
202
|
+
* STRUCTURALLY (through `tools.definitions()`, scope-filtered by the loop), NOT serialized into
|
|
202
203
|
* the prompt, so they never appear in `build()`'s output. The context managers are observable
|
|
203
204
|
* (their own `emitter`s); the context itself is event-free.
|
|
204
205
|
*/
|
|
@@ -206,9 +207,9 @@ export declare interface AgentContextInterface {
|
|
|
206
207
|
readonly system: string | undefined;
|
|
207
208
|
readonly instructions: InstructionManagerInterface;
|
|
208
209
|
/**
|
|
209
|
-
*
|
|
210
|
+
* Holds the {@link WorkspaceManagerInterface} whose ACTIVE workspace `build()` renders by carrier —
|
|
210
211
|
* its text files folded into the system block (fenced reference blocks) and its image files'
|
|
211
|
-
* base64
|
|
212
|
+
* `base64` payload attached to the LAST user message. The active workspace is the SOLE
|
|
212
213
|
* document/image context. ALWAYS present (a fresh empty manager when none was supplied).
|
|
213
214
|
* `build()` reads its `active` (and the active workspace's `files()`) FRESH each call. With NO
|
|
214
215
|
* active workspace, nothing is rendered for workspaces. Active-only — never the other registered
|
|
@@ -216,7 +217,7 @@ export declare interface AgentContextInterface {
|
|
|
216
217
|
*/
|
|
217
218
|
readonly workspaces: WorkspaceManagerInterface;
|
|
218
219
|
/**
|
|
219
|
-
*
|
|
220
|
+
* Holds the active conversation's LIVE tail — the agent's message source, ALWAYS defined (the
|
|
220
221
|
* {@link conversations} registry always has an active conversation; a default is added at
|
|
221
222
|
* construction). It IS the active {@link ConversationInterface} itself (which satisfies
|
|
222
223
|
* {@link MessageManagerInterface} structurally), so appends through `messages` route to the
|
|
@@ -226,24 +227,23 @@ export declare interface AgentContextInterface {
|
|
|
226
227
|
*/
|
|
227
228
|
readonly messages: MessageManagerInterface;
|
|
228
229
|
/**
|
|
229
|
-
*
|
|
230
|
+
* Holds the {@link ConversationManagerInterface} the message source flows from — `messages` IS its
|
|
230
231
|
* ACTIVE conversation's live tail and `build()` folds that conversation's `view()`. ALWAYS holds
|
|
231
232
|
* an active conversation (a default is added at construction when none was supplied), so
|
|
232
233
|
* `messages` is always defined. Switch the active conversation through
|
|
233
234
|
* `conversations.switch(id)` — so one agent can serve MANY conversations (set the active one per
|
|
234
|
-
* request). Switch BETWEEN runs, not during one; for CONCURRENT threads use separate agents
|
|
235
|
-
* clause 23).
|
|
235
|
+
* request). Switch BETWEEN runs, not during one; for CONCURRENT threads use separate agents.
|
|
236
236
|
*/
|
|
237
237
|
readonly conversations: ConversationManagerInterface;
|
|
238
238
|
/**
|
|
239
|
-
*
|
|
239
|
+
* Holds the loop's tool registry for provider advertising and call dispatch. Tools are structural
|
|
240
240
|
* loop machinery and never render into `build()`'s prompt.
|
|
241
241
|
*/
|
|
242
242
|
readonly tools: ToolManagerInterface;
|
|
243
|
-
/**
|
|
243
|
+
/** Holds the active scope applied at `build()` time + the loop's tool-advertise step (`undefined` ⇒ no filtering). */
|
|
244
244
|
readonly scope: ScopeInterface | undefined;
|
|
245
245
|
/**
|
|
246
|
-
*
|
|
246
|
+
* Applies the active per-turn scope filter. Passing `undefined` removes filtering.
|
|
247
247
|
*
|
|
248
248
|
* @param scope - The scope to apply, or `undefined` to remove the active filter
|
|
249
249
|
*
|
|
@@ -255,10 +255,10 @@ export declare interface AgentContextInterface {
|
|
|
255
255
|
*/
|
|
256
256
|
apply(scope: ScopeInterface | undefined): void;
|
|
257
257
|
/**
|
|
258
|
-
*
|
|
258
|
+
* Builds the provider input for the next turn: a leading `system` message folding the prompt
|
|
259
259
|
* + the scoped instructions + the ACTIVE workspace's scoped-in TEXT files (rendered as
|
|
260
260
|
* fenced reference blocks), then the ACTIVE conversation's `view()` (with the active workspace's
|
|
261
|
-
* scoped-in IMAGE files' `
|
|
261
|
+
* scoped-in IMAGE files' `base64` payload attached to the last user message). Tools are advertised
|
|
262
262
|
* structurally, not in the prompt. Built fresh on each call.
|
|
263
263
|
*
|
|
264
264
|
* @remarks
|
|
@@ -268,8 +268,8 @@ export declare interface AgentContextInterface {
|
|
|
268
268
|
* `scope.files` (a three-way allow-list; `undefined` ⇒ all active files), then split by
|
|
269
269
|
* carrier: TEXT files ({@link import('@orkestrel/workspace').isText}) render into a dedicated
|
|
270
270
|
* `## Workspace` section in the system block — each a fenced
|
|
271
|
-
* `` File: <path>\n```<language>\n<text>\n``` `` block — placed
|
|
272
|
-
* section; binary files whose MIME starts with `image/` have their base64
|
|
271
|
+
* `` File: <path>\n```<language>\n<text>\n``` `` block — placed immediately after the instructions
|
|
272
|
+
* section; binary files whose MIME starts with `image/` have their `base64` payload
|
|
273
273
|
* attached to the LAST user message (a vision provider reads images off a user turn).
|
|
274
274
|
* ACTIVE-ONLY — never the other registered workspaces; with NO active workspace nothing is
|
|
275
275
|
* rendered for workspaces.
|
|
@@ -279,40 +279,40 @@ export declare interface AgentContextInterface {
|
|
|
279
279
|
* leading text), each item's `render`, and the `close` (the section's trailing text)
|
|
280
280
|
* resolve INDEPENDENTLY, MOST-SPECIFIC-FIRST, from a {@link ContextSectionFormat} at each
|
|
281
281
|
* level — an item override, a manager-options override, the provider `format` default,
|
|
282
|
-
* and the manager's built-in. For
|
|
282
|
+
* and the manager's built-in. For the `instructions` section kind `K`, manager
|
|
283
283
|
* `M`, and the supplied `format` `F`:
|
|
284
|
-
* - **open** = `M.
|
|
284
|
+
* - **open** = `M.format?.open ?? F?.[K]?.open ?? M.open` — that is,
|
|
285
285
|
* **manager-options override > provider default > built-in** (the leading text has no
|
|
286
286
|
* per-item level). The manager ENCAPSULATES the `[options-override → built-in]` half:
|
|
287
|
-
* `M.
|
|
287
|
+
* `M.open` already returns the options override's `open` when one is set, else
|
|
288
288
|
* the built-in header — so `build()` only layers the provider default BETWEEN them.
|
|
289
|
-
* - **item** `I` = `I.
|
|
290
|
-
* —
|
|
291
|
-
* Again `M.
|
|
292
|
-
* built-in, so `build()` layers the per-item `I.
|
|
289
|
+
* - **item** `I` = `I.override ?? M.format?.render?.(I) ?? F?.[K]?.render?.(I) ?? M.render(I)`
|
|
290
|
+
* — that is, **item override > manager-options override > provider default > built-in**.
|
|
291
|
+
* Again `M.render(I)` already returns the options override when set, else the
|
|
292
|
+
* built-in, so `build()` layers the per-item `I.override` ON TOP and the provider
|
|
293
293
|
* default BETWEEN.
|
|
294
|
-
* - **close** = `M.
|
|
294
|
+
* - **close** = `M.format?.close ?? F?.[K]?.close` — that is, **manager-options
|
|
295
295
|
* override > provider default**, with NO built-in floor (the trailing text has no
|
|
296
296
|
* per-item level): unset at both levels ⇒ `undefined` ⇒ no closing line. Paired with
|
|
297
297
|
* `open`, it lets a level WRAP the group (`open: '<instructions>'` … `close: '</instructions>'`).
|
|
298
298
|
*
|
|
299
299
|
* Passing NO `format` (the default) leaves the provider-default level empty, so the
|
|
300
|
-
* output is BYTE-FOR-BYTE the managers' built-in framing — every section is
|
|
300
|
+
* output is BYTE-FOR-BYTE the managers' built-in framing — every section is its
|
|
301
301
|
* built-in header + items, with no closing line (the regression contract). Scope
|
|
302
302
|
* filtering runs BEFORE formatting (unchanged); the workspace image-data attachment to the
|
|
303
303
|
* last user message is unchanged.
|
|
304
304
|
*
|
|
305
|
-
* @param format - The provider's optional {@link
|
|
305
|
+
* @param format - The provider's optional {@link ContextFormat} default
|
|
306
306
|
* (typically `provider.format`); omitted ⇒ only the manager-options / item / built-in
|
|
307
307
|
* levels apply, reproducing the prior built-in output exactly
|
|
308
308
|
* @returns The scoped conversation, prefixed by the assembled `system` message when any
|
|
309
309
|
* of (the prompt, the scoped instructions, the active workspace's text files) is non-empty
|
|
310
310
|
*/
|
|
311
|
-
build(format?:
|
|
311
|
+
build(format?: ContextFormat): readonly Message[];
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
/**
|
|
315
|
-
*
|
|
315
|
+
* Configures `createAgentContext` — the richer context's configuration.
|
|
316
316
|
*
|
|
317
317
|
* @remarks
|
|
318
318
|
* `system` is the optional system prompt prepended to the turn's input. `instructions` /
|
|
@@ -331,29 +331,29 @@ export declare interface AgentContextInterface {
|
|
|
331
331
|
export declare interface AgentContextOptions {
|
|
332
332
|
readonly system?: string;
|
|
333
333
|
/**
|
|
334
|
-
*
|
|
334
|
+
* Holds the loop's pre-built tool registry for provider advertising and call dispatch; an empty one is
|
|
335
335
|
* created when omitted. Tools never render into `build()`'s prompt.
|
|
336
336
|
*/
|
|
337
337
|
readonly tools?: ToolManagerInterface;
|
|
338
|
-
/**
|
|
338
|
+
/** Reuses a pre-built instruction registry; an empty one is created when omitted. */
|
|
339
339
|
readonly instructions?: InstructionManagerInterface;
|
|
340
340
|
/**
|
|
341
|
-
*
|
|
341
|
+
* Reuses a pre-built {@link WorkspaceManagerInterface}; a fresh empty one is created when
|
|
342
342
|
* omitted (so `context.workspaces` is ALWAYS present). `build()` renders the ACTIVE workspace's
|
|
343
343
|
* files by carrier — text files into the system block (fenced), image files attached to the last
|
|
344
344
|
* user message. The registry is structural; change its active workspace through
|
|
345
345
|
* `workspaces.switch(id)`. The active workspace is the SOLE document/image context.
|
|
346
346
|
*/
|
|
347
347
|
readonly workspaces?: WorkspaceManagerInterface;
|
|
348
|
-
/**
|
|
348
|
+
/** Sets the initial active scope (the build-time filter); `undefined` ⇒ no filtering. */
|
|
349
349
|
readonly scope?: ScopeInterface;
|
|
350
350
|
/**
|
|
351
|
-
*
|
|
351
|
+
* Reuses a pre-built {@link ConversationManagerInterface} as the message source; a fresh
|
|
352
352
|
* empty one is created when omitted. The context ENSURES an active conversation at construction
|
|
353
353
|
* (it `add`s a default when the manager has none), so `messages` — the manager's ACTIVE
|
|
354
354
|
* conversation's LIVE tail — is ALWAYS defined. `build()` folds the active conversation's
|
|
355
355
|
* `view()` (the per-section summaries + the live tail) as its AUTHORITATIVE message inclusion —
|
|
356
|
-
* the scope does NOT filter the conversation (it owns inclusion
|
|
356
|
+
* the scope does NOT filter the conversation (it owns inclusion through compaction; scope filters
|
|
357
357
|
* only instructions / tools / workspace files). The registry is structural; change its active
|
|
358
358
|
* conversation through the manager's `switch(id)`.
|
|
359
359
|
*/
|
|
@@ -361,25 +361,28 @@ export declare interface AgentContextOptions {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
/**
|
|
364
|
-
*
|
|
365
|
-
*
|
|
364
|
+
* Reports a concurrent run that would corrupt SHARED per-agent accounting, or a rehydration
|
|
365
|
+
* name absent from its registry pool — thrown synchronously by an {@link AgentInterface}'s
|
|
366
|
+
* `stream()` and by an {@link AgentRegistryInterface}'s accessors, carrying a machine-readable
|
|
367
|
+
* `code`.
|
|
366
368
|
*
|
|
367
369
|
* @remarks
|
|
368
|
-
*
|
|
369
|
-
* context budget) or a construction-level `budget` with no per-run override
|
|
370
|
-
* budget)
|
|
371
|
-
* shared instance
|
|
372
|
-
*
|
|
373
|
-
*
|
|
370
|
+
* `'CONCURRENCY'` reports a run already in flight on the same agent, PLUS a construction-level
|
|
371
|
+
* `window` (a shared context budget) or a construction-level `budget` with no per-run override
|
|
372
|
+
* (a shared cost budget) — a second concurrent `stream()` would race its charges against the
|
|
373
|
+
* same shared instance, corrupting the accounting. Use separate agents, or per-run `budget`
|
|
374
|
+
* overrides with no `window`, for genuinely concurrent runs. `'REGISTRY'` reports a rehydration
|
|
375
|
+
* name absent from its registry pool, on `provider` / `tool` / `authority` / `scheduler` /
|
|
376
|
+
* `build`. Narrow a caught value with {@link isAgentError} and branch on `error.code`.
|
|
374
377
|
*/
|
|
375
378
|
export declare class AgentError extends Error {
|
|
376
|
-
/**
|
|
377
|
-
readonly code: 'CONCURRENCY';
|
|
378
|
-
constructor(code: 'CONCURRENCY', message: string);
|
|
379
|
+
/** Names the machine-readable condition — `'CONCURRENCY'`: a concurrent run on a shared accounting agent; `'REGISTRY'`: a rehydration name absent from its registry pool. */
|
|
380
|
+
readonly code: 'CONCURRENCY' | 'REGISTRY';
|
|
381
|
+
constructor(code: 'CONCURRENCY' | 'REGISTRY', message: string);
|
|
379
382
|
}
|
|
380
383
|
|
|
381
384
|
/**
|
|
382
|
-
*
|
|
385
|
+
* Maps the push observation surface of an {@link AgentInterface} — the
|
|
383
386
|
* lifecycle + usage/tool moments a fire-and-forget observer (logging, metrics,
|
|
384
387
|
* tracing) subscribes to, ALONGSIDE the pull {@link AgentChunk} stream.
|
|
385
388
|
*
|
|
@@ -389,10 +392,10 @@ export declare class AgentError extends Error {
|
|
|
389
392
|
* the chunk stream can't express (a `deny` never reaches the stream) or that a
|
|
390
393
|
* fire-and-forget observer wants without draining the stream. PER-TOKEN deltas stay
|
|
391
394
|
* EXCLUSIVELY the {@link AgentChunk} stream's job (the pull surface) — there is
|
|
392
|
-
* deliberately NO `token` event here. Subscribe
|
|
395
|
+
* deliberately NO `token` event here. Subscribe through `agent.emitter.on(...)`.
|
|
393
396
|
*
|
|
394
|
-
* Observation is
|
|
395
|
-
*
|
|
397
|
+
* Observation is side-effect-free on the loop: listener isolation is the emitter's
|
|
398
|
+
* — every event is emitted directly and a listener throw is routed to the emitter's OWN
|
|
396
399
|
* `error` handler (the `error` option), never onto this domain map and never into the
|
|
397
400
|
* settle-once / wake-park engine — so a buggy observer can never reorder, throw into, or
|
|
398
401
|
* corrupt the run.
|
|
@@ -401,55 +404,80 @@ export declare class AgentError extends Error {
|
|
|
401
404
|
* PARTIAL result) — so an observer sees both that the run was cancelled and the partial
|
|
402
405
|
* outcome it committed; a genuine error emits `error` instead of `finish`.
|
|
403
406
|
*
|
|
404
|
-
* Declared as a `type` alias (not `interface extends EventMap
|
|
407
|
+
* Declared as a `type` alias (not `interface extends EventMap` — `EventMap` is a
|
|
405
408
|
* `type` kind): a type-literal satisfies the `EventMap` constraint
|
|
406
409
|
* (`Record<string, readonly unknown[]>`) structurally, whereas an interface lacks the
|
|
407
410
|
* required index signature.
|
|
408
411
|
*/
|
|
409
412
|
export declare type AgentEventMap = {
|
|
410
|
-
/**
|
|
413
|
+
/** Reports a run beginning — emitted at the top of `stream()` once `status` is `running`. */
|
|
411
414
|
readonly start: readonly [id: string];
|
|
412
|
-
/**
|
|
415
|
+
/** Reports each `#run` loop iteration beginning — the zero-based turn index. */
|
|
413
416
|
readonly turn: readonly [index: number];
|
|
414
|
-
/**
|
|
417
|
+
/** Reports a dispatched {@link ToolCall} paired with its {@link ToolResult} (executed or a denial). */
|
|
415
418
|
readonly tool: readonly [call: ToolCall, result: ToolResult];
|
|
416
|
-
/**
|
|
419
|
+
/** Reports a turn's {@link TokenUsage} — emitted after a usage-bearing provider call. */
|
|
417
420
|
readonly usage: readonly [usage: TokenUsage];
|
|
418
|
-
/**
|
|
421
|
+
/** Reports a call the authority DENIED — the call + the optional reason (NOT in the chunk stream). */
|
|
419
422
|
readonly deny: readonly [call: ToolCall, reason: string | undefined];
|
|
420
|
-
/**
|
|
423
|
+
/** Reports the run settled successfully (a natural finish OR a cancel's partial) — the {@link AgentResult}. */
|
|
421
424
|
readonly finish: readonly [result: AgentResult];
|
|
422
|
-
/**
|
|
425
|
+
/** Reports the run settled with a genuine (non-cancel) error — the thrown value (always `unknown`). */
|
|
423
426
|
readonly error: readonly [error: unknown];
|
|
424
|
-
/**
|
|
427
|
+
/** Reports the run cancelled (external signal / timeout / budget / `abort()`) — the cancel reason. */
|
|
425
428
|
readonly abort: readonly [reason: unknown];
|
|
426
429
|
/**
|
|
427
|
-
*
|
|
430
|
+
* Reports the loop exhausting its `limit` while still holding unresolved tool intent (the model
|
|
428
431
|
* requested tools on the very last allowed turn) — the turn count reached. Distinct from
|
|
429
432
|
* `abort`: exhaustion is NOT a cancel (no external signal / timeout / budget tripped), so
|
|
430
433
|
* this fires INSTEAD of `abort`, still followed by `finish` carrying the partial result.
|
|
431
434
|
*/
|
|
432
435
|
readonly exhaust: readonly [turns: number];
|
|
433
436
|
/**
|
|
434
|
-
* AUTOMATIC compaction's summarizer
|
|
437
|
+
* Reports AUTOMATIC compaction's summarizer THROWING — a NON-FATAL warn channel (the run continues; see
|
|
435
438
|
* {@link AgentOptions.window}). When the loop's between-turns / pre-first-turn auto-compaction
|
|
436
439
|
* (`conversation.compact()`) rejects, the run does NOT crash: the loop skips compaction that
|
|
437
440
|
* turn and surfaces the caught error here so the failure is observable, never silently lost.
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
441
|
+
* The run still SETTLES through the other events — `finish` for the lenient default, and
|
|
442
|
+
* `error` when {@link AgentOptions.strict} rethrows the same caught value — so `fault` reports
|
|
443
|
+
* the best-effort optimization that failed and never the run's own outcome. A MANUAL
|
|
444
|
+
* `conversation.compact()` still propagates its own error; only the agent's AUTO path is
|
|
445
|
+
* resilient. A DOMAIN event (the emitter isolates a listener throw separately, routing it to
|
|
446
|
+
* its `error` handler).
|
|
442
447
|
*/
|
|
443
|
-
readonly
|
|
448
|
+
readonly fault: readonly [error: unknown];
|
|
444
449
|
};
|
|
445
450
|
|
|
451
|
+
/**
|
|
452
|
+
* Composes a {@link ProviderInterface}, an {@link AgentContextInterface}, and a
|
|
453
|
+
* {@link ToolManagerInterface} into a bounded context → provider → tools → repeat turn.
|
|
454
|
+
*
|
|
455
|
+
* @remarks
|
|
456
|
+
* - **One loop, two faces.** `generate` and `stream` share ONE private run, so they
|
|
457
|
+
* can never diverge: `generate` drains the same stream `stream` exposes, then
|
|
458
|
+
* resolves its settled {@link AgentResult}.
|
|
459
|
+
* - **Bounded.** Each turn arms a single cancel folded from the external `signal`, the
|
|
460
|
+
* `timeout` deadline, and the `budget` signal (through `AbortSignal.any`); any of them —
|
|
461
|
+
* or `abort()` — stops the loop and settles the result `partial: true`.
|
|
462
|
+
* - **Paced + capped.** The `scheduler` (when given) yields between turns; tool
|
|
463
|
+
* iteration is capped at `limit` so the loop always terminates.
|
|
464
|
+
* - **Two observation surfaces.** PULL: the {@link AgentChunk} stream (`stream().events`)
|
|
465
|
+
* carries per-token answer deltas, per-think reasoning deltas, and usage/tool chunks for a live consumer. PUSH: the
|
|
466
|
+
* {@link emitter} ({@link AgentEventMap}) carries lifecycle + usage/tool/deny moments
|
|
467
|
+
* for fire-and-forget observers — the emitter isolates a listener throw and routes it to
|
|
468
|
+
* its `error` handler (the `error` option), so a buggy observer can NEVER corrupt the
|
|
469
|
+
* loop. Per-token / per-thinking deltas are the stream's job exclusively; there is no
|
|
470
|
+
* `token` or `think` event.
|
|
471
|
+
* - **Per-run overrides.** Both faces accept an optional {@link AgentRunOptions} bag whose
|
|
472
|
+
* members override the construction {@link AgentOptions} for that one run.
|
|
473
|
+
*/
|
|
446
474
|
export declare interface AgentInterface {
|
|
447
475
|
readonly emitter: EmitterInterface<AgentEventMap>;
|
|
448
476
|
readonly id: string;
|
|
449
477
|
readonly status: AgentStatus;
|
|
450
478
|
readonly context: AgentContextInterface;
|
|
451
479
|
/**
|
|
452
|
-
*
|
|
480
|
+
* Runs the turn to completion, discarding the live chunks — drains the shared
|
|
453
481
|
* stream and resolves the settled outcome.
|
|
454
482
|
*
|
|
455
483
|
* @remarks
|
|
@@ -460,13 +488,13 @@ export declare interface AgentInterface {
|
|
|
460
488
|
* itself, ahead of the `.catch` ever attaching) — `await` the call (inside a `try`/`catch`)
|
|
461
489
|
* or wrap the call expression itself in `try`/`catch`.
|
|
462
490
|
*
|
|
463
|
-
* @param options - Optional per-run {@link AgentRunOptions} (
|
|
491
|
+
* @param options - Optional per-run {@link AgentRunOptions} (for example `think`); omitted ⇒ defaults
|
|
464
492
|
* @returns The settled {@link AgentResult} (`partial: true` when cancelled)
|
|
465
493
|
* @throws {AgentError} Synchronously, with `code: 'CONCURRENCY'`, for a concurrent run
|
|
466
494
|
*/
|
|
467
495
|
generate(options?: AgentRunOptions): Promise<AgentResult>;
|
|
468
496
|
/**
|
|
469
|
-
*
|
|
497
|
+
* Runs the turn as a live stream — iterate `events` for {@link AgentChunk}s and
|
|
470
498
|
* `await result` for the settled outcome.
|
|
471
499
|
*
|
|
472
500
|
* @remarks
|
|
@@ -475,13 +503,13 @@ export declare interface AgentInterface {
|
|
|
475
503
|
* {@link AgentStreamInterface} handle is even returned, so it cannot be caught by chaining
|
|
476
504
|
* off the (never-produced) handle; wrap the call itself in `try`/`catch`.
|
|
477
505
|
*
|
|
478
|
-
* @param options - Optional per-run {@link AgentRunOptions} (
|
|
506
|
+
* @param options - Optional per-run {@link AgentRunOptions} (for example `think`); omitted ⇒ defaults
|
|
479
507
|
* @returns A live {@link AgentStreamInterface} handle (events + result + abort)
|
|
480
508
|
* @throws {AgentError} Synchronously, with `code: 'CONCURRENCY'`, for a concurrent run
|
|
481
509
|
*/
|
|
482
510
|
stream(options?: AgentRunOptions): AgentStreamInterface;
|
|
483
511
|
/**
|
|
484
|
-
*
|
|
512
|
+
* Cancels the in-flight turn — fires the turn's signal; the `result` settles
|
|
485
513
|
* `partial: true` with whatever content accumulated.
|
|
486
514
|
*
|
|
487
515
|
* @param reason - An optional cancellation reason propagated to the signal
|
|
@@ -490,9 +518,9 @@ export declare interface AgentInterface {
|
|
|
490
518
|
}
|
|
491
519
|
|
|
492
520
|
/**
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* `
|
|
521
|
+
* Reports an {@link AgentInterface} run that ended {@link AgentResult.partial} under a
|
|
522
|
+
* `partial` policy of `false` (the default) — thrown by an agent-job handler (a
|
|
523
|
+
* `createAgentQueue` / `createAgentRunner` job), carrying the partial
|
|
496
524
|
* {@link AgentResult} so the failure stays inspectable.
|
|
497
525
|
*
|
|
498
526
|
* @remarks
|
|
@@ -500,18 +528,22 @@ export declare interface AgentInterface {
|
|
|
500
528
|
* runner abort threaded in, a `timeout` deadline, or an exhausted token `budget`) rather
|
|
501
529
|
* than finishing naturally. For a durable JOB that is a failure by default: throwing this
|
|
502
530
|
* lets the Queue's retries re-run the job and a Runner's fail-fast abort its siblings.
|
|
503
|
-
* Set `
|
|
531
|
+
* Set `partial: true` (see `AgentQueueOptions` / `AgentRunnerOptions`) to treat a
|
|
504
532
|
* partial as success instead, in which case this is never thrown. Narrow a caught value
|
|
505
|
-
* with {@link isAgentJobError} to read `partial`.
|
|
533
|
+
* with {@link isAgentJobError} to read `partial`. `code` is the machine-readable condition
|
|
534
|
+
* (`'PARTIAL'` — the only one this error reports), so a `catch` branches on it rather than on
|
|
535
|
+
* the message string.
|
|
506
536
|
*/
|
|
507
537
|
export declare class AgentJobError extends Error {
|
|
508
|
-
/**
|
|
538
|
+
/** Names the machine-readable condition — `'PARTIAL'`: a job that ended partial under a disallowing policy. */
|
|
539
|
+
readonly code: "PARTIAL";
|
|
540
|
+
/** Holds the partial {@link AgentResult} the cancelled job produced. */
|
|
509
541
|
readonly partial: AgentResult;
|
|
510
542
|
constructor(message: string, partial: AgentResult);
|
|
511
543
|
}
|
|
512
544
|
|
|
513
545
|
/**
|
|
514
|
-
*
|
|
546
|
+
* Represents a JSON-serializable agent job — the descriptor a durable queue / runner runs. Its
|
|
515
547
|
* non-serializable pieces (the provider, tools, authority, scheduler) are referenced by
|
|
516
548
|
* NAME and resolved to live objects through an {@link AgentRegistryInterface} at handler
|
|
517
549
|
* time; its data fields (the seed `messages`, `system`, `limit`, `timeout`, and a token
|
|
@@ -528,26 +560,26 @@ export declare class AgentJobError extends Error {
|
|
|
528
560
|
* `budget` is a token ceiling rebuilt into a `createTokenBudget({ max })`.
|
|
529
561
|
*/
|
|
530
562
|
export declare interface AgentJobInput {
|
|
531
|
-
/**
|
|
563
|
+
/** Names the registry key of the {@link ProviderInterface} the job runs against. */
|
|
532
564
|
readonly provider: string;
|
|
533
|
-
/**
|
|
565
|
+
/** Holds the seed conversation added to the rehydrated agent's context (serializable). */
|
|
534
566
|
readonly messages: readonly MessageInput[];
|
|
535
|
-
/**
|
|
567
|
+
/** Holds an optional system prompt seeding the agent's context. */
|
|
536
568
|
readonly system?: string;
|
|
537
|
-
/**
|
|
569
|
+
/** Names the registry keys of the {@link ToolInterface}s loaded into the agent's tool manager. */
|
|
538
570
|
readonly tools?: readonly string[];
|
|
539
|
-
/**
|
|
571
|
+
/** Names the registry key of an optional {@link AuthorityInterface} policy gate. */
|
|
540
572
|
readonly authority?: string;
|
|
541
|
-
/**
|
|
573
|
+
/** Names the registry key of an optional {@link SchedulerInterface} pacing the loop. */
|
|
542
574
|
readonly scheduler?: string;
|
|
543
|
-
/**
|
|
575
|
+
/** Caps the tool-iteration turns before the loop stops (see {@link AgentOptions.limit}). */
|
|
544
576
|
readonly limit?: number;
|
|
545
|
-
/**
|
|
577
|
+
/** Sets a wall-clock deadline (ms) for the whole turn (see {@link AgentOptions.timeout}). */
|
|
546
578
|
readonly timeout?: number;
|
|
547
|
-
/**
|
|
579
|
+
/** Sets a token ceiling rebuilt into a `createTokenBudget({ max })` cost bound. */
|
|
548
580
|
readonly budget?: number;
|
|
549
581
|
/**
|
|
550
|
-
*
|
|
582
|
+
* Lists the sub-agent jobs this job fans out — each a nested {@link AgentJobInput} (so the whole
|
|
551
583
|
* tree stays serializable). On a `createAgentRunner`, the handler `controller.spawn`s
|
|
552
584
|
* each child through the same bounded queue BEFORE running this (parent) job, so the
|
|
553
585
|
* children run as sibling sub-agents and their results join the run after the declared
|
|
@@ -557,7 +589,7 @@ export declare interface AgentJobInput {
|
|
|
557
589
|
}
|
|
558
590
|
|
|
559
591
|
/**
|
|
560
|
-
*
|
|
592
|
+
* Configures `createAgent` — bounds and pacing for the agent loop.
|
|
561
593
|
*
|
|
562
594
|
* @remarks
|
|
563
595
|
* - `system` — an optional system prompt prepended to the turn (seeds the context).
|
|
@@ -582,12 +614,12 @@ export declare interface AgentJobInput {
|
|
|
582
614
|
* the ACTIVE conversation when it is summarizable.
|
|
583
615
|
* - `window` — an optional CONTEXT {@link BudgetInterface} for AUTOMATIC conversation
|
|
584
616
|
* compaction: when set, the loop measures the CURRENT FULL prompt against this budget each turn
|
|
585
|
-
* (its `
|
|
617
|
+
* (its `consumer` is a token estimator, its `max` the context window) and, when the prompt
|
|
586
618
|
* reaches the window AND the active conversation is summarizable, COMPACTS the active
|
|
587
619
|
* conversation + continues on the rebuilt smaller view — compact-and-continue, distinct from
|
|
588
620
|
* `budget`'s hard abort. Omitted ⇒ no auto-compaction.
|
|
589
621
|
* - `strict` — when `true`, a summarizer failure during AUTOMATIC compaction ABORTS the run
|
|
590
|
-
* (rethrown after the `
|
|
622
|
+
* (rethrown after the `fault` event, propagating through `#run` to a genuine `error`
|
|
591
623
|
* settle) instead of skipping compaction and continuing over-window. Defaults to `false`
|
|
592
624
|
* (lenient — the prior, byte-for-byte behavior).
|
|
593
625
|
* - `instructions` — an optional pre-built {@link InstructionManagerInterface} forwarded to the
|
|
@@ -596,34 +628,34 @@ export declare interface AgentJobInput {
|
|
|
596
628
|
* agent's context; a fresh empty one is created when omitted (mirrors {@link AgentContextOptions.workspaces}).
|
|
597
629
|
* - `scope` — an optional initial active {@link ScopeInterface} forwarded to the agent's context
|
|
598
630
|
* (the build-time filter); `undefined` ⇒ no filtering (mirrors {@link AgentContextOptions.scope}).
|
|
599
|
-
* - `on` — the reserved {@link EmitterHooks} key
|
|
600
|
-
* {@link AgentEventMap}, wired at construction (
|
|
631
|
+
* - `on` — the reserved {@link EmitterHooks} key: initial listeners for the agent's
|
|
632
|
+
* {@link AgentEventMap}, wired at construction (for example `{ finish: (r) => log(r) }`).
|
|
601
633
|
*/
|
|
602
634
|
export declare interface AgentOptions {
|
|
603
635
|
readonly on?: EmitterHooks<AgentEventMap>;
|
|
604
|
-
/**
|
|
636
|
+
/** Holds the emitter's listener-error handler — a listener throw routes here, not to a domain event. */
|
|
605
637
|
readonly error?: EmitterErrorHandler;
|
|
606
638
|
readonly system?: string;
|
|
607
|
-
/**
|
|
639
|
+
/** Reuses a pre-built tool registry the loop dispatches calls through; an empty one is created when omitted. */
|
|
608
640
|
readonly tools?: ToolManagerInterface;
|
|
609
|
-
/**
|
|
641
|
+
/** Reuses a pre-built instruction registry forwarded to the agent's context; an empty one is created when omitted. */
|
|
610
642
|
readonly instructions?: InstructionManagerInterface;
|
|
611
|
-
/**
|
|
643
|
+
/** Reuses a pre-built workspace registry forwarded to the agent's context; a fresh empty one is created when omitted. */
|
|
612
644
|
readonly workspaces?: WorkspaceManagerInterface;
|
|
613
|
-
/**
|
|
645
|
+
/** Sets the initial active scope forwarded to the agent's context (the build-time filter); `undefined` ⇒ no filtering. */
|
|
614
646
|
readonly scope?: ScopeInterface;
|
|
615
|
-
/**
|
|
647
|
+
/** Caps the tool-iteration turns before the loop stops; defaults to `DEFAULT_AGENT_LIMIT`. */
|
|
616
648
|
readonly limit?: number;
|
|
617
|
-
/**
|
|
649
|
+
/** Sets a wall-clock deadline (ms) for the whole turn; its abort commits a partial result. */
|
|
618
650
|
readonly timeout?: number;
|
|
619
|
-
/**
|
|
651
|
+
/** Bounds the token cost; each provider call's usage is charged and its abort commits a partial. */
|
|
620
652
|
readonly budget?: BudgetInterface<TokenUsage>;
|
|
621
653
|
/** Paces the loop — `yield`ed between turns so the host regains control. */
|
|
622
654
|
readonly scheduler?: SchedulerInterface;
|
|
623
|
-
/**
|
|
655
|
+
/** Carries an external cancel; its abort commits a partial result. */
|
|
624
656
|
readonly signal?: AbortSignal;
|
|
625
657
|
/**
|
|
626
|
-
*
|
|
658
|
+
* Holds an optional policy gate consulted before each tool call runs — a denied call is
|
|
627
659
|
* fed back to the model as a denial {@link ToolResult} (a `tool` chunk + a tool
|
|
628
660
|
* message) rather than executed (no tool run, no budget cost), so the model sees the
|
|
629
661
|
* denial and can react; an allowed call dispatches normally. Omitted ⇒ every call
|
|
@@ -631,7 +663,7 @@ export declare interface AgentOptions {
|
|
|
631
663
|
*/
|
|
632
664
|
readonly authority?: AuthorityInterface;
|
|
633
665
|
/**
|
|
634
|
-
*
|
|
666
|
+
* Holds an optional {@link ConversationManagerInterface} that becomes the agent context's MESSAGE
|
|
635
667
|
* SOURCE — forwarded to the {@link AgentContextInterface} the agent builds, so
|
|
636
668
|
* `agent.context.messages` IS its ACTIVE conversation's live tail and `build()` folds that
|
|
637
669
|
* conversation's `view()` (the per-section summaries + the live tail). Omitted ⇒ a fresh
|
|
@@ -640,18 +672,18 @@ export declare interface AgentOptions {
|
|
|
640
672
|
*/
|
|
641
673
|
readonly conversations?: ConversationManagerInterface;
|
|
642
674
|
/**
|
|
643
|
-
*
|
|
644
|
-
* token estimator (
|
|
675
|
+
* Holds an optional CONTEXT {@link BudgetInterface} for AUTOMATIC compaction. Its `consumer` is a
|
|
676
|
+
* token estimator (for example the exported {@link import('./helpers.js').estimateMessages}) and
|
|
645
677
|
* its `max` is the context window. When set, the loop measures the CURRENT FULL prompt (the
|
|
646
678
|
* next provider request) against this budget each turn; when that prompt reaches the window AND
|
|
647
679
|
* the active conversation is summarizable, it **compacts the active conversation + continues on
|
|
648
680
|
* the rebuilt smaller view** (compact-and-continue) — the same consume-to-a-ceiling primitive
|
|
649
681
|
* as the cost `budget`, but compaction is the ceiling action instead of abort. Omit to disable.
|
|
650
682
|
*/
|
|
651
|
-
readonly window?: BudgetInterface<readonly
|
|
683
|
+
readonly window?: BudgetInterface<readonly Message[]>;
|
|
652
684
|
/**
|
|
653
|
-
*
|
|
654
|
-
* `
|
|
685
|
+
* If `true`, a summarizer failure during AUTOMATIC compaction ABORTS the run — the
|
|
686
|
+
* `fault` event still fires, then the caught error is RETHROWN so the run settles
|
|
655
687
|
* `error` instead of continuing over-window. Defaults to `false` (lenient — the run
|
|
656
688
|
* continues over-window, byte-for-byte the prior behavior).
|
|
657
689
|
*/
|
|
@@ -659,13 +691,13 @@ export declare interface AgentOptions {
|
|
|
659
691
|
}
|
|
660
692
|
|
|
661
693
|
/**
|
|
662
|
-
*
|
|
694
|
+
* Configures `createAgentQueue` — the registry that rehydrates jobs, the partial-result
|
|
663
695
|
* policy, and the substrate knobs threaded into the backing `createQueue`.
|
|
664
696
|
*
|
|
665
697
|
* @remarks
|
|
666
698
|
* - `registry` — the {@link AgentRegistryInterface} the handler rehydrates each job
|
|
667
699
|
* through (required).
|
|
668
|
-
* - `
|
|
700
|
+
* - `partial` — the partial policy. A partial {@link AgentResult} (a job committed
|
|
669
701
|
* early from an abort / budget / timeout) is by DEFAULT a FAILURE: the handler THROWS
|
|
670
702
|
* an {@link import('./errors.js').AgentJobError}, so the Queue's retries (and a
|
|
671
703
|
* Runner's fail-fast) engage. Set `true` to treat a partial as SUCCESS instead — the
|
|
@@ -676,8 +708,8 @@ export declare interface AgentOptions {
|
|
|
676
708
|
*/
|
|
677
709
|
export declare interface AgentQueueOptions {
|
|
678
710
|
readonly registry: AgentRegistryInterface;
|
|
679
|
-
/**
|
|
680
|
-
readonly
|
|
711
|
+
/** If `true`, a partial `AgentResult` resolves as success; if `false` (the default), it THROWS and retries engage. */
|
|
712
|
+
readonly partial?: boolean;
|
|
681
713
|
readonly concurrency?: number;
|
|
682
714
|
readonly retries?: number;
|
|
683
715
|
readonly timeout?: number;
|
|
@@ -685,10 +717,9 @@ export declare interface AgentQueueOptions {
|
|
|
685
717
|
}
|
|
686
718
|
|
|
687
719
|
/**
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
* job's names + data.
|
|
720
|
+
* Makes a durable, JSON-serializable {@link AgentJobInput} runnable — holds the named
|
|
721
|
+
* pools of live, non-serializable pieces (providers, tools, authorities, schedulers) and
|
|
722
|
+
* rehydrates a seeded, signal-wired {@link Agent} from a job's names + data.
|
|
692
723
|
*
|
|
693
724
|
* @remarks
|
|
694
725
|
* - **Why it exists.** An `AgentJobInput` is serializable so it can survive a crash in a
|
|
@@ -696,18 +727,18 @@ export declare interface AgentQueueOptions {
|
|
|
696
727
|
* schedulers carrying functions) cannot serialize. The registry closes that gap:
|
|
697
728
|
* construct it once with the live pools, then a queue / runner handler calls `build`
|
|
698
729
|
* on each (possibly restored) job to get a ready agent.
|
|
699
|
-
* - **Accessors throw on a miss
|
|
700
|
-
*
|
|
701
|
-
* when it is absent — an unknown name in a
|
|
702
|
-
* error that must fail LOUDLY at build time, never
|
|
703
|
-
* run an agent missing a dependency.
|
|
730
|
+
* - **Accessors throw on a miss.** `provider` / `tool` / `authority` / `scheduler` resolve a
|
|
731
|
+
* name against their pool and THROW an {@link AgentError} carrying `code: 'REGISTRY'` and
|
|
732
|
+
* the message `unknown <category>: <name>` when it is absent — an unknown name in a
|
|
733
|
+
* rehydrated job is a programmer / config error that must fail LOUDLY at build time, never
|
|
734
|
+
* silently resolve to `undefined` and run an agent missing a dependency.
|
|
704
735
|
* - **`build` rehydrates.** Resolve the job's `provider`; assemble a fresh
|
|
705
736
|
* {@link ToolManager} from the `tools` names; rebuild the token `budget` from its
|
|
706
737
|
* ceiling (`createTokenBudget({ max })`); resolve the optional `authority` /
|
|
707
738
|
* `scheduler` names; construct the {@link Agent} with `system` / `limit` / `timeout` /
|
|
708
739
|
* the threaded `signal`; seed its context with the job's `messages`; return it. The
|
|
709
740
|
* `signal` is the queue attempt's / runner unit's cancel, so a bounded abort propagates
|
|
710
|
-
* into the agent (which commits a partial — the job's `
|
|
741
|
+
* into the agent (which commits a partial — the job's `partial` policy then
|
|
711
742
|
* decides success vs. retry).
|
|
712
743
|
* - **Event-free.** A pure resolver — no Emitter, no events.
|
|
713
744
|
*
|
|
@@ -735,11 +766,11 @@ export declare class AgentRegistry implements AgentRegistryInterface {
|
|
|
735
766
|
* durable, serializable job runnable.
|
|
736
767
|
*
|
|
737
768
|
* @remarks
|
|
738
|
-
* - **Accessors throw on a miss
|
|
739
|
-
*
|
|
740
|
-
* <name
|
|
741
|
-
* must fail loudly, never silently resolve to `undefined`, so a
|
|
742
|
-
* surfaces at once rather than running with a missing dependency.
|
|
769
|
+
* - **Accessors throw on a miss.** `provider` / `tool` / `authority` / `scheduler` look one
|
|
770
|
+
* up by name and THROW an {@link AgentError} carrying `code: 'REGISTRY'` and the message
|
|
771
|
+
* `unknown <category>: <name>` when the name is unregistered — an unknown name in a
|
|
772
|
+
* rehydrated job must fail loudly, never silently resolve to `undefined`, so a
|
|
773
|
+
* misconfigured job surfaces at once rather than running with a missing dependency.
|
|
743
774
|
* - **`build` rehydrates.** It resolves the job's `provider`, assembles a
|
|
744
775
|
* {@link ToolManagerInterface} from the `tools` names, rebuilds the token `budget`
|
|
745
776
|
* from its ceiling, resolves the `authority` / `scheduler` names, seeds the agent's
|
|
@@ -749,7 +780,7 @@ export declare class AgentRegistry implements AgentRegistryInterface {
|
|
|
749
780
|
*/
|
|
750
781
|
export declare interface AgentRegistryInterface {
|
|
751
782
|
/**
|
|
752
|
-
*
|
|
783
|
+
* Resolves a registered {@link ProviderInterface} by name.
|
|
753
784
|
*
|
|
754
785
|
* @param name - The provider's registry key
|
|
755
786
|
* @returns The live provider
|
|
@@ -757,7 +788,7 @@ export declare interface AgentRegistryInterface {
|
|
|
757
788
|
*/
|
|
758
789
|
provider(name: string): ProviderInterface;
|
|
759
790
|
/**
|
|
760
|
-
*
|
|
791
|
+
* Resolves a registered {@link ToolInterface} by name.
|
|
761
792
|
*
|
|
762
793
|
* @param name - The tool's registry key
|
|
763
794
|
* @returns The live tool
|
|
@@ -765,7 +796,7 @@ export declare interface AgentRegistryInterface {
|
|
|
765
796
|
*/
|
|
766
797
|
tool(name: string): ToolInterface;
|
|
767
798
|
/**
|
|
768
|
-
*
|
|
799
|
+
* Resolves a registered {@link AuthorityInterface} by name.
|
|
769
800
|
*
|
|
770
801
|
* @param name - The authority's registry key
|
|
771
802
|
* @returns The live authority
|
|
@@ -773,7 +804,7 @@ export declare interface AgentRegistryInterface {
|
|
|
773
804
|
*/
|
|
774
805
|
authority(name: string): AuthorityInterface;
|
|
775
806
|
/**
|
|
776
|
-
*
|
|
807
|
+
* Resolves a registered {@link SchedulerInterface} by name.
|
|
777
808
|
*
|
|
778
809
|
* @param name - The scheduler's registry key
|
|
779
810
|
* @returns The live scheduler
|
|
@@ -781,7 +812,7 @@ export declare interface AgentRegistryInterface {
|
|
|
781
812
|
*/
|
|
782
813
|
scheduler(name: string): SchedulerInterface;
|
|
783
814
|
/**
|
|
784
|
-
*
|
|
815
|
+
* Rehydrates a live, seeded {@link AgentInterface} from a serializable job — resolving
|
|
785
816
|
* its names, rebuilding its budget, seeding its conversation, and wiring `signal`.
|
|
786
817
|
*
|
|
787
818
|
* @param input - The serializable {@link AgentJobInput} to rehydrate
|
|
@@ -793,18 +824,18 @@ export declare interface AgentRegistryInterface {
|
|
|
793
824
|
}
|
|
794
825
|
|
|
795
826
|
/**
|
|
796
|
-
*
|
|
827
|
+
* Configures `createAgentRegistry` — the named pools of live, non-serializable pieces
|
|
797
828
|
* a {@link AgentJobInput}'s names resolve against.
|
|
798
829
|
*
|
|
799
830
|
* @remarks
|
|
800
831
|
* `providers` is required (a job always names a provider); `tools` / `authorities` /
|
|
801
|
-
* `schedulers` are optional pools, each an entity-keyed record
|
|
832
|
+
* `schedulers` are optional pools, each an entity-keyed record mapping a registry
|
|
802
833
|
* name to its live object. A name absent from its pool throws when resolved (see
|
|
803
834
|
* {@link AgentRegistryInterface}). `store` is the durable {@link ConversationStoreInterface}
|
|
804
835
|
* every agent this registry builds carries: each built agent gets its OWN store-backed
|
|
805
836
|
* {@link ConversationManagerInterface} over THIS shared store — a fresh conversation id per
|
|
806
837
|
* build (minted by the seeded `add`), so concurrent builds never collide, and the store
|
|
807
|
-
*
|
|
838
|
+
* accumulates one snapshot per built agent that later calls `save`. Persistence
|
|
808
839
|
* stays caller-triggered (`open` / `save`) — `build` never hydrates, so `build` stays
|
|
809
840
|
* SYNCHRONOUS. Omitted ⇒ every built agent gets a registry-only manager, byte-identical
|
|
810
841
|
* to today.
|
|
@@ -818,7 +849,7 @@ export declare interface AgentRegistryOptions {
|
|
|
818
849
|
}
|
|
819
850
|
|
|
820
851
|
/**
|
|
821
|
-
*
|
|
852
|
+
* Holds the settled outcome of an agent turn — the assembled assistant `content`, the
|
|
822
853
|
* `usage` summed across the turn's provider calls, and whether it was committed
|
|
823
854
|
* `partial`.
|
|
824
855
|
*
|
|
@@ -834,7 +865,7 @@ export declare interface AgentRegistryOptions {
|
|
|
834
865
|
* present only when at least one provider call reported usage — an aborted run's `usage`
|
|
835
866
|
* INCLUDES the cancelled turn's tokens when the provider reports partial usage on the
|
|
836
867
|
* abort (folded in exactly like a completed turn's); a provider that cannot observe
|
|
837
|
-
* usage mid-stream (
|
|
868
|
+
* usage mid-stream (for example a daemon whose final counts never arrive before the cancel)
|
|
838
869
|
* reports none for that turn, and none is fabricated. `thinking` is present
|
|
839
870
|
* only when a provider call surfaced reasoning it separated from the answer
|
|
840
871
|
* ({@link ProviderResult.thinking}, joined across the run's calls) — display/audit
|
|
@@ -842,15 +873,15 @@ export declare interface AgentRegistryOptions {
|
|
|
842
873
|
*/
|
|
843
874
|
export declare interface AgentResult {
|
|
844
875
|
readonly content: string;
|
|
845
|
-
/**
|
|
876
|
+
/** Carries reasoning the run's provider calls separated from the answer (present when any surfaced it). */
|
|
846
877
|
readonly thinking?: string;
|
|
847
|
-
/**
|
|
878
|
+
/** Holds the summed {@link TokenUsage} across the turn's provider calls (present when any reported it). */
|
|
848
879
|
readonly usage?: TokenUsage;
|
|
849
880
|
readonly partial: boolean;
|
|
850
881
|
}
|
|
851
882
|
|
|
852
883
|
/**
|
|
853
|
-
*
|
|
884
|
+
* Projects an unknown value onto the canonical JSON representation of an
|
|
854
885
|
* {@link AgentResult}.
|
|
855
886
|
*
|
|
856
887
|
* @remarks
|
|
@@ -876,11 +907,11 @@ export declare interface AgentResult {
|
|
|
876
907
|
export declare function agentResultToJSON(value: unknown): JSONValue | undefined;
|
|
877
908
|
|
|
878
909
|
/**
|
|
879
|
-
*
|
|
910
|
+
* Configures `createAgentRunner` — the registry that rehydrates jobs, the partial-result
|
|
880
911
|
* policy, and the substrate knobs threaded into the backing `createRunner`.
|
|
881
912
|
*
|
|
882
913
|
* @remarks
|
|
883
|
-
* Identical partial policy to {@link AgentQueueOptions} (`
|
|
914
|
+
* Identical partial policy to {@link AgentQueueOptions} (`partial` — a partial
|
|
884
915
|
* `AgentResult` THROWS by default so the run's fail-fast engages, `true` resolves it as
|
|
885
916
|
* success). `concurrency` / `retries` / `timeout` pass straight to the backing
|
|
886
917
|
* `RunnerInterface` (see `RunnerOptions`). The runner enables sub-agent fan-out: a
|
|
@@ -889,38 +920,29 @@ export declare function agentResultToJSON(value: unknown): JSONValue | undefined
|
|
|
889
920
|
*/
|
|
890
921
|
export declare interface AgentRunnerOptions {
|
|
891
922
|
readonly registry: AgentRegistryInterface;
|
|
892
|
-
/**
|
|
893
|
-
readonly
|
|
923
|
+
/** If `true`, a partial `AgentResult` resolves as success; if `false` (the default), it THROWS and fail-fast engages. */
|
|
924
|
+
readonly partial?: boolean;
|
|
894
925
|
readonly concurrency?: number;
|
|
895
926
|
readonly retries?: number;
|
|
896
927
|
readonly timeout?: number;
|
|
897
928
|
}
|
|
898
929
|
|
|
899
930
|
/**
|
|
900
|
-
*
|
|
901
|
-
*
|
|
902
|
-
* context → provider → tools → repeat turn.
|
|
931
|
+
* Carries the per-run override bag an {@link AgentInterface}'s `generate` / `stream` accepts — each
|
|
932
|
+
* member overrides the matching {@link AgentOptions} value for ONE run.
|
|
903
933
|
*
|
|
904
934
|
* @remarks
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
*
|
|
908
|
-
*
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
*
|
|
912
|
-
* iteration is capped at `limit` so the loop always terminates.
|
|
913
|
-
* - **Two observation surfaces.** PULL: the {@link AgentChunk} stream (`stream().events`)
|
|
914
|
-
* carries per-token answer deltas, per-think reasoning deltas, and usage/tool chunks for a live consumer. PUSH: the
|
|
915
|
-
* {@link emitter} ({@link AgentEventMap}) carries lifecycle + usage/tool/deny moments
|
|
916
|
-
* for fire-and-forget observers — the emitter isolates a listener throw and routes it to
|
|
917
|
-
* its `error` handler (the `error` option, §13), so a buggy observer can NEVER corrupt the
|
|
918
|
-
* loop. Per-token / per-thinking deltas are the stream's job exclusively; there is no
|
|
919
|
-
* `token` or `think` event.
|
|
935
|
+
* Every member is optional and resolved independently, so an omitted member leaves the
|
|
936
|
+
* agent's constructed value in force and a caller that passes no options runs exactly the
|
|
937
|
+
* agent it configured. `think` / `schema` ride through to the provider as
|
|
938
|
+
* {@link ProviderStreamOptions}; `limit` / `timeout` / `budget` replace their construction
|
|
939
|
+
* defaults for this run only; `signal` COMPOSES with the constructed `signal` (both fold into
|
|
940
|
+
* the run's bound abort) rather than replacing it. Nothing here mutates the agent — the next
|
|
941
|
+
* run reads the construction defaults again.
|
|
920
942
|
*/
|
|
921
943
|
export declare interface AgentRunOptions {
|
|
922
944
|
/**
|
|
923
|
-
*
|
|
945
|
+
* Sets the per-run reasoning preference forwarded to the provider's `stream` as
|
|
924
946
|
* {@link ProviderStreamOptions.think} — `true` asks the backend to separate reasoning
|
|
925
947
|
* (surfaced as `think` {@link AgentChunk}s + the settled `thinking`), `false` suppresses
|
|
926
948
|
* it. Omitted ⇒ the provider's own default applies (the loop is byte-for-byte the prior
|
|
@@ -928,7 +950,7 @@ export declare interface AgentRunOptions {
|
|
|
928
950
|
*/
|
|
929
951
|
readonly think?: boolean;
|
|
930
952
|
/**
|
|
931
|
-
*
|
|
953
|
+
* Constrains the response to this JSON-Schema shape, forwarded to the provider's `stream`
|
|
932
954
|
* as {@link ProviderStreamOptions.schema} — a per-run structured-output request. Omitted ⇒
|
|
933
955
|
* no constraint (the loop is byte-for-byte the prior behaviour).
|
|
934
956
|
*/
|
|
@@ -950,29 +972,93 @@ export declare interface AgentRunOptions {
|
|
|
950
972
|
*/
|
|
951
973
|
readonly budget?: BudgetInterface<TokenUsage>;
|
|
952
974
|
/**
|
|
953
|
-
*
|
|
954
|
-
* fold into the run's bound abort
|
|
975
|
+
* Carries an additional per-run external cancel, COMPOSED with {@link AgentOptions.signal} (both
|
|
976
|
+
* fold into the run's bound abort through `AbortSignal.any` — neither is dropped). Omitted ⇒
|
|
955
977
|
* only the agent's constructed `signal` (if any) applies.
|
|
956
978
|
*/
|
|
957
979
|
readonly signal?: AbortSignal;
|
|
958
980
|
}
|
|
959
981
|
|
|
960
982
|
/**
|
|
961
|
-
*
|
|
983
|
+
* Names the lifecycle state of an {@link AgentInterface} turn — `idle` before a run,
|
|
962
984
|
* `running` while the loop is in flight, then the settled `done` (a normal finish or
|
|
963
985
|
* a cancel) or `error` (a genuine provider / tool failure).
|
|
964
986
|
*/
|
|
965
987
|
export declare type AgentStatus = 'idle' | 'running' | 'done' | 'error';
|
|
966
988
|
|
|
967
989
|
/**
|
|
968
|
-
*
|
|
990
|
+
* Names the agent turn's live handle — a {@link StreamInterface} of {@link AgentChunk}s
|
|
969
991
|
* resolving an {@link AgentResult}.
|
|
970
992
|
*/
|
|
971
993
|
export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResult>;
|
|
972
994
|
|
|
973
995
|
/**
|
|
974
|
-
*
|
|
975
|
-
*
|
|
996
|
+
* Assembles the settled {@link AgentResult} from a run's {@link RunOutcome} — `thinking` and
|
|
997
|
+
* `usage` are carried only when the run surfaced them.
|
|
998
|
+
*
|
|
999
|
+
* @remarks
|
|
1000
|
+
* Pure and total. An absent optional is OMITTED rather than stored as `undefined` (the
|
|
1001
|
+
* present-when-given convention the message store follows), so a settled result JSON
|
|
1002
|
+
* round-trips without an explicit `undefined` field. `exhausted` is loop bookkeeping and does
|
|
1003
|
+
* not reach the public result — the `exhaust` event carries it instead.
|
|
1004
|
+
*
|
|
1005
|
+
* @param outcome - The run's settled outcome
|
|
1006
|
+
* @returns The public {@link AgentResult}
|
|
1007
|
+
*
|
|
1008
|
+
* @example
|
|
1009
|
+
* ```ts
|
|
1010
|
+
* assembleResult({ content: 'hi', thinking: undefined, usage: undefined, partial: false, exhausted: false })
|
|
1011
|
+
* // { content: 'hi', partial: false }
|
|
1012
|
+
* ```
|
|
1013
|
+
*/
|
|
1014
|
+
export declare function assembleResult(outcome: RunOutcome): AgentResult;
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Copies a message with image data merged onto its `images` — the message's own images
|
|
1018
|
+
* first, then the attached data.
|
|
1019
|
+
*
|
|
1020
|
+
* @remarks
|
|
1021
|
+
* Pure and total: the original message is NEVER mutated. `calls` is carried only when the
|
|
1022
|
+
* source message has one (kept omitted otherwise, mirroring the store's present-when-given
|
|
1023
|
+
* convention).
|
|
1024
|
+
*
|
|
1025
|
+
* @param message - The message to copy (left unchanged)
|
|
1026
|
+
* @param data - The base64 image data to attach
|
|
1027
|
+
* @returns A new message carrying the merged `images`
|
|
1028
|
+
*
|
|
1029
|
+
* @example
|
|
1030
|
+
* ```ts
|
|
1031
|
+
* attachImages({ id: '1', role: 'user', content: 'Describe' }, ['<payload>'])
|
|
1032
|
+
* // { id: '1', role: 'user', content: 'Describe', images: ['<payload>'] }
|
|
1033
|
+
* ```
|
|
1034
|
+
*/
|
|
1035
|
+
export declare function attachImages(message: Message, data: readonly string[]): Message;
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* Attaches image data to a conversation's LAST user message — the turn a vision provider
|
|
1039
|
+
* reads images off.
|
|
1040
|
+
*
|
|
1041
|
+
* @remarks
|
|
1042
|
+
* Pure and total: the conversation and its messages are NEVER mutated, and the returned array
|
|
1043
|
+
* replaces exactly the one target message with the copy {@link attachImages} builds. Empty
|
|
1044
|
+
* data returns the conversation unchanged; a conversation with NO user message returns it
|
|
1045
|
+
* unchanged too (there is nowhere to attach, and the images already rode the system block).
|
|
1046
|
+
*
|
|
1047
|
+
* @param conversation - The messages to attach into (left unchanged)
|
|
1048
|
+
* @param data - The base64 image data to attach
|
|
1049
|
+
* @returns The conversation with its last user message replaced by the carrying copy
|
|
1050
|
+
*
|
|
1051
|
+
* @example
|
|
1052
|
+
* ```ts
|
|
1053
|
+
* attachUserImages([{ id: '1', role: 'user', content: 'Describe' }], ['<payload>'])
|
|
1054
|
+
* // [{ id: '1', role: 'user', content: 'Describe', images: ['<payload>'] }]
|
|
1055
|
+
* ```
|
|
1056
|
+
*/
|
|
1057
|
+
export declare function attachUserImages(conversation: readonly Message[], data: readonly string[]): readonly Message[];
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Gates the agent loop's tool calls — the synchronous policy consulted before each call
|
|
1061
|
+
* runs, turning one {@link AuthorityContext} into an {@link AuthorityDecision}.
|
|
976
1062
|
*
|
|
977
1063
|
* @remarks
|
|
978
1064
|
* - **Ordered, first-match-wins.** `evaluate` walks the configured rules in order and
|
|
@@ -989,8 +1075,7 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
|
|
|
989
1075
|
* back to the model as a denial {@link import('@orkestrel/tool').ToolResult} (a `tool`
|
|
990
1076
|
* chunk + a tool message) instead of being executed — no tool run, no budget cost —
|
|
991
1077
|
* so the model sees the denial and can react.
|
|
992
|
-
* - **Synchronous
|
|
993
|
-
* deferred to a later chunk; `evaluate` returns a verdict directly.
|
|
1078
|
+
* - **Synchronous.** `evaluate` returns the verdict directly.
|
|
994
1079
|
* - **Event-free.** A purely functional gate — no Emitter, no events.
|
|
995
1080
|
*
|
|
996
1081
|
* @example
|
|
@@ -1006,28 +1091,27 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
|
|
|
1006
1091
|
export declare class Authority implements AuthorityInterface {
|
|
1007
1092
|
#private;
|
|
1008
1093
|
constructor(options?: AuthorityOptions);
|
|
1009
|
-
evaluate(context:
|
|
1094
|
+
evaluate(context: AuthorityContext): AuthorityDecision;
|
|
1010
1095
|
}
|
|
1011
1096
|
|
|
1012
1097
|
/**
|
|
1013
|
-
*
|
|
1098
|
+
* Carries what an {@link AuthorityInterface} evaluates for one tool call — the call under
|
|
1014
1099
|
* consideration.
|
|
1015
1100
|
*
|
|
1016
1101
|
* @remarks
|
|
1017
|
-
* Lean by design: it carries
|
|
1102
|
+
* Lean by design: it carries the {@link ToolCall} (the tool `name` and its
|
|
1018
1103
|
* parsed `arguments`), which is enough for a rule to branch on what is being called
|
|
1019
|
-
* and with what.
|
|
1020
|
-
* later WITHOUT changing the `evaluate` signature — those would join as new fields.
|
|
1104
|
+
* and with what.
|
|
1021
1105
|
*/
|
|
1022
|
-
export declare interface
|
|
1106
|
+
export declare interface AuthorityContext {
|
|
1023
1107
|
readonly call: ToolCall;
|
|
1024
1108
|
}
|
|
1025
1109
|
|
|
1026
1110
|
/**
|
|
1027
|
-
*
|
|
1111
|
+
* Holds an {@link AuthorityInterface}'s verdict on one tool call.
|
|
1028
1112
|
*
|
|
1029
1113
|
* @remarks
|
|
1030
|
-
* `zone` is a project-defined classification (
|
|
1114
|
+
* `zone` is a project-defined classification (for example `'default'` / `'sensitive'` /
|
|
1031
1115
|
* `'restricted'`) carried for routing + observability; `allowed` is the gate decision
|
|
1032
1116
|
* (a denied call is fed back to the model, never executed); `reason` is an optional
|
|
1033
1117
|
* human-readable explanation surfaced in the denial {@link ToolResult}.
|
|
@@ -1039,27 +1123,26 @@ export declare interface AuthorityDecision {
|
|
|
1039
1123
|
}
|
|
1040
1124
|
|
|
1041
1125
|
/**
|
|
1042
|
-
*
|
|
1043
|
-
* {@link
|
|
1126
|
+
* Gates each tool call before it runs — the synchronous policy that turns one
|
|
1127
|
+
* {@link AuthorityContext} into an {@link AuthorityDecision}.
|
|
1044
1128
|
*
|
|
1045
1129
|
* @remarks
|
|
1046
1130
|
* Ordered first-match-wins over the configured rules, falling back to the configured
|
|
1047
|
-
* default when none match (see {@link AuthorityOptions}).
|
|
1048
|
-
* the
|
|
1049
|
-
* chunk. Event-free — no Emitter, no events.
|
|
1131
|
+
* default when none match (see {@link AuthorityOptions}). `evaluate` is synchronous and
|
|
1132
|
+
* returns the verdict directly. Event-free — no Emitter, no events.
|
|
1050
1133
|
*/
|
|
1051
1134
|
export declare interface AuthorityInterface {
|
|
1052
1135
|
/**
|
|
1053
|
-
*
|
|
1136
|
+
* Evaluates one tool call against the ordered rules.
|
|
1054
1137
|
*
|
|
1055
|
-
* @param context - The call under consideration (see {@link
|
|
1138
|
+
* @param context - The call under consideration (see {@link AuthorityContext})
|
|
1056
1139
|
* @returns The first matching rule's verdict, or the fallback when none match
|
|
1057
1140
|
*/
|
|
1058
|
-
evaluate(context:
|
|
1141
|
+
evaluate(context: AuthorityContext): AuthorityDecision;
|
|
1059
1142
|
}
|
|
1060
1143
|
|
|
1061
1144
|
/**
|
|
1062
|
-
*
|
|
1145
|
+
* Configures `createAuthority` — the ordered rules and the no-match fallback.
|
|
1063
1146
|
*
|
|
1064
1147
|
* @remarks
|
|
1065
1148
|
* `rules` are evaluated in order, first match wins (see {@link AuthorityRule}).
|
|
@@ -1075,7 +1158,7 @@ export declare interface AuthorityOptions {
|
|
|
1075
1158
|
}
|
|
1076
1159
|
|
|
1077
1160
|
/**
|
|
1078
|
-
*
|
|
1161
|
+
* Represents one ordered policy rule an {@link AuthorityInterface} evaluates.
|
|
1079
1162
|
*
|
|
1080
1163
|
* @remarks
|
|
1081
1164
|
* The FIRST rule whose `match` returns true decides; if none match, the authority's
|
|
@@ -1085,16 +1168,59 @@ export declare interface AuthorityOptions {
|
|
|
1085
1168
|
* into the denial {@link ToolResult}).
|
|
1086
1169
|
*/
|
|
1087
1170
|
export declare interface AuthorityRule {
|
|
1088
|
-
readonly match: (context:
|
|
1171
|
+
readonly match: (context: AuthorityContext) => boolean;
|
|
1089
1172
|
readonly zone: string;
|
|
1090
1173
|
readonly allowed?: boolean;
|
|
1091
1174
|
readonly reason?: string;
|
|
1092
1175
|
}
|
|
1093
1176
|
|
|
1094
1177
|
/**
|
|
1095
|
-
*
|
|
1096
|
-
*
|
|
1097
|
-
*
|
|
1178
|
+
* Builds the FRAMED recap message for one compacted section — the same role and stable `id`
|
|
1179
|
+
* as {@link buildSummaryMessage}, with the content prefixed by
|
|
1180
|
+
* {@link import('./constants.js').CONVERSATION_RECAP_PREFIX}.
|
|
1181
|
+
*
|
|
1182
|
+
* @remarks
|
|
1183
|
+
* Pure and total. The prefix is what makes a small model read the message as a CONDENSED
|
|
1184
|
+
* RECAP of earlier turns rather than a literal assistant turn to echo or answer from. It is a
|
|
1185
|
+
* fixed handful of tokens, so a conversation's `view()` stays lean however many sections it
|
|
1186
|
+
* carries.
|
|
1187
|
+
*
|
|
1188
|
+
* @param section - The compacted section to render
|
|
1189
|
+
* @returns The framed recap message
|
|
1190
|
+
*
|
|
1191
|
+
* @example
|
|
1192
|
+
* ```ts
|
|
1193
|
+
* buildRecapMessage({ id: 's1', summary: 'recap', messages: [] })
|
|
1194
|
+
* // { id: 's1', role: 'assistant', content: `${CONVERSATION_RECAP_PREFIX}recap` }
|
|
1195
|
+
* ```
|
|
1196
|
+
*/
|
|
1197
|
+
export declare function buildRecapMessage(section: Section): Message;
|
|
1198
|
+
|
|
1199
|
+
/**
|
|
1200
|
+
* Builds the RAW synthetic summary message for one compacted section — role `'assistant'`,
|
|
1201
|
+
* the section's stable `id`, its `summary` VERBATIM as content.
|
|
1202
|
+
*
|
|
1203
|
+
* @remarks
|
|
1204
|
+
* Pure and total. This is the unframed form the rollup regeneration digests (a
|
|
1205
|
+
* summary-of-summaries over the section summaries); the recap LABEL is a `view()`
|
|
1206
|
+
* presentation concern kept out of what the summarizer re-reads — see
|
|
1207
|
+
* {@link buildRecapMessage}.
|
|
1208
|
+
*
|
|
1209
|
+
* @param section - The compacted section to render
|
|
1210
|
+
* @returns The synthetic summary message
|
|
1211
|
+
*
|
|
1212
|
+
* @example
|
|
1213
|
+
* ```ts
|
|
1214
|
+
* buildSummaryMessage({ id: 's1', summary: 'recap', messages: [] })
|
|
1215
|
+
* // { id: 's1', role: 'assistant', content: 'recap' }
|
|
1216
|
+
* ```
|
|
1217
|
+
*/
|
|
1218
|
+
export declare function buildSummaryMessage(section: Section): Message;
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* Buffers chunks in a minimal unbounded async channel — the eager pump WRITES them in
|
|
1222
|
+
* (`push`) and ends it (`close` / `fail`) regardless of consumption; a consumer READS them back
|
|
1223
|
+
* live through the `drain` async-iterator. Decoupling write from read is what lets a
|
|
1098
1224
|
* producer make progress without a consumer pulling.
|
|
1099
1225
|
*
|
|
1100
1226
|
* @remarks
|
|
@@ -1115,7 +1241,7 @@ export declare interface AuthorityRule {
|
|
|
1115
1241
|
* }
|
|
1116
1242
|
* ```
|
|
1117
1243
|
*/
|
|
1118
|
-
export declare class Channel<T> {
|
|
1244
|
+
export declare class Channel<T> implements ChannelInterface<T> {
|
|
1119
1245
|
#private;
|
|
1120
1246
|
push(value: T): void;
|
|
1121
1247
|
close(): void;
|
|
@@ -1124,23 +1250,66 @@ export declare class Channel<T> {
|
|
|
1124
1250
|
}
|
|
1125
1251
|
|
|
1126
1252
|
/**
|
|
1127
|
-
*
|
|
1128
|
-
*
|
|
1129
|
-
*
|
|
1253
|
+
* Buffers values in an unbounded async channel — a producer WRITES them in (`push`) and
|
|
1254
|
+
* ends it (`close` / `fail`) regardless of consumption, while a consumer READS them back
|
|
1255
|
+
* live through `drain`.
|
|
1130
1256
|
*
|
|
1131
1257
|
* @remarks
|
|
1132
|
-
*
|
|
1133
|
-
*
|
|
1134
|
-
*
|
|
1135
|
-
*
|
|
1136
|
-
*
|
|
1258
|
+
* Decoupling the write from the read is what lets a producer make progress with nobody
|
|
1259
|
+
* pulling: an agent's eager pump writes each {@link AgentChunk} into one, so the run's
|
|
1260
|
+
* `result` settles whether or not `events` is ever drained. A waiting `drain` parks on a
|
|
1261
|
+
* resolver the next `push` / `close` / `fail` fires, so a value pushed at a parked reader is
|
|
1262
|
+
* delivered rather than dropped. Buffered values are always yielded BEFORE the end is
|
|
1263
|
+
* reported, so a `close` arriving alongside the last values still delivers them. The FIRST
|
|
1264
|
+
* failure wins — a later `close` / `fail` cannot override a recorded error. Event-free.
|
|
1265
|
+
*
|
|
1266
|
+
* @typeParam T - The value type the channel carries
|
|
1137
1267
|
*/
|
|
1138
|
-
export declare interface
|
|
1139
|
-
|
|
1268
|
+
export declare interface ChannelInterface<T> {
|
|
1269
|
+
/**
|
|
1270
|
+
* Writes one value — buffered, then handed to a parked consumer.
|
|
1271
|
+
*
|
|
1272
|
+
* @param value - The value to enqueue
|
|
1273
|
+
*/
|
|
1274
|
+
push(value: T): void;
|
|
1275
|
+
/** Ends the channel normally — a draining consumer returns once the buffer is empty. */
|
|
1276
|
+
close(): void;
|
|
1277
|
+
/**
|
|
1278
|
+
* Ends the channel with a failure — a draining consumer throws it once the buffer is empty.
|
|
1279
|
+
*
|
|
1280
|
+
* @param error - The failure to surface (the first one recorded wins)
|
|
1281
|
+
*/
|
|
1282
|
+
fail(error: unknown): void;
|
|
1283
|
+
/**
|
|
1284
|
+
* Reads the values back live, in write order.
|
|
1285
|
+
*
|
|
1286
|
+
* @returns A generator yielding each pushed value, returning on `close` and throwing on `fail`
|
|
1287
|
+
*/
|
|
1288
|
+
drain(): AsyncGenerator<T, void>;
|
|
1140
1289
|
}
|
|
1141
1290
|
|
|
1142
1291
|
/**
|
|
1143
|
-
*
|
|
1292
|
+
* Collects the `base64` payload of the IMAGE files in a workspace file list — the data an
|
|
1293
|
+
* agent context attaches to the last user message.
|
|
1294
|
+
*
|
|
1295
|
+
* @remarks
|
|
1296
|
+
* Pure and total. `isBinary` NARROWS the tagless content to its binary arm (a total guard,
|
|
1297
|
+
* never an assertion), then the MIME prefix gates it to an image, so a text file and a non-image
|
|
1298
|
+
* binary (a PDF) are both skipped. Order follows the file list.
|
|
1299
|
+
*
|
|
1300
|
+
* @param files - The (already scope-filtered) workspace files
|
|
1301
|
+
* @returns The `base64` payload of each image file, in file order
|
|
1302
|
+
*
|
|
1303
|
+
* @example
|
|
1304
|
+
* ```ts
|
|
1305
|
+
* collectImageData([createFile({ path: 'a.png', content: { base64: '<payload>', mime: 'image/png' } })])
|
|
1306
|
+
* // ['<payload>']
|
|
1307
|
+
* ```
|
|
1308
|
+
*/
|
|
1309
|
+
export declare function collectImageData(files: readonly FileInterface[]): readonly string[];
|
|
1310
|
+
|
|
1311
|
+
/**
|
|
1312
|
+
* Configures one {@link ConversationInterface.compact} call — overrides for ONE fold.
|
|
1144
1313
|
*
|
|
1145
1314
|
* @remarks
|
|
1146
1315
|
* `keep` overrides the conversation's configured retained-tail size for THIS compaction only
|
|
@@ -1152,52 +1321,52 @@ export declare interface CompactionState {
|
|
|
1152
1321
|
* conversation's own `sections` cap (or unlimited) applies.
|
|
1153
1322
|
*/
|
|
1154
1323
|
export declare interface CompactOptions {
|
|
1155
|
-
/**
|
|
1324
|
+
/** Overrides the retained-tail size for this compaction; omitted ⇒ the conversation's own `keep`. */
|
|
1156
1325
|
readonly keep?: number;
|
|
1157
|
-
/**
|
|
1326
|
+
/** Overrides the `sections` cap for this compaction; omitted ⇒ the conversation's own cap (or unlimited). */
|
|
1158
1327
|
readonly sections?: number;
|
|
1159
1328
|
}
|
|
1160
1329
|
|
|
1161
1330
|
/**
|
|
1162
|
-
*
|
|
1163
|
-
* model prefers (
|
|
1331
|
+
* Holds a provider's OPTIONAL context-framing default, keyed by section kind — the framing a
|
|
1332
|
+
* model prefers (for example XML tags against Markdown headers), declared by a
|
|
1164
1333
|
* {@link ProviderInterface} that opts in.
|
|
1165
1334
|
*
|
|
1166
1335
|
* @remarks
|
|
1167
1336
|
* Each key is a {@link ContextSectionFormat} for one of the observable context sections
|
|
1168
|
-
* (
|
|
1337
|
+
* (the `instructions` section), so a provider can frame each section independently — and any
|
|
1169
1338
|
* it omits falls through to that manager's built-in default. It is the PROVIDER-DEFAULT
|
|
1170
1339
|
* level of the {@link import('./AgentContext.js').AgentContext} build cascade: it BEATS a
|
|
1171
1340
|
* manager's built-in default but is BEATEN by a manager-options override and by a per-item
|
|
1172
1341
|
* override (see {@link AgentContextInterface.build}). It references the ABSTRACT core
|
|
1173
1342
|
* item interface ({@link InstructionInterface}), so a provider opting in imports it from
|
|
1174
|
-
* `@
|
|
1343
|
+
* `@orkestrel/agent` — the type is provider-agnostic, with no backend coupling. Omitting it
|
|
1175
1344
|
* entirely (the default for an agnostic provider) leaves every section on its manager's
|
|
1176
1345
|
* built-in framing.
|
|
1177
1346
|
*/
|
|
1178
|
-
export declare interface
|
|
1179
|
-
/**
|
|
1347
|
+
export declare interface ContextFormat {
|
|
1348
|
+
/** Frames the instructions section; omitted ⇒ that manager's built-in. */
|
|
1180
1349
|
readonly instructions?: ContextSectionFormat<InstructionInterface>;
|
|
1181
1350
|
}
|
|
1182
1351
|
|
|
1183
1352
|
/**
|
|
1184
|
-
*
|
|
1353
|
+
* Overrides one context section's format — an `open` / `render` / `close` trio
|
|
1185
1354
|
* that frames a section in the {@link import('./AgentContext.js').AgentContext} build
|
|
1186
1355
|
* cascade: a top line rendered once before the items, a per-item rendering, and a bottom
|
|
1187
1356
|
* line rendered once after the items.
|
|
1188
1357
|
*
|
|
1189
1358
|
* @remarks
|
|
1190
|
-
*
|
|
1359
|
+
* `open`, `render`, and `close` are OPTIONAL and resolved INDEPENDENTLY (so an override may set only
|
|
1191
1360
|
* the top, only the per-item rendering, only the bottom, or any mix). A section assembles
|
|
1192
1361
|
* as `[open, ...items.map(render), close]` with empty / absent slots dropped, the survivors
|
|
1193
1362
|
* blank-line (`\n\n`) joined — so `open` + `close` together let a developer WRAP the whole
|
|
1194
|
-
* group (
|
|
1195
|
-
* leading text (the header, or a group's opening tag); `render` turns one section
|
|
1196
|
-
* {@link InstructionInterface}) into its prompt text; `close` is the trailing text.
|
|
1197
|
-
* and `render` cascade through the
|
|
1363
|
+
* group (for example `open: '<instructions>'` … `close: '</instructions>'`). `open` is the
|
|
1364
|
+
* section's leading text (the header, or a group's opening tag); `render` turns one section
|
|
1365
|
+
* item (an {@link InstructionInterface}) into its prompt text; `close` is the trailing text.
|
|
1366
|
+
* `open` and `render` cascade through the
|
|
1198
1367
|
* built-in floor (`open` ⇒ the manager's built-in header, `render` ⇒ the manager's built-in
|
|
1199
|
-
* rendering); `close` has NO built-in, so an unset `close`
|
|
1200
|
-
* It is the unit BOTH a provider's {@link
|
|
1368
|
+
* rendering); `close` has NO built-in, so an unset `close` yields no closing line.
|
|
1369
|
+
* It is the unit BOTH a provider's {@link ContextFormat} (a per-section-kind
|
|
1201
1370
|
* default) and a manager's `Options` carry — see {@link AgentContextInterface.build} for
|
|
1202
1371
|
* the full precedence.
|
|
1203
1372
|
*
|
|
@@ -1205,29 +1374,54 @@ export declare interface ContextFormatInterface {
|
|
|
1205
1374
|
*/
|
|
1206
1375
|
export declare interface ContextSectionFormat<T> {
|
|
1207
1376
|
/**
|
|
1208
|
-
*
|
|
1209
|
-
* opening wrapper,
|
|
1377
|
+
* Holds text rendered ONCE before the section's items — the section header or a group's
|
|
1378
|
+
* opening wrapper, for example `'<instructions>'`; omitted ⇒ the next cascade level decides
|
|
1210
1379
|
* (defaulting to the built-in header).
|
|
1211
1380
|
*/
|
|
1212
1381
|
readonly open?: string;
|
|
1213
|
-
/**
|
|
1382
|
+
/** Overrides one item's rendering; omitted ⇒ the next cascade level decides. */
|
|
1214
1383
|
readonly render?: (item: T) => string;
|
|
1215
1384
|
/**
|
|
1216
|
-
*
|
|
1217
|
-
* `'</instructions>'`; omitted ⇒ no closing line (there is no built-in close).
|
|
1385
|
+
* Holds text rendered ONCE after the section's items — a group's closing wrapper, for
|
|
1386
|
+
* example `'</instructions>'`; omitted ⇒ no closing line (there is no built-in close).
|
|
1218
1387
|
*/
|
|
1219
1388
|
readonly close?: string;
|
|
1220
1389
|
}
|
|
1221
1390
|
|
|
1222
1391
|
/**
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1392
|
+
* Exposes the manager surface one context section's format cascade reads — its built-in
|
|
1393
|
+
* `open` / `render`, plus the raw options override the cascade layers a provider
|
|
1394
|
+
* default beneath.
|
|
1395
|
+
*
|
|
1396
|
+
* @remarks
|
|
1397
|
+
* The narrow contract the cascade resolvers
|
|
1398
|
+
* ({@link import('./helpers.js').resolveOpen} / {@link import('./helpers.js').resolveClose} /
|
|
1399
|
+
* {@link import('./helpers.js').resolveItem}) take, so they stay independent of WHICH manager
|
|
1400
|
+
* supplies the section: an {@link InstructionManagerInterface} satisfies it structurally.
|
|
1401
|
+
* `open` and `render` already encapsulate `[options-override → built-in]` (so a manager
|
|
1402
|
+
* used standalone renders correctly), and `format` exposes the raw override so `build()` can
|
|
1403
|
+
* interleave the provider default BENEATH it.
|
|
1404
|
+
*
|
|
1405
|
+
* @typeParam T - The section item this source renders
|
|
1406
|
+
*/
|
|
1407
|
+
export declare interface ContextSectionSourceInterface<T> {
|
|
1408
|
+
/** Names the built-in section header (already resolved against the manager-options override). */
|
|
1409
|
+
readonly open: string;
|
|
1410
|
+
/** Holds the raw manager-options override, or `undefined` when none was supplied. */
|
|
1411
|
+
readonly format: ContextSectionFormat<T> | undefined;
|
|
1412
|
+
/** Renders one item (already resolved against the manager-options override). */
|
|
1413
|
+
render(item: T): string;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* Represents a conversation — a live uncompacted tail of messages it OWNS DIRECTLY ABOVE a
|
|
1418
|
+
* flat message store, plus compacted, summarized {@link Section}s and a regenerated rollup
|
|
1225
1419
|
* `summary`, with on-demand `rehydrate` and substring `search`, driven by a provider-agnostic
|
|
1226
|
-
* {@link
|
|
1420
|
+
* {@link ConversationSummaryHandler} seam (so `core` never imports a provider).
|
|
1227
1421
|
*
|
|
1228
1422
|
* @remarks
|
|
1229
1423
|
* - **Live tail + sections.** The conversation OWNS its live tail DIRECTLY — `#messages` is an
|
|
1230
|
-
* insertion-ordered `Map` of immutable {@link
|
|
1424
|
+
* insertion-ordered `Map` of immutable {@link Message}s keyed by their minted id
|
|
1231
1425
|
* (the SAME store mechanics a flat manager had, folded in: `add` / `message` / `messages` /
|
|
1232
1426
|
* `remove` / `clear` / `count`), exactly as a `Workspace` owns its files (no separate
|
|
1233
1427
|
* per-value manager). `#sections` are the compacted history (oldest → newest), each a
|
|
@@ -1245,10 +1439,10 @@ export declare interface ContextSectionFormat<T> {
|
|
|
1245
1439
|
* THROWS a {@link ConversationError} when no `#summarize` was supplied. Two summarizer calls
|
|
1246
1440
|
* per compaction.
|
|
1247
1441
|
* - **`rehydrate(id)` / `search(query)`.** `rehydrate` returns a section's full original
|
|
1248
|
-
* messages (`[]` for an unknown id) and emits `rehydrate` — a pure read (
|
|
1249
|
-
*
|
|
1250
|
-
* messages (every section's originals + the live tail).
|
|
1251
|
-
* - **Observable
|
|
1442
|
+
* messages (`[]` for an unknown id) and emits `rehydrate` — a pure read (the caller decides
|
|
1443
|
+
* whether to re-add them; `rehydrate` never reinserts). `search` is a case-insensitive
|
|
1444
|
+
* substring scan of `content` across ALL messages (every section's originals + the live tail).
|
|
1445
|
+
* - **Observable.** The owned {@link emitter} ({@link ConversationEventMap}) carries
|
|
1252
1446
|
* `compact` / `summary` / `rehydrate`, emitted directly, strictly AFTER the state change;
|
|
1253
1447
|
* the emitter isolates a listener throw and routes it to its `error` handler (the `error`
|
|
1254
1448
|
* option), so a buggy observer can never corrupt a compaction.
|
|
@@ -1267,30 +1461,30 @@ export declare interface ContextSectionFormat<T> {
|
|
|
1267
1461
|
*/
|
|
1268
1462
|
export declare class Conversation implements ConversationInterface {
|
|
1269
1463
|
#private;
|
|
1270
|
-
constructor(options?: ConversationOptions
|
|
1464
|
+
constructor(options?: ConversationOptions);
|
|
1271
1465
|
get id(): string;
|
|
1272
1466
|
get emitter(): EmitterInterface<ConversationEventMap>;
|
|
1273
1467
|
get summary(): string | undefined;
|
|
1274
|
-
get sections(): readonly
|
|
1468
|
+
get sections(): readonly Section[];
|
|
1275
1469
|
get summarizable(): boolean;
|
|
1276
1470
|
get count(): number;
|
|
1277
|
-
add(input: MessageInput):
|
|
1278
|
-
add(inputs: readonly MessageInput[]): readonly
|
|
1279
|
-
message(id: string):
|
|
1280
|
-
messages(): readonly
|
|
1471
|
+
add(input: MessageInput): Message;
|
|
1472
|
+
add(inputs: readonly MessageInput[]): readonly Message[];
|
|
1473
|
+
message(id: string): Message | undefined;
|
|
1474
|
+
messages(): readonly Message[];
|
|
1281
1475
|
remove(id: string): boolean;
|
|
1282
1476
|
remove(ids: readonly string[]): boolean;
|
|
1283
1477
|
clear(): void;
|
|
1284
|
-
view(): readonly
|
|
1285
|
-
compact(options?: CompactOptions): Promise<
|
|
1286
|
-
rehydrate(id: string): readonly
|
|
1287
|
-
search(query: string): readonly
|
|
1478
|
+
view(): readonly Message[];
|
|
1479
|
+
compact(options?: CompactOptions): Promise<Section | undefined>;
|
|
1480
|
+
rehydrate(id: string): readonly Message[];
|
|
1481
|
+
search(query: string): readonly Message[];
|
|
1288
1482
|
reference(options?: ConversationReferenceOptions): string;
|
|
1289
1483
|
snapshot(): ConversationSnapshot;
|
|
1290
1484
|
}
|
|
1291
1485
|
|
|
1292
1486
|
/**
|
|
1293
|
-
*
|
|
1487
|
+
* Names the framing label a {@link ConversationInterface}'s `view()` prefixes onto each compacted
|
|
1294
1488
|
* section's summary so a small model reads it as a CONDENSED RECAP of earlier turns — not a
|
|
1295
1489
|
* literal assistant turn to echo or treat as the live answer.
|
|
1296
1490
|
*
|
|
@@ -1306,70 +1500,71 @@ export declare class Conversation implements ConversationInterface {
|
|
|
1306
1500
|
export declare const CONVERSATION_RECAP_PREFIX = "[Summary of earlier messages] ";
|
|
1307
1501
|
|
|
1308
1502
|
/**
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1503
|
+
* Reports a conversation with no {@link ConversationSummaryHandler} to fold its messages
|
|
1504
|
+
* with, or with a structurally invalid `sections` cap — thrown by a
|
|
1505
|
+
* {@link ConversationInterface}'s `compact()`, carrying a machine-readable `code`.
|
|
1312
1506
|
*
|
|
1313
1507
|
* @remarks
|
|
1314
1508
|
* Compaction REQUIRES a summarizer (it digests the folded slice into a section summary and
|
|
1315
1509
|
* regenerates the rollup); a conversation created without one can still store + `view()` its
|
|
1316
|
-
* live tail, but a `compact()` is a programmer error
|
|
1317
|
-
* A `sections` cap (
|
|
1510
|
+
* live tail, but a `compact()` is a programmer error and throws this with `'SUMMARIZER'`.
|
|
1511
|
+
* A `sections` cap (on {@link import('./types.js').ConversationOptions} /
|
|
1318
1512
|
* {@link import('./types.js').ConversationManagerOptions} /
|
|
1319
1513
|
* {@link import('./types.js').CompactOptions}) must be `>= 1` — a sub-1 cap is a programmer
|
|
1320
1514
|
* error and throws this with `'SECTIONS'`. Narrow a caught value with
|
|
1321
1515
|
* {@link isConversationError} and branch on `error.code`.
|
|
1322
1516
|
*/
|
|
1323
1517
|
export declare class ConversationError extends Error {
|
|
1324
|
-
/**
|
|
1518
|
+
/** Names the machine-readable condition — `'SUMMARIZER'`: a `compact()` with no summarizer; `'SECTIONS'`: a sub-1 `sections` cap. */
|
|
1325
1519
|
readonly code: 'SUMMARIZER' | 'SECTIONS';
|
|
1326
1520
|
constructor(code: 'SUMMARIZER' | 'SECTIONS', message: string);
|
|
1327
1521
|
}
|
|
1328
1522
|
|
|
1329
1523
|
/**
|
|
1330
|
-
*
|
|
1331
|
-
* moments a fire-and-forget observer subscribes to
|
|
1524
|
+
* Maps the push observation surface of a {@link ConversationInterface} — the compaction
|
|
1525
|
+
* moments a fire-and-forget observer subscribes to through `conversation.emitter.on`.
|
|
1332
1526
|
*
|
|
1333
1527
|
* @remarks
|
|
1334
|
-
* `compact` carries the newly-folded {@link
|
|
1528
|
+
* `compact` carries the newly-folded {@link Section}; `collapse` carries a section
|
|
1335
1529
|
* created by folding multiple OLDER sections together (a bounded-`sections` cap enforcement,
|
|
1336
1530
|
* distinct from `compact`'s fresh live-tail fold); `summary` carries the regenerated
|
|
1337
1531
|
* conversation rollup (refreshed on each compaction); `rehydrate` carries the `id` of a
|
|
1338
|
-
* section whose originals were pulled back. Listener isolation is the emitter's
|
|
1339
|
-
*
|
|
1532
|
+
* section whose originals were pulled back. Listener isolation is the emitter's:
|
|
1533
|
+
* every event is emitted directly and a listener throw is routed to the emitter's
|
|
1340
1534
|
* `error` handler (the `error` option), never onto this map, so a buggy observer can never
|
|
1341
|
-
* corrupt a compaction. A `type` alias (not `interface extends EventMap
|
|
1535
|
+
* corrupt a compaction. A `type` alias (not `interface extends EventMap`) so the
|
|
1342
1536
|
* type-literal satisfies `EventMap` structurally.
|
|
1343
1537
|
*/
|
|
1344
1538
|
export declare type ConversationEventMap = {
|
|
1345
|
-
/**
|
|
1346
|
-
readonly compact: readonly [section:
|
|
1347
|
-
/**
|
|
1539
|
+
/** Reports a new section folded from the live tail — the created section. */
|
|
1540
|
+
readonly compact: readonly [section: Section];
|
|
1541
|
+
/** Reports the conversation rollup regenerated — the new summary text. */
|
|
1348
1542
|
readonly summary: readonly [summary: string];
|
|
1349
|
-
/**
|
|
1543
|
+
/** Reports a section's original messages pulled back — the section's `id`. */
|
|
1350
1544
|
readonly rehydrate: readonly [id: string];
|
|
1351
1545
|
/**
|
|
1352
|
-
*
|
|
1353
|
-
* merged {@link
|
|
1546
|
+
* Reports the bounded-`sections` cap folding the oldest sections into ONE merged section — the
|
|
1547
|
+
* merged {@link Section} that replaced them.
|
|
1354
1548
|
*/
|
|
1355
|
-
readonly collapse: readonly [section:
|
|
1549
|
+
readonly collapse: readonly [section: Section];
|
|
1356
1550
|
};
|
|
1357
1551
|
|
|
1358
1552
|
/**
|
|
1359
|
-
*
|
|
1553
|
+
* Carries the data to author a {@link ConversationInterface} through a
|
|
1360
1554
|
* {@link ConversationManagerInterface} — the optional `id`, a `summarize` override, a `keep`
|
|
1361
1555
|
* override, and the reserved `on` hooks.
|
|
1362
1556
|
*
|
|
1363
1557
|
* @remarks
|
|
1364
1558
|
* `id` is the conversation's identity (minted when omitted). `summarize` OVERRIDES the
|
|
1365
|
-
* manager's default {@link
|
|
1559
|
+
* manager's default {@link ConversationSummaryHandler} for this conversation (omitted ⇒ the
|
|
1366
1560
|
* manager's default flows in). `keep` overrides the manager's default retained-tail size.
|
|
1367
|
-
* `sections` overrides the manager's default `sections` cap. `on` is the
|
|
1561
|
+
* `sections` overrides the manager's default `sections` cap. `on` is the reserved listener key
|
|
1368
1562
|
* (initial {@link ConversationEventMap} listeners). `snapshot` is
|
|
1369
1563
|
* the construction-time hydration seam — a {@link ConversationSnapshot} whose `id` / `summary` /
|
|
1370
1564
|
* `sections` / live tail are RESTORED into the new conversation (the live `summarize` / `keep` /
|
|
1371
1565
|
* `on` re-supplied alongside it), the conversation analogue of
|
|
1372
|
-
* {@link import('@orkestrel/workspace').WorkspaceOptions}'s `seed
|
|
1566
|
+
* {@link import('@orkestrel/workspace').WorkspaceOptions}'s `seed`, carried onto
|
|
1567
|
+
* {@link ConversationOptions.snapshot}, that a
|
|
1373
1568
|
* {@link ConversationManagerInterface.open} reads a stored snapshot back through; hydration is
|
|
1374
1569
|
* silent (no events). When both `snapshot.id` and `id` are given, `snapshot.id` wins (the snapshot
|
|
1375
1570
|
* IS the conversation's identity).
|
|
@@ -1377,21 +1572,21 @@ export declare type ConversationEventMap = {
|
|
|
1377
1572
|
export declare interface ConversationInput {
|
|
1378
1573
|
readonly id?: string;
|
|
1379
1574
|
/** Overrides the manager's default summarizer for this conversation. */
|
|
1380
|
-
readonly summarize?:
|
|
1575
|
+
readonly summarize?: ConversationSummaryHandler;
|
|
1381
1576
|
/** Overrides the manager's default retained-tail size for this conversation. */
|
|
1382
1577
|
readonly keep?: number;
|
|
1383
1578
|
/** Overrides the manager's default `sections` cap for this conversation. */
|
|
1384
1579
|
readonly sections?: number;
|
|
1385
1580
|
readonly on?: EmitterHooks<ConversationEventMap>;
|
|
1386
|
-
/**
|
|
1581
|
+
/** Hydrates from a {@link ConversationSnapshot}, passed on as {@link ConversationOptions.snapshot}. */
|
|
1387
1582
|
readonly snapshot?: ConversationSnapshot;
|
|
1388
1583
|
}
|
|
1389
1584
|
|
|
1390
1585
|
/**
|
|
1391
|
-
*
|
|
1392
|
-
* uncompacted tail plus compacted, summarized {@link
|
|
1586
|
+
* Groups messages ABOVE the flat {@link MessageManagerInterface} — a live
|
|
1587
|
+
* uncompacted tail plus compacted, summarized {@link Section}s and a conversation
|
|
1393
1588
|
* rollup `summary`, with on-demand `rehydrate` and substring `search`, driven by a
|
|
1394
|
-
* provider-agnostic {@link
|
|
1589
|
+
* provider-agnostic {@link ConversationSummaryHandler} seam.
|
|
1395
1590
|
*
|
|
1396
1591
|
* @remarks
|
|
1397
1592
|
* - **Live tail + sections.** The conversation OWNS its LIVE uncompacted tail DIRECTLY — a
|
|
@@ -1401,109 +1596,110 @@ export declare interface ConversationInput {
|
|
|
1401
1596
|
* (oldest → newest), each a summarized slice that RETAINS its originals. `summary` is the
|
|
1402
1597
|
* conversation rollup (a summary-of-summaries over all sections), regenerated on each
|
|
1403
1598
|
* compaction (`undefined` until the first compaction).
|
|
1404
|
-
* - **Message verbs (the inlined store).** `add` takes one {@link MessageInput} or a batch
|
|
1405
|
-
*
|
|
1599
|
+
* - **Message verbs (the inlined store).** `add` takes one {@link MessageInput} or a batch,
|
|
1600
|
+
* MINTS each message's `id` (a random UUID), stores it, and returns the created
|
|
1406
1601
|
* message(s); a stored message is immutable. `message(id)` resolves one (`undefined` when
|
|
1407
1602
|
* absent); `messages()` lists the live tail in insertion order; `remove` drops one by id or
|
|
1408
|
-
* a batch (
|
|
1603
|
+
* a batch (`true` only when EVERY supplied id was removed); `clear` empties the tail;
|
|
1604
|
+
* `count` is how many live messages are stored.
|
|
1409
1605
|
* - **`view()` — the model input.** Each section folds to ONE synthetic summary message,
|
|
1410
1606
|
* followed by the live messages verbatim: `[...sections-as-summary-messages, ...live]`. The
|
|
1411
1607
|
* rollup `summary` is NOT injected (it is a separately pull-able digest for a
|
|
1412
1608
|
* cross-conversation case); `view()` carries the per-section summaries, which ARE the
|
|
1413
1609
|
* compaction benefit.
|
|
1414
1610
|
* - **`compact()` — fold older live → a section.** Folds the oldest `count - keep` live
|
|
1415
|
-
* messages into a new {@link
|
|
1611
|
+
* messages into a new {@link Section} (its `summary` from `summarize`), removes
|
|
1416
1612
|
* them from the live tail, REGENERATES the rollup (a second `summarize` over all section
|
|
1417
1613
|
* summaries), and emits `summary` then `compact` — returning the new section (or
|
|
1418
1614
|
* `undefined` when nothing folds). TWO summarizer calls per compaction (the section digest
|
|
1419
1615
|
* + the rollup). Throws a {@link import('./errors.js').ConversationError} when no
|
|
1420
1616
|
* `summarize` was supplied.
|
|
1421
1617
|
* - **`summarizable` — whether a `compact()` CAN fold.** `true` when a
|
|
1422
|
-
* {@link
|
|
1618
|
+
* {@link ConversationSummaryHandler} was supplied, `false` otherwise. The agent loop's AUTOMATIC
|
|
1423
1619
|
* compaction (`AgentOptions.window`) gates on it so a conversation that has no summarizer is
|
|
1424
1620
|
* never auto-compacted (and the loop never throws the `compact()` `SUMMARIZER` error from the
|
|
1425
1621
|
* auto path). A MANUAL `compact()` still throws without a summarizer — only the auto path is
|
|
1426
1622
|
* guarded.
|
|
1427
1623
|
* - **`rehydrate(id)` / `search(query)` — read the retained originals.** `rehydrate` returns
|
|
1428
1624
|
* a section's full original messages (`[]` for an unknown id) and emits `rehydrate` — a
|
|
1429
|
-
* pure READ (the caller decides whether to re-add them;
|
|
1625
|
+
* pure READ (the caller decides whether to re-add them; `rehydrate` never reinserts).
|
|
1430
1626
|
* `search` is a case-insensitive substring scan of `content` across ALL messages (every
|
|
1431
1627
|
* section's originals + the live tail).
|
|
1432
1628
|
* - **`reference(options?)` — pull THIS conversation into ANOTHER with provenance.** A PURE
|
|
1433
1629
|
* string render (no model call) of a self-labeled, fenced cross-conversation block — the
|
|
1434
1630
|
* rollup `summary` (when included + present) plus cherry-picked excerpts — framed so a small
|
|
1435
|
-
* model reads it as FOREIGN material. Written into the ACTIVE conversation's context
|
|
1436
|
-
* active workspace (`context.workspaces.active?.write(path, block)`); the cherry-pick
|
|
1437
|
-
* from this conversation's own `search` / `rehydrate`, never its whole history.
|
|
1438
|
-
* - **Observable
|
|
1631
|
+
* model reads it as FOREIGN material. Written into the ACTIVE conversation's context through
|
|
1632
|
+
* the active workspace (`context.workspaces.active?.write(path, block)`); the cherry-pick
|
|
1633
|
+
* comes from this conversation's own `search` / `rehydrate`, never its whole history.
|
|
1634
|
+
* - **Observable.** The owned `emitter` ({@link ConversationEventMap}) carries
|
|
1439
1635
|
* `compact` / `summary` / `rehydrate`; the emitter isolates a listener throw and routes it
|
|
1440
|
-
* to its `error` handler (the `error` option
|
|
1636
|
+
* to its `error` handler (the `error` option).
|
|
1441
1637
|
*/
|
|
1442
1638
|
export declare interface ConversationInterface {
|
|
1443
1639
|
readonly id: string;
|
|
1444
1640
|
readonly emitter: EmitterInterface<ConversationEventMap>;
|
|
1445
|
-
/**
|
|
1641
|
+
/** Holds the conversation rollup (a summary-of-summaries), regenerated on each compaction; `undefined` until the first. */
|
|
1446
1642
|
readonly summary: string | undefined;
|
|
1447
|
-
/**
|
|
1448
|
-
readonly sections: readonly
|
|
1643
|
+
/** Lists the compacted history, oldest → newest. */
|
|
1644
|
+
readonly sections: readonly Section[];
|
|
1449
1645
|
/**
|
|
1450
|
-
*
|
|
1646
|
+
* Reports whether a `compact()` CAN fold — `true` when a {@link ConversationSummaryHandler} was supplied.
|
|
1451
1647
|
* The agent loop's AUTOMATIC compaction (`AgentOptions.window`) gates on it (a non-summarizable
|
|
1452
1648
|
* conversation is never auto-compacted, so the auto path never throws the `SUMMARIZER` error);
|
|
1453
1649
|
* a MANUAL `compact()` still throws without a summarizer.
|
|
1454
1650
|
*/
|
|
1455
1651
|
readonly summarizable: boolean;
|
|
1456
|
-
/**
|
|
1652
|
+
/** Counts the LIVE (uncompacted) messages stored in the tail. */
|
|
1457
1653
|
readonly count: number;
|
|
1458
1654
|
/**
|
|
1459
|
-
*
|
|
1655
|
+
* Appends one message to the live tail (or a batch) — MINTS each message's `id`
|
|
1460
1656
|
* (a random UUID) and returns the created message(s); a stored message is immutable.
|
|
1461
1657
|
*
|
|
1462
1658
|
* @param input - One {@link MessageInput}, or a batch
|
|
1463
|
-
* @returns The created {@link
|
|
1659
|
+
* @returns The created {@link Message}(s), with their minted `id`s
|
|
1464
1660
|
*/
|
|
1465
|
-
add(input: MessageInput):
|
|
1466
|
-
add(inputs: readonly MessageInput[]): readonly
|
|
1661
|
+
add(input: MessageInput): Message;
|
|
1662
|
+
add(inputs: readonly MessageInput[]): readonly Message[];
|
|
1467
1663
|
/**
|
|
1468
|
-
*
|
|
1664
|
+
* Looks up one LIVE message by id.
|
|
1469
1665
|
*
|
|
1470
1666
|
* @param id - The message id to resolve
|
|
1471
|
-
* @returns The {@link
|
|
1667
|
+
* @returns The {@link Message}, or `undefined` when absent
|
|
1472
1668
|
*/
|
|
1473
|
-
message(id: string):
|
|
1669
|
+
message(id: string): Message | undefined;
|
|
1474
1670
|
/**
|
|
1475
|
-
*
|
|
1671
|
+
* Lists every LIVE (uncompacted) message in the tail, in insertion order.
|
|
1476
1672
|
*
|
|
1477
1673
|
* @returns The live tail, in insertion order
|
|
1478
1674
|
*/
|
|
1479
|
-
messages(): readonly
|
|
1675
|
+
messages(): readonly Message[];
|
|
1480
1676
|
/**
|
|
1481
|
-
*
|
|
1677
|
+
* Removes one LIVE message by id (or a batch) from the tail.
|
|
1482
1678
|
*
|
|
1483
1679
|
* @param id - One message id, or a batch
|
|
1484
|
-
* @returns
|
|
1680
|
+
* @returns True when every supplied id was present and removed; false otherwise
|
|
1485
1681
|
*/
|
|
1486
1682
|
remove(id: string): boolean;
|
|
1487
1683
|
remove(ids: readonly string[]): boolean;
|
|
1488
|
-
/**
|
|
1684
|
+
/** Empties the live tail (the compacted `sections` are untouched). */
|
|
1489
1685
|
clear(): void;
|
|
1490
1686
|
/**
|
|
1491
|
-
*
|
|
1687
|
+
* Builds the model input for the next turn — each section as ONE synthetic summary message,
|
|
1492
1688
|
* then the live messages verbatim (the rollup `summary` is NOT injected).
|
|
1493
1689
|
*
|
|
1494
1690
|
* @returns `[...sections-as-summary-messages, ...live messages]`
|
|
1495
1691
|
*/
|
|
1496
|
-
view(): readonly
|
|
1692
|
+
view(): readonly Message[];
|
|
1497
1693
|
/**
|
|
1498
|
-
*
|
|
1499
|
-
* rollup, and
|
|
1694
|
+
* Folds the older live messages into a summarized {@link Section}, regenerates the
|
|
1695
|
+
* rollup, and emits `summary` then `compact`.
|
|
1500
1696
|
*
|
|
1501
1697
|
* @remarks
|
|
1502
1698
|
* Folds the oldest `count - keep` live messages (`keep` from `options`, else the
|
|
1503
1699
|
* conversation's own); when `count <= keep` NOTHING folds and this is a no-op resolving
|
|
1504
1700
|
* `undefined`. Otherwise it summarizes the slice into the section, removes those messages
|
|
1505
1701
|
* from the live tail, regenerates the rollup (a second `summarize` over all sections), and
|
|
1506
|
-
* resolves the new section. Requires a {@link
|
|
1702
|
+
* resolves the new section. Requires a {@link ConversationSummaryHandler} — THROWS a
|
|
1507
1703
|
* {@link import('./errors.js').ConversationError} when none was supplied.
|
|
1508
1704
|
*
|
|
1509
1705
|
* @remarks
|
|
@@ -1514,26 +1710,26 @@ export declare interface ConversationInterface {
|
|
|
1514
1710
|
* propagates; the next successful `compact()` self-heals the section count back to `cap`.
|
|
1515
1711
|
*
|
|
1516
1712
|
* @param options - Optional {@link CompactOptions} (`keep` overrides the retained-tail size)
|
|
1517
|
-
* @returns The new {@link
|
|
1713
|
+
* @returns The new {@link Section}, or `undefined` when nothing folded
|
|
1518
1714
|
*/
|
|
1519
|
-
compact(options?: CompactOptions): Promise<
|
|
1715
|
+
compact(options?: CompactOptions): Promise<Section | undefined>;
|
|
1520
1716
|
/**
|
|
1521
|
-
*
|
|
1717
|
+
* Returns a section's full original messages — a pure READ that emits `rehydrate`.
|
|
1522
1718
|
*
|
|
1523
|
-
* @param id - The {@link
|
|
1719
|
+
* @param id - The {@link Section} `id` to pull back
|
|
1524
1720
|
* @returns The section's retained original messages (empty when no such section)
|
|
1525
1721
|
*/
|
|
1526
|
-
rehydrate(id: string): readonly
|
|
1722
|
+
rehydrate(id: string): readonly Message[];
|
|
1527
1723
|
/**
|
|
1528
|
-
*
|
|
1724
|
+
* Searches `content` for a case-insensitive substring across ALL messages — every section's
|
|
1529
1725
|
* retained originals plus the live tail.
|
|
1530
1726
|
*
|
|
1531
1727
|
* @param query - The substring to match (case-insensitive)
|
|
1532
1728
|
* @returns The matching messages, sections' originals first then the live tail
|
|
1533
1729
|
*/
|
|
1534
|
-
search(query: string): readonly
|
|
1730
|
+
search(query: string): readonly Message[];
|
|
1535
1731
|
/**
|
|
1536
|
-
*
|
|
1732
|
+
* Renders THIS conversation as a self-labeled, fenced PROVENANCE block to pull INTO another
|
|
1537
1733
|
* conversation — a pure string (NO model call), framed so a small model reads it as FOREIGN
|
|
1538
1734
|
* material, not as part of the live thread.
|
|
1539
1735
|
*
|
|
@@ -1554,7 +1750,7 @@ export declare interface ConversationInterface {
|
|
|
1554
1750
|
*/
|
|
1555
1751
|
reference(options?: ConversationReferenceOptions): string;
|
|
1556
1752
|
/**
|
|
1557
|
-
*
|
|
1753
|
+
* Serializes this conversation to a plain, JSON-serializable {@link ConversationSnapshot} — its
|
|
1558
1754
|
* `id`, the rollup `summary`, the compacted `sections`, and the live tail (its `messages()`).
|
|
1559
1755
|
*
|
|
1560
1756
|
* @remarks
|
|
@@ -1562,8 +1758,8 @@ export declare interface ConversationInterface {
|
|
|
1562
1758
|
* {@link ConversationStoreInterface} persistence seam's payload, the exact analogue of
|
|
1563
1759
|
* {@link import('@orkestrel/workspace').WorkspaceInterface}'s `snapshot`. The summarizer /
|
|
1564
1760
|
* `keep` are NOT serialized — they are live
|
|
1565
|
-
* CONFIG re-supplied on hydrate (a `
|
|
1566
|
-
* is the durable analogue of the
|
|
1761
|
+
* CONFIG re-supplied on hydrate (a `ConversationSummaryHandler` is a function, not data). The snapshot
|
|
1762
|
+
* is the durable analogue of the `snapshot` option: a {@link ConversationManagerInterface}
|
|
1567
1763
|
* HYDRATES a conversation from it through that seam (see {@link ConversationManagerInterface.open}).
|
|
1568
1764
|
* Pure — the sections + messages are already plain immutable records (so the snapshot
|
|
1569
1765
|
* `structuredClone`s / JSON-round-trips losslessly), and snapshotting mutates nothing.
|
|
@@ -1574,8 +1770,8 @@ export declare interface ConversationInterface {
|
|
|
1574
1770
|
}
|
|
1575
1771
|
|
|
1576
1772
|
/**
|
|
1577
|
-
*
|
|
1578
|
-
* — the
|
|
1773
|
+
* Registers {@link Conversation}s keyed by `id`, in insertion order, WITH an active pointer
|
|
1774
|
+
* — the id-keyed store over the conversation layer PLUS the `active` / `switch` seam the
|
|
1579
1775
|
* {@link import('../AgentContext.js').AgentContext} renders. Event-free (a registry, like
|
|
1580
1776
|
* {@link import('@orkestrel/workspace').WorkspaceManager}); the observability lives
|
|
1581
1777
|
* on each {@link Conversation}.
|
|
@@ -1592,8 +1788,8 @@ export declare interface ConversationInterface {
|
|
|
1592
1788
|
* `switch(id)` re-points `active` to the conversation with `id` and returns it; an unknown `id`
|
|
1593
1789
|
* returns `undefined` and leaves `active` unchanged (the lenient lookup style — never throws,
|
|
1594
1790
|
* no new error code).
|
|
1595
|
-
* - **Removal.** `remove` drops one by id, or a batch
|
|
1596
|
-
* removing the ACTIVE conversation sets `active` to `undefined`. `clear` empties the registry
|
|
1791
|
+
* - **Removal.** `remove` drops one by id, or a batch — `true` only when EVERY supplied id was
|
|
1792
|
+
* removed; removing the ACTIVE conversation sets `active` to `undefined`. `clear` empties the registry
|
|
1597
1793
|
* and sets `active` to `undefined`.
|
|
1598
1794
|
* - **Event-free.** A purely registry store — no Emitter, no events (each conversation owns
|
|
1599
1795
|
* its own observable `emitter`).
|
|
@@ -1624,8 +1820,8 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1624
1820
|
}
|
|
1625
1821
|
|
|
1626
1822
|
/**
|
|
1627
|
-
*
|
|
1628
|
-
* active pointer — the
|
|
1823
|
+
* Registers {@link ConversationInterface}s keyed by their `id`, in insertion order, WITH an
|
|
1824
|
+
* active pointer — the id-keyed store over the conversation layer PLUS the `active` / `switch` seam the
|
|
1629
1825
|
* {@link AgentContextInterface} renders. Event-free (a registry, like
|
|
1630
1826
|
* {@link import('@orkestrel/workspace').WorkspaceManagerInterface}); the observability lives on each
|
|
1631
1827
|
* {@link ConversationInterface}.
|
|
@@ -1642,12 +1838,12 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1642
1838
|
* `switch(id)` re-points `active` to the conversation with `id` and returns it; an unknown
|
|
1643
1839
|
* `id` returns `undefined` and leaves `active` unchanged (the lenient lookup style — never
|
|
1644
1840
|
* throws, no new error code).
|
|
1645
|
-
* - **Removal.** `remove` drops one by id, or a batch (
|
|
1646
|
-
* when
|
|
1841
|
+
* - **Removal.** `remove` drops one by id, or a batch (array overload FIRST) — `true`
|
|
1842
|
+
* only when EVERY supplied id was removed; removing the ACTIVE conversation sets `active` to `undefined`. `clear`
|
|
1647
1843
|
* empties the registry and sets `active` to `undefined`.
|
|
1648
1844
|
* - **Durable open / save (the optional `store` seam).** When a {@link ConversationStoreInterface}
|
|
1649
1845
|
* is supplied (the `store` option), `open(id)` HYDRATES a conversation from the store on a registry
|
|
1650
|
-
* miss (rebuilding it through the
|
|
1846
|
+
* miss (rebuilding it through the `snapshot` option, flowing the manager's
|
|
1651
1847
|
* default `summarize` / `keep` in) and `save(id)` PERSISTS a registered conversation's
|
|
1652
1848
|
* {@link ConversationInterface.snapshot}. Both are LENIENT without a store — `open` resolves only
|
|
1653
1849
|
* registered ids, `save` is a no-op (`false`) — consistent with the lenient `switch`. It mirrors
|
|
@@ -1657,20 +1853,20 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1657
1853
|
*/
|
|
1658
1854
|
export declare interface ConversationManagerInterface {
|
|
1659
1855
|
readonly count: number;
|
|
1660
|
-
/**
|
|
1856
|
+
/** Holds the active conversation — the agent's message source the context renders; `undefined` until the first `add`. */
|
|
1661
1857
|
readonly active: ConversationInterface | undefined;
|
|
1662
1858
|
conversation(id: string): ConversationInterface | undefined;
|
|
1663
1859
|
conversations(): readonly ConversationInterface[];
|
|
1664
1860
|
add(input?: ConversationInput): ConversationInterface;
|
|
1665
1861
|
switch(id: string): ConversationInterface | undefined;
|
|
1666
1862
|
/**
|
|
1667
|
-
*
|
|
1863
|
+
* Resolves a conversation by id, ACTIVATING it — from the registry if present, else HYDRATED from
|
|
1668
1864
|
* the optional {@link ConversationStoreInterface} (`store`).
|
|
1669
1865
|
*
|
|
1670
1866
|
* @remarks
|
|
1671
1867
|
* - If `id` is ALREADY registered, it is ACTIVATED (`switch`ed to) and returned — no store hit.
|
|
1672
1868
|
* - Else if a `store` is set, `store.get(id)` is awaited; on a HIT the snapshot is rehydrated
|
|
1673
|
-
* into a fresh {@link ConversationInterface} through the
|
|
1869
|
+
* into a fresh {@link ConversationInterface} through the `snapshot` option
|
|
1674
1870
|
* (`add({ snapshot, ... })`, flowing the manager's default `summarize` / `keep` in), which
|
|
1675
1871
|
* registers AND activates it, and it is returned.
|
|
1676
1872
|
* - Else (no store, or a store MISS) ⇒ `undefined` (lenient — no throw).
|
|
@@ -1680,7 +1876,7 @@ export declare interface ConversationManagerInterface {
|
|
|
1680
1876
|
*/
|
|
1681
1877
|
open(id: string): Promise<ConversationInterface | undefined>;
|
|
1682
1878
|
/**
|
|
1683
|
-
*
|
|
1879
|
+
* Persists a REGISTERED conversation's {@link ConversationInterface.snapshot} to the optional
|
|
1684
1880
|
* {@link ConversationStoreInterface} (`store`).
|
|
1685
1881
|
*
|
|
1686
1882
|
* @remarks
|
|
@@ -1689,7 +1885,7 @@ export declare interface ConversationManagerInterface {
|
|
|
1689
1885
|
* `false` — never a throw, consistent with the lenient `switch`.
|
|
1690
1886
|
*
|
|
1691
1887
|
* @param id - The id of the registered conversation to persist
|
|
1692
|
-
* @returns
|
|
1888
|
+
* @returns True if the snapshot was persisted; false otherwise (no store, or an unknown id)
|
|
1693
1889
|
*/
|
|
1694
1890
|
save(id: string): Promise<boolean>;
|
|
1695
1891
|
remove(ids: readonly string[]): boolean;
|
|
@@ -1698,7 +1894,7 @@ export declare interface ConversationManagerInterface {
|
|
|
1698
1894
|
}
|
|
1699
1895
|
|
|
1700
1896
|
/**
|
|
1701
|
-
*
|
|
1897
|
+
* Configures `createConversationManager` — the default {@link ConversationSummaryHandler} and
|
|
1702
1898
|
* retained-tail size the conversations it creates inherit.
|
|
1703
1899
|
*
|
|
1704
1900
|
* @remarks
|
|
@@ -1711,14 +1907,14 @@ export declare interface ConversationManagerInterface {
|
|
|
1711
1907
|
* overrides it); omitted ⇒ unlimited.
|
|
1712
1908
|
*/
|
|
1713
1909
|
export declare interface ConversationManagerOptions {
|
|
1714
|
-
/**
|
|
1715
|
-
readonly summarize?:
|
|
1716
|
-
/**
|
|
1910
|
+
/** Supplies the default summarizer for conversations this manager creates (a per-`add` override wins). */
|
|
1911
|
+
readonly summarize?: ConversationSummaryHandler;
|
|
1912
|
+
/** Sets the default retained-tail size (a per-`add` override wins); defaults to `DEFAULT_CONVERSATION_KEEP`. */
|
|
1717
1913
|
readonly keep?: number;
|
|
1718
|
-
/**
|
|
1914
|
+
/** Sets the default `sections` cap for conversations this manager creates (a per-`add` override wins); omitted ⇒ unlimited. */
|
|
1719
1915
|
readonly sections?: number;
|
|
1720
1916
|
/**
|
|
1721
|
-
*
|
|
1917
|
+
* Holds the optional durable {@link ConversationStoreInterface} backing
|
|
1722
1918
|
* {@link ConversationManagerInterface.open} / {@link ConversationManagerInterface.save} — a memory
|
|
1723
1919
|
* / JSON / SQLite / IndexedDB store a conversation is HYDRATED from (`open` a registry-miss) and
|
|
1724
1920
|
* PERSISTED to (`save`). Omitted ⇒ the manager is registry-only: `open` resolves only what is
|
|
@@ -1729,37 +1925,46 @@ export declare interface ConversationManagerOptions {
|
|
|
1729
1925
|
}
|
|
1730
1926
|
|
|
1731
1927
|
/**
|
|
1732
|
-
*
|
|
1928
|
+
* Configures `createConversation` — the optional `id`, the reserved `on` hooks, the
|
|
1733
1929
|
* provider-agnostic `summarize` seam, and the retained-tail size.
|
|
1734
1930
|
*
|
|
1735
1931
|
* @remarks
|
|
1736
|
-
* `id` is the conversation's identity (a random UUID when omitted). `on` is the
|
|
1737
|
-
* key (initial {@link ConversationEventMap} listeners). `summarize` is the
|
|
1738
|
-
* {@link
|
|
1932
|
+
* `id` is the conversation's identity (a random UUID when omitted). `on` is the reserved
|
|
1933
|
+
* listener key (initial {@link ConversationEventMap} listeners). `summarize` is the
|
|
1934
|
+
* {@link ConversationSummaryHandler} compaction needs — ABSENT ⇒ `compact()` throws a
|
|
1739
1935
|
* {@link import('./errors.js').ConversationError} (a conversation can still store + view a
|
|
1740
|
-
* live tail
|
|
1936
|
+
* live tail; it cannot fold). `keep` is how many recent live messages a `compact()`
|
|
1741
1937
|
* retains VERBATIM (folding only the older ones); it defaults to
|
|
1742
1938
|
* {@link import('./constants.js').DEFAULT_CONVERSATION_KEEP} (`0` — a manual `compact()`
|
|
1743
1939
|
* folds the WHOLE current live tail into one section). `sections` is an optional cap on the
|
|
1744
1940
|
* compacted `sections` list — when set (`>= 1`), a `compact()` that would leave more than
|
|
1745
1941
|
* `sections` sections FOLDS the oldest overflow into ONE merged section so the list never
|
|
1746
1942
|
* exceeds `sections`, emitting `collapse`; omitted ⇒ unlimited (the prior behavior).
|
|
1943
|
+
* `snapshot` is the HYDRATION seam — a {@link ConversationSnapshot} whose `id`, rollup
|
|
1944
|
+
* `summary`, compacted `sections`, and live tail are RESTORED into the new conversation, with
|
|
1945
|
+
* the live `summarize` / `keep` / `on` supplied alongside it (a summarizer is a function, not
|
|
1946
|
+
* serialized data). Restoring is SILENT (no events — nothing was edited), and a `snapshot.id`
|
|
1947
|
+
* WINS over `id` (the snapshot IS the conversation's identity). It is what lets
|
|
1948
|
+
* `createConversation` hydrate, and what a {@link ConversationManagerInterface.open} reads a
|
|
1949
|
+
* stored snapshot back through.
|
|
1747
1950
|
*/
|
|
1748
1951
|
export declare interface ConversationOptions {
|
|
1749
1952
|
readonly id?: string;
|
|
1750
1953
|
readonly on?: EmitterHooks<ConversationEventMap>;
|
|
1751
|
-
/**
|
|
1954
|
+
/** Holds the emitter's listener-error handler — a listener throw routes here, not to a domain event. */
|
|
1752
1955
|
readonly error?: EmitterErrorHandler;
|
|
1753
|
-
/**
|
|
1754
|
-
readonly summarize?:
|
|
1755
|
-
/**
|
|
1956
|
+
/** Supplies the summarizer compaction needs; ABSENT ⇒ `compact()` throws a `ConversationError`. */
|
|
1957
|
+
readonly summarize?: ConversationSummaryHandler;
|
|
1958
|
+
/** Keeps this many recent live messages verbatim on `compact`; defaults to `DEFAULT_CONVERSATION_KEEP` (`0`). */
|
|
1756
1959
|
readonly keep?: number;
|
|
1757
|
-
/**
|
|
1960
|
+
/** Caps the compacted `sections` list (`>= 1`); overflow folds into one merged section. Omitted ⇒ unlimited. */
|
|
1758
1961
|
readonly sections?: number;
|
|
1962
|
+
/** Hydrates from a {@link ConversationSnapshot} — its `id` wins over `id`; restoring is silent. */
|
|
1963
|
+
readonly snapshot?: ConversationSnapshot;
|
|
1759
1964
|
}
|
|
1760
1965
|
|
|
1761
1966
|
/**
|
|
1762
|
-
*
|
|
1967
|
+
* Configures {@link ConversationInterface.reference} — how to render ONE conversation as a
|
|
1763
1968
|
* self-labeled, fenced PROVENANCE block to pull INTO another conversation (by writing it to
|
|
1764
1969
|
* the active context's active workspace).
|
|
1765
1970
|
*
|
|
@@ -1767,56 +1972,56 @@ export declare interface ConversationOptions {
|
|
|
1767
1972
|
* The rendered block is a cross-conversation reference a SMALL model must read as foreign
|
|
1768
1973
|
* material, NOT as part of the live thread — so every member keeps it CONCISE and unmistakably
|
|
1769
1974
|
* attributed:
|
|
1770
|
-
* - `label` — the human PROVENANCE name shown in the block's leading marker (
|
|
1975
|
+
* - `label` — the human PROVENANCE name shown in the block's leading marker (for example `'planning'`);
|
|
1771
1976
|
* defaults to the conversation's own `id`. It is what the model attributes the content to.
|
|
1772
1977
|
* - `summary` — whether to include the conversation's rollup `summary` (its summary-of-summaries)
|
|
1773
1978
|
* in the block; defaults to `true` (the rollup is included WHEN one exists — `undefined` until
|
|
1774
|
-
* the first compaction
|
|
1979
|
+
* the first compaction omits the `Summary:` line). Pass `false` to exclude it.
|
|
1775
1980
|
* - `messages` — the CHERRY-PICKED excerpts to include (each rendered `role: content`), default
|
|
1776
1981
|
* NONE. The intended source is the conversation's OWN `search(query)` / `rehydrate(id)` output
|
|
1777
1982
|
* (select the few relevant turns), NOT its whole history — dumping every message defeats the
|
|
1778
1983
|
* point (it re-bloats the destination context a small model then has to wade through).
|
|
1779
1984
|
*/
|
|
1780
1985
|
export declare interface ConversationReferenceOptions {
|
|
1781
|
-
/**
|
|
1986
|
+
/** Names the human provenance label in the block's marker; defaults to the conversation's `id`. */
|
|
1782
1987
|
readonly label?: string;
|
|
1783
|
-
/**
|
|
1988
|
+
/** Includes the conversation's rollup `summary` (when one exists); defaults to `true`. */
|
|
1784
1989
|
readonly summary?: boolean;
|
|
1785
|
-
/**
|
|
1786
|
-
readonly messages?: readonly
|
|
1990
|
+
/** Lists the cherry-picked excerpts to include (`role: content`); defaults to none. */
|
|
1991
|
+
readonly messages?: readonly Message[];
|
|
1787
1992
|
}
|
|
1788
1993
|
|
|
1789
1994
|
/**
|
|
1790
|
-
*
|
|
1995
|
+
* Holds a JSON-serializable snapshot of a conversation's state — its `id`, the rollup `summary`, the
|
|
1791
1996
|
* compacted `sections`, and the live tail `messages` — the durable payload the
|
|
1792
1997
|
* {@link ConversationStoreInterface} persists. The exact analogue of
|
|
1793
1998
|
* {@link import('@orkestrel/workspace').WorkspaceSnapshot}.
|
|
1794
1999
|
*
|
|
1795
2000
|
* @remarks
|
|
1796
|
-
* Pure JSON DATA (no class instances, no functions): each {@link
|
|
1797
|
-
* {@link
|
|
2001
|
+
* Pure JSON DATA (no class instances, no functions): each {@link Section} and
|
|
2002
|
+
* {@link Message} is already a PLAIN record that `structuredClone`s / JSON-round-trips
|
|
1798
2003
|
* losslessly. The snapshot carries the rollup `summary` (a summary-of-summaries; `undefined` until
|
|
1799
2004
|
* the first compaction), the compacted `sections` (each RETAINING its folded originals), and the
|
|
1800
2005
|
* live uncompacted tail `messages` — but NOT the `summarize` / `keep`, which are live CONFIG
|
|
1801
2006
|
* re-supplied on hydrate (a summarizer is a function, not serializable data). The snapshot the
|
|
1802
2007
|
* container produces from itself ({@link ConversationInterface.snapshot}); the durable analogue of
|
|
1803
|
-
* the
|
|
1804
|
-
* through
|
|
1805
|
-
* untrusted storage read by {@link import('./
|
|
1806
|
-
* boundary
|
|
2008
|
+
* the {@link ConversationOptions.snapshot} hydration seam. A {@link ConversationManagerInterface}
|
|
2009
|
+
* hydrates a conversation from it through that seam (see {@link ConversationManagerInterface.open}). It is narrowed back from an
|
|
2010
|
+
* untrusted storage read by {@link import('./validators.js').isConversationSnapshot} (the total
|
|
2011
|
+
* boundary guard).
|
|
1807
2012
|
*/
|
|
1808
2013
|
export declare interface ConversationSnapshot {
|
|
1809
2014
|
readonly id: string;
|
|
1810
|
-
/**
|
|
2015
|
+
/** Holds the rollup (a summary-of-summaries); `undefined` until the first compaction. */
|
|
1811
2016
|
readonly summary?: string;
|
|
1812
|
-
/**
|
|
1813
|
-
readonly sections: readonly
|
|
1814
|
-
/**
|
|
1815
|
-
readonly messages: readonly
|
|
2017
|
+
/** Lists the compacted history, oldest → newest (each section RETAINS its folded originals). */
|
|
2018
|
+
readonly sections: readonly Section[];
|
|
2019
|
+
/** Lists the live uncompacted tail, in insertion order. */
|
|
2020
|
+
readonly messages: readonly Message[];
|
|
1816
2021
|
}
|
|
1817
2022
|
|
|
1818
2023
|
/**
|
|
1819
|
-
*
|
|
2024
|
+
* Represents one row of the table a
|
|
1820
2025
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
1821
2026
|
* persists — a conversation `id` plus its {@link ConversationSnapshot} held as ONE OPAQUE JSON
|
|
1822
2027
|
* column. The exact analogue of {@link import('@orkestrel/workspace').WorkspaceSnapshotRow}.
|
|
@@ -1828,18 +2033,18 @@ export declare interface ConversationSnapshot {
|
|
|
1828
2033
|
* row type stays FLAT and the sections/messages snapshot shape never
|
|
1829
2034
|
* forces the contract to `Infer` it. The column therefore reads back as the broad `unknown`; the
|
|
1830
2035
|
* store narrows it to a {@link ConversationSnapshot} on `get`
|
|
1831
|
-
* ({@link import('./
|
|
2036
|
+
* ({@link import('./validators.js').isConversationSnapshot}, the total boundary guard). `id`
|
|
1832
2037
|
* mirrors {@link ConversationSnapshot.id} (the primary key), so a `set` writes
|
|
1833
2038
|
* `{ id: snapshot.id, snapshot }`.
|
|
1834
2039
|
*/
|
|
1835
2040
|
export declare interface ConversationSnapshotRow {
|
|
1836
2041
|
readonly id: string;
|
|
1837
|
-
/**
|
|
2042
|
+
/** Holds the whole {@link ConversationSnapshot} as one opaque JSON blob — read back as `unknown`, narrowed on `get`. */
|
|
1838
2043
|
readonly snapshot: unknown;
|
|
1839
2044
|
}
|
|
1840
2045
|
|
|
1841
2046
|
/**
|
|
1842
|
-
*
|
|
2047
|
+
* Persists a {@link ConversationSnapshot} durably — three async primitives
|
|
1843
2048
|
* (`get` / `set` / `delete`) keyed by a conversation id, the exact analogue of
|
|
1844
2049
|
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}.
|
|
1845
2050
|
*
|
|
@@ -1852,7 +2057,7 @@ export declare interface ConversationSnapshotRow {
|
|
|
1852
2057
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore} (the
|
|
1853
2058
|
* snapshot as one opaque JSON column) share THIS one interface. Hydration is NOT a store concern
|
|
1854
2059
|
* — a {@link ConversationManagerInterface} reads a snapshot back and rebuilds the live conversation
|
|
1855
|
-
* through the
|
|
2060
|
+
* through the {@link ConversationOptions.snapshot} seam (re-supplying the live `summarize` / `keep`; see
|
|
1856
2061
|
* {@link ConversationManagerInterface.open} / {@link ConversationManagerInterface.save}).
|
|
1857
2062
|
*
|
|
1858
2063
|
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
@@ -1861,26 +2066,26 @@ export declare interface ConversationSnapshotRow {
|
|
|
1861
2066
|
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`). UNLIKE a session store
|
|
1862
2067
|
* there is NO idle-TTL
|
|
1863
2068
|
* / eviction — a persisted conversation lives until an explicit `delete`. It is concrete over
|
|
1864
|
-
* {@link ConversationSnapshot} — no generic parameter
|
|
2069
|
+
* {@link ConversationSnapshot} — no generic parameter, because the
|
|
1865
2070
|
* snapshot is the ONE payload a conversation store persists.
|
|
1866
2071
|
*/
|
|
1867
2072
|
export declare interface ConversationStoreInterface {
|
|
1868
2073
|
/**
|
|
1869
|
-
*
|
|
2074
|
+
* Resolves the persisted snapshot for `id`, or `undefined` if none is stored.
|
|
1870
2075
|
*
|
|
1871
2076
|
* @param id - The conversation id to resolve (a {@link ConversationSnapshot.id})
|
|
1872
2077
|
* @returns The persisted snapshot, or `undefined` if absent
|
|
1873
2078
|
*/
|
|
1874
2079
|
get(id: string): Promise<ConversationSnapshot | undefined>;
|
|
1875
2080
|
/**
|
|
1876
|
-
*
|
|
2081
|
+
* Inserts or replaces a snapshot under its own `snapshot.id` (no separate id param —
|
|
1877
2082
|
* mirroring {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`).
|
|
1878
2083
|
*
|
|
1879
2084
|
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
1880
2085
|
*/
|
|
1881
2086
|
set(snapshot: ConversationSnapshot): Promise<void>;
|
|
1882
2087
|
/**
|
|
1883
|
-
*
|
|
2088
|
+
* Drops a snapshot by id; an absent id is a no-op (no throw).
|
|
1884
2089
|
*
|
|
1885
2090
|
* @param id - The conversation id to drop
|
|
1886
2091
|
*/
|
|
@@ -1888,25 +2093,25 @@ export declare interface ConversationStoreInterface {
|
|
|
1888
2093
|
}
|
|
1889
2094
|
|
|
1890
2095
|
/**
|
|
1891
|
-
*
|
|
2096
|
+
* Summarizes a conversation, provider-agnostically — the seam the agent RUNTIME supplies so
|
|
1892
2097
|
* core never imports a provider. Given the folded messages, it resolves their digest (the
|
|
1893
|
-
* model-written summary), used both to summarize a compacted {@link
|
|
2098
|
+
* model-written summary), used both to summarize a compacted {@link Section} and
|
|
1894
2099
|
* to regenerate a {@link ConversationInterface}'s rollup `summary`.
|
|
1895
2100
|
*
|
|
1896
2101
|
* @remarks
|
|
1897
|
-
* The agent runtime builds one from its `ProviderInterface` (
|
|
2102
|
+
* The agent runtime builds one from its `ProviderInterface` (for example
|
|
1898
2103
|
* `async (messages) => (await provider.generate([systemPrompt, ...messages], signal)).content`)
|
|
1899
2104
|
* and hands it to a {@link ConversationInterface} / {@link ConversationManagerInterface}.
|
|
1900
|
-
* The core conversation layer treats it as an opaque async function — it
|
|
1901
|
-
*
|
|
2105
|
+
* The core conversation layer treats it as an opaque async function — it never reads which
|
|
2106
|
+
* backend produced the digest, keeping `core` free of any provider coupling.
|
|
1902
2107
|
*
|
|
1903
2108
|
* @param messages - The folded messages to digest into a summary
|
|
1904
2109
|
* @returns The summary text (the model-written digest of those messages)
|
|
1905
2110
|
*/
|
|
1906
|
-
export declare type
|
|
2111
|
+
export declare type ConversationSummaryHandler = (messages: readonly Message[]) => Promise<string>;
|
|
1907
2112
|
|
|
1908
2113
|
/**
|
|
1909
|
-
*
|
|
2114
|
+
* Creates an agent loop — an {@link AgentInterface} composing a
|
|
1910
2115
|
* {@link ProviderInterface}, its {@link AgentContextInterface}, and a tool registry
|
|
1911
2116
|
* into a bounded context → provider → tools → repeat turn, exposed as a one-shot
|
|
1912
2117
|
* `generate` and a live `stream`.
|
|
@@ -1914,11 +2119,11 @@ export declare type ConversationSummarizer = (messages: readonly MessageInterfac
|
|
|
1914
2119
|
* @remarks
|
|
1915
2120
|
* One private loop drives the turn; `generate` DRAINS the same stream `stream`
|
|
1916
2121
|
* exposes, so they can never diverge. Each turn is bounded by one cancel folded from
|
|
1917
|
-
* `signal` + `timeout` + `budget` (
|
|
2122
|
+
* `signal` + `timeout` + `budget` (through `AbortSignal.any`) — any trip (or `abort()`)
|
|
1918
2123
|
* commits a PARTIAL result (the stream's `result` RESOLVES on a cancel, rejects only
|
|
1919
2124
|
* on a genuine provider / tool error). The `scheduler` paces between turns; tool
|
|
1920
2125
|
* iteration is capped at `limit` (default `DEFAULT_AGENT_LIMIT`). Tools are advertised
|
|
1921
|
-
* structurally
|
|
2126
|
+
* structurally through `context.tools.definitions()`. Two observation surfaces: the
|
|
1922
2127
|
* {@link AgentChunk} stream (pull — per-token content) and a typed `emitter` (push —
|
|
1923
2128
|
* lifecycle + `usage` / `tool` / `deny` for fire-and-forget observers).
|
|
1924
2129
|
*
|
|
@@ -1929,8 +2134,9 @@ export declare type ConversationSummarizer = (messages: readonly MessageInterfac
|
|
|
1929
2134
|
*
|
|
1930
2135
|
* @example
|
|
1931
2136
|
* ```ts
|
|
1932
|
-
* import type { ProviderInterface } from '@
|
|
1933
|
-
* import { createAgent
|
|
2137
|
+
* import type { ProviderInterface } from '@orkestrel/agent'
|
|
2138
|
+
* import { createAgent } from '@orkestrel/agent'
|
|
2139
|
+
* import { createTokenBudget } from '@orkestrel/budget'
|
|
1934
2140
|
*
|
|
1935
2141
|
* declare const provider: ProviderInterface // any concrete implementation supplied by the host app
|
|
1936
2142
|
* const agent = createAgent(provider, {
|
|
@@ -1941,7 +2147,7 @@ export declare type ConversationSummarizer = (messages: readonly MessageInterfac
|
|
|
1941
2147
|
*
|
|
1942
2148
|
* const stream = agent.stream()
|
|
1943
2149
|
* for await (const chunk of stream.events) {
|
|
1944
|
-
* if (chunk.
|
|
2150
|
+
* if (chunk.category === 'token') process.stdout.write(chunk.content)
|
|
1945
2151
|
* }
|
|
1946
2152
|
* const result = await stream.result // { content, usage?, partial }
|
|
1947
2153
|
* ```
|
|
@@ -1949,7 +2155,7 @@ export declare type ConversationSummarizer = (messages: readonly MessageInterfac
|
|
|
1949
2155
|
export declare function createAgent(provider: ProviderInterface, options?: AgentOptions): AgentInterface;
|
|
1950
2156
|
|
|
1951
2157
|
/**
|
|
1952
|
-
*
|
|
2158
|
+
* Creates a richer turn context — an {@link AgentContextInterface} assembling a provider
|
|
1953
2159
|
* request from the optional system prompt, the instruction registry, the workspace registry,
|
|
1954
2160
|
* the conversation store, the tool registry, and the active scope.
|
|
1955
2161
|
*
|
|
@@ -1957,11 +2163,11 @@ export declare function createAgent(provider: ProviderInterface, options?: Agent
|
|
|
1957
2163
|
* `system` is the optional system prompt; `tools` / `instructions` / `workspaces` are pre-built
|
|
1958
2164
|
* managers to reuse (empty ones are created when omitted, so `context.workspaces` is ALWAYS
|
|
1959
2165
|
* present); `scope` is the initial active filter (`undefined` ⇒ no filtering, changeable afterwards
|
|
1960
|
-
*
|
|
2166
|
+
* through `context.apply(...)`). The `messages` store is always fresh. `build()` folds the scoped
|
|
1961
2167
|
* instructions — PLUS the ACTIVE workspace's scope-filtered text files (fenced) — into ONE leading
|
|
1962
2168
|
* `system` message and appends the scoped conversation (attaching the active workspace's
|
|
1963
|
-
* scope-filtered image files' `
|
|
1964
|
-
* workspace is the SOLE document/image context. Tools are advertised STRUCTURALLY (
|
|
2169
|
+
* scope-filtered image files' `base64` payload to the last user message), built fresh each call; the active
|
|
2170
|
+
* workspace is the SOLE document/image context. Tools are advertised STRUCTURALLY (through
|
|
1965
2171
|
* `tools.definitions()`, scope-filtered by the loop), never serialized into the prompt.
|
|
1966
2172
|
*
|
|
1967
2173
|
* @param options - Optional `system` / `tools` / `instructions` / `workspaces` / `scope`
|
|
@@ -1970,7 +2176,7 @@ export declare function createAgent(provider: ProviderInterface, options?: Agent
|
|
|
1970
2176
|
*
|
|
1971
2177
|
* @example
|
|
1972
2178
|
* ```ts
|
|
1973
|
-
* import { createAgentContext } from '@
|
|
2179
|
+
* import { createAgentContext } from '@orkestrel/agent'
|
|
1974
2180
|
*
|
|
1975
2181
|
* const context = createAgentContext({ system: 'You are concise.' })
|
|
1976
2182
|
* context.instructions.add({ name: 'tone', content: 'Be terse.' })
|
|
@@ -1981,7 +2187,7 @@ export declare function createAgent(provider: ProviderInterface, options?: Agent
|
|
|
1981
2187
|
export declare function createAgentContext(options?: AgentContextOptions): AgentContextInterface;
|
|
1982
2188
|
|
|
1983
2189
|
/**
|
|
1984
|
-
*
|
|
2190
|
+
* Creates a durable, bounded-concurrency agent-job queue — a {@link QueueInterface} over
|
|
1985
2191
|
* serializable {@link AgentJobInput}s that COMPOSES `createQueue`: each job is rehydrated
|
|
1986
2192
|
* through the `registry` into a live {@link AgentInterface}, run to its {@link AgentResult},
|
|
1987
2193
|
* and subjected to the partial-as-configurable-failure policy.
|
|
@@ -1989,30 +2195,31 @@ export declare function createAgentContext(options?: AgentContextOptions): Agent
|
|
|
1989
2195
|
* @remarks
|
|
1990
2196
|
* - **Composes the substrate (no new engine).** The handler is the only new logic;
|
|
1991
2197
|
* bounded `concurrency`, `retries`, the per-attempt `timeout`, and durable persistence
|
|
1992
|
-
*
|
|
2198
|
+
* through `store` (+ `restore()` after a crash) are all the backing Queue's. `enqueue`
|
|
1993
2199
|
* returns a per-job promise.
|
|
1994
2200
|
* - **Durable + serializable.** Because `AgentJobInput` is JSON-serializable, a `store`
|
|
1995
|
-
* (
|
|
2201
|
+
* (for example `createMemoryQueueStore` / `createDatabaseQueueStore`) persists outstanding
|
|
1996
2202
|
* jobs; `restore()` re-enqueues them after a restart and the `registry` rehydrates the
|
|
1997
2203
|
* live pieces from the names — so a job survives a crash.
|
|
1998
2204
|
* - **Partial policy.** A partial result THROWS an
|
|
1999
2205
|
* {@link import('./errors.js').AgentJobError} by default, so a job cancelled by its
|
|
2000
|
-
* attempt deadline / a queue abort RETRIES while attempts remain; `
|
|
2206
|
+
* attempt deadline / a queue abort RETRIES while attempts remain; `partial: true`
|
|
2001
2207
|
* resolves the partial as success instead.
|
|
2002
|
-
* - **Cancellation threads through.** The handler passes `
|
|
2208
|
+
* - **Cancellation threads through.** The handler passes `context.signal` into
|
|
2003
2209
|
* `registry.build`, so a queue `abort()` or a per-attempt timeout cancels the in-flight
|
|
2004
2210
|
* agent (which commits a partial → throws → retries / fails per policy).
|
|
2005
2211
|
*
|
|
2006
|
-
* @param options - The `registry`, the `
|
|
2212
|
+
* @param options - The `registry`, the `partial` policy, and the substrate knobs
|
|
2007
2213
|
* (`concurrency` / `retries` / `timeout` / `store`) (see {@link AgentQueueOptions})
|
|
2008
2214
|
* @returns A {@link QueueInterface} of {@link AgentJobInput} → {@link AgentResult}
|
|
2009
2215
|
*
|
|
2010
2216
|
* @example
|
|
2011
2217
|
* ```ts
|
|
2012
|
-
* import { createAgentQueue, createAgentRegistry
|
|
2218
|
+
* import { createAgentQueue, createAgentRegistry } from '@orkestrel/agent'
|
|
2219
|
+
* import { createMemoryQueueStore } from '@orkestrel/queue'
|
|
2013
2220
|
*
|
|
2014
2221
|
* const registry = createAgentRegistry({ providers: { main: provider } })
|
|
2015
|
-
* const store = createMemoryQueueStore(agentJobShape) // survives a restart
|
|
2222
|
+
* const store = createMemoryQueueStore(agentJobShape) // survives a restart through restore()
|
|
2016
2223
|
* const queue = createAgentQueue({ registry, concurrency: 2, retries: 1, store })
|
|
2017
2224
|
* const result = await queue.enqueue({ provider: 'main', messages: [{ role: 'user', content: 'ok?' }] })
|
|
2018
2225
|
* ```
|
|
@@ -2020,16 +2227,17 @@ export declare function createAgentContext(options?: AgentContextOptions): Agent
|
|
|
2020
2227
|
export declare function createAgentQueue(options: AgentQueueOptions): QueueInterface<AgentJobInput, AgentResult>;
|
|
2021
2228
|
|
|
2022
2229
|
/**
|
|
2023
|
-
*
|
|
2230
|
+
* Creates an agent registry — an {@link AgentRegistryInterface} holding the named pools of
|
|
2024
2231
|
* live, non-serializable pieces (providers, tools, authorities, schedulers) that a
|
|
2025
2232
|
* serializable {@link AgentJobInput}'s names resolve against, and `build`ing a seeded,
|
|
2026
2233
|
* signal-wired {@link AgentInterface} from a job.
|
|
2027
2234
|
*
|
|
2028
2235
|
* @remarks
|
|
2029
2236
|
* `providers` is required; `tools` / `authorities` / `schedulers` are optional pools.
|
|
2030
|
-
* The accessors (`provider` / `tool` / `authority` / `scheduler`) THROW
|
|
2031
|
-
*
|
|
2032
|
-
*
|
|
2237
|
+
* The accessors (`provider` / `tool` / `authority` / `scheduler`) THROW an
|
|
2238
|
+
* {@link import('./errors.js').AgentError} carrying `code: 'REGISTRY'` and the message
|
|
2239
|
+
* `unknown <category>: <name>` on an unregistered name — a misconfigured or crash-restored
|
|
2240
|
+
* job fails loudly rather than running with a missing dependency. `build(input, signal)`
|
|
2033
2241
|
* resolves the names, rebuilds the token budget from its ceiling, seeds the agent's
|
|
2034
2242
|
* context with the job's messages, and threads `signal` so a queue / runner abort
|
|
2035
2243
|
* propagates. This is the bridge that makes durable, serializable agent jobs runnable.
|
|
@@ -2039,8 +2247,8 @@ export declare function createAgentQueue(options: AgentQueueOptions): QueueInter
|
|
|
2039
2247
|
*
|
|
2040
2248
|
* @example
|
|
2041
2249
|
* ```ts
|
|
2042
|
-
* import { createAgentRegistry } from '@
|
|
2043
|
-
* import type { ProviderInterface } from '@
|
|
2250
|
+
* import { createAgentRegistry } from '@orkestrel/agent'
|
|
2251
|
+
* import type { ProviderInterface } from '@orkestrel/agent'
|
|
2044
2252
|
* import { createTool } from '@orkestrel/tool'
|
|
2045
2253
|
*
|
|
2046
2254
|
* declare const provider: ProviderInterface // any concrete implementation supplied by the host app
|
|
@@ -2054,7 +2262,7 @@ export declare function createAgentQueue(options: AgentQueueOptions): QueueInter
|
|
|
2054
2262
|
export declare function createAgentRegistry(options: AgentRegistryOptions): AgentRegistryInterface;
|
|
2055
2263
|
|
|
2056
2264
|
/**
|
|
2057
|
-
*
|
|
2265
|
+
* Creates an agent-job runner — a {@link RunnerInterface} over serializable
|
|
2058
2266
|
* {@link AgentJobInput}s that COMPOSES `createRunner` (one-shot, ordered, fail-fast), each
|
|
2059
2267
|
* unit rehydrated through the `registry` and subjected to the partial policy. The runner
|
|
2060
2268
|
* enables **sub-agent fan-out**: a parent job's handler can `controller.spawn(childJob)`.
|
|
@@ -2069,17 +2277,17 @@ export declare function createAgentRegistry(options: AgentRegistryOptions): Agen
|
|
|
2069
2277
|
* runner, FAN OUT and return — do NOT inline-`await` a spawn from within the handler (a
|
|
2070
2278
|
* slot-holding handler awaiting its own spawn can deadlock; see `ControllerInterface`).
|
|
2071
2279
|
* - **Partial policy + cancellation.** Same as `createAgentQueue`: a partial result
|
|
2072
|
-
* THROWS by default (the run's fail-fast engages), `
|
|
2280
|
+
* THROWS by default (the run's fail-fast engages), `partial: true` resolves it; the
|
|
2073
2281
|
* handler threads `controller.signal` into `registry.build`, so a runner abort / a
|
|
2074
2282
|
* per-attempt timeout cancels the agent.
|
|
2075
2283
|
*
|
|
2076
|
-
* @param options - The `registry`, the `
|
|
2284
|
+
* @param options - The `registry`, the `partial` policy, and the substrate knobs
|
|
2077
2285
|
* (`concurrency` / `retries` / `timeout`) (see {@link AgentRunnerOptions})
|
|
2078
2286
|
* @returns A {@link RunnerInterface} of {@link AgentJobInput} → {@link AgentResult}
|
|
2079
2287
|
*
|
|
2080
2288
|
* @example
|
|
2081
2289
|
* ```ts
|
|
2082
|
-
* import { createAgentRunner, createAgentRegistry } from '@
|
|
2290
|
+
* import { createAgentRunner, createAgentRegistry } from '@orkestrel/agent'
|
|
2083
2291
|
*
|
|
2084
2292
|
* const registry = createAgentRegistry({ providers: { main: provider } })
|
|
2085
2293
|
* const runner = createAgentRunner({ registry, concurrency: 2 })
|
|
@@ -2092,7 +2300,7 @@ export declare function createAgentRegistry(options: AgentRegistryOptions): Agen
|
|
|
2092
2300
|
export declare function createAgentRunner(options: AgentRunnerOptions): RunnerInterface<AgentJobInput, AgentResult>;
|
|
2093
2301
|
|
|
2094
2302
|
/**
|
|
2095
|
-
*
|
|
2303
|
+
* Creates a policy gate — an {@link AuthorityInterface} the agent loop consults before
|
|
2096
2304
|
* each tool call runs, evaluating the ordered rules first-match-wins and falling back
|
|
2097
2305
|
* to the configured default when none match.
|
|
2098
2306
|
*
|
|
@@ -2102,16 +2310,16 @@ export declare function createAgentRunner(options: AgentRunnerOptions): RunnerIn
|
|
|
2102
2310
|
* `fallback` decides; it defaults to `{ zone: DEFAULT_AUTHORITY_ZONE, allowed: true }`
|
|
2103
2311
|
* (allow-unmatched — a rules list of denials acts as a DENYLIST). Pass an
|
|
2104
2312
|
* `allowed: false` `fallback` to flip the gate to deny-by-default (an ALLOWLIST). Wire
|
|
2105
|
-
* the result into `createAgent`
|
|
2313
|
+
* the result into `createAgent` through `AgentOptions.authority`: a denied call is fed back
|
|
2106
2314
|
* to the model as a denial `ToolResult` (not executed, no budget cost), so the model
|
|
2107
|
-
* can react. Synchronous
|
|
2315
|
+
* can react. Synchronous — `evaluate` returns the verdict directly.
|
|
2108
2316
|
*
|
|
2109
2317
|
* @param options - Optional `rules` (ordered) and `fallback` (see {@link AuthorityOptions})
|
|
2110
2318
|
* @returns A working {@link AuthorityInterface}
|
|
2111
2319
|
*
|
|
2112
2320
|
* @example
|
|
2113
2321
|
* ```ts
|
|
2114
|
-
* import { createAgent, createAuthority } from '@
|
|
2322
|
+
* import { createAgent, createAuthority } from '@orkestrel/agent'
|
|
2115
2323
|
*
|
|
2116
2324
|
* // Deny the `delete` tool, allow everything else.
|
|
2117
2325
|
* const authority = createAuthority({
|
|
@@ -2123,28 +2331,56 @@ export declare function createAgentRunner(options: AgentRunnerOptions): RunnerIn
|
|
|
2123
2331
|
export declare function createAuthority(options?: AuthorityOptions): AuthorityInterface;
|
|
2124
2332
|
|
|
2125
2333
|
/**
|
|
2126
|
-
*
|
|
2334
|
+
* Creates an empty unbounded async channel — a {@link ChannelInterface} a producer writes
|
|
2335
|
+
* values into (`push`) and ends (`close` / `fail`) regardless of consumption, while a
|
|
2336
|
+
* consumer reads them back live through `drain`.
|
|
2337
|
+
*
|
|
2338
|
+
* @remarks
|
|
2339
|
+
* Write and read are decoupled, so the producer never waits for a consumer: an agent's eager
|
|
2340
|
+
* pump writes each chunk into one, which is why a run's `result` settles whether or not the
|
|
2341
|
+
* live events are drained. A value pushed at an already-parked consumer is delivered, buffered
|
|
2342
|
+
* values are yielded before the end is reported, and the FIRST failure wins.
|
|
2343
|
+
*
|
|
2344
|
+
* @typeParam T - The value type the channel carries
|
|
2345
|
+
* @returns A fresh, empty {@link ChannelInterface}
|
|
2346
|
+
*
|
|
2347
|
+
* @example
|
|
2348
|
+
* ```ts
|
|
2349
|
+
* import { createChannel } from '@orkestrel/agent'
|
|
2350
|
+
*
|
|
2351
|
+
* const channel = createChannel<number>()
|
|
2352
|
+
* channel.push(1)
|
|
2353
|
+
* channel.close()
|
|
2354
|
+
* for await (const value of channel.drain()) {
|
|
2355
|
+
* value // 1
|
|
2356
|
+
* }
|
|
2357
|
+
* ```
|
|
2358
|
+
*/
|
|
2359
|
+
export declare function createChannel<T>(): ChannelInterface<T>;
|
|
2360
|
+
|
|
2361
|
+
/**
|
|
2362
|
+
* Creates a conversation — a {@link ConversationInterface} grouping messages above a flat
|
|
2127
2363
|
* message store it OWNS DIRECTLY, with compaction into summarized sections, a regenerated
|
|
2128
2364
|
* rollup `summary`, on-demand `rehydrate`, and substring `search`, driven by a
|
|
2129
|
-
* provider-agnostic {@link
|
|
2365
|
+
* provider-agnostic {@link ConversationSummaryHandler} seam.
|
|
2130
2366
|
*
|
|
2131
2367
|
* @remarks
|
|
2132
2368
|
* Append turns through the conversation's own `add` (the live tail it owns); `view()` is the model input
|
|
2133
2369
|
* (each section as a summary message, then the live tail). `compact()` folds the older live
|
|
2134
|
-
* messages into a summarized {@link
|
|
2370
|
+
* messages into a summarized {@link Section} and regenerates the rollup — it REQUIRES
|
|
2135
2371
|
* a `summarize` (omitted ⇒ `compact()` throws a `ConversationError`); `keep` retains a recent
|
|
2136
2372
|
* tail (default `DEFAULT_CONVERSATION_KEEP` — fold ALL). `rehydrate(id)` / `search(query)` read
|
|
2137
2373
|
* the retained originals. Observable (`emitter` — `compact` / `summary` / `rehydrate`), wired
|
|
2138
|
-
*
|
|
2139
|
-
* its `error` handler (the `error` option
|
|
2374
|
+
* through the reserved `on` option; the emitter isolates a listener throw and routes it to
|
|
2375
|
+
* its `error` handler (the `error` option), so it can never corrupt a compaction.
|
|
2140
2376
|
*
|
|
2141
2377
|
* @param options - Optional `id` / `on` hooks + the `summarize` seam + `keep` (see {@link ConversationOptions})
|
|
2142
2378
|
* @returns A working {@link ConversationInterface}
|
|
2143
2379
|
*
|
|
2144
2380
|
* @example
|
|
2145
2381
|
* ```ts
|
|
2146
|
-
* import type { ProviderInterface } from '@
|
|
2147
|
-
* import { createConversation } from '@
|
|
2382
|
+
* import type { ProviderInterface } from '@orkestrel/agent'
|
|
2383
|
+
* import { createConversation } from '@orkestrel/agent'
|
|
2148
2384
|
*
|
|
2149
2385
|
* declare const provider: ProviderInterface // any concrete implementation supplied by the host app
|
|
2150
2386
|
* const conversation = createConversation({
|
|
@@ -2160,9 +2396,10 @@ export declare function createAuthority(options?: AuthorityOptions): AuthorityIn
|
|
|
2160
2396
|
export declare function createConversation(options?: ConversationOptions): ConversationInterface;
|
|
2161
2397
|
|
|
2162
2398
|
/**
|
|
2163
|
-
*
|
|
2399
|
+
* Creates a conversation registry — a {@link ConversationManagerInterface} holding
|
|
2164
2400
|
* {@link ConversationInterface}s keyed by their `id` (in insertion order) WITH an active pointer:
|
|
2165
|
-
* the
|
|
2401
|
+
* the id-keyed store over the conversation layer plus the `active` / `switch` seam the context
|
|
2402
|
+
* renders.
|
|
2166
2403
|
*
|
|
2167
2404
|
* @remarks
|
|
2168
2405
|
* Starts empty; `add(input?)` mints a {@link ConversationInterface} (its `id` from the input
|
|
@@ -2171,8 +2408,9 @@ export declare function createConversation(options?: ConversationOptions): Conve
|
|
|
2171
2408
|
* AUTO-ACTIVATES the FIRST one (a registry with conversations always has one `active`); a later
|
|
2172
2409
|
* `add` leaves `active` unchanged. `switch(id)` re-points `active` (an unknown `id` returns
|
|
2173
2410
|
* `undefined`, leaving `active` unchanged — lenient, never throws); `conversation(id)` /
|
|
2174
|
-
* `conversations()` look up; `remove` (one or a batch
|
|
2175
|
-
* clears `active` if it was
|
|
2411
|
+
* `conversations()` look up; `remove` (one or a batch) reports `true` only when every supplied id
|
|
2412
|
+
* was removed AND clears `active` if it was a removed one; `clear` empties it and clears `active`.
|
|
2413
|
+
* Event-free
|
|
2176
2414
|
* (each conversation owns its own observable `emitter`). A conversation created with NEITHER a
|
|
2177
2415
|
* manager default nor a per-`add` `summarize` cannot `compact` (it throws a `ConversationError`).
|
|
2178
2416
|
*
|
|
@@ -2181,7 +2419,7 @@ export declare function createConversation(options?: ConversationOptions): Conve
|
|
|
2181
2419
|
*
|
|
2182
2420
|
* @example
|
|
2183
2421
|
* ```ts
|
|
2184
|
-
* import { createConversationManager } from '@
|
|
2422
|
+
* import { createConversationManager } from '@orkestrel/agent'
|
|
2185
2423
|
*
|
|
2186
2424
|
* const conversations = createConversationManager({ summarize: async (m) => `recap of ${m.length}` })
|
|
2187
2425
|
* const chat = conversations.add() // auto-activates — conversations.active === chat
|
|
@@ -2191,7 +2429,7 @@ export declare function createConversation(options?: ConversationOptions): Conve
|
|
|
2191
2429
|
export declare function createConversationManager(options?: ConversationManagerOptions): ConversationManagerInterface;
|
|
2192
2430
|
|
|
2193
2431
|
/**
|
|
2194
|
-
*
|
|
2432
|
+
* Creates a {@link DatabaseConversationStore} over any {@link DriverInterface} — the durable,
|
|
2195
2433
|
* driver-pluggable backing for the conversation persistence seam, the opt-in twin of
|
|
2196
2434
|
* {@link createMemoryConversationStore}. The exact twin of
|
|
2197
2435
|
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore}.
|
|
@@ -2203,7 +2441,7 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2203
2441
|
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore} stores its snapshot. The
|
|
2204
2442
|
* snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
2205
2443
|
* AND keeps the row type FLAT (the column reads back as `unknown`, narrowed on `get` by
|
|
2206
|
-
* {@link import('./
|
|
2444
|
+
* {@link import('./validators.js').isConversationSnapshot}). The `driver` DEFAULTS to
|
|
2207
2445
|
* {@link createMemoryDriver}, so the store ALSO works in memory out of the box; pass a server
|
|
2208
2446
|
* `createJSONDriver` / `createSQLiteDriver` (or a browser IndexedDB driver) for a persistent one —
|
|
2209
2447
|
* the durability is the driver's job, the store engine is shared. It swaps in behind
|
|
@@ -2214,7 +2452,8 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2214
2452
|
*
|
|
2215
2453
|
* @example
|
|
2216
2454
|
* ```ts
|
|
2217
|
-
* import { createConversationManager, createDatabaseConversationStore
|
|
2455
|
+
* import { createConversationManager, createDatabaseConversationStore } from '@orkestrel/agent'
|
|
2456
|
+
* import { createMemoryDriver } from '@orkestrel/database'
|
|
2218
2457
|
*
|
|
2219
2458
|
* const store = createDatabaseConversationStore(createMemoryDriver()) // a durable driver swaps in here
|
|
2220
2459
|
* const manager = createConversationManager({ store })
|
|
@@ -2226,7 +2465,7 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2226
2465
|
export declare function createDatabaseConversationStore(driver?: DriverInterface): ConversationStoreInterface;
|
|
2227
2466
|
|
|
2228
2467
|
/**
|
|
2229
|
-
*
|
|
2468
|
+
* Creates an instruction — an immutable {@link InstructionInterface} (a named directive)
|
|
2230
2469
|
* from its `name` / `content` and optional `priority`, the `id` minted at construction.
|
|
2231
2470
|
*
|
|
2232
2471
|
* @remarks
|
|
@@ -2240,7 +2479,7 @@ export declare function createDatabaseConversationStore(driver?: DriverInterface
|
|
|
2240
2479
|
*
|
|
2241
2480
|
* @example
|
|
2242
2481
|
* ```ts
|
|
2243
|
-
* import { createInstruction } from '@
|
|
2482
|
+
* import { createInstruction } from '@orkestrel/agent'
|
|
2244
2483
|
*
|
|
2245
2484
|
* const instruction = createInstruction({ name: 'tone', content: 'Be concise.', priority: 5 })
|
|
2246
2485
|
* ```
|
|
@@ -2248,28 +2487,28 @@ export declare function createDatabaseConversationStore(driver?: DriverInterface
|
|
|
2248
2487
|
export declare function createInstruction(input: InstructionInput): InstructionInterface;
|
|
2249
2488
|
|
|
2250
2489
|
/**
|
|
2251
|
-
*
|
|
2490
|
+
* Creates an instruction registry — an {@link InstructionManagerInterface} holding
|
|
2252
2491
|
* immutable instructions keyed by `name`, listed by descending `priority`.
|
|
2253
2492
|
*
|
|
2254
2493
|
* @remarks
|
|
2255
|
-
* Starts empty; `add` (one or a batch
|
|
2494
|
+
* Starts empty; `add` (one or a batch) MINTS each `id` and OVERWRITES a same-name
|
|
2256
2495
|
* instruction (last write wins); `instructions()` lists them sorted by descending
|
|
2257
|
-
* `priority` (stable for ties); `
|
|
2258
|
-
* context renders an instructions block with; `remove` (one or a batch) reports
|
|
2259
|
-
*
|
|
2260
|
-
* ({@link import('./types.js').InstructionManagerEventMap}) wired
|
|
2261
|
-
* option
|
|
2262
|
-
* (the `error` option
|
|
2496
|
+
* `priority` (stable for ties); `open` / `render` are the build contract a richer
|
|
2497
|
+
* context renders an instructions block with; `remove` (one or a batch) reports `true` only
|
|
2498
|
+
* when every supplied name was removed; `clear` empties it. Carries an observable `emitter`
|
|
2499
|
+
* ({@link import('./types.js').InstructionManagerEventMap}) wired through the reserved `on`
|
|
2500
|
+
* option; the emitter isolates a listener throw and routes it to its `error` handler
|
|
2501
|
+
* (the `error` option), so it can never corrupt a mutation. An optional `format`
|
|
2263
2502
|
* override is the manager-options level of the `AgentContext` build cascade (consulted by
|
|
2264
|
-
* `
|
|
2265
|
-
* `InstructionInput.
|
|
2503
|
+
* `open` / `render`, beating the provider default + built-in; a per-item
|
|
2504
|
+
* `InstructionInput.override` still beats it).
|
|
2266
2505
|
*
|
|
2267
2506
|
* @param options - Optional `on` hooks + a `format` override (see {@link InstructionManagerOptions})
|
|
2268
2507
|
* @returns An empty {@link InstructionManagerInterface}
|
|
2269
2508
|
*
|
|
2270
2509
|
* @example
|
|
2271
2510
|
* ```ts
|
|
2272
|
-
* import { createInstructionManager } from '@
|
|
2511
|
+
* import { createInstructionManager } from '@orkestrel/agent'
|
|
2273
2512
|
*
|
|
2274
2513
|
* const instructions = createInstructionManager()
|
|
2275
2514
|
* instructions.add({ name: 'tone', content: 'Be concise.', priority: 5 })
|
|
@@ -2278,7 +2517,7 @@ export declare function createInstruction(input: InstructionInput): InstructionI
|
|
|
2278
2517
|
export declare function createInstructionManager(options?: InstructionManagerOptions): InstructionManagerInterface;
|
|
2279
2518
|
|
|
2280
2519
|
/**
|
|
2281
|
-
*
|
|
2520
|
+
* Creates the in-memory conversation store — a {@link ConversationStoreInterface} backed by a
|
|
2282
2521
|
* process-lifetime `Map` of {@link import('./types.js').ConversationSnapshot}s keyed by conversation
|
|
2283
2522
|
* id, the DEFAULT backing for the durable {@link ConversationManagerInterface.open} /
|
|
2284
2523
|
* {@link ConversationManagerInterface.save} seam. The exact twin of
|
|
@@ -2293,14 +2532,14 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2293
2532
|
* {@link createDatabaseConversationStore} (the snapshot as one opaque JSON column over a `databases`
|
|
2294
2533
|
* table) — for a DURABLE store pass it a JSON / SQLite / IndexedDB driver, and it swaps in WITHOUT
|
|
2295
2534
|
* touching the manager or the conversation. Hydration stays a manager concern: read a snapshot back
|
|
2296
|
-
* and rebuild the live conversation through the
|
|
2535
|
+
* and rebuild the live conversation through the `snapshot` option (re-supplying the live
|
|
2297
2536
|
* `summarize` / `keep`).
|
|
2298
2537
|
*
|
|
2299
2538
|
* @returns A memory-backed {@link ConversationStoreInterface}
|
|
2300
2539
|
*
|
|
2301
2540
|
* @example
|
|
2302
2541
|
* ```ts
|
|
2303
|
-
* import { createConversationManager, createMemoryConversationStore } from '@
|
|
2542
|
+
* import { createConversationManager, createMemoryConversationStore } from '@orkestrel/agent'
|
|
2304
2543
|
*
|
|
2305
2544
|
* const store = createMemoryConversationStore()
|
|
2306
2545
|
* const manager = createConversationManager({ store })
|
|
@@ -2312,8 +2551,8 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2312
2551
|
export declare function createMemoryConversationStore(): ConversationStoreInterface;
|
|
2313
2552
|
|
|
2314
2553
|
/**
|
|
2315
|
-
*
|
|
2316
|
-
*
|
|
2554
|
+
* Creates a named scope — an immutable {@link ScopeInterface} from its `name` and its
|
|
2555
|
+
* per-category allow-lists, the `id` minted at construction.
|
|
2317
2556
|
*
|
|
2318
2557
|
* @remarks
|
|
2319
2558
|
* Each list is THREE-WAY: `undefined` ⇒ NO constraint on that category (all pass), `[]` ⇒
|
|
@@ -2321,13 +2560,13 @@ export declare function createMemoryConversationStore(): ConversationStoreInterf
|
|
|
2321
2560
|
* tighter child by set-INTERSECTION (an `undefined` side imposing no constraint). Stored
|
|
2322
2561
|
* immutable — never mutated after creation (`narrow` returns a new scope).
|
|
2323
2562
|
*
|
|
2324
|
-
* @param input - `name` (required) and the optional `instructions` / `tools` / `
|
|
2325
|
-
*
|
|
2563
|
+
* @param input - `name` (required) and the optional `instructions` / `tools` / `files`
|
|
2564
|
+
* allow-lists (see {@link ScopeInput})
|
|
2326
2565
|
* @returns A working {@link ScopeInterface}
|
|
2327
2566
|
*
|
|
2328
2567
|
* @example
|
|
2329
2568
|
* ```ts
|
|
2330
|
-
* import { createScope } from '@
|
|
2569
|
+
* import { createScope } from '@orkestrel/agent'
|
|
2331
2570
|
*
|
|
2332
2571
|
* const reader = createScope({ name: 'reader', tools: ['search', 'read'] })
|
|
2333
2572
|
* reader.narrow({ tools: ['read', 'write'] }).tools // ['read'] — intersection tightens
|
|
@@ -2336,23 +2575,24 @@ export declare function createMemoryConversationStore(): ConversationStoreInterf
|
|
|
2336
2575
|
export declare function createScope(input: ScopeInput): ScopeInterface;
|
|
2337
2576
|
|
|
2338
2577
|
/**
|
|
2339
|
-
*
|
|
2578
|
+
* Creates a scope registry — a {@link ScopeManagerInterface} holding immutable scopes keyed
|
|
2340
2579
|
* by their minted `id`, in insertion order.
|
|
2341
2580
|
*
|
|
2342
2581
|
* @remarks
|
|
2343
2582
|
* Starts empty; `create` mints each scope's `id` and stores it (keyed by `id`, so it
|
|
2344
2583
|
* always adds — two scopes may share a `name`); `scopes()` lists them in insertion order;
|
|
2345
|
-
* `remove` (one or a batch
|
|
2346
|
-
* Carries an observable `emitter`
|
|
2347
|
-
*
|
|
2348
|
-
*
|
|
2584
|
+
* `remove` (one or a batch) reports `true` only when every supplied id was removed; `clear`
|
|
2585
|
+
* empties it. Carries an observable `emitter`
|
|
2586
|
+
* ({@link import('./types.js').ScopeManagerEventMap}) wired through the reserved `on`
|
|
2587
|
+
* option; the emitter isolates a listener throw and routes it to its `error` handler
|
|
2588
|
+
* (the `error` option), so it can never corrupt a mutation.
|
|
2349
2589
|
*
|
|
2350
2590
|
* @param options - Optional `on` hooks (see {@link ScopeManagerOptions})
|
|
2351
2591
|
* @returns An empty {@link ScopeManagerInterface}
|
|
2352
2592
|
*
|
|
2353
2593
|
* @example
|
|
2354
2594
|
* ```ts
|
|
2355
|
-
* import { createScopeManager } from '@
|
|
2595
|
+
* import { createScopeManager } from '@orkestrel/agent'
|
|
2356
2596
|
*
|
|
2357
2597
|
* const scopes = createScopeManager()
|
|
2358
2598
|
* const reader = scopes.create({ name: 'reader', tools: ['search'] })
|
|
@@ -2361,7 +2601,7 @@ export declare function createScope(input: ScopeInput): ScopeInterface;
|
|
|
2361
2601
|
export declare function createScopeManager(options?: ScopeManagerOptions): ScopeManagerInterface;
|
|
2362
2602
|
|
|
2363
2603
|
/**
|
|
2364
|
-
*
|
|
2604
|
+
* Creates a stream-stateful `<think>` separator — a {@link ThinkSplitterInterface} that
|
|
2365
2605
|
* splits a thinking model's in-content `<think>…</think>` reasoning spans away from
|
|
2366
2606
|
* the answer, delta by delta, so a provider yields ONLY clean content and surfaces the
|
|
2367
2607
|
* accumulated reasoning as {@link import('./types.js').ProviderResult.thinking}.
|
|
@@ -2372,14 +2612,14 @@ export declare function createScopeManager(options?: ScopeManagerOptions): Scope
|
|
|
2372
2612
|
* partial open tag that never completed returns as final content; an UNCLOSED think
|
|
2373
2613
|
* span lands on `thinking`). Tags split ACROSS deltas are held back until
|
|
2374
2614
|
* disambiguated, multiple spans accumulate in order, and a nested-looking `<think>`
|
|
2375
|
-
* inside an open span is
|
|
2615
|
+
* inside an open span is thinking text. One splitter serves ONE stream — create
|
|
2376
2616
|
* a fresh one per provider call.
|
|
2377
2617
|
*
|
|
2378
2618
|
* @returns A fresh {@link ThinkSplitterInterface} (state empty, outside any span)
|
|
2379
2619
|
*
|
|
2380
2620
|
* @example
|
|
2381
2621
|
* ```ts
|
|
2382
|
-
* import { createThinkSplitter } from '@
|
|
2622
|
+
* import { createThinkSplitter } from '@orkestrel/agent'
|
|
2383
2623
|
*
|
|
2384
2624
|
* const splitter = createThinkSplitter()
|
|
2385
2625
|
* const clean = splitter.split('<think>plan the answer</think>Here it is.')
|
|
@@ -2390,7 +2630,7 @@ export declare function createScopeManager(options?: ScopeManagerOptions): Scope
|
|
|
2390
2630
|
export declare function createThinkSplitter(): ThinkSplitterInterface;
|
|
2391
2631
|
|
|
2392
2632
|
/**
|
|
2393
|
-
*
|
|
2633
|
+
* Backs a {@link ConversationStoreInterface} with one table of the `databases` layer — a
|
|
2394
2634
|
* conversation's durable state IS a row, so persistence reduces to keyed point-access (`get` / `set`
|
|
2395
2635
|
* / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`
|
|
2396
2636
|
* {@link import('./MemoryConversationStore.js').MemoryConversationStore}. The EXACT twin of
|
|
@@ -2416,19 +2656,20 @@ export declare function createThinkSplitter(): ThinkSplitterInterface;
|
|
|
2416
2656
|
* - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes
|
|
2417
2657
|
* the row `{ id: snapshot.id, snapshot }`.
|
|
2418
2658
|
* - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
|
|
2419
|
-
* a {@link ConversationSnapshot} ({@link import('../../
|
|
2420
|
-
*
|
|
2659
|
+
* a {@link ConversationSnapshot} ({@link import('../../validators.js').isConversationSnapshot} — the
|
|
2660
|
+
* total guard for an untrusted storage read), or `undefined` if none is stored.
|
|
2421
2661
|
* - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
2422
2662
|
*
|
|
2423
2663
|
* UNLIKE a session store there is NO idle-TTL / eviction — a persisted conversation lives until an
|
|
2424
2664
|
* explicit `delete`. The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the
|
|
2425
|
-
*
|
|
2665
|
+
* method bijection with {@link ConversationStoreInterface}). Hydration stays a caller concern: a
|
|
2426
2666
|
* {@link import('../ConversationManager.js').ConversationManager} reads a snapshot back and rebuilds
|
|
2427
|
-
* the live conversation through the
|
|
2667
|
+
* the live conversation through the `snapshot` option (its `open` / `save`).
|
|
2428
2668
|
*
|
|
2429
2669
|
* @example
|
|
2430
2670
|
* ```ts
|
|
2431
|
-
* import { createConversation, createDatabaseConversationStore
|
|
2671
|
+
* import { createConversation, createDatabaseConversationStore } from '@orkestrel/agent'
|
|
2672
|
+
* import { createMemoryDriver } from '@orkestrel/database'
|
|
2432
2673
|
*
|
|
2433
2674
|
* const store = createDatabaseConversationStore(createMemoryDriver()) // a durable driver swaps in here
|
|
2434
2675
|
* const conversation = createConversation()
|
|
@@ -2441,30 +2682,30 @@ export declare function createThinkSplitter(): ThinkSplitterInterface;
|
|
|
2441
2682
|
export declare class DatabaseConversationStore implements ConversationStoreInterface {
|
|
2442
2683
|
#private;
|
|
2443
2684
|
/**
|
|
2444
|
-
*
|
|
2685
|
+
* Wraps a table as a conversation store.
|
|
2445
2686
|
*
|
|
2446
2687
|
* @param table - The {@link TableInterface} holding the snapshots — its row is the
|
|
2447
2688
|
* {@link ConversationSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)
|
|
2448
2689
|
*/
|
|
2449
2690
|
constructor(table: TableInterface<ConversationSnapshotRow>);
|
|
2450
|
-
/**
|
|
2691
|
+
/** Resolves the persisted snapshot for `id`, narrowing the opaque JSON column back to a `ConversationSnapshot`. */
|
|
2451
2692
|
get(id: string): Promise<ConversationSnapshot | undefined>;
|
|
2452
|
-
/**
|
|
2693
|
+
/** Inserts or replaces under the snapshot's OWN `id` (no separate id param) — the row is `{ id, snapshot }`. */
|
|
2453
2694
|
set(snapshot: ConversationSnapshot): Promise<void>;
|
|
2454
|
-
/**
|
|
2695
|
+
/** Drops a snapshot by id; an absent id is a no-op (no throw). */
|
|
2455
2696
|
delete(id: string): Promise<void>;
|
|
2456
2697
|
}
|
|
2457
2698
|
|
|
2458
2699
|
/**
|
|
2459
|
-
*
|
|
2700
|
+
* Caps an {@link AgentInterface} turn's tool iterations by default — the maximum
|
|
2460
2701
|
* number of context → provider → tools cycles before the loop stops, so a model that
|
|
2461
|
-
* keeps requesting tools can never loop forever. Overridable per agent
|
|
2702
|
+
* keeps requesting tools can never loop forever. Overridable per agent through
|
|
2462
2703
|
* `AgentOptions.limit`.
|
|
2463
2704
|
*/
|
|
2464
2705
|
export declare const DEFAULT_AGENT_LIMIT = 10;
|
|
2465
2706
|
|
|
2466
2707
|
/**
|
|
2467
|
-
*
|
|
2708
|
+
* Names the zone an {@link AuthorityInterface}'s default fallback {@link AuthorityDecision}
|
|
2468
2709
|
* carries — the classification for a tool call that matched no rule. Paired with the
|
|
2469
2710
|
* default `allowed: true` fallback, an unmatched call is allowed under this zone, so a
|
|
2470
2711
|
* rules list of denials acts as a denylist; a caller wanting deny-by-default supplies
|
|
@@ -2473,17 +2714,38 @@ export declare const DEFAULT_AGENT_LIMIT = 10;
|
|
|
2473
2714
|
export declare const DEFAULT_AUTHORITY_ZONE = "default";
|
|
2474
2715
|
|
|
2475
2716
|
/**
|
|
2476
|
-
*
|
|
2717
|
+
* Sets the default number of recent live messages a {@link ConversationInterface}'s `compact()`
|
|
2477
2718
|
* RETAINS verbatim — `0`, so a manual `compact()` folds ALL of the current live messages
|
|
2478
2719
|
* into one summarized section (no tail kept). A caller retains a recent tail by passing
|
|
2479
2720
|
* `keep` (on {@link ConversationOptions}, {@link ConversationManagerOptions}, or per-fold
|
|
2480
|
-
*
|
|
2721
|
+
* through {@link CompactOptions}), folding only the older `count - keep` messages and leaving
|
|
2481
2722
|
* the most recent `keep` live for the next turn. Overridable everywhere `keep` is accepted.
|
|
2482
2723
|
*/
|
|
2483
2724
|
export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
2484
2725
|
|
|
2485
2726
|
/**
|
|
2486
|
-
*
|
|
2727
|
+
* Synthesizes the denial {@link ToolResult} an authority-blocked call is fed back with — the
|
|
2728
|
+
* call's `id` / `name` keyed back, carrying a denial `error` instead of a value.
|
|
2729
|
+
*
|
|
2730
|
+
* @remarks
|
|
2731
|
+
* Pure and total. The rule's `reason` is rendered as `denied: <reason>` when one was given,
|
|
2732
|
+
* else the generic `denied by authority`. There is no `value`, so the agent loop feeds it back
|
|
2733
|
+
* exactly like a tool error and the model can react to it.
|
|
2734
|
+
*
|
|
2735
|
+
* @param call - The denied {@link ToolCall}
|
|
2736
|
+
* @param reason - The rule's explanation, or `undefined` for the generic denial
|
|
2737
|
+
* @returns The failure-arm {@link ToolResult}
|
|
2738
|
+
*
|
|
2739
|
+
* @example
|
|
2740
|
+
* ```ts
|
|
2741
|
+
* denyCall({ id: '1', name: 'drop', arguments: {} }, 'read-only mode')
|
|
2742
|
+
* // { success: false, id: '1', name: 'drop', error: 'denied: read-only mode' }
|
|
2743
|
+
* ```
|
|
2744
|
+
*/
|
|
2745
|
+
export declare function denyCall(call: ToolCall, reason: string | undefined): ToolResult;
|
|
2746
|
+
|
|
2747
|
+
/**
|
|
2748
|
+
* Estimates the context-token footprint of a batch of messages — the default `consumer`
|
|
2487
2749
|
* estimator for an agent's context `BudgetInterface` (a budgets surface's tracking contract)
|
|
2488
2750
|
* (the {@link import('./types.js').AgentOptions} `window`).
|
|
2489
2751
|
*
|
|
@@ -2495,7 +2757,7 @@ export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
|
2495
2757
|
* deliberately-approximate per-image cost — a base64 length is NOT a token proxy). Deterministic
|
|
2496
2758
|
* and provider-free — the same messages always yield the same estimate, with an empty batch `0`.
|
|
2497
2759
|
* It is the fully-swappable default an agent's auto-compaction context budget charges each
|
|
2498
|
-
* turn's new messages through; a caller wanting a sharper count supplies its own `
|
|
2760
|
+
* turn's new messages through; a caller wanting a sharper count supplies its own `consumer` to
|
|
2499
2761
|
* `createBudget` instead. Total — never throws: a `calls` `JSON.stringify` that throws (a
|
|
2500
2762
|
* circular `ToolCall.arguments`) is caught and replaced with a conservative fixed contribution of
|
|
2501
2763
|
* {@link import('./constants.js').MESSAGE_TOKEN_OVERHEAD} (the same per-message overhead scale)
|
|
@@ -2510,10 +2772,10 @@ export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
|
2510
2772
|
* estimateMessages([{ id: '1', role: 'user', content: 'hello' }]) // 6 (2 content + 4 overhead)
|
|
2511
2773
|
* ```
|
|
2512
2774
|
*/
|
|
2513
|
-
export declare function estimateMessages(messages: readonly
|
|
2775
|
+
export declare function estimateMessages(messages: readonly Message[]): number;
|
|
2514
2776
|
|
|
2515
2777
|
/**
|
|
2516
|
-
*
|
|
2778
|
+
* Estimates the context-token footprint of a string — the deterministic char-based heuristic
|
|
2517
2779
|
* {@link estimateMessages} sums over a conversation's messages (the default context-budget
|
|
2518
2780
|
* estimator).
|
|
2519
2781
|
*
|
|
@@ -2537,34 +2799,7 @@ export declare function estimateMessages(messages: readonly MessageInterface[]):
|
|
|
2537
2799
|
export declare function estimateTokens(text: string): number;
|
|
2538
2800
|
|
|
2539
2801
|
/**
|
|
2540
|
-
*
|
|
2541
|
-
* {@link import('./AgentContext.js').AgentContext}'s ACTIVE-workspace text-file render emits (the
|
|
2542
|
-
* active workspace is the SOLE document/image context).
|
|
2543
|
-
*
|
|
2544
|
-
* @remarks
|
|
2545
|
-
* Produces `` File: <path>\n```<language>\n<content>\n``` `` — the `File:` label line, then a
|
|
2546
|
-
* fenced code block tagged with `language`, the `content` verbatim inside. Pure string assembly,
|
|
2547
|
-
* total — never throws. The one fenced-file format string for the whole module — `AgentContext.build()`
|
|
2548
|
-
* frames an active workspace's text files with it (each carries its own `language` on its
|
|
2549
|
-
* {@link import('@orkestrel/workspace').FileContent} text arm).
|
|
2550
|
-
*
|
|
2551
|
-
* @param path - The file path shown on the `File:` label line
|
|
2552
|
-
* @param language - The fenced-code language tag (e.g. `'typescript'`)
|
|
2553
|
-
* @param content - The file body rendered verbatim inside the fence
|
|
2554
|
-
* @returns The fenced reference block
|
|
2555
|
-
*
|
|
2556
|
-
* @example
|
|
2557
|
-
* ```ts
|
|
2558
|
-
* import { fencedFile } from '@src/core'
|
|
2559
|
-
*
|
|
2560
|
-
* fencedFile('src/main.ts', 'typescript', 'const x = 1')
|
|
2561
|
-
* // 'File: src/main.ts\n```typescript\nconst x = 1\n```'
|
|
2562
|
-
* ```
|
|
2563
|
-
*/
|
|
2564
|
-
export declare function fencedFile(path: string, language: string, content: string): string;
|
|
2565
|
-
|
|
2566
|
-
/**
|
|
2567
|
-
* Filter a list of items by a {@link import('./types.js').ScopeInterface} allow-list of
|
|
2802
|
+
* Filters a list of items by a {@link import('./types.js').ScopeInterface} allow-list of
|
|
2568
2803
|
* keys — the pure, total set-membership primitive the context's build step and the agent
|
|
2569
2804
|
* loop's tool-advertise step apply a scope through.
|
|
2570
2805
|
*
|
|
@@ -2581,7 +2816,7 @@ export declare function fencedFile(path: string, language: string, content: stri
|
|
|
2581
2816
|
* @typeParam T - The item type being filtered
|
|
2582
2817
|
* @param allow - The allow-list of keys (`undefined` ⇒ all, `[]` ⇒ none, else only-listed)
|
|
2583
2818
|
* @param items - The items to filter (returned unchanged when `allow` is `undefined`)
|
|
2584
|
-
* @param key - Extracts the key an item is matched on (
|
|
2819
|
+
* @param key - Extracts the key an item is matched on (for example an instruction's `name`)
|
|
2585
2820
|
* @returns The items that pass the allow-list, in their original order
|
|
2586
2821
|
*
|
|
2587
2822
|
* @example
|
|
@@ -2595,19 +2830,19 @@ export declare function fencedFile(path: string, language: string, content: stri
|
|
|
2595
2830
|
export declare function filterAllowList<T>(allow: readonly string[] | undefined, items: readonly T[], key: (item: T) => string): readonly T[];
|
|
2596
2831
|
|
|
2597
2832
|
/**
|
|
2598
|
-
*
|
|
2833
|
+
* Handles one queued agent job by rehydrating it through a registry with the queue
|
|
2599
2834
|
* attempt's signal, then applying the shared partial-result policy.
|
|
2600
2835
|
*
|
|
2601
2836
|
* @param registry - The registry that rehydrates the serializable job
|
|
2602
|
-
* @param
|
|
2837
|
+
* @param partial - The partial policy. If `true`, a partial result resolves; if `false`, it throws
|
|
2603
2838
|
* @param input - The serializable agent job
|
|
2604
|
-
* @param
|
|
2839
|
+
* @param context - The queue attempt whose signal bounds the agent
|
|
2605
2840
|
* @returns The settled agent result
|
|
2606
2841
|
*/
|
|
2607
|
-
export declare function handleAgentQueueJob(registry: AgentRegistryInterface,
|
|
2842
|
+
export declare function handleAgentQueueJob(registry: AgentRegistryInterface, partial: boolean, input: AgentJobInput, context: QueueContext): Promise<AgentResult>;
|
|
2608
2843
|
|
|
2609
2844
|
/**
|
|
2610
|
-
*
|
|
2845
|
+
* Handles one runner agent job by fanning out its declared children, rehydrating the
|
|
2611
2846
|
* parent through a registry with the controller signal, and applying the shared
|
|
2612
2847
|
* partial-result policy.
|
|
2613
2848
|
*
|
|
@@ -2616,14 +2851,14 @@ export declare function handleAgentQueueJob(registry: AgentRegistryInterface, al
|
|
|
2616
2851
|
* inline, preserving bounded-runner progress.
|
|
2617
2852
|
*
|
|
2618
2853
|
* @param registry - The registry that rehydrates serializable jobs
|
|
2619
|
-
* @param
|
|
2854
|
+
* @param partial - The partial policy. If `true`, a partial result resolves; if `false`, it throws
|
|
2620
2855
|
* @param controller - The runner controller for this parent job
|
|
2621
2856
|
* @returns The settled parent agent result
|
|
2622
2857
|
*/
|
|
2623
|
-
export declare function handleAgentRunnerJob(registry: AgentRegistryInterface,
|
|
2858
|
+
export declare function handleAgentRunnerJob(registry: AgentRegistryInterface, partial: boolean, controller: ControllerInterface<AgentJobInput, AgentResult>): Promise<AgentResult>;
|
|
2624
2859
|
|
|
2625
2860
|
/**
|
|
2626
|
-
*
|
|
2861
|
+
* Names the coarse, deliberately-approximate per-image token cost {@link import('./helpers.js').estimateMessages}
|
|
2627
2862
|
* charges for each attached image.
|
|
2628
2863
|
*
|
|
2629
2864
|
* @remarks
|
|
@@ -2635,15 +2870,15 @@ export declare function handleAgentRunnerJob(registry: AgentRegistryInterface, a
|
|
|
2635
2870
|
export declare const IMAGE_TOKEN_ESTIMATE = 512;
|
|
2636
2871
|
|
|
2637
2872
|
/**
|
|
2638
|
-
*
|
|
2639
|
-
* input (`name` / `content`, an optional `priority` defaulting to `0`), the `id`
|
|
2640
|
-
* at construction.
|
|
2873
|
+
* Represents an immutable named directive — a {@link InstructionInterface} assembled once
|
|
2874
|
+
* from its input (`name` / `content`, an optional `priority` defaulting to `0`), the `id`
|
|
2875
|
+
* minted at construction.
|
|
2641
2876
|
*
|
|
2642
2877
|
* @remarks
|
|
2643
2878
|
* A thin immutable value object (mirroring {@link import('@orkestrel/tool').Tool}): the
|
|
2644
2879
|
* constructor mints a fresh `id` (`crypto.randomUUID()`), copies the input's `name` /
|
|
2645
2880
|
* `content`, resolves `priority` to the input's value or `0`, and carries the input's
|
|
2646
|
-
* per-item `
|
|
2881
|
+
* per-item `override` ONLY when supplied (assigned when present, mirroring a
|
|
2647
2882
|
* message's `images` / `calls` present-when-given convention — kept absent otherwise).
|
|
2648
2883
|
* Never mutated after construction. An
|
|
2649
2884
|
* {@link import('./InstructionManager.js').InstructionManager} keys it by `name` and
|
|
@@ -2660,77 +2895,77 @@ export declare class Instruction implements InstructionInterface {
|
|
|
2660
2895
|
readonly name: string;
|
|
2661
2896
|
readonly content: string;
|
|
2662
2897
|
readonly priority: number;
|
|
2663
|
-
readonly
|
|
2898
|
+
readonly override?: string;
|
|
2664
2899
|
constructor(input: InstructionInput);
|
|
2665
2900
|
}
|
|
2666
2901
|
|
|
2667
2902
|
/**
|
|
2668
|
-
*
|
|
2903
|
+
* Carries the minimal data to author an {@link InstructionInterface} — the `id` is minted by
|
|
2669
2904
|
* the {@link InstructionManagerInterface} that stores it, so a caller supplies only
|
|
2670
2905
|
* `name` / `content` (and an optional `priority`, defaulting to `0`).
|
|
2671
2906
|
*/
|
|
2672
2907
|
export declare interface InstructionInput {
|
|
2673
2908
|
readonly name: string;
|
|
2674
2909
|
readonly content: string;
|
|
2675
|
-
/**
|
|
2910
|
+
/** Weights the ordering (higher renders first); defaults to `0` when omitted. */
|
|
2676
2911
|
readonly priority?: number;
|
|
2677
2912
|
/**
|
|
2678
|
-
*
|
|
2913
|
+
* Holds a fully-rendered override of THIS instruction's prompt text — the most-specific
|
|
2679
2914
|
* level of the {@link import('./AgentContext.js').AgentContext} build cascade (beats a
|
|
2680
2915
|
* manager-options / provider / built-in format for this item). Round-tripped onto the
|
|
2681
2916
|
* stored {@link InstructionInterface} when given (present-when-supplied, like `images`).
|
|
2682
2917
|
*/
|
|
2683
|
-
readonly
|
|
2918
|
+
readonly override?: string;
|
|
2684
2919
|
}
|
|
2685
2920
|
|
|
2686
2921
|
/**
|
|
2687
|
-
*
|
|
2922
|
+
* Represents an immutable instruction — a named directive a richer context places between the
|
|
2688
2923
|
* system prompt and the conversation, ordered by descending {@link priority}.
|
|
2689
2924
|
*
|
|
2690
2925
|
* @remarks
|
|
2691
2926
|
* Assembled once from its {@link InstructionInput} (the `id` minted by the storing
|
|
2692
2927
|
* layer) and never mutated. `name` keys it in an {@link InstructionManagerInterface}
|
|
2693
2928
|
* (last write wins); `priority` orders the rendered list (higher first), defaulting to
|
|
2694
|
-
* `0`. The {@link import('./AgentContext.js').AgentContext} build step renders it
|
|
2695
|
-
* its manager's `
|
|
2929
|
+
* `0`. The {@link import('./AgentContext.js').AgentContext} build step renders it through
|
|
2930
|
+
* its manager's `render` (`content`) under the manager's `open` header.
|
|
2696
2931
|
*/
|
|
2697
2932
|
export declare interface InstructionInterface {
|
|
2698
2933
|
readonly id: string;
|
|
2699
2934
|
readonly name: string;
|
|
2700
2935
|
readonly content: string;
|
|
2701
|
-
/**
|
|
2936
|
+
/** Ranks the instruction — higher renders first; defaults to `0`. */
|
|
2702
2937
|
readonly priority: number;
|
|
2703
2938
|
/**
|
|
2704
|
-
*
|
|
2939
|
+
* Holds a fully-rendered per-item override of this instruction's prompt text — the
|
|
2705
2940
|
* MOST-SPECIFIC level of the {@link import('./AgentContext.js').AgentContext} build
|
|
2706
2941
|
* cascade, beating every format level for THIS item. Present only when supplied on the
|
|
2707
2942
|
* {@link InstructionInput} (round-tripped through the manager, like a message's
|
|
2708
2943
|
* `images`); absent ⇒ the cascade decides.
|
|
2709
2944
|
*/
|
|
2710
|
-
readonly
|
|
2945
|
+
readonly override?: string;
|
|
2711
2946
|
}
|
|
2712
2947
|
|
|
2713
2948
|
/**
|
|
2714
|
-
*
|
|
2715
|
-
*
|
|
2949
|
+
* Registers the immutable {@link Instruction}s a richer context assembles a directives
|
|
2950
|
+
* block from — keyed by `name`, listed by descending `priority`.
|
|
2716
2951
|
*
|
|
2717
2952
|
* @remarks
|
|
2718
2953
|
* - **Registry.** Instructions live in an insertion-ordered `Map` keyed by `name`;
|
|
2719
|
-
* `add` takes one {@link InstructionInput} or a batch
|
|
2954
|
+
* `add` takes one {@link InstructionInput} or a batch, MINTS each instruction's
|
|
2720
2955
|
* `id`, and a re-`add` of the same name OVERWRITES it (last write wins). `count` is the
|
|
2721
2956
|
* map size, `instruction(name)` looks one up, and `instructions()` lists them SORTED by
|
|
2722
2957
|
* descending `priority` (a stable sort, so equal priorities keep insertion order).
|
|
2723
|
-
* - **Build contract (with the manager-options override).** `
|
|
2724
|
-
* header a context renders the instructions under; `
|
|
2958
|
+
* - **Build contract (with the manager-options override).** `open` is the section
|
|
2959
|
+
* header a context renders the instructions under; `render(instruction)` renders one
|
|
2725
2960
|
* instruction (its `content`). Each ENCAPSULATES the cascade's `[options-override →
|
|
2726
2961
|
* built-in]` half: when `InstructionManagerOptions.format` supplies an `open` /
|
|
2727
|
-
* `render`, `
|
|
2962
|
+
* `render`, `open` / `render` return IT, else the built-in — so a richer context
|
|
2728
2963
|
* reads one consistent pair and layers the provider default + per-item override on top
|
|
2729
2964
|
* (see {@link import('../AgentContext.js').AgentContext}). The per-item
|
|
2730
|
-
* {@link InstructionInput.
|
|
2731
|
-
* - **Removal.** `remove` drops one by name, or a batch
|
|
2732
|
-
* removed; `clear` empties the registry.
|
|
2733
|
-
* - **Observable
|
|
2965
|
+
* {@link InstructionInput.override} is round-tripped onto the stored instruction.
|
|
2966
|
+
* - **Removal.** `remove` drops one by name, or a batch — `true` only when EVERY supplied
|
|
2967
|
+
* name was removed; `clear` empties the registry.
|
|
2968
|
+
* - **Observable.** The owned {@link emitter} ({@link InstructionManagerEventMap})
|
|
2734
2969
|
* carries `add` (the created instruction) / `remove` (the name) / `clear` for
|
|
2735
2970
|
* fire-and-forget observers. Every event is emitted directly, strictly AFTER the map
|
|
2736
2971
|
* mutation completes; the emitter isolates a listener throw and routes it to its `error`
|
|
@@ -2751,105 +2986,129 @@ export declare class InstructionManager implements InstructionManagerInterface {
|
|
|
2751
2986
|
constructor(options?: InstructionManagerOptions);
|
|
2752
2987
|
get emitter(): EmitterInterface<InstructionManagerEventMap>;
|
|
2753
2988
|
get count(): number;
|
|
2754
|
-
get
|
|
2755
|
-
get
|
|
2989
|
+
get open(): string;
|
|
2990
|
+
get format(): ContextSectionFormat<InstructionInterface> | undefined;
|
|
2756
2991
|
add(input: InstructionInput): InstructionInterface;
|
|
2757
2992
|
add(inputs: readonly InstructionInput[]): readonly InstructionInterface[];
|
|
2758
2993
|
instruction(name: string): InstructionInterface | undefined;
|
|
2759
2994
|
instructions(): readonly InstructionInterface[];
|
|
2760
|
-
|
|
2995
|
+
render(instruction: InstructionInterface): string;
|
|
2761
2996
|
remove(name: string): boolean;
|
|
2762
2997
|
remove(names: readonly string[]): boolean;
|
|
2763
2998
|
clear(): void;
|
|
2764
2999
|
}
|
|
2765
3000
|
|
|
2766
3001
|
/**
|
|
2767
|
-
*
|
|
2768
|
-
* mutation moments a fire-and-forget observer subscribes to
|
|
3002
|
+
* Maps the push observation surface of an {@link InstructionManagerInterface} — the
|
|
3003
|
+
* mutation moments a fire-and-forget observer subscribes to through `manager.emitter.on`.
|
|
2769
3004
|
*
|
|
2770
3005
|
* @remarks
|
|
2771
3006
|
* `add` carries the created (or replaced) {@link InstructionInterface}; `remove`
|
|
2772
3007
|
* carries the removed instruction's `name`; `clear` is a pure signal (no payload).
|
|
2773
|
-
* Listener isolation is the emitter's
|
|
3008
|
+
* Listener isolation is the emitter's: a listener throw is routed to the
|
|
2774
3009
|
* emitter's `error` handler (the `error` option), never onto this map, so a buggy
|
|
2775
3010
|
* observer can never corrupt a mutation. Declared as a `type` alias (not `interface
|
|
2776
|
-
* extends EventMap
|
|
3011
|
+
* extends EventMap`) so the type-literal satisfies `EventMap` structurally.
|
|
2777
3012
|
*/
|
|
2778
3013
|
export declare type InstructionManagerEventMap = {
|
|
2779
|
-
/**
|
|
3014
|
+
/** Reports an instruction added (or a same-name one replaced) — the created instruction. */
|
|
2780
3015
|
readonly add: readonly [instruction: InstructionInterface];
|
|
2781
|
-
/**
|
|
3016
|
+
/** Reports an instruction removed — its `name`. */
|
|
2782
3017
|
readonly remove: readonly [name: string];
|
|
2783
|
-
/**
|
|
3018
|
+
/** Reports every instruction removed. */
|
|
2784
3019
|
readonly clear: readonly [];
|
|
2785
3020
|
};
|
|
2786
3021
|
|
|
2787
3022
|
/**
|
|
2788
|
-
*
|
|
2789
|
-
*
|
|
3023
|
+
* Registers {@link InstructionInterface}s keyed by `name` — `add` (one or a batch)
|
|
3024
|
+
* mints each `id` and OVERWRITES a same-name instruction (last write wins);
|
|
2790
3025
|
* `instructions()` lists them SORTED by descending `priority` (stable for ties).
|
|
2791
3026
|
*
|
|
2792
3027
|
* @remarks
|
|
2793
|
-
* - **Build contract.** `
|
|
2794
|
-
* the instructions under; `
|
|
3028
|
+
* - **Build contract.** `open` is the section header a richer context renders
|
|
3029
|
+
* the instructions under; `render(instruction)` renders one instruction (its
|
|
2795
3030
|
* `content`). Together they let an {@link import('./AgentContext.js').AgentContext}
|
|
2796
3031
|
* assemble an instructions block.
|
|
2797
|
-
* - **Observable
|
|
3032
|
+
* - **Observable.** The owned `emitter` ({@link InstructionManagerEventMap})
|
|
2798
3033
|
* carries `add` / `remove` / `clear` for fire-and-forget observers; the emitter
|
|
2799
|
-
* isolates a listener throw and routes it to its `error` handler (the `error` option
|
|
3034
|
+
* isolates a listener throw and routes it to its `error` handler (the `error` option).
|
|
2800
3035
|
*/
|
|
2801
3036
|
export declare interface InstructionManagerInterface {
|
|
2802
3037
|
readonly emitter: EmitterInterface<InstructionManagerEventMap>;
|
|
2803
3038
|
readonly count: number;
|
|
2804
|
-
/**
|
|
2805
|
-
readonly
|
|
3039
|
+
/** Names the section header a context renders the instructions under. */
|
|
3040
|
+
readonly open: string;
|
|
2806
3041
|
/**
|
|
2807
|
-
*
|
|
3042
|
+
* Holds the manager-options format override (the {@link InstructionManagerOptions.format}
|
|
2808
3043
|
* supplied at construction), or `undefined` when none — the MANAGER-OPTIONS level of the
|
|
2809
3044
|
* {@link import('./AgentContext.js').AgentContext} build cascade, exposed so `build()`
|
|
2810
|
-
* can interleave the provider default BENEATH it (`
|
|
3045
|
+
* can interleave the provider default BENEATH it (`open` / `render` already
|
|
2811
3046
|
* encapsulate the `[override → built-in]` half for standalone use). A `readonly` data
|
|
2812
3047
|
* member, not a method.
|
|
2813
3048
|
*/
|
|
2814
|
-
readonly
|
|
3049
|
+
readonly format: ContextSectionFormat<InstructionInterface> | undefined;
|
|
2815
3050
|
add(input: InstructionInput): InstructionInterface;
|
|
2816
3051
|
add(inputs: readonly InstructionInput[]): readonly InstructionInterface[];
|
|
2817
3052
|
instruction(name: string): InstructionInterface | undefined;
|
|
2818
|
-
/**
|
|
3053
|
+
/** Lists every instruction, sorted by descending `priority` (stable for equal priorities). */
|
|
2819
3054
|
instructions(): readonly InstructionInterface[];
|
|
2820
|
-
/**
|
|
2821
|
-
|
|
3055
|
+
/** Renders one instruction for the prompt — its `content`. */
|
|
3056
|
+
render(instruction: InstructionInterface): string;
|
|
2822
3057
|
remove(name: string): boolean;
|
|
2823
3058
|
remove(names: readonly string[]): boolean;
|
|
2824
3059
|
clear(): void;
|
|
2825
3060
|
}
|
|
2826
3061
|
|
|
2827
3062
|
/**
|
|
2828
|
-
*
|
|
3063
|
+
* Configures `createInstructionManager` — the reserved `on` hooks plus an optional
|
|
2829
3064
|
* per-section format override.
|
|
2830
3065
|
*
|
|
2831
3066
|
* @remarks
|
|
2832
|
-
* `on` is the
|
|
3067
|
+
* `on` is the reserved listener key: initial listeners for the manager's
|
|
2833
3068
|
* {@link InstructionManagerEventMap}, wired at construction. `format` is the
|
|
2834
3069
|
* MANAGER-OPTIONS level of the {@link import('./AgentContext.js').AgentContext} build
|
|
2835
3070
|
* cascade — a {@link ContextSectionFormat} the manager consults FIRST in its own
|
|
2836
|
-
* `
|
|
3071
|
+
* `open` / `render` (falling back to the built-in when a member is omitted), so it
|
|
2837
3072
|
* BEATS the provider default and the built-in, while a per-item
|
|
2838
|
-
* {@link InstructionInput.
|
|
3073
|
+
* {@link InstructionInput.override} still beats it. Omitted ⇒ the built-in framing applies.
|
|
2839
3074
|
*/
|
|
2840
3075
|
export declare interface InstructionManagerOptions {
|
|
2841
3076
|
readonly on?: EmitterHooks<InstructionManagerEventMap>;
|
|
2842
|
-
/**
|
|
3077
|
+
/** Holds the emitter's listener-error handler — a listener throw routes here, not to a domain event. */
|
|
2843
3078
|
readonly error?: EmitterErrorHandler;
|
|
2844
|
-
/**
|
|
3079
|
+
/** Holds a manager-level format override (beats the provider default + built-in); see {@link AgentContextInterface.build}. */
|
|
2845
3080
|
readonly format?: ContextSectionFormat<InstructionInterface>;
|
|
2846
3081
|
}
|
|
2847
3082
|
|
|
2848
3083
|
/**
|
|
2849
|
-
*
|
|
3084
|
+
* Intersects two scope category lists under the "`undefined` is the universal set" rule — the
|
|
3085
|
+
* primitive a scope narrows through.
|
|
3086
|
+
*
|
|
3087
|
+
* @remarks
|
|
3088
|
+
* Pure and total, and it can only TIGHTEN: `undefined` ∩ `undefined` is `undefined` (still no
|
|
3089
|
+
* constraint); `undefined` ∩ a list is a COPY of that list (the `undefined` side imposes
|
|
3090
|
+
* nothing); a list ∩ a list keeps the child keys the parent also allows, so a parent-excluded
|
|
3091
|
+
* key can never be re-admitted. Every returned list is a fresh copy, so a later mutation of
|
|
3092
|
+
* either input cannot leak into the result.
|
|
3093
|
+
*
|
|
3094
|
+
* @param parent - The parent's allow-list (`undefined` ⇒ no constraint)
|
|
3095
|
+
* @param child - The narrowing allow-list (`undefined` ⇒ no constraint)
|
|
3096
|
+
* @returns The intersected allow-list, or `undefined` when neither side constrains
|
|
3097
|
+
*
|
|
3098
|
+
* @example
|
|
3099
|
+
* ```ts
|
|
3100
|
+
* intersectKeys(['read', 'write'], ['write', 'admin']) // ['write']
|
|
3101
|
+
* intersectKeys(undefined, ['read']) // ['read']
|
|
3102
|
+
* intersectKeys(undefined, undefined) // undefined
|
|
3103
|
+
* ```
|
|
3104
|
+
*/
|
|
3105
|
+
export declare function intersectKeys(parent: readonly string[] | undefined, child: readonly string[] | undefined): readonly string[] | undefined;
|
|
3106
|
+
|
|
3107
|
+
/**
|
|
3108
|
+
* Narrows an unknown caught value to an {@link AgentError}.
|
|
2850
3109
|
*
|
|
2851
3110
|
* @param value - The value to test (typically a `catch` binding)
|
|
2852
|
-
* @returns
|
|
3111
|
+
* @returns True if `value` is an {@link AgentError}; false otherwise
|
|
2853
3112
|
*
|
|
2854
3113
|
* @example
|
|
2855
3114
|
* ```ts
|
|
@@ -2863,10 +3122,10 @@ export declare interface InstructionManagerOptions {
|
|
|
2863
3122
|
export declare function isAgentError(value: unknown): value is AgentError;
|
|
2864
3123
|
|
|
2865
3124
|
/**
|
|
2866
|
-
*
|
|
3125
|
+
* Narrows an unknown caught value to an {@link AgentJobError}.
|
|
2867
3126
|
*
|
|
2868
3127
|
* @param value - The value to test (typically a `catch` binding or a rejected enqueue)
|
|
2869
|
-
* @returns
|
|
3128
|
+
* @returns True if `value` is an {@link AgentJobError}; false otherwise
|
|
2870
3129
|
*
|
|
2871
3130
|
* @example
|
|
2872
3131
|
* ```ts
|
|
@@ -2880,10 +3139,10 @@ export declare function isAgentError(value: unknown): value is AgentError;
|
|
|
2880
3139
|
export declare function isAgentJobError(value: unknown): value is AgentJobError;
|
|
2881
3140
|
|
|
2882
3141
|
/**
|
|
2883
|
-
*
|
|
3142
|
+
* Narrows an unknown caught value to a {@link ConversationError}.
|
|
2884
3143
|
*
|
|
2885
3144
|
* @param value - The value to test (typically a `catch` binding)
|
|
2886
|
-
* @returns
|
|
3145
|
+
* @returns True if `value` is a {@link ConversationError}; false otherwise
|
|
2887
3146
|
*
|
|
2888
3147
|
* @example
|
|
2889
3148
|
* ```ts
|
|
@@ -2897,7 +3156,7 @@ export declare function isAgentJobError(value: unknown): value is AgentJobError;
|
|
|
2897
3156
|
export declare function isConversationError(value: unknown): value is ConversationError;
|
|
2898
3157
|
|
|
2899
3158
|
/**
|
|
2900
|
-
*
|
|
3159
|
+
* Narrows an `unknown` to a {@link ConversationSnapshot} — the total boundary guard for an
|
|
2901
3160
|
* UNTRUSTED snapshot read (a storage row a
|
|
2902
3161
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
2903
3162
|
* reads back from its opaque JSON column, a snapshot loaded from disk). The EXACT analogue of
|
|
@@ -2907,8 +3166,8 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
2907
3166
|
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the snapshot's
|
|
2908
3167
|
* SHAPE: a `string` `id`, an OPTIONAL `string` `summary` (present-or-absent — the rollup is
|
|
2909
3168
|
* `undefined` until the first compaction), a `sections` array EVERY element of which is a valid
|
|
2910
|
-
* {@link
|
|
2911
|
-
* valid {@link
|
|
3169
|
+
* {@link Section} ({@link isSection}), and a `messages` array EVERY element of which is a
|
|
3170
|
+
* valid {@link Message} ({@link isMessage}) — enough to safely impose the
|
|
2912
3171
|
* {@link ConversationSnapshot} type at a storage boundary WITHOUT a cast. The structural twin of
|
|
2913
3172
|
* {@link import('@orkestrel/workspace').isWorkspaceSnapshot}. A malformed blob (a non-record, a missing / non-string `id`, a
|
|
2914
3173
|
* non-string `summary` when present, a non-array `sections` / `messages`, or any malformed
|
|
@@ -2917,7 +3176,7 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
2917
3176
|
* read yields `undefined` rather than a broken conversation.
|
|
2918
3177
|
*
|
|
2919
3178
|
* @param value - The value to test (an opaque storage read)
|
|
2920
|
-
* @returns
|
|
3179
|
+
* @returns True if `value` has the structural shape of a {@link ConversationSnapshot}; false otherwise
|
|
2921
3180
|
*
|
|
2922
3181
|
* @example
|
|
2923
3182
|
* ```ts
|
|
@@ -2930,9 +3189,9 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
2930
3189
|
export declare function isConversationSnapshot(value: unknown): value is ConversationSnapshot;
|
|
2931
3190
|
|
|
2932
3191
|
/**
|
|
2933
|
-
*
|
|
2934
|
-
* the {@link isConversationSnapshot} read-boundary narrow (
|
|
2935
|
-
* read
|
|
3192
|
+
* Checks whether an `unknown` is structurally a {@link Message} record — the per-message step of
|
|
3193
|
+
* the {@link isConversationSnapshot} read-boundary narrow (a total guard over an untrusted storage
|
|
3194
|
+
* read, never an assertion). The conversation analogue of
|
|
2936
3195
|
* {@link import('@orkestrel/workspace').isFile}.
|
|
2937
3196
|
*
|
|
2938
3197
|
* @remarks
|
|
@@ -2940,16 +3199,16 @@ export declare function isConversationSnapshot(value: unknown): value is Convers
|
|
|
2940
3199
|
* SHAPE: a record with a `string` `id`, a `string` `role`, a `string` `content`, and — WHEN present
|
|
2941
3200
|
* — a `calls` array EVERY element of which is a valid
|
|
2942
3201
|
* {@link import('@orkestrel/tool').ToolCall} ({@link isToolCall} — the
|
|
2943
|
-
*
|
|
3202
|
+
* fail-closed deepening: a tampered `calls` element rejects the message, so the snapshot
|
|
2944
3203
|
* reads back as absent rather than replaying a malformed call) and an `images` that is an array
|
|
2945
3204
|
* (an absent optional passes). The `role` is left as a broad `string` here (an open
|
|
2946
3205
|
* {@link import('./types.js').MessageRole}, so any storage-read role string is accepted
|
|
2947
3206
|
* defensively rather than rejected against the current literal set). Enough to safely impose the
|
|
2948
|
-
* {@link
|
|
3207
|
+
* {@link Message} type at
|
|
2949
3208
|
* a storage boundary WITHOUT a cast.
|
|
2950
3209
|
*
|
|
2951
3210
|
* @param value - The value to test (one element of a snapshot's `messages` / a section's `messages`)
|
|
2952
|
-
* @returns
|
|
3211
|
+
* @returns True if `value` has the structural shape of a {@link Message}; false otherwise
|
|
2953
3212
|
*
|
|
2954
3213
|
* @example
|
|
2955
3214
|
* ```ts
|
|
@@ -2959,13 +3218,13 @@ export declare function isConversationSnapshot(value: unknown): value is Convers
|
|
|
2959
3218
|
* isMessage({ id: '1', role: 'assistant', content: '', calls: [null] }) // false (malformed call)
|
|
2960
3219
|
* ```
|
|
2961
3220
|
*/
|
|
2962
|
-
export declare function isMessage(value: unknown): value is
|
|
3221
|
+
export declare function isMessage(value: unknown): value is Message;
|
|
2963
3222
|
|
|
2964
3223
|
/**
|
|
2965
|
-
*
|
|
3224
|
+
* Narrows an unknown caught value to a {@link ProviderAbortError}.
|
|
2966
3225
|
*
|
|
2967
3226
|
* @param value - The value to test (typically a `catch` binding)
|
|
2968
|
-
* @returns
|
|
3227
|
+
* @returns True if `value` is a {@link ProviderAbortError}; false otherwise
|
|
2969
3228
|
*
|
|
2970
3229
|
* @example
|
|
2971
3230
|
* ```ts
|
|
@@ -2979,18 +3238,18 @@ export declare function isMessage(value: unknown): value is MessageInterface;
|
|
|
2979
3238
|
export declare function isProviderAbortError(value: unknown): value is ProviderAbortError;
|
|
2980
3239
|
|
|
2981
3240
|
/**
|
|
2982
|
-
*
|
|
2983
|
-
* the {@link isConversationSnapshot} read-boundary narrow (
|
|
2984
|
-
* read
|
|
3241
|
+
* Checks whether an `unknown` is structurally a {@link Section} record — the per-section step of
|
|
3242
|
+
* the {@link isConversationSnapshot} read-boundary narrow (a total guard over an untrusted storage
|
|
3243
|
+
* read, never an assertion).
|
|
2985
3244
|
*
|
|
2986
3245
|
* @remarks
|
|
2987
3246
|
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the section's
|
|
2988
3247
|
* SHAPE: a record with a `string` `id`, a `string` `summary`, and a `messages` array EVERY element
|
|
2989
|
-
* of which is a valid {@link
|
|
2990
|
-
* the {@link
|
|
3248
|
+
* of which is a valid {@link Message} record ({@link isMessage}). Enough to safely impose
|
|
3249
|
+
* the {@link Section} type at a storage boundary WITHOUT a cast.
|
|
2991
3250
|
*
|
|
2992
3251
|
* @param value - The value to test (one element of a snapshot's `sections` array)
|
|
2993
|
-
* @returns
|
|
3252
|
+
* @returns True if `value` has the structural shape of a {@link Section}; false otherwise
|
|
2994
3253
|
*
|
|
2995
3254
|
* @example
|
|
2996
3255
|
* ```ts
|
|
@@ -2999,17 +3258,39 @@ export declare function isProviderAbortError(value: unknown): value is ProviderA
|
|
|
2999
3258
|
* isSection({ id: 's', messages: [] }) // false (missing summary)
|
|
3000
3259
|
* ```
|
|
3001
3260
|
*/
|
|
3002
|
-
export declare function isSection(value: unknown): value is
|
|
3261
|
+
export declare function isSection(value: unknown): value is Section;
|
|
3262
|
+
|
|
3263
|
+
/**
|
|
3264
|
+
* Joins the reasoning a run's provider calls separated from the answer — the first call
|
|
3265
|
+
* seeds the accumulation, a later call appends blank-line separated so each turn's reasoning
|
|
3266
|
+
* stays readable.
|
|
3267
|
+
*
|
|
3268
|
+
* @remarks
|
|
3269
|
+
* Pure and total. `running` is `undefined` until a call surfaces reasoning, so the first join
|
|
3270
|
+
* returns `next` verbatim (no leading separator). The result is display/audit metadata that
|
|
3271
|
+
* never re-enters the conversation.
|
|
3272
|
+
*
|
|
3273
|
+
* @param running - The reasoning accumulated so far (`undefined` before the first)
|
|
3274
|
+
* @param next - This call's separated reasoning
|
|
3275
|
+
* @returns The joined reasoning
|
|
3276
|
+
*
|
|
3277
|
+
* @example
|
|
3278
|
+
* ```ts
|
|
3279
|
+
* joinThinking(undefined, 'first') // 'first'
|
|
3280
|
+
* joinThinking('first', 'second') // 'first\n\nsecond'
|
|
3281
|
+
* ```
|
|
3282
|
+
*/
|
|
3283
|
+
export declare function joinThinking(running: string | undefined, next: string): string;
|
|
3003
3284
|
|
|
3004
3285
|
/**
|
|
3005
|
-
*
|
|
3286
|
+
* Implements the {@link ConversationStoreInterface} in memory — a process-lifetime `Map` of
|
|
3006
3287
|
* {@link ConversationSnapshot}s keyed by conversation id, the DEFAULT store
|
|
3007
3288
|
* {@link import('../../factories.js').createMemoryConversationStore} builds. The EXACT twin of
|
|
3008
3289
|
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore}.
|
|
3009
3290
|
*
|
|
3010
3291
|
* @remarks
|
|
3011
|
-
* A plain `Map<string, ConversationSnapshot>`
|
|
3012
|
-
* self-contained JSON, so no encoding is needed for the memory tier
|
|
3292
|
+
* A plain `Map<string, ConversationSnapshot>` — the snapshot is already pure,
|
|
3293
|
+
* self-contained JSON, so no encoding is needed for the memory tier. Like the
|
|
3013
3294
|
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore} it twins,
|
|
3014
3295
|
* there is NO idle-TTL and NO eviction: a persisted conversation lives until an explicit `delete`. A
|
|
3015
3296
|
* durable backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching
|
|
@@ -3022,14 +3303,14 @@ export declare function isSection(value: unknown): value is SectionInterface;
|
|
|
3022
3303
|
* - **`set` inserts / replaces under the snapshot's OWN `id`** (no separate id param).
|
|
3023
3304
|
* - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
3024
3305
|
*
|
|
3025
|
-
* The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the
|
|
3306
|
+
* The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the method
|
|
3026
3307
|
* bijection with {@link ConversationStoreInterface}). Hydration is a caller concern: a
|
|
3027
3308
|
* {@link import('../ConversationManager.js').ConversationManager} reads a snapshot back and rebuilds
|
|
3028
|
-
* the live conversation through the
|
|
3309
|
+
* the live conversation through the `snapshot` option (its `open` / `save`).
|
|
3029
3310
|
*
|
|
3030
3311
|
* @example
|
|
3031
3312
|
* ```ts
|
|
3032
|
-
* import { createConversation, createMemoryConversationStore } from '@
|
|
3313
|
+
* import { createConversation, createMemoryConversationStore } from '@orkestrel/agent'
|
|
3033
3314
|
*
|
|
3034
3315
|
* const store = createMemoryConversationStore()
|
|
3035
3316
|
* const conversation = createConversation()
|
|
@@ -3047,31 +3328,7 @@ export declare class MemoryConversationStore implements ConversationStoreInterfa
|
|
|
3047
3328
|
}
|
|
3048
3329
|
|
|
3049
3330
|
/**
|
|
3050
|
-
*
|
|
3051
|
-
* adds on top of a message's content estimate — accounts for the fixed wire framing every
|
|
3052
|
-
* conversation turn carries (its role tag, delimiters) that {@link import('./helpers.js').estimateTokens}'s
|
|
3053
|
-
* content-only heuristic does not otherwise capture.
|
|
3054
|
-
*/
|
|
3055
|
-
export declare const MESSAGE_TOKEN_OVERHEAD = 4;
|
|
3056
|
-
|
|
3057
|
-
/**
|
|
3058
|
-
* The minimal data needed to author a {@link MessageInterface} — the `id` is
|
|
3059
|
-
* assigned by the layer that stores it, so a caller supplies only role / content
|
|
3060
|
-
* (and, for a replayed assistant turn, its `calls`).
|
|
3061
|
-
*/
|
|
3062
|
-
export declare interface MessageInput {
|
|
3063
|
-
readonly role: MessageRole;
|
|
3064
|
-
readonly content: string;
|
|
3065
|
-
readonly calls?: readonly ToolCall[];
|
|
3066
|
-
/**
|
|
3067
|
-
* Multimodal image data for this turn — base64-encoded image strings forwarded to a
|
|
3068
|
-
* vision-capable provider (carried verbatim onto the stored {@link MessageInterface}).
|
|
3069
|
-
*/
|
|
3070
|
-
readonly images?: readonly string[];
|
|
3071
|
-
}
|
|
3072
|
-
|
|
3073
|
-
/**
|
|
3074
|
-
* One conversation turn fed to a {@link ProviderInterface} — a stored, identified
|
|
3331
|
+
* Represents one conversation turn fed to a {@link ProviderInterface} — a stored, identified
|
|
3075
3332
|
* message.
|
|
3076
3333
|
*
|
|
3077
3334
|
* @remarks
|
|
@@ -3080,14 +3337,14 @@ export declare interface MessageInput {
|
|
|
3080
3337
|
* the model sees its own decision. A `tool` turn carries the tool's result in
|
|
3081
3338
|
* `content` (the textual outcome), keyed back to the call by the conversation order.
|
|
3082
3339
|
*/
|
|
3083
|
-
export declare interface
|
|
3340
|
+
export declare interface Message {
|
|
3084
3341
|
readonly id: string;
|
|
3085
3342
|
readonly role: MessageRole;
|
|
3086
3343
|
readonly content: string;
|
|
3087
|
-
/**
|
|
3344
|
+
/** Holds an assistant turn's requested tools — its `tool_calls`, replayed. */
|
|
3088
3345
|
readonly calls?: readonly ToolCall[];
|
|
3089
3346
|
/**
|
|
3090
|
-
*
|
|
3347
|
+
* Holds multimodal image data attached to this turn — base64-encoded image strings,
|
|
3091
3348
|
* forwarded to a vision-capable provider (the provider maps them onto the wire's
|
|
3092
3349
|
* per-message `images` array). Present only on a multimodal turn; absent otherwise.
|
|
3093
3350
|
*/
|
|
@@ -3095,56 +3352,82 @@ export declare interface MessageInterface {
|
|
|
3095
3352
|
}
|
|
3096
3353
|
|
|
3097
3354
|
/**
|
|
3098
|
-
*
|
|
3099
|
-
*
|
|
3355
|
+
* Estimates the per-message role/framing overhead {@link import('./helpers.js').estimateMessages}
|
|
3356
|
+
* adds on top of a message's content estimate — accounts for the fixed wire framing every
|
|
3357
|
+
* conversation turn carries (its role tag, delimiters) that {@link import('./helpers.js').estimateTokens}'s
|
|
3358
|
+
* content-only heuristic does not otherwise capture.
|
|
3359
|
+
*/
|
|
3360
|
+
export declare const MESSAGE_TOKEN_OVERHEAD = 4;
|
|
3361
|
+
|
|
3362
|
+
/**
|
|
3363
|
+
* Carries the minimal data needed to author a {@link Message} — the `id` is
|
|
3364
|
+
* assigned by the layer that stores it, so a caller supplies only role / content
|
|
3365
|
+
* (and, for a replayed assistant turn, its `calls`).
|
|
3366
|
+
*/
|
|
3367
|
+
export declare interface MessageInput {
|
|
3368
|
+
readonly role: MessageRole;
|
|
3369
|
+
readonly content: string;
|
|
3370
|
+
readonly calls?: readonly ToolCall[];
|
|
3371
|
+
/**
|
|
3372
|
+
* Holds multimodal image data for this turn — base64-encoded image strings forwarded to a
|
|
3373
|
+
* vision-capable provider (carried verbatim onto the stored {@link Message}).
|
|
3374
|
+
*/
|
|
3375
|
+
readonly images?: readonly string[];
|
|
3376
|
+
}
|
|
3377
|
+
|
|
3378
|
+
/**
|
|
3379
|
+
* Stores immutable {@link Message}s in insertion order; `add` mints the `id`.
|
|
3100
3380
|
*
|
|
3101
3381
|
* @remarks
|
|
3102
3382
|
* - **Store.** Messages live in insertion order; `count` is how many are stored.
|
|
3103
|
-
* `add` takes one {@link MessageInput} or a batch
|
|
3383
|
+
* `add` takes one {@link MessageInput} or a batch and MINTS each message's
|
|
3104
3384
|
* `id` (a random UUID), returning the created message(s). A stored message is
|
|
3105
3385
|
* immutable — created once from its input, never mutated.
|
|
3106
3386
|
* - **Lookup.** `message(id)` resolves one by id (`undefined` when absent);
|
|
3107
3387
|
* `messages()` lists every message in insertion order.
|
|
3108
|
-
* - **Removal.** `remove` drops one by id, or a batch
|
|
3109
|
-
* removed; `clear` empties the store.
|
|
3388
|
+
* - **Removal.** `remove` drops one by id, or a batch — `true` only when EVERY supplied id
|
|
3389
|
+
* was removed; `clear` empties the store.
|
|
3110
3390
|
* - **Event-free.** A purely data store — no Emitter, no events.
|
|
3111
3391
|
*/
|
|
3112
3392
|
export declare interface MessageManagerInterface {
|
|
3113
3393
|
readonly count: number;
|
|
3114
|
-
add(input: MessageInput):
|
|
3115
|
-
add(inputs: readonly MessageInput[]): readonly
|
|
3116
|
-
message(id: string):
|
|
3117
|
-
messages(): readonly
|
|
3394
|
+
add(input: MessageInput): Message;
|
|
3395
|
+
add(inputs: readonly MessageInput[]): readonly Message[];
|
|
3396
|
+
message(id: string): Message | undefined;
|
|
3397
|
+
messages(): readonly Message[];
|
|
3118
3398
|
remove(id: string): boolean;
|
|
3119
3399
|
remove(ids: readonly string[]): boolean;
|
|
3120
3400
|
clear(): void;
|
|
3121
3401
|
}
|
|
3122
3402
|
|
|
3123
|
-
/**
|
|
3403
|
+
/** Names the role a {@link Message} plays in a conversation turn. */
|
|
3124
3404
|
export declare type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
3125
3405
|
|
|
3126
3406
|
/**
|
|
3127
|
-
*
|
|
3128
|
-
*
|
|
3129
|
-
* before the cancel.
|
|
3407
|
+
* Reports a provider stream cancelled mid-flight by its bound signal — thrown by a
|
|
3408
|
+
* {@link ProviderInterface}'s `stream`, carrying the {@link ProviderResult} assembled
|
|
3409
|
+
* from whatever streamed before the cancel.
|
|
3130
3410
|
*
|
|
3131
3411
|
* @remarks
|
|
3132
3412
|
* Lets a caller recover the partial content (and any tool calls / usage seen so far)
|
|
3133
3413
|
* on cancellation: `catch` the throw, narrow with {@link isProviderAbortError}, and
|
|
3134
|
-
* read `partial`.
|
|
3414
|
+
* read `partial`. `code` is the machine-readable condition (`'ABORT'` — the only one this
|
|
3415
|
+
* error reports), so a `catch` branches on it rather than on the message string.
|
|
3135
3416
|
*/
|
|
3136
3417
|
export declare class ProviderAbortError extends Error {
|
|
3418
|
+
/** Names the machine-readable condition — `'ABORT'`: a stream cancelled mid-flight. */
|
|
3419
|
+
readonly code: "ABORT";
|
|
3137
3420
|
readonly partial: ProviderResult;
|
|
3138
3421
|
constructor(partial: ProviderResult);
|
|
3139
3422
|
}
|
|
3140
3423
|
|
|
3141
3424
|
/**
|
|
3142
|
-
*
|
|
3425
|
+
* Represents one streamed delta a {@link ProviderInterface}'s `stream` yields — a TAGGED unit
|
|
3143
3426
|
* discriminated by the channel it belongs to, so the agent loop can re-surface the two
|
|
3144
3427
|
* channels separately (answer content vs. live reasoning) as it pumps.
|
|
3145
3428
|
*
|
|
3146
3429
|
* @remarks
|
|
3147
|
-
* The discriminant `
|
|
3430
|
+
* The discriminant `channel` names the axis that varies: a
|
|
3148
3431
|
* `'content'` delta is a chunk of the assistant ANSWER (the deltas that accumulate into
|
|
3149
3432
|
* {@link ProviderResult.content}); a `'thinking'` delta is a chunk of the model's
|
|
3150
3433
|
* REASONING the provider separated from the answer (the daemon's native
|
|
@@ -3154,15 +3437,15 @@ export declare class ProviderAbortError extends Error {
|
|
|
3154
3437
|
* as {@link ProviderResult.thinking} (the authoritative final accumulation) is.
|
|
3155
3438
|
*/
|
|
3156
3439
|
export declare type ProviderDelta = {
|
|
3157
|
-
readonly
|
|
3440
|
+
readonly channel: 'content';
|
|
3158
3441
|
readonly text: string;
|
|
3159
3442
|
} | {
|
|
3160
|
-
readonly
|
|
3443
|
+
readonly channel: 'thinking';
|
|
3161
3444
|
readonly text: string;
|
|
3162
3445
|
};
|
|
3163
3446
|
|
|
3164
3447
|
/**
|
|
3165
|
-
*
|
|
3448
|
+
* Defines the pluggable LLM inference boundary — the one contract every agent chunk depends
|
|
3166
3449
|
* on. A provider turns a conversation (plus optional tools) into either a single
|
|
3167
3450
|
* assembled {@link ProviderResult} (`generate`) or a stream of {@link ProviderDelta}s that
|
|
3168
3451
|
* RETURNS the assembled result (`stream`).
|
|
@@ -3171,35 +3454,35 @@ export declare type ProviderDelta = {
|
|
|
3171
3454
|
* - `id` is a stable per-instance trace label; `name` identifies the backend
|
|
3172
3455
|
* (`'ollama'`).
|
|
3173
3456
|
* - Both calls take an `AbortSignal` so a caller bounds the request (cancel,
|
|
3174
|
-
* deadline, or budget folded
|
|
3457
|
+
* deadline, or budget folded through `AbortSignal.any`); aborting a `stream` mid-flight
|
|
3175
3458
|
* surfaces a `ProviderAbortError` carrying the partial result.
|
|
3176
3459
|
* - `tools`, when given non-empty, advertises the callable tools for this turn.
|
|
3177
|
-
* - `options` carries the optional per-call {@link ProviderStreamOptions} (
|
|
3460
|
+
* - `options` carries the optional per-call {@link ProviderStreamOptions} (for example `think`),
|
|
3178
3461
|
* overriding the provider's constructed defaults for that one call; omitted ⇒ defaults.
|
|
3179
3462
|
*/
|
|
3180
3463
|
export declare interface ProviderInterface {
|
|
3181
3464
|
readonly id: string;
|
|
3182
3465
|
readonly name: string;
|
|
3183
3466
|
/**
|
|
3184
|
-
*
|
|
3185
|
-
* {@link
|
|
3467
|
+
* Holds the model's preferred context framing, by section kind — an OPTIONAL
|
|
3468
|
+
* {@link ContextFormat} an {@link import('./AgentContext.js').AgentContext}
|
|
3186
3469
|
* applies as the PROVIDER-DEFAULT level of its build cascade (beating the managers'
|
|
3187
3470
|
* built-in framing, beaten by a manager-options or per-item override). Omitted ⇒ the
|
|
3188
3471
|
* provider is framing-agnostic and the managers' built-in defaults apply unchanged.
|
|
3189
3472
|
*/
|
|
3190
|
-
readonly format?:
|
|
3473
|
+
readonly format?: ContextFormat | undefined;
|
|
3191
3474
|
/**
|
|
3192
|
-
*
|
|
3475
|
+
* Generates one complete turn — resolves the assembled {@link ProviderResult}.
|
|
3193
3476
|
*
|
|
3194
3477
|
* @param messages - The conversation so far
|
|
3195
3478
|
* @param signal - Bounds the request; an abort rejects the call
|
|
3196
3479
|
* @param tools - Optional tools the model may call this turn
|
|
3197
|
-
* @param options - Optional per-call {@link ProviderStreamOptions} (
|
|
3480
|
+
* @param options - Optional per-call {@link ProviderStreamOptions} (for example `think`); omitted ⇒ defaults
|
|
3198
3481
|
* @returns The assembled result (content + any tool calls + any usage)
|
|
3199
3482
|
*/
|
|
3200
|
-
generate(messages: readonly
|
|
3483
|
+
generate(messages: readonly Message[], signal: AbortSignal, tools?: readonly ToolDefinition[], options?: ProviderStreamOptions): Promise<ProviderResult>;
|
|
3201
3484
|
/**
|
|
3202
|
-
*
|
|
3485
|
+
* Streams one turn — yields {@link ProviderDelta}s (channel-tagged `content` / `thinking`
|
|
3203
3486
|
* chunks) as they arrive and RETURNS the assembled {@link ProviderResult} (the
|
|
3204
3487
|
* concatenated content + any separated reasoning + any tool calls + any usage) when the
|
|
3205
3488
|
* stream completes.
|
|
@@ -3211,14 +3494,14 @@ export declare interface ProviderInterface {
|
|
|
3211
3494
|
* @param messages - The conversation so far
|
|
3212
3495
|
* @param signal - Bounds the request; an abort throws `ProviderAbortError`
|
|
3213
3496
|
* @param tools - Optional tools the model may call this turn
|
|
3214
|
-
* @param options - Optional per-call {@link ProviderStreamOptions} (
|
|
3497
|
+
* @param options - Optional per-call {@link ProviderStreamOptions} (for example `think`); omitted ⇒ defaults
|
|
3215
3498
|
* @returns A generator of {@link ProviderDelta}s, returning the assembled result
|
|
3216
3499
|
*/
|
|
3217
|
-
stream(messages: readonly
|
|
3500
|
+
stream(messages: readonly Message[], signal: AbortSignal, tools?: readonly ToolDefinition[], options?: ProviderStreamOptions): AsyncGenerator<ProviderDelta, ProviderResult>;
|
|
3218
3501
|
}
|
|
3219
3502
|
|
|
3220
3503
|
/**
|
|
3221
|
-
*
|
|
3504
|
+
* Holds a single inference turn's structured outcome — the assembled assistant content,
|
|
3222
3505
|
* any reasoning the provider separated from it, any tool calls the model requested,
|
|
3223
3506
|
* and the token usage it reported.
|
|
3224
3507
|
*
|
|
@@ -3234,16 +3517,16 @@ export declare interface ProviderInterface {
|
|
|
3234
3517
|
*/
|
|
3235
3518
|
export declare interface ProviderResult {
|
|
3236
3519
|
readonly content: string;
|
|
3237
|
-
/**
|
|
3520
|
+
/** Carries reasoning the provider separated from the answer when present — never re-enters the conversation. */
|
|
3238
3521
|
readonly thinking?: string;
|
|
3239
|
-
/**
|
|
3522
|
+
/** Carries the tool calls the model wants when present. */
|
|
3240
3523
|
readonly tools?: readonly ToolCall[];
|
|
3241
|
-
/**
|
|
3524
|
+
/** Carries token consumption for this turn when present (from the wire's `done` line / body). */
|
|
3242
3525
|
readonly usage?: TokenUsage;
|
|
3243
3526
|
}
|
|
3244
3527
|
|
|
3245
3528
|
/**
|
|
3246
|
-
*
|
|
3529
|
+
* Carries the per-call options threaded into a {@link ProviderInterface}'s `generate` / `stream` —
|
|
3247
3530
|
* the bag a caller passes to influence ONE inference call without reconfiguring the
|
|
3248
3531
|
* provider instance.
|
|
3249
3532
|
*
|
|
@@ -3259,28 +3542,151 @@ export declare interface ProviderResult {
|
|
|
3259
3542
|
* that passes no options behaves exactly as before.
|
|
3260
3543
|
*/
|
|
3261
3544
|
export declare interface ProviderStreamOptions {
|
|
3262
|
-
/**
|
|
3545
|
+
/** Overrides the provider's reasoning preference for this call; omitted ⇒ the provider default. */
|
|
3263
3546
|
readonly think?: boolean;
|
|
3264
|
-
/**
|
|
3547
|
+
/** Constrains the response to this JSON-Schema shape (the same open record {@link ToolDefinition.parameters} uses); omitted ⇒ no constraint. */
|
|
3265
3548
|
readonly schema?: Readonly<Record<string, unknown>>;
|
|
3266
3549
|
}
|
|
3267
3550
|
|
|
3268
3551
|
/**
|
|
3269
|
-
*
|
|
3270
|
-
*
|
|
3271
|
-
*
|
|
3552
|
+
* Renders a path-addressed text body as a fenced reference block — the framing an
|
|
3553
|
+
* {@link import('./AgentContext.js').AgentContext}'s ACTIVE-workspace text-file render emits (the
|
|
3554
|
+
* active workspace is the SOLE document/image context).
|
|
3272
3555
|
*
|
|
3273
3556
|
* @remarks
|
|
3274
|
-
*
|
|
3275
|
-
*
|
|
3276
|
-
*
|
|
3277
|
-
*
|
|
3278
|
-
* {@link
|
|
3279
|
-
*
|
|
3280
|
-
*
|
|
3281
|
-
*
|
|
3282
|
-
*
|
|
3283
|
-
*
|
|
3557
|
+
* Produces `` File: <path>\n```<language>\n<content>\n``` `` — the `File:` label line, then a
|
|
3558
|
+
* fenced code block tagged with `language`, the `content` verbatim inside. Pure string assembly,
|
|
3559
|
+
* total — never throws. The one fenced-file format string for the whole module — `AgentContext.build()`
|
|
3560
|
+
* frames an active workspace's text files with it (each carries its own `language` on its
|
|
3561
|
+
* {@link import('@orkestrel/workspace').FileContent} text arm).
|
|
3562
|
+
*
|
|
3563
|
+
* @param path - The file path shown on the `File:` label line
|
|
3564
|
+
* @param language - The fenced-code language tag (for example `'typescript'`)
|
|
3565
|
+
* @param content - The file body rendered verbatim inside the fence
|
|
3566
|
+
* @returns The fenced reference block
|
|
3567
|
+
*
|
|
3568
|
+
* @example
|
|
3569
|
+
* ```ts
|
|
3570
|
+
* import { renderFencedFile } from '@orkestrel/agent'
|
|
3571
|
+
*
|
|
3572
|
+
* renderFencedFile('src/main.ts', 'typescript', 'const x = 1')
|
|
3573
|
+
* // 'File: src/main.ts\n```typescript\nconst x = 1\n```'
|
|
3574
|
+
* ```
|
|
3575
|
+
*/
|
|
3576
|
+
export declare function renderFencedFile(path: string, language: string, content: string): string;
|
|
3577
|
+
|
|
3578
|
+
/**
|
|
3579
|
+
* Renders one context section — the resolved `open`, each item's rendering, and the resolved
|
|
3580
|
+
* `close` when one exists, blank-line joined.
|
|
3581
|
+
*
|
|
3582
|
+
* @remarks
|
|
3583
|
+
* Pure and total. A section with NO items renders nothing (`undefined`), so an empty or fully
|
|
3584
|
+
* scoped-out manager stays silent — its `open` / `close` never appear without items. `close`
|
|
3585
|
+
* is the only optional slot: an unset one (there is no built-in close) drops the
|
|
3586
|
+
* trailing line.
|
|
3587
|
+
*
|
|
3588
|
+
* @typeParam T - The section item being rendered
|
|
3589
|
+
* @param open - The section's resolved leading text
|
|
3590
|
+
* @param items - The already scope-filtered items
|
|
3591
|
+
* @param render - Renders one item to its prompt text
|
|
3592
|
+
* @param close - The section's resolved trailing text, or `undefined` for none
|
|
3593
|
+
* @returns The rendered section, or `undefined` when there are no items
|
|
3594
|
+
*
|
|
3595
|
+
* @example
|
|
3596
|
+
* ```ts
|
|
3597
|
+
* renderSection('## Instructions', [{ content: 'Be terse.' }], (one) => one.content, undefined)
|
|
3598
|
+
* // '## Instructions\n\nBe terse.'
|
|
3599
|
+
* renderSection('<rules>', [], (one) => one.content, '</rules>') // undefined (no items)
|
|
3600
|
+
* ```
|
|
3601
|
+
*/
|
|
3602
|
+
export declare function renderSection<T>(open: string, items: readonly T[], render: (item: T) => string, close: string | undefined): string | undefined;
|
|
3603
|
+
|
|
3604
|
+
/**
|
|
3605
|
+
* Resolves one section's CLOSE text through the format cascade — manager-options override >
|
|
3606
|
+
* provider default.
|
|
3607
|
+
*
|
|
3608
|
+
* @remarks
|
|
3609
|
+
* Pure and total. There is NO built-in close, so a section with neither level set returns
|
|
3610
|
+
* `undefined` and {@link renderSection} appends no closing line. Paired with
|
|
3611
|
+
* {@link resolveOpen}, one level can WRAP the whole group.
|
|
3612
|
+
*
|
|
3613
|
+
* @typeParam T - The section item the manager renders
|
|
3614
|
+
* @param manager - The section source (its `format` override)
|
|
3615
|
+
* @param provider - The provider-default framing for this section, or `undefined`
|
|
3616
|
+
* @returns The section's trailing text, or `undefined` when no level sets one
|
|
3617
|
+
*
|
|
3618
|
+
* @example
|
|
3619
|
+
* ```ts
|
|
3620
|
+
* resolveClose(instructions, undefined) // undefined (no built-in close)
|
|
3621
|
+
* resolveClose(instructions, { close: '</rules>' }) // '</rules>'
|
|
3622
|
+
* ```
|
|
3623
|
+
*/
|
|
3624
|
+
export declare function resolveClose<T>(manager: ContextSectionSourceInterface<T>, provider: ContextSectionFormat<T> | undefined): string | undefined;
|
|
3625
|
+
|
|
3626
|
+
/**
|
|
3627
|
+
* Resolves ONE item's rendering through the format cascade — item override >
|
|
3628
|
+
* manager-options override > provider default > built-in rendering.
|
|
3629
|
+
*
|
|
3630
|
+
* @remarks
|
|
3631
|
+
* Pure and total. The item's own `override` is the most-specific level (a fully-rendered
|
|
3632
|
+
* string for that item alone). A manager's `render(item)` already encapsulates
|
|
3633
|
+
* `[options-override → built-in]`, so it is reached only when no higher level applies — and
|
|
3634
|
+
* there it IS the built-in rendering.
|
|
3635
|
+
*
|
|
3636
|
+
* @typeParam T - The section item being rendered (it may carry its own `override`)
|
|
3637
|
+
* @param manager - The section source (its `format` override + its built-in `render`)
|
|
3638
|
+
* @param provider - The provider-default framing for this section, or `undefined`
|
|
3639
|
+
* @param item - The item to render
|
|
3640
|
+
* @returns The item's prompt text
|
|
3641
|
+
*
|
|
3642
|
+
* @example
|
|
3643
|
+
* ```ts
|
|
3644
|
+
* resolveItem(instructions, undefined, terse) // 'Be terse.' (the built-in rendering)
|
|
3645
|
+
* resolveItem(instructions, { render: (one) => `<rule>${one.content}</rule>` }, terse)
|
|
3646
|
+
* // '<rule>Be terse.</rule>'
|
|
3647
|
+
* ```
|
|
3648
|
+
*/
|
|
3649
|
+
export declare function resolveItem<T extends {
|
|
3650
|
+
readonly override?: string;
|
|
3651
|
+
}>(manager: ContextSectionSourceInterface<T>, provider: ContextSectionFormat<T> | undefined, item: T): string;
|
|
3652
|
+
|
|
3653
|
+
/**
|
|
3654
|
+
* Resolves one section's OPEN text through the format cascade — manager-options override >
|
|
3655
|
+
* provider default > built-in header.
|
|
3656
|
+
*
|
|
3657
|
+
* @remarks
|
|
3658
|
+
* Pure and total. The leading text has NO per-item level. A manager's `open` already
|
|
3659
|
+
* encapsulates `[options-override → built-in]`, so it is reached only when neither the
|
|
3660
|
+
* override's `open` nor the provider's `open` applies — and there it IS the built-in header.
|
|
3661
|
+
*
|
|
3662
|
+
* @typeParam T - The section item the manager renders
|
|
3663
|
+
* @param manager - The section source (its `format` override + its built-in `open`)
|
|
3664
|
+
* @param provider - The provider-default framing for this section, or `undefined`
|
|
3665
|
+
* @returns The section's leading text
|
|
3666
|
+
*
|
|
3667
|
+
* @example
|
|
3668
|
+
* ```ts
|
|
3669
|
+
* resolveOpen(instructions, undefined) // '## Instructions' (the built-in header)
|
|
3670
|
+
* resolveOpen(instructions, { open: '<rules>' }) // '<rules>' (the provider default)
|
|
3671
|
+
* ```
|
|
3672
|
+
*/
|
|
3673
|
+
export declare function resolveOpen<T>(manager: ContextSectionSourceInterface<T>, provider: ContextSectionFormat<T> | undefined): string;
|
|
3674
|
+
|
|
3675
|
+
/**
|
|
3676
|
+
* Holds the immutable per-run outcome an {@link AgentInterface}'s loop settles on — the value its
|
|
3677
|
+
* run RETURNS, assembled from there into the {@link AgentResult} its `stream`'s `result`
|
|
3678
|
+
* promise resolves.
|
|
3679
|
+
*
|
|
3680
|
+
* @remarks
|
|
3681
|
+
* Computed inside one run (so concurrent runs never share state) and returned once, when the
|
|
3682
|
+
* loop settles: `content` is the streamed assistant text, `thinking` the reasoning the
|
|
3683
|
+
* provider calls separated from it ({@link ProviderResult.thinking}, joined across calls —
|
|
3684
|
+
* `undefined` when none surfaced), `usage` the summed {@link TokenUsage} (present only when
|
|
3685
|
+
* a provider call reported it), `partial` is `true` when a cancel committed the run early OR
|
|
3686
|
+
* when the loop exhausted its `limit` with unresolved tool intent, and `exhausted` is `true`
|
|
3687
|
+
* in that second case specifically (a distinct, non-cancel cause the {@link AgentEventMap}
|
|
3688
|
+
* `exhaust` event observes). It is the settled outcome one run returns, before the agent folds
|
|
3689
|
+
* it into the {@link AgentResult} its `stream`'s `result` promise resolves.
|
|
3284
3690
|
*/
|
|
3285
3691
|
export declare interface RunOutcome {
|
|
3286
3692
|
readonly content: string;
|
|
@@ -3291,7 +3697,7 @@ export declare interface RunOutcome {
|
|
|
3291
3697
|
}
|
|
3292
3698
|
|
|
3293
3699
|
/**
|
|
3294
|
-
*
|
|
3700
|
+
* Sanitizes one reported token count into a safe non-negative integer.
|
|
3295
3701
|
*
|
|
3296
3702
|
* @param value - The token count to sanitize
|
|
3297
3703
|
* @returns The floored count, or `0` when the value is non-finite or non-positive
|
|
@@ -3299,7 +3705,7 @@ export declare interface RunOutcome {
|
|
|
3299
3705
|
export declare function sanitizeToken(value: number): number;
|
|
3300
3706
|
|
|
3301
3707
|
/**
|
|
3302
|
-
*
|
|
3708
|
+
* Sanitizes a {@link TokenUsage} into safe, non-negative integers — the guard an agent's
|
|
3303
3709
|
* abort-usage path applies to a provider's partial usage before it is charged against a
|
|
3304
3710
|
* budget or folded into the run total.
|
|
3305
3711
|
*
|
|
@@ -3308,7 +3714,7 @@ export declare function sanitizeToken(value: number): number;
|
|
|
3308
3714
|
* `-Infinity`) or a negative value floors to `0`; a fractional value floors to its
|
|
3309
3715
|
* non-negative integer part. No upper cap is applied. Total — never throws.
|
|
3310
3716
|
*
|
|
3311
|
-
* @param usage - The token usage to sanitize (
|
|
3717
|
+
* @param usage - The token usage to sanitize (for example a provider's abort-partial usage)
|
|
3312
3718
|
* @returns A new {@link TokenUsage} with every field a safe non-negative integer
|
|
3313
3719
|
*
|
|
3314
3720
|
* @example
|
|
@@ -3319,14 +3725,14 @@ export declare function sanitizeToken(value: number): number;
|
|
|
3319
3725
|
export declare function sanitizeUsage(usage: TokenUsage): TokenUsage;
|
|
3320
3726
|
|
|
3321
3727
|
/**
|
|
3322
|
-
*
|
|
3323
|
-
*
|
|
3324
|
-
* identity (an instruction's `name`, a tool's `name`, a workspace file's `path`).
|
|
3728
|
+
* Represents a named, immutable filter over a richer context's items — an optional
|
|
3729
|
+
* allow-list per category (`instructions` / `tools` / `files`), each keyed by that
|
|
3730
|
+
* category's identity (an instruction's `name`, a tool's `name`, a workspace file's `path`).
|
|
3325
3731
|
*
|
|
3326
3732
|
* @remarks
|
|
3327
3733
|
* - **A category list is three-way.** `undefined` ⇒ NO constraint on that category (all
|
|
3328
3734
|
* pass); `[]` ⇒ NONE pass; a non-empty list ⇒ only the listed keys pass. The build
|
|
3329
|
-
* step / loop apply this
|
|
3735
|
+
* step / loop apply this through `filterAllowList`.
|
|
3330
3736
|
* - **Immutable.** The `id` is minted at construction; every supplied list is COPIED in
|
|
3331
3737
|
* (so a later mutation of the caller's array can't leak in), and the lists are
|
|
3332
3738
|
* `readonly`. A `Scope` is never mutated after construction — `narrow` returns a NEW
|
|
@@ -3349,19 +3755,18 @@ export declare function sanitizeUsage(usage: TokenUsage): TokenUsage;
|
|
|
3349
3755
|
* ```
|
|
3350
3756
|
*/
|
|
3351
3757
|
export declare class Scope implements ScopeInterface {
|
|
3352
|
-
#private;
|
|
3353
3758
|
readonly id: string;
|
|
3354
3759
|
readonly name: string;
|
|
3355
3760
|
readonly instructions?: readonly string[];
|
|
3356
3761
|
readonly tools?: readonly string[];
|
|
3357
3762
|
readonly files?: readonly string[];
|
|
3358
3763
|
constructor(input: ScopeInput);
|
|
3359
|
-
narrow(config:
|
|
3764
|
+
narrow(config: ScopeFilter): ScopeInterface;
|
|
3360
3765
|
}
|
|
3361
3766
|
|
|
3362
3767
|
/**
|
|
3363
|
-
*
|
|
3364
|
-
* `readonly string[]`
|
|
3768
|
+
* Lists the per-category allow-lists a {@link ScopeInterface} carries — an optional
|
|
3769
|
+
* `readonly string[]` for `instructions`, for `tools`, and for `files`, each keyed by that
|
|
3365
3770
|
* category's identity (an instruction's `name`, a tool's `name`, a workspace file's
|
|
3366
3771
|
* `path`).
|
|
3367
3772
|
*
|
|
@@ -3373,13 +3778,13 @@ export declare class Scope implements ScopeInterface {
|
|
|
3373
3778
|
* files (by `path`) in {@link AgentContextInterface.build} — both the text files folded into
|
|
3374
3779
|
* the system block and the image files attached to the last user message.
|
|
3375
3780
|
*/
|
|
3376
|
-
export declare interface
|
|
3377
|
-
/**
|
|
3781
|
+
export declare interface ScopeFilter {
|
|
3782
|
+
/** Lists the allowed instruction `name`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed). */
|
|
3378
3783
|
readonly instructions?: readonly string[];
|
|
3379
|
-
/**
|
|
3784
|
+
/** Lists the allowed tool `name`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed). */
|
|
3380
3785
|
readonly tools?: readonly string[];
|
|
3381
3786
|
/**
|
|
3382
|
-
*
|
|
3787
|
+
* Lists the allowed ACTIVE-workspace file `path`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed) —
|
|
3383
3788
|
* the filter {@link AgentContextInterface.build} applies to the active workspace's
|
|
3384
3789
|
* {@link import('@orkestrel/workspace').WorkspaceInterface.files} before rendering them (text → the system block, image →
|
|
3385
3790
|
* the last user message).
|
|
@@ -3388,16 +3793,16 @@ export declare interface ScopeConfiguration {
|
|
|
3388
3793
|
}
|
|
3389
3794
|
|
|
3390
3795
|
/**
|
|
3391
|
-
*
|
|
3796
|
+
* Carries the data to author a {@link ScopeInterface} — a {@link ScopeFilter} plus the
|
|
3392
3797
|
* required `name` (a human label; the `id` is minted by the layer that stores it).
|
|
3393
3798
|
*/
|
|
3394
|
-
export declare interface ScopeInput extends
|
|
3799
|
+
export declare interface ScopeInput extends ScopeFilter {
|
|
3395
3800
|
readonly name: string;
|
|
3396
3801
|
}
|
|
3397
3802
|
|
|
3398
3803
|
/**
|
|
3399
|
-
*
|
|
3400
|
-
* allow-lists ({@link
|
|
3804
|
+
* Represents a named, immutable filter over a richer context's items — the per-category
|
|
3805
|
+
* allow-lists ({@link ScopeFilter}) plus an `id` / `name`, and a `narrow` that
|
|
3401
3806
|
* composes a tighter child by set-INTERSECTION.
|
|
3402
3807
|
*
|
|
3403
3808
|
* @remarks
|
|
@@ -3407,22 +3812,22 @@ export declare interface ScopeInput extends ScopeConfiguration {
|
|
|
3407
3812
|
* so `undefined ∩ list = list` and `undefined ∩ undefined = undefined`. Narrowing can
|
|
3408
3813
|
* only TIGHTEN (a parent-excluded key never returns); the scope itself is never mutated.
|
|
3409
3814
|
*/
|
|
3410
|
-
export declare interface ScopeInterface extends
|
|
3815
|
+
export declare interface ScopeInterface extends ScopeFilter {
|
|
3411
3816
|
readonly id: string;
|
|
3412
3817
|
readonly name: string;
|
|
3413
3818
|
/**
|
|
3414
|
-
*
|
|
3819
|
+
* Composes a tighter child scope — its per-category set is the intersection of this
|
|
3415
3820
|
* scope's list and `config`'s (an `undefined` side imposing no constraint).
|
|
3416
3821
|
*
|
|
3417
|
-
* @param config - The narrowing allow-lists (a `name`-less {@link
|
|
3822
|
+
* @param config - The narrowing allow-lists (a `name`-less {@link ScopeFilter})
|
|
3418
3823
|
* @returns A NEW, tighter {@link ScopeInterface} (this one is left unchanged)
|
|
3419
3824
|
*/
|
|
3420
|
-
narrow(config:
|
|
3825
|
+
narrow(config: ScopeFilter): ScopeInterface;
|
|
3421
3826
|
}
|
|
3422
3827
|
|
|
3423
3828
|
/**
|
|
3424
|
-
*
|
|
3425
|
-
*
|
|
3829
|
+
* Registers the named filters a richer context reuses — immutable {@link Scope}s keyed by
|
|
3830
|
+
* their minted `id`, in insertion order.
|
|
3426
3831
|
*
|
|
3427
3832
|
* @remarks
|
|
3428
3833
|
* - **Registry.** Scopes live in an insertion-ordered `Map` keyed by their minted `id`;
|
|
@@ -3431,9 +3836,9 @@ export declare interface ScopeInterface extends ScopeConfiguration {
|
|
|
3431
3836
|
* one up, and `scopes()` lists them in insertion order. (Unlike the name-keyed
|
|
3432
3837
|
* instruction registry, a scope's key is its minted `id`, so two scopes may share a
|
|
3433
3838
|
* `name`; `create` therefore always adds — it never overwrites.)
|
|
3434
|
-
* - **Removal.** `remove` drops one by id, or a batch
|
|
3435
|
-
* removed; `clear` empties the registry.
|
|
3436
|
-
* - **Observable
|
|
3839
|
+
* - **Removal.** `remove` drops one by id, or a batch — `true` only when EVERY supplied id
|
|
3840
|
+
* was removed; `clear` empties the registry.
|
|
3841
|
+
* - **Observable.** The owned {@link emitter} ({@link ScopeManagerEventMap}) carries
|
|
3437
3842
|
* `create` (the created scope) / `remove` (the id) / `clear`. Every event is emitted
|
|
3438
3843
|
* directly, strictly AFTER the map mutation completes; the emitter isolates a listener
|
|
3439
3844
|
* throw and routes it to its `error` handler (the `error` option), so a buggy observer can
|
|
@@ -3449,7 +3854,7 @@ export declare interface ScopeInterface extends ScopeConfiguration {
|
|
|
3449
3854
|
*/
|
|
3450
3855
|
export declare class ScopeManager implements ScopeManagerInterface {
|
|
3451
3856
|
#private;
|
|
3452
|
-
constructor(
|
|
3857
|
+
constructor(options?: ScopeManagerOptions);
|
|
3453
3858
|
get emitter(): EmitterInterface<ScopeManagerEventMap>;
|
|
3454
3859
|
get count(): number;
|
|
3455
3860
|
create(input: ScopeInput): ScopeInterface;
|
|
@@ -3461,43 +3866,43 @@ export declare class ScopeManager implements ScopeManagerInterface {
|
|
|
3461
3866
|
}
|
|
3462
3867
|
|
|
3463
3868
|
/**
|
|
3464
|
-
*
|
|
3869
|
+
* Maps the push observation surface of a {@link ScopeManagerInterface} — analogous to
|
|
3465
3870
|
* {@link InstructionManagerEventMap}, but keyed by the minted `id` and carrying `create`
|
|
3466
3871
|
* (a scope always mints, never overwrites) rather than `add`.
|
|
3467
3872
|
*
|
|
3468
3873
|
* @remarks
|
|
3469
3874
|
* `create` carries the created {@link ScopeInterface}; `remove` carries the removed
|
|
3470
3875
|
* scope's `id`; `clear` is a pure signal. The emitter isolates a listener throw and routes
|
|
3471
|
-
* it to its `error` handler
|
|
3876
|
+
* it to its `error` handler. A `type` alias so it satisfies `EventMap` structurally.
|
|
3472
3877
|
*/
|
|
3473
3878
|
export declare type ScopeManagerEventMap = {
|
|
3474
|
-
/**
|
|
3879
|
+
/** Reports a scope created — the created scope. */
|
|
3475
3880
|
readonly create: readonly [scope: ScopeInterface];
|
|
3476
|
-
/**
|
|
3881
|
+
/** Reports a scope removed — its `id`. */
|
|
3477
3882
|
readonly remove: readonly [id: string];
|
|
3478
|
-
/**
|
|
3883
|
+
/** Reports every scope removed. */
|
|
3479
3884
|
readonly clear: readonly [];
|
|
3480
3885
|
};
|
|
3481
3886
|
|
|
3482
3887
|
/**
|
|
3483
|
-
*
|
|
3888
|
+
* Registers reusable {@link ScopeInterface}s keyed by their minted `id` — `create`
|
|
3484
3889
|
* mints + stores one (never overwrites), `scopes()` lists them in insertion order.
|
|
3485
3890
|
*
|
|
3486
3891
|
* @remarks
|
|
3487
|
-
* - **Registry.** `create(input)` mints a scope (an `id` + the
|
|
3892
|
+
* - **Registry.** `create(input)` mints a scope (an `id` + the per-category allow-lists) and
|
|
3488
3893
|
* stores it; `count` is how many are stored. `scope(id)` looks one up; `scopes()` lists
|
|
3489
3894
|
* them in insertion order. (Keyed by minted `id`, not `name`, so two scopes may share a
|
|
3490
3895
|
* `name` and `create` always adds.)
|
|
3491
|
-
* - **Observable
|
|
3896
|
+
* - **Observable.** The owned `emitter` ({@link ScopeManagerEventMap}) carries
|
|
3492
3897
|
* `create` / `remove` / `clear` for fire-and-forget observers; the emitter isolates a
|
|
3493
|
-
* listener throw and routes it to its `error` handler (the `error` option
|
|
3898
|
+
* listener throw and routes it to its `error` handler (the `error` option).
|
|
3494
3899
|
*/
|
|
3495
3900
|
export declare interface ScopeManagerInterface {
|
|
3496
3901
|
readonly emitter: EmitterInterface<ScopeManagerEventMap>;
|
|
3497
3902
|
readonly count: number;
|
|
3498
3903
|
create(input: ScopeInput): ScopeInterface;
|
|
3499
3904
|
scope(id: string): ScopeInterface | undefined;
|
|
3500
|
-
/**
|
|
3905
|
+
/** Lists every scope, in insertion order. */
|
|
3501
3906
|
scopes(): readonly ScopeInterface[];
|
|
3502
3907
|
remove(id: string): boolean;
|
|
3503
3908
|
remove(ids: readonly string[]): boolean;
|
|
@@ -3505,59 +3910,60 @@ export declare interface ScopeManagerInterface {
|
|
|
3505
3910
|
}
|
|
3506
3911
|
|
|
3507
3912
|
/**
|
|
3508
|
-
*
|
|
3913
|
+
* Configures `createScopeManager` — the reserved `on` hooks: initial listeners for
|
|
3509
3914
|
* the manager's {@link ScopeManagerEventMap}, wired at construction.
|
|
3510
3915
|
*/
|
|
3511
3916
|
export declare interface ScopeManagerOptions {
|
|
3512
3917
|
readonly on?: EmitterHooks<ScopeManagerEventMap>;
|
|
3513
|
-
/**
|
|
3918
|
+
/** Holds the emitter's listener-error handler — a listener throw routes here, not to a domain event. */
|
|
3514
3919
|
readonly error?: EmitterErrorHandler;
|
|
3515
3920
|
}
|
|
3516
3921
|
|
|
3517
3922
|
/**
|
|
3518
|
-
*
|
|
3923
|
+
* Holds a slice of folded messages digested into a summary — the unit of compaction a
|
|
3519
3924
|
* {@link ConversationInterface} produces when it `compact`s its live tail.
|
|
3520
3925
|
*
|
|
3521
3926
|
* @remarks
|
|
3522
|
-
* `summary` is the model-written digest of this slice (
|
|
3523
|
-
* {@link
|
|
3927
|
+
* `summary` is the model-written digest of this slice (through the
|
|
3928
|
+
* {@link ConversationSummaryHandler}); `messages` are the folded ORIGINALS, RETAINED in full so
|
|
3524
3929
|
* `rehydrate` can pull them back and `search` can scan them (compaction shrinks the model
|
|
3525
3930
|
* INPUT, never discards history).
|
|
3526
3931
|
*/
|
|
3527
|
-
export declare interface
|
|
3932
|
+
export declare interface Section {
|
|
3528
3933
|
readonly id: string;
|
|
3529
|
-
/**
|
|
3934
|
+
/** Holds the model-written digest of this slice (its {@link ConversationSummaryHandler} output). */
|
|
3530
3935
|
readonly summary: string;
|
|
3531
|
-
/**
|
|
3532
|
-
readonly messages: readonly
|
|
3936
|
+
/** Retains the folded original messages in full for `rehydrate` / `search`. */
|
|
3937
|
+
readonly messages: readonly Message[];
|
|
3533
3938
|
}
|
|
3534
3939
|
|
|
3535
3940
|
/**
|
|
3536
|
-
*
|
|
3941
|
+
* Runs one rehydrated agent and applies the partial-as-configurable-failure policy — the
|
|
3537
3942
|
* shared job-handler step BOTH `createAgentQueue` and `createAgentRunner` settle each job
|
|
3538
3943
|
* through, so the policy can never diverge between them.
|
|
3539
3944
|
*
|
|
3540
3945
|
* @remarks
|
|
3541
3946
|
* A turn that committed PARTIAL (a cancel — abort / budget / timeout) is by default a
|
|
3542
3947
|
* FAILURE, so it THROWS an {@link import('./errors.js').AgentJobError} carrying the partial
|
|
3543
|
-
* (the Queue's retries + a Runner's fail-fast then engage);
|
|
3544
|
-
*
|
|
3948
|
+
* (the Queue's retries + a Runner's fail-fast then engage); the `partial` policy RESOLVES
|
|
3949
|
+
* it as success instead. A natural finish ALWAYS resolves with its result.
|
|
3545
3950
|
*
|
|
3546
3951
|
* @param agent - The rehydrated {@link AgentInterface} to run to its {@link AgentResult}
|
|
3547
|
-
* @param
|
|
3548
|
-
* (the default policy), a partial result throws an {@link AgentJobError}
|
|
3549
|
-
* @returns The agent's {@link AgentResult} (a natural finish, or a partial
|
|
3550
|
-
*
|
|
3952
|
+
* @param partial - The partial policy. If `true`, a partial result resolves as success; if
|
|
3953
|
+
* `false` (the default policy), a partial result throws an {@link AgentJobError}
|
|
3954
|
+
* @returns The agent's {@link AgentResult} (a natural finish, or a partial one under the
|
|
3955
|
+
* `partial` policy)
|
|
3956
|
+
* @throws {AgentJobError} Thrown when the run ended partial and the `partial` policy is `false`
|
|
3551
3957
|
*
|
|
3552
3958
|
* @example
|
|
3553
3959
|
* ```ts
|
|
3554
3960
|
* const result = await settleAgentJob(registry.build(input, signal), false)
|
|
3555
3961
|
* ```
|
|
3556
3962
|
*/
|
|
3557
|
-
export declare function settleAgentJob(agent: AgentInterface,
|
|
3963
|
+
export declare function settleAgentJob(agent: AgentInterface, partial: boolean): Promise<AgentResult>;
|
|
3558
3964
|
|
|
3559
3965
|
/**
|
|
3560
|
-
*
|
|
3966
|
+
* Pairs a live event stream with the eventual settled result and a cancel — the
|
|
3561
3967
|
* generic pull/streaming handle a long-running operation hands back.
|
|
3562
3968
|
*
|
|
3563
3969
|
* @remarks
|
|
@@ -3573,7 +3979,7 @@ export declare interface StreamInterface<T, R> {
|
|
|
3573
3979
|
readonly events: AsyncIterable<T>;
|
|
3574
3980
|
readonly result: Promise<R>;
|
|
3575
3981
|
/**
|
|
3576
|
-
*
|
|
3982
|
+
* Cancels the in-flight operation — fires its bound signal.
|
|
3577
3983
|
*
|
|
3578
3984
|
* @param reason - An optional cancellation reason propagated to the signal
|
|
3579
3985
|
*/
|
|
@@ -3581,14 +3987,36 @@ export declare interface StreamInterface<T, R> {
|
|
|
3581
3987
|
}
|
|
3582
3988
|
|
|
3583
3989
|
/**
|
|
3584
|
-
*
|
|
3990
|
+
* Adds two {@link TokenUsage} values field by field — the running total an agent run keeps
|
|
3991
|
+
* across its provider calls.
|
|
3992
|
+
*
|
|
3993
|
+
* @remarks
|
|
3994
|
+
* Pure and total: the first call seeds the total (`running` `undefined` returns `next`
|
|
3995
|
+
* unchanged), later calls accumulate. No sanitization happens here — charge a provider's
|
|
3996
|
+
* reported usage through {@link sanitizeUsage} first.
|
|
3997
|
+
*
|
|
3998
|
+
* @param running - The total so far (`undefined` before the first usage-bearing call)
|
|
3999
|
+
* @param next - This call's reported usage
|
|
4000
|
+
* @returns The summed usage
|
|
4001
|
+
*
|
|
4002
|
+
* @example
|
|
4003
|
+
* ```ts
|
|
4004
|
+
* sumUsage(undefined, { prompt: 2, completion: 1, total: 3 }) // { prompt: 2, completion: 1, total: 3 }
|
|
4005
|
+
* sumUsage({ prompt: 2, completion: 1, total: 3 }, { prompt: 1, completion: 1, total: 2 })
|
|
4006
|
+
* // { prompt: 3, completion: 2, total: 5 }
|
|
4007
|
+
* ```
|
|
4008
|
+
*/
|
|
4009
|
+
export declare function sumUsage(running: TokenUsage | undefined, next: TokenUsage): TokenUsage;
|
|
4010
|
+
|
|
4011
|
+
/**
|
|
4012
|
+
* Names the closing tag that ends a {@link THINK_OPEN} reasoning span. A span the stream never closes
|
|
3585
4013
|
* (the model was cut off mid-reasoning) is treated as thinking to its end —
|
|
3586
4014
|
* {@link import('./types.js').ThinkSplitterInterface.flush} settles it.
|
|
3587
4015
|
*/
|
|
3588
4016
|
export declare const THINK_CLOSE = "</think>";
|
|
3589
4017
|
|
|
3590
4018
|
/**
|
|
3591
|
-
*
|
|
4019
|
+
* Names the opening tag a {@link import('./ThinkSplitter.js').ThinkSplitter} recognizes as the start of
|
|
3592
4020
|
* an in-content reasoning span — the de-facto wire convention thinking models (qwen3, DeepSeek-R1
|
|
3593
4021
|
* family) emit their chain-of-thought under when a daemon renders it inline instead of on a
|
|
3594
4022
|
* separate wire field. Paired with {@link THINK_CLOSE}.
|
|
@@ -3596,10 +4024,10 @@ export declare const THINK_CLOSE = "</think>";
|
|
|
3596
4024
|
export declare const THINK_OPEN = "<think>";
|
|
3597
4025
|
|
|
3598
4026
|
/**
|
|
3599
|
-
*
|
|
3600
|
-
*
|
|
3601
|
-
*
|
|
3602
|
-
*
|
|
4027
|
+
* Feeds raw content deltas through a tiny stream-stateful state machine that routes
|
|
4028
|
+
* everything inside a `<think>…</think>` span to `thinking` and returns everything outside
|
|
4029
|
+
* it as clean content, so a provider yields ONLY the answer and surfaces the reasoning as
|
|
4030
|
+
* {@link import('./types.js').ProviderResult.thinking}.
|
|
3603
4031
|
*
|
|
3604
4032
|
* @remarks
|
|
3605
4033
|
* - **Cross-chunk tags.** A tag may arrive split across wire deltas (`'<thi'` then
|
|
@@ -3615,7 +4043,7 @@ export declare const THINK_OPEN = "<think>";
|
|
|
3615
4043
|
* prefix cannot be recalled, so `content` is the authoritative accumulation). The
|
|
3616
4044
|
* rule is ONE-SHOT: after any tag event a bare `</think>` is plain text.
|
|
3617
4045
|
* - **Multiple spans** accumulate onto `thinking` in stream order. A nested-looking
|
|
3618
|
-
* `<think>` inside an open span is
|
|
4046
|
+
* `<think>` inside an open span is thinking text (no nesting is tracked — the
|
|
3619
4047
|
* first `</think>` closes the span), matching how the models emit it.
|
|
3620
4048
|
* - **Unclosed span at stream end.** `flush()` routes the open span's tail (including
|
|
3621
4049
|
* any held partial close tag) to `thinking` — a cut-off model was still reasoning.
|
|
@@ -3641,10 +4069,9 @@ export declare class ThinkSplitter implements ThinkSplitterInterface {
|
|
|
3641
4069
|
}
|
|
3642
4070
|
|
|
3643
4071
|
/**
|
|
3644
|
-
*
|
|
3645
|
-
*
|
|
3646
|
-
*
|
|
3647
|
-
* {@link ProviderResult.thinking}.
|
|
4072
|
+
* Splits a thinking model's in-content `<think>…</think>` reasoning spans away from the
|
|
4073
|
+
* answer, delta by delta with per-stream state, so a provider yields ONLY clean content
|
|
4074
|
+
* and surfaces the reasoning as {@link ProviderResult.thinking}.
|
|
3648
4075
|
*
|
|
3649
4076
|
* @remarks
|
|
3650
4077
|
* - **Stateful across deltas.** A tag may arrive SPLIT across wire chunks (`'<thi'`
|
|
@@ -3652,9 +4079,9 @@ export declare class ThinkSplitter implements ThinkSplitterInterface {
|
|
|
3652
4079
|
* back until the next delta (or `flush`) disambiguates it, so a partial tag is
|
|
3653
4080
|
* never leaked as content and never mis-eaten as thinking.
|
|
3654
4081
|
* - **`split(delta)`** feeds one raw content delta and returns the CLEAN content to
|
|
3655
|
-
* surface for it (possibly `''` —
|
|
4082
|
+
* surface for it (possibly `''` — for example mid-think). Text inside a
|
|
3656
4083
|
* `<think>…</think>` span accumulates on `thinking`; multiple spans accumulate in
|
|
3657
|
-
* order; a nested-looking `<think>` inside an open span is
|
|
4084
|
+
* order; a nested-looking `<think>` inside an open span is thinking text (no
|
|
3658
4085
|
* nesting — the first `</think>` closes).
|
|
3659
4086
|
* - **The IMPLICIT leading open (the qwen3-template shape).** Some chat templates
|
|
3660
4087
|
* PRE-SEED `<think>` into the prompt scaffold, so the wire stream begins
|
|
@@ -3675,27 +4102,27 @@ export declare class ThinkSplitter implements ThinkSplitterInterface {
|
|
|
3675
4102
|
* one per call ({@link import('./factories.js').createThinkSplitter}).
|
|
3676
4103
|
*/
|
|
3677
4104
|
export declare interface ThinkSplitterInterface {
|
|
3678
|
-
/**
|
|
4105
|
+
/** Holds the AUTHORITATIVE clean content accumulated so far (corrected across an implicit-open reclassification). */
|
|
3679
4106
|
readonly content: string;
|
|
3680
|
-
/**
|
|
4107
|
+
/** Holds the reasoning text accumulated from every `<think>…</think>` span so far. */
|
|
3681
4108
|
readonly thinking: string;
|
|
3682
|
-
/**
|
|
4109
|
+
/** Feeds one raw delta; returns the clean (non-think) content to surface for it. */
|
|
3683
4110
|
split(delta: string): string;
|
|
3684
|
-
/**
|
|
4111
|
+
/** Settles the stream end — returns any held clean tail; an unclosed think span lands on `thinking`. */
|
|
3685
4112
|
flush(): string;
|
|
3686
4113
|
}
|
|
3687
4114
|
|
|
3688
4115
|
/**
|
|
3689
|
-
*
|
|
4116
|
+
* Names the section header {@link import('./AgentContext.js').AgentContext}'s `build()` renders the
|
|
3690
4117
|
* ACTIVE workspace's TEXT files under — the leading line of the dedicated workspace block in the
|
|
3691
4118
|
* system message, the carrier-split counterpart to the documents / images section headers.
|
|
3692
4119
|
*
|
|
3693
4120
|
* @remarks
|
|
3694
4121
|
* `build()` OWNS the workspace render (a `Workspace` / `WorkspaceManager` stays file-focused — no
|
|
3695
|
-
* `
|
|
4122
|
+
* `open` / `format` getters), so this header lives here as the agents module's one
|
|
3696
4123
|
* workspace-section framing constant rather than on a manager. Each workspace text file renders
|
|
3697
4124
|
* beneath it as a fenced `` File: <path>\n```<language>\n<text>\n``` `` block — the SAME framing
|
|
3698
|
-
* the documents section uses — placed
|
|
4125
|
+
* the documents section uses — placed immediately after the documents section in the system block.
|
|
3699
4126
|
*/
|
|
3700
4127
|
export declare const WORKSPACE_SECTION_HEADER = "## Workspace";
|
|
3701
4128
|
|