@orkestrel/agent 0.0.11 → 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 +73 -1616
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +81 -1716
- package/dist/src/core/index.d.ts +81 -1716
- package/dist/src/core/index.js +69 -1575
- 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
|
|
@@ -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`,
|
|
@@ -225,9 +231,13 @@ 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;
|
|
@@ -252,12 +262,13 @@ export declare interface AgentContextInterface {
|
|
|
252
262
|
*
|
|
253
263
|
* @remarks
|
|
254
264
|
* **The active workspace (rendered by carrier) — the SOLE document/image context.** When
|
|
255
|
-
* `workspaces.active` is set, its
|
|
265
|
+
* `workspaces.active` is set, its
|
|
266
|
+
* {@link import('@orkestrel/workspace').WorkspaceInterface.files} are filtered by
|
|
256
267
|
* `scope.files` (a three-way allow-list; `undefined` ⇒ all active files), then split by
|
|
257
|
-
* carrier: TEXT files ({@link import('
|
|
268
|
+
* carrier: TEXT files ({@link import('@orkestrel/workspace').isText}) render into a dedicated
|
|
258
269
|
* `## Workspace` section in the system block — each a fenced
|
|
259
270
|
* `` File: <path>\n```<language>\n<text>\n``` `` block — placed just after the instructions
|
|
260
|
-
* section;
|
|
271
|
+
* section; binary files whose MIME starts with `image/` have their base64 `data`
|
|
261
272
|
* attached to the LAST user message (a vision provider reads images off a user turn).
|
|
262
273
|
* ACTIVE-ONLY — never the other registered workspaces; with NO active workspace nothing is
|
|
263
274
|
* rendered for workspaces.
|
|
@@ -303,9 +314,10 @@ export declare interface AgentContextInterface {
|
|
|
303
314
|
* Options for `createAgentContext` — the richer context's configuration.
|
|
304
315
|
*
|
|
305
316
|
* @remarks
|
|
306
|
-
* `system` is the optional system prompt prepended to the turn's input. `
|
|
307
|
-
* `
|
|
308
|
-
*
|
|
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
|
|
309
321
|
* initial active filter applied at `build()` time (and at the loop's tool-advertise step); it
|
|
310
322
|
* defaults to `undefined` — no filtering — and can be changed through the context's `apply`
|
|
311
323
|
* method afterwards. `conversations` is the structural {@link ConversationManagerInterface} the
|
|
@@ -317,7 +329,10 @@ export declare interface AgentContextInterface {
|
|
|
317
329
|
*/
|
|
318
330
|
export declare interface AgentContextOptions {
|
|
319
331
|
readonly system?: string;
|
|
320
|
-
/**
|
|
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
|
+
*/
|
|
321
336
|
readonly tools?: ToolManagerInterface;
|
|
322
337
|
/** A pre-built instruction registry to reuse; an empty one is created when omitted. */
|
|
323
338
|
readonly instructions?: InstructionManagerInterface;
|
|
@@ -943,8 +958,8 @@ export declare type AgentStreamInterface = StreamInterface<AgentChunk, AgentResu
|
|
|
943
958
|
* (an ALLOWLIST — only matched rules that allow get through), pass an `allowed: false`
|
|
944
959
|
* `fallback`.
|
|
945
960
|
* - **Consulted before each tool call.** The agent loop calls `evaluate({ call })` for
|
|
946
|
-
* every {@link import('
|
|
947
|
-
* 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`
|
|
948
963
|
* chunk + a tool message) instead of being executed — no tool run, no budget cost —
|
|
949
964
|
* so the model sees the denial and can react.
|
|
950
965
|
* - **Synchronous now.** The async human-approval handshake (request / grant / deny) is
|
|
@@ -1049,37 +1064,6 @@ export declare interface AuthorityRule {
|
|
|
1049
1064
|
readonly reason?: string;
|
|
1050
1065
|
}
|
|
1051
1066
|
|
|
1052
|
-
/**
|
|
1053
|
-
* The binary MIME types a {@link FileContent} binary arm carries — the labels for a
|
|
1054
|
-
* base64-encoded payload.
|
|
1055
|
-
*
|
|
1056
|
-
* @remarks
|
|
1057
|
-
* Initialized to the four image MIMEs a vision-capable provider accepts; the union is OPEN
|
|
1058
|
-
* by design — a future binary MIME (e.g. `'application/pdf'`) slots in purely additively (a
|
|
1059
|
-
* new member), with nothing above it changed. {@link import('./helpers.js').isImage}
|
|
1060
|
-
* narrows a binary arm to an image by the `image/` prefix, so an image is just a binary with
|
|
1061
|
-
* an image MIME.
|
|
1062
|
-
*/
|
|
1063
|
-
export declare type BinaryMIME = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
|
|
1064
|
-
|
|
1065
|
-
/**
|
|
1066
|
-
* Project a {@link ToolResult} into the MCP `CallToolResult` shape — a top-level `error`
|
|
1067
|
-
* maps to a single `isError: true` text block (the failure reason), otherwise the `value`
|
|
1068
|
-
* is JSON-stringified into a single text block with no `isError`.
|
|
1069
|
-
*
|
|
1070
|
-
* @param result - The {@link ToolResult} to project (as returned by {@link import('./tools/ToolManager.js').ToolManager.execute})
|
|
1071
|
-
* @returns The equivalent {@link ToolCallResult}
|
|
1072
|
-
*
|
|
1073
|
-
* @example
|
|
1074
|
-
* ```ts
|
|
1075
|
-
* buildToolResult({ id: 'c1', name: 'search', error: 'max depth' })
|
|
1076
|
-
* // { content: [{ type: 'text', text: 'max depth' }], isError: true }
|
|
1077
|
-
* buildToolResult({ id: 'c1', name: 'search', value: { count: 1 } })
|
|
1078
|
-
* // { content: [{ type: 'text', text: '{"count":1}' }] }
|
|
1079
|
-
* ```
|
|
1080
|
-
*/
|
|
1081
|
-
export declare function buildToolResult(result: ToolResult): ToolCallResult;
|
|
1082
|
-
|
|
1083
1067
|
/**
|
|
1084
1068
|
* A minimal unbounded async channel — the eager pump WRITES chunks into it (`push`)
|
|
1085
1069
|
* and ends it (`close` / `fail`) regardless of consumption; a consumer READS them back
|
|
@@ -1100,47 +1084,6 @@ export declare class Channel<T> {
|
|
|
1100
1084
|
drain(): AsyncGenerator<T, void>;
|
|
1101
1085
|
}
|
|
1102
1086
|
|
|
1103
|
-
/**
|
|
1104
|
-
* Clamp a 1-based {@link Position} to the bounds of `text` — every component pinned into a
|
|
1105
|
-
* caret that actually exists in the content.
|
|
1106
|
-
*
|
|
1107
|
-
* @remarks
|
|
1108
|
-
* `line` is pinned to `[1, lineCount]` and `column` to `[1, lineLength + 1]` of the
|
|
1109
|
-
* resolved line (column `lineLength + 1` is the caret just past the line's last
|
|
1110
|
-
* character). So a position beyond the end of the text resolves to the end rather than
|
|
1111
|
-
* overflowing. Total — never throws.
|
|
1112
|
-
*
|
|
1113
|
-
* @param text - The text the position addresses
|
|
1114
|
-
* @param position - The 1-based position to clamp
|
|
1115
|
-
* @returns The clamped {@link Position}
|
|
1116
|
-
*
|
|
1117
|
-
* @example
|
|
1118
|
-
* ```ts
|
|
1119
|
-
* clampPosition('ab\ncd', { line: 9, column: 9 }) // { line: 2, column: 3 } (end of 'cd')
|
|
1120
|
-
* ```
|
|
1121
|
-
*/
|
|
1122
|
-
export declare function clampPosition(text: string, position: Position): Position;
|
|
1123
|
-
|
|
1124
|
-
/**
|
|
1125
|
-
* Clamp both ends of a {@link Range} to the bounds of `text` — the actual span a ranged
|
|
1126
|
-
* read / write applies (and the `range` a {@link import('./types.js').ReadResult} reports).
|
|
1127
|
-
*
|
|
1128
|
-
* @remarks
|
|
1129
|
-
* Clamps `start` and `end` independently via {@link clampPosition}, so a range reaching
|
|
1130
|
-
* past the end of the content is trimmed to the content's end. Total — never throws.
|
|
1131
|
-
*
|
|
1132
|
-
* @param text - The text the range addresses
|
|
1133
|
-
* @param range - The 1-based range to clamp
|
|
1134
|
-
* @returns The clamped {@link Range}
|
|
1135
|
-
*
|
|
1136
|
-
* @example
|
|
1137
|
-
* ```ts
|
|
1138
|
-
* clampRange('ab\ncd', { start: { line: 1, column: 1 }, end: { line: 9, column: 9 } })
|
|
1139
|
-
* // { start: { line: 1, column: 1 }, end: { line: 2, column: 3 } }
|
|
1140
|
-
* ```
|
|
1141
|
-
*/
|
|
1142
|
-
export declare function clampRange(text: string, range: Range): Range;
|
|
1143
|
-
|
|
1144
1087
|
/**
|
|
1145
1088
|
* The PER-RUN auto-compaction state threaded through an {@link AgentInterface}'s loop —
|
|
1146
1089
|
* a tiny immutable value replaced within a holder created fresh per run (so no state leaks across runs or a
|
|
@@ -1176,28 +1119,6 @@ export declare interface CompactOptions {
|
|
|
1176
1119
|
readonly sections?: number;
|
|
1177
1120
|
}
|
|
1178
1121
|
|
|
1179
|
-
/**
|
|
1180
|
-
* Compute the byte size of a {@link FileContent} — the `size` a {@link FileInterface} derives
|
|
1181
|
-
* once when built.
|
|
1182
|
-
*
|
|
1183
|
-
* @remarks
|
|
1184
|
-
* Dispatches on {@link isText}: a text arm is its UTF-8 byte length (via `new
|
|
1185
|
-
* TextEncoder().encode(text).length` — the standard Web/Node API, so a multi-byte
|
|
1186
|
-
* character like `'é'` or `'😀'` counts as its real encoded bytes, NOT its character
|
|
1187
|
-
* count); a binary arm is the decoded payload byte length of its base64 `data` (via
|
|
1188
|
-
* {@link decodedSize}, computed arithmetically — no `atob` / `Buffer`). Total — never throws.
|
|
1189
|
-
*
|
|
1190
|
-
* @param content - The file content to size
|
|
1191
|
-
* @returns The byte size (UTF-8 bytes for text; decoded payload bytes for binary)
|
|
1192
|
-
*
|
|
1193
|
-
* @example
|
|
1194
|
-
* ```ts
|
|
1195
|
-
* computeSize({ text: 'café', language: 'text' }) // 5 (é is two bytes)
|
|
1196
|
-
* computeSize({ data: 'AAAA', mime: 'image/png' }) // 3
|
|
1197
|
-
* ```
|
|
1198
|
-
*/
|
|
1199
|
-
export declare function computeSize(content: FileContent): number;
|
|
1200
|
-
|
|
1201
1122
|
/**
|
|
1202
1123
|
* A provider's OPTIONAL context-framing default, keyed by section kind — the framing a
|
|
1203
1124
|
* model prefers (e.g. XML tags vs. Markdown headers), declared by a
|
|
@@ -1408,7 +1329,8 @@ export declare type ConversationEventMap = {
|
|
|
1408
1329
|
* (initial {@link ConversationEventMap} listeners). `snapshot` is
|
|
1409
1330
|
* the construction-time hydration seam — a {@link ConversationSnapshot} whose `id` / `summary` /
|
|
1410
1331
|
* `sections` / live tail are RESTORED into the new conversation (the live `summarize` / `keep` /
|
|
1411
|
-
* `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
|
|
1412
1334
|
* {@link ConversationManagerInterface.open} reads a stored snapshot back through; hydration is
|
|
1413
1335
|
* silent (no events). When both `snapshot.id` and `id` are given, `snapshot.id` wins (the snapshot
|
|
1414
1336
|
* IS the conversation's identity).
|
|
@@ -1422,7 +1344,7 @@ export declare interface ConversationInput {
|
|
|
1422
1344
|
/** Overrides the manager's default `sections` cap for this conversation. */
|
|
1423
1345
|
readonly sections?: number;
|
|
1424
1346
|
readonly on?: EmitterHooks<ConversationEventMap>;
|
|
1425
|
-
/** A {@link ConversationSnapshot} to hydrate
|
|
1347
|
+
/** A {@link ConversationSnapshot} to hydrate from, analogous to the workspace package's seed input. */
|
|
1426
1348
|
readonly snapshot?: ConversationSnapshot;
|
|
1427
1349
|
}
|
|
1428
1350
|
|
|
@@ -1598,8 +1520,9 @@ export declare interface ConversationInterface {
|
|
|
1598
1520
|
*
|
|
1599
1521
|
* @remarks
|
|
1600
1522
|
* The container serializes ITSELF (`{ id, summary, sections, messages: this.messages() }`) — the
|
|
1601
|
-
* {@link ConversationStoreInterface} persistence seam's payload, the
|
|
1602
|
-
* {@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
|
|
1603
1526
|
* CONFIG re-supplied on hydrate (a `ConversationSummarizer` is a function, not data). The snapshot
|
|
1604
1527
|
* is the durable analogue of the constructor `seed`: a {@link ConversationManagerInterface}
|
|
1605
1528
|
* HYDRATES a conversation from it through that seam (see {@link ConversationManagerInterface.open}).
|
|
@@ -1615,7 +1538,7 @@ export declare interface ConversationInterface {
|
|
|
1615
1538
|
* The registry of {@link Conversation}s keyed by `id`, in insertion order, WITH an active pointer
|
|
1616
1539
|
* — the §9 store over the conversation layer PLUS the `active` / `switch` seam the
|
|
1617
1540
|
* {@link import('../AgentContext.js').AgentContext} renders. Event-free (a registry, like
|
|
1618
|
-
* {@link import('
|
|
1541
|
+
* {@link import('@orkestrel/workspace').WorkspaceManager}); the observability lives
|
|
1619
1542
|
* on each {@link Conversation}.
|
|
1620
1543
|
*
|
|
1621
1544
|
* @remarks
|
|
@@ -1665,7 +1588,7 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1665
1588
|
* A registry of {@link ConversationInterface}s keyed by their `id`, in insertion order, WITH an
|
|
1666
1589
|
* active pointer — the §9 store over the conversation layer PLUS the `active` / `switch` seam the
|
|
1667
1590
|
* {@link AgentContextInterface} renders. Event-free (a registry, like
|
|
1668
|
-
* {@link WorkspaceManagerInterface}); the observability lives on each
|
|
1591
|
+
* {@link import('@orkestrel/workspace').WorkspaceManagerInterface}); the observability lives on each
|
|
1669
1592
|
* {@link ConversationInterface}.
|
|
1670
1593
|
*
|
|
1671
1594
|
* @remarks
|
|
@@ -1688,8 +1611,8 @@ export declare class ConversationManager implements ConversationManagerInterface
|
|
|
1688
1611
|
* miss (rebuilding it through the constructor `seed` from the snapshot, flowing the manager's
|
|
1689
1612
|
* default `summarize` / `keep` in) and `save(id)` PERSISTS a registered conversation's
|
|
1690
1613
|
* {@link ConversationInterface.snapshot}. Both are LENIENT without a store — `open` resolves only
|
|
1691
|
-
* registered ids, `save` is a no-op (`false`) — consistent with the lenient `switch`.
|
|
1692
|
-
*
|
|
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.
|
|
1693
1616
|
* - **Event-free.** A purely registry store — no Emitter, no events (each conversation owns
|
|
1694
1617
|
* its own).
|
|
1695
1618
|
*/
|
|
@@ -1760,8 +1683,8 @@ export declare interface ConversationManagerOptions {
|
|
|
1760
1683
|
* {@link ConversationManagerInterface.open} / {@link ConversationManagerInterface.save} — a memory
|
|
1761
1684
|
* / JSON / SQLite / IndexedDB store a conversation is HYDRATED from (`open` a registry-miss) and
|
|
1762
1685
|
* PERSISTED to (`save`). Omitted ⇒ the manager is registry-only: `open` resolves only what is
|
|
1763
|
-
* already registered, and `save` is a no-op (`false`). The
|
|
1764
|
-
* {@link WorkspaceManagerOptions
|
|
1686
|
+
* already registered, and `save` is a no-op (`false`). The exact analogue of
|
|
1687
|
+
* {@link import('@orkestrel/workspace').WorkspaceManagerOptions}'s `store`.
|
|
1765
1688
|
*/
|
|
1766
1689
|
readonly store?: ConversationStoreInterface;
|
|
1767
1690
|
}
|
|
@@ -1827,7 +1750,8 @@ export declare interface ConversationReferenceOptions {
|
|
|
1827
1750
|
/**
|
|
1828
1751
|
* A JSON-serializable snapshot of a conversation's state — its `id`, the rollup `summary`, the
|
|
1829
1752
|
* compacted `sections`, and the live tail `messages` — the durable payload the
|
|
1830
|
-
* {@link ConversationStoreInterface} persists. The
|
|
1753
|
+
* {@link ConversationStoreInterface} persists. The exact analogue of
|
|
1754
|
+
* {@link import('@orkestrel/workspace').WorkspaceSnapshot}.
|
|
1831
1755
|
*
|
|
1832
1756
|
* @remarks
|
|
1833
1757
|
* Pure JSON DATA (no class instances, no functions): each {@link SectionInterface} and
|
|
@@ -1856,12 +1780,13 @@ export declare interface ConversationSnapshot {
|
|
|
1856
1780
|
* One row of the table a
|
|
1857
1781
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
1858
1782
|
* persists — a conversation `id` plus its {@link ConversationSnapshot} held as ONE OPAQUE JSON
|
|
1859
|
-
* column. The
|
|
1783
|
+
* column. The exact analogue of {@link import('@orkestrel/workspace').WorkspaceSnapshotRow}.
|
|
1860
1784
|
*
|
|
1861
1785
|
* @remarks
|
|
1862
1786
|
* The Database twin of {@link ConversationStoreInterface} stores the snapshot whole (the `snapshot`
|
|
1863
|
-
* column is a `rawShape`, an opaque JSON blob — exactly as
|
|
1864
|
-
* 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
|
|
1865
1790
|
* forces the contract to `Infer` it. The column therefore reads back as the broad `unknown`; the
|
|
1866
1791
|
* store narrows it to a {@link ConversationSnapshot} on `get`
|
|
1867
1792
|
* ({@link import('./helpers.js').isConversationSnapshot}, the AGENTS §14 boundary narrow). `id`
|
|
@@ -1876,8 +1801,8 @@ export declare interface ConversationSnapshotRow {
|
|
|
1876
1801
|
|
|
1877
1802
|
/**
|
|
1878
1803
|
* The durable persistence seam for a {@link ConversationSnapshot} — three async primitives
|
|
1879
|
-
* (`get` / `set` / `delete`) keyed by a conversation id, the
|
|
1880
|
-
* {@link WorkspaceStoreInterface}.
|
|
1804
|
+
* (`get` / `set` / `delete`) keyed by a conversation id, the exact analogue of
|
|
1805
|
+
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}.
|
|
1881
1806
|
*
|
|
1882
1807
|
* @remarks
|
|
1883
1808
|
* The store persists the {@link ConversationSnapshot} — the self-contained, pure-JSON conversation
|
|
@@ -1893,7 +1818,9 @@ export declare interface ConversationSnapshotRow {
|
|
|
1893
1818
|
*
|
|
1894
1819
|
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
1895
1820
|
* same shape as the memory one. The snapshot carries its OWN id, so `set` takes no separate id
|
|
1896
|
-
* param (mirroring
|
|
1821
|
+
* param (mirroring
|
|
1822
|
+
* {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`). UNLIKE a session store
|
|
1823
|
+
* there is NO idle-TTL
|
|
1897
1824
|
* / eviction — a persisted conversation lives until an explicit `delete`. It is concrete over
|
|
1898
1825
|
* {@link ConversationSnapshot} — no generic parameter (AGENTS §21 minimal-interface), since the
|
|
1899
1826
|
* snapshot is the ONE payload a conversation store persists.
|
|
@@ -1908,7 +1835,7 @@ export declare interface ConversationStoreInterface {
|
|
|
1908
1835
|
get(id: string): Promise<ConversationSnapshot | undefined>;
|
|
1909
1836
|
/**
|
|
1910
1837
|
* Insert or replace a snapshot under its own `snapshot.id` (no separate id param —
|
|
1911
|
-
* mirroring {@link WorkspaceStoreInterface
|
|
1838
|
+
* mirroring {@link import('@orkestrel/workspace').WorkspaceStoreInterface}'s `set`).
|
|
1912
1839
|
*
|
|
1913
1840
|
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
1914
1841
|
*/
|
|
@@ -1939,28 +1866,6 @@ export declare interface ConversationStoreInterface {
|
|
|
1939
1866
|
*/
|
|
1940
1867
|
export declare type ConversationSummarizer = (messages: readonly MessageInterface[]) => Promise<string>;
|
|
1941
1868
|
|
|
1942
|
-
/**
|
|
1943
|
-
* Count the lines of a {@link FileContent} — the `lines` a {@link FileInterface} derives once
|
|
1944
|
-
* when built.
|
|
1945
|
-
*
|
|
1946
|
-
* @remarks
|
|
1947
|
-
* A text arm's line count is `0` for the empty string, otherwise one more than the
|
|
1948
|
-
* number of newline (`\n`) separators it contains — so `'a'` is one line, `'a\nb'` is two,
|
|
1949
|
-
* and a trailing newline `'a\n'` counts the empty final line as two. A binary arm has no
|
|
1950
|
-
* lines and returns `0`. Total — never throws.
|
|
1951
|
-
*
|
|
1952
|
-
* @param content - The file content to count lines for
|
|
1953
|
-
* @returns The line count (text line count; `0` for a binary arm or empty text)
|
|
1954
|
-
*
|
|
1955
|
-
* @example
|
|
1956
|
-
* ```ts
|
|
1957
|
-
* countLines({ text: '', language: 'text' }) // 0
|
|
1958
|
-
* countLines({ text: 'a\nb\nc', language: 'text' }) // 3
|
|
1959
|
-
* countLines({ data: 'AAAA', mime: 'image/png' }) // 0
|
|
1960
|
-
* ```
|
|
1961
|
-
*/
|
|
1962
|
-
export declare function countLines(content: FileContent): number;
|
|
1963
|
-
|
|
1964
1869
|
/**
|
|
1965
1870
|
* Create an agent loop — an {@link AgentInterface} composing a
|
|
1966
1871
|
* {@link ProviderInterface}, its {@link AgentContextInterface}, and a tool registry
|
|
@@ -2095,8 +2000,9 @@ export declare function createAgentQueue(options: AgentQueueOptions): QueueInter
|
|
|
2095
2000
|
*
|
|
2096
2001
|
* @example
|
|
2097
2002
|
* ```ts
|
|
2003
|
+
* import { createAgentRegistry } from '@src/core'
|
|
2098
2004
|
* import type { ProviderInterface } from '@src/core'
|
|
2099
|
-
* import {
|
|
2005
|
+
* import { createTool } from '@orkestrel/tool'
|
|
2100
2006
|
*
|
|
2101
2007
|
* declare const provider: ProviderInterface // any concrete implementation supplied by the host app
|
|
2102
2008
|
* const registry = createAgentRegistry({
|
|
@@ -2177,24 +2083,6 @@ export declare function createAgentRunner(options: AgentRunnerOptions): RunnerIn
|
|
|
2177
2083
|
*/
|
|
2178
2084
|
export declare function createAuthority(options?: AuthorityOptions): AuthorityInterface;
|
|
2179
2085
|
|
|
2180
|
-
/**
|
|
2181
|
-
* Build the BINARY {@link FileContent} arm — the §4.2.3 split constructor for binary (a
|
|
2182
|
-
* separate function per arm, not one constructor dispatching on a discriminator parameter).
|
|
2183
|
-
* An image is just a binary with an image {@link BinaryMIME}.
|
|
2184
|
-
*
|
|
2185
|
-
* @param data - The base64-encoded binary payload
|
|
2186
|
-
* @param mime - The {@link BinaryMIME} that labels the payload
|
|
2187
|
-
* @returns A `{ data; mime }` content arm
|
|
2188
|
-
*
|
|
2189
|
-
* @example
|
|
2190
|
-
* ```ts
|
|
2191
|
-
* import { createBinaryContent } from '@src/core'
|
|
2192
|
-
*
|
|
2193
|
-
* createBinaryContent('<base64>', 'image/png') // { data: '<base64>', mime: 'image/png' }
|
|
2194
|
-
* ```
|
|
2195
|
-
*/
|
|
2196
|
-
export declare function createBinaryContent(data: string, mime: BinaryMIME): FileContent;
|
|
2197
|
-
|
|
2198
2086
|
/**
|
|
2199
2087
|
* Create a conversation — a {@link ConversationInterface} grouping messages above a flat
|
|
2200
2088
|
* message store it OWNS DIRECTLY, with compaction into summarized sections, a regenerated
|
|
@@ -2266,12 +2154,14 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2266
2154
|
/**
|
|
2267
2155
|
* Create a {@link DatabaseConversationStore} over any {@link DriverInterface} — the durable,
|
|
2268
2156
|
* driver-pluggable backing for the conversation persistence seam, the opt-in twin of
|
|
2269
|
-
* {@link createMemoryConversationStore}. The
|
|
2157
|
+
* {@link createMemoryConversationStore}. The exact twin of
|
|
2158
|
+
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore}.
|
|
2270
2159
|
*
|
|
2271
2160
|
* @remarks
|
|
2272
2161
|
* Builds a one-table database (`conversations`, keyed by `id`) over the supplied driver, the snapshot
|
|
2273
2162
|
* held as ONE OPAQUE JSON COLUMN — the column map is `{ id; snapshot }` where `snapshot` is a
|
|
2274
|
-
* `rawShape` (a JSON blob), exactly as
|
|
2163
|
+
* `rawShape` (a JSON blob), exactly as
|
|
2164
|
+
* {@link import('@orkestrel/workspace').createDatabaseWorkspaceStore} stores its snapshot. The
|
|
2275
2165
|
* snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
2276
2166
|
* AND keeps the row type FLAT (the column reads back as `unknown`, narrowed on `get` by
|
|
2277
2167
|
* {@link import('./helpers.js').isConversationSnapshot}). The `driver` DEFAULTS to
|
|
@@ -2296,65 +2186,6 @@ export declare function createConversationManager(options?: ConversationManagerO
|
|
|
2296
2186
|
*/
|
|
2297
2187
|
export declare function createDatabaseConversationStore(driver?: DriverInterface): ConversationStoreInterface;
|
|
2298
2188
|
|
|
2299
|
-
/**
|
|
2300
|
-
* Create a {@link DatabaseWorkspaceStore} over any {@link DriverInterface} — the durable,
|
|
2301
|
-
* driver-pluggable backing for the workspace persistence seam, the opt-in twin of
|
|
2302
|
-
* {@link createMemoryWorkspaceStore}.
|
|
2303
|
-
*
|
|
2304
|
-
* @remarks
|
|
2305
|
-
* Builds a one-table database (`workspaces`, keyed by `id`) over the supplied driver, the snapshot
|
|
2306
|
-
* held as ONE OPAQUE JSON COLUMN — the column map is `{ id; snapshot }` where `snapshot` is a
|
|
2307
|
-
* `rawShape` (a JSON blob), exactly as
|
|
2308
|
-
* the analogous `createDatabaseWorkflowStore` in `@orkestrel/workflow` stores its snapshot. The
|
|
2309
|
-
* snapshot is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless
|
|
2310
|
-
* AND keeps the row type FLAT (the column reads back as `unknown`, narrowed on `get` by
|
|
2311
|
-
* {@link import('./helpers.js').isWorkspaceSnapshot}). The `driver` DEFAULTS to
|
|
2312
|
-
* {@link createMemoryDriver}, so the store ALSO works in memory out of the box; pass a server
|
|
2313
|
-
* `createJSONDriver` / `createSQLiteDriver` (or a browser IndexedDB driver) for a persistent one —
|
|
2314
|
-
* the durability is the driver's job, the store engine is shared. It swaps in behind
|
|
2315
|
-
* {@link WorkspaceStoreInterface} WITHOUT touching the manager or the workspace.
|
|
2316
|
-
*
|
|
2317
|
-
* @param driver - The storage backend the snapshots persist to (defaults to {@link createMemoryDriver})
|
|
2318
|
-
* @returns A {@link WorkspaceStoreInterface} over the driver
|
|
2319
|
-
*
|
|
2320
|
-
* @example
|
|
2321
|
-
* ```ts
|
|
2322
|
-
* import { createDatabaseWorkspaceStore, createMemoryDriver, createWorkspaceManager } from '@src/core'
|
|
2323
|
-
*
|
|
2324
|
-
* const store = createDatabaseWorkspaceStore(createMemoryDriver()) // a durable driver swaps in here
|
|
2325
|
-
* const manager = createWorkspaceManager({ store })
|
|
2326
|
-
* const workspace = manager.add()
|
|
2327
|
-
* workspace.write('notes.txt', 'hello')
|
|
2328
|
-
* await manager.save(workspace.id) // persist the workspace (one JSON column)
|
|
2329
|
-
* ```
|
|
2330
|
-
*/
|
|
2331
|
-
export declare function createDatabaseWorkspaceStore(driver?: DriverInterface): WorkspaceStoreInterface;
|
|
2332
|
-
|
|
2333
|
-
/**
|
|
2334
|
-
* Create a file — an immutable {@link FileInterface} from its `path` + {@link FileContent}
|
|
2335
|
-
* and optional {@link import('./types.js').FileState}, with `size` / `lines` DERIVED from the
|
|
2336
|
-
* content.
|
|
2337
|
-
*
|
|
2338
|
-
* @remarks
|
|
2339
|
-
* Returns a PLAIN `Object.freeze`d record (NOT a class instance) — the `path` IS its identity
|
|
2340
|
-
* (there is no `id`). Only `path` / `content` are required; `state` defaults to `'created'`
|
|
2341
|
-
* when omitted. `size` (via {@link computeSize}) and `lines` (via {@link countLines}) are
|
|
2342
|
-
* computed from the content here (so they never drift from it). Frozen + plain, so it
|
|
2343
|
-
* `structuredClone`s losslessly and is never mutated after creation.
|
|
2344
|
-
*
|
|
2345
|
-
* @param input - `path` / `content` (required) and an optional `state` (see {@link FileInput})
|
|
2346
|
-
* @returns A frozen {@link FileInterface} record
|
|
2347
|
-
*
|
|
2348
|
-
* @example
|
|
2349
|
-
* ```ts
|
|
2350
|
-
* import { createFile, createTextContent } from '@src/core'
|
|
2351
|
-
*
|
|
2352
|
-
* const file = createFile({ path: 'src/main.ts', content: createTextContent('const x = 1', 'typescript') })
|
|
2353
|
-
* file.lines // 1
|
|
2354
|
-
* ```
|
|
2355
|
-
*/
|
|
2356
|
-
export declare function createFile(input: FileInput): FileInterface;
|
|
2357
|
-
|
|
2358
2189
|
/**
|
|
2359
2190
|
* Create an instruction — an immutable {@link InstructionInterface} (a named directive)
|
|
2360
2191
|
* from its `name` / `content` and optional `priority`, the `id` minted at construction.
|
|
@@ -2411,11 +2242,13 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2411
2242
|
* Create the in-memory conversation store — a {@link ConversationStoreInterface} backed by a
|
|
2412
2243
|
* process-lifetime `Map` of {@link import('./types.js').ConversationSnapshot}s keyed by conversation
|
|
2413
2244
|
* id, the DEFAULT backing for the durable {@link ConversationManagerInterface.open} /
|
|
2414
|
-
* {@link ConversationManagerInterface.save} seam. The
|
|
2245
|
+
* {@link ConversationManagerInterface.save} seam. The exact twin of
|
|
2246
|
+
* {@link import('@orkestrel/workspace').createMemoryWorkspaceStore}.
|
|
2415
2247
|
*
|
|
2416
2248
|
* @remarks
|
|
2417
2249
|
* A plain `Map` (the snapshot is already pure JSON, so no encoding is needed for the memory tier),
|
|
2418
|
-
* the structural twin of {@link createMemoryWorkspaceStore}.
|
|
2250
|
+
* the structural twin of {@link import('@orkestrel/workspace').createMemoryWorkspaceStore}.
|
|
2251
|
+
* `get` / `set` / `delete` are async (the
|
|
2419
2252
|
* same shape a durable backend fits); UNLIKE a session store there is NO idle-TTL / eviction — a
|
|
2420
2253
|
* persisted conversation lives until an explicit `delete`. Its driver-pluggable twin is
|
|
2421
2254
|
* {@link createDatabaseConversationStore} (the snapshot as one opaque JSON column over a `databases`
|
|
@@ -2439,37 +2272,6 @@ export declare function createInstructionManager(options?: InstructionManagerOpt
|
|
|
2439
2272
|
*/
|
|
2440
2273
|
export declare function createMemoryConversationStore(): ConversationStoreInterface;
|
|
2441
2274
|
|
|
2442
|
-
/**
|
|
2443
|
-
* Create the in-memory workspace store — a {@link WorkspaceStoreInterface} backed by a
|
|
2444
|
-
* process-lifetime `Map` of {@link import('./types.js').WorkspaceSnapshot}s keyed by workspace id,
|
|
2445
|
-
* the DEFAULT backing for the durable {@link WorkspaceManagerInterface.open} /
|
|
2446
|
-
* {@link WorkspaceManagerInterface.save} seam.
|
|
2447
|
-
*
|
|
2448
|
-
* @remarks
|
|
2449
|
-
* A plain `Map` (the snapshot is already pure JSON, so no encoding is needed for the memory tier),
|
|
2450
|
-
* the structural twin of the analogous `createMemoryWorkflowStore` in `@orkestrel/workflow`.
|
|
2451
|
-
* `get` / `set` / `delete` are async (the same shape a durable backend fits); UNLIKE a session
|
|
2452
|
-
* store there is NO idle-TTL / eviction — a persisted workspace lives until an explicit `delete`.
|
|
2453
|
-
* Its driver-pluggable twin is {@link createDatabaseWorkspaceStore} (the snapshot as one opaque
|
|
2454
|
-
* JSON column over a `databases` table) — for a DURABLE store pass it a JSON / SQLite / IndexedDB
|
|
2455
|
-
* driver, and it swaps in WITHOUT touching the manager or the workspace. Hydration stays a manager
|
|
2456
|
-
* concern: read a snapshot back and rebuild the live workspace through the constructor `seed`.
|
|
2457
|
-
*
|
|
2458
|
-
* @returns A memory-backed {@link WorkspaceStoreInterface}
|
|
2459
|
-
*
|
|
2460
|
-
* @example
|
|
2461
|
-
* ```ts
|
|
2462
|
-
* import { createMemoryWorkspaceStore, createWorkspaceManager } from '@src/core'
|
|
2463
|
-
*
|
|
2464
|
-
* const store = createMemoryWorkspaceStore()
|
|
2465
|
-
* const manager = createWorkspaceManager({ store })
|
|
2466
|
-
* const workspace = manager.add()
|
|
2467
|
-
* workspace.write('notes.txt', 'hello')
|
|
2468
|
-
* await manager.save(workspace.id) // persist the workspace
|
|
2469
|
-
* ```
|
|
2470
|
-
*/
|
|
2471
|
-
export declare function createMemoryWorkspaceStore(): WorkspaceStoreInterface;
|
|
2472
|
-
|
|
2473
2275
|
/**
|
|
2474
2276
|
* Create a named scope — an immutable {@link ScopeInterface} from its `name` and the four
|
|
2475
2277
|
* optional per-category allow-lists, the `id` minted at construction.
|
|
@@ -2519,23 +2321,6 @@ export declare function createScope(input: ScopeInput): ScopeInterface;
|
|
|
2519
2321
|
*/
|
|
2520
2322
|
export declare function createScopeManager(options?: ScopeManagerOptions): ScopeManagerInterface;
|
|
2521
2323
|
|
|
2522
|
-
/**
|
|
2523
|
-
* Build the TEXT {@link FileContent} arm — the §4.2.3 split constructor for text (a separate
|
|
2524
|
-
* function per arm, not one constructor dispatching on a discriminator parameter).
|
|
2525
|
-
*
|
|
2526
|
-
* @param text - The literal text body
|
|
2527
|
-
* @param language - The fenced-code language the text renders as (e.g. `'typescript'`)
|
|
2528
|
-
* @returns A `{ text; language }` content arm
|
|
2529
|
-
*
|
|
2530
|
-
* @example
|
|
2531
|
-
* ```ts
|
|
2532
|
-
* import { createTextContent } from '@src/core'
|
|
2533
|
-
*
|
|
2534
|
-
* createTextContent('const x = 1', 'typescript') // { text: 'const x = 1', language: 'typescript' }
|
|
2535
|
-
* ```
|
|
2536
|
-
*/
|
|
2537
|
-
export declare function createTextContent(text: string, language: string): FileContent;
|
|
2538
|
-
|
|
2539
2324
|
/**
|
|
2540
2325
|
* Create a stream-stateful `<think>` separator — a {@link ThinkSplitterInterface} that
|
|
2541
2326
|
* splits a thinking model's in-content `<think>…</think>` reasoning spans away from
|
|
@@ -2565,122 +2350,12 @@ export declare function createTextContent(text: string, language: string): FileC
|
|
|
2565
2350
|
*/
|
|
2566
2351
|
export declare function createThinkSplitter(): ThinkSplitterInterface;
|
|
2567
2352
|
|
|
2568
|
-
/**
|
|
2569
|
-
* Create a tool — a {@link ToolInterface} binding a {@link ToolDefinition} schema
|
|
2570
|
-
* (the `name` / `description` / `parameters` the model sees) to the `execute` handler
|
|
2571
|
-
* that runs a call.
|
|
2572
|
-
*
|
|
2573
|
-
* @remarks
|
|
2574
|
-
* Only `name` is required (it keys the tool in a {@link ToolManagerInterface} and is
|
|
2575
|
-
* what the model calls); `description` / `parameters` are the optional JSON-Schema the
|
|
2576
|
-
* provider advertises (forwarded verbatim). The handler's `args` is the model-supplied
|
|
2577
|
-
* `unknown` arguments record — narrow it inside (§14); a `createToolManager` registry
|
|
2578
|
-
* isolates a throw into a `ToolResult.error`.
|
|
2579
|
-
*
|
|
2580
|
-
* @param options - `name` (required), optional `description` / `parameters`, and the
|
|
2581
|
-
* `execute` handler (see {@link ToolOptions})
|
|
2582
|
-
* @returns A working {@link ToolInterface}
|
|
2583
|
-
*
|
|
2584
|
-
* @example
|
|
2585
|
-
* ```ts
|
|
2586
|
-
* import { createTool } from '@src/core'
|
|
2587
|
-
*
|
|
2588
|
-
* const add = createTool({
|
|
2589
|
-
* name: 'add',
|
|
2590
|
-
* description: 'Add two numbers',
|
|
2591
|
-
* execute: (args) => Number(args.a) + Number(args.b),
|
|
2592
|
-
* })
|
|
2593
|
-
* ```
|
|
2594
|
-
*/
|
|
2595
|
-
export declare function createTool(options: ToolOptions): ToolInterface;
|
|
2596
|
-
|
|
2597
|
-
/**
|
|
2598
|
-
* Create a tool registry — a {@link ToolManagerInterface} that resolves tool names,
|
|
2599
|
-
* lists {@link ToolDefinition}s for the provider, and executes calls with per-call
|
|
2600
|
-
* error isolation.
|
|
2601
|
-
*
|
|
2602
|
-
* @remarks
|
|
2603
|
-
* Starts empty; `add` registers one tool or a batch (§9.2), `definitions()` yields the
|
|
2604
|
-
* schemas to hand a provider, and `execute` runs a {@link ToolCall} (or a batch),
|
|
2605
|
-
* ALWAYS resolving a {@link ToolResult} — a handler throw becomes an `error` result and
|
|
2606
|
-
* an unknown name a not-found `error`, so a tool throw never escapes and a batch never
|
|
2607
|
-
* fails as a whole.
|
|
2608
|
-
*
|
|
2609
|
-
* @returns An empty {@link ToolManagerInterface}
|
|
2610
|
-
*
|
|
2611
|
-
* @example
|
|
2612
|
-
* ```ts
|
|
2613
|
-
* import { createTool, createToolManager } from '@src/core'
|
|
2614
|
-
*
|
|
2615
|
-
* const tools = createToolManager()
|
|
2616
|
-
* tools.add(createTool({ name: 'add', execute: (a) => Number(a.x) + Number(a.y) }))
|
|
2617
|
-
* const result = await tools.execute({ id: '1', name: 'add', arguments: { x: 1, y: 2 } })
|
|
2618
|
-
* ```
|
|
2619
|
-
*/
|
|
2620
|
-
export declare function createToolManager(): ToolManagerInterface;
|
|
2621
|
-
|
|
2622
|
-
/**
|
|
2623
|
-
* Create a workspace — a mutable, `path`-keyed working set of immutable
|
|
2624
|
-
* {@link FileInterface}s with the in-memory edit surface (read / write / search / replace /
|
|
2625
|
-
* move / remove), observable through its `EmitterInterface` (from `@orkestrel/emitter`).
|
|
2626
|
-
*
|
|
2627
|
-
* @param options - Optional initial {@link import('./types.js').WorkspaceEventMap} listeners (`on`) and the emitter's `error` handler (see {@link WorkspaceOptions})
|
|
2628
|
-
* @returns A working {@link WorkspaceInterface}
|
|
2629
|
-
*
|
|
2630
|
-
* @example
|
|
2631
|
-
* ```ts
|
|
2632
|
-
* import { createWorkspace } from '@src/core'
|
|
2633
|
-
*
|
|
2634
|
-
* const workspace = createWorkspace({ on: { write: (file) => console.log(file.path) } })
|
|
2635
|
-
* workspace.write('src/main.ts', 'const x = 1')
|
|
2636
|
-
* workspace.file('src/main.ts')?.state // 'created'
|
|
2637
|
-
* ```
|
|
2638
|
-
*/
|
|
2639
|
-
export declare function createWorkspace(options?: WorkspaceOptions): WorkspaceInterface;
|
|
2640
|
-
|
|
2641
|
-
/**
|
|
2642
|
-
* Create a workspace registry — a {@link WorkspaceManagerInterface} holding
|
|
2643
|
-
* {@link WorkspaceInterface}s keyed by their `id` (in insertion order) WITH an active pointer:
|
|
2644
|
-
* the §9 store over the workspace layer plus the `active` / `switch` seam the context renders.
|
|
2645
|
-
*
|
|
2646
|
-
* @remarks
|
|
2647
|
-
* Starts empty; `add(input?)` mints a {@link WorkspaceInterface} (its `id` from the input or a
|
|
2648
|
-
* random UUID), flowing the manager's default `on` / `error` in unless the input overrides them,
|
|
2649
|
-
* and stores it (an already-present `id` overwrites — last write wins) — and AUTO-ACTIVATES the
|
|
2650
|
-
* FIRST one (a registry with workspaces always has one `active`); a later `add` leaves `active`
|
|
2651
|
-
* unchanged. `switch(id)` re-points `active` (an unknown `id` returns `undefined`, leaving
|
|
2652
|
-
* `active` unchanged — lenient, never throws); `workspace(id)` / `workspaces()` look up;
|
|
2653
|
-
* `remove` (one or a batch, §9.2) reports whether any was removed AND clears `active` if it was
|
|
2654
|
-
* the removed one; `clear` empties it and clears `active`. Event-free (each workspace owns its
|
|
2655
|
-
* own observable `emitter`).
|
|
2656
|
-
*
|
|
2657
|
-
* With the optional `store` ({@link WorkspaceStoreInterface}, e.g. `createMemoryWorkspaceStore` /
|
|
2658
|
-
* `createDatabaseWorkspaceStore`), `open(id)` HYDRATES a workspace on a registry miss (rebuilding it
|
|
2659
|
-
* through the constructor `seed` from the snapshot's `files`, then activating it) and `save(id)`
|
|
2660
|
-
* PERSISTS a registered workspace's `snapshot()`. Both are LENIENT without a store (open resolves
|
|
2661
|
-
* only registered ids, save is a no-op `false`).
|
|
2662
|
-
*
|
|
2663
|
-
* @param options - Optional default `on` / `error` for created workspaces + the durable `store`
|
|
2664
|
-
* (see {@link WorkspaceManagerOptions})
|
|
2665
|
-
* @returns An empty {@link WorkspaceManagerInterface}
|
|
2666
|
-
*
|
|
2667
|
-
* @example
|
|
2668
|
-
* ```ts
|
|
2669
|
-
* import { createWorkspaceManager } from '@src/core'
|
|
2670
|
-
*
|
|
2671
|
-
* const workspaces = createWorkspaceManager()
|
|
2672
|
-
* const scratch = workspaces.add() // auto-activates — workspaces.active === scratch
|
|
2673
|
-
* scratch.write('notes.txt', 'hello')
|
|
2674
|
-
* ```
|
|
2675
|
-
*/
|
|
2676
|
-
export declare function createWorkspaceManager(options?: WorkspaceManagerOptions): WorkspaceManagerInterface;
|
|
2677
|
-
|
|
2678
2353
|
/**
|
|
2679
2354
|
* A {@link ConversationStoreInterface} backed by one table of the `databases` layer — a
|
|
2680
2355
|
* conversation's durable state IS a row, so persistence reduces to keyed point-access (`get` / `set`
|
|
2681
2356
|
* / `delete`) over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`
|
|
2682
2357
|
* {@link import('./MemoryConversationStore.js').MemoryConversationStore}. The EXACT twin of
|
|
2683
|
-
* {@link import('
|
|
2358
|
+
* {@link import('@orkestrel/workspace').DatabaseWorkspaceStore}.
|
|
2684
2359
|
*
|
|
2685
2360
|
* @remarks
|
|
2686
2361
|
* The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
|
|
@@ -2688,7 +2363,7 @@ export declare function createWorkspaceManager(options?: WorkspaceManagerOptions
|
|
|
2688
2363
|
* IndexedDB backend swaps in WITHOUT touching the
|
|
2689
2364
|
* {@link import('../ConversationManager.js').ConversationManager} or the
|
|
2690
2365
|
* {@link import('../Conversation.js').Conversation} — the same seam as
|
|
2691
|
-
* {@link import('
|
|
2366
|
+
* {@link import('@orkestrel/workspace').DatabaseWorkspaceStore}. The
|
|
2692
2367
|
* driver defaults to memory ({@link import('../../factories.js').createDatabaseConversationStore}
|
|
2693
2368
|
* passes `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the
|
|
2694
2369
|
* durable plumbing by passing a JSON / SQLite / IndexedDB driver.
|
|
@@ -2741,96 +2416,6 @@ export declare class DatabaseConversationStore implements ConversationStoreInter
|
|
|
2741
2416
|
delete(id: string): Promise<void>;
|
|
2742
2417
|
}
|
|
2743
2418
|
|
|
2744
|
-
/**
|
|
2745
|
-
* A {@link WorkspaceStoreInterface} backed by one table of the `databases` layer — a workspace's
|
|
2746
|
-
* durable state IS a row, so persistence reduces to keyed point-access (`get` / `set` / `delete`)
|
|
2747
|
-
* over a {@link TableInterface}, the driver-pluggable twin of the plain-`Map`
|
|
2748
|
-
* {@link import('./MemoryWorkspaceStore.js').MemoryWorkspaceStore}.
|
|
2749
|
-
*
|
|
2750
|
-
* @remarks
|
|
2751
|
-
* The store is driver-agnostic: it holds a single {@link TableInterface} whose backend (memory,
|
|
2752
|
-
* JSON, SQLite, IndexedDB) is chosen by whoever builds it (the factories), so a JSON / SQLite /
|
|
2753
|
-
* IndexedDB backend swaps in WITHOUT touching the
|
|
2754
|
-
* {@link import('../WorkspaceManager.js').WorkspaceManager} or the
|
|
2755
|
-
* {@link import('../Workspace.js').Workspace} — the same seam as
|
|
2756
|
-
* the analogous `DatabaseWorkflowStore` in `@orkestrel/workflow`. The
|
|
2757
|
-
* driver defaults to memory ({@link import('../../factories.js').createDatabaseWorkspaceStore}
|
|
2758
|
-
* passes `createMemoryDriver()`), so it ALSO works in memory out of the box; you opt into the
|
|
2759
|
-
* durable plumbing by passing a JSON / SQLite / IndexedDB driver.
|
|
2760
|
-
*
|
|
2761
|
-
* The {@link WorkspaceSnapshot} is stored as ONE OPAQUE JSON COLUMN — the table is a row of
|
|
2762
|
-
* `{ id; snapshot }` ({@link WorkspaceSnapshotRow}), the snapshot the whole JSON blob (a `rawShape`
|
|
2763
|
-
* column the factory builds) — exactly as `DatabaseWorkflowStore` stores its snapshot. The snapshot
|
|
2764
|
-
* is already a COMPLETE, self-contained, pure-JSON payload, so storing it whole is lossless AND
|
|
2765
|
-
* keeps the row type flat (`snapshot` reads back as `unknown`).
|
|
2766
|
-
*
|
|
2767
|
-
* - **`set(snapshot)` upserts under the snapshot's OWN `id`** (no separate id param) — it writes
|
|
2768
|
-
* the row `{ id: snapshot.id, snapshot }`.
|
|
2769
|
-
* - **`get(id)` resolves the stored snapshot for an id**, narrowing the opaque JSON column back to
|
|
2770
|
-
* a {@link WorkspaceSnapshot} ({@link import('../../helpers.js').isWorkspaceSnapshot} — the AGENTS
|
|
2771
|
-
* §14 boundary narrow for an untrusted storage read), or `undefined` if none is stored.
|
|
2772
|
-
* - **`delete(id)` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
2773
|
-
*
|
|
2774
|
-
* UNLIKE a session store there is NO idle-TTL / eviction — a persisted workspace lives until an
|
|
2775
|
-
* explicit `delete`. The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the
|
|
2776
|
-
* §22 method bijection with {@link WorkspaceStoreInterface}). Hydration stays a caller concern: a
|
|
2777
|
-
* {@link import('../WorkspaceManager.js').WorkspaceManager} reads a snapshot back and rebuilds the
|
|
2778
|
-
* live workspace through the constructor `seed` (its `open` / `save`).
|
|
2779
|
-
*
|
|
2780
|
-
* @example
|
|
2781
|
-
* ```ts
|
|
2782
|
-
* import { createDatabaseWorkspaceStore, createMemoryDriver, createWorkspace } from '@src/core'
|
|
2783
|
-
*
|
|
2784
|
-
* const store = createDatabaseWorkspaceStore(createMemoryDriver()) // a durable driver swaps in here
|
|
2785
|
-
* const workspace = createWorkspace()
|
|
2786
|
-
* workspace.write('notes.txt', 'hello')
|
|
2787
|
-
* await store.set(workspace.snapshot()) // persist the workspace (one JSON column)
|
|
2788
|
-
* const snapshot = await store.get(workspace.id)
|
|
2789
|
-
* await store.delete(workspace.id) // drop it
|
|
2790
|
-
* ```
|
|
2791
|
-
*/
|
|
2792
|
-
export declare class DatabaseWorkspaceStore implements WorkspaceStoreInterface {
|
|
2793
|
-
#private;
|
|
2794
|
-
/**
|
|
2795
|
-
* Wrap a table as a workspace store.
|
|
2796
|
-
*
|
|
2797
|
-
* @param table - The {@link TableInterface} holding the snapshots — its row is the
|
|
2798
|
-
* {@link WorkspaceSnapshotRow} `{ id; snapshot }` shape (the snapshot one opaque JSON column)
|
|
2799
|
-
*/
|
|
2800
|
-
constructor(table: TableInterface<WorkspaceSnapshotRow>);
|
|
2801
|
-
/** Resolve the persisted snapshot for `id`, narrowing the opaque JSON column back to a `WorkspaceSnapshot`. */
|
|
2802
|
-
get(id: string): Promise<WorkspaceSnapshot | undefined>;
|
|
2803
|
-
/** Insert or replace under the snapshot's OWN `id` (no separate id param) — the row is `{ id, snapshot }`. */
|
|
2804
|
-
set(snapshot: WorkspaceSnapshot): Promise<void>;
|
|
2805
|
-
/** Drop a snapshot by id; an absent id is a no-op (no throw). */
|
|
2806
|
-
delete(id: string): Promise<void>;
|
|
2807
|
-
}
|
|
2808
|
-
|
|
2809
|
-
/**
|
|
2810
|
-
* Compute the decoded byte length of a base64 string ARITHMETICALLY — the image-payload
|
|
2811
|
-
* sizing primitive {@link computeSize} uses, with no `atob` / `Buffer` decode.
|
|
2812
|
-
*
|
|
2813
|
-
* @remarks
|
|
2814
|
-
* A base64 string encodes each group of 3 input bytes as 4 characters, so a well-formed
|
|
2815
|
-
* string's length is a multiple of 4 and its decoded length is `(length / 4) * 3` MINUS
|
|
2816
|
-
* the trailing `=` padding (one `=` ⇒ the last group held 2 bytes, two `==` ⇒ 1 byte).
|
|
2817
|
-
* The padding is counted from the trailing `=` characters, so both the `=` and `==` cases
|
|
2818
|
-
* are handled. The empty string decodes to `0`. Total — never throws (a malformed,
|
|
2819
|
-
* non-multiple-of-4 length still yields a defined non-negative estimate via `floor`).
|
|
2820
|
-
*
|
|
2821
|
-
* @param base64 - The base64-encoded string (e.g. an image's `data`)
|
|
2822
|
-
* @returns The decoded payload's byte length
|
|
2823
|
-
*
|
|
2824
|
-
* @example
|
|
2825
|
-
* ```ts
|
|
2826
|
-
* decodedSize('') // 0
|
|
2827
|
-
* decodedSize('AAAA') // 3 (no padding)
|
|
2828
|
-
* decodedSize('AAA=') // 2 (one '=')
|
|
2829
|
-
* decodedSize('AA==') // 1 (two '=')
|
|
2830
|
-
* ```
|
|
2831
|
-
*/
|
|
2832
|
-
export declare function decodedSize(base64: string): number;
|
|
2833
|
-
|
|
2834
2419
|
/**
|
|
2835
2420
|
* The default cap on an {@link AgentInterface} turn's tool iterations — the maximum
|
|
2836
2421
|
* number of context → provider → tools cycles before the loop stops, so a model that
|
|
@@ -2858,28 +2443,6 @@ export declare const DEFAULT_AUTHORITY_ZONE = "default";
|
|
|
2858
2443
|
*/
|
|
2859
2444
|
export declare const DEFAULT_CONVERSATION_KEEP = 0;
|
|
2860
2445
|
|
|
2861
|
-
/**
|
|
2862
|
-
* Escape a string's regex-special characters so it matches LITERALLY inside a `RegExp` — the
|
|
2863
|
-
* primitive a {@link import('./workspaces/Workspace.js').Workspace} search builds a literal-text
|
|
2864
|
-
* search pattern through (as opposed to a caller-supplied regex pattern).
|
|
2865
|
-
*
|
|
2866
|
-
* @remarks
|
|
2867
|
-
* Prefixes every character in the class `. * + ? ^ $ { } ( ) | [ ] \` with a backslash, so the
|
|
2868
|
-
* escaped string, when compiled into a `RegExp`, matches only its own literal characters — no
|
|
2869
|
-
* character acts as a quantifier, anchor, group, or class. Pure string assembly, total — never
|
|
2870
|
-
* throws.
|
|
2871
|
-
*
|
|
2872
|
-
* @param value - The text to escape for literal use inside a `RegExp` pattern
|
|
2873
|
-
* @returns `value` with every regex-special character backslash-escaped
|
|
2874
|
-
*
|
|
2875
|
-
* @example
|
|
2876
|
-
* ```ts
|
|
2877
|
-
* escapeRegExp('a.b*c') // 'a\\.b\\*c'
|
|
2878
|
-
* new RegExp(escapeRegExp('a.b*c')).test('a.b*c') // true
|
|
2879
|
-
* ```
|
|
2880
|
-
*/
|
|
2881
|
-
export declare function escapeRegExp(value: string): string;
|
|
2882
|
-
|
|
2883
2446
|
/**
|
|
2884
2447
|
* Estimate the context-token footprint of a batch of messages — the default `consume`
|
|
2885
2448
|
* estimator for an agent's context `BudgetInterface` (a budgets surface's tracking contract)
|
|
@@ -2934,13 +2497,6 @@ export declare function estimateMessages(messages: readonly MessageInterface[]):
|
|
|
2934
2497
|
*/
|
|
2935
2498
|
export declare function estimateTokens(text: string): number;
|
|
2936
2499
|
|
|
2937
|
-
/**
|
|
2938
|
-
* The extension→language table {@link import('./helpers.js').inferLanguage} reads to
|
|
2939
|
-
* map a file path's extension to a fenced-code language tag. Covers the common source /
|
|
2940
|
-
* markup / data extensions; an unlisted extension falls back to `'text'`.
|
|
2941
|
-
*/
|
|
2942
|
-
export declare const EXTENSION_TO_LANGUAGE: Readonly<Record<string, string>>;
|
|
2943
|
-
|
|
2944
2500
|
/**
|
|
2945
2501
|
* Render a path-addressed text body as a fenced reference block — the framing an
|
|
2946
2502
|
* {@link import('./AgentContext.js').AgentContext}'s ACTIVE-workspace text-file render emits (the
|
|
@@ -2951,7 +2507,7 @@ export declare const EXTENSION_TO_LANGUAGE: Readonly<Record<string, string>>;
|
|
|
2951
2507
|
* fenced code block tagged with `language`, the `content` verbatim inside. Pure string assembly,
|
|
2952
2508
|
* total — never throws. The one fenced-file format string for the whole module — `AgentContext.build()`
|
|
2953
2509
|
* frames an active workspace's text files with it (each carries its own `language` on its
|
|
2954
|
-
* {@link FileContent} text arm).
|
|
2510
|
+
* {@link import('@orkestrel/workspace').FileContent} text arm).
|
|
2955
2511
|
*
|
|
2956
2512
|
* @param path - The file path shown on the `File:` label line
|
|
2957
2513
|
* @param language - The fenced-code language tag (e.g. `'typescript'`)
|
|
@@ -2968,74 +2524,6 @@ export declare const EXTENSION_TO_LANGUAGE: Readonly<Record<string, string>>;
|
|
|
2968
2524
|
*/
|
|
2969
2525
|
export declare function fencedFile(path: string, language: string, content: string): string;
|
|
2970
2526
|
|
|
2971
|
-
/**
|
|
2972
|
-
* A {@link FileInterface}'s content — a TAGLESS union of a TEXT arm and a BINARY arm, narrowed
|
|
2973
|
-
* by the {@link import('./helpers.js').isText} / {@link import('./helpers.js').isBinary}
|
|
2974
|
-
* guards (AGENTS §14: an untyped arm is narrowed via a guard, never an `as`).
|
|
2975
|
-
*
|
|
2976
|
-
* @remarks
|
|
2977
|
-
* - The TEXT arm carries the literal `text` plus the fenced-code `language` it renders as.
|
|
2978
|
-
* - The BINARY arm carries the base64-encoded `data` plus the {@link BinaryMIME} that labels it.
|
|
2979
|
-
*
|
|
2980
|
-
* There is no `modality` discriminant — the arms are told apart structurally
|
|
2981
|
-
* (`'text' in content` vs `'data' in content`) by the guards. A binary arm whose `mime`
|
|
2982
|
-
* starts with `image/` IS an image ({@link import('./helpers.js').isImage}). A future
|
|
2983
|
-
* non-image binary (a PDF) is the same binary arm with a new {@link BinaryMIME} — additive,
|
|
2984
|
-
* with nothing above it changed.
|
|
2985
|
-
*/
|
|
2986
|
-
export declare type FileContent = {
|
|
2987
|
-
readonly text: string;
|
|
2988
|
-
readonly language: string;
|
|
2989
|
-
} | {
|
|
2990
|
-
readonly data: string;
|
|
2991
|
-
readonly mime: BinaryMIME;
|
|
2992
|
-
};
|
|
2993
|
-
|
|
2994
|
-
/**
|
|
2995
|
-
* The minimal data to author a {@link FileInterface} — `size` / `lines` are DERIVED from the
|
|
2996
|
-
* `content`, so a caller supplies only `path` / `content` (and an optional `state`, defaulting
|
|
2997
|
-
* to `'created'`).
|
|
2998
|
-
*/
|
|
2999
|
-
export declare interface FileInput {
|
|
3000
|
-
readonly path: string;
|
|
3001
|
-
readonly content: FileContent;
|
|
3002
|
-
/** The lifecycle state; defaults to `'created'` when omitted. */
|
|
3003
|
-
readonly state?: FileState;
|
|
3004
|
-
}
|
|
3005
|
-
|
|
3006
|
-
/**
|
|
3007
|
-
* An immutable file value object — a `path`-addressed {@link FileContent} carrying a
|
|
3008
|
-
* lifecycle {@link FileState}, with `size` / `lines` DERIVED once when built.
|
|
3009
|
-
*
|
|
3010
|
-
* @remarks
|
|
3011
|
-
* A PLAIN frozen record (not a class instance) produced by
|
|
3012
|
-
* {@link import('./factories.js').createFile} — the `path` IS its identity (there is no
|
|
3013
|
-
* `id`). `size` and `lines` are computed from `content` when built (so they can never drift
|
|
3014
|
-
* from it) and re-read for free thereafter. Never mutated — a Workspace REPLACES a file
|
|
3015
|
-
* rather than editing it in place. A DATA-ONLY value object — no methods, plus it
|
|
3016
|
-
* `structuredClone`s losslessly (every field is a plain primitive / record).
|
|
3017
|
-
*/
|
|
3018
|
-
export declare interface FileInterface {
|
|
3019
|
-
readonly path: string;
|
|
3020
|
-
readonly content: FileContent;
|
|
3021
|
-
readonly state: FileState;
|
|
3022
|
-
/** Derived byte size: UTF-8 byte length (text) / decoded payload bytes (binary). */
|
|
3023
|
-
readonly size: number;
|
|
3024
|
-
/** Derived line count: the text line count; `0` for a binary arm. */
|
|
3025
|
-
readonly lines: number;
|
|
3026
|
-
}
|
|
3027
|
-
|
|
3028
|
-
/**
|
|
3029
|
-
* The lifecycle state of a {@link FileInterface} relative to its (future) durable backing
|
|
3030
|
-
* — a multi-value lifecycle union (AGENTS §10), not a boolean.
|
|
3031
|
-
*
|
|
3032
|
-
* @remarks
|
|
3033
|
-
* `'created'` is a brand-new file not yet persisted; `'modified'` has unsaved edits over a
|
|
3034
|
-
* persisted original; `'loaded'` was read from the backing and is unchanged; `'deleted'`
|
|
3035
|
-
* is tombstoned. A `File` authored without a `state` defaults to `'created'`.
|
|
3036
|
-
*/
|
|
3037
|
-
export declare type FileState = 'created' | 'modified' | 'loaded' | 'deleted';
|
|
3038
|
-
|
|
3039
2527
|
/**
|
|
3040
2528
|
* Filter a list of items by a {@link import('./types.js').ScopeInterface} allow-list of
|
|
3041
2529
|
* keys — the pure, total set-membership primitive the context's build step and the agent
|
|
@@ -3107,34 +2595,13 @@ export declare function handleAgentRunnerJob(registry: AgentRegistryInterface, a
|
|
|
3107
2595
|
*/
|
|
3108
2596
|
export declare const IMAGE_TOKEN_ESTIMATE = 512;
|
|
3109
2597
|
|
|
3110
|
-
/**
|
|
3111
|
-
* Infer a fenced-code language tag from a file path's extension — what a workspace text file
|
|
3112
|
-
* (or the {@link fencedFile} renderer) renders its content block as.
|
|
3113
|
-
*
|
|
3114
|
-
* @remarks
|
|
3115
|
-
* Reads the extension after the last `.` (case-insensitive) and maps it through a
|
|
3116
|
-
* fixed extension→language table. An unknown extension, or a path with no extension,
|
|
3117
|
-
* falls back to `'text'` (a safe, language-agnostic fence). Total — never throws.
|
|
3118
|
-
*
|
|
3119
|
-
* @param path - The document's file path (e.g. `'src/main.ts'`)
|
|
3120
|
-
* @returns The inferred language tag (e.g. `'typescript'`), or `'text'` when unknown
|
|
3121
|
-
*
|
|
3122
|
-
* @example
|
|
3123
|
-
* ```ts
|
|
3124
|
-
* inferLanguage('src/main.ts') // 'typescript'
|
|
3125
|
-
* inferLanguage('README.md') // 'markdown'
|
|
3126
|
-
* inferLanguage('LICENSE') // 'text'
|
|
3127
|
-
* ```
|
|
3128
|
-
*/
|
|
3129
|
-
export declare function inferLanguage(path: string): string;
|
|
3130
|
-
|
|
3131
2598
|
/**
|
|
3132
2599
|
* An immutable named directive — a {@link InstructionInterface} assembled once from its
|
|
3133
2600
|
* input (`name` / `content`, an optional `priority` defaulting to `0`), the `id` minted
|
|
3134
2601
|
* at construction.
|
|
3135
2602
|
*
|
|
3136
2603
|
* @remarks
|
|
3137
|
-
* A thin immutable value object (mirroring {@link import('
|
|
2604
|
+
* A thin immutable value object (mirroring {@link import('@orkestrel/tool').Tool}): the
|
|
3138
2605
|
* constructor mints a fresh `id` (`crypto.randomUUID()`), copies the input's `name` /
|
|
3139
2606
|
* `content`, resolves `priority` to the input's value or `0`, and carries the input's
|
|
3140
2607
|
* per-item `format` override ONLY when supplied (assigned just when present, mirroring a
|
|
@@ -3374,32 +2841,10 @@ export declare function isAgentError(value: unknown): value is AgentError;
|
|
|
3374
2841
|
export declare function isAgentJobError(value: unknown): value is AgentJobError;
|
|
3375
2842
|
|
|
3376
2843
|
/**
|
|
3377
|
-
*
|
|
3378
|
-
* union (AGENTS §14: narrow an untyped arm via a guard, never an `as`).
|
|
3379
|
-
*
|
|
3380
|
-
* @remarks
|
|
3381
|
-
* Tests `'data' in content` structurally — there is no `modality` discriminant. A `true`
|
|
3382
|
-
* narrows `content` to `{ data: string; mime: BinaryMIME }`, unlocking `.data` / `.mime`. An
|
|
3383
|
-
* image is a binary whose `mime` starts with `image/` ({@link isImage}). Total — never throws.
|
|
2844
|
+
* Narrow an unknown caught value to a {@link ConversationError}.
|
|
3384
2845
|
*
|
|
3385
|
-
* @param
|
|
3386
|
-
* @returns `true` when `
|
|
3387
|
-
*
|
|
3388
|
-
* @example
|
|
3389
|
-
* ```ts
|
|
3390
|
-
* if (isBinary(file.content)) file.content.data // the base64 payload + .mime
|
|
3391
|
-
* ```
|
|
3392
|
-
*/
|
|
3393
|
-
export declare function isBinary(content: FileContent): content is {
|
|
3394
|
-
readonly data: string;
|
|
3395
|
-
readonly mime: BinaryMIME;
|
|
3396
|
-
};
|
|
3397
|
-
|
|
3398
|
-
/**
|
|
3399
|
-
* Narrow an unknown caught value to a {@link ConversationError}.
|
|
3400
|
-
*
|
|
3401
|
-
* @param value - The value to test (typically a `catch` binding)
|
|
3402
|
-
* @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}
|
|
3403
2848
|
*
|
|
3404
2849
|
* @example
|
|
3405
2850
|
* ```ts
|
|
@@ -3417,7 +2862,7 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
3417
2862
|
* UNTRUSTED snapshot read (a storage row a
|
|
3418
2863
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
3419
2864
|
* reads back from its opaque JSON column, a snapshot loaded from disk). The EXACT analogue of
|
|
3420
|
-
* {@link isWorkspaceSnapshot}.
|
|
2865
|
+
* {@link import('@orkestrel/workspace').isWorkspaceSnapshot}.
|
|
3421
2866
|
*
|
|
3422
2867
|
* @remarks
|
|
3423
2868
|
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the snapshot's
|
|
@@ -3426,7 +2871,7 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
3426
2871
|
* {@link SectionInterface} ({@link isSection}), and a `messages` array EVERY element of which is a
|
|
3427
2872
|
* valid {@link MessageInterface} ({@link isMessage}) — enough to safely impose the
|
|
3428
2873
|
* {@link ConversationSnapshot} type at a storage boundary WITHOUT a cast. The structural twin of
|
|
3429
|
-
* {@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
|
|
3430
2875
|
* non-string `summary` when present, a non-array `sections` / `messages`, or any malformed
|
|
3431
2876
|
* element) resolves `false`, so a
|
|
3432
2877
|
* {@link import('./conversations/stores/DatabaseConversationStore.js').DatabaseConversationStore}
|
|
@@ -3445,68 +2890,23 @@ export declare function isConversationError(value: unknown): value is Conversati
|
|
|
3445
2890
|
*/
|
|
3446
2891
|
export declare function isConversationSnapshot(value: unknown): value is ConversationSnapshot;
|
|
3447
2892
|
|
|
3448
|
-
/**
|
|
3449
|
-
* Whether an `unknown` is structurally a {@link FileInterface} record — the per-file step of the
|
|
3450
|
-
* {@link isWorkspaceSnapshot} read-boundary narrow (AGENTS §14: narrow an untrusted storage read
|
|
3451
|
-
* via a guard, never an `as`).
|
|
3452
|
-
*
|
|
3453
|
-
* @remarks
|
|
3454
|
-
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the file's SHAPE:
|
|
3455
|
-
* a record with a `string` `path`, a `string` `state`, `number` `size` / `lines`, and a `content`
|
|
3456
|
-
* that is EITHER the TEXT arm (`{ text: string; language: string }`) OR the BINARY arm
|
|
3457
|
-
* (`{ data: string; mime: string }`) — the tagless {@link FileContent} union, told apart
|
|
3458
|
-
* structurally exactly as {@link isText} / {@link isBinary} do (no `modality` discriminant). Enough
|
|
3459
|
-
* to safely impose the {@link FileInterface} type at a storage boundary WITHOUT a cast; the `mime`
|
|
3460
|
-
* is left as a broad `string` here (an open {@link BinaryMIME}, so any storage-read MIME string is
|
|
3461
|
-
* accepted defensively rather than rejected against the current literal set).
|
|
3462
|
-
*
|
|
3463
|
-
* @param value - The value to test (one element of a snapshot's opaque `files` array)
|
|
3464
|
-
* @returns `true` when `value` has the structural shape of a {@link FileInterface}
|
|
3465
|
-
*
|
|
3466
|
-
* @example
|
|
3467
|
-
* ```ts
|
|
3468
|
-
* isFile({ path: 'a.ts', content: { text: 'x', language: 'typescript' }, state: 'created', size: 1, lines: 1 }) // true
|
|
3469
|
-
* isFile({ path: 'a.png', content: { data: 'AAAA', mime: 'image/png' }, state: 'created', size: 3, lines: 0 }) // true
|
|
3470
|
-
* isFile({ path: 'a.ts' }) // false (missing content / state / size / lines)
|
|
3471
|
-
* ```
|
|
3472
|
-
*/
|
|
3473
|
-
export declare function isFile(value: unknown): value is FileInterface;
|
|
3474
|
-
|
|
3475
|
-
/**
|
|
3476
|
-
* Whether a {@link FileContent} is an IMAGE — a {@link isBinary} arm whose `mime` is an
|
|
3477
|
-
* `image/*` type (an image is just a binary with an image MIME).
|
|
3478
|
-
*
|
|
3479
|
-
* @remarks
|
|
3480
|
-
* Narrows to the binary arm first, then checks the `image/` MIME prefix — so a future
|
|
3481
|
-
* non-image binary (a PDF, `'application/pdf'`) is binary but NOT an image. Total — never
|
|
3482
|
-
* throws.
|
|
3483
|
-
*
|
|
3484
|
-
* @param content - The file content to test
|
|
3485
|
-
* @returns `true` when `content` is a binary arm with an `image/*` MIME
|
|
3486
|
-
*
|
|
3487
|
-
* @example
|
|
3488
|
-
* ```ts
|
|
3489
|
-
* isImage({ data: '<base64>', mime: 'image/png' }) // true
|
|
3490
|
-
* isImage({ text: 'hi', language: 'text' }) // false
|
|
3491
|
-
* ```
|
|
3492
|
-
*/
|
|
3493
|
-
export declare function isImage(content: FileContent): boolean;
|
|
3494
|
-
|
|
3495
2893
|
/**
|
|
3496
2894
|
* Whether an `unknown` is structurally a {@link MessageInterface} record — the per-message step of
|
|
3497
2895
|
* the {@link isConversationSnapshot} read-boundary narrow (AGENTS §14: narrow an untrusted storage
|
|
3498
|
-
* 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}.
|
|
3499
2898
|
*
|
|
3500
2899
|
* @remarks
|
|
3501
2900
|
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the message's
|
|
3502
2901
|
* SHAPE: a record with a `string` `id`, a `string` `role`, a `string` `content`, and — WHEN present
|
|
3503
|
-
* — 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
|
|
3504
2904
|
* ASI06 fail-closed deepening: a tampered `calls` element rejects the message, so the snapshot
|
|
3505
2905
|
* reads back as absent rather than replaying a malformed call) and an `images` that is an array
|
|
3506
2906
|
* (an absent optional passes). The `role` is left as a broad `string` here (an open
|
|
3507
2907
|
* {@link import('./types.js').MessageRole}, so any storage-read role string is accepted
|
|
3508
|
-
* defensively rather than rejected against the current literal set)
|
|
3509
|
-
*
|
|
2908
|
+
* defensively rather than rejected against the current literal set). Enough to safely impose the
|
|
2909
|
+
* {@link MessageInterface} type at
|
|
3510
2910
|
* a storage boundary WITHOUT a cast.
|
|
3511
2911
|
*
|
|
3512
2912
|
* @param value - The value to test (one element of a snapshot's `messages` / a section's `messages`)
|
|
@@ -3562,132 +2962,16 @@ export declare function isProviderAbortError(value: unknown): value is ProviderA
|
|
|
3562
2962
|
*/
|
|
3563
2963
|
export declare function isSection(value: unknown): value is SectionInterface;
|
|
3564
2964
|
|
|
3565
|
-
/**
|
|
3566
|
-
* Whether a {@link FileContent} is the TEXT arm — the narrowing guard for the text-vs-binary
|
|
3567
|
-
* union (AGENTS §14: narrow an untyped arm via a guard, never an `as`).
|
|
3568
|
-
*
|
|
3569
|
-
* @remarks
|
|
3570
|
-
* Tests `'text' in content` structurally — there is no `modality` discriminant. A `true`
|
|
3571
|
-
* narrows `content` to `{ text: string; language: string }`, unlocking `.text` / `.language`.
|
|
3572
|
-
* Total — never throws.
|
|
3573
|
-
*
|
|
3574
|
-
* @param content - The file content to test
|
|
3575
|
-
* @returns `true` when `content` is the text arm (carries `text` + `language`)
|
|
3576
|
-
*
|
|
3577
|
-
* @example
|
|
3578
|
-
* ```ts
|
|
3579
|
-
* if (isText(file.content)) file.content.text // the literal text + .language
|
|
3580
|
-
* ```
|
|
3581
|
-
*/
|
|
3582
|
-
export declare function isText(content: FileContent): content is {
|
|
3583
|
-
readonly text: string;
|
|
3584
|
-
readonly language: string;
|
|
3585
|
-
};
|
|
3586
|
-
|
|
3587
|
-
/**
|
|
3588
|
-
* Whether an `unknown` is structurally a {@link ToolCall} record — the per-call step of the
|
|
3589
|
-
* {@link isMessage} read-boundary narrow (AGENTS §14: narrow an untrusted storage read via a
|
|
3590
|
-
* guard, never an `as`).
|
|
3591
|
-
*
|
|
3592
|
-
* @remarks
|
|
3593
|
-
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the call's
|
|
3594
|
-
* SHAPE: a record with a `string` `id`, a `string` `name`, and a record `arguments` — the real
|
|
3595
|
-
* {@link ToolCall} shape a restored assistant turn replays to a provider. This is the ASI06
|
|
3596
|
-
* fail-CLOSED element check: a tampered persisted call (`null`, a bare string, a non-record
|
|
3597
|
-
* `arguments`) fails the guard, so {@link isMessage} — and through it
|
|
3598
|
-
* {@link isConversationSnapshot} — rejects the whole snapshot and a poisoned store row reads
|
|
3599
|
-
* back as ABSENT instead of replaying a malformed call into a chat template.
|
|
3600
|
-
*
|
|
3601
|
-
* @param value - The value to test (one element of an assistant message's `calls`)
|
|
3602
|
-
* @returns `true` when `value` has the structural shape of a {@link ToolCall}
|
|
3603
|
-
*
|
|
3604
|
-
* @example
|
|
3605
|
-
* ```ts
|
|
3606
|
-
* isToolCall({ id: 'c1', name: 'search', arguments: { q: 'acme' } }) // true
|
|
3607
|
-
* isToolCall({ id: 'c1', name: 'search' }) // false (missing arguments)
|
|
3608
|
-
* isToolCall({ id: 'c1', name: 123, arguments: {} }) // false (non-string name)
|
|
3609
|
-
* ```
|
|
3610
|
-
*/
|
|
3611
|
-
export declare function isToolCall(value: unknown): value is ToolCall;
|
|
3612
|
-
|
|
3613
|
-
/**
|
|
3614
|
-
* Whether a {@link Range} is STRUCTURALLY valid — the predicate a ranged `write` checks
|
|
3615
|
-
* before applying (a `false` here is the `RANGE` throw).
|
|
3616
|
-
*
|
|
3617
|
-
* @remarks
|
|
3618
|
-
* Structural validity is independent of any content: every component must be `>= 1`
|
|
3619
|
-
* (1-based lines and columns), and `start` must not come after `end` (an inverted range
|
|
3620
|
-
* is invalid). A range that is structurally valid but reaches PAST the end of a specific
|
|
3621
|
-
* text is still valid — it is {@link clampRange}d to the bounds when applied, not rejected.
|
|
3622
|
-
* Total — never throws.
|
|
3623
|
-
*
|
|
3624
|
-
* @param range - The range to validate
|
|
3625
|
-
* @returns `true` when every component is `>= 1` and `start` is at or before `end`
|
|
3626
|
-
*
|
|
3627
|
-
* @example
|
|
3628
|
-
* ```ts
|
|
3629
|
-
* isValidRange({ start: { line: 1, column: 1 }, end: { line: 2, column: 1 } }) // true
|
|
3630
|
-
* isValidRange({ start: { line: 2, column: 1 }, end: { line: 1, column: 1 } }) // false (inverted)
|
|
3631
|
-
* isValidRange({ start: { line: 0, column: 1 }, end: { line: 1, column: 1 } }) // false (sub-1 line)
|
|
3632
|
-
* ```
|
|
3633
|
-
*/
|
|
3634
|
-
export declare function isValidRange(range: Range): boolean;
|
|
3635
|
-
|
|
3636
|
-
/**
|
|
3637
|
-
* Narrow an unknown caught value to a {@link WorkspaceError}.
|
|
3638
|
-
*
|
|
3639
|
-
* @param value - The value to test (typically a `catch` binding)
|
|
3640
|
-
* @returns `true` when `value` is a {@link WorkspaceError}
|
|
3641
|
-
*
|
|
3642
|
-
* @example
|
|
3643
|
-
* ```ts
|
|
3644
|
-
* try {
|
|
3645
|
-
* workspace.prepend('icon.png', '// header')
|
|
3646
|
-
* } catch (error) {
|
|
3647
|
-
* if (isWorkspaceError(error) && error.code === 'MODALITY') skipBinary()
|
|
3648
|
-
* }
|
|
3649
|
-
* ```
|
|
3650
|
-
*/
|
|
3651
|
-
export declare function isWorkspaceError(value: unknown): value is WorkspaceError;
|
|
3652
|
-
|
|
3653
|
-
/**
|
|
3654
|
-
* Narrow an `unknown` to a {@link WorkspaceSnapshot} — the AGENTS §14 boundary guard for an
|
|
3655
|
-
* UNTRUSTED snapshot read (a storage row a
|
|
3656
|
-
* {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} reads back
|
|
3657
|
-
* from its opaque JSON column, a snapshot loaded from disk).
|
|
3658
|
-
*
|
|
3659
|
-
* @remarks
|
|
3660
|
-
* A total guard (it NEVER throws — adversarial input returns `false`). It checks the snapshot's
|
|
3661
|
-
* SHAPE: a `string` `id` and a `files` array EVERY element of which is a valid {@link FileInterface}
|
|
3662
|
-
* record ({@link isFile}) — enough to safely impose the {@link WorkspaceSnapshot} type at a storage
|
|
3663
|
-
* boundary WITHOUT a cast. The structural twin of
|
|
3664
|
-
* the analogous `isWorkflowSnapshot` in `@orkestrel/workflow`. A malformed blob (a non-record, a
|
|
3665
|
-
* missing / non-string `id`, a non-array `files`, or any malformed file element) resolves `false`,
|
|
3666
|
-
* so a {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} read
|
|
3667
|
-
* yields `undefined` rather than a broken workspace.
|
|
3668
|
-
*
|
|
3669
|
-
* @param value - The value to test (an opaque storage read)
|
|
3670
|
-
* @returns `true` when `value` has the structural shape of a {@link WorkspaceSnapshot}
|
|
3671
|
-
*
|
|
3672
|
-
* @example
|
|
3673
|
-
* ```ts
|
|
3674
|
-
* isWorkspaceSnapshot({ id: 'w1', files: [] }) // true
|
|
3675
|
-
* isWorkspaceSnapshot({ id: 'w1', files: 'nope' }) // false
|
|
3676
|
-
* isWorkspaceSnapshot({ files: [] }) // false (missing id)
|
|
3677
|
-
* ```
|
|
3678
|
-
*/
|
|
3679
|
-
export declare function isWorkspaceSnapshot(value: unknown): value is WorkspaceSnapshot;
|
|
3680
|
-
|
|
3681
2965
|
/**
|
|
3682
2966
|
* The in-memory {@link ConversationStoreInterface} — a process-lifetime `Map` of
|
|
3683
2967
|
* {@link ConversationSnapshot}s keyed by conversation id, the DEFAULT store
|
|
3684
2968
|
* {@link import('../../factories.js').createMemoryConversationStore} builds. The EXACT twin of
|
|
3685
|
-
* {@link import('
|
|
2969
|
+
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore}.
|
|
3686
2970
|
*
|
|
3687
2971
|
* @remarks
|
|
3688
2972
|
* A plain `Map<string, ConversationSnapshot>` (AGENTS §21 — the snapshot is already pure,
|
|
3689
2973
|
* self-contained JSON, so no encoding is needed for the memory tier). Like the
|
|
3690
|
-
* {@link import('
|
|
2974
|
+
* {@link import('@orkestrel/workspace').MemoryWorkspaceStore} it twins,
|
|
3691
2975
|
* there is NO idle-TTL and NO eviction: a persisted conversation lives until an explicit `delete`. A
|
|
3692
2976
|
* durable backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching
|
|
3693
2977
|
* the {@link import('../ConversationManager.js').ConversationManager} or the
|
|
@@ -3723,50 +3007,6 @@ export declare class MemoryConversationStore implements ConversationStoreInterfa
|
|
|
3723
3007
|
delete(id: string): Promise<void>;
|
|
3724
3008
|
}
|
|
3725
3009
|
|
|
3726
|
-
/**
|
|
3727
|
-
* The in-memory {@link WorkspaceStoreInterface} — a process-lifetime `Map` of
|
|
3728
|
-
* {@link WorkspaceSnapshot}s keyed by workspace id, the DEFAULT store
|
|
3729
|
-
* {@link import('../../factories.js').createMemoryWorkspaceStore} builds.
|
|
3730
|
-
*
|
|
3731
|
-
* @remarks
|
|
3732
|
-
* A plain `Map<string, WorkspaceSnapshot>` (AGENTS §21 — the snapshot is already pure,
|
|
3733
|
-
* self-contained JSON, so no encoding is needed for the memory tier). Like the
|
|
3734
|
-
* the analogous `MemoryWorkflowStore` in `@orkestrel/workflow` it twins,
|
|
3735
|
-
* there is NO idle-TTL and NO eviction: a persisted workspace lives until an explicit `delete`. A
|
|
3736
|
-
* durable backend (JSON / SQLite / IndexedDB) swaps in through the SAME interface without touching
|
|
3737
|
-
* the {@link import('../WorkspaceManager.js').WorkspaceManager} or the
|
|
3738
|
-
* {@link import('../Workspace.js').Workspace} — its driver-pluggable twin is
|
|
3739
|
-
* {@link import('./DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} (the snapshot as one opaque
|
|
3740
|
-
* JSON column).
|
|
3741
|
-
*
|
|
3742
|
-
* - **`get` resolves the persisted snapshot for an id**, or `undefined` if none is stored.
|
|
3743
|
-
* - **`set` inserts / replaces under the snapshot's OWN `id`** (no separate id param).
|
|
3744
|
-
* - **`delete` drops a snapshot by id**; an absent id is a no-op (no throw).
|
|
3745
|
-
*
|
|
3746
|
-
* The public surface is EXACTLY `get` / `set` / `delete` — no extra members (the §22 method
|
|
3747
|
-
* bijection with {@link WorkspaceStoreInterface}). Hydration is a caller concern: a
|
|
3748
|
-
* {@link import('../WorkspaceManager.js').WorkspaceManager} reads a snapshot back and rebuilds the
|
|
3749
|
-
* live workspace through the constructor `seed` (its `open` / `save`).
|
|
3750
|
-
*
|
|
3751
|
-
* @example
|
|
3752
|
-
* ```ts
|
|
3753
|
-
* import { createMemoryWorkspaceStore, createWorkspace } from '@src/core'
|
|
3754
|
-
*
|
|
3755
|
-
* const store = createMemoryWorkspaceStore()
|
|
3756
|
-
* const workspace = createWorkspace()
|
|
3757
|
-
* workspace.write('notes.txt', 'hello')
|
|
3758
|
-
* await store.set(workspace.snapshot()) // persist the workspace
|
|
3759
|
-
* const snapshot = await store.get(workspace.id)
|
|
3760
|
-
* await store.delete(workspace.id) // drop it
|
|
3761
|
-
* ```
|
|
3762
|
-
*/
|
|
3763
|
-
export declare class MemoryWorkspaceStore implements WorkspaceStoreInterface {
|
|
3764
|
-
#private;
|
|
3765
|
-
get(id: string): Promise<WorkspaceSnapshot | undefined>;
|
|
3766
|
-
set(snapshot: WorkspaceSnapshot): Promise<void>;
|
|
3767
|
-
delete(id: string): Promise<void>;
|
|
3768
|
-
}
|
|
3769
|
-
|
|
3770
3010
|
/**
|
|
3771
3011
|
* The estimated per-message role/framing overhead {@link import('./helpers.js').estimateMessages}
|
|
3772
3012
|
* adds on top of a message's content estimate — accounts for the fixed wire framing every
|
|
@@ -3844,42 +3084,6 @@ export declare interface MessageManagerInterface {
|
|
|
3844
3084
|
/** The role a {@link MessageInterface} plays in a conversation turn. */
|
|
3845
3085
|
export declare type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
|
|
3846
3086
|
|
|
3847
|
-
/**
|
|
3848
|
-
* Convert a 1-based {@link Position} to a 0-based string offset into `text` — the indexing
|
|
3849
|
-
* primitive {@link sliceRange} / {@link spliceRange} use, clamped to `text.length`.
|
|
3850
|
-
*
|
|
3851
|
-
* @remarks
|
|
3852
|
-
* Sums each preceding line's length plus its `\n` separator, then adds the `column - 1`
|
|
3853
|
-
* within the target line, capped at `text.length`. Total — never throws (an out-of-bounds
|
|
3854
|
-
* position yields a defined in-range offset).
|
|
3855
|
-
*
|
|
3856
|
-
* @param text - The text to index into
|
|
3857
|
-
* @param position - The 1-based position to resolve
|
|
3858
|
-
* @returns The 0-based offset (in `[0, text.length]`)
|
|
3859
|
-
*
|
|
3860
|
-
* @example
|
|
3861
|
-
* ```ts
|
|
3862
|
-
* offsetAt('ab\ncd', { line: 2, column: 1 }) // 3 (just after 'ab\n')
|
|
3863
|
-
* ```
|
|
3864
|
-
*/
|
|
3865
|
-
export declare function offsetAt(text: string, position: Position): number;
|
|
3866
|
-
|
|
3867
|
-
/**
|
|
3868
|
-
* A 1-based caret position inside a text file — `line` and `column` both count from `1`
|
|
3869
|
-
* (column `1` is the first character of the line), matching an editor's gutter.
|
|
3870
|
-
*
|
|
3871
|
-
* @remarks
|
|
3872
|
-
* The {@link import('./workspaces/Workspace.js').Workspace} edit surface speaks 1-based
|
|
3873
|
-
* positions end to end ({@link Range}, {@link ReadResult}, {@link SearchMatch}). A
|
|
3874
|
-
* structurally invalid component (`line < 1` or `column < 1`) is rejected by a range op
|
|
3875
|
-
* (`RANGE`); an in-bounds-but-past-the-end one is CLAMPED to the nearest valid caret rather
|
|
3876
|
-
* than rejected.
|
|
3877
|
-
*/
|
|
3878
|
-
export declare interface Position {
|
|
3879
|
-
readonly line: number;
|
|
3880
|
-
readonly column: number;
|
|
3881
|
-
}
|
|
3882
|
-
|
|
3883
3087
|
/**
|
|
3884
3088
|
* Thrown by a {@link ProviderInterface}'s `stream` when its bound signal aborts
|
|
3885
3089
|
* mid-flight — carries the {@link ProviderResult} assembled from whatever streamed
|
|
@@ -4022,87 +3226,6 @@ export declare interface ProviderStreamOptions {
|
|
|
4022
3226
|
readonly schema?: Readonly<Record<string, unknown>>;
|
|
4023
3227
|
}
|
|
4024
3228
|
|
|
4025
|
-
/**
|
|
4026
|
-
* A half-open span of text between two {@link Position}s — `start` INCLUSIVE, `end`
|
|
4027
|
-
* EXCLUSIVE (the character at `end` is not part of the span).
|
|
4028
|
-
*
|
|
4029
|
-
* @remarks
|
|
4030
|
-
* A range whose `start` is at or before its `end` is valid; an inverted range
|
|
4031
|
-
* (`start` after `end`) or one with a sub-1 component is structurally invalid and a range
|
|
4032
|
-
* op throws `RANGE`. Each in-bounds component is clamped to the text before it is applied,
|
|
4033
|
-
* so a range reaching past the end of the content reads / splices up to the end.
|
|
4034
|
-
*/
|
|
4035
|
-
export declare interface Range {
|
|
4036
|
-
readonly start: Position;
|
|
4037
|
-
readonly end: Position;
|
|
4038
|
-
}
|
|
4039
|
-
|
|
4040
|
-
/**
|
|
4041
|
-
* Assemble a 1-based nested {@link Range} from four FLAT caret integers — the bridge a
|
|
4042
|
-
* workspace-editing tool (see `@orkestrel/tool`) uses from its small-model FLAT surface back to the
|
|
4043
|
-
* nested {@link Range} the {@link import('./workspaces/Workspace.js').Workspace} edit surface
|
|
4044
|
-
* speaks. Published as a public helper for that consumer.
|
|
4045
|
-
*
|
|
4046
|
-
* @remarks
|
|
4047
|
-
* Pairs `(fromLine, fromColumn)` into `start` and `(toLine, toColumn)` into `end` verbatim — a pure
|
|
4048
|
-
* structural lift, no validation (a structurally invalid range is rejected downstream by the ranged
|
|
4049
|
-
* `write` it feeds, via {@link isValidRange}). Total — never throws. Zero-Node.
|
|
4050
|
-
*
|
|
4051
|
-
* @param fromLine - The 1-based start line
|
|
4052
|
-
* @param fromColumn - The 1-based start column
|
|
4053
|
-
* @param toLine - The 1-based end line
|
|
4054
|
-
* @param toColumn - The 1-based end column
|
|
4055
|
-
* @returns The `{ start, end }` {@link Range}
|
|
4056
|
-
*
|
|
4057
|
-
* @example
|
|
4058
|
-
* ```ts
|
|
4059
|
-
* rangeOf(1, 11, 1, 12) // { start: { line: 1, column: 11 }, end: { line: 1, column: 12 } }
|
|
4060
|
-
* ```
|
|
4061
|
-
*/
|
|
4062
|
-
export declare function rangeOf(fromLine: number, fromColumn: number, toLine: number, toColumn: number): Range;
|
|
4063
|
-
|
|
4064
|
-
/**
|
|
4065
|
-
* The outcome of a ranged {@link WorkspaceInterface.read} — the sliced `content` plus the
|
|
4066
|
-
* `range` actually applied after clamping (so a caller learns the real span it got).
|
|
4067
|
-
*
|
|
4068
|
-
* @remarks
|
|
4069
|
-
* `range` is the input {@link Range} CLAMPED to the file's bounds — when the requested
|
|
4070
|
-
* span reached past the end of the text, `range` reflects the trimmed span that was read,
|
|
4071
|
-
* never the original out-of-bounds request.
|
|
4072
|
-
*/
|
|
4073
|
-
export declare interface ReadResult {
|
|
4074
|
-
readonly content: string;
|
|
4075
|
-
/** The actual (clamped) range applied to produce `content`. */
|
|
4076
|
-
readonly range: Range;
|
|
4077
|
-
}
|
|
4078
|
-
|
|
4079
|
-
/**
|
|
4080
|
-
* Options for {@link WorkspaceInterface.replace} — how the `query` matches (the same axes
|
|
4081
|
-
* as {@link SearchOptions}).
|
|
4082
|
-
*
|
|
4083
|
-
* @param options - The replace options
|
|
4084
|
-
*
|
|
4085
|
-
* @remarks
|
|
4086
|
-
* - `regex` — treat `query` as a regular expression source rather than a literal substring; defaults to `false`.
|
|
4087
|
-
* - `exact` — match case-sensitively; defaults to `true`.
|
|
4088
|
-
* - `limit` — stop after this many replacements across all files; defaults to unlimited.
|
|
4089
|
-
*/
|
|
4090
|
-
export declare interface ReplaceOptions {
|
|
4091
|
-
readonly regex?: boolean;
|
|
4092
|
-
readonly exact?: boolean;
|
|
4093
|
-
readonly limit?: number;
|
|
4094
|
-
}
|
|
4095
|
-
|
|
4096
|
-
/**
|
|
4097
|
-
* The tally returned by {@link WorkspaceInterface.replace} — the `query` that ran, how
|
|
4098
|
-
* many occurrences were `replaced`, and the number of `files` changed.
|
|
4099
|
-
*/
|
|
4100
|
-
export declare interface ReplaceResult {
|
|
4101
|
-
readonly query: string;
|
|
4102
|
-
readonly replaced: number;
|
|
4103
|
-
readonly files: number;
|
|
4104
|
-
}
|
|
4105
|
-
|
|
4106
3229
|
/**
|
|
4107
3230
|
* The immutable per-run outcome value an {@link AgentInterface}'s loop replaces as it runs — the
|
|
4108
3231
|
* assembled value its `stream`'s `result` promise resolves into a settled
|
|
@@ -4219,7 +3342,7 @@ export declare interface ScopeConfiguration {
|
|
|
4219
3342
|
/**
|
|
4220
3343
|
* Allowed ACTIVE-workspace file `path`s (`undefined` ⇒ all, `[]` ⇒ none, else only-listed) —
|
|
4221
3344
|
* the filter {@link AgentContextInterface.build} applies to the active workspace's
|
|
4222
|
-
* {@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 →
|
|
4223
3346
|
* the last user message).
|
|
4224
3347
|
*/
|
|
4225
3348
|
readonly files?: readonly string[];
|
|
@@ -4234,7 +3357,7 @@ export declare interface ScopeInput extends ScopeConfiguration {
|
|
|
4234
3357
|
}
|
|
4235
3358
|
|
|
4236
3359
|
/**
|
|
4237
|
-
* 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
|
|
4238
3361
|
* allow-lists ({@link ScopeConfiguration}) plus an `id` / `name`, and a `narrow` that
|
|
4239
3362
|
* composes a tighter child by set-INTERSECTION.
|
|
4240
3363
|
*
|
|
@@ -4322,7 +3445,7 @@ export declare type ScopeManagerEventMap = {
|
|
|
4322
3445
|
* mints + stores one (never overwrites), `scopes()` lists them in insertion order.
|
|
4323
3446
|
*
|
|
4324
3447
|
* @remarks
|
|
4325
|
-
* - **Registry.** `create(input)` mints a scope (an `id` + the
|
|
3448
|
+
* - **Registry.** `create(input)` mints a scope (an `id` + the three allow-lists) and
|
|
4326
3449
|
* stores it; `count` is how many are stored. `scope(id)` looks one up; `scopes()` lists
|
|
4327
3450
|
* them in insertion order. (Keyed by minted `id`, not `name`, so two scopes may share a
|
|
4328
3451
|
* `name` and `create` always adds.)
|
|
@@ -4352,40 +3475,6 @@ export declare interface ScopeManagerOptions {
|
|
|
4352
3475
|
readonly error?: EmitterErrorHandler;
|
|
4353
3476
|
}
|
|
4354
3477
|
|
|
4355
|
-
/**
|
|
4356
|
-
* One hit from {@link WorkspaceInterface.search} — where the match was found and the line
|
|
4357
|
-
* that carried it.
|
|
4358
|
-
*
|
|
4359
|
-
* @remarks
|
|
4360
|
-
* `line` / `column` are 1-based (column `1` is the first character of the line); `length`
|
|
4361
|
-
* is the matched substring's length; `content` is the FULL line the match sits on (not
|
|
4362
|
-
* just the matched fragment), so a caller can render the hit in context.
|
|
4363
|
-
*/
|
|
4364
|
-
export declare interface SearchMatch {
|
|
4365
|
-
readonly path: string;
|
|
4366
|
-
readonly line: number;
|
|
4367
|
-
readonly column: number;
|
|
4368
|
-
readonly length: number;
|
|
4369
|
-
/** The full text of the line the match was found on. */
|
|
4370
|
-
readonly content: string;
|
|
4371
|
-
}
|
|
4372
|
-
|
|
4373
|
-
/**
|
|
4374
|
-
* Options for {@link WorkspaceInterface.search} — how the `query` matches.
|
|
4375
|
-
*
|
|
4376
|
-
* @param options - The search options
|
|
4377
|
-
*
|
|
4378
|
-
* @remarks
|
|
4379
|
-
* - `regex` — treat `query` as a regular expression source rather than a literal substring; defaults to `false`.
|
|
4380
|
-
* - `exact` — match case-sensitively; defaults to `true` (set `false` for a case-insensitive scan).
|
|
4381
|
-
* - `limit` — stop after this many matches across all files; defaults to unlimited.
|
|
4382
|
-
*/
|
|
4383
|
-
export declare interface SearchOptions {
|
|
4384
|
-
readonly regex?: boolean;
|
|
4385
|
-
readonly exact?: boolean;
|
|
4386
|
-
readonly limit?: number;
|
|
4387
|
-
}
|
|
4388
|
-
|
|
4389
3478
|
/**
|
|
4390
3479
|
* A slice of folded messages digested into a summary — the unit of compaction a
|
|
4391
3480
|
* {@link ConversationInterface} produces when it `compact`s its live tail.
|
|
@@ -4428,48 +3517,6 @@ export declare interface SectionInterface {
|
|
|
4428
3517
|
*/
|
|
4429
3518
|
export declare function settleAgentJob(agent: AgentInterface, allowPartial: boolean): Promise<AgentResult>;
|
|
4430
3519
|
|
|
4431
|
-
/**
|
|
4432
|
-
* Slice the substring of `text` spanned by a {@link Range} (start INCLUSIVE, end
|
|
4433
|
-
* EXCLUSIVE), clamping the range to the text's bounds first — the read half of the ranged
|
|
4434
|
-
* edit surface.
|
|
4435
|
-
*
|
|
4436
|
-
* @remarks
|
|
4437
|
-
* Clamps via {@link clampRange}, resolves each end to an offset via {@link offsetAt}, and
|
|
4438
|
-
* returns `text.slice(startOffset, endOffset)`. Total — never throws.
|
|
4439
|
-
*
|
|
4440
|
-
* @param text - The text to slice
|
|
4441
|
-
* @param range - The 1-based range to extract
|
|
4442
|
-
* @returns The spanned substring (empty when the clamped span is empty)
|
|
4443
|
-
*
|
|
4444
|
-
* @example
|
|
4445
|
-
* ```ts
|
|
4446
|
-
* sliceRange('hello\nworld', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }) // 'hello'
|
|
4447
|
-
* ```
|
|
4448
|
-
*/
|
|
4449
|
-
export declare function sliceRange(text: string, range: Range): string;
|
|
4450
|
-
|
|
4451
|
-
/**
|
|
4452
|
-
* Replace the span of `text` covered by a {@link Range} with `replacement` (start
|
|
4453
|
-
* INCLUSIVE, end EXCLUSIVE), clamping the range to the text's bounds first — the write
|
|
4454
|
-
* half of the ranged edit surface.
|
|
4455
|
-
*
|
|
4456
|
-
* @remarks
|
|
4457
|
-
* Clamps via {@link clampRange}, then stitches `before + replacement + after` around the
|
|
4458
|
-
* resolved offsets. An empty span (`start === end`) becomes a pure insertion. Total —
|
|
4459
|
-
* never throws.
|
|
4460
|
-
*
|
|
4461
|
-
* @param text - The original text
|
|
4462
|
-
* @param range - The 1-based range to overwrite
|
|
4463
|
-
* @param replacement - The text to splice in place of the spanned range
|
|
4464
|
-
* @returns The text with the spanned range replaced by `replacement`
|
|
4465
|
-
*
|
|
4466
|
-
* @example
|
|
4467
|
-
* ```ts
|
|
4468
|
-
* spliceRange('hello', { start: { line: 1, column: 1 }, end: { line: 1, column: 6 } }, 'bye') // 'bye'
|
|
4469
|
-
* ```
|
|
4470
|
-
*/
|
|
4471
|
-
export declare function spliceRange(text: string, range: Range, replacement: string): string;
|
|
4472
|
-
|
|
4473
3520
|
/**
|
|
4474
3521
|
* A live event stream paired with the eventual settled result and a cancel — the
|
|
4475
3522
|
* generic pull/streaming handle a long-running operation hands back.
|
|
@@ -4599,299 +3646,6 @@ export declare interface ThinkSplitterInterface {
|
|
|
4599
3646
|
flush(): string;
|
|
4600
3647
|
}
|
|
4601
3648
|
|
|
4602
|
-
/**
|
|
4603
|
-
* A registered tool — its {@link import('../types.js').ToolDefinition} schema (the
|
|
4604
|
-
* `name` / `description` / `parameters` the model sees) bound to the `execute`
|
|
4605
|
-
* handler that runs a call.
|
|
4606
|
-
*
|
|
4607
|
-
* @remarks
|
|
4608
|
-
* A thin value object: the constructor stores the schema fields and the handler, and
|
|
4609
|
-
* `execute` delegates to the handler verbatim. `parameters` is kept by reference (the
|
|
4610
|
-
* open JSON-Schema the provider forwards as-is) — not cloned. The handler's `args` is
|
|
4611
|
-
* the model-supplied `unknown` arguments record, narrowed inside the handler (§14);
|
|
4612
|
-
* isolating a throw is the {@link ToolManager}'s job, not this class's. Event-free —
|
|
4613
|
-
* no Emitter, no events.
|
|
4614
|
-
*
|
|
4615
|
-
* @example
|
|
4616
|
-
* ```ts
|
|
4617
|
-
* const tool = new Tool({
|
|
4618
|
-
* name: 'add',
|
|
4619
|
-
* description: 'Add two numbers',
|
|
4620
|
-
* parameters: { type: 'object', properties: { a: { type: 'number' }, b: { type: 'number' } } },
|
|
4621
|
-
* execute: (args) => Number(args.a) + Number(args.b),
|
|
4622
|
-
* })
|
|
4623
|
-
* ```
|
|
4624
|
-
*/
|
|
4625
|
-
export declare class Tool implements ToolInterface {
|
|
4626
|
-
#private;
|
|
4627
|
-
readonly name: string;
|
|
4628
|
-
readonly description?: string;
|
|
4629
|
-
readonly summary?: string;
|
|
4630
|
-
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
4631
|
-
constructor(options: ToolOptions);
|
|
4632
|
-
execute(args: Readonly<Record<string, unknown>>): Promise<unknown> | unknown;
|
|
4633
|
-
}
|
|
4634
|
-
|
|
4635
|
-
/**
|
|
4636
|
-
* A tool call the model emitted — the tool `name` and its parsed `arguments`.
|
|
4637
|
-
*
|
|
4638
|
-
* @remarks
|
|
4639
|
-
* `id` correlates the call with its later {@link ToolResult}; when the wire omits an
|
|
4640
|
-
* id the provider mints one (a random UUID) so every call is addressable. `arguments`
|
|
4641
|
-
* is always a record — the provider narrows the wire value (an object, or a JSON
|
|
4642
|
-
* string it parses) to one, defaulting to `{}` when neither.
|
|
4643
|
-
*/
|
|
4644
|
-
export declare interface ToolCall {
|
|
4645
|
-
readonly id: string;
|
|
4646
|
-
readonly name: string;
|
|
4647
|
-
readonly arguments: Readonly<Record<string, unknown>>;
|
|
4648
|
-
}
|
|
4649
|
-
|
|
4650
|
-
/**
|
|
4651
|
-
* The MCP `CallToolResult` shape a {@link ToolResult} maps to via {@link buildToolResult} —
|
|
4652
|
-
* `content` blocks plus an `isError` flag set ONLY on failure (never `false`).
|
|
4653
|
-
*/
|
|
4654
|
-
export declare interface ToolCallResult {
|
|
4655
|
-
readonly content: readonly ToolResultContent[];
|
|
4656
|
-
readonly isError?: true;
|
|
4657
|
-
}
|
|
4658
|
-
|
|
4659
|
-
/**
|
|
4660
|
-
* A tool the model may call — its name, an optional description, and an optional
|
|
4661
|
-
* JSON-Schema `parameters` object describing its arguments.
|
|
4662
|
-
*
|
|
4663
|
-
* @remarks
|
|
4664
|
-
* Passed to a {@link ProviderInterface}'s `generate` / `stream`; the provider maps
|
|
4665
|
-
* each into the wire's function-tool shape. `parameters` is an open JSON-Schema
|
|
4666
|
-
* record (the provider forwards it verbatim).
|
|
4667
|
-
*/
|
|
4668
|
-
export declare interface ToolDefinition {
|
|
4669
|
-
readonly name: string;
|
|
4670
|
-
readonly description?: string;
|
|
4671
|
-
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
4672
|
-
}
|
|
4673
|
-
|
|
4674
|
-
/**
|
|
4675
|
-
* A registered tool: its {@link ToolDefinition} (the schema the model sees) plus the
|
|
4676
|
-
* handler that runs a call.
|
|
4677
|
-
*
|
|
4678
|
-
* @remarks
|
|
4679
|
-
* The definition fields (`name` / `description` / `parameters`) are what a
|
|
4680
|
-
* {@link ProviderInterface} advertises to the model; `execute` is the local handler a
|
|
4681
|
-
* {@link ToolManagerInterface} invokes when the model calls the tool. The handler's
|
|
4682
|
-
* `args` is the model-supplied `unknown` JSON object — narrow it inside the handler
|
|
4683
|
-
* (§14), never assert; the manager isolates a throw into a {@link ToolResult} `error`.
|
|
4684
|
-
*/
|
|
4685
|
-
export declare interface ToolInterface extends ToolDefinition {
|
|
4686
|
-
/**
|
|
4687
|
-
* A one-or-two-sentence concise description advertised to the model IN PLACE of the
|
|
4688
|
-
* full `description` (which stays on the tool for on-demand retrieval, e.g. a
|
|
4689
|
-
* describe tool); absent ⇒ the full `description` is advertised exactly as today.
|
|
4690
|
-
*/
|
|
4691
|
-
readonly summary?: string;
|
|
4692
|
-
/**
|
|
4693
|
-
* Run the tool. `args` is the model-supplied `unknown` JSON object — narrow it
|
|
4694
|
-
* inside (§14); the manager isolates a throw into a {@link ToolResult} `error`.
|
|
4695
|
-
*
|
|
4696
|
-
* @param args - The model-supplied arguments record (an open `unknown` object)
|
|
4697
|
-
* @returns The tool's result (sync or async) — folded into a `ToolResult.value`
|
|
4698
|
-
*/
|
|
4699
|
-
execute(args: Readonly<Record<string, unknown>>): Promise<unknown> | unknown;
|
|
4700
|
-
}
|
|
4701
|
-
|
|
4702
|
-
/**
|
|
4703
|
-
* The tool registry the agent loop dispatches model tool-calls through — resolves
|
|
4704
|
-
* names, lists {@link ToolDefinition}s for the provider, and executes calls with
|
|
4705
|
-
* per-call error isolation.
|
|
4706
|
-
*
|
|
4707
|
-
* @remarks
|
|
4708
|
-
* - **Registry.** Tools live in an insertion-ordered `Map` keyed by `tool.name`;
|
|
4709
|
-
* `add` takes one or a batch (§9.2) and a re-`add` of the same name OVERWRITES it
|
|
4710
|
-
* (last write wins). `count` is the map size, `tool(name)` looks one up, `tools()`
|
|
4711
|
-
* lists them in insertion order, and `definitions()` maps each to a plain
|
|
4712
|
-
* {@link ToolDefinition} (`name` / `description?` / `parameters?`, the `execute`
|
|
4713
|
-
* handler stripped) — exactly what a provider advertises to the model, with
|
|
4714
|
-
* `tool.summary ?? tool.description` advertised as `description` (a lean `summary`
|
|
4715
|
-
* stands in for the full text when set).
|
|
4716
|
-
* - **Per-call error isolation (the load-bearing part).** `execute` resolves a
|
|
4717
|
-
* {@link ToolCall}'s tool by name and ALWAYS resolves a {@link ToolResult}: an
|
|
4718
|
-
* unknown name → `{ id, name, error: 'tool not found: <name>' }`; a successful run →
|
|
4719
|
-
* `{ id, name, value }`; a handler throw is CAUGHT into `{ id, name, error }` (an
|
|
4720
|
-
* `Error`'s message, else the stringified throw). A tool throw never escapes — it
|
|
4721
|
-
* becomes a result the model can react to.
|
|
4722
|
-
* - **Batch never fails as a whole.** `execute(calls)` runs every call via
|
|
4723
|
-
* `Promise.all(calls.map(...))` and resolves the results correlated by `id` in the
|
|
4724
|
-
* input order — a mix of success, throw, and not-found all resolve; one bad call
|
|
4725
|
-
* does not reject the batch.
|
|
4726
|
-
* - **Event-free.** A purely functional registry — no Emitter, no events.
|
|
4727
|
-
*
|
|
4728
|
-
* @example
|
|
4729
|
-
* ```ts
|
|
4730
|
-
* const manager = new ToolManager()
|
|
4731
|
-
* manager.add(new Tool({ name: 'add', execute: (a) => Number(a.x) + Number(a.y) }))
|
|
4732
|
-
* const result = await manager.execute({ id: '1', name: 'add', arguments: { x: 1, y: 2 } })
|
|
4733
|
-
* result.value // 3
|
|
4734
|
-
* ```
|
|
4735
|
-
*/
|
|
4736
|
-
export declare class ToolManager implements ToolManagerInterface {
|
|
4737
|
-
#private;
|
|
4738
|
-
get count(): number;
|
|
4739
|
-
add(tool: ToolInterface): void;
|
|
4740
|
-
add(tools: readonly ToolInterface[]): void;
|
|
4741
|
-
tool(name: string): ToolInterface | undefined;
|
|
4742
|
-
tools(): readonly ToolInterface[];
|
|
4743
|
-
definitions(): readonly ToolDefinition[];
|
|
4744
|
-
execute(call: ToolCall): Promise<ToolResult>;
|
|
4745
|
-
execute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
|
|
4746
|
-
remove(name: string): boolean;
|
|
4747
|
-
remove(names: readonly string[]): boolean;
|
|
4748
|
-
clear(): void;
|
|
4749
|
-
}
|
|
4750
|
-
|
|
4751
|
-
/**
|
|
4752
|
-
* A registry of tools — resolves names, lists definitions for the provider, and
|
|
4753
|
-
* executes calls with per-call error isolation.
|
|
4754
|
-
*
|
|
4755
|
-
* @remarks
|
|
4756
|
-
* - **Registry.** `add` registers one tool or a batch (§9.2), keyed by `tool.name`
|
|
4757
|
-
* (a re-`add` of the same name overwrites — last write wins); `count` is the number
|
|
4758
|
-
* registered. `tool(name)` looks one up; `tools()` lists them in insertion order;
|
|
4759
|
-
* `definitions()` strips each to a plain {@link ToolDefinition} for the provider,
|
|
4760
|
-
* advertising `tool.summary ?? tool.description` in the definition's `description`
|
|
4761
|
-
* field — a lean `summary` stands in for the full `description` when set.
|
|
4762
|
-
* - **Per-call error isolation.** `execute` resolves a {@link ToolCall}'s tool by name
|
|
4763
|
-
* and runs it, ALWAYS resolving a {@link ToolResult}: a success carries `value`, a
|
|
4764
|
-
* handler throw is caught into `error`, and an unknown name becomes a not-found
|
|
4765
|
-
* `error`. A tool throw NEVER escapes — it becomes a result the model can react to.
|
|
4766
|
-
* - **Batch never fails as a whole.** The array `execute` runs every call (via
|
|
4767
|
-
* `Promise.all`) and resolves results correlated by `id` in order — one bad call
|
|
4768
|
-
* (throw or not-found) does not fail the batch.
|
|
4769
|
-
* - **Event-free.** A purely functional registry — no Emitter, no events.
|
|
4770
|
-
*/
|
|
4771
|
-
export declare interface ToolManagerInterface {
|
|
4772
|
-
readonly count: number;
|
|
4773
|
-
add(tool: ToolInterface): void;
|
|
4774
|
-
add(tools: readonly ToolInterface[]): void;
|
|
4775
|
-
tool(name: string): ToolInterface | undefined;
|
|
4776
|
-
tools(): readonly ToolInterface[];
|
|
4777
|
-
definitions(): readonly ToolDefinition[];
|
|
4778
|
-
execute(call: ToolCall): Promise<ToolResult>;
|
|
4779
|
-
execute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
|
|
4780
|
-
remove(name: string): boolean;
|
|
4781
|
-
remove(names: readonly string[]): boolean;
|
|
4782
|
-
clear(): void;
|
|
4783
|
-
}
|
|
4784
|
-
|
|
4785
|
-
/**
|
|
4786
|
-
* Options for `createTool` — the schema the model sees (`name` / `description` /
|
|
4787
|
-
* `parameters`) plus the `execute` handler that runs a call.
|
|
4788
|
-
*
|
|
4789
|
-
* @remarks
|
|
4790
|
-
* `name` is required (it keys the tool in a {@link ToolManagerInterface} and is what
|
|
4791
|
-
* the model calls); `description` and `parameters` are the optional JSON-Schema the
|
|
4792
|
-
* provider advertises (forwarded verbatim). `summary`, when set, is a lean
|
|
4793
|
-
* one-or-two-sentence advertisement used IN PLACE of `description` in a
|
|
4794
|
-
* {@link ToolManagerInterface.definitions} listing — `description` stays available on
|
|
4795
|
-
* the tool for on-demand retrieval. `execute` receives the model-supplied arguments
|
|
4796
|
-
* record and returns the tool's result (sync or async).
|
|
4797
|
-
*/
|
|
4798
|
-
export declare interface ToolOptions {
|
|
4799
|
-
readonly name: string;
|
|
4800
|
-
readonly description?: string;
|
|
4801
|
-
readonly summary?: string;
|
|
4802
|
-
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
4803
|
-
readonly execute: (args: Readonly<Record<string, unknown>>) => Promise<unknown> | unknown;
|
|
4804
|
-
}
|
|
4805
|
-
|
|
4806
|
-
/**
|
|
4807
|
-
* The outcome of executing a {@link ToolCall} — keyed back to the call by `id` and
|
|
4808
|
-
* `name`, carrying either a `value` (the result) or an `error` string (the failure).
|
|
4809
|
-
*/
|
|
4810
|
-
export declare interface ToolResult {
|
|
4811
|
-
readonly id: string;
|
|
4812
|
-
readonly name: string;
|
|
4813
|
-
readonly value?: unknown;
|
|
4814
|
-
readonly error?: string;
|
|
4815
|
-
}
|
|
4816
|
-
|
|
4817
|
-
/**
|
|
4818
|
-
* One block of an MCP-shaped tool call response — plain text, the only content kind
|
|
4819
|
-
* {@link buildToolResult} emits.
|
|
4820
|
-
*/
|
|
4821
|
-
export declare interface ToolResultContent {
|
|
4822
|
-
readonly type: 'text';
|
|
4823
|
-
readonly text: string;
|
|
4824
|
-
}
|
|
4825
|
-
|
|
4826
|
-
/**
|
|
4827
|
-
* A mutable, `path`-keyed working set of immutable {@link FileInterface}s — the
|
|
4828
|
-
* in-memory editing surface over the file primitive.
|
|
4829
|
-
*
|
|
4830
|
-
* @remarks
|
|
4831
|
-
* - **Registry.** Files live in an insertion-ordered `Map` keyed by `path`; `count` is the
|
|
4832
|
-
* map size, `file(path)` looks one up, and `files()` lists them in insertion order.
|
|
4833
|
-
* - **Write replaces the File (§11 immutability).** Every edit MINTS a replacement
|
|
4834
|
-
* {@link FileInterface} (via {@link import('../factories.js').createFile}) rather than
|
|
4835
|
-
* mutating in place, transitioning `state` to `'created'` for a brand-new path or
|
|
4836
|
-
* `'modified'` for an existing one. A whole-file string write preserves an existing text
|
|
4837
|
-
* file's `language`, else infers it from the `path` (`inferLanguage`); writing a string
|
|
4838
|
-
* onto an existing BINARY path replaces it with a text file (a deliberate retype). A
|
|
4839
|
-
* ranged `write` splices a `Range` of an existing text file.
|
|
4840
|
-
* - **Modality rules.** Text-only ops on a binary file are rejected: a ranged `read` /
|
|
4841
|
-
* `write`, `prepend`, and `append` throw `MODALITY`; a plain `read(path)` of a binary
|
|
4842
|
-
* file returns `undefined`; `search` / `replace` skip binary files (0 matches).
|
|
4843
|
-
* - **In-memory removal.** `remove(path)` / `remove(paths)` drop files outright (no
|
|
4844
|
-
* tombstone — the `'loaded'` / `'deleted'` states are reserved for a future FileStore);
|
|
4845
|
-
* `remove()` and `clear()` both empty the registry and emit the single `clear` signal.
|
|
4846
|
-
* The disk/sync lifecycle (`load` / `revert` / `accept` / `purge` / `dirty`) is NOT part
|
|
4847
|
-
* of this surface.
|
|
4848
|
-
* - **Observable (§13).** The owned {@link emitter} ({@link WorkspaceEventMap}) carries
|
|
4849
|
-
* `write` (the resulting file) / `remove` (the path) / `move` (`{ from, to }`) / `clear`.
|
|
4850
|
-
* Every event is emitted directly, strictly AFTER the map mutation completes; the
|
|
4851
|
-
* emitter isolates a listener throw and routes it to its `error` handler, so a buggy
|
|
4852
|
-
* observer can never corrupt a mutation.
|
|
4853
|
-
*
|
|
4854
|
-
* @example
|
|
4855
|
-
* ```ts
|
|
4856
|
-
* const workspace = new Workspace()
|
|
4857
|
-
* workspace.write('src/main.ts', 'const x = 1')
|
|
4858
|
-
* workspace.file('src/main.ts')?.state // 'created'
|
|
4859
|
-
* workspace.append('src/main.ts', '\nconst y = 2')
|
|
4860
|
-
* workspace.file('src/main.ts')?.state // 'modified'
|
|
4861
|
-
* workspace.read('src/main.ts') // 'const x = 1\nconst y = 2'
|
|
4862
|
-
* ```
|
|
4863
|
-
*/
|
|
4864
|
-
export declare class Workspace implements WorkspaceInterface {
|
|
4865
|
-
#private;
|
|
4866
|
-
constructor(options?: WorkspaceOptions, seed?: Iterable<readonly [string, FileInterface]>);
|
|
4867
|
-
get id(): string;
|
|
4868
|
-
get emitter(): EmitterInterface<WorkspaceEventMap>;
|
|
4869
|
-
get count(): number;
|
|
4870
|
-
file(path: string): FileInterface | undefined;
|
|
4871
|
-
files(): readonly FileInterface[];
|
|
4872
|
-
read(path: string): string | undefined;
|
|
4873
|
-
read(path: string, range: Range): ReadResult | undefined;
|
|
4874
|
-
read(paths: readonly string[]): Readonly<Record<string, string>>;
|
|
4875
|
-
has(path: string): boolean;
|
|
4876
|
-
has(paths: readonly string[]): boolean;
|
|
4877
|
-
search(query: string, options?: SearchOptions): readonly SearchMatch[];
|
|
4878
|
-
replace(query: string, replacement: string, options?: ReplaceOptions): ReplaceResult;
|
|
4879
|
-
write(path: string, content: string): void;
|
|
4880
|
-
write(path: string, content: string, range: Range): void;
|
|
4881
|
-
write(files: Readonly<Record<string, string>>): void;
|
|
4882
|
-
prepend(path: string, content: string): void;
|
|
4883
|
-
prepend(files: Readonly<Record<string, string>>): void;
|
|
4884
|
-
append(path: string, content: string): void;
|
|
4885
|
-
append(files: Readonly<Record<string, string>>): void;
|
|
4886
|
-
move(from: string, to: string): boolean;
|
|
4887
|
-
move(mapping: Readonly<Record<string, string>>): boolean;
|
|
4888
|
-
remove(): void;
|
|
4889
|
-
remove(path: string): boolean;
|
|
4890
|
-
remove(paths: readonly string[]): boolean;
|
|
4891
|
-
clear(): void;
|
|
4892
|
-
snapshot(): WorkspaceSnapshot;
|
|
4893
|
-
}
|
|
4894
|
-
|
|
4895
3649
|
/**
|
|
4896
3650
|
* The section header {@link import('./AgentContext.js').AgentContext}'s `build()` renders the
|
|
4897
3651
|
* ACTIVE workspace's TEXT files under — the leading line of the dedicated workspace block in the
|
|
@@ -4906,393 +3660,4 @@ export declare class Workspace implements WorkspaceInterface {
|
|
|
4906
3660
|
*/
|
|
4907
3661
|
export declare const WORKSPACE_SECTION_HEADER = "## Workspace";
|
|
4908
3662
|
|
|
4909
|
-
/**
|
|
4910
|
-
* An error thrown by the in-memory {@link import('./workspaces/Workspace.js').Workspace} edit
|
|
4911
|
-
* surface.
|
|
4912
|
-
*
|
|
4913
|
-
* @remarks
|
|
4914
|
-
* Carries a {@link WorkspaceErrorCode} and an optional `context` bag naming the offending
|
|
4915
|
-
* path / range. Thrown for a text-only operation aimed at an image file (`MODALITY` — a
|
|
4916
|
-
* ranged read / write, `prepend`, or `append`), an invalid `search` / `replace` regular
|
|
4917
|
-
* expression (`PATTERN`), and a structurally invalid ranged-write {@link import('./types.js').Range}
|
|
4918
|
-
* (`RANGE` — inverted, or a sub-1 line / column).
|
|
4919
|
-
*/
|
|
4920
|
-
export declare class WorkspaceError extends Error {
|
|
4921
|
-
readonly code: WorkspaceErrorCode;
|
|
4922
|
-
readonly context?: Readonly<Record<string, unknown>>;
|
|
4923
|
-
constructor(code: WorkspaceErrorCode, message: string, context?: Readonly<Record<string, unknown>>);
|
|
4924
|
-
}
|
|
4925
|
-
|
|
4926
|
-
/**
|
|
4927
|
-
* The machine-readable code a {@link import('./errors.js').WorkspaceError} carries
|
|
4928
|
-
* (AGENTS §12) — a `catch` branches on `error.code` instead of parsing the message.
|
|
4929
|
-
*
|
|
4930
|
-
* @remarks
|
|
4931
|
-
* - `MODALITY` — a text-only op (ranged read/write, `prepend`, `append`) was aimed at a binary file.
|
|
4932
|
-
* - `PATTERN` — a `search` / `replace` `query` was an invalid regular expression (with `regex: true`).
|
|
4933
|
-
* - `RANGE` — a ranged `write` got a structurally invalid {@link Range} (inverted, or a sub-1 line/column).
|
|
4934
|
-
* - `TOOL` — a handler-level validation fault raised by a workspace-editing tool boundary (see
|
|
4935
|
-
* `@orkestrel/tool`) when the agent-supplied args were malformed / unknown. Distinct from the
|
|
4936
|
-
* surface faults above (which the live workspace raises) — this is the tool boundary rejecting an
|
|
4937
|
-
* un-parseable operation before any workspace call.
|
|
4938
|
-
*/
|
|
4939
|
-
export declare type WorkspaceErrorCode = 'MODALITY' | 'PATTERN' | 'RANGE' | 'TOOL';
|
|
4940
|
-
|
|
4941
|
-
/**
|
|
4942
|
-
* The observable events a {@link import('./workspaces/Workspace.js').Workspace} emits
|
|
4943
|
-
* (AGENTS §13) — each fired AFTER the corresponding mutation completes.
|
|
4944
|
-
*
|
|
4945
|
-
* @remarks
|
|
4946
|
-
* - `write` — a file was written / edited, carrying the resulting {@link FileInterface}.
|
|
4947
|
-
* - `remove` — a single file was dropped, carrying its `path`.
|
|
4948
|
-
* - `move` — a file was re-keyed, carrying `{ from, to }`.
|
|
4949
|
-
* - `clear` — the workspace was emptied (the canonical "emptied" signal, fired by both `remove()` and `clear()`).
|
|
4950
|
-
*/
|
|
4951
|
-
export declare type WorkspaceEventMap = {
|
|
4952
|
-
readonly write: readonly [file: FileInterface];
|
|
4953
|
-
readonly remove: readonly [path: string];
|
|
4954
|
-
readonly move: readonly [move: {
|
|
4955
|
-
readonly from: string;
|
|
4956
|
-
readonly to: string;
|
|
4957
|
-
}];
|
|
4958
|
-
readonly clear: readonly [];
|
|
4959
|
-
};
|
|
4960
|
-
|
|
4961
|
-
/**
|
|
4962
|
-
* The data to author a {@link WorkspaceInterface} through a
|
|
4963
|
-
* {@link WorkspaceManagerInterface} — the optional `id`, the reserved `on` hooks + `error`
|
|
4964
|
-
* handler (§13), and an optional `seed` of initial files.
|
|
4965
|
-
*
|
|
4966
|
-
* @remarks
|
|
4967
|
-
* `id` is the workspace's identity (minted when omitted). `on` / `error` are the §8/§13
|
|
4968
|
-
* keys (initial {@link WorkspaceEventMap} listeners + the listener-error handler), flowing
|
|
4969
|
-
* the manager's defaults in unless overridden. `seed` is the construction-time hydration
|
|
4970
|
-
* seam (path → {@link FileInterface}) — the only way to seat a non-text (binary) file, and
|
|
4971
|
-
* what a future FileStore reads a snapshot into; seeding is silent (no `write` events).
|
|
4972
|
-
*/
|
|
4973
|
-
export declare interface WorkspaceInput {
|
|
4974
|
-
readonly id?: string;
|
|
4975
|
-
readonly on?: EmitterHooks<WorkspaceEventMap>;
|
|
4976
|
-
readonly error?: EmitterErrorHandler;
|
|
4977
|
-
/** Pre-seeded initial files (path → File), placed silently at construction. */
|
|
4978
|
-
readonly seed?: Iterable<readonly [string, FileInterface]>;
|
|
4979
|
-
}
|
|
4980
|
-
|
|
4981
|
-
/**
|
|
4982
|
-
* A mutable, `path`-keyed working set of immutable {@link FileInterface}s — the in-memory
|
|
4983
|
-
* editing surface over the file primitive.
|
|
4984
|
-
*
|
|
4985
|
-
* @remarks
|
|
4986
|
-
* Files live in an insertion-ordered map keyed by `path`. Every edit REPLACES the
|
|
4987
|
-
* immutable {@link FileInterface} at a path with a new one (transitioning its `state` to
|
|
4988
|
-
* `'created'` for a fresh path or `'modified'` for an existing one) rather than mutating in
|
|
4989
|
-
* place. The disk/sync lifecycle (`load` / `revert` / `accept` / `purge` / `dirty`) is
|
|
4990
|
-
* deliberately NOT part of this surface — it is deferred to a future FileStore. Text-only
|
|
4991
|
-
* operations on a binary file are governed by the modality rules (a ranged read/write,
|
|
4992
|
-
* `prepend`, and `append` throw `MODALITY`; a plain `read` returns `undefined`; `search` /
|
|
4993
|
-
* `replace` skip the file). Observe mutations through the owned {@link emitter} (AGENTS §13).
|
|
4994
|
-
*/
|
|
4995
|
-
export declare interface WorkspaceInterface {
|
|
4996
|
-
/** The workspace's identity — its key in a {@link WorkspaceManagerInterface}; minted when not supplied. */
|
|
4997
|
-
readonly id: string;
|
|
4998
|
-
/** The push observation surface (AGENTS §13) — `write` / `remove` / `move` / `clear`. */
|
|
4999
|
-
readonly emitter: EmitterInterface<WorkspaceEventMap>;
|
|
5000
|
-
/** The number of files currently held. */
|
|
5001
|
-
readonly count: number;
|
|
5002
|
-
/** Look up one file by path, or `undefined` when absent. */
|
|
5003
|
-
file(path: string): FileInterface | undefined;
|
|
5004
|
-
/** List every file in insertion order. */
|
|
5005
|
-
files(): readonly FileInterface[];
|
|
5006
|
-
read(path: string): string | undefined;
|
|
5007
|
-
read(path: string, range: Range): ReadResult | undefined;
|
|
5008
|
-
read(paths: readonly string[]): Readonly<Record<string, string>>;
|
|
5009
|
-
has(path: string): boolean;
|
|
5010
|
-
has(paths: readonly string[]): boolean;
|
|
5011
|
-
/** Scan every text file's lines for `query`, returning each hit in insertion order. */
|
|
5012
|
-
search(query: string, options?: SearchOptions): readonly SearchMatch[];
|
|
5013
|
-
/** Replace `query` with `replacement` across every text file, returning the tally. */
|
|
5014
|
-
replace(query: string, replacement: string, options?: ReplaceOptions): ReplaceResult;
|
|
5015
|
-
write(path: string, content: string): void;
|
|
5016
|
-
write(path: string, content: string, range: Range): void;
|
|
5017
|
-
write(files: Readonly<Record<string, string>>): void;
|
|
5018
|
-
prepend(path: string, content: string): void;
|
|
5019
|
-
prepend(files: Readonly<Record<string, string>>): void;
|
|
5020
|
-
append(path: string, content: string): void;
|
|
5021
|
-
append(files: Readonly<Record<string, string>>): void;
|
|
5022
|
-
move(from: string, to: string): boolean;
|
|
5023
|
-
move(mapping: Readonly<Record<string, string>>): boolean;
|
|
5024
|
-
remove(): void;
|
|
5025
|
-
remove(path: string): boolean;
|
|
5026
|
-
remove(paths: readonly string[]): boolean;
|
|
5027
|
-
/** Empty the workspace (emits `clear`). */
|
|
5028
|
-
clear(): void;
|
|
5029
|
-
/**
|
|
5030
|
-
* Serialize this workspace to a plain, JSON-serializable {@link WorkspaceSnapshot} — its
|
|
5031
|
-
* `id` plus a flat list of its {@link FileInterface}s (each already carries its `path`).
|
|
5032
|
-
*
|
|
5033
|
-
* @remarks
|
|
5034
|
-
* The container serializes ITSELF (`{ id: this.id, files: this.files() }`) — the
|
|
5035
|
-
* {@link WorkspaceStoreInterface} persistence seam's payload, paralleling the
|
|
5036
|
-
* {@link ConversationInterface}'s own snapshot a later track adds. The snapshot is the
|
|
5037
|
-
* durable analogue of the constructor `seed`: a {@link WorkspaceManagerInterface} HYDRATES a
|
|
5038
|
-
* workspace from `snapshot.files` through that seam (see {@link WorkspaceManagerInterface.open}).
|
|
5039
|
-
* Pure — the `File`s are already frozen plain records (so the snapshot `structuredClone`s /
|
|
5040
|
-
* JSON-round-trips losslessly), and snapshotting mutates nothing.
|
|
5041
|
-
*
|
|
5042
|
-
* @returns The {@link WorkspaceSnapshot} (`{ id, files }`)
|
|
5043
|
-
*/
|
|
5044
|
-
snapshot(): WorkspaceSnapshot;
|
|
5045
|
-
}
|
|
5046
|
-
|
|
5047
|
-
/**
|
|
5048
|
-
* The registry of {@link Workspace}s keyed by `id`, in insertion order, WITH an active pointer
|
|
5049
|
-
* — the §9 store over the workspace layer PLUS the `active` / `switch` seam the context renders.
|
|
5050
|
-
* Event-free (a registry, like {@link ConversationManager}); the observability lives on each
|
|
5051
|
-
* {@link Workspace}.
|
|
5052
|
-
*
|
|
5053
|
-
* @remarks
|
|
5054
|
-
* - **Registry.** Workspaces live in an insertion-ordered `Map` keyed by `id`. `add(input?)`
|
|
5055
|
-
* mints a {@link Workspace} (its `id` from `input` or `crypto.randomUUID()`), flowing the
|
|
5056
|
-
* manager's default `on` / `error` in unless the `input` OVERRIDES them, and stores it (an
|
|
5057
|
-
* already-present `id` OVERWRITES — last write wins). `count` is the map size, `workspace(id)`
|
|
5058
|
-
* looks one up, `workspaces()` lists them in insertion order.
|
|
5059
|
-
* - **Active pointer.** `active` is the active workspace (what the context renders), `undefined`
|
|
5060
|
-
* until the FIRST `add` (which auto-activates it — a registry with workspaces always has one
|
|
5061
|
-
* active). A subsequent `add` leaves `active` unchanged. `switch(id)` re-points `active` to the
|
|
5062
|
-
* workspace with `id` and returns it; an unknown `id` returns `undefined` and leaves `active`
|
|
5063
|
-
* unchanged (the lenient lookup style — never throws, no new error code).
|
|
5064
|
-
* - **Removal.** `remove` drops one by id, or a batch (§9.2) — `true` when any was removed;
|
|
5065
|
-
* removing the ACTIVE workspace sets `active` to `undefined`. `clear` empties the registry and
|
|
5066
|
-
* sets `active` to `undefined`.
|
|
5067
|
-
* - **Durable open / save (the optional `store`).** With a {@link WorkspaceStoreInterface} supplied
|
|
5068
|
-
* (the `store` option), `open(id)` HYDRATES a workspace on a registry miss — it `store.get(id)`s
|
|
5069
|
-
* the snapshot and rebuilds a fresh {@link Workspace} through the constructor `seed`
|
|
5070
|
-
* (`snapshot.files` → path → File), then activates it — and `save(id)` PERSISTS a registered
|
|
5071
|
-
* workspace's `snapshot()`. Both are LENIENT without a store (open resolves only registered ids,
|
|
5072
|
-
* save is a no-op `false`), consistent with the lenient `switch`.
|
|
5073
|
-
* - **Event-free.** A purely registry store — no Emitter, no events (each workspace owns its own
|
|
5074
|
-
* observable `emitter`).
|
|
5075
|
-
*
|
|
5076
|
-
* @example
|
|
5077
|
-
* ```ts
|
|
5078
|
-
* const manager = new WorkspaceManager()
|
|
5079
|
-
* const first = manager.add() // auto-activates — active === first
|
|
5080
|
-
* manager.add({ id: 'scratch' }) // leaves active unchanged
|
|
5081
|
-
* manager.switch('scratch') // re-points active to the 'scratch' workspace
|
|
5082
|
-
* manager.count // 2
|
|
5083
|
-
* ```
|
|
5084
|
-
*/
|
|
5085
|
-
export declare class WorkspaceManager implements WorkspaceManagerInterface {
|
|
5086
|
-
#private;
|
|
5087
|
-
constructor(options?: WorkspaceManagerOptions);
|
|
5088
|
-
get count(): number;
|
|
5089
|
-
get active(): WorkspaceInterface | undefined;
|
|
5090
|
-
workspace(id: string): WorkspaceInterface | undefined;
|
|
5091
|
-
workspaces(): readonly WorkspaceInterface[];
|
|
5092
|
-
add(input?: WorkspaceInput): WorkspaceInterface;
|
|
5093
|
-
switch(id: string): WorkspaceInterface | undefined;
|
|
5094
|
-
open(id: string): Promise<WorkspaceInterface | undefined>;
|
|
5095
|
-
save(id: string): Promise<boolean>;
|
|
5096
|
-
remove(ids: readonly string[]): boolean;
|
|
5097
|
-
remove(id: string): boolean;
|
|
5098
|
-
clear(): void;
|
|
5099
|
-
}
|
|
5100
|
-
|
|
5101
|
-
/**
|
|
5102
|
-
* A registry of {@link WorkspaceInterface}s keyed by their `id`, in insertion order, WITH an
|
|
5103
|
-
* active pointer — the §9 store over the workspace layer PLUS the `active` / `switch` seam the
|
|
5104
|
-
* context renders. Event-free (each {@link WorkspaceInterface} owns its own `emitter`).
|
|
5105
|
-
*
|
|
5106
|
-
* @remarks
|
|
5107
|
-
* - **Registry.** `count` is how many are stored. `add(input?)` mints a
|
|
5108
|
-
* {@link WorkspaceInterface} (its `id` from `input` or a random UUID), flowing the manager's
|
|
5109
|
-
* default `on` / `error` in unless the `input` overrides them; `add` of an already-present
|
|
5110
|
-
* `id` OVERWRITES it (last write wins). `workspace(id)` looks one up (`undefined` when
|
|
5111
|
-
* absent); `workspaces()` lists them in insertion order.
|
|
5112
|
-
* - **Active pointer.** `active` is the active workspace (what the context renders), `undefined`
|
|
5113
|
-
* until the FIRST `add` (which auto-activates it). A later `add` leaves `active` unchanged.
|
|
5114
|
-
* `switch(id)` re-points `active` to the workspace with `id` and returns it; an unknown `id`
|
|
5115
|
-
* returns `undefined` and leaves `active` unchanged (the lenient lookup style — never throws).
|
|
5116
|
-
* - **Removal.** `remove` drops one by id, or a batch (§9.2, array overload FIRST) — `true`
|
|
5117
|
-
* when any was removed; removing the ACTIVE workspace sets `active` to `undefined`. `clear`
|
|
5118
|
-
* empties the registry and sets `active` to `undefined`.
|
|
5119
|
-
* - **Durable open / save (the optional `store` seam).** When a {@link WorkspaceStoreInterface}
|
|
5120
|
-
* is supplied (the `store` option), `open(id)` HYDRATES a workspace from the store on a registry
|
|
5121
|
-
* miss (rebuilding it through the constructor `seed` from `snapshot.files`) and `save(id)`
|
|
5122
|
-
* PERSISTS a registered workspace's {@link WorkspaceInterface.snapshot}. Both are LENIENT without
|
|
5123
|
-
* a store — `open` resolves only registered ids, `save` is a no-op (`false`) — consistent with
|
|
5124
|
-
* the lenient `switch`.
|
|
5125
|
-
* - **Event-free.** A purely registry store — no Emitter, no events (each workspace owns its own).
|
|
5126
|
-
*/
|
|
5127
|
-
export declare interface WorkspaceManagerInterface {
|
|
5128
|
-
readonly count: number;
|
|
5129
|
-
/** The active workspace — what the context renders; `undefined` until the first `add`. */
|
|
5130
|
-
readonly active: WorkspaceInterface | undefined;
|
|
5131
|
-
workspace(id: string): WorkspaceInterface | undefined;
|
|
5132
|
-
workspaces(): readonly WorkspaceInterface[];
|
|
5133
|
-
add(input?: WorkspaceInput): WorkspaceInterface;
|
|
5134
|
-
switch(id: string): WorkspaceInterface | undefined;
|
|
5135
|
-
/**
|
|
5136
|
-
* Resolve a workspace by id, ACTIVATING it — from the registry if present, else HYDRATED from
|
|
5137
|
-
* the optional {@link WorkspaceStoreInterface} (`store`).
|
|
5138
|
-
*
|
|
5139
|
-
* @remarks
|
|
5140
|
-
* - If `id` is ALREADY registered, it is ACTIVATED (`switch`ed to) and returned — no store hit.
|
|
5141
|
-
* - Else if a `store` is set, `store.get(id)` is awaited; on a HIT the snapshot is rehydrated
|
|
5142
|
-
* into a fresh {@link WorkspaceInterface} through the constructor `seed`
|
|
5143
|
-
* (`add({ id, seed: snapshot.files.map((file) => [file.path, file]) })`), which registers AND
|
|
5144
|
-
* auto-activates it (or activates it explicitly), and it is returned.
|
|
5145
|
-
* - Else (no store, or a store MISS) ⇒ `undefined` (lenient — no throw).
|
|
5146
|
-
*
|
|
5147
|
-
* @param id - The workspace id to open
|
|
5148
|
-
* @returns The activated {@link WorkspaceInterface}, or `undefined` when neither registered nor stored
|
|
5149
|
-
*/
|
|
5150
|
-
open(id: string): Promise<WorkspaceInterface | undefined>;
|
|
5151
|
-
/**
|
|
5152
|
-
* Persist a REGISTERED workspace's {@link WorkspaceInterface.snapshot} to the optional
|
|
5153
|
-
* {@link WorkspaceStoreInterface} (`store`).
|
|
5154
|
-
*
|
|
5155
|
-
* @remarks
|
|
5156
|
-
* Lenient: when a `store` is set AND `id` is registered, `store.set(workspace.snapshot())` is
|
|
5157
|
-
* awaited and `true` is returned; otherwise (no store, OR an unknown id) it is a NO-OP returning
|
|
5158
|
-
* `false` — never a throw, consistent with the lenient `switch`.
|
|
5159
|
-
*
|
|
5160
|
-
* @param id - The id of the registered workspace to persist
|
|
5161
|
-
* @returns `true` when the snapshot was persisted; `false` when no store / unknown id
|
|
5162
|
-
*/
|
|
5163
|
-
save(id: string): Promise<boolean>;
|
|
5164
|
-
remove(ids: readonly string[]): boolean;
|
|
5165
|
-
remove(id: string): boolean;
|
|
5166
|
-
clear(): void;
|
|
5167
|
-
}
|
|
5168
|
-
|
|
5169
|
-
/**
|
|
5170
|
-
* Options for `createWorkspaceManager` — the per-workspace `on` / `error` defaults the
|
|
5171
|
-
* workspaces it creates inherit.
|
|
5172
|
-
*
|
|
5173
|
-
* @remarks
|
|
5174
|
-
* `on` / `error` are the default {@link WorkspaceEventMap} listeners + the emitter's
|
|
5175
|
-
* listener-error handler (§13) flowed into every workspace the manager `add`s (a per-`add`
|
|
5176
|
-
* {@link WorkspaceInput.on} / `.error` overrides them). Kept minimal (AGENTS §21) — a
|
|
5177
|
-
* registry needs no more.
|
|
5178
|
-
*/
|
|
5179
|
-
export declare interface WorkspaceManagerOptions {
|
|
5180
|
-
/** The default event listeners for workspaces this manager creates (a per-`add` override wins). */
|
|
5181
|
-
readonly on?: EmitterHooks<WorkspaceEventMap>;
|
|
5182
|
-
/** The default listener-error handler (a per-`add` override wins). */
|
|
5183
|
-
readonly error?: EmitterErrorHandler;
|
|
5184
|
-
/**
|
|
5185
|
-
* The optional durable {@link WorkspaceStoreInterface} backing {@link WorkspaceManagerInterface.open}
|
|
5186
|
-
* / {@link WorkspaceManagerInterface.save} — a memory / JSON / SQLite / IndexedDB store a workspace
|
|
5187
|
-
* is HYDRATED from (`open` a registry-miss) and PERSISTED to (`save`). Omitted ⇒ the manager is
|
|
5188
|
-
* registry-only: `open` resolves only what is already registered, and `save` is a no-op (`false`).
|
|
5189
|
-
*/
|
|
5190
|
-
readonly store?: WorkspaceStoreInterface;
|
|
5191
|
-
}
|
|
5192
|
-
|
|
5193
|
-
/**
|
|
5194
|
-
* Options for {@link import('./factories.js').createWorkspace} / the
|
|
5195
|
-
* {@link import('./workspaces/Workspace.js').Workspace} constructor.
|
|
5196
|
-
*
|
|
5197
|
-
* @param options - The workspace options
|
|
5198
|
-
*
|
|
5199
|
-
* @remarks
|
|
5200
|
-
* - `id` — the workspace's identity (its key in a {@link WorkspaceManagerInterface}); MINTED via `crypto.randomUUID()` when omitted.
|
|
5201
|
-
* - `on` — initial {@link WorkspaceEventMap} listeners (AGENTS §8), wired at construction.
|
|
5202
|
-
* - `error` — the emitter's listener-error handler (AGENTS §13); a throw from any listener is routed here instead of rethrown.
|
|
5203
|
-
*/
|
|
5204
|
-
export declare interface WorkspaceOptions {
|
|
5205
|
-
readonly id?: string;
|
|
5206
|
-
readonly on?: EmitterHooks<WorkspaceEventMap>;
|
|
5207
|
-
readonly error?: EmitterErrorHandler;
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
/**
|
|
5211
|
-
* A JSON-serializable snapshot of a workspace's state — its `id` plus a FLAT list of its
|
|
5212
|
-
* {@link FileInterface}s — the durable payload the {@link WorkspaceStoreInterface} persists.
|
|
5213
|
-
*
|
|
5214
|
-
* @remarks
|
|
5215
|
-
* Pure JSON DATA (no class instances, no functions): each {@link FileInterface} is already a
|
|
5216
|
-
* PLAIN frozen record that `structuredClone`s / JSON-round-trips losslessly, and a `File` carries
|
|
5217
|
-
* its OWN `path`, so a flat `files` list is enough to reconstruct the path-keyed map (no nested
|
|
5218
|
-
* `path → File` object needed for serialization). The snapshot the container produces from itself
|
|
5219
|
-
* ({@link WorkspaceInterface.snapshot}); the durable analogue of the constructor `seed`. A
|
|
5220
|
-
* {@link WorkspaceManagerInterface} hydrates a workspace from `snapshot.files` through the seed
|
|
5221
|
-
* seam (see {@link WorkspaceManagerInterface.open}). It is narrowed back from an untrusted storage
|
|
5222
|
-
* read by {@link import('./helpers.js').isWorkspaceSnapshot} (the AGENTS §14 boundary narrow).
|
|
5223
|
-
*/
|
|
5224
|
-
export declare interface WorkspaceSnapshot {
|
|
5225
|
-
readonly id: string;
|
|
5226
|
-
readonly files: readonly FileInterface[];
|
|
5227
|
-
}
|
|
5228
|
-
|
|
5229
|
-
/**
|
|
5230
|
-
* One row of the table a
|
|
5231
|
-
* {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} persists
|
|
5232
|
-
* — a workspace `id` plus its {@link WorkspaceSnapshot} held as ONE OPAQUE JSON column.
|
|
5233
|
-
*
|
|
5234
|
-
* @remarks
|
|
5235
|
-
* The Database twin of {@link WorkspaceStoreInterface} stores the snapshot whole (the `snapshot`
|
|
5236
|
-
* column is a `rawShape`, an opaque JSON blob — exactly as the analogous
|
|
5237
|
-
* `WorkflowSnapshotRow` in `@orkestrel/workflow` stores a workflow snapshot), so the
|
|
5238
|
-
* row type stays FLAT and the `File`-list snapshot shape never forces the contract to `Infer` it.
|
|
5239
|
-
* The column therefore reads back as the broad `unknown`; the store narrows it to a
|
|
5240
|
-
* {@link WorkspaceSnapshot} on `get` ({@link import('./helpers.js').isWorkspaceSnapshot}, the
|
|
5241
|
-
* AGENTS §14 boundary narrow). `id` mirrors {@link WorkspaceSnapshot.id} (the primary key), so a
|
|
5242
|
-
* `set` writes `{ id: snapshot.id, snapshot }`.
|
|
5243
|
-
*/
|
|
5244
|
-
export declare interface WorkspaceSnapshotRow {
|
|
5245
|
-
readonly id: string;
|
|
5246
|
-
/** The whole {@link WorkspaceSnapshot} as one opaque JSON blob — read back as `unknown`, narrowed on `get`. */
|
|
5247
|
-
readonly snapshot: unknown;
|
|
5248
|
-
}
|
|
5249
|
-
|
|
5250
|
-
/**
|
|
5251
|
-
* The durable persistence seam for a {@link WorkspaceSnapshot} — three async primitives
|
|
5252
|
-
* (`get` / `set` / `delete`) keyed by a workspace id, mirroring the analogous
|
|
5253
|
-
* `WorkflowStoreInterface` in `@orkestrel/workflow` (and the driver-swap pattern a server
|
|
5254
|
-
* surface's session store would follow).
|
|
5255
|
-
*
|
|
5256
|
-
* @remarks
|
|
5257
|
-
* The store persists the {@link WorkspaceSnapshot} — the self-contained, pure-JSON workspace
|
|
5258
|
-
* state — so a JSON / SQLite / IndexedDB backend swaps in WITHOUT touching the manager or the
|
|
5259
|
-
* workspace: the in-memory default
|
|
5260
|
-
* {@link import('./workspaces/stores/MemoryWorkspaceStore.js').MemoryWorkspaceStore} and its
|
|
5261
|
-
* driver-pluggable twin
|
|
5262
|
-
* {@link import('./workspaces/stores/DatabaseWorkspaceStore.js').DatabaseWorkspaceStore} (the
|
|
5263
|
-
* snapshot as one opaque JSON column) share THIS one interface. Hydration is NOT a store concern
|
|
5264
|
-
* — a {@link WorkspaceManagerInterface} reads a snapshot back and rebuilds the live workspace
|
|
5265
|
-
* through the constructor `seed` (see {@link WorkspaceManagerInterface.open} /
|
|
5266
|
-
* {@link WorkspaceManagerInterface.save}).
|
|
5267
|
-
*
|
|
5268
|
-
* Every primitive is async (a `Promise`), so a durable backend (a database round-trip) fits the
|
|
5269
|
-
* same shape as the memory one. The snapshot carries its OWN id, so `set` takes no separate id
|
|
5270
|
-
* param (mirroring the analogous `WorkflowStoreInterface.set` in `@orkestrel/workflow`). UNLIKE a
|
|
5271
|
-
* session store there is NO idle-TTL / eviction — a persisted workspace lives until an explicit
|
|
5272
|
-
* `delete`. It is concrete over {@link WorkspaceSnapshot} — no generic parameter (AGENTS §21
|
|
5273
|
-
* minimal-interface), since the snapshot is the ONE payload a workspace store persists.
|
|
5274
|
-
*/
|
|
5275
|
-
export declare interface WorkspaceStoreInterface {
|
|
5276
|
-
/**
|
|
5277
|
-
* Resolve the persisted snapshot for `id`, or `undefined` if none is stored.
|
|
5278
|
-
*
|
|
5279
|
-
* @param id - The workspace id to resolve (a {@link WorkspaceSnapshot.id})
|
|
5280
|
-
* @returns The persisted snapshot, or `undefined` if absent
|
|
5281
|
-
*/
|
|
5282
|
-
get(id: string): Promise<WorkspaceSnapshot | undefined>;
|
|
5283
|
-
/**
|
|
5284
|
-
* Insert or replace a snapshot under its own `snapshot.id` (no separate id param —
|
|
5285
|
-
* mirroring the analogous `WorkflowStoreInterface.set` in `@orkestrel/workflow`).
|
|
5286
|
-
*
|
|
5287
|
-
* @param snapshot - The snapshot to store (keyed by its `id`)
|
|
5288
|
-
*/
|
|
5289
|
-
set(snapshot: WorkspaceSnapshot): Promise<void>;
|
|
5290
|
-
/**
|
|
5291
|
-
* Drop a snapshot by id; an absent id is a no-op (no throw).
|
|
5292
|
-
*
|
|
5293
|
-
* @param id - The workspace id to drop
|
|
5294
|
-
*/
|
|
5295
|
-
delete(id: string): Promise<void>;
|
|
5296
|
-
}
|
|
5297
|
-
|
|
5298
3663
|
export { }
|