@h-rig/cli 0.0.6-alpha.78 → 0.0.6-alpha.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/build-rig-binaries.d.ts +2 -0
- package/dist/bin/rig.d.ts +2 -0
- package/dist/bin/rig.js +37 -13
- package/dist/src/app/board.d.ts +23 -0
- package/dist/src/app/board.js +11 -8
- package/dist/src/app/drone-ui.d.ts +37 -0
- package/dist/src/app/theme.d.ts +47 -0
- package/dist/src/commands/_async-ui.d.ts +13 -0
- package/dist/src/commands/_authority-runs.d.ts +22 -0
- package/dist/src/commands/_cli-format.d.ts +49 -0
- package/dist/src/commands/_connection-state.d.ts +44 -0
- package/dist/src/commands/_doctor-checks.d.ts +52 -0
- package/dist/src/commands/_help-catalog.d.ts +51 -0
- package/dist/src/commands/_help-catalog.js +1 -0
- package/dist/src/commands/_json-output.d.ts +11 -0
- package/dist/src/commands/_operator-surface.d.ts +34 -0
- package/dist/src/commands/_operator-view.d.ts +30 -0
- package/dist/src/commands/_parsers.d.ts +15 -0
- package/dist/src/commands/_paths.d.ts +11 -0
- package/dist/src/commands/_pi-frontend.d.ts +27 -0
- package/dist/src/commands/_pi-install.d.ts +42 -0
- package/dist/src/commands/_pi-install.js +1 -1
- package/dist/src/commands/_policy.d.ts +8 -0
- package/dist/src/commands/_preflight.d.ts +22 -0
- package/dist/src/commands/_probes.d.ts +1 -0
- package/dist/src/commands/_run-driver-helpers.d.ts +99 -0
- package/dist/src/commands/_run-replay.d.ts +24 -0
- package/dist/src/commands/_server-client.d.ts +186 -0
- package/dist/src/commands/_snapshot-upload.d.ts +39 -0
- package/dist/src/commands/_spinner.d.ts +25 -0
- package/dist/src/commands/_task-picker.d.ts +9 -0
- package/dist/src/commands/agent.d.ts +3 -0
- package/dist/src/commands/browser.d.ts +65 -0
- package/dist/src/commands/connect.d.ts +7 -0
- package/dist/src/commands/dist.d.ts +28 -0
- package/dist/src/commands/doctor.d.ts +3 -0
- package/dist/src/commands/github.d.ts +3 -0
- package/dist/src/commands/inbox.d.ts +30 -0
- package/dist/src/commands/init.d.ts +74 -0
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/inspect.d.ts +3 -0
- package/dist/src/commands/inspector.d.ts +3 -0
- package/dist/src/commands/pi.d.ts +3 -0
- package/dist/src/commands/plugin.d.ts +16 -0
- package/dist/src/commands/profile-and-review.d.ts +4 -0
- package/dist/src/commands/queue.d.ts +3 -0
- package/dist/src/commands/remote.d.ts +3 -0
- package/dist/src/commands/repo-git-harness.d.ts +5 -0
- package/dist/src/commands/run.d.ts +3 -0
- package/dist/src/commands/server.d.ts +7 -0
- package/dist/src/commands/setup.d.ts +16 -0
- package/dist/src/commands/stats.d.ts +12 -0
- package/dist/src/commands/stats.js +1 -0
- package/dist/src/commands/task-report-bug.d.ts +19 -0
- package/dist/src/commands/task-run-driver.d.ts +132 -0
- package/dist/src/commands/task-run-driver.js +23 -2
- package/dist/src/commands/task.d.ts +14 -0
- package/dist/src/commands/task.js +1 -0
- package/dist/src/commands/test.d.ts +3 -0
- package/dist/src/commands/workspace.d.ts +3 -0
- package/dist/src/commands.d.ts +29 -0
- package/dist/src/commands.js +37 -13
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +37 -13
- package/dist/src/launcher.d.ts +61 -0
- package/dist/src/report-bug.d.ts +44 -0
- package/dist/src/runner.d.ts +47 -0
- package/dist/src/withMutedConsole.d.ts +2 -0
- package/package.json +10 -8
package/dist/bin/rig.js
CHANGED
|
@@ -3217,6 +3217,7 @@ var init__help_catalog = __esm(() => {
|
|
|
3217
3217
|
{ command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
|
|
3218
3218
|
{ command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
|
|
3219
3219
|
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
3220
|
+
{ command: "ready", description: "List task IDs that are runnable now." },
|
|
3220
3221
|
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
3221
3222
|
{ command: "details --task <id>", description: "Show full task info from the configured source." },
|
|
3222
3223
|
{ command: "reopen [--task <id> | --all] [--reason <text>]", description: "Reopen closed task(s) in the configured source." },
|
|
@@ -4011,7 +4012,7 @@ __export(exports_board, {
|
|
|
4011
4012
|
import { randomUUID } from "crypto";
|
|
4012
4013
|
import { existsSync as existsSync18 } from "fs";
|
|
4013
4014
|
import { resolve as resolvePath } from "path";
|
|
4014
|
-
import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
|
|
4015
|
+
import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, isKeyRelease, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
|
|
4015
4016
|
function oneLine(message2) {
|
|
4016
4017
|
return message2.split(`
|
|
4017
4018
|
`).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? "unknown error";
|
|
@@ -4463,13 +4464,13 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
4463
4464
|
return;
|
|
4464
4465
|
}
|
|
4465
4466
|
if (view === "help") {
|
|
4466
|
-
footer.setText(` ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
|
|
4467
|
+
footer.setText(` ${accent("\u2190")}${ink3(" back")} ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
|
|
4467
4468
|
return;
|
|
4468
4469
|
}
|
|
4469
4470
|
if (view === "tasks") {
|
|
4470
4471
|
footer.setText([
|
|
4471
4472
|
` ${notice ? accentDim(notice) : ink4("pick a task \u2014 a drone launches with project defaults")}`,
|
|
4472
|
-
` ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
|
|
4473
|
+
` ${accent("\u2190")}${ink3(" back")} ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
|
|
4473
4474
|
].join(`
|
|
4474
4475
|
`));
|
|
4475
4476
|
return;
|
|
@@ -4477,7 +4478,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
4477
4478
|
if (view === "inbox") {
|
|
4478
4479
|
footer.setText([
|
|
4479
4480
|
` ${notice ? accentDim(notice) : ink4("gates the fleet is waiting on \u2014 resolve them here")}`,
|
|
4480
|
-
` ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
|
|
4481
|
+
` ${accent("\u2190")}${ink3(" back")} ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
|
|
4481
4482
|
].join(`
|
|
4482
4483
|
`));
|
|
4483
4484
|
return;
|
|
@@ -4644,6 +4645,8 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
4644
4645
|
tui.requestRender();
|
|
4645
4646
|
}).catch(() => {});
|
|
4646
4647
|
tui.addInputListener((data) => {
|
|
4648
|
+
if (isKeyRelease(data))
|
|
4649
|
+
return { consume: true };
|
|
4647
4650
|
if (inputLine) {
|
|
4648
4651
|
if (matchesKey2(data, "escape")) {
|
|
4649
4652
|
if (inputLine.kind === "search")
|
|
@@ -4680,7 +4683,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
4680
4683
|
helpView.scroll(-15);
|
|
4681
4684
|
else if (matchesKey2(data, "pageDown") || data === " ")
|
|
4682
4685
|
helpView.scroll(15);
|
|
4683
|
-
else if (matchesKey2(data, "escape") || data === "?") {
|
|
4686
|
+
else if (matchesKey2(data, "left") || matchesKey2(data, "escape") || data === "?") {
|
|
4684
4687
|
setView("board");
|
|
4685
4688
|
return { consume: true };
|
|
4686
4689
|
}
|
|
@@ -4698,7 +4701,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
4698
4701
|
dispatchTask(task);
|
|
4699
4702
|
} else if (data === "r")
|
|
4700
4703
|
refreshTasks();
|
|
4701
|
-
else if (matchesKey2(data, "escape"))
|
|
4704
|
+
else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
|
|
4702
4705
|
setView("board");
|
|
4703
4706
|
tui.requestRender();
|
|
4704
4707
|
return { consume: true };
|
|
@@ -4726,7 +4729,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
4726
4729
|
}
|
|
4727
4730
|
} else if (data === "r")
|
|
4728
4731
|
refreshInbox();
|
|
4729
|
-
else if (matchesKey2(data, "escape"))
|
|
4732
|
+
else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
|
|
4730
4733
|
setView("board");
|
|
4731
4734
|
tui.requestRender();
|
|
4732
4735
|
return { consume: true };
|
|
@@ -4837,7 +4840,7 @@ async function runOperatorBoardLoop(context, attach, options = {}) {
|
|
|
4837
4840
|
await attach(outcome.runId);
|
|
4838
4841
|
}
|
|
4839
4842
|
}
|
|
4840
|
-
var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS =
|
|
4843
|
+
var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS = 250, BOARD_TASK_PAGE = 20;
|
|
4841
4844
|
var init_board = __esm(() => {
|
|
4842
4845
|
init_theme();
|
|
4843
4846
|
init__help_catalog();
|
|
@@ -7745,7 +7748,7 @@ async function ensurePiBinaryAvailable(input) {
|
|
|
7745
7748
|
}
|
|
7746
7749
|
return { ok: true, detail: (current.stdout || current.stderr).trim() || undefined };
|
|
7747
7750
|
}
|
|
7748
|
-
const installCommand = process.env.RIG_PI_INSTALL_COMMAND?.trim() || "bunx @earendil-works/pi@latest install";
|
|
7751
|
+
const installCommand = process.env.RIG_PI_INSTALL_COMMAND?.trim() || "bunx @earendil-works/pi-coding-agent@latest install";
|
|
7749
7752
|
const parts = splitInstallCommand(installCommand);
|
|
7750
7753
|
if (parts.length === 0) {
|
|
7751
7754
|
return { ok: false, error: (current.stderr || current.stdout).trim() || "pi --version failed" };
|
|
@@ -11213,6 +11216,19 @@ function looksLikeGitHubToken(value) {
|
|
|
11213
11216
|
return false;
|
|
11214
11217
|
return /^(gh[opusr]_|github_pat_)/.test(token);
|
|
11215
11218
|
}
|
|
11219
|
+
function isSensitivePayloadKey(key) {
|
|
11220
|
+
return /token|secret|password|authorization|credential/i.test(key);
|
|
11221
|
+
}
|
|
11222
|
+
function redactSensitivePayload(value) {
|
|
11223
|
+
if (Array.isArray(value))
|
|
11224
|
+
return value.map(redactSensitivePayload);
|
|
11225
|
+
if (!value || typeof value !== "object")
|
|
11226
|
+
return value;
|
|
11227
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [
|
|
11228
|
+
key,
|
|
11229
|
+
isSensitivePayloadKey(key) && typeof child === "string" && child.trim() ? "[redacted]" : redactSensitivePayload(child)
|
|
11230
|
+
]));
|
|
11231
|
+
}
|
|
11216
11232
|
function githubBridgeEnv(token) {
|
|
11217
11233
|
const clean = token?.trim();
|
|
11218
11234
|
if (!clean)
|
|
@@ -11903,7 +11919,7 @@ function appendPiToolTimelineFromRecord(input) {
|
|
|
11903
11919
|
}
|
|
11904
11920
|
function isNonRenderablePiProtocolRecord(record) {
|
|
11905
11921
|
const type = typeof record.type === "string" ? record.type : "";
|
|
11906
|
-
return type === "agent_start" || type === "agent_end" || type === "message_start" || type === "message_end" || type === "turn_start" || type === "turn_end" || type === "tool_result" || type === "message_update" && (!record.assistantMessageEvent || typeof record.assistantMessageEvent !== "object" || Array.isArray(record.assistantMessageEvent) || record.assistantMessageEvent.type !== "text_delta");
|
|
11922
|
+
return type === "pi.event" || type === "status.update" || type === "activity.update" || type === "ready" || type === "agent_start" || type === "agent_end" || type === "message_start" || type === "message_end" || type === "turn_start" || type === "turn_end" || type === "tool_result" || type === "message_update" && (!record.assistantMessageEvent || typeof record.assistantMessageEvent !== "object" || Array.isArray(record.assistantMessageEvent) || record.assistantMessageEvent.type !== "text_delta");
|
|
11907
11923
|
}
|
|
11908
11924
|
function appendToolTimelineFromLog(input) {
|
|
11909
11925
|
const title = typeof input.log.title === "string" ? input.log.title : "";
|
|
@@ -12463,7 +12479,15 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
12463
12479
|
emitServerRunEvent({ type: "log", runId: input.runId, title });
|
|
12464
12480
|
return true;
|
|
12465
12481
|
}
|
|
12466
|
-
|
|
12482
|
+
appendRunTimeline(context.projectRoot, input.runId, {
|
|
12483
|
+
id: `timeline:${input.runId}:${Date.now()}:wrapper:${event.type}`,
|
|
12484
|
+
type: "wrapper-event",
|
|
12485
|
+
eventType: event.type,
|
|
12486
|
+
payload: redactSensitivePayload(payload),
|
|
12487
|
+
createdAt: new Date().toISOString()
|
|
12488
|
+
});
|
|
12489
|
+
emitServerRunEvent({ type: "timeline", runId: input.runId });
|
|
12490
|
+
return true;
|
|
12467
12491
|
};
|
|
12468
12492
|
const handleAgentStdoutLine = (line) => {
|
|
12469
12493
|
const trimmed = line.trim();
|
|
@@ -13520,9 +13544,9 @@ async function openApp(context, options = {}) {
|
|
|
13520
13544
|
const { runOperatorBoardLoop: runOperatorBoardLoop2 } = await Promise.resolve().then(() => (init_board(), exports_board));
|
|
13521
13545
|
await runOperatorBoardLoop2(context, async (runId) => {
|
|
13522
13546
|
const scriptArg = typeof process.argv[1] === "string" && /\.(ts|js|mjs)$/.test(process.argv[1]) ? [process.argv[1]] : [];
|
|
13523
|
-
const child = Bun.spawn([process.execPath, ...scriptArg, "run", "attach", runId], {
|
|
13547
|
+
const child = Bun.spawn([process.execPath, ...scriptArg, "--project", context.projectRoot, "run", "attach", runId], {
|
|
13524
13548
|
stdio: ["inherit", "inherit", "inherit"],
|
|
13525
|
-
env: process.env
|
|
13549
|
+
env: { ...process.env, PROJECT_RIG_ROOT: context.projectRoot }
|
|
13526
13550
|
});
|
|
13527
13551
|
await child.exited;
|
|
13528
13552
|
}, options);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { RunnerContext } from "../runner";
|
|
2
|
+
export type BoardOutcome = {
|
|
3
|
+
action: "quit";
|
|
4
|
+
} | {
|
|
5
|
+
action: "attach";
|
|
6
|
+
runId: string;
|
|
7
|
+
};
|
|
8
|
+
export type RunSortMode = "active" | "recent" | "status";
|
|
9
|
+
export type BoardView = "board" | "help" | "tasks" | "inbox";
|
|
10
|
+
/**
|
|
11
|
+
* Run the operator board until the operator picks a run (→ attach) or
|
|
12
|
+
* quits. The caller owns the attach loop so the Pi console gets a clean
|
|
13
|
+
* terminal between board sessions.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runOperatorBoard(context: Pick<RunnerContext, "projectRoot" | "outputMode">, options?: {
|
|
16
|
+
initialView?: BoardView;
|
|
17
|
+
helpGroup?: string;
|
|
18
|
+
}): Promise<BoardOutcome>;
|
|
19
|
+
/** Board ⇆ console loop: the operator lives here. */
|
|
20
|
+
export declare function runOperatorBoardLoop(context: Pick<RunnerContext, "projectRoot" | "outputMode">, attach: (runId: string) => Promise<void>, options?: {
|
|
21
|
+
initialView?: BoardView;
|
|
22
|
+
helpGroup?: string;
|
|
23
|
+
}): Promise<void>;
|
package/dist/src/app/board.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { randomUUID } from "crypto";
|
|
4
4
|
import { existsSync as existsSync3 } from "fs";
|
|
5
5
|
import { resolve as resolvePath } from "path";
|
|
6
|
-
import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
|
|
6
|
+
import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, isKeyRelease, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
|
|
7
7
|
|
|
8
8
|
// packages/cli/src/app/theme.ts
|
|
9
9
|
var RIG_PALETTE = {
|
|
@@ -223,6 +223,7 @@ var PRIMARY_GROUPS = [
|
|
|
223
223
|
{ command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
|
|
224
224
|
{ command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
|
|
225
225
|
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
226
|
+
{ command: "ready", description: "List task IDs that are runnable now." },
|
|
226
227
|
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
227
228
|
{ command: "details --task <id>", description: "Show full task info from the configured source." },
|
|
228
229
|
{ command: "reopen [--task <id> | --all] [--reason <text>]", description: "Reopen closed task(s) in the configured source." },
|
|
@@ -950,7 +951,7 @@ async function loadTaskRunProjectDefaults(projectRoot) {
|
|
|
950
951
|
|
|
951
952
|
// packages/cli/src/app/board.ts
|
|
952
953
|
var BOARD_REFRESH_MS = 5000;
|
|
953
|
-
var BOARD_TICK_MS =
|
|
954
|
+
var BOARD_TICK_MS = 250;
|
|
954
955
|
var BOARD_TASK_PAGE = 20;
|
|
955
956
|
function oneLine(message) {
|
|
956
957
|
return message.split(`
|
|
@@ -1403,13 +1404,13 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
1403
1404
|
return;
|
|
1404
1405
|
}
|
|
1405
1406
|
if (view === "help") {
|
|
1406
|
-
footer.setText(` ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
|
|
1407
|
+
footer.setText(` ${accent("\u2190")}${ink3(" back")} ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
|
|
1407
1408
|
return;
|
|
1408
1409
|
}
|
|
1409
1410
|
if (view === "tasks") {
|
|
1410
1411
|
footer.setText([
|
|
1411
1412
|
` ${notice ? accentDim(notice) : ink4("pick a task \u2014 a drone launches with project defaults")}`,
|
|
1412
|
-
` ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
|
|
1413
|
+
` ${accent("\u2190")}${ink3(" back")} ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
|
|
1413
1414
|
].join(`
|
|
1414
1415
|
`));
|
|
1415
1416
|
return;
|
|
@@ -1417,7 +1418,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
1417
1418
|
if (view === "inbox") {
|
|
1418
1419
|
footer.setText([
|
|
1419
1420
|
` ${notice ? accentDim(notice) : ink4("gates the fleet is waiting on \u2014 resolve them here")}`,
|
|
1420
|
-
` ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
|
|
1421
|
+
` ${accent("\u2190")}${ink3(" back")} ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
|
|
1421
1422
|
].join(`
|
|
1422
1423
|
`));
|
|
1423
1424
|
return;
|
|
@@ -1584,6 +1585,8 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
1584
1585
|
tui.requestRender();
|
|
1585
1586
|
}).catch(() => {});
|
|
1586
1587
|
tui.addInputListener((data) => {
|
|
1588
|
+
if (isKeyRelease(data))
|
|
1589
|
+
return { consume: true };
|
|
1587
1590
|
if (inputLine) {
|
|
1588
1591
|
if (matchesKey2(data, "escape")) {
|
|
1589
1592
|
if (inputLine.kind === "search")
|
|
@@ -1620,7 +1623,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
1620
1623
|
helpView.scroll(-15);
|
|
1621
1624
|
else if (matchesKey2(data, "pageDown") || data === " ")
|
|
1622
1625
|
helpView.scroll(15);
|
|
1623
|
-
else if (matchesKey2(data, "escape") || data === "?") {
|
|
1626
|
+
else if (matchesKey2(data, "left") || matchesKey2(data, "escape") || data === "?") {
|
|
1624
1627
|
setView("board");
|
|
1625
1628
|
return { consume: true };
|
|
1626
1629
|
}
|
|
@@ -1638,7 +1641,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
1638
1641
|
dispatchTask(task);
|
|
1639
1642
|
} else if (data === "r")
|
|
1640
1643
|
refreshTasks();
|
|
1641
|
-
else if (matchesKey2(data, "escape"))
|
|
1644
|
+
else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
|
|
1642
1645
|
setView("board");
|
|
1643
1646
|
tui.requestRender();
|
|
1644
1647
|
return { consume: true };
|
|
@@ -1666,7 +1669,7 @@ async function runOperatorBoard(context, options = {}) {
|
|
|
1666
1669
|
}
|
|
1667
1670
|
} else if (data === "r")
|
|
1668
1671
|
refreshInbox();
|
|
1669
|
-
else if (matchesKey2(data, "escape"))
|
|
1672
|
+
else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
|
|
1670
1673
|
setView("board");
|
|
1671
1674
|
tui.requestRender();
|
|
1672
1675
|
return { consume: true };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare function droneIntro(title: string, subtitle?: string): void;
|
|
2
|
+
export declare function droneOutro(text: string): void;
|
|
3
|
+
export declare function droneNote(message: string, title?: string): void;
|
|
4
|
+
export declare function droneStep(text: string): void;
|
|
5
|
+
export declare function droneInfo(text: string): void;
|
|
6
|
+
export declare function droneWarn(text: string): void;
|
|
7
|
+
export declare function droneError(text: string): void;
|
|
8
|
+
export declare function droneCancel(text: string): void;
|
|
9
|
+
/** Clack-spinner-shaped adapter over the micro-drone TTY spinner. */
|
|
10
|
+
export declare function droneSpinner(): {
|
|
11
|
+
start(message: string): void;
|
|
12
|
+
stop(message?: string): void;
|
|
13
|
+
error(message?: string): void;
|
|
14
|
+
};
|
|
15
|
+
type DroneSelectOption<T extends string> = {
|
|
16
|
+
value: T;
|
|
17
|
+
label: string;
|
|
18
|
+
hint?: string;
|
|
19
|
+
};
|
|
20
|
+
/** Drone-styled select. Returns null on cancel (esc / ctrl+c / q). */
|
|
21
|
+
export declare function droneSelect<T extends string>(input: {
|
|
22
|
+
readonly message: string;
|
|
23
|
+
readonly options: readonly DroneSelectOption<T>[];
|
|
24
|
+
readonly initialValue?: T;
|
|
25
|
+
}): Promise<T | null>;
|
|
26
|
+
/** Drone-styled text input. Returns null on cancel. */
|
|
27
|
+
export declare function droneText(input: {
|
|
28
|
+
readonly message: string;
|
|
29
|
+
readonly placeholder?: string;
|
|
30
|
+
readonly initialValue?: string;
|
|
31
|
+
}): Promise<string | null>;
|
|
32
|
+
/** Drone-styled yes/no. Returns null on cancel. */
|
|
33
|
+
export declare function droneConfirm(input: {
|
|
34
|
+
readonly message: string;
|
|
35
|
+
readonly initialValue?: boolean;
|
|
36
|
+
}): Promise<boolean | null>;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export declare const RIG_PALETTE: {
|
|
2
|
+
/** --ink: primary text */
|
|
3
|
+
readonly ink: "#f2f3f6";
|
|
4
|
+
/** --ink-2: body text */
|
|
5
|
+
readonly ink2: "#aeb0ba";
|
|
6
|
+
/** --ink-3: muted */
|
|
7
|
+
readonly ink3: "#6c6e79";
|
|
8
|
+
/** --ink-4: faint */
|
|
9
|
+
readonly ink4: "#44464f";
|
|
10
|
+
/** --ac: acid green accent */
|
|
11
|
+
readonly accent: "#ccff4d";
|
|
12
|
+
/** --ac-dim */
|
|
13
|
+
readonly accentDim: "#a9d63f";
|
|
14
|
+
/** --ac-2: cyan secondary */
|
|
15
|
+
readonly cyan: "#56d8ff";
|
|
16
|
+
/** status colors tuned to sit on the dark site bg */
|
|
17
|
+
readonly red: "#ff5d5d";
|
|
18
|
+
readonly yellow: "#ffd24d";
|
|
19
|
+
};
|
|
20
|
+
/** 24-bit foreground colorizer. */
|
|
21
|
+
export declare function fg(hex: string): (text: string) => string;
|
|
22
|
+
export declare const ink: (text: string) => string;
|
|
23
|
+
export declare const ink2: (text: string) => string;
|
|
24
|
+
export declare const ink3: (text: string) => string;
|
|
25
|
+
export declare const ink4: (text: string) => string;
|
|
26
|
+
export declare const accent: (text: string) => string;
|
|
27
|
+
export declare const accentDim: (text: string) => string;
|
|
28
|
+
export declare const cyan: (text: string) => string;
|
|
29
|
+
export declare const red: (text: string) => string;
|
|
30
|
+
export declare const yellow: (text: string) => string;
|
|
31
|
+
export declare function bold(text: string): string;
|
|
32
|
+
/** Run-status color, matching the site's pipeline color story. */
|
|
33
|
+
export declare function statusColor(status: string): (text: string) => string;
|
|
34
|
+
/** The braille spinner the site's hero terminal mirrors. */
|
|
35
|
+
export declare const RIG_SPINNER_FRAMES: readonly ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
36
|
+
/**
|
|
37
|
+
* Render one animation frame of the drone. `tick` drives rotor rotation and
|
|
38
|
+
* the eye pulse — call with an incrementing counter (the site advances the
|
|
39
|
+
* rotor every 4 ticks and pulses the eye on a sine).
|
|
40
|
+
*/
|
|
41
|
+
export declare function renderDroneFrame(tick: number): string[];
|
|
42
|
+
export declare const DRONE_WIDTH: number;
|
|
43
|
+
export declare const DRONE_HEIGHT: 18;
|
|
44
|
+
export declare function microDroneFrame(tick: number): string;
|
|
45
|
+
export declare const MICRO_DRONE_FRAMES: readonly string[];
|
|
46
|
+
/** Truecolor micro-drone: cyan rotors, acid eye — site colors. */
|
|
47
|
+
export declare function renderMicroDroneFrame(tick: number): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { OutputMode } from "@rig/runtime/control-plane/runtime/types";
|
|
2
|
+
export type SpinnerOutput = Pick<NodeJS.WriteStream, "write"> & {
|
|
3
|
+
readonly isTTY?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export type WithSpinnerOptions = {
|
|
6
|
+
/** Final line left behind on success. Default: the spinner line is erased. */
|
|
7
|
+
readonly doneLabel?: string;
|
|
8
|
+
/** Pass context.outputMode; "json" suppresses all spinner output. */
|
|
9
|
+
readonly outputMode?: OutputMode;
|
|
10
|
+
/** Stream override for tests. Defaults to process.stderr. */
|
|
11
|
+
readonly output?: SpinnerOutput;
|
|
12
|
+
};
|
|
13
|
+
export declare function withSpinner<T>(label: string, work: (update: (label: string) => void) => Promise<T>, options?: WithSpinnerOptions): Promise<T>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AuthorityRunRecord } from "@rig/runtime/control-plane/authority-files";
|
|
2
|
+
import type { RunStatus } from "@rig/contracts";
|
|
3
|
+
export declare const RIG_WORKSPACE_ID = "rig-local-workspace";
|
|
4
|
+
export type RuntimeAdapter = "claude-code" | "codex" | "pi";
|
|
5
|
+
export declare function normalizeRuntimeAdapter(value: string | undefined): RuntimeAdapter;
|
|
6
|
+
export declare function readLatestBeadRecord(projectRoot: string, taskId: string): Record<string, unknown> | null;
|
|
7
|
+
export declare function upsertAgentAuthorityRun(projectRoot: string, input: {
|
|
8
|
+
runId: string;
|
|
9
|
+
taskId: string;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
runtimeAdapter?: string;
|
|
12
|
+
status: RunStatus;
|
|
13
|
+
startedAt?: string | null;
|
|
14
|
+
completedAt?: string | null;
|
|
15
|
+
worktreePath?: string | null;
|
|
16
|
+
artifactRoot?: string | null;
|
|
17
|
+
logRoot?: string | null;
|
|
18
|
+
sessionPath?: string | null;
|
|
19
|
+
sessionLogPath?: string | null;
|
|
20
|
+
pid?: number | null;
|
|
21
|
+
errorText?: string | null;
|
|
22
|
+
}): AuthorityRunRecord & Record<string, unknown>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type CliTaskLike = Record<string, unknown>;
|
|
2
|
+
export type CliRunLike = Record<string, unknown>;
|
|
3
|
+
export declare function printFormattedOutput(message: string, options?: {
|
|
4
|
+
title?: string;
|
|
5
|
+
}): void;
|
|
6
|
+
export declare function formatStatusPill(status: string): string;
|
|
7
|
+
export declare function formatSection(title: string, subtitle?: string): string;
|
|
8
|
+
export declare function formatSuccessCard(title: string, rows?: Array<[string, string | number | null | undefined]>): string;
|
|
9
|
+
export declare function formatNextSteps(steps: readonly string[]): string[];
|
|
10
|
+
export declare function formatTaskList(tasks: readonly CliTaskLike[], options?: {
|
|
11
|
+
raw?: boolean;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function formatTaskCard(task: CliTaskLike, options?: {
|
|
14
|
+
title?: string;
|
|
15
|
+
selected?: boolean;
|
|
16
|
+
}): string;
|
|
17
|
+
export declare function formatTaskDetails(task: CliTaskLike): string;
|
|
18
|
+
export declare function formatRunList(runs: readonly CliRunLike[], options?: {
|
|
19
|
+
source?: "local" | "server";
|
|
20
|
+
}): string;
|
|
21
|
+
export declare function formatSubmittedRun(input: {
|
|
22
|
+
runId: string;
|
|
23
|
+
task?: CliTaskLike | null;
|
|
24
|
+
runtimeAdapter?: string | null;
|
|
25
|
+
runtimeMode?: string | null;
|
|
26
|
+
interactionMode?: string | null;
|
|
27
|
+
detached?: boolean;
|
|
28
|
+
}): string;
|
|
29
|
+
export declare function formatRunCard(run: CliRunLike, options?: {
|
|
30
|
+
title?: string;
|
|
31
|
+
}): string;
|
|
32
|
+
export declare function formatRunStatus(summary: {
|
|
33
|
+
activeRuns?: CliRunLike[];
|
|
34
|
+
recentRuns?: CliRunLike[];
|
|
35
|
+
runs?: CliRunLike[];
|
|
36
|
+
}, options?: {
|
|
37
|
+
source?: "local" | "server";
|
|
38
|
+
}): string;
|
|
39
|
+
export declare function formatInboxList(kind: "approvals" | "inputs", entries: readonly Record<string, unknown>[]): string;
|
|
40
|
+
export declare function formatConnectionList(connections: Record<string, {
|
|
41
|
+
kind: string;
|
|
42
|
+
baseUrl?: string;
|
|
43
|
+
mode?: string;
|
|
44
|
+
}>): string;
|
|
45
|
+
export declare function formatConnectionStatus(selected: string, connections: Record<string, {
|
|
46
|
+
kind: string;
|
|
47
|
+
baseUrl?: string;
|
|
48
|
+
mode?: string;
|
|
49
|
+
}>): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export type RigConnection = {
|
|
2
|
+
kind: "local";
|
|
3
|
+
mode: "auto";
|
|
4
|
+
} | {
|
|
5
|
+
kind: "remote";
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
};
|
|
8
|
+
export type GlobalConnectionState = {
|
|
9
|
+
connections: Record<string, RigConnection>;
|
|
10
|
+
};
|
|
11
|
+
export type RepoConnectionState = {
|
|
12
|
+
selected: string;
|
|
13
|
+
project?: string;
|
|
14
|
+
linkedAt?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The server-host project root this repo scopes to (multi-root serving).
|
|
17
|
+
* Sent as the x-rig-project-root header on every remote request.
|
|
18
|
+
*/
|
|
19
|
+
serverProjectRoot?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function resolveGlobalConnectionsPath(env?: NodeJS.ProcessEnv): string;
|
|
22
|
+
export declare function resolveRepoConnectionPath(projectRoot: string): string;
|
|
23
|
+
export declare function readGlobalConnections(options?: {
|
|
24
|
+
env?: NodeJS.ProcessEnv;
|
|
25
|
+
}): GlobalConnectionState;
|
|
26
|
+
export declare function writeGlobalConnections(state: GlobalConnectionState, options?: {
|
|
27
|
+
env?: NodeJS.ProcessEnv;
|
|
28
|
+
}): void;
|
|
29
|
+
export declare function upsertGlobalConnection(alias: string, connection: RigConnection, options?: {
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
}): GlobalConnectionState;
|
|
32
|
+
export declare function readRepoConnection(projectRoot: string): RepoConnectionState | null;
|
|
33
|
+
export declare function writeRepoConnection(projectRoot: string, state: RepoConnectionState): void;
|
|
34
|
+
export declare function resolveSelectedConnection(projectRoot: string, options?: {
|
|
35
|
+
env?: NodeJS.ProcessEnv;
|
|
36
|
+
}): {
|
|
37
|
+
alias: string;
|
|
38
|
+
connection: RigConnection;
|
|
39
|
+
serverProjectRoot?: string;
|
|
40
|
+
} | null;
|
|
41
|
+
/** Persist the server-host project root this repo scopes to (multi-root serving). */
|
|
42
|
+
export declare function writeRepoServerProjectRoot(projectRoot: string, serverProjectRoot: string): void;
|
|
43
|
+
/** Whether this repo's selected connection targets a remote Rig server. */
|
|
44
|
+
export declare function isRemoteConnectionSelected(projectRoot: string): boolean;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
type DoctorConfig = {
|
|
2
|
+
readonly project?: Record<string, unknown>;
|
|
3
|
+
readonly taskSource?: {
|
|
4
|
+
readonly kind?: string;
|
|
5
|
+
readonly owner?: string;
|
|
6
|
+
readonly repo?: string;
|
|
7
|
+
};
|
|
8
|
+
readonly github?: {
|
|
9
|
+
readonly projects?: {
|
|
10
|
+
readonly enabled?: boolean;
|
|
11
|
+
readonly projectId?: string;
|
|
12
|
+
readonly statusFieldId?: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
readonly pr?: {
|
|
16
|
+
readonly mode?: string;
|
|
17
|
+
};
|
|
18
|
+
readonly merge?: {
|
|
19
|
+
readonly mode?: string;
|
|
20
|
+
readonly method?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
import { type PiInstallCheck } from "./_pi-install";
|
|
24
|
+
export type DoctorStatus = "pass" | "warn" | "fail";
|
|
25
|
+
export type RigDoctorCheck = {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly label: string;
|
|
28
|
+
readonly status: DoctorStatus;
|
|
29
|
+
readonly detail?: string;
|
|
30
|
+
readonly remediation?: string;
|
|
31
|
+
};
|
|
32
|
+
export type RigDoctorServer = {
|
|
33
|
+
readonly baseUrl: string;
|
|
34
|
+
readonly authToken: string | null;
|
|
35
|
+
readonly connectionKind: "local" | "remote";
|
|
36
|
+
};
|
|
37
|
+
export type RunRigDoctorChecksOptions = {
|
|
38
|
+
readonly projectRoot: string;
|
|
39
|
+
readonly resolveServer?: (projectRoot: string) => Promise<RigDoctorServer>;
|
|
40
|
+
readonly requestJson?: (pathname: string, init?: RequestInit) => Promise<unknown>;
|
|
41
|
+
readonly piChecks?: () => Promise<readonly PiInstallCheck[]>;
|
|
42
|
+
readonly which?: (binary: string) => string | null;
|
|
43
|
+
readonly bunVersion?: string;
|
|
44
|
+
readonly loadConfig?: (projectRoot: string) => Promise<DoctorConfig | null>;
|
|
45
|
+
/** Per-check status narration ("Checking GitHub auth…") for wait spinners. */
|
|
46
|
+
readonly onProgress?: (label: string) => void;
|
|
47
|
+
};
|
|
48
|
+
export declare function runRigDoctorChecks(options: RunRigDoctorChecksOptions): Promise<RigDoctorCheck[]>;
|
|
49
|
+
export declare function formatDoctorChecks(checks: readonly RigDoctorCheck[]): string;
|
|
50
|
+
export declare function countDoctorFailures(checks: readonly RigDoctorCheck[]): number;
|
|
51
|
+
export declare function throwIfDoctorFailed(checks: readonly RigDoctorCheck[]): void;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type HelpCommand = {
|
|
2
|
+
command: string;
|
|
3
|
+
description: string;
|
|
4
|
+
primary?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export type HelpGroup = {
|
|
7
|
+
name: string;
|
|
8
|
+
summary: string;
|
|
9
|
+
usage: string[];
|
|
10
|
+
commands: HelpCommand[];
|
|
11
|
+
examples?: string[];
|
|
12
|
+
next?: string[];
|
|
13
|
+
advanced?: string[];
|
|
14
|
+
};
|
|
15
|
+
export type TopLevelSection = {
|
|
16
|
+
title: string;
|
|
17
|
+
subtitle: string;
|
|
18
|
+
commands: HelpCommand[];
|
|
19
|
+
};
|
|
20
|
+
/** Catalog DATA for the app's help view — the view builds its own layout
|
|
21
|
+
* from these; the render* functions below remain for plain/script output. */
|
|
22
|
+
export declare function helpCatalog(): {
|
|
23
|
+
sections: readonly TopLevelSection[];
|
|
24
|
+
groups: readonly HelpGroup[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Night City boot screen. Rendered only on interactive TTY launches — plain
|
|
28
|
+
* mode and --json never see it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderRigBanner(version?: string): string;
|
|
31
|
+
export declare function renderTopLevelHelp(): string;
|
|
32
|
+
export declare function renderAdvancedHelp(): string;
|
|
33
|
+
export declare function renderGroupHelp(groupName: string): string | null;
|
|
34
|
+
export declare function listHelpGroups(): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Fuzzy-match a bare word against known group subcommand names so the
|
|
37
|
+
* unknown-command error can suggest the canonical `rig <group> <cmd>`
|
|
38
|
+
* spelling. Primary groups win ties (ALL_GROUPS is primary-first).
|
|
39
|
+
*/
|
|
40
|
+
export declare function suggestGroupCommandForWord(word: string): string | null;
|
|
41
|
+
export type TopLevelLaunchState = {
|
|
42
|
+
/** True when the cwd resolves to an initialized Rig project. */
|
|
43
|
+
projectInitialized?: boolean;
|
|
44
|
+
/** Short description of the selected server connection, if known. */
|
|
45
|
+
selectedServer?: string | null;
|
|
46
|
+
/** CLI version for the banner footer. */
|
|
47
|
+
version?: string;
|
|
48
|
+
};
|
|
49
|
+
export declare function printTopLevelHelp(state?: TopLevelLaunchState): void;
|
|
50
|
+
export declare function printAdvancedHelp(): void;
|
|
51
|
+
export declare function printGroupHelpDocument(groupName: string): void;
|
|
@@ -94,6 +94,7 @@ var PRIMARY_GROUPS = [
|
|
|
94
94
|
{ command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
|
|
95
95
|
{ command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
|
|
96
96
|
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
97
|
+
{ command: "ready", description: "List task IDs that are runnable now." },
|
|
97
98
|
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
98
99
|
{ command: "details --task <id>", description: "Show full task info from the configured source." },
|
|
99
100
|
{ command: "reopen [--task <id> | --all] [--reason <text>]", description: "Reopen closed task(s) in the configured source." },
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type RigCliOutputEnvelope } from "@rig/contracts";
|
|
2
|
+
/**
|
|
3
|
+
* Build the versioned `{ v: 1, command, data }` envelope for a command
|
|
4
|
+
* outcome, or null when the command has no output schema (legacy payload)
|
|
5
|
+
* or the details fail validation (warned on stderr, legacy payload).
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildCliJsonEnvelope(outcome: unknown, options?: {
|
|
8
|
+
warn?: (message: string) => void;
|
|
9
|
+
}): RigCliOutputEnvelope | null;
|
|
10
|
+
/** Commands with a versioned --json envelope (for help/docs/tests). */
|
|
11
|
+
export declare function listSchematizedCliCommands(): string[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { WorkspaceTaskRecord } from "./_server-client";
|
|
2
|
+
export type OperatorSnapshot = {
|
|
3
|
+
readonly run: Record<string, unknown>;
|
|
4
|
+
readonly logs?: readonly Record<string, unknown>[];
|
|
5
|
+
readonly timeline?: readonly Record<string, unknown>[];
|
|
6
|
+
};
|
|
7
|
+
export declare function renderOperatorSnapshot(snapshot: OperatorSnapshot): string;
|
|
8
|
+
export type PiRunStreamRenderer = {
|
|
9
|
+
renderSnapshot(snapshot: OperatorSnapshot): void;
|
|
10
|
+
renderTimeline(entries: readonly Record<string, unknown>[]): void;
|
|
11
|
+
renderLogs(entries: readonly Record<string, unknown>[]): void;
|
|
12
|
+
};
|
|
13
|
+
export declare function createPiRunStreamRenderer(output?: Pick<NodeJS.WriteStream, "write">): PiRunStreamRenderer;
|
|
14
|
+
export type OperatorSurface = PiRunStreamRenderer & {
|
|
15
|
+
readonly mode: "text" | "pi-compatible-text";
|
|
16
|
+
info(message: string): void;
|
|
17
|
+
error(message: string): void;
|
|
18
|
+
attachCommandInput(handler: (line: string) => void | Promise<void>): {
|
|
19
|
+
close(): void;
|
|
20
|
+
} | null;
|
|
21
|
+
};
|
|
22
|
+
export declare function createOperatorSurface(options?: {
|
|
23
|
+
readonly input?: NodeJS.ReadStream;
|
|
24
|
+
readonly output?: Pick<NodeJS.WriteStream, "write"> & {
|
|
25
|
+
readonly isTTY?: boolean;
|
|
26
|
+
};
|
|
27
|
+
readonly errorOutput?: Pick<NodeJS.WriteStream, "write">;
|
|
28
|
+
readonly interactive?: boolean;
|
|
29
|
+
}): OperatorSurface;
|
|
30
|
+
export type TaskPickerRenderer = {
|
|
31
|
+
readonly writeLine: (line: string) => void;
|
|
32
|
+
};
|
|
33
|
+
export declare function renderTaskPickerRows(tasks: readonly WorkspaceTaskRecord[]): string[];
|
|
34
|
+
export declare function promptForTaskSelection(question: string): Promise<string>;
|