@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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BrainOS, defineHook, hook, mergeHooks, createHookRegistry, HookEvent, version } from '../src/index.js';
|
|
2
|
+
|
|
3
|
+
const beforeHook = defineHook(HookEvent.BeforeToolCall, (ctx: any) => {
|
|
4
|
+
console.log(` [BeforeToolCall] ${ctx.data?.tool_name}`);
|
|
5
|
+
return 'continue';
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const afterHook = defineHook(HookEvent.AfterToolCall, (ctx: any) => {
|
|
9
|
+
console.log(` [AfterToolCall] completed`);
|
|
10
|
+
return 'continue';
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const beforeLlmHook = defineHook(HookEvent.BeforeLlmCall, (ctx: any) => {
|
|
14
|
+
console.log(` [BeforeLlmCall]`);
|
|
15
|
+
return 'continue';
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const afterLlmHook = defineHook(HookEvent.AfterLlmCall, (ctx: any) => {
|
|
19
|
+
console.log(` [AfterLlmCall]`);
|
|
20
|
+
return 'continue';
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const onMessageHook = defineHook(HookEvent.OnMessage, (ctx: any) => {
|
|
24
|
+
console.log(` [OnMessage] ${ctx.data?.message?.substring(0, 50)}`);
|
|
25
|
+
return 'continue';
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const onCompleteHook = defineHook(HookEvent.OnComplete, (ctx: any) => {
|
|
29
|
+
console.log(` [OnComplete]`);
|
|
30
|
+
return 'continue';
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const onErrorHook = defineHook(HookEvent.OnError, (ctx: any) => {
|
|
34
|
+
console.log(` [OnError] ${ctx.data?.error}`);
|
|
35
|
+
return 'continue';
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
async function main() {
|
|
39
|
+
console.log(`\n=== 02-hooks.ts - Hook API Demo (v${version()}) ===\n`);
|
|
40
|
+
|
|
41
|
+
const brain = new BrainOS();
|
|
42
|
+
await brain.start();
|
|
43
|
+
|
|
44
|
+
const addTool = { name: 'Add', description: 'Add', schema: { properties: { a: {}, b: {} } }, callback: () => '42' };
|
|
45
|
+
|
|
46
|
+
console.log('--- All HookEvent values ---');
|
|
47
|
+
console.log('HookEvent.BeforeToolCall:', HookEvent.BeforeToolCall);
|
|
48
|
+
console.log('HookEvent.AfterToolCall:', HookEvent.AfterToolCall);
|
|
49
|
+
console.log('HookEvent.BeforeLlmCall:', HookEvent.BeforeLlmCall);
|
|
50
|
+
console.log('HookEvent.AfterLlmCall:', HookEvent.AfterLlmCall);
|
|
51
|
+
console.log('HookEvent.OnMessage:', HookEvent.OnMessage);
|
|
52
|
+
console.log('HookEvent.OnComplete:', HookEvent.OnComplete);
|
|
53
|
+
console.log('HookEvent.OnError:', HookEvent.OnError);
|
|
54
|
+
|
|
55
|
+
console.log('\n--- mergeHooks ---');
|
|
56
|
+
const allHooks = mergeHooks(
|
|
57
|
+
beforeHook, afterHook, beforeLlmHook, afterLlmHook,
|
|
58
|
+
onMessageHook, onCompleteHook, onErrorHook
|
|
59
|
+
);
|
|
60
|
+
console.log(`Merged ${allHooks.length} hooks`);
|
|
61
|
+
|
|
62
|
+
console.log('\n--- defineHook returns ---');
|
|
63
|
+
console.log('beforeHook:', beforeHook);
|
|
64
|
+
console.log('afterHook:', afterHook);
|
|
65
|
+
|
|
66
|
+
const agent = brain.agent('hooks-demo')
|
|
67
|
+
.with_tools(addTool)
|
|
68
|
+
.with_hooks(beforeHook, afterHook, beforeLlmHook, afterLlmHook);
|
|
69
|
+
|
|
70
|
+
const started = await agent.start();
|
|
71
|
+
|
|
72
|
+
console.log('\n--- Running agent with hooks ---');
|
|
73
|
+
const result = await started.ask('What is 10 + 20? Use the Add tool.');
|
|
74
|
+
console.log(`Result: ${result}`);
|
|
75
|
+
|
|
76
|
+
await started.close();
|
|
77
|
+
await brain.stop();
|
|
78
|
+
console.log('\nDone.');
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { BrainOS, definePlugin, plugin, on_llm_request, on_llm_response, on_tool_call, on_tool_result, mergePlugins, getPluginHandlers, version } from '../src/index.js';
|
|
2
|
+
|
|
3
|
+
const plainPlugin = definePlugin({
|
|
4
|
+
name: 'plain-plugin',
|
|
5
|
+
on_llm_request(req: any) { console.log(' [Plain Plugin] LLM request:', req.model); return req; },
|
|
6
|
+
on_llm_response(resp: any) { console.log(' [Plain Plugin] LLM response'); return resp; },
|
|
7
|
+
on_tool_call(call: any) { console.log(' [Plain Plugin] Tool call:', call.name); return call; },
|
|
8
|
+
on_tool_result(result: any) { console.log(' [Plain Plugin] Tool result:', String(result).slice(0, 30)); return result; },
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const pluginA = definePlugin({
|
|
12
|
+
name: 'plugin-a',
|
|
13
|
+
on_llm_request(req: any) { console.log(' [Plugin A] LLM request'); return req; },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const pluginB = definePlugin({
|
|
17
|
+
name: 'plugin-b',
|
|
18
|
+
on_tool_result(result: any) { console.log(' [Plugin B] Tool result:', String(result).slice(0, 30)); return result; },
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
class DecoratedPlugin {
|
|
22
|
+
__pluginName = 'decorated-plugin';
|
|
23
|
+
|
|
24
|
+
on_llm_request(req: any) {
|
|
25
|
+
console.log(' [Decorated] LLM request');
|
|
26
|
+
return req;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
on_llm_response(resp: any) {
|
|
30
|
+
console.log(' [Decorated] LLM response');
|
|
31
|
+
return resp;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
on_tool_call(call: any) {
|
|
35
|
+
console.log(' [Decorated] Tool call:', call.name);
|
|
36
|
+
return call;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
on_tool_result(result: any) {
|
|
40
|
+
console.log(' [Decorated] Tool result');
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function main() {
|
|
46
|
+
console.log(`\n=== 03-plugins.ts - Plugin API Demo (v${version()}) ===\n`);
|
|
47
|
+
|
|
48
|
+
const brain = new BrainOS();
|
|
49
|
+
await brain.start();
|
|
50
|
+
|
|
51
|
+
const addTool = { name: 'Add', description: 'Add', schema: { properties: { a: {}, b: {} } }, callback: () => '42' };
|
|
52
|
+
|
|
53
|
+
console.log('--- definePlugin ---');
|
|
54
|
+
console.log('plainPlugin name:', plainPlugin.name);
|
|
55
|
+
console.log('pluginA name:', pluginA.name);
|
|
56
|
+
console.log('pluginB name:', pluginB.name);
|
|
57
|
+
|
|
58
|
+
console.log('\n--- mergePlugins ---');
|
|
59
|
+
const merged = mergePlugins(pluginA, pluginB, plainPlugin);
|
|
60
|
+
console.log(`Merged ${merged.length} plugins:`, merged.map(p => p.name));
|
|
61
|
+
|
|
62
|
+
console.log('\n--- getPluginHandlers from class instance ---');
|
|
63
|
+
const decorated = new DecoratedPlugin();
|
|
64
|
+
const handlers = getPluginHandlers(decorated);
|
|
65
|
+
console.log('DecoratedPlugin handlers extracted:', handlers);
|
|
66
|
+
|
|
67
|
+
console.log('\n--- Agent with merged plugins ---');
|
|
68
|
+
const agent = brain.agent('plugins-demo')
|
|
69
|
+
.with_tools(addTool)
|
|
70
|
+
.with_plugins(plainPlugin);
|
|
71
|
+
|
|
72
|
+
const started = await agent.start();
|
|
73
|
+
console.log('Running agent with plainPlugin...');
|
|
74
|
+
await started.ask('Use the Add tool to calculate 5 + 3.');
|
|
75
|
+
|
|
76
|
+
console.log('\n--- Agent with decorated class plugin ---');
|
|
77
|
+
const agent2 = brain.agent('plugins-demo-2')
|
|
78
|
+
.with_tools(addTool)
|
|
79
|
+
.with_plugins(decorated);
|
|
80
|
+
|
|
81
|
+
const started2 = await agent2.start();
|
|
82
|
+
await started2.ask('Use the Add tool to calculate 7 + 3.');
|
|
83
|
+
|
|
84
|
+
await started.close();
|
|
85
|
+
await started2.close();
|
|
86
|
+
await brain.stop();
|
|
87
|
+
console.log('\nDone.');
|
|
88
|
+
process.exit(0);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { BrainOS, defineMcpProcess, defineMcpHttp, McpBuilder, version } from '../src/index.js';
|
|
2
|
+
|
|
3
|
+
const HTTP_MCP_URL = 'http://127.0.0.1:8000/mcp';
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
console.log(`\n=== 04-mcp.ts - MCP Server Demo (v${version()}) ===\n`);
|
|
7
|
+
|
|
8
|
+
console.log('--- defineMcpProcess / defineMcpHttp ---');
|
|
9
|
+
const processConfig = defineMcpProcess('files', 'npx', ['-y', '@modelcontextprotocol/server-filesystem', '/tmp']);
|
|
10
|
+
const httpConfig = defineMcpHttp('hello-mcp', HTTP_MCP_URL);
|
|
11
|
+
console.log('processConfig:', processConfig);
|
|
12
|
+
console.log('httpConfig:', httpConfig);
|
|
13
|
+
|
|
14
|
+
console.log('\n--- McpBuilder ---');
|
|
15
|
+
const mcpBuilder = new McpBuilder()
|
|
16
|
+
.process('files', 'npx', ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'])
|
|
17
|
+
.http('hello-mcp', HTTP_MCP_URL);
|
|
18
|
+
const builtConfigs = mcpBuilder.build();
|
|
19
|
+
console.log('Built MCP configs:', builtConfigs);
|
|
20
|
+
|
|
21
|
+
const brain = new BrainOS();
|
|
22
|
+
await brain.start();
|
|
23
|
+
|
|
24
|
+
console.log('\n--- Agent with MCP process (filesystem server) ---');
|
|
25
|
+
const agent = brain.agent('mcp-demo')
|
|
26
|
+
.with_mcp_process('files', 'npx', ['-y', '@modelcontextprotocol/server-filesystem', '/tmp']);
|
|
27
|
+
|
|
28
|
+
const started = await agent.start();
|
|
29
|
+
|
|
30
|
+
console.log('--- listMcpTools() ---');
|
|
31
|
+
try {
|
|
32
|
+
const mcpTools = await started.listMcpTools();
|
|
33
|
+
console.log(`MCP tools available: ${mcpTools.length}`);
|
|
34
|
+
mcpTools.slice(0, 3).forEach((t: any) => console.log(` - ${t.name}: ${t.description?.substring(0, 80)}...`));
|
|
35
|
+
if (mcpTools.length > 3) console.log(` ... and ${mcpTools.length - 3} more`);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log('MCP tools listing result:', (e as Error).message);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log('\n--- LLM call using MCP process tool ---');
|
|
41
|
+
try {
|
|
42
|
+
const result = await started.ask('List the files in /tmp directory using the MCP filesystem tool');
|
|
43
|
+
console.log('Result:', result.substring(0, 200));
|
|
44
|
+
} catch (e) {
|
|
45
|
+
console.log('LLM call error:', (e as Error).message);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log('\n--- Agent with MCP HTTP server ---');
|
|
49
|
+
const httpAgent = brain.agent('mcp-http-demo')
|
|
50
|
+
.with_mcp_http('hello-mcp', HTTP_MCP_URL);
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const httpStarted = await httpAgent.start();
|
|
54
|
+
const httpTools = await httpStarted.listMcpTools();
|
|
55
|
+
console.log(`HTTP MCP tools available: ${httpTools.length}`);
|
|
56
|
+
httpTools.forEach((t: any) => console.log(` - ${t.name}: ${t.description}`));
|
|
57
|
+
|
|
58
|
+
if (httpTools.length > 0) {
|
|
59
|
+
console.log('\n--- LLM call using HTTP MCP tool ---');
|
|
60
|
+
const httpResult = await httpStarted.ask('Use the greet tool to say hello to World');
|
|
61
|
+
console.log('HTTP MCP Result:', httpResult);
|
|
62
|
+
}
|
|
63
|
+
await httpStarted.close();
|
|
64
|
+
} catch (e) {
|
|
65
|
+
console.log('HTTP MCP failed:', (e as Error).message);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await started.close();
|
|
69
|
+
await brain.stop();
|
|
70
|
+
console.log('\nDone.');
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BrainOS, defineSkill, SkillsBuilder, version } from '../src/index.js';
|
|
2
|
+
import { initTracing } from '@open1s/jsbos';
|
|
3
|
+
|
|
4
|
+
initTracing();
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
console.log(`\n=== 05-skills.ts - Skills API Demo (v${version()}) ===\n`);
|
|
9
|
+
|
|
10
|
+
console.log('--- defineSkill ---');
|
|
11
|
+
const skill = defineSkill('math-expert', 'You are a math expert. Always show your work step by step.');
|
|
12
|
+
console.log('Skill:', skill);
|
|
13
|
+
|
|
14
|
+
console.log('\n--- SkillsBuilder ---');
|
|
15
|
+
const builder = new SkillsBuilder()
|
|
16
|
+
.from_dir('./skills')
|
|
17
|
+
.add('code-review', 'You are a code reviewer. Be thorough.')
|
|
18
|
+
.add('api-design', 'You are an API designer. Follow REST best practices.');
|
|
19
|
+
|
|
20
|
+
const built = builder.build();
|
|
21
|
+
console.log('Built skills:', built);
|
|
22
|
+
console.log(' dirs:', built.dirs);
|
|
23
|
+
console.log(' inline:', built.inline.map(s => s.name));
|
|
24
|
+
|
|
25
|
+
const brain = new BrainOS();
|
|
26
|
+
await brain.start();
|
|
27
|
+
|
|
28
|
+
console.log('\n--- Agent with skills from directory ---');
|
|
29
|
+
const agent = brain.agent('skills-demo')
|
|
30
|
+
.with_skills_dir('./skills');
|
|
31
|
+
|
|
32
|
+
const started = await agent.start();
|
|
33
|
+
console.log('Agent started with skills configured');
|
|
34
|
+
|
|
35
|
+
console.log('\n--- LLM call with skills ---');
|
|
36
|
+
const result = await started.ask('Review this code for potential bugs: function greet(name) { return "Hello, " + name; }');
|
|
37
|
+
console.log('Result:', result);
|
|
38
|
+
|
|
39
|
+
await started.close();
|
|
40
|
+
await brain.stop();
|
|
41
|
+
console.log('\nDone.');
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { initTracing } from '@open1s/jsbos';
|
|
2
|
+
import { BrainOS, defineTool, version } from '../src/index.js';
|
|
3
|
+
|
|
4
|
+
initTracing();
|
|
5
|
+
|
|
6
|
+
async function main() {
|
|
7
|
+
console.log(`\n=== 06-session.ts - Session API Demo (v${version()}) ===\n`);
|
|
8
|
+
|
|
9
|
+
const brain = new BrainOS();
|
|
10
|
+
await brain.start();
|
|
11
|
+
|
|
12
|
+
const greetingTool = defineTool('Greet', 'Greet someone')
|
|
13
|
+
.required('name', 'string', 'Name of the person to greet')
|
|
14
|
+
.handle((args: any) => `Hello, ${args.name}!`);
|
|
15
|
+
|
|
16
|
+
const agent = brain.agent('session-demo')
|
|
17
|
+
.with_tools(greetingTool)
|
|
18
|
+
.with_systemPrompt('You are a friendly assistant.');
|
|
19
|
+
|
|
20
|
+
const started = await agent.start();
|
|
21
|
+
|
|
22
|
+
console.log('--- Multi-turn conversation ---');
|
|
23
|
+
|
|
24
|
+
await started.ask('My name is Alice');
|
|
25
|
+
console.log('After Q1, session chars:', started.exportSession().length);
|
|
26
|
+
|
|
27
|
+
await started.ask('What is 2 + 2?');
|
|
28
|
+
console.log('After Q2, session chars:', started.exportSession().length);
|
|
29
|
+
|
|
30
|
+
await started.ask('What is my name?');
|
|
31
|
+
console.log('After Q3, session chars:', started.exportSession().length);
|
|
32
|
+
|
|
33
|
+
console.log('\n--- Session compact (LLM summary) ---');
|
|
34
|
+
const sessionBefore = started.exportSession().length;
|
|
35
|
+
console.log('Session before compact:', sessionBefore, 'chars');
|
|
36
|
+
|
|
37
|
+
await started.compactSession();
|
|
38
|
+
const afterCompact = started.exportSession().length;
|
|
39
|
+
console.log('After compactSession:', afterCompact, 'chars');
|
|
40
|
+
|
|
41
|
+
console.log('\n--- Verify compact worked ---');
|
|
42
|
+
const verifyResult = await started.ask('What is my name?');
|
|
43
|
+
console.log('Verify:', verifyResult.trim());
|
|
44
|
+
|
|
45
|
+
console.log('\n--- Session export / import ---');
|
|
46
|
+
const json = started.exportSession();
|
|
47
|
+
console.log('Export (first 150 chars):', json.substring(0, 150), '...');
|
|
48
|
+
|
|
49
|
+
console.log('\n--- SessionManager fluent API ---');
|
|
50
|
+
const agent2 = brain.agent('session-demo-2')
|
|
51
|
+
.with_tools(greetingTool)
|
|
52
|
+
.with_systemPrompt('You are a friendly assistant.');
|
|
53
|
+
const started2 = await agent2.start();
|
|
54
|
+
|
|
55
|
+
await started2.ask('Say hello to Bob');
|
|
56
|
+
const sessionJson = started2.exportSession();
|
|
57
|
+
console.log('Session before import length:', sessionJson.length);
|
|
58
|
+
|
|
59
|
+
started2.clearSession();
|
|
60
|
+
console.log('After clear, length:', started2.exportSession().length);
|
|
61
|
+
|
|
62
|
+
started2.importSession(sessionJson);
|
|
63
|
+
console.log('After import, length:', started2.exportSession().length);
|
|
64
|
+
|
|
65
|
+
await started.close();
|
|
66
|
+
await started2.close();
|
|
67
|
+
await brain.stop();
|
|
68
|
+
console.log('\nDone.');
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { BrainOS, tool, version } from '../src/index.js';
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log(`\n=== 07-agent-advanced.ts - Agent Advanced Demo (v${version()}) ===\n`);
|
|
5
|
+
|
|
6
|
+
const brain = new BrainOS();
|
|
7
|
+
await brain.start();
|
|
8
|
+
|
|
9
|
+
const addTool = tool('Add', 'Add two numbers', (args: any) => String(args.a + args.b));
|
|
10
|
+
|
|
11
|
+
console.log('--- BrainOS.with() static factory ---');
|
|
12
|
+
const quickBuilder = brain.agent('quick');
|
|
13
|
+
const quickAgent = await quickBuilder
|
|
14
|
+
.with_systemPrompt('You are a calculator.')
|
|
15
|
+
.with_temperature(0.5)
|
|
16
|
+
.start();
|
|
17
|
+
console.log('Quick agent created via BrainOS.with()');
|
|
18
|
+
console.log('Quick agent tools:', quickAgent.tools);
|
|
19
|
+
console.log('Quick agent config:', quickAgent.config);
|
|
20
|
+
|
|
21
|
+
console.log('\n--- Agent stream() - Real-time chat ---');
|
|
22
|
+
const streamAgent = brain.agent('stream-demo')
|
|
23
|
+
.with_tools(addTool)
|
|
24
|
+
.with_systemPrompt('You are a helpful assistant.');
|
|
25
|
+
|
|
26
|
+
const started = await streamAgent.start();
|
|
27
|
+
|
|
28
|
+
console.log('Streaming response:');
|
|
29
|
+
let streamedText = '';
|
|
30
|
+
await started.stream('What is 5 + 3? And what is the capital of France?', (token) => {
|
|
31
|
+
if(token.type === 'Text') {
|
|
32
|
+
process.stdout.write(token.text);
|
|
33
|
+
}
|
|
34
|
+
if(token.type === 'ReasoningContent') {
|
|
35
|
+
process.stdout.write(token.text);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
console.log('\n\nStreamed text length:', streamedText.length);
|
|
39
|
+
|
|
40
|
+
console.log('\n--- Agent streamCollect() ---');
|
|
41
|
+
const tokens = await started.streamCollect('What is 10 + 20?');
|
|
42
|
+
console.log('Collected', tokens.length, 'tokens');
|
|
43
|
+
const textTokens = tokens.filter(t => t.text);
|
|
44
|
+
console.log('Text tokens:', textTokens.length);
|
|
45
|
+
if (textTokens.length > 0) {
|
|
46
|
+
console.log('Collected text:', textTokens.map(t => t.text).join(''));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log('\n--- Agent metrics ---');
|
|
50
|
+
const metrics = started.metrics;
|
|
51
|
+
console.log('Metrics object keys:', Object.keys(metrics));
|
|
52
|
+
console.log('Metrics:', JSON.stringify(metrics, null, 2));
|
|
53
|
+
|
|
54
|
+
console.log('\n--- resetMetrics() ---');
|
|
55
|
+
started.resetMetrics();
|
|
56
|
+
console.log('Metrics after reset:', started.metrics);
|
|
57
|
+
|
|
58
|
+
console.log('\n--- Agent config ---');
|
|
59
|
+
console.log('Config:', started.config);
|
|
60
|
+
console.log('Config model:', started.config.model);
|
|
61
|
+
console.log('Config temperature:', started.config.temperature);
|
|
62
|
+
|
|
63
|
+
console.log('\n--- Agent tools list ---');
|
|
64
|
+
console.log('Tools:', started.tools);
|
|
65
|
+
|
|
66
|
+
console.log('\n--- Resilience options ---');
|
|
67
|
+
const resilientAgent = brain.agent('resilient')
|
|
68
|
+
.with_tools(addTool)
|
|
69
|
+
.with_resilience({
|
|
70
|
+
circuitBreakerMaxFailures: 3,
|
|
71
|
+
circuitBreakerCooldownSecs: 10,
|
|
72
|
+
rateLimitCapacity: 5,
|
|
73
|
+
rateLimitWindowSecs: 60,
|
|
74
|
+
rateLimitMaxRetries: 3,
|
|
75
|
+
});
|
|
76
|
+
const resilientStarted = await resilientAgent.start();
|
|
77
|
+
console.log('Resilient agent configured with circuit breaker + rate limiting');
|
|
78
|
+
console.log('Resilient agent config:', resilientStarted.config);
|
|
79
|
+
|
|
80
|
+
await resilientStarted.close();
|
|
81
|
+
await brain.stop();
|
|
82
|
+
console.log('\nDone.');
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { BrainOS, version } from '../src/index.js';
|
|
2
|
+
|
|
3
|
+
async function main() {
|
|
4
|
+
console.log(`\n=== 08-brainos-messaging.ts - Messaging Demo (v${version()}) ===\n`);
|
|
5
|
+
|
|
6
|
+
const brain = new BrainOS();
|
|
7
|
+
await brain.start();
|
|
8
|
+
|
|
9
|
+
console.log('--- Query/Queryable pattern ---');
|
|
10
|
+
const queryServer = await brain.queryable('math-query', (input: string) => {
|
|
11
|
+
console.log('[Queryable] Received:', input);
|
|
12
|
+
const n = parseInt(input);
|
|
13
|
+
if (isNaN(n)) return 'Error: invalid number';
|
|
14
|
+
return String(n * n);
|
|
15
|
+
});
|
|
16
|
+
await queryServer.start();
|
|
17
|
+
|
|
18
|
+
const queryClient = await brain.query('math-query');
|
|
19
|
+
const response = await queryClient.ask('42', 5000);
|
|
20
|
+
console.log('[QueryClient] Response for 42:', response);
|
|
21
|
+
|
|
22
|
+
console.log('\n--- Caller/Callable pattern ---');
|
|
23
|
+
const callableServer = await brain.callable('rpc-add', (input: string) => {
|
|
24
|
+
console.log('[Callable] Received:', input);
|
|
25
|
+
const parts = input.split(',');
|
|
26
|
+
if (parts.length !== 2) return 'Error: need two numbers separated by comma';
|
|
27
|
+
return String(parseInt(parts[0]) + parseInt(parts[1]));
|
|
28
|
+
});
|
|
29
|
+
await callableServer.start();
|
|
30
|
+
|
|
31
|
+
const callerClient = await brain.caller('rpc-add');
|
|
32
|
+
const callResult = await callerClient.call('10,20');
|
|
33
|
+
console.log('[CallerClient] Result for 10,20:', callResult);
|
|
34
|
+
|
|
35
|
+
console.log('\n--- Publisher/Subscriber pattern (recv) ---');
|
|
36
|
+
const sub1 = await brain.subscriber('test-topic');
|
|
37
|
+
console.log('Subscriber topic:', sub1.topic);
|
|
38
|
+
|
|
39
|
+
const pub = await brain.publisher('test-topic');
|
|
40
|
+
console.log('Publisher topic:', pub.topic);
|
|
41
|
+
await pub.text('Hello from PublisherWrapper!');
|
|
42
|
+
await pub.json({ msg: 'structured', value: 123 });
|
|
43
|
+
console.log('Published via PublisherWrapper.text() and .json()');
|
|
44
|
+
|
|
45
|
+
console.log('Waiting for messages...');
|
|
46
|
+
const msg1 = await sub1.recv(3000);
|
|
47
|
+
console.log('[Subscriber] Received 1:', msg1);
|
|
48
|
+
const msg2 = await sub1.recv(3000);
|
|
49
|
+
console.log('[Subscriber] Received 2:', msg2);
|
|
50
|
+
await sub1.stop();
|
|
51
|
+
|
|
52
|
+
console.log('\n--- Publisher/Subscriber pattern (run) ---');
|
|
53
|
+
const sub2 = await brain.subscriber('run-topic');
|
|
54
|
+
const pub2 = await brain.publisher('run-topic');
|
|
55
|
+
|
|
56
|
+
console.log('Starting subscriber with run()...');
|
|
57
|
+
const runPromise = sub2.run((msg) => {
|
|
58
|
+
console.log('[Subscriber.run] Received:', msg);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await pub2.text('Message 1 via run');
|
|
62
|
+
await pub2.text('Message 2 via run');
|
|
63
|
+
await pub2.json({ action: 'test', id: 42 });
|
|
64
|
+
|
|
65
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
66
|
+
await sub2.stop();
|
|
67
|
+
await runPromise;
|
|
68
|
+
|
|
69
|
+
console.log('\n--- Agent with messaging integration ---');
|
|
70
|
+
const agent = brain.agent('messaging-demo')
|
|
71
|
+
.with_systemPrompt('You are a helpful assistant. When asked about messaging, explain the patterns.');
|
|
72
|
+
|
|
73
|
+
const started = await agent.start();
|
|
74
|
+
const messagingResult = await started.ask('Explain the difference between Query and Publisher messaging patterns.');
|
|
75
|
+
console.log('Agent response:', messagingResult);
|
|
76
|
+
|
|
77
|
+
await started.close();
|
|
78
|
+
await brain.stop();
|
|
79
|
+
console.log('\nDone.');
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
main().catch((e) => { console.error(e); process.exit(1); });
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@open1s/ezbos",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Simple BrainOS - Easy wrapper for @open1s/jsbos",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"dev": "tsc --watch",
|
|
18
|
+
"test": "node --test",
|
|
19
|
+
"example:tools": "tsx examples/01-tools.ts",
|
|
20
|
+
"example:hooks": "tsx examples/02-hooks.ts",
|
|
21
|
+
"example:plugins": "tsx examples/03-plugins.ts",
|
|
22
|
+
"example:mcp": "tsx examples/04-mcp.ts",
|
|
23
|
+
"example:skills": "tsx examples/05-skills.ts",
|
|
24
|
+
"example:session": "tsx examples/06-session.ts",
|
|
25
|
+
"example:agent": "tsx examples/07-agent-advanced.ts",
|
|
26
|
+
"example:messaging": "tsx examples/08-brainos-messaging.ts"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"ai",
|
|
30
|
+
"agent",
|
|
31
|
+
"brainos",
|
|
32
|
+
"ezbos"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@open1s/jsbos": "^2.1.4"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
40
|
+
"@types/node": "^25.8.0",
|
|
41
|
+
"tsx": "^4.22.0",
|
|
42
|
+
"typescript": "^6.0.3",
|
|
43
|
+
"zod": "^4.4.3"
|
|
44
|
+
},
|
|
45
|
+
"packageManager": "yarn@4.13.0+sha512.5c20ba010c99815433e5c8453112165e673f1c7948d8d2b267f4b5e52097538658388ebc9f9580656d9b75c5cc996f990f611f99304a2197d4c56d21eea370e7"
|
|
46
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
description: Expert code review for potential bugs, security, and performance
|
|
4
|
+
category: development
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Code Review Skill
|
|
9
|
+
|
|
10
|
+
You are an expert code reviewer. When reviewing code:
|
|
11
|
+
|
|
12
|
+
1. Check for potential bugs and edge cases
|
|
13
|
+
2. Identify security vulnerabilities
|
|
14
|
+
3. Suggest performance improvements
|
|
15
|
+
4. Review for readability and maintainability
|
|
16
|
+
5. Provide concrete examples of improvements
|
|
17
|
+
|
|
18
|
+
Always format your response with clear sections and code examples.
|