@polka-codes/core 0.7.2 → 0.7.3

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.cjs ADDED
@@ -0,0 +1,3457 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AgentBase: () => AgentBase,
34
+ AiServiceProvider: () => AiServiceProvider,
35
+ AnalyzerAgent: () => AnalyzerAgent,
36
+ ArchitectAgent: () => ArchitectAgent,
37
+ CodeFixerAgent: () => CodeFixerAgent,
38
+ CoderAgent: () => CoderAgent,
39
+ MockProvider: () => MockProvider,
40
+ MultiAgent: () => MultiAgent,
41
+ PermissionLevel: () => PermissionLevel,
42
+ TaskEventKind: () => TaskEventKind,
43
+ ToolResponseType: () => ToolResponseType,
44
+ UsageMeter: () => UsageMeter,
45
+ allAgents: () => allAgents,
46
+ allTools: () => allTools_exports,
47
+ analyzerAgentInfo: () => analyzerAgentInfo,
48
+ anthropicDefaultModelId: () => anthropicDefaultModelId,
49
+ anthropicModels: () => anthropicModels,
50
+ architectAgentInfo: () => architectAgentInfo,
51
+ askFollowupQuestion: () => askFollowupQuestion_default,
52
+ attemptCompletion: () => attemptCompletion_default,
53
+ codeFixerAgentInfo: () => codeFixerAgentInfo,
54
+ coderAgentInfo: () => coderAgentInfo,
55
+ createNewProject: () => createNewProject,
56
+ createService: () => createService,
57
+ deepSeekDefaultModelId: () => deepSeekDefaultModelId,
58
+ deepSeekModels: () => deepSeekModels,
59
+ defaultModels: () => defaultModels,
60
+ delegate: () => delegate_default,
61
+ executeAgentTool: () => executeAgentTool,
62
+ executeCommand: () => executeCommand_default,
63
+ executeTool: () => executeTool,
64
+ generateGitCommitMessage: () => generateGitCommitMessage,
65
+ generateGithubPullRequestDetails: () => generateGithubPullRequestDetails,
66
+ generateProjectConfig: () => generateProjectConfig,
67
+ getAvailableTools: () => getAvailableTools,
68
+ handOver: () => handOver_default,
69
+ listCodeDefinitionNames: () => listCodeDefinitionNames_default,
70
+ listFiles: () => listFiles_default,
71
+ makeAgentTool: () => makeAgentTool,
72
+ makeTool: () => makeTool,
73
+ modelInfos: () => modelInfos,
74
+ openAiModelInfoSaneDefaults: () => openAiModelInfoSaneDefaults,
75
+ readFile: () => readFile_default,
76
+ removeFile: () => removeFile_default,
77
+ renameFile: () => renameFile_default,
78
+ replaceInFile: () => replaceInFile_default,
79
+ searchFiles: () => searchFiles_default,
80
+ writeToFile: () => writeToFile_default
81
+ });
82
+ module.exports = __toCommonJS(index_exports);
83
+
84
+ // src/AiService/AnthropicService.ts
85
+ var import_sdk = require("@anthropic-ai/sdk");
86
+
87
+ // src/AiService/AiServiceBase.ts
88
+ var AiServiceBase = class {
89
+ usageMeter;
90
+ constructor(usageMeter) {
91
+ this.usageMeter = usageMeter;
92
+ }
93
+ async *send(systemPrompt, messages) {
94
+ this.usageMeter.incrementMessageCount();
95
+ const stream = this.sendImpl(systemPrompt, messages);
96
+ for await (const chunk of stream) {
97
+ switch (chunk.type) {
98
+ case "usage":
99
+ this.usageMeter.addUsage(chunk, this.model);
100
+ break;
101
+ }
102
+ yield chunk;
103
+ }
104
+ }
105
+ async request(systemPrompt, messages) {
106
+ this.usageMeter.incrementMessageCount();
107
+ const stream = this.sendImpl(systemPrompt, messages);
108
+ const usage = {
109
+ inputTokens: 0,
110
+ outputTokens: 0,
111
+ cacheWriteTokens: 0,
112
+ cacheReadTokens: 0,
113
+ totalCost: 0
114
+ };
115
+ let resp = "";
116
+ let reasoning = "";
117
+ for await (const chunk of stream) {
118
+ switch (chunk.type) {
119
+ case "usage":
120
+ usage.inputTokens = chunk.inputTokens ?? 0;
121
+ usage.outputTokens = chunk.outputTokens ?? 0;
122
+ usage.cacheWriteTokens = chunk.cacheWriteTokens ?? 0;
123
+ usage.cacheReadTokens = chunk.cacheReadTokens ?? 0;
124
+ usage.totalCost = chunk.totalCost;
125
+ break;
126
+ case "text":
127
+ resp += chunk.text;
128
+ break;
129
+ case "reasoning":
130
+ reasoning += chunk.text;
131
+ }
132
+ }
133
+ this.usageMeter.addUsage(usage, this.model);
134
+ return {
135
+ response: resp,
136
+ reasoning,
137
+ usage
138
+ };
139
+ }
140
+ };
141
+
142
+ // src/AiService/ModelInfo.ts
143
+ var anthropicDefaultModelId = "claude-3-7-sonnet-20250219";
144
+ var anthropicModels = {
145
+ "claude-3-7-sonnet-20250219": {
146
+ maxTokens: 8192,
147
+ contextWindow: 2e5,
148
+ supportsImages: true,
149
+ supportsComputerUse: true,
150
+ supportsPromptCache: true,
151
+ inputPrice: 3,
152
+ outputPrice: 15,
153
+ cacheWritesPrice: 3.75,
154
+ cacheReadsPrice: 0.3
155
+ },
156
+ "claude-3-5-sonnet-20241022": {
157
+ maxTokens: 8192,
158
+ contextWindow: 2e5,
159
+ supportsImages: true,
160
+ supportsComputerUse: true,
161
+ supportsPromptCache: true,
162
+ inputPrice: 3,
163
+ // $3 per million input tokens
164
+ outputPrice: 15,
165
+ // $15 per million output tokens
166
+ cacheWritesPrice: 3.75,
167
+ // $3.75 per million tokens
168
+ cacheReadsPrice: 0.3
169
+ // $0.30 per million tokens
170
+ },
171
+ "claude-3-5-haiku-20241022": {
172
+ maxTokens: 8192,
173
+ contextWindow: 2e5,
174
+ supportsImages: false,
175
+ supportsPromptCache: true,
176
+ inputPrice: 0.8,
177
+ outputPrice: 4,
178
+ cacheWritesPrice: 1,
179
+ cacheReadsPrice: 0.08
180
+ },
181
+ "claude-3-opus-20240229": {
182
+ maxTokens: 4096,
183
+ contextWindow: 2e5,
184
+ supportsImages: true,
185
+ supportsPromptCache: true,
186
+ inputPrice: 15,
187
+ outputPrice: 75,
188
+ cacheWritesPrice: 18.75,
189
+ cacheReadsPrice: 1.5
190
+ },
191
+ "claude-3-haiku-20240307": {
192
+ maxTokens: 4096,
193
+ contextWindow: 2e5,
194
+ supportsImages: true,
195
+ supportsPromptCache: true,
196
+ inputPrice: 0.25,
197
+ outputPrice: 1.25,
198
+ cacheWritesPrice: 0.3,
199
+ cacheReadsPrice: 0.03
200
+ }
201
+ };
202
+ var openAiModelInfoSaneDefaults = {
203
+ maxTokens: -1,
204
+ contextWindow: 128e3,
205
+ supportsImages: true,
206
+ supportsPromptCache: false,
207
+ inputPrice: 0,
208
+ outputPrice: 0
209
+ };
210
+ var deepSeekDefaultModelId = "deepseek-chat";
211
+ var deepSeekModels = {
212
+ "deepseek-chat": {
213
+ maxTokens: 8e3,
214
+ contextWindow: 64e3,
215
+ supportsImages: false,
216
+ supportsPromptCache: true,
217
+ // supports context caching, but not in the way anthropic does it (deepseek reports input tokens and reads/writes in the same usage report) FIXME: we need to show users cache stats how deepseek does it
218
+ inputPrice: 0,
219
+ // technically there is no input price, it's all either a cache hit or miss (ApiOptions will not show this)
220
+ outputPrice: 1.1,
221
+ cacheWritesPrice: 0.27,
222
+ cacheReadsPrice: 0.07
223
+ },
224
+ "deepseek-reasoner": {
225
+ maxTokens: 8e3,
226
+ contextWindow: 64e3,
227
+ supportsImages: false,
228
+ supportsPromptCache: true,
229
+ inputPrice: 0,
230
+ outputPrice: 2.19,
231
+ cacheWritesPrice: 0.55,
232
+ cacheReadsPrice: 0.14
233
+ }
234
+ };
235
+ var modelInfos = {
236
+ anthropic: anthropicModels,
237
+ deepseek: deepSeekModels
238
+ };
239
+
240
+ // src/AiService/AnthropicService.ts
241
+ var AnthropicService = class extends AiServiceBase {
242
+ #options;
243
+ #client;
244
+ model;
245
+ constructor(options) {
246
+ super(options.usageMeter);
247
+ this.#options = options;
248
+ this.#client = new import_sdk.Anthropic({
249
+ apiKey: options.apiKey,
250
+ baseURL: options.baseUrl || void 0
251
+ });
252
+ const id = this.#options.model ?? anthropicDefaultModelId;
253
+ this.model = {
254
+ provider: "anthropic",
255
+ id,
256
+ info: anthropicModels[id] ?? anthropicModels[anthropicDefaultModelId]
257
+ };
258
+ }
259
+ async *sendImpl(systemPrompt, messages) {
260
+ let stream;
261
+ const modelId = this.model.id;
262
+ const cacheControl = this.#options.enableCache ? { type: "ephemeral" } : void 0;
263
+ switch (modelId) {
264
+ // 'latest' alias does not support cache_control
265
+ case "claude-3-7-sonnet-20250219":
266
+ case "claude-3-5-sonnet-20241022":
267
+ case "claude-3-5-haiku-20241022":
268
+ case "claude-3-opus-20240229":
269
+ case "claude-3-haiku-20240307": {
270
+ const userMsgIndices = messages.reduce((acc, msg, index) => {
271
+ if (msg.role === "user") {
272
+ acc.push(index);
273
+ }
274
+ return acc;
275
+ }, []);
276
+ const lastUserMsgIndex = userMsgIndices[userMsgIndices.length - 1] ?? -1;
277
+ const secondLastMsgUserIndex = userMsgIndices[userMsgIndices.length - 2] ?? -1;
278
+ stream = await this.#client.messages.create({
279
+ model: modelId,
280
+ max_tokens: this.model.info.maxTokens || 8192,
281
+ temperature: 0,
282
+ system: [
283
+ {
284
+ text: systemPrompt,
285
+ type: "text",
286
+ cache_control: cacheControl
287
+ }
288
+ ],
289
+ // setting cache breakpoint for system prompt so new tasks can reuse it
290
+ messages: messages.map((message, index) => {
291
+ if (index === lastUserMsgIndex || index === secondLastMsgUserIndex) {
292
+ return {
293
+ ...message,
294
+ content: typeof message.content === "string" ? [
295
+ {
296
+ type: "text",
297
+ text: message.content,
298
+ cache_control: cacheControl
299
+ }
300
+ ] : message.content.map(
301
+ (content, contentIndex) => contentIndex === message.content.length - 1 ? {
302
+ ...content,
303
+ cache_control: cacheControl
304
+ } : content
305
+ )
306
+ };
307
+ }
308
+ return message;
309
+ }),
310
+ stream: true
311
+ });
312
+ break;
313
+ }
314
+ default: {
315
+ stream = await this.#client.messages.create({
316
+ model: modelId,
317
+ max_tokens: this.model.info.maxTokens || 8192,
318
+ temperature: 0,
319
+ system: [{ text: systemPrompt, type: "text" }],
320
+ messages,
321
+ // tools,
322
+ // tool_choice: { type: "auto" },
323
+ stream: true
324
+ });
325
+ break;
326
+ }
327
+ }
328
+ for await (const chunk of stream) {
329
+ switch (chunk.type) {
330
+ case "message_start": {
331
+ const usage = chunk.message.usage;
332
+ yield {
333
+ type: "usage",
334
+ inputTokens: usage.input_tokens,
335
+ outputTokens: usage.output_tokens,
336
+ cacheWriteTokens: usage.cache_creation_input_tokens || 0,
337
+ cacheReadTokens: usage.cache_read_input_tokens || 0
338
+ };
339
+ break;
340
+ }
341
+ case "message_delta": {
342
+ yield {
343
+ type: "usage",
344
+ inputTokens: 0,
345
+ outputTokens: chunk.usage.output_tokens
346
+ };
347
+ break;
348
+ }
349
+ case "message_stop":
350
+ break;
351
+ case "content_block_start":
352
+ switch (chunk.content_block.type) {
353
+ case "text":
354
+ if (chunk.index > 0) {
355
+ yield {
356
+ type: "text",
357
+ text: "\n"
358
+ };
359
+ }
360
+ yield {
361
+ type: "text",
362
+ text: chunk.content_block.text
363
+ };
364
+ break;
365
+ }
366
+ break;
367
+ case "content_block_delta":
368
+ switch (chunk.delta.type) {
369
+ case "text_delta":
370
+ yield {
371
+ type: "text",
372
+ text: chunk.delta.text
373
+ };
374
+ break;
375
+ }
376
+ break;
377
+ case "content_block_stop":
378
+ break;
379
+ }
380
+ }
381
+ }
382
+ };
383
+
384
+ // src/AiService/DeepSeekService.ts
385
+ var import_openai = __toESM(require("openai"), 1);
386
+
387
+ // src/AiService/utils.ts
388
+ function convertToOpenAiMessages(anthropicMessages) {
389
+ const openAiMessages = [];
390
+ for (const anthropicMessage of anthropicMessages) {
391
+ if (typeof anthropicMessage.content === "string") {
392
+ openAiMessages.push({
393
+ role: anthropicMessage.role,
394
+ content: anthropicMessage.content
395
+ });
396
+ } else {
397
+ if (anthropicMessage.role === "user") {
398
+ const { nonToolMessages, toolMessages } = anthropicMessage.content.reduce(
399
+ (acc, part) => {
400
+ if (part.type === "tool_result") {
401
+ acc.toolMessages.push(part);
402
+ } else if (part.type === "text" || part.type === "image") {
403
+ acc.nonToolMessages.push(part);
404
+ }
405
+ return acc;
406
+ },
407
+ { nonToolMessages: [], toolMessages: [] }
408
+ );
409
+ const toolResultImages = [];
410
+ for (const toolMessage of toolMessages) {
411
+ let content;
412
+ if (typeof toolMessage.content === "string") {
413
+ content = toolMessage.content;
414
+ } else {
415
+ content = toolMessage.content?.map((part) => {
416
+ if (part.type === "image") {
417
+ toolResultImages.push(part);
418
+ return "(see following user message for image)";
419
+ }
420
+ return part.text;
421
+ }).join("\n") ?? "";
422
+ }
423
+ openAiMessages.push({
424
+ role: "tool",
425
+ tool_call_id: toolMessage.tool_use_id,
426
+ content
427
+ });
428
+ }
429
+ if (nonToolMessages.length > 0) {
430
+ openAiMessages.push({
431
+ role: "user",
432
+ content: nonToolMessages.map((part) => {
433
+ if (part.type === "image") {
434
+ return {
435
+ type: "image_url",
436
+ image_url: {
437
+ url: `data:${part.source.media_type};base64,${part.source.data}`
438
+ }
439
+ };
440
+ }
441
+ return { type: "text", text: part.text };
442
+ })
443
+ });
444
+ }
445
+ } else if (anthropicMessage.role === "assistant") {
446
+ const { nonToolMessages, toolMessages } = anthropicMessage.content.reduce(
447
+ (acc, part) => {
448
+ if (part.type === "tool_use") {
449
+ acc.toolMessages.push(part);
450
+ } else if (part.type === "text" || part.type === "image") {
451
+ acc.nonToolMessages.push(part);
452
+ }
453
+ return acc;
454
+ },
455
+ { nonToolMessages: [], toolMessages: [] }
456
+ );
457
+ let content;
458
+ if (nonToolMessages.length > 0) {
459
+ content = nonToolMessages.map((part) => {
460
+ if (part.type === "image") {
461
+ return "";
462
+ }
463
+ return part.text;
464
+ }).join("\n");
465
+ }
466
+ const tool_calls = toolMessages.map((toolMessage) => ({
467
+ id: toolMessage.id,
468
+ type: "function",
469
+ function: {
470
+ name: toolMessage.name,
471
+ // json string
472
+ arguments: JSON.stringify(toolMessage.input)
473
+ }
474
+ }));
475
+ openAiMessages.push({
476
+ role: "assistant",
477
+ content,
478
+ // Cannot be an empty array. API expects an array with minimum length 1, and will respond with an error if it's empty
479
+ tool_calls: tool_calls.length > 0 ? tool_calls : void 0
480
+ });
481
+ }
482
+ }
483
+ }
484
+ return openAiMessages;
485
+ }
486
+
487
+ // src/AiService/DeepSeekService.ts
488
+ var DeepSeekService = class extends AiServiceBase {
489
+ #client;
490
+ model;
491
+ constructor(options) {
492
+ super(options.usageMeter);
493
+ this.#client = new import_openai.default({
494
+ baseURL: "https://api.deepseek.com/v1",
495
+ apiKey: options.apiKey
496
+ });
497
+ const id = options.model || deepSeekDefaultModelId;
498
+ this.model = {
499
+ provider: "deepseek",
500
+ id,
501
+ info: deepSeekModels[id] ?? deepSeekModels[deepSeekDefaultModelId]
502
+ };
503
+ }
504
+ async *sendImpl(systemPrompt, messages) {
505
+ const openAiMessages = [
506
+ { role: "system", content: systemPrompt },
507
+ ...convertToOpenAiMessages(messages)
508
+ ];
509
+ const stream = await this.#client.chat.completions.create({
510
+ model: this.model.id,
511
+ max_completion_tokens: this.model.info.maxTokens,
512
+ messages: openAiMessages,
513
+ temperature: 0,
514
+ stream: true,
515
+ stream_options: { include_usage: true }
516
+ });
517
+ for await (const chunk of stream) {
518
+ const delta = chunk.choices[0]?.delta;
519
+ if (delta?.reasoning_content) {
520
+ yield {
521
+ type: "reasoning",
522
+ text: delta.reasoning_content
523
+ };
524
+ }
525
+ if (delta?.content) {
526
+ yield {
527
+ type: "text",
528
+ text: delta.content
529
+ };
530
+ }
531
+ if (chunk.usage) {
532
+ yield {
533
+ type: "usage",
534
+ // deepseek reports total input AND cache reads/writes, see context caching: https://api-docs.deepseek.com/guides/kv_cache
535
+ // where the input tokens is the sum of the cache hits/misses, while anthropic reports them as separate tokens.
536
+ // This is important to know for
537
+ // 1) context management truncation algorithm, and
538
+ // 2) cost calculation (NOTE: we report both input and cache stats but for now set input price to 0 since all the cost calculation will be done using cache hits/misses)
539
+ inputTokens: chunk.usage.prompt_tokens,
540
+ outputTokens: chunk.usage.completion_tokens,
541
+ cacheWriteTokens: chunk.usage.prompt_cache_hit_tokens || 0,
542
+ cacheReadTokens: chunk.usage.prompt_cache_miss_tokens || 0
543
+ };
544
+ }
545
+ }
546
+ }
547
+ };
548
+
549
+ // src/AiService/OllamaService.ts
550
+ var import_openai2 = __toESM(require("openai"), 1);
551
+ var OllamaService = class extends AiServiceBase {
552
+ #client;
553
+ model;
554
+ constructor(options) {
555
+ super(options.usageMeter);
556
+ this.#client = new import_openai2.default({
557
+ baseURL: `${options.baseUrl || "http://localhost:11434"}/v1`,
558
+ apiKey: "ollama"
559
+ });
560
+ this.model = {
561
+ provider: "ollama",
562
+ id: options.model || "maryasov/qwen2.5-coder-cline:7b",
563
+ info: openAiModelInfoSaneDefaults
564
+ };
565
+ }
566
+ async *sendImpl(systemPrompt, messages) {
567
+ const openAiMessages = [
568
+ { role: "system", content: systemPrompt },
569
+ ...convertToOpenAiMessages(messages)
570
+ ];
571
+ const stream = await this.#client.chat.completions.create({
572
+ model: this.model.id,
573
+ messages: openAiMessages,
574
+ temperature: 0,
575
+ stream: true
576
+ });
577
+ for await (const chunk of stream) {
578
+ const delta = chunk.choices[0]?.delta;
579
+ if (delta?.content) {
580
+ yield {
581
+ type: "text",
582
+ text: delta.content
583
+ };
584
+ }
585
+ }
586
+ }
587
+ };
588
+
589
+ // src/AiService/OpenRouterService.ts
590
+ var import_openai3 = __toESM(require("openai"), 1);
591
+ var OpenRouterService = class extends AiServiceBase {
592
+ #client;
593
+ #apiKey;
594
+ #options;
595
+ #modelProviderInfo;
596
+ model;
597
+ constructor(options) {
598
+ super(options.usageMeter);
599
+ if (!options.model) {
600
+ throw new Error("OpenRouter requires a model");
601
+ }
602
+ if (!options.apiKey) {
603
+ throw new Error("OpenRouter requires an API key");
604
+ }
605
+ this.#apiKey = options.apiKey;
606
+ this.#client = new import_openai3.default({
607
+ baseURL: "https://openrouter.ai/api/v1",
608
+ apiKey: options.apiKey,
609
+ defaultHeaders: {
610
+ "HTTP-Referer": "https://polka.codes",
611
+ // Optional, for including your app on openrouter.ai rankings.
612
+ "X-Title": "Polka Codes"
613
+ // Optional. Shows in rankings on openrouter.ai.
614
+ }
615
+ });
616
+ this.#options = options;
617
+ this.model = {
618
+ provider: "openrouter",
619
+ id: options.model,
620
+ info: {}
621
+ };
622
+ fetch(`https://openrouter.ai/api/v1/models/${this.model.id}/endpoints`).then((res) => res.json()).then((data) => {
623
+ this.#modelProviderInfo = data.data;
624
+ });
625
+ }
626
+ async *sendImpl(systemPrompt, messages) {
627
+ const openAiMessages = [
628
+ { role: "system", content: systemPrompt },
629
+ ...convertToOpenAiMessages(messages)
630
+ ];
631
+ const cacheControl = this.#options.enableCache ? { type: "ephemeral" } : void 0;
632
+ switch (this.model.id) {
633
+ case "anthropic/claude-3.7-sonnet:thinking":
634
+ case "anthropic/claude-3.7-sonnet":
635
+ case "anthropic/claude-3.7-sonnet:beta":
636
+ case "anthropic/claude-3-7-sonnet":
637
+ case "anthropic/claude-3-7-sonnet:beta":
638
+ case "anthropic/claude-3.5-sonnet":
639
+ case "anthropic/claude-3.5-sonnet:beta":
640
+ case "anthropic/claude-3.5-sonnet-20240620":
641
+ case "anthropic/claude-3.5-sonnet-20240620:beta":
642
+ case "anthropic/claude-3-5-haiku":
643
+ case "anthropic/claude-3-5-haiku:beta":
644
+ case "anthropic/claude-3-5-haiku-20241022":
645
+ case "anthropic/claude-3-5-haiku-20241022:beta":
646
+ case "anthropic/claude-3-haiku":
647
+ case "anthropic/claude-3-haiku:beta":
648
+ case "anthropic/claude-3-opus":
649
+ case "anthropic/claude-3-opus:beta": {
650
+ openAiMessages[0] = {
651
+ role: "system",
652
+ content: [
653
+ {
654
+ type: "text",
655
+ text: systemPrompt,
656
+ // @ts-ignore-next-line
657
+ cache_control: cacheControl
658
+ }
659
+ ]
660
+ };
661
+ const lastTwoUserMessages = openAiMessages.filter((msg) => msg.role === "user").slice(-2);
662
+ for (const msg of lastTwoUserMessages) {
663
+ if (typeof msg.content === "string") {
664
+ msg.content = [{ type: "text", text: msg.content }];
665
+ }
666
+ if (Array.isArray(msg.content)) {
667
+ let lastTextPart = msg.content.filter((part) => part.type === "text").pop();
668
+ if (!lastTextPart) {
669
+ lastTextPart = { type: "text", text: "..." };
670
+ msg.content.push(lastTextPart);
671
+ }
672
+ lastTextPart.cache_control = cacheControl;
673
+ }
674
+ }
675
+ break;
676
+ }
677
+ default:
678
+ break;
679
+ }
680
+ let maxTokens;
681
+ switch (this.model.id) {
682
+ case "anthropic/claude-3.7-sonnet:thinking":
683
+ case "anthropic/claude-3.7-sonnet":
684
+ case "anthropic/claude-3.7-sonnet:beta":
685
+ case "anthropic/claude-3-7-sonnet":
686
+ case "anthropic/claude-3-7-sonnet:beta":
687
+ case "anthropic/claude-3.5-sonnet":
688
+ case "anthropic/claude-3.5-sonnet:beta":
689
+ case "anthropic/claude-3.5-sonnet-20240620":
690
+ case "anthropic/claude-3.5-sonnet-20240620:beta":
691
+ case "anthropic/claude-3-5-haiku":
692
+ case "anthropic/claude-3-5-haiku:beta":
693
+ case "anthropic/claude-3-5-haiku-20241022":
694
+ case "anthropic/claude-3-5-haiku-20241022:beta":
695
+ maxTokens = 8192;
696
+ break;
697
+ }
698
+ let shouldApplyMiddleOutTransform = !this.model.info.supportsPromptCache;
699
+ if (this.model.id === "deepseek/deepseek-chat") {
700
+ shouldApplyMiddleOutTransform = true;
701
+ }
702
+ const stream = await this.#client.chat.completions.create({
703
+ model: this.model.id,
704
+ max_completion_tokens: maxTokens,
705
+ messages: openAiMessages,
706
+ temperature: 0,
707
+ stream: true,
708
+ transforms: shouldApplyMiddleOutTransform ? ["middle-out"] : void 0,
709
+ include_reasoning: true
710
+ });
711
+ let genId;
712
+ for await (const chunk of stream) {
713
+ if ("error" in chunk) {
714
+ const error = chunk.error;
715
+ console.error(`OpenRouter API Error: ${error?.code} - ${error?.message}`);
716
+ throw new Error(`OpenRouter API Error ${error?.code}: ${error?.message}`);
717
+ }
718
+ if (!genId && chunk.id) {
719
+ genId = chunk.id;
720
+ }
721
+ const delta = chunk.choices[0]?.delta;
722
+ if (delta?.reasoning) {
723
+ yield {
724
+ type: "reasoning",
725
+ text: delta.reasoning
726
+ };
727
+ }
728
+ if (delta?.content) {
729
+ yield {
730
+ type: "text",
731
+ text: delta.content
732
+ };
733
+ }
734
+ }
735
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
736
+ const controller = new AbortController();
737
+ const timeout = setTimeout(() => controller.abort(), 5e3);
738
+ try {
739
+ const response = await fetch(`https://openrouter.ai/api/v1/generation?id=${genId}`, {
740
+ headers: {
741
+ Authorization: `Bearer ${this.#apiKey}`
742
+ },
743
+ signal: controller.signal
744
+ // this request hangs sometimes
745
+ });
746
+ const responseBody = await response.json();
747
+ const generation = responseBody.data ?? {};
748
+ let totalCost = generation.total_cost || 0;
749
+ if (generation.is_byok && this.#modelProviderInfo) {
750
+ const price = this.#modelProviderInfo.endpoints.find((e) => e.provider_name === generation.provider_name)?.pricing;
751
+ if (price) {
752
+ totalCost += (generation.native_tokens_prompt || 0) * price.request;
753
+ totalCost += (generation.native_tokens_completion || 0) * price.completion;
754
+ }
755
+ }
756
+ yield {
757
+ type: "usage",
758
+ // cacheWriteTokens: 0,
759
+ // cacheReadTokens: 0,
760
+ // openrouter generation endpoint fails often
761
+ inputTokens: generation.native_tokens_prompt || 0,
762
+ outputTokens: generation.native_tokens_completion || 0,
763
+ totalCost
764
+ };
765
+ } catch (error) {
766
+ console.error("Error fetching OpenRouter generation details:", error);
767
+ } finally {
768
+ clearTimeout(timeout);
769
+ }
770
+ }
771
+ };
772
+
773
+ // src/AiService/UsageMeter.ts
774
+ var import_lodash = require("lodash");
775
+ var UsageMeter = class {
776
+ #usage = {
777
+ inputTokens: 0,
778
+ outputTokens: 0,
779
+ cacheWriteTokens: 0,
780
+ cacheReadTokens: 0,
781
+ totalCost: 0
782
+ };
783
+ #messageCount = 0;
784
+ #prices = {};
785
+ maxCost;
786
+ maxMessageCount;
787
+ constructor(options = {}) {
788
+ this.maxCost = options.maxCost || 1e3;
789
+ this.maxMessageCount = options.maxMessageCount || 1e3;
790
+ this.#prices = (0, import_lodash.merge)({}, modelInfos, options.prices ?? {});
791
+ }
792
+ /**
793
+ * Add usage metrics to the current totals
794
+ */
795
+ addUsage(usage, model) {
796
+ this.#usage.inputTokens += usage.inputTokens ?? 0;
797
+ this.#usage.outputTokens += usage.outputTokens ?? 0;
798
+ this.#usage.cacheWriteTokens += usage.cacheWriteTokens ?? 0;
799
+ this.#usage.cacheReadTokens += usage.cacheReadTokens ?? 0;
800
+ if (!usage.totalCost && model) {
801
+ const modelInfo = this.#prices[model.provider]?.[model.id] ?? {};
802
+ usage.totalCost = ((modelInfo.inputPrice ?? 0) * (usage.inputTokens ?? 0) + (modelInfo.outputPrice ?? 0) * (usage.outputTokens ?? 0) + (modelInfo.cacheWritesPrice ?? 0) * (usage.cacheWriteTokens ?? 0) + (modelInfo.cacheReadsPrice ?? 0) * (usage.cacheReadTokens ?? 0)) / 1e6;
803
+ }
804
+ this.#usage.totalCost += usage.totalCost ?? 0;
805
+ }
806
+ incrementMessageCount(count = 1) {
807
+ this.#messageCount += count;
808
+ }
809
+ isLimitExceeded() {
810
+ const messageCount = this.#messageCount >= this.maxMessageCount;
811
+ const cost = this.#usage.totalCost >= this.maxCost;
812
+ return {
813
+ messageCount,
814
+ cost,
815
+ result: messageCount || cost
816
+ };
817
+ }
818
+ /**
819
+ * Get current usage totals
820
+ */
821
+ get usage() {
822
+ return { ...this.#usage };
823
+ }
824
+ printUsage() {
825
+ const { inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens } = this.#usage;
826
+ const allTokensZero = inputTokens === 0 && outputTokens === 0 && cacheReadTokens === 0 && cacheWriteTokens === 0;
827
+ console.log("Usages:");
828
+ if (!allTokensZero) {
829
+ console.log(`Input tokens: ${this.#usage.inputTokens}`);
830
+ console.log(`Output tokens: ${this.#usage.outputTokens}`);
831
+ console.log(`Cache read tokens: ${this.#usage.cacheReadTokens}`);
832
+ console.log(`Cache write tokens: ${this.#usage.cacheWriteTokens}`);
833
+ }
834
+ console.log(`Total cost: ${this.#usage.totalCost}`);
835
+ }
836
+ };
837
+
838
+ // src/AiService/index.ts
839
+ var AiServiceProvider = /* @__PURE__ */ ((AiServiceProvider2) => {
840
+ AiServiceProvider2["Anthropic"] = "anthropic";
841
+ AiServiceProvider2["Ollama"] = "ollama";
842
+ AiServiceProvider2["DeepSeek"] = "deepseek";
843
+ AiServiceProvider2["OpenRouter"] = "openrouter";
844
+ return AiServiceProvider2;
845
+ })(AiServiceProvider || {});
846
+ var defaultModels = {
847
+ ["anthropic" /* Anthropic */]: "claude-3-7-sonnet-20250219",
848
+ ["ollama" /* Ollama */]: "maryasov/qwen2.5-coder-cline:7b",
849
+ ["deepseek" /* DeepSeek */]: "deepseek-chat",
850
+ ["openrouter" /* OpenRouter */]: "anthropic/claude-3.7-sonnet"
851
+ };
852
+ var createService = (provider, options) => {
853
+ switch (provider) {
854
+ case "anthropic" /* Anthropic */:
855
+ return new AnthropicService(options);
856
+ case "ollama" /* Ollama */:
857
+ return new OllamaService(options);
858
+ case "deepseek" /* DeepSeek */:
859
+ return new DeepSeekService(options);
860
+ case "openrouter" /* OpenRouter */:
861
+ return new OpenRouterService(options);
862
+ }
863
+ };
864
+
865
+ // src/tools/provider.ts
866
+ var MockProvider = class {
867
+ async readFile(path) {
868
+ return "mock content";
869
+ }
870
+ async writeFile(path, content) {
871
+ return;
872
+ }
873
+ async removeFile(path) {
874
+ return;
875
+ }
876
+ async renameFile(sourcePath, targetPath) {
877
+ return;
878
+ }
879
+ async listFiles(path, recursive, maxCount) {
880
+ return [["mock-file.txt"], false];
881
+ }
882
+ async searchFiles(path, regex, filePattern) {
883
+ return ["mock-file.txt"];
884
+ }
885
+ async listCodeDefinitionNames(path) {
886
+ return "mockDefinition";
887
+ }
888
+ async executeCommand(command, needApprove) {
889
+ return { stdout: "mock output", stderr: "", exitCode: 0 };
890
+ }
891
+ async askFollowupQuestion(question, options) {
892
+ return "mock answer";
893
+ }
894
+ async attemptCompletion(result) {
895
+ return "mock completion";
896
+ }
897
+ };
898
+
899
+ // src/tools/allTools.ts
900
+ var allTools_exports = {};
901
+ __export(allTools_exports, {
902
+ askFollowupQuestion: () => askFollowupQuestion_default,
903
+ attemptCompletion: () => attemptCompletion_default,
904
+ delegate: () => delegate_default,
905
+ executeCommand: () => executeCommand_default,
906
+ handOver: () => handOver_default,
907
+ listCodeDefinitionNames: () => listCodeDefinitionNames_default,
908
+ listFiles: () => listFiles_default,
909
+ readFile: () => readFile_default,
910
+ removeFile: () => removeFile_default,
911
+ renameFile: () => renameFile_default,
912
+ replaceInFile: () => replaceInFile_default,
913
+ searchFiles: () => searchFiles_default,
914
+ writeToFile: () => writeToFile_default
915
+ });
916
+
917
+ // src/tool.ts
918
+ var PermissionLevel = /* @__PURE__ */ ((PermissionLevel2) => {
919
+ PermissionLevel2[PermissionLevel2["None"] = 0] = "None";
920
+ PermissionLevel2[PermissionLevel2["Read"] = 1] = "Read";
921
+ PermissionLevel2[PermissionLevel2["Write"] = 2] = "Write";
922
+ PermissionLevel2[PermissionLevel2["Arbitrary"] = 3] = "Arbitrary";
923
+ return PermissionLevel2;
924
+ })(PermissionLevel || {});
925
+ var ToolResponseType = /* @__PURE__ */ ((ToolResponseType2) => {
926
+ ToolResponseType2["Reply"] = "Reply";
927
+ ToolResponseType2["Exit"] = "Exit";
928
+ ToolResponseType2["Invalid"] = "Invalid";
929
+ ToolResponseType2["Error"] = "Error";
930
+ ToolResponseType2["Interrupted"] = "Interrupted";
931
+ ToolResponseType2["HandOver"] = "HandOver";
932
+ ToolResponseType2["Delegate"] = "Delegate";
933
+ return ToolResponseType2;
934
+ })(ToolResponseType || {});
935
+
936
+ // src/tools/utils/replaceInFile.ts
937
+ var replaceInFile = async (fileContent, diff) => {
938
+ const blockPattern = /<<<<<+ SEARCH\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
939
+ const blocks = [];
940
+ for (let match = blockPattern.exec(diff); match !== null; match = blockPattern.exec(diff)) {
941
+ blocks.push({ search: match[1], replace: match[2] });
942
+ }
943
+ if (blocks.length === 0) {
944
+ throw new Error("No valid diff blocks found.");
945
+ }
946
+ const findAndReplace = (content, search, replace) => {
947
+ let index = content.indexOf(search);
948
+ if (index !== -1) {
949
+ return content.slice(0, index) + replace + content.slice(index + search.length);
950
+ }
951
+ const trimmedSearch = search.trim();
952
+ const trimmedContent = content.trim();
953
+ const offset = content.indexOf(trimmedContent);
954
+ index = trimmedContent.indexOf(trimmedSearch);
955
+ if (index !== -1) {
956
+ const absoluteIndex = offset + index;
957
+ return content.slice(0, absoluteIndex) + replace + content.slice(absoluteIndex + trimmedSearch.length);
958
+ }
959
+ const normalizedSearch = trimmedSearch.replace(/\s+/g, " ");
960
+ const normalizedContent = trimmedContent.replace(/\s+/g, " ");
961
+ index = normalizedContent.indexOf(normalizedSearch);
962
+ if (index !== -1) {
963
+ let runningIndex = 0;
964
+ let actualPos = offset;
965
+ for (const segment of trimmedSearch.replace(/\s+/g, " ").split(" ")) {
966
+ const segIndex = content.indexOf(segment, actualPos);
967
+ if (segIndex === -1) {
968
+ break;
969
+ }
970
+ if (runningIndex === 0) {
971
+ actualPos = segIndex;
972
+ } else {
973
+ actualPos = segIndex + segment.length;
974
+ }
975
+ runningIndex++;
976
+ }
977
+ const strippedSearch = trimmedSearch.replace(/\s+/g, "");
978
+ const endPos = actualPos;
979
+ const startPos = endPos - strippedSearch.length;
980
+ return content.slice(0, startPos) + replace + content.slice(endPos);
981
+ }
982
+ throw new Error(`Could not find the following text in file:
983
+ ${search}`);
984
+ };
985
+ let updatedFile = fileContent;
986
+ for (const { search, replace } of blocks) {
987
+ updatedFile = findAndReplace(updatedFile, search, replace);
988
+ }
989
+ return updatedFile;
990
+ };
991
+
992
+ // src/tools/utils/getArg.ts
993
+ var getString = (args, name, defaultValue) => {
994
+ const ret = args[name] ?? defaultValue;
995
+ if (ret === void 0) {
996
+ throw new Error(`Missing required argument: ${name}`);
997
+ }
998
+ return ret;
999
+ };
1000
+ var getStringArray = (args, name, defaultValue) => {
1001
+ const ret = args[name];
1002
+ if (ret === void 0) {
1003
+ if (defaultValue === void 0) {
1004
+ throw new Error(`Missing required argument: ${name}`);
1005
+ }
1006
+ return defaultValue;
1007
+ }
1008
+ if (ret === "") {
1009
+ return [];
1010
+ }
1011
+ return ret.split(",").map((s) => s.trim());
1012
+ };
1013
+ var getBoolean = (args, name, defaultValue) => {
1014
+ const ret = args[name];
1015
+ if (ret === void 0) {
1016
+ if (defaultValue === void 0) {
1017
+ throw new Error(`Missing required argument: ${name}`);
1018
+ }
1019
+ return defaultValue;
1020
+ }
1021
+ switch (ret.toLowerCase()) {
1022
+ case "true":
1023
+ return true;
1024
+ case "false":
1025
+ return false;
1026
+ default:
1027
+ throw new Error(`Invalid argument value: ${name}`);
1028
+ }
1029
+ };
1030
+ var getInt = (args, name, defaultValue) => {
1031
+ const ret = args[name];
1032
+ if (ret === void 0) {
1033
+ if (defaultValue === void 0) {
1034
+ throw new Error(`Missing required argument: ${name}`);
1035
+ }
1036
+ return defaultValue;
1037
+ }
1038
+ const parsed = Number.parseInt(ret);
1039
+ if (Number.isNaN(parsed)) {
1040
+ throw new Error(`Invalid argument value: ${name}`);
1041
+ }
1042
+ return parsed;
1043
+ };
1044
+
1045
+ // src/tools/askFollowupQuestion.ts
1046
+ var toolInfo = {
1047
+ name: "ask_followup_question",
1048
+ description: "Whenever you need extra details or clarification to complete the task, pose a direct question to the user. Use this tool sparingly to avoid excessive back-and-forth. If helpful, offer multiple-choice options or examples to guide the user\u2019s response.",
1049
+ parameters: [
1050
+ {
1051
+ name: "question",
1052
+ description: "The question to ask the user. This should be a clear, specific question that addresses the information you need.",
1053
+ required: true,
1054
+ usageValue: "Your question here"
1055
+ },
1056
+ {
1057
+ name: "options",
1058
+ description: "A comma separated list of possible answers to the question. Ordered by preference. If not provided, the user will be prompted to provide an answer.",
1059
+ required: false,
1060
+ usageValue: "A comma separated list of possible answers (optional)"
1061
+ }
1062
+ ],
1063
+ examples: [
1064
+ {
1065
+ description: "Request to ask a question",
1066
+ parameters: [
1067
+ {
1068
+ name: "question",
1069
+ value: "What is the name of the project?"
1070
+ }
1071
+ ]
1072
+ },
1073
+ {
1074
+ description: "Request to ask a question with options",
1075
+ parameters: [
1076
+ {
1077
+ name: "question",
1078
+ value: "What framework do you use?"
1079
+ },
1080
+ {
1081
+ name: "options",
1082
+ value: "React,Angular,Vue,Svelte"
1083
+ }
1084
+ ]
1085
+ }
1086
+ ],
1087
+ permissionLevel: 0 /* None */
1088
+ };
1089
+ var handler = async (provider, args) => {
1090
+ if (!provider.askFollowupQuestion) {
1091
+ return {
1092
+ type: "Error" /* Error */,
1093
+ message: "Not possible to ask followup question. Abort."
1094
+ };
1095
+ }
1096
+ const question = getString(args, "question");
1097
+ const options = getStringArray(args, "options", []);
1098
+ const answer = await provider.askFollowupQuestion(question, options);
1099
+ return {
1100
+ type: "Reply" /* Reply */,
1101
+ message: `<ask_followup_question_question>${question}</ask_followup_question_question>
1102
+ <ask_followup_question_answer>${answer}</ask_followup_question_answer>`
1103
+ };
1104
+ };
1105
+ var isAvailable = (provider) => {
1106
+ return !!provider.askFollowupQuestion;
1107
+ };
1108
+ var askFollowupQuestion_default = {
1109
+ ...toolInfo,
1110
+ handler,
1111
+ isAvailable
1112
+ };
1113
+
1114
+ // src/tools/attemptCompletion.ts
1115
+ var toolInfo2 = {
1116
+ name: "attempt_completion",
1117
+ 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.",
1118
+ parameters: [
1119
+ {
1120
+ name: "result",
1121
+ description: "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.",
1122
+ required: true,
1123
+ usageValue: "Your final result description here"
1124
+ }
1125
+ ],
1126
+ examples: [
1127
+ {
1128
+ description: "Request to present the result of the task",
1129
+ parameters: [
1130
+ {
1131
+ name: "result",
1132
+ value: "Your final result description here"
1133
+ }
1134
+ ]
1135
+ }
1136
+ ],
1137
+ permissionLevel: 0 /* None */
1138
+ };
1139
+ var handler2 = async (provider, args) => {
1140
+ const result = getString(args, "result");
1141
+ const moreMessage = await provider.attemptCompletion?.(result);
1142
+ if (!moreMessage) {
1143
+ return {
1144
+ type: "Exit" /* Exit */,
1145
+ message: result
1146
+ };
1147
+ }
1148
+ return {
1149
+ type: "Reply" /* Reply */,
1150
+ message: `<user_message>${moreMessage}</user_message>`
1151
+ };
1152
+ };
1153
+ var isAvailable2 = (provider) => {
1154
+ return true;
1155
+ };
1156
+ var attemptCompletion_default = {
1157
+ ...toolInfo2,
1158
+ handler: handler2,
1159
+ isAvailable: isAvailable2
1160
+ };
1161
+
1162
+ // src/tools/delegate.ts
1163
+ var toolInfo3 = {
1164
+ name: "delegate",
1165
+ description: "Temporarily delegate a task to another agent and receive the result back. This tool MUST NOT to be used with any other tool.",
1166
+ parameters: [
1167
+ {
1168
+ name: "agent_name",
1169
+ description: "The name of the agent to delegate the task to",
1170
+ required: true,
1171
+ usageValue: "Name of the target agent"
1172
+ },
1173
+ {
1174
+ name: "task",
1175
+ description: "The task to be completed by the target agent",
1176
+ required: true,
1177
+ usageValue: "Task description"
1178
+ },
1179
+ {
1180
+ name: "context",
1181
+ description: "The context information for the task",
1182
+ required: true,
1183
+ usageValue: "Context information"
1184
+ },
1185
+ {
1186
+ name: "files",
1187
+ description: "The files relevant to the task. Comma separated paths",
1188
+ required: false,
1189
+ usageValue: "Relevant files"
1190
+ }
1191
+ ],
1192
+ examples: [
1193
+ {
1194
+ description: "Delegate a code analysis task to the analyzer agent",
1195
+ parameters: [
1196
+ {
1197
+ name: "agent_name",
1198
+ value: "analyzer"
1199
+ },
1200
+ {
1201
+ name: "task",
1202
+ value: "Analyze the authentication implementation"
1203
+ },
1204
+ {
1205
+ name: "context",
1206
+ value: "Need to understand the security implications of the current auth system"
1207
+ },
1208
+ {
1209
+ name: "files",
1210
+ value: "src/auth/login.ts,src/auth/types.ts"
1211
+ }
1212
+ ]
1213
+ }
1214
+ ],
1215
+ permissionLevel: 0 /* None */
1216
+ };
1217
+ var handler3 = async (_provider, args) => {
1218
+ const agentName = getString(args, "agent_name");
1219
+ const task = getString(args, "task");
1220
+ const context = getString(args, "context", void 0);
1221
+ const files = getStringArray(args, "files", []);
1222
+ return {
1223
+ type: "Delegate" /* Delegate */,
1224
+ agentName,
1225
+ task,
1226
+ context,
1227
+ files
1228
+ };
1229
+ };
1230
+ var isAvailable3 = (_provider) => {
1231
+ return true;
1232
+ };
1233
+ var delegate_default = {
1234
+ ...toolInfo3,
1235
+ handler: handler3,
1236
+ isAvailable: isAvailable3
1237
+ };
1238
+
1239
+ // src/tools/executeCommand.ts
1240
+ var toolInfo4 = {
1241
+ name: "execute_command",
1242
+ description: `Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will also be executed in the project root directory regardless of executed commands in previous tool uses.`,
1243
+ parameters: [
1244
+ {
1245
+ name: "command",
1246
+ description: "The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.",
1247
+ required: true,
1248
+ usageValue: "Your command here"
1249
+ },
1250
+ {
1251
+ name: "requires_approval",
1252
+ description: `A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.`,
1253
+ required: false,
1254
+ usageValue: "true or false"
1255
+ }
1256
+ ],
1257
+ examples: [
1258
+ {
1259
+ description: "Request to execute a command",
1260
+ parameters: [
1261
+ {
1262
+ name: "command",
1263
+ value: "npm run dev"
1264
+ },
1265
+ {
1266
+ name: "requires_approval",
1267
+ value: "false"
1268
+ }
1269
+ ]
1270
+ }
1271
+ ],
1272
+ permissionLevel: 3 /* Arbitrary */
1273
+ };
1274
+ var handler4 = async (provider, args) => {
1275
+ if (!provider.executeCommand) {
1276
+ return {
1277
+ type: "Error" /* Error */,
1278
+ message: "Not possible to execute command. Abort."
1279
+ };
1280
+ }
1281
+ const command = getString(args, "command");
1282
+ const requiresApproval = getBoolean(args, "requires_approval", false);
1283
+ const result = await provider.executeCommand?.(command, requiresApproval);
1284
+ const message = `<command>${command}</command>
1285
+ <command_exit_code>${result.exitCode}</command_exit_code>
1286
+ <command_stdout>
1287
+ ${result.stdout}
1288
+ </command_stdout>
1289
+ <command_stderr>
1290
+ ${result.stderr}
1291
+ </command_stderr>`;
1292
+ if (result.exitCode === 0) {
1293
+ return {
1294
+ type: "Reply" /* Reply */,
1295
+ message
1296
+ };
1297
+ }
1298
+ return {
1299
+ type: "Error" /* Error */,
1300
+ message
1301
+ };
1302
+ };
1303
+ var isAvailable4 = (provider) => {
1304
+ return !!provider.executeCommand;
1305
+ };
1306
+ var executeCommand_default = {
1307
+ ...toolInfo4,
1308
+ handler: handler4,
1309
+ isAvailable: isAvailable4
1310
+ };
1311
+
1312
+ // src/tools/listCodeDefinitionNames.ts
1313
+ var toolInfo5 = {
1314
+ name: "list_code_definition_names",
1315
+ description: "Request to list definition names (classes, functions, methods, etc.) used for all files in a directory. This tool provides insights into the codebase structure and important constructs, encapsulating high-level concepts and relationships that are crucial for understanding the overall architecture.",
1316
+ parameters: [
1317
+ {
1318
+ name: "path",
1319
+ description: "The path of a code file to list top level source code definitions for.",
1320
+ required: true,
1321
+ usageValue: "Directory path here"
1322
+ }
1323
+ ],
1324
+ examples: [
1325
+ {
1326
+ description: "Request to list code definition names in a directory",
1327
+ parameters: [
1328
+ {
1329
+ name: "path",
1330
+ value: "src/utils"
1331
+ }
1332
+ ]
1333
+ }
1334
+ ],
1335
+ permissionLevel: 1 /* Read */
1336
+ };
1337
+ var handler5 = async (provider, args) => {
1338
+ if (!provider.listCodeDefinitionNames) {
1339
+ return {
1340
+ type: "Error" /* Error */,
1341
+ message: "Not possible to list code definition names. Abort."
1342
+ };
1343
+ }
1344
+ const path = getString(args, "path");
1345
+ const result = await provider.listCodeDefinitionNames(path);
1346
+ return {
1347
+ type: "Reply" /* Reply */,
1348
+ message: `<list_code_definition_names_path>${path}</list_code_definition_names_path>
1349
+ <list_code_definition_names_result>
1350
+ ${result}
1351
+ </list_code_definition_names_result>`
1352
+ };
1353
+ };
1354
+ var isAvailable5 = (provider) => {
1355
+ return !!provider.listCodeDefinitionNames;
1356
+ };
1357
+ var listCodeDefinitionNames_default = {
1358
+ ...toolInfo5,
1359
+ handler: handler5,
1360
+ isAvailable: isAvailable5
1361
+ };
1362
+
1363
+ // src/tools/listFiles.ts
1364
+ var toolInfo6 = {
1365
+ name: "list_files",
1366
+ 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.",
1367
+ parameters: [
1368
+ {
1369
+ name: "path",
1370
+ description: "The path of the directory to list contents for (relative to the current working directory)",
1371
+ required: true,
1372
+ usageValue: "Directory path here"
1373
+ },
1374
+ {
1375
+ name: "max_count",
1376
+ description: "The maximum number of files to list. Default to 2000",
1377
+ required: false,
1378
+ usageValue: "Maximum number of files to list (optional)"
1379
+ },
1380
+ {
1381
+ name: "recursive",
1382
+ description: "Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.",
1383
+ required: false,
1384
+ usageValue: "true or false (optional)"
1385
+ }
1386
+ ],
1387
+ examples: [
1388
+ {
1389
+ description: "Request to list files",
1390
+ parameters: [
1391
+ {
1392
+ name: "path",
1393
+ value: "src"
1394
+ },
1395
+ {
1396
+ name: "max_count",
1397
+ value: "100"
1398
+ }
1399
+ ]
1400
+ }
1401
+ ],
1402
+ permissionLevel: 1 /* Read */
1403
+ };
1404
+ var handler6 = async (provider, args) => {
1405
+ if (!provider.listFiles) {
1406
+ return {
1407
+ type: "Error" /* Error */,
1408
+ message: "Not possible to list files. Abort."
1409
+ };
1410
+ }
1411
+ const path = getString(args, "path");
1412
+ const maxCount = getInt(args, "max_count", 2e3);
1413
+ const recursive = getBoolean(args, "recursive", true);
1414
+ const [files, limitReached] = await provider.listFiles(path, recursive, maxCount);
1415
+ return {
1416
+ type: "Reply" /* Reply */,
1417
+ message: `<list_files_path>${path}</list_files_path>
1418
+ <list_files_files>
1419
+ ${files.join("\n")}
1420
+ </list_files_files>
1421
+ <list_files_truncated>${limitReached}</list_files_truncated>`
1422
+ };
1423
+ };
1424
+ var isAvailable6 = (provider) => {
1425
+ return !!provider.listFiles;
1426
+ };
1427
+ var listFiles_default = {
1428
+ ...toolInfo6,
1429
+ handler: handler6,
1430
+ isAvailable: isAvailable6
1431
+ };
1432
+
1433
+ // src/tools/readFile.ts
1434
+ var toolInfo7 = {
1435
+ name: "read_file",
1436
+ 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.",
1437
+ parameters: [
1438
+ {
1439
+ name: "path",
1440
+ description: "The path of the file to read",
1441
+ required: true,
1442
+ usageValue: "Comma separated paths here"
1443
+ }
1444
+ ],
1445
+ examples: [
1446
+ {
1447
+ description: "Request to read the contents of a file",
1448
+ parameters: [
1449
+ {
1450
+ name: "path",
1451
+ value: "src/main.js"
1452
+ }
1453
+ ]
1454
+ },
1455
+ {
1456
+ description: "Request to read multiple files",
1457
+ parameters: [
1458
+ {
1459
+ name: "path",
1460
+ value: "src/main.js,src/index.js"
1461
+ }
1462
+ ]
1463
+ }
1464
+ ],
1465
+ permissionLevel: 1 /* Read */
1466
+ };
1467
+ var handler7 = async (provider, args) => {
1468
+ if (!provider.readFile) {
1469
+ return {
1470
+ type: "Error" /* Error */,
1471
+ message: "Not possible to read file. Abort."
1472
+ };
1473
+ }
1474
+ const paths = getStringArray(args, "path");
1475
+ const resp = [];
1476
+ for (const path of paths) {
1477
+ const fileContent = await provider.readFile(path);
1478
+ const isEmpty = fileContent.trim().length === 0;
1479
+ if (isEmpty) {
1480
+ resp.push(`<read_file_file_content path="${path}" is_empty="true" />`);
1481
+ } else {
1482
+ resp.push(`<read_file_file_conten path="${path}">${fileContent}</read_file_file_content>`);
1483
+ }
1484
+ }
1485
+ return {
1486
+ type: "Reply" /* Reply */,
1487
+ message: resp.join("\n")
1488
+ };
1489
+ };
1490
+ var isAvailable7 = (provider) => {
1491
+ return !!provider.readFile;
1492
+ };
1493
+ var readFile_default = {
1494
+ ...toolInfo7,
1495
+ handler: handler7,
1496
+ isAvailable: isAvailable7
1497
+ };
1498
+
1499
+ // src/tools/replaceInFile.ts
1500
+ var toolInfo8 = {
1501
+ name: "replace_in_file",
1502
+ 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.",
1503
+ parameters: [
1504
+ {
1505
+ name: "path",
1506
+ description: "The path of the file to modify",
1507
+ required: true,
1508
+ usageValue: "File path here"
1509
+ },
1510
+ {
1511
+ name: "diff",
1512
+ description: `One or more SEARCH/REPLACE blocks following this exact format:
1513
+ \`\`\`
1514
+ <<<<<<< SEARCH
1515
+ [exact content to find]
1516
+ =======
1517
+ [new content to replace with]
1518
+ >>>>>>> REPLACE
1519
+ \`\`\`
1520
+ Critical rules:
1521
+ 1. SEARCH content must match the associated file section to find EXACTLY:
1522
+ * Match character-for-character including whitespace, indentation, line endings
1523
+ * Include all comments, docstrings, etc.
1524
+ 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
1525
+ * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes.
1526
+ * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change.
1527
+ * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file.
1528
+ 3. Keep SEARCH/REPLACE blocks concise:
1529
+ * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file.
1530
+ * Include just the changing lines, and a few surrounding lines if needed for uniqueness.
1531
+ * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks.
1532
+ * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures.
1533
+ 4. Special operations:
1534
+ * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location)
1535
+ * To delete code: Use empty REPLACE section`,
1536
+ required: true,
1537
+ usageValue: "Search and replace blocks here"
1538
+ }
1539
+ ],
1540
+ examples: [
1541
+ {
1542
+ description: "Request to replace sections of content in a file",
1543
+ parameters: [
1544
+ {
1545
+ name: "path",
1546
+ value: "src/main.js"
1547
+ },
1548
+ {
1549
+ name: "diff",
1550
+ value: `
1551
+ <<<<<<< SEARCH
1552
+ import React from 'react';
1553
+ =======
1554
+ import React, { useState } from 'react';
1555
+ >>>>>>> REPLACE
1556
+
1557
+ <<<<<<< SEARCH
1558
+ function handleSubmit() {
1559
+ saveData();
1560
+ setLoading(false);
1561
+ }
1562
+
1563
+ =======
1564
+ >>>>>>> REPLACE
1565
+
1566
+ <<<<<<< SEARCH
1567
+ return (
1568
+ <div>
1569
+ =======
1570
+ function handleSubmit() {
1571
+ saveData();
1572
+ setLoading(false);
1573
+ }
1574
+
1575
+ return (
1576
+ <div>
1577
+ >>>>>>> REPLACE
1578
+ `
1579
+ }
1580
+ ]
1581
+ }
1582
+ ],
1583
+ permissionLevel: 2 /* Write */
1584
+ };
1585
+ var handler8 = async (provider, args) => {
1586
+ if (!provider.readFile || !provider.writeFile) {
1587
+ return {
1588
+ type: "Error" /* Error */,
1589
+ message: "Not possible to replace in file. Abort."
1590
+ };
1591
+ }
1592
+ const path = getString(args, "path");
1593
+ const diff = getString(args, "diff");
1594
+ const fileContent = await provider.readFile(path);
1595
+ const result = await replaceInFile(fileContent, diff);
1596
+ await provider.writeFile(path, result);
1597
+ return {
1598
+ type: "Reply" /* Reply */,
1599
+ message: `<replace_in_file_path>${path}</replace_in_file_path>`
1600
+ };
1601
+ };
1602
+ var isAvailable8 = (provider) => {
1603
+ return !!provider.readFile && !!provider.writeFile;
1604
+ };
1605
+ var replaceInFile_default = {
1606
+ ...toolInfo8,
1607
+ handler: handler8,
1608
+ isAvailable: isAvailable8
1609
+ };
1610
+
1611
+ // src/tools/searchFiles.ts
1612
+ var toolInfo9 = {
1613
+ name: "search_files",
1614
+ 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.",
1615
+ parameters: [
1616
+ {
1617
+ name: "path",
1618
+ description: "The path of the directory to search in (relative to the current working directory). This directory will be recursively searched.",
1619
+ required: true,
1620
+ usageValue: "Directory path here"
1621
+ },
1622
+ {
1623
+ name: "regex",
1624
+ description: "The regular expression pattern to search for. Uses Rust regex syntax.",
1625
+ required: true,
1626
+ usageValue: "Your regex pattern here"
1627
+ },
1628
+ {
1629
+ name: "file_pattern",
1630
+ description: 'Glob pattern to filter files (e.g., "*.ts" for TypeScript files). If not provided, it will search all files (*).',
1631
+ required: false,
1632
+ usageValue: "file pattern here (optional)"
1633
+ }
1634
+ ],
1635
+ examples: [
1636
+ {
1637
+ description: "Request to perform a regex search across files",
1638
+ parameters: [
1639
+ {
1640
+ name: "path",
1641
+ value: "src"
1642
+ },
1643
+ {
1644
+ name: "regex",
1645
+ value: "^components/"
1646
+ },
1647
+ {
1648
+ name: "file_pattern",
1649
+ value: "*.ts"
1650
+ }
1651
+ ]
1652
+ }
1653
+ ],
1654
+ permissionLevel: 1 /* Read */
1655
+ };
1656
+ var handler9 = async (provider, args) => {
1657
+ if (!provider.searchFiles) {
1658
+ return {
1659
+ type: "Error" /* Error */,
1660
+ message: "Not possible to search files. Abort."
1661
+ };
1662
+ }
1663
+ const path = getString(args, "path");
1664
+ const regex = getString(args, "regex");
1665
+ const filePattern = getString(args, "file_pattern", "*");
1666
+ const files = await provider.searchFiles(path, regex, filePattern);
1667
+ return {
1668
+ type: "Reply" /* Reply */,
1669
+ message: `<search_files_path>${path}</search_files_path>
1670
+ <search_files_regex>${regex}</search_files_regex>
1671
+ <search_files_file_pattern>${filePattern}</search_files_file_pattern>
1672
+ <search_files_files>
1673
+ ${files.join("\n")}
1674
+ </search_files_files>
1675
+ `
1676
+ };
1677
+ };
1678
+ var isAvailable9 = (provider) => {
1679
+ return !!provider.searchFiles;
1680
+ };
1681
+ var searchFiles_default = {
1682
+ ...toolInfo9,
1683
+ handler: handler9,
1684
+ isAvailable: isAvailable9
1685
+ };
1686
+
1687
+ // src/tools/writeToFile.ts
1688
+ var toolInfo10 = {
1689
+ name: "write_to_file",
1690
+ 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.",
1691
+ parameters: [
1692
+ {
1693
+ name: "path",
1694
+ description: "The path of the file to write to",
1695
+ required: true,
1696
+ usageValue: "File path here"
1697
+ },
1698
+ {
1699
+ name: "content",
1700
+ description: "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.",
1701
+ required: true,
1702
+ usageValue: "Your file content here"
1703
+ }
1704
+ ],
1705
+ examples: [
1706
+ {
1707
+ description: "Request to write content to a file",
1708
+ parameters: [
1709
+ {
1710
+ name: "path",
1711
+ value: "src/main.js"
1712
+ },
1713
+ {
1714
+ name: "content",
1715
+ value: `import React from 'react';
1716
+
1717
+ function App() {
1718
+ return (
1719
+ <div>
1720
+ <h1>Hello, World!</h1>
1721
+ </div>
1722
+ );
1723
+ }
1724
+
1725
+ export default App;
1726
+ `
1727
+ }
1728
+ ]
1729
+ }
1730
+ ],
1731
+ permissionLevel: 2 /* Write */
1732
+ };
1733
+ var handler10 = async (provider, args) => {
1734
+ if (!provider.writeFile) {
1735
+ return {
1736
+ type: "Error" /* Error */,
1737
+ message: "Not possible to write file. Abort."
1738
+ };
1739
+ }
1740
+ const path = getString(args, "path");
1741
+ const content = getString(args, "content");
1742
+ await provider.writeFile(path, content);
1743
+ return {
1744
+ type: "Reply" /* Reply */,
1745
+ message: `<write_to_file_path>${path}</write_to_file_path><status>Success</status>`
1746
+ };
1747
+ };
1748
+ var isAvailable10 = (provider) => {
1749
+ return !!provider.writeFile;
1750
+ };
1751
+ var writeToFile_default = {
1752
+ ...toolInfo10,
1753
+ handler: handler10,
1754
+ isAvailable: isAvailable10
1755
+ };
1756
+
1757
+ // src/tools/handOver.ts
1758
+ var toolInfo11 = {
1759
+ name: "hand_over",
1760
+ description: "Hand over the current task to another agent to complete. This tool MUST NOT to be used with any other tool.",
1761
+ parameters: [
1762
+ {
1763
+ name: "agent_name",
1764
+ description: "The name of the agent to hand over the task to",
1765
+ required: true,
1766
+ usageValue: "Name of the target agent"
1767
+ },
1768
+ {
1769
+ name: "task",
1770
+ description: "The task to be completed by the target agent",
1771
+ required: true,
1772
+ usageValue: "Task description"
1773
+ },
1774
+ {
1775
+ name: "context",
1776
+ description: "The context information for the task",
1777
+ required: true,
1778
+ usageValue: "Context information"
1779
+ },
1780
+ {
1781
+ name: "files",
1782
+ description: "The files relevant to the task. Comma separated paths",
1783
+ required: false,
1784
+ usageValue: "Relevant files"
1785
+ }
1786
+ ],
1787
+ examples: [
1788
+ {
1789
+ description: "Hand over a coding task to the coder agent",
1790
+ parameters: [
1791
+ {
1792
+ name: "agent_name",
1793
+ value: "coder"
1794
+ },
1795
+ {
1796
+ name: "task",
1797
+ value: "Implement the login feature"
1798
+ },
1799
+ {
1800
+ name: "context",
1801
+ value: "We need a secure login system with email and password"
1802
+ },
1803
+ {
1804
+ name: "files",
1805
+ value: "src/auth/login.ts,src/auth/types.ts"
1806
+ }
1807
+ ]
1808
+ }
1809
+ ],
1810
+ permissionLevel: 0 /* None */
1811
+ };
1812
+ var handler11 = async (_provider, args) => {
1813
+ const agentName = getString(args, "agent_name");
1814
+ const task = getString(args, "task");
1815
+ const context = getString(args, "context", void 0);
1816
+ const files = getStringArray(args, "files", []);
1817
+ return {
1818
+ type: "HandOver" /* HandOver */,
1819
+ agentName,
1820
+ task,
1821
+ context,
1822
+ files
1823
+ };
1824
+ };
1825
+ var isAvailable11 = (_provider) => {
1826
+ return true;
1827
+ };
1828
+ var handOver_default = {
1829
+ ...toolInfo11,
1830
+ handler: handler11,
1831
+ isAvailable: isAvailable11
1832
+ };
1833
+
1834
+ // src/tools/removeFile.ts
1835
+ var toolInfo12 = {
1836
+ name: "remove_file",
1837
+ description: "Request to remove a file at the specified path.",
1838
+ parameters: [
1839
+ {
1840
+ name: "path",
1841
+ description: "The path of the file to remove",
1842
+ required: true,
1843
+ usageValue: "File path here"
1844
+ }
1845
+ ],
1846
+ examples: [
1847
+ {
1848
+ description: "Request to remove a file",
1849
+ parameters: [
1850
+ {
1851
+ name: "path",
1852
+ value: "src/main.js"
1853
+ }
1854
+ ]
1855
+ }
1856
+ ],
1857
+ permissionLevel: 2 /* Write */
1858
+ };
1859
+ var handler12 = async (provider, args) => {
1860
+ if (!provider.removeFile) {
1861
+ return {
1862
+ type: "Error" /* Error */,
1863
+ message: "Not possible to remove file. Abort."
1864
+ };
1865
+ }
1866
+ const path = getString(args, "path");
1867
+ await provider.removeFile(path);
1868
+ return {
1869
+ type: "Reply" /* Reply */,
1870
+ message: `<remove_file_path>${path}</remove_file_path><status>Success</status>`
1871
+ };
1872
+ };
1873
+ var isAvailable12 = (provider) => {
1874
+ return !!provider.removeFile;
1875
+ };
1876
+ var removeFile_default = {
1877
+ ...toolInfo12,
1878
+ handler: handler12,
1879
+ isAvailable: isAvailable12
1880
+ };
1881
+
1882
+ // src/tools/renameFile.ts
1883
+ var toolInfo13 = {
1884
+ name: "rename_file",
1885
+ description: "Request to rename a file from source path to target path.",
1886
+ parameters: [
1887
+ {
1888
+ name: "sourcePath",
1889
+ description: "The current path of the file",
1890
+ required: true,
1891
+ usageValue: "Source file path here"
1892
+ },
1893
+ {
1894
+ name: "targetPath",
1895
+ description: "The new path for the file",
1896
+ required: true,
1897
+ usageValue: "Target file path here"
1898
+ }
1899
+ ],
1900
+ examples: [
1901
+ {
1902
+ description: "Request to rename a file",
1903
+ parameters: [
1904
+ {
1905
+ name: "sourcePath",
1906
+ value: "src/old-name.js"
1907
+ },
1908
+ {
1909
+ name: "targetPath",
1910
+ value: "src/new-name.js"
1911
+ }
1912
+ ]
1913
+ }
1914
+ ],
1915
+ permissionLevel: 2 /* Write */
1916
+ };
1917
+ var handler13 = async (provider, args) => {
1918
+ if (!provider.renameFile) {
1919
+ return {
1920
+ type: "Error" /* Error */,
1921
+ message: "Not possible to rename file. Abort."
1922
+ };
1923
+ }
1924
+ const sourcePath = getString(args, "sourcePath");
1925
+ const targetPath = getString(args, "targetPath");
1926
+ await provider.renameFile(sourcePath, targetPath);
1927
+ return {
1928
+ type: "Reply" /* Reply */,
1929
+ message: `<rename_file_path>${targetPath}</rename_file_path><status>Success</status>`
1930
+ };
1931
+ };
1932
+ var isAvailable13 = (provider) => {
1933
+ return !!provider.renameFile;
1934
+ };
1935
+ var renameFile_default = {
1936
+ ...toolInfo13,
1937
+ handler: handler13,
1938
+ isAvailable: isAvailable13
1939
+ };
1940
+
1941
+ // src/getAvailableTools.ts
1942
+ var getAvailableTools = ({
1943
+ provider,
1944
+ allTools,
1945
+ hasAgent,
1946
+ permissionLevel,
1947
+ interactive
1948
+ }) => {
1949
+ const filteredTools = interactive ? allTools : allTools.filter((tool) => tool.name !== askFollowupQuestion_default.name);
1950
+ const tools = [];
1951
+ for (const tool of filteredTools) {
1952
+ if (!hasAgent) {
1953
+ switch (tool.name) {
1954
+ case handOver_default.name:
1955
+ case delegate_default.name:
1956
+ continue;
1957
+ }
1958
+ }
1959
+ if (tool.isAvailable(provider) && tool.permissionLevel <= permissionLevel) {
1960
+ tools.push(tool);
1961
+ }
1962
+ }
1963
+ return tools;
1964
+ };
1965
+
1966
+ // src/Agent/parseAssistantMessage.ts
1967
+ function parseAssistantMessage(assistantMessage, tools, toolNamePrefix) {
1968
+ const parameterPrefix = `${toolNamePrefix}parameter_`;
1969
+ const results = [];
1970
+ const toolTags = tools.map((tool) => `${toolNamePrefix}${tool.name}`);
1971
+ const toolPattern = toolTags.join("|");
1972
+ let remainingMessage = assistantMessage;
1973
+ let match;
1974
+ const tagRegex = new RegExp(`<(${toolPattern})>([\\s\\S]*?)<\\/\\1>`, "s");
1975
+ while (true) {
1976
+ match = tagRegex.exec(remainingMessage);
1977
+ if (match === null) break;
1978
+ const beforeTag = remainingMessage.slice(0, match.index).trim();
1979
+ if (beforeTag) {
1980
+ results.push({
1981
+ type: "text",
1982
+ content: beforeTag
1983
+ });
1984
+ }
1985
+ const tagName = match[1];
1986
+ const toolName = tagName.replace(toolNamePrefix, "");
1987
+ const tool = tools.find((t) => t.name === toolName);
1988
+ const fullTagContent = match[0];
1989
+ if (tool) {
1990
+ const params = {};
1991
+ for (const param of tool.parameters) {
1992
+ const paramName = `${parameterPrefix}${param.name}`;
1993
+ const escapedParamName = paramName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1994
+ const paramPattern = `<${escapedParamName}>([\\s\\S]*?)<\\/${escapedParamName}>`;
1995
+ const paramMatch = fullTagContent.match(new RegExp(paramPattern, "s"));
1996
+ if (paramMatch) {
1997
+ params[param.name] = paramMatch[1].trim();
1998
+ }
1999
+ }
2000
+ results.push({
2001
+ type: "tool_use",
2002
+ name: toolName,
2003
+ params
2004
+ });
2005
+ } else {
2006
+ results.push({
2007
+ type: "text",
2008
+ content: fullTagContent
2009
+ });
2010
+ }
2011
+ remainingMessage = remainingMessage.slice(match.index + fullTagContent.length);
2012
+ }
2013
+ if (remainingMessage.trim()) {
2014
+ results.push({
2015
+ type: "text",
2016
+ content: remainingMessage.trim()
2017
+ });
2018
+ }
2019
+ if (results.length === 0) {
2020
+ results.push({
2021
+ type: "text",
2022
+ content: assistantMessage
2023
+ });
2024
+ }
2025
+ return results;
2026
+ }
2027
+
2028
+ // src/Agent/prompts.ts
2029
+ var toolInfoPrompt = (tool, toolNamePrefix, parameterPrefix) => `
2030
+ ## ${toolNamePrefix}${tool.name}
2031
+
2032
+ Description: ${tool.description}
2033
+
2034
+ Parameters:
2035
+ ${tool.parameters.map((param) => `- ${parameterPrefix}${param.name}: (${param.required ? "required" : "optional"}) ${param.description}`).join("\n")}
2036
+
2037
+ Usage:
2038
+ <${toolNamePrefix}${tool.name}>
2039
+ ${tool.parameters.map((param) => `<${parameterPrefix}${param.name}>${param.usageValue}</${parameterPrefix}${param.name}>`).join("\n")}
2040
+ </${toolNamePrefix}${tool.name}>`;
2041
+ var toolInfoExamplesPrompt = (idx, tool, example, toolNamePrefix, parameterPrefix) => `
2042
+ ## Example ${idx + 1}: ${example.description}
2043
+
2044
+ <${toolNamePrefix}${tool.name}>
2045
+ ${example.parameters.map((param) => `<${parameterPrefix}${param.name}>${param.value}</${parameterPrefix}${param.name}>`).join("\n")}
2046
+ </${toolNamePrefix}${tool.name}>
2047
+ `;
2048
+ var toolUsePrompt = (tools, toolNamePrefix) => {
2049
+ if (tools.length === 0) {
2050
+ return "";
2051
+ }
2052
+ const parameterPrefix = `${toolNamePrefix}parameter_`;
2053
+ let exampleIndex = 0;
2054
+ return `
2055
+ ====
2056
+
2057
+ TOOL USE
2058
+
2059
+ You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use 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.
2060
+
2061
+ # Tool Use Formatting
2062
+
2063
+ 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:
2064
+
2065
+ <${toolNamePrefix}tool_name>
2066
+ <${parameterPrefix}name1>value1</${parameterPrefix}name1>
2067
+ <${parameterPrefix}name2>value2</${parameterPrefix}name2>
2068
+ ...
2069
+ </${toolNamePrefix}tool_name>
2070
+
2071
+ For example:
2072
+
2073
+ <${toolNamePrefix}read_file>
2074
+ <${parameterPrefix}path>src/main.js</${parameterPrefix}path>
2075
+ </${toolNamePrefix}read_file>
2076
+
2077
+ Always adhere to this format for the tool use to ensure proper parsing and execution.
2078
+
2079
+ NEVER surround tool use with triple backticks (\`\`\`).
2080
+
2081
+ # Tools
2082
+ ${tools.map((tool) => toolInfoPrompt(tool, toolNamePrefix, parameterPrefix)).join("\n")}
2083
+
2084
+ # Tool Use Examples
2085
+ ${tools.map((tool) => {
2086
+ let promp = "";
2087
+ for (const example of tool.examples ?? []) {
2088
+ promp += toolInfoExamplesPrompt(exampleIndex++, tool, example, toolNamePrefix, parameterPrefix);
2089
+ }
2090
+ return promp;
2091
+ }).join("")}
2092
+ # Tool Use Guidelines
2093
+
2094
+ 1. **Thinking**: Use \`<thinking>\` XCM tag to clearly outline your thought process *before* using any tools. This includes:
2095
+ * Assessing the current situation and available information.
2096
+ * Defining specific goals and a plan to achieve them.
2097
+ * Justifying the selection of a particular tool.
2098
+ * Explaining how you intend to use the tool and what you expect to achieve.
2099
+ 2. **Tool Selection**: Choose one tool at a time per message based on the task and its description. Do not assume a tool\u2019s outcome without explicit confirmation.
2100
+ 3. **Formatting**: Formulate tool use only in the specified XML format for each tool.
2101
+ 4. **User Response**: Wait for the user\u2019s response after each tool use. Do not proceed until you have their confirmation. The user\u2019s response may include:
2102
+ * Tool success or failure details
2103
+ * Linter errors
2104
+ * Terminal output or other relevant feedback
2105
+ 5. **Conciseness**: Never repeat or quote the entire tool command in your final user-facing message. Summarize outcomes clearly and avoid echoing commands verbatim.
2106
+ 6. **Brevity**: Respond concisely and move the conversation forward. Do not re-issue the same command or re-trigger tool use without necessity.
2107
+ 7. **Iteration**: Follow these steps iteratively, confirming success and addressing issues as you go.
2108
+ 8. **Error Handling**: If a tool returns an error, analyze the error message and adjust your approach accordingly. Consider alternative tools or strategies to achieve the desired outcome.
2109
+
2110
+ By adhering to these guidelines:
2111
+ - You maintain clarity without accidentally re-invoking tools.
2112
+ - You confirm each step\u2019s results before proceeding.
2113
+ - You provide only the necessary information in user-facing replies to prevent re-interpretation as new commands.`;
2114
+ };
2115
+ var agentsPrompt = (agents, name) => `
2116
+ ====
2117
+
2118
+ AVAILABLE AGENTS
2119
+
2120
+ The following agents are available for task handover/delegate:
2121
+ ${agents.map(
2122
+ (agent) => `
2123
+ - **${agent.name}**
2124
+ - Responsibilities:
2125
+ ${agent.responsibilities.map((resp) => ` - ${resp}`).join("\n")}`
2126
+ ).join("\n")}
2127
+
2128
+ - **Current Agent Role**
2129
+ 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.
2130
+ `;
2131
+ var capabilities = (toolNamePrefix) => `
2132
+ ====
2133
+
2134
+ CAPABILITIES
2135
+
2136
+ - 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.
2137
+ - 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.`;
2138
+ var systemInformation = (info) => `
2139
+ ====
2140
+
2141
+ SYSTEM INFORMATION
2142
+
2143
+ Operating System: ${info.os}`;
2144
+ var customInstructions = (customInstructions2) => {
2145
+ const joined = customInstructions2.join("\n");
2146
+ if (joined.trim() === "") {
2147
+ return "";
2148
+ }
2149
+ return `
2150
+ ====
2151
+
2152
+ USER'S CUSTOM INSTRUCTIONS
2153
+
2154
+ 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.
2155
+
2156
+ ${joined}`;
2157
+ };
2158
+ var customScripts = (commands) => {
2159
+ const joined = Object.entries(commands).map(([name, command]) => {
2160
+ if (typeof command === "string") {
2161
+ return `- ${name}
2162
+ - Command: \`${command}\``;
2163
+ }
2164
+ return `- ${name}
2165
+ - Command: \`${command.command}\`
2166
+ - Description: ${command.description}`;
2167
+ }).join("\n");
2168
+ if (joined.trim() === "") {
2169
+ return "";
2170
+ }
2171
+ return `
2172
+ ====
2173
+
2174
+ USER'S CUSTOM COMMANDS
2175
+
2176
+ 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.
2177
+
2178
+ ${joined}`;
2179
+ };
2180
+ var responsePrompts = {
2181
+ errorInvokeTool: (tool, error) => `An error occurred while invoking the tool "${tool}": ${error}`,
2182
+ requireUseTool: "Error: You MUST use a tool before proceeding using XCM tags. e.g. <tool_tool_name>tool_name</tool_tool_name>",
2183
+ toolResults: (tool, result) => `<tool_response>
2184
+ <tool_name>${tool}</tool_name>
2185
+ <tool_result>
2186
+ ${result}
2187
+ </tool_result>
2188
+ </tool_response>`,
2189
+ commandResult: (command, exitCode, stdout, stderr) => `<command>${command}</command>
2190
+ <command_exit_code>${exitCode}</command_exit_code>
2191
+ <command_stdout>
2192
+ ${stdout}
2193
+ </command_stdout>
2194
+ <command_stderr>
2195
+ ${stderr}
2196
+ </command_stderr>`
2197
+ };
2198
+
2199
+ // src/Agent/AgentBase.ts
2200
+ var TaskEventKind = /* @__PURE__ */ ((TaskEventKind2) => {
2201
+ TaskEventKind2["StartTask"] = "StartTask";
2202
+ TaskEventKind2["StartRequest"] = "StartRequest";
2203
+ TaskEventKind2["EndRequest"] = "EndRequest";
2204
+ TaskEventKind2["Usage"] = "Usage";
2205
+ TaskEventKind2["Text"] = "Text";
2206
+ TaskEventKind2["Reasoning"] = "Reasoning";
2207
+ TaskEventKind2["ToolUse"] = "ToolUse";
2208
+ TaskEventKind2["ToolReply"] = "ToolReply";
2209
+ TaskEventKind2["ToolInvalid"] = "ToolInvalid";
2210
+ TaskEventKind2["ToolError"] = "ToolError";
2211
+ TaskEventKind2["ToolInterrupted"] = "ToolInterrupted";
2212
+ TaskEventKind2["ToolHandOver"] = "ToolHandOver";
2213
+ TaskEventKind2["ToolDelegate"] = "ToolDelegate";
2214
+ TaskEventKind2["UsageExceeded"] = "UsageExceeded";
2215
+ TaskEventKind2["EndTask"] = "EndTask";
2216
+ return TaskEventKind2;
2217
+ })(TaskEventKind || {});
2218
+ var AgentBase = class {
2219
+ ai;
2220
+ config;
2221
+ handlers;
2222
+ messages = [];
2223
+ constructor(name, ai, config) {
2224
+ this.ai = ai;
2225
+ if (config.agents && config.agents.length > 0) {
2226
+ const agents = agentsPrompt(config.agents, name);
2227
+ config.systemPrompt += `
2228
+ ${agents}`;
2229
+ }
2230
+ this.config = config;
2231
+ const handlers = {};
2232
+ for (const tool of config.tools) {
2233
+ handlers[tool.name] = tool;
2234
+ }
2235
+ this.handlers = handlers;
2236
+ }
2237
+ async #callback(event) {
2238
+ await this.config.callback?.(event);
2239
+ }
2240
+ async startTask({ task, context }) {
2241
+ let text = `<task>${task}</task>`;
2242
+ if (context) {
2243
+ text += `
2244
+ <context>${context}</context>`;
2245
+ }
2246
+ this.#callback({ kind: "StartTask" /* StartTask */, agent: this, systemPrompt: this.config.systemPrompt });
2247
+ return await this.#processLoop(text);
2248
+ }
2249
+ async #processLoop(userMessage) {
2250
+ let nextRequest = userMessage;
2251
+ while (true) {
2252
+ if (this.ai.usageMeter.isLimitExceeded().result) {
2253
+ this.#callback({ kind: "UsageExceeded" /* UsageExceeded */, agent: this });
2254
+ return { type: "UsageExceeded" };
2255
+ }
2256
+ const response = await this.#request(nextRequest);
2257
+ const resp = await this.#handleResponse(response);
2258
+ if ("exit" in resp) {
2259
+ this.#callback({ kind: "EndTask" /* EndTask */, agent: this, exitReason: resp.exit });
2260
+ return resp.exit;
2261
+ }
2262
+ nextRequest = resp.replay;
2263
+ }
2264
+ }
2265
+ async continueTask(userMessage) {
2266
+ return await this.#processLoop(userMessage);
2267
+ }
2268
+ async #request(userMessage) {
2269
+ if (!userMessage) {
2270
+ throw new Error("userMessage is missing");
2271
+ }
2272
+ await this.#callback({ kind: "StartRequest" /* StartRequest */, agent: this, userMessage });
2273
+ this.messages.push({
2274
+ role: "user",
2275
+ content: userMessage
2276
+ });
2277
+ let currentAssistantMessage = "";
2278
+ const retryCount = 5;
2279
+ for (let i = 0; i < retryCount; i++) {
2280
+ currentAssistantMessage = "";
2281
+ const stream = this.ai.send(this.config.systemPrompt, this.messages);
2282
+ for await (const chunk of stream) {
2283
+ switch (chunk.type) {
2284
+ case "usage":
2285
+ await this.#callback({ kind: "Usage" /* Usage */, agent: this });
2286
+ break;
2287
+ case "text":
2288
+ currentAssistantMessage += chunk.text;
2289
+ await this.#callback({ kind: "Text" /* Text */, agent: this, newText: chunk.text });
2290
+ break;
2291
+ case "reasoning":
2292
+ await this.#callback({ kind: "Reasoning" /* Reasoning */, agent: this, newText: chunk.text });
2293
+ break;
2294
+ }
2295
+ }
2296
+ if (currentAssistantMessage) {
2297
+ break;
2298
+ }
2299
+ console.debug(`Retrying request ${i + 1} of ${retryCount}`);
2300
+ }
2301
+ if (!currentAssistantMessage) {
2302
+ throw new Error("No assistant message received");
2303
+ }
2304
+ this.messages.push({
2305
+ role: "assistant",
2306
+ content: currentAssistantMessage
2307
+ });
2308
+ const ret = parseAssistantMessage(currentAssistantMessage, this.config.tools, this.config.toolNamePrefix);
2309
+ await this.#callback({ kind: "EndRequest" /* EndRequest */, agent: this });
2310
+ return ret;
2311
+ }
2312
+ async #handleResponse(response) {
2313
+ const toolReponses = [];
2314
+ outer: for (const content of response) {
2315
+ switch (content.type) {
2316
+ case "text":
2317
+ break;
2318
+ case "tool_use": {
2319
+ await this.#callback({ kind: "ToolUse" /* ToolUse */, agent: this, tool: content.name });
2320
+ const toolResp = await this.#invokeTool(content.name, content.params);
2321
+ switch (toolResp.type) {
2322
+ case "Reply" /* Reply */:
2323
+ await this.#callback({ kind: "ToolReply" /* ToolReply */, agent: this, tool: content.name });
2324
+ toolReponses.push({ tool: content.name, response: toolResp.message });
2325
+ break;
2326
+ case "Exit" /* Exit */:
2327
+ if (toolReponses.length > 0) {
2328
+ break outer;
2329
+ }
2330
+ return { exit: toolResp };
2331
+ case "Invalid" /* Invalid */:
2332
+ await this.#callback({ kind: "ToolInvalid" /* ToolInvalid */, agent: this, tool: content.name });
2333
+ toolReponses.push({ tool: content.name, response: toolResp.message });
2334
+ break outer;
2335
+ case "Error" /* Error */:
2336
+ await this.#callback({ kind: "ToolError" /* ToolError */, agent: this, tool: content.name });
2337
+ toolReponses.push({ tool: content.name, response: toolResp.message });
2338
+ break outer;
2339
+ case "Interrupted" /* Interrupted */:
2340
+ await this.#callback({ kind: "ToolInterrupted" /* ToolInterrupted */, agent: this, tool: content.name });
2341
+ return { exit: toolResp };
2342
+ case "HandOver" /* HandOver */:
2343
+ if (toolReponses.length > 0) {
2344
+ break outer;
2345
+ }
2346
+ await this.#callback({
2347
+ kind: "ToolHandOver" /* ToolHandOver */,
2348
+ agent: this,
2349
+ tool: content.name,
2350
+ agentName: toolResp.agentName,
2351
+ task: toolResp.task,
2352
+ context: toolResp.context,
2353
+ files: toolResp.files
2354
+ });
2355
+ return { exit: toolResp };
2356
+ case "Delegate" /* Delegate */:
2357
+ if (toolReponses.length > 0) {
2358
+ continue;
2359
+ }
2360
+ await this.#callback({
2361
+ kind: "ToolDelegate" /* ToolDelegate */,
2362
+ agent: this,
2363
+ tool: content.name,
2364
+ agentName: toolResp.agentName,
2365
+ task: toolResp.task,
2366
+ context: toolResp.context,
2367
+ files: toolResp.files
2368
+ });
2369
+ return { exit: toolResp };
2370
+ }
2371
+ break;
2372
+ }
2373
+ }
2374
+ }
2375
+ if (toolReponses.length === 0) {
2376
+ return { replay: responsePrompts.requireUseTool };
2377
+ }
2378
+ const finalResp = toolReponses.map(({ tool, response: response2 }) => responsePrompts.toolResults(tool, response2)).join("\n\n");
2379
+ return { replay: finalResp };
2380
+ }
2381
+ async #invokeTool(name, args) {
2382
+ try {
2383
+ const handler14 = this.handlers[name]?.handler;
2384
+ if (!handler14) {
2385
+ return {
2386
+ type: "Error" /* Error */,
2387
+ message: responsePrompts.errorInvokeTool(name, "Tool not found"),
2388
+ canRetry: false
2389
+ };
2390
+ }
2391
+ const resp = await this.onBeforeInvokeTool(this.handlers[name].name, args);
2392
+ if (resp) {
2393
+ return resp;
2394
+ }
2395
+ return await handler14(this.config.provider, args);
2396
+ } catch (error) {
2397
+ return {
2398
+ type: "Error" /* Error */,
2399
+ message: responsePrompts.errorInvokeTool(name, error),
2400
+ canRetry: false
2401
+ };
2402
+ }
2403
+ }
2404
+ get model() {
2405
+ return this.ai.model;
2406
+ }
2407
+ get usage() {
2408
+ return this.ai.usageMeter.usage;
2409
+ }
2410
+ };
2411
+
2412
+ // src/Agent/AnalyzerAgent/prompts.ts
2413
+ var fullSystemPrompt = (info, tools, toolNamePrefix, instructions, scripts) => `
2414
+ # Analyzer Agent
2415
+
2416
+ ## Role
2417
+ You are the **Analyzer** agent, responsible for:
2418
+ 1. **Project Structure Analysis** \u2013 Understand codebase organization and architecture.
2419
+ 2. **Code Pattern Analysis** \u2013 Identify common patterns, conventions, and best practices.
2420
+ 3. **Dependency Analysis** \u2013 Examine project dependencies and their usage.
2421
+ 4. **Workflow Analysis** \u2013 Understand development tools, scripts, and processes.
2422
+ 5. **Documentation Review** \u2013 Analyze documentation and code comments.
2423
+
2424
+ > **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.
2425
+
2426
+ ## Rules
2427
+ 1. **Thoroughness**: Conduct comprehensive analysis of relevant project aspects.
2428
+ 2. **Pattern Recognition**: Identify recurring patterns, conventions, and architectural decisions.
2429
+ 3. **Dependency Mapping**: Track and understand relationships between components.
2430
+ 4. **Workflow Understanding**: Analyze build processes, testing approaches, and development tools.
2431
+ 5. **Documentation Assessment**: Review documentation quality and completeness.
2432
+ 6. **Non-Modification**: Never modify code or files - focus solely on analysis.
2433
+
2434
+ ${toolUsePrompt(tools, toolNamePrefix)}
2435
+ ${capabilities(toolNamePrefix)}
2436
+ ${systemInformation(info)}
2437
+ ${customInstructions(instructions)}
2438
+ ${customScripts(scripts)}
2439
+ `;
2440
+
2441
+ // src/Agent/AnalyzerAgent/index.ts
2442
+ var AnalyzerAgent = class extends AgentBase {
2443
+ constructor(options) {
2444
+ const combinedTools = [...options.additionalTools ?? [], ...Object.values(allTools_exports)];
2445
+ const tools = getAvailableTools({
2446
+ provider: options.provider,
2447
+ allTools: combinedTools,
2448
+ hasAgent: (options.agents?.length ?? 0) > 0,
2449
+ permissionLevel: 1 /* Read */,
2450
+ interactive: true
2451
+ });
2452
+ const toolNamePrefix = "tool_";
2453
+ const systemPrompt = fullSystemPrompt(
2454
+ {
2455
+ os: options.os
2456
+ },
2457
+ tools,
2458
+ toolNamePrefix,
2459
+ options.customInstructions ?? [],
2460
+ options.scripts ?? {}
2461
+ );
2462
+ super(analyzerAgentInfo.name, options.ai, {
2463
+ systemPrompt,
2464
+ tools,
2465
+ toolNamePrefix,
2466
+ provider: options.provider,
2467
+ interactive: options.interactive,
2468
+ agents: options.agents,
2469
+ scripts: options.scripts,
2470
+ callback: options.callback
2471
+ });
2472
+ }
2473
+ onBeforeInvokeTool() {
2474
+ return Promise.resolve(void 0);
2475
+ }
2476
+ };
2477
+ var analyzerAgentInfo = {
2478
+ name: "analyzer",
2479
+ responsibilities: [
2480
+ "Analyzing project structure and organization",
2481
+ "Identifying key source code files and their relationships",
2482
+ "Understanding common coding patterns and conventions",
2483
+ "Examining development workflow and tooling",
2484
+ "Analyzing dependencies and their usage patterns"
2485
+ ]
2486
+ };
2487
+
2488
+ // src/Agent/ArchitectAgent/prompts.ts
2489
+ var fullSystemPrompt2 = (info, tools, toolNamePrefix, instructions, scripts) => `
2490
+ # Architect Agent
2491
+
2492
+ ## Role
2493
+ You are the **Architect** agent, responsible for:
2494
+ 1. **Task Analysis** \u2013 Understand requirements.
2495
+ 2. **File Identification** \u2013 Find and select relevant files.
2496
+ 3. **File Reading** \u2013 Use the provided tools to gather information from these files.
2497
+ 4. **Implementation Plan** \u2013 Draft a concise plan detailing steps, resources, and dependencies.
2498
+ 5. **Review & Improve** \u2013 Evaluate and refine the plan.
2499
+ 6. **Handover/Delegate** \u2013 Provide the final plan, context, and files to the **Coder** agent.
2500
+
2501
+ > **Note**: The **Architect** agent must not make any direct modifications. Your role is limited to creating the implementation plan and handing it over to the **Coder** agent, who will perform any actual changes.
2502
+
2503
+ ## Rules
2504
+ 1. **Consistency**: Maintain alignment with the user\u2019s instructions and the system\u2019s objectives at all times.
2505
+ 2. **Relevance**: Only read and use files directly related to the task. Avoid unnecessary or tangential information.
2506
+ 3. **Conciseness**: Keep all communications and plans succinct, avoiding superfluous or repetitive details.
2507
+ 4. **Accuracy**: Ensure the information you gather and any conclusions you draw are correct and verifiable.
2508
+ 5. **Clarity**: Present the final plan and any supporting details in a structured and easily understandable format.
2509
+ 6. **Minimal Queries**: Ask clarifying questions only when essential, and avoid repeated questioning that does not add value.
2510
+
2511
+ ## Steps
2512
+ 1. **Analyze Task**
2513
+ - Gather and understand the user\u2019s requirements.
2514
+ - Note any potential constraints or objectives that may influence the plan.
2515
+
2516
+ 2. **Identify Relevant Files**
2517
+ - Determine which files or documents are necessary.
2518
+ - Justify why these files are relevant.
2519
+
2520
+ 3. **Read Files via Tools**
2521
+ - Utilize the provided tools to access and extract information from the identified files.
2522
+ - Summarize key insights or data for the solution.
2523
+
2524
+ 4. **Create Implementation Plan**
2525
+ - Outline tasks, define milestones, and detail resources or dependencies.
2526
+ - Provide clear, concise instructions for each step.
2527
+ - Each step should be appropriate sized and self-contained.
2528
+
2529
+ 5. **Handover/Delegate**
2530
+ - Evaluate the number of steps required.
2531
+ - Handleover to the **Coder** agent if only one step is required.
2532
+ - If multiple steps are required, delegate each step to the **Coder** agent.
2533
+ - Deliver the final implementation plan, context, and relevant files to the **Coder** agent.
2534
+ - Provide any additional instructions or clarifications needed for successful implementation.
2535
+
2536
+ ${toolUsePrompt(tools, toolNamePrefix)}
2537
+ ${capabilities(toolNamePrefix)}
2538
+ ${systemInformation(info)}
2539
+ ${customInstructions(instructions)}
2540
+ ${customScripts(scripts)}
2541
+ `;
2542
+
2543
+ // src/Agent/ArchitectAgent/index.ts
2544
+ var ArchitectAgent = class extends AgentBase {
2545
+ constructor(options) {
2546
+ const combinedTools = [...options.additionalTools ?? [], ...Object.values(allTools_exports)];
2547
+ const tools = getAvailableTools({
2548
+ provider: options.provider,
2549
+ allTools: combinedTools,
2550
+ hasAgent: (options.agents?.length ?? 0) > 0,
2551
+ permissionLevel: 1 /* Read */,
2552
+ interactive: true
2553
+ });
2554
+ const toolNamePrefix = "tool_";
2555
+ const systemPrompt = fullSystemPrompt2(
2556
+ {
2557
+ os: options.os
2558
+ },
2559
+ tools,
2560
+ toolNamePrefix,
2561
+ options.customInstructions ?? [],
2562
+ options.scripts ?? {}
2563
+ );
2564
+ super(architectAgentInfo.name, options.ai, {
2565
+ systemPrompt,
2566
+ tools,
2567
+ toolNamePrefix,
2568
+ provider: options.provider,
2569
+ interactive: options.interactive,
2570
+ agents: options.agents,
2571
+ scripts: options.scripts,
2572
+ callback: options.callback
2573
+ });
2574
+ }
2575
+ onBeforeInvokeTool() {
2576
+ return Promise.resolve(void 0);
2577
+ }
2578
+ };
2579
+ var architectAgentInfo = {
2580
+ name: "architect",
2581
+ responsibilities: [
2582
+ "Analyzing the user\u2019s overall task and requirements.",
2583
+ "Creating plans and making higher-level decisions about system structure and design.",
2584
+ "Reviewing and analyzing existing code or components for maintainability and scalability.",
2585
+ "Laying out the roadmap for implementation."
2586
+ ]
2587
+ };
2588
+
2589
+ // src/Agent/CodeFixerAgent/prompts.ts
2590
+ var basePrompt = `You are a highly skilled software engineer specializing in debugging and fixing code issues. You have extensive experience with:
2591
+ - Type systems and type checking
2592
+ - Test frameworks and debugging test failures
2593
+ - Code quality tools and best practices
2594
+ - Systematic debugging approaches`;
2595
+ var codeFixingStrategies = `
2596
+ ====
2597
+
2598
+ CODE FIXING STRATEGIES
2599
+
2600
+ 1. Type Errors
2601
+ - Analyze type error messages carefully
2602
+ - Check type definitions and imports
2603
+ - Consider type assertions only as a last resort
2604
+ - Verify type compatibility across function boundaries
2605
+ - Look for null/undefined handling issues
2606
+
2607
+ 2. Test Failures
2608
+ - Examine test output and error messages
2609
+ - Check test setup and fixtures
2610
+ - Verify assertions and expectations
2611
+ - Look for async/timing issues
2612
+ - Consider edge cases and input validation
2613
+
2614
+ 3. Code Quality Issues
2615
+ - Follow project's coding standards
2616
+ - Address linter warnings systematically
2617
+ - Improve code readability
2618
+ - Fix potential runtime issues
2619
+ - Consider performance implications
2620
+
2621
+ 4. General Approach
2622
+ - Start with the most critical issues
2623
+ - Make minimal necessary changes
2624
+ - Verify fixes don't introduce new issues
2625
+ - Document complex fixes with comments
2626
+ - Track attempted solutions for each issue`;
2627
+ var retryGuidelines = `
2628
+ ====
2629
+
2630
+ RETRY GUIDELINES
2631
+
2632
+ 1. Before Retrying
2633
+ - Analyze previous attempt's failure
2634
+ - Consider alternative approaches
2635
+ - Check if similar issues were fixed
2636
+ - Verify no new issues were introduced
2637
+
2638
+ 2. When to Retry
2639
+ - Error message changed but issue persists
2640
+ - New information available about the root cause
2641
+ - Different fixing strategy available
2642
+ - Previous attempt partially successful
2643
+
2644
+ 3. When to Stop
2645
+ - Maximum retry limit reached
2646
+ - Same error occurs repeatedly
2647
+ - Fix would require major refactoring
2648
+ - Issue requires human intervention
2649
+
2650
+ 4. After Maximum Retries
2651
+ - Document attempted solutions
2652
+ - Explain why the issue remains
2653
+ - Suggest manual intervention steps
2654
+ - Report any partial improvements`;
2655
+ var fullSystemPrompt3 = (info, tools, toolNamePrefix, instructions, scripts, interactive) => `
2656
+ ${basePrompt}
2657
+ ${toolUsePrompt(tools, toolNamePrefix)}
2658
+ ${codeFixingStrategies}
2659
+ ${retryGuidelines}
2660
+ ${capabilities(toolNamePrefix)}
2661
+ ${systemInformation(info)}
2662
+ ${customInstructions(instructions)}
2663
+ ${customScripts(scripts)}`;
2664
+
2665
+ // src/Agent/CodeFixerAgent/index.ts
2666
+ var CodeFixerAgent = class extends AgentBase {
2667
+ #maxRetries;
2668
+ #retryCount = 0;
2669
+ constructor(options) {
2670
+ const combinedTools = [...options.additionalTools ?? [], ...Object.values(allTools_exports)];
2671
+ const tools = getAvailableTools({
2672
+ provider: options.provider,
2673
+ allTools: combinedTools,
2674
+ hasAgent: (options.agents?.length ?? 0) > 0,
2675
+ permissionLevel: 3 /* Arbitrary */,
2676
+ interactive: true
2677
+ });
2678
+ const toolNamePrefix = "tool_";
2679
+ const systemPrompt = fullSystemPrompt3(
2680
+ {
2681
+ os: options.os
2682
+ },
2683
+ tools,
2684
+ toolNamePrefix,
2685
+ options.customInstructions ?? [],
2686
+ options.scripts ?? {},
2687
+ options.interactive
2688
+ );
2689
+ super(codeFixerAgentInfo.name, options.ai, {
2690
+ systemPrompt,
2691
+ tools,
2692
+ toolNamePrefix,
2693
+ provider: options.provider,
2694
+ interactive: options.interactive,
2695
+ agents: options.agents,
2696
+ scripts: options.scripts,
2697
+ callback: options.callback
2698
+ });
2699
+ this.#maxRetries = options.maxRetries ?? 5;
2700
+ }
2701
+ async onBeforeInvokeTool(name, args) {
2702
+ if (name === attemptCompletion_default.name) {
2703
+ if (this.#retryCount > this.#maxRetries) {
2704
+ return;
2705
+ }
2706
+ this.#retryCount++;
2707
+ const executeCommand = this.config.provider.executeCommand;
2708
+ if (!executeCommand) {
2709
+ return;
2710
+ }
2711
+ const check = this.config.scripts?.check;
2712
+ const checkCommand = typeof check === "string" ? check : check?.command;
2713
+ if (checkCommand) {
2714
+ try {
2715
+ const { exitCode, stdout, stderr } = await executeCommand(checkCommand, false);
2716
+ if (exitCode !== 0) {
2717
+ return {
2718
+ type: "Reply" /* Reply */,
2719
+ message: responsePrompts.commandResult(checkCommand, exitCode, stdout, stderr)
2720
+ };
2721
+ }
2722
+ } catch (error) {
2723
+ console.warn(`Failed to check code using command: ${checkCommand}`, error);
2724
+ }
2725
+ }
2726
+ const test = this.config.scripts?.test;
2727
+ const testCommand = typeof test === "string" ? test : test?.command;
2728
+ if (testCommand) {
2729
+ try {
2730
+ const { exitCode, stdout, stderr } = await executeCommand(testCommand, false);
2731
+ if (exitCode !== 0) {
2732
+ return {
2733
+ type: "Reply" /* Reply */,
2734
+ message: responsePrompts.commandResult(testCommand, exitCode, stdout, stderr)
2735
+ };
2736
+ }
2737
+ } catch (error) {
2738
+ console.warn(`Failed to test code using command: ${testCommand}`, error);
2739
+ }
2740
+ }
2741
+ }
2742
+ }
2743
+ };
2744
+ var codeFixerAgentInfo = {
2745
+ name: "codefixer",
2746
+ responsibilities: [
2747
+ "Fixing type errors and type-related issues",
2748
+ "Resolving failing tests",
2749
+ "Addressing code quality issues",
2750
+ "Tracking and reporting unfixed issues"
2751
+ ]
2752
+ };
2753
+
2754
+ // src/Agent/CoderAgent/prompts.ts
2755
+ var basePrompt2 = "You are a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.";
2756
+ var editingFilesPrompt = (toolNamePrefix) => `
2757
+ ====
2758
+
2759
+ EDITING FILES
2760
+
2761
+ You have access to two tools for working with files: **${toolNamePrefix}write_to_file** and **${toolNamePrefix}replace_in_file**. Understanding their roles and selecting the right one for the job will help ensure efficient and accurate modifications.
2762
+
2763
+ # ${toolNamePrefix}write_to_file
2764
+
2765
+ ## Purpose
2766
+
2767
+ - Create a new file, or overwrite the entire contents of an existing file.
2768
+
2769
+ ## When to Use
2770
+
2771
+ - Initial file creation, such as when scaffolding a new project.
2772
+ - Overwriting large boilerplate files where you want to replace the entire content at once.
2773
+ - When the complexity or number of changes would make ${toolNamePrefix}replace_in_file unwieldy or error-prone.
2774
+ - When you need to completely restructure a file's content or change its fundamental organization.
2775
+
2776
+ ## Important Considerations
2777
+
2778
+ - Using ${toolNamePrefix}write_to_file requires providing the file\u2019s complete final content.
2779
+ - 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.
2780
+ - While ${toolNamePrefix}write_to_file should not be your default choice, don't hesitate to use it when the situation truly calls for it.
2781
+
2782
+ # ${toolNamePrefix}replace_in_file
2783
+
2784
+ ## Purpose
2785
+
2786
+ - Make targeted edits to specific parts of an existing file without overwriting the entire file.
2787
+
2788
+ ## When to Use
2789
+
2790
+ - Small, localized changes like updating a few lines, function implementations, changing variable names, modifying a section of text, etc.
2791
+ - Targeted improvements where only specific portions of the file\u2019s content needs to be altered.
2792
+ - Especially useful for long files where much of the file will remain unchanged.
2793
+
2794
+ ## Advantages
2795
+
2796
+ - More efficient for minor edits, since you don\u2019t need to supply the entire file content.
2797
+ - Reduces the chance of errors that can occur when overwriting large files.
2798
+
2799
+ # Choosing the Appropriate Tool
2800
+
2801
+ - **Default to ${toolNamePrefix}replace_in_file** for most changes. It's the safer, more precise option that minimizes potential issues.
2802
+ - **Use ${toolNamePrefix}write_to_file** when:
2803
+ - Creating new files
2804
+ - The changes are so extensive that using ${toolNamePrefix}replace_in_file would be more complex or risky
2805
+ - You need to completely reorganize or restructure a file
2806
+ - The file is relatively small and the changes affect most of its content
2807
+ - You're generating boilerplate or template files
2808
+
2809
+ # Workflow Tips
2810
+
2811
+ 1. Before editing, assess the scope of your changes and decide which tool to use.
2812
+ 2. For targeted edits, apply ${toolNamePrefix}replace_in_file with carefully crafted SEARCH/REPLACE blocks. If you need multiple changes, you can stack multiple SEARCH/REPLACE blocks within a single ${toolNamePrefix}replace_in_file call.
2813
+ 3. For major overhauls or initial file creation, rely on ${toolNamePrefix}write_to_file.
2814
+ 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 SEARCH/REPLACE operations, since it reflects any auto-formatting or user-applied changes.
2815
+
2816
+ By thoughtfully selecting between ${toolNamePrefix}write_to_file and ${toolNamePrefix}replace_in_file, you can make your file editing process smoother, safer, and more efficient.`;
2817
+ var rules = (toolNamePrefix) => `
2818
+ ====
2819
+
2820
+ RULES
2821
+
2822
+ - You may use \`cd\` to enter any child directory within the current working directory. For example, \`cd myChildDir\`. But you may never move to a parent directory or any directory outside your current path. For example, do not use \`cd ..\`, \`cd /\`, or any absolute path.
2823
+ - Always work with relative path names, and never use absolute paths.
2824
+ - When generating code or test or any file that support comments, add a comment on top of the file with a description of the file's purpose and a note that this file is generated by "polka.codes".
2825
+ - When generate text file such as README.md, add a footer indicating this file is generated by "polka.codes".
2826
+ - Before using the ${toolNamePrefix}execute_command tool, you must first think about the SYSTEM INFORMATION context provided to understand the user's environment and tailor your commands to ensure they are compatible with their system. You must also consider if the command you need to run should be executed in a specific directory outside of the current working directory, and if so prepend with \`cd\`'ing into that directory && then executing the command (as one command). For example, if you needed to run \`npm install\` in a project that's not in the current working directory, you would need to prepend with a \`cd\` i.e. pseudocode for this would be \`cd (path to project) && (command, in this case npm install)\`. However, you can only cd into child directory, but never parent directory or root directory or home directory.
2827
+ - When using the ${toolNamePrefix}search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the user's task you may use it to find code patterns, TODO comments, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the ${toolNamePrefix}search_files tool in combination with other tools for more comprehensive analysis. For example, use it to find specific code patterns, then use ${toolNamePrefix}read_file to examine the full context of interesting matches before using ${toolNamePrefix}replace_in_file to make informed changes.
2828
+ - When creating a new project (such as an app, website, or any software project), organize all new files within a dedicated project directory unless the user specifies otherwise. Use appropriate file paths when creating files, as the ${toolNamePrefix}write_to_file tool will automatically create any necessary directories. Structure the project logically, adhering to best practices for the specific type of project being created. Unless otherwise specified, new projects should be easily run without additional setup, for example most projects can be built in HTML, CSS, and JavaScript - which you can open in a browser.
2829
+ - Be sure to consider the type of project (e.g. Python, JavaScript, web application) when determining the appropriate structure and files to include. Also consider what files may be most relevant to accomplishing the task, for example looking at a project's manifest file would help you understand the project's dependencies, which you could incorporate into any code you write.
2830
+ - When making changes to code, always consider the context in which the code is being used. Ensure that your changes are compatible with the existing codebase and that they follow the project's coding standards and best practices.
2831
+ - **Adhere to any established coding style, linting rules, or naming conventions if they are known or can be inferred from the existing codebase, to maintain consistency.**
2832
+ - When you want to modify a file, use the ${toolNamePrefix}replace_in_file or ${toolNamePrefix}write_to_file tool directly with the desired changes. You do not need to display the changes before using the tool.
2833
+ - **Do not guess or hallucinate file content that has not been explicitly provided or read. Always read an existing file with \`${toolNamePrefix}read_file\` (or rely on content the user directly provided) before modifying it, unless you are creating a brand-new file.**
2834
+ - Do not ask for more information than necessary. Use the tools provided to accomplish the user's request efficiently and effectively. When you've completed your task, you must use the ${toolNamePrefix}attempt_completion tool to present the result to the user.
2835
+ - The user may provide a file's contents directly in their message, in which case you shouldn't use the ${toolNamePrefix}read_file tool to get the file contents again since you already have it.
2836
+ - Your goal is to try to accomplish the user's task, NOT engage in a back and forth conversation.
2837
+ - NEVER end ${toolNamePrefix}attempt_completion result with a question or request to engage in further conversation! Formulate the end of your result in a way that is final and does not require further input from the user.
2838
+ - You are STRICTLY FORBIDDEN from starting your messages with "Great", "Certainly", "Okay", "Sure". You should NOT be conversational in your responses, but rather direct and to the point. For example you should NOT say "Great, I've updated the CSS" but instead something like "I've updated the CSS". It is important you be clear and technical in your messages.
2839
+ - When presented with images, utilize your vision capabilities to thoroughly examine them and extract meaningful information. Incorporate these insights into your thought process as you accomplish the user's task.
2840
+ - When using the ${toolNamePrefix}replace_in_file tool, you must include complete lines in your SEARCH blocks, not partial lines. The system requires exact line matches and cannot match partial lines. For example, if you want to match a line containing "const x = 5;", your SEARCH block must include the entire line, not just "x = 5" or other fragments.
2841
+ - When using the ${toolNamePrefix}replace_in_file tool, if you use multiple SEARCH/REPLACE blocks, list them in the order they appear in the file. For example if you need to make changes to both line 10 and line 50, first include the SEARCH/REPLACE block for line 10, followed by the SEARCH/REPLACE block for line 50.
2842
+ - It is critical you wait for the user's response after each tool use, in order to confirm the success of the tool use. For example, if asked to make a todo app, you would create a file, wait for the user's response it was created successfully, then create another file if needed, wait for the user's response it was created successfully, etc.
2843
+ - Keep the inline docs up to date if needed.
2844
+ `;
2845
+ var objectives = (toolNamePrefix) => `
2846
+ ====
2847
+
2848
+ OBJECTIVE
2849
+
2850
+ You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
2851
+
2852
+ 1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
2853
+ 2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process. You will be informed on the work completed and what's remaining as you go.
2854
+ 3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within <thinking></thinking> tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use.
2855
+ 4. Once you've completed the user's task, you must use the ${toolNamePrefix}attempt_completion tool to present the result of the task to the user.
2856
+ 5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance.`;
2857
+ var fullSystemPrompt4 = (info, tools, toolNamePrefix, instructions, scripts) => `
2858
+ ${basePrompt2}
2859
+ ${toolUsePrompt(tools, toolNamePrefix)}
2860
+ ${editingFilesPrompt(toolNamePrefix)}
2861
+ ${capabilities(toolNamePrefix)}
2862
+ ${rules(toolNamePrefix)}
2863
+ ${objectives(toolNamePrefix)}
2864
+ ${systemInformation(info)}
2865
+ ${customInstructions(instructions)}
2866
+ ${customScripts(scripts)}
2867
+ `;
2868
+
2869
+ // src/Agent/CoderAgent/index.ts
2870
+ var CoderAgent = class extends AgentBase {
2871
+ constructor(options) {
2872
+ const combinedTools = [...options.additionalTools ?? [], ...Object.values(allTools_exports)];
2873
+ const tools = getAvailableTools({
2874
+ provider: options.provider,
2875
+ allTools: combinedTools,
2876
+ hasAgent: (options.agents?.length ?? 0) > 0,
2877
+ permissionLevel: 3 /* Arbitrary */,
2878
+ interactive: true
2879
+ });
2880
+ const toolNamePrefix = "tool_";
2881
+ const systemPrompt = fullSystemPrompt4(
2882
+ {
2883
+ os: options.os
2884
+ },
2885
+ tools,
2886
+ toolNamePrefix,
2887
+ options.customInstructions ?? [],
2888
+ options.scripts ?? {}
2889
+ );
2890
+ super(coderAgentInfo.name, options.ai, {
2891
+ systemPrompt,
2892
+ tools,
2893
+ toolNamePrefix,
2894
+ provider: options.provider,
2895
+ interactive: options.interactive,
2896
+ agents: options.agents,
2897
+ scripts: options.scripts,
2898
+ callback: options.callback
2899
+ });
2900
+ }
2901
+ async onBeforeInvokeTool(name, args) {
2902
+ if (name !== attemptCompletion_default.name) {
2903
+ return;
2904
+ }
2905
+ const executeCommand = this.config.provider.executeCommand;
2906
+ if (!executeCommand) {
2907
+ return;
2908
+ }
2909
+ const format = this.config.scripts?.format;
2910
+ const formatCommand = typeof format === "string" ? format : format?.command;
2911
+ if (formatCommand) {
2912
+ try {
2913
+ await executeCommand(formatCommand, false);
2914
+ } catch (error) {
2915
+ console.warn(`Failed to format code using command: ${formatCommand}`, error);
2916
+ }
2917
+ }
2918
+ const check = this.config.scripts?.check;
2919
+ const checkCommand = typeof check === "string" ? check : check?.command;
2920
+ if (checkCommand) {
2921
+ try {
2922
+ const { exitCode, stdout, stderr } = await executeCommand(checkCommand, false);
2923
+ if (exitCode !== 0) {
2924
+ return {
2925
+ type: "Reply" /* Reply */,
2926
+ message: responsePrompts.commandResult(checkCommand, exitCode, stdout, stderr)
2927
+ };
2928
+ }
2929
+ } catch (error) {
2930
+ console.warn(`Failed to check code using command: ${checkCommand}`, error);
2931
+ }
2932
+ }
2933
+ const test = this.config.scripts?.test;
2934
+ const testCommand = typeof test === "string" ? test : test?.command;
2935
+ if (testCommand) {
2936
+ try {
2937
+ const { exitCode, stdout, stderr } = await executeCommand(testCommand, false);
2938
+ if (exitCode !== 0) {
2939
+ return {
2940
+ type: "Reply" /* Reply */,
2941
+ message: responsePrompts.commandResult(testCommand, exitCode, stdout, stderr)
2942
+ };
2943
+ }
2944
+ } catch (error) {
2945
+ console.warn(`Failed to test code using command: ${testCommand}`, error);
2946
+ }
2947
+ }
2948
+ }
2949
+ };
2950
+ var coderAgentInfo = {
2951
+ name: "coder",
2952
+ responsibilities: [
2953
+ "Editing and refactoring existing code.",
2954
+ "Creating new features or modules.",
2955
+ "Running tests and analyzing test results.",
2956
+ "Maintaining coding standards, lint rules, and general code quality."
2957
+ ]
2958
+ };
2959
+
2960
+ // src/Agent/MultiAgent.ts
2961
+ var MultiAgent = class {
2962
+ #config;
2963
+ #agents = [];
2964
+ constructor(config) {
2965
+ this.#config = config;
2966
+ }
2967
+ async #handleTaskResult(exitReason) {
2968
+ switch (exitReason.type) {
2969
+ case "HandOver" /* HandOver */: {
2970
+ this.#agents.pop();
2971
+ const newContext = await this.#config.getContext?.(exitReason.agentName, exitReason.context, exitReason.files);
2972
+ return await this.#startTask(exitReason.agentName, exitReason.task, newContext);
2973
+ }
2974
+ case "Delegate" /* Delegate */: {
2975
+ const newContext = await this.#config.getContext?.(exitReason.agentName, exitReason.context, exitReason.files);
2976
+ const delegateResult = await this.#startTask(exitReason.agentName, exitReason.task, newContext);
2977
+ switch (delegateResult.type) {
2978
+ case "HandOver" /* HandOver */:
2979
+ case "Delegate" /* Delegate */:
2980
+ console.warn("Unexpected exit reason", delegateResult);
2981
+ break;
2982
+ case "Interrupted" /* Interrupted */:
2983
+ return delegateResult;
2984
+ case "Exit" /* Exit */:
2985
+ return this.continueTask(delegateResult.message);
2986
+ }
2987
+ return delegateResult;
2988
+ }
2989
+ case "Interrupted" /* Interrupted */:
2990
+ case "Exit" /* Exit */:
2991
+ this.#agents.pop();
2992
+ return exitReason;
2993
+ default:
2994
+ return exitReason;
2995
+ }
2996
+ }
2997
+ async #startTask(agentName, task, context) {
2998
+ const newAgent = await this.#config.createAgent(agentName);
2999
+ this.#agents.push(newAgent);
3000
+ const exitReason = await newAgent.startTask({
3001
+ task,
3002
+ context
3003
+ });
3004
+ return await this.#handleTaskResult(exitReason);
3005
+ }
3006
+ async startTask(options) {
3007
+ if (this.#agents.length > 0) {
3008
+ throw new Error("An active agent already exists");
3009
+ }
3010
+ return this.#startTask(options.agentName, options.task, options.context);
3011
+ }
3012
+ async continueTask(userMessage) {
3013
+ if (!this.#agents.length) {
3014
+ throw new Error("No active agent");
3015
+ }
3016
+ const exitReason = await this.#agents[this.#agents.length - 1].continueTask(userMessage);
3017
+ return await this.#handleTaskResult(exitReason);
3018
+ }
3019
+ get hasActiveAgent() {
3020
+ return this.#agents.length > 0;
3021
+ }
3022
+ };
3023
+
3024
+ // src/Agent/index.ts
3025
+ var allAgents = [architectAgentInfo, coderAgentInfo, analyzerAgentInfo, codeFixerAgentInfo];
3026
+
3027
+ // src/AiTool/createNewProject.ts
3028
+ var prompt = `You are an AiTool designed to assist users in creating new projects. Follow these guidelines:
3029
+
3030
+ 1. **Gather Information:**
3031
+ - Begin by asking the user for essential project details, including:
3032
+ - Project type (e.g., web, mobile, desktop, etc.)
3033
+ - Desired programming languages
3034
+ - Preferred frameworks or libraries
3035
+ - Build tools and package manager preferences
3036
+ - Testing frameworks and patterns
3037
+ - Code style and linting preferences
3038
+ - Any additional specifications or requirements
3039
+
3040
+ 2. **Clarification & Confirmation:**
3041
+ - Do not make any decisions or assumptions on behalf of the user.
3042
+ - Ask clarifying questions if any detail is ambiguous.
3043
+ - Confirm each piece of information with the user before proceeding to the next step.
3044
+
3045
+ 3. **Avoid Redundancy:**
3046
+ - Do not repeat questions or details that have already been confirmed.
3047
+ - Keep interactions concise and focused on gathering complete and accurate details.
3048
+
3049
+ 4. **Generate Configuration:**
3050
+ - Based on the collected information, generate a .polkacodes.yml configuration file that includes:
3051
+ - scripts section with common development commands (test, format, check, etc.)
3052
+ - rules section reflecting project conventions and tools
3053
+ - excludeFiles section for sensitive files only
3054
+ - Example structure:
3055
+ \`\`\`yaml
3056
+ scripts:
3057
+ test:
3058
+ command: "[test-command]"
3059
+ description: "Run tests"
3060
+ format:
3061
+ command: "[format-command]"
3062
+ description: "Format code"
3063
+ check:
3064
+ command: "[check-command]"
3065
+ description: "Check code"
3066
+
3067
+ rules:
3068
+ - "[package-manager-rule]"
3069
+ - "[testing-framework-rule]"
3070
+ - "[code-style-rule]"
3071
+ - "[other-rule]"
3072
+
3073
+ excludeFiles:
3074
+ - ".env"
3075
+ - ".env.*"
3076
+ \`\`\`
3077
+
3078
+ 5. **Generate Essential Project Files:**
3079
+ - Create a .gitattributes file with appropriate configurations:
3080
+ - Mark lock files as generated and exclude them from diffs
3081
+ - Example for different package managers:
3082
+
3083
+ # For Bun
3084
+ bun.lock linguist-generated=true
3085
+ bun.lock -diff
3086
+
3087
+ # For npm
3088
+ package-lock.json linguist-generated=true
3089
+ package-lock.json -diff
3090
+
3091
+ # For Yarn
3092
+ yarn.lock linguist-generated=true
3093
+ yarn.lock -diff
3094
+
3095
+ # For pnpm
3096
+ pnpm-lock.yaml linguist-generated=true
3097
+ pnpm-lock.yaml -diff
3098
+
3099
+ - Include other common configurations as needed based on project type
3100
+
3101
+ 6. **Handover to Coder Agent:**
3102
+ - Once all required information is collected and validated by the user, compile:
3103
+ 1. The final project specifications
3104
+ 2. The .polkacodes.yml configuration content
3105
+ - Clearly hand over these details to the coder agent, instructing them to:
3106
+ 1. Create the new project based on the confirmed specifications
3107
+ 2. Include the .polkacodes.yml file in the project root
3108
+ 3. Include the .gitattributes file with appropriate configurations
3109
+ 4. Ensure all specified tools and configurations are properly set up`;
3110
+ var createNewProject_default = {
3111
+ name: "createNewProject",
3112
+ description: "Creates a new project",
3113
+ prompt,
3114
+ formatInput: (params) => {
3115
+ return `<project_name>${params}</project_name>`;
3116
+ },
3117
+ parseOutput: (output) => {
3118
+ return output.trim();
3119
+ },
3120
+ agent: "architect"
3121
+ };
3122
+
3123
+ // src/AiTool/generateGitCommitMessage.ts
3124
+ var prompt2 = `
3125
+ You are an advanced assistant specialized in creating concise and accurate Git commit messages. When you receive:
3126
+ - A Git diff inside the <tool_input> tag.
3127
+ - Additional user-supplied context inside the <tool_input_context> tag (if any).
3128
+
3129
+ You will produce a single commit message enclosed within <tool_output> tags. The commit message must accurately reflect the changes shown in the diff and should be clear, descriptive, and devoid of unnecessary or repeated information. If a context is provided, it MUST be incorporated into the commit message.
3130
+
3131
+ Here\u2019s an example of the input and the expected output format:
3132
+
3133
+ <tool_input>
3134
+ --- a/example_file.py
3135
+ +++ b/example_file.py
3136
+ @@ -10,7 +10,7 @@ def example_function():
3137
+ - print("Old behavior")
3138
+ + print("New behavior")
3139
+ </tool_input>
3140
+ <tool_input_context>
3141
+ Changing print statement to update the user-facing message.
3142
+ </tool_input_context>
3143
+
3144
+ Example Output:
3145
+
3146
+ <tool_output>
3147
+ Update print statement for revised user-facing message
3148
+ </tool_output>
3149
+
3150
+ Follow the same structure for any new input. Never repeat questions; focus on generating a concise commit message that captures the essence of the changes.
3151
+ `;
3152
+ var generateGitCommitMessage_default = {
3153
+ name: "generateGitCommitMessage",
3154
+ description: "Generates git commit messages from git diff output",
3155
+ prompt: prompt2,
3156
+ formatInput: (params) => {
3157
+ let ret = `<tool_input>
3158
+ ${params.diff}
3159
+ </tool_input>`;
3160
+ if (params.context) {
3161
+ ret += `
3162
+ <tool_input_context>
3163
+ ${params.context}
3164
+ </tool_input_context>`;
3165
+ }
3166
+ return ret;
3167
+ },
3168
+ parseOutput: (output) => {
3169
+ const regex = /<tool_output>([\s\S]*)<\/tool_output>/gm;
3170
+ const match = regex.exec(output);
3171
+ if (match) {
3172
+ return match[1];
3173
+ }
3174
+ throw new Error(`Could not parse output:
3175
+ ${output}`);
3176
+ }
3177
+ };
3178
+
3179
+ // src/AiTool/generateGithubPullRequestDetails.ts
3180
+ var prompt3 = `
3181
+ # Generate Github Pull Request Details
3182
+
3183
+ You are given:
3184
+ - A branch name in <tool_input_branch_name>.
3185
+ - An optional context message in <tool_input_context> (which may or may not be present).
3186
+ - All commit messages combined in <tool_input_commit_messages>.
3187
+ - All diffs combined in <tool_input_commit_diff>.
3188
+
3189
+ Your task:
3190
+ 1. Consider the optional context (if provided).
3191
+ - If an issue number is found, add "Closes #xxx" at the beginning of the PR description
3192
+ - IMPORTANT: Use ONLY the exact format "Closes #xxx" at the beginning of the description
3193
+ - DO NOT use variations like "Closes issue #xxx" or other formats
3194
+ 2. Analyze the combined commit messages and diffs.
3195
+ 3. Produce a single GitHub Pull Request title.
3196
+ 4. Produce a Pull Request description that explains the changes.
3197
+
3198
+ Use the following template for the Pull Request description:
3199
+
3200
+ ---
3201
+ **Context (if provided)**:
3202
+ - Acknowledge any guiding concerns or instructions.
3203
+
3204
+ **Summary of Changes**:
3205
+ - Provide a concise list or overview of what changed.
3206
+
3207
+ **Highlights of Changed Code**:
3208
+ - Mention only the specific sections or functionalities updated, without showing full surrounding context.
3209
+
3210
+ **Additional Information (if needed)**:
3211
+ - Testing steps (if applicable).
3212
+ - Any notes or caveats.
3213
+
3214
+ ---
3215
+
3216
+ Output format:
3217
+ <tool_output>
3218
+ <tool_output_pr_title>YOUR PR TITLE HERE</tool_output_pr_title>
3219
+ <tool_output_pr_description>
3220
+ YOUR PR DESCRIPTION HERE
3221
+ </tool_output_pr_description>
3222
+ </tool_output>
3223
+
3224
+ Below is an **example** of the input and output:
3225
+
3226
+ Example Input:
3227
+ <tool_input>
3228
+ <tool_input_branch_name>feature/refactor-logging</tool_input_branch_name>
3229
+ <tool_input_context>Implementing changes for issue #123 - Focus on clean code and maintainability</tool_input_context>
3230
+ <tool_input_commit_messages>
3231
+ Remove debug logs
3232
+ Refactor order validation logic
3233
+ </tool_input_commit_messages>
3234
+ <tool_input_commit_diff>
3235
+ diff --git a/user_service.py b/user_service.py
3236
+ - print("Debug info")
3237
+ + # Removed debug print statements
3238
+
3239
+ diff --git a/order_service.py b/order_service.py
3240
+ - if is_valid_order(order):
3241
+ - process_order(order)
3242
+ + validate_and_process(order)
3243
+ </tool_input_commit_diff>
3244
+ </tool_input>
3245
+
3246
+ Example Output:
3247
+ <tool_output>
3248
+ <tool_output_pr_title>Refactor Order Validation and Remove Debug Logs</tool_output_pr_title>
3249
+ <tool_output_pr_description>
3250
+ closes #123
3251
+
3252
+ This PR removes unnecessary debug print statements and updates order validation
3253
+ to use the new validate_and_process method for improved maintainability.
3254
+ </tool_output_pr_description>
3255
+ </tool_output>
3256
+
3257
+ ---
3258
+
3259
+ Use the above format whenever you receive <tool_input> that may include a branch name, an optional context, aggregated commit messages in a single tag, and a combined diff in a single tag. Provide your final output strictly in <tool_output> with <tool_output_pr_title> and <tool_output_pr_description>. Only highlight the changed code and avoid including the context around the changes in the description.
3260
+ `;
3261
+ var generateGithubPullRequestDetails_default = {
3262
+ name: "generateGithubPullRequestDetails",
3263
+ description: "Generates a GitHub pull request title and description from git commits",
3264
+ prompt: prompt3,
3265
+ formatInput: (params) => {
3266
+ return `<tool_input>
3267
+ <tool_input_branch_name>${params.branchName}</tool_input_branch_name>${params.context ? `
3268
+ <tool_input_context>${params.context}</tool_input_context>` : ""}
3269
+ <tool_input_commit_messages>${params.commitMessages}</tool_input_commit_messages>
3270
+ <tool_input_commit_diff>${params.commitDiff}</tool_input_commit_diff>
3271
+ </tool_input>`;
3272
+ },
3273
+ parseOutput: (output) => {
3274
+ const regex = /<tool_output>([\s\S]*)<\/tool_output>/gm;
3275
+ const match = regex.exec(output);
3276
+ if (!match) {
3277
+ throw new Error(`Could not parse output:
3278
+ ${output}`);
3279
+ }
3280
+ const [, outputContent] = match;
3281
+ const titleRegex = /<tool_output_pr_title>([\s\S]*)<\/tool_output_pr_title>/gm;
3282
+ const titleMatch = titleRegex.exec(outputContent);
3283
+ const descriptionRegex = /<tool_output_pr_description>([\s\S]*)<\/tool_output_pr_description>/gm;
3284
+ const descriptionMatch = descriptionRegex.exec(outputContent);
3285
+ if (titleMatch && descriptionMatch) {
3286
+ return {
3287
+ title: titleMatch[1],
3288
+ description: descriptionMatch[1]
3289
+ };
3290
+ }
3291
+ throw new Error(`Could not parse output:
3292
+ ${output}`);
3293
+ }
3294
+ };
3295
+
3296
+ // src/AiTool/generateProjectConfig.ts
3297
+ var prompt4 = `You are an analyzer agent responsible for examining project files and generating appropriate polkacodes configuration. Your task is to:
3298
+
3299
+ 1. Read and analyze the provided files using tool_read_file to understand:
3300
+ - Build tools and package manager (e.g., bun, npm)
3301
+ - Testing frameworks and patterns
3302
+ - Code style tools and rules
3303
+ - Project structure and conventions
3304
+ - Common development workflows
3305
+
3306
+ 2. Generate a YAML configuration that captures:
3307
+ - scripts section based on package.json scripts and CI workflows. If applicable, generate following scripts:
3308
+ - format: Format the code using a code formatter tool
3309
+ - check: Check the code for errors using a linter tool
3310
+ - test: Run tests using a test runner tool
3311
+ - include other relevant scripts based on project conventions, tools, and patterns
3312
+ - rules section based on project conventions, tools, and patterns
3313
+ - excludeFiles section for sensitive files
3314
+
3315
+ 3. Use tool_attempt_completion to return the final configuration in this format:
3316
+
3317
+ <tool_attempt_completion>
3318
+ <tool_parameter_result>
3319
+ scripts:
3320
+ test:
3321
+ command: "bun test"
3322
+ description: "Run tests with bun:test"
3323
+ lint:
3324
+ command: "biome check ."
3325
+ description: "Check code style with Biome"
3326
+
3327
+ rules:
3328
+ - "Use \`bun\` as package manager"
3329
+ - "Write tests using bun:test with snapshots"
3330
+ - "Follow Biome code style"
3331
+
3332
+ excludeFiles:
3333
+ # Sensitive files
3334
+ - ".env"
3335
+ - ".env.*"
3336
+ - ".npmrc"
3337
+ </tool_parameter_result>
3338
+ </tool_attempt_completion>
3339
+
3340
+ Focus on:
3341
+ - Package manager and dependency management
3342
+ - Testing frameworks and patterns
3343
+ - Code style and linting rules
3344
+ - File organization and naming conventions
3345
+ - Build and development workflows
3346
+ - Sensitive files that should not be committed:
3347
+ - Environment files (.env*)
3348
+ - Configuration files with potential secrets
3349
+ - Generated files to exclude:
3350
+ - Lock files from package managers
3351
+ - Build artifacts and outputs
3352
+ - Generated file that are not ignored by .gitignore
3353
+
3354
+ The configuration should accurately reflect the project's structure, tools, and conventions.
3355
+ `;
3356
+ var generateProjectConfig_default = {
3357
+ name: "generateProjectConfig",
3358
+ description: "Analyzes project files to generate polkacodes config sections",
3359
+ prompt: prompt4,
3360
+ formatInput: () => {
3361
+ return "";
3362
+ },
3363
+ parseOutput: (output) => {
3364
+ return output;
3365
+ },
3366
+ agent: "analyzer"
3367
+ };
3368
+
3369
+ // src/AiTool/index.ts
3370
+ var executeTool = async (definition, ai, params) => {
3371
+ const { response, usage } = await ai.request(definition.prompt, [
3372
+ { role: "user", content: definition.formatInput(params) }
3373
+ ]);
3374
+ return {
3375
+ response: definition.parseOutput(response),
3376
+ usage
3377
+ };
3378
+ };
3379
+ var executeAgentTool = async (definition, agent, params) => {
3380
+ if (!definition.agent) {
3381
+ throw new Error("Agent not specified");
3382
+ }
3383
+ const exitReason = await agent.startTask({
3384
+ agentName: definition.agent,
3385
+ task: definition.prompt,
3386
+ context: definition.formatInput(params)
3387
+ });
3388
+ if (exitReason.type === "Exit" /* Exit */) {
3389
+ return definition.parseOutput(exitReason.message);
3390
+ }
3391
+ throw new Error(`Tool execution failed: ${exitReason.type}`);
3392
+ };
3393
+ var makeTool = (definition) => {
3394
+ return async (ai, params) => {
3395
+ return executeTool(definition, ai, params);
3396
+ };
3397
+ };
3398
+ var makeAgentTool = (definition) => {
3399
+ return async (agent, params) => {
3400
+ return executeAgentTool(definition, agent, params);
3401
+ };
3402
+ };
3403
+ var generateGitCommitMessage = makeTool(generateGitCommitMessage_default);
3404
+ var generateGithubPullRequestDetails = makeTool(generateGithubPullRequestDetails_default);
3405
+ var generateProjectConfig = makeAgentTool(generateProjectConfig_default);
3406
+ var createNewProject = makeAgentTool(createNewProject_default);
3407
+ // Annotate the CommonJS export names for ESM import in node:
3408
+ 0 && (module.exports = {
3409
+ AgentBase,
3410
+ AiServiceProvider,
3411
+ AnalyzerAgent,
3412
+ ArchitectAgent,
3413
+ CodeFixerAgent,
3414
+ CoderAgent,
3415
+ MockProvider,
3416
+ MultiAgent,
3417
+ PermissionLevel,
3418
+ TaskEventKind,
3419
+ ToolResponseType,
3420
+ UsageMeter,
3421
+ allAgents,
3422
+ allTools,
3423
+ analyzerAgentInfo,
3424
+ anthropicDefaultModelId,
3425
+ anthropicModels,
3426
+ architectAgentInfo,
3427
+ askFollowupQuestion,
3428
+ attemptCompletion,
3429
+ codeFixerAgentInfo,
3430
+ coderAgentInfo,
3431
+ createNewProject,
3432
+ createService,
3433
+ deepSeekDefaultModelId,
3434
+ deepSeekModels,
3435
+ defaultModels,
3436
+ delegate,
3437
+ executeAgentTool,
3438
+ executeCommand,
3439
+ executeTool,
3440
+ generateGitCommitMessage,
3441
+ generateGithubPullRequestDetails,
3442
+ generateProjectConfig,
3443
+ getAvailableTools,
3444
+ handOver,
3445
+ listCodeDefinitionNames,
3446
+ listFiles,
3447
+ makeAgentTool,
3448
+ makeTool,
3449
+ modelInfos,
3450
+ openAiModelInfoSaneDefaults,
3451
+ readFile,
3452
+ removeFile,
3453
+ renameFile,
3454
+ replaceInFile,
3455
+ searchFiles,
3456
+ writeToFile
3457
+ });