@viraatdas/rudder 2.10.7 → 2.10.8
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 +9 -21
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +203 -0
- package/dist/hooks.js.map +1 -0
- package/dist/main.js +8 -171
- package/dist/main.js.map +1 -1
- package/dist/native/rudder-native +0 -0
- package/dist/recipes.d.ts +11 -0
- package/dist/recipes.js +212 -0
- package/dist/recipes.js.map +1 -0
- package/dist/routines.d.ts +9 -0
- package/dist/routines.js +153 -0
- package/dist/routines.js.map +1 -0
- package/dist/run-manager.d.ts +0 -21
- package/dist/run-manager.js +0 -369
- package/dist/run-manager.js.map +1 -1
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -48,10 +48,9 @@ rudder
|
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
With no arguments, `rudder` opens the dashboard. Type in the bottom input and
|
|
51
|
-
press `Enter` to
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
workers.
|
|
51
|
+
press `Enter` to hand the request to the orchestrator. It can answer, inspect the
|
|
52
|
+
repo, or plan a DAG and run isolated workers. Use `/ask <text>` when you want a
|
|
53
|
+
one-off agent in the main checkout with no DAG.
|
|
55
54
|
|
|
56
55
|
If a task needs shared local context like API tokens, private URLs, account ids,
|
|
57
56
|
or environment values, save it with `/share <text>` in the task input. Rudder
|
|
@@ -91,7 +90,7 @@ to `~/.rudder/config.json`.
|
|
|
91
90
|
│ task list │ live Claude Code or Codex terminal │
|
|
92
91
|
│ status/model │ DAG-over-orchestrator, scrollback, review │
|
|
93
92
|
├───────────────┴────────────────────────────────────────────┤
|
|
94
|
-
│ task input:
|
|
93
|
+
│ task input: orchestrator by default, /ask for one-off │
|
|
95
94
|
└──────────────────────────────────────────────────────────────┘
|
|
96
95
|
```
|
|
97
96
|
|
|
@@ -191,13 +190,12 @@ reused next time. Rudder refreshes model metadata from
|
|
|
191
190
|
## One-Off and Planning
|
|
192
191
|
|
|
193
192
|
Type a fresh request in the bottom task input. When no plan is active, Rudder
|
|
194
|
-
starts
|
|
195
|
-
|
|
196
|
-
it ready to use?" out of the DAG planner.
|
|
193
|
+
starts the orchestrator, which can inspect the repo, plan the work, and spawn
|
|
194
|
+
isolated workers when needed.
|
|
197
195
|
|
|
198
|
-
Use `/
|
|
199
|
-
|
|
200
|
-
|
|
196
|
+
Use `/ask <text>` for a one-off conversational agent in the main checkout, with
|
|
197
|
+
no DAG. Use `/plan <text>` when you want to be explicit about the orchestrator /
|
|
198
|
+
DAG path; it is the same route as plain input.
|
|
201
199
|
|
|
202
200
|
For planned work, Rudder runs a dedicated Claude Code orchestrator PTY with a DAG
|
|
203
201
|
pane above it. The flow stays inside Rudder: the orchestrator researches
|
|
@@ -325,16 +323,6 @@ rudder sync <runId>
|
|
|
325
323
|
rudder cleanup
|
|
326
324
|
```
|
|
327
325
|
|
|
328
|
-
## Other interfaces
|
|
329
|
-
|
|
330
|
-
The native dashboard is the default. Older interfaces remain available:
|
|
331
|
-
|
|
332
|
-
```bash
|
|
333
|
-
rudder tmux # legacy tmux dashboard
|
|
334
|
-
rudder tui # Ink-based interactive TUI
|
|
335
|
-
rudder --no-native # skip the native binary
|
|
336
|
-
```
|
|
337
|
-
|
|
338
326
|
## Troubleshooting
|
|
339
327
|
|
|
340
328
|
- Stale behavior after an upgrade: restart any already-running Rudder dashboards
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HookConfig, HookInvocation, HookResult, RudderEvent } from "./types.js";
|
|
2
|
+
export declare function hooksConfigPath(repoRoot: string): string;
|
|
3
|
+
export declare function loadHookConfig(repoRoot: string): Promise<HookConfig>;
|
|
4
|
+
export declare function runHooks(invocation: HookInvocation, emit?: (event: RudderEvent) => Promise<void> | void): Promise<HookResult[]>;
|
|
5
|
+
export declare function firstBlockingHook(results: HookResult[]): HookResult | undefined;
|
|
6
|
+
export declare function initHookTemplates(repoRoot: string): Promise<string>;
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { projectStateDir, loadConfig } from "./state.js";
|
|
4
|
+
import { nowIso, readJson, writeJson } from "./util.js";
|
|
5
|
+
export function hooksConfigPath(repoRoot) {
|
|
6
|
+
return path.join(projectStateDir(repoRoot), "hooks.json");
|
|
7
|
+
}
|
|
8
|
+
export async function loadHookConfig(repoRoot) {
|
|
9
|
+
const config = await loadConfig();
|
|
10
|
+
if (config.hooks?.enabled === false) {
|
|
11
|
+
return { version: 1, hooks: [] };
|
|
12
|
+
}
|
|
13
|
+
const configured = config.hooks?.configPath
|
|
14
|
+
? path.resolve(repoRoot, config.hooks.configPath)
|
|
15
|
+
: hooksConfigPath(repoRoot);
|
|
16
|
+
const raw = await readJson(configured);
|
|
17
|
+
if (!raw || raw.version !== 1 || !Array.isArray(raw.hooks)) {
|
|
18
|
+
return { version: 1, hooks: [] };
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
version: 1,
|
|
22
|
+
hooks: raw.hooks.filter(isHookDefinition),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export async function runHooks(invocation, emit) {
|
|
26
|
+
const config = await loadHookConfig(invocation.repoRoot);
|
|
27
|
+
const hooks = config.hooks.filter((hook) => hook.event === invocation.event && hookMatches(hook, invocation));
|
|
28
|
+
const results = [];
|
|
29
|
+
for (const hook of hooks) {
|
|
30
|
+
await emit?.({
|
|
31
|
+
ts: nowIso(),
|
|
32
|
+
runId: invocation.runId ?? "hooks",
|
|
33
|
+
nodeId: invocation.nodeId,
|
|
34
|
+
type: "hook.started",
|
|
35
|
+
message: `hook ${hook.name ?? hook.command} on ${invocation.event}`,
|
|
36
|
+
data: hookData(hook),
|
|
37
|
+
});
|
|
38
|
+
const result = await runHookCommand(hook, invocation);
|
|
39
|
+
results.push(result);
|
|
40
|
+
if (result.status === "blocked") {
|
|
41
|
+
await emit?.({
|
|
42
|
+
ts: nowIso(),
|
|
43
|
+
runId: invocation.runId ?? "hooks",
|
|
44
|
+
nodeId: invocation.nodeId,
|
|
45
|
+
type: "hook.blocked",
|
|
46
|
+
message: result.reason ?? result.stderr ?? `hook blocked ${invocation.event}`,
|
|
47
|
+
data: hookData(hook),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (result.status === "failed" || result.status === "timeout") {
|
|
51
|
+
await emit?.({
|
|
52
|
+
ts: nowIso(),
|
|
53
|
+
runId: invocation.runId ?? "hooks",
|
|
54
|
+
nodeId: invocation.nodeId,
|
|
55
|
+
type: "hook.failed",
|
|
56
|
+
message: result.reason ?? result.stderr ?? `hook failed ${invocation.event}`,
|
|
57
|
+
data: hookData(hook),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (isBlockingEvent(invocation.event) && result.status === "blocked") {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return results;
|
|
65
|
+
}
|
|
66
|
+
export function firstBlockingHook(results) {
|
|
67
|
+
return results.find((result) => result.status === "blocked");
|
|
68
|
+
}
|
|
69
|
+
export async function initHookTemplates(repoRoot) {
|
|
70
|
+
const target = hooksConfigPath(repoRoot);
|
|
71
|
+
const initial = {
|
|
72
|
+
version: 1,
|
|
73
|
+
hooks: [
|
|
74
|
+
{
|
|
75
|
+
event: "PromptSubmit",
|
|
76
|
+
name: "secret-prompt-warning",
|
|
77
|
+
command: "node -e \"let s='';process.stdin.on('data',d=>s+=d);process.stdin.on('end',()=>{const j=JSON.parse(s); if(/(sk-|ghp_|github_pat_|api[_-]?key=)/i.test(j.message||'')){console.error('prompt appears to contain a secret; use rudder share instead'); process.exit(2)}})\"",
|
|
78
|
+
timeoutMs: 5000,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
await writeJson(target, initial, { mode: 0o600 });
|
|
83
|
+
return target;
|
|
84
|
+
}
|
|
85
|
+
function runHookCommand(hook, invocation) {
|
|
86
|
+
const timeoutMs = hook.timeoutMs ?? defaultTimeout(invocation.event);
|
|
87
|
+
const input = JSON.stringify(invocation);
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
const child = spawn(hook.command, {
|
|
90
|
+
cwd: invocation.repoRoot,
|
|
91
|
+
shell: true,
|
|
92
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
93
|
+
env: {
|
|
94
|
+
...process.env,
|
|
95
|
+
RUDDER_REPO: invocation.repoRoot,
|
|
96
|
+
RUDDER_EVENT: invocation.event,
|
|
97
|
+
...(invocation.runId ? { RUDDER_RUN_ID: invocation.runId } : {}),
|
|
98
|
+
...(invocation.nodeId ? { RUDDER_NODE_ID: invocation.nodeId } : {}),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
let stdout = "";
|
|
102
|
+
let stderr = "";
|
|
103
|
+
let settled = false;
|
|
104
|
+
const timer = setTimeout(() => {
|
|
105
|
+
if (settled) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
settled = true;
|
|
109
|
+
child.kill("SIGTERM");
|
|
110
|
+
resolve({ hook, status: "timeout", stdout, stderr, reason: `hook timed out after ${timeoutMs}ms` });
|
|
111
|
+
}, timeoutMs);
|
|
112
|
+
timer.unref?.();
|
|
113
|
+
child.stdout?.on("data", (chunk) => {
|
|
114
|
+
stdout += String(chunk);
|
|
115
|
+
});
|
|
116
|
+
child.stderr?.on("data", (chunk) => {
|
|
117
|
+
stderr += String(chunk);
|
|
118
|
+
});
|
|
119
|
+
child.on("error", (error) => {
|
|
120
|
+
if (settled) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
settled = true;
|
|
124
|
+
clearTimeout(timer);
|
|
125
|
+
resolve({ hook, status: "failed", stdout, stderr, reason: error.message });
|
|
126
|
+
});
|
|
127
|
+
child.on("exit", (code) => {
|
|
128
|
+
if (settled) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
settled = true;
|
|
132
|
+
clearTimeout(timer);
|
|
133
|
+
const parsed = parseHookJson(stdout);
|
|
134
|
+
const blocked = code === 2 || parsed?.decision === "block";
|
|
135
|
+
resolve({
|
|
136
|
+
hook,
|
|
137
|
+
status: blocked ? "blocked" : code === 0 ? "allowed" : "failed",
|
|
138
|
+
stdout,
|
|
139
|
+
stderr,
|
|
140
|
+
...(blocked ? { reason: parsed?.reason ?? firstLine(stderr) ?? "blocked by hook" } : {}),
|
|
141
|
+
...(code !== 0 && !blocked ? { reason: firstLine(stderr) ?? `hook exited ${code}` } : {}),
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
child.stdin?.end(input);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function hookMatches(hook, invocation) {
|
|
148
|
+
if (!hook.matcher) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
const haystack = `${invocation.message ?? ""}\n${JSON.stringify(invocation.data ?? {})}`;
|
|
152
|
+
try {
|
|
153
|
+
return new RegExp(hook.matcher).test(haystack);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return haystack.includes(hook.matcher);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function isHookDefinition(value) {
|
|
160
|
+
const hook = value;
|
|
161
|
+
return Boolean(hook && isHookEvent(hook.event) && typeof hook.command === "string" && hook.command.trim());
|
|
162
|
+
}
|
|
163
|
+
function isHookEvent(value) {
|
|
164
|
+
return (value === "PromptSubmit" ||
|
|
165
|
+
value === "RunStart" ||
|
|
166
|
+
value === "RunComplete" ||
|
|
167
|
+
value === "NodeReview" ||
|
|
168
|
+
value === "NodeMerged" ||
|
|
169
|
+
value === "MergeConflict" ||
|
|
170
|
+
value === "BudgetExceeded" ||
|
|
171
|
+
value === "WorktreeCreate" ||
|
|
172
|
+
value === "SessionEnd");
|
|
173
|
+
}
|
|
174
|
+
function isBlockingEvent(event) {
|
|
175
|
+
return event === "PromptSubmit" || event === "RunStart" || event === "WorktreeCreate";
|
|
176
|
+
}
|
|
177
|
+
function defaultTimeout(event) {
|
|
178
|
+
return event === "PromptSubmit" ? 30_000 : 600_000;
|
|
179
|
+
}
|
|
180
|
+
function parseHookJson(stdout) {
|
|
181
|
+
const trimmed = stdout.trim();
|
|
182
|
+
if (!trimmed.startsWith("{")) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
return JSON.parse(trimmed);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function firstLine(value) {
|
|
193
|
+
return value.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
|
|
194
|
+
}
|
|
195
|
+
function hookData(hook) {
|
|
196
|
+
return {
|
|
197
|
+
event: hook.event,
|
|
198
|
+
command: hook.command,
|
|
199
|
+
...(hook.name ? { name: hook.name } : {}),
|
|
200
|
+
...(hook.matcher ? { matcher: hook.matcher } : {}),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/main.js
CHANGED
|
@@ -3,7 +3,7 @@ import fsp from "node:fs/promises";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { authStoreExists, runDoctor, runOnboard } from "./auth.js";
|
|
6
|
-
import {
|
|
6
|
+
import { codexLaunchEnv } from "./codex-binary.js";
|
|
7
7
|
import { runCloudCommand } from "./cloud.js";
|
|
8
8
|
import { printContextAudit } from "./context-audit.js";
|
|
9
9
|
import { currentBranch, findRepoRoot } from "./git.js";
|
|
@@ -15,13 +15,9 @@ import { backfillLlmTaskSummaries, listRuns, popUndoEntry, projectStateDir, regi
|
|
|
15
15
|
import { discoverModelOptions } from "./models.js";
|
|
16
16
|
import { resolveNativeBinaryPath } from "./native-binary.js";
|
|
17
17
|
import { cleanupRuns, deleteRun, listProjectRuns, mergeRun, printLogs, startRun, statusRuns, stopRun, syncRun, watchRun, workerRun, } from "./run-manager.js";
|
|
18
|
-
import { runInteractiveShell } from "./repl.js";
|
|
19
18
|
import { appendCompletionNote, appendDecision, appendSharedContext, parseCompletionNoteArg, RUDDER_DONE_END, RUDDER_DONE_START, SHARED_CONTEXT_FILE, syncSharedContextToWorkspaces, writeCompletionNoteFile } from "./surfaces.js";
|
|
20
|
-
import {
|
|
21
|
-
import { runInteractiveTui } from "./tui.js";
|
|
22
|
-
import { commandExists, isTty, MissingToolError, newRunId, runCommand } from "./util.js";
|
|
19
|
+
import { commandExists, isTty, MissingToolError, newRunId } from "./util.js";
|
|
23
20
|
import { autoUpdateAndRerunIfNeeded, getUpdateAvailable } from "./version-check.js";
|
|
24
|
-
import { attachTmuxSession, ensureTmuxDashboardSession, hasTmux, repoTmuxSessionName, shellCommand } from "./tmux.js";
|
|
25
21
|
export async function main() {
|
|
26
22
|
const parsed = parseArgs(process.argv.slice(2));
|
|
27
23
|
if (shouldAutoUpdateForCommand(parsed.command) && await autoUpdateAndRerunIfNeeded(process.argv.slice(2))) {
|
|
@@ -64,52 +60,8 @@ export async function main() {
|
|
|
64
60
|
return;
|
|
65
61
|
}
|
|
66
62
|
switch (parsed.command) {
|
|
67
|
-
case "__agents": {
|
|
68
|
-
const repo = parsed.flags.repo;
|
|
69
|
-
const tmuxSessionName = parsed.flags.tmuxSession;
|
|
70
|
-
if (!repo || !tmuxSessionName) {
|
|
71
|
-
throw new Error("__agents requires --repo and --tmux-session");
|
|
72
|
-
}
|
|
73
|
-
process.chdir(repo);
|
|
74
|
-
await runTmuxAgentPane({
|
|
75
|
-
tmuxSessionName,
|
|
76
|
-
backend: parsed.flags.backend,
|
|
77
|
-
model: parsed.flags.model,
|
|
78
|
-
});
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
case "__task": {
|
|
82
|
-
const repo = parsed.flags.repo;
|
|
83
|
-
const tmuxSessionName = parsed.flags.tmuxSession;
|
|
84
|
-
if (!repo || !tmuxSessionName) {
|
|
85
|
-
throw new Error("__task requires --repo and --tmux-session");
|
|
86
|
-
}
|
|
87
|
-
process.chdir(repo);
|
|
88
|
-
await runTmuxTaskPane({
|
|
89
|
-
tmuxSessionName,
|
|
90
|
-
backend: parsed.flags.backend,
|
|
91
|
-
model: parsed.flags.model,
|
|
92
|
-
});
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
case "__worker-idle": {
|
|
96
|
-
const repo = parsed.flags.repo;
|
|
97
|
-
const tmuxSessionName = parsed.flags.tmuxSession;
|
|
98
|
-
if (!repo || !tmuxSessionName) {
|
|
99
|
-
throw new Error("__worker-idle requires --repo and --tmux-session");
|
|
100
|
-
}
|
|
101
|
-
process.chdir(repo);
|
|
102
|
-
await runTmuxWorkerIdle({
|
|
103
|
-
tmuxSessionName,
|
|
104
|
-
backend: parsed.flags.backend,
|
|
105
|
-
model: parsed.flags.model,
|
|
106
|
-
});
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
63
|
case "tmux":
|
|
110
|
-
|
|
111
|
-
await openTmuxDashboard(parsed);
|
|
112
|
-
return;
|
|
64
|
+
throw new Error("The tmux dashboard has been removed. Run `rudder` or `rudder dashboard` to open the native dashboard.");
|
|
113
65
|
case "dashboard":
|
|
114
66
|
await maybeOnboard();
|
|
115
67
|
await openDashboard(parsed);
|
|
@@ -123,33 +75,10 @@ export async function main() {
|
|
|
123
75
|
await runNativeCommand(["mouse-test", ...parsed.args]);
|
|
124
76
|
return;
|
|
125
77
|
case "tui":
|
|
126
|
-
await maybeOnboard();
|
|
127
|
-
await runInteractiveTui({
|
|
128
|
-
backend: parsed.flags.backend,
|
|
129
|
-
model: parsed.flags.model,
|
|
130
|
-
worktree: parsed.flags.worktree,
|
|
131
|
-
detach: parsed.flags.detach,
|
|
132
|
-
});
|
|
133
|
-
return;
|
|
134
78
|
case "shell":
|
|
135
79
|
case "interactive":
|
|
136
|
-
await maybeOnboard();
|
|
137
|
-
await runInteractiveTui({
|
|
138
|
-
backend: parsed.flags.backend,
|
|
139
|
-
model: parsed.flags.model,
|
|
140
|
-
worktree: parsed.flags.worktree,
|
|
141
|
-
detach: parsed.flags.detach,
|
|
142
|
-
});
|
|
143
|
-
return;
|
|
144
80
|
case "legacy-shell":
|
|
145
|
-
|
|
146
|
-
await runInteractiveShell({
|
|
147
|
-
backend: parsed.flags.backend,
|
|
148
|
-
model: parsed.flags.model,
|
|
149
|
-
worktree: parsed.flags.worktree,
|
|
150
|
-
detach: parsed.flags.detach,
|
|
151
|
-
});
|
|
152
|
-
return;
|
|
81
|
+
throw new Error("Legacy interactive shells have been removed. Run `rudder` or `rudder dashboard` to open the native dashboard.");
|
|
153
82
|
case "__worker": {
|
|
154
83
|
const repo = parsed.flags.repo;
|
|
155
84
|
const run = parsed.flags.run;
|
|
@@ -435,17 +364,8 @@ function parseArgs(argv) {
|
|
|
435
364
|
parsed.flags.nonInteractive = true;
|
|
436
365
|
continue;
|
|
437
366
|
}
|
|
438
|
-
if (arg === "--no-tmux") {
|
|
439
|
-
|
|
440
|
-
continue;
|
|
441
|
-
}
|
|
442
|
-
if (arg === "--no-native") {
|
|
443
|
-
parsed.flags.noNative = true;
|
|
444
|
-
continue;
|
|
445
|
-
}
|
|
446
|
-
if (arg === "--headless") {
|
|
447
|
-
parsed.flags.headless = true;
|
|
448
|
-
continue;
|
|
367
|
+
if (arg === "--no-tmux" || arg === "--no-native" || arg === "--headless") {
|
|
368
|
+
throw new Error(`${arg} was removed with the legacy dashboards. Run \`rudder\` for the native dashboard.`);
|
|
449
369
|
}
|
|
450
370
|
if (arg === "--open") {
|
|
451
371
|
parsed.flags.open = true;
|
|
@@ -503,10 +423,6 @@ function parseArgs(argv) {
|
|
|
503
423
|
parsed.flags.base = readValue(argv, ++i, arg);
|
|
504
424
|
continue;
|
|
505
425
|
}
|
|
506
|
-
if (takesValue(arg, "--tmux-session")) {
|
|
507
|
-
parsed.flags.tmuxSession = readValue(argv, ++i, arg);
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
426
|
if (takesValue(arg, "--home-path")) {
|
|
511
427
|
parsed.flags.homePaths = [...(parsed.flags.homePaths ?? []), readValue(argv, ++i, arg)];
|
|
512
428
|
continue;
|
|
@@ -547,10 +463,6 @@ function parseArgs(argv) {
|
|
|
547
463
|
parsed.flags.base = arg.slice("--base=".length);
|
|
548
464
|
continue;
|
|
549
465
|
}
|
|
550
|
-
if (arg.startsWith("--tmux-session=")) {
|
|
551
|
-
parsed.flags.tmuxSession = arg.slice("--tmux-session=".length);
|
|
552
|
-
continue;
|
|
553
|
-
}
|
|
554
466
|
if (arg.startsWith("--home-path=")) {
|
|
555
467
|
parsed.flags.homePaths = [...(parsed.flags.homePaths ?? []), arg.slice("--home-path=".length)];
|
|
556
468
|
continue;
|
|
@@ -598,29 +510,11 @@ async function maybeOnboard() {
|
|
|
598
510
|
await runOnboard();
|
|
599
511
|
}
|
|
600
512
|
async function openDashboard(parsed) {
|
|
601
|
-
if (parsed.flags.noTmux || parsed.flags.headless) {
|
|
602
|
-
await runInteractiveTui({
|
|
603
|
-
backend: parsed.flags.backend,
|
|
604
|
-
model: parsed.flags.model,
|
|
605
|
-
worktree: parsed.flags.worktree,
|
|
606
|
-
detach: parsed.flags.detach,
|
|
607
|
-
});
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
513
|
await refreshModelCache();
|
|
611
|
-
if (
|
|
514
|
+
if (await runNativeDashboard()) {
|
|
612
515
|
return;
|
|
613
516
|
}
|
|
614
|
-
|
|
615
|
-
await openTmuxDashboard(parsed);
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
await runInteractiveTui({
|
|
619
|
-
backend: parsed.flags.backend,
|
|
620
|
-
model: parsed.flags.model,
|
|
621
|
-
worktree: parsed.flags.worktree,
|
|
622
|
-
detach: parsed.flags.detach,
|
|
623
|
-
});
|
|
517
|
+
throw new Error("rudder-native binary is not available. Reinstall or rebuild Rudder, then run `rudder` again.");
|
|
624
518
|
}
|
|
625
519
|
async function refreshModelCache() {
|
|
626
520
|
await Promise.all([
|
|
@@ -719,54 +613,6 @@ async function runNativeCommand(args) {
|
|
|
719
613
|
});
|
|
720
614
|
process.exitCode = code ?? 1;
|
|
721
615
|
}
|
|
722
|
-
async function openTmuxDashboard(parsed) {
|
|
723
|
-
if (!hasTmux()) {
|
|
724
|
-
await runInteractiveTui({
|
|
725
|
-
backend: parsed.flags.backend,
|
|
726
|
-
model: parsed.flags.model,
|
|
727
|
-
worktree: parsed.flags.worktree,
|
|
728
|
-
detach: parsed.flags.detach,
|
|
729
|
-
});
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
const repoRoot = findRepoRoot();
|
|
733
|
-
const sessionName = parsed.flags.tmuxSession ?? repoTmuxSessionName(repoRoot);
|
|
734
|
-
const entry = process.argv[1];
|
|
735
|
-
if (!entry) {
|
|
736
|
-
throw new Error("Cannot locate Rudder entrypoint.");
|
|
737
|
-
}
|
|
738
|
-
const common = [
|
|
739
|
-
entry,
|
|
740
|
-
];
|
|
741
|
-
const commonFlags = [
|
|
742
|
-
"--repo",
|
|
743
|
-
repoRoot,
|
|
744
|
-
"--tmux-session",
|
|
745
|
-
sessionName,
|
|
746
|
-
...(parsed.flags.backend ? ["--backend", parsed.flags.backend] : []),
|
|
747
|
-
...(parsed.flags.model ? ["--model", parsed.flags.model] : []),
|
|
748
|
-
];
|
|
749
|
-
const managedCodexEnv = await codexEnvVars();
|
|
750
|
-
// Only inject codex env vars that are actually present. On platforms without a
|
|
751
|
-
// managed Codex binary codexEnvVars() returns {}, and interpolating the missing
|
|
752
|
-
// values would emit a literal `RUDDER_CODEX_BIN=undefined` that hard-fails Codex
|
|
753
|
-
// (and breaks the graceful optional-Codex behavior).
|
|
754
|
-
const codexEnvArgs = Object.entries(managedCodexEnv)
|
|
755
|
-
.filter(([, value]) => value != null && value !== "")
|
|
756
|
-
.map(([key, value]) => `${key}=${value}`);
|
|
757
|
-
const withManagedCodex = (args) => shellCommand("env", [...codexEnvArgs, ...args]);
|
|
758
|
-
await ensureTmuxDashboardSession({
|
|
759
|
-
repoRoot,
|
|
760
|
-
sessionName,
|
|
761
|
-
agentCommand: withManagedCodex([process.execPath, ...common, "__agents", ...commonFlags]),
|
|
762
|
-
workerCommand: withManagedCodex([process.execPath, ...common, "__worker-idle", ...commonFlags]),
|
|
763
|
-
taskCommand: withManagedCodex([process.execPath, ...common, "__task", ...commonFlags]),
|
|
764
|
-
backend: parsed.flags.backend === "codex" ? "codex" : "claude",
|
|
765
|
-
model: parsed.flags.model,
|
|
766
|
-
});
|
|
767
|
-
const code = await attachTmuxSession(sessionName);
|
|
768
|
-
process.exitCode = code;
|
|
769
|
-
}
|
|
770
616
|
async function resetLocalRudderSession(parsed) {
|
|
771
617
|
const repoRoot = findRepoRoot();
|
|
772
618
|
const stateDir = projectStateDir(repoRoot);
|
|
@@ -776,10 +622,6 @@ async function resetLocalRudderSession(parsed) {
|
|
|
776
622
|
fsp.rm(path.join(stateDir, "tmux"), { recursive: true, force: true }),
|
|
777
623
|
]);
|
|
778
624
|
await fsp.mkdir(runsDir(repoRoot), { recursive: true });
|
|
779
|
-
if (hasTmux()) {
|
|
780
|
-
const sessionName = parsed.flags.tmuxSession ?? repoTmuxSessionName(repoRoot);
|
|
781
|
-
await runCommand("tmux", ["kill-session", "-t", sessionName], { allowFailure: true });
|
|
782
|
-
}
|
|
783
625
|
}
|
|
784
626
|
async function packageVersion() {
|
|
785
627
|
const packageFile = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
@@ -1020,9 +862,7 @@ function printHelp() {
|
|
|
1020
862
|
|
|
1021
863
|
Usage:
|
|
1022
864
|
rudder Open native dashboard with real agent panes
|
|
1023
|
-
rudder tmux Open tmux dashboard with native agent panes
|
|
1024
865
|
rudder restart Clear local session and open dashboard
|
|
1025
|
-
rudder tui Open legacy full-screen stream TUI
|
|
1026
866
|
rudder "task"
|
|
1027
867
|
rudder run [options] "task"
|
|
1028
868
|
rudder claude [options] "task"
|
|
@@ -1098,9 +938,6 @@ Options:
|
|
|
1098
938
|
-p, --port <port> Board server port (default 4774)
|
|
1099
939
|
--n <count> Number of fan-out variants for rudder fanout (default 3)
|
|
1100
940
|
--open / --no-open Open (or do not open) the browser for the board
|
|
1101
|
-
--no-tmux Use the legacy TUI for bare rudder
|
|
1102
|
-
--no-native Use the tmux dashboard instead of native
|
|
1103
|
-
--headless Alias for --no-tmux on bare rudder
|
|
1104
941
|
--home-path <path> Include extra HOME path in cloud snapshot
|
|
1105
942
|
--ssh <host> BYOC SSH host from ~/.ssh/config
|
|
1106
943
|
--json Machine-readable output
|