@orkestrel/agent 0.0.20 → 0.0.21
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 +10 -10
- package/dist/src/core/index.cjs +414 -329
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +907 -724
- package/dist/src/core/index.d.ts +907 -724
- package/dist/src/core/index.js +414 -329
- package/dist/src/core/index.js.map +1 -1
- package/package.json +21 -22
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import { BudgetInterface } from '@orkestrel/budget';
|
|
2
|
-
import { ControllerInterface } from '@orkestrel/workflow';
|
|
3
|
-
import { DriverInterface } from '@orkestrel/database';
|
|
4
|
-
import { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
5
|
-
import { EmitterHooks } from '@orkestrel/emitter';
|
|
6
|
-
import { EmitterInterface } from '@orkestrel/emitter';
|
|
7
|
-
import { FileInterface } from '@orkestrel/workspace';
|
|
8
|
-
import { JSONValue } from '@orkestrel/contract';
|
|
9
|
-
import { QueueContext } from '@orkestrel/queue';
|
|
10
|
-
import { QueueInterface } from '@orkestrel/queue';
|
|
11
|
-
import { QueueStoreInterface } from '@orkestrel/queue';
|
|
12
|
-
import { RunnerInterface } from '@orkestrel/workflow';
|
|
13
|
-
import { SchedulerInterface } from '@orkestrel/workflow';
|
|
14
|
-
import { TableInterface } from '@orkestrel/database';
|
|
15
|
-
import { TokenUsage } from '@orkestrel/budget';
|
|
16
|
-
import { ToolCall } from '@orkestrel/tool';
|
|
17
|
-
import { ToolDefinition } from '@orkestrel/tool';
|
|
18
|
-
import { ToolInterface } from '@orkestrel/tool';
|
|
19
|
-
import { ToolManagerInterface } from '@orkestrel/tool';
|
|
20
|
-
import { ToolResult } from '@orkestrel/tool';
|
|
21
|
-
import { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
1
|
+
import type { BudgetInterface } from '@orkestrel/budget';
|
|
2
|
+
import type { ControllerInterface } from '@orkestrel/workflow';
|
|
3
|
+
import type { DriverInterface } from '@orkestrel/database';
|
|
4
|
+
import type { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
5
|
+
import type { EmitterHooks } from '@orkestrel/emitter';
|
|
6
|
+
import type { EmitterInterface } from '@orkestrel/emitter';
|
|
7
|
+
import type { FileInterface } from '@orkestrel/workspace';
|
|
8
|
+
import type { JSONValue } from '@orkestrel/contract';
|
|
9
|
+
import type { QueueContext } from '@orkestrel/queue';
|
|
10
|
+
import type { QueueInterface } from '@orkestrel/queue';
|
|
11
|
+
import type { QueueStoreInterface } from '@orkestrel/queue';
|
|
12
|
+
import type { RunnerInterface } from '@orkestrel/workflow';
|
|
13
|
+
import type { SchedulerInterface } from '@orkestrel/workflow';
|
|
14
|
+
import type { TableInterface } from '@orkestrel/database';
|
|
15
|
+
import type { TokenUsage } from '@orkestrel/budget';
|
|
16
|
+
import type { ToolCall } from '@orkestrel/tool';
|
|
17
|
+
import type { ToolDefinition } from '@orkestrel/tool';
|
|
18
|
+
import type { ToolInterface } from '@orkestrel/tool';
|
|
19
|
+
import type { ToolManagerInterface } from '@orkestrel/tool';
|
|
20
|
+
import type { ToolResult } from '@orkestrel/tool';
|
|
21
|
+
import type { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
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
|
|
26
|
-
*
|
|
25
|
+
* {@link ToolManagerInterface} into a bounded context → provider → tools → repeat turn, exposed
|
|
26
|
+
* as both a one-shot `generate` and a live `stream` that share one private run — bounded by the
|
|
27
|
+
* run `signal`, the `timeout`, and the `budget` folded through `AbortSignal.any`, paced by
|
|
28
|
+
* `scheduler`, with tool iteration capped at `limit`.
|
|
27
29
|
*
|
|
28
30
|
* @remarks
|
|
29
31
|
* - **One loop, two faces.** A single private async generator (`#run`) drives the
|
|
@@ -40,15 +42,15 @@ import { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
|
40
42
|
* assistant message and stop.
|
|
41
43
|
* - **Bounded.** Each run arms one cancel through `createAbort({ signal: AbortSignal.any([
|
|
42
44
|
* …]) })` folding the external `signal`, the `timeout` deadline, and the `budget`
|
|
43
|
-
* signal; `abort()` fires it. Any trip stops the loop and commits a
|
|
44
|
-
* (the `result` promise
|
|
45
|
+
* signal; `abort()` fires it. Any trip stops the loop and commits a partial result
|
|
46
|
+
* (the `result` promise resolves, never rejects, on a cancel) — only a genuine
|
|
45
47
|
* provider / tool error rejects.
|
|
46
48
|
* - **Paced + capped.** The `scheduler` (when given) `yield`s between turns; tool
|
|
47
49
|
* iteration is capped at `limit`.
|
|
48
|
-
* - **Two observation surfaces.** The
|
|
49
|
-
* deltas (+ usage/tool chunks); the
|
|
50
|
+
* - **Two observation surfaces.** The pull {@link AgentChunk} stream carries per-token
|
|
51
|
+
* deltas (+ usage/tool chunks); the push {@link emitter} ({@link AgentEventMap}) carries
|
|
50
52
|
* lifecycle + usage/tool/deny moments for fire-and-forget observers. Every event is
|
|
51
|
-
* emitted directly,
|
|
53
|
+
* emitted directly, after the relevant state transition / settle; the emitter isolates a
|
|
52
54
|
* listener throw and routes it to its `error` handler (the `error` option), so a buggy
|
|
53
55
|
* observer can never escape into / reorder / corrupt the settle-once loop — observation is
|
|
54
56
|
* purely a side-channel.
|
|
@@ -74,15 +76,15 @@ export declare class Agent implements AgentInterface {
|
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
78
|
* 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.
|
|
79
|
+
* by the `category` of step it carries, and the pull surface beside the push {@link AgentEventMap}.
|
|
78
80
|
*
|
|
79
81
|
* @remarks
|
|
80
82
|
* - `token` — a content delta the provider streamed (the `'content'`
|
|
81
83
|
* {@link ProviderDelta}s a {@link ProviderInterface}'s `stream` yields), re-surfaced for
|
|
82
|
-
* live rendering of the assistant
|
|
84
|
+
* live rendering of the assistant answer.
|
|
83
85
|
* - `think` — a reasoning delta the provider streamed (the `'thinking'`
|
|
84
86
|
* {@link ProviderDelta}s, the daemon's native `message.thinking` channel), surfaced so a
|
|
85
|
-
* consumer can stream the model's reasoning
|
|
87
|
+
* consumer can stream the model's reasoning live into a collapsible; never answer content
|
|
86
88
|
* (it is never fed into the accumulated `content`).
|
|
87
89
|
* - `tool` — a {@link ToolCall} the loop dispatched paired with its {@link ToolResult},
|
|
88
90
|
* emitted once the tool ran (so a consumer sees what was called and what came back).
|
|
@@ -107,58 +109,59 @@ export declare type AgentChunk = {
|
|
|
107
109
|
/**
|
|
108
110
|
* Assembles a provider request from the richer turn context — the optional system prompt, the
|
|
109
111
|
* observable context managers (instructions / workspaces), the
|
|
110
|
-
* {@link ConversationManagerInterface} message source
|
|
111
|
-
*
|
|
112
|
-
* {@link AgentContextInterface.apply}.
|
|
112
|
+
* {@link ConversationManagerInterface} message source whose active conversation is `messages`, the
|
|
113
|
+
* {@link ToolManagerInterface} registry, and an active {@link ScopeInterface} changed through
|
|
114
|
+
* {@link AgentContextInterface.apply}. `build()` folds the scoped managers and the active
|
|
115
|
+
* workspace into one system block, then the conversation, and never reads `tools`.
|
|
113
116
|
*
|
|
114
117
|
* @remarks
|
|
115
118
|
* - **Composition.** `system` is the optional system prompt; `instructions` / `tools` /
|
|
116
119
|
* `workspaces` / `conversations` are the registries passed in `options` (bring your own), or
|
|
117
|
-
* fresh empty ones when omitted (so `workspaces` is
|
|
118
|
-
* conversation's live tail (
|
|
120
|
+
* fresh empty ones when omitted (so `workspaces` is always present); `messages` is the active
|
|
121
|
+
* conversation's live tail (always defined — see the following item). `scope` is the active filter —
|
|
119
122
|
* `undefined` (the default) ⇒ no filtering; change it through `apply(scope)`. The structural
|
|
120
123
|
* `workspaces` / `conversations` registries are fixed at construction; switch their active
|
|
121
124
|
* members through their own `switch(id)` methods.
|
|
122
|
-
* - **The message source — the conversation registry's
|
|
123
|
-
* {@link ConversationManagerInterface}; the context
|
|
124
|
-
* (at construction it `add`s a default when the manager has none), so the
|
|
125
|
-
* getter — `this.#conversations.active` — is
|
|
126
|
-
* conversation
|
|
125
|
+
* - **The message source — the conversation registry's active conversation.** `conversations` is a
|
|
126
|
+
* {@link ConversationManagerInterface}; the context ensures it always has an active conversation
|
|
127
|
+
* (at construction it `add`s a default when the manager has none), so the dynamic `messages`
|
|
128
|
+
* getter — `this.#conversations.active` — is always defined. `messages` returns the active
|
|
129
|
+
* conversation itself (it owns the live tail + the message verbs directly, satisfying
|
|
127
130
|
* {@link MessageManagerInterface} structurally — the same reference, no duplication), and
|
|
128
131
|
* `build()` folds that conversation's `view()` (its per-section summaries + live tail) as the
|
|
129
|
-
*
|
|
132
|
+
* authoritative message inclusion — the scope does not filter the conversation (it owns inclusion
|
|
130
133
|
* through compaction; scope filters only instructions / tools / workspace files). Because `messages`
|
|
131
|
-
* is read dynamically, an agent
|
|
132
|
-
* conversation
|
|
134
|
+
* is read dynamically, an agent switches the active
|
|
135
|
+
* conversation between runs (`conversations.switch(id)`) to serve many threads (the real
|
|
133
136
|
* multi-conversation pattern); switch between runs, not during a run, and use separate agents
|
|
134
137
|
* for concurrent threads.
|
|
135
138
|
* - **`build(format?)` — the scoped assembly + the format cascade.** It folds, in order,
|
|
136
|
-
* the system prompt then the scope-filtered instructions → the
|
|
139
|
+
* the system prompt then the scope-filtered instructions → the active workspace's text files
|
|
137
140
|
* (each as a block: the section's resolved `open` text, each item's resolved rendering, then
|
|
138
|
-
* any resolved `close` text) into
|
|
139
|
-
* one part exists), then appends the
|
|
140
|
-
* message inclusion through compaction — the scope does
|
|
141
|
+
* any resolved `close` text) into one leading `system` message (prepended only when at least
|
|
142
|
+
* one part exists), then appends the active conversation's `view()` (the conversation owns
|
|
143
|
+
* message inclusion through compaction — the scope does not filter the conversation). Each
|
|
141
144
|
* `open` / item / `close`
|
|
142
|
-
* resolves
|
|
143
|
-
* per-section default) is the
|
|
145
|
+
* resolves independently, most-specific-first — `build()`'s optional `format` (a provider's
|
|
146
|
+
* per-section default) is the provider level: `open` = manager-options-override > provider >
|
|
144
147
|
* built-in; per item = item-override > manager-options-override > provider > built-in; `close` =
|
|
145
|
-
* manager-options-override > provider (
|
|
146
|
-
* {@link AgentContextInterface.build}). Passing
|
|
148
|
+
* manager-options-override > provider (no built-in ⇒ no closing line when unset) (see
|
|
149
|
+
* {@link AgentContextInterface.build}). Passing no `format` (and with no overrides / no per-item
|
|
147
150
|
* override) reproduces the built-in framing byte-for-byte (each section is its built-in header +
|
|
148
151
|
* items, no closing line). The active workspace's scoped-in image files' `base64` payload is attached to
|
|
149
|
-
* the
|
|
152
|
+
* the last user message (a vision provider reads images off a user turn); when no user message
|
|
150
153
|
* exists the attachment is skipped. Built fresh each call (recomputed, never cached), so it
|
|
151
154
|
* always reflects the current managers / messages / scope / active workspace; it never mutates a
|
|
152
155
|
* manager or the stored messages.
|
|
153
|
-
* - **The
|
|
156
|
+
* - **The active workspace, rendered by carrier — the sole document/image context.**
|
|
154
157
|
* `workspaces.active` (when set) has its {@link import('@orkestrel/workspace').FileInterface}s scope-filtered by `scope.files`,
|
|
155
|
-
* then split:
|
|
156
|
-
* blocks — placed right after the instructions section), and
|
|
157
|
-
* to the last user message.
|
|
158
|
-
* workspace nothing renders for workspaces. `build()`
|
|
158
|
+
* then split: text files fold into a dedicated `## Workspace` system section (fenced reference
|
|
159
|
+
* blocks — placed right after the instructions section), and image files' `base64` payload attaches
|
|
160
|
+
* to the last user message. Active-only — never the other registered workspaces; with no active
|
|
161
|
+
* workspace nothing renders for workspaces. `build()` owns this render (a `Workspace` /
|
|
159
162
|
* `WorkspaceManager` stays file-focused).
|
|
160
163
|
* - **Tools are structural, not in the prompt.** The registry is advertised to the provider
|
|
161
|
-
* through `tools.definitions()` (scope-filtered by the loop),
|
|
164
|
+
* through `tools.definitions()` (scope-filtered by the loop), never serialized into the
|
|
162
165
|
* message array — so `build()`'s output carries no tool content, scoped or not.
|
|
163
166
|
* - **Event-free context; observable managers.** The context itself owns no Emitter; the
|
|
164
167
|
* context managers each carry their own (the push observation surface).
|
|
@@ -194,12 +197,12 @@ export declare class AgentContext implements AgentContextInterface {
|
|
|
194
197
|
* (`instructions` / `workspaces` / `conversations`), `messages` (the active
|
|
195
198
|
* conversation's live tail, satisfying {@link MessageManagerInterface}), and the current `scope`
|
|
196
199
|
* (the active {@link ScopeInterface} filter, or `undefined` for no filtering). `build()` folds the
|
|
197
|
-
* scoped instructions into
|
|
198
|
-
* each item through its `render`) —
|
|
199
|
-
* (rendered as fenced reference blocks) — and appends the
|
|
200
|
-
* the active workspace's scope-filtered image files' `base64` payload to the
|
|
201
|
-
* active workspace is the
|
|
202
|
-
*
|
|
200
|
+
* scoped instructions into one leading `system` message (under the manager's `open`,
|
|
201
|
+
* each item through its `render`) — plus the active workspace's scope-filtered text files
|
|
202
|
+
* (rendered as fenced reference blocks) — and appends the active conversation's `view()`, attaching
|
|
203
|
+
* the active workspace's scope-filtered image files' `base64` payload to the last user message. The
|
|
204
|
+
* active workspace is the sole document/image context. Tools are advertised to the provider
|
|
205
|
+
* structurally (through `tools.definitions()`, scope-filtered by the loop), not serialized into
|
|
203
206
|
* the prompt, so they never appear in `build()`'s output. The context managers are observable
|
|
204
207
|
* (their own `emitter`s); the context itself is event-free.
|
|
205
208
|
*/
|
|
@@ -207,32 +210,32 @@ export declare interface AgentContextInterface {
|
|
|
207
210
|
readonly system: string | undefined;
|
|
208
211
|
readonly instructions: InstructionManagerInterface;
|
|
209
212
|
/**
|
|
210
|
-
* Holds the {@link WorkspaceManagerInterface} whose
|
|
213
|
+
* Holds the {@link WorkspaceManagerInterface} whose active workspace `build()` renders by carrier —
|
|
211
214
|
* its text files folded into the system block (fenced reference blocks) and its image files'
|
|
212
|
-
* `base64` payload attached to the
|
|
213
|
-
* document/image context.
|
|
214
|
-
* `build()` reads its `active` (and the active workspace's `files()`)
|
|
215
|
+
* `base64` payload attached to the last user message. The active workspace is the sole
|
|
216
|
+
* document/image context. Always present (a fresh empty manager when none was supplied).
|
|
217
|
+
* `build()` reads its `active` (and the active workspace's `files()`) fresh each call. With no
|
|
215
218
|
* active workspace, nothing is rendered for workspaces. Active-only — never the other registered
|
|
216
219
|
* workspaces.
|
|
217
220
|
*/
|
|
218
221
|
readonly workspaces: WorkspaceManagerInterface;
|
|
219
222
|
/**
|
|
220
|
-
* Holds the active conversation's
|
|
223
|
+
* Holds the active conversation's live tail — the agent's message source, always defined (the
|
|
221
224
|
* {@link conversations} registry always has an active conversation; a default is added at
|
|
222
|
-
* construction). It
|
|
225
|
+
* construction). It is the active {@link ConversationInterface} itself (which satisfies
|
|
223
226
|
* {@link MessageManagerInterface} structurally), so appends through `messages` route to the
|
|
224
227
|
* active conversation's tail and `build()` folds its `view()`. Computed dynamically (it follows
|
|
225
|
-
* `conversations.switch(id)`), the
|
|
228
|
+
* `conversations.switch(id)`), the same reference the active conversation exposes — no
|
|
226
229
|
* duplication.
|
|
227
230
|
*/
|
|
228
231
|
readonly messages: MessageManagerInterface;
|
|
229
232
|
/**
|
|
230
|
-
* Holds the {@link ConversationManagerInterface} the message source flows from — `messages`
|
|
231
|
-
*
|
|
233
|
+
* Holds the {@link ConversationManagerInterface} the message source flows from — `messages` is its
|
|
234
|
+
* active conversation's live tail and `build()` folds that conversation's `view()`. Always holds
|
|
232
235
|
* an active conversation (a default is added at construction when none was supplied), so
|
|
233
236
|
* `messages` is always defined. Switch the active conversation through
|
|
234
|
-
* `conversations.switch(id)` — so one agent can serve
|
|
235
|
-
* request). Switch
|
|
237
|
+
* `conversations.switch(id)` — so one agent can serve many conversations (set the active one per
|
|
238
|
+
* request). Switch between runs, not during one; for concurrent threads use separate agents.
|
|
236
239
|
*/
|
|
237
240
|
readonly conversations: ConversationManagerInterface;
|
|
238
241
|
/**
|
|
@@ -243,7 +246,8 @@ export declare interface AgentContextInterface {
|
|
|
243
246
|
/** Holds the active scope applied at `build()` time + the loop's tool-advertise step (`undefined` ⇒ no filtering). */
|
|
244
247
|
readonly scope: ScopeInterface | undefined;
|
|
245
248
|
/**
|
|
246
|
-
* Applies the active per-turn
|
|
249
|
+
* Applies the given scope as the active per-turn filter; passing `undefined` explicitly
|
|
250
|
+
* removes filtering.
|
|
247
251
|
*
|
|
248
252
|
* @param scope - The scope to apply, or `undefined` to remove the active filter
|
|
249
253
|
*
|
|
@@ -255,51 +259,57 @@ export declare interface AgentContextInterface {
|
|
|
255
259
|
*/
|
|
256
260
|
apply(scope: ScopeInterface | undefined): void;
|
|
257
261
|
/**
|
|
258
|
-
* Builds the provider input for the next turn: a leading `system` message folding the
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
262
|
+
* Builds the provider input for the next turn: a leading `system` message folding the
|
|
263
|
+
* prompt, the scope-filtered instructions (each section's header and each item's rendering
|
|
264
|
+
* resolved through the format cascade), and the active workspace's scope-filtered
|
|
265
|
+
* (`scope.files`) text files as fenced reference blocks in a `## Workspace` section, then
|
|
266
|
+
* the active conversation's `view()`, with the active workspace's image files' `base64`
|
|
267
|
+
* payload attached to the last user message. Takes an optional `format` — typically
|
|
268
|
+
* `provider.format`, the provider level of the cascade — and omitting it with no overrides
|
|
269
|
+
* set renders each section on its manager's built-in framing. The `system` message is
|
|
270
|
+
* prepended only when some part of it exists, the workspace render covers the active
|
|
271
|
+
* workspace alone, tools are advertised structurally rather than in the prompt, and the
|
|
272
|
+
* input is built fresh on each call.
|
|
263
273
|
*
|
|
264
274
|
* @remarks
|
|
265
|
-
* **The active workspace (rendered by carrier) — the
|
|
275
|
+
* **The active workspace (rendered by carrier) — the sole document/image context.** When
|
|
266
276
|
* `workspaces.active` is set, its
|
|
267
277
|
* {@link import('@orkestrel/workspace').WorkspaceInterface.files} are filtered by
|
|
268
278
|
* `scope.files` (a three-way allow-list; `undefined` ⇒ all active files), then split by
|
|
269
|
-
* carrier:
|
|
279
|
+
* carrier: text files ({@link import('@orkestrel/workspace').isText}) render into a dedicated
|
|
270
280
|
* `## Workspace` section in the system block — each a fenced
|
|
271
281
|
* `` File: <path>\n```<language>\n<text>\n``` `` block — placed immediately after the instructions
|
|
272
282
|
* section; binary files whose MIME starts with `image/` have their `base64` payload
|
|
273
|
-
* attached to the
|
|
274
|
-
*
|
|
283
|
+
* attached to the last user message (a vision provider reads images off a user turn).
|
|
284
|
+
* Active-only — never the other registered workspaces; with no active workspace nothing is
|
|
275
285
|
* rendered for workspaces.
|
|
276
286
|
*
|
|
277
287
|
* **The format cascade.** Each manager section frames as `[open, ...items.map(render), close]`
|
|
278
288
|
* (empty / absent slots dropped, the survivors `\n\n`-joined). The `open` (the section's
|
|
279
289
|
* leading text), each item's `render`, and the `close` (the section's trailing text)
|
|
280
|
-
* resolve
|
|
290
|
+
* resolve independently, most-specific-first, from a {@link ContextSectionFormat} at each
|
|
281
291
|
* level — an item override, a manager-options override, the provider `format` default,
|
|
282
292
|
* and the manager's built-in. For the `instructions` section kind `K`, manager
|
|
283
293
|
* `M`, and the supplied `format` `F`:
|
|
284
294
|
* - **open** = `M.format?.open ?? F?.[K]?.open ?? M.open` — that is,
|
|
285
295
|
* **manager-options override > provider default > built-in** (the leading text has no
|
|
286
|
-
* per-item level). The manager
|
|
296
|
+
* per-item level). The manager encapsulates the `[options-override → built-in]` half:
|
|
287
297
|
* `M.open` already returns the options override's `open` when one is set, else
|
|
288
|
-
* the built-in header — so `build()` only layers the provider default
|
|
298
|
+
* the built-in header — so `build()` only layers the provider default between them.
|
|
289
299
|
* - **item** `I` = `I.override ?? M.format?.render?.(I) ?? F?.[K]?.render?.(I) ?? M.render(I)`
|
|
290
300
|
* — that is, **item override > manager-options override > provider default > built-in**.
|
|
291
301
|
* Again `M.render(I)` already returns the options override when set, else the
|
|
292
|
-
* built-in, so `build()` layers the per-item `I.override`
|
|
293
|
-
* default
|
|
302
|
+
* built-in, so `build()` layers the per-item `I.override` on top and the provider
|
|
303
|
+
* default between.
|
|
294
304
|
* - **close** = `M.format?.close ?? F?.[K]?.close` — that is, **manager-options
|
|
295
|
-
* override > provider default**, with
|
|
305
|
+
* override > provider default**, with no built-in floor (the trailing text has no
|
|
296
306
|
* per-item level): unset at both levels ⇒ `undefined` ⇒ no closing line. Paired with
|
|
297
|
-
* `open`, it lets a level
|
|
307
|
+
* `open`, it lets a level wrap the group (`open: '<instructions>'` … `close: '</instructions>'`).
|
|
298
308
|
*
|
|
299
|
-
* Passing
|
|
300
|
-
* output is
|
|
309
|
+
* Passing no `format` (the default) leaves the provider-default level empty, so the
|
|
310
|
+
* output is byte-for-byte the managers' built-in framing — every section is its
|
|
301
311
|
* built-in header + items, with no closing line (the regression contract). Scope
|
|
302
|
-
* filtering runs
|
|
312
|
+
* filtering runs before formatting (unchanged); the workspace image-data attachment to the
|
|
303
313
|
* last user message is unchanged.
|
|
304
314
|
*
|
|
305
315
|
* @param format - The provider's optional {@link ContextFormat} default
|
|
@@ -312,7 +322,10 @@ export declare interface AgentContextInterface {
|
|
|
312
322
|
}
|
|
313
323
|
|
|
314
324
|
/**
|
|
315
|
-
* Configures `createAgentContext` — the
|
|
325
|
+
* Configures `createAgentContext` — the optional system prompt plus the pre-built managers to
|
|
326
|
+
* reuse: an `instructions` registry, a `workspaces` registry (the only document channel), a
|
|
327
|
+
* `conversations` registry (the message source), a `tools` registry (the loop's advertise and
|
|
328
|
+
* dispatch surface), and an initial `scope`.
|
|
316
329
|
*
|
|
317
330
|
* @remarks
|
|
318
331
|
* `system` is the optional system prompt prepended to the turn's input. `instructions` /
|
|
@@ -322,10 +335,10 @@ export declare interface AgentContextInterface {
|
|
|
322
335
|
* initial active filter applied at `build()` time (and at the loop's tool-advertise step); it
|
|
323
336
|
* defaults to `undefined` — no filtering — and can be changed through the context's `apply`
|
|
324
337
|
* method afterwards. `conversations` is the structural {@link ConversationManagerInterface} the
|
|
325
|
-
* context's message source flows from: `messages`
|
|
338
|
+
* context's message source flows from: `messages` is the manager's active conversation's live tail
|
|
326
339
|
* and `build()` folds that conversation's `view()` (section summaries + live). When omitted, a fresh
|
|
327
340
|
* {@link ConversationManagerInterface} is created and a default conversation is added (so
|
|
328
|
-
* `messages` is
|
|
341
|
+
* `messages` is always defined). All default to a context with no system prompt, empty registries,
|
|
329
342
|
* no scope, and a fresh conversation registry holding one default conversation.
|
|
330
343
|
*/
|
|
331
344
|
export declare interface AgentContextOptions {
|
|
@@ -339,21 +352,21 @@ export declare interface AgentContextOptions {
|
|
|
339
352
|
readonly instructions?: InstructionManagerInterface;
|
|
340
353
|
/**
|
|
341
354
|
* Reuses a pre-built {@link WorkspaceManagerInterface}; a fresh empty one is created when
|
|
342
|
-
* omitted (so `context.workspaces` is
|
|
355
|
+
* omitted (so `context.workspaces` is always present). `build()` renders the active workspace's
|
|
343
356
|
* files by carrier — text files into the system block (fenced), image files attached to the last
|
|
344
357
|
* user message. The registry is structural; change its active workspace through
|
|
345
|
-
* `workspaces.switch(id)`. The active workspace is the
|
|
358
|
+
* `workspaces.switch(id)`. The active workspace is the sole document/image context.
|
|
346
359
|
*/
|
|
347
360
|
readonly workspaces?: WorkspaceManagerInterface;
|
|
348
361
|
/** Sets the initial active scope (the build-time filter); `undefined` ⇒ no filtering. */
|
|
349
362
|
readonly scope?: ScopeInterface;
|
|
350
363
|
/**
|
|
351
364
|
* Reuses a pre-built {@link ConversationManagerInterface} as the message source; a fresh
|
|
352
|
-
* empty one is created when omitted. The context
|
|
353
|
-
* (it `add`s a default when the manager has none), so `messages` — the manager's
|
|
354
|
-
* conversation's
|
|
355
|
-
* `view()` (the per-section summaries + the live tail) as its
|
|
356
|
-
* the scope does
|
|
365
|
+
* empty one is created when omitted. The context ensures an active conversation at construction
|
|
366
|
+
* (it `add`s a default when the manager has none), so `messages` — the manager's active
|
|
367
|
+
* conversation's live tail — is always defined. `build()` folds the active conversation's
|
|
368
|
+
* `view()` (the per-section summaries + the live tail) as its authoritative message inclusion —
|
|
369
|
+
* the scope does not filter the conversation (it owns inclusion through compaction; scope filters
|
|
357
370
|
* only instructions / tools / workspace files). The registry is structural; change its active
|
|
358
371
|
* conversation through the manager's `switch(id)`.
|
|
359
372
|
*/
|
|
@@ -361,13 +374,16 @@ export declare interface AgentContextOptions {
|
|
|
361
374
|
}
|
|
362
375
|
|
|
363
376
|
/**
|
|
364
|
-
* Reports a concurrent run that would corrupt
|
|
377
|
+
* Reports a concurrent run that would corrupt shared per-agent accounting, or a rehydration
|
|
365
378
|
* name absent from its registry pool — thrown synchronously by an {@link AgentInterface}'s
|
|
366
|
-
* `stream()` and by
|
|
367
|
-
* `code
|
|
379
|
+
* `stream()` (and so by `generate()`, which calls it) and by an
|
|
380
|
+
* {@link AgentRegistryInterface}'s accessors, carrying the machine-readable `code`
|
|
381
|
+
* `'CONCURRENCY' | 'REGISTRY'`. Synchronous means a fire-and-forget
|
|
382
|
+
* `agent.generate().catch(…)` never catches it: `await` the call inside `try`/`catch`, or wrap
|
|
383
|
+
* the call expression itself.
|
|
368
384
|
*
|
|
369
385
|
* @remarks
|
|
370
|
-
* `'CONCURRENCY'` reports a run already in flight on the same agent,
|
|
386
|
+
* `'CONCURRENCY'` reports a run already in flight on the same agent, plus a construction-level
|
|
371
387
|
* `window` (a shared context budget) or a construction-level `budget` with no per-run override
|
|
372
388
|
* (a shared cost budget) — a second concurrent `stream()` would race its charges against the
|
|
373
389
|
* same shared instance, corrupting the accounting. Use separate agents, or per-run `budget`
|
|
@@ -382,26 +398,26 @@ export declare class AgentError extends Error {
|
|
|
382
398
|
}
|
|
383
399
|
|
|
384
400
|
/**
|
|
385
|
-
* Maps the push observation surface of an {@link AgentInterface} — the
|
|
386
|
-
*
|
|
387
|
-
*
|
|
401
|
+
* Maps the push observation surface of an {@link AgentInterface} — the lifecycle, usage, and tool
|
|
402
|
+
* moments a fire-and-forget observer (logging, metrics, tracing) subscribes to, beside the pull
|
|
403
|
+
* {@link AgentChunk} stream.
|
|
388
404
|
*
|
|
389
405
|
* @remarks
|
|
390
|
-
* Push vs. pull: the Emitter carries the loop's
|
|
406
|
+
* Push vs. pull: the Emitter carries the loop's lifecycle moments (a run begins /
|
|
391
407
|
* each turn / a settle / a cancel) plus usage and dispatched-tool events — the things
|
|
392
408
|
* the chunk stream can't express (a `deny` never reaches the stream) or that a
|
|
393
|
-
* fire-and-forget observer wants without draining the stream.
|
|
394
|
-
*
|
|
395
|
-
* deliberately
|
|
409
|
+
* fire-and-forget observer wants without draining the stream. Per-token deltas stay
|
|
410
|
+
* exclusively the {@link AgentChunk} stream's job (the pull surface) — there is
|
|
411
|
+
* deliberately no `token` event here. Subscribe through `agent.emitter.on(...)`.
|
|
396
412
|
*
|
|
397
413
|
* 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
|
|
414
|
+
* — every event is emitted directly and a listener throw is routed to the emitter's own
|
|
399
415
|
* `error` handler (the `error` option), never onto this domain map and never into the
|
|
400
416
|
* settle-once / wake-park engine — so a buggy observer can never reorder, throw into, or
|
|
401
417
|
* corrupt the run.
|
|
402
418
|
*
|
|
403
|
-
* A cancelled run emits `abort` (the cancel signal)
|
|
404
|
-
*
|
|
419
|
+
* A cancelled run emits `abort` (the cancel signal) and then `finish` (the settled
|
|
420
|
+
* partial result) — so an observer sees both that the run was cancelled and the partial
|
|
405
421
|
* outcome it committed; a genuine error emits `error` instead of `finish`.
|
|
406
422
|
*
|
|
407
423
|
* Declared as a `type` alias (not `interface extends EventMap` — `EventMap` is a
|
|
@@ -418,9 +434,9 @@ export declare type AgentEventMap = {
|
|
|
418
434
|
readonly tool: readonly [call: ToolCall, result: ToolResult];
|
|
419
435
|
/** Reports a turn's {@link TokenUsage} — emitted after a usage-bearing provider call. */
|
|
420
436
|
readonly usage: readonly [usage: TokenUsage];
|
|
421
|
-
/** Reports a call the authority
|
|
437
|
+
/** Reports a call the authority denied — the call + the optional reason (not in the chunk stream). */
|
|
422
438
|
readonly deny: readonly [call: ToolCall, reason: string | undefined];
|
|
423
|
-
/** Reports the run settled successfully (a natural finish
|
|
439
|
+
/** Reports the run settled successfully (a natural finish or a cancel's partial) — the {@link AgentResult}. */
|
|
424
440
|
readonly finish: readonly [result: AgentResult];
|
|
425
441
|
/** Reports the run settled with a genuine (non-cancel) error — the thrown value (always `unknown`). */
|
|
426
442
|
readonly error: readonly [error: unknown];
|
|
@@ -429,20 +445,20 @@ export declare type AgentEventMap = {
|
|
|
429
445
|
/**
|
|
430
446
|
* Reports the loop exhausting its `limit` while still holding unresolved tool intent (the model
|
|
431
447
|
* requested tools on the very last allowed turn) — the turn count reached. Distinct from
|
|
432
|
-
* `abort`: exhaustion is
|
|
433
|
-
* this fires
|
|
448
|
+
* `abort`: exhaustion is not a cancel (no external signal / timeout / budget tripped), so
|
|
449
|
+
* this fires instead of `abort`, still followed by `finish` carrying the partial result.
|
|
434
450
|
*/
|
|
435
451
|
readonly exhaust: readonly [turns: number];
|
|
436
452
|
/**
|
|
437
|
-
* Reports
|
|
453
|
+
* Reports automatic compaction's summarizer throwing — a non-fatal warn channel (the run continues; see
|
|
438
454
|
* {@link AgentOptions.window}). When the loop's between-turns / pre-first-turn auto-compaction
|
|
439
|
-
* (`conversation.compact()`) rejects, the run does
|
|
455
|
+
* (`conversation.compact()`) rejects, the run does not crash: the loop skips compaction that
|
|
440
456
|
* turn and surfaces the caught error here so the failure is observable, never silently lost.
|
|
441
|
-
* The run still
|
|
457
|
+
* The run still settles through the other events — `finish` for the lenient default, and
|
|
442
458
|
* `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
|
|
444
|
-
* `conversation.compact()` still propagates its own error; only the agent's
|
|
445
|
-
* resilient. A
|
|
459
|
+
* the best-effort optimization that failed and never the run's own outcome. A manual
|
|
460
|
+
* `conversation.compact()` still propagates its own error; only the agent's auto path is
|
|
461
|
+
* resilient. A domain event (the emitter isolates a listener throw separately, routing it to
|
|
446
462
|
* its `error` handler).
|
|
447
463
|
*/
|
|
448
464
|
readonly fault: readonly [error: unknown];
|
|
@@ -453,7 +469,7 @@ export declare type AgentEventMap = {
|
|
|
453
469
|
* {@link ToolManagerInterface} into a bounded context → provider → tools → repeat turn.
|
|
454
470
|
*
|
|
455
471
|
* @remarks
|
|
456
|
-
* - **One loop, two faces.** `generate` and `stream` share
|
|
472
|
+
* - **One loop, two faces.** `generate` and `stream` share one private run, so they
|
|
457
473
|
* can never diverge: `generate` drains the same stream `stream` exposes, then
|
|
458
474
|
* resolves its settled {@link AgentResult}.
|
|
459
475
|
* - **Bounded.** Each turn arms a single cancel folded from the external `signal`, the
|
|
@@ -461,11 +477,11 @@ export declare type AgentEventMap = {
|
|
|
461
477
|
* or `abort()` — stops the loop and settles the result `partial: true`.
|
|
462
478
|
* - **Paced + capped.** The `scheduler` (when given) yields between turns; tool
|
|
463
479
|
* iteration is capped at `limit` so the loop always terminates.
|
|
464
|
-
* - **Two observation surfaces.**
|
|
465
|
-
* carries per-token answer deltas, per-think reasoning deltas, and usage/tool chunks for a live consumer.
|
|
480
|
+
* - **Two observation surfaces.** Pull: the {@link AgentChunk} stream (`stream().events`)
|
|
481
|
+
* carries per-token answer deltas, per-think reasoning deltas, and usage/tool chunks for a live consumer. Push: the
|
|
466
482
|
* {@link emitter} ({@link AgentEventMap}) carries lifecycle + usage/tool/deny moments
|
|
467
483
|
* 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
|
|
484
|
+
* its `error` handler (the `error` option), so a buggy observer can never corrupt the
|
|
469
485
|
* loop. Per-token / per-thinking deltas are the stream's job exclusively; there is no
|
|
470
486
|
* `token` or `think` event.
|
|
471
487
|
* - **Per-run overrides.** Both faces accept an optional {@link AgentRunOptions} bag whose
|
|
@@ -477,14 +493,14 @@ export declare interface AgentInterface {
|
|
|
477
493
|
readonly status: AgentStatus;
|
|
478
494
|
readonly context: AgentContextInterface;
|
|
479
495
|
/**
|
|
480
|
-
* Runs the turn to completion, discarding the live chunks — drains the shared
|
|
481
|
-
*
|
|
496
|
+
* Runs the turn to completion, discarding the live chunks — drains the shared stream and
|
|
497
|
+
* resolves the settled {@link AgentResult} (`partial: true` when cancelled).
|
|
482
498
|
*
|
|
483
499
|
* @remarks
|
|
484
500
|
* A concurrent run on a shared accounting agent throws an
|
|
485
501
|
* {@link import('./errors.js').AgentError} (`code: 'CONCURRENCY'`) — and it throws
|
|
486
|
-
*
|
|
487
|
-
* `agent.generate().catch(...)` therefore will
|
|
502
|
+
* synchronously, before any `Promise` is returned. A fire-and-forget
|
|
503
|
+
* `agent.generate().catch(...)` therefore will not catch it (the throw happens on the call
|
|
488
504
|
* itself, ahead of the `.catch` ever attaching) — `await` the call (inside a `try`/`catch`)
|
|
489
505
|
* or wrap the call expression itself in `try`/`catch`.
|
|
490
506
|
*
|
|
@@ -495,11 +511,12 @@ export declare interface AgentInterface {
|
|
|
495
511
|
generate(options?: AgentRunOptions): Promise<AgentResult>;
|
|
496
512
|
/**
|
|
497
513
|
* Runs the turn as a live stream — iterate `events` for {@link AgentChunk}s and
|
|
498
|
-
* `await result` for the settled outcome
|
|
514
|
+
* `await result` for the settled outcome; `result` resolves partial on a cancel and rejects
|
|
515
|
+
* on a genuine error.
|
|
499
516
|
*
|
|
500
517
|
* @remarks
|
|
501
518
|
* Like `generate()`, a concurrent run on a shared accounting agent throws an
|
|
502
|
-
* {@link import('./errors.js').AgentError} (`code: 'CONCURRENCY'`)
|
|
519
|
+
* {@link import('./errors.js').AgentError} (`code: 'CONCURRENCY'`) synchronously — before the
|
|
503
520
|
* {@link AgentStreamInterface} handle is even returned, so it cannot be caught by chaining
|
|
504
521
|
* off the (never-produced) handle; wrap the call itself in `try`/`catch`.
|
|
505
522
|
*
|
|
@@ -520,13 +537,13 @@ export declare interface AgentInterface {
|
|
|
520
537
|
/**
|
|
521
538
|
* Reports an {@link AgentInterface} run that ended {@link AgentResult.partial} under a
|
|
522
539
|
* `partial` policy of `false` (the default) — thrown by an agent-job handler (a
|
|
523
|
-
* `createAgentQueue` / `createAgentRunner` job), carrying the partial
|
|
524
|
-
*
|
|
540
|
+
* `createAgentQueue` / `createAgentRunner` job), carrying the partial {@link AgentResult} so
|
|
541
|
+
* the failure stays inspectable, and the machine-readable `code` `'PARTIAL'`.
|
|
525
542
|
*
|
|
526
543
|
* @remarks
|
|
527
544
|
* A partial result means the agent was cancelled (an external `signal` abort, a queue /
|
|
528
545
|
* runner abort threaded in, a `timeout` deadline, or an exhausted token `budget`) rather
|
|
529
|
-
* than finishing naturally. For a durable
|
|
546
|
+
* than finishing naturally. For a durable job that is a failure by default: throwing this
|
|
530
547
|
* lets the Queue's retries re-run the job and a Runner's fail-fast abort its siblings.
|
|
531
548
|
* Set `partial: true` (see `AgentQueueOptions` / `AgentRunnerOptions`) to treat a
|
|
532
549
|
* partial as success instead, in which case this is never thrown. Narrow a caught value
|
|
@@ -543,11 +560,11 @@ export declare class AgentJobError extends Error {
|
|
|
543
560
|
}
|
|
544
561
|
|
|
545
562
|
/**
|
|
546
|
-
* Represents a JSON-serializable agent job — the descriptor a durable queue
|
|
547
|
-
* non-serializable pieces (the provider, tools, authority, scheduler) are referenced by
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
563
|
+
* Represents a JSON-serializable agent job — the descriptor a durable queue or runner runs. Its
|
|
564
|
+
* non-serializable pieces (the provider, tools, authority, scheduler) are referenced by name and
|
|
565
|
+
* resolved to live objects through an {@link AgentRegistryInterface} at handler time, while its
|
|
566
|
+
* data fields (the seed `messages`, `system`, `limit`, `timeout`, and a token `budget` ceiling)
|
|
567
|
+
* carry directly.
|
|
551
568
|
*
|
|
552
569
|
* @remarks
|
|
553
570
|
* Because every field is JSON-serializable, a job survives a crash through the Queue's
|
|
@@ -581,7 +598,7 @@ export declare interface AgentJobInput {
|
|
|
581
598
|
/**
|
|
582
599
|
* Lists the sub-agent jobs this job fans out — each a nested {@link AgentJobInput} (so the whole
|
|
583
600
|
* tree stays serializable). On a `createAgentRunner`, the handler `controller.spawn`s
|
|
584
|
-
* each child through the same bounded queue
|
|
601
|
+
* each child through the same bounded queue before running this (parent) job, so the
|
|
585
602
|
* children run as sibling sub-agents and their results join the run after the declared
|
|
586
603
|
* jobs (in spawn order). Ignored by `createAgentQueue` (a queue has no fan-out).
|
|
587
604
|
*/
|
|
@@ -589,7 +606,11 @@ export declare interface AgentJobInput {
|
|
|
589
606
|
}
|
|
590
607
|
|
|
591
608
|
/**
|
|
592
|
-
* Configures `createAgent` — bounds and pacing
|
|
609
|
+
* Configures `createAgent` — the loop's bounds and pacing, the reserved `on` hooks, the
|
|
610
|
+
* construction-time context wiring (`instructions` / `workspaces` / `scope`), the `conversations`
|
|
611
|
+
* registry that is the message source, the context `window` budget that opts into automatic
|
|
612
|
+
* compaction of the active conversation, and the `strict` switch that aborts the run on an
|
|
613
|
+
* automatic-compaction summarizer failure instead of the lenient default.
|
|
593
614
|
*
|
|
594
615
|
* @remarks
|
|
595
616
|
* - `system` — an optional system prompt prepended to the turn (seeds the context).
|
|
@@ -609,16 +630,16 @@ export declare interface AgentJobInput {
|
|
|
609
630
|
* - `signal` — an optional external `AbortSignal` whose abort cancels the turn (a
|
|
610
631
|
* partial result).
|
|
611
632
|
* - `conversations` — an optional {@link ConversationManagerInterface} forwarded to the agent's
|
|
612
|
-
* context as the message source (so `context.messages` is its
|
|
633
|
+
* context as the message source (so `context.messages` is its active conversation's live tail);
|
|
613
634
|
* omitted ⇒ a fresh registry holding one default conversation. Auto-compaction (`window`) folds
|
|
614
|
-
* the
|
|
615
|
-
* - `window` — an optional
|
|
616
|
-
* compaction: when set, the loop measures the
|
|
635
|
+
* the active conversation when it is summarizable.
|
|
636
|
+
* - `window` — an optional context {@link BudgetInterface} for automatic conversation
|
|
637
|
+
* compaction: when set, the loop measures the current full prompt against this budget each turn
|
|
617
638
|
* (its `consumer` is a token estimator, its `max` the context window) and, when the prompt
|
|
618
|
-
* reaches the window
|
|
639
|
+
* reaches the window and the active conversation is summarizable, compacts the active
|
|
619
640
|
* conversation + continues on the rebuilt smaller view — compact-and-continue, distinct from
|
|
620
641
|
* `budget`'s hard abort. Omitted ⇒ no auto-compaction.
|
|
621
|
-
* - `strict` — when `true`, a summarizer failure during
|
|
642
|
+
* - `strict` — when `true`, a summarizer failure during automatic compaction aborts the run
|
|
622
643
|
* (rethrown after the `fault` event, propagating through `#run` to a genuine `error`
|
|
623
644
|
* settle) instead of skipping compaction and continuing over-window. Defaults to `false`
|
|
624
645
|
* (lenient — the prior, byte-for-byte behavior).
|
|
@@ -663,27 +684,27 @@ export declare interface AgentOptions {
|
|
|
663
684
|
*/
|
|
664
685
|
readonly authority?: AuthorityInterface;
|
|
665
686
|
/**
|
|
666
|
-
* Holds an optional {@link ConversationManagerInterface} that becomes the agent context's
|
|
667
|
-
*
|
|
668
|
-
* `agent.context.messages`
|
|
687
|
+
* Holds an optional {@link ConversationManagerInterface} that becomes the agent context's message
|
|
688
|
+
* source — forwarded to the {@link AgentContextInterface} the agent builds, so
|
|
689
|
+
* `agent.context.messages` is its active conversation's live tail and `build()` folds that
|
|
669
690
|
* conversation's `view()` (the per-section summaries + the live tail). Omitted ⇒ a fresh
|
|
670
|
-
* registry holding one default conversation. With `window` set,
|
|
671
|
-
*
|
|
691
|
+
* registry holding one default conversation. With `window` set, automatic compaction folds the
|
|
692
|
+
* active conversation between turns (when it is summarizable).
|
|
672
693
|
*/
|
|
673
694
|
readonly conversations?: ConversationManagerInterface;
|
|
674
695
|
/**
|
|
675
|
-
* Holds an optional
|
|
696
|
+
* Holds an optional context {@link BudgetInterface} for automatic compaction. Its `consumer` is a
|
|
676
697
|
* token estimator (for example the exported {@link import('./helpers.js').estimateMessages}) and
|
|
677
|
-
* its `max` is the context window. When set, the loop measures the
|
|
678
|
-
* next provider request) against this budget each turn; when that prompt reaches the window
|
|
698
|
+
* its `max` is the context window. When set, the loop measures the current full prompt (the
|
|
699
|
+
* next provider request) against this budget each turn; when that prompt reaches the window and
|
|
679
700
|
* the active conversation is summarizable, it **compacts the active conversation + continues on
|
|
680
701
|
* the rebuilt smaller view** (compact-and-continue) — the same consume-to-a-ceiling primitive
|
|
681
702
|
* as the cost `budget`, but compaction is the ceiling action instead of abort. Omit to disable.
|
|
682
703
|
*/
|
|
683
704
|
readonly window?: BudgetInterface<readonly Message[]>;
|
|
684
705
|
/**
|
|
685
|
-
* If `true`, a summarizer failure during
|
|
686
|
-
* `fault` event still fires, then the caught error is
|
|
706
|
+
* If `true`, a summarizer failure during automatic compaction aborts the run — the
|
|
707
|
+
* `fault` event still fires, then the caught error is rethrown so the run settles
|
|
687
708
|
* `error` instead of continuing over-window. Defaults to `false` (lenient — the run
|
|
688
709
|
* continues over-window, byte-for-byte the prior behavior).
|
|
689
710
|
*/
|
|
@@ -698,9 +719,9 @@ export declare interface AgentOptions {
|
|
|
698
719
|
* - `registry` — the {@link AgentRegistryInterface} the handler rehydrates each job
|
|
699
720
|
* through (required).
|
|
700
721
|
* - `partial` — the partial policy. A partial {@link AgentResult} (a job committed
|
|
701
|
-
* early from an abort / budget / timeout) is by
|
|
722
|
+
* early from an abort / budget / timeout) is by default a failure: the handler throws
|
|
702
723
|
* an {@link import('./errors.js').AgentJobError}, so the Queue's retries (and a
|
|
703
|
-
* Runner's fail-fast) engage. Set `true` to treat a partial as
|
|
724
|
+
* Runner's fail-fast) engage. Set `true` to treat a partial as success instead — the
|
|
704
725
|
* handler resolves the partial result rather than throwing.
|
|
705
726
|
* - `concurrency` / `retries` / `timeout` / `store` — passed straight to the backing
|
|
706
727
|
* `QueueInterface` (see `QueueOptions`): bounded concurrency, the retry budget, the
|
|
@@ -708,7 +729,7 @@ export declare interface AgentOptions {
|
|
|
708
729
|
*/
|
|
709
730
|
export declare interface AgentQueueOptions {
|
|
710
731
|
readonly registry: AgentRegistryInterface;
|
|
711
|
-
/** If `true`, a partial `AgentResult` resolves as success; if `false` (the default), it
|
|
732
|
+
/** If `true`, a partial `AgentResult` resolves as success; if `false` (the default), it throws and retries engage. */
|
|
712
733
|
readonly partial?: boolean;
|
|
713
734
|
readonly concurrency?: number;
|
|
714
735
|
readonly retries?: number;
|
|
@@ -717,9 +738,10 @@ export declare interface AgentQueueOptions {
|
|
|
717
738
|
}
|
|
718
739
|
|
|
719
740
|
/**
|
|
720
|
-
* Makes a durable, JSON-serializable {@link AgentJobInput} runnable — holds the named
|
|
721
|
-
*
|
|
722
|
-
*
|
|
741
|
+
* Makes a durable, JSON-serializable {@link AgentJobInput} runnable — holds the named pools of
|
|
742
|
+
* live, non-serializable pieces (providers, tools, authorities, schedulers), throws on a name
|
|
743
|
+
* absent from its pool, and `build`s a seeded, signal-wired {@link Agent} from a job's names and
|
|
744
|
+
* data.
|
|
723
745
|
*
|
|
724
746
|
* @remarks
|
|
725
747
|
* - **Why it exists.** An `AgentJobInput` is serializable so it can survive a crash in a
|
|
@@ -728,9 +750,9 @@ export declare interface AgentQueueOptions {
|
|
|
728
750
|
* construct it once with the live pools, then a queue / runner handler calls `build`
|
|
729
751
|
* on each (possibly restored) job to get a ready agent.
|
|
730
752
|
* - **Accessors throw on a miss.** `provider` / `tool` / `authority` / `scheduler` resolve a
|
|
731
|
-
* name against their pool and
|
|
753
|
+
* name against their pool and throw an {@link AgentError} carrying `code: 'REGISTRY'` and
|
|
732
754
|
* 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
|
|
755
|
+
* rehydrated job is a programmer / config error that must fail loudly at build time, never
|
|
734
756
|
* silently resolve to `undefined` and run an agent missing a dependency.
|
|
735
757
|
* - **`build` rehydrates.** Resolve the job's `provider`; assemble a fresh
|
|
736
758
|
* {@link ToolManager} from the `tools` names; rebuild the token `budget` from its
|
|
@@ -767,7 +789,7 @@ export declare class AgentRegistry implements AgentRegistryInterface {
|
|
|
767
789
|
*
|
|
768
790
|
* @remarks
|
|
769
791
|
* - **Accessors throw on a miss.** `provider` / `tool` / `authority` / `scheduler` look one
|
|
770
|
-
* up by name and
|
|
792
|
+
* up by name and throw an {@link AgentError} carrying `code: 'REGISTRY'` and the message
|
|
771
793
|
* `unknown <category>: <name>` when the name is unregistered — an unknown name in a
|
|
772
794
|
* rehydrated job must fail loudly, never silently resolve to `undefined`, so a
|
|
773
795
|
* misconfigured job surfaces at once rather than running with a missing dependency.
|
|
@@ -780,7 +802,8 @@ export declare class AgentRegistry implements AgentRegistryInterface {
|
|
|
780
802
|
*/
|
|
781
803
|
export declare interface AgentRegistryInterface {
|
|
782
804
|
/**
|
|
783
|
-
* Resolves a registered {@link ProviderInterface} by name
|
|
805
|
+
* Resolves a registered {@link ProviderInterface} by name — throws `unknown provider: <name>` when
|
|
806
|
+
* absent.
|
|
784
807
|
*
|
|
785
808
|
* @param name - The provider's registry key
|
|
786
809
|
* @returns The live provider
|
|
@@ -788,7 +811,8 @@ export declare interface AgentRegistryInterface {
|
|
|
788
811
|
*/
|
|
789
812
|
provider(name: string): ProviderInterface;
|
|
790
813
|
/**
|
|
791
|
-
* Resolves a registered {@link ToolInterface} by name
|
|
814
|
+
* Resolves a registered {@link ToolInterface} by name — throws `unknown tool: <name>` when
|
|
815
|
+
* absent.
|
|
792
816
|
*
|
|
793
817
|
* @param name - The tool's registry key
|
|
794
818
|
* @returns The live tool
|
|
@@ -796,7 +820,8 @@ export declare interface AgentRegistryInterface {
|
|
|
796
820
|
*/
|
|
797
821
|
tool(name: string): ToolInterface;
|
|
798
822
|
/**
|
|
799
|
-
* Resolves a registered {@link AuthorityInterface} by name
|
|
823
|
+
* Resolves a registered {@link AuthorityInterface} by name — throws `unknown authority: <name>` when
|
|
824
|
+
* absent.
|
|
800
825
|
*
|
|
801
826
|
* @param name - The authority's registry key
|
|
802
827
|
* @returns The live authority
|
|
@@ -804,7 +829,8 @@ export declare interface AgentRegistryInterface {
|
|
|
804
829
|
*/
|
|
805
830
|
authority(name: string): AuthorityInterface;
|
|
806
831
|
/**
|
|
807
|
-
* Resolves a registered {@link SchedulerInterface} by name
|
|
832
|
+
* Resolves a registered {@link SchedulerInterface} by name — throws `unknown scheduler: <name>` when
|
|
833
|
+
* absent.
|
|
808
834
|
*
|
|
809
835
|
* @param name - The scheduler's registry key
|
|
810
836
|
* @returns The live scheduler
|
|
@@ -812,8 +838,9 @@ export declare interface AgentRegistryInterface {
|
|
|
812
838
|
*/
|
|
813
839
|
scheduler(name: string): SchedulerInterface;
|
|
814
840
|
/**
|
|
815
|
-
* Rehydrates a live, seeded {@link AgentInterface} from a serializable
|
|
816
|
-
* its names, rebuilding its budget, seeding its conversation, and wiring
|
|
841
|
+
* Rehydrates a live, seeded {@link AgentInterface} from a serializable {@link AgentJobInput}
|
|
842
|
+
* — resolving its names, rebuilding its token budget, seeding its conversation, and wiring
|
|
843
|
+
* `signal`; a name absent from its pool throws.
|
|
817
844
|
*
|
|
818
845
|
* @param input - The serializable {@link AgentJobInput} to rehydrate
|
|
819
846
|
* @param signal - An optional cancel threaded into the agent (a queue / runner abort)
|
|
@@ -824,20 +851,21 @@ export declare interface AgentRegistryInterface {
|
|
|
824
851
|
}
|
|
825
852
|
|
|
826
853
|
/**
|
|
827
|
-
* Configures `createAgentRegistry` — the named pools of live, non-serializable pieces
|
|
828
|
-
*
|
|
854
|
+
* Configures `createAgentRegistry` — the named pools of live, non-serializable pieces an {@link
|
|
855
|
+
* AgentJobInput}'s names resolve against, plus the optional durable `store` every built agent's
|
|
856
|
+
* conversation manager shares.
|
|
829
857
|
*
|
|
830
858
|
* @remarks
|
|
831
859
|
* `providers` is required (a job always names a provider); `tools` / `authorities` /
|
|
832
860
|
* `schedulers` are optional pools, each an entity-keyed record mapping a registry
|
|
833
861
|
* name to its live object. A name absent from its pool throws when resolved (see
|
|
834
862
|
* {@link AgentRegistryInterface}). `store` is the durable {@link ConversationStoreInterface}
|
|
835
|
-
* every agent this registry builds carries: each built agent gets its
|
|
836
|
-
* {@link ConversationManagerInterface} over
|
|
863
|
+
* every agent this registry builds carries: each built agent gets its own store-backed
|
|
864
|
+
* {@link ConversationManagerInterface} over this shared store — a fresh conversation id per
|
|
837
865
|
* build (minted by the seeded `add`), so concurrent builds never collide, and the store
|
|
838
866
|
* accumulates one snapshot per built agent that later calls `save`. Persistence
|
|
839
867
|
* stays caller-triggered (`open` / `save`) — `build` never hydrates, so `build` stays
|
|
840
|
-
*
|
|
868
|
+
* synchronous. Omitted ⇒ every built agent gets a registry-only manager, byte-identical
|
|
841
869
|
* to today.
|
|
842
870
|
*/
|
|
843
871
|
export declare interface AgentRegistryOptions {
|
|
@@ -857,13 +885,13 @@ export declare interface AgentRegistryOptions {
|
|
|
857
885
|
* `partial` is `true` when the turn was committed early from a cancel — an external
|
|
858
886
|
* `signal` abort, the turn's own `abort()`, a `timeout` deadline, or an exhausted
|
|
859
887
|
* `budget` — in which case `content` is whatever had accumulated when the cancel
|
|
860
|
-
* landed. `partial` is
|
|
888
|
+
* landed. `partial` is also `true` when the loop exhausted its `limit` while still
|
|
861
889
|
* holding unresolved tool intent (the model requested tools on the very last allowed
|
|
862
890
|
* turn) — a distinct, non-cancel cause covered by {@link RunOutcome.exhausted} (see
|
|
863
891
|
* the `exhaust` {@link AgentEventMap} event). It is `false` for a turn that ran to a
|
|
864
892
|
* natural finish (including a `limit: 0` run, which never enters the loop). `usage` is
|
|
865
893
|
* present only when at least one provider call reported usage — an aborted run's `usage`
|
|
866
|
-
*
|
|
894
|
+
* includes the cancelled turn's tokens when the provider reports partial usage on the
|
|
867
895
|
* abort (folded in exactly like a completed turn's); a provider that cannot observe
|
|
868
896
|
* usage mid-stream (for example a daemon whose final counts never arrive before the cancel)
|
|
869
897
|
* reports none for that turn, and none is fabricated. `thinking` is present
|
|
@@ -881,8 +909,11 @@ export declare interface AgentResult {
|
|
|
881
909
|
}
|
|
882
910
|
|
|
883
911
|
/**
|
|
884
|
-
* Projects an unknown value onto
|
|
885
|
-
* {@link AgentResult}
|
|
912
|
+
* Projects an unknown value onto a fresh, exact `JSONValue` representation of an
|
|
913
|
+
* {@link AgentResult} — capturing each structural field once through a total boundary,
|
|
914
|
+
* accepting conforming accessors and inherited properties, preserving finite negative and
|
|
915
|
+
* fractional usage counts, dropping extras, and resolving `undefined` for a malformed field, a
|
|
916
|
+
* non-finite usage number, a throwing getter, or a hostile or revoked proxy.
|
|
886
917
|
*
|
|
887
918
|
* @remarks
|
|
888
919
|
* This is a total hostile-boundary projection. Each structural field is captured once
|
|
@@ -912,7 +943,7 @@ export declare function agentResultToJSON(value: unknown): JSONValue | undefined
|
|
|
912
943
|
*
|
|
913
944
|
* @remarks
|
|
914
945
|
* Identical partial policy to {@link AgentQueueOptions} (`partial` — a partial
|
|
915
|
-
* `AgentResult`
|
|
946
|
+
* `AgentResult` throws by default so the run's fail-fast engages, `true` resolves it as
|
|
916
947
|
* success). `concurrency` / `retries` / `timeout` pass straight to the backing
|
|
917
948
|
* `RunnerInterface` (see `RunnerOptions`). The runner enables sub-agent fan-out: a
|
|
918
949
|
* parent job's handler can `controller.spawn(childJob)` to launch a child agent job
|
|
@@ -920,7 +951,7 @@ export declare function agentResultToJSON(value: unknown): JSONValue | undefined
|
|
|
920
951
|
*/
|
|
921
952
|
export declare interface AgentRunnerOptions {
|
|
922
953
|
readonly registry: AgentRegistryInterface;
|
|
923
|
-
/** If `true`, a partial `AgentResult` resolves as success; if `false` (the default), it
|
|
954
|
+
/** If `true`, a partial `AgentResult` resolves as success; if `false` (the default), it throws and fail-fast engages. */
|
|
924
955
|
readonly partial?: boolean;
|
|
925
956
|
readonly concurrency?: number;
|
|
926
957
|
readonly retries?: number;
|
|
@@ -929,14 +960,15 @@ export declare interface AgentRunnerOptions {
|
|
|
929
960
|
|
|
930
961
|
/**
|
|
931
962
|
* Carries the per-run override bag an {@link AgentInterface}'s `generate` / `stream` accepts — each
|
|
932
|
-
* member overrides the matching {@link AgentOptions} value for
|
|
963
|
+
* member overrides the matching {@link AgentOptions} value for one run, where `think` and `schema`
|
|
964
|
+
* forward to the provider call and `signal` composes with the constructed one.
|
|
933
965
|
*
|
|
934
966
|
* @remarks
|
|
935
967
|
* Every member is optional and resolved independently, so an omitted member leaves the
|
|
936
968
|
* agent's constructed value in force and a caller that passes no options runs exactly the
|
|
937
969
|
* agent it configured. `think` / `schema` ride through to the provider as
|
|
938
970
|
* {@link ProviderStreamOptions}; `limit` / `timeout` / `budget` replace their construction
|
|
939
|
-
* defaults for this run only; `signal`
|
|
971
|
+
* defaults for this run only; `signal` composes with the constructed `signal` (both fold into
|
|
940
972
|
* the run's bound abort) rather than replacing it. Nothing here mutates the agent — the next
|
|
941
973
|
* run reads the construction defaults again.
|
|
942
974
|
*/
|
|
@@ -956,23 +988,23 @@ export declare interface AgentRunOptions {
|
|
|
956
988
|
*/
|
|
957
989
|
readonly schema?: Readonly<Record<string, unknown>>;
|
|
958
990
|
/**
|
|
959
|
-
* Overrides {@link AgentOptions.limit} for
|
|
991
|
+
* Overrides {@link AgentOptions.limit} for this run only — the max tool-iteration turns
|
|
960
992
|
* before the loop stops. Omitted ⇒ the agent's constructed `limit` applies.
|
|
961
993
|
*/
|
|
962
994
|
readonly limit?: number;
|
|
963
995
|
/**
|
|
964
|
-
* Overrides {@link AgentOptions.timeout} for
|
|
996
|
+
* Overrides {@link AgentOptions.timeout} for this run only — a wall-clock deadline (ms)
|
|
965
997
|
* whose abort commits a partial result. Omitted ⇒ the agent's constructed `timeout` applies.
|
|
966
998
|
*/
|
|
967
999
|
readonly timeout?: number;
|
|
968
1000
|
/**
|
|
969
|
-
* Overrides {@link AgentOptions.budget} for
|
|
1001
|
+
* Overrides {@link AgentOptions.budget} for this run only — a token cost bound whose abort
|
|
970
1002
|
* commits a partial result; `start()`ed for this run exactly as the constructed budget is.
|
|
971
1003
|
* Omitted ⇒ the agent's constructed `budget` applies.
|
|
972
1004
|
*/
|
|
973
1005
|
readonly budget?: BudgetInterface<TokenUsage>;
|
|
974
1006
|
/**
|
|
975
|
-
* Carries an additional per-run external cancel,
|
|
1007
|
+
* Carries an additional per-run external cancel, composed with {@link AgentOptions.signal} (both
|
|
976
1008
|
* fold into the run's bound abort through `AbortSignal.any` — neither is dropped). Omitted ⇒
|
|
977
1009
|
* only the agent's constructed `signal` (if any) applies.
|
|
978
1010
|
*/
|
|
@@ -994,10 +1026,11 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
|
|
|
994
1026
|
|
|
995
1027
|
/**
|
|
996
1028
|
* Assembles the settled {@link AgentResult} from a run's {@link RunOutcome} — `thinking` and
|
|
997
|
-
* `usage` are carried only when the run surfaced them
|
|
1029
|
+
* `usage` are carried only when the run surfaced them, and the loop-internal `exhausted` flag is
|
|
1030
|
+
* left out.
|
|
998
1031
|
*
|
|
999
1032
|
* @remarks
|
|
1000
|
-
* Pure and total. An absent optional is
|
|
1033
|
+
* Pure and total. An absent optional is omitted rather than stored as `undefined` (the
|
|
1001
1034
|
* present-when-given convention the message store follows), so a settled result JSON
|
|
1002
1035
|
* round-trips without an explicit `undefined` field. `exhausted` is loop bookkeeping and does
|
|
1003
1036
|
* not reach the public result — the `exhaust` event carries it instead.
|
|
@@ -1014,11 +1047,11 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
|
|
|
1014
1047
|
export declare function assembleResult(outcome: RunOutcome): AgentResult;
|
|
1015
1048
|
|
|
1016
1049
|
/**
|
|
1017
|
-
* Copies a message with image data merged onto its `images` — the message's own images
|
|
1018
|
-
*
|
|
1050
|
+
* Copies a message with image data merged onto its `images` — the message's own images first,
|
|
1051
|
+
* then the attached data, carrying `calls` only when present and never mutating the original.
|
|
1019
1052
|
*
|
|
1020
1053
|
* @remarks
|
|
1021
|
-
* Pure and total: the original message is
|
|
1054
|
+
* Pure and total: the original message is never mutated. `calls` is carried only when the
|
|
1022
1055
|
* source message has one (kept omitted otherwise, mirroring the store's present-when-given
|
|
1023
1056
|
* convention).
|
|
1024
1057
|
*
|
|
@@ -1035,13 +1068,14 @@ export declare function assembleResult(outcome: RunOutcome): AgentResult;
|
|
|
1035
1068
|
export declare function attachImages(message: Message, data: readonly string[]): Message;
|
|
1036
1069
|
|
|
1037
1070
|
/**
|
|
1038
|
-
* Attaches image data to a conversation's
|
|
1039
|
-
*
|
|
1071
|
+
* Attaches image data to a conversation's last user message — the turn a vision provider reads
|
|
1072
|
+
* images off — as a new array with that one message replaced by its carrying copy, and unchanged
|
|
1073
|
+
* when there is no data or no user turn.
|
|
1040
1074
|
*
|
|
1041
1075
|
* @remarks
|
|
1042
|
-
* Pure and total: the conversation and its messages are
|
|
1076
|
+
* Pure and total: the conversation and its messages are never mutated, and the returned array
|
|
1043
1077
|
* replaces exactly the one target message with the copy {@link attachImages} builds. Empty
|
|
1044
|
-
* data returns the conversation unchanged; a conversation with
|
|
1078
|
+
* data returns the conversation unchanged; a conversation with no user message returns it
|
|
1045
1079
|
* unchanged too (there is nowhere to attach, and the images already rode the system block).
|
|
1046
1080
|
*
|
|
1047
1081
|
* @param conversation - The messages to attach into (left unchanged)
|
|
@@ -1057,18 +1091,20 @@ export declare function attachImages(message: Message, data: readonly string[]):
|
|
|
1057
1091
|
export declare function attachUserImages(conversation: readonly Message[], data: readonly string[]): readonly Message[];
|
|
1058
1092
|
|
|
1059
1093
|
/**
|
|
1060
|
-
* Gates the agent loop's tool calls — the synchronous policy consulted before each call
|
|
1061
|
-
*
|
|
1094
|
+
* Gates the agent loop's tool calls — the synchronous policy consulted before each call runs,
|
|
1095
|
+
* turning one {@link AuthorityContext} into an {@link AuthorityDecision} by walking the ordered
|
|
1096
|
+
* rules first-match-wins and falling back to a configurable default, which allows an unmatched
|
|
1097
|
+
* call unless its `fallback` denies.
|
|
1062
1098
|
*
|
|
1063
1099
|
* @remarks
|
|
1064
1100
|
* - **Ordered, first-match-wins.** `evaluate` walks the configured rules in order and
|
|
1065
|
-
* returns the
|
|
1066
|
-
* `{ zone, allowed: rule.allowed ?? true, reason }` — a matched rule
|
|
1067
|
-
* default and
|
|
1101
|
+
* returns the first whose `match(context)` is true as
|
|
1102
|
+
* `{ zone, allowed: rule.allowed ?? true, reason }` — a matched rule allows by
|
|
1103
|
+
* default and denies only when its `allowed` is explicitly `false`.
|
|
1068
1104
|
* - **Fallback.** When no rule matches, `evaluate` returns the configured `fallback`.
|
|
1069
1105
|
* It defaults to `{ zone: DEFAULT_AUTHORITY_ZONE, allowed: true }` (allow-unmatched),
|
|
1070
|
-
* so a rules list of denials behaves as a
|
|
1071
|
-
* (an
|
|
1106
|
+
* so a rules list of denials behaves as a denylist. To make the gate deny-by-default
|
|
1107
|
+
* (an allowlist — only matched rules that allow get through), pass an `allowed: false`
|
|
1072
1108
|
* `fallback`.
|
|
1073
1109
|
* - **Consulted before each tool call.** The agent loop calls `evaluate({ call })` for
|
|
1074
1110
|
* every {@link import('@orkestrel/tool').ToolCall} the model emits; a denied call is fed
|
|
@@ -1133,7 +1169,8 @@ export declare interface AuthorityDecision {
|
|
|
1133
1169
|
*/
|
|
1134
1170
|
export declare interface AuthorityInterface {
|
|
1135
1171
|
/**
|
|
1136
|
-
* Evaluates one tool call against the ordered rules
|
|
1172
|
+
* Evaluates one tool call against the ordered rules — returns the first matching rule's
|
|
1173
|
+
* verdict, which allows unless `allowed: false`, or the fallback when none match.
|
|
1137
1174
|
*
|
|
1138
1175
|
* @param context - The call under consideration (see {@link AuthorityContext})
|
|
1139
1176
|
* @returns The first matching rule's verdict, or the fallback when none match
|
|
@@ -1146,7 +1183,7 @@ export declare interface AuthorityInterface {
|
|
|
1146
1183
|
*
|
|
1147
1184
|
* @remarks
|
|
1148
1185
|
* `rules` are evaluated in order, first match wins (see {@link AuthorityRule}).
|
|
1149
|
-
* `fallback` is the {@link AuthorityDecision} returned when
|
|
1186
|
+
* `fallback` is the {@link AuthorityDecision} returned when no rule matches; it
|
|
1150
1187
|
* defaults to `{ zone: DEFAULT_AUTHORITY_ZONE, allowed: true }` (allow-unmatched — a
|
|
1151
1188
|
* rules list of denials acts as a denylist). Set `fallback` to an `allowed: false`
|
|
1152
1189
|
* decision to flip the gate to deny-by-default (an allowlist — only matched rules
|
|
@@ -1161,8 +1198,8 @@ export declare interface AuthorityOptions {
|
|
|
1161
1198
|
* Represents one ordered policy rule an {@link AuthorityInterface} evaluates.
|
|
1162
1199
|
*
|
|
1163
1200
|
* @remarks
|
|
1164
|
-
* The
|
|
1165
|
-
* `fallback` decides. A matched rule
|
|
1201
|
+
* The first rule whose `match` returns true decides; if none match, the authority's
|
|
1202
|
+
* `fallback` decides. A matched rule allows by default and denies only when its
|
|
1166
1203
|
* `allowed` is explicitly `false`. `zone` classifies the matched call; `reason` is the
|
|
1167
1204
|
* optional explanation carried into the {@link AuthorityDecision} (and, on a denial,
|
|
1168
1205
|
* into the denial {@link ToolResult}).
|
|
@@ -1175,13 +1212,13 @@ export declare interface AuthorityRule {
|
|
|
1175
1212
|
}
|
|
1176
1213
|
|
|
1177
1214
|
/**
|
|
1178
|
-
* Builds the
|
|
1179
|
-
*
|
|
1180
|
-
*
|
|
1215
|
+
* Builds the framed recap message for one compacted section — the same role and stable `id` as
|
|
1216
|
+
* {@link buildSummaryMessage}, with the content prefixed by {@link
|
|
1217
|
+
* import('./constants.js').CONVERSATION_RECAP_PREFIX}.
|
|
1181
1218
|
*
|
|
1182
1219
|
* @remarks
|
|
1183
|
-
* Pure and total. The prefix is what makes a small model read the message as a
|
|
1184
|
-
*
|
|
1220
|
+
* Pure and total. The prefix is what makes a small model read the message as a condensed
|
|
1221
|
+
* recap of earlier turns rather than a literal assistant turn to echo or answer from. It is a
|
|
1185
1222
|
* fixed handful of tokens, so a conversation's `view()` stays lean however many sections it
|
|
1186
1223
|
* carries.
|
|
1187
1224
|
*
|
|
@@ -1197,12 +1234,12 @@ export declare interface AuthorityRule {
|
|
|
1197
1234
|
export declare function buildRecapMessage(section: Section): Message;
|
|
1198
1235
|
|
|
1199
1236
|
/**
|
|
1200
|
-
* Builds the
|
|
1201
|
-
*
|
|
1237
|
+
* Builds the raw synthetic summary message for one compacted section — role `'assistant'`, the
|
|
1238
|
+
* section's stable `id`, and its `summary` verbatim as content.
|
|
1202
1239
|
*
|
|
1203
1240
|
* @remarks
|
|
1204
1241
|
* Pure and total. This is the unframed form the rollup regeneration digests (a
|
|
1205
|
-
* summary-of-summaries over the section summaries); the recap
|
|
1242
|
+
* summary-of-summaries over the section summaries); the recap label is a `view()`
|
|
1206
1243
|
* presentation concern kept out of what the summarizer re-reads — see
|
|
1207
1244
|
* {@link buildRecapMessage}.
|
|
1208
1245
|
*
|
|
@@ -1218,10 +1255,11 @@ export declare function buildRecapMessage(section: Section): Message;
|
|
|
1218
1255
|
export declare function buildSummaryMessage(section: Section): Message;
|
|
1219
1256
|
|
|
1220
1257
|
/**
|
|
1221
|
-
* Buffers chunks in a minimal unbounded async channel — the eager pump
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1258
|
+
* Buffers chunks in a minimal unbounded async channel — the eager pump writes them in (`push`)
|
|
1259
|
+
* and ends it (`close` / `fail`) regardless of consumption, while a consumer reads them back live
|
|
1260
|
+
* through the `drain` async-iterator. Decoupling write from read is what lets a producer make
|
|
1261
|
+
* progress without a consumer pulling, and it is why an agent's `result` settles whether or not
|
|
1262
|
+
* its `events` are drained.
|
|
1225
1263
|
*
|
|
1226
1264
|
* @remarks
|
|
1227
1265
|
* The standard resolver-swap: a waiting `drain` parks on `#wake` (a void resolver);
|
|
@@ -1250,24 +1288,25 @@ export declare class Channel<T> implements ChannelInterface<T> {
|
|
|
1250
1288
|
}
|
|
1251
1289
|
|
|
1252
1290
|
/**
|
|
1253
|
-
* Buffers values in an unbounded async channel — a producer
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1291
|
+
* Buffers values in an unbounded async channel — a producer writes them in (`push`) and ends it
|
|
1292
|
+
* (`close` / `fail`) regardless of consumption, while a consumer reads them back live through
|
|
1293
|
+
* `drain`.
|
|
1256
1294
|
*
|
|
1257
1295
|
* @remarks
|
|
1258
1296
|
* Decoupling the write from the read is what lets a producer make progress with nobody
|
|
1259
1297
|
* pulling: an agent's eager pump writes each {@link AgentChunk} into one, so the run's
|
|
1260
1298
|
* `result` settles whether or not `events` is ever drained. A waiting `drain` parks on a
|
|
1261
1299
|
* 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
|
|
1263
|
-
* reported, so a `close` arriving alongside the last values still delivers them. The
|
|
1300
|
+
* delivered rather than dropped. Buffered values are always yielded before the end is
|
|
1301
|
+
* reported, so a `close` arriving alongside the last values still delivers them. The first
|
|
1264
1302
|
* failure wins — a later `close` / `fail` cannot override a recorded error. Event-free.
|
|
1265
1303
|
*
|
|
1266
1304
|
* @typeParam T - The value type the channel carries
|
|
1267
1305
|
*/
|
|
1268
1306
|
export declare interface ChannelInterface<T> {
|
|
1269
1307
|
/**
|
|
1270
|
-
* Writes one value — buffered, then handed to a parked consumer
|
|
1308
|
+
* Writes one value — buffered, then handed to a parked consumer; a value pushed at an
|
|
1309
|
+
* already-parked reader is delivered, never dropped.
|
|
1271
1310
|
*
|
|
1272
1311
|
* @param value - The value to enqueue
|
|
1273
1312
|
*/
|
|
@@ -1275,13 +1314,14 @@ export declare interface ChannelInterface<T> {
|
|
|
1275
1314
|
/** Ends the channel normally — a draining consumer returns once the buffer is empty. */
|
|
1276
1315
|
close(): void;
|
|
1277
1316
|
/**
|
|
1278
|
-
* Ends the channel with a failure — a draining consumer throws it once the buffer is empty
|
|
1317
|
+
* Ends the channel with a failure — a draining consumer throws it once the buffer is empty;
|
|
1318
|
+
* the first failure wins.
|
|
1279
1319
|
*
|
|
1280
1320
|
* @param error - The failure to surface (the first one recorded wins)
|
|
1281
1321
|
*/
|
|
1282
1322
|
fail(error: unknown): void;
|
|
1283
1323
|
/**
|
|
1284
|
-
* Reads the values back live, in write order
|
|
1324
|
+
* Reads the values back live, in write order — returning on `close` and throwing on `fail`.
|
|
1285
1325
|
*
|
|
1286
1326
|
* @returns A generator yielding each pushed value, returning on `close` and throwing on `fail`
|
|
1287
1327
|
*/
|
|
@@ -1289,11 +1329,11 @@ export declare interface ChannelInterface<T> {
|
|
|
1289
1329
|
}
|
|
1290
1330
|
|
|
1291
1331
|
/**
|
|
1292
|
-
* Collects the `base64` payload of the
|
|
1293
|
-
*
|
|
1332
|
+
* Collects the `base64` payload of the image files in a workspace file list — the data an agent
|
|
1333
|
+
* context attaches to the last user message.
|
|
1294
1334
|
*
|
|
1295
1335
|
* @remarks
|
|
1296
|
-
* Pure and total. `isBinary`
|
|
1336
|
+
* Pure and total. `isBinary` narrows the tagless content to its binary arm (a total guard,
|
|
1297
1337
|
* never an assertion), then the MIME prefix gates it to an image, so a text file and a non-image
|
|
1298
1338
|
* binary (a PDF) are both skipped. Order follows the file list.
|
|
1299
1339
|
*
|
|
@@ -1309,14 +1349,15 @@ export declare interface ChannelInterface<T> {
|
|
|
1309
1349
|
export declare function collectImageData(files: readonly FileInterface[]): readonly string[];
|
|
1310
1350
|
|
|
1311
1351
|
/**
|
|
1312
|
-
* Configures one {@link ConversationInterface.compact} call —
|
|
1352
|
+
* Configures one {@link ConversationInterface.compact} call — the retained-tail size, the
|
|
1353
|
+
* `sections` cap, or both, overridden for one fold.
|
|
1313
1354
|
*
|
|
1314
1355
|
* @remarks
|
|
1315
|
-
* `keep` overrides the conversation's configured retained-tail size for
|
|
1356
|
+
* `keep` overrides the conversation's configured retained-tail size for this compaction only
|
|
1316
1357
|
* (the older `count - keep` live messages fold; when `count <= keep` nothing folds and
|
|
1317
1358
|
* `compact()` is a no-op returning `undefined`). Omitted ⇒ the conversation's own `keep`
|
|
1318
1359
|
* (its option, or `DEFAULT_CONVERSATION_KEEP`) applies. `sections` overrides the conversation's
|
|
1319
|
-
* configured `sections` cap for
|
|
1360
|
+
* configured `sections` cap for this compaction only — after the new section is pushed, an
|
|
1320
1361
|
* overflow past `sections` folds the oldest sections into one merged section. Omitted ⇒ the
|
|
1321
1362
|
* conversation's own `sections` cap (or unlimited) applies.
|
|
1322
1363
|
*/
|
|
@@ -1328,17 +1369,17 @@ export declare interface CompactOptions {
|
|
|
1328
1369
|
}
|
|
1329
1370
|
|
|
1330
1371
|
/**
|
|
1331
|
-
* Holds a provider's
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1372
|
+
* Holds a provider's optional context-framing default, keyed by section kind — the framing a model
|
|
1373
|
+
* prefers (for example XML tags against Markdown headers), declared by a {@link ProviderInterface}
|
|
1374
|
+
* that opts in.
|
|
1334
1375
|
*
|
|
1335
1376
|
* @remarks
|
|
1336
1377
|
* Each key is a {@link ContextSectionFormat} for one of the observable context sections
|
|
1337
1378
|
* (the `instructions` section), so a provider can frame each section independently — and any
|
|
1338
|
-
* it omits falls through to that manager's built-in default. It is the
|
|
1339
|
-
* level of the {@link import('./AgentContext.js').AgentContext} build cascade: it
|
|
1340
|
-
* manager's built-in default but is
|
|
1341
|
-
* override (see {@link AgentContextInterface.build}). It references the
|
|
1379
|
+
* it omits falls through to that manager's built-in default. It is the provider-default
|
|
1380
|
+
* level of the {@link import('./AgentContext.js').AgentContext} build cascade: it beats a
|
|
1381
|
+
* manager's built-in default but is beaten by a manager-options override and by a per-item
|
|
1382
|
+
* override (see {@link AgentContextInterface.build}). It references the abstract core
|
|
1342
1383
|
* item interface ({@link InstructionInterface}), so a provider opting in imports it from
|
|
1343
1384
|
* `@orkestrel/agent` — the type is provider-agnostic, with no backend coupling. Omitting it
|
|
1344
1385
|
* entirely (the default for an agnostic provider) leaves every section on its manager's
|
|
@@ -1356,17 +1397,17 @@ export declare interface ContextFormat {
|
|
|
1356
1397
|
* line rendered once after the items.
|
|
1357
1398
|
*
|
|
1358
1399
|
* @remarks
|
|
1359
|
-
* `open`, `render`, and `close` are
|
|
1400
|
+
* `open`, `render`, and `close` are optional and resolved independently (so an override may set only
|
|
1360
1401
|
* the top, only the per-item rendering, only the bottom, or any mix). A section assembles
|
|
1361
1402
|
* as `[open, ...items.map(render), close]` with empty / absent slots dropped, the survivors
|
|
1362
|
-
* blank-line (`\n\n`) joined — so `open` + `close` together let a developer
|
|
1403
|
+
* blank-line (`\n\n`) joined — so `open` + `close` together let a developer wrap the whole
|
|
1363
1404
|
* group (for example `open: '<instructions>'` … `close: '</instructions>'`). `open` is the
|
|
1364
1405
|
* section's leading text (the header, or a group's opening tag); `render` turns one section
|
|
1365
1406
|
* item (an {@link InstructionInterface}) into its prompt text; `close` is the trailing text.
|
|
1366
1407
|
* `open` and `render` cascade through the
|
|
1367
1408
|
* built-in floor (`open` ⇒ the manager's built-in header, `render` ⇒ the manager's built-in
|
|
1368
|
-
* rendering); `close` has
|
|
1369
|
-
* It is the unit
|
|
1409
|
+
* rendering); `close` has no built-in, so an unset `close` yields no closing line.
|
|
1410
|
+
* It is the unit both a provider's {@link ContextFormat} (a per-section-kind
|
|
1370
1411
|
* default) and a manager's `Options` carry — see {@link AgentContextInterface.build} for
|
|
1371
1412
|
* the full precedence.
|
|
1372
1413
|
*
|
|
@@ -1374,7 +1415,7 @@ export declare interface ContextFormat {
|
|
|
1374
1415
|
*/
|
|
1375
1416
|
export declare interface ContextSectionFormat<T> {
|
|
1376
1417
|
/**
|
|
1377
|
-
* Holds text rendered
|
|
1418
|
+
* Holds text rendered once before the section's items — the section header or a group's
|
|
1378
1419
|
* opening wrapper, for example `'<instructions>'`; omitted ⇒ the next cascade level decides
|
|
1379
1420
|
* (defaulting to the built-in header).
|
|
1380
1421
|
*/
|
|
@@ -1382,25 +1423,25 @@ export declare interface ContextSectionFormat<T> {
|
|
|
1382
1423
|
/** Overrides one item's rendering; omitted ⇒ the next cascade level decides. */
|
|
1383
1424
|
readonly render?: (item: T) => string;
|
|
1384
1425
|
/**
|
|
1385
|
-
* Holds text rendered
|
|
1426
|
+
* Holds text rendered once after the section's items — a group's closing wrapper, for
|
|
1386
1427
|
* example `'</instructions>'`; omitted ⇒ no closing line (there is no built-in close).
|
|
1387
1428
|
*/
|
|
1388
1429
|
readonly close?: string;
|
|
1389
1430
|
}
|
|
1390
1431
|
|
|
1391
1432
|
/**
|
|
1392
|
-
* Exposes the manager surface one context section's format cascade reads — its built-in
|
|
1393
|
-
* `
|
|
1394
|
-
*
|
|
1433
|
+
* Exposes the manager surface one context section's format cascade reads — its built-in `open` /
|
|
1434
|
+
* `render`, plus the raw options override the cascade layers a provider default beneath; {@link
|
|
1435
|
+
* InstructionManagerInterface} satisfies it structurally.
|
|
1395
1436
|
*
|
|
1396
1437
|
* @remarks
|
|
1397
1438
|
* The narrow contract the cascade resolvers
|
|
1398
1439
|
* ({@link import('./helpers.js').resolveOpen} / {@link import('./helpers.js').resolveClose} /
|
|
1399
|
-
* {@link import('./helpers.js').resolveItem}) take, so they stay independent of
|
|
1440
|
+
* {@link import('./helpers.js').resolveItem}) take, so they stay independent of which manager
|
|
1400
1441
|
* supplies the section: an {@link InstructionManagerInterface} satisfies it structurally.
|
|
1401
1442
|
* `open` and `render` already encapsulate `[options-override → built-in]` (so a manager
|
|
1402
1443
|
* used standalone renders correctly), and `format` exposes the raw override so `build()` can
|
|
1403
|
-
* interleave the provider default
|
|
1444
|
+
* interleave the provider default beneath it.
|
|
1404
1445
|
*
|
|
1405
1446
|
* @typeParam T - The section item this source renders
|
|
1406
1447
|
*/
|
|
@@ -1409,41 +1450,45 @@ export declare interface ContextSectionSourceInterface<T> {
|
|
|
1409
1450
|
readonly open: string;
|
|
1410
1451
|
/** Holds the raw manager-options override, or `undefined` when none was supplied. */
|
|
1411
1452
|
readonly format: ContextSectionFormat<T> | undefined;
|
|
1412
|
-
/**
|
|
1453
|
+
/**
|
|
1454
|
+
* Renders one section item, already resolved against the manager-options override and
|
|
1455
|
+
* otherwise on the built-in rendering.
|
|
1456
|
+
*/
|
|
1413
1457
|
render(item: T): string;
|
|
1414
1458
|
}
|
|
1415
1459
|
|
|
1416
1460
|
/**
|
|
1417
|
-
* Represents a conversation — a live uncompacted tail of messages it
|
|
1418
|
-
*
|
|
1419
|
-
* `
|
|
1420
|
-
* {@link ConversationSummaryHandler} seam
|
|
1461
|
+
* Represents a conversation — a live uncompacted tail of messages it owns directly above a flat
|
|
1462
|
+
* message store, plus compacted, summarized {@link Section}s, a regenerated rollup `summary`, and
|
|
1463
|
+
* a `summarizable` flag, with on-demand `rehydrate` and substring `search`, driven by a
|
|
1464
|
+
* provider-agnostic {@link ConversationSummaryHandler} seam so `core` never imports a provider.
|
|
1465
|
+
* Observable through its own `emitter`.
|
|
1421
1466
|
*
|
|
1422
1467
|
* @remarks
|
|
1423
|
-
* - **Live tail + sections.** The conversation
|
|
1468
|
+
* - **Live tail + sections.** The conversation owns its live tail directly — `#messages` is an
|
|
1424
1469
|
* insertion-ordered `Map` of immutable {@link Message}s keyed by their minted id
|
|
1425
|
-
* (the
|
|
1470
|
+
* (the same store mechanics a flat manager had, folded in: `add` / `message` / `messages` /
|
|
1426
1471
|
* `remove` / `clear` / `count`), exactly as a `Workspace` owns its files (no separate
|
|
1427
1472
|
* per-value manager). `#sections` are the compacted history (oldest → newest), each a
|
|
1428
|
-
* summarized slice that
|
|
1473
|
+
* summarized slice that retains its originals. `#summary` is the rollup (a
|
|
1429
1474
|
* summary-of-summaries over all sections), regenerated on each compaction (`undefined`
|
|
1430
1475
|
* until the first).
|
|
1431
|
-
* - **`view()`.** Each section folds to
|
|
1476
|
+
* - **`view()`.** Each section folds to one synthetic summary message (role `'assistant'` — a
|
|
1432
1477
|
* prior-context recap — keyed by the section's stable `id`), then the live messages
|
|
1433
|
-
* verbatim. The rollup `summary` is
|
|
1434
|
-
* carries the per-section summaries, which
|
|
1478
|
+
* verbatim. The rollup `summary` is not injected (it is separately pull-able); `view()`
|
|
1479
|
+
* carries the per-section summaries, which are the compaction benefit.
|
|
1435
1480
|
* - **`compact()`.** Folds the oldest `count - keep` live messages into a new section
|
|
1436
1481
|
* (its `summary` from `#summarize`), removes them from the live tail by id, regenerates the
|
|
1437
|
-
* rollup (a
|
|
1482
|
+
* rollup (a second `#summarize` over all section summaries), and emits `summary` then
|
|
1438
1483
|
* `compact`. Returns the section, or `undefined` when nothing folds (`count <= keep`).
|
|
1439
|
-
*
|
|
1440
|
-
*
|
|
1484
|
+
* Throws a {@link ConversationError} when no `#summarize` was supplied. A compaction calls
|
|
1485
|
+
* the summarizer for the section digest and again for the rollup.
|
|
1441
1486
|
* - **`rehydrate(id)` / `search(query)`.** `rehydrate` returns a section's full original
|
|
1442
1487
|
* messages (`[]` for an unknown id) and emits `rehydrate` — a pure read (the caller decides
|
|
1443
1488
|
* whether to re-add them; `rehydrate` never reinserts). `search` is a case-insensitive
|
|
1444
|
-
* substring scan of `content` across
|
|
1489
|
+
* substring scan of `content` across all messages (every section's originals + the live tail).
|
|
1445
1490
|
* - **Observable.** The owned {@link emitter} ({@link ConversationEventMap}) carries
|
|
1446
|
-
* `compact` / `summary` / `rehydrate`, emitted directly, strictly
|
|
1491
|
+
* `compact` / `summary` / `rehydrate`, emitted directly, strictly after the state change;
|
|
1447
1492
|
* the emitter isolates a listener throw and routes it to its `error` handler (the `error`
|
|
1448
1493
|
* option), so a buggy observer can never corrupt a compaction.
|
|
1449
1494
|
*
|
|
@@ -1485,12 +1530,13 @@ export declare class Conversation implements ConversationInterface {
|
|
|
1485
1530
|
|
|
1486
1531
|
/**
|
|
1487
1532
|
* Names the framing label a {@link ConversationInterface}'s `view()` prefixes onto each compacted
|
|
1488
|
-
* section's summary so a small model reads it as a
|
|
1489
|
-
* literal assistant turn to echo or treat as
|
|
1533
|
+
* section's summary so a small model reads it as a condensed recap of earlier turns — the lean
|
|
1534
|
+
* `'[Summary of earlier messages] '` marker, never a literal assistant turn to echo or treat as
|
|
1535
|
+
* the live answer.
|
|
1490
1536
|
*
|
|
1491
1537
|
* @remarks
|
|
1492
|
-
* Deliberately a
|
|
1493
|
-
* bounded `prefix × sections` overhead and
|
|
1538
|
+
* Deliberately a fixed, lean handful of tokens (a short bracketed marker) so the framing adds a
|
|
1539
|
+
* bounded `prefix × sections` overhead and never an open-ended blow-up — the
|
|
1494
1540
|
* {@link ConversationInterface} no-bloat test guard pins exactly that. Kept here (beside
|
|
1495
1541
|
* {@link DEFAULT_CONVERSATION_KEEP}) as the conversation layer's one tunable framing constant, so
|
|
1496
1542
|
* the wording has a single source of truth as it is optimized against real small-model behavior
|
|
@@ -1500,12 +1546,13 @@ export declare class Conversation implements ConversationInterface {
|
|
|
1500
1546
|
export declare const CONVERSATION_RECAP_PREFIX = "[Summary of earlier messages] ";
|
|
1501
1547
|
|
|
1502
1548
|
/**
|
|
1503
|
-
* Reports a conversation with no {@link ConversationSummaryHandler} to fold its messages
|
|
1504
|
-
*
|
|
1505
|
-
*
|
|
1549
|
+
* Reports a conversation with no {@link ConversationSummaryHandler} to fold its messages with,
|
|
1550
|
+
* or with a `sections` cap below `1` — thrown by a {@link ConversationInterface}'s `compact()`
|
|
1551
|
+
* or its construction, carrying the machine-readable `code`
|
|
1552
|
+
* `'SUMMARIZER' | 'SECTIONS'`.
|
|
1506
1553
|
*
|
|
1507
1554
|
* @remarks
|
|
1508
|
-
* Compaction
|
|
1555
|
+
* Compaction requires a summarizer (it digests the folded slice into a section summary and
|
|
1509
1556
|
* regenerates the rollup); a conversation created without one can still store + `view()` its
|
|
1510
1557
|
* live tail, but a `compact()` is a programmer error and throws this with `'SUMMARIZER'`.
|
|
1511
1558
|
* A `sections` cap (on {@link import('./types.js').ConversationOptions} /
|
|
@@ -1526,7 +1573,7 @@ export declare class ConversationError extends Error {
|
|
|
1526
1573
|
*
|
|
1527
1574
|
* @remarks
|
|
1528
1575
|
* `compact` carries the newly-folded {@link Section}; `collapse` carries a section
|
|
1529
|
-
* created by folding multiple
|
|
1576
|
+
* created by folding multiple older sections together (a bounded-`sections` cap enforcement,
|
|
1530
1577
|
* distinct from `compact`'s fresh live-tail fold); `summary` carries the regenerated
|
|
1531
1578
|
* conversation rollup (refreshed on each compaction); `rehydrate` carries the `id` of a
|
|
1532
1579
|
* section whose originals were pulled back. Listener isolation is the emitter's:
|
|
@@ -1543,31 +1590,32 @@ export declare type ConversationEventMap = {
|
|
|
1543
1590
|
/** Reports a section's original messages pulled back — the section's `id`. */
|
|
1544
1591
|
readonly rehydrate: readonly [id: string];
|
|
1545
1592
|
/**
|
|
1546
|
-
* Reports the bounded-`sections` cap folding the oldest sections into
|
|
1593
|
+
* Reports the bounded-`sections` cap folding the oldest sections into one merged section — the
|
|
1547
1594
|
* merged {@link Section} that replaced them.
|
|
1548
1595
|
*/
|
|
1549
1596
|
readonly collapse: readonly [section: Section];
|
|
1550
1597
|
};
|
|
1551
1598
|
|
|
1552
1599
|
/**
|
|
1553
|
-
* Carries the data to author a {@link ConversationInterface} through a
|
|
1554
|
-
*
|
|
1555
|
-
* override,
|
|
1600
|
+
* Carries the data to author a {@link ConversationInterface} through a {@link
|
|
1601
|
+
* ConversationManagerInterface} — the optional `id`, a `summarize` override, a `keep` override, a
|
|
1602
|
+
* `sections` cap override, the reserved `on` hooks, and a {@link ConversationSnapshot} to hydrate
|
|
1603
|
+
* from.
|
|
1556
1604
|
*
|
|
1557
1605
|
* @remarks
|
|
1558
|
-
* `id` is the conversation's identity (minted when omitted). `summarize`
|
|
1606
|
+
* `id` is the conversation's identity (minted when omitted). `summarize` overrides the
|
|
1559
1607
|
* manager's default {@link ConversationSummaryHandler} for this conversation (omitted ⇒ the
|
|
1560
1608
|
* manager's default flows in). `keep` overrides the manager's default retained-tail size.
|
|
1561
1609
|
* `sections` overrides the manager's default `sections` cap. `on` is the reserved listener key
|
|
1562
1610
|
* (initial {@link ConversationEventMap} listeners). `snapshot` is
|
|
1563
1611
|
* the construction-time hydration seam — a {@link ConversationSnapshot} whose `id` / `summary` /
|
|
1564
|
-
* `sections` / live tail are
|
|
1612
|
+
* `sections` / live tail are restored into the new conversation (the live `summarize` / `keep` /
|
|
1565
1613
|
* `on` re-supplied alongside it), the conversation analogue of
|
|
1566
1614
|
* {@link import('@orkestrel/workspace').WorkspaceOptions}'s `seed`, carried onto
|
|
1567
1615
|
* {@link ConversationOptions.snapshot}, that a
|
|
1568
1616
|
* {@link ConversationManagerInterface.open} reads a stored snapshot back through; hydration is
|
|
1569
1617
|
* silent (no events). When both `snapshot.id` and `id` are given, `snapshot.id` wins (the snapshot
|
|
1570
|
-
*
|
|
1618
|
+
* is the conversation's identity).
|
|
1571
1619
|
*/
|
|
1572
1620
|
export declare interface ConversationInput {
|
|
1573
1621
|
readonly id?: string;
|
|
@@ -1583,52 +1631,53 @@ export declare interface ConversationInput {
|
|
|
1583
1631
|
}
|
|
1584
1632
|
|
|
1585
1633
|
/**
|
|
1586
|
-
* Groups messages
|
|
1587
|
-
*
|
|
1588
|
-
*
|
|
1589
|
-
* provider-agnostic {@link ConversationSummaryHandler} seam
|
|
1634
|
+
* Groups messages above the flat {@link MessageManagerInterface} — a live uncompacted tail plus
|
|
1635
|
+
* compacted, summarized {@link Section}s and a conversation rollup `summary`, with on-demand
|
|
1636
|
+
* `rehydrate`, substring `search`, a cross-conversation `reference`, and a JSON `snapshot`, driven
|
|
1637
|
+
* by a provider-agnostic {@link ConversationSummaryHandler} seam; `summarizable` reports whether
|
|
1638
|
+
* that seam was supplied, and the agent loop gates automatic compaction on it.
|
|
1590
1639
|
*
|
|
1591
1640
|
* @remarks
|
|
1592
|
-
* - **Live tail + sections.** The conversation
|
|
1641
|
+
* - **Live tail + sections.** The conversation owns its live uncompacted tail directly — a
|
|
1593
1642
|
* caller appends turns through its own message verbs (`add` mints each `id`, `message` /
|
|
1594
1643
|
* `messages` look up, `remove` / `clear` drop, `count` tallies), exactly as a `Workspace`
|
|
1595
1644
|
* owns its files (no separate per-value manager). `sections` are the compacted history
|
|
1596
|
-
* (oldest → newest), each a summarized slice that
|
|
1645
|
+
* (oldest → newest), each a summarized slice that retains its originals. `summary` is the
|
|
1597
1646
|
* conversation rollup (a summary-of-summaries over all sections), regenerated on each
|
|
1598
1647
|
* compaction (`undefined` until the first compaction).
|
|
1599
1648
|
* - **Message verbs (the inlined store).** `add` takes one {@link MessageInput} or a batch,
|
|
1600
|
-
*
|
|
1649
|
+
* mints each message's `id` (a random UUID), stores it, and returns the created
|
|
1601
1650
|
* message(s); a stored message is immutable. `message(id)` resolves one (`undefined` when
|
|
1602
1651
|
* absent); `messages()` lists the live tail in insertion order; `remove` drops one by id or
|
|
1603
|
-
* a batch (`true` only when
|
|
1652
|
+
* a batch (`true` only when every supplied id was removed); `clear` empties the tail;
|
|
1604
1653
|
* `count` is how many live messages are stored.
|
|
1605
|
-
* - **`view()` — the model input.** Each section folds to
|
|
1654
|
+
* - **`view()` — the model input.** Each section folds to one synthetic summary message,
|
|
1606
1655
|
* followed by the live messages verbatim: `[...sections-as-summary-messages, ...live]`. The
|
|
1607
|
-
* rollup `summary` is
|
|
1608
|
-
* cross-conversation case); `view()` carries the per-section summaries, which
|
|
1656
|
+
* rollup `summary` is not injected (it is a separately pull-able digest for a
|
|
1657
|
+
* cross-conversation case); `view()` carries the per-section summaries, which are the
|
|
1609
1658
|
* compaction benefit.
|
|
1610
1659
|
* - **`compact()` — fold older live → a section.** Folds the oldest `count - keep` live
|
|
1611
1660
|
* messages into a new {@link Section} (its `summary` from `summarize`), removes
|
|
1612
|
-
* them from the live tail,
|
|
1661
|
+
* them from the live tail, regenerates the rollup (a second `summarize` over all section
|
|
1613
1662
|
* summaries), and emits `summary` then `compact` — returning the new section (or
|
|
1614
|
-
* `undefined` when nothing folds).
|
|
1615
|
-
*
|
|
1616
|
-
* `summarize` was supplied.
|
|
1617
|
-
* - **`summarizable` — whether a `compact()`
|
|
1618
|
-
* {@link ConversationSummaryHandler} was supplied, `false` otherwise. The agent loop's
|
|
1663
|
+
* `undefined` when nothing folds). A compaction calls the summarizer for the section
|
|
1664
|
+
* digest and again for the rollup. Throws a
|
|
1665
|
+
* {@link import('./errors.js').ConversationError} when no `summarize` was supplied.
|
|
1666
|
+
* - **`summarizable` — whether a `compact()` can fold.** `true` when a
|
|
1667
|
+
* {@link ConversationSummaryHandler} was supplied, `false` otherwise. The agent loop's automatic
|
|
1619
1668
|
* compaction (`AgentOptions.window`) gates on it so a conversation that has no summarizer is
|
|
1620
1669
|
* never auto-compacted (and the loop never throws the `compact()` `SUMMARIZER` error from the
|
|
1621
|
-
* auto path). A
|
|
1670
|
+
* auto path). A manual `compact()` still throws without a summarizer — only the auto path is
|
|
1622
1671
|
* guarded.
|
|
1623
1672
|
* - **`rehydrate(id)` / `search(query)` — read the retained originals.** `rehydrate` returns
|
|
1624
1673
|
* a section's full original messages (`[]` for an unknown id) and emits `rehydrate` — a
|
|
1625
|
-
* pure
|
|
1626
|
-
* `search` is a case-insensitive substring scan of `content` across
|
|
1674
|
+
* pure read (the caller decides whether to re-add them; `rehydrate` never reinserts).
|
|
1675
|
+
* `search` is a case-insensitive substring scan of `content` across all messages (every
|
|
1627
1676
|
* section's originals + the live tail).
|
|
1628
|
-
* - **`reference(options?)` — pull
|
|
1677
|
+
* - **`reference(options?)` — pull this conversation into another with provenance.** A pure
|
|
1629
1678
|
* string render (no model call) of a self-labeled, fenced cross-conversation block — the
|
|
1630
1679
|
* rollup `summary` (when included + present) plus cherry-picked excerpts — framed so a small
|
|
1631
|
-
* model reads it as
|
|
1680
|
+
* model reads it as foreign material. Written into the active conversation's context through
|
|
1632
1681
|
* the active workspace (`context.workspaces.active?.write(path, block)`); the cherry-pick
|
|
1633
1682
|
* comes from this conversation's own `search` / `rehydrate`, never its whole history.
|
|
1634
1683
|
* - **Observable.** The owned `emitter` ({@link ConversationEventMap}) carries
|
|
@@ -1643,17 +1692,18 @@ export declare interface ConversationInterface {
|
|
|
1643
1692
|
/** Lists the compacted history, oldest → newest. */
|
|
1644
1693
|
readonly sections: readonly Section[];
|
|
1645
1694
|
/**
|
|
1646
|
-
* Reports whether a `compact()`
|
|
1647
|
-
* The agent loop's
|
|
1695
|
+
* Reports whether a `compact()` can fold — `true` when a {@link ConversationSummaryHandler} was supplied.
|
|
1696
|
+
* The agent loop's automatic compaction (`AgentOptions.window`) gates on it (a non-summarizable
|
|
1648
1697
|
* conversation is never auto-compacted, so the auto path never throws the `SUMMARIZER` error);
|
|
1649
|
-
* a
|
|
1698
|
+
* a manual `compact()` still throws without a summarizer.
|
|
1650
1699
|
*/
|
|
1651
1700
|
readonly summarizable: boolean;
|
|
1652
|
-
/** Counts the
|
|
1701
|
+
/** Counts the live (uncompacted) messages stored in the tail. */
|
|
1653
1702
|
readonly count: number;
|
|
1654
1703
|
/**
|
|
1655
|
-
* Appends one
|
|
1656
|
-
* (a random UUID) and returns the created message
|
|
1704
|
+
* Appends one {@link MessageInput} to the live tail, or a batch — mints each message's `id`
|
|
1705
|
+
* (a random UUID) and returns the created message or messages; a stored message is
|
|
1706
|
+
* immutable.
|
|
1657
1707
|
*
|
|
1658
1708
|
* @param input - One {@link MessageInput}, or a batch
|
|
1659
1709
|
* @returns The created {@link Message}(s), with their minted `id`s
|
|
@@ -1661,50 +1711,52 @@ export declare interface ConversationInterface {
|
|
|
1661
1711
|
add(input: MessageInput): Message;
|
|
1662
1712
|
add(inputs: readonly MessageInput[]): readonly Message[];
|
|
1663
1713
|
/**
|
|
1664
|
-
* Looks up one
|
|
1714
|
+
* Looks up one live message by id (`undefined` when absent).
|
|
1665
1715
|
*
|
|
1666
1716
|
* @param id - The message id to resolve
|
|
1667
1717
|
* @returns The {@link Message}, or `undefined` when absent
|
|
1668
1718
|
*/
|
|
1669
1719
|
message(id: string): Message | undefined;
|
|
1670
1720
|
/**
|
|
1671
|
-
* Lists every
|
|
1721
|
+
* Lists every live, uncompacted message in the tail, in insertion order.
|
|
1672
1722
|
*
|
|
1673
1723
|
* @returns The live tail, in insertion order
|
|
1674
1724
|
*/
|
|
1675
1725
|
messages(): readonly Message[];
|
|
1676
1726
|
/**
|
|
1677
|
-
* Removes one
|
|
1727
|
+
* Removes one live message by id, or a batch, from the tail — `true` only when every
|
|
1728
|
+
* supplied id was removed.
|
|
1678
1729
|
*
|
|
1679
1730
|
* @param id - One message id, or a batch
|
|
1680
1731
|
* @returns True when every supplied id was present and removed; false otherwise
|
|
1681
1732
|
*/
|
|
1682
1733
|
remove(id: string): boolean;
|
|
1683
1734
|
remove(ids: readonly string[]): boolean;
|
|
1684
|
-
/** Empties the live tail
|
|
1735
|
+
/** Empties the live tail, leaving the compacted `sections` untouched. */
|
|
1685
1736
|
clear(): void;
|
|
1686
1737
|
/**
|
|
1687
|
-
* Builds the model input for the next turn — each section as
|
|
1688
|
-
*
|
|
1738
|
+
* Builds the model input for the next turn — each section as one synthetic recap message,
|
|
1739
|
+
* its summary prefixed with `CONVERSATION_RECAP_PREFIX` so a small model reads it as a
|
|
1740
|
+
* recap rather than a literal turn, then the live tail verbatim; the rollup `summary` is
|
|
1741
|
+
* not injected.
|
|
1689
1742
|
*
|
|
1690
1743
|
* @returns `[...sections-as-summary-messages, ...live messages]`
|
|
1691
1744
|
*/
|
|
1692
1745
|
view(): readonly Message[];
|
|
1693
1746
|
/**
|
|
1694
|
-
* Folds the
|
|
1695
|
-
*
|
|
1747
|
+
* Folds the oldest `count - keep` live messages into a summarized {@link Section} through
|
|
1748
|
+
* the {@link ConversationSummaryHandler}, removes them from the live tail, regenerates the
|
|
1749
|
+
* rollup, and emits `summary` then `compact` — resolving `undefined` when nothing folds
|
|
1750
|
+
* (`count <= keep`). Throws a {@link import('./errors.js').ConversationError} when no
|
|
1751
|
+
* summarizer was supplied.
|
|
1696
1752
|
*
|
|
1697
1753
|
* @remarks
|
|
1698
|
-
*
|
|
1699
|
-
*
|
|
1700
|
-
* `undefined`. Otherwise it summarizes the slice into the section, removes those messages
|
|
1701
|
-
* from the live tail, regenerates the rollup (a second `summarize` over all sections), and
|
|
1702
|
-
* resolves the new section. Requires a {@link ConversationSummaryHandler} — THROWS a
|
|
1703
|
-
* {@link import('./errors.js').ConversationError} when none was supplied.
|
|
1754
|
+
* The effective `keep` comes from `options`, else the conversation's own. Regenerating the
|
|
1755
|
+
* rollup runs `summarize` again, over all sections.
|
|
1704
1756
|
*
|
|
1705
1757
|
* @remarks
|
|
1706
1758
|
* When a `sections` cap is set and the fold pushes the section count over it, an overflow
|
|
1707
|
-
* merge step folds the oldest sections into one — if
|
|
1759
|
+
* merge step folds the oldest sections into one — if that merge's `summarize` call throws,
|
|
1708
1760
|
* the merge is skipped (sections transiently sit at `cap + 1`, no loss) but the rollup still
|
|
1709
1761
|
* regenerates over the current unmerged sections (never left stale) before the error
|
|
1710
1762
|
* propagates; the next successful `compact()` self-heals the section count back to `cap`.
|
|
@@ -1714,35 +1766,38 @@ export declare interface ConversationInterface {
|
|
|
1714
1766
|
*/
|
|
1715
1767
|
compact(options?: CompactOptions): Promise<Section | undefined>;
|
|
1716
1768
|
/**
|
|
1717
|
-
* Returns a section's full original messages — a pure
|
|
1769
|
+
* Returns a section's full original messages — a pure read that emits `rehydrate`, empty for
|
|
1770
|
+
* an unknown id and never reinserting.
|
|
1718
1771
|
*
|
|
1719
1772
|
* @param id - The {@link Section} `id` to pull back
|
|
1720
1773
|
* @returns The section's retained original messages (empty when no such section)
|
|
1721
1774
|
*/
|
|
1722
1775
|
rehydrate(id: string): readonly Message[];
|
|
1723
1776
|
/**
|
|
1724
|
-
* Searches `content` for a case-insensitive substring across
|
|
1725
|
-
* retained originals
|
|
1777
|
+
* Searches `content` for a case-insensitive substring across every message — each section's
|
|
1778
|
+
* retained originals, then the live tail.
|
|
1726
1779
|
*
|
|
1727
1780
|
* @param query - The substring to match (case-insensitive)
|
|
1728
1781
|
* @returns The matching messages, sections' originals first then the live tail
|
|
1729
1782
|
*/
|
|
1730
1783
|
search(query: string): readonly Message[];
|
|
1731
1784
|
/**
|
|
1732
|
-
* Renders
|
|
1733
|
-
* conversation — a pure string
|
|
1734
|
-
*
|
|
1785
|
+
* Renders this conversation as a self-labeled, fenced provenance block to pull into another
|
|
1786
|
+
* conversation — a pure string with no model call: a leading
|
|
1787
|
+
* `[Reference — conversation "<label>" — NOT part of this conversation]` marker, the rollup
|
|
1788
|
+
* `Summary:` when `summary` is not `false` and a rollup exists, and the cherry-picked
|
|
1789
|
+
* excerpts (`- role: content`) when `messages` is supplied. `label` defaults to the `id`.
|
|
1735
1790
|
*
|
|
1736
1791
|
* @remarks
|
|
1737
1792
|
* The block leads with an unmistakable provenance marker
|
|
1738
1793
|
* (`[Reference — conversation "<label>" — NOT part of this conversation]`), then optionally
|
|
1739
|
-
* the rollup `Summary:` (when `options.summary !== false`
|
|
1794
|
+
* the rollup `Summary:` (when `options.summary !== false` and a rollup exists), then the
|
|
1740
1795
|
* cherry-picked `Relevant messages:` (each `- role: content`) when `options.messages` is
|
|
1741
1796
|
* supplied. The intended flow is to pull another conversation B into the active conversation
|
|
1742
1797
|
* A's active workspace: decide relevance from `B.summary`, select the few right turns with
|
|
1743
1798
|
* `B.search(query)` / `B.rehydrate(id)`, frame them here, then
|
|
1744
1799
|
* `A.context.workspaces.active?.write(\`conversation:${B.id}.md\`, B.reference({ label, messages }))`.
|
|
1745
|
-
* Keep the excerpts
|
|
1800
|
+
* Keep the excerpts cherry-picked, never B's whole history — this content enters another
|
|
1746
1801
|
* context a small model must read.
|
|
1747
1802
|
*
|
|
1748
1803
|
* @param options - The {@link ConversationReferenceOptions} (label / summary / cherry-picked messages)
|
|
@@ -1750,17 +1805,18 @@ export declare interface ConversationInterface {
|
|
|
1750
1805
|
*/
|
|
1751
1806
|
reference(options?: ConversationReferenceOptions): string;
|
|
1752
1807
|
/**
|
|
1753
|
-
* Serializes this conversation to a plain, JSON-serializable {@link ConversationSnapshot} —
|
|
1754
|
-
* `id`, the rollup `summary`, the compacted `sections`, and the live tail
|
|
1808
|
+
* Serializes this conversation to a plain, JSON-serializable {@link ConversationSnapshot} —
|
|
1809
|
+
* its `id`, the rollup `summary`, the compacted `sections`, and the live tail; the live
|
|
1810
|
+
* `summarize` / `keep` are configuration re-supplied on hydrate rather than serialized.
|
|
1755
1811
|
*
|
|
1756
1812
|
* @remarks
|
|
1757
|
-
* The container serializes
|
|
1813
|
+
* The container serializes itself (`{ id, summary, sections, messages: this.messages() }`) — the
|
|
1758
1814
|
* {@link ConversationStoreInterface} persistence seam's payload, the exact analogue of
|
|
1759
1815
|
* {@link import('@orkestrel/workspace').WorkspaceInterface}'s `snapshot`. The summarizer /
|
|
1760
|
-
* `keep` are
|
|
1761
|
-
*
|
|
1816
|
+
* `keep` are not serialized — they are live
|
|
1817
|
+
* config re-supplied on hydrate (a `ConversationSummaryHandler` is a function, not data). The snapshot
|
|
1762
1818
|
* is the durable analogue of the `snapshot` option: a {@link ConversationManagerInterface}
|
|
1763
|
-
*
|
|
1819
|
+
* hydrates a conversation from it through that seam (see {@link ConversationManagerInterface.open}).
|
|
1764
1820
|
* Pure — the sections + messages are already plain immutable records (so the snapshot
|
|
1765
1821
|
* `structuredClone`s / JSON-round-trips losslessly), and snapshotting mutates nothing.
|
|
1766
1822
|
*
|
|
@@ -1770,26 +1826,27 @@ export declare interface ConversationInterface {
|
|
|
1770
1826
|
}
|
|
1771
1827
|
|
|
1772
1828
|
/**
|
|
1773
|
-
* Registers {@link Conversation}s keyed by `id`, in insertion order,
|
|
1774
|
-
*
|
|
1775
|
-
* {@link import('../AgentContext.js').AgentContext} renders
|
|
1776
|
-
*
|
|
1777
|
-
*
|
|
1829
|
+
* Registers {@link Conversation}s keyed by `id`, in insertion order, with an active pointer —
|
|
1830
|
+
* the id-keyed store over the conversation layer, the `active` / `switch` seam the
|
|
1831
|
+
* {@link import('../AgentContext.js').AgentContext} renders, and the durable `open` / `save`
|
|
1832
|
+
* store seam. Event-free (a registry, like
|
|
1833
|
+
* {@link import('@orkestrel/workspace').WorkspaceManager}); the observability lives on each
|
|
1834
|
+
* {@link Conversation}.
|
|
1778
1835
|
*
|
|
1779
1836
|
* @remarks
|
|
1780
1837
|
* - **Registry.** Conversations live in an insertion-ordered `Map` keyed by `id`. `add(input?)`
|
|
1781
1838
|
* mints a {@link Conversation} (its `id` from `input` or `crypto.randomUUID()`), flowing the
|
|
1782
|
-
* manager's default `#summarize` / `#keep` in unless the `input`
|
|
1783
|
-
* it (an already-present `id`
|
|
1839
|
+
* manager's default `#summarize` / `#keep` in unless the `input` overrides them, and stores
|
|
1840
|
+
* it (an already-present `id` overwrites — last write wins). `count` is the map size,
|
|
1784
1841
|
* `conversation(id)` looks one up, `conversations()` lists them in insertion order.
|
|
1785
1842
|
* - **Active pointer.** `active` is the active conversation (the agent's message source the
|
|
1786
|
-
* context renders), `undefined` until the
|
|
1843
|
+
* context renders), `undefined` until the first `add` (which auto-activates it — a registry
|
|
1787
1844
|
* with conversations always has one active). A subsequent `add` leaves `active` unchanged.
|
|
1788
1845
|
* `switch(id)` re-points `active` to the conversation with `id` and returns it; an unknown `id`
|
|
1789
1846
|
* returns `undefined` and leaves `active` unchanged (the lenient lookup style — never throws,
|
|
1790
1847
|
* no new error code).
|
|
1791
|
-
* - **Removal.** `remove` drops one by id, or a batch — `true` only when
|
|
1792
|
-
* removed; removing the
|
|
1848
|
+
* - **Removal.** `remove` drops one by id, or a batch — `true` only when every supplied id was
|
|
1849
|
+
* removed; removing the active conversation sets `active` to `undefined`. `clear` empties the registry
|
|
1793
1850
|
* and sets `active` to `undefined`.
|
|
1794
1851
|
* - **Event-free.** A purely registry store — no Emitter, no events (each conversation owns
|
|
1795
1852
|
* its own observable `emitter`).
|
|
@@ -1820,32 +1877,32 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1820
1877
|
}
|
|
1821
1878
|
|
|
1822
1879
|
/**
|
|
1823
|
-
* Registers {@link ConversationInterface}s keyed by their `id`, in insertion order,
|
|
1824
|
-
*
|
|
1825
|
-
*
|
|
1826
|
-
* {@link import('@orkestrel/workspace').WorkspaceManagerInterface}); the
|
|
1827
|
-
* {@link ConversationInterface}.
|
|
1880
|
+
* Registers {@link ConversationInterface}s keyed by their `id`, in insertion order, with an active
|
|
1881
|
+
* pointer — the id-keyed store over the conversation layer, the `active` / `switch` seam the {@link
|
|
1882
|
+
* AgentContextInterface} renders, and the durable `open` / `save` store seam. Event-free (a
|
|
1883
|
+
* registry, like {@link import('@orkestrel/workspace').WorkspaceManagerInterface}); the
|
|
1884
|
+
* observability lives on each {@link ConversationInterface}.
|
|
1828
1885
|
*
|
|
1829
1886
|
* @remarks
|
|
1830
1887
|
* - **Registry.** `count` is how many are stored. `add(input?)` mints a
|
|
1831
1888
|
* {@link ConversationInterface} (its `id` from `input` or a random UUID), flowing the
|
|
1832
1889
|
* manager's default `summarize` / `keep` in unless the `input` overrides them; `add` of an
|
|
1833
|
-
* already-present `id`
|
|
1890
|
+
* already-present `id` overwrites it (last write wins). `conversation(id)` looks one up
|
|
1834
1891
|
* (`undefined` when absent); `conversations()` lists them in insertion order.
|
|
1835
1892
|
* - **Active pointer.** `active` is the active conversation (the agent's message source the
|
|
1836
|
-
* context renders), `undefined` until the
|
|
1893
|
+
* context renders), `undefined` until the first `add` (which auto-activates it — a registry
|
|
1837
1894
|
* with conversations always has one active). A subsequent `add` leaves `active` unchanged.
|
|
1838
1895
|
* `switch(id)` re-points `active` to the conversation with `id` and returns it; an unknown
|
|
1839
1896
|
* `id` returns `undefined` and leaves `active` unchanged (the lenient lookup style — never
|
|
1840
1897
|
* throws, no new error code).
|
|
1841
|
-
* - **Removal.** `remove` drops one by id, or a batch (array overload
|
|
1842
|
-
* only when
|
|
1898
|
+
* - **Removal.** `remove` drops one by id, or a batch (the array overload declared first) — `true`
|
|
1899
|
+
* only when every supplied id was removed; removing the active conversation sets `active` to `undefined`. `clear`
|
|
1843
1900
|
* empties the registry and sets `active` to `undefined`.
|
|
1844
1901
|
* - **Durable open / save (the optional `store` seam).** When a {@link ConversationStoreInterface}
|
|
1845
|
-
* is supplied (the `store` option), `open(id)`
|
|
1902
|
+
* is supplied (the `store` option), `open(id)` hydrates a conversation from the store on a registry
|
|
1846
1903
|
* miss (rebuilding it through the `snapshot` option, flowing the manager's
|
|
1847
|
-
* default `summarize` / `keep` in) and `save(id)`
|
|
1848
|
-
* {@link ConversationInterface.snapshot}. Both are
|
|
1904
|
+
* default `summarize` / `keep` in) and `save(id)` persists a registered conversation's
|
|
1905
|
+
* {@link ConversationInterface.snapshot}. Both are lenient without a store — `open` resolves only
|
|
1849
1906
|
* registered ids, `save` is a no-op (`false`) — consistent with the lenient `switch`. It mirrors
|
|
1850
1907
|
* the workspace package manager's `open` / `save` seam.
|
|
1851
1908
|
* - **Event-free.** A purely registry store — no Emitter, no events (each conversation owns
|
|
@@ -1855,47 +1912,66 @@ export declare interface ConversationManagerInterface {
|
|
|
1855
1912
|
readonly count: number;
|
|
1856
1913
|
/** Holds the active conversation — the agent's message source the context renders; `undefined` until the first `add`. */
|
|
1857
1914
|
readonly active: ConversationInterface | undefined;
|
|
1915
|
+
/** Looks up one conversation by id (`undefined` when absent). */
|
|
1858
1916
|
conversation(id: string): ConversationInterface | undefined;
|
|
1917
|
+
/** Lists every conversation, in insertion order. */
|
|
1859
1918
|
conversations(): readonly ConversationInterface[];
|
|
1919
|
+
/**
|
|
1920
|
+
* Mints a conversation, taking its `id` from the input or a fresh UUID and flowing the
|
|
1921
|
+
* manager's default `summarize` / `keep` in unless the input overrides them — auto-activates
|
|
1922
|
+
* the first, and an already-present `id` overwrites, last write wins.
|
|
1923
|
+
*/
|
|
1860
1924
|
add(input?: ConversationInput): ConversationInterface;
|
|
1925
|
+
/**
|
|
1926
|
+
* Re-points `active` at the conversation with `id` and returns it; an unknown `id` returns
|
|
1927
|
+
* `undefined` and leaves `active` unchanged, never throwing.
|
|
1928
|
+
*/
|
|
1861
1929
|
switch(id: string): ConversationInterface | undefined;
|
|
1862
1930
|
/**
|
|
1863
|
-
* Resolves a conversation by id
|
|
1864
|
-
* the optional {@link ConversationStoreInterface} (`store`)
|
|
1931
|
+
* Resolves a conversation by id and activates it — from the registry when present, else
|
|
1932
|
+
* hydrated from the optional {@link ConversationStoreInterface} (`store`); `undefined` when
|
|
1933
|
+
* it is neither registered nor stored.
|
|
1865
1934
|
*
|
|
1866
1935
|
* @remarks
|
|
1867
|
-
* - If `id` is
|
|
1868
|
-
* - Else if a `store` is set, `store.get(id)` is awaited; on a
|
|
1936
|
+
* - If `id` is already registered, it is activated (`switch`ed to) and returned — no store hit.
|
|
1937
|
+
* - Else if a `store` is set, `store.get(id)` is awaited; on a hit the snapshot is rehydrated
|
|
1869
1938
|
* into a fresh {@link ConversationInterface} through the `snapshot` option
|
|
1870
1939
|
* (`add({ snapshot, ... })`, flowing the manager's default `summarize` / `keep` in), which
|
|
1871
|
-
* registers
|
|
1872
|
-
* - Else (no store, or a store
|
|
1940
|
+
* registers and activates it, and it is returned.
|
|
1941
|
+
* - Else (no store, or a store miss) ⇒ `undefined` (lenient — no throw).
|
|
1873
1942
|
*
|
|
1874
1943
|
* @param id - The conversation id to open
|
|
1875
1944
|
* @returns The activated {@link ConversationInterface}, or `undefined` when neither registered nor stored
|
|
1876
1945
|
*/
|
|
1877
1946
|
open(id: string): Promise<ConversationInterface | undefined>;
|
|
1878
1947
|
/**
|
|
1879
|
-
* Persists a
|
|
1880
|
-
* {@link ConversationStoreInterface} (`store`)
|
|
1948
|
+
* Persists a registered conversation's {@link ConversationInterface.snapshot} to the optional
|
|
1949
|
+
* {@link ConversationStoreInterface} (`store`) — `true` when persisted, `false` when there is
|
|
1950
|
+
* no store or the id is unknown, and never throwing.
|
|
1881
1951
|
*
|
|
1882
1952
|
* @remarks
|
|
1883
|
-
* Lenient: when a `store` is set
|
|
1884
|
-
* awaited and `true` is returned; otherwise (no store,
|
|
1953
|
+
* Lenient: when a `store` is set and `id` is registered, `store.set(conversation.snapshot())` is
|
|
1954
|
+
* awaited and `true` is returned; otherwise (no store, or an unknown id) it is a no-op returning
|
|
1885
1955
|
* `false` — never a throw, consistent with the lenient `switch`.
|
|
1886
1956
|
*
|
|
1887
1957
|
* @param id - The id of the registered conversation to persist
|
|
1888
1958
|
* @returns True if the snapshot was persisted; false otherwise (no store, or an unknown id)
|
|
1889
1959
|
*/
|
|
1890
1960
|
save(id: string): Promise<boolean>;
|
|
1961
|
+
/**
|
|
1962
|
+
* Removes one conversation by id, or a batch — `true` only when every supplied id was
|
|
1963
|
+
* removed; clears `active` when a removed conversation was the active one.
|
|
1964
|
+
*/
|
|
1891
1965
|
remove(ids: readonly string[]): boolean;
|
|
1892
1966
|
remove(id: string): boolean;
|
|
1967
|
+
/** Removes every conversation and clears `active`. */
|
|
1893
1968
|
clear(): void;
|
|
1894
1969
|
}
|
|
1895
1970
|
|
|
1896
1971
|
/**
|
|
1897
|
-
* Configures `createConversationManager` — the default
|
|
1898
|
-
*
|
|
1972
|
+
* Configures `createConversationManager` — the default `ConversationSummaryHandler`, retained-tail
|
|
1973
|
+
* size, and `sections` cap the conversations it creates inherit, plus the optional durable `store`
|
|
1974
|
+
* backing `open` / `save`.
|
|
1899
1975
|
*
|
|
1900
1976
|
* @remarks
|
|
1901
1977
|
* `summarize` is the default summarizer flowed into every conversation the manager `add`s
|
|
@@ -1916,8 +1992,8 @@ export declare interface ConversationManagerOptions {
|
|
|
1916
1992
|
/**
|
|
1917
1993
|
* Holds the optional durable {@link ConversationStoreInterface} backing
|
|
1918
1994
|
* {@link ConversationManagerInterface.open} / {@link ConversationManagerInterface.save} — a memory
|
|
1919
|
-
* / JSON / SQLite / IndexedDB store a conversation is
|
|
1920
|
-
*
|
|
1995
|
+
* / JSON / SQLite / IndexedDB store a conversation is hydrated from (`open` a registry-miss) and
|
|
1996
|
+
* persisted to (`save`). Omitted ⇒ the manager is registry-only: `open` resolves only what is
|
|
1921
1997
|
* already registered, and `save` is a no-op (`false`). The exact analogue of
|
|
1922
1998
|
* {@link import('@orkestrel/workspace').WorkspaceManagerOptions}'s `store`.
|
|
1923
1999
|
*/
|
|
@@ -1926,25 +2002,26 @@ export declare interface ConversationManagerOptions {
|
|
|
1926
2002
|
|
|
1927
2003
|
/**
|
|
1928
2004
|
* Configures `createConversation` — the optional `id`, the reserved `on` hooks, the
|
|
1929
|
-
* provider-agnostic `summarize` seam,
|
|
2005
|
+
* provider-agnostic `summarize` seam, the retained-tail size, an optional cap on the compacted
|
|
2006
|
+
* `sections` list, and a {@link ConversationSnapshot} to hydrate from.
|
|
1930
2007
|
*
|
|
1931
2008
|
* @remarks
|
|
1932
2009
|
* `id` is the conversation's identity (a random UUID when omitted). `on` is the reserved
|
|
1933
2010
|
* listener key (initial {@link ConversationEventMap} listeners). `summarize` is the
|
|
1934
|
-
* {@link ConversationSummaryHandler} compaction needs —
|
|
2011
|
+
* {@link ConversationSummaryHandler} compaction needs — absent ⇒ `compact()` throws a
|
|
1935
2012
|
* {@link import('./errors.js').ConversationError} (a conversation can still store + view a
|
|
1936
2013
|
* live tail; it cannot fold). `keep` is how many recent live messages a `compact()`
|
|
1937
|
-
* retains
|
|
2014
|
+
* retains verbatim (folding only the older ones); it defaults to
|
|
1938
2015
|
* {@link import('./constants.js').DEFAULT_CONVERSATION_KEEP} (`0` — a manual `compact()`
|
|
1939
|
-
* folds the
|
|
2016
|
+
* folds the whole current live tail into one section). `sections` is an optional cap on the
|
|
1940
2017
|
* compacted `sections` list — when set (`>= 1`), a `compact()` that would leave more than
|
|
1941
|
-
* `sections` sections
|
|
2018
|
+
* `sections` sections folds the oldest overflow into one merged section so the list never
|
|
1942
2019
|
* exceeds `sections`, emitting `collapse`; omitted ⇒ unlimited (the prior behavior).
|
|
1943
|
-
* `snapshot` is the
|
|
1944
|
-
* `summary`, compacted `sections`, and live tail are
|
|
2020
|
+
* `snapshot` is the hydration seam — a {@link ConversationSnapshot} whose `id`, rollup
|
|
2021
|
+
* `summary`, compacted `sections`, and live tail are restored into the new conversation, with
|
|
1945
2022
|
* the live `summarize` / `keep` / `on` supplied alongside it (a summarizer is a function, not
|
|
1946
|
-
* serialized data). Restoring is
|
|
1947
|
-
*
|
|
2023
|
+
* serialized data). Restoring is silent (no events — nothing was edited), and a `snapshot.id`
|
|
2024
|
+
* wins over `id` (the snapshot is the conversation's identity). It is what lets
|
|
1948
2025
|
* `createConversation` hydrate, and what a {@link ConversationManagerInterface.open} reads a
|
|
1949
2026
|
* stored snapshot back through.
|
|
1950
2027
|
*/
|
|
@@ -1953,7 +2030,7 @@ export declare interface ConversationOptions {
|
|
|
1953
2030
|
readonly on?: EmitterHooks<ConversationEventMap>;
|
|
1954
2031
|
/** Holds the emitter's listener-error handler — a listener throw routes here, not to a domain event. */
|
|
1955
2032
|
readonly error?: EmitterErrorHandler;
|
|
1956
|
-
/** Supplies the summarizer compaction needs;
|
|
2033
|
+
/** Supplies the summarizer compaction needs; absent ⇒ `compact()` throws a `ConversationError`. */
|
|
1957
2034
|
readonly summarize?: ConversationSummaryHandler;
|
|
1958
2035
|
/** Keeps this many recent live messages verbatim on `compact`; defaults to `DEFAULT_CONVERSATION_KEEP` (`0`). */
|
|
1959
2036
|
readonly keep?: number;
|
|
@@ -1964,22 +2041,23 @@ export declare interface ConversationOptions {
|
|
|
1964
2041
|
}
|
|
1965
2042
|
|
|
1966
2043
|
/**
|
|
1967
|
-
* Configures {@link ConversationInterface.reference} — how to render
|
|
1968
|
-
* self-labeled, fenced
|
|
1969
|
-
*
|
|
2044
|
+
* Configures {@link ConversationInterface.reference} — how to render one conversation as a
|
|
2045
|
+
* self-labeled, fenced provenance block to pull into another conversation by writing it to the
|
|
2046
|
+
* active context's active workspace: `label` defaults to the `id`, `summary` defaults to `true`,
|
|
2047
|
+
* and `messages` are cherry-picked excerpts defaulting to none.
|
|
1970
2048
|
*
|
|
1971
2049
|
* @remarks
|
|
1972
|
-
* The rendered block is a cross-conversation reference a
|
|
1973
|
-
* material,
|
|
2050
|
+
* The rendered block is a cross-conversation reference a small model must read as foreign
|
|
2051
|
+
* material, not as part of the live thread — so every member keeps it concise and unmistakably
|
|
1974
2052
|
* attributed:
|
|
1975
|
-
* - `label` — the human
|
|
2053
|
+
* - `label` — the human provenance name shown in the block's leading marker (for example `'planning'`);
|
|
1976
2054
|
* defaults to the conversation's own `id`. It is what the model attributes the content to.
|
|
1977
2055
|
* - `summary` — whether to include the conversation's rollup `summary` (its summary-of-summaries)
|
|
1978
|
-
* in the block; defaults to `true` (the rollup is included
|
|
2056
|
+
* in the block; defaults to `true` (the rollup is included when one exists — `undefined` until
|
|
1979
2057
|
* the first compaction omits the `Summary:` line). Pass `false` to exclude it.
|
|
1980
|
-
* - `messages` — the
|
|
1981
|
-
*
|
|
1982
|
-
* (select the few relevant turns),
|
|
2058
|
+
* - `messages` — the cherry-picked excerpts to include (each rendered `role: content`), default
|
|
2059
|
+
* none. The intended source is the conversation's own `search(query)` / `rehydrate(id)` output
|
|
2060
|
+
* (select the few relevant turns), not its whole history — dumping every message defeats the
|
|
1983
2061
|
* point (it re-bloats the destination context a small model then has to wade through).
|
|
1984
2062
|
*/
|
|
1985
2063
|
export declare interface ConversationReferenceOptions {
|
|
@@ -1998,11 +2076,11 @@ export declare interface ConversationReferenceOptions {
|
|
|
1998
2076
|
* {@link import('@orkestrel/workspace').WorkspaceSnapshot}.
|
|
1999
2077
|
*
|
|
2000
2078
|
* @remarks
|
|
2001
|
-
* Pure JSON
|
|
2002
|
-
* {@link Message} is already a
|
|
2079
|
+
* Pure JSON data (no class instances, no functions): each {@link Section} and
|
|
2080
|
+
* {@link Message} is already a plain record that `structuredClone`s / JSON-round-trips
|
|
2003
2081
|
* losslessly. The snapshot carries the rollup `summary` (a summary-of-summaries; `undefined` until
|
|
2004
|
-
* the first compaction), the compacted `sections` (each
|
|
2005
|
-
* live uncompacted tail `messages` — but
|
|
2082
|
+
* the first compaction), the compacted `sections` (each retaining its folded originals), and the
|
|
2083
|
+
* live uncompacted tail `messages` — but not the `summarize` / `keep`, which are live config
|
|
2006
2084
|
* re-supplied on hydrate (a summarizer is a function, not serializable data). The snapshot the
|
|
2007
2085
|
* container produces from itself ({@link ConversationInterface.snapshot}); the durable analogue of
|
|
2008
2086
|
* the {@link ConversationOptions.snapshot} hydration seam. A {@link ConversationManagerInterface}
|
|
@@ -2014,23 +2092,24 @@ export declare interface ConversationSnapshot {
|
|
|
2014
2092
|
readonly id: string;
|
|
2015
2093
|
/** Holds the rollup (a summary-of-summaries); `undefined` until the first compaction. */
|
|
2016
2094
|
readonly summary?: string;
|
|
2017
|
-
/** Lists the compacted history, oldest → newest (each section
|
|
2095
|
+
/** Lists the compacted history, oldest → newest (each section retains its folded originals). */
|
|
2018
2096
|
readonly sections: readonly Section[];
|
|
2019
2097
|
/** Lists the live uncompacted tail, in insertion order. */
|
|
2020
2098
|
readonly messages: readonly Message[];
|
|
2021
2099
|
}
|
|
2022
2100
|
|
|
2023
2101
|
/**
|
|
2024
|
-
* Represents one row of the table a
|
|
2025
|
-
*
|
|
2026
|
-
*
|
|
2027
|
-
*
|
|
2102
|
+
* Represents one row of the table a {@link
|
|
2103
|
+
* import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore} persists
|
|
2104
|
+
* — a conversation `id` plus its {@link ConversationSnapshot} held as one opaque JSON column, read
|
|
2105
|
+
* back as `unknown` and narrowed on `get`. The exact analogue of {@link
|
|
2106
|
+
* import('@orkestrel/workspace').WorkspaceSnapshotRow}.
|
|
2028
2107
|
*
|
|
2029
2108
|
* @remarks
|
|
2030
2109
|
* The Database twin of {@link ConversationStoreInterface} stores the snapshot whole (the `snapshot`
|
|
2031
2110
|
* column is a `rawShape`, an opaque JSON blob — exactly as
|
|
2032
2111
|
* {@link import('@orkestrel/workspace').WorkspaceSnapshotRow} stores a workspace snapshot), so the
|
|
2033
|
-
* row type stays
|
|
2112
|
+
* row type stays flat and the sections/messages snapshot shape never
|
|
2034
2113
|
* forces the contract to `Infer` it. The column therefore reads back as the broad `unknown`; the
|
|
2035
2114
|
* store narrows it to a {@link ConversationSnapshot} on `get`
|
|
2036
2115
|
* ({@link import('./validators.js').isConversationSnapshot}, the total boundary guard). `id`
|
|
@@ -2044,30 +2123,30 @@ export declare interface ConversationSnapshotRow {
|
|
|
2044
2123
|
}
|
|
2045
2124
|
|
|
2046
2125
|
/**
|
|
2047
|
-
* Persists a {@link ConversationSnapshot} durably —
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
2126
|
+
* Persists a {@link ConversationSnapshot} durably — the async `get` / `set` / `delete` primitives,
|
|
2127
|
+
* keyed by a conversation id and holding no expiry, the exact analogue of {@link
|
|
2128
|
+
* import('@orkestrel/workspace').WorkspaceStoreInterface}.
|
|
2050
2129
|
*
|
|
2051
2130
|
* @remarks
|
|
2052
2131
|
* The store persists the {@link ConversationSnapshot} — the self-contained, pure-JSON conversation
|
|
2053
|
-
* state — so a JSON / SQLite / IndexedDB backend swaps in
|
|
2132
|
+
* state — so a JSON / SQLite / IndexedDB backend swaps in without touching the manager or the
|
|
2054
2133
|
* conversation: the in-memory default
|
|
2055
2134
|
* {@link import('./conversations/stores/MemoryConversationStore.js').MemoryConversationStore} and its
|
|
2056
2135
|
* driver-pluggable twin
|
|
2057
2136
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore} (the
|
|
2058
|
-
* snapshot as one opaque JSON column) share
|
|
2137
|
+
* snapshot as one opaque JSON column) share this one interface. Hydration is not a store concern
|
|
2059
2138
|
* — a {@link ConversationManagerInterface} reads a snapshot back and rebuilds the live conversation
|
|
2060
2139
|
* through the {@link ConversationOptions.snapshot} seam (re-supplying the live `summarize` / `keep`; see
|
|
2061
2140
|
* {@link ConversationManagerInterface.open} / {@link ConversationManagerInterface.save}).
|
|
2062
2141
|
*
|
|
2063
2142
|
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
2064
|
-
* same shape as the memory one. The snapshot carries its
|
|
2143
|
+
* same shape as the memory one. The snapshot carries its own id, so `set` takes no separate id
|
|
2065
2144
|
* param (mirroring
|
|
2066
|
-
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`).
|
|
2067
|
-
* there is
|
|
2145
|
+
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`). Unlike a session store
|
|
2146
|
+
* there is no idle-TTL
|
|
2068
2147
|
* / eviction — a persisted conversation lives until an explicit `delete`. It is concrete over
|
|
2069
2148
|
* {@link ConversationSnapshot} — no generic parameter, because the
|
|
2070
|
-
* snapshot is the
|
|
2149
|
+
* snapshot is the one payload a conversation store persists.
|
|
2071
2150
|
*/
|
|
2072
2151
|
export declare interface ConversationStoreInterface {
|
|
2073
2152
|
/**
|
|
@@ -2093,10 +2172,10 @@ export declare interface ConversationStoreInterface {
|
|
|
2093
2172
|
}
|
|
2094
2173
|
|
|
2095
2174
|
/**
|
|
2096
|
-
* Summarizes a conversation, provider-agnostically — the seam the agent
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
2099
|
-
*
|
|
2175
|
+
* Summarizes a conversation, provider-agnostically — the seam the agent runtime supplies so core
|
|
2176
|
+
* never imports a provider. Given the folded messages, it resolves their digest, the model-written
|
|
2177
|
+
* summary used to summarize a compacted {@link Section} and to regenerate a {@link
|
|
2178
|
+
* ConversationInterface}'s rollup `summary`.
|
|
2100
2179
|
*
|
|
2101
2180
|
* @remarks
|
|
2102
2181
|
* The agent runtime builds one from its `ProviderInterface` (for example
|
|
@@ -2117,10 +2196,10 @@ export declare type ConversationSummaryHandler = (messages: readonly Message[])
|
|
|
2117
2196
|
* `generate` and a live `stream`.
|
|
2118
2197
|
*
|
|
2119
2198
|
* @remarks
|
|
2120
|
-
* One private loop drives the turn; `generate`
|
|
2199
|
+
* One private loop drives the turn; `generate` drains the same stream `stream`
|
|
2121
2200
|
* exposes, so they can never diverge. Each turn is bounded by one cancel folded from
|
|
2122
2201
|
* `signal` + `timeout` + `budget` (through `AbortSignal.any`) — any trip (or `abort()`)
|
|
2123
|
-
* commits a
|
|
2202
|
+
* commits a partial result (the stream's `result` resolves on a cancel, rejects only
|
|
2124
2203
|
* on a genuine provider / tool error). The `scheduler` paces between turns; tool
|
|
2125
2204
|
* iteration is capped at `limit` (default `DEFAULT_AGENT_LIMIT`). Tools are advertised
|
|
2126
2205
|
* structurally through `context.tools.definitions()`. Two observation surfaces: the
|
|
@@ -2155,19 +2234,20 @@ export declare type ConversationSummaryHandler = (messages: readonly Message[])
|
|
|
2155
2234
|
export declare function createAgent(provider: ProviderInterface, options?: AgentOptions): AgentInterface;
|
|
2156
2235
|
|
|
2157
2236
|
/**
|
|
2158
|
-
* Creates a richer turn context — an {@link AgentContextInterface} assembling a provider
|
|
2159
|
-
*
|
|
2160
|
-
* the conversation
|
|
2237
|
+
* Creates a richer turn context — an {@link AgentContextInterface} assembling a provider request
|
|
2238
|
+
* from the optional system prompt, the instruction registry, the workspace registry (the only
|
|
2239
|
+
* document channel), the conversation registry that is its `messages` source, the tool registry,
|
|
2240
|
+
* and the active scope, which `build()` folds into the next turn's input.
|
|
2161
2241
|
*
|
|
2162
2242
|
* @remarks
|
|
2163
2243
|
* `system` is the optional system prompt; `tools` / `instructions` / `workspaces` are pre-built
|
|
2164
|
-
* managers to reuse (empty ones are created when omitted, so `context.workspaces` is
|
|
2244
|
+
* managers to reuse (empty ones are created when omitted, so `context.workspaces` is always
|
|
2165
2245
|
* present); `scope` is the initial active filter (`undefined` ⇒ no filtering, changeable afterwards
|
|
2166
2246
|
* through `context.apply(...)`). The `messages` store is always fresh. `build()` folds the scoped
|
|
2167
|
-
* instructions —
|
|
2247
|
+
* instructions — plus the active workspace's scope-filtered text files (fenced) — into one leading
|
|
2168
2248
|
* `system` message and appends the scoped conversation (attaching the active workspace's
|
|
2169
2249
|
* scope-filtered image files' `base64` payload to the last user message), built fresh each call; the active
|
|
2170
|
-
* workspace is the
|
|
2250
|
+
* workspace is the sole document/image context. Tools are advertised structurally (through
|
|
2171
2251
|
* `tools.definitions()`, scope-filtered by the loop), never serialized into the prompt.
|
|
2172
2252
|
*
|
|
2173
2253
|
* @param options - Optional `system` / `tools` / `instructions` / `workspaces` / `scope`
|
|
@@ -2188,7 +2268,7 @@ export declare function createAgentContext(options?: AgentContextOptions): Agent
|
|
|
2188
2268
|
|
|
2189
2269
|
/**
|
|
2190
2270
|
* Creates a durable, bounded-concurrency agent-job queue — a {@link QueueInterface} over
|
|
2191
|
-
* serializable {@link AgentJobInput}s that
|
|
2271
|
+
* serializable {@link AgentJobInput}s that composes `createQueue`: each job is rehydrated
|
|
2192
2272
|
* through the `registry` into a live {@link AgentInterface}, run to its {@link AgentResult},
|
|
2193
2273
|
* and subjected to the partial-as-configurable-failure policy.
|
|
2194
2274
|
*
|
|
@@ -2201,9 +2281,9 @@ export declare function createAgentContext(options?: AgentContextOptions): Agent
|
|
|
2201
2281
|
* (for example `createMemoryQueueStore` / `createDatabaseQueueStore`) persists outstanding
|
|
2202
2282
|
* jobs; `restore()` re-enqueues them after a restart and the `registry` rehydrates the
|
|
2203
2283
|
* live pieces from the names — so a job survives a crash.
|
|
2204
|
-
* - **Partial policy.** A partial result
|
|
2284
|
+
* - **Partial policy.** A partial result throws an
|
|
2205
2285
|
* {@link import('./errors.js').AgentJobError} by default, so a job cancelled by its
|
|
2206
|
-
* attempt deadline / a queue abort
|
|
2286
|
+
* attempt deadline / a queue abort retries while attempts remain; `partial: true`
|
|
2207
2287
|
* resolves the partial as success instead.
|
|
2208
2288
|
* - **Cancellation threads through.** The handler passes `context.signal` into
|
|
2209
2289
|
* `registry.build`, so a queue `abort()` or a per-attempt timeout cancels the in-flight
|
|
@@ -2234,7 +2314,7 @@ export declare function createAgentQueue(options: AgentQueueOptions): QueueInter
|
|
|
2234
2314
|
*
|
|
2235
2315
|
* @remarks
|
|
2236
2316
|
* `providers` is required; `tools` / `authorities` / `schedulers` are optional pools.
|
|
2237
|
-
* The accessors (`provider` / `tool` / `authority` / `scheduler`)
|
|
2317
|
+
* The accessors (`provider` / `tool` / `authority` / `scheduler`) throw an
|
|
2238
2318
|
* {@link import('./errors.js').AgentError} carrying `code: 'REGISTRY'` and the message
|
|
2239
2319
|
* `unknown <category>: <name>` on an unregistered name — a misconfigured or crash-restored
|
|
2240
2320
|
* job fails loudly rather than running with a missing dependency. `build(input, signal)`
|
|
@@ -2263,21 +2343,21 @@ export declare function createAgentRegistry(options: AgentRegistryOptions): Agen
|
|
|
2263
2343
|
|
|
2264
2344
|
/**
|
|
2265
2345
|
* Creates an agent-job runner — a {@link RunnerInterface} over serializable
|
|
2266
|
-
* {@link AgentJobInput}s that
|
|
2267
|
-
*
|
|
2268
|
-
*
|
|
2346
|
+
* {@link AgentJobInput}s that composes `createRunner` (one-shot, ordered, fail-fast), each unit
|
|
2347
|
+
* rehydrated through the `registry` and subjected to the partial policy. The runner also carries
|
|
2348
|
+
* sub-agent fan-out: a parent job's handler can `controller.spawn(childJob)`.
|
|
2269
2349
|
*
|
|
2270
2350
|
* @remarks
|
|
2271
2351
|
* - **Composes the substrate (no new engine).** Bounded `concurrency`, `retries`, the
|
|
2272
2352
|
* per-attempt `timeout`, ordered results, and fail-fast are all the backing Runner's;
|
|
2273
2353
|
* the handler adds only rehydration + the partial policy.
|
|
2274
2354
|
* - **Sub-agent fan-out.** Each unit's handler receives a `ControllerInterface` whose
|
|
2275
|
-
* `spawn(childJob)` launches a
|
|
2355
|
+
* `spawn(childJob)` launches a child agent job through the same bounded queue (the
|
|
2276
2356
|
* child's result joins the run after the declared units, in spawn order). On a bounded
|
|
2277
|
-
* runner,
|
|
2357
|
+
* runner, fan out and return — do not inline-`await` a spawn from within the handler (a
|
|
2278
2358
|
* slot-holding handler awaiting its own spawn can deadlock; see `ControllerInterface`).
|
|
2279
2359
|
* - **Partial policy + cancellation.** Same as `createAgentQueue`: a partial result
|
|
2280
|
-
*
|
|
2360
|
+
* throws by default (the run's fail-fast engages), `partial: true` resolves it; the
|
|
2281
2361
|
* handler threads `controller.signal` into `registry.build`, so a runner abort / a
|
|
2282
2362
|
* per-attempt timeout cancels the agent.
|
|
2283
2363
|
*
|
|
@@ -2305,11 +2385,11 @@ export declare function createAgentRunner(options: AgentRunnerOptions): RunnerIn
|
|
|
2305
2385
|
* to the configured default when none match.
|
|
2306
2386
|
*
|
|
2307
2387
|
* @remarks
|
|
2308
|
-
* `rules` are evaluated in order — the
|
|
2309
|
-
* rule
|
|
2388
|
+
* `rules` are evaluated in order — the first whose `match` is true decides (a matched
|
|
2389
|
+
* rule allows unless its `allowed` is explicitly `false`). When no rule matches, the
|
|
2310
2390
|
* `fallback` decides; it defaults to `{ zone: DEFAULT_AUTHORITY_ZONE, allowed: true }`
|
|
2311
|
-
* (allow-unmatched — a rules list of denials acts as a
|
|
2312
|
-
* `allowed: false` `fallback` to flip the gate to deny-by-default (an
|
|
2391
|
+
* (allow-unmatched — a rules list of denials acts as a denylist). Pass an
|
|
2392
|
+
* `allowed: false` `fallback` to flip the gate to deny-by-default (an allowlist). Wire
|
|
2313
2393
|
* the result into `createAgent` through `AgentOptions.authority`: a denied call is fed back
|
|
2314
2394
|
* to the model as a denial `ToolResult` (not executed, no budget cost), so the model
|
|
2315
2395
|
* can react. Synchronous — `evaluate` returns the verdict directly.
|
|
@@ -2339,7 +2419,7 @@ export declare function createAuthority(options?: AuthorityOptions): AuthorityIn
|
|
|
2339
2419
|
* Write and read are decoupled, so the producer never waits for a consumer: an agent's eager
|
|
2340
2420
|
* pump writes each chunk into one, which is why a run's `result` settles whether or not the
|
|
2341
2421
|
* 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
|
|
2422
|
+
* values are yielded before the end is reported, and the first failure wins.
|
|
2343
2423
|
*
|
|
2344
2424
|
* @typeParam T - The value type the channel carries
|
|
2345
2425
|
* @returns A fresh, empty {@link ChannelInterface}
|
|
@@ -2360,16 +2440,16 @@ export declare function createChannel<T>(): ChannelInterface<T>;
|
|
|
2360
2440
|
|
|
2361
2441
|
/**
|
|
2362
2442
|
* Creates a conversation — a {@link ConversationInterface} grouping messages above a flat
|
|
2363
|
-
* message store it
|
|
2443
|
+
* message store it owns directly, with compaction into summarized sections, a regenerated
|
|
2364
2444
|
* rollup `summary`, on-demand `rehydrate`, and substring `search`, driven by a
|
|
2365
2445
|
* provider-agnostic {@link ConversationSummaryHandler} seam.
|
|
2366
2446
|
*
|
|
2367
2447
|
* @remarks
|
|
2368
2448
|
* Append turns through the conversation's own `add` (the live tail it owns); `view()` is the model input
|
|
2369
2449
|
* (each section as a summary message, then the live tail). `compact()` folds the older live
|
|
2370
|
-
* messages into a summarized {@link Section} and regenerates the rollup — it
|
|
2450
|
+
* messages into a summarized {@link Section} and regenerates the rollup — it requires
|
|
2371
2451
|
* a `summarize` (omitted ⇒ `compact()` throws a `ConversationError`); `keep` retains a recent
|
|
2372
|
-
* tail (default `DEFAULT_CONVERSATION_KEEP` — fold
|
|
2452
|
+
* tail (default `DEFAULT_CONVERSATION_KEEP` — fold all). `rehydrate(id)` / `search(query)` read
|
|
2373
2453
|
* the retained originals. Observable (`emitter` — `compact` / `summary` / `rehydrate`), wired
|
|
2374
2454
|
* through the reserved `on` option; the emitter isolates a listener throw and routes it to
|
|
2375
2455
|
* its `error` handler (the `error` option), so it can never corrupt a compaction.
|
|
@@ -2377,41 +2457,61 @@ export declare function createChannel<T>(): ChannelInterface<T>;
|
|
|
2377
2457
|
* @param options - Optional `id` / `on` hooks + the `summarize` seam + `keep` (see {@link ConversationOptions})
|
|
2378
2458
|
* @returns A working {@link ConversationInterface}
|
|
2379
2459
|
*
|
|
2380
|
-
* @example
|
|
2460
|
+
* @example Conversations & compaction
|
|
2381
2461
|
* ```ts
|
|
2382
|
-
* import type { ProviderInterface } from '@orkestrel/agent'
|
|
2383
2462
|
* import { createConversation } from '@orkestrel/agent'
|
|
2463
|
+
* import type { ProviderInterface } from '@orkestrel/agent'
|
|
2384
2464
|
*
|
|
2385
2465
|
* declare const provider: ProviderInterface // any concrete implementation supplied by the host app
|
|
2466
|
+
* // The summarizer seam — built from the provider by the runtime; core stays provider-agnostic.
|
|
2467
|
+
* // Append the instruction as the FINAL user turn: a chat model emits nothing when the prompt
|
|
2468
|
+
* // ends on an assistant turn, so a leading-system instruction is unreliable.
|
|
2386
2469
|
* const conversation = createConversation({
|
|
2387
|
-
* // Append the instruction as the FINAL user turn — a chat model emits nothing when the
|
|
2388
|
-
* // prompt ends on an assistant turn, so a leading-system instruction is unreliable.
|
|
2389
2470
|
* summarize: async (messages) =>
|
|
2390
|
-
* (
|
|
2471
|
+
* (
|
|
2472
|
+
* await provider.generate(
|
|
2473
|
+
* [
|
|
2474
|
+
* ...messages,
|
|
2475
|
+
* { id: 's', role: 'user', content: 'Summarize the conversation so far concisely.' },
|
|
2476
|
+
* ],
|
|
2477
|
+
* AbortSignal.timeout(30_000),
|
|
2478
|
+
* )
|
|
2479
|
+
* ).content,
|
|
2480
|
+
* keep: 2, // retain the two most recent turns verbatim on each compaction
|
|
2391
2481
|
* })
|
|
2392
|
-
* conversation.add(
|
|
2393
|
-
*
|
|
2482
|
+
* conversation.add([
|
|
2483
|
+
* { role: 'user', content: 'My name is Ada.' },
|
|
2484
|
+
* { role: 'assistant', content: 'Nice to meet you, Ada.' },
|
|
2485
|
+
* { role: 'user', content: 'What did I say my name was?' },
|
|
2486
|
+
* ])
|
|
2487
|
+
*
|
|
2488
|
+
* const section = await conversation.compact() // folds the older turns → a summarized section
|
|
2489
|
+
* conversation.view() // [<section summary message>, ...the retained recent tail] — the model input
|
|
2490
|
+
* conversation.summary // the regenerated rollup (a summary-of-summaries over all sections)
|
|
2491
|
+
* conversation.search('ada') // case-insensitive across sections' originals + the live tail
|
|
2492
|
+
* section && conversation.rehydrate(section.id) // the section's full original messages (a pure read)
|
|
2394
2493
|
* ```
|
|
2395
2494
|
*/
|
|
2396
2495
|
export declare function createConversation(options?: ConversationOptions): ConversationInterface;
|
|
2397
2496
|
|
|
2398
2497
|
/**
|
|
2399
2498
|
* Creates a conversation registry — a {@link ConversationManagerInterface} holding
|
|
2400
|
-
* {@link ConversationInterface}s keyed by their `id
|
|
2499
|
+
* {@link ConversationInterface}s keyed by their `id`, in insertion order, with an active pointer:
|
|
2401
2500
|
* the id-keyed store over the conversation layer plus the `active` / `switch` seam the context
|
|
2402
|
-
* renders.
|
|
2501
|
+
* renders. `add` auto-activates the first conversation and flows the registry's default
|
|
2502
|
+
* `summarize` / `keep` into every conversation it creates.
|
|
2403
2503
|
*
|
|
2404
2504
|
* @remarks
|
|
2405
2505
|
* Starts empty; `add(input?)` mints a {@link ConversationInterface} (its `id` from the input
|
|
2406
2506
|
* or a random UUID), flowing the manager's default `summarize` / `keep` in unless the input
|
|
2407
2507
|
* overrides them, and stores it (an already-present `id` overwrites — last write wins) — and
|
|
2408
|
-
*
|
|
2508
|
+
* auto-activates the first one (a registry with conversations always has one `active`); a later
|
|
2409
2509
|
* `add` leaves `active` unchanged. `switch(id)` re-points `active` (an unknown `id` returns
|
|
2410
2510
|
* `undefined`, leaving `active` unchanged — lenient, never throws); `conversation(id)` /
|
|
2411
2511
|
* `conversations()` look up; `remove` (one or a batch) reports `true` only when every supplied id
|
|
2412
|
-
* was removed
|
|
2512
|
+
* was removed and clears `active` if it was a removed one; `clear` empties it and clears `active`.
|
|
2413
2513
|
* Event-free
|
|
2414
|
-
* (each conversation owns its own observable `emitter`). A conversation created with
|
|
2514
|
+
* (each conversation owns its own observable `emitter`). A conversation created with neither a
|
|
2415
2515
|
* manager default nor a per-`add` `summarize` cannot `compact` (it throws a `ConversationError`).
|
|
2416
2516
|
*
|
|
2417
2517
|
* @param options - Optional default `summarize` / `keep` (see {@link ConversationManagerOptions})
|
|
@@ -2429,23 +2529,24 @@ export declare function createConversation(options?: ConversationOptions): Conve
|
|
|
2429
2529
|
export declare function createConversationManager(options?: ConversationManagerOptions): ConversationManagerInterface;
|
|
2430
2530
|
|
|
2431
2531
|
/**
|
|
2432
|
-
* Creates a {@link DatabaseConversationStore} over any {@link DriverInterface}
|
|
2433
|
-
* driver-pluggable backing for the conversation persistence
|
|
2532
|
+
* Creates a {@link DatabaseConversationStore} over any {@link DriverInterface}, defaulting to
|
|
2533
|
+
* `createMemoryDriver()` — the durable, driver-pluggable backing for the conversation persistence
|
|
2534
|
+
* seam, holding each snapshot as one opaque JSON column and standing as the opt-in twin of
|
|
2434
2535
|
* {@link createMemoryConversationStore}. The exact twin of
|
|
2435
2536
|
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore}.
|
|
2436
2537
|
*
|
|
2437
2538
|
* @remarks
|
|
2438
2539
|
* Builds a one-table database (`conversations`, keyed by `id`) over the supplied driver, the snapshot
|
|
2439
|
-
* held as
|
|
2540
|
+
* held as one opaque JSON column — the column map is `{ id; snapshot }` where `snapshot` is a
|
|
2440
2541
|
* `rawShape` (a JSON blob), exactly as
|
|
2441
2542
|
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore} stores its snapshot. The
|
|
2442
|
-
* snapshot is already a
|
|
2443
|
-
*
|
|
2444
|
-
* {@link import('./validators.js').isConversationSnapshot}). The `driver`
|
|
2445
|
-
* {@link createMemoryDriver}, so the store
|
|
2543
|
+
* snapshot is already a complete, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
2544
|
+
* and keeps the row type flat (the column reads back as `unknown`, narrowed on `get` by
|
|
2545
|
+
* {@link import('./validators.js').isConversationSnapshot}). The `driver` defaults to
|
|
2546
|
+
* {@link createMemoryDriver}, so the store also works in memory out of the box; pass a server
|
|
2446
2547
|
* `createJSONDriver` / `createSQLiteDriver` (or a browser IndexedDB driver) for a persistent one —
|
|
2447
2548
|
* the durability is the driver's job, the store engine is shared. It swaps in behind
|
|
2448
|
-
* {@link ConversationStoreInterface}
|
|
2549
|
+
* {@link ConversationStoreInterface} without touching the manager or the conversation.
|
|
2449
2550
|
*
|
|
2450
2551
|
* @param driver - The storage backend the snapshots persist to (defaults to {@link createMemoryDriver})
|
|
2451
2552
|
* @returns A {@link ConversationStoreInterface} over the driver
|
|
@@ -2491,7 +2592,7 @@ export declare function createInstruction(input: InstructionInput): InstructionI
|
|
|
2491
2592
|
* immutable instructions keyed by `name`, listed by descending `priority`.
|
|
2492
2593
|
*
|
|
2493
2594
|
* @remarks
|
|
2494
|
-
* Starts empty; `add` (one or a batch)
|
|
2595
|
+
* Starts empty; `add` (one or a batch) mints each `id` and overwrites a same-name
|
|
2495
2596
|
* instruction (last write wins); `instructions()` lists them sorted by descending
|
|
2496
2597
|
* `priority` (stable for ties); `open` / `render` are the build contract a richer
|
|
2497
2598
|
* context renders an instructions block with; `remove` (one or a batch) reports `true` only
|
|
@@ -2519,7 +2620,7 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2519
2620
|
/**
|
|
2520
2621
|
* Creates the in-memory conversation store — a {@link ConversationStoreInterface} backed by a
|
|
2521
2622
|
* process-lifetime `Map` of {@link import('./types.js').ConversationSnapshot}s keyed by conversation
|
|
2522
|
-
* id, the
|
|
2623
|
+
* id, the default backing for the durable {@link ConversationManagerInterface.open} /
|
|
2523
2624
|
* {@link ConversationManagerInterface.save} seam. The exact twin of
|
|
2524
2625
|
* {@link import('@orkestrel/workspace').createMemoryWorkspaceStore}.
|
|
2525
2626
|
*
|
|
@@ -2527,10 +2628,10 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2527
2628
|
* A plain `Map` (the snapshot is already pure JSON, so no encoding is needed for the memory tier),
|
|
2528
2629
|
* the structural twin of {@link import('@orkestrel/workspace').createMemoryWorkspaceStore}.
|
|
2529
2630
|
* `get` / `set` / `delete` are async (the
|
|
2530
|
-
* same shape a durable backend fits);
|
|
2631
|
+
* same shape a durable backend fits); unlike a session store there is no idle-TTL / eviction — a
|
|
2531
2632
|
* persisted conversation lives until an explicit `delete`. Its driver-pluggable twin is
|
|
2532
2633
|
* {@link createDatabaseConversationStore} (the snapshot as one opaque JSON column over a `databases`
|
|
2533
|
-
* table) — for a
|
|
2634
|
+
* table) — for a durable store pass it a JSON / SQLite / IndexedDB driver, and it swaps in without
|
|
2534
2635
|
* touching the manager or the conversation. Hydration stays a manager concern: read a snapshot back
|
|
2535
2636
|
* and rebuild the live conversation through the `snapshot` option (re-supplying the live
|
|
2536
2637
|
* `summarize` / `keep`).
|
|
@@ -2555,9 +2656,9 @@ export declare function createMemoryConversationStore(): ConversationStoreInterf
|
|
|
2555
2656
|
* per-category allow-lists, the `id` minted at construction.
|
|
2556
2657
|
*
|
|
2557
2658
|
* @remarks
|
|
2558
|
-
* Each list is
|
|
2559
|
-
*
|
|
2560
|
-
* tighter child by set-
|
|
2659
|
+
* Each list is three-way: `undefined` ⇒ no constraint on that category (all pass), `[]` ⇒
|
|
2660
|
+
* none pass, a non-empty list ⇒ only the listed keys pass. `narrow(config)` composes a
|
|
2661
|
+
* tighter child by set-intersection (an `undefined` side imposing no constraint). Stored
|
|
2561
2662
|
* immutable — never mutated after creation (`narrow` returns a new scope).
|
|
2562
2663
|
*
|
|
2563
2664
|
* @param input - `name` (required) and the optional `instructions` / `tools` / `files`
|
|
@@ -2601,18 +2702,19 @@ export declare function createScope(input: ScopeInput): ScopeInterface;
|
|
|
2601
2702
|
export declare function createScopeManager(options?: ScopeManagerOptions): ScopeManagerInterface;
|
|
2602
2703
|
|
|
2603
2704
|
/**
|
|
2604
|
-
* Creates a stream-stateful `<think>` separator — a {@link ThinkSplitterInterface} that
|
|
2605
|
-
* splits a thinking model's in-content `<think>…</think>` reasoning spans away from
|
|
2606
|
-
*
|
|
2607
|
-
*
|
|
2705
|
+
* Creates a fresh stream-stateful `<think>` separator — a {@link ThinkSplitterInterface} that
|
|
2706
|
+
* splits a thinking model's in-content `<think>…</think>` reasoning spans away from the answer,
|
|
2707
|
+
* delta by delta, so a provider yields clean content alone and surfaces the accumulated
|
|
2708
|
+
* reasoning as {@link import('./types.js').ProviderResult.thinking}. One splitter serves one
|
|
2709
|
+
* stream.
|
|
2608
2710
|
*
|
|
2609
2711
|
* @remarks
|
|
2610
2712
|
* Feed each raw wire delta through `split(delta)` (it returns the clean content to
|
|
2611
2713
|
* surface — possibly `''` mid-think) and settle the stream end with `flush()` (a held
|
|
2612
|
-
* partial open tag that never completed returns as final content; an
|
|
2613
|
-
* span lands on `thinking`). Tags split
|
|
2714
|
+
* partial open tag that never completed returns as final content; an unclosed think
|
|
2715
|
+
* span lands on `thinking`). Tags split across deltas are held back until
|
|
2614
2716
|
* disambiguated, multiple spans accumulate in order, and a nested-looking `<think>`
|
|
2615
|
-
* inside an open span is thinking text. One splitter serves
|
|
2717
|
+
* inside an open span is thinking text. One splitter serves one stream — create
|
|
2616
2718
|
* a fresh one per provider call.
|
|
2617
2719
|
*
|
|
2618
2720
|
* @returns A fresh {@link ThinkSplitterInterface} (state empty, outside any span)
|
|
@@ -2631,37 +2733,39 @@ export declare function createThinkSplitter(): ThinkSplitterInterface;
|
|
|
2631
2733
|
|
|
2632
2734
|
/**
|
|
2633
2735
|
* Backs a {@link ConversationStoreInterface} with one table of the `databases` layer — a
|
|
2634
|
-
* conversation's durable state
|
|
2635
|
-
*
|
|
2636
|
-
* {@link
|
|
2736
|
+
* conversation's durable state is a row holding the snapshot as one opaque JSON column, narrowed
|
|
2737
|
+
* back on `get` by {@link import('../../validators.js').isConversationSnapshot}, so persistence
|
|
2738
|
+
* reduces to keyed point-access (`get` / `set` / `delete`) over a {@link TableInterface}. The
|
|
2739
|
+
* driver-pluggable twin of the plain-`Map`
|
|
2740
|
+
* {@link import('./MemoryConversationStore.js').MemoryConversationStore}, and the exact twin of
|
|
2637
2741
|
* {@link import('@orkestrel/workspace').DatabaseWorkspaceStore}.
|
|
2638
2742
|
*
|
|
2639
2743
|
* @remarks
|
|
2640
2744
|
* The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
|
|
2641
2745
|
* JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /
|
|
2642
|
-
* IndexedDB backend swaps in
|
|
2746
|
+
* IndexedDB backend swaps in without touching the
|
|
2643
2747
|
* {@link import('../ConversationManager.js').ConversationManager} or the
|
|
2644
2748
|
* {@link import('../Conversation.js').Conversation} — the same seam as
|
|
2645
2749
|
* {@link import('@orkestrel/workspace').DatabaseWorkspaceStore}. The
|
|
2646
2750
|
* driver defaults to memory ({@link import('../../factories.js').createDatabaseConversationStore}
|
|
2647
|
-
* passes `createMemoryDriver()`), so it
|
|
2751
|
+
* passes `createMemoryDriver()`), so it also works in memory out of the box; you opt into the
|
|
2648
2752
|
* durable plumbing by passing a JSON / SQLite / IndexedDB driver.
|
|
2649
2753
|
*
|
|
2650
|
-
* The {@link ConversationSnapshot} is stored as
|
|
2754
|
+
* The {@link ConversationSnapshot} is stored as one opaque JSON column — the table is a row of
|
|
2651
2755
|
* `{ id; snapshot }` ({@link ConversationSnapshotRow}), the snapshot the whole JSON blob (a
|
|
2652
2756
|
* `rawShape` column the factory builds) — exactly as `DatabaseWorkspaceStore` stores its snapshot.
|
|
2653
|
-
* The snapshot is already a
|
|
2654
|
-
* lossless
|
|
2757
|
+
* The snapshot is already a complete, self-contained, pure-JSON payload, so storing it whole is
|
|
2758
|
+
* lossless and keeps the row type flat (`snapshot` reads back as `unknown`).
|
|
2655
2759
|
*
|
|
2656
|
-
* - **`set(snapshot)` upserts under the snapshot's
|
|
2760
|
+
* - **`set(snapshot)` upserts under the snapshot's own `id`** (no separate id param) — it writes
|
|
2657
2761
|
* the row `{ id: snapshot.id, snapshot }`.
|
|
2658
2762
|
* - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
|
|
2659
2763
|
* a {@link ConversationSnapshot} ({@link import('../../validators.js').isConversationSnapshot} — the
|
|
2660
2764
|
* total guard for an untrusted storage read), or `undefined` if none is stored.
|
|
2661
2765
|
* - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
2662
2766
|
*
|
|
2663
|
-
*
|
|
2664
|
-
* explicit `delete`. The public surface is
|
|
2767
|
+
* Unlike a session store there is no idle-TTL / eviction — a persisted conversation lives until an
|
|
2768
|
+
* explicit `delete`. The public surface is exactly `get` / `set` / `delete` — no extra members (the
|
|
2665
2769
|
* method bijection with {@link ConversationStoreInterface}). Hydration stays a caller concern: a
|
|
2666
2770
|
* {@link import('../ConversationManager.js').ConversationManager} reads a snapshot back and rebuilds
|
|
2667
2771
|
* the live conversation through the `snapshot` option (its `open` / `save`).
|
|
@@ -2690,36 +2794,35 @@ export declare class DatabaseConversationStore implements ConversationStoreInter
|
|
|
2690
2794
|
constructor(table: TableInterface<ConversationSnapshotRow>);
|
|
2691
2795
|
/** Resolves the persisted snapshot for `id`, narrowing the opaque JSON column back to a `ConversationSnapshot`. */
|
|
2692
2796
|
get(id: string): Promise<ConversationSnapshot | undefined>;
|
|
2693
|
-
/** Inserts or replaces under the snapshot's
|
|
2797
|
+
/** Inserts or replaces under the snapshot's own `id` (no separate id param) — the row is `{ id, snapshot }`. */
|
|
2694
2798
|
set(snapshot: ConversationSnapshot): Promise<void>;
|
|
2695
2799
|
/** Drops a snapshot by id; an absent id is a no-op (no throw). */
|
|
2696
2800
|
delete(id: string): Promise<void>;
|
|
2697
2801
|
}
|
|
2698
2802
|
|
|
2699
2803
|
/**
|
|
2700
|
-
* Caps an {@link AgentInterface} turn's tool iterations by default —
|
|
2701
|
-
*
|
|
2702
|
-
*
|
|
2703
|
-
* `AgentOptions.limit`.
|
|
2804
|
+
* Caps an {@link AgentInterface} turn's tool iterations by default — `10` context → provider →
|
|
2805
|
+
* tools cycles before the loop stops, so a model that keeps requesting tools can never loop
|
|
2806
|
+
* forever. Overridable per agent through `AgentOptions.limit`.
|
|
2704
2807
|
*/
|
|
2705
2808
|
export declare const DEFAULT_AGENT_LIMIT = 10;
|
|
2706
2809
|
|
|
2707
2810
|
/**
|
|
2708
2811
|
* Names the zone an {@link AuthorityInterface}'s default fallback {@link AuthorityDecision}
|
|
2709
|
-
* carries — the classification for a tool call that matched no rule. Paired with
|
|
2710
|
-
* default `allowed: true` fallback, an unmatched call is allowed under this zone, so a
|
|
2711
|
-
* rules list of denials acts as a denylist; a caller wanting deny-by-default supplies
|
|
2712
|
-
*
|
|
2812
|
+
* carries — `'default'`, the classification for a tool call that matched no rule. Paired with
|
|
2813
|
+
* the default `allowed: true` fallback, an unmatched call is allowed under this zone, so a
|
|
2814
|
+
* rules list of denials acts as a denylist; a caller wanting deny-by-default supplies an
|
|
2815
|
+
* `allowed: false` `fallback` of their own (see `AuthorityOptions`).
|
|
2713
2816
|
*/
|
|
2714
2817
|
export declare const DEFAULT_AUTHORITY_ZONE = "default";
|
|
2715
2818
|
|
|
2716
2819
|
/**
|
|
2717
2820
|
* Sets the default number of recent live messages a {@link ConversationInterface}'s `compact()`
|
|
2718
|
-
*
|
|
2719
|
-
*
|
|
2720
|
-
*
|
|
2721
|
-
*
|
|
2722
|
-
*
|
|
2821
|
+
* retains verbatim — `0`, so a manual `compact()` folds every current live message into one
|
|
2822
|
+
* summarized section and keeps no tail. A caller retains a recent tail by passing `keep` (on
|
|
2823
|
+
* {@link ConversationOptions}, {@link ConversationManagerOptions}, or per-fold through
|
|
2824
|
+
* {@link CompactOptions}), folding only the older `count - keep` messages and leaving the most
|
|
2825
|
+
* recent `keep` live for the next turn. Overridable everywhere `keep` is accepted.
|
|
2723
2826
|
*/
|
|
2724
2827
|
export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
2725
2828
|
|
|
@@ -2745,16 +2848,19 @@ export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
|
2745
2848
|
export declare function denyCall(call: ToolCall, reason: string | undefined): ToolResult;
|
|
2746
2849
|
|
|
2747
2850
|
/**
|
|
2748
|
-
* Estimates the context-token footprint of a batch of messages —
|
|
2749
|
-
*
|
|
2750
|
-
*
|
|
2851
|
+
* Estimates the context-token footprint of a batch of messages — each message's content plus
|
|
2852
|
+
* {@link import('./constants.js').MESSAGE_TOKEN_OVERHEAD}, a tool-call JSON estimate, and
|
|
2853
|
+
* {@link import('./constants.js').IMAGE_TOKEN_ESTIMATE} for each attached image. The default
|
|
2854
|
+
* `consumer` estimator for an agent's context budget (the
|
|
2855
|
+
* {@link import('./types.js').AgentOptions} `window`), total and never throwing, and a
|
|
2856
|
+
* deliberate provider-agnostic approximation rather than an exact tokenizer count.
|
|
2751
2857
|
*
|
|
2752
2858
|
* @remarks
|
|
2753
2859
|
* Sums, per message, {@link estimateTokens} over its `content` (the `ceil(length / 4)` char
|
|
2754
|
-
* heuristic)
|
|
2755
|
-
* role/framing overhead)
|
|
2756
|
-
* `calls`
|
|
2757
|
-
* deliberately-approximate per-image cost — a base64 length is
|
|
2860
|
+
* heuristic) plus {@link import('./constants.js').MESSAGE_TOKEN_OVERHEAD} (a fixed per-message
|
|
2861
|
+
* role/framing overhead) plus, when present, {@link estimateTokens} over its JSON-stringified
|
|
2862
|
+
* `calls` plus `images.length * `{@link import('./constants.js').IMAGE_TOKEN_ESTIMATE} (a coarse,
|
|
2863
|
+
* deliberately-approximate per-image cost — a base64 length is not a token proxy). Deterministic
|
|
2758
2864
|
* and provider-free — the same messages always yield the same estimate, with an empty batch `0`.
|
|
2759
2865
|
* It is the fully-swappable default an agent's auto-compaction context budget charges each
|
|
2760
2866
|
* turn's new messages through; a caller wanting a sharper count supplies its own `consumer` to
|
|
@@ -2775,15 +2881,15 @@ export declare function denyCall(call: ToolCall, reason: string | undefined): To
|
|
|
2775
2881
|
export declare function estimateMessages(messages: readonly Message[]): number;
|
|
2776
2882
|
|
|
2777
2883
|
/**
|
|
2778
|
-
* Estimates the context-token footprint of a string — the deterministic
|
|
2779
|
-
* {@link estimateMessages} sums over a conversation's messages (the default
|
|
2780
|
-
* estimator).
|
|
2884
|
+
* Estimates the context-token footprint of a string — the deterministic `ceil(length / 4)`
|
|
2885
|
+
* character heuristic {@link estimateMessages} sums over a conversation's messages (the default
|
|
2886
|
+
* context-budget estimator).
|
|
2781
2887
|
*
|
|
2782
2888
|
* @remarks
|
|
2783
2889
|
* Approximates `ceil(length / 4)` (≈ four characters per token — the rough average for
|
|
2784
2890
|
* English text), so the same input always yields the same estimate (no model round-trip).
|
|
2785
2891
|
* Empty text is `0`. This is a planning heuristic for reasoning about how much a turn's
|
|
2786
|
-
* messages cost the next request,
|
|
2892
|
+
* messages cost the next request, not an exact tokenizer count — it never calls a provider,
|
|
2787
2893
|
* so the agent layer stays provider-agnostic and synchronous where it can be.
|
|
2788
2894
|
*
|
|
2789
2895
|
* @param text - The text to estimate (a section summary, a message's content)
|
|
@@ -2799,15 +2905,16 @@ export declare function estimateMessages(messages: readonly Message[]): number;
|
|
|
2799
2905
|
export declare function estimateTokens(text: string): number;
|
|
2800
2906
|
|
|
2801
2907
|
/**
|
|
2802
|
-
* Filters a list of items by a {@link import('./types.js').ScopeInterface} allow-list of
|
|
2803
|
-
*
|
|
2804
|
-
*
|
|
2908
|
+
* Filters a list of items by a {@link import('./types.js').ScopeInterface} allow-list of keys —
|
|
2909
|
+
* `undefined` passes everything, `[]` passes nothing, and a non-empty list passes the listed keys
|
|
2910
|
+
* alone, order preserved. The pure, total set-membership primitive the context's build step and
|
|
2911
|
+
* the agent loop's tool-advertise step apply a scope through.
|
|
2805
2912
|
*
|
|
2806
2913
|
* @remarks
|
|
2807
2914
|
* Three-way by the allow-list's shape, so a `Scope` category cleanly expresses "all /
|
|
2808
2915
|
* none / only these":
|
|
2809
|
-
* - `undefined` ⇒
|
|
2810
|
-
* - `[]` (empty) ⇒
|
|
2916
|
+
* - `undefined` ⇒ no constraint — every item passes (returned unchanged).
|
|
2917
|
+
* - `[]` (empty) ⇒ none pass (no key is in an empty set).
|
|
2811
2918
|
* - a non-empty list ⇒ only items whose `key(item)` is in the list pass.
|
|
2812
2919
|
*
|
|
2813
2920
|
* Order-preserving (it filters `items` in place order, never reorders) and total — never
|
|
@@ -2858,11 +2965,12 @@ export declare function handleAgentQueueJob(registry: AgentRegistryInterface, pa
|
|
|
2858
2965
|
export declare function handleAgentRunnerJob(registry: AgentRegistryInterface, partial: boolean, controller: ControllerInterface<AgentJobInput, AgentResult>): Promise<AgentResult>;
|
|
2859
2966
|
|
|
2860
2967
|
/**
|
|
2861
|
-
* Names the coarse, deliberately
|
|
2862
|
-
* charges for each attached image
|
|
2968
|
+
* Names the coarse, deliberately approximate per-image token cost
|
|
2969
|
+
* {@link import('./helpers.js').estimateMessages} charges for each attached image — `512`, because
|
|
2970
|
+
* a base64 payload's length is no reliable token proxy.
|
|
2863
2971
|
*
|
|
2864
2972
|
* @remarks
|
|
2865
|
-
* A base64 image payload's
|
|
2973
|
+
* A base64 image payload's length is not a reliable token proxy (a vision model's actual image
|
|
2866
2974
|
* token cost depends on resolution / tiling, not byte size), so this is a fixed, coarse
|
|
2867
2975
|
* per-image estimate rather than a derivation from `image.length` — a planning heuristic, not an
|
|
2868
2976
|
* exact count.
|
|
@@ -2870,15 +2978,15 @@ export declare function handleAgentRunnerJob(registry: AgentRegistryInterface, p
|
|
|
2870
2978
|
export declare const IMAGE_TOKEN_ESTIMATE = 512;
|
|
2871
2979
|
|
|
2872
2980
|
/**
|
|
2873
|
-
* Represents an immutable named directive —
|
|
2874
|
-
*
|
|
2875
|
-
*
|
|
2981
|
+
* Represents an immutable named directive — an {@link InstructionInterface} assembled once from
|
|
2982
|
+
* its input (`name` / `content`, an optional `priority` defaulting to `0`), the `id` minted at
|
|
2983
|
+
* construction.
|
|
2876
2984
|
*
|
|
2877
2985
|
* @remarks
|
|
2878
2986
|
* A thin immutable value object (mirroring {@link import('@orkestrel/tool').Tool}): the
|
|
2879
2987
|
* constructor mints a fresh `id` (`crypto.randomUUID()`), copies the input's `name` /
|
|
2880
2988
|
* `content`, resolves `priority` to the input's value or `0`, and carries the input's
|
|
2881
|
-
* per-item `override`
|
|
2989
|
+
* per-item `override` only when supplied (assigned when present, mirroring a
|
|
2882
2990
|
* message's `images` / `calls` present-when-given convention — kept absent otherwise).
|
|
2883
2991
|
* Never mutated after construction. An
|
|
2884
2992
|
* {@link import('./InstructionManager.js').InstructionManager} keys it by `name` and
|
|
@@ -2910,7 +3018,7 @@ export declare interface InstructionInput {
|
|
|
2910
3018
|
/** Weights the ordering (higher renders first); defaults to `0` when omitted. */
|
|
2911
3019
|
readonly priority?: number;
|
|
2912
3020
|
/**
|
|
2913
|
-
* Holds a fully-rendered override of
|
|
3021
|
+
* Holds a fully-rendered override of this instruction's prompt text — the most-specific
|
|
2914
3022
|
* level of the {@link import('./AgentContext.js').AgentContext} build cascade (beats a
|
|
2915
3023
|
* manager-options / provider / built-in format for this item). Round-tripped onto the
|
|
2916
3024
|
* stored {@link InstructionInterface} when given (present-when-supplied, like `images`).
|
|
@@ -2937,8 +3045,8 @@ export declare interface InstructionInterface {
|
|
|
2937
3045
|
readonly priority: number;
|
|
2938
3046
|
/**
|
|
2939
3047
|
* Holds a fully-rendered per-item override of this instruction's prompt text — the
|
|
2940
|
-
*
|
|
2941
|
-
* cascade, beating every format level for
|
|
3048
|
+
* most-specific level of the {@link import('./AgentContext.js').AgentContext} build
|
|
3049
|
+
* cascade, beating every format level for this item. Present only when supplied on the
|
|
2942
3050
|
* {@link InstructionInput} (round-tripped through the manager, like a message's
|
|
2943
3051
|
* `images`); absent ⇒ the cascade decides.
|
|
2944
3052
|
*/
|
|
@@ -2946,28 +3054,29 @@ export declare interface InstructionInterface {
|
|
|
2946
3054
|
}
|
|
2947
3055
|
|
|
2948
3056
|
/**
|
|
2949
|
-
* Registers the immutable {@link Instruction}s a richer context assembles a directives
|
|
2950
|
-
*
|
|
3057
|
+
* Registers the immutable {@link Instruction}s a richer context assembles a directives block
|
|
3058
|
+
* from — keyed by `name` so a re-`add` overwrites, last write wins, and listed by descending
|
|
3059
|
+
* `priority`, carrying the `open` / `render` build contract and an observable `emitter`.
|
|
2951
3060
|
*
|
|
2952
3061
|
* @remarks
|
|
2953
3062
|
* - **Registry.** Instructions live in an insertion-ordered `Map` keyed by `name`;
|
|
2954
|
-
* `add` takes one {@link InstructionInput} or a batch,
|
|
2955
|
-
* `id`, and a re-`add` of the same name
|
|
2956
|
-
* map size, `instruction(name)` looks one up, and `instructions()` lists them
|
|
3063
|
+
* `add` takes one {@link InstructionInput} or a batch, mints each instruction's
|
|
3064
|
+
* `id`, and a re-`add` of the same name overwrites it (last write wins). `count` is the
|
|
3065
|
+
* map size, `instruction(name)` looks one up, and `instructions()` lists them sorted by
|
|
2957
3066
|
* descending `priority` (a stable sort, so equal priorities keep insertion order).
|
|
2958
3067
|
* - **Build contract (with the manager-options override).** `open` is the section
|
|
2959
3068
|
* header a context renders the instructions under; `render(instruction)` renders one
|
|
2960
|
-
* instruction (its `content`). Each
|
|
3069
|
+
* instruction (its `content`). Each encapsulates the cascade's `[options-override →
|
|
2961
3070
|
* built-in]` half: when `InstructionManagerOptions.format` supplies an `open` /
|
|
2962
|
-
* `render`, `open` / `render` return
|
|
3071
|
+
* `render`, `open` / `render` return it, else the built-in — so a richer context
|
|
2963
3072
|
* reads one consistent pair and layers the provider default + per-item override on top
|
|
2964
3073
|
* (see {@link import('../AgentContext.js').AgentContext}). The per-item
|
|
2965
3074
|
* {@link InstructionInput.override} is round-tripped onto the stored instruction.
|
|
2966
|
-
* - **Removal.** `remove` drops one by name, or a batch — `true` only when
|
|
3075
|
+
* - **Removal.** `remove` drops one by name, or a batch — `true` only when every supplied
|
|
2967
3076
|
* name was removed; `clear` empties the registry.
|
|
2968
3077
|
* - **Observable.** The owned {@link emitter} ({@link InstructionManagerEventMap})
|
|
2969
3078
|
* carries `add` (the created instruction) / `remove` (the name) / `clear` for
|
|
2970
|
-
* fire-and-forget observers. Every event is emitted directly, strictly
|
|
3079
|
+
* fire-and-forget observers. Every event is emitted directly, strictly after the map
|
|
2971
3080
|
* mutation completes; the emitter isolates a listener throw and routes it to its `error`
|
|
2972
3081
|
* handler (the `error` option), so a buggy observer can never corrupt a mutation.
|
|
2973
3082
|
*
|
|
@@ -3020,9 +3129,9 @@ export declare type InstructionManagerEventMap = {
|
|
|
3020
3129
|
};
|
|
3021
3130
|
|
|
3022
3131
|
/**
|
|
3023
|
-
* Registers {@link InstructionInterface}s keyed by `name` — `add` (one or a batch)
|
|
3024
|
-
*
|
|
3025
|
-
*
|
|
3132
|
+
* Registers {@link InstructionInterface}s keyed by `name` — `add` (one or a batch) mints each `id`
|
|
3133
|
+
* and overwrites a same-name instruction, last write wins, while `instructions()` lists them sorted
|
|
3134
|
+
* by descending `priority` and stable for ties.
|
|
3026
3135
|
*
|
|
3027
3136
|
* @remarks
|
|
3028
3137
|
* - **Build contract.** `open` is the section header a richer context renders
|
|
@@ -3040,22 +3149,32 @@ export declare interface InstructionManagerInterface {
|
|
|
3040
3149
|
readonly open: string;
|
|
3041
3150
|
/**
|
|
3042
3151
|
* Holds the manager-options format override (the {@link InstructionManagerOptions.format}
|
|
3043
|
-
* supplied at construction), or `undefined` when none — the
|
|
3152
|
+
* supplied at construction), or `undefined` when none — the manager-options level of the
|
|
3044
3153
|
* {@link import('./AgentContext.js').AgentContext} build cascade, exposed so `build()`
|
|
3045
|
-
* can interleave the provider default
|
|
3154
|
+
* can interleave the provider default beneath it (`open` / `render` already
|
|
3046
3155
|
* encapsulate the `[override → built-in]` half for standalone use). A `readonly` data
|
|
3047
3156
|
* member, not a method.
|
|
3048
3157
|
*/
|
|
3049
3158
|
readonly format: ContextSectionFormat<InstructionInterface> | undefined;
|
|
3159
|
+
/**
|
|
3160
|
+
* Adds one {@link InstructionInput}, or a batch — mints each `id`; a re-`add` of the same
|
|
3161
|
+
* name overwrites it, last write wins.
|
|
3162
|
+
*/
|
|
3050
3163
|
add(input: InstructionInput): InstructionInterface;
|
|
3051
3164
|
add(inputs: readonly InstructionInput[]): readonly InstructionInterface[];
|
|
3165
|
+
/** Looks up one instruction by name (`undefined` when absent). */
|
|
3052
3166
|
instruction(name: string): InstructionInterface | undefined;
|
|
3053
3167
|
/** Lists every instruction, sorted by descending `priority` (stable for equal priorities). */
|
|
3054
3168
|
instructions(): readonly InstructionInterface[];
|
|
3055
3169
|
/** Renders one instruction for the prompt — its `content`. */
|
|
3056
3170
|
render(instruction: InstructionInterface): string;
|
|
3171
|
+
/**
|
|
3172
|
+
* Removes one instruction by name, or a batch — `true` only when every supplied name was
|
|
3173
|
+
* removed.
|
|
3174
|
+
*/
|
|
3057
3175
|
remove(name: string): boolean;
|
|
3058
3176
|
remove(names: readonly string[]): boolean;
|
|
3177
|
+
/** Removes every instruction. */
|
|
3059
3178
|
clear(): void;
|
|
3060
3179
|
}
|
|
3061
3180
|
|
|
@@ -3066,10 +3185,10 @@ export declare interface InstructionManagerInterface {
|
|
|
3066
3185
|
* @remarks
|
|
3067
3186
|
* `on` is the reserved listener key: initial listeners for the manager's
|
|
3068
3187
|
* {@link InstructionManagerEventMap}, wired at construction. `format` is the
|
|
3069
|
-
*
|
|
3070
|
-
* cascade — a {@link ContextSectionFormat} the manager consults
|
|
3188
|
+
* manager-options level of the {@link import('./AgentContext.js').AgentContext} build
|
|
3189
|
+
* cascade — a {@link ContextSectionFormat} the manager consults first in its own
|
|
3071
3190
|
* `open` / `render` (falling back to the built-in when a member is omitted), so it
|
|
3072
|
-
*
|
|
3191
|
+
* beats the provider default and the built-in, while a per-item
|
|
3073
3192
|
* {@link InstructionInput.override} still beats it. Omitted ⇒ the built-in framing applies.
|
|
3074
3193
|
*/
|
|
3075
3194
|
export declare interface InstructionManagerOptions {
|
|
@@ -3081,12 +3200,12 @@ export declare interface InstructionManagerOptions {
|
|
|
3081
3200
|
}
|
|
3082
3201
|
|
|
3083
3202
|
/**
|
|
3084
|
-
* Intersects two scope category lists under the "`undefined` is the universal set" rule —
|
|
3085
|
-
* primitive a scope narrows through.
|
|
3203
|
+
* Intersects two scope category lists under the "`undefined` is the universal set" rule — a
|
|
3204
|
+
* fresh copy that can only tighten, and the primitive a scope narrows through.
|
|
3086
3205
|
*
|
|
3087
3206
|
* @remarks
|
|
3088
|
-
* Pure and total, and it can only
|
|
3089
|
-
* constraint); `undefined` ∩ a list is a
|
|
3207
|
+
* Pure and total, and it can only tighten: `undefined` ∩ `undefined` is `undefined` (still no
|
|
3208
|
+
* constraint); `undefined` ∩ a list is a copy of that list (the `undefined` side imposes
|
|
3090
3209
|
* nothing); a list ∩ a list keeps the child keys the parent also allows, so a parent-excluded
|
|
3091
3210
|
* key can never be re-admitted. Every returned list is a fresh copy, so a later mutation of
|
|
3092
3211
|
* either input cannot leak into the result.
|
|
@@ -3105,7 +3224,8 @@ export declare interface InstructionManagerOptions {
|
|
|
3105
3224
|
export declare function intersectKeys(parent: readonly string[] | undefined, child: readonly string[] | undefined): readonly string[] | undefined;
|
|
3106
3225
|
|
|
3107
3226
|
/**
|
|
3108
|
-
* Narrows an unknown caught value to an {@link AgentError}
|
|
3227
|
+
* Narrows an unknown caught value to an {@link AgentError} through `instanceof`, so a `catch`
|
|
3228
|
+
* can branch on its `code`.
|
|
3109
3229
|
*
|
|
3110
3230
|
* @param value - The value to test (typically a `catch` binding)
|
|
3111
3231
|
* @returns True if `value` is an {@link AgentError}; false otherwise
|
|
@@ -3122,7 +3242,8 @@ export declare function intersectKeys(parent: readonly string[] | undefined, chi
|
|
|
3122
3242
|
export declare function isAgentError(value: unknown): value is AgentError;
|
|
3123
3243
|
|
|
3124
3244
|
/**
|
|
3125
|
-
* Narrows an unknown caught value to an {@link AgentJobError}
|
|
3245
|
+
* Narrows an unknown caught value to an {@link AgentJobError} through `instanceof`, so a
|
|
3246
|
+
* `catch` can recover its `partial` result.
|
|
3126
3247
|
*
|
|
3127
3248
|
* @param value - The value to test (typically a `catch` binding or a rejected enqueue)
|
|
3128
3249
|
* @returns True if `value` is an {@link AgentJobError}; false otherwise
|
|
@@ -3139,7 +3260,8 @@ export declare function isAgentError(value: unknown): value is AgentError;
|
|
|
3139
3260
|
export declare function isAgentJobError(value: unknown): value is AgentJobError;
|
|
3140
3261
|
|
|
3141
3262
|
/**
|
|
3142
|
-
* Narrows an unknown caught value to a {@link ConversationError}
|
|
3263
|
+
* Narrows an unknown caught value to a {@link ConversationError} through `instanceof`, so a
|
|
3264
|
+
* `catch` can branch on its `code`.
|
|
3143
3265
|
*
|
|
3144
3266
|
* @param value - The value to test (typically a `catch` binding)
|
|
3145
3267
|
* @returns True if `value` is a {@link ConversationError}; false otherwise
|
|
@@ -3156,19 +3278,20 @@ export declare function isAgentJobError(value: unknown): value is AgentJobError;
|
|
|
3156
3278
|
export declare function isConversationError(value: unknown): value is ConversationError;
|
|
3157
3279
|
|
|
3158
3280
|
/**
|
|
3159
|
-
* Narrows an `unknown` to a {@link ConversationSnapshot} —
|
|
3160
|
-
*
|
|
3281
|
+
* Narrows an `unknown` to a {@link ConversationSnapshot} — a `string` `id`, an optional `string`
|
|
3282
|
+
* `summary`, and valid `sections` and `messages` arrays; the total boundary guard for an
|
|
3283
|
+
* untrusted snapshot read (a storage row a
|
|
3161
3284
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
3162
|
-
* reads back from its opaque JSON column, a snapshot loaded from disk). The
|
|
3163
|
-
* {@link import('@orkestrel/workspace').isWorkspaceSnapshot}.
|
|
3285
|
+
* reads back from its opaque JSON column, a snapshot loaded from disk), never throwing. The exact
|
|
3286
|
+
* analogue of {@link import('@orkestrel/workspace').isWorkspaceSnapshot}.
|
|
3164
3287
|
*
|
|
3165
3288
|
* @remarks
|
|
3166
|
-
* A total guard (it
|
|
3167
|
-
*
|
|
3168
|
-
* `undefined` until the first compaction), a `sections` array
|
|
3169
|
-
* {@link Section} ({@link isSection}), and a `messages` array
|
|
3289
|
+
* A total guard (it never throws — adversarial input returns `false`). It checks the snapshot's
|
|
3290
|
+
* shape: a `string` `id`, an optional `string` `summary` (present-or-absent — the rollup is
|
|
3291
|
+
* `undefined` until the first compaction), a `sections` array every element of which is a valid
|
|
3292
|
+
* {@link Section} ({@link isSection}), and a `messages` array every element of which is a
|
|
3170
3293
|
* valid {@link Message} ({@link isMessage}) — enough to safely impose the
|
|
3171
|
-
* {@link ConversationSnapshot} type at a storage boundary
|
|
3294
|
+
* {@link ConversationSnapshot} type at a storage boundary without a cast. The structural twin of
|
|
3172
3295
|
* {@link import('@orkestrel/workspace').isWorkspaceSnapshot}. A malformed blob (a non-record, a missing / non-string `id`, a
|
|
3173
3296
|
* non-string `summary` when present, a non-array `sections` / `messages`, or any malformed
|
|
3174
3297
|
* element) resolves `false`, so a
|
|
@@ -3190,14 +3313,15 @@ export declare function isConversationSnapshot(value: unknown): value is Convers
|
|
|
3190
3313
|
|
|
3191
3314
|
/**
|
|
3192
3315
|
* Checks whether an `unknown` is structurally a {@link Message} record — the per-message step of
|
|
3193
|
-
* the {@link isConversationSnapshot} read-boundary
|
|
3194
|
-
*
|
|
3316
|
+
* the {@link isConversationSnapshot} and {@link isSection} read-boundary narrows, where a present
|
|
3317
|
+
* `calls` must be an array of valid {@link import('@orkestrel/tool').ToolCall}s. Total, never
|
|
3318
|
+
* throwing, and never an assertion; the conversation analogue of
|
|
3195
3319
|
* {@link import('@orkestrel/workspace').isFile}.
|
|
3196
3320
|
*
|
|
3197
3321
|
* @remarks
|
|
3198
|
-
* A total guard (it
|
|
3199
|
-
*
|
|
3200
|
-
* — a `calls` array
|
|
3322
|
+
* A total guard (it never throws — adversarial input returns `false`). It checks the message's
|
|
3323
|
+
* shape: a record with a `string` `id`, a `string` `role`, a `string` `content`, and — when present
|
|
3324
|
+
* — a `calls` array every element of which is a valid
|
|
3201
3325
|
* {@link import('@orkestrel/tool').ToolCall} ({@link isToolCall} — the
|
|
3202
3326
|
* fail-closed deepening: a tampered `calls` element rejects the message, so the snapshot
|
|
3203
3327
|
* reads back as absent rather than replaying a malformed call) and an `images` that is an array
|
|
@@ -3205,7 +3329,7 @@ export declare function isConversationSnapshot(value: unknown): value is Convers
|
|
|
3205
3329
|
* {@link import('./types.js').MessageRole}, so any storage-read role string is accepted
|
|
3206
3330
|
* defensively rather than rejected against the current literal set). Enough to safely impose the
|
|
3207
3331
|
* {@link Message} type at
|
|
3208
|
-
* a storage boundary
|
|
3332
|
+
* a storage boundary without a cast.
|
|
3209
3333
|
*
|
|
3210
3334
|
* @param value - The value to test (one element of a snapshot's `messages` / a section's `messages`)
|
|
3211
3335
|
* @returns True if `value` has the structural shape of a {@link Message}; false otherwise
|
|
@@ -3221,7 +3345,8 @@ export declare function isConversationSnapshot(value: unknown): value is Convers
|
|
|
3221
3345
|
export declare function isMessage(value: unknown): value is Message;
|
|
3222
3346
|
|
|
3223
3347
|
/**
|
|
3224
|
-
* Narrows an unknown caught value to a {@link ProviderAbortError}
|
|
3348
|
+
* Narrows an unknown caught value to a {@link ProviderAbortError} through `instanceof`, so a
|
|
3349
|
+
* `catch` can recover its `partial` result.
|
|
3225
3350
|
*
|
|
3226
3351
|
* @param value - The value to test (typically a `catch` binding)
|
|
3227
3352
|
* @returns True if `value` is a {@link ProviderAbortError}; false otherwise
|
|
@@ -3238,15 +3363,16 @@ export declare function isMessage(value: unknown): value is Message;
|
|
|
3238
3363
|
export declare function isProviderAbortError(value: unknown): value is ProviderAbortError;
|
|
3239
3364
|
|
|
3240
3365
|
/**
|
|
3241
|
-
* Checks whether an `unknown` is structurally a {@link Section} record —
|
|
3242
|
-
*
|
|
3243
|
-
* read, never an
|
|
3366
|
+
* Checks whether an `unknown` is structurally a {@link Section} record — a `string` `id` and
|
|
3367
|
+
* `summary` beside a `messages` array of valid {@link Message}s, the per-section step of the
|
|
3368
|
+
* {@link isConversationSnapshot} read-boundary narrow. Total, never throwing, and never an
|
|
3369
|
+
* assertion.
|
|
3244
3370
|
*
|
|
3245
3371
|
* @remarks
|
|
3246
|
-
* A total guard (it
|
|
3247
|
-
*
|
|
3372
|
+
* A total guard (it never throws — adversarial input returns `false`). It checks the section's
|
|
3373
|
+
* shape: a record with a `string` `id`, a `string` `summary`, and a `messages` array every element
|
|
3248
3374
|
* of which is a valid {@link Message} record ({@link isMessage}). Enough to safely impose
|
|
3249
|
-
* the {@link Section} type at a storage boundary
|
|
3375
|
+
* the {@link Section} type at a storage boundary without a cast.
|
|
3250
3376
|
*
|
|
3251
3377
|
* @param value - The value to test (one element of a snapshot's `sections` array)
|
|
3252
3378
|
* @returns True if `value` has the structural shape of a {@link Section}; false otherwise
|
|
@@ -3284,26 +3410,27 @@ export declare function joinThinking(running: string | undefined, next: string):
|
|
|
3284
3410
|
|
|
3285
3411
|
/**
|
|
3286
3412
|
* Implements the {@link ConversationStoreInterface} in memory — a process-lifetime `Map` of
|
|
3287
|
-
* {@link ConversationSnapshot}s keyed by conversation id, the
|
|
3288
|
-
* {@link import('../../factories.js').createMemoryConversationStore} builds
|
|
3413
|
+
* {@link ConversationSnapshot}s keyed by conversation id, the default store
|
|
3414
|
+
* {@link import('../../factories.js').createMemoryConversationStore} builds and the default
|
|
3415
|
+
* backing for `open` / `save`. The exact twin of
|
|
3289
3416
|
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore}.
|
|
3290
3417
|
*
|
|
3291
3418
|
* @remarks
|
|
3292
3419
|
* A plain `Map<string, ConversationSnapshot>` — the snapshot is already pure,
|
|
3293
3420
|
* self-contained JSON, so no encoding is needed for the memory tier. Like the
|
|
3294
3421
|
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore} it twins,
|
|
3295
|
-
* there is
|
|
3296
|
-
* durable backend (JSON / SQLite / IndexedDB) swaps in through the
|
|
3422
|
+
* there is no idle-TTL and no eviction: a persisted conversation lives until an explicit `delete`. A
|
|
3423
|
+
* durable backend (JSON / SQLite / IndexedDB) swaps in through the same interface without touching
|
|
3297
3424
|
* the {@link import('../ConversationManager.js').ConversationManager} or the
|
|
3298
3425
|
* {@link import('../Conversation.js').Conversation} — its driver-pluggable twin is
|
|
3299
3426
|
* {@link import('./DatabaseConversationStore.js').DatabaseConversationStore} (the snapshot as one
|
|
3300
3427
|
* opaque JSON column).
|
|
3301
3428
|
*
|
|
3302
3429
|
* - **`get` resolves the persisted snapshot for an id**, or `undefined` if none is stored.
|
|
3303
|
-
* - **`set` inserts / replaces under the snapshot's
|
|
3430
|
+
* - **`set` inserts / replaces under the snapshot's own `id`** (no separate id param).
|
|
3304
3431
|
* - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
3305
3432
|
*
|
|
3306
|
-
* The public surface is
|
|
3433
|
+
* The public surface is exactly `get` / `set` / `delete` — no extra members (the method
|
|
3307
3434
|
* bijection with {@link ConversationStoreInterface}). Hydration is a caller concern: a
|
|
3308
3435
|
* {@link import('../ConversationManager.js').ConversationManager} reads a snapshot back and rebuilds
|
|
3309
3436
|
* the live conversation through the `snapshot` option (its `open` / `save`).
|
|
@@ -3322,8 +3449,27 @@ export declare function joinThinking(running: string | undefined, next: string):
|
|
|
3322
3449
|
*/
|
|
3323
3450
|
export declare class MemoryConversationStore implements ConversationStoreInterface {
|
|
3324
3451
|
#private;
|
|
3452
|
+
/**
|
|
3453
|
+
* Resolves the persisted snapshot for `id`, or `undefined` if none is stored.
|
|
3454
|
+
*
|
|
3455
|
+
* @param id - The conversation id to resolve (a {@link ConversationSnapshot.id})
|
|
3456
|
+
* @returns The persisted snapshot, or `undefined` if absent
|
|
3457
|
+
*/
|
|
3325
3458
|
get(id: string): Promise<ConversationSnapshot | undefined>;
|
|
3459
|
+
/**
|
|
3460
|
+
* Inserts or replaces a snapshot under its own `snapshot.id` (no separate id param —
|
|
3461
|
+
* mirroring {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`).
|
|
3462
|
+
*
|
|
3463
|
+
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
3464
|
+
* @returns A promise that resolves after the snapshot is stored
|
|
3465
|
+
*/
|
|
3326
3466
|
set(snapshot: ConversationSnapshot): Promise<void>;
|
|
3467
|
+
/**
|
|
3468
|
+
* Drops a snapshot by id; an absent id is a no-op (no throw).
|
|
3469
|
+
*
|
|
3470
|
+
* @param id - The conversation id to drop
|
|
3471
|
+
* @returns A promise that resolves after the snapshot is dropped
|
|
3472
|
+
*/
|
|
3327
3473
|
delete(id: string): Promise<void>;
|
|
3328
3474
|
}
|
|
3329
3475
|
|
|
@@ -3352,10 +3498,11 @@ export declare interface Message {
|
|
|
3352
3498
|
}
|
|
3353
3499
|
|
|
3354
3500
|
/**
|
|
3355
|
-
* Estimates the per-message role
|
|
3356
|
-
* adds on top of a message's content estimate —
|
|
3357
|
-
* conversation turn carries (its role tag, delimiters) that
|
|
3358
|
-
* content-only heuristic does not otherwise
|
|
3501
|
+
* Estimates the per-message role and framing overhead {@link import('./helpers.js').estimateMessages}
|
|
3502
|
+
* adds on top of a message's content estimate — `4` tokens for the fixed wire framing every
|
|
3503
|
+
* conversation turn carries (its role tag, its delimiters) that
|
|
3504
|
+
* {@link import('./helpers.js').estimateTokens}'s content-only heuristic does not otherwise
|
|
3505
|
+
* capture.
|
|
3359
3506
|
*/
|
|
3360
3507
|
export declare const MESSAGE_TOKEN_OVERHEAD = 4;
|
|
3361
3508
|
|
|
@@ -3376,27 +3523,39 @@ export declare interface MessageInput {
|
|
|
3376
3523
|
}
|
|
3377
3524
|
|
|
3378
3525
|
/**
|
|
3379
|
-
* Stores immutable {@link Message}s in insertion order
|
|
3526
|
+
* Stores immutable {@link Message}s in insertion order and mints each `id` on `add` — the
|
|
3527
|
+
* message-store contract {@link AgentContextInterface.messages} is typed to, which the active
|
|
3528
|
+
* {@link ConversationInterface} satisfies structurally.
|
|
3380
3529
|
*
|
|
3381
3530
|
* @remarks
|
|
3382
3531
|
* - **Store.** Messages live in insertion order; `count` is how many are stored.
|
|
3383
|
-
* `add` takes one {@link MessageInput} or a batch and
|
|
3532
|
+
* `add` takes one {@link MessageInput} or a batch and mints each message's
|
|
3384
3533
|
* `id` (a random UUID), returning the created message(s). A stored message is
|
|
3385
3534
|
* immutable — created once from its input, never mutated.
|
|
3386
3535
|
* - **Lookup.** `message(id)` resolves one by id (`undefined` when absent);
|
|
3387
3536
|
* `messages()` lists every message in insertion order.
|
|
3388
|
-
* - **Removal.** `remove` drops one by id, or a batch — `true` only when
|
|
3537
|
+
* - **Removal.** `remove` drops one by id, or a batch — `true` only when every supplied id
|
|
3389
3538
|
* was removed; `clear` empties the store.
|
|
3390
3539
|
* - **Event-free.** A purely data store — no Emitter, no events.
|
|
3391
3540
|
*/
|
|
3392
3541
|
export declare interface MessageManagerInterface {
|
|
3393
3542
|
readonly count: number;
|
|
3543
|
+
/**
|
|
3544
|
+
* Stores one {@link MessageInput}, or a batch — mints each message's `id` and returns the
|
|
3545
|
+
* created message or messages; a stored message is immutable.
|
|
3546
|
+
*/
|
|
3394
3547
|
add(input: MessageInput): Message;
|
|
3395
3548
|
add(inputs: readonly MessageInput[]): readonly Message[];
|
|
3549
|
+
/** Looks up one stored message by id (`undefined` when absent). */
|
|
3396
3550
|
message(id: string): Message | undefined;
|
|
3551
|
+
/** Lists every stored message, in insertion order. */
|
|
3397
3552
|
messages(): readonly Message[];
|
|
3553
|
+
/**
|
|
3554
|
+
* Removes one message by id, or a batch — `true` only when every supplied id was removed.
|
|
3555
|
+
*/
|
|
3398
3556
|
remove(id: string): boolean;
|
|
3399
3557
|
remove(ids: readonly string[]): boolean;
|
|
3558
|
+
/** Removes every stored message. */
|
|
3400
3559
|
clear(): void;
|
|
3401
3560
|
}
|
|
3402
3561
|
|
|
@@ -3405,8 +3564,8 @@ export declare type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
|
3405
3564
|
|
|
3406
3565
|
/**
|
|
3407
3566
|
* 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
|
-
*
|
|
3567
|
+
* {@link ProviderInterface}'s `stream`, carrying the {@link ProviderResult} assembled from
|
|
3568
|
+
* whatever streamed before the cancel and the machine-readable `code` `'ABORT'`.
|
|
3410
3569
|
*
|
|
3411
3570
|
* @remarks
|
|
3412
3571
|
* Lets a caller recover the partial content (and any tool calls / usage seen so far)
|
|
@@ -3422,18 +3581,18 @@ export declare class ProviderAbortError extends Error {
|
|
|
3422
3581
|
}
|
|
3423
3582
|
|
|
3424
3583
|
/**
|
|
3425
|
-
* Represents one streamed delta a {@link ProviderInterface}'s `stream` yields — a
|
|
3426
|
-
*
|
|
3427
|
-
*
|
|
3584
|
+
* Represents one streamed delta a {@link ProviderInterface}'s `stream` yields — a unit tagged by
|
|
3585
|
+
* the channel it belongs to, so the agent loop can re-surface answer content and live reasoning
|
|
3586
|
+
* separately as it pumps.
|
|
3428
3587
|
*
|
|
3429
3588
|
* @remarks
|
|
3430
3589
|
* The discriminant `channel` names the axis that varies: a
|
|
3431
|
-
* `'content'` delta is a chunk of the assistant
|
|
3590
|
+
* `'content'` delta is a chunk of the assistant answer (the deltas that accumulate into
|
|
3432
3591
|
* {@link ProviderResult.content}); a `'thinking'` delta is a chunk of the model's
|
|
3433
|
-
*
|
|
3434
|
-
* `message.thinking` wire channel), surfaced
|
|
3592
|
+
* reasoning the provider separated from the answer (the daemon's native
|
|
3593
|
+
* `message.thinking` wire channel), surfaced live so a consumer can stream it into a
|
|
3435
3594
|
* collapsible without waiting for the assembled result. `text` is the delta's literal
|
|
3436
|
-
* text. Thinking
|
|
3595
|
+
* text. Thinking never re-enters the conversation — it is display/audit metadata, exactly
|
|
3437
3596
|
* as {@link ProviderResult.thinking} (the authoritative final accumulation) is.
|
|
3438
3597
|
*/
|
|
3439
3598
|
export declare type ProviderDelta = {
|
|
@@ -3445,10 +3604,10 @@ export declare type ProviderDelta = {
|
|
|
3445
3604
|
};
|
|
3446
3605
|
|
|
3447
3606
|
/**
|
|
3448
|
-
* Defines the pluggable LLM inference boundary — the one contract every agent chunk depends
|
|
3449
|
-
*
|
|
3450
|
-
*
|
|
3451
|
-
*
|
|
3607
|
+
* Defines the pluggable LLM inference boundary — the one contract every agent chunk depends on. A
|
|
3608
|
+
* provider turns a conversation (plus optional tools) into either a single assembled {@link
|
|
3609
|
+
* ProviderResult} (`generate`) or a stream of {@link ProviderDelta}s that returns the assembled
|
|
3610
|
+
* result (`stream`).
|
|
3452
3611
|
*
|
|
3453
3612
|
* @remarks
|
|
3454
3613
|
* - `id` is a stable per-instance trace label; `name` identifies the backend
|
|
@@ -3464,9 +3623,9 @@ export declare interface ProviderInterface {
|
|
|
3464
3623
|
readonly id: string;
|
|
3465
3624
|
readonly name: string;
|
|
3466
3625
|
/**
|
|
3467
|
-
* Holds the model's preferred context framing, by section kind — an
|
|
3626
|
+
* Holds the model's preferred context framing, by section kind — an optional
|
|
3468
3627
|
* {@link ContextFormat} an {@link import('./AgentContext.js').AgentContext}
|
|
3469
|
-
* applies as the
|
|
3628
|
+
* applies as the provider-default level of its build cascade (beating the managers'
|
|
3470
3629
|
* built-in framing, beaten by a manager-options or per-item override). Omitted ⇒ the
|
|
3471
3630
|
* provider is framing-agnostic and the managers' built-in defaults apply unchanged.
|
|
3472
3631
|
*/
|
|
@@ -3482,14 +3641,14 @@ export declare interface ProviderInterface {
|
|
|
3482
3641
|
*/
|
|
3483
3642
|
generate(messages: readonly Message[], signal: AbortSignal, tools?: readonly ToolDefinition[], options?: ProviderStreamOptions): Promise<ProviderResult>;
|
|
3484
3643
|
/**
|
|
3485
|
-
* Streams one turn — yields
|
|
3486
|
-
*
|
|
3487
|
-
*
|
|
3488
|
-
* stream
|
|
3644
|
+
* Streams one turn — yields channel-tagged `content` / `thinking` {@link ProviderDelta}s as
|
|
3645
|
+
* they arrive and returns the assembled {@link ProviderResult} (the concatenated content,
|
|
3646
|
+
* any separated reasoning, any tool calls, and any usage) when the stream completes. A
|
|
3647
|
+
* mid-stream abort throws a `ProviderAbortError` carrying the partial result.
|
|
3489
3648
|
*
|
|
3490
3649
|
* @remarks
|
|
3491
|
-
*
|
|
3492
|
-
*
|
|
3650
|
+
* The `partial` holds whatever streamed before the cancel, so a caller can recover the
|
|
3651
|
+
* partial content.
|
|
3493
3652
|
*
|
|
3494
3653
|
* @param messages - The conversation so far
|
|
3495
3654
|
* @param signal - Bounds the request; an abort throws `ProviderAbortError`
|
|
@@ -3506,9 +3665,9 @@ export declare interface ProviderInterface {
|
|
|
3506
3665
|
* and the token usage it reported.
|
|
3507
3666
|
*
|
|
3508
3667
|
* @remarks
|
|
3509
|
-
* `thinking` is present only when the turn produced reasoning the provider
|
|
3510
|
-
*
|
|
3511
|
-
* emitted, or a wire-side reasoning field) — `content` is always the
|
|
3668
|
+
* `thinking` is present only when the turn produced reasoning the provider split
|
|
3669
|
+
* away from the answer (an in-content `<think>…</think>` span a thinking model
|
|
3670
|
+
* emitted, or a wire-side reasoning field) — `content` is always the clean answer,
|
|
3512
3671
|
* and the thinking never re-enters the conversation (it is display/audit metadata,
|
|
3513
3672
|
* not prompt text). `tools` is present only when the model wants tool calls (an
|
|
3514
3673
|
* empty array is never surfaced — its absence means "no calls"). `usage` is present
|
|
@@ -3527,17 +3686,17 @@ export declare interface ProviderResult {
|
|
|
3527
3686
|
|
|
3528
3687
|
/**
|
|
3529
3688
|
* Carries the per-call options threaded into a {@link ProviderInterface}'s `generate` / `stream` —
|
|
3530
|
-
* the bag a caller passes to influence
|
|
3531
|
-
*
|
|
3689
|
+
* the bag a caller passes to influence one inference call without reconfiguring the provider
|
|
3690
|
+
* instance.
|
|
3532
3691
|
*
|
|
3533
3692
|
* @remarks
|
|
3534
|
-
* `think`
|
|
3693
|
+
* `think` overrides the provider's constructed reasoning preference for this call: `true`
|
|
3535
3694
|
* asks the backend to separate reasoning natively (a thinking model returns it on its
|
|
3536
3695
|
* `message.thinking` channel, surfaced as `'thinking'` {@link ProviderDelta}s + the final
|
|
3537
3696
|
* {@link ProviderResult.thinking}); `false` suppresses it. `schema`, when given, asks the
|
|
3538
3697
|
* backend to constrain its response to the given JSON-Schema shape (the same open
|
|
3539
3698
|
* JSON-Schema record {@link ToolDefinition.parameters} already carries) — a structured-output
|
|
3540
|
-
* request for
|
|
3699
|
+
* request for this call only. Both omitted ⇒ the provider's own defaults apply (the
|
|
3541
3700
|
* constructor value / no schema constraint), so the contract stays backward-safe — a caller
|
|
3542
3701
|
* that passes no options behaves exactly as before.
|
|
3543
3702
|
*/
|
|
@@ -3549,9 +3708,9 @@ export declare interface ProviderStreamOptions {
|
|
|
3549
3708
|
}
|
|
3550
3709
|
|
|
3551
3710
|
/**
|
|
3552
|
-
* Renders a path-addressed text body as a fenced reference block —
|
|
3553
|
-
*
|
|
3554
|
-
* active
|
|
3711
|
+
* Renders a path-addressed text body as a fenced reference block — a `File: <path>` label line
|
|
3712
|
+
* over a language-tagged fence, the framing an
|
|
3713
|
+
* {@link import('./AgentContext.js').AgentContext}'s active-workspace text-file render emits.
|
|
3555
3714
|
*
|
|
3556
3715
|
* @remarks
|
|
3557
3716
|
* Produces `` File: <path>\n```<language>\n<content>\n``` `` — the `File:` label line, then a
|
|
@@ -3577,10 +3736,10 @@ export declare function renderFencedFile(path: string, language: string, content
|
|
|
3577
3736
|
|
|
3578
3737
|
/**
|
|
3579
3738
|
* Renders one context section — the resolved `open`, each item's rendering, and the resolved
|
|
3580
|
-
* `close` when one exists, blank-line joined.
|
|
3739
|
+
* `close` when one exists, blank-line joined; `undefined` when the section has no items.
|
|
3581
3740
|
*
|
|
3582
3741
|
* @remarks
|
|
3583
|
-
* Pure and total. A section with
|
|
3742
|
+
* Pure and total. A section with no items renders nothing (`undefined`), so an empty or fully
|
|
3584
3743
|
* scoped-out manager stays silent — its `open` / `close` never appear without items. `close`
|
|
3585
3744
|
* is the only optional slot: an unset one (there is no built-in close) drops the
|
|
3586
3745
|
* trailing line.
|
|
@@ -3602,13 +3761,13 @@ export declare function renderFencedFile(path: string, language: string, content
|
|
|
3602
3761
|
export declare function renderSection<T>(open: string, items: readonly T[], render: (item: T) => string, close: string | undefined): string | undefined;
|
|
3603
3762
|
|
|
3604
3763
|
/**
|
|
3605
|
-
* Resolves one section's
|
|
3606
|
-
* provider default.
|
|
3764
|
+
* Resolves one section's close text through the format cascade — manager-options override >
|
|
3765
|
+
* provider default; `undefined` when neither sets one, because there is no built-in close.
|
|
3607
3766
|
*
|
|
3608
3767
|
* @remarks
|
|
3609
|
-
* Pure and total. There is
|
|
3768
|
+
* Pure and total. There is no built-in close, so a section with neither level set returns
|
|
3610
3769
|
* `undefined` and {@link renderSection} appends no closing line. Paired with
|
|
3611
|
-
* {@link resolveOpen}, one level can
|
|
3770
|
+
* {@link resolveOpen}, one level can wrap the whole group.
|
|
3612
3771
|
*
|
|
3613
3772
|
* @typeParam T - The section item the manager renders
|
|
3614
3773
|
* @param manager - The section source (its `format` override)
|
|
@@ -3624,14 +3783,14 @@ export declare function renderSection<T>(open: string, items: readonly T[], rend
|
|
|
3624
3783
|
export declare function resolveClose<T>(manager: ContextSectionSourceInterface<T>, provider: ContextSectionFormat<T> | undefined): string | undefined;
|
|
3625
3784
|
|
|
3626
3785
|
/**
|
|
3627
|
-
* Resolves
|
|
3628
|
-
*
|
|
3786
|
+
* Resolves one item's rendering through the format cascade — item override > manager-options
|
|
3787
|
+
* override > provider default > built-in rendering.
|
|
3629
3788
|
*
|
|
3630
3789
|
* @remarks
|
|
3631
3790
|
* Pure and total. The item's own `override` is the most-specific level (a fully-rendered
|
|
3632
3791
|
* string for that item alone). A manager's `render(item)` already encapsulates
|
|
3633
3792
|
* `[options-override → built-in]`, so it is reached only when no higher level applies — and
|
|
3634
|
-
* there it
|
|
3793
|
+
* there it is the built-in rendering.
|
|
3635
3794
|
*
|
|
3636
3795
|
* @typeParam T - The section item being rendered (it may carry its own `override`)
|
|
3637
3796
|
* @param manager - The section source (its `format` override + its built-in `render`)
|
|
@@ -3651,13 +3810,13 @@ export declare function resolveItem<T extends {
|
|
|
3651
3810
|
}>(manager: ContextSectionSourceInterface<T>, provider: ContextSectionFormat<T> | undefined, item: T): string;
|
|
3652
3811
|
|
|
3653
3812
|
/**
|
|
3654
|
-
* Resolves one section's
|
|
3813
|
+
* Resolves one section's open text through the format cascade — manager-options override >
|
|
3655
3814
|
* provider default > built-in header.
|
|
3656
3815
|
*
|
|
3657
3816
|
* @remarks
|
|
3658
|
-
* Pure and total. The leading text has
|
|
3817
|
+
* Pure and total. The leading text has no per-item level. A manager's `open` already
|
|
3659
3818
|
* 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
|
|
3819
|
+
* override's `open` nor the provider's `open` applies — and there it is the built-in header.
|
|
3661
3820
|
*
|
|
3662
3821
|
* @typeParam T - The section item the manager renders
|
|
3663
3822
|
* @param manager - The section source (its `format` override + its built-in `open`)
|
|
@@ -3674,15 +3833,15 @@ export declare function resolveOpen<T>(manager: ContextSectionSourceInterface<T>
|
|
|
3674
3833
|
|
|
3675
3834
|
/**
|
|
3676
3835
|
* Holds the immutable per-run outcome an {@link AgentInterface}'s loop settles on — the value its
|
|
3677
|
-
* run
|
|
3678
|
-
*
|
|
3836
|
+
* run returns, assembled from there into the {@link AgentResult} its `stream`'s `result` promise
|
|
3837
|
+
* resolves.
|
|
3679
3838
|
*
|
|
3680
3839
|
* @remarks
|
|
3681
3840
|
* Computed inside one run (so concurrent runs never share state) and returned once, when the
|
|
3682
3841
|
* loop settles: `content` is the streamed assistant text, `thinking` the reasoning the
|
|
3683
3842
|
* provider calls separated from it ({@link ProviderResult.thinking}, joined across calls —
|
|
3684
3843
|
* `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
|
|
3844
|
+
* a provider call reported it), `partial` is `true` when a cancel committed the run early or
|
|
3686
3845
|
* when the loop exhausted its `limit` with unresolved tool intent, and `exhausted` is `true`
|
|
3687
3846
|
* in that second case specifically (a distinct, non-cancel cause the {@link AgentEventMap}
|
|
3688
3847
|
* `exhaust` event observes). It is the settled outcome one run returns, before the agent folds
|
|
@@ -3697,7 +3856,8 @@ export declare interface RunOutcome {
|
|
|
3697
3856
|
}
|
|
3698
3857
|
|
|
3699
3858
|
/**
|
|
3700
|
-
* Sanitizes one reported token count into a safe non-negative integer
|
|
3859
|
+
* Sanitizes one reported token count into a safe non-negative integer — a non-finite or
|
|
3860
|
+
* non-positive value becomes `0`, and a positive fractional value floors down.
|
|
3701
3861
|
*
|
|
3702
3862
|
* @param value - The token count to sanitize
|
|
3703
3863
|
* @returns The floored count, or `0` when the value is non-finite or non-positive
|
|
@@ -3725,23 +3885,25 @@ export declare function sanitizeToken(value: number): number;
|
|
|
3725
3885
|
export declare function sanitizeUsage(usage: TokenUsage): TokenUsage;
|
|
3726
3886
|
|
|
3727
3887
|
/**
|
|
3728
|
-
* Represents a named, immutable filter over a richer context's items — an optional
|
|
3729
|
-
*
|
|
3730
|
-
*
|
|
3888
|
+
* Represents a named, immutable filter over a richer context's items — an optional allow-list per
|
|
3889
|
+
* category (`instructions` / `tools` / `files`), each keyed by that category's identity (an
|
|
3890
|
+
* instruction's `name`, a tool's `name`, a workspace file's `path`) and read as an allow-list:
|
|
3891
|
+
* `undefined` lets everything pass, `[]` lets nothing pass, and a non-empty list passes the listed
|
|
3892
|
+
* keys alone. `narrow` composes a tighter child by set intersection.
|
|
3731
3893
|
*
|
|
3732
3894
|
* @remarks
|
|
3733
|
-
* - **A category list is three-way.** `undefined` ⇒
|
|
3734
|
-
* pass); `[]` ⇒
|
|
3895
|
+
* - **A category list is three-way.** `undefined` ⇒ no constraint on that category (all
|
|
3896
|
+
* pass); `[]` ⇒ none pass; a non-empty list ⇒ only the listed keys pass. The build
|
|
3735
3897
|
* step / loop apply this through `filterAllowList`.
|
|
3736
|
-
* - **Immutable.** The `id` is minted at construction; every supplied list is
|
|
3898
|
+
* - **Immutable.** The `id` is minted at construction; every supplied list is copied in
|
|
3737
3899
|
* (so a later mutation of the caller's array can't leak in), and the lists are
|
|
3738
|
-
* `readonly`. A `Scope` is never mutated after construction — `narrow` returns a
|
|
3900
|
+
* `readonly`. A `Scope` is never mutated after construction — `narrow` returns a new
|
|
3739
3901
|
* one rather than altering this one.
|
|
3740
|
-
* - **`narrow` is set-
|
|
3741
|
-
* per category is the intersection of
|
|
3902
|
+
* - **`narrow` is set-intersection (immutable composition).** A child scope's visible set
|
|
3903
|
+
* per category is the intersection of this scope's list and the config's list — but
|
|
3742
3904
|
* `undefined` means "no constraint", so it acts as the universal set: intersecting
|
|
3743
3905
|
* `undefined` with a list yields the list, and `undefined` with `undefined` stays
|
|
3744
|
-
* `undefined`. Narrowing can only
|
|
3906
|
+
* `undefined`. Narrowing can only tighten, never widen — a key excluded by a parent
|
|
3745
3907
|
* can never be re-admitted by a child.
|
|
3746
3908
|
*
|
|
3747
3909
|
* @example
|
|
@@ -3765,16 +3927,17 @@ export declare class Scope implements ScopeInterface {
|
|
|
3765
3927
|
}
|
|
3766
3928
|
|
|
3767
3929
|
/**
|
|
3768
|
-
* Lists the per-category allow-lists a {@link ScopeInterface} carries — an optional
|
|
3769
|
-
*
|
|
3770
|
-
*
|
|
3771
|
-
* `
|
|
3930
|
+
* Lists the per-category allow-lists a {@link ScopeInterface} carries — an optional `readonly
|
|
3931
|
+
* string[]` for `instructions`, for `tools`, and for `files`, each keyed by that category's
|
|
3932
|
+
* identity (an instruction's `name`, a tool's `name`, a workspace file's `path`) and read as an
|
|
3933
|
+
* allow-list: `undefined` lets everything pass, `[]` lets nothing pass, and a non-empty list passes
|
|
3934
|
+
* the listed keys alone.
|
|
3772
3935
|
*
|
|
3773
3936
|
* @remarks
|
|
3774
|
-
* Each list is
|
|
3775
|
-
* ⇒
|
|
3937
|
+
* Each list is three-way (see {@link import('./helpers.js').filterAllowList}): `undefined`
|
|
3938
|
+
* ⇒ no constraint on that category (all pass); `[]` ⇒ none pass; a non-empty list ⇒ only
|
|
3776
3939
|
* the listed keys pass. It is the shape both a {@link ScopeInput} and `Scope.narrow`
|
|
3777
|
-
* accept (a `name`-less narrowing config). `files` filters the
|
|
3940
|
+
* accept (a `name`-less narrowing config). `files` filters the active workspace's rendered
|
|
3778
3941
|
* files (by `path`) in {@link AgentContextInterface.build} — both the text files folded into
|
|
3779
3942
|
* the system block and the image files attached to the last user message.
|
|
3780
3943
|
*/
|
|
@@ -3784,7 +3947,7 @@ export declare interface ScopeFilter {
|
|
|
3784
3947
|
/** Lists the allowed tool `name`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed). */
|
|
3785
3948
|
readonly tools?: readonly string[];
|
|
3786
3949
|
/**
|
|
3787
|
-
* Lists the allowed
|
|
3950
|
+
* Lists the allowed active-workspace file `path`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed) —
|
|
3788
3951
|
* the filter {@link AgentContextInterface.build} applies to the active workspace's
|
|
3789
3952
|
* {@link import('@orkestrel/workspace').WorkspaceInterface.files} before rendering them (text → the system block, image →
|
|
3790
3953
|
* the last user message).
|
|
@@ -3801,33 +3964,35 @@ export declare interface ScopeInput extends ScopeFilter {
|
|
|
3801
3964
|
}
|
|
3802
3965
|
|
|
3803
3966
|
/**
|
|
3804
|
-
* Represents a named, immutable filter over a richer context's items — the per-category
|
|
3805
|
-
*
|
|
3806
|
-
*
|
|
3967
|
+
* Represents a named, immutable filter over a richer context's items — the per-category allow-lists
|
|
3968
|
+
* ({@link ScopeFilter}) plus an `id` / `name`, and a `narrow` that composes a tighter child by set
|
|
3969
|
+
* intersection.
|
|
3807
3970
|
*
|
|
3808
3971
|
* @remarks
|
|
3809
3972
|
* Each list is three-way (`undefined` ⇒ all, `[]` ⇒ none, else only-listed). `narrow`
|
|
3810
|
-
* returns a
|
|
3973
|
+
* returns a new scope whose per-category visible set is the intersection of this scope's
|
|
3811
3974
|
* list and the config's — with `undefined` treated as the universal set (no constraint),
|
|
3812
3975
|
* so `undefined ∩ list = list` and `undefined ∩ undefined = undefined`. Narrowing can
|
|
3813
|
-
* only
|
|
3976
|
+
* only tighten (a parent-excluded key never returns); the scope itself is never mutated.
|
|
3814
3977
|
*/
|
|
3815
3978
|
export declare interface ScopeInterface extends ScopeFilter {
|
|
3816
3979
|
readonly id: string;
|
|
3817
3980
|
readonly name: string;
|
|
3818
3981
|
/**
|
|
3819
|
-
* Composes a tighter child scope —
|
|
3820
|
-
*
|
|
3982
|
+
* Composes a tighter child scope — each category is the set intersection of this scope's
|
|
3983
|
+
* list and `config`'s (an `undefined` side imposing no constraint), returned as a new
|
|
3984
|
+
* scope that leaves this one unchanged.
|
|
3821
3985
|
*
|
|
3822
3986
|
* @param config - The narrowing allow-lists (a `name`-less {@link ScopeFilter})
|
|
3823
|
-
* @returns A
|
|
3987
|
+
* @returns A new, tighter {@link ScopeInterface} (this one is left unchanged)
|
|
3824
3988
|
*/
|
|
3825
3989
|
narrow(config: ScopeFilter): ScopeInterface;
|
|
3826
3990
|
}
|
|
3827
3991
|
|
|
3828
3992
|
/**
|
|
3829
|
-
* Registers the named filters a richer context reuses — immutable {@link Scope}s keyed by
|
|
3830
|
-
*
|
|
3993
|
+
* Registers the named filters a richer context reuses — immutable {@link Scope}s keyed by their
|
|
3994
|
+
* minted `id`, in insertion order, where `create` always mints and stores rather than overwriting,
|
|
3995
|
+
* and an observable `emitter` reports each change.
|
|
3831
3996
|
*
|
|
3832
3997
|
* @remarks
|
|
3833
3998
|
* - **Registry.** Scopes live in an insertion-ordered `Map` keyed by their minted `id`;
|
|
@@ -3836,11 +4001,11 @@ export declare interface ScopeInterface extends ScopeFilter {
|
|
|
3836
4001
|
* one up, and `scopes()` lists them in insertion order. (Unlike the name-keyed
|
|
3837
4002
|
* instruction registry, a scope's key is its minted `id`, so two scopes may share a
|
|
3838
4003
|
* `name`; `create` therefore always adds — it never overwrites.)
|
|
3839
|
-
* - **Removal.** `remove` drops one by id, or a batch — `true` only when
|
|
4004
|
+
* - **Removal.** `remove` drops one by id, or a batch — `true` only when every supplied id
|
|
3840
4005
|
* was removed; `clear` empties the registry.
|
|
3841
4006
|
* - **Observable.** The owned {@link emitter} ({@link ScopeManagerEventMap}) carries
|
|
3842
4007
|
* `create` (the created scope) / `remove` (the id) / `clear`. Every event is emitted
|
|
3843
|
-
* directly, strictly
|
|
4008
|
+
* directly, strictly after the map mutation completes; the emitter isolates a listener
|
|
3844
4009
|
* throw and routes it to its `error` handler (the `error` option), so a buggy observer can
|
|
3845
4010
|
* never corrupt a mutation.
|
|
3846
4011
|
*
|
|
@@ -3900,12 +4065,19 @@ export declare type ScopeManagerEventMap = {
|
|
|
3900
4065
|
export declare interface ScopeManagerInterface {
|
|
3901
4066
|
readonly emitter: EmitterInterface<ScopeManagerEventMap>;
|
|
3902
4067
|
readonly count: number;
|
|
4068
|
+
/**
|
|
4069
|
+
* Mints a scope from a {@link ScopeInput} (an `id` plus the per-category allow-lists) and
|
|
4070
|
+
* stores it — always adds, never overwrites.
|
|
4071
|
+
*/
|
|
3903
4072
|
create(input: ScopeInput): ScopeInterface;
|
|
4073
|
+
/** Looks up one scope by id (`undefined` when absent). */
|
|
3904
4074
|
scope(id: string): ScopeInterface | undefined;
|
|
3905
4075
|
/** Lists every scope, in insertion order. */
|
|
3906
4076
|
scopes(): readonly ScopeInterface[];
|
|
4077
|
+
/** Removes one scope by id, or a batch — `true` only when every supplied id was removed. */
|
|
3907
4078
|
remove(id: string): boolean;
|
|
3908
4079
|
remove(ids: readonly string[]): boolean;
|
|
4080
|
+
/** Removes every scope. */
|
|
3909
4081
|
clear(): void;
|
|
3910
4082
|
}
|
|
3911
4083
|
|
|
@@ -3925,9 +4097,9 @@ export declare interface ScopeManagerOptions {
|
|
|
3925
4097
|
*
|
|
3926
4098
|
* @remarks
|
|
3927
4099
|
* `summary` is the model-written digest of this slice (through the
|
|
3928
|
-
* {@link ConversationSummaryHandler}); `messages` are the folded
|
|
4100
|
+
* {@link ConversationSummaryHandler}); `messages` are the folded originals, retained in full so
|
|
3929
4101
|
* `rehydrate` can pull them back and `search` can scan them (compaction shrinks the model
|
|
3930
|
-
*
|
|
4102
|
+
* input, never discards history).
|
|
3931
4103
|
*/
|
|
3932
4104
|
export declare interface Section {
|
|
3933
4105
|
readonly id: string;
|
|
@@ -3938,15 +4110,17 @@ export declare interface Section {
|
|
|
3938
4110
|
}
|
|
3939
4111
|
|
|
3940
4112
|
/**
|
|
3941
|
-
* Runs one rehydrated agent and applies the partial-as-configurable-failure policy —
|
|
3942
|
-
*
|
|
3943
|
-
*
|
|
4113
|
+
* Runs one rehydrated agent and applies the partial-as-configurable-failure policy — a partial
|
|
4114
|
+
* run throws an {@link import('./errors.js').AgentJobError} unless the `partial` policy allows
|
|
4115
|
+
* it, and a natural finish resolves. The shared job-handler step `createAgentQueue` and
|
|
4116
|
+
* `createAgentRunner` both settle each job through, so the policy can never diverge between
|
|
4117
|
+
* them.
|
|
3944
4118
|
*
|
|
3945
4119
|
* @remarks
|
|
3946
|
-
* A turn that committed
|
|
3947
|
-
*
|
|
3948
|
-
* (the Queue's retries + a Runner's fail-fast then engage); the `partial` policy
|
|
3949
|
-
* it as success instead. A natural finish
|
|
4120
|
+
* A turn that committed partial (a cancel — abort / budget / timeout) is by default a
|
|
4121
|
+
* failure, so it throws an {@link import('./errors.js').AgentJobError} carrying the partial
|
|
4122
|
+
* (the Queue's retries + a Runner's fail-fast then engage); the `partial` policy resolves
|
|
4123
|
+
* it as success instead. A natural finish always resolves with its result.
|
|
3950
4124
|
*
|
|
3951
4125
|
* @param agent - The rehydrated {@link AgentInterface} to run to its {@link AgentResult}
|
|
3952
4126
|
* @param partial - The partial policy. If `true`, a partial result resolves as success; if
|
|
@@ -3969,7 +4143,7 @@ export declare function settleAgentJob(agent: AgentInterface, partial: boolean):
|
|
|
3969
4143
|
* @remarks
|
|
3970
4144
|
* Iterate `events` to consume the live `T` chunks as they arrive; `await result` for
|
|
3971
4145
|
* the eventual `R` outcome (it resolves once `events` completes). `abort(reason)`
|
|
3972
|
-
* cancels the in-flight operation — for an agent turn the `result` then
|
|
4146
|
+
* cancels the in-flight operation — for an agent turn the `result` then resolves
|
|
3973
4147
|
* (with a partial outcome), since a cancel is not an error.
|
|
3974
4148
|
*
|
|
3975
4149
|
* @typeParam T - The live event type the stream yields
|
|
@@ -4009,39 +4183,40 @@ export declare interface StreamInterface<T, R> {
|
|
|
4009
4183
|
export declare function sumUsage(running: TokenUsage | undefined, next: TokenUsage): TokenUsage;
|
|
4010
4184
|
|
|
4011
4185
|
/**
|
|
4012
|
-
* Names the closing tag that ends a {@link THINK_OPEN} reasoning span
|
|
4013
|
-
* (the model was cut off mid-reasoning) is treated as thinking to its end
|
|
4014
|
-
* {@link import('./types.js').ThinkSplitterInterface.flush} settles it.
|
|
4186
|
+
* Names the closing tag that ends a {@link THINK_OPEN} reasoning span — `'</think>'`. A span the
|
|
4187
|
+
* stream never closes (the model was cut off mid-reasoning) is treated as thinking to its end,
|
|
4188
|
+
* and {@link import('./types.js').ThinkSplitterInterface.flush} settles it.
|
|
4015
4189
|
*/
|
|
4016
4190
|
export declare const THINK_CLOSE = "</think>";
|
|
4017
4191
|
|
|
4018
4192
|
/**
|
|
4019
4193
|
* Names the opening tag a {@link import('./ThinkSplitter.js').ThinkSplitter} recognizes as the start of
|
|
4020
|
-
* an in-content reasoning span — the de-facto wire convention thinking models
|
|
4021
|
-
* family) emit their chain-of-thought under when a daemon renders it inline
|
|
4022
|
-
* separate wire field. Paired with {@link THINK_CLOSE}.
|
|
4194
|
+
* an in-content reasoning span — `'<think>'`, the de-facto wire convention thinking models
|
|
4195
|
+
* (qwen3, DeepSeek-R1 family) emit their chain-of-thought under when a daemon renders it inline
|
|
4196
|
+
* instead of on a separate wire field. Paired with {@link THINK_CLOSE}.
|
|
4023
4197
|
*/
|
|
4024
4198
|
export declare const THINK_OPEN = "<think>";
|
|
4025
4199
|
|
|
4026
4200
|
/**
|
|
4027
|
-
* Feeds raw content deltas through a tiny stream-stateful state machine that routes
|
|
4028
|
-
*
|
|
4029
|
-
*
|
|
4030
|
-
* {@link import('./types.js').ProviderResult.thinking}.
|
|
4201
|
+
* Feeds raw content deltas through a tiny stream-stateful state machine that routes everything
|
|
4202
|
+
* inside a `<think>…</think>` span to `thinking` and returns everything outside it as clean
|
|
4203
|
+
* content, so a provider yields the answer alone and surfaces the reasoning as
|
|
4204
|
+
* {@link import('./types.js').ProviderResult.thinking}. A tag split across deltas is held until
|
|
4205
|
+
* disambiguated, `flush()` settles the stream end, and one splitter serves one stream.
|
|
4031
4206
|
*
|
|
4032
4207
|
* @remarks
|
|
4033
4208
|
* - **Cross-chunk tags.** A tag may arrive split across wire deltas (`'<thi'` then
|
|
4034
|
-
* `'nk>'`): any suffix of the pending text that is a strict
|
|
4035
|
-
* scanned for is
|
|
4209
|
+
* `'nk>'`): any suffix of the pending text that is a strict prefix of a tag being
|
|
4210
|
+
* scanned for is held back (neither surfaced nor routed) until the next delta — or
|
|
4036
4211
|
* `flush()` — disambiguates it. A held tag prefix that never completes is real
|
|
4037
4212
|
* content; a held close-tag prefix inside a span is thinking.
|
|
4038
|
-
* - **The
|
|
4039
|
-
*
|
|
4040
|
-
*
|
|
4041
|
-
* close therefore
|
|
4213
|
+
* - **The implicit leading open (the qwen3-template shape).** Some chat templates
|
|
4214
|
+
* pre-seed `<think>` into the prompt scaffold, so the wire stream begins
|
|
4215
|
+
* mid-reasoning and only a bare `</think>` appears. Before any tag event, a bare
|
|
4216
|
+
* close therefore reclassifies everything surfaced so far (plus the pre-close
|
|
4042
4217
|
* pending) as thinking — `content` is corrected retroactively (the already-returned
|
|
4043
4218
|
* prefix cannot be recalled, so `content` is the authoritative accumulation). The
|
|
4044
|
-
* rule is
|
|
4219
|
+
* rule is one-shot: after any tag event a bare `</think>` is plain text.
|
|
4045
4220
|
* - **Multiple spans** accumulate onto `thinking` in stream order. A nested-looking
|
|
4046
4221
|
* `<think>` inside an open span is thinking text (no nesting is tracked — the
|
|
4047
4222
|
* first `</think>` closes the span), matching how the models emit it.
|
|
@@ -4069,59 +4244,67 @@ export declare class ThinkSplitter implements ThinkSplitterInterface {
|
|
|
4069
4244
|
}
|
|
4070
4245
|
|
|
4071
4246
|
/**
|
|
4072
|
-
* Splits a thinking model's in-content `<think>…</think>` reasoning spans away from the
|
|
4073
|
-
*
|
|
4074
|
-
*
|
|
4247
|
+
* Splits a thinking model's in-content `<think>…</think>` reasoning spans away from the answer,
|
|
4248
|
+
* delta by delta with per-stream state, so a provider yields clean content alone and surfaces the
|
|
4249
|
+
* reasoning as {@link ProviderResult.thinking}.
|
|
4075
4250
|
*
|
|
4076
4251
|
* @remarks
|
|
4077
|
-
* - **Stateful across deltas.** A tag may arrive
|
|
4252
|
+
* - **Stateful across deltas.** A tag may arrive split across wire chunks (`'<thi'`
|
|
4078
4253
|
* ending one delta, `'nk>'` opening the next) — `split` holds any ambiguous tail
|
|
4079
4254
|
* back until the next delta (or `flush`) disambiguates it, so a partial tag is
|
|
4080
4255
|
* never leaked as content and never mis-eaten as thinking.
|
|
4081
|
-
* - **`split(delta)`** feeds one raw content delta and returns the
|
|
4256
|
+
* - **`split(delta)`** feeds one raw content delta and returns the clean content to
|
|
4082
4257
|
* surface for it (possibly `''` — for example mid-think). Text inside a
|
|
4083
4258
|
* `<think>…</think>` span accumulates on `thinking`; multiple spans accumulate in
|
|
4084
4259
|
* order; a nested-looking `<think>` inside an open span is thinking text (no
|
|
4085
4260
|
* nesting — the first `</think>` closes).
|
|
4086
|
-
* - **The
|
|
4087
|
-
*
|
|
4088
|
-
*
|
|
4089
|
-
* bare close therefore
|
|
4261
|
+
* - **The implicit leading open (the qwen3-template shape).** Some chat templates
|
|
4262
|
+
* pre-seed `<think>` into the prompt scaffold, so the wire stream begins
|
|
4263
|
+
* mid-reasoning and only a bare `</think>` ever appears. Before any tag event, a
|
|
4264
|
+
* bare close therefore reclassifies everything surfaced so far (plus the pre-close
|
|
4090
4265
|
* pending) as thinking — `content` is corrected retroactively, while the already
|
|
4091
4266
|
* `split`-returned prefix cannot be recalled (the one shape where the per-delta
|
|
4092
|
-
* returns over-report; `content` stays authoritative). The rule is
|
|
4267
|
+
* returns over-report; `content` stays authoritative). The rule is one-shot: after
|
|
4093
4268
|
* any tag event a bare `</think>` is plain text (prose quoting the tag stays text).
|
|
4094
|
-
* - **`flush()`** settles the stream end: an
|
|
4269
|
+
* - **`flush()`** settles the stream end: an unclosed `<think>` tail (the model was
|
|
4095
4270
|
* cut off mid-reasoning) lands on `thinking`; a held partial tag that never
|
|
4096
4271
|
* completed (`'<thi'` then EOF) is returned as the final clean-content delta —
|
|
4097
4272
|
* it was real text after all.
|
|
4098
4273
|
* - **`content` / `thinking`** are the authoritative accumulations so far (read them
|
|
4099
|
-
* after the stream — or mid-stream for a cancel's partial); `content` is the
|
|
4274
|
+
* after the stream — or mid-stream for a cancel's partial); `content` is the one
|
|
4100
4275
|
* exact clean-content source (the per-delta returns match it except across an
|
|
4101
|
-
* implicit-open reclassification). One splitter serves
|
|
4276
|
+
* implicit-open reclassification). One splitter serves one stream; create a fresh
|
|
4102
4277
|
* one per call ({@link import('./factories.js').createThinkSplitter}).
|
|
4103
4278
|
*/
|
|
4104
4279
|
export declare interface ThinkSplitterInterface {
|
|
4105
|
-
/** Holds the
|
|
4280
|
+
/** Holds the authoritative clean content accumulated so far (corrected across an implicit-open reclassification). */
|
|
4106
4281
|
readonly content: string;
|
|
4107
4282
|
/** Holds the reasoning text accumulated from every `<think>…</think>` span so far. */
|
|
4108
4283
|
readonly thinking: string;
|
|
4109
|
-
/**
|
|
4284
|
+
/**
|
|
4285
|
+
* Feeds one raw delta and returns the clean, non-think content to surface for it (possibly
|
|
4286
|
+
* `''`) — a tag split across deltas is held until disambiguated, never leaked as content
|
|
4287
|
+
* and never mis-eaten as thinking.
|
|
4288
|
+
*/
|
|
4110
4289
|
split(delta: string): string;
|
|
4111
|
-
/**
|
|
4290
|
+
/**
|
|
4291
|
+
* Settles the stream end — a held partial tag that never completed returns as the final
|
|
4292
|
+
* content delta, and an unclosed think span's tail lands on `thinking`.
|
|
4293
|
+
*/
|
|
4112
4294
|
flush(): string;
|
|
4113
4295
|
}
|
|
4114
4296
|
|
|
4115
4297
|
/**
|
|
4116
4298
|
* Names the section header {@link import('./AgentContext.js').AgentContext}'s `build()` renders the
|
|
4117
|
-
*
|
|
4118
|
-
* system message
|
|
4299
|
+
* active workspace's text files under — `'## Workspace'`, the leading line of the dedicated
|
|
4300
|
+
* workspace block in the system message and the carrier-split counterpart to the documents and
|
|
4301
|
+
* images section headers.
|
|
4119
4302
|
*
|
|
4120
4303
|
* @remarks
|
|
4121
|
-
* `build()`
|
|
4304
|
+
* `build()` owns the workspace render (a `Workspace` / `WorkspaceManager` stays file-focused — no
|
|
4122
4305
|
* `open` / `format` getters), so this header lives here as the agents module's one
|
|
4123
4306
|
* workspace-section framing constant rather than on a manager. Each workspace text file renders
|
|
4124
|
-
* beneath it as a fenced `` File: <path>\n```<language>\n<text>\n``` `` block — the
|
|
4307
|
+
* beneath it as a fenced `` File: <path>\n```<language>\n<text>\n``` `` block — the same framing
|
|
4125
4308
|
* the documents section uses — placed immediately after the documents section in the system block.
|
|
4126
4309
|
*/
|
|
4127
4310
|
export declare const WORKSPACE_SECTION_HEADER = "## Workspace";
|