@finityno/claude-code-acp 0.13.7 → 0.15.0

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.
@@ -0,0 +1,256 @@
1
+ import { z } from "zod";
2
+ import { TaskManager } from "./task-manager.js";
3
+ /**
4
+ * Register MCP tools for task management
5
+ */
6
+ export function registerTaskMcpTools(server, options) {
7
+ const { tracker, taskManager, sessionId } = options;
8
+ // List all tasks
9
+ server.registerTool("ListTasks", {
10
+ title: "List Tasks",
11
+ description: `List all tracked tasks/subagents across sessions.
12
+ Use this to see running, completed, failed, or cancelled tasks.
13
+ Can filter by status, session, or background execution.`,
14
+ inputSchema: {
15
+ status: z
16
+ .array(z.enum(["pending", "running", "completed", "failed", "cancelled", "stopped"]))
17
+ .optional()
18
+ .describe("Filter by task status"),
19
+ sessionId: z.string().optional().describe("Filter by session ID"),
20
+ backgroundOnly: z.boolean().optional().describe("Only show background tasks"),
21
+ subagentType: z.string().optional().describe("Filter by subagent type"),
22
+ limit: z.number().optional().default(20).describe("Maximum number of tasks to return"),
23
+ },
24
+ annotations: {
25
+ title: "List tasks",
26
+ readOnlyHint: true,
27
+ },
28
+ }, async (input) => {
29
+ const manager = taskManager ?? createTempManager(tracker);
30
+ const tasks = manager.getAllTasks({
31
+ status: input.status,
32
+ sessionId: input.sessionId,
33
+ runInBackground: input.backgroundOnly,
34
+ subagentType: input.subagentType,
35
+ });
36
+ const limited = tasks.slice(0, input.limit);
37
+ return {
38
+ content: [{
39
+ type: "text",
40
+ text: JSON.stringify({
41
+ total: tasks.length,
42
+ returned: limited.length,
43
+ tasks: limited.map((t) => ({
44
+ id: t.id,
45
+ type: t.subagentType,
46
+ description: t.description,
47
+ status: t.status,
48
+ runInBackground: t.runInBackground,
49
+ createdAt: new Date(t.createdAt).toISOString(),
50
+ durationMs: t.completedAt && t.startedAt ? t.completedAt - t.startedAt : undefined,
51
+ agentId: t.agentId,
52
+ canResume: !!(t.agentId && ["completed", "failed", "stopped"].includes(t.status)),
53
+ summary: t.summary,
54
+ })),
55
+ }, null, 2),
56
+ }],
57
+ };
58
+ });
59
+ // Get task status
60
+ server.registerTool("GetTaskStatus", {
61
+ title: "Get Task Status",
62
+ description: "Get detailed status and metadata for a specific task.",
63
+ inputSchema: {
64
+ taskId: z.string().describe("The task ID to get status for"),
65
+ },
66
+ annotations: {
67
+ title: "Get task status",
68
+ readOnlyHint: true,
69
+ },
70
+ }, async (input) => {
71
+ const task = tracker.getSubagent(input.taskId);
72
+ if (!task) {
73
+ return {
74
+ isError: true,
75
+ content: [{ type: "text", text: `Task not found: ${input.taskId}` }],
76
+ };
77
+ }
78
+ return {
79
+ content: [{
80
+ type: "text",
81
+ text: JSON.stringify({
82
+ id: task.id,
83
+ type: task.subagentType,
84
+ description: task.description,
85
+ prompt: task.prompt,
86
+ status: task.status,
87
+ model: task.model,
88
+ runInBackground: task.runInBackground,
89
+ parentSessionId: task.parentSessionId,
90
+ parentToolUseId: task.parentToolUseId,
91
+ createdAt: new Date(task.createdAt).toISOString(),
92
+ startedAt: task.startedAt ? new Date(task.startedAt).toISOString() : undefined,
93
+ completedAt: task.completedAt ? new Date(task.completedAt).toISOString() : undefined,
94
+ durationMs: task.completedAt && task.startedAt ? task.completedAt - task.startedAt : undefined,
95
+ agentId: task.agentId,
96
+ agentName: task.agentName,
97
+ teamName: task.teamName,
98
+ permissionMode: task.permissionMode,
99
+ outputFile: task.outputFile,
100
+ summary: task.summary,
101
+ result: task.result,
102
+ error: task.error,
103
+ isResumed: task.isResumed,
104
+ originalTaskId: task.originalTaskId,
105
+ canResume: !!(task.agentId && ["completed", "failed", "stopped"].includes(task.status)),
106
+ }, null, 2),
107
+ }],
108
+ };
109
+ });
110
+ // Get task output
111
+ server.registerTool("GetTaskOutput", {
112
+ title: "Get Task Output",
113
+ description: "Read output file content for a background task.",
114
+ inputSchema: {
115
+ taskId: z.string().describe("The task ID to get output for"),
116
+ tail: z.number().optional().describe("Only return last N lines"),
117
+ },
118
+ annotations: {
119
+ title: "Get task output",
120
+ readOnlyHint: true,
121
+ },
122
+ }, async (input) => {
123
+ const task = tracker.getSubagent(input.taskId);
124
+ if (!task) {
125
+ return {
126
+ isError: true,
127
+ content: [{ type: "text", text: `Task not found: ${input.taskId}` }],
128
+ };
129
+ }
130
+ if (!task.outputFile) {
131
+ return {
132
+ isError: true,
133
+ content: [{ type: "text", text: `Task ${input.taskId} has no output file` }],
134
+ };
135
+ }
136
+ const manager = taskManager ?? createTempManager(tracker);
137
+ const output = input.tail
138
+ ? await manager.getTaskOutputTail(input.taskId, input.tail)
139
+ : await manager.getTaskOutput(input.taskId);
140
+ if (output === null) {
141
+ return {
142
+ isError: true,
143
+ content: [{ type: "text", text: `Output file not found: ${task.outputFile}` }],
144
+ };
145
+ }
146
+ return { content: [{ type: "text", text: output }] };
147
+ });
148
+ // Cancel task
149
+ server.registerTool("CancelTask", {
150
+ title: "Cancel Task",
151
+ description: "Cancel a running task/subagent.",
152
+ inputSchema: {
153
+ taskId: z.string().describe("The task ID to cancel"),
154
+ },
155
+ annotations: {
156
+ title: "Cancel task",
157
+ destructiveHint: true,
158
+ },
159
+ }, async (input) => {
160
+ const task = tracker.getSubagent(input.taskId);
161
+ if (!task) {
162
+ return {
163
+ isError: true,
164
+ content: [{ type: "text", text: `Task not found: ${input.taskId}` }],
165
+ };
166
+ }
167
+ if (task.status !== "running") {
168
+ return {
169
+ isError: true,
170
+ content: [{ type: "text", text: `Task not running: ${task.status}` }],
171
+ };
172
+ }
173
+ await tracker.cancelSubagent(input.taskId);
174
+ return { content: [{ type: "text", text: `Task ${input.taskId} cancelled` }] };
175
+ });
176
+ // List resumable tasks
177
+ server.registerTool("ListResumableTasks", {
178
+ title: "List Resumable Tasks",
179
+ description: "List tasks that can be resumed via Task tool's resume parameter.",
180
+ inputSchema: {
181
+ limit: z.number().optional().default(10).describe("Maximum number of tasks to return"),
182
+ },
183
+ annotations: {
184
+ title: "List resumable tasks",
185
+ readOnlyHint: true,
186
+ },
187
+ }, async (input) => {
188
+ const tasks = tracker.getResumableTasks().slice(0, input.limit);
189
+ return {
190
+ content: [{
191
+ type: "text",
192
+ text: JSON.stringify({
193
+ count: tasks.length,
194
+ tasks: tasks.map((t) => ({
195
+ id: t.id,
196
+ agentId: t.agentId,
197
+ type: t.subagentType,
198
+ description: t.description,
199
+ status: t.status,
200
+ completedAt: t.completedAt ? new Date(t.completedAt).toISOString() : undefined,
201
+ summary: t.summary,
202
+ error: t.error,
203
+ })),
204
+ }, null, 2),
205
+ }],
206
+ };
207
+ });
208
+ // Get task stats
209
+ server.registerTool("GetTaskStats", {
210
+ title: "Get Task Statistics",
211
+ description: "Get statistics about all tracked tasks.",
212
+ inputSchema: {},
213
+ annotations: {
214
+ title: "Get task statistics",
215
+ readOnlyHint: true,
216
+ },
217
+ }, async () => {
218
+ const stats = tracker.getStats();
219
+ return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
220
+ });
221
+ // Get running tasks
222
+ server.registerTool("GetRunningTasks", {
223
+ title: "Get Running Tasks",
224
+ description: "Get all currently running tasks.",
225
+ inputSchema: {
226
+ allSessions: z.boolean().optional().default(false).describe("Include all sessions"),
227
+ },
228
+ annotations: {
229
+ title: "Get running tasks",
230
+ readOnlyHint: true,
231
+ },
232
+ }, async (input) => {
233
+ const tasks = input.allSessions
234
+ ? tracker.getRunningSubagents()
235
+ : tracker.getRunningSubagentsForSession(sessionId);
236
+ return {
237
+ content: [{
238
+ type: "text",
239
+ text: JSON.stringify({
240
+ count: tasks.length,
241
+ tasks: tasks.map((t) => ({
242
+ id: t.id,
243
+ type: t.subagentType,
244
+ description: t.description,
245
+ runInBackground: t.runInBackground,
246
+ startedAt: t.startedAt ? new Date(t.startedAt).toISOString() : undefined,
247
+ elapsedMs: t.startedAt ? Date.now() - t.startedAt : undefined,
248
+ })),
249
+ }, null, 2),
250
+ }],
251
+ };
252
+ });
253
+ }
254
+ function createTempManager(tracker) {
255
+ return new TaskManager(tracker, { autoSave: false });
256
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGlG,OAAO,EAAE,oBAAoB,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAWlG,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,YAAY;;;;;;;CAOxB,CAAC;AAEF,eAAO,MAAM,eAAe,UAA0C,CAAC;AAEvE,OAAO,EACL,yCAAyC,EACzC,qCAAqC,EACrC,kCAAkC,EAClC,+CAA+C,EAC/C,kCAAkC,EAClC,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqCzD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,QAAQ,CAgX1D;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EACN,oBAAoB,GACpB,iCAAiC,GACjC,gCAAgC,GAChC,6BAA6B,GAC7B,qCAAqC,GACrC,yCAAyC,GACzC,+CAA+C,GAC/C,kCAAkC,GAClC,kCAAkC,EACtC,OAAO,EAAE,GAAG,GAAG,SAAS,GACvB,UAAU,CA8GZ;AAmCD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,SAAS,EAAE,CAM5E;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAcD,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,wBAEG;IACD,iBAAiB,CAAC,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,SAKF,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAC/B,SAAQ,MAAgB,KAAG,YAa3B,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC9B,iBAAiB,eAAe,EAAE,SAAQ,MAAgB,KAAG,YA2C7D,CAAC"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGlG,OAAO,EAAE,oBAAoB,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAWlG,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,YAAY;;;;;;;CAOxB,CAAC;AAEF,eAAO,MAAM,eAAe,UAA0C,CAAC;AAEvE,OAAO,EACL,yCAAyC,EACzC,qCAAqC,EACrC,kCAAkC,EAClC,+CAA+C,EAC/C,kCAAkC,EAClC,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqCzD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,QAAQ,CAuX1D;AAED,wBAAgB,wBAAwB,CACtC,UAAU,EACN,oBAAoB,GACpB,iCAAiC,GACjC,gCAAgC,GAChC,6BAA6B,GAC7B,qCAAqC,GACrC,yCAAyC,GACzC,+CAA+C,GAC/C,kCAAkC,GAClC,kCAAkC,EACtC,OAAO,EAAE,GAAG,GAAG,SAAS,GACvB,UAAU,CA8GZ;AAmCD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,SAAS,EAAE,CAM5E;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAcD,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,wBAEG;IACD,iBAAiB,CAAC,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,SAKF,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAC/B,SAAQ,MAAgB,KAAG,YAa3B,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAC9B,iBAAiB,eAAe,EAAE,SAAQ,MAAgB,KAAG,YA2C7D,CAAC"}
package/dist/tools.js CHANGED
@@ -326,7 +326,7 @@ export function toolInfoFromToolUse(toolUse) {
326
326
  };
327
327
  case "AskUserQuestion":
328
328
  return {
329
- title: "Question",
329
+ title: input?.questions?.[0]?.header || "Question",
330
330
  kind: "think",
331
331
  content: input?.questions
332
332
  ? [
@@ -335,7 +335,14 @@ export function toolInfoFromToolUse(toolUse) {
335
335
  content: {
336
336
  type: "text",
337
337
  text: Array.isArray(input.questions)
338
- ? input.questions.map((q) => q.question).join("\n")
338
+ ? input.questions
339
+ .map((q) => {
340
+ const options = q.options
341
+ ?.map((o) => ` - ${o.label}: ${o.description}`)
342
+ .join("\n");
343
+ return `${q.question}\n${options || ""}`;
344
+ })
345
+ .join("\n\n")
339
346
  : String(input.questions),
340
347
  },
341
348
  },
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.13.7",
6
+ "version": "0.15.0",
7
7
  "description": "An ACP-compatible coding agent powered by the Claude Code SDK (TypeScript)",
8
8
  "main": "dist/lib.js",
9
9
  "types": "dist/lib.d.ts",
@@ -61,7 +61,7 @@
61
61
  "license": "Apache-2.0",
62
62
  "dependencies": {
63
63
  "@agentclientprotocol/sdk": "0.13.0",
64
- "@anthropic-ai/claude-agent-sdk": "0.2.7",
64
+ "@anthropic-ai/claude-agent-sdk": "0.2.18",
65
65
  "@modelcontextprotocol/sdk": "1.25.2",
66
66
  "diff": "8.0.3",
67
67
  "minimatch": "10.1.1"