cmdr-mcp 0.1.1 → 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.
@@ -6,8 +6,8 @@ var __export = (target, all) => {
6
6
  __defProp(target, name, { get: all[name], enumerable: true });
7
7
  };
8
8
 
9
- // src/cli/session.ts
10
- import { parseArgs } from "node:util";
9
+ // src/cli/watch.ts
10
+ import { randomUUID as randomUUID2 } from "node:crypto";
11
11
 
12
12
  // src/shared/diagnostics.ts
13
13
  import { mkdirSync as mkdirSync2, readFileSync, writeFileSync, renameSync, rmSync } from "node:fs";
@@ -115,7 +115,18 @@ import { connect } from "node:net";
115
115
  import { spawn } from "node:child_process";
116
116
  import { dirname, join as join3 } from "node:path";
117
117
  import { fileURLToPath } from "node:url";
118
- import { mkdirSync as mkdirSync3, rmSync as rmSync2, statSync } from "node:fs";
118
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync2, rmSync as rmSync2, statSync } from "node:fs";
119
+
120
+ // src/daemon/lock.ts
121
+ function alive(pid) {
122
+ if (!Number.isInteger(pid) || pid <= 0) return false;
123
+ try {
124
+ process.kill(pid, 0);
125
+ return true;
126
+ } catch (e) {
127
+ return e.code === "EPERM";
128
+ }
129
+ }
119
130
 
120
131
  // src/shared/rpc.ts
121
132
  import { EventEmitter } from "node:events";
@@ -260,7 +271,7 @@ var Rpc = class extends EventEmitter {
260
271
  };
261
272
 
262
273
  // src/shared/version.ts
263
- var VERSION = true ? "0.1.1" : "0.1.0";
274
+ var VERSION = true ? "0.3.0" : MIN_CLIENT_VERSION;
264
275
  var PROTOCOL = 1;
265
276
  function newer(a, b) {
266
277
  const x = a.split(".").map(Number), y = b.split(".").map(Number);
@@ -306,15 +317,16 @@ async function daemonConnection(options = {}) {
306
317
  { from: hello.version, to: VERSION, protocol: hello.protocol },
307
318
  options.home
308
319
  );
309
- await rpc.request("admin.shutdown", { reason: "upgrade", version: VERSION }, timeout);
310
- rpc.close();
311
- await sleep(100);
312
- continue;
320
+ throw new CmdrError(
321
+ "UPGRADE_REQUIRED",
322
+ `Daemon ${hello.version} is older than client ${VERSION}. Run cmdr daemon restart from this installation; automatic replacement is disabled to protect live sessions.`
323
+ );
313
324
  }
314
325
  return rpc;
315
326
  } catch (e) {
316
327
  rpc?.close();
317
- if (e.code === "PROTOCOL_MISMATCH" || !options.start) throw e;
328
+ if (e.code === "PROTOCOL_MISMATCH" || e.code === "UPGRADE_REQUIRED" || !options.start)
329
+ throw e;
318
330
  }
319
331
  if (!owner) {
320
332
  try {
@@ -328,7 +340,12 @@ async function daemonConnection(options = {}) {
328
340
  }
329
341
  }
330
342
  }
331
- if (owner) {
343
+ let daemonOwnsLock = false;
344
+ try {
345
+ daemonOwnsLock = alive(Number(readFileSync2(p.lock, "utf8")));
346
+ } catch {
347
+ }
348
+ if (owner && !daemonOwnsLock) {
332
349
  if (attempt === 0 || !spawned) {
333
350
  const child = spawn(
334
351
  process.execPath,
@@ -439,6 +456,173 @@ var DaemonClient = class {
439
456
  }
440
457
  };
441
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
+
550
+ // src/cli/tail.ts
551
+ async function tail(options) {
552
+ let after = options.after, stopped = false;
553
+ let connection;
554
+ const stop = () => {
555
+ stopped = true;
556
+ connection?.close();
557
+ };
558
+ process.on("SIGINT", stop);
559
+ process.on("SIGTERM", stop);
560
+ const show = (event) => {
561
+ if (typeof after === "number" && event.event_seq <= after) return;
562
+ process.stdout.write(
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, " ")}` : ""}
565
+ `
566
+ );
567
+ after = event.event_seq;
568
+ };
569
+ try {
570
+ do {
571
+ try {
572
+ const rpc = connection = await daemonConnection();
573
+ const closed = new Promise((resolve3) => rpc.once("close", resolve3));
574
+ await rpc.request("session.register", { kind: "cli" });
575
+ let replaying = true;
576
+ const buffer = [];
577
+ rpc.on("notification", (method, value) => {
578
+ if (method === "lifecycle.event") replaying ? buffer.push(value) : show(value);
579
+ });
580
+ let result = await rpc.request(options.follow ? "admin.tail" : "admin.events", {
581
+ ...options,
582
+ after
583
+ });
584
+ if (result.gap) {
585
+ const gap = { kind: "retention.gap", after, retained_after: result.retained_after };
586
+ if (options.json) process.stdout.write(JSON.stringify(gap) + "\n");
587
+ else
588
+ process.stderr.write(
589
+ `cmdr: event retention gap; events through ${result.retained_after} expired
590
+ `
591
+ );
592
+ }
593
+ for (; ; ) {
594
+ for (const event of result.events) show(event);
595
+ after = Math.max(typeof after === "number" ? after : 0, result.next);
596
+ if (result.next >= result.high) break;
597
+ result = await rpc.request("admin.events", { ...options, after });
598
+ }
599
+ replaying = false;
600
+ for (const event of buffer.sort((a, b) => a.event_seq - b.event_seq)) show(event);
601
+ if (!options.follow) rpc.close();
602
+ else await closed;
603
+ } catch (e) {
604
+ if (!options.follow || stopped) {
605
+ if (!stopped) throw e;
606
+ } else
607
+ process.stderr.write(
608
+ `cmdr tail: ${String(e)}; reconnecting after ${after ?? "latest"}
609
+ `
610
+ );
611
+ } finally {
612
+ connection?.close();
613
+ connection = void 0;
614
+ }
615
+ if (options.follow && !stopped) await new Promise((r) => setTimeout(r, 1e3));
616
+ } while (options.follow && !stopped);
617
+ } finally {
618
+ process.off("SIGINT", stop);
619
+ process.off("SIGTERM", stop);
620
+ }
621
+ }
622
+
623
+ // src/cli/session.ts
624
+ import { parseArgs } from "node:util";
625
+
442
626
  // node_modules/zod/v3/external.js
443
627
  var external_exports = {};
444
628
  __export(external_exports, {
@@ -4492,16 +4676,20 @@ var schemas = {
4492
4676
  squad: external_exports.string().optional(),
4493
4677
  name: external_exports.string().trim().min(1).max(64).optional(),
4494
4678
  note: text.optional(),
4495
- squad_name: external_exports.string().trim().min(1).max(64).optional()
4679
+ squad_name: external_exports.string().trim().min(1).max(64).optional(),
4680
+ takeover: external_exports.boolean().default(false),
4681
+ standby: external_exports.enum(["auto", "manual"]).optional(),
4682
+ rebind: external_exports.string().optional()
4496
4683
  }).strict(),
4497
4684
  list: external_exports.object({
4498
4685
  ...identity,
4686
+ full: external_exports.boolean().default(false),
4499
4687
  scope: external_exports.enum(["squad", "all"]).optional(),
4500
4688
  squad: external_exports.string().optional()
4501
4689
  }).strict(),
4502
4690
  report: external_exports.object({
4503
4691
  ...identity,
4504
- status: external_exports.enum(["ready", "working", "blocked", "done", "failed"]),
4692
+ status: external_exports.enum(["ready", "working", "blocked", "done", "failed", "cancelled"]),
4505
4693
  message: text,
4506
4694
  reply_to: external_exports.string().optional(),
4507
4695
  data
@@ -4511,7 +4699,10 @@ var schemas = {
4511
4699
  ...identity,
4512
4700
  to: external_exports.union([external_exports.string().min(1), external_exports.array(external_exports.string().min(1)).min(1).max(1e3)]),
4513
4701
  message: text,
4514
- type: external_exports.enum(["command", "answer", "info"]).default("command"),
4702
+ type: external_exports.enum(["command", "cancel", "answer", "info"]).default("command"),
4703
+ task_key: external_exports.string().min(1).max(128).optional(),
4704
+ reassign: external_exports.string().optional(),
4705
+ attention: external_exports.boolean().optional(),
4515
4706
  priority: external_exports.enum(["high", "normal", "low"]).optional(),
4516
4707
  reply_to: external_exports.string().optional(),
4517
4708
  data
@@ -4522,7 +4713,10 @@ var schemas = {
4522
4713
  limit: external_exports.number().int().min(1).max(100).default(20),
4523
4714
  peek: external_exports.boolean().default(false),
4524
4715
  history: external_exports.boolean().default(false),
4525
- since: external_exports.string().optional()
4716
+ since: external_exports.string().optional(),
4717
+ id: external_exports.string().optional(),
4718
+ recover: external_exports.boolean().default(false),
4719
+ full: external_exports.boolean().default(false)
4526
4720
  }).strict(),
4527
4721
  leave: external_exports.object({ ...identity, dissolve: external_exports.boolean().default(false), message: text.optional() }).strict()
4528
4722
  };
@@ -4591,6 +4785,16 @@ async function runSession(argv) {
4591
4785
  to: { type: "string" },
4592
4786
  type: { type: "string" },
4593
4787
  "reply-to": { type: "string" },
4788
+ priority: { type: "string" },
4789
+ "task-key": { type: "string" },
4790
+ reassign: { type: "string" },
4791
+ rebind: { type: "string" },
4792
+ takeover: { type: "boolean" },
4793
+ standby: { type: "string" },
4794
+ full: { type: "boolean" },
4795
+ recover: { type: "boolean" },
4796
+ id: { type: "string" },
4797
+ limit: { type: "string" },
4594
4798
  peek: { type: "boolean" },
4595
4799
  history: { type: "boolean" },
4596
4800
  dissolve: { type: "boolean" },
@@ -4600,7 +4804,7 @@ async function runSession(argv) {
4600
4804
  });
4601
4805
  if (v.help) {
4602
4806
  console.log(
4603
- "cmdr session join|list|send|report|ask|read|leave --agent HOST --native-id ID [--input JSON] [--timeout SECONDS]\nUse --squad-name for join; --status and text for report; --to and text for send; text for ask. read supports --wait/--peek/--history. IDs must match the host session; commands do not wake agents."
4807
+ "cmdr session join|list|send|report|ask|read|leave --agent HOST --native-id ID [--input JSON] [--timeout SECONDS]\nUse --squad-name for join; --status and text for report; --to and text for send; text for ask. read supports --wait/--peek/--history. IDs must match the host session; read also supports --recover/--id/--full/--limit. Configure automatic wake with cmdr standby start --session SID; unsupported hosts remain manual."
4604
4808
  );
4605
4809
  return;
4606
4810
  }
@@ -4631,12 +4835,22 @@ async function runSession(argv) {
4631
4835
  to: "to",
4632
4836
  type: "type",
4633
4837
  "reply-to": "reply_to",
4838
+ priority: "priority",
4839
+ "task-key": "task_key",
4840
+ reassign: "reassign",
4841
+ rebind: "rebind",
4842
+ takeover: "takeover",
4843
+ standby: "standby",
4844
+ full: "full",
4845
+ recover: "recover",
4846
+ id: "id",
4634
4847
  peek: "peek",
4635
4848
  history: "history",
4636
4849
  dissolve: "dissolve"
4637
4850
  };
4638
4851
  for (const [flag, field] of Object.entries(mapping))
4639
4852
  if (v[flag] !== void 0) input[field] = v[flag];
4853
+ if (v.limit !== void 0) input.limit = Number(v.limit);
4640
4854
  if (v.all) input.scope = "all";
4641
4855
  if (v.wait !== void 0) input.wait = Number(v.wait);
4642
4856
  if (args.length > 1) input[action === "ask" ? "question" : "message"] = args.slice(1).join(" ");
@@ -4646,6 +4860,7 @@ async function runSession(argv) {
4646
4860
  throw new Error("--timeout must be >0 and <=3600 seconds");
4647
4861
  client = new DaemonClient({
4648
4862
  kind: "mcp",
4863
+ transport: "cli",
4649
4864
  agent,
4650
4865
  native_id: native,
4651
4866
  cwd: process.cwd(),
@@ -4794,7 +5009,7 @@ async function probeMcp(root) {
4794
5009
  }
4795
5010
 
4796
5011
  // src/cli/main.ts
4797
- import { readFileSync as readFileSync2, existsSync } from "node:fs";
5012
+ import { readFileSync as readFileSync3, existsSync } from "node:fs";
4798
5013
  import { dirname as dirname2, join as join5, resolve as resolve2 } from "node:path";
4799
5014
  import { homedir as homedir2 } from "node:os";
4800
5015
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -4814,6 +5029,23 @@ if (process.argv[2] === "session") {
4814
5029
  to: { type: "string" },
4815
5030
  type: { type: "string" },
4816
5031
  "reply-to": { type: "string" },
5032
+ priority: { type: "string" },
5033
+ "task-key": { type: "string" },
5034
+ reassign: { type: "string" },
5035
+ after: { type: "string" },
5036
+ for: { type: "string" },
5037
+ adapter: { type: "string" },
5038
+ transport: { type: "string" },
5039
+ actionable: { type: "boolean" },
5040
+ once: { type: "boolean" },
5041
+ format: { type: "string" },
5042
+ executable: { type: "string" },
5043
+ socket: { type: "string" },
5044
+ resolve: { type: "string" },
5045
+ recover: { type: "boolean" },
5046
+ history: { type: "boolean" },
5047
+ id: { type: "string" },
5048
+ limit: { type: "string" },
4817
5049
  session: { type: "string" },
4818
5050
  peek: { type: "boolean" },
4819
5051
  follow: { type: "boolean" },
@@ -4864,7 +5096,7 @@ if (process.argv[2] === "session") {
4864
5096
  checks.daemon = "not running";
4865
5097
  }
4866
5098
  try {
4867
- const conf = readFileSync2(
5099
+ const conf = readFileSync3(
4868
5100
  join5(process.env.CODEX_HOME || join5(homedir2(), ".codex"), "config.toml"),
4869
5101
  "utf8"
4870
5102
  );
@@ -4899,7 +5131,7 @@ if (process.argv[2] === "session") {
4899
5131
  } else
4900
5132
  checks.zcode = "Desktop app not found in /Applications; generic MCP configuration is available.";
4901
5133
  try {
4902
- const zconfig = JSON.parse(readFileSync2(join5(homedir2(), ".zcode/cli/config.json"), "utf8"));
5134
+ const zconfig = JSON.parse(readFileSync3(join5(homedir2(), ".zcode/cli/config.json"), "utf8"));
4903
5135
  checks.zcode_user_hooks = zconfig.hooks?.enabled === true;
4904
5136
  } catch {
4905
5137
  checks.zcode_user_hooks = "No user hook config; installed plugin hooks follow plugin enablement.";
@@ -4909,7 +5141,7 @@ if (process.argv[2] === "session") {
4909
5141
  try {
4910
5142
  if (v.help)
4911
5143
  process.stdout.write(
4912
- "cmdr status | list [--all] [--squad ID] | tail [--follow] [--full] | send --squad ID [--to MEMBER] [--type command|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"
4913
5145
  );
4914
5146
  else if (cmd === "config") {
4915
5147
  const agent = v.agent || "generic";
@@ -4933,7 +5165,8 @@ if (process.argv[2] === "session") {
4933
5165
  else if (cmd === "list") {
4934
5166
  const result = await call("session.list", {
4935
5167
  scope: v.all ? "all" : void 0,
4936
- squad: v.squad
5168
+ squad: v.squad,
5169
+ full: !!v.full
4937
5170
  });
4938
5171
  if (v.json) print(result);
4939
5172
  else {
@@ -4945,11 +5178,16 @@ if (process.argv[2] === "session") {
4945
5178
  title: s.title,
4946
5179
  role: s.role,
4947
5180
  squad: s.squad,
4948
- presence: s.presence,
5181
+ work: s.commands.map((m) => `${m.id}:${m.state}${m.cancel_requested_at ? ":cancelling" : ""}`).join(", "),
5182
+ unacked: s.unacked,
5183
+ in_progress: s.in_progress,
4949
5184
  activity: s.activity,
5185
+ progress_seconds_ago: s.last_progress_at ? Math.floor((Date.now() - s.last_progress_at) / 1e3) : "unknown",
5186
+ connection: s.presence,
4950
5187
  pending: s.pending,
5188
+ wake: `${s.listener.wake_mode}/${s.listener.health}`,
4951
5189
  identity: s.native_id ? "confirmed" : "provisional",
4952
- age_ms: Date.now() - s.created_at,
5190
+ seen_seconds_ago: Math.floor((Date.now() - s.last_seen) / 1e3),
4953
5191
  cwd: s.cwd,
4954
5192
  terminal: s.terminal?.program
4955
5193
  }))
@@ -4972,6 +5210,9 @@ if (process.argv[2] === "session") {
4972
5210
  to: v.to || "all",
4973
5211
  type: v.type || "command",
4974
5212
  reply_to: v["reply-to"],
5213
+ priority: v.priority,
5214
+ reassign: v.reassign,
5215
+ task_key: v["task-key"],
4975
5216
  message: args.slice(1).join(" ")
4976
5217
  },
4977
5218
  true
@@ -4979,26 +5220,71 @@ if (process.argv[2] === "session") {
4979
5220
  );
4980
5221
  else if (cmd === "read") {
4981
5222
  if (!v.session) throw new Error("--session SID is required");
4982
- print(await call("admin.read", { sid: v.session, options: { peek: !!v.peek } }));
5223
+ print(
5224
+ await call("admin.read", {
5225
+ sid: v.session,
5226
+ options: {
5227
+ peek: !!v.peek,
5228
+ history: !!v.history,
5229
+ full: !!v.full,
5230
+ recover: !!v.recover,
5231
+ id: v.id,
5232
+ limit: v.limit ? Number(v.limit) : void 0
5233
+ }
5234
+ })
5235
+ );
4983
5236
  } else if (cmd === "purge") print(await call("admin.purge", { all: !!v.all }));
4984
- else if (cmd === "tail") {
4985
- const rpc = await daemonConnection();
4986
- await rpc.request("session.register", { kind: "cli" });
4987
- if (v.follow) {
4988
- rpc.on("notification", (method, value) => {
4989
- if (method === "msg.event") print(value);
4990
- });
4991
- await rpc.request("admin.tail", { squad: v.squad, full: !!v.full });
4992
- }
4993
- print(await rpc.request("admin.recent", { squad: v.squad, full: !!v.full }));
4994
- if (!v.follow) rpc.close();
4995
- else process.on("SIGINT", () => rpc.close());
5237
+ else if (cmd === "standby") {
5238
+ if (!v.session) throw new Error("--session SID is required");
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
+ );
5256
+ } else if (cmd === "tail") {
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");
5262
+ await tail({
5263
+ squad: v.squad,
5264
+ for: v.for,
5265
+ after,
5266
+ full: !!v.full,
5267
+ json: !!v.json || v.format === "json",
5268
+ line: v.format === "line",
5269
+ actionable: !!v.actionable,
5270
+ follow: !!v.follow
5271
+ });
4996
5272
  } else if (cmd === "daemon") {
4997
5273
  const action = args[1] || "status";
4998
5274
  if (action === "logs")
4999
- process.stdout.write(existsSync(p.log) ? readFileSync2(p.log, "utf8") : "No daemon logs.\n");
5275
+ process.stdout.write(existsSync(p.log) ? readFileSync3(p.log, "utf8") : "No daemon logs.\n");
5000
5276
  else if (action === "status") print(await call("admin.status"));
5001
5277
  else if (action === "stop" || action === "restart") {
5278
+ if (action === "restart")
5279
+ execFileSync(
5280
+ process.execPath,
5281
+ [
5282
+ "--experimental-sqlite",
5283
+ join5(dirname2(fileURLToPath3(import.meta.url)), "daemon.mjs"),
5284
+ "--preflight"
5285
+ ],
5286
+ { timeout: 15e3, stdio: ["ignore", "pipe", "pipe"] }
5287
+ );
5002
5288
  try {
5003
5289
  print(await call("admin.shutdown", { reason: action }));
5004
5290
  } catch (e) {