@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.
Files changed (2) hide show
  1. package/dist/index.js +175 -111
  2. 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.50";
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" /* Exit */, message: textContent };
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" /* Exit */, message: textContent, object: validated.data };
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" /* 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
- await event("end-task", { kind: "EndTask" /* EndTask */, exitReason: toolResponse });
64500
- return toolResponse;
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
- ${createJsonResponseInstruction({
79042
- plan: "The generated or updated plan.",
79043
- branchName: "feat/new-feature-name",
79044
- question: {
79045
- question: "The clarifying question to ask the user.",
79046
- defaultAnswer: "The default answer to provide if the user does not provide an answer."
79047
- },
79048
- reason: "If no plan is needed, provide a reason here."
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" /* Exit */ && result.object) {
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" /* Exit */ && result.object) {
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" /* Exit */ && res.object) {
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" /* 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" /* Exit */ && result.object) {
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" /* Exit */ && result.object) {
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" /* Exit */) {
80485
- return { ...planResult.object, type: planResult.type };
80540
+ if (planResult.type === "Exit") {
80541
+ return planResult.object;
80486
80542
  }
80487
- return { plan: "", reason: "Usage limit exceeded.", type: "Exit" /* Exit */, branchName: "" };
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
- 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:
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
- 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;
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({ command: "git", args: ["checkout", "-b", branchName] }));
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
- 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
- }
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
- 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.");
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 === defaultBranch) {
80833
- logger.info(`You are on the default branch ('${defaultBranch}'). No final review needed.`);
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 = `${defaultBranch}...${currentBranch}`;
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 (input2, context) => {
80973
+ var epicWorkflow = async (epicContext, context) => {
80917
80974
  const { logger, tools: tools2 } = context;
80918
- const { task, epicContext = {} } = input2;
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" /* 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
- await runWorkflow(epicWorkflow, workflowInput, {
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({ ...opt, todoItemStore: new EpicTodoItemStore(ctx), memoryStore: new EpicMemoryStore(ctx) })
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli",
3
- "version": "0.9.50",
3
+ "version": "0.9.52",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",