@open1s/ezbos 1.0.1 → 1.0.3

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.
@@ -0,0 +1,78 @@
1
+ import * as jsbos from '@open1s/jsbos';
2
+ import { SkillDef } from './skills.js';
3
+ export declare class AgentBuilder {
4
+ private _inner;
5
+ private _tools;
6
+ private _hooks;
7
+ private _plugins;
8
+ private _mcp;
9
+ private _skillsDirs;
10
+ private _inlineSkills;
11
+ private _config;
12
+ constructor(name: string, options?: {
13
+ model?: string;
14
+ baseUrl?: string;
15
+ apiKey?: string;
16
+ systemPrompt?: string;
17
+ temperature?: number;
18
+ timeoutSecs?: number;
19
+ maxTokens?: number;
20
+ circuitBreakerMaxFailures?: number;
21
+ circuitBreakerCooldownSecs?: number;
22
+ rateLimitCapacity?: number;
23
+ rateLimitWindowSecs?: number;
24
+ rateLimitMaxRetries?: number;
25
+ });
26
+ with_model(model: string): this;
27
+ with_baseUrl(url: string): this;
28
+ with_apiKey(key: string): this;
29
+ with_systemPrompt(prompt: string): this;
30
+ with_prompt(prompt: string): this;
31
+ with_temperature(temp: number): this;
32
+ with_timeout(secs: number): this;
33
+ with_maxTokens(tokens: number): this;
34
+ with_tools(...tools: any[]): this;
35
+ register(...tools: any[]): this;
36
+ with_hooks(...sources: any[]): this;
37
+ with_plugins(...sources: any[]): this;
38
+ with_mcp_process(namespace: string, command: string, args: string[]): this;
39
+ with_mcp_http(namespace: string, url: string): this;
40
+ with_skills_dir(dirPath: string): this;
41
+ with_skills(...skills: SkillDef[]): this;
42
+ with_resilience(opts: {
43
+ circuitBreakerMaxFailures?: number;
44
+ circuitBreakerCooldownSecs?: number;
45
+ rateLimitCapacity?: number;
46
+ rateLimitWindowSecs?: number;
47
+ rateLimitMaxRetries?: number;
48
+ }): this;
49
+ start(): Promise<Agent>;
50
+ private rebuildAgentWithPrompt;
51
+ ask(prompt: string): Promise<string>;
52
+ runSimple(prompt: string): Promise<string>;
53
+ react(task: string): Promise<string>;
54
+ stop(): Promise<void>;
55
+ }
56
+ export declare class Agent {
57
+ private _inner;
58
+ constructor(_inner: jsbos.Agent);
59
+ run(task: string): Promise<string>;
60
+ ask(prompt: string): Promise<string>;
61
+ runSimple(prompt: string): Promise<string>;
62
+ react(task: string): Promise<string>;
63
+ compactSession(): Promise<void>;
64
+ saveSession(path: string): void;
65
+ restoreSession(path: string): void;
66
+ clearSession(): void;
67
+ exportSession(): string;
68
+ importSession(json: string): void;
69
+ stream(task: string, onToken: (token: any) => void): Promise<string>;
70
+ streamCollect(task: string): Promise<any[]>;
71
+ get tools(): string[];
72
+ get config(): any;
73
+ get inner(): jsbos.Agent;
74
+ listMcpTools(): Promise<any[]>;
75
+ get metrics(): jsbos.PerfSnapshot;
76
+ resetMetrics(): void;
77
+ close(): Promise<void>;
78
+ }
package/dist/agent.js ADDED
@@ -0,0 +1,316 @@
1
+ import * as jsbos from '@open1s/jsbos';
2
+ import { mergeHooks } from './hook.js';
3
+ import { mergePlugins } from './plugin.js';
4
+ const DEFAULT_MODEL = 'nvidia/meta/llama-3.1-8b-instruct';
5
+ const DEFAULT_BASE_URL = 'https://integrate.api.nvidia.com/v1';
6
+ export class AgentBuilder {
7
+ _inner = null;
8
+ _tools = [];
9
+ _hooks = [];
10
+ _plugins = [];
11
+ _mcp = [];
12
+ _skillsDirs = [];
13
+ _inlineSkills = [];
14
+ _config;
15
+ constructor(name, options = {}) {
16
+ this._config = {
17
+ name,
18
+ model: options.model || DEFAULT_MODEL,
19
+ baseUrl: options.baseUrl || DEFAULT_BASE_URL,
20
+ apiKey: options.apiKey,
21
+ systemPrompt: options.systemPrompt || 'You are a helpful assistant.',
22
+ temperature: options.temperature ?? 0.7,
23
+ timeoutSecs: options.timeoutSecs || 120,
24
+ maxTokens: options.maxTokens ?? 4096,
25
+ circuitBreakerMaxFailures: options.circuitBreakerMaxFailures,
26
+ circuitBreakerCooldownSecs: options.circuitBreakerCooldownSecs,
27
+ rateLimitCapacity: options.rateLimitCapacity,
28
+ rateLimitWindowSecs: options.rateLimitWindowSecs,
29
+ rateLimitMaxRetries: options.rateLimitMaxRetries,
30
+ };
31
+ }
32
+ with_model(model) {
33
+ this._config.model = model;
34
+ return this;
35
+ }
36
+ with_baseUrl(url) {
37
+ this._config.baseUrl = url;
38
+ return this;
39
+ }
40
+ with_apiKey(key) {
41
+ this._config.apiKey = key;
42
+ return this;
43
+ }
44
+ with_systemPrompt(prompt) {
45
+ this._config.systemPrompt = prompt;
46
+ return this;
47
+ }
48
+ with_prompt(prompt) {
49
+ return this.with_systemPrompt(prompt);
50
+ }
51
+ with_temperature(temp) {
52
+ this._config.temperature = temp;
53
+ return this;
54
+ }
55
+ with_timeout(secs) {
56
+ this._config.timeoutSecs = secs;
57
+ return this;
58
+ }
59
+ with_maxTokens(tokens) {
60
+ this._config.maxTokens = tokens;
61
+ return this;
62
+ }
63
+ with_tools(...tools) {
64
+ for (const t of tools) {
65
+ if (t && typeof t === 'object' && 'name' in t && 'description' in t && 'callback' in t) {
66
+ this._tools.push(t);
67
+ }
68
+ else if (typeof t === 'function' && t.toolDef) {
69
+ this._tools.push(t.toolDef);
70
+ }
71
+ }
72
+ return this;
73
+ }
74
+ register(...tools) {
75
+ return this.with_tools(...tools);
76
+ }
77
+ with_hooks(...sources) {
78
+ const merged = mergeHooks(...sources);
79
+ this._hooks.push(...merged);
80
+ return this;
81
+ }
82
+ with_plugins(...sources) {
83
+ const merged = mergePlugins(...sources);
84
+ this._plugins.push(...merged);
85
+ return this;
86
+ }
87
+ with_mcp_process(namespace, command, args) {
88
+ this._mcp.push({ type: 'process', namespace, command, args });
89
+ return this;
90
+ }
91
+ with_mcp_http(namespace, url) {
92
+ this._mcp.push({ type: 'http', namespace, url });
93
+ return this;
94
+ }
95
+ with_skills_dir(dirPath) {
96
+ this._skillsDirs.push(dirPath);
97
+ return this;
98
+ }
99
+ with_skills(...skills) {
100
+ this._inlineSkills.push(...skills);
101
+ return this;
102
+ }
103
+ with_resilience(opts) {
104
+ if (opts.circuitBreakerMaxFailures !== undefined) {
105
+ this._config.circuitBreakerMaxFailures = opts.circuitBreakerMaxFailures;
106
+ }
107
+ if (opts.circuitBreakerCooldownSecs !== undefined) {
108
+ this._config.circuitBreakerCooldownSecs = opts.circuitBreakerCooldownSecs;
109
+ }
110
+ if (opts.rateLimitCapacity !== undefined) {
111
+ this._config.rateLimitCapacity = opts.rateLimitCapacity;
112
+ }
113
+ if (opts.rateLimitWindowSecs !== undefined) {
114
+ this._config.rateLimitWindowSecs = opts.rateLimitWindowSecs;
115
+ }
116
+ if (opts.rateLimitMaxRetries !== undefined) {
117
+ this._config.rateLimitMaxRetries = opts.rateLimitMaxRetries;
118
+ }
119
+ return this;
120
+ }
121
+ async start() {
122
+ this._inner = await jsbos.Agent.create(this._config);
123
+ for (const tool of this._tools) {
124
+ this._inner.addTool(tool.name, tool.description, JSON.stringify(tool.schema.properties || {}), JSON.stringify(tool.schema), (err, args) => {
125
+ if (err)
126
+ return String(err);
127
+ try {
128
+ return tool.callback(args);
129
+ }
130
+ catch (e) {
131
+ return String(e);
132
+ }
133
+ });
134
+ }
135
+ for (const { event, callback } of this._hooks) {
136
+ this._inner.registerHook(event, async (e, ctx) => {
137
+ if (e)
138
+ return 'continue';
139
+ return await callback(ctx);
140
+ });
141
+ }
142
+ for (const plugin of this._plugins) {
143
+ this._inner.registerPlugin(plugin.name || 'plugin', plugin.on_llm_request ? ((err, arg) => {
144
+ if (err)
145
+ return;
146
+ return plugin.on_llm_request(arg);
147
+ }) : undefined, plugin.on_llm_response ? ((err, arg) => {
148
+ if (err)
149
+ return;
150
+ return plugin.on_llm_response(arg);
151
+ }) : undefined, plugin.on_tool_call ? ((err, arg) => {
152
+ if (err)
153
+ return;
154
+ return plugin.on_tool_call(arg);
155
+ }) : undefined, plugin.on_tool_result ? ((err, arg) => {
156
+ if (err)
157
+ return;
158
+ return plugin.on_tool_result(arg);
159
+ }) : undefined);
160
+ }
161
+ for (const mcp of this._mcp) {
162
+ if (mcp.type === 'process' && mcp.command && mcp.args) {
163
+ await this._inner.addMcpServer(mcp.namespace, mcp.command, mcp.args);
164
+ }
165
+ else if (mcp.type === 'http' && mcp.url) {
166
+ await this._inner.addMcpServerHttp(mcp.namespace, mcp.url);
167
+ }
168
+ }
169
+ let systemPrompt = this._config.systemPrompt || '';
170
+ for (const dir of this._skillsDirs) {
171
+ await this._inner.registerSkillsFromDir(dir);
172
+ }
173
+ for (const skill of this._inlineSkills) {
174
+ const addition = `\n\n# Skill: ${skill.name}\n${skill.content}`;
175
+ systemPrompt += addition;
176
+ }
177
+ if (systemPrompt !== this._config.systemPrompt) {
178
+ this._config.systemPrompt = systemPrompt;
179
+ const newAgent = await this.rebuildAgentWithPrompt(systemPrompt);
180
+ this._inner = newAgent;
181
+ }
182
+ return new Agent(this._inner);
183
+ }
184
+ async rebuildAgentWithPrompt(newPrompt) {
185
+ const newAgent = await jsbos.Agent.create({
186
+ name: this._config.name,
187
+ model: this._config.model,
188
+ baseUrl: this._config.baseUrl,
189
+ apiKey: this._config.apiKey || '',
190
+ systemPrompt: newPrompt,
191
+ temperature: this._config.temperature,
192
+ timeoutSecs: this._config.timeoutSecs,
193
+ maxTokens: this._config.maxTokens,
194
+ });
195
+ for (const tool of this._tools) {
196
+ newAgent.addTool(tool.name, tool.description, JSON.stringify(tool.schema.properties || {}), JSON.stringify(tool.schema), (err, args) => {
197
+ if (err)
198
+ return String(err);
199
+ try {
200
+ return tool.callback(args);
201
+ }
202
+ catch (e) {
203
+ return String(e);
204
+ }
205
+ });
206
+ }
207
+ return newAgent;
208
+ }
209
+ async ask(prompt) {
210
+ if (!this._inner)
211
+ await this.start();
212
+ return this._inner.react(prompt);
213
+ }
214
+ async runSimple(prompt) {
215
+ if (!this._inner)
216
+ await this.start();
217
+ return this._inner.runSimple(prompt);
218
+ }
219
+ async react(task) {
220
+ if (!this._inner)
221
+ await this.start();
222
+ return this._inner.react(task);
223
+ }
224
+ async stop() {
225
+ if (!this._inner)
226
+ return;
227
+ this._inner.stop();
228
+ }
229
+ }
230
+ export class Agent {
231
+ _inner;
232
+ constructor(_inner) {
233
+ this._inner = _inner;
234
+ }
235
+ async run(task) {
236
+ return this._inner.runSimple(task);
237
+ }
238
+ async ask(prompt) {
239
+ return this._inner.react(prompt);
240
+ }
241
+ async runSimple(prompt) {
242
+ return this._inner.runSimple(prompt);
243
+ }
244
+ async react(task) {
245
+ return this._inner.react(task);
246
+ }
247
+ async compactSession() {
248
+ const sessionJson = this._inner.getSessionJson();
249
+ const compactedJson = await this.ask(`Compact this session JSON. Preserve all important context, facts, and decisions while removing redundant messages. Return ONLY valid JSON. Use exact role names: "System", "User", "Assistant", "AssistantToolCall", "ToolResult".\n\nSession JSON:\n${sessionJson}`);
250
+ let cleaned = compactedJson.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
251
+ cleaned = cleaned.replace(/"user"/g, '"User"')
252
+ .replace(/"assistant"/g, '"Assistant"')
253
+ .replace(/"system"/g, '"System"')
254
+ .replace(/"toolresult"/g, '"ToolResult"')
255
+ .replace(/"assistanttoolcall"/g, '"AssistantToolCall"');
256
+ this._inner.restoreSessionJson(cleaned);
257
+ }
258
+ saveSession(path) {
259
+ this._inner.saveSession(path);
260
+ }
261
+ restoreSession(path) {
262
+ this._inner.restoreSessionFromFile(path);
263
+ }
264
+ clearSession() {
265
+ this._inner.clearSession();
266
+ }
267
+ exportSession() {
268
+ return this._inner.getSessionJson();
269
+ }
270
+ importSession(json) {
271
+ this._inner.restoreSessionJson(json);
272
+ }
273
+ stream(task, onToken) {
274
+ return this._inner.stream(task, (err, token) => {
275
+ if (err) {
276
+ onToken({ type: 'Error', error: err.message });
277
+ }
278
+ else {
279
+ onToken(token);
280
+ }
281
+ });
282
+ }
283
+ async streamCollect(task) {
284
+ const tokens = [];
285
+ await new Promise((resolve) => {
286
+ this.stream(task, token => {
287
+ tokens.push(token);
288
+ if (token.type === 'Done') {
289
+ resolve();
290
+ }
291
+ });
292
+ });
293
+ return tokens;
294
+ }
295
+ get tools() {
296
+ return this._inner.listTools();
297
+ }
298
+ get config() {
299
+ return this._inner.config();
300
+ }
301
+ get inner() {
302
+ return this._inner;
303
+ }
304
+ async listMcpTools() {
305
+ return this._inner.listMcpTools();
306
+ }
307
+ get metrics() {
308
+ return this._inner.getPerfMetrics();
309
+ }
310
+ resetMetrics() {
311
+ this._inner.resetPerfMetrics();
312
+ }
313
+ async close() {
314
+ this._inner.close();
315
+ }
316
+ }
@@ -0,0 +1,99 @@
1
+ import * as jsbos from '@open1s/jsbos';
2
+ import { AgentBuilder, Agent } from './agent.js';
3
+ interface BrainOSOptions {
4
+ model?: string;
5
+ baseUrl?: string;
6
+ apiKey?: string;
7
+ }
8
+ interface BusOptions {
9
+ mode?: string;
10
+ connect?: string[];
11
+ listen?: string[];
12
+ peer?: string;
13
+ }
14
+ export declare class BrainOS {
15
+ private _bus;
16
+ private _started;
17
+ private _config;
18
+ private _options;
19
+ constructor(options?: BrainOSOptions);
20
+ start(): Promise<this>;
21
+ stop(): Promise<void>;
22
+ get isStarted(): boolean;
23
+ with_bus(config: BusOptions): this;
24
+ agent(name?: string, options?: {
25
+ model?: string;
26
+ baseUrl?: string;
27
+ apiKey?: string;
28
+ systemPrompt?: string;
29
+ temperature?: number;
30
+ timeoutSecs?: number;
31
+ maxTokens?: number;
32
+ }): AgentBuilder;
33
+ get bus(): jsbos.Bus;
34
+ publish(topic: string, payload: any, isJson?: boolean): Promise<void>;
35
+ publisher(topic: string): Promise<PublisherWrapper>;
36
+ subscriber(topic: string): Promise<SubscriberWrapper>;
37
+ query(topic: string): Promise<QueryClient>;
38
+ queryable(topic: string, handler?: (input: string) => any): Promise<QueryableServer>;
39
+ caller(name: string): Promise<CallerClient>;
40
+ callable(uri: string, handler?: (input: string) => any): Promise<CallableServer>;
41
+ get config(): any;
42
+ static with(name?: string, options?: BrainOSOptions): Promise<Agent>;
43
+ }
44
+ export declare class PublisherWrapper {
45
+ private _inner;
46
+ constructor(_inner: jsbos.Publisher);
47
+ get topic(): string;
48
+ publish(payload: any, isJson?: boolean): Promise<void>;
49
+ text(payload: string): Promise<void>;
50
+ json(data: any): Promise<void>;
51
+ }
52
+ export declare class SubscriberWrapper {
53
+ private _inner;
54
+ constructor(_inner: jsbos.Subscriber);
55
+ get topic(): string;
56
+ recv(timeoutMs?: number): Promise<string | null>;
57
+ recvJson(timeoutMs?: number): Promise<any | null>;
58
+ run(callback: (msg: string) => void): Promise<void>;
59
+ runJson(callback: (data: any) => void): Promise<void>;
60
+ stop(): Promise<void>;
61
+ [Symbol.asyncIterator](): this;
62
+ next(): Promise<{
63
+ done: boolean;
64
+ value?: string;
65
+ }>;
66
+ }
67
+ export declare class QueryClient {
68
+ private _inner;
69
+ constructor(_inner: jsbos.Query);
70
+ get topic(): string;
71
+ ask(payload: string, timeoutMs?: number): Promise<string>;
72
+ askJson(payload: any, timeoutMs?: number): Promise<any>;
73
+ }
74
+ export declare class QueryableServer {
75
+ private _inner;
76
+ private _handler?;
77
+ constructor(_inner: jsbos.Queryable, handler?: (input: string) => any);
78
+ handle(handler: (input: string) => any): this;
79
+ start(): Promise<this>;
80
+ run(handler: (input: string) => any): Promise<void>;
81
+ runJson(handler: (input: any) => any): Promise<void>;
82
+ }
83
+ export declare class CallerClient {
84
+ private _inner;
85
+ constructor(_inner: jsbos.Caller);
86
+ call(payload: string): Promise<string>;
87
+ callJson(payload: any): Promise<any>;
88
+ }
89
+ export declare class CallableServer {
90
+ private _inner;
91
+ private _handler?;
92
+ constructor(_inner: jsbos.Callable, handler?: (input: string) => any);
93
+ handle(handler: (input: string) => any): this;
94
+ get isStarted(): boolean;
95
+ start(): Promise<this>;
96
+ run(handler: (input: string) => any): Promise<void>;
97
+ runJson(handler: (input: any) => any): Promise<void>;
98
+ }
99
+ export {};