(config: ToolConfiguration)
| 77 | } |
| 78 | |
| 79 | export const createTaskTerminateTool: ToolFactory = (config: ToolConfiguration) => { |
| 80 | return tool({ |
| 81 | description: TOOL_DEFINITIONS.task_terminate.description, |
| 82 | inputSchema: TOOL_DEFINITIONS.task_terminate.schema, |
| 83 | execute: async (args): Promise<unknown> => { |
| 84 | const workspaceId = requireWorkspaceId(config, "task_terminate"); |
| 85 | const taskService = requireTaskService(config, "task_terminate"); |
| 86 | |
| 87 | const uniqueTaskIds = dedupeStrings(args.task_ids); |
| 88 | |
| 89 | const results = await Promise.all( |
| 90 | uniqueTaskIds.map(async (taskId) => { |
| 91 | if (isWorkflowRunTaskId(taskId)) { |
| 92 | return await interruptWorkflowRun(config, workspaceId, taskId); |
| 93 | } |
| 94 | |
| 95 | if (isWorkspaceTurnTaskId(taskId)) { |
| 96 | const interruptResult = await taskService.interruptWorkspaceTurn(workspaceId, taskId); |
| 97 | if (!interruptResult.success) { |
| 98 | const msg = interruptResult.error; |
| 99 | if (/not found/i.test(msg) || /scope/i.test(msg)) { |
| 100 | return { status: "invalid_scope" as const, taskId }; |
| 101 | } |
| 102 | return { status: "error" as const, taskId, error: msg }; |
| 103 | } |
| 104 | return { |
| 105 | status: "interrupted" as const, |
| 106 | taskId, |
| 107 | note: "Workspace turn interrupted. The full workspace is preserved for inspection and future prompts.", |
| 108 | }; |
| 109 | } |
| 110 | |
| 111 | const maybeProcessId = fromBashTaskId(taskId); |
| 112 | if (taskId.startsWith("bash:") && !maybeProcessId) { |
| 113 | return { status: "error" as const, taskId, error: "Invalid bash taskId." }; |
| 114 | } |
| 115 | |
| 116 | if (maybeProcessId) { |
| 117 | if (!config.backgroundProcessManager) { |
| 118 | return { |
| 119 | status: "error" as const, |
| 120 | taskId, |
| 121 | error: "Background process manager not available", |
| 122 | }; |
| 123 | } |
| 124 | |
| 125 | const proc = await config.backgroundProcessManager.getProcess(maybeProcessId); |
| 126 | if (!proc) { |
| 127 | return { status: "not_found" as const, taskId }; |
| 128 | } |
| 129 | |
| 130 | const inScope = |
| 131 | proc.workspaceId === workspaceId || |
| 132 | (await taskService.isDescendantAgentTask(workspaceId, proc.workspaceId)); |
| 133 | if (!inScope) { |
| 134 | return { status: "invalid_scope" as const, taskId }; |
| 135 | } |
| 136 |
no test coverage detected