@ricsam/r5dctl 0.0.34 → 0.0.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/cjs/cli.cjs CHANGED
@@ -38,6 +38,7 @@ __export(cli_exports, {
38
38
  parseEnvFlags: () => parseEnvFlags,
39
39
  parseGlobalArgs: () => parseGlobalArgs,
40
40
  parsePromptArgs: () => parsePromptArgs,
41
+ parsePsHistoryArgs: () => parsePsHistoryArgs,
41
42
  parsePsListArgs: () => parsePsListArgs,
42
43
  parseSetEnvArgs: () => parseSetEnvArgs,
43
44
  parseShellArgs: () => parseShellArgs,
@@ -45,6 +46,8 @@ __export(cli_exports, {
45
46
  renderConversationOverviewResponse: () => renderConversationOverviewResponse,
46
47
  renderConversationResponse: () => renderConversationResponse,
47
48
  renderConversationWorkResponse: () => renderConversationWorkResponse,
49
+ renderProcessHistory: () => renderProcessHistory,
50
+ renderProcessInspection: () => renderProcessInspection,
48
51
  renderProcessList: () => renderProcessList,
49
52
  resolveCommandExecution: () => resolveCommandExecution,
50
53
  runR5dctlCli: () => runR5dctlCli,
@@ -65,7 +68,6 @@ const CHAT_MODES = /* @__PURE__ */ new Set([
65
68
  "build",
66
69
  "agent",
67
70
  "explore",
68
- "review",
69
71
  "test",
70
72
  "research",
71
73
  "security_review",
@@ -112,10 +114,12 @@ const CLI_ONLY_COMMAND_HELP = [
112
114
  const PS_HELP_TEXT = [
113
115
  "Usage:",
114
116
  " r5dctl ps list [--worker <label>]",
117
+ " r5dctl ps history [--worker <label>] [--limit <n>]",
118
+ " r5dctl ps inspect <run-id>",
115
119
  " r5dctl ps stop <run-id>",
116
120
  "",
117
- "List or gracefully stop active r5d-managed worker processes.",
118
- "Use -p/--project, -b/--branch, or -s/--session to filter ps list.",
121
+ "List, inspect, or gracefully stop r5d-managed worker processes.",
122
+ "Use -p/--project, -b/--branch, or -s/--session to filter list and history.",
119
123
  ""
120
124
  ].join("\n");
121
125
  const SHARED_HELP_ENTRIES = [
@@ -197,6 +201,16 @@ const SHARED_HELP_ENTRIES = [
197
201
  usage: "ps list [--worker <label>]",
198
202
  description: "List active r5d-managed worker processes; global project, branch, and session filters apply."
199
203
  },
204
+ {
205
+ section: "processes",
206
+ usage: "ps history [--worker <label>] [--limit <n>]",
207
+ description: "List recent process runs, defaulting to the 50 most recent; global filters apply."
208
+ },
209
+ {
210
+ section: "processes",
211
+ usage: "ps inspect <run-id>",
212
+ description: "Inspect process metadata and bounded stdout/stderr tails."
213
+ },
200
214
  { section: "processes", usage: "ps stop <run-id>", description: "Gracefully stop an active process with SIGTERM." },
201
215
  {
202
216
  section: "agents",
@@ -817,6 +831,25 @@ function parsePsListArgs(args) {
817
831
  }
818
832
  return input;
819
833
  }
834
+ function parsePsHistoryArgs(args) {
835
+ const filterArgs = [];
836
+ let limit;
837
+ for (let index = 0; index < args.length; index += 1) {
838
+ const arg = args[index];
839
+ if (arg === "--limit" || arg?.startsWith("--limit=")) {
840
+ if (limit !== void 0) throw new Error("Use only one --limit value");
841
+ const raw = arg === "--limit" ? args[++index] : parseLongOptionWithEquals(arg, "--limit");
842
+ const parsed = Number(requireValue(raw, "Missing value for --limit"));
843
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 200) {
844
+ throw new Error("--limit must be an integer between 1 and 200");
845
+ }
846
+ limit = parsed;
847
+ continue;
848
+ }
849
+ if (arg) filterArgs.push(arg);
850
+ }
851
+ return { ...parsePsListArgs(filterArgs), ...limit !== void 0 ? { limit } : {} };
852
+ }
820
853
  async function openInBrowser(url) {
821
854
  if (process.platform === "darwin") {
822
855
  (0, import_node_child_process.spawn)("open", [url], { stdio: "ignore", detached: true }).unref();
@@ -1002,6 +1035,36 @@ function renderProcessList(processes, nowMs = Date.now()) {
1002
1035
  return `${[formatRow(headers), separator, ...rows.map(formatRow)].join("\n")}
1003
1036
  `;
1004
1037
  }
1038
+ function renderProcessHistory(processes, nowMs = Date.now()) {
1039
+ return processes.length === 0 ? "No process history.\n" : renderProcessList(processes, nowMs);
1040
+ }
1041
+ function renderProcessInspection(process2) {
1042
+ return [
1043
+ `Run: ${process2.runId}`,
1044
+ `Status: ${process2.status}`,
1045
+ `Mode: ${process2.mode}`,
1046
+ `Worker: ${process2.workerLabel} (${process2.platform ?? "unknown"}/${process2.arch ?? "unknown"})`,
1047
+ `Project: ${process2.projectPath} ${process2.branchName}`,
1048
+ `Session: ${process2.sessionId}`,
1049
+ `Command: ${process2.command}`,
1050
+ `Argv: ${JSON.stringify(process2.argv)}`,
1051
+ `CWD: ${process2.cwd ?? "(project root)"}`,
1052
+ `PID/process group: ${process2.pid ?? "(unknown)"}/${process2.processGroupId ?? "(unknown)"}`,
1053
+ `Started: ${process2.startedAt}`,
1054
+ `Updated: ${process2.updatedAt}`,
1055
+ `Completed: ${process2.completedAt ?? "(running)"}`,
1056
+ `Exit code: ${process2.exitCode ?? "(none)"}`,
1057
+ `Error: ${process2.error ?? "(none)"}`,
1058
+ `Log: ${process2.logPath}`,
1059
+ "",
1060
+ `stdout tail${process2.stdoutTailTruncated ? " (truncated)" : ""}:`,
1061
+ process2.stdoutTail || "(empty)",
1062
+ "",
1063
+ `stderr tail${process2.stderrTailTruncated ? " (truncated)" : ""}:`,
1064
+ process2.stderrTail || "(empty)",
1065
+ ""
1066
+ ].join("\n");
1067
+ }
1005
1068
  function summarizeEnvData(data) {
1006
1069
  return Object.fromEntries(
1007
1070
  Object.entries(data).sort(([left], [right]) => left.localeCompare(right)).map(([name, env]) => [
@@ -1276,6 +1339,17 @@ async function executeR5dctlCommand(client, json, args) {
1276
1339
  write(processes, renderProcessList(processes));
1277
1340
  return;
1278
1341
  }
1342
+ if (first === "ps" && second === "history") {
1343
+ const processes = await client.processes.history(parsePsHistoryArgs(args.slice(2)));
1344
+ write(processes, renderProcessHistory(processes));
1345
+ return;
1346
+ }
1347
+ if (first === "ps" && second === "inspect") {
1348
+ if (args.length > 3) throw new Error(`Unexpected ps inspect value: ${args[3]}`);
1349
+ const process2 = await client.processes.inspect(requireValue(args[2], "Missing process run id"));
1350
+ write(process2, renderProcessInspection(process2));
1351
+ return;
1352
+ }
1279
1353
  if (first === "ps" && second === "stop") {
1280
1354
  const process2 = await client.processes.stop(requireValue(args[2], "Missing process run id"));
1281
1355
  write(process2, `Stopped process ${process2.runId}: ${process2.command}
@@ -1593,6 +1667,31 @@ function resolveCommandExecution(options, rest) {
1593
1667
  }
1594
1668
  return { kind: "plugin", pluginArgs };
1595
1669
  }
1670
+ if (subcommand === "history") {
1671
+ const commandFilters = parsePsHistoryArgs(commandArgs.slice(1));
1672
+ const filters = {
1673
+ ...commandFilters,
1674
+ ...options.project ? { project: options.project } : {},
1675
+ ...options.branch ? { branch: options.branch } : {},
1676
+ ...options.session ? { session: options.session } : {}
1677
+ };
1678
+ const pluginArgs = ["ps", "history"];
1679
+ for (const [flag, value] of [
1680
+ ["--project", filters.project],
1681
+ ["--branch", filters.branch],
1682
+ ["--session", filters.session],
1683
+ ["--worker", filters.worker]
1684
+ ]) {
1685
+ if (value) pluginArgs.push(flag, value);
1686
+ }
1687
+ if (filters.limit !== void 0) pluginArgs.push("--limit", String(filters.limit));
1688
+ return { kind: "plugin", pluginArgs };
1689
+ }
1690
+ if (subcommand === "inspect") {
1691
+ const runId = requireValue(commandArgs[1], "Missing process run id");
1692
+ if (commandArgs.length > 2) throw new Error(`Unexpected ps inspect value: ${commandArgs[2]}`);
1693
+ return { kind: "plugin", pluginArgs: ["ps", "inspect", runId] };
1694
+ }
1596
1695
  if (subcommand === "stop") {
1597
1696
  const runId = requireValue(commandArgs[1], "Missing process run id");
1598
1697
  if (commandArgs.length > 2) {
@@ -2025,6 +2124,7 @@ async function main(argv = process.argv.slice(2)) {
2025
2124
  parseEnvFlags,
2026
2125
  parseGlobalArgs,
2027
2126
  parsePromptArgs,
2127
+ parsePsHistoryArgs,
2028
2128
  parsePsListArgs,
2029
2129
  parseSetEnvArgs,
2030
2130
  parseShellArgs,
@@ -2032,6 +2132,8 @@ async function main(argv = process.argv.slice(2)) {
2032
2132
  renderConversationOverviewResponse,
2033
2133
  renderConversationResponse,
2034
2134
  renderConversationWorkResponse,
2135
+ renderProcessHistory,
2136
+ renderProcessInspection,
2035
2137
  renderProcessList,
2036
2138
  resolveCommandExecution,
2037
2139
  runR5dctlCli,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "type": "commonjs"
5
5
  }
package/dist/mjs/cli.mjs CHANGED
@@ -15,7 +15,6 @@ const CHAT_MODES = /* @__PURE__ */ new Set([
15
15
  "build",
16
16
  "agent",
17
17
  "explore",
18
- "review",
19
18
  "test",
20
19
  "research",
21
20
  "security_review",
@@ -62,10 +61,12 @@ const CLI_ONLY_COMMAND_HELP = [
62
61
  const PS_HELP_TEXT = [
63
62
  "Usage:",
64
63
  " r5dctl ps list [--worker <label>]",
64
+ " r5dctl ps history [--worker <label>] [--limit <n>]",
65
+ " r5dctl ps inspect <run-id>",
65
66
  " r5dctl ps stop <run-id>",
66
67
  "",
67
- "List or gracefully stop active r5d-managed worker processes.",
68
- "Use -p/--project, -b/--branch, or -s/--session to filter ps list.",
68
+ "List, inspect, or gracefully stop r5d-managed worker processes.",
69
+ "Use -p/--project, -b/--branch, or -s/--session to filter list and history.",
69
70
  ""
70
71
  ].join("\n");
71
72
  const SHARED_HELP_ENTRIES = [
@@ -147,6 +148,16 @@ const SHARED_HELP_ENTRIES = [
147
148
  usage: "ps list [--worker <label>]",
148
149
  description: "List active r5d-managed worker processes; global project, branch, and session filters apply."
149
150
  },
151
+ {
152
+ section: "processes",
153
+ usage: "ps history [--worker <label>] [--limit <n>]",
154
+ description: "List recent process runs, defaulting to the 50 most recent; global filters apply."
155
+ },
156
+ {
157
+ section: "processes",
158
+ usage: "ps inspect <run-id>",
159
+ description: "Inspect process metadata and bounded stdout/stderr tails."
160
+ },
150
161
  { section: "processes", usage: "ps stop <run-id>", description: "Gracefully stop an active process with SIGTERM." },
151
162
  {
152
163
  section: "agents",
@@ -767,6 +778,25 @@ function parsePsListArgs(args) {
767
778
  }
768
779
  return input;
769
780
  }
781
+ function parsePsHistoryArgs(args) {
782
+ const filterArgs = [];
783
+ let limit;
784
+ for (let index = 0; index < args.length; index += 1) {
785
+ const arg = args[index];
786
+ if (arg === "--limit" || arg?.startsWith("--limit=")) {
787
+ if (limit !== void 0) throw new Error("Use only one --limit value");
788
+ const raw = arg === "--limit" ? args[++index] : parseLongOptionWithEquals(arg, "--limit");
789
+ const parsed = Number(requireValue(raw, "Missing value for --limit"));
790
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 200) {
791
+ throw new Error("--limit must be an integer between 1 and 200");
792
+ }
793
+ limit = parsed;
794
+ continue;
795
+ }
796
+ if (arg) filterArgs.push(arg);
797
+ }
798
+ return { ...parsePsListArgs(filterArgs), ...limit !== void 0 ? { limit } : {} };
799
+ }
770
800
  async function openInBrowser(url) {
771
801
  if (process.platform === "darwin") {
772
802
  spawn("open", [url], { stdio: "ignore", detached: true }).unref();
@@ -952,6 +982,36 @@ function renderProcessList(processes, nowMs = Date.now()) {
952
982
  return `${[formatRow(headers), separator, ...rows.map(formatRow)].join("\n")}
953
983
  `;
954
984
  }
985
+ function renderProcessHistory(processes, nowMs = Date.now()) {
986
+ return processes.length === 0 ? "No process history.\n" : renderProcessList(processes, nowMs);
987
+ }
988
+ function renderProcessInspection(process2) {
989
+ return [
990
+ `Run: ${process2.runId}`,
991
+ `Status: ${process2.status}`,
992
+ `Mode: ${process2.mode}`,
993
+ `Worker: ${process2.workerLabel} (${process2.platform ?? "unknown"}/${process2.arch ?? "unknown"})`,
994
+ `Project: ${process2.projectPath} ${process2.branchName}`,
995
+ `Session: ${process2.sessionId}`,
996
+ `Command: ${process2.command}`,
997
+ `Argv: ${JSON.stringify(process2.argv)}`,
998
+ `CWD: ${process2.cwd ?? "(project root)"}`,
999
+ `PID/process group: ${process2.pid ?? "(unknown)"}/${process2.processGroupId ?? "(unknown)"}`,
1000
+ `Started: ${process2.startedAt}`,
1001
+ `Updated: ${process2.updatedAt}`,
1002
+ `Completed: ${process2.completedAt ?? "(running)"}`,
1003
+ `Exit code: ${process2.exitCode ?? "(none)"}`,
1004
+ `Error: ${process2.error ?? "(none)"}`,
1005
+ `Log: ${process2.logPath}`,
1006
+ "",
1007
+ `stdout tail${process2.stdoutTailTruncated ? " (truncated)" : ""}:`,
1008
+ process2.stdoutTail || "(empty)",
1009
+ "",
1010
+ `stderr tail${process2.stderrTailTruncated ? " (truncated)" : ""}:`,
1011
+ process2.stderrTail || "(empty)",
1012
+ ""
1013
+ ].join("\n");
1014
+ }
955
1015
  function summarizeEnvData(data) {
956
1016
  return Object.fromEntries(
957
1017
  Object.entries(data).sort(([left], [right]) => left.localeCompare(right)).map(([name, env]) => [
@@ -1226,6 +1286,17 @@ async function executeR5dctlCommand(client, json, args) {
1226
1286
  write(processes, renderProcessList(processes));
1227
1287
  return;
1228
1288
  }
1289
+ if (first === "ps" && second === "history") {
1290
+ const processes = await client.processes.history(parsePsHistoryArgs(args.slice(2)));
1291
+ write(processes, renderProcessHistory(processes));
1292
+ return;
1293
+ }
1294
+ if (first === "ps" && second === "inspect") {
1295
+ if (args.length > 3) throw new Error(`Unexpected ps inspect value: ${args[3]}`);
1296
+ const process2 = await client.processes.inspect(requireValue(args[2], "Missing process run id"));
1297
+ write(process2, renderProcessInspection(process2));
1298
+ return;
1299
+ }
1229
1300
  if (first === "ps" && second === "stop") {
1230
1301
  const process2 = await client.processes.stop(requireValue(args[2], "Missing process run id"));
1231
1302
  write(process2, `Stopped process ${process2.runId}: ${process2.command}
@@ -1543,6 +1614,31 @@ function resolveCommandExecution(options, rest) {
1543
1614
  }
1544
1615
  return { kind: "plugin", pluginArgs };
1545
1616
  }
1617
+ if (subcommand === "history") {
1618
+ const commandFilters = parsePsHistoryArgs(commandArgs.slice(1));
1619
+ const filters = {
1620
+ ...commandFilters,
1621
+ ...options.project ? { project: options.project } : {},
1622
+ ...options.branch ? { branch: options.branch } : {},
1623
+ ...options.session ? { session: options.session } : {}
1624
+ };
1625
+ const pluginArgs = ["ps", "history"];
1626
+ for (const [flag, value] of [
1627
+ ["--project", filters.project],
1628
+ ["--branch", filters.branch],
1629
+ ["--session", filters.session],
1630
+ ["--worker", filters.worker]
1631
+ ]) {
1632
+ if (value) pluginArgs.push(flag, value);
1633
+ }
1634
+ if (filters.limit !== void 0) pluginArgs.push("--limit", String(filters.limit));
1635
+ return { kind: "plugin", pluginArgs };
1636
+ }
1637
+ if (subcommand === "inspect") {
1638
+ const runId = requireValue(commandArgs[1], "Missing process run id");
1639
+ if (commandArgs.length > 2) throw new Error(`Unexpected ps inspect value: ${commandArgs[2]}`);
1640
+ return { kind: "plugin", pluginArgs: ["ps", "inspect", runId] };
1641
+ }
1546
1642
  if (subcommand === "stop") {
1547
1643
  const runId = requireValue(commandArgs[1], "Missing process run id");
1548
1644
  if (commandArgs.length > 2) {
@@ -1974,6 +2070,7 @@ export {
1974
2070
  parseEnvFlags,
1975
2071
  parseGlobalArgs,
1976
2072
  parsePromptArgs,
2073
+ parsePsHistoryArgs,
1977
2074
  parsePsListArgs,
1978
2075
  parseSetEnvArgs,
1979
2076
  parseShellArgs,
@@ -1981,6 +2078,8 @@ export {
1981
2078
  renderConversationOverviewResponse,
1982
2079
  renderConversationResponse,
1983
2080
  renderConversationWorkResponse,
2081
+ renderProcessHistory,
2082
+ renderProcessInspection,
1984
2083
  renderProcessList,
1985
2084
  resolveCommandExecution,
1986
2085
  runR5dctlCli,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "type": "module"
5
5
  }
@@ -1,4 +1,4 @@
1
- import { type R5dctlConversationRenderOptions, type R5dctlConversationResponse, type R5dctlConversationOverviewResponse, type R5dctlConversationWorkDetail, type R5dctlConversationWorkResponse, type R5dctlEnvData, type R5dctlProcessListInput, type R5dctlProcessRun, type ChatMode, type ModelTier } from "@ricsam/r5d-api";
1
+ import { type R5dctlConversationRenderOptions, type R5dctlConversationResponse, type R5dctlConversationOverviewResponse, type R5dctlConversationWorkDetail, type R5dctlConversationWorkResponse, type R5dctlEnvData, type R5dctlProcessInspection, type R5dctlProcessListInput, type R5dctlProcessRun, type ChatMode, type ModelTier } from "@ricsam/r5d-api";
2
2
  export type GlobalOptions = {
3
3
  baseUrl?: string;
4
4
  json: boolean;
@@ -61,8 +61,11 @@ export declare function parseShellArgs(args: string[]): {
61
61
  command?: string;
62
62
  };
63
63
  export declare function parsePsListArgs(args: string[]): R5dctlProcessListInput;
64
+ export declare function parsePsHistoryArgs(args: string[]): R5dctlProcessListInput;
64
65
  export declare function formatProcessAge(startedAt: string, nowMs?: number): string;
65
66
  export declare function renderProcessList(processes: R5dctlProcessRun[], nowMs?: number): string;
67
+ export declare function renderProcessHistory(processes: R5dctlProcessRun[], nowMs?: number): string;
68
+ export declare function renderProcessInspection(process: R5dctlProcessInspection): string;
66
69
  export type EnvSummaryData = Record<string, {
67
70
  optional: boolean;
68
71
  description: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/cli.cjs",
6
6
  "module": "./dist/mjs/cli.mjs",
@@ -26,7 +26,7 @@
26
26
  "r5dctl": "dist/cjs/main.cjs"
27
27
  },
28
28
  "dependencies": {
29
- "@ricsam/r5d-api": "^0.0.34",
29
+ "@ricsam/r5d-api": "^0.0.36",
30
30
  "dotenv": "^17",
31
31
  "ws": "^8.18.3"
32
32
  },