@orkestrel/agent 0.0.10 → 0.0.12
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 +16 -9
- package/dist/src/core/index.cjs +81 -1629
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +112 -1736
- package/dist/src/core/index.d.ts +112 -1736
- package/dist/src/core/index.js +77 -1588
- package/dist/src/core/index.js.map +1 -1
- package/package.json +11 -9
|
@@ -11,6 +11,12 @@ import { RunnerInterface } from '@orkestrel/workflow';
|
|
|
11
11
|
import { SchedulerInterface } from '@orkestrel/workflow';
|
|
12
12
|
import { TableInterface } from '@orkestrel/database';
|
|
13
13
|
import { TokenUsage } from '@orkestrel/budget';
|
|
14
|
+
import { ToolCall } from '@orkestrel/tool';
|
|
15
|
+
import { ToolDefinition } from '@orkestrel/tool';
|
|
16
|
+
import { ToolInterface } from '@orkestrel/tool';
|
|
17
|
+
import { ToolManagerInterface } from '@orkestrel/tool';
|
|
18
|
+
import { ToolResult } from '@orkestrel/tool';
|
|
19
|
+
import { WorkspaceManagerInterface } from '@orkestrel/workspace';
|
|
14
20
|
|
|
15
21
|
/**
|
|
16
22
|
* The agent loop — composes a {@link ProviderInterface}, an {@link AgentContext}, and
|
|
@@ -100,15 +106,17 @@ export declare type AgentChunk = {
|
|
|
100
106
|
* The richer turn context the agent loop assembles a provider request from — the optional
|
|
101
107
|
* system prompt, the observable context managers (instructions / workspaces), the
|
|
102
108
|
* {@link ConversationManagerInterface} message source (whose active conversation IS `messages`),
|
|
103
|
-
* the {@link ToolManagerInterface} registry, and
|
|
109
|
+
* the {@link ToolManagerInterface} registry, and an active {@link ScopeInterface} changed through
|
|
110
|
+
* {@link AgentContextInterface.apply}.
|
|
104
111
|
*
|
|
105
112
|
* @remarks
|
|
106
113
|
* - **Composition.** `system` is the optional system prompt; `instructions` / `tools` /
|
|
107
114
|
* `workspaces` / `conversations` are the registries passed in `options` (bring your own), or
|
|
108
115
|
* fresh empty ones when omitted (so `workspaces` is ALWAYS present); `messages` is the ACTIVE
|
|
109
116
|
* conversation's live tail (ALWAYS defined — see below). `scope` is the active filter —
|
|
110
|
-
* `undefined` (the default) ⇒ no filtering;
|
|
111
|
-
*
|
|
117
|
+
* `undefined` (the default) ⇒ no filtering; change it through `apply(scope)`. The structural
|
|
118
|
+
* `workspaces` / `conversations` registries are fixed at construction; switch their active
|
|
119
|
+
* members through their own `switch(id)` methods.
|
|
112
120
|
* - **The message source — the conversation registry's ACTIVE conversation.** `conversations` is a
|
|
113
121
|
* {@link ConversationManagerInterface}; the context ENSURES it always has an active conversation
|
|
114
122
|
* (at construction it `add`s a default when the manager has none), so the DYNAMIC `messages`
|
|
@@ -167,13 +175,11 @@ export declare class AgentContext implements AgentContextInterface {
|
|
|
167
175
|
get system(): string | undefined;
|
|
168
176
|
get instructions(): InstructionManagerInterface;
|
|
169
177
|
get workspaces(): WorkspaceManagerInterface;
|
|
170
|
-
set workspaces(value: WorkspaceManagerInterface);
|
|
171
178
|
get messages(): MessageManagerInterface;
|
|
172
179
|
get conversations(): ConversationManagerInterface;
|
|
173
|
-
set conversations(value: ConversationManagerInterface);
|
|
174
180
|
get tools(): ToolManagerInterface;
|
|
175
181
|
get scope(): ScopeInterface | undefined;
|
|
176
|
-
|
|
182
|
+
apply(scope: ScopeInterface | undefined): void;
|
|
177
183
|
build(format?: ContextFormatInterface): readonly MessageInterface[];
|
|
178
184
|
}
|
|
179
185
|
|
|
@@ -182,8 +188,8 @@ export declare class AgentContext implements AgentContextInterface {
|
|
|
182
188
|
* the conversation, applying the active scope per category.
|
|
183
189
|
*
|
|
184
190
|
* @remarks
|
|
185
|
-
* The richer context — `system` (the optional system prompt), the context managers
|
|
186
|
-
* (`instructions` / `
|
|
191
|
+
* The richer context — `system` (the optional system prompt), the prompt context managers
|
|
192
|
+
* (`instructions` / `workspaces` / `conversations`), `messages` (the active
|
|
187
193
|
* conversation's live tail, satisfying {@link MessageManagerInterface}), and the current `scope`
|
|
188
194
|
* (the active {@link ScopeInterface} filter, or `undefined` for no filtering). `build()` folds the
|
|
189
195
|
* scoped instructions into ONE leading `system` message (under the manager's `description`,
|
|
@@ -214,8 +220,8 @@ export declare interface AgentContextInterface {
|
|
|
214
220
|
* construction). It IS the active {@link ConversationInterface} itself (which satisfies
|
|
215
221
|
* {@link MessageManagerInterface} structurally), so appends through `messages` route to the
|
|
216
222
|
* active conversation's tail and `build()` folds its `view()`. Computed dynamically (it follows
|
|
217
|
-
*
|
|
218
|
-
*
|
|
223
|
+
* `conversations.switch(id)`), the SAME reference the active conversation exposes — no
|
|
224
|
+
* duplication.
|
|
219
225
|
*/
|
|
220
226
|
readonly messages: MessageManagerInterface;
|
|
221
227
|
/**
|
|
@@ -225,12 +231,28 @@ export declare interface AgentContextInterface {
|
|
|
225
231
|
* `messages` is always defined. Switch the active conversation through
|
|
226
232
|
* `conversations.switch(id)` — so one agent can serve MANY conversations (set the active one per
|
|
227
233
|
* request). Switch BETWEEN runs, not during one; for CONCURRENT threads use separate agents (see
|
|
228
|
-
* clause
|
|
234
|
+
* clause 23).
|
|
229
235
|
*/
|
|
230
236
|
readonly conversations: ConversationManagerInterface;
|
|
237
|
+
/**
|
|
238
|
+
* The loop's tool registry for provider advertising and call dispatch. Tools are structural
|
|
239
|
+
* loop machinery and never render into `build()`'s prompt.
|
|
240
|
+
*/
|
|
231
241
|
readonly tools: ToolManagerInterface;
|
|
232
242
|
/** The active scope applied at `build()` time + the loop's tool-advertise step (`undefined` ⇒ no filtering). */
|
|
233
243
|
readonly scope: ScopeInterface | undefined;
|
|
244
|
+
/**
|
|
245
|
+
* Apply the active per-turn scope filter. Passing `undefined` removes filtering.
|
|
246
|
+
*
|
|
247
|
+
* @param scope - The scope to apply, or `undefined` to remove the active filter
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* context.apply(scope)
|
|
252
|
+
* context.apply(undefined)
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
apply(scope: ScopeInterface | undefined): void;
|
|
234
256
|
/**
|
|
235
257
|
* The provider input for the next turn: a leading `system` message folding the prompt
|
|
236
258
|
* + the scoped instructions + the ACTIVE workspace's scoped-in TEXT files (rendered as
|
|
@@ -240,12 +262,13 @@ export declare interface AgentContextInterface {
|
|
|
240
262
|
*
|
|
241
263
|
* @remarks
|
|
242
264
|
* **The active workspace (rendered by carrier) — the SOLE document/image context.** When
|
|
243
|
-
* `workspaces.active` is set, its
|
|
265
|
+
* `workspaces.active` is set, its
|
|
266
|
+
* {@link import('@orkestrel/workspace').WorkspaceInterface.files} are filtered by
|
|
244
267
|
* `scope.files` (a three-way allow-list; `undefined` ⇒ all active files), then split by
|
|
245
|
-
* carrier: TEXT files ({@link import('
|
|
268
|
+
* carrier: TEXT files ({@link import('@orkestrel/workspace').isText}) render into a dedicated
|
|
246
269
|
* `## Workspace` section in the system block — each a fenced
|
|
247
270
|
* `` File: <path>\n```<language>\n<text>\n``` `` block — placed just after the instructions
|
|
248
|
-
* section;
|
|
271
|
+
* section; binary files whose MIME starts with `image/` have their base64 `data`
|
|
249
272
|
* attached to the LAST user message (a vision provider reads images off a user turn).
|
|
250
273
|
* ACTIVE-ONLY — never the other registered workspaces; with NO active workspace nothing is
|
|
251
274
|
* rendered for workspaces.
|
|
@@ -291,21 +314,25 @@ export declare interface AgentContextInterface {
|
|
|
291
314
|
* Options for `createAgentContext` — the richer context's configuration.
|
|
292
315
|
*
|
|
293
316
|
* @remarks
|
|
294
|
-
* `system` is the optional system prompt prepended to the turn's input. `
|
|
295
|
-
* `
|
|
296
|
-
*
|
|
317
|
+
* `system` is the optional system prompt prepended to the turn's input. `instructions` /
|
|
318
|
+
* `workspaces` are optional pre-built context managers to reuse (bring your own registry);
|
|
319
|
+
* when one is omitted, the context creates a fresh empty one. `tools` supplies the loop's
|
|
320
|
+
* call-dispatch and provider-advertising registry; it never renders into the prompt. `scope` is the
|
|
297
321
|
* initial active filter applied at `build()` time (and at the loop's tool-advertise step); it
|
|
298
|
-
* defaults to `undefined` — no filtering — and
|
|
299
|
-
* afterwards. `conversations` is the {@link ConversationManagerInterface} the
|
|
300
|
-
* source flows from: `messages` IS the manager's ACTIVE conversation's live tail
|
|
301
|
-
* folds that conversation's `view()` (section summaries + live). When omitted, a fresh
|
|
322
|
+
* defaults to `undefined` — no filtering — and can be changed through the context's `apply`
|
|
323
|
+
* method afterwards. `conversations` is the structural {@link ConversationManagerInterface} the
|
|
324
|
+
* context's message source flows from: `messages` IS the manager's ACTIVE conversation's live tail
|
|
325
|
+
* and `build()` folds that conversation's `view()` (section summaries + live). When omitted, a fresh
|
|
302
326
|
* {@link ConversationManagerInterface} is created and a default conversation is added (so
|
|
303
327
|
* `messages` is ALWAYS defined). All default to a context with no system prompt, empty registries,
|
|
304
328
|
* no scope, and a fresh conversation registry holding one default conversation.
|
|
305
329
|
*/
|
|
306
330
|
export declare interface AgentContextOptions {
|
|
307
331
|
readonly system?: string;
|
|
308
|
-
/**
|
|
332
|
+
/**
|
|
333
|
+
* The loop's pre-built tool registry for provider advertising and call dispatch; an empty one is
|
|
334
|
+
* created when omitted. Tools never render into `build()`'s prompt.
|
|
335
|
+
*/
|
|
309
336
|
readonly tools?: ToolManagerInterface;
|
|
310
337
|
/** A pre-built instruction registry to reuse; an empty one is created when omitted. */
|
|
311
338
|
readonly instructions?: InstructionManagerInterface;
|
|
@@ -313,8 +340,8 @@ export declare interface AgentContextOptions {
|
|
|
313
340
|
* A pre-built {@link WorkspaceManagerInterface} to reuse; a fresh empty one is created when
|
|
314
341
|
* omitted (so `context.workspaces` is ALWAYS present). `build()` renders the ACTIVE workspace's
|
|
315
342
|
* files by carrier — text files into the system block (fenced), image files attached to the last
|
|
316
|
-
* user message
|
|
317
|
-
* workspace is the SOLE document/image context.
|
|
343
|
+
* user message. The registry is structural; change its active workspace through
|
|
344
|
+
* `workspaces.switch(id)`. The active workspace is the SOLE document/image context.
|
|
318
345
|
*/
|
|
319
346
|
readonly workspaces?: WorkspaceManagerInterface;
|
|
320
347
|
/** The initial active scope (the build-time filter); `undefined` ⇒ no filtering. */
|
|
@@ -326,9 +353,8 @@ export declare interface AgentContextOptions {
|
|
|
326
353
|
* conversation's LIVE tail — is ALWAYS defined. `build()` folds the active conversation's
|
|
327
354
|
* `view()` (the per-section summaries + the live tail) as its AUTHORITATIVE message inclusion —
|
|
328
355
|
* the scope does NOT filter the conversation (it owns inclusion via compaction; scope filters
|
|
329
|
-
* only instructions / tools / workspace files).
|
|
330
|
-
*
|
|
331
|
-
* runs), and the active conversation is switchable through the manager's `switch(id)`.
|
|
356
|
+
* only instructions / tools / workspace files). The registry is structural; change its active
|
|
357
|
+
* conversation through the manager's `switch(id)`.
|
|
332
358
|
*/
|
|
333
359
|
readonly conversations?: ConversationManagerInterface;
|
|
334
360
|
}
|
|
@@ -932,8 +958,8 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
|
|
|
932
958
|
* (an ALLOWLIST — only matched rules that allow get through), pass an `allowed: false`
|
|
933
959
|
* `fallback`.
|
|
934
960
|
* - **Consulted before each tool call.** The agent loop calls `evaluate({ call })` for
|
|
935
|
-
* every {@link import('
|
|
936
|
-
* back to the model as a denial {@link import('
|
|
961
|
+
* every {@link import('@orkestrel/tool').ToolCall} the model emits; a denied call is fed
|
|
962
|
+
* back to the model as a denial {@link import('@orkestrel/tool').ToolResult} (a `tool`
|
|
937
963
|
* chunk + a tool message) instead of being executed — no tool run, no budget cost —
|
|
938
964
|
* so the model sees the denial and can react.
|
|
939
965
|
* - **Synchronous now.** The async human-approval handshake (request / grant / deny) is
|
|
@@ -1038,37 +1064,6 @@ export declare interface AuthorityRule {
|
|
|
1038
1064
|
readonly reason?: string;
|
|
1039
1065
|
}
|
|
1040
1066
|
|
|
1041
|
-
/**
|
|
1042
|
-
* The binary MIME types a {@link FileContent} binary arm carries — the labels for a
|
|
1043
|
-
* base64-encoded payload.
|
|
1044
|
-
*
|
|
1045
|
-
* @remarks
|
|
1046
|
-
* Initialized to the four image MIMEs a vision-capable provider accepts; the union is OPEN
|
|
1047
|
-
* by design — a future binary MIME (e.g. `'application/pdf'`) slots in purely additively (a
|
|
1048
|
-
* new member), with nothing above it changed. {@link import('./helpers.js').isImage}
|
|
1049
|
-
* narrows a binary arm to an image by the `image/` prefix, so an image is just a binary with
|
|
1050
|
-
* an image MIME.
|
|
1051
|
-
*/
|
|
1052
|
-
export declare type BinaryMIME = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
|
|
1053
|
-
|
|
1054
|
-
/**
|
|
1055
|
-
* Project a {@link ToolResult} into the MCP `CallToolResult` shape — a top-level `error`
|
|
1056
|
-
* maps to a single `isError: true` text block (the failure reason), otherwise the `value`
|
|
1057
|
-
* is JSON-stringified into a single text block with no `isError`.
|
|
1058
|
-
*
|
|
1059
|
-
* @param result - The {@link ToolResult} to project (as returned by {@link import('./tools/ToolManager.js').ToolManager.execute})
|
|
1060
|
-
* @returns The equivalent {@link ToolCallResult}
|
|
1061
|
-
*
|
|
1062
|
-
* @example
|
|
1063
|
-
* ```ts
|
|
1064
|
-
* buildToolResult({ id: 'c1', name: 'search', error: 'max depth' })
|
|
1065
|
-
* // { content: [{ type: 'text', text: 'max depth' }], isError: true }
|
|
1066
|
-
* buildToolResult({ id: 'c1', name: 'search', value: { count: 1 } })
|
|
1067
|
-
* // { content: [{ type: 'text', text: '{"count":1}' }] }
|
|
1068
|
-
* ```
|
|
1069
|
-
*/
|
|
1070
|
-
export declare function buildToolResult(result: ToolResult): ToolCallResult;
|
|
1071
|
-
|
|
1072
1067
|
/**
|
|
1073
1068
|
* A minimal unbounded async channel — the eager pump WRITES chunks into it (`push`)
|
|
1074
1069
|
* and ends it (`close` / `fail`) regardless of consumption; a consumer READS them back
|
|
@@ -1089,47 +1084,6 @@ export declare class Channel<T> {
|
|
|
1089
1084
|
drain(): AsyncGenerator<T, void>;
|
|
1090
1085
|
}
|
|
1091
1086
|
|
|
1092
|
-
/**
|
|
1093
|
-
* Clamp a 1-based {@link Position} to the bounds of `text` — every component pinned into a
|
|
1094
|
-
* caret that actually exists in the content.
|
|
1095
|
-
*
|
|
1096
|
-
* @remarks
|
|
1097
|
-
* `line` is pinned to `[1, lineCount]` and `column` to `[1, lineLength + 1]` of the
|
|
1098
|
-
* resolved line (column `lineLength + 1` is the caret just past the line's last
|
|
1099
|
-
* character). So a position beyond the end of the text resolves to the end rather than
|
|
1100
|
-
* overflowing. Total — never throws.
|
|
1101
|
-
*
|
|
1102
|
-
* @param text - The text the position addresses
|
|
1103
|
-
* @param position - The 1-based position to clamp
|
|
1104
|
-
* @returns The clamped {@link Position}
|
|
1105
|
-
*
|
|
1106
|
-
* @example
|
|
1107
|
-
* ```ts
|
|
1108
|
-
* clampPosition('ab\ncd', { line: 9, column: 9 }) // { line: 2, column: 3 } (end of 'cd')
|
|
1109
|
-
* ```
|
|
1110
|
-
*/
|
|
1111
|
-
export declare function clampPosition(text: string, position: Position): Position;
|
|
1112
|
-
|
|
1113
|
-
/**
|
|
1114
|
-
* Clamp both ends of a {@link Range} to the bounds of `text` — the actual span a ranged
|
|
1115
|
-
* read / write applies (and the `range` a {@link import('./types.js').ReadResult} reports).
|
|
1116
|
-
*
|
|
1117
|
-
* @remarks
|
|
1118
|
-
* Clamps `start` and `end` independently via {@link clampPosition}, so a range reaching
|
|
1119
|
-
* past the end of the content is trimmed to the content's end. Total — never throws.
|
|
1120
|
-
*
|
|
1121
|
-
* @param text - The text the range addresses
|
|
1122
|
-
* @param range - The 1-based range to clamp
|
|
1123
|
-
* @returns The clamped {@link Range}
|
|
1124
|
-
*
|
|
1125
|
-
* @example
|
|
1126
|
-
* ```ts
|
|
1127
|
-
* clampRange('ab\ncd', { start: { line: 1, column: 1 }, end: { line: 9, column: 9 } })
|
|
1128
|
-
* // { start: { line: 1, column: 1 }, end: { line: 2, column: 3 } }
|
|
1129
|
-
* ```
|
|
1130
|
-
*/
|
|
1131
|
-
export declare function clampRange(text: string, range: Range): Range;
|
|
1132
|
-
|
|
1133
1087
|
/**
|
|
1134
1088
|
* The PER-RUN auto-compaction state threaded through an {@link AgentInterface}'s loop —
|
|
1135
1089
|
* a tiny immutable value replaced within a holder created fresh per run (so no state leaks across runs or a
|
|
@@ -1165,28 +1119,6 @@ export declare interface CompactOptions {
|
|
|
1165
1119
|
readonly sections?: number;
|
|
1166
1120
|
}
|
|
1167
1121
|
|
|
1168
|
-
/**
|
|
1169
|
-
* Compute the byte size of a {@link FileContent} — the `size` a {@link FileInterface} derives
|
|
1170
|
-
* once when built.
|
|
1171
|
-
*
|
|
1172
|
-
* @remarks
|
|
1173
|
-
* Dispatches on {@link isText}: a text arm is its UTF-8 byte length (via `new
|
|
1174
|
-
* TextEncoder().encode(text).length` — the standard Web/Node API, so a multi-byte
|
|
1175
|
-
* character like `'é'` or `'😀'` counts as its real encoded bytes, NOT its character
|
|
1176
|
-
* count); a binary arm is the decoded payload byte length of its base64 `data` (via
|
|
1177
|
-
* {@link decodedSize}, computed arithmetically — no `atob` / `Buffer`). Total — never throws.
|
|
1178
|
-
*
|
|
1179
|
-
* @param content - The file content to size
|
|
1180
|
-
* @returns The byte size (UTF-8 bytes for text; decoded payload bytes for binary)
|
|
1181
|
-
*
|
|
1182
|
-
* @example
|
|
1183
|
-
* ```ts
|
|
1184
|
-
* computeSize({ text: 'café', language: 'text' }) // 5 (é is two bytes)
|
|
1185
|
-
* computeSize({ data: 'AAAA', mime: 'image/png' }) // 3
|
|
1186
|
-
* ```
|
|
1187
|
-
*/
|
|
1188
|
-
export declare function computeSize(content: FileContent): number;
|
|
1189
|
-
|
|
1190
1122
|
/**
|
|
1191
1123
|
* A provider's OPTIONAL context-framing default, keyed by section kind — the framing a
|
|
1192
1124
|
* model prefers (e.g. XML tags vs. Markdown headers), declared by a
|
|
@@ -1397,7 +1329,8 @@ export declare type ConversationEventMap = {
|
|
|
1397
1329
|
* (initial {@link ConversationEventMap} listeners). `snapshot` is
|
|
1398
1330
|
* the construction-time hydration seam — a {@link ConversationSnapshot} whose `id` / `summary` /
|
|
1399
1331
|
* `sections` / live tail are RESTORED into the new conversation (the live `summarize` / `keep` /
|
|
1400
|
-
* `on` re-supplied alongside it), the conversation analogue of
|
|
1332
|
+
* `on` re-supplied alongside it), the conversation analogue of
|
|
1333
|
+
* {@link import('@orkestrel/workspace').WorkspaceOptions}'s `seed` that a
|
|
1401
1334
|
* {@link ConversationManagerInterface.open} reads a stored snapshot back through; hydration is
|
|
1402
1335
|
* silent (no events). When both `snapshot.id` and `id` are given, `snapshot.id` wins (the snapshot
|
|
1403
1336
|
* IS the conversation's identity).
|
|
@@ -1411,7 +1344,7 @@ export declare interface ConversationInput {
|
|
|
1411
1344
|
/** Overrides the manager's default `sections` cap for this conversation. */
|
|
1412
1345
|
readonly sections?: number;
|
|
1413
1346
|
readonly on?: EmitterHooks<ConversationEventMap>;
|
|
1414
|
-
/** A {@link ConversationSnapshot} to hydrate
|
|
1347
|
+
/** A {@link ConversationSnapshot} to hydrate from, analogous to the workspace package's seed input. */
|
|
1415
1348
|
readonly snapshot?: ConversationSnapshot;
|
|
1416
1349
|
}
|
|
1417
1350
|
|
|
@@ -1587,8 +1520,9 @@ export declare interface ConversationInterface {
|
|
|
1587
1520
|
*
|
|
1588
1521
|
* @remarks
|
|
1589
1522
|
* The container serializes ITSELF (`{ id, summary, sections, messages: this.messages() }`) — the
|
|
1590
|
-
* {@link ConversationStoreInterface} persistence seam's payload, the
|
|
1591
|
-
* {@link WorkspaceInterface
|
|
1523
|
+
* {@link ConversationStoreInterface} persistence seam's payload, the exact analogue of
|
|
1524
|
+
* {@link import('@orkestrel/workspace').WorkspaceInterface}'s `snapshot`. The summarizer /
|
|
1525
|
+
* `keep` are NOT serialized — they are live
|
|
1592
1526
|
* CONFIG re-supplied on hydrate (a `ConversationSummarizer` is a function, not data). The snapshot
|
|
1593
1527
|
* is the durable analogue of the constructor `seed`: a {@link ConversationManagerInterface}
|
|
1594
1528
|
* HYDRATES a conversation from it through that seam (see {@link ConversationManagerInterface.open}).
|
|
@@ -1604,7 +1538,7 @@ export declare interface ConversationInterface {
|
|
|
1604
1538
|
* The registry of {@link Conversation}s keyed by `id`, in insertion order, WITH an active pointer
|
|
1605
1539
|
* — the §9 store over the conversation layer PLUS the `active` / `switch` seam the
|
|
1606
1540
|
* {@link import('../AgentContext.js').AgentContext} renders. Event-free (a registry, like
|
|
1607
|
-
* {@link import('
|
|
1541
|
+
* {@link import('@orkestrel/workspace').WorkspaceManager}); the observability lives
|
|
1608
1542
|
* on each {@link Conversation}.
|
|
1609
1543
|
*
|
|
1610
1544
|
* @remarks
|
|
@@ -1654,7 +1588,7 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1654
1588
|
* A registry of {@link ConversationInterface}s keyed by their `id`, in insertion order, WITH an
|
|
1655
1589
|
* active pointer — the §9 store over the conversation layer PLUS the `active` / `switch` seam the
|
|
1656
1590
|
* {@link AgentContextInterface} renders. Event-free (a registry, like
|
|
1657
|
-
* {@link WorkspaceManagerInterface}); the observability lives on each
|
|
1591
|
+
* {@link import('@orkestrel/workspace').WorkspaceManagerInterface}); the observability lives on each
|
|
1658
1592
|
* {@link ConversationInterface}.
|
|
1659
1593
|
*
|
|
1660
1594
|
* @remarks
|
|
@@ -1677,8 +1611,8 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1677
1611
|
* miss (rebuilding it through the constructor `seed` from the snapshot, flowing the manager's
|
|
1678
1612
|
* default `summarize` / `keep` in) and `save(id)` PERSISTS a registered conversation's
|
|
1679
1613
|
* {@link ConversationInterface.snapshot}. Both are LENIENT without a store — `open` resolves only
|
|
1680
|
-
* registered ids, `save` is a no-op (`false`) — consistent with the lenient `switch`.
|
|
1681
|
-
*
|
|
1614
|
+
* registered ids, `save` is a no-op (`false`) — consistent with the lenient `switch`. It mirrors
|
|
1615
|
+
* the workspace package manager's `open` / `save` seam.
|
|
1682
1616
|
* - **Event-free.** A purely registry store — no Emitter, no events (each conversation owns
|
|
1683
1617
|
* its own).
|
|
1684
1618
|
*/
|
|
@@ -1749,8 +1683,8 @@ export declare interface ConversationManagerOptions {
|
|
|
1749
1683
|
* {@link ConversationManagerInterface.open} / {@link ConversationManagerInterface.save} — a memory
|
|
1750
1684
|
* / JSON / SQLite / IndexedDB store a conversation is HYDRATED from (`open` a registry-miss) and
|
|
1751
1685
|
* PERSISTED to (`save`). Omitted ⇒ the manager is registry-only: `open` resolves only what is
|
|
1752
|
-
* already registered, and `save` is a no-op (`false`). The
|
|
1753
|
-
* {@link WorkspaceManagerOptions
|
|
1686
|
+
* already registered, and `save` is a no-op (`false`). The exact analogue of
|
|
1687
|
+
* {@link import('@orkestrel/workspace').WorkspaceManagerOptions}'s `store`.
|
|
1754
1688
|
*/
|
|
1755
1689
|
readonly store?: ConversationStoreInterface;
|
|
1756
1690
|
}
|
|
@@ -1816,7 +1750,8 @@ export declare interface ConversationReferenceOptions {
|
|
|
1816
1750
|
/**
|
|
1817
1751
|
* A JSON-serializable snapshot of a conversation's state — its `id`, the rollup `summary`, the
|
|
1818
1752
|
* compacted `sections`, and the live tail `messages` — the durable payload the
|
|
1819
|
-
* {@link ConversationStoreInterface} persists. The
|
|
1753
|
+
* {@link ConversationStoreInterface} persists. The exact analogue of
|
|
1754
|
+
* {@link import('@orkestrel/workspace').WorkspaceSnapshot}.
|
|
1820
1755
|
*
|
|
1821
1756
|
* @remarks
|
|
1822
1757
|
* Pure JSON DATA (no class instances, no functions): each {@link SectionInterface} and
|
|
@@ -1845,12 +1780,13 @@ export declare interface ConversationSnapshot {
|
|
|
1845
1780
|
* One row of the table a
|
|
1846
1781
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
1847
1782
|
* persists — a conversation `id` plus its {@link ConversationSnapshot} held as ONE OPAQUE JSON
|
|
1848
|
-
* column. The
|
|
1783
|
+
* column. The exact analogue of {@link import('@orkestrel/workspace').WorkspaceSnapshotRow}.
|
|
1849
1784
|
*
|
|
1850
1785
|
* @remarks
|
|
1851
1786
|
* The Database twin of {@link ConversationStoreInterface} stores the snapshot whole (the `snapshot`
|
|
1852
|
-
* column is a `rawShape`, an opaque JSON blob — exactly as
|
|
1853
|
-
* workspace snapshot), so the
|
|
1787
|
+
* column is a `rawShape`, an opaque JSON blob — exactly as
|
|
1788
|
+
* {@link import('@orkestrel/workspace').WorkspaceSnapshotRow} stores a workspace snapshot), so the
|
|
1789
|
+
* row type stays FLAT and the sections/messages snapshot shape never
|
|
1854
1790
|
* forces the contract to `Infer` it. The column therefore reads back as the broad `unknown`; the
|
|
1855
1791
|
* store narrows it to a {@link ConversationSnapshot} on `get`
|
|
1856
1792
|
* ({@link import('./helpers.js').isConversationSnapshot}, the AGENTS §14 boundary narrow). `id`
|
|
@@ -1865,8 +1801,8 @@ export declare interface ConversationSnapshotRow {
|
|
|
1865
1801
|
|
|
1866
1802
|
/**
|
|
1867
1803
|
* The durable persistence seam for a {@link ConversationSnapshot} — three async primitives
|
|
1868
|
-
* (`get` / `set` / `delete`) keyed by a conversation id, the
|
|
1869
|
-
* {@link WorkspaceStoreInterface}.
|
|
1804
|
+
* (`get` / `set` / `delete`) keyed by a conversation id, the exact analogue of
|
|
1805
|
+
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}.
|
|
1870
1806
|
*
|
|
1871
1807
|
* @remarks
|
|
1872
1808
|
* The store persists the {@link ConversationSnapshot} — the self-contained, pure-JSON conversation
|
|
@@ -1882,7 +1818,9 @@ export declare interface ConversationSnapshotRow {
|
|
|
1882
1818
|
*
|
|
1883
1819
|
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
1884
1820
|
* same shape as the memory one. The snapshot carries its OWN id, so `set` takes no separate id
|
|
1885
|
-
* param (mirroring
|
|
1821
|
+
* param (mirroring
|
|
1822
|
+
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`). UNLIKE a session store
|
|
1823
|
+
* there is NO idle-TTL
|
|
1886
1824
|
* / eviction — a persisted conversation lives until an explicit `delete`. It is concrete over
|
|
1887
1825
|
* {@link ConversationSnapshot} — no generic parameter (AGENTS §21 minimal-interface), since the
|
|
1888
1826
|
* snapshot is the ONE payload a conversation store persists.
|
|
@@ -1897,7 +1835,7 @@ export declare interface ConversationStoreInterface {
|
|
|
1897
1835
|
get(id: string): Promise<ConversationSnapshot | undefined>;
|
|
1898
1836
|
/**
|
|
1899
1837
|
* Insert or replace a snapshot under its own `snapshot.id` (no separate id param —
|
|
1900
|
-
* mirroring {@link WorkspaceStoreInterface
|
|
1838
|
+
* mirroring {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`).
|
|
1901
1839
|
*
|
|
1902
1840
|
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
1903
1841
|
*/
|
|
@@ -1928,28 +1866,6 @@ export declare interface ConversationStoreInterface {
|
|
|
1928
1866
|
*/
|
|
1929
1867
|
export declare type ConversationSummarizer = (messages: readonly MessageInterface[]) => Promise<string>;
|
|
1930
1868
|
|
|
1931
|
-
/**
|
|
1932
|
-
* Count the lines of a {@link FileContent} — the `lines` a {@link FileInterface} derives once
|
|
1933
|
-
* when built.
|
|
1934
|
-
*
|
|
1935
|
-
* @remarks
|
|
1936
|
-
* A text arm's line count is `0` for the empty string, otherwise one more than the
|
|
1937
|
-
* number of newline (`\n`) separators it contains — so `'a'` is one line, `'a\nb'` is two,
|
|
1938
|
-
* and a trailing newline `'a\n'` counts the empty final line as two. A binary arm has no
|
|
1939
|
-
* lines and returns `0`. Total — never throws.
|
|
1940
|
-
*
|
|
1941
|
-
* @param content - The file content to count lines for
|
|
1942
|
-
* @returns The line count (text line count; `0` for a binary arm or empty text)
|
|
1943
|
-
*
|
|
1944
|
-
* @example
|
|
1945
|
-
* ```ts
|
|
1946
|
-
* countLines({ text: '', language: 'text' }) // 0
|
|
1947
|
-
* countLines({ text: 'a\nb\nc', language: 'text' }) // 3
|
|
1948
|
-
* countLines({ data: 'AAAA', mime: 'image/png' }) // 0
|
|
1949
|
-
* ```
|
|
1950
|
-
*/
|
|
1951
|
-
export declare function countLines(content: FileContent): number;
|
|
1952
|
-
|
|
1953
1869
|
/**
|
|
1954
1870
|
* Create an agent loop — an {@link AgentInterface} composing a
|
|
1955
1871
|
* {@link ProviderInterface}, its {@link AgentContextInterface}, and a tool registry
|
|
@@ -2001,8 +1917,8 @@ export declare function createAgent(provider: ProviderInterface, options?: Agent
|
|
|
2001
1917
|
* @remarks
|
|
2002
1918
|
* `system` is the optional system prompt; `tools` / `instructions` / `workspaces` are pre-built
|
|
2003
1919
|
* managers to reuse (empty ones are created when omitted, so `context.workspaces` is ALWAYS
|
|
2004
|
-
* present); `scope` is the initial active filter (`undefined` ⇒ no filtering,
|
|
2005
|
-
* via `context.
|
|
1920
|
+
* present); `scope` is the initial active filter (`undefined` ⇒ no filtering, changeable afterwards
|
|
1921
|
+
* via `context.apply(...)`). The `messages` store is always fresh. `build()` folds the scoped
|
|
2006
1922
|
* instructions — PLUS the ACTIVE workspace's scope-filtered text files (fenced) — into ONE leading
|
|
2007
1923
|
* `system` message and appends the scoped conversation (attaching the active workspace's
|
|
2008
1924
|
* scope-filtered image files' `data` to the last user message), built fresh each call; the active
|
|
@@ -2084,8 +2000,9 @@ export declare function createAgentQueue(options: AgentQueueOptions): QueueInter
|
|
|
2084
2000
|
*
|
|
2085
2001
|
* @example
|
|
2086
2002
|
* ```ts
|
|
2003
|
+
* import { createAgentRegistry } from '@src/core'
|
|
2087
2004
|
* import type { ProviderInterface } from '@src/core'
|
|
2088
|
-
* import {
|
|
2005
|
+
* import { createTool } from '@orkestrel/tool'
|
|
2089
2006
|
*
|
|
2090
2007
|
* declare const provider: ProviderInterface // any concrete implementation supplied by the host app
|
|
2091
2008
|
* const registry = createAgentRegistry({
|
|
@@ -2166,24 +2083,6 @@ export declare function createAgentRunner(options: AgentRunnerOptions): RunnerIn
|
|
|
2166
2083
|
*/
|
|
2167
2084
|
export declare function createAuthority(options?: AuthorityOptions): AuthorityInterface;
|
|
2168
2085
|
|
|
2169
|
-
/**
|
|
2170
|
-
* Build the BINARY {@link FileContent} arm — the §4.2.3 split constructor for binary (a
|
|
2171
|
-
* separate function per arm, not one constructor dispatching on a discriminator parameter).
|
|
2172
|
-
* An image is just a binary with an image {@link BinaryMIME}.
|
|
2173
|
-
*
|
|
2174
|
-
* @param data - The base64-encoded binary payload
|
|
2175
|
-
* @param mime - The {@link BinaryMIME} that labels the payload
|
|
2176
|
-
* @returns A `{ data; mime }` content arm
|
|
2177
|
-
*
|
|
2178
|
-
* @example
|
|
2179
|
-
* ```ts
|
|
2180
|
-
* import { createBinaryContent } from '@src/core'
|
|
2181
|
-
*
|
|
2182
|
-
* createBinaryContent('<base64>', 'image/png') // { data: '<base64>', mime: 'image/png' }
|
|
2183
|
-
* ```
|
|
2184
|
-
*/
|
|
2185
|
-
export declare function createBinaryContent(data: string, mime: BinaryMIME): FileContent;
|
|
2186
|
-
|
|
2187
2086
|
/**
|
|
2188
2087
|
* Create a conversation — a {@link ConversationInterface} grouping messages above a flat
|
|
2189
2088
|
* message store it OWNS DIRECTLY, with compaction into summarized sections, a regenerated
|
|
@@ -2255,12 +2154,14 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2255
2154
|
/**
|
|
2256
2155
|
* Create a {@link DatabaseConversationStore} over any {@link DriverInterface} — the durable,
|
|
2257
2156
|
* driver-pluggable backing for the conversation persistence seam, the opt-in twin of
|
|
2258
|
-
* {@link createMemoryConversationStore}. The
|
|
2157
|
+
* {@link createMemoryConversationStore}. The exact twin of
|
|
2158
|
+
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore}.
|
|
2259
2159
|
*
|
|
2260
2160
|
* @remarks
|
|
2261
2161
|
* Builds a one-table database (`conversations`, keyed by `id`) over the supplied driver, the snapshot
|
|
2262
2162
|
* held as ONE OPAQUE JSON COLUMN — the column map is `{ id; snapshot }` where `snapshot` is a
|
|
2263
|
-
* `rawShape` (a JSON blob), exactly as
|
|
2163
|
+
* `rawShape` (a JSON blob), exactly as
|
|
2164
|
+
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore} stores its snapshot. The
|
|
2264
2165
|
* snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
2265
2166
|
* AND keeps the row type FLAT (the column reads back as `unknown`, narrowed on `get` by
|
|
2266
2167
|
* {@link import('./helpers.js').isConversationSnapshot}). The `driver` DEFAULTS to
|
|
@@ -2285,65 +2186,6 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2285
2186
|
*/
|
|
2286
2187
|
export declare function createDatabaseConversationStore(driver?: DriverInterface): ConversationStoreInterface;
|
|
2287
2188
|
|
|
2288
|
-
/**
|
|
2289
|
-
* Create a {@link DatabaseWorkspaceStore} over any {@link DriverInterface} — the durable,
|
|
2290
|
-
* driver-pluggable backing for the workspace persistence seam, the opt-in twin of
|
|
2291
|
-
* {@link createMemoryWorkspaceStore}.
|
|
2292
|
-
*
|
|
2293
|
-
* @remarks
|
|
2294
|
-
* Builds a one-table database (`workspaces`, keyed by `id`) over the supplied driver, the snapshot
|
|
2295
|
-
* held as ONE OPAQUE JSON COLUMN — the column map is `{ id; snapshot }` where `snapshot` is a
|
|
2296
|
-
* `rawShape` (a JSON blob), exactly as
|
|
2297
|
-
* the analogous `createDatabaseWorkflowStore` in `@orkestrel/workflow` stores its snapshot. The
|
|
2298
|
-
* snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
2299
|
-
* AND keeps the row type FLAT (the column reads back as `unknown`, narrowed on `get` by
|
|
2300
|
-
* {@link import('./helpers.js').isWorkspaceSnapshot}). The `driver` DEFAULTS to
|
|
2301
|
-
* {@link createMemoryDriver}, so the store ALSO works in memory out of the box; pass a server
|
|
2302
|
-
* `createJSONDriver` / `createSQLiteDriver` (or a browser IndexedDB driver) for a persistent one —
|
|
2303
|
-
* the durability is the driver's job, the store engine is shared. It swaps in behind
|
|
2304
|
-
* {@link WorkspaceStoreInterface} WITHOUT touching the manager or the workspace.
|
|
2305
|
-
*
|
|
2306
|
-
* @param driver - The storage backend the snapshots persist to (defaults to {@link createMemoryDriver})
|
|
2307
|
-
* @returns A {@link WorkspaceStoreInterface} over the driver
|
|
2308
|
-
*
|
|
2309
|
-
* @example
|
|
2310
|
-
* ```ts
|
|
2311
|
-
* import { createDatabaseWorkspaceStore, createMemoryDriver, createWorkspaceManager } from '@src/core'
|
|
2312
|
-
*
|
|
2313
|
-
* const store = createDatabaseWorkspaceStore(createMemoryDriver()) // a durable driver swaps in here
|
|
2314
|
-
* const manager = createWorkspaceManager({ store })
|
|
2315
|
-
* const workspace = manager.add()
|
|
2316
|
-
* workspace.write('notes.txt', 'hello')
|
|
2317
|
-
* await manager.save(workspace.id) // persist the workspace (one JSON column)
|
|
2318
|
-
* ```
|
|
2319
|
-
*/
|
|
2320
|
-
export declare function createDatabaseWorkspaceStore(driver?: DriverInterface): WorkspaceStoreInterface;
|
|
2321
|
-
|
|
2322
|
-
/**
|
|
2323
|
-
* Create a file — an immutable {@link FileInterface} from its `path` + {@link FileContent}
|
|
2324
|
-
* and optional {@link import('./types.js').FileState}, with `size` / `lines` DERIVED from the
|
|
2325
|
-
* content.
|
|
2326
|
-
*
|
|
2327
|
-
* @remarks
|
|
2328
|
-
* Returns a PLAIN `Object.freeze`d record (NOT a class instance) — the `path` IS its identity
|
|
2329
|
-
* (there is no `id`). Only `path` / `content` are required; `state` defaults to `'created'`
|
|
2330
|
-
* when omitted. `size` (via {@link computeSize}) and `lines` (via {@link countLines}) are
|
|
2331
|
-
* computed from the content here (so they never drift from it). Frozen + plain, so it
|
|
2332
|
-
* `structuredClone`s losslessly and is never mutated after creation.
|
|
2333
|
-
*
|
|
2334
|
-
* @param input - `path` / `content` (required) and an optional `state` (see {@link FileInput})
|
|
2335
|
-
* @returns A frozen {@link FileInterface} record
|
|
2336
|
-
*
|
|
2337
|
-
* @example
|
|
2338
|
-
* ```ts
|
|
2339
|
-
* import { createFile, createTextContent } from '@src/core'
|
|
2340
|
-
*
|
|
2341
|
-
* const file = createFile({ path: 'src/main.ts', content: createTextContent('const x = 1', 'typescript') })
|
|
2342
|
-
* file.lines // 1
|
|
2343
|
-
* ```
|
|
2344
|
-
*/
|
|
2345
|
-
export declare function createFile(input: FileInput): FileInterface;
|
|
2346
|
-
|
|
2347
2189
|
/**
|
|
2348
2190
|
* Create an instruction — an immutable {@link InstructionInterface} (a named directive)
|
|
2349
2191
|
* from its `name` / `content` and optional `priority`, the `id` minted at construction.
|
|
@@ -2400,11 +2242,13 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2400
2242
|
* Create the in-memory conversation store — a {@link ConversationStoreInterface} backed by a
|
|
2401
2243
|
* process-lifetime `Map` of {@link import('./types.js').ConversationSnapshot}s keyed by conversation
|
|
2402
2244
|
* id, the DEFAULT backing for the durable {@link ConversationManagerInterface.open} /
|
|
2403
|
-
* {@link ConversationManagerInterface.save} seam. The
|
|
2245
|
+
* {@link ConversationManagerInterface.save} seam. The exact twin of
|
|
2246
|
+
* {@link import('@orkestrel/workspace').createMemoryWorkspaceStore}.
|
|
2404
2247
|
*
|
|
2405
2248
|
* @remarks
|
|
2406
2249
|
* A plain `Map` (the snapshot is already pure JSON, so no encoding is needed for the memory tier),
|
|
2407
|
-
* the structural twin of {@link createMemoryWorkspaceStore}.
|
|
2250
|
+
* the structural twin of {@link import('@orkestrel/workspace').createMemoryWorkspaceStore}.
|
|
2251
|
+
* `get` / `set` / `delete` are async (the
|
|
2408
2252
|
* same shape a durable backend fits); UNLIKE a session store there is NO idle-TTL / eviction — a
|
|
2409
2253
|
* persisted conversation lives until an explicit `delete`. Its driver-pluggable twin is
|
|
2410
2254
|
* {@link createDatabaseConversationStore} (the snapshot as one opaque JSON column over a `databases`
|
|
@@ -2428,37 +2272,6 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2428
2272
|
*/
|
|
2429
2273
|
export declare function createMemoryConversationStore(): ConversationStoreInterface;
|
|
2430
2274
|
|
|
2431
|
-
/**
|
|
2432
|
-
* Create the in-memory workspace store — a {@link WorkspaceStoreInterface} backed by a
|
|
2433
|
-
* process-lifetime `Map` of {@link import('./types.js').WorkspaceSnapshot}s keyed by workspace id,
|
|
2434
|
-
* the DEFAULT backing for the durable {@link WorkspaceManagerInterface.open} /
|
|
2435
|
-
* {@link WorkspaceManagerInterface.save} seam.
|
|
2436
|
-
*
|
|
2437
|
-
* @remarks
|
|
2438
|
-
* A plain `Map` (the snapshot is already pure JSON, so no encoding is needed for the memory tier),
|
|
2439
|
-
* the structural twin of the analogous `createMemoryWorkflowStore` in `@orkestrel/workflow`.
|
|
2440
|
-
* `get` / `set` / `delete` are async (the same shape a durable backend fits); UNLIKE a session
|
|
2441
|
-
* store there is NO idle-TTL / eviction — a persisted workspace lives until an explicit `delete`.
|
|
2442
|
-
* Its driver-pluggable twin is {@link createDatabaseWorkspaceStore} (the snapshot as one opaque
|
|
2443
|
-
* JSON column over a `databases` table) — for a DURABLE store pass it a JSON / SQLite / IndexedDB
|
|
2444
|
-
* driver, and it swaps in WITHOUT touching the manager or the workspace. Hydration stays a manager
|
|
2445
|
-
* concern: read a snapshot back and rebuild the live workspace through the constructor `seed`.
|
|
2446
|
-
*
|
|
2447
|
-
* @returns A memory-backed {@link WorkspaceStoreInterface}
|
|
2448
|
-
*
|
|
2449
|
-
* @example
|
|
2450
|
-
* ```ts
|
|
2451
|
-
* import { createMemoryWorkspaceStore, createWorkspaceManager } from '@src/core'
|
|
2452
|
-
*
|
|
2453
|
-
* const store = createMemoryWorkspaceStore()
|
|
2454
|
-
* const manager = createWorkspaceManager({ store })
|
|
2455
|
-
* const workspace = manager.add()
|
|
2456
|
-
* workspace.write('notes.txt', 'hello')
|
|
2457
|
-
* await manager.save(workspace.id) // persist the workspace
|
|
2458
|
-
* ```
|
|
2459
|
-
*/
|
|
2460
|
-
export declare function createMemoryWorkspaceStore(): WorkspaceStoreInterface;
|
|
2461
|
-
|
|
2462
2275
|
/**
|
|
2463
2276
|
* Create a named scope — an immutable {@link ScopeInterface} from its `name` and the four
|
|
2464
2277
|
* optional per-category allow-lists, the `id` minted at construction.
|
|
@@ -2508,23 +2321,6 @@ export declare function createScope(input: ScopeInput): ScopeInterface;
|
|
|
2508
2321
|
*/
|
|
2509
2322
|
export declare function createScopeManager(options?: ScopeManagerOptions): ScopeManagerInterface;
|
|
2510
2323
|
|
|
2511
|
-
/**
|
|
2512
|
-
* Build the TEXT {@link FileContent} arm — the §4.2.3 split constructor for text (a separate
|
|
2513
|
-
* function per arm, not one constructor dispatching on a discriminator parameter).
|
|
2514
|
-
*
|
|
2515
|
-
* @param text - The literal text body
|
|
2516
|
-
* @param language - The fenced-code language the text renders as (e.g. `'typescript'`)
|
|
2517
|
-
* @returns A `{ text; language }` content arm
|
|
2518
|
-
*
|
|
2519
|
-
* @example
|
|
2520
|
-
* ```ts
|
|
2521
|
-
* import { createTextContent } from '@src/core'
|
|
2522
|
-
*
|
|
2523
|
-
* createTextContent('const x = 1', 'typescript') // { text: 'const x = 1', language: 'typescript' }
|
|
2524
|
-
* ```
|
|
2525
|
-
*/
|
|
2526
|
-
export declare function createTextContent(text: string, language: string): FileContent;
|
|
2527
|
-
|
|
2528
2324
|
/**
|
|
2529
2325
|
* Create a stream-stateful `<think>` separator — a {@link ThinkSplitterInterface} that
|
|
2530
2326
|
* splits a thinking model's in-content `<think>…</think>` reasoning spans away from
|
|
@@ -2554,122 +2350,12 @@ export declare function createTextContent(text: string, language: string): FileC
|
|
|
2554
2350
|
*/
|
|
2555
2351
|
export declare function createThinkSplitter(): ThinkSplitterInterface;
|
|
2556
2352
|
|
|
2557
|
-
/**
|
|
2558
|
-
* Create a tool — a {@link ToolInterface} binding a {@link ToolDefinition} schema
|
|
2559
|
-
* (the `name` / `description` / `parameters` the model sees) to the `execute` handler
|
|
2560
|
-
* that runs a call.
|
|
2561
|
-
*
|
|
2562
|
-
* @remarks
|
|
2563
|
-
* Only `name` is required (it keys the tool in a {@link ToolManagerInterface} and is
|
|
2564
|
-
* what the model calls); `description` / `parameters` are the optional JSON-Schema the
|
|
2565
|
-
* provider advertises (forwarded verbatim). The handler's `args` is the model-supplied
|
|
2566
|
-
* `unknown` arguments record — narrow it inside (§14); a `createToolManager` registry
|
|
2567
|
-
* isolates a throw into a `ToolResult.error`.
|
|
2568
|
-
*
|
|
2569
|
-
* @param options - `name` (required), optional `description` / `parameters`, and the
|
|
2570
|
-
* `execute` handler (see {@link ToolOptions})
|
|
2571
|
-
* @returns A working {@link ToolInterface}
|
|
2572
|
-
*
|
|
2573
|
-
* @example
|
|
2574
|
-
* ```ts
|
|
2575
|
-
* import { createTool } from '@src/core'
|
|
2576
|
-
*
|
|
2577
|
-
* const add = createTool({
|
|
2578
|
-
* name: 'add',
|
|
2579
|
-
* description: 'Add two numbers',
|
|
2580
|
-
* execute: (args) => Number(args.a) + Number(args.b),
|
|
2581
|
-
* })
|
|
2582
|
-
* ```
|
|
2583
|
-
*/
|
|
2584
|
-
export declare function createTool(options: ToolOptions): ToolInterface;
|
|
2585
|
-
|
|
2586
|
-
/**
|
|
2587
|
-
* Create a tool registry — a {@link ToolManagerInterface} that resolves tool names,
|
|
2588
|
-
* lists {@link ToolDefinition}s for the provider, and executes calls with per-call
|
|
2589
|
-
* error isolation.
|
|
2590
|
-
*
|
|
2591
|
-
* @remarks
|
|
2592
|
-
* Starts empty; `add` registers one tool or a batch (§9.2), `definitions()` yields the
|
|
2593
|
-
* schemas to hand a provider, and `execute` runs a {@link ToolCall} (or a batch),
|
|
2594
|
-
* ALWAYS resolving a {@link ToolResult} — a handler throw becomes an `error` result and
|
|
2595
|
-
* an unknown name a not-found `error`, so a tool throw never escapes and a batch never
|
|
2596
|
-
* fails as a whole.
|
|
2597
|
-
*
|
|
2598
|
-
* @returns An empty {@link ToolManagerInterface}
|
|
2599
|
-
*
|
|
2600
|
-
* @example
|
|
2601
|
-
* ```ts
|
|
2602
|
-
* import { createTool, createToolManager } from '@src/core'
|
|
2603
|
-
*
|
|
2604
|
-
* const tools = createToolManager()
|
|
2605
|
-
* tools.add(createTool({ name: 'add', execute: (a) => Number(a.x) + Number(a.y) }))
|
|
2606
|
-
* const result = await tools.execute({ id: '1', name: 'add', arguments: { x: 1, y: 2 } })
|
|
2607
|
-
* ```
|
|
2608
|
-
*/
|
|
2609
|
-
export declare function createToolManager(): ToolManagerInterface;
|
|
2610
|
-
|
|
2611
|
-
/**
|
|
2612
|
-
* Create a workspace — a mutable, `path`-keyed working set of immutable
|
|
2613
|
-
* {@link FileInterface}s with the in-memory edit surface (read / write / search / replace /
|
|
2614
|
-
* move / remove), observable through its `EmitterInterface` (from `@orkestrel/emitter`).
|
|
2615
|
-
*
|
|
2616
|
-
* @param options - Optional initial {@link import('./types.js').WorkspaceEventMap} listeners (`on`) and the emitter's `error` handler (see {@link WorkspaceOptions})
|
|
2617
|
-
* @returns A working {@link WorkspaceInterface}
|
|
2618
|
-
*
|
|
2619
|
-
* @example
|
|
2620
|
-
* ```ts
|
|
2621
|
-
* import { createWorkspace } from '@src/core'
|
|
2622
|
-
*
|
|
2623
|
-
* const workspace = createWorkspace({ on: { write: (file) => console.log(file.path) } })
|
|
2624
|
-
* workspace.write('src/main.ts', 'const x = 1')
|
|
2625
|
-
* workspace.file('src/main.ts')?.state // 'created'
|
|
2626
|
-
* ```
|
|
2627
|
-
*/
|
|
2628
|
-
export declare function createWorkspace(options?: WorkspaceOptions): WorkspaceInterface;
|
|
2629
|
-
|
|
2630
|
-
/**
|
|
2631
|
-
* Create a workspace registry — a {@link WorkspaceManagerInterface} holding
|
|
2632
|
-
* {@link WorkspaceInterface}s keyed by their `id` (in insertion order) WITH an active pointer:
|
|
2633
|
-
* the §9 store over the workspace layer plus the `active` / `switch` seam the context renders.
|
|
2634
|
-
*
|
|
2635
|
-
* @remarks
|
|
2636
|
-
* Starts empty; `add(input?)` mints a {@link WorkspaceInterface} (its `id` from the input or a
|
|
2637
|
-
* random UUID), flowing the manager's default `on` / `error` in unless the input overrides them,
|
|
2638
|
-
* and stores it (an already-present `id` overwrites — last write wins) — and AUTO-ACTIVATES the
|
|
2639
|
-
* FIRST one (a registry with workspaces always has one `active`); a later `add` leaves `active`
|
|
2640
|
-
* unchanged. `switch(id)` re-points `active` (an unknown `id` returns `undefined`, leaving
|
|
2641
|
-
* `active` unchanged — lenient, never throws); `workspace(id)` / `workspaces()` look up;
|
|
2642
|
-
* `remove` (one or a batch, §9.2) reports whether any was removed AND clears `active` if it was
|
|
2643
|
-
* the removed one; `clear` empties it and clears `active`. Event-free (each workspace owns its
|
|
2644
|
-
* own observable `emitter`).
|
|
2645
|
-
*
|
|
2646
|
-
* With the optional `store` ({@link WorkspaceStoreInterface}, e.g. `createMemoryWorkspaceStore` /
|
|
2647
|
-
* `createDatabaseWorkspaceStore`), `open(id)` HYDRATES a workspace on a registry miss (rebuilding it
|
|
2648
|
-
* through the constructor `seed` from the snapshot's `files`, then activating it) and `save(id)`
|
|
2649
|
-
* PERSISTS a registered workspace's `snapshot()`. Both are LENIENT without a store (open resolves
|
|
2650
|
-
* only registered ids, save is a no-op `false`).
|
|
2651
|
-
*
|
|
2652
|
-
* @param options - Optional default `on` / `error` for created workspaces + the durable `store`
|
|
2653
|
-
* (see {@link WorkspaceManagerOptions})
|
|
2654
|
-
* @returns An empty {@link WorkspaceManagerInterface}
|
|
2655
|
-
*
|
|
2656
|
-
* @example
|
|
2657
|
-
* ```ts
|
|
2658
|
-
* import { createWorkspaceManager } from '@src/core'
|
|
2659
|
-
*
|
|
2660
|
-
* const workspaces = createWorkspaceManager()
|
|
2661
|
-
* const scratch = workspaces.add() // auto-activates — workspaces.active === scratch
|
|
2662
|
-
* scratch.write('notes.txt', 'hello')
|
|
2663
|
-
* ```
|
|
2664
|
-
*/
|
|
2665
|
-
export declare function createWorkspaceManager(options?: WorkspaceManagerOptions): WorkspaceManagerInterface;
|
|
2666
|
-
|
|
2667
2353
|
/**
|
|
2668
2354
|
* A {@link ConversationStoreInterface} backed by one table of the `databases` layer — a
|
|
2669
2355
|
* conversation's durable state IS a row, so persistence reduces to keyed point-access (`get` / `set`
|
|
2670
2356
|
* / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`
|
|
2671
2357
|
* {@link import('./MemoryConversationStore.js').MemoryConversationStore}. The EXACT twin of
|
|
2672
|
-
* {@link import('
|
|
2358
|
+
* {@link import('@orkestrel/workspace').DatabaseWorkspaceStore}.
|
|
2673
2359
|
*
|
|
2674
2360
|
* @remarks
|
|
2675
2361
|
* The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
|
|
@@ -2677,7 +2363,7 @@ export declare function createWorkspaceManager(options?: WorkspaceManagerOptions
|
|
|
2677
2363
|
* IndexedDB backend swaps in WITHOUT touching the
|
|
2678
2364
|
* {@link import('../ConversationManager.js').ConversationManager} or the
|
|
2679
2365
|
* {@link import('../Conversation.js').Conversation} — the same seam as
|
|
2680
|
-
* {@link import('
|
|
2366
|
+
* {@link import('@orkestrel/workspace').DatabaseWorkspaceStore}. The
|
|
2681
2367
|
* driver defaults to memory ({@link import('../../factories.js').createDatabaseConversationStore}
|
|
2682
2368
|
* passes `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the
|
|
2683
2369
|
* durable plumbing by passing a JSON / SQLite / IndexedDB driver.
|
|
@@ -2730,96 +2416,6 @@ export declare class DatabaseConversationStore implements ConversationStoreInter
|
|
|
2730
2416
|
delete(id: string): Promise<void>;
|
|
2731
2417
|
}
|
|
2732
2418
|
|
|
2733
|
-
/**
|
|
2734
|
-
* A {@link WorkspaceStoreInterface} backed by one table of the `databases` layer — a workspace's
|
|
2735
|
-
* durable state IS a row, so persistence reduces to keyed point-access (`get` / `set` / `delete`)
|
|
2736
|
-
* over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`
|
|
2737
|
-
* {@link import('./MemoryWorkspaceStore.js').MemoryWorkspaceStore}.
|
|
2738
|
-
*
|
|
2739
|
-
* @remarks
|
|
2740
|
-
* The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
|
|
2741
|
-
* JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /
|
|
2742
|
-
* IndexedDB backend swaps in WITHOUT touching the
|
|
2743
|
-
* {@link import('../WorkspaceManager.js').WorkspaceManager} or the
|
|
2744
|
-
* {@link import('../Workspace.js').Workspace} — the same seam as
|
|
2745
|
-
* the analogous `DatabaseWorkflowStore` in `@orkestrel/workflow`. The
|
|
2746
|
-
* driver defaults to memory ({@link import('../../factories.js').createDatabaseWorkspaceStore}
|
|
2747
|
-
* passes `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the
|
|
2748
|
-
* durable plumbing by passing a JSON / SQLite / IndexedDB driver.
|
|
2749
|
-
*
|
|
2750
|
-
* The {@link WorkspaceSnapshot} is stored as ONE OPAQUE JSON COLUMN — the table is a row of
|
|
2751
|
-
* `{ id; snapshot }` ({@link WorkspaceSnapshotRow}), the snapshot the whole JSON blob (a `rawShape`
|
|
2752
|
-
* column the factory builds) — exactly as `DatabaseWorkflowStore` stores its snapshot. The snapshot
|
|
2753
|
-
* is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless AND
|
|
2754
|
-
* keeps the row type flat (`snapshot` reads back as `unknown`).
|
|
2755
|
-
*
|
|
2756
|
-
* - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes
|
|
2757
|
-
* the row `{ id: snapshot.id, snapshot }`.
|
|
2758
|
-
* - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
|
|
2759
|
-
* a {@link WorkspaceSnapshot} ({@link import('../../helpers.js').isWorkspaceSnapshot} — the AGENTS
|
|
2760
|
-
* §14 boundary narrow for an untrusted storage read), or `undefined` if none is stored.
|
|
2761
|
-
* - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
2762
|
-
*
|
|
2763
|
-
* UNLIKE a session store there is NO idle-TTL / eviction — a persisted workspace lives until an
|
|
2764
|
-
* explicit `delete`. The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the
|
|
2765
|
-
* §22 method bijection with {@link WorkspaceStoreInterface}). Hydration stays a caller concern: a
|
|
2766
|
-
* {@link import('../WorkspaceManager.js').WorkspaceManager} reads a snapshot back and rebuilds the
|
|
2767
|
-
* live workspace through the constructor `seed` (its `open` / `save`).
|
|
2768
|
-
*
|
|
2769
|
-
* @example
|
|
2770
|
-
* ```ts
|
|
2771
|
-
* import { createDatabaseWorkspaceStore, createMemoryDriver, createWorkspace } from '@src/core'
|
|
2772
|
-
*
|
|
2773
|
-
* const store = createDatabaseWorkspaceStore(createMemoryDriver()) // a durable driver swaps in here
|
|
2774
|
-
* const workspace = createWorkspace()
|
|
2775
|
-
* workspace.write('notes.txt', 'hello')
|
|
2776
|
-
* await store.set(workspace.snapshot()) // persist the workspace (one JSON column)
|
|
2777
|
-
* const snapshot = await store.get(workspace.id)
|
|
2778
|
-
* await store.delete(workspace.id) // drop it
|
|
2779
|
-
* ```
|
|
2780
|
-
*/
|
|
2781
|
-
export declare class DatabaseWorkspaceStore implements WorkspaceStoreInterface {
|
|
2782
|
-
#private;
|
|
2783
|
-
/**
|
|
2784
|
-
* Wrap a table as a workspace store.
|
|
2785
|
-
*
|
|
2786
|
-
* @param table - The {@link TableInterface} holding the snapshots — its row is the
|
|
2787
|
-
* {@link WorkspaceSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)
|
|
2788
|
-
*/
|
|
2789
|
-
constructor(table: TableInterface<WorkspaceSnapshotRow>);
|
|
2790
|
-
/** Resolve the persisted snapshot for `id`, narrowing the opaque JSON column back to a `WorkspaceSnapshot`. */
|
|
2791
|
-
get(id: string): Promise<WorkspaceSnapshot | undefined>;
|
|
2792
|
-
/** Insert or replace under the snapshot's OWN `id` (no separate id param) — the row is `{ id, snapshot }`. */
|
|
2793
|
-
set(snapshot: WorkspaceSnapshot): Promise<void>;
|
|
2794
|
-
/** Drop a snapshot by id; an absent id is a no-op (no throw). */
|
|
2795
|
-
delete(id: string): Promise<void>;
|
|
2796
|
-
}
|
|
2797
|
-
|
|
2798
|
-
/**
|
|
2799
|
-
* Compute the decoded byte length of a base64 string ARITHMETICALLY — the image-payload
|
|
2800
|
-
* sizing primitive {@link computeSize} uses, with no `atob` / `Buffer` decode.
|
|
2801
|
-
*
|
|
2802
|
-
* @remarks
|
|
2803
|
-
* A base64 string encodes each group of 3 input bytes as 4 characters, so a well-formed
|
|
2804
|
-
* string's length is a multiple of 4 and its decoded length is `(length / 4) * 3` MINUS
|
|
2805
|
-
* the trailing `=` padding (one `=` ⇒ the last group held 2 bytes, two `==` ⇒ 1 byte).
|
|
2806
|
-
* The padding is counted from the trailing `=` characters, so both the `=` and `==` cases
|
|
2807
|
-
* are handled. The empty string decodes to `0`. Total — never throws (a malformed,
|
|
2808
|
-
* non-multiple-of-4 length still yields a defined non-negative estimate via `floor`).
|
|
2809
|
-
*
|
|
2810
|
-
* @param base64 - The base64-encoded string (e.g. an image's `data`)
|
|
2811
|
-
* @returns The decoded payload's byte length
|
|
2812
|
-
*
|
|
2813
|
-
* @example
|
|
2814
|
-
* ```ts
|
|
2815
|
-
* decodedSize('') // 0
|
|
2816
|
-
* decodedSize('AAAA') // 3 (no padding)
|
|
2817
|
-
* decodedSize('AAA=') // 2 (one '=')
|
|
2818
|
-
* decodedSize('AA==') // 1 (two '=')
|
|
2819
|
-
* ```
|
|
2820
|
-
*/
|
|
2821
|
-
export declare function decodedSize(base64: string): number;
|
|
2822
|
-
|
|
2823
2419
|
/**
|
|
2824
2420
|
* The default cap on an {@link AgentInterface} turn's tool iterations — the maximum
|
|
2825
2421
|
* number of context → provider → tools cycles before the loop stops, so a model that
|
|
@@ -2847,28 +2443,6 @@ export declare const DEFAULT_AUTHORITY_ZONE = "default";
|
|
|
2847
2443
|
*/
|
|
2848
2444
|
export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
2849
2445
|
|
|
2850
|
-
/**
|
|
2851
|
-
* Escape a string's regex-special characters so it matches LITERALLY inside a `RegExp` — the
|
|
2852
|
-
* primitive a {@link import('./workspaces/Workspace.js').Workspace} search builds a literal-text
|
|
2853
|
-
* search pattern through (as opposed to a caller-supplied regex pattern).
|
|
2854
|
-
*
|
|
2855
|
-
* @remarks
|
|
2856
|
-
* Prefixes every character in the class `. * + ? ^ $ { } ( ) | [ ] \` with a backslash, so the
|
|
2857
|
-
* escaped string, when compiled into a `RegExp`, matches only its own literal characters — no
|
|
2858
|
-
* character acts as a quantifier, anchor, group, or class. Pure string assembly, total — never
|
|
2859
|
-
* throws.
|
|
2860
|
-
*
|
|
2861
|
-
* @param value - The text to escape for literal use inside a `RegExp` pattern
|
|
2862
|
-
* @returns `value` with every regex-special character backslash-escaped
|
|
2863
|
-
*
|
|
2864
|
-
* @example
|
|
2865
|
-
* ```ts
|
|
2866
|
-
* escapeRegExp('a.b*c') // 'a\\.b\\*c'
|
|
2867
|
-
* new RegExp(escapeRegExp('a.b*c')).test('a.b*c') // true
|
|
2868
|
-
* ```
|
|
2869
|
-
*/
|
|
2870
|
-
export declare function escapeRegExp(value: string): string;
|
|
2871
|
-
|
|
2872
2446
|
/**
|
|
2873
2447
|
* Estimate the context-token footprint of a batch of messages — the default `consume`
|
|
2874
2448
|
* estimator for an agent's context `BudgetInterface` (a budgets surface's tracking contract)
|
|
@@ -2923,13 +2497,6 @@ export declare function estimateMessages(messages: readonly MessageInterface[]):
|
|
|
2923
2497
|
*/
|
|
2924
2498
|
export declare function estimateTokens(text: string): number;
|
|
2925
2499
|
|
|
2926
|
-
/**
|
|
2927
|
-
* The extension→language table {@link import('./helpers.js').inferLanguage} reads to
|
|
2928
|
-
* map a file path's extension to a fenced-code language tag. Covers the common source /
|
|
2929
|
-
* markup / data extensions; an unlisted extension falls back to `'text'`.
|
|
2930
|
-
*/
|
|
2931
|
-
export declare const EXTENSION_TO_LANGUAGE: Readonly<Record<string, string>>;
|
|
2932
|
-
|
|
2933
2500
|
/**
|
|
2934
2501
|
* Render a path-addressed text body as a fenced reference block — the framing an
|
|
2935
2502
|
* {@link import('./AgentContext.js').AgentContext}'s ACTIVE-workspace text-file render emits (the
|
|
@@ -2940,7 +2507,7 @@ export declare const EXTENSION_TO_LANGUAGE: Readonly<Record<string, string>>;
|
|
|
2940
2507
|
* fenced code block tagged with `language`, the `content` verbatim inside. Pure string assembly,
|
|
2941
2508
|
* total — never throws. The one fenced-file format string for the whole module — `AgentContext.build()`
|
|
2942
2509
|
* frames an active workspace's text files with it (each carries its own `language` on its
|
|
2943
|
-
* {@link FileContent} text arm).
|
|
2510
|
+
* {@link import('@orkestrel/workspace').FileContent} text arm).
|
|
2944
2511
|
*
|
|
2945
2512
|
* @param path - The file path shown on the `File:` label line
|
|
2946
2513
|
* @param language - The fenced-code language tag (e.g. `'typescript'`)
|
|
@@ -2957,74 +2524,6 @@ export declare const EXTENSION_TO_LANGUAGE: Readonly<Record<string, string>>;
|
|
|
2957
2524
|
*/
|
|
2958
2525
|
export declare function fencedFile(path: string, language: string, content: string): string;
|
|
2959
2526
|
|
|
2960
|
-
/**
|
|
2961
|
-
* A {@link FileInterface}'s content — a TAGLESS union of a TEXT arm and a BINARY arm, narrowed
|
|
2962
|
-
* by the {@link import('./helpers.js').isText} / {@link import('./helpers.js').isBinary}
|
|
2963
|
-
* guards (AGENTS §14: an untyped arm is narrowed via a guard, never an `as`).
|
|
2964
|
-
*
|
|
2965
|
-
* @remarks
|
|
2966
|
-
* - The TEXT arm carries the literal `text` plus the fenced-code `language` it renders as.
|
|
2967
|
-
* - The BINARY arm carries the base64-encoded `data` plus the {@link BinaryMIME} that labels it.
|
|
2968
|
-
*
|
|
2969
|
-
* There is no `modality` discriminant — the arms are told apart structurally
|
|
2970
|
-
* (`'text' in content` vs `'data' in content`) by the guards. A binary arm whose `mime`
|
|
2971
|
-
* starts with `image/` IS an image ({@link import('./helpers.js').isImage}). A future
|
|
2972
|
-
* non-image binary (a PDF) is the same binary arm with a new {@link BinaryMIME} — additive,
|
|
2973
|
-
* with nothing above it changed.
|
|
2974
|
-
*/
|
|
2975
|
-
export declare type FileContent = {
|
|
2976
|
-
readonly text: string;
|
|
2977
|
-
readonly language: string;
|
|
2978
|
-
} | {
|
|
2979
|
-
readonly data: string;
|
|
2980
|
-
readonly mime: BinaryMIME;
|
|
2981
|
-
};
|
|
2982
|
-
|
|
2983
|
-
/**
|
|
2984
|
-
* The minimal data to author a {@link FileInterface} — `size` / `lines` are DERIVED from the
|
|
2985
|
-
* `content`, so a caller supplies only `path` / `content` (and an optional `state`, defaulting
|
|
2986
|
-
* to `'created'`).
|
|
2987
|
-
*/
|
|
2988
|
-
export declare interface FileInput {
|
|
2989
|
-
readonly path: string;
|
|
2990
|
-
readonly content: FileContent;
|
|
2991
|
-
/** The lifecycle state; defaults to `'created'` when omitted. */
|
|
2992
|
-
readonly state?: FileState;
|
|
2993
|
-
}
|
|
2994
|
-
|
|
2995
|
-
/**
|
|
2996
|
-
* An immutable file value object — a `path`-addressed {@link FileContent} carrying a
|
|
2997
|
-
* lifecycle {@link FileState}, with `size` / `lines` DERIVED once when built.
|
|
2998
|
-
*
|
|
2999
|
-
* @remarks
|
|
3000
|
-
* A PLAIN frozen record (not a class instance) produced by
|
|
3001
|
-
* {@link import('./factories.js').createFile} — the `path` IS its identity (there is no
|
|
3002
|
-
* `id`). `size` and `lines` are computed from `content` when built (so they can never drift
|
|
3003
|
-
* from it) and re-read for free thereafter. Never mutated — a Workspace REPLACES a file
|
|
3004
|
-
* rather than editing it in place. A DATA-ONLY value object — no methods, plus it
|
|
3005
|
-
* `structuredClone`s losslessly (every field is a plain primitive / record).
|
|
3006
|
-
*/
|
|
3007
|
-
export declare interface FileInterface {
|
|
3008
|
-
readonly path: string;
|
|
3009
|
-
readonly content: FileContent;
|
|
3010
|
-
readonly state: FileState;
|
|
3011
|
-
/** Derived byte size: UTF-8 byte length (text) / decoded payload bytes (binary). */
|
|
3012
|
-
readonly size: number;
|
|
3013
|
-
/** Derived line count: the text line count; `0` for a binary arm. */
|
|
3014
|
-
readonly lines: number;
|
|
3015
|
-
}
|
|
3016
|
-
|
|
3017
|
-
/**
|
|
3018
|
-
* The lifecycle state of a {@link FileInterface} relative to its (future) durable backing
|
|
3019
|
-
* — a multi-value lifecycle union (AGENTS §10), not a boolean.
|
|
3020
|
-
*
|
|
3021
|
-
* @remarks
|
|
3022
|
-
* `'created'` is a brand-new file not yet persisted; `'modified'` has unsaved edits over a
|
|
3023
|
-
* persisted original; `'loaded'` was read from the backing and is unchanged; `'deleted'`
|
|
3024
|
-
* is tombstoned. A `File` authored without a `state` defaults to `'created'`.
|
|
3025
|
-
*/
|
|
3026
|
-
export declare type FileState = 'created' | 'modified' | 'loaded' | 'deleted';
|
|
3027
|
-
|
|
3028
2527
|
/**
|
|
3029
2528
|
* Filter a list of items by a {@link import('./types.js').ScopeInterface} allow-list of
|
|
3030
2529
|
* keys — the pure, total set-membership primitive the context's build step and the agent
|
|
@@ -3096,34 +2595,13 @@ export declare function handleAgentRunnerJob(registry: AgentRegistryInterface, a
|
|
|
3096
2595
|
*/
|
|
3097
2596
|
export declare const IMAGE_TOKEN_ESTIMATE = 512;
|
|
3098
2597
|
|
|
3099
|
-
/**
|
|
3100
|
-
* Infer a fenced-code language tag from a file path's extension — what a workspace text file
|
|
3101
|
-
* (or the {@link fencedFile} renderer) renders its content block as.
|
|
3102
|
-
*
|
|
3103
|
-
* @remarks
|
|
3104
|
-
* Reads the extension after the last `.` (case-insensitive) and maps it through a
|
|
3105
|
-
* fixed extension→language table. An unknown extension, or a path with no extension,
|
|
3106
|
-
* falls back to `'text'` (a safe, language-agnostic fence). Total — never throws.
|
|
3107
|
-
*
|
|
3108
|
-
* @param path - The document's file path (e.g. `'src/main.ts'`)
|
|
3109
|
-
* @returns The inferred language tag (e.g. `'typescript'`), or `'text'` when unknown
|
|
3110
|
-
*
|
|
3111
|
-
* @example
|
|
3112
|
-
* ```ts
|
|
3113
|
-
* inferLanguage('src/main.ts') // 'typescript'
|
|
3114
|
-
* inferLanguage('README.md') // 'markdown'
|
|
3115
|
-
* inferLanguage('LICENSE') // 'text'
|
|
3116
|
-
* ```
|
|
3117
|
-
*/
|
|
3118
|
-
export declare function inferLanguage(path: string): string;
|
|
3119
|
-
|
|
3120
2598
|
/**
|
|
3121
2599
|
* An immutable named directive — a {@link InstructionInterface} assembled once from its
|
|
3122
2600
|
* input (`name` / `content`, an optional `priority` defaulting to `0`), the `id` minted
|
|
3123
2601
|
* at construction.
|
|
3124
2602
|
*
|
|
3125
2603
|
* @remarks
|
|
3126
|
-
* A thin immutable value object (mirroring {@link import('
|
|
2604
|
+
* A thin immutable value object (mirroring {@link import('@orkestrel/tool').Tool}): the
|
|
3127
2605
|
* constructor mints a fresh `id` (`crypto.randomUUID()`), copies the input's `name` /
|
|
3128
2606
|
* `content`, resolves `priority` to the input's value or `0`, and carries the input's
|
|
3129
2607
|
* per-item `format` override ONLY when supplied (assigned just when present, mirroring a
|
|
@@ -3363,32 +2841,10 @@ export declare function isAgentError(value: unknown): value is AgentError;
|
|
|
3363
2841
|
export declare function isAgentJobError(value: unknown): value is AgentJobError;
|
|
3364
2842
|
|
|
3365
2843
|
/**
|
|
3366
|
-
*
|
|
3367
|
-
* union (AGENTS §14: narrow an untyped arm via a guard, never an `as`).
|
|
3368
|
-
*
|
|
3369
|
-
* @remarks
|
|
3370
|
-
* Tests `'data' in content` structurally — there is no `modality` discriminant. A `true`
|
|
3371
|
-
* narrows `content` to `{ data: string; mime: BinaryMIME }`, unlocking `.data` / `.mime`. An
|
|
3372
|
-
* image is a binary whose `mime` starts with `image/` ({@link isImage}). Total — never throws.
|
|
2844
|
+
* Narrow an unknown caught value to a {@link ConversationError}.
|
|
3373
2845
|
*
|
|
3374
|
-
* @param
|
|
3375
|
-
* @returns `true` when `
|
|
3376
|
-
*
|
|
3377
|
-
* @example
|
|
3378
|
-
* ```ts
|
|
3379
|
-
* if (isBinary(file.content)) file.content.data // the base64 payload + .mime
|
|
3380
|
-
* ```
|
|
3381
|
-
*/
|
|
3382
|
-
export declare function isBinary(content: FileContent): content is {
|
|
3383
|
-
readonly data: string;
|
|
3384
|
-
readonly mime: BinaryMIME;
|
|
3385
|
-
};
|
|
3386
|
-
|
|
3387
|
-
/**
|
|
3388
|
-
* Narrow an unknown caught value to a {@link ConversationError}.
|
|
3389
|
-
*
|
|
3390
|
-
* @param value - The value to test (typically a `catch` binding)
|
|
3391
|
-
* @returns `true` when `value` is a {@link ConversationError}
|
|
2846
|
+
* @param value - The value to test (typically a `catch` binding)
|
|
2847
|
+
* @returns `true` when `value` is a {@link ConversationError}
|
|
3392
2848
|
*
|
|
3393
2849
|
* @example
|
|
3394
2850
|
* ```ts
|
|
@@ -3406,7 +2862,7 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
3406
2862
|
* UNTRUSTED snapshot read (a storage row a
|
|
3407
2863
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
3408
2864
|
* reads back from its opaque JSON column, a snapshot loaded from disk). The EXACT analogue of
|
|
3409
|
-
* {@link isWorkspaceSnapshot}.
|
|
2865
|
+
* {@link import('@orkestrel/workspace').isWorkspaceSnapshot}.
|
|
3410
2866
|
*
|
|
3411
2867
|
* @remarks
|
|
3412
2868
|
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the snapshot's
|
|
@@ -3415,7 +2871,7 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
3415
2871
|
* {@link SectionInterface} ({@link isSection}), and a `messages` array EVERY element of which is a
|
|
3416
2872
|
* valid {@link MessageInterface} ({@link isMessage}) — enough to safely impose the
|
|
3417
2873
|
* {@link ConversationSnapshot} type at a storage boundary WITHOUT a cast. The structural twin of
|
|
3418
|
-
* {@link isWorkspaceSnapshot}. A malformed blob (a non-record, a missing / non-string `id`, a
|
|
2874
|
+
* {@link import('@orkestrel/workspace').isWorkspaceSnapshot}. A malformed blob (a non-record, a missing / non-string `id`, a
|
|
3419
2875
|
* non-string `summary` when present, a non-array `sections` / `messages`, or any malformed
|
|
3420
2876
|
* element) resolves `false`, so a
|
|
3421
2877
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
@@ -3434,68 +2890,23 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
3434
2890
|
*/
|
|
3435
2891
|
export declare function isConversationSnapshot(value: unknown): value is ConversationSnapshot;
|
|
3436
2892
|
|
|
3437
|
-
/**
|
|
3438
|
-
* Whether an `unknown` is structurally a {@link FileInterface} record — the per-file step of the
|
|
3439
|
-
* {@link isWorkspaceSnapshot} read-boundary narrow (AGENTS §14: narrow an untrusted storage read
|
|
3440
|
-
* via a guard, never an `as`).
|
|
3441
|
-
*
|
|
3442
|
-
* @remarks
|
|
3443
|
-
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the file's SHAPE:
|
|
3444
|
-
* a record with a `string` `path`, a `string` `state`, `number` `size` / `lines`, and a `content`
|
|
3445
|
-
* that is EITHER the TEXT arm (`{ text: string; language: string }`) OR the BINARY arm
|
|
3446
|
-
* (`{ data: string; mime: string }`) — the tagless {@link FileContent} union, told apart
|
|
3447
|
-
* structurally exactly as {@link isText} / {@link isBinary} do (no `modality` discriminant). Enough
|
|
3448
|
-
* to safely impose the {@link FileInterface} type at a storage boundary WITHOUT a cast; the `mime`
|
|
3449
|
-
* is left as a broad `string` here (an open {@link BinaryMIME}, so any storage-read MIME string is
|
|
3450
|
-
* accepted defensively rather than rejected against the current literal set).
|
|
3451
|
-
*
|
|
3452
|
-
* @param value - The value to test (one element of a snapshot's opaque `files` array)
|
|
3453
|
-
* @returns `true` when `value` has the structural shape of a {@link FileInterface}
|
|
3454
|
-
*
|
|
3455
|
-
* @example
|
|
3456
|
-
* ```ts
|
|
3457
|
-
* isFile({ path: 'a.ts', content: { text: 'x', language: 'typescript' }, state: 'created', size: 1, lines: 1 }) // true
|
|
3458
|
-
* isFile({ path: 'a.png', content: { data: 'AAAA', mime: 'image/png' }, state: 'created', size: 3, lines: 0 }) // true
|
|
3459
|
-
* isFile({ path: 'a.ts' }) // false (missing content / state / size / lines)
|
|
3460
|
-
* ```
|
|
3461
|
-
*/
|
|
3462
|
-
export declare function isFile(value: unknown): value is FileInterface;
|
|
3463
|
-
|
|
3464
|
-
/**
|
|
3465
|
-
* Whether a {@link FileContent} is an IMAGE — a {@link isBinary} arm whose `mime` is an
|
|
3466
|
-
* `image/*` type (an image is just a binary with an image MIME).
|
|
3467
|
-
*
|
|
3468
|
-
* @remarks
|
|
3469
|
-
* Narrows to the binary arm first, then checks the `image/` MIME prefix — so a future
|
|
3470
|
-
* non-image binary (a PDF, `'application/pdf'`) is binary but NOT an image. Total — never
|
|
3471
|
-
* throws.
|
|
3472
|
-
*
|
|
3473
|
-
* @param content - The file content to test
|
|
3474
|
-
* @returns `true` when `content` is a binary arm with an `image/*` MIME
|
|
3475
|
-
*
|
|
3476
|
-
* @example
|
|
3477
|
-
* ```ts
|
|
3478
|
-
* isImage({ data: '<base64>', mime: 'image/png' }) // true
|
|
3479
|
-
* isImage({ text: 'hi', language: 'text' }) // false
|
|
3480
|
-
* ```
|
|
3481
|
-
*/
|
|
3482
|
-
export declare function isImage(content: FileContent): boolean;
|
|
3483
|
-
|
|
3484
2893
|
/**
|
|
3485
2894
|
* Whether an `unknown` is structurally a {@link MessageInterface} record — the per-message step of
|
|
3486
2895
|
* the {@link isConversationSnapshot} read-boundary narrow (AGENTS §14: narrow an untrusted storage
|
|
3487
|
-
* read via a guard, never an `as`). The conversation analogue of
|
|
2896
|
+
* read via a guard, never an `as`). The conversation analogue of
|
|
2897
|
+
* {@link import('@orkestrel/workspace').isFile}.
|
|
3488
2898
|
*
|
|
3489
2899
|
* @remarks
|
|
3490
2900
|
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the message's
|
|
3491
2901
|
* SHAPE: a record with a `string` `id`, a `string` `role`, a `string` `content`, and — WHEN present
|
|
3492
|
-
* — a `calls` array EVERY element of which is a valid
|
|
2902
|
+
* — a `calls` array EVERY element of which is a valid
|
|
2903
|
+
* {@link import('@orkestrel/tool').ToolCall} ({@link isToolCall} — the
|
|
3493
2904
|
* ASI06 fail-closed deepening: a tampered `calls` element rejects the message, so the snapshot
|
|
3494
2905
|
* reads back as absent rather than replaying a malformed call) and an `images` that is an array
|
|
3495
2906
|
* (an absent optional passes). The `role` is left as a broad `string` here (an open
|
|
3496
2907
|
* {@link import('./types.js').MessageRole}, so any storage-read role string is accepted
|
|
3497
|
-
* defensively rather than rejected against the current literal set)
|
|
3498
|
-
*
|
|
2908
|
+
* defensively rather than rejected against the current literal set). Enough to safely impose the
|
|
2909
|
+
* {@link MessageInterface} type at
|
|
3499
2910
|
* a storage boundary WITHOUT a cast.
|
|
3500
2911
|
*
|
|
3501
2912
|
* @param value - The value to test (one element of a snapshot's `messages` / a section's `messages`)
|
|
@@ -3551,132 +2962,16 @@ export declare function isProviderAbortError(value: unknown): value is ProviderA
|
|
|
3551
2962
|
*/
|
|
3552
2963
|
export declare function isSection(value: unknown): value is SectionInterface;
|
|
3553
2964
|
|
|
3554
|
-
/**
|
|
3555
|
-
* Whether a {@link FileContent} is the TEXT arm — the narrowing guard for the text-vs-binary
|
|
3556
|
-
* union (AGENTS §14: narrow an untyped arm via a guard, never an `as`).
|
|
3557
|
-
*
|
|
3558
|
-
* @remarks
|
|
3559
|
-
* Tests `'text' in content` structurally — there is no `modality` discriminant. A `true`
|
|
3560
|
-
* narrows `content` to `{ text: string; language: string }`, unlocking `.text` / `.language`.
|
|
3561
|
-
* Total — never throws.
|
|
3562
|
-
*
|
|
3563
|
-
* @param content - The file content to test
|
|
3564
|
-
* @returns `true` when `content` is the text arm (carries `text` + `language`)
|
|
3565
|
-
*
|
|
3566
|
-
* @example
|
|
3567
|
-
* ```ts
|
|
3568
|
-
* if (isText(file.content)) file.content.text // the literal text + .language
|
|
3569
|
-
* ```
|
|
3570
|
-
*/
|
|
3571
|
-
export declare function isText(content: FileContent): content is {
|
|
3572
|
-
readonly text: string;
|
|
3573
|
-
readonly language: string;
|
|
3574
|
-
};
|
|
3575
|
-
|
|
3576
|
-
/**
|
|
3577
|
-
* Whether an `unknown` is structurally a {@link ToolCall} record — the per-call step of the
|
|
3578
|
-
* {@link isMessage} read-boundary narrow (AGENTS §14: narrow an untrusted storage read via a
|
|
3579
|
-
* guard, never an `as`).
|
|
3580
|
-
*
|
|
3581
|
-
* @remarks
|
|
3582
|
-
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the call's
|
|
3583
|
-
* SHAPE: a record with a `string` `id`, a `string` `name`, and a record `arguments` — the real
|
|
3584
|
-
* {@link ToolCall} shape a restored assistant turn replays to a provider. This is the ASI06
|
|
3585
|
-
* fail-CLOSED element check: a tampered persisted call (`null`, a bare string, a non-record
|
|
3586
|
-
* `arguments`) fails the guard, so {@link isMessage} — and through it
|
|
3587
|
-
* {@link isConversationSnapshot} — rejects the whole snapshot and a poisoned store row reads
|
|
3588
|
-
* back as ABSENT instead of replaying a malformed call into a chat template.
|
|
3589
|
-
*
|
|
3590
|
-
* @param value - The value to test (one element of an assistant message's `calls`)
|
|
3591
|
-
* @returns `true` when `value` has the structural shape of a {@link ToolCall}
|
|
3592
|
-
*
|
|
3593
|
-
* @example
|
|
3594
|
-
* ```ts
|
|
3595
|
-
* isToolCall({ id: 'c1', name: 'search', arguments: { q: 'acme' } }) // true
|
|
3596
|
-
* isToolCall({ id: 'c1', name: 'search' }) // false (missing arguments)
|
|
3597
|
-
* isToolCall({ id: 'c1', name: 123, arguments: {} }) // false (non-string name)
|
|
3598
|
-
* ```
|
|
3599
|
-
*/
|
|
3600
|
-
export declare function isToolCall(value: unknown): value is ToolCall;
|
|
3601
|
-
|
|
3602
|
-
/**
|
|
3603
|
-
* Whether a {@link Range} is STRUCTURALLY valid — the predicate a ranged `write` checks
|
|
3604
|
-
* before applying (a `false` here is the `RANGE` throw).
|
|
3605
|
-
*
|
|
3606
|
-
* @remarks
|
|
3607
|
-
* Structural validity is independent of any content: every component must be `>= 1`
|
|
3608
|
-
* (1-based lines and columns), and `start` must not come after `end` (an inverted range
|
|
3609
|
-
* is invalid). A range that is structurally valid but reaches PAST the end of a specific
|
|
3610
|
-
* text is still valid — it is {@link clampRange}d to the bounds when applied, not rejected.
|
|
3611
|
-
* Total — never throws.
|
|
3612
|
-
*
|
|
3613
|
-
* @param range - The range to validate
|
|
3614
|
-
* @returns `true` when every component is `>= 1` and `start` is at or before `end`
|
|
3615
|
-
*
|
|
3616
|
-
* @example
|
|
3617
|
-
* ```ts
|
|
3618
|
-
* isValidRange({ start: { line: 1, column: 1 }, end: { line: 2, column: 1 } }) // true
|
|
3619
|
-
* isValidRange({ start: { line: 2, column: 1 }, end: { line: 1, column: 1 } }) // false (inverted)
|
|
3620
|
-
* isValidRange({ start: { line: 0, column: 1 }, end: { line: 1, column: 1 } }) // false (sub-1 line)
|
|
3621
|
-
* ```
|
|
3622
|
-
*/
|
|
3623
|
-
export declare function isValidRange(range: Range): boolean;
|
|
3624
|
-
|
|
3625
|
-
/**
|
|
3626
|
-
* Narrow an unknown caught value to a {@link WorkspaceError}.
|
|
3627
|
-
*
|
|
3628
|
-
* @param value - The value to test (typically a `catch` binding)
|
|
3629
|
-
* @returns `true` when `value` is a {@link WorkspaceError}
|
|
3630
|
-
*
|
|
3631
|
-
* @example
|
|
3632
|
-
* ```ts
|
|
3633
|
-
* try {
|
|
3634
|
-
* workspace.prepend('icon.png', '// header')
|
|
3635
|
-
* } catch (error) {
|
|
3636
|
-
* if (isWorkspaceError(error) && error.code === 'MODALITY') skipBinary()
|
|
3637
|
-
* }
|
|
3638
|
-
* ```
|
|
3639
|
-
*/
|
|
3640
|
-
export declare function isWorkspaceError(value: unknown): value is WorkspaceError;
|
|
3641
|
-
|
|
3642
|
-
/**
|
|
3643
|
-
* Narrow an `unknown` to a {@link WorkspaceSnapshot} — the AGENTS §14 boundary guard for an
|
|
3644
|
-
* UNTRUSTED snapshot read (a storage row a
|
|
3645
|
-
* {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} reads back
|
|
3646
|
-
* from its opaque JSON column, a snapshot loaded from disk).
|
|
3647
|
-
*
|
|
3648
|
-
* @remarks
|
|
3649
|
-
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the snapshot's
|
|
3650
|
-
* SHAPE: a `string` `id` and a `files` array EVERY element of which is a valid {@link FileInterface}
|
|
3651
|
-
* record ({@link isFile}) — enough to safely impose the {@link WorkspaceSnapshot} type at a storage
|
|
3652
|
-
* boundary WITHOUT a cast. The structural twin of
|
|
3653
|
-
* the analogous `isWorkflowSnapshot` in `@orkestrel/workflow`. A malformed blob (a non-record, a
|
|
3654
|
-
* missing / non-string `id`, a non-array `files`, or any malformed file element) resolves `false`,
|
|
3655
|
-
* so a {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} read
|
|
3656
|
-
* yields `undefined` rather than a broken workspace.
|
|
3657
|
-
*
|
|
3658
|
-
* @param value - The value to test (an opaque storage read)
|
|
3659
|
-
* @returns `true` when `value` has the structural shape of a {@link WorkspaceSnapshot}
|
|
3660
|
-
*
|
|
3661
|
-
* @example
|
|
3662
|
-
* ```ts
|
|
3663
|
-
* isWorkspaceSnapshot({ id: 'w1', files: [] }) // true
|
|
3664
|
-
* isWorkspaceSnapshot({ id: 'w1', files: 'nope' }) // false
|
|
3665
|
-
* isWorkspaceSnapshot({ files: [] }) // false (missing id)
|
|
3666
|
-
* ```
|
|
3667
|
-
*/
|
|
3668
|
-
export declare function isWorkspaceSnapshot(value: unknown): value is WorkspaceSnapshot;
|
|
3669
|
-
|
|
3670
2965
|
/**
|
|
3671
2966
|
* The in-memory {@link ConversationStoreInterface} — a process-lifetime `Map` of
|
|
3672
2967
|
* {@link ConversationSnapshot}s keyed by conversation id, the DEFAULT store
|
|
3673
2968
|
* {@link import('../../factories.js').createMemoryConversationStore} builds. The EXACT twin of
|
|
3674
|
-
* {@link import('
|
|
2969
|
+
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore}.
|
|
3675
2970
|
*
|
|
3676
2971
|
* @remarks
|
|
3677
2972
|
* A plain `Map<string, ConversationSnapshot>` (AGENTS §21 — the snapshot is already pure,
|
|
3678
2973
|
* self-contained JSON, so no encoding is needed for the memory tier). Like the
|
|
3679
|
-
* {@link import('
|
|
2974
|
+
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore} it twins,
|
|
3680
2975
|
* there is NO idle-TTL and NO eviction: a persisted conversation lives until an explicit `delete`. A
|
|
3681
2976
|
* durable backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching
|
|
3682
2977
|
* the {@link import('../ConversationManager.js').ConversationManager} or the
|
|
@@ -3712,50 +3007,6 @@ export declare class MemoryConversationStore implements ConversationStoreInterfa
|
|
|
3712
3007
|
delete(id: string): Promise<void>;
|
|
3713
3008
|
}
|
|
3714
3009
|
|
|
3715
|
-
/**
|
|
3716
|
-
* The in-memory {@link WorkspaceStoreInterface} — a process-lifetime `Map` of
|
|
3717
|
-
* {@link WorkspaceSnapshot}s keyed by workspace id, the DEFAULT store
|
|
3718
|
-
* {@link import('../../factories.js').createMemoryWorkspaceStore} builds.
|
|
3719
|
-
*
|
|
3720
|
-
* @remarks
|
|
3721
|
-
* A plain `Map<string, WorkspaceSnapshot>` (AGENTS §21 — the snapshot is already pure,
|
|
3722
|
-
* self-contained JSON, so no encoding is needed for the memory tier). Like the
|
|
3723
|
-
* the analogous `MemoryWorkflowStore` in `@orkestrel/workflow` it twins,
|
|
3724
|
-
* there is NO idle-TTL and NO eviction: a persisted workspace lives until an explicit `delete`. A
|
|
3725
|
-
* durable backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching
|
|
3726
|
-
* the {@link import('../WorkspaceManager.js').WorkspaceManager} or the
|
|
3727
|
-
* {@link import('../Workspace.js').Workspace} — its driver-pluggable twin is
|
|
3728
|
-
* {@link import('./DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} (the snapshot as one opaque
|
|
3729
|
-
* JSON column).
|
|
3730
|
-
*
|
|
3731
|
-
* - **`get` resolves the persisted snapshot for an id**, or `undefined` if none is stored.
|
|
3732
|
-
* - **`set` inserts / replaces under the snapshot's OWN `id`** (no separate id param).
|
|
3733
|
-
* - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
3734
|
-
*
|
|
3735
|
-
* The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the §22 method
|
|
3736
|
-
* bijection with {@link WorkspaceStoreInterface}). Hydration is a caller concern: a
|
|
3737
|
-
* {@link import('../WorkspaceManager.js').WorkspaceManager} reads a snapshot back and rebuilds the
|
|
3738
|
-
* live workspace through the constructor `seed` (its `open` / `save`).
|
|
3739
|
-
*
|
|
3740
|
-
* @example
|
|
3741
|
-
* ```ts
|
|
3742
|
-
* import { createMemoryWorkspaceStore, createWorkspace } from '@src/core'
|
|
3743
|
-
*
|
|
3744
|
-
* const store = createMemoryWorkspaceStore()
|
|
3745
|
-
* const workspace = createWorkspace()
|
|
3746
|
-
* workspace.write('notes.txt', 'hello')
|
|
3747
|
-
* await store.set(workspace.snapshot()) // persist the workspace
|
|
3748
|
-
* const snapshot = await store.get(workspace.id)
|
|
3749
|
-
* await store.delete(workspace.id) // drop it
|
|
3750
|
-
* ```
|
|
3751
|
-
*/
|
|
3752
|
-
export declare class MemoryWorkspaceStore implements WorkspaceStoreInterface {
|
|
3753
|
-
#private;
|
|
3754
|
-
get(id: string): Promise<WorkspaceSnapshot | undefined>;
|
|
3755
|
-
set(snapshot: WorkspaceSnapshot): Promise<void>;
|
|
3756
|
-
delete(id: string): Promise<void>;
|
|
3757
|
-
}
|
|
3758
|
-
|
|
3759
3010
|
/**
|
|
3760
3011
|
* The estimated per-message role/framing overhead {@link import('./helpers.js').estimateMessages}
|
|
3761
3012
|
* adds on top of a message's content estimate — accounts for the fixed wire framing every
|
|
@@ -3833,42 +3084,6 @@ export declare interface MessageManagerInterface {
|
|
|
3833
3084
|
/** The role a {@link MessageInterface} plays in a conversation turn. */
|
|
3834
3085
|
export declare type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
3835
3086
|
|
|
3836
|
-
/**
|
|
3837
|
-
* Convert a 1-based {@link Position} to a 0-based string offset into `text` — the indexing
|
|
3838
|
-
* primitive {@link sliceRange} / {@link spliceRange} use, clamped to `text.length`.
|
|
3839
|
-
*
|
|
3840
|
-
* @remarks
|
|
3841
|
-
* Sums each preceding line's length plus its `\n` separator, then adds the `column - 1`
|
|
3842
|
-
* within the target line, capped at `text.length`. Total — never throws (an out-of-bounds
|
|
3843
|
-
* position yields a defined in-range offset).
|
|
3844
|
-
*
|
|
3845
|
-
* @param text - The text to index into
|
|
3846
|
-
* @param position - The 1-based position to resolve
|
|
3847
|
-
* @returns The 0-based offset (in `[0, text.length]`)
|
|
3848
|
-
*
|
|
3849
|
-
* @example
|
|
3850
|
-
* ```ts
|
|
3851
|
-
* offsetAt('ab\ncd', { line: 2, column: 1 }) // 3 (just after 'ab\n')
|
|
3852
|
-
* ```
|
|
3853
|
-
*/
|
|
3854
|
-
export declare function offsetAt(text: string, position: Position): number;
|
|
3855
|
-
|
|
3856
|
-
/**
|
|
3857
|
-
* A 1-based caret position inside a text file — `line` and `column` both count from `1`
|
|
3858
|
-
* (column `1` is the first character of the line), matching an editor's gutter.
|
|
3859
|
-
*
|
|
3860
|
-
* @remarks
|
|
3861
|
-
* The {@link import('./workspaces/Workspace.js').Workspace} edit surface speaks 1-based
|
|
3862
|
-
* positions end to end ({@link Range}, {@link ReadResult}, {@link SearchMatch}). A
|
|
3863
|
-
* structurally invalid component (`line < 1` or `column < 1`) is rejected by a range op
|
|
3864
|
-
* (`RANGE`); an in-bounds-but-past-the-end one is CLAMPED to the nearest valid caret rather
|
|
3865
|
-
* than rejected.
|
|
3866
|
-
*/
|
|
3867
|
-
export declare interface Position {
|
|
3868
|
-
readonly line: number;
|
|
3869
|
-
readonly column: number;
|
|
3870
|
-
}
|
|
3871
|
-
|
|
3872
3087
|
/**
|
|
3873
3088
|
* Thrown by a {@link ProviderInterface}'s `stream` when its bound signal aborts
|
|
3874
3089
|
* mid-flight — carries the {@link ProviderResult} assembled from whatever streamed
|
|
@@ -3933,7 +3148,7 @@ export declare interface ProviderInterface {
|
|
|
3933
3148
|
* built-in framing, beaten by a manager-options or per-item override). Omitted ⇒ the
|
|
3934
3149
|
* provider is framing-agnostic and the managers' built-in defaults apply unchanged.
|
|
3935
3150
|
*/
|
|
3936
|
-
readonly format?: ContextFormatInterface;
|
|
3151
|
+
readonly format?: ContextFormatInterface | undefined;
|
|
3937
3152
|
/**
|
|
3938
3153
|
* Generate one complete turn — resolves the assembled {@link ProviderResult}.
|
|
3939
3154
|
*
|
|
@@ -4011,87 +3226,6 @@ export declare interface ProviderStreamOptions {
|
|
|
4011
3226
|
readonly schema?: Readonly<Record<string, unknown>>;
|
|
4012
3227
|
}
|
|
4013
3228
|
|
|
4014
|
-
/**
|
|
4015
|
-
* A half-open span of text between two {@link Position}s — `start` INCLUSIVE, `end`
|
|
4016
|
-
* EXCLUSIVE (the character at `end` is not part of the span).
|
|
4017
|
-
*
|
|
4018
|
-
* @remarks
|
|
4019
|
-
* A range whose `start` is at or before its `end` is valid; an inverted range
|
|
4020
|
-
* (`start` after `end`) or one with a sub-1 component is structurally invalid and a range
|
|
4021
|
-
* op throws `RANGE`. Each in-bounds component is clamped to the text before it is applied,
|
|
4022
|
-
* so a range reaching past the end of the content reads / splices up to the end.
|
|
4023
|
-
*/
|
|
4024
|
-
export declare interface Range {
|
|
4025
|
-
readonly start: Position;
|
|
4026
|
-
readonly end: Position;
|
|
4027
|
-
}
|
|
4028
|
-
|
|
4029
|
-
/**
|
|
4030
|
-
* Assemble a 1-based nested {@link Range} from four FLAT caret integers — the bridge a
|
|
4031
|
-
* workspace-editing tool (see `@orkestrel/tool`) uses from its small-model FLAT surface back to the
|
|
4032
|
-
* nested {@link Range} the {@link import('./workspaces/Workspace.js').Workspace} edit surface
|
|
4033
|
-
* speaks. Published as a public helper for that consumer.
|
|
4034
|
-
*
|
|
4035
|
-
* @remarks
|
|
4036
|
-
* Pairs `(fromLine, fromColumn)` into `start` and `(toLine, toColumn)` into `end` verbatim — a pure
|
|
4037
|
-
* structural lift, no validation (a structurally invalid range is rejected downstream by the ranged
|
|
4038
|
-
* `write` it feeds, via {@link isValidRange}). Total — never throws. Zero-Node.
|
|
4039
|
-
*
|
|
4040
|
-
* @param fromLine - The 1-based start line
|
|
4041
|
-
* @param fromColumn - The 1-based start column
|
|
4042
|
-
* @param toLine - The 1-based end line
|
|
4043
|
-
* @param toColumn - The 1-based end column
|
|
4044
|
-
* @returns The `{ start, end }` {@link Range}
|
|
4045
|
-
*
|
|
4046
|
-
* @example
|
|
4047
|
-
* ```ts
|
|
4048
|
-
* rangeOf(1, 11, 1, 12) // { start: { line: 1, column: 11 }, end: { line: 1, column: 12 } }
|
|
4049
|
-
* ```
|
|
4050
|
-
*/
|
|
4051
|
-
export declare function rangeOf(fromLine: number, fromColumn: number, toLine: number, toColumn: number): Range;
|
|
4052
|
-
|
|
4053
|
-
/**
|
|
4054
|
-
* The outcome of a ranged {@link WorkspaceInterface.read} — the sliced `content` plus the
|
|
4055
|
-
* `range` actually applied after clamping (so a caller learns the real span it got).
|
|
4056
|
-
*
|
|
4057
|
-
* @remarks
|
|
4058
|
-
* `range` is the input {@link Range} CLAMPED to the file's bounds — when the requested
|
|
4059
|
-
* span reached past the end of the text, `range` reflects the trimmed span that was read,
|
|
4060
|
-
* never the original out-of-bounds request.
|
|
4061
|
-
*/
|
|
4062
|
-
export declare interface ReadResult {
|
|
4063
|
-
readonly content: string;
|
|
4064
|
-
/** The actual (clamped) range applied to produce `content`. */
|
|
4065
|
-
readonly range: Range;
|
|
4066
|
-
}
|
|
4067
|
-
|
|
4068
|
-
/**
|
|
4069
|
-
* Options for {@link WorkspaceInterface.replace} — how the `query` matches (the same axes
|
|
4070
|
-
* as {@link SearchOptions}).
|
|
4071
|
-
*
|
|
4072
|
-
* @param options - The replace options
|
|
4073
|
-
*
|
|
4074
|
-
* @remarks
|
|
4075
|
-
* - `regex` — treat `query` as a regular expression source rather than a literal substring; defaults to `false`.
|
|
4076
|
-
* - `exact` — match case-sensitively; defaults to `true`.
|
|
4077
|
-
* - `limit` — stop after this many replacements across all files; defaults to unlimited.
|
|
4078
|
-
*/
|
|
4079
|
-
export declare interface ReplaceOptions {
|
|
4080
|
-
readonly regex?: boolean;
|
|
4081
|
-
readonly exact?: boolean;
|
|
4082
|
-
readonly limit?: number;
|
|
4083
|
-
}
|
|
4084
|
-
|
|
4085
|
-
/**
|
|
4086
|
-
* The tally returned by {@link WorkspaceInterface.replace} — the `query` that ran, how
|
|
4087
|
-
* many occurrences were `replaced`, and the number of `files` changed.
|
|
4088
|
-
*/
|
|
4089
|
-
export declare interface ReplaceResult {
|
|
4090
|
-
readonly query: string;
|
|
4091
|
-
readonly replaced: number;
|
|
4092
|
-
readonly files: number;
|
|
4093
|
-
}
|
|
4094
|
-
|
|
4095
3229
|
/**
|
|
4096
3230
|
* The immutable per-run outcome value an {@link AgentInterface}'s loop replaces as it runs — the
|
|
4097
3231
|
* assembled value its `stream`'s `result` promise resolves into a settled
|
|
@@ -4208,7 +3342,7 @@ export declare interface ScopeConfiguration {
|
|
|
4208
3342
|
/**
|
|
4209
3343
|
* Allowed ACTIVE-workspace file `path`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed) —
|
|
4210
3344
|
* the filter {@link AgentContextInterface.build} applies to the active workspace's
|
|
4211
|
-
* {@link WorkspaceInterface.files} before rendering them (text → the system block, image →
|
|
3345
|
+
* {@link import('@orkestrel/workspace').WorkspaceInterface.files} before rendering them (text → the system block, image →
|
|
4212
3346
|
* the last user message).
|
|
4213
3347
|
*/
|
|
4214
3348
|
readonly files?: readonly string[];
|
|
@@ -4223,7 +3357,7 @@ export declare interface ScopeInput extends ScopeConfiguration {
|
|
|
4223
3357
|
}
|
|
4224
3358
|
|
|
4225
3359
|
/**
|
|
4226
|
-
* A named, immutable filter over a richer context's items — the
|
|
3360
|
+
* A named, immutable filter over a richer context's items — the three per-category
|
|
4227
3361
|
* allow-lists ({@link ScopeConfiguration}) plus an `id` / `name`, and a `narrow` that
|
|
4228
3362
|
* composes a tighter child by set-INTERSECTION.
|
|
4229
3363
|
*
|
|
@@ -4311,7 +3445,7 @@ export declare type ScopeManagerEventMap = {
|
|
|
4311
3445
|
* mints + stores one (never overwrites), `scopes()` lists them in insertion order.
|
|
4312
3446
|
*
|
|
4313
3447
|
* @remarks
|
|
4314
|
-
* - **Registry.** `create(input)` mints a scope (an `id` + the
|
|
3448
|
+
* - **Registry.** `create(input)` mints a scope (an `id` + the three allow-lists) and
|
|
4315
3449
|
* stores it; `count` is how many are stored. `scope(id)` looks one up; `scopes()` lists
|
|
4316
3450
|
* them in insertion order. (Keyed by minted `id`, not `name`, so two scopes may share a
|
|
4317
3451
|
* `name` and `create` always adds.)
|
|
@@ -4341,40 +3475,6 @@ export declare interface ScopeManagerOptions {
|
|
|
4341
3475
|
readonly error?: EmitterErrorHandler;
|
|
4342
3476
|
}
|
|
4343
3477
|
|
|
4344
|
-
/**
|
|
4345
|
-
* One hit from {@link WorkspaceInterface.search} — where the match was found and the line
|
|
4346
|
-
* that carried it.
|
|
4347
|
-
*
|
|
4348
|
-
* @remarks
|
|
4349
|
-
* `line` / `column` are 1-based (column `1` is the first character of the line); `length`
|
|
4350
|
-
* is the matched substring's length; `content` is the FULL line the match sits on (not
|
|
4351
|
-
* just the matched fragment), so a caller can render the hit in context.
|
|
4352
|
-
*/
|
|
4353
|
-
export declare interface SearchMatch {
|
|
4354
|
-
readonly path: string;
|
|
4355
|
-
readonly line: number;
|
|
4356
|
-
readonly column: number;
|
|
4357
|
-
readonly length: number;
|
|
4358
|
-
/** The full text of the line the match was found on. */
|
|
4359
|
-
readonly content: string;
|
|
4360
|
-
}
|
|
4361
|
-
|
|
4362
|
-
/**
|
|
4363
|
-
* Options for {@link WorkspaceInterface.search} — how the `query` matches.
|
|
4364
|
-
*
|
|
4365
|
-
* @param options - The search options
|
|
4366
|
-
*
|
|
4367
|
-
* @remarks
|
|
4368
|
-
* - `regex` — treat `query` as a regular expression source rather than a literal substring; defaults to `false`.
|
|
4369
|
-
* - `exact` — match case-sensitively; defaults to `true` (set `false` for a case-insensitive scan).
|
|
4370
|
-
* - `limit` — stop after this many matches across all files; defaults to unlimited.
|
|
4371
|
-
*/
|
|
4372
|
-
export declare interface SearchOptions {
|
|
4373
|
-
readonly regex?: boolean;
|
|
4374
|
-
readonly exact?: boolean;
|
|
4375
|
-
readonly limit?: number;
|
|
4376
|
-
}
|
|
4377
|
-
|
|
4378
3478
|
/**
|
|
4379
3479
|
* A slice of folded messages digested into a summary — the unit of compaction a
|
|
4380
3480
|
* {@link ConversationInterface} produces when it `compact`s its live tail.
|
|
@@ -4417,48 +3517,6 @@ export declare interface SectionInterface {
|
|
|
4417
3517
|
*/
|
|
4418
3518
|
export declare function settleAgentJob(agent: AgentInterface, allowPartial: boolean): Promise<AgentResult>;
|
|
4419
3519
|
|
|
4420
|
-
/**
|
|
4421
|
-
* Slice the substring of `text` spanned by a {@link Range} (start INCLUSIVE, end
|
|
4422
|
-
* EXCLUSIVE), clamping the range to the text's bounds first — the read half of the ranged
|
|
4423
|
-
* edit surface.
|
|
4424
|
-
*
|
|
4425
|
-
* @remarks
|
|
4426
|
-
* Clamps via {@link clampRange}, resolves each end to an offset via {@link offsetAt}, and
|
|
4427
|
-
* returns `text.slice(startOffset, endOffset)`. Total — never throws.
|
|
4428
|
-
*
|
|
4429
|
-
* @param text - The text to slice
|
|
4430
|
-
* @param range - The 1-based range to extract
|
|
4431
|
-
* @returns The spanned substring (empty when the clamped span is empty)
|
|
4432
|
-
*
|
|
4433
|
-
* @example
|
|
4434
|
-
* ```ts
|
|
4435
|
-
* sliceRange('hello\nworld', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }) // 'hello'
|
|
4436
|
-
* ```
|
|
4437
|
-
*/
|
|
4438
|
-
export declare function sliceRange(text: string, range: Range): string;
|
|
4439
|
-
|
|
4440
|
-
/**
|
|
4441
|
-
* Replace the span of `text` covered by a {@link Range} with `replacement` (start
|
|
4442
|
-
* INCLUSIVE, end EXCLUSIVE), clamping the range to the text's bounds first — the write
|
|
4443
|
-
* half of the ranged edit surface.
|
|
4444
|
-
*
|
|
4445
|
-
* @remarks
|
|
4446
|
-
* Clamps via {@link clampRange}, then stitches `before + replacement + after` around the
|
|
4447
|
-
* resolved offsets. An empty span (`start === end`) becomes a pure insertion. Total —
|
|
4448
|
-
* never throws.
|
|
4449
|
-
*
|
|
4450
|
-
* @param text - The original text
|
|
4451
|
-
* @param range - The 1-based range to overwrite
|
|
4452
|
-
* @param replacement - The text to splice in place of the spanned range
|
|
4453
|
-
* @returns The text with the spanned range replaced by `replacement`
|
|
4454
|
-
*
|
|
4455
|
-
* @example
|
|
4456
|
-
* ```ts
|
|
4457
|
-
* spliceRange('hello', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }, 'bye') // 'bye'
|
|
4458
|
-
* ```
|
|
4459
|
-
*/
|
|
4460
|
-
export declare function spliceRange(text: string, range: Range, replacement: string): string;
|
|
4461
|
-
|
|
4462
3520
|
/**
|
|
4463
3521
|
* A live event stream paired with the eventual settled result and a cancel — the
|
|
4464
3522
|
* generic pull/streaming handle a long-running operation hands back.
|
|
@@ -4588,299 +3646,6 @@ export declare interface ThinkSplitterInterface {
|
|
|
4588
3646
|
flush(): string;
|
|
4589
3647
|
}
|
|
4590
3648
|
|
|
4591
|
-
/**
|
|
4592
|
-
* A registered tool — its {@link import('../types.js').ToolDefinition} schema (the
|
|
4593
|
-
* `name` / `description` / `parameters` the model sees) bound to the `execute`
|
|
4594
|
-
* handler that runs a call.
|
|
4595
|
-
*
|
|
4596
|
-
* @remarks
|
|
4597
|
-
* A thin value object: the constructor stores the schema fields and the handler, and
|
|
4598
|
-
* `execute` delegates to the handler verbatim. `parameters` is kept by reference (the
|
|
4599
|
-
* open JSON-Schema the provider forwards as-is) — not cloned. The handler's `args` is
|
|
4600
|
-
* the model-supplied `unknown` arguments record, narrowed inside the handler (§14);
|
|
4601
|
-
* isolating a throw is the {@link ToolManager}'s job, not this class's. Event-free —
|
|
4602
|
-
* no Emitter, no events.
|
|
4603
|
-
*
|
|
4604
|
-
* @example
|
|
4605
|
-
* ```ts
|
|
4606
|
-
* const tool = new Tool({
|
|
4607
|
-
* name: 'add',
|
|
4608
|
-
* description: 'Add two numbers',
|
|
4609
|
-
* parameters: { type: 'object', properties: { a: { type: 'number' }, b: { type: 'number' } } },
|
|
4610
|
-
* execute: (args) => Number(args.a) + Number(args.b),
|
|
4611
|
-
* })
|
|
4612
|
-
* ```
|
|
4613
|
-
*/
|
|
4614
|
-
export declare class Tool implements ToolInterface {
|
|
4615
|
-
#private;
|
|
4616
|
-
readonly name: string;
|
|
4617
|
-
readonly description?: string;
|
|
4618
|
-
readonly summary?: string;
|
|
4619
|
-
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
4620
|
-
constructor(options: ToolOptions);
|
|
4621
|
-
execute(args: Readonly<Record<string, unknown>>): Promise<unknown> | unknown;
|
|
4622
|
-
}
|
|
4623
|
-
|
|
4624
|
-
/**
|
|
4625
|
-
* A tool call the model emitted — the tool `name` and its parsed `arguments`.
|
|
4626
|
-
*
|
|
4627
|
-
* @remarks
|
|
4628
|
-
* `id` correlates the call with its later {@link ToolResult}; when the wire omits an
|
|
4629
|
-
* id the provider mints one (a random UUID) so every call is addressable. `arguments`
|
|
4630
|
-
* is always a record — the provider narrows the wire value (an object, or a JSON
|
|
4631
|
-
* string it parses) to one, defaulting to `{}` when neither.
|
|
4632
|
-
*/
|
|
4633
|
-
export declare interface ToolCall {
|
|
4634
|
-
readonly id: string;
|
|
4635
|
-
readonly name: string;
|
|
4636
|
-
readonly arguments: Readonly<Record<string, unknown>>;
|
|
4637
|
-
}
|
|
4638
|
-
|
|
4639
|
-
/**
|
|
4640
|
-
* The MCP `CallToolResult` shape a {@link ToolResult} maps to via {@link buildToolResult} —
|
|
4641
|
-
* `content` blocks plus an `isError` flag set ONLY on failure (never `false`).
|
|
4642
|
-
*/
|
|
4643
|
-
export declare interface ToolCallResult {
|
|
4644
|
-
readonly content: readonly ToolResultContent[];
|
|
4645
|
-
readonly isError?: true;
|
|
4646
|
-
}
|
|
4647
|
-
|
|
4648
|
-
/**
|
|
4649
|
-
* A tool the model may call — its name, an optional description, and an optional
|
|
4650
|
-
* JSON-Schema `parameters` object describing its arguments.
|
|
4651
|
-
*
|
|
4652
|
-
* @remarks
|
|
4653
|
-
* Passed to a {@link ProviderInterface}'s `generate` / `stream`; the provider maps
|
|
4654
|
-
* each into the wire's function-tool shape. `parameters` is an open JSON-Schema
|
|
4655
|
-
* record (the provider forwards it verbatim).
|
|
4656
|
-
*/
|
|
4657
|
-
export declare interface ToolDefinition {
|
|
4658
|
-
readonly name: string;
|
|
4659
|
-
readonly description?: string;
|
|
4660
|
-
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
4661
|
-
}
|
|
4662
|
-
|
|
4663
|
-
/**
|
|
4664
|
-
* A registered tool: its {@link ToolDefinition} (the schema the model sees) plus the
|
|
4665
|
-
* handler that runs a call.
|
|
4666
|
-
*
|
|
4667
|
-
* @remarks
|
|
4668
|
-
* The definition fields (`name` / `description` / `parameters`) are what a
|
|
4669
|
-
* {@link ProviderInterface} advertises to the model; `execute` is the local handler a
|
|
4670
|
-
* {@link ToolManagerInterface} invokes when the model calls the tool. The handler's
|
|
4671
|
-
* `args` is the model-supplied `unknown` JSON object — narrow it inside the handler
|
|
4672
|
-
* (§14), never assert; the manager isolates a throw into a {@link ToolResult} `error`.
|
|
4673
|
-
*/
|
|
4674
|
-
export declare interface ToolInterface extends ToolDefinition {
|
|
4675
|
-
/**
|
|
4676
|
-
* A one-or-two-sentence concise description advertised to the model IN PLACE of the
|
|
4677
|
-
* full `description` (which stays on the tool for on-demand retrieval, e.g. a
|
|
4678
|
-
* describe tool); absent ⇒ the full `description` is advertised exactly as today.
|
|
4679
|
-
*/
|
|
4680
|
-
readonly summary?: string;
|
|
4681
|
-
/**
|
|
4682
|
-
* Run the tool. `args` is the model-supplied `unknown` JSON object — narrow it
|
|
4683
|
-
* inside (§14); the manager isolates a throw into a {@link ToolResult} `error`.
|
|
4684
|
-
*
|
|
4685
|
-
* @param args - The model-supplied arguments record (an open `unknown` object)
|
|
4686
|
-
* @returns The tool's result (sync or async) — folded into a `ToolResult.value`
|
|
4687
|
-
*/
|
|
4688
|
-
execute(args: Readonly<Record<string, unknown>>): Promise<unknown> | unknown;
|
|
4689
|
-
}
|
|
4690
|
-
|
|
4691
|
-
/**
|
|
4692
|
-
* The tool registry the agent loop dispatches model tool-calls through — resolves
|
|
4693
|
-
* names, lists {@link ToolDefinition}s for the provider, and executes calls with
|
|
4694
|
-
* per-call error isolation.
|
|
4695
|
-
*
|
|
4696
|
-
* @remarks
|
|
4697
|
-
* - **Registry.** Tools live in an insertion-ordered `Map` keyed by `tool.name`;
|
|
4698
|
-
* `add` takes one or a batch (§9.2) and a re-`add` of the same name OVERWRITES it
|
|
4699
|
-
* (last write wins). `count` is the map size, `tool(name)` looks one up, `tools()`
|
|
4700
|
-
* lists them in insertion order, and `definitions()` maps each to a plain
|
|
4701
|
-
* {@link ToolDefinition} (`name` / `description?` / `parameters?`, the `execute`
|
|
4702
|
-
* handler stripped) — exactly what a provider advertises to the model, with
|
|
4703
|
-
* `tool.summary ?? tool.description` advertised as `description` (a lean `summary`
|
|
4704
|
-
* stands in for the full text when set).
|
|
4705
|
-
* - **Per-call error isolation (the load-bearing part).** `execute` resolves a
|
|
4706
|
-
* {@link ToolCall}'s tool by name and ALWAYS resolves a {@link ToolResult}: an
|
|
4707
|
-
* unknown name → `{ id, name, error: 'tool not found: <name>' }`; a successful run →
|
|
4708
|
-
* `{ id, name, value }`; a handler throw is CAUGHT into `{ id, name, error }` (an
|
|
4709
|
-
* `Error`'s message, else the stringified throw). A tool throw never escapes — it
|
|
4710
|
-
* becomes a result the model can react to.
|
|
4711
|
-
* - **Batch never fails as a whole.** `execute(calls)` runs every call via
|
|
4712
|
-
* `Promise.all(calls.map(...))` and resolves the results correlated by `id` in the
|
|
4713
|
-
* input order — a mix of success, throw, and not-found all resolve; one bad call
|
|
4714
|
-
* does not reject the batch.
|
|
4715
|
-
* - **Event-free.** A purely functional registry — no Emitter, no events.
|
|
4716
|
-
*
|
|
4717
|
-
* @example
|
|
4718
|
-
* ```ts
|
|
4719
|
-
* const manager = new ToolManager()
|
|
4720
|
-
* manager.add(new Tool({ name: 'add', execute: (a) => Number(a.x) + Number(a.y) }))
|
|
4721
|
-
* const result = await manager.execute({ id: '1', name: 'add', arguments: { x: 1, y: 2 } })
|
|
4722
|
-
* result.value // 3
|
|
4723
|
-
* ```
|
|
4724
|
-
*/
|
|
4725
|
-
export declare class ToolManager implements ToolManagerInterface {
|
|
4726
|
-
#private;
|
|
4727
|
-
get count(): number;
|
|
4728
|
-
add(tool: ToolInterface): void;
|
|
4729
|
-
add(tools: readonly ToolInterface[]): void;
|
|
4730
|
-
tool(name: string): ToolInterface | undefined;
|
|
4731
|
-
tools(): readonly ToolInterface[];
|
|
4732
|
-
definitions(): readonly ToolDefinition[];
|
|
4733
|
-
execute(call: ToolCall): Promise<ToolResult>;
|
|
4734
|
-
execute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
|
|
4735
|
-
remove(name: string): boolean;
|
|
4736
|
-
remove(names: readonly string[]): boolean;
|
|
4737
|
-
clear(): void;
|
|
4738
|
-
}
|
|
4739
|
-
|
|
4740
|
-
/**
|
|
4741
|
-
* A registry of tools — resolves names, lists definitions for the provider, and
|
|
4742
|
-
* executes calls with per-call error isolation.
|
|
4743
|
-
*
|
|
4744
|
-
* @remarks
|
|
4745
|
-
* - **Registry.** `add` registers one tool or a batch (§9.2), keyed by `tool.name`
|
|
4746
|
-
* (a re-`add` of the same name overwrites — last write wins); `count` is the number
|
|
4747
|
-
* registered. `tool(name)` looks one up; `tools()` lists them in insertion order;
|
|
4748
|
-
* `definitions()` strips each to a plain {@link ToolDefinition} for the provider,
|
|
4749
|
-
* advertising `tool.summary ?? tool.description` in the definition's `description`
|
|
4750
|
-
* field — a lean `summary` stands in for the full `description` when set.
|
|
4751
|
-
* - **Per-call error isolation.** `execute` resolves a {@link ToolCall}'s tool by name
|
|
4752
|
-
* and runs it, ALWAYS resolving a {@link ToolResult}: a success carries `value`, a
|
|
4753
|
-
* handler throw is caught into `error`, and an unknown name becomes a not-found
|
|
4754
|
-
* `error`. A tool throw NEVER escapes — it becomes a result the model can react to.
|
|
4755
|
-
* - **Batch never fails as a whole.** The array `execute` runs every call (via
|
|
4756
|
-
* `Promise.all`) and resolves results correlated by `id` in order — one bad call
|
|
4757
|
-
* (throw or not-found) does not fail the batch.
|
|
4758
|
-
* - **Event-free.** A purely functional registry — no Emitter, no events.
|
|
4759
|
-
*/
|
|
4760
|
-
export declare interface ToolManagerInterface {
|
|
4761
|
-
readonly count: number;
|
|
4762
|
-
add(tool: ToolInterface): void;
|
|
4763
|
-
add(tools: readonly ToolInterface[]): void;
|
|
4764
|
-
tool(name: string): ToolInterface | undefined;
|
|
4765
|
-
tools(): readonly ToolInterface[];
|
|
4766
|
-
definitions(): readonly ToolDefinition[];
|
|
4767
|
-
execute(call: ToolCall): Promise<ToolResult>;
|
|
4768
|
-
execute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
|
|
4769
|
-
remove(name: string): boolean;
|
|
4770
|
-
remove(names: readonly string[]): boolean;
|
|
4771
|
-
clear(): void;
|
|
4772
|
-
}
|
|
4773
|
-
|
|
4774
|
-
/**
|
|
4775
|
-
* Options for `createTool` — the schema the model sees (`name` / `description` /
|
|
4776
|
-
* `parameters`) plus the `execute` handler that runs a call.
|
|
4777
|
-
*
|
|
4778
|
-
* @remarks
|
|
4779
|
-
* `name` is required (it keys the tool in a {@link ToolManagerInterface} and is what
|
|
4780
|
-
* the model calls); `description` and `parameters` are the optional JSON-Schema the
|
|
4781
|
-
* provider advertises (forwarded verbatim). `summary`, when set, is a lean
|
|
4782
|
-
* one-or-two-sentence advertisement used IN PLACE of `description` in a
|
|
4783
|
-
* {@link ToolManagerInterface.definitions} listing — `description` stays available on
|
|
4784
|
-
* the tool for on-demand retrieval. `execute` receives the model-supplied arguments
|
|
4785
|
-
* record and returns the tool's result (sync or async).
|
|
4786
|
-
*/
|
|
4787
|
-
export declare interface ToolOptions {
|
|
4788
|
-
readonly name: string;
|
|
4789
|
-
readonly description?: string;
|
|
4790
|
-
readonly summary?: string;
|
|
4791
|
-
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
4792
|
-
readonly execute: (args: Readonly<Record<string, unknown>>) => Promise<unknown> | unknown;
|
|
4793
|
-
}
|
|
4794
|
-
|
|
4795
|
-
/**
|
|
4796
|
-
* The outcome of executing a {@link ToolCall} — keyed back to the call by `id` and
|
|
4797
|
-
* `name`, carrying either a `value` (the result) or an `error` string (the failure).
|
|
4798
|
-
*/
|
|
4799
|
-
export declare interface ToolResult {
|
|
4800
|
-
readonly id: string;
|
|
4801
|
-
readonly name: string;
|
|
4802
|
-
readonly value?: unknown;
|
|
4803
|
-
readonly error?: string;
|
|
4804
|
-
}
|
|
4805
|
-
|
|
4806
|
-
/**
|
|
4807
|
-
* One block of an MCP-shaped tool call response — plain text, the only content kind
|
|
4808
|
-
* {@link buildToolResult} emits.
|
|
4809
|
-
*/
|
|
4810
|
-
export declare interface ToolResultContent {
|
|
4811
|
-
readonly type: 'text';
|
|
4812
|
-
readonly text: string;
|
|
4813
|
-
}
|
|
4814
|
-
|
|
4815
|
-
/**
|
|
4816
|
-
* A mutable, `path`-keyed working set of immutable {@link FileInterface}s — the
|
|
4817
|
-
* in-memory editing surface over the file primitive.
|
|
4818
|
-
*
|
|
4819
|
-
* @remarks
|
|
4820
|
-
* - **Registry.** Files live in an insertion-ordered `Map` keyed by `path`; `count` is the
|
|
4821
|
-
* map size, `file(path)` looks one up, and `files()` lists them in insertion order.
|
|
4822
|
-
* - **Write replaces the File (§11 immutability).** Every edit MINTS a replacement
|
|
4823
|
-
* {@link FileInterface} (via {@link import('../factories.js').createFile}) rather than
|
|
4824
|
-
* mutating in place, transitioning `state` to `'created'` for a brand-new path or
|
|
4825
|
-
* `'modified'` for an existing one. A whole-file string write preserves an existing text
|
|
4826
|
-
* file's `language`, else infers it from the `path` (`inferLanguage`); writing a string
|
|
4827
|
-
* onto an existing BINARY path replaces it with a text file (a deliberate retype). A
|
|
4828
|
-
* ranged `write` splices a `Range` of an existing text file.
|
|
4829
|
-
* - **Modality rules.** Text-only ops on a binary file are rejected: a ranged `read` /
|
|
4830
|
-
* `write`, `prepend`, and `append` throw `MODALITY`; a plain `read(path)` of a binary
|
|
4831
|
-
* file returns `undefined`; `search` / `replace` skip binary files (0 matches).
|
|
4832
|
-
* - **In-memory removal.** `remove(path)` / `remove(paths)` drop files outright (no
|
|
4833
|
-
* tombstone — the `'loaded'` / `'deleted'` states are reserved for a future FileStore);
|
|
4834
|
-
* `remove()` and `clear()` both empty the registry and emit the single `clear` signal.
|
|
4835
|
-
* The disk/sync lifecycle (`load` / `revert` / `accept` / `purge` / `dirty`) is NOT part
|
|
4836
|
-
* of this surface.
|
|
4837
|
-
* - **Observable (§13).** The owned {@link emitter} ({@link WorkspaceEventMap}) carries
|
|
4838
|
-
* `write` (the resulting file) / `remove` (the path) / `move` (`{ from, to }`) / `clear`.
|
|
4839
|
-
* Every event is emitted directly, strictly AFTER the map mutation completes; the
|
|
4840
|
-
* emitter isolates a listener throw and routes it to its `error` handler, so a buggy
|
|
4841
|
-
* observer can never corrupt a mutation.
|
|
4842
|
-
*
|
|
4843
|
-
* @example
|
|
4844
|
-
* ```ts
|
|
4845
|
-
* const workspace = new Workspace()
|
|
4846
|
-
* workspace.write('src/main.ts', 'const x = 1')
|
|
4847
|
-
* workspace.file('src/main.ts')?.state // 'created'
|
|
4848
|
-
* workspace.append('src/main.ts', '\nconst y = 2')
|
|
4849
|
-
* workspace.file('src/main.ts')?.state // 'modified'
|
|
4850
|
-
* workspace.read('src/main.ts') // 'const x = 1\nconst y = 2'
|
|
4851
|
-
* ```
|
|
4852
|
-
*/
|
|
4853
|
-
export declare class Workspace implements WorkspaceInterface {
|
|
4854
|
-
#private;
|
|
4855
|
-
constructor(options?: WorkspaceOptions, seed?: Iterable<readonly [string, FileInterface]>);
|
|
4856
|
-
get id(): string;
|
|
4857
|
-
get emitter(): EmitterInterface<WorkspaceEventMap>;
|
|
4858
|
-
get count(): number;
|
|
4859
|
-
file(path: string): FileInterface | undefined;
|
|
4860
|
-
files(): readonly FileInterface[];
|
|
4861
|
-
read(path: string): string | undefined;
|
|
4862
|
-
read(path: string, range: Range): ReadResult | undefined;
|
|
4863
|
-
read(paths: readonly string[]): Readonly<Record<string, string>>;
|
|
4864
|
-
has(path: string): boolean;
|
|
4865
|
-
has(paths: readonly string[]): boolean;
|
|
4866
|
-
search(query: string, options?: SearchOptions): readonly SearchMatch[];
|
|
4867
|
-
replace(query: string, replacement: string, options?: ReplaceOptions): ReplaceResult;
|
|
4868
|
-
write(path: string, content: string): void;
|
|
4869
|
-
write(path: string, content: string, range: Range): void;
|
|
4870
|
-
write(files: Readonly<Record<string, string>>): void;
|
|
4871
|
-
prepend(path: string, content: string): void;
|
|
4872
|
-
prepend(files: Readonly<Record<string, string>>): void;
|
|
4873
|
-
append(path: string, content: string): void;
|
|
4874
|
-
append(files: Readonly<Record<string, string>>): void;
|
|
4875
|
-
move(from: string, to: string): boolean;
|
|
4876
|
-
move(mapping: Readonly<Record<string, string>>): boolean;
|
|
4877
|
-
remove(): void;
|
|
4878
|
-
remove(path: string): boolean;
|
|
4879
|
-
remove(paths: readonly string[]): boolean;
|
|
4880
|
-
clear(): void;
|
|
4881
|
-
snapshot(): WorkspaceSnapshot;
|
|
4882
|
-
}
|
|
4883
|
-
|
|
4884
3649
|
/**
|
|
4885
3650
|
* The section header {@link import('./AgentContext.js').AgentContext}'s `build()` renders the
|
|
4886
3651
|
* ACTIVE workspace's TEXT files under — the leading line of the dedicated workspace block in the
|
|
@@ -4895,393 +3660,4 @@ export declare class Workspace implements WorkspaceInterface {
|
|
|
4895
3660
|
*/
|
|
4896
3661
|
export declare const WORKSPACE_SECTION_HEADER = "## Workspace";
|
|
4897
3662
|
|
|
4898
|
-
/**
|
|
4899
|
-
* An error thrown by the in-memory {@link import('./workspaces/Workspace.js').Workspace} edit
|
|
4900
|
-
* surface.
|
|
4901
|
-
*
|
|
4902
|
-
* @remarks
|
|
4903
|
-
* Carries a {@link WorkspaceErrorCode} and an optional `context` bag naming the offending
|
|
4904
|
-
* path / range. Thrown for a text-only operation aimed at an image file (`MODALITY` — a
|
|
4905
|
-
* ranged read / write, `prepend`, or `append`), an invalid `search` / `replace` regular
|
|
4906
|
-
* expression (`PATTERN`), and a structurally invalid ranged-write {@link import('./types.js').Range}
|
|
4907
|
-
* (`RANGE` — inverted, or a sub-1 line / column).
|
|
4908
|
-
*/
|
|
4909
|
-
export declare class WorkspaceError extends Error {
|
|
4910
|
-
readonly code: WorkspaceErrorCode;
|
|
4911
|
-
readonly context?: Readonly<Record<string, unknown>>;
|
|
4912
|
-
constructor(code: WorkspaceErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
|
|
4913
|
-
}
|
|
4914
|
-
|
|
4915
|
-
/**
|
|
4916
|
-
* The machine-readable code a {@link import('./errors.js').WorkspaceError} carries
|
|
4917
|
-
* (AGENTS §12) — a `catch` branches on `error.code` instead of parsing the message.
|
|
4918
|
-
*
|
|
4919
|
-
* @remarks
|
|
4920
|
-
* - `MODALITY` — a text-only op (ranged read/write, `prepend`, `append`) was aimed at a binary file.
|
|
4921
|
-
* - `PATTERN` — a `search` / `replace` `query` was an invalid regular expression (with `regex: true`).
|
|
4922
|
-
* - `RANGE` — a ranged `write` got a structurally invalid {@link Range} (inverted, or a sub-1 line/column).
|
|
4923
|
-
* - `TOOL` — a handler-level validation fault raised by a workspace-editing tool boundary (see
|
|
4924
|
-
* `@orkestrel/tool`) when the agent-supplied args were malformed / unknown. Distinct from the
|
|
4925
|
-
* surface faults above (which the live workspace raises) — this is the tool boundary rejecting an
|
|
4926
|
-
* un-parseable operation before any workspace call.
|
|
4927
|
-
*/
|
|
4928
|
-
export declare type WorkspaceErrorCode = 'MODALITY' | 'PATTERN' | 'RANGE' | 'TOOL';
|
|
4929
|
-
|
|
4930
|
-
/**
|
|
4931
|
-
* The observable events a {@link import('./workspaces/Workspace.js').Workspace} emits
|
|
4932
|
-
* (AGENTS §13) — each fired AFTER the corresponding mutation completes.
|
|
4933
|
-
*
|
|
4934
|
-
* @remarks
|
|
4935
|
-
* - `write` — a file was written / edited, carrying the resulting {@link FileInterface}.
|
|
4936
|
-
* - `remove` — a single file was dropped, carrying its `path`.
|
|
4937
|
-
* - `move` — a file was re-keyed, carrying `{ from, to }`.
|
|
4938
|
-
* - `clear` — the workspace was emptied (the canonical "emptied" signal, fired by both `remove()` and `clear()`).
|
|
4939
|
-
*/
|
|
4940
|
-
export declare type WorkspaceEventMap = {
|
|
4941
|
-
readonly write: readonly [file: FileInterface];
|
|
4942
|
-
readonly remove: readonly [path: string];
|
|
4943
|
-
readonly move: readonly [move: {
|
|
4944
|
-
readonly from: string;
|
|
4945
|
-
readonly to: string;
|
|
4946
|
-
}];
|
|
4947
|
-
readonly clear: readonly [];
|
|
4948
|
-
};
|
|
4949
|
-
|
|
4950
|
-
/**
|
|
4951
|
-
* The data to author a {@link WorkspaceInterface} through a
|
|
4952
|
-
* {@link WorkspaceManagerInterface} — the optional `id`, the reserved `on` hooks + `error`
|
|
4953
|
-
* handler (§13), and an optional `seed` of initial files.
|
|
4954
|
-
*
|
|
4955
|
-
* @remarks
|
|
4956
|
-
* `id` is the workspace's identity (minted when omitted). `on` / `error` are the §8/§13
|
|
4957
|
-
* keys (initial {@link WorkspaceEventMap} listeners + the listener-error handler), flowing
|
|
4958
|
-
* the manager's defaults in unless overridden. `seed` is the construction-time hydration
|
|
4959
|
-
* seam (path → {@link FileInterface}) — the only way to seat a non-text (binary) file, and
|
|
4960
|
-
* what a future FileStore reads a snapshot into; seeding is silent (no `write` events).
|
|
4961
|
-
*/
|
|
4962
|
-
export declare interface WorkspaceInput {
|
|
4963
|
-
readonly id?: string;
|
|
4964
|
-
readonly on?: EmitterHooks<WorkspaceEventMap>;
|
|
4965
|
-
readonly error?: EmitterErrorHandler;
|
|
4966
|
-
/** Pre-seeded initial files (path → File), placed silently at construction. */
|
|
4967
|
-
readonly seed?: Iterable<readonly [string, FileInterface]>;
|
|
4968
|
-
}
|
|
4969
|
-
|
|
4970
|
-
/**
|
|
4971
|
-
* A mutable, `path`-keyed working set of immutable {@link FileInterface}s — the in-memory
|
|
4972
|
-
* editing surface over the file primitive.
|
|
4973
|
-
*
|
|
4974
|
-
* @remarks
|
|
4975
|
-
* Files live in an insertion-ordered map keyed by `path`. Every edit REPLACES the
|
|
4976
|
-
* immutable {@link FileInterface} at a path with a new one (transitioning its `state` to
|
|
4977
|
-
* `'created'` for a fresh path or `'modified'` for an existing one) rather than mutating in
|
|
4978
|
-
* place. The disk/sync lifecycle (`load` / `revert` / `accept` / `purge` / `dirty`) is
|
|
4979
|
-
* deliberately NOT part of this surface — it is deferred to a future FileStore. Text-only
|
|
4980
|
-
* operations on a binary file are governed by the modality rules (a ranged read/write,
|
|
4981
|
-
* `prepend`, and `append` throw `MODALITY`; a plain `read` returns `undefined`; `search` /
|
|
4982
|
-
* `replace` skip the file). Observe mutations through the owned {@link emitter} (AGENTS §13).
|
|
4983
|
-
*/
|
|
4984
|
-
export declare interface WorkspaceInterface {
|
|
4985
|
-
/** The workspace's identity — its key in a {@link WorkspaceManagerInterface}; minted when not supplied. */
|
|
4986
|
-
readonly id: string;
|
|
4987
|
-
/** The push observation surface (AGENTS §13) — `write` / `remove` / `move` / `clear`. */
|
|
4988
|
-
readonly emitter: EmitterInterface<WorkspaceEventMap>;
|
|
4989
|
-
/** The number of files currently held. */
|
|
4990
|
-
readonly count: number;
|
|
4991
|
-
/** Look up one file by path, or `undefined` when absent. */
|
|
4992
|
-
file(path: string): FileInterface | undefined;
|
|
4993
|
-
/** List every file in insertion order. */
|
|
4994
|
-
files(): readonly FileInterface[];
|
|
4995
|
-
read(path: string): string | undefined;
|
|
4996
|
-
read(path: string, range: Range): ReadResult | undefined;
|
|
4997
|
-
read(paths: readonly string[]): Readonly<Record<string, string>>;
|
|
4998
|
-
has(path: string): boolean;
|
|
4999
|
-
has(paths: readonly string[]): boolean;
|
|
5000
|
-
/** Scan every text file's lines for `query`, returning each hit in insertion order. */
|
|
5001
|
-
search(query: string, options?: SearchOptions): readonly SearchMatch[];
|
|
5002
|
-
/** Replace `query` with `replacement` across every text file, returning the tally. */
|
|
5003
|
-
replace(query: string, replacement: string, options?: ReplaceOptions): ReplaceResult;
|
|
5004
|
-
write(path: string, content: string): void;
|
|
5005
|
-
write(path: string, content: string, range: Range): void;
|
|
5006
|
-
write(files: Readonly<Record<string, string>>): void;
|
|
5007
|
-
prepend(path: string, content: string): void;
|
|
5008
|
-
prepend(files: Readonly<Record<string, string>>): void;
|
|
5009
|
-
append(path: string, content: string): void;
|
|
5010
|
-
append(files: Readonly<Record<string, string>>): void;
|
|
5011
|
-
move(from: string, to: string): boolean;
|
|
5012
|
-
move(mapping: Readonly<Record<string, string>>): boolean;
|
|
5013
|
-
remove(): void;
|
|
5014
|
-
remove(path: string): boolean;
|
|
5015
|
-
remove(paths: readonly string[]): boolean;
|
|
5016
|
-
/** Empty the workspace (emits `clear`). */
|
|
5017
|
-
clear(): void;
|
|
5018
|
-
/**
|
|
5019
|
-
* Serialize this workspace to a plain, JSON-serializable {@link WorkspaceSnapshot} — its
|
|
5020
|
-
* `id` plus a flat list of its {@link FileInterface}s (each already carries its `path`).
|
|
5021
|
-
*
|
|
5022
|
-
* @remarks
|
|
5023
|
-
* The container serializes ITSELF (`{ id: this.id, files: this.files() }`) — the
|
|
5024
|
-
* {@link WorkspaceStoreInterface} persistence seam's payload, paralleling the
|
|
5025
|
-
* {@link ConversationInterface}'s own snapshot a later track adds. The snapshot is the
|
|
5026
|
-
* durable analogue of the constructor `seed`: a {@link WorkspaceManagerInterface} HYDRATES a
|
|
5027
|
-
* workspace from `snapshot.files` through that seam (see {@link WorkspaceManagerInterface.open}).
|
|
5028
|
-
* Pure — the `File`s are already frozen plain records (so the snapshot `structuredClone`s /
|
|
5029
|
-
* JSON-round-trips losslessly), and snapshotting mutates nothing.
|
|
5030
|
-
*
|
|
5031
|
-
* @returns The {@link WorkspaceSnapshot} (`{ id, files }`)
|
|
5032
|
-
*/
|
|
5033
|
-
snapshot(): WorkspaceSnapshot;
|
|
5034
|
-
}
|
|
5035
|
-
|
|
5036
|
-
/**
|
|
5037
|
-
* The registry of {@link Workspace}s keyed by `id`, in insertion order, WITH an active pointer
|
|
5038
|
-
* — the §9 store over the workspace layer PLUS the `active` / `switch` seam the context renders.
|
|
5039
|
-
* Event-free (a registry, like {@link ConversationManager}); the observability lives on each
|
|
5040
|
-
* {@link Workspace}.
|
|
5041
|
-
*
|
|
5042
|
-
* @remarks
|
|
5043
|
-
* - **Registry.** Workspaces live in an insertion-ordered `Map` keyed by `id`. `add(input?)`
|
|
5044
|
-
* mints a {@link Workspace} (its `id` from `input` or `crypto.randomUUID()`), flowing the
|
|
5045
|
-
* manager's default `on` / `error` in unless the `input` OVERRIDES them, and stores it (an
|
|
5046
|
-
* already-present `id` OVERWRITES — last write wins). `count` is the map size, `workspace(id)`
|
|
5047
|
-
* looks one up, `workspaces()` lists them in insertion order.
|
|
5048
|
-
* - **Active pointer.** `active` is the active workspace (what the context renders), `undefined`
|
|
5049
|
-
* until the FIRST `add` (which auto-activates it — a registry with workspaces always has one
|
|
5050
|
-
* active). A subsequent `add` leaves `active` unchanged. `switch(id)` re-points `active` to the
|
|
5051
|
-
* workspace with `id` and returns it; an unknown `id` returns `undefined` and leaves `active`
|
|
5052
|
-
* unchanged (the lenient lookup style — never throws, no new error code).
|
|
5053
|
-
* - **Removal.** `remove` drops one by id, or a batch (§9.2) — `true` when any was removed;
|
|
5054
|
-
* removing the ACTIVE workspace sets `active` to `undefined`. `clear` empties the registry and
|
|
5055
|
-
* sets `active` to `undefined`.
|
|
5056
|
-
* - **Durable open / save (the optional `store`).** With a {@link WorkspaceStoreInterface} supplied
|
|
5057
|
-
* (the `store` option), `open(id)` HYDRATES a workspace on a registry miss — it `store.get(id)`s
|
|
5058
|
-
* the snapshot and rebuilds a fresh {@link Workspace} through the constructor `seed`
|
|
5059
|
-
* (`snapshot.files` → path → File), then activates it — and `save(id)` PERSISTS a registered
|
|
5060
|
-
* workspace's `snapshot()`. Both are LENIENT without a store (open resolves only registered ids,
|
|
5061
|
-
* save is a no-op `false`), consistent with the lenient `switch`.
|
|
5062
|
-
* - **Event-free.** A purely registry store — no Emitter, no events (each workspace owns its own
|
|
5063
|
-
* observable `emitter`).
|
|
5064
|
-
*
|
|
5065
|
-
* @example
|
|
5066
|
-
* ```ts
|
|
5067
|
-
* const manager = new WorkspaceManager()
|
|
5068
|
-
* const first = manager.add() // auto-activates — active === first
|
|
5069
|
-
* manager.add({ id: 'scratch' }) // leaves active unchanged
|
|
5070
|
-
* manager.switch('scratch') // re-points active to the 'scratch' workspace
|
|
5071
|
-
* manager.count // 2
|
|
5072
|
-
* ```
|
|
5073
|
-
*/
|
|
5074
|
-
export declare class WorkspaceManager implements WorkspaceManagerInterface {
|
|
5075
|
-
#private;
|
|
5076
|
-
constructor(options?: WorkspaceManagerOptions);
|
|
5077
|
-
get count(): number;
|
|
5078
|
-
get active(): WorkspaceInterface | undefined;
|
|
5079
|
-
workspace(id: string): WorkspaceInterface | undefined;
|
|
5080
|
-
workspaces(): readonly WorkspaceInterface[];
|
|
5081
|
-
add(input?: WorkspaceInput): WorkspaceInterface;
|
|
5082
|
-
switch(id: string): WorkspaceInterface | undefined;
|
|
5083
|
-
open(id: string): Promise<WorkspaceInterface | undefined>;
|
|
5084
|
-
save(id: string): Promise<boolean>;
|
|
5085
|
-
remove(ids: readonly string[]): boolean;
|
|
5086
|
-
remove(id: string): boolean;
|
|
5087
|
-
clear(): void;
|
|
5088
|
-
}
|
|
5089
|
-
|
|
5090
|
-
/**
|
|
5091
|
-
* A registry of {@link WorkspaceInterface}s keyed by their `id`, in insertion order, WITH an
|
|
5092
|
-
* active pointer — the §9 store over the workspace layer PLUS the `active` / `switch` seam the
|
|
5093
|
-
* context renders. Event-free (each {@link WorkspaceInterface} owns its own `emitter`).
|
|
5094
|
-
*
|
|
5095
|
-
* @remarks
|
|
5096
|
-
* - **Registry.** `count` is how many are stored. `add(input?)` mints a
|
|
5097
|
-
* {@link WorkspaceInterface} (its `id` from `input` or a random UUID), flowing the manager's
|
|
5098
|
-
* default `on` / `error` in unless the `input` overrides them; `add` of an already-present
|
|
5099
|
-
* `id` OVERWRITES it (last write wins). `workspace(id)` looks one up (`undefined` when
|
|
5100
|
-
* absent); `workspaces()` lists them in insertion order.
|
|
5101
|
-
* - **Active pointer.** `active` is the active workspace (what the context renders), `undefined`
|
|
5102
|
-
* until the FIRST `add` (which auto-activates it). A later `add` leaves `active` unchanged.
|
|
5103
|
-
* `switch(id)` re-points `active` to the workspace with `id` and returns it; an unknown `id`
|
|
5104
|
-
* returns `undefined` and leaves `active` unchanged (the lenient lookup style — never throws).
|
|
5105
|
-
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true`
|
|
5106
|
-
* when any was removed; removing the ACTIVE workspace sets `active` to `undefined`. `clear`
|
|
5107
|
-
* empties the registry and sets `active` to `undefined`.
|
|
5108
|
-
* - **Durable open / save (the optional `store` seam).** When a {@link WorkspaceStoreInterface}
|
|
5109
|
-
* is supplied (the `store` option), `open(id)` HYDRATES a workspace from the store on a registry
|
|
5110
|
-
* miss (rebuilding it through the constructor `seed` from `snapshot.files`) and `save(id)`
|
|
5111
|
-
* PERSISTS a registered workspace's {@link WorkspaceInterface.snapshot}. Both are LENIENT without
|
|
5112
|
-
* a store — `open` resolves only registered ids, `save` is a no-op (`false`) — consistent with
|
|
5113
|
-
* the lenient `switch`.
|
|
5114
|
-
* - **Event-free.** A purely registry store — no Emitter, no events (each workspace owns its own).
|
|
5115
|
-
*/
|
|
5116
|
-
export declare interface WorkspaceManagerInterface {
|
|
5117
|
-
readonly count: number;
|
|
5118
|
-
/** The active workspace — what the context renders; `undefined` until the first `add`. */
|
|
5119
|
-
readonly active: WorkspaceInterface | undefined;
|
|
5120
|
-
workspace(id: string): WorkspaceInterface | undefined;
|
|
5121
|
-
workspaces(): readonly WorkspaceInterface[];
|
|
5122
|
-
add(input?: WorkspaceInput): WorkspaceInterface;
|
|
5123
|
-
switch(id: string): WorkspaceInterface | undefined;
|
|
5124
|
-
/**
|
|
5125
|
-
* Resolve a workspace by id, ACTIVATING it — from the registry if present, else HYDRATED from
|
|
5126
|
-
* the optional {@link WorkspaceStoreInterface} (`store`).
|
|
5127
|
-
*
|
|
5128
|
-
* @remarks
|
|
5129
|
-
* - If `id` is ALREADY registered, it is ACTIVATED (`switch`ed to) and returned — no store hit.
|
|
5130
|
-
* - Else if a `store` is set, `store.get(id)` is awaited; on a HIT the snapshot is rehydrated
|
|
5131
|
-
* into a fresh {@link WorkspaceInterface} through the constructor `seed`
|
|
5132
|
-
* (`add({ id, seed: snapshot.files.map((file) => [file.path, file]) })`), which registers AND
|
|
5133
|
-
* auto-activates it (or activates it explicitly), and it is returned.
|
|
5134
|
-
* - Else (no store, or a store MISS) ⇒ `undefined` (lenient — no throw).
|
|
5135
|
-
*
|
|
5136
|
-
* @param id - The workspace id to open
|
|
5137
|
-
* @returns The activated {@link WorkspaceInterface}, or `undefined` when neither registered nor stored
|
|
5138
|
-
*/
|
|
5139
|
-
open(id: string): Promise<WorkspaceInterface | undefined>;
|
|
5140
|
-
/**
|
|
5141
|
-
* Persist a REGISTERED workspace's {@link WorkspaceInterface.snapshot} to the optional
|
|
5142
|
-
* {@link WorkspaceStoreInterface} (`store`).
|
|
5143
|
-
*
|
|
5144
|
-
* @remarks
|
|
5145
|
-
* Lenient: when a `store` is set AND `id` is registered, `store.set(workspace.snapshot())` is
|
|
5146
|
-
* awaited and `true` is returned; otherwise (no store, OR an unknown id) it is a NO-OP returning
|
|
5147
|
-
* `false` — never a throw, consistent with the lenient `switch`.
|
|
5148
|
-
*
|
|
5149
|
-
* @param id - The id of the registered workspace to persist
|
|
5150
|
-
* @returns `true` when the snapshot was persisted; `false` when no store / unknown id
|
|
5151
|
-
*/
|
|
5152
|
-
save(id: string): Promise<boolean>;
|
|
5153
|
-
remove(ids: readonly string[]): boolean;
|
|
5154
|
-
remove(id: string): boolean;
|
|
5155
|
-
clear(): void;
|
|
5156
|
-
}
|
|
5157
|
-
|
|
5158
|
-
/**
|
|
5159
|
-
* Options for `createWorkspaceManager` — the per-workspace `on` / `error` defaults the
|
|
5160
|
-
* workspaces it creates inherit.
|
|
5161
|
-
*
|
|
5162
|
-
* @remarks
|
|
5163
|
-
* `on` / `error` are the default {@link WorkspaceEventMap} listeners + the emitter's
|
|
5164
|
-
* listener-error handler (§13) flowed into every workspace the manager `add`s (a per-`add`
|
|
5165
|
-
* {@link WorkspaceInput.on} / `.error` overrides them). Kept minimal (AGENTS §21) — a
|
|
5166
|
-
* registry needs no more.
|
|
5167
|
-
*/
|
|
5168
|
-
export declare interface WorkspaceManagerOptions {
|
|
5169
|
-
/** The default event listeners for workspaces this manager creates (a per-`add` override wins). */
|
|
5170
|
-
readonly on?: EmitterHooks<WorkspaceEventMap>;
|
|
5171
|
-
/** The default listener-error handler (a per-`add` override wins). */
|
|
5172
|
-
readonly error?: EmitterErrorHandler;
|
|
5173
|
-
/**
|
|
5174
|
-
* The optional durable {@link WorkspaceStoreInterface} backing {@link WorkspaceManagerInterface.open}
|
|
5175
|
-
* / {@link WorkspaceManagerInterface.save} — a memory / JSON / SQLite / IndexedDB store a workspace
|
|
5176
|
-
* is HYDRATED from (`open` a registry-miss) and PERSISTED to (`save`). Omitted ⇒ the manager is
|
|
5177
|
-
* registry-only: `open` resolves only what is already registered, and `save` is a no-op (`false`).
|
|
5178
|
-
*/
|
|
5179
|
-
readonly store?: WorkspaceStoreInterface;
|
|
5180
|
-
}
|
|
5181
|
-
|
|
5182
|
-
/**
|
|
5183
|
-
* Options for {@link import('./factories.js').createWorkspace} / the
|
|
5184
|
-
* {@link import('./workspaces/Workspace.js').Workspace} constructor.
|
|
5185
|
-
*
|
|
5186
|
-
* @param options - The workspace options
|
|
5187
|
-
*
|
|
5188
|
-
* @remarks
|
|
5189
|
-
* - `id` — the workspace's identity (its key in a {@link WorkspaceManagerInterface}); MINTED via `crypto.randomUUID()` when omitted.
|
|
5190
|
-
* - `on` — initial {@link WorkspaceEventMap} listeners (AGENTS §8), wired at construction.
|
|
5191
|
-
* - `error` — the emitter's listener-error handler (AGENTS §13); a throw from any listener is routed here instead of rethrown.
|
|
5192
|
-
*/
|
|
5193
|
-
export declare interface WorkspaceOptions {
|
|
5194
|
-
readonly id?: string;
|
|
5195
|
-
readonly on?: EmitterHooks<WorkspaceEventMap>;
|
|
5196
|
-
readonly error?: EmitterErrorHandler;
|
|
5197
|
-
}
|
|
5198
|
-
|
|
5199
|
-
/**
|
|
5200
|
-
* A JSON-serializable snapshot of a workspace's state — its `id` plus a FLAT list of its
|
|
5201
|
-
* {@link FileInterface}s — the durable payload the {@link WorkspaceStoreInterface} persists.
|
|
5202
|
-
*
|
|
5203
|
-
* @remarks
|
|
5204
|
-
* Pure JSON DATA (no class instances, no functions): each {@link FileInterface} is already a
|
|
5205
|
-
* PLAIN frozen record that `structuredClone`s / JSON-round-trips losslessly, and a `File` carries
|
|
5206
|
-
* its OWN `path`, so a flat `files` list is enough to reconstruct the path-keyed map (no nested
|
|
5207
|
-
* `path → File` object needed for serialization). The snapshot the container produces from itself
|
|
5208
|
-
* ({@link WorkspaceInterface.snapshot}); the durable analogue of the constructor `seed`. A
|
|
5209
|
-
* {@link WorkspaceManagerInterface} hydrates a workspace from `snapshot.files` through the seed
|
|
5210
|
-
* seam (see {@link WorkspaceManagerInterface.open}). It is narrowed back from an untrusted storage
|
|
5211
|
-
* read by {@link import('./helpers.js').isWorkspaceSnapshot} (the AGENTS §14 boundary narrow).
|
|
5212
|
-
*/
|
|
5213
|
-
export declare interface WorkspaceSnapshot {
|
|
5214
|
-
readonly id: string;
|
|
5215
|
-
readonly files: readonly FileInterface[];
|
|
5216
|
-
}
|
|
5217
|
-
|
|
5218
|
-
/**
|
|
5219
|
-
* One row of the table a
|
|
5220
|
-
* {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} persists
|
|
5221
|
-
* — a workspace `id` plus its {@link WorkspaceSnapshot} held as ONE OPAQUE JSON column.
|
|
5222
|
-
*
|
|
5223
|
-
* @remarks
|
|
5224
|
-
* The Database twin of {@link WorkspaceStoreInterface} stores the snapshot whole (the `snapshot`
|
|
5225
|
-
* column is a `rawShape`, an opaque JSON blob — exactly as the analogous
|
|
5226
|
-
* `WorkflowSnapshotRow` in `@orkestrel/workflow` stores a workflow snapshot), so the
|
|
5227
|
-
* row type stays FLAT and the `File`-list snapshot shape never forces the contract to `Infer` it.
|
|
5228
|
-
* The column therefore reads back as the broad `unknown`; the store narrows it to a
|
|
5229
|
-
* {@link WorkspaceSnapshot} on `get` ({@link import('./helpers.js').isWorkspaceSnapshot}, the
|
|
5230
|
-
* AGENTS §14 boundary narrow). `id` mirrors {@link WorkspaceSnapshot.id} (the primary key), so a
|
|
5231
|
-
* `set` writes `{ id: snapshot.id, snapshot }`.
|
|
5232
|
-
*/
|
|
5233
|
-
export declare interface WorkspaceSnapshotRow {
|
|
5234
|
-
readonly id: string;
|
|
5235
|
-
/** The whole {@link WorkspaceSnapshot} as one opaque JSON blob — read back as `unknown`, narrowed on `get`. */
|
|
5236
|
-
readonly snapshot: unknown;
|
|
5237
|
-
}
|
|
5238
|
-
|
|
5239
|
-
/**
|
|
5240
|
-
* The durable persistence seam for a {@link WorkspaceSnapshot} — three async primitives
|
|
5241
|
-
* (`get` / `set` / `delete`) keyed by a workspace id, mirroring the analogous
|
|
5242
|
-
* `WorkflowStoreInterface` in `@orkestrel/workflow` (and the driver-swap pattern a server
|
|
5243
|
-
* surface's session store would follow).
|
|
5244
|
-
*
|
|
5245
|
-
* @remarks
|
|
5246
|
-
* The store persists the {@link WorkspaceSnapshot} — the self-contained, pure-JSON workspace
|
|
5247
|
-
* state — so a JSON / SQLite / IndexedDB backend swaps in WITHOUT touching the manager or the
|
|
5248
|
-
* workspace: the in-memory default
|
|
5249
|
-
* {@link import('./workspaces/stores/MemoryWorkspaceStore.js').MemoryWorkspaceStore} and its
|
|
5250
|
-
* driver-pluggable twin
|
|
5251
|
-
* {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} (the
|
|
5252
|
-
* snapshot as one opaque JSON column) share THIS one interface. Hydration is NOT a store concern
|
|
5253
|
-
* — a {@link WorkspaceManagerInterface} reads a snapshot back and rebuilds the live workspace
|
|
5254
|
-
* through the constructor `seed` (see {@link WorkspaceManagerInterface.open} /
|
|
5255
|
-
* {@link WorkspaceManagerInterface.save}).
|
|
5256
|
-
*
|
|
5257
|
-
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
5258
|
-
* same shape as the memory one. The snapshot carries its OWN id, so `set` takes no separate id
|
|
5259
|
-
* param (mirroring the analogous `WorkflowStoreInterface.set` in `@orkestrel/workflow`). UNLIKE a
|
|
5260
|
-
* session store there is NO idle-TTL / eviction — a persisted workspace lives until an explicit
|
|
5261
|
-
* `delete`. It is concrete over {@link WorkspaceSnapshot} — no generic parameter (AGENTS §21
|
|
5262
|
-
* minimal-interface), since the snapshot is the ONE payload a workspace store persists.
|
|
5263
|
-
*/
|
|
5264
|
-
export declare interface WorkspaceStoreInterface {
|
|
5265
|
-
/**
|
|
5266
|
-
* Resolve the persisted snapshot for `id`, or `undefined` if none is stored.
|
|
5267
|
-
*
|
|
5268
|
-
* @param id - The workspace id to resolve (a {@link WorkspaceSnapshot.id})
|
|
5269
|
-
* @returns The persisted snapshot, or `undefined` if absent
|
|
5270
|
-
*/
|
|
5271
|
-
get(id: string): Promise<WorkspaceSnapshot | undefined>;
|
|
5272
|
-
/**
|
|
5273
|
-
* Insert or replace a snapshot under its own `snapshot.id` (no separate id param —
|
|
5274
|
-
* mirroring the analogous `WorkflowStoreInterface.set` in `@orkestrel/workflow`).
|
|
5275
|
-
*
|
|
5276
|
-
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
5277
|
-
*/
|
|
5278
|
-
set(snapshot: WorkspaceSnapshot): Promise<void>;
|
|
5279
|
-
/**
|
|
5280
|
-
* Drop a snapshot by id; an absent id is a no-op (no throw).
|
|
5281
|
-
*
|
|
5282
|
-
* @param id - The workspace id to drop
|
|
5283
|
-
*/
|
|
5284
|
-
delete(id: string): Promise<void>;
|
|
5285
|
-
}
|
|
5286
|
-
|
|
5287
3663
|
export { }
|