opencara 0.106.0 → 0.107.1
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/dist/bin.js +241 -6
- package/dist/claude-acp.js +44 -8
- package/dist/opencara-mcp.js +187 -4
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -82,12 +82,19 @@ var AcpHistoryTurnSchema = z3.object({
|
|
|
82
82
|
role: z3.enum(["user", "assistant"]),
|
|
83
83
|
text: z3.string()
|
|
84
84
|
});
|
|
85
|
+
var AcpPermissionModeSchema = z3.enum([
|
|
86
|
+
"default",
|
|
87
|
+
"acceptEdits",
|
|
88
|
+
"plan",
|
|
89
|
+
"bypassPermissions"
|
|
90
|
+
]);
|
|
85
91
|
var AcpSpecSchema = z3.object({
|
|
86
92
|
systemPromptMd: z3.string(),
|
|
87
93
|
userPromptMd: z3.string(),
|
|
88
94
|
history: z3.array(AcpHistoryTurnSchema).default([]),
|
|
89
95
|
pageContextJson: z3.string().optional(),
|
|
90
|
-
priorSessionId: z3.string().optional()
|
|
96
|
+
priorSessionId: z3.string().optional(),
|
|
97
|
+
permissionMode: AcpPermissionModeSchema.optional()
|
|
91
98
|
});
|
|
92
99
|
var AgentSpecSchema = z3.object({
|
|
93
100
|
kind: z3.string(),
|
|
@@ -198,6 +205,11 @@ var HelloAckSchema = z4.object({
|
|
|
198
205
|
agentHostId: z4.string(),
|
|
199
206
|
deviceName: z4.string()
|
|
200
207
|
});
|
|
208
|
+
var CancelJobSchema = z4.object({
|
|
209
|
+
type: z4.literal("cancel"),
|
|
210
|
+
runId: z4.string(),
|
|
211
|
+
reason: z4.enum(["user_stopped", "wave_cancelled"])
|
|
212
|
+
});
|
|
201
213
|
var PingSchema = z4.object({ type: z4.literal("ping") });
|
|
202
214
|
var PongSchema = z4.object({ type: z4.literal("pong") });
|
|
203
215
|
var AgentCallEnvelope = {
|
|
@@ -225,10 +237,56 @@ var TemplateNodeConfigSetCallSchema = z4.object({
|
|
|
225
237
|
nodeId: z4.string().min(1),
|
|
226
238
|
config: z4.record(z4.string(), z4.unknown())
|
|
227
239
|
});
|
|
240
|
+
var KanbanWaveDispatchCallSchema = z4.object({
|
|
241
|
+
...AgentCallEnvelope,
|
|
242
|
+
kind: z4.literal("kanban.wave.dispatch"),
|
|
243
|
+
flowSlug: z4.string().min(1),
|
|
244
|
+
issueNumbers: z4.array(z4.number().int()).min(1).max(10)
|
|
245
|
+
});
|
|
246
|
+
var IssueSubissueCreateCallSchema = z4.object({
|
|
247
|
+
...AgentCallEnvelope,
|
|
248
|
+
kind: z4.literal("issue.subissue.create"),
|
|
249
|
+
parentIssueNumber: z4.number().int(),
|
|
250
|
+
title: z4.string().min(1),
|
|
251
|
+
bodyMd: z4.string(),
|
|
252
|
+
labels: z4.array(z4.string()).optional()
|
|
253
|
+
});
|
|
254
|
+
var IssueCreateCallSchema = z4.object({
|
|
255
|
+
...AgentCallEnvelope,
|
|
256
|
+
kind: z4.literal("issue.create"),
|
|
257
|
+
title: z4.string().min(1),
|
|
258
|
+
bodyMd: z4.string(),
|
|
259
|
+
labels: z4.array(z4.string()).optional()
|
|
260
|
+
});
|
|
261
|
+
var IssueStateSetCallSchema = z4.object({
|
|
262
|
+
...AgentCallEnvelope,
|
|
263
|
+
kind: z4.literal("issue.state.set"),
|
|
264
|
+
issueNumber: z4.number().int(),
|
|
265
|
+
state: z4.enum(["open", "closed"]),
|
|
266
|
+
stateReason: z4.enum(["completed", "not_planned", "reopened"]).nullable().optional()
|
|
267
|
+
});
|
|
268
|
+
var IssueCommentCreateCallSchema = z4.object({
|
|
269
|
+
...AgentCallEnvelope,
|
|
270
|
+
kind: z4.literal("issue.comment.create"),
|
|
271
|
+
issueNumber: z4.number().int(),
|
|
272
|
+
bodyMd: z4.string().min(1)
|
|
273
|
+
});
|
|
274
|
+
var IssueLabelsSetCallSchema = z4.object({
|
|
275
|
+
...AgentCallEnvelope,
|
|
276
|
+
kind: z4.literal("issue.labels.set"),
|
|
277
|
+
issueNumber: z4.number().int(),
|
|
278
|
+
labels: z4.array(z4.string())
|
|
279
|
+
});
|
|
228
280
|
var AgentCallSchema = z4.discriminatedUnion("kind", [
|
|
229
281
|
IssueBodySetCallSchema,
|
|
230
282
|
FlowNodeConfigSetCallSchema,
|
|
231
|
-
TemplateNodeConfigSetCallSchema
|
|
283
|
+
TemplateNodeConfigSetCallSchema,
|
|
284
|
+
KanbanWaveDispatchCallSchema,
|
|
285
|
+
IssueSubissueCreateCallSchema,
|
|
286
|
+
IssueCreateCallSchema,
|
|
287
|
+
IssueStateSetCallSchema,
|
|
288
|
+
IssueCommentCreateCallSchema,
|
|
289
|
+
IssueLabelsSetCallSchema
|
|
232
290
|
]);
|
|
233
291
|
var AgentCallRequestEnvelope = {
|
|
234
292
|
type: z4.literal("agent-call-request"),
|
|
@@ -255,10 +313,56 @@ var TemplateNodeConfigSetCallRequestSchema = z4.object({
|
|
|
255
313
|
nodeId: z4.string().min(1),
|
|
256
314
|
config: z4.record(z4.string(), z4.unknown())
|
|
257
315
|
});
|
|
316
|
+
var KanbanWaveDispatchCallRequestSchema = z4.object({
|
|
317
|
+
...AgentCallRequestEnvelope,
|
|
318
|
+
kind: z4.literal("kanban.wave.dispatch"),
|
|
319
|
+
flowSlug: z4.string().min(1),
|
|
320
|
+
issueNumbers: z4.array(z4.number().int()).min(1).max(10)
|
|
321
|
+
});
|
|
322
|
+
var IssueSubissueCreateCallRequestSchema = z4.object({
|
|
323
|
+
...AgentCallRequestEnvelope,
|
|
324
|
+
kind: z4.literal("issue.subissue.create"),
|
|
325
|
+
parentIssueNumber: z4.number().int(),
|
|
326
|
+
title: z4.string().min(1),
|
|
327
|
+
bodyMd: z4.string(),
|
|
328
|
+
labels: z4.array(z4.string()).optional()
|
|
329
|
+
});
|
|
330
|
+
var IssueCreateCallRequestSchema = z4.object({
|
|
331
|
+
...AgentCallRequestEnvelope,
|
|
332
|
+
kind: z4.literal("issue.create"),
|
|
333
|
+
title: z4.string().min(1),
|
|
334
|
+
bodyMd: z4.string(),
|
|
335
|
+
labels: z4.array(z4.string()).optional()
|
|
336
|
+
});
|
|
337
|
+
var IssueStateSetCallRequestSchema = z4.object({
|
|
338
|
+
...AgentCallRequestEnvelope,
|
|
339
|
+
kind: z4.literal("issue.state.set"),
|
|
340
|
+
issueNumber: z4.number().int(),
|
|
341
|
+
state: z4.enum(["open", "closed"]),
|
|
342
|
+
stateReason: z4.enum(["completed", "not_planned", "reopened"]).nullable().optional()
|
|
343
|
+
});
|
|
344
|
+
var IssueCommentCreateCallRequestSchema = z4.object({
|
|
345
|
+
...AgentCallRequestEnvelope,
|
|
346
|
+
kind: z4.literal("issue.comment.create"),
|
|
347
|
+
issueNumber: z4.number().int(),
|
|
348
|
+
bodyMd: z4.string().min(1)
|
|
349
|
+
});
|
|
350
|
+
var IssueLabelsSetCallRequestSchema = z4.object({
|
|
351
|
+
...AgentCallRequestEnvelope,
|
|
352
|
+
kind: z4.literal("issue.labels.set"),
|
|
353
|
+
issueNumber: z4.number().int(),
|
|
354
|
+
labels: z4.array(z4.string())
|
|
355
|
+
});
|
|
258
356
|
var AgentCallRequestSchema = z4.discriminatedUnion("kind", [
|
|
259
357
|
IssueBodySetCallRequestSchema,
|
|
260
358
|
FlowNodeConfigSetCallRequestSchema,
|
|
261
|
-
TemplateNodeConfigSetCallRequestSchema
|
|
359
|
+
TemplateNodeConfigSetCallRequestSchema,
|
|
360
|
+
KanbanWaveDispatchCallRequestSchema,
|
|
361
|
+
IssueSubissueCreateCallRequestSchema,
|
|
362
|
+
IssueCreateCallRequestSchema,
|
|
363
|
+
IssueStateSetCallRequestSchema,
|
|
364
|
+
IssueCommentCreateCallRequestSchema,
|
|
365
|
+
IssueLabelsSetCallRequestSchema
|
|
262
366
|
]);
|
|
263
367
|
var AgentCallResultSchema = z4.object({
|
|
264
368
|
type: z4.literal("agent-call-result"),
|
|
@@ -273,7 +377,8 @@ var ServerToDeviceMessageSchema = z4.discriminatedUnion("type", [
|
|
|
273
377
|
JobAssignmentSchema,
|
|
274
378
|
HelloAckSchema,
|
|
275
379
|
PingSchema,
|
|
276
|
-
AgentCallResultSchema
|
|
380
|
+
AgentCallResultSchema,
|
|
381
|
+
CancelJobSchema
|
|
277
382
|
]);
|
|
278
383
|
var DeviceToServerMessageSchema = z4.union([
|
|
279
384
|
HelloMessageSchema,
|
|
@@ -1046,6 +1151,72 @@ function buildAgentCallRequest(runId, callId, kind, args) {
|
|
|
1046
1151
|
nodeId: String(args["nodeId"] ?? ""),
|
|
1047
1152
|
config: args["config"] ?? {}
|
|
1048
1153
|
};
|
|
1154
|
+
case "kanban.wave.dispatch":
|
|
1155
|
+
return {
|
|
1156
|
+
type: "agent-call-request",
|
|
1157
|
+
runId,
|
|
1158
|
+
callId,
|
|
1159
|
+
kind: "kanban.wave.dispatch",
|
|
1160
|
+
flowSlug: String(args["flowSlug"] ?? ""),
|
|
1161
|
+
issueNumbers: Array.isArray(args["issueNumbers"]) ? args["issueNumbers"].map((n) => Number(n)) : []
|
|
1162
|
+
};
|
|
1163
|
+
case "issue.subissue.create": {
|
|
1164
|
+
const labels = args["labels"];
|
|
1165
|
+
return {
|
|
1166
|
+
type: "agent-call-request",
|
|
1167
|
+
runId,
|
|
1168
|
+
callId,
|
|
1169
|
+
kind: "issue.subissue.create",
|
|
1170
|
+
parentIssueNumber: Number(args["parentIssueNumber"]),
|
|
1171
|
+
title: String(args["title"] ?? ""),
|
|
1172
|
+
bodyMd: String(args["bodyMd"] ?? ""),
|
|
1173
|
+
...Array.isArray(labels) ? { labels: labels.map((l) => String(l)) } : {}
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
case "issue.create": {
|
|
1177
|
+
const labels = args["labels"];
|
|
1178
|
+
return {
|
|
1179
|
+
type: "agent-call-request",
|
|
1180
|
+
runId,
|
|
1181
|
+
callId,
|
|
1182
|
+
kind: "issue.create",
|
|
1183
|
+
title: String(args["title"] ?? ""),
|
|
1184
|
+
bodyMd: String(args["bodyMd"] ?? ""),
|
|
1185
|
+
...Array.isArray(labels) ? { labels: labels.map((l) => String(l)) } : {}
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
case "issue.state.set": {
|
|
1189
|
+
const reason = args["stateReason"];
|
|
1190
|
+
return {
|
|
1191
|
+
type: "agent-call-request",
|
|
1192
|
+
runId,
|
|
1193
|
+
callId,
|
|
1194
|
+
kind: "issue.state.set",
|
|
1195
|
+
issueNumber: Number(args["issueNumber"]),
|
|
1196
|
+
state: args["state"] === "closed" ? "closed" : "open",
|
|
1197
|
+
...reason === void 0 ? {} : {
|
|
1198
|
+
stateReason: reason === null ? null : String(reason)
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
case "issue.comment.create":
|
|
1203
|
+
return {
|
|
1204
|
+
type: "agent-call-request",
|
|
1205
|
+
runId,
|
|
1206
|
+
callId,
|
|
1207
|
+
kind: "issue.comment.create",
|
|
1208
|
+
issueNumber: Number(args["issueNumber"]),
|
|
1209
|
+
bodyMd: String(args["bodyMd"] ?? "")
|
|
1210
|
+
};
|
|
1211
|
+
case "issue.labels.set":
|
|
1212
|
+
return {
|
|
1213
|
+
type: "agent-call-request",
|
|
1214
|
+
runId,
|
|
1215
|
+
callId,
|
|
1216
|
+
kind: "issue.labels.set",
|
|
1217
|
+
issueNumber: Number(args["issueNumber"]),
|
|
1218
|
+
labels: Array.isArray(args["labels"]) ? args["labels"].map((l) => String(l)) : []
|
|
1219
|
+
};
|
|
1049
1220
|
default:
|
|
1050
1221
|
return null;
|
|
1051
1222
|
}
|
|
@@ -1073,9 +1244,35 @@ function runAcpJob(opts) {
|
|
|
1073
1244
|
const translator = createUpdateTranslator(handlers.onLog);
|
|
1074
1245
|
client.onSessionUpdate((p) => translator.handle(p.update));
|
|
1075
1246
|
client.onStderr((chunk) => handlers.onLog("stderr", chunk));
|
|
1247
|
+
let activeSessionId = null;
|
|
1248
|
+
let cancelRequested = false;
|
|
1249
|
+
let forceCloseScheduled = false;
|
|
1250
|
+
const scheduleForceClose = () => {
|
|
1251
|
+
if (forceCloseScheduled) return;
|
|
1252
|
+
forceCloseScheduled = true;
|
|
1253
|
+
setTimeout(() => {
|
|
1254
|
+
client.close(0).catch(() => void 0);
|
|
1255
|
+
}, 2e3);
|
|
1256
|
+
};
|
|
1076
1257
|
const controller = {
|
|
1077
1258
|
onAgentCallResult(msg) {
|
|
1078
1259
|
bridge.onResult(msg);
|
|
1260
|
+
},
|
|
1261
|
+
cancel() {
|
|
1262
|
+
if (cancelRequested) return;
|
|
1263
|
+
cancelRequested = true;
|
|
1264
|
+
if (activeSessionId) {
|
|
1265
|
+
try {
|
|
1266
|
+
client.cancel(activeSessionId);
|
|
1267
|
+
} catch (err) {
|
|
1268
|
+
handlers.onLog(
|
|
1269
|
+
"stderr",
|
|
1270
|
+
`[opencara] cancel notify failed: ${err instanceof Error ? err.message : String(err)}
|
|
1271
|
+
`
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
scheduleForceClose();
|
|
1079
1276
|
}
|
|
1080
1277
|
};
|
|
1081
1278
|
const promise = (async () => {
|
|
@@ -1102,8 +1299,21 @@ function runAcpJob(opts) {
|
|
|
1102
1299
|
const session = await client.newSession({ cwd, mcpServers });
|
|
1103
1300
|
sessionId = session.sessionId;
|
|
1104
1301
|
}
|
|
1302
|
+
activeSessionId = sessionId;
|
|
1303
|
+
if (cancelRequested) {
|
|
1304
|
+
try {
|
|
1305
|
+
client.cancel(sessionId);
|
|
1306
|
+
} catch {
|
|
1307
|
+
}
|
|
1308
|
+
result = { exitCode: 1, stopReason: "cancelled", sessionId };
|
|
1309
|
+
return result;
|
|
1310
|
+
}
|
|
1105
1311
|
const prompt = buildPromptContent(acpSpec);
|
|
1106
|
-
const promptResult = await client.prompt({
|
|
1312
|
+
const promptResult = await client.prompt({
|
|
1313
|
+
sessionId,
|
|
1314
|
+
prompt,
|
|
1315
|
+
...acpSpec.permissionMode ? { permissionMode: acpSpec.permissionMode } : {}
|
|
1316
|
+
});
|
|
1107
1317
|
result = {
|
|
1108
1318
|
exitCode: promptResult.stopReason === "end_turn" ? 0 : 1,
|
|
1109
1319
|
stopReason: promptResult.stopReason,
|
|
@@ -1232,7 +1442,7 @@ function resolveLocalAcpAdapter(command, args) {
|
|
|
1232
1442
|
}
|
|
1233
1443
|
|
|
1234
1444
|
// src/commands/run.ts
|
|
1235
|
-
var PKG_VERSION = "0.
|
|
1445
|
+
var PKG_VERSION = "0.107.1";
|
|
1236
1446
|
var LOG_FLUSH_MS = 800;
|
|
1237
1447
|
var MAX_CHUNK_SIZE = 4 * 1024;
|
|
1238
1448
|
async function run(opts = {}) {
|
|
@@ -1283,6 +1493,16 @@ function handleServerMessage(msg, client, _cfg) {
|
|
|
1283
1493
|
acpControllers.get(msg.runId)?.onAgentCallResult(msg);
|
|
1284
1494
|
return;
|
|
1285
1495
|
}
|
|
1496
|
+
if (msg.type === "cancel") {
|
|
1497
|
+
const ctrl = acpControllers.get(msg.runId);
|
|
1498
|
+
if (ctrl) {
|
|
1499
|
+
console.log(
|
|
1500
|
+
`[opencara] job ${msg.runId.slice(-8)} cancel requested (${msg.reason})`
|
|
1501
|
+
);
|
|
1502
|
+
ctrl.cancel();
|
|
1503
|
+
}
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1286
1506
|
}
|
|
1287
1507
|
async function executeJob(job, client) {
|
|
1288
1508
|
const runId = job.run.id;
|
|
@@ -1561,6 +1781,11 @@ function worktreeCreate(args) {
|
|
|
1561
1781
|
if (useLfs && !useCache) {
|
|
1562
1782
|
fail("--lfs requires --cache-repo");
|
|
1563
1783
|
}
|
|
1784
|
+
if (useLfs && !hasGitLfs()) {
|
|
1785
|
+
fail(
|
|
1786
|
+
"--lfs is set but git-lfs is not installed on this host \u2014 install it (e.g. `apt install git-lfs && git lfs install`) or disable LFS on the agent.worktree.cacheRepo config"
|
|
1787
|
+
);
|
|
1788
|
+
}
|
|
1564
1789
|
const cacheDir = useCache ? join2(CACHE_ROOT, safeKey(repo)) : null;
|
|
1565
1790
|
const gitEnv = useCache && !useLfs ? { ...process.env, GIT_LFS_SKIP_SMUDGE: "1" } : void 0;
|
|
1566
1791
|
const HELPER_SNIPPET = '!f() { echo username=x-access-token; echo "password=$GH_TOKEN"; }; f';
|
|
@@ -1733,6 +1958,16 @@ function refExists(cwd, ref) {
|
|
|
1733
1958
|
return false;
|
|
1734
1959
|
}
|
|
1735
1960
|
}
|
|
1961
|
+
function hasGitLfs() {
|
|
1962
|
+
try {
|
|
1963
|
+
execFileSync("git", ["lfs", "version"], {
|
|
1964
|
+
stdio: ["ignore", "ignore", "ignore"]
|
|
1965
|
+
});
|
|
1966
|
+
return true;
|
|
1967
|
+
} catch {
|
|
1968
|
+
return false;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1736
1971
|
function pickFlag(argv, name) {
|
|
1737
1972
|
const i = argv.indexOf(name);
|
|
1738
1973
|
if (i === -1) return void 0;
|
package/dist/claude-acp.js
CHANGED
|
@@ -62,7 +62,7 @@ function notify(method, params) {
|
|
|
62
62
|
send({ jsonrpc: "2.0", method, params });
|
|
63
63
|
}
|
|
64
64
|
var sessions = /* @__PURE__ */ new Map();
|
|
65
|
-
async function runClaudeTurn(sessionId, state, promptText) {
|
|
65
|
+
async function runClaudeTurn(sessionId, state, promptText, permissionMode) {
|
|
66
66
|
return new Promise((resolve, reject) => {
|
|
67
67
|
const idFlag = state.resume ? "--resume" : "--session-id";
|
|
68
68
|
const args = [
|
|
@@ -75,16 +75,19 @@ async function runClaudeTurn(sessionId, state, promptText) {
|
|
|
75
75
|
"--include-partial-messages",
|
|
76
76
|
"--verbose",
|
|
77
77
|
idFlag,
|
|
78
|
-
sessionId
|
|
79
|
-
// Headless: no human in the loop to approve tool use. Matches the
|
|
80
|
-
// legacy `claudeAdapter` posture in agents/kinds.ts.
|
|
81
|
-
"--dangerously-skip-permissions"
|
|
78
|
+
sessionId
|
|
82
79
|
];
|
|
80
|
+
if (permissionMode && permissionMode !== "default") {
|
|
81
|
+
args.push("--permission-mode", permissionMode);
|
|
82
|
+
} else {
|
|
83
|
+
args.push("--dangerously-skip-permissions");
|
|
84
|
+
}
|
|
83
85
|
const child = spawn("claude", args, {
|
|
84
86
|
cwd: state.cwd,
|
|
85
87
|
env: process.env,
|
|
86
88
|
stdio: ["pipe", "pipe", "pipe"]
|
|
87
89
|
});
|
|
90
|
+
state.activeChild = child;
|
|
88
91
|
child.stdin.on("error", () => {
|
|
89
92
|
});
|
|
90
93
|
child.stdin.end(promptText);
|
|
@@ -116,9 +119,14 @@ async function runClaudeTurn(sessionId, state, promptText) {
|
|
|
116
119
|
reject(err);
|
|
117
120
|
}
|
|
118
121
|
});
|
|
119
|
-
child.on("close", (code) => {
|
|
122
|
+
child.on("close", (code, signal) => {
|
|
123
|
+
state.activeChild = null;
|
|
120
124
|
if (!resolved) {
|
|
121
125
|
resolved = true;
|
|
126
|
+
if (signal === "SIGTERM" || signal === "SIGINT") {
|
|
127
|
+
resolve({ stopReason: "cancelled" });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
122
130
|
if (code !== 0) {
|
|
123
131
|
stderr.write(`[claude-acp] claude exited code=${code} without result event
|
|
124
132
|
`);
|
|
@@ -225,10 +233,29 @@ async function handlePrompt(params) {
|
|
|
225
233
|
if (promptText.length === 0) {
|
|
226
234
|
throw new Error("session/prompt: no text content blocks");
|
|
227
235
|
}
|
|
228
|
-
const result = await runClaudeTurn(
|
|
236
|
+
const result = await runClaudeTurn(
|
|
237
|
+
params.sessionId,
|
|
238
|
+
state,
|
|
239
|
+
promptText,
|
|
240
|
+
params.permissionMode
|
|
241
|
+
);
|
|
229
242
|
state.resume = true;
|
|
230
243
|
return { stopReason: result.stopReason };
|
|
231
244
|
}
|
|
245
|
+
function handleCancel(params) {
|
|
246
|
+
const state = sessions.get(params.sessionId);
|
|
247
|
+
if (!state) return;
|
|
248
|
+
const child = state.activeChild;
|
|
249
|
+
if (!child) return;
|
|
250
|
+
try {
|
|
251
|
+
child.kill("SIGTERM");
|
|
252
|
+
} catch (err) {
|
|
253
|
+
stderr.write(
|
|
254
|
+
`[claude-acp] session/cancel kill failed: ${err instanceof Error ? err.message : String(err)}
|
|
255
|
+
`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
232
259
|
var isMainModule = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("claude-acp.ts") === true || process.argv[1]?.endsWith("claude-acp.js") === true;
|
|
233
260
|
if (isMainModule) {
|
|
234
261
|
const decoder = new FrameDecoder();
|
|
@@ -246,7 +273,16 @@ if (isMainModule) {
|
|
|
246
273
|
});
|
|
247
274
|
}
|
|
248
275
|
async function dispatch(msg) {
|
|
249
|
-
if (!("id" in msg) || msg.id == null)
|
|
276
|
+
if (!("id" in msg) || msg.id == null) {
|
|
277
|
+
const notification = msg;
|
|
278
|
+
if (notification.method === "session/cancel") {
|
|
279
|
+
const params = notification.params;
|
|
280
|
+
if (params && typeof params.sessionId === "string") {
|
|
281
|
+
handleCancel(params);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
250
286
|
if ("result" in msg || "error" in msg) return;
|
|
251
287
|
const req = msg;
|
|
252
288
|
try {
|
package/dist/opencara-mcp.js
CHANGED
|
@@ -123,12 +123,19 @@ var AcpHistoryTurnSchema = z2.object({
|
|
|
123
123
|
role: z2.enum(["user", "assistant"]),
|
|
124
124
|
text: z2.string()
|
|
125
125
|
});
|
|
126
|
+
var AcpPermissionModeSchema = z2.enum([
|
|
127
|
+
"default",
|
|
128
|
+
"acceptEdits",
|
|
129
|
+
"plan",
|
|
130
|
+
"bypassPermissions"
|
|
131
|
+
]);
|
|
126
132
|
var AcpSpecSchema = z2.object({
|
|
127
133
|
systemPromptMd: z2.string(),
|
|
128
134
|
userPromptMd: z2.string(),
|
|
129
135
|
history: z2.array(AcpHistoryTurnSchema).default([]),
|
|
130
136
|
pageContextJson: z2.string().optional(),
|
|
131
|
-
priorSessionId: z2.string().optional()
|
|
137
|
+
priorSessionId: z2.string().optional(),
|
|
138
|
+
permissionMode: AcpPermissionModeSchema.optional()
|
|
132
139
|
});
|
|
133
140
|
var AgentSpecSchema = z2.object({
|
|
134
141
|
kind: z2.string(),
|
|
@@ -239,6 +246,11 @@ var HelloAckSchema = z3.object({
|
|
|
239
246
|
agentHostId: z3.string(),
|
|
240
247
|
deviceName: z3.string()
|
|
241
248
|
});
|
|
249
|
+
var CancelJobSchema = z3.object({
|
|
250
|
+
type: z3.literal("cancel"),
|
|
251
|
+
runId: z3.string(),
|
|
252
|
+
reason: z3.enum(["user_stopped", "wave_cancelled"])
|
|
253
|
+
});
|
|
242
254
|
var PingSchema = z3.object({ type: z3.literal("ping") });
|
|
243
255
|
var PongSchema = z3.object({ type: z3.literal("pong") });
|
|
244
256
|
var AgentCallEnvelope = {
|
|
@@ -266,10 +278,56 @@ var TemplateNodeConfigSetCallSchema = z3.object({
|
|
|
266
278
|
nodeId: z3.string().min(1),
|
|
267
279
|
config: z3.record(z3.string(), z3.unknown())
|
|
268
280
|
});
|
|
281
|
+
var KanbanWaveDispatchCallSchema = z3.object({
|
|
282
|
+
...AgentCallEnvelope,
|
|
283
|
+
kind: z3.literal("kanban.wave.dispatch"),
|
|
284
|
+
flowSlug: z3.string().min(1),
|
|
285
|
+
issueNumbers: z3.array(z3.number().int()).min(1).max(10)
|
|
286
|
+
});
|
|
287
|
+
var IssueSubissueCreateCallSchema = z3.object({
|
|
288
|
+
...AgentCallEnvelope,
|
|
289
|
+
kind: z3.literal("issue.subissue.create"),
|
|
290
|
+
parentIssueNumber: z3.number().int(),
|
|
291
|
+
title: z3.string().min(1),
|
|
292
|
+
bodyMd: z3.string(),
|
|
293
|
+
labels: z3.array(z3.string()).optional()
|
|
294
|
+
});
|
|
295
|
+
var IssueCreateCallSchema = z3.object({
|
|
296
|
+
...AgentCallEnvelope,
|
|
297
|
+
kind: z3.literal("issue.create"),
|
|
298
|
+
title: z3.string().min(1),
|
|
299
|
+
bodyMd: z3.string(),
|
|
300
|
+
labels: z3.array(z3.string()).optional()
|
|
301
|
+
});
|
|
302
|
+
var IssueStateSetCallSchema = z3.object({
|
|
303
|
+
...AgentCallEnvelope,
|
|
304
|
+
kind: z3.literal("issue.state.set"),
|
|
305
|
+
issueNumber: z3.number().int(),
|
|
306
|
+
state: z3.enum(["open", "closed"]),
|
|
307
|
+
stateReason: z3.enum(["completed", "not_planned", "reopened"]).nullable().optional()
|
|
308
|
+
});
|
|
309
|
+
var IssueCommentCreateCallSchema = z3.object({
|
|
310
|
+
...AgentCallEnvelope,
|
|
311
|
+
kind: z3.literal("issue.comment.create"),
|
|
312
|
+
issueNumber: z3.number().int(),
|
|
313
|
+
bodyMd: z3.string().min(1)
|
|
314
|
+
});
|
|
315
|
+
var IssueLabelsSetCallSchema = z3.object({
|
|
316
|
+
...AgentCallEnvelope,
|
|
317
|
+
kind: z3.literal("issue.labels.set"),
|
|
318
|
+
issueNumber: z3.number().int(),
|
|
319
|
+
labels: z3.array(z3.string())
|
|
320
|
+
});
|
|
269
321
|
var AgentCallSchema = z3.discriminatedUnion("kind", [
|
|
270
322
|
IssueBodySetCallSchema,
|
|
271
323
|
FlowNodeConfigSetCallSchema,
|
|
272
|
-
TemplateNodeConfigSetCallSchema
|
|
324
|
+
TemplateNodeConfigSetCallSchema,
|
|
325
|
+
KanbanWaveDispatchCallSchema,
|
|
326
|
+
IssueSubissueCreateCallSchema,
|
|
327
|
+
IssueCreateCallSchema,
|
|
328
|
+
IssueStateSetCallSchema,
|
|
329
|
+
IssueCommentCreateCallSchema,
|
|
330
|
+
IssueLabelsSetCallSchema
|
|
273
331
|
]);
|
|
274
332
|
var AgentCallRequestEnvelope = {
|
|
275
333
|
type: z3.literal("agent-call-request"),
|
|
@@ -296,10 +354,56 @@ var TemplateNodeConfigSetCallRequestSchema = z3.object({
|
|
|
296
354
|
nodeId: z3.string().min(1),
|
|
297
355
|
config: z3.record(z3.string(), z3.unknown())
|
|
298
356
|
});
|
|
357
|
+
var KanbanWaveDispatchCallRequestSchema = z3.object({
|
|
358
|
+
...AgentCallRequestEnvelope,
|
|
359
|
+
kind: z3.literal("kanban.wave.dispatch"),
|
|
360
|
+
flowSlug: z3.string().min(1),
|
|
361
|
+
issueNumbers: z3.array(z3.number().int()).min(1).max(10)
|
|
362
|
+
});
|
|
363
|
+
var IssueSubissueCreateCallRequestSchema = z3.object({
|
|
364
|
+
...AgentCallRequestEnvelope,
|
|
365
|
+
kind: z3.literal("issue.subissue.create"),
|
|
366
|
+
parentIssueNumber: z3.number().int(),
|
|
367
|
+
title: z3.string().min(1),
|
|
368
|
+
bodyMd: z3.string(),
|
|
369
|
+
labels: z3.array(z3.string()).optional()
|
|
370
|
+
});
|
|
371
|
+
var IssueCreateCallRequestSchema = z3.object({
|
|
372
|
+
...AgentCallRequestEnvelope,
|
|
373
|
+
kind: z3.literal("issue.create"),
|
|
374
|
+
title: z3.string().min(1),
|
|
375
|
+
bodyMd: z3.string(),
|
|
376
|
+
labels: z3.array(z3.string()).optional()
|
|
377
|
+
});
|
|
378
|
+
var IssueStateSetCallRequestSchema = z3.object({
|
|
379
|
+
...AgentCallRequestEnvelope,
|
|
380
|
+
kind: z3.literal("issue.state.set"),
|
|
381
|
+
issueNumber: z3.number().int(),
|
|
382
|
+
state: z3.enum(["open", "closed"]),
|
|
383
|
+
stateReason: z3.enum(["completed", "not_planned", "reopened"]).nullable().optional()
|
|
384
|
+
});
|
|
385
|
+
var IssueCommentCreateCallRequestSchema = z3.object({
|
|
386
|
+
...AgentCallRequestEnvelope,
|
|
387
|
+
kind: z3.literal("issue.comment.create"),
|
|
388
|
+
issueNumber: z3.number().int(),
|
|
389
|
+
bodyMd: z3.string().min(1)
|
|
390
|
+
});
|
|
391
|
+
var IssueLabelsSetCallRequestSchema = z3.object({
|
|
392
|
+
...AgentCallRequestEnvelope,
|
|
393
|
+
kind: z3.literal("issue.labels.set"),
|
|
394
|
+
issueNumber: z3.number().int(),
|
|
395
|
+
labels: z3.array(z3.string())
|
|
396
|
+
});
|
|
299
397
|
var AgentCallRequestSchema = z3.discriminatedUnion("kind", [
|
|
300
398
|
IssueBodySetCallRequestSchema,
|
|
301
399
|
FlowNodeConfigSetCallRequestSchema,
|
|
302
|
-
TemplateNodeConfigSetCallRequestSchema
|
|
400
|
+
TemplateNodeConfigSetCallRequestSchema,
|
|
401
|
+
KanbanWaveDispatchCallRequestSchema,
|
|
402
|
+
IssueSubissueCreateCallRequestSchema,
|
|
403
|
+
IssueCreateCallRequestSchema,
|
|
404
|
+
IssueStateSetCallRequestSchema,
|
|
405
|
+
IssueCommentCreateCallRequestSchema,
|
|
406
|
+
IssueLabelsSetCallRequestSchema
|
|
303
407
|
]);
|
|
304
408
|
var AgentCallResultSchema = z3.object({
|
|
305
409
|
type: z3.literal("agent-call-result"),
|
|
@@ -314,7 +418,8 @@ var ServerToDeviceMessageSchema = z3.discriminatedUnion("type", [
|
|
|
314
418
|
JobAssignmentSchema,
|
|
315
419
|
HelloAckSchema,
|
|
316
420
|
PingSchema,
|
|
317
|
-
AgentCallResultSchema
|
|
421
|
+
AgentCallResultSchema,
|
|
422
|
+
CancelJobSchema
|
|
318
423
|
]);
|
|
319
424
|
var DeviceToServerMessageSchema = z3.union([
|
|
320
425
|
HelloMessageSchema,
|
|
@@ -383,6 +488,42 @@ var templateNodeConfigSetShape = TemplateNodeConfigSetCallSchema.omit({
|
|
|
383
488
|
callId: true,
|
|
384
489
|
kind: true
|
|
385
490
|
}).shape;
|
|
491
|
+
var kanbanWaveDispatchShape = KanbanWaveDispatchCallSchema.omit({
|
|
492
|
+
type: true,
|
|
493
|
+
runId: true,
|
|
494
|
+
callId: true,
|
|
495
|
+
kind: true
|
|
496
|
+
}).shape;
|
|
497
|
+
var issueSubissueCreateShape = IssueSubissueCreateCallSchema.omit({
|
|
498
|
+
type: true,
|
|
499
|
+
runId: true,
|
|
500
|
+
callId: true,
|
|
501
|
+
kind: true
|
|
502
|
+
}).shape;
|
|
503
|
+
var issueCreateShape = IssueCreateCallSchema.omit({
|
|
504
|
+
type: true,
|
|
505
|
+
runId: true,
|
|
506
|
+
callId: true,
|
|
507
|
+
kind: true
|
|
508
|
+
}).shape;
|
|
509
|
+
var issueStateSetShape = IssueStateSetCallSchema.omit({
|
|
510
|
+
type: true,
|
|
511
|
+
runId: true,
|
|
512
|
+
callId: true,
|
|
513
|
+
kind: true
|
|
514
|
+
}).shape;
|
|
515
|
+
var issueCommentCreateShape = IssueCommentCreateCallSchema.omit({
|
|
516
|
+
type: true,
|
|
517
|
+
runId: true,
|
|
518
|
+
callId: true,
|
|
519
|
+
kind: true
|
|
520
|
+
}).shape;
|
|
521
|
+
var issueLabelsSetShape = IssueLabelsSetCallSchema.omit({
|
|
522
|
+
type: true,
|
|
523
|
+
runId: true,
|
|
524
|
+
callId: true,
|
|
525
|
+
kind: true
|
|
526
|
+
}).shape;
|
|
386
527
|
var TOOLS = [
|
|
387
528
|
{
|
|
388
529
|
name: "opencara_issue_body_set",
|
|
@@ -404,6 +545,48 @@ var TOOLS = [
|
|
|
404
545
|
title: "Update a flow-template draft node's config",
|
|
405
546
|
description: "Replace the config blob of a node in the user's draft of the named flow template. Per-user scope, not per-project. Reject with reason if the template draft isn't owned by the run's user.",
|
|
406
547
|
inputShape: templateNodeConfigSetShape
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
name: "opencara_kanban_wave_dispatch",
|
|
551
|
+
kind: "kanban.wave.dispatch",
|
|
552
|
+
title: "Dispatch a batch of issues to a flow",
|
|
553
|
+
description: "Dispatch up to 10 issues in parallel to the named project flow. Requires project scope. Reject if the flow does not exist, is disabled, or any of the issue numbers are not in the project. Returns the wave id.",
|
|
554
|
+
inputShape: kanbanWaveDispatchShape
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
name: "opencara_issue_subissue_create",
|
|
558
|
+
kind: "issue.subissue.create",
|
|
559
|
+
title: "Create a GitHub sub-issue under a parent",
|
|
560
|
+
description: "Create a new GitHub issue and link it as a child of the given parent issue via the GraphQL addSubIssue mutation. Requires project scope. Reject if the parent issue is not in the project.",
|
|
561
|
+
inputShape: issueSubissueCreateShape
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
name: "opencara_issue_create",
|
|
565
|
+
kind: "issue.create",
|
|
566
|
+
title: "Create a top-level GitHub issue",
|
|
567
|
+
description: "Create a new GitHub issue in the run's project with no parent link. Requires project scope. Returns the new issueNumber and nodeId.",
|
|
568
|
+
inputShape: issueCreateShape
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
name: "opencara_issue_state_set",
|
|
572
|
+
kind: "issue.state.set",
|
|
573
|
+
title: "Open or close an existing issue",
|
|
574
|
+
description: "Set an issue's state to open or closed. Optional stateReason: completed | not_planned | reopened. Requires project scope. Reject if the issue is not in the project.",
|
|
575
|
+
inputShape: issueStateSetShape
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
name: "opencara_issue_comment_create",
|
|
579
|
+
kind: "issue.comment.create",
|
|
580
|
+
title: "Post a comment on an issue",
|
|
581
|
+
description: "Post a Markdown comment on the named issue. Comments are not mirrored locally; the comment lives on GitHub. Requires project scope. Reject if the issue is not in the project.",
|
|
582
|
+
inputShape: issueCommentCreateShape
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
name: "opencara_issue_labels_set",
|
|
586
|
+
kind: "issue.labels.set",
|
|
587
|
+
title: "Replace the label set on an issue",
|
|
588
|
+
description: "Set the issue's labels to exactly the listed names (REST setLabels semantics). Any label not in the list is removed; empty array clears all labels. Requires project scope.",
|
|
589
|
+
inputShape: issueLabelsSetShape
|
|
407
590
|
}
|
|
408
591
|
];
|
|
409
592
|
function registerOpencaraTools(server, router) {
|