@push.rocks/smartagent 1.7.0 → 3.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.
Files changed (81) hide show
  1. package/dist_ts/00_commitinfo_data.js +3 -3
  2. package/dist_ts/index.d.ts +9 -12
  3. package/dist_ts/index.js +9 -20
  4. package/dist_ts/plugins.d.ts +8 -9
  5. package/dist_ts/plugins.js +10 -12
  6. package/dist_ts/smartagent.classes.agent.d.ts +2 -0
  7. package/dist_ts/smartagent.classes.agent.js +173 -0
  8. package/dist_ts/smartagent.classes.toolregistry.d.ts +12 -0
  9. package/dist_ts/smartagent.classes.toolregistry.js +17 -0
  10. package/dist_ts/smartagent.interfaces.d.ts +47 -231
  11. package/dist_ts/smartagent.interfaces.js +6 -7
  12. package/dist_ts/smartagent.utils.truncation.d.ts +10 -0
  13. package/dist_ts/smartagent.utils.truncation.js +26 -0
  14. package/dist_ts_compaction/index.d.ts +1 -0
  15. package/dist_ts_compaction/index.js +2 -0
  16. package/dist_ts_compaction/plugins.d.ts +4 -0
  17. package/dist_ts_compaction/plugins.js +3 -0
  18. package/dist_ts_compaction/smartagent.compaction.d.ts +10 -0
  19. package/dist_ts_compaction/smartagent.compaction.js +46 -0
  20. package/dist_ts_tools/index.d.ts +8 -0
  21. package/dist_ts_tools/index.js +6 -0
  22. package/dist_ts_tools/plugins.d.ts +15 -0
  23. package/dist_ts_tools/plugins.js +19 -0
  24. package/dist_ts_tools/tool.filesystem.d.ts +6 -0
  25. package/dist_ts_tools/tool.filesystem.js +102 -0
  26. package/dist_ts_tools/tool.http.d.ts +2 -0
  27. package/dist_ts_tools/tool.http.js +65 -0
  28. package/dist_ts_tools/tool.json.d.ts +2 -0
  29. package/dist_ts_tools/tool.json.js +47 -0
  30. package/dist_ts_tools/tool.shell.d.ts +8 -0
  31. package/dist_ts_tools/tool.shell.js +40 -0
  32. package/npmextra.json +1 -1
  33. package/package.json +30 -18
  34. package/readme.hints.md +43 -42
  35. package/readme.md +257 -526
  36. package/ts/00_commitinfo_data.ts +2 -2
  37. package/ts/index.ts +11 -31
  38. package/ts/plugins.ts +22 -21
  39. package/ts/smartagent.classes.agent.ts +198 -0
  40. package/ts/smartagent.classes.toolregistry.ts +20 -0
  41. package/ts/smartagent.interfaces.ts +51 -303
  42. package/ts/smartagent.utils.truncation.ts +39 -0
  43. package/ts_compaction/index.ts +1 -0
  44. package/ts_compaction/plugins.ts +6 -0
  45. package/ts_compaction/smartagent.compaction.ts +51 -0
  46. package/ts_tools/index.ts +8 -0
  47. package/ts_tools/plugins.ts +30 -0
  48. package/ts_tools/tool.filesystem.ts +131 -0
  49. package/ts_tools/tool.http.ts +78 -0
  50. package/ts_tools/tool.json.ts +53 -0
  51. package/ts_tools/tool.shell.ts +62 -0
  52. package/dist_ts/smartagent.classes.driveragent.d.ts +0 -134
  53. package/dist_ts/smartagent.classes.driveragent.js +0 -671
  54. package/dist_ts/smartagent.classes.dualagent.d.ts +0 -79
  55. package/dist_ts/smartagent.classes.dualagent.js +0 -583
  56. package/dist_ts/smartagent.classes.guardianagent.d.ts +0 -46
  57. package/dist_ts/smartagent.classes.guardianagent.js +0 -201
  58. package/dist_ts/smartagent.tools.base.d.ts +0 -52
  59. package/dist_ts/smartagent.tools.base.js +0 -42
  60. package/dist_ts/smartagent.tools.browser.d.ts +0 -17
  61. package/dist_ts/smartagent.tools.browser.js +0 -229
  62. package/dist_ts/smartagent.tools.deno.d.ts +0 -21
  63. package/dist_ts/smartagent.tools.deno.js +0 -191
  64. package/dist_ts/smartagent.tools.filesystem.d.ts +0 -40
  65. package/dist_ts/smartagent.tools.filesystem.js +0 -801
  66. package/dist_ts/smartagent.tools.http.d.ts +0 -16
  67. package/dist_ts/smartagent.tools.http.js +0 -264
  68. package/dist_ts/smartagent.tools.json.d.ts +0 -24
  69. package/dist_ts/smartagent.tools.json.js +0 -202
  70. package/dist_ts/smartagent.tools.shell.d.ts +0 -17
  71. package/dist_ts/smartagent.tools.shell.js +0 -202
  72. package/ts/smartagent.classes.driveragent.ts +0 -775
  73. package/ts/smartagent.classes.dualagent.ts +0 -657
  74. package/ts/smartagent.classes.guardianagent.ts +0 -241
  75. package/ts/smartagent.tools.base.ts +0 -83
  76. package/ts/smartagent.tools.browser.ts +0 -253
  77. package/ts/smartagent.tools.deno.ts +0 -230
  78. package/ts/smartagent.tools.filesystem.ts +0 -885
  79. package/ts/smartagent.tools.http.ts +0 -283
  80. package/ts/smartagent.tools.json.ts +0 -224
  81. package/ts/smartagent.tools.shell.ts +0 -230
@@ -1,241 +0,0 @@
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
- /**
6
- * GuardianAgent - Evaluates tool call proposals against a policy
7
- * Uses AI reasoning to approve or reject tool calls
8
- */
9
- export class GuardianAgent {
10
- private provider: plugins.smartai.MultiModalModel;
11
- private policyPrompt: string;
12
- private tools: Map<string, BaseToolWrapper> = new Map();
13
-
14
- constructor(
15
- provider: plugins.smartai.MultiModalModel,
16
- policyPrompt: string
17
- ) {
18
- this.provider = provider;
19
- this.policyPrompt = policyPrompt;
20
- }
21
-
22
- /**
23
- * Register a tool for reference during evaluation
24
- */
25
- public registerTool(tool: BaseToolWrapper): void {
26
- this.tools.set(tool.name, tool);
27
- }
28
-
29
- /**
30
- * Evaluate a tool call proposal against the policy
31
- */
32
- public async evaluate(
33
- proposal: interfaces.IToolCallProposal,
34
- taskContext: string
35
- ): Promise<interfaces.IGuardianDecision> {
36
- // Get the tool to generate a human-readable summary
37
- const tool = this.tools.get(proposal.toolName);
38
- let callSummary = `${proposal.toolName}.${proposal.action}(${JSON.stringify(proposal.params)})`;
39
-
40
- if (tool) {
41
- try {
42
- callSummary = tool.getCallSummary(proposal.action, proposal.params);
43
- } catch {
44
- // Fallback to basic summary
45
- }
46
- }
47
-
48
- // Build the evaluation prompt
49
- const evaluationPrompt = this.buildEvaluationPrompt(
50
- proposal,
51
- callSummary,
52
- taskContext
53
- );
54
-
55
- // Get response from provider
56
- const response = await this.provider.chat({
57
- systemMessage: this.buildGuardianSystemMessage(),
58
- userMessage: evaluationPrompt,
59
- messageHistory: [],
60
- });
61
-
62
- // Parse the decision from the response
63
- return this.parseDecision(response.message, proposal);
64
- }
65
-
66
- /**
67
- * Build the system message for the Guardian
68
- */
69
- private buildGuardianSystemMessage(): string {
70
- return `You are a Guardian AI responsible for evaluating tool call proposals.
71
-
72
- ## Your Role
73
- You evaluate whether proposed tool calls are safe and aligned with the policy.
74
-
75
- ## Policy to Enforce
76
- ${this.policyPrompt}
77
-
78
- ## Response Format
79
- For EVERY evaluation, respond with a decision in this exact format:
80
-
81
- <guardian_decision>
82
- <decision>approve OR reject</decision>
83
- <reason>Your detailed explanation</reason>
84
- <concerns>List any concerns, even if approving</concerns>
85
- <suggestions>Alternative approaches if rejecting</suggestions>
86
- </guardian_decision>
87
-
88
- ## Guidelines
89
- 1. Carefully analyze what the tool call will do
90
- 2. Consider security implications
91
- 3. Check against the policy requirements
92
- 4. If uncertain, err on the side of caution (reject)
93
- 5. Provide actionable feedback when rejecting`;
94
- }
95
-
96
- /**
97
- * Build the evaluation prompt for a specific proposal
98
- */
99
- private buildEvaluationPrompt(
100
- proposal: interfaces.IToolCallProposal,
101
- callSummary: string,
102
- taskContext: string
103
- ): string {
104
- const toolInfo = this.tools.get(proposal.toolName);
105
- const toolDescription = toolInfo ? toolInfo.getFullDescription() : 'Unknown tool';
106
-
107
- return `## Task Context
108
- ${taskContext}
109
-
110
- ## Tool Being Used
111
- ${toolDescription}
112
-
113
- ## Proposed Tool Call
114
- - **Tool**: ${proposal.toolName}
115
- - **Action**: ${proposal.action}
116
- - **Parameters**: ${JSON.stringify(proposal.params, null, 2)}
117
-
118
- ## Human-Readable Summary
119
- ${callSummary}
120
-
121
- ## Driver's Reasoning
122
- ${proposal.reasoning || 'No reasoning provided'}
123
-
124
- ---
125
-
126
- Evaluate this tool call against the policy. Should it be approved or rejected?`;
127
- }
128
-
129
- /**
130
- * Parse the guardian decision from the response
131
- */
132
- private parseDecision(
133
- response: string,
134
- proposal: interfaces.IToolCallProposal
135
- ): interfaces.IGuardianDecision {
136
- // Try to extract from XML tags
137
- const decisionMatch = response.match(/<decision>(.*?)<\/decision>/s);
138
- const reasonMatch = response.match(/<reason>([\s\S]*?)<\/reason>/);
139
- const concernsMatch = response.match(/<concerns>([\s\S]*?)<\/concerns>/);
140
- const suggestionsMatch = response.match(/<suggestions>([\s\S]*?)<\/suggestions>/);
141
-
142
- // Determine decision
143
- let decision: 'approve' | 'reject' = 'reject';
144
- if (decisionMatch) {
145
- const decisionText = decisionMatch[1].trim().toLowerCase();
146
- decision = decisionText.includes('approve') ? 'approve' : 'reject';
147
- } else {
148
- // Fallback: look for approval keywords in the response
149
- const lowerResponse = response.toLowerCase();
150
- if (
151
- lowerResponse.includes('approved') ||
152
- lowerResponse.includes('i approve') ||
153
- lowerResponse.includes('looks safe')
154
- ) {
155
- decision = 'approve';
156
- }
157
- }
158
-
159
- // Extract reason
160
- let reason = reasonMatch ? reasonMatch[1].trim() : '';
161
- if (!reason) {
162
- // Use the full response as reason if no tag found
163
- reason = response.substring(0, 500);
164
- }
165
-
166
- // Extract concerns
167
- const concerns: string[] = [];
168
- if (concernsMatch) {
169
- const concernsText = concernsMatch[1].trim();
170
- if (concernsText && concernsText.toLowerCase() !== 'none') {
171
- // Split by newlines or bullet points
172
- const concernLines = concernsText.split(/[\n\r]+/).map(l => l.trim()).filter(l => l);
173
- concerns.push(...concernLines);
174
- }
175
- }
176
-
177
- // Extract suggestions
178
- const suggestions = suggestionsMatch ? suggestionsMatch[1].trim() : undefined;
179
-
180
- return {
181
- decision,
182
- reason,
183
- concerns: concerns.length > 0 ? concerns : undefined,
184
- suggestions: suggestions && suggestions.toLowerCase() !== 'none' ? suggestions : undefined,
185
- };
186
- }
187
-
188
- /**
189
- * Quick validation without AI (for obviously safe/unsafe operations)
190
- * Returns null if AI evaluation is needed
191
- */
192
- public quickValidate(proposal: interfaces.IToolCallProposal): interfaces.IGuardianDecision | null {
193
- // Check if tool exists
194
- if (!this.tools.has(proposal.toolName)) {
195
- return {
196
- decision: 'reject',
197
- reason: `Unknown tool: ${proposal.toolName}`,
198
- };
199
- }
200
-
201
- // Check if action exists
202
- const tool = this.tools.get(proposal.toolName)!;
203
- const validAction = tool.actions.find(a => a.name === proposal.action);
204
- if (!validAction) {
205
- return {
206
- decision: 'reject',
207
- reason: `Unknown action "${proposal.action}" for tool "${proposal.toolName}". Available actions: ${tool.actions.map(a => a.name).join(', ')}`,
208
- };
209
- }
210
-
211
- // Check required parameters
212
- const schema = validAction.parameters;
213
- if (schema && schema.required && Array.isArray(schema.required)) {
214
- for (const requiredParam of schema.required as string[]) {
215
- if (!(requiredParam in proposal.params)) {
216
- return {
217
- decision: 'reject',
218
- reason: `Missing required parameter: ${requiredParam}`,
219
- };
220
- }
221
- }
222
- }
223
-
224
- // Needs full AI evaluation
225
- return null;
226
- }
227
-
228
- /**
229
- * Update the policy prompt
230
- */
231
- public setPolicy(policyPrompt: string): void {
232
- this.policyPrompt = policyPrompt;
233
- }
234
-
235
- /**
236
- * Get current policy
237
- */
238
- public getPolicy(): string {
239
- return this.policyPrompt;
240
- }
241
- }
@@ -1,83 +0,0 @@
1
- import * as interfaces from './smartagent.interfaces.js';
2
-
3
- /**
4
- * Abstract base class for tool wrappers
5
- * All tool implementations should extend this class
6
- */
7
- export abstract class BaseToolWrapper implements interfaces.IAgentToolWrapper {
8
- abstract name: string;
9
- abstract description: string;
10
- abstract actions: interfaces.IToolAction[];
11
-
12
- protected isInitialized = false;
13
-
14
- /**
15
- * Initialize the tool and any required resources
16
- */
17
- abstract initialize(): Promise<void>;
18
-
19
- /**
20
- * Cleanup any resources used by the tool
21
- */
22
- abstract cleanup(): Promise<void>;
23
-
24
- /**
25
- * Execute an action with the given parameters
26
- */
27
- abstract execute(
28
- action: string,
29
- params: Record<string, unknown>
30
- ): Promise<interfaces.IToolExecutionResult>;
31
-
32
- /**
33
- * Generate a human-readable summary of what the action will do
34
- * This is used by the Guardian to understand the proposed action
35
- */
36
- abstract getCallSummary(action: string, params: Record<string, unknown>): string;
37
-
38
- /**
39
- * Get a comprehensive explanation of this tool for LLM consumption.
40
- * Tools should implement this to provide detailed usage instructions with examples.
41
- * This includes parameter schemas and concrete <tool_call> XML examples.
42
- */
43
- abstract getToolExplanation(): string;
44
-
45
- /**
46
- * Validate that an action exists for this tool
47
- * @throws Error if the action is not valid
48
- */
49
- protected validateAction(action: string): void {
50
- const validAction = this.actions.find((a) => a.name === action);
51
- if (!validAction) {
52
- const availableActions = this.actions.map((a) => a.name).join(', ');
53
- throw new Error(
54
- `Unknown action "${action}" for tool "${this.name}". Available actions: ${availableActions}`
55
- );
56
- }
57
- }
58
-
59
- /**
60
- * Check if the tool is initialized
61
- */
62
- protected ensureInitialized(): void {
63
- if (!this.isInitialized) {
64
- throw new Error(`Tool "${this.name}" is not initialized. Call initialize() first.`);
65
- }
66
- }
67
-
68
- /**
69
- * Get the full tool description including all actions
70
- * Used for Driver's tool awareness - now delegates to getToolExplanation()
71
- */
72
- public getFullDescription(): string {
73
- return this.getToolExplanation();
74
- }
75
-
76
- /**
77
- * Get the JSON schema for a specific action
78
- */
79
- public getActionSchema(action: string): Record<string, unknown> | undefined {
80
- const actionDef = this.actions.find((a) => a.name === action);
81
- return actionDef?.parameters;
82
- }
83
- }
@@ -1,253 +0,0 @@
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
- /**
6
- * Browser tool for web page interaction
7
- * Wraps @push.rocks/smartbrowser (Puppeteer-based)
8
- */
9
- export class BrowserTool extends BaseToolWrapper {
10
- public name = 'browser';
11
- public description =
12
- 'Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages';
13
-
14
- public actions: interfaces.IToolAction[] = [
15
- {
16
- name: 'screenshot',
17
- description: 'Take a screenshot of a webpage',
18
- parameters: {
19
- type: 'object',
20
- properties: {
21
- url: { type: 'string', description: 'URL of the page to screenshot' },
22
- },
23
- required: ['url'],
24
- },
25
- },
26
- {
27
- name: 'pdf',
28
- description: 'Generate a PDF from a webpage',
29
- parameters: {
30
- type: 'object',
31
- properties: {
32
- url: { type: 'string', description: 'URL of the page to convert to PDF' },
33
- },
34
- required: ['url'],
35
- },
36
- },
37
- {
38
- name: 'evaluate',
39
- description:
40
- 'Execute JavaScript code on a webpage and return the result. The script runs in the browser context.',
41
- parameters: {
42
- type: 'object',
43
- properties: {
44
- url: { type: 'string', description: 'URL of the page to run the script on' },
45
- script: {
46
- type: 'string',
47
- description:
48
- 'JavaScript code to execute. Must be a valid expression or statements that return a value.',
49
- },
50
- },
51
- required: ['url', 'script'],
52
- },
53
- },
54
- {
55
- name: 'getPageContent',
56
- description: 'Get the text content and title of a webpage',
57
- parameters: {
58
- type: 'object',
59
- properties: {
60
- url: { type: 'string', description: 'URL of the page to get content from' },
61
- },
62
- required: ['url'],
63
- },
64
- },
65
- ];
66
-
67
- private smartbrowser!: plugins.smartbrowser.SmartBrowser;
68
-
69
- public async initialize(): Promise<void> {
70
- this.smartbrowser = new plugins.smartbrowser.SmartBrowser();
71
- await this.smartbrowser.start();
72
- this.isInitialized = true;
73
- }
74
-
75
- public async cleanup(): Promise<void> {
76
- if (this.smartbrowser) {
77
- await this.smartbrowser.stop();
78
- }
79
- this.isInitialized = false;
80
- }
81
-
82
- public async execute(
83
- action: string,
84
- params: Record<string, unknown>
85
- ): Promise<interfaces.IToolExecutionResult> {
86
- this.validateAction(action);
87
- this.ensureInitialized();
88
-
89
- try {
90
- switch (action) {
91
- case 'screenshot': {
92
- const result = await this.smartbrowser.screenshotFromPage(params.url as string);
93
- return {
94
- success: true,
95
- result: {
96
- url: params.url,
97
- name: result.name,
98
- id: result.id,
99
- bufferBase64: Buffer.from(result.buffer).toString('base64'),
100
- bufferLength: result.buffer.length,
101
- type: 'screenshot',
102
- },
103
- };
104
- }
105
-
106
- case 'pdf': {
107
- const result = await this.smartbrowser.pdfFromPage(params.url as string);
108
- return {
109
- success: true,
110
- result: {
111
- url: params.url,
112
- name: result.name,
113
- id: result.id,
114
- bufferBase64: Buffer.from(result.buffer).toString('base64'),
115
- bufferLength: result.buffer.length,
116
- type: 'pdf',
117
- },
118
- };
119
- }
120
-
121
- case 'evaluate': {
122
- const script = params.script as string;
123
- // Create an async function from the script
124
- // The script should be valid JavaScript that returns a value
125
- const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => {
126
- // This runs in the browser context
127
- // We need to evaluate the script string dynamically
128
- // eslint-disable-next-line no-eval
129
- return eval(script);
130
- });
131
-
132
- return {
133
- success: true,
134
- result: {
135
- url: params.url,
136
- script: script.substring(0, 200) + (script.length > 200 ? '...' : ''),
137
- evaluationResult: result,
138
- },
139
- };
140
- }
141
-
142
- case 'getPageContent': {
143
- const result = await this.smartbrowser.evaluateOnPage(params.url as string, async () => {
144
- return {
145
- title: document.title,
146
- textContent: document.body?.innerText || '',
147
- url: window.location.href,
148
- };
149
- });
150
-
151
- return {
152
- success: true,
153
- result: {
154
- url: params.url,
155
- title: result.title,
156
- textContent:
157
- result.textContent.length > 10000
158
- ? result.textContent.substring(0, 10000) + '... [truncated]'
159
- : result.textContent,
160
- actualUrl: result.url,
161
- },
162
- };
163
- }
164
-
165
- default:
166
- return {
167
- success: false,
168
- error: `Unknown action: ${action}`,
169
- };
170
- }
171
- } catch (error) {
172
- return {
173
- success: false,
174
- error: error instanceof Error ? error.message : String(error),
175
- };
176
- }
177
- }
178
-
179
- public getToolExplanation(): string {
180
- return `## Tool: browser
181
- Interact with web pages - take screenshots, generate PDFs, and execute JavaScript on pages.
182
-
183
- ### Actions:
184
-
185
- **screenshot** - Take a screenshot of a webpage
186
- Parameters:
187
- - url (required): URL of the page to screenshot
188
-
189
- Example:
190
- <tool_call>
191
- <tool>browser</tool>
192
- <action>screenshot</action>
193
- <params>{"url": "https://example.com"}</params>
194
- </tool_call>
195
-
196
- **pdf** - Generate a PDF from a webpage
197
- Parameters:
198
- - url (required): URL of the page to convert to PDF
199
-
200
- Example:
201
- <tool_call>
202
- <tool>browser</tool>
203
- <action>pdf</action>
204
- <params>{"url": "https://example.com/report"}</params>
205
- </tool_call>
206
-
207
- **evaluate** - Execute JavaScript code on a webpage and return the result
208
- Parameters:
209
- - url (required): URL of the page to run the script on
210
- - script (required): JavaScript code to execute (must return a value)
211
-
212
- Example:
213
- <tool_call>
214
- <tool>browser</tool>
215
- <action>evaluate</action>
216
- <params>{"url": "https://example.com", "script": "document.querySelectorAll('a').length"}</params>
217
- </tool_call>
218
-
219
- **getPageContent** - Get the text content and title of a webpage
220
- Parameters:
221
- - url (required): URL of the page to get content from
222
-
223
- Example:
224
- <tool_call>
225
- <tool>browser</tool>
226
- <action>getPageContent</action>
227
- <params>{"url": "https://example.com"}</params>
228
- </tool_call>
229
- `;
230
- }
231
-
232
- public getCallSummary(action: string, params: Record<string, unknown>): string {
233
- switch (action) {
234
- case 'screenshot':
235
- return `Take screenshot of "${params.url}"`;
236
-
237
- case 'pdf':
238
- return `Generate PDF from "${params.url}"`;
239
-
240
- case 'evaluate': {
241
- const script = params.script as string;
242
- const preview = script.length > 100 ? script.substring(0, 100) + '...' : script;
243
- return `Execute JavaScript on "${params.url}": "${preview}"`;
244
- }
245
-
246
- case 'getPageContent':
247
- return `Get text content and title from "${params.url}"`;
248
-
249
- default:
250
- return `Unknown action: ${action}`;
251
- }
252
- }
253
- }