@polka-codes/core 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_tsup-dts-rollup.d.ts +259 -254
- package/dist/index.d.ts +36 -36
- package/dist/index.js +463 -455
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -4,176 +4,6 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// src/UsageMeter.ts
|
|
8
|
-
var UsageMeter = class {
|
|
9
|
-
#totals = { input: 0, output: 0, cachedRead: 0, cost: 0 };
|
|
10
|
-
#calls = 0;
|
|
11
|
-
#modelInfos;
|
|
12
|
-
#maxMessages;
|
|
13
|
-
#maxCost;
|
|
14
|
-
constructor(modelInfos = {}, opts = {}) {
|
|
15
|
-
const infos = {};
|
|
16
|
-
for (const [provider, providerInfo] of Object.entries(modelInfos)) {
|
|
17
|
-
for (const [model, modelInfo] of Object.entries(providerInfo)) {
|
|
18
|
-
infos[`${provider.split("-")[0]}:${model.replace(/[\.-]/g, "")}`] = {
|
|
19
|
-
inputPrice: modelInfo.inputPrice ?? 0,
|
|
20
|
-
outputPrice: modelInfo.outputPrice ?? 0,
|
|
21
|
-
cacheWritesPrice: modelInfo.cacheWritesPrice ?? 0,
|
|
22
|
-
cacheReadsPrice: modelInfo.cacheReadsPrice ?? 0
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
this.#modelInfos = infos;
|
|
27
|
-
this.#maxMessages = opts.maxMessages ?? 1e3;
|
|
28
|
-
this.#maxCost = opts.maxCost ?? 100;
|
|
29
|
-
}
|
|
30
|
-
#calculageUsage(usage, providerMetadata, modelInfo) {
|
|
31
|
-
const providerMetadataKey = Object.keys(providerMetadata ?? {})[0];
|
|
32
|
-
const metadata = providerMetadata?.[providerMetadataKey] ?? {};
|
|
33
|
-
switch (providerMetadataKey) {
|
|
34
|
-
case "openrouter":
|
|
35
|
-
return {
|
|
36
|
-
input: usage.inputTokens ?? 0,
|
|
37
|
-
output: usage.outputTokens ?? 0,
|
|
38
|
-
cachedRead: usage.cachedInputTokens ?? 0,
|
|
39
|
-
cost: metadata.usage?.cost ?? 0
|
|
40
|
-
};
|
|
41
|
-
case "anthropic": {
|
|
42
|
-
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
43
|
-
const cacheWrite = metadata?.promptCacheMissTokens ?? 0;
|
|
44
|
-
const input = usage.inputTokens ?? 0;
|
|
45
|
-
const output = usage.outputTokens ?? 0;
|
|
46
|
-
return {
|
|
47
|
-
input: input + cacheWrite + cachedRead,
|
|
48
|
-
output,
|
|
49
|
-
cachedRead,
|
|
50
|
-
cost: (input * modelInfo.inputPrice + output * modelInfo.outputPrice + cacheWrite * modelInfo.cacheWritesPrice + cachedRead * modelInfo.cacheReadsPrice) / 1e6
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
case "deepseek": {
|
|
54
|
-
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
55
|
-
const cacheWrite = metadata.promptCacheMissTokens ?? 0;
|
|
56
|
-
const input = usage.inputTokens ?? 0;
|
|
57
|
-
const output = usage.outputTokens ?? 0;
|
|
58
|
-
return {
|
|
59
|
-
input,
|
|
60
|
-
output,
|
|
61
|
-
cachedRead,
|
|
62
|
-
cost: (output * modelInfo.outputPrice + cacheWrite * modelInfo.inputPrice + cachedRead * modelInfo.cacheReadsPrice) / 1e6
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
default: {
|
|
66
|
-
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
67
|
-
const input = usage.inputTokens ?? 0;
|
|
68
|
-
const output = usage.outputTokens ?? 0;
|
|
69
|
-
return {
|
|
70
|
-
input,
|
|
71
|
-
output,
|
|
72
|
-
cachedRead,
|
|
73
|
-
cost: (input * modelInfo.inputPrice + output * modelInfo.outputPrice) / 1e6
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
addUsage(llm, resp, options = {}) {
|
|
79
|
-
const modelInfo = options.modelInfo ?? // make google.vertex.chat to google
|
|
80
|
-
// and anthropic.messages to anthropic
|
|
81
|
-
this.#modelInfos[`${llm.provider.split(".")[0]}:${llm.modelId.replace(/[\.-]/g, "")}`] ?? {
|
|
82
|
-
inputPrice: 0,
|
|
83
|
-
outputPrice: 0,
|
|
84
|
-
cacheWritesPrice: 0,
|
|
85
|
-
cacheReadsPrice: 0
|
|
86
|
-
};
|
|
87
|
-
const usage = "totalUsage" in resp ? resp.totalUsage : resp.usage;
|
|
88
|
-
const result = this.#calculageUsage(usage, resp.providerMetadata, modelInfo);
|
|
89
|
-
this.#totals.input += result.input;
|
|
90
|
-
this.#totals.output += result.output;
|
|
91
|
-
this.#totals.cachedRead += result.cachedRead;
|
|
92
|
-
this.#totals.cost += result.cost;
|
|
93
|
-
this.#calls++;
|
|
94
|
-
}
|
|
95
|
-
/** Override the running totals (e.g., restore from saved state). */
|
|
96
|
-
setUsage(newUsage) {
|
|
97
|
-
if (newUsage.input != null) this.#totals.input = newUsage.input;
|
|
98
|
-
if (newUsage.output != null) this.#totals.output = newUsage.output;
|
|
99
|
-
if (newUsage.cachedRead != null) this.#totals.cachedRead = newUsage.cachedRead;
|
|
100
|
-
if (newUsage.cost != null) this.#totals.cost = newUsage.cost;
|
|
101
|
-
if (newUsage.calls != null) this.#calls = newUsage.calls;
|
|
102
|
-
}
|
|
103
|
-
/** Manually bump the message count (useful if you record some calls without token info). */
|
|
104
|
-
incrementMessageCount(n = 1) {
|
|
105
|
-
this.#calls += n;
|
|
106
|
-
}
|
|
107
|
-
/** Return true once either messages or cost exceed the configured caps. */
|
|
108
|
-
isLimitExceeded() {
|
|
109
|
-
const messageCount = this.#maxMessages !== void 0 && this.#calls >= this.#maxMessages;
|
|
110
|
-
const cost = this.#maxCost !== void 0 && this.#totals.cost >= this.#maxCost;
|
|
111
|
-
return {
|
|
112
|
-
messageCount,
|
|
113
|
-
maxMessages: this.#maxMessages,
|
|
114
|
-
cost,
|
|
115
|
-
maxCost: this.#maxCost,
|
|
116
|
-
result: messageCount || cost
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
/** Same as isLimitExceeded but throws an error if a limit is hit. */
|
|
120
|
-
checkLimit() {
|
|
121
|
-
const result = this.isLimitExceeded();
|
|
122
|
-
if (result.result) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
`Usage limit exceeded. Message count: ${result.messageCount}/${result.maxMessages}, cost: ${result.cost}/${result.maxCost}`
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
/** Getter for the aggregated totals (immutable copy). */
|
|
129
|
-
get usage() {
|
|
130
|
-
return { ...this.#totals, messageCount: this.#calls };
|
|
131
|
-
}
|
|
132
|
-
/** Print a concise usage summary to console. */
|
|
133
|
-
printUsage() {
|
|
134
|
-
const u = this.usage;
|
|
135
|
-
console.log(
|
|
136
|
-
`Usage - messages: ${u.messageCount}, input: ${u.input}, cached: ${u.cachedRead}, output: ${u.output}, cost: $${u.cost.toFixed(4)}`
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
onFinishHandler(llm) {
|
|
140
|
-
return (evt) => {
|
|
141
|
-
this.addUsage(llm, evt);
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
// src/tools/provider.ts
|
|
147
|
-
var MockProvider = class {
|
|
148
|
-
async readFile(path) {
|
|
149
|
-
return "mock content";
|
|
150
|
-
}
|
|
151
|
-
async writeFile(path, content) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
async removeFile(path) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
async renameFile(sourcePath, targetPath) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
async listFiles(path, recursive, maxCount) {
|
|
161
|
-
return [["mock-file.txt"], false];
|
|
162
|
-
}
|
|
163
|
-
async searchFiles(path, regex, filePattern) {
|
|
164
|
-
return ["mock-file.txt"];
|
|
165
|
-
}
|
|
166
|
-
async executeCommand(command, needApprove) {
|
|
167
|
-
return { stdout: "mock output", stderr: "", exitCode: 0 };
|
|
168
|
-
}
|
|
169
|
-
async askFollowupQuestion(question, options) {
|
|
170
|
-
return "mock answer";
|
|
171
|
-
}
|
|
172
|
-
async attemptCompletion(result) {
|
|
173
|
-
return "mock completion";
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
7
|
// src/tools/allTools.ts
|
|
178
8
|
var allTools_exports = {};
|
|
179
9
|
__export(allTools_exports, {
|
|
@@ -358,7 +188,7 @@ var handler2 = async (provider, args) => {
|
|
|
358
188
|
message: `<user_message>${moreMessage}</user_message>`
|
|
359
189
|
};
|
|
360
190
|
};
|
|
361
|
-
var isAvailable2 = (
|
|
191
|
+
var isAvailable2 = (_provider) => {
|
|
362
192
|
return true;
|
|
363
193
|
};
|
|
364
194
|
var attemptCompletion_default = {
|
|
@@ -589,22 +419,88 @@ var fetchUrl_default = {
|
|
|
589
419
|
isAvailable: isAvailable5
|
|
590
420
|
};
|
|
591
421
|
|
|
592
|
-
// src/tools/
|
|
422
|
+
// src/tools/handOver.ts
|
|
593
423
|
import { z as z6 } from "zod";
|
|
594
424
|
var toolInfo6 = {
|
|
425
|
+
name: "hand_over",
|
|
426
|
+
description: "Hand over the current task to another agent to complete. This tool MUST NOT to be used with any other tool.",
|
|
427
|
+
parameters: z6.object({
|
|
428
|
+
agentName: z6.string().describe("The name of the agent to hand over the task to").meta({ usageValue: "Name of the target agent" }),
|
|
429
|
+
task: z6.string().describe("The task to be completed by the target agent").meta({ usageValue: "Task description" }),
|
|
430
|
+
context: z6.string().describe("The context information for the task").meta({ usageValue: "Context information" }),
|
|
431
|
+
files: z6.preprocess((val) => {
|
|
432
|
+
if (!val) return [];
|
|
433
|
+
const values = Array.isArray(val) ? val : [val];
|
|
434
|
+
return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
|
|
435
|
+
}, z6.array(z6.string())).optional().describe("The files relevant to the task. Comma separated paths").meta({ usageValue: "Relevant files" })
|
|
436
|
+
}),
|
|
437
|
+
examples: [
|
|
438
|
+
{
|
|
439
|
+
description: "Hand over a coding task to the coder agent",
|
|
440
|
+
parameters: [
|
|
441
|
+
{
|
|
442
|
+
name: "agentName",
|
|
443
|
+
value: "coder"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
name: "task",
|
|
447
|
+
value: "Implement the login feature"
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
name: "context",
|
|
451
|
+
value: "We need a secure login system with email and password"
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
name: "files",
|
|
455
|
+
value: "src/auth/login.ts,src/auth/types.ts"
|
|
456
|
+
}
|
|
457
|
+
]
|
|
458
|
+
}
|
|
459
|
+
],
|
|
460
|
+
permissionLevel: 0 /* None */
|
|
461
|
+
};
|
|
462
|
+
var handler6 = async (_provider, args) => {
|
|
463
|
+
const parsed = toolInfo6.parameters.safeParse(args);
|
|
464
|
+
if (!parsed.success) {
|
|
465
|
+
return {
|
|
466
|
+
type: "Invalid" /* Invalid */,
|
|
467
|
+
message: `Invalid arguments for hand_over: ${parsed.error.message}`
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
const { agentName, task, context, files } = parsed.data;
|
|
471
|
+
return {
|
|
472
|
+
type: "HandOver" /* HandOver */,
|
|
473
|
+
agentName,
|
|
474
|
+
task,
|
|
475
|
+
context,
|
|
476
|
+
files: files ?? []
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
var isAvailable6 = (_provider) => {
|
|
480
|
+
return true;
|
|
481
|
+
};
|
|
482
|
+
var handOver_default = {
|
|
483
|
+
...toolInfo6,
|
|
484
|
+
handler: handler6,
|
|
485
|
+
isAvailable: isAvailable6
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// src/tools/listFiles.ts
|
|
489
|
+
import { z as z7 } from "zod";
|
|
490
|
+
var toolInfo7 = {
|
|
595
491
|
name: "list_files",
|
|
596
492
|
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.",
|
|
597
|
-
parameters:
|
|
598
|
-
path:
|
|
599
|
-
maxCount:
|
|
600
|
-
recursive:
|
|
493
|
+
parameters: z7.object({
|
|
494
|
+
path: z7.string().describe("The path of the directory to list contents for (relative to the current working directory)").meta({ usageValue: "Directory path here" }),
|
|
495
|
+
maxCount: z7.coerce.number().optional().default(2e3).describe("The maximum number of files to list. Default to 2000").meta({ usageValue: "Maximum number of files to list (optional)" }),
|
|
496
|
+
recursive: z7.preprocess((val) => {
|
|
601
497
|
if (typeof val === "string") {
|
|
602
498
|
const lower = val.toLowerCase();
|
|
603
499
|
if (lower === "false") return false;
|
|
604
500
|
if (lower === "true") return true;
|
|
605
501
|
}
|
|
606
502
|
return val;
|
|
607
|
-
},
|
|
503
|
+
}, z7.boolean().optional().default(true)).describe("Whether to list files recursively. Use true for recursive listing, false or omit for top-level only.").meta({ usageValue: "true or false (optional)" })
|
|
608
504
|
}),
|
|
609
505
|
examples: [
|
|
610
506
|
{
|
|
@@ -623,14 +519,14 @@ var toolInfo6 = {
|
|
|
623
519
|
],
|
|
624
520
|
permissionLevel: 1 /* Read */
|
|
625
521
|
};
|
|
626
|
-
var
|
|
522
|
+
var handler7 = async (provider, args) => {
|
|
627
523
|
if (!provider.listFiles) {
|
|
628
524
|
return {
|
|
629
525
|
type: "Error" /* Error */,
|
|
630
526
|
message: "Not possible to list files. Abort."
|
|
631
527
|
};
|
|
632
528
|
}
|
|
633
|
-
const { path, maxCount, recursive } =
|
|
529
|
+
const { path, maxCount, recursive } = toolInfo7.parameters.parse(args);
|
|
634
530
|
const [files, limitReached] = await provider.listFiles(path, recursive, maxCount);
|
|
635
531
|
return {
|
|
636
532
|
type: "Reply" /* Reply */,
|
|
@@ -641,26 +537,26 @@ ${files.join("\n")}
|
|
|
641
537
|
<list_files_truncated>${limitReached}</list_files_truncated>`
|
|
642
538
|
};
|
|
643
539
|
};
|
|
644
|
-
var
|
|
540
|
+
var isAvailable7 = (provider) => {
|
|
645
541
|
return !!provider.listFiles;
|
|
646
542
|
};
|
|
647
543
|
var listFiles_default = {
|
|
648
|
-
...
|
|
649
|
-
handler:
|
|
650
|
-
isAvailable:
|
|
544
|
+
...toolInfo7,
|
|
545
|
+
handler: handler7,
|
|
546
|
+
isAvailable: isAvailable7
|
|
651
547
|
};
|
|
652
548
|
|
|
653
549
|
// src/tools/readFile.ts
|
|
654
|
-
import { z as
|
|
655
|
-
var
|
|
550
|
+
import { z as z8 } from "zod";
|
|
551
|
+
var toolInfo8 = {
|
|
656
552
|
name: "read_file",
|
|
657
553
|
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.",
|
|
658
|
-
parameters:
|
|
659
|
-
path:
|
|
554
|
+
parameters: z8.object({
|
|
555
|
+
path: z8.preprocess((val) => {
|
|
660
556
|
if (!val) return [];
|
|
661
557
|
const values = Array.isArray(val) ? val : [val];
|
|
662
558
|
return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
|
|
663
|
-
},
|
|
559
|
+
}, z8.array(z8.string())).describe("The path of the file to read").meta({ usageValue: "Comma separated paths here" })
|
|
664
560
|
}),
|
|
665
561
|
examples: [
|
|
666
562
|
{
|
|
@@ -684,14 +580,14 @@ var toolInfo7 = {
|
|
|
684
580
|
],
|
|
685
581
|
permissionLevel: 1 /* Read */
|
|
686
582
|
};
|
|
687
|
-
var
|
|
583
|
+
var handler8 = async (provider, args) => {
|
|
688
584
|
if (!provider.readFile) {
|
|
689
585
|
return {
|
|
690
586
|
type: "Error" /* Error */,
|
|
691
587
|
message: "Not possible to read file. Abort."
|
|
692
588
|
};
|
|
693
589
|
}
|
|
694
|
-
const { path: paths } =
|
|
590
|
+
const { path: paths } = toolInfo8.parameters.parse(args);
|
|
695
591
|
const resp = [];
|
|
696
592
|
for (const path of paths) {
|
|
697
593
|
const fileContent = await provider.readFile(path);
|
|
@@ -711,26 +607,126 @@ var handler7 = async (provider, args) => {
|
|
|
711
607
|
message: resp.join("\n")
|
|
712
608
|
};
|
|
713
609
|
};
|
|
714
|
-
var
|
|
610
|
+
var isAvailable8 = (provider) => {
|
|
715
611
|
return !!provider.readFile;
|
|
716
612
|
};
|
|
717
613
|
var readFile_default = {
|
|
718
|
-
...
|
|
719
|
-
handler:
|
|
720
|
-
isAvailable:
|
|
614
|
+
...toolInfo8,
|
|
615
|
+
handler: handler8,
|
|
616
|
+
isAvailable: isAvailable8
|
|
721
617
|
};
|
|
722
618
|
|
|
723
|
-
// src/tools/
|
|
724
|
-
import { z as
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
619
|
+
// src/tools/removeFile.ts
|
|
620
|
+
import { z as z9 } from "zod";
|
|
621
|
+
var toolInfo9 = {
|
|
622
|
+
name: "remove_file",
|
|
623
|
+
description: "Request to remove a file at the specified path.",
|
|
624
|
+
parameters: z9.object({
|
|
625
|
+
path: z9.string().describe("The path of the file to remove").meta({ usageValue: "File path here" })
|
|
626
|
+
}),
|
|
627
|
+
examples: [
|
|
628
|
+
{
|
|
629
|
+
description: "Request to remove a file",
|
|
630
|
+
parameters: [
|
|
631
|
+
{
|
|
632
|
+
name: "path",
|
|
633
|
+
value: "src/main.js"
|
|
634
|
+
}
|
|
635
|
+
]
|
|
636
|
+
}
|
|
637
|
+
],
|
|
638
|
+
permissionLevel: 2 /* Write */
|
|
639
|
+
};
|
|
640
|
+
var handler9 = async (provider, args) => {
|
|
641
|
+
if (!provider.removeFile) {
|
|
642
|
+
return {
|
|
643
|
+
type: "Error" /* Error */,
|
|
644
|
+
message: "Not possible to remove file. Abort."
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
const parsed = toolInfo9.parameters.safeParse(args);
|
|
648
|
+
if (!parsed.success) {
|
|
649
|
+
return {
|
|
650
|
+
type: "Invalid" /* Invalid */,
|
|
651
|
+
message: `Invalid arguments for remove_file: ${parsed.error.message}`
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
const { path } = parsed.data;
|
|
655
|
+
await provider.removeFile(path);
|
|
656
|
+
return {
|
|
657
|
+
type: "Reply" /* Reply */,
|
|
658
|
+
message: `<remove_file_path>${path}</remove_file_path><status>Success</status>`
|
|
659
|
+
};
|
|
660
|
+
};
|
|
661
|
+
var isAvailable9 = (provider) => {
|
|
662
|
+
return !!provider.removeFile;
|
|
663
|
+
};
|
|
664
|
+
var removeFile_default = {
|
|
665
|
+
...toolInfo9,
|
|
666
|
+
handler: handler9,
|
|
667
|
+
isAvailable: isAvailable9
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
// src/tools/renameFile.ts
|
|
671
|
+
import { z as z10 } from "zod";
|
|
672
|
+
var toolInfo10 = {
|
|
673
|
+
name: "rename_file",
|
|
674
|
+
description: "Request to rename a file from source path to target path.",
|
|
675
|
+
parameters: z10.object({
|
|
676
|
+
source_path: z10.string().describe("The current path of the file").meta({ usageValue: "Source file path here" }),
|
|
677
|
+
target_path: z10.string().describe("The new path for the file").meta({ usageValue: "Target file path here" })
|
|
678
|
+
}),
|
|
679
|
+
examples: [
|
|
680
|
+
{
|
|
681
|
+
description: "Request to rename a file",
|
|
682
|
+
parameters: [
|
|
683
|
+
{
|
|
684
|
+
name: "source_path",
|
|
685
|
+
value: "src/old-name.js"
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
name: "target_path",
|
|
689
|
+
value: "src/new-name.js"
|
|
690
|
+
}
|
|
691
|
+
]
|
|
692
|
+
}
|
|
693
|
+
],
|
|
694
|
+
permissionLevel: 2 /* Write */
|
|
695
|
+
};
|
|
696
|
+
var handler10 = async (provider, args) => {
|
|
697
|
+
if (!provider.renameFile) {
|
|
698
|
+
return {
|
|
699
|
+
type: "Error" /* Error */,
|
|
700
|
+
message: "Not possible to rename file. Abort."
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
const { source_path, target_path } = toolInfo10.parameters.parse(args);
|
|
704
|
+
await provider.renameFile(source_path, target_path);
|
|
705
|
+
return {
|
|
706
|
+
type: "Reply" /* Reply */,
|
|
707
|
+
message: `<rename_file_path>${target_path}</rename_file_path><status>Success</status>`
|
|
708
|
+
};
|
|
709
|
+
};
|
|
710
|
+
var isAvailable10 = (provider) => {
|
|
711
|
+
return !!provider.renameFile;
|
|
712
|
+
};
|
|
713
|
+
var renameFile_default = {
|
|
714
|
+
...toolInfo10,
|
|
715
|
+
handler: handler10,
|
|
716
|
+
isAvailable: isAvailable10
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
// src/tools/replaceInFile.ts
|
|
720
|
+
import { z as z11 } from "zod";
|
|
721
|
+
|
|
722
|
+
// src/tools/utils/replaceInFile.ts
|
|
723
|
+
var replaceInFile = (fileContent, diff) => {
|
|
724
|
+
const blockPattern = /<<<<<+ SEARCH>?\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+ REPLACE/g;
|
|
725
|
+
const blocks = [];
|
|
726
|
+
for (let match = blockPattern.exec(diff); match !== null; match = blockPattern.exec(diff)) {
|
|
727
|
+
blocks.push({ search: match[1], replace: match[2] });
|
|
728
|
+
}
|
|
729
|
+
if (blocks.length === 0) {
|
|
734
730
|
throw new Error("No valid diff blocks found.");
|
|
735
731
|
}
|
|
736
732
|
const findAndReplace = (content, search, replace) => {
|
|
@@ -798,12 +794,12 @@ var replaceInFile = (fileContent, diff) => {
|
|
|
798
794
|
};
|
|
799
795
|
|
|
800
796
|
// src/tools/replaceInFile.ts
|
|
801
|
-
var
|
|
797
|
+
var toolInfo11 = {
|
|
802
798
|
name: "replace_in_file",
|
|
803
799
|
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.",
|
|
804
|
-
parameters:
|
|
805
|
-
path:
|
|
806
|
-
diff:
|
|
800
|
+
parameters: z11.object({
|
|
801
|
+
path: z11.string().describe("The path of the file to modify").meta({ usageValue: "File path here" }),
|
|
802
|
+
diff: z11.string().describe(
|
|
807
803
|
`One or more SEARCH/REPLACE blocks following this exact format:
|
|
808
804
|
\`\`\`
|
|
809
805
|
<<<<<<< SEARCH
|
|
@@ -934,7 +930,7 @@ function oldFeature() {
|
|
|
934
930
|
],
|
|
935
931
|
permissionLevel: 2 /* Write */
|
|
936
932
|
};
|
|
937
|
-
var
|
|
933
|
+
var handler11 = async (provider, args) => {
|
|
938
934
|
if (!provider.readFile || !provider.writeFile) {
|
|
939
935
|
return {
|
|
940
936
|
type: "Error" /* Error */,
|
|
@@ -942,7 +938,7 @@ var handler8 = async (provider, args) => {
|
|
|
942
938
|
};
|
|
943
939
|
}
|
|
944
940
|
try {
|
|
945
|
-
const { path, diff } =
|
|
941
|
+
const { path, diff } = toolInfo11.parameters.parse(args);
|
|
946
942
|
const fileContent = await provider.readFile(path);
|
|
947
943
|
if (fileContent == null) {
|
|
948
944
|
return {
|
|
@@ -979,28 +975,28 @@ var handler8 = async (provider, args) => {
|
|
|
979
975
|
};
|
|
980
976
|
}
|
|
981
977
|
};
|
|
982
|
-
var
|
|
978
|
+
var isAvailable11 = (provider) => {
|
|
983
979
|
return !!provider.readFile && !!provider.writeFile;
|
|
984
980
|
};
|
|
985
981
|
var replaceInFile_default = {
|
|
986
|
-
...
|
|
987
|
-
handler:
|
|
988
|
-
isAvailable:
|
|
982
|
+
...toolInfo11,
|
|
983
|
+
handler: handler11,
|
|
984
|
+
isAvailable: isAvailable11
|
|
989
985
|
};
|
|
990
986
|
|
|
991
987
|
// src/tools/searchFiles.ts
|
|
992
|
-
import { z as
|
|
993
|
-
var
|
|
988
|
+
import { z as z12 } from "zod";
|
|
989
|
+
var toolInfo12 = {
|
|
994
990
|
name: "search_files",
|
|
995
991
|
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.",
|
|
996
|
-
parameters:
|
|
997
|
-
path:
|
|
992
|
+
parameters: z12.object({
|
|
993
|
+
path: z12.string().describe(
|
|
998
994
|
"The path of the directory to search in (relative to the current working directory). This directory will be recursively searched."
|
|
999
995
|
).meta({ usageValue: "Directory path here" }),
|
|
1000
|
-
regex:
|
|
996
|
+
regex: z12.string().describe("The regular expression pattern to search for. Uses Rust regex syntax.").meta({
|
|
1001
997
|
usageValue: "Your regex pattern here"
|
|
1002
998
|
}),
|
|
1003
|
-
filePattern:
|
|
999
|
+
filePattern: z12.string().optional().describe(
|
|
1004
1000
|
'Comma-separated glob pattern to filter files (e.g., "*.ts" for TypeScript files or "*.ts,*.js" for both TypeScript and JavaScript files). If not provided, it will search all files (*).'
|
|
1005
1001
|
).meta({
|
|
1006
1002
|
usageValue: "file pattern here (optional)"
|
|
@@ -1027,7 +1023,7 @@ var toolInfo9 = {
|
|
|
1027
1023
|
],
|
|
1028
1024
|
permissionLevel: 1 /* Read */
|
|
1029
1025
|
};
|
|
1030
|
-
var
|
|
1026
|
+
var handler12 = async (provider, args) => {
|
|
1031
1027
|
if (!provider.searchFiles) {
|
|
1032
1028
|
return {
|
|
1033
1029
|
type: "Error" /* Error */,
|
|
@@ -1035,7 +1031,7 @@ var handler9 = async (provider, args) => {
|
|
|
1035
1031
|
};
|
|
1036
1032
|
}
|
|
1037
1033
|
try {
|
|
1038
|
-
const { path, regex, filePattern } =
|
|
1034
|
+
const { path, regex, filePattern } = toolInfo12.parameters.parse(args);
|
|
1039
1035
|
const files = await provider.searchFiles(path, regex, filePattern ?? "*");
|
|
1040
1036
|
return {
|
|
1041
1037
|
type: "Reply" /* Reply */,
|
|
@@ -1054,23 +1050,23 @@ ${files.join("\n")}
|
|
|
1054
1050
|
};
|
|
1055
1051
|
}
|
|
1056
1052
|
};
|
|
1057
|
-
var
|
|
1053
|
+
var isAvailable12 = (provider) => {
|
|
1058
1054
|
return !!provider.searchFiles;
|
|
1059
1055
|
};
|
|
1060
1056
|
var searchFiles_default = {
|
|
1061
|
-
...
|
|
1062
|
-
handler:
|
|
1063
|
-
isAvailable:
|
|
1057
|
+
...toolInfo12,
|
|
1058
|
+
handler: handler12,
|
|
1059
|
+
isAvailable: isAvailable12
|
|
1064
1060
|
};
|
|
1065
1061
|
|
|
1066
1062
|
// src/tools/writeToFile.ts
|
|
1067
|
-
import { z as
|
|
1068
|
-
var
|
|
1063
|
+
import { z as z13 } from "zod";
|
|
1064
|
+
var toolInfo13 = {
|
|
1069
1065
|
name: "write_to_file",
|
|
1070
1066
|
description: "Request to write content to a file at the specified path. If the file exists, it will be overwritten with the provided content. If the file doesn't exist, it will be created. This tool will automatically create any directories needed to write the file. Ensure that the output content does not include incorrect escaped character patterns such as `<`, `>`, or `&`. Also ensure there is no unwanted CDATA tags in the content.",
|
|
1071
|
-
parameters:
|
|
1072
|
-
path:
|
|
1073
|
-
content:
|
|
1067
|
+
parameters: z13.object({
|
|
1068
|
+
path: z13.string().describe("The path of the file to write to").meta({ usageValue: "File path here" }),
|
|
1069
|
+
content: z13.string().describe(
|
|
1074
1070
|
"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."
|
|
1075
1071
|
).meta({ usageValue: "Your file content here" })
|
|
1076
1072
|
}),
|
|
@@ -1102,14 +1098,14 @@ export default App;
|
|
|
1102
1098
|
],
|
|
1103
1099
|
permissionLevel: 2 /* Write */
|
|
1104
1100
|
};
|
|
1105
|
-
var
|
|
1101
|
+
var handler13 = async (provider, args) => {
|
|
1106
1102
|
if (!provider.writeFile) {
|
|
1107
1103
|
return {
|
|
1108
1104
|
type: "Error" /* Error */,
|
|
1109
1105
|
message: "Not possible to write file. Abort."
|
|
1110
1106
|
};
|
|
1111
1107
|
}
|
|
1112
|
-
const parsed =
|
|
1108
|
+
const parsed = toolInfo13.parameters.safeParse(args);
|
|
1113
1109
|
if (!parsed.success) {
|
|
1114
1110
|
return {
|
|
1115
1111
|
type: "Invalid" /* Invalid */,
|
|
@@ -1125,179 +1121,44 @@ var handler10 = async (provider, args) => {
|
|
|
1125
1121
|
message: `<write_to_file_path>${path}</write_to_file_path><status>Success</status>`
|
|
1126
1122
|
};
|
|
1127
1123
|
};
|
|
1128
|
-
var
|
|
1124
|
+
var isAvailable13 = (provider) => {
|
|
1129
1125
|
return !!provider.writeFile;
|
|
1130
1126
|
};
|
|
1131
1127
|
var writeToFile_default = {
|
|
1132
|
-
...
|
|
1133
|
-
handler:
|
|
1134
|
-
isAvailable:
|
|
1128
|
+
...toolInfo13,
|
|
1129
|
+
handler: handler13,
|
|
1130
|
+
isAvailable: isAvailable13
|
|
1135
1131
|
};
|
|
1136
1132
|
|
|
1137
|
-
// src/tools/
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
description: "Hand over the current task to another agent to complete. This tool MUST NOT to be used with any other tool.",
|
|
1142
|
-
parameters: z11.object({
|
|
1143
|
-
agentName: z11.string().describe("The name of the agent to hand over the task to").meta({ usageValue: "Name of the target agent" }),
|
|
1144
|
-
task: z11.string().describe("The task to be completed by the target agent").meta({ usageValue: "Task description" }),
|
|
1145
|
-
context: z11.string().describe("The context information for the task").meta({ usageValue: "Context information" }),
|
|
1146
|
-
files: z11.preprocess((val) => {
|
|
1147
|
-
if (!val) return [];
|
|
1148
|
-
const values = Array.isArray(val) ? val : [val];
|
|
1149
|
-
return values.flatMap((i) => typeof i === "string" ? i.split(",") : []).filter((s) => s.length > 0);
|
|
1150
|
-
}, z11.array(z11.string())).optional().describe("The files relevant to the task. Comma separated paths").meta({ usageValue: "Relevant files" })
|
|
1151
|
-
}),
|
|
1152
|
-
examples: [
|
|
1153
|
-
{
|
|
1154
|
-
description: "Hand over a coding task to the coder agent",
|
|
1155
|
-
parameters: [
|
|
1156
|
-
{
|
|
1157
|
-
name: "agentName",
|
|
1158
|
-
value: "coder"
|
|
1159
|
-
},
|
|
1160
|
-
{
|
|
1161
|
-
name: "task",
|
|
1162
|
-
value: "Implement the login feature"
|
|
1163
|
-
},
|
|
1164
|
-
{
|
|
1165
|
-
name: "context",
|
|
1166
|
-
value: "We need a secure login system with email and password"
|
|
1167
|
-
},
|
|
1168
|
-
{
|
|
1169
|
-
name: "files",
|
|
1170
|
-
value: "src/auth/login.ts,src/auth/types.ts"
|
|
1171
|
-
}
|
|
1172
|
-
]
|
|
1173
|
-
}
|
|
1174
|
-
],
|
|
1175
|
-
permissionLevel: 0 /* None */
|
|
1176
|
-
};
|
|
1177
|
-
var handler11 = async (_provider, args) => {
|
|
1178
|
-
const parsed = toolInfo11.parameters.safeParse(args);
|
|
1179
|
-
if (!parsed.success) {
|
|
1180
|
-
return {
|
|
1181
|
-
type: "Invalid" /* Invalid */,
|
|
1182
|
-
message: `Invalid arguments for hand_over: ${parsed.error.message}`
|
|
1183
|
-
};
|
|
1133
|
+
// src/tools/provider.ts
|
|
1134
|
+
var MockProvider = class {
|
|
1135
|
+
async readFile(_path) {
|
|
1136
|
+
return "mock content";
|
|
1184
1137
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
type: "HandOver" /* HandOver */,
|
|
1188
|
-
agentName,
|
|
1189
|
-
task,
|
|
1190
|
-
context,
|
|
1191
|
-
files: files ?? []
|
|
1192
|
-
};
|
|
1193
|
-
};
|
|
1194
|
-
var isAvailable11 = (_provider) => {
|
|
1195
|
-
return true;
|
|
1196
|
-
};
|
|
1197
|
-
var handOver_default = {
|
|
1198
|
-
...toolInfo11,
|
|
1199
|
-
handler: handler11,
|
|
1200
|
-
isAvailable: isAvailable11
|
|
1201
|
-
};
|
|
1202
|
-
|
|
1203
|
-
// src/tools/removeFile.ts
|
|
1204
|
-
import { z as z12 } from "zod";
|
|
1205
|
-
var toolInfo12 = {
|
|
1206
|
-
name: "remove_file",
|
|
1207
|
-
description: "Request to remove a file at the specified path.",
|
|
1208
|
-
parameters: z12.object({
|
|
1209
|
-
path: z12.string().describe("The path of the file to remove").meta({ usageValue: "File path here" })
|
|
1210
|
-
}),
|
|
1211
|
-
examples: [
|
|
1212
|
-
{
|
|
1213
|
-
description: "Request to remove a file",
|
|
1214
|
-
parameters: [
|
|
1215
|
-
{
|
|
1216
|
-
name: "path",
|
|
1217
|
-
value: "src/main.js"
|
|
1218
|
-
}
|
|
1219
|
-
]
|
|
1220
|
-
}
|
|
1221
|
-
],
|
|
1222
|
-
permissionLevel: 2 /* Write */
|
|
1223
|
-
};
|
|
1224
|
-
var handler12 = async (provider, args) => {
|
|
1225
|
-
if (!provider.removeFile) {
|
|
1226
|
-
return {
|
|
1227
|
-
type: "Error" /* Error */,
|
|
1228
|
-
message: "Not possible to remove file. Abort."
|
|
1229
|
-
};
|
|
1138
|
+
async writeFile(_path, _content) {
|
|
1139
|
+
return;
|
|
1230
1140
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
return {
|
|
1234
|
-
type: "Invalid" /* Invalid */,
|
|
1235
|
-
message: `Invalid arguments for remove_file: ${parsed.error.message}`
|
|
1236
|
-
};
|
|
1141
|
+
async removeFile(_path) {
|
|
1142
|
+
return;
|
|
1237
1143
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
import { z as z13 } from "zod";
|
|
1256
|
-
var toolInfo13 = {
|
|
1257
|
-
name: "rename_file",
|
|
1258
|
-
description: "Request to rename a file from source path to target path.",
|
|
1259
|
-
parameters: z13.object({
|
|
1260
|
-
source_path: z13.string().describe("The current path of the file").meta({ usageValue: "Source file path here" }),
|
|
1261
|
-
target_path: z13.string().describe("The new path for the file").meta({ usageValue: "Target file path here" })
|
|
1262
|
-
}),
|
|
1263
|
-
examples: [
|
|
1264
|
-
{
|
|
1265
|
-
description: "Request to rename a file",
|
|
1266
|
-
parameters: [
|
|
1267
|
-
{
|
|
1268
|
-
name: "source_path",
|
|
1269
|
-
value: "src/old-name.js"
|
|
1270
|
-
},
|
|
1271
|
-
{
|
|
1272
|
-
name: "target_path",
|
|
1273
|
-
value: "src/new-name.js"
|
|
1274
|
-
}
|
|
1275
|
-
]
|
|
1276
|
-
}
|
|
1277
|
-
],
|
|
1278
|
-
permissionLevel: 2 /* Write */
|
|
1279
|
-
};
|
|
1280
|
-
var handler13 = async (provider, args) => {
|
|
1281
|
-
if (!provider.renameFile) {
|
|
1282
|
-
return {
|
|
1283
|
-
type: "Error" /* Error */,
|
|
1284
|
-
message: "Not possible to rename file. Abort."
|
|
1285
|
-
};
|
|
1144
|
+
async renameFile(_sourcePath, _targetPath) {
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
async listFiles(_path, _recursive, _maxCount) {
|
|
1148
|
+
return [["mock-file.txt"], false];
|
|
1149
|
+
}
|
|
1150
|
+
async searchFiles(_path, _regex, _filePattern) {
|
|
1151
|
+
return ["mock-file.txt"];
|
|
1152
|
+
}
|
|
1153
|
+
async executeCommand(_command, _needApprove) {
|
|
1154
|
+
return { stdout: "mock output", stderr: "", exitCode: 0 };
|
|
1155
|
+
}
|
|
1156
|
+
async askFollowupQuestion(_question, _options) {
|
|
1157
|
+
return "mock answer";
|
|
1158
|
+
}
|
|
1159
|
+
async attemptCompletion(_result) {
|
|
1160
|
+
return "mock completion";
|
|
1286
1161
|
}
|
|
1287
|
-
const { source_path, target_path } = toolInfo13.parameters.parse(args);
|
|
1288
|
-
await provider.renameFile(source_path, target_path);
|
|
1289
|
-
return {
|
|
1290
|
-
type: "Reply" /* Reply */,
|
|
1291
|
-
message: `<rename_file_path>${target_path}</rename_file_path><status>Success</status>`
|
|
1292
|
-
};
|
|
1293
|
-
};
|
|
1294
|
-
var isAvailable13 = (provider) => {
|
|
1295
|
-
return !!provider.renameFile;
|
|
1296
|
-
};
|
|
1297
|
-
var renameFile_default = {
|
|
1298
|
-
...toolInfo13,
|
|
1299
|
-
handler: handler13,
|
|
1300
|
-
isAvailable: isAvailable13
|
|
1301
1162
|
};
|
|
1302
1163
|
|
|
1303
1164
|
// src/getAvailableTools.ts
|
|
@@ -1365,6 +1226,150 @@ function toToolInfoV1(tool) {
|
|
|
1365
1226
|
};
|
|
1366
1227
|
}
|
|
1367
1228
|
|
|
1229
|
+
// src/UsageMeter.ts
|
|
1230
|
+
var UsageMeter = class {
|
|
1231
|
+
#totals = { input: 0, output: 0, cachedRead: 0, cost: 0 };
|
|
1232
|
+
#calls = 0;
|
|
1233
|
+
#modelInfos;
|
|
1234
|
+
#maxMessages;
|
|
1235
|
+
#maxCost;
|
|
1236
|
+
constructor(modelInfos = {}, opts = {}) {
|
|
1237
|
+
const infos = {};
|
|
1238
|
+
for (const [provider, providerInfo] of Object.entries(modelInfos)) {
|
|
1239
|
+
for (const [model, modelInfo] of Object.entries(providerInfo)) {
|
|
1240
|
+
infos[`${provider.split("-")[0]}:${model.replace(/[.-]/g, "")}`] = {
|
|
1241
|
+
inputPrice: modelInfo.inputPrice ?? 0,
|
|
1242
|
+
outputPrice: modelInfo.outputPrice ?? 0,
|
|
1243
|
+
cacheWritesPrice: modelInfo.cacheWritesPrice ?? 0,
|
|
1244
|
+
cacheReadsPrice: modelInfo.cacheReadsPrice ?? 0
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
this.#modelInfos = infos;
|
|
1249
|
+
this.#maxMessages = opts.maxMessages ?? 1e3;
|
|
1250
|
+
this.#maxCost = opts.maxCost ?? 100;
|
|
1251
|
+
}
|
|
1252
|
+
#calculageUsage(usage, providerMetadata, modelInfo) {
|
|
1253
|
+
const providerMetadataKey = Object.keys(providerMetadata ?? {})[0];
|
|
1254
|
+
const metadata = providerMetadata?.[providerMetadataKey] ?? {};
|
|
1255
|
+
switch (providerMetadataKey) {
|
|
1256
|
+
case "openrouter":
|
|
1257
|
+
return {
|
|
1258
|
+
input: usage.inputTokens ?? 0,
|
|
1259
|
+
output: usage.outputTokens ?? 0,
|
|
1260
|
+
cachedRead: usage.cachedInputTokens ?? 0,
|
|
1261
|
+
cost: metadata.usage?.cost ?? 0
|
|
1262
|
+
};
|
|
1263
|
+
case "anthropic": {
|
|
1264
|
+
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
1265
|
+
const cacheWrite = metadata?.promptCacheMissTokens ?? 0;
|
|
1266
|
+
const input = usage.inputTokens ?? 0;
|
|
1267
|
+
const output = usage.outputTokens ?? 0;
|
|
1268
|
+
return {
|
|
1269
|
+
input: input + cacheWrite + cachedRead,
|
|
1270
|
+
output,
|
|
1271
|
+
cachedRead,
|
|
1272
|
+
cost: (input * modelInfo.inputPrice + output * modelInfo.outputPrice + cacheWrite * modelInfo.cacheWritesPrice + cachedRead * modelInfo.cacheReadsPrice) / 1e6
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
case "deepseek": {
|
|
1276
|
+
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
1277
|
+
const cacheWrite = metadata.promptCacheMissTokens ?? 0;
|
|
1278
|
+
const input = usage.inputTokens ?? 0;
|
|
1279
|
+
const output = usage.outputTokens ?? 0;
|
|
1280
|
+
return {
|
|
1281
|
+
input,
|
|
1282
|
+
output,
|
|
1283
|
+
cachedRead,
|
|
1284
|
+
cost: (output * modelInfo.outputPrice + cacheWrite * modelInfo.inputPrice + cachedRead * modelInfo.cacheReadsPrice) / 1e6
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
default: {
|
|
1288
|
+
const cachedRead = usage.cachedInputTokens ?? 0;
|
|
1289
|
+
const input = usage.inputTokens ?? 0;
|
|
1290
|
+
const output = usage.outputTokens ?? 0;
|
|
1291
|
+
return {
|
|
1292
|
+
input,
|
|
1293
|
+
output,
|
|
1294
|
+
cachedRead,
|
|
1295
|
+
cost: (input * modelInfo.inputPrice + output * modelInfo.outputPrice) / 1e6
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
addUsage(llm, resp, options = {}) {
|
|
1301
|
+
const modelInfo = options.modelInfo ?? // make google.vertex.chat to google
|
|
1302
|
+
// and anthropic.messages to anthropic
|
|
1303
|
+
this.#modelInfos[`${llm.provider.split(".")[0]}:${llm.modelId.replace(/[.-]/g, "")}`] ?? {
|
|
1304
|
+
inputPrice: 0,
|
|
1305
|
+
outputPrice: 0,
|
|
1306
|
+
cacheWritesPrice: 0,
|
|
1307
|
+
cacheReadsPrice: 0
|
|
1308
|
+
};
|
|
1309
|
+
const usage = "totalUsage" in resp ? resp.totalUsage : resp.usage;
|
|
1310
|
+
const result = this.#calculageUsage(usage, resp.providerMetadata, modelInfo);
|
|
1311
|
+
this.#totals.input += result.input;
|
|
1312
|
+
this.#totals.output += result.output;
|
|
1313
|
+
this.#totals.cachedRead += result.cachedRead;
|
|
1314
|
+
this.#totals.cost += result.cost;
|
|
1315
|
+
this.#calls++;
|
|
1316
|
+
}
|
|
1317
|
+
/** Override the running totals (e.g., restore from saved state). */
|
|
1318
|
+
setUsage(newUsage) {
|
|
1319
|
+
if (newUsage.input != null) this.#totals.input = newUsage.input;
|
|
1320
|
+
if (newUsage.output != null) this.#totals.output = newUsage.output;
|
|
1321
|
+
if (newUsage.cachedRead != null) this.#totals.cachedRead = newUsage.cachedRead;
|
|
1322
|
+
if (newUsage.cost != null) this.#totals.cost = newUsage.cost;
|
|
1323
|
+
if (newUsage.calls != null) this.#calls = newUsage.calls;
|
|
1324
|
+
}
|
|
1325
|
+
/** Manually bump the message count (useful if you record some calls without token info). */
|
|
1326
|
+
incrementMessageCount(n = 1) {
|
|
1327
|
+
this.#calls += n;
|
|
1328
|
+
}
|
|
1329
|
+
/** Reset the running totals. */
|
|
1330
|
+
resetUsage() {
|
|
1331
|
+
this.#totals = { input: 0, output: 0, cachedRead: 0, cost: 0 };
|
|
1332
|
+
this.#calls = 0;
|
|
1333
|
+
}
|
|
1334
|
+
/** Return true once either messages or cost exceed the configured caps. */
|
|
1335
|
+
isLimitExceeded() {
|
|
1336
|
+
const messageCount = this.#maxMessages !== void 0 && this.#calls >= this.#maxMessages;
|
|
1337
|
+
const cost = this.#maxCost !== void 0 && this.#totals.cost >= this.#maxCost;
|
|
1338
|
+
return {
|
|
1339
|
+
messageCount,
|
|
1340
|
+
maxMessages: this.#maxMessages,
|
|
1341
|
+
cost,
|
|
1342
|
+
maxCost: this.#maxCost,
|
|
1343
|
+
result: messageCount || cost
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
/** Same as isLimitExceeded but throws an error if a limit is hit. */
|
|
1347
|
+
checkLimit() {
|
|
1348
|
+
const result = this.isLimitExceeded();
|
|
1349
|
+
if (result.result) {
|
|
1350
|
+
throw new Error(
|
|
1351
|
+
`Usage limit exceeded. Message count: ${result.messageCount}/${result.maxMessages}, cost: ${result.cost}/${result.maxCost}`
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
/** Getter for the aggregated totals (immutable copy). */
|
|
1356
|
+
get usage() {
|
|
1357
|
+
return { ...this.#totals, messageCount: this.#calls };
|
|
1358
|
+
}
|
|
1359
|
+
/** Print a concise usage summary to console. */
|
|
1360
|
+
printUsage() {
|
|
1361
|
+
const u = this.usage;
|
|
1362
|
+
console.log(
|
|
1363
|
+
`Usage - messages: ${u.messageCount}, input: ${u.input}, cached: ${u.cachedRead}, output: ${u.output}, cost: $${u.cost.toFixed(4)}`
|
|
1364
|
+
);
|
|
1365
|
+
}
|
|
1366
|
+
onFinishHandler(llm) {
|
|
1367
|
+
return (evt) => {
|
|
1368
|
+
this.addUsage(llm, evt);
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
|
|
1368
1373
|
// src/Agent/AgentBase.ts
|
|
1369
1374
|
import { streamText } from "ai";
|
|
1370
1375
|
|
|
@@ -1641,7 +1646,7 @@ ${agent.responsibilities.map((resp) => ` - ${resp}`).join("\n")}`
|
|
|
1641
1646
|
- **Current Agent Role**
|
|
1642
1647
|
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.
|
|
1643
1648
|
`;
|
|
1644
|
-
var capabilities = (
|
|
1649
|
+
var capabilities = (_toolNamePrefix) => `
|
|
1645
1650
|
====
|
|
1646
1651
|
|
|
1647
1652
|
CAPABILITIES
|
|
@@ -2327,7 +2332,7 @@ RETRY GUIDELINES
|
|
|
2327
2332
|
- Explain why the issue remains
|
|
2328
2333
|
- Suggest manual intervention steps
|
|
2329
2334
|
- Report any partial improvements`;
|
|
2330
|
-
var fullSystemPrompt3 = (info, tools, toolNamePrefix, instructions, scripts,
|
|
2335
|
+
var fullSystemPrompt3 = (info, tools, toolNamePrefix, instructions, scripts, _interactive, useNativeTool) => `
|
|
2331
2336
|
${basePrompt}
|
|
2332
2337
|
${useNativeTool ? "" : toolUsePrompt(tools, toolNamePrefix)}
|
|
2333
2338
|
${codeFixingStrategies}
|
|
@@ -2378,7 +2383,7 @@ var CodeFixerAgent = class extends AgentBase {
|
|
|
2378
2383
|
});
|
|
2379
2384
|
this.#maxRetries = options.maxRetries ?? 5;
|
|
2380
2385
|
}
|
|
2381
|
-
async onBeforeInvokeTool(name,
|
|
2386
|
+
async onBeforeInvokeTool(name, _args) {
|
|
2382
2387
|
if (name === attemptCompletion_default.name) {
|
|
2383
2388
|
if (this.#retryCount > this.#maxRetries) {
|
|
2384
2389
|
return;
|
|
@@ -2582,7 +2587,7 @@ var CoderAgent = class extends AgentBase {
|
|
|
2582
2587
|
usageMeter: options.usageMeter ?? new UsageMeter()
|
|
2583
2588
|
});
|
|
2584
2589
|
}
|
|
2585
|
-
async onBeforeInvokeTool(name,
|
|
2590
|
+
async onBeforeInvokeTool(name, _args) {
|
|
2586
2591
|
if (name !== attemptCompletion_default.name) {
|
|
2587
2592
|
return;
|
|
2588
2593
|
}
|
|
@@ -2762,7 +2767,10 @@ var configSchema = z15.object({
|
|
|
2762
2767
|
z15.object({
|
|
2763
2768
|
apiKey: z15.string().optional(),
|
|
2764
2769
|
defaultModel: z15.string().optional(),
|
|
2765
|
-
defaultParameters: z15.record(z15.string(), z15.any()).optional()
|
|
2770
|
+
defaultParameters: z15.record(z15.string(), z15.any()).optional(),
|
|
2771
|
+
location: z15.string().optional(),
|
|
2772
|
+
project: z15.string().optional(),
|
|
2773
|
+
keyFile: z15.string().optional()
|
|
2766
2774
|
})
|
|
2767
2775
|
).optional(),
|
|
2768
2776
|
defaultProvider: z15.string().optional(),
|
|
@@ -2796,6 +2804,58 @@ var Policies = /* @__PURE__ */ ((Policies2) => {
|
|
|
2796
2804
|
return Policies2;
|
|
2797
2805
|
})(Policies || {});
|
|
2798
2806
|
|
|
2807
|
+
// src/Agent/policies/EnableCachePolicy.ts
|
|
2808
|
+
var CACHEABLE_MODELS = ["sonnet", "opus", "haiku", "gemini"];
|
|
2809
|
+
function isCacheableModel(modelId) {
|
|
2810
|
+
return CACHEABLE_MODELS.some((model) => modelId.includes(model));
|
|
2811
|
+
}
|
|
2812
|
+
function getProviderKey(provider) {
|
|
2813
|
+
if (provider === "openrouter") {
|
|
2814
|
+
return "openrouter";
|
|
2815
|
+
}
|
|
2816
|
+
if (provider.includes("anthropic")) {
|
|
2817
|
+
return "anthropic";
|
|
2818
|
+
}
|
|
2819
|
+
return void 0;
|
|
2820
|
+
}
|
|
2821
|
+
var EnableCachePolicy = () => {
|
|
2822
|
+
return {
|
|
2823
|
+
name: "enablecache" /* EnableCache */,
|
|
2824
|
+
async prepareMessages(agent, messages) {
|
|
2825
|
+
const providerKey = getProviderKey(agent.ai.provider);
|
|
2826
|
+
if (!providerKey || !isCacheableModel(agent.ai.modelId)) {
|
|
2827
|
+
return messages;
|
|
2828
|
+
}
|
|
2829
|
+
const providerOptions = { [providerKey]: { cacheControl: { type: "ephemeral" } } };
|
|
2830
|
+
const newMessages = messages.slice();
|
|
2831
|
+
let userMessagesToUpdate = 2;
|
|
2832
|
+
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
2833
|
+
const message = newMessages[i];
|
|
2834
|
+
if (message.role === "user" && userMessagesToUpdate > 0) {
|
|
2835
|
+
newMessages[i] = {
|
|
2836
|
+
...message,
|
|
2837
|
+
providerOptions: {
|
|
2838
|
+
...providerOptions,
|
|
2839
|
+
...message.providerOptions ?? {}
|
|
2840
|
+
}
|
|
2841
|
+
};
|
|
2842
|
+
userMessagesToUpdate--;
|
|
2843
|
+
} else if (message.role === "system") {
|
|
2844
|
+
newMessages[i] = {
|
|
2845
|
+
...message,
|
|
2846
|
+
providerOptions: {
|
|
2847
|
+
...providerOptions,
|
|
2848
|
+
...message.providerOptions ?? {}
|
|
2849
|
+
}
|
|
2850
|
+
};
|
|
2851
|
+
break;
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
return newMessages;
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
};
|
|
2858
|
+
|
|
2799
2859
|
// src/Agent/policies/TruncateContextPolicy.ts
|
|
2800
2860
|
var DEFAULT_MAX_TOKENS_ESTIMATE = 32e3;
|
|
2801
2861
|
function getMaxTokens(agent) {
|
|
@@ -2893,58 +2953,6 @@ var TruncateContextPolicy = () => {
|
|
|
2893
2953
|
};
|
|
2894
2954
|
};
|
|
2895
2955
|
|
|
2896
|
-
// src/Agent/policies/EnableCachePolicy.ts
|
|
2897
|
-
var CACHEABLE_MODELS = ["sonnet", "opus", "haiku", "gemini"];
|
|
2898
|
-
function isCacheableModel(modelId) {
|
|
2899
|
-
return CACHEABLE_MODELS.some((model) => modelId.includes(model));
|
|
2900
|
-
}
|
|
2901
|
-
function getProviderKey(provider) {
|
|
2902
|
-
if (provider === "openrouter") {
|
|
2903
|
-
return "openrouter";
|
|
2904
|
-
}
|
|
2905
|
-
if (provider.includes("anthropic")) {
|
|
2906
|
-
return "anthropic";
|
|
2907
|
-
}
|
|
2908
|
-
return void 0;
|
|
2909
|
-
}
|
|
2910
|
-
var EnableCachePolicy = () => {
|
|
2911
|
-
return {
|
|
2912
|
-
name: "enablecache" /* EnableCache */,
|
|
2913
|
-
async prepareMessages(agent, messages) {
|
|
2914
|
-
const providerKey = getProviderKey(agent.ai.provider);
|
|
2915
|
-
if (!providerKey || !isCacheableModel(agent.ai.modelId)) {
|
|
2916
|
-
return messages;
|
|
2917
|
-
}
|
|
2918
|
-
const providerOptions = { [providerKey]: { cacheControl: { type: "ephemeral" } } };
|
|
2919
|
-
const newMessages = messages.slice();
|
|
2920
|
-
let userMessagesToUpdate = 2;
|
|
2921
|
-
for (let i = newMessages.length - 1; i >= 0; i--) {
|
|
2922
|
-
const message = newMessages[i];
|
|
2923
|
-
if (message.role === "user" && userMessagesToUpdate > 0) {
|
|
2924
|
-
newMessages[i] = {
|
|
2925
|
-
...message,
|
|
2926
|
-
providerOptions: {
|
|
2927
|
-
...providerOptions,
|
|
2928
|
-
...message.providerOptions ?? {}
|
|
2929
|
-
}
|
|
2930
|
-
};
|
|
2931
|
-
userMessagesToUpdate--;
|
|
2932
|
-
} else if (message.role === "system") {
|
|
2933
|
-
newMessages[i] = {
|
|
2934
|
-
...message,
|
|
2935
|
-
providerOptions: {
|
|
2936
|
-
...providerOptions,
|
|
2937
|
-
...message.providerOptions ?? {}
|
|
2938
|
-
}
|
|
2939
|
-
};
|
|
2940
|
-
break;
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
return newMessages;
|
|
2944
|
-
}
|
|
2945
|
-
};
|
|
2946
|
-
};
|
|
2947
|
-
|
|
2948
2956
|
// src/Agent/index.ts
|
|
2949
2957
|
var allAgents = [architectAgentInfo, coderAgentInfo, analyzerAgentInfo, codeFixerAgentInfo];
|
|
2950
2958
|
|