@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.
- package/README.md +34 -1
- package/dist/acp-agent.d.ts +8 -0
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +153 -7
- package/dist/lib.d.ts +3 -1
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +4 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +6 -0
- package/dist/subagent-tracker.d.ts +102 -2
- package/dist/subagent-tracker.d.ts.map +1 -1
- package/dist/subagent-tracker.js +189 -22
- package/dist/task-manager.d.ts +106 -0
- package/dist/task-manager.d.ts.map +1 -0
- package/dist/task-manager.js +231 -0
- package/dist/task-mcp-tools.d.ts +16 -0
- package/dist/task-mcp-tools.d.ts.map +1 -0
- package/dist/task-mcp-tools.js +256 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +9 -2
- package/package.json +2 -2
|
@@ -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
|
+
}
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -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,
|
|
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
|
|
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.
|
|
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.
|
|
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"
|