@olane/o-tool 0.6.13 → 0.7.2

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.
Files changed (55) hide show
  1. package/README.md +382 -1
  2. package/dist/src/index.d.ts +2 -5
  3. package/dist/src/index.d.ts.map +1 -1
  4. package/dist/src/index.js +2 -5
  5. package/dist/src/interfaces/tool.interface.d.ts +2 -2
  6. package/dist/src/interfaces/tool.interface.d.ts.map +1 -1
  7. package/dist/src/o-tool.base.d.ts +36 -0
  8. package/dist/src/o-tool.base.d.ts.map +1 -0
  9. package/dist/src/o-tool.base.js +207 -0
  10. package/dist/src/o-tool.d.ts +2 -2
  11. package/dist/src/o-tool.d.ts.map +1 -1
  12. package/dist/src/o-tool.js +59 -269
  13. package/dist/src/router/index.d.ts +3 -0
  14. package/dist/src/router/index.d.ts.map +1 -0
  15. package/dist/src/router/index.js +2 -0
  16. package/dist/src/router/o-request.router.d.ts +15 -0
  17. package/dist/src/router/o-request.router.d.ts.map +1 -0
  18. package/dist/src/router/o-request.router.js +10 -0
  19. package/dist/src/router/o-tool.router.d.ts +6 -0
  20. package/dist/src/router/o-tool.router.d.ts.map +1 -0
  21. package/dist/src/router/o-tool.router.js +49 -0
  22. package/dist/src/router/resolvers/method.resolver.d.ts +8 -0
  23. package/dist/src/router/resolvers/method.resolver.d.ts.map +1 -0
  24. package/dist/src/router/resolvers/method.resolver.js +46 -0
  25. package/dist/src/utils/method.utils.d.ts +7 -0
  26. package/dist/src/utils/method.utils.d.ts.map +1 -0
  27. package/dist/src/utils/method.utils.js +26 -0
  28. package/dist/src/utils/tool.utils.d.ts.map +1 -0
  29. package/dist/test/method.spec.d.ts +0 -1
  30. package/dist/test/method.spec.js +29 -28
  31. package/package.json +4 -4
  32. package/dist/src/client.tool.d.ts +0 -10
  33. package/dist/src/client.tool.d.ts.map +0 -1
  34. package/dist/src/client.tool.js +0 -7
  35. package/dist/src/nodes/client.node.d.ts +0 -6
  36. package/dist/src/nodes/client.node.d.ts.map +0 -1
  37. package/dist/src/nodes/client.node.js +0 -16
  38. package/dist/src/nodes/index.d.ts +0 -4
  39. package/dist/src/nodes/index.d.ts.map +0 -1
  40. package/dist/src/nodes/index.js +0 -3
  41. package/dist/src/nodes/server.node.d.ts +0 -6
  42. package/dist/src/nodes/server.node.d.ts.map +0 -1
  43. package/dist/src/nodes/server.node.js +0 -20
  44. package/dist/src/nodes/websocket.node.d.ts +0 -6
  45. package/dist/src/nodes/websocket.node.d.ts.map +0 -1
  46. package/dist/src/nodes/websocket.node.js +0 -18
  47. package/dist/src/server.tool.d.ts +0 -10
  48. package/dist/src/server.tool.d.ts.map +0 -1
  49. package/dist/src/server.tool.js +0 -7
  50. package/dist/src/tool.utils.d.ts.map +0 -1
  51. package/dist/src/virtual.tool.d.ts +0 -10
  52. package/dist/src/virtual.tool.d.ts.map +0 -1
  53. package/dist/src/virtual.tool.js +0 -7
  54. /package/dist/src/{tool.utils.d.ts → utils/tool.utils.d.ts} +0 -0
  55. /package/dist/src/{tool.utils.js → utils/tool.utils.js} +0 -0
package/README.md CHANGED
@@ -1 +1,382 @@
1
- # o-tool
1
+ # @olane/o-tool
2
+
3
+ > Tool augmentation system for Olane OS - build specialized tool nodes (applications) that AI agents use
4
+
5
+ The tool system layer of Olane OS. Transform generalist LLMs into specialists through tool augmentation and context injection - create discoverable, validated capabilities without fine-tuning models.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@olane/o-tool.svg)](https://www.npmjs.com/package/@olane/o-tool)
8
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
9
+
10
+ ## Features
11
+
12
+ - 🔧 **Convention-Based Tool Registration** - Automatic discovery via `_tool_` prefix
13
+ - ✅ **Built-in Parameter Validation** - Type-safe parameter checking with clear error messages
14
+ - 🔍 **Automatic Discovery** - Tools indexed in vector store for semantic search by agents
15
+ - 🏗️ **Mixin Architecture** - Compose tool capabilities with any `oCore` class
16
+ - 🌲 **Hierarchical Organization** - Inherit context and capabilities from parent tools
17
+ - 📡 **Streaming Support** - Handle long-running operations with progress updates
18
+ - 🎯 **Built-in Tools** - Handshake, routing, indexing, and lifecycle management included
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @olane/o-tool
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### Creating a Simple Tool
29
+
30
+ ```typescript
31
+ import { oToolBase, oRequest, ToolResult } from '@olane/o-tool';
32
+ import { oAddress } from '@olane/o-core';
33
+
34
+ class CalculatorTool extends oToolBase {
35
+ constructor() {
36
+ super({
37
+ address: new oAddress('o://calculator'),
38
+ description: 'Performs mathematical calculations',
39
+ methods: {
40
+ add: {
41
+ description: 'Add two numbers',
42
+ parameters: {
43
+ a: { type: 'number', required: true },
44
+ b: { type: 'number', required: true }
45
+ }
46
+ }
47
+ }
48
+ });
49
+ }
50
+
51
+ // Tool methods use _tool_ prefix for automatic registration
52
+ async _tool_add(request: oRequest): Promise<ToolResult> {
53
+ const { a, b } = request.params;
54
+ return { result: a + b };
55
+ }
56
+ }
57
+
58
+ // Start the tool
59
+ const calculator = new CalculatorTool();
60
+ await calculator.start();
61
+
62
+ // Use the tool
63
+ const response = await calculator.use({
64
+ method: 'add',
65
+ params: { a: 5, b: 3 }
66
+ });
67
+
68
+ console.log(response.result); // { result: 8 }
69
+ ```
70
+
71
+ ### Using the Mixin Pattern
72
+
73
+ Extend any `oCore` class with tool capabilities:
74
+
75
+ ```typescript
76
+ import { oTool } from '@olane/o-tool';
77
+ import { oNode } from '@olane/o-node';
78
+
79
+ class MyNetworkTool extends oTool(oNode) {
80
+ constructor(config) {
81
+ super(config);
82
+ }
83
+
84
+ async _tool_process(request: oRequest): Promise<ToolResult> {
85
+ // Your custom logic here
86
+ return { status: 'processed' };
87
+ }
88
+ }
89
+ ```
90
+
91
+ ## Core Concepts
92
+
93
+ ### Tool Convention Pattern
94
+
95
+ Tools are automatically discovered using naming conventions:
96
+
97
+ - **`_tool_methodName`** - Defines an executable tool method
98
+ - **`_params_methodName`** - Defines parameter schema (optional)
99
+
100
+ ```typescript
101
+ class WeatherTool extends oToolBase {
102
+ // Executable tool method
103
+ async _tool_get_forecast(request: oRequest): Promise<ToolResult> {
104
+ const { city } = request.params;
105
+ return { forecast: '☀️ Sunny, 72°F' };
106
+ }
107
+
108
+ // Parameter schema (optional)
109
+ _params_get_forecast() {
110
+ return {
111
+ city: { type: 'string', required: true, description: 'City name' }
112
+ };
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### Built-in Tools
118
+
119
+ Every tool automatically includes these methods:
120
+
121
+ | Method | Description |
122
+ |--------|-------------|
123
+ | `handshake` | Capability negotiation between agents |
124
+ | `route` | Route requests through the hierarchy |
125
+ | `index_network` | Index tool in vector store for discovery |
126
+ | `hello_world` | Connectivity test |
127
+ | `stop` | Graceful shutdown |
128
+ | `child_register` | Register child tools in hierarchy |
129
+
130
+ ### Automatic Validation
131
+
132
+ Parameter validation happens automatically before tool execution:
133
+
134
+ ```typescript
135
+ // Missing required parameters trigger clear errors
136
+ try {
137
+ await tool.use({ method: 'add', params: { a: 5 } });
138
+ } catch (error) {
139
+ // Error: Missing required parameters: ["b"]
140
+ console.log(error.message);
141
+ }
142
+ ```
143
+
144
+ ## Examples
145
+
146
+ ### Search Tool with Vector Store Integration
147
+
148
+ ```typescript
149
+ import { oLaneTool } from '@olane/o-lane';
150
+ import { oAddress, oRequest } from '@olane/o-core';
151
+
152
+ class SearchTool extends oLaneTool {
153
+ constructor(config) {
154
+ super({
155
+ ...config,
156
+ address: new oAddress('o://search'),
157
+ description: 'Search for information in the network'
158
+ });
159
+ }
160
+
161
+ async _tool_vector(request: oRequest): Promise<ToolResult> {
162
+ const { query } = request.params;
163
+
164
+ const response = await this.use(new oAddress('o://vector-store'), {
165
+ method: 'search_similar',
166
+ params: { query, limit: 10 }
167
+ });
168
+
169
+ return response.result.data;
170
+ }
171
+ }
172
+ ```
173
+
174
+ ### Tool with Streaming Support
175
+
176
+ ```typescript
177
+ class DataProcessorTool extends oToolBase {
178
+ async _tool_process_large_file(request: oRequest & { stream?: Stream }): Promise<ToolResult> {
179
+ const { filePath } = request.params;
180
+ const { stream } = request;
181
+
182
+ // Send progress updates
183
+ for (let i = 0; i < 100; i += 10) {
184
+ if (stream) {
185
+ await CoreUtils.sendResponse(
186
+ { progress: i, status: 'processing' },
187
+ stream
188
+ );
189
+ }
190
+ }
191
+
192
+ return { status: 'complete', processed: true };
193
+ }
194
+ }
195
+ ```
196
+
197
+ ### Hierarchical Tool Organization
198
+
199
+ ```typescript
200
+ // Parent tool
201
+ const parentTool = new CalculatorTool();
202
+ await parentTool.start();
203
+
204
+ // Child tool inherits context from parent
205
+ class AdvancedCalculatorTool extends oToolBase {
206
+ async initialize() {
207
+ await super.initialize();
208
+
209
+ // Register with parent
210
+ await this.use(new oAddress('o://calculator'), {
211
+ method: 'child_register',
212
+ params: { address: this.address.toString() }
213
+ });
214
+ }
215
+
216
+ async _tool_complex_calculation(request: oRequest): Promise<ToolResult> {
217
+ // Can leverage parent tool capabilities
218
+ const result = await this.use(new oAddress('o://calculator'), {
219
+ method: 'add',
220
+ params: { a: 10, b: 20 }
221
+ });
222
+
223
+ return { result: result.result * 2 };
224
+ }
225
+ }
226
+ ```
227
+
228
+ ## API Reference
229
+
230
+ ### `oToolBase`
231
+
232
+ Base class for creating tools.
233
+
234
+ **Key Methods:**
235
+ - `execute(request: oRequest, stream?: Stream): Promise<RunResult>` - Execute tool with request
236
+ - `run(request: oRequest, stream?: Stream): Promise<RunResult>` - Run with validation
237
+ - `myTools(): Promise<string[]>` - Get list of available tool methods
238
+ - `callMyTool(request: oRequest, stream?: Stream): Promise<ToolResult>` - Call specific tool method
239
+ - `index(): Promise<{summary: string}>` - Index tool in vector store
240
+ - `whoami(): Promise<object>` - Get tool metadata
241
+
242
+ ### `oTool(Base)`
243
+
244
+ Mixin function that adds tool capabilities to any `oCore` class.
245
+
246
+ ```typescript
247
+ function oTool<T extends new (...args: any[]) => oToolBase>(Base: T): T
248
+ ```
249
+
250
+ **Usage:**
251
+ ```typescript
252
+ class CustomTool extends oTool(MyBaseClass) {
253
+ // Tool methods...
254
+ }
255
+ ```
256
+
257
+ ### Interfaces
258
+
259
+ #### `oToolConfig`
260
+ ```typescript
261
+ interface oToolConfig extends Omit<oCoreConfig, 'address'> {
262
+ description?: string;
263
+ methods?: Record<string, MethodMetadata>;
264
+ }
265
+ ```
266
+
267
+ #### `ToolResult`
268
+ ```typescript
269
+ interface ToolResult {
270
+ [key: string]: unknown;
271
+ }
272
+ ```
273
+
274
+ #### `RunResult`
275
+ ```typescript
276
+ interface RunResult extends ToolResult {
277
+ error?: oError;
278
+ }
279
+ ```
280
+
281
+ ### Utilities
282
+
283
+ #### `MethodUtils.findMissingParams(tool, method, params)`
284
+
285
+ Validates parameters against tool method requirements.
286
+
287
+ ```typescript
288
+ const missing = MethodUtils.findMissingParams(tool, 'add', { a: 5 });
289
+ // Returns: ['b']
290
+ ```
291
+
292
+ ## Tool Discovery & Indexing
293
+
294
+ Tools automatically integrate with Olane's vector store for semantic discovery:
295
+
296
+ ```typescript
297
+ // Index your tool for agent discovery
298
+ await tool.use({ method: 'index_network' });
299
+
300
+ // Agents can now discover your tool semantically
301
+ const results = await this.use(new oAddress('o://vector-store'), {
302
+ method: 'search_similar',
303
+ params: { query: 'calculate numbers' }
304
+ });
305
+ // Returns: o://calculator with tool descriptions
306
+ ```
307
+
308
+ ## Error Handling
309
+
310
+ Tools use structured error handling with `oError`:
311
+
312
+ ```typescript
313
+ import { oError, oErrorCodes } from '@olane/o-core';
314
+
315
+ async _tool_divide(request: oRequest): Promise<ToolResult> {
316
+ const { a, b } = request.params;
317
+
318
+ if (b === 0) {
319
+ throw new oError(
320
+ oErrorCodes.INVALID_PARAMETERS,
321
+ 'Cannot divide by zero',
322
+ { a, b }
323
+ );
324
+ }
325
+
326
+ return { result: a / b };
327
+ }
328
+ ```
329
+
330
+ ## Testing
331
+
332
+ ```typescript
333
+ import { oRequest } from '@olane/o-core';
334
+
335
+ describe('CalculatorTool', () => {
336
+ let tool: CalculatorTool;
337
+
338
+ beforeEach(async () => {
339
+ tool = new CalculatorTool();
340
+ await tool.start();
341
+ });
342
+
343
+ it('should add two numbers', async () => {
344
+ const request = new oRequest({
345
+ method: 'add',
346
+ params: { a: 5, b: 3 },
347
+ id: '123'
348
+ });
349
+
350
+ const result = await tool.callMyTool(request);
351
+ expect(result.result).toBe(8);
352
+ });
353
+
354
+ afterEach(async () => {
355
+ await tool.stop();
356
+ });
357
+ });
358
+ ```
359
+
360
+ ## Related Packages
361
+
362
+ - **[@olane/o-core](../o-core)** - Core OS functionality and base classes
363
+ - **[@olane/o-node](../o-node)** - Network-connected tools with P2P capabilities
364
+ - **[@olane/o-protocol](../o-protocol)** - Protocol definitions and types
365
+ - **[@olane/o-lane](../o-lane)** - Lane-based tool organization
366
+ - **[@olane/o-tools-common](../o-tools-common)** - Pre-built common tools
367
+
368
+ ## Contributing
369
+
370
+ Contributions are welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md) for details on our code of conduct and development process.
371
+
372
+ ## License
373
+
374
+ ISC © oLane Inc.
375
+
376
+ ## Resources
377
+
378
+ - [Full Documentation](../../docs)
379
+ - [Olane OS Overview](../../README.md)
380
+ - [Examples](../../examples)
381
+ - [GitHub Repository](https://github.com/olane-labs/olane)
382
+ - [Report Issues](https://github.com/olane-labs/olane/issues)
@@ -4,9 +4,6 @@ export * from './interfaces/run-result.interface.js';
4
4
  export * from './interfaces/run-params.interface.js';
5
5
  export * from './interfaces/run-tool.interface.js';
6
6
  export * from './interfaces/tool-result.interface.js';
7
- export * from './tool.utils.js';
8
- export * from './virtual.tool.js';
9
- export * from './nodes/index.js';
10
- export * from './server.tool.js';
11
- export * from './client.tool.js';
7
+ export * from './router/index.js';
8
+ export * from './o-tool.base.js';
12
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC"}
package/dist/src/index.js CHANGED
@@ -4,8 +4,5 @@ export * from './interfaces/run-result.interface.js';
4
4
  export * from './interfaces/run-params.interface.js';
5
5
  export * from './interfaces/run-tool.interface.js';
6
6
  export * from './interfaces/tool-result.interface.js';
7
- export * from './tool.utils.js';
8
- export * from './virtual.tool.js';
9
- export * from './nodes/index.js';
10
- export * from './server.tool.js';
11
- export * from './client.tool.js';
7
+ export * from './router/index.js';
8
+ export * from './o-tool.base.js';
@@ -1,4 +1,4 @@
1
- import { CoreConfig } from '@olane/o-core';
2
- export interface oToolConfig extends Omit<CoreConfig, 'address'> {
1
+ import { oCoreConfig } from '@olane/o-core';
2
+ export interface oToolConfig extends Omit<oCoreConfig, 'address'> {
3
3
  }
4
4
  //# sourceMappingURL=tool.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool.interface.d.ts","sourceRoot":"","sources":["../../../src/interfaces/tool.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC;CAAG"}
1
+ {"version":3,"file":"tool.interface.d.ts","sourceRoot":"","sources":["../../../src/interfaces/tool.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;CAAG"}
@@ -0,0 +1,36 @@
1
+ import { oAddress, oConnection, oCore, oRequest } from '@olane/o-core';
2
+ import { Stream } from '@olane/o-config';
3
+ import { RunResult } from './interfaces/run-result.interface.js';
4
+ import { ToolResult } from './interfaces/tool-result.interface.js';
5
+ /**
6
+ * oTool is a mixin that extends the base class and implements the oTool interface
7
+ * @param Base - The base class to extend
8
+ * @returns A new class that extends the base class and implements the oTool interface
9
+ */
10
+ export declare class oToolBase extends oCore {
11
+ private indexed;
12
+ validateToolCall(oRequest: oRequest): boolean;
13
+ configureTransports(): any[];
14
+ connect(nextHopAddress: oAddress, targetAddress: oAddress): Promise<oConnection>;
15
+ initializeRouter(): Promise<void>;
16
+ unregister(): Promise<void>;
17
+ register(): Promise<void>;
18
+ execute(req: oRequest, stream?: Stream): Promise<RunResult>;
19
+ run(request: oRequest, stream?: Stream): Promise<RunResult>;
20
+ myTools(obj?: any): Promise<string[]>;
21
+ findMethod(method: string): Promise<string | undefined>;
22
+ myToolParams(tool: string): Record<string, any>;
23
+ callMyTool(request: oRequest, stream?: Stream): Promise<ToolResult>;
24
+ index(): Promise<{
25
+ provider: string;
26
+ summary: string;
27
+ } | {
28
+ summary: string | null;
29
+ provider?: undefined;
30
+ }>;
31
+ whoami(): Promise<{
32
+ tools: string[];
33
+ description: string;
34
+ }>;
35
+ }
36
+ //# sourceMappingURL=o-tool.base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"o-tool.base.d.ts","sourceRoot":"","sources":["../../src/o-tool.base.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,KAAK,EAGL,QAAQ,EAET,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAInE;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,OAAO,CAAC,OAAO,CAAkB;IAEjC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO;IAY7C,mBAAmB,IAAI,GAAG,EAAE;IAI5B,OAAO,CACL,cAAc,EAAE,QAAQ,EACxB,aAAa,EAAE,QAAQ,GACtB,OAAO,CAAC,WAAW,CAAC;IAGvB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAG3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAInB,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA8B3D,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA2BjE,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS/B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAI7D,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAWzC,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBnE,KAAK;;;;;;;IA4FL,MAAM;;;;CAQb"}
@@ -0,0 +1,207 @@
1
+ import { oAddress, oCore, oError, oErrorCodes, oRequest, } from '@olane/o-core';
2
+ import { oProtocolMethods } from '@olane/o-protocol';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ import { MethodUtils } from './utils/method.utils.js';
5
+ /**
6
+ * oTool is a mixin that extends the base class and implements the oTool interface
7
+ * @param Base - The base class to extend
8
+ * @returns A new class that extends the base class and implements the oTool interface
9
+ */
10
+ export class oToolBase extends oCore {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.indexed = false;
14
+ }
15
+ validateToolCall(oRequest) {
16
+ const method = oRequest.method;
17
+ if (!method) {
18
+ throw new Error('method parameter is required');
19
+ }
20
+ // @ts-ignore
21
+ if (!this[`_tool_${method}`]) {
22
+ throw new Error(`Tool ${method} is not implemented`);
23
+ }
24
+ return true;
25
+ }
26
+ configureTransports() {
27
+ return [];
28
+ }
29
+ connect(nextHopAddress, targetAddress) {
30
+ throw new oError(oErrorCodes.NOT_IMPLEMENTED, 'Connect not implemented');
31
+ }
32
+ initializeRouter() {
33
+ throw new oError(oErrorCodes.NOT_IMPLEMENTED, 'Initialize router not implemented');
34
+ }
35
+ unregister() {
36
+ throw new oError(oErrorCodes.NOT_IMPLEMENTED, 'Unregister not implemented');
37
+ }
38
+ register() {
39
+ throw new oError(oErrorCodes.NOT_IMPLEMENTED, 'Register not implemented');
40
+ }
41
+ async execute(req, stream) {
42
+ let request = req;
43
+ const requestConfig = req.toJSON();
44
+ // validate and run the tool
45
+ this.validateToolCall(request);
46
+ // check if it's a route and we have reached the destination
47
+ if (request.method === oProtocolMethods.ROUTE &&
48
+ request.params.address === this.address.value) {
49
+ const { payload } = request.params;
50
+ request = new oRequest({
51
+ id: requestConfig.id,
52
+ method: payload.method,
53
+ params: {
54
+ _connectionId: requestConfig.params?._connectionId,
55
+ _requestMethod: payload.method,
56
+ ...(payload.params || {}), // TODO: is this correct? this line used to be ...payload
57
+ },
58
+ });
59
+ }
60
+ const result = await this.run(request, stream);
61
+ return result;
62
+ }
63
+ async run(request, stream) {
64
+ const missingParams = MethodUtils.findMissingParams(this, request.method, request.params || {});
65
+ if (missingParams.length > 0) {
66
+ this.logger.error('Missing required parameters: ', missingParams, ' with passed params: ', request.params);
67
+ throw new oError(oErrorCodes.MISSING_PARAMETERS, 'Missing required parameters', {
68
+ parameters: missingParams,
69
+ toolAddress: this.address.toString(),
70
+ data: request.params,
71
+ });
72
+ }
73
+ let result = await this.callMyTool(request, stream);
74
+ return result;
75
+ }
76
+ myTools(obj) {
77
+ return Promise.resolve(Object.getOwnPropertyNames(obj || this.constructor.prototype)
78
+ .filter((key) => key.startsWith('_tool_'))
79
+ .filter((key) => !!key)
80
+ .map((key) => key.replace('_tool_', '')));
81
+ }
82
+ async findMethod(method) {
83
+ return (await this.myTools()).find((key) => key.startsWith(method));
84
+ }
85
+ myToolParams(tool) {
86
+ const func = Object.keys(this).find((key) => key.startsWith('_params_' + tool));
87
+ if (!func) {
88
+ throw new Error(`Tool ${tool} not found`);
89
+ }
90
+ // @ts-ignore
91
+ return this[func]();
92
+ }
93
+ async callMyTool(request, stream) {
94
+ const method = request.method;
95
+ this.logger.debug('Calling tool: ' + method, 'Origin caller address: ', request?.params?._callerAddress);
96
+ // TODO: implement this
97
+ // this.requests[request.id] = request;
98
+ // @ts-ignore
99
+ const result = await this[`_tool_${method}`]({
100
+ ...request.toJSON(),
101
+ stream,
102
+ }).catch((error) => {
103
+ // delete this.requests[request.id];
104
+ throw error;
105
+ });
106
+ // delete this.requests[request.id];
107
+ return result;
108
+ }
109
+ async index() {
110
+ if (this.indexed) {
111
+ this.logger.debug('Tool already indexed, skipping...');
112
+ return {
113
+ summary: 'Tool already indexed',
114
+ };
115
+ }
116
+ this.indexed = true;
117
+ // perform index
118
+ const metadata = await this.whoami();
119
+ if (!metadata.tools.length && !metadata.description) {
120
+ this.logger.warn('No metadata found, skipping...');
121
+ return {
122
+ provider: 'Empty node',
123
+ summary: 'Empty node',
124
+ };
125
+ }
126
+ for (const method in this.methods) {
127
+ const m = this.methods[method];
128
+ await this.use(new oAddress('o://vector-store'), {
129
+ method: 'add_documents',
130
+ params: {
131
+ documents: [
132
+ {
133
+ pageContent: m.description,
134
+ metadata: {
135
+ address: this.address?.toString() + '/' + method,
136
+ id: uuidv4(),
137
+ },
138
+ },
139
+ ],
140
+ },
141
+ });
142
+ }
143
+ let summary = metadata.description ? metadata.description : null;
144
+ if (!summary) {
145
+ this.logger.debug('No description found, generating summary...');
146
+ const response = await this.use(new oAddress('o://intelligence'), {
147
+ method: 'prompt',
148
+ params: {
149
+ prompt: `You are a helpful assistant that summarizes what a service does by looking at the service description and the details of the tools that the service contains. \n
150
+ Format the output in JSON using this template:` +
151
+ JSON.stringify({
152
+ summary: 'string',
153
+ }) +
154
+ 'Do NOT include any other text other than the JSON response. The following is the JSON input of the service: ' +
155
+ JSON.stringify(metadata),
156
+ },
157
+ });
158
+ const { result } = response;
159
+ const { success } = result;
160
+ if (!success) {
161
+ this.logger.error('Failed to index network: ', result);
162
+ throw new Error('Failed to index network');
163
+ }
164
+ const data = result.data;
165
+ const { message } = data;
166
+ const json = JSON.parse(message);
167
+ summary = json.summary;
168
+ // update the description to avoid re-indexing
169
+ if (summary) {
170
+ this.config.description = summary;
171
+ }
172
+ }
173
+ try {
174
+ if (summary) {
175
+ await this.use(new oAddress('o://vector-store'), {
176
+ method: 'add_documents',
177
+ params: {
178
+ documents: [
179
+ {
180
+ pageContent: summary,
181
+ metadata: {
182
+ address: this.address?.toString(),
183
+ id: uuidv4(),
184
+ },
185
+ },
186
+ ],
187
+ },
188
+ });
189
+ }
190
+ return {
191
+ summary: summary,
192
+ };
193
+ }
194
+ catch (e) {
195
+ this.logger.error('Error indexing network: ', e);
196
+ throw e;
197
+ }
198
+ }
199
+ async whoami() {
200
+ const metadata = await super.whoami();
201
+ return {
202
+ // @ts-ignore
203
+ tools: await this.myTools(),
204
+ description: this.description,
205
+ };
206
+ }
207
+ }
@@ -1,8 +1,8 @@
1
- import { oCoreNode } from '@olane/o-core';
1
+ import { oToolBase } from './o-tool.base.js';
2
2
  /**
3
3
  * oTool is a mixin that extends the base class and implements the oTool interface
4
4
  * @param Base - The base class to extend
5
5
  * @returns A new class that extends the base class and implements the oTool interface
6
6
  */
7
- export declare function oTool<T extends new (...args: any[]) => oCoreNode>(Base: T): T;
7
+ export declare function oTool<T extends new (...args: any[]) => oToolBase>(Base: T): T;
8
8
  //# sourceMappingURL=o-tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"o-tool.d.ts","sourceRoot":"","sources":["../../src/o-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,EAKV,MAAM,eAAe,CAAC;AASvB;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAsW7E"}
1
+ {"version":3,"file":"o-tool.d.ts","sourceRoot":"","sources":["../../src/o-tool.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CA0G7E"}