@ricsam/r5dctl 0.0.126 → 0.0.127

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/README.md CHANGED
@@ -111,22 +111,8 @@ r5dctl -p <project> -b <branch> ps list --worker <label>
111
111
  r5dctl -s <session-id> ps list --json
112
112
  r5dctl ps stop <run-id>
113
113
 
114
- r5dctl k8s usage
115
- r5dctl k8s usage --namespace default --workload api --container server
116
- r5dctl k8s usage --window 7d
117
- r5dctl k8s usage --workload default/api --window 7d --json
118
- r5dctl vcluster trusted-workflow add --repo owner/repository --workflow .github/workflows/deploy.yml
119
- r5dctl vcluster trusted-workflow list
120
- r5dctl vcluster trusted-workflow remove <workflow-id>
121
114
  ```
122
115
 
123
- Trusted workflows authenticate Kubernetes through the dedicated
124
- `ricsam/r5d-cluster-auth` GitHub Action. They do not run or authenticate
125
- `r5dctl` inside GitHub Actions, and no R5D secret needs to be stored in the
126
- repository. Trust applies to that workflow path on every Git ref and grants
127
- cluster-admin, so protect workflow changes and do not invoke it for untrusted
128
- pull requests.
129
-
130
116
  `create branch` creates a linked worktree branch through the platform from an existing branch's checkout, with the same `--source worktree:<branch>` and `--working-tree carry|clean` semantics as `session start --new-worktree` (carry is the default) and no session prompt. `--worker <label>` selects the connected worker that cuts the checkout; omitted, the platform chooses one, and an r5d worker shell's temporary credential is always bound to its own worker. The command returns as soon as the operation is accepted and prints its id; `describe branch-operation <operation-id>` reports `provisioning`, `ready`, or `failed` with the worker and any error. Neither prints a commit hash: read the branch with git in its checkout once it is ready.
131
117
 
132
118
  `delete branch` removes one or more branches and every session on them through the platform, which is the only supported way to remove a linked worktree: the platform owns those checkouts, so never run `git worktree remove`, `git worktree prune`, or `git branch -D` inside a project checkout. Without `--confirm` it prints each branch and its sessions and exits non-zero without deleting anything. With `--confirm` each branch is resolved to the exact managed branch it names today, its deletion is accepted at once by the platform, and the command waits (polling every 2 seconds, up to 10 minutes) until the platform reports it completed before requesting the next one; a failure does not stop the remaining deletions, and the exit status is non-zero if any branch failed. `--no-wait` prints the accepted branch id instead of waiting; `describe branch-deletion <branch-id>` reports `pending` (with the retry reason when the worker has not answered yet), `failed` with the platform's error, or `completed`, and answers `completed` for a branch id that no longer exists. The deletion stays bound to that branch id: a same-name branch created afterwards is never deleted by an old request, and re-running the command for a branch whose deletion failed retries it. The primary branch `main` is refused before anything is deleted, as is a branch with a running agent or active process (stop them first); a name that only has sessions and no managed branch is refused too (delete those sessions with `delete session`). On a server that predates the route, the command explains that the server does not support `delete branch` yet instead of reporting a missing branch.
@@ -157,9 +143,7 @@ Add `-f`/`--follow`/`--watch` to `session start` to poll the provisioning handle
157
143
 
158
144
  `ps list` shows active long-running commands managed by r5d. It does not expose the worker host's general OS process table or interactive PTYs. Global project, branch, and session options filter the list, while `--worker` selects a worker label. The `LANE` column names the worker command lane each run holds (`general`, `utility`, or `control`) or waits for (`queued:general`), from the worker's latest capacity report; `-` means the worker did not report the run. `ps stop` sends `SIGTERM` to the selected run. Inside an r5d-provided worker shell, the temporary credential can only list and stop runs on that shell's worker.
159
145
 
160
- A managed worker runs two general shells at a time; a third waits up to 60 seconds and then fails with "command capacity is busy". Coordination does not compete for those slots: when an agent shell runs one plain `r5dctl` coordination command (`ps list`, `ps stop`, `workspace status`, `session status|stop|prompt|claim|claims|process-log`, `describe …`, `get …`, `sessions recent`, the `conversation` read forms, `create|update|delete session`, `answer-questions`, `answer-env-request`) with plain or simply quoted arguments, the platform runs it in a reserved control lane: two small slots, no shell, a 120-second limit. Shell operators, pipes, redirections, `$` expansions, environment assignments, wrappers, paths to r5dctl, `--`, `--follow`, and credential or endpoint flags make it an ordinary shell command again. `workspace status` prints each worker's lane totals, holders, and queue.
161
-
162
- `k8s usage` shows current and rolling CPU and memory usage for every workload container in your managed vCluster. The default window is `24h`; pass `--window 7d` for seven days. Filter with `--namespace`, `--workload`, or `--container`; a workload may be identified by name, `namespace/name`, or Kubernetes UID. Human-readable output shows current totals across sampled replicas and the selected window's maximum. Global `--json` includes min/max summaries, the complete five-minute history envelope, per-pod series, coverage, and freshness metadata.
146
+ The worker host determines execution capacity. If its configured command launcher provides a reserved control lane, an agent shell can use it for one plain `r5dctl` coordination command (`ps list`, `ps stop`, `workspace status`, `session status|stop|prompt|claim|claims|process-log`, `describe …`, `get …`, `sessions recent`, the `conversation` read forms, `create|update|delete session`, `answer-questions`, `answer-env-request`) with plain or simply quoted arguments. The command runs without a shell, using the launcher's control capacity and runtime limit. Shell operators, pipes, redirections, `$` expansions, environment assignments, wrappers, paths to r5dctl, `--`, `--follow`, and credential or endpoint flags make it an ordinary shell command again. `workspace status` prints each worker's lane totals, holders, and queue.
163
147
 
164
148
  `get envs` reports names and whether values are set without revealing the values by default. Add `--show-values` to reveal every value; multiline and control characters are escaped for readable output. Without the global `--json` flag, `get env <name>` writes only that value to stdout, with no added newline or labels, so it works directly with command substitution and pipelines:
165
149
 
package/dist/cjs/cli.cjs CHANGED
@@ -34,18 +34,14 @@ __export(cli_exports, {
34
34
  branchDeletionConfirmationMessage: () => branchDeletionConfirmationMessage,
35
35
  branchDeletionsConfirmationMessage: () => branchDeletionsConfirmationMessage,
36
36
  branchDeletionsFailureMessage: () => branchDeletionsFailureMessage,
37
- collectK8sUsage: () => collectK8sUsage,
38
37
  createBranchThroughPlatform: () => createBranchThroughPlatform,
39
38
  deleteBranchThroughPlatform: () => deleteBranchThroughPlatform,
40
39
  deleteBranchesThroughPlatform: () => deleteBranchesThroughPlatform,
41
40
  dispatchSessionRunCommand: () => dispatchSessionRunCommand,
42
41
  followR5dctlSession: () => followR5dctlSession,
43
- formatK8sCpu: () => formatK8sCpu,
44
- formatK8sMemory: () => formatK8sMemory,
45
42
  formatProcessAge: () => formatProcessAge,
46
43
  formatProcessLane: () => formatProcessLane,
47
44
  getCliHelpText: () => getCliHelpText,
48
- getK8sUsageState: () => getK8sUsageState,
49
45
  getProjectEnvValue: () => getProjectEnvValue,
50
46
  getR5dctlVersion: () => getR5dctlVersion,
51
47
  getTransientDevicePollDelay: () => getTransientDevicePollDelay,
@@ -66,7 +62,6 @@ __export(cli_exports, {
66
62
  parseEnvRequestResponseArgs: () => parseEnvRequestResponseArgs,
67
63
  parseGetEnvsArgs: () => parseGetEnvsArgs,
68
64
  parseGlobalArgs: () => parseGlobalArgs,
69
- parseK8sUsageArgs: () => parseK8sUsageArgs,
70
65
  parsePromptArgs: () => parsePromptArgs,
71
66
  parsePsHistoryArgs: () => parsePsHistoryArgs,
72
67
  parsePsListArgs: () => parsePsListArgs,
@@ -91,7 +86,6 @@ __export(cli_exports, {
91
86
  renderConversationWorkResponse: () => renderConversationWorkResponse,
92
87
  renderDeviceAuthorizationPrompt: () => renderDeviceAuthorizationPrompt,
93
88
  renderEnvValues: () => renderEnvValues,
94
- renderK8sUsageReport: () => renderK8sUsageReport,
95
89
  renderProcessHistory: () => renderProcessHistory,
96
90
  renderProcessInspection: () => renderProcessInspection,
97
91
  renderProcessList: () => renderProcessList,
@@ -169,20 +163,10 @@ const PS_HELP_TEXT = [
169
163
  " r5dctl ps inspect <run-id>",
170
164
  " r5dctl ps stop <run-id>",
171
165
  "",
172
- "List, inspect, or gracefully stop r5d-managed worker processes.",
166
+ "List, inspect, or gracefully stop agent processes on workers.",
173
167
  "Use -p/--project, -b/--branch, or -s/--session to filter list and history.",
174
168
  ""
175
169
  ].join("\n");
176
- const K8S_HELP_TEXT = [
177
- "Usage:",
178
- " r5dctl k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
179
- " r5dctl vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
180
- " r5dctl vcluster trusted-workflow list",
181
- " r5dctl vcluster trusted-workflow remove <workflow-id>",
182
- "",
183
- "Show current and rolling CPU and memory usage for managed-vCluster workload containers.",
184
- ""
185
- ].join("\n");
186
170
  const SESSION_RUN_HELP_TEXT = [
187
171
  "Usage:",
188
172
  ' r5dctl -p <project> session start --worker <label> --worktree <branch> --model <tier> [-f|--follow|--watch] [--tools] [--parent-session <session-id>] "<prompt>"',
@@ -374,26 +358,10 @@ const SHARED_HELP_ENTRIES = [
374
358
  usage: "-s <session-id> answer-env-request --worker <label> --mode <mode> --model <tier> [-e KEY=value] [--context <text>]",
375
359
  description: "Answer a pending environment variable request with values, context, or both."
376
360
  },
377
- {
378
- section: "kubernetes",
379
- usage: "k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
380
- description: "Show current and rolling CPU and memory usage for managed-vCluster workload containers."
381
- },
382
- {
383
- section: "kubernetes",
384
- usage: "vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
385
- description: "Trust an exact GitHub Actions workflow path to authenticate kubectl against your managed vCluster."
386
- },
387
- { section: "kubernetes", usage: "vcluster trusted-workflow list", description: "List trusted GitHub Actions workflows." },
388
- {
389
- section: "kubernetes",
390
- usage: "vcluster trusted-workflow remove <workflow-id>",
391
- description: "Revoke a trusted GitHub Actions workflow and its outstanding credentials."
392
- },
393
361
  {
394
362
  section: "processes",
395
363
  usage: "ps list [--worker <label>]",
396
- description: "List active r5d-managed worker processes; global project, branch, and session filters apply."
364
+ description: "List active agent processes on workers; global project, branch, and session filters apply."
397
365
  },
398
366
  {
399
367
  section: "processes",
@@ -414,7 +382,6 @@ const HELP_SECTION_ORDER = [
414
382
  "branches",
415
383
  "envs",
416
384
  "sessions",
417
- "kubernetes",
418
385
  "processes",
419
386
  "shell"
420
387
  ];
@@ -425,7 +392,6 @@ const HELP_SECTION_TITLES = {
425
392
  branches: "Branches",
426
393
  envs: "Environment variables",
427
394
  sessions: "Sessions",
428
- kubernetes: "Kubernetes",
429
395
  processes: "Processes",
430
396
  shell: "Shell"
431
397
  };
@@ -1664,36 +1630,6 @@ function parseRecentSessionArgs(args) {
1664
1630
  if (!Number.isInteger(limit) || limit < 1 || limit > 200) throw new Error("--limit must be an integer between 1 and 200");
1665
1631
  return { limit };
1666
1632
  }
1667
- function parseK8sUsageArgs(args) {
1668
- const parsed = { window: "24h" };
1669
- const seen = /* @__PURE__ */ new Set();
1670
- for (let index = 0; index < args.length; index += 1) {
1671
- const arg = args[index];
1672
- if (!arg) continue;
1673
- const option = ["--namespace", "--workload", "--container", "--window"].find(
1674
- (candidate) => arg === candidate || arg.startsWith(`${candidate}=`)
1675
- );
1676
- if (!option) throw new Error(`Unknown k8s usage argument: ${arg}`);
1677
- if (seen.has(option)) throw new Error(`Use ${option} only once`);
1678
- seen.add(option);
1679
- const inlineValue = parseLongOptionWithEquals(arg, option);
1680
- const candidateValue = inlineValue ?? args[index + 1];
1681
- if (!candidateValue || candidateValue.startsWith("--")) throw new Error(`Missing value for ${option}`);
1682
- const value = candidateValue;
1683
- if (inlineValue === void 0) index += 1;
1684
- if (option === "--window") {
1685
- if (value !== "24h" && value !== "7d") throw new Error("--window must be 24h or 7d");
1686
- parsed.window = value;
1687
- } else if (option === "--namespace") {
1688
- parsed.namespace = value;
1689
- } else if (option === "--workload") {
1690
- parsed.workload = value;
1691
- } else {
1692
- parsed.container = value;
1693
- }
1694
- }
1695
- return parsed;
1696
- }
1697
1633
  async function openInBrowser(url) {
1698
1634
  if (process.platform === "darwin") {
1699
1635
  (0, import_node_child_process.spawn)("open", [url], { stdio: "ignore", detached: true }).unref();
@@ -1956,171 +1892,6 @@ Error: ${result.error}` : "";
1956
1892
  return `Workspace sync ${result.outcome} on ${result.workerLabel}; HEAD ${head}; ${result.diffSizeBytes} bytes.${discarded}${error}
1957
1893
  `;
1958
1894
  }
1959
- function summarizeK8sHistory(history) {
1960
- if (history.envelope.length === 0) {
1961
- return {
1962
- cpuMinNanoCores: null,
1963
- cpuMaxNanoCores: null,
1964
- memoryMinBytes: null,
1965
- memoryMaxBytes: null,
1966
- sampleCount: 0
1967
- };
1968
- }
1969
- return {
1970
- cpuMinNanoCores: Math.min(...history.envelope.map((point) => point.cpuMinNanoCores)),
1971
- cpuMaxNanoCores: Math.max(...history.envelope.map((point) => point.cpuMaxNanoCores)),
1972
- memoryMinBytes: Math.min(...history.envelope.map((point) => point.memoryMinBytes)),
1973
- memoryMaxBytes: Math.max(...history.envelope.map((point) => point.memoryMaxBytes)),
1974
- sampleCount: history.envelope.reduce((total, point) => total + point.sampleCount, 0)
1975
- };
1976
- }
1977
- async function mapWithConcurrency(items, concurrency, fn) {
1978
- const results = new Array(items.length);
1979
- let nextIndex = 0;
1980
- await Promise.all(
1981
- Array.from({ length: Math.min(concurrency, items.length) }, async () => {
1982
- while (nextIndex < items.length) {
1983
- const index = nextIndex++;
1984
- const item = items[index];
1985
- if (item !== void 0) results[index] = await fn(item);
1986
- }
1987
- })
1988
- );
1989
- return results;
1990
- }
1991
- async function collectK8sUsage(client, options) {
1992
- const resources = await client.k8s.resources();
1993
- const candidates = resources.workloads.flatMap((workload) => workload.containers.map((container) => ({ workload, container }))).filter(({ workload, container }) => {
1994
- const workloadMatches = !options.workload || options.workload === workload.name || options.workload === `${workload.namespace}/${workload.name}` || options.workload === workload.uid;
1995
- return (!options.namespace || options.namespace === workload.namespace) && workloadMatches && (!options.container || options.container === container.name);
1996
- }).sort(
1997
- (left, right) => left.workload.namespace.localeCompare(right.workload.namespace) || left.workload.name.localeCompare(right.workload.name) || left.container.name.localeCompare(right.container.name)
1998
- );
1999
- if (candidates.length === 0 && (options.namespace || options.workload || options.container)) {
2000
- throw new Error("No managed-vCluster workload containers matched the requested filters");
2001
- }
2002
- const entries = await mapWithConcurrency(candidates, 8, async ({ workload, container }) => {
2003
- const history = await client.k8s.resourceHistory({ workloadUid: workload.uid, containerName: container.name, window: options.window });
2004
- return {
2005
- workload: {
2006
- uid: workload.uid,
2007
- kind: workload.kind,
2008
- namespace: workload.namespace,
2009
- name: workload.name,
2010
- replicas: workload.replicas,
2011
- readyReplicas: workload.readyReplicas
2012
- },
2013
- container: {
2014
- name: container.name,
2015
- currentUsage: container.currentUsage,
2016
- pods: container.pods
2017
- },
2018
- sampledPodCount: container.pods.filter((pod) => pod.cpuNanoCores !== null || pod.memoryBytes !== null).length,
2019
- summary: summarizeK8sHistory(history),
2020
- history
2021
- };
2022
- });
2023
- return {
2024
- window: options.window,
2025
- collectedAt: resources.collectedAt,
2026
- metricsFreshAt: resources.metricsFreshAt,
2027
- metricsStale: resources.metricsStale,
2028
- filters: {
2029
- namespace: options.namespace,
2030
- workload: options.workload,
2031
- container: options.container
2032
- },
2033
- entries
2034
- };
2035
- }
2036
- function formatDecimal(value) {
2037
- if (value >= 100) return value.toFixed(0);
2038
- if (value >= 10) return value.toFixed(1).replace(/\.0$/, "");
2039
- return value.toFixed(2).replace(/\.0+$/, "").replace(/(\.\d)0$/, "$1");
2040
- }
2041
- function formatK8sCpu(value) {
2042
- if (value === null) return "-";
2043
- const milliCores = value / 1e6;
2044
- return `${formatDecimal(milliCores)}m`;
2045
- }
2046
- function formatK8sMemory(value) {
2047
- if (value === null) return "-";
2048
- const units = ["B", "Ki", "Mi", "Gi", "Ti"];
2049
- let amount = value;
2050
- let unitIndex = 0;
2051
- while (amount >= 1024 && unitIndex < units.length - 1) {
2052
- amount /= 1024;
2053
- unitIndex += 1;
2054
- }
2055
- return `${formatDecimal(amount)}${units[unitIndex]}`;
2056
- }
2057
- function getK8sUsageState(entry) {
2058
- const hasHistory = entry.history.envelope.length > 0;
2059
- const terminalPods = entry.container.pods.filter((pod) => pod.phase === "Succeeded" || pod.phase === "Failed").length;
2060
- const inactive = entry.sampledPodCount === 0 && (entry.workload.replicas === 0 || entry.container.pods.length > 0 && terminalPods === entry.container.pods.length || entry.workload.kind === "CronJob" && entry.container.pods.length === 0);
2061
- if (inactive) return "inactive";
2062
- if (entry.sampledPodCount === 0) return hasHistory ? entry.history.stale ? "stale" : "no current" : "no data";
2063
- if (!hasHistory) return "warming";
2064
- if (entry.history.stale) return "stale";
2065
- if (entry.history.incomplete) return "partial";
2066
- return "healthy";
2067
- }
2068
- function abbreviatedK8sKind(kind) {
2069
- switch (kind) {
2070
- case "Deployment":
2071
- return "deploy";
2072
- case "StatefulSet":
2073
- return "sts";
2074
- case "DaemonSet":
2075
- return "ds";
2076
- case "CronJob":
2077
- return "cron";
2078
- case "ReplicaSet":
2079
- return "rs";
2080
- case "Job":
2081
- return "job";
2082
- case "Pod":
2083
- return "pod";
2084
- }
2085
- }
2086
- function renderK8sUsageReport(report) {
2087
- const freshness = report.metricsFreshAt ?? "unavailable";
2088
- const lines = [
2089
- `Window: ${report.window} Collector: ${report.metricsStale ? "stale" : "current"} Fresh: ${freshness}`,
2090
- "PODS counts pods with current metrics."
2091
- ];
2092
- if (report.entries.length === 0) return `${lines.join("\n")}
2093
- No managed-vCluster workload containers found.
2094
- `;
2095
- const headers = ["WORKLOAD", "CONTAINER", "PODS", "CPU NOW", "CPU MAX", "MEM NOW", "MEM MAX", "STATE"];
2096
- const grouped = /* @__PURE__ */ new Map();
2097
- for (const entry of report.entries) {
2098
- const entries = grouped.get(entry.workload.namespace) ?? [];
2099
- entries.push(entry);
2100
- grouped.set(entry.workload.namespace, entries);
2101
- }
2102
- for (const [namespace, entries] of grouped) {
2103
- const rows = entries.map((entry) => {
2104
- const state = getK8sUsageState(entry);
2105
- return [
2106
- `${abbreviatedK8sKind(entry.workload.kind)}/${entry.workload.name}`,
2107
- entry.container.name,
2108
- String(entry.sampledPodCount),
2109
- formatK8sCpu(entry.container.currentUsage.cpuNanoCores),
2110
- formatK8sCpu(entry.summary.cpuMaxNanoCores),
2111
- formatK8sMemory(entry.container.currentUsage.memoryBytes),
2112
- formatK8sMemory(entry.summary.memoryMaxBytes),
2113
- state === "healthy" ? "-" : state
2114
- ];
2115
- });
2116
- const widths = headers.map((header, column) => Math.max(header.length, ...rows.map((row) => row[column]?.length ?? 0)));
2117
- const formatRow = (row) => row.map((value, column) => column === row.length - 1 ? value : value.padEnd(widths[column] ?? value.length)).join(" ");
2118
- const separator = widths.map((width) => "-".repeat(width)).join(" ");
2119
- lines.push("", `Namespace: ${namespace}`, formatRow(headers), separator, ...rows.map(formatRow));
2120
- }
2121
- return `${lines.join("\n")}
2122
- `;
2123
- }
2124
1895
  function renderSessionDescription(session) {
2125
1896
  return [`Session: ${session.id}`, `Project: ${session.projectPath}`, `Branch: ${session.branchName}`].join("\n") + "\n";
2126
1897
  }
@@ -3047,45 +2818,6 @@ async function executeR5dctlCommand(client, json, args) {
3047
2818
  write(result, renderWorkspaceSync(result));
3048
2819
  return;
3049
2820
  }
3050
- if (first === "k8s" && second === "usage") {
3051
- const report = await collectK8sUsage(client, parseK8sUsageArgs(args.slice(2)));
3052
- write(report, renderK8sUsageReport(report));
3053
- return;
3054
- }
3055
- if (first === "vcluster" && second === "trusted-workflow") {
3056
- const subcommand = requireValue(args[2], "Missing trusted-workflow command");
3057
- if (subcommand === "add") {
3058
- const parsed = parseCommandOperands(args.slice(3), /* @__PURE__ */ new Set(["--repo", "--workflow"]), /* @__PURE__ */ new Map(), "trusted-workflow add");
3059
- if (parsed.positionals.length > 0) throw new Error(`Unexpected trusted-workflow add value: ${parsed.positionals[0]}`);
3060
- const workflow = await client.k8s.trustedWorkflows.add({
3061
- repository: requireValue(parsed.values.get("--repo"), "--repo <owner/repository> is required"),
3062
- workflowPath: requireValue(parsed.values.get("--workflow"), "--workflow <path> is required")
3063
- });
3064
- write(workflow, "Trusted GitHub workflow configured successfully.\n");
3065
- return;
3066
- }
3067
- if (subcommand === "list") {
3068
- if (args.length > 3) throw new Error(`Unexpected trusted-workflow list value: ${args[3]}`);
3069
- const workflows = await client.k8s.trustedWorkflows.list();
3070
- write(
3071
- workflows,
3072
- workflows.length === 0 ? "No trusted GitHub workflows.\n" : `${workflows.map(
3073
- (workflow) => `${workflow.id} ${workflow.repository} ${workflow.workflowPath} ${workflow.revokedAt ? "revoked" : "active"}`
3074
- ).join("\n")}
3075
- `
3076
- );
3077
- return;
3078
- }
3079
- if (subcommand === "remove") {
3080
- const workflowId = requireValue(args[3], "Missing trusted workflow id");
3081
- if (args.length > 4) throw new Error(`Unexpected trusted-workflow remove value: ${args[4]}`);
3082
- const result = await client.k8s.trustedWorkflows.revoke(workflowId);
3083
- if (!result.success) throw new Error("Trusted GitHub workflow was not found or was already revoked");
3084
- write(result, "Trusted GitHub workflow revoked.\n");
3085
- return;
3086
- }
3087
- throw new Error(`Unknown trusted-workflow command: ${subcommand}`);
3088
- }
3089
2821
  if (first === "ps" && second === "list") {
3090
2822
  const processes = await client.processes.list(parsePsListArgs(args.slice(2)));
3091
2823
  write(processes, renderProcessList(processes));
@@ -3421,12 +3153,6 @@ function resolveCommandExecution(options, rest) {
3421
3153
  text: PS_HELP_TEXT
3422
3154
  };
3423
3155
  }
3424
- if (command === "k8s" && commandArgs.length === 0) {
3425
- return {
3426
- kind: "cli-help",
3427
- text: K8S_HELP_TEXT
3428
- };
3429
- }
3430
3156
  if (command === "session" && commandArgs.length === 0) {
3431
3157
  return {
3432
3158
  kind: "cli-help",
@@ -3448,10 +3174,7 @@ function resolveCommandExecution(options, rest) {
3448
3174
  text: sharedHelp
3449
3175
  };
3450
3176
  }
3451
- return {
3452
- kind: "plugin",
3453
- pluginArgs: [...normalizedRest, "--help"]
3454
- };
3177
+ throw new Error(`Unknown command: ${normalizedRest.join(" ")}`);
3455
3178
  }
3456
3179
  if (command === "projects" || command === "sessions" || command === "workspace") {
3457
3180
  return {
@@ -3561,26 +3284,6 @@ function resolveCommandExecution(options, rest) {
3561
3284
  }
3562
3285
  throw new Error(`Unknown ps command: ${subcommand ?? ""}`.trim());
3563
3286
  }
3564
- if (command === "k8s") {
3565
- const subcommand = commandArgs[0];
3566
- if (options.project || options.branch || options.session) {
3567
- throw new Error("Project, branch, and session scopes are not supported for `k8s`");
3568
- }
3569
- if (subcommand === "usage") {
3570
- parseK8sUsageArgs(commandArgs.slice(1));
3571
- return { kind: "plugin", pluginArgs: ["k8s", "usage", ...commandArgs.slice(1)] };
3572
- }
3573
- throw new Error(`Unknown k8s command: ${subcommand ?? ""}`.trim());
3574
- }
3575
- if (command === "vcluster") {
3576
- if (options.project || options.branch || options.session) {
3577
- throw new Error("Project, branch, and session scopes are not supported for `vcluster`");
3578
- }
3579
- if (commandArgs[0] !== "trusted-workflow") {
3580
- throw new Error(`Unknown vcluster command: ${commandArgs[0] ?? ""}`.trim());
3581
- }
3582
- return { kind: "plugin", pluginArgs: ["vcluster", "trusted-workflow", ...commandArgs.slice(1)] };
3583
- }
3584
3287
  if (command === "get") {
3585
3288
  const target = commandArgs[0];
3586
3289
  if (target === "projects") {
@@ -4063,18 +3766,14 @@ async function main(argv = process.argv.slice(2)) {
4063
3766
  branchDeletionConfirmationMessage,
4064
3767
  branchDeletionsConfirmationMessage,
4065
3768
  branchDeletionsFailureMessage,
4066
- collectK8sUsage,
4067
3769
  createBranchThroughPlatform,
4068
3770
  deleteBranchThroughPlatform,
4069
3771
  deleteBranchesThroughPlatform,
4070
3772
  dispatchSessionRunCommand,
4071
3773
  followR5dctlSession,
4072
- formatK8sCpu,
4073
- formatK8sMemory,
4074
3774
  formatProcessAge,
4075
3775
  formatProcessLane,
4076
3776
  getCliHelpText,
4077
- getK8sUsageState,
4078
3777
  getProjectEnvValue,
4079
3778
  getR5dctlVersion,
4080
3779
  getTransientDevicePollDelay,
@@ -4095,7 +3794,6 @@ async function main(argv = process.argv.slice(2)) {
4095
3794
  parseEnvRequestResponseArgs,
4096
3795
  parseGetEnvsArgs,
4097
3796
  parseGlobalArgs,
4098
- parseK8sUsageArgs,
4099
3797
  parsePromptArgs,
4100
3798
  parsePsHistoryArgs,
4101
3799
  parsePsListArgs,
@@ -4120,7 +3818,6 @@ async function main(argv = process.argv.slice(2)) {
4120
3818
  renderConversationWorkResponse,
4121
3819
  renderDeviceAuthorizationPrompt,
4122
3820
  renderEnvValues,
4123
- renderK8sUsageReport,
4124
3821
  renderProcessHistory,
4125
3822
  renderProcessInspection,
4126
3823
  renderProcessList,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.126",
3
+ "version": "0.0.127",
4
4
  "type": "commonjs"
5
5
  }
package/dist/mjs/cli.mjs CHANGED
@@ -58,20 +58,10 @@ const PS_HELP_TEXT = [
58
58
  " r5dctl ps inspect <run-id>",
59
59
  " r5dctl ps stop <run-id>",
60
60
  "",
61
- "List, inspect, or gracefully stop r5d-managed worker processes.",
61
+ "List, inspect, or gracefully stop agent processes on workers.",
62
62
  "Use -p/--project, -b/--branch, or -s/--session to filter list and history.",
63
63
  ""
64
64
  ].join("\n");
65
- const K8S_HELP_TEXT = [
66
- "Usage:",
67
- " r5dctl k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
68
- " r5dctl vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
69
- " r5dctl vcluster trusted-workflow list",
70
- " r5dctl vcluster trusted-workflow remove <workflow-id>",
71
- "",
72
- "Show current and rolling CPU and memory usage for managed-vCluster workload containers.",
73
- ""
74
- ].join("\n");
75
65
  const SESSION_RUN_HELP_TEXT = [
76
66
  "Usage:",
77
67
  ' r5dctl -p <project> session start --worker <label> --worktree <branch> --model <tier> [-f|--follow|--watch] [--tools] [--parent-session <session-id>] "<prompt>"',
@@ -263,26 +253,10 @@ const SHARED_HELP_ENTRIES = [
263
253
  usage: "-s <session-id> answer-env-request --worker <label> --mode <mode> --model <tier> [-e KEY=value] [--context <text>]",
264
254
  description: "Answer a pending environment variable request with values, context, or both."
265
255
  },
266
- {
267
- section: "kubernetes",
268
- usage: "k8s usage [--namespace <name>] [--workload <name|namespace/name|uid>] [--container <name>] [--window <24h|7d>]",
269
- description: "Show current and rolling CPU and memory usage for managed-vCluster workload containers."
270
- },
271
- {
272
- section: "kubernetes",
273
- usage: "vcluster trusted-workflow add --repo <owner/repository> --workflow <.github/workflows/file.yml>",
274
- description: "Trust an exact GitHub Actions workflow path to authenticate kubectl against your managed vCluster."
275
- },
276
- { section: "kubernetes", usage: "vcluster trusted-workflow list", description: "List trusted GitHub Actions workflows." },
277
- {
278
- section: "kubernetes",
279
- usage: "vcluster trusted-workflow remove <workflow-id>",
280
- description: "Revoke a trusted GitHub Actions workflow and its outstanding credentials."
281
- },
282
256
  {
283
257
  section: "processes",
284
258
  usage: "ps list [--worker <label>]",
285
- description: "List active r5d-managed worker processes; global project, branch, and session filters apply."
259
+ description: "List active agent processes on workers; global project, branch, and session filters apply."
286
260
  },
287
261
  {
288
262
  section: "processes",
@@ -303,7 +277,6 @@ const HELP_SECTION_ORDER = [
303
277
  "branches",
304
278
  "envs",
305
279
  "sessions",
306
- "kubernetes",
307
280
  "processes",
308
281
  "shell"
309
282
  ];
@@ -314,7 +287,6 @@ const HELP_SECTION_TITLES = {
314
287
  branches: "Branches",
315
288
  envs: "Environment variables",
316
289
  sessions: "Sessions",
317
- kubernetes: "Kubernetes",
318
290
  processes: "Processes",
319
291
  shell: "Shell"
320
292
  };
@@ -1553,36 +1525,6 @@ function parseRecentSessionArgs(args) {
1553
1525
  if (!Number.isInteger(limit) || limit < 1 || limit > 200) throw new Error("--limit must be an integer between 1 and 200");
1554
1526
  return { limit };
1555
1527
  }
1556
- function parseK8sUsageArgs(args) {
1557
- const parsed = { window: "24h" };
1558
- const seen = /* @__PURE__ */ new Set();
1559
- for (let index = 0; index < args.length; index += 1) {
1560
- const arg = args[index];
1561
- if (!arg) continue;
1562
- const option = ["--namespace", "--workload", "--container", "--window"].find(
1563
- (candidate) => arg === candidate || arg.startsWith(`${candidate}=`)
1564
- );
1565
- if (!option) throw new Error(`Unknown k8s usage argument: ${arg}`);
1566
- if (seen.has(option)) throw new Error(`Use ${option} only once`);
1567
- seen.add(option);
1568
- const inlineValue = parseLongOptionWithEquals(arg, option);
1569
- const candidateValue = inlineValue ?? args[index + 1];
1570
- if (!candidateValue || candidateValue.startsWith("--")) throw new Error(`Missing value for ${option}`);
1571
- const value = candidateValue;
1572
- if (inlineValue === void 0) index += 1;
1573
- if (option === "--window") {
1574
- if (value !== "24h" && value !== "7d") throw new Error("--window must be 24h or 7d");
1575
- parsed.window = value;
1576
- } else if (option === "--namespace") {
1577
- parsed.namespace = value;
1578
- } else if (option === "--workload") {
1579
- parsed.workload = value;
1580
- } else {
1581
- parsed.container = value;
1582
- }
1583
- }
1584
- return parsed;
1585
- }
1586
1528
  async function openInBrowser(url) {
1587
1529
  if (process.platform === "darwin") {
1588
1530
  spawn("open", [url], { stdio: "ignore", detached: true }).unref();
@@ -1845,171 +1787,6 @@ Error: ${result.error}` : "";
1845
1787
  return `Workspace sync ${result.outcome} on ${result.workerLabel}; HEAD ${head}; ${result.diffSizeBytes} bytes.${discarded}${error}
1846
1788
  `;
1847
1789
  }
1848
- function summarizeK8sHistory(history) {
1849
- if (history.envelope.length === 0) {
1850
- return {
1851
- cpuMinNanoCores: null,
1852
- cpuMaxNanoCores: null,
1853
- memoryMinBytes: null,
1854
- memoryMaxBytes: null,
1855
- sampleCount: 0
1856
- };
1857
- }
1858
- return {
1859
- cpuMinNanoCores: Math.min(...history.envelope.map((point) => point.cpuMinNanoCores)),
1860
- cpuMaxNanoCores: Math.max(...history.envelope.map((point) => point.cpuMaxNanoCores)),
1861
- memoryMinBytes: Math.min(...history.envelope.map((point) => point.memoryMinBytes)),
1862
- memoryMaxBytes: Math.max(...history.envelope.map((point) => point.memoryMaxBytes)),
1863
- sampleCount: history.envelope.reduce((total, point) => total + point.sampleCount, 0)
1864
- };
1865
- }
1866
- async function mapWithConcurrency(items, concurrency, fn) {
1867
- const results = new Array(items.length);
1868
- let nextIndex = 0;
1869
- await Promise.all(
1870
- Array.from({ length: Math.min(concurrency, items.length) }, async () => {
1871
- while (nextIndex < items.length) {
1872
- const index = nextIndex++;
1873
- const item = items[index];
1874
- if (item !== void 0) results[index] = await fn(item);
1875
- }
1876
- })
1877
- );
1878
- return results;
1879
- }
1880
- async function collectK8sUsage(client, options) {
1881
- const resources = await client.k8s.resources();
1882
- const candidates = resources.workloads.flatMap((workload) => workload.containers.map((container) => ({ workload, container }))).filter(({ workload, container }) => {
1883
- const workloadMatches = !options.workload || options.workload === workload.name || options.workload === `${workload.namespace}/${workload.name}` || options.workload === workload.uid;
1884
- return (!options.namespace || options.namespace === workload.namespace) && workloadMatches && (!options.container || options.container === container.name);
1885
- }).sort(
1886
- (left, right) => left.workload.namespace.localeCompare(right.workload.namespace) || left.workload.name.localeCompare(right.workload.name) || left.container.name.localeCompare(right.container.name)
1887
- );
1888
- if (candidates.length === 0 && (options.namespace || options.workload || options.container)) {
1889
- throw new Error("No managed-vCluster workload containers matched the requested filters");
1890
- }
1891
- const entries = await mapWithConcurrency(candidates, 8, async ({ workload, container }) => {
1892
- const history = await client.k8s.resourceHistory({ workloadUid: workload.uid, containerName: container.name, window: options.window });
1893
- return {
1894
- workload: {
1895
- uid: workload.uid,
1896
- kind: workload.kind,
1897
- namespace: workload.namespace,
1898
- name: workload.name,
1899
- replicas: workload.replicas,
1900
- readyReplicas: workload.readyReplicas
1901
- },
1902
- container: {
1903
- name: container.name,
1904
- currentUsage: container.currentUsage,
1905
- pods: container.pods
1906
- },
1907
- sampledPodCount: container.pods.filter((pod) => pod.cpuNanoCores !== null || pod.memoryBytes !== null).length,
1908
- summary: summarizeK8sHistory(history),
1909
- history
1910
- };
1911
- });
1912
- return {
1913
- window: options.window,
1914
- collectedAt: resources.collectedAt,
1915
- metricsFreshAt: resources.metricsFreshAt,
1916
- metricsStale: resources.metricsStale,
1917
- filters: {
1918
- namespace: options.namespace,
1919
- workload: options.workload,
1920
- container: options.container
1921
- },
1922
- entries
1923
- };
1924
- }
1925
- function formatDecimal(value) {
1926
- if (value >= 100) return value.toFixed(0);
1927
- if (value >= 10) return value.toFixed(1).replace(/\.0$/, "");
1928
- return value.toFixed(2).replace(/\.0+$/, "").replace(/(\.\d)0$/, "$1");
1929
- }
1930
- function formatK8sCpu(value) {
1931
- if (value === null) return "-";
1932
- const milliCores = value / 1e6;
1933
- return `${formatDecimal(milliCores)}m`;
1934
- }
1935
- function formatK8sMemory(value) {
1936
- if (value === null) return "-";
1937
- const units = ["B", "Ki", "Mi", "Gi", "Ti"];
1938
- let amount = value;
1939
- let unitIndex = 0;
1940
- while (amount >= 1024 && unitIndex < units.length - 1) {
1941
- amount /= 1024;
1942
- unitIndex += 1;
1943
- }
1944
- return `${formatDecimal(amount)}${units[unitIndex]}`;
1945
- }
1946
- function getK8sUsageState(entry) {
1947
- const hasHistory = entry.history.envelope.length > 0;
1948
- const terminalPods = entry.container.pods.filter((pod) => pod.phase === "Succeeded" || pod.phase === "Failed").length;
1949
- const inactive = entry.sampledPodCount === 0 && (entry.workload.replicas === 0 || entry.container.pods.length > 0 && terminalPods === entry.container.pods.length || entry.workload.kind === "CronJob" && entry.container.pods.length === 0);
1950
- if (inactive) return "inactive";
1951
- if (entry.sampledPodCount === 0) return hasHistory ? entry.history.stale ? "stale" : "no current" : "no data";
1952
- if (!hasHistory) return "warming";
1953
- if (entry.history.stale) return "stale";
1954
- if (entry.history.incomplete) return "partial";
1955
- return "healthy";
1956
- }
1957
- function abbreviatedK8sKind(kind) {
1958
- switch (kind) {
1959
- case "Deployment":
1960
- return "deploy";
1961
- case "StatefulSet":
1962
- return "sts";
1963
- case "DaemonSet":
1964
- return "ds";
1965
- case "CronJob":
1966
- return "cron";
1967
- case "ReplicaSet":
1968
- return "rs";
1969
- case "Job":
1970
- return "job";
1971
- case "Pod":
1972
- return "pod";
1973
- }
1974
- }
1975
- function renderK8sUsageReport(report) {
1976
- const freshness = report.metricsFreshAt ?? "unavailable";
1977
- const lines = [
1978
- `Window: ${report.window} Collector: ${report.metricsStale ? "stale" : "current"} Fresh: ${freshness}`,
1979
- "PODS counts pods with current metrics."
1980
- ];
1981
- if (report.entries.length === 0) return `${lines.join("\n")}
1982
- No managed-vCluster workload containers found.
1983
- `;
1984
- const headers = ["WORKLOAD", "CONTAINER", "PODS", "CPU NOW", "CPU MAX", "MEM NOW", "MEM MAX", "STATE"];
1985
- const grouped = /* @__PURE__ */ new Map();
1986
- for (const entry of report.entries) {
1987
- const entries = grouped.get(entry.workload.namespace) ?? [];
1988
- entries.push(entry);
1989
- grouped.set(entry.workload.namespace, entries);
1990
- }
1991
- for (const [namespace, entries] of grouped) {
1992
- const rows = entries.map((entry) => {
1993
- const state = getK8sUsageState(entry);
1994
- return [
1995
- `${abbreviatedK8sKind(entry.workload.kind)}/${entry.workload.name}`,
1996
- entry.container.name,
1997
- String(entry.sampledPodCount),
1998
- formatK8sCpu(entry.container.currentUsage.cpuNanoCores),
1999
- formatK8sCpu(entry.summary.cpuMaxNanoCores),
2000
- formatK8sMemory(entry.container.currentUsage.memoryBytes),
2001
- formatK8sMemory(entry.summary.memoryMaxBytes),
2002
- state === "healthy" ? "-" : state
2003
- ];
2004
- });
2005
- const widths = headers.map((header, column) => Math.max(header.length, ...rows.map((row) => row[column]?.length ?? 0)));
2006
- const formatRow = (row) => row.map((value, column) => column === row.length - 1 ? value : value.padEnd(widths[column] ?? value.length)).join(" ");
2007
- const separator = widths.map((width) => "-".repeat(width)).join(" ");
2008
- lines.push("", `Namespace: ${namespace}`, formatRow(headers), separator, ...rows.map(formatRow));
2009
- }
2010
- return `${lines.join("\n")}
2011
- `;
2012
- }
2013
1790
  function renderSessionDescription(session) {
2014
1791
  return [`Session: ${session.id}`, `Project: ${session.projectPath}`, `Branch: ${session.branchName}`].join("\n") + "\n";
2015
1792
  }
@@ -2936,45 +2713,6 @@ async function executeR5dctlCommand(client, json, args) {
2936
2713
  write(result, renderWorkspaceSync(result));
2937
2714
  return;
2938
2715
  }
2939
- if (first === "k8s" && second === "usage") {
2940
- const report = await collectK8sUsage(client, parseK8sUsageArgs(args.slice(2)));
2941
- write(report, renderK8sUsageReport(report));
2942
- return;
2943
- }
2944
- if (first === "vcluster" && second === "trusted-workflow") {
2945
- const subcommand = requireValue(args[2], "Missing trusted-workflow command");
2946
- if (subcommand === "add") {
2947
- const parsed = parseCommandOperands(args.slice(3), /* @__PURE__ */ new Set(["--repo", "--workflow"]), /* @__PURE__ */ new Map(), "trusted-workflow add");
2948
- if (parsed.positionals.length > 0) throw new Error(`Unexpected trusted-workflow add value: ${parsed.positionals[0]}`);
2949
- const workflow = await client.k8s.trustedWorkflows.add({
2950
- repository: requireValue(parsed.values.get("--repo"), "--repo <owner/repository> is required"),
2951
- workflowPath: requireValue(parsed.values.get("--workflow"), "--workflow <path> is required")
2952
- });
2953
- write(workflow, "Trusted GitHub workflow configured successfully.\n");
2954
- return;
2955
- }
2956
- if (subcommand === "list") {
2957
- if (args.length > 3) throw new Error(`Unexpected trusted-workflow list value: ${args[3]}`);
2958
- const workflows = await client.k8s.trustedWorkflows.list();
2959
- write(
2960
- workflows,
2961
- workflows.length === 0 ? "No trusted GitHub workflows.\n" : `${workflows.map(
2962
- (workflow) => `${workflow.id} ${workflow.repository} ${workflow.workflowPath} ${workflow.revokedAt ? "revoked" : "active"}`
2963
- ).join("\n")}
2964
- `
2965
- );
2966
- return;
2967
- }
2968
- if (subcommand === "remove") {
2969
- const workflowId = requireValue(args[3], "Missing trusted workflow id");
2970
- if (args.length > 4) throw new Error(`Unexpected trusted-workflow remove value: ${args[4]}`);
2971
- const result = await client.k8s.trustedWorkflows.revoke(workflowId);
2972
- if (!result.success) throw new Error("Trusted GitHub workflow was not found or was already revoked");
2973
- write(result, "Trusted GitHub workflow revoked.\n");
2974
- return;
2975
- }
2976
- throw new Error(`Unknown trusted-workflow command: ${subcommand}`);
2977
- }
2978
2716
  if (first === "ps" && second === "list") {
2979
2717
  const processes = await client.processes.list(parsePsListArgs(args.slice(2)));
2980
2718
  write(processes, renderProcessList(processes));
@@ -3310,12 +3048,6 @@ function resolveCommandExecution(options, rest) {
3310
3048
  text: PS_HELP_TEXT
3311
3049
  };
3312
3050
  }
3313
- if (command === "k8s" && commandArgs.length === 0) {
3314
- return {
3315
- kind: "cli-help",
3316
- text: K8S_HELP_TEXT
3317
- };
3318
- }
3319
3051
  if (command === "session" && commandArgs.length === 0) {
3320
3052
  return {
3321
3053
  kind: "cli-help",
@@ -3337,10 +3069,7 @@ function resolveCommandExecution(options, rest) {
3337
3069
  text: sharedHelp
3338
3070
  };
3339
3071
  }
3340
- return {
3341
- kind: "plugin",
3342
- pluginArgs: [...normalizedRest, "--help"]
3343
- };
3072
+ throw new Error(`Unknown command: ${normalizedRest.join(" ")}`);
3344
3073
  }
3345
3074
  if (command === "projects" || command === "sessions" || command === "workspace") {
3346
3075
  return {
@@ -3450,26 +3179,6 @@ function resolveCommandExecution(options, rest) {
3450
3179
  }
3451
3180
  throw new Error(`Unknown ps command: ${subcommand ?? ""}`.trim());
3452
3181
  }
3453
- if (command === "k8s") {
3454
- const subcommand = commandArgs[0];
3455
- if (options.project || options.branch || options.session) {
3456
- throw new Error("Project, branch, and session scopes are not supported for `k8s`");
3457
- }
3458
- if (subcommand === "usage") {
3459
- parseK8sUsageArgs(commandArgs.slice(1));
3460
- return { kind: "plugin", pluginArgs: ["k8s", "usage", ...commandArgs.slice(1)] };
3461
- }
3462
- throw new Error(`Unknown k8s command: ${subcommand ?? ""}`.trim());
3463
- }
3464
- if (command === "vcluster") {
3465
- if (options.project || options.branch || options.session) {
3466
- throw new Error("Project, branch, and session scopes are not supported for `vcluster`");
3467
- }
3468
- if (commandArgs[0] !== "trusted-workflow") {
3469
- throw new Error(`Unknown vcluster command: ${commandArgs[0] ?? ""}`.trim());
3470
- }
3471
- return { kind: "plugin", pluginArgs: ["vcluster", "trusted-workflow", ...commandArgs.slice(1)] };
3472
- }
3473
3182
  if (command === "get") {
3474
3183
  const target = commandArgs[0];
3475
3184
  if (target === "projects") {
@@ -3951,18 +3660,14 @@ export {
3951
3660
  branchDeletionConfirmationMessage,
3952
3661
  branchDeletionsConfirmationMessage,
3953
3662
  branchDeletionsFailureMessage,
3954
- collectK8sUsage,
3955
3663
  createBranchThroughPlatform,
3956
3664
  deleteBranchThroughPlatform,
3957
3665
  deleteBranchesThroughPlatform,
3958
3666
  dispatchSessionRunCommand,
3959
3667
  followR5dctlSession,
3960
- formatK8sCpu,
3961
- formatK8sMemory,
3962
3668
  formatProcessAge,
3963
3669
  formatProcessLane,
3964
3670
  getCliHelpText,
3965
- getK8sUsageState,
3966
3671
  getProjectEnvValue,
3967
3672
  getR5dctlVersion,
3968
3673
  getTransientDevicePollDelay,
@@ -3983,7 +3688,6 @@ export {
3983
3688
  parseEnvRequestResponseArgs,
3984
3689
  parseGetEnvsArgs,
3985
3690
  parseGlobalArgs,
3986
- parseK8sUsageArgs,
3987
3691
  parsePromptArgs,
3988
3692
  parsePsHistoryArgs,
3989
3693
  parsePsListArgs,
@@ -4008,7 +3712,6 @@ export {
4008
3712
  renderConversationWorkResponse,
4009
3713
  renderDeviceAuthorizationPrompt,
4010
3714
  renderEnvValues,
4011
- renderK8sUsageReport,
4012
3715
  renderProcessHistory,
4013
3716
  renderProcessInspection,
4014
3717
  renderProcessList,
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.126",
3
+ "version": "0.0.127",
4
4
  "type": "module"
5
5
  }
@@ -1,4 +1,4 @@
1
- import { R5dctlApiError, R5dctlClient, type R5dctlConversationForkResponse, type R5dctlConversationHeadResponse, type R5dctlConversationRenderOptions, type R5dctlConversationResponse, type R5dctlConversationNodeResponse, type R5dctlConversationOverviewResponse, type R5dctlConversationWorkDetail, type R5dctlConversationWorkResponse, type R5dctlEnvData, type R5dctlK8sResourceHistory, type R5dctlK8sUsage, type R5dctlK8sWorkload, type R5dctlProcessInspection, type R5dctlProcessListInput, type R5dctlProcessLog, type R5dctlProcessRun, type R5dctlWorkerCapacityReport, type R5dctlBranch, type R5dctlBranchDeletionStatus, type R5dctlBranchDescription, type R5dctlBranchOperation, type R5dctlSessionSummary, type R5dctlSessionClaim, type R5dctlSessionClaimListResponse, type R5dctlSessionEvent, type R5dctlSessionStartInput, type R5dctlWorkspaceStatus, type R5dctlWorkspaceSyncResult, type R5dctlWorkingTreeMode, type R5dctlWorktreeSource, type R5dctlPromptDelivery, type R5dctlSessionMode, type ChatMode, type ModelTier } from "@ricsam/r5d-api";
1
+ import { R5dctlApiError, R5dctlClient, type R5dctlConversationForkResponse, type R5dctlConversationHeadResponse, type R5dctlConversationRenderOptions, type R5dctlConversationResponse, type R5dctlConversationNodeResponse, type R5dctlConversationOverviewResponse, type R5dctlConversationWorkDetail, type R5dctlConversationWorkResponse, type R5dctlEnvData, type R5dctlProcessInspection, type R5dctlProcessListInput, type R5dctlProcessLog, type R5dctlProcessRun, type R5dctlWorkerCapacityReport, type R5dctlBranch, type R5dctlBranchDeletionStatus, type R5dctlBranchDescription, type R5dctlBranchOperation, type R5dctlSessionSummary, type R5dctlSessionClaim, type R5dctlSessionClaimListResponse, type R5dctlSessionEvent, type R5dctlSessionStartInput, type R5dctlWorkspaceStatus, type R5dctlWorkspaceSyncResult, type R5dctlWorkingTreeMode, type R5dctlWorktreeSource, type R5dctlPromptDelivery, type R5dctlSessionMode, type ChatMode, type ModelTier } from "@ricsam/r5d-api";
2
2
  export type GlobalOptions = {
3
3
  baseUrl?: string;
4
4
  json: boolean;
@@ -260,13 +260,6 @@ export declare function parseShellArgs(args: string[]): {
260
260
  };
261
261
  export declare function parsePsListArgs(args: string[]): R5dctlProcessListInput;
262
262
  export declare function parsePsHistoryArgs(args: string[]): R5dctlProcessListInput;
263
- export type K8sUsageOptions = {
264
- namespace?: string;
265
- workload?: string;
266
- container?: string;
267
- window: "24h" | "7d";
268
- };
269
- export declare function parseK8sUsageArgs(args: string[]): K8sUsageOptions;
270
263
  export declare function renderDeviceAuthorizationPrompt(input: {
271
264
  verificationUri: string;
272
265
  userCode: string;
@@ -283,41 +276,6 @@ export declare function renderWorkerCapacity(workerLabel: string, capacity: R5dc
283
276
  export declare function renderWorkspaceStatus(status: R5dctlWorkspaceStatus): string;
284
277
  export declare function renderBranchList(branches: R5dctlBranch[]): string;
285
278
  export declare function renderWorkspaceSync(result: R5dctlWorkspaceSyncResult): string;
286
- export type K8sUsageSummary = {
287
- cpuMinNanoCores: number | null;
288
- cpuMaxNanoCores: number | null;
289
- memoryMinBytes: number | null;
290
- memoryMaxBytes: number | null;
291
- sampleCount: number;
292
- };
293
- export type K8sUsageReport = {
294
- window: "24h" | "7d";
295
- collectedAt: string;
296
- metricsFreshAt: string | null;
297
- metricsStale: boolean;
298
- filters: Omit<K8sUsageOptions, "window">;
299
- entries: Array<{
300
- workload: Pick<R5dctlK8sWorkload, "uid" | "kind" | "namespace" | "name" | "replicas" | "readyReplicas">;
301
- container: {
302
- name: string;
303
- currentUsage: R5dctlK8sUsage;
304
- pods: Array<R5dctlK8sUsage & {
305
- podUid: string;
306
- podName: string;
307
- phase: string | null;
308
- }>;
309
- };
310
- sampledPodCount: number;
311
- summary: K8sUsageSummary;
312
- history: R5dctlK8sResourceHistory;
313
- }>;
314
- };
315
- export declare function collectK8sUsage(client: Pick<R5dctlClient, "k8s">, options: K8sUsageOptions): Promise<K8sUsageReport>;
316
- export declare function formatK8sCpu(value: number | null): string;
317
- export declare function formatK8sMemory(value: number | null): string;
318
- export type K8sUsageState = "healthy" | "partial" | "stale" | "inactive" | "warming" | "no data" | "no current";
319
- export declare function getK8sUsageState(entry: K8sUsageReport["entries"][number]): K8sUsageState;
320
- export declare function renderK8sUsageReport(report: K8sUsageReport): string;
321
279
  export declare function formatProcessAge(startedAt: string, nowMs?: number): string;
322
280
  export declare function renderProcessList(processes: R5dctlProcessRun[], nowMs?: number): string;
323
281
  /** `general`, `control`, `queued:general`, or `-` when the worker reported nothing for this run. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5dctl",
3
- "version": "0.0.126",
3
+ "version": "0.0.127",
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.126",
29
+ "@ricsam/r5d-api": "^0.0.127",
30
30
  "dotenv": "^17",
31
31
  "qrcode": "^1.5.4",
32
32
  "ws": "^8.18.3"