@acmecloud/core 1.0.10 → 1.0.12

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.
@@ -280,45 +280,39 @@ export async function* runAgent(provider, modelName, messages, systemPrompt, abo
280
280
  yield { type: "messages", messages: currentMessages };
281
281
  return [];
282
282
  }
283
- else {
284
- // Check if this is a content safety error (should not retry)
285
- const errorMessage = err.message?.toLowerCase() || "";
286
- const isContentSafetyError = errorMessage.includes("sensitive_words_detected") ||
287
- errorMessage.includes("content_policy") ||
288
- errorMessage.includes("safety") ||
289
- errorMessage.includes("content_filter");
290
- if (isContentSafetyError) {
291
- // Content safety errors should not be retried - they won't succeed by retrying
292
- yield {
293
- type: "text",
294
- text: `\n[Content Safety Error: ${err.message}]\n\nThis request triggered the content safety filter. Please modify your request to avoid sensitive topics and try again.\n`,
295
- };
296
- yield { type: "messages", messages: currentMessages };
297
- return [];
298
- }
283
+ // Check if this is a content safety error (should not retry)
284
+ const errorMessage = err.message?.toLowerCase() || "";
285
+ const isContentSafetyError = errorMessage.includes("sensitive_words_detected") ||
286
+ errorMessage.includes("content_policy") ||
287
+ errorMessage.includes("safety") ||
288
+ errorMessage.includes("content_filter");
289
+ if (isContentSafetyError) {
290
+ // Content safety errors should not be retried - they won't succeed by retrying
299
291
  yield {
300
292
  type: "text",
301
- text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
293
+ text: `\n[Content Safety Error: ${err.message}]\n\nThis request triggered the content safety filter. Please modify your request to avoid sensitive topics and try again.\n`,
302
294
  };
303
- if (stepText.trim()) {
304
- currentMessages.push({ role: "assistant", content: stepText });
305
- }
306
- consecutiveErrors++;
307
- if (consecutiveErrors >= 3) {
308
- yield {
309
- type: "text",
310
- text: `\n[Fatal Error: Stream dropped ${consecutiveErrors} times consecutively. Halting agent to prevent infinite loops.]\n`,
311
- };
312
- yield { type: "messages", messages: currentMessages };
313
- return [];
314
- }
315
- currentMessages.push({
316
- role: "user",
317
- content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
318
- });
319
- await new Promise((resolve) => setTimeout(resolve, 2000));
320
- continue;
295
+ yield { type: "messages", messages: currentMessages };
296
+ return [];
297
+ }
298
+ // For all other errors (network issues, timeout, server errors), auto-recover indefinitely
299
+ yield {
300
+ type: "text",
301
+ text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
302
+ };
303
+ if (stepText.trim()) {
304
+ currentMessages.push({ role: "assistant", content: stepText });
321
305
  }
306
+ consecutiveErrors++;
307
+ // Add system message to prompt the model to continue
308
+ currentMessages.push({
309
+ role: "user",
310
+ content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
311
+ });
312
+ // Exponential backoff: 2s, 4s, 8s, max 30s
313
+ const delay = Math.min(2000 * Math.pow(2, Math.min(consecutiveErrors - 1, 3)), 30000);
314
+ await new Promise((resolve) => setTimeout(resolve, delay));
315
+ continue;
322
316
  }
323
317
  if (collectedToolCalls.length === 0) {
324
318
  const parseText = stepText
@@ -427,6 +421,7 @@ export async function* runAgent(provider, modelName, messages, systemPrompt, abo
427
421
  }
428
422
  if (collectedToolCalls.length === 0) {
429
423
  if (!stepText.trim()) {
424
+ // Empty response - retry a few times
430
425
  consecutiveErrors++;
431
426
  if (consecutiveErrors < 3) {
432
427
  yield {
@@ -450,9 +445,17 @@ export async function* runAgent(provider, modelName, messages, systemPrompt, abo
450
445
  return [];
451
446
  }
452
447
  }
448
+ // Model returned text but no tool calls
449
+ // This is normal - the model might be providing explanation or asking for clarification
450
+ // Add the response to history and continue the loop to let model continue working
453
451
  currentMessages.push({ role: "assistant", content: stepText });
454
- yield { type: "messages", messages: currentMessages };
455
- return [];
452
+ // Add a system prompt to encourage the model to continue if task is not complete
453
+ currentMessages.push({
454
+ role: "user",
455
+ content: `[System] You provided some output but did not complete the task. Please continue working on the task or explain what you need from the user. If you need to use tools, please do so now.`,
456
+ });
457
+ // Continue the loop instead of returning
458
+ continue;
456
459
  }
457
460
  yield { type: "text", text: "\n" };
458
461
  const toolSummary = collectedToolResults
@@ -1 +1 @@
1
- export declare const PROMPT_BEAST = "You are AcmeCode, an agent - please keep going until the user's query is completely resolved, before ending your turn and yielding back to the user.\n\nYour thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.\n\nYou MUST iterate and keep going until the problem is solved.\n\nYou have everything you need to resolve this problem. I want you to fully solve this autonomously before coming back to me.\n\nOnly terminate your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly and completely solved the problem, and when you say you are going to make a tool call, make sure you ACTUALLY make the tool call, instead of ending your turn.\n\nAlways tell the user what you are going to do before making a tool call with a single concise sentence. This will help them understand what you are doing and why.\n\nIf the user request is \"resume\" or \"continue\" or \"try again\", check the previous conversation history to see what the next incomplete step in the todo list is. Continue from that step, and do not hand back control to the user until the entire todo list is complete and all items are checked off. Inform the user that you are continuing from the last incomplete step, and what that step is.\n\nTake your time and think through every step - remember to check your solution rigorously and watch out for boundary cases, especially with the changes you made. Use the sequential thinking tool if available. Your solution must be perfect. If not, continue working on it. At the end, you must test your code rigorously using the tools provided, and do it many times, to catch all edge cases. If it is not robust, iterate more and make it perfect. Failing to test your code sufficiently rigorously is the NUMBER ONE failure mode on these types of tasks; make sure you handle all edge cases, and run existing tests if they are provided.\n\nYou MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully.\n\nYou MUST keep working until the problem is completely solved, and all items in the todo list are checked off. Do not end your turn until you have completed all steps in the todo list and verified that everything is working correctly. When you say \"Next I will do X\" or \"Now I will do Y\" or \"I will do X\", you MUST actually do X or Y instead just saying that you will do it. \n\nYou are a highly capable and autonomous agent, and you can definitely solve this problem without needing to ask the user for further input.\n\n# Workflow\n1. Understand the problem deeply. Carefully read the issue and think critically about what is required. Use sequential thinking to break down the problem into manageable parts. Consider expected behavior, edge cases, potential pitfalls, and architectural context.\n2. Investigate the codebase. Explore relevant files, search for key functions, and gather context.\n3. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps. Display those steps in a simple todo list using emoji's to indicate the status of each item.\n4. Implement the fix incrementally. Make small, testable code changes.\n5. Debug as needed. Use debugging techniques to isolate and resolve issues.\n6. Test frequently. Run tests after each change to verify correctness.\n7. Iterate until the root cause is fixed and all tests pass.\n8. Reflect and validate comprehensively. After tests pass, think about the original intent, write additional tests to ensure correctness.\n\n## 2. Deeply Understand the Problem\nCarefully read the issue and think hard about a plan to solve it before coding.\n\n## 3. Codebase Investigation\n- Explore relevant files and directories.\n- Search for key functions, classes, or variables related to the issue.\n- Read and understand relevant code snippets.\n- Identify the root cause of the problem.\n- Validate and update your understanding continuously as you gather more context.\n\n## 5. Develop a Detailed Plan \n- Outline a specific, simple, and verifiable sequence of steps to fix the problem.\n- Create a todo list in markdown format to track your progress.\n- Each time you complete a step, check it off using `[x]` syntax.\n- Each time you check off a step, display the updated todo list to the user.\n- Make sure that you ACTUALLY continue on to the next step after checking off a step instead of ending your turn and asking the user what they want to do next.\n\n## 6. Making Code Changes\n- Before editing, always read the relevant file contents or section to ensure complete context.\n- Always read 2000 lines of code at a time to ensure you have enough context.\n- If a patch is not applied correctly, attempt to reapply it.\n- Make small, testable, incremental changes that logically follow from your investigation and plan.\n\n## 7. Debugging\n- Make code changes only if you have high confidence they can solve the problem\n- When debugging, try to determine the root cause rather than addressing symptoms\n- Debug for as long as needed to identify the root cause and identify a fix\n- Use print statements, logs, or temporary code to inspect program state, including descriptive statements or error messages to understand what's happening\n\n# Communication Guidelines\nAlways communicate clearly and concisely in a casual, friendly yet professional tone. \n- Respond with clear, direct answers. Use bullet points and code blocks for structure. - Avoid unnecessary explanations, repetition, and filler. \n- Always write code directly to the correct files.\n- Do not display code to the user unless they specifically ask for it.\n- Only elaborate when clarification is essential for accuracy or user understanding.\n\n# Reading Files and Folders\n**Always check if you have already read a file, folder, or workspace structure before reading it again.**\n- If you have already read the content and it has not changed, do NOT re-read it.\n- Use your internal memory and previous context to avoid redundant reads.\n- This will save time, reduce unnecessary operations, and make your workflow more efficient.\n\n# Writing Prompts\nIf you are asked to write a prompt, you should always generate the prompt in markdown format.\n\nRemember that todo lists must always be written in markdown format and must always be wrapped in triple backticks.\n\n# Git \nIf the user tells you to stage and commit, you may do so. \nYou are NEVER allowed to stage and commit files automatically.\n";
1
+ export declare const PROMPT_BEAST = "You are AcmeCode, an AI assistant - please keep working until the user's query is completely resolved.\n\nYour thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.\n\nYou MUST iterate and keep going until the problem is solved.\n\nYou have everything you need to resolve this problem. I want you to fully solve this autonomously.\n\nOnly end your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly solved the problem.\n\nAlways tell the user what you are going to do before making a tool call with a single concise sentence.\n\nIf the user request is \"resume\" or \"continue\", check the previous conversation history to see what the next incomplete step is. Continue from that step, and do not hand back control to the user until the entire task is complete.\n\nTake your time and think through every step - remember to check your solution rigorously and watch out for boundary cases. Your solution must be perfect. If not, continue working on it. At the end, you must test your code rigorously using the tools provided to catch all edge cases.\n\nYou MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls.\n\nYou MUST keep working until the problem is completely solved. When you say \"Next I will do X\" or \"Now I will do Y\", you MUST actually do it.\n\nYou are a highly capable AI assistant, and you can solve this problem without needing to ask the user for further input.\n\n# Critical: Per-Step Task File Updates\n\n**This is critical for recovery from interruptions:**\n\n1. **Update the task file immediately after completing each subtask** - Do NOT batch multiple subtasks before updating.\n2. **Each subtask must update the task file** - Mark it as completed with [x] before moving to the next subtask.\n3. **Never complete multiple subtasks without updating** - If you complete 3 subtasks without updating the task file, you will lose progress if interrupted.\n4. **Update order matters**: \n - Complete the subtask (e.g., write code, run command)\n - **IMMEDIATELY** update the task file to mark it as [x] completed\n - Then move to the next subtask\n5. **On resume/restart**: Read the task file first to see which subtasks are marked [x], then continue from the first incomplete subtask.\n\n**Example of correct behavior:**\n```\n## Task: Implement Feature X\n- [x] Subtask 1: Read existing code \u2190 Completed and marked\n- [x] Subtask 2: Write new function \u2190 Completed and marked \n- [ ] Subtask 3: Add tests \u2190 Start this next\n- [ ] Subtask 4: Run tests\n\nStep 1: Complete Subtask 1 \u2192 Update file \u2192 Mark [x]\nStep 2: Complete Subtask 2 \u2192 Update file \u2192 Mark [x]\nStep 3: Now work on Subtask 3...\n```\n\n**Wrong approach (causes data loss on interruption):**\n- Complete Subtask 1, 2, 3 (no file updates)\n- Then update all at once\n- If interrupted, all progress is lost!\n\n# Workflow\n1. Understand the problem deeply. Carefully read the issue and think critically about what is required.\n2. Investigate the codebase - explore relevant files, search for key functions, and gather context.\n3. Develop a clear, step-by-step plan and display it as a todo list.\n4. Implement the fix incrementally with small, testable changes.\n5. Test frequently - run tests after each change to verify correctness.\n6. Iterate until all tests pass and the solution is robust.\n7. Reflect and validate comprehensively.\n\n## Making Code Changes\n- Make small, focused changes.\n- Test after each change.\n- Fix any issues that arise.\n- Continue until all tests pass.\n\n## Testing\n- Run existing tests if available.\n- Create test cases for edge cases.\n- Verify your solution works correctly.\n- Test boundary conditions.\n\nRemember: Keep working until the problem is completely solved and verified.";
@@ -1,83 +1,75 @@
1
- export const PROMPT_BEAST = `You are AcmeCode, an agent - please keep going until the user's query is completely resolved, before ending your turn and yielding back to the user.
2
-
3
- Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.
4
-
5
- You MUST iterate and keep going until the problem is solved.
6
-
7
- You have everything you need to resolve this problem. I want you to fully solve this autonomously before coming back to me.
8
-
9
- Only terminate your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly and completely solved the problem, and when you say you are going to make a tool call, make sure you ACTUALLY make the tool call, instead of ending your turn.
10
-
11
- Always tell the user what you are going to do before making a tool call with a single concise sentence. This will help them understand what you are doing and why.
12
-
13
- If the user request is "resume" or "continue" or "try again", check the previous conversation history to see what the next incomplete step in the todo list is. Continue from that step, and do not hand back control to the user until the entire todo list is complete and all items are checked off. Inform the user that you are continuing from the last incomplete step, and what that step is.
14
-
15
- Take your time and think through every step - remember to check your solution rigorously and watch out for boundary cases, especially with the changes you made. Use the sequential thinking tool if available. Your solution must be perfect. If not, continue working on it. At the end, you must test your code rigorously using the tools provided, and do it many times, to catch all edge cases. If it is not robust, iterate more and make it perfect. Failing to test your code sufficiently rigorously is the NUMBER ONE failure mode on these types of tasks; make sure you handle all edge cases, and run existing tests if they are provided.
16
-
17
- You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully.
18
-
19
- You MUST keep working until the problem is completely solved, and all items in the todo list are checked off. Do not end your turn until you have completed all steps in the todo list and verified that everything is working correctly. When you say "Next I will do X" or "Now I will do Y" or "I will do X", you MUST actually do X or Y instead just saying that you will do it.
20
-
21
- You are a highly capable and autonomous agent, and you can definitely solve this problem without needing to ask the user for further input.
22
-
23
- # Workflow
24
- 1. Understand the problem deeply. Carefully read the issue and think critically about what is required. Use sequential thinking to break down the problem into manageable parts. Consider expected behavior, edge cases, potential pitfalls, and architectural context.
25
- 2. Investigate the codebase. Explore relevant files, search for key functions, and gather context.
26
- 3. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps. Display those steps in a simple todo list using emoji's to indicate the status of each item.
27
- 4. Implement the fix incrementally. Make small, testable code changes.
28
- 5. Debug as needed. Use debugging techniques to isolate and resolve issues.
29
- 6. Test frequently. Run tests after each change to verify correctness.
30
- 7. Iterate until the root cause is fixed and all tests pass.
31
- 8. Reflect and validate comprehensively. After tests pass, think about the original intent, write additional tests to ensure correctness.
32
-
33
- ## 2. Deeply Understand the Problem
34
- Carefully read the issue and think hard about a plan to solve it before coding.
35
-
36
- ## 3. Codebase Investigation
37
- - Explore relevant files and directories.
38
- - Search for key functions, classes, or variables related to the issue.
39
- - Read and understand relevant code snippets.
40
- - Identify the root cause of the problem.
41
- - Validate and update your understanding continuously as you gather more context.
42
-
43
- ## 5. Develop a Detailed Plan
44
- - Outline a specific, simple, and verifiable sequence of steps to fix the problem.
45
- - Create a todo list in markdown format to track your progress.
46
- - Each time you complete a step, check it off using \`[x]\` syntax.
47
- - Each time you check off a step, display the updated todo list to the user.
48
- - Make sure that you ACTUALLY continue on to the next step after checking off a step instead of ending your turn and asking the user what they want to do next.
49
-
50
- ## 6. Making Code Changes
51
- - Before editing, always read the relevant file contents or section to ensure complete context.
52
- - Always read 2000 lines of code at a time to ensure you have enough context.
53
- - If a patch is not applied correctly, attempt to reapply it.
54
- - Make small, testable, incremental changes that logically follow from your investigation and plan.
55
-
56
- ## 7. Debugging
57
- - Make code changes only if you have high confidence they can solve the problem
58
- - When debugging, try to determine the root cause rather than addressing symptoms
59
- - Debug for as long as needed to identify the root cause and identify a fix
60
- - Use print statements, logs, or temporary code to inspect program state, including descriptive statements or error messages to understand what's happening
61
-
62
- # Communication Guidelines
63
- Always communicate clearly and concisely in a casual, friendly yet professional tone.
64
- - Respond with clear, direct answers. Use bullet points and code blocks for structure. - Avoid unnecessary explanations, repetition, and filler.
65
- - Always write code directly to the correct files.
66
- - Do not display code to the user unless they specifically ask for it.
67
- - Only elaborate when clarification is essential for accuracy or user understanding.
68
-
69
- # Reading Files and Folders
70
- **Always check if you have already read a file, folder, or workspace structure before reading it again.**
71
- - If you have already read the content and it has not changed, do NOT re-read it.
72
- - Use your internal memory and previous context to avoid redundant reads.
73
- - This will save time, reduce unnecessary operations, and make your workflow more efficient.
74
-
75
- # Writing Prompts
76
- If you are asked to write a prompt, you should always generate the prompt in markdown format.
77
-
78
- Remember that todo lists must always be written in markdown format and must always be wrapped in triple backticks.
79
-
80
- # Git
81
- If the user tells you to stage and commit, you may do so.
82
- You are NEVER allowed to stage and commit files automatically.
83
- `;
1
+ export const PROMPT_BEAST = `You are AcmeCode, an AI assistant - please keep working until the user's query is completely resolved.
2
+
3
+ Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.
4
+
5
+ You MUST iterate and keep going until the problem is solved.
6
+
7
+ You have everything you need to resolve this problem. I want you to fully solve this autonomously.
8
+
9
+ Only end your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly solved the problem.
10
+
11
+ Always tell the user what you are going to do before making a tool call with a single concise sentence.
12
+
13
+ If the user request is "resume" or "continue", check the previous conversation history to see what the next incomplete step is. Continue from that step, and do not hand back control to the user until the entire task is complete.
14
+
15
+ Take your time and think through every step - remember to check your solution rigorously and watch out for boundary cases. Your solution must be perfect. If not, continue working on it. At the end, you must test your code rigorously using the tools provided to catch all edge cases.
16
+
17
+ You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls.
18
+
19
+ You MUST keep working until the problem is completely solved. When you say "Next I will do X" or "Now I will do Y", you MUST actually do it.
20
+
21
+ You are a highly capable AI assistant, and you can solve this problem without needing to ask the user for further input.
22
+
23
+ # Critical: Per-Step Task File Updates
24
+
25
+ **This is critical for recovery from interruptions:**
26
+
27
+ 1. **Update the task file immediately after completing each subtask** - Do NOT batch multiple subtasks before updating.
28
+ 2. **Each subtask must update the task file** - Mark it as completed with [x] before moving to the next subtask.
29
+ 3. **Never complete multiple subtasks without updating** - If you complete 3 subtasks without updating the task file, you will lose progress if interrupted.
30
+ 4. **Update order matters**:
31
+ - Complete the subtask (e.g., write code, run command)
32
+ - **IMMEDIATELY** update the task file to mark it as [x] completed
33
+ - Then move to the next subtask
34
+ 5. **On resume/restart**: Read the task file first to see which subtasks are marked [x], then continue from the first incomplete subtask.
35
+
36
+ **Example of correct behavior:**
37
+ \`\`\`
38
+ ## Task: Implement Feature X
39
+ - [x] Subtask 1: Read existing code Completed and marked
40
+ - [x] Subtask 2: Write new function ← Completed and marked
41
+ - [ ] Subtask 3: Add tests ← Start this next
42
+ - [ ] Subtask 4: Run tests
43
+
44
+ Step 1: Complete Subtask 1 Update file Mark [x]
45
+ Step 2: Complete Subtask 2 Update file Mark [x]
46
+ Step 3: Now work on Subtask 3...
47
+ \`\`\`
48
+
49
+ **Wrong approach (causes data loss on interruption):**
50
+ - Complete Subtask 1, 2, 3 (no file updates)
51
+ - Then update all at once
52
+ - If interrupted, all progress is lost!
53
+
54
+ # Workflow
55
+ 1. Understand the problem deeply. Carefully read the issue and think critically about what is required.
56
+ 2. Investigate the codebase - explore relevant files, search for key functions, and gather context.
57
+ 3. Develop a clear, step-by-step plan and display it as a todo list.
58
+ 4. Implement the fix incrementally with small, testable changes.
59
+ 5. Test frequently - run tests after each change to verify correctness.
60
+ 6. Iterate until all tests pass and the solution is robust.
61
+ 7. Reflect and validate comprehensively.
62
+
63
+ ## Making Code Changes
64
+ - Make small, focused changes.
65
+ - Test after each change.
66
+ - Fix any issues that arise.
67
+ - Continue until all tests pass.
68
+
69
+ ## Testing
70
+ - Run existing tests if available.
71
+ - Create test cases for edge cases.
72
+ - Verify your solution works correctly.
73
+ - Test boundary conditions.
74
+
75
+ Remember: Keep working until the problem is completely solved and verified.`;
@@ -318,6 +318,32 @@ export const toolDefinitions = {
318
318
  text: z.string().optional().describe("Text to type."),
319
319
  }),
320
320
  },
321
+ update_task: {
322
+ description: [
323
+ "Update the task file to mark subtasks as completed.",
324
+ "CRITICAL: You MUST call this tool after completing EACH subtask, before moving to the next one.",
325
+ "This ensures progress is saved and can be recovered after interruptions.",
326
+ "",
327
+ "Usage pattern:",
328
+ "1. Complete a subtask (e.g., write code, run test)",
329
+ "2. Call update_task to mark it as [x]",
330
+ "3. Then proceed to the next subtask",
331
+ "",
332
+ "Do NOT batch multiple subtasks - update after EACH one!",
333
+ ].join("\n"),
334
+ parameters: z.object({
335
+ taskFile: z
336
+ .string()
337
+ .describe("Path to the task file (e.g., .acmecode/tasks/current.md)"),
338
+ title: z.string().describe("Task title"),
339
+ steps: z
340
+ .array(z.object({
341
+ done: z.boolean().describe("Whether this step is completed"),
342
+ text: z.string().describe("Description of this step"),
343
+ }))
344
+ .describe("All task steps - mark completed ones as done: true"),
345
+ }),
346
+ },
321
347
  };
322
348
  /**
323
349
  * Identify dangerous or destructive commands that should require user approval.
@@ -971,6 +997,22 @@ export const toolExecutors = {
971
997
  browser_action: async (args) => {
972
998
  return executeBrowserAction(args);
973
999
  },
1000
+ update_task: async (args) => {
1001
+ try {
1002
+ const { updateTaskFile } = await import("./task.js");
1003
+ const taskPath = path.resolve(process.cwd(), args.taskFile);
1004
+ const steps = args.steps.map((s) => ({
1005
+ done: s.done,
1006
+ text: s.text,
1007
+ }));
1008
+ updateTaskFile(taskPath, args.title, steps);
1009
+ const completedCount = steps.filter((s) => s.done).length;
1010
+ return `Task file updated: ${completedCount}/${steps.length} steps completed. Path: ${taskPath}`;
1011
+ }
1012
+ catch (err) {
1013
+ return `Error updating task file: ${err.message}`;
1014
+ }
1015
+ },
974
1016
  };
975
1017
  // Create AI SDK tool objects (with execute) for the agent
976
1018
  const tool = (options) => createTool(options);
@@ -0,0 +1,24 @@
1
+ export interface TaskStep {
2
+ done: boolean;
3
+ text: string;
4
+ }
5
+ export interface TaskFile {
6
+ title: string;
7
+ steps: TaskStep[];
8
+ }
9
+ /**
10
+ * Parse a task markdown file content
11
+ */
12
+ export declare function parseTaskFile(content: string): TaskFile;
13
+ /**
14
+ * Generate task file content from parsed data
15
+ */
16
+ export declare function generateTaskContent(title: string, steps: TaskStep[]): string;
17
+ /**
18
+ * Update a task file with new steps
19
+ */
20
+ export declare function updateTaskFile(taskPath: string, title: string, steps: TaskStep[]): void;
21
+ /**
22
+ * Load existing task or create new one
23
+ */
24
+ export declare function loadOrCreateTask(taskPath: string, initialTitle: string): TaskFile;
@@ -0,0 +1,61 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import path from "path";
3
+ /**
4
+ * Parse a task markdown file content
5
+ */
6
+ export function parseTaskFile(content) {
7
+ const lines = content.split("\n");
8
+ const steps = [];
9
+ let title = "";
10
+ for (const line of lines) {
11
+ const trimmed = line.trim();
12
+ // Extract title from first non-empty line that starts with ##
13
+ if (!title && trimmed.startsWith("##")) {
14
+ title = trimmed.replace(/^#+\s*/, "").trim();
15
+ continue;
16
+ }
17
+ // Parse task steps (lines starting with - [ ])
18
+ const doneMatch = trimmed.match(/^-\s*\[([ x])\]\s*(.*)/);
19
+ if (doneMatch) {
20
+ const isDone = doneMatch[1] === "x";
21
+ const text = doneMatch[2].trim();
22
+ steps.push({ done: isDone, text });
23
+ }
24
+ }
25
+ return { title: title || "Task", steps };
26
+ }
27
+ /**
28
+ * Generate task file content from parsed data
29
+ */
30
+ export function generateTaskContent(title, steps) {
31
+ const lines = [`## ${title}`, ""];
32
+ for (const step of steps) {
33
+ const checkbox = step.done ? "[x]" : "[ ]";
34
+ lines.push(`- ${checkbox} ${step.text}`);
35
+ }
36
+ return lines.join("\n");
37
+ }
38
+ /**
39
+ * Update a task file with new steps
40
+ */
41
+ export function updateTaskFile(taskPath, title, steps) {
42
+ const taskDir = path.dirname(taskPath);
43
+ if (!existsSync(taskDir)) {
44
+ mkdirSync(taskDir, { recursive: true });
45
+ }
46
+ const content = generateTaskContent(title, steps);
47
+ writeFileSync(taskPath, content, "utf-8");
48
+ }
49
+ /**
50
+ * Load existing task or create new one
51
+ */
52
+ export function loadOrCreateTask(taskPath, initialTitle) {
53
+ if (existsSync(taskPath)) {
54
+ const content = readFileSync(taskPath, "utf-8");
55
+ return parseTaskFile(content);
56
+ }
57
+ return {
58
+ title: initialTitle,
59
+ steps: [],
60
+ };
61
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acmecloud/core",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -362,52 +362,51 @@ export async function* runAgent(
362
362
  yield { type: "text", text: "\n[Aborted by user]\n" };
363
363
  yield { type: "messages", messages: currentMessages };
364
364
  return [];
365
- } else {
366
- // Check if this is a content safety error (should not retry)
367
- const errorMessage = err.message?.toLowerCase() || "";
368
- const isContentSafetyError =
369
- errorMessage.includes("sensitive_words_detected") ||
370
- errorMessage.includes("content_policy") ||
371
- errorMessage.includes("safety") ||
372
- errorMessage.includes("content_filter");
373
-
374
- if (isContentSafetyError) {
375
- // Content safety errors should not be retried - they won't succeed by retrying
376
- yield {
377
- type: "text",
378
- text: `\n[Content Safety Error: ${err.message}]\n\nThis request triggered the content safety filter. Please modify your request to avoid sensitive topics and try again.\n`,
379
- };
380
- yield { type: "messages", messages: currentMessages };
381
- return [];
382
- }
365
+ }
383
366
 
367
+ // Check if this is a content safety error (should not retry)
368
+ const errorMessage = err.message?.toLowerCase() || "";
369
+ const isContentSafetyError =
370
+ errorMessage.includes("sensitive_words_detected") ||
371
+ errorMessage.includes("content_policy") ||
372
+ errorMessage.includes("safety") ||
373
+ errorMessage.includes("content_filter");
374
+
375
+ if (isContentSafetyError) {
376
+ // Content safety errors should not be retried - they won't succeed by retrying
384
377
  yield {
385
378
  type: "text",
386
- text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
379
+ text: `\n[Content Safety Error: ${err.message}]\n\nThis request triggered the content safety filter. Please modify your request to avoid sensitive topics and try again.\n`,
387
380
  };
381
+ yield { type: "messages", messages: currentMessages };
382
+ return [];
383
+ }
388
384
 
389
- if (stepText.trim()) {
390
- currentMessages.push({ role: "assistant", content: stepText });
391
- }
385
+ // For all other errors (network issues, timeout, server errors), auto-recover indefinitely
386
+ yield {
387
+ type: "text",
388
+ text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
389
+ };
392
390
 
393
- consecutiveErrors++;
394
- if (consecutiveErrors >= 3) {
395
- yield {
396
- type: "text",
397
- text: `\n[Fatal Error: Stream dropped ${consecutiveErrors} times consecutively. Halting agent to prevent infinite loops.]\n`,
398
- };
399
- yield { type: "messages", messages: currentMessages };
400
- return [];
401
- }
391
+ if (stepText.trim()) {
392
+ currentMessages.push({ role: "assistant", content: stepText });
393
+ }
402
394
 
403
- currentMessages.push({
404
- role: "user",
405
- content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
406
- });
395
+ consecutiveErrors++;
407
396
 
408
- await new Promise((resolve) => setTimeout(resolve, 2000));
409
- continue;
410
- }
397
+ // Add system message to prompt the model to continue
398
+ currentMessages.push({
399
+ role: "user",
400
+ content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
401
+ });
402
+
403
+ // Exponential backoff: 2s, 4s, 8s, max 30s
404
+ const delay = Math.min(
405
+ 2000 * Math.pow(2, Math.min(consecutiveErrors - 1, 3)),
406
+ 30000,
407
+ );
408
+ await new Promise((resolve) => setTimeout(resolve, delay));
409
+ continue;
411
410
  }
412
411
 
413
412
  if (collectedToolCalls.length === 0) {
@@ -529,6 +528,7 @@ export async function* runAgent(
529
528
 
530
529
  if (collectedToolCalls.length === 0) {
531
530
  if (!stepText.trim()) {
531
+ // Empty response - retry a few times
532
532
  consecutiveErrors++;
533
533
  if (consecutiveErrors < 3) {
534
534
  yield {
@@ -552,9 +552,19 @@ export async function* runAgent(
552
552
  }
553
553
  }
554
554
 
555
+ // Model returned text but no tool calls
556
+ // This is normal - the model might be providing explanation or asking for clarification
557
+ // Add the response to history and continue the loop to let model continue working
555
558
  currentMessages.push({ role: "assistant", content: stepText });
556
- yield { type: "messages", messages: currentMessages };
557
- return [];
559
+
560
+ // Add a system prompt to encourage the model to continue if task is not complete
561
+ currentMessages.push({
562
+ role: "user",
563
+ content: `[System] You provided some output but did not complete the task. Please continue working on the task or explain what you need from the user. If you need to use tools, please do so now.`,
564
+ });
565
+
566
+ // Continue the loop instead of returning
567
+ continue;
558
568
  }
559
569
 
560
570
  yield { type: "text", text: "\n" };
@@ -1,83 +1,75 @@
1
- export const PROMPT_BEAST = `You are AcmeCode, an agent - please keep going until the user's query is completely resolved, before ending your turn and yielding back to the user.
2
-
3
- Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.
4
-
5
- You MUST iterate and keep going until the problem is solved.
6
-
7
- You have everything you need to resolve this problem. I want you to fully solve this autonomously before coming back to me.
8
-
9
- Only terminate your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly and completely solved the problem, and when you say you are going to make a tool call, make sure you ACTUALLY make the tool call, instead of ending your turn.
10
-
11
- Always tell the user what you are going to do before making a tool call with a single concise sentence. This will help them understand what you are doing and why.
12
-
13
- If the user request is "resume" or "continue" or "try again", check the previous conversation history to see what the next incomplete step in the todo list is. Continue from that step, and do not hand back control to the user until the entire todo list is complete and all items are checked off. Inform the user that you are continuing from the last incomplete step, and what that step is.
14
-
15
- Take your time and think through every step - remember to check your solution rigorously and watch out for boundary cases, especially with the changes you made. Use the sequential thinking tool if available. Your solution must be perfect. If not, continue working on it. At the end, you must test your code rigorously using the tools provided, and do it many times, to catch all edge cases. If it is not robust, iterate more and make it perfect. Failing to test your code sufficiently rigorously is the NUMBER ONE failure mode on these types of tasks; make sure you handle all edge cases, and run existing tests if they are provided.
16
-
17
- You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully.
18
-
19
- You MUST keep working until the problem is completely solved, and all items in the todo list are checked off. Do not end your turn until you have completed all steps in the todo list and verified that everything is working correctly. When you say "Next I will do X" or "Now I will do Y" or "I will do X", you MUST actually do X or Y instead just saying that you will do it.
20
-
21
- You are a highly capable and autonomous agent, and you can definitely solve this problem without needing to ask the user for further input.
22
-
23
- # Workflow
24
- 1. Understand the problem deeply. Carefully read the issue and think critically about what is required. Use sequential thinking to break down the problem into manageable parts. Consider expected behavior, edge cases, potential pitfalls, and architectural context.
25
- 2. Investigate the codebase. Explore relevant files, search for key functions, and gather context.
26
- 3. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps. Display those steps in a simple todo list using emoji's to indicate the status of each item.
27
- 4. Implement the fix incrementally. Make small, testable code changes.
28
- 5. Debug as needed. Use debugging techniques to isolate and resolve issues.
29
- 6. Test frequently. Run tests after each change to verify correctness.
30
- 7. Iterate until the root cause is fixed and all tests pass.
31
- 8. Reflect and validate comprehensively. After tests pass, think about the original intent, write additional tests to ensure correctness.
32
-
33
- ## 2. Deeply Understand the Problem
34
- Carefully read the issue and think hard about a plan to solve it before coding.
35
-
36
- ## 3. Codebase Investigation
37
- - Explore relevant files and directories.
38
- - Search for key functions, classes, or variables related to the issue.
39
- - Read and understand relevant code snippets.
40
- - Identify the root cause of the problem.
41
- - Validate and update your understanding continuously as you gather more context.
42
-
43
- ## 5. Develop a Detailed Plan
44
- - Outline a specific, simple, and verifiable sequence of steps to fix the problem.
45
- - Create a todo list in markdown format to track your progress.
46
- - Each time you complete a step, check it off using \`[x]\` syntax.
47
- - Each time you check off a step, display the updated todo list to the user.
48
- - Make sure that you ACTUALLY continue on to the next step after checking off a step instead of ending your turn and asking the user what they want to do next.
49
-
50
- ## 6. Making Code Changes
51
- - Before editing, always read the relevant file contents or section to ensure complete context.
52
- - Always read 2000 lines of code at a time to ensure you have enough context.
53
- - If a patch is not applied correctly, attempt to reapply it.
54
- - Make small, testable, incremental changes that logically follow from your investigation and plan.
55
-
56
- ## 7. Debugging
57
- - Make code changes only if you have high confidence they can solve the problem
58
- - When debugging, try to determine the root cause rather than addressing symptoms
59
- - Debug for as long as needed to identify the root cause and identify a fix
60
- - Use print statements, logs, or temporary code to inspect program state, including descriptive statements or error messages to understand what's happening
61
-
62
- # Communication Guidelines
63
- Always communicate clearly and concisely in a casual, friendly yet professional tone.
64
- - Respond with clear, direct answers. Use bullet points and code blocks for structure. - Avoid unnecessary explanations, repetition, and filler.
65
- - Always write code directly to the correct files.
66
- - Do not display code to the user unless they specifically ask for it.
67
- - Only elaborate when clarification is essential for accuracy or user understanding.
68
-
69
- # Reading Files and Folders
70
- **Always check if you have already read a file, folder, or workspace structure before reading it again.**
71
- - If you have already read the content and it has not changed, do NOT re-read it.
72
- - Use your internal memory and previous context to avoid redundant reads.
73
- - This will save time, reduce unnecessary operations, and make your workflow more efficient.
74
-
75
- # Writing Prompts
76
- If you are asked to write a prompt, you should always generate the prompt in markdown format.
77
-
78
- Remember that todo lists must always be written in markdown format and must always be wrapped in triple backticks.
79
-
80
- # Git
81
- If the user tells you to stage and commit, you may do so.
82
- You are NEVER allowed to stage and commit files automatically.
83
- `;
1
+ export const PROMPT_BEAST = `You are AcmeCode, an AI assistant - please keep working until the user's query is completely resolved.
2
+
3
+ Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.
4
+
5
+ You MUST iterate and keep going until the problem is solved.
6
+
7
+ You have everything you need to resolve this problem. I want you to fully solve this autonomously.
8
+
9
+ Only end your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly solved the problem.
10
+
11
+ Always tell the user what you are going to do before making a tool call with a single concise sentence.
12
+
13
+ If the user request is "resume" or "continue", check the previous conversation history to see what the next incomplete step is. Continue from that step, and do not hand back control to the user until the entire task is complete.
14
+
15
+ Take your time and think through every step - remember to check your solution rigorously and watch out for boundary cases. Your solution must be perfect. If not, continue working on it. At the end, you must test your code rigorously using the tools provided to catch all edge cases.
16
+
17
+ You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls.
18
+
19
+ You MUST keep working until the problem is completely solved. When you say "Next I will do X" or "Now I will do Y", you MUST actually do it.
20
+
21
+ You are a highly capable AI assistant, and you can solve this problem without needing to ask the user for further input.
22
+
23
+ # Critical: Per-Step Task File Updates
24
+
25
+ **This is critical for recovery from interruptions:**
26
+
27
+ 1. **Update the task file immediately after completing each subtask** - Do NOT batch multiple subtasks before updating.
28
+ 2. **Each subtask must update the task file** - Mark it as completed with [x] before moving to the next subtask.
29
+ 3. **Never complete multiple subtasks without updating** - If you complete 3 subtasks without updating the task file, you will lose progress if interrupted.
30
+ 4. **Update order matters**:
31
+ - Complete the subtask (e.g., write code, run command)
32
+ - **IMMEDIATELY** update the task file to mark it as [x] completed
33
+ - Then move to the next subtask
34
+ 5. **On resume/restart**: Read the task file first to see which subtasks are marked [x], then continue from the first incomplete subtask.
35
+
36
+ **Example of correct behavior:**
37
+ \`\`\`
38
+ ## Task: Implement Feature X
39
+ - [x] Subtask 1: Read existing code Completed and marked
40
+ - [x] Subtask 2: Write new function ← Completed and marked
41
+ - [ ] Subtask 3: Add tests ← Start this next
42
+ - [ ] Subtask 4: Run tests
43
+
44
+ Step 1: Complete Subtask 1 Update file Mark [x]
45
+ Step 2: Complete Subtask 2 Update file Mark [x]
46
+ Step 3: Now work on Subtask 3...
47
+ \`\`\`
48
+
49
+ **Wrong approach (causes data loss on interruption):**
50
+ - Complete Subtask 1, 2, 3 (no file updates)
51
+ - Then update all at once
52
+ - If interrupted, all progress is lost!
53
+
54
+ # Workflow
55
+ 1. Understand the problem deeply. Carefully read the issue and think critically about what is required.
56
+ 2. Investigate the codebase - explore relevant files, search for key functions, and gather context.
57
+ 3. Develop a clear, step-by-step plan and display it as a todo list.
58
+ 4. Implement the fix incrementally with small, testable changes.
59
+ 5. Test frequently - run tests after each change to verify correctness.
60
+ 6. Iterate until all tests pass and the solution is robust.
61
+ 7. Reflect and validate comprehensively.
62
+
63
+ ## Making Code Changes
64
+ - Make small, focused changes.
65
+ - Test after each change.
66
+ - Fix any issues that arise.
67
+ - Continue until all tests pass.
68
+
69
+ ## Testing
70
+ - Run existing tests if available.
71
+ - Create test cases for edge cases.
72
+ - Verify your solution works correctly.
73
+ - Test boundary conditions.
74
+
75
+ Remember: Keep working until the problem is completely solved and verified.`;
@@ -356,6 +356,34 @@ export const toolDefinitions: Record<string, ToolDef> = {
356
356
  text: z.string().optional().describe("Text to type."),
357
357
  }),
358
358
  },
359
+ update_task: {
360
+ description: [
361
+ "Update the task file to mark subtasks as completed.",
362
+ "CRITICAL: You MUST call this tool after completing EACH subtask, before moving to the next one.",
363
+ "This ensures progress is saved and can be recovered after interruptions.",
364
+ "",
365
+ "Usage pattern:",
366
+ "1. Complete a subtask (e.g., write code, run test)",
367
+ "2. Call update_task to mark it as [x]",
368
+ "3. Then proceed to the next subtask",
369
+ "",
370
+ "Do NOT batch multiple subtasks - update after EACH one!",
371
+ ].join("\n"),
372
+ parameters: z.object({
373
+ taskFile: z
374
+ .string()
375
+ .describe("Path to the task file (e.g., .acmecode/tasks/current.md)"),
376
+ title: z.string().describe("Task title"),
377
+ steps: z
378
+ .array(
379
+ z.object({
380
+ done: z.boolean().describe("Whether this step is completed"),
381
+ text: z.string().describe("Description of this step"),
382
+ }),
383
+ )
384
+ .describe("All task steps - mark completed ones as done: true"),
385
+ }),
386
+ },
359
387
  };
360
388
 
361
389
  /**
@@ -1098,6 +1126,25 @@ export const toolExecutors: Record<string, (args: any) => Promise<string>> = {
1098
1126
  browser_action: async (args) => {
1099
1127
  return executeBrowserAction(args);
1100
1128
  },
1129
+ update_task: async (args) => {
1130
+ try {
1131
+ const { updateTaskFile } = await import("./task.js");
1132
+ const taskPath = path.resolve(process.cwd(), args.taskFile);
1133
+ const steps = args.steps.map((s: { done: boolean; text: string }) => ({
1134
+ done: s.done,
1135
+ text: s.text,
1136
+ }));
1137
+
1138
+ updateTaskFile(taskPath, args.title, steps);
1139
+
1140
+ const completedCount = steps.filter(
1141
+ (s: { done: boolean }) => s.done,
1142
+ ).length;
1143
+ return `Task file updated: ${completedCount}/${steps.length} steps completed. Path: ${taskPath}`;
1144
+ } catch (err: any) {
1145
+ return `Error updating task file: ${err.message}`;
1146
+ }
1147
+ },
1101
1148
  };
1102
1149
 
1103
1150
  // Create AI SDK tool objects (with execute) for the agent
@@ -0,0 +1,90 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import path from "path";
3
+
4
+ export interface TaskStep {
5
+ done: boolean;
6
+ text: string;
7
+ }
8
+
9
+ export interface TaskFile {
10
+ title: string;
11
+ steps: TaskStep[];
12
+ }
13
+
14
+ /**
15
+ * Parse a task markdown file content
16
+ */
17
+ export function parseTaskFile(content: string): TaskFile {
18
+ const lines = content.split("\n");
19
+ const steps: TaskStep[] = [];
20
+ let title = "";
21
+
22
+ for (const line of lines) {
23
+ const trimmed = line.trim();
24
+
25
+ // Extract title from first non-empty line that starts with ##
26
+ if (!title && trimmed.startsWith("##")) {
27
+ title = trimmed.replace(/^#+\s*/, "").trim();
28
+ continue;
29
+ }
30
+
31
+ // Parse task steps (lines starting with - [ ])
32
+ const doneMatch = trimmed.match(/^-\s*\[([ x])\]\s*(.*)/);
33
+ if (doneMatch) {
34
+ const isDone = doneMatch[1] === "x";
35
+ const text = doneMatch[2].trim();
36
+ steps.push({ done: isDone, text });
37
+ }
38
+ }
39
+
40
+ return { title: title || "Task", steps };
41
+ }
42
+
43
+ /**
44
+ * Generate task file content from parsed data
45
+ */
46
+ export function generateTaskContent(title: string, steps: TaskStep[]): string {
47
+ const lines = [`## ${title}`, ""];
48
+
49
+ for (const step of steps) {
50
+ const checkbox = step.done ? "[x]" : "[ ]";
51
+ lines.push(`- ${checkbox} ${step.text}`);
52
+ }
53
+
54
+ return lines.join("\n");
55
+ }
56
+
57
+ /**
58
+ * Update a task file with new steps
59
+ */
60
+ export function updateTaskFile(
61
+ taskPath: string,
62
+ title: string,
63
+ steps: TaskStep[],
64
+ ): void {
65
+ const taskDir = path.dirname(taskPath);
66
+ if (!existsSync(taskDir)) {
67
+ mkdirSync(taskDir, { recursive: true });
68
+ }
69
+
70
+ const content = generateTaskContent(title, steps);
71
+ writeFileSync(taskPath, content, "utf-8");
72
+ }
73
+
74
+ /**
75
+ * Load existing task or create new one
76
+ */
77
+ export function loadOrCreateTask(
78
+ taskPath: string,
79
+ initialTitle: string,
80
+ ): TaskFile {
81
+ if (existsSync(taskPath)) {
82
+ const content = readFileSync(taskPath, "utf-8");
83
+ return parseTaskFile(content);
84
+ }
85
+
86
+ return {
87
+ title: initialTitle,
88
+ steps: [],
89
+ };
90
+ }