@orkestrel/tool 0.0.7 → 0.0.9
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 +5 -1
- package/dist/src/core/index.cjs +14 -6
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +54 -17
- package/dist/src/core/index.d.ts +54 -17
- package/dist/src/core/index.js +14 -6
- package/dist/src/core/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -47,7 +47,11 @@ const result = await tools.execute({
|
|
|
47
47
|
name: 'add',
|
|
48
48
|
arguments: { left: 2, right: 3 },
|
|
49
49
|
})
|
|
50
|
-
|
|
50
|
+
if (result.success) {
|
|
51
|
+
result.value // 5
|
|
52
|
+
} else {
|
|
53
|
+
result.error // the failure message
|
|
54
|
+
}
|
|
51
55
|
```
|
|
52
56
|
|
|
53
57
|
Handlers may be synchronous or asynchronous. An unknown name or a thrown handler becomes an
|
package/dist/src/core/index.cjs
CHANGED
|
@@ -6,7 +6,8 @@ let _orkestrel_contract = require("@orkestrel/contract");
|
|
|
6
6
|
*
|
|
7
7
|
* @remarks
|
|
8
8
|
* This total guard accepts a plain record with string `id` and `name` fields and a
|
|
9
|
-
* plain-record `arguments` field.
|
|
9
|
+
* plain-record `arguments` field. Optional caller context remains opaque and is not
|
|
10
|
+
* read or verified. Adversarial values return `false`.
|
|
10
11
|
*
|
|
11
12
|
* @param value - The value to test
|
|
12
13
|
* @returns `true` when the value has the complete tool-call shape
|
|
@@ -28,7 +29,8 @@ function isToolCall(value) {
|
|
|
28
29
|
* An executable tool definition bound to a handler.
|
|
29
30
|
*
|
|
30
31
|
* @remarks
|
|
31
|
-
* Schema fields and
|
|
32
|
+
* Schema fields, arguments, and present caller context are forwarded by reference.
|
|
33
|
+
* Caller context is consumer-asserted and is not verified. Handler failures are not
|
|
32
34
|
* caught here; {@link ToolManager} owns per-call error isolation.
|
|
33
35
|
*
|
|
34
36
|
* @example
|
|
@@ -59,8 +61,9 @@ var Tool = class {
|
|
|
59
61
|
if (options.parameters !== void 0) this.parameters = options.parameters;
|
|
60
62
|
this.#execute = options.execute;
|
|
61
63
|
}
|
|
62
|
-
execute(args) {
|
|
63
|
-
return this.#execute(args);
|
|
64
|
+
execute(args, caller) {
|
|
65
|
+
if (caller === void 0) return this.#execute(args);
|
|
66
|
+
return this.#execute(args, caller);
|
|
64
67
|
}
|
|
65
68
|
};
|
|
66
69
|
//#endregion
|
|
@@ -72,7 +75,8 @@ var Tool = class {
|
|
|
72
75
|
* A repeated name overwrites the registered tool without changing its insertion
|
|
73
76
|
* position. Definitions advertise `summary` in place of `description` when present.
|
|
74
77
|
* Unknown names and handler throws resolve to error results; batch execution preserves
|
|
75
|
-
* input order and never fails as a whole because of an individual call.
|
|
78
|
+
* input order and never fails as a whole because of an individual call. Optional
|
|
79
|
+
* consumer-asserted caller context is forwarded without verification.
|
|
76
80
|
*
|
|
77
81
|
* @example
|
|
78
82
|
* ```ts
|
|
@@ -128,13 +132,16 @@ var ToolManager = class {
|
|
|
128
132
|
if (tool === void 0) return {
|
|
129
133
|
id: call.id,
|
|
130
134
|
name: call.name,
|
|
135
|
+
success: false,
|
|
131
136
|
error: `tool not found: ${call.name}`
|
|
132
137
|
};
|
|
133
138
|
try {
|
|
134
|
-
const
|
|
139
|
+
const caller = call.caller;
|
|
140
|
+
const value = await (caller === void 0 ? tool.execute(call.arguments) : tool.execute(call.arguments, caller));
|
|
135
141
|
return {
|
|
136
142
|
id: call.id,
|
|
137
143
|
name: call.name,
|
|
144
|
+
success: true,
|
|
138
145
|
value
|
|
139
146
|
};
|
|
140
147
|
} catch (error) {
|
|
@@ -142,6 +149,7 @@ var ToolManager = class {
|
|
|
142
149
|
return {
|
|
143
150
|
id: call.id,
|
|
144
151
|
name: call.name,
|
|
152
|
+
success: false,
|
|
145
153
|
error: message.success ? message.value : "Unknown thrown value"
|
|
146
154
|
};
|
|
147
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["#execute","#tools","#definition","#run"],"sources":["../../../src/core/helpers.ts","../../../src/core/tools/Tool.ts","../../../src/core/tools/ToolManager.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { ToolCall } from './types.js'\nimport { holds, isRecord, isString } from '@orkestrel/contract'\n\n/**\n * Determine whether an unknown value is structurally a {@link ToolCall}.\n *\n * @remarks\n * This total guard accepts a plain record with string `id` and `name` fields and a\n * plain-record `arguments` field. Adversarial values return `false`.\n *\n * @param value - The value to test\n * @returns `true` when the value has the complete tool-call shape\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 * An executable tool definition bound to a handler.\n *\n * @remarks\n * Schema fields and arguments are forwarded by reference. 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: (args: Readonly<Record<string, unknown>>) => 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>>): Promise<unknown> | unknown {\n\t\treturn this.#execute(args)\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'\n\n/**\n * 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; batch execution preserves\n * input order and never fails as a whole because of an individual call.\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) => this.#definition(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 = false\n\t\t\tfor (const name of names) {\n\t\t\t\tif (this.#tools.delete(name)) removed = true\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 { id: call.id, name: call.name, error: `tool not found: ${call.name}` }\n\t\t}\n\t\ttry {\n\t\t\tconst value = await tool.execute(call.arguments)\n\t\t\treturn { id: call.id, name: call.name, 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\terror: message.success ? message.value : 'Unknown thrown value',\n\t\t\t}\n\t\t}\n\t}\n\n\t#definition(tool: ToolInterface): ToolDefinition {\n\t\tconst definition: {\n\t\t\tname: string\n\t\t\tdescription?: string\n\t\t\tparameters?: Readonly<Record<string, unknown>>\n\t\t} = {\n\t\t\tname: tool.name,\n\t\t}\n\t\tconst description = tool.summary ?? tool.description\n\t\tif (description !== undefined) definition.description = description\n\t\tif (tool.parameters !== undefined) definition.parameters = tool.parameters\n\t\treturn definition\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 * Create an executable tool.\n *\n * @param options - The advertised definition and execution handler\n * @returns A tool bound to the supplied handler\n *\n * @example\n * ```ts\n * import { createTool } from '@orkestrel/tool'\n *\n * const add = createTool({\n * \tname: 'add',\n * \tdescription: 'Add two numbers',\n * \texecute: (args) => Number(args.a) + Number(args.b),\n * })\n * ```\n */\nexport function createTool(options: ToolOptions): ToolInterface {\n\treturn new Tool(options)\n}\n\n/**\n * Create an empty tool registry.\n *\n * @returns A registry that advertises definitions and executes calls with per-call\n * error isolation\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.cjs","names":["#execute","#tools","#definition","#run"],"sources":["../../../src/core/helpers.ts","../../../src/core/tools/Tool.ts","../../../src/core/tools/ToolManager.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { ToolCall } from './types.js'\nimport { holds, isRecord, isString } from '@orkestrel/contract'\n\n/**\n * Determine whether an unknown value is structurally a {@link ToolCall}.\n *\n * @remarks\n * This total guard accepts 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. Adversarial values return `false`.\n *\n * @param value - The value to test\n * @returns `true` when the value has the complete tool-call shape\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 * An executable tool definition bound 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'\n\n/**\n * 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; batch execution preserves\n * input order and never fails as a whole because of an individual call. Optional\n * 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) => this.#definition(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 = false\n\t\t\tfor (const name of names) {\n\t\t\t\tif (this.#tools.delete(name)) removed = true\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\t#definition(tool: ToolInterface): ToolDefinition {\n\t\tconst definition: {\n\t\t\tname: string\n\t\t\tdescription?: string\n\t\t\tparameters?: Readonly<Record<string, unknown>>\n\t\t} = {\n\t\t\tname: tool.name,\n\t\t}\n\t\tconst description = tool.summary ?? tool.description\n\t\tif (description !== undefined) definition.description = description\n\t\tif (tool.parameters !== undefined) definition.parameters = tool.parameters\n\t\treturn definition\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 * Create an executable tool.\n *\n * @param options - The advertised definition and execution handler\n * @returns A tool bound to the supplied handler\n *\n * @example\n * ```ts\n * import { createTool } from '@orkestrel/tool'\n *\n * const add = createTool({\n * \tname: 'add',\n * \tdescription: 'Add two numbers',\n * \texecute: (args) => Number(args.a) + Number(args.b),\n * })\n * ```\n */\nexport function createTool(options: ToolOptions): ToolInterface {\n\treturn new Tool(options)\n}\n\n/**\n * Create an empty tool registry.\n *\n * @returns A registry that advertises definitions and executes calls with per-call\n * error isolation\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,3 +1,6 @@
|
|
|
1
|
+
import { Failure } from '@orkestrel/contract';
|
|
2
|
+
import { Success } from '@orkestrel/contract';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Create an executable tool.
|
|
3
6
|
*
|
|
@@ -43,7 +46,8 @@ export declare function createToolManager(): ToolManagerInterface;
|
|
|
43
46
|
*
|
|
44
47
|
* @remarks
|
|
45
48
|
* This total guard accepts a plain record with string `id` and `name` fields and a
|
|
46
|
-
* plain-record `arguments` field.
|
|
49
|
+
* plain-record `arguments` field. Optional caller context remains opaque and is not
|
|
50
|
+
* read or verified. Adversarial values return `false`.
|
|
47
51
|
*
|
|
48
52
|
* @param value - The value to test
|
|
49
53
|
* @returns `true` when the value has the complete tool-call shape
|
|
@@ -62,7 +66,8 @@ export declare function isToolCall(value: unknown): value is ToolCall;
|
|
|
62
66
|
* An executable tool definition bound to a handler.
|
|
63
67
|
*
|
|
64
68
|
* @remarks
|
|
65
|
-
* Schema fields and
|
|
69
|
+
* Schema fields, arguments, and present caller context are forwarded by reference.
|
|
70
|
+
* Caller context is consumer-asserted and is not verified. Handler failures are not
|
|
66
71
|
* caught here; {@link ToolManager} owns per-call error isolation.
|
|
67
72
|
*
|
|
68
73
|
* @example
|
|
@@ -87,7 +92,7 @@ export declare class Tool implements ToolInterface {
|
|
|
87
92
|
readonly summary?: string;
|
|
88
93
|
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
89
94
|
constructor(options: ToolOptions);
|
|
90
|
-
execute(args: Readonly<Record<string, unknown
|
|
95
|
+
execute(args: Readonly<Record<string, unknown>>, caller?: unknown): Promise<unknown> | unknown;
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
/**
|
|
@@ -95,7 +100,9 @@ export declare class Tool implements ToolInterface {
|
|
|
95
100
|
*
|
|
96
101
|
* @remarks
|
|
97
102
|
* `id` correlates the call with its later {@link ToolResult}. `arguments` is the
|
|
98
|
-
* caller-supplied arguments record.
|
|
103
|
+
* caller-supplied arguments record. `caller` is optional consumer-asserted context:
|
|
104
|
+
* this package forwards it without verification, so the tool or its policy layer owns
|
|
105
|
+
* every trust decision.
|
|
99
106
|
*/
|
|
100
107
|
export declare interface ToolCall {
|
|
101
108
|
/** The identifier that correlates this call with its result. */
|
|
@@ -104,6 +111,8 @@ export declare interface ToolCall {
|
|
|
104
111
|
readonly name: string;
|
|
105
112
|
/** The caller-supplied arguments record. */
|
|
106
113
|
readonly arguments: Readonly<Record<string, unknown>>;
|
|
114
|
+
/** Consumer-asserted caller context, forwarded without verification. */
|
|
115
|
+
readonly caller?: unknown;
|
|
107
116
|
}
|
|
108
117
|
|
|
109
118
|
/**
|
|
@@ -121,6 +130,22 @@ export declare interface ToolDefinition {
|
|
|
121
130
|
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
122
131
|
}
|
|
123
132
|
|
|
133
|
+
/**
|
|
134
|
+
* The failed outcome of executing a {@link ToolCall}.
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* `error` is the failure message: an unknown tool name, an `Error`'s message, or
|
|
138
|
+
* a String-converted throw. The registry carries no further structure. An
|
|
139
|
+
* in-process caller needing a typed error calls `tools.tool(name)`, then
|
|
140
|
+
* `tool.execute(args)` in its own `try`/`catch`.
|
|
141
|
+
*/
|
|
142
|
+
export declare interface ToolFailure extends Failure<string> {
|
|
143
|
+
/** The identifier of the corresponding call. */
|
|
144
|
+
readonly id: string;
|
|
145
|
+
/** The name of the called tool. */
|
|
146
|
+
readonly name: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
124
149
|
/**
|
|
125
150
|
* An executable tool: its advertised definition plus its local handler.
|
|
126
151
|
*
|
|
@@ -135,9 +160,10 @@ export declare interface ToolInterface extends ToolDefinition {
|
|
|
135
160
|
* Execute the tool.
|
|
136
161
|
*
|
|
137
162
|
* @param args - The caller-supplied arguments record
|
|
163
|
+
* @param caller - Optional consumer-asserted caller context, forwarded without verification
|
|
138
164
|
* @returns The tool's synchronous or asynchronous result
|
|
139
165
|
*/
|
|
140
|
-
execute(args: Readonly<Record<string, unknown
|
|
166
|
+
execute(args: Readonly<Record<string, unknown>>, caller?: unknown): Promise<unknown> | unknown;
|
|
141
167
|
}
|
|
142
168
|
|
|
143
169
|
/**
|
|
@@ -147,7 +173,8 @@ export declare interface ToolInterface extends ToolDefinition {
|
|
|
147
173
|
* A repeated name overwrites the registered tool without changing its insertion
|
|
148
174
|
* position. Definitions advertise `summary` in place of `description` when present.
|
|
149
175
|
* Unknown names and handler throws resolve to error results; batch execution preserves
|
|
150
|
-
* input order and never fails as a whole because of an individual call.
|
|
176
|
+
* input order and never fails as a whole because of an individual call. Optional
|
|
177
|
+
* consumer-asserted caller context is forwarded without verification.
|
|
151
178
|
*
|
|
152
179
|
* @example
|
|
153
180
|
* ```ts
|
|
@@ -219,20 +246,24 @@ export declare interface ToolManagerInterface {
|
|
|
219
246
|
/**
|
|
220
247
|
* List the definitions advertised to a caller.
|
|
221
248
|
*
|
|
249
|
+
* The projected `description` is the tool's `summary` when one was authored,
|
|
250
|
+
* advertised in place of the full description. The full text stays on the tool
|
|
251
|
+
* for direct lookup.
|
|
252
|
+
*
|
|
222
253
|
* @returns A new readonly array of tool definitions
|
|
223
254
|
*/
|
|
224
255
|
definitions(): readonly ToolDefinition[];
|
|
225
256
|
/**
|
|
226
257
|
* Execute one call with error isolation.
|
|
227
258
|
*
|
|
228
|
-
* @param call - The tool call to execute
|
|
259
|
+
* @param call - The tool call to execute, including optional caller context
|
|
229
260
|
* @returns The correlated result
|
|
230
261
|
*/
|
|
231
262
|
execute(call: ToolCall): Promise<ToolResult>;
|
|
232
263
|
/**
|
|
233
264
|
* Execute a batch of calls with per-call error isolation.
|
|
234
265
|
*
|
|
235
|
-
* @param calls - The tool calls to execute
|
|
266
|
+
* @param calls - The tool calls to execute, including optional caller context
|
|
236
267
|
* @returns The correlated results in input order
|
|
237
268
|
*/
|
|
238
269
|
execute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
|
|
@@ -264,7 +295,8 @@ export declare interface ToolManagerInterface {
|
|
|
264
295
|
* @remarks
|
|
265
296
|
* `name` identifies the tool, `description` and `parameters` define what is advertised
|
|
266
297
|
* to a caller, `summary` optionally replaces the advertised description, and `execute`
|
|
267
|
-
* handles the caller-supplied arguments record
|
|
298
|
+
* handles the caller-supplied arguments record plus optional consumer-asserted caller
|
|
299
|
+
* context. This package forwards that context without verification.
|
|
268
300
|
*/
|
|
269
301
|
export declare interface ToolOptions {
|
|
270
302
|
/** The name a caller uses to select the tool. */
|
|
@@ -275,25 +307,30 @@ export declare interface ToolOptions {
|
|
|
275
307
|
readonly summary?: string;
|
|
276
308
|
/** The JSON Schema for the tool's arguments. */
|
|
277
309
|
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
278
|
-
/** The handler that
|
|
279
|
-
readonly execute: (args: Readonly<Record<string, unknown
|
|
310
|
+
/** The handler that receives arguments and optional unverified caller context. */
|
|
311
|
+
readonly execute: (args: Readonly<Record<string, unknown>>, caller?: unknown) => Promise<unknown> | unknown;
|
|
280
312
|
}
|
|
281
313
|
|
|
282
314
|
/**
|
|
283
315
|
* The outcome of executing a {@link ToolCall}.
|
|
284
316
|
*
|
|
285
317
|
* @remarks
|
|
286
|
-
*
|
|
318
|
+
* Always a result and never a throw. Narrow on `success`.
|
|
319
|
+
*/
|
|
320
|
+
export declare type ToolResult = ToolSuccess | ToolFailure;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* The successful outcome of executing a {@link ToolCall}.
|
|
324
|
+
*
|
|
325
|
+
* @remarks
|
|
326
|
+
* `value` is whatever the handler returned — including `undefined`, `null`, `0`,
|
|
327
|
+
* `''`, or `false`. A present value never implies a meaningful one.
|
|
287
328
|
*/
|
|
288
|
-
export declare interface
|
|
329
|
+
export declare interface ToolSuccess extends Success<unknown> {
|
|
289
330
|
/** The identifier of the corresponding call. */
|
|
290
331
|
readonly id: string;
|
|
291
332
|
/** The name of the called tool. */
|
|
292
333
|
readonly name: string;
|
|
293
|
-
/** The successful return value. */
|
|
294
|
-
readonly value?: unknown;
|
|
295
|
-
/** The failure message. */
|
|
296
|
-
readonly error?: string;
|
|
297
334
|
}
|
|
298
335
|
|
|
299
336
|
export { }
|
package/dist/src/core/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Failure } from '@orkestrel/contract';
|
|
2
|
+
import { Success } from '@orkestrel/contract';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Create an executable tool.
|
|
3
6
|
*
|
|
@@ -43,7 +46,8 @@ export declare function createToolManager(): ToolManagerInterface;
|
|
|
43
46
|
*
|
|
44
47
|
* @remarks
|
|
45
48
|
* This total guard accepts a plain record with string `id` and `name` fields and a
|
|
46
|
-
* plain-record `arguments` field.
|
|
49
|
+
* plain-record `arguments` field. Optional caller context remains opaque and is not
|
|
50
|
+
* read or verified. Adversarial values return `false`.
|
|
47
51
|
*
|
|
48
52
|
* @param value - The value to test
|
|
49
53
|
* @returns `true` when the value has the complete tool-call shape
|
|
@@ -62,7 +66,8 @@ export declare function isToolCall(value: unknown): value is ToolCall;
|
|
|
62
66
|
* An executable tool definition bound to a handler.
|
|
63
67
|
*
|
|
64
68
|
* @remarks
|
|
65
|
-
* Schema fields and
|
|
69
|
+
* Schema fields, arguments, and present caller context are forwarded by reference.
|
|
70
|
+
* Caller context is consumer-asserted and is not verified. Handler failures are not
|
|
66
71
|
* caught here; {@link ToolManager} owns per-call error isolation.
|
|
67
72
|
*
|
|
68
73
|
* @example
|
|
@@ -87,7 +92,7 @@ export declare class Tool implements ToolInterface {
|
|
|
87
92
|
readonly summary?: string;
|
|
88
93
|
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
89
94
|
constructor(options: ToolOptions);
|
|
90
|
-
execute(args: Readonly<Record<string, unknown
|
|
95
|
+
execute(args: Readonly<Record<string, unknown>>, caller?: unknown): Promise<unknown> | unknown;
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
/**
|
|
@@ -95,7 +100,9 @@ export declare class Tool implements ToolInterface {
|
|
|
95
100
|
*
|
|
96
101
|
* @remarks
|
|
97
102
|
* `id` correlates the call with its later {@link ToolResult}. `arguments` is the
|
|
98
|
-
* caller-supplied arguments record.
|
|
103
|
+
* caller-supplied arguments record. `caller` is optional consumer-asserted context:
|
|
104
|
+
* this package forwards it without verification, so the tool or its policy layer owns
|
|
105
|
+
* every trust decision.
|
|
99
106
|
*/
|
|
100
107
|
export declare interface ToolCall {
|
|
101
108
|
/** The identifier that correlates this call with its result. */
|
|
@@ -104,6 +111,8 @@ export declare interface ToolCall {
|
|
|
104
111
|
readonly name: string;
|
|
105
112
|
/** The caller-supplied arguments record. */
|
|
106
113
|
readonly arguments: Readonly<Record<string, unknown>>;
|
|
114
|
+
/** Consumer-asserted caller context, forwarded without verification. */
|
|
115
|
+
readonly caller?: unknown;
|
|
107
116
|
}
|
|
108
117
|
|
|
109
118
|
/**
|
|
@@ -121,6 +130,22 @@ export declare interface ToolDefinition {
|
|
|
121
130
|
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
122
131
|
}
|
|
123
132
|
|
|
133
|
+
/**
|
|
134
|
+
* The failed outcome of executing a {@link ToolCall}.
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* `error` is the failure message: an unknown tool name, an `Error`'s message, or
|
|
138
|
+
* a String-converted throw. The registry carries no further structure. An
|
|
139
|
+
* in-process caller needing a typed error calls `tools.tool(name)`, then
|
|
140
|
+
* `tool.execute(args)` in its own `try`/`catch`.
|
|
141
|
+
*/
|
|
142
|
+
export declare interface ToolFailure extends Failure<string> {
|
|
143
|
+
/** The identifier of the corresponding call. */
|
|
144
|
+
readonly id: string;
|
|
145
|
+
/** The name of the called tool. */
|
|
146
|
+
readonly name: string;
|
|
147
|
+
}
|
|
148
|
+
|
|
124
149
|
/**
|
|
125
150
|
* An executable tool: its advertised definition plus its local handler.
|
|
126
151
|
*
|
|
@@ -135,9 +160,10 @@ export declare interface ToolInterface extends ToolDefinition {
|
|
|
135
160
|
* Execute the tool.
|
|
136
161
|
*
|
|
137
162
|
* @param args - The caller-supplied arguments record
|
|
163
|
+
* @param caller - Optional consumer-asserted caller context, forwarded without verification
|
|
138
164
|
* @returns The tool's synchronous or asynchronous result
|
|
139
165
|
*/
|
|
140
|
-
execute(args: Readonly<Record<string, unknown
|
|
166
|
+
execute(args: Readonly<Record<string, unknown>>, caller?: unknown): Promise<unknown> | unknown;
|
|
141
167
|
}
|
|
142
168
|
|
|
143
169
|
/**
|
|
@@ -147,7 +173,8 @@ export declare interface ToolInterface extends ToolDefinition {
|
|
|
147
173
|
* A repeated name overwrites the registered tool without changing its insertion
|
|
148
174
|
* position. Definitions advertise `summary` in place of `description` when present.
|
|
149
175
|
* Unknown names and handler throws resolve to error results; batch execution preserves
|
|
150
|
-
* input order and never fails as a whole because of an individual call.
|
|
176
|
+
* input order and never fails as a whole because of an individual call. Optional
|
|
177
|
+
* consumer-asserted caller context is forwarded without verification.
|
|
151
178
|
*
|
|
152
179
|
* @example
|
|
153
180
|
* ```ts
|
|
@@ -219,20 +246,24 @@ export declare interface ToolManagerInterface {
|
|
|
219
246
|
/**
|
|
220
247
|
* List the definitions advertised to a caller.
|
|
221
248
|
*
|
|
249
|
+
* The projected `description` is the tool's `summary` when one was authored,
|
|
250
|
+
* advertised in place of the full description. The full text stays on the tool
|
|
251
|
+
* for direct lookup.
|
|
252
|
+
*
|
|
222
253
|
* @returns A new readonly array of tool definitions
|
|
223
254
|
*/
|
|
224
255
|
definitions(): readonly ToolDefinition[];
|
|
225
256
|
/**
|
|
226
257
|
* Execute one call with error isolation.
|
|
227
258
|
*
|
|
228
|
-
* @param call - The tool call to execute
|
|
259
|
+
* @param call - The tool call to execute, including optional caller context
|
|
229
260
|
* @returns The correlated result
|
|
230
261
|
*/
|
|
231
262
|
execute(call: ToolCall): Promise<ToolResult>;
|
|
232
263
|
/**
|
|
233
264
|
* Execute a batch of calls with per-call error isolation.
|
|
234
265
|
*
|
|
235
|
-
* @param calls - The tool calls to execute
|
|
266
|
+
* @param calls - The tool calls to execute, including optional caller context
|
|
236
267
|
* @returns The correlated results in input order
|
|
237
268
|
*/
|
|
238
269
|
execute(calls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
|
|
@@ -264,7 +295,8 @@ export declare interface ToolManagerInterface {
|
|
|
264
295
|
* @remarks
|
|
265
296
|
* `name` identifies the tool, `description` and `parameters` define what is advertised
|
|
266
297
|
* to a caller, `summary` optionally replaces the advertised description, and `execute`
|
|
267
|
-
* handles the caller-supplied arguments record
|
|
298
|
+
* handles the caller-supplied arguments record plus optional consumer-asserted caller
|
|
299
|
+
* context. This package forwards that context without verification.
|
|
268
300
|
*/
|
|
269
301
|
export declare interface ToolOptions {
|
|
270
302
|
/** The name a caller uses to select the tool. */
|
|
@@ -275,25 +307,30 @@ export declare interface ToolOptions {
|
|
|
275
307
|
readonly summary?: string;
|
|
276
308
|
/** The JSON Schema for the tool's arguments. */
|
|
277
309
|
readonly parameters?: Readonly<Record<string, unknown>>;
|
|
278
|
-
/** The handler that
|
|
279
|
-
readonly execute: (args: Readonly<Record<string, unknown
|
|
310
|
+
/** The handler that receives arguments and optional unverified caller context. */
|
|
311
|
+
readonly execute: (args: Readonly<Record<string, unknown>>, caller?: unknown) => Promise<unknown> | unknown;
|
|
280
312
|
}
|
|
281
313
|
|
|
282
314
|
/**
|
|
283
315
|
* The outcome of executing a {@link ToolCall}.
|
|
284
316
|
*
|
|
285
317
|
* @remarks
|
|
286
|
-
*
|
|
318
|
+
* Always a result and never a throw. Narrow on `success`.
|
|
319
|
+
*/
|
|
320
|
+
export declare type ToolResult = ToolSuccess | ToolFailure;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* The successful outcome of executing a {@link ToolCall}.
|
|
324
|
+
*
|
|
325
|
+
* @remarks
|
|
326
|
+
* `value` is whatever the handler returned — including `undefined`, `null`, `0`,
|
|
327
|
+
* `''`, or `false`. A present value never implies a meaningful one.
|
|
287
328
|
*/
|
|
288
|
-
export declare interface
|
|
329
|
+
export declare interface ToolSuccess extends Success<unknown> {
|
|
289
330
|
/** The identifier of the corresponding call. */
|
|
290
331
|
readonly id: string;
|
|
291
332
|
/** The name of the called tool. */
|
|
292
333
|
readonly name: string;
|
|
293
|
-
/** The successful return value. */
|
|
294
|
-
readonly value?: unknown;
|
|
295
|
-
/** The failure message. */
|
|
296
|
-
readonly error?: string;
|
|
297
334
|
}
|
|
298
335
|
|
|
299
336
|
export { }
|
package/dist/src/core/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import { attempt, holds, isArray, isRecord, isString } from "@orkestrel/contract
|
|
|
5
5
|
*
|
|
6
6
|
* @remarks
|
|
7
7
|
* This total guard accepts a plain record with string `id` and `name` fields and a
|
|
8
|
-
* plain-record `arguments` field.
|
|
8
|
+
* plain-record `arguments` field. Optional caller context remains opaque and is not
|
|
9
|
+
* read or verified. Adversarial values return `false`.
|
|
9
10
|
*
|
|
10
11
|
* @param value - The value to test
|
|
11
12
|
* @returns `true` when the value has the complete tool-call shape
|
|
@@ -27,7 +28,8 @@ function isToolCall(value) {
|
|
|
27
28
|
* An executable tool definition bound to a handler.
|
|
28
29
|
*
|
|
29
30
|
* @remarks
|
|
30
|
-
* Schema fields and
|
|
31
|
+
* Schema fields, arguments, and present caller context are forwarded by reference.
|
|
32
|
+
* Caller context is consumer-asserted and is not verified. Handler failures are not
|
|
31
33
|
* caught here; {@link ToolManager} owns per-call error isolation.
|
|
32
34
|
*
|
|
33
35
|
* @example
|
|
@@ -58,8 +60,9 @@ var Tool = class {
|
|
|
58
60
|
if (options.parameters !== void 0) this.parameters = options.parameters;
|
|
59
61
|
this.#execute = options.execute;
|
|
60
62
|
}
|
|
61
|
-
execute(args) {
|
|
62
|
-
return this.#execute(args);
|
|
63
|
+
execute(args, caller) {
|
|
64
|
+
if (caller === void 0) return this.#execute(args);
|
|
65
|
+
return this.#execute(args, caller);
|
|
63
66
|
}
|
|
64
67
|
};
|
|
65
68
|
//#endregion
|
|
@@ -71,7 +74,8 @@ var Tool = class {
|
|
|
71
74
|
* A repeated name overwrites the registered tool without changing its insertion
|
|
72
75
|
* position. Definitions advertise `summary` in place of `description` when present.
|
|
73
76
|
* Unknown names and handler throws resolve to error results; batch execution preserves
|
|
74
|
-
* input order and never fails as a whole because of an individual call.
|
|
77
|
+
* input order and never fails as a whole because of an individual call. Optional
|
|
78
|
+
* consumer-asserted caller context is forwarded without verification.
|
|
75
79
|
*
|
|
76
80
|
* @example
|
|
77
81
|
* ```ts
|
|
@@ -127,13 +131,16 @@ var ToolManager = class {
|
|
|
127
131
|
if (tool === void 0) return {
|
|
128
132
|
id: call.id,
|
|
129
133
|
name: call.name,
|
|
134
|
+
success: false,
|
|
130
135
|
error: `tool not found: ${call.name}`
|
|
131
136
|
};
|
|
132
137
|
try {
|
|
133
|
-
const
|
|
138
|
+
const caller = call.caller;
|
|
139
|
+
const value = await (caller === void 0 ? tool.execute(call.arguments) : tool.execute(call.arguments, caller));
|
|
134
140
|
return {
|
|
135
141
|
id: call.id,
|
|
136
142
|
name: call.name,
|
|
143
|
+
success: true,
|
|
137
144
|
value
|
|
138
145
|
};
|
|
139
146
|
} catch (error) {
|
|
@@ -141,6 +148,7 @@ var ToolManager = class {
|
|
|
141
148
|
return {
|
|
142
149
|
id: call.id,
|
|
143
150
|
name: call.name,
|
|
151
|
+
success: false,
|
|
144
152
|
error: message.success ? message.value : "Unknown thrown value"
|
|
145
153
|
};
|
|
146
154
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#execute","#tools","#definition","#run"],"sources":["../../../src/core/helpers.ts","../../../src/core/tools/Tool.ts","../../../src/core/tools/ToolManager.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { ToolCall } from './types.js'\nimport { holds, isRecord, isString } from '@orkestrel/contract'\n\n/**\n * Determine whether an unknown value is structurally a {@link ToolCall}.\n *\n * @remarks\n * This total guard accepts a plain record with string `id` and `name` fields and a\n * plain-record `arguments` field. Adversarial values return `false`.\n *\n * @param value - The value to test\n * @returns `true` when the value has the complete tool-call shape\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 * An executable tool definition bound to a handler.\n *\n * @remarks\n * Schema fields and arguments are forwarded by reference. 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: (args: Readonly<Record<string, unknown>>) => 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>>): Promise<unknown> | unknown {\n\t\treturn this.#execute(args)\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'\n\n/**\n * 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; batch execution preserves\n * input order and never fails as a whole because of an individual call.\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) => this.#definition(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 = false\n\t\t\tfor (const name of names) {\n\t\t\t\tif (this.#tools.delete(name)) removed = true\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 { id: call.id, name: call.name, error: `tool not found: ${call.name}` }\n\t\t}\n\t\ttry {\n\t\t\tconst value = await tool.execute(call.arguments)\n\t\t\treturn { id: call.id, name: call.name, 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\terror: message.success ? message.value : 'Unknown thrown value',\n\t\t\t}\n\t\t}\n\t}\n\n\t#definition(tool: ToolInterface): ToolDefinition {\n\t\tconst definition: {\n\t\t\tname: string\n\t\t\tdescription?: string\n\t\t\tparameters?: Readonly<Record<string, unknown>>\n\t\t} = {\n\t\t\tname: tool.name,\n\t\t}\n\t\tconst description = tool.summary ?? tool.description\n\t\tif (description !== undefined) definition.description = description\n\t\tif (tool.parameters !== undefined) definition.parameters = tool.parameters\n\t\treturn definition\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 * Create an executable tool.\n *\n * @param options - The advertised definition and execution handler\n * @returns A tool bound to the supplied handler\n *\n * @example\n * ```ts\n * import { createTool } from '@orkestrel/tool'\n *\n * const add = createTool({\n * \tname: 'add',\n * \tdescription: 'Add two numbers',\n * \texecute: (args) => Number(args.a) + Number(args.b),\n * })\n * ```\n */\nexport function createTool(options: ToolOptions): ToolInterface {\n\treturn new Tool(options)\n}\n\n/**\n * Create an empty tool registry.\n *\n * @returns A registry that advertises definitions and executes calls with per-call\n * error isolation\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":["#execute","#tools","#definition","#run"],"sources":["../../../src/core/helpers.ts","../../../src/core/tools/Tool.ts","../../../src/core/tools/ToolManager.ts","../../../src/core/factories.ts"],"sourcesContent":["import type { ToolCall } from './types.js'\nimport { holds, isRecord, isString } from '@orkestrel/contract'\n\n/**\n * Determine whether an unknown value is structurally a {@link ToolCall}.\n *\n * @remarks\n * This total guard accepts 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. Adversarial values return `false`.\n *\n * @param value - The value to test\n * @returns `true` when the value has the complete tool-call shape\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 * An executable tool definition bound 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'\n\n/**\n * 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; batch execution preserves\n * input order and never fails as a whole because of an individual call. Optional\n * 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) => this.#definition(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 = false\n\t\t\tfor (const name of names) {\n\t\t\t\tif (this.#tools.delete(name)) removed = true\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\t#definition(tool: ToolInterface): ToolDefinition {\n\t\tconst definition: {\n\t\t\tname: string\n\t\t\tdescription?: string\n\t\t\tparameters?: Readonly<Record<string, unknown>>\n\t\t} = {\n\t\t\tname: tool.name,\n\t\t}\n\t\tconst description = tool.summary ?? tool.description\n\t\tif (description !== undefined) definition.description = description\n\t\tif (tool.parameters !== undefined) definition.parameters = tool.parameters\n\t\treturn definition\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 * Create an executable tool.\n *\n * @param options - The advertised definition and execution handler\n * @returns A tool bound to the supplied handler\n *\n * @example\n * ```ts\n * import { createTool } from '@orkestrel/tool'\n *\n * const add = createTool({\n * \tname: 'add',\n * \tdescription: 'Add two numbers',\n * \texecute: (args) => Number(args.a) + Number(args.b),\n * })\n * ```\n */\nexport function createTool(options: ToolOptions): ToolInterface {\n\treturn new Tool(options)\n}\n\n/**\n * Create an empty tool registry.\n *\n * @returns A registry that advertises definitions and executes calls with per-call\n * error isolation\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkestrel/tool",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
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",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@microsoft/api-extractor": "^7.58.12",
|
|
70
70
|
"@orkestrel/guide": "^0.0.8",
|
|
71
|
-
"@orkestrel/scaffold": "^0.0.
|
|
71
|
+
"@orkestrel/scaffold": "^0.0.16",
|
|
72
72
|
"@types/node": "^26.1.2",
|
|
73
73
|
"@vitest/browser-playwright": "^4.1.10",
|
|
74
74
|
"oxfmt": "^0.61.0",
|