@push.rocks/smartagent 1.0.2
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.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/index.d.ts +10 -0
- package/dist_ts/index.js +18 -0
- package/dist_ts/plugins.d.ts +6 -0
- package/dist_ts/plugins.js +8 -0
- package/dist_ts/smartagent.classes.driveragent.d.ts +70 -0
- package/dist_ts/smartagent.classes.driveragent.js +274 -0
- package/dist_ts/smartagent.classes.dualagent.d.ts +62 -0
- package/dist_ts/smartagent.classes.dualagent.js +298 -0
- package/dist_ts/smartagent.classes.guardianagent.d.ts +46 -0
- package/dist_ts/smartagent.classes.guardianagent.js +201 -0
- package/dist_ts/smartagent.classes.smartagent.d.ts +123 -0
- package/dist_ts/smartagent.classes.smartagent.js +274 -0
- package/dist_ts/smartagent.interfaces.d.ts +165 -0
- package/dist_ts/smartagent.interfaces.js +8 -0
- package/dist_ts/smartagent.tools.base.d.ts +46 -0
- package/dist_ts/smartagent.tools.base.js +45 -0
- package/dist_ts/smartagent.tools.browser.d.ts +16 -0
- package/dist_ts/smartagent.tools.browser.js +177 -0
- package/dist_ts/smartagent.tools.filesystem.d.ts +16 -0
- package/dist_ts/smartagent.tools.filesystem.js +352 -0
- package/dist_ts/smartagent.tools.http.d.ts +15 -0
- package/dist_ts/smartagent.tools.http.js +187 -0
- package/dist_ts/smartagent.tools.shell.d.ts +16 -0
- package/dist_ts/smartagent.tools.shell.js +155 -0
- package/npmextra.json +18 -0
- package/package.json +50 -0
- package/readme.hints.md +16 -0
- package/readme.md +299 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +29 -0
- package/ts/plugins.ts +14 -0
- package/ts/smartagent.classes.driveragent.ts +321 -0
- package/ts/smartagent.classes.dualagent.ts +350 -0
- package/ts/smartagent.classes.guardianagent.ts +241 -0
- package/ts/smartagent.interfaces.ts +210 -0
- package/ts/smartagent.tools.base.ts +80 -0
- package/ts/smartagent.tools.browser.ts +200 -0
- package/ts/smartagent.tools.filesystem.ts +379 -0
- package/ts/smartagent.tools.http.ts +205 -0
- package/ts/smartagent.tools.shell.ts +182 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as interfaces from './smartagent.interfaces.js';
|
|
3
|
+
import { BaseToolWrapper } from './smartagent.tools.base.js';
|
|
4
|
+
import { DriverAgent } from './smartagent.classes.driveragent.js';
|
|
5
|
+
import { GuardianAgent } from './smartagent.classes.guardianagent.js';
|
|
6
|
+
import { FilesystemTool } from './smartagent.tools.filesystem.js';
|
|
7
|
+
import { HttpTool } from './smartagent.tools.http.js';
|
|
8
|
+
import { ShellTool } from './smartagent.tools.shell.js';
|
|
9
|
+
import { BrowserTool } from './smartagent.tools.browser.js';
|
|
10
|
+
/**
|
|
11
|
+
* DualAgentOrchestrator - Coordinates Driver and Guardian agents
|
|
12
|
+
* Manages the complete lifecycle of task execution with tool approval
|
|
13
|
+
*/
|
|
14
|
+
export class DualAgentOrchestrator {
|
|
15
|
+
options;
|
|
16
|
+
smartai;
|
|
17
|
+
driverProvider;
|
|
18
|
+
guardianProvider;
|
|
19
|
+
driver;
|
|
20
|
+
guardian;
|
|
21
|
+
tools = new Map();
|
|
22
|
+
isRunning = false;
|
|
23
|
+
conversationHistory = [];
|
|
24
|
+
constructor(options) {
|
|
25
|
+
this.options = {
|
|
26
|
+
maxIterations: 20,
|
|
27
|
+
maxConsecutiveRejections: 3,
|
|
28
|
+
defaultProvider: 'openai',
|
|
29
|
+
...options,
|
|
30
|
+
};
|
|
31
|
+
// Create SmartAi instance
|
|
32
|
+
this.smartai = new plugins.smartai.SmartAi(options);
|
|
33
|
+
// Get providers
|
|
34
|
+
this.driverProvider = this.getProviderByName(this.options.defaultProvider);
|
|
35
|
+
this.guardianProvider = this.options.guardianProvider
|
|
36
|
+
? this.getProviderByName(this.options.guardianProvider)
|
|
37
|
+
: this.driverProvider;
|
|
38
|
+
// Create agents
|
|
39
|
+
this.driver = new DriverAgent(this.driverProvider, options.driverSystemMessage);
|
|
40
|
+
this.guardian = new GuardianAgent(this.guardianProvider, options.guardianPolicyPrompt);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get provider by name
|
|
44
|
+
*/
|
|
45
|
+
getProviderByName(providerName) {
|
|
46
|
+
switch (providerName) {
|
|
47
|
+
case 'openai':
|
|
48
|
+
return this.smartai.openaiProvider;
|
|
49
|
+
case 'anthropic':
|
|
50
|
+
return this.smartai.anthropicProvider;
|
|
51
|
+
case 'perplexity':
|
|
52
|
+
return this.smartai.perplexityProvider;
|
|
53
|
+
case 'ollama':
|
|
54
|
+
return this.smartai.ollamaProvider;
|
|
55
|
+
case 'groq':
|
|
56
|
+
return this.smartai.groqProvider;
|
|
57
|
+
case 'xai':
|
|
58
|
+
return this.smartai.xaiProvider;
|
|
59
|
+
case 'exo':
|
|
60
|
+
return this.smartai.exoProvider;
|
|
61
|
+
default:
|
|
62
|
+
return this.smartai.openaiProvider;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Register a custom tool
|
|
67
|
+
*/
|
|
68
|
+
registerTool(tool) {
|
|
69
|
+
this.tools.set(tool.name, tool);
|
|
70
|
+
this.driver.registerTool(tool);
|
|
71
|
+
this.guardian.registerTool(tool);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Register all standard tools
|
|
75
|
+
*/
|
|
76
|
+
registerStandardTools() {
|
|
77
|
+
const standardTools = [
|
|
78
|
+
new FilesystemTool(),
|
|
79
|
+
new HttpTool(),
|
|
80
|
+
new ShellTool(),
|
|
81
|
+
new BrowserTool(),
|
|
82
|
+
];
|
|
83
|
+
for (const tool of standardTools) {
|
|
84
|
+
this.registerTool(tool);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Initialize all tools (eager loading)
|
|
89
|
+
*/
|
|
90
|
+
async start() {
|
|
91
|
+
// Start smartai
|
|
92
|
+
await this.smartai.start();
|
|
93
|
+
// Initialize all tools
|
|
94
|
+
const initPromises = [];
|
|
95
|
+
for (const tool of this.tools.values()) {
|
|
96
|
+
initPromises.push(tool.initialize());
|
|
97
|
+
}
|
|
98
|
+
await Promise.all(initPromises);
|
|
99
|
+
this.isRunning = true;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Cleanup all tools
|
|
103
|
+
*/
|
|
104
|
+
async stop() {
|
|
105
|
+
const cleanupPromises = [];
|
|
106
|
+
for (const tool of this.tools.values()) {
|
|
107
|
+
cleanupPromises.push(tool.cleanup());
|
|
108
|
+
}
|
|
109
|
+
await Promise.all(cleanupPromises);
|
|
110
|
+
await this.smartai.stop();
|
|
111
|
+
this.isRunning = false;
|
|
112
|
+
this.driver.reset();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Run a task through the dual-agent system
|
|
116
|
+
*/
|
|
117
|
+
async run(task) {
|
|
118
|
+
if (!this.isRunning) {
|
|
119
|
+
throw new Error('Orchestrator not started. Call start() first.');
|
|
120
|
+
}
|
|
121
|
+
this.conversationHistory = [];
|
|
122
|
+
let iterations = 0;
|
|
123
|
+
let consecutiveRejections = 0;
|
|
124
|
+
let completed = false;
|
|
125
|
+
let finalResult = null;
|
|
126
|
+
// Add initial task to history
|
|
127
|
+
this.conversationHistory.push({
|
|
128
|
+
role: 'user',
|
|
129
|
+
content: task,
|
|
130
|
+
});
|
|
131
|
+
// Start the driver with the task
|
|
132
|
+
let driverResponse = await this.driver.startTask(task);
|
|
133
|
+
this.conversationHistory.push(driverResponse);
|
|
134
|
+
while (iterations < this.options.maxIterations &&
|
|
135
|
+
consecutiveRejections < this.options.maxConsecutiveRejections &&
|
|
136
|
+
!completed) {
|
|
137
|
+
iterations++;
|
|
138
|
+
// Check if task is complete
|
|
139
|
+
if (this.driver.isTaskComplete(driverResponse.content)) {
|
|
140
|
+
completed = true;
|
|
141
|
+
finalResult = this.driver.extractTaskResult(driverResponse.content) || driverResponse.content;
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
// Check if driver needs clarification
|
|
145
|
+
if (this.driver.needsClarification(driverResponse.content)) {
|
|
146
|
+
// Return with clarification needed status
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
completed: false,
|
|
150
|
+
result: driverResponse.content,
|
|
151
|
+
iterations,
|
|
152
|
+
history: this.conversationHistory,
|
|
153
|
+
status: 'clarification_needed',
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// Parse tool call proposals
|
|
157
|
+
const proposals = this.driver.parseToolCallProposals(driverResponse.content);
|
|
158
|
+
if (proposals.length === 0) {
|
|
159
|
+
// No tool calls, continue the conversation
|
|
160
|
+
driverResponse = await this.driver.continueWithMessage('Please either use a tool to make progress on the task, or indicate that the task is complete with <task_complete>summary</task_complete>.');
|
|
161
|
+
this.conversationHistory.push(driverResponse);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
// Process the first proposal (one at a time)
|
|
165
|
+
const proposal = proposals[0];
|
|
166
|
+
// Quick validation first
|
|
167
|
+
const quickDecision = this.guardian.quickValidate(proposal);
|
|
168
|
+
let decision;
|
|
169
|
+
if (quickDecision) {
|
|
170
|
+
decision = quickDecision;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// Full AI evaluation
|
|
174
|
+
decision = await this.guardian.evaluate(proposal, task);
|
|
175
|
+
}
|
|
176
|
+
if (decision.decision === 'approve') {
|
|
177
|
+
consecutiveRejections = 0;
|
|
178
|
+
// Execute the tool
|
|
179
|
+
const tool = this.tools.get(proposal.toolName);
|
|
180
|
+
if (!tool) {
|
|
181
|
+
const errorMessage = `Tool "${proposal.toolName}" not found.`;
|
|
182
|
+
driverResponse = await this.driver.continueWithMessage(`TOOL ERROR: ${errorMessage}\n\nPlease try a different approach.`);
|
|
183
|
+
this.conversationHistory.push(driverResponse);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
const result = await tool.execute(proposal.action, proposal.params);
|
|
188
|
+
// Send result to driver
|
|
189
|
+
const resultMessage = result.success
|
|
190
|
+
? `TOOL RESULT (${proposal.toolName}.${proposal.action}):\n${JSON.stringify(result.result, null, 2)}`
|
|
191
|
+
: `TOOL ERROR (${proposal.toolName}.${proposal.action}):\n${result.error}`;
|
|
192
|
+
this.conversationHistory.push({
|
|
193
|
+
role: 'system',
|
|
194
|
+
content: resultMessage,
|
|
195
|
+
toolCall: proposal,
|
|
196
|
+
toolResult: result,
|
|
197
|
+
});
|
|
198
|
+
driverResponse = await this.driver.continueWithMessage(resultMessage);
|
|
199
|
+
this.conversationHistory.push(driverResponse);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
const errorMessage = `Tool execution failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
203
|
+
driverResponse = await this.driver.continueWithMessage(`TOOL ERROR: ${errorMessage}\n\nPlease try a different approach.`);
|
|
204
|
+
this.conversationHistory.push(driverResponse);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// Rejected
|
|
209
|
+
consecutiveRejections++;
|
|
210
|
+
// Build rejection feedback
|
|
211
|
+
let feedback = `TOOL CALL REJECTED by Guardian:\n`;
|
|
212
|
+
feedback += `- Reason: ${decision.reason}\n`;
|
|
213
|
+
if (decision.concerns && decision.concerns.length > 0) {
|
|
214
|
+
feedback += `- Concerns:\n${decision.concerns.map(c => ` - ${c}`).join('\n')}\n`;
|
|
215
|
+
}
|
|
216
|
+
if (decision.suggestions) {
|
|
217
|
+
feedback += `- Suggestions: ${decision.suggestions}\n`;
|
|
218
|
+
}
|
|
219
|
+
feedback += `\nPlease adapt your approach based on this feedback.`;
|
|
220
|
+
this.conversationHistory.push({
|
|
221
|
+
role: 'system',
|
|
222
|
+
content: feedback,
|
|
223
|
+
toolCall: proposal,
|
|
224
|
+
guardianDecision: decision,
|
|
225
|
+
});
|
|
226
|
+
driverResponse = await this.driver.continueWithMessage(feedback);
|
|
227
|
+
this.conversationHistory.push(driverResponse);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Determine final status
|
|
231
|
+
let status = 'completed';
|
|
232
|
+
if (!completed) {
|
|
233
|
+
if (iterations >= this.options.maxIterations) {
|
|
234
|
+
status = 'max_iterations_reached';
|
|
235
|
+
}
|
|
236
|
+
else if (consecutiveRejections >= this.options.maxConsecutiveRejections) {
|
|
237
|
+
status = 'max_rejections_reached';
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
success: completed,
|
|
242
|
+
completed,
|
|
243
|
+
result: finalResult || driverResponse.content,
|
|
244
|
+
iterations,
|
|
245
|
+
history: this.conversationHistory,
|
|
246
|
+
status,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Continue an existing task with user input
|
|
251
|
+
*/
|
|
252
|
+
async continueTask(userInput) {
|
|
253
|
+
if (!this.isRunning) {
|
|
254
|
+
throw new Error('Orchestrator not started. Call start() first.');
|
|
255
|
+
}
|
|
256
|
+
this.conversationHistory.push({
|
|
257
|
+
role: 'user',
|
|
258
|
+
content: userInput,
|
|
259
|
+
});
|
|
260
|
+
const driverResponse = await this.driver.continueWithMessage(userInput);
|
|
261
|
+
this.conversationHistory.push(driverResponse);
|
|
262
|
+
// Continue the run loop
|
|
263
|
+
// For simplicity, we return the current state - full continuation would need refactoring
|
|
264
|
+
return {
|
|
265
|
+
success: false,
|
|
266
|
+
completed: false,
|
|
267
|
+
result: driverResponse.content,
|
|
268
|
+
iterations: 1,
|
|
269
|
+
history: this.conversationHistory,
|
|
270
|
+
status: 'in_progress',
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get the conversation history
|
|
275
|
+
*/
|
|
276
|
+
getHistory() {
|
|
277
|
+
return [...this.conversationHistory];
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Update the guardian policy
|
|
281
|
+
*/
|
|
282
|
+
setGuardianPolicy(policyPrompt) {
|
|
283
|
+
this.guardian.setPolicy(policyPrompt);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Check if orchestrator is running
|
|
287
|
+
*/
|
|
288
|
+
isActive() {
|
|
289
|
+
return this.isRunning;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Get registered tool names
|
|
293
|
+
*/
|
|
294
|
+
getToolNames() {
|
|
295
|
+
return Array.from(this.tools.keys());
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhZ2VudC5jbGFzc2VzLmR1YWxhZ2VudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0YWdlbnQuY2xhc3Nlcy5kdWFsYWdlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLFVBQVUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFNUQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLHFCQUFxQjtJQUN4QixPQUFPLENBQStCO0lBQ3RDLE9BQU8sQ0FBMEI7SUFDakMsY0FBYyxDQUFrQztJQUNoRCxnQkFBZ0IsQ0FBa0M7SUFDbEQsTUFBTSxDQUFjO0lBQ3BCLFFBQVEsQ0FBZ0I7SUFDeEIsS0FBSyxHQUFpQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2hELFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsbUJBQW1CLEdBQStCLEVBQUUsQ0FBQztJQUU3RCxZQUFZLE9BQXFDO1FBQy9DLElBQUksQ0FBQyxPQUFPLEdBQUc7WUFDYixhQUFhLEVBQUUsRUFBRTtZQUNqQix3QkFBd0IsRUFBRSxDQUFDO1lBQzNCLGVBQWUsRUFBRSxRQUFRO1lBQ3pCLEdBQUcsT0FBTztTQUNYLENBQUM7UUFFRiwwQkFBMEI7UUFDMUIs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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as interfaces from './smartagent.interfaces.js';
|
|
3
|
+
import type { BaseToolWrapper } from './smartagent.tools.base.js';
|
|
4
|
+
/**
|
|
5
|
+
* GuardianAgent - Evaluates tool call proposals against a policy
|
|
6
|
+
* Uses AI reasoning to approve or reject tool calls
|
|
7
|
+
*/
|
|
8
|
+
export declare class GuardianAgent {
|
|
9
|
+
private provider;
|
|
10
|
+
private policyPrompt;
|
|
11
|
+
private tools;
|
|
12
|
+
constructor(provider: plugins.smartai.MultiModalModel, policyPrompt: string);
|
|
13
|
+
/**
|
|
14
|
+
* Register a tool for reference during evaluation
|
|
15
|
+
*/
|
|
16
|
+
registerTool(tool: BaseToolWrapper): void;
|
|
17
|
+
/**
|
|
18
|
+
* Evaluate a tool call proposal against the policy
|
|
19
|
+
*/
|
|
20
|
+
evaluate(proposal: interfaces.IToolCallProposal, taskContext: string): Promise<interfaces.IGuardianDecision>;
|
|
21
|
+
/**
|
|
22
|
+
* Build the system message for the Guardian
|
|
23
|
+
*/
|
|
24
|
+
private buildGuardianSystemMessage;
|
|
25
|
+
/**
|
|
26
|
+
* Build the evaluation prompt for a specific proposal
|
|
27
|
+
*/
|
|
28
|
+
private buildEvaluationPrompt;
|
|
29
|
+
/**
|
|
30
|
+
* Parse the guardian decision from the response
|
|
31
|
+
*/
|
|
32
|
+
private parseDecision;
|
|
33
|
+
/**
|
|
34
|
+
* Quick validation without AI (for obviously safe/unsafe operations)
|
|
35
|
+
* Returns null if AI evaluation is needed
|
|
36
|
+
*/
|
|
37
|
+
quickValidate(proposal: interfaces.IToolCallProposal): interfaces.IGuardianDecision | null;
|
|
38
|
+
/**
|
|
39
|
+
* Update the policy prompt
|
|
40
|
+
*/
|
|
41
|
+
setPolicy(policyPrompt: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get current policy
|
|
44
|
+
*/
|
|
45
|
+
getPolicy(): string;
|
|
46
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as interfaces from './smartagent.interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* GuardianAgent - Evaluates tool call proposals against a policy
|
|
5
|
+
* Uses AI reasoning to approve or reject tool calls
|
|
6
|
+
*/
|
|
7
|
+
export class GuardianAgent {
|
|
8
|
+
provider;
|
|
9
|
+
policyPrompt;
|
|
10
|
+
tools = new Map();
|
|
11
|
+
constructor(provider, policyPrompt) {
|
|
12
|
+
this.provider = provider;
|
|
13
|
+
this.policyPrompt = policyPrompt;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Register a tool for reference during evaluation
|
|
17
|
+
*/
|
|
18
|
+
registerTool(tool) {
|
|
19
|
+
this.tools.set(tool.name, tool);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Evaluate a tool call proposal against the policy
|
|
23
|
+
*/
|
|
24
|
+
async evaluate(proposal, taskContext) {
|
|
25
|
+
// Get the tool to generate a human-readable summary
|
|
26
|
+
const tool = this.tools.get(proposal.toolName);
|
|
27
|
+
let callSummary = `${proposal.toolName}.${proposal.action}(${JSON.stringify(proposal.params)})`;
|
|
28
|
+
if (tool) {
|
|
29
|
+
try {
|
|
30
|
+
callSummary = tool.getCallSummary(proposal.action, proposal.params);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Fallback to basic summary
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Build the evaluation prompt
|
|
37
|
+
const evaluationPrompt = this.buildEvaluationPrompt(proposal, callSummary, taskContext);
|
|
38
|
+
// Get response from provider
|
|
39
|
+
const response = await this.provider.chat({
|
|
40
|
+
systemMessage: this.buildGuardianSystemMessage(),
|
|
41
|
+
userMessage: evaluationPrompt,
|
|
42
|
+
messageHistory: [],
|
|
43
|
+
});
|
|
44
|
+
// Parse the decision from the response
|
|
45
|
+
return this.parseDecision(response.message, proposal);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build the system message for the Guardian
|
|
49
|
+
*/
|
|
50
|
+
buildGuardianSystemMessage() {
|
|
51
|
+
return `You are a Guardian AI responsible for evaluating tool call proposals.
|
|
52
|
+
|
|
53
|
+
## Your Role
|
|
54
|
+
You evaluate whether proposed tool calls are safe and aligned with the policy.
|
|
55
|
+
|
|
56
|
+
## Policy to Enforce
|
|
57
|
+
${this.policyPrompt}
|
|
58
|
+
|
|
59
|
+
## Response Format
|
|
60
|
+
For EVERY evaluation, respond with a decision in this exact format:
|
|
61
|
+
|
|
62
|
+
<guardian_decision>
|
|
63
|
+
<decision>approve OR reject</decision>
|
|
64
|
+
<reason>Your detailed explanation</reason>
|
|
65
|
+
<concerns>List any concerns, even if approving</concerns>
|
|
66
|
+
<suggestions>Alternative approaches if rejecting</suggestions>
|
|
67
|
+
</guardian_decision>
|
|
68
|
+
|
|
69
|
+
## Guidelines
|
|
70
|
+
1. Carefully analyze what the tool call will do
|
|
71
|
+
2. Consider security implications
|
|
72
|
+
3. Check against the policy requirements
|
|
73
|
+
4. If uncertain, err on the side of caution (reject)
|
|
74
|
+
5. Provide actionable feedback when rejecting`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build the evaluation prompt for a specific proposal
|
|
78
|
+
*/
|
|
79
|
+
buildEvaluationPrompt(proposal, callSummary, taskContext) {
|
|
80
|
+
const toolInfo = this.tools.get(proposal.toolName);
|
|
81
|
+
const toolDescription = toolInfo ? toolInfo.getFullDescription() : 'Unknown tool';
|
|
82
|
+
return `## Task Context
|
|
83
|
+
${taskContext}
|
|
84
|
+
|
|
85
|
+
## Tool Being Used
|
|
86
|
+
${toolDescription}
|
|
87
|
+
|
|
88
|
+
## Proposed Tool Call
|
|
89
|
+
- **Tool**: ${proposal.toolName}
|
|
90
|
+
- **Action**: ${proposal.action}
|
|
91
|
+
- **Parameters**: ${JSON.stringify(proposal.params, null, 2)}
|
|
92
|
+
|
|
93
|
+
## Human-Readable Summary
|
|
94
|
+
${callSummary}
|
|
95
|
+
|
|
96
|
+
## Driver's Reasoning
|
|
97
|
+
${proposal.reasoning || 'No reasoning provided'}
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
Evaluate this tool call against the policy. Should it be approved or rejected?`;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Parse the guardian decision from the response
|
|
105
|
+
*/
|
|
106
|
+
parseDecision(response, proposal) {
|
|
107
|
+
// Try to extract from XML tags
|
|
108
|
+
const decisionMatch = response.match(/<decision>(.*?)<\/decision>/s);
|
|
109
|
+
const reasonMatch = response.match(/<reason>([\s\S]*?)<\/reason>/);
|
|
110
|
+
const concernsMatch = response.match(/<concerns>([\s\S]*?)<\/concerns>/);
|
|
111
|
+
const suggestionsMatch = response.match(/<suggestions>([\s\S]*?)<\/suggestions>/);
|
|
112
|
+
// Determine decision
|
|
113
|
+
let decision = 'reject';
|
|
114
|
+
if (decisionMatch) {
|
|
115
|
+
const decisionText = decisionMatch[1].trim().toLowerCase();
|
|
116
|
+
decision = decisionText.includes('approve') ? 'approve' : 'reject';
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Fallback: look for approval keywords in the response
|
|
120
|
+
const lowerResponse = response.toLowerCase();
|
|
121
|
+
if (lowerResponse.includes('approved') ||
|
|
122
|
+
lowerResponse.includes('i approve') ||
|
|
123
|
+
lowerResponse.includes('looks safe')) {
|
|
124
|
+
decision = 'approve';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Extract reason
|
|
128
|
+
let reason = reasonMatch ? reasonMatch[1].trim() : '';
|
|
129
|
+
if (!reason) {
|
|
130
|
+
// Use the full response as reason if no tag found
|
|
131
|
+
reason = response.substring(0, 500);
|
|
132
|
+
}
|
|
133
|
+
// Extract concerns
|
|
134
|
+
const concerns = [];
|
|
135
|
+
if (concernsMatch) {
|
|
136
|
+
const concernsText = concernsMatch[1].trim();
|
|
137
|
+
if (concernsText && concernsText.toLowerCase() !== 'none') {
|
|
138
|
+
// Split by newlines or bullet points
|
|
139
|
+
const concernLines = concernsText.split(/[\n\r]+/).map(l => l.trim()).filter(l => l);
|
|
140
|
+
concerns.push(...concernLines);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Extract suggestions
|
|
144
|
+
const suggestions = suggestionsMatch ? suggestionsMatch[1].trim() : undefined;
|
|
145
|
+
return {
|
|
146
|
+
decision,
|
|
147
|
+
reason,
|
|
148
|
+
concerns: concerns.length > 0 ? concerns : undefined,
|
|
149
|
+
suggestions: suggestions && suggestions.toLowerCase() !== 'none' ? suggestions : undefined,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Quick validation without AI (for obviously safe/unsafe operations)
|
|
154
|
+
* Returns null if AI evaluation is needed
|
|
155
|
+
*/
|
|
156
|
+
quickValidate(proposal) {
|
|
157
|
+
// Check if tool exists
|
|
158
|
+
if (!this.tools.has(proposal.toolName)) {
|
|
159
|
+
return {
|
|
160
|
+
decision: 'reject',
|
|
161
|
+
reason: `Unknown tool: ${proposal.toolName}`,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
// Check if action exists
|
|
165
|
+
const tool = this.tools.get(proposal.toolName);
|
|
166
|
+
const validAction = tool.actions.find(a => a.name === proposal.action);
|
|
167
|
+
if (!validAction) {
|
|
168
|
+
return {
|
|
169
|
+
decision: 'reject',
|
|
170
|
+
reason: `Unknown action "${proposal.action}" for tool "${proposal.toolName}". Available actions: ${tool.actions.map(a => a.name).join(', ')}`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Check required parameters
|
|
174
|
+
const schema = validAction.parameters;
|
|
175
|
+
if (schema && schema.required && Array.isArray(schema.required)) {
|
|
176
|
+
for (const requiredParam of schema.required) {
|
|
177
|
+
if (!(requiredParam in proposal.params)) {
|
|
178
|
+
return {
|
|
179
|
+
decision: 'reject',
|
|
180
|
+
reason: `Missing required parameter: ${requiredParam}`,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Needs full AI evaluation
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Update the policy prompt
|
|
190
|
+
*/
|
|
191
|
+
setPolicy(policyPrompt) {
|
|
192
|
+
this.policyPrompt = policyPrompt;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get current policy
|
|
196
|
+
*/
|
|
197
|
+
getPolicy() {
|
|
198
|
+
return this.policyPrompt;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhZ2VudC5jbGFzc2VzLmd1YXJkaWFuYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydGFnZW50LmNsYXNzZXMuZ3VhcmRpYW5hZ2VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEtBQUssVUFBVSxNQUFNLDRCQUE0QixDQUFDO0FBR3pEOzs7R0FHRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBQ2hCLFFBQVEsQ0FBa0M7SUFDMUMsWUFBWSxDQUFTO0lBQ3JCLEtBQUssR0FBaUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUV4RCxZQUNFLFFBQXlDLEVBQ3pDLFlBQW9CO1FBRXBCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNJLFlBQVksQ0FBQyxJQUFxQjtRQUN2QyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxRQUFRLENBQ25CLFFBQXNDLEVBQ3RDLFdBQW1CO1FBRW5CLG9EQUFvRDtRQUNwRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0MsSUFBSSxXQUFXLEdBQUcsR0FBRyxRQUFRLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztRQUVoRyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ1QsSUFBSSxDQUFDO2dCQUNILFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FB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
|