@within-7/minto 0.3.0 → 0.3.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 (84) hide show
  1. package/dist/commands/setup.js +40 -2
  2. package/dist/commands/setup.js.map +2 -2
  3. package/dist/components/SubagentProgress.js +10 -2
  4. package/dist/components/SubagentProgress.js.map +2 -2
  5. package/dist/constants/prompts.js +22 -1
  6. package/dist/constants/prompts.js.map +2 -2
  7. package/dist/entrypoints/cli.js +15 -9
  8. package/dist/entrypoints/cli.js.map +2 -2
  9. package/dist/permissions.js +121 -2
  10. package/dist/permissions.js.map +2 -2
  11. package/dist/screens/ResumeConversation.js +2 -0
  12. package/dist/screens/ResumeConversation.js.map +2 -2
  13. package/dist/services/taskStore.js +205 -0
  14. package/dist/services/taskStore.js.map +7 -0
  15. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js +40 -3
  16. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +2 -2
  17. package/dist/tools/BashTool/BashTool.js +21 -4
  18. package/dist/tools/BashTool/BashTool.js.map +2 -2
  19. package/dist/tools/BashTool/prompt.js +6 -0
  20. package/dist/tools/BashTool/prompt.js.map +2 -2
  21. package/dist/tools/FileEditTool/FileEditTool.js +24 -9
  22. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  23. package/dist/tools/FileEditTool/prompt.js +4 -1
  24. package/dist/tools/FileEditTool/prompt.js.map +2 -2
  25. package/dist/tools/FileEditTool/utils.js +10 -4
  26. package/dist/tools/FileEditTool/utils.js.map +2 -2
  27. package/dist/tools/FileReadTool/FileReadTool.js +1 -1
  28. package/dist/tools/FileReadTool/FileReadTool.js.map +1 -1
  29. package/dist/tools/FileReadTool/prompt.js +16 -1
  30. package/dist/tools/FileReadTool/prompt.js.map +2 -2
  31. package/dist/tools/FileWriteTool/FileWriteTool.js +1 -1
  32. package/dist/tools/FileWriteTool/FileWriteTool.js.map +1 -1
  33. package/dist/tools/FileWriteTool/prompt.js +8 -1
  34. package/dist/tools/FileWriteTool/prompt.js.map +2 -2
  35. package/dist/tools/GlobTool/prompt.js +12 -1
  36. package/dist/tools/GlobTool/prompt.js.map +2 -2
  37. package/dist/tools/GrepTool/GrepTool.js +333 -65
  38. package/dist/tools/GrepTool/GrepTool.js.map +2 -2
  39. package/dist/tools/GrepTool/prompt.js +15 -8
  40. package/dist/tools/GrepTool/prompt.js.map +2 -2
  41. package/dist/tools/NotebookEditTool/NotebookEditTool.js +57 -45
  42. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  43. package/dist/tools/NotebookEditTool/prompt.js +1 -1
  44. package/dist/tools/NotebookEditTool/prompt.js.map +1 -1
  45. package/dist/tools/TaskCreateTool/TaskCreateTool.js +102 -0
  46. package/dist/tools/TaskCreateTool/TaskCreateTool.js.map +7 -0
  47. package/dist/tools/TaskCreateTool/prompt.js +47 -0
  48. package/dist/tools/TaskCreateTool/prompt.js.map +7 -0
  49. package/dist/tools/TaskGetTool/TaskGetTool.js +115 -0
  50. package/dist/tools/TaskGetTool/TaskGetTool.js.map +7 -0
  51. package/dist/tools/TaskGetTool/prompt.js +28 -0
  52. package/dist/tools/TaskGetTool/prompt.js.map +7 -0
  53. package/dist/tools/TaskListTool/TaskListTool.js +102 -0
  54. package/dist/tools/TaskListTool/TaskListTool.js.map +7 -0
  55. package/dist/tools/TaskListTool/prompt.js +27 -0
  56. package/dist/tools/TaskListTool/prompt.js.map +7 -0
  57. package/dist/tools/TaskStopTool/TaskStopTool.js +150 -0
  58. package/dist/tools/TaskStopTool/TaskStopTool.js.map +7 -0
  59. package/dist/tools/TaskStopTool/prompt.js +15 -0
  60. package/dist/tools/TaskStopTool/prompt.js.map +7 -0
  61. package/dist/tools/TaskTool/TaskTool.js +41 -1
  62. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  63. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +134 -0
  64. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +7 -0
  65. package/dist/tools/TaskUpdateTool/prompt.js +81 -0
  66. package/dist/tools/TaskUpdateTool/prompt.js.map +7 -0
  67. package/dist/tools/URLFetcherTool/prompt.js +1 -1
  68. package/dist/tools/URLFetcherTool/prompt.js.map +1 -1
  69. package/dist/tools.js +12 -0
  70. package/dist/tools.js.map +2 -2
  71. package/dist/utils/config.js.map +2 -2
  72. package/dist/utils/model.js +15 -2
  73. package/dist/utils/model.js.map +2 -2
  74. package/dist/utils/ripgrep.js +53 -1
  75. package/dist/utils/ripgrep.js.map +2 -2
  76. package/dist/utils/teamConfig.js +160 -0
  77. package/dist/utils/teamConfig.js.map +3 -3
  78. package/dist/utils/terminal.js +12 -0
  79. package/dist/utils/terminal.js.map +2 -2
  80. package/dist/utils/tooling/safeRender.js +13 -14
  81. package/dist/utils/tooling/safeRender.js.map +2 -2
  82. package/dist/version.js +2 -2
  83. package/dist/version.js.map +1 -1
  84. package/package.json +20 -28
@@ -0,0 +1,28 @@
1
+ const PROMPT = `Use this tool to retrieve a task by its ID from the task list.
2
+
3
+ ## When to Use This Tool
4
+
5
+ - When you need the full description and context before starting work on a task
6
+ - To understand task dependencies (what it blocks, what blocks it)
7
+ - After being assigned a task, to get complete requirements
8
+
9
+ ## Output
10
+
11
+ Returns full task details:
12
+ - **subject**: Task title
13
+ - **description**: Detailed requirements and context
14
+ - **status**: 'pending', 'in_progress', or 'completed'
15
+ - **blocks**: Tasks waiting on this one to complete
16
+ - **blockedBy**: Tasks that must complete before this one can start
17
+
18
+ ## Tips
19
+
20
+ - After fetching a task, verify its blockedBy list is empty before beginning work.
21
+ - Use TaskList to see all tasks in summary form.
22
+ `;
23
+ const DESCRIPTION = "Get full details of a task by its ID";
24
+ export {
25
+ DESCRIPTION,
26
+ PROMPT
27
+ };
28
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/TaskGetTool/prompt.ts"],
4
+ "sourcesContent": ["export const PROMPT = `Use this tool to retrieve a task by its ID from the task list.\n\n## When to Use This Tool\n\n- When you need the full description and context before starting work on a task\n- To understand task dependencies (what it blocks, what blocks it)\n- After being assigned a task, to get complete requirements\n\n## Output\n\nReturns full task details:\n- **subject**: Task title\n- **description**: Detailed requirements and context\n- **status**: 'pending', 'in_progress', or 'completed'\n- **blocks**: Tasks waiting on this one to complete\n- **blockedBy**: Tasks that must complete before this one can start\n\n## Tips\n\n- After fetching a task, verify its blockedBy list is empty before beginning work.\n- Use TaskList to see all tasks in summary form.\n`\n\nexport const DESCRIPTION = 'Get full details of a task by its ID'\n"],
5
+ "mappings": "AAAO,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBf,MAAM,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,102 @@
1
+ import { Box, Text } from "ink";
2
+ import * as React from "react";
3
+ import { z } from "zod";
4
+ import { FallbackToolUseRejectedMessage } from "../../components/FallbackToolUseRejectedMessage.js";
5
+ import { getTaskList, getTaskStatistics } from "../../services/taskStore.js";
6
+ import { DESCRIPTION, PROMPT } from "./prompt.js";
7
+ import { getTheme } from "../../utils/theme.js";
8
+ const inputSchema = z.strictObject({});
9
+ const TaskListTool = {
10
+ name: "TaskList",
11
+ async description() {
12
+ return DESCRIPTION;
13
+ },
14
+ async prompt() {
15
+ return PROMPT;
16
+ },
17
+ inputSchema,
18
+ userFacingName() {
19
+ return "List Tasks";
20
+ },
21
+ async isEnabled() {
22
+ return true;
23
+ },
24
+ isReadOnly() {
25
+ return true;
26
+ },
27
+ isConcurrencySafe() {
28
+ return true;
29
+ },
30
+ needsPermissions() {
31
+ return false;
32
+ },
33
+ renderToolUseMessage() {
34
+ return "";
35
+ },
36
+ renderToolUseRejectedMessage() {
37
+ return /* @__PURE__ */ React.createElement(FallbackToolUseRejectedMessage, null);
38
+ },
39
+ renderToolResultMessage(output) {
40
+ if (!output || !output.tasks) {
41
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, "No tasks found"));
42
+ }
43
+ const { tasks, stats } = output;
44
+ if (tasks.length === 0) {
45
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "No tasks in list"));
46
+ }
47
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, "\xA0\xA0\u23BF \xA0"), /* @__PURE__ */ React.createElement(Text, null, stats.total, " task(s): ", stats.pending, " pending, ", stats.inProgress, " ", "in progress, ", stats.completed, " completed")), tasks.slice(0, 5).map((task) => {
48
+ const statusColor = task.status === "completed" ? getTheme().success : task.status === "in_progress" ? getTheme().warning : getTheme().secondaryText;
49
+ return /* @__PURE__ */ React.createElement(Box, { key: task.id, flexDirection: "row", paddingLeft: 5 }, /* @__PURE__ */ React.createElement(Text, { color: statusColor }, "#", task.id), /* @__PURE__ */ React.createElement(Text, null, " "), /* @__PURE__ */ React.createElement(Text, null, task.subject.length > 40 ? task.subject.slice(0, 40) + "..." : task.subject), task.blockedBy && task.blockedBy.length > 0 && /* @__PURE__ */ React.createElement(Text, { color: getTheme().error }, " ", "(blocked by: ", task.blockedBy.join(", "), ")"));
50
+ }), tasks.length > 5 && /* @__PURE__ */ React.createElement(Box, { paddingLeft: 5 }, /* @__PURE__ */ React.createElement(Text, { color: getTheme().secondaryText }, "... and ", tasks.length - 5, " more")));
51
+ },
52
+ renderResultForAssistant(result) {
53
+ const { tasks, stats } = result;
54
+ if (tasks.length === 0) {
55
+ return "No tasks in the task list.";
56
+ }
57
+ const lines = [
58
+ `Task List (${stats.total} total: ${stats.pending} pending, ${stats.inProgress} in progress, ${stats.completed} completed):`,
59
+ ""
60
+ ];
61
+ for (const task of tasks) {
62
+ let line = `#${task.id} [${task.status}] ${task.subject}`;
63
+ if (task.owner) {
64
+ line += ` (owner: ${task.owner})`;
65
+ }
66
+ if (task.blockedBy && task.blockedBy.length > 0) {
67
+ line += ` (blocked by: ${task.blockedBy.join(", ")})`;
68
+ }
69
+ lines.push(line);
70
+ }
71
+ return lines.join("\n");
72
+ },
73
+ async *call() {
74
+ try {
75
+ const tasks = getTaskList();
76
+ const stats = getTaskStatistics();
77
+ const result = {
78
+ tasks,
79
+ stats
80
+ };
81
+ yield {
82
+ type: "result",
83
+ data: result,
84
+ resultForAssistant: this.renderResultForAssistant(result)
85
+ };
86
+ } catch (error) {
87
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
88
+ yield {
89
+ type: "result",
90
+ data: {
91
+ tasks: [],
92
+ stats: { total: 0, pending: 0, inProgress: 0, completed: 0 }
93
+ },
94
+ resultForAssistant: `Error listing tasks: ${errorMessage}`
95
+ };
96
+ }
97
+ }
98
+ };
99
+ export {
100
+ TaskListTool
101
+ };
102
+ //# sourceMappingURL=TaskListTool.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/TaskListTool/TaskListTool.tsx"],
4
+ "sourcesContent": ["import { Box, Text } from 'ink'\nimport * as React from 'react'\nimport { z } from 'zod'\nimport { FallbackToolUseRejectedMessage } from '@components/FallbackToolUseRejectedMessage'\nimport { Tool } from '@tool'\nimport { getTaskList, getTaskStatistics } from '@services/taskStore'\nimport { DESCRIPTION, PROMPT } from './prompt'\nimport { getTheme } from '@utils/theme'\n\nconst inputSchema = z.strictObject({})\n\ntype TaskSummary = {\n id: string\n subject: string\n status: 'pending' | 'in_progress' | 'completed'\n owner?: string\n blockedBy?: string[]\n}\n\ntype TaskListOutput = {\n tasks: TaskSummary[]\n stats: {\n total: number\n pending: number\n inProgress: number\n completed: number\n }\n}\n\nexport const TaskListTool = {\n name: 'TaskList',\n async description() {\n return DESCRIPTION\n },\n async prompt() {\n return PROMPT\n },\n inputSchema,\n userFacingName() {\n return 'List Tasks'\n },\n async isEnabled() {\n return true\n },\n isReadOnly() {\n return true\n },\n isConcurrencySafe() {\n return true\n },\n needsPermissions() {\n return false\n },\n renderToolUseMessage() {\n return ''\n },\n renderToolUseRejectedMessage() {\n return <FallbackToolUseRejectedMessage />\n },\n renderToolResultMessage(output: TaskListOutput) {\n if (!output || !output.tasks) {\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>No tasks found</Text>\n </Box>\n )\n }\n\n const { tasks, stats } = output\n\n if (tasks.length === 0) {\n return (\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text color={getTheme().secondaryText}>No tasks in list</Text>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text>&nbsp;&nbsp;\u23BF &nbsp;</Text>\n <Text>\n {stats.total} task(s): {stats.pending} pending, {stats.inProgress}{' '}\n in progress, {stats.completed} completed\n </Text>\n </Box>\n {tasks.slice(0, 5).map(task => {\n const statusColor =\n task.status === 'completed'\n ? getTheme().success\n : task.status === 'in_progress'\n ? getTheme().warning\n : getTheme().secondaryText\n\n return (\n <Box key={task.id} flexDirection=\"row\" paddingLeft={5}>\n <Text color={statusColor}>#{task.id}</Text>\n <Text> </Text>\n <Text>\n {task.subject.length > 40\n ? task.subject.slice(0, 40) + '...'\n : task.subject}\n </Text>\n {task.blockedBy && task.blockedBy.length > 0 && (\n <Text color={getTheme().error}>\n {' '}\n (blocked by: {task.blockedBy.join(', ')})\n </Text>\n )}\n </Box>\n )\n })}\n {tasks.length > 5 && (\n <Box paddingLeft={5}>\n <Text color={getTheme().secondaryText}>\n ... and {tasks.length - 5} more\n </Text>\n </Box>\n )}\n </Box>\n )\n },\n renderResultForAssistant(result: TaskListOutput) {\n const { tasks, stats } = result\n\n if (tasks.length === 0) {\n return 'No tasks in the task list.'\n }\n\n const lines: string[] = [\n `Task List (${stats.total} total: ${stats.pending} pending, ${stats.inProgress} in progress, ${stats.completed} completed):`,\n '',\n ]\n\n for (const task of tasks) {\n let line = `#${task.id} [${task.status}] ${task.subject}`\n if (task.owner) {\n line += ` (owner: ${task.owner})`\n }\n if (task.blockedBy && task.blockedBy.length > 0) {\n line += ` (blocked by: ${task.blockedBy.join(', ')})`\n }\n lines.push(line)\n }\n\n return lines.join('\\n')\n },\n async *call() {\n try {\n const tasks = getTaskList()\n const stats = getTaskStatistics()\n\n const result: TaskListOutput = {\n tasks,\n stats,\n }\n\n yield {\n type: 'result',\n data: result,\n resultForAssistant: this.renderResultForAssistant(result),\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error occurred'\n yield {\n type: 'result',\n data: {\n tasks: [],\n stats: { total: 0, pending: 0, inProgress: 0, completed: 0 },\n },\n resultForAssistant: `Error listing tasks: ${errorMessage}`,\n }\n }\n },\n} satisfies Tool<typeof inputSchema, TaskListOutput>\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,27 @@
1
+ const PROMPT = `Use this tool to list all tasks in the task list.
2
+
3
+ ## When to Use This Tool
4
+
5
+ - To see what tasks are available to work on (status: 'pending', no owner, not blocked)
6
+ - To check overall progress on the project
7
+ - To find tasks that are blocked and need dependencies resolved
8
+ - After completing a task, to check for newly unblocked work or claim the next available task
9
+ - **Prefer working on tasks in ID order** (lowest ID first) when multiple tasks are available, as earlier tasks often set up context for later ones
10
+
11
+ ## Output
12
+
13
+ Returns a summary of each task:
14
+ - **id**: Task identifier (use with TaskGet, TaskUpdate)
15
+ - **subject**: Brief description of the task
16
+ - **status**: 'pending', 'in_progress', or 'completed'
17
+ - **owner**: Agent ID if assigned, empty if available
18
+ - **blockedBy**: List of open task IDs that must be resolved first (tasks with blockedBy cannot be claimed until dependencies resolve)
19
+
20
+ Use TaskGet with a specific task ID to view full details including description and comments.
21
+ `;
22
+ const DESCRIPTION = "List all tasks in the task list";
23
+ export {
24
+ DESCRIPTION,
25
+ PROMPT
26
+ };
27
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/TaskListTool/prompt.ts"],
4
+ "sourcesContent": ["export const PROMPT = `Use this tool to list all tasks in the task list.\n\n## When to Use This Tool\n\n- To see what tasks are available to work on (status: 'pending', no owner, not blocked)\n- To check overall progress on the project\n- To find tasks that are blocked and need dependencies resolved\n- After completing a task, to check for newly unblocked work or claim the next available task\n- **Prefer working on tasks in ID order** (lowest ID first) when multiple tasks are available, as earlier tasks often set up context for later ones\n\n## Output\n\nReturns a summary of each task:\n- **id**: Task identifier (use with TaskGet, TaskUpdate)\n- **subject**: Brief description of the task\n- **status**: 'pending', 'in_progress', or 'completed'\n- **owner**: Agent ID if assigned, empty if available\n- **blockedBy**: List of open task IDs that must be resolved first (tasks with blockedBy cannot be claimed until dependencies resolve)\n\nUse TaskGet with a specific task ID to view full details including description and comments.\n`\n\nexport const DESCRIPTION = 'List all tasks in the task list'\n"],
5
+ "mappings": "AAAO,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBf,MAAM,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,150 @@
1
+ import { Box, Text } from "ink";
2
+ import React from "react";
3
+ import { z } from "zod";
4
+ import { DESCRIPTION, PROMPT, TOOL_NAME } from "./prompt.js";
5
+ import { BackgroundShellManager } from "../../utils/BackgroundShellManager.js";
6
+ import {
7
+ getAgentTranscript,
8
+ interruptAgentTranscript
9
+ } from "../../utils/agentTranscripts.js";
10
+ import { SEMANTIC_COLORS } from "../../constants/colors.js";
11
+ const inputSchema = z.strictObject({
12
+ task_id: z.string().describe("The ID of the background task to stop"),
13
+ shell_id: z.string().optional().describe("Deprecated: use task_id instead")
14
+ });
15
+ const TaskStopTool = {
16
+ name: TOOL_NAME,
17
+ async description() {
18
+ return DESCRIPTION;
19
+ },
20
+ userFacingName() {
21
+ return "Task Stop";
22
+ },
23
+ inputSchema,
24
+ isReadOnly() {
25
+ return false;
26
+ },
27
+ isConcurrencySafe() {
28
+ return true;
29
+ },
30
+ async isEnabled() {
31
+ return true;
32
+ },
33
+ needsPermissions() {
34
+ return false;
35
+ },
36
+ async prompt() {
37
+ return PROMPT;
38
+ },
39
+ renderToolUseMessage(input) {
40
+ const taskId = input.task_id || input.shell_id || "";
41
+ return `task_id: "${taskId}"`;
42
+ },
43
+ renderToolUseRejectedMessage() {
44
+ return /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, "Task stop request rejected"));
45
+ },
46
+ renderToolResultMessage(output) {
47
+ if (!output) {
48
+ return /* @__PURE__ */ React.createElement(Box, { paddingLeft: 2 }, /* @__PURE__ */ React.createElement(Text, null, "Task stop completed"));
49
+ }
50
+ const statusColor = output.success ? "green" : "red";
51
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", paddingLeft: 2 }, /* @__PURE__ */ React.createElement(Box, { flexDirection: "row" }, /* @__PURE__ */ React.createElement(Text, null, output.task_type === "agent" ? "Agent" : "Task", " "), /* @__PURE__ */ React.createElement(Text, { bold: true }, output.task_id), /* @__PURE__ */ React.createElement(Text, null, ": "), /* @__PURE__ */ React.createElement(Text, { color: statusColor }, output.success ? "stopped" : "failed")), !output.success && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: SEMANTIC_COLORS.dim }, output.message)));
52
+ },
53
+ renderResultForAssistant(output) {
54
+ return output.message;
55
+ },
56
+ async *call(input, _context) {
57
+ const taskId = input.task_id || input.shell_id;
58
+ if (!taskId) {
59
+ const output2 = {
60
+ success: false,
61
+ message: "Error: No task_id provided",
62
+ task_id: "",
63
+ task_type: "unknown"
64
+ };
65
+ yield {
66
+ type: "result",
67
+ data: output2,
68
+ resultForAssistant: this.renderResultForAssistant(output2)
69
+ };
70
+ return;
71
+ }
72
+ const transcript = getAgentTranscript(taskId);
73
+ if (transcript) {
74
+ if (transcript.status !== "running") {
75
+ const output3 = {
76
+ success: false,
77
+ message: `Error: Agent '${taskId}' is already ${transcript.status}`,
78
+ task_id: taskId,
79
+ task_type: "agent"
80
+ };
81
+ yield {
82
+ type: "result",
83
+ data: output3,
84
+ resultForAssistant: this.renderResultForAssistant(output3)
85
+ };
86
+ return;
87
+ }
88
+ const updated = interruptAgentTranscript(taskId);
89
+ const success = updated !== null && updated.status === "interrupted";
90
+ const output2 = {
91
+ success,
92
+ message: success ? `Successfully stopped agent '${taskId}'` : `Failed to stop agent '${taskId}'`,
93
+ task_id: taskId,
94
+ task_type: "agent"
95
+ };
96
+ yield {
97
+ type: "result",
98
+ data: output2,
99
+ resultForAssistant: this.renderResultForAssistant(output2)
100
+ };
101
+ return;
102
+ }
103
+ const manager = BackgroundShellManager.getInstance();
104
+ const shell = manager.get(taskId);
105
+ if (!shell) {
106
+ const output2 = {
107
+ success: false,
108
+ message: `Error: No task found with ID '${taskId}'. This could be a background shell or agent ID.`,
109
+ task_id: taskId,
110
+ task_type: "unknown"
111
+ };
112
+ yield {
113
+ type: "result",
114
+ data: output2,
115
+ resultForAssistant: this.renderResultForAssistant(output2)
116
+ };
117
+ return;
118
+ }
119
+ if (shell.status !== "running") {
120
+ const output2 = {
121
+ success: false,
122
+ message: `Error: Task '${taskId}' is already ${shell.status}`,
123
+ task_id: taskId,
124
+ task_type: "shell"
125
+ };
126
+ yield {
127
+ type: "result",
128
+ data: output2,
129
+ resultForAssistant: this.renderResultForAssistant(output2)
130
+ };
131
+ return;
132
+ }
133
+ const killed = manager.kill(taskId);
134
+ const output = {
135
+ success: killed,
136
+ message: killed ? `Successfully stopped background task '${taskId}'` : `Failed to stop background task '${taskId}'`,
137
+ task_id: taskId,
138
+ task_type: "shell"
139
+ };
140
+ yield {
141
+ type: "result",
142
+ data: output,
143
+ resultForAssistant: this.renderResultForAssistant(output)
144
+ };
145
+ }
146
+ };
147
+ export {
148
+ TaskStopTool
149
+ };
150
+ //# sourceMappingURL=TaskStopTool.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/TaskStopTool/TaskStopTool.tsx"],
4
+ "sourcesContent": ["/**\n * Task Stop Tool\n *\n * Stops a running background task by its ID.\n * Supports both background shell commands and agent tasks.\n */\n\nimport { Box, Text } from 'ink'\nimport React from 'react'\nimport { z } from 'zod'\nimport { Tool } from '@tool'\nimport { DESCRIPTION, PROMPT, TOOL_NAME } from './prompt'\nimport { BackgroundShellManager } from '@utils/BackgroundShellManager'\nimport {\n getAgentTranscript,\n interruptAgentTranscript,\n} from '@utils/agentTranscripts'\nimport { SEMANTIC_COLORS } from '@constants/colors'\n\nconst inputSchema = z.strictObject({\n task_id: z.string().describe('The ID of the background task to stop'),\n shell_id: z.string().optional().describe('Deprecated: use task_id instead'),\n})\n\ntype Output = {\n success: boolean\n message: string\n task_id: string\n task_type: 'shell' | 'agent' | 'unknown'\n}\n\nexport const TaskStopTool = {\n name: TOOL_NAME,\n async description() {\n return DESCRIPTION\n },\n userFacingName() {\n return 'Task Stop'\n },\n inputSchema,\n isReadOnly() {\n return false\n },\n isConcurrencySafe() {\n return true\n },\n async isEnabled() {\n return true\n },\n needsPermissions() {\n return false // Stopping tasks doesn't require user permission\n },\n async prompt() {\n return PROMPT\n },\n renderToolUseMessage(input: z.infer<typeof inputSchema>) {\n const taskId = input.task_id || input.shell_id || ''\n return `task_id: \"${taskId}\"`\n },\n renderToolUseRejectedMessage() {\n return (\n <Box paddingLeft={2}>\n <Text color={SEMANTIC_COLORS.dim}>Task stop request rejected</Text>\n </Box>\n )\n },\n renderToolResultMessage(output: Output) {\n if (!output) {\n return (\n <Box paddingLeft={2}>\n <Text>Task stop completed</Text>\n </Box>\n )\n }\n\n const statusColor = output.success ? 'green' : 'red'\n\n return (\n <Box flexDirection=\"column\" paddingLeft={2}>\n <Box flexDirection=\"row\">\n <Text>{output.task_type === 'agent' ? 'Agent' : 'Task'} </Text>\n <Text bold>{output.task_id}</Text>\n <Text>: </Text>\n <Text color={statusColor}>\n {output.success ? 'stopped' : 'failed'}\n </Text>\n </Box>\n {!output.success && (\n <Box marginTop={1}>\n <Text color={SEMANTIC_COLORS.dim}>{output.message}</Text>\n </Box>\n )}\n </Box>\n )\n },\n renderResultForAssistant(output: Output) {\n return output.message\n },\n async *call(input: z.infer<typeof inputSchema>, _context: any) {\n // Support deprecated shell_id parameter\n const taskId = input.task_id || input.shell_id\n\n if (!taskId) {\n const output: Output = {\n success: false,\n message: 'Error: No task_id provided',\n task_id: '',\n task_type: 'unknown',\n }\n yield {\n type: 'result',\n data: output,\n resultForAssistant: this.renderResultForAssistant(output),\n }\n return\n }\n\n // First, check if this is an agent transcript\n const transcript = getAgentTranscript(taskId)\n if (transcript) {\n // Handle agent transcript\n if (transcript.status !== 'running') {\n const output: Output = {\n success: false,\n message: `Error: Agent '${taskId}' is already ${transcript.status}`,\n task_id: taskId,\n task_type: 'agent',\n }\n yield {\n type: 'result',\n data: output,\n resultForAssistant: this.renderResultForAssistant(output),\n }\n return\n }\n\n // Interrupt the agent\n const updated = interruptAgentTranscript(taskId)\n const success = updated !== null && updated.status === 'interrupted'\n\n const output: Output = {\n success,\n message: success\n ? `Successfully stopped agent '${taskId}'`\n : `Failed to stop agent '${taskId}'`,\n task_id: taskId,\n task_type: 'agent',\n }\n\n yield {\n type: 'result',\n data: output,\n resultForAssistant: this.renderResultForAssistant(output),\n }\n return\n }\n\n // Fall back to background shell\n const manager = BackgroundShellManager.getInstance()\n const shell = manager.get(taskId)\n\n if (!shell) {\n const output: Output = {\n success: false,\n message: `Error: No task found with ID '${taskId}'. This could be a background shell or agent ID.`,\n task_id: taskId,\n task_type: 'unknown',\n }\n yield {\n type: 'result',\n data: output,\n resultForAssistant: this.renderResultForAssistant(output),\n }\n return\n }\n\n if (shell.status !== 'running') {\n const output: Output = {\n success: false,\n message: `Error: Task '${taskId}' is already ${shell.status}`,\n task_id: taskId,\n task_type: 'shell',\n }\n yield {\n type: 'result',\n data: output,\n resultForAssistant: this.renderResultForAssistant(output),\n }\n return\n }\n\n // Kill the shell\n const killed = manager.kill(taskId)\n\n const output: Output = {\n success: killed,\n message: killed\n ? `Successfully stopped background task '${taskId}'`\n : `Failed to stop background task '${taskId}'`,\n task_id: taskId,\n task_type: 'shell',\n }\n\n yield {\n type: 'result',\n data: output,\n resultForAssistant: this.renderResultForAssistant(output),\n }\n },\n} satisfies Tool<typeof inputSchema, Output>\n"],
5
+ "mappings": "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",
6
+ "names": ["output"]
7
+ }
@@ -0,0 +1,15 @@
1
+ const TOOL_NAME = "TaskStop";
2
+ const DESCRIPTION = `Stops a running background task by its ID`;
3
+ const PROMPT = `- Stops a running background task by its ID
4
+ - Takes a task_id parameter identifying the task to stop
5
+ - Returns a success or failure status
6
+ - Use this tool when you need to terminate a long-running task
7
+ - Task IDs can be obtained from BashTool when run_in_background is true, or from Task tool for agent tasks
8
+ - Can only stop tasks that are currently running (not already completed or stopped)
9
+ - Works with both background shells and agent tasks`;
10
+ export {
11
+ DESCRIPTION,
12
+ PROMPT,
13
+ TOOL_NAME
14
+ };
15
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/tools/TaskStopTool/prompt.ts"],
4
+ "sourcesContent": ["export const TOOL_NAME = 'TaskStop'\n\nexport const DESCRIPTION = `Stops a running background task by its ID`\n\nexport const PROMPT = `- Stops a running background task by its ID\n- Takes a task_id parameter identifying the task to stop\n- Returns a success or failure status\n- Use this tool when you need to terminate a long-running task\n- Task IDs can be obtained from BashTool when run_in_background is true, or from Task tool for agent tasks\n- Can only stop tasks that are currently running (not already completed or stopped)\n- Works with both background shells and agent tasks`\n"],
5
+ "mappings": "AAAO,MAAM,YAAY;AAElB,MAAM,cAAc;AAEpB,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -55,11 +55,17 @@ const inputSchema = z.object({
55
55
  model_name: z.string().optional().describe(
56
56
  "Optional: Specific model name to use for this task. If not provided, uses the default task model pointer."
57
57
  ),
58
+ model: z.enum(["sonnet", "opus", "haiku"]).optional().describe(
59
+ "Optional model hint for this agent. Maps to configured model pointers: sonnet\u2192main, opus\u2192reasoning, haiku\u2192quick. If not specified, uses the task model pointer. Prefer haiku for quick, straightforward tasks."
60
+ ),
58
61
  subagent_type: z.string().optional().describe(
59
62
  'The specialized agent type to use. MUST be an exact name from the available agents list in the tool description. Defaults to "general-purpose" if not specified.'
60
63
  ),
61
64
  resume: z.string().optional().describe(
62
65
  "Optional agent ID to resume from. If provided, the agent will continue from the previous execution transcript."
66
+ ),
67
+ max_turns: z.number().int().positive().optional().describe(
68
+ "Maximum number of agentic turns (API round-trips) before stopping. Used internally for warmup."
63
69
  )
64
70
  // run_in_background parameter removed - concurrent execution is automatic
65
71
  });
@@ -74,7 +80,15 @@ const TaskTool = {
74
80
  return `Launch a specialized agent to handle tasks autonomously. You MUST use an exact agent type name from this list: ${typesList}. Default to "general-purpose" if unsure.`;
75
81
  },
76
82
  inputSchema,
77
- async *call({ description, prompt, model_name, subagent_type, resume }, {
83
+ async *call({
84
+ description,
85
+ prompt,
86
+ model_name,
87
+ model,
88
+ subagent_type,
89
+ resume,
90
+ max_turns
91
+ }, {
78
92
  abortController,
79
93
  options: { safeMode = false, forkNumber, messageLogName, verbose },
80
94
  readFileTimestamps,
@@ -147,6 +161,22 @@ ${prompt}`;
147
161
  }
148
162
  toolFilter = agentConfig.tools;
149
163
  }
164
+ if (model) {
165
+ const modelPointerMap = {
166
+ sonnet: "main",
167
+ // Use main model for standard tasks
168
+ opus: "reasoning",
169
+ // Use reasoning model for complex tasks
170
+ haiku: "quick"
171
+ // Use quick model for fast tasks
172
+ };
173
+ const pointerType = modelPointerMap[model] || "task";
174
+ const modelManager = getModelManager();
175
+ const resolvedModelName = modelManager.getModelName(pointerType);
176
+ if (resolvedModelName) {
177
+ effectiveModel = resolvedModelName;
178
+ }
179
+ }
150
180
  const messages = resumedTranscript ? [...resumedTranscript.messages] : [createUserMessage(effectivePrompt)];
151
181
  let tools = await getTaskTools(safeMode);
152
182
  if (toolFilter) {
@@ -249,6 +279,7 @@ IMPORTANT: You are currently running as ${modelToUse}. You do not need to consul
249
279
  queryOptions["temperature"] = temperature;
250
280
  }
251
281
  pushAgentContext(agentId);
282
+ let turnCount = 0;
252
283
  try {
253
284
  for await (const message of query(
254
285
  messages,
@@ -275,6 +306,15 @@ IMPORTANT: You are currently running as ${modelToUse}. You do not need to consul
275
306
  if (message.type !== "assistant") {
276
307
  continue;
277
308
  }
309
+ turnCount++;
310
+ if (max_turns && turnCount >= max_turns) {
311
+ debugLogger.info("TASK_AGENT_MAX_TURNS_REACHED", {
312
+ agentId,
313
+ turnCount,
314
+ max_turns
315
+ });
316
+ break;
317
+ }
278
318
  if (message.message.usage) {
279
319
  updateAgentTranscript(agentId, {
280
320
  tokenUsage: {