cmdr-mcp 0.2.0 → 0.3.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/.claude-plugin/marketplace.json +1 -1
- package/README.md +3 -3
- package/docs/README.zh-CN.md +1 -1
- package/docs/agent-integration.md +6 -2
- package/docs/cmdr-design-v1.md +2 -0
- package/docs/implementation.md +33 -3
- package/docs/long-running-collaboration.md +53 -14
- package/docs/publishing.md +8 -8
- package/docs/troubleshooting.md +6 -0
- package/docs/zcode-desktop-session-visibility.md +172 -0
- package/marketplace.json +1 -1
- package/package.json +1 -1
- package/plugins/cmdr/.claude-plugin/plugin.json +1 -1
- package/plugins/cmdr/.codex-plugin/plugin.json +1 -1
- package/plugins/cmdr/.zcode-plugin/plugin.json +1 -1
- package/plugins/cmdr/README.md +1 -1
- package/plugins/cmdr/commands/cmdr.md +1 -1
- package/plugins/cmdr/dist/cli.mjs +129 -23
- package/plugins/cmdr/dist/daemon.mjs +396 -86
- package/plugins/cmdr/dist/hook.mjs +1 -1
- package/plugins/cmdr/dist/integrity.json +12 -12
- package/plugins/cmdr/dist/mcp.mjs +3 -3
- package/plugins/cmdr/skills/cmdr-commander/SKILL.md +1 -1
- package/plugins/cmdr/skills/cmdr-executor/SKILL.md +2 -2
- package/plugins/cmdr/skills/using-cmdr/SKILL.md +2 -2
|
@@ -6,6 +6,9 @@ var __export = (target, all) => {
|
|
|
6
6
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
// src/cli/watch.ts
|
|
10
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
11
|
+
|
|
9
12
|
// src/shared/diagnostics.ts
|
|
10
13
|
import { mkdirSync as mkdirSync2, readFileSync, writeFileSync, renameSync, rmSync } from "node:fs";
|
|
11
14
|
import { join as join2 } from "node:path";
|
|
@@ -268,7 +271,7 @@ var Rpc = class extends EventEmitter {
|
|
|
268
271
|
};
|
|
269
272
|
|
|
270
273
|
// src/shared/version.ts
|
|
271
|
-
var VERSION = true ? "0.
|
|
274
|
+
var VERSION = true ? "0.3.0" : MIN_CLIENT_VERSION;
|
|
272
275
|
var PROTOCOL = 1;
|
|
273
276
|
function newer(a, b) {
|
|
274
277
|
const x = a.split(".").map(Number), y = b.split(".").map(Number);
|
|
@@ -453,6 +456,97 @@ var DaemonClient = class {
|
|
|
453
456
|
}
|
|
454
457
|
};
|
|
455
458
|
|
|
459
|
+
// src/cli/watch.ts
|
|
460
|
+
async function watch(sid, once = false) {
|
|
461
|
+
const rpc = await daemonConnection({ start: true, upgrade: true });
|
|
462
|
+
const token = randomUUID2();
|
|
463
|
+
let timer;
|
|
464
|
+
let stopped = false;
|
|
465
|
+
let checking = false;
|
|
466
|
+
let dirty = false;
|
|
467
|
+
let error;
|
|
468
|
+
const seen = /* @__PURE__ */ new Set();
|
|
469
|
+
const stop = () => {
|
|
470
|
+
stopped = true;
|
|
471
|
+
rpc.close();
|
|
472
|
+
};
|
|
473
|
+
process.on("SIGINT", stop);
|
|
474
|
+
process.on("SIGTERM", stop);
|
|
475
|
+
const closed = new Promise(
|
|
476
|
+
(resolve3) => rpc.once("close", () => {
|
|
477
|
+
if (!stopped) error ||= new Error("cmdr daemon disconnected; re-arm the host watcher");
|
|
478
|
+
resolve3();
|
|
479
|
+
})
|
|
480
|
+
);
|
|
481
|
+
const show = (result, initial = false) => {
|
|
482
|
+
const current = /* @__PURE__ */ new Set();
|
|
483
|
+
const fresh = result.messages.filter((m) => {
|
|
484
|
+
const key = JSON.stringify([m.id, m.cancel_requested_at]);
|
|
485
|
+
current.add(key);
|
|
486
|
+
const alreadyAccepted = initial && m.type === "command" && m.work_state === "accepted" && !m.cancel_requested_at;
|
|
487
|
+
return !alreadyAccepted && !seen.has(key);
|
|
488
|
+
});
|
|
489
|
+
seen.clear();
|
|
490
|
+
for (const key of current) seen.add(key);
|
|
491
|
+
if (!fresh.length) return;
|
|
492
|
+
process.stdout.write(
|
|
493
|
+
JSON.stringify({
|
|
494
|
+
kind: "cmdr.wake",
|
|
495
|
+
sid,
|
|
496
|
+
messages: fresh,
|
|
497
|
+
instruction: "Call read and read(recover=true); handle cancellation first and report with reply_to."
|
|
498
|
+
}) + "\n"
|
|
499
|
+
);
|
|
500
|
+
if (once || result.wake_mode === "zcode") stop();
|
|
501
|
+
};
|
|
502
|
+
const check = async () => {
|
|
503
|
+
if (stopped) return;
|
|
504
|
+
if (checking) {
|
|
505
|
+
dirty = true;
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
checking = true;
|
|
509
|
+
try {
|
|
510
|
+
do {
|
|
511
|
+
dirty = false;
|
|
512
|
+
show(await rpc.request("admin.watch", { sid, token, action: "pulse" }));
|
|
513
|
+
} while (dirty && !stopped);
|
|
514
|
+
} catch (e) {
|
|
515
|
+
if (!stopped) {
|
|
516
|
+
error = e;
|
|
517
|
+
stop();
|
|
518
|
+
}
|
|
519
|
+
} finally {
|
|
520
|
+
checking = false;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
try {
|
|
524
|
+
await rpc.request("session.register", { kind: "cli" });
|
|
525
|
+
rpc.on("notification", (method) => {
|
|
526
|
+
if (method === "lifecycle.event") {
|
|
527
|
+
dirty = true;
|
|
528
|
+
if (timer) void check();
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
await rpc.request("admin.tail", { for: sid, after: "now" });
|
|
532
|
+
show(await rpc.request("admin.watch", { sid, token, action: "attach" }), true);
|
|
533
|
+
if (!stopped) {
|
|
534
|
+
timer = setInterval(() => {
|
|
535
|
+
void check();
|
|
536
|
+
}, 3e4);
|
|
537
|
+
if (dirty) await check();
|
|
538
|
+
}
|
|
539
|
+
await closed;
|
|
540
|
+
if (error) throw error;
|
|
541
|
+
} finally {
|
|
542
|
+
clearInterval(timer);
|
|
543
|
+
stopped = true;
|
|
544
|
+
rpc.close();
|
|
545
|
+
process.off("SIGINT", stop);
|
|
546
|
+
process.off("SIGTERM", stop);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
456
550
|
// src/cli/tail.ts
|
|
457
551
|
async function tail(options) {
|
|
458
552
|
let after = options.after, stopped = false;
|
|
@@ -464,9 +558,10 @@ async function tail(options) {
|
|
|
464
558
|
process.on("SIGINT", stop);
|
|
465
559
|
process.on("SIGTERM", stop);
|
|
466
560
|
const show = (event) => {
|
|
467
|
-
if (after
|
|
561
|
+
if (typeof after === "number" && event.event_seq <= after) return;
|
|
468
562
|
process.stdout.write(
|
|
469
|
-
options.json ? JSON.stringify(event) + "\n" :
|
|
563
|
+
options.json ? JSON.stringify(event) + "\n" : options.line ? `[cmdr] ${event.message?.type || event.kind} id=${event.message_id || "-"} from=${event.from_sid || "-"}${event.reply_to ? ` reply_to=${event.reply_to}` : ""}; call read and read(recover=true)
|
|
564
|
+
` : `${event.event_seq} ${new Date(event.at).toISOString()} ${event.channel || "-"} ${event.kind} ${event.from_sid || "-"} \u2192 ${event.to_sid || "-"} ${event.message_id || ""}${event.reply_to ? ` reply_to=${event.reply_to}` : ""}${event.reason ? ` ${event.reason}` : ""}${event.message ? ` ${event.message.body.replace(/\s+/g, " ")}` : ""}
|
|
470
565
|
`
|
|
471
566
|
);
|
|
472
567
|
after = event.event_seq;
|
|
@@ -497,7 +592,7 @@ async function tail(options) {
|
|
|
497
592
|
}
|
|
498
593
|
for (; ; ) {
|
|
499
594
|
for (const event of result.events) show(event);
|
|
500
|
-
after = Math.max(after
|
|
595
|
+
after = Math.max(typeof after === "number" ? after : 0, result.next);
|
|
501
596
|
if (result.next >= result.high) break;
|
|
502
597
|
result = await rpc.request("admin.events", { ...options, after });
|
|
503
598
|
}
|
|
@@ -4940,6 +5035,10 @@ if (process.argv[2] === "session") {
|
|
|
4940
5035
|
after: { type: "string" },
|
|
4941
5036
|
for: { type: "string" },
|
|
4942
5037
|
adapter: { type: "string" },
|
|
5038
|
+
transport: { type: "string" },
|
|
5039
|
+
actionable: { type: "boolean" },
|
|
5040
|
+
once: { type: "boolean" },
|
|
5041
|
+
format: { type: "string" },
|
|
4943
5042
|
executable: { type: "string" },
|
|
4944
5043
|
socket: { type: "string" },
|
|
4945
5044
|
resolve: { type: "string" },
|
|
@@ -5042,7 +5141,7 @@ if (process.argv[2] === "session") {
|
|
|
5042
5141
|
try {
|
|
5043
5142
|
if (v.help)
|
|
5044
5143
|
process.stdout.write(
|
|
5045
|
-
"cmdr status | list [--all] [--squad ID] | tail [--follow] [--full] [--json] [--after EVENT_SEQ] [--for SID] | standby start|status|stop|resume --session SID [--adapter codex|manual] | send --squad ID [--to MEMBER] [--type command|cancel|info|answer] TEXT | read --session SID [--peek] | daemon start|stop|restart|status|logs | config [--agent HOST] [--session ID] | doctor [--plugin-root PATH] [--deep] | session --help | purge [--all]\n"
|
|
5144
|
+
"cmdr status | list [--all] [--squad ID] | tail [--follow] [--full] [--json] [--after EVENT_SEQ|now] [--actionable] [--format line|json] [--for SID] | standby start|status|stop|resume|watch --session SID [--adapter codex|claude|zcode|manual] [--transport auto|proxy|queue] [--once] | send --squad ID [--to MEMBER] [--type command|cancel|info|answer] TEXT | read --session SID [--peek] | daemon start|stop|restart|status|logs | config [--agent HOST] [--session ID] | doctor [--plugin-root PATH] [--deep] | session --help | purge [--all]\n"
|
|
5046
5145
|
);
|
|
5047
5146
|
else if (cmd === "config") {
|
|
5048
5147
|
const agent = v.agent || "generic";
|
|
@@ -5137,30 +5236,37 @@ if (process.argv[2] === "session") {
|
|
|
5137
5236
|
} else if (cmd === "purge") print(await call("admin.purge", { all: !!v.all }));
|
|
5138
5237
|
else if (cmd === "standby") {
|
|
5139
5238
|
if (!v.session) throw new Error("--session SID is required");
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5239
|
+
if (args[1] === "watch") await watch(v.session, !!v.once);
|
|
5240
|
+
else
|
|
5241
|
+
print(
|
|
5242
|
+
await call(
|
|
5243
|
+
"admin.standby",
|
|
5244
|
+
{
|
|
5245
|
+
sid: v.session,
|
|
5246
|
+
action: args[1] || "status",
|
|
5247
|
+
adapter: v.adapter,
|
|
5248
|
+
transport: v.transport,
|
|
5249
|
+
executable: v.executable,
|
|
5250
|
+
socket: v.socket,
|
|
5251
|
+
resolve: v.resolve
|
|
5252
|
+
},
|
|
5253
|
+
true
|
|
5254
|
+
)
|
|
5255
|
+
);
|
|
5154
5256
|
} else if (cmd === "tail") {
|
|
5155
|
-
const after = v.after === void 0 ? void 0 : Number(v.after);
|
|
5156
|
-
if (after !== void 0 && (!Number.isSafeInteger(after) || after < 0))
|
|
5157
|
-
throw new Error("--after requires a nonnegative event_seq");
|
|
5257
|
+
const after = v.after === void 0 ? void 0 : v.after === "now" ? "now" : Number(v.after);
|
|
5258
|
+
if (after !== void 0 && after !== "now" && (!Number.isSafeInteger(after) || after < 0))
|
|
5259
|
+
throw new Error("--after requires now or a nonnegative event_seq");
|
|
5260
|
+
if (v.format && !["line", "json"].includes(v.format))
|
|
5261
|
+
throw new Error("--format must be line or json");
|
|
5158
5262
|
await tail({
|
|
5159
5263
|
squad: v.squad,
|
|
5160
5264
|
for: v.for,
|
|
5161
5265
|
after,
|
|
5162
5266
|
full: !!v.full,
|
|
5163
|
-
json: !!v.json,
|
|
5267
|
+
json: !!v.json || v.format === "json",
|
|
5268
|
+
line: v.format === "line",
|
|
5269
|
+
actionable: !!v.actionable,
|
|
5164
5270
|
follow: !!v.follow
|
|
5165
5271
|
});
|
|
5166
5272
|
} else if (cmd === "daemon") {
|