@h-rig/cli 0.0.6-alpha.0
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 +30 -0
- package/dist/bin/build-rig-binaries.js +107 -0
- package/dist/bin/rig.js +9330 -0
- package/dist/src/commands/_authority-runs.js +110 -0
- package/dist/src/commands/_connection-state.js +123 -0
- package/dist/src/commands/_doctor-checks.js +501 -0
- package/dist/src/commands/_operator-view.js +322 -0
- package/dist/src/commands/_parsers.js +107 -0
- package/dist/src/commands/_paths.js +50 -0
- package/dist/src/commands/_pi-install.js +184 -0
- package/dist/src/commands/_policy.js +79 -0
- package/dist/src/commands/_preflight.js +460 -0
- package/dist/src/commands/_probes.js +13 -0
- package/dist/src/commands/_run-driver-helpers.js +289 -0
- package/dist/src/commands/_server-client.js +364 -0
- package/dist/src/commands/_snapshot-upload.js +313 -0
- package/dist/src/commands/_task-picker.js +48 -0
- package/dist/src/commands/agent.js +497 -0
- package/dist/src/commands/browser.js +890 -0
- package/dist/src/commands/connect.js +180 -0
- package/dist/src/commands/dist.js +402 -0
- package/dist/src/commands/doctor.js +511 -0
- package/dist/src/commands/github.js +276 -0
- package/dist/src/commands/inbox.js +160 -0
- package/dist/src/commands/init.js +1254 -0
- package/dist/src/commands/inspect.js +174 -0
- package/dist/src/commands/inspector.js +256 -0
- package/dist/src/commands/plugin.js +167 -0
- package/dist/src/commands/profile-and-review.js +178 -0
- package/dist/src/commands/queue.js +197 -0
- package/dist/src/commands/remote.js +507 -0
- package/dist/src/commands/repo-git-harness.js +221 -0
- package/dist/src/commands/run.js +753 -0
- package/dist/src/commands/server.js +368 -0
- package/dist/src/commands/setup.js +681 -0
- package/dist/src/commands/task-report-bug.js +1083 -0
- package/dist/src/commands/task-run-driver.js +1933 -0
- package/dist/src/commands/task.js +1325 -0
- package/dist/src/commands/test.js +39 -0
- package/dist/src/commands/workspace.js +123 -0
- package/dist/src/commands.js +9012 -0
- package/dist/src/index.js +9348 -0
- package/dist/src/launcher.js +131 -0
- package/dist/src/report-bug.js +260 -0
- package/dist/src/runner.js +272 -0
- package/dist/src/withMutedConsole.js +42 -0
- package/package.json +31 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/cli/src/runner.ts
|
|
3
|
+
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
4
|
+
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
5
|
+
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
6
|
+
import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
|
|
7
|
+
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
8
|
+
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
9
|
+
import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
|
|
10
|
+
function takeFlag(args, flag) {
|
|
11
|
+
const rest = [];
|
|
12
|
+
let value = false;
|
|
13
|
+
for (const arg of args) {
|
|
14
|
+
if (arg === flag) {
|
|
15
|
+
value = true;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
rest.push(arg);
|
|
19
|
+
}
|
|
20
|
+
return { value, rest };
|
|
21
|
+
}
|
|
22
|
+
function takeOption(args, option) {
|
|
23
|
+
const rest = [];
|
|
24
|
+
let value;
|
|
25
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
26
|
+
const current = args[index];
|
|
27
|
+
if (current === option) {
|
|
28
|
+
const next = args[index + 1];
|
|
29
|
+
if (!next || next.startsWith("-")) {
|
|
30
|
+
throw new CliError(`Missing value for ${option}`);
|
|
31
|
+
}
|
|
32
|
+
value = next;
|
|
33
|
+
index += 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (current !== undefined) {
|
|
37
|
+
rest.push(current);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { value, rest };
|
|
41
|
+
}
|
|
42
|
+
function requireNoExtraArgs(args, usage) {
|
|
43
|
+
if (args.length > 0) {
|
|
44
|
+
throw new CliError(`Unexpected arguments: ${args.join(" ")}
|
|
45
|
+
Usage: ${usage}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function requireTask(taskId, usage) {
|
|
49
|
+
if (!taskId) {
|
|
50
|
+
throw new CliError(`Missing --task option.
|
|
51
|
+
Usage: ${usage}`);
|
|
52
|
+
}
|
|
53
|
+
return taskId;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// packages/cli/src/commands/remote.ts
|
|
57
|
+
import {
|
|
58
|
+
doctorManagedRemoteEndpoints,
|
|
59
|
+
listManagedRemoteEndpoints,
|
|
60
|
+
matchesEventFilter,
|
|
61
|
+
migrateManagedRemoteEndpoints,
|
|
62
|
+
RemoteCliError,
|
|
63
|
+
RemoteWsClient,
|
|
64
|
+
removeManagedRemoteEndpoint,
|
|
65
|
+
resolveRemoteEndpoint,
|
|
66
|
+
summarizeMessage,
|
|
67
|
+
updateManagedRemoteEndpointInAuthority,
|
|
68
|
+
upsertManagedRemoteEndpoint
|
|
69
|
+
} from "@rig/runtime/control-plane/remote";
|
|
70
|
+
|
|
71
|
+
// packages/cli/src/commands/_parsers.ts
|
|
72
|
+
function parseOptionalPositiveInt(value, option) {
|
|
73
|
+
if (!value) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const parsed = Number.parseInt(value, 10);
|
|
77
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
78
|
+
throw new CliError2(`Invalid ${option} value: ${value}`);
|
|
79
|
+
}
|
|
80
|
+
return parsed;
|
|
81
|
+
}
|
|
82
|
+
function parseRequiredPositiveInt(value, option) {
|
|
83
|
+
if (!value) {
|
|
84
|
+
throw new CliError2(`Missing value for ${option}.`);
|
|
85
|
+
}
|
|
86
|
+
const parsed = Number.parseInt(value, 10);
|
|
87
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
88
|
+
throw new CliError2(`Invalid ${option} value: ${value}`);
|
|
89
|
+
}
|
|
90
|
+
return parsed;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// packages/cli/src/commands/remote.ts
|
|
94
|
+
function assertRemoteOperationSuccess(command, response) {
|
|
95
|
+
if (!("success" in response)) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (response.success === false) {
|
|
99
|
+
const error = typeof response.error === "string" && response.error || `${command} failed without explicit error detail from remote server.`;
|
|
100
|
+
throw new RemoteCliError("RIG_REMOTE_OPERATION_FAILED", error, 3, { command, response: redactSecretFields(response) });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function redactRemoteEndpoint(endpoint) {
|
|
104
|
+
const { token, ...rest } = endpoint;
|
|
105
|
+
return {
|
|
106
|
+
...rest,
|
|
107
|
+
token: "",
|
|
108
|
+
tokenConfigured: token.trim().length > 0
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function isRecord(value) {
|
|
112
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
113
|
+
}
|
|
114
|
+
function isSecretKey(key) {
|
|
115
|
+
const normalized = key.toLowerCase();
|
|
116
|
+
return normalized === "token" || normalized === "authtoken" || normalized === "authorization" || normalized === "connectiontoken" || normalized === "access_token" || normalized === "secret";
|
|
117
|
+
}
|
|
118
|
+
function redactSecretFields(value) {
|
|
119
|
+
if (Array.isArray(value)) {
|
|
120
|
+
return value.map((entry) => redactSecretFields(entry));
|
|
121
|
+
}
|
|
122
|
+
if (!isRecord(value)) {
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
const redacted = {};
|
|
126
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
127
|
+
redacted[key] = isSecretKey(key) && typeof entry === "string" ? entry.trim().length > 0 ? "[redacted]" : "" : redactSecretFields(entry);
|
|
128
|
+
}
|
|
129
|
+
return redacted;
|
|
130
|
+
}
|
|
131
|
+
async function executeRemote(context, args) {
|
|
132
|
+
const [command = "status", ...rest] = args;
|
|
133
|
+
if (command === "endpoint" || command === "endpoints") {
|
|
134
|
+
const [subcommand = "list", ...subRest] = rest;
|
|
135
|
+
switch (subcommand) {
|
|
136
|
+
case "list": {
|
|
137
|
+
requireNoExtraArgs(subRest, "bun run rig remote endpoint list");
|
|
138
|
+
const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
|
|
139
|
+
const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
|
|
140
|
+
if (context.outputMode === "text") {
|
|
141
|
+
if (endpoints.length === 0) {
|
|
142
|
+
console.log("No remote endpoints configured.");
|
|
143
|
+
} else {
|
|
144
|
+
for (const endpoint2 of endpoints) {
|
|
145
|
+
console.log(`- ${endpoint2.alias} \xB7 ${endpoint2.host}:${endpoint2.port}${endpoint2.lastConnected ? ` \xB7 last connected ${endpoint2.lastConnected}` : ""}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return { ok: true, group: "remote", command: "endpoint list", details: { endpoints: redactedEndpoints } };
|
|
150
|
+
}
|
|
151
|
+
case "add": {
|
|
152
|
+
let pending2 = subRest;
|
|
153
|
+
const alias = takeOption(pending2, "--alias");
|
|
154
|
+
pending2 = alias.rest;
|
|
155
|
+
const host = takeOption(pending2, "--host");
|
|
156
|
+
pending2 = host.rest;
|
|
157
|
+
const port = takeOption(pending2, "--port");
|
|
158
|
+
pending2 = port.rest;
|
|
159
|
+
const token = takeOption(pending2, "--token");
|
|
160
|
+
pending2 = token.rest;
|
|
161
|
+
requireNoExtraArgs(pending2, "bun run rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
|
|
162
|
+
if (!alias.value || !host.value || !token.value || !port.value) {
|
|
163
|
+
throw new CliError2("remote endpoint add requires --alias, --host, --port, and --token.");
|
|
164
|
+
}
|
|
165
|
+
const created = upsertManagedRemoteEndpoint({
|
|
166
|
+
alias: alias.value,
|
|
167
|
+
host: host.value,
|
|
168
|
+
port: parseRequiredPositiveInt(port.value, "--port"),
|
|
169
|
+
token: token.value
|
|
170
|
+
}, undefined, context.projectRoot);
|
|
171
|
+
if (context.outputMode === "text") {
|
|
172
|
+
console.log(`Saved remote endpoint ${created.alias} -> ${created.host}:${created.port}`);
|
|
173
|
+
}
|
|
174
|
+
return { ok: true, group: "remote", command: "endpoint add", details: redactRemoteEndpoint(created) };
|
|
175
|
+
}
|
|
176
|
+
case "update": {
|
|
177
|
+
let pending2 = subRest;
|
|
178
|
+
const endpointId = takeOption(pending2, "--id");
|
|
179
|
+
pending2 = endpointId.rest;
|
|
180
|
+
const alias = takeOption(pending2, "--alias");
|
|
181
|
+
pending2 = alias.rest;
|
|
182
|
+
const host = takeOption(pending2, "--host");
|
|
183
|
+
pending2 = host.rest;
|
|
184
|
+
const port = takeOption(pending2, "--port");
|
|
185
|
+
pending2 = port.rest;
|
|
186
|
+
const token = takeOption(pending2, "--token");
|
|
187
|
+
pending2 = token.rest;
|
|
188
|
+
requireNoExtraArgs(pending2, "bun run rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
|
|
189
|
+
if (!endpointId.value && !alias.value) {
|
|
190
|
+
throw new CliError2("remote endpoint update requires --id <id> or --alias <a>.");
|
|
191
|
+
}
|
|
192
|
+
const updated = updateManagedRemoteEndpointInAuthority(context.projectRoot, {
|
|
193
|
+
endpointId: endpointId.value || undefined,
|
|
194
|
+
alias: alias.value || undefined,
|
|
195
|
+
host: host.value || undefined,
|
|
196
|
+
port: port.value ? parseRequiredPositiveInt(port.value, "--port") : undefined,
|
|
197
|
+
token: token.value || undefined
|
|
198
|
+
});
|
|
199
|
+
if (!updated) {
|
|
200
|
+
throw new CliError2("Remote endpoint not found.", 2);
|
|
201
|
+
}
|
|
202
|
+
if (context.outputMode === "text") {
|
|
203
|
+
console.log(`Updated remote endpoint ${updated.alias} -> ${updated.host}:${updated.port}`);
|
|
204
|
+
}
|
|
205
|
+
return { ok: true, group: "remote", command: "endpoint update", details: redactRemoteEndpoint(updated) };
|
|
206
|
+
}
|
|
207
|
+
case "remove": {
|
|
208
|
+
let pending2 = subRest;
|
|
209
|
+
const alias = takeOption(pending2, "--alias");
|
|
210
|
+
pending2 = alias.rest;
|
|
211
|
+
requireNoExtraArgs(pending2, "bun run rig remote endpoint remove --alias <a>");
|
|
212
|
+
if (!alias.value) {
|
|
213
|
+
throw new CliError2("remote endpoint remove requires --alias.");
|
|
214
|
+
}
|
|
215
|
+
const removed = removeManagedRemoteEndpoint(alias.value, undefined, context.projectRoot);
|
|
216
|
+
if (!removed) {
|
|
217
|
+
throw new CliError2(`Remote endpoint alias not found: ${alias.value}`, 2);
|
|
218
|
+
}
|
|
219
|
+
if (context.outputMode === "text") {
|
|
220
|
+
console.log(`Removed remote endpoint ${alias.value}`);
|
|
221
|
+
}
|
|
222
|
+
return { ok: true, group: "remote", command: "endpoint remove", details: { alias: alias.value } };
|
|
223
|
+
}
|
|
224
|
+
case "test": {
|
|
225
|
+
let pending2 = subRest;
|
|
226
|
+
const alias = takeOption(pending2, "--alias");
|
|
227
|
+
pending2 = alias.rest;
|
|
228
|
+
requireNoExtraArgs(pending2, "bun run rig remote endpoint test --alias <a>");
|
|
229
|
+
if (!alias.value) {
|
|
230
|
+
throw new CliError2("remote endpoint test requires --alias.");
|
|
231
|
+
}
|
|
232
|
+
const endpoint2 = resolveRemoteEndpoint({ remoteAlias: alias.value, projectRoot: context.projectRoot });
|
|
233
|
+
const client = new RemoteWsClient(endpoint2);
|
|
234
|
+
const startedAt = Date.now();
|
|
235
|
+
try {
|
|
236
|
+
await client.connect();
|
|
237
|
+
const response = await client.ping();
|
|
238
|
+
const latencyMs = Date.now() - startedAt;
|
|
239
|
+
if (context.outputMode === "text") {
|
|
240
|
+
console.log(`Remote endpoint ${alias.value} responded in ${latencyMs}ms.`);
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
ok: true,
|
|
244
|
+
group: "remote",
|
|
245
|
+
command: "endpoint test",
|
|
246
|
+
details: {
|
|
247
|
+
alias: alias.value,
|
|
248
|
+
host: endpoint2.host,
|
|
249
|
+
port: endpoint2.port,
|
|
250
|
+
latencyMs,
|
|
251
|
+
response: redactSecretFields(response)
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
} finally {
|
|
255
|
+
client.disconnect();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
case "migrate": {
|
|
259
|
+
requireNoExtraArgs(subRest, "bun run rig remote endpoint migrate");
|
|
260
|
+
const result = migrateManagedRemoteEndpoints(context.projectRoot);
|
|
261
|
+
if (context.outputMode === "text") {
|
|
262
|
+
console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
|
|
263
|
+
}
|
|
264
|
+
return { ok: true, group: "remote", command: "endpoint migrate", details: result };
|
|
265
|
+
}
|
|
266
|
+
case "doctor": {
|
|
267
|
+
requireNoExtraArgs(subRest, "bun run rig remote endpoint doctor");
|
|
268
|
+
const result = doctorManagedRemoteEndpoints(context.projectRoot);
|
|
269
|
+
if (context.outputMode === "text") {
|
|
270
|
+
console.log(JSON.stringify(result, null, 2));
|
|
271
|
+
}
|
|
272
|
+
return { ok: true, group: "remote", command: "endpoint doctor", details: result };
|
|
273
|
+
}
|
|
274
|
+
default:
|
|
275
|
+
throw new CliError2(`Unknown remote endpoint command: ${subcommand}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
let pending = rest;
|
|
279
|
+
const remoteAliasResult = takeOption(pending, "--remote");
|
|
280
|
+
pending = remoteAliasResult.rest;
|
|
281
|
+
const hostResult = takeOption(pending, "--host");
|
|
282
|
+
pending = hostResult.rest;
|
|
283
|
+
const portResult = takeOption(pending, "--port");
|
|
284
|
+
pending = portResult.rest;
|
|
285
|
+
const tokenResult = takeOption(pending, "--token");
|
|
286
|
+
pending = tokenResult.rest;
|
|
287
|
+
const endpoint = resolveRemoteEndpoint({
|
|
288
|
+
host: hostResult.value,
|
|
289
|
+
port: portResult.value,
|
|
290
|
+
token: tokenResult.value,
|
|
291
|
+
remoteAlias: remoteAliasResult.value,
|
|
292
|
+
projectRoot: context.projectRoot
|
|
293
|
+
});
|
|
294
|
+
const remoteMeta = {
|
|
295
|
+
source: endpoint.source,
|
|
296
|
+
alias: endpoint.alias || null,
|
|
297
|
+
host: endpoint.host,
|
|
298
|
+
port: endpoint.port
|
|
299
|
+
};
|
|
300
|
+
const withClient = async (runner) => {
|
|
301
|
+
const client = new RemoteWsClient(endpoint);
|
|
302
|
+
try {
|
|
303
|
+
await client.connect();
|
|
304
|
+
return await runner(client);
|
|
305
|
+
} finally {
|
|
306
|
+
client.disconnect();
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
const toDetails = (response) => ({
|
|
310
|
+
command: `remote ${command}`,
|
|
311
|
+
remote: remoteMeta,
|
|
312
|
+
requestId: response.id || null,
|
|
313
|
+
messageType: response.type,
|
|
314
|
+
payload: redactSecretFields(response),
|
|
315
|
+
error: null
|
|
316
|
+
});
|
|
317
|
+
try {
|
|
318
|
+
switch (command) {
|
|
319
|
+
case "test": {
|
|
320
|
+
requireNoExtraArgs(pending, "bun run rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
321
|
+
const response = await withClient((client) => client.ping());
|
|
322
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
323
|
+
}
|
|
324
|
+
case "status": {
|
|
325
|
+
requireNoExtraArgs(pending, "bun run rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
326
|
+
const response = await withClient((client) => client.getState());
|
|
327
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
328
|
+
}
|
|
329
|
+
case "tasks": {
|
|
330
|
+
requireNoExtraArgs(pending, "bun run rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
331
|
+
const response = await withClient((client) => client.getTasks());
|
|
332
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
333
|
+
}
|
|
334
|
+
case "watch": {
|
|
335
|
+
let watchPending = pending;
|
|
336
|
+
const secondsResult = takeOption(watchPending, "--seconds");
|
|
337
|
+
watchPending = secondsResult.rest;
|
|
338
|
+
const eventResult = takeOption(watchPending, "--event");
|
|
339
|
+
watchPending = eventResult.rest;
|
|
340
|
+
requireNoExtraArgs(watchPending, "bun run rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
341
|
+
const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
|
|
342
|
+
const eventFilter = eventResult.value || undefined;
|
|
343
|
+
if (context.outputMode === "json" && !seconds) {
|
|
344
|
+
throw new CliError2("--json remote watch requires --seconds <n> to produce bounded output.", 2);
|
|
345
|
+
}
|
|
346
|
+
const captured = [];
|
|
347
|
+
let dropped = 0;
|
|
348
|
+
let received = 0;
|
|
349
|
+
let stop = false;
|
|
350
|
+
const onSignal = () => {
|
|
351
|
+
stop = true;
|
|
352
|
+
};
|
|
353
|
+
process.once("SIGINT", onSignal);
|
|
354
|
+
process.once("SIGTERM", onSignal);
|
|
355
|
+
try {
|
|
356
|
+
await withClient(async (client) => {
|
|
357
|
+
client.setEventHandler((event) => {
|
|
358
|
+
if (!matchesEventFilter(event.message, eventFilter)) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
received += 1;
|
|
362
|
+
if (context.outputMode === "text") {
|
|
363
|
+
console.log(`[${event.receivedAt}] ${summarizeMessage(event.message)}`);
|
|
364
|
+
} else if (captured.length < 200) {
|
|
365
|
+
captured.push(event.message);
|
|
366
|
+
} else {
|
|
367
|
+
dropped += 1;
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
const subscribed = await client.subscribe(eventFilter ? [eventFilter] : []);
|
|
371
|
+
if (!subscribed.success) {
|
|
372
|
+
throw new RemoteCliError("RIG_REMOTE_SUBSCRIBE_FAILED", subscribed.error || "Failed to subscribe to remote events.", 3);
|
|
373
|
+
}
|
|
374
|
+
if (seconds) {
|
|
375
|
+
await Bun.sleep(seconds * 1000);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
while (!stop) {
|
|
379
|
+
await Bun.sleep(250);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
} finally {
|
|
383
|
+
process.off("SIGINT", onSignal);
|
|
384
|
+
process.off("SIGTERM", onSignal);
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
ok: true,
|
|
388
|
+
group: "remote",
|
|
389
|
+
command,
|
|
390
|
+
details: {
|
|
391
|
+
command: "remote watch",
|
|
392
|
+
remote: remoteMeta,
|
|
393
|
+
messageType: "stream",
|
|
394
|
+
requestId: null,
|
|
395
|
+
payload: context.outputMode === "json" ? captured : null,
|
|
396
|
+
error: null,
|
|
397
|
+
received,
|
|
398
|
+
dropped,
|
|
399
|
+
event: eventFilter || null,
|
|
400
|
+
seconds: seconds || null
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
case "pause":
|
|
405
|
+
case "resume":
|
|
406
|
+
case "stop":
|
|
407
|
+
case "continue":
|
|
408
|
+
case "refresh": {
|
|
409
|
+
requireNoExtraArgs(pending, `bun run rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
410
|
+
const response = await withClient(async (client) => {
|
|
411
|
+
switch (command) {
|
|
412
|
+
case "pause":
|
|
413
|
+
return await client.pause();
|
|
414
|
+
case "resume":
|
|
415
|
+
return await client.resume();
|
|
416
|
+
case "stop":
|
|
417
|
+
return await client.interrupt();
|
|
418
|
+
case "continue":
|
|
419
|
+
return await client.continueExecution();
|
|
420
|
+
default:
|
|
421
|
+
return await client.refreshTasks();
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
assertRemoteOperationSuccess(command, response);
|
|
425
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
426
|
+
}
|
|
427
|
+
case "add-iterations":
|
|
428
|
+
case "remove-iterations": {
|
|
429
|
+
let countPending = pending;
|
|
430
|
+
const countResult = takeOption(countPending, "--count");
|
|
431
|
+
countPending = countResult.rest;
|
|
432
|
+
requireNoExtraArgs(countPending, `bun run rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
433
|
+
const count = parseRequiredPositiveInt(countResult.value, "--count");
|
|
434
|
+
const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
|
|
435
|
+
assertRemoteOperationSuccess(command, response);
|
|
436
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
437
|
+
}
|
|
438
|
+
case "prompt-preview":
|
|
439
|
+
case "iteration-output": {
|
|
440
|
+
let taskPending = pending;
|
|
441
|
+
const taskResult = takeOption(taskPending, "--task");
|
|
442
|
+
taskPending = taskResult.rest;
|
|
443
|
+
requireNoExtraArgs(taskPending, `bun run rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
444
|
+
const taskId = requireTask(taskResult.value, `bun run rig remote ${command} --task <id>`);
|
|
445
|
+
const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
|
|
446
|
+
assertRemoteOperationSuccess(command, response);
|
|
447
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
448
|
+
}
|
|
449
|
+
case "orchestrate-start": {
|
|
450
|
+
let orchestrationPending = pending;
|
|
451
|
+
const maxWorkersResult = takeOption(orchestrationPending, "--max-workers");
|
|
452
|
+
orchestrationPending = maxWorkersResult.rest;
|
|
453
|
+
const maxIterationsResult = takeOption(orchestrationPending, "--max-iterations");
|
|
454
|
+
orchestrationPending = maxIterationsResult.rest;
|
|
455
|
+
const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
|
|
456
|
+
orchestrationPending = directMergeResult.rest;
|
|
457
|
+
requireNoExtraArgs(orchestrationPending, "bun run rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
|
|
458
|
+
const response = await withClient((client) => client.startOrchestration({
|
|
459
|
+
maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
|
|
460
|
+
maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
|
|
461
|
+
directMerge: directMergeResult.value
|
|
462
|
+
}));
|
|
463
|
+
assertRemoteOperationSuccess(command, response);
|
|
464
|
+
return {
|
|
465
|
+
ok: true,
|
|
466
|
+
group: "remote",
|
|
467
|
+
command,
|
|
468
|
+
details: toDetails(response)
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
case "orchestrate-pause":
|
|
472
|
+
case "orchestrate-resume":
|
|
473
|
+
case "orchestrate-stop":
|
|
474
|
+
case "orchestrate-state": {
|
|
475
|
+
let orchestrationPending = pending;
|
|
476
|
+
const idResult = takeOption(orchestrationPending, "--id");
|
|
477
|
+
orchestrationPending = idResult.rest;
|
|
478
|
+
requireNoExtraArgs(orchestrationPending, `bun run rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
479
|
+
const orchestrationId = requireTask(idResult.value, `bun run rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
480
|
+
const response = await withClient(async (client) => {
|
|
481
|
+
switch (command) {
|
|
482
|
+
case "orchestrate-pause":
|
|
483
|
+
return await client.pauseOrchestration(orchestrationId);
|
|
484
|
+
case "orchestrate-resume":
|
|
485
|
+
return await client.resumeOrchestration(orchestrationId);
|
|
486
|
+
case "orchestrate-stop":
|
|
487
|
+
return await client.stopOrchestration(orchestrationId);
|
|
488
|
+
default:
|
|
489
|
+
return await client.getOrchestrationState(orchestrationId);
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
assertRemoteOperationSuccess(command, response);
|
|
493
|
+
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
494
|
+
}
|
|
495
|
+
default:
|
|
496
|
+
throw new CliError2(`Unknown remote command: ${command}`);
|
|
497
|
+
}
|
|
498
|
+
} catch (error) {
|
|
499
|
+
if (error instanceof RemoteCliError) {
|
|
500
|
+
throw new CliError2(`[${error.code}] ${error.message}`, error.exitCode);
|
|
501
|
+
}
|
|
502
|
+
throw error;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
export {
|
|
506
|
+
executeRemote
|
|
507
|
+
};
|