@polka-codes/core 0.9.45 → 0.9.47

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/index.js CHANGED
@@ -1,29 +1,232 @@
1
- // src/tools/askFollowupQuestion.ts
1
+ // src/Agent/parseJsonFromMarkdown.ts
2
+ var parseJsonFromMarkdown = (markdown) => {
3
+ const jsonRegex = /```(?:json)?\n([\s\S]*?)\n```/;
4
+ const match = markdown.match(jsonRegex);
5
+ const tryParse = (str) => {
6
+ try {
7
+ let parsed = JSON.parse(str);
8
+ if (typeof parsed === "string") {
9
+ try {
10
+ parsed = JSON.parse(parsed);
11
+ } catch {
12
+ }
13
+ }
14
+ return { success: true, data: parsed };
15
+ } catch (e) {
16
+ const error = e instanceof Error ? e.message : String(e);
17
+ return { success: false, error: `Failed to parse JSON: ${error}` };
18
+ }
19
+ };
20
+ if (match?.[1]) {
21
+ const content = match[1].trim();
22
+ return tryParse(content);
23
+ }
24
+ const parseResult = tryParse(markdown);
25
+ if (parseResult.success) {
26
+ return parseResult;
27
+ }
28
+ return { success: false, error: "No JSON object found in the string." };
29
+ };
30
+
31
+ // src/Agent/prompts.ts
32
+ var responsePrompts = {
33
+ errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
34
+ requireUseTool: `Error: No tool use detected. You MUST use a tool before proceeding.
35
+ e.g. <tool_tool_name>tool_name</tool_tool_name>
36
+
37
+ Ensure the opening and closing tags are correctly nested and closed, and that you are using the correct tool name.
38
+ Avoid unnecessary text or symbols before or after the tool use.
39
+ Avoid unnecessary escape characters or special characters.
40
+ `,
41
+ requireUseToolNative: `Error: No tool use detected. You MUST use a tool before proceeding.
42
+ `,
43
+ toolResults: (tool, result) => {
44
+ switch (result.type) {
45
+ case "text":
46
+ return [
47
+ {
48
+ type: "text",
49
+ text: `<tool_response name=${tool}>${result.value}</tool_response>`
50
+ }
51
+ ];
52
+ case "error-text":
53
+ return [
54
+ {
55
+ type: "text",
56
+ text: `<tool_response_error name=${tool}>${result.value}</tool_response_error>`
57
+ }
58
+ ];
59
+ case "json":
60
+ return [
61
+ {
62
+ type: "text",
63
+ text: `<tool_response_json name=${tool}>${JSON.stringify(result.value)}</tool_response_json>`
64
+ }
65
+ ];
66
+ case "error-json":
67
+ return [
68
+ {
69
+ type: "text",
70
+ text: `<tool_response_error_json name=${tool}>${JSON.stringify(result.value)}</tool_response_error_json>`
71
+ }
72
+ ];
73
+ case "content":
74
+ return [
75
+ {
76
+ type: "text",
77
+ text: `<tool_response name=${tool}>`
78
+ },
79
+ ...result.value.map((part) => {
80
+ if (part.type === "text") {
81
+ return part;
82
+ }
83
+ if (part.mediaType.startsWith("image/")) {
84
+ return {
85
+ type: "image",
86
+ mediaType: part.mediaType,
87
+ image: part.data
88
+ };
89
+ }
90
+ return {
91
+ type: "file",
92
+ mediaType: part.mediaType,
93
+ data: part.data
94
+ };
95
+ }),
96
+ {
97
+ type: "text",
98
+ text: "</tool_response>"
99
+ }
100
+ ];
101
+ }
102
+ },
103
+ commandResult: (command, exitCode, stdout, stderr) => `<command>${command}</command>
104
+ <command_exit_code>${exitCode}</command_exit_code>
105
+ <command_stdout>
106
+ ${stdout}
107
+ </command_stdout>
108
+ <command_stderr>
109
+ ${stderr}
110
+ </command_stderr>`
111
+ };
112
+
113
+ // src/Agent/backoff.ts
114
+ function computeRateLimitBackoffSeconds(count, baseSeconds = 2, capSeconds = 60) {
115
+ if (!Number.isFinite(count) || count <= 0) {
116
+ count = 1;
117
+ }
118
+ if (!Number.isFinite(baseSeconds) || baseSeconds <= 0) {
119
+ baseSeconds = 2;
120
+ }
121
+ if (!Number.isFinite(capSeconds) || capSeconds <= 0) {
122
+ capSeconds = 60;
123
+ }
124
+ const delay = baseSeconds * 2 ** (count - 1);
125
+ return Math.min(delay, capSeconds);
126
+ }
127
+
128
+ // src/config.ts
2
129
  import { z } from "zod";
130
+ var providerModelSchema = z.object({
131
+ provider: z.string().optional(),
132
+ model: z.string().optional(),
133
+ parameters: z.record(z.string(), z.any()).optional()
134
+ });
135
+ var configSchema = z.object({
136
+ prices: z.record(
137
+ z.string(),
138
+ // provider
139
+ z.record(
140
+ z.string(),
141
+ // model
142
+ z.object({
143
+ inputPrice: z.number().optional(),
144
+ outputPrice: z.number().optional(),
145
+ cacheWritesPrice: z.number().optional(),
146
+ cacheReadsPrice: z.number().optional()
147
+ })
148
+ )
149
+ ).optional(),
150
+ providers: z.record(
151
+ z.string(),
152
+ z.object({
153
+ apiKey: z.string().optional(),
154
+ defaultModel: z.string().optional(),
155
+ defaultParameters: z.record(z.string(), z.any()).optional(),
156
+ location: z.string().optional(),
157
+ project: z.string().optional(),
158
+ keyFile: z.string().optional()
159
+ })
160
+ ).optional(),
161
+ defaultProvider: z.string().optional(),
162
+ defaultModel: z.string().optional(),
163
+ defaultParameters: z.record(z.string(), z.any()).optional(),
164
+ maxMessageCount: z.number().int().positive().optional(),
165
+ budget: z.number().positive().optional(),
166
+ retryCount: z.number().int().min(0).optional(),
167
+ requestTimeoutSeconds: z.number().int().positive().optional(),
168
+ summaryThreshold: z.number().int().positive().optional(),
169
+ scripts: z.record(
170
+ z.string(),
171
+ z.string().or(
172
+ z.object({
173
+ command: z.string(),
174
+ description: z.string()
175
+ })
176
+ )
177
+ ).optional(),
178
+ commands: z.object({
179
+ default: providerModelSchema.optional()
180
+ }).catchall(providerModelSchema).optional(),
181
+ rules: z.array(z.string()).optional().or(z.string()).optional(),
182
+ excludeFiles: z.array(z.string()).optional()
183
+ }).strict();
3
184
 
4
185
  // src/tool.ts
5
186
  var ToolResponseType = /* @__PURE__ */ ((ToolResponseType2) => {
6
187
  ToolResponseType2["Reply"] = "Reply";
7
188
  ToolResponseType2["Exit"] = "Exit";
8
- ToolResponseType2["Invalid"] = "Invalid";
9
189
  ToolResponseType2["Error"] = "Error";
10
- ToolResponseType2["Interrupted"] = "Interrupted";
11
- ToolResponseType2["HandOver"] = "HandOver";
12
- ToolResponseType2["Delegate"] = "Delegate";
13
- ToolResponseType2["Pause"] = "Pause";
14
190
  return ToolResponseType2;
15
191
  })(ToolResponseType || {});
16
192
 
193
+ // src/tools/appendMemory.ts
194
+ import { z as z2 } from "zod";
195
+ var toolInfo = {
196
+ name: "appendMemory",
197
+ description: "Appends content to a memory topic.",
198
+ parameters: z2.object({
199
+ topic: z2.string().nullish().describe('The topic to append to in memory. Defaults to ":default:".'),
200
+ content: z2.string().describe("The content to append.")
201
+ })
202
+ };
203
+ var handler = async (provider, args) => {
204
+ const { topic, content } = toolInfo.parameters.parse(args);
205
+ await provider.appendMemory(topic ?? void 0, content);
206
+ return {
207
+ type: "Reply" /* Reply */,
208
+ message: {
209
+ type: "text",
210
+ value: `Content appended to memory topic '${topic || ""}'.`
211
+ }
212
+ };
213
+ };
214
+ var appendMemory_default = {
215
+ ...toolInfo,
216
+ handler
217
+ };
218
+
17
219
  // src/tools/askFollowupQuestion.ts
18
- var questionObject = z.object({
19
- prompt: z.string().describe("The text of the question.").meta({ usageValue: "question text here" }),
20
- options: z.array(z.string()).default([]).describe("Ordered list of suggested answers (omit if none).").meta({ usageValue: "suggested answer here" })
220
+ import { z as z3 } from "zod";
221
+ var questionObject = z3.object({
222
+ prompt: z3.string().describe("The text of the question.").meta({ usageValue: "question text here" }),
223
+ options: z3.array(z3.string()).default([]).describe("Ordered list of suggested answers (omit if none).").meta({ usageValue: "suggested answer here" })
21
224
  });
22
- var toolInfo = {
23
- name: "ask_followup_question",
225
+ var toolInfo2 = {
226
+ name: "askFollowupQuestion",
24
227
  description: "Call this when vital details are missing. Pose each follow-up as one direct, unambiguous question. If it speeds the reply, add up to five short, mutually-exclusive answer options. Group any related questions in the same call to avoid a back-and-forth chain.",
25
- parameters: z.object({
26
- questions: z.array(questionObject).describe("One or more follow-up questions you need answered before you can continue.").meta({ usageValue: "questions here" })
228
+ parameters: z3.object({
229
+ questions: z3.array(questionObject).describe("One or more follow-up questions you need answered before you can continue.").meta({ usageValue: "questions here" })
27
230
  }).meta({
28
231
  examples: [
29
232
  {
@@ -69,7 +272,7 @@ var toolInfo = {
69
272
  ]
70
273
  })
71
274
  };
72
- var handler = async (provider, args) => {
275
+ var handler2 = async (provider, args) => {
73
276
  if (!provider.askFollowupQuestion) {
74
277
  return {
75
278
  type: "Error" /* Error */,
@@ -79,10 +282,10 @@ var handler = async (provider, args) => {
79
282
  }
80
283
  };
81
284
  }
82
- const { questions } = toolInfo.parameters.parse(args);
285
+ const { questions } = toolInfo2.parameters.parse(args);
83
286
  if (questions.length === 0) {
84
287
  return {
85
- type: "Invalid" /* Invalid */,
288
+ type: "Error" /* Error */,
86
289
  message: {
87
290
  type: "error-text",
88
291
  value: "No questions provided"
@@ -91,9 +294,9 @@ var handler = async (provider, args) => {
91
294
  }
92
295
  const answers = [];
93
296
  for (const question of questions) {
94
- const { prompt: prompt2, options } = question;
95
- const answer = await provider.askFollowupQuestion(prompt2, options);
96
- answers.push(`<ask_followup_question_answer question="${prompt2}">
297
+ const { prompt, options } = question;
298
+ const answer = await provider.askFollowupQuestion(prompt, options);
299
+ answers.push(`<ask_followup_question_answer question="${prompt}">
97
300
  ${answer}
98
301
  </ask_followup_question_answer>`);
99
302
  }
@@ -105,132 +308,15 @@ ${answer}
105
308
  }
106
309
  };
107
310
  };
108
- var isAvailable = (provider) => {
109
- return !!provider.askFollowupQuestion;
110
- };
111
311
  var askFollowupQuestion_default = {
112
- ...toolInfo,
113
- handler,
114
- isAvailable
115
- };
116
-
117
- // src/tools/attemptCompletion.ts
118
- import { z as z2 } from "zod";
119
- var toolInfo2 = {
120
- name: "attempt_completion",
121
- description: "Use this tool when you believe the user\u2019s requested task is complete. Indicate that your work is finished, but acknowledge the user may still provide additional instructions or questions if they want to continue. This tool MUST NOT to be used with any other tool.",
122
- parameters: z2.object({
123
- result: z2.string().describe(
124
- "The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance."
125
- ).meta({ usageValue: "Your final result description here" })
126
- }).meta({
127
- examples: [
128
- {
129
- description: "Request to present the result of the task",
130
- input: {
131
- result: "Your final result description here"
132
- }
133
- }
134
- ]
135
- })
136
- };
137
- var handler2 = async (provider, args) => {
138
- const parsed = toolInfo2.parameters.safeParse(args);
139
- if (!parsed.success) {
140
- return {
141
- type: "Invalid" /* Invalid */,
142
- message: {
143
- type: "error-text",
144
- value: `Invalid arguments for attempt_completion: ${parsed.error.message}`
145
- }
146
- };
147
- }
148
- const { result } = parsed.data;
149
- const moreMessage = await provider.attemptCompletion?.(result);
150
- if (!moreMessage) {
151
- return {
152
- type: "Exit" /* Exit */,
153
- message: result
154
- };
155
- }
156
- return {
157
- type: "Reply" /* Reply */,
158
- message: {
159
- type: "text",
160
- value: `<user_message>${moreMessage}</user_message>`
161
- }
162
- };
163
- };
164
- var isAvailable2 = (_provider) => {
165
- return true;
166
- };
167
- var attemptCompletion_default = {
168
312
  ...toolInfo2,
169
- handler: handler2,
170
- isAvailable: isAvailable2
171
- };
172
-
173
- // src/tools/delegate.ts
174
- import { z as z3 } from "zod";
175
- var toolInfo3 = {
176
- name: "delegate",
177
- description: "Temporarily delegate a task to another agent and receive the result back. This tool MUST NOT to be used with any other tool.",
178
- parameters: z3.object({
179
- agentName: z3.string().describe("The name of the agent to delegate the task to").meta({ usageValue: "Name of the target agent" }),
180
- task: z3.string().describe("The task to be completed by the target agent").meta({ usageValue: "Task description" }),
181
- context: z3.string().describe("The context information for the task").meta({ usageValue: "Context information" }),
182
- files: z3.preprocess((val) => {
183
- if (!val) return [];
184
- const values = Array.isArray(val) ? val : [val];
185
- return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
186
- }, z3.array(z3.string())).optional().describe("The files relevant to the task. Comma separated paths").meta({ usageValue: "Relevant files" })
187
- }).meta({
188
- examples: [
189
- {
190
- description: "Delegate a code analysis task to the analyzer agent",
191
- input: {
192
- agentName: "analyzer",
193
- task: "Analyze the authentication implementation",
194
- context: "Need to understand the security implications of the current auth system",
195
- files: "src/auth/login.ts,src/auth/types.ts"
196
- }
197
- }
198
- ]
199
- })
200
- };
201
- var handler3 = async (_provider, args) => {
202
- const parsed = toolInfo3.parameters.safeParse(args);
203
- if (!parsed.success) {
204
- return {
205
- type: "Invalid" /* Invalid */,
206
- message: {
207
- type: "error-text",
208
- value: `Invalid arguments for delegate: ${parsed.error.message}`
209
- }
210
- };
211
- }
212
- const { agentName, task, context, files } = parsed.data;
213
- return {
214
- type: "Delegate" /* Delegate */,
215
- agentName,
216
- task,
217
- context,
218
- files: files ?? []
219
- };
220
- };
221
- var isAvailable3 = (_provider) => {
222
- return true;
223
- };
224
- var delegate_default = {
225
- ...toolInfo3,
226
- handler: handler3,
227
- isAvailable: isAvailable3
313
+ handler: handler2
228
314
  };
229
315
 
230
316
  // src/tools/executeCommand.ts
231
317
  import { z as z4 } from "zod";
232
- var toolInfo4 = {
233
- name: "execute_command",
318
+ var toolInfo3 = {
319
+ name: "executeCommand",
234
320
  description: "Run a single CLI command. The command is always executed in the project-root working directory (regardless of earlier commands). Prefer one-off shell commands over wrapper scripts for flexibility. **IMPORTANT**: After an `execute_command` call, you MUST stop and NOT allowed to make further tool calls in the same message.",
235
321
  parameters: z4.object({
236
322
  command: z4.string().describe("The exact command to run (valid for the current OS). It must be correctly formatted and free of harmful instructions.").meta({ usageValue: "your-command-here" }),
@@ -256,7 +342,7 @@ var toolInfo4 = {
256
342
  ]
257
343
  })
258
344
  };
259
- var handler4 = async (provider, args) => {
345
+ var handler3 = async (provider, args) => {
260
346
  if (!provider.executeCommand) {
261
347
  return {
262
348
  type: "Error" /* Error */,
@@ -266,9 +352,8 @@ var handler4 = async (provider, args) => {
266
352
  }
267
353
  };
268
354
  }
269
- const { command, requiresApproval } = toolInfo4.parameters.parse(args);
355
+ const { command, requiresApproval } = toolInfo3.parameters.parse(args);
270
356
  try {
271
- console.log("Executing command:", command, "Requires approval:", requiresApproval);
272
357
  const result = await provider.executeCommand(command, requiresApproval);
273
358
  let message = `<command>${command}</command>
274
359
  <command_exit_code>${result.exitCode}</command_exit_code>
@@ -313,19 +398,15 @@ ${result.stderr}
313
398
  };
314
399
  }
315
400
  };
316
- var isAvailable4 = (provider) => {
317
- return !!provider.executeCommand;
318
- };
319
401
  var executeCommand_default = {
320
- ...toolInfo4,
321
- handler: handler4,
322
- isAvailable: isAvailable4
402
+ ...toolInfo3,
403
+ handler: handler3
323
404
  };
324
405
 
325
406
  // src/tools/fetchUrl.ts
326
407
  import { z as z5 } from "zod";
327
- var toolInfo5 = {
328
- name: "fetch_url",
408
+ var toolInfo4 = {
409
+ name: "fetchUrl",
329
410
  description: "Fetch the content located at one or more HTTP(S) URLs and return it in Markdown format. This works for standard web pages as well as raw files (e.g. README.md, source code) hosted on platforms like GitHub.",
330
411
  parameters: z5.object({
331
412
  url: z5.preprocess((val) => {
@@ -356,7 +437,7 @@ var toolInfo5 = {
356
437
  ]
357
438
  })
358
439
  };
359
- var handler5 = async (provider, args) => {
440
+ var handler4 = async (provider, args) => {
360
441
  if (!provider.fetchUrl) {
361
442
  return {
362
443
  type: "Error" /* Error */,
@@ -366,7 +447,7 @@ var handler5 = async (provider, args) => {
366
447
  }
367
448
  };
368
449
  }
369
- const { url: urls } = toolInfo5.parameters.parse(args);
450
+ const { url: urls } = toolInfo4.parameters.parse(args);
370
451
  if (urls.length === 0) {
371
452
  return {
372
453
  type: "Error" /* Error */,
@@ -395,96 +476,35 @@ var handler5 = async (provider, args) => {
395
476
  }
396
477
  };
397
478
  };
398
- var isAvailable5 = (provider) => {
399
- return typeof provider.fetchUrl === "function";
400
- };
401
479
  var fetchUrl_default = {
402
- ...toolInfo5,
403
- handler: handler5,
404
- isAvailable: isAvailable5
480
+ ...toolInfo4,
481
+ handler: handler4
405
482
  };
406
483
 
407
- // src/tools/handOver.ts
484
+ // src/tools/listFiles.ts
408
485
  import { z as z6 } from "zod";
409
- var toolInfo6 = {
410
- name: "hand_over",
411
- description: "Hand over the current task to another agent to complete. This tool MUST NOT to be used with any other tool.",
486
+ var toolInfo5 = {
487
+ name: "listFiles",
488
+ description: "Request to list files and directories within the specified directory. If recursive is true, it will list all files and directories recursively. If recursive is false or not provided, it will only list the top-level contents. Do not use this tool to confirm the existence of files you may have created, as the user will let you know if the files were created successfully or not.",
412
489
  parameters: z6.object({
413
- agentName: z6.string().describe("The name of the agent to hand over the task to").meta({ usageValue: "Name of the target agent" }),
414
- task: z6.string().describe("The task to be completed by the target agent").meta({ usageValue: "Task description" }),
415
- context: z6.string().describe("The context information for the task").meta({ usageValue: "Context information" }),
416
- files: z6.preprocess((val) => {
417
- if (!val) return [];
418
- const values = Array.isArray(val) ? val : [val];
419
- return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
420
- }, z6.array(z6.string())).optional().describe("The files relevant to the task. Comma separated paths").meta({ usageValue: "Relevant files" })
421
- }).meta({
422
- examples: [
423
- {
424
- description: "Hand over a coding task to the coder agent",
425
- input: {
426
- agentName: "coder",
427
- task: "Implement the login feature",
428
- context: "We need a secure login system with email and password",
429
- files: "src/auth/login.ts,src/auth/types.ts"
430
- }
431
- }
432
- ]
433
- })
434
- };
435
- var handler6 = async (_provider, args) => {
436
- const parsed = toolInfo6.parameters.safeParse(args);
437
- if (!parsed.success) {
438
- return {
439
- type: "Invalid" /* Invalid */,
440
- message: {
441
- type: "error-text",
442
- value: `Invalid arguments for hand_over: ${parsed.error.message}`
443
- }
444
- };
445
- }
446
- const { agentName, task, context, files } = parsed.data;
447
- return {
448
- type: "HandOver" /* HandOver */,
449
- agentName,
450
- task,
451
- context,
452
- files: files ?? []
453
- };
454
- };
455
- var isAvailable6 = (_provider) => {
456
- return true;
457
- };
458
- var handOver_default = {
459
- ...toolInfo6,
460
- handler: handler6,
461
- isAvailable: isAvailable6
462
- };
463
-
464
- // src/tools/listFiles.ts
465
- import { z as z7 } from "zod";
466
- var toolInfo7 = {
467
- name: "list_files",
468
- description: "Request to list files and directories within the specified directory. If recursive is true, it will list all files and directories recursively. If recursive is false or not provided, it will only list the top-level contents. Do not use this tool to confirm the existence of files you may have created, as the user will let you know if the files were created successfully or not.",
469
- parameters: z7.object({
470
- path: z7.string().describe("The path of the directory to list contents for (relative to the current working directory)").meta({ usageValue: "Directory path here" }),
471
- maxCount: z7.coerce.number().optional().default(2e3).describe("The maximum number of files to list. Default to 2000").meta({ usageValue: "Maximum number of files to list (optional)" }),
472
- recursive: z7.preprocess((val) => {
490
+ path: z6.string().describe("The path of the directory to list contents for (relative to the current working directory)").meta({ usageValue: "Directory path here" }),
491
+ maxCount: z6.coerce.number().optional().default(2e3).describe("The maximum number of files to list. Default to 2000").meta({ usageValue: "Maximum number of files to list (optional)" }),
492
+ recursive: z6.preprocess((val) => {
473
493
  if (typeof val === "string") {
474
494
  const lower = val.toLowerCase();
475
495
  if (lower === "false") return false;
476
496
  if (lower === "true") return true;
477
497
  }
478
498
  return val;
479
- }, z7.boolean().optional().default(true)).describe("Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.").meta({ usageValue: "true or false (optional)" }),
480
- includeIgnored: z7.preprocess((val) => {
499
+ }, z6.boolean().optional().default(true)).describe("Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.").meta({ usageValue: "true or false (optional)" }),
500
+ includeIgnored: z6.preprocess((val) => {
481
501
  if (typeof val === "string") {
482
502
  const lower = val.toLowerCase();
483
503
  if (lower === "false") return false;
484
504
  if (lower === "true") return true;
485
505
  }
486
506
  return val;
487
- }, z7.boolean().optional().default(false)).describe("Whether to include ignored files. Use true to include files ignored by .gitignore.").meta({ usageValue: "true or false (optional)" })
507
+ }, z6.boolean().optional().default(false)).describe("Whether to include ignored files. Use true to include files ignored by .gitignore.").meta({ usageValue: "true or false (optional)" })
488
508
  }).meta({
489
509
  examples: [
490
510
  {
@@ -497,7 +517,7 @@ var toolInfo7 = {
497
517
  ]
498
518
  })
499
519
  };
500
- var handler7 = async (provider, args) => {
520
+ var handler5 = async (provider, args) => {
501
521
  if (!provider.listFiles) {
502
522
  return {
503
523
  type: "Error" /* Error */,
@@ -507,7 +527,7 @@ var handler7 = async (provider, args) => {
507
527
  }
508
528
  };
509
529
  }
510
- const { path, maxCount, recursive, includeIgnored } = toolInfo7.parameters.parse(args);
530
+ const { path, maxCount, recursive, includeIgnored } = toolInfo5.parameters.parse(args);
511
531
  const [files, limitReached] = await provider.listFiles(path, recursive, maxCount, includeIgnored);
512
532
  return {
513
533
  type: "Reply" /* Reply */,
@@ -521,13 +541,35 @@ ${files.join("\n")}
521
541
  }
522
542
  };
523
543
  };
524
- var isAvailable7 = (provider) => {
525
- return !!provider.listFiles;
526
- };
527
544
  var listFiles_default = {
528
- ...toolInfo7,
529
- handler: handler7,
530
- isAvailable: isAvailable7
545
+ ...toolInfo5,
546
+ handler: handler5
547
+ };
548
+
549
+ // src/tools/listMemoryTopics.ts
550
+ import { z as z7 } from "zod";
551
+ var toolInfo6 = {
552
+ name: "listMemoryTopics",
553
+ description: "Lists all topics in memory.",
554
+ parameters: z7.object({})
555
+ };
556
+ var handler6 = async (provider, _args) => {
557
+ const topics = await provider.listMemoryTopics();
558
+ if (!topics.length) {
559
+ return { type: "Reply" /* Reply */, message: { type: "text", value: "No topics found." } };
560
+ }
561
+ return {
562
+ type: "Reply" /* Reply */,
563
+ message: {
564
+ type: "text",
565
+ value: `Memory topics:
566
+ ${topics.join("\n")}`
567
+ }
568
+ };
569
+ };
570
+ var listMemoryTopics_default = {
571
+ ...toolInfo6,
572
+ handler: handler6
531
573
  };
532
574
 
533
575
  // src/tools/provider.ts
@@ -556,21 +598,18 @@ var MockProvider = class {
556
598
  async askFollowupQuestion(_question, _options) {
557
599
  return "mock answer";
558
600
  }
559
- async attemptCompletion(_result) {
560
- return "mock completion";
561
- }
562
601
  };
563
602
 
564
603
  // src/tools/readBinaryFile.ts
565
604
  import { z as z8 } from "zod";
566
- var toolInfo8 = {
567
- name: "read_binary_file",
605
+ var toolInfo7 = {
606
+ name: "readBinaryFile",
568
607
  description: "Read a binary file from a URL or local path. Use file:// prefix to access local files. This can be used to access non-text files such as PDFs or images.",
569
608
  parameters: z8.object({
570
609
  url: z8.string().describe("The URL or local path of the file to read.")
571
610
  })
572
611
  };
573
- var handler8 = async (provider, args) => {
612
+ var handler7 = async (provider, args) => {
574
613
  if (!provider.readBinaryFile) {
575
614
  return {
576
615
  type: "Error" /* Error */,
@@ -580,7 +619,7 @@ var handler8 = async (provider, args) => {
580
619
  }
581
620
  };
582
621
  }
583
- const { url } = toolInfo8.parameters.parse(args);
622
+ const { url } = toolInfo7.parameters.parse(args);
584
623
  try {
585
624
  const filePart = await provider.readBinaryFile(url);
586
625
  return {
@@ -608,19 +647,15 @@ var handler8 = async (provider, args) => {
608
647
  };
609
648
  }
610
649
  };
611
- var isAvailable8 = (provider) => {
612
- return typeof provider.readBinaryFile === "function";
613
- };
614
650
  var readBinaryFile_default = {
615
- ...toolInfo8,
616
- handler: handler8,
617
- isAvailable: isAvailable8
651
+ ...toolInfo7,
652
+ handler: handler7
618
653
  };
619
654
 
620
655
  // src/tools/readFile.ts
621
656
  import { z as z9 } from "zod";
622
- var toolInfo9 = {
623
- name: "read_file",
657
+ var toolInfo8 = {
658
+ name: "readFile",
624
659
  description: "Request to read the contents of one or multiple files at the specified paths. Use comma separated paths to read multiple files. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. May not be suitable for other types of binary files, as it returns the raw content as a string. Try to list all the potential files are relevent to the task, and then use this tool to read all the relevant files.",
625
660
  parameters: z9.object({
626
661
  path: z9.preprocess((val) => {
@@ -653,7 +688,7 @@ var toolInfo9 = {
653
688
  ]
654
689
  })
655
690
  };
656
- var handler9 = async (provider, args) => {
691
+ var handler8 = async (provider, args) => {
657
692
  if (!provider.readFile) {
658
693
  return {
659
694
  type: "Error" /* Error */,
@@ -663,7 +698,7 @@ var handler9 = async (provider, args) => {
663
698
  }
664
699
  };
665
700
  }
666
- const { path: paths, includeIgnored } = toolInfo9.parameters.parse(args);
701
+ const { path: paths, includeIgnored } = toolInfo8.parameters.parse(args);
667
702
  const resp = [];
668
703
  for (const path of paths) {
669
704
  const fileContent = await provider.readFile(path, includeIgnored);
@@ -686,22 +721,54 @@ var handler9 = async (provider, args) => {
686
721
  }
687
722
  };
688
723
  };
689
- var isAvailable9 = (provider) => {
690
- return !!provider.readFile;
691
- };
692
724
  var readFile_default = {
725
+ ...toolInfo8,
726
+ handler: handler8
727
+ };
728
+
729
+ // src/tools/readMemory.ts
730
+ import { z as z10 } from "zod";
731
+ var toolInfo9 = {
732
+ name: "readMemory",
733
+ description: "Reads content from a memory topic.",
734
+ parameters: z10.object({
735
+ topic: z10.string().optional().describe('The topic to read from memory. Defaults to ":default:".')
736
+ })
737
+ };
738
+ var handler9 = async (provider, args) => {
739
+ const { topic } = toolInfo9.parameters.parse(args);
740
+ const content = await provider.readMemory(topic);
741
+ if (content) {
742
+ return {
743
+ type: "Reply" /* Reply */,
744
+ message: {
745
+ type: "text",
746
+ value: `<memory${topic ? ` topic="${topic}"` : ""}>
747
+ ${content}
748
+ </memory>`
749
+ }
750
+ };
751
+ }
752
+ return {
753
+ type: "Reply" /* Reply */,
754
+ message: {
755
+ type: "text",
756
+ value: `<memory ${topic ? `topic="${topic}"` : ""} isEmpty="true" />`
757
+ }
758
+ };
759
+ };
760
+ var readMemory_default = {
693
761
  ...toolInfo9,
694
- handler: handler9,
695
- isAvailable: isAvailable9
762
+ handler: handler9
696
763
  };
697
764
 
698
765
  // src/tools/removeFile.ts
699
- import { z as z10 } from "zod";
766
+ import { z as z11 } from "zod";
700
767
  var toolInfo10 = {
701
- name: "remove_file",
768
+ name: "removeFile",
702
769
  description: "Request to remove a file at the specified path.",
703
- parameters: z10.object({
704
- path: z10.string().describe("The path of the file to remove").meta({ usageValue: "File path here" })
770
+ parameters: z11.object({
771
+ path: z11.string().describe("The path of the file to remove").meta({ usageValue: "File path here" })
705
772
  }).meta({
706
773
  examples: [
707
774
  {
@@ -726,10 +793,10 @@ var handler10 = async (provider, args) => {
726
793
  const parsed = toolInfo10.parameters.safeParse(args);
727
794
  if (!parsed.success) {
728
795
  return {
729
- type: "Invalid" /* Invalid */,
796
+ type: "Error" /* Error */,
730
797
  message: {
731
798
  type: "error-text",
732
- value: `Invalid arguments for remove_file: ${parsed.error.message}`
799
+ value: `Invalid arguments for removeFile: ${parsed.error.message}`
733
800
  }
734
801
  };
735
802
  }
@@ -743,23 +810,44 @@ var handler10 = async (provider, args) => {
743
810
  }
744
811
  };
745
812
  };
746
- var isAvailable10 = (provider) => {
747
- return !!provider.removeFile;
748
- };
749
813
  var removeFile_default = {
750
814
  ...toolInfo10,
751
- handler: handler10,
752
- isAvailable: isAvailable10
815
+ handler: handler10
753
816
  };
754
817
 
755
- // src/tools/renameFile.ts
756
- import { z as z11 } from "zod";
818
+ // src/tools/removeMemory.ts
819
+ import { z as z12 } from "zod";
757
820
  var toolInfo11 = {
758
- name: "rename_file",
821
+ name: "removeMemory",
822
+ description: "Removes a topic from memory.",
823
+ parameters: z12.object({
824
+ topic: z12.string().optional().describe('The topic to remove from memory. Defaults to ":default:".')
825
+ })
826
+ };
827
+ var handler11 = async (provider, args) => {
828
+ const { topic } = toolInfo11.parameters.parse(args);
829
+ await provider.removeMemory(topic);
830
+ return {
831
+ type: "Reply" /* Reply */,
832
+ message: {
833
+ type: "text",
834
+ value: `Memory topic '${topic || ""}' removed.`
835
+ }
836
+ };
837
+ };
838
+ var removeMemory_default = {
839
+ ...toolInfo11,
840
+ handler: handler11
841
+ };
842
+
843
+ // src/tools/renameFile.ts
844
+ import { z as z13 } from "zod";
845
+ var toolInfo12 = {
846
+ name: "renameFile",
759
847
  description: "Request to rename a file from source path to target path.",
760
- parameters: z11.object({
761
- source_path: z11.string().describe("The current path of the file").meta({ usageValue: "Source file path here" }),
762
- target_path: z11.string().describe("The new path for the file").meta({ usageValue: "Target file path here" })
848
+ parameters: z13.object({
849
+ source_path: z13.string().describe("The current path of the file").meta({ usageValue: "Source file path here" }),
850
+ target_path: z13.string().describe("The new path for the file").meta({ usageValue: "Target file path here" })
763
851
  }).meta({
764
852
  examples: [
765
853
  {
@@ -772,7 +860,7 @@ var toolInfo11 = {
772
860
  ]
773
861
  })
774
862
  };
775
- var handler11 = async (provider, args) => {
863
+ var handler12 = async (provider, args) => {
776
864
  if (!provider.renameFile) {
777
865
  return {
778
866
  type: "Error" /* Error */,
@@ -782,7 +870,7 @@ var handler11 = async (provider, args) => {
782
870
  }
783
871
  };
784
872
  }
785
- const { source_path, target_path } = toolInfo11.parameters.parse(args);
873
+ const { source_path, target_path } = toolInfo12.parameters.parse(args);
786
874
  await provider.renameFile(source_path, target_path);
787
875
  return {
788
876
  type: "Reply" /* Reply */,
@@ -792,17 +880,13 @@ var handler11 = async (provider, args) => {
792
880
  }
793
881
  };
794
882
  };
795
- var isAvailable11 = (provider) => {
796
- return !!provider.renameFile;
797
- };
798
883
  var renameFile_default = {
799
- ...toolInfo11,
800
- handler: handler11,
801
- isAvailable: isAvailable11
884
+ ...toolInfo12,
885
+ handler: handler12
802
886
  };
803
887
 
804
888
  // src/tools/replaceInFile.ts
805
- import { z as z12 } from "zod";
889
+ import { z as z14 } from "zod";
806
890
 
807
891
  // src/tools/utils/replaceInFile.ts
808
892
  var replaceInFile = (fileContent, diff) => {
@@ -879,12 +963,12 @@ var replaceInFile = (fileContent, diff) => {
879
963
  };
880
964
 
881
965
  // src/tools/replaceInFile.ts
882
- var toolInfo12 = {
883
- name: "replace_in_file",
966
+ var toolInfo13 = {
967
+ name: "replaceInFile",
884
968
  description: "Request to replace sections of content in an existing file using SEARCH/REPLACE blocks that define exact changes to specific parts of the file. This tool should be used when you need to make targeted changes to specific parts of a file.",
885
- parameters: z12.object({
886
- path: z12.string().describe("The path of the file to modify").meta({ usageValue: "File path here" }),
887
- diff: z12.string().describe(
969
+ parameters: z14.object({
970
+ path: z14.string().describe("The path of the file to modify").meta({ usageValue: "File path here" }),
971
+ diff: z14.string().describe(
888
972
  `One or more SEARCH/REPLACE blocks following this exact format:
889
973
  \`\`\`
890
974
  <<<<<<< SEARCH
@@ -991,7 +1075,7 @@ function oldFeature() {
991
1075
  ]
992
1076
  })
993
1077
  };
994
- var handler12 = async (provider, args) => {
1078
+ var handler13 = async (provider, args) => {
995
1079
  if (!provider.readFile || !provider.writeFile) {
996
1080
  return {
997
1081
  type: "Error" /* Error */,
@@ -1001,13 +1085,13 @@ var handler12 = async (provider, args) => {
1001
1085
  }
1002
1086
  };
1003
1087
  }
1004
- const parsed = toolInfo12.parameters.safeParse(args);
1088
+ const parsed = toolInfo13.parameters.safeParse(args);
1005
1089
  if (!parsed.success) {
1006
1090
  return {
1007
- type: "Invalid" /* Invalid */,
1091
+ type: "Error" /* Error */,
1008
1092
  message: {
1009
1093
  type: "error-text",
1010
- value: `Invalid arguments for replace_in_file: ${parsed.error.message}`
1094
+ value: `Invalid arguments for replaceInFile: ${parsed.error.message}`
1011
1095
  }
1012
1096
  };
1013
1097
  }
@@ -1056,36 +1140,58 @@ var handler12 = async (provider, args) => {
1056
1140
  };
1057
1141
  } catch (error) {
1058
1142
  return {
1059
- type: "Invalid" /* Invalid */,
1143
+ type: "Error" /* Error */,
1060
1144
  message: {
1061
1145
  type: "error-text",
1062
- value: `Invalid arguments for replace_in_file: ${error}`
1146
+ value: `Invalid arguments for replaceInFile: ${error}`
1063
1147
  }
1064
1148
  };
1065
1149
  }
1066
1150
  };
1067
- var isAvailable12 = (provider) => {
1068
- return !!provider.readFile && !!provider.writeFile;
1069
- };
1070
1151
  var replaceInFile_default = {
1071
- ...toolInfo12,
1072
- handler: handler12,
1073
- isAvailable: isAvailable12
1152
+ ...toolInfo13,
1153
+ handler: handler13
1154
+ };
1155
+
1156
+ // src/tools/replaceMemory.ts
1157
+ import { z as z15 } from "zod";
1158
+ var toolInfo14 = {
1159
+ name: "replaceMemory",
1160
+ description: "Replaces content of a memory topic.",
1161
+ parameters: z15.object({
1162
+ topic: z15.string().optional().describe('The topic to replace in memory. Defaults to ":default:".'),
1163
+ content: z15.string().describe("The new content.")
1164
+ })
1165
+ };
1166
+ var handler14 = async (provider, args) => {
1167
+ const { topic, content } = toolInfo14.parameters.parse(args);
1168
+ await provider.replaceMemory(topic, content);
1169
+ return {
1170
+ type: "Reply" /* Reply */,
1171
+ message: {
1172
+ type: "text",
1173
+ value: `Memory topic '${topic || ""}' replaced.`
1174
+ }
1175
+ };
1176
+ };
1177
+ var replaceMemory_default = {
1178
+ ...toolInfo14,
1179
+ handler: handler14
1074
1180
  };
1075
1181
 
1076
1182
  // src/tools/searchFiles.ts
1077
- import { z as z13 } from "zod";
1078
- var toolInfo13 = {
1079
- name: "search_files",
1183
+ import { z as z16 } from "zod";
1184
+ var toolInfo15 = {
1185
+ name: "searchFiles",
1080
1186
  description: "Request to perform a regex search across files in a specified directory, outputting context-rich results that include surrounding lines. This tool searches for patterns or specific content across multiple files, displaying each match with encapsulating context.",
1081
- parameters: z13.object({
1082
- path: z13.string().describe(
1187
+ parameters: z16.object({
1188
+ path: z16.string().describe(
1083
1189
  "The path of the directory to search in (relative to the current working directory). This directory will be recursively searched."
1084
1190
  ).meta({ usageValue: "Directory path here" }),
1085
- regex: z13.string().describe("The regular expression pattern to search for. Uses Rust regex syntax.").meta({
1191
+ regex: z16.string().describe("The regular expression pattern to search for. Uses Rust regex syntax.").meta({
1086
1192
  usageValue: "Your regex pattern here"
1087
1193
  }),
1088
- filePattern: z13.string().optional().describe(
1194
+ filePattern: z16.string().optional().describe(
1089
1195
  'Comma-separated glob pattern to filter files (e.g., "*.ts" for TypeScript files or "*.ts,*.js" for both TypeScript and JavaScript files). If not provided, it will search all files (*).'
1090
1196
  ).meta({
1091
1197
  usageValue: "file pattern here (optional)"
@@ -1103,7 +1209,7 @@ var toolInfo13 = {
1103
1209
  ]
1104
1210
  })
1105
1211
  };
1106
- var handler13 = async (provider, args) => {
1212
+ var handler15 = async (provider, args) => {
1107
1213
  if (!provider.searchFiles) {
1108
1214
  return {
1109
1215
  type: "Error" /* Error */,
@@ -1113,13 +1219,13 @@ var handler13 = async (provider, args) => {
1113
1219
  }
1114
1220
  };
1115
1221
  }
1116
- const parsed = toolInfo13.parameters.safeParse(args);
1222
+ const parsed = toolInfo15.parameters.safeParse(args);
1117
1223
  if (!parsed.success) {
1118
1224
  return {
1119
- type: "Invalid" /* Invalid */,
1225
+ type: "Error" /* Error */,
1120
1226
  message: {
1121
1227
  type: "error-text",
1122
- value: `Invalid arguments for search_files: ${parsed.error.message}`
1228
+ value: `Invalid arguments for searchFiles: ${parsed.error.message}`
1123
1229
  }
1124
1230
  };
1125
1231
  }
@@ -1149,23 +1255,19 @@ ${files.join("\n")}
1149
1255
  };
1150
1256
  }
1151
1257
  };
1152
- var isAvailable13 = (provider) => {
1153
- return !!provider.searchFiles;
1154
- };
1155
1258
  var searchFiles_default = {
1156
- ...toolInfo13,
1157
- handler: handler13,
1158
- isAvailable: isAvailable13
1259
+ ...toolInfo15,
1260
+ handler: handler15
1159
1261
  };
1160
1262
 
1161
1263
  // src/tools/writeToFile.ts
1162
- import { z as z14 } from "zod";
1163
- var toolInfo14 = {
1164
- name: "write_to_file",
1264
+ import { z as z17 } from "zod";
1265
+ var toolInfo16 = {
1266
+ name: "writeToFile",
1165
1267
  description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `&lt;`, `&gt;`, or `&amp;`. Also ensure there is no unwanted CDATA tags in the content.",
1166
- parameters: z14.object({
1167
- path: z14.string().describe("The path of the file to write to").meta({ usageValue: "File path here" }),
1168
- content: z14.string().describe(
1268
+ parameters: z17.object({
1269
+ path: z17.string().describe("The path of the file to write to").meta({ usageValue: "File path here" }),
1270
+ content: z17.string().describe(
1169
1271
  "The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified."
1170
1272
  ).meta({ usageValue: "Your file content here" })
1171
1273
  }).meta({
@@ -1191,7 +1293,7 @@ export default App;
1191
1293
  ]
1192
1294
  })
1193
1295
  };
1194
- var handler14 = async (provider, args) => {
1296
+ var handler16 = async (provider, args) => {
1195
1297
  if (!provider.writeFile) {
1196
1298
  return {
1197
1299
  type: "Error" /* Error */,
@@ -1201,13 +1303,13 @@ var handler14 = async (provider, args) => {
1201
1303
  }
1202
1304
  };
1203
1305
  }
1204
- const parsed = toolInfo14.parameters.safeParse(args);
1306
+ const parsed = toolInfo16.parameters.safeParse(args);
1205
1307
  if (!parsed.success) {
1206
1308
  return {
1207
- type: "Invalid" /* Invalid */,
1309
+ type: "Error" /* Error */,
1208
1310
  message: {
1209
1311
  type: "error-text",
1210
- value: `Invalid arguments for write_to_file: ${parsed.error.message}`
1312
+ value: `Invalid arguments for writeToFile: ${parsed.error.message}`
1211
1313
  }
1212
1314
  };
1213
1315
  }
@@ -1223,35 +1325,9 @@ var handler14 = async (provider, args) => {
1223
1325
  }
1224
1326
  };
1225
1327
  };
1226
- var isAvailable14 = (provider) => {
1227
- return !!provider.writeFile;
1228
- };
1229
1328
  var writeToFile_default = {
1230
- ...toolInfo14,
1231
- handler: handler14,
1232
- isAvailable: isAvailable14
1233
- };
1234
-
1235
- // src/getAvailableTools.ts
1236
- var getAvailableTools = ({
1237
- provider,
1238
- allTools,
1239
- hasAgent
1240
- }) => {
1241
- const tools = [];
1242
- for (const tool of allTools) {
1243
- if (!hasAgent) {
1244
- switch (tool.name) {
1245
- case handOver_default.name:
1246
- case delegate_default.name:
1247
- continue;
1248
- }
1249
- }
1250
- if (tool.isAvailable(provider)) {
1251
- tools.push(tool);
1252
- }
1253
- }
1254
- return tools;
1329
+ ...toolInfo16,
1330
+ handler: handler16
1255
1331
  };
1256
1332
 
1257
1333
  // src/UsageMeter.ts
@@ -1391,12 +1467,9 @@ var UsageMeter = class {
1391
1467
  this.#totals.cost += otherUsage.cost;
1392
1468
  this.#totals.messageCount += otherUsage.messageCount;
1393
1469
  }
1394
- /** Print a concise usage summary to console. */
1395
- printUsage(customConsole = console) {
1470
+ getUsageText() {
1396
1471
  const u = this.usage;
1397
- customConsole.log(
1398
- `Usage - messages: ${u.messageCount}, input: ${u.input}, cached: ${u.cachedRead}, output: ${u.output}, cost: $${u.cost.toFixed(4)}`
1399
- );
1472
+ return `Usage - messages: ${u.messageCount}, input: ${u.input}, cached: ${u.cachedRead}, output: ${u.output}, cost: $${u.cost.toFixed(4)}`;
1400
1473
  }
1401
1474
  onFinishHandler(llm) {
1402
1475
  return (evt) => {
@@ -1404,2197 +1477,29 @@ var UsageMeter = class {
1404
1477
  };
1405
1478
  }
1406
1479
  };
1407
-
1408
- // src/Agent/AgentBase.ts
1409
- import { jsonSchema, streamText } from "ai";
1410
- import { camelCase } from "lodash";
1411
- import { toJSONSchema } from "zod";
1412
-
1413
- // src/tool-v1-compat.ts
1414
- import { z as z15 } from "zod";
1415
- function zodSchemaToParameters(schema) {
1416
- const parameters = [];
1417
- const { shape } = schema;
1418
- for (const name in shape) {
1419
- const def = shape[name];
1420
- const isOptional = def.safeParse(void 0).success;
1421
- const description = def.description || "";
1422
- const param = {
1423
- name,
1424
- description,
1425
- required: !isOptional
1426
- };
1427
- const usageValue = def.meta()?.usageValue;
1428
- if (usageValue) {
1429
- param.usageValue = usageValue;
1430
- }
1431
- if (def instanceof z15.ZodObject) {
1432
- param.children = zodSchemaToParameters(def);
1433
- } else if (def instanceof z15.ZodArray) {
1434
- param.allowMultiple = true;
1435
- const element = def.element;
1436
- if (element instanceof z15.ZodObject) {
1437
- param.children = zodSchemaToParameters(element);
1438
- }
1439
- }
1440
- parameters.push(param);
1441
- }
1442
- return parameters;
1443
- }
1444
- function toToolInfoV1(tool) {
1445
- const { parameters: zodSchema, ...rest } = tool;
1446
- const v1Parameters = zodSchemaToParameters(zodSchema);
1447
- const examples = zodSchema.meta()?.examples;
1448
- const v1Tool = {
1449
- ...rest,
1450
- parameters: v1Parameters
1451
- };
1452
- if (examples) {
1453
- v1Tool.examples = examples;
1454
- }
1455
- return v1Tool;
1456
- }
1457
-
1458
- // src/Agent/backoff.ts
1459
- function computeRateLimitBackoffSeconds(count, baseSeconds = 2, capSeconds = 60) {
1460
- if (!Number.isFinite(count) || count <= 0) {
1461
- count = 1;
1462
- }
1463
- if (!Number.isFinite(baseSeconds) || baseSeconds <= 0) {
1464
- baseSeconds = 2;
1465
- }
1466
- if (!Number.isFinite(capSeconds) || capSeconds <= 0) {
1467
- capSeconds = 60;
1468
- }
1469
- const delay = baseSeconds * 2 ** (count - 1);
1470
- return Math.min(delay, capSeconds);
1471
- }
1472
-
1473
- // src/Agent/parseAssistantMessage.ts
1474
- function parseNestedParameters(content, parameterPrefix, childrenParams) {
1475
- const result = {};
1476
- const nestedParamRegex = new RegExp(`<${parameterPrefix}([^>]+)>([\\s\\S]*?)<\\/${parameterPrefix}\\1>`, "gs");
1477
- const arrayParams = /* @__PURE__ */ new Set();
1478
- if (childrenParams) {
1479
- for (const param of childrenParams) {
1480
- if (param.allowMultiple) {
1481
- arrayParams.add(param.name);
1482
- }
1483
- }
1484
- }
1485
- while (true) {
1486
- const match = nestedParamRegex.exec(content);
1487
- if (match === null) break;
1488
- const paramName = match[1];
1489
- const paramContent = match[2].trim();
1490
- const childParam = childrenParams?.find((p) => p.name === paramName);
1491
- if (paramContent.includes(`<${parameterPrefix}`) && childParam?.children) {
1492
- const nestedResult = parseNestedParameters(paramContent, parameterPrefix, childParam.children);
1493
- if (arrayParams.has(paramName)) {
1494
- if (!result[paramName]) {
1495
- result[paramName] = [];
1496
- }
1497
- if (Array.isArray(result[paramName])) {
1498
- result[paramName].push(nestedResult);
1499
- } else {
1500
- result[paramName] = [nestedResult];
1501
- }
1502
- } else {
1503
- result[paramName] = nestedResult;
1504
- }
1505
- } else if (arrayParams.has(paramName)) {
1506
- if (!result[paramName]) {
1507
- result[paramName] = [];
1508
- }
1509
- if (Array.isArray(result[paramName])) {
1510
- result[paramName].push(paramContent);
1511
- } else {
1512
- result[paramName] = [paramContent];
1513
- }
1514
- } else {
1515
- result[paramName] = paramContent;
1516
- }
1517
- }
1518
- return result;
1519
- }
1520
- function parseAssistantMessage(assistantMessage, tools, toolNamePrefix) {
1521
- const parameterPrefix = `${toolNamePrefix}parameter_`;
1522
- const results = [];
1523
- const toolTags = tools.map((tool) => `${toolNamePrefix}${tool.name}`);
1524
- const toolPattern = toolTags.join("|");
1525
- let remainingMessage = assistantMessage;
1526
- let match;
1527
- const tagRegex = new RegExp(`<(${toolPattern})>([\\s\\S]*?)<\\/\\1>`, "s");
1528
- while (true) {
1529
- match = tagRegex.exec(remainingMessage);
1530
- if (match === null) break;
1531
- const beforeTag = remainingMessage.slice(0, match.index).trim();
1532
- if (beforeTag) {
1533
- results.push({
1534
- type: "text",
1535
- content: beforeTag
1536
- });
1537
- }
1538
- const tagName = match[1];
1539
- const toolName = tagName.replace(toolNamePrefix, "");
1540
- const tool = tools.find((t) => t.name === toolName);
1541
- const fullTagContent = match[0];
1542
- if (tool) {
1543
- const params = {};
1544
- for (const param of tool.parameters) {
1545
- const paramName = `${parameterPrefix}${param.name}`;
1546
- const escapedParamName = paramName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1547
- const paramRegex = new RegExp(`<${escapedParamName}>([\\s\\S]*?)<\\/${escapedParamName}>`, "gs");
1548
- const paramMatches = [];
1549
- while (true) {
1550
- const paramMatch = paramRegex.exec(fullTagContent);
1551
- if (paramMatch === null) break;
1552
- paramMatches.push(paramMatch[1].trim());
1553
- }
1554
- if (paramMatches.length > 0) {
1555
- if (paramMatches.length === 1 && !param.allowMultiple) {
1556
- const paramContent = paramMatches[0];
1557
- if (paramContent.includes(`<${parameterPrefix}`) && param.children) {
1558
- params[param.name] = parseNestedParameters(paramContent, parameterPrefix, param.children);
1559
- } else {
1560
- params[param.name] = paramContent;
1561
- }
1562
- } else {
1563
- if (param.allowMultiple) {
1564
- params[param.name] = paramMatches.map((paramContent) => {
1565
- if (paramContent.includes(`<${parameterPrefix}`) && param.children) {
1566
- return parseNestedParameters(paramContent, parameterPrefix, param.children);
1567
- }
1568
- return paramContent;
1569
- });
1570
- } else {
1571
- const paramContent = paramMatches[0];
1572
- if (paramContent.includes(`<${parameterPrefix}`) && param.children) {
1573
- params[param.name] = parseNestedParameters(paramContent, parameterPrefix, param.children);
1574
- } else {
1575
- params[param.name] = paramContent;
1576
- }
1577
- }
1578
- }
1579
- }
1580
- }
1581
- results.push({
1582
- type: "tool_use",
1583
- name: toolName,
1584
- params
1585
- });
1586
- } else {
1587
- results.push({
1588
- type: "text",
1589
- content: fullTagContent
1590
- });
1591
- }
1592
- remainingMessage = remainingMessage.slice(match.index + fullTagContent.length);
1593
- }
1594
- if (remainingMessage.trim()) {
1595
- results.push({
1596
- type: "text",
1597
- content: remainingMessage.trim()
1598
- });
1599
- }
1600
- if (results.length === 0) {
1601
- results.push({
1602
- type: "text",
1603
- content: assistantMessage
1604
- });
1605
- }
1606
- return results;
1607
- }
1608
-
1609
- // src/Agent/prompts.ts
1610
- var renderParameterValue = (key, value, parameterPrefix) => {
1611
- if (typeof value === "string") {
1612
- return `<${parameterPrefix}${key}>${value}</${parameterPrefix}${key}>`;
1613
- }
1614
- if (Array.isArray(value)) {
1615
- return value.map((v) => renderParameterValue(key, v, parameterPrefix)).join("\n");
1616
- }
1617
- const inner = Object.entries(value).map(([key2, v]) => renderParameterValue(key2, v, parameterPrefix)).join("\n");
1618
- return `<${parameterPrefix}${key}>
1619
- ${inner}
1620
- </${parameterPrefix}${key}>`;
1621
- };
1622
- var toolInfoPrompt = (tool, toolNamePrefix, parameterPrefix) => `
1623
- ## ${toolNamePrefix}${tool.name}
1624
-
1625
- Description: ${tool.description}
1626
-
1627
- Parameters:
1628
- ${tool.parameters.map(
1629
- (param) => `- ${parameterPrefix}${param.name}: (${param.required ? "required" : "optional"})${param.allowMultiple ? " (multiple allowed)" : ""} ${param.description}`
1630
- ).join("\n")}
1631
-
1632
- Usage:
1633
- <${toolNamePrefix}${tool.name}>
1634
- ${tool.parameters.map(
1635
- (param) => param.allowMultiple ? `<${parameterPrefix}${param.name}>${param.usageValue}</${parameterPrefix}${param.name}>
1636
- <${parameterPrefix}${param.name}>${param.usageValue}</${parameterPrefix}${param.name}>` : `<${parameterPrefix}${param.name}>${param.usageValue}</${parameterPrefix}${param.name}>`
1637
- ).join("\n")}
1638
- </${toolNamePrefix}${tool.name}>`;
1639
- var toolInfoExamplesPrompt = (tool, example, toolNamePrefix, parameterPrefix) => `
1640
- ## Example: ${example.description}
1641
-
1642
- <${toolNamePrefix}${tool.name}>
1643
- ${Object.entries(example.input).map(([name, value]) => renderParameterValue(name, value, parameterPrefix)).join("\n")}
1644
- </${toolNamePrefix}${tool.name}>
1645
- `;
1646
- var toolUsePrompt = (useNativeTool, tools, toolNamePrefix) => {
1647
- if (useNativeTool) {
1648
- return `
1649
- ====
1650
-
1651
- TOOL USE
1652
-
1653
- - You MUST use a tool.
1654
- - Batch tool use when feasible; avoid redundant calls.
1655
- `;
1656
- }
1657
- if (tools.length === 0) {
1658
- return "";
1659
- }
1660
- const parameterPrefix = `${toolNamePrefix}parameter_`;
1661
- const v1Tools = tools.map(toToolInfoV1);
1662
- return `
1663
- ====
1664
-
1665
- TOOL USE
1666
-
1667
- You have access to a set of tools that are executed upon the user's approval. You can use up to 5 tool calls per message, and will receive the results of those tool uses in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
1668
-
1669
- # Tool Use Formatting
1670
-
1671
- Tool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:
1672
-
1673
- <${toolNamePrefix}tool_name>
1674
- <${parameterPrefix}name1>value1</${parameterPrefix}name1>
1675
- <${parameterPrefix}name2>value2</${parameterPrefix}name2>
1676
- ...
1677
- </${toolNamePrefix}tool_name>
1678
-
1679
- **It is crucial that all tags are correctly nested and closed.**
1680
-
1681
- ## Array Parameters
1682
-
1683
- To create an array of values for a parameter, repeat the parameter tag multiple times:
1684
-
1685
- <${toolNamePrefix}process_file>
1686
- <${parameterPrefix}path>test.ts</${parameterPrefix}path>
1687
- <${parameterPrefix}path>main.ts</${parameterPrefix}path>
1688
- </${toolNamePrefix}process_file>
1689
-
1690
- ## Nested Object Parameters
1691
-
1692
- To create nested objects, nest parameter tags within other parameter tags:
1693
-
1694
- <${toolNamePrefix}example_tool>
1695
- <${parameterPrefix}key>
1696
- <${parameterPrefix}key2>value</${parameterPrefix}key2>
1697
- <${parameterPrefix}key3>value2</${parameterPrefix}key3>
1698
- </${parameterPrefix}key>
1699
- </${toolNamePrefix}example_tool>
1700
-
1701
- You can also combine array parameters with nested objects:
1702
-
1703
- <${toolNamePrefix}example_tool>
1704
- <${parameterPrefix}key>
1705
- <${parameterPrefix}key2>value</${parameterPrefix}key2>
1706
- <${parameterPrefix}key3>value2</${parameterPrefix}key3>
1707
- </${parameterPrefix}key>
1708
- <${parameterPrefix}key>
1709
- <${parameterPrefix}key2>value3</${parameterPrefix}key2>
1710
- <${parameterPrefix}key3>value4</${parameterPrefix}key3>
1711
- <${parameterPrefix}key3>value5</${parameterPrefix}key3>
1712
- </${parameterPrefix}key>
1713
- </${toolNamePrefix}example_tool>
1714
-
1715
- Always adhere to this format, ensuring every opening tag has a matching closing tag, to ensure proper parsing and execution.
1716
-
1717
- NEVER surround tool use with triple backticks (\`\`\`).
1718
-
1719
- # Tools
1720
- ${v1Tools.map((tool) => toolInfoPrompt(tool, toolNamePrefix, parameterPrefix)).join("\n")}
1721
-
1722
- # Tool Use Examples
1723
- ${v1Tools.map((tool) => {
1724
- let promp = "";
1725
- for (const example of tool.examples ?? []) {
1726
- promp += toolInfoExamplesPrompt(tool, example, toolNamePrefix, parameterPrefix);
1727
- }
1728
- return promp;
1729
- }).join("")}
1730
- # Tool Use Guidelines
1731
-
1732
- 1. **Wait for Feedback**
1733
- - After using a tool, wait for the user's response indicating success/failure or any output logs. Do not assume the result of a tool without explicit confirmation.
1734
- 2. **Error Handling**
1735
- - If a tool fails or produces an unexpected result, analyze the error, decide on an alternative approach or tool, and proceed carefully.
1736
- 3. **Avoid Repetition**
1737
- - Do not quote or repeat previous commands or prompts verbatim. Move the conversation forward by focusing on the latest required action.
1738
- 4. **Tool Call Limit**
1739
- - It is **STRIGHTLY FORBIDDEN** to make more than 5 tool calls in a single message.`;
1740
- };
1741
- var agentsPrompt = (agents, name) => `
1742
- ====
1743
-
1744
- AVAILABLE AGENTS
1745
-
1746
- The following agents are available for task handover/delegate:
1747
- ${agents.map(
1748
- (agent) => `
1749
- - **${agent.name}**
1750
- - Responsibilities:
1751
- ${agent.responsibilities.map((resp) => ` - ${resp}`).join("\n")}`
1752
- ).join("\n")}
1753
-
1754
- - **Current Agent Role**
1755
- You are currently acting as **${name}**. If you identify the task is beyond your current scope, use the handover or delegate tool to transition to the other agent. Include sufficient context so the new agent can seamlessly continue the work.
1756
- `;
1757
- var capabilities = (_toolNamePrefix) => `
1758
- ====
1759
-
1760
- CAPABILITIES
1761
-
1762
- - You have access to a range of tools to aid you in your work. These tools help you effectively accomplish a wide range of tasks.
1763
- - When the user initially gives you a task, a recursive list of all filepaths in the current working directory will be included in context. This provides an overview of the project's file structure, offering key insights into the project from directory/file names (how developers conceptualize and organize their code) and file extensions (the language used). This can also guide decision-making on which files to explore further.`;
1764
- var systemInformation = (info) => `
1765
- ====
1766
-
1767
- SYSTEM INFORMATION
1768
-
1769
- Operating System: ${info.os}`;
1770
- var customInstructions = (customInstructions2) => {
1771
- const joined = customInstructions2.join("\n");
1772
- if (joined.trim() === "") {
1773
- return "";
1774
- }
1775
- return `
1776
- ====
1777
-
1778
- USER'S CUSTOM INSTRUCTIONS
1779
-
1780
- The following additional instructions are provided by the user, and should be followed to the best of your ability without interfering with the TOOL USE guidelines.
1781
-
1782
- ${joined}`;
1783
- };
1784
- var customScripts = (commands) => {
1785
- const joined = Object.entries(commands).map(([name, command]) => {
1786
- if (typeof command === "string") {
1787
- return `- ${name}
1788
- - Command: \`${command}\``;
1789
- }
1790
- return `- ${name}
1791
- - Command: \`${command.command}\`
1792
- - Description: ${command.description}`;
1793
- }).join("\n");
1794
- if (joined.trim() === "") {
1795
- return "";
1796
- }
1797
- return `
1798
- ====
1799
-
1800
- USER'S CUSTOM COMMANDS
1801
-
1802
- The following additional commands are provided by the user, and should be followed to the best of your ability without interfering with the TOOL USE guidelines.
1803
-
1804
- ${joined}`;
1805
- };
1806
- var responsePrompts = {
1807
- errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
1808
- requireUseTool: `Error: No tool use detected. You MUST use a tool before proceeding.
1809
- e.g. <tool_tool_name>tool_name</tool_tool_name>
1810
-
1811
- Ensure the opening and closing tags are correctly nested and closed, and that you are using the correct tool name.
1812
- Avoid unnecessary text or symbols before or after the tool use.
1813
- Avoid unnecessary escape characters or special characters.
1814
- `,
1815
- requireUseToolNative: `Error: No tool use detected. You MUST use a tool before proceeding.
1816
- `,
1817
- toolResults: (tool, result) => {
1818
- switch (result.type) {
1819
- case "text":
1820
- return [
1821
- {
1822
- type: "text",
1823
- text: `<tool_response name=${tool}>${result.value}</tool_response>`
1824
- }
1825
- ];
1826
- case "error-text":
1827
- return [
1828
- {
1829
- type: "text",
1830
- text: `<tool_response_error name=${tool}>${result.value}</tool_response_error>`
1831
- }
1832
- ];
1833
- case "json":
1834
- return [
1835
- {
1836
- type: "text",
1837
- text: `<tool_response_json name=${tool}>${JSON.stringify(result.value)}</tool_response_json>`
1838
- }
1839
- ];
1840
- case "error-json":
1841
- return [
1842
- {
1843
- type: "text",
1844
- text: `<tool_response_error_json name=${tool}>${JSON.stringify(result.value)}</tool_response_error_json>`
1845
- }
1846
- ];
1847
- case "content":
1848
- return [
1849
- {
1850
- type: "text",
1851
- text: `<tool_response name=${tool}>`
1852
- },
1853
- ...result.value.map((part) => {
1854
- if (part.type === "text") {
1855
- return part;
1856
- }
1857
- if (part.mediaType.startsWith("image/")) {
1858
- return {
1859
- type: "image",
1860
- mediaType: part.mediaType,
1861
- image: part.data
1862
- };
1863
- }
1864
- return {
1865
- type: "file",
1866
- mediaType: part.mediaType,
1867
- data: part.data
1868
- };
1869
- }),
1870
- {
1871
- type: "text",
1872
- text: "</tool_response>"
1873
- }
1874
- ];
1875
- }
1876
- },
1877
- commandResult: (command, exitCode, stdout, stderr) => `<command>${command}</command>
1878
- <command_exit_code>${exitCode}</command_exit_code>
1879
- <command_stdout>
1880
- ${stdout}
1881
- </command_stdout>
1882
- <command_stderr>
1883
- ${stderr}
1884
- </command_stderr>`
1885
- };
1886
-
1887
- // src/Agent/AgentBase.ts
1888
- var TaskEventKind = /* @__PURE__ */ ((TaskEventKind2) => {
1889
- TaskEventKind2["StartTask"] = "StartTask";
1890
- TaskEventKind2["StartRequest"] = "StartRequest";
1891
- TaskEventKind2["EndRequest"] = "EndRequest";
1892
- TaskEventKind2["Usage"] = "Usage";
1893
- TaskEventKind2["Text"] = "Text";
1894
- TaskEventKind2["Reasoning"] = "Reasoning";
1895
- TaskEventKind2["ToolUse"] = "ToolUse";
1896
- TaskEventKind2["ToolReply"] = "ToolReply";
1897
- TaskEventKind2["ToolInvalid"] = "ToolInvalid";
1898
- TaskEventKind2["ToolError"] = "ToolError";
1899
- TaskEventKind2["ToolInterrupted"] = "ToolInterrupted";
1900
- TaskEventKind2["ToolHandOver"] = "ToolHandOver";
1901
- TaskEventKind2["ToolDelegate"] = "ToolDelegate";
1902
- TaskEventKind2["ToolPause"] = "ToolPause";
1903
- TaskEventKind2["UsageExceeded"] = "UsageExceeded";
1904
- TaskEventKind2["EndTask"] = "EndTask";
1905
- return TaskEventKind2;
1906
- })(TaskEventKind || {});
1907
- var AgentBase = class {
1908
- ai;
1909
- config;
1910
- handlers;
1911
- #policies;
1912
- #toolSet;
1913
- #messages = [];
1914
- #aborted = false;
1915
- #abortController;
1916
- constructor(name, ai, config) {
1917
- this.ai = ai;
1918
- if (config.agents && config.agents.length > 0) {
1919
- const agents = agentsPrompt(config.agents, name);
1920
- config.systemPrompt += `
1921
- ${agents}`;
1922
- }
1923
- const handlers = {};
1924
- for (const tool of config.tools) {
1925
- handlers[tool.name] = tool;
1926
- }
1927
- const policies = [];
1928
- for (const policy of config.policies) {
1929
- const instance = policy(handlers, config.parameters);
1930
- if (instance) {
1931
- policies.push(instance);
1932
- if (instance.prompt) {
1933
- config.systemPrompt += `
1934
- ${instance.prompt}`;
1935
- }
1936
- if (instance.tools) {
1937
- for (const tool of instance.tools) {
1938
- handlers[tool.name] = tool;
1939
- }
1940
- }
1941
- }
1942
- }
1943
- this.handlers = handlers;
1944
- this.config = config;
1945
- this.#policies = policies;
1946
- this.#messages.push({
1947
- role: "system",
1948
- content: this.config.systemPrompt
1949
- });
1950
- if (this.config.toolFormat === "native") {
1951
- const tools = {};
1952
- for (const tool of Object.values(this.handlers)) {
1953
- const toolName = camelCase(tool.name);
1954
- tools[toolName] = {
1955
- description: tool.description,
1956
- inputSchema: jsonSchema(toJSONSchema(tool.parameters))
1957
- };
1958
- this.handlers[toolName] = tool;
1959
- }
1960
- this.#toolSet = tools;
1961
- } else {
1962
- this.#toolSet = {};
1963
- }
1964
- }
1965
- abort() {
1966
- this.#aborted = true;
1967
- if (this.#abortController) {
1968
- this.#abortController.abort();
1969
- }
1970
- }
1971
- get parameters() {
1972
- return this.config.parameters;
1973
- }
1974
- get messages() {
1975
- return this.#messages;
1976
- }
1977
- setMessages(messages) {
1978
- this.#messages = [...messages];
1979
- }
1980
- async #callback(event) {
1981
- await this.config.callback?.(event);
1982
- }
1983
- async start(prompt2) {
1984
- this.#callback({ kind: "StartTask" /* StartTask */, agent: this, systemPrompt: this.config.systemPrompt });
1985
- return await this.#processLoop(prompt2);
1986
- }
1987
- async step(message) {
1988
- if (this.#messages.length === 0) {
1989
- this.#callback({ kind: "StartTask" /* StartTask */, agent: this, systemPrompt: this.config.systemPrompt });
1990
- }
1991
- return await this.#request(message);
1992
- }
1993
- async handleStepResponse(response) {
1994
- return this.#handleResponse(response);
1995
- }
1996
- async #processLoop(userMessage) {
1997
- let nextRequest = [
1998
- {
1999
- role: "user",
2000
- content: userMessage
2001
- }
2002
- ];
2003
- while (true) {
2004
- if (this.#aborted) {
2005
- return { type: "Aborted" };
2006
- }
2007
- if (this.config.usageMeter.isLimitExceeded().result) {
2008
- this.#callback({ kind: "UsageExceeded" /* UsageExceeded */, agent: this });
2009
- return { type: "UsageExceeded" };
2010
- }
2011
- const response = await this.#request(nextRequest);
2012
- if (this.#aborted) {
2013
- return { type: "Aborted" };
2014
- }
2015
- const resp = await this.#handleResponse(response);
2016
- if (resp.type === "exit") {
2017
- this.#callback({ kind: "EndTask" /* EndTask */, agent: this, exitReason: resp.reason });
2018
- return resp.reason;
2019
- }
2020
- nextRequest = resp.message;
2021
- }
2022
- }
2023
- async continueTask(userMessage) {
2024
- return await this.#processLoop(userMessage);
2025
- }
2026
- async #request(userMessage) {
2027
- if (!userMessage) {
2028
- throw new Error("userMessage is missing");
2029
- }
2030
- await this.#callback({ kind: "StartRequest" /* StartRequest */, agent: this, userMessage });
2031
- this.#messages.push(...userMessage);
2032
- for (const instance of this.#policies) {
2033
- if (instance.onBeforeRequest) {
2034
- await instance.onBeforeRequest(this);
2035
- }
2036
- }
2037
- let messages = this.#messages;
2038
- for (const instance of this.#policies) {
2039
- if (instance.prepareMessages) {
2040
- messages = await instance.prepareMessages(this, messages);
2041
- }
2042
- }
2043
- const retryCount = this.config.retryCount ?? 5;
2044
- const requestTimeoutSeconds = this.config.requestTimeoutSeconds ?? 90;
2045
- let respMessages = [];
2046
- let rateLimitErrorCount = 0;
2047
- for (let i = 0; i < retryCount; i++) {
2048
- if (this.#aborted) {
2049
- break;
2050
- }
2051
- respMessages = [];
2052
- let timeout;
2053
- let requestAbortController;
2054
- requestAbortController = new AbortController();
2055
- this.#abortController = requestAbortController;
2056
- const resetTimeout = () => {
2057
- if (timeout) {
2058
- clearTimeout(timeout);
2059
- }
2060
- if (requestTimeoutSeconds > 0 && requestAbortController) {
2061
- timeout = setTimeout(() => {
2062
- console.error(
2063
- `
2064
- Request timeout after ${requestTimeoutSeconds} seconds. Canceling current request attempt ${i + 1}/${retryCount}.`
2065
- );
2066
- requestAbortController?.abort();
2067
- }, requestTimeoutSeconds * 1e3);
2068
- }
2069
- };
2070
- try {
2071
- resetTimeout();
2072
- const usageMeterOnFinishHandler = this.config.usageMeter.onFinishHandler(this.ai);
2073
- const streamTextOptions = {
2074
- model: this.ai,
2075
- temperature: 0,
2076
- messages,
2077
- providerOptions: this.config.parameters?.providerOptions,
2078
- onChunk: async ({ chunk }) => {
2079
- resetTimeout();
2080
- switch (chunk.type) {
2081
- case "text-delta":
2082
- await this.#callback({ kind: "Text" /* Text */, agent: this, newText: chunk.text });
2083
- break;
2084
- case "reasoning-delta":
2085
- await this.#callback({ kind: "Reasoning" /* Reasoning */, agent: this, newText: chunk.text });
2086
- break;
2087
- case "tool-call":
2088
- break;
2089
- }
2090
- },
2091
- onFinish: (evt) => {
2092
- usageMeterOnFinishHandler(evt);
2093
- this.#callback({ kind: "Usage" /* Usage */, agent: this, usage: evt.totalUsage });
2094
- },
2095
- onError: async (error) => {
2096
- console.error("Error in stream:", error);
2097
- },
2098
- abortSignal: requestAbortController.signal
2099
- };
2100
- if (this.config.toolFormat === "native") {
2101
- streamTextOptions.tools = this.#toolSet;
2102
- }
2103
- const stream = streamText(streamTextOptions);
2104
- await stream.consumeStream({
2105
- onError: (error) => {
2106
- console.error("Error in stream:", error);
2107
- }
2108
- });
2109
- const resp = await stream.response;
2110
- respMessages = resp.messages;
2111
- rateLimitErrorCount = 0;
2112
- if (timeout) {
2113
- clearTimeout(timeout);
2114
- timeout = void 0;
2115
- }
2116
- } catch (error) {
2117
- if (error instanceof Error && error.name === "AbortError") {
2118
- if (this.#aborted) {
2119
- break;
2120
- }
2121
- console.error(`Request attempt ${i + 1} timed out, will retry`);
2122
- } else if (error?.error?.error?.code === "rate_limit_exceeded" || error?.error?.code === "rate_limit_exceeded" || error?.code === "rate_limit_exceeded" || error?.status === 429 || error?.error?.status === 429) {
2123
- rateLimitErrorCount++;
2124
- const waitSeconds = computeRateLimitBackoffSeconds(rateLimitErrorCount);
2125
- console.error(`Rate limit exceeded. Waiting ${waitSeconds}s before retrying...`);
2126
- if (timeout) {
2127
- clearTimeout(timeout);
2128
- timeout = void 0;
2129
- }
2130
- await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1e3));
2131
- console.error("Retrying request...");
2132
- } else {
2133
- rateLimitErrorCount = 0;
2134
- console.error("Error in stream:", error);
2135
- }
2136
- } finally {
2137
- if (timeout) {
2138
- clearTimeout(timeout);
2139
- }
2140
- }
2141
- if (this.config.toolFormat === "native") {
2142
- if (respMessages.some((m) => {
2143
- if (m.role === "tool") {
2144
- return true;
2145
- }
2146
- if (typeof m.content === "string") {
2147
- return true;
2148
- }
2149
- return m.content.some((part) => part.type === "tool-call" || part.type === "tool-result" || part.type === "text");
2150
- })) {
2151
- break;
2152
- }
2153
- } else {
2154
- if (respMessages.length > 0) {
2155
- break;
2156
- }
2157
- }
2158
- if (this.#aborted) {
2159
- break;
2160
- }
2161
- if (i < retryCount - 1) {
2162
- console.error(`
2163
- Retrying request ${i + 2} of ${retryCount}`);
2164
- }
2165
- }
2166
- if (respMessages.length === 0) {
2167
- if (this.#aborted) {
2168
- return [];
2169
- }
2170
- throw new Error("No assistant message received after all retry attempts");
2171
- }
2172
- this.#messages.push(...respMessages);
2173
- if (this.config.toolFormat === "native") {
2174
- const assistantText = respMessages.map((msg) => {
2175
- if (typeof msg.content === "string") {
2176
- return msg.content;
2177
- }
2178
- return msg.content.map((part) => part.type === "text" || part.type === "reasoning" ? part.text : "").join("");
2179
- }).join("\n");
2180
- await this.#callback({ kind: "EndRequest" /* EndRequest */, agent: this, message: assistantText });
2181
- return respMessages.flatMap((msg) => {
2182
- if (msg.role === "assistant") {
2183
- const content = msg.content;
2184
- if (typeof content === "string") {
2185
- return [{ type: "text", content }];
2186
- }
2187
- return content.flatMap((part) => {
2188
- if (part.type === "text" || part.type === "reasoning") {
2189
- return [{ type: "text", content: part.text }];
2190
- }
2191
- if (part.type === "tool-call") {
2192
- return [{ type: "tool_use", id: part.toolCallId, name: part.toolName, params: part.input }];
2193
- }
2194
- return [];
2195
- });
2196
- }
2197
- return [];
2198
- });
2199
- }
2200
- const currentAssistantMessage = respMessages.map((msg) => {
2201
- if (typeof msg.content === "string") {
2202
- return msg.content;
2203
- }
2204
- return msg.content.map((part) => {
2205
- if (part.type === "text") {
2206
- return part.text;
2207
- }
2208
- return "";
2209
- });
2210
- }).join("\n");
2211
- const ret = parseAssistantMessage(currentAssistantMessage, this.config.tools.map(toToolInfoV1), this.config.toolNamePrefix);
2212
- await this.#callback({ kind: "EndRequest" /* EndRequest */, agent: this, message: currentAssistantMessage });
2213
- return ret;
2214
- }
2215
- async #handleResponse(response) {
2216
- const toolResponses = [];
2217
- const medias = [];
2218
- const processResponse = (resp) => {
2219
- if (resp.type === "content") {
2220
- return {
2221
- type: "content",
2222
- value: resp.value.map((part) => {
2223
- if (part.type === "media") {
2224
- medias.push(part);
2225
- return {
2226
- type: "text",
2227
- text: `<media url="${part.url}" media-type="${part.mediaType}" />`
2228
- };
2229
- }
2230
- return part;
2231
- })
2232
- };
2233
- }
2234
- return resp;
2235
- };
2236
- let hasPause = false;
2237
- const toolUseContents = response.filter((c) => c.type === "tool_use");
2238
- outer: for (const content of response) {
2239
- switch (content.type) {
2240
- case "text":
2241
- break;
2242
- case "tool_use": {
2243
- await this.#callback({ kind: "ToolUse" /* ToolUse */, agent: this, tool: content.name, params: content.params });
2244
- const toolResp = await this.#invokeTool(content.name, content.params);
2245
- switch (toolResp.type) {
2246
- case "Reply" /* Reply */: {
2247
- await this.#callback({ kind: "ToolReply" /* ToolReply */, agent: this, tool: content.name, content: toolResp.message });
2248
- toolResponses.push({ type: "response", tool: content.name, response: processResponse(toolResp.message), id: content.id });
2249
- break;
2250
- }
2251
- case "Exit" /* Exit */:
2252
- case "HandOver" /* HandOver */:
2253
- case "Delegate" /* Delegate */: {
2254
- if (this.config.toolFormat === "native" && toolUseContents.length > 1) {
2255
- const message = {
2256
- type: "Error" /* Error */,
2257
- message: {
2258
- type: "error-text",
2259
- value: `Error: The tool '${content.name}' must be called alone, but it was called with other tools.`
2260
- },
2261
- canRetry: false
2262
- };
2263
- await this.#callback({ kind: "ToolError" /* ToolError */, agent: this, tool: content.name, error: message });
2264
- toolResponses.push({
2265
- type: "response",
2266
- tool: content.name,
2267
- response: processResponse(message.message),
2268
- id: content.id
2269
- });
2270
- break;
2271
- }
2272
- if (toolResponses.length > 0) {
2273
- break outer;
2274
- }
2275
- if (toolResp.type === "Exit" /* Exit */) {
2276
- return { type: "exit", reason: toolResp };
2277
- }
2278
- if (toolResp.type === "HandOver" /* HandOver */) {
2279
- await this.#callback({
2280
- kind: "ToolHandOver" /* ToolHandOver */,
2281
- agent: this,
2282
- tool: content.name,
2283
- agentName: toolResp.agentName,
2284
- task: toolResp.task,
2285
- context: toolResp.context,
2286
- files: toolResp.files
2287
- });
2288
- return { type: "exit", reason: toolResp };
2289
- }
2290
- if (toolResp.type === "Delegate" /* Delegate */) {
2291
- await this.#callback({
2292
- kind: "ToolDelegate" /* ToolDelegate */,
2293
- agent: this,
2294
- tool: content.name,
2295
- agentName: toolResp.agentName,
2296
- task: toolResp.task,
2297
- context: toolResp.context,
2298
- files: toolResp.files
2299
- });
2300
- return { type: "exit", reason: toolResp };
2301
- }
2302
- break;
2303
- }
2304
- case "Invalid" /* Invalid */: {
2305
- await this.#callback({ kind: "ToolInvalid" /* ToolInvalid */, agent: this, tool: content.name, content: toolResp.message });
2306
- toolResponses.push({ type: "response", tool: content.name, response: processResponse(toolResp.message), id: content.id });
2307
- if (this.config.toolFormat !== "native") {
2308
- break outer;
2309
- }
2310
- break;
2311
- }
2312
- case "Error" /* Error */: {
2313
- await this.#callback({ kind: "ToolError" /* ToolError */, agent: this, tool: content.name, error: toolResp.message });
2314
- toolResponses.push({ type: "response", tool: content.name, response: processResponse(toolResp.message), id: content.id });
2315
- if (this.config.toolFormat !== "native") {
2316
- break outer;
2317
- }
2318
- break;
2319
- }
2320
- case "Pause" /* Pause */: {
2321
- await this.#callback({ kind: "ToolPause" /* ToolPause */, agent: this, tool: content.name, object: toolResp.object });
2322
- toolResponses.push({ type: "pause", tool: content.name, object: toolResp.object, id: content.id });
2323
- hasPause = true;
2324
- }
2325
- }
2326
- break;
2327
- }
2328
- }
2329
- }
2330
- if (hasPause) {
2331
- return { type: "exit", reason: { type: "Pause", responses: toolResponses } };
2332
- }
2333
- if (toolResponses.length === 0) {
2334
- if (this.config.requireToolUse) {
2335
- return {
2336
- type: "reply",
2337
- message: [
2338
- {
2339
- role: "user",
2340
- content: responsePrompts.requireUseToolNative
2341
- }
2342
- ]
2343
- };
2344
- }
2345
- return {
2346
- type: "exit",
2347
- reason: {
2348
- type: "Exit" /* Exit */,
2349
- message: response.filter((c) => c.type === "text").map((c) => c.content).join("")
2350
- }
2351
- };
2352
- }
2353
- const mediaUserMessage = medias.length > 0 ? [
2354
- {
2355
- role: "user",
2356
- content: medias.map((m) => {
2357
- if (m.mediaType.startsWith("image/")) {
2358
- return {
2359
- type: "image",
2360
- image: m.base64Data,
2361
- mediaType: m.mediaType
2362
- };
2363
- }
2364
- return {
2365
- type: "file",
2366
- data: m.base64Data,
2367
- mediaType: m.mediaType,
2368
- filename: m.url.split("/").pop()
2369
- };
2370
- })
2371
- }
2372
- ] : [];
2373
- if (this.config.toolFormat === "native") {
2374
- const toolResults = toolResponses.filter((resp) => resp.type === "response").map(
2375
- (resp) => ({
2376
- type: "tool-result",
2377
- toolCallId: resp.id,
2378
- toolName: resp.tool,
2379
- output: resp.response
2380
- })
2381
- );
2382
- return {
2383
- type: "reply",
2384
- message: [
2385
- {
2386
- role: "tool",
2387
- content: toolResults
2388
- },
2389
- ...mediaUserMessage
2390
- ]
2391
- };
2392
- }
2393
- if (toolResponses.length === 0) {
2394
- if (this.config.requireToolUse) {
2395
- return {
2396
- type: "reply",
2397
- message: [
2398
- {
2399
- role: "user",
2400
- content: responsePrompts.requireUseTool
2401
- }
2402
- ]
2403
- };
2404
- }
2405
- return {
2406
- type: "exit",
2407
- reason: {
2408
- type: "Exit" /* Exit */,
2409
- message: response.filter((c) => c.type === "text").map((c) => c.content).join("")
2410
- }
2411
- };
2412
- }
2413
- const finalResp = toolResponses.filter((resp) => resp.type === "response").flatMap(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2));
2414
- return {
2415
- type: "reply",
2416
- message: [
2417
- {
2418
- role: "user",
2419
- content: finalResp
2420
- },
2421
- ...mediaUserMessage
2422
- ]
2423
- };
2424
- }
2425
- async #invokeTool(name, args) {
2426
- try {
2427
- const handler15 = this.handlers[name]?.handler;
2428
- if (!handler15) {
2429
- return {
2430
- type: "Error" /* Error */,
2431
- message: {
2432
- type: "error-text",
2433
- value: responsePrompts.errorInvokeTool(name, "Tool not found")
2434
- },
2435
- canRetry: false
2436
- };
2437
- }
2438
- for (const instance of this.#policies) {
2439
- if (instance.onBeforeInvokeTool) {
2440
- const resp2 = await instance.onBeforeInvokeTool(name, args);
2441
- if (resp2) {
2442
- return resp2;
2443
- }
2444
- }
2445
- }
2446
- const resp = await this.onBeforeInvokeTool(this.handlers[name].name, args);
2447
- if (resp) {
2448
- return resp;
2449
- }
2450
- return await handler15(this.config.provider, args);
2451
- } catch (error) {
2452
- return {
2453
- type: "Error" /* Error */,
2454
- message: {
2455
- type: "error-text",
2456
- value: responsePrompts.errorInvokeTool(name, error)
2457
- },
2458
- canRetry: false
2459
- };
2460
- }
2461
- }
2462
- get model() {
2463
- return `${this.ai.provider}:${this.ai.modelId}`;
2464
- }
2465
- get usage() {
2466
- return this.config.usageMeter.usage;
2467
- }
2468
- };
2469
-
2470
- // src/Agent/AnalyzerAgent/prompts.ts
2471
- var fullSystemPrompt = (info, tools, toolNamePrefix, instructions, scripts, useNativeTool) => `
2472
- # Analyzer Agent
2473
-
2474
- ## Role
2475
- You are the **Analyzer** agent, responsible for:
2476
- 1. **Project Structure Analysis** \u2013 Understand codebase organization and architecture.
2477
- 2. **Code Pattern Analysis** \u2013 Identify common patterns, conventions, and best practices.
2478
- 3. **Dependency Analysis** \u2013 Examine project dependencies and their usage.
2479
- 4. **Workflow Analysis** \u2013 Understand development tools, scripts, and processes.
2480
- 5. **Documentation Review** \u2013 Analyze documentation and code comments.
2481
-
2482
- > **Note**: The **Analyzer** agent focuses on understanding and analyzing the codebase without making modifications. Your role is to provide insights and understanding that can inform development decisions.
2483
-
2484
- ## Rules
2485
- 1. **Thoroughness**: Conduct comprehensive analysis of relevant project aspects.
2486
- 2. **Pattern Recognition**: Identify recurring patterns, conventions, and architectural decisions.
2487
- 3. **Dependency Mapping**: Track and understand relationships between components.
2488
- 4. **Workflow Understanding**: Analyze build processes, testing approaches, and development tools.
2489
- 5. **Documentation Assessment**: Review documentation quality and completeness.
2490
- 6. **Non-Modification**: Never modify code or files - focus solely on analysis.
2491
-
2492
- ${toolUsePrompt(useNativeTool, tools, toolNamePrefix)}
2493
- ${capabilities(toolNamePrefix)}
2494
- ${systemInformation(info)}
2495
- ${customInstructions(instructions)}
2496
- ${customScripts(scripts)}
2497
- `;
2498
-
2499
- // src/Agent/AnalyzerAgent/index.ts
2500
- var agentTools = [attemptCompletion_default, delegate_default, fetchUrl_default, handOver_default, listFiles_default, readBinaryFile_default, readFile_default, searchFiles_default];
2501
- var AnalyzerAgent = class extends AgentBase {
2502
- constructor(options) {
2503
- const combinedTools = [...options.additionalTools ?? [], ...agentTools];
2504
- const tools = getAvailableTools({
2505
- provider: options.provider,
2506
- allTools: combinedTools,
2507
- hasAgent: (options.agents?.length ?? 0) > 0
2508
- });
2509
- const toolNamePrefix = options.toolFormat === "native" ? "" : "tool_";
2510
- const systemPrompt = fullSystemPrompt(
2511
- {
2512
- os: options.os
2513
- },
2514
- tools,
2515
- toolNamePrefix,
2516
- options.customInstructions ?? [],
2517
- options.scripts ?? {},
2518
- options.toolFormat === "native"
2519
- );
2520
- super(analyzerAgentInfo.name, options.ai, {
2521
- systemPrompt,
2522
- tools,
2523
- toolNamePrefix,
2524
- provider: options.provider,
2525
- agents: options.agents,
2526
- scripts: options.scripts,
2527
- callback: options.callback,
2528
- policies: options.policies,
2529
- toolFormat: options.toolFormat,
2530
- parameters: options.parameters ?? {},
2531
- usageMeter: options.usageMeter ?? new UsageMeter(),
2532
- requestTimeoutSeconds: options.requestTimeoutSeconds,
2533
- requireToolUse: options.requireToolUse ?? true
2534
- });
2535
- }
2536
- onBeforeInvokeTool() {
2537
- return Promise.resolve(void 0);
2538
- }
2539
- };
2540
- var analyzerAgentInfo = {
2541
- name: "analyzer",
2542
- responsibilities: [
2543
- "Analyzing project structure and organization",
2544
- "Identifying key source code files and their relationships",
2545
- "Understanding common coding patterns and conventions",
2546
- "Examining development workflow and tooling",
2547
- "Analyzing dependencies and their usage patterns"
2548
- ]
2549
- };
2550
-
2551
- // src/Agent/ArchitectAgent/prompts.ts
2552
- var fullSystemPrompt2 = (info, tools, toolNamePrefix, instructions, scripts, useNativeTool) => `
2553
- # Architect Agent
2554
-
2555
- ## Role
2556
- You are the **Architect** agent, responsible for:
2557
- 1. **Task Analysis** - Understand requirements.
2558
- 2. **File Identification** - Select relevant files.
2559
- 3. **File Reading** - Use provided tools to gather information.
2560
- 4. **Implementation Plan** - Draft a *code-free* plan (pseudocode/interface stubs permitted).
2561
- 5. **Review & Improve** - Refine the plan.
2562
- 6. **Handover/Delegate** - Provide the final plan, context, and files to the **Coder** agent.
2563
-
2564
- > **Never** modify project files directly. Only produce the implementation plan; the **Coder** agent performs all code changes.
2565
-
2566
- ## Rules
2567
- 1. **Consistency** - Align with user objectives.
2568
- 2. **Relevance** - Consult only essential files.
2569
- 3. **Conciseness** - Be succinct; avoid repetition.
2570
- 4. **Accuracy** - Ensure conclusions are verifiable.
2571
- 5. **Clarity** - Present information in a structured format.
2572
- 6. **Minimal Queries** - Ask questions only when truly needed.
2573
- 7. **Completion** - Only use the \`attemptCompletion\` tool if the user's request has been fully satisfied and no coding tasks need to be delegated to the Coder agent.
2574
-
2575
- ## Steps
2576
- 1. **Analyze Task** - Capture goals, constraints, and success criteria.
2577
- 2. **Identify Relevant Files** - List files and justify each choice.
2578
- 3. **Read Files via Tools** - Summarize key insights.
2579
- 4. **Create Implementation Plan** - Provide a detailed, step-by-step breakdown:
2580
- * Tasks, resources, and dependencies.
2581
- * Pseudocode or interface declarations only\u2014no concrete code.
2582
- * Sufficient detail for the **Coder** to implement without follow-ups.
2583
- 5. **Review & Improve** - Confirm the plan is unambiguous and complete.
2584
- 6. **Handover/Delegate**
2585
- - If the plan consists of a single self-contained step, hand it over as one task.
2586
- - If multiple steps are required, break them into numbered tasks to delegate to the **Coder** agent.
2587
- - When handing over or delegating, you MUST provide the full implementation plan. Include all necessary context, file references, and clarifications for successful execution.
2588
-
2589
- ${toolUsePrompt(useNativeTool, tools, toolNamePrefix)}
2590
- ${capabilities(toolNamePrefix)}
2591
- ${systemInformation(info)}
2592
- ${customInstructions(instructions)}
2593
- ${customScripts(scripts)}
2594
- `;
2595
-
2596
- // src/Agent/ArchitectAgent/index.ts
2597
- var agentTools2 = [attemptCompletion_default, delegate_default, fetchUrl_default, handOver_default, listFiles_default, readBinaryFile_default, readFile_default, searchFiles_default];
2598
- var ArchitectAgent = class extends AgentBase {
2599
- constructor(options) {
2600
- const combinedTools = [...options.additionalTools ?? [], ...agentTools2];
2601
- const tools = getAvailableTools({
2602
- provider: options.provider,
2603
- allTools: combinedTools,
2604
- hasAgent: (options.agents?.length ?? 0) > 0
2605
- });
2606
- const toolNamePrefix = options.toolFormat === "native" ? "" : "tool_";
2607
- const systemPrompt = fullSystemPrompt2(
2608
- {
2609
- os: options.os
2610
- },
2611
- tools,
2612
- toolNamePrefix,
2613
- options.customInstructions ?? [],
2614
- options.scripts ?? {},
2615
- options.toolFormat === "native"
2616
- );
2617
- super(architectAgentInfo.name, options.ai, {
2618
- systemPrompt,
2619
- tools,
2620
- toolNamePrefix,
2621
- provider: options.provider,
2622
- agents: options.agents,
2623
- scripts: options.scripts,
2624
- callback: options.callback,
2625
- policies: options.policies,
2626
- toolFormat: options.toolFormat,
2627
- parameters: options.parameters ?? {},
2628
- usageMeter: options.usageMeter ?? new UsageMeter(),
2629
- requestTimeoutSeconds: options.requestTimeoutSeconds,
2630
- requireToolUse: options.requireToolUse ?? true
2631
- });
2632
- }
2633
- onBeforeInvokeTool() {
2634
- return Promise.resolve(void 0);
2635
- }
2636
- };
2637
- var architectAgentInfo = {
2638
- name: "architect",
2639
- responsibilities: [
2640
- "Analyzing the user\u2019s overall task and requirements.",
2641
- "Creating plans and making higher-level decisions about system structure and design.",
2642
- "Reviewing and analyzing existing code or components for maintainability and scalability.",
2643
- "Laying out the roadmap for implementation."
2644
- ]
2645
- };
2646
-
2647
- // src/Agent/CodeFixerAgent/prompts.ts
2648
- var basePrompt = `You are a highly skilled software engineer specializing in debugging and fixing code issues. You have extensive experience with:
2649
- - Type systems and type checking
2650
- - Test frameworks and debugging test failures
2651
- - Code quality tools and best practices
2652
- - Systematic debugging approaches`;
2653
- var codeFixingStrategies = `
2654
- ====
2655
-
2656
- CODE FIXING STRATEGIES
2657
-
2658
- 1. Type Errors
2659
- - Analyze type error messages carefully
2660
- - Check type definitions and imports
2661
- - Consider type assertions only as a last resort
2662
- - Verify type compatibility across function boundaries
2663
- - Look for null/undefined handling issues
2664
-
2665
- 2. Test Failures
2666
- - Examine test output and error messages
2667
- - Check test setup and fixtures
2668
- - Verify assertions and expectations
2669
- - Look for async/timing issues
2670
- - Consider edge cases and input validation
2671
-
2672
- 3. Code Quality Issues
2673
- - Follow project's coding standards
2674
- - Address linter warnings systematically
2675
- - Improve code readability
2676
- - Fix potential runtime issues
2677
- - Consider performance implications
2678
-
2679
- 4. General Approach
2680
- - Start with the most critical issues
2681
- - Make minimal necessary changes
2682
- - Verify fixes don't introduce new issues
2683
- - Document complex fixes with comments
2684
- - Track attempted solutions for each issue`;
2685
- var retryGuidelines = `
2686
- ====
2687
-
2688
- RETRY GUIDELINES
2689
-
2690
- 1. Before Retrying
2691
- - Analyze previous attempt's failure
2692
- - Consider alternative approaches
2693
- - Check if similar issues were fixed
2694
- - Verify no new issues were introduced
2695
-
2696
- 2. When to Retry
2697
- - Error message changed but issue persists
2698
- - New information available about the root cause
2699
- - Different fixing strategy available
2700
- - Previous attempt partially successful
2701
-
2702
- 3. When to Stop
2703
- - Maximum retry limit reached
2704
- - Same error occurs repeatedly
2705
- - Fix would require major refactoring
2706
- - Issue requires human intervention
2707
-
2708
- 4. After Maximum Retries
2709
- - Document attempted solutions
2710
- - Explain why the issue remains
2711
- - Suggest manual intervention steps
2712
- - Report any partial improvements`;
2713
- var fullSystemPrompt3 = (info, tools, toolNamePrefix, instructions, scripts, useNativeTool) => `
2714
- ${basePrompt}
2715
- ${toolUsePrompt(useNativeTool, tools, toolNamePrefix)}
2716
- ${codeFixingStrategies}
2717
- ${retryGuidelines}
2718
- ${capabilities(toolNamePrefix)}
2719
- ${systemInformation(info)}
2720
- ${customInstructions(instructions)}
2721
- ${customScripts(scripts)}`;
2722
-
2723
- // src/Agent/CodeFixerAgent/index.ts
2724
- var agentTools3 = [
2725
- attemptCompletion_default,
2726
- delegate_default,
2727
- executeCommand_default,
2728
- fetchUrl_default,
2729
- handOver_default,
2730
- listFiles_default,
2731
- readBinaryFile_default,
2732
- readFile_default,
2733
- removeFile_default,
2734
- renameFile_default,
2735
- replaceInFile_default,
2736
- searchFiles_default,
2737
- writeToFile_default
2738
- ];
2739
- var CodeFixerAgent = class extends AgentBase {
2740
- #maxRetries;
2741
- #retryCount = 0;
2742
- constructor(options) {
2743
- const combinedTools = [...options.additionalTools ?? [], ...agentTools3];
2744
- const tools = getAvailableTools({
2745
- provider: options.provider,
2746
- allTools: combinedTools,
2747
- hasAgent: (options.agents?.length ?? 0) > 0
2748
- });
2749
- const toolNamePrefix = options.toolFormat === "native" ? "" : "tool_";
2750
- const systemPrompt = fullSystemPrompt3(
2751
- {
2752
- os: options.os
2753
- },
2754
- tools,
2755
- toolNamePrefix,
2756
- options.customInstructions ?? [],
2757
- options.scripts ?? {},
2758
- options.toolFormat === "native"
2759
- );
2760
- super(codeFixerAgentInfo.name, options.ai, {
2761
- systemPrompt,
2762
- tools,
2763
- toolNamePrefix,
2764
- provider: options.provider,
2765
- agents: options.agents,
2766
- scripts: options.scripts,
2767
- callback: options.callback,
2768
- policies: options.policies,
2769
- toolFormat: options.toolFormat,
2770
- parameters: options.parameters ?? {},
2771
- usageMeter: options.usageMeter ?? new UsageMeter(),
2772
- requestTimeoutSeconds: options.requestTimeoutSeconds,
2773
- requireToolUse: options.requireToolUse ?? true
2774
- });
2775
- this.#maxRetries = options.maxRetries ?? 5;
2776
- }
2777
- async onBeforeInvokeTool(name, _args) {
2778
- if (name === attemptCompletion_default.name) {
2779
- if (this.#retryCount > this.#maxRetries) {
2780
- return;
2781
- }
2782
- this.#retryCount++;
2783
- const executeCommand = this.config.provider.executeCommand;
2784
- if (!executeCommand) {
2785
- return;
2786
- }
2787
- const check = this.config.scripts?.check;
2788
- const checkCommand = typeof check === "string" ? check : check?.command;
2789
- if (checkCommand) {
2790
- try {
2791
- const { exitCode, stdout, stderr } = await executeCommand(checkCommand, false);
2792
- if (exitCode !== 0) {
2793
- return {
2794
- type: "Reply" /* Reply */,
2795
- message: {
2796
- type: "error-text",
2797
- value: responsePrompts.commandResult(checkCommand, exitCode, stdout, stderr)
2798
- }
2799
- };
2800
- }
2801
- } catch (error) {
2802
- console.warn(`Failed to check code using command: ${checkCommand}`, error);
2803
- }
2804
- }
2805
- const test = this.config.scripts?.test;
2806
- const testCommand = typeof test === "string" ? test : test?.command;
2807
- if (testCommand) {
2808
- try {
2809
- const { exitCode, stdout, stderr } = await executeCommand(testCommand, false);
2810
- if (exitCode !== 0) {
2811
- return {
2812
- type: "Reply" /* Reply */,
2813
- message: {
2814
- type: "error-text",
2815
- value: responsePrompts.commandResult(testCommand, exitCode, stdout, stderr)
2816
- }
2817
- };
2818
- }
2819
- } catch (error) {
2820
- console.warn(`Failed to test code using command: ${testCommand}`, error);
2821
- }
2822
- }
2823
- }
2824
- }
2825
- };
2826
- var codeFixerAgentInfo = {
2827
- name: "codefixer",
2828
- responsibilities: [
2829
- "Fixing type errors and type-related issues",
2830
- "Resolving failing tests",
2831
- "Addressing code quality issues",
2832
- "Tracking and reporting unfixed issues"
2833
- ]
2834
- };
2835
-
2836
- // src/Agent/CoderAgent/prompts.ts
2837
- var basePrompt2 = "You are a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.";
2838
- var editingFilesPrompt = (toolNamePrefix) => `
2839
- ====
2840
-
2841
- EDITING FILES
2842
-
2843
- You have two file-manipulation tools: **${toolNamePrefix}write_to_file** (full overwrite) and **${toolNamePrefix}replace_in_file** (targeted anchor-based edits). Choose the smallest safe operation for every change.
2844
-
2845
- # ${toolNamePrefix}write_to_file
2846
-
2847
- ## Purpose
2848
-
2849
- - Create a new file, or overwrite the entire contents of an existing file.
2850
-
2851
- ## When to Use
2852
-
2853
- - Initial file creation, such as when scaffolding a new project.
2854
- - Overwriting large boilerplate files where you want to replace the entire content at once.
2855
- - When the complexity or number of changes would make ${toolNamePrefix}replace_in_file unwieldy or error-prone.
2856
- - When you need to completely restructure a file's content or change its fundamental organization.
2857
-
2858
- ## Important Considerations
2859
-
2860
- - Using ${toolNamePrefix}write_to_file requires providing the file's complete final content.
2861
- - If you only need to make small changes to an existing file, consider using ${toolNamePrefix}replace_in_file instead to avoid unnecessarily rewriting the entire file.
2862
- - While ${toolNamePrefix}write_to_file should not be your default choice, don't hesitate to use it when the situation truly calls for it.
2863
-
2864
- # ${toolNamePrefix}replace_in_file
2865
-
2866
- ## Purpose
2867
-
2868
- - Make targeted edits to specific parts of an existing file without overwriting the entire file.
2869
-
2870
- ## When to Use
2871
-
2872
- - Small, localized changes like updating a few lines, function implementations, changing variable names, modifying a section of text, etc.
2873
- - Targeted improvements where only specific portions of the file's content needs to be altered.
2874
- - Especially useful for long files where much of the file will remain unchanged.
2875
-
2876
- ## Advantages
2877
-
2878
- - More efficient for minor edits, since you don't need to supply the entire file content.
2879
- - Reduces the chance of errors that can occur when overwriting large files.
2880
-
2881
- # Choosing the Appropriate Tool
2882
-
2883
- - **Default to ${toolNamePrefix}replace_in_file** for most changes. It keeps diffs small and reduces risk.
2884
- - **Use ${toolNamePrefix}write_to_file** when:
2885
- - Creating new files
2886
- - The changes are so extensive that using ${toolNamePrefix}replace_in_file would be more complex or risky
2887
- - You need to completely reorganize or restructure a file
2888
- - The file is relatively small and the changes affect most of its content
2889
- - You're generating boilerplate or template files
2890
-
2891
- # Workflow Tips
2892
-
2893
- 1. Before editing, assess the scope of your changes and decide which tool to use.
2894
- 2. For targeted edits, apply ${toolNamePrefix}replace_in_file with carefully crafted before/after text anchors. If you need multiple changes, you can stack multiple operations within a single ${toolNamePrefix}replace_in_file call.
2895
- 3. For major overhauls or initial file creation, rely on ${toolNamePrefix}write_to_file.
2896
- 4. Once the file has been edited with either ${toolNamePrefix}write_to_file or ${toolNamePrefix}replace_in_file, the system will provide you with the final state of the modified file. Use this updated content as the reference point for any subsequent operations, since it reflects any auto-formatting or user-applied changes.
2897
-
2898
- Picking the right tool keeps edits minimal, safe, and easy to review.
2899
- `;
2900
- var rules = (toolNamePrefix) => `
2901
- ====
2902
-
2903
- RULES
2904
-
2905
- - Work only with relative paths; you may \`cd\` into child directories but never use \`cd ..\`, root, or absolute paths.
2906
- - When generating code, tests, or other comment-capable files, prepend a comment describing the file's purpose plus \u201Cgenerated by polka.codes\u201D.
2907
- For text files (e.g. README.md), append a footer with the same notice.
2908
- - Never describe what changed inside code comments; comments must focus on purpose or usage only.
2909
- - Before using ${toolNamePrefix}execute_command, consider SYSTEM INFORMATION to ensure commands suit the user's OS. If a command must run in a subdirectory, prepend a single \`cd childDir &&\` segment.
2910
- - Use ${toolNamePrefix}search_files for broad analysis, then ${toolNamePrefix}read_file to inspect context, and finally ${toolNamePrefix}replace_in_file or ${toolNamePrefix}write_to_file to modify.
2911
- - Prefer ${toolNamePrefix}replace_in_file for focused edits; choose ${toolNamePrefix}write_to_file for new files or complete rewrites.
2912
- - When creating a new file, look for existing files with similar content or patterns; if found, read them and use their structure or conventions as a reference.
2913
- - Use before/after text anchors in ${toolNamePrefix}replace_in_file to target changes. If multiple operations are needed, list them in file order.
2914
- - Do not guess unseen content. Read existing files first unless creating new ones.
2915
- - Follow existing style, lint, and naming conventions. Ensure all changes compile and pass tests where applicable.
2916
- - ALWAYS wait for the user's confirmation after each tool call before starting the next step.
2917
- - The agent must never invoke more than 5 tools in a single response.
2918
- - Do not end ${toolNamePrefix}attempt_completion output with questions or conversational prompts.
2919
- - Avoid filler words like \u201CGreat\u201D, \u201CCertainly\u201D, \u201COkay\u201D, \u201CSure\u201D at the start of responses; be direct and technical.
2920
- - Keep inline documentation current as you edit.
2921
- `;
2922
- var objectives = (toolNamePrefix) => `
2923
- ====
2924
-
2925
- OBJECTIVE
2926
-
2927
- You solve the user's task by working in small, verifiable steps.
2928
-
2929
- 1. **Plan** - Parse the task, list clear goals, and order them logically.
2930
- 2. **Think** - Wrap private reasoning in <thinking></thinking>.
2931
- \u2022 Review project context.
2932
- \u2022 Select the single best tool for the next goal.
2933
- \u2022 Ensure every required parameter is available or can be inferred.
2934
- 3. **Act** - Invoke one tool per step. Wait for the system's response (and user confirmation where required) before continuing.
2935
- 4. **Iterate** - Repeat Plan \u2192 Think \u2192 Act until all goals are complete.
2936
- 5. **Complete** - Use ${toolNamePrefix}attempt_completion to deliver the final result. Do not invite further discussion unless the user explicitly requests changes.
2937
- `;
2938
- var fullSystemPrompt4 = (info, tools, toolNamePrefix, instructions, scripts, useNativeTool) => `
2939
- ${basePrompt2}
2940
- ${toolUsePrompt(useNativeTool, tools, toolNamePrefix)}
2941
- ${editingFilesPrompt(toolNamePrefix)}
2942
- ${capabilities(toolNamePrefix)}
2943
- ${rules(toolNamePrefix)}
2944
- ${objectives(toolNamePrefix)}
2945
- ${systemInformation(info)}
2946
- ${customInstructions(instructions)}
2947
- ${customScripts(scripts)}
2948
- `;
2949
-
2950
- // src/Agent/CoderAgent/index.ts
2951
- var agentTools4 = [
2952
- attemptCompletion_default,
2953
- delegate_default,
2954
- executeCommand_default,
2955
- fetchUrl_default,
2956
- handOver_default,
2957
- listFiles_default,
2958
- readBinaryFile_default,
2959
- readFile_default,
2960
- removeFile_default,
2961
- renameFile_default,
2962
- replaceInFile_default,
2963
- searchFiles_default,
2964
- writeToFile_default
2965
- ];
2966
- var CoderAgent = class extends AgentBase {
2967
- constructor(options) {
2968
- const combinedTools = [...options.additionalTools ?? [], ...agentTools4];
2969
- const tools = getAvailableTools({
2970
- provider: options.provider,
2971
- allTools: combinedTools,
2972
- hasAgent: (options.agents?.length ?? 0) > 0
2973
- });
2974
- const toolNamePrefix = options.toolFormat === "native" ? "" : "tool_";
2975
- const systemPrompt = fullSystemPrompt4(
2976
- {
2977
- os: options.os
2978
- },
2979
- tools,
2980
- toolNamePrefix,
2981
- options.customInstructions ?? [],
2982
- options.scripts ?? {},
2983
- options.toolFormat === "native"
2984
- );
2985
- super(coderAgentInfo.name, options.ai, {
2986
- systemPrompt,
2987
- tools,
2988
- toolNamePrefix,
2989
- provider: options.provider,
2990
- agents: options.agents,
2991
- scripts: options.scripts,
2992
- callback: options.callback,
2993
- policies: options.policies,
2994
- toolFormat: options.toolFormat,
2995
- parameters: options.parameters ?? {},
2996
- usageMeter: options.usageMeter ?? new UsageMeter(),
2997
- requestTimeoutSeconds: options.requestTimeoutSeconds,
2998
- requireToolUse: options.requireToolUse ?? true
2999
- });
3000
- }
3001
- async #runScript(scriptName, shouldReplyWithError) {
3002
- const executeCommand = this.config.provider.executeCommand;
3003
- if (!executeCommand) {
3004
- return;
3005
- }
3006
- const script = this.config.scripts?.[scriptName];
3007
- const command = typeof script === "string" ? script : script?.command;
3008
- if (command) {
3009
- try {
3010
- const { exitCode, stdout, stderr } = await executeCommand(command, false);
3011
- if (exitCode !== 0 && shouldReplyWithError) {
3012
- return {
3013
- type: "Reply" /* Reply */,
3014
- message: {
3015
- type: "error-text",
3016
- value: responsePrompts.commandResult(command, exitCode, stdout, stderr)
3017
- }
3018
- };
3019
- }
3020
- } catch (error) {
3021
- console.warn(`Failed to run ${scriptName} using command: ${command}`, error);
3022
- }
3023
- }
3024
- }
3025
- async onBeforeInvokeTool(name, _args) {
3026
- if (name !== attemptCompletion_default.name) {
3027
- return;
3028
- }
3029
- await this.#runScript("format", false);
3030
- const checkResult = await this.#runScript("check", true);
3031
- if (checkResult) {
3032
- return checkResult;
3033
- }
3034
- const testResult = await this.#runScript("test", true);
3035
- if (testResult) {
3036
- return testResult;
3037
- }
3038
- }
3039
- };
3040
- var coderAgentInfo = {
3041
- name: "coder",
3042
- responsibilities: [
3043
- "Editing and refactoring existing code.",
3044
- "Creating new features or modules.",
3045
- "Running tests and analyzing test results.",
3046
- "Maintaining coding standards, lint rules, and general code quality."
3047
- ]
3048
- };
3049
-
3050
- // src/Agent/MultiAgent.ts
3051
- var MultiAgent = class {
3052
- #config;
3053
- #agents = [];
3054
- #originalTask;
3055
- constructor(config) {
3056
- this.#config = config;
3057
- }
3058
- async #handleTaskResult(exitReason) {
3059
- switch (exitReason.type) {
3060
- case "HandOver" /* HandOver */: {
3061
- this.#agents.pop();
3062
- const prompt2 = await this.#config.getPrompt?.(
3063
- exitReason.agentName,
3064
- exitReason.task,
3065
- exitReason.context,
3066
- exitReason.files,
3067
- this.#originalTask
3068
- ) ?? exitReason.task;
3069
- return await this.#startTask(exitReason.agentName, prompt2);
3070
- }
3071
- case "Delegate" /* Delegate */: {
3072
- const prompt2 = await this.#config.getPrompt?.(
3073
- exitReason.agentName,
3074
- exitReason.task,
3075
- exitReason.context,
3076
- exitReason.files,
3077
- this.#originalTask
3078
- ) ?? exitReason.task;
3079
- const delegateResult = await this.#startTask(exitReason.agentName, prompt2);
3080
- switch (delegateResult.type) {
3081
- case "HandOver" /* HandOver */:
3082
- case "Delegate" /* Delegate */:
3083
- console.warn("Unexpected exit reason", delegateResult);
3084
- break;
3085
- case "Aborted":
3086
- case "Interrupted" /* Interrupted */:
3087
- return delegateResult;
3088
- case "Exit" /* Exit */:
3089
- return this.continueTask(delegateResult.message);
3090
- }
3091
- return delegateResult;
3092
- }
3093
- case "Aborted":
3094
- case "Interrupted" /* Interrupted */:
3095
- case "Exit" /* Exit */:
3096
- this.#agents.pop();
3097
- return exitReason;
3098
- default:
3099
- return exitReason;
3100
- }
3101
- }
3102
- async #startTask(agentName, task) {
3103
- const newAgent = await this.#config.createAgent(agentName);
3104
- this.#agents.push(newAgent);
3105
- const exitReason = await newAgent.start(task);
3106
- return await this.#handleTaskResult(exitReason);
3107
- }
3108
- async startTask(options) {
3109
- if (this.#agents.length > 0) {
3110
- throw new Error("An active agent already exists");
3111
- }
3112
- this.#originalTask = options.task;
3113
- const userContent = options.files ?? [];
3114
- userContent.push({
3115
- type: "text",
3116
- text: `<task>${options.task}</task>
3117
- <context>${options.context}</context>`
3118
- });
3119
- return this.#startTask(options.agentName, userContent);
3120
- }
3121
- async continueTask(userMessage) {
3122
- if (!this.#agents.length) {
3123
- throw new Error("No active agent");
3124
- }
3125
- const exitReason = await this.#agents[this.#agents.length - 1].continueTask(userMessage);
3126
- return await this.#handleTaskResult(exitReason);
3127
- }
3128
- get hasActiveAgent() {
3129
- return this.#agents.length > 0;
3130
- }
3131
- abort() {
3132
- if (this.hasActiveAgent) {
3133
- this.#agents[this.#agents.length - 1].abort();
3134
- }
3135
- }
3136
- };
3137
-
3138
- // src/Agent/parseJsonFromMarkdown.ts
3139
- var parseJsonFromMarkdown = (markdown) => {
3140
- const jsonRegex = /```(?:json)?\n([\s\S]*?)\n```/;
3141
- const match = markdown.match(jsonRegex);
3142
- const tryParse = (str) => {
3143
- try {
3144
- let parsed = JSON.parse(str);
3145
- if (typeof parsed === "string") {
3146
- try {
3147
- parsed = JSON.parse(parsed);
3148
- } catch {
3149
- }
3150
- }
3151
- return { success: true, data: parsed };
3152
- } catch (e) {
3153
- const error = e instanceof Error ? e.message : String(e);
3154
- return { success: false, error: `Failed to parse JSON: ${error}` };
3155
- }
3156
- };
3157
- if (match?.[1]) {
3158
- const content = match[1].trim();
3159
- return tryParse(content);
3160
- }
3161
- const parseResult = tryParse(markdown);
3162
- if (parseResult.success) {
3163
- return parseResult;
3164
- }
3165
- return { success: false, error: "No JSON object found in the string." };
3166
- };
3167
-
3168
- // src/config.ts
3169
- import { z as z16 } from "zod";
3170
- var toolFormatSchema = z16.enum(["native", "polka-codes"]).optional();
3171
- var providerModelSchema = z16.object({
3172
- provider: z16.string().optional(),
3173
- model: z16.string().optional(),
3174
- parameters: z16.record(z16.string(), z16.any()).optional(),
3175
- toolFormat: toolFormatSchema
3176
- });
3177
- var agentSchema = providerModelSchema.extend({
3178
- initialContext: z16.object({
3179
- maxFileCount: z16.number().int().positive().optional(),
3180
- excludes: z16.array(z16.string()).optional()
3181
- }).optional(),
3182
- retryCount: z16.number().int().min(0).optional(),
3183
- requestTimeoutSeconds: z16.number().int().positive().optional()
3184
- });
3185
- var configSchema = z16.object({
3186
- agent: z16.string().optional(),
3187
- prices: z16.record(
3188
- z16.string(),
3189
- // provider
3190
- z16.record(
3191
- z16.string(),
3192
- // model
3193
- z16.object({
3194
- inputPrice: z16.number().optional(),
3195
- outputPrice: z16.number().optional(),
3196
- cacheWritesPrice: z16.number().optional(),
3197
- cacheReadsPrice: z16.number().optional()
3198
- })
3199
- )
3200
- ).optional(),
3201
- providers: z16.record(
3202
- z16.string(),
3203
- z16.object({
3204
- apiKey: z16.string().optional(),
3205
- defaultModel: z16.string().optional(),
3206
- defaultParameters: z16.record(z16.string(), z16.any()).optional(),
3207
- location: z16.string().optional(),
3208
- project: z16.string().optional(),
3209
- keyFile: z16.string().optional()
3210
- })
3211
- ).optional(),
3212
- defaultProvider: z16.string().optional(),
3213
- defaultModel: z16.string().optional(),
3214
- defaultParameters: z16.record(z16.string(), z16.any()).optional(),
3215
- toolFormat: toolFormatSchema,
3216
- maxMessageCount: z16.number().int().positive().optional(),
3217
- budget: z16.number().positive().optional(),
3218
- retryCount: z16.number().int().min(0).optional(),
3219
- requestTimeoutSeconds: z16.number().int().positive().optional(),
3220
- summaryThreshold: z16.number().int().positive().optional(),
3221
- scripts: z16.record(
3222
- z16.string(),
3223
- z16.string().or(
3224
- z16.object({
3225
- command: z16.string(),
3226
- description: z16.string()
3227
- })
3228
- )
3229
- ).optional(),
3230
- agents: z16.record(z16.string(), agentSchema).optional(),
3231
- commands: z16.object({
3232
- default: providerModelSchema.optional()
3233
- }).catchall(providerModelSchema).optional(),
3234
- rules: z16.array(z16.string()).optional().or(z16.string()).optional(),
3235
- excludeFiles: z16.array(z16.string()).optional(),
3236
- policies: z16.array(z16.string()).optional()
3237
- }).strict();
3238
- var Policies = /* @__PURE__ */ ((Policies2) => {
3239
- Policies2["TruncateContext"] = "truncatecontext";
3240
- Policies2["EnableCache"] = "enablecache";
3241
- return Policies2;
3242
- })(Policies || {});
3243
-
3244
- // src/Agent/policies/EnableCachePolicy.ts
3245
- var CACHEABLE_MODELS = ["sonnet", "opus", "haiku", "gemini"];
3246
- function isCacheableModel(modelId) {
3247
- return CACHEABLE_MODELS.some((model) => modelId.includes(model));
3248
- }
3249
- function getProviderKey(provider) {
3250
- if (provider === "openrouter") {
3251
- return "openrouter";
3252
- }
3253
- if (provider.includes("anthropic")) {
3254
- return "anthropic";
3255
- }
3256
- return void 0;
3257
- }
3258
- var EnableCachePolicy = () => {
3259
- return {
3260
- name: "enablecache" /* EnableCache */,
3261
- async prepareMessages(agent, messages) {
3262
- const providerKey = getProviderKey(agent.ai.provider);
3263
- if (!providerKey || !isCacheableModel(agent.ai.modelId)) {
3264
- return messages;
3265
- }
3266
- const providerOptions = { [providerKey]: { cacheControl: { type: "ephemeral" } } };
3267
- const newMessages = messages.slice();
3268
- let userMessagesToUpdate = 2;
3269
- for (let i = newMessages.length - 1; i >= 0; i--) {
3270
- const message = newMessages[i];
3271
- if (message.role === "user" && userMessagesToUpdate > 0) {
3272
- newMessages[i] = {
3273
- ...message,
3274
- providerOptions: {
3275
- ...providerOptions,
3276
- ...message.providerOptions ?? {}
3277
- }
3278
- };
3279
- userMessagesToUpdate--;
3280
- } else if (message.role === "system") {
3281
- newMessages[i] = {
3282
- ...message,
3283
- providerOptions: {
3284
- ...providerOptions,
3285
- ...message.providerOptions ?? {}
3286
- }
3287
- };
3288
- break;
3289
- }
3290
- }
3291
- return newMessages;
3292
- }
3293
- };
3294
- };
3295
-
3296
- // src/Agent/policies/TruncateContextPolicy.ts
3297
- var DEFAULT_MAX_TOKENS_ESTIMATE = 32e3;
3298
- function getMaxTokens(agent) {
3299
- const params = agent.parameters || {};
3300
- if (params.maxTokens && typeof params.maxTokens === "number" && params.maxTokens > 0) {
3301
- return params.maxTokens;
3302
- }
3303
- return DEFAULT_MAX_TOKENS_ESTIMATE;
3304
- }
3305
- function estimateTokens(text) {
3306
- return Math.ceil(text.length / 4);
3307
- }
3308
- function estimateMessageTokens(msg) {
3309
- if (typeof msg.content === "string") {
3310
- return estimateTokens(msg.content);
3311
- }
3312
- if (Array.isArray(msg.content)) {
3313
- let messageTokens = 0;
3314
- for (const block of msg.content) {
3315
- if (typeof block === "object" && "text" in block && typeof block.text === "string") {
3316
- messageTokens += estimateTokens(block.text);
3317
- }
3318
- }
3319
- return messageTokens;
3320
- }
3321
- return 0;
3322
- }
3323
- var TruncateContextPolicy = () => {
3324
- return {
3325
- name: "truncatecontext" /* TruncateContext */,
3326
- async onBeforeRequest(agent) {
3327
- const messages = agent.messages;
3328
- if (messages.length < 3) {
3329
- return;
3330
- }
3331
- let totalTokens = messages.reduce((acc, msg) => acc + estimateMessageTokens(msg), 0);
3332
- const maxTokens = getMaxTokens(agent);
3333
- if (totalTokens <= maxTokens) {
3334
- return;
3335
- }
3336
- const protectedIndices = /* @__PURE__ */ new Set();
3337
- let userMessagesFound = 0;
3338
- messages.forEach((msg, index) => {
3339
- if (msg.role === "system") {
3340
- protectedIndices.add(index);
3341
- }
3342
- if (msg.role === "user") {
3343
- if (userMessagesFound < 2) {
3344
- protectedIndices.add(index);
3345
- }
3346
- userMessagesFound++;
3347
- }
3348
- });
3349
- if (messages.length > 0) {
3350
- protectedIndices.add(messages.length - 1);
3351
- }
3352
- const truncatableIndices = [];
3353
- for (let i = 0; i < messages.length; i++) {
3354
- if (!protectedIndices.has(i)) {
3355
- truncatableIndices.push(i);
3356
- }
3357
- }
3358
- const removedIndices = /* @__PURE__ */ new Set();
3359
- const initialTotalTokens = totalTokens;
3360
- while (totalTokens > maxTokens && truncatableIndices.length > 0) {
3361
- const middleIndex = Math.floor(truncatableIndices.length / 2);
3362
- const indexToRemove = truncatableIndices.splice(middleIndex, 1)[0];
3363
- removedIndices.add(indexToRemove);
3364
- totalTokens -= estimateMessageTokens(messages[indexToRemove]);
3365
- }
3366
- if (removedIndices.size === 0) {
3367
- if (initialTotalTokens > maxTokens) {
3368
- console.warn("Warning: Protected messages exceed token limit. Cannot truncate further.");
3369
- }
3370
- return;
3371
- }
3372
- const truncatedMessages = [];
3373
- let truncationNoticeAdded = false;
3374
- for (let i = 0; i < messages.length; i++) {
3375
- if (removedIndices.has(i)) {
3376
- if (!truncationNoticeAdded) {
3377
- truncatedMessages.push({
3378
- role: "user",
3379
- content: `Note: ${removedIndices.size} messages were truncated from the conversation to prevent context overflow.`
3380
- });
3381
- truncationNoticeAdded = true;
3382
- }
3383
- } else {
3384
- truncatedMessages.push(messages[i]);
3385
- }
3386
- }
3387
- console.log(`Truncated context: removed ${removedIndices.size} messages.`);
3388
- agent.setMessages(truncatedMessages);
3389
- }
3390
- };
3391
- };
3392
-
3393
- // src/Agent/index.ts
3394
- var allAgents = [architectAgentInfo, coderAgentInfo, analyzerAgentInfo, codeFixerAgentInfo];
3395
-
3396
- // src/AiTool/index.ts
3397
- import { generateText } from "ai";
3398
-
3399
- // src/AiTool/createNewProject.ts
3400
- var prompt = `You are an AiTool designed to assist users in creating new projects. Follow these guidelines:
3401
-
3402
- 1. **Gather Information:**
3403
- - Begin by asking the user for essential project details, including:
3404
- - Project type (e.g., web, mobile, desktop, etc.)
3405
- - Desired programming languages
3406
- - Preferred frameworks or libraries
3407
- - Build tools and package manager preferences
3408
- - Testing frameworks and patterns
3409
- - Code style and linting preferences
3410
- - Any additional specifications or requirements
3411
-
3412
- 2. **Clarification & Confirmation:**
3413
- - Do not make any decisions or assumptions on behalf of the user.
3414
- - Ask clarifying questions if any detail is ambiguous.
3415
- - Confirm each piece of information with the user before proceeding to the next step.
3416
-
3417
- 3. **Avoid Redundancy:**
3418
- - Do not repeat questions or details that have already been confirmed.
3419
- - Keep interactions concise and focused on gathering complete and accurate details.
3420
-
3421
- 4. **Generate Configuration:**
3422
- - Based on the collected information, generate a .polkacodes.yml configuration file that includes:
3423
- - scripts section with common development commands (test, format, check, etc.)
3424
- - rules section reflecting project conventions and tools
3425
- - excludeFiles section for sensitive files only
3426
- - Example structure:
3427
- \`\`\`yaml
3428
- scripts:
3429
- test:
3430
- command: "[test-command]"
3431
- description: "Run tests"
3432
- format:
3433
- command: "[format-command]"
3434
- description: "Format code"
3435
- check:
3436
- command: "[check-command]"
3437
- description: "Check code"
3438
-
3439
- rules:
3440
- - "[package-manager-rule]"
3441
- - "[testing-framework-rule]"
3442
- - "[code-style-rule]"
3443
- - "[other-rule]"
3444
-
3445
- excludeFiles:
3446
- - ".env"
3447
- - ".env.*"
3448
- \`\`\`
3449
-
3450
- 5. **Generate Essential Project Files:**
3451
- - Create a .gitattributes file with appropriate configurations:
3452
- - Mark lock files as generated and exclude them from diffs
3453
- - Example for different package managers:
3454
-
3455
- # For Bun
3456
- bun.lock linguist-generated=true
3457
- bun.lock -diff
3458
-
3459
- # For npm
3460
- package-lock.json linguist-generated=true
3461
- package-lock.json -diff
3462
-
3463
- # For Yarn
3464
- yarn.lock linguist-generated=true
3465
- yarn.lock -diff
3466
-
3467
- # For pnpm
3468
- pnpm-lock.yaml linguist-generated=true
3469
- pnpm-lock.yaml -diff
3470
-
3471
- - Include other common configurations as needed based on project type
3472
-
3473
- 6. **Handover to Coder Agent:**
3474
- - Once all required information is collected and validated by the user, compile:
3475
- 1. The final project specifications
3476
- 2. The .polkacodes.yml configuration content
3477
- - Clearly hand over these details to the coder agent, instructing them to:
3478
- 1. Create the new project based on the confirmed specifications
3479
- 2. Include the .polkacodes.yml file in the project root
3480
- 3. Include the .gitattributes file with appropriate configurations
3481
- 4. Ensure all specified tools and configurations are properly set up`;
3482
- var createNewProject_default = {
3483
- name: "createNewProject",
3484
- description: "Creates a new project",
3485
- prompt,
3486
- formatInput: (params) => {
3487
- return `<project_name>${params}</project_name>`;
3488
- },
3489
- parseOutput: (output) => {
3490
- return output.trim();
3491
- },
3492
- agent: "architect"
3493
- };
3494
-
3495
- // src/AiTool/index.ts
3496
- var executeTool = async (definition, ai, params, usageMeter) => {
3497
- const resp = await generateText({
3498
- model: ai,
3499
- temperature: 0,
3500
- system: definition.prompt,
3501
- messages: [
3502
- {
3503
- role: "user",
3504
- content: definition.formatInput(params)
3505
- }
3506
- ]
3507
- });
3508
- usageMeter.addUsage(ai, resp);
3509
- return definition.parseOutput(resp.text);
3510
- };
3511
- var executeMultiAgentTool = async (definition, agent, params) => {
3512
- const exitReason = await agent.startTask({
3513
- agentName: definition.agent,
3514
- task: definition.prompt,
3515
- context: definition.formatInput(params)
3516
- });
3517
- if (exitReason.type === "Exit" /* Exit */) {
3518
- return definition.parseOutput(exitReason.message);
3519
- }
3520
- throw new Error(`Tool execution failed: ${exitReason.type}`);
3521
- };
3522
- var executeAgentTool = async (definition, options, params) => {
3523
- const agent = definition.agent(options);
3524
- const exitReason = await agent.start(`${definition.prompt}
3525
-
3526
- ${definition.formatInput(params)}`);
3527
- if (exitReason.type === "Exit" /* Exit */) {
3528
- return definition.parseOutput(exitReason.message);
3529
- }
3530
- throw new Error(`Tool execution failed: ${exitReason.type}`);
3531
- };
3532
- var makeTool = (definition) => {
3533
- return async (ai, params, usageMeter) => {
3534
- return executeTool(definition, ai, params, usageMeter);
3535
- };
3536
- };
3537
- var makeMultiAgentTool = (definition) => {
3538
- return async (agent, params) => {
3539
- return executeMultiAgentTool(definition, agent, params);
3540
- };
3541
- };
3542
- var makeAgentTool = (definition) => {
3543
- return async (options, params) => {
3544
- return executeAgentTool(definition, options, params);
3545
- };
3546
- };
3547
- var createNewProject = makeMultiAgentTool(createNewProject_default);
3548
1480
  export {
3549
- AgentBase,
3550
- AnalyzerAgent,
3551
- ArchitectAgent,
3552
- CodeFixerAgent,
3553
- CoderAgent,
3554
- EnableCachePolicy,
3555
1481
  MockProvider,
3556
- MultiAgent,
3557
- Policies,
3558
- TaskEventKind,
3559
1482
  ToolResponseType,
3560
- TruncateContextPolicy,
3561
1483
  UsageMeter,
3562
- agentsPrompt,
3563
- allAgents,
3564
- analyzerAgentInfo,
3565
- architectAgentInfo,
1484
+ appendMemory_default as appendMemory,
3566
1485
  askFollowupQuestion_default as askFollowupQuestion,
3567
- attemptCompletion_default as attemptCompletion,
3568
- capabilities,
3569
- codeFixerAgentInfo,
3570
- coderAgentInfo,
1486
+ computeRateLimitBackoffSeconds,
3571
1487
  configSchema,
3572
- createNewProject,
3573
- customInstructions,
3574
- customScripts,
3575
- delegate_default as delegate,
3576
- executeAgentTool,
3577
1488
  executeCommand_default as executeCommand,
3578
- executeMultiAgentTool,
3579
- executeTool,
3580
1489
  fetchUrl_default as fetchUrl,
3581
- getAvailableTools,
3582
- handOver_default as handOver,
3583
1490
  listFiles_default as listFiles,
3584
- makeAgentTool,
3585
- makeMultiAgentTool,
3586
- makeTool,
3587
- parseAssistantMessage,
1491
+ listMemoryTopics_default as listMemoryTopics,
3588
1492
  parseJsonFromMarkdown,
3589
1493
  readBinaryFile_default as readBinaryFile,
3590
1494
  readFile_default as readFile,
1495
+ readMemory_default as readMemory,
3591
1496
  removeFile_default as removeFile,
1497
+ removeMemory_default as removeMemory,
3592
1498
  renameFile_default as renameFile,
3593
1499
  replaceInFile_default as replaceInFile,
3594
1500
  replaceInFile as replaceInFileHelper,
1501
+ replaceMemory_default as replaceMemory,
3595
1502
  responsePrompts,
3596
1503
  searchFiles_default as searchFiles,
3597
- systemInformation,
3598
- toolUsePrompt,
3599
1504
  writeToFile_default as writeToFile
3600
1505
  };