@push.rocks/smartagent 1.2.7 → 1.4.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 (38) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/index.d.ts +1 -0
  3. package/dist_ts/index.js +2 -1
  4. package/dist_ts/smartagent.classes.driveragent.d.ts +11 -1
  5. package/dist_ts/smartagent.classes.driveragent.js +57 -16
  6. package/dist_ts/smartagent.classes.dualagent.d.ts +3 -1
  7. package/dist_ts/smartagent.classes.dualagent.js +13 -4
  8. package/dist_ts/smartagent.interfaces.d.ts +9 -0
  9. package/dist_ts/smartagent.interfaces.js +1 -1
  10. package/dist_ts/smartagent.tools.base.d.ts +7 -1
  11. package/dist_ts/smartagent.tools.base.js +3 -6
  12. package/dist_ts/smartagent.tools.browser.d.ts +1 -0
  13. package/dist_ts/smartagent.tools.browser.js +53 -1
  14. package/dist_ts/smartagent.tools.deno.d.ts +1 -0
  15. package/dist_ts/smartagent.tools.deno.js +39 -1
  16. package/dist_ts/smartagent.tools.filesystem.d.ts +1 -0
  17. package/dist_ts/smartagent.tools.filesystem.js +164 -1
  18. package/dist_ts/smartagent.tools.http.d.ts +1 -0
  19. package/dist_ts/smartagent.tools.http.js +78 -1
  20. package/dist_ts/smartagent.tools.json.d.ts +24 -0
  21. package/dist_ts/smartagent.tools.json.js +202 -0
  22. package/dist_ts/smartagent.tools.shell.d.ts +1 -0
  23. package/dist_ts/smartagent.tools.shell.js +48 -1
  24. package/package.json +2 -2
  25. package/readme.hints.md +29 -5
  26. package/readme.md +145 -9
  27. package/ts/00_commitinfo_data.ts +1 -1
  28. package/ts/index.ts +1 -0
  29. package/ts/smartagent.classes.driveragent.ts +59 -15
  30. package/ts/smartagent.classes.dualagent.ts +14 -3
  31. package/ts/smartagent.interfaces.ts +14 -0
  32. package/ts/smartagent.tools.base.ts +9 -6
  33. package/ts/smartagent.tools.browser.ts +53 -0
  34. package/ts/smartagent.tools.deno.ts +39 -0
  35. package/ts/smartagent.tools.filesystem.ts +164 -0
  36. package/ts/smartagent.tools.http.ts +78 -0
  37. package/ts/smartagent.tools.json.ts +224 -0
  38. package/ts/smartagent.tools.shell.ts +48 -0
@@ -10,6 +10,8 @@ export interface IDriverAgentOptions {
10
10
  systemMessage?: string;
11
11
  /** Maximum history messages to pass to API (default: 20). Set to 0 for unlimited. */
12
12
  maxHistoryMessages?: number;
13
+ /** Callback fired for each token during LLM generation */
14
+ onToken?: (token: string) => void;
13
15
  }
14
16
 
15
17
  /**
@@ -22,6 +24,7 @@ export class DriverAgent {
22
24
  private maxHistoryMessages: number;
23
25
  private messageHistory: plugins.smartai.ChatMessage[] = [];
24
26
  private tools: Map<string, BaseToolWrapper> = new Map();
27
+ private onToken?: (token: string) => void;
25
28
 
26
29
  constructor(
27
30
  provider: plugins.smartai.MultiModalModel,
@@ -36,9 +39,18 @@ export class DriverAgent {
36
39
  } else {
37
40
  this.systemMessage = options?.systemMessage || this.getDefaultSystemMessage();
38
41
  this.maxHistoryMessages = options?.maxHistoryMessages ?? 20;
42
+ this.onToken = options?.onToken;
39
43
  }
40
44
  }
41
45
 
46
+ /**
47
+ * Set the token callback for streaming mode
48
+ * @param callback Function to call for each generated token
49
+ */
50
+ public setOnToken(callback: (token: string) => void): void {
51
+ this.onToken = callback;
52
+ }
53
+
42
54
  /**
43
55
  * Register a tool for use by the driver
44
56
  */
@@ -55,8 +67,10 @@ export class DriverAgent {
55
67
 
56
68
  /**
57
69
  * Initialize a new conversation for a task
70
+ * @param task The task description
71
+ * @param images Optional base64-encoded images for vision tasks
58
72
  */
59
- public async startTask(task: string): Promise<interfaces.IAgentMessage> {
73
+ public async startTask(task: string, images?: string[]): Promise<interfaces.IAgentMessage> {
60
74
  // Reset message history
61
75
  this.messageHistory = [];
62
76
 
@@ -85,18 +99,34 @@ export class DriverAgent {
85
99
  fullSystemMessage = this.getNoToolsSystemMessage();
86
100
  }
87
101
 
88
- // Get response from provider
89
- const response = await this.provider.chat({
90
- systemMessage: fullSystemMessage,
91
- userMessage: userMessage,
92
- messageHistory: [],
93
- });
102
+ // Get response from provider - use streaming if available and callback is set
103
+ let response: plugins.smartai.ChatResponse;
104
+
105
+ if (this.onToken && typeof (this.provider as any).chatStreaming === 'function') {
106
+ // Use streaming mode with token callback
107
+ response = await (this.provider as any).chatStreaming({
108
+ systemMessage: fullSystemMessage,
109
+ userMessage: userMessage,
110
+ messageHistory: [],
111
+ images: images,
112
+ onToken: this.onToken,
113
+ });
114
+ } else {
115
+ // Fallback to non-streaming mode
116
+ response = await this.provider.chat({
117
+ systemMessage: fullSystemMessage,
118
+ userMessage: userMessage,
119
+ messageHistory: [],
120
+ images: images,
121
+ });
122
+ }
94
123
 
95
- // Add assistant response to history
96
- this.messageHistory.push({
124
+ // Add assistant response to history (store images if provided)
125
+ const historyMessage: plugins.smartai.ChatMessage = {
97
126
  role: 'assistant',
98
127
  content: response.message,
99
- });
128
+ };
129
+ this.messageHistory.push(historyMessage);
100
130
 
101
131
  return {
102
132
  role: 'assistant',
@@ -139,11 +169,25 @@ export class DriverAgent {
139
169
  historyForChat = fullHistory;
140
170
  }
141
171
 
142
- const response = await this.provider.chat({
143
- systemMessage: fullSystemMessage,
144
- userMessage: message,
145
- messageHistory: historyForChat,
146
- });
172
+ // Get response from provider - use streaming if available and callback is set
173
+ let response: plugins.smartai.ChatResponse;
174
+
175
+ if (this.onToken && typeof (this.provider as any).chatStreaming === 'function') {
176
+ // Use streaming mode with token callback
177
+ response = await (this.provider as any).chatStreaming({
178
+ systemMessage: fullSystemMessage,
179
+ userMessage: message,
180
+ messageHistory: historyForChat,
181
+ onToken: this.onToken,
182
+ });
183
+ } else {
184
+ // Fallback to non-streaming mode
185
+ response = await this.provider.chat({
186
+ systemMessage: fullSystemMessage,
187
+ userMessage: message,
188
+ messageHistory: historyForChat,
189
+ });
190
+ }
147
191
 
148
192
  // Add assistant response to history
149
193
  this.messageHistory.push({
@@ -181,9 +181,15 @@ export class DualAgentOrchestrator {
181
181
  : this.driverProvider;
182
182
 
183
183
  // NOW create agents with initialized providers
184
+ // Set up token callback wrapper if streaming is enabled
185
+ const driverOnToken = this.options.onToken
186
+ ? (token: string) => this.options.onToken!(token, 'driver')
187
+ : undefined;
188
+
184
189
  this.driver = new DriverAgent(this.driverProvider, {
185
190
  systemMessage: this.options.driverSystemMessage,
186
191
  maxHistoryMessages: this.options.maxHistoryMessages,
192
+ onToken: driverOnToken,
187
193
  });
188
194
  this.guardian = new GuardianAgent(this.guardianProvider, this.options.guardianPolicyPrompt);
189
195
 
@@ -228,8 +234,10 @@ export class DualAgentOrchestrator {
228
234
 
229
235
  /**
230
236
  * Run a task through the dual-agent system
237
+ * @param task The task description
238
+ * @param options Optional task run options (e.g., images for vision tasks)
231
239
  */
232
- public async run(task: string): Promise<interfaces.IDualAgentRunResult> {
240
+ public async run(task: string, options?: interfaces.ITaskRunOptions): Promise<interfaces.IDualAgentRunResult> {
233
241
  if (!this.isRunning) {
234
242
  throw new Error('Orchestrator not started. Call start() first.');
235
243
  }
@@ -240,14 +248,17 @@ export class DualAgentOrchestrator {
240
248
  let completed = false;
241
249
  let finalResult: string | null = null;
242
250
 
251
+ // Extract images from options
252
+ const images = options?.images;
253
+
243
254
  // Add initial task to history
244
255
  this.conversationHistory.push({
245
256
  role: 'user',
246
257
  content: task,
247
258
  });
248
259
 
249
- // Start the driver with the task
250
- let driverResponse = await this.driver.startTask(task);
260
+ // Start the driver with the task and optional images
261
+ let driverResponse = await this.driver.startTask(task, images);
251
262
  this.conversationHistory.push(driverResponse);
252
263
 
253
264
  // Emit task started event
@@ -1,5 +1,17 @@
1
1
  import * as plugins from './plugins.js';
2
2
 
3
+ // ================================
4
+ // Task Run Options
5
+ // ================================
6
+
7
+ /**
8
+ * Options for running a task with the DualAgentOrchestrator
9
+ */
10
+ export interface ITaskRunOptions {
11
+ /** Base64-encoded images to include with the task (for vision-capable models) */
12
+ images?: string[];
13
+ }
14
+
3
15
  // ================================
4
16
  // Agent Configuration Interfaces
5
17
  // ================================
@@ -34,6 +46,8 @@ export interface IDualAgentOptions extends plugins.smartai.ISmartAiOptions {
34
46
  onProgress?: (event: IProgressEvent) => void;
35
47
  /** Prefix for log messages (e.g., "[README]", "[Commit]"). Default: empty */
36
48
  logPrefix?: string;
49
+ /** Callback fired for each token during LLM generation (streaming mode) */
50
+ onToken?: (token: string, source: 'driver' | 'guardian') => void;
37
51
  }
38
52
 
39
53
  // ================================
@@ -35,6 +35,13 @@ export abstract class BaseToolWrapper implements interfaces.IAgentToolWrapper {
35
35
  */
36
36
  abstract getCallSummary(action: string, params: Record<string, unknown>): string;
37
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
+
38
45
  /**
39
46
  * Validate that an action exists for this tool
40
47
  * @throws Error if the action is not valid
@@ -60,14 +67,10 @@ export abstract class BaseToolWrapper implements interfaces.IAgentToolWrapper {
60
67
 
61
68
  /**
62
69
  * Get the full tool description including all actions
63
- * Used for Driver's tool awareness
70
+ * Used for Driver's tool awareness - now delegates to getToolExplanation()
64
71
  */
65
72
  public getFullDescription(): string {
66
- const actionDescriptions = this.actions
67
- .map((a) => ` - ${a.name}: ${a.description}`)
68
- .join('\n');
69
-
70
- return `${this.name}: ${this.description}\nActions:\n${actionDescriptions}`;
73
+ return this.getToolExplanation();
71
74
  }
72
75
 
73
76
  /**
@@ -176,6 +176,59 @@ export class BrowserTool extends BaseToolWrapper {
176
176
  }
177
177
  }
178
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
+
179
232
  public getCallSummary(action: string, params: Record<string, unknown>): string {
180
233
  switch (action) {
181
234
  case 'screenshot':
@@ -164,6 +164,45 @@ export class DenoTool extends BaseToolWrapper {
164
164
  }
165
165
  }
166
166
 
167
+ public getToolExplanation(): string {
168
+ return `## Tool: deno
169
+ Execute TypeScript/JavaScript code in a sandboxed Deno environment with fine-grained permission control.
170
+
171
+ ### Actions:
172
+
173
+ **execute** - Execute TypeScript/JavaScript code and return stdout/stderr
174
+ Parameters:
175
+ - code (required): TypeScript/JavaScript code to execute
176
+ - permissions (optional): Array of Deno permissions to grant. Options: "all", "env", "net", "read", "write", "run", "sys", "ffi", "hrtime". Default: none (fully sandboxed)
177
+
178
+ Example - Simple execution:
179
+ <tool_call>
180
+ <tool>deno</tool>
181
+ <action>execute</action>
182
+ <params>{"code": "console.log('Hello from Deno!');"}</params>
183
+ </tool_call>
184
+
185
+ Example - With network permission:
186
+ <tool_call>
187
+ <tool>deno</tool>
188
+ <action>execute</action>
189
+ <params>{"code": "const resp = await fetch('https://api.example.com/data');\\nconsole.log(await resp.text());", "permissions": ["net"]}</params>
190
+ </tool_call>
191
+
192
+ **executeWithResult** - Execute code that outputs JSON on the last line of stdout
193
+ Parameters:
194
+ - code (required): Code that console.logs a JSON value on the final line
195
+ - permissions (optional): Array of Deno permissions to grant
196
+
197
+ Example:
198
+ <tool_call>
199
+ <tool>deno</tool>
200
+ <action>executeWithResult</action>
201
+ <params>{"code": "const result = { sum: 1 + 2, product: 2 * 3 };\\nconsole.log(JSON.stringify(result));"}</params>
202
+ </tool_call>
203
+ `;
204
+ }
205
+
167
206
  public getCallSummary(action: string, params: Record<string, unknown>): string {
168
207
  const code = params.code as string;
169
208
  const permissions = (params.permissions as string[]) || [];
@@ -666,6 +666,170 @@ export class FilesystemTool extends BaseToolWrapper {
666
666
  }
667
667
  }
668
668
 
669
+ public getToolExplanation(): string {
670
+ return `## Tool: filesystem
671
+ Read, write, list, and delete files and directories.
672
+
673
+ ### Actions:
674
+
675
+ **read** - Read file contents (full or specific line range)
676
+ Parameters:
677
+ - path (required): Path to the file
678
+ - encoding (optional): File encoding - "utf8" (default), "binary", or "base64"
679
+ - startLine (optional): First line to read (1-indexed, inclusive)
680
+ - endLine (optional): Last line to read (1-indexed, inclusive)
681
+
682
+ Example:
683
+ <tool_call>
684
+ <tool>filesystem</tool>
685
+ <action>read</action>
686
+ <params>{"path": "/path/to/file.txt"}</params>
687
+ </tool_call>
688
+
689
+ Example with line range:
690
+ <tool_call>
691
+ <tool>filesystem</tool>
692
+ <action>read</action>
693
+ <params>{"path": "/path/to/file.txt", "startLine": 10, "endLine": 20}</params>
694
+ </tool_call>
695
+
696
+ **write** - Write content to a file (creates or overwrites)
697
+ Parameters:
698
+ - path (required): Absolute path to the file
699
+ - content (required): Content to write
700
+ - encoding (optional): File encoding - "utf8" (default), "binary", or "base64"
701
+
702
+ Example:
703
+ <tool_call>
704
+ <tool>filesystem</tool>
705
+ <action>write</action>
706
+ <params>{"path": "/path/to/output.txt", "content": "Hello, World!"}</params>
707
+ </tool_call>
708
+
709
+ **list** - List files and directories in a path
710
+ Parameters:
711
+ - path (required): Directory path to list
712
+ - recursive (optional): List recursively (default: false)
713
+ - filter (optional): Glob pattern to filter results (e.g., "*.ts")
714
+
715
+ Example:
716
+ <tool_call>
717
+ <tool>filesystem</tool>
718
+ <action>list</action>
719
+ <params>{"path": "/path/to/dir", "recursive": true, "filter": "*.ts"}</params>
720
+ </tool_call>
721
+
722
+ **exists** - Check if a file or directory exists
723
+ Parameters:
724
+ - path (required): Path to check
725
+
726
+ Example:
727
+ <tool_call>
728
+ <tool>filesystem</tool>
729
+ <action>exists</action>
730
+ <params>{"path": "/path/to/check"}</params>
731
+ </tool_call>
732
+
733
+ **mkdir** - Create a directory
734
+ Parameters:
735
+ - path (required): Directory path to create
736
+ - recursive (optional): Create parent directories if needed (default: true)
737
+
738
+ Example:
739
+ <tool_call>
740
+ <tool>filesystem</tool>
741
+ <action>mkdir</action>
742
+ <params>{"path": "/path/to/new/dir"}</params>
743
+ </tool_call>
744
+
745
+ **delete** - Delete a file or directory
746
+ Parameters:
747
+ - path (required): Path to delete
748
+ - recursive (optional): For directories, delete recursively (default: false)
749
+
750
+ Example:
751
+ <tool_call>
752
+ <tool>filesystem</tool>
753
+ <action>delete</action>
754
+ <params>{"path": "/path/to/delete", "recursive": true}</params>
755
+ </tool_call>
756
+
757
+ **copy** - Copy a file to a new location
758
+ Parameters:
759
+ - source (required): Source file path
760
+ - destination (required): Destination file path
761
+
762
+ Example:
763
+ <tool_call>
764
+ <tool>filesystem</tool>
765
+ <action>copy</action>
766
+ <params>{"source": "/path/to/source.txt", "destination": "/path/to/dest.txt"}</params>
767
+ </tool_call>
768
+
769
+ **move** - Move a file to a new location
770
+ Parameters:
771
+ - source (required): Source file path
772
+ - destination (required): Destination file path
773
+
774
+ Example:
775
+ <tool_call>
776
+ <tool>filesystem</tool>
777
+ <action>move</action>
778
+ <params>{"source": "/path/to/old.txt", "destination": "/path/to/new.txt"}</params>
779
+ </tool_call>
780
+
781
+ **stat** - Get file or directory statistics (size, dates, etc.)
782
+ Parameters:
783
+ - path (required): Path to get stats for
784
+
785
+ Example:
786
+ <tool_call>
787
+ <tool>filesystem</tool>
788
+ <action>stat</action>
789
+ <params>{"path": "/path/to/file.txt"}</params>
790
+ </tool_call>
791
+
792
+ **append** - Append content to a file
793
+ Parameters:
794
+ - path (required): Absolute path to the file
795
+ - content (required): Content to append
796
+
797
+ Example:
798
+ <tool_call>
799
+ <tool>filesystem</tool>
800
+ <action>append</action>
801
+ <params>{"path": "/path/to/log.txt", "content": "New log entry\\n"}</params>
802
+ </tool_call>
803
+
804
+ **tree** - Show directory structure as a tree
805
+ Parameters:
806
+ - path (required): Root directory path
807
+ - maxDepth (optional): Maximum depth to traverse (default: 3)
808
+ - filter (optional): Glob pattern to filter files
809
+ - showSizes (optional): Include file sizes in output (default: false)
810
+ - format (optional): Output format - "string" (default) or "json"
811
+
812
+ Example:
813
+ <tool_call>
814
+ <tool>filesystem</tool>
815
+ <action>tree</action>
816
+ <params>{"path": "/path/to/dir", "maxDepth": 2}</params>
817
+ </tool_call>
818
+
819
+ **glob** - Find files matching a glob pattern
820
+ Parameters:
821
+ - pattern (required): Glob pattern (e.g., "**/*.ts", "src/**/*.js")
822
+ - path (optional): Base path to search from
823
+
824
+ Example:
825
+ <tool_call>
826
+ <tool>filesystem</tool>
827
+ <action>glob</action>
828
+ <params>{"pattern": "**/*.ts", "path": "/path/to/project"}</params>
829
+ </tool_call>
830
+ `;
831
+ }
832
+
669
833
  public getCallSummary(action: string, params: Record<string, unknown>): string {
670
834
  switch (action) {
671
835
  case 'read': {
@@ -180,6 +180,84 @@ export class HttpTool extends BaseToolWrapper {
180
180
  }
181
181
  }
182
182
 
183
+ public getToolExplanation(): string {
184
+ return `## Tool: http
185
+ Make HTTP requests to web APIs and services.
186
+
187
+ ### Actions:
188
+
189
+ **get** - Make a GET request
190
+ Parameters:
191
+ - url (required): URL to request
192
+ - headers (optional): Request headers (key-value object)
193
+ - query (optional): Query parameters (key-value object)
194
+ - timeout (optional): Timeout in milliseconds
195
+
196
+ Example:
197
+ <tool_call>
198
+ <tool>http</tool>
199
+ <action>get</action>
200
+ <params>{"url": "https://api.example.com/data", "headers": {"Authorization": "Bearer token123"}}</params>
201
+ </tool_call>
202
+
203
+ **post** - Make a POST request with JSON body
204
+ Parameters:
205
+ - url (required): URL to request
206
+ - body (optional): JSON body to send
207
+ - headers (optional): Request headers (key-value object)
208
+ - query (optional): Query parameters (key-value object)
209
+ - timeout (optional): Timeout in milliseconds
210
+
211
+ Example:
212
+ <tool_call>
213
+ <tool>http</tool>
214
+ <action>post</action>
215
+ <params>{"url": "https://api.example.com/submit", "body": {"name": "test", "value": 123}}</params>
216
+ </tool_call>
217
+
218
+ **put** - Make a PUT request with JSON body
219
+ Parameters:
220
+ - url (required): URL to request
221
+ - body (required): JSON body to send
222
+ - headers (optional): Request headers (key-value object)
223
+ - timeout (optional): Timeout in milliseconds
224
+
225
+ Example:
226
+ <tool_call>
227
+ <tool>http</tool>
228
+ <action>put</action>
229
+ <params>{"url": "https://api.example.com/resource/1", "body": {"name": "updated"}}</params>
230
+ </tool_call>
231
+
232
+ **patch** - Make a PATCH request with JSON body
233
+ Parameters:
234
+ - url (required): URL to request
235
+ - body (required): JSON body to send
236
+ - headers (optional): Request headers (key-value object)
237
+ - timeout (optional): Timeout in milliseconds
238
+
239
+ Example:
240
+ <tool_call>
241
+ <tool>http</tool>
242
+ <action>patch</action>
243
+ <params>{"url": "https://api.example.com/resource/1", "body": {"status": "active"}}</params>
244
+ </tool_call>
245
+
246
+ **delete** - Make a DELETE request
247
+ Parameters:
248
+ - url (required): URL to request
249
+ - headers (optional): Request headers (key-value object)
250
+ - timeout (optional): Timeout in milliseconds
251
+
252
+ Example:
253
+ <tool_call>
254
+ <tool>http</tool>
255
+ <action>delete</action>
256
+ <params>{"url": "https://api.example.com/resource/1"}</params>
257
+ </tool_call>
258
+ `;
259
+ }
260
+
183
261
  public getCallSummary(action: string, params: Record<string, unknown>): string {
184
262
  const method = action.toUpperCase();
185
263
  let summary = `${method} request to "${params.url}"`;