@orkestrel/tool 0.0.14 → 0.0.15
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 +149 -40
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +182 -33
- package/dist/src/core/index.d.ts +182 -33
- package/dist/src/core/index.js +149 -42
- package/dist/src/core/index.js.map +1 -1
- package/package.json +11 -10
package/dist/src/core/index.js
CHANGED
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
import { attempt, holds, isArray, isRecord, isString } from "@orkestrel/contract";
|
|
2
|
-
|
|
1
|
+
import { attempt, createContract, holds, isArray, isInstance, isRecord, isString, schemaToParameters } from "@orkestrel/contract";
|
|
2
|
+
import { Emitter } from "@orkestrel/emitter";
|
|
3
|
+
//#region src/core/errors.ts
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
* authored `summary` in place of the full description and carrying the parameter schema
|
|
6
|
-
* by reference.
|
|
5
|
+
* Reports a schema conflict or argument validation failure with a machine-readable code.
|
|
7
6
|
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* authored a schema. The full `description` stays on the tool for direct lookup, and
|
|
12
|
-
* the definition is never a live handle on the tool's handler.
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { ToolError } from '@orkestrel/tool'
|
|
13
10
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* const error = new ToolError('SCHEMA', 'Choose contract or parameters')
|
|
12
|
+
* error.code // 'SCHEMA'
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
var ToolError = class extends Error {
|
|
16
|
+
name = "ToolError";
|
|
17
|
+
code;
|
|
18
|
+
context;
|
|
19
|
+
constructor(code, message, context) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.code = code;
|
|
22
|
+
if (context !== void 0) this.context = context;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Checks whether a value is a tool error, containing hostile prototype access.
|
|
27
|
+
*
|
|
28
|
+
* @param value - The value to test
|
|
29
|
+
* @returns True if the value is an instance of the tool error class; false otherwise
|
|
16
30
|
*
|
|
17
31
|
* @example
|
|
18
32
|
* ```ts
|
|
19
|
-
* import {
|
|
33
|
+
* import { ToolError, isToolError } from '@orkestrel/tool'
|
|
20
34
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
35
|
+
* isToolError(new ToolError('ARGUMENTS', 'Invalid amount')) // true
|
|
36
|
+
* isToolError(new Error('Unrelated')) // false
|
|
23
37
|
* ```
|
|
24
38
|
*/
|
|
25
|
-
function
|
|
26
|
-
|
|
27
|
-
const description = tool.summary ?? tool.description;
|
|
28
|
-
if (description !== void 0) definition.description = description;
|
|
29
|
-
if (tool.parameters !== void 0) definition.parameters = tool.parameters;
|
|
30
|
-
return definition;
|
|
39
|
+
function isToolError(value) {
|
|
40
|
+
return isInstance(value, ToolError);
|
|
31
41
|
}
|
|
32
42
|
//#endregion
|
|
33
43
|
//#region src/core/validators.ts
|
|
@@ -37,8 +47,7 @@ function toolToDefinition(tool) {
|
|
|
37
47
|
*
|
|
38
48
|
* @remarks
|
|
39
49
|
* The accepted shape is a plain record with string `id` and `name` fields and a
|
|
40
|
-
* plain-record `arguments` field.
|
|
41
|
-
* read or verified.
|
|
50
|
+
* plain-record `arguments` field. Extra fields are not read or verified.
|
|
42
51
|
*
|
|
43
52
|
* @param value - The value to test
|
|
44
53
|
* @returns True if the value has the complete tool-call shape; false otherwise
|
|
@@ -55,12 +64,48 @@ function isToolCall(value) {
|
|
|
55
64
|
return holds(() => isRecord(value) && isString(value.id) && isString(value.name) && isRecord(value.arguments));
|
|
56
65
|
}
|
|
57
66
|
//#endregion
|
|
67
|
+
//#region src/core/helpers.ts
|
|
68
|
+
/**
|
|
69
|
+
* Projects a tool onto the plain definition advertised to a caller, advertising an
|
|
70
|
+
* authored `summary` in place of the full description and carrying `parameters` and
|
|
71
|
+
* `annotations` by reference.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* The projection carries `name` and present `title`, `description`, `parameters`, and
|
|
75
|
+
* `annotations` fields in that order. The full `description` stays on the tool for
|
|
76
|
+
* direct lookup, and the definition is never a live handle on the tool's handler.
|
|
77
|
+
*
|
|
78
|
+
* @param tool - The tool to project
|
|
79
|
+
* @returns A fresh definition carrying only the fields the tool authored
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* import { Tool, toolToDefinition } from '@orkestrel/tool'
|
|
84
|
+
*
|
|
85
|
+
* const echo = new Tool({ name: 'echo', summary: 'Echo a value.', execute: (args) => args.value })
|
|
86
|
+
* toolToDefinition(echo) // { name: 'echo', description: 'Echo a value.' }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
function toolToDefinition(tool) {
|
|
90
|
+
const description = tool.summary ?? tool.description;
|
|
91
|
+
return {
|
|
92
|
+
name: tool.name,
|
|
93
|
+
...tool.title === void 0 ? {} : { title: tool.title },
|
|
94
|
+
...description === void 0 ? {} : { description },
|
|
95
|
+
...tool.parameters === void 0 ? {} : { parameters: tool.parameters },
|
|
96
|
+
...tool.annotations === void 0 ? {} : { annotations: tool.annotations }
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
58
100
|
//#region src/core/tools/Tool.ts
|
|
59
101
|
/**
|
|
60
102
|
* Binds an executable tool definition to a handler.
|
|
61
103
|
*
|
|
62
104
|
* @remarks
|
|
63
|
-
*
|
|
105
|
+
* Advertised fields and execution context are forwarded by reference.
|
|
106
|
+
* A contract derives parameters at construction and refuses parse faults before the
|
|
107
|
+
* handler runs, then forwards the parsed arguments; without a contract, arguments
|
|
108
|
+
* retain their identity. Supplying a contract and parameters throws a schema conflict.
|
|
64
109
|
* Caller context is consumer-asserted and is not verified. Handler failures are not
|
|
65
110
|
* caught here; {@link ToolManager} owns per-call error isolation.
|
|
66
111
|
*
|
|
@@ -80,21 +125,47 @@ function isToolCall(value) {
|
|
|
80
125
|
* ```
|
|
81
126
|
*/
|
|
82
127
|
var Tool = class {
|
|
128
|
+
#contract;
|
|
129
|
+
#execute;
|
|
83
130
|
name;
|
|
131
|
+
title;
|
|
84
132
|
description;
|
|
85
133
|
summary;
|
|
86
134
|
parameters;
|
|
87
|
-
|
|
135
|
+
annotations;
|
|
88
136
|
constructor(options) {
|
|
137
|
+
if (options.contract !== void 0 && options.parameters !== void 0) throw new ToolError("SCHEMA", "Choose contract or parameters, not both");
|
|
89
138
|
this.name = options.name;
|
|
139
|
+
if (options.title !== void 0) this.title = options.title;
|
|
90
140
|
if (options.description !== void 0) this.description = options.description;
|
|
91
141
|
if (options.summary !== void 0) this.summary = options.summary;
|
|
92
|
-
if (options.
|
|
142
|
+
if (options.annotations !== void 0) this.annotations = options.annotations;
|
|
143
|
+
if (options.contract !== void 0) {
|
|
144
|
+
this.#contract = createContract(options.contract);
|
|
145
|
+
const parameters = schemaToParameters(this.#contract.schema);
|
|
146
|
+
if (parameters !== void 0) this.parameters = parameters;
|
|
147
|
+
} else if (options.parameters !== void 0) this.parameters = options.parameters;
|
|
93
148
|
this.#execute = options.execute;
|
|
94
149
|
}
|
|
95
|
-
execute(args,
|
|
96
|
-
|
|
97
|
-
|
|
150
|
+
execute(args, context) {
|
|
151
|
+
const faults = this.#contract?.explain(args) ?? [];
|
|
152
|
+
const fault = faults[0];
|
|
153
|
+
if (fault !== void 0) {
|
|
154
|
+
let message = `${isString(fault.path) ? fault.path : fault.path.join(".")}: ${fault.reason}`;
|
|
155
|
+
if ("expected" in fault) message += `; expected ${fault.expected}`;
|
|
156
|
+
if ("received" in fault) message += `; received ${fault.received}`;
|
|
157
|
+
if ("constraint" in fault) message += `; constraint ${fault.constraint}`;
|
|
158
|
+
if ("limit" in fault && fault.limit !== void 0) message += `; limit ${fault.limit}`;
|
|
159
|
+
if ("variants" in fault) message += `; variants ${fault.variants}`;
|
|
160
|
+
if ("matched" in fault) message += `; matched ${fault.matched}`;
|
|
161
|
+
throw new ToolError("ARGUMENTS", message, { faults });
|
|
162
|
+
}
|
|
163
|
+
if (this.#contract !== void 0) {
|
|
164
|
+
const parsed = this.#contract.parse(args);
|
|
165
|
+
if (!isRecord(parsed)) throw new ToolError("ARGUMENTS", "Arguments did not parse");
|
|
166
|
+
return this.#execute(parsed, context);
|
|
167
|
+
}
|
|
168
|
+
return this.#execute(args, context);
|
|
98
169
|
}
|
|
99
170
|
};
|
|
100
171
|
//#endregion
|
|
@@ -108,7 +179,13 @@ var Tool = class {
|
|
|
108
179
|
* Unknown names and handler throws resolve to error results; a call whose `id` or `name`
|
|
109
180
|
* accessor throws when read makes its call, and the batch holding it, reject. Batch
|
|
110
181
|
* execution preserves input order and isolates each call whose members are plain
|
|
111
|
-
* values.
|
|
182
|
+
* values. Execution context is shared across a batch and forwarded unchanged. An
|
|
183
|
+
* omitted context receives a non-aborted signal. A signal aborted before handler
|
|
184
|
+
* entry produces an error result; later cancellation is the handler's responsibility.
|
|
185
|
+
* Registry changes publish synchronously. Replacements publish `remove`, then `add`
|
|
186
|
+
* if the map still holds that exact replacement after the removal listeners return.
|
|
187
|
+
* Destruction clears the tools before releasing listeners. A destroyed registry
|
|
188
|
+
* publishes nothing, even when later additions update its tool map.
|
|
112
189
|
*
|
|
113
190
|
* @example
|
|
114
191
|
* ```ts
|
|
@@ -125,15 +202,25 @@ var Tool = class {
|
|
|
125
202
|
*/
|
|
126
203
|
var ToolManager = class {
|
|
127
204
|
#tools = /* @__PURE__ */ new Map();
|
|
205
|
+
#emitter;
|
|
206
|
+
constructor(options) {
|
|
207
|
+
this.#emitter = new Emitter(options);
|
|
208
|
+
}
|
|
128
209
|
get count() {
|
|
129
210
|
return this.#tools.size;
|
|
130
211
|
}
|
|
212
|
+
get emitter() {
|
|
213
|
+
return this.#emitter;
|
|
214
|
+
}
|
|
131
215
|
add(tools) {
|
|
132
216
|
if (isArray(tools)) {
|
|
133
|
-
for (const tool of tools) this
|
|
217
|
+
for (const tool of tools) this.add(tool);
|
|
134
218
|
return;
|
|
135
219
|
}
|
|
220
|
+
const previous = this.#tools.get(tools.name);
|
|
136
221
|
this.#tools.set(tools.name, tools);
|
|
222
|
+
if (previous !== void 0) this.#emitter.emit("remove", previous);
|
|
223
|
+
if (this.#tools.get(tools.name) === tools) this.#emitter.emit("add", tools);
|
|
137
224
|
}
|
|
138
225
|
tool(name) {
|
|
139
226
|
return this.#tools.get(name);
|
|
@@ -144,22 +231,33 @@ var ToolManager = class {
|
|
|
144
231
|
definitions() {
|
|
145
232
|
return [...this.#tools.values()].map((tool) => toolToDefinition(tool));
|
|
146
233
|
}
|
|
147
|
-
execute(call) {
|
|
148
|
-
if (isArray(call)) return Promise.all(call.map((one) => this.#run(one)));
|
|
149
|
-
return this.#run(call);
|
|
234
|
+
execute(call, context = { signal: new AbortController().signal }) {
|
|
235
|
+
if (isArray(call)) return Promise.all(call.map((one) => this.#run(one, context)));
|
|
236
|
+
return this.#run(call, context);
|
|
150
237
|
}
|
|
151
238
|
remove(names) {
|
|
152
239
|
if (isArray(names)) {
|
|
153
240
|
let removed = true;
|
|
154
|
-
for (const name of names) if (!this
|
|
241
|
+
for (const name of names) if (!this.remove(name)) removed = false;
|
|
155
242
|
return removed;
|
|
156
243
|
}
|
|
157
|
-
|
|
244
|
+
const tool = this.#tools.get(names);
|
|
245
|
+
if (tool === void 0) return false;
|
|
246
|
+
this.#tools.delete(names);
|
|
247
|
+
this.#emitter.emit("remove", tool);
|
|
248
|
+
return true;
|
|
158
249
|
}
|
|
159
250
|
clear() {
|
|
251
|
+
const tools = this.tools();
|
|
252
|
+
this.#tools.clear();
|
|
253
|
+
this.#emitter.emit("clear", tools);
|
|
254
|
+
}
|
|
255
|
+
destroy() {
|
|
256
|
+
this.clear();
|
|
257
|
+
this.#emitter.destroy();
|
|
160
258
|
this.#tools.clear();
|
|
161
259
|
}
|
|
162
|
-
async #run(call) {
|
|
260
|
+
async #run(call, context) {
|
|
163
261
|
const tool = this.#tools.get(call.name);
|
|
164
262
|
if (tool === void 0) return {
|
|
165
263
|
id: call.id,
|
|
@@ -168,8 +266,16 @@ var ToolManager = class {
|
|
|
168
266
|
error: `tool not found: ${call.name}`
|
|
169
267
|
};
|
|
170
268
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
269
|
+
if (context.signal.aborted) {
|
|
270
|
+
const reason = context.signal.reason;
|
|
271
|
+
return {
|
|
272
|
+
id: call.id,
|
|
273
|
+
name: call.name,
|
|
274
|
+
success: false,
|
|
275
|
+
error: reason === void 0 ? "aborted" : String(reason)
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
const value = await tool.execute(call.arguments, context);
|
|
173
279
|
return {
|
|
174
280
|
id: call.id,
|
|
175
281
|
name: call.name,
|
|
@@ -225,6 +331,7 @@ function createTool(options) {
|
|
|
225
331
|
* per-call error isolation, returned as a `ToolManagerInterface` so a caller holds the
|
|
226
332
|
* published contract rather than the `ToolManager` class.
|
|
227
333
|
*
|
|
334
|
+
* @param options - The initial registry listeners and listener-error handler
|
|
228
335
|
* @returns A registry bound to no tools
|
|
229
336
|
*
|
|
230
337
|
* @example
|
|
@@ -240,10 +347,10 @@ function createTool(options) {
|
|
|
240
347
|
* })
|
|
241
348
|
* ```
|
|
242
349
|
*/
|
|
243
|
-
function createToolManager() {
|
|
244
|
-
return new ToolManager();
|
|
350
|
+
function createToolManager(options) {
|
|
351
|
+
return new ToolManager(options);
|
|
245
352
|
}
|
|
246
353
|
//#endregion
|
|
247
|
-
export { Tool, ToolManager, createTool, createToolManager, isToolCall, toolToDefinition };
|
|
354
|
+
export { Tool, ToolError, ToolManager, createTool, createToolManager, isToolCall, isToolError, toolToDefinition };
|
|
248
355
|
|
|
249
356
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/helpers.ts","../../../src/core/validators.ts","../../../src/core/tools/Tool.ts","../../../src/core/tools/ToolManager.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { ToolDefinition, ToolInterface } from './types.js'\n\n/**\n * Projects a tool onto the plain definition advertised to a caller, advertising an\n * authored `summary` in place of the full description and carrying the parameter schema\n * by reference.\n *\n * @remarks\n * The projection is a fresh object carrying `name`, then `description` only when the\n * tool authored a summary or a description, then `parameters` only when the tool\n * authored a schema. The full `description` stays on the tool for direct lookup, and\n * the definition is never a live handle on the tool's handler.\n *\n * @param tool - The tool to project\n * @returns A fresh definition carrying only the fields the tool authored\n *\n * @example\n * ```ts\n * import { Tool, toolToDefinition } from '@orkestrel/tool'\n *\n * const echo = new Tool({ name: 'echo', summary: 'Echo a value.', execute: (args) => args.value })\n * toolToDefinition(echo) // { name: 'echo', description: 'Echo a value.' }\n * ```\n */\nexport function toolToDefinition(tool: ToolInterface): ToolDefinition {\n\tconst definition: {\n\t\tname: string\n\t\tdescription?: string\n\t\tparameters?: Readonly<Record<string, unknown>>\n\t} = {\n\t\tname: tool.name,\n\t}\n\tconst description = tool.summary ?? tool.description\n\tif (description !== undefined) definition.description = description\n\tif (tool.parameters !== undefined) definition.parameters = tool.parameters\n\treturn definition\n}\n","import type { ToolCall } from './types.js'\nimport { holds, isRecord, isString } from '@orkestrel/contract'\n\n/**\n * Determines whether an unknown value is structurally a {@link ToolCall}, staying total\n * for malformed and adversarial input.\n *\n * @remarks\n * The accepted shape is a plain record with string `id` and `name` fields and a\n * plain-record `arguments` field. Optional caller context remains opaque and is not\n * read or verified.\n *\n * @param value - The value to test\n * @returns True if the value has the complete tool-call shape; false otherwise\n *\n * @example\n * ```ts\n * import { isToolCall } from '@orkestrel/tool'\n *\n * isToolCall({ id: '1', name: 'search', arguments: { query: 'birds' } }) // true\n * isToolCall({ id: '1', name: 'search', arguments: [] }) // false\n * ```\n */\nexport function isToolCall(value: unknown): value is ToolCall {\n\treturn holds(\n\t\t() =>\n\t\t\tisRecord(value) && isString(value.id) && isString(value.name) && isRecord(value.arguments),\n\t)\n}\n","import type { ToolInterface, ToolOptions } from '../types.js'\n\n/**\n * Binds an executable tool definition to a handler.\n *\n * @remarks\n * Schema fields, arguments, and present caller context are forwarded by reference.\n * Caller context is consumer-asserted and is not verified. Handler failures are not\n * caught here; {@link ToolManager} owns per-call error isolation.\n *\n * @example\n * ```ts\n * import { Tool } from '@orkestrel/tool'\n *\n * const tool = new Tool({\n * \tname: 'add',\n * \tdescription: 'Add two numbers',\n * \tparameters: {\n * \t\ttype: 'object',\n * \t\tproperties: { a: { type: 'number' }, b: { type: 'number' } },\n * \t},\n * \texecute: (args) => Number(args.a) + Number(args.b),\n * })\n * ```\n */\nexport class Tool implements ToolInterface {\n\treadonly name: string\n\treadonly description?: string\n\treadonly summary?: string\n\treadonly parameters?: Readonly<Record<string, unknown>>\n\treadonly #execute: (\n\t\targs: Readonly<Record<string, unknown>>,\n\t\tcaller?: unknown,\n\t) => Promise<unknown> | unknown\n\n\tconstructor(options: ToolOptions) {\n\t\tthis.name = options.name\n\t\tif (options.description !== undefined) this.description = options.description\n\t\tif (options.summary !== undefined) this.summary = options.summary\n\t\tif (options.parameters !== undefined) this.parameters = options.parameters\n\t\tthis.#execute = options.execute\n\t}\n\n\texecute(args: Readonly<Record<string, unknown>>, caller?: unknown): Promise<unknown> | unknown {\n\t\tif (caller === undefined) return this.#execute(args)\n\t\treturn this.#execute(args, caller)\n\t}\n}\n","import type {\n\tToolCall,\n\tToolDefinition,\n\tToolInterface,\n\tToolManagerInterface,\n\tToolResult,\n} from '../types.js'\nimport { attempt, isArray } from '@orkestrel/contract'\nimport { toolToDefinition } from '../helpers.js'\n\n/**\n * Represents an insertion-ordered tool registry with per-call error isolation.\n *\n * @remarks\n * A repeated name overwrites the registered tool without changing its insertion\n * position. Definitions advertise `summary` in place of `description` when present.\n * Unknown names and handler throws resolve to error results; a call whose `id` or `name`\n * accessor throws when read makes its call, and the batch holding it, reject. Batch\n * execution preserves input order and isolates each call whose members are plain\n * values. Optional consumer-asserted caller context is forwarded without verification.\n *\n * @example\n * ```ts\n * import { Tool, ToolManager } from '@orkestrel/tool'\n *\n * const tools = new ToolManager()\n * tools.add(new Tool({ name: 'add', execute: (args) => Number(args.x) + Number(args.y) }))\n * const result = await tools.execute({\n * \tid: '1',\n * \tname: 'add',\n * \targuments: { x: 1, y: 2 },\n * })\n * ```\n */\nexport class ToolManager implements ToolManagerInterface {\n\treadonly #tools = new Map<string, ToolInterface>()\n\n\tget count(): number {\n\t\treturn this.#tools.size\n\t}\n\n\tadd(tool: ToolInterface): void\n\tadd(tools: readonly ToolInterface[]): void\n\tadd(tools: ToolInterface | readonly ToolInterface[]): void {\n\t\tif (isArray(tools)) {\n\t\t\tfor (const tool of tools) this.#tools.set(tool.name, tool)\n\t\t\treturn\n\t\t}\n\t\tthis.#tools.set(tools.name, tools)\n\t}\n\n\ttool(name: string): ToolInterface | undefined {\n\t\treturn this.#tools.get(name)\n\t}\n\n\ttools(): readonly ToolInterface[] {\n\t\treturn [...this.#tools.values()]\n\t}\n\n\tdefinitions(): readonly ToolDefinition[] {\n\t\treturn [...this.#tools.values()].map((tool) => toolToDefinition(tool))\n\t}\n\n\texecute(call: ToolCall): Promise<ToolResult>\n\texecute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>\n\texecute(call: ToolCall | readonly ToolCall[]): Promise<ToolResult | readonly ToolResult[]> {\n\t\tif (isArray(call)) return Promise.all(call.map((one) => this.#run(one)))\n\t\treturn this.#run(call)\n\t}\n\n\tremove(name: string): boolean\n\tremove(names: readonly string[]): boolean\n\tremove(names: string | readonly string[]): boolean {\n\t\tif (isArray(names)) {\n\t\t\tlet removed = true\n\t\t\tfor (const name of names) {\n\t\t\t\tif (!this.#tools.delete(name)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\treturn this.#tools.delete(names)\n\t}\n\n\tclear(): void {\n\t\tthis.#tools.clear()\n\t}\n\n\tasync #run(call: ToolCall): Promise<ToolResult> {\n\t\tconst tool = this.#tools.get(call.name)\n\t\tif (tool === undefined) {\n\t\t\treturn {\n\t\t\t\tid: call.id,\n\t\t\t\tname: call.name,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `tool not found: ${call.name}`,\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tconst caller = call.caller\n\t\t\tconst value = await (caller === undefined\n\t\t\t\t? tool.execute(call.arguments)\n\t\t\t\t: tool.execute(call.arguments, caller))\n\t\t\treturn { id: call.id, name: call.name, success: true, value }\n\t\t} catch (error) {\n\t\t\tconst message = attempt(() =>\n\t\t\t\terror instanceof Error ? String(error.message) : String(error),\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tid: call.id,\n\t\t\t\tname: call.name,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: message.success ? message.value : 'Unknown thrown value',\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { ToolInterface, ToolManagerInterface, ToolOptions } from './types.js'\nimport { Tool } from './tools/Tool.js'\nimport { ToolManager } from './tools/ToolManager.js'\n\n/**\n * Creates an executable tool bound to the supplied handler, returned as a\n * `ToolInterface` so a call site holds the published contract rather than the `Tool`\n * class.\n *\n * @param options - The advertised definition and execution handler\n * @returns A tool bound to the supplied handler\n *\n * @example Anatomy of a tool\n * ```ts\n * import { createTool } from '@orkestrel/tool'\n *\n * const add = createTool({\n * \tname: 'add',\n * \tdescription: 'Add two numeric values and return their sum. Both operands are required.',\n * \tsummary: 'Add two numbers.',\n * \tparameters: {\n * \t\ttype: 'object',\n * \t\tproperties: {\n * \t\t\tleft: { type: 'number' },\n * \t\t\tright: { type: 'number' },\n * \t\t},\n * \t\trequired: ['left', 'right'],\n * \t},\n * \texecute: (args) => Number(args.left) + Number(args.right),\n * })\n * ```\n */\nexport function createTool(options: ToolOptions): ToolInterface {\n\treturn new Tool(options)\n}\n\n/**\n * Creates an empty registry that advertises definitions and executes calls with\n * per-call error isolation, returned as a `ToolManagerInterface` so a caller holds the\n * published contract rather than the `ToolManager` class.\n *\n * @returns A registry bound to no tools\n *\n * @example\n * ```ts\n * import { createTool, createToolManager } from '@orkestrel/tool'\n *\n * const tools = createToolManager()\n * tools.add(createTool({ name: 'echo', execute: (args) => args.value }))\n * const result = await tools.execute({\n * \tid: '1',\n * \tname: 'echo',\n * \targuments: { value: 'hello' },\n * })\n * ```\n */\nexport function createToolManager(): ToolManagerInterface {\n\treturn new ToolManager()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/core/errors.ts","../../../src/core/validators.ts","../../../src/core/helpers.ts","../../../src/core/tools/Tool.ts","../../../src/core/tools/ToolManager.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { ToolErrorCode, ToolErrorContext } from './types.js'\nimport { isInstance } from '@orkestrel/contract'\n\n/**\n * Reports a schema conflict or argument validation failure with a machine-readable code.\n *\n * @example\n * ```ts\n * import { ToolError } from '@orkestrel/tool'\n *\n * const error = new ToolError('SCHEMA', 'Choose contract or parameters')\n * error.code // 'SCHEMA'\n * ```\n */\nexport class ToolError extends Error {\n\toverride readonly name = 'ToolError' as const\n\treadonly code: ToolErrorCode\n\treadonly context?: ToolErrorContext\n\n\tconstructor(code: ToolErrorCode, message: string, context?: ToolErrorContext) {\n\t\tsuper(message)\n\t\tthis.code = code\n\t\tif (context !== undefined) this.context = context\n\t}\n}\n\n/**\n * Checks whether a value is a tool error, containing hostile prototype access.\n *\n * @param value - The value to test\n * @returns True if the value is an instance of the tool error class; false otherwise\n *\n * @example\n * ```ts\n * import { ToolError, isToolError } from '@orkestrel/tool'\n *\n * isToolError(new ToolError('ARGUMENTS', 'Invalid amount')) // true\n * isToolError(new Error('Unrelated')) // false\n * ```\n */\nexport function isToolError(value: unknown): value is ToolError {\n\treturn isInstance(value, ToolError)\n}\n","import type { ToolCall } from './types.js'\nimport { holds, isRecord, isString } from '@orkestrel/contract'\n\n/**\n * Determines whether an unknown value is structurally a {@link ToolCall}, staying total\n * for malformed and adversarial input.\n *\n * @remarks\n * The accepted shape is a plain record with string `id` and `name` fields and a\n * plain-record `arguments` field. Extra fields are not read or verified.\n *\n * @param value - The value to test\n * @returns True if the value has the complete tool-call shape; false otherwise\n *\n * @example\n * ```ts\n * import { isToolCall } from '@orkestrel/tool'\n *\n * isToolCall({ id: '1', name: 'search', arguments: { query: 'birds' } }) // true\n * isToolCall({ id: '1', name: 'search', arguments: [] }) // false\n * ```\n */\nexport function isToolCall(value: unknown): value is ToolCall {\n\treturn holds(\n\t\t() =>\n\t\t\tisRecord(value) && isString(value.id) && isString(value.name) && isRecord(value.arguments),\n\t)\n}\n","import type { ToolDefinition, ToolInterface } from './types.js'\n\n/**\n * Projects a tool onto the plain definition advertised to a caller, advertising an\n * authored `summary` in place of the full description and carrying `parameters` and\n * `annotations` by reference.\n *\n * @remarks\n * The projection carries `name` and present `title`, `description`, `parameters`, and\n * `annotations` fields in that order. The full `description` stays on the tool for\n * direct lookup, and the definition is never a live handle on the tool's handler.\n *\n * @param tool - The tool to project\n * @returns A fresh definition carrying only the fields the tool authored\n *\n * @example\n * ```ts\n * import { Tool, toolToDefinition } from '@orkestrel/tool'\n *\n * const echo = new Tool({ name: 'echo', summary: 'Echo a value.', execute: (args) => args.value })\n * toolToDefinition(echo) // { name: 'echo', description: 'Echo a value.' }\n * ```\n */\nexport function toolToDefinition(tool: ToolInterface): ToolDefinition {\n\tconst description = tool.summary ?? tool.description\n\treturn {\n\t\tname: tool.name,\n\t\t...(tool.title === undefined ? {} : { title: tool.title }),\n\t\t...(description === undefined ? {} : { description }),\n\t\t...(tool.parameters === undefined ? {} : { parameters: tool.parameters }),\n\t\t...(tool.annotations === undefined ? {} : { annotations: tool.annotations }),\n\t}\n}\n","import type { ContractInterface } from '@orkestrel/contract'\nimport type { ToolAnnotations, ToolContext, ToolInterface, ToolOptions } from '../types.js'\nimport { createContract, isRecord, isString, schemaToParameters } from '@orkestrel/contract'\nimport { ToolError } from '../errors.js'\n\n/**\n * Binds an executable tool definition to a handler.\n *\n * @remarks\n * Advertised fields and execution context are forwarded by reference.\n * A contract derives parameters at construction and refuses parse faults before the\n * handler runs, then forwards the parsed arguments; without a contract, arguments\n * retain their identity. Supplying a contract and parameters throws a schema conflict.\n * Caller context is consumer-asserted and is not verified. Handler failures are not\n * caught here; {@link ToolManager} owns per-call error isolation.\n *\n * @example\n * ```ts\n * import { Tool } from '@orkestrel/tool'\n *\n * const tool = new Tool({\n * \tname: 'add',\n * \tdescription: 'Add two numbers',\n * \tparameters: {\n * \t\ttype: 'object',\n * \t\tproperties: { a: { type: 'number' }, b: { type: 'number' } },\n * \t},\n * \texecute: (args) => Number(args.a) + Number(args.b),\n * })\n * ```\n */\nexport class Tool implements ToolInterface {\n\treadonly #contract?: ContractInterface<unknown>\n\treadonly #execute: ToolOptions['execute']\n\n\treadonly name: string\n\treadonly title?: string\n\treadonly description?: string\n\treadonly summary?: string\n\treadonly parameters?: Readonly<Record<string, unknown>>\n\treadonly annotations?: ToolAnnotations\n\n\tconstructor(options: ToolOptions) {\n\t\tif (options.contract !== undefined && options.parameters !== undefined) {\n\t\t\tthrow new ToolError('SCHEMA', 'Choose contract or parameters, not both')\n\t\t}\n\t\tthis.name = options.name\n\t\tif (options.title !== undefined) this.title = options.title\n\t\tif (options.description !== undefined) this.description = options.description\n\t\tif (options.summary !== undefined) this.summary = options.summary\n\t\tif (options.annotations !== undefined) this.annotations = options.annotations\n\t\tif (options.contract !== undefined) {\n\t\t\tthis.#contract = createContract(options.contract)\n\t\t\tconst parameters = schemaToParameters(this.#contract.schema)\n\t\t\tif (parameters !== undefined) this.parameters = parameters\n\t\t} else if (options.parameters !== undefined) this.parameters = options.parameters\n\t\tthis.#execute = options.execute\n\t}\n\n\texecute(\n\t\targs: Readonly<Record<string, unknown>>,\n\t\tcontext: ToolContext,\n\t): Promise<unknown> | unknown {\n\t\tconst faults = this.#contract?.explain(args) ?? []\n\t\tconst fault = faults[0]\n\t\tif (fault !== undefined) {\n\t\t\tconst path = isString(fault.path) ? fault.path : fault.path.join('.')\n\t\t\tlet message = `${path}: ${fault.reason}`\n\t\t\tif ('expected' in fault) message += `; expected ${fault.expected}`\n\t\t\tif ('received' in fault) message += `; received ${fault.received}`\n\t\t\tif ('constraint' in fault) message += `; constraint ${fault.constraint}`\n\t\t\tif ('limit' in fault && fault.limit !== undefined) message += `; limit ${fault.limit}`\n\t\t\tif ('variants' in fault) message += `; variants ${fault.variants}`\n\t\t\tif ('matched' in fault) message += `; matched ${fault.matched}`\n\t\t\tthrow new ToolError('ARGUMENTS', message, { faults })\n\t\t}\n\t\tif (this.#contract !== undefined) {\n\t\t\tconst parsed = this.#contract.parse(args)\n\t\t\tif (!isRecord(parsed)) throw new ToolError('ARGUMENTS', 'Arguments did not parse')\n\t\t\treturn this.#execute(parsed, context)\n\t\t}\n\t\treturn this.#execute(args, context)\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tToolCall,\n\tToolContext,\n\tToolDefinition,\n\tToolInterface,\n\tToolManagerEventMap,\n\tToolManagerInterface,\n\tToolManagerOptions,\n\tToolResult,\n} from '../types.js'\nimport { attempt, isArray } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { toolToDefinition } from '../helpers.js'\n\n/**\n * Represents an insertion-ordered tool registry with per-call error isolation.\n *\n * @remarks\n * A repeated name overwrites the registered tool without changing its insertion\n * position. Definitions advertise `summary` in place of `description` when present.\n * Unknown names and handler throws resolve to error results; a call whose `id` or `name`\n * accessor throws when read makes its call, and the batch holding it, reject. Batch\n * execution preserves input order and isolates each call whose members are plain\n * values. Execution context is shared across a batch and forwarded unchanged. An\n * omitted context receives a non-aborted signal. A signal aborted before handler\n * entry produces an error result; later cancellation is the handler's responsibility.\n * Registry changes publish synchronously. Replacements publish `remove`, then `add`\n * if the map still holds that exact replacement after the removal listeners return.\n * Destruction clears the tools before releasing listeners. A destroyed registry\n * publishes nothing, even when later additions update its tool map.\n *\n * @example\n * ```ts\n * import { Tool, ToolManager } from '@orkestrel/tool'\n *\n * const tools = new ToolManager()\n * tools.add(new Tool({ name: 'add', execute: (args) => Number(args.x) + Number(args.y) }))\n * const result = await tools.execute({\n * \tid: '1',\n * \tname: 'add',\n * \targuments: { x: 1, y: 2 },\n * })\n * ```\n */\nexport class ToolManager implements ToolManagerInterface {\n\treadonly #tools = new Map<string, ToolInterface>()\n\treadonly #emitter: Emitter<ToolManagerEventMap>\n\n\tconstructor(options?: ToolManagerOptions) {\n\t\tthis.#emitter = new Emitter<ToolManagerEventMap>(options)\n\t}\n\n\tget count(): number {\n\t\treturn this.#tools.size\n\t}\n\n\tget emitter(): EmitterInterface<ToolManagerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tadd(tool: ToolInterface): void\n\tadd(tools: readonly ToolInterface[]): void\n\tadd(tools: ToolInterface | readonly ToolInterface[]): void {\n\t\tif (isArray(tools)) {\n\t\t\tfor (const tool of tools) this.add(tool)\n\t\t\treturn\n\t\t}\n\t\tconst previous = this.#tools.get(tools.name)\n\t\tthis.#tools.set(tools.name, tools)\n\t\tif (previous !== undefined) this.#emitter.emit('remove', previous)\n\t\tif (this.#tools.get(tools.name) === tools) this.#emitter.emit('add', tools)\n\t}\n\n\ttool(name: string): ToolInterface | undefined {\n\t\treturn this.#tools.get(name)\n\t}\n\n\ttools(): readonly ToolInterface[] {\n\t\treturn [...this.#tools.values()]\n\t}\n\n\tdefinitions(): readonly ToolDefinition[] {\n\t\treturn [...this.#tools.values()].map((tool) => toolToDefinition(tool))\n\t}\n\n\texecute(call: ToolCall, context?: ToolContext): Promise<ToolResult>\n\texecute(calls: readonly ToolCall[], context?: ToolContext): Promise<readonly ToolResult[]>\n\texecute(\n\t\tcall: ToolCall | readonly ToolCall[],\n\t\tcontext: ToolContext = { signal: new AbortController().signal },\n\t): Promise<ToolResult | readonly ToolResult[]> {\n\t\tif (isArray(call)) return Promise.all(call.map((one) => this.#run(one, context)))\n\t\treturn this.#run(call, context)\n\t}\n\n\tremove(name: string): boolean\n\tremove(names: readonly string[]): boolean\n\tremove(names: string | readonly string[]): boolean {\n\t\tif (isArray(names)) {\n\t\t\tlet removed = true\n\t\t\tfor (const name of names) {\n\t\t\t\tif (!this.remove(name)) removed = false\n\t\t\t}\n\t\t\treturn removed\n\t\t}\n\t\tconst tool = this.#tools.get(names)\n\t\tif (tool === undefined) return false\n\t\tthis.#tools.delete(names)\n\t\tthis.#emitter.emit('remove', tool)\n\t\treturn true\n\t}\n\n\tclear(): void {\n\t\tconst tools = this.tools()\n\t\tthis.#tools.clear()\n\t\tthis.#emitter.emit('clear', tools)\n\t}\n\n\tdestroy(): void {\n\t\tthis.clear()\n\t\tthis.#emitter.destroy()\n\t\tthis.#tools.clear()\n\t}\n\n\tasync #run(call: ToolCall, context: ToolContext): Promise<ToolResult> {\n\t\tconst tool = this.#tools.get(call.name)\n\t\tif (tool === undefined) {\n\t\t\treturn {\n\t\t\t\tid: call.id,\n\t\t\t\tname: call.name,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `tool not found: ${call.name}`,\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tif (context.signal.aborted) {\n\t\t\t\tconst reason: unknown = context.signal.reason\n\t\t\t\treturn {\n\t\t\t\t\tid: call.id,\n\t\t\t\t\tname: call.name,\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: reason === undefined ? 'aborted' : String(reason),\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst value = await tool.execute(call.arguments, context)\n\t\t\treturn { id: call.id, name: call.name, success: true, value }\n\t\t} catch (error) {\n\t\t\tconst message = attempt(() =>\n\t\t\t\terror instanceof Error ? String(error.message) : String(error),\n\t\t\t)\n\t\t\treturn {\n\t\t\t\tid: call.id,\n\t\t\t\tname: call.name,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: message.success ? message.value : 'Unknown thrown value',\n\t\t\t}\n\t\t}\n\t}\n}\n","import type {\n\tToolInterface,\n\tToolManagerInterface,\n\tToolManagerOptions,\n\tToolOptions,\n} from './types.js'\nimport { Tool } from './tools/Tool.js'\nimport { ToolManager } from './tools/ToolManager.js'\n\n/**\n * Creates an executable tool bound to the supplied handler, returned as a\n * `ToolInterface` so a call site holds the published contract rather than the `Tool`\n * class.\n *\n * @param options - The advertised definition and execution handler\n * @returns A tool bound to the supplied handler\n *\n * @example Anatomy of a tool\n * ```ts\n * import { createTool } from '@orkestrel/tool'\n *\n * const add = createTool({\n * \tname: 'add',\n * \tdescription: 'Add two numeric values and return their sum. Both operands are required.',\n * \tsummary: 'Add two numbers.',\n * \tparameters: {\n * \t\ttype: 'object',\n * \t\tproperties: {\n * \t\t\tleft: { type: 'number' },\n * \t\t\tright: { type: 'number' },\n * \t\t},\n * \t\trequired: ['left', 'right'],\n * \t},\n * \texecute: (args) => Number(args.left) + Number(args.right),\n * })\n * ```\n */\nexport function createTool(options: ToolOptions): ToolInterface {\n\treturn new Tool(options)\n}\n\n/**\n * Creates an empty registry that advertises definitions and executes calls with\n * per-call error isolation, returned as a `ToolManagerInterface` so a caller holds the\n * published contract rather than the `ToolManager` class.\n *\n * @param options - The initial registry listeners and listener-error handler\n * @returns A registry bound to no tools\n *\n * @example\n * ```ts\n * import { createTool, createToolManager } from '@orkestrel/tool'\n *\n * const tools = createToolManager()\n * tools.add(createTool({ name: 'echo', execute: (args) => args.value }))\n * const result = await tools.execute({\n * \tid: '1',\n * \tname: 'echo',\n * \targuments: { value: 'hello' },\n * })\n * ```\n */\nexport function createToolManager(options?: ToolManagerOptions): ToolManagerInterface {\n\treturn new ToolManager(options)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkestrel/tool",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "The tool runtime for the @orkestrel line — JSON-Schema tool definitions, calls, results, executable tools, and a registry with per-call error isolation. Part of the @orkestrel line.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -69,19 +69,20 @@
|
|
|
69
69
|
"test:setup": "vitest run --config vite.config.ts --no-cache --reporter=dot --project setup"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@orkestrel/contract": "^0.0.17"
|
|
72
|
+
"@orkestrel/contract": "^0.0.17",
|
|
73
|
+
"@orkestrel/emitter": "^0.0.10"
|
|
73
74
|
},
|
|
74
75
|
"devDependencies": {
|
|
75
|
-
"@microsoft/api-extractor": "^7.59.
|
|
76
|
-
"@orkestrel/guide": "^0.0.
|
|
77
|
-
"@orkestrel/probe": "^0.0.
|
|
78
|
-
"@orkestrel/scaffold": "^0.0.
|
|
76
|
+
"@microsoft/api-extractor": "^7.59.1",
|
|
77
|
+
"@orkestrel/guide": "^0.0.19",
|
|
78
|
+
"@orkestrel/probe": "^0.0.14",
|
|
79
|
+
"@orkestrel/scaffold": "^0.0.68",
|
|
79
80
|
"@orkestrel/test": "^0.0.14",
|
|
80
|
-
"@types/node": "^26.
|
|
81
|
-
"oxfmt": "^0.
|
|
82
|
-
"oxlint": "^1.
|
|
81
|
+
"@types/node": "^26.5.1",
|
|
82
|
+
"oxfmt": "^0.68.0",
|
|
83
|
+
"oxlint": "^1.83.0",
|
|
83
84
|
"typescript": "^6.0.3",
|
|
84
|
-
"vite": "^8.
|
|
85
|
+
"vite": "^8.3.0",
|
|
85
86
|
"vitest": "^4.1.11"
|
|
86
87
|
},
|
|
87
88
|
"engines": {
|