centaurus-cli 3.1.2 → 3.1.4

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 (142) hide show
  1. package/dist/cli-adapter.js +689 -155
  2. package/dist/cli-adapter.js.map +1 -1
  3. package/dist/config/defaultConfig.js +1 -4
  4. package/dist/config/defaultConfig.js.map +1 -1
  5. package/dist/config/models.js +6 -0
  6. package/dist/config/models.js.map +1 -1
  7. package/dist/config/slash-commands.js +66 -2
  8. package/dist/config/slash-commands.js.map +1 -1
  9. package/dist/config/types.js +4 -4
  10. package/dist/config/types.js.map +1 -1
  11. package/dist/index.js +36 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/services/ai-context-injector.js +109 -0
  14. package/dist/services/ai-context-injector.js.map +1 -1
  15. package/dist/services/ai-service-client.js +3 -2
  16. package/dist/services/ai-service-client.js.map +1 -1
  17. package/dist/services/api-client.js.map +1 -1
  18. package/dist/services/background-task-manager.js +59 -0
  19. package/dist/services/background-task-manager.js.map +1 -1
  20. package/dist/services/local-chat-storage.js +2 -0
  21. package/dist/services/local-chat-storage.js.map +1 -1
  22. package/dist/services/skill-storage.js +141 -0
  23. package/dist/services/skill-storage.js.map +1 -0
  24. package/dist/services/sub-agent-manager.js +49 -8
  25. package/dist/services/sub-agent-manager.js.map +1 -1
  26. package/dist/services/warpify-detector.js +17 -5
  27. package/dist/services/warpify-detector.js.map +1 -1
  28. package/dist/tools/background-command.js +5 -2
  29. package/dist/tools/background-command.js.map +1 -1
  30. package/dist/tools/command.js +367 -109
  31. package/dist/tools/command.js.map +1 -1
  32. package/dist/tools/file-ops.js +23 -6
  33. package/dist/tools/file-ops.js.map +1 -1
  34. package/dist/tools/plan-mode.js +184 -336
  35. package/dist/tools/plan-mode.js.map +1 -1
  36. package/dist/tools/sub-agent.js +24 -5
  37. package/dist/tools/sub-agent.js.map +1 -1
  38. package/dist/tools/todo-list.js +157 -0
  39. package/dist/tools/todo-list.js.map +1 -0
  40. package/dist/types/skill.js +30 -0
  41. package/dist/types/skill.js.map +1 -0
  42. package/dist/ui/components/App.js +956 -162
  43. package/dist/ui/components/App.js.map +1 -1
  44. package/dist/ui/components/AuthScreen.js +3 -1
  45. package/dist/ui/components/AuthScreen.js.map +1 -1
  46. package/dist/ui/components/AuthWelcomeScreen.js +3 -1
  47. package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
  48. package/dist/ui/components/CodeBlock.js +3 -1
  49. package/dist/ui/components/CodeBlock.js.map +1 -1
  50. package/dist/ui/components/CompactShellPreview.js +44 -0
  51. package/dist/ui/components/CompactShellPreview.js.map +1 -0
  52. package/dist/ui/components/ConfigViewer.js +3 -1
  53. package/dist/ui/components/ConfigViewer.js.map +1 -1
  54. package/dist/ui/components/ConfirmPrompt.js +3 -1
  55. package/dist/ui/components/ConfirmPrompt.js.map +1 -1
  56. package/dist/ui/components/ConnectionStatusMessage.js +3 -1
  57. package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
  58. package/dist/ui/components/DetailedPlanReviewScreen.js +84 -74
  59. package/dist/ui/components/DetailedPlanReviewScreen.js.map +1 -1
  60. package/dist/ui/components/DiffViewer.js +6 -3
  61. package/dist/ui/components/DiffViewer.js.map +1 -1
  62. package/dist/ui/components/FileCreationPreview.js.map +1 -1
  63. package/dist/ui/components/FileTagAutocomplete.js +4 -2
  64. package/dist/ui/components/FileTagAutocomplete.js.map +1 -1
  65. package/dist/ui/components/InputBox.js +243 -40
  66. package/dist/ui/components/InputBox.js.map +1 -1
  67. package/dist/ui/components/InteractiveShell.js +5 -3
  68. package/dist/ui/components/InteractiveShell.js.map +1 -1
  69. package/dist/ui/components/KeyboardHelp.js +4 -1
  70. package/dist/ui/components/KeyboardHelp.js.map +1 -1
  71. package/dist/ui/components/LoadingIndicator.js +3 -1
  72. package/dist/ui/components/LoadingIndicator.js.map +1 -1
  73. package/dist/ui/components/MCPAddScreen.js +63 -13
  74. package/dist/ui/components/MCPAddScreen.js.map +1 -1
  75. package/dist/ui/components/MarkdownRenderer.js +3 -1
  76. package/dist/ui/components/MarkdownRenderer.js.map +1 -1
  77. package/dist/ui/components/MessageDisplay.js +9 -7
  78. package/dist/ui/components/MessageDisplay.js.map +1 -1
  79. package/dist/ui/components/ModelPicker.js +170 -0
  80. package/dist/ui/components/ModelPicker.js.map +1 -0
  81. package/dist/ui/components/MonitorModeAIPanel.js +3 -1
  82. package/dist/ui/components/MonitorModeAIPanel.js.map +1 -1
  83. package/dist/ui/components/PlanAcceptedMessage.js +12 -6
  84. package/dist/ui/components/PlanAcceptedMessage.js.map +1 -1
  85. package/dist/ui/components/PlanQuestionMessage.js +37 -0
  86. package/dist/ui/components/PlanQuestionMessage.js.map +1 -0
  87. package/dist/ui/components/PlanQuestionScreen.js +138 -0
  88. package/dist/ui/components/PlanQuestionScreen.js.map +1 -0
  89. package/dist/ui/components/PlanReviewScreen.js +7 -9
  90. package/dist/ui/components/PlanReviewScreen.js.map +1 -1
  91. package/dist/ui/components/RulesEditorScreen.js +65 -28
  92. package/dist/ui/components/RulesEditorScreen.js.map +1 -1
  93. package/dist/ui/components/SelectPrompt.js +3 -1
  94. package/dist/ui/components/SelectPrompt.js.map +1 -1
  95. package/dist/ui/components/SkillCreatorScreen.js +217 -0
  96. package/dist/ui/components/SkillCreatorScreen.js.map +1 -0
  97. package/dist/ui/components/SlashCommandAutocomplete.js +4 -2
  98. package/dist/ui/components/SlashCommandAutocomplete.js.map +1 -1
  99. package/dist/ui/components/StatusBar.js +4 -2
  100. package/dist/ui/components/StatusBar.js.map +1 -1
  101. package/dist/ui/components/StreamingMessageDisplay.js +5 -3
  102. package/dist/ui/components/StreamingMessageDisplay.js.map +1 -1
  103. package/dist/ui/components/SubAgentListScreen.js +65 -0
  104. package/dist/ui/components/SubAgentListScreen.js.map +1 -0
  105. package/dist/ui/components/SubAgentViewScreen.js +123 -0
  106. package/dist/ui/components/SubAgentViewScreen.js.map +1 -0
  107. package/dist/ui/components/TaskCompletedMessage.js +40 -8
  108. package/dist/ui/components/TaskCompletedMessage.js.map +1 -1
  109. package/dist/ui/components/TaskProgressIndicator.js +6 -4
  110. package/dist/ui/components/TaskProgressIndicator.js.map +1 -1
  111. package/dist/ui/components/TextEditor.js +297 -0
  112. package/dist/ui/components/TextEditor.js.map +1 -0
  113. package/dist/ui/components/TodoListMessage.js +59 -0
  114. package/dist/ui/components/TodoListMessage.js.map +1 -0
  115. package/dist/ui/components/ToolExecutionMessage.js +134 -84
  116. package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
  117. package/dist/ui/components/ToolExecutionStatus.js +3 -1
  118. package/dist/ui/components/ToolExecutionStatus.js.map +1 -1
  119. package/dist/ui/components/WelcomeBanner.js +33 -33
  120. package/dist/ui/components/WelcomeBanner.js.map +1 -1
  121. package/dist/ui/components/WorkflowCreatorScreen.js +5 -3
  122. package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -1
  123. package/dist/ui/theme.js +97 -0
  124. package/dist/ui/theme.js.map +1 -0
  125. package/dist/ui/utils/chat-history-limit.js +247 -0
  126. package/dist/ui/utils/chat-history-limit.js.map +1 -0
  127. package/dist/utils/chat-formatter.js +22 -9
  128. package/dist/utils/chat-formatter.js.map +1 -1
  129. package/dist/utils/git-stats.js +7 -5
  130. package/dist/utils/git-stats.js.map +1 -1
  131. package/dist/utils/input-classifier.js +11 -1
  132. package/dist/utils/input-classifier.js.map +1 -1
  133. package/dist/utils/output-truncation.js +175 -0
  134. package/dist/utils/output-truncation.js.map +1 -0
  135. package/dist/utils/rule-reference-resolver.js +3 -3
  136. package/dist/utils/rule-reference-resolver.js.map +1 -1
  137. package/dist/utils/tunnel-commands-manager.js +134 -0
  138. package/dist/utils/tunnel-commands-manager.js.map +1 -0
  139. package/package.json +91 -90
  140. package/postinstall.js +4 -11
  141. package/dist/ui/components/MultiLineInput.js +0 -255
  142. package/dist/ui/components/MultiLineInput.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/plan-mode.ts"],"sourcesContent":["/**\r\n * Plan Mode - Structured Task Planning and Execution\r\n * Enables AI to create structured plans with hierarchical tasks and track completion\r\n * \r\n * Enhanced Features:\r\n * - Hierarchical tasks with subtasks (e.g., Task 1 -> 1.1, 1.2, 1.3)\r\n * - Design summary for context understanding\r\n * - Phased execution (one task at a time)\r\n * - Subtask-level completion tracking\r\n */\r\n\r\nimport { Tool, ToolExecutionContext } from './types.js';\r\n\r\n// ============================================================================\r\n// INTERFACES\r\n// ============================================================================\r\n\r\n/**\r\n * A subtask within a main task (e.g., 1.1, 1.2, 2.1)\r\n */\r\nexport interface PlanSubtask {\r\n id: string; // e.g., \"1.1\", \"2.3\"\r\n description: string;\r\n status: 'pending' | 'in_progress' | 'completed' | 'skipped';\r\n requirements?: string; // Traceability, e.g., \"Requirements: 1.1, 1.4\"\r\n completedAt?: Date;\r\n}\r\n\r\n/**\r\n * A main task in the plan (e.g., Task 1, Task 2)\r\n */\r\nexport interface PlanStep {\r\n id: string; // e.g., \"task_1\", \"task_2\"\r\n description: string; // Main task description\r\n subtasks: PlanSubtask[]; // Numbered subtasks (1.1, 1.2, etc.)\r\n status: 'pending' | 'in_progress' | 'completed' | 'skipped';\r\n estimatedComplexity?: 'low' | 'medium' | 'high';\r\n requirements?: string; // Traceability requirements\r\n completedAt?: Date;\r\n}\r\n\r\n/**\r\n * The complete plan with design summary and hierarchical tasks\r\n */\r\nexport interface Plan {\r\n title: string;\r\n designSummary: string; // Detailed design understanding\r\n summary: string; // Brief approach summary\r\n steps: PlanStep[];\r\n createdAt: Date;\r\n approved: boolean;\r\n isActive: boolean;\r\n currentTaskIndex: number; // Index of current main task (0-based)\r\n currentSubtaskIndex: number; // Index of current subtask within task (-1 if no subtasks)\r\n}\r\n\r\n// ============================================================================\r\n// STATE\r\n// ============================================================================\r\n\r\n// In-memory plan state\r\nlet currentPlan: Plan | null = null;\r\n\r\n// ============================================================================\r\n// TOOLS\r\n// ============================================================================\r\n\r\n/**\r\n * Create Plan Tool\r\n * AI uses this to generate a structured plan with hierarchical tasks\r\n */\r\nexport const createPlanTool: Tool = {\r\n schema: {\r\n name: 'create_plan',\r\n description: `Use this tool when in planning mode to create a detailed implementation plan.\r\nThis will present the plan to the user for review and approval before execution begins.\r\n\r\nThe plan should include:\r\n1. A clear title describing what will be accomplished\r\n2. A detailed design summary explaining your understanding of the codebase and approach\r\n3. A brief summary of the overall approach\r\n4. A numbered list of main tasks, each optionally containing subtasks\r\n\r\nIMPORTANT: Only use this tool when in planning mode. Each task should be:\r\n- Specific and actionable\r\n- Can have subtasks for more granular steps\r\n- Ordered in a logical sequence\r\n\r\nExample structure:\r\n- Task 1: Set up core infrastructure\r\n - 1.1: Create directory structure\r\n - 1.2: Define TypeScript interfaces\r\n- Task 2: Implement main feature\r\n - 2.1: Create component files\r\n - 2.2: Add unit tests`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n title: {\r\n type: 'string',\r\n description: 'A clear, concise title for the plan'\r\n },\r\n designSummary: {\r\n type: 'string',\r\n description: 'Detailed understanding of the codebase and how the changes will be implemented. Include architecture decisions, file structure understanding, and implementation approach.'\r\n },\r\n summary: {\r\n type: 'string',\r\n description: 'Brief 1-2 sentence summary of the overall approach'\r\n },\r\n tasks: {\r\n type: 'array',\r\n items: {\r\n type: 'object',\r\n properties: {\r\n description: {\r\n type: 'string',\r\n description: 'Clear description of what this main task accomplishes'\r\n },\r\n subtasks: {\r\n type: 'array',\r\n items: {\r\n type: 'object',\r\n properties: {\r\n description: {\r\n type: 'string',\r\n description: 'Specific subtask description'\r\n },\r\n requirements: {\r\n type: 'string',\r\n description: 'Optional traceability requirements'\r\n }\r\n },\r\n required: ['description']\r\n },\r\n description: 'Optional list of subtasks within this main task'\r\n },\r\n complexity: {\r\n type: 'string',\r\n enum: ['low', 'medium', 'high'],\r\n description: 'Estimated complexity of the task'\r\n },\r\n requirements: {\r\n type: 'string',\r\n description: 'Optional traceability requirements'\r\n }\r\n },\r\n required: ['description']\r\n },\r\n description: 'List of main tasks to execute, in order'\r\n }\r\n },\r\n required: ['title', 'summary', 'tasks']\r\n }\r\n },\r\n\r\n async execute(args: Record<string, any>, context: ToolExecutionContext): Promise<string> {\r\n const title = args.title as string;\r\n const designSummary = args.designSummary as string || '';\r\n const summary = args.summary as string;\r\n const tasks = args.tasks as Array<{\r\n description: string;\r\n subtasks?: Array<{ description: string; requirements?: string }>;\r\n complexity?: string;\r\n requirements?: string;\r\n }>;\r\n\r\n if (!title || title.trim().length === 0) {\r\n throw new Error('Plan title cannot be empty');\r\n }\r\n\r\n if (!tasks || tasks.length === 0) {\r\n throw new Error('Plan must have at least one task');\r\n }\r\n\r\n // Create the plan object with hierarchical structure\r\n const plan: Plan = {\r\n title: title.trim(),\r\n designSummary: designSummary?.trim() || '',\r\n summary: summary?.trim() || '',\r\n steps: tasks.map((task, taskIndex) => ({\r\n id: `task_${taskIndex + 1}`,\r\n description: task.description.trim(),\r\n subtasks: (task.subtasks || []).map((subtask, subtaskIndex) => ({\r\n id: `${taskIndex + 1}.${subtaskIndex + 1}`,\r\n description: subtask.description.trim(),\r\n status: 'pending' as const,\r\n requirements: subtask.requirements?.trim()\r\n })),\r\n status: 'pending' as const,\r\n estimatedComplexity: task.complexity as 'low' | 'medium' | 'high' | undefined,\r\n requirements: task.requirements?.trim()\r\n })),\r\n createdAt: new Date(),\r\n approved: false,\r\n isActive: false,\r\n currentTaskIndex: 0,\r\n currentSubtaskIndex: -1\r\n };\r\n\r\n currentPlan = plan;\r\n\r\n // Return confirmation - the UI will handle displaying the plan\r\n return `PLAN_CREATED:${JSON.stringify(plan)}`;\r\n }\r\n};\r\n\r\n/**\r\n * Mark Task Complete Tool\r\n * AI uses this to mark individual tasks or subtasks as completed during execution\r\n */\r\nexport const markTaskCompleteTool: Tool = {\r\n schema: {\r\n name: 'mark_task_complete',\r\n description: `Use this tool to mark a task or subtask as completed in the current plan.\r\nCall this after successfully completing each task/subtask in the plan.\r\n\r\nThis will:\r\n1. Update the task/subtask status to 'completed'\r\n2. Show a completion message in the UI\r\n3. Automatically advance to the next task/subtask\r\n\r\nYou can mark:\r\n- A main task: task_number=2\r\n- A subtask: task_number=\"2.1\" (marks subtask 1 of task 2)\r\n\r\nIMPORTANT: \r\n- Must have an active approved plan\r\n- Mark subtasks complete as you finish them\r\n- After marking the LAST task/subtask complete, output your summary then call task_complete to end the session`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n task_number: {\r\n type: 'string',\r\n description: 'The task number to mark complete. Use integer for main task (e.g., \"2\") or dot notation for subtask (e.g., \"2.1\")'\r\n },\r\n completion_note: {\r\n type: 'string',\r\n description: 'Optional note about what was accomplished'\r\n }\r\n },\r\n required: ['task_number']\r\n }\r\n },\r\n\r\n async execute(args: Record<string, any>, context: ToolExecutionContext): Promise<string> {\r\n if (!currentPlan) {\r\n throw new Error('No active plan. Create a plan first using create_plan.');\r\n }\r\n\r\n if (!currentPlan.approved || !currentPlan.isActive) {\r\n throw new Error('Plan must be approved and active before marking tasks complete.');\r\n }\r\n\r\n const taskNumberStr = String(args.task_number);\r\n const completionNote = args.completion_note as string | undefined;\r\n\r\n // Parse task number - can be \"2\" or \"2.1\"\r\n const parts = taskNumberStr.split('.');\r\n const mainTaskNum = parseInt(parts[0], 10);\r\n const subtaskNum = parts.length > 1 ? parseInt(parts[1], 10) : null;\r\n\r\n if (isNaN(mainTaskNum) || mainTaskNum < 1 || mainTaskNum > currentPlan.steps.length) {\r\n throw new Error(`Invalid task number. Must be between 1 and ${currentPlan.steps.length}.`);\r\n }\r\n\r\n const taskIndex = mainTaskNum - 1;\r\n const task = currentPlan.steps[taskIndex];\r\n\r\n // Handle subtask completion\r\n if (subtaskNum !== null) {\r\n if (!task.subtasks || subtaskNum < 1 || subtaskNum > task.subtasks.length) {\r\n throw new Error(`Invalid subtask number. Task ${mainTaskNum} has ${task.subtasks?.length || 0} subtasks.`);\r\n }\r\n\r\n const subtaskIndex = subtaskNum - 1;\r\n const subtask = task.subtasks[subtaskIndex];\r\n\r\n if (subtask.status === 'completed') {\r\n return `Subtask ${taskNumberStr} is already marked as completed.`;\r\n }\r\n\r\n // Mark subtask complete\r\n subtask.status = 'completed';\r\n subtask.completedAt = new Date();\r\n\r\n // Check if all subtasks are complete, then mark main task as complete\r\n const allSubtasksComplete = task.subtasks.every(st => st.status === 'completed' || st.status === 'skipped');\r\n if (allSubtasksComplete) {\r\n task.status = 'completed';\r\n task.completedAt = new Date();\r\n } else {\r\n task.status = 'in_progress';\r\n }\r\n\r\n // Update current subtask index\r\n const nextPendingSubtaskIndex = task.subtasks.findIndex(\r\n (st, idx) => idx > subtaskIndex && st.status === 'pending'\r\n );\r\n currentPlan.currentSubtaskIndex = nextPendingSubtaskIndex;\r\n\r\n // Calculate progress\r\n const { completedCount, totalCount, allComplete } = calculateProgress();\r\n\r\n const result = {\r\n type: 'subtask',\r\n taskNumber: taskNumberStr,\r\n taskDescription: subtask.description,\r\n completionNote: completionNote || null,\r\n completedCount,\r\n totalCount,\r\n allComplete,\r\n nextSubtask: nextPendingSubtaskIndex !== -1 ? task.subtasks[nextPendingSubtaskIndex].description : null,\r\n mainTaskComplete: allSubtasksComplete\r\n };\r\n\r\n return `TASK_COMPLETED:${JSON.stringify(result)}`;\r\n }\r\n\r\n // Handle main task completion (mark all subtasks as complete too)\r\n if (task.status === 'completed') {\r\n return `Task ${mainTaskNum} is already marked as completed.`;\r\n }\r\n\r\n // Mark the main task and all its subtasks as complete\r\n task.status = 'completed';\r\n task.completedAt = new Date();\r\n task.subtasks.forEach(st => {\r\n if (st.status !== 'completed' && st.status !== 'skipped') {\r\n st.status = 'completed';\r\n st.completedAt = new Date();\r\n }\r\n });\r\n\r\n // Update current task index to next pending task\r\n const nextPendingIndex = currentPlan.steps.findIndex(\r\n (step, idx) => idx > taskIndex && step.status === 'pending'\r\n );\r\n if (nextPendingIndex !== -1) {\r\n currentPlan.currentTaskIndex = nextPendingIndex;\r\n currentPlan.currentSubtaskIndex = -1;\r\n }\r\n\r\n // Calculate progress\r\n const { completedCount, totalCount, allComplete } = calculateProgress();\r\n\r\n const result = {\r\n type: 'task',\r\n taskNumber: mainTaskNum,\r\n taskDescription: task.description,\r\n completionNote: completionNote || null,\r\n completedCount,\r\n totalCount,\r\n allComplete,\r\n nextTask: allComplete ? null : currentPlan.steps[currentPlan.currentTaskIndex]?.description\r\n };\r\n\r\n return `TASK_COMPLETED:${JSON.stringify(result)}`;\r\n }\r\n};\r\n\r\n// ============================================================================\r\n// HELPER FUNCTIONS\r\n// ============================================================================\r\n\r\n/**\r\n * Calculate overall progress including subtasks\r\n */\r\nfunction calculateProgress(): { completedCount: number; totalCount: number; allComplete: boolean } {\r\n if (!currentPlan) {\r\n return { completedCount: 0, totalCount: 0, allComplete: false };\r\n }\r\n\r\n let completedCount = 0;\r\n let totalCount = 0;\r\n\r\n currentPlan.steps.forEach(step => {\r\n if (step.subtasks.length > 0) {\r\n // Count subtasks\r\n totalCount += step.subtasks.length;\r\n completedCount += step.subtasks.filter(st => st.status === 'completed').length;\r\n } else {\r\n // Count the main task if no subtasks\r\n totalCount += 1;\r\n if (step.status === 'completed') completedCount += 1;\r\n }\r\n });\r\n\r\n return {\r\n completedCount,\r\n totalCount,\r\n allComplete: completedCount === totalCount && totalCount > 0\r\n };\r\n}\r\n\r\n/**\r\n * Set the current plan (used by CLI adapter)\r\n */\r\nexport function setPlan(plan: Plan): void {\r\n currentPlan = plan;\r\n}\r\n\r\n/**\r\n * Get the current plan\r\n */\r\nexport function getCurrentPlan(): Plan | null {\r\n return currentPlan;\r\n}\r\n\r\n/**\r\n * Clear the current plan\r\n */\r\nexport function clearPlan(): void {\r\n currentPlan = null;\r\n}\r\n\r\n/**\r\n * Approve the current plan and make it active\r\n */\r\nexport function approvePlan(): Plan | null {\r\n if (currentPlan) {\r\n currentPlan.approved = true;\r\n currentPlan.isActive = true;\r\n currentPlan.currentTaskIndex = 0;\r\n currentPlan.currentSubtaskIndex = currentPlan.steps[0]?.subtasks?.length > 0 ? 0 : -1;\r\n }\r\n return currentPlan;\r\n}\r\n\r\n/**\r\n * Mark a task as complete by task number (for compatibility)\r\n */\r\nexport function markTaskComplete(taskNumber: number): PlanStep | null {\r\n if (!currentPlan || taskNumber < 1 || taskNumber > currentPlan.steps.length) {\r\n return null;\r\n }\r\n\r\n const task = currentPlan.steps[taskNumber - 1];\r\n task.status = 'completed';\r\n task.completedAt = new Date();\r\n\r\n // Also mark all subtasks as complete\r\n task.subtasks.forEach(st => {\r\n st.status = 'completed';\r\n st.completedAt = new Date();\r\n });\r\n\r\n return task;\r\n}\r\n\r\n/**\r\n * Get the current phase (task) with all its subtasks\r\n */\r\nexport function getCurrentPhase(): { taskNumber: number; task: PlanStep } | null {\r\n if (!currentPlan || !currentPlan.isActive) return null;\r\n\r\n const taskIndex = currentPlan.currentTaskIndex;\r\n if (taskIndex < 0 || taskIndex >= currentPlan.steps.length) return null;\r\n\r\n const task = currentPlan.steps[taskIndex];\r\n if (task.status === 'completed') {\r\n // Find next pending task\r\n const nextIndex = currentPlan.steps.findIndex(\r\n (step, idx) => idx > taskIndex && step.status === 'pending'\r\n );\r\n if (nextIndex === -1) return null;\r\n return { taskNumber: nextIndex + 1, task: currentPlan.steps[nextIndex] };\r\n }\r\n\r\n return { taskNumber: taskIndex + 1, task };\r\n}\r\n\r\n/**\r\n * Advance to the next phase after current task is complete\r\n * Returns the new phase or null if all phases are done\r\n */\r\nexport function advanceToNextPhase(): { taskNumber: number; task: PlanStep } | null {\r\n if (!currentPlan || !currentPlan.isActive) return null;\r\n\r\n const currentTask = currentPlan.steps[currentPlan.currentTaskIndex];\r\n\r\n // Mark current task as complete if not already\r\n if (currentTask && currentTask.status !== 'completed') {\r\n currentTask.status = 'completed';\r\n currentTask.completedAt = new Date();\r\n }\r\n\r\n // Find next pending task\r\n const nextIndex = currentPlan.steps.findIndex(\r\n (step, idx) => idx > currentPlan!.currentTaskIndex && step.status === 'pending'\r\n );\r\n\r\n if (nextIndex === -1) {\r\n return null; // All phases complete\r\n }\r\n\r\n currentPlan.currentTaskIndex = nextIndex;\r\n currentPlan.currentSubtaskIndex = currentPlan.steps[nextIndex].subtasks.length > 0 ? 0 : -1;\r\n\r\n return { taskNumber: nextIndex + 1, task: currentPlan.steps[nextIndex] };\r\n}\r\n\r\n/**\r\n * Get the next incomplete task\r\n */\r\nexport function getNextIncompleteTask(): { taskNumber: number; task: PlanStep } | null {\r\n if (!currentPlan) return null;\r\n\r\n const index = currentPlan.steps.findIndex(step => step.status === 'pending' || step.status === 'in_progress');\r\n if (index === -1) return null;\r\n\r\n return {\r\n taskNumber: index + 1,\r\n task: currentPlan.steps[index]\r\n };\r\n}\r\n\r\n/**\r\n * Check if all tasks are complete\r\n */\r\nexport function areAllTasksComplete(): boolean {\r\n if (!currentPlan) return false;\r\n return currentPlan.steps.every(step => step.status === 'completed' || step.status === 'skipped');\r\n}\r\n\r\n/**\r\n * Get plan progress summary (including subtasks)\r\n */\r\nexport function getPlanProgress(): { completed: number; total: number; percentage: number; currentTask: number; totalTasks: number } | null {\r\n if (!currentPlan) return null;\r\n\r\n const { completedCount, totalCount } = calculateProgress();\r\n const percentage = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0;\r\n\r\n const completedTasks = currentPlan.steps.filter(s => s.status === 'completed').length;\r\n\r\n return {\r\n completed: completedCount,\r\n total: totalCount,\r\n percentage,\r\n currentTask: currentPlan.currentTaskIndex + 1,\r\n totalTasks: currentPlan.steps.length\r\n };\r\n}\r\n\r\n/**\r\n * Generate plan context for AI system prompt injection (shows all tasks)\r\n */\r\nexport function getPlanContextForPrompt(): string {\r\n if (!currentPlan || !currentPlan.isActive) return '';\r\n\r\n const progress = getPlanProgress();\r\n if (!progress) return '';\r\n\r\n let context = `\\n\\n## ACTIVE PLAN: ${currentPlan.title}\\n`;\r\n if (currentPlan.designSummary) {\r\n context += `\\n### Design Summary:\\n${currentPlan.designSummary}\\n`;\r\n }\r\n context += `\\nProgress: ${progress.completed}/${progress.total} items completed (${progress.percentage}%)\\n`;\r\n context += `Current Task: ${progress.currentTask}/${progress.totalTasks}\\n\\n`;\r\n context += `### Tasks:\\n`;\r\n\r\n currentPlan.steps.forEach((step, index) => {\r\n const statusIcon = step.status === 'completed' ? '✅' :\r\n step.status === 'in_progress' ? '🔄' :\r\n step.status === 'skipped' ? '⏭️' : '⏳';\r\n const isCurrent = index === currentPlan!.currentTaskIndex && step.status !== 'completed';\r\n const marker = isCurrent ? ' 👈 CURRENT' : '';\r\n context += `${index + 1}. ${statusIcon} ${step.description}${marker}\\n`;\r\n\r\n // Add subtasks\r\n step.subtasks.forEach((subtask, subIndex) => {\r\n const subStatusIcon = subtask.status === 'completed' ? '✅' :\r\n subtask.status === 'in_progress' ? '🔄' : '⬜';\r\n context += ` ${index + 1}.${subIndex + 1}. ${subStatusIcon} ${subtask.description}\\n`;\r\n });\r\n });\r\n\r\n const nextTask = getNextIncompleteTask();\r\n if (nextTask) {\r\n context += `\\n**NEXT ACTION**: Complete task ${nextTask.taskNumber}: ${nextTask.task.description}\\n`;\r\n context += `After completing this task, call mark_task_complete with task_number=${nextTask.taskNumber}\\n`;\r\n } else {\r\n context += `\\n**ALL TASKS COMPLETE**: Output your summary of what was accomplished, then call task_complete().\\n`;\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * Generate context for only the current phase (single task with its subtasks)\r\n * Used for phased execution where AI only sees one task at a time\r\n */\r\nexport function getPhaseContextForPrompt(): string {\r\n if (!currentPlan || !currentPlan.isActive) return '';\r\n\r\n const currentPhase = getCurrentPhase();\r\n if (!currentPhase) {\r\n return `\\n**ALL TASKS COMPLETE**: Output your summary of what was accomplished, then call task_complete().\\n`;\r\n }\r\n\r\n const progress = getPlanProgress();\r\n const { taskNumber, task } = currentPhase;\r\n\r\n let context = `\\n\\n## CURRENT TASK: ${currentPlan.title}\\n`;\r\n\r\n if (currentPlan.designSummary) {\r\n context += `\\n### Design Context:\\n${currentPlan.designSummary}\\n`;\r\n }\r\n\r\n context += `\\n### Overall Progress: Task ${taskNumber}/${currentPlan.steps.length}\\n`;\r\n context += `${progress ? `(${progress.completed}/${progress.total} items completed - ${progress.percentage}%)` : ''}\\n\\n`;\r\n\r\n context += `### YOUR CURRENT TASK:\\n`;\r\n context += `**Task ${taskNumber}: ${task.description}**\\n\\n`;\r\n\r\n if (task.subtasks.length > 0) {\r\n context += `Subtasks to complete:\\n`;\r\n task.subtasks.forEach((subtask, index) => {\r\n const subStatusIcon = subtask.status === 'completed' ? '✅' :\r\n subtask.status === 'in_progress' ? '🔄' : '⬜';\r\n const isCurrentSubtask = index === currentPlan!.currentSubtaskIndex;\r\n const marker = isCurrentSubtask && subtask.status === 'pending' ? ' 👈 CURRENT' : '';\r\n context += ` ${taskNumber}.${index + 1}. ${subStatusIcon} ${subtask.description}${marker}\\n`;\r\n });\r\n\r\n context += `\\n**Instructions**: Complete each subtask in order.\\n`;\r\n context += `After completing a subtask, call: mark_task_complete(task_number=\"${taskNumber}.X\")\\n`;\r\n context += `When all subtasks are done, the main task will be automatically marked complete.\\n`;\r\n } else {\r\n context += `\\n**Instructions**: Complete this task.\\n`;\r\n context += `When done, call: mark_task_complete(task_number=\"${taskNumber}\")\\n`;\r\n }\r\n\r\n return context;\r\n}\r\n\r\n// ============================================================================\r\n// EXPORTS\r\n// ============================================================================\r\n\r\nexport default {\r\n createPlanTool,\r\n markTaskCompleteTool,\r\n setPlan,\r\n getCurrentPlan,\r\n clearPlan,\r\n approvePlan,\r\n markTaskComplete,\r\n getCurrentPhase,\r\n advanceToNextPhase,\r\n getNextIncompleteTask,\r\n areAllTasksComplete,\r\n getPlanProgress,\r\n getPlanContextForPrompt,\r\n getPhaseContextForPrompt\r\n};\r\n"],"mappings":"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","names":["completedCount","totalCount","allComplete","result"]}
1
+ {"version":3,"sources":["../../src/tools/plan-mode.ts"],"sourcesContent":["/**\r\n * Plan Mode - Structured Plan Document and Step-wise Execution\r\n * Enables AI to create detailed plan documents and track step-by-step completion\r\n * \r\n * Features:\r\n * - Full markdown plan document storage\r\n * - Flat implementation steps (no phases/subtasks hierarchy)\r\n * - Step-by-step completion tracking with tick marks\r\n * - Plan document rendered in review screen\r\n */\r\n\r\nimport { Tool, ToolExecutionContext } from './types.js';\r\n\r\n// ============================================================================\r\n// INTERFACES\r\n// ============================================================================\r\n\r\n/**\r\n * An implementation step extracted from the plan document\r\n */\r\nexport interface PlanImplementationStep {\r\n id: number; // 1-indexed step number\r\n description: string; // Step description\r\n status: 'pending' | 'completed';\r\n completedAt?: Date;\r\n}\r\n\r\n/**\r\n * The complete plan with markdown document and flat implementation steps\r\n */\r\nexport interface Plan {\r\n title: string;\r\n document: string; // Full markdown plan document\r\n implementationSteps: PlanImplementationStep[];\r\n createdAt: Date;\r\n approved: boolean;\r\n isActive: boolean;\r\n}\r\n\r\n// Keep old interfaces as aliases for backward compat in imports\r\nexport type PlanStep = PlanImplementationStep;\r\nexport type PlanSubtask = PlanImplementationStep;\r\n\r\n// ============================================================================\r\n// STATE\r\n// ============================================================================\r\n\r\n// In-memory plan state\r\nlet currentPlan: Plan | null = null;\r\n\r\n// ============================================================================\r\n// TOOLS\r\n// ============================================================================\r\n\r\n/**\r\n * Create Plan Tool\r\n * AI uses this to submit a detailed plan document with extracted implementation steps\r\n */\r\nexport const createPlanTool: Tool = {\r\n schema: {\r\n name: 'create_plan',\r\n description: `Use this tool when in planning mode to submit your detailed implementation plan.\r\n\r\nYou MUST provide:\r\n1. A clear title for the plan\r\n2. A comprehensive markdown document detailing the full plan (analysis, mappings, tables, etc.)\r\n3. An array of implementation steps extracted from the document\r\n\r\nThe markdown document should be detailed and include sections like:\r\n- Overview/summary of what will be done\r\n- Analysis (current state, proposed changes, tables, mappings)\r\n- Implementation Steps section with numbered steps\r\n- Verification/testing notes\r\n\r\nThe implementation_steps array should contain one string per step, matching the numbered steps in your document.\r\nEach step should be a concise one-line description.\r\n\r\nIMPORTANT: Only use this tool when in planning mode.`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n title: {\r\n type: 'string',\r\n description: 'A clear, concise title for the plan'\r\n },\r\n document: {\r\n type: 'string',\r\n description: 'The full markdown plan document with detailed analysis, tables, mappings, and implementation steps'\r\n },\r\n implementation_steps: {\r\n type: 'array',\r\n items: {\r\n type: 'string'\r\n },\r\n description: 'Array of implementation step descriptions, one per step. These are the actionable items that will be tracked.'\r\n }\r\n },\r\n required: ['title', 'document', 'implementation_steps']\r\n }\r\n },\r\n\r\n async execute(args: Record<string, any>, context: ToolExecutionContext): Promise<string> {\r\n const title = args.title as string;\r\n const document = args.document as string;\r\n const implementationSteps = args.implementation_steps as string[];\r\n\r\n if (!title || title.trim().length === 0) {\r\n throw new Error('Plan title cannot be empty');\r\n }\r\n\r\n if (!document || document.trim().length === 0) {\r\n throw new Error('Plan document cannot be empty');\r\n }\r\n\r\n if (!implementationSteps || implementationSteps.length === 0) {\r\n throw new Error('Plan must have at least one implementation step');\r\n }\r\n\r\n // Create the plan object with flat step structure\r\n const plan: Plan = {\r\n title: title.trim(),\r\n document: document.trim(),\r\n implementationSteps: implementationSteps.map((step, index) => {\r\n // Strip leading number prefix (e.g., \"1. \", \"2. \", \"1: \") if the AI included it,\r\n // since the UI adds step.id as the number. This prevents \"1. 1. Create...\"\r\n const cleaned = step.trim().replace(/^\\d+[\\.\\)\\:\\-]\\s*/, '');\r\n return {\r\n id: index + 1,\r\n description: cleaned,\r\n status: 'pending' as const,\r\n };\r\n }),\r\n createdAt: new Date(),\r\n approved: false,\r\n isActive: false,\r\n };\r\n\r\n currentPlan = plan;\r\n\r\n // Return confirmation - the UI will handle displaying the plan\r\n return `PLAN_CREATED:${JSON.stringify(plan)}`;\r\n }\r\n};\r\n\r\n/**\r\n * Mark Task Complete Tool\r\n * AI uses this to mark implementation steps as completed during execution\r\n */\r\nexport const markTaskCompleteTool: Tool = {\r\n schema: {\r\n name: 'mark_task_complete',\r\n description: `Use this tool to mark an implementation step as completed in the current plan.\r\nCall this after successfully completing each step in the plan.\r\n\r\nThis will:\r\n1. Update the step status to 'completed'\r\n2. Show a tick mark next to the step in the UI\r\n3. Report progress on all steps\r\n\r\nYou must provide the step number (1-indexed) matching the implementation steps list.\r\n\r\nIMPORTANT: \r\n- Must have an active approved plan\r\n- Mark steps complete in order as you finish them\r\n- After marking the LAST step complete, output your summary then call task_complete to end the session`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n step_number: {\r\n type: 'number',\r\n description: 'The step number to mark complete (1-indexed, e.g., 1, 2, 3...)'\r\n },\r\n completion_note: {\r\n type: 'string',\r\n description: 'Optional note about what was accomplished'\r\n }\r\n },\r\n required: ['step_number']\r\n }\r\n },\r\n\r\n async execute(args: Record<string, any>, context: ToolExecutionContext): Promise<string> {\r\n if (!currentPlan) {\r\n throw new Error('No active plan. Create a plan first using create_plan.');\r\n }\r\n\r\n if (!currentPlan.approved || !currentPlan.isActive) {\r\n throw new Error('Plan must be approved and active before marking steps complete.');\r\n }\r\n\r\n const stepNumber = Number(args.step_number);\r\n const completionNote = args.completion_note as string | undefined;\r\n\r\n if (isNaN(stepNumber) || stepNumber < 1 || stepNumber > currentPlan.implementationSteps.length) {\r\n throw new Error(`Invalid step number. Must be between 1 and ${currentPlan.implementationSteps.length}.`);\r\n }\r\n\r\n const stepIndex = stepNumber - 1;\r\n const step = currentPlan.implementationSteps[stepIndex];\r\n\r\n if (step.status === 'completed') {\r\n return `Step ${stepNumber} is already marked as completed.`;\r\n }\r\n\r\n // Mark step complete\r\n step.status = 'completed';\r\n step.completedAt = new Date();\r\n\r\n // Calculate progress\r\n const completedCount = currentPlan.implementationSteps.filter(s => s.status === 'completed').length;\r\n const totalCount = currentPlan.implementationSteps.length;\r\n const allComplete = completedCount === totalCount;\r\n\r\n // Find next pending step\r\n const nextStep = currentPlan.implementationSteps.find(s => s.status === 'pending');\r\n\r\n const result = {\r\n stepNumber,\r\n stepDescription: step.description,\r\n completionNote: completionNote || null,\r\n completedCount,\r\n totalCount,\r\n allComplete,\r\n nextStep: nextStep ? nextStep.description : null,\r\n nextStepNumber: nextStep ? nextStep.id : null,\r\n // Include all steps with their current status for UI rendering\r\n allSteps: currentPlan.implementationSteps.map(s => ({\r\n id: s.id,\r\n description: s.description,\r\n status: s.status,\r\n })),\r\n };\r\n\r\n return `TASK_COMPLETED:${JSON.stringify(result)}`;\r\n }\r\n};\r\n\r\n/**\r\n * Plan Ask Question Tool\r\n * AI uses this during planning to ask the user clarifying questions\r\n */\r\nexport const planAskQuestionTool: Tool = {\r\n schema: {\r\n name: 'plan_ask_question',\r\n description: `Use this tool during planning mode to ask the user a clarifying question when you need more information before creating the plan.\r\n\r\nUse this when:\r\n- The user's request is ambiguous and could be interpreted in multiple ways\r\n- You need to know about specific preferences (e.g., framework, architecture style)\r\n- There are multiple valid approaches and you want the user to choose\r\n- Important details are missing from the request\r\n\r\nYou provide:\r\n1. The question text\r\n2. An array of suggested answer options (2-4 options)\r\n\r\nThe user can select one of your suggested options, type a custom answer, or skip the question.\r\nIf the user skips, proceed with the most appropriate default approach.\r\n\r\nIMPORTANT: Only use this during planning mode, before calling create_plan.\r\nDo not ask too many questions — 1-2 targeted questions maximum.`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n question: {\r\n type: 'string',\r\n description: 'The clarifying question to ask the user'\r\n },\r\n options: {\r\n type: 'array',\r\n items: {\r\n type: 'string'\r\n },\r\n description: 'Array of 2-4 suggested answer options for the user to choose from'\r\n }\r\n },\r\n required: ['question', 'options']\r\n }\r\n },\r\n\r\n async execute(args: Record<string, any>, context: ToolExecutionContext): Promise<string> {\r\n const question = args.question as string;\r\n const options = args.options as string[];\r\n\r\n if (!question || question.trim().length === 0) {\r\n throw new Error('Question cannot be empty');\r\n }\r\n\r\n if (!options || options.length < 2) {\r\n throw new Error('Must provide at least 2 answer options');\r\n }\r\n\r\n if (options.length > 4) {\r\n throw new Error('Maximum 4 answer options allowed');\r\n }\r\n\r\n const result = {\r\n question: question.trim(),\r\n options: options.map(o => o.trim()),\r\n };\r\n\r\n return `ASK_QUESTION:${JSON.stringify(result)}`;\r\n }\r\n};\r\n\r\n// ============================================================================\r\n// HELPER FUNCTIONS\r\n// ============================================================================\r\n\r\n/**\r\n * Set the current plan (used by CLI adapter)\r\n */\r\nexport function setPlan(plan: Plan): void {\r\n currentPlan = plan;\r\n}\r\n\r\n/**\r\n * Get the current plan\r\n */\r\nexport function getCurrentPlan(): Plan | null {\r\n return currentPlan;\r\n}\r\n\r\n/**\r\n * Clear the current plan\r\n */\r\nexport function clearPlan(): void {\r\n currentPlan = null;\r\n}\r\n\r\n/**\r\n * Approve the current plan and make it active\r\n */\r\nexport function approvePlan(): Plan | null {\r\n if (currentPlan) {\r\n currentPlan.approved = true;\r\n currentPlan.isActive = true;\r\n }\r\n return currentPlan;\r\n}\r\n\r\n/**\r\n * Get all implementation steps with their current status\r\n */\r\nexport function getAllStepsStatus(): PlanImplementationStep[] {\r\n if (!currentPlan) return [];\r\n return currentPlan.implementationSteps.map(s => ({ ...s }));\r\n}\r\n\r\n/**\r\n * Check if all steps are complete\r\n */\r\nexport function areAllTasksComplete(): boolean {\r\n if (!currentPlan) return false;\r\n return currentPlan.implementationSteps.every(step => step.status === 'completed');\r\n}\r\n\r\n/**\r\n * Get plan progress summary\r\n */\r\nexport function getPlanProgress(): { completed: number; total: number; percentage: number } | null {\r\n if (!currentPlan) return null;\r\n\r\n const completed = currentPlan.implementationSteps.filter(s => s.status === 'completed').length;\r\n const total = currentPlan.implementationSteps.length;\r\n const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;\r\n\r\n return { completed, total, percentage };\r\n}\r\n\r\n/**\r\n * Get the plan document (markdown)\r\n */\r\nexport function getPlanDocument(): string | null {\r\n if (!currentPlan) return null;\r\n return currentPlan.document;\r\n}\r\n\r\n/**\r\n * Generate plan context for AI prompt injection (shows all steps with status)\r\n */\r\nexport function getPlanContextForPrompt(): string {\r\n if (!currentPlan || !currentPlan.isActive) return '';\r\n\r\n const progress = getPlanProgress();\r\n if (!progress) return '';\r\n\r\n let context = `\\n\\n## ACTIVE PLAN: ${currentPlan.title}\\n`;\r\n context += `Progress: ${progress.completed}/${progress.total} steps completed (${progress.percentage}%)\\n\\n`;\r\n context += `### Implementation Steps:\\n`;\r\n\r\n currentPlan.implementationSteps.forEach((step) => {\r\n const statusIcon = step.status === 'completed' ? '[x]' : '[ ]';\r\n const marker = step.status === 'pending' && !currentPlan!.implementationSteps.slice(0, step.id - 1).some(s => s.status === 'pending')\r\n ? ' <-- NEXT'\r\n : '';\r\n context += `${step.id}. ${statusIcon} ${step.description}${marker}\\n`;\r\n });\r\n\r\n const nextStep = currentPlan.implementationSteps.find(s => s.status === 'pending');\r\n if (nextStep) {\r\n context += `\\n**NEXT ACTION**: Complete step ${nextStep.id}: ${nextStep.description}\\n`;\r\n context += `After completing this step, call mark_task_complete with step_number=${nextStep.id}\\n`;\r\n } else {\r\n context += `\\n**ALL STEPS COMPLETE**: Output your summary of what was accomplished, then call task_complete().\\n`;\r\n }\r\n\r\n return context;\r\n}\r\n\r\n// Legacy exports for backward compatibility\r\nexport function getCurrentPhase(): { taskNumber: number; task: PlanImplementationStep } | null {\r\n if (!currentPlan || !currentPlan.isActive) return null;\r\n const nextStep = currentPlan.implementationSteps.find(s => s.status === 'pending');\r\n if (!nextStep) return null;\r\n return { taskNumber: nextStep.id, task: nextStep };\r\n}\r\n\r\nexport function advanceToNextPhase(): { taskNumber: number; task: PlanImplementationStep } | null {\r\n return getCurrentPhase();\r\n}\r\n\r\nexport function getNextIncompleteTask(): { taskNumber: number; task: PlanImplementationStep } | null {\r\n return getCurrentPhase();\r\n}\r\n\r\nexport function getPhaseContextForPrompt(): string {\r\n return getPlanContextForPrompt();\r\n}\r\n\r\nexport function markTaskComplete(taskNumber: number): PlanImplementationStep | null {\r\n if (!currentPlan || taskNumber < 1 || taskNumber > currentPlan.implementationSteps.length) {\r\n return null;\r\n }\r\n const step = currentPlan.implementationSteps[taskNumber - 1];\r\n step.status = 'completed';\r\n step.completedAt = new Date();\r\n return step;\r\n}\r\n\r\n// ============================================================================\r\n// EXPORTS\r\n// ============================================================================\r\n\r\nexport default {\r\n createPlanTool,\r\n markTaskCompleteTool,\r\n planAskQuestionTool,\r\n setPlan,\r\n getCurrentPlan,\r\n clearPlan,\r\n approvePlan,\r\n getAllStepsStatus,\r\n areAllTasksComplete,\r\n getPlanProgress,\r\n getPlanDocument,\r\n getPlanContextForPrompt,\r\n getPhaseContextForPrompt,\r\n getCurrentPhase,\r\n advanceToNextPhase,\r\n getNextIncompleteTask,\r\n markTaskComplete,\r\n};\r\n"],"mappings":"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","names":[]}
@@ -59,13 +59,18 @@ IMPORTANT:
59
59
  complexity: {
60
60
  type: "integer",
61
61
  description: "Task complexity rating 1-10. REQUIRED for spawn action. Determines which AI model is used."
62
+ },
63
+ allowed_tools: {
64
+ type: "array",
65
+ items: { type: "string" },
66
+ description: 'Optional list of tool names the sub-agent is allowed to use (e.g. ["view_file", "grep_search", "list_dir"]). If not specified, all tools are available. Use this to restrict the sub-agent to read-only operations or specific capabilities. The sub-agent will always have access to task_complete regardless of this list.'
62
67
  }
63
68
  },
64
69
  required: ["action"]
65
70
  }
66
71
  },
67
72
  async execute(args, context) {
68
- const { action, agent_id, prompt, context: agentContext, working_directory, complexity, time_delay } = args;
73
+ const { action, agent_id, prompt, context: agentContext, working_directory, complexity, time_delay, allowed_tools } = args;
69
74
  switch (action) {
70
75
  case "spawn": {
71
76
  if (!prompt) {
@@ -85,17 +90,20 @@ IMPORTANT:
85
90
  context: agentContext || "",
86
91
  workingDirectory: working_directory,
87
92
  complexity,
88
- parentContextManager: context.contextManager
93
+ parentContextManager: context.contextManager,
94
+ allowedTools: allowed_tools
89
95
  });
90
96
  if (!result.success) {
91
97
  throw new Error(result.error || "Failed to spawn sub-agent");
92
98
  }
93
- const modelUsed = complexity <= 5 ? "Gemini 3 Flash Preview" : "Gemini 3.1 Pro Preview";
99
+ const modelUsed = complexity <= 5 ? "MiniMax M2.5 (NIM)" : "GLM-5 (NIM)";
100
+ const toolRestriction = allowed_tools && allowed_tools.length > 0 ? `
101
+ **Allowed Tools:** ${allowed_tools.join(", ")}` : "\n**Allowed Tools:** All tools (unrestricted)";
94
102
  return `**Sub-Agent Spawned Successfully**
95
103
 
96
104
  **Agent ID:** ${result.agentId}
97
105
  **Model:** ${modelUsed} (complexity: ${complexity}/10)
98
- **Working Directory:** ${working_directory}
106
+ **Working Directory:** ${working_directory}${toolRestriction}
99
107
  **Task:** ${prompt.substring(0, 200)}${prompt.length > 200 ? "..." : ""}
100
108
 
101
109
  The sub-agent is now running in the background. Use:
@@ -110,7 +118,18 @@ The sub-agent is now running in the background. Use:
110
118
  throw new Error('Missing required parameter "agent_id" for action "wait_for_status"');
111
119
  }
112
120
  if (time_delay && time_delay > 0) {
113
- await new Promise((resolve) => setTimeout(resolve, time_delay * 1e3));
121
+ const pollIntervalMs = 1e3;
122
+ const totalMs = time_delay * 1e3;
123
+ let elapsed = 0;
124
+ while (elapsed < totalMs) {
125
+ const agent = SubAgentManager.getSubAgent(agent_id);
126
+ if (agent && agent.status !== "running" && agent.status !== "pending") {
127
+ break;
128
+ }
129
+ const sleepMs = Math.min(pollIntervalMs, totalMs - elapsed);
130
+ await new Promise((resolve) => setTimeout(resolve, sleepMs));
131
+ elapsed += sleepMs;
132
+ }
114
133
  }
115
134
  const subAgent = SubAgentManager.getSubAgent(agent_id);
116
135
  if (!subAgent) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/sub-agent.ts"],"sourcesContent":["/**\r\n * Sub-Agent Tool\r\n * \r\n * Allows the main AI agent to spawn and manage background sub-agents\r\n * for delegated tasks. Uses action-based pattern similar to background_command.\r\n */\r\n\r\nimport { Tool } from './types.js';\r\nimport { SubAgentManager } from '../services/sub-agent-manager.js';\r\n\r\nexport const subAgentTool: Tool = {\r\n schema: {\r\n name: 'sub_agent',\r\n description: `Spawn and manage background sub-agents for delegated tasks. Sub-agents run independently and have full tool access.\r\n\r\nACTIONS:\r\n1. \"spawn\" - Create and start a new sub-agent with a specific task\r\n2. \"wait_for_status\" - Wait for a duration and then check the status/progress of a sub-agent enterduration as 0 if you want to check immediately\r\n3. \"terminate\" - Kill a running sub-agent\r\n4. \"read_results\" - Get the final results and diffs from a completed sub-agent\r\n5. \"list\" - List all sub-agents and their current status\r\n\r\nUSE CASES:\r\n- Delegate a well-defined subtask while you continue with other work\r\n- Run multiple independent tasks in parallel\r\n- Handle complex multi-step operations in the background\r\n\r\nCOMPLEXITY GUIDELINES (1-10):\r\n- 1-3: Very simple tasks (create a single file, fix a typo)\r\n- 4-5: Simple tasks (implement a small function, update configs)\r\n- 6-7: Medium tasks (implement a feature, refactor a file)\r\n- 8-10: Complex tasks (multi-file refactors, debugging complex issues)\r\n\r\nIMPORTANT:\r\n- You CANNOT call task_complete while sub-agents are running\r\n- Always check status or read_results before completing your main task\r\n- Sub-agents auto-terminate after 10 minutes\r\n- Maximum 5 concurrent sub-agents allowed\r\n- Sub-agents use the same session quota as you`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n action: {\r\n type: 'string',\r\n enum: ['spawn', 'wait_for_status', 'terminate', 'read_results', 'list'],\r\n description: 'The action to perform.',\r\n },\r\n agent_id: {\r\n type: 'string',\r\n description: 'Sub-agent ID. REQUIRED for wait_for_status, terminate, and read_results actions.',\r\n },\r\n time_delay: {\r\n type: 'integer',\r\n description: 'Optional delay in seconds to wait before checking status (for wait_for_status action). Set to 0 for immediate check.',\r\n },\r\n prompt: {\r\n type: 'string',\r\n description: 'Detailed task description for the sub-agent. REQUIRED for spawn action. Be specific about what needs to be done.',\r\n },\r\n context: {\r\n type: 'string',\r\n description: 'Relevant context information for spawn action. Include file paths, project structure, relevant code snippets, or any information the sub-agent needs.',\r\n },\r\n working_directory: {\r\n type: 'string',\r\n description: 'Already Existing Working directory for the sub-agent to start working in. REQUIRED for spawn action.',\r\n },\r\n complexity: {\r\n type: 'integer',\r\n description: 'Task complexity rating 1-10. REQUIRED for spawn action. Determines which AI model is used.',\r\n },\r\n },\r\n required: ['action'],\r\n },\r\n },\r\n\r\n async execute(args, context) {\r\n const { action, agent_id, prompt, context: agentContext, working_directory, complexity, time_delay } = args;\r\n\r\n switch (action) {\r\n case 'spawn': {\r\n // Validate required parameters\r\n if (!prompt) {\r\n throw new Error('Missing required parameter \"prompt\" for action \"spawn\"');\r\n }\r\n if (!working_directory) {\r\n throw new Error('Missing required parameter \"working_directory\" for action \"spawn\"');\r\n }\r\n if (complexity === undefined || complexity === null) {\r\n throw new Error('Missing required parameter \"complexity\" for action \"spawn\"');\r\n }\r\n if (complexity < 1 || complexity > 10) {\r\n throw new Error('Complexity must be between 1 and 10');\r\n }\r\n\r\n // Spawn the sub-agent\r\n // Pass parent's contextManager so the subagent can route tools\r\n // through the active remote session (SSH/Docker/WSL)\r\n const result = await SubAgentManager.spawnSubAgent({\r\n prompt,\r\n context: agentContext || '',\r\n workingDirectory: working_directory,\r\n complexity,\r\n parentContextManager: context.contextManager,\r\n });\r\n\r\n if (!result.success) {\r\n throw new Error(result.error || 'Failed to spawn sub-agent');\r\n }\r\n\r\n const modelUsed = complexity <= 5 ? 'Gemini 3 Flash Preview' : 'Gemini 3.1 Pro Preview';\r\n\r\n return `**Sub-Agent Spawned Successfully**\r\n\r\n**Agent ID:** ${result.agentId}\r\n**Model:** ${modelUsed} (complexity: ${complexity}/10)\r\n**Working Directory:** ${working_directory}\r\n**Task:** ${prompt.substring(0, 200)}${prompt.length > 200 ? '...' : ''}\r\n\r\nThe sub-agent is now running in the background. Use:\r\n- \\`sub_agent(action=\"wait_for_status\", agent_id=\"${result.agentId}\", time_delay=5)\\` to wait and check progress\r\n- \\`sub_agent(action=\"terminate\", agent_id=\"${result.agentId}\")\\` to stop it\r\n- \\`sub_agent(action=\"read_results\", agent_id=\"${result.agentId}\")\\` to get results when completed\r\n\r\n⚠️ You cannot call task_complete while this sub-agent is running.`;\r\n }\r\n\r\n case 'wait_for_status': {\r\n if (!agent_id) {\r\n throw new Error('Missing required parameter \"agent_id\" for action \"wait_for_status\"');\r\n }\r\n\r\n // Wait if delay is requested\r\n if (time_delay && time_delay > 0) {\r\n await new Promise(resolve => setTimeout(resolve, time_delay * 1000));\r\n }\r\n\r\n const subAgent = SubAgentManager.getSubAgent(agent_id);\r\n if (!subAgent) {\r\n // List available sub-agents\r\n const allAgents = SubAgentManager.getAllSubAgents();\r\n if (allAgents.length === 0) {\r\n throw new Error(`Sub-agent \"${agent_id}\" not found. No sub-agents are currently tracked.`);\r\n }\r\n const agentList = allAgents.map(a =>\r\n `- ${a.id} (${a.status}): ${a.prompt.substring(0, 50)}...`\r\n ).join('\\n');\r\n throw new Error(`Sub-agent \"${agent_id}\" not found.\\n\\nAvailable sub-agents:\\n${agentList}`);\r\n }\r\n\r\n const durationMs = (subAgent.endTime || new Date()).getTime() - subAgent.startTime.getTime();\r\n const durationSec = Math.round(durationMs / 1000);\r\n\r\n let statusEmoji = '⏳';\r\n if (subAgent.status === 'running') statusEmoji = '🔄';\r\n else if (subAgent.status === 'completed') statusEmoji = '✓';\r\n else if (subAgent.status === 'failed') statusEmoji = '❌';\r\n else if (subAgent.status === 'terminated') statusEmoji = '⏹️';\r\n\r\n let statusDetails = `**Sub-Agent Status**\r\n\r\n**Agent ID:** ${agent_id}\r\n**Status:** ${statusEmoji} ${subAgent.status}\r\n**Model:** ${subAgent.model}\r\n**Duration:** ${durationSec}s\r\n**Turns:** ${subAgent.turnCount}\r\n**File Operations:** ${subAgent.fileOperations.length}\r\n**Tool Calls:** ${subAgent.toolHistory.length}`;\r\n\r\n if (subAgent.result) {\r\n statusDetails += `\\n\\n**Result:** ${subAgent.result}`;\r\n }\r\n\r\n if (subAgent.error) {\r\n statusDetails += `\\n\\n**Error:** ${subAgent.error}`;\r\n }\r\n\r\n if (subAgent.status === 'completed' || subAgent.status === 'failed' || subAgent.status === 'terminated') {\r\n statusDetails += `\\n\\nUse \\`sub_agent(action=\"read_results\", agent_id=\"${agent_id}\")\\` to see the full diff of changes.`;\r\n }\r\n\r\n return statusDetails;\r\n }\r\n\r\n case 'terminate': {\r\n if (!agent_id) {\r\n throw new Error('Missing required parameter \"agent_id\" for action \"terminate\"');\r\n }\r\n\r\n const result = SubAgentManager.terminateSubAgent(agent_id);\r\n if (!result.success) {\r\n throw new Error(result.error || 'Failed to terminate sub-agent');\r\n }\r\n\r\n return `**Sub-Agent Terminated**\r\n\r\n**Agent ID:** ${agent_id}\r\n**Status:** ⏹️ Terminated\r\n\r\nThe sub-agent has been stopped. Use \\`sub_agent(action=\"read_results\", agent_id=\"${agent_id}\")\\` to see what it accomplished before termination.`;\r\n }\r\n\r\n case 'read_results': {\r\n if (!agent_id) {\r\n throw new Error('Missing required parameter \"agent_id\" for action \"read_results\"');\r\n }\r\n\r\n const subAgent = SubAgentManager.getSubAgent(agent_id);\r\n if (!subAgent) {\r\n throw new Error(`Sub-agent \"${agent_id}\" not found`);\r\n }\r\n\r\n if (subAgent.status === 'running' || subAgent.status === 'pending') {\r\n throw new Error(`Sub-agent \"${agent_id}\" is still running. Wait for it to complete or terminate it first.`);\r\n }\r\n\r\n // Get the formatted diff output\r\n const diffOutput = SubAgentManager.getSubAgentDiff(agent_id);\r\n\r\n // Mark as read\r\n SubAgentManager.markSubAgentRead(agent_id);\r\n\r\n return diffOutput;\r\n }\r\n\r\n case 'list': {\r\n const allAgents = SubAgentManager.getAllSubAgents();\r\n\r\n if (allAgents.length === 0) {\r\n return 'No sub-agents currently tracked.';\r\n }\r\n\r\n const runningCount = allAgents.filter(a => a.status === 'running' || a.status === 'pending').length;\r\n const completedCount = allAgents.filter(a => a.status === 'completed').length;\r\n const failedCount = allAgents.filter(a => a.status === 'failed' || a.status === 'terminated').length;\r\n\r\n let output = `**Sub-Agent Summary**\r\n\r\n**Running:** ${runningCount}\r\n**Completed:** ${completedCount} \r\n**Failed/Terminated:** ${failedCount}\r\n\r\n**All Sub-Agents:**\r\n`;\r\n\r\n for (const agent of allAgents) {\r\n let statusEmoji = '⏳';\r\n if (agent.status === 'running') statusEmoji = '🔄';\r\n else if (agent.status === 'completed') statusEmoji = '✅';\r\n else if (agent.status === 'failed') statusEmoji = '❌';\r\n else if (agent.status === 'terminated') statusEmoji = '⏹️';\r\n\r\n const taskPreview = agent.prompt.substring(0, 60) + (agent.prompt.length > 60 ? '...' : '');\r\n output += `\\n${statusEmoji} **${agent.id}** (${agent.status})\\n Task: ${taskPreview}\\n`;\r\n }\r\n\r\n return output;\r\n }\r\n\r\n default:\r\n throw new Error(`Unknown action \"${action}\". Valid actions are: spawn, status, terminate, read_results, list`);\r\n }\r\n },\r\n};\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tools/sub-agent.ts"],"sourcesContent":["/**\r\n * Sub-Agent Tool\r\n * \r\n * Allows the main AI agent to spawn and manage background sub-agents\r\n * for delegated tasks. Uses action-based pattern similar to background_command.\r\n */\r\n\r\nimport { Tool } from './types.js';\r\nimport { SubAgentManager } from '../services/sub-agent-manager.js';\r\n\r\nexport const subAgentTool: Tool = {\r\n schema: {\r\n name: 'sub_agent',\r\n description: `Spawn and manage background sub-agents for delegated tasks. Sub-agents run independently and have full tool access.\r\n\r\nACTIONS:\r\n1. \"spawn\" - Create and start a new sub-agent with a specific task\r\n2. \"wait_for_status\" - Wait for a duration and then check the status/progress of a sub-agent enterduration as 0 if you want to check immediately\r\n3. \"terminate\" - Kill a running sub-agent\r\n4. \"read_results\" - Get the final results and diffs from a completed sub-agent\r\n5. \"list\" - List all sub-agents and their current status\r\n\r\nUSE CASES:\r\n- Delegate a well-defined subtask while you continue with other work\r\n- Run multiple independent tasks in parallel\r\n- Handle complex multi-step operations in the background\r\n\r\nCOMPLEXITY GUIDELINES (1-10):\r\n- 1-3: Very simple tasks (create a single file, fix a typo)\r\n- 4-5: Simple tasks (implement a small function, update configs)\r\n- 6-7: Medium tasks (implement a feature, refactor a file)\r\n- 8-10: Complex tasks (multi-file refactors, debugging complex issues)\r\n\r\nIMPORTANT:\r\n- You CANNOT call task_complete while sub-agents are running\r\n- Always check status or read_results before completing your main task\r\n- Sub-agents auto-terminate after 10 minutes\r\n- Maximum 5 concurrent sub-agents allowed\r\n- Sub-agents use the same session quota as you`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n action: {\r\n type: 'string',\r\n enum: ['spawn', 'wait_for_status', 'terminate', 'read_results', 'list'],\r\n description: 'The action to perform.',\r\n },\r\n agent_id: {\r\n type: 'string',\r\n description: 'Sub-agent ID. REQUIRED for wait_for_status, terminate, and read_results actions.',\r\n },\r\n time_delay: {\r\n type: 'integer',\r\n description: 'Optional delay in seconds to wait before checking status (for wait_for_status action). Set to 0 for immediate check.',\r\n },\r\n prompt: {\r\n type: 'string',\r\n description: 'Detailed task description for the sub-agent. REQUIRED for spawn action. Be specific about what needs to be done.',\r\n },\r\n context: {\r\n type: 'string',\r\n description: 'Relevant context information for spawn action. Include file paths, project structure, relevant code snippets, or any information the sub-agent needs.',\r\n },\r\n working_directory: {\r\n type: 'string',\r\n description: 'Already Existing Working directory for the sub-agent to start working in. REQUIRED for spawn action.',\r\n },\r\n complexity: {\r\n type: 'integer',\r\n description: 'Task complexity rating 1-10. REQUIRED for spawn action. Determines which AI model is used.',\r\n },\r\n allowed_tools: {\r\n type: 'array',\r\n items: { type: 'string' },\r\n description: 'Optional list of tool names the sub-agent is allowed to use (e.g. [\"view_file\", \"grep_search\", \"list_dir\"]). If not specified, all tools are available. Use this to restrict the sub-agent to read-only operations or specific capabilities. The sub-agent will always have access to task_complete regardless of this list.',\r\n },\r\n },\r\n required: ['action'],\r\n },\r\n },\r\n\r\n async execute(args, context) {\r\n const { action, agent_id, prompt, context: agentContext, working_directory, complexity, time_delay, allowed_tools } = args;\r\n\r\n switch (action) {\r\n case 'spawn': {\r\n // Validate required parameters\r\n if (!prompt) {\r\n throw new Error('Missing required parameter \"prompt\" for action \"spawn\"');\r\n }\r\n if (!working_directory) {\r\n throw new Error('Missing required parameter \"working_directory\" for action \"spawn\"');\r\n }\r\n if (complexity === undefined || complexity === null) {\r\n throw new Error('Missing required parameter \"complexity\" for action \"spawn\"');\r\n }\r\n if (complexity < 1 || complexity > 10) {\r\n throw new Error('Complexity must be between 1 and 10');\r\n }\r\n\r\n // Spawn the sub-agent\r\n // Pass parent's contextManager so the subagent can route tools\r\n // through the active remote session (SSH/Docker/WSL)\r\n const result = await SubAgentManager.spawnSubAgent({\r\n prompt,\r\n context: agentContext || '',\r\n workingDirectory: working_directory,\r\n complexity,\r\n parentContextManager: context.contextManager,\r\n allowedTools: allowed_tools,\r\n });\r\n\r\n if (!result.success) {\r\n throw new Error(result.error || 'Failed to spawn sub-agent');\r\n }\r\n\r\n const modelUsed = complexity <= 5 ? 'MiniMax M2.5 (NIM)' : 'GLM-5 (NIM)';\r\n const toolRestriction = allowed_tools && allowed_tools.length > 0\r\n ? `\\n**Allowed Tools:** ${allowed_tools.join(', ')}`\r\n : '\\n**Allowed Tools:** All tools (unrestricted)';\r\n\r\n return `**Sub-Agent Spawned Successfully**\r\n\r\n**Agent ID:** ${result.agentId}\r\n**Model:** ${modelUsed} (complexity: ${complexity}/10)\r\n**Working Directory:** ${working_directory}${toolRestriction}\r\n**Task:** ${prompt.substring(0, 200)}${prompt.length > 200 ? '...' : ''}\r\n\r\nThe sub-agent is now running in the background. Use:\r\n- \\`sub_agent(action=\"wait_for_status\", agent_id=\"${result.agentId}\", time_delay=5)\\` to wait and check progress\r\n- \\`sub_agent(action=\"terminate\", agent_id=\"${result.agentId}\")\\` to stop it\r\n- \\`sub_agent(action=\"read_results\", agent_id=\"${result.agentId}\")\\` to get results when completed\r\n\r\n⚠️ You cannot call task_complete while this sub-agent is running.`;\r\n }\r\n\r\n case 'wait_for_status': {\r\n if (!agent_id) {\r\n throw new Error('Missing required parameter \"agent_id\" for action \"wait_for_status\"');\r\n }\r\n\r\n // Wait with early exit: poll every second and return immediately\r\n // if the sub-agent completes before the full delay elapses\r\n if (time_delay && time_delay > 0) {\r\n const pollIntervalMs = 1000; // check every 1 second\r\n const totalMs = time_delay * 1000;\r\n let elapsed = 0;\r\n\r\n while (elapsed < totalMs) {\r\n const agent = SubAgentManager.getSubAgent(agent_id);\r\n // Exit early if agent finished (completed, failed, or terminated)\r\n if (agent && agent.status !== 'running' && agent.status !== 'pending') {\r\n break;\r\n }\r\n const sleepMs = Math.min(pollIntervalMs, totalMs - elapsed);\r\n await new Promise(resolve => setTimeout(resolve, sleepMs));\r\n elapsed += sleepMs;\r\n }\r\n }\r\n\r\n const subAgent = SubAgentManager.getSubAgent(agent_id);\r\n if (!subAgent) {\r\n // List available sub-agents\r\n const allAgents = SubAgentManager.getAllSubAgents();\r\n if (allAgents.length === 0) {\r\n throw new Error(`Sub-agent \"${agent_id}\" not found. No sub-agents are currently tracked.`);\r\n }\r\n const agentList = allAgents.map(a =>\r\n `- ${a.id} (${a.status}): ${a.prompt.substring(0, 50)}...`\r\n ).join('\\n');\r\n throw new Error(`Sub-agent \"${agent_id}\" not found.\\n\\nAvailable sub-agents:\\n${agentList}`);\r\n }\r\n\r\n const durationMs = (subAgent.endTime || new Date()).getTime() - subAgent.startTime.getTime();\r\n const durationSec = Math.round(durationMs / 1000);\r\n\r\n let statusEmoji = '⏳';\r\n if (subAgent.status === 'running') statusEmoji = '🔄';\r\n else if (subAgent.status === 'completed') statusEmoji = '✓';\r\n else if (subAgent.status === 'failed') statusEmoji = '❌';\r\n else if (subAgent.status === 'terminated') statusEmoji = '⏹️';\r\n\r\n let statusDetails = `**Sub-Agent Status**\r\n\r\n**Agent ID:** ${agent_id}\r\n**Status:** ${statusEmoji} ${subAgent.status}\r\n**Model:** ${subAgent.model}\r\n**Duration:** ${durationSec}s\r\n**Turns:** ${subAgent.turnCount}\r\n**File Operations:** ${subAgent.fileOperations.length}\r\n**Tool Calls:** ${subAgent.toolHistory.length}`;\r\n\r\n if (subAgent.result) {\r\n statusDetails += `\\n\\n**Result:** ${subAgent.result}`;\r\n }\r\n\r\n if (subAgent.error) {\r\n statusDetails += `\\n\\n**Error:** ${subAgent.error}`;\r\n }\r\n\r\n if (subAgent.status === 'completed' || subAgent.status === 'failed' || subAgent.status === 'terminated') {\r\n statusDetails += `\\n\\nUse \\`sub_agent(action=\"read_results\", agent_id=\"${agent_id}\")\\` to see the full diff of changes.`;\r\n }\r\n\r\n return statusDetails;\r\n }\r\n\r\n case 'terminate': {\r\n if (!agent_id) {\r\n throw new Error('Missing required parameter \"agent_id\" for action \"terminate\"');\r\n }\r\n\r\n const result = SubAgentManager.terminateSubAgent(agent_id);\r\n if (!result.success) {\r\n throw new Error(result.error || 'Failed to terminate sub-agent');\r\n }\r\n\r\n return `**Sub-Agent Terminated**\r\n\r\n**Agent ID:** ${agent_id}\r\n**Status:** ⏹️ Terminated\r\n\r\nThe sub-agent has been stopped. Use \\`sub_agent(action=\"read_results\", agent_id=\"${agent_id}\")\\` to see what it accomplished before termination.`;\r\n }\r\n\r\n case 'read_results': {\r\n if (!agent_id) {\r\n throw new Error('Missing required parameter \"agent_id\" for action \"read_results\"');\r\n }\r\n\r\n const subAgent = SubAgentManager.getSubAgent(agent_id);\r\n if (!subAgent) {\r\n throw new Error(`Sub-agent \"${agent_id}\" not found`);\r\n }\r\n\r\n if (subAgent.status === 'running' || subAgent.status === 'pending') {\r\n throw new Error(`Sub-agent \"${agent_id}\" is still running. Wait for it to complete or terminate it first.`);\r\n }\r\n\r\n // Get the formatted diff output\r\n const diffOutput = SubAgentManager.getSubAgentDiff(agent_id);\r\n\r\n // Mark as read\r\n SubAgentManager.markSubAgentRead(agent_id);\r\n\r\n return diffOutput;\r\n }\r\n\r\n case 'list': {\r\n const allAgents = SubAgentManager.getAllSubAgents();\r\n\r\n if (allAgents.length === 0) {\r\n return 'No sub-agents currently tracked.';\r\n }\r\n\r\n const runningCount = allAgents.filter(a => a.status === 'running' || a.status === 'pending').length;\r\n const completedCount = allAgents.filter(a => a.status === 'completed').length;\r\n const failedCount = allAgents.filter(a => a.status === 'failed' || a.status === 'terminated').length;\r\n\r\n let output = `**Sub-Agent Summary**\r\n\r\n**Running:** ${runningCount}\r\n**Completed:** ${completedCount} \r\n**Failed/Terminated:** ${failedCount}\r\n\r\n**All Sub-Agents:**\r\n`;\r\n\r\n for (const agent of allAgents) {\r\n let statusEmoji = '⏳';\r\n if (agent.status === 'running') statusEmoji = '🔄';\r\n else if (agent.status === 'completed') statusEmoji = '✅';\r\n else if (agent.status === 'failed') statusEmoji = '❌';\r\n else if (agent.status === 'terminated') statusEmoji = '⏹️';\r\n\r\n const taskPreview = agent.prompt.substring(0, 60) + (agent.prompt.length > 60 ? '...' : '');\r\n output += `\\n${statusEmoji} **${agent.id}** (${agent.status})\\n Task: ${taskPreview}\\n`;\r\n }\r\n\r\n return output;\r\n }\r\n\r\n default:\r\n throw new Error(`Unknown action \"${action}\". Valid actions are: spawn, status, terminate, read_results, list`);\r\n }\r\n },\r\n};\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,157 @@
1
+ let currentTodoList = [];
2
+ const todoWriteTool = {
3
+ schema: {
4
+ name: "todo_write",
5
+ description: `Use this tool to create and manage a todo list for tracking your progress on multi-step tasks.
6
+
7
+ When to use:
8
+ - When the user asks you to do something that involves 3 or more distinct steps
9
+ - When you need to track progress on a complex task
10
+ - When you want to show the user what you're working on and what's coming next
11
+
12
+ How to use:
13
+ - Provide the FULL list of todo items each time (this replaces the previous list)
14
+ - Each item needs: id (unique string), content (task description), status (pending/in_progress/completed)
15
+ - Mark a task as "in_progress" BEFORE you start working on it
16
+ - Mark a task as "completed" as soon as you finish it
17
+ - You can add new items or remove items by updating the full list
18
+ - Only have ONE task as in_progress at a time
19
+
20
+ You do NOT need to be in plan mode to use this. Use it anytime during normal task execution.`,
21
+ parameters: {
22
+ type: "object",
23
+ properties: {
24
+ todos: {
25
+ type: "array",
26
+ items: {
27
+ type: "object",
28
+ properties: {
29
+ id: {
30
+ type: "string",
31
+ description: "Unique identifier for the todo item"
32
+ },
33
+ content: {
34
+ type: "string",
35
+ description: "The task description"
36
+ },
37
+ status: {
38
+ type: "string",
39
+ enum: ["pending", "in_progress", "completed"],
40
+ description: "Current status: pending, in_progress, or completed"
41
+ }
42
+ },
43
+ required: ["id", "content", "status"]
44
+ },
45
+ description: "The full list of todo items (replaces previous list)"
46
+ }
47
+ },
48
+ required: ["todos"]
49
+ }
50
+ },
51
+ async execute(args, context) {
52
+ const todos = args.todos;
53
+ if (!todos || !Array.isArray(todos)) {
54
+ throw new Error("todos must be an array of todo items");
55
+ }
56
+ if (todos.length === 0) {
57
+ currentTodoList = [];
58
+ return `TODO_UPDATED:${JSON.stringify({ todos: [], summary: "Todo list cleared." })}`;
59
+ }
60
+ for (const item of todos) {
61
+ if (!item.id || !item.content || !item.status) {
62
+ throw new Error("Each todo item must have id, content, and status fields");
63
+ }
64
+ if (!["pending", "in_progress", "completed"].includes(item.status)) {
65
+ throw new Error(`Invalid status "${item.status}". Must be pending, in_progress, or completed.`);
66
+ }
67
+ }
68
+ currentTodoList = todos.map((item) => ({
69
+ id: String(item.id),
70
+ content: item.content.trim(),
71
+ status: item.status
72
+ }));
73
+ const completedCount = currentTodoList.filter((t) => t.status === "completed").length;
74
+ const inProgressCount = currentTodoList.filter((t) => t.status === "in_progress").length;
75
+ const pendingCount = currentTodoList.filter((t) => t.status === "pending").length;
76
+ const totalCount = currentTodoList.length;
77
+ const result = {
78
+ todos: currentTodoList,
79
+ completedCount,
80
+ inProgressCount,
81
+ pendingCount,
82
+ totalCount,
83
+ summary: `Todo list updated: ${completedCount}/${totalCount} completed, ${inProgressCount} in progress, ${pendingCount} pending.`
84
+ };
85
+ return `TODO_UPDATED:${JSON.stringify(result)}`;
86
+ }
87
+ };
88
+ function getCurrentTodoList() {
89
+ return [...currentTodoList];
90
+ }
91
+ function clearTodoList() {
92
+ currentTodoList = [];
93
+ }
94
+ function hasTodoList() {
95
+ return currentTodoList.length > 0;
96
+ }
97
+ function getTodoContextForPrompt() {
98
+ if (currentTodoList.length === 0) return "";
99
+ const completedCount = currentTodoList.filter((t) => t.status === "completed").length;
100
+ const totalCount = currentTodoList.length;
101
+ const percentage = totalCount > 0 ? Math.round(completedCount / totalCount * 100) : 0;
102
+ let context = `
103
+
104
+ ## CURRENT TODO LIST
105
+ `;
106
+ context += `Progress: ${completedCount}/${totalCount} tasks completed (${percentage}%)
107
+
108
+ `;
109
+ currentTodoList.forEach((item) => {
110
+ let statusIcon;
111
+ if (item.status === "completed") {
112
+ statusIcon = "[x]";
113
+ } else if (item.status === "in_progress") {
114
+ statusIcon = "[>]";
115
+ } else {
116
+ statusIcon = "[ ]";
117
+ }
118
+ const marker = item.status === "in_progress" ? " <-- IN PROGRESS" : "";
119
+ context += `- ${statusIcon} ${item.content}${marker}
120
+ `;
121
+ });
122
+ const inProgress = currentTodoList.find((t) => t.status === "in_progress");
123
+ const nextPending = currentTodoList.find((t) => t.status === "pending");
124
+ if (inProgress) {
125
+ context += `
126
+ **CURRENTLY WORKING ON**: ${inProgress.content}
127
+ `;
128
+ } else if (nextPending) {
129
+ context += `
130
+ **NEXT TASK**: ${nextPending.content}
131
+ `;
132
+ } else if (completedCount === totalCount) {
133
+ context += `
134
+ **ALL TASKS COMPLETE**
135
+ `;
136
+ }
137
+ context += `
138
+ Update the todo list using todo_write as you make progress.
139
+ `;
140
+ return context;
141
+ }
142
+ var todo_list_default = {
143
+ todoWriteTool,
144
+ getCurrentTodoList,
145
+ clearTodoList,
146
+ hasTodoList,
147
+ getTodoContextForPrompt
148
+ };
149
+ export {
150
+ clearTodoList,
151
+ todo_list_default as default,
152
+ getCurrentTodoList,
153
+ getTodoContextForPrompt,
154
+ hasTodoList,
155
+ todoWriteTool
156
+ };
157
+ //# sourceMappingURL=todo-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/tools/todo-list.ts"],"sourcesContent":["/**\r\n * Todo List - AI-managed task tracking during normal execution\r\n * Allows AI to create and manage a todo list to track progress on multi-step tasks\r\n * \r\n * Features:\r\n * - Create/update a flat list of todo items\r\n * - Track items as pending, in_progress, or completed\r\n * - Same UI rendering style as plan mode task lists\r\n * - Available in normal mode (not just plan mode)\r\n * - Persistent within a session\r\n */\r\n\r\nimport { Tool, ToolExecutionContext } from './types.js';\r\n\r\n// ============================================================================\r\n// INTERFACES\r\n// ============================================================================\r\n\r\n/**\r\n * A single todo item\r\n */\r\nexport interface TodoItem {\r\n id: string; // Unique identifier\r\n content: string; // Task description\r\n status: 'pending' | 'in_progress' | 'completed';\r\n}\r\n\r\n// ============================================================================\r\n// STATE\r\n// ============================================================================\r\n\r\n// In-memory todo list state\r\nlet currentTodoList: TodoItem[] = [];\r\n\r\n// ============================================================================\r\n// TOOLS\r\n// ============================================================================\r\n\r\n/**\r\n * Todo Write Tool\r\n * AI uses this to create or update the todo list\r\n */\r\nexport const todoWriteTool: Tool = {\r\n schema: {\r\n name: 'todo_write',\r\n description: `Use this tool to create and manage a todo list for tracking your progress on multi-step tasks.\r\n\r\nWhen to use:\r\n- When the user asks you to do something that involves 3 or more distinct steps\r\n- When you need to track progress on a complex task\r\n- When you want to show the user what you're working on and what's coming next\r\n\r\nHow to use:\r\n- Provide the FULL list of todo items each time (this replaces the previous list)\r\n- Each item needs: id (unique string), content (task description), status (pending/in_progress/completed)\r\n- Mark a task as \"in_progress\" BEFORE you start working on it\r\n- Mark a task as \"completed\" as soon as you finish it\r\n- You can add new items or remove items by updating the full list\r\n- Only have ONE task as in_progress at a time\r\n\r\nYou do NOT need to be in plan mode to use this. Use it anytime during normal task execution.`,\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n todos: {\r\n type: 'array',\r\n items: {\r\n type: 'object',\r\n properties: {\r\n id: {\r\n type: 'string',\r\n description: 'Unique identifier for the todo item'\r\n },\r\n content: {\r\n type: 'string',\r\n description: 'The task description'\r\n },\r\n status: {\r\n type: 'string',\r\n enum: ['pending', 'in_progress', 'completed'],\r\n description: 'Current status: pending, in_progress, or completed'\r\n }\r\n },\r\n required: ['id', 'content', 'status']\r\n },\r\n description: 'The full list of todo items (replaces previous list)'\r\n }\r\n },\r\n required: ['todos']\r\n }\r\n },\r\n\r\n async execute(args: Record<string, any>, context: ToolExecutionContext): Promise<string> {\r\n const todos = args.todos as TodoItem[];\r\n\r\n if (!todos || !Array.isArray(todos)) {\r\n throw new Error('todos must be an array of todo items');\r\n }\r\n\r\n if (todos.length === 0) {\r\n // Clear the todo list\r\n currentTodoList = [];\r\n return `TODO_UPDATED:${JSON.stringify({ todos: [], summary: 'Todo list cleared.' })}`;\r\n }\r\n\r\n // Validate each todo item\r\n for (const item of todos) {\r\n if (!item.id || !item.content || !item.status) {\r\n throw new Error('Each todo item must have id, content, and status fields');\r\n }\r\n if (!['pending', 'in_progress', 'completed'].includes(item.status)) {\r\n throw new Error(`Invalid status \"${item.status}\". Must be pending, in_progress, or completed.`);\r\n }\r\n }\r\n\r\n // Update the todo list\r\n currentTodoList = todos.map(item => ({\r\n id: String(item.id),\r\n content: item.content.trim(),\r\n status: item.status,\r\n }));\r\n\r\n // Calculate summary\r\n const completedCount = currentTodoList.filter(t => t.status === 'completed').length;\r\n const inProgressCount = currentTodoList.filter(t => t.status === 'in_progress').length;\r\n const pendingCount = currentTodoList.filter(t => t.status === 'pending').length;\r\n const totalCount = currentTodoList.length;\r\n\r\n const result = {\r\n todos: currentTodoList,\r\n completedCount,\r\n inProgressCount,\r\n pendingCount,\r\n totalCount,\r\n summary: `Todo list updated: ${completedCount}/${totalCount} completed, ${inProgressCount} in progress, ${pendingCount} pending.`,\r\n };\r\n\r\n return `TODO_UPDATED:${JSON.stringify(result)}`;\r\n }\r\n};\r\n\r\n// ============================================================================\r\n// HELPER FUNCTIONS\r\n// ============================================================================\r\n\r\n/**\r\n * Get the current todo list\r\n */\r\nexport function getCurrentTodoList(): TodoItem[] {\r\n return [...currentTodoList];\r\n}\r\n\r\n/**\r\n * Clear the todo list\r\n */\r\nexport function clearTodoList(): void {\r\n currentTodoList = [];\r\n}\r\n\r\n/**\r\n * Check if there's an active todo list\r\n */\r\nexport function hasTodoList(): boolean {\r\n return currentTodoList.length > 0;\r\n}\r\n\r\n/**\r\n * Generate todo list context for AI prompt injection\r\n * This helps the AI remember its current todo list state\r\n */\r\nexport function getTodoContextForPrompt(): string {\r\n if (currentTodoList.length === 0) return '';\r\n\r\n const completedCount = currentTodoList.filter(t => t.status === 'completed').length;\r\n const totalCount = currentTodoList.length;\r\n const percentage = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0;\r\n\r\n let context = `\\n\\n## CURRENT TODO LIST\\n`;\r\n context += `Progress: ${completedCount}/${totalCount} tasks completed (${percentage}%)\\n\\n`;\r\n\r\n currentTodoList.forEach((item) => {\r\n let statusIcon: string;\r\n if (item.status === 'completed') {\r\n statusIcon = '[x]';\r\n } else if (item.status === 'in_progress') {\r\n statusIcon = '[>]';\r\n } else {\r\n statusIcon = '[ ]';\r\n }\r\n const marker = item.status === 'in_progress' ? ' <-- IN PROGRESS' : '';\r\n context += `- ${statusIcon} ${item.content}${marker}\\n`;\r\n });\r\n\r\n const inProgress = currentTodoList.find(t => t.status === 'in_progress');\r\n const nextPending = currentTodoList.find(t => t.status === 'pending');\r\n\r\n if (inProgress) {\r\n context += `\\n**CURRENTLY WORKING ON**: ${inProgress.content}\\n`;\r\n } else if (nextPending) {\r\n context += `\\n**NEXT TASK**: ${nextPending.content}\\n`;\r\n } else if (completedCount === totalCount) {\r\n context += `\\n**ALL TASKS COMPLETE**\\n`;\r\n }\r\n\r\n context += `\\nUpdate the todo list using todo_write as you make progress.\\n`;\r\n\r\n return context;\r\n}\r\n\r\n// ============================================================================\r\n// EXPORTS\r\n// ============================================================================\r\n\r\nexport default {\r\n todoWriteTool,\r\n getCurrentTodoList,\r\n clearTodoList,\r\n hasTodoList,\r\n getTodoContextForPrompt,\r\n};\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,30 @@
1
+ const SKILL_TOOL_PRESETS = {
2
+ "read": [
3
+ "view_file",
4
+ "list_dir",
5
+ "grep_search",
6
+ "find_files",
7
+ "inspect_symbol",
8
+ "fast_context_search",
9
+ "web_search"
10
+ ],
11
+ "read-write": [
12
+ "view_file",
13
+ "write_to_file",
14
+ "edit_file",
15
+ "multi_edit_file",
16
+ "list_dir",
17
+ "grep_search",
18
+ "find_files",
19
+ "execute_command",
20
+ "inspect_symbol",
21
+ "fast_context_search",
22
+ "web_search",
23
+ "background_command",
24
+ "get_diff"
25
+ ]
26
+ };
27
+ export {
28
+ SKILL_TOOL_PRESETS
29
+ };
30
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/skill.ts"],"sourcesContent":["/**\r\n * Skill types for the Centaurus CLI skill system.\r\n * Skills are reusable agent configurations that users can invoke as slash commands.\r\n */\r\n\r\n/** Access level determines what tools the skill agent can use */\r\nexport type SkillAccessLevel = 'read' | 'read-write';\r\n\r\n/** Predefined tool sets for each access level */\r\nexport const SKILL_TOOL_PRESETS: Record<SkillAccessLevel, string[]> = {\r\n 'read': [\r\n 'view_file', 'list_dir', 'grep_search', 'find_files',\r\n 'inspect_symbol', 'fast_context_search', 'web_search',\r\n ],\r\n 'read-write': [\r\n 'view_file', 'write_to_file', 'edit_file', 'multi_edit_file',\r\n 'list_dir', 'grep_search', 'find_files', 'execute_command',\r\n 'inspect_symbol', 'fast_context_search', 'web_search',\r\n 'background_command', 'get_diff',\r\n ],\r\n};\r\n\r\n/** Full persisted skill definition */\r\nexport interface SavedSkill {\r\n name: string;\r\n prompt: string; // The instruction/system prompt for the skill agent\r\n accessLevel: SkillAccessLevel;\r\n allowedTools: string[]; // Concrete tool list (may be customised beyond presets)\r\n model?: string; // Optional model override (otherwise uses default sub-agent model)\r\n createdAt: string; // ISO date string\r\n updatedAt: string; // ISO date string\r\n}\r\n\r\n/** Lightweight listing entry */\r\nexport interface SkillMeta {\r\n name: string;\r\n promptPreview: string; // First ~80 chars of prompt\r\n accessLevel: SkillAccessLevel;\r\n model?: string;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n/** Result of a save/delete operation */\r\nexport interface SaveSkillResult {\r\n success: boolean;\r\n error?: string;\r\n savedName?: string;\r\n renamedFrom?: string;\r\n}\r\n\r\n/** Payload to trigger the skill editor UI */\r\nexport interface SkillEditorRequest {\r\n mode: 'add' | 'edit';\r\n initialSkill?: SavedSkill;\r\n}\r\n"],"mappings":"AASO,MAAM,qBAAyD;AAAA,EACpE,QAAQ;AAAA,IACN;AAAA,IAAa;AAAA,IAAY;AAAA,IAAe;AAAA,IACxC;AAAA,IAAkB;AAAA,IAAuB;AAAA,EAC3C;AAAA,EACA,cAAc;AAAA,IACZ;AAAA,IAAa;AAAA,IAAiB;AAAA,IAAa;AAAA,IAC3C;AAAA,IAAY;AAAA,IAAe;AAAA,IAAc;AAAA,IACzC;AAAA,IAAkB;AAAA,IAAuB;AAAA,IACzC;AAAA,IAAsB;AAAA,EACxB;AACF;","names":[]}