@ai-setting/roy-task-plugin 0.6.0 → 0.7.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/dist/claude-plugin/hooks/stop-check.mjs +23 -19
- package/dist/claude-plugin/mcp/bridge.mjs +64 -443
- package/dist/claude-plugin/mcp/roy-task-mcp-server.mjs +75 -50
- package/dist/claude-plugin/mcp/tools.mjs +39 -225
- package/dist/cli.js +100 -78
- package/dist/index.js +525 -524
- package/dist/index.js.map +22 -21
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -142,7 +142,7 @@ var CREATED_LINE = /Task created(?:\s+successfully)?\s*:\s*#(\d+)/;
|
|
|
142
142
|
function extractCreatedTask(text, titleHint) {
|
|
143
143
|
if (!text)
|
|
144
144
|
return;
|
|
145
|
-
return fromJson(text) ??
|
|
145
|
+
return fromJson(text) ?? fromSuccessLine(text, titleHint) ?? fromEmbeddedTaskObject(text) ?? fromTaskObjectBlob(text);
|
|
146
146
|
}
|
|
147
147
|
function uniqueTaskId(text) {
|
|
148
148
|
let id;
|
|
@@ -199,10 +199,7 @@ function titleFromCreatedActionTitle(text) {
|
|
|
199
199
|
var BLOB_GATE = ['"taskId"', '"actionTitle"', "Task created:"];
|
|
200
200
|
function fromEmbeddedTaskObject(text) {
|
|
201
201
|
let found;
|
|
202
|
-
for (const
|
|
203
|
-
const task = taskFromObject(obj);
|
|
204
|
-
if (!task)
|
|
205
|
-
continue;
|
|
202
|
+
for (const task of taskCandidates(text, jsonTree(text))) {
|
|
206
203
|
if (found === undefined)
|
|
207
204
|
found = task;
|
|
208
205
|
else if (found.id !== task.id)
|
|
@@ -210,6 +207,49 @@ function fromEmbeddedTaskObject(text) {
|
|
|
210
207
|
}
|
|
211
208
|
return found;
|
|
212
209
|
}
|
|
210
|
+
function looksLikeArrayStart(text, at) {
|
|
211
|
+
for (let i = at + 1;i < text.length; i++) {
|
|
212
|
+
const ch = text[i];
|
|
213
|
+
if (ch === " " || ch === "\t" || ch === `
|
|
214
|
+
` || ch === "\r")
|
|
215
|
+
continue;
|
|
216
|
+
return ch === "{" || ch === "[" || ch === '"' || ch === "]";
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
function taskCandidates(text, roots) {
|
|
221
|
+
const out = [];
|
|
222
|
+
const pending = [...roots].reverse();
|
|
223
|
+
while (pending.length > 0) {
|
|
224
|
+
const node = pending.pop();
|
|
225
|
+
if (node.end < 0) {
|
|
226
|
+
if (node.ch === "[" && looksLikeArrayStart(text, node.start))
|
|
227
|
+
continue;
|
|
228
|
+
pushChildren(pending, node);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (node.ch === "[")
|
|
232
|
+
continue;
|
|
233
|
+
const parsed = parseObject(text, node);
|
|
234
|
+
const task = parsed ? taskFromObject(parsed) : undefined;
|
|
235
|
+
if (task)
|
|
236
|
+
out.push(task);
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
function pushChildren(pending, node) {
|
|
241
|
+
for (let i = node.children.length - 1;i >= 0; i--)
|
|
242
|
+
pending.push(node.children[i]);
|
|
243
|
+
}
|
|
244
|
+
function parseObject(text, node) {
|
|
245
|
+
try {
|
|
246
|
+
const parsed = JSON.parse(text.slice(node.start, node.end + 1));
|
|
247
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
248
|
+
return parsed;
|
|
249
|
+
}
|
|
250
|
+
} catch {}
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
213
253
|
function taskFromObject(obj) {
|
|
214
254
|
const id = obj["id"];
|
|
215
255
|
const title = obj["title"];
|
|
@@ -219,60 +259,36 @@ function taskFromObject(obj) {
|
|
|
219
259
|
return;
|
|
220
260
|
return { id, title: title.trim() };
|
|
221
261
|
}
|
|
222
|
-
function
|
|
223
|
-
const
|
|
224
|
-
|
|
262
|
+
function jsonTree(text) {
|
|
263
|
+
const roots = [];
|
|
264
|
+
const stack = [];
|
|
225
265
|
let inString = false;
|
|
226
266
|
let escaped = false;
|
|
227
|
-
|
|
267
|
+
const open = (ch, at) => {
|
|
268
|
+
const node = { ch, start: at, end: -1, children: [] };
|
|
269
|
+
const parent = stack[stack.length - 1];
|
|
270
|
+
(parent ? parent.children : roots).push(node);
|
|
271
|
+
stack.push(node);
|
|
272
|
+
};
|
|
273
|
+
const close = (ch, at) => {
|
|
274
|
+
const want = ch === "}" ? "{" : "[";
|
|
275
|
+
let k = stack.length - 1;
|
|
276
|
+
while (k >= 0 && stack[k].ch !== want)
|
|
277
|
+
k--;
|
|
278
|
+
if (k < 0)
|
|
279
|
+
return;
|
|
280
|
+
stack.length = k + 1;
|
|
281
|
+
const node = stack.pop();
|
|
282
|
+
node.end = at;
|
|
283
|
+
};
|
|
228
284
|
for (let i = 0;i < text.length; i++) {
|
|
229
285
|
const ch = text[i];
|
|
230
286
|
if (inString) {
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
else if (ch === "\\")
|
|
234
|
-
escaped = true;
|
|
235
|
-
else if (ch === '"')
|
|
287
|
+
if (ch === `
|
|
288
|
+
`) {
|
|
236
289
|
inString = false;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (ch === '"') {
|
|
240
|
-
inString = true;
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
if (ch === "{") {
|
|
244
|
-
if (depth === 0 && !insideArray(text, i))
|
|
245
|
-
start = i;
|
|
246
|
-
depth++;
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
if (ch === "]" && depth === 0)
|
|
250
|
-
continue;
|
|
251
|
-
if (ch !== "}")
|
|
252
|
-
continue;
|
|
253
|
-
depth--;
|
|
254
|
-
if (depth !== 0 || start < 0)
|
|
255
|
-
continue;
|
|
256
|
-
const slice = text.slice(start, i + 1);
|
|
257
|
-
start = -1;
|
|
258
|
-
try {
|
|
259
|
-
const parsed = JSON.parse(slice);
|
|
260
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
261
|
-
out.push(parsed);
|
|
262
|
-
}
|
|
263
|
-
} catch {}
|
|
264
|
-
}
|
|
265
|
-
return out;
|
|
266
|
-
}
|
|
267
|
-
function insideArray(text, at) {
|
|
268
|
-
let brackets = 0;
|
|
269
|
-
let braces = 0;
|
|
270
|
-
let inString = false;
|
|
271
|
-
let escaped = false;
|
|
272
|
-
for (let i = 0;i < at; i++) {
|
|
273
|
-
const ch = text[i];
|
|
274
|
-
if (inString) {
|
|
275
|
-
if (escaped)
|
|
290
|
+
escaped = false;
|
|
291
|
+
} else if (escaped)
|
|
276
292
|
escaped = false;
|
|
277
293
|
else if (ch === "\\")
|
|
278
294
|
escaped = true;
|
|
@@ -282,16 +298,12 @@ function insideArray(text, at) {
|
|
|
282
298
|
}
|
|
283
299
|
if (ch === '"')
|
|
284
300
|
inString = true;
|
|
285
|
-
else if (ch === "{")
|
|
286
|
-
|
|
287
|
-
else if (ch === "}")
|
|
288
|
-
|
|
289
|
-
else if (ch === "[")
|
|
290
|
-
brackets++;
|
|
291
|
-
else if (ch === "]")
|
|
292
|
-
brackets--;
|
|
301
|
+
else if (ch === "{" || ch === "[")
|
|
302
|
+
open(ch, i);
|
|
303
|
+
else if (ch === "}" || ch === "]")
|
|
304
|
+
close(ch, i);
|
|
293
305
|
}
|
|
294
|
-
return
|
|
306
|
+
return roots;
|
|
295
307
|
}
|
|
296
308
|
function fromSuccessLine(text, titleHint) {
|
|
297
309
|
const m = CREATED_LINE.exec(text);
|
|
@@ -1142,12 +1154,13 @@ function createRoyAgentCardPort(options = {}) {
|
|
|
1142
1154
|
let inFlight;
|
|
1143
1155
|
const loadNotifier = async () => {
|
|
1144
1156
|
const mod = await import("@ai-setting/roy-agent-core/env/task/plugins");
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
if (!maybeNotifier) {
|
|
1148
|
-
throw new Error("roy-agent did not expose cardNotifier from createLarkCliTaskNotifyHook");
|
|
1157
|
+
if (typeof mod.LarkCardPatchNotifier !== "function") {
|
|
1158
|
+
throw new Error("roy-agent did not export LarkCardPatchNotifier from env/task/plugins");
|
|
1149
1159
|
}
|
|
1150
|
-
notifier =
|
|
1160
|
+
notifier = new mod.LarkCardPatchNotifier({
|
|
1161
|
+
pinOnStart: true,
|
|
1162
|
+
unpinOnFinish: true
|
|
1163
|
+
});
|
|
1151
1164
|
return notifier;
|
|
1152
1165
|
};
|
|
1153
1166
|
const getNotifier = () => {
|
|
@@ -1162,6 +1175,7 @@ function createRoyAgentCardPort(options = {}) {
|
|
|
1162
1175
|
return inFlight;
|
|
1163
1176
|
};
|
|
1164
1177
|
return {
|
|
1178
|
+
enabled: true,
|
|
1165
1179
|
async start(input) {
|
|
1166
1180
|
const n = await withTimeout("load", getNotifier(), opTimeoutMs);
|
|
1167
1181
|
return withTimeout("start", n.startTask({
|
|
@@ -1200,6 +1214,7 @@ function createRoyAgentCardPort(options = {}) {
|
|
|
1200
1214
|
}
|
|
1201
1215
|
function createNoopCardPort() {
|
|
1202
1216
|
return {
|
|
1217
|
+
enabled: false,
|
|
1203
1218
|
async start() {
|
|
1204
1219
|
return { messageId: "", pinned: false };
|
|
1205
1220
|
},
|
|
@@ -1248,6 +1263,8 @@ function cardReport(handle) {
|
|
|
1248
1263
|
out.cardMessageId = handle.messageId;
|
|
1249
1264
|
if (handle.error)
|
|
1250
1265
|
out.cardError = handle.error;
|
|
1266
|
+
if (handle.cardWantedButNoTask && !handle.messageId && !handle.error)
|
|
1267
|
+
out.cardExpected = true;
|
|
1251
1268
|
if (handle.meta && typeof handle.meta.id === "number")
|
|
1252
1269
|
out.taskId = handle.meta.id;
|
|
1253
1270
|
return out;
|
|
@@ -1433,6 +1450,7 @@ class Dispatcher {
|
|
|
1433
1450
|
plan,
|
|
1434
1451
|
error: sent.error ?? "unknown",
|
|
1435
1452
|
text: result.text,
|
|
1453
|
+
...createdTaskReport(result.createdTask),
|
|
1436
1454
|
...cardReport(card)
|
|
1437
1455
|
};
|
|
1438
1456
|
}
|
|
@@ -1447,6 +1465,7 @@ class Dispatcher {
|
|
|
1447
1465
|
plan,
|
|
1448
1466
|
replyMessageId: sent.messageId,
|
|
1449
1467
|
text: result.text,
|
|
1468
|
+
...createdTaskReport(result.createdTask),
|
|
1450
1469
|
...cardReport(card)
|
|
1451
1470
|
};
|
|
1452
1471
|
};
|
|
@@ -1456,8 +1475,10 @@ class Dispatcher {
|
|
|
1456
1475
|
const handle = { messageId: "" };
|
|
1457
1476
|
if (!this.deps.card)
|
|
1458
1477
|
return handle;
|
|
1459
|
-
if (!input.createdTask)
|
|
1478
|
+
if (!input.createdTask) {
|
|
1479
|
+
handle.cardWantedButNoTask = this.deps.card.enabled === true;
|
|
1460
1480
|
return handle;
|
|
1481
|
+
}
|
|
1461
1482
|
const meta = buildCardMeta({
|
|
1462
1483
|
task: input.createdTask,
|
|
1463
1484
|
messageId: input.messageId,
|
|
@@ -2308,13 +2329,14 @@ function formatBanner(options, commands, maxConcurrency) {
|
|
|
2308
2329
|
`);
|
|
2309
2330
|
}
|
|
2310
2331
|
function cardSuffix(result) {
|
|
2311
|
-
if (
|
|
2312
|
-
return "";
|
|
2313
|
-
if (result.cardError)
|
|
2332
|
+
if ("cardError" in result && result.cardError)
|
|
2314
2333
|
return ` card=FAILED(${result.cardError})`;
|
|
2315
|
-
if (result.cardMessageId)
|
|
2334
|
+
if ("cardMessageId" in result && result.cardMessageId)
|
|
2316
2335
|
return ` card=${result.cardMessageId}`;
|
|
2317
|
-
return " card=none(no task created)";
|
|
2336
|
+
return result.cardExpected ? " card=none(no task created)" : "";
|
|
2337
|
+
}
|
|
2338
|
+
function taskSuffix(result) {
|
|
2339
|
+
return result.taskId === undefined ? "" : ` task=${result.taskId}`;
|
|
2318
2340
|
}
|
|
2319
2341
|
function formatResult(label, result) {
|
|
2320
2342
|
const card = cardSuffix(result);
|
|
@@ -2326,13 +2348,13 @@ function formatResult(label, result) {
|
|
|
2326
2348
|
case "duplicate":
|
|
2327
2349
|
return `[roy-task] ${label} duplicate dropped key=${result.key ?? "(unknown)"}`;
|
|
2328
2350
|
case "no-output":
|
|
2329
|
-
return `[roy-task] ${label} no-output (agent produced no text; not replying) ` + `toolCalls=${result.toolCalls}${card}`;
|
|
2351
|
+
return `[roy-task] ${label} no-output (agent produced no text; not replying) ` + `toolCalls=${result.toolCalls}${taskSuffix(result)}${card}`;
|
|
2330
2352
|
case "no-reply":
|
|
2331
|
-
return `[roy-task] ${label} no-reply (reply disabled) chars=${result.text.length}${card}`;
|
|
2353
|
+
return `[roy-task] ${label} no-reply (reply disabled) chars=${result.text.length}${taskSuffix(result)}${card}`;
|
|
2332
2354
|
case "agent-error":
|
|
2333
|
-
return `[roy-task] ${label} agent-error: ${result.error}${card}`;
|
|
2355
|
+
return `[roy-task] ${label} agent-error: ${result.error}${taskSuffix(result)}${card}`;
|
|
2334
2356
|
case "reply-failed":
|
|
2335
|
-
return `[roy-task] ${label} reply-failed: ${result.error}${card}`;
|
|
2357
|
+
return `[roy-task] ${label} reply-failed: ${result.error}${taskSuffix(result)}${card}`;
|
|
2336
2358
|
case "no-target":
|
|
2337
2359
|
return `[roy-task] ${label} skipped: ${result.reason}`;
|
|
2338
2360
|
}
|
|
@@ -2462,7 +2484,7 @@ function formatStatus(report) {
|
|
|
2462
2484
|
}
|
|
2463
2485
|
|
|
2464
2486
|
// ../../../packages/cli/src/main.ts
|
|
2465
|
-
var VERSION = "0.
|
|
2487
|
+
var VERSION = "0.7.0";
|
|
2466
2488
|
async function main(argv) {
|
|
2467
2489
|
const parsed = parseArgs(argv);
|
|
2468
2490
|
switch (parsed.command) {
|