@push.rocks/smartagent 1.7.0 → 1.8.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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +3 -0
- package/dist_ts/index.js +6 -1
- package/dist_ts/smartagent.classes.dualagent.d.ts +17 -3
- package/dist_ts/smartagent.classes.dualagent.js +57 -26
- package/dist_ts/smartagent.classes.toolregistry.d.ts +75 -0
- package/dist_ts/smartagent.classes.toolregistry.js +161 -0
- package/dist_ts/smartagent.interfaces.d.ts +52 -0
- package/dist_ts/smartagent.interfaces.js +1 -1
- package/dist_ts/smartagent.tools.expert.d.ts +27 -0
- package/dist_ts/smartagent.tools.expert.js +126 -0
- package/dist_ts/smartagent.tools.search.d.ts +29 -0
- package/dist_ts/smartagent.tools.search.js +215 -0
- package/package.json +1 -1
- package/readme.hints.md +47 -0
- package/readme.md +167 -8
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +7 -0
- package/ts/smartagent.classes.dualagent.ts +63 -28
- package/ts/smartagent.classes.toolregistry.ts +188 -0
- package/ts/smartagent.interfaces.ts +60 -0
- package/ts/smartagent.tools.expert.ts +144 -0
- package/ts/smartagent.tools.search.ts +237 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as interfaces from './smartagent.interfaces.js';
|
|
3
|
+
import { BaseToolWrapper } from './smartagent.tools.base.js';
|
|
4
|
+
|
|
5
|
+
// Forward declaration to avoid circular import at module load time
|
|
6
|
+
// The actual import happens lazily in initialize()
|
|
7
|
+
let DualAgentOrchestrator: typeof import('./smartagent.classes.dualagent.js').DualAgentOrchestrator;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* ExpertTool - A specialized agent wrapped as a tool
|
|
11
|
+
*
|
|
12
|
+
* Enables hierarchical agent architectures where the Driver can delegate
|
|
13
|
+
* complex tasks to specialized experts with their own tools and policies.
|
|
14
|
+
*/
|
|
15
|
+
export class ExpertTool extends BaseToolWrapper {
|
|
16
|
+
public name: string;
|
|
17
|
+
public description: string;
|
|
18
|
+
public actions: interfaces.IToolAction[] = [
|
|
19
|
+
{
|
|
20
|
+
name: 'consult',
|
|
21
|
+
description: 'Delegate a task or question to this expert',
|
|
22
|
+
parameters: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
task: { type: 'string', description: 'The task or question for the expert' },
|
|
26
|
+
context: { type: 'string', description: 'Additional context to help the expert' },
|
|
27
|
+
},
|
|
28
|
+
required: ['task'],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
private config: interfaces.IExpertConfig;
|
|
34
|
+
private smartAi: plugins.smartai.SmartAi;
|
|
35
|
+
private inner?: InstanceType<typeof DualAgentOrchestrator>;
|
|
36
|
+
|
|
37
|
+
constructor(config: interfaces.IExpertConfig, smartAi: plugins.smartai.SmartAi) {
|
|
38
|
+
super();
|
|
39
|
+
this.config = config;
|
|
40
|
+
this.smartAi = smartAi;
|
|
41
|
+
this.name = config.name;
|
|
42
|
+
this.description = config.description;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async initialize(): Promise<void> {
|
|
46
|
+
// Lazy import to avoid circular dependency
|
|
47
|
+
if (!DualAgentOrchestrator) {
|
|
48
|
+
const module = await import('./smartagent.classes.dualagent.js');
|
|
49
|
+
DualAgentOrchestrator = module.DualAgentOrchestrator;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.inner = new DualAgentOrchestrator({
|
|
53
|
+
smartAiInstance: this.smartAi, // Share SmartAi instance
|
|
54
|
+
defaultProvider: this.config.provider,
|
|
55
|
+
driverSystemMessage: this.config.systemMessage,
|
|
56
|
+
guardianPolicyPrompt: this.config.guardianPolicy,
|
|
57
|
+
maxIterations: this.config.maxIterations ?? 10,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Register expert's tools
|
|
61
|
+
if (this.config.tools) {
|
|
62
|
+
for (const tool of this.config.tools) {
|
|
63
|
+
// Tools in the config are IAgentToolWrapper, but we need BaseToolWrapper
|
|
64
|
+
// Since all our tools extend BaseToolWrapper, this cast is safe
|
|
65
|
+
this.inner.registerTool(tool as BaseToolWrapper);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await this.inner.start();
|
|
70
|
+
this.isInitialized = true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async cleanup(): Promise<void> {
|
|
74
|
+
if (this.inner) {
|
|
75
|
+
await this.inner.stop();
|
|
76
|
+
this.inner = undefined;
|
|
77
|
+
}
|
|
78
|
+
this.isInitialized = false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async execute(
|
|
82
|
+
action: string,
|
|
83
|
+
params: Record<string, unknown>
|
|
84
|
+
): Promise<interfaces.IToolExecutionResult> {
|
|
85
|
+
this.validateAction(action);
|
|
86
|
+
this.ensureInitialized();
|
|
87
|
+
|
|
88
|
+
const task = params.task as string;
|
|
89
|
+
const context = params.context as string | undefined;
|
|
90
|
+
|
|
91
|
+
const fullTask = context ? `Context: ${context}\n\nTask: ${task}` : task;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const result = await this.inner!.run(fullTask);
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
success: result.success,
|
|
98
|
+
result: {
|
|
99
|
+
response: result.result,
|
|
100
|
+
iterations: result.iterations,
|
|
101
|
+
status: result.status,
|
|
102
|
+
},
|
|
103
|
+
summary: result.success
|
|
104
|
+
? `Expert "${this.name}" completed (${result.iterations} iterations)`
|
|
105
|
+
: `Expert "${this.name}" failed: ${result.status}`,
|
|
106
|
+
};
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return {
|
|
109
|
+
success: false,
|
|
110
|
+
error: `Expert error: ${error instanceof Error ? error.message : String(error)}`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getCallSummary(action: string, params: Record<string, unknown>): string {
|
|
116
|
+
const task = params.task as string;
|
|
117
|
+
const preview = task.length > 60 ? task.substring(0, 60) + '...' : task;
|
|
118
|
+
return `Consult ${this.name}: "${preview}"`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
getToolExplanation(): string {
|
|
122
|
+
return `## Expert: ${this.name}
|
|
123
|
+
${this.description}
|
|
124
|
+
|
|
125
|
+
### Usage:
|
|
126
|
+
Delegate tasks to this expert when you need specialized help.
|
|
127
|
+
|
|
128
|
+
\`\`\`
|
|
129
|
+
<tool_call>
|
|
130
|
+
<tool>${this.name}</tool>
|
|
131
|
+
<action>consult</action>
|
|
132
|
+
<params>{"task": "Your question or task", "context": "Optional background"}</params>
|
|
133
|
+
</tool_call>
|
|
134
|
+
\`\`\`
|
|
135
|
+
`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get the expert's configuration
|
|
140
|
+
*/
|
|
141
|
+
getConfig(): interfaces.IExpertConfig {
|
|
142
|
+
return this.config;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import * as interfaces from './smartagent.interfaces.js';
|
|
2
|
+
import { BaseToolWrapper } from './smartagent.tools.base.js';
|
|
3
|
+
import { ToolRegistry } from './smartagent.classes.toolregistry.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ToolSearchTool - AI-facing interface for discovering and activating tools
|
|
7
|
+
*
|
|
8
|
+
* This tool enables the Driver to:
|
|
9
|
+
* - Search for tools by capability
|
|
10
|
+
* - List all available tools
|
|
11
|
+
* - Activate on-demand tools
|
|
12
|
+
* - Get detailed information about specific tools
|
|
13
|
+
*/
|
|
14
|
+
export class ToolSearchTool extends BaseToolWrapper {
|
|
15
|
+
public name = 'tools';
|
|
16
|
+
public description =
|
|
17
|
+
'Search for and activate available tools and experts. Use this to discover specialized capabilities.';
|
|
18
|
+
|
|
19
|
+
public actions: interfaces.IToolAction[] = [
|
|
20
|
+
{
|
|
21
|
+
name: 'search',
|
|
22
|
+
description: 'Search for tools by name, description, tags, or capabilities',
|
|
23
|
+
parameters: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
query: { type: 'string', description: 'Search query' },
|
|
27
|
+
},
|
|
28
|
+
required: ['query'],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'list',
|
|
33
|
+
description: 'List all available tools grouped by visibility',
|
|
34
|
+
parameters: { type: 'object', properties: {} },
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'activate',
|
|
38
|
+
description: 'Activate an on-demand tool to make it available for use',
|
|
39
|
+
parameters: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
name: { type: 'string', description: 'Name of the tool to activate' },
|
|
43
|
+
},
|
|
44
|
+
required: ['name'],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'details',
|
|
49
|
+
description: 'Get detailed information about a specific tool',
|
|
50
|
+
parameters: {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
name: { type: 'string', description: 'Name of the tool' },
|
|
54
|
+
},
|
|
55
|
+
required: ['name'],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
private registry: ToolRegistry;
|
|
61
|
+
private onToolActivated?: (tool: BaseToolWrapper) => void;
|
|
62
|
+
|
|
63
|
+
constructor(registry: ToolRegistry, onToolActivated?: (tool: BaseToolWrapper) => void) {
|
|
64
|
+
super();
|
|
65
|
+
this.registry = registry;
|
|
66
|
+
this.onToolActivated = onToolActivated;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async initialize(): Promise<void> {
|
|
70
|
+
this.isInitialized = true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async cleanup(): Promise<void> {
|
|
74
|
+
this.isInitialized = false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async execute(
|
|
78
|
+
action: string,
|
|
79
|
+
params: Record<string, unknown>
|
|
80
|
+
): Promise<interfaces.IToolExecutionResult> {
|
|
81
|
+
this.validateAction(action);
|
|
82
|
+
|
|
83
|
+
switch (action) {
|
|
84
|
+
case 'search':
|
|
85
|
+
return this.handleSearch(params.query as string);
|
|
86
|
+
case 'list':
|
|
87
|
+
return this.handleList();
|
|
88
|
+
case 'activate':
|
|
89
|
+
return this.handleActivate(params.name as string);
|
|
90
|
+
case 'details':
|
|
91
|
+
return this.handleDetails(params.name as string);
|
|
92
|
+
default:
|
|
93
|
+
return { success: false, error: `Unknown action: ${action}` };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private handleSearch(query: string): interfaces.IToolExecutionResult {
|
|
98
|
+
const results = this.registry.search(query);
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
result: results.map((m) => ({
|
|
102
|
+
name: m.name,
|
|
103
|
+
description: m.description,
|
|
104
|
+
visibility: m.visibility,
|
|
105
|
+
isActivated: m.isActivated,
|
|
106
|
+
category: m.category,
|
|
107
|
+
tags: m.tags,
|
|
108
|
+
actionCount: m.actions.length,
|
|
109
|
+
})),
|
|
110
|
+
summary: `Found ${results.length} tools matching "${query}"`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private handleList(): interfaces.IToolExecutionResult {
|
|
115
|
+
const all = this.registry.getAllMetadata();
|
|
116
|
+
const initial = all.filter((m) => m.visibility === 'initial');
|
|
117
|
+
const onDemand = all.filter((m) => m.visibility === 'on-demand');
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
success: true,
|
|
121
|
+
result: {
|
|
122
|
+
initial: initial.map((m) => ({
|
|
123
|
+
name: m.name,
|
|
124
|
+
description: m.description,
|
|
125
|
+
category: m.category,
|
|
126
|
+
})),
|
|
127
|
+
onDemand: onDemand.map((m) => ({
|
|
128
|
+
name: m.name,
|
|
129
|
+
description: m.description,
|
|
130
|
+
category: m.category,
|
|
131
|
+
isActivated: m.isActivated,
|
|
132
|
+
})),
|
|
133
|
+
summary: `${initial.length} initial, ${onDemand.length} on-demand`,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private async handleActivate(name: string): Promise<interfaces.IToolExecutionResult> {
|
|
139
|
+
const result = await this.registry.activate(name);
|
|
140
|
+
|
|
141
|
+
if (result.success && this.onToolActivated) {
|
|
142
|
+
const tool = this.registry.getTool(name);
|
|
143
|
+
if (tool) {
|
|
144
|
+
this.onToolActivated(tool);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
success: result.success,
|
|
150
|
+
result: result.success ? { name, message: `Tool "${name}" is now available` } : undefined,
|
|
151
|
+
error: result.error,
|
|
152
|
+
summary: result.success ? `Activated: ${name}` : result.error,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private handleDetails(name: string): interfaces.IToolExecutionResult {
|
|
157
|
+
const tool = this.registry.getTool(name);
|
|
158
|
+
const meta = this.registry.getMetadata(name);
|
|
159
|
+
|
|
160
|
+
if (!tool || !meta) {
|
|
161
|
+
return { success: false, error: `Tool "${name}" not found` };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
success: true,
|
|
166
|
+
result: {
|
|
167
|
+
name: meta.name,
|
|
168
|
+
description: meta.description,
|
|
169
|
+
visibility: meta.visibility,
|
|
170
|
+
isActivated: meta.isActivated,
|
|
171
|
+
category: meta.category,
|
|
172
|
+
tags: meta.tags,
|
|
173
|
+
actions: meta.actions,
|
|
174
|
+
fullExplanation: tool.getToolExplanation(),
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getCallSummary(action: string, params: Record<string, unknown>): string {
|
|
180
|
+
switch (action) {
|
|
181
|
+
case 'search':
|
|
182
|
+
return `Search tools: "${params.query}"`;
|
|
183
|
+
case 'list':
|
|
184
|
+
return 'List all tools';
|
|
185
|
+
case 'activate':
|
|
186
|
+
return `Activate tool: ${params.name}`;
|
|
187
|
+
case 'details':
|
|
188
|
+
return `Get details: ${params.name}`;
|
|
189
|
+
default:
|
|
190
|
+
return `tools.${action}`;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
getToolExplanation(): string {
|
|
195
|
+
return `## Tool: tools
|
|
196
|
+
Search for and manage available tools and experts.
|
|
197
|
+
|
|
198
|
+
### Actions:
|
|
199
|
+
|
|
200
|
+
**search** - Find tools by capability
|
|
201
|
+
\`\`\`
|
|
202
|
+
<tool_call>
|
|
203
|
+
<tool>tools</tool>
|
|
204
|
+
<action>search</action>
|
|
205
|
+
<params>{"query": "database"}</params>
|
|
206
|
+
</tool_call>
|
|
207
|
+
\`\`\`
|
|
208
|
+
|
|
209
|
+
**list** - List all tools grouped by visibility
|
|
210
|
+
\`\`\`
|
|
211
|
+
<tool_call>
|
|
212
|
+
<tool>tools</tool>
|
|
213
|
+
<action>list</action>
|
|
214
|
+
<params>{}</params>
|
|
215
|
+
</tool_call>
|
|
216
|
+
\`\`\`
|
|
217
|
+
|
|
218
|
+
**activate** - Activate an on-demand tool
|
|
219
|
+
\`\`\`
|
|
220
|
+
<tool_call>
|
|
221
|
+
<tool>tools</tool>
|
|
222
|
+
<action>activate</action>
|
|
223
|
+
<params>{"name": "database_expert"}</params>
|
|
224
|
+
</tool_call>
|
|
225
|
+
\`\`\`
|
|
226
|
+
|
|
227
|
+
**details** - Get full information about a tool
|
|
228
|
+
\`\`\`
|
|
229
|
+
<tool_call>
|
|
230
|
+
<tool>tools</tool>
|
|
231
|
+
<action>details</action>
|
|
232
|
+
<params>{"name": "filesystem"}</params>
|
|
233
|
+
</tool_call>
|
|
234
|
+
\`\`\`
|
|
235
|
+
`;
|
|
236
|
+
}
|
|
237
|
+
}
|