@polka-codes/cli 0.9.50 → 0.9.52
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 +175 -111
- 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.52";
|
|
35583
35583
|
|
|
35584
35584
|
// src/commands/code.ts
|
|
35585
35585
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
@@ -64388,7 +64388,8 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64388
64388
|
const assistantMessage = await step(`agent-round-${i}`, async () => {
|
|
64389
64389
|
return await tools2.generateText({
|
|
64390
64390
|
messages,
|
|
64391
|
-
tools: toolSet
|
|
64391
|
+
tools: toolSet,
|
|
64392
|
+
model: input.model
|
|
64392
64393
|
});
|
|
64393
64394
|
});
|
|
64394
64395
|
messages.push(...assistantMessage);
|
|
@@ -64423,7 +64424,7 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64423
64424
|
await event(`end-round-${i}`, { kind: "EndRequest" /* EndRequest */, message: textContent });
|
|
64424
64425
|
if (toolCalls.length === 0) {
|
|
64425
64426
|
if (!input.outputSchema) {
|
|
64426
|
-
const exitReason2 = { type: "Exit"
|
|
64427
|
+
const exitReason2 = { type: "Exit", message: textContent, messages };
|
|
64427
64428
|
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: exitReason2 });
|
|
64428
64429
|
return exitReason2;
|
|
64429
64430
|
}
|
|
@@ -64439,7 +64440,7 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64439
64440
|
nextMessage = [{ role: "user", content: errorMessage }];
|
|
64440
64441
|
continue;
|
|
64441
64442
|
}
|
|
64442
|
-
const exitReason = { type: "Exit"
|
|
64443
|
+
const exitReason = { type: "Exit", message: textContent, object: validated.data, messages };
|
|
64443
64444
|
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason });
|
|
64444
64445
|
return exitReason;
|
|
64445
64446
|
}
|
|
@@ -64481,7 +64482,7 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64481
64482
|
output: toolResponse.message
|
|
64482
64483
|
});
|
|
64483
64484
|
break;
|
|
64484
|
-
case "Exit"
|
|
64485
|
+
case "Exit": {
|
|
64485
64486
|
if (toolCalls.length > 1) {
|
|
64486
64487
|
toolResults.push({
|
|
64487
64488
|
toolCallId: toolCall.toolCallId,
|
|
@@ -64496,8 +64497,10 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64496
64497
|
if (toolResults.length > 0) {
|
|
64497
64498
|
break;
|
|
64498
64499
|
}
|
|
64499
|
-
|
|
64500
|
-
|
|
64500
|
+
const exitReason = { ...toolResponse, messages };
|
|
64501
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason });
|
|
64502
|
+
return exitReason;
|
|
64503
|
+
}
|
|
64501
64504
|
}
|
|
64502
64505
|
}
|
|
64503
64506
|
nextMessage = [
|
|
@@ -64510,7 +64513,7 @@ var agentWorkflow = async (input, { step, tools: tools2 }) => {
|
|
|
64510
64513
|
}
|
|
64511
64514
|
];
|
|
64512
64515
|
}
|
|
64513
|
-
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: { type: "UsageExceeded" } });
|
|
64516
|
+
await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: { type: "UsageExceeded", messages } });
|
|
64514
64517
|
throw new Error("Maximum number of tool round trips reached.");
|
|
64515
64518
|
};
|
|
64516
64519
|
// ../workflow/src/json-ai-types.ts
|
|
@@ -78650,7 +78653,8 @@ Workflow completed successfully.`);
|
|
|
78650
78653
|
kind: "EndTask" /* EndTask */,
|
|
78651
78654
|
exitReason: {
|
|
78652
78655
|
type: "Error",
|
|
78653
|
-
error: { message: error46.message, stack: error46.stack }
|
|
78656
|
+
error: { message: error46.message, stack: error46.stack },
|
|
78657
|
+
messages: []
|
|
78654
78658
|
}
|
|
78655
78659
|
});
|
|
78656
78660
|
if (error46 instanceof UserCancelledError) {
|
|
@@ -79038,27 +79042,78 @@ Branch names should:
|
|
|
79038
79042
|
|
|
79039
79043
|
## Response Format
|
|
79040
79044
|
|
|
79041
|
-
|
|
79042
|
-
|
|
79043
|
-
|
|
79044
|
-
|
|
79045
|
-
|
|
79046
|
-
|
|
79047
|
-
|
|
79048
|
-
|
|
79049
|
-
|
|
79045
|
+
Respond with a JSON object in a markdown code block. The JSON object should have a "type" field that determines the structure of the rest of the object.
|
|
79046
|
+
|
|
79047
|
+
### 1. When you generate a plan (type: 'plan-generated')
|
|
79048
|
+
- **type**: Must be "plan-generated".
|
|
79049
|
+
- **plan**: The generated or updated plan.
|
|
79050
|
+
- **branchName**: A suitable git branch name for the work.
|
|
79051
|
+
|
|
79052
|
+
Example:
|
|
79053
|
+
\`\`\`json
|
|
79054
|
+
{
|
|
79055
|
+
"type": "plan-generated",
|
|
79056
|
+
"plan": "1. Phase 1: Backend API Development\\n - [ ] Design and implement user authentication endpoints...",
|
|
79057
|
+
"branchName": "feat/user-authentication"
|
|
79058
|
+
}
|
|
79059
|
+
\`\`\`
|
|
79060
|
+
|
|
79061
|
+
### 2. When you need to ask a question (type: 'question')
|
|
79062
|
+
- **type**: Must be "question".
|
|
79063
|
+
- **question**: An object containing the question and an optional default answer.
|
|
79064
|
+
|
|
79065
|
+
Example:
|
|
79066
|
+
\`\`\`json
|
|
79067
|
+
{
|
|
79068
|
+
"type": "question",
|
|
79069
|
+
"question": {
|
|
79070
|
+
"question": "What database are you using?",
|
|
79071
|
+
"defaultAnswer": "PostgreSQL"
|
|
79072
|
+
}
|
|
79073
|
+
}
|
|
79074
|
+
\`\`\`
|
|
79075
|
+
|
|
79076
|
+
### 3. When no plan is needed or an error occurs (type: 'error')
|
|
79077
|
+
- **type**: Must be "error".
|
|
79078
|
+
- **reason**: A string explaining why no plan is generated (e.g., task already complete, unclear requirements after questioning).
|
|
79079
|
+
|
|
79080
|
+
Example:
|
|
79081
|
+
\`\`\`json
|
|
79082
|
+
{
|
|
79083
|
+
"type": "error",
|
|
79084
|
+
"reason": "The requested feature is already implemented in 'src/features/existing-feature.ts'."
|
|
79085
|
+
}
|
|
79086
|
+
\`\`\`
|
|
79050
79087
|
`;
|
|
79051
79088
|
var BRANCH_NAME_PATTERN = /^[a-zA-Z0-9/_-]+$/;
|
|
79052
79089
|
var EpicPlanSchema = exports_external.object({
|
|
79090
|
+
type: exports_external.enum(["plan-generated", "question", "error"]),
|
|
79053
79091
|
plan: exports_external.string().nullish(),
|
|
79054
79092
|
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
79093
|
message: "Invalid branch name format. Branch names should contain only letters, numbers, hyphens, underscores, and forward slashes."
|
|
79056
|
-
}),
|
|
79094
|
+
}).nullish(),
|
|
79057
79095
|
question: exports_external.object({
|
|
79058
79096
|
question: exports_external.string(),
|
|
79059
79097
|
defaultAnswer: exports_external.string().nullish()
|
|
79060
79098
|
}).nullish(),
|
|
79061
79099
|
reason: exports_external.string().nullish()
|
|
79100
|
+
}).superRefine((data, ctx) => {
|
|
79101
|
+
if (data.type === "plan-generated") {
|
|
79102
|
+
if (!data.plan || data.plan.trim() === "") {
|
|
79103
|
+
ctx.addIssue({
|
|
79104
|
+
code: "custom",
|
|
79105
|
+
message: 'Plan is required when type is "plan-generated".',
|
|
79106
|
+
path: ["plan"]
|
|
79107
|
+
});
|
|
79108
|
+
}
|
|
79109
|
+
if (!data.branchName || data.branchName.trim() === "") {
|
|
79110
|
+
ctx.addIssue({
|
|
79111
|
+
code: "custom",
|
|
79112
|
+
message: 'Branch name is required when type is "plan-generated".',
|
|
79113
|
+
path: ["branchName"]
|
|
79114
|
+
});
|
|
79115
|
+
}
|
|
79116
|
+
}
|
|
79062
79117
|
});
|
|
79063
79118
|
function getPlanPrompt(task, planContent) {
|
|
79064
79119
|
const planSection = planContent ? `
|
|
@@ -79593,7 +79648,7 @@ ${memoryContext}`
|
|
|
79593
79648
|
}, context);
|
|
79594
79649
|
});
|
|
79595
79650
|
const res = await step(`fix-summary-${i}`, async () => {
|
|
79596
|
-
if (result.type === "Exit"
|
|
79651
|
+
if (result.type === "Exit" && result.object) {
|
|
79597
79652
|
const { summary, bailReason } = result.object;
|
|
79598
79653
|
if (bailReason) {
|
|
79599
79654
|
logger.warn(`Agent bailed: ${bailReason}`);
|
|
@@ -79667,7 +79722,7 @@ ${defaultContext}`;
|
|
|
79667
79722
|
outputSchema: PlanSchema
|
|
79668
79723
|
}, context);
|
|
79669
79724
|
});
|
|
79670
|
-
if (result.type === "Exit"
|
|
79725
|
+
if (result.type === "Exit" && result.object) {
|
|
79671
79726
|
const { plan, question, reason, files: filePaths } = result.object;
|
|
79672
79727
|
if (reason) {
|
|
79673
79728
|
return { reason };
|
|
@@ -79832,8 +79887,8 @@ Files:`);
|
|
|
79832
79887
|
|
|
79833
79888
|
// src/workflows/code.workflow.ts
|
|
79834
79889
|
var ImplementOutputSchema = exports_external.object({
|
|
79835
|
-
summary: exports_external.string().nullish(),
|
|
79836
|
-
bailReason: exports_external.string().nullish()
|
|
79890
|
+
summary: exports_external.string().nullish().describe("Short summary of the changes made"),
|
|
79891
|
+
bailReason: exports_external.string().nullish().describe("Reason for bailing out of the implementation loop")
|
|
79837
79892
|
}).refine((data) => data.summary != null !== (data.bailReason != null), {
|
|
79838
79893
|
message: "Either summary or bailReason must be provided, but not both"
|
|
79839
79894
|
});
|
|
@@ -79930,7 +79985,7 @@ ${additionalInstructions}` : CODER_SYSTEM_PROMPT;
|
|
|
79930
79985
|
outputSchema: ImplementOutputSchema
|
|
79931
79986
|
}, context);
|
|
79932
79987
|
});
|
|
79933
|
-
if (res.type === "Exit"
|
|
79988
|
+
if (res.type === "Exit" && res.object) {
|
|
79934
79989
|
const { summary, bailReason } = res.object;
|
|
79935
79990
|
if (bailReason) {
|
|
79936
79991
|
logger.error(`
|
|
@@ -79956,7 +80011,7 @@ Implementation complete!
|
|
|
79956
80011
|
Implementation complete!
|
|
79957
80012
|
`);
|
|
79958
80013
|
}
|
|
79959
|
-
} else if (res.type === "Exit"
|
|
80014
|
+
} else if (res.type === "Exit") {
|
|
79960
80015
|
logger.info(`
|
|
79961
80016
|
Implementation complete!
|
|
79962
80017
|
`);
|
|
@@ -80147,7 +80202,7 @@ ${input2.context}
|
|
|
80147
80202
|
outputSchema: commitMessageSchema
|
|
80148
80203
|
}, context);
|
|
80149
80204
|
});
|
|
80150
|
-
if (result.type === "Exit"
|
|
80205
|
+
if (result.type === "Exit" && result.object) {
|
|
80151
80206
|
const { commitMessage } = commitMessageSchema.parse(result.object);
|
|
80152
80207
|
if (commitMessage) {
|
|
80153
80208
|
logger.info(`
|
|
@@ -80354,7 +80409,7 @@ ${provider3.toUpperCase()}_API_KEY=${providerConfig.apiKey}`;
|
|
|
80354
80409
|
outputSchema: exports_external.object({ yaml: exports_external.string() })
|
|
80355
80410
|
}, { logger, tools: tools2, step });
|
|
80356
80411
|
});
|
|
80357
|
-
if (result.type === "Exit"
|
|
80412
|
+
if (result.type === "Exit" && result.object) {
|
|
80358
80413
|
const yamlConfig = result.object.yaml;
|
|
80359
80414
|
generatedConfig = yamlConfig ? $parse(yamlConfig) : {};
|
|
80360
80415
|
}
|
|
@@ -80383,6 +80438,7 @@ var EpicContextSchema = exports_external.object({
|
|
|
80383
80438
|
task: exports_external.string().nullish(),
|
|
80384
80439
|
plan: exports_external.string().nullish(),
|
|
80385
80440
|
branchName: exports_external.string().nullish(),
|
|
80441
|
+
baseBranch: exports_external.string().nullish(),
|
|
80386
80442
|
todos: exports_external.array(TodoItemSchema).nullish(),
|
|
80387
80443
|
memory: exports_external.record(exports_external.string(), exports_external.string()).nullish()
|
|
80388
80444
|
});
|
|
@@ -80481,49 +80537,58 @@ ${feedback}`
|
|
|
80481
80537
|
],
|
|
80482
80538
|
outputSchema: EpicPlanSchema
|
|
80483
80539
|
}, context);
|
|
80484
|
-
if (planResult.type === "Exit"
|
|
80485
|
-
return
|
|
80540
|
+
if (planResult.type === "Exit") {
|
|
80541
|
+
return planResult.object;
|
|
80486
80542
|
}
|
|
80487
|
-
return {
|
|
80543
|
+
return { type: "error", reason: "Usage limit exceeded." };
|
|
80488
80544
|
}
|
|
80489
80545
|
async function createAndApprovePlan(task, context) {
|
|
80490
80546
|
const { logger, step, tools: tools2 } = context;
|
|
80491
80547
|
logger.info(`Phase 2: Creating high-level plan...
|
|
80492
80548
|
`);
|
|
80493
80549
|
let feedback;
|
|
80494
|
-
let highLevelPlan;
|
|
80495
|
-
let branchName;
|
|
80496
80550
|
let planAttempt = 1;
|
|
80497
80551
|
try {
|
|
80498
80552
|
while (true) {
|
|
80499
80553
|
const result = await step(`plan-${planAttempt}`, () => createPlan2({ task, feedback }, context));
|
|
80500
80554
|
planAttempt++;
|
|
80501
|
-
|
|
80502
|
-
|
|
80503
|
-
|
|
80504
|
-
|
|
80505
|
-
|
|
80506
|
-
|
|
80507
|
-
|
|
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:
|
|
80555
|
+
switch (result.type) {
|
|
80556
|
+
case "plan-generated": {
|
|
80557
|
+
if (!result.plan || !result.branchName) {
|
|
80558
|
+
logger.error("Invalid plan-generated response. Missing plan or branchName.");
|
|
80559
|
+
return null;
|
|
80560
|
+
}
|
|
80561
|
+
logger.info(`Plan:
|
|
80518
80562
|
${result.plan}`);
|
|
80519
|
-
|
|
80520
|
-
|
|
80521
|
-
|
|
80522
|
-
|
|
80523
|
-
|
|
80524
|
-
|
|
80525
|
-
|
|
80526
|
-
|
|
80563
|
+
logger.info(`Suggested branch name: ${result.branchName}`);
|
|
80564
|
+
feedback = await tools2.input({ message: "Press Enter to approve the plan, or provide feedback to refine it." });
|
|
80565
|
+
if (feedback.trim() === "") {
|
|
80566
|
+
logger.info(`High-level plan approved.
|
|
80567
|
+
`);
|
|
80568
|
+
return { plan: result.plan, branchName: result.branchName };
|
|
80569
|
+
}
|
|
80570
|
+
break;
|
|
80571
|
+
}
|
|
80572
|
+
case "question": {
|
|
80573
|
+
if (!result.question) {
|
|
80574
|
+
logger.error("Invalid question response. Missing question object.");
|
|
80575
|
+
return null;
|
|
80576
|
+
}
|
|
80577
|
+
const answer = await tools2.input({
|
|
80578
|
+
message: result.question.question,
|
|
80579
|
+
default: result.question.defaultAnswer || undefined
|
|
80580
|
+
});
|
|
80581
|
+
feedback = `The user answered the question "${result.question.question}" with: "${answer}"`;
|
|
80582
|
+
break;
|
|
80583
|
+
}
|
|
80584
|
+
case "error": {
|
|
80585
|
+
logger.info(`Plan creation failed. Reason: ${result.reason || "Unknown error"}`);
|
|
80586
|
+
return null;
|
|
80587
|
+
}
|
|
80588
|
+
default: {
|
|
80589
|
+
logger.error(`Unknown response type from planner: ${result.type}`);
|
|
80590
|
+
return null;
|
|
80591
|
+
}
|
|
80527
80592
|
}
|
|
80528
80593
|
}
|
|
80529
80594
|
} catch (e) {
|
|
@@ -80533,19 +80598,8 @@ ${result.plan}`);
|
|
|
80533
80598
|
}
|
|
80534
80599
|
throw e;
|
|
80535
80600
|
}
|
|
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
80601
|
}
|
|
80548
|
-
async function createFeatureBranch(branchName, context) {
|
|
80602
|
+
async function createFeatureBranch(branchName, baseBranch, context) {
|
|
80549
80603
|
const { logger, step, tools: tools2 } = context;
|
|
80550
80604
|
logger.info(`Phase 3: Creating/switching to feature branch...
|
|
80551
80605
|
`);
|
|
@@ -80565,7 +80619,10 @@ async function createFeatureBranch(branchName, context) {
|
|
|
80565
80619
|
}
|
|
80566
80620
|
} else {
|
|
80567
80621
|
logger.info(`Creating new branch '${branchName}'...`);
|
|
80568
|
-
const createBranchResult = await step("createBranch", async () => await tools2.executeCommand({
|
|
80622
|
+
const createBranchResult = await step("createBranch", async () => await tools2.executeCommand({
|
|
80623
|
+
command: "git",
|
|
80624
|
+
args: baseBranch ? ["checkout", "-b", branchName, baseBranch] : ["checkout", "-b", branchName]
|
|
80625
|
+
}));
|
|
80569
80626
|
if (createBranchResult.exitCode !== 0) {
|
|
80570
80627
|
logger.error(`Error: Failed to create branch '${branchName}'. Git command failed.`);
|
|
80571
80628
|
return { success: false, branchName: null };
|
|
@@ -80604,12 +80661,13 @@ async function runPreflightChecks(epicContext, context) {
|
|
|
80604
80661
|
}
|
|
80605
80662
|
if (epicContext.plan) {
|
|
80606
80663
|
logger.info("Found an existing `.epic.yml` file.");
|
|
80607
|
-
if (epicContext.branchName) {
|
|
80608
|
-
|
|
80609
|
-
|
|
80610
|
-
|
|
80611
|
-
|
|
80612
|
-
|
|
80664
|
+
if (!epicContext.branchName) {
|
|
80665
|
+
throw new Error("Invalid epic context loaded from .epic.yml: branchName is required.");
|
|
80666
|
+
}
|
|
80667
|
+
const currentBranchResult = await step("getCurrentBranch", async () => tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] }));
|
|
80668
|
+
const currentBranch = currentBranchResult.stdout.trim();
|
|
80669
|
+
if (currentBranch !== epicContext.branchName) {
|
|
80670
|
+
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.`);
|
|
80613
80671
|
}
|
|
80614
80672
|
logger.info("Resuming previous epic session.");
|
|
80615
80673
|
return true;
|
|
@@ -80620,6 +80678,11 @@ async function runPreflightChecks(epicContext, context) {
|
|
|
80620
80678
|
logger.info("Suggestion: Run `git add .` and `git commit` to clean your working directory, or `git stash` to temporarily save changes.\n");
|
|
80621
80679
|
return false;
|
|
80622
80680
|
}
|
|
80681
|
+
const baseBranchResult = await step("getBaseBranch", async () => tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] }));
|
|
80682
|
+
if (baseBranchResult.exitCode === 0 && baseBranchResult.stdout.trim()) {
|
|
80683
|
+
epicContext.baseBranch = baseBranchResult.stdout.trim();
|
|
80684
|
+
logger.info(`Using current branch '${epicContext.baseBranch}' as the base for this epic.`);
|
|
80685
|
+
}
|
|
80623
80686
|
logger.info(`Pre-flight checks passed.
|
|
80624
80687
|
`);
|
|
80625
80688
|
return true;
|
|
@@ -80812,28 +80875,22 @@ Progress: ${progressMessage}`);
|
|
|
80812
80875
|
}
|
|
80813
80876
|
return commitMessages;
|
|
80814
80877
|
}
|
|
80815
|
-
async function performFinalReviewAndFix(context, highLevelPlan) {
|
|
80878
|
+
async function performFinalReviewAndFix(context, highLevelPlan, baseBranch) {
|
|
80816
80879
|
const { logger, step, tools: tools2 } = context;
|
|
80817
80880
|
logger.info(`
|
|
80818
80881
|
Phase 6: Final Review and Fixup...
|
|
80819
80882
|
`);
|
|
80820
|
-
|
|
80821
|
-
|
|
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.");
|
|
80883
|
+
if (!baseBranch) {
|
|
80884
|
+
logger.warn("Warning: Base branch is not defined. Skipping final review step.");
|
|
80823
80885
|
return { passed: true };
|
|
80824
80886
|
}
|
|
80825
|
-
const defaultBranchResult = await tools2.executeCommand({
|
|
80826
|
-
command: "gh",
|
|
80827
|
-
args: ["repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"]
|
|
80828
|
-
});
|
|
80829
|
-
const defaultBranch = defaultBranchResult.stdout.trim();
|
|
80830
80887
|
const currentBranchResult = await tools2.executeCommand({ command: "git", args: ["rev-parse", "--abbrev-ref", "HEAD"] });
|
|
80831
80888
|
const currentBranch = currentBranchResult.stdout.trim();
|
|
80832
|
-
if (currentBranch ===
|
|
80833
|
-
logger.info(`You are on the
|
|
80889
|
+
if (currentBranch === baseBranch) {
|
|
80890
|
+
logger.info(`You are on the base branch ('${baseBranch}'). No final review needed.`);
|
|
80834
80891
|
return { passed: true };
|
|
80835
80892
|
}
|
|
80836
|
-
const commitRange = `${
|
|
80893
|
+
const commitRange = `${baseBranch}...${currentBranch}`;
|
|
80837
80894
|
for (let i = 0;i < MAX_REVIEW_RETRIES; i++) {
|
|
80838
80895
|
const diffResult = await tools2.executeCommand({ command: "git", args: ["diff", "--name-status", commitRange] });
|
|
80839
80896
|
const changedFiles = parseGitDiffNameStatus(diffResult.stdout);
|
|
@@ -80913,9 +80970,9 @@ Max retries (${MAX_REVIEW_RETRIES}) reached for final review. Issues might remai
|
|
|
80913
80970
|
}
|
|
80914
80971
|
return { passed: false };
|
|
80915
80972
|
}
|
|
80916
|
-
var epicWorkflow = async (
|
|
80973
|
+
var epicWorkflow = async (epicContext, context) => {
|
|
80917
80974
|
const { logger, tools: tools2 } = context;
|
|
80918
|
-
const { task
|
|
80975
|
+
const { task } = epicContext;
|
|
80919
80976
|
const workflowStartTime = Date.now();
|
|
80920
80977
|
if (!task || task.trim() === "") {
|
|
80921
80978
|
logger.error("Error: Task cannot be empty. Please provide a valid task description.");
|
|
@@ -80949,7 +81006,7 @@ var epicWorkflow = async (input2, context) => {
|
|
|
80949
81006
|
logger.error("Error: Branch name is missing after planning phase. Exiting.");
|
|
80950
81007
|
return;
|
|
80951
81008
|
}
|
|
80952
|
-
const branchResult = await createFeatureBranch(epicContext.branchName, context);
|
|
81009
|
+
const branchResult = await createFeatureBranch(epicContext.branchName, epicContext.baseBranch ?? undefined, context);
|
|
80953
81010
|
if (!branchResult.success || !branchResult.branchName)
|
|
80954
81011
|
return;
|
|
80955
81012
|
if (epicContext.branchName !== branchResult.branchName) {
|
|
@@ -80961,7 +81018,7 @@ var epicWorkflow = async (input2, context) => {
|
|
|
80961
81018
|
await addTodoItemsFromPlan(epicContext.plan, context);
|
|
80962
81019
|
}
|
|
80963
81020
|
const commitMessages = await runImplementationLoop(context, epicContext.plan);
|
|
80964
|
-
await performFinalReviewAndFix(context, epicContext.plan);
|
|
81021
|
+
await performFinalReviewAndFix(context, epicContext.plan, epicContext.baseBranch ?? undefined);
|
|
80965
81022
|
await tools2.executeCommand({ command: "git", args: ["rm", "-f", ".epic.yml"] });
|
|
80966
81023
|
const statusResult = await tools2.executeCommand({
|
|
80967
81024
|
command: "git",
|
|
@@ -81258,7 +81315,7 @@ var reviewWorkflow = async (input2, context) => {
|
|
|
81258
81315
|
outputSchema: reviewOutputSchema
|
|
81259
81316
|
}, context);
|
|
81260
81317
|
});
|
|
81261
|
-
if (result.type === "Exit"
|
|
81318
|
+
if (result.type === "Exit") {
|
|
81262
81319
|
const reviewResult = result.object;
|
|
81263
81320
|
if (!reviewResult) {
|
|
81264
81321
|
return { overview: "AI agent failed to produce a review.", specificReviews: [] };
|
|
@@ -81284,33 +81341,40 @@ var commitCommand = new Command("commit").description("Create a commit with AI-g
|
|
|
81284
81341
|
|
|
81285
81342
|
// src/commands/epic.ts
|
|
81286
81343
|
async function runEpic(task2, _options, command) {
|
|
81287
|
-
let taskInput = task2;
|
|
81288
|
-
if (!taskInput) {
|
|
81289
|
-
taskInput = await getUserInput("What epic or large feature do you want to implement?");
|
|
81290
|
-
if (!taskInput) {
|
|
81291
|
-
return;
|
|
81292
|
-
}
|
|
81293
|
-
}
|
|
81294
|
-
if (!taskInput) {
|
|
81295
|
-
console.error("No task provided. Aborting.");
|
|
81296
|
-
return;
|
|
81297
|
-
}
|
|
81298
|
-
const ctx = await loadEpicContext();
|
|
81299
|
-
const workflowInput = {
|
|
81300
|
-
task: taskInput,
|
|
81301
|
-
epicContext: ctx
|
|
81302
|
-
};
|
|
81303
81344
|
const globalOpts = (command.parent ?? command).opts();
|
|
81304
81345
|
const { verbose, yes } = globalOpts;
|
|
81305
81346
|
const logger = createLogger({
|
|
81306
81347
|
verbose
|
|
81307
81348
|
});
|
|
81308
|
-
|
|
81349
|
+
let taskInput = task2;
|
|
81350
|
+
const epicContext = await loadEpicContext();
|
|
81351
|
+
if (epicContext.task) {
|
|
81352
|
+
if (taskInput) {
|
|
81353
|
+
logger.error("Error: Existing epic context found, but task was provided via CLI args. Exiting.");
|
|
81354
|
+
return;
|
|
81355
|
+
}
|
|
81356
|
+
logger.info("Resuming existing epic session. Task:");
|
|
81357
|
+
logger.info(` ${epicContext.task}`);
|
|
81358
|
+
} else {
|
|
81359
|
+
if (!taskInput) {
|
|
81360
|
+
taskInput = await getUserInput("What feature do you want to implement?");
|
|
81361
|
+
if (!taskInput) {
|
|
81362
|
+
logger.info("No task provided. Exiting.");
|
|
81363
|
+
return;
|
|
81364
|
+
}
|
|
81365
|
+
}
|
|
81366
|
+
epicContext.task = taskInput;
|
|
81367
|
+
}
|
|
81368
|
+
await runWorkflow(epicWorkflow, epicContext, {
|
|
81309
81369
|
commandName: "epic",
|
|
81310
81370
|
command,
|
|
81311
81371
|
logger,
|
|
81312
81372
|
yes,
|
|
81313
|
-
getProvider: (opt) => getProvider({
|
|
81373
|
+
getProvider: (opt) => getProvider({
|
|
81374
|
+
...opt,
|
|
81375
|
+
todoItemStore: new EpicTodoItemStore(epicContext),
|
|
81376
|
+
memoryStore: new EpicMemoryStore(epicContext)
|
|
81377
|
+
})
|
|
81314
81378
|
});
|
|
81315
81379
|
}
|
|
81316
81380
|
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);
|