@ricsam/r5dctl 0.0.74 → 0.0.76
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 +2 -15
- package/dist/cjs/cli.cjs +29 -230
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/cli.mjs +28 -226
- package/dist/mjs/package.json +1 -1
- package/dist/types/cli.d.ts +5 -69
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -90,13 +90,6 @@ r5dctl session status <session-id>
|
|
|
90
90
|
r5dctl session prompt --worker <label> --mode agent --model max <session-id> "Also check the migration"
|
|
91
91
|
r5dctl session stop <session-id>
|
|
92
92
|
|
|
93
|
-
r5dctl -p <project> merge fix/tests
|
|
94
|
-
r5dctl -p <project> merge --worker <label> --create-conflict-worktree fix/tests
|
|
95
|
-
r5dctl -p <project> merge --worker <label> --launch-conflict-resolution-agent fix/tests
|
|
96
|
-
r5dctl -p <project> merge --worker <label> --launch-conflict-resolution-agent --no-wait fix/tests
|
|
97
|
-
r5dctl -p <project> merge status <attempt-id>
|
|
98
|
-
r5dctl -p <project> merge finish --worker <label> conflicts/fix-tests --summary "Resolved the conflicts"
|
|
99
|
-
|
|
100
93
|
r5dctl -p <project> -b <branch> shell
|
|
101
94
|
r5dctl -p <project> -b <branch> shell -c "bun test"
|
|
102
95
|
|
|
@@ -121,15 +114,9 @@ repository. Trust applies to that workflow path on every Git ref and grants
|
|
|
121
114
|
cluster-admin, so protect workflow changes and do not invoke it for untrusted
|
|
122
115
|
pull requests.
|
|
123
116
|
|
|
124
|
-
`session start` creates an ordinary agent-mode chat on an explicitly selected existing worktree, or creates a named worktree from an explicit `worktree:<branch>` source. It requires project, worker, model, and prompt and never infers them from the current shell.
|
|
125
|
-
|
|
126
|
-
Add `-f`/`--follow`/`--watch` to `session start` to attach after enqueue, or to `conversation` to print the current transcript and follow new output. Assistant text is written to stdout and lifecycle/tool progress to stderr; `--tools` includes tool calls and results. With global `--json`, follow mode emits one JSON event per line. Ctrl-C only detaches and never stops the session. The CLI reconnects transiently interrupted event streams and resynchronizes committed conversation revisions without repeating assistant text.
|
|
127
|
-
|
|
128
|
-
`merge` merges a managed source worktree into its recorded parent. By default conflicts are reported without creating more work. `--create-conflict-worktree` prepares a manual conflict worktree, while `--launch-conflict-resolution-agent` starts the dedicated merge-conflict resolver; those strategies are mutually exclusive. A worker-bound shell credential supplies its own worker automatically; otherwise pass `--worker`. Finish a reviewed manual resolution with `merge finish`.
|
|
129
|
-
|
|
130
|
-
Merging is lockless and optimistic: nothing blocks agents from continuing to work on the involved branches. Every merge pins the branch tips it previewed and publishes through an atomic compare-and-swap, and a concurrent publication simply retries. When a resolver agent finishes after the target advanced, the platform automatically continues the merge — publishing directly if the refreshed merge is conflict-free, or launching a fresh resolver attempt (whose prompt references the superseded session's resolution) — repeating until one resolution publishes. Superseded attempts surface the follow-up attempt id in `merge status`. Only manual conflict worktrees stop at `stale`: re-run `merge` to start a fresh resolution.
|
|
117
|
+
`session start` creates an ordinary agent-mode chat on an explicitly selected existing worktree, or creates a named linked worktree from an explicit `worktree:<branch>` source. It requires project, worker, model, and prompt and never infers them from the current shell. Start returns a durable `provisioning` handle immediately; workspace synchronization, linked-worktree creation, and prompt enqueue continue in the background and are visible through `session status`. Idempotent request retries return the same handle. Prompts return after durable enqueue. Task specialization belongs in the prompt; there are no predefined debug, explore, research, or test agents. `session stop` returns as soon as the agent run is stopped; the stopped worktree's workspace Git synchronization finishes asynchronously behind the response.
|
|
131
118
|
|
|
132
|
-
|
|
119
|
+
Add `-f`/`--follow`/`--watch` to `session start` to poll the provisioning handle and attach after enqueue, or to `conversation` to print the current transcript and follow new output. Assistant text is written to stdout and lifecycle/tool progress to stderr; `--tools` includes tool calls and results. With global `--json`, follow mode emits one JSON event per line. Ctrl-C only detaches and never stops the session. The CLI reconnects transiently interrupted event streams and resynchronizes committed conversation revisions without repeating assistant text.
|
|
133
120
|
|
|
134
121
|
`shell` connects to the same live worker PTY as the web Shell tab. Without `-c` it attaches the local terminal interactively. With `-c`/`--command`, it runs the supplied shell expression, streams combined PTY output, and exits with the remote command's status. Because command output uses a PTY, stdout and stderr are combined and programs may emit colors or other terminal control sequences.
|
|
135
122
|
|
package/dist/cjs/cli.cjs
CHANGED
|
@@ -30,7 +30,6 @@ var cli_exports = {};
|
|
|
30
30
|
__export(cli_exports, {
|
|
31
31
|
advanceTransientDevicePollBackoff: () => advanceTransientDevicePollBackoff,
|
|
32
32
|
collectK8sUsage: () => collectK8sUsage,
|
|
33
|
-
dispatchMergeCommand: () => dispatchMergeCommand,
|
|
34
33
|
dispatchSessionRunCommand: () => dispatchSessionRunCommand,
|
|
35
34
|
followR5dctlSession: () => followR5dctlSession,
|
|
36
35
|
formatK8sCpu: () => formatK8sCpu,
|
|
@@ -42,7 +41,6 @@ __export(cli_exports, {
|
|
|
42
41
|
getR5dctlVersion: () => getR5dctlVersion,
|
|
43
42
|
getTransientDevicePollDelay: () => getTransientDevicePollDelay,
|
|
44
43
|
handleAuthLogin: () => handleAuthLogin,
|
|
45
|
-
isMergeAttemptSettled: () => isMergeAttemptSettled,
|
|
46
44
|
main: () => main,
|
|
47
45
|
parseAnswerEnvRequestCommandArgs: () => parseAnswerEnvRequestCommandArgs,
|
|
48
46
|
parseAnswerFlags: () => parseAnswerFlags,
|
|
@@ -56,7 +54,6 @@ __export(cli_exports, {
|
|
|
56
54
|
parseGetEnvsArgs: () => parseGetEnvsArgs,
|
|
57
55
|
parseGlobalArgs: () => parseGlobalArgs,
|
|
58
56
|
parseK8sUsageArgs: () => parseK8sUsageArgs,
|
|
59
|
-
parseMergeCommand: () => parseMergeCommand,
|
|
60
57
|
parsePromptArgs: () => parsePromptArgs,
|
|
61
58
|
parsePsHistoryArgs: () => parsePsHistoryArgs,
|
|
62
59
|
parsePsListArgs: () => parsePsListArgs,
|
|
@@ -80,10 +77,10 @@ __export(cli_exports, {
|
|
|
80
77
|
renderSessionRunStatus: () => renderSessionRunStatus,
|
|
81
78
|
renderWorkspaceStatus: () => renderWorkspaceStatus,
|
|
82
79
|
renderWorkspaceSync: () => renderWorkspaceSync,
|
|
83
|
-
renderWorktreeMerge: () => renderWorktreeMerge,
|
|
84
80
|
resolveCommandExecution: () => resolveCommandExecution,
|
|
85
81
|
runR5dctlCli: () => runR5dctlCli,
|
|
86
82
|
summarizeEnvData: () => summarizeEnvData,
|
|
83
|
+
waitForSessionProvisioning: () => waitForSessionProvisioning,
|
|
87
84
|
writeConfig: () => writeConfig
|
|
88
85
|
});
|
|
89
86
|
module.exports = __toCommonJS(cli_exports);
|
|
@@ -97,7 +94,7 @@ var import_promises = require("node:timers/promises");
|
|
|
97
94
|
var import_dotenv = require("dotenv");
|
|
98
95
|
var import_r5d_api = require("@ricsam/r5d-api");
|
|
99
96
|
var import_shell = require("./shell.cjs");
|
|
100
|
-
const CHAT_MODES = /* @__PURE__ */ new Set(["ask", "plan", "agent", "large_diff_remediation"
|
|
97
|
+
const CHAT_MODES = /* @__PURE__ */ new Set(["ask", "plan", "agent", "large_diff_remediation"]);
|
|
101
98
|
const R5DCTL_SESSION_MODES = /* @__PURE__ */ new Set(["ask", "plan", "agent"]);
|
|
102
99
|
const MODEL_TIERS = /* @__PURE__ */ new Set(["low", "medium", "high", "max"]);
|
|
103
100
|
const R5DCTL_PACKAGE_NAME = "@ricsam/r5dctl";
|
|
@@ -168,16 +165,6 @@ const SESSION_RUN_HELP_TEXT = [
|
|
|
168
165
|
"Use -f/--follow/--watch to attach after a start; Ctrl-C detaches without stopping the session.",
|
|
169
166
|
""
|
|
170
167
|
].join("\n");
|
|
171
|
-
const MERGE_HELP_TEXT = [
|
|
172
|
-
"Usage:",
|
|
173
|
-
" r5dctl -p <project> merge [--worker <label>] [--create-conflict-worktree|--launch-conflict-resolution-agent] [--no-wait] <source-worktree>",
|
|
174
|
-
" r5dctl -p <project> merge status <attempt-id>",
|
|
175
|
-
' r5dctl -p <project> merge finish --worker <label> [--summary "<summary>"] <conflict-worktree>',
|
|
176
|
-
"",
|
|
177
|
-
"Merge a managed worktree into its recorded parent worktree.",
|
|
178
|
-
"Conflict worktrees provision in the background; merge waits by default and --no-wait returns the attempt immediately.",
|
|
179
|
-
""
|
|
180
|
-
].join("\n");
|
|
181
168
|
const SHARED_HELP_ENTRIES = [
|
|
182
169
|
{ section: "auth", usage: "auth status", description: "Show the current authenticated user and credential source." },
|
|
183
170
|
{ section: "auth", usage: "auth logout", description: "Revoke the current credential and clear saved auth." },
|
|
@@ -188,16 +175,16 @@ const SHARED_HELP_ENTRIES = [
|
|
|
188
175
|
},
|
|
189
176
|
{ section: "auth", usage: "auth api-key list", description: "List API keys for the current account." },
|
|
190
177
|
{ section: "auth", usage: "auth api-key revoke <key-id>", description: "Revoke an API key." },
|
|
191
|
-
{ section: "workspace", usage: "workspace status", description: "Inspect
|
|
178
|
+
{ section: "workspace", usage: "workspace status", description: "Inspect per-user workspace Git state and active remediation." },
|
|
192
179
|
{
|
|
193
180
|
section: "workspace",
|
|
194
181
|
usage: "workspace sync [--worker <label>]",
|
|
195
|
-
description: "
|
|
182
|
+
description: "Commit, rebase, and push a connected worker's workspace now."
|
|
196
183
|
},
|
|
197
184
|
{
|
|
198
185
|
section: "workspace",
|
|
199
186
|
usage: "workspace reset [--worker <label>] --confirm",
|
|
200
|
-
description: "Destructively discard a blocked
|
|
187
|
+
description: "Destructively discard a blocked local workspace commit and restore origin/main."
|
|
201
188
|
},
|
|
202
189
|
{ section: "projects", usage: "get projects", description: "List projects you can access." },
|
|
203
190
|
{ section: "projects", usage: "describe project <namespace/name|id>", description: "Show details for a project." },
|
|
@@ -334,22 +321,7 @@ const SHARED_HELP_ENTRIES = [
|
|
|
334
321
|
usage: "ps inspect <run-id>",
|
|
335
322
|
description: "Inspect process metadata and bounded stdout/stderr tails."
|
|
336
323
|
},
|
|
337
|
-
{ section: "processes", usage: "ps stop <run-id>", description: "Gracefully stop an active process with SIGTERM." }
|
|
338
|
-
{
|
|
339
|
-
section: "merge",
|
|
340
|
-
usage: "-p <project> merge [--worker <label>] [--create-conflict-worktree|--launch-conflict-resolution-agent] [--no-wait] <source-worktree>",
|
|
341
|
-
description: "Merge a worktree into its recorded parent, with an explicit conflict strategy."
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
section: "merge",
|
|
345
|
-
usage: "-p <project> merge status <attempt-id>",
|
|
346
|
-
description: "Show a merge attempt's provisioning and resolution status."
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
section: "merge",
|
|
350
|
-
usage: '-p <project> merge finish --worker <label> [--summary "<summary>"] <conflict-worktree>',
|
|
351
|
-
description: "Publish and finish a manually resolved conflict worktree."
|
|
352
|
-
}
|
|
324
|
+
{ section: "processes", usage: "ps stop <run-id>", description: "Gracefully stop an active process with SIGTERM." }
|
|
353
325
|
];
|
|
354
326
|
const HELP_SECTION_ORDER = [
|
|
355
327
|
"auth",
|
|
@@ -360,8 +332,7 @@ const HELP_SECTION_ORDER = [
|
|
|
360
332
|
"sessions",
|
|
361
333
|
"kubernetes",
|
|
362
334
|
"processes",
|
|
363
|
-
"shell"
|
|
364
|
-
"merge"
|
|
335
|
+
"shell"
|
|
365
336
|
];
|
|
366
337
|
const HELP_SECTION_TITLES = {
|
|
367
338
|
auth: "Auth",
|
|
@@ -372,8 +343,7 @@ const HELP_SECTION_TITLES = {
|
|
|
372
343
|
sessions: "Sessions",
|
|
373
344
|
kubernetes: "Kubernetes",
|
|
374
345
|
processes: "Processes",
|
|
375
|
-
shell: "Shell"
|
|
376
|
-
merge: "Worktree merging"
|
|
346
|
+
shell: "Shell"
|
|
377
347
|
};
|
|
378
348
|
function getCliHelpText() {
|
|
379
349
|
const entries = [...CLI_ONLY_HELP_ENTRIES, ...SHARED_HELP_ENTRIES];
|
|
@@ -651,56 +621,6 @@ function parseSessionRunCommand(options, args) {
|
|
|
651
621
|
}
|
|
652
622
|
throw new Error(`Unknown session command: ${subcommand}`);
|
|
653
623
|
}
|
|
654
|
-
function parseMergeCommand(options, args) {
|
|
655
|
-
const project = requireValue(options.project, "--project/-p is required for `merge`");
|
|
656
|
-
if (options.branch) throw new Error("--branch/-b is not supported for `merge`; pass the source worktree explicitly");
|
|
657
|
-
if (options.session) throw new Error("--session/-s is not supported for `merge`");
|
|
658
|
-
if (args[0] === "finish") {
|
|
659
|
-
const parsed2 = parseCommandOperands(args.slice(1), /* @__PURE__ */ new Set(["--worker", "--summary"]), /* @__PURE__ */ new Map(), "merge finish");
|
|
660
|
-
const conflictWorktree = requireValue(parsed2.positionals[0], "Conflict worktree is required for `merge finish`");
|
|
661
|
-
if (parsed2.positionals.length > 1) throw new Error(`Unexpected merge finish argument: ${parsed2.positionals[1]}`);
|
|
662
|
-
return {
|
|
663
|
-
kind: "finish",
|
|
664
|
-
project,
|
|
665
|
-
conflictWorktree,
|
|
666
|
-
worker: requireWorker(parsed2.values),
|
|
667
|
-
...parsed2.values.get("--summary")?.trim() ? { summary: parsed2.values.get("--summary").trim() } : {}
|
|
668
|
-
};
|
|
669
|
-
}
|
|
670
|
-
if (args[0] === "status") {
|
|
671
|
-
const parsed2 = parseCommandOperands(args.slice(1), /* @__PURE__ */ new Set(), /* @__PURE__ */ new Map(), "merge status");
|
|
672
|
-
const attemptId = requireValue(parsed2.positionals[0], "Attempt id is required for `merge status`");
|
|
673
|
-
if (parsed2.positionals.length > 1) throw new Error(`Unexpected merge status argument: ${parsed2.positionals[1]}`);
|
|
674
|
-
return { kind: "status", project, attemptId };
|
|
675
|
-
}
|
|
676
|
-
const parsed = parseCommandOperands(
|
|
677
|
-
args,
|
|
678
|
-
/* @__PURE__ */ new Set(["--worker"]),
|
|
679
|
-
/* @__PURE__ */ new Map([
|
|
680
|
-
["--create-conflict-worktree", "--create-conflict-worktree"],
|
|
681
|
-
["--launch-conflict-resolution-agent", "--launch-conflict-resolution-agent"],
|
|
682
|
-
["--no-wait", "--no-wait"]
|
|
683
|
-
]),
|
|
684
|
-
"merge"
|
|
685
|
-
);
|
|
686
|
-
const sourceWorktree = requireValue(parsed.positionals[0], "Source worktree is required for `merge`");
|
|
687
|
-
if (parsed.positionals.length > 1) throw new Error(`Unexpected merge argument: ${parsed.positionals[1]}`);
|
|
688
|
-
const createWorktree = parsed.booleans.has("--create-conflict-worktree");
|
|
689
|
-
const launchAgent = parsed.booleans.has("--launch-conflict-resolution-agent");
|
|
690
|
-
if (createWorktree && launchAgent) {
|
|
691
|
-
throw new Error("Use only one of --create-conflict-worktree or --launch-conflict-resolution-agent");
|
|
692
|
-
}
|
|
693
|
-
const conflictMode = createWorktree ? "worktree" : launchAgent ? "agent" : "none";
|
|
694
|
-
const worker = parsed.values.get("--worker")?.trim();
|
|
695
|
-
return {
|
|
696
|
-
kind: "merge",
|
|
697
|
-
project,
|
|
698
|
-
sourceWorktree,
|
|
699
|
-
conflictMode,
|
|
700
|
-
...worker ? { worker } : {},
|
|
701
|
-
...parsed.booleans.has("--no-wait") ? { noWait: true } : {}
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
624
|
function assertAuthLoginArgs(args) {
|
|
705
625
|
const valueFlags = /* @__PURE__ */ new Set(["--device-name", "--worker-label"]);
|
|
706
626
|
const booleanFlags = /* @__PURE__ */ new Set(["--no-open", "--no-qr"]);
|
|
@@ -1527,16 +1447,15 @@ function renderWorkspaceStatus(status) {
|
|
|
1527
1447
|
`Workspace HEAD: ${status.head ?? "(not initialized)"}`,
|
|
1528
1448
|
`Latest sync: ${status.latestSync ? `${status.latestSync.outcome} on ${status.latestSync.workerLabel}` : "(none)"}`,
|
|
1529
1449
|
`Remediation: ${status.incident ? `${status.incident.kind} ${status.incident.status} (${status.incident.id}) on ${status.incident.originWorkerLabel}` : "none"}`,
|
|
1530
|
-
`Materialization: ${status.materialization ? `${status.materialization.state}; ${status.materialization.materializedHead ?? "(none)"} -> ${status.materialization.desiredHead ?? "(none)"}; lag ${status.materialization.lagMs}ms` : "not initialized"}`,
|
|
1531
1450
|
...status.workers.map(
|
|
1532
|
-
(worker) => `Worker ${worker.workerLabel}: ${worker.
|
|
1451
|
+
(worker) => `Worker ${worker.workerLabel}: ${worker.configured ? "configured" : "configuring"}; head ${worker.localHead ?? "(none)"}; pending checkouts ${worker.pendingCheckouts.length}`
|
|
1533
1452
|
)
|
|
1534
1453
|
];
|
|
1535
1454
|
return `${lines.join("\n")}
|
|
1536
1455
|
`;
|
|
1537
1456
|
}
|
|
1538
1457
|
function renderWorkspaceSync(result) {
|
|
1539
|
-
const head = result.publishedHead ?? result.
|
|
1458
|
+
const head = result.publishedHead ?? result.localHead ?? result.startingHead ?? "(none)";
|
|
1540
1459
|
const discarded = result.discardedPaths.length > 0 ? `
|
|
1541
1460
|
Discarded paths: ${result.discardedPaths.join(", ")}` : "";
|
|
1542
1461
|
const error = result.error ? `
|
|
@@ -1912,30 +1831,6 @@ function formatStatusValue(value) {
|
|
|
1912
1831
|
}
|
|
1913
1832
|
return value === void 0 || value === null ? void 0 : String(value);
|
|
1914
1833
|
}
|
|
1915
|
-
function appendMergeDetails(lines, merge) {
|
|
1916
|
-
const mergeStatus = formatStatusValue(merge.status);
|
|
1917
|
-
lines.push(`Merge: ${mergeStatus ?? "pending"}`);
|
|
1918
|
-
for (const [label, key] of [
|
|
1919
|
-
["Attempt", "attemptId"],
|
|
1920
|
-
["Source worktree", "sourceWorktree"],
|
|
1921
|
-
["Target worktree", "targetWorktree"],
|
|
1922
|
-
["Commit", "commitHash"],
|
|
1923
|
-
["Resolver agent", "resolverSessionId"],
|
|
1924
|
-
["Conflict worktree", "conflictWorktree"],
|
|
1925
|
-
["Resolver worktree", "folderPath"]
|
|
1926
|
-
]) {
|
|
1927
|
-
const value = responseString(merge, key);
|
|
1928
|
-
if (value) lines.push(`${label}: ${value}`);
|
|
1929
|
-
}
|
|
1930
|
-
const conflictedFiles = Array.isArray(merge.conflictedFiles) ? merge.conflictedFiles.filter((file) => typeof file === "string") : [];
|
|
1931
|
-
if (conflictedFiles.length > 0) {
|
|
1932
|
-
lines.push("", "Conflicts:", ...conflictedFiles.map((file) => `- ${file}`));
|
|
1933
|
-
}
|
|
1934
|
-
const message = responseString(merge, "message");
|
|
1935
|
-
if (message) lines.push("", message);
|
|
1936
|
-
const failureReason = responseString(merge, "failureReason");
|
|
1937
|
-
if (failureReason) lines.push(`Failure: ${failureReason}`);
|
|
1938
|
-
}
|
|
1939
1834
|
function renderSessionRunStart(session) {
|
|
1940
1835
|
const lines = [
|
|
1941
1836
|
`Session: ${responseString(session, "sessionId") ?? "(unknown)"}`,
|
|
@@ -1984,28 +1879,6 @@ function renderSessionRunStatus(session) {
|
|
|
1984
1879
|
return `${lines.join("\n")}
|
|
1985
1880
|
`;
|
|
1986
1881
|
}
|
|
1987
|
-
function renderWorktreeMerge(result, input) {
|
|
1988
|
-
const lines = [];
|
|
1989
|
-
appendMergeDetails(lines, result);
|
|
1990
|
-
const status = responseString(result, "status");
|
|
1991
|
-
const conflictWorktree = responseString(result, "conflictWorktree");
|
|
1992
|
-
const resolverSessionId = responseString(result, "resolverSessionId");
|
|
1993
|
-
const attemptId = responseString(result, "attemptId");
|
|
1994
|
-
const worker = responseString(result, "worker") ?? input.worker;
|
|
1995
|
-
if (resolverSessionId) lines.push("", `Resolver session: ${resolverSessionId}`, ` r5dctl session stop ${resolverSessionId}`);
|
|
1996
|
-
if (conflictWorktree && worker && ["conflicts", "conflict_worktree_created", "resolving"].includes(status ?? "")) {
|
|
1997
|
-
lines.push(
|
|
1998
|
-
"",
|
|
1999
|
-
"Finish after resolving and reviewing the conflict worktree:",
|
|
2000
|
-
` r5dctl -p ${input.project} merge finish --worker ${worker} ${conflictWorktree} --summary "<summary>"`
|
|
2001
|
-
);
|
|
2002
|
-
}
|
|
2003
|
-
if (attemptId && (status === "provisioning" || status === "resolving" && result.resolverAgentRunning === false)) {
|
|
2004
|
-
lines.push("", "Check progress:", ` r5dctl -p ${input.project} merge status ${attemptId}`);
|
|
2005
|
-
}
|
|
2006
|
-
return `${lines.join("\n")}
|
|
2007
|
-
`;
|
|
2008
|
-
}
|
|
2009
1882
|
async function dispatchSessionRunCommand(client, command) {
|
|
2010
1883
|
if (command.kind === "start") {
|
|
2011
1884
|
const commonInput = {
|
|
@@ -2042,70 +1915,16 @@ async function dispatchSessionRunCommand(client, command) {
|
|
|
2042
1915
|
const data = await client.sessions.stop(command.sessionId);
|
|
2043
1916
|
return { data, human: renderSessionRunStatus(data) };
|
|
2044
1917
|
}
|
|
2045
|
-
|
|
2046
|
-
const
|
|
2047
|
-
const
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
}
|
|
2054
|
-
async function pollMergeAttemptUntilSettled(client, project, attemptId, initial, options) {
|
|
2055
|
-
const intervalMs = options.pollIntervalMs ?? MERGE_POLL_INTERVAL_MS;
|
|
2056
|
-
const timeoutMs = options.pollTimeoutMs ?? MERGE_POLL_TIMEOUT_MS;
|
|
2057
|
-
const sleep2 = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
2058
|
-
const onProgress = options.onProgress ?? (() => {
|
|
2059
|
-
});
|
|
2060
|
-
let latest = initial;
|
|
2061
|
-
let worktreeReadyReported = latest.worktreeReady === true;
|
|
2062
|
-
let consecutiveFailures = 0;
|
|
2063
|
-
let waitedMs = 0;
|
|
2064
|
-
while (!isMergeAttemptSettled(latest)) {
|
|
2065
|
-
if (waitedMs >= timeoutMs) {
|
|
2066
|
-
onProgress(`Still waiting after ${Math.round(timeoutMs / 6e4)} minutes; check later with: r5dctl -p ${project} merge status ${attemptId}`);
|
|
2067
|
-
return latest;
|
|
2068
|
-
}
|
|
2069
|
-
await sleep2(intervalMs);
|
|
2070
|
-
waitedMs += intervalMs;
|
|
2071
|
-
try {
|
|
2072
|
-
latest = await client.projects.worktrees.mergeAttempt(project, attemptId);
|
|
2073
|
-
consecutiveFailures = 0;
|
|
2074
|
-
} catch (error) {
|
|
2075
|
-
consecutiveFailures += 1;
|
|
2076
|
-
if (consecutiveFailures >= MERGE_POLL_MAX_CONSECUTIVE_FAILURES) throw error;
|
|
2077
|
-
continue;
|
|
2078
|
-
}
|
|
2079
|
-
if (!worktreeReadyReported && latest.worktreeReady === true) {
|
|
2080
|
-
worktreeReadyReported = true;
|
|
2081
|
-
onProgress("Conflict worktree ready.");
|
|
2082
|
-
}
|
|
1918
|
+
async function waitForSessionProvisioning(client, initial, options = {}) {
|
|
1919
|
+
const sessionId = requireValue(responseString(initial, "sessionId"), "Session start did not return a session id");
|
|
1920
|
+
const wait = options.wait ?? import_promises.setTimeout;
|
|
1921
|
+
const intervalMs = options.intervalMs ?? 500;
|
|
1922
|
+
let current = initial;
|
|
1923
|
+
while (formatStatusValue(current.status) === "provisioning") {
|
|
1924
|
+
await wait(intervalMs);
|
|
1925
|
+
current = await client.sessions.status(sessionId);
|
|
2083
1926
|
}
|
|
2084
|
-
return
|
|
2085
|
-
}
|
|
2086
|
-
async function dispatchMergeCommand(client, command, pollOptions = {}) {
|
|
2087
|
-
if (command.kind === "merge") {
|
|
2088
|
-
const data2 = await client.projects.worktrees.merge(command.project, command.sourceWorktree, {
|
|
2089
|
-
conflictMode: command.conflictMode,
|
|
2090
|
-
...command.worker ? { worker: command.worker } : {}
|
|
2091
|
-
});
|
|
2092
|
-
const attemptId = responseString(data2, "attemptId");
|
|
2093
|
-
if (command.noWait || !attemptId || isMergeAttemptSettled(data2)) {
|
|
2094
|
-
return { data: data2, human: renderWorktreeMerge(data2, command) };
|
|
2095
|
-
}
|
|
2096
|
-
pollOptions.onProgress?.(`Provisioning the conflict worktree (attempt ${attemptId})...`);
|
|
2097
|
-
const settled = await pollMergeAttemptUntilSettled(client, command.project, attemptId, data2, pollOptions);
|
|
2098
|
-
return { data: settled, human: renderWorktreeMerge(settled, command) };
|
|
2099
|
-
}
|
|
2100
|
-
if (command.kind === "status") {
|
|
2101
|
-
const data2 = await client.projects.worktrees.mergeAttempt(command.project, command.attemptId);
|
|
2102
|
-
return { data: data2, human: renderWorktreeMerge(data2, { project: command.project }) };
|
|
2103
|
-
}
|
|
2104
|
-
const data = await client.projects.worktrees.finishMerge(command.project, command.conflictWorktree, {
|
|
2105
|
-
worker: command.worker,
|
|
2106
|
-
...command.summary ? { summary: command.summary } : {}
|
|
2107
|
-
});
|
|
2108
|
-
return { data, human: renderWorktreeMerge(data, command) };
|
|
1927
|
+
return current;
|
|
2109
1928
|
}
|
|
2110
1929
|
function parseProjectUpdateArgs(args) {
|
|
2111
1930
|
const input = {};
|
|
@@ -2923,12 +2742,6 @@ function resolveCommandExecution(options, rest) {
|
|
|
2923
2742
|
text: SESSION_RUN_HELP_TEXT
|
|
2924
2743
|
};
|
|
2925
2744
|
}
|
|
2926
|
-
if (command === "merge" && commandArgs.length === 0) {
|
|
2927
|
-
return {
|
|
2928
|
-
kind: "cli-help",
|
|
2929
|
-
text: MERGE_HELP_TEXT
|
|
2930
|
-
};
|
|
2931
|
-
}
|
|
2932
2745
|
if (trailingHelp) {
|
|
2933
2746
|
const cliOnlyHelp = findCliOnlyCommandHelp(normalizedRest);
|
|
2934
2747
|
if (cliOnlyHelp) {
|
|
@@ -3327,9 +3140,6 @@ function resolveCommandExecution(options, rest) {
|
|
|
3327
3140
|
if (command === "session") {
|
|
3328
3141
|
return { kind: "session-run", command: parseSessionRunCommand(options, commandArgs) };
|
|
3329
3142
|
}
|
|
3330
|
-
if (command === "merge") {
|
|
3331
|
-
return { kind: "merge", command: parseMergeCommand(options, commandArgs) };
|
|
3332
|
-
}
|
|
3333
3143
|
if (command === "answer-questions") {
|
|
3334
3144
|
const sessionId = options.session;
|
|
3335
3145
|
if (!sessionId) {
|
|
@@ -3391,7 +3201,7 @@ async function runCommand(argv) {
|
|
|
3391
3201
|
if (execution.kind === "session-run") {
|
|
3392
3202
|
if (!options.json) {
|
|
3393
3203
|
if (execution.command.kind === "start") {
|
|
3394
|
-
process.stderr.write("Starting session
|
|
3204
|
+
process.stderr.write("Starting session...\n");
|
|
3395
3205
|
} else if (execution.command.kind === "stop") {
|
|
3396
3206
|
process.stderr.write(`Stopping session ${execution.command.sessionId}...
|
|
3397
3207
|
`);
|
|
@@ -3406,28 +3216,20 @@ async function runCommand(argv) {
|
|
|
3406
3216
|
if (options.json) process.stdout.write(`${JSON.stringify({ type: "session_started", data: result.data })}
|
|
3407
3217
|
`);
|
|
3408
3218
|
else process.stderr.write(result.human);
|
|
3219
|
+
const ready = await waitForSessionProvisioning(client, result.data);
|
|
3220
|
+
const readyStatus = formatStatusValue(ready.status);
|
|
3221
|
+
if (readyStatus === "failed" || readyStatus === "stopped") {
|
|
3222
|
+
if (options.json) process.stdout.write(`${JSON.stringify({ type: "session_status", data: ready })}
|
|
3223
|
+
`);
|
|
3224
|
+
else process.stderr.write(renderSessionRunStatus(ready));
|
|
3225
|
+
return readyStatus === "failed" ? 1 : 0;
|
|
3226
|
+
}
|
|
3409
3227
|
return await followWithInterrupt(client, sessionId, {
|
|
3410
3228
|
json: options.json,
|
|
3411
3229
|
includeTools: execution.command.includeTools,
|
|
3412
3230
|
printInitialTranscript: false
|
|
3413
3231
|
});
|
|
3414
3232
|
}
|
|
3415
|
-
if (execution.kind === "merge") {
|
|
3416
|
-
if (!options.json) {
|
|
3417
|
-
if (execution.command.kind === "merge") {
|
|
3418
|
-
process.stderr.write("Merging (publishing the workspace and computing the merge)...\n");
|
|
3419
|
-
} else if (execution.command.kind === "finish") {
|
|
3420
|
-
process.stderr.write(`Finalizing ${execution.command.conflictWorktree} (publishing the resolver workspace)...
|
|
3421
|
-
`);
|
|
3422
|
-
}
|
|
3423
|
-
}
|
|
3424
|
-
const result = await dispatchMergeCommand(client, execution.command, {
|
|
3425
|
-
...options.json ? {} : { onProgress: (line) => process.stderr.write(`${line}
|
|
3426
|
-
`) }
|
|
3427
|
-
});
|
|
3428
|
-
writeDataOutput(options.json, result.data, result.human);
|
|
3429
|
-
return 0;
|
|
3430
|
-
}
|
|
3431
3233
|
if (execution.kind === "conversation-follow") {
|
|
3432
3234
|
const { follow: _follow, ...renderOptions } = execution.renderOptions;
|
|
3433
3235
|
const initialConversation = await client.sessions.conversation(execution.sessionId, renderOptions);
|
|
@@ -3488,7 +3290,6 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
3488
3290
|
0 && (module.exports = {
|
|
3489
3291
|
advanceTransientDevicePollBackoff,
|
|
3490
3292
|
collectK8sUsage,
|
|
3491
|
-
dispatchMergeCommand,
|
|
3492
3293
|
dispatchSessionRunCommand,
|
|
3493
3294
|
followR5dctlSession,
|
|
3494
3295
|
formatK8sCpu,
|
|
@@ -3500,7 +3301,6 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
3500
3301
|
getR5dctlVersion,
|
|
3501
3302
|
getTransientDevicePollDelay,
|
|
3502
3303
|
handleAuthLogin,
|
|
3503
|
-
isMergeAttemptSettled,
|
|
3504
3304
|
main,
|
|
3505
3305
|
parseAnswerEnvRequestCommandArgs,
|
|
3506
3306
|
parseAnswerFlags,
|
|
@@ -3514,7 +3314,6 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
3514
3314
|
parseGetEnvsArgs,
|
|
3515
3315
|
parseGlobalArgs,
|
|
3516
3316
|
parseK8sUsageArgs,
|
|
3517
|
-
parseMergeCommand,
|
|
3518
3317
|
parsePromptArgs,
|
|
3519
3318
|
parsePsHistoryArgs,
|
|
3520
3319
|
parsePsListArgs,
|
|
@@ -3538,9 +3337,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
3538
3337
|
renderSessionRunStatus,
|
|
3539
3338
|
renderWorkspaceStatus,
|
|
3540
3339
|
renderWorkspaceSync,
|
|
3541
|
-
renderWorktreeMerge,
|
|
3542
3340
|
resolveCommandExecution,
|
|
3543
3341
|
runR5dctlCli,
|
|
3544
3342
|
summarizeEnvData,
|
|
3343
|
+
waitForSessionProvisioning,
|
|
3545
3344
|
writeConfig
|
|
3546
3345
|
});
|
package/dist/cjs/package.json
CHANGED
package/dist/mjs/cli.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
R5dctlClient
|
|
12
12
|
} from "@ricsam/r5d-api";
|
|
13
13
|
import { runR5dctlShell } from "./shell.mjs";
|
|
14
|
-
const CHAT_MODES = /* @__PURE__ */ new Set(["ask", "plan", "agent", "large_diff_remediation"
|
|
14
|
+
const CHAT_MODES = /* @__PURE__ */ new Set(["ask", "plan", "agent", "large_diff_remediation"]);
|
|
15
15
|
const R5DCTL_SESSION_MODES = /* @__PURE__ */ new Set(["ask", "plan", "agent"]);
|
|
16
16
|
const MODEL_TIERS = /* @__PURE__ */ new Set(["low", "medium", "high", "max"]);
|
|
17
17
|
const R5DCTL_PACKAGE_NAME = "@ricsam/r5dctl";
|
|
@@ -82,16 +82,6 @@ const SESSION_RUN_HELP_TEXT = [
|
|
|
82
82
|
"Use -f/--follow/--watch to attach after a start; Ctrl-C detaches without stopping the session.",
|
|
83
83
|
""
|
|
84
84
|
].join("\n");
|
|
85
|
-
const MERGE_HELP_TEXT = [
|
|
86
|
-
"Usage:",
|
|
87
|
-
" r5dctl -p <project> merge [--worker <label>] [--create-conflict-worktree|--launch-conflict-resolution-agent] [--no-wait] <source-worktree>",
|
|
88
|
-
" r5dctl -p <project> merge status <attempt-id>",
|
|
89
|
-
' r5dctl -p <project> merge finish --worker <label> [--summary "<summary>"] <conflict-worktree>',
|
|
90
|
-
"",
|
|
91
|
-
"Merge a managed worktree into its recorded parent worktree.",
|
|
92
|
-
"Conflict worktrees provision in the background; merge waits by default and --no-wait returns the attempt immediately.",
|
|
93
|
-
""
|
|
94
|
-
].join("\n");
|
|
95
85
|
const SHARED_HELP_ENTRIES = [
|
|
96
86
|
{ section: "auth", usage: "auth status", description: "Show the current authenticated user and credential source." },
|
|
97
87
|
{ section: "auth", usage: "auth logout", description: "Revoke the current credential and clear saved auth." },
|
|
@@ -102,16 +92,16 @@ const SHARED_HELP_ENTRIES = [
|
|
|
102
92
|
},
|
|
103
93
|
{ section: "auth", usage: "auth api-key list", description: "List API keys for the current account." },
|
|
104
94
|
{ section: "auth", usage: "auth api-key revoke <key-id>", description: "Revoke an API key." },
|
|
105
|
-
{ section: "workspace", usage: "workspace status", description: "Inspect
|
|
95
|
+
{ section: "workspace", usage: "workspace status", description: "Inspect per-user workspace Git state and active remediation." },
|
|
106
96
|
{
|
|
107
97
|
section: "workspace",
|
|
108
98
|
usage: "workspace sync [--worker <label>]",
|
|
109
|
-
description: "
|
|
99
|
+
description: "Commit, rebase, and push a connected worker's workspace now."
|
|
110
100
|
},
|
|
111
101
|
{
|
|
112
102
|
section: "workspace",
|
|
113
103
|
usage: "workspace reset [--worker <label>] --confirm",
|
|
114
|
-
description: "Destructively discard a blocked
|
|
104
|
+
description: "Destructively discard a blocked local workspace commit and restore origin/main."
|
|
115
105
|
},
|
|
116
106
|
{ section: "projects", usage: "get projects", description: "List projects you can access." },
|
|
117
107
|
{ section: "projects", usage: "describe project <namespace/name|id>", description: "Show details for a project." },
|
|
@@ -248,22 +238,7 @@ const SHARED_HELP_ENTRIES = [
|
|
|
248
238
|
usage: "ps inspect <run-id>",
|
|
249
239
|
description: "Inspect process metadata and bounded stdout/stderr tails."
|
|
250
240
|
},
|
|
251
|
-
{ section: "processes", usage: "ps stop <run-id>", description: "Gracefully stop an active process with SIGTERM." }
|
|
252
|
-
{
|
|
253
|
-
section: "merge",
|
|
254
|
-
usage: "-p <project> merge [--worker <label>] [--create-conflict-worktree|--launch-conflict-resolution-agent] [--no-wait] <source-worktree>",
|
|
255
|
-
description: "Merge a worktree into its recorded parent, with an explicit conflict strategy."
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
section: "merge",
|
|
259
|
-
usage: "-p <project> merge status <attempt-id>",
|
|
260
|
-
description: "Show a merge attempt's provisioning and resolution status."
|
|
261
|
-
},
|
|
262
|
-
{
|
|
263
|
-
section: "merge",
|
|
264
|
-
usage: '-p <project> merge finish --worker <label> [--summary "<summary>"] <conflict-worktree>',
|
|
265
|
-
description: "Publish and finish a manually resolved conflict worktree."
|
|
266
|
-
}
|
|
241
|
+
{ section: "processes", usage: "ps stop <run-id>", description: "Gracefully stop an active process with SIGTERM." }
|
|
267
242
|
];
|
|
268
243
|
const HELP_SECTION_ORDER = [
|
|
269
244
|
"auth",
|
|
@@ -274,8 +249,7 @@ const HELP_SECTION_ORDER = [
|
|
|
274
249
|
"sessions",
|
|
275
250
|
"kubernetes",
|
|
276
251
|
"processes",
|
|
277
|
-
"shell"
|
|
278
|
-
"merge"
|
|
252
|
+
"shell"
|
|
279
253
|
];
|
|
280
254
|
const HELP_SECTION_TITLES = {
|
|
281
255
|
auth: "Auth",
|
|
@@ -286,8 +260,7 @@ const HELP_SECTION_TITLES = {
|
|
|
286
260
|
sessions: "Sessions",
|
|
287
261
|
kubernetes: "Kubernetes",
|
|
288
262
|
processes: "Processes",
|
|
289
|
-
shell: "Shell"
|
|
290
|
-
merge: "Worktree merging"
|
|
263
|
+
shell: "Shell"
|
|
291
264
|
};
|
|
292
265
|
function getCliHelpText() {
|
|
293
266
|
const entries = [...CLI_ONLY_HELP_ENTRIES, ...SHARED_HELP_ENTRIES];
|
|
@@ -565,56 +538,6 @@ function parseSessionRunCommand(options, args) {
|
|
|
565
538
|
}
|
|
566
539
|
throw new Error(`Unknown session command: ${subcommand}`);
|
|
567
540
|
}
|
|
568
|
-
function parseMergeCommand(options, args) {
|
|
569
|
-
const project = requireValue(options.project, "--project/-p is required for `merge`");
|
|
570
|
-
if (options.branch) throw new Error("--branch/-b is not supported for `merge`; pass the source worktree explicitly");
|
|
571
|
-
if (options.session) throw new Error("--session/-s is not supported for `merge`");
|
|
572
|
-
if (args[0] === "finish") {
|
|
573
|
-
const parsed2 = parseCommandOperands(args.slice(1), /* @__PURE__ */ new Set(["--worker", "--summary"]), /* @__PURE__ */ new Map(), "merge finish");
|
|
574
|
-
const conflictWorktree = requireValue(parsed2.positionals[0], "Conflict worktree is required for `merge finish`");
|
|
575
|
-
if (parsed2.positionals.length > 1) throw new Error(`Unexpected merge finish argument: ${parsed2.positionals[1]}`);
|
|
576
|
-
return {
|
|
577
|
-
kind: "finish",
|
|
578
|
-
project,
|
|
579
|
-
conflictWorktree,
|
|
580
|
-
worker: requireWorker(parsed2.values),
|
|
581
|
-
...parsed2.values.get("--summary")?.trim() ? { summary: parsed2.values.get("--summary").trim() } : {}
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
if (args[0] === "status") {
|
|
585
|
-
const parsed2 = parseCommandOperands(args.slice(1), /* @__PURE__ */ new Set(), /* @__PURE__ */ new Map(), "merge status");
|
|
586
|
-
const attemptId = requireValue(parsed2.positionals[0], "Attempt id is required for `merge status`");
|
|
587
|
-
if (parsed2.positionals.length > 1) throw new Error(`Unexpected merge status argument: ${parsed2.positionals[1]}`);
|
|
588
|
-
return { kind: "status", project, attemptId };
|
|
589
|
-
}
|
|
590
|
-
const parsed = parseCommandOperands(
|
|
591
|
-
args,
|
|
592
|
-
/* @__PURE__ */ new Set(["--worker"]),
|
|
593
|
-
/* @__PURE__ */ new Map([
|
|
594
|
-
["--create-conflict-worktree", "--create-conflict-worktree"],
|
|
595
|
-
["--launch-conflict-resolution-agent", "--launch-conflict-resolution-agent"],
|
|
596
|
-
["--no-wait", "--no-wait"]
|
|
597
|
-
]),
|
|
598
|
-
"merge"
|
|
599
|
-
);
|
|
600
|
-
const sourceWorktree = requireValue(parsed.positionals[0], "Source worktree is required for `merge`");
|
|
601
|
-
if (parsed.positionals.length > 1) throw new Error(`Unexpected merge argument: ${parsed.positionals[1]}`);
|
|
602
|
-
const createWorktree = parsed.booleans.has("--create-conflict-worktree");
|
|
603
|
-
const launchAgent = parsed.booleans.has("--launch-conflict-resolution-agent");
|
|
604
|
-
if (createWorktree && launchAgent) {
|
|
605
|
-
throw new Error("Use only one of --create-conflict-worktree or --launch-conflict-resolution-agent");
|
|
606
|
-
}
|
|
607
|
-
const conflictMode = createWorktree ? "worktree" : launchAgent ? "agent" : "none";
|
|
608
|
-
const worker = parsed.values.get("--worker")?.trim();
|
|
609
|
-
return {
|
|
610
|
-
kind: "merge",
|
|
611
|
-
project,
|
|
612
|
-
sourceWorktree,
|
|
613
|
-
conflictMode,
|
|
614
|
-
...worker ? { worker } : {},
|
|
615
|
-
...parsed.booleans.has("--no-wait") ? { noWait: true } : {}
|
|
616
|
-
};
|
|
617
|
-
}
|
|
618
541
|
function assertAuthLoginArgs(args) {
|
|
619
542
|
const valueFlags = /* @__PURE__ */ new Set(["--device-name", "--worker-label"]);
|
|
620
543
|
const booleanFlags = /* @__PURE__ */ new Set(["--no-open", "--no-qr"]);
|
|
@@ -1441,16 +1364,15 @@ function renderWorkspaceStatus(status) {
|
|
|
1441
1364
|
`Workspace HEAD: ${status.head ?? "(not initialized)"}`,
|
|
1442
1365
|
`Latest sync: ${status.latestSync ? `${status.latestSync.outcome} on ${status.latestSync.workerLabel}` : "(none)"}`,
|
|
1443
1366
|
`Remediation: ${status.incident ? `${status.incident.kind} ${status.incident.status} (${status.incident.id}) on ${status.incident.originWorkerLabel}` : "none"}`,
|
|
1444
|
-
`Materialization: ${status.materialization ? `${status.materialization.state}; ${status.materialization.materializedHead ?? "(none)"} -> ${status.materialization.desiredHead ?? "(none)"}; lag ${status.materialization.lagMs}ms` : "not initialized"}`,
|
|
1445
1367
|
...status.workers.map(
|
|
1446
|
-
(worker) => `Worker ${worker.workerLabel}: ${worker.
|
|
1368
|
+
(worker) => `Worker ${worker.workerLabel}: ${worker.configured ? "configured" : "configuring"}; head ${worker.localHead ?? "(none)"}; pending checkouts ${worker.pendingCheckouts.length}`
|
|
1447
1369
|
)
|
|
1448
1370
|
];
|
|
1449
1371
|
return `${lines.join("\n")}
|
|
1450
1372
|
`;
|
|
1451
1373
|
}
|
|
1452
1374
|
function renderWorkspaceSync(result) {
|
|
1453
|
-
const head = result.publishedHead ?? result.
|
|
1375
|
+
const head = result.publishedHead ?? result.localHead ?? result.startingHead ?? "(none)";
|
|
1454
1376
|
const discarded = result.discardedPaths.length > 0 ? `
|
|
1455
1377
|
Discarded paths: ${result.discardedPaths.join(", ")}` : "";
|
|
1456
1378
|
const error = result.error ? `
|
|
@@ -1826,30 +1748,6 @@ function formatStatusValue(value) {
|
|
|
1826
1748
|
}
|
|
1827
1749
|
return value === void 0 || value === null ? void 0 : String(value);
|
|
1828
1750
|
}
|
|
1829
|
-
function appendMergeDetails(lines, merge) {
|
|
1830
|
-
const mergeStatus = formatStatusValue(merge.status);
|
|
1831
|
-
lines.push(`Merge: ${mergeStatus ?? "pending"}`);
|
|
1832
|
-
for (const [label, key] of [
|
|
1833
|
-
["Attempt", "attemptId"],
|
|
1834
|
-
["Source worktree", "sourceWorktree"],
|
|
1835
|
-
["Target worktree", "targetWorktree"],
|
|
1836
|
-
["Commit", "commitHash"],
|
|
1837
|
-
["Resolver agent", "resolverSessionId"],
|
|
1838
|
-
["Conflict worktree", "conflictWorktree"],
|
|
1839
|
-
["Resolver worktree", "folderPath"]
|
|
1840
|
-
]) {
|
|
1841
|
-
const value = responseString(merge, key);
|
|
1842
|
-
if (value) lines.push(`${label}: ${value}`);
|
|
1843
|
-
}
|
|
1844
|
-
const conflictedFiles = Array.isArray(merge.conflictedFiles) ? merge.conflictedFiles.filter((file) => typeof file === "string") : [];
|
|
1845
|
-
if (conflictedFiles.length > 0) {
|
|
1846
|
-
lines.push("", "Conflicts:", ...conflictedFiles.map((file) => `- ${file}`));
|
|
1847
|
-
}
|
|
1848
|
-
const message = responseString(merge, "message");
|
|
1849
|
-
if (message) lines.push("", message);
|
|
1850
|
-
const failureReason = responseString(merge, "failureReason");
|
|
1851
|
-
if (failureReason) lines.push(`Failure: ${failureReason}`);
|
|
1852
|
-
}
|
|
1853
1751
|
function renderSessionRunStart(session) {
|
|
1854
1752
|
const lines = [
|
|
1855
1753
|
`Session: ${responseString(session, "sessionId") ?? "(unknown)"}`,
|
|
@@ -1898,28 +1796,6 @@ function renderSessionRunStatus(session) {
|
|
|
1898
1796
|
return `${lines.join("\n")}
|
|
1899
1797
|
`;
|
|
1900
1798
|
}
|
|
1901
|
-
function renderWorktreeMerge(result, input) {
|
|
1902
|
-
const lines = [];
|
|
1903
|
-
appendMergeDetails(lines, result);
|
|
1904
|
-
const status = responseString(result, "status");
|
|
1905
|
-
const conflictWorktree = responseString(result, "conflictWorktree");
|
|
1906
|
-
const resolverSessionId = responseString(result, "resolverSessionId");
|
|
1907
|
-
const attemptId = responseString(result, "attemptId");
|
|
1908
|
-
const worker = responseString(result, "worker") ?? input.worker;
|
|
1909
|
-
if (resolverSessionId) lines.push("", `Resolver session: ${resolverSessionId}`, ` r5dctl session stop ${resolverSessionId}`);
|
|
1910
|
-
if (conflictWorktree && worker && ["conflicts", "conflict_worktree_created", "resolving"].includes(status ?? "")) {
|
|
1911
|
-
lines.push(
|
|
1912
|
-
"",
|
|
1913
|
-
"Finish after resolving and reviewing the conflict worktree:",
|
|
1914
|
-
` r5dctl -p ${input.project} merge finish --worker ${worker} ${conflictWorktree} --summary "<summary>"`
|
|
1915
|
-
);
|
|
1916
|
-
}
|
|
1917
|
-
if (attemptId && (status === "provisioning" || status === "resolving" && result.resolverAgentRunning === false)) {
|
|
1918
|
-
lines.push("", "Check progress:", ` r5dctl -p ${input.project} merge status ${attemptId}`);
|
|
1919
|
-
}
|
|
1920
|
-
return `${lines.join("\n")}
|
|
1921
|
-
`;
|
|
1922
|
-
}
|
|
1923
1799
|
async function dispatchSessionRunCommand(client, command) {
|
|
1924
1800
|
if (command.kind === "start") {
|
|
1925
1801
|
const commonInput = {
|
|
@@ -1956,70 +1832,16 @@ async function dispatchSessionRunCommand(client, command) {
|
|
|
1956
1832
|
const data = await client.sessions.stop(command.sessionId);
|
|
1957
1833
|
return { data, human: renderSessionRunStatus(data) };
|
|
1958
1834
|
}
|
|
1959
|
-
|
|
1960
|
-
const
|
|
1961
|
-
const
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
}
|
|
1968
|
-
async function pollMergeAttemptUntilSettled(client, project, attemptId, initial, options) {
|
|
1969
|
-
const intervalMs = options.pollIntervalMs ?? MERGE_POLL_INTERVAL_MS;
|
|
1970
|
-
const timeoutMs = options.pollTimeoutMs ?? MERGE_POLL_TIMEOUT_MS;
|
|
1971
|
-
const sleep2 = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
1972
|
-
const onProgress = options.onProgress ?? (() => {
|
|
1973
|
-
});
|
|
1974
|
-
let latest = initial;
|
|
1975
|
-
let worktreeReadyReported = latest.worktreeReady === true;
|
|
1976
|
-
let consecutiveFailures = 0;
|
|
1977
|
-
let waitedMs = 0;
|
|
1978
|
-
while (!isMergeAttemptSettled(latest)) {
|
|
1979
|
-
if (waitedMs >= timeoutMs) {
|
|
1980
|
-
onProgress(`Still waiting after ${Math.round(timeoutMs / 6e4)} minutes; check later with: r5dctl -p ${project} merge status ${attemptId}`);
|
|
1981
|
-
return latest;
|
|
1982
|
-
}
|
|
1983
|
-
await sleep2(intervalMs);
|
|
1984
|
-
waitedMs += intervalMs;
|
|
1985
|
-
try {
|
|
1986
|
-
latest = await client.projects.worktrees.mergeAttempt(project, attemptId);
|
|
1987
|
-
consecutiveFailures = 0;
|
|
1988
|
-
} catch (error) {
|
|
1989
|
-
consecutiveFailures += 1;
|
|
1990
|
-
if (consecutiveFailures >= MERGE_POLL_MAX_CONSECUTIVE_FAILURES) throw error;
|
|
1991
|
-
continue;
|
|
1992
|
-
}
|
|
1993
|
-
if (!worktreeReadyReported && latest.worktreeReady === true) {
|
|
1994
|
-
worktreeReadyReported = true;
|
|
1995
|
-
onProgress("Conflict worktree ready.");
|
|
1996
|
-
}
|
|
1835
|
+
async function waitForSessionProvisioning(client, initial, options = {}) {
|
|
1836
|
+
const sessionId = requireValue(responseString(initial, "sessionId"), "Session start did not return a session id");
|
|
1837
|
+
const wait = options.wait ?? sleep;
|
|
1838
|
+
const intervalMs = options.intervalMs ?? 500;
|
|
1839
|
+
let current = initial;
|
|
1840
|
+
while (formatStatusValue(current.status) === "provisioning") {
|
|
1841
|
+
await wait(intervalMs);
|
|
1842
|
+
current = await client.sessions.status(sessionId);
|
|
1997
1843
|
}
|
|
1998
|
-
return
|
|
1999
|
-
}
|
|
2000
|
-
async function dispatchMergeCommand(client, command, pollOptions = {}) {
|
|
2001
|
-
if (command.kind === "merge") {
|
|
2002
|
-
const data2 = await client.projects.worktrees.merge(command.project, command.sourceWorktree, {
|
|
2003
|
-
conflictMode: command.conflictMode,
|
|
2004
|
-
...command.worker ? { worker: command.worker } : {}
|
|
2005
|
-
});
|
|
2006
|
-
const attemptId = responseString(data2, "attemptId");
|
|
2007
|
-
if (command.noWait || !attemptId || isMergeAttemptSettled(data2)) {
|
|
2008
|
-
return { data: data2, human: renderWorktreeMerge(data2, command) };
|
|
2009
|
-
}
|
|
2010
|
-
pollOptions.onProgress?.(`Provisioning the conflict worktree (attempt ${attemptId})...`);
|
|
2011
|
-
const settled = await pollMergeAttemptUntilSettled(client, command.project, attemptId, data2, pollOptions);
|
|
2012
|
-
return { data: settled, human: renderWorktreeMerge(settled, command) };
|
|
2013
|
-
}
|
|
2014
|
-
if (command.kind === "status") {
|
|
2015
|
-
const data2 = await client.projects.worktrees.mergeAttempt(command.project, command.attemptId);
|
|
2016
|
-
return { data: data2, human: renderWorktreeMerge(data2, { project: command.project }) };
|
|
2017
|
-
}
|
|
2018
|
-
const data = await client.projects.worktrees.finishMerge(command.project, command.conflictWorktree, {
|
|
2019
|
-
worker: command.worker,
|
|
2020
|
-
...command.summary ? { summary: command.summary } : {}
|
|
2021
|
-
});
|
|
2022
|
-
return { data, human: renderWorktreeMerge(data, command) };
|
|
1844
|
+
return current;
|
|
2023
1845
|
}
|
|
2024
1846
|
function parseProjectUpdateArgs(args) {
|
|
2025
1847
|
const input = {};
|
|
@@ -2837,12 +2659,6 @@ function resolveCommandExecution(options, rest) {
|
|
|
2837
2659
|
text: SESSION_RUN_HELP_TEXT
|
|
2838
2660
|
};
|
|
2839
2661
|
}
|
|
2840
|
-
if (command === "merge" && commandArgs.length === 0) {
|
|
2841
|
-
return {
|
|
2842
|
-
kind: "cli-help",
|
|
2843
|
-
text: MERGE_HELP_TEXT
|
|
2844
|
-
};
|
|
2845
|
-
}
|
|
2846
2662
|
if (trailingHelp) {
|
|
2847
2663
|
const cliOnlyHelp = findCliOnlyCommandHelp(normalizedRest);
|
|
2848
2664
|
if (cliOnlyHelp) {
|
|
@@ -3241,9 +3057,6 @@ function resolveCommandExecution(options, rest) {
|
|
|
3241
3057
|
if (command === "session") {
|
|
3242
3058
|
return { kind: "session-run", command: parseSessionRunCommand(options, commandArgs) };
|
|
3243
3059
|
}
|
|
3244
|
-
if (command === "merge") {
|
|
3245
|
-
return { kind: "merge", command: parseMergeCommand(options, commandArgs) };
|
|
3246
|
-
}
|
|
3247
3060
|
if (command === "answer-questions") {
|
|
3248
3061
|
const sessionId = options.session;
|
|
3249
3062
|
if (!sessionId) {
|
|
@@ -3305,7 +3118,7 @@ async function runCommand(argv) {
|
|
|
3305
3118
|
if (execution.kind === "session-run") {
|
|
3306
3119
|
if (!options.json) {
|
|
3307
3120
|
if (execution.command.kind === "start") {
|
|
3308
|
-
process.stderr.write("Starting session
|
|
3121
|
+
process.stderr.write("Starting session...\n");
|
|
3309
3122
|
} else if (execution.command.kind === "stop") {
|
|
3310
3123
|
process.stderr.write(`Stopping session ${execution.command.sessionId}...
|
|
3311
3124
|
`);
|
|
@@ -3320,28 +3133,20 @@ async function runCommand(argv) {
|
|
|
3320
3133
|
if (options.json) process.stdout.write(`${JSON.stringify({ type: "session_started", data: result.data })}
|
|
3321
3134
|
`);
|
|
3322
3135
|
else process.stderr.write(result.human);
|
|
3136
|
+
const ready = await waitForSessionProvisioning(client, result.data);
|
|
3137
|
+
const readyStatus = formatStatusValue(ready.status);
|
|
3138
|
+
if (readyStatus === "failed" || readyStatus === "stopped") {
|
|
3139
|
+
if (options.json) process.stdout.write(`${JSON.stringify({ type: "session_status", data: ready })}
|
|
3140
|
+
`);
|
|
3141
|
+
else process.stderr.write(renderSessionRunStatus(ready));
|
|
3142
|
+
return readyStatus === "failed" ? 1 : 0;
|
|
3143
|
+
}
|
|
3323
3144
|
return await followWithInterrupt(client, sessionId, {
|
|
3324
3145
|
json: options.json,
|
|
3325
3146
|
includeTools: execution.command.includeTools,
|
|
3326
3147
|
printInitialTranscript: false
|
|
3327
3148
|
});
|
|
3328
3149
|
}
|
|
3329
|
-
if (execution.kind === "merge") {
|
|
3330
|
-
if (!options.json) {
|
|
3331
|
-
if (execution.command.kind === "merge") {
|
|
3332
|
-
process.stderr.write("Merging (publishing the workspace and computing the merge)...\n");
|
|
3333
|
-
} else if (execution.command.kind === "finish") {
|
|
3334
|
-
process.stderr.write(`Finalizing ${execution.command.conflictWorktree} (publishing the resolver workspace)...
|
|
3335
|
-
`);
|
|
3336
|
-
}
|
|
3337
|
-
}
|
|
3338
|
-
const result = await dispatchMergeCommand(client, execution.command, {
|
|
3339
|
-
...options.json ? {} : { onProgress: (line) => process.stderr.write(`${line}
|
|
3340
|
-
`) }
|
|
3341
|
-
});
|
|
3342
|
-
writeDataOutput(options.json, result.data, result.human);
|
|
3343
|
-
return 0;
|
|
3344
|
-
}
|
|
3345
3150
|
if (execution.kind === "conversation-follow") {
|
|
3346
3151
|
const { follow: _follow, ...renderOptions } = execution.renderOptions;
|
|
3347
3152
|
const initialConversation = await client.sessions.conversation(execution.sessionId, renderOptions);
|
|
@@ -3401,7 +3206,6 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
3401
3206
|
export {
|
|
3402
3207
|
advanceTransientDevicePollBackoff,
|
|
3403
3208
|
collectK8sUsage,
|
|
3404
|
-
dispatchMergeCommand,
|
|
3405
3209
|
dispatchSessionRunCommand,
|
|
3406
3210
|
followR5dctlSession,
|
|
3407
3211
|
formatK8sCpu,
|
|
@@ -3413,7 +3217,6 @@ export {
|
|
|
3413
3217
|
getR5dctlVersion,
|
|
3414
3218
|
getTransientDevicePollDelay,
|
|
3415
3219
|
handleAuthLogin,
|
|
3416
|
-
isMergeAttemptSettled,
|
|
3417
3220
|
main,
|
|
3418
3221
|
parseAnswerEnvRequestCommandArgs,
|
|
3419
3222
|
parseAnswerFlags,
|
|
@@ -3427,7 +3230,6 @@ export {
|
|
|
3427
3230
|
parseGetEnvsArgs,
|
|
3428
3231
|
parseGlobalArgs,
|
|
3429
3232
|
parseK8sUsageArgs,
|
|
3430
|
-
parseMergeCommand,
|
|
3431
3233
|
parsePromptArgs,
|
|
3432
3234
|
parsePsHistoryArgs,
|
|
3433
3235
|
parsePsListArgs,
|
|
@@ -3451,9 +3253,9 @@ export {
|
|
|
3451
3253
|
renderSessionRunStatus,
|
|
3452
3254
|
renderWorkspaceStatus,
|
|
3453
3255
|
renderWorkspaceSync,
|
|
3454
|
-
renderWorktreeMerge,
|
|
3455
3256
|
resolveCommandExecution,
|
|
3456
3257
|
runR5dctlCli,
|
|
3457
3258
|
summarizeEnvData,
|
|
3259
|
+
waitForSessionProvisioning,
|
|
3458
3260
|
writeConfig
|
|
3459
3261
|
};
|
package/dist/mjs/package.json
CHANGED
package/dist/types/cli.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { 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 R5dctlProcessRun, type R5dctlSessionEvent, type R5dctlSessionStartInput, type R5dctlWorkspaceStatus, type R5dctlWorkspaceSyncResult, type R5dctlWorktreeSource, type
|
|
1
|
+
import { 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 R5dctlProcessRun, type R5dctlSessionEvent, type R5dctlSessionStartInput, type R5dctlWorkspaceStatus, type R5dctlWorkspaceSyncResult, type R5dctlWorktreeSource, type R5dctlSessionMode, type ChatMode, type ModelTier } from "@ricsam/r5d-api";
|
|
2
2
|
export type GlobalOptions = {
|
|
3
3
|
baseUrl?: string;
|
|
4
4
|
json: boolean;
|
|
@@ -32,9 +32,6 @@ type CommandExecutionPlan = {
|
|
|
32
32
|
} | {
|
|
33
33
|
kind: "session-run";
|
|
34
34
|
command: R5dctlSessionRunCommand;
|
|
35
|
-
} | {
|
|
36
|
-
kind: "merge";
|
|
37
|
-
command: R5dctlMergeCommand;
|
|
38
35
|
} | {
|
|
39
36
|
kind: "conversation-follow";
|
|
40
37
|
sessionId: string;
|
|
@@ -79,26 +76,7 @@ export type R5dctlSessionRunCommand = R5dctlSessionStartCommand | {
|
|
|
79
76
|
kind: "stop";
|
|
80
77
|
sessionId: string;
|
|
81
78
|
};
|
|
82
|
-
export type R5dctlMergeCommand = {
|
|
83
|
-
kind: "merge";
|
|
84
|
-
project: string;
|
|
85
|
-
sourceWorktree: string;
|
|
86
|
-
worker?: string;
|
|
87
|
-
conflictMode: R5dctlMergeConflictMode;
|
|
88
|
-
noWait?: boolean;
|
|
89
|
-
} | {
|
|
90
|
-
kind: "status";
|
|
91
|
-
project: string;
|
|
92
|
-
attemptId: string;
|
|
93
|
-
} | {
|
|
94
|
-
kind: "finish";
|
|
95
|
-
project: string;
|
|
96
|
-
conflictWorktree: string;
|
|
97
|
-
worker: string;
|
|
98
|
-
summary?: string;
|
|
99
|
-
};
|
|
100
79
|
export declare function parseSessionRunCommand(options: Pick<GlobalOptions, "project" | "branch" | "session">, args: string[]): R5dctlSessionRunCommand;
|
|
101
|
-
export declare function parseMergeCommand(options: Pick<GlobalOptions, "project" | "branch" | "session">, args: string[]): R5dctlMergeCommand;
|
|
102
80
|
export declare function parseGlobalArgs(argv: string[]): {
|
|
103
81
|
options: GlobalOptions;
|
|
104
82
|
rest: string[];
|
|
@@ -224,18 +202,6 @@ export type R5dctlCommandResponse = {
|
|
|
224
202
|
error?: string;
|
|
225
203
|
summary?: string;
|
|
226
204
|
diffSummary?: string;
|
|
227
|
-
attemptId?: string;
|
|
228
|
-
sourceWorktree?: string;
|
|
229
|
-
targetWorktree?: string;
|
|
230
|
-
commitHash?: string;
|
|
231
|
-
resolverSessionId?: string;
|
|
232
|
-
conflictWorktree?: string;
|
|
233
|
-
folderPath?: string;
|
|
234
|
-
conflictedFiles?: string[];
|
|
235
|
-
failureReason?: string;
|
|
236
|
-
message?: string;
|
|
237
|
-
worktreeReady?: boolean;
|
|
238
|
-
resolverAgentRunning?: boolean;
|
|
239
205
|
};
|
|
240
206
|
export type R5dctlSessionRunClient = {
|
|
241
207
|
projects: {
|
|
@@ -255,47 +221,17 @@ export type R5dctlSessionRunClient = {
|
|
|
255
221
|
stop: (sessionId: string) => Promise<R5dctlCommandResponse>;
|
|
256
222
|
};
|
|
257
223
|
};
|
|
258
|
-
export type R5dctlMergeClient = {
|
|
259
|
-
projects: {
|
|
260
|
-
worktrees: {
|
|
261
|
-
merge: (projectRef: string, sourceWorktree: string, input: {
|
|
262
|
-
worker?: string;
|
|
263
|
-
conflictMode: R5dctlMergeConflictMode;
|
|
264
|
-
}) => Promise<R5dctlCommandResponse>;
|
|
265
|
-
finishMerge: (projectRef: string, conflictWorktree: string, input: {
|
|
266
|
-
worker: string;
|
|
267
|
-
summary?: string;
|
|
268
|
-
}) => Promise<R5dctlCommandResponse>;
|
|
269
|
-
mergeAttempt: (projectRef: string, attemptId: string) => Promise<R5dctlCommandResponse>;
|
|
270
|
-
};
|
|
271
|
-
};
|
|
272
|
-
};
|
|
273
224
|
export declare function renderSessionRunStart(session: R5dctlCommandResponse): string;
|
|
274
225
|
export declare function renderSessionRunStatus(session: R5dctlCommandResponse): string;
|
|
275
|
-
export declare function renderWorktreeMerge(result: R5dctlCommandResponse, input: {
|
|
276
|
-
project: string;
|
|
277
|
-
worker?: string;
|
|
278
|
-
}): string;
|
|
279
226
|
export type R5dctlCommandDispatchResult = {
|
|
280
227
|
data: R5dctlCommandResponse;
|
|
281
228
|
human: string;
|
|
282
229
|
};
|
|
283
230
|
export declare function dispatchSessionRunCommand(client: R5dctlSessionRunClient, command: R5dctlSessionRunCommand): Promise<R5dctlCommandDispatchResult>;
|
|
284
|
-
export
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
sleep?: (ms: number) => Promise<void>;
|
|
289
|
-
};
|
|
290
|
-
/**
|
|
291
|
-
* Whether a merge attempt response is settled for the CLI: terminal, waiting
|
|
292
|
-
* on the user (a ready manual conflict worktree), or actively resolving with
|
|
293
|
-
* its agent running. Anything else is still provisioning or starting. A
|
|
294
|
-
* "resolving" response without the resolverAgentRunning field comes from a
|
|
295
|
-
* server that starts the agent in-request, so it counts as settled.
|
|
296
|
-
*/
|
|
297
|
-
export declare function isMergeAttemptSettled(response: R5dctlCommandResponse): boolean;
|
|
298
|
-
export declare function dispatchMergeCommand(client: R5dctlMergeClient, command: R5dctlMergeCommand, pollOptions?: R5dctlMergePollOptions): Promise<R5dctlCommandDispatchResult>;
|
|
231
|
+
export declare function waitForSessionProvisioning(client: Pick<R5dctlSessionRunClient, "sessions">, initial: R5dctlCommandResponse, options?: {
|
|
232
|
+
intervalMs?: number;
|
|
233
|
+
wait?: (milliseconds: number) => Promise<unknown>;
|
|
234
|
+
}): Promise<R5dctlCommandResponse>;
|
|
299
235
|
export declare function parseConversationRenderArgs(args: string[]): ConversationRenderOptions;
|
|
300
236
|
export declare function renderConversationResponse(read: R5dctlConversationResponse): string;
|
|
301
237
|
type R5dctlFollowClient = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ricsam/r5dctl",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.76",
|
|
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.
|
|
29
|
+
"@ricsam/r5d-api": "^0.0.76",
|
|
30
30
|
"dotenv": "^17",
|
|
31
31
|
"qrcode": "^1.5.4",
|
|
32
32
|
"ws": "^8.18.3"
|