@open1s/ezbos 1.0.0
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/.github/workflows/ci.yml +34 -0
- package/.github/workflows/publish.yml +33 -0
- package/.pnp.cjs +8400 -0
- package/.pnp.loader.mjs +2126 -0
- package/.yarn/install-state.gz +0 -0
- package/README.md +468 -0
- package/bun.lock +89 -0
- package/examples/00-pr.ts +1 -0
- package/examples/01-tools.ts +85 -0
- package/examples/02-hooks.ts +82 -0
- package/examples/03-plugins.ts +91 -0
- package/examples/04-mcp.ts +74 -0
- package/examples/05-skills.ts +45 -0
- package/examples/06-session.ts +72 -0
- package/examples/07-agent-advanced.ts +86 -0
- package/examples/08-brainos-messaging.ts +83 -0
- package/package.json +46 -0
- package/skills/code-review/SKILL.md +18 -0
- package/src/agent.ts +404 -0
- package/src/brainos.ts +357 -0
- package/src/hook.ts +73 -0
- package/src/index.ts +17 -0
- package/src/mcp.ts +40 -0
- package/src/plugin.ts +93 -0
- package/src/skills.ts +31 -0
- package/src/tool.ts +110 -0
- package/src/types.ts +30 -0
- package/tsconfig.json +21 -0
|
Binary file
|
package/README.md
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
# @open1s/ezbos
|
|
2
|
+
|
|
3
|
+
Simple BrainOS - Easy wrapper for [@open1s/jsbos](https://www.npmjs.com/package/@open1s/jsbos). Build AI agents with tools, hooks, plugins, MCP, skills, and messaging.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @open1s/ezbos
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { BrainOS, tool } from '@open1s/ezbos';
|
|
15
|
+
|
|
16
|
+
const brain = new BrainOS();
|
|
17
|
+
await brain.start();
|
|
18
|
+
|
|
19
|
+
const addTool = tool('Add', 'Add two numbers', (args) => String(args.a + args.b));
|
|
20
|
+
|
|
21
|
+
const agent = brain.agent('assistant')
|
|
22
|
+
.with_tools(addTool)
|
|
23
|
+
.with_systemPrompt('You are a helpful assistant.');
|
|
24
|
+
|
|
25
|
+
const started = await agent.start();
|
|
26
|
+
const result = await started.ask('What is 5 + 3?');
|
|
27
|
+
console.log(result);
|
|
28
|
+
|
|
29
|
+
await started.close();
|
|
30
|
+
await brain.stop();
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration
|
|
34
|
+
|
|
35
|
+
Place a `brainos.json` in your project root:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"global_model": {
|
|
40
|
+
"model": "nvidia/meta/llama-3.1-8b-instruct",
|
|
41
|
+
"base_url": "https://integrate.api.nvidia.com/v1",
|
|
42
|
+
"api_key": "your-key"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
BrainOS auto-discovers this config on `start()`. You can also pass options directly:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
const brain = new BrainOS({
|
|
51
|
+
model: 'nvidia/meta/llama-3.1-8b-instruct',
|
|
52
|
+
baseUrl: 'https://integrate.api.nvidia.com/v1',
|
|
53
|
+
apiKey: 'nvapi-xxx',
|
|
54
|
+
});
|
|
55
|
+
await brain.start();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Agent Builder
|
|
59
|
+
|
|
60
|
+
Fluent builder for creating agents:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const agent = brain.agent('name')
|
|
64
|
+
.with_systemPrompt('You are helpful.')
|
|
65
|
+
.with_model('nvidia/meta/llama-3.1-8b-instruct')
|
|
66
|
+
.with_baseUrl('https://integrate.api.nvidia.com/v1')
|
|
67
|
+
.with_apiKey('your-key')
|
|
68
|
+
.with_temperature(0.7)
|
|
69
|
+
.with_timeout(120)
|
|
70
|
+
.with_maxTokens(4096)
|
|
71
|
+
.with_tools(tool1, tool2)
|
|
72
|
+
.with_hooks(hook1, hook2)
|
|
73
|
+
.with_plugins(plugin1)
|
|
74
|
+
.with_mcp_process('fs', 'npx', ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'])
|
|
75
|
+
.with_mcp_http('math', 'http://127.0.0.1:8000/mcp')
|
|
76
|
+
.with_skills_dir('./skills')
|
|
77
|
+
.with_skills({ name: 'Code Review', content: '...' })
|
|
78
|
+
.with_resilience({ circuitBreakerMaxFailures: 3, rateLimitCapacity: 5 });
|
|
79
|
+
|
|
80
|
+
const started = await agent.start();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Resilience
|
|
84
|
+
|
|
85
|
+
Configure circuit breaker and rate limiting:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
agent.with_resilience({
|
|
89
|
+
circuitBreakerMaxFailures: 3, // trip after 3 failures
|
|
90
|
+
circuitBreakerCooldownSecs: 10, // wait 10s before retry
|
|
91
|
+
rateLimitCapacity: 5, // allow 5 requests
|
|
92
|
+
rateLimitWindowSecs: 60, // per 60 seconds
|
|
93
|
+
rateLimitMaxRetries: 3, // retry 3 times when limited
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Tools
|
|
98
|
+
|
|
99
|
+
Define tools the LLM can call.
|
|
100
|
+
|
|
101
|
+
### Simple Tool
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { tool } from '@open1s/ezbos';
|
|
105
|
+
|
|
106
|
+
const add = tool('Add', 'Add two numbers', (args) => String(args.a + args.b));
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Tool Builder
|
|
110
|
+
|
|
111
|
+
For tools with schema and optional parameters:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { defineTool, ok, err } from '@open1s/ezbos';
|
|
115
|
+
|
|
116
|
+
const greet = defineTool('Greet', 'Greet someone')
|
|
117
|
+
.required('name', 'string', 'Name to greet')
|
|
118
|
+
.param('language', 'string', 'Language code', 'en')
|
|
119
|
+
.handle((args) => `Hello, ${args.name}!`);
|
|
120
|
+
|
|
121
|
+
const divide = defineTool('Divide', 'Divide two numbers')
|
|
122
|
+
.required('n', 'number', 'Numerator')
|
|
123
|
+
.required('d', 'number', 'Denominator')
|
|
124
|
+
.handle((args) => {
|
|
125
|
+
if (args.d === 0) return err('Division by zero');
|
|
126
|
+
return ok(args.n / args.d);
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Result Helpers
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const success = ok({ value: 42 }, { cached: true });
|
|
134
|
+
const failure = err('Not found', { code: 404 });
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Note:** Tool callbacks must be synchronous. The underlying jsbos native layer does not support async tool callbacks.
|
|
138
|
+
|
|
139
|
+
## Hooks
|
|
140
|
+
|
|
141
|
+
Intercept agent lifecycle events.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { HookEvent, defineHook } from '@open1s/ezbos';
|
|
145
|
+
|
|
146
|
+
const logHook = defineHook(HookEvent.BeforeToolCall, (ctx) => {
|
|
147
|
+
console.log('About to call:', ctx.data?.tool_name);
|
|
148
|
+
return 'continue'; // or 'abort'
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
agent.with_hooks(logHook);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Available events:
|
|
155
|
+
|
|
156
|
+
| Event | Description |
|
|
157
|
+
|-------|-------------|
|
|
158
|
+
| `BeforeToolCall` | Before a tool is invoked |
|
|
159
|
+
| `AfterToolCall` | After a tool returns |
|
|
160
|
+
| `BeforeLlmCall` | Before sending to LLM |
|
|
161
|
+
| `AfterLlmCall` | After receiving from LLM |
|
|
162
|
+
| `OnMessage` | On each message |
|
|
163
|
+
| `OnComplete` | When task completes |
|
|
164
|
+
| `OnError` | On error |
|
|
165
|
+
|
|
166
|
+
### Merge Hooks
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { mergeHooks } from '@open1s/ezbos';
|
|
170
|
+
|
|
171
|
+
const allHooks = mergeHooks(beforeHook, afterHook, beforeLlmHook);
|
|
172
|
+
agent.with_hooks(allHooks);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Plugins
|
|
176
|
+
|
|
177
|
+
Register plugins for LLM/tool lifecycle events.
|
|
178
|
+
|
|
179
|
+
### Plain Plugin
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { definePlugin } from '@open1s/ezbos';
|
|
183
|
+
|
|
184
|
+
const loggerPlugin = definePlugin({
|
|
185
|
+
name: 'logger',
|
|
186
|
+
on_llm_request: (req) => { console.log('LLM request:', req.model); return req; },
|
|
187
|
+
on_llm_response: (resp) => { console.log('LLM response'); return resp; },
|
|
188
|
+
on_tool_call: (call) => { console.log('Tool call:', call.name); return call; },
|
|
189
|
+
on_tool_result: (result) => { console.log('Tool result'); return result; },
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
agent.with_plugins(loggerPlugin);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Class-based Plugin
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { getPluginHandlers } from '@open1s/ezbos';
|
|
199
|
+
|
|
200
|
+
class MyPlugin {
|
|
201
|
+
__pluginName = 'my-plugin';
|
|
202
|
+
|
|
203
|
+
on_llm_request(req: any) { return req; }
|
|
204
|
+
on_llm_response(resp: any) { return resp; }
|
|
205
|
+
on_tool_call(call: any) { return call; }
|
|
206
|
+
on_tool_result(result: any) { return result; }
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const plugin = new MyPlugin();
|
|
210
|
+
const handlers = getPluginHandlers(plugin);
|
|
211
|
+
agent.with_plugins(plugin);
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Merge Plugins
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { mergePlugins } from '@open1s/ezbos';
|
|
218
|
+
|
|
219
|
+
const merged = mergePlugins(pluginA, pluginB);
|
|
220
|
+
agent.with_plugins(merged);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## MCP
|
|
224
|
+
|
|
225
|
+
Connect to MCP (Model Context Protocol) servers.
|
|
226
|
+
|
|
227
|
+
### Process-based
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import { defineMcpProcess } from '@open1s/ezbos';
|
|
231
|
+
|
|
232
|
+
const config = defineMcpProcess('files', 'npx', [
|
|
233
|
+
'-y', '@modelcontextprotocol/server-filesystem', '/tmp'
|
|
234
|
+
]);
|
|
235
|
+
|
|
236
|
+
agent.with_mcp_process('files', 'npx', [
|
|
237
|
+
'-y', '@modelcontextprotocol/server-filesystem', '/tmp'
|
|
238
|
+
]);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### HTTP-based
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
import { defineMcpHttp } from '@open1s/ezbos';
|
|
245
|
+
|
|
246
|
+
const config = defineMcpHttp('hello-mcp', 'http://127.0.0.1:8000/mcp');
|
|
247
|
+
|
|
248
|
+
agent.with_mcp_http('hello-mcp', 'http://127.0.0.1:8000/mcp');
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### MCP Builder
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
import { McpBuilder } from '@open1s/ezbos';
|
|
255
|
+
|
|
256
|
+
const configs = new McpBuilder()
|
|
257
|
+
.process('files', 'npx', ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'])
|
|
258
|
+
.http('hello-mcp', 'http://127.0.0.1:8000/mcp')
|
|
259
|
+
.build();
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### List MCP Tools
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
const mcpTools = await started.listMcpTools();
|
|
266
|
+
console.log(`MCP tools available: ${mcpTools.length}`);
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Skills
|
|
270
|
+
|
|
271
|
+
Add domain-specific instructions to the system prompt.
|
|
272
|
+
|
|
273
|
+
### Define Skill
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
import { defineSkill } from '@open1s/ezbos';
|
|
277
|
+
|
|
278
|
+
const skill = defineSkill('math-expert', 'You are a math expert. Always show your work step by step.');
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Directory-based
|
|
282
|
+
|
|
283
|
+
Auto-discovers `SKILL.md` files in a directory:
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
agent.with_skills_dir('./skills');
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Directory structure:
|
|
290
|
+
```
|
|
291
|
+
skills/
|
|
292
|
+
code-review/
|
|
293
|
+
SKILL.md
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Skills Builder
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
import { SkillsBuilder } from '@open1s/ezbos';
|
|
300
|
+
|
|
301
|
+
const built = new SkillsBuilder()
|
|
302
|
+
.from_dir('./skills')
|
|
303
|
+
.add('code-review', 'You are a code reviewer. Be thorough.')
|
|
304
|
+
.add('api-design', 'You are an API designer. Follow REST best practices.')
|
|
305
|
+
.build();
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Agent (Started)
|
|
309
|
+
|
|
310
|
+
The running agent instance.
|
|
311
|
+
|
|
312
|
+
### LLM Calls
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
// ReAct loop (tools + reasoning)
|
|
316
|
+
const result = await started.ask('What is 5 + 3?');
|
|
317
|
+
|
|
318
|
+
// ReAct with explicit task
|
|
319
|
+
const result2 = await started.react('Calculate the sum');
|
|
320
|
+
|
|
321
|
+
// Simple LLM call (no tools)
|
|
322
|
+
const result3 = await started.runSimple('Say hello');
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Streaming
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
// Stream tokens
|
|
329
|
+
await started.stream('Task', (token) => {
|
|
330
|
+
if (token.type === 'Text') process.stdout.write(token.text);
|
|
331
|
+
if (token.type === 'ReasoningContent') process.stdout.write(token.text);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Collect all tokens
|
|
335
|
+
const tokens = await started.streamCollect('Task');
|
|
336
|
+
const text = tokens.filter(t => t.text).map(t => t.text).join('');
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Session Management
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
// AI-powered compaction (replaces old messages with LLM summary)
|
|
343
|
+
await started.compactSession();
|
|
344
|
+
|
|
345
|
+
// Save/restore
|
|
346
|
+
started.saveSession('./session.json');
|
|
347
|
+
started.restoreSession('./session.json');
|
|
348
|
+
|
|
349
|
+
// Clear
|
|
350
|
+
started.clearSession();
|
|
351
|
+
|
|
352
|
+
// Export/import as JSON
|
|
353
|
+
const json = started.exportSession();
|
|
354
|
+
started.importSession(json);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Metrics
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
const metrics = started.metrics;
|
|
361
|
+
console.log(metrics.llmCallCount);
|
|
362
|
+
console.log(metrics.toolInvocationCount);
|
|
363
|
+
console.log(metrics.totalWallTimeUs);
|
|
364
|
+
|
|
365
|
+
started.resetMetrics();
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Info
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
console.log(started.tools); // ['Add', 'Greet']
|
|
372
|
+
console.log(started.config); // { model, baseUrl, temperature, ... }
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Messaging
|
|
376
|
+
|
|
377
|
+
Pub/sub, query, and RPC patterns via the message bus.
|
|
378
|
+
|
|
379
|
+
### Publisher / Subscriber
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
// Publisher
|
|
383
|
+
const pub = await brain.publisher('events');
|
|
384
|
+
await pub.text('Hello');
|
|
385
|
+
await pub.json({ event: 'click', x: 100 });
|
|
386
|
+
|
|
387
|
+
// Subscriber - recv with timeout
|
|
388
|
+
const sub = await brain.subscriber('events');
|
|
389
|
+
const msg = await sub.recv(3000);
|
|
390
|
+
|
|
391
|
+
// Subscriber - continuous processing
|
|
392
|
+
const sub2 = await brain.subscriber('events');
|
|
393
|
+
await sub2.run((msg) => console.log('Received:', msg));
|
|
394
|
+
await sub2.stop();
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Query / Queryable (request-response)
|
|
398
|
+
|
|
399
|
+
```ts
|
|
400
|
+
// Server
|
|
401
|
+
const server = await brain.queryable('math', (input) => {
|
|
402
|
+
const n = parseInt(input);
|
|
403
|
+
return String(n * n);
|
|
404
|
+
});
|
|
405
|
+
await server.start();
|
|
406
|
+
|
|
407
|
+
// Client
|
|
408
|
+
const client = await brain.query('math');
|
|
409
|
+
const response = await client.ask('21', 5000); // "441"
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Caller / Callable (RPC)
|
|
413
|
+
|
|
414
|
+
```ts
|
|
415
|
+
// Server
|
|
416
|
+
const rpcServer = await brain.callable('add', (input) => {
|
|
417
|
+
const [a, b] = input.split(',').map(Number);
|
|
418
|
+
return String(a + b);
|
|
419
|
+
});
|
|
420
|
+
await rpcServer.start();
|
|
421
|
+
|
|
422
|
+
// Client
|
|
423
|
+
const rpcClient = await brain.caller('add');
|
|
424
|
+
const result = await rpcClient.call('10,20'); // "30"
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Quick Agent
|
|
428
|
+
|
|
429
|
+
One-liner to create and start an agent:
|
|
430
|
+
|
|
431
|
+
```ts
|
|
432
|
+
import { BrainOS } from '@open1s/ezbos';
|
|
433
|
+
|
|
434
|
+
const agent = await BrainOS.with('assistant', {
|
|
435
|
+
model: 'nvidia/meta/llama-3.1-8b-instruct',
|
|
436
|
+
apiKey: 'nvapi-xxx',
|
|
437
|
+
});
|
|
438
|
+
const result = await agent.ask('Hello');
|
|
439
|
+
await agent.close();
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
## Examples
|
|
443
|
+
|
|
444
|
+
| Example | Description |
|
|
445
|
+
|---------|-------------|
|
|
446
|
+
| `01-tools.ts` | Tool definitions (required/optional params), ok/err results, isErrorResult, error handling |
|
|
447
|
+
| `02-hooks.ts` | All 7 hook events, defineHook, mergeHooks, hook registry |
|
|
448
|
+
| `03-plugins.ts` | Plain plugins, class-based plugins, getPluginHandlers, mergePlugins |
|
|
449
|
+
| `04-mcp.ts` | Process-based MCP, HTTP MCP, McpBuilder, listMcpTools |
|
|
450
|
+
| `05-skills.ts` | defineSkill, SkillsBuilder, skill directories |
|
|
451
|
+
| `06-session.ts` | Multi-turn conversation, compactSession, save/restore, export/import |
|
|
452
|
+
| `07-agent-advanced.ts` | Streaming, streamCollect, metrics, resilience, config |
|
|
453
|
+
| `08-brainos-messaging.ts` | Query/Queryable, Caller/Callable, Publisher/Subscriber (recv + run) |
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
npm run example:tools
|
|
457
|
+
npm run example:hooks
|
|
458
|
+
npm run example:plugins
|
|
459
|
+
npm run example:mcp
|
|
460
|
+
npm run example:skills
|
|
461
|
+
npm run example:session
|
|
462
|
+
npm run example:agent
|
|
463
|
+
npm run example:messaging
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## License
|
|
467
|
+
|
|
468
|
+
MIT
|
package/bun.lock
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 0,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "@open1s/ezbos",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@open1s/jsbos": "^2.1.4",
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"tsx": "^4.22.0",
|
|
12
|
+
"typescript": "^6.0.3",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
"packages": {
|
|
17
|
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA=="],
|
|
18
|
+
|
|
19
|
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.28.0", "", { "os": "android", "cpu": "arm" }, "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ=="],
|
|
20
|
+
|
|
21
|
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.0", "", { "os": "android", "cpu": "arm64" }, "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw=="],
|
|
22
|
+
|
|
23
|
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.28.0", "", { "os": "android", "cpu": "x64" }, "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA=="],
|
|
24
|
+
|
|
25
|
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q=="],
|
|
26
|
+
|
|
27
|
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ=="],
|
|
28
|
+
|
|
29
|
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q=="],
|
|
30
|
+
|
|
31
|
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw=="],
|
|
32
|
+
|
|
33
|
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw=="],
|
|
34
|
+
|
|
35
|
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A=="],
|
|
36
|
+
|
|
37
|
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ=="],
|
|
38
|
+
|
|
39
|
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg=="],
|
|
40
|
+
|
|
41
|
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w=="],
|
|
42
|
+
|
|
43
|
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg=="],
|
|
44
|
+
|
|
45
|
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ=="],
|
|
46
|
+
|
|
47
|
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q=="],
|
|
48
|
+
|
|
49
|
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.0", "", { "os": "linux", "cpu": "x64" }, "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ=="],
|
|
50
|
+
|
|
51
|
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw=="],
|
|
52
|
+
|
|
53
|
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.0", "", { "os": "none", "cpu": "x64" }, "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw=="],
|
|
54
|
+
|
|
55
|
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g=="],
|
|
56
|
+
|
|
57
|
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA=="],
|
|
58
|
+
|
|
59
|
+
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w=="],
|
|
60
|
+
|
|
61
|
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw=="],
|
|
62
|
+
|
|
63
|
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA=="],
|
|
64
|
+
|
|
65
|
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA=="],
|
|
66
|
+
|
|
67
|
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.0", "", { "os": "win32", "cpu": "x64" }, "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw=="],
|
|
68
|
+
|
|
69
|
+
"@open1s/jsbos": ["@open1s/jsbos@2.1.4", "", { "optionalDependencies": { "@open1s/jsbos-darwin-arm64": "2.1.4", "@open1s/jsbos-linux-arm64-gnu": "2.1.4", "@open1s/jsbos-linux-x64-gnu": "2.1.4", "@open1s/jsbos-win32-arm64-msvc": "2.1.4", "@open1s/jsbos-win32-x64-msvc": "2.1.4" } }, "sha512-G8FCJFJsELMWtBSyqiDyO1BqFMi45wxdS8RVKUc6+B+imjhht2ZBn7L2O46AErhlZOAKoU/yEeVOKu17Ni5RKQ=="],
|
|
70
|
+
|
|
71
|
+
"@open1s/jsbos-darwin-arm64": ["@open1s/jsbos-darwin-arm64@2.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b6N2J37Rdg2i4+pFQLhmPpXSiPu842eYqY8ZfV/hWdwTIiehg9qG/1kcMETK9icmHc4Md9xQzXtN1Ytb3Q0l6g=="],
|
|
72
|
+
|
|
73
|
+
"@open1s/jsbos-linux-arm64-gnu": ["@open1s/jsbos-linux-arm64-gnu@2.1.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-3BrurLQGxHBkfL51T3EFOqmnFIml7cNFm5f5xX1nBqBLJ+u2TyRMMemeGNlPVI4vl0CQDKy3SIQaEsL1pRzvwQ=="],
|
|
74
|
+
|
|
75
|
+
"@open1s/jsbos-linux-x64-gnu": ["@open1s/jsbos-linux-x64-gnu@2.1.4", "", { "os": "linux", "cpu": "x64" }, "sha512-XfLzVZG4fHyyIbX1sV5uADHRIsXLtzNiEKMuJG1oz6ZWA3k4WOZKWhrFw/M3D4ZuyrovQdA4FdfmPI5za9Epcw=="],
|
|
76
|
+
|
|
77
|
+
"@open1s/jsbos-win32-arm64-msvc": ["@open1s/jsbos-win32-arm64-msvc@2.1.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-pelaitUjyLYCtaXkSFvD5N0v6GX7fOs+B8vZ60/WwraTcksrD4ZU9twEwdgRiep/qY1lydIQIv/72ReX5dCDSA=="],
|
|
78
|
+
|
|
79
|
+
"@open1s/jsbos-win32-x64-msvc": ["@open1s/jsbos-win32-x64-msvc@2.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-tCOtC0pjF9IWwF3WcmBIIdufQTA4pZlnB9OStDBT4jOR++ukTffXLg3i52H77rz5HayJSJBE2Onrmxy2ZXBj6Q=="],
|
|
80
|
+
|
|
81
|
+
"esbuild": ["esbuild@0.28.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.0", "@esbuild/android-arm": "0.28.0", "@esbuild/android-arm64": "0.28.0", "@esbuild/android-x64": "0.28.0", "@esbuild/darwin-arm64": "0.28.0", "@esbuild/darwin-x64": "0.28.0", "@esbuild/freebsd-arm64": "0.28.0", "@esbuild/freebsd-x64": "0.28.0", "@esbuild/linux-arm": "0.28.0", "@esbuild/linux-arm64": "0.28.0", "@esbuild/linux-ia32": "0.28.0", "@esbuild/linux-loong64": "0.28.0", "@esbuild/linux-mips64el": "0.28.0", "@esbuild/linux-ppc64": "0.28.0", "@esbuild/linux-riscv64": "0.28.0", "@esbuild/linux-s390x": "0.28.0", "@esbuild/linux-x64": "0.28.0", "@esbuild/netbsd-arm64": "0.28.0", "@esbuild/netbsd-x64": "0.28.0", "@esbuild/openbsd-arm64": "0.28.0", "@esbuild/openbsd-x64": "0.28.0", "@esbuild/openharmony-arm64": "0.28.0", "@esbuild/sunos-x64": "0.28.0", "@esbuild/win32-arm64": "0.28.0", "@esbuild/win32-ia32": "0.28.0", "@esbuild/win32-x64": "0.28.0" }, "bin": "bin/esbuild" }, "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw=="],
|
|
82
|
+
|
|
83
|
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
84
|
+
|
|
85
|
+
"tsx": ["tsx@4.22.0", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": "dist/cli.mjs" }, "sha512-8ccZMPD69s1AbKXx0C5ddTNZfNjwV04iIKgjZmKfKxMynEtSYcK0Lh7iQFh53fI5Yu4pb9usgAiqyPmEONaALg=="],
|
|
86
|
+
|
|
87
|
+
"typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('This is a placeholder file for the 00-pr.ts example. Please refer to the other example files for actual code demonstrations of BrainOS features.');
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { BrainOS, defineTool, tool, ok, err, isErrorResult, version } from '../src/index.js';
|
|
2
|
+
|
|
3
|
+
import {initTracing} from "@open1s/jsbos";
|
|
4
|
+
|
|
5
|
+
// initTracing();
|
|
6
|
+
|
|
7
|
+
const addTool = defineTool('Add', 'Add two numbers')
|
|
8
|
+
.required('a', 'number', 'First number')
|
|
9
|
+
.required('b', 'number', 'Second number')
|
|
10
|
+
.handle((args: any) => { console.error('Adding numbers:', args.a, args.b); return args.a + args.b; });
|
|
11
|
+
|
|
12
|
+
const multiplyTool = defineTool('Multiply', 'Multiply two numbers')
|
|
13
|
+
.required('x', 'number', 'First number')
|
|
14
|
+
.required('y', 'number', 'Second number')
|
|
15
|
+
.handle((args: any) => { console.error('Multiplying numbers:', args.x, args.y); return args.x * args.y; });
|
|
16
|
+
|
|
17
|
+
const stringConcatTool = defineTool('Concat', 'Concatenate two strings')
|
|
18
|
+
.param('str1', 'string', 'First string')
|
|
19
|
+
.param('str2', 'string', 'Second string')
|
|
20
|
+
.param('separator', 'string', 'Separator', ', ')
|
|
21
|
+
.handle((args: any) => { console.error('Concatenating strings:', args.str1, args.str2, args.separator); return args.str1 + args.separator + args.str2; });
|
|
22
|
+
|
|
23
|
+
const divideTool = defineTool('Divide', 'Divide two numbers')
|
|
24
|
+
.required('n', 'number', 'Numerator')
|
|
25
|
+
.required('d', 'number', 'Denominator')
|
|
26
|
+
.handle((args: any) => {
|
|
27
|
+
console.error('Dividing numbers:', args.n, args.d);
|
|
28
|
+
if (args.d === 0) return err('Division by zero');
|
|
29
|
+
return ok(args.n / args.d);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const asyncWeatherTool = defineTool('Weather', 'Get weather for a city')
|
|
33
|
+
.required('city', 'string', 'City name')
|
|
34
|
+
.handle((args: any) => {
|
|
35
|
+
console.error('Fetching weather for city:', args.city);
|
|
36
|
+
return ok({ city: args.city, temp: 22, condition: 'sunny', unit: 'celsius' });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const errorTool = tool('Fail', 'Always returns an error', () => {
|
|
40
|
+
throw new Error('Intentional failure from errorTool');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
async function main() {
|
|
44
|
+
console.log(`\n=== 01-tools.ts - Tool API Demo (v${version()}) ===\n`);
|
|
45
|
+
|
|
46
|
+
const brain = new BrainOS();
|
|
47
|
+
await brain.start();
|
|
48
|
+
|
|
49
|
+
const agent = brain.agent('tools-demo')
|
|
50
|
+
.with_tools(addTool, multiplyTool, stringConcatTool, divideTool, asyncWeatherTool, errorTool);
|
|
51
|
+
|
|
52
|
+
const started = await agent.start();
|
|
53
|
+
|
|
54
|
+
const tests = [
|
|
55
|
+
{ q: 'What is 15 + 27?', expect: 42 },
|
|
56
|
+
{ q: 'What is 8 times 6?', expect: 48 },
|
|
57
|
+
{ q: 'Concatenate "Brain" and "OS" with separator "-"', expect: 'Brain-OS' },
|
|
58
|
+
{ q: 'Divide 100 by 4', expect: 25 },
|
|
59
|
+
{ q: 'Divide 10 by 0', expect: 'error' },
|
|
60
|
+
{ q: 'What is the weather in Tokyo?', expect: 'ok' },
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
for (const t of tests) {
|
|
64
|
+
console.log(`\nQ: ${t.q}`);
|
|
65
|
+
console.log(` Expected: ${t.expect}`);
|
|
66
|
+
const result = await started.ask(t.q);
|
|
67
|
+
console.log(` A: ${result}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log('\n--- Tool definitions ---');
|
|
71
|
+
console.log('addTool schema:', JSON.stringify((addTool as any).schema, null, 2));
|
|
72
|
+
|
|
73
|
+
console.log('\n--- isErrorResult demo ---');
|
|
74
|
+
const okResult = ok(42);
|
|
75
|
+
const errResult = err('bad');
|
|
76
|
+
console.log('ok(42):', okResult, 'isErrorResult:', isErrorResult(okResult));
|
|
77
|
+
console.log('err("bad"):', errResult, 'isErrorResult:', isErrorResult(errResult));
|
|
78
|
+
|
|
79
|
+
await started.close();
|
|
80
|
+
await brain.stop();
|
|
81
|
+
console.log('\nDone.');
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|