@h-rig/cli 0.0.6-alpha.35 → 0.0.6-alpha.36

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/rig.js CHANGED
@@ -6398,7 +6398,24 @@ async function executeInspect(context, args) {
6398
6398
  const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
6399
6399
  const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6400
6400
  if (!latestRun) {
6401
- throw new CliError2(`No runs found for ${requiredTask}.`);
6401
+ const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
6402
+ const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6403
+ if (!serverRun || typeof serverRun.runId !== "string") {
6404
+ throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
6405
+ }
6406
+ const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
6407
+ const entries = Array.isArray(page.entries) ? page.entries : [];
6408
+ if (context.outputMode === "text") {
6409
+ for (const entry of entries) {
6410
+ const record = entry && typeof entry === "object" ? entry : {};
6411
+ const title = String(record.title ?? "");
6412
+ const detail = String(record.detail ?? "");
6413
+ console.log([title, detail].filter(Boolean).join(" \u2014 "));
6414
+ }
6415
+ if (entries.length === 0)
6416
+ console.log(`(no log entries for run ${serverRun.runId})`);
6417
+ }
6418
+ return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
6402
6419
  }
6403
6420
  const logsPath = resolve21(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
6404
6421
  if (!existsSync13(logsPath)) {
@@ -7683,7 +7700,38 @@ function parseWsPayload(message2) {
7683
7700
  return JSON.parse(message2.data);
7684
7701
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
7685
7702
  }
7686
- async function connectWorkerStream(options, ctx, state) {
7703
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
7704
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
7705
+ for (const command of commands) {
7706
+ const record = recordOf(command);
7707
+ const name = typeof record?.name === "string" ? record.name : "";
7708
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
7709
+ continue;
7710
+ registered.add(name);
7711
+ const description = typeof record?.description === "string" ? record.description : undefined;
7712
+ const source = typeof record?.source === "string" ? record.source : "worker";
7713
+ try {
7714
+ pi.registerCommand(name, {
7715
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
7716
+ handler: async (args) => {
7717
+ const text2 = `/${name}${args ? ` ${args}` : ""}`;
7718
+ appendTranscript(state, "You", text2);
7719
+ try {
7720
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text2);
7721
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
7722
+ appendTranscript(state, "System", message2);
7723
+ if (state.nativeStream)
7724
+ ctx.ui.notify(message2, "info");
7725
+ } catch (error) {
7726
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
7727
+ }
7728
+ updatePiUi(ctx, state);
7729
+ }
7730
+ });
7731
+ } catch {}
7732
+ }
7733
+ }
7734
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
7687
7735
  const ready = await waitForWorkerReady(options, ctx, state);
7688
7736
  if (!ready)
7689
7737
  return;
@@ -7738,6 +7786,7 @@ async function connectWorkerStream(options, ctx, state) {
7738
7786
  const record = recordOf(command);
7739
7787
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
7740
7788
  });
7789
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
7741
7790
  catchupDone = true;
7742
7791
  for (const payload of buffered.splice(0))
7743
7792
  applyEnvelope(ctx, state, payload);
@@ -7865,6 +7914,7 @@ function createRigWorkerPiBridgeExtension(options) {
7865
7914
  };
7866
7915
  if (options.initialMessageSent)
7867
7916
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
7917
+ const registeredDaemonCommands = new Set;
7868
7918
  let nativePiUiContextAvailable = false;
7869
7919
  pi.on("user_bash", (event) => {
7870
7920
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -7897,7 +7947,7 @@ function createRigWorkerPiBridgeExtension(options) {
7897
7947
  });
7898
7948
  return { consume: true };
7899
7949
  });
7900
- connectWorkerStream(options, ctx, state).catch((error) => {
7950
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
7901
7951
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
7902
7952
  updatePiUi(ctx, state);
7903
7953
  });
@@ -7944,8 +7994,6 @@ async function attachRunBundledPiFrontend(context, input) {
7944
7994
  "--no-tools",
7945
7995
  "--no-builtin-tools",
7946
7996
  "--no-skills",
7947
- "--no-prompt-templates",
7948
- "--no-themes",
7949
7997
  "--no-context-files",
7950
7998
  "--no-approve"
7951
7999
  ], {
@@ -8490,6 +8538,7 @@ async function executeRun(context, args) {
8490
8538
 
8491
8539
  // packages/cli/src/commands/server.ts
8492
8540
  init_runner();
8541
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
8493
8542
  async function executeServer(context, args, options) {
8494
8543
  const [command = "status", ...rest] = args;
8495
8544
  if (["status", "list", "add", "use"].includes(command)) {
@@ -8507,7 +8556,8 @@ async function executeServer(context, args, options) {
8507
8556
  const authTokenResult = takeOption(pending, "--auth-token");
8508
8557
  pending = authTokenResult.rest;
8509
8558
  requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
8510
- const commandParts = ["rig-server", "start"];
8559
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8560
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
8511
8561
  if (hostResult.value) {
8512
8562
  commandParts.push("--host", hostResult.value);
8513
8563
  }
@@ -8530,7 +8580,8 @@ async function executeServer(context, args, options) {
8530
8580
  const eventResult = takeOption(pending, "--event");
8531
8581
  pending = eventResult.rest;
8532
8582
  requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
8533
- const commandParts = ["rig-server", "notify-test"];
8583
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8584
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
8534
8585
  if (eventResult.value) {
8535
8586
  commandParts.push("--event", eventResult.value);
8536
8587
  }
@@ -802,7 +802,38 @@ function parseWsPayload(message) {
802
802
  return JSON.parse(message.data);
803
803
  return JSON.parse(Buffer.from(message.data).toString("utf8"));
804
804
  }
805
- async function connectWorkerStream(options, ctx, state) {
805
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
806
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
807
+ for (const command of commands) {
808
+ const record = recordOf(command);
809
+ const name = typeof record?.name === "string" ? record.name : "";
810
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
811
+ continue;
812
+ registered.add(name);
813
+ const description = typeof record?.description === "string" ? record.description : undefined;
814
+ const source = typeof record?.source === "string" ? record.source : "worker";
815
+ try {
816
+ pi.registerCommand(name, {
817
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
818
+ handler: async (args) => {
819
+ const text = `/${name}${args ? ` ${args}` : ""}`;
820
+ appendTranscript(state, "You", text);
821
+ try {
822
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text);
823
+ const message = typeof result.message === "string" ? result.message : "worker command accepted";
824
+ appendTranscript(state, "System", message);
825
+ if (state.nativeStream)
826
+ ctx.ui.notify(message, "info");
827
+ } catch (error) {
828
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
829
+ }
830
+ updatePiUi(ctx, state);
831
+ }
832
+ });
833
+ } catch {}
834
+ }
835
+ }
836
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
806
837
  const ready = await waitForWorkerReady(options, ctx, state);
807
838
  if (!ready)
808
839
  return;
@@ -857,6 +888,7 @@ async function connectWorkerStream(options, ctx, state) {
857
888
  const record = recordOf(command);
858
889
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
859
890
  });
891
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
860
892
  catchupDone = true;
861
893
  for (const payload of buffered.splice(0))
862
894
  applyEnvelope(ctx, state, payload);
@@ -984,6 +1016,7 @@ function createRigWorkerPiBridgeExtension(options) {
984
1016
  };
985
1017
  if (options.initialMessageSent)
986
1018
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
1019
+ const registeredDaemonCommands = new Set;
987
1020
  let nativePiUiContextAvailable = false;
988
1021
  pi.on("user_bash", (event) => {
989
1022
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -1016,7 +1049,7 @@ function createRigWorkerPiBridgeExtension(options) {
1016
1049
  });
1017
1050
  return { consume: true };
1018
1051
  });
1019
- connectWorkerStream(options, ctx, state).catch((error) => {
1052
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
1020
1053
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
1021
1054
  updatePiUi(ctx, state);
1022
1055
  });
@@ -1063,8 +1096,6 @@ async function attachRunBundledPiFrontend(context, input) {
1063
1096
  "--no-tools",
1064
1097
  "--no-builtin-tools",
1065
1098
  "--no-skills",
1066
- "--no-prompt-templates",
1067
- "--no-themes",
1068
1099
  "--no-context-files",
1069
1100
  "--no-approve"
1070
1101
  ], {
@@ -576,7 +576,38 @@ function parseWsPayload(message) {
576
576
  return JSON.parse(message.data);
577
577
  return JSON.parse(Buffer.from(message.data).toString("utf8"));
578
578
  }
579
- async function connectWorkerStream(options, ctx, state) {
579
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
580
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
581
+ for (const command of commands) {
582
+ const record = recordOf(command);
583
+ const name = typeof record?.name === "string" ? record.name : "";
584
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
585
+ continue;
586
+ registered.add(name);
587
+ const description = typeof record?.description === "string" ? record.description : undefined;
588
+ const source = typeof record?.source === "string" ? record.source : "worker";
589
+ try {
590
+ pi.registerCommand(name, {
591
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
592
+ handler: async (args) => {
593
+ const text = `/${name}${args ? ` ${args}` : ""}`;
594
+ appendTranscript(state, "You", text);
595
+ try {
596
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text);
597
+ const message = typeof result.message === "string" ? result.message : "worker command accepted";
598
+ appendTranscript(state, "System", message);
599
+ if (state.nativeStream)
600
+ ctx.ui.notify(message, "info");
601
+ } catch (error) {
602
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
603
+ }
604
+ updatePiUi(ctx, state);
605
+ }
606
+ });
607
+ } catch {}
608
+ }
609
+ }
610
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
580
611
  const ready = await waitForWorkerReady(options, ctx, state);
581
612
  if (!ready)
582
613
  return;
@@ -631,6 +662,7 @@ async function connectWorkerStream(options, ctx, state) {
631
662
  const record = recordOf(command);
632
663
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
633
664
  });
665
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
634
666
  catchupDone = true;
635
667
  for (const payload of buffered.splice(0))
636
668
  applyEnvelope(ctx, state, payload);
@@ -758,6 +790,7 @@ function createRigWorkerPiBridgeExtension(options) {
758
790
  };
759
791
  if (options.initialMessageSent)
760
792
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
793
+ const registeredDaemonCommands = new Set;
761
794
  let nativePiUiContextAvailable = false;
762
795
  pi.on("user_bash", (event) => {
763
796
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -790,7 +823,7 @@ function createRigWorkerPiBridgeExtension(options) {
790
823
  });
791
824
  return { consume: true };
792
825
  });
793
- connectWorkerStream(options, ctx, state).catch((error) => {
826
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
794
827
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
795
828
  updatePiUi(ctx, state);
796
829
  });
@@ -837,8 +870,6 @@ async function attachRunBundledPiFrontend(context, input) {
837
870
  "--no-tools",
838
871
  "--no-builtin-tools",
839
872
  "--no-skills",
840
- "--no-prompt-templates",
841
- "--no-themes",
842
873
  "--no-context-files",
843
874
  "--no-approve"
844
875
  ], {
@@ -566,7 +566,38 @@ function parseWsPayload(message) {
566
566
  return JSON.parse(message.data);
567
567
  return JSON.parse(Buffer.from(message.data).toString("utf8"));
568
568
  }
569
- async function connectWorkerStream(options, ctx, state) {
569
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
570
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
571
+ for (const command of commands) {
572
+ const record = recordOf(command);
573
+ const name = typeof record?.name === "string" ? record.name : "";
574
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
575
+ continue;
576
+ registered.add(name);
577
+ const description = typeof record?.description === "string" ? record.description : undefined;
578
+ const source = typeof record?.source === "string" ? record.source : "worker";
579
+ try {
580
+ pi.registerCommand(name, {
581
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
582
+ handler: async (args) => {
583
+ const text = `/${name}${args ? ` ${args}` : ""}`;
584
+ appendTranscript(state, "You", text);
585
+ try {
586
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text);
587
+ const message = typeof result.message === "string" ? result.message : "worker command accepted";
588
+ appendTranscript(state, "System", message);
589
+ if (state.nativeStream)
590
+ ctx.ui.notify(message, "info");
591
+ } catch (error) {
592
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
593
+ }
594
+ updatePiUi(ctx, state);
595
+ }
596
+ });
597
+ } catch {}
598
+ }
599
+ }
600
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
570
601
  const ready = await waitForWorkerReady(options, ctx, state);
571
602
  if (!ready)
572
603
  return;
@@ -621,6 +652,7 @@ async function connectWorkerStream(options, ctx, state) {
621
652
  const record = recordOf(command);
622
653
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
623
654
  });
655
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
624
656
  catchupDone = true;
625
657
  for (const payload of buffered.splice(0))
626
658
  applyEnvelope(ctx, state, payload);
@@ -748,6 +780,7 @@ function createRigWorkerPiBridgeExtension(options) {
748
780
  };
749
781
  if (options.initialMessageSent)
750
782
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
783
+ const registeredDaemonCommands = new Set;
751
784
  let nativePiUiContextAvailable = false;
752
785
  pi.on("user_bash", (event) => {
753
786
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -780,7 +813,7 @@ function createRigWorkerPiBridgeExtension(options) {
780
813
  });
781
814
  return { consume: true };
782
815
  });
783
- connectWorkerStream(options, ctx, state).catch((error) => {
816
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
784
817
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
785
818
  updatePiUi(ctx, state);
786
819
  });
@@ -416,14 +416,6 @@ async function runRunPiCommandViaServer(context, runId, text) {
416
416
  });
417
417
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { type: "done" };
418
418
  }
419
- async function respondRunPiCommandViaServer(context, runId, requestId, value) {
420
- const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/pi/commands/respond`, {
421
- method: "POST",
422
- headers: { "content-type": "application/json" },
423
- body: JSON.stringify({ requestId, value })
424
- });
425
- return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { type: "done" };
426
- }
427
419
  async function respondRunPiExtensionUiViaServer(context, runId, requestId, valueOrCancel) {
428
420
  const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/pi/extension-ui/respond`, {
429
421
  method: "POST",
@@ -487,7 +479,6 @@ export {
487
479
  selectNextWorkspaceTaskViaServer,
488
480
  runRunPiCommandViaServer,
489
481
  respondRunPiExtensionUiViaServer,
490
- respondRunPiCommandViaServer,
491
482
  requestServerJson,
492
483
  registerProjectViaServer,
493
484
  prepareRemoteCheckoutViaServer,
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/inspect.ts
3
- import { existsSync, readFileSync } from "fs";
4
- import { resolve } from "path";
3
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
4
+ import { resolve as resolve3 } from "path";
5
5
 
6
6
  // packages/cli/src/runner.ts
7
7
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
@@ -53,6 +53,205 @@ import {
53
53
  import { changedFilesForTask } from "@rig/runtime/control-plane/native/task-ops";
54
54
  import { resolveHarnessPaths, resolveMonorepoRoot, runCapture } from "@rig/runtime/control-plane/native/utils";
55
55
  import { readTaskArtifactPreview } from "@rig/runtime/control-plane/native/workspace-ops";
56
+
57
+ // packages/cli/src/commands/_server-client.ts
58
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
59
+ import { resolve as resolve2 } from "path";
60
+ import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
61
+
62
+ // packages/cli/src/commands/_connection-state.ts
63
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
64
+ import { homedir } from "os";
65
+ import { dirname, resolve } from "path";
66
+ function resolveGlobalConnectionsPath(env = process.env) {
67
+ const explicit = env.RIG_CONNECTIONS_FILE?.trim();
68
+ if (explicit)
69
+ return resolve(explicit);
70
+ const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
71
+ if (stateDir)
72
+ return resolve(stateDir, "connections.json");
73
+ return resolve(homedir(), ".rig", "connections.json");
74
+ }
75
+ function resolveRepoConnectionPath(projectRoot) {
76
+ return resolve(projectRoot, ".rig", "state", "connection.json");
77
+ }
78
+ function readJsonFile(path) {
79
+ if (!existsSync(path))
80
+ return null;
81
+ try {
82
+ return JSON.parse(readFileSync(path, "utf8"));
83
+ } catch (error) {
84
+ throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
85
+ }
86
+ }
87
+ function normalizeConnection(value) {
88
+ if (!value || typeof value !== "object" || Array.isArray(value))
89
+ return null;
90
+ const record = value;
91
+ if (record.kind === "local")
92
+ return { kind: "local", mode: "auto" };
93
+ if (record.kind === "remote" && typeof record.baseUrl === "string" && record.baseUrl.trim()) {
94
+ const baseUrl = record.baseUrl.trim().replace(/\/+$/, "");
95
+ return { kind: "remote", baseUrl };
96
+ }
97
+ return null;
98
+ }
99
+ function readGlobalConnections(options = {}) {
100
+ const path = resolveGlobalConnectionsPath(options.env ?? process.env);
101
+ const payload = readJsonFile(path);
102
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
103
+ return { connections: {} };
104
+ }
105
+ const rawConnections = payload.connections;
106
+ const connections = {};
107
+ if (rawConnections && typeof rawConnections === "object" && !Array.isArray(rawConnections)) {
108
+ for (const [alias, raw] of Object.entries(rawConnections)) {
109
+ const connection = normalizeConnection(raw);
110
+ if (connection)
111
+ connections[alias] = connection;
112
+ }
113
+ }
114
+ return { connections };
115
+ }
116
+ function readRepoConnection(projectRoot) {
117
+ const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
118
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
119
+ return null;
120
+ const record = payload;
121
+ const selected = typeof record.selected === "string" ? record.selected.trim() : "";
122
+ if (!selected)
123
+ return null;
124
+ return {
125
+ selected,
126
+ project: typeof record.project === "string" ? record.project : undefined,
127
+ linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
128
+ };
129
+ }
130
+ function resolveSelectedConnection(projectRoot, options = {}) {
131
+ const repo = readRepoConnection(projectRoot);
132
+ if (!repo)
133
+ return null;
134
+ if (repo.selected === "local")
135
+ return { alias: "local", connection: { kind: "local", mode: "auto" } };
136
+ const global = readGlobalConnections(options);
137
+ const connection = global.connections[repo.selected];
138
+ if (!connection) {
139
+ throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
140
+ }
141
+ return { alias: repo.selected, connection };
142
+ }
143
+
144
+ // packages/cli/src/commands/_server-client.ts
145
+ var scopedGitHubBearerTokens = new Map;
146
+ function cleanToken(value) {
147
+ const trimmed = value?.trim();
148
+ return trimmed ? trimmed : null;
149
+ }
150
+ function readPrivateRemoteSessionToken(projectRoot) {
151
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
152
+ if (!existsSync2(path))
153
+ return null;
154
+ try {
155
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
156
+ return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
157
+ } catch {
158
+ return null;
159
+ }
160
+ }
161
+ function readGitHubBearerTokenForRemote(projectRoot) {
162
+ const scopedKey = resolve2(projectRoot);
163
+ if (scopedGitHubBearerTokens.has(scopedKey))
164
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
165
+ const privateSession = readPrivateRemoteSessionToken(projectRoot);
166
+ if (privateSession)
167
+ return privateSession;
168
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
169
+ }
170
+ async function ensureServerForCli(projectRoot) {
171
+ try {
172
+ const selected = resolveSelectedConnection(projectRoot);
173
+ if (selected?.connection.kind === "remote") {
174
+ return {
175
+ baseUrl: selected.connection.baseUrl,
176
+ authToken: readGitHubBearerTokenForRemote(projectRoot),
177
+ connectionKind: "remote"
178
+ };
179
+ }
180
+ const connection = await ensureLocalRigServerConnection(projectRoot);
181
+ return {
182
+ baseUrl: connection.baseUrl,
183
+ authToken: connection.authToken,
184
+ connectionKind: "local"
185
+ };
186
+ } catch (error) {
187
+ if (error instanceof Error) {
188
+ throw new CliError2(error.message, 1);
189
+ }
190
+ throw error;
191
+ }
192
+ }
193
+ function mergeHeaders(headers, authToken) {
194
+ const merged = new Headers(headers);
195
+ if (authToken) {
196
+ merged.set("authorization", `Bearer ${authToken}`);
197
+ }
198
+ return merged;
199
+ }
200
+ function diagnosticMessage(payload) {
201
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
202
+ return null;
203
+ const record = payload;
204
+ const diagnostics = Array.isArray(record.diagnostics) ? record.diagnostics : [];
205
+ const messages = diagnostics.flatMap((entry) => {
206
+ if (!entry || typeof entry !== "object" || Array.isArray(entry))
207
+ return [];
208
+ const diagnostic = entry;
209
+ const kind = typeof diagnostic.kind === "string" ? diagnostic.kind : "task-source";
210
+ const message = typeof diagnostic.message === "string" ? diagnostic.message : null;
211
+ return message ? [`${kind}: ${message}`] : [];
212
+ });
213
+ return messages.length > 0 ? messages.join("; ") : null;
214
+ }
215
+ async function requestServerJson(context, pathname, init = {}) {
216
+ const server = await ensureServerForCli(context.projectRoot);
217
+ const response = await fetch(`${server.baseUrl}${pathname}`, {
218
+ ...init,
219
+ headers: mergeHeaders(init.headers, server.authToken)
220
+ });
221
+ const text = await response.text();
222
+ const payload = text.trim().length > 0 ? (() => {
223
+ try {
224
+ return JSON.parse(text);
225
+ } catch {
226
+ return null;
227
+ }
228
+ })() : null;
229
+ if (!response.ok) {
230
+ const diagnostics = diagnosticMessage(payload);
231
+ const detail = diagnostics ?? (text || response.statusText);
232
+ throw new CliError2(`Rig server request failed (${response.status}): ${detail}`, 1);
233
+ }
234
+ return payload;
235
+ }
236
+ async function listRunsViaServer(context, options = {}) {
237
+ const url = new URL("http://rig.local/api/runs");
238
+ if (options.limit !== undefined)
239
+ url.searchParams.set("limit", String(options.limit));
240
+ const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
241
+ const runs = Array.isArray(payload) ? payload : payload && typeof payload === "object" && !Array.isArray(payload) && Array.isArray(payload.runs) ? payload.runs : [];
242
+ return runs.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry)));
243
+ }
244
+ async function getRunLogsViaServer(context, runId, options = {}) {
245
+ const url = new URL(`http://rig.local/api/runs/${encodeURIComponent(runId)}/logs`);
246
+ if (options.limit !== undefined)
247
+ url.searchParams.set("limit", String(options.limit));
248
+ if (options.cursor)
249
+ url.searchParams.set("cursor", options.cursor);
250
+ const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
251
+ return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { entries: [] };
252
+ }
253
+
254
+ // packages/cli/src/commands/inspect.ts
56
255
  async function executeInspect(context, args) {
57
256
  const [command = "failures", ...rest] = args;
58
257
  switch (command) {
@@ -62,10 +261,27 @@ async function executeInspect(context, args) {
62
261
  const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
63
262
  const latestRun = listAuthorityRuns(context.projectRoot).map((entry) => readAuthorityRun(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
64
263
  if (!latestRun) {
65
- throw new CliError2(`No runs found for ${requiredTask}.`);
264
+ const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
265
+ const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
266
+ if (!serverRun || typeof serverRun.runId !== "string") {
267
+ throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
268
+ }
269
+ const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
270
+ const entries = Array.isArray(page.entries) ? page.entries : [];
271
+ if (context.outputMode === "text") {
272
+ for (const entry of entries) {
273
+ const record = entry && typeof entry === "object" ? entry : {};
274
+ const title = String(record.title ?? "");
275
+ const detail = String(record.detail ?? "");
276
+ console.log([title, detail].filter(Boolean).join(" \u2014 "));
277
+ }
278
+ if (entries.length === 0)
279
+ console.log(`(no log entries for run ${serverRun.runId})`);
280
+ }
281
+ return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
66
282
  }
67
- const logsPath = resolve(resolveAuthorityRunDir(context.projectRoot, latestRun.runId), "logs.jsonl");
68
- if (!existsSync(logsPath)) {
283
+ const logsPath = resolve3(resolveAuthorityRunDir(context.projectRoot, latestRun.runId), "logs.jsonl");
284
+ if (!existsSync3(logsPath)) {
69
285
  throw new CliError2(`No logs found for run ${latestRun.runId}.`);
70
286
  }
71
287
  await context.runCommand(["cat", logsPath]);
@@ -75,7 +291,7 @@ async function executeInspect(context, args) {
75
291
  const { value: task, rest: remaining } = takeOption(rest, "--task");
76
292
  requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
77
293
  const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
78
- const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync(path));
294
+ const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync3(path));
79
295
  if (!artifactRoot) {
80
296
  throw new CliError2(`No artifacts found for ${requiredTask}.`);
81
297
  }
@@ -132,10 +348,10 @@ async function executeInspect(context, args) {
132
348
  case "failures": {
133
349
  requireNoExtraArgs(rest, "rig inspect failures");
134
350
  const failed = resolveHarnessPaths(context.projectRoot).failedApproachesPath;
135
- if (!existsSync(failed)) {
351
+ if (!existsSync3(failed)) {
136
352
  console.log("No failures recorded.");
137
353
  } else {
138
- process.stdout.write(readFileSync(failed, "utf-8"));
354
+ process.stdout.write(readFileSync3(failed, "utf-8"));
139
355
  }
140
356
  return { ok: true, group: "inspect", command };
141
357
  }
@@ -152,11 +368,11 @@ async function executeInspect(context, args) {
152
368
  return { ok: true, group: "inspect", command };
153
369
  case "audit": {
154
370
  requireNoExtraArgs(rest, "rig inspect audit");
155
- const auditPath = resolve(resolveHarnessPaths(context.projectRoot).logsDir, "audit.jsonl");
156
- if (!existsSync(auditPath)) {
371
+ const auditPath = resolve3(resolveHarnessPaths(context.projectRoot).logsDir, "audit.jsonl");
372
+ if (!existsSync3(auditPath)) {
157
373
  console.log("No audit log found.");
158
374
  } else {
159
- const lines = readFileSync(auditPath, "utf-8").split(/\r?\n/).filter(Boolean).slice(-20);
375
+ const lines = readFileSync3(auditPath, "utf-8").split(/\r?\n/).filter(Boolean).slice(-20);
160
376
  for (const line of lines) {
161
377
  console.log(line);
162
378
  }
@@ -880,7 +880,38 @@ function parseWsPayload(message) {
880
880
  return JSON.parse(message.data);
881
881
  return JSON.parse(Buffer.from(message.data).toString("utf8"));
882
882
  }
883
- async function connectWorkerStream(options, ctx, state) {
883
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
884
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
885
+ for (const command of commands) {
886
+ const record = recordOf(command);
887
+ const name = typeof record?.name === "string" ? record.name : "";
888
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
889
+ continue;
890
+ registered.add(name);
891
+ const description = typeof record?.description === "string" ? record.description : undefined;
892
+ const source = typeof record?.source === "string" ? record.source : "worker";
893
+ try {
894
+ pi.registerCommand(name, {
895
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
896
+ handler: async (args) => {
897
+ const text = `/${name}${args ? ` ${args}` : ""}`;
898
+ appendTranscript(state, "You", text);
899
+ try {
900
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text);
901
+ const message = typeof result.message === "string" ? result.message : "worker command accepted";
902
+ appendTranscript(state, "System", message);
903
+ if (state.nativeStream)
904
+ ctx.ui.notify(message, "info");
905
+ } catch (error) {
906
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
907
+ }
908
+ updatePiUi(ctx, state);
909
+ }
910
+ });
911
+ } catch {}
912
+ }
913
+ }
914
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
884
915
  const ready = await waitForWorkerReady(options, ctx, state);
885
916
  if (!ready)
886
917
  return;
@@ -935,6 +966,7 @@ async function connectWorkerStream(options, ctx, state) {
935
966
  const record = recordOf(command);
936
967
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
937
968
  });
969
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
938
970
  catchupDone = true;
939
971
  for (const payload of buffered.splice(0))
940
972
  applyEnvelope(ctx, state, payload);
@@ -1062,6 +1094,7 @@ function createRigWorkerPiBridgeExtension(options) {
1062
1094
  };
1063
1095
  if (options.initialMessageSent)
1064
1096
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
1097
+ const registeredDaemonCommands = new Set;
1065
1098
  let nativePiUiContextAvailable = false;
1066
1099
  pi.on("user_bash", (event) => {
1067
1100
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -1094,7 +1127,7 @@ function createRigWorkerPiBridgeExtension(options) {
1094
1127
  });
1095
1128
  return { consume: true };
1096
1129
  });
1097
- connectWorkerStream(options, ctx, state).catch((error) => {
1130
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
1098
1131
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
1099
1132
  updatePiUi(ctx, state);
1100
1133
  });
@@ -1141,8 +1174,6 @@ async function attachRunBundledPiFrontend(context, input) {
1141
1174
  "--no-tools",
1142
1175
  "--no-builtin-tools",
1143
1176
  "--no-skills",
1144
- "--no-prompt-templates",
1145
- "--no-themes",
1146
1177
  "--no-context-files",
1147
1178
  "--no-approve"
1148
1179
  ], {
@@ -32,6 +32,9 @@ Usage: ${usage}`);
32
32
  }
33
33
  }
34
34
 
35
+ // packages/cli/src/commands/server.ts
36
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
37
+
35
38
  // packages/cli/src/commands/_authority-runs.ts
36
39
  import {
37
40
  readAuthorityRun,
@@ -483,7 +486,8 @@ async function executeServer(context, args, options) {
483
486
  const authTokenResult = takeOption(pending, "--auth-token");
484
487
  pending = authTokenResult.rest;
485
488
  requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
486
- const commandParts = ["rig-server", "start"];
489
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
490
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
487
491
  if (hostResult.value) {
488
492
  commandParts.push("--host", hostResult.value);
489
493
  }
@@ -506,7 +510,8 @@ async function executeServer(context, args, options) {
506
510
  const eventResult = takeOption(pending, "--event");
507
511
  pending = eventResult.rest;
508
512
  requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
509
- const commandParts = ["rig-server", "notify-test"];
513
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
514
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
510
515
  if (eventResult.value) {
511
516
  commandParts.push("--event", eventResult.value);
512
517
  }
@@ -1283,7 +1283,38 @@ function parseWsPayload(message2) {
1283
1283
  return JSON.parse(message2.data);
1284
1284
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
1285
1285
  }
1286
- async function connectWorkerStream(options, ctx, state) {
1286
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
1287
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
1288
+ for (const command of commands) {
1289
+ const record = recordOf(command);
1290
+ const name = typeof record?.name === "string" ? record.name : "";
1291
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
1292
+ continue;
1293
+ registered.add(name);
1294
+ const description = typeof record?.description === "string" ? record.description : undefined;
1295
+ const source = typeof record?.source === "string" ? record.source : "worker";
1296
+ try {
1297
+ pi.registerCommand(name, {
1298
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
1299
+ handler: async (args) => {
1300
+ const text = `/${name}${args ? ` ${args}` : ""}`;
1301
+ appendTranscript(state, "You", text);
1302
+ try {
1303
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text);
1304
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
1305
+ appendTranscript(state, "System", message2);
1306
+ if (state.nativeStream)
1307
+ ctx.ui.notify(message2, "info");
1308
+ } catch (error) {
1309
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
1310
+ }
1311
+ updatePiUi(ctx, state);
1312
+ }
1313
+ });
1314
+ } catch {}
1315
+ }
1316
+ }
1317
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
1287
1318
  const ready = await waitForWorkerReady(options, ctx, state);
1288
1319
  if (!ready)
1289
1320
  return;
@@ -1338,6 +1369,7 @@ async function connectWorkerStream(options, ctx, state) {
1338
1369
  const record = recordOf(command);
1339
1370
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
1340
1371
  });
1372
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
1341
1373
  catchupDone = true;
1342
1374
  for (const payload of buffered.splice(0))
1343
1375
  applyEnvelope(ctx, state, payload);
@@ -1465,6 +1497,7 @@ function createRigWorkerPiBridgeExtension(options) {
1465
1497
  };
1466
1498
  if (options.initialMessageSent)
1467
1499
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
1500
+ const registeredDaemonCommands = new Set;
1468
1501
  let nativePiUiContextAvailable = false;
1469
1502
  pi.on("user_bash", (event) => {
1470
1503
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -1497,7 +1530,7 @@ function createRigWorkerPiBridgeExtension(options) {
1497
1530
  });
1498
1531
  return { consume: true };
1499
1532
  });
1500
- connectWorkerStream(options, ctx, state).catch((error) => {
1533
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
1501
1534
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
1502
1535
  updatePiUi(ctx, state);
1503
1536
  });
@@ -1544,8 +1577,6 @@ async function attachRunBundledPiFrontend(context, input) {
1544
1577
  "--no-tools",
1545
1578
  "--no-builtin-tools",
1546
1579
  "--no-skills",
1547
- "--no-prompt-templates",
1548
- "--no-themes",
1549
1580
  "--no-context-files",
1550
1581
  "--no-approve"
1551
1582
  ], {
@@ -6204,7 +6204,24 @@ async function executeInspect(context, args) {
6204
6204
  const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
6205
6205
  const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6206
6206
  if (!latestRun) {
6207
- throw new CliError2(`No runs found for ${requiredTask}.`);
6207
+ const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
6208
+ const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6209
+ if (!serverRun || typeof serverRun.runId !== "string") {
6210
+ throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
6211
+ }
6212
+ const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
6213
+ const entries = Array.isArray(page.entries) ? page.entries : [];
6214
+ if (context.outputMode === "text") {
6215
+ for (const entry of entries) {
6216
+ const record = entry && typeof entry === "object" ? entry : {};
6217
+ const title = String(record.title ?? "");
6218
+ const detail = String(record.detail ?? "");
6219
+ console.log([title, detail].filter(Boolean).join(" \u2014 "));
6220
+ }
6221
+ if (entries.length === 0)
6222
+ console.log(`(no log entries for run ${serverRun.runId})`);
6223
+ }
6224
+ return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
6208
6225
  }
6209
6226
  const logsPath = resolve20(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
6210
6227
  if (!existsSync12(logsPath)) {
@@ -7489,7 +7506,38 @@ function parseWsPayload(message2) {
7489
7506
  return JSON.parse(message2.data);
7490
7507
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
7491
7508
  }
7492
- async function connectWorkerStream(options, ctx, state) {
7509
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
7510
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
7511
+ for (const command of commands) {
7512
+ const record = recordOf(command);
7513
+ const name = typeof record?.name === "string" ? record.name : "";
7514
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
7515
+ continue;
7516
+ registered.add(name);
7517
+ const description = typeof record?.description === "string" ? record.description : undefined;
7518
+ const source = typeof record?.source === "string" ? record.source : "worker";
7519
+ try {
7520
+ pi.registerCommand(name, {
7521
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
7522
+ handler: async (args) => {
7523
+ const text2 = `/${name}${args ? ` ${args}` : ""}`;
7524
+ appendTranscript(state, "You", text2);
7525
+ try {
7526
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text2);
7527
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
7528
+ appendTranscript(state, "System", message2);
7529
+ if (state.nativeStream)
7530
+ ctx.ui.notify(message2, "info");
7531
+ } catch (error) {
7532
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
7533
+ }
7534
+ updatePiUi(ctx, state);
7535
+ }
7536
+ });
7537
+ } catch {}
7538
+ }
7539
+ }
7540
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
7493
7541
  const ready = await waitForWorkerReady(options, ctx, state);
7494
7542
  if (!ready)
7495
7543
  return;
@@ -7544,6 +7592,7 @@ async function connectWorkerStream(options, ctx, state) {
7544
7592
  const record = recordOf(command);
7545
7593
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
7546
7594
  });
7595
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
7547
7596
  catchupDone = true;
7548
7597
  for (const payload of buffered.splice(0))
7549
7598
  applyEnvelope(ctx, state, payload);
@@ -7671,6 +7720,7 @@ function createRigWorkerPiBridgeExtension(options) {
7671
7720
  };
7672
7721
  if (options.initialMessageSent)
7673
7722
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
7723
+ const registeredDaemonCommands = new Set;
7674
7724
  let nativePiUiContextAvailable = false;
7675
7725
  pi.on("user_bash", (event) => {
7676
7726
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -7703,7 +7753,7 @@ function createRigWorkerPiBridgeExtension(options) {
7703
7753
  });
7704
7754
  return { consume: true };
7705
7755
  });
7706
- connectWorkerStream(options, ctx, state).catch((error) => {
7756
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
7707
7757
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
7708
7758
  updatePiUi(ctx, state);
7709
7759
  });
@@ -7750,8 +7800,6 @@ async function attachRunBundledPiFrontend(context, input) {
7750
7800
  "--no-tools",
7751
7801
  "--no-builtin-tools",
7752
7802
  "--no-skills",
7753
- "--no-prompt-templates",
7754
- "--no-themes",
7755
7803
  "--no-context-files",
7756
7804
  "--no-approve"
7757
7805
  ], {
@@ -8296,6 +8344,7 @@ async function executeRun(context, args) {
8296
8344
 
8297
8345
  // packages/cli/src/commands/server.ts
8298
8346
  init_runner();
8347
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
8299
8348
  async function executeServer(context, args, options) {
8300
8349
  const [command = "status", ...rest] = args;
8301
8350
  if (["status", "list", "add", "use"].includes(command)) {
@@ -8313,7 +8362,8 @@ async function executeServer(context, args, options) {
8313
8362
  const authTokenResult = takeOption(pending, "--auth-token");
8314
8363
  pending = authTokenResult.rest;
8315
8364
  requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
8316
- const commandParts = ["rig-server", "start"];
8365
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8366
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
8317
8367
  if (hostResult.value) {
8318
8368
  commandParts.push("--host", hostResult.value);
8319
8369
  }
@@ -8336,7 +8386,8 @@ async function executeServer(context, args, options) {
8336
8386
  const eventResult = takeOption(pending, "--event");
8337
8387
  pending = eventResult.rest;
8338
8388
  requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
8339
- const commandParts = ["rig-server", "notify-test"];
8389
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8390
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
8340
8391
  if (eventResult.value) {
8341
8392
  commandParts.push("--event", eventResult.value);
8342
8393
  }
package/dist/src/index.js CHANGED
@@ -6394,7 +6394,24 @@ async function executeInspect(context, args) {
6394
6394
  const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
6395
6395
  const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6396
6396
  if (!latestRun) {
6397
- throw new CliError2(`No runs found for ${requiredTask}.`);
6397
+ const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
6398
+ const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
6399
+ if (!serverRun || typeof serverRun.runId !== "string") {
6400
+ throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
6401
+ }
6402
+ const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
6403
+ const entries = Array.isArray(page.entries) ? page.entries : [];
6404
+ if (context.outputMode === "text") {
6405
+ for (const entry of entries) {
6406
+ const record = entry && typeof entry === "object" ? entry : {};
6407
+ const title = String(record.title ?? "");
6408
+ const detail = String(record.detail ?? "");
6409
+ console.log([title, detail].filter(Boolean).join(" \u2014 "));
6410
+ }
6411
+ if (entries.length === 0)
6412
+ console.log(`(no log entries for run ${serverRun.runId})`);
6413
+ }
6414
+ return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
6398
6415
  }
6399
6416
  const logsPath = resolve21(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
6400
6417
  if (!existsSync13(logsPath)) {
@@ -7679,7 +7696,38 @@ function parseWsPayload(message2) {
7679
7696
  return JSON.parse(message2.data);
7680
7697
  return JSON.parse(Buffer.from(message2.data).toString("utf8"));
7681
7698
  }
7682
- async function connectWorkerStream(options, ctx, state) {
7699
+ var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
7700
+ function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
7701
+ for (const command of commands) {
7702
+ const record = recordOf(command);
7703
+ const name = typeof record?.name === "string" ? record.name : "";
7704
+ if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
7705
+ continue;
7706
+ registered.add(name);
7707
+ const description = typeof record?.description === "string" ? record.description : undefined;
7708
+ const source = typeof record?.source === "string" ? record.source : "worker";
7709
+ try {
7710
+ pi.registerCommand(name, {
7711
+ description: `[worker ${source}] ${description ?? ""}`.trim(),
7712
+ handler: async (args) => {
7713
+ const text2 = `/${name}${args ? ` ${args}` : ""}`;
7714
+ appendTranscript(state, "You", text2);
7715
+ try {
7716
+ const result = await runRunPiCommandViaServer(options.context, options.runId, text2);
7717
+ const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
7718
+ appendTranscript(state, "System", message2);
7719
+ if (state.nativeStream)
7720
+ ctx.ui.notify(message2, "info");
7721
+ } catch (error) {
7722
+ reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
7723
+ }
7724
+ updatePiUi(ctx, state);
7725
+ }
7726
+ });
7727
+ } catch {}
7728
+ }
7729
+ }
7730
+ async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
7683
7731
  const ready = await waitForWorkerReady(options, ctx, state);
7684
7732
  if (!ready)
7685
7733
  return;
@@ -7734,6 +7782,7 @@ async function connectWorkerStream(options, ctx, state) {
7734
7782
  const record = recordOf(command);
7735
7783
  return typeof record?.name === "string" ? [`/${record.name}`] : [];
7736
7784
  });
7785
+ registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
7737
7786
  catchupDone = true;
7738
7787
  for (const payload of buffered.splice(0))
7739
7788
  applyEnvelope(ctx, state, payload);
@@ -7861,6 +7910,7 @@ function createRigWorkerPiBridgeExtension(options) {
7861
7910
  };
7862
7911
  if (options.initialMessageSent)
7863
7912
  appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
7913
+ const registeredDaemonCommands = new Set;
7864
7914
  let nativePiUiContextAvailable = false;
7865
7915
  pi.on("user_bash", (event) => {
7866
7916
  state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
@@ -7893,7 +7943,7 @@ function createRigWorkerPiBridgeExtension(options) {
7893
7943
  });
7894
7944
  return { consume: true };
7895
7945
  });
7896
- connectWorkerStream(options, ctx, state).catch((error) => {
7946
+ connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
7897
7947
  appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
7898
7948
  updatePiUi(ctx, state);
7899
7949
  });
@@ -7940,8 +7990,6 @@ async function attachRunBundledPiFrontend(context, input) {
7940
7990
  "--no-tools",
7941
7991
  "--no-builtin-tools",
7942
7992
  "--no-skills",
7943
- "--no-prompt-templates",
7944
- "--no-themes",
7945
7993
  "--no-context-files",
7946
7994
  "--no-approve"
7947
7995
  ], {
@@ -8486,6 +8534,7 @@ async function executeRun(context, args) {
8486
8534
 
8487
8535
  // packages/cli/src/commands/server.ts
8488
8536
  init_runner();
8537
+ import { resolveRigServerCommand } from "@rig/runtime/local-server";
8489
8538
  async function executeServer(context, args, options) {
8490
8539
  const [command = "status", ...rest] = args;
8491
8540
  if (["status", "list", "add", "use"].includes(command)) {
@@ -8503,7 +8552,8 @@ async function executeServer(context, args, options) {
8503
8552
  const authTokenResult = takeOption(pending, "--auth-token");
8504
8553
  pending = authTokenResult.rest;
8505
8554
  requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
8506
- const commandParts = ["rig-server", "start"];
8555
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8556
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
8507
8557
  if (hostResult.value) {
8508
8558
  commandParts.push("--host", hostResult.value);
8509
8559
  }
@@ -8526,7 +8576,8 @@ async function executeServer(context, args, options) {
8526
8576
  const eventResult = takeOption(pending, "--event");
8527
8577
  pending = eventResult.rest;
8528
8578
  requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
8529
- const commandParts = ["rig-server", "notify-test"];
8579
+ const serverCommand = resolveRigServerCommand(context.projectRoot);
8580
+ const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
8530
8581
  if (eventResult.value) {
8531
8582
  commandParts.push("--event", eventResult.value);
8532
8583
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/cli",
3
- "version": "0.0.6-alpha.35",
3
+ "version": "0.0.6-alpha.36",
4
4
  "type": "module",
5
5
  "description": "Rig package",
6
6
  "license": "UNLICENSED",
@@ -23,11 +23,11 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@clack/prompts": "^1.2.0",
26
- "@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.35",
27
- "@rig/core": "npm:@h-rig/core@0.0.6-alpha.35",
28
- "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.35",
29
- "@rig/client": "npm:@h-rig/client@0.0.6-alpha.35",
30
- "@rig/server": "npm:@h-rig/server@0.0.6-alpha.35",
26
+ "@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.36",
27
+ "@rig/core": "npm:@h-rig/core@0.0.6-alpha.36",
28
+ "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.36",
29
+ "@rig/client": "npm:@h-rig/client@0.0.6-alpha.36",
30
+ "@rig/server": "npm:@h-rig/server@0.0.6-alpha.36",
31
31
  "picocolors": "^1.1.1"
32
32
  }
33
33
  }