@h-rig/cli 0.0.6-alpha.89 → 0.0.6-alpha.90
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 +8 -40
- package/dist/bin/rig.js +12519 -26675
- package/dist/src/app/board.js +74 -693
- package/dist/src/app/drone-ui.js +1 -1
- package/dist/src/app/theme.js +0 -1
- package/dist/src/commands/_async-ui.js +1 -1
- package/dist/src/commands/_authority-runs.d.ts +1 -1
- package/dist/src/commands/_authority-runs.js +12 -2
- package/dist/src/commands/_cli-format.d.ts +1 -10
- package/dist/src/commands/_cli-format.js +2 -5
- package/dist/src/commands/_connection-state.d.ts +1 -11
- package/dist/src/commands/_connection-state.js +5 -50
- package/dist/src/commands/_doctor-checks.js +40 -501
- package/dist/src/commands/_help-catalog.js +17 -99
- package/dist/src/commands/_json-output.js +0 -4
- package/dist/src/commands/_operator-view.js +54 -575
- package/dist/src/commands/_pi-frontend.d.ts +0 -27
- package/dist/src/commands/_pi-frontend.js +52 -576
- package/dist/src/commands/_preflight.js +66 -553
- package/dist/src/commands/_server-client.d.ts +0 -33
- package/dist/src/commands/_server-client.js +46 -541
- package/dist/src/commands/_snapshot-upload.js +42 -503
- package/dist/src/commands/_spinner.js +1 -1
- package/dist/src/commands/agent.js +12 -2
- package/dist/src/commands/browser.js +1 -1
- package/dist/src/commands/connect.js +15 -626
- package/dist/src/commands/doctor.js +41 -502
- package/dist/src/commands/github.js +51 -584
- package/dist/src/commands/inbox.js +41 -502
- package/dist/src/commands/init.js +74 -561
- package/dist/src/commands/inspect.js +41 -502
- package/dist/src/commands/run.js +54 -578
- package/dist/src/commands/server.js +163 -692
- package/dist/src/commands/setup.js +46 -507
- package/dist/src/commands/stats.js +58 -601
- package/dist/src/commands/task-run-driver.js +58 -509
- package/dist/src/commands/task.js +110 -729
- package/dist/src/commands.js +237 -1112
- package/dist/src/index.js +244 -1123
- package/dist/src/launcher.js +0 -4
- package/package.json +9 -13
- package/dist/src/app-opentui/adapters/command.d.ts +0 -2
- package/dist/src/app-opentui/adapters/command.js +0 -329
- package/dist/src/app-opentui/adapters/common.d.ts +0 -56
- package/dist/src/app-opentui/adapters/common.js +0 -153
- package/dist/src/app-opentui/adapters/doctor.d.ts +0 -9
- package/dist/src/app-opentui/adapters/doctor.js +0 -1217
- package/dist/src/app-opentui/adapters/family.d.ts +0 -62
- package/dist/src/app-opentui/adapters/family.js +0 -14855
- package/dist/src/app-opentui/adapters/fleet.d.ts +0 -14
- package/dist/src/app-opentui/adapters/fleet.js +0 -1335
- package/dist/src/app-opentui/adapters/inbox.d.ts +0 -43
- package/dist/src/app-opentui/adapters/inbox.js +0 -1944
- package/dist/src/app-opentui/adapters/init.d.ts +0 -11
- package/dist/src/app-opentui/adapters/init.js +0 -2818
- package/dist/src/app-opentui/adapters/inspect.d.ts +0 -52
- package/dist/src/app-opentui/adapters/inspect.js +0 -1455
- package/dist/src/app-opentui/adapters/pi-attach.d.ts +0 -32
- package/dist/src/app-opentui/adapters/pi-attach.js +0 -2101
- package/dist/src/app-opentui/adapters/pi.d.ts +0 -23
- package/dist/src/app-opentui/adapters/pi.js +0 -363
- package/dist/src/app-opentui/adapters/plugin.d.ts +0 -84
- package/dist/src/app-opentui/adapters/plugin.js +0 -544
- package/dist/src/app-opentui/adapters/repo.d.ts +0 -37
- package/dist/src/app-opentui/adapters/repo.js +0 -186
- package/dist/src/app-opentui/adapters/run-detail.d.ts +0 -27
- package/dist/src/app-opentui/adapters/run-detail.js +0 -1441
- package/dist/src/app-opentui/adapters/server.d.ts +0 -48
- package/dist/src/app-opentui/adapters/server.js +0 -1561
- package/dist/src/app-opentui/adapters/tasks.d.ts +0 -64
- package/dist/src/app-opentui/adapters/tasks.js +0 -4524
- package/dist/src/app-opentui/adapters/workspace.d.ts +0 -49
- package/dist/src/app-opentui/adapters/workspace.js +0 -333
- package/dist/src/app-opentui/autocomplete.d.ts +0 -20
- package/dist/src/app-opentui/autocomplete.js +0 -578
- package/dist/src/app-opentui/bootstrap.d.ts +0 -11
- package/dist/src/app-opentui/bootstrap.js +0 -27833
- package/dist/src/app-opentui/command-palette.d.ts +0 -3
- package/dist/src/app-opentui/command-palette.js +0 -1038
- package/dist/src/app-opentui/command-pty-host.d.ts +0 -62
- package/dist/src/app-opentui/command-pty-host.js +0 -248
- package/dist/src/app-opentui/drone.d.ts +0 -12
- package/dist/src/app-opentui/drone.js +0 -230
- package/dist/src/app-opentui/events.d.ts +0 -7
- package/dist/src/app-opentui/events.js +0 -28
- package/dist/src/app-opentui/fleet-stats.d.ts +0 -32
- package/dist/src/app-opentui/fleet-stats.js +0 -114
- package/dist/src/app-opentui/focus-manager.d.ts +0 -14
- package/dist/src/app-opentui/focus-manager.js +0 -24
- package/dist/src/app-opentui/index.d.ts +0 -8
- package/dist/src/app-opentui/index.js +0 -5260
- package/dist/src/app-opentui/intent.d.ts +0 -3
- package/dist/src/app-opentui/intent.js +0 -365
- package/dist/src/app-opentui/keymap.d.ts +0 -21
- package/dist/src/app-opentui/keymap.js +0 -1377
- package/dist/src/app-opentui/launch-routing.d.ts +0 -16
- package/dist/src/app-opentui/launch-routing.js +0 -55
- package/dist/src/app-opentui/layout.d.ts +0 -22
- package/dist/src/app-opentui/layout.js +0 -51
- package/dist/src/app-opentui/list-search.d.ts +0 -36
- package/dist/src/app-opentui/list-search.js +0 -130
- package/dist/src/app-opentui/pi-host-child.d.ts +0 -2
- package/dist/src/app-opentui/pi-host-child.js +0 -1299
- package/dist/src/app-opentui/pi-pty-host.d.ts +0 -28
- package/dist/src/app-opentui/pi-pty-host.js +0 -10
- package/dist/src/app-opentui/react/App.d.ts +0 -9
- package/dist/src/app-opentui/react/App.js +0 -3866
- package/dist/src/app-opentui/react/Backdrop.d.ts +0 -5
- package/dist/src/app-opentui/react/Backdrop.js +0 -823
- package/dist/src/app-opentui/react/ChromeHost.d.ts +0 -5
- package/dist/src/app-opentui/react/ChromeHost.js +0 -1539
- package/dist/src/app-opentui/react/SceneFrameView.d.ts +0 -7
- package/dist/src/app-opentui/react/SceneFrameView.js +0 -579
- package/dist/src/app-opentui/react/context.d.ts +0 -17
- package/dist/src/app-opentui/react/context.js +0 -37
- package/dist/src/app-opentui/react/launch.d.ts +0 -2
- package/dist/src/app-opentui/react/launch.js +0 -4897
- package/dist/src/app-opentui/react/nav.d.ts +0 -18
- package/dist/src/app-opentui/react/nav.js +0 -54
- package/dist/src/app-opentui/react/scroll.d.ts +0 -12
- package/dist/src/app-opentui/react/scroll.js +0 -21
- package/dist/src/app-opentui/react/syntax.d.ts +0 -2
- package/dist/src/app-opentui/react/syntax.js +0 -65
- package/dist/src/app-opentui/registry.d.ts +0 -4
- package/dist/src/app-opentui/registry.js +0 -22876
- package/dist/src/app-opentui/remote-link.d.ts +0 -10
- package/dist/src/app-opentui/remote-link.js +0 -47
- package/dist/src/app-opentui/render/ascii-fleet.d.ts +0 -15
- package/dist/src/app-opentui/render/ascii-fleet.js +0 -82
- package/dist/src/app-opentui/render/constants.d.ts +0 -30
- package/dist/src/app-opentui/render/constants.js +0 -64
- package/dist/src/app-opentui/render/graphics.d.ts +0 -40
- package/dist/src/app-opentui/render/graphics.js +0 -713
- package/dist/src/app-opentui/render/hover.d.ts +0 -11
- package/dist/src/app-opentui/render/hover.js +0 -34
- package/dist/src/app-opentui/render/native-host.d.ts +0 -37
- package/dist/src/app-opentui/render/native-host.js +0 -180
- package/dist/src/app-opentui/render/panel-layout.d.ts +0 -38
- package/dist/src/app-opentui/render/panel-layout.js +0 -48
- package/dist/src/app-opentui/render/panels.d.ts +0 -12
- package/dist/src/app-opentui/render/panels.js +0 -288
- package/dist/src/app-opentui/render/preloader.d.ts +0 -10
- package/dist/src/app-opentui/render/preloader.js +0 -166
- package/dist/src/app-opentui/render/scene.d.ts +0 -68
- package/dist/src/app-opentui/render/scene.js +0 -300
- package/dist/src/app-opentui/render/terminal-handoff.d.ts +0 -16
- package/dist/src/app-opentui/render/terminal-handoff.js +0 -14
- package/dist/src/app-opentui/render/text.d.ts +0 -29
- package/dist/src/app-opentui/render/text.js +0 -177
- package/dist/src/app-opentui/render/type-bar.d.ts +0 -15
- package/dist/src/app-opentui/render/type-bar.js +0 -212
- package/dist/src/app-opentui/runtime-resources.d.ts +0 -16
- package/dist/src/app-opentui/runtime-resources.js +0 -62
- package/dist/src/app-opentui/runtime.d.ts +0 -45
- package/dist/src/app-opentui/runtime.js +0 -5232
- package/dist/src/app-opentui/scenes/command.d.ts +0 -3
- package/dist/src/app-opentui/scenes/command.js +0 -118
- package/dist/src/app-opentui/scenes/doctor.d.ts +0 -3
- package/dist/src/app-opentui/scenes/doctor.js +0 -296
- package/dist/src/app-opentui/scenes/error.d.ts +0 -2
- package/dist/src/app-opentui/scenes/error.js +0 -277
- package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/agent.js +0 -349
- package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/browser.js +0 -196
- package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/dist.js +0 -244
- package/dist/src/app-opentui/scenes/family-domains/git.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/git.js +0 -196
- package/dist/src/app-opentui/scenes/family-domains/github.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/github.js +0 -275
- package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/harness.js +0 -153
- package/dist/src/app-opentui/scenes/family-domains/index.d.ts +0 -4
- package/dist/src/app-opentui/scenes/family-domains/index.js +0 -1680
- package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +0 -76
- package/dist/src/app-opentui/scenes/family-domains/kit.js +0 -306
- package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/profile.js +0 -213
- package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/queue.js +0 -147
- package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/remote.js +0 -519
- package/dist/src/app-opentui/scenes/family-domains/review.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/review.js +0 -281
- package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/setup.js +0 -268
- package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +0 -2
- package/dist/src/app-opentui/scenes/family-domains/stats.js +0 -371
- package/dist/src/app-opentui/scenes/family.d.ts +0 -3
- package/dist/src/app-opentui/scenes/family.js +0 -2199
- package/dist/src/app-opentui/scenes/fleet.d.ts +0 -3
- package/dist/src/app-opentui/scenes/fleet.js +0 -766
- package/dist/src/app-opentui/scenes/handoff.d.ts +0 -2
- package/dist/src/app-opentui/scenes/handoff.js +0 -455
- package/dist/src/app-opentui/scenes/help.d.ts +0 -3
- package/dist/src/app-opentui/scenes/help.js +0 -725
- package/dist/src/app-opentui/scenes/inbox.d.ts +0 -3
- package/dist/src/app-opentui/scenes/inbox.js +0 -427
- package/dist/src/app-opentui/scenes/init.d.ts +0 -3
- package/dist/src/app-opentui/scenes/init.js +0 -181
- package/dist/src/app-opentui/scenes/inspect.d.ts +0 -3
- package/dist/src/app-opentui/scenes/inspect.js +0 -794
- package/dist/src/app-opentui/scenes/main.d.ts +0 -3
- package/dist/src/app-opentui/scenes/main.js +0 -332
- package/dist/src/app-opentui/scenes/pi.d.ts +0 -3
- package/dist/src/app-opentui/scenes/pi.js +0 -509
- package/dist/src/app-opentui/scenes/plugin.d.ts +0 -3
- package/dist/src/app-opentui/scenes/plugin.js +0 -487
- package/dist/src/app-opentui/scenes/repo.d.ts +0 -3
- package/dist/src/app-opentui/scenes/repo.js +0 -425
- package/dist/src/app-opentui/scenes/run-detail.d.ts +0 -3
- package/dist/src/app-opentui/scenes/run-detail.js +0 -467
- package/dist/src/app-opentui/scenes/server.d.ts +0 -3
- package/dist/src/app-opentui/scenes/server.js +0 -378
- package/dist/src/app-opentui/scenes/tasks.d.ts +0 -3
- package/dist/src/app-opentui/scenes/tasks.js +0 -768
- package/dist/src/app-opentui/scenes/workspace.d.ts +0 -3
- package/dist/src/app-opentui/scenes/workspace.js +0 -427
- package/dist/src/app-opentui/selectable.d.ts +0 -19
- package/dist/src/app-opentui/selectable.js +0 -80
- package/dist/src/app-opentui/state.d.ts +0 -4
- package/dist/src/app-opentui/state.js +0 -399
- package/dist/src/app-opentui/surface-catalog.d.ts +0 -20
- package/dist/src/app-opentui/surface-catalog.js +0 -542
- package/dist/src/app-opentui/theme.d.ts +0 -59
- package/dist/src/app-opentui/theme.js +0 -142
- package/dist/src/app-opentui/types.d.ts +0 -313
- package/dist/src/app-opentui/types.js +0 -1
- package/dist/src/commands/_server-events.d.ts +0 -26
- package/dist/src/commands/_server-events.js +0 -715
|
@@ -1,768 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// packages/cli/src/app-opentui/theme.ts
|
|
3
|
-
import {
|
|
4
|
-
bold as otuiBold,
|
|
5
|
-
dim as otuiDim,
|
|
6
|
-
fg as otuiFg,
|
|
7
|
-
t,
|
|
8
|
-
TextAttributes
|
|
9
|
-
} from "@opentui/core";
|
|
10
|
-
var RIG_UI = {
|
|
11
|
-
bg: "#070809",
|
|
12
|
-
bg2: "#0b0c0e",
|
|
13
|
-
panel: "#101115",
|
|
14
|
-
panel2: "#14161b",
|
|
15
|
-
hover: "#181b24",
|
|
16
|
-
glass: "#1e2230",
|
|
17
|
-
border: "#2a2e3a",
|
|
18
|
-
ink: "#f4f5f8",
|
|
19
|
-
ink2: "#c7c9d3",
|
|
20
|
-
ink3: "#9aa0ae",
|
|
21
|
-
ink4: "#787b86",
|
|
22
|
-
lime: "#ccff4d",
|
|
23
|
-
limeDim: "#a9d63f",
|
|
24
|
-
cyan: "#56d8ff",
|
|
25
|
-
cyanDim: "#3f9fbd",
|
|
26
|
-
red: "#ff5d5d",
|
|
27
|
-
yellow: "#ffd24d",
|
|
28
|
-
magenta: "#ff79b0"
|
|
29
|
-
};
|
|
30
|
-
var styles = {
|
|
31
|
-
ink: otuiFg(RIG_UI.ink),
|
|
32
|
-
ink2: otuiFg(RIG_UI.ink2),
|
|
33
|
-
ink3: otuiFg(RIG_UI.ink3),
|
|
34
|
-
ink4: otuiFg(RIG_UI.ink4),
|
|
35
|
-
lime: otuiFg(RIG_UI.lime),
|
|
36
|
-
limeDim: otuiFg(RIG_UI.limeDim),
|
|
37
|
-
cyan: otuiFg(RIG_UI.cyan),
|
|
38
|
-
red: otuiFg(RIG_UI.red),
|
|
39
|
-
yellow: otuiFg(RIG_UI.yellow),
|
|
40
|
-
magenta: otuiFg(RIG_UI.magenta)
|
|
41
|
-
};
|
|
42
|
-
function statusColor(status) {
|
|
43
|
-
switch (status) {
|
|
44
|
-
case "success":
|
|
45
|
-
case "completed":
|
|
46
|
-
case "merged":
|
|
47
|
-
return RIG_UI.lime;
|
|
48
|
-
case "running":
|
|
49
|
-
case "preparing":
|
|
50
|
-
case "created":
|
|
51
|
-
case "validating":
|
|
52
|
-
case "reviewing":
|
|
53
|
-
case "closing-out":
|
|
54
|
-
case "stopping":
|
|
55
|
-
case "loading":
|
|
56
|
-
case "action":
|
|
57
|
-
return RIG_UI.cyan;
|
|
58
|
-
case "needs-attention":
|
|
59
|
-
case "needs_attention":
|
|
60
|
-
return RIG_UI.yellow;
|
|
61
|
-
case "failed":
|
|
62
|
-
case "error":
|
|
63
|
-
return RIG_UI.red;
|
|
64
|
-
default:
|
|
65
|
-
return RIG_UI.ink3;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function statusGlyph(status) {
|
|
69
|
-
switch (status) {
|
|
70
|
-
case "success":
|
|
71
|
-
case "completed":
|
|
72
|
-
case "merged":
|
|
73
|
-
return "\u2713";
|
|
74
|
-
case "running":
|
|
75
|
-
return "\u25CF";
|
|
76
|
-
case "preparing":
|
|
77
|
-
case "created":
|
|
78
|
-
case "validating":
|
|
79
|
-
case "reviewing":
|
|
80
|
-
case "closing-out":
|
|
81
|
-
case "stopping":
|
|
82
|
-
case "loading":
|
|
83
|
-
case "action":
|
|
84
|
-
return "\u25D0";
|
|
85
|
-
case "needs-attention":
|
|
86
|
-
case "needs_attention":
|
|
87
|
-
return "\u26A0";
|
|
88
|
-
case "failed":
|
|
89
|
-
case "error":
|
|
90
|
-
return "\u2717";
|
|
91
|
-
default:
|
|
92
|
-
return "\xB7";
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
function noColorActive() {
|
|
96
|
-
const noColor = process.env.NO_COLOR;
|
|
97
|
-
if (noColor !== undefined && noColor !== "") {
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
return process.env.RIG_NO_COLOR !== undefined;
|
|
101
|
-
}
|
|
102
|
-
function statusLabel(status) {
|
|
103
|
-
return {
|
|
104
|
-
glyph: statusGlyph(status),
|
|
105
|
-
color: noColorActive() ? RIG_UI.ink : statusColor(status)
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// packages/cli/src/app-opentui/drone.ts
|
|
110
|
-
import { RGBA, StyledText, TextAttributes as TextAttributes2 } from "@opentui/core";
|
|
111
|
-
var MINI_DRONE = [
|
|
112
|
-
"(!!!) (!!!)",
|
|
113
|
-
" \\%==%/ ",
|
|
114
|
-
" %%?%% ",
|
|
115
|
-
" /%==%\\ ",
|
|
116
|
-
"(!!!) (!!!)"
|
|
117
|
-
];
|
|
118
|
-
var LEAD_MARK = [
|
|
119
|
-
" .-=-. ",
|
|
120
|
-
"=%%?%%=",
|
|
121
|
-
" '-=-' "
|
|
122
|
-
];
|
|
123
|
-
var BLADE_FRAMES = ["---", "\\\\\\", "|||", "///"];
|
|
124
|
-
var EYE_FRAMES = ["o", "@", "\u2022", "."];
|
|
125
|
-
var COLOR = {
|
|
126
|
-
body: RGBA.fromHex(RIG_UI.lime),
|
|
127
|
-
mini: RGBA.fromHex(RIG_UI.limeDim),
|
|
128
|
-
rotor: RGBA.fromHex(RIG_UI.cyan),
|
|
129
|
-
path: RGBA.fromHex(RIG_UI.cyan),
|
|
130
|
-
eye: RGBA.fromHex(RIG_UI.ink),
|
|
131
|
-
dim: RGBA.fromHex(RIG_UI.ink4),
|
|
132
|
-
ink: RGBA.fromHex(RIG_UI.ink2)
|
|
133
|
-
};
|
|
134
|
-
function bladeForTick(tick, phase = 0) {
|
|
135
|
-
return BLADE_FRAMES[(Math.floor(tick / 3) + phase) % BLADE_FRAMES.length];
|
|
136
|
-
}
|
|
137
|
-
function eyeForTick(tick, phase = 0) {
|
|
138
|
-
const pulse = Math.sin(tick * 0.09 + phase);
|
|
139
|
-
return pulse > 0.55 ? EYE_FRAMES[1] : pulse > 0.1 ? EYE_FRAMES[0] : pulse > -0.45 ? EYE_FRAMES[2] : EYE_FRAMES[3];
|
|
140
|
-
}
|
|
141
|
-
function chunk(text, fg, bold = false, dim = false) {
|
|
142
|
-
let attributes = TextAttributes2.NONE;
|
|
143
|
-
if (bold)
|
|
144
|
-
attributes |= TextAttributes2.BOLD;
|
|
145
|
-
if (dim)
|
|
146
|
-
attributes |= TextAttributes2.DIM;
|
|
147
|
-
return { __isChunk: true, text, fg, ...attributes !== TextAttributes2.NONE ? { attributes } : {} };
|
|
148
|
-
}
|
|
149
|
-
function styledLine(text, colorFor) {
|
|
150
|
-
const chunks = [];
|
|
151
|
-
let run = "";
|
|
152
|
-
let runColor = null;
|
|
153
|
-
const flush = () => {
|
|
154
|
-
if (!run || !runColor)
|
|
155
|
-
return;
|
|
156
|
-
chunks.push(chunk(run, COLOR[runColor], runColor === "body" || runColor === "eye", runColor === "dim"));
|
|
157
|
-
run = "";
|
|
158
|
-
};
|
|
159
|
-
for (const char of text) {
|
|
160
|
-
const next = colorFor(char);
|
|
161
|
-
if (next !== runColor) {
|
|
162
|
-
flush();
|
|
163
|
-
runColor = next;
|
|
164
|
-
}
|
|
165
|
-
run += char;
|
|
166
|
-
}
|
|
167
|
-
flush();
|
|
168
|
-
return new StyledText(chunks.length > 0 ? chunks : [chunk("", COLOR.ink)]);
|
|
169
|
-
}
|
|
170
|
-
function droneColor(char) {
|
|
171
|
-
if (char === "?" || char === "o" || char === "@" || char === "\u2022")
|
|
172
|
-
return "eye";
|
|
173
|
-
if (char === "%" || char === "=")
|
|
174
|
-
return "mini";
|
|
175
|
-
if (char === "$")
|
|
176
|
-
return "body";
|
|
177
|
-
if (char === "(" || char === ")" || char === "/" || char === "\\" || char === "|" || char === "-")
|
|
178
|
-
return "rotor";
|
|
179
|
-
if (char === "\xB7" || char === "\u2022" || char === "'" || char === ".")
|
|
180
|
-
return "path";
|
|
181
|
-
if (char.trim() === "")
|
|
182
|
-
return "dim";
|
|
183
|
-
return "ink";
|
|
184
|
-
}
|
|
185
|
-
function motionColor(char) {
|
|
186
|
-
if (char === "\u25CF" || char === "\u25C6" || char === "\u25C9")
|
|
187
|
-
return "body";
|
|
188
|
-
if (char === "\u2022" || char === "\xB7" || char === "\u2500" || char === "\u2502" || char === "\u2571" || char === "\u2572" || char === "\u256D" || char === "\u256E" || char === "\u2570" || char === "\u256F")
|
|
189
|
-
return "path";
|
|
190
|
-
if (char === "\u258C" || char === "\u2590" || char === "\u2581" || char === "\u2594")
|
|
191
|
-
return "mini";
|
|
192
|
-
return droneColor(char);
|
|
193
|
-
}
|
|
194
|
-
function materializeDrone(lines, tick, phase = 0) {
|
|
195
|
-
const blade = bladeForTick(tick, phase);
|
|
196
|
-
const eye = eyeForTick(tick, phase);
|
|
197
|
-
return lines.map((line) => line.replaceAll("!!!", blade).replaceAll("?", eye));
|
|
198
|
-
}
|
|
199
|
-
function miniDroneLines(tick, align = "left", phase = 0) {
|
|
200
|
-
return materializeDrone(MINI_DRONE, tick, phase).map((text) => ({
|
|
201
|
-
text,
|
|
202
|
-
styledText: styledLine(text, droneColor),
|
|
203
|
-
fg: RIG_UI.limeDim,
|
|
204
|
-
align
|
|
205
|
-
}));
|
|
206
|
-
}
|
|
207
|
-
function brandFleetLines(tick, align = "center") {
|
|
208
|
-
const left = materializeDrone(MINI_DRONE, tick, 0);
|
|
209
|
-
const right = materializeDrone(MINI_DRONE, tick, 2);
|
|
210
|
-
const lead = materializeDrone(LEAD_MARK, tick, 1);
|
|
211
|
-
const packet = ["\xB7", "\u2022", "\u25CF", "\u2022"][Math.floor(tick / 2) % 4];
|
|
212
|
-
const bridge = [
|
|
213
|
-
` ${left[0]} ${lead[0]} ${right[0]}`,
|
|
214
|
-
` ${left[1]} \xB7\u2500\u2500${packet}\u2500\u2500\xB7 ${lead[1]} \xB7\u2500\u2500${packet}\u2500\u2500\xB7 ${right[1]}`,
|
|
215
|
-
` ${left[2]} \xB7' '${lead[2]}' '\xB7 ${right[2]}`,
|
|
216
|
-
` ${left[3]} \u2572 signal bus \u2571 ${right[3]}`,
|
|
217
|
-
` ${left[4]} \xB7\u2500\u2500\u2500${packet}\u2500\u2500\u2500\u2500\u2500\u2500${packet}\u2500\u2500\u2500\xB7 ${right[4]}`
|
|
218
|
-
];
|
|
219
|
-
return bridge.map((text) => ({
|
|
220
|
-
text,
|
|
221
|
-
styledText: styledLine(text, motionColor),
|
|
222
|
-
fg: RIG_UI.limeDim,
|
|
223
|
-
align
|
|
224
|
-
}));
|
|
225
|
-
}
|
|
226
|
-
function actionDrone(tick, phase = 0) {
|
|
227
|
-
const blade = bladeForTick(tick, phase);
|
|
228
|
-
const eye = eyeForTick(tick, phase);
|
|
229
|
-
return `(${blade})\u2572${eye}\u2571(${blade})`;
|
|
230
|
-
}
|
|
231
|
-
function actionDroneLine(tick, text, fg = RIG_UI.ink2) {
|
|
232
|
-
const prefix = actionDrone(tick);
|
|
233
|
-
const content = `${prefix} ${text}`;
|
|
234
|
-
return { text: content, styledText: styledLine(content, motionColor), fg, align: "center" };
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// packages/cli/src/app-opentui/render/scene.ts
|
|
238
|
-
function line(text, options = {}) {
|
|
239
|
-
return { text, ...options };
|
|
240
|
-
}
|
|
241
|
-
function blank() {
|
|
242
|
-
return { text: "" };
|
|
243
|
-
}
|
|
244
|
-
function deckRow(input) {
|
|
245
|
-
const prefix = input.active ? "\u25B8" : " ";
|
|
246
|
-
const label = input.label.toUpperCase().padEnd(10);
|
|
247
|
-
return line(`${prefix} ${label} ${input.detail}`, {
|
|
248
|
-
fg: input.active ? RIG_UI.lime : RIG_UI.ink2,
|
|
249
|
-
bold: input.active,
|
|
250
|
-
selectableIndex: input.index,
|
|
251
|
-
activateOnClick: input.activateOnClick
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
function loadingRows(label, tick = 0, compact = false) {
|
|
255
|
-
const mascot = compact ? miniDroneLines(tick, "center") : brandFleetLines(tick, "center");
|
|
256
|
-
return [
|
|
257
|
-
blank(),
|
|
258
|
-
...mascot,
|
|
259
|
-
blank(),
|
|
260
|
-
{ ...actionDroneLine(tick, `loading ${label}\u2026`, RIG_UI.cyan), align: "center" }
|
|
261
|
-
];
|
|
262
|
-
}
|
|
263
|
-
function errorBanner(message, hint) {
|
|
264
|
-
return [
|
|
265
|
-
line(`\u2717 failed to load \u2014 ${message}`, { fg: RIG_UI.red, bold: true }),
|
|
266
|
-
...hint ? [line(` ${hint}`, { fg: RIG_UI.ink3 })] : [],
|
|
267
|
-
line(" select refresh/retry below", { fg: RIG_UI.ink4 }),
|
|
268
|
-
line("", { fg: RIG_UI.ink3 })
|
|
269
|
-
];
|
|
270
|
-
}
|
|
271
|
-
function lastRefreshError(state) {
|
|
272
|
-
const value = state.data.lastRefreshError;
|
|
273
|
-
return typeof value === "string" && value.trim() ? value : undefined;
|
|
274
|
-
}
|
|
275
|
-
function makeSceneFrame(input) {
|
|
276
|
-
return input;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// packages/cli/src/app-opentui/selectable.ts
|
|
280
|
-
function selectableDeckRow(deck, item) {
|
|
281
|
-
return { ...deckRow({ ...deck, activateOnClick: true }), selectable: item };
|
|
282
|
-
}
|
|
283
|
-
function withSelectable(line2, item) {
|
|
284
|
-
return { ...line2, selectable: item, activateOnClick: true };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// packages/cli/src/app-opentui/list-search.ts
|
|
288
|
-
function listSearchQuery(_state) {
|
|
289
|
-
return "";
|
|
290
|
-
}
|
|
291
|
-
function valueText(value) {
|
|
292
|
-
if (value === undefined || value === null)
|
|
293
|
-
return "";
|
|
294
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
295
|
-
return String(value);
|
|
296
|
-
if (Array.isArray(value))
|
|
297
|
-
return value.map(valueText).join(" ");
|
|
298
|
-
if (typeof value === "object") {
|
|
299
|
-
const record = value;
|
|
300
|
-
return ["id", "runId", "taskId", "number", "title", "name", "summary", "status", "state", "label", "labels", "assignee", "assignees", "url"].map((key) => valueText(record[key])).join(" ");
|
|
301
|
-
}
|
|
302
|
-
return "";
|
|
303
|
-
}
|
|
304
|
-
function includesQuery(haystack, query) {
|
|
305
|
-
const needle = query.trim().toLowerCase();
|
|
306
|
-
if (!needle)
|
|
307
|
-
return true;
|
|
308
|
-
return haystack.map(valueText).join(" ").toLowerCase().includes(needle);
|
|
309
|
-
}
|
|
310
|
-
function filterTasksForSearch(tasks, query) {
|
|
311
|
-
return query.trim() ? tasks.filter((task) => includesQuery([task.id, task.status, task.title, task.priority, task.labels, task.assignees, task.raw], query)) : [...tasks];
|
|
312
|
-
}
|
|
313
|
-
function searchSummary(kind, query, visible, total) {
|
|
314
|
-
return query.trim() ? `search ${JSON.stringify(query)} \xB7 ${visible}/${total} ${kind}` : `${total} ${kind}`;
|
|
315
|
-
}
|
|
316
|
-
function taskSortSpec(value) {
|
|
317
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
318
|
-
return null;
|
|
319
|
-
const record = value;
|
|
320
|
-
const key = record.key;
|
|
321
|
-
const dir = record.dir;
|
|
322
|
-
if ((key === "status" || key === "id" || key === "priority" || key === "assignee" || key === "title") && (dir === "asc" || dir === "desc")) {
|
|
323
|
-
return { key, dir };
|
|
324
|
-
}
|
|
325
|
-
return null;
|
|
326
|
-
}
|
|
327
|
-
function cycleTaskSort(current, key) {
|
|
328
|
-
if (!current || current.key !== key)
|
|
329
|
-
return { key, dir: "asc" };
|
|
330
|
-
if (current.dir === "asc")
|
|
331
|
-
return { key, dir: "desc" };
|
|
332
|
-
return null;
|
|
333
|
-
}
|
|
334
|
-
function applyDir(rows, compare, dir) {
|
|
335
|
-
const sorted = [...rows].sort(compare);
|
|
336
|
-
return dir === "desc" ? sorted.reverse() : sorted;
|
|
337
|
-
}
|
|
338
|
-
function sortTasks(tasks, spec) {
|
|
339
|
-
if (!spec)
|
|
340
|
-
return [...tasks];
|
|
341
|
-
const { key, dir } = spec;
|
|
342
|
-
const compare = (a, b) => {
|
|
343
|
-
if (key === "status")
|
|
344
|
-
return a.status.localeCompare(b.status) || a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
345
|
-
if (key === "priority") {
|
|
346
|
-
const left = a.priority ?? Number.NEGATIVE_INFINITY;
|
|
347
|
-
const right = b.priority ?? Number.NEGATIVE_INFINITY;
|
|
348
|
-
return right - left || a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
349
|
-
}
|
|
350
|
-
if (key === "assignee")
|
|
351
|
-
return (a.assignees[0] ?? "").localeCompare(b.assignees[0] ?? "") || a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
352
|
-
if (key === "title")
|
|
353
|
-
return a.title.localeCompare(b.title, undefined, { sensitivity: "base" }) || a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
354
|
-
return a.id.localeCompare(b.id, undefined, { numeric: true });
|
|
355
|
-
};
|
|
356
|
-
return applyDir(tasks, compare, dir);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// packages/cli/src/app-opentui/remote-link.ts
|
|
360
|
-
var REPAIRABLE_REMOTE_LINK_STATUSES = new Set([
|
|
361
|
-
"auth_required",
|
|
362
|
-
"project_not_registered",
|
|
363
|
-
"no_server_checkout",
|
|
364
|
-
"invalid_root",
|
|
365
|
-
"needs_prepare",
|
|
366
|
-
"error"
|
|
367
|
-
]);
|
|
368
|
-
function remoteProjectLinkError(message) {
|
|
369
|
-
return /no server-host project root link|remote project(?:-root)? link|x-rig-project-root|serverProjectRoot/i.test(message ?? "");
|
|
370
|
-
}
|
|
371
|
-
function serverRecordForRemoteLink(state) {
|
|
372
|
-
const server = state.data.server;
|
|
373
|
-
return server && typeof server === "object" && !Array.isArray(server) ? server : null;
|
|
374
|
-
}
|
|
375
|
-
function remoteProjectLinkState(state) {
|
|
376
|
-
const serverRecord = serverRecordForRemoteLink(state);
|
|
377
|
-
if (!serverRecord || serverRecord.kind !== "remote")
|
|
378
|
-
return null;
|
|
379
|
-
const link = serverRecord.remoteProjectLink;
|
|
380
|
-
if (link && typeof link === "object" && !Array.isArray(link))
|
|
381
|
-
return link;
|
|
382
|
-
const direct = state.data.remoteProjectLink;
|
|
383
|
-
if (direct && typeof direct === "object" && !Array.isArray(direct))
|
|
384
|
-
return direct;
|
|
385
|
-
return null;
|
|
386
|
-
}
|
|
387
|
-
function shouldOfferRemoteLinkRepair(state, message) {
|
|
388
|
-
const link = remoteProjectLinkState(state);
|
|
389
|
-
if (link) {
|
|
390
|
-
if (link.ok === true)
|
|
391
|
-
return false;
|
|
392
|
-
const status = link.status ?? "";
|
|
393
|
-
return REPAIRABLE_REMOTE_LINK_STATUSES.has(status);
|
|
394
|
-
}
|
|
395
|
-
const serverRecord = serverRecordForRemoteLink(state);
|
|
396
|
-
if (serverRecord && serverRecord.kind !== "remote")
|
|
397
|
-
return false;
|
|
398
|
-
return remoteProjectLinkError(message ?? state.error?.message);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// packages/cli/src/app-opentui/scenes/tasks.ts
|
|
402
|
-
var BASE_TASK_RECOVERY_ITEMS = [
|
|
403
|
-
{ id: "refresh", label: "refresh", intent: { scene: "tasks", argv: ["tasks"], action: { kind: "refresh", label: "Refresh tasks" } }, message: "refresh task source" },
|
|
404
|
-
{ id: "next", label: "next", intent: { scene: "tasks", argv: ["task", "run", "--next"], action: { kind: "task-run-next", label: "Dispatch next task" } }, message: "dispatch next runnable task" },
|
|
405
|
-
{ id: "server", label: "server", intent: { scene: "server", argv: ["server", "status"], action: { kind: "refresh", label: "Open server controls" } }, message: "server controls" },
|
|
406
|
-
{ id: "doctor", label: "doctor", intent: { scene: "doctor", argv: ["doctor"], action: { kind: "doctor-run", label: "Run doctor" } }, message: "diagnose task source" }
|
|
407
|
-
];
|
|
408
|
-
var TASK_REPAIR_LINK_ITEM = { id: "repair-link", label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "tasks" } } }, message: "backfill or prepare remote project link" };
|
|
409
|
-
var COL = {
|
|
410
|
-
glyph: 1,
|
|
411
|
-
id: 11,
|
|
412
|
-
status: 12,
|
|
413
|
-
priority: 5,
|
|
414
|
-
assignee: 12
|
|
415
|
-
};
|
|
416
|
-
var GUTTER = " ";
|
|
417
|
-
var TASK_COLUMNS = [
|
|
418
|
-
{ key: "status", label: "status", hint: "by task state" },
|
|
419
|
-
{ key: "id", label: "task-id", hint: "by id" },
|
|
420
|
-
{ key: "priority", label: "priority", hint: "by priority" },
|
|
421
|
-
{ key: "assignee", label: "assignee", hint: "by assignee" },
|
|
422
|
-
{ key: "title", label: "title", hint: "by title" }
|
|
423
|
-
];
|
|
424
|
-
function taskSelectableItem(task) {
|
|
425
|
-
const taskId = task.id?.trim();
|
|
426
|
-
if (!taskId)
|
|
427
|
-
return null;
|
|
428
|
-
const title = (task.title || "task").trim() || "task";
|
|
429
|
-
const activeRunId = task.activeRun?.runId?.trim();
|
|
430
|
-
return {
|
|
431
|
-
id: taskId,
|
|
432
|
-
label: title,
|
|
433
|
-
data: { taskDetailId: taskId, selectedTaskId: taskId, ...activeRunId ? { selectedRunId: activeRunId } : {} },
|
|
434
|
-
intent: { scene: "tasks", argv: ["tasks", taskId], action: { kind: "refresh", label: `Open ${title}`, payload: { taskDetailId: taskId } } },
|
|
435
|
-
message: `open ${title} detail`
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
function taskView(state) {
|
|
439
|
-
const tasks = state.data.tasks;
|
|
440
|
-
return tasks && typeof tasks === "object" && !Array.isArray(tasks) ? tasks : null;
|
|
441
|
-
}
|
|
442
|
-
function taskRecords(state) {
|
|
443
|
-
const records = taskView(state)?.records;
|
|
444
|
-
return Array.isArray(records) ? records : [];
|
|
445
|
-
}
|
|
446
|
-
function dispatchingFor(state) {
|
|
447
|
-
const value = state.data.dispatchingRun;
|
|
448
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
449
|
-
return null;
|
|
450
|
-
const record = value;
|
|
451
|
-
if (typeof record.taskId !== "string" || !record.taskId.trim())
|
|
452
|
-
return null;
|
|
453
|
-
return { taskId: record.taskId, status: typeof record.status === "string" ? record.status : "dispatching" };
|
|
454
|
-
}
|
|
455
|
-
function updatedAgoLabel(state) {
|
|
456
|
-
const refreshedAt = taskView(state)?.refreshedAt;
|
|
457
|
-
if (typeof refreshedAt !== "string")
|
|
458
|
-
return;
|
|
459
|
-
const parsed = Date.parse(refreshedAt);
|
|
460
|
-
if (!Number.isFinite(parsed))
|
|
461
|
-
return;
|
|
462
|
-
const seconds = Math.max(0, Math.round((Date.now() - parsed) / 1000));
|
|
463
|
-
if (seconds < 1)
|
|
464
|
-
return "updated just now";
|
|
465
|
-
if (seconds < 60)
|
|
466
|
-
return `updated ${seconds}s ago`;
|
|
467
|
-
const minutes = Math.round(seconds / 60);
|
|
468
|
-
if (minutes < 60)
|
|
469
|
-
return `updated ${minutes}m ago`;
|
|
470
|
-
return `updated ${Math.round(minutes / 60)}h ago`;
|
|
471
|
-
}
|
|
472
|
-
function panelWidth(layout) {
|
|
473
|
-
return layout?.centerWidth ?? 100;
|
|
474
|
-
}
|
|
475
|
-
function panelHeight(layout, top = 3) {
|
|
476
|
-
return Math.max(4, (layout?.centerHeight ?? 24) - top);
|
|
477
|
-
}
|
|
478
|
-
function clip(value, width) {
|
|
479
|
-
if (width <= 0)
|
|
480
|
-
return "";
|
|
481
|
-
return value.length <= width ? value : `${value.slice(0, Math.max(0, width - 1))}\u2026`;
|
|
482
|
-
}
|
|
483
|
-
function cell(value, width) {
|
|
484
|
-
return clip(value, width).padEnd(width);
|
|
485
|
-
}
|
|
486
|
-
function formatAssignee(value) {
|
|
487
|
-
return value.startsWith("@") ? value : `@${value}`;
|
|
488
|
-
}
|
|
489
|
-
function assigneeCell(task) {
|
|
490
|
-
const first = task.assignees[0];
|
|
491
|
-
return first ? formatAssignee(first) : "\u2014";
|
|
492
|
-
}
|
|
493
|
-
function priorityCell(task) {
|
|
494
|
-
return task.priority === undefined ? "\u2014" : `P${String(task.priority).slice(0, 3)}`;
|
|
495
|
-
}
|
|
496
|
-
function taskViewLabel(view) {
|
|
497
|
-
const filters = view?.filters && typeof view.filters === "object" && !Array.isArray(view.filters) ? view.filters : {};
|
|
498
|
-
const filter = typeof filters.preset === "string" && filters.preset !== "custom" ? filters.preset : [
|
|
499
|
-
typeof filters.state === "string" ? `state:${filters.state}` : null,
|
|
500
|
-
typeof filters.status === "string" ? `status:${filters.status}` : null,
|
|
501
|
-
typeof filters.assignee === "string" ? formatAssignee(filters.assignee) : null,
|
|
502
|
-
typeof filters.label === "string" ? `label:${filters.label}` : null,
|
|
503
|
-
typeof filters.search === "string" ? `search:${filters.search}` : null
|
|
504
|
-
].filter(Boolean).join(" ") || "open";
|
|
505
|
-
const sort = typeof view?.sort === "string" ? view.sort : "priority";
|
|
506
|
-
const visible = typeof view?.visibleCount === "number" ? view.visibleCount : undefined;
|
|
507
|
-
const total = typeof view?.totalCount === "number" ? view.totalCount : undefined;
|
|
508
|
-
const count = visible !== undefined && total !== undefined ? `${visible}/${total}` : "syncing";
|
|
509
|
-
return `filter ${filter} \xB7 sort ${sort} \xB7 ${count}`;
|
|
510
|
-
}
|
|
511
|
-
function sortArrow(spec, key) {
|
|
512
|
-
if (!spec || spec.key !== key)
|
|
513
|
-
return "";
|
|
514
|
-
return spec.dir === "asc" ? "\u25B2" : "\u25BC";
|
|
515
|
-
}
|
|
516
|
-
function headerRow(spec) {
|
|
517
|
-
const text = [
|
|
518
|
-
" ",
|
|
519
|
-
cell(`task-id${sortArrow(spec, "id")}`, COL.id),
|
|
520
|
-
cell(`status${sortArrow(spec, "status")}`, COL.status),
|
|
521
|
-
cell(`prio${sortArrow(spec, "priority")}`, COL.priority),
|
|
522
|
-
cell(`assignee${sortArrow(spec, "assignee")}`, COL.assignee),
|
|
523
|
-
`title${sortArrow(spec, "title")}`
|
|
524
|
-
].join(GUTTER);
|
|
525
|
-
return line(text, { fg: RIG_UI.ink, bold: true, bg: RIG_UI.glass });
|
|
526
|
-
}
|
|
527
|
-
function sortToggleRow(column, current) {
|
|
528
|
-
const arrow = sortArrow(current, column.key);
|
|
529
|
-
const active = current?.key === column.key;
|
|
530
|
-
const next = cycleTaskSort(current, column.key);
|
|
531
|
-
const marker = active ? "\u25B8" : " ";
|
|
532
|
-
const label = `${column.label}${arrow ? ` ${arrow}` : ""}`.padEnd(12);
|
|
533
|
-
const row = line(`${marker} ${label} ${column.hint}`, {
|
|
534
|
-
fg: active ? RIG_UI.lime : RIG_UI.ink2,
|
|
535
|
-
bold: active
|
|
536
|
-
});
|
|
537
|
-
return withSelectable(row, {
|
|
538
|
-
id: `task-sort-${column.key}`,
|
|
539
|
-
label: `sort by ${column.label}`,
|
|
540
|
-
data: { taskSort: next },
|
|
541
|
-
message: `sort tasks ${next ? `${column.label} ${next.dir}` : "default"}`
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
function sortStrip(spec) {
|
|
545
|
-
return [
|
|
546
|
-
line("SORT", { fg: RIG_UI.ink3, bold: true }),
|
|
547
|
-
...TASK_COLUMNS.map((column) => sortToggleRow(column, spec)),
|
|
548
|
-
line("", { fg: RIG_UI.ink3 })
|
|
549
|
-
];
|
|
550
|
-
}
|
|
551
|
-
function taskRow(width, task, active, optimistic) {
|
|
552
|
-
const effectiveStatus = optimistic ?? task.status;
|
|
553
|
-
const { glyph } = statusLabel(effectiveStatus);
|
|
554
|
-
const marker = active ? "\u258C" : " ";
|
|
555
|
-
const status = effectiveStatus.replace(/[_-]/g, " ");
|
|
556
|
-
const fixed = `${marker} ${glyph}${GUTTER}${cell(task.id, COL.id)}${GUTTER}${cell(status, COL.status)}${GUTTER}${cell(priorityCell(task), COL.priority)}${GUTTER}${cell(assigneeCell(task), COL.assignee)}${GUTTER}`;
|
|
557
|
-
const activeRun = task.activeRun;
|
|
558
|
-
const activeSuffix = activeRun ? ` \xB7 attach ${activeRun.runId.slice(0, 8)}${activeRun.status ? ` ${activeRun.status}` : ""}` : "";
|
|
559
|
-
const titleWidth = Math.max(8, width - fixed.length - 2);
|
|
560
|
-
const row = line(`${fixed}${clip(`${task.title}${activeSuffix}`, titleWidth)}`, {
|
|
561
|
-
fg: active ? RIG_UI.ink : RIG_UI.ink2,
|
|
562
|
-
bold: active,
|
|
563
|
-
...active ? { bg: RIG_UI.glass } : {}
|
|
564
|
-
});
|
|
565
|
-
const item = taskSelectableItem(task);
|
|
566
|
-
return item ? withSelectable(row, item) : row;
|
|
567
|
-
}
|
|
568
|
-
var BASE_RECOVERY_DECKS = [
|
|
569
|
-
{ label: "refresh", detail: "reload task source" },
|
|
570
|
-
{ label: "next", detail: "dispatch next runnable task" },
|
|
571
|
-
{ label: "server", detail: "open server controls" },
|
|
572
|
-
{ label: "doctor", detail: "diagnose task source" }
|
|
573
|
-
];
|
|
574
|
-
function taskRecoveryItems(state) {
|
|
575
|
-
if (!shouldOfferRemoteLinkRepair(state))
|
|
576
|
-
return BASE_TASK_RECOVERY_ITEMS;
|
|
577
|
-
return [BASE_TASK_RECOVERY_ITEMS[0], BASE_TASK_RECOVERY_ITEMS[1], TASK_REPAIR_LINK_ITEM, ...BASE_TASK_RECOVERY_ITEMS.slice(2)];
|
|
578
|
-
}
|
|
579
|
-
function taskRecoveryDecks(state) {
|
|
580
|
-
if (!shouldOfferRemoteLinkRepair(state))
|
|
581
|
-
return BASE_RECOVERY_DECKS;
|
|
582
|
-
return [BASE_RECOVERY_DECKS[0], BASE_RECOVERY_DECKS[1], { label: "repair link", detail: "backfill/prepare remote project-root link" }, ...BASE_RECOVERY_DECKS.slice(2)];
|
|
583
|
-
}
|
|
584
|
-
function recoveryRows(state, selected, reason) {
|
|
585
|
-
const items = taskRecoveryItems(state);
|
|
586
|
-
return [
|
|
587
|
-
...reason ? [line(reason, { fg: RIG_UI.yellow }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
588
|
-
line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
|
|
589
|
-
...taskRecoveryDecks(state).map((deck, index) => selectableDeckRow({ ...deck, index, active: selected === index }, items[index]))
|
|
590
|
-
];
|
|
591
|
-
}
|
|
592
|
-
function emptyRows(state, query, total, selected) {
|
|
593
|
-
if (!query.trim() && total === 0)
|
|
594
|
-
return recoveryRows(state, selected, "No tasks loaded.");
|
|
595
|
-
if (query.trim() && total > 0) {
|
|
596
|
-
return [
|
|
597
|
-
...recoveryRows(state, selected, `No matching tasks for ${JSON.stringify(query)} (${total} total).`)
|
|
598
|
-
];
|
|
599
|
-
}
|
|
600
|
-
return recoveryRows(state, selected, "No tasks are visible with this filter.");
|
|
601
|
-
}
|
|
602
|
-
function degradedRows(state, selected) {
|
|
603
|
-
if (!state.error)
|
|
604
|
-
return [];
|
|
605
|
-
return recoveryRows(state, selected, state.error.message);
|
|
606
|
-
}
|
|
607
|
-
function rawString(raw, key) {
|
|
608
|
-
const value = raw?.[key];
|
|
609
|
-
return typeof value === "string" ? value : "";
|
|
610
|
-
}
|
|
611
|
-
function taskBody(state, task) {
|
|
612
|
-
const preview = state.data.taskPreviewRaw;
|
|
613
|
-
if (preview && typeof preview === "object" && !Array.isArray(preview)) {
|
|
614
|
-
const fromPreview = rawString(preview, "body");
|
|
615
|
-
if (fromPreview.trim())
|
|
616
|
-
return fromPreview;
|
|
617
|
-
}
|
|
618
|
-
return rawString(task?.raw, "body");
|
|
619
|
-
}
|
|
620
|
-
function renderTaskDetail(state, taskId, layout) {
|
|
621
|
-
const task = taskRecords(state).find((entry) => entry.id === taskId);
|
|
622
|
-
const title = (task?.title || taskId).trim();
|
|
623
|
-
const status = task?.status ?? "unknown";
|
|
624
|
-
const { glyph, color } = statusLabel(status);
|
|
625
|
-
const body = taskBody(state, task);
|
|
626
|
-
const activeRunId = task?.activeRun?.runId?.trim();
|
|
627
|
-
const width = panelWidth(layout);
|
|
628
|
-
const selected = Math.max(0, state.selection.index);
|
|
629
|
-
const errorText = state.error?.message ?? lastRefreshError(state);
|
|
630
|
-
const offerRepairLink = shouldOfferRemoteLinkRepair(state, errorText);
|
|
631
|
-
const headerLines = [
|
|
632
|
-
...errorText ? errorBanner(errorText, offerRepairLink ? "select repair link below to prepare the remote checkout" : "retry dispatch after resolving the issue") : [],
|
|
633
|
-
line(`${glyph} ${title}`, { fg: color, bold: true }),
|
|
634
|
-
line(`task ${taskId} \xB7 ${status}`, { fg: RIG_UI.ink3 }),
|
|
635
|
-
...task && task.labels.length > 0 ? [line(`labels: ${task.labels.join(", ")}`, { fg: RIG_UI.ink4 })] : [],
|
|
636
|
-
...task && task.assignees.length > 0 ? [line(`assignees: ${task.assignees.join(", ")}`, { fg: RIG_UI.ink4 })] : [],
|
|
637
|
-
line("", { fg: RIG_UI.ink3 }),
|
|
638
|
-
line("ACTIONS", { fg: RIG_UI.ink3, bold: true })
|
|
639
|
-
];
|
|
640
|
-
let index = 0;
|
|
641
|
-
const actionRows = [];
|
|
642
|
-
actionRows.push(selectableDeckRow({ label: "back", detail: "return to the task list", index, active: selected === index }, { id: "task-detail-back", label: "back", data: { taskDetailId: undefined }, message: "back to task list" }));
|
|
643
|
-
index += 1;
|
|
644
|
-
if (offerRepairLink) {
|
|
645
|
-
actionRows.push(selectableDeckRow({ label: "repair link", detail: "prepare/backfill the selected remote project-root link", index, active: selected === index }, { id: `task-detail-repair-link:${taskId}`, label: "repair link", intent: { scene: "server", argv: ["server", "repair-link"], action: { kind: "remote-link-repair", label: "Repair remote link", payload: { returnScene: "tasks", taskDetailId: taskId } } }, message: "prepare remote checkout link" }));
|
|
646
|
-
index += 1;
|
|
647
|
-
}
|
|
648
|
-
if (offerRepairLink) {
|
|
649
|
-
actionRows.push(line(" dispatch blocked until the remote project link is repaired", { fg: RIG_UI.ink4 }));
|
|
650
|
-
} else {
|
|
651
|
-
actionRows.push(selectableDeckRow({ label: "dispatch", detail: "submit a Pi run for this task", index, active: selected === index }, { id: `task-detail-run:${taskId}`, label: `dispatch ${taskId}`, intent: { scene: "tasks", argv: ["run", taskId], action: { kind: "task-run-id", payload: { task: taskId }, label: `Dispatching ${taskId}` } }, message: `dispatch task ${taskId}` }));
|
|
652
|
-
index += 1;
|
|
653
|
-
}
|
|
654
|
-
if (activeRunId) {
|
|
655
|
-
actionRows.push(selectableDeckRow({ label: "attach", detail: `attach the Pi console to run ${activeRunId.slice(0, 8)}`, index, active: selected === index }, { id: `task-detail-attach:${taskId}`, label: `attach ${activeRunId.slice(0, 8)}`, intent: { scene: "handoff", argv: ["attach", activeRunId], action: { kind: "run-attach", payload: { runId: activeRunId }, label: `Attach Pi ${activeRunId.slice(0, 8)}` } }, message: `attach Pi to ${activeRunId.slice(0, 8)}` }));
|
|
656
|
-
index += 1;
|
|
657
|
-
}
|
|
658
|
-
const bodyHeading = [line("", { fg: RIG_UI.ink3 }), line("BODY", { fg: RIG_UI.ink3, bold: true })];
|
|
659
|
-
const bodyLines = body.trim() ? body.split(`
|
|
660
|
-
`).slice(0, 400).map((text) => line(text, { fg: RIG_UI.ink2 })) : [line("(no description)", { fg: RIG_UI.ink4 })];
|
|
661
|
-
const panelLines = [...headerLines, ...actionRows, ...bodyHeading, ...bodyLines];
|
|
662
|
-
const paddingX = layout?.compact ? 2 : 3;
|
|
663
|
-
const chromeTopInset = 3 + 1;
|
|
664
|
-
const headerCount = headerLines.length + actionRows.length + bodyHeading.length;
|
|
665
|
-
const native = body.trim() ? {
|
|
666
|
-
kind: "markdown",
|
|
667
|
-
content: body,
|
|
668
|
-
top: (layout?.centerTop ?? 1) + chromeTopInset + headerCount,
|
|
669
|
-
left: (layout?.centerLeft ?? 2) + paddingX,
|
|
670
|
-
width: Math.max(20, width - paddingX * 2),
|
|
671
|
-
height: Math.max(6, panelHeight(layout, 0) - chromeTopInset - headerCount - 1)
|
|
672
|
-
} : undefined;
|
|
673
|
-
return makeSceneFrame({
|
|
674
|
-
scene: "tasks",
|
|
675
|
-
title: "Task",
|
|
676
|
-
lines: [],
|
|
677
|
-
...native ? { native } : {},
|
|
678
|
-
panels: [{
|
|
679
|
-
id: "task-detail",
|
|
680
|
-
top: 0,
|
|
681
|
-
width,
|
|
682
|
-
height: panelHeight(layout, 0),
|
|
683
|
-
lines: panelLines,
|
|
684
|
-
backgroundColor: RIG_UI.panel,
|
|
685
|
-
backgroundAlpha: 184,
|
|
686
|
-
opacity: 1,
|
|
687
|
-
border: false,
|
|
688
|
-
stickyScroll: true,
|
|
689
|
-
stickyStart: "top",
|
|
690
|
-
chrome: "ad-terminal",
|
|
691
|
-
headerText: `task ${taskId}`,
|
|
692
|
-
headerHeight: 3,
|
|
693
|
-
paddingX,
|
|
694
|
-
paddingY: 1
|
|
695
|
-
}],
|
|
696
|
-
footer: { run: activeRunId ? `${activeRunId.slice(0, 8)} active` : undefined, message: "back returns to the list \xB7 dispatch runs the task" },
|
|
697
|
-
live: state.status === "action"
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
function renderTasksScene(state, layout) {
|
|
701
|
-
const detailId = typeof state.data.taskDetailId === "string" ? state.data.taskDetailId.trim() : "";
|
|
702
|
-
if (detailId)
|
|
703
|
-
return renderTaskDetail(state, detailId, layout);
|
|
704
|
-
const width = panelWidth(layout);
|
|
705
|
-
const view = taskView(state);
|
|
706
|
-
const allTasks = taskRecords(state);
|
|
707
|
-
const query = listSearchQuery(state);
|
|
708
|
-
const spec = taskSortSpec(state.data.taskSort);
|
|
709
|
-
const tasks = sortTasks(filterTasksForSearch(allTasks, query), spec);
|
|
710
|
-
const selected = typeof state.data.selectedTaskId === "string" && tasks.some((task) => task.id === state.data.selectedTaskId) ? state.data.selectedTaskId : tasks[0]?.id;
|
|
711
|
-
const selectedIndex = Math.max(0, tasks.findIndex((task) => task.id === selected));
|
|
712
|
-
const recoveryIndex = Math.max(0, Math.min(taskRecoveryItems(state).length - 1, state.selection.index));
|
|
713
|
-
const dispatching = dispatchingFor(state);
|
|
714
|
-
const dispatchLine = dispatching ? ` \xB7 ${state.data.dispatchingRun?.runId ?? "new"} ${dispatching.status}` : "";
|
|
715
|
-
const updatedAgo = updatedAgoLabel(state);
|
|
716
|
-
const panelTop = 0;
|
|
717
|
-
const contentWidth = Math.max(12, width - (layout?.compact ? 8 : 10));
|
|
718
|
-
const loading = state.status === "loading" && allTasks.length === 0;
|
|
719
|
-
const refreshError = lastRefreshError(state);
|
|
720
|
-
const banner = refreshError && !state.error ? errorBanner(refreshError) : [];
|
|
721
|
-
const panelLines = [
|
|
722
|
-
...banner,
|
|
723
|
-
...tasks.length > 0 ? [
|
|
724
|
-
...degradedRows(state, recoveryIndex),
|
|
725
|
-
...query.trim() ? [line(searchSummary("tasks", query, tasks.length, allTasks.length), { fg: RIG_UI.ink4 }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
726
|
-
...sortStrip(spec),
|
|
727
|
-
headerRow(spec),
|
|
728
|
-
line("", { fg: RIG_UI.ink3 }),
|
|
729
|
-
...tasks.map((task, index) => taskRow(contentWidth, task, index === selectedIndex, dispatching && dispatching.taskId === task.id ? dispatching.status : undefined))
|
|
730
|
-
] : state.error ? degradedRows(state, recoveryIndex) : loading ? loadingRows("tasks", state.tick) : [
|
|
731
|
-
...query.trim() ? [line(searchSummary("tasks", query, tasks.length, allTasks.length), { fg: RIG_UI.ink4 }), line("", { fg: RIG_UI.ink3 })] : [],
|
|
732
|
-
...emptyRows(state, query, allTasks.length, recoveryIndex)
|
|
733
|
-
]
|
|
734
|
-
];
|
|
735
|
-
return makeSceneFrame({
|
|
736
|
-
scene: "tasks",
|
|
737
|
-
title: "Tasks",
|
|
738
|
-
lines: [
|
|
739
|
-
line("", { fg: RIG_UI.ink4 }),
|
|
740
|
-
line(`${query.trim() ? ` tasks --search ${JSON.stringify(query)}` : ` tasks \xB7 ${taskViewLabel(view)}${dispatchLine}`}${updatedAgo ? ` \xB7 ${updatedAgo}` : ""}`, { fg: RIG_UI.ink3 })
|
|
741
|
-
],
|
|
742
|
-
panels: [{
|
|
743
|
-
id: "tasks-list",
|
|
744
|
-
top: panelTop,
|
|
745
|
-
width,
|
|
746
|
-
height: panelHeight(layout, panelTop),
|
|
747
|
-
lines: panelLines,
|
|
748
|
-
backgroundColor: RIG_UI.panel,
|
|
749
|
-
backgroundAlpha: 184,
|
|
750
|
-
opacity: 1,
|
|
751
|
-
border: false,
|
|
752
|
-
chrome: "ad-terminal",
|
|
753
|
-
headerText: query.trim() ? `tasks --search ${JSON.stringify(query)}` : `tasks \xB7 ${taskViewLabel(view)}${dispatchLine}`,
|
|
754
|
-
headerHeight: 3,
|
|
755
|
-
paddingX: layout?.compact ? 2 : 3,
|
|
756
|
-
paddingY: 1
|
|
757
|
-
}],
|
|
758
|
-
footer: {
|
|
759
|
-
message: query.trim() ? searchSummary("tasks", query, tasks.length, allTasks.length) : taskViewLabel(view),
|
|
760
|
-
...updatedAgo ? { updated: updatedAgo } : {}
|
|
761
|
-
},
|
|
762
|
-
typeBarPlaceholder: "search tasks\u2026",
|
|
763
|
-
live: true
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
export {
|
|
767
|
-
renderTasksScene
|
|
768
|
-
};
|