@orkestrel/agent 0.0.3 → 0.0.5
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/dist/src/core/index.cjs +14 -317
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +36 -321
- package/dist/src/core/index.d.ts +36 -321
- package/dist/src/core/index.js +16 -314
- package/dist/src/core/index.js.map +1 -1
- package/package.json +17 -17
package/dist/src/core/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isArray, isNumber, isRecord, isString, rawShape, stringShape } from "@orkestrel/contract";
|
|
2
2
|
import { createDatabase, createMemoryDriver } from "@orkestrel/database";
|
|
3
3
|
import { createQueue } from "@orkestrel/queue";
|
|
4
4
|
import { createDeferred, createRunner } from "@orkestrel/workflow";
|
|
@@ -119,64 +119,6 @@ var EXTENSION_TO_LANGUAGE = Object.freeze({
|
|
|
119
119
|
svg: "xml",
|
|
120
120
|
txt: "text"
|
|
121
121
|
});
|
|
122
|
-
/**
|
|
123
|
-
* The name {@link import('./factories.js').createWorkspaceTool} advertises by default — the key a
|
|
124
|
-
* model calls and the {@link import('./types.js').ToolManagerInterface} registers under.
|
|
125
|
-
*/
|
|
126
|
-
var WORKSPACE_TOOL_NAME = "workspace";
|
|
127
|
-
/**
|
|
128
|
-
* A valid {@link WorkspaceOperation} object — the canonical example embedded VERBATIM in
|
|
129
|
-
* {@link WORKSPACE_TOOL_DESCRIPTION} and pinned by a parity test (it must satisfy the compiled
|
|
130
|
-
* contract's `is`), so the doc example can never drift from a real, contract-valid operation.
|
|
131
|
-
*
|
|
132
|
-
* @remarks
|
|
133
|
-
* A `'write'` op (the most common authoring action): create or overwrite `notes.txt` with
|
|
134
|
-
* `hello`. Frozen so it cannot be mutated in place.
|
|
135
|
-
*/
|
|
136
|
-
var WORKSPACE_TOOL_EXAMPLE = Object.freeze({
|
|
137
|
-
operation: "write",
|
|
138
|
-
path: "notes.txt",
|
|
139
|
-
content: "hello"
|
|
140
|
-
});
|
|
141
|
-
/**
|
|
142
|
-
* The DESCRIPTION {@link import('./factories.js').createWorkspaceTool} advertises — a multi-line
|
|
143
|
-
* guide that teaches a small model how to drive a workspace through the single `operation`-keyed
|
|
144
|
-
* tool.
|
|
145
|
-
*
|
|
146
|
-
* @remarks
|
|
147
|
-
* Mirrors the analogous `WORKFLOW_TOOL_DESCRIPTION` in `@orkestrel/workflow`'s teaching style:
|
|
148
|
-
* names the `operation` discriminant field, enumerates all 13 operations with their FLAT fields,
|
|
149
|
-
* gives a worked example for the common ones (read / write / search / replace / splice), and embeds
|
|
150
|
-
* {@link WORKSPACE_TOOL_EXAMPLE} verbatim (pinned by a parity test). The range edit is the FLAT
|
|
151
|
-
* `'splice'` op — four positive-integer caret components, NOT a nested range — the ergonomic lever
|
|
152
|
-
* a 2B model can fill. The edit / read ops target the ACTIVE workspace (one is auto-created on the
|
|
153
|
-
* first edit when none is active); the `workspaces` / `switch` ops let the model move between
|
|
154
|
-
* workspaces.
|
|
155
|
-
*/
|
|
156
|
-
var WORKSPACE_TOOL_DESCRIPTION = [
|
|
157
|
-
"Read and edit files in a workspace. Every call is ONE operation, chosen by the \"operation\" field.",
|
|
158
|
-
"All file operations act on the ACTIVE workspace; use \"workspaces\" then \"switch\" to move between workspaces.",
|
|
159
|
-
"",
|
|
160
|
-
"Operations (each takes the fields listed):",
|
|
161
|
-
"- read { \"operation\": \"read\", \"path\": \"<file>\" } — return the file's text.",
|
|
162
|
-
"- list { \"operation\": \"list\" } — list every file in the active workspace (path, state, size, lines, kind).",
|
|
163
|
-
"- has { \"operation\": \"has\", \"path\": \"<file>\" } — whether the file exists.",
|
|
164
|
-
"- search { \"operation\": \"search\", \"query\": \"<text>\", \"regex\"?: bool, \"exact\"?: bool, \"limit\"?: int } — find lines matching the query across all files.",
|
|
165
|
-
"- replace { \"operation\": \"replace\", \"query\": \"<text>\", \"replacement\": \"<text>\", \"regex\"?: bool, \"exact\"?: bool, \"limit\"?: int } — replace matches across all files.",
|
|
166
|
-
"- write { \"operation\": \"write\", \"path\": \"<file>\", \"content\": \"<text>\" } — create or overwrite the whole file.",
|
|
167
|
-
"- splice { \"operation\": \"splice\", \"path\": \"<file>\", \"content\": \"<text>\", \"fromLine\": int, \"fromColumn\": int, \"toLine\": int, \"toColumn\": int } — replace a 1-based range (from inclusive, to exclusive) with content.",
|
|
168
|
-
"- prepend { \"operation\": \"prepend\", \"path\": \"<file>\", \"content\": \"<text>\" } — add content to the start of the file.",
|
|
169
|
-
"- append { \"operation\": \"append\", \"path\": \"<file>\", \"content\": \"<text>\" } — add content to the end of the file.",
|
|
170
|
-
"- move { \"operation\": \"move\", \"from\": \"<file>\", \"to\": \"<file>\" } — rename / move a file.",
|
|
171
|
-
"- remove { \"operation\": \"remove\", \"path\": \"<file>\" } — delete a file.",
|
|
172
|
-
"- workspaces { \"operation\": \"workspaces\" } — list the workspaces you can switch between (each id, file count, active).",
|
|
173
|
-
"- switch { \"operation\": \"switch\", \"id\": \"<id>\" } — make the workspace with that id active (ids come from \"workspaces\").",
|
|
174
|
-
"",
|
|
175
|
-
"Notes: lines and columns are 1-based (column 1 is the first character). \"regex\" defaults to false (a literal substring), \"exact\" defaults to true (case-sensitive). \"search\"/\"replace\"/\"splice\" act only on text files. Editing with no active workspace auto-creates one.",
|
|
176
|
-
"",
|
|
177
|
-
"Example — write a file:",
|
|
178
|
-
JSON.stringify(WORKSPACE_TOOL_EXAMPLE)
|
|
179
|
-
].join("\n");
|
|
180
122
|
//#endregion
|
|
181
123
|
//#region src/core/errors.ts
|
|
182
124
|
/**
|
|
@@ -336,93 +278,6 @@ function isWorkspaceError(value) {
|
|
|
336
278
|
return value instanceof WorkspaceError;
|
|
337
279
|
}
|
|
338
280
|
//#endregion
|
|
339
|
-
//#region src/core/shapers.ts
|
|
340
|
-
/**
|
|
341
|
-
* The shape of a {@link import('./types.js').WorkspaceOperation} — a descriptive tagged union over
|
|
342
|
-
* the 13 workspace edit / read / navigation operations, discriminated by the `operation` literal
|
|
343
|
-
* (never a bare `kind`; AGENTS §4.8). Each variant leads with its `operation` discriminant then its
|
|
344
|
-
* FLAT fields, every field via `stringShape` / `optionalShape` / `integerShape({ min: 1 })` /
|
|
345
|
-
* `booleanShape`, each carrying a strong field-level `description`.
|
|
346
|
-
*
|
|
347
|
-
* @remarks
|
|
348
|
-
* The union compiles to an `anyOf` JSON Schema + a `unionOf` guard + a first-match parser
|
|
349
|
-
* automatically ({@link import('./factories.js').createWorkspaceTool} types the result to the
|
|
350
|
-
* hand-written `WorkspaceOperation`). `limit` and the four `'splice'` caret components are POSITIVE
|
|
351
|
-
* integers (`integerShape({ min: 1 })`); `regex` / `exact` are `optionalShape(booleanShape(...))`.
|
|
352
|
-
* The two REGISTRY arms — `workspaces` (list the workspaces the model can move between) and `switch`
|
|
353
|
-
* (re-point the active one by `id`) — let a model DISCOVER then CHOOSE which workspace the edit /
|
|
354
|
-
* read arms target. The descriptions are the small-model ergonomic lever — they ride into the
|
|
355
|
-
* advertised schema so a model authoring an operation gets per-field guidance.
|
|
356
|
-
*/
|
|
357
|
-
var workspaceToolShape = unionShape(objectShape({
|
|
358
|
-
operation: literalShape(["read"], { description: "Read a whole text file's text by path." }),
|
|
359
|
-
path: stringShape({ description: "The path of the file to read." })
|
|
360
|
-
}), objectShape({ operation: literalShape(["list"], { description: "List every file in the workspace." }) }), objectShape({
|
|
361
|
-
operation: literalShape(["has"], { description: "Check whether a file exists at the path." }),
|
|
362
|
-
path: stringShape({ description: "The path to check for." })
|
|
363
|
-
}), objectShape({
|
|
364
|
-
operation: literalShape(["search"], { description: "Search every text file for a query, returning each hit." }),
|
|
365
|
-
query: stringShape({ description: "The text (or regular-expression source) to search for." }),
|
|
366
|
-
regex: optionalShape(booleanShape({ description: "Treat the query as a regular expression. Defaults to false (a literal substring)." })),
|
|
367
|
-
exact: optionalShape(booleanShape({ description: "Match case-sensitively. Defaults to true (set false for case-insensitive)." })),
|
|
368
|
-
limit: optionalShape(integerShape({
|
|
369
|
-
min: 1,
|
|
370
|
-
description: "Stop after this many matches across all files. Omitted means unlimited."
|
|
371
|
-
}))
|
|
372
|
-
}), objectShape({
|
|
373
|
-
operation: literalShape(["replace"], { description: "Replace a query with a replacement across every text file." }),
|
|
374
|
-
query: stringShape({ description: "The text (or regular-expression source) to replace." }),
|
|
375
|
-
replacement: stringShape({ description: "The text to substitute for each match." }),
|
|
376
|
-
regex: optionalShape(booleanShape({ description: "Treat the query as a regular expression. Defaults to false (a literal substring)." })),
|
|
377
|
-
exact: optionalShape(booleanShape({ description: "Match case-sensitively. Defaults to true (set false for case-insensitive)." })),
|
|
378
|
-
limit: optionalShape(integerShape({
|
|
379
|
-
min: 1,
|
|
380
|
-
description: "Stop after this many replacements across all files. Omitted means unlimited."
|
|
381
|
-
}))
|
|
382
|
-
}), objectShape({
|
|
383
|
-
operation: literalShape(["write"], { description: "Create or overwrite a whole file with content." }),
|
|
384
|
-
path: stringShape({ description: "The path of the file to write." }),
|
|
385
|
-
content: stringShape({ description: "The full new contents of the file." })
|
|
386
|
-
}), objectShape({
|
|
387
|
-
operation: literalShape(["splice"], { description: "Replace a 1-based range of an existing text file (from inclusive, to exclusive) with content." }),
|
|
388
|
-
path: stringShape({ description: "The path of the text file to edit." }),
|
|
389
|
-
content: stringShape({ description: "The text to splice in place of the range." }),
|
|
390
|
-
fromLine: integerShape({
|
|
391
|
-
min: 1,
|
|
392
|
-
description: "The 1-based start line of the range (inclusive)."
|
|
393
|
-
}),
|
|
394
|
-
fromColumn: integerShape({
|
|
395
|
-
min: 1,
|
|
396
|
-
description: "The 1-based start column of the range (inclusive; column 1 is the first character)."
|
|
397
|
-
}),
|
|
398
|
-
toLine: integerShape({
|
|
399
|
-
min: 1,
|
|
400
|
-
description: "The 1-based end line of the range (exclusive)."
|
|
401
|
-
}),
|
|
402
|
-
toColumn: integerShape({
|
|
403
|
-
min: 1,
|
|
404
|
-
description: "The 1-based end column of the range (exclusive)."
|
|
405
|
-
})
|
|
406
|
-
}), objectShape({
|
|
407
|
-
operation: literalShape(["prepend"], { description: "Add content to the start of a file (creating it when absent)." }),
|
|
408
|
-
path: stringShape({ description: "The path of the file to prepend to." }),
|
|
409
|
-
content: stringShape({ description: "The text to add at the start of the file." })
|
|
410
|
-
}), objectShape({
|
|
411
|
-
operation: literalShape(["append"], { description: "Add content to the end of a file (creating it when absent)." }),
|
|
412
|
-
path: stringShape({ description: "The path of the file to append to." }),
|
|
413
|
-
content: stringShape({ description: "The text to add at the end of the file." })
|
|
414
|
-
}), objectShape({
|
|
415
|
-
operation: literalShape(["move"], { description: "Rename or move a file (overwriting an occupied target)." }),
|
|
416
|
-
from: stringShape({ description: "The current path of the file." }),
|
|
417
|
-
to: stringShape({ description: "The new path for the file." })
|
|
418
|
-
}), objectShape({
|
|
419
|
-
operation: literalShape(["remove"], { description: "Delete a file from the workspace." }),
|
|
420
|
-
path: stringShape({ description: "The path of the file to remove." })
|
|
421
|
-
}), objectShape({ operation: literalShape(["workspaces"], { description: "List the workspaces you can move between (each id, file count, and whether it is active), so you can pick an id to switch to." }) }), objectShape({
|
|
422
|
-
operation: literalShape(["switch"], { description: "Switch the active workspace to the one with this id (get ids from the \"workspaces\" operation). Edit and read operations then target it." }),
|
|
423
|
-
id: stringShape({ description: "The id of the workspace to make active (from the \"workspaces\" listing)." })
|
|
424
|
-
}));
|
|
425
|
-
//#endregion
|
|
426
281
|
//#region src/core/conversations/Conversation.ts
|
|
427
282
|
/**
|
|
428
283
|
* A conversation grouping messages ABOVE a flat message store — a live uncompacted tail it
|
|
@@ -1371,10 +1226,10 @@ function spliceRange(text, range, replacement) {
|
|
|
1371
1226
|
return text.slice(0, start) + replacement + text.slice(end);
|
|
1372
1227
|
}
|
|
1373
1228
|
/**
|
|
1374
|
-
* Assemble a 1-based nested {@link Range} from
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
1229
|
+
* Assemble a 1-based nested {@link Range} from four FLAT caret integers — the bridge a
|
|
1230
|
+
* workspace-editing tool (see `@orkestrel/tool`) uses from its small-model FLAT surface back to the
|
|
1231
|
+
* nested {@link Range} the {@link import('./workspaces/Workspace.js').Workspace} edit surface
|
|
1232
|
+
* speaks. Published as a public helper for that consumer.
|
|
1378
1233
|
*
|
|
1379
1234
|
* @remarks
|
|
1380
1235
|
* Pairs `(fromLine, fromColumn)` into `start` and `(toLine, toColumn)` into `end` verbatim — a pure
|
|
@@ -1603,7 +1458,9 @@ var InstructionManager = class {
|
|
|
1603
1458
|
* (last write wins). `count` is the map size, `tool(name)` looks one up, `tools()`
|
|
1604
1459
|
* lists them in insertion order, and `definitions()` maps each to a plain
|
|
1605
1460
|
* {@link ToolDefinition} (`name` / `description?` / `parameters?`, the `execute`
|
|
1606
|
-
* handler stripped) — exactly what a provider advertises to the model
|
|
1461
|
+
* handler stripped) — exactly what a provider advertises to the model, with
|
|
1462
|
+
* `tool.summary ?? tool.description` advertised as `description` (a lean `summary`
|
|
1463
|
+
* stands in for the full text when set).
|
|
1607
1464
|
* - **Per-call error isolation (the load-bearing part).** `execute` resolves a
|
|
1608
1465
|
* {@link ToolCall}'s tool by name and ALWAYS resolves a {@link ToolResult}: an
|
|
1609
1466
|
* unknown name → `{ id, name, error: 'tool not found: <name>' }`; a successful run →
|
|
@@ -1684,7 +1541,8 @@ var ToolManager = class {
|
|
|
1684
1541
|
}
|
|
1685
1542
|
#definition(tool) {
|
|
1686
1543
|
const definition = { name: tool.name };
|
|
1687
|
-
|
|
1544
|
+
const description = tool.summary ?? tool.description;
|
|
1545
|
+
if (description !== void 0) definition.description = description;
|
|
1688
1546
|
if (tool.parameters !== void 0) definition.parameters = tool.parameters;
|
|
1689
1547
|
return definition;
|
|
1690
1548
|
}
|
|
@@ -2708,11 +2566,13 @@ var AgentRegistry = class {
|
|
|
2708
2566
|
#tools;
|
|
2709
2567
|
#authorities;
|
|
2710
2568
|
#schedulers;
|
|
2569
|
+
#store;
|
|
2711
2570
|
constructor(options) {
|
|
2712
2571
|
this.#providers = new Map(Object.entries(options.providers));
|
|
2713
2572
|
this.#tools = new Map(Object.entries(options.tools ?? {}));
|
|
2714
2573
|
this.#authorities = new Map(Object.entries(options.authorities ?? {}));
|
|
2715
2574
|
this.#schedulers = new Map(Object.entries(options.schedulers ?? {}));
|
|
2575
|
+
this.#store = options.store;
|
|
2716
2576
|
}
|
|
2717
2577
|
provider(name) {
|
|
2718
2578
|
return this.#resolve(this.#providers, "provider", name);
|
|
@@ -2740,6 +2600,7 @@ var AgentRegistry = class {
|
|
|
2740
2600
|
budget: this.#budget(input.budget),
|
|
2741
2601
|
authority: input.authority === void 0 ? void 0 : this.authority(input.authority),
|
|
2742
2602
|
scheduler: input.scheduler === void 0 ? void 0 : this.scheduler(input.scheduler),
|
|
2603
|
+
conversations: this.#store === void 0 ? void 0 : new ConversationManager({ store: this.#store }),
|
|
2743
2604
|
signal
|
|
2744
2605
|
};
|
|
2745
2606
|
}
|
|
@@ -3224,11 +3085,13 @@ var ThinkSplitter = class {
|
|
|
3224
3085
|
var Tool = class {
|
|
3225
3086
|
name;
|
|
3226
3087
|
description;
|
|
3088
|
+
summary;
|
|
3227
3089
|
parameters;
|
|
3228
3090
|
#execute;
|
|
3229
3091
|
constructor(options) {
|
|
3230
3092
|
this.name = options.name;
|
|
3231
3093
|
this.description = options.description;
|
|
3094
|
+
this.summary = options.summary;
|
|
3232
3095
|
this.parameters = options.parameters;
|
|
3233
3096
|
this.#execute = options.execute;
|
|
3234
3097
|
}
|
|
@@ -4149,168 +4012,7 @@ function createDatabaseWorkspaceStore(driver = createMemoryDriver()) {
|
|
|
4149
4012
|
function createWorkspaceManager(options) {
|
|
4150
4013
|
return new WorkspaceManager(options);
|
|
4151
4014
|
}
|
|
4152
|
-
/**
|
|
4153
|
-
* Wrap a {@link WorkspaceManagerInterface} as an LLM-callable {@link ToolInterface} — it ADVERTISES
|
|
4154
|
-
* the `operation`-discriminated 13-op union ({@link import('./shapers.js').workspaceToolShape}) as
|
|
4155
|
-
* its `parameters`, and its handler PARSES the model-supplied args against that contract and
|
|
4156
|
-
* DISPATCHES the matched operation against the manager's ACTIVE workspace (the registry ops drive
|
|
4157
|
-
* the manager itself), returning the plain result (throwing a typed {@link WorkspaceError} on
|
|
4158
|
-
* failure).
|
|
4159
|
-
*
|
|
4160
|
-
* @remarks
|
|
4161
|
-
* MANAGER-DRIVEN: every edit / read op (read / list / has / search / replace / write / splice /
|
|
4162
|
-
* prepend / append / move / remove) targets `manager.active`, so the model edits whichever workspace
|
|
4163
|
-
* is active and a host can re-point it ({@link WorkspaceManagerInterface.switch}) between turns —
|
|
4164
|
-
* wire the agent's registry in via `createWorkspaceTool(agent.context.workspaces)`. Two REGISTRY ops
|
|
4165
|
-
* make the model self-sufficient: `workspaces` LISTS the registered workspaces (each
|
|
4166
|
-
* `{ id, files, active }`) so it can discover an id, and `switch` re-points the active workspace by
|
|
4167
|
-
* id (lenient — an unknown id is a no-op reporting `switched: false`, never a throw).
|
|
4168
|
-
*
|
|
4169
|
-
* NO-ACTIVE RULE (the ergonomic seam): a WRITING op (write / splice / prepend / append / move /
|
|
4170
|
-
* remove / replace) run when `manager.active` is `undefined` AUTO-CREATES + activates a default
|
|
4171
|
-
* workspace (`manager.add()`) so the model can just start writing; a pure-READ op (read / list / has
|
|
4172
|
-
* / search) against no active workspace returns the EMPTY result (`undefined` / `[]` / `false`),
|
|
4173
|
-
* never creating one and never throwing.
|
|
4174
|
-
*
|
|
4175
|
-
* A plain {@link ToolManagerInterface}-compatible tool (so `createMCPServer` / `createMCPRoutes`
|
|
4176
|
-
* expose it over MCP for free — nothing MCP is wired here), built as a factory + dispatch closure
|
|
4177
|
-
* in the same consumer-edge style as `createWorkflowTool` in `@orkestrel/workflow` (NOT a class —
|
|
4178
|
-
* their signatures differ; the shared idea is that concrete tools live at the factories edge over
|
|
4179
|
-
* a pure tool runtime). The
|
|
4180
|
-
* contract is compiled ONCE and its JSON Schema is narrowed to the open
|
|
4181
|
-
* `Readonly<Record<string, unknown>>` a tool advertises via the shared
|
|
4182
|
-
* {@link schemaToParameters} contracts helper, never an assertion
|
|
4183
|
-
* (§14) — a compiled contract schema is always a record, so it passes; the `undefined` fallback only
|
|
4184
|
-
* satisfies the type's optionality.
|
|
4185
|
-
*
|
|
4186
|
-
* The handler conforms to the universal tool-handler contract (AGENTS §14): it `contract.parse`s the
|
|
4187
|
-
* args, THROWS a `TOOL` {@link WorkspaceError} when no operation arm matched (a malformed / unknown
|
|
4188
|
-
* operation), else `switch`es on `op.operation` and RETURNS the plain result — letting a
|
|
4189
|
-
* `WorkspaceError` raised by the live workspace (`MODALITY` / `PATTERN` / `RANGE`) PROPAGATE
|
|
4190
|
-
* unCAUGHT. The {@link import('./tools/ToolManager.js').ToolManager} performs the ONE
|
|
4191
|
-
* canonical wrap (`{ id, name, value }` on a return; `{ id, name, error }` on a throw, ISOLATED so
|
|
4192
|
-
* nothing escapes the run), so the outcome appears EXACTLY ONCE over BOTH the agent loop and MCP (a
|
|
4193
|
-
* throw → MCP `isError: true`). There is no `{ ok, output, duration }` envelope. The range edit is
|
|
4194
|
-
* the FLAT `'splice'` op: its four flat caret integers are reassembled into a {@link import('./types.js').Range}
|
|
4195
|
-
* by {@link rangeOf} and fed to the workspace's ranged `write`.
|
|
4196
|
-
*
|
|
4197
|
-
* @param manager - The workspace registry the tool reads + edits (its ACTIVE workspace; closed over by the handler)
|
|
4198
|
-
* @param options - Optional advertised `name` / `description` overrides (see {@link WorkspaceToolOptions})
|
|
4199
|
-
* @returns A {@link ToolInterface} (named {@link import('./constants.js').WORKSPACE_TOOL_NAME} by
|
|
4200
|
-
* default) whose `parameters` advertise the `operation`-discriminated union schema
|
|
4201
|
-
*
|
|
4202
|
-
* @example
|
|
4203
|
-
* ```ts
|
|
4204
|
-
* import { createWorkspaceManager, createWorkspaceTool, createToolManager } from '@src/core'
|
|
4205
|
-
*
|
|
4206
|
-
* const manager = createWorkspaceManager()
|
|
4207
|
-
* const tool = createWorkspaceTool(manager) // edits the manager's ACTIVE workspace
|
|
4208
|
-
* const tools = createToolManager()
|
|
4209
|
-
* tools.add(tool) // a model can now read + edit the active workspace by calling `workspace`
|
|
4210
|
-
* ```
|
|
4211
|
-
*/
|
|
4212
|
-
function createWorkspaceTool(manager, options) {
|
|
4213
|
-
const contract = createContract(workspaceToolShape);
|
|
4214
|
-
const parameters = schemaToParameters(contract.schema);
|
|
4215
|
-
return createTool({
|
|
4216
|
-
name: options?.name ?? "workspace",
|
|
4217
|
-
description: options?.description ?? WORKSPACE_TOOL_DESCRIPTION,
|
|
4218
|
-
parameters,
|
|
4219
|
-
execute: (args) => {
|
|
4220
|
-
const op = contract.parse(args);
|
|
4221
|
-
if (op === void 0) throw new WorkspaceError("TOOL", `unknown or malformed operation`, { args });
|
|
4222
|
-
if (op.operation === "workspaces") {
|
|
4223
|
-
const activeId = manager.active?.id;
|
|
4224
|
-
return manager.workspaces().map((workspace) => ({
|
|
4225
|
-
id: workspace.id,
|
|
4226
|
-
files: workspace.count,
|
|
4227
|
-
active: workspace.id === activeId
|
|
4228
|
-
}));
|
|
4229
|
-
}
|
|
4230
|
-
if (op.operation === "switch") {
|
|
4231
|
-
const switched = manager.switch(op.id);
|
|
4232
|
-
return switched === void 0 ? {
|
|
4233
|
-
id: op.id,
|
|
4234
|
-
switched: false
|
|
4235
|
-
} : {
|
|
4236
|
-
id: switched.id,
|
|
4237
|
-
switched: true,
|
|
4238
|
-
files: switched.count
|
|
4239
|
-
};
|
|
4240
|
-
}
|
|
4241
|
-
const active = manager.active;
|
|
4242
|
-
switch (op.operation) {
|
|
4243
|
-
case "read": return active?.read(op.path);
|
|
4244
|
-
case "list": return (active?.files() ?? []).map((file) => ({
|
|
4245
|
-
path: file.path,
|
|
4246
|
-
state: file.state,
|
|
4247
|
-
size: file.size,
|
|
4248
|
-
lines: file.lines,
|
|
4249
|
-
kind: isText(file.content) ? "text" : "binary"
|
|
4250
|
-
}));
|
|
4251
|
-
case "has": return active?.has(op.path) ?? false;
|
|
4252
|
-
case "search": return active?.search(op.query, {
|
|
4253
|
-
regex: op.regex,
|
|
4254
|
-
exact: op.exact,
|
|
4255
|
-
limit: op.limit
|
|
4256
|
-
}) ?? [];
|
|
4257
|
-
case "replace": return (active ?? manager.add()).replace(op.query, op.replacement, {
|
|
4258
|
-
regex: op.regex,
|
|
4259
|
-
exact: op.exact,
|
|
4260
|
-
limit: op.limit
|
|
4261
|
-
});
|
|
4262
|
-
case "write": {
|
|
4263
|
-
const workspace = active ?? manager.add();
|
|
4264
|
-
workspace.write(op.path, op.content);
|
|
4265
|
-
return {
|
|
4266
|
-
path: op.path,
|
|
4267
|
-
state: workspace.file(op.path)?.state
|
|
4268
|
-
};
|
|
4269
|
-
}
|
|
4270
|
-
case "splice": {
|
|
4271
|
-
const workspace = active ?? manager.add();
|
|
4272
|
-
workspace.write(op.path, op.content, rangeOf(op.fromLine, op.fromColumn, op.toLine, op.toColumn));
|
|
4273
|
-
return {
|
|
4274
|
-
path: op.path,
|
|
4275
|
-
state: workspace.file(op.path)?.state
|
|
4276
|
-
};
|
|
4277
|
-
}
|
|
4278
|
-
case "prepend": {
|
|
4279
|
-
const workspace = active ?? manager.add();
|
|
4280
|
-
workspace.prepend(op.path, op.content);
|
|
4281
|
-
return {
|
|
4282
|
-
path: op.path,
|
|
4283
|
-
state: workspace.file(op.path)?.state
|
|
4284
|
-
};
|
|
4285
|
-
}
|
|
4286
|
-
case "append": {
|
|
4287
|
-
const workspace = active ?? manager.add();
|
|
4288
|
-
workspace.append(op.path, op.content);
|
|
4289
|
-
return {
|
|
4290
|
-
path: op.path,
|
|
4291
|
-
state: workspace.file(op.path)?.state
|
|
4292
|
-
};
|
|
4293
|
-
}
|
|
4294
|
-
case "move": {
|
|
4295
|
-
const workspace = active ?? manager.add();
|
|
4296
|
-
return {
|
|
4297
|
-
from: op.from,
|
|
4298
|
-
to: op.to,
|
|
4299
|
-
moved: workspace.move(op.from, op.to)
|
|
4300
|
-
};
|
|
4301
|
-
}
|
|
4302
|
-
case "remove": {
|
|
4303
|
-
const workspace = active ?? manager.add();
|
|
4304
|
-
return {
|
|
4305
|
-
path: op.path,
|
|
4306
|
-
removed: workspace.remove(op.path)
|
|
4307
|
-
};
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
}
|
|
4311
|
-
});
|
|
4312
|
-
}
|
|
4313
4015
|
//#endregion
|
|
4314
|
-
export { Agent, AgentContext, AgentJobError, AgentRegistry, Authority, CONVERSATION_RECAP_PREFIX, Channel, Conversation, ConversationError, ConversationManager, DEFAULT_AGENT_LIMIT, DEFAULT_AUTHORITY_ZONE, DEFAULT_CONVERSATION_KEEP, DatabaseConversationStore, DatabaseWorkspaceStore, EXTENSION_TO_LANGUAGE, Instruction, InstructionManager, MemoryConversationStore, MemoryWorkspaceStore, ProviderAbortError, Scope, ScopeManager, THINK_CLOSE, THINK_OPEN, ThinkSplitter, Tool, ToolManager, WORKSPACE_SECTION_HEADER,
|
|
4016
|
+
export { Agent, AgentContext, AgentJobError, AgentRegistry, Authority, CONVERSATION_RECAP_PREFIX, Channel, Conversation, ConversationError, ConversationManager, DEFAULT_AGENT_LIMIT, DEFAULT_AUTHORITY_ZONE, DEFAULT_CONVERSATION_KEEP, DatabaseConversationStore, DatabaseWorkspaceStore, EXTENSION_TO_LANGUAGE, Instruction, InstructionManager, MemoryConversationStore, MemoryWorkspaceStore, ProviderAbortError, Scope, ScopeManager, THINK_CLOSE, THINK_OPEN, ThinkSplitter, Tool, ToolManager, WORKSPACE_SECTION_HEADER, Workspace, WorkspaceError, WorkspaceManager, buildToolResult, clampPosition, clampRange, computeSize, countLines, createAgent, createAgentContext, createAgentQueue, createAgentRegistry, createAgentRunner, createAuthority, createBinaryContent, createConversation, createConversationManager, createDatabaseConversationStore, createDatabaseWorkspaceStore, createFile, createInstruction, createInstructionManager, createMemoryConversationStore, createMemoryWorkspaceStore, createScope, createScopeManager, createTextContent, createThinkSplitter, createTool, createToolManager, createWorkspace, createWorkspaceManager, decodedSize, escapeRegExp, estimateMessages, estimateTokens, fencedFile, filterAllowList, inferLanguage, isAgentJobError, isBinary, isConversationError, isConversationSnapshot, isFile, isImage, isMessage, isProviderAbortError, isSection, isText, isToolCall, isValidRange, isWorkspaceError, isWorkspaceSnapshot, offsetAt, rangeOf, settleAgentJob, sliceRange, spliceRange };
|
|
4315
4017
|
|
|
4316
4018
|
//# sourceMappingURL=index.js.map
|