@polka-codes/cli 0.9.48 → 0.9.50
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 +1198 -545
- 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.50";
|
|
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,89 @@ ${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
|
+
status: TodoStatus
|
|
48613
|
+
});
|
|
48614
|
+
var UpdateTodoItemInputSchema = exports_external.object({
|
|
48615
|
+
operation: exports_external.enum(["add", "update"]),
|
|
48616
|
+
id: exports_external.string().nullish(),
|
|
48617
|
+
parentId: exports_external.string().nullish(),
|
|
48618
|
+
title: exports_external.string().nullish(),
|
|
48619
|
+
description: exports_external.string().nullish(),
|
|
48620
|
+
status: TodoStatus.nullish()
|
|
48621
|
+
}).superRefine((data, ctx) => {
|
|
48622
|
+
if (data.operation === "add") {
|
|
48623
|
+
if (!data.title) {
|
|
48624
|
+
ctx.addIssue({
|
|
48625
|
+
code: "custom",
|
|
48626
|
+
message: 'Title is required for "add" operation',
|
|
48627
|
+
path: ["title"]
|
|
48628
|
+
});
|
|
48629
|
+
}
|
|
48630
|
+
} else if (data.operation === "update") {
|
|
48631
|
+
if (!data.id) {
|
|
48632
|
+
ctx.addIssue({
|
|
48633
|
+
code: "custom",
|
|
48634
|
+
message: 'ID is required for "update" operation',
|
|
48635
|
+
path: ["id"]
|
|
48636
|
+
});
|
|
48637
|
+
}
|
|
48638
|
+
}
|
|
48639
|
+
});
|
|
48640
|
+
var UpdateTodoItemOutputSchema = exports_external.object({
|
|
48641
|
+
id: exports_external.string()
|
|
48642
|
+
});
|
|
48643
|
+
|
|
48644
|
+
// ../core/src/tools/listTodoItems.ts
|
|
48645
|
+
var toolInfo7 = {
|
|
48646
|
+
name: "listTodoItems",
|
|
48647
|
+
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.",
|
|
48648
|
+
parameters: exports_external.object({
|
|
48649
|
+
id: exports_external.string().nullish(),
|
|
48650
|
+
status: TodoStatus.nullish()
|
|
48651
|
+
})
|
|
48652
|
+
};
|
|
48653
|
+
var handler7 = async (provider, args) => {
|
|
48654
|
+
if (!provider.listTodoItems) {
|
|
48655
|
+
return {
|
|
48656
|
+
type: "Error" /* Error */,
|
|
48657
|
+
message: {
|
|
48658
|
+
type: "error-text",
|
|
48659
|
+
value: "Not possible to list to-do items."
|
|
48660
|
+
}
|
|
48661
|
+
};
|
|
48662
|
+
}
|
|
48663
|
+
const { id, status } = toolInfo7.parameters.parse(args);
|
|
48664
|
+
const items = await provider.listTodoItems(id, status);
|
|
48665
|
+
return {
|
|
48666
|
+
type: "Reply" /* Reply */,
|
|
48667
|
+
message: {
|
|
48668
|
+
type: "json",
|
|
48669
|
+
value: items
|
|
48670
|
+
}
|
|
48671
|
+
};
|
|
48672
|
+
};
|
|
48673
|
+
var listTodoItems_default = {
|
|
48674
|
+
...toolInfo7,
|
|
48675
|
+
handler: handler7
|
|
48573
48676
|
};
|
|
48574
48677
|
// ../core/src/tools/readBinaryFile.ts
|
|
48575
|
-
var
|
|
48678
|
+
var toolInfo8 = {
|
|
48576
48679
|
name: "readBinaryFile",
|
|
48577
48680
|
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
48681
|
parameters: exports_external.object({
|
|
48579
48682
|
url: exports_external.string().describe("The URL or local path of the file to read.")
|
|
48580
48683
|
})
|
|
48581
48684
|
};
|
|
48582
|
-
var
|
|
48685
|
+
var handler8 = async (provider, args) => {
|
|
48583
48686
|
if (!provider.readBinaryFile) {
|
|
48584
48687
|
return {
|
|
48585
48688
|
type: "Error" /* Error */,
|
|
@@ -48589,7 +48692,7 @@ var handler6 = async (provider, args) => {
|
|
|
48589
48692
|
}
|
|
48590
48693
|
};
|
|
48591
48694
|
}
|
|
48592
|
-
const { url: url2 } =
|
|
48695
|
+
const { url: url2 } = toolInfo8.parameters.parse(args);
|
|
48593
48696
|
try {
|
|
48594
48697
|
const filePart = await provider.readBinaryFile(url2);
|
|
48595
48698
|
return {
|
|
@@ -48618,11 +48721,11 @@ var handler6 = async (provider, args) => {
|
|
|
48618
48721
|
}
|
|
48619
48722
|
};
|
|
48620
48723
|
var readBinaryFile_default = {
|
|
48621
|
-
...
|
|
48622
|
-
handler:
|
|
48724
|
+
...toolInfo8,
|
|
48725
|
+
handler: handler8
|
|
48623
48726
|
};
|
|
48624
48727
|
// ../core/src/tools/readFile.ts
|
|
48625
|
-
var
|
|
48728
|
+
var toolInfo9 = {
|
|
48626
48729
|
name: "readFile",
|
|
48627
48730
|
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
48731
|
parameters: exports_external.object({
|
|
@@ -48659,7 +48762,7 @@ var toolInfo7 = {
|
|
|
48659
48762
|
]
|
|
48660
48763
|
})
|
|
48661
48764
|
};
|
|
48662
|
-
var
|
|
48765
|
+
var handler9 = async (provider, args) => {
|
|
48663
48766
|
if (!provider.readFile) {
|
|
48664
48767
|
return {
|
|
48665
48768
|
type: "Error" /* Error */,
|
|
@@ -48669,7 +48772,7 @@ var handler7 = async (provider, args) => {
|
|
|
48669
48772
|
}
|
|
48670
48773
|
};
|
|
48671
48774
|
}
|
|
48672
|
-
const { path: paths, includeIgnored } =
|
|
48775
|
+
const { path: paths, includeIgnored } = toolInfo9.parameters.parse(args);
|
|
48673
48776
|
const resp = [];
|
|
48674
48777
|
for (const path of paths) {
|
|
48675
48778
|
const fileContent = await provider.readFile(path, includeIgnored);
|
|
@@ -48694,19 +48797,19 @@ var handler7 = async (provider, args) => {
|
|
|
48694
48797
|
};
|
|
48695
48798
|
};
|
|
48696
48799
|
var readFile_default = {
|
|
48697
|
-
...
|
|
48698
|
-
handler:
|
|
48800
|
+
...toolInfo9,
|
|
48801
|
+
handler: handler9
|
|
48699
48802
|
};
|
|
48700
48803
|
// ../core/src/tools/readMemory.ts
|
|
48701
|
-
var
|
|
48804
|
+
var toolInfo10 = {
|
|
48702
48805
|
name: "readMemory",
|
|
48703
|
-
description: "Reads content from a memory topic.",
|
|
48806
|
+
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
48807
|
parameters: exports_external.object({
|
|
48705
48808
|
topic: exports_external.string().optional().describe('The topic to read from memory. Defaults to ":default:".')
|
|
48706
48809
|
})
|
|
48707
48810
|
};
|
|
48708
|
-
var
|
|
48709
|
-
const { topic } =
|
|
48811
|
+
var handler10 = async (provider, args) => {
|
|
48812
|
+
const { topic } = toolInfo10.parameters.parse(args);
|
|
48710
48813
|
const content = await provider.readMemory(topic);
|
|
48711
48814
|
if (content) {
|
|
48712
48815
|
return {
|
|
@@ -48728,11 +48831,11 @@ ${content}
|
|
|
48728
48831
|
};
|
|
48729
48832
|
};
|
|
48730
48833
|
var readMemory_default = {
|
|
48731
|
-
...
|
|
48732
|
-
handler:
|
|
48834
|
+
...toolInfo10,
|
|
48835
|
+
handler: handler10
|
|
48733
48836
|
};
|
|
48734
48837
|
// ../core/src/tools/removeFile.ts
|
|
48735
|
-
var
|
|
48838
|
+
var toolInfo11 = {
|
|
48736
48839
|
name: "removeFile",
|
|
48737
48840
|
description: "Request to remove a file at the specified path.",
|
|
48738
48841
|
parameters: exports_external.object({
|
|
@@ -48748,7 +48851,7 @@ var toolInfo9 = {
|
|
|
48748
48851
|
]
|
|
48749
48852
|
})
|
|
48750
48853
|
};
|
|
48751
|
-
var
|
|
48854
|
+
var handler11 = async (provider, args) => {
|
|
48752
48855
|
if (!provider.removeFile) {
|
|
48753
48856
|
return {
|
|
48754
48857
|
type: "Error" /* Error */,
|
|
@@ -48758,7 +48861,7 @@ var handler9 = async (provider, args) => {
|
|
|
48758
48861
|
}
|
|
48759
48862
|
};
|
|
48760
48863
|
}
|
|
48761
|
-
const parsed =
|
|
48864
|
+
const parsed = toolInfo11.parameters.safeParse(args);
|
|
48762
48865
|
if (!parsed.success) {
|
|
48763
48866
|
return {
|
|
48764
48867
|
type: "Error" /* Error */,
|
|
@@ -48779,11 +48882,11 @@ var handler9 = async (provider, args) => {
|
|
|
48779
48882
|
};
|
|
48780
48883
|
};
|
|
48781
48884
|
var removeFile_default = {
|
|
48782
|
-
...
|
|
48783
|
-
handler:
|
|
48885
|
+
...toolInfo11,
|
|
48886
|
+
handler: handler11
|
|
48784
48887
|
};
|
|
48785
48888
|
// ../core/src/tools/renameFile.ts
|
|
48786
|
-
var
|
|
48889
|
+
var toolInfo12 = {
|
|
48787
48890
|
name: "renameFile",
|
|
48788
48891
|
description: "Request to rename a file from source path to target path.",
|
|
48789
48892
|
parameters: exports_external.object({
|
|
@@ -48801,7 +48904,7 @@ var toolInfo10 = {
|
|
|
48801
48904
|
]
|
|
48802
48905
|
})
|
|
48803
48906
|
};
|
|
48804
|
-
var
|
|
48907
|
+
var handler12 = async (provider, args) => {
|
|
48805
48908
|
if (!provider.renameFile) {
|
|
48806
48909
|
return {
|
|
48807
48910
|
type: "Error" /* Error */,
|
|
@@ -48811,7 +48914,7 @@ var handler10 = async (provider, args) => {
|
|
|
48811
48914
|
}
|
|
48812
48915
|
};
|
|
48813
48916
|
}
|
|
48814
|
-
const { source_path, target_path } =
|
|
48917
|
+
const { source_path, target_path } = toolInfo12.parameters.parse(args);
|
|
48815
48918
|
await provider.renameFile(source_path, target_path);
|
|
48816
48919
|
return {
|
|
48817
48920
|
type: "Reply" /* Reply */,
|
|
@@ -48822,12 +48925,12 @@ var handler10 = async (provider, args) => {
|
|
|
48822
48925
|
};
|
|
48823
48926
|
};
|
|
48824
48927
|
var renameFile_default = {
|
|
48825
|
-
...
|
|
48826
|
-
handler:
|
|
48928
|
+
...toolInfo12,
|
|
48929
|
+
handler: handler12
|
|
48827
48930
|
};
|
|
48828
48931
|
// ../core/src/tools/utils/replaceInFile.ts
|
|
48829
48932
|
var replaceInFile = (fileContent, diff) => {
|
|
48830
|
-
const blockPattern =
|
|
48933
|
+
const blockPattern = /^\s*<<<<<+\s*SEARCH>?\s*\r?\n([\s\S]*?)\r?\n=======[ \t]*\r?\n([\s\S]*?)\r?\n?>>>>>+\s*REPLACE\s*$/gm;
|
|
48831
48934
|
const blocks = [];
|
|
48832
48935
|
for (let match = blockPattern.exec(diff);match !== null; match = blockPattern.exec(diff)) {
|
|
48833
48936
|
blocks.push({ search: match[1], replace: match[2] });
|
|
@@ -48900,7 +49003,7 @@ var replaceInFile = (fileContent, diff) => {
|
|
|
48900
49003
|
};
|
|
48901
49004
|
|
|
48902
49005
|
// ../core/src/tools/replaceInFile.ts
|
|
48903
|
-
var
|
|
49006
|
+
var toolInfo13 = {
|
|
48904
49007
|
name: "replaceInFile",
|
|
48905
49008
|
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
49009
|
parameters: exports_external.object({
|
|
@@ -49010,7 +49113,7 @@ function oldFeature() {
|
|
|
49010
49113
|
]
|
|
49011
49114
|
})
|
|
49012
49115
|
};
|
|
49013
|
-
var
|
|
49116
|
+
var handler13 = async (provider, args) => {
|
|
49014
49117
|
if (!provider.readFile || !provider.writeFile) {
|
|
49015
49118
|
return {
|
|
49016
49119
|
type: "Error" /* Error */,
|
|
@@ -49020,7 +49123,7 @@ var handler11 = async (provider, args) => {
|
|
|
49020
49123
|
}
|
|
49021
49124
|
};
|
|
49022
49125
|
}
|
|
49023
|
-
const parsed =
|
|
49126
|
+
const parsed = toolInfo13.parameters.safeParse(args);
|
|
49024
49127
|
if (!parsed.success) {
|
|
49025
49128
|
return {
|
|
49026
49129
|
type: "Error" /* Error */,
|
|
@@ -49084,11 +49187,11 @@ var handler11 = async (provider, args) => {
|
|
|
49084
49187
|
}
|
|
49085
49188
|
};
|
|
49086
49189
|
var replaceInFile_default = {
|
|
49087
|
-
...
|
|
49088
|
-
handler:
|
|
49190
|
+
...toolInfo13,
|
|
49191
|
+
handler: handler13
|
|
49089
49192
|
};
|
|
49090
49193
|
// ../core/src/tools/searchFiles.ts
|
|
49091
|
-
var
|
|
49194
|
+
var toolInfo14 = {
|
|
49092
49195
|
name: "searchFiles",
|
|
49093
49196
|
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
49197
|
parameters: exports_external.object({
|
|
@@ -49112,7 +49215,7 @@ var toolInfo12 = {
|
|
|
49112
49215
|
]
|
|
49113
49216
|
})
|
|
49114
49217
|
};
|
|
49115
|
-
var
|
|
49218
|
+
var handler14 = async (provider, args) => {
|
|
49116
49219
|
if (!provider.searchFiles) {
|
|
49117
49220
|
return {
|
|
49118
49221
|
type: "Error" /* Error */,
|
|
@@ -49122,7 +49225,7 @@ var handler12 = async (provider, args) => {
|
|
|
49122
49225
|
}
|
|
49123
49226
|
};
|
|
49124
49227
|
}
|
|
49125
|
-
const parsed =
|
|
49228
|
+
const parsed = toolInfo14.parameters.safeParse(args);
|
|
49126
49229
|
if (!parsed.success) {
|
|
49127
49230
|
return {
|
|
49128
49231
|
type: "Error" /* Error */,
|
|
@@ -49160,13 +49263,13 @@ ${files.join(`
|
|
|
49160
49263
|
}
|
|
49161
49264
|
};
|
|
49162
49265
|
var searchFiles_default = {
|
|
49163
|
-
...
|
|
49164
|
-
handler:
|
|
49266
|
+
...toolInfo14,
|
|
49267
|
+
handler: handler14
|
|
49165
49268
|
};
|
|
49166
49269
|
// ../core/src/tools/updateMemory.ts
|
|
49167
|
-
var
|
|
49270
|
+
var toolInfo15 = {
|
|
49168
49271
|
name: "updateMemory",
|
|
49169
|
-
description:
|
|
49272
|
+
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
49273
|
parameters: exports_external.object({
|
|
49171
49274
|
operation: exports_external.enum(["append", "replace", "remove"]).describe("The operation to perform."),
|
|
49172
49275
|
topic: exports_external.string().nullish().describe('The topic to update in memory. Defaults to ":default:".'),
|
|
@@ -49191,7 +49294,7 @@ var toolInfo13 = {
|
|
|
49191
49294
|
}
|
|
49192
49295
|
})
|
|
49193
49296
|
};
|
|
49194
|
-
var
|
|
49297
|
+
var handler15 = async (provider, args) => {
|
|
49195
49298
|
if (!provider.updateMemory) {
|
|
49196
49299
|
return {
|
|
49197
49300
|
type: "Error" /* Error */,
|
|
@@ -49201,7 +49304,7 @@ var handler13 = async (provider, args) => {
|
|
|
49201
49304
|
}
|
|
49202
49305
|
};
|
|
49203
49306
|
}
|
|
49204
|
-
const params =
|
|
49307
|
+
const params = toolInfo15.parameters.parse(args);
|
|
49205
49308
|
await provider.updateMemory(params.operation, params.topic ?? undefined, "content" in params ? params.content : undefined);
|
|
49206
49309
|
switch (params.operation) {
|
|
49207
49310
|
case "append":
|
|
@@ -49231,11 +49334,41 @@ var handler13 = async (provider, args) => {
|
|
|
49231
49334
|
}
|
|
49232
49335
|
};
|
|
49233
49336
|
var updateMemory_default = {
|
|
49234
|
-
...
|
|
49235
|
-
handler:
|
|
49337
|
+
...toolInfo15,
|
|
49338
|
+
handler: handler15
|
|
49339
|
+
};
|
|
49340
|
+
// ../core/src/tools/updateTodoItem.ts
|
|
49341
|
+
var toolInfo16 = {
|
|
49342
|
+
name: "updateTodoItem",
|
|
49343
|
+
description: "Add or update a to-do item.",
|
|
49344
|
+
parameters: UpdateTodoItemInputSchema
|
|
49345
|
+
};
|
|
49346
|
+
var handler16 = async (provider, args) => {
|
|
49347
|
+
if (!provider.updateTodoItem) {
|
|
49348
|
+
return {
|
|
49349
|
+
type: "Error" /* Error */,
|
|
49350
|
+
message: {
|
|
49351
|
+
type: "error-text",
|
|
49352
|
+
value: "Not possible to update a to-do item."
|
|
49353
|
+
}
|
|
49354
|
+
};
|
|
49355
|
+
}
|
|
49356
|
+
const input = toolInfo16.parameters.parse(args);
|
|
49357
|
+
const result = await provider.updateTodoItem(input);
|
|
49358
|
+
return {
|
|
49359
|
+
type: "Reply" /* Reply */,
|
|
49360
|
+
message: {
|
|
49361
|
+
type: "json",
|
|
49362
|
+
value: result
|
|
49363
|
+
}
|
|
49364
|
+
};
|
|
49365
|
+
};
|
|
49366
|
+
var updateTodoItem_default = {
|
|
49367
|
+
...toolInfo16,
|
|
49368
|
+
handler: handler16
|
|
49236
49369
|
};
|
|
49237
49370
|
// ../core/src/tools/writeToFile.ts
|
|
49238
|
-
var
|
|
49371
|
+
var toolInfo17 = {
|
|
49239
49372
|
name: "writeToFile",
|
|
49240
49373
|
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
49374
|
parameters: exports_external.object({
|
|
@@ -49264,7 +49397,7 @@ export default App;
|
|
|
49264
49397
|
]
|
|
49265
49398
|
})
|
|
49266
49399
|
};
|
|
49267
|
-
var
|
|
49400
|
+
var handler17 = async (provider, args) => {
|
|
49268
49401
|
if (!provider.writeFile) {
|
|
49269
49402
|
return {
|
|
49270
49403
|
type: "Error" /* Error */,
|
|
@@ -49274,7 +49407,7 @@ var handler14 = async (provider, args) => {
|
|
|
49274
49407
|
}
|
|
49275
49408
|
};
|
|
49276
49409
|
}
|
|
49277
|
-
const parsed =
|
|
49410
|
+
const parsed = toolInfo17.parameters.safeParse(args);
|
|
49278
49411
|
if (!parsed.success) {
|
|
49279
49412
|
return {
|
|
49280
49413
|
type: "Error" /* Error */,
|
|
@@ -49298,8 +49431,8 @@ var handler14 = async (provider, args) => {
|
|
|
49298
49431
|
};
|
|
49299
49432
|
};
|
|
49300
49433
|
var writeToFile_default = {
|
|
49301
|
-
...
|
|
49302
|
-
handler:
|
|
49434
|
+
...toolInfo17,
|
|
49435
|
+
handler: handler17
|
|
49303
49436
|
};
|
|
49304
49437
|
// ../core/src/UsageMeter.ts
|
|
49305
49438
|
class UsageMeter {
|
|
@@ -51340,15 +51473,15 @@ function useKeypress(userHandler) {
|
|
|
51340
51473
|
signal.current = userHandler;
|
|
51341
51474
|
useEffect((rl) => {
|
|
51342
51475
|
let ignore = false;
|
|
51343
|
-
const
|
|
51476
|
+
const handler18 = withUpdates((_input, event) => {
|
|
51344
51477
|
if (ignore)
|
|
51345
51478
|
return;
|
|
51346
51479
|
signal.current(event, rl);
|
|
51347
51480
|
});
|
|
51348
|
-
rl.input.on("keypress",
|
|
51481
|
+
rl.input.on("keypress", handler18);
|
|
51349
51482
|
return () => {
|
|
51350
51483
|
ignore = true;
|
|
51351
|
-
rl.input.removeListener("keypress",
|
|
51484
|
+
rl.input.removeListener("keypress", handler18);
|
|
51352
51485
|
};
|
|
51353
51486
|
}, []);
|
|
51354
51487
|
}
|
|
@@ -51507,16 +51640,16 @@ class Emitter {
|
|
|
51507
51640
|
|
|
51508
51641
|
class SignalExitBase {
|
|
51509
51642
|
}
|
|
51510
|
-
var signalExitWrap = (
|
|
51643
|
+
var signalExitWrap = (handler18) => {
|
|
51511
51644
|
return {
|
|
51512
51645
|
onExit(cb, opts) {
|
|
51513
|
-
return
|
|
51646
|
+
return handler18.onExit(cb, opts);
|
|
51514
51647
|
},
|
|
51515
51648
|
load() {
|
|
51516
|
-
return
|
|
51649
|
+
return handler18.load();
|
|
51517
51650
|
},
|
|
51518
51651
|
unload() {
|
|
51519
|
-
return
|
|
51652
|
+
return handler18.unload();
|
|
51520
51653
|
}
|
|
51521
51654
|
};
|
|
51522
51655
|
};
|
|
@@ -52337,36 +52470,147 @@ async function searchFiles(path, regex, filePattern, cwd, excludeFiles) {
|
|
|
52337
52470
|
}
|
|
52338
52471
|
|
|
52339
52472
|
// ../cli-shared/src/provider.ts
|
|
52473
|
+
class InMemoryStore {
|
|
52474
|
+
#data;
|
|
52475
|
+
async read() {
|
|
52476
|
+
return this.#data;
|
|
52477
|
+
}
|
|
52478
|
+
async write(data) {
|
|
52479
|
+
this.#data = data;
|
|
52480
|
+
}
|
|
52481
|
+
}
|
|
52340
52482
|
var getProvider = (options = {}) => {
|
|
52341
52483
|
const ig = import_ignore2.default().add(options.excludeFiles ?? []);
|
|
52342
|
-
const memoryStore =
|
|
52484
|
+
const memoryStore = options.memoryStore ?? new InMemoryStore;
|
|
52485
|
+
const todoItemStore = options.todoItemStore ?? new InMemoryStore;
|
|
52343
52486
|
const defaultMemoryTopic = ":default:";
|
|
52344
52487
|
const provider2 = {
|
|
52488
|
+
listTodoItems: async (id, status) => {
|
|
52489
|
+
const todoItems = await todoItemStore.read() ?? [];
|
|
52490
|
+
let items;
|
|
52491
|
+
if (!id) {
|
|
52492
|
+
items = todoItems.filter((i) => !i.id.includes("."));
|
|
52493
|
+
} else {
|
|
52494
|
+
const parent = todoItems.find((i) => i.id === id);
|
|
52495
|
+
if (!parent) {
|
|
52496
|
+
throw new Error(`To-do item with id ${id} not found`);
|
|
52497
|
+
}
|
|
52498
|
+
items = todoItems.filter((i) => i.id.startsWith(`${id}.`) && i.id.split(".").length === id.split(".").length + 1);
|
|
52499
|
+
}
|
|
52500
|
+
if (status) {
|
|
52501
|
+
items = items.filter((item) => item.status === status);
|
|
52502
|
+
}
|
|
52503
|
+
items.sort((a, b) => {
|
|
52504
|
+
const aParts = a.id.split(".");
|
|
52505
|
+
const bParts = b.id.split(".");
|
|
52506
|
+
const len = Math.min(aParts.length, bParts.length);
|
|
52507
|
+
for (let i = 0;i < len; i++) {
|
|
52508
|
+
const comparison = aParts[i].localeCompare(bParts[i], undefined, { numeric: true });
|
|
52509
|
+
if (comparison !== 0) {
|
|
52510
|
+
return comparison;
|
|
52511
|
+
}
|
|
52512
|
+
}
|
|
52513
|
+
return aParts.length - bParts.length;
|
|
52514
|
+
});
|
|
52515
|
+
return items;
|
|
52516
|
+
},
|
|
52517
|
+
getTodoItem: async (id) => {
|
|
52518
|
+
const todoItems = await todoItemStore.read() ?? [];
|
|
52519
|
+
const item = todoItems.find((i) => i.id === id);
|
|
52520
|
+
if (!item) {
|
|
52521
|
+
throw new Error(`To-do item with id ${id} not found`);
|
|
52522
|
+
}
|
|
52523
|
+
const subItems = todoItems.filter((i) => i.id.startsWith(`${id}.`) && i.id.split(".").length === id.split(".").length + 1).map(({ id: id2, title }) => ({ id: id2, title }));
|
|
52524
|
+
return { ...item, subItems };
|
|
52525
|
+
},
|
|
52526
|
+
updateTodoItem: async (input) => {
|
|
52527
|
+
const todoItems = await todoItemStore.read() ?? [];
|
|
52528
|
+
if (input.operation === "add") {
|
|
52529
|
+
const { parentId, title, description, status } = input;
|
|
52530
|
+
if (!title) {
|
|
52531
|
+
throw new Error("Title is required for add operation");
|
|
52532
|
+
}
|
|
52533
|
+
let newId;
|
|
52534
|
+
if (parentId) {
|
|
52535
|
+
const parent = todoItems.find((i) => i.id === parentId);
|
|
52536
|
+
if (!parent) {
|
|
52537
|
+
throw new Error(`Parent to-do item with id ${parentId} not found`);
|
|
52538
|
+
}
|
|
52539
|
+
const childItems = todoItems.filter((i) => i.id.startsWith(`${parentId}.`) && i.id.split(".").length === parentId.split(".").length + 1);
|
|
52540
|
+
const maxId = childItems.reduce((max, item) => {
|
|
52541
|
+
const parts = item.id.split(".");
|
|
52542
|
+
const lastPart = parseInt(parts[parts.length - 1], 10);
|
|
52543
|
+
return Math.max(max, lastPart);
|
|
52544
|
+
}, 0);
|
|
52545
|
+
newId = `${parentId}.${maxId + 1}`;
|
|
52546
|
+
} else {
|
|
52547
|
+
const rootItems = todoItems.filter((i) => !i.id.includes("."));
|
|
52548
|
+
const maxId = rootItems.reduce((max, item) => {
|
|
52549
|
+
const idNum = parseInt(item.id, 10);
|
|
52550
|
+
return Math.max(max, idNum);
|
|
52551
|
+
}, 0);
|
|
52552
|
+
newId = `${maxId + 1}`;
|
|
52553
|
+
}
|
|
52554
|
+
const newItem = {
|
|
52555
|
+
id: newId,
|
|
52556
|
+
title,
|
|
52557
|
+
description: description ?? "",
|
|
52558
|
+
status: status ?? "open"
|
|
52559
|
+
};
|
|
52560
|
+
await todoItemStore.write([...todoItems, newItem]);
|
|
52561
|
+
return { id: newId };
|
|
52562
|
+
} else {
|
|
52563
|
+
const { id } = input;
|
|
52564
|
+
if (!id) {
|
|
52565
|
+
throw new Error("ID is required for update operation");
|
|
52566
|
+
}
|
|
52567
|
+
const item = todoItems.find((i) => i.id === id);
|
|
52568
|
+
if (!item) {
|
|
52569
|
+
throw new Error(`To-do item with id ${id} not found`);
|
|
52570
|
+
}
|
|
52571
|
+
if (input.title != null) {
|
|
52572
|
+
item.title = input.title;
|
|
52573
|
+
}
|
|
52574
|
+
if (input.description != null) {
|
|
52575
|
+
item.description = input.description ?? "";
|
|
52576
|
+
}
|
|
52577
|
+
if (input.status != null) {
|
|
52578
|
+
item.status = input.status;
|
|
52579
|
+
}
|
|
52580
|
+
await todoItemStore.write(todoItems);
|
|
52581
|
+
return { id };
|
|
52582
|
+
}
|
|
52583
|
+
},
|
|
52345
52584
|
listMemoryTopics: async () => {
|
|
52346
|
-
|
|
52585
|
+
const memory = await memoryStore.read() ?? {};
|
|
52586
|
+
return Object.keys(memory);
|
|
52347
52587
|
},
|
|
52348
52588
|
readMemory: async (topic = defaultMemoryTopic) => {
|
|
52349
|
-
|
|
52589
|
+
const memory = await memoryStore.read() ?? {};
|
|
52590
|
+
return memory[topic];
|
|
52350
52591
|
},
|
|
52351
52592
|
updateMemory: async (operation, topic, content) => {
|
|
52352
52593
|
const memoryTopic = topic ?? defaultMemoryTopic;
|
|
52594
|
+
const memory = await memoryStore.read() ?? {};
|
|
52353
52595
|
switch (operation) {
|
|
52354
52596
|
case "append":
|
|
52355
52597
|
if (content === undefined) {
|
|
52356
52598
|
throw new Error("Content is required for append operation.");
|
|
52357
52599
|
}
|
|
52358
|
-
|
|
52600
|
+
memory[memoryTopic] = `${memory[memoryTopic] || ""}
|
|
52601
|
+
${content}`;
|
|
52359
52602
|
break;
|
|
52360
52603
|
case "replace":
|
|
52361
52604
|
if (content === undefined) {
|
|
52362
52605
|
throw new Error("Content is required for replace operation.");
|
|
52363
52606
|
}
|
|
52364
|
-
|
|
52607
|
+
memory[memoryTopic] = content;
|
|
52365
52608
|
break;
|
|
52366
52609
|
case "remove":
|
|
52367
|
-
delete
|
|
52610
|
+
delete memory[memoryTopic];
|
|
52368
52611
|
break;
|
|
52369
52612
|
}
|
|
52613
|
+
await memoryStore.write(memory);
|
|
52370
52614
|
},
|
|
52371
52615
|
readFile: async (path, includeIgnored) => {
|
|
52372
52616
|
if (!includeIgnored && ig.ignores(path)) {
|
|
@@ -64126,16 +64370,12 @@ var uiMessagesSchema = lazyValidator(() => zodSchema(exports_external.array(expo
|
|
|
64126
64370
|
|
|
64127
64371
|
// ../workflow/src/agent.workflow.ts
|
|
64128
64372
|
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;
|
|
64373
|
+
const event = (name17, event2) => step(name17, () => tools2.taskEvent(event2));
|
|
64374
|
+
const { tools: toolInfo18, maxToolRoundTrips = 200 } = input;
|
|
64135
64375
|
const messages = "systemPrompt" in input ? [{ role: "system", content: input.systemPrompt }] : input.messages;
|
|
64136
64376
|
await event("start-task", { kind: "StartTask" /* StartTask */, systemPrompt: "systemPrompt" in input ? input.systemPrompt : "" });
|
|
64137
64377
|
const toolSet = {};
|
|
64138
|
-
for (const tool3 of
|
|
64378
|
+
for (const tool3 of toolInfo18) {
|
|
64139
64379
|
toolSet[tool3.name] = {
|
|
64140
64380
|
description: tool3.description,
|
|
64141
64381
|
inputSchema: jsonSchema(toJSONSchema(tool3.parameters))
|
|
@@ -64183,7 +64423,9 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64183
64423
|
await event(`end-round-${i}`, { kind: "EndRequest" /* EndRequest */, message: textContent });
|
|
64184
64424
|
if (toolCalls.length === 0) {
|
|
64185
64425
|
if (!input.outputSchema) {
|
|
64186
|
-
|
|
64426
|
+
const exitReason2 = { type: "Exit" /* Exit */, message: textContent };
|
|
64427
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: exitReason2 });
|
|
64428
|
+
return exitReason2;
|
|
64187
64429
|
}
|
|
64188
64430
|
const parsed = parseJsonFromMarkdown(textContent);
|
|
64189
64431
|
if (!parsed.success) {
|
|
@@ -64197,7 +64439,9 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64197
64439
|
nextMessage = [{ role: "user", content: errorMessage }];
|
|
64198
64440
|
continue;
|
|
64199
64441
|
}
|
|
64200
|
-
|
|
64442
|
+
const exitReason = { type: "Exit" /* Exit */, message: textContent, object: validated.data };
|
|
64443
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason });
|
|
64444
|
+
return exitReason;
|
|
64201
64445
|
}
|
|
64202
64446
|
const toolResults = [];
|
|
64203
64447
|
for (const toolCall of toolCalls) {
|
|
@@ -64266,6 +64510,7 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64266
64510
|
}
|
|
64267
64511
|
];
|
|
64268
64512
|
}
|
|
64513
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: { type: "UsageExceeded" } });
|
|
64269
64514
|
throw new Error("Maximum number of tool round trips reached.");
|
|
64270
64515
|
};
|
|
64271
64516
|
// ../workflow/src/json-ai-types.ts
|
|
@@ -64835,6 +65080,53 @@ var chalk = createChalk();
|
|
|
64835
65080
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
64836
65081
|
var source_default = chalk;
|
|
64837
65082
|
|
|
65083
|
+
// ../cli-shared/src/utils/parameterSimplifier.ts
|
|
65084
|
+
function replaceInFileSimplifier(params) {
|
|
65085
|
+
return { path: params.path };
|
|
65086
|
+
}
|
|
65087
|
+
function writeToFileSimplifier(params) {
|
|
65088
|
+
return { path: params.path };
|
|
65089
|
+
}
|
|
65090
|
+
function readFileSimplifier(params) {
|
|
65091
|
+
return { path: params.path, includeIgnored: params.includeIgnored };
|
|
65092
|
+
}
|
|
65093
|
+
function listFilesSimplifier(params) {
|
|
65094
|
+
const maxCount = params.maxCount;
|
|
65095
|
+
return {
|
|
65096
|
+
path: params.path,
|
|
65097
|
+
recursive: params.recursive,
|
|
65098
|
+
...maxCount !== 2000 && { maxCount }
|
|
65099
|
+
};
|
|
65100
|
+
}
|
|
65101
|
+
function searchFilesSimplifier(params) {
|
|
65102
|
+
return { ...params };
|
|
65103
|
+
}
|
|
65104
|
+
function executeCommandSimplifier(params) {
|
|
65105
|
+
return { command: params.command, requiresApproval: params.requiresApproval };
|
|
65106
|
+
}
|
|
65107
|
+
function updateMemorySimplifier(params) {
|
|
65108
|
+
return { operation: params.operation, topic: params.topic };
|
|
65109
|
+
}
|
|
65110
|
+
var SIMPLIFIERS = {
|
|
65111
|
+
replaceInFile: replaceInFileSimplifier,
|
|
65112
|
+
writeToFile: writeToFileSimplifier,
|
|
65113
|
+
readFile: readFileSimplifier,
|
|
65114
|
+
listFiles: listFilesSimplifier,
|
|
65115
|
+
searchFiles: searchFilesSimplifier,
|
|
65116
|
+
executeCommand: executeCommandSimplifier,
|
|
65117
|
+
updateMemory: updateMemorySimplifier
|
|
65118
|
+
};
|
|
65119
|
+
function simplifyToolParameters(toolName, params) {
|
|
65120
|
+
if (params === undefined || params === null) {
|
|
65121
|
+
return {};
|
|
65122
|
+
}
|
|
65123
|
+
const simplifier = SIMPLIFIERS[toolName];
|
|
65124
|
+
if (simplifier) {
|
|
65125
|
+
return simplifier(params);
|
|
65126
|
+
}
|
|
65127
|
+
return { ...params };
|
|
65128
|
+
}
|
|
65129
|
+
|
|
64838
65130
|
// ../cli-shared/src/utils/eventHandler.ts
|
|
64839
65131
|
var taskToolCallStats = new Map;
|
|
64840
65132
|
var globalToolCallStats = new Map;
|
|
@@ -64859,8 +65151,26 @@ function logToolCallStats(stream, statsMap, title) {
|
|
|
64859
65151
|
customConsole.log("No tools were called.");
|
|
64860
65152
|
}
|
|
64861
65153
|
}
|
|
65154
|
+
var mergeToolCallStats = (a, b) => {
|
|
65155
|
+
const merged = new Map;
|
|
65156
|
+
for (const [tool3, stat] of a) {
|
|
65157
|
+
merged.set(tool3, { ...stat });
|
|
65158
|
+
}
|
|
65159
|
+
for (const [tool3, stat] of b) {
|
|
65160
|
+
const existing = merged.get(tool3);
|
|
65161
|
+
if (existing) {
|
|
65162
|
+
existing.calls += stat.calls;
|
|
65163
|
+
existing.success += stat.success;
|
|
65164
|
+
existing.errors += stat.errors;
|
|
65165
|
+
} else {
|
|
65166
|
+
merged.set(tool3, { ...stat });
|
|
65167
|
+
}
|
|
65168
|
+
}
|
|
65169
|
+
return merged;
|
|
65170
|
+
};
|
|
64862
65171
|
function logGlobalToolCallStats(stream) {
|
|
64863
|
-
|
|
65172
|
+
const merged = mergeToolCallStats(globalToolCallStats, taskToolCallStats);
|
|
65173
|
+
logToolCallStats(stream, merged, "Global Tool Call Stats");
|
|
64864
65174
|
}
|
|
64865
65175
|
var printEvent = (verbose, usageMeter, stream = process.stdout) => {
|
|
64866
65176
|
if (verbose < 0) {
|
|
@@ -64868,6 +65178,7 @@ var printEvent = (verbose, usageMeter, stream = process.stdout) => {
|
|
|
64868
65178
|
}
|
|
64869
65179
|
const customConsole = new Console(stream, stream);
|
|
64870
65180
|
let hadReasoning = false;
|
|
65181
|
+
let hasText = false;
|
|
64871
65182
|
const write = stream.write.bind(stream);
|
|
64872
65183
|
return (event) => {
|
|
64873
65184
|
switch (event.kind) {
|
|
@@ -64884,6 +65195,7 @@ ${event.systemPrompt}`);
|
|
|
64884
65195
|
}
|
|
64885
65196
|
break;
|
|
64886
65197
|
case "StartRequest" /* StartRequest */:
|
|
65198
|
+
hasText = false;
|
|
64887
65199
|
if (verbose > 0) {
|
|
64888
65200
|
customConsole.log(`
|
|
64889
65201
|
|
|
@@ -64937,6 +65249,11 @@ ${event.systemPrompt}`);
|
|
|
64937
65249
|
customConsole.log(`
|
|
64938
65250
|
|
|
64939
65251
|
======== Request Ended ========
|
|
65252
|
+
`);
|
|
65253
|
+
}
|
|
65254
|
+
if (verbose === 0 && hasText) {
|
|
65255
|
+
write(`
|
|
65256
|
+
|
|
64940
65257
|
`);
|
|
64941
65258
|
}
|
|
64942
65259
|
if (verbose > 1) {
|
|
@@ -64950,6 +65267,9 @@ ${event.systemPrompt}`);
|
|
|
64950
65267
|
`);
|
|
64951
65268
|
hadReasoning = false;
|
|
64952
65269
|
}
|
|
65270
|
+
if (event.newText.trim().length > 0) {
|
|
65271
|
+
hasText = true;
|
|
65272
|
+
}
|
|
64953
65273
|
write(event.newText);
|
|
64954
65274
|
break;
|
|
64955
65275
|
}
|
|
@@ -64962,9 +65282,10 @@ ${event.systemPrompt}`);
|
|
|
64962
65282
|
}
|
|
64963
65283
|
case "ToolUse" /* ToolUse */: {
|
|
64964
65284
|
if (verbose > 0) {
|
|
65285
|
+
const params = verbose > 1 ? event.params : simplifyToolParameters(event.tool, event.params);
|
|
64965
65286
|
customConsole.log(source_default.yellow(`
|
|
64966
65287
|
|
|
64967
|
-
Tool use:`, event.tool),
|
|
65288
|
+
Tool use:`, event.tool), params);
|
|
64968
65289
|
}
|
|
64969
65290
|
const stats = taskToolCallStats.get(event.tool) ?? { calls: 0, success: 0, errors: 0 };
|
|
64970
65291
|
stats.calls++;
|
|
@@ -65000,18 +65321,28 @@ Tool error:`, event.tool));
|
|
|
65000
65321
|
`);
|
|
65001
65322
|
customConsole.log("Reason:", event.exitReason.type);
|
|
65002
65323
|
switch (event.exitReason.type) {
|
|
65324
|
+
case "Error": {
|
|
65325
|
+
const { error: error46 } = event.exitReason;
|
|
65326
|
+
customConsole.error(source_default.red(`Workflow failed: ${error46.message}`));
|
|
65327
|
+
if (verbose > 0 && error46.stack) {
|
|
65328
|
+
customConsole.error(source_default.red(error46.stack));
|
|
65329
|
+
}
|
|
65330
|
+
break;
|
|
65331
|
+
}
|
|
65003
65332
|
case "Exit" /* Exit */:
|
|
65004
|
-
|
|
65333
|
+
if (verbose > 0) {
|
|
65334
|
+
customConsole.log("Exit Message:", event.exitReason.message);
|
|
65335
|
+
}
|
|
65005
65336
|
break;
|
|
65006
65337
|
}
|
|
65338
|
+
for (const [tool3, taskStats] of taskToolCallStats.entries()) {
|
|
65339
|
+
const globalStats = globalToolCallStats.get(tool3) ?? { calls: 0, success: 0, errors: 0 };
|
|
65340
|
+
globalStats.calls += taskStats.calls;
|
|
65341
|
+
globalStats.success += taskStats.success;
|
|
65342
|
+
globalStats.errors += taskStats.errors;
|
|
65343
|
+
globalToolCallStats.set(tool3, globalStats);
|
|
65344
|
+
}
|
|
65007
65345
|
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
65346
|
logToolCallStats(stream, taskToolCallStats, "Task Tool Call Stats");
|
|
65016
65347
|
}
|
|
65017
65348
|
break;
|
|
@@ -77501,7 +77832,7 @@ function annotateDiffWithLineNumbers(diff) {
|
|
|
77501
77832
|
}
|
|
77502
77833
|
|
|
77503
77834
|
// src/tools/gitDiff.ts
|
|
77504
|
-
var
|
|
77835
|
+
var toolInfo18 = {
|
|
77505
77836
|
name: "git_diff",
|
|
77506
77837
|
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
77838
|
parameters: exports_external.object({
|
|
@@ -77530,7 +77861,7 @@ var toolInfo15 = {
|
|
|
77530
77861
|
}, exports_external.boolean().optional().default(false)).describe("Annotate the diff with line numbers for additions and deletions.")
|
|
77531
77862
|
})
|
|
77532
77863
|
};
|
|
77533
|
-
var
|
|
77864
|
+
var handler18 = async (provider3, args) => {
|
|
77534
77865
|
if (!provider3.executeCommand) {
|
|
77535
77866
|
return {
|
|
77536
77867
|
type: "Error" /* Error */,
|
|
@@ -77540,7 +77871,7 @@ var handler15 = async (provider3, args) => {
|
|
|
77540
77871
|
}
|
|
77541
77872
|
};
|
|
77542
77873
|
}
|
|
77543
|
-
const { staged, file: file2, commitRange, contextLines, includeLineNumbers } =
|
|
77874
|
+
const { staged, file: file2, commitRange, contextLines, includeLineNumbers } = toolInfo18.parameters.parse(args);
|
|
77544
77875
|
const commandParts = ["git", "diff", "--no-color", `-U${contextLines}`];
|
|
77545
77876
|
if (staged) {
|
|
77546
77877
|
commandParts.push("--staged");
|
|
@@ -77597,8 +77928,8 @@ ${result.stderr}`
|
|
|
77597
77928
|
}
|
|
77598
77929
|
};
|
|
77599
77930
|
var gitDiff_default = {
|
|
77600
|
-
...
|
|
77601
|
-
handler:
|
|
77931
|
+
...toolInfo18,
|
|
77932
|
+
handler: handler18
|
|
77602
77933
|
};
|
|
77603
77934
|
// src/utils/cacheControl.ts
|
|
77604
77935
|
var CACHEABLE_MODELS = ["sonnet", "opus", "haiku", "gemini"];
|
|
@@ -77929,7 +78260,10 @@ var allTools = [
|
|
|
77929
78260
|
replaceInFile_default,
|
|
77930
78261
|
searchFiles_default,
|
|
77931
78262
|
writeToFile_default,
|
|
77932
|
-
gitDiff_default
|
|
78263
|
+
gitDiff_default,
|
|
78264
|
+
getTodoItem_default,
|
|
78265
|
+
listTodoItems_default,
|
|
78266
|
+
updateTodoItem_default
|
|
77933
78267
|
];
|
|
77934
78268
|
var toolHandlers = new Map(allTools.map((t) => [t.name, t]));
|
|
77935
78269
|
async function createPullRequest(input, _context) {
|
|
@@ -77974,6 +78308,7 @@ async function confirm(input, context) {
|
|
|
77974
78308
|
}
|
|
77975
78309
|
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
77976
78310
|
try {
|
|
78311
|
+
process.stderr.write("\x07");
|
|
77977
78312
|
const result = await esm_default2({ message: input.message });
|
|
77978
78313
|
return result;
|
|
77979
78314
|
} catch (_e) {
|
|
@@ -77985,6 +78320,7 @@ async function input(input2, context) {
|
|
|
77985
78320
|
return input2.default ?? "";
|
|
77986
78321
|
}
|
|
77987
78322
|
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
78323
|
+
process.stderr.write("\x07");
|
|
77988
78324
|
const result = await getUserInput(input2.message, {
|
|
77989
78325
|
default: input2.default
|
|
77990
78326
|
});
|
|
@@ -77999,6 +78335,7 @@ async function select(input2, context) {
|
|
|
77999
78335
|
}
|
|
78000
78336
|
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
78001
78337
|
try {
|
|
78338
|
+
process.stderr.write("\x07");
|
|
78002
78339
|
const result = await esm_default5({ message: input2.message, choices: input2.choices });
|
|
78003
78340
|
return result;
|
|
78004
78341
|
} catch (_e) {
|
|
@@ -78188,11 +78525,31 @@ ${defaultContent}
|
|
|
78188
78525
|
return contextParts.join(`
|
|
78189
78526
|
`);
|
|
78190
78527
|
}
|
|
78528
|
+
async function readMemory(input2, context) {
|
|
78529
|
+
const provider3 = context.toolProvider;
|
|
78530
|
+
return await provider3.readMemory(input2.topic) ?? "";
|
|
78531
|
+
}
|
|
78532
|
+
async function listMemoryTopics(_input, context) {
|
|
78533
|
+
const provider3 = context.toolProvider;
|
|
78534
|
+
return provider3.listMemoryTopics();
|
|
78535
|
+
}
|
|
78191
78536
|
async function updateMemory(input2, context) {
|
|
78192
78537
|
const provider3 = context.toolProvider;
|
|
78193
78538
|
const content = "content" in input2 ? input2.content : undefined;
|
|
78194
78539
|
return provider3.updateMemory(input2.operation, input2.topic, content);
|
|
78195
78540
|
}
|
|
78541
|
+
async function listTodoItems(input2, context) {
|
|
78542
|
+
const provider3 = context.toolProvider;
|
|
78543
|
+
return provider3.listTodoItems(input2.id, input2.status);
|
|
78544
|
+
}
|
|
78545
|
+
async function getTodoItem(input2, context) {
|
|
78546
|
+
const provider3 = context.toolProvider;
|
|
78547
|
+
return provider3.getTodoItem(input2.id);
|
|
78548
|
+
}
|
|
78549
|
+
async function updateTodoItem(input2, context) {
|
|
78550
|
+
const provider3 = context.toolProvider;
|
|
78551
|
+
return provider3.updateTodoItem(input2);
|
|
78552
|
+
}
|
|
78196
78553
|
var localToolHandlers = {
|
|
78197
78554
|
createPullRequest,
|
|
78198
78555
|
createCommit,
|
|
@@ -78207,12 +78564,17 @@ var localToolHandlers = {
|
|
|
78207
78564
|
invokeTool,
|
|
78208
78565
|
taskEvent,
|
|
78209
78566
|
getMemoryContext,
|
|
78210
|
-
|
|
78567
|
+
readMemory,
|
|
78568
|
+
listMemoryTopics,
|
|
78569
|
+
updateMemory,
|
|
78570
|
+
listTodoItems,
|
|
78571
|
+
getTodoItem,
|
|
78572
|
+
updateTodoItem
|
|
78211
78573
|
};
|
|
78212
78574
|
async function toolCall(toolCall2, context) {
|
|
78213
|
-
const
|
|
78214
|
-
if (
|
|
78215
|
-
return
|
|
78575
|
+
const handler19 = localToolHandlers[toolCall2.tool];
|
|
78576
|
+
if (handler19) {
|
|
78577
|
+
return handler19(toolCall2.input, context);
|
|
78216
78578
|
}
|
|
78217
78579
|
throw new Error(`Unknown tool: ${toolCall2.tool}`);
|
|
78218
78580
|
}
|
|
@@ -78236,7 +78598,7 @@ async function runWorkflow(workflow2, workflowInput, options) {
|
|
|
78236
78598
|
maxCost: config4.budget
|
|
78237
78599
|
});
|
|
78238
78600
|
const onEvent = printEvent(verbose, usage, process.stderr);
|
|
78239
|
-
const toolProvider = getProvider({ excludeFiles: config4.excludeFiles });
|
|
78601
|
+
const toolProvider = (options.getProvider ?? getProvider)({ excludeFiles: config4.excludeFiles });
|
|
78240
78602
|
const commandConfig = providerConfig.getConfigForCommand(commandName);
|
|
78241
78603
|
if (!commandConfig) {
|
|
78242
78604
|
throw new Error(`No provider configured for command: ${commandName}`);
|
|
@@ -78284,11 +78646,15 @@ Workflow completed successfully.`);
|
|
|
78284
78646
|
return output;
|
|
78285
78647
|
} catch (e) {
|
|
78286
78648
|
const error46 = e;
|
|
78649
|
+
onEvent({
|
|
78650
|
+
kind: "EndTask" /* EndTask */,
|
|
78651
|
+
exitReason: {
|
|
78652
|
+
type: "Error",
|
|
78653
|
+
error: { message: error46.message, stack: error46.stack }
|
|
78654
|
+
}
|
|
78655
|
+
});
|
|
78287
78656
|
if (error46 instanceof UserCancelledError) {
|
|
78288
78657
|
logger.warn("Workflow cancelled by user.");
|
|
78289
|
-
} else {
|
|
78290
|
-
logger.error(`Workflow failed: ${error46.message}`);
|
|
78291
|
-
logger.error(error46);
|
|
78292
78658
|
}
|
|
78293
78659
|
logger.info(usage.getUsageText());
|
|
78294
78660
|
return;
|
|
@@ -78305,14 +78671,33 @@ ${JSON.stringify(schema, null, 2)}
|
|
|
78305
78671
|
\`\`\`
|
|
78306
78672
|
`;
|
|
78307
78673
|
}
|
|
78674
|
+
var TOOL_USAGE_INSTRUCTION = `
|
|
78675
|
+
## Action Line
|
|
78676
|
+
|
|
78677
|
+
Before any tool call, emit a single high-level action line.
|
|
78678
|
+
|
|
78679
|
+
You MUST follow these style constraints for the action line:
|
|
78680
|
+
- NO filler or preambles.
|
|
78681
|
+
- DO NOT use "ok", "okay", "alright".
|
|
78682
|
+
- DO NOT use first person ("I", "I'm", "I will", "I'll", etc.).
|
|
78683
|
+
- NO apologies, hedging, or promises about later work.
|
|
78684
|
+
`;
|
|
78308
78685
|
var MEMORY_USAGE_SECTION = `## Memory Usage
|
|
78309
78686
|
|
|
78310
78687
|
You have access to a memory feature to store and retrieve information across tool calls.
|
|
78311
78688
|
|
|
78312
|
-
|
|
78313
|
-
|
|
78314
|
-
|
|
78315
|
-
-
|
|
78689
|
+
### Topic Organization
|
|
78690
|
+
|
|
78691
|
+
Memory is organized using topics, which are like named containers for different types of information:
|
|
78692
|
+
- **Default topic** (\`:default:\`): Used when no topic is specified. Good for general context.
|
|
78693
|
+
- **Named topics**: Create meaningful topic names to organize different types of information
|
|
78694
|
+
|
|
78695
|
+
### Best Practices
|
|
78696
|
+
|
|
78697
|
+
- Store decisions and context that inform subsequent steps
|
|
78698
|
+
- Use named topics to organize different types of information
|
|
78699
|
+
- Use the default topic for simple, single-context scenarios
|
|
78700
|
+
- Memory persists across all tool calls within the current workflow
|
|
78316
78701
|
`;
|
|
78317
78702
|
var PLANNER_SYSTEM_PROMPT = `Role: Expert software architect and planner.
|
|
78318
78703
|
Goal: Analyze user requests and create detailed, actionable implementation plans for software development tasks.
|
|
@@ -78321,6 +78706,8 @@ You are an expert software architect and planner with deep experience in breakin
|
|
|
78321
78706
|
|
|
78322
78707
|
${MEMORY_USAGE_SECTION}
|
|
78323
78708
|
|
|
78709
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
78710
|
+
|
|
78324
78711
|
## Your Role
|
|
78325
78712
|
|
|
78326
78713
|
As a planner, your expertise lies in:
|
|
@@ -78506,6 +78893,8 @@ You are an expert software architect specializing in creating high-level plans f
|
|
|
78506
78893
|
|
|
78507
78894
|
${MEMORY_USAGE_SECTION}
|
|
78508
78895
|
|
|
78896
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
78897
|
+
|
|
78509
78898
|
## Your Role
|
|
78510
78899
|
|
|
78511
78900
|
As a high-level planner for epics, your expertise lies in:
|
|
@@ -78528,15 +78917,21 @@ Effective planning requires understanding before action:
|
|
|
78528
78917
|
- File system exploration (\`listFiles\`, \`searchFiles\`) reveals structure and patterns.
|
|
78529
78918
|
- Reading existing files (\`readFile\`) shows coding style and conventions.
|
|
78530
78919
|
|
|
78531
|
-
3. **High-Level
|
|
78532
|
-
-
|
|
78533
|
-
-
|
|
78534
|
-
-
|
|
78920
|
+
3. **High-Level Strategy with Detailed Tasks**
|
|
78921
|
+
- "High-level" refers to strategic phases and architectural decisions, not individual implementation steps.
|
|
78922
|
+
- While the plan structure should be strategic (phases, components), each task item must contain detailed implementation guidance.
|
|
78923
|
+
- Each task should include specific file paths, function names, implementation patterns, and technical details.
|
|
78924
|
+
- The plan should be detailed enough that task creation does not require additional codebase exploration.
|
|
78925
|
+
- Example of appropriate detail level:
|
|
78926
|
+
* ❌ Too vague: "Add authentication"
|
|
78927
|
+
* ❌ Too granular: "Add a 20px margin to the button on line 45"
|
|
78928
|
+
* ✅ Appropriate: "Implement authentication endpoints in \`src/api/auth.ts\` with \`POST /api/auth/login\` that validates credentials using bcrypt and returns JWT tokens"
|
|
78535
78929
|
|
|
78536
78930
|
4. **Clarity for AI Implementation**
|
|
78537
|
-
- The plan must be clear enough for AI agents to implement directly.
|
|
78538
|
-
- Each task should be a concrete, implementable piece of work.
|
|
78539
|
-
-
|
|
78931
|
+
- The plan must be clear enough for AI agents to implement directly without further exploration.
|
|
78932
|
+
- Each task should be a concrete, implementable piece of work with all necessary details.
|
|
78933
|
+
- Include specific technical information: file paths, function signatures, dependencies, patterns to follow.
|
|
78934
|
+
- The task creation agent should be able to parse the plan and create todo items without exploring the codebase.
|
|
78540
78935
|
|
|
78541
78936
|
## Your Approach
|
|
78542
78937
|
|
|
@@ -78557,33 +78952,61 @@ For epic-scale work, **checkboxes are RECOMMENDED** to help track progress throu
|
|
|
78557
78952
|
|
|
78558
78953
|
**Recommended Checklist Format**:
|
|
78559
78954
|
- Use markdown checkboxes (\`- [ ] item\`) for major components and tasks
|
|
78955
|
+
- Create nested task breakdowns with 3-4 levels of detail
|
|
78560
78956
|
- Each checkbox represents a distinct, trackable piece of work
|
|
78561
|
-
- Each checkbox item
|
|
78562
|
-
- Group related checkboxes under numbered sections or phases
|
|
78957
|
+
- Each checkbox item must include detailed implementation guidance
|
|
78958
|
+
- Group related checkboxes under numbered sections or phases
|
|
78563
78959
|
- Items will be implemented one at a time iteratively
|
|
78564
78960
|
- After each implementation, the completed item will be marked with \`- [x]\` when the plan is updated
|
|
78565
78961
|
|
|
78566
|
-
**
|
|
78962
|
+
**Implementation Details Requirements**:
|
|
78963
|
+
|
|
78964
|
+
Each task item must specify:
|
|
78965
|
+
- **Exact file paths** for new files or modifications (e.g., \`src/api/auth.ts\`)
|
|
78966
|
+
- **Function signatures and class names** to implement (e.g., \`async function authenticateUser(email: string, password: string)\`)
|
|
78967
|
+
- **Specific patterns from the codebase** to follow (e.g., "Follow the middleware pattern used in \`src/middleware/logger.ts\`")
|
|
78968
|
+
- **Required imports and dependencies** (e.g., "Import \`bcrypt\` for password hashing, use \`jsonwebtoken\` for JWT generation")
|
|
78969
|
+
- **Error handling approach** (e.g., "Use \`ApiError\` class from \`src/errors.ts\`")
|
|
78970
|
+
- **Integration points** with existing code (e.g., "Register middleware in \`src/app.ts\` before route handlers")
|
|
78971
|
+
- **Testing requirements** if applicable (e.g., "Add unit tests in \`src/api/__tests__/auth.test.ts\`")
|
|
78972
|
+
|
|
78973
|
+
**Example checklist format with proper detail**:
|
|
78567
78974
|
\`\`\`
|
|
78568
78975
|
1. Phase 1: Backend API Development
|
|
78569
|
-
- [ ] Design and implement user authentication endpoints
|
|
78976
|
+
- [ ] Design and implement user authentication endpoints in \`src/api/auth.ts\`
|
|
78977
|
+
- [ ] Create \`POST /api/auth/login\` endpoint that accepts email/password in request body, validates using bcrypt, returns JWT token using \`jsonwebtoken\` library with 24h expiration
|
|
78978
|
+
- [ ] Create \`POST /api/auth/register\` endpoint that validates input with zod schema (\`email\`, \`password\` min 8 chars), hashes password with bcrypt (10 rounds), stores in database using Prisma ORM
|
|
78979
|
+
- [ ] Add authentication middleware in \`src/middleware/auth.ts\` that verifies JWT tokens from Authorization header and attaches user object to \`req.user\`
|
|
78570
78980
|
- [ ] Create database schema and migrations
|
|
78571
|
-
|
|
78981
|
+
- [ ] Define User model in \`prisma/schema.prisma\` with fields: id (UUID), email (unique string), passwordHash (string), createdAt (DateTime), updatedAt (DateTime)
|
|
78982
|
+
- [ ] Generate migration with \`npx prisma migrate dev --name add-user-auth\`
|
|
78983
|
+
- [ ] Update \`src/db/client.ts\` to export Prisma client instance
|
|
78984
|
+
- [ ] Implement data validation middleware in \`src/middleware/validation.ts\`
|
|
78985
|
+
- [ ] Create \`validateRequest\` function that accepts zod schema and returns Express middleware
|
|
78986
|
+
- [ ] Add error handling that returns 400 status with validation errors in response body
|
|
78987
|
+
- [ ] Follow error format used in \`src/middleware/errorHandler.ts\`
|
|
78572
78988
|
|
|
78573
78989
|
2. Phase 2: Frontend Integration
|
|
78574
|
-
- [ ] Build authentication UI components
|
|
78575
|
-
|
|
78990
|
+
- [ ] Build authentication UI components in \`src/components/auth/\`
|
|
78991
|
+
- [ ] Create \`LoginForm.tsx\` component with email/password fields using React Hook Form, submit handler calls \`/api/auth/login\`
|
|
78992
|
+
- [ ] Create \`RegisterForm.tsx\` component with email/password/confirmPassword fields, client-side validation matches backend rules
|
|
78993
|
+
- [ ] Add \`AuthContext.tsx\` using React Context API to manage auth state (user object, isAuthenticated boolean, login/logout functions)
|
|
78994
|
+
- [ ] Integrate with backend API using \`src/lib/api.ts\`
|
|
78995
|
+
- [ ] Add \`login(email, password)\` function that calls \`POST /api/auth/login\`, stores JWT in localStorage, returns user object
|
|
78996
|
+
- [ ] Add \`register(email, password)\` function that calls \`POST /api/auth/register\`
|
|
78997
|
+
- [ ] Add \`logout()\` function that removes JWT from localStorage and clears auth state
|
|
78576
78998
|
- [ ] Add error handling and loading states
|
|
78999
|
+
- [ ] Display API errors in form using \`ErrorMessage\` component from \`src/components/ui/ErrorMessage.tsx\`
|
|
79000
|
+
- [ ] Show loading spinner during API calls using \`LoadingSpinner\` component from \`src/components/ui/LoadingSpinner.tsx\`
|
|
79001
|
+
- [ ] Add toast notifications for success/error using \`react-hot-toast\` library
|
|
78577
79002
|
\`\`\`
|
|
78578
79003
|
|
|
78579
|
-
**Alternative Format**:
|
|
78580
|
-
You may also use numbered lists if checkboxes don't fit the task structure. However, each item should still be clear, actionable, and implementable independently.
|
|
78581
|
-
|
|
78582
79004
|
**What to Include**:
|
|
78583
|
-
- Actionable implementation steps
|
|
78584
|
-
-
|
|
78585
|
-
-
|
|
78586
|
-
-
|
|
79005
|
+
- Actionable implementation steps with complete technical specifications
|
|
79006
|
+
- Exact file paths, function names, and implementation patterns
|
|
79007
|
+
- All dependencies, imports, and integration points
|
|
79008
|
+
- Specific technical constraints and requirements
|
|
79009
|
+
- Testing approach if applicable
|
|
78587
79010
|
|
|
78588
79011
|
**What NOT to Include**:
|
|
78589
79012
|
- Future enhancements or scope outside the current task
|
|
@@ -78602,9 +79025,11 @@ Branch names should:
|
|
|
78602
79025
|
|
|
78603
79026
|
1. Analyze the task and the existing plan (if any).
|
|
78604
79027
|
2. If the requirements are clear and you can generate or update the plan:
|
|
78605
|
-
a.
|
|
78606
|
-
b.
|
|
78607
|
-
c.
|
|
79028
|
+
a. **Explore the codebase first** to understand patterns, conventions, and existing implementations
|
|
79029
|
+
b. Provide the plan in the "plan" field using the checklist format with detailed implementation guidance
|
|
79030
|
+
c. Ensure the plan is detailed enough that task creation does not require additional codebase exploration
|
|
79031
|
+
d. Each task item must include specific file paths, function names, implementation patterns, and technical details
|
|
79032
|
+
e. Propose a suitable git branch name in the "branchName" field
|
|
78608
79033
|
3. If the requirements are not clear:
|
|
78609
79034
|
a. Ask a clarifying question in the "question" field
|
|
78610
79035
|
4. If the task is already implemented or no action is needed:
|
|
@@ -78623,9 +79048,12 @@ ${createJsonResponseInstruction({
|
|
|
78623
79048
|
reason: "If no plan is needed, provide a reason here."
|
|
78624
79049
|
})}
|
|
78625
79050
|
`;
|
|
79051
|
+
var BRANCH_NAME_PATTERN = /^[a-zA-Z0-9/_-]+$/;
|
|
78626
79052
|
var EpicPlanSchema = exports_external.object({
|
|
78627
79053
|
plan: exports_external.string().nullish(),
|
|
78628
|
-
branchName: exports_external.string(),
|
|
79054
|
+
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), {
|
|
79055
|
+
message: "Invalid branch name format. Branch names should contain only letters, numbers, hyphens, underscores, and forward slashes."
|
|
79056
|
+
}),
|
|
78629
79057
|
question: exports_external.object({
|
|
78630
79058
|
question: exports_external.string(),
|
|
78631
79059
|
defaultAnswer: exports_external.string().nullish()
|
|
@@ -78647,57 +79075,92 @@ ${task}
|
|
|
78647
79075
|
</task>
|
|
78648
79076
|
${planSection}`;
|
|
78649
79077
|
}
|
|
78650
|
-
var
|
|
78651
|
-
Goal:
|
|
79078
|
+
var EPIC_ADD_TODO_ITEMS_SYSTEM_PROMPT = `Role: Task creation agent
|
|
79079
|
+
Goal: Parse a detailed epic plan and create todo items from the provided task breakdowns.
|
|
78652
79080
|
|
|
78653
|
-
|
|
79081
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
78654
79082
|
|
|
78655
|
-
|
|
79083
|
+
You are a task creation agent responsible for parsing a detailed epic plan and creating todo items that can be executed autonomously by an AI coding agent.
|
|
78656
79084
|
|
|
78657
|
-
## Your
|
|
79085
|
+
## Your Responsibility
|
|
78658
79086
|
|
|
78659
|
-
|
|
78660
|
-
- **
|
|
78661
|
-
- **
|
|
78662
|
-
- **
|
|
79087
|
+
Your goal is to create todo items that are:
|
|
79088
|
+
- **Specific and actionable**: Each item should be clear enough for an AI agent to implement without human intervention
|
|
79089
|
+
- **Well-documented**: Include detailed implementation guidance extracted from the plan
|
|
79090
|
+
- **Context-rich**: Specify relevant files that will be modified or created (as provided in the plan)
|
|
79091
|
+
- **Self-contained**: Each item should be implementable independently with the context from the plan
|
|
78663
79092
|
|
|
78664
|
-
##
|
|
79093
|
+
## Plan Structure Expectations
|
|
78665
79094
|
|
|
78666
|
-
|
|
78667
|
-
|
|
78668
|
-
|
|
78669
|
-
|
|
78670
|
-
|
|
78671
|
-
|
|
78672
|
-
|
|
79095
|
+
The plan you receive contains all necessary implementation details. You should NOT need to explore the codebase because:
|
|
79096
|
+
- Each task in the plan already includes specific file paths
|
|
79097
|
+
- Function and class names are specified in the plan
|
|
79098
|
+
- Implementation patterns and approaches are provided
|
|
79099
|
+
- Dependencies and imports are listed
|
|
79100
|
+
- Technical specifications are included
|
|
79101
|
+
- Integration points are documented
|
|
78673
79102
|
|
|
78674
|
-
|
|
79103
|
+
Your job is to extract these details from the plan and create todo items, not to research or discover them.
|
|
78675
79104
|
|
|
78676
|
-
|
|
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
|
|
79105
|
+
## Todo Item Requirements
|
|
78680
79106
|
|
|
78681
|
-
|
|
79107
|
+
For each task in the plan, create a todo item using the \`updateTodoItem\` tool with:
|
|
78682
79108
|
|
|
78683
|
-
|
|
78684
|
-
-
|
|
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
|
|
79109
|
+
### 1. **title** (required)
|
|
79110
|
+
A concise, action-oriented task name that clearly states what needs to be done.
|
|
78687
79111
|
|
|
78688
|
-
|
|
79112
|
+
**Examples:**
|
|
79113
|
+
- ✅ "Implement user authentication with JWT tokens"
|
|
79114
|
+
- ✅ "Add validation middleware for API endpoints"
|
|
79115
|
+
- ❌ "Authentication" (too vague)
|
|
79116
|
+
|
|
79117
|
+
### 2. **description** (required)
|
|
79118
|
+
Detailed implementation instructions extracted from the plan. Include:
|
|
79119
|
+
|
|
79120
|
+
**Must extract from the plan:**
|
|
79121
|
+
- **Specific files to create or modify** with exact paths (as specified in the plan)
|
|
79122
|
+
- **Function/class names** to implement or modify (as specified in the plan)
|
|
79123
|
+
- **Implementation patterns** to follow (as referenced in the plan)
|
|
79124
|
+
- **Technical requirements** and constraints (as documented in the plan)
|
|
79125
|
+
- **Dependencies** and imports needed (as listed in the plan)
|
|
79126
|
+
- **Integration points** with existing code (as described in the plan)
|
|
79127
|
+
|
|
79128
|
+
**Example of extracting from a detailed plan task:**
|
|
79129
|
+
|
|
79130
|
+
Plan task:
|
|
79131
|
+
\`\`\`
|
|
79132
|
+
- [ ] Add authentication middleware in \`src/middleware/auth.ts\` that verifies JWT tokens from Authorization header and attaches user object to \`req.user\`
|
|
79133
|
+
\`\`\`
|
|
79134
|
+
|
|
79135
|
+
Todo item description:
|
|
79136
|
+
\`\`\`
|
|
79137
|
+
Create a new authentication middleware in \`src/middleware/auth.ts\`:
|
|
79138
|
+
|
|
79139
|
+
1. Implement \`authenticateJWT\` function that:
|
|
79140
|
+
- Extracts JWT token from Authorization header
|
|
79141
|
+
- Verifies token (implementation details from plan)
|
|
79142
|
+
- Attaches user object to \`req.user\`
|
|
79143
|
+
- Returns 401 error for invalid/missing tokens
|
|
79144
|
+
|
|
79145
|
+
2. Export the middleware for use in route definitions
|
|
79146
|
+
\`\`\`
|
|
79147
|
+
|
|
79148
|
+
**Note:** All implementation details should come from the plan. Do not add information not present in the plan.
|
|
79149
|
+
|
|
79150
|
+
## Process
|
|
79151
|
+
|
|
79152
|
+
1. **Read and parse the plan** provided in the user message to identify individual tasks
|
|
79153
|
+
2. **Parse the plan structure** to understand the task hierarchy and details
|
|
79154
|
+
3. **For each task in the plan:**
|
|
79155
|
+
a. Extract the specific files mentioned in the task
|
|
79156
|
+
b. Extract implementation patterns specified in the plan
|
|
79157
|
+
c. Create a detailed description using the plan's guidance
|
|
79158
|
+
d. Identify all relevant files from the plan
|
|
79159
|
+
e. Call \`updateTodoItem\` with operation='add', title and description
|
|
79160
|
+
|
|
79161
|
+
**Important:** Do NOT explore the codebase. All necessary information is already in the plan.
|
|
78689
79162
|
|
|
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
|
-
})}
|
|
78695
79163
|
`;
|
|
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
79164
|
var CODER_SYSTEM_PROMPT = `Role: AI developer.
|
|
78702
79165
|
Goal: Implement the provided plan by writing and modifying code.
|
|
78703
79166
|
|
|
@@ -78705,6 +79168,8 @@ Your task is to implement the plan created and approved in Phase 1.
|
|
|
78705
79168
|
|
|
78706
79169
|
${MEMORY_USAGE_SECTION}
|
|
78707
79170
|
|
|
79171
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79172
|
+
|
|
78708
79173
|
## Implementation Guidelines
|
|
78709
79174
|
|
|
78710
79175
|
### 1. Plan Analysis
|
|
@@ -78778,6 +79243,8 @@ You are an expert software developer. Your task is to fix a project that is fail
|
|
|
78778
79243
|
|
|
78779
79244
|
${MEMORY_USAGE_SECTION}
|
|
78780
79245
|
|
|
79246
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79247
|
+
|
|
78781
79248
|
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
79249
|
|
|
78783
79250
|
Example for successful fix:
|
|
@@ -78815,6 +79282,8 @@ ${stderr || "(empty)"}
|
|
|
78815
79282
|
var CODE_REVIEW_SYSTEM_PROMPT = `Role: Senior software engineer.
|
|
78816
79283
|
Goal: Review code changes and provide specific, actionable feedback on any issues found.
|
|
78817
79284
|
|
|
79285
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79286
|
+
|
|
78818
79287
|
# Code Review Prompt
|
|
78819
79288
|
|
|
78820
79289
|
You are a senior software engineer reviewing code changes.
|
|
@@ -78929,6 +79398,8 @@ ${instructions}
|
|
|
78929
79398
|
var COMMIT_MESSAGE_SYSTEM_PROMPT = `Role: Expert git user.
|
|
78930
79399
|
Goal: Generate a concise and descriptive commit message in conventional commit format based on staged changes.
|
|
78931
79400
|
|
|
79401
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79402
|
+
|
|
78932
79403
|
You are an expert at writing git commit messages.
|
|
78933
79404
|
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
79405
|
|
|
@@ -78941,6 +79412,8 @@ ${createJsonResponseInstruction({
|
|
|
78941
79412
|
var GET_PR_DETAILS_SYSTEM_PROMPT = `Role: Expert developer.
|
|
78942
79413
|
Goal: Generate a pull request title and description based on the branch name, commits, and diff.
|
|
78943
79414
|
|
|
79415
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79416
|
+
|
|
78944
79417
|
You are an expert at creating pull requests.
|
|
78945
79418
|
Based on the provided branch name, commit messages, and diff, generate a title and description for the pull request.
|
|
78946
79419
|
|
|
@@ -78953,6 +79426,8 @@ var INIT_WORKFLOW_ANALYZE_SYSTEM_PROMPT = `
|
|
|
78953
79426
|
Role: Analyzer agent
|
|
78954
79427
|
Goal: Produce a valid polkacodes YAML configuration for the project.
|
|
78955
79428
|
|
|
79429
|
+
${TOOL_USAGE_INSTRUCTION}
|
|
79430
|
+
|
|
78956
79431
|
Workflow
|
|
78957
79432
|
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
79433
|
- Package/build tool (npm, bun, pnpm, etc.)
|
|
@@ -79364,10 +79839,10 @@ var ImplementOutputSchema = exports_external.object({
|
|
|
79364
79839
|
});
|
|
79365
79840
|
var codeWorkflow = async (input2, context) => {
|
|
79366
79841
|
const { logger, step, tools: tools2 } = context;
|
|
79367
|
-
const { task, files, mode = "interactive" } = input2;
|
|
79842
|
+
const { task, files, mode = "interactive", additionalTools, additionalInstructions } = input2;
|
|
79368
79843
|
const summaries = [];
|
|
79369
79844
|
logger.info(`
|
|
79370
|
-
|
|
79845
|
+
Phase 1: Creating implementation plan...
|
|
79371
79846
|
`);
|
|
79372
79847
|
const planResult = await step("plan", async () => {
|
|
79373
79848
|
return await planWorkflow({ task, files, mode: mode === "interactive" ? "confirm" : "noninteractive" }, context);
|
|
@@ -79378,7 +79853,7 @@ var codeWorkflow = async (input2, context) => {
|
|
|
79378
79853
|
}
|
|
79379
79854
|
const { plan, files: planFiles } = planResult;
|
|
79380
79855
|
logger.info(`
|
|
79381
|
-
|
|
79856
|
+
Phase 2: Implementing the plan...
|
|
79382
79857
|
`);
|
|
79383
79858
|
let implementPrompt = getImplementPrompt(plan);
|
|
79384
79859
|
if (planFiles && planFiles.length > 0) {
|
|
@@ -79426,6 +79901,9 @@ ${fileContentString}`;
|
|
|
79426
79901
|
if (mode === "interactive") {
|
|
79427
79902
|
agentTools.push(askFollowupQuestion_default);
|
|
79428
79903
|
}
|
|
79904
|
+
if (additionalTools) {
|
|
79905
|
+
agentTools.push(...additionalTools);
|
|
79906
|
+
}
|
|
79429
79907
|
const res = await step("implement", async () => {
|
|
79430
79908
|
const defaultContext = await getDefaultContext();
|
|
79431
79909
|
const memoryContext = await tools2.getMemoryContext();
|
|
@@ -79442,8 +79920,11 @@ ${memoryContext}`;
|
|
|
79442
79920
|
${memoryContext}`
|
|
79443
79921
|
});
|
|
79444
79922
|
}
|
|
79923
|
+
const systemPrompt = additionalInstructions ? `${CODER_SYSTEM_PROMPT}
|
|
79924
|
+
|
|
79925
|
+
${additionalInstructions}` : CODER_SYSTEM_PROMPT;
|
|
79445
79926
|
return await agentWorkflow({
|
|
79446
|
-
systemPrompt
|
|
79927
|
+
systemPrompt,
|
|
79447
79928
|
userMessage: [{ role: "user", content: userContent }],
|
|
79448
79929
|
tools: agentTools,
|
|
79449
79930
|
outputSchema: ImplementOutputSchema
|
|
@@ -79453,13 +79934,13 @@ ${memoryContext}`
|
|
|
79453
79934
|
const { summary, bailReason } = res.object;
|
|
79454
79935
|
if (bailReason) {
|
|
79455
79936
|
logger.error(`
|
|
79456
|
-
|
|
79937
|
+
Implementation failed: ${bailReason}
|
|
79457
79938
|
`);
|
|
79458
79939
|
return { success: false, reason: bailReason, summaries };
|
|
79459
79940
|
}
|
|
79460
79941
|
if (summary) {
|
|
79461
79942
|
logger.info(`
|
|
79462
|
-
|
|
79943
|
+
Implementation complete!
|
|
79463
79944
|
`);
|
|
79464
79945
|
summaries.push(summary);
|
|
79465
79946
|
logger.info(`Summary: ${summary}`);
|
|
@@ -79472,20 +79953,20 @@ ${memoryContext}`
|
|
|
79472
79953
|
});
|
|
79473
79954
|
} else {
|
|
79474
79955
|
logger.info(`
|
|
79475
|
-
|
|
79956
|
+
Implementation complete!
|
|
79476
79957
|
`);
|
|
79477
79958
|
}
|
|
79478
79959
|
} else if (res.type === "Exit" /* Exit */) {
|
|
79479
79960
|
logger.info(`
|
|
79480
|
-
|
|
79961
|
+
Implementation complete!
|
|
79481
79962
|
`);
|
|
79482
79963
|
} else {
|
|
79483
79964
|
logger.warn(`
|
|
79484
|
-
|
|
79965
|
+
Warning: Implementation failed. Please check the output for errors.
|
|
79485
79966
|
`, res);
|
|
79486
79967
|
}
|
|
79487
79968
|
logger.info(`
|
|
79488
|
-
|
|
79969
|
+
Phase 3: Checking for errors...
|
|
79489
79970
|
`);
|
|
79490
79971
|
const fixResult = await step("fix", async () => {
|
|
79491
79972
|
return await fixWorkflow({ interactive: false, task: input2.task }, context);
|
|
@@ -79895,98 +80376,67 @@ ${provider3.toUpperCase()}_API_KEY=${providerConfig.apiKey}`;
|
|
|
79895
80376
|
});
|
|
79896
80377
|
return { configPath };
|
|
79897
80378
|
};
|
|
79898
|
-
// src/workflows/epic.
|
|
79899
|
-
|
|
79900
|
-
var
|
|
79901
|
-
|
|
79902
|
-
|
|
79903
|
-
|
|
79904
|
-
|
|
79905
|
-
|
|
79906
|
-
|
|
80379
|
+
// src/workflows/epic-context.ts
|
|
80380
|
+
import { promises as fs3 } from "node:fs";
|
|
80381
|
+
var EPIC_CONTEXT_FILE = ".epic.yml";
|
|
80382
|
+
var EpicContextSchema = exports_external.object({
|
|
80383
|
+
task: exports_external.string().nullish(),
|
|
80384
|
+
plan: exports_external.string().nullish(),
|
|
80385
|
+
branchName: exports_external.string().nullish(),
|
|
80386
|
+
todos: exports_external.array(TodoItemSchema).nullish(),
|
|
80387
|
+
memory: exports_external.record(exports_external.string(), exports_external.string()).nullish()
|
|
80388
|
+
});
|
|
80389
|
+
var saveEpicContext = async (context) => {
|
|
80390
|
+
const yamlString = $stringify(context);
|
|
80391
|
+
await fs3.writeFile(EPIC_CONTEXT_FILE, yamlString, "utf-8");
|
|
80392
|
+
};
|
|
80393
|
+
var loadEpicContext = async () => {
|
|
80394
|
+
let fileContent;
|
|
80395
|
+
try {
|
|
80396
|
+
fileContent = await fs3.readFile(EPIC_CONTEXT_FILE, "utf-8");
|
|
80397
|
+
} catch {
|
|
80398
|
+
return {};
|
|
79907
80399
|
}
|
|
79908
|
-
|
|
79909
|
-
|
|
80400
|
+
try {
|
|
80401
|
+
const loaded = $parse(fileContent);
|
|
80402
|
+
return EpicContextSchema.parse(loaded);
|
|
80403
|
+
} catch (error46) {
|
|
80404
|
+
console.error("Error parsing epic context file:", EPIC_CONTEXT_FILE, error46);
|
|
80405
|
+
return {};
|
|
79910
80406
|
}
|
|
79911
|
-
|
|
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>
|
|
80407
|
+
};
|
|
79970
80408
|
|
|
79971
|
-
|
|
80409
|
+
class EpicMemoryStore {
|
|
80410
|
+
#context;
|
|
80411
|
+
constructor(context) {
|
|
80412
|
+
this.#context = context;
|
|
80413
|
+
}
|
|
80414
|
+
async read() {
|
|
80415
|
+
return this.#context.memory ?? {};
|
|
80416
|
+
}
|
|
80417
|
+
async write(data) {
|
|
80418
|
+
this.#context.memory = data;
|
|
80419
|
+
await saveEpicContext(this.#context);
|
|
80420
|
+
}
|
|
80421
|
+
}
|
|
79972
80422
|
|
|
79973
|
-
|
|
79974
|
-
|
|
79975
|
-
|
|
79976
|
-
|
|
79977
|
-
|
|
79978
|
-
|
|
79979
|
-
|
|
79980
|
-
|
|
79981
|
-
|
|
79982
|
-
|
|
79983
|
-
|
|
79984
|
-
`);
|
|
79985
|
-
return { passed: false };
|
|
79986
|
-
}
|
|
80423
|
+
class EpicTodoItemStore {
|
|
80424
|
+
#context;
|
|
80425
|
+
constructor(context) {
|
|
80426
|
+
this.#context = context;
|
|
80427
|
+
}
|
|
80428
|
+
async read() {
|
|
80429
|
+
return this.#context.todos ?? [];
|
|
80430
|
+
}
|
|
80431
|
+
async write(data) {
|
|
80432
|
+
this.#context.todos = data;
|
|
80433
|
+
await saveEpicContext(this.#context);
|
|
79987
80434
|
}
|
|
79988
|
-
return { passed: false };
|
|
79989
80435
|
}
|
|
80436
|
+
|
|
80437
|
+
// src/workflows/epic.workflow.ts
|
|
80438
|
+
var MAX_REVIEW_RETRIES = 5;
|
|
80439
|
+
var TODO_HANDLING_INSTRUCTIONS = `If you discover that a task is larger than you thought, or that a new task is required, you can add a // TODO comment in the code and create a todo item for it. This will allow you to continue with the current task and address the larger issue later.`;
|
|
79990
80440
|
async function createPlan2(input2, context) {
|
|
79991
80441
|
const { task, plan, files, feedback } = input2;
|
|
79992
80442
|
const content = [{ type: "text", text: getPlanPrompt(task, plan) }];
|
|
@@ -80036,316 +80486,517 @@ ${feedback}`
|
|
|
80036
80486
|
}
|
|
80037
80487
|
return { plan: "", reason: "Usage limit exceeded.", type: "Exit" /* Exit */, branchName: "" };
|
|
80038
80488
|
}
|
|
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
|
-
|
|
80489
|
+
async function createAndApprovePlan(task, context) {
|
|
80490
|
+
const { logger, step, tools: tools2 } = context;
|
|
80491
|
+
logger.info(`Phase 2: Creating high-level plan...
|
|
80492
|
+
`);
|
|
80493
|
+
let feedback;
|
|
80494
|
+
let highLevelPlan;
|
|
80495
|
+
let branchName;
|
|
80496
|
+
let planAttempt = 1;
|
|
80497
|
+
try {
|
|
80498
|
+
while (true) {
|
|
80499
|
+
const result = await step(`plan-${planAttempt}`, () => createPlan2({ task, feedback }, context));
|
|
80500
|
+
planAttempt++;
|
|
80501
|
+
if (result.question) {
|
|
80502
|
+
const answer = await tools2.input({
|
|
80503
|
+
message: result.question.question,
|
|
80504
|
+
default: result.question.defaultAnswer || undefined
|
|
80505
|
+
});
|
|
80506
|
+
feedback = `The user answered the question "${result.question.question}" with: "${answer}"`;
|
|
80507
|
+
continue;
|
|
80508
|
+
}
|
|
80509
|
+
if (!result.plan) {
|
|
80510
|
+
if (result.reason) {
|
|
80511
|
+
logger.info(`No plan created. Reason: ${result.reason}`);
|
|
80512
|
+
} else {
|
|
80513
|
+
logger.info("No plan created.");
|
|
80514
|
+
}
|
|
80515
|
+
return null;
|
|
80516
|
+
}
|
|
80517
|
+
logger.info(`Plan:
|
|
80518
|
+
${result.plan}`);
|
|
80519
|
+
if (result.branchName) {
|
|
80520
|
+
logger.info(`Suggested branch name: ${result.branchName}`);
|
|
80521
|
+
}
|
|
80522
|
+
feedback = await tools2.input({ message: "Press Enter to approve the plan, or provide feedback to refine it." });
|
|
80523
|
+
if (feedback.trim() === "") {
|
|
80524
|
+
highLevelPlan = result.plan;
|
|
80525
|
+
branchName = result.branchName;
|
|
80526
|
+
break;
|
|
80527
|
+
}
|
|
80528
|
+
}
|
|
80529
|
+
} catch (e) {
|
|
80530
|
+
if (e instanceof UserCancelledError) {
|
|
80531
|
+
logger.info("Plan creation cancelled by user.");
|
|
80532
|
+
return null;
|
|
80533
|
+
}
|
|
80534
|
+
throw e;
|
|
80063
80535
|
}
|
|
80064
|
-
|
|
80065
|
-
|
|
80066
|
-
|
|
80067
|
-
|
|
80068
|
-
|
|
80069
|
-
|
|
80536
|
+
if (!highLevelPlan) {
|
|
80537
|
+
logger.info("Plan not approved. Exiting.");
|
|
80538
|
+
return null;
|
|
80539
|
+
}
|
|
80540
|
+
if (!branchName) {
|
|
80541
|
+
logger.error("Error: No branch name was generated from the plan. Exiting.");
|
|
80542
|
+
return null;
|
|
80543
|
+
}
|
|
80544
|
+
logger.info(`High-level plan approved.
|
|
80545
|
+
`);
|
|
80546
|
+
return { plan: highLevelPlan, branchName };
|
|
80547
|
+
}
|
|
80548
|
+
async function createFeatureBranch(branchName, context) {
|
|
80549
|
+
const { logger, step, tools: tools2 } = context;
|
|
80550
|
+
logger.info(`Phase 3: Creating/switching to feature branch...
|
|
80551
|
+
`);
|
|
80552
|
+
const branchExistsResult = await step("checkBranchExists", async () => await tools2.executeCommand({ command: "git", args: ["rev-parse", "--verify", branchName] }));
|
|
80553
|
+
if (branchExistsResult.exitCode === 0) {
|
|
80554
|
+
const currentBranchResult = await step("getCurrentBranch", async () => tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] }));
|
|
80555
|
+
const currentBranch = currentBranchResult.stdout.trim();
|
|
80556
|
+
if (currentBranch !== branchName) {
|
|
80557
|
+
logger.info(`Branch '${branchName}' already exists. Switching to it...`);
|
|
80558
|
+
const checkoutResult = await step("checkoutBranch", async () => await tools2.executeCommand({ command: "git", args: ["checkout", branchName] }));
|
|
80559
|
+
if (checkoutResult.exitCode !== 0) {
|
|
80560
|
+
logger.error(`Error: Failed to switch to branch '${branchName}'. Git command failed.`);
|
|
80561
|
+
return { success: false, branchName: null };
|
|
80562
|
+
}
|
|
80563
|
+
} else {
|
|
80564
|
+
logger.info(`Already on branch '${branchName}'.`);
|
|
80565
|
+
}
|
|
80566
|
+
} else {
|
|
80567
|
+
logger.info(`Creating new branch '${branchName}'...`);
|
|
80568
|
+
const createBranchResult = await step("createBranch", async () => await tools2.executeCommand({ command: "git", args: ["checkout", "-b", branchName] }));
|
|
80569
|
+
if (createBranchResult.exitCode !== 0) {
|
|
80570
|
+
logger.error(`Error: Failed to create branch '${branchName}'. Git command failed.`);
|
|
80571
|
+
return { success: false, branchName: null };
|
|
80572
|
+
}
|
|
80573
|
+
}
|
|
80574
|
+
logger.info(`Successfully on branch '${branchName}'.
|
|
80575
|
+
`);
|
|
80576
|
+
return { success: true, branchName };
|
|
80070
80577
|
}
|
|
80071
|
-
async function
|
|
80578
|
+
async function addTodoItemsFromPlan(plan, context) {
|
|
80072
80579
|
const { logger, step, tools: tools2 } = context;
|
|
80073
|
-
logger.info(
|
|
80580
|
+
logger.info(`Phase 4: Creating todo items from plan...
|
|
80581
|
+
`);
|
|
80582
|
+
await step("add-todo-items", async () => {
|
|
80583
|
+
await agentWorkflow({
|
|
80584
|
+
systemPrompt: EPIC_ADD_TODO_ITEMS_SYSTEM_PROMPT,
|
|
80585
|
+
userMessage: [{ role: "user", content: `Please create the todo items based on the plan
|
|
80586
|
+
<plan>
|
|
80587
|
+
${plan}</plan>` }],
|
|
80588
|
+
tools: [readFile_default, searchFiles_default, listFiles_default, readMemory_default, getTodoItem_default, listTodoItems_default, updateTodoItem_default, updateMemory_default, listMemoryTopics_default]
|
|
80589
|
+
}, context);
|
|
80590
|
+
});
|
|
80591
|
+
const todos = await tools2.listTodoItems({});
|
|
80592
|
+
logger.info(`Created ${todos.length} todo items.
|
|
80593
|
+
`);
|
|
80594
|
+
}
|
|
80595
|
+
async function runPreflightChecks(epicContext, context) {
|
|
80596
|
+
const { logger, step, tools: tools2 } = context;
|
|
80597
|
+
logger.info(`Phase 1: Running pre-flight checks...
|
|
80074
80598
|
`);
|
|
80075
80599
|
const gitCheckResult = await step("gitCheck", async () => tools2.executeCommand({ command: "git", args: ["rev-parse", "--git-dir"] }));
|
|
80076
80600
|
if (gitCheckResult.exitCode !== 0) {
|
|
80077
|
-
logger.error("
|
|
80078
|
-
logger.info("
|
|
80079
|
-
return
|
|
80601
|
+
logger.error("Error: Git is not initialized in this directory. Please run `git init` first.");
|
|
80602
|
+
logger.info("Suggestion: Run `git init` to initialize a git repository.\n");
|
|
80603
|
+
return false;
|
|
80604
|
+
}
|
|
80605
|
+
if (epicContext.plan) {
|
|
80606
|
+
logger.info("Found an existing `.epic.yml` file.");
|
|
80607
|
+
if (epicContext.branchName) {
|
|
80608
|
+
const currentBranchResult = await step("getCurrentBranch", async () => tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] }));
|
|
80609
|
+
const currentBranch = currentBranchResult.stdout.trim();
|
|
80610
|
+
if (currentBranch !== epicContext.branchName) {
|
|
80611
|
+
throw new Error(`You are on branch '${currentBranch}' but the epic was started on branch '${epicContext.branchName}'. Please switch to the correct branch to resume.`);
|
|
80612
|
+
}
|
|
80613
|
+
}
|
|
80614
|
+
logger.info("Resuming previous epic session.");
|
|
80615
|
+
return true;
|
|
80080
80616
|
}
|
|
80081
80617
|
const gitStatusResult = await step("gitStatus", async () => tools2.executeCommand({ command: "git status --porcelain", shell: true }));
|
|
80082
80618
|
if (gitStatusResult.stdout.trim() !== "") {
|
|
80083
|
-
logger.error("
|
|
80084
|
-
logger.info("
|
|
80085
|
-
return
|
|
80619
|
+
logger.error("Error: Your working directory is not clean. Please stash or commit your changes before running the epic workflow.");
|
|
80620
|
+
logger.info("Suggestion: Run `git add .` and `git commit` to clean your working directory, or `git stash` to temporarily save changes.\n");
|
|
80621
|
+
return false;
|
|
80086
80622
|
}
|
|
80087
|
-
logger.info(
|
|
80623
|
+
logger.info(`Pre-flight checks passed.
|
|
80088
80624
|
`);
|
|
80089
|
-
return
|
|
80625
|
+
return true;
|
|
80090
80626
|
}
|
|
80091
|
-
|
|
80627
|
+
async function performReviewAndFixCycle(iterationCount, taskItem, highLevelPlan, context) {
|
|
80092
80628
|
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...
|
|
80629
|
+
for (let i = 0;i < MAX_REVIEW_RETRIES; i++) {
|
|
80630
|
+
const diffResult = await tools2.executeCommand({ command: "git", args: ["diff", "--name-status", "HEAD~1", "HEAD"] });
|
|
80631
|
+
const changedFiles = parseGitDiffNameStatus(diffResult.stdout);
|
|
80632
|
+
if (changedFiles.length === 0) {
|
|
80633
|
+
logger.info(`No files were changed. Skipping review.
|
|
80107
80634
|
`);
|
|
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;
|
|
80635
|
+
return { passed: true };
|
|
80154
80636
|
}
|
|
80155
|
-
|
|
80156
|
-
|
|
80157
|
-
|
|
80637
|
+
logger.info(`
|
|
80638
|
+
Review iteration ${i + 1}/${MAX_REVIEW_RETRIES}`);
|
|
80639
|
+
logger.info(` Changed files: ${changedFiles.length}`);
|
|
80640
|
+
const changeInfo = {
|
|
80641
|
+
commitRange: "HEAD~1...HEAD",
|
|
80642
|
+
changedFiles
|
|
80643
|
+
};
|
|
80644
|
+
const reviewAgentResult = await step(`review-${iterationCount}-${i}`, async () => {
|
|
80645
|
+
const defaultContext = await getDefaultContext();
|
|
80646
|
+
const memoryContext = await tools2.getMemoryContext();
|
|
80647
|
+
const userMessage = `${defaultContext}
|
|
80648
|
+
${memoryContext}
|
|
80649
|
+
|
|
80650
|
+
${formatReviewToolInput(changeInfo)}`;
|
|
80651
|
+
return await agentWorkflow({
|
|
80652
|
+
systemPrompt: CODE_REVIEW_SYSTEM_PROMPT,
|
|
80653
|
+
userMessage: [{ role: "user", content: userMessage }],
|
|
80654
|
+
tools: [readFile_default, readBinaryFile_default, searchFiles_default, listFiles_default, gitDiff_default, readMemory_default, updateMemory_default, listMemoryTopics_default],
|
|
80655
|
+
outputSchema: reviewOutputSchema
|
|
80656
|
+
}, context);
|
|
80657
|
+
});
|
|
80658
|
+
if (reviewAgentResult.type !== "Exit" /* Exit */) {
|
|
80659
|
+
logger.error(`Review agent failed with status: ${reviewAgentResult.type}.`);
|
|
80660
|
+
break;
|
|
80158
80661
|
}
|
|
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...
|
|
80662
|
+
const reviewResult = reviewAgentResult.object;
|
|
80663
|
+
if (!reviewResult || !reviewResult.specificReviews || reviewResult.specificReviews.length === 0) {
|
|
80664
|
+
logger.info(`Review passed. No issues found.
|
|
80172
80665
|
`);
|
|
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
|
-
}
|
|
80666
|
+
return { passed: true };
|
|
80197
80667
|
}
|
|
80198
|
-
|
|
80199
|
-
|
|
80668
|
+
logger.warn(`Warning: Review found ${reviewResult.specificReviews.length} issue(s). Attempting to fix...
|
|
80669
|
+
`);
|
|
80670
|
+
for (const [idx, review] of reviewResult.specificReviews.entries()) {
|
|
80671
|
+
logger.warn(` ${idx + 1}. ${review.file}:${review.lines}`);
|
|
80200
80672
|
}
|
|
80201
|
-
|
|
80202
|
-
|
|
80673
|
+
logger.warn("");
|
|
80674
|
+
const reviewSummary = reviewResult.specificReviews.map((r) => `File: ${r.file} (lines: ${r.lines})
|
|
80675
|
+
Review: ${r.review}`).join(`
|
|
80676
|
+
|
|
80203
80677
|
`);
|
|
80204
|
-
|
|
80205
|
-
|
|
80206
|
-
|
|
80207
|
-
|
|
80208
|
-
|
|
80209
|
-
|
|
80678
|
+
const fixTask = `You are working on an epic. The original task was: "${taskItem}".
|
|
80679
|
+
|
|
80680
|
+
Here is the full plan for context:
|
|
80681
|
+
<plan>
|
|
80682
|
+
${highLevelPlan}
|
|
80683
|
+
</plan>
|
|
80684
|
+
|
|
80685
|
+
After an initial implementation, a review found the following issues. Please fix them:
|
|
80686
|
+
|
|
80687
|
+
${reviewSummary}`;
|
|
80688
|
+
await step(`fix-${iterationCount}-${i}`, async () => {
|
|
80689
|
+
await codeWorkflow({
|
|
80690
|
+
task: fixTask,
|
|
80691
|
+
mode: "noninteractive",
|
|
80692
|
+
additionalInstructions: TODO_HANDLING_INSTRUCTIONS,
|
|
80693
|
+
additionalTools: [getTodoItem_default, listTodoItems_default, updateTodoItem_default]
|
|
80694
|
+
}, context);
|
|
80210
80695
|
});
|
|
80211
|
-
await
|
|
80212
|
-
|
|
80213
|
-
|
|
80214
|
-
|
|
80215
|
-
|
|
80216
|
-
|
|
80696
|
+
await step(`commit-fix-${iterationCount}-${i}`, async () => {
|
|
80697
|
+
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
80698
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "--amend", "--no-edit"] });
|
|
80699
|
+
});
|
|
80700
|
+
if (i === MAX_REVIEW_RETRIES - 1) {
|
|
80701
|
+
logger.error(`
|
|
80702
|
+
Max retries (${MAX_REVIEW_RETRIES}) reached. Moving to the next task, but issues might remain.
|
|
80703
|
+
`);
|
|
80704
|
+
return { passed: false };
|
|
80705
|
+
}
|
|
80217
80706
|
}
|
|
80218
|
-
|
|
80219
|
-
|
|
80707
|
+
return { passed: false };
|
|
80708
|
+
}
|
|
80709
|
+
async function runImplementationLoop(context, highLevelPlan) {
|
|
80710
|
+
const { logger, step, tools: tools2 } = context;
|
|
80711
|
+
const commitMessages = [];
|
|
80712
|
+
logger.info(`Phase 5: Iterative Implementation Loop...
|
|
80220
80713
|
`);
|
|
80221
80714
|
logger.info(`${"=".repeat(80)}
|
|
80222
80715
|
`);
|
|
80223
|
-
let currentPlan = highLevelPlan;
|
|
80224
80716
|
let iterationCount = 0;
|
|
80225
80717
|
let isComplete = false;
|
|
80226
80718
|
let nextTask = null;
|
|
80227
|
-
|
|
80228
|
-
|
|
80229
|
-
|
|
80230
|
-
|
|
80231
|
-
|
|
80232
|
-
|
|
80233
|
-
|
|
80234
|
-
|
|
80235
|
-
|
|
80236
|
-
|
|
80237
|
-
|
|
80238
|
-
|
|
80239
|
-
|
|
80240
|
-
|
|
80241
|
-
|
|
80719
|
+
let nextTaskId = null;
|
|
80720
|
+
const initialTasks = await step("get-initial-tasks", async () => {
|
|
80721
|
+
return await tools2.listTodoItems({ status: "open" });
|
|
80722
|
+
});
|
|
80723
|
+
if (initialTasks.length > 0) {
|
|
80724
|
+
const firstTask = initialTasks[0];
|
|
80725
|
+
nextTask = firstTask.title;
|
|
80726
|
+
nextTaskId = firstTask.id;
|
|
80727
|
+
} else {
|
|
80728
|
+
isComplete = true;
|
|
80729
|
+
}
|
|
80730
|
+
while (!isComplete && nextTask && nextTaskId) {
|
|
80731
|
+
iterationCount++;
|
|
80732
|
+
const taskStartTime = Date.now();
|
|
80733
|
+
logger.info(`
|
|
80734
|
+
${"-".repeat(80)}`);
|
|
80735
|
+
logger.info(`Iteration ${iterationCount}`);
|
|
80736
|
+
logger.info(`${"-".repeat(80)}`);
|
|
80737
|
+
logger.info(`${nextTask}
|
|
80242
80738
|
`);
|
|
80243
|
-
|
|
80244
|
-
const
|
|
80245
|
-
const taskWithContext = `You are working on an epic. Here is the full plan:
|
|
80739
|
+
await step(`task-${iterationCount}`, async () => {
|
|
80740
|
+
const taskWithContext = `You are working on an epic. Here is the full plan:
|
|
80246
80741
|
|
|
80247
80742
|
<plan>
|
|
80248
|
-
${
|
|
80743
|
+
${highLevelPlan}
|
|
80249
80744
|
</plan>
|
|
80250
80745
|
|
|
80251
80746
|
Your current task is to implement this specific item:
|
|
80252
80747
|
${nextTask}
|
|
80253
80748
|
|
|
80254
80749
|
Focus only on this item, but use the plan for context.`;
|
|
80255
|
-
|
|
80256
|
-
|
|
80257
|
-
|
|
80258
|
-
|
|
80259
|
-
|
|
80260
|
-
}
|
|
80261
|
-
|
|
80262
|
-
|
|
80263
|
-
|
|
80264
|
-
await
|
|
80265
|
-
|
|
80266
|
-
|
|
80267
|
-
|
|
80268
|
-
|
|
80269
|
-
|
|
80270
|
-
|
|
80271
|
-
|
|
80272
|
-
|
|
80273
|
-
|
|
80274
|
-
}
|
|
80275
|
-
|
|
80276
|
-
|
|
80277
|
-
|
|
80278
|
-
|
|
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`;
|
|
80294
|
-
}
|
|
80295
|
-
logger.info(`
|
|
80296
|
-
\uD83D\uDCCA Progress: ${progressMessage}`);
|
|
80297
|
-
if (isComplete) {
|
|
80298
|
-
logger.info(`✅ All tasks complete!
|
|
80299
|
-
`);
|
|
80300
|
-
break;
|
|
80750
|
+
return await codeWorkflow({
|
|
80751
|
+
task: taskWithContext,
|
|
80752
|
+
mode: "noninteractive",
|
|
80753
|
+
additionalInstructions: TODO_HANDLING_INSTRUCTIONS,
|
|
80754
|
+
additionalTools: [getTodoItem_default, listTodoItems_default, updateTodoItem_default]
|
|
80755
|
+
}, context);
|
|
80756
|
+
});
|
|
80757
|
+
const commitMessage = `feat: ${nextTask}`;
|
|
80758
|
+
await step(`commit-initial-${iterationCount}`, async () => {
|
|
80759
|
+
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
80760
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "-m", commitMessage] });
|
|
80761
|
+
});
|
|
80762
|
+
commitMessages.push(commitMessage);
|
|
80763
|
+
const { passed: reviewPassed } = await performReviewAndFixCycle(iterationCount, nextTask, highLevelPlan, context);
|
|
80764
|
+
const taskElapsed = Date.now() - taskStartTime;
|
|
80765
|
+
const taskElapsedTime = formatElapsedTime(taskElapsed);
|
|
80766
|
+
if (reviewPassed) {
|
|
80767
|
+
logger.info(`Iteration ${iterationCount} completed successfully (${taskElapsedTime})`);
|
|
80768
|
+
} else {
|
|
80769
|
+
logger.warn(`Warning: Iteration ${iterationCount} completed with potential issues (${taskElapsedTime})`);
|
|
80770
|
+
}
|
|
80771
|
+
await step(`update-task-status-${iterationCount}`, async () => {
|
|
80772
|
+
if (!nextTaskId) {
|
|
80773
|
+
throw new Error("Invariant violation: nextTaskId is null inside the implementation loop.");
|
|
80301
80774
|
}
|
|
80302
|
-
|
|
80303
|
-
|
|
80775
|
+
await tools2.updateTodoItem({ operation: "update", id: nextTaskId, status: "completed" });
|
|
80776
|
+
});
|
|
80777
|
+
const openTasks = await step(`get-next-task-${iterationCount}`, async () => {
|
|
80778
|
+
return await tools2.listTodoItems({ status: "open" });
|
|
80779
|
+
});
|
|
80780
|
+
if (openTasks.length > 0) {
|
|
80781
|
+
const nextTodo = openTasks[0];
|
|
80782
|
+
nextTask = nextTodo.title;
|
|
80783
|
+
nextTaskId = nextTodo.id;
|
|
80784
|
+
isComplete = false;
|
|
80785
|
+
} else {
|
|
80786
|
+
nextTask = null;
|
|
80787
|
+
nextTaskId = null;
|
|
80788
|
+
isComplete = true;
|
|
80789
|
+
}
|
|
80790
|
+
const allTodos = await tools2.listTodoItems({});
|
|
80791
|
+
const completedTodos = allTodos.filter((t) => t.status === "completed").length;
|
|
80792
|
+
const totalTodos = allTodos.length;
|
|
80793
|
+
let progressMessage = "";
|
|
80794
|
+
if (totalTodos > 0) {
|
|
80795
|
+
progressMessage = `${completedTodos}/${totalTodos} items completed`;
|
|
80796
|
+
} else {
|
|
80797
|
+
progressMessage = `Iteration ${iterationCount} completed`;
|
|
80798
|
+
}
|
|
80799
|
+
logger.info(`
|
|
80800
|
+
Progress: ${progressMessage}`);
|
|
80801
|
+
if (isComplete) {
|
|
80802
|
+
logger.info(`All tasks complete!
|
|
80304
80803
|
`);
|
|
80305
|
-
|
|
80306
|
-
|
|
80804
|
+
break;
|
|
80805
|
+
}
|
|
80806
|
+
if (nextTask) {
|
|
80807
|
+
logger.info(`Next task: ${nextTask}
|
|
80307
80808
|
`);
|
|
80308
80809
|
}
|
|
80309
|
-
|
|
80310
|
-
logger.error(`
|
|
80311
|
-
❌ Epic workflow failed: ${error46 instanceof Error ? error46.message : String(error46)}`);
|
|
80312
|
-
logger.info(`
|
|
80313
|
-
Branch '${branchName}' was created but work is incomplete.`);
|
|
80314
|
-
logger.info(`To cleanup: git checkout <previous-branch> && git branch -D ${branchName}
|
|
80810
|
+
logger.info(`${"-".repeat(80)}
|
|
80315
80811
|
`);
|
|
80316
|
-
await tools2.updateMemory({ operation: "remove", topic: "epic-context" });
|
|
80317
|
-
await tools2.updateMemory({ operation: "remove", topic: "epic-plan" });
|
|
80318
|
-
throw error46;
|
|
80319
80812
|
}
|
|
80320
|
-
|
|
80321
|
-
|
|
80322
|
-
|
|
80323
|
-
logger
|
|
80324
|
-
${"=".repeat(80)}`);
|
|
80325
|
-
logger.info("\uD83C\uDF89 Epic Workflow Complete!");
|
|
80326
|
-
logger.info(`${"=".repeat(80)}`);
|
|
80813
|
+
return commitMessages;
|
|
80814
|
+
}
|
|
80815
|
+
async function performFinalReviewAndFix(context, highLevelPlan) {
|
|
80816
|
+
const { logger, step, tools: tools2 } = context;
|
|
80327
80817
|
logger.info(`
|
|
80328
|
-
|
|
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}
|
|
80818
|
+
Phase 6: Final Review and Fixup...
|
|
80334
80819
|
`);
|
|
80335
|
-
|
|
80336
|
-
|
|
80337
|
-
logger.
|
|
80820
|
+
const ghCheckResult = await tools2.executeCommand({ command: "gh", args: ["--version"] });
|
|
80821
|
+
if (ghCheckResult.exitCode !== 0) {
|
|
80822
|
+
logger.warn("Warning: GitHub CLI (gh) is not installed. Skipping final review step. Please install it from https://cli.github.com/ to enable final reviews.");
|
|
80823
|
+
return { passed: true };
|
|
80824
|
+
}
|
|
80825
|
+
const defaultBranchResult = await tools2.executeCommand({
|
|
80826
|
+
command: "gh",
|
|
80827
|
+
args: ["repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"]
|
|
80338
80828
|
});
|
|
80339
|
-
|
|
80340
|
-
|
|
80341
|
-
|
|
80342
|
-
|
|
80343
|
-
|
|
80829
|
+
const defaultBranch = defaultBranchResult.stdout.trim();
|
|
80830
|
+
const currentBranchResult = await tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] });
|
|
80831
|
+
const currentBranch = currentBranchResult.stdout.trim();
|
|
80832
|
+
if (currentBranch === defaultBranch) {
|
|
80833
|
+
logger.info(`You are on the default branch ('${defaultBranch}'). No final review needed.`);
|
|
80834
|
+
return { passed: true };
|
|
80835
|
+
}
|
|
80836
|
+
const commitRange = `${defaultBranch}...${currentBranch}`;
|
|
80837
|
+
for (let i = 0;i < MAX_REVIEW_RETRIES; i++) {
|
|
80838
|
+
const diffResult = await tools2.executeCommand({ command: "git", args: ["diff", "--name-status", commitRange] });
|
|
80839
|
+
const changedFiles = parseGitDiffNameStatus(diffResult.stdout);
|
|
80840
|
+
if (changedFiles.length === 0) {
|
|
80841
|
+
logger.info(`No files have been changed in this branch. Skipping final review.
|
|
80344
80842
|
`);
|
|
80345
|
-
|
|
80843
|
+
return { passed: true };
|
|
80844
|
+
}
|
|
80845
|
+
logger.info(`
|
|
80846
|
+
Final review iteration ${i + 1}/${MAX_REVIEW_RETRIES}`);
|
|
80847
|
+
logger.info(` Changed files: ${changedFiles.length}`);
|
|
80848
|
+
const changeInfo = {
|
|
80849
|
+
commitRange,
|
|
80850
|
+
changedFiles
|
|
80851
|
+
};
|
|
80852
|
+
const reviewAgentResult = await step(`final-review-${i}`, async () => {
|
|
80853
|
+
const defaultContext = await getDefaultContext();
|
|
80854
|
+
const memoryContext = await tools2.getMemoryContext();
|
|
80855
|
+
const userMessage = `${defaultContext}
|
|
80856
|
+
${memoryContext}
|
|
80857
|
+
|
|
80858
|
+
${formatReviewToolInput(changeInfo)}`;
|
|
80859
|
+
return await agentWorkflow({
|
|
80860
|
+
systemPrompt: CODE_REVIEW_SYSTEM_PROMPT,
|
|
80861
|
+
userMessage: [{ role: "user", content: userMessage }],
|
|
80862
|
+
tools: [readFile_default, readBinaryFile_default, searchFiles_default, listFiles_default, gitDiff_default, readMemory_default, updateMemory_default, listMemoryTopics_default],
|
|
80863
|
+
outputSchema: reviewOutputSchema
|
|
80864
|
+
}, context);
|
|
80865
|
+
});
|
|
80866
|
+
if (reviewAgentResult.type !== "Exit" /* Exit */) {
|
|
80867
|
+
logger.error(`Review agent failed with status: ${reviewAgentResult.type}.`);
|
|
80868
|
+
break;
|
|
80869
|
+
}
|
|
80870
|
+
const reviewResult = reviewAgentResult.object;
|
|
80871
|
+
if (!reviewResult || !reviewResult.specificReviews || reviewResult.specificReviews.length === 0) {
|
|
80872
|
+
logger.info(`Final review passed. No issues found.
|
|
80873
|
+
`);
|
|
80874
|
+
return { passed: true };
|
|
80875
|
+
}
|
|
80876
|
+
logger.warn(`Warning: Final review found ${reviewResult.specificReviews.length} issue(s). Attempting to fix...
|
|
80877
|
+
`);
|
|
80878
|
+
for (const [idx, review] of reviewResult.specificReviews.entries()) {
|
|
80879
|
+
logger.warn(` ${idx + 1}. ${review.file}:${review.lines}`);
|
|
80880
|
+
}
|
|
80881
|
+
logger.warn("");
|
|
80882
|
+
const reviewSummary = reviewResult.specificReviews.map((r) => `File: ${r.file} (lines: ${r.lines})
|
|
80883
|
+
Review: ${r.review}`).join(`
|
|
80884
|
+
|
|
80346
80885
|
`);
|
|
80347
|
-
|
|
80348
|
-
|
|
80886
|
+
const fixTask = `You are working on an epic. The original task was to implement a feature based on this plan:
|
|
80887
|
+
|
|
80888
|
+
<plan>
|
|
80889
|
+
${highLevelPlan}
|
|
80890
|
+
</plan>
|
|
80891
|
+
|
|
80892
|
+
A final review of all the changes in the branch found the following issues. Please fix them:
|
|
80893
|
+
|
|
80894
|
+
${reviewSummary}`;
|
|
80895
|
+
await step(`final-fix-${i}`, async () => {
|
|
80896
|
+
await codeWorkflow({
|
|
80897
|
+
task: fixTask,
|
|
80898
|
+
mode: "noninteractive",
|
|
80899
|
+
additionalInstructions: TODO_HANDLING_INSTRUCTIONS,
|
|
80900
|
+
additionalTools: [getTodoItem_default, listTodoItems_default, updateTodoItem_default]
|
|
80901
|
+
}, context);
|
|
80902
|
+
});
|
|
80903
|
+
await step(`commit-final-fix-${i}`, async () => {
|
|
80904
|
+
await tools2.executeCommand({ command: "git", args: ["add", "."] });
|
|
80905
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "-m", "chore: apply automated review feedback"] });
|
|
80906
|
+
});
|
|
80907
|
+
if (i === MAX_REVIEW_RETRIES - 1) {
|
|
80908
|
+
logger.error(`
|
|
80909
|
+
Max retries (${MAX_REVIEW_RETRIES}) reached for final review. Issues might remain.
|
|
80910
|
+
`);
|
|
80911
|
+
return { passed: false };
|
|
80912
|
+
}
|
|
80913
|
+
}
|
|
80914
|
+
return { passed: false };
|
|
80915
|
+
}
|
|
80916
|
+
var epicWorkflow = async (input2, context) => {
|
|
80917
|
+
const { logger, tools: tools2 } = context;
|
|
80918
|
+
const { task, epicContext = {} } = input2;
|
|
80919
|
+
const workflowStartTime = Date.now();
|
|
80920
|
+
if (!task || task.trim() === "") {
|
|
80921
|
+
logger.error("Error: Task cannot be empty. Please provide a valid task description.");
|
|
80922
|
+
return;
|
|
80923
|
+
}
|
|
80924
|
+
if (!epicContext.task) {
|
|
80925
|
+
epicContext.task = task;
|
|
80926
|
+
}
|
|
80927
|
+
try {
|
|
80928
|
+
const preflightResult = await runPreflightChecks(epicContext, context);
|
|
80929
|
+
if (!preflightResult) {
|
|
80930
|
+
return;
|
|
80931
|
+
}
|
|
80932
|
+
if (!epicContext.plan) {
|
|
80933
|
+
if (!epicContext.task) {
|
|
80934
|
+
logger.error("Error: Task is missing in epic context. Exiting.");
|
|
80935
|
+
return;
|
|
80936
|
+
}
|
|
80937
|
+
const planResult = await createAndApprovePlan(epicContext.task, context);
|
|
80938
|
+
if (!planResult)
|
|
80939
|
+
return;
|
|
80940
|
+
epicContext.plan = planResult.plan;
|
|
80941
|
+
epicContext.branchName = planResult.branchName;
|
|
80942
|
+
await saveEpicContext(epicContext);
|
|
80943
|
+
}
|
|
80944
|
+
if (!epicContext.plan) {
|
|
80945
|
+
logger.error("Error: Plan is missing after planning phase. Exiting.");
|
|
80946
|
+
return;
|
|
80947
|
+
}
|
|
80948
|
+
if (!epicContext.branchName) {
|
|
80949
|
+
logger.error("Error: Branch name is missing after planning phase. Exiting.");
|
|
80950
|
+
return;
|
|
80951
|
+
}
|
|
80952
|
+
const branchResult = await createFeatureBranch(epicContext.branchName, context);
|
|
80953
|
+
if (!branchResult.success || !branchResult.branchName)
|
|
80954
|
+
return;
|
|
80955
|
+
if (epicContext.branchName !== branchResult.branchName) {
|
|
80956
|
+
epicContext.branchName = branchResult.branchName;
|
|
80957
|
+
await saveEpicContext(epicContext);
|
|
80958
|
+
}
|
|
80959
|
+
const todos = await tools2.listTodoItems({});
|
|
80960
|
+
if (todos.length === 0) {
|
|
80961
|
+
await addTodoItemsFromPlan(epicContext.plan, context);
|
|
80962
|
+
}
|
|
80963
|
+
const commitMessages = await runImplementationLoop(context, epicContext.plan);
|
|
80964
|
+
await performFinalReviewAndFix(context, epicContext.plan);
|
|
80965
|
+
await tools2.executeCommand({ command: "git", args: ["rm", "-f", ".epic.yml"] });
|
|
80966
|
+
const statusResult = await tools2.executeCommand({
|
|
80967
|
+
command: "git",
|
|
80968
|
+
args: ["status", "--porcelain", "--", ".epic.yml"]
|
|
80969
|
+
});
|
|
80970
|
+
if (statusResult.stdout.trim() !== "") {
|
|
80971
|
+
await tools2.executeCommand({ command: "git", args: ["commit", "-m", "chore: remove .epic.yml", "--", ".epic.yml"] });
|
|
80972
|
+
logger.info("Cleaned up .epic.yml file.");
|
|
80973
|
+
}
|
|
80974
|
+
const totalElapsed = Date.now() - workflowStartTime;
|
|
80975
|
+
const totalElapsedTime = formatElapsedTime(totalElapsed);
|
|
80976
|
+
logger.info(`
|
|
80977
|
+
${"=".repeat(80)}`);
|
|
80978
|
+
logger.info("Epic Workflow Complete!");
|
|
80979
|
+
logger.info(`${"=".repeat(80)}`);
|
|
80980
|
+
logger.info(`
|
|
80981
|
+
Summary:`);
|
|
80982
|
+
logger.info(` Branch: ${epicContext.branchName}`);
|
|
80983
|
+
logger.info(` Total time: ${totalElapsedTime}`);
|
|
80984
|
+
logger.info(` Total commits: ${commitMessages.length}`);
|
|
80985
|
+
logger.info("Commits created:");
|
|
80986
|
+
for (const [idx, msg] of commitMessages.entries()) {
|
|
80987
|
+
logger.info(` ${idx + 1}. ${msg}`);
|
|
80988
|
+
}
|
|
80989
|
+
} catch (error46) {
|
|
80990
|
+
logger.error(`
|
|
80991
|
+
Epic workflow failed: ${error46 instanceof Error ? error46.message : String(error46)}`);
|
|
80992
|
+
if (epicContext?.branchName) {
|
|
80993
|
+
logger.info(`
|
|
80994
|
+
Branch '${epicContext.branchName}' was created but work is incomplete.`);
|
|
80995
|
+
logger.info(`To cleanup: git checkout <previous-branch> && git branch -D ${epicContext.branchName}
|
|
80996
|
+
`);
|
|
80997
|
+
}
|
|
80998
|
+
throw error46;
|
|
80999
|
+
}
|
|
80349
81000
|
};
|
|
80350
81001
|
|
|
80351
81002
|
// src/workflows/task.workflow.ts
|
|
@@ -80356,7 +81007,7 @@ var taskWorkflow = async (input2, context) => {
|
|
|
80356
81007
|
const { logger, step } = context;
|
|
80357
81008
|
const { task } = input2;
|
|
80358
81009
|
logger.info(`
|
|
80359
|
-
|
|
81010
|
+
Running generic agent...
|
|
80360
81011
|
`);
|
|
80361
81012
|
await step("agent", async () => {
|
|
80362
81013
|
const defaultContext = await getDefaultContext();
|
|
@@ -80381,7 +81032,7 @@ ${defaultContext}`;
|
|
|
80381
81032
|
}, context);
|
|
80382
81033
|
});
|
|
80383
81034
|
logger.info(`
|
|
80384
|
-
|
|
81035
|
+
Agent finished!
|
|
80385
81036
|
`);
|
|
80386
81037
|
return { success: true };
|
|
80387
81038
|
};
|
|
@@ -80394,7 +81045,7 @@ var metaWorkflow = async (input2, context) => {
|
|
|
80394
81045
|
const { task } = input2;
|
|
80395
81046
|
const { logger } = context;
|
|
80396
81047
|
logger.info(`
|
|
80397
|
-
|
|
81048
|
+
Deciding which workflow to use for task...
|
|
80398
81049
|
`);
|
|
80399
81050
|
const result = await agentWorkflow({
|
|
80400
81051
|
systemPrompt: META_SYSTEM_PROMPT,
|
|
@@ -80415,7 +81066,7 @@ var metaWorkflow = async (input2, context) => {
|
|
|
80415
81066
|
throw new Error("Could not decide which workflow to run.");
|
|
80416
81067
|
}
|
|
80417
81068
|
logger.info(`
|
|
80418
|
-
|
|
81069
|
+
Decision: Using '${decision.workflow}' workflow.`);
|
|
80419
81070
|
switch (decision.workflow) {
|
|
80420
81071
|
case "code":
|
|
80421
81072
|
await codeWorkflow({ task }, context);
|
|
@@ -80635,30 +81286,32 @@ var commitCommand = new Command("commit").description("Create a commit with AI-g
|
|
|
80635
81286
|
async function runEpic(task2, _options, command) {
|
|
80636
81287
|
let taskInput = task2;
|
|
80637
81288
|
if (!taskInput) {
|
|
80638
|
-
|
|
80639
|
-
|
|
80640
|
-
|
|
80641
|
-
});
|
|
80642
|
-
} catch (error46) {
|
|
80643
|
-
if (error46 instanceof Error && error46.name === "ExitPromptError") {
|
|
80644
|
-
return;
|
|
80645
|
-
}
|
|
80646
|
-
throw error46;
|
|
81289
|
+
taskInput = await getUserInput("What epic or large feature do you want to implement?");
|
|
81290
|
+
if (!taskInput) {
|
|
81291
|
+
return;
|
|
80647
81292
|
}
|
|
80648
81293
|
}
|
|
80649
81294
|
if (!taskInput) {
|
|
80650
81295
|
console.error("No task provided. Aborting.");
|
|
80651
81296
|
return;
|
|
80652
81297
|
}
|
|
81298
|
+
const ctx = await loadEpicContext();
|
|
80653
81299
|
const workflowInput = {
|
|
80654
|
-
task: taskInput
|
|
81300
|
+
task: taskInput,
|
|
81301
|
+
epicContext: ctx
|
|
80655
81302
|
};
|
|
80656
81303
|
const globalOpts = (command.parent ?? command).opts();
|
|
80657
81304
|
const { verbose, yes } = globalOpts;
|
|
80658
81305
|
const logger = createLogger({
|
|
80659
81306
|
verbose
|
|
80660
81307
|
});
|
|
80661
|
-
await runWorkflow(epicWorkflow, workflowInput, {
|
|
81308
|
+
await runWorkflow(epicWorkflow, workflowInput, {
|
|
81309
|
+
commandName: "epic",
|
|
81310
|
+
command,
|
|
81311
|
+
logger,
|
|
81312
|
+
yes,
|
|
81313
|
+
getProvider: (opt) => getProvider({ ...opt, todoItemStore: new EpicTodoItemStore(ctx), memoryStore: new EpicMemoryStore(ctx) })
|
|
81314
|
+
});
|
|
80662
81315
|
}
|
|
80663
81316
|
var epicCommand = new Command("epic").description("Orchestrates a large feature or epic, breaking it down into smaller tasks.").argument("[task]", "The epic to plan and implement.").action(runEpic);
|
|
80664
81317
|
|