@robota-sdk/agent-tools 3.0.0-beta.79 → 3.0.0-beta.81

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @robota-sdk/agent-tools
2
2
 
3
- Tool registry, tool creation infrastructure, 8 built-in CLI tools, sandbox execution ports, and sandbox workspace manifests for the Robota SDK.
3
+ Tool registry, tool creation infrastructure, 9 built-in CLI tools, sandbox execution ports, and sandbox workspace manifests for the Robota SDK.
4
4
 
5
5
  ## Installation
6
6
 
@@ -31,41 +31,64 @@ const weatherTool = createZodFunctionTool(
31
31
  ### Use Built-in Tools
32
32
 
33
33
  ```typescript
34
- import { bashTool, readTool, globTool, grepTool } from '@robota-sdk/agent-tools';
34
+ import {
35
+ createBashTool,
36
+ createReadTool,
37
+ createGlobTool,
38
+ createGrepTool,
39
+ } from '@robota-sdk/agent-tools';
35
40
  import { Robota } from '@robota-sdk/agent-core';
36
41
  import type { IAIProvider } from '@robota-sdk/agent-core';
37
42
 
38
43
  declare const provider: IAIProvider;
44
+
45
+ // A file tool is built against an explicit containment root and refuses anything outside it
46
+ // (ARCH-010). There is no ready-made instance to import: one bound at import time can carry no root,
47
+ // and a file tool without a root has no boundary.
48
+ const cwd = process.cwd();
49
+
39
50
  const agent = new Robota({
40
51
  name: 'DevAgent',
41
52
  aiProviders: [provider],
42
53
  defaultModel: { provider: 'anthropic', model: 'claude-sonnet-4-6' },
43
- tools: [bashTool, readTool, globTool, grepTool],
54
+ tools: [
55
+ createBashTool({ cwd }),
56
+ createReadTool({ cwd }),
57
+ createGlobTool({ cwd }),
58
+ createGrepTool({ cwd }),
59
+ ],
44
60
  });
45
61
  ```
46
62
 
47
63
  ## Built-in Tools
48
64
 
65
+ Every tool that touches the filesystem is a FACTORY taking the containment root it operates in
66
+ (`cwd`, required — ARCH-010). There is no ready-made instance to import: one bound at import time can
67
+ carry no root, and a file tool with no root has no boundary.
68
+
49
69
  | Export | Tool Name | Description |
50
70
  | --------------------- | --------------- | ----------------------------------------------------------------------------- |
51
- | `shellTool` | Shell | Execute host shell commands; OS-aware (POSIX `sh`/`bash`, Windows PowerShell) |
52
- | `bashTool` | Bash | Model-familiar alias of `Shell` — same OS-aware implementation |
53
- | `readTool` | Read | Read file contents with line numbers (cat -n) |
54
- | `writeTool` | Write | Write content to a file (creates parent dirs) |
55
- | `editTool` | Edit | Replace a specific string in a file |
56
- | `globTool` | Glob | Find files matching a glob pattern (fast-glob) |
57
- | `grepTool` | Grep | Search file contents with regex patterns |
71
+ | `createShellTool` | Shell | Execute host shell commands; OS-aware (POSIX `sh`/`bash`, Windows PowerShell) |
72
+ | `createBashTool` | Bash | Model-familiar alias of `Shell` — same OS-aware implementation |
73
+ | `createReadTool` | Read | Read file contents with line numbers (cat -n) |
74
+ | `createWriteTool` | Write | Write content to a file (creates parent dirs) |
75
+ | `createEditTool` | Edit | Replace a specific string in a file |
76
+ | `createGlobTool` | Glob | Find files matching a glob pattern (fast-glob) |
77
+ | `createGrepTool` | Grep | Search file contents with regex patterns |
78
+ | `createToolSearchTool` | ToolSearch | Load withheld (deferred) tool schemas by query or exact name; resident so the model can reach it |
58
79
  | `webFetchTool` | WebFetch | Fetch URL content (HTML-to-text conversion) |
59
80
  | `webSearchTool` | WebSearch | Web search via Brave Search API |
60
81
  | `askUserQuestionTool` | AskUserQuestion | Model asks the user structured questions (options/multi-select/free text) |
61
82
 
83
+ The last three stay instances: they touch no filesystem, so there is no root to contain them by.
84
+
62
85
  `AskUserQuestion` lets the model ask the user 1–4 structured questions mid-turn through the injected
63
86
  ask port (CMD-004); each environment renders it its own way (Ink dialog, web modal, programmatic
64
87
  pre-answer), and headless runs get a structured `unavailable` result instead of a hang or a guess.
65
88
 
66
89
  `Shell` and `Bash` are two registered names for one OS-aware implementation: the shell is resolved per-OS and the tool description names the active OS/shell so the model writes the right syntax (e.g. macOS BSD vs Linux GNU utilities differ).
67
90
 
68
- Factory exports (`createBashTool`, `createReadTool`, `createWriteTool`, `createEditTool`) accept an optional `sandboxClient`. The default singleton exports keep host-local behavior.
91
+ The sandbox-aware factories (`createBashTool`, `createReadTool`, `createWriteTool`, `createEditTool`) also accept an optional `sandboxClient`; without one they run against the host filesystem, contained by `cwd`.
69
92
 
70
93
  ## Sandbox Execution
71
94
 
@@ -80,8 +103,11 @@ import { Sandbox } from 'e2b';
80
103
  const e2b = await Sandbox.create();
81
104
  const sandboxClient = new E2BSandboxClient({ sandbox: e2b });
82
105
 
83
- const bashTool = createBashTool({ sandboxClient });
84
- const readTool = createReadTool({ sandboxClient });
106
+ // `cwd` is required even with a sandbox client: it is the root inside the sandbox, and the host
107
+ // path guard still applies to any tool that falls through to the host filesystem.
108
+ const cwd = '/workspace';
109
+ const bashTool = createBashTool({ sandboxClient, cwd });
110
+ const readTool = createReadTool({ sandboxClient, cwd });
85
111
  ```
86
112
 
87
113
  The package does not depend on E2B directly. `E2BSandboxClient` adapts an E2B-compatible object with `commands.run`, `files.read`, `files.write`, and optional `createSnapshot`, `pause`, `connect`, or factory methods supplied by the application. `snapshot()` returns a provider-owned resumable workspace reference; `restore(snapshotId)` hydrates the adapter from that reference. `InMemorySandboxClient` is available for deterministic tests and contract verification.
@@ -122,8 +148,6 @@ Recent file tool updates keep write/edit behavior atomic and make Edit tool resu
122
148
  | `FunctionTool` | JS function tool with Zod schema validation |
123
149
  | `createFunctionTool` | Factory for creating function tools |
124
150
  | `createZodFunctionTool` | Factory with Zod validation and JSON Schema conversion |
125
- | `OpenAPITool` | Tool generated from OpenAPI specification |
126
- | `createOpenAPITool` | Factory for creating OpenAPI tools |
127
151
  | `IToolInvocationResult` | Result type for built-in CLI tool invocations |
128
152
  | `ISandboxClient` | Provider-neutral sandbox execution port |
129
153
  | `IWorkspaceManifest` | Declarative sandbox workspace setup contract |
@@ -1,6 +1,5 @@
1
- import { IEventService, IFunctionTool, IParameterValidationResult, ITool, IToolExecutionContext, IToolRegistry, IToolResult, IToolSchema, TToolExecutor, TToolParameters, TUniversalValue } from "@robota-sdk/agent-core";
1
+ import { FunctionTool, IToolSchema, TToolExecutor, TToolParameters, TUniversalValue } from "@robota-sdk/agent-core";
2
2
  import { TypeOf, ZodType } from "zod";
3
-
4
3
  //#region src/types/tool-result.d.ts
5
4
  /**
6
5
  * Result returned by a CLI tool invocation
@@ -14,111 +13,29 @@ interface IToolInvocationResult {
14
13
  startLine?: number;
15
14
  }
16
15
  //#endregion
17
- //#region src/registry/tool-registry.d.ts
16
+ //#region src/implementations/function-tool.d.ts
18
17
  /**
19
- * Tool registry implementation
20
- * Manages tool registration, validation, and retrieval
18
+ * Helper function to create a function tool from a simple function
21
19
  */
22
- declare class ToolRegistry implements IToolRegistry {
23
- private tools;
24
- /**
25
- * Register a tool
26
- */
27
- register(tool: ITool): void;
28
- /**
29
- * Unregister a tool
30
- */
31
- unregister(name: string): void;
32
- /**
33
- * Get tool by name
34
- */
35
- get(name: string): ITool | undefined;
36
- /**
37
- * Get all registered tools
38
- */
39
- getAll(): ITool[];
40
- /**
41
- * Get tool schemas
42
- */
43
- getSchemas(): IToolSchema[];
44
- /**
45
- * Check if tool exists
46
- */
47
- has(name: string): boolean;
48
- /**
49
- * Clear all tools
50
- */
51
- clear(): void;
52
- /**
53
- * Get tool names
54
- */
55
- getToolNames(): string[];
56
- /**
57
- * Get tools by pattern
58
- */
59
- getToolsByPattern(pattern: string | RegExp): ITool[];
60
- /**
61
- * Get tool count
62
- */
63
- size(): number;
64
- /**
65
- * Validate tool schema
66
- */
67
- private validateToolSchema;
68
- }
69
- //#endregion
70
- //#region src/implementations/function-tool.d.ts
20
+ declare function createFunctionTool(name: string, description: string, parameters: IToolSchema['parameters'], fn: TToolExecutor): FunctionTool;
71
21
  /**
72
- * Function tool implementation
73
- * Wraps a JavaScript function as a tool with schema validation
22
+ * What a tool declares about itself beyond its callable shape (CLI-1990).
74
23
  *
75
- * Implements IFunctionTool without extending AbstractTool to avoid
76
- * circular runtime dependency (tools → agents → tools).
24
+ * Optional, and omission is a declaration too: a tool that says nothing is RESIDENT — its schema is
25
+ * sent on every request, which is what every tool in the tree does today.
77
26
  */
78
- declare class FunctionTool implements IFunctionTool {
79
- readonly schema: IToolSchema;
80
- readonly fn: TToolExecutor;
81
- private eventService;
82
- constructor(schema: IToolSchema, fn: TToolExecutor);
83
- /**
84
- * Get tool name
85
- */
86
- getName(): string;
87
- /**
88
- * Set EventService for post-construction injection.
89
- * Accepts EventService as-is without transformation.
90
- * Caller is responsible for providing properly configured EventService.
91
- */
92
- setEventService(eventService: IEventService | undefined): void;
93
- /**
94
- * Execute the function tool
95
- */
96
- execute(parameters: TToolParameters, context?: IToolExecutionContext): Promise<IToolResult>;
97
- /**
98
- * Validate parameters (simple boolean result)
99
- */
100
- validate(parameters: TToolParameters): boolean;
27
+ interface IFunctionToolResidencyOptions {
101
28
  /**
102
- * Validate tool parameters with detailed result
29
+ * Withhold this tool's schema from the model until it is loaded by `ToolSearch` or forced by a
30
+ * `toolChoice`. Only honoured while the tool-search policy is engaged, so declaring it on a small
31
+ * tool set costs nothing.
103
32
  */
104
- validateParameters(parameters: TToolParameters): IParameterValidationResult;
105
- /**
106
- * Get tool description
107
- */
108
- getDescription(): string;
109
- /**
110
- * Validate constructor inputs
111
- */
112
- private validateConstructorInputs;
33
+ deferLoading?: boolean;
113
34
  }
114
- /**
115
- * Helper function to create a function tool from a simple function
116
- */
117
- declare function createFunctionTool(name: string, description: string, parameters: IToolSchema['parameters'], fn: TToolExecutor): FunctionTool;
118
35
  /**
119
36
  * Helper function to create a function tool from Zod schema
120
37
  */
121
- declare function createZodFunctionTool<S extends ZodType>(name: string, description: string, zodSchema: S, fn: TToolExecutor<TypeOf<S>>): FunctionTool;
38
+ declare function createZodFunctionTool<S extends ZodType>(name: string, description: string, zodSchema: S, fn: TToolExecutor<TypeOf<S>>, residency?: IFunctionToolResidencyOptions): FunctionTool;
122
39
  //#endregion
123
40
  //#region src/implementations/function-tool/types.d.ts
124
41
  /**
@@ -146,5 +63,5 @@ interface IFunctionToolResult {
146
63
  metadata?: IFunctionToolExecutionMetadata;
147
64
  }
148
65
  //#endregion
149
- export { FunctionTool, type IFunctionToolExecutionMetadata, type IFunctionToolResult, type IFunctionToolValidationOptions, type IToolInvocationResult, ToolRegistry, createFunctionTool, createZodFunctionTool };
66
+ export { type IFunctionToolExecutionMetadata, type IFunctionToolResult, type IFunctionToolValidationOptions, type IToolInvocationResult, createFunctionTool, createZodFunctionTool };
150
67
  //# sourceMappingURL=browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","names":[],"sources":["../../src/types/tool-result.ts","../../src/registry/tool-registry.ts","../../src/implementations/function-tool.ts","../../src/implementations/function-tool/types.ts"],"mappings":";;;;;;;UAGiB,qBAAA;EACf,OAAA;EACA,MAAA;EACA,KAAA;EACA,QAAA;EAHA;EAKA,SAAA;AAAA;;;;;AANF;;cCOa,YAAA,YAAwB,aAAA;EAAA,QAC3B,KAAA;EDPR;;;ECYA,QAAA,CAAS,IAAA,EAAM,KAAA;EDPf;;AAAS;ECoCT,UAAA,CAAW,IAAA;;;AAnCb;EAgDE,GAAA,CAAI,IAAA,WAAe,KAAA;;;;EAOnB,MAAA,IAAU,KAAA;EAOI;;;EAAd,UAAA,IAAc,WAAA;EA9DkC;;;EAkFhD,GAAA,CAAI,IAAA;EA5EJ;;;EAmFA,KAAA;EAtDW;;;EA+DX,YAAA;EA3CA;;;EAkDA,iBAAA,CAAkB,OAAA,WAAkB,MAAA,GAAS,KAAA;EAvB7C;;;EA+BA,IAAA;EARA;;;EAAA,QAeQ,kBAAA;AAAA;;;;AD/HV;;;;;;cEuBa,YAAA,YAAwB,aAAA;EAAA,SAC1B,MAAA,EAAQ,WAAA;EAAA,SACR,EAAA,EAAI,aAAA;EAAA,QACL,YAAA;cAEI,MAAA,EAAQ,WAAA,EAAa,EAAA,EAAI,aAAA;;;;EASrC,OAAA;ED9BwB;;;;;ECuCxB,eAAA,CAAgB,YAAA,EAAc,aAAA;EDkEM;;;EC3D9B,OAAA,CACJ,UAAA,EAAY,eAAA,EACZ,OAAA,GAAU,qBAAA,GACT,OAAA,CAAQ,WAAA;EDjDqC;;;ECoGhD,QAAA,CAAS,UAAA,EAAY,eAAA;ED9FN;;;EC4Gf,kBAAA,CAAmB,UAAA,EAAY,eAAA,GAAkB,0BAAA;EDlEjD;;;EC8EA,cAAA;EDvEU;;;EAAA,QC8EF,yBAAA;AAAA;;;;iBAkBM,kBAAA,CACd,IAAA,UACA,WAAA,UACA,UAAA,EAAY,WAAA,gBACZ,EAAA,EAAI,aAAA,GACH,YAAA;;;;iBAaa,qBAAA,WAAgC,OAAA,EAC9C,IAAA,UACA,WAAA,UACA,SAAA,EAAW,CAAA,EACX,EAAA,EAAI,aAAA,CAAc,MAAA,CAAO,CAAA,KACxB,YAAA;;;;;;UChLc,8BAAA;EACf,MAAA;EACA,YAAA;EACA,aAAA;AAAA;;;;UAMe,8BAAA;EACf,aAAA;EACA,QAAA;EACA,UAAA,EAAY,eAAe;AAAA;;AFV7B;;UEgBiB,mBAAA;EACf,OAAA;EACA,IAAA,EAAM,eAAA;EACN,QAAA,GAAW,8BAA8B;AAAA"}
1
+ {"version":3,"file":"browser.d.ts","names":[],"sources":["../../src/types/tool-result.ts","../../src/implementations/function-tool.ts","../../src/implementations/function-tool/types.ts"],"mappings":";;;;;;UAGiB;EACf;EACA;EACA;EACA;;EAEA;;;;;;;iBCKc,mBACd,cACA,qBACA,YAAY,2BACZ,IAAI,gBACH;;;;;;;UAgBc;;;;;;EAMf;;;;;iBAMc,sBAAsB,UAAU,SAC9C,cACA,qBACA,WAAW,GACX,IAAI,cAAc,OAAO,KACzB,YAAW,gCACV;;;;;;UC7Cc;EACf;EACA;EACA;;;;;UAMe;EACf;EACA;EACA,YAAY;;;;;UAMG;EACf;EACA,MAAM;EACN,WAAW"}
@@ -1,2 +1,2 @@
1
- import{ToolExecutionError as e,ValidationError as t,logger as n,zodToJsonSchema as r}from"@robota-sdk/agent-core";var i=class{tools=new Map;register(e){if(!e.schema?.name)throw new t(`Tool must have a valid schema with name`);let r=e.schema.name;this.validateToolSchema(e.schema),this.tools.has(r)&&n.warn(`Tool "${r}" is already registered, overriding`,{toolName:r,existingTool:this.tools.get(r)?.constructor.name}),this.tools.set(r,e),n.debug(`Tool "${r}" registered successfully`,{toolName:r,toolType:e.constructor.name,parameters:Object.keys(e.schema.parameters?.properties||{})})}unregister(e){if(!this.tools.has(e)){n.warn(`Attempted to unregister non-existent tool "${e}"`);return}this.tools.delete(e),n.debug(`Tool "${e}" unregistered successfully`)}get(e){return this.tools.get(e)}getAll(){return Array.from(this.tools.values())}getSchemas(){let e=this.getAll();return n.debug(`[TOOL-FLOW] ToolRegistry.getSchemas() - Tools before schema extraction`,{count:e.length,tools:e.map(e=>({name:e.schema?.name??`unnamed`,hasSchema:!!e.schema,schemaType:typeof e.schema,toolType:e.constructor?.name||`unknown`}))}),this.getAll().map(e=>e.schema)}has(e){return this.tools.has(e)}clear(){let e=this.tools.size;this.tools.clear(),n.debug(`Cleared ${e} tools from registry`)}getToolNames(){return Array.from(this.tools.keys())}getToolsByPattern(e){let t=typeof e==`string`?new RegExp(e):e;return this.getAll().filter(e=>t.test(e.schema.name))}size(){return this.tools.size}validateToolSchema(e){if(!e.name||typeof e.name!=`string`)throw new t(`Tool schema must have a valid name`);if(!e.description||typeof e.description!=`string`)throw new t(`Tool schema must have a description`);if(!e.parameters||typeof e.parameters!=`object`||e.parameters===null||Array.isArray(e.parameters))throw new t(`Tool schema must have parameters object`);if(e.parameters.type!==`object`)throw new t(`Tool parameters type must be "object"`);if(e.parameters.properties)for(let n of Object.keys(e.parameters.properties)){let r=e.parameters.properties[n];if(!r?.type)throw new t(`Parameter "${n}" must have a type`);if(![`string`,`number`,`boolean`,`array`,`object`].includes(r.type))throw new t(`Parameter "${n}" has invalid type "${r.type}"`)}if(e.parameters.required){let n=e.parameters.properties||{};for(let r of e.parameters.required)if(!n[r])throw new t(`Required parameter "${r}" is not defined in properties`)}}};function a(e,t,n){switch(n.type){case`string`:if(typeof t!=`string`)return`Parameter "${e}" must be a string, got ${typeof t}`;break;case`number`:if(typeof t!=`number`||isNaN(t))return`Parameter "${e}" must be a number, got ${typeof t}`;break;case`boolean`:if(typeof t!=`boolean`)return`Parameter "${e}" must be a boolean, got ${typeof t}`;break;case`array`:if(!Array.isArray(t))return`Parameter "${e}" must be an array, got ${typeof t}`;if(n.items)for(let r=0;r<t.length;r++){let i=a(`${e}[${r}]`,t[r],n.items);if(i)return i}break;case`object`:if(typeof t!=`object`||!t||Array.isArray(t))return`Parameter "${e}" must be an object, got ${typeof t}`;break}if(n.enum&&n.enum.length>0){let r=n.enum,i=!1;for(let e of r)if(t===e){i=!0;break}if(!i)return`Parameter "${e}" must be one of: ${r.join(`, `)}, got ${t}`}}function o(e,t,n,r){let i=[];for(let n of t)n in e||i.push(`Missing required parameter: ${n}`);for(let[t,o]of Object.entries(e)){let e=n[t];if(!e){if(r===!0)continue;if(r&&typeof r==`object`){let e=a(t,o,r);e&&i.push(e);continue}i.push(`Unknown parameter: ${t}`);continue}let s=a(t,o,e);s&&i.push(s)}return i}function s(e,t,n,r){let i=o(e,t,n,r);return{isValid:i.length===0,errors:i}}var c=class{schema;fn;eventService;constructor(e,t){this.schema=e,this.fn=t,this.validateConstructorInputs()}getName(){return this.schema.name}setEventService(e){this.eventService=e}async execute(n,r){let i=this.schema.name;if(!this.validate(n))throw new t(`Invalid parameters for tool "${i}": ${o(n,this.schema.parameters.required||[],this.schema.parameters.properties||{},this.schema.parameters.additionalProperties).join(`, `)}`);let a=Date.now(),s;try{s=await this.fn(n,r)}catch(a){throw a instanceof e||a instanceof t?a:new e(`Function tool execution failed: ${a instanceof Error?a.message:String(a)}`,i,a instanceof Error?a:Error(String(a)),{parameterCount:Object.keys(n||{}).length,hasContext:!!r})}let c=Date.now()-a;return{success:!0,data:s,metadata:{executionTime:c,toolName:i,parameters:n}}}validate(e){return o(e,this.schema.parameters.required||[],this.schema.parameters.properties||{},this.schema.parameters.additionalProperties).length===0}validateParameters(e){return s(e,this.schema.parameters.required||[],this.schema.parameters.properties||{},this.schema.parameters.additionalProperties)}getDescription(){return this.schema.description}validateConstructorInputs(){if(!this.schema)throw new t(`Tool schema is required`);if(!this.fn||typeof this.fn!=`function`)throw new t(`Tool function is required and must be a function`);if(!this.schema.name)throw new t(`Tool schema must have a name`)}};function l(e,t,n,r){return new c({name:e,description:t,parameters:n},r)}function u(e,n,i,a){return new c({name:e,description:n,parameters:r(i)},async(e,n)=>{let r=i.safeParse(e);if(!r.success)throw new t(`Zod validation failed: ${r.error}`);let o=await a(r.data,n);return typeof o==`string`?o:JSON.stringify(o)})}export{c as FunctionTool,i as ToolRegistry,l as createFunctionTool,u as createZodFunctionTool};
1
+ import{FunctionTool as e,ValidationError as t,zodToJsonSchema as n}from"@robota-sdk/agent-core";function r(t,n,r,i){return new e({name:t,description:n,parameters:r},i)}function i(r,i,a,o,s={}){return new e({name:r,description:i,parameters:n(a),...s.deferLoading!==void 0&&{deferLoading:s.deferLoading}},async(e,n)=>{let r=a.safeParse(e);if(!r.success)throw new t(`Zod validation failed: ${r.error}`);let i=await o(r.data,n);return typeof i==`string`?i:JSON.stringify(i)})}export{r as createFunctionTool,i as createZodFunctionTool};
2
2
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","names":[],"sources":["../../src/registry/tool-registry.ts","../../src/implementations/function-tool/parameter-validator.ts","../../src/implementations/function-tool.ts"],"sourcesContent":["import { ValidationError } from '@robota-sdk/agent-core';\nimport { logger } from '@robota-sdk/agent-core';\n\nimport type { ITool, IToolRegistry } from '@robota-sdk/agent-core';\nimport type { IToolSchema } from '@robota-sdk/agent-core';\n\n/**\n * Tool registry implementation\n * Manages tool registration, validation, and retrieval\n */\nexport class ToolRegistry implements IToolRegistry {\n private tools = new Map<string, ITool>();\n\n /**\n * Register a tool\n */\n register(tool: ITool): void {\n if (!tool.schema?.name) {\n throw new ValidationError('Tool must have a valid schema with name');\n }\n\n const toolName = tool.schema.name;\n\n // Validate tool schema\n this.validateToolSchema(tool.schema);\n\n // Check for duplicate registration\n if (this.tools.has(toolName)) {\n logger.warn(`Tool \"${toolName}\" is already registered, overriding`, {\n toolName,\n existingTool: this.tools.get(toolName)?.constructor.name,\n });\n }\n\n this.tools.set(toolName, tool);\n logger.debug(`Tool \"${toolName}\" registered successfully`, {\n toolName,\n toolType: tool.constructor.name,\n parameters: Object.keys(tool.schema.parameters?.properties || {}),\n });\n }\n\n /**\n * Unregister a tool\n */\n unregister(name: string): void {\n if (!this.tools.has(name)) {\n logger.warn(`Attempted to unregister non-existent tool \"${name}\"`);\n return;\n }\n\n this.tools.delete(name);\n logger.debug(`Tool \"${name}\" unregistered successfully`);\n }\n\n /**\n * Get tool by name\n */\n get(name: string): ITool | undefined {\n return this.tools.get(name);\n }\n\n /**\n * Get all registered tools\n */\n getAll(): ITool[] {\n return Array.from(this.tools.values());\n }\n\n /**\n * Get tool schemas\n */\n getSchemas(): IToolSchema[] {\n const tools = this.getAll();\n\n // 🔍 [TOOL-FLOW] ToolRegistry.getSchemas() - Extracting schemas from tools\n logger.debug('[TOOL-FLOW] ToolRegistry.getSchemas() - Tools before schema extraction', {\n count: tools.length,\n tools: tools.map((t) => ({\n name: t.schema?.name ?? 'unnamed',\n hasSchema: !!t.schema,\n schemaType: typeof t.schema,\n toolType: t.constructor?.name || 'unknown',\n })),\n });\n\n return this.getAll().map((tool) => tool.schema);\n }\n\n /**\n * Check if tool exists\n */\n has(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Clear all tools\n */\n clear(): void {\n const toolCount = this.tools.size;\n this.tools.clear();\n logger.debug(`Cleared ${toolCount} tools from registry`);\n }\n\n /**\n * Get tool names\n */\n getToolNames(): string[] {\n return Array.from(this.tools.keys());\n }\n\n /**\n * Get tools by pattern\n */\n getToolsByPattern(pattern: string | RegExp): ITool[] {\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n return this.getAll().filter((tool) => regex.test(tool.schema.name));\n }\n\n /**\n * Get tool count\n */\n size(): number {\n return this.tools.size;\n }\n\n /**\n * Validate tool schema\n */\n private validateToolSchema(schema: IToolSchema): void {\n if (!schema.name || typeof schema.name !== 'string') {\n throw new ValidationError('Tool schema must have a valid name');\n }\n\n if (!schema.description || typeof schema.description !== 'string') {\n throw new ValidationError('Tool schema must have a description');\n }\n\n if (\n !schema.parameters ||\n typeof schema.parameters !== 'object' ||\n schema.parameters === null ||\n Array.isArray(schema.parameters)\n ) {\n throw new ValidationError('Tool schema must have parameters object');\n }\n\n if (schema.parameters.type !== 'object') {\n throw new ValidationError('Tool parameters type must be \"object\"');\n }\n\n // Validate parameter properties\n if (schema.parameters.properties) {\n for (const propName of Object.keys(schema.parameters.properties)) {\n const propSchema = schema.parameters.properties[propName];\n if (!propSchema?.type) {\n throw new ValidationError(`Parameter \"${propName}\" must have a type`);\n }\n\n const validTypes = ['string', 'number', 'boolean', 'array', 'object'];\n if (!validTypes.includes(propSchema.type)) {\n throw new ValidationError(\n `Parameter \"${propName}\" has invalid type \"${propSchema.type}\"`,\n );\n }\n }\n }\n\n // Validate required fields exist in properties\n if (schema.parameters.required) {\n const properties = schema.parameters.properties || {};\n for (const requiredField of schema.parameters.required) {\n if (!properties[requiredField]) {\n throw new ValidationError(\n `Required parameter \"${requiredField}\" is not defined in properties`,\n );\n }\n }\n }\n }\n}\n","import type {\n IParameterSchema,\n TToolParameters,\n IParameterValidationResult,\n} from '@robota-sdk/agent-core';\nimport type { TUniversalValue } from '@robota-sdk/agent-core';\n\n/**\n * Validate individual parameter type against its schema.\n * Returns an error string if invalid, undefined if valid.\n */\nexport function validateParameterType(\n key: string,\n value: TUniversalValue,\n schema: IParameterSchema,\n): string | undefined {\n const expectedType = schema['type'];\n\n switch (expectedType) {\n case 'string':\n if (typeof value !== 'string') {\n return `Parameter \"${key}\" must be a string, got ${typeof value}`;\n }\n break;\n\n case 'number':\n if (typeof value !== 'number' || isNaN(value)) {\n return `Parameter \"${key}\" must be a number, got ${typeof value}`;\n }\n break;\n\n case 'boolean':\n if (typeof value !== 'boolean') {\n return `Parameter \"${key}\" must be a boolean, got ${typeof value}`;\n }\n break;\n\n case 'array':\n if (!Array.isArray(value)) {\n return `Parameter \"${key}\" must be an array, got ${typeof value}`;\n }\n // Check array items if specified\n if (schema.items) {\n for (let i = 0; i < value.length; i++) {\n const itemError = validateParameterType(`${key}[${i}]`, value[i], schema.items);\n if (itemError) {\n return itemError;\n }\n }\n }\n break;\n\n case 'object':\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return `Parameter \"${key}\" must be an object, got ${typeof value}`;\n }\n break;\n }\n\n // Check enum constraints\n if (schema.enum && schema.enum.length > 0) {\n const enumValues = schema.enum;\n let isValidEnum = false;\n\n // Type-safe enum checking based on JSONSchemaEnum type\n for (const enumValue of enumValues) {\n if (value === enumValue) {\n isValidEnum = true;\n break;\n }\n }\n\n if (!isValidEnum) {\n return `Parameter \"${key}\" must be one of: ${enumValues.join(', ')}, got ${value}`;\n }\n }\n\n return undefined;\n}\n\n/**\n * Collect all validation errors for the given parameters against a schema.\n */\nexport function getValidationErrors(\n parameters: TToolParameters,\n schemaRequired: string[],\n schemaProperties: Record<string, IParameterSchema>,\n additionalProperties?: boolean | IParameterSchema,\n): string[] {\n const errors: string[] = [];\n\n // Check required parameters\n for (const field of schemaRequired) {\n if (!(field in parameters)) {\n errors.push(`Missing required parameter: ${field}`);\n }\n }\n\n // Check parameter types and constraints\n for (const [key, value] of Object.entries(parameters)) {\n const paramSchema = schemaProperties[key];\n if (!paramSchema) {\n if (additionalProperties === true) {\n continue;\n }\n if (additionalProperties && typeof additionalProperties === 'object') {\n const additionalTypeError = validateParameterType(key, value, additionalProperties);\n if (additionalTypeError) errors.push(additionalTypeError);\n continue;\n }\n errors.push(`Unknown parameter: ${key}`);\n continue;\n }\n\n const typeError = validateParameterType(key, value, paramSchema);\n if (typeError) {\n errors.push(typeError);\n }\n }\n\n return errors;\n}\n\n/**\n * Validate parameters and return a structured result.\n */\nexport function validateToolParameters(\n parameters: TToolParameters,\n schemaRequired: string[],\n schemaProperties: Record<string, IParameterSchema>,\n additionalProperties?: boolean | IParameterSchema,\n): IParameterValidationResult {\n const errors = getValidationErrors(\n parameters,\n schemaRequired,\n schemaProperties,\n additionalProperties,\n );\n return {\n isValid: errors.length === 0,\n errors,\n };\n}\n","import { ToolExecutionError, ValidationError, zodToJsonSchema } from '@robota-sdk/agent-core';\n\nimport { getValidationErrors, validateToolParameters } from './function-tool/parameter-validator';\n\nimport type {\n IFunctionTool,\n IToolResult,\n IToolExecutionContext,\n IParameterValidationResult,\n TToolExecutor,\n TToolParameters,\n IEventService,\n} from '@robota-sdk/agent-core';\nimport type { IToolSchema } from '@robota-sdk/agent-core';\nimport type { TUniversalValue } from '@robota-sdk/agent-core';\nimport type { TypeOf, ZodType } from 'zod';\n\n// Import from Facade pattern modules for type safety\n\n/**\n * Function tool implementation\n * Wraps a JavaScript function as a tool with schema validation\n *\n * Implements IFunctionTool without extending AbstractTool to avoid\n * circular runtime dependency (tools → agents → tools).\n */\nexport class FunctionTool implements IFunctionTool {\n readonly schema: IToolSchema;\n readonly fn: TToolExecutor;\n private eventService: IEventService | undefined;\n\n constructor(schema: IToolSchema, fn: TToolExecutor) {\n this.schema = schema;\n this.fn = fn;\n this.validateConstructorInputs();\n }\n\n /**\n * Get tool name\n */\n getName(): string {\n return this.schema.name;\n }\n\n /**\n * Set EventService for post-construction injection.\n * Accepts EventService as-is without transformation.\n * Caller is responsible for providing properly configured EventService.\n */\n setEventService(eventService: IEventService | undefined): void {\n this.eventService = eventService;\n }\n\n /**\n * Execute the function tool\n */\n async execute(\n parameters: TToolParameters,\n context?: IToolExecutionContext,\n ): Promise<IToolResult> {\n const toolName = this.schema.name;\n\n // Validate parameters before execution\n if (!this.validate(parameters)) {\n const errors = getValidationErrors(\n parameters,\n this.schema.parameters.required || [],\n this.schema.parameters.properties || {},\n this.schema.parameters.additionalProperties,\n );\n throw new ValidationError(`Invalid parameters for tool \"${toolName}\": ${errors.join(', ')}`);\n }\n\n // Execute the function\n const startTime = Date.now();\n let result: TUniversalValue;\n try {\n result = await this.fn(parameters, context);\n } catch (error) {\n if (error instanceof ToolExecutionError || error instanceof ValidationError) {\n throw error;\n }\n\n throw new ToolExecutionError(\n `Function tool execution failed: ${error instanceof Error ? error.message : String(error)}`,\n toolName,\n error instanceof Error ? error : new Error(String(error)),\n {\n parameterCount: Object.keys(parameters || {}).length,\n hasContext: !!context,\n },\n );\n }\n\n const executionTime = Date.now() - startTime;\n\n return {\n success: true,\n data: result,\n metadata: {\n executionTime,\n toolName,\n parameters,\n },\n };\n }\n\n /**\n * Validate parameters (simple boolean result)\n */\n validate(parameters: TToolParameters): boolean {\n return (\n getValidationErrors(\n parameters,\n this.schema.parameters.required || [],\n this.schema.parameters.properties || {},\n this.schema.parameters.additionalProperties,\n ).length === 0\n );\n }\n\n /**\n * Validate tool parameters with detailed result\n */\n validateParameters(parameters: TToolParameters): IParameterValidationResult {\n return validateToolParameters(\n parameters,\n this.schema.parameters.required || [],\n this.schema.parameters.properties || {},\n this.schema.parameters.additionalProperties,\n );\n }\n\n /**\n * Get tool description\n */\n getDescription(): string {\n return this.schema.description;\n }\n\n /**\n * Validate constructor inputs\n */\n private validateConstructorInputs(): void {\n if (!this.schema) {\n throw new ValidationError('Tool schema is required');\n }\n\n if (!this.fn || typeof this.fn !== 'function') {\n throw new ValidationError('Tool function is required and must be a function');\n }\n\n if (!this.schema.name) {\n throw new ValidationError('Tool schema must have a name');\n }\n }\n}\n\n/**\n * Helper function to create a function tool from a simple function\n */\nexport function createFunctionTool(\n name: string,\n description: string,\n parameters: IToolSchema['parameters'],\n fn: TToolExecutor,\n): FunctionTool {\n const schema: IToolSchema = {\n name,\n description,\n parameters,\n };\n\n return new FunctionTool(schema, fn);\n}\n\n/**\n * Helper function to create a function tool from Zod schema\n */\nexport function createZodFunctionTool<S extends ZodType>(\n name: string,\n description: string,\n zodSchema: S,\n fn: TToolExecutor<TypeOf<S>>,\n): FunctionTool {\n // Use comprehensive Zod to JSON schema conversion\n const parameters = zodToJsonSchema(zodSchema);\n\n const schema: IToolSchema = {\n name,\n description,\n parameters,\n };\n\n // Wrap the function with validation and ensure proper parameter handling\n const wrappedFn: TToolExecutor = async (\n parameters: TToolParameters,\n context?: IToolExecutionContext,\n ): Promise<TUniversalValue> => {\n // Use Zod for runtime validation — the executor receives the PARSED, schema-typed value\n // (SDK-009): the runtime guarantee and the compile-time type now flow together.\n const parseResult = zodSchema.safeParse(parameters);\n if (!parseResult.success) {\n throw new ValidationError(`Zod validation failed: ${parseResult.error}`);\n }\n\n const result = await fn(parseResult.data as TypeOf<S>, context);\n // Ensure result is always a string for consistency with core package\n return typeof result === 'string' ? result : JSON.stringify(result);\n };\n\n return new FunctionTool(schema, wrappedFn);\n}\n\n// zodToJsonSchema function moved to Facade pattern schema-converter module\n"],"mappings":"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"}
1
+ {"version":3,"file":"browser.js","names":[],"sources":["../../src/implementations/function-tool.ts"],"sourcesContent":["import { FunctionTool, ValidationError, zodToJsonSchema } from '@robota-sdk/agent-core';\n\nimport type { IToolExecutionContext, TToolExecutor, TToolParameters } from '@robota-sdk/agent-core';\nimport type { IToolSchema } from '@robota-sdk/agent-core';\nimport type { TUniversalValue } from '@robota-sdk/agent-core';\nimport type { TypeOf, ZodType } from 'zod';\n\n// The concrete `FunctionTool` class is owned by @robota-sdk/agent-core (DATA-005 SSOT).\n// These factories construct core's `FunctionTool`; agent-tools owns only the factories\n// and the Zod-flavored wrapper.\n\n/**\n * Helper function to create a function tool from a simple function\n */\nexport function createFunctionTool(\n name: string,\n description: string,\n parameters: IToolSchema['parameters'],\n fn: TToolExecutor,\n): FunctionTool {\n const schema: IToolSchema = {\n name,\n description,\n parameters,\n };\n\n return new FunctionTool(schema, fn);\n}\n\n/**\n * What a tool declares about itself beyond its callable shape (CLI-1990).\n *\n * Optional, and omission is a declaration too: a tool that says nothing is RESIDENT — its schema is\n * sent on every request, which is what every tool in the tree does today.\n */\nexport interface IFunctionToolResidencyOptions {\n /**\n * Withhold this tool's schema from the model until it is loaded by `ToolSearch` or forced by a\n * `toolChoice`. Only honoured while the tool-search policy is engaged, so declaring it on a small\n * tool set costs nothing.\n */\n deferLoading?: boolean;\n}\n\n/**\n * Helper function to create a function tool from Zod schema\n */\nexport function createZodFunctionTool<S extends ZodType>(\n name: string,\n description: string,\n zodSchema: S,\n fn: TToolExecutor<TypeOf<S>>,\n residency: IFunctionToolResidencyOptions = {},\n): FunctionTool {\n // Use comprehensive Zod to JSON schema conversion\n const parameters = zodToJsonSchema(zodSchema);\n\n const schema: IToolSchema = {\n name,\n description,\n parameters,\n // Spread rather than assigned: an absent marker must stay ABSENT, not become `undefined`, so a\n // resident tool's schema is byte-identical to what it was before residency existed.\n ...(residency.deferLoading !== undefined && { deferLoading: residency.deferLoading }),\n };\n\n // Wrap the function with validation and ensure proper parameter handling\n const wrappedFn: TToolExecutor = async (\n parameters: TToolParameters,\n context?: IToolExecutionContext,\n ): Promise<TUniversalValue> => {\n // Use Zod for runtime validation — the executor receives the PARSED, schema-typed value\n // (SDK-009): the runtime guarantee and the compile-time type now flow together.\n const parseResult = zodSchema.safeParse(parameters);\n if (!parseResult.success) {\n throw new ValidationError(`Zod validation failed: ${parseResult.error}`);\n }\n\n const result = await fn(parseResult.data as TypeOf<S>, context);\n // Ensure result is always a string for consistency with core package\n return typeof result === 'string' ? result : JSON.stringify(result);\n };\n\n return new FunctionTool(schema, wrappedFn);\n}\n\n// zodToJsonSchema function moved to Facade pattern schema-converter module\n"],"mappings":"gGAcA,SAAgB,EACd,EACA,EACA,EACA,EACc,CAOd,OAAO,IAAI,EAAa,CALtB,OACA,cACA,YAG2B,EAAG,CAAE,CACpC,CAoBA,SAAgB,EACd,EACA,EACA,EACA,EACA,EAA2C,CAAC,EAC9B,CA8Bd,OAAO,IAAI,EAAa,CAzBtB,OACA,cACA,WALiB,EAAgB,CAKxB,EAGT,GAAI,EAAU,eAAiB,IAAA,IAAa,CAAE,aAAc,EAAU,YAAa,CAoB7D,EAAQ,MAf9B,EACA,IAC6B,CAG7B,IAAM,EAAc,EAAU,UAAU,CAAU,EAClD,GAAI,CAAC,EAAY,QACf,MAAM,IAAI,EAAgB,0BAA0B,EAAY,OAAO,EAGzE,IAAM,EAAS,MAAM,EAAG,EAAY,KAAmB,CAAO,EAE9D,OAAO,OAAO,GAAW,SAAW,EAAS,KAAK,UAAU,CAAM,CACpE,CAEyC,CAC3C"}