@polka-codes/cli 0.9.48 → 0.9.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +867 -483
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35579,7 +35579,7 @@ var {
|
|
|
35579
35579
|
Help
|
|
35580
35580
|
} = import__.default;
|
|
35581
35581
|
// package.json
|
|
35582
|
-
var version = "0.9.
|
|
35582
|
+
var version = "0.9.49";
|
|
35583
35583
|
|
|
35584
35584
|
// src/commands/code.ts
|
|
35585
35585
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
@@ -48478,8 +48478,40 @@ var fetchUrl_default = {
|
|
|
48478
48478
|
...toolInfo3,
|
|
48479
48479
|
handler: handler3
|
|
48480
48480
|
};
|
|
48481
|
-
// ../core/src/tools/
|
|
48481
|
+
// ../core/src/tools/getTodoItem.ts
|
|
48482
48482
|
var toolInfo4 = {
|
|
48483
|
+
name: "getTodoItem",
|
|
48484
|
+
description: "Get a to-do item by its ID.",
|
|
48485
|
+
parameters: exports_external.object({
|
|
48486
|
+
id: exports_external.string().describe("The ID of the to-do item.")
|
|
48487
|
+
})
|
|
48488
|
+
};
|
|
48489
|
+
var handler4 = async (provider, args) => {
|
|
48490
|
+
if (!provider.getTodoItem) {
|
|
48491
|
+
return {
|
|
48492
|
+
type: "Error" /* Error */,
|
|
48493
|
+
message: {
|
|
48494
|
+
type: "error-text",
|
|
48495
|
+
value: "Not possible to get a to-do item."
|
|
48496
|
+
}
|
|
48497
|
+
};
|
|
48498
|
+
}
|
|
48499
|
+
const { id } = toolInfo4.parameters.parse(args);
|
|
48500
|
+
const item = await provider.getTodoItem(id);
|
|
48501
|
+
return {
|
|
48502
|
+
type: "Reply" /* Reply */,
|
|
48503
|
+
message: {
|
|
48504
|
+
type: "json",
|
|
48505
|
+
value: item ?? null
|
|
48506
|
+
}
|
|
48507
|
+
};
|
|
48508
|
+
};
|
|
48509
|
+
var getTodoItem_default = {
|
|
48510
|
+
...toolInfo4,
|
|
48511
|
+
handler: handler4
|
|
48512
|
+
};
|
|
48513
|
+
// ../core/src/tools/listFiles.ts
|
|
48514
|
+
var toolInfo5 = {
|
|
48483
48515
|
name: "listFiles",
|
|
48484
48516
|
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.",
|
|
48485
48517
|
parameters: exports_external.object({
|
|
@@ -48517,7 +48549,7 @@ var toolInfo4 = {
|
|
|
48517
48549
|
]
|
|
48518
48550
|
})
|
|
48519
48551
|
};
|
|
48520
|
-
var
|
|
48552
|
+
var handler5 = async (provider, args) => {
|
|
48521
48553
|
if (!provider.listFiles) {
|
|
48522
48554
|
return {
|
|
48523
48555
|
type: "Error" /* Error */,
|
|
@@ -48527,7 +48559,7 @@ var handler4 = async (provider, args) => {
|
|
|
48527
48559
|
}
|
|
48528
48560
|
};
|
|
48529
48561
|
}
|
|
48530
|
-
const { path, maxCount, recursive, includeIgnored } =
|
|
48562
|
+
const { path, maxCount, recursive, includeIgnored } = toolInfo5.parameters.parse(args);
|
|
48531
48563
|
const [files, limitReached] = await provider.listFiles(path, recursive, maxCount, includeIgnored);
|
|
48532
48564
|
return {
|
|
48533
48565
|
type: "Reply" /* Reply */,
|
|
@@ -48543,16 +48575,16 @@ ${files.join(`
|
|
|
48543
48575
|
};
|
|
48544
48576
|
};
|
|
48545
48577
|
var listFiles_default = {
|
|
48546
|
-
...
|
|
48547
|
-
handler:
|
|
48578
|
+
...toolInfo5,
|
|
48579
|
+
handler: handler5
|
|
48548
48580
|
};
|
|
48549
48581
|
// ../core/src/tools/listMemoryTopics.ts
|
|
48550
|
-
var
|
|
48582
|
+
var toolInfo6 = {
|
|
48551
48583
|
name: "listMemoryTopics",
|
|
48552
|
-
description: "Lists all topics in memory.",
|
|
48584
|
+
description: "Lists all topics in memory. Use this to see what information has been stored and which topics are available to read from.",
|
|
48553
48585
|
parameters: exports_external.object({})
|
|
48554
48586
|
};
|
|
48555
|
-
var
|
|
48587
|
+
var handler6 = async (provider, _args) => {
|
|
48556
48588
|
const topics = await provider.listMemoryTopics();
|
|
48557
48589
|
if (!topics.length) {
|
|
48558
48590
|
return { type: "Reply" /* Reply */, message: { type: "text", value: "No topics found." } };
|
|
@@ -48568,18 +48600,91 @@ ${topics.join(`
|
|
|
48568
48600
|
};
|
|
48569
48601
|
};
|
|
48570
48602
|
var listMemoryTopics_default = {
|
|
48571
|
-
...
|
|
48572
|
-
handler:
|
|
48603
|
+
...toolInfo6,
|
|
48604
|
+
handler: handler6
|
|
48605
|
+
};
|
|
48606
|
+
// ../core/src/tools/todo.ts
|
|
48607
|
+
var TodoStatus = exports_external.enum(["open", "completed", "closed"]);
|
|
48608
|
+
var TodoItemSchema = exports_external.object({
|
|
48609
|
+
id: exports_external.string(),
|
|
48610
|
+
title: exports_external.string(),
|
|
48611
|
+
description: exports_external.string(),
|
|
48612
|
+
relevantFileList: exports_external.array(exports_external.string()),
|
|
48613
|
+
status: TodoStatus
|
|
48614
|
+
});
|
|
48615
|
+
var UpdateTodoItemInputSchema = exports_external.object({
|
|
48616
|
+
operation: exports_external.enum(["add", "update"]),
|
|
48617
|
+
id: exports_external.string().nullish(),
|
|
48618
|
+
parentId: exports_external.string().nullish(),
|
|
48619
|
+
title: exports_external.string().nullish(),
|
|
48620
|
+
description: exports_external.string().nullish(),
|
|
48621
|
+
relevantFileList: exports_external.array(exports_external.string()).nullish(),
|
|
48622
|
+
status: TodoStatus.nullish()
|
|
48623
|
+
}).superRefine((data, ctx) => {
|
|
48624
|
+
if (data.operation === "add") {
|
|
48625
|
+
if (!data.title) {
|
|
48626
|
+
ctx.addIssue({
|
|
48627
|
+
code: "custom",
|
|
48628
|
+
message: 'Title is required for "add" operation',
|
|
48629
|
+
path: ["title"]
|
|
48630
|
+
});
|
|
48631
|
+
}
|
|
48632
|
+
} else if (data.operation === "update") {
|
|
48633
|
+
if (!data.id) {
|
|
48634
|
+
ctx.addIssue({
|
|
48635
|
+
code: "custom",
|
|
48636
|
+
message: 'ID is required for "update" operation',
|
|
48637
|
+
path: ["id"]
|
|
48638
|
+
});
|
|
48639
|
+
}
|
|
48640
|
+
}
|
|
48641
|
+
});
|
|
48642
|
+
var UpdateTodoItemOutputSchema = exports_external.object({
|
|
48643
|
+
id: exports_external.string()
|
|
48644
|
+
});
|
|
48645
|
+
|
|
48646
|
+
// ../core/src/tools/listTodoItems.ts
|
|
48647
|
+
var toolInfo7 = {
|
|
48648
|
+
name: "listTodoItems",
|
|
48649
|
+
description: "List all to-do items, sorted by id. If an id is provided, it lists all sub-items for that id. Can be filtered by status.",
|
|
48650
|
+
parameters: exports_external.object({
|
|
48651
|
+
id: exports_external.string().nullish(),
|
|
48652
|
+
status: TodoStatus.nullish()
|
|
48653
|
+
})
|
|
48654
|
+
};
|
|
48655
|
+
var handler7 = async (provider, args) => {
|
|
48656
|
+
if (!provider.listTodoItems) {
|
|
48657
|
+
return {
|
|
48658
|
+
type: "Error" /* Error */,
|
|
48659
|
+
message: {
|
|
48660
|
+
type: "error-text",
|
|
48661
|
+
value: "Not possible to list to-do items."
|
|
48662
|
+
}
|
|
48663
|
+
};
|
|
48664
|
+
}
|
|
48665
|
+
const { id, status } = toolInfo7.parameters.parse(args);
|
|
48666
|
+
const items = await provider.listTodoItems(id, status);
|
|
48667
|
+
return {
|
|
48668
|
+
type: "Reply" /* Reply */,
|
|
48669
|
+
message: {
|
|
48670
|
+
type: "json",
|
|
48671
|
+
value: items
|
|
48672
|
+
}
|
|
48673
|
+
};
|
|
48674
|
+
};
|
|
48675
|
+
var listTodoItems_default = {
|
|
48676
|
+
...toolInfo7,
|
|
48677
|
+
handler: handler7
|
|
48573
48678
|
};
|
|
48574
48679
|
// ../core/src/tools/readBinaryFile.ts
|
|
48575
|
-
var
|
|
48680
|
+
var toolInfo8 = {
|
|
48576
48681
|
name: "readBinaryFile",
|
|
48577
48682
|
description: "Read a binary file from a URL or local path. Use file:// prefix to access local files. This can be used to access non-text files such as PDFs or images.",
|
|
48578
48683
|
parameters: exports_external.object({
|
|
48579
48684
|
url: exports_external.string().describe("The URL or local path of the file to read.")
|
|
48580
48685
|
})
|
|
48581
48686
|
};
|
|
48582
|
-
var
|
|
48687
|
+
var handler8 = async (provider, args) => {
|
|
48583
48688
|
if (!provider.readBinaryFile) {
|
|
48584
48689
|
return {
|
|
48585
48690
|
type: "Error" /* Error */,
|
|
@@ -48589,7 +48694,7 @@ var handler6 = async (provider, args) => {
|
|
|
48589
48694
|
}
|
|
48590
48695
|
};
|
|
48591
48696
|
}
|
|
48592
|
-
const { url: url2 } =
|
|
48697
|
+
const { url: url2 } = toolInfo8.parameters.parse(args);
|
|
48593
48698
|
try {
|
|
48594
48699
|
const filePart = await provider.readBinaryFile(url2);
|
|
48595
48700
|
return {
|
|
@@ -48618,11 +48723,11 @@ var handler6 = async (provider, args) => {
|
|
|
48618
48723
|
}
|
|
48619
48724
|
};
|
|
48620
48725
|
var readBinaryFile_default = {
|
|
48621
|
-
...
|
|
48622
|
-
handler:
|
|
48726
|
+
...toolInfo8,
|
|
48727
|
+
handler: handler8
|
|
48623
48728
|
};
|
|
48624
48729
|
// ../core/src/tools/readFile.ts
|
|
48625
|
-
var
|
|
48730
|
+
var toolInfo9 = {
|
|
48626
48731
|
name: "readFile",
|
|
48627
48732
|
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.",
|
|
48628
48733
|
parameters: exports_external.object({
|
|
@@ -48659,7 +48764,7 @@ var toolInfo7 = {
|
|
|
48659
48764
|
]
|
|
48660
48765
|
})
|
|
48661
48766
|
};
|
|
48662
|
-
var
|
|
48767
|
+
var handler9 = async (provider, args) => {
|
|
48663
48768
|
if (!provider.readFile) {
|
|
48664
48769
|
return {
|
|
48665
48770
|
type: "Error" /* Error */,
|
|
@@ -48669,7 +48774,7 @@ var handler7 = async (provider, args) => {
|
|
|
48669
48774
|
}
|
|
48670
48775
|
};
|
|
48671
48776
|
}
|
|
48672
|
-
const { path: paths, includeIgnored } =
|
|
48777
|
+
const { path: paths, includeIgnored } = toolInfo9.parameters.parse(args);
|
|
48673
48778
|
const resp = [];
|
|
48674
48779
|
for (const path of paths) {
|
|
48675
48780
|
const fileContent = await provider.readFile(path, includeIgnored);
|
|
@@ -48694,19 +48799,19 @@ var handler7 = async (provider, args) => {
|
|
|
48694
48799
|
};
|
|
48695
48800
|
};
|
|
48696
48801
|
var readFile_default = {
|
|
48697
|
-
...
|
|
48698
|
-
handler:
|
|
48802
|
+
...toolInfo9,
|
|
48803
|
+
handler: handler9
|
|
48699
48804
|
};
|
|
48700
48805
|
// ../core/src/tools/readMemory.ts
|
|
48701
|
-
var
|
|
48806
|
+
var toolInfo10 = {
|
|
48702
48807
|
name: "readMemory",
|
|
48703
|
-
description: "Reads content from a memory topic.",
|
|
48808
|
+
description: "Reads content from a memory topic. Use this to retrieve information stored in previous steps. If no topic is specified, reads from the default topic.",
|
|
48704
48809
|
parameters: exports_external.object({
|
|
48705
48810
|
topic: exports_external.string().optional().describe('The topic to read from memory. Defaults to ":default:".')
|
|
48706
48811
|
})
|
|
48707
48812
|
};
|
|
48708
|
-
var
|
|
48709
|
-
const { topic } =
|
|
48813
|
+
var handler10 = async (provider, args) => {
|
|
48814
|
+
const { topic } = toolInfo10.parameters.parse(args);
|
|
48710
48815
|
const content = await provider.readMemory(topic);
|
|
48711
48816
|
if (content) {
|
|
48712
48817
|
return {
|
|
@@ -48728,11 +48833,11 @@ ${content}
|
|
|
48728
48833
|
};
|
|
48729
48834
|
};
|
|
48730
48835
|
var readMemory_default = {
|
|
48731
|
-
...
|
|
48732
|
-
handler:
|
|
48836
|
+
...toolInfo10,
|
|
48837
|
+
handler: handler10
|
|
48733
48838
|
};
|
|
48734
48839
|
// ../core/src/tools/removeFile.ts
|
|
48735
|
-
var
|
|
48840
|
+
var toolInfo11 = {
|
|
48736
48841
|
name: "removeFile",
|
|
48737
48842
|
description: "Request to remove a file at the specified path.",
|
|
48738
48843
|
parameters: exports_external.object({
|
|
@@ -48748,7 +48853,7 @@ var toolInfo9 = {
|
|
|
48748
48853
|
]
|
|
48749
48854
|
})
|
|
48750
48855
|
};
|
|
48751
|
-
var
|
|
48856
|
+
var handler11 = async (provider, args) => {
|
|
48752
48857
|
if (!provider.removeFile) {
|
|
48753
48858
|
return {
|
|
48754
48859
|
type: "Error" /* Error */,
|
|
@@ -48758,7 +48863,7 @@ var handler9 = async (provider, args) => {
|
|
|
48758
48863
|
}
|
|
48759
48864
|
};
|
|
48760
48865
|
}
|
|
48761
|
-
const parsed =
|
|
48866
|
+
const parsed = toolInfo11.parameters.safeParse(args);
|
|
48762
48867
|
if (!parsed.success) {
|
|
48763
48868
|
return {
|
|
48764
48869
|
type: "Error" /* Error */,
|
|
@@ -48779,11 +48884,11 @@ var handler9 = async (provider, args) => {
|
|
|
48779
48884
|
};
|
|
48780
48885
|
};
|
|
48781
48886
|
var removeFile_default = {
|
|
48782
|
-
...
|
|
48783
|
-
handler:
|
|
48887
|
+
...toolInfo11,
|
|
48888
|
+
handler: handler11
|
|
48784
48889
|
};
|
|
48785
48890
|
// ../core/src/tools/renameFile.ts
|
|
48786
|
-
var
|
|
48891
|
+
var toolInfo12 = {
|
|
48787
48892
|
name: "renameFile",
|
|
48788
48893
|
description: "Request to rename a file from source path to target path.",
|
|
48789
48894
|
parameters: exports_external.object({
|
|
@@ -48801,7 +48906,7 @@ var toolInfo10 = {
|
|
|
48801
48906
|
]
|
|
48802
48907
|
})
|
|
48803
48908
|
};
|
|
48804
|
-
var
|
|
48909
|
+
var handler12 = async (provider, args) => {
|
|
48805
48910
|
if (!provider.renameFile) {
|
|
48806
48911
|
return {
|
|
48807
48912
|
type: "Error" /* Error */,
|
|
@@ -48811,7 +48916,7 @@ var handler10 = async (provider, args) => {
|
|
|
48811
48916
|
}
|
|
48812
48917
|
};
|
|
48813
48918
|
}
|
|
48814
|
-
const { source_path, target_path } =
|
|
48919
|
+
const { source_path, target_path } = toolInfo12.parameters.parse(args);
|
|
48815
48920
|
await provider.renameFile(source_path, target_path);
|
|
48816
48921
|
return {
|
|
48817
48922
|
type: "Reply" /* Reply */,
|
|
@@ -48822,12 +48927,12 @@ var handler10 = async (provider, args) => {
|
|
|
48822
48927
|
};
|
|
48823
48928
|
};
|
|
48824
48929
|
var renameFile_default = {
|
|
48825
|
-
...
|
|
48826
|
-
handler:
|
|
48930
|
+
...toolInfo12,
|
|
48931
|
+
handler: handler12
|
|
48827
48932
|
};
|
|
48828
48933
|
// ../core/src/tools/utils/replaceInFile.ts
|
|
48829
48934
|
var replaceInFile = (fileContent, diff) => {
|
|
48830
|
-
const blockPattern =
|
|
48935
|
+
const blockPattern = /^\s*<<<<<+\s*SEARCH>?\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+\s*REPLACE\s*$/gm;
|
|
48831
48936
|
const blocks = [];
|
|
48832
48937
|
for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
|
|
48833
48938
|
blocks.push({ search: match[1], replace: match[2] });
|
|
@@ -48900,7 +49005,7 @@ var replaceInFile = (fileContent, diff) => {
|
|
|
48900
49005
|
};
|
|
48901
49006
|
|
|
48902
49007
|
// ../core/src/tools/replaceInFile.ts
|
|
48903
|
-
var
|
|
49008
|
+
var toolInfo13 = {
|
|
48904
49009
|
name: "replaceInFile",
|
|
48905
49010
|
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.",
|
|
48906
49011
|
parameters: exports_external.object({
|
|
@@ -49010,7 +49115,7 @@ function oldFeature() {
|
|
|
49010
49115
|
]
|
|
49011
49116
|
})
|
|
49012
49117
|
};
|
|
49013
|
-
var
|
|
49118
|
+
var handler13 = async (provider, args) => {
|
|
49014
49119
|
if (!provider.readFile || !provider.writeFile) {
|
|
49015
49120
|
return {
|
|
49016
49121
|
type: "Error" /* Error */,
|
|
@@ -49020,7 +49125,7 @@ var handler11 = async (provider, args) => {
|
|
|
49020
49125
|
}
|
|
49021
49126
|
};
|
|
49022
49127
|
}
|
|
49023
|
-
const parsed =
|
|
49128
|
+
const parsed = toolInfo13.parameters.safeParse(args);
|
|
49024
49129
|
if (!parsed.success) {
|
|
49025
49130
|
return {
|
|
49026
49131
|
type: "Error" /* Error */,
|
|
@@ -49084,11 +49189,11 @@ var handler11 = async (provider, args) => {
|
|
|
49084
49189
|
}
|
|
49085
49190
|
};
|
|
49086
49191
|
var replaceInFile_default = {
|
|
49087
|
-
...
|
|
49088
|
-
handler:
|
|
49192
|
+
...toolInfo13,
|
|
49193
|
+
handler: handler13
|
|
49089
49194
|
};
|
|
49090
49195
|
// ../core/src/tools/searchFiles.ts
|
|
49091
|
-
var
|
|
49196
|
+
var toolInfo14 = {
|
|
49092
49197
|
name: "searchFiles",
|
|
49093
49198
|
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.",
|
|
49094
49199
|
parameters: exports_external.object({
|
|
@@ -49112,7 +49217,7 @@ var toolInfo12 = {
|
|
|
49112
49217
|
]
|
|
49113
49218
|
})
|
|
49114
49219
|
};
|
|
49115
|
-
var
|
|
49220
|
+
var handler14 = async (provider, args) => {
|
|
49116
49221
|
if (!provider.searchFiles) {
|
|
49117
49222
|
return {
|
|
49118
49223
|
type: "Error" /* Error */,
|
|
@@ -49122,7 +49227,7 @@ var handler12 = async (provider, args) => {
|
|
|
49122
49227
|
}
|
|
49123
49228
|
};
|
|
49124
49229
|
}
|
|
49125
|
-
const parsed =
|
|
49230
|
+
const parsed = toolInfo14.parameters.safeParse(args);
|
|
49126
49231
|
if (!parsed.success) {
|
|
49127
49232
|
return {
|
|
49128
49233
|
type: "Error" /* Error */,
|
|
@@ -49160,13 +49265,13 @@ ${files.join(`
|
|
|
49160
49265
|
}
|
|
49161
49266
|
};
|
|
49162
49267
|
var searchFiles_default = {
|
|
49163
|
-
...
|
|
49164
|
-
handler:
|
|
49268
|
+
...toolInfo14,
|
|
49269
|
+
handler: handler14
|
|
49165
49270
|
};
|
|
49166
49271
|
// ../core/src/tools/updateMemory.ts
|
|
49167
|
-
var
|
|
49272
|
+
var toolInfo15 = {
|
|
49168
49273
|
name: "updateMemory",
|
|
49169
|
-
description:
|
|
49274
|
+
description: 'Appends, replaces, or removes content from a memory topic. Use "append" to add to existing content, "replace" to overwrite entirely, or "remove" to delete a topic. Memory persists across tool calls within a workflow.',
|
|
49170
49275
|
parameters: exports_external.object({
|
|
49171
49276
|
operation: exports_external.enum(["append", "replace", "remove"]).describe("The operation to perform."),
|
|
49172
49277
|
topic: exports_external.string().nullish().describe('The topic to update in memory. Defaults to ":default:".'),
|
|
@@ -49191,7 +49296,7 @@ var toolInfo13 = {
|
|
|
49191
49296
|
}
|
|
49192
49297
|
})
|
|
49193
49298
|
};
|
|
49194
|
-
var
|
|
49299
|
+
var handler15 = async (provider, args) => {
|
|
49195
49300
|
if (!provider.updateMemory) {
|
|
49196
49301
|
return {
|
|
49197
49302
|
type: "Error" /* Error */,
|
|
@@ -49201,7 +49306,7 @@ var handler13 = async (provider, args) => {
|
|
|
49201
49306
|
}
|
|
49202
49307
|
};
|
|
49203
49308
|
}
|
|
49204
|
-
const params =
|
|
49309
|
+
const params = toolInfo15.parameters.parse(args);
|
|
49205
49310
|
await provider.updateMemory(params.operation, params.topic ?? undefined, "content" in params ? params.content : undefined);
|
|
49206
49311
|
switch (params.operation) {
|
|
49207
49312
|
case "append":
|
|
@@ -49231,11 +49336,41 @@ var handler13 = async (provider, args) => {
|
|
|
49231
49336
|
}
|
|
49232
49337
|
};
|
|
49233
49338
|
var updateMemory_default = {
|
|
49234
|
-
...
|
|
49235
|
-
handler:
|
|
49339
|
+
...toolInfo15,
|
|
49340
|
+
handler: handler15
|
|
49341
|
+
};
|
|
49342
|
+
// ../core/src/tools/updateTodoItem.ts
|
|
49343
|
+
var toolInfo16 = {
|
|
49344
|
+
name: "updateTodoItem",
|
|
49345
|
+
description: "Add or update a to-do item.",
|
|
49346
|
+
parameters: UpdateTodoItemInputSchema
|
|
49347
|
+
};
|
|
49348
|
+
var handler16 = async (provider, args) => {
|
|
49349
|
+
if (!provider.updateTodoItem) {
|
|
49350
|
+
return {
|
|
49351
|
+
type: "Error" /* Error */,
|
|
49352
|
+
message: {
|
|
49353
|
+
type: "error-text",
|
|
49354
|
+
value: "Not possible to update a to-do item."
|
|
49355
|
+
}
|
|
49356
|
+
};
|
|
49357
|
+
}
|
|
49358
|
+
const input = toolInfo16.parameters.parse(args);
|
|
49359
|
+
const result = await provider.updateTodoItem(input);
|
|
49360
|
+
return {
|
|
49361
|
+
type: "Reply" /* Reply */,
|
|
49362
|
+
message: {
|
|
49363
|
+
type: "json",
|
|
49364
|
+
value: result
|
|
49365
|
+
}
|
|
49366
|
+
};
|
|
49367
|
+
};
|
|
49368
|
+
var updateTodoItem_default = {
|
|
49369
|
+
...toolInfo16,
|
|
49370
|
+
handler: handler16
|
|
49236
49371
|
};
|
|
49237
49372
|
// ../core/src/tools/writeToFile.ts
|
|
49238
|
-
var
|
|
49373
|
+
var toolInfo17 = {
|
|
49239
49374
|
name: "writeToFile",
|
|
49240
49375
|
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.",
|
|
49241
49376
|
parameters: exports_external.object({
|
|
@@ -49264,7 +49399,7 @@ export default App;
|
|
|
49264
49399
|
]
|
|
49265
49400
|
})
|
|
49266
49401
|
};
|
|
49267
|
-
var
|
|
49402
|
+
var handler17 = async (provider, args) => {
|
|
49268
49403
|
if (!provider.writeFile) {
|
|
49269
49404
|
return {
|
|
49270
49405
|
type: "Error" /* Error */,
|
|
@@ -49274,7 +49409,7 @@ var handler14 = async (provider, args) => {
|
|
|
49274
49409
|
}
|
|
49275
49410
|
};
|
|
49276
49411
|
}
|
|
49277
|
-
const parsed =
|
|
49412
|
+
const parsed = toolInfo17.parameters.safeParse(args);
|
|
49278
49413
|
if (!parsed.success) {
|
|
49279
49414
|
return {
|
|
49280
49415
|
type: "Error" /* Error */,
|
|
@@ -49298,8 +49433,8 @@ var handler14 = async (provider, args) => {
|
|
|
49298
49433
|
};
|
|
49299
49434
|
};
|
|
49300
49435
|
var writeToFile_default = {
|
|
49301
|
-
...
|
|
49302
|
-
handler:
|
|
49436
|
+
...toolInfo17,
|
|
49437
|
+
handler: handler17
|
|
49303
49438
|
};
|
|
49304
49439
|
// ../core/src/UsageMeter.ts
|
|
49305
49440
|
class UsageMeter {
|
|
@@ -51340,15 +51475,15 @@ function useKeypress(userHandler) {
|
|
|
51340
51475
|
signal.current = userHandler;
|
|
51341
51476
|
useEffect((rl) => {
|
|
51342
51477
|
let ignore = false;
|
|
51343
|
-
const
|
|
51478
|
+
const handler18 = withUpdates((_input, event) => {
|
|
51344
51479
|
if (ignore)
|
|
51345
51480
|
return;
|
|
51346
51481
|
signal.current(event, rl);
|
|
51347
51482
|
});
|
|
51348
|
-
rl.input.on("keypress",
|
|
51483
|
+
rl.input.on("keypress", handler18);
|
|
51349
51484
|
return () => {
|
|
51350
51485
|
ignore = true;
|
|
51351
|
-
rl.input.removeListener("keypress",
|
|
51486
|
+
rl.input.removeListener("keypress", handler18);
|
|
51352
51487
|
};
|
|
51353
51488
|
}, []);
|
|
51354
51489
|
}
|
|
@@ -51507,16 +51642,16 @@ class Emitter {
|
|
|
51507
51642
|
|
|
51508
51643
|
class SignalExitBase {
|
|
51509
51644
|
}
|
|
51510
|
-
var signalExitWrap = (
|
|
51645
|
+
var signalExitWrap = (handler18) => {
|
|
51511
51646
|
return {
|
|
51512
51647
|
onExit(cb, opts) {
|
|
51513
|
-
return
|
|
51648
|
+
return handler18.onExit(cb, opts);
|
|
51514
51649
|
},
|
|
51515
51650
|
load() {
|
|
51516
|
-
return
|
|
51651
|
+
return handler18.load();
|
|
51517
51652
|
},
|
|
51518
51653
|
unload() {
|
|
51519
|
-
return
|
|
51654
|
+
return handler18.unload();
|
|
51520
51655
|
}
|
|
51521
51656
|
};
|
|
51522
51657
|
};
|
|
@@ -52340,8 +52475,96 @@ async function searchFiles(path, regex, filePattern, cwd, excludeFiles) {
|
|
|
52340
52475
|
var getProvider = (options = {}) => {
|
|
52341
52476
|
const ig = import_ignore2.default().add(options.excludeFiles ?? []);
|
|
52342
52477
|
const memoryStore = {};
|
|
52478
|
+
const todoItems = [];
|
|
52343
52479
|
const defaultMemoryTopic = ":default:";
|
|
52344
52480
|
const provider2 = {
|
|
52481
|
+
listTodoItems: async (id, status) => {
|
|
52482
|
+
let items;
|
|
52483
|
+
if (!id) {
|
|
52484
|
+
items = todoItems.filter((i) => !i.id.includes("."));
|
|
52485
|
+
} else {
|
|
52486
|
+
const parent = todoItems.find((i) => i.id === id);
|
|
52487
|
+
if (!parent) {
|
|
52488
|
+
throw new Error(`To-do item with id ${id} not found`);
|
|
52489
|
+
}
|
|
52490
|
+
items = todoItems.filter((i) => i.id.startsWith(`${id}.`) && i.id.split(".").length === id.split(".").length + 1);
|
|
52491
|
+
}
|
|
52492
|
+
if (status) {
|
|
52493
|
+
items = items.filter((item) => item.status === status);
|
|
52494
|
+
}
|
|
52495
|
+
items.sort((a, b) => {
|
|
52496
|
+
const aParts = a.id.split(".");
|
|
52497
|
+
const bParts = b.id.split(".");
|
|
52498
|
+
const len = Math.min(aParts.length, bParts.length);
|
|
52499
|
+
for (let i = 0;i < len; i++) {
|
|
52500
|
+
const comparison = aParts[i].localeCompare(bParts[i], undefined, { numeric: true });
|
|
52501
|
+
if (comparison !== 0) {
|
|
52502
|
+
return comparison;
|
|
52503
|
+
}
|
|
52504
|
+
}
|
|
52505
|
+
return aParts.length - bParts.length;
|
|
52506
|
+
});
|
|
52507
|
+
return items;
|
|
52508
|
+
},
|
|
52509
|
+
getTodoItem: async (id) => {
|
|
52510
|
+
const item = todoItems.find((i) => i.id === id);
|
|
52511
|
+
if (!item) {
|
|
52512
|
+
throw new Error(`To-do item with id ${id} not found`);
|
|
52513
|
+
}
|
|
52514
|
+
const subItems = todoItems.filter((i) => i.id.startsWith(`${id}.`) && i.id.split(".").length === id.split(".").length + 1).map(({ id: id2, title }) => ({ id: id2, title }));
|
|
52515
|
+
return { ...item, subItems };
|
|
52516
|
+
},
|
|
52517
|
+
updateTodoItem: async (input) => {
|
|
52518
|
+
if (input.operation === "add") {
|
|
52519
|
+
const { parentId, title, description, relevantFileList } = input;
|
|
52520
|
+
if (!title) {
|
|
52521
|
+
throw new Error("Title is required for add operation");
|
|
52522
|
+
}
|
|
52523
|
+
let newId;
|
|
52524
|
+
if (parentId) {
|
|
52525
|
+
const parent = todoItems.find((i) => i.id === parentId);
|
|
52526
|
+
if (!parent) {
|
|
52527
|
+
throw new Error(`Parent to-do item with id ${parentId} not found`);
|
|
52528
|
+
}
|
|
52529
|
+
const childItems = todoItems.filter((i) => i.id.startsWith(`${parentId}.`) && i.id.split(".").length === parentId.split(".").length + 1);
|
|
52530
|
+
newId = `${parentId}.${childItems.length + 1}`;
|
|
52531
|
+
} else {
|
|
52532
|
+
const rootItems = todoItems.filter((i) => !i.id.includes("."));
|
|
52533
|
+
newId = `${rootItems.length + 1}`;
|
|
52534
|
+
}
|
|
52535
|
+
const newItem = {
|
|
52536
|
+
id: newId,
|
|
52537
|
+
title,
|
|
52538
|
+
description: description ?? "",
|
|
52539
|
+
relevantFileList: relevantFileList ?? [],
|
|
52540
|
+
status: "open"
|
|
52541
|
+
};
|
|
52542
|
+
todoItems.push(newItem);
|
|
52543
|
+
return { id: newId };
|
|
52544
|
+
} else {
|
|
52545
|
+
const { id } = input;
|
|
52546
|
+
if (!id) {
|
|
52547
|
+
throw new Error("ID is required for update operation");
|
|
52548
|
+
}
|
|
52549
|
+
const item = todoItems.find((i) => i.id === id);
|
|
52550
|
+
if (!item) {
|
|
52551
|
+
throw new Error(`To-do item with id ${id} not found`);
|
|
52552
|
+
}
|
|
52553
|
+
if (input.title != null) {
|
|
52554
|
+
item.title = input.title;
|
|
52555
|
+
}
|
|
52556
|
+
if (input.description != null) {
|
|
52557
|
+
item.description = input.description ?? "";
|
|
52558
|
+
}
|
|
52559
|
+
if (input.relevantFileList != null) {
|
|
52560
|
+
item.relevantFileList = input.relevantFileList;
|
|
52561
|
+
}
|
|
52562
|
+
if (input.status != null) {
|
|
52563
|
+
item.status = input.status;
|
|
52564
|
+
}
|
|
52565
|
+
return { id };
|
|
52566
|
+
}
|
|
52567
|
+
},
|
|
52345
52568
|
listMemoryTopics: async () => {
|
|
52346
52569
|
return Object.keys(memoryStore);
|
|
52347
52570
|
},
|
|
@@ -64126,16 +64349,12 @@ var uiMessagesSchema = lazyValidator(() => zodSchema(exports_external.array(expo
|
|
|
64126
64349
|
|
|
64127
64350
|
// ../workflow/src/agent.workflow.ts
|
|
64128
64351
|
var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
64129
|
-
const event =
|
|
64130
|
-
|
|
64131
|
-
await tools2.taskEvent(event2);
|
|
64132
|
-
});
|
|
64133
|
-
};
|
|
64134
|
-
const { tools: toolInfo15, maxToolRoundTrips = 200 } = input;
|
|
64352
|
+
const event = (name17, event2) => step(name17, () => tools2.taskEvent(event2));
|
|
64353
|
+
const { tools: toolInfo18, maxToolRoundTrips = 200 } = input;
|
|
64135
64354
|
const messages = "systemPrompt" in input ? [{ role: "system", content: input.systemPrompt }] : input.messages;
|
|
64136
64355
|
await event("start-task", { kind: "StartTask" /* StartTask */, systemPrompt: "systemPrompt" in input ? input.systemPrompt : "" });
|
|
64137
64356
|
const toolSet = {};
|
|
64138
|
-
for (const tool3 of
|
|
64357
|
+
for (const tool3 of toolInfo18) {
|
|
64139
64358
|
toolSet[tool3.name] = {
|
|
64140
64359
|
description: tool3.description,
|
|
64141
64360
|
inputSchema: jsonSchema(toJSONSchema(tool3.parameters))
|
|
@@ -64183,7 +64402,9 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64183
64402
|
await event(`end-round-${i}`, { kind: "EndRequest" /* EndRequest */, message: textContent });
|
|
64184
64403
|
if (toolCalls.length === 0) {
|
|
64185
64404
|
if (!input.outputSchema) {
|
|
64186
|
-
|
|
64405
|
+
const exitReason2 = { type: "Exit" /* Exit */, message: textContent };
|
|
64406
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: exitReason2 });
|
|
64407
|
+
return exitReason2;
|
|
64187
64408
|
}
|
|
64188
64409
|
const parsed = parseJsonFromMarkdown(textContent);
|
|
64189
64410
|
if (!parsed.success) {
|
|
@@ -64197,7 +64418,9 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64197
64418
|
nextMessage = [{ role: "user", content: errorMessage }];
|
|
64198
64419
|
continue;
|
|
64199
64420
|
}
|
|
64200
|
-
|
|
64421
|
+
const exitReason = { type: "Exit" /* Exit */, message: textContent, object: validated.data };
|
|
64422
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason });
|
|
64423
|
+
return exitReason;
|
|
64201
64424
|
}
|
|
64202
64425
|
const toolResults = [];
|
|
64203
64426
|
for (const toolCall of toolCalls) {
|
|
@@ -64266,6 +64489,7 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64266
64489
|
}
|
|
64267
64490
|
];
|
|
64268
64491
|
}
|
|
64492
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: { type: "UsageExceeded" } });
|
|
64269
64493
|
throw new Error("Maximum number of tool round trips reached.");
|
|
64270
64494
|
};
|
|
64271
64495
|
// ../workflow/src/json-ai-types.ts
|
|
@@ -64835,6 +65059,53 @@ var chalk = createChalk();
|
|
|
64835
65059
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
64836
65060
|
var source_default = chalk;
|
|
64837
65061
|
|
|
65062
|
+
// ../cli-shared/src/utils/parameterSimplifier.ts
|
|
65063
|
+
function replaceInFileSimplifier(params) {
|
|
65064
|
+
return { path: params.path };
|
|
65065
|
+
}
|
|
65066
|
+
function writeToFileSimplifier(params) {
|
|
65067
|
+
return { path: params.path };
|
|
65068
|
+
}
|
|
65069
|
+
function readFileSimplifier(params) {
|
|
65070
|
+
return { path: params.path, includeIgnored: params.includeIgnored };
|
|
65071
|
+
}
|
|
65072
|
+
function listFilesSimplifier(params) {
|
|
65073
|
+
const maxCount = params.maxCount;
|
|
65074
|
+
return {
|
|
65075
|
+
path: params.path,
|
|
65076
|
+
recursive: params.recursive,
|
|
65077
|
+
...maxCount !== 2000 && { maxCount }
|
|
65078
|
+
};
|
|
65079
|
+
}
|
|
65080
|
+
function searchFilesSimplifier(params) {
|
|
65081
|
+
return { ...params };
|
|
65082
|
+
}
|
|
65083
|
+
function executeCommandSimplifier(params) {
|
|
65084
|
+
return { command: params.command, requiresApproval: params.requiresApproval };
|
|
65085
|
+
}
|
|
65086
|
+
function updateMemorySimplifier(params) {
|
|
65087
|
+
return { operation: params.operation, topic: params.topic };
|
|
65088
|
+
}
|
|
65089
|
+
var SIMPLIFIERS = {
|
|
65090
|
+
replaceInFile: replaceInFileSimplifier,
|
|
65091
|
+
writeToFile: writeToFileSimplifier,
|
|
65092
|
+
readFile: readFileSimplifier,
|
|
65093
|
+
listFiles: listFilesSimplifier,
|
|
65094
|
+
searchFiles: searchFilesSimplifier,
|
|
65095
|
+
executeCommand: executeCommandSimplifier,
|
|
65096
|
+
updateMemory: updateMemorySimplifier
|
|
65097
|
+
};
|
|
65098
|
+
function simplifyToolParameters(toolName, params) {
|
|
65099
|
+
if (params === undefined || params === null) {
|
|
65100
|
+
return {};
|
|
65101
|
+
}
|
|
65102
|
+
const simplifier = SIMPLIFIERS[toolName];
|
|
65103
|
+
if (simplifier) {
|
|
65104
|
+
return simplifier(params);
|
|
65105
|
+
}
|
|
65106
|
+
return { ...params };
|
|
65107
|
+
}
|
|
65108
|
+
|
|
64838
65109
|
// ../cli-shared/src/utils/eventHandler.ts
|
|
64839
65110
|
var taskToolCallStats = new Map;
|
|
64840
65111
|
var globalToolCallStats = new Map;
|
|
@@ -64859,8 +65130,26 @@ function logToolCallStats(stream, statsMap, title) {
|
|
|
64859
65130
|
customConsole.log("No tools were called.");
|
|
64860
65131
|
}
|
|
64861
65132
|
}
|
|
65133
|
+
var mergeToolCallStats = (a, b) => {
|
|
65134
|
+
const merged = new Map;
|
|
65135
|
+
for (const [tool3, stat] of a) {
|
|
65136
|
+
merged.set(tool3, { ...stat });
|
|
65137
|
+
}
|
|
65138
|
+
for (const [tool3, stat] of b) {
|
|
65139
|
+
const existing = merged.get(tool3);
|
|
65140
|
+
if (existing) {
|
|
65141
|
+
existing.calls += stat.calls;
|
|
65142
|
+
existing.success += stat.success;
|
|
65143
|
+
existing.errors += stat.errors;
|
|
65144
|
+
} else {
|
|
65145
|
+
merged.set(tool3, { ...stat });
|
|
65146
|
+
}
|
|
65147
|
+
}
|
|
65148
|
+
return merged;
|
|
65149
|
+
};
|
|
64862
65150
|
function logGlobalToolCallStats(stream) {
|
|
64863
|
-
|
|
65151
|
+
const merged = mergeToolCallStats(globalToolCallStats, taskToolCallStats);
|
|
65152
|
+
logToolCallStats(stream, merged, "Global Tool Call Stats");
|
|
64864
65153
|
}
|
|
64865
65154
|
var printEvent = (verbose, usageMeter, stream = process.stdout) => {
|
|
64866
65155
|
if (verbose < 0) {
|
|
@@ -64868,6 +65157,7 @@ var printEvent = (verbose, usageMeter, stream = process.stdout) => {
|
|
|
64868
65157
|
}
|
|
64869
65158
|
const customConsole = new Console(stream, stream);
|
|
64870
65159
|
let hadReasoning = false;
|
|
65160
|
+
let hasText = false;
|
|
64871
65161
|
const write = stream.write.bind(stream);
|
|
64872
65162
|
return (event) => {
|
|
64873
65163
|
switch (event.kind) {
|
|
@@ -64884,6 +65174,7 @@ ${event.systemPrompt}`);
|
|
|
64884
65174
|
}
|
|
64885
65175
|
break;
|
|
64886
65176
|
case "StartRequest" /* StartRequest */:
|
|
65177
|
+
hasText = false;
|
|
64887
65178
|
if (verbose > 0) {
|
|
64888
65179
|
customConsole.log(`
|
|
64889
65180
|
|
|
@@ -64937,6 +65228,11 @@ ${event.systemPrompt}`);
|
|
|
64937
65228
|
customConsole.log(`
|
|
64938
65229
|
|
|
64939
65230
|
======== Request Ended ========
|
|
65231
|
+
`);
|
|
65232
|
+
}
|
|
65233
|
+
if (verbose === 0 && hasText) {
|
|
65234
|
+
write(`
|
|
65235
|
+
|
|
64940
65236
|
`);
|
|
64941
65237
|
}
|
|
64942
65238
|
if (verbose > 1) {
|
|
@@ -64950,6 +65246,9 @@ ${event.systemPrompt}`);
|
|
|
64950
65246
|
`);
|
|
64951
65247
|
hadReasoning = false;
|
|
64952
65248
|
}
|
|
65249
|
+
if (event.newText.trim().length > 0) {
|
|
65250
|
+
hasText = true;
|
|
65251
|
+
}
|
|
64953
65252
|
write(event.newText);
|
|
64954
65253
|
break;
|
|
64955
65254
|
}
|
|
@@ -64964,7 +65263,7 @@ ${event.systemPrompt}`);
|
|
|
64964
65263
|
if (verbose > 0) {
|
|
64965
65264
|
customConsole.log(source_default.yellow(`
|
|
64966
65265
|
|
|
64967
|
-
Tool use:`, event.tool), event.params);
|
|
65266
|
+
Tool use:`, event.tool), simplifyToolParameters(event.tool, event.params));
|
|
64968
65267
|
}
|
|
64969
65268
|
const stats = taskToolCallStats.get(event.tool) ?? { calls: 0, success: 0, errors: 0 };
|
|
64970
65269
|
stats.calls++;
|
|
@@ -65000,18 +65299,26 @@ Tool error:`, event.tool));
|
|
|
65000
65299
|
`);
|
|
65001
65300
|
customConsole.log("Reason:", event.exitReason.type);
|
|
65002
65301
|
switch (event.exitReason.type) {
|
|
65302
|
+
case "Error": {
|
|
65303
|
+
const { error: error46 } = event.exitReason;
|
|
65304
|
+
customConsole.error(source_default.red(`Workflow failed: ${error46.message}`));
|
|
65305
|
+
if (verbose > 0 && error46.stack) {
|
|
65306
|
+
customConsole.error(source_default.red(error46.stack));
|
|
65307
|
+
}
|
|
65308
|
+
break;
|
|
65309
|
+
}
|
|
65003
65310
|
case "Exit" /* Exit */:
|
|
65004
65311
|
customConsole.log("Exit Message:", event.exitReason.message);
|
|
65005
65312
|
break;
|
|
65006
65313
|
}
|
|
65314
|
+
for (const [tool3, taskStats] of taskToolCallStats.entries()) {
|
|
65315
|
+
const globalStats = globalToolCallStats.get(tool3) ?? { calls: 0, success: 0, errors: 0 };
|
|
65316
|
+
globalStats.calls += taskStats.calls;
|
|
65317
|
+
globalStats.success += taskStats.success;
|
|
65318
|
+
globalStats.errors += taskStats.errors;
|
|
65319
|
+
globalToolCallStats.set(tool3, globalStats);
|
|
65320
|
+
}
|
|
65007
65321
|
if (verbose > 0) {
|
|
65008
|
-
for (const [tool3, taskStats] of taskToolCallStats.entries()) {
|
|
65009
|
-
const globalStats = globalToolCallStats.get(tool3) ?? { calls: 0, success: 0, errors: 0 };
|
|
65010
|
-
globalStats.calls += taskStats.calls;
|
|
65011
|
-
globalStats.success += taskStats.success;
|
|
65012
|
-
globalStats.errors += taskStats.errors;
|
|
65013
|
-
globalToolCallStats.set(tool3, globalStats);
|
|
65014
|
-
}
|
|
65015
65322
|
logToolCallStats(stream, taskToolCallStats, "Task Tool Call Stats");
|
|
65016
65323
|
}
|
|
65017
65324
|
break;
|
|
@@ -77501,7 +77808,7 @@ function annotateDiffWithLineNumbers(diff) {
|
|
|
77501
77808
|
}
|
|
77502
77809
|
|
|
77503
77810
|
// src/tools/gitDiff.ts
|
|
77504
|
-
var
|
|
77811
|
+
var toolInfo18 = {
|
|
77505
77812
|
name: "git_diff",
|
|
77506
77813
|
description: "Get the git diff for the current repository. Can be used to get staged changes, unstaged changes, or changes between commits. By default, it returns unstaged changes.",
|
|
77507
77814
|
parameters: exports_external.object({
|
|
@@ -77530,7 +77837,7 @@ var toolInfo15 = {
|
|
|
77530
77837
|
}, exports_external.boolean().optional().default(false)).describe("Annotate the diff with line numbers for additions and deletions.")
|
|
77531
77838
|
})
|
|
77532
77839
|
};
|
|
77533
|
-
var
|
|
77840
|
+
var handler18 = async (provider3, args) => {
|
|
77534
77841
|
if (!provider3.executeCommand) {
|
|
77535
77842
|
return {
|
|
77536
77843
|
type: "Error" /* Error */,
|
|
@@ -77540,7 +77847,7 @@ var handler15 = async (provider3, args) => {
|
|
|
77540
77847
|
}
|
|
77541
77848
|
};
|
|
77542
77849
|
}
|
|
77543
|
-
const { staged, file: file2, commitRange, contextLines, includeLineNumbers } =
|
|
77850
|
+
const { staged, file: file2, commitRange, contextLines, includeLineNumbers } = toolInfo18.parameters.parse(args);
|
|
77544
77851
|
const commandParts = ["git", "diff", "--no-color", `-U${contextLines}`];
|
|
77545
77852
|
if (staged) {
|
|
77546
77853
|
commandParts.push("--staged");
|
|
@@ -77597,8 +77904,8 @@ ${result.stderr}`
|
|
|
77597
77904
|
}
|
|
77598
77905
|
};
|
|
77599
77906
|
var gitDiff_default = {
|
|
77600
|
-
...
|
|
77601
|
-
handler:
|
|
77907
|
+
...toolInfo18,
|
|
77908
|
+
handler: handler18
|
|
77602
77909
|
};
|
|
77603
77910
|
// src/utils/cacheControl.ts
|
|
77604
77911
|
var CACHEABLE_MODELS = ["sonnet", "opus", "haiku", "gemini"];
|
|
@@ -77929,7 +78236,10 @@ var allTools = [
|
|
|
77929
78236
|
replaceInFile_default,
|
|
77930
78237
|
searchFiles_default,
|
|
77931
78238
|
writeToFile_default,
|
|
77932
|
-
gitDiff_default
|
|
78239
|
+
gitDiff_default,
|
|
78240
|
+
getTodoItem_default,
|
|
78241
|
+
listTodoItems_default,
|
|
78242
|
+
updateTodoItem_default
|
|
77933
78243
|
];
|
|
77934
78244
|
var toolHandlers = new Map(allTools.map((t) => [t.name, t]));
|
|
77935
78245
|
async function createPullRequest(input, _context) {
|
|
@@ -77974,6 +78284,7 @@ async function confirm(input, context) {
|
|
|
77974
78284
|
}
|
|
77975
78285
|
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
77976
78286
|
try {
|
|
78287
|
+
process.stderr.write("\x07");
|
|
77977
78288
|
const result = await esm_default2({ message: input.message });
|
|
77978
78289
|
return result;
|
|
77979
78290
|
} catch (_e) {
|
|
@@ -77985,6 +78296,7 @@ async function input(input2, context) {
|
|
|
77985
78296
|
return input2.default ?? "";
|
|
77986
78297
|
}
|
|
77987
78298
|
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
78299
|
+
process.stderr.write("\x07");
|
|
77988
78300
|
const result = await getUserInput(input2.message, {
|
|
77989
78301
|
default: input2.default
|
|
77990
78302
|
});
|
|
@@ -77999,6 +78311,7 @@ async function select(input2, context) {
|
|
|
77999
78311
|
}
|
|
78000
78312
|
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
78001
78313
|
try {
|
|
78314
|
+
process.stderr.write("\x07");
|
|
78002
78315
|
const result = await esm_default5({ message: input2.message, choices: input2.choices });
|
|
78003
78316
|
return result;
|
|
78004
78317
|
} catch (_e) {
|
|
@@ -78193,6 +78506,18 @@ async function updateMemory(input2, context) {
|
|
|
78193
78506
|
const content = "content" in input2 ? input2.content : undefined;
|
|
78194
78507
|
return provider3.updateMemory(input2.operation, input2.topic, content);
|
|
78195
78508
|
}
|
|
78509
|
+
async function listTodoItems(input2, context) {
|
|
78510
|
+
const provider3 = context.toolProvider;
|
|
78511
|
+
return provider3.listTodoItems(input2.id, input2.status);
|
|
78512
|
+
}
|
|
78513
|
+
async function getTodoItem(input2, context) {
|
|
78514
|
+
const provider3 = context.toolProvider;
|
|
78515
|
+
return provider3.getTodoItem(input2.id);
|
|
78516
|
+
}
|
|
78517
|
+
async function updateTodoItem(input2, context) {
|
|
78518
|
+
const provider3 = context.toolProvider;
|
|
78519
|
+
return provider3.updateTodoItem(input2);
|
|
78520
|
+
}
|
|
78196
78521
|
var localToolHandlers = {
|
|
78197
78522
|
createPullRequest,
|
|
78198
78523
|
createCommit,
|
|
@@ -78207,12 +78532,15 @@ var localToolHandlers = {
|
|
|
78207
78532
|
invokeTool,
|
|
78208
78533
|
taskEvent,
|
|
78209
78534
|
getMemoryContext,
|
|
78210
|
-
updateMemory
|
|
78535
|
+
updateMemory,
|
|
78536
|
+
listTodoItems,
|
|
78537
|
+
getTodoItem,
|
|
78538
|
+
updateTodoItem
|
|
78211
78539
|
};
|
|
78212
78540
|
async function toolCall(toolCall2, context) {
|
|
78213
|
-
const
|
|
78214
|
-
if (
|
|
78215
|
-
return
|
|
78541
|
+
const handler19 = localToolHandlers[toolCall2.tool];
|
|
78542
|
+
if (handler19) {
|
|
78543
|
+
return handler19(toolCall2.input, context);
|
|
78216
78544
|
}
|
|
78217
78545
|
throw new Error(`Unknown tool: ${toolCall2.tool}`);
|
|
78218
78546
|
}
|
|
@@ -78284,11 +78612,15 @@ Workflow completed successfully.`);
|
|
|
78284
78612
|
return output;
|
|
78285
78613
|
} catch (e) {
|
|
78286
78614
|
const error46 = e;
|
|
78615
|
+
onEvent({
|
|
78616
|
+
kind: "EndTask" /* EndTask */,
|
|
78617
|
+
exitReason: {
|
|
78618
|
+
type: "Error",
|
|
78619
|
+
error: { message: error46.message, stack: error46.stack }
|
|
78620
|
+
}
|
|
78621
|
+
});
|
|
78287
78622
|
if (error46 instanceof UserCancelledError) {
|
|
78288
78623
|
logger.warn("Workflow cancelled by user.");
|
|
78289
|
-
} else {
|
|
78290
|
-
logger.error(`Workflow failed: ${error46.message}`);
|
|
78291
|
-
logger.error(error46);
|
|
78292
78624
|
}
|
|
78293
78625
|
logger.info(usage.getUsageText());
|
|
78294
78626
|
return;
|
|
@@ -78305,14 +78637,23 @@ ${JSON.stringify(schema, null, 2)}
|
|
|
78305
78637
|
\`\`\`
|
|
78306
78638
|
`;
|
|
78307
78639
|
}
|
|
78640
|
+
var TOOL_USAGE_INSTRUCTION = `When you use a tool, you MUST first provide a short summary of what you are doing and why you are using that tool. This summary will be shown to the user to explain your actions.`;
|
|
78308
78641
|
var MEMORY_USAGE_SECTION = `## Memory Usage
|
|
78309
78642
|
|
|
78310
78643
|
You have access to a memory feature to store and retrieve information across tool calls.
|
|
78311
78644
|
|
|
78312
|
-
|
|
78313
|
-
|
|
78314
|
-
|
|
78315
|
-
-
|
|
78645
|
+
### Topic Organization
|
|
78646
|
+
|
|
78647
|
+
Memory is organized using topics, which are like named containers for different types of information:
|
|
78648
|
+
- **Default topic** (\`:default:\`): Used when no topic is specified. Good for general context.
|
|
78649
|
+
- **Named topics**: Create meaningful topic names to organize different types of information
|
|
78650
|
+
|
|
78651
|
+
### Best Practices
|
|
78652
|
+
|
|
78653
|
+
- Store decisions and context that inform subsequent steps
|
|
78654
|
+
- Use named topics to organize different types of information
|
|
78655
|
+
- Use the default topic for simple, single-context scenarios
|
|
78656
|
+
- Memory persists across all tool calls within the current workflow
|
|
78316
78657
|
`;
|
|
78317
78658
|
var PLANNER_SYSTEM_PROMPT = `Role: Expert software architect and planner.
|
|
78318
78659
|
Goal: Analyze user requests and create detailed, actionable implementation plans for software development tasks.
|
|
@@ -78321,6 +78662,8 @@ You are an expert software architect and planner with deep experience in breakin
|
|
|
78321
78662
|
|
|
78322
78663
|
${MEMORY_USAGE_SECTION}
|
|
78323
78664
|
|
|
78665
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
78666
|
+
|
|
78324
78667
|
## Your Role
|
|
78325
78668
|
|
|
78326
78669
|
As a planner, your expertise lies in:
|
|
@@ -78506,6 +78849,8 @@ You are an expert software architect specializing in creating high-level plans f
|
|
|
78506
78849
|
|
|
78507
78850
|
${MEMORY_USAGE_SECTION}
|
|
78508
78851
|
|
|
78852
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
78853
|
+
|
|
78509
78854
|
## Your Role
|
|
78510
78855
|
|
|
78511
78856
|
As a high-level planner for epics, your expertise lies in:
|
|
@@ -78623,9 +78968,12 @@ ${createJsonResponseInstruction({
|
|
|
78623
78968
|
reason: "If no plan is needed, provide a reason here."
|
|
78624
78969
|
})}
|
|
78625
78970
|
`;
|
|
78971
|
+
var BRANCH_NAME_PATTERN = /^[a-zA-Z0-9/_-]+$/;
|
|
78626
78972
|
var EpicPlanSchema = exports_external.object({
|
|
78627
78973
|
plan: exports_external.string().nullish(),
|
|
78628
|
-
branchName: exports_external.string(),
|
|
78974
|
+
branchName: exports_external.string().refine((name18) => name18.length >= 3, { message: "Branch name is too short (min 3 characters)." }).refine((name18) => name18.length <= 255, { message: "Branch name is too long (max 255 characters)." }).refine((name18) => BRANCH_NAME_PATTERN.test(name18), {
|
|
78975
|
+
message: "Invalid branch name format. Branch names should contain only letters, numbers, hyphens, underscores, and forward slashes."
|
|
78976
|
+
}),
|
|
78629
78977
|
question: exports_external.object({
|
|
78630
78978
|
question: exports_external.string(),
|
|
78631
78979
|
defaultAnswer: exports_external.string().nullish()
|
|
@@ -78647,57 +78995,23 @@ ${task}
|
|
|
78647
78995
|
</task>
|
|
78648
78996
|
${planSection}`;
|
|
78649
78997
|
}
|
|
78650
|
-
var
|
|
78651
|
-
Goal:
|
|
78998
|
+
var EPIC_ADD_TODO_ITEMS_SYSTEM_PROMPT = `Role: Task creation agent
|
|
78999
|
+
Goal: Read a high-level plan and create corresponding todo items.
|
|
78652
79000
|
|
|
78653
|
-
|
|
79001
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
78654
79002
|
|
|
78655
|
-
|
|
79003
|
+
You are a task creation agent. Your responsibility is to read a high-level plan for an epic and create a todo item for each task in the plan.
|
|
78656
79004
|
|
|
78657
79005
|
## Your Task
|
|
78658
79006
|
|
|
78659
|
-
You will
|
|
78660
|
-
|
|
78661
|
-
- **Implementation summary** describing what was just completed
|
|
78662
|
-
- **The specific task** that was just implemented
|
|
79007
|
+
You will have access to the high-level plan stored in memory under the topic 'epic-plan'.
|
|
79008
|
+
Read the plan and for each task item in the plan, use the 'updateTodoItem' tool to create a new todo item.
|
|
78663
79009
|
|
|
78664
79010
|
## Process
|
|
78665
79011
|
|
|
78666
|
-
1.
|
|
78667
|
-
2.
|
|
78668
|
-
- If using checkboxes: Change \`- [ ]\` to \`- [x]\`
|
|
78669
|
-
- If using numbered lists: Add a ✅ prefix (e.g., "1. Task" → "✅ 1. Task")
|
|
78670
|
-
- If using narrative: Mark completion in context-appropriate way
|
|
78671
|
-
3. **Scan for next task**: Find the next incomplete item
|
|
78672
|
-
4. **Determine completion status**: Check if all items are complete
|
|
78673
|
-
|
|
78674
|
-
## Output Requirements
|
|
78675
|
-
|
|
78676
|
-
Return:
|
|
78677
|
-
- **updatedPlan**: The full plan text with the completed item marked
|
|
78678
|
-
- **isComplete**: boolean - true if all items are done, false if incomplete items remain
|
|
78679
|
-
- **nextTask**: The text of the next incomplete item, or null if all items are complete
|
|
78680
|
-
|
|
78681
|
-
## Important Notes
|
|
78682
|
-
|
|
78683
|
-
- Keep the plan structure and formatting intact
|
|
78684
|
-
- Adapt completion marking to match the plan's format
|
|
78685
|
-
- Extract the next task text without format prefixes (e.g., without "- [ ]" or "1.")
|
|
78686
|
-
- If multiple incomplete items remain, return the first one in document order
|
|
78687
|
-
|
|
78688
|
-
## Response Format
|
|
78689
|
-
|
|
78690
|
-
${createJsonResponseInstruction({
|
|
78691
|
-
updatedPlan: "The full plan with completed item marked",
|
|
78692
|
-
isComplete: false,
|
|
78693
|
-
nextTask: "The text of the next incomplete item (or null if complete)"
|
|
78694
|
-
})}
|
|
79012
|
+
1. Parse the plan to identify individual tasks.
|
|
79013
|
+
2. For each task, call 'updateTodoItem' with the task description as the 'title'.
|
|
78695
79014
|
`;
|
|
78696
|
-
var UpdatedPlanSchema = exports_external.object({
|
|
78697
|
-
updatedPlan: exports_external.string().describe("The updated plan with completed item marked as [x]"),
|
|
78698
|
-
isComplete: exports_external.boolean().describe("True if all checklist items are completed, false if incomplete items remain"),
|
|
78699
|
-
nextTask: exports_external.string().nullish().describe("The next incomplete checklist item to implement, or null if complete")
|
|
78700
|
-
});
|
|
78701
79015
|
var CODER_SYSTEM_PROMPT = `Role: AI developer.
|
|
78702
79016
|
Goal: Implement the provided plan by writing and modifying code.
|
|
78703
79017
|
|
|
@@ -78705,6 +79019,8 @@ Your task is to implement the plan created and approved in Phase 1.
|
|
|
78705
79019
|
|
|
78706
79020
|
${MEMORY_USAGE_SECTION}
|
|
78707
79021
|
|
|
79022
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79023
|
+
|
|
78708
79024
|
## Implementation Guidelines
|
|
78709
79025
|
|
|
78710
79026
|
### 1. Plan Analysis
|
|
@@ -78778,6 +79094,8 @@ You are an expert software developer. Your task is to fix a project that is fail
|
|
|
78778
79094
|
|
|
78779
79095
|
${MEMORY_USAGE_SECTION}
|
|
78780
79096
|
|
|
79097
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79098
|
+
|
|
78781
79099
|
After making changes, you MUST return a JSON object in a markdown block with either a summary of the changes OR a bailReason if you cannot complete the task.
|
|
78782
79100
|
|
|
78783
79101
|
Example for successful fix:
|
|
@@ -78815,6 +79133,8 @@ ${stderr || "(empty)"}
|
|
|
78815
79133
|
var CODE_REVIEW_SYSTEM_PROMPT = `Role: Senior software engineer.
|
|
78816
79134
|
Goal: Review code changes and provide specific, actionable feedback on any issues found.
|
|
78817
79135
|
|
|
79136
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79137
|
+
|
|
78818
79138
|
# Code Review Prompt
|
|
78819
79139
|
|
|
78820
79140
|
You are a senior software engineer reviewing code changes.
|
|
@@ -78929,6 +79249,8 @@ ${instructions}
|
|
|
78929
79249
|
var COMMIT_MESSAGE_SYSTEM_PROMPT = `Role: Expert git user.
|
|
78930
79250
|
Goal: Generate a concise and descriptive commit message in conventional commit format based on staged changes.
|
|
78931
79251
|
|
|
79252
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79253
|
+
|
|
78932
79254
|
You are an expert at writing git commit messages.
|
|
78933
79255
|
Based on the provided list of staged files in <file_status>, the diff in <diff> and optional user context in <tool_input_context>, generate a concise and descriptive commit message.
|
|
78934
79256
|
|
|
@@ -78941,6 +79263,8 @@ ${createJsonResponseInstruction({
|
|
|
78941
79263
|
var GET_PR_DETAILS_SYSTEM_PROMPT = `Role: Expert developer.
|
|
78942
79264
|
Goal: Generate a pull request title and description based on the branch name, commits, and diff.
|
|
78943
79265
|
|
|
79266
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79267
|
+
|
|
78944
79268
|
You are an expert at creating pull requests.
|
|
78945
79269
|
Based on the provided branch name, commit messages, and diff, generate a title and description for the pull request.
|
|
78946
79270
|
|
|
@@ -78953,6 +79277,8 @@ var INIT_WORKFLOW_ANALYZE_SYSTEM_PROMPT = `
|
|
|
78953
79277
|
Role: Analyzer agent
|
|
78954
79278
|
Goal: Produce a valid polkacodes YAML configuration for the project.
|
|
78955
79279
|
|
|
79280
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79281
|
+
|
|
78956
79282
|
Workflow
|
|
78957
79283
|
1. Scan project files to identify the project's characteristics. Start using the "readFile" tool to understand the project's dependencies, scripts, and basic configuration.
|
|
78958
79284
|
- Package/build tool (npm, bun, pnpm, etc.)
|
|
@@ -79897,96 +80223,6 @@ ${provider3.toUpperCase()}_API_KEY=${providerConfig.apiKey}`;
|
|
|
79897
80223
|
};
|
|
79898
80224
|
// src/workflows/epic.workflow.ts
|
|
79899
80225
|
var MAX_REVIEW_RETRIES = 5;
|
|
79900
|
-
var BRANCH_NAME_PATTERN = /^[a-zA-Z0-9/_-]+$/;
|
|
79901
|
-
function validateBranchName(name18) {
|
|
79902
|
-
if (!BRANCH_NAME_PATTERN.test(name18)) {
|
|
79903
|
-
return {
|
|
79904
|
-
valid: false,
|
|
79905
|
-
error: `Invalid branch name format: "${name18}". Branch names should contain only letters, numbers, hyphens, underscores, and forward slashes.`
|
|
79906
|
-
};
|
|
79907
|
-
}
|
|
79908
|
-
if (name18.length > 255) {
|
|
79909
|
-
return { valid: false, error: "Branch name is too long (max 255 characters)." };
|
|
79910
|
-
}
|
|
79911
|
-
return { valid: true };
|
|
79912
|
-
}
|
|
79913
|
-
async function performReviewAndFixCycle(iterationCount, taskItem, currentPlan, context) {
|
|
79914
|
-
const { logger, step, tools: tools2 } = context;
|
|
79915
|
-
for (let i = 0;i < MAX_REVIEW_RETRIES; i++) {
|
|
79916
|
-
const diffResult = await tools2.executeCommand({ command: "git", args: ["diff", "--name-status", "HEAD~1", "HEAD"] });
|
|
79917
|
-
const changedFiles = parseGitDiffNameStatus(diffResult.stdout);
|
|
79918
|
-
if (changedFiles.length === 0) {
|
|
79919
|
-
logger.info(`ℹ️ No files were changed. Skipping review.
|
|
79920
|
-
`);
|
|
79921
|
-
return { passed: true };
|
|
79922
|
-
}
|
|
79923
|
-
logger.info(`
|
|
79924
|
-
\uD83D\uDD0E Review iteration ${i + 1}/${MAX_REVIEW_RETRIES}`);
|
|
79925
|
-
logger.info(` Changed files: ${changedFiles.length}`);
|
|
79926
|
-
const changeInfo = {
|
|
79927
|
-
commitRange: "HEAD~1...HEAD",
|
|
79928
|
-
changedFiles
|
|
79929
|
-
};
|
|
79930
|
-
const reviewAgentResult = await step(`review-${iterationCount}-${i}`, async () => {
|
|
79931
|
-
const defaultContext = await getDefaultContext();
|
|
79932
|
-
const memoryContext = await tools2.getMemoryContext();
|
|
79933
|
-
const userMessage = `${defaultContext}
|
|
79934
|
-
${memoryContext}
|
|
79935
|
-
|
|
79936
|
-
${formatReviewToolInput(changeInfo)}`;
|
|
79937
|
-
return await agentWorkflow({
|
|
79938
|
-
systemPrompt: CODE_REVIEW_SYSTEM_PROMPT,
|
|
79939
|
-
userMessage: [{ role: "user", content: userMessage }],
|
|
79940
|
-
tools: [readFile_default, readBinaryFile_default, searchFiles_default, listFiles_default, gitDiff_default, readMemory_default, updateMemory_default, listMemoryTopics_default],
|
|
79941
|
-
outputSchema: reviewOutputSchema
|
|
79942
|
-
}, context);
|
|
79943
|
-
});
|
|
79944
|
-
if (reviewAgentResult.type !== "Exit" /* Exit */) {
|
|
79945
|
-
logger.error(`\uD83D\uDEAB Review agent failed with status: ${reviewAgentResult.type}.`);
|
|
79946
|
-
break;
|
|
79947
|
-
}
|
|
79948
|
-
const reviewResult = reviewAgentResult.object;
|
|
79949
|
-
if (!reviewResult || !reviewResult.specificReviews || reviewResult.specificReviews.length === 0) {
|
|
79950
|
-
logger.info(`✅ Review passed. No issues found.
|
|
79951
|
-
`);
|
|
79952
|
-
return { passed: true };
|
|
79953
|
-
}
|
|
79954
|
-
logger.warn(`⚠️ Review found ${reviewResult.specificReviews.length} issue(s). Attempting to fix...
|
|
79955
|
-
`);
|
|
79956
|
-
reviewResult.specificReviews.forEach((review, idx) => {
|
|
79957
|
-
logger.warn(` ${idx + 1}. ${review.file}:${review.lines}`);
|
|
79958
|
-
});
|
|
79959
|
-
logger.warn("");
|
|
79960
|
-
const reviewSummary = reviewResult.specificReviews.map((r) => `File: ${r.file} (lines: ${r.lines})
|
|
79961
|
-
Review: ${r.review}`).join(`
|
|
79962
|
-
|
|
79963
|
-
`);
|
|
79964
|
-
const fixTask = `You are working on an epic. The original task was: "${taskItem}".
|
|
79965
|
-
|
|
79966
|
-
Here is the full plan for context:
|
|
79967
|
-
<plan>
|
|
79968
|
-
${currentPlan}
|
|
79969
|
-
</plan>
|
|
79970
|
-
|
|
79971
|
-
After an initial implementation, a review found the following issues. Please fix them:
|
|
79972
|
-
|
|
79973
|
-
${reviewSummary}`;
|
|
79974
|
-
await step(`fix-${iterationCount}-${i}`, async () => {
|
|
79975
|
-
await codeWorkflow({ task: fixTask, mode: "noninteractive" }, context);
|
|
79976
|
-
});
|
|
79977
|
-
await step(`commit-fix-${iterationCount}-${i}`, async () => {
|
|
79978
|
-
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
79979
|
-
await tools2.executeCommand({ command: "git", args: ["commit", "--amend", "--no-edit"] });
|
|
79980
|
-
});
|
|
79981
|
-
if (i === MAX_REVIEW_RETRIES - 1) {
|
|
79982
|
-
logger.error(`
|
|
79983
|
-
\uD83D\uDEAB Max retries (${MAX_REVIEW_RETRIES}) reached. Moving to the next task, but issues might remain.
|
|
79984
|
-
`);
|
|
79985
|
-
return { passed: false };
|
|
79986
|
-
}
|
|
79987
|
-
}
|
|
79988
|
-
return { passed: false };
|
|
79989
|
-
}
|
|
79990
80226
|
async function createPlan2(input2, context) {
|
|
79991
80227
|
const { task, plan, files, feedback } = input2;
|
|
79992
80228
|
const content = [{ type: "text", text: getPlanPrompt(task, plan) }];
|
|
@@ -80036,37 +80272,113 @@ ${feedback}`
|
|
|
80036
80272
|
}
|
|
80037
80273
|
return { plan: "", reason: "Usage limit exceeded.", type: "Exit" /* Exit */, branchName: "" };
|
|
80038
80274
|
}
|
|
80039
|
-
async function
|
|
80040
|
-
const
|
|
80041
|
-
|
|
80042
|
-
|
|
80043
|
-
|
|
80044
|
-
|
|
80045
|
-
|
|
80046
|
-
|
|
80047
|
-
|
|
80048
|
-
|
|
80049
|
-
|
|
80050
|
-
|
|
80051
|
-
|
|
80052
|
-
|
|
80053
|
-
|
|
80054
|
-
|
|
80055
|
-
|
|
80056
|
-
|
|
80057
|
-
|
|
80058
|
-
|
|
80059
|
-
|
|
80060
|
-
|
|
80061
|
-
|
|
80062
|
-
|
|
80275
|
+
async function createAndApprovePlan(task, context) {
|
|
80276
|
+
const { logger, step, tools: tools2 } = context;
|
|
80277
|
+
logger.info(`\uD83D\uDCDD Phase 2: Creating high-level plan...
|
|
80278
|
+
`);
|
|
80279
|
+
let feedback;
|
|
80280
|
+
let highLevelPlan;
|
|
80281
|
+
let branchName;
|
|
80282
|
+
let planAttempt = 1;
|
|
80283
|
+
try {
|
|
80284
|
+
while (true) {
|
|
80285
|
+
const result = await step(`plan-${planAttempt}`, () => createPlan2({ task, feedback }, context));
|
|
80286
|
+
planAttempt++;
|
|
80287
|
+
if (result.question) {
|
|
80288
|
+
const answer = await tools2.input({
|
|
80289
|
+
message: result.question.question,
|
|
80290
|
+
default: result.question.defaultAnswer || undefined
|
|
80291
|
+
});
|
|
80292
|
+
feedback = `The user answered the question "${result.question.question}" with: "${answer}"`;
|
|
80293
|
+
continue;
|
|
80294
|
+
}
|
|
80295
|
+
if (!result.plan) {
|
|
80296
|
+
if (result.reason) {
|
|
80297
|
+
logger.info(`No plan created. Reason: ${result.reason}`);
|
|
80298
|
+
} else {
|
|
80299
|
+
logger.info("No plan created.");
|
|
80300
|
+
}
|
|
80301
|
+
return null;
|
|
80302
|
+
}
|
|
80303
|
+
logger.info(`\uD83D\uDCDD Plan:
|
|
80304
|
+
${result.plan}`);
|
|
80305
|
+
if (result.branchName) {
|
|
80306
|
+
logger.info(`\uD83C\uDF3F Suggested branch name: ${result.branchName}`);
|
|
80307
|
+
}
|
|
80308
|
+
feedback = await tools2.input({ message: "Press Enter to approve the plan, or provide feedback to refine it." });
|
|
80309
|
+
if (feedback.trim() === "") {
|
|
80310
|
+
highLevelPlan = result.plan;
|
|
80311
|
+
branchName = result.branchName;
|
|
80312
|
+
break;
|
|
80313
|
+
}
|
|
80314
|
+
}
|
|
80315
|
+
} catch (e) {
|
|
80316
|
+
if (e instanceof UserCancelledError) {
|
|
80317
|
+
logger.info("Plan creation cancelled by user.");
|
|
80318
|
+
return null;
|
|
80319
|
+
}
|
|
80320
|
+
throw e;
|
|
80063
80321
|
}
|
|
80064
|
-
|
|
80065
|
-
|
|
80066
|
-
|
|
80067
|
-
|
|
80068
|
-
|
|
80069
|
-
|
|
80322
|
+
if (!highLevelPlan) {
|
|
80323
|
+
logger.info("Plan not approved. Exiting.");
|
|
80324
|
+
return null;
|
|
80325
|
+
}
|
|
80326
|
+
if (!branchName) {
|
|
80327
|
+
logger.error("❌ Error: No branch name was generated from the plan. Exiting.");
|
|
80328
|
+
return null;
|
|
80329
|
+
}
|
|
80330
|
+
logger.info(`✅ High-level plan approved.
|
|
80331
|
+
`);
|
|
80332
|
+
return { plan: highLevelPlan, branchName };
|
|
80333
|
+
}
|
|
80334
|
+
async function createFeatureBranch(branchName, context) {
|
|
80335
|
+
const { logger, step, tools: tools2 } = context;
|
|
80336
|
+
logger.info(`\uD83C\uDF3F Phase 3: Creating feature branch...
|
|
80337
|
+
`);
|
|
80338
|
+
let finalBranchName = branchName;
|
|
80339
|
+
const initialCheckResult = await step("checkBranch-initial", async () => await tools2.executeCommand({ command: "git", args: ["rev-parse", "--verify", finalBranchName] }));
|
|
80340
|
+
if (initialCheckResult.exitCode === 0) {
|
|
80341
|
+
logger.warn(`⚠️ Branch '${finalBranchName}' already exists. Trying to find an available name...`);
|
|
80342
|
+
const suffixMatch = branchName.match(/-(\d+)$/);
|
|
80343
|
+
let baseName = branchName;
|
|
80344
|
+
let counter = 2;
|
|
80345
|
+
if (suffixMatch) {
|
|
80346
|
+
baseName = branchName.substring(0, suffixMatch.index);
|
|
80347
|
+
counter = parseInt(suffixMatch[1], 10) + 1;
|
|
80348
|
+
}
|
|
80349
|
+
while (true) {
|
|
80350
|
+
finalBranchName = `${baseName}-${counter}`;
|
|
80351
|
+
const branchCheckResult = await step(`checkBranch-${counter}`, async () => await tools2.executeCommand({ command: "git", args: ["rev-parse", "--verify", finalBranchName] }));
|
|
80352
|
+
if (branchCheckResult.exitCode !== 0) {
|
|
80353
|
+
break;
|
|
80354
|
+
}
|
|
80355
|
+
counter++;
|
|
80356
|
+
}
|
|
80357
|
+
}
|
|
80358
|
+
if (finalBranchName !== branchName) {
|
|
80359
|
+
logger.info(`Branch name '${branchName}' was taken. Using '${finalBranchName}' instead.`);
|
|
80360
|
+
}
|
|
80361
|
+
await step("createBranch", async () => await tools2.executeCommand({ command: "git", args: ["checkout", "-b", finalBranchName] }));
|
|
80362
|
+
logger.info(`✅ Branch '${finalBranchName}' created.
|
|
80363
|
+
`);
|
|
80364
|
+
return { success: true, branchName: finalBranchName };
|
|
80365
|
+
}
|
|
80366
|
+
async function addTodoItemsFromPlan(plan, context) {
|
|
80367
|
+
const { logger, step, tools: tools2 } = context;
|
|
80368
|
+
logger.info(`\uD83D\uDCDD Phase 4: Creating todo items from plan...
|
|
80369
|
+
`);
|
|
80370
|
+
await step("add-todo-items", async () => {
|
|
80371
|
+
await agentWorkflow({
|
|
80372
|
+
systemPrompt: EPIC_ADD_TODO_ITEMS_SYSTEM_PROMPT,
|
|
80373
|
+
userMessage: [{ role: "user", content: `Please create the todo items based on the plan
|
|
80374
|
+
<plan>
|
|
80375
|
+
${plan}</plan>` }],
|
|
80376
|
+
tools: [readFile_default, searchFiles_default, listFiles_default, readMemory_default, getTodoItem_default, listTodoItems_default, updateTodoItem_default, updateMemory_default, listMemoryTopics_default]
|
|
80377
|
+
}, context);
|
|
80378
|
+
});
|
|
80379
|
+
const todos = await tools2.listTodoItems({});
|
|
80380
|
+
logger.info(`✅ Created ${todos.length} todo items.
|
|
80381
|
+
`);
|
|
80070
80382
|
}
|
|
80071
80383
|
async function runPreflightChecks(context) {
|
|
80072
80384
|
const { logger, step, tools: tools2 } = context;
|
|
@@ -80088,264 +80400,336 @@ async function runPreflightChecks(context) {
|
|
|
80088
80400
|
`);
|
|
80089
80401
|
return { success: true };
|
|
80090
80402
|
}
|
|
80091
|
-
|
|
80403
|
+
async function performReviewAndFixCycle(iterationCount, taskItem, highLevelPlan, context) {
|
|
80092
80404
|
const { logger, step, tools: tools2 } = context;
|
|
80093
|
-
|
|
80094
|
-
|
|
80095
|
-
|
|
80096
|
-
|
|
80097
|
-
|
|
80098
|
-
return;
|
|
80099
|
-
}
|
|
80100
|
-
const preflightResult = await runPreflightChecks(context);
|
|
80101
|
-
if (!preflightResult.success) {
|
|
80102
|
-
return;
|
|
80103
|
-
}
|
|
80104
|
-
async function createAndApprovePlan(task2, context2) {
|
|
80105
|
-
const { logger: logger2, step: step2, tools: tools3 } = context2;
|
|
80106
|
-
logger2.info(`\uD83D\uDCDD Phase 2: Creating high-level plan...
|
|
80405
|
+
for (let i = 0;i < MAX_REVIEW_RETRIES; i++) {
|
|
80406
|
+
const diffResult = await tools2.executeCommand({ command: "git", args: ["diff", "--name-status", "HEAD~1", "HEAD"] });
|
|
80407
|
+
const changedFiles = parseGitDiffNameStatus(diffResult.stdout);
|
|
80408
|
+
if (changedFiles.length === 0) {
|
|
80409
|
+
logger.info(`ℹ️ No files were changed. Skipping review.
|
|
80107
80410
|
`);
|
|
80108
|
-
|
|
80109
|
-
let highLevelPlan2;
|
|
80110
|
-
let branchName2;
|
|
80111
|
-
let planAttempt = 1;
|
|
80112
|
-
try {
|
|
80113
|
-
while (true) {
|
|
80114
|
-
const result = await step2(`plan-${planAttempt}`, () => createPlan2({ task: task2, feedback }, context2));
|
|
80115
|
-
planAttempt++;
|
|
80116
|
-
if (result.question) {
|
|
80117
|
-
const answer = await tools3.input({
|
|
80118
|
-
message: result.question.question,
|
|
80119
|
-
default: result.question.defaultAnswer || undefined
|
|
80120
|
-
});
|
|
80121
|
-
feedback = `The user answered the question "${result.question.question}" with: "${answer}"`;
|
|
80122
|
-
continue;
|
|
80123
|
-
}
|
|
80124
|
-
if (!result.plan) {
|
|
80125
|
-
if (result.reason) {
|
|
80126
|
-
logger2.info(`No plan created. Reason: ${result.reason}`);
|
|
80127
|
-
} else {
|
|
80128
|
-
logger2.info("No plan created.");
|
|
80129
|
-
}
|
|
80130
|
-
return null;
|
|
80131
|
-
}
|
|
80132
|
-
logger2.info(`\uD83D\uDCDD Plan:
|
|
80133
|
-
${result.plan}`);
|
|
80134
|
-
if (result.branchName) {
|
|
80135
|
-
logger2.info(`\uD83C\uDF3F Suggested branch name: ${result.branchName}`);
|
|
80136
|
-
}
|
|
80137
|
-
feedback = await tools3.input({ message: "Press Enter to approve the plan, or provide feedback to refine it." });
|
|
80138
|
-
if (feedback.trim() === "") {
|
|
80139
|
-
highLevelPlan2 = result.plan;
|
|
80140
|
-
branchName2 = result.branchName;
|
|
80141
|
-
break;
|
|
80142
|
-
}
|
|
80143
|
-
}
|
|
80144
|
-
} catch (e) {
|
|
80145
|
-
if (e instanceof UserCancelledError) {
|
|
80146
|
-
logger2.info("Plan creation cancelled by user.");
|
|
80147
|
-
return null;
|
|
80148
|
-
}
|
|
80149
|
-
throw e;
|
|
80150
|
-
}
|
|
80151
|
-
if (!highLevelPlan2) {
|
|
80152
|
-
logger2.info("Plan not approved. Exiting.");
|
|
80153
|
-
return null;
|
|
80411
|
+
return { passed: true };
|
|
80154
80412
|
}
|
|
80155
|
-
|
|
80156
|
-
|
|
80157
|
-
|
|
80413
|
+
logger.info(`
|
|
80414
|
+
\uD83D\uDD0E Review iteration ${i + 1}/${MAX_REVIEW_RETRIES}`);
|
|
80415
|
+
logger.info(` Changed files: ${changedFiles.length}`);
|
|
80416
|
+
const changeInfo = {
|
|
80417
|
+
commitRange: "HEAD~1...HEAD",
|
|
80418
|
+
changedFiles
|
|
80419
|
+
};
|
|
80420
|
+
const reviewAgentResult = await step(`review-${iterationCount}-${i}`, async () => {
|
|
80421
|
+
const defaultContext = await getDefaultContext();
|
|
80422
|
+
const memoryContext = await tools2.getMemoryContext();
|
|
80423
|
+
const userMessage = `${defaultContext}
|
|
80424
|
+
${memoryContext}
|
|
80425
|
+
|
|
80426
|
+
${formatReviewToolInput(changeInfo)}`;
|
|
80427
|
+
return await agentWorkflow({
|
|
80428
|
+
systemPrompt: CODE_REVIEW_SYSTEM_PROMPT,
|
|
80429
|
+
userMessage: [{ role: "user", content: userMessage }],
|
|
80430
|
+
tools: [readFile_default, readBinaryFile_default, searchFiles_default, listFiles_default, gitDiff_default, readMemory_default, updateMemory_default, listMemoryTopics_default],
|
|
80431
|
+
outputSchema: reviewOutputSchema
|
|
80432
|
+
}, context);
|
|
80433
|
+
});
|
|
80434
|
+
if (reviewAgentResult.type !== "Exit" /* Exit */) {
|
|
80435
|
+
logger.error(`\uD83D\uDEAB Review agent failed with status: ${reviewAgentResult.type}.`);
|
|
80436
|
+
break;
|
|
80158
80437
|
}
|
|
80159
|
-
|
|
80160
|
-
|
|
80161
|
-
|
|
80162
|
-
}
|
|
80163
|
-
const planResult = await createAndApprovePlan(task, context);
|
|
80164
|
-
if (!planResult) {
|
|
80165
|
-
return;
|
|
80166
|
-
}
|
|
80167
|
-
const highLevelPlan = planResult.plan;
|
|
80168
|
-
let branchName = planResult.branchName;
|
|
80169
|
-
async function createFeatureBranch(branchName2, task2, plan, context2) {
|
|
80170
|
-
const { logger: logger2, step: step2, tools: tools3 } = context2;
|
|
80171
|
-
logger2.info(`\uD83C\uDF3F Phase 3: Creating feature branch...
|
|
80438
|
+
const reviewResult = reviewAgentResult.object;
|
|
80439
|
+
if (!reviewResult || !reviewResult.specificReviews || reviewResult.specificReviews.length === 0) {
|
|
80440
|
+
logger.info(`✅ Review passed. No issues found.
|
|
80172
80441
|
`);
|
|
80173
|
-
|
|
80174
|
-
if (!branchValidation.valid) {
|
|
80175
|
-
logger2.error(`❌ Error: ${branchValidation.error}`);
|
|
80176
|
-
return { success: false, branchName: null };
|
|
80177
|
-
}
|
|
80178
|
-
let finalBranchName = branchName2;
|
|
80179
|
-
const initialCheckResult = await step2("checkBranch-initial", async () => tools3.executeCommand({ command: "git", args: ["rev-parse", "--verify", finalBranchName] }));
|
|
80180
|
-
if (initialCheckResult.exitCode === 0) {
|
|
80181
|
-
logger2.warn(`⚠️ Branch '${finalBranchName}' already exists. Trying to find an available name...`);
|
|
80182
|
-
const suffixMatch = branchName2.match(/-(\d+)$/);
|
|
80183
|
-
let baseName = branchName2;
|
|
80184
|
-
let counter = 2;
|
|
80185
|
-
if (suffixMatch) {
|
|
80186
|
-
baseName = branchName2.substring(0, suffixMatch.index);
|
|
80187
|
-
counter = parseInt(suffixMatch[1], 10) + 1;
|
|
80188
|
-
}
|
|
80189
|
-
while (true) {
|
|
80190
|
-
finalBranchName = `${baseName}-${counter}`;
|
|
80191
|
-
const branchCheckResult = await step2(`checkBranch-${counter}`, async () => tools3.executeCommand({ command: "git", args: ["rev-parse", "--verify", finalBranchName] }));
|
|
80192
|
-
if (branchCheckResult.exitCode !== 0) {
|
|
80193
|
-
break;
|
|
80194
|
-
}
|
|
80195
|
-
counter++;
|
|
80196
|
-
}
|
|
80442
|
+
return { passed: true };
|
|
80197
80443
|
}
|
|
80198
|
-
|
|
80199
|
-
|
|
80444
|
+
logger.warn(`⚠️ Review found ${reviewResult.specificReviews.length} issue(s). Attempting to fix...
|
|
80445
|
+
`);
|
|
80446
|
+
for (const [idx, review] of reviewResult.specificReviews.entries()) {
|
|
80447
|
+
logger.warn(` ${idx + 1}. ${review.file}:${review.lines}`);
|
|
80200
80448
|
}
|
|
80201
|
-
|
|
80202
|
-
|
|
80449
|
+
logger.warn("");
|
|
80450
|
+
const reviewSummary = reviewResult.specificReviews.map((r) => `File: ${r.file} (lines: ${r.lines})
|
|
80451
|
+
Review: ${r.review}`).join(`
|
|
80452
|
+
|
|
80203
80453
|
`);
|
|
80204
|
-
|
|
80205
|
-
|
|
80206
|
-
|
|
80207
|
-
|
|
80208
|
-
|
|
80209
|
-
|
|
80454
|
+
const fixTask = `You are working on an epic. The original task was: "${taskItem}".
|
|
80455
|
+
|
|
80456
|
+
Here is the full plan for context:
|
|
80457
|
+
<plan>
|
|
80458
|
+
${highLevelPlan}
|
|
80459
|
+
</plan>
|
|
80460
|
+
|
|
80461
|
+
After an initial implementation, a review found the following issues. Please fix them:
|
|
80462
|
+
|
|
80463
|
+
${reviewSummary}`;
|
|
80464
|
+
await step(`fix-${iterationCount}-${i}`, async () => {
|
|
80465
|
+
await codeWorkflow({ task: fixTask, mode: "noninteractive" }, context);
|
|
80210
80466
|
});
|
|
80211
|
-
await
|
|
80212
|
-
|
|
80213
|
-
|
|
80214
|
-
|
|
80215
|
-
|
|
80216
|
-
|
|
80467
|
+
await step(`commit-fix-${iterationCount}-${i}`, async () => {
|
|
80468
|
+
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
80469
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "--amend", "--no-edit"] });
|
|
80470
|
+
});
|
|
80471
|
+
if (i === MAX_REVIEW_RETRIES - 1) {
|
|
80472
|
+
logger.error(`
|
|
80473
|
+
\uD83D\uDEAB Max retries (${MAX_REVIEW_RETRIES}) reached. Moving to the next task, but issues might remain.
|
|
80474
|
+
`);
|
|
80475
|
+
return { passed: false };
|
|
80476
|
+
}
|
|
80217
80477
|
}
|
|
80218
|
-
|
|
80219
|
-
|
|
80478
|
+
return { passed: false };
|
|
80479
|
+
}
|
|
80480
|
+
async function runImplementationLoop(context, highLevelPlan) {
|
|
80481
|
+
const { logger, step, tools: tools2 } = context;
|
|
80482
|
+
const commitMessages = [];
|
|
80483
|
+
logger.info(`\uD83D\uDE80 Phase 5: Iterative Implementation Loop...
|
|
80220
80484
|
`);
|
|
80221
80485
|
logger.info(`${"=".repeat(80)}
|
|
80222
80486
|
`);
|
|
80223
|
-
let currentPlan = highLevelPlan;
|
|
80224
80487
|
let iterationCount = 0;
|
|
80225
80488
|
let isComplete = false;
|
|
80226
80489
|
let nextTask = null;
|
|
80227
|
-
|
|
80228
|
-
|
|
80229
|
-
|
|
80230
|
-
|
|
80231
|
-
|
|
80232
|
-
|
|
80233
|
-
|
|
80234
|
-
|
|
80235
|
-
|
|
80236
|
-
|
|
80237
|
-
|
|
80490
|
+
let nextTaskId = null;
|
|
80491
|
+
const initialTasks = await step("get-initial-tasks", async () => {
|
|
80492
|
+
return await tools2.listTodoItems({ status: "open" });
|
|
80493
|
+
});
|
|
80494
|
+
if (initialTasks.length > 0) {
|
|
80495
|
+
const firstTask = initialTasks[0];
|
|
80496
|
+
nextTask = firstTask.title;
|
|
80497
|
+
nextTaskId = firstTask.id;
|
|
80498
|
+
} else {
|
|
80499
|
+
isComplete = true;
|
|
80500
|
+
}
|
|
80501
|
+
while (!isComplete && nextTask && nextTaskId) {
|
|
80502
|
+
iterationCount++;
|
|
80503
|
+
const taskStartTime = Date.now();
|
|
80504
|
+
logger.info(`
|
|
80238
80505
|
${"━".repeat(80)}`);
|
|
80239
|
-
|
|
80240
|
-
|
|
80241
|
-
|
|
80506
|
+
logger.info(`\uD83D\uDCCC Iteration ${iterationCount}`);
|
|
80507
|
+
logger.info(`${"━".repeat(80)}`);
|
|
80508
|
+
logger.info(`${nextTask}
|
|
80242
80509
|
`);
|
|
80243
|
-
|
|
80244
|
-
const
|
|
80245
|
-
const taskWithContext = `You are working on an epic. Here is the full plan:
|
|
80510
|
+
await step(`task-${iterationCount}`, async () => {
|
|
80511
|
+
const taskWithContext = `You are working on an epic. Here is the full plan:
|
|
80246
80512
|
|
|
80247
80513
|
<plan>
|
|
80248
|
-
${
|
|
80514
|
+
${highLevelPlan}
|
|
80249
80515
|
</plan>
|
|
80250
80516
|
|
|
80251
80517
|
Your current task is to implement this specific item:
|
|
80252
80518
|
${nextTask}
|
|
80253
80519
|
|
|
80254
80520
|
Focus only on this item, but use the plan for context.`;
|
|
80255
|
-
|
|
80256
|
-
|
|
80257
|
-
|
|
80258
|
-
|
|
80259
|
-
|
|
80260
|
-
|
|
80261
|
-
|
|
80262
|
-
|
|
80263
|
-
|
|
80264
|
-
|
|
80265
|
-
|
|
80266
|
-
|
|
80267
|
-
});
|
|
80268
|
-
|
|
80269
|
-
|
|
80270
|
-
|
|
80271
|
-
|
|
80272
|
-
if (
|
|
80273
|
-
|
|
80274
|
-
} else {
|
|
80275
|
-
logger.warn(`⚠️ Iteration ${iterationCount} completed with potential issues (${taskElapsedTime})`);
|
|
80276
|
-
}
|
|
80277
|
-
const updateResult = await step(`update-plan-${iterationCount}`, async () => {
|
|
80278
|
-
return await updatePlanAgent(currentPlan, implementationSummary, nextTask ?? "", context);
|
|
80279
|
-
});
|
|
80280
|
-
currentPlan = updateResult.updatedPlan;
|
|
80281
|
-
isComplete = updateResult.isComplete;
|
|
80282
|
-
nextTask = updateResult.nextTask;
|
|
80283
|
-
await tools2.updateMemory({ operation: "replace", topic: "epic-plan", content: currentPlan });
|
|
80284
|
-
const checkboxCompleted = (currentPlan.match(/- \[x\]/g) || []).length;
|
|
80285
|
-
const checkboxTotal = (currentPlan.match(/- \[[x ]\]/g) || []).length;
|
|
80286
|
-
const checkmarkCompleted = (currentPlan.match(/^✅/gm) || []).length;
|
|
80287
|
-
let progressMessage = "";
|
|
80288
|
-
if (checkboxTotal > 0) {
|
|
80289
|
-
progressMessage = `${checkboxCompleted}/${checkboxTotal} items completed`;
|
|
80290
|
-
} else if (checkmarkCompleted > 0) {
|
|
80291
|
-
progressMessage = `${checkmarkCompleted} items completed`;
|
|
80292
|
-
} else {
|
|
80293
|
-
progressMessage = `Iteration ${iterationCount} completed`;
|
|
80521
|
+
return await codeWorkflow({ task: taskWithContext, mode: "noninteractive" }, context);
|
|
80522
|
+
});
|
|
80523
|
+
const commitMessage = `feat: ${nextTask}`;
|
|
80524
|
+
await step(`commit-initial-${iterationCount}`, async () => {
|
|
80525
|
+
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
80526
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "-m", commitMessage] });
|
|
80527
|
+
});
|
|
80528
|
+
commitMessages.push(commitMessage);
|
|
80529
|
+
const { passed: reviewPassed } = await performReviewAndFixCycle(iterationCount, nextTask, highLevelPlan, context);
|
|
80530
|
+
const taskElapsed = Date.now() - taskStartTime;
|
|
80531
|
+
const taskElapsedTime = formatElapsedTime(taskElapsed);
|
|
80532
|
+
if (reviewPassed) {
|
|
80533
|
+
logger.info(`✅ Iteration ${iterationCount} completed successfully (${taskElapsedTime})`);
|
|
80534
|
+
} else {
|
|
80535
|
+
logger.warn(`⚠️ Iteration ${iterationCount} completed with potential issues (${taskElapsedTime})`);
|
|
80536
|
+
}
|
|
80537
|
+
await step(`update-task-status-${iterationCount}`, async () => {
|
|
80538
|
+
if (!nextTaskId) {
|
|
80539
|
+
throw new Error("Invariant violation: nextTaskId is null inside the implementation loop.");
|
|
80294
80540
|
}
|
|
80295
|
-
|
|
80541
|
+
await tools2.updateTodoItem({ operation: "update", id: nextTaskId, status: "completed" });
|
|
80542
|
+
});
|
|
80543
|
+
const openTasks = await step(`get-next-task-${iterationCount}`, async () => {
|
|
80544
|
+
return await tools2.listTodoItems({ status: "open" });
|
|
80545
|
+
});
|
|
80546
|
+
if (openTasks.length > 0) {
|
|
80547
|
+
const nextTodo = openTasks[0];
|
|
80548
|
+
nextTask = nextTodo.title;
|
|
80549
|
+
nextTaskId = nextTodo.id;
|
|
80550
|
+
isComplete = false;
|
|
80551
|
+
} else {
|
|
80552
|
+
nextTask = null;
|
|
80553
|
+
nextTaskId = null;
|
|
80554
|
+
isComplete = true;
|
|
80555
|
+
}
|
|
80556
|
+
const allTodos = await tools2.listTodoItems({});
|
|
80557
|
+
const completedTodos = allTodos.filter((t) => t.status === "completed").length;
|
|
80558
|
+
const totalTodos = allTodos.length;
|
|
80559
|
+
let progressMessage = "";
|
|
80560
|
+
if (totalTodos > 0) {
|
|
80561
|
+
progressMessage = `${completedTodos}/${totalTodos} items completed`;
|
|
80562
|
+
} else {
|
|
80563
|
+
progressMessage = `Iteration ${iterationCount} completed`;
|
|
80564
|
+
}
|
|
80565
|
+
logger.info(`
|
|
80296
80566
|
\uD83D\uDCCA Progress: ${progressMessage}`);
|
|
80297
|
-
|
|
80298
|
-
|
|
80567
|
+
if (isComplete) {
|
|
80568
|
+
logger.info(`✅ All tasks complete!
|
|
80299
80569
|
`);
|
|
80300
|
-
|
|
80301
|
-
|
|
80302
|
-
|
|
80303
|
-
|
|
80570
|
+
break;
|
|
80571
|
+
}
|
|
80572
|
+
if (nextTask) {
|
|
80573
|
+
logger.info(`\uD83D\uDCCC Next task: ${nextTask}
|
|
80304
80574
|
`);
|
|
80305
|
-
|
|
80306
|
-
|
|
80575
|
+
}
|
|
80576
|
+
logger.info(`${"━".repeat(80)}
|
|
80577
|
+
`);
|
|
80578
|
+
}
|
|
80579
|
+
return commitMessages;
|
|
80580
|
+
}
|
|
80581
|
+
async function performFinalReviewAndFix(context, highLevelPlan) {
|
|
80582
|
+
const { logger, step, tools: tools2 } = context;
|
|
80583
|
+
logger.info(`
|
|
80584
|
+
Phase 6: Final Review and Fixup...
|
|
80585
|
+
`);
|
|
80586
|
+
const ghCheckResult = await tools2.executeCommand({ command: "gh", args: ["--version"] });
|
|
80587
|
+
if (ghCheckResult.exitCode !== 0) {
|
|
80588
|
+
logger.warn("⚠️ GitHub CLI (gh) is not installed. Skipping final review step. Please install it from https://cli.github.com/ to enable final reviews.");
|
|
80589
|
+
return { passed: true };
|
|
80590
|
+
}
|
|
80591
|
+
const defaultBranchResult = await tools2.executeCommand({
|
|
80592
|
+
command: "gh",
|
|
80593
|
+
args: ["repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"]
|
|
80594
|
+
});
|
|
80595
|
+
const defaultBranch = defaultBranchResult.stdout.trim();
|
|
80596
|
+
const currentBranchResult = await tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] });
|
|
80597
|
+
const currentBranch = currentBranchResult.stdout.trim();
|
|
80598
|
+
if (currentBranch === defaultBranch) {
|
|
80599
|
+
logger.info(`✅ You are on the default branch ('${defaultBranch}'). No final review needed.`);
|
|
80600
|
+
return { passed: true };
|
|
80601
|
+
}
|
|
80602
|
+
const commitRange = `${defaultBranch}...${currentBranch}`;
|
|
80603
|
+
for (let i = 0;i < MAX_REVIEW_RETRIES; i++) {
|
|
80604
|
+
const diffResult = await tools2.executeCommand({ command: "git", args: ["diff", "--name-status", commitRange] });
|
|
80605
|
+
const changedFiles = parseGitDiffNameStatus(diffResult.stdout);
|
|
80606
|
+
if (changedFiles.length === 0) {
|
|
80607
|
+
logger.info(`ℹ️ No files have been changed in this branch. Skipping final review.
|
|
80608
|
+
`);
|
|
80609
|
+
return { passed: true };
|
|
80610
|
+
}
|
|
80611
|
+
logger.info(`
|
|
80612
|
+
\uD83D\uDD0E Final review iteration ${i + 1}/${MAX_REVIEW_RETRIES}`);
|
|
80613
|
+
logger.info(` Changed files: ${changedFiles.length}`);
|
|
80614
|
+
const changeInfo = {
|
|
80615
|
+
commitRange,
|
|
80616
|
+
changedFiles
|
|
80617
|
+
};
|
|
80618
|
+
const reviewAgentResult = await step(`final-review-${i}`, async () => {
|
|
80619
|
+
const defaultContext = await getDefaultContext();
|
|
80620
|
+
const memoryContext = await tools2.getMemoryContext();
|
|
80621
|
+
const userMessage = `${defaultContext}
|
|
80622
|
+
${memoryContext}
|
|
80623
|
+
|
|
80624
|
+
${formatReviewToolInput(changeInfo)}`;
|
|
80625
|
+
return await agentWorkflow({
|
|
80626
|
+
systemPrompt: CODE_REVIEW_SYSTEM_PROMPT,
|
|
80627
|
+
userMessage: [{ role: "user", content: userMessage }],
|
|
80628
|
+
tools: [readFile_default, readBinaryFile_default, searchFiles_default, listFiles_default, gitDiff_default, readMemory_default, updateMemory_default, listMemoryTopics_default],
|
|
80629
|
+
outputSchema: reviewOutputSchema
|
|
80630
|
+
}, context);
|
|
80631
|
+
});
|
|
80632
|
+
if (reviewAgentResult.type !== "Exit" /* Exit */) {
|
|
80633
|
+
logger.error(`\uD83D\uDEAB Review agent failed with status: ${reviewAgentResult.type}.`);
|
|
80634
|
+
break;
|
|
80635
|
+
}
|
|
80636
|
+
const reviewResult = reviewAgentResult.object;
|
|
80637
|
+
if (!reviewResult || !reviewResult.specificReviews || reviewResult.specificReviews.length === 0) {
|
|
80638
|
+
logger.info(`✅ Final review passed. No issues found.
|
|
80639
|
+
`);
|
|
80640
|
+
return { passed: true };
|
|
80641
|
+
}
|
|
80642
|
+
logger.warn(`⚠️ Final review found ${reviewResult.specificReviews.length} issue(s). Attempting to fix...
|
|
80643
|
+
`);
|
|
80644
|
+
for (const [idx, review] of reviewResult.specificReviews.entries()) {
|
|
80645
|
+
logger.warn(` ${idx + 1}. ${review.file}:${review.lines}`);
|
|
80646
|
+
}
|
|
80647
|
+
logger.warn("");
|
|
80648
|
+
const reviewSummary = reviewResult.specificReviews.map((r) => `File: ${r.file} (lines: ${r.lines})
|
|
80649
|
+
Review: ${r.review}`).join(`
|
|
80650
|
+
|
|
80651
|
+
`);
|
|
80652
|
+
const fixTask = `You are working on an epic. The original task was to implement a feature based on this plan:
|
|
80653
|
+
|
|
80654
|
+
<plan>
|
|
80655
|
+
${highLevelPlan}
|
|
80656
|
+
</plan>
|
|
80657
|
+
|
|
80658
|
+
A final review of all the changes in the branch found the following issues. Please fix them:
|
|
80659
|
+
|
|
80660
|
+
${reviewSummary}`;
|
|
80661
|
+
await step(`final-fix-${i}`, async () => {
|
|
80662
|
+
await codeWorkflow({ task: fixTask, mode: "noninteractive" }, context);
|
|
80663
|
+
});
|
|
80664
|
+
await step(`commit-final-fix-${i}`, async () => {
|
|
80665
|
+
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
80666
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "-m", "chore: apply automated review feedback"] });
|
|
80667
|
+
});
|
|
80668
|
+
if (i === MAX_REVIEW_RETRIES - 1) {
|
|
80669
|
+
logger.error(`
|
|
80670
|
+
\uD83D\uDEAB Max retries (${MAX_REVIEW_RETRIES}) reached for final review. Issues might remain.
|
|
80307
80671
|
`);
|
|
80672
|
+
return { passed: false };
|
|
80673
|
+
}
|
|
80674
|
+
}
|
|
80675
|
+
return { passed: false };
|
|
80676
|
+
}
|
|
80677
|
+
var epicWorkflow = async (input2, context) => {
|
|
80678
|
+
const { logger } = context;
|
|
80679
|
+
const { task } = input2;
|
|
80680
|
+
const workflowStartTime = Date.now();
|
|
80681
|
+
let branchName = "";
|
|
80682
|
+
if (!task || task.trim() === "") {
|
|
80683
|
+
logger.error("❌ Error: Task cannot be empty. Please provide a valid task description.");
|
|
80684
|
+
return;
|
|
80685
|
+
}
|
|
80686
|
+
try {
|
|
80687
|
+
const preflightResult = await runPreflightChecks(context);
|
|
80688
|
+
if (!preflightResult.success) {
|
|
80689
|
+
return;
|
|
80690
|
+
}
|
|
80691
|
+
const planResult = await createAndApprovePlan(task, context);
|
|
80692
|
+
if (!planResult) {
|
|
80693
|
+
return;
|
|
80694
|
+
}
|
|
80695
|
+
const { plan: highLevelPlan } = planResult;
|
|
80696
|
+
branchName = planResult.branchName;
|
|
80697
|
+
const branchResult = await createFeatureBranch(branchName, context);
|
|
80698
|
+
if (!branchResult.success || !branchResult.branchName) {
|
|
80699
|
+
return;
|
|
80700
|
+
}
|
|
80701
|
+
branchName = branchResult.branchName;
|
|
80702
|
+
await addTodoItemsFromPlan(highLevelPlan, context);
|
|
80703
|
+
const commitMessages = await runImplementationLoop(context, highLevelPlan);
|
|
80704
|
+
await performFinalReviewAndFix(context, highLevelPlan);
|
|
80705
|
+
const totalElapsed = Date.now() - workflowStartTime;
|
|
80706
|
+
const totalElapsedTime = formatElapsedTime(totalElapsed);
|
|
80707
|
+
const iterationCount = commitMessages.length;
|
|
80708
|
+
logger.info(`
|
|
80709
|
+
${"=".repeat(80)}`);
|
|
80710
|
+
logger.info("\uD83C\uDF89 Epic Workflow Complete!");
|
|
80711
|
+
logger.info(`${"=".repeat(80)}`);
|
|
80712
|
+
logger.info(`
|
|
80713
|
+
\uD83D\uDCCA Summary:`);
|
|
80714
|
+
logger.info(` Total iterations: ${iterationCount}`);
|
|
80715
|
+
logger.info(` Total commits: ${commitMessages.length}`);
|
|
80716
|
+
logger.info(` Branch: ${branchName}`);
|
|
80717
|
+
logger.info(` Total time: ${totalElapsedTime}`);
|
|
80718
|
+
logger.info("\uD83D\uDCDD Commits created:");
|
|
80719
|
+
for (const [idx, msg] of commitMessages.entries()) {
|
|
80720
|
+
logger.info(` ${idx + 1}. ${msg}`);
|
|
80308
80721
|
}
|
|
80309
80722
|
} catch (error46) {
|
|
80310
80723
|
logger.error(`
|
|
80311
80724
|
❌ Epic workflow failed: ${error46 instanceof Error ? error46.message : String(error46)}`);
|
|
80312
|
-
|
|
80725
|
+
if (branchName) {
|
|
80726
|
+
logger.info(`
|
|
80313
80727
|
Branch '${branchName}' was created but work is incomplete.`);
|
|
80314
|
-
|
|
80728
|
+
logger.info(`To cleanup: git checkout <previous-branch> && git branch -D ${branchName}
|
|
80315
80729
|
`);
|
|
80316
|
-
|
|
80317
|
-
await tools2.updateMemory({ operation: "remove", topic: "epic-plan" });
|
|
80730
|
+
}
|
|
80318
80731
|
throw error46;
|
|
80319
80732
|
}
|
|
80320
|
-
const totalElapsed = Date.now() - workflowStartTime;
|
|
80321
|
-
const totalElapsedTime = formatElapsedTime(totalElapsed);
|
|
80322
|
-
const avgTimePerIteration = iterationCount > 0 ? formatElapsedTime(totalElapsed / iterationCount) : "N/A";
|
|
80323
|
-
logger.info(`
|
|
80324
|
-
${"=".repeat(80)}`);
|
|
80325
|
-
logger.info("\uD83C\uDF89 Epic Workflow Complete!");
|
|
80326
|
-
logger.info(`${"=".repeat(80)}`);
|
|
80327
|
-
logger.info(`
|
|
80328
|
-
\uD83D\uDCCA Summary:`);
|
|
80329
|
-
logger.info(` Total iterations: ${iterationCount}`);
|
|
80330
|
-
logger.info(` Total commits: ${commitMessages.length}`);
|
|
80331
|
-
logger.info(` Branch: ${branchName}`);
|
|
80332
|
-
logger.info(` Total time: ${totalElapsedTime}`);
|
|
80333
|
-
logger.info(` Average per iteration: ${avgTimePerIteration}
|
|
80334
|
-
`);
|
|
80335
|
-
logger.info("\uD83D\uDCDD Commits created:");
|
|
80336
|
-
commitMessages.forEach((msg, idx) => {
|
|
80337
|
-
logger.info(` ${idx + 1}. ${msg}`);
|
|
80338
|
-
});
|
|
80339
|
-
logger.info(`
|
|
80340
|
-
\uD83D\uDCA1 Next steps:`);
|
|
80341
|
-
logger.info(` • Review your changes: git log`);
|
|
80342
|
-
logger.info(` • Push to remote: git push origin ${branchName}`);
|
|
80343
|
-
logger.info(` • Create a pull request on your Git platform
|
|
80344
|
-
`);
|
|
80345
|
-
logger.info(`${"=".repeat(80)}
|
|
80346
|
-
`);
|
|
80347
|
-
await tools2.updateMemory({ operation: "remove", topic: "epic-context" });
|
|
80348
|
-
await tools2.updateMemory({ operation: "remove", topic: "epic-plan" });
|
|
80349
80733
|
};
|
|
80350
80734
|
|
|
80351
80735
|
// src/workflows/task.workflow.ts
|