@h-rig/cli 0.0.6-alpha.82 → 0.0.6-alpha.84
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.js +40 -8
- package/dist/bin/rig.js +23402 -14577
- package/dist/src/app/board.js +217 -41
- package/dist/src/app-opentui/adapters/command.d.ts +2 -0
- package/dist/src/app-opentui/adapters/command.js +329 -0
- package/dist/src/app-opentui/adapters/common.js +2 -2
- package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
- package/dist/src/app-opentui/adapters/doctor.js +64 -39
- package/dist/src/app-opentui/adapters/family.d.ts +62 -0
- package/dist/src/app-opentui/adapters/family.js +14305 -0
- package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
- package/dist/src/app-opentui/adapters/fleet.js +90 -60
- package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
- package/dist/src/app-opentui/adapters/inbox.js +137 -78
- package/dist/src/app-opentui/adapters/init.d.ts +0 -2
- package/dist/src/app-opentui/adapters/init.js +85 -47
- package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
- package/dist/src/app-opentui/adapters/inspect.js +1024 -0
- package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
- package/dist/src/app-opentui/adapters/pi-attach.js +442 -125
- package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
- package/dist/src/app-opentui/adapters/pi.js +363 -0
- package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
- package/dist/src/app-opentui/adapters/plugin.js +544 -0
- package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
- package/dist/src/app-opentui/adapters/repo.js +186 -0
- package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
- package/dist/src/app-opentui/adapters/run-detail.js +180 -63
- package/dist/src/app-opentui/adapters/server.d.ts +10 -2
- package/dist/src/app-opentui/adapters/server.js +191 -45
- package/dist/src/app-opentui/adapters/tasks.d.ts +11 -2
- package/dist/src/app-opentui/adapters/tasks.js +1123 -143
- package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
- package/dist/src/app-opentui/adapters/workspace.js +333 -0
- package/dist/src/app-opentui/autocomplete.d.ts +20 -0
- package/dist/src/app-opentui/autocomplete.js +576 -0
- package/dist/src/app-opentui/bootstrap.d.ts +1 -6
- package/dist/src/app-opentui/bootstrap.js +25252 -16474
- package/dist/src/app-opentui/command-palette.d.ts +3 -0
- package/dist/src/app-opentui/command-palette.js +1010 -0
- package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
- package/dist/src/app-opentui/command-pty-host.js +248 -0
- package/dist/src/app-opentui/drone.js +8 -6
- package/dist/src/app-opentui/events.js +1 -1
- package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
- package/dist/src/app-opentui/fleet-stats.js +114 -0
- package/dist/src/app-opentui/focus-manager.d.ts +14 -0
- package/dist/src/app-opentui/focus-manager.js +24 -0
- package/dist/src/app-opentui/index.js +5431 -2797
- package/dist/src/app-opentui/intent.js +179 -50
- package/dist/src/app-opentui/keymap.d.ts +21 -0
- package/dist/src/app-opentui/keymap.js +1748 -0
- package/dist/src/app-opentui/launch-routing.d.ts +16 -0
- package/dist/src/app-opentui/launch-routing.js +55 -0
- package/dist/src/app-opentui/layout.d.ts +7 -0
- package/dist/src/app-opentui/layout.js +13 -6
- package/dist/src/app-opentui/list-search.d.ts +24 -0
- package/dist/src/app-opentui/list-search.js +88 -1
- package/dist/src/app-opentui/pi-host-child.js +99 -17
- package/dist/src/app-opentui/pi-pty-host.d.ts +14 -0
- package/dist/src/app-opentui/pi-pty-host.js +30 -14
- package/dist/src/app-opentui/react/App.d.ts +9 -0
- package/dist/src/app-opentui/react/App.js +5144 -0
- package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
- package/dist/src/app-opentui/react/Backdrop.js +1834 -0
- package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
- package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
- package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
- package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
- package/dist/src/app-opentui/react/context.d.ts +17 -0
- package/dist/src/app-opentui/react/context.js +37 -0
- package/dist/src/app-opentui/react/launch.d.ts +2 -0
- package/dist/src/app-opentui/react/launch.js +5743 -0
- package/dist/src/app-opentui/react/nav.d.ts +18 -0
- package/dist/src/app-opentui/react/nav.js +54 -0
- package/dist/src/app-opentui/react/scroll.d.ts +12 -0
- package/dist/src/app-opentui/react/scroll.js +21 -0
- package/dist/src/app-opentui/react/syntax.d.ts +2 -0
- package/dist/src/app-opentui/react/syntax.js +64 -0
- package/dist/src/app-opentui/registry.js +20428 -4828
- package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
- package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
- package/dist/src/app-opentui/render/constants.d.ts +31 -0
- package/dist/src/app-opentui/render/constants.js +66 -0
- package/dist/src/app-opentui/render/graphics.d.ts +2 -1
- package/dist/src/app-opentui/render/graphics.js +228 -46
- package/dist/src/app-opentui/render/image-visual-layer-worker.js +469 -930
- package/dist/src/app-opentui/render/image-visual-layer.d.ts +25 -10
- package/dist/src/app-opentui/render/image-visual-layer.js +448 -329
- package/dist/src/app-opentui/render/native-host.d.ts +37 -0
- package/dist/src/app-opentui/render/native-host.js +179 -0
- package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
- package/dist/src/app-opentui/render/panel-layout.js +48 -0
- package/dist/src/app-opentui/render/panels.d.ts +2 -0
- package/dist/src/app-opentui/render/panels.js +78 -38
- package/dist/src/app-opentui/render/preloader.d.ts +10 -0
- package/dist/src/app-opentui/render/preloader.js +165 -0
- package/dist/src/app-opentui/render/scene.d.ts +53 -1
- package/dist/src/app-opentui/render/scene.js +195 -6
- package/dist/src/app-opentui/render/text.d.ts +7 -1
- package/dist/src/app-opentui/render/text.js +15 -8
- package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
- package/dist/src/app-opentui/render/type-bar.js +113 -39
- package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
- package/dist/src/app-opentui/runtime-resources.js +62 -0
- package/dist/src/app-opentui/runtime.d.ts +44 -1
- package/dist/src/app-opentui/runtime.js +5415 -2738
- package/dist/src/app-opentui/scenes/command.d.ts +3 -0
- package/dist/src/app-opentui/scenes/command.js +117 -0
- package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
- package/dist/src/app-opentui/scenes/doctor.js +221 -17
- package/dist/src/app-opentui/scenes/error.js +60 -20
- package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
- package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
- package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
- package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
- package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
- package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
- package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
- package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
- package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
- package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
- package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
- package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
- package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
- package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
- package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
- package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
- package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
- package/dist/src/app-opentui/scenes/family.d.ts +3 -0
- package/dist/src/app-opentui/scenes/family.js +2144 -0
- package/dist/src/app-opentui/scenes/fleet.js +552 -43
- package/dist/src/app-opentui/scenes/handoff.js +342 -35
- package/dist/src/app-opentui/scenes/help.js +640 -56
- package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
- package/dist/src/app-opentui/scenes/inbox.js +329 -21
- package/dist/src/app-opentui/scenes/init.d.ts +2 -1
- package/dist/src/app-opentui/scenes/init.js +120 -34
- package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
- package/dist/src/app-opentui/scenes/inspect.js +793 -0
- package/dist/src/app-opentui/scenes/main.d.ts +2 -1
- package/dist/src/app-opentui/scenes/main.js +264 -29
- package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
- package/dist/src/app-opentui/scenes/pi.js +508 -0
- package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
- package/dist/src/app-opentui/scenes/plugin.js +486 -0
- package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
- package/dist/src/app-opentui/scenes/repo.js +424 -0
- package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
- package/dist/src/app-opentui/scenes/run-detail.js +362 -35
- package/dist/src/app-opentui/scenes/server.d.ts +2 -1
- package/dist/src/app-opentui/scenes/server.js +243 -26
- package/dist/src/app-opentui/scenes/tasks.js +518 -41
- package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
- package/dist/src/app-opentui/scenes/workspace.js +426 -0
- package/dist/src/app-opentui/selectable.d.ts +19 -0
- package/dist/src/app-opentui/selectable.js +79 -0
- package/dist/src/app-opentui/state.js +129 -36
- package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
- package/dist/src/app-opentui/surface-catalog.js +540 -0
- package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
- package/dist/src/app-opentui/terminal-capabilities.js +15 -0
- package/dist/src/app-opentui/theme.d.ts +28 -6
- package/dist/src/app-opentui/theme.js +61 -8
- package/dist/src/app-opentui/types.d.ts +130 -5
- package/dist/src/commands/_authority-runs.d.ts +1 -1
- package/dist/src/commands/_authority-runs.js +2 -12
- package/dist/src/commands/_doctor-checks.js +62 -13
- package/dist/src/commands/_help-catalog.js +95 -15
- package/dist/src/commands/_operator-view.js +97 -15
- package/dist/src/commands/_pi-frontend.d.ts +2 -0
- package/dist/src/commands/_pi-frontend.js +97 -13
- package/dist/src/commands/_preflight.js +64 -14
- package/dist/src/commands/_server-client.js +82 -18
- package/dist/src/commands/_server-events.d.ts +26 -0
- package/dist/src/commands/_server-events.js +310 -0
- package/dist/src/commands/_snapshot-upload.js +62 -13
- package/dist/src/commands/agent.js +2 -12
- package/dist/src/commands/connect.js +7 -1
- package/dist/src/commands/doctor.js +62 -13
- package/dist/src/commands/github.js +144 -23
- package/dist/src/commands/inbox.js +62 -13
- package/dist/src/commands/init.js +82 -18
- package/dist/src/commands/inspect.js +62 -13
- package/dist/src/commands/run.js +100 -15
- package/dist/src/commands/server.js +71 -26
- package/dist/src/commands/setup.js +62 -13
- package/dist/src/commands/stats.js +157 -28
- package/dist/src/commands/task-run-driver.js +64 -25
- package/dist/src/commands/task.js +196 -43
- package/dist/src/commands.js +419 -123
- package/dist/src/index.js +426 -130
- package/package.json +11 -10
- package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
- package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __require = import.meta.require;
|
|
3
|
+
|
|
4
|
+
// packages/cli/src/app-opentui/adapters/common.ts
|
|
5
|
+
function projectRootOf(ctx) {
|
|
6
|
+
const root = ctx.rig?.projectRoot ?? ctx.projectRoot ?? ctx.getState().projectRoot;
|
|
7
|
+
if (typeof root === "string" && root.trim())
|
|
8
|
+
return root;
|
|
9
|
+
throw new Error("App adapter requires a projectRoot.");
|
|
10
|
+
}
|
|
11
|
+
function normalizeAppError(error) {
|
|
12
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13
|
+
const rawHint = error instanceof Error ? error.hint : undefined;
|
|
14
|
+
return {
|
|
15
|
+
message,
|
|
16
|
+
...typeof rawHint === "string" && rawHint.trim() ? { hint: rawHint.trim() } : {}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function emitStarted(ctx, label, optimistic) {
|
|
20
|
+
ctx.emit({ type: "action.started", label, ...optimistic ? { optimistic } : {} });
|
|
21
|
+
}
|
|
22
|
+
function emitProgress(ctx, label, detail, data) {
|
|
23
|
+
ctx.emit({ type: "action.progress", label, ...detail ? { detail } : {}, ...data ? { data } : {} });
|
|
24
|
+
}
|
|
25
|
+
function emitCompleted(ctx, label, data) {
|
|
26
|
+
ctx.emit({ type: "action.completed", label, ...data ? { data } : {} });
|
|
27
|
+
}
|
|
28
|
+
function emitFailed(ctx, label, error, data) {
|
|
29
|
+
if (data)
|
|
30
|
+
patchData(ctx, data);
|
|
31
|
+
const normalized = normalizeAppError(error);
|
|
32
|
+
ctx.emit({
|
|
33
|
+
type: "action.failed",
|
|
34
|
+
label,
|
|
35
|
+
message: normalized.message,
|
|
36
|
+
...normalized.hint ? { hint: normalized.hint } : {},
|
|
37
|
+
cause: error
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function patchData(ctx, data) {
|
|
41
|
+
ctx.emit({ type: "data.patch", data });
|
|
42
|
+
}
|
|
43
|
+
function patchFooter(ctx, footer) {
|
|
44
|
+
ctx.emit({ type: "footer.patch", footer });
|
|
45
|
+
}
|
|
46
|
+
async function captureConsole(fn) {
|
|
47
|
+
const output = [];
|
|
48
|
+
const original = {
|
|
49
|
+
log: console.log,
|
|
50
|
+
info: console.info,
|
|
51
|
+
warn: console.warn,
|
|
52
|
+
error: console.error
|
|
53
|
+
};
|
|
54
|
+
const capture = (...parts) => {
|
|
55
|
+
output.push(parts.map((part) => typeof part === "string" ? part : JSON.stringify(part)).join(" "));
|
|
56
|
+
};
|
|
57
|
+
console.log = capture;
|
|
58
|
+
console.info = capture;
|
|
59
|
+
console.warn = capture;
|
|
60
|
+
console.error = capture;
|
|
61
|
+
try {
|
|
62
|
+
const result = await fn();
|
|
63
|
+
return { result, output };
|
|
64
|
+
} finally {
|
|
65
|
+
console.log = original.log;
|
|
66
|
+
console.info = original.info;
|
|
67
|
+
console.warn = original.warn;
|
|
68
|
+
console.error = original.error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// packages/cli/src/app-opentui/adapters/repo.ts
|
|
73
|
+
function repoActionRequest(ctx) {
|
|
74
|
+
const intent = ctx.getState().intent;
|
|
75
|
+
const payload = intent?.action?.payload;
|
|
76
|
+
if (!payload)
|
|
77
|
+
return { kind: "none" };
|
|
78
|
+
if (payload.repoReset === true)
|
|
79
|
+
return { kind: "reset" };
|
|
80
|
+
const alias = payload.repoSync;
|
|
81
|
+
if (typeof alias === "string" && alias.trim())
|
|
82
|
+
return { kind: "sync", alias: alias.trim() };
|
|
83
|
+
return { kind: "none" };
|
|
84
|
+
}
|
|
85
|
+
function readRepoGitStatus(projectRoot, checkoutRoot, pinnedCommit, runCapture, existsSync, joinPath) {
|
|
86
|
+
const unavailable = { available: false, clean: false, dirtyCount: 0, head: "", branch: "", ahead: 0, behind: 0 };
|
|
87
|
+
if (!checkoutRoot || !existsSync(joinPath(checkoutRoot, ".git")))
|
|
88
|
+
return unavailable;
|
|
89
|
+
const porcelain = runCapture(["git", "-C", checkoutRoot, "status", "--porcelain"], projectRoot);
|
|
90
|
+
if (porcelain.exitCode !== 0)
|
|
91
|
+
return unavailable;
|
|
92
|
+
const dirtyLines = porcelain.stdout.split(/\r?\n/).filter((row) => row.trim().length > 0);
|
|
93
|
+
const head = runCapture(["git", "-C", checkoutRoot, "rev-parse", "--short", "HEAD"], projectRoot).stdout.trim();
|
|
94
|
+
const branchRaw = runCapture(["git", "-C", checkoutRoot, "rev-parse", "--abbrev-ref", "HEAD"], projectRoot).stdout.trim();
|
|
95
|
+
let ahead = 0;
|
|
96
|
+
let behind = 0;
|
|
97
|
+
if (pinnedCommit) {
|
|
98
|
+
const counts = runCapture(["git", "-C", checkoutRoot, "rev-list", "--left-right", "--count", `${pinnedCommit}...HEAD`], projectRoot);
|
|
99
|
+
if (counts.exitCode === 0) {
|
|
100
|
+
const [behindStr = "0", aheadStr = "0"] = counts.stdout.trim().split(/\s+/);
|
|
101
|
+
behind = Number.parseInt(behindStr, 10) || 0;
|
|
102
|
+
ahead = Number.parseInt(aheadStr, 10) || 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
available: true,
|
|
107
|
+
clean: dirtyLines.length === 0,
|
|
108
|
+
dirtyCount: dirtyLines.length,
|
|
109
|
+
head,
|
|
110
|
+
branch: branchRaw && branchRaw !== "HEAD" ? branchRaw : "(detached)",
|
|
111
|
+
ahead,
|
|
112
|
+
behind
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async function refreshRepo(ctx) {
|
|
116
|
+
const request = repoActionRequest(ctx);
|
|
117
|
+
const label = request.kind === "sync" ? `Syncing ${request.alias}` : request.kind === "reset" ? "Resetting repo baseline" : "Loading repo state";
|
|
118
|
+
emitStarted(ctx, label);
|
|
119
|
+
try {
|
|
120
|
+
const projectRoot = projectRootOf(ctx);
|
|
121
|
+
const [
|
|
122
|
+
{ repoBaseline, resetBaseline },
|
|
123
|
+
{ currentTaskId },
|
|
124
|
+
{ listManagedRepoEntries, resolveManagedRepoIdByAlias },
|
|
125
|
+
{ syncManagedRepo, resolveManagedRepoLayoutByAlias },
|
|
126
|
+
{ runCapture },
|
|
127
|
+
{ existsSync },
|
|
128
|
+
pathMod
|
|
129
|
+
] = await Promise.all([
|
|
130
|
+
import("@rig/runtime/control-plane/native/repo-ops"),
|
|
131
|
+
import("@rig/runtime/control-plane/native/task-state"),
|
|
132
|
+
import("@rig/runtime/control-plane/repos/registry"),
|
|
133
|
+
import("@rig/runtime/control-plane/repos"),
|
|
134
|
+
import("@rig/runtime/control-plane/native/utils"),
|
|
135
|
+
import("fs"),
|
|
136
|
+
import("path")
|
|
137
|
+
]);
|
|
138
|
+
const joinPath = (...parts) => pathMod.resolve(...parts);
|
|
139
|
+
if (request.kind === "sync") {
|
|
140
|
+
const repoId = resolveManagedRepoIdByAlias(request.alias);
|
|
141
|
+
if (!repoId)
|
|
142
|
+
throw new Error(`No managed repo registered for alias ${request.alias}.`);
|
|
143
|
+
emitProgress(ctx, label, `re-syncing ${request.alias} from its remote default branch`);
|
|
144
|
+
await captureConsole(() => syncManagedRepo(projectRoot, repoId));
|
|
145
|
+
} else if (request.kind === "reset") {
|
|
146
|
+
emitProgress(ctx, label, "resetting baseline to origin/main and refreshing pins");
|
|
147
|
+
await captureConsole(() => resetBaseline(projectRoot, false));
|
|
148
|
+
}
|
|
149
|
+
emitProgress(ctx, label, "reading baseline pins and managed repos");
|
|
150
|
+
const { result } = await captureConsole(() => ({
|
|
151
|
+
pins: repoBaseline(projectRoot, false),
|
|
152
|
+
taskId: currentTaskId(projectRoot),
|
|
153
|
+
managed: listManagedRepoEntries()
|
|
154
|
+
}));
|
|
155
|
+
const baselinePins = Object.entries(result.pins).map(([alias, commit]) => ({ alias, commit: String(commit) }));
|
|
156
|
+
const pinByAlias = new Map(baselinePins.map((pin) => [pin.alias, pin.commit]));
|
|
157
|
+
const managedRepos = result.managed.map((entry) => {
|
|
158
|
+
const layout = resolveManagedRepoLayoutByAlias(projectRoot, entry.alias);
|
|
159
|
+
const git = layout ? readRepoGitStatus(projectRoot, layout.checkoutRoot, pinByAlias.get(entry.alias), runCapture, existsSync, joinPath) : undefined;
|
|
160
|
+
return {
|
|
161
|
+
id: entry.id,
|
|
162
|
+
alias: entry.alias,
|
|
163
|
+
defaultBranch: entry.defaultBranch,
|
|
164
|
+
defaultRemoteUrl: entry.defaultRemoteUrl,
|
|
165
|
+
...git ? { git } : {}
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
const snapshot = {
|
|
169
|
+
activeTaskId: result.taskId.trim() ? result.taskId.trim() : null,
|
|
170
|
+
baselinePins,
|
|
171
|
+
managedRepos,
|
|
172
|
+
flatLayout: managedRepos.length === 0,
|
|
173
|
+
refreshedAt: Date.now()
|
|
174
|
+
};
|
|
175
|
+
patchData(ctx, { repo: snapshot, lastRefreshError: undefined });
|
|
176
|
+
patchFooter(ctx, { message: snapshot.flatLayout ? "flat layout \xB7 no managed repos" : `${managedRepos.length} managed repos \xB7 ${baselinePins.length} pins` });
|
|
177
|
+
emitCompleted(ctx, label, { managed: managedRepos.length, pins: baselinePins.length, task: snapshot.activeTaskId });
|
|
178
|
+
return snapshot;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
emitFailed(ctx, label, error);
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export {
|
|
185
|
+
refreshRepo
|
|
186
|
+
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { AppAdapter } from "../types";
|
|
2
1
|
import { type AppAdapterContext } from "./common";
|
|
3
|
-
export declare function createRunDetailAdapter(): AppAdapter;
|
|
4
2
|
export type AppRunSnapshot = {
|
|
5
3
|
readonly runId: string;
|
|
6
4
|
readonly status: string;
|
|
@@ -9,10 +7,19 @@ export type AppRunSnapshot = {
|
|
|
9
7
|
readonly logs: Record<string, unknown>[];
|
|
10
8
|
readonly timeline: Record<string, unknown>[];
|
|
11
9
|
readonly timelineCursor: string | null;
|
|
10
|
+
/** Server-reported totals (when available) so the scene can show "N of M" and
|
|
11
|
+
* decide whether a "load more" affordance is warranted (#2). */
|
|
12
|
+
readonly logsTotal?: number;
|
|
13
|
+
readonly timelineTotal?: number;
|
|
12
14
|
};
|
|
13
15
|
export declare function loadRunDetail(ctx: AppAdapterContext, runId: string, options?: {
|
|
14
16
|
readonly timelineCursor?: string | null;
|
|
15
17
|
}): Promise<AppRunSnapshot>;
|
|
18
|
+
/** "Load more" for the timeline (#2): fetch the NEXT page using the stored
|
|
19
|
+
* `timelineCursor` and APPEND it to the existing snapshot, advancing the cursor.
|
|
20
|
+
* The previously-loaded rows stay; nothing is re-fetched. No cursor ⇒ nothing
|
|
21
|
+
* more to load (the scene only offers the affordance while a cursor exists). */
|
|
22
|
+
export declare function loadMoreRunTimeline(ctx: AppAdapterContext, runId: string): Promise<AppRunSnapshot | null>;
|
|
16
23
|
export declare function steerRunFromApp(ctx: AppAdapterContext, input: {
|
|
17
24
|
readonly runId: string;
|
|
18
25
|
readonly message: string;
|
|
@@ -192,17 +192,21 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
|
192
192
|
const scopedKey = resolve2(projectRoot ?? process.cwd());
|
|
193
193
|
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
194
194
|
}
|
|
195
|
-
function
|
|
195
|
+
function readRemoteAuthState(projectRoot) {
|
|
196
196
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
197
197
|
if (!existsSync2(path))
|
|
198
198
|
return null;
|
|
199
199
|
try {
|
|
200
200
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
201
|
-
return
|
|
201
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
202
202
|
} catch {
|
|
203
203
|
return null;
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
207
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
208
|
+
return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
|
|
209
|
+
}
|
|
206
210
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
207
211
|
const scopedKey = resolve2(projectRoot);
|
|
208
212
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
@@ -213,15 +217,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
|
|
|
213
217
|
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
214
218
|
}
|
|
215
219
|
function readStoredGitHubAuthToken(projectRoot) {
|
|
216
|
-
const
|
|
217
|
-
|
|
220
|
+
const parsed = readRemoteAuthState(projectRoot);
|
|
221
|
+
return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
|
|
222
|
+
}
|
|
223
|
+
function inferRemoteServerProjectRootFromAuthState(projectRoot) {
|
|
224
|
+
const repo = readRepoConnection(projectRoot);
|
|
225
|
+
const slug = repo?.project?.trim();
|
|
226
|
+
if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
|
|
218
227
|
return null;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
const auth = readRemoteAuthState(projectRoot);
|
|
229
|
+
const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
|
|
230
|
+
const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
|
|
231
|
+
if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
|
|
223
232
|
return null;
|
|
224
|
-
|
|
233
|
+
const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
|
|
234
|
+
if (!checkoutBaseDir)
|
|
235
|
+
return null;
|
|
236
|
+
const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
|
|
237
|
+
writeRepoServerProjectRoot(projectRoot, inferred);
|
|
238
|
+
return inferred;
|
|
225
239
|
}
|
|
226
240
|
function readLocalConnectionFallbackToken(projectRoot) {
|
|
227
241
|
return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
|
|
@@ -232,7 +246,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
232
246
|
if (selected?.connection.kind === "remote") {
|
|
233
247
|
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
234
248
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
235
|
-
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
249
|
+
const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
236
250
|
return {
|
|
237
251
|
baseUrl: selected.connection.baseUrl,
|
|
238
252
|
authToken,
|
|
@@ -261,7 +275,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
|
|
|
261
275
|
if (!slug)
|
|
262
276
|
return null;
|
|
263
277
|
try {
|
|
264
|
-
const
|
|
278
|
+
const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
|
|
279
|
+
if (authToken && queryAuthFallbackEnabled())
|
|
280
|
+
url.searchParams.set("rt", authToken);
|
|
281
|
+
const response = await fetch(url, {
|
|
265
282
|
headers: mergeHeaders(undefined, authToken)
|
|
266
283
|
});
|
|
267
284
|
if (!response.ok)
|
|
@@ -288,10 +305,23 @@ function appendTaskFilterParams(url, filters) {
|
|
|
288
305
|
if (filters.limit !== undefined)
|
|
289
306
|
url.searchParams.set("limit", String(filters.limit));
|
|
290
307
|
}
|
|
308
|
+
function mergeCookie(existing, name, value) {
|
|
309
|
+
const encoded = `${name}=${encodeURIComponent(value)}`;
|
|
310
|
+
if (!existing?.trim())
|
|
311
|
+
return encoded;
|
|
312
|
+
const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
|
|
313
|
+
return [...parts, encoded].join("; ");
|
|
314
|
+
}
|
|
315
|
+
function queryAuthFallbackEnabled(env = process.env) {
|
|
316
|
+
return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
|
|
317
|
+
}
|
|
291
318
|
function mergeHeaders(headers, authToken) {
|
|
292
319
|
const merged = new Headers(headers);
|
|
293
320
|
if (authToken) {
|
|
294
|
-
|
|
321
|
+
const bearer = `Bearer ${authToken}`;
|
|
322
|
+
merged.set("authorization", bearer);
|
|
323
|
+
merged.set("x-auth", bearer);
|
|
324
|
+
merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
|
|
295
325
|
}
|
|
296
326
|
return merged;
|
|
297
327
|
}
|
|
@@ -351,15 +381,34 @@ async function buildServerFailureContext(projectRoot, server) {
|
|
|
351
381
|
hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
|
|
352
382
|
};
|
|
353
383
|
}
|
|
384
|
+
function isLoopbackRemoteBaseUrl(baseUrl) {
|
|
385
|
+
try {
|
|
386
|
+
const host = new URL(baseUrl).hostname.toLowerCase();
|
|
387
|
+
return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
|
|
388
|
+
} catch {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function canUseRemoteWithoutProjectRoot(pathname) {
|
|
393
|
+
return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
|
|
394
|
+
}
|
|
354
395
|
async function requestServerJson(context, pathname, init = {}) {
|
|
355
396
|
const server = await ensureServerForCli(context.projectRoot);
|
|
397
|
+
const requestUrl = new URL(`${server.baseUrl}${pathname}`);
|
|
398
|
+
if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
|
|
399
|
+
const repo = readRepoConnection(context.projectRoot);
|
|
400
|
+
throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
|
|
401
|
+
}
|
|
356
402
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
357
403
|
if (server.serverProjectRoot)
|
|
358
404
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
405
|
+
if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
|
|
406
|
+
requestUrl.searchParams.set("rt", server.authToken);
|
|
407
|
+
}
|
|
359
408
|
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
360
409
|
let response;
|
|
361
410
|
try {
|
|
362
|
-
response = await fetch(
|
|
411
|
+
response = await fetch(requestUrl, {
|
|
363
412
|
...init,
|
|
364
413
|
headers
|
|
365
414
|
});
|
|
@@ -421,11 +470,26 @@ async function getGitHubAuthStatusViaServer(context) {
|
|
|
421
470
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
422
471
|
}
|
|
423
472
|
async function postGitHubTokenViaServer(context, token, options = {}) {
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
473
|
+
const server = await ensureServerForCli(context.projectRoot);
|
|
474
|
+
const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
|
|
475
|
+
reportServerPhase("POST /api/github/auth/token\u2026");
|
|
476
|
+
let response;
|
|
477
|
+
try {
|
|
478
|
+
response = await fetch(requestUrl, {
|
|
479
|
+
method: "POST",
|
|
480
|
+
headers: { "content-type": "application/json" },
|
|
481
|
+
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
|
|
482
|
+
});
|
|
483
|
+
} catch (error) {
|
|
484
|
+
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
485
|
+
throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
|
|
486
|
+
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
487
|
+
}
|
|
488
|
+
const payload = await response.json().catch(() => null);
|
|
489
|
+
if (!response.ok) {
|
|
490
|
+
const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
|
|
491
|
+
throw new CliError(`Rig server auth bootstrap failed (${response.status}): ${detail}`, 1, { hint: "Re-run `rig github auth import-gh`, or check the selected server with `rig server status`." });
|
|
492
|
+
}
|
|
429
493
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
430
494
|
}
|
|
431
495
|
async function prepareRemoteCheckoutViaServer(context, input) {
|
|
@@ -703,20 +767,11 @@ var init__server_client = __esm(() => {
|
|
|
703
767
|
});
|
|
704
768
|
|
|
705
769
|
// packages/cli/src/app-opentui/adapters/common.ts
|
|
706
|
-
function adapterContextFromRuntime(runtime, renderer) {
|
|
707
|
-
return {
|
|
708
|
-
projectRoot: runtime.getState().projectRoot,
|
|
709
|
-
renderer,
|
|
710
|
-
ensureRuntime: () => runtime.getRunnerContext(),
|
|
711
|
-
emit: (event) => runtime.emit(event),
|
|
712
|
-
getState: () => runtime.getState()
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
770
|
function projectRootOf(ctx) {
|
|
716
771
|
const root = ctx.rig?.projectRoot ?? ctx.projectRoot ?? ctx.getState().projectRoot;
|
|
717
772
|
if (typeof root === "string" && root.trim())
|
|
718
773
|
return root;
|
|
719
|
-
throw new Error("
|
|
774
|
+
throw new Error("App adapter requires a projectRoot.");
|
|
720
775
|
}
|
|
721
776
|
function normalizeAppError(error) {
|
|
722
777
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -774,33 +829,17 @@ function stringField(record, keys, fallback = "") {
|
|
|
774
829
|
}
|
|
775
830
|
return fallback;
|
|
776
831
|
}
|
|
777
|
-
function payloadString(intent, key) {
|
|
778
|
-
const value = intent.action.payload?.[key];
|
|
779
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
780
|
-
}
|
|
781
832
|
|
|
782
833
|
// packages/cli/src/app-opentui/adapters/run-detail.ts
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const message = payloadString(intent, "message") ?? intent.raw;
|
|
793
|
-
if (runId && message)
|
|
794
|
-
await steerRunFromApp(ctx, { runId, message });
|
|
795
|
-
return true;
|
|
796
|
-
}
|
|
797
|
-
if (runId) {
|
|
798
|
-
await loadRunDetail(ctx, runId);
|
|
799
|
-
return true;
|
|
800
|
-
}
|
|
801
|
-
return false;
|
|
802
|
-
}
|
|
803
|
-
};
|
|
834
|
+
var LOG_PAGE = 100;
|
|
835
|
+
var TIMELINE_PAGE = 200;
|
|
836
|
+
function payloadTotal(payload) {
|
|
837
|
+
for (const key of ["total", "totalCount", "count"]) {
|
|
838
|
+
const value = payload[key];
|
|
839
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
840
|
+
return value;
|
|
841
|
+
}
|
|
842
|
+
return;
|
|
804
843
|
}
|
|
805
844
|
function unwrapRun(payload) {
|
|
806
845
|
return payload.run && typeof payload.run === "object" && !Array.isArray(payload.run) ? payload.run : payload;
|
|
@@ -809,8 +848,24 @@ function nextCursor(payload) {
|
|
|
809
848
|
const cursor = payload.nextCursor ?? payload.cursor;
|
|
810
849
|
return typeof cursor === "string" && cursor.trim() ? cursor : null;
|
|
811
850
|
}
|
|
851
|
+
function loadMoreRequest(ctx, runId) {
|
|
852
|
+
const value = ctx.getState().data?.runDetailLoadMore;
|
|
853
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
854
|
+
return null;
|
|
855
|
+
const record = value;
|
|
856
|
+
if (record.runId !== runId || typeof record.cursor !== "string" || !record.cursor.trim())
|
|
857
|
+
return null;
|
|
858
|
+
return { runId, cursor: record.cursor };
|
|
859
|
+
}
|
|
812
860
|
async function loadRunDetail(ctx, runId, options = {}) {
|
|
813
861
|
const cleanRunId = runId.trim();
|
|
862
|
+
const more = loadMoreRequest(ctx, cleanRunId);
|
|
863
|
+
if (more) {
|
|
864
|
+
patchData(ctx, { runDetailLoadMore: undefined });
|
|
865
|
+
const appended = await loadMoreRunTimeline(ctx, cleanRunId).catch(() => null);
|
|
866
|
+
if (appended)
|
|
867
|
+
return appended;
|
|
868
|
+
}
|
|
814
869
|
const label = `Loading run ${cleanRunId.slice(0, 8)}`;
|
|
815
870
|
if (!cleanRunId) {
|
|
816
871
|
const error = new Error("Run detail requires a run id.");
|
|
@@ -824,10 +879,12 @@ async function loadRunDetail(ctx, runId, options = {}) {
|
|
|
824
879
|
emitProgress(ctx, label, "loading run, logs, and timeline");
|
|
825
880
|
const [runPayload, logsPayload, timelinePayload] = await Promise.all([
|
|
826
881
|
getRunDetailsViaServer2(context, cleanRunId),
|
|
827
|
-
getRunLogsViaServer2(context, cleanRunId, { limit:
|
|
828
|
-
getRunTimelineViaServer2(context, cleanRunId, { limit:
|
|
882
|
+
getRunLogsViaServer2(context, cleanRunId, { limit: LOG_PAGE }),
|
|
883
|
+
getRunTimelineViaServer2(context, cleanRunId, { limit: TIMELINE_PAGE, ...options.timelineCursor ? { cursor: options.timelineCursor } : {} })
|
|
829
884
|
]);
|
|
830
885
|
const run = unwrapRun(runPayload);
|
|
886
|
+
const logsTotal = payloadTotal(logsPayload);
|
|
887
|
+
const timelineTotal = payloadTotal(timelinePayload);
|
|
831
888
|
const snapshot = {
|
|
832
889
|
runId: cleanRunId,
|
|
833
890
|
status: stringField(run, ["status", "state"], "unknown"),
|
|
@@ -835,9 +892,12 @@ async function loadRunDetail(ctx, runId, options = {}) {
|
|
|
835
892
|
run,
|
|
836
893
|
logs: arrayFromPayload(logsPayload),
|
|
837
894
|
timeline: arrayFromPayload(timelinePayload),
|
|
838
|
-
timelineCursor: nextCursor(timelinePayload)
|
|
895
|
+
timelineCursor: nextCursor(timelinePayload),
|
|
896
|
+
...logsTotal !== undefined ? { logsTotal } : {},
|
|
897
|
+
...timelineTotal !== undefined ? { timelineTotal } : {}
|
|
839
898
|
};
|
|
840
|
-
|
|
899
|
+
const clearSettledSteer = settledSteerForRun(ctx, cleanRunId) ? { pendingRunMessage: undefined } : {};
|
|
900
|
+
patchData(ctx, { selectedRunId: cleanRunId, runDetail: snapshot, lastRefreshError: undefined, ...clearSettledSteer });
|
|
841
901
|
patchFooter(ctx, { run: `${cleanRunId.slice(0, 8)} ${snapshot.status}` });
|
|
842
902
|
emitCompleted(ctx, label, { runId: cleanRunId, status: snapshot.status, logs: snapshot.logs.length, timeline: snapshot.timeline.length });
|
|
843
903
|
return snapshot;
|
|
@@ -846,6 +906,56 @@ async function loadRunDetail(ctx, runId, options = {}) {
|
|
|
846
906
|
throw error;
|
|
847
907
|
}
|
|
848
908
|
}
|
|
909
|
+
function settledSteerForRun(ctx, runId) {
|
|
910
|
+
const value = ctx.getState().data?.pendingRunMessage;
|
|
911
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
912
|
+
return false;
|
|
913
|
+
const record = value;
|
|
914
|
+
if (record.runId !== runId)
|
|
915
|
+
return false;
|
|
916
|
+
return record.status === "sent" || record.status === "delivered" || record.status === "failed";
|
|
917
|
+
}
|
|
918
|
+
function currentSnapshot(ctx) {
|
|
919
|
+
const value = ctx.getState().data?.runDetail;
|
|
920
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
921
|
+
}
|
|
922
|
+
async function loadMoreRunTimeline(ctx, runId) {
|
|
923
|
+
const cleanRunId = runId.trim();
|
|
924
|
+
const snapshot = currentSnapshot(ctx);
|
|
925
|
+
if (!snapshot || snapshot.runId !== cleanRunId || !snapshot.timelineCursor)
|
|
926
|
+
return snapshot;
|
|
927
|
+
const label = `More timeline ${cleanRunId.slice(0, 8)}`;
|
|
928
|
+
emitStarted(ctx, label);
|
|
929
|
+
try {
|
|
930
|
+
const { getRunTimelineViaServer: getRunTimelineViaServer2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
931
|
+
const context = { projectRoot: projectRootOf(ctx) };
|
|
932
|
+
const page = await getRunTimelineViaServer2(context, cleanRunId, { limit: TIMELINE_PAGE, cursor: snapshot.timelineCursor });
|
|
933
|
+
const more = arrayFromPayload(page);
|
|
934
|
+
const timelineTotal = payloadTotal(page) ?? snapshot.timelineTotal;
|
|
935
|
+
const next = {
|
|
936
|
+
...snapshot,
|
|
937
|
+
timeline: [...snapshot.timeline, ...more],
|
|
938
|
+
timelineCursor: nextCursor(page),
|
|
939
|
+
...timelineTotal !== undefined ? { timelineTotal } : {}
|
|
940
|
+
};
|
|
941
|
+
patchData(ctx, { runDetail: next, lastRefreshError: undefined });
|
|
942
|
+
emitCompleted(ctx, label, { runId: cleanRunId, added: more.length, timeline: next.timeline.length });
|
|
943
|
+
return next;
|
|
944
|
+
} catch (error) {
|
|
945
|
+
emitFailed(ctx, label, error, { runId: cleanRunId });
|
|
946
|
+
throw error;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
function steerResultSummary(result) {
|
|
950
|
+
for (const key of ["status", "state", "message", "detail"]) {
|
|
951
|
+
const value = result[key];
|
|
952
|
+
if (typeof value === "string" && value.trim())
|
|
953
|
+
return value.trim();
|
|
954
|
+
}
|
|
955
|
+
if (result.ok === true || result.queued === true || result.delivered === true)
|
|
956
|
+
return "accepted by run";
|
|
957
|
+
return "delivered";
|
|
958
|
+
}
|
|
849
959
|
async function steerRunFromApp(ctx, input) {
|
|
850
960
|
const label = `Steering ${input.runId.slice(0, 8)}`;
|
|
851
961
|
const message = input.message.trim();
|
|
@@ -854,17 +964,21 @@ async function steerRunFromApp(ctx, input) {
|
|
|
854
964
|
emitFailed(ctx, label, error, { runId: input.runId });
|
|
855
965
|
throw error;
|
|
856
966
|
}
|
|
857
|
-
|
|
858
|
-
|
|
967
|
+
const pending = { runId: input.runId, text: message, status: "queued" };
|
|
968
|
+
emitStarted(ctx, label, { pendingRunMessage: pending });
|
|
969
|
+
patchData(ctx, { pendingRunMessage: pending });
|
|
859
970
|
try {
|
|
860
971
|
const { sendRunPiPromptViaServer: sendRunPiPromptViaServer2, steerRunViaServer: steerRunViaServer2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
861
972
|
const context = { projectRoot: projectRootOf(ctx) };
|
|
862
973
|
const result = await sendRunPiPromptViaServer2(context, input.runId, message, "steer").catch(() => steerRunViaServer2(context, input.runId, message));
|
|
974
|
+
const summary = steerResultSummary(result);
|
|
975
|
+
patchData(ctx, { pendingRunMessage: { runId: input.runId, text: message, status: "sent", result: summary } });
|
|
863
976
|
emitCompleted(ctx, label, { runId: input.runId, result });
|
|
864
|
-
patchData(ctx, { pendingRunMessage: null });
|
|
865
977
|
return result;
|
|
866
978
|
} catch (error) {
|
|
867
|
-
|
|
979
|
+
const message2 = normalizeAppError(error).message;
|
|
980
|
+
emitFailed(ctx, label, error, { runId: input.runId });
|
|
981
|
+
patchData(ctx, { pendingRunMessage: { runId: input.runId, text: message, status: "failed", result: message2 } });
|
|
868
982
|
throw error;
|
|
869
983
|
}
|
|
870
984
|
}
|
|
@@ -878,7 +992,10 @@ async function stopRunFromDetail(ctx, runId) {
|
|
|
878
992
|
const { stopRunViaServer: stopRunViaServer2 } = await Promise.resolve().then(() => (init__server_client(), exports__server_client));
|
|
879
993
|
const result = await stopRunViaServer2({ projectRoot: projectRootOf(ctx) }, cleanRunId);
|
|
880
994
|
emitCompleted(ctx, label, { runId: cleanRunId, result });
|
|
881
|
-
await loadRunDetail(ctx, cleanRunId).catch(() =>
|
|
995
|
+
await loadRunDetail(ctx, cleanRunId).catch((error) => {
|
|
996
|
+
patchData(ctx, { lastRefreshError: normalizeAppError(error).message });
|
|
997
|
+
return null;
|
|
998
|
+
});
|
|
882
999
|
return result;
|
|
883
1000
|
} catch (error) {
|
|
884
1001
|
emitFailed(ctx, label, error, { runId: cleanRunId, revert: { status: "unknown" } });
|
|
@@ -889,5 +1006,5 @@ export {
|
|
|
889
1006
|
stopRunFromDetail,
|
|
890
1007
|
steerRunFromApp,
|
|
891
1008
|
loadRunDetail,
|
|
892
|
-
|
|
1009
|
+
loadMoreRunTimeline
|
|
893
1010
|
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { AppAdapter } from "../types";
|
|
2
1
|
import { type AppAdapterContext } from "./common";
|
|
3
|
-
export declare function createServerAdapter(): AppAdapter;
|
|
4
2
|
export type AppServerState = {
|
|
5
3
|
readonly label: string;
|
|
6
4
|
readonly baseUrl?: string;
|
|
@@ -11,4 +9,14 @@ export type AppServerState = {
|
|
|
11
9
|
readonly auth?: Record<string, unknown>;
|
|
12
10
|
readonly error?: string;
|
|
13
11
|
};
|
|
12
|
+
/** Start the local Rig server DETACHED and return to the server scene (bug #3).
|
|
13
|
+
*
|
|
14
|
+
* `rig server start` is a blocking long-running process; running it through the
|
|
15
|
+
* foreground command PTY traps the operator (kitty-mode even swallows ctrl-c).
|
|
16
|
+
* Instead we: (a) switch this repo's connection to local, (b) spawn the server
|
|
17
|
+
* detached + wait for ready via ensureLocalRigServerConnection (it writes the
|
|
18
|
+
* published server state and unrefs the child), then (c) re-probe. The operator
|
|
19
|
+
* is never blocked: this returns once the detached server answers.
|
|
20
|
+
*/
|
|
21
|
+
export declare function startLocalServerFromApp(ctx: AppAdapterContext): Promise<AppServerState>;
|
|
14
22
|
export declare function refreshServerStatus(ctx: AppAdapterContext): Promise<AppServerState>;
|