YeonGyu-Kim ee72c45552 refactor(tools/background-task): split tools.ts into focused modules under 200 LOC
- Create modules/ directory with 6 focused modules:
  - background-task.ts: task creation logic
  - background-output.ts: output retrieval logic
  - background-cancel.ts: cancellation logic
  - formatters.ts: message formatting utilities
  - message-processing.ts: message extraction utilities
  - utils.ts: shared utility functions
- Reduce tools.ts from ~798 to ~30 lines (barrel pattern)
- Add new types to types.ts for module interfaces
- Update index.ts for clean re-exports
- Follow modular code architecture (200 LOC limit)

🤖 Generated with assistance of OhMyOpenCode
2026-02-08 17:52:00 +09:00

117 lines
4.0 KiB
TypeScript

import { tool, type ToolDefinition } from "@opencode-ai/plugin"
import type { BackgroundCancelClient } from "../types"
import type { BackgroundManager } from "../../../features/background-agent"
import type { BackgroundCancelArgs } from "../types"
import { BACKGROUND_CANCEL_DESCRIPTION } from "../constants"
export function createBackgroundCancel(manager: BackgroundManager, client: BackgroundCancelClient): ToolDefinition {
return tool({
description: BACKGROUND_CANCEL_DESCRIPTION,
args: {
taskId: tool.schema.string().optional().describe("Task ID to cancel (required if all=false)"),
all: tool.schema.boolean().optional().describe("Cancel all running background tasks (default: false)"),
},
async execute(args: BackgroundCancelArgs, toolContext) {
try {
const cancelAll = args.all === true
if (!cancelAll && !args.taskId) {
return `[ERROR] Invalid arguments: Either provide a taskId or set all=true to cancel all running tasks.`
}
if (cancelAll) {
const tasks = manager.getAllDescendantTasks(toolContext.sessionID)
const cancellableTasks = tasks.filter((t: any) => t.status === "running" || t.status === "pending")
if (cancellableTasks.length === 0) {
return `No running or pending background tasks to cancel.`
}
const cancelledInfo: Array<{
id: string
description: string
status: string
sessionID?: string
}> = []
for (const task of cancellableTasks) {
const originalStatus = task.status
const cancelled = await manager.cancelTask(task.id, {
source: "background_cancel",
abortSession: originalStatus === "running",
skipNotification: true,
})
if (!cancelled) continue
cancelledInfo.push({
id: task.id,
description: task.description,
status: originalStatus === "pending" ? "pending" : "running",
sessionID: task.sessionID,
})
}
const tableRows = cancelledInfo
.map(t => `| \`${t.id}\` | ${t.description} | ${t.status} | ${t.sessionID ? `\`${t.sessionID}\`` : "(not started)"} |`)
.join("\n")
const resumableTasks = cancelledInfo.filter(t => t.sessionID)
const resumeSection = resumableTasks.length > 0
? `\n## Continue Instructions
To continue a cancelled task, use:
\`\`\`
task(session_id="<session_id>", prompt="Continue: <your follow-up>")
\`\`\`
Continuable sessions:
${resumableTasks.map(t => `- \`${t.sessionID}\` (${t.description})`).join("\n")}`
: ""
return `Cancelled ${cancelledInfo.length} background task(s):
| Task ID | Description | Status | Session ID |
|---------|-------------|--------|------------|
${tableRows}
${resumeSection}`
}
const task = manager.getTask(args.taskId!)
if (!task) {
return `[ERROR] Task not found: ${args.taskId}`
}
if (task.status !== "running" && task.status !== "pending") {
return `[ERROR] Cannot cancel task: current status is "${task.status}".
Only running or pending tasks can be cancelled.`
}
const cancelled = await manager.cancelTask(task.id, {
source: "background_cancel",
abortSession: task.status === "running",
skipNotification: true,
})
if (!cancelled) {
return `[ERROR] Failed to cancel task: ${task.id}`
}
if (task.status === "pending") {
return `Pending task cancelled successfully
Task ID: ${task.id}
Description: ${task.description}
Status: ${task.status}`
}
return `Task cancelled successfully
Task ID: ${task.id}
Description: ${task.description}
Session ID: ${task.sessionID}
Status: ${task.status}`
} catch (error) {
return `[ERROR] Error cancelling task: ${error instanceof Error ? error.message : String(error)}`
}
},
})
}