@polka-codes/cli 0.9.57 → 0.9.59

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 +89 -62
  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.57";
35582
+ var version = "0.9.59";
35583
35583
 
35584
35584
  // src/commands/code.ts
35585
35585
  import { readFile as readFile3 } from "node:fs/promises";
@@ -78530,7 +78530,9 @@ async function generateText(input2, context) {
78530
78530
  const messages = applyCacheControl(input2.messages.map(fromJsonModelMessage), model.provider, model.modelId);
78531
78531
  for (let i = 0;i < retryCount; i++) {
78532
78532
  const abortController = new AbortController;
78533
- const timeout = setTimeout(() => abortController.abort(), requestTimeoutSeconds * 1000);
78533
+ let timeout = setTimeout(() => abortController.abort(), requestTimeoutSeconds * 1000);
78534
+ const lastOutputs = [];
78535
+ let repetitionDetected = false;
78534
78536
  const usageMeterOnFinishHandler = context.parameters.usageMeter.onFinishHandler(model);
78535
78537
  try {
78536
78538
  const stream = streamText({
@@ -78539,8 +78541,24 @@ async function generateText(input2, context) {
78539
78541
  messages,
78540
78542
  tools: input2.tools,
78541
78543
  async onChunk({ chunk }) {
78544
+ clearTimeout(timeout);
78545
+ timeout = setTimeout(() => abortController.abort(), requestTimeoutSeconds * 1000);
78542
78546
  switch (chunk.type) {
78543
78547
  case "text-delta":
78548
+ lastOutputs.push(chunk.text);
78549
+ if (lastOutputs.length > 20) {
78550
+ lastOutputs.shift();
78551
+ }
78552
+ if (lastOutputs.length === 20) {
78553
+ const firstHalf = lastOutputs.slice(0, 10).join("");
78554
+ const secondHalf = lastOutputs.slice(10).join("");
78555
+ if (firstHalf === secondHalf) {
78556
+ if (firstHalf.length > 20) {
78557
+ repetitionDetected = true;
78558
+ abortController.abort();
78559
+ }
78560
+ }
78561
+ }
78544
78562
  agentCallback?.({
78545
78563
  kind: "Text" /* Text */,
78546
78564
  newText: chunk.text
@@ -78569,6 +78587,11 @@ async function generateText(input2, context) {
78569
78587
  return resp.messages;
78570
78588
  } catch (error46) {
78571
78589
  if (error46.name === "AbortError") {
78590
+ if (repetitionDetected) {
78591
+ console.warn("Repetition detected, retrying...");
78592
+ continue;
78593
+ }
78594
+ console.warn(`Request timed out after ${requestTimeoutSeconds} seconds, retrying...`);
78572
78595
  continue;
78573
78596
  }
78574
78597
  if ("response" in error46) {
@@ -79656,47 +79679,35 @@ ${createJsonResponseInstruction({
79656
79679
  }
79657
79680
  \`\`\`
79658
79681
  `;
79659
- function formatReviewToolInput(params) {
79660
- const parts = [];
79661
- if (params.pullRequestTitle) {
79662
- parts.push(`<pr_title>
79663
- ${params.pullRequestTitle}
79664
- </pr_title>`);
79665
- }
79666
- if (params.pullRequestDescription) {
79667
- parts.push(`<pr_description>
79668
- ${params.pullRequestDescription}
79669
- </pr_description>`);
79670
- }
79671
- if (params.commitMessages) {
79672
- parts.push(`<commit_messages>
79673
- ${params.commitMessages}
79674
- </commit_messages>`);
79675
- }
79676
- if (params.context) {
79677
- parts.push(`<user_context>
79678
- ${params.context}
79679
- </user_context>`);
79680
- }
79681
- if (params.changedFiles && params.changedFiles.length > 0) {
79682
- const fileList = params.changedFiles.map((file2) => `${file2.status}: ${file2.path}`).join(`
79683
- `);
79684
- parts.push(`<file_status>
79685
- ${fileList}
79686
- </file_status>`);
79682
+ function formatContext(tag, value) {
79683
+ if (!value) {
79684
+ return;
79687
79685
  }
79688
- let instructions = "";
79686
+ return `<${tag}>
79687
+ ${value}
79688
+ </${tag}>`;
79689
+ }
79690
+ function getReviewInstructions(params) {
79689
79691
  if (params.commitRange) {
79690
- instructions = `Review the pull request. Use the gitDiff tool with commit range '${params.commitRange}', contextLines: 5, and includeLineNumbers: true to inspect the actual code changes. The diff will include line number annotations to help you report accurate line numbers. File status information is already provided above.`;
79691
- } else if (params.staged) {
79692
- instructions = "Review the staged changes. Use the gitDiff tool with staged: true, contextLines: 5, and includeLineNumbers: true to inspect the actual code changes. The diff will include line number annotations to help you report accurate line numbers. File status information is already provided above.";
79693
- } else {
79694
- instructions = "Review the unstaged changes. Use the gitDiff tool with contextLines: 5, and includeLineNumbers: true to inspect the actual code changes. The diff will include line number annotations to help you report accurate line numbers. File status information is already provided above.";
79692
+ return `Review the pull request. Use the gitDiff tool with commit range '${params.commitRange}' to inspect the actual code changes.`;
79695
79693
  }
79696
- parts.push(`<review_instructions>
79697
- ${instructions}
79698
- </review_instructions>`);
79699
- return parts.join(`
79694
+ if (params.staged) {
79695
+ return "Review the staged changes. Use the gitDiff tool with staged: true to inspect the actual code changes.";
79696
+ }
79697
+ return "Review the unstaged changes. Use the gitDiff tool to inspect the actual code changes.";
79698
+ }
79699
+ function formatReviewToolInput(params) {
79700
+ const fileList = params.changedFiles && params.changedFiles.length > 0 ? params.changedFiles.map((file2) => `${file2.status}: ${file2.path}`).join(`
79701
+ `) : undefined;
79702
+ const parts = [
79703
+ formatContext("pr_title", params.pullRequestTitle),
79704
+ formatContext("pr_description", params.pullRequestDescription),
79705
+ formatContext("commit_messages", params.commitMessages),
79706
+ formatContext("user_context", params.context),
79707
+ formatContext("file_status", fileList),
79708
+ formatContext("review_instructions", getReviewInstructions(params))
79709
+ ];
79710
+ return parts.filter(Boolean).join(`
79700
79711
  `);
79701
79712
  }
79702
79713
  // src/workflows/fix.workflow.ts
@@ -80663,7 +80674,7 @@ ${defaultContext}`;
80663
80674
  outputSchema: EpicPlanSchema
80664
80675
  }, context);
80665
80676
  }
80666
- async function createAndApprovePlan(task, context) {
80677
+ async function createAndApprovePlan(task, context, saveUsageSnapshot) {
80667
80678
  const { logger, step, tools: tools2 } = context;
80668
80679
  logger.info(`Phase 2: Creating high-level plan...
80669
80680
  `);
@@ -80693,6 +80704,7 @@ ${result.plan}`);
80693
80704
  if (feedback.trim() === "") {
80694
80705
  logger.info(`High-level plan approved.
80695
80706
  `);
80707
+ await saveUsageSnapshot();
80696
80708
  return { plan: result.plan, branchName: result.branchName };
80697
80709
  }
80698
80710
  break;
@@ -80924,7 +80936,7 @@ async function findNextTask(tools2) {
80924
80936
  currentTask = subTasks[0];
80925
80937
  }
80926
80938
  }
80927
- async function runImplementationLoop(context, highLevelPlan) {
80939
+ async function runImplementationLoop(context, highLevelPlan, saveUsageSnapshot) {
80928
80940
  const { logger, step, tools: tools2 } = context;
80929
80941
  const commitMessages = [];
80930
80942
  logger.info(`Phase 5: Iterative Implementation Loop...
@@ -80990,6 +81002,7 @@ Focus only on this item, but use the plan for context.`;
80990
81002
  }
80991
81003
  logger.info(`
80992
81004
  Progress: ${progressMessage}`);
81005
+ await saveUsageSnapshot();
80993
81006
  if (!nextTaskItem) {
80994
81007
  logger.info(`All tasks complete!
80995
81008
  `);
@@ -81101,7 +81114,7 @@ Max retries (${MAX_REVIEW_RETRIES}) reached for final review. Issues might remai
81101
81114
  }
81102
81115
  var epicWorkflow = async (input2, context) => {
81103
81116
  const { logger, tools: tools2 } = context;
81104
- const { task, saveEpicContext } = input2;
81117
+ const { task, saveEpicContext, saveUsageSnapshot } = input2;
81105
81118
  const workflowStartTime = Date.now();
81106
81119
  if (!task || task.trim() === "") {
81107
81120
  logger.error("Error: Task cannot be empty. Please provide a valid task description.");
@@ -81120,7 +81133,7 @@ var epicWorkflow = async (input2, context) => {
81120
81133
  logger.error("Error: Task is missing in epic context. Exiting.");
81121
81134
  return;
81122
81135
  }
81123
- const planResult = await createAndApprovePlan(input2.task, context);
81136
+ const planResult = await createAndApprovePlan(input2.task, context, saveUsageSnapshot);
81124
81137
  if (!planResult)
81125
81138
  return;
81126
81139
  input2.plan = planResult.plan;
@@ -81146,8 +81159,9 @@ var epicWorkflow = async (input2, context) => {
81146
81159
  if (todos.length === 0) {
81147
81160
  await addTodoItemsFromPlan(input2.plan, context);
81148
81161
  }
81149
- const commitMessages = await runImplementationLoop(context, input2.plan);
81162
+ const commitMessages = await runImplementationLoop(context, input2.plan, saveUsageSnapshot);
81150
81163
  await performFinalReviewAndFix(context, input2.plan, input2.baseBranch ?? undefined);
81164
+ await saveUsageSnapshot();
81151
81165
  await tools2.executeCommand({ command: "git", args: ["rm", "-f", ".epic.yml"] });
81152
81166
  const statusResult = await tools2.executeCommand({
81153
81167
  command: "git",
@@ -81606,26 +81620,23 @@ async function runEpic(task2, _options, command) {
81606
81620
  }
81607
81621
  epicContext.task = taskInput;
81608
81622
  }
81609
- let usageAppended = false;
81623
+ let usageMeter;
81624
+ const saveUsageSnapshot = async () => {
81625
+ if (usageMeter) {
81626
+ const currentUsage = usageMeter.usage;
81627
+ if (!epicContext.usages) {
81628
+ epicContext.usages = [];
81629
+ }
81630
+ epicContext.usages.push({ ...currentUsage, timestamp: Date.now() });
81631
+ }
81632
+ };
81610
81633
  const workflowInput = {
81611
81634
  ...epicContext,
81612
81635
  async saveEpicContext(context) {
81613
- if (usageMeter) {
81614
- const currentUsage = usageMeter.usage;
81615
- if (!context.usages) {
81616
- context.usages = [];
81617
- }
81618
- if (!usageAppended) {
81619
- context.usages.push({ ...currentUsage, timestamp: Date.now() });
81620
- usageAppended = true;
81621
- } else {
81622
- context.usages[context.usages.length - 1] = { ...currentUsage, timestamp: Date.now() };
81623
- }
81624
- }
81625
81636
  await saveEpicContext(context);
81626
- }
81637
+ },
81638
+ saveUsageSnapshot
81627
81639
  };
81628
- let usageMeter;
81629
81640
  await runWorkflow(epicWorkflow, workflowInput, {
81630
81641
  commandName: "epic",
81631
81642
  command,
@@ -81698,9 +81709,22 @@ async function runMeta(task2, command) {
81698
81709
  }
81699
81710
  epicContext.task = taskInput;
81700
81711
  }
81712
+ let usageMeter;
81713
+ const saveUsageSnapshot = async () => {
81714
+ if (usageMeter) {
81715
+ const currentUsage = usageMeter.usage;
81716
+ if (!epicContext.usages) {
81717
+ epicContext.usages = [];
81718
+ }
81719
+ epicContext.usages.push({ ...currentUsage, timestamp: Date.now() });
81720
+ }
81721
+ };
81701
81722
  const workflowInput = {
81702
81723
  ...epicContext,
81703
- saveEpicContext
81724
+ async saveEpicContext(context) {
81725
+ await saveEpicContext(context);
81726
+ },
81727
+ saveUsageSnapshot
81704
81728
  };
81705
81729
  await runWorkflow(metaWorkflow, workflowInput, {
81706
81730
  commandName: "meta",
@@ -81711,7 +81735,10 @@ async function runMeta(task2, command) {
81711
81735
  ...opt,
81712
81736
  todoItemStore: new EpicTodoItemStore(workflowInput),
81713
81737
  memoryStore: new EpicMemoryStore(workflowInput)
81714
- })
81738
+ }),
81739
+ onUsageMeterCreated: (meter) => {
81740
+ usageMeter = meter;
81741
+ }
81715
81742
  });
81716
81743
  }
81717
81744
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli",
3
- "version": "0.9.57",
3
+ "version": "0.9.59",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",