@mast-ai/core 0.1.2 → 0.3.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/dist/agentTool.js +1 -2
- package/dist/runner.d.ts +14 -1
- package/dist/runner.js +27 -1
- package/dist/tool.d.ts +33 -0
- package/dist/tool.js +68 -1
- package/package.json +1 -1
package/dist/agentTool.js
CHANGED
|
@@ -22,14 +22,13 @@ export function createAgentTool(runner, agent, options) {
|
|
|
22
22
|
definition: () => definition,
|
|
23
23
|
async call(args, context) {
|
|
24
24
|
const input = options.buildInput(args);
|
|
25
|
-
const builder = runner.runBuilder(agent);
|
|
25
|
+
const builder = runner.runBuilder(agent).forwardTo(context);
|
|
26
26
|
if (context.signal)
|
|
27
27
|
builder.signal(context.signal);
|
|
28
28
|
for await (const event of builder.runStream(input)) {
|
|
29
29
|
if (event.type === 'done') {
|
|
30
30
|
return event.output;
|
|
31
31
|
}
|
|
32
|
-
context.onEvent?.(event);
|
|
33
32
|
}
|
|
34
33
|
throw new AgentError(`Sub-agent '${agent.name}' stream ended without a 'done' event.`);
|
|
35
34
|
},
|
package/dist/runner.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentConfig, AgentEvent, AgentResult, Message } from './types.js';
|
|
2
2
|
import type { LlmAdapter } from './adapter/index.js';
|
|
3
|
-
import { type ToolProvider } from './tool.js';
|
|
3
|
+
import { type ToolContext, type ToolProvider } from './tool.js';
|
|
4
4
|
import { Conversation } from './conversation.js';
|
|
5
5
|
type StreamExecutor = (input: string, history: Message[], signal?: AbortSignal, onToolEvent?: (toolName: string, event: AgentEvent) => void) => AsyncIterable<AgentEvent>;
|
|
6
6
|
/**
|
|
@@ -15,6 +15,7 @@ export declare class RunBuilder {
|
|
|
15
15
|
private _history;
|
|
16
16
|
private _signal?;
|
|
17
17
|
private _onToolEvent?;
|
|
18
|
+
private _forwardContext?;
|
|
18
19
|
constructor(agent: AgentConfig, execute: StreamExecutor);
|
|
19
20
|
/** Prepend prior conversation turns. */
|
|
20
21
|
history(messages: Message[]): this;
|
|
@@ -27,6 +28,18 @@ export declare class RunBuilder {
|
|
|
27
28
|
* events — use `runBuilder().onToolEvent(...).runStream()` for that.
|
|
28
29
|
*/
|
|
29
30
|
onToolEvent(handler: (toolName: string, event: AgentEvent) => void): this;
|
|
31
|
+
/**
|
|
32
|
+
* Forwards every non-`done` event yielded by this run to
|
|
33
|
+
* `parentContext.onEvent`. Intended for tools that internally run a
|
|
34
|
+
* sub-agent: chain this so the parent runner's UI can populate
|
|
35
|
+
* `subThinking` / `subText` / `nestedToolEvents` on the parent's tool
|
|
36
|
+
* entry without manual forwarding boilerplate.
|
|
37
|
+
*
|
|
38
|
+
* `done` events are filtered out to avoid leaking child conversation
|
|
39
|
+
* history to the parent's consumers. If `parentContext.onEvent` is
|
|
40
|
+
* undefined, this is a no-op.
|
|
41
|
+
*/
|
|
42
|
+
forwardTo(parentContext: ToolContext): this;
|
|
30
43
|
/** Executes the run and returns a stream of {@link AgentEvent} objects. */
|
|
31
44
|
runStream(input: string): AsyncIterable<AgentEvent>;
|
|
32
45
|
/** Executes the run and returns the final text output. */
|
package/dist/runner.js
CHANGED
|
@@ -15,6 +15,7 @@ export class RunBuilder {
|
|
|
15
15
|
_history = [];
|
|
16
16
|
_signal;
|
|
17
17
|
_onToolEvent;
|
|
18
|
+
_forwardContext;
|
|
18
19
|
constructor(agent, execute) {
|
|
19
20
|
this.agent = agent;
|
|
20
21
|
this.execute = execute;
|
|
@@ -39,9 +40,34 @@ export class RunBuilder {
|
|
|
39
40
|
this._onToolEvent = handler;
|
|
40
41
|
return this;
|
|
41
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Forwards every non-`done` event yielded by this run to
|
|
45
|
+
* `parentContext.onEvent`. Intended for tools that internally run a
|
|
46
|
+
* sub-agent: chain this so the parent runner's UI can populate
|
|
47
|
+
* `subThinking` / `subText` / `nestedToolEvents` on the parent's tool
|
|
48
|
+
* entry without manual forwarding boilerplate.
|
|
49
|
+
*
|
|
50
|
+
* `done` events are filtered out to avoid leaking child conversation
|
|
51
|
+
* history to the parent's consumers. If `parentContext.onEvent` is
|
|
52
|
+
* undefined, this is a no-op.
|
|
53
|
+
*/
|
|
54
|
+
forwardTo(parentContext) {
|
|
55
|
+
this._forwardContext = parentContext;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
42
58
|
/** Executes the run and returns a stream of {@link AgentEvent} objects. */
|
|
43
59
|
runStream(input) {
|
|
44
|
-
|
|
60
|
+
const stream = this.execute(input, this._history, this._signal, this._onToolEvent);
|
|
61
|
+
const onEvent = this._forwardContext?.onEvent;
|
|
62
|
+
if (!onEvent)
|
|
63
|
+
return stream;
|
|
64
|
+
return (async function* () {
|
|
65
|
+
for await (const event of stream) {
|
|
66
|
+
if (event.type !== 'done')
|
|
67
|
+
onEvent(event);
|
|
68
|
+
yield event;
|
|
69
|
+
}
|
|
70
|
+
})();
|
|
45
71
|
}
|
|
46
72
|
/** Executes the run and returns the final text output. */
|
|
47
73
|
async run(input) {
|
package/dist/tool.d.ts
CHANGED
|
@@ -45,9 +45,27 @@ export interface ToolProvider {
|
|
|
45
45
|
/** Returns the tool registered under `name`, or `undefined` if not found or out of scope. */
|
|
46
46
|
getTool(name: string): Tool | undefined;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Events emitted by {@link ToolRegistry} (and {@link ToolRegistryView}) when its
|
|
50
|
+
* contents change at runtime. UI components and adapters can subscribe via
|
|
51
|
+
* `addEventListener` to refresh toolbars, re-advertise capabilities, or trigger
|
|
52
|
+
* a new agent turn.
|
|
53
|
+
*/
|
|
54
|
+
export type ToolRegistryEventMap = {
|
|
55
|
+
/** Fired after a tool is successfully added. */
|
|
56
|
+
'tool-registered': {
|
|
57
|
+
tool: Tool;
|
|
58
|
+
};
|
|
59
|
+
/** Fired after a tool is removed. Not fired for no-op `unregister` calls. */
|
|
60
|
+
'tool-unregistered': {
|
|
61
|
+
name: string;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
type ToolRegistryListener<K extends keyof ToolRegistryEventMap> = (event: ToolRegistryEventMap[K]) => void;
|
|
48
65
|
/** Holds all tools available to an {@link AgentRunner} and resolves them by name during execution. */
|
|
49
66
|
export declare class ToolRegistry implements ToolProvider {
|
|
50
67
|
private _tools;
|
|
68
|
+
private _emitter;
|
|
51
69
|
/**
|
|
52
70
|
* Registers a tool. Throws if a tool with the same name is already registered.
|
|
53
71
|
* Returns `this` for chaining.
|
|
@@ -61,6 +79,10 @@ export declare class ToolRegistry implements ToolProvider {
|
|
|
61
79
|
getTools(): ToolDefinition[];
|
|
62
80
|
/** Returns a live read-only view filtered to tools with `scope: 'read'`. */
|
|
63
81
|
readOnly(): ToolRegistryView;
|
|
82
|
+
/** Subscribe to registry mutation events. */
|
|
83
|
+
addEventListener<K extends keyof ToolRegistryEventMap>(type: K, listener: ToolRegistryListener<K>): void;
|
|
84
|
+
/** Unsubscribe a previously registered listener. */
|
|
85
|
+
removeEventListener<K extends keyof ToolRegistryEventMap>(type: K, listener: ToolRegistryListener<K>): void;
|
|
64
86
|
}
|
|
65
87
|
/**
|
|
66
88
|
* A live filtered projection of a {@link ToolRegistry}.
|
|
@@ -71,7 +93,18 @@ export declare class ToolRegistry implements ToolProvider {
|
|
|
71
93
|
export declare class ToolRegistryView implements ToolProvider {
|
|
72
94
|
private readonly parent;
|
|
73
95
|
private readonly scope;
|
|
96
|
+
private _emitter;
|
|
97
|
+
private _scopedNames?;
|
|
74
98
|
constructor(parent: ToolRegistry, scope: 'read' | 'write');
|
|
75
99
|
getTools(): ToolDefinition[];
|
|
76
100
|
getTool(name: string): Tool | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Subscribe to mutation events forwarded from the parent registry. Only
|
|
103
|
+
* events for tools whose `scope` matches this view's scope are delivered.
|
|
104
|
+
*/
|
|
105
|
+
addEventListener<K extends keyof ToolRegistryEventMap>(type: K, listener: ToolRegistryListener<K>): void;
|
|
106
|
+
/** Unsubscribe a previously registered listener. */
|
|
107
|
+
removeEventListener<K extends keyof ToolRegistryEventMap>(type: K, listener: ToolRegistryListener<K>): void;
|
|
108
|
+
private ensureParentSubscription;
|
|
77
109
|
}
|
|
110
|
+
export {};
|
package/dist/tool.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
// Copyright 2026 Andre Cipriani Bandarra
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
class ToolRegistryEventEmitter {
|
|
4
|
+
registered = new Set();
|
|
5
|
+
unregistered = new Set();
|
|
6
|
+
on(type, listener) {
|
|
7
|
+
this.bucket(type).add(listener);
|
|
8
|
+
}
|
|
9
|
+
off(type, listener) {
|
|
10
|
+
this.bucket(type).delete(listener);
|
|
11
|
+
}
|
|
12
|
+
emit(type, event) {
|
|
13
|
+
for (const listener of [...this.bucket(type)])
|
|
14
|
+
listener(event);
|
|
15
|
+
}
|
|
16
|
+
// The cast is contained here: each generic call resolves `K` to one of the
|
|
17
|
+
// literal keys, and the matching bucket has a compatible listener type.
|
|
18
|
+
bucket(type) {
|
|
19
|
+
return (type === 'tool-registered' ? this.registered : this.unregistered);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
3
22
|
/** Holds all tools available to an {@link AgentRunner} and resolves them by name during execution. */
|
|
4
23
|
export class ToolRegistry {
|
|
5
24
|
_tools = new Map();
|
|
25
|
+
_emitter = new ToolRegistryEventEmitter();
|
|
6
26
|
/**
|
|
7
27
|
* Registers a tool. Throws if a tool with the same name is already registered.
|
|
8
28
|
* Returns `this` for chaining.
|
|
@@ -13,11 +33,14 @@ export class ToolRegistry {
|
|
|
13
33
|
throw new Error(`Tool '${name}' is already registered.`);
|
|
14
34
|
}
|
|
15
35
|
this._tools.set(name, tool);
|
|
36
|
+
this._emitter.emit('tool-registered', { tool });
|
|
16
37
|
return this;
|
|
17
38
|
}
|
|
18
39
|
/** Removes the tool registered under `name`. No-op if not found. */
|
|
19
40
|
unregister(name) {
|
|
20
|
-
this._tools.delete(name)
|
|
41
|
+
if (!this._tools.delete(name))
|
|
42
|
+
return;
|
|
43
|
+
this._emitter.emit('tool-unregistered', { name });
|
|
21
44
|
}
|
|
22
45
|
/** Returns the tool registered under `name`, or `undefined` if not found. */
|
|
23
46
|
getTool(name) {
|
|
@@ -31,6 +54,14 @@ export class ToolRegistry {
|
|
|
31
54
|
readOnly() {
|
|
32
55
|
return new ToolRegistryView(this, 'read');
|
|
33
56
|
}
|
|
57
|
+
/** Subscribe to registry mutation events. */
|
|
58
|
+
addEventListener(type, listener) {
|
|
59
|
+
this._emitter.on(type, listener);
|
|
60
|
+
}
|
|
61
|
+
/** Unsubscribe a previously registered listener. */
|
|
62
|
+
removeEventListener(type, listener) {
|
|
63
|
+
this._emitter.off(type, listener);
|
|
64
|
+
}
|
|
34
65
|
}
|
|
35
66
|
/**
|
|
36
67
|
* A live filtered projection of a {@link ToolRegistry}.
|
|
@@ -41,6 +72,8 @@ export class ToolRegistry {
|
|
|
41
72
|
export class ToolRegistryView {
|
|
42
73
|
parent;
|
|
43
74
|
scope;
|
|
75
|
+
_emitter = new ToolRegistryEventEmitter();
|
|
76
|
+
_scopedNames;
|
|
44
77
|
constructor(parent, scope) {
|
|
45
78
|
this.parent = parent;
|
|
46
79
|
this.scope = scope;
|
|
@@ -54,4 +87,38 @@ export class ToolRegistryView {
|
|
|
54
87
|
return undefined;
|
|
55
88
|
return tool.definition().scope === this.scope ? tool : undefined;
|
|
56
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Subscribe to mutation events forwarded from the parent registry. Only
|
|
92
|
+
* events for tools whose `scope` matches this view's scope are delivered.
|
|
93
|
+
*/
|
|
94
|
+
addEventListener(type, listener) {
|
|
95
|
+
this.ensureParentSubscription();
|
|
96
|
+
this._emitter.on(type, listener);
|
|
97
|
+
}
|
|
98
|
+
/** Unsubscribe a previously registered listener. */
|
|
99
|
+
removeEventListener(type, listener) {
|
|
100
|
+
this._emitter.off(type, listener);
|
|
101
|
+
}
|
|
102
|
+
ensureParentSubscription() {
|
|
103
|
+
if (this._scopedNames)
|
|
104
|
+
return;
|
|
105
|
+
const scoped = new Set();
|
|
106
|
+
for (const def of this.parent.getTools()) {
|
|
107
|
+
if (def.scope === this.scope)
|
|
108
|
+
scoped.add(def.name);
|
|
109
|
+
}
|
|
110
|
+
this._scopedNames = scoped;
|
|
111
|
+
this.parent.addEventListener('tool-registered', (event) => {
|
|
112
|
+
const def = event.tool.definition();
|
|
113
|
+
if (def.scope !== this.scope)
|
|
114
|
+
return;
|
|
115
|
+
scoped.add(def.name);
|
|
116
|
+
this._emitter.emit('tool-registered', event);
|
|
117
|
+
});
|
|
118
|
+
this.parent.addEventListener('tool-unregistered', (event) => {
|
|
119
|
+
if (!scoped.delete(event.name))
|
|
120
|
+
return;
|
|
121
|
+
this._emitter.emit('tool-unregistered', event);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
57
124
|
}
|