@cabane/companion 0.6.215 → 0.6.217
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/dist/cli.js +448 -2670
- package/dist/credential-broker.js +653 -0
- package/dist/launch.js +7 -4
- package/dist/pairing-config.js +7 -4
- package/dist/runtime.js +770 -2955
- package/package.json +11 -4
- package/dist/static/app.js +0 -545
- package/dist/static/index.html +0 -122
- package/dist/static/styles.css +0 -531
package/dist/static/index.html
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<title>Cabane Companion</title>
|
|
7
|
-
<link rel="stylesheet" href="/static/styles.css" />
|
|
8
|
-
<!-- the Cabane app-icon — ink tile, ember A-frame mark. Reads on a
|
|
9
|
-
light or dark browser tab. -->
|
|
10
|
-
<link
|
|
11
|
-
rel="icon"
|
|
12
|
-
href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'><rect width='512' height='512' rx='112' ry='112' fill='%23141413'/><g fill='none' stroke='%23c8552a' stroke-width='2.52' stroke-linecap='round' transform='translate(116 151) scale(11.67)'><path d='M 1.26 16.74 L 12 1.26'/><path d='M 12 1.26 L 22.74 16.74'/></g></svg>"
|
|
13
|
-
/>
|
|
14
|
-
</head>
|
|
15
|
-
<body>
|
|
16
|
-
<main class="shell">
|
|
17
|
-
<header class="topbar">
|
|
18
|
-
<div class="brand">
|
|
19
|
-
<svg class="logo" viewBox="0 0 24 18" fill="none" aria-hidden="true">
|
|
20
|
-
<path
|
|
21
|
-
d="M 1.26 16.74 L 12 1.26"
|
|
22
|
-
stroke="currentColor"
|
|
23
|
-
stroke-width="2.52"
|
|
24
|
-
stroke-linecap="round"
|
|
25
|
-
/>
|
|
26
|
-
<path
|
|
27
|
-
d="M 12 1.26 L 22.74 16.74"
|
|
28
|
-
stroke="currentColor"
|
|
29
|
-
stroke-width="2.52"
|
|
30
|
-
stroke-linecap="round"
|
|
31
|
-
/>
|
|
32
|
-
</svg>
|
|
33
|
-
<span id="status-dot" class="dot dot--unknown" aria-hidden="true"></span>
|
|
34
|
-
<h1 id="status-title">Cabane Companion</h1>
|
|
35
|
-
</div>
|
|
36
|
-
<p id="conn-line" class="conn-line">Connecting…</p>
|
|
37
|
-
<p id="listen-line" class="listen-line"></p>
|
|
38
|
-
</header>
|
|
39
|
-
|
|
40
|
-
<!-- CT586: the harnesses this device exposes to Cabane. Primary panel — a
|
|
41
|
-
device exposing NONE is useless, so the loud empty state lives here. -->
|
|
42
|
-
<section class="panel" id="harnesses-panel">
|
|
43
|
-
<h2>
|
|
44
|
-
Harnesses
|
|
45
|
-
<button type="button" id="recheck-btn" class="link-btn" title="Re-check now">
|
|
46
|
-
Recheck
|
|
47
|
-
</button>
|
|
48
|
-
</h2>
|
|
49
|
-
<div id="harness-empty" class="harness-empty" hidden>
|
|
50
|
-
<p class="harness-empty-title">Cabane can’t run anything on this device yet.</p>
|
|
51
|
-
<p class="harness-empty-body">
|
|
52
|
-
Install and sign in to a harness — Claude Code, Codex, or opencode — then it’ll appear
|
|
53
|
-
here as ready. Until then, agents assigned to this device have nothing to run on.
|
|
54
|
-
</p>
|
|
55
|
-
</div>
|
|
56
|
-
<ul id="harness-list" class="harness-list"></ul>
|
|
57
|
-
<p id="harness-checking" class="empty">Checking harnesses…</p>
|
|
58
|
-
</section>
|
|
59
|
-
|
|
60
|
-
<section class="panel" id="connected-panel">
|
|
61
|
-
<h2>Connected workspaces <span id="connected-count" class="count"></span></h2>
|
|
62
|
-
<ul id="connected-list" class="ws-list"></ul>
|
|
63
|
-
<p id="connected-empty" class="empty" hidden>
|
|
64
|
-
No agents assigned yet. In a workspace, open an agent's page and choose this device under
|
|
65
|
-
Where they run.
|
|
66
|
-
</p>
|
|
67
|
-
</section>
|
|
68
|
-
|
|
69
|
-
<section class="panel" id="dispatches-panel">
|
|
70
|
-
<h2>Recent dispatches</h2>
|
|
71
|
-
<ul id="dispatch-list" class="dispatch-list"></ul>
|
|
72
|
-
<p id="dispatch-empty" class="empty" hidden>
|
|
73
|
-
No dispatches yet. Post a message in cabane and it'll show up here.
|
|
74
|
-
</p>
|
|
75
|
-
</section>
|
|
76
|
-
|
|
77
|
-
<footer class="actions">
|
|
78
|
-
<button type="button" data-toggle="logs-panel">Open logs</button>
|
|
79
|
-
<button type="button" data-toggle="settings-panel">Settings</button>
|
|
80
|
-
<button type="button" id="restart-btn" class="ghost">Restart</button>
|
|
81
|
-
<button type="button" id="stop-btn" class="ghost danger">Stop</button>
|
|
82
|
-
</footer>
|
|
83
|
-
|
|
84
|
-
<section class="panel collapsible" id="logs-panel" hidden>
|
|
85
|
-
<h2>Logs <span class="hint">~/.cabane/companion.log</span></h2>
|
|
86
|
-
<pre id="logs-view" class="logs">Loading…</pre>
|
|
87
|
-
</section>
|
|
88
|
-
|
|
89
|
-
<section class="panel collapsible" id="settings-panel" hidden>
|
|
90
|
-
<h2>Settings</h2>
|
|
91
|
-
<div class="setting">
|
|
92
|
-
<label>Cabane URL</label>
|
|
93
|
-
<span id="set-url" class="readonly">—</span>
|
|
94
|
-
</div>
|
|
95
|
-
<div class="setting">
|
|
96
|
-
<label>Dashboard port</label>
|
|
97
|
-
<span id="set-port" class="readonly">—</span>
|
|
98
|
-
<span class="hint">change in ~/.cabane/config.json (needs restart)</span>
|
|
99
|
-
</div>
|
|
100
|
-
<div class="setting">
|
|
101
|
-
<label for="set-loglevel">Log level</label>
|
|
102
|
-
<select id="set-loglevel">
|
|
103
|
-
<option value="warn">warn</option>
|
|
104
|
-
<option value="info">info</option>
|
|
105
|
-
<option value="debug">debug</option>
|
|
106
|
-
</select>
|
|
107
|
-
<span id="check-loglevel" class="saved-check" hidden>✓</span>
|
|
108
|
-
</div>
|
|
109
|
-
<div class="setting">
|
|
110
|
-
<label for="set-autoopen">Auto-open browser on start</label>
|
|
111
|
-
<input type="checkbox" id="set-autoopen" />
|
|
112
|
-
<span id="check-autoopen" class="saved-check" hidden>✓</span>
|
|
113
|
-
</div>
|
|
114
|
-
</section>
|
|
115
|
-
|
|
116
|
-
<p class="version">companion <span id="ver-companion">—</span></p>
|
|
117
|
-
</main>
|
|
118
|
-
|
|
119
|
-
<div id="toast" class="toast" hidden></div>
|
|
120
|
-
<script src="/static/app.js"></script>
|
|
121
|
-
</body>
|
|
122
|
-
</html>
|
package/dist/static/styles.css
DELETED
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
/* Cabane Companion dashboard. Utilitarian, no framework. Light by
|
|
2
|
-
default, dark via prefers-color-scheme. The job is to answer "is it
|
|
3
|
-
running / what's it doing / why isn't it replying" at a glance.
|
|
4
|
-
|
|
5
|
-
Brand tokens: the app's neutral grounds, ink foreground, ember accent +
|
|
6
|
-
mark, copied by value from apps/web/src/index.css. Secondary text takes
|
|
7
|
-
the app's fg-2, not fg-faint: hints and dispatch bodies here are read. The status dots stay emerald/amber/red intent tints — health is
|
|
8
|
-
not a brand slot. */
|
|
9
|
-
|
|
10
|
-
:root {
|
|
11
|
-
--bg: #f9f9fa; /* page ground */
|
|
12
|
-
--panel: #ffffff; /* Surface — cards */
|
|
13
|
-
--ink: #141413; /* Ink — foreground */
|
|
14
|
-
--muted: rgba(20, 20, 19, 0.72); /* fg-2 — labels, secondary */
|
|
15
|
-
--line: rgba(0, 0, 0, 0.08); /* hairline */
|
|
16
|
-
--inset: #f1f1f3; /* recessed well — code, detail */
|
|
17
|
-
--accent: #c8552a; /* Ember — fills, mark, large accents */
|
|
18
|
-
--accent-text: #b44b25; /* link / small accent text — deepened from #c8552a to clear AA on the panel (lifts on dark) */
|
|
19
|
-
--green: #059669; /* healthy */
|
|
20
|
-
--amber: #d97706; /* degraded */
|
|
21
|
-
--red: #b8423a; /* error / destructive */
|
|
22
|
-
--danger: #b8423a;
|
|
23
|
-
--radius: 9px;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
@media (prefers-color-scheme: dark) {
|
|
27
|
-
:root {
|
|
28
|
-
--bg: #131315; /* the page */
|
|
29
|
-
--panel: #1d1d20; /* surface — cards, panels */
|
|
30
|
-
--ink: #ededef; /* off-white */
|
|
31
|
-
--muted: rgba(237, 237, 239, 0.74);
|
|
32
|
-
--line: rgba(255, 255, 255, 0.1);
|
|
33
|
-
--inset: #18181b;
|
|
34
|
-
--accent: #c8552a; /* ember holds for fills */
|
|
35
|
-
--accent-text: #e2794a; /* ember-lift — clears AA on dark */
|
|
36
|
-
--green: #10b981;
|
|
37
|
-
--amber: #f59e0b;
|
|
38
|
-
--red: #e0635a;
|
|
39
|
-
--danger: #e0635a;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
* {
|
|
44
|
-
box-sizing: border-box;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
body {
|
|
48
|
-
margin: 0;
|
|
49
|
-
background: var(--bg);
|
|
50
|
-
color: var(--ink);
|
|
51
|
-
font:
|
|
52
|
-
14px/1.5 system-ui,
|
|
53
|
-
-apple-system,
|
|
54
|
-
'Segoe UI',
|
|
55
|
-
Roboto,
|
|
56
|
-
sans-serif;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.shell {
|
|
60
|
-
max-width: 720px;
|
|
61
|
-
margin: 0 auto;
|
|
62
|
-
padding: 28px 20px 48px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.topbar {
|
|
66
|
-
margin-bottom: 24px;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.brand {
|
|
70
|
-
display: flex;
|
|
71
|
-
align-items: center;
|
|
72
|
-
gap: 10px;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* the Cabane mark: an A-frame roofline ("cabin"), ember stroke (viewBox 0 0 24 18). */
|
|
76
|
-
.logo {
|
|
77
|
-
height: 17px;
|
|
78
|
-
width: auto;
|
|
79
|
-
color: var(--accent);
|
|
80
|
-
flex: 0 0 auto;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.brand h1 {
|
|
84
|
-
font-size: 20px;
|
|
85
|
-
margin: 0;
|
|
86
|
-
font-weight: 650;
|
|
87
|
-
letter-spacing: -0.01em;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.dot {
|
|
91
|
-
width: 11px;
|
|
92
|
-
height: 11px;
|
|
93
|
-
border-radius: 50%;
|
|
94
|
-
flex: 0 0 auto;
|
|
95
|
-
background: var(--muted);
|
|
96
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent);
|
|
97
|
-
}
|
|
98
|
-
.dot--green {
|
|
99
|
-
background: var(--green);
|
|
100
|
-
color: var(--green);
|
|
101
|
-
}
|
|
102
|
-
.dot--amber {
|
|
103
|
-
background: var(--amber);
|
|
104
|
-
color: var(--amber);
|
|
105
|
-
}
|
|
106
|
-
.dot--red {
|
|
107
|
-
background: var(--red);
|
|
108
|
-
color: var(--red);
|
|
109
|
-
}
|
|
110
|
-
.dot--unknown {
|
|
111
|
-
background: var(--muted);
|
|
112
|
-
color: var(--muted);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.conn-line {
|
|
116
|
-
margin: 10px 0 2px;
|
|
117
|
-
font-weight: 500;
|
|
118
|
-
}
|
|
119
|
-
.listen-line {
|
|
120
|
-
margin: 0;
|
|
121
|
-
color: var(--muted);
|
|
122
|
-
font-size: 13px;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.panel {
|
|
126
|
-
background: var(--panel);
|
|
127
|
-
border: 1px solid var(--line);
|
|
128
|
-
border-radius: var(--radius);
|
|
129
|
-
padding: 16px 18px;
|
|
130
|
-
margin-bottom: 16px;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.panel h2 {
|
|
134
|
-
font-size: 13px;
|
|
135
|
-
text-transform: uppercase;
|
|
136
|
-
letter-spacing: 0.04em;
|
|
137
|
-
color: var(--muted);
|
|
138
|
-
margin: 0 0 12px;
|
|
139
|
-
font-weight: 600;
|
|
140
|
-
display: flex;
|
|
141
|
-
align-items: baseline;
|
|
142
|
-
gap: 8px;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.count {
|
|
146
|
-
color: var(--muted);
|
|
147
|
-
font-weight: 400;
|
|
148
|
-
}
|
|
149
|
-
.hint {
|
|
150
|
-
color: var(--muted);
|
|
151
|
-
font-weight: 400;
|
|
152
|
-
font-size: 12px;
|
|
153
|
-
text-transform: none;
|
|
154
|
-
letter-spacing: 0;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.ws-list,
|
|
158
|
-
.dispatch-list {
|
|
159
|
-
list-style: none;
|
|
160
|
-
margin: 0;
|
|
161
|
-
padding: 0;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.ws-row {
|
|
165
|
-
display: flex;
|
|
166
|
-
align-items: center;
|
|
167
|
-
flex-wrap: wrap;
|
|
168
|
-
gap: 10px;
|
|
169
|
-
padding: 9px 0;
|
|
170
|
-
border-top: 1px solid var(--line);
|
|
171
|
-
}
|
|
172
|
-
.ws-row:first-child {
|
|
173
|
-
border-top: none;
|
|
174
|
-
}
|
|
175
|
-
.ws-row .ws-name {
|
|
176
|
-
font-weight: 550;
|
|
177
|
-
}
|
|
178
|
-
.ws-row .ws-meta {
|
|
179
|
-
color: var(--muted);
|
|
180
|
-
font-size: 13px;
|
|
181
|
-
margin-left: 2px;
|
|
182
|
-
}
|
|
183
|
-
.ws-row .spacer {
|
|
184
|
-
flex: 1;
|
|
185
|
-
}
|
|
186
|
-
/* a terminally auth-failed workspace (rotated/revoked PAT). The
|
|
187
|
-
meta line carries the "re-add this workspace" call to action in red so it
|
|
188
|
-
reads as actionable, not as a transient reconnect. */
|
|
189
|
-
.ws-row .ws-meta.ws-meta--alert {
|
|
190
|
-
color: var(--red);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/* CT29: the agents this device runs in this workspace, pulled from Cabane.
|
|
194
|
-
Wraps to its own line under the workspace row (flex-basis 100%). */
|
|
195
|
-
.ws-row .ws-agents {
|
|
196
|
-
flex-basis: 100%;
|
|
197
|
-
list-style: none;
|
|
198
|
-
margin: 4px 0 0;
|
|
199
|
-
padding: 0 0 0 18px;
|
|
200
|
-
display: flex;
|
|
201
|
-
flex-direction: column;
|
|
202
|
-
gap: 4px;
|
|
203
|
-
}
|
|
204
|
-
.ws-row .ws-agent {
|
|
205
|
-
display: flex;
|
|
206
|
-
align-items: center;
|
|
207
|
-
gap: 8px;
|
|
208
|
-
font-size: 13px;
|
|
209
|
-
}
|
|
210
|
-
.ws-row .ws-agent-name {
|
|
211
|
-
font-weight: 550;
|
|
212
|
-
}
|
|
213
|
-
.ws-row .ws-agent-warn {
|
|
214
|
-
color: var(--red);
|
|
215
|
-
font-size: 12px;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
button {
|
|
219
|
-
font: inherit;
|
|
220
|
-
cursor: pointer;
|
|
221
|
-
border-radius: 7px;
|
|
222
|
-
border: 1px solid var(--line);
|
|
223
|
-
background: var(--panel);
|
|
224
|
-
color: var(--ink);
|
|
225
|
-
padding: 6px 12px;
|
|
226
|
-
}
|
|
227
|
-
button:hover {
|
|
228
|
-
border-color: var(--accent);
|
|
229
|
-
}
|
|
230
|
-
button.primary {
|
|
231
|
-
background: var(--accent);
|
|
232
|
-
border-color: var(--accent);
|
|
233
|
-
color: #fff;
|
|
234
|
-
}
|
|
235
|
-
button.ghost {
|
|
236
|
-
background: transparent;
|
|
237
|
-
}
|
|
238
|
-
button.danger,
|
|
239
|
-
button.danger:hover {
|
|
240
|
-
color: var(--danger);
|
|
241
|
-
border-color: color-mix(in srgb, var(--danger) 40%, var(--line));
|
|
242
|
-
}
|
|
243
|
-
button.small {
|
|
244
|
-
padding: 3px 9px;
|
|
245
|
-
font-size: 13px;
|
|
246
|
-
}
|
|
247
|
-
button:disabled {
|
|
248
|
-
opacity: 0.5;
|
|
249
|
-
cursor: default;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
.actions {
|
|
253
|
-
display: flex;
|
|
254
|
-
gap: 8px;
|
|
255
|
-
flex-wrap: wrap;
|
|
256
|
-
margin: 4px 0 16px;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
.empty {
|
|
260
|
-
color: var(--muted);
|
|
261
|
-
font-size: 13px;
|
|
262
|
-
margin: 4px 0 0;
|
|
263
|
-
}
|
|
264
|
-
.empty.error {
|
|
265
|
-
color: var(--red);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/* CT586: harnesses surface — which of the three the device exposes, how healthy
|
|
269
|
-
each is, and (loudly) when it exposes none. */
|
|
270
|
-
|
|
271
|
-
/* a text-style button in a panel heading (the "Recheck" affordance). */
|
|
272
|
-
.link-btn {
|
|
273
|
-
border: none;
|
|
274
|
-
background: none;
|
|
275
|
-
padding: 0;
|
|
276
|
-
margin-left: auto;
|
|
277
|
-
color: var(--accent-text);
|
|
278
|
-
font-size: 12px;
|
|
279
|
-
text-transform: none;
|
|
280
|
-
letter-spacing: 0;
|
|
281
|
-
font-weight: 500;
|
|
282
|
-
}
|
|
283
|
-
.link-btn:hover {
|
|
284
|
-
border: none;
|
|
285
|
-
text-decoration: underline;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/* The loud empty state — the headline requirement. A device exposing zero
|
|
289
|
-
harnesses is useless, so this is impossible to miss: an ember-tinted well with
|
|
290
|
-
a large lead line, not a grey dot. */
|
|
291
|
-
.harness-empty {
|
|
292
|
-
border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
|
|
293
|
-
background: rgba(200, 85, 42, 0.1);
|
|
294
|
-
border-radius: var(--radius);
|
|
295
|
-
padding: 14px 16px;
|
|
296
|
-
margin-bottom: 14px;
|
|
297
|
-
}
|
|
298
|
-
.harness-empty-title {
|
|
299
|
-
margin: 0 0 6px;
|
|
300
|
-
font-size: 15px;
|
|
301
|
-
font-weight: 650;
|
|
302
|
-
color: var(--accent-text);
|
|
303
|
-
}
|
|
304
|
-
.harness-empty-body {
|
|
305
|
-
margin: 0;
|
|
306
|
-
font-size: 13px;
|
|
307
|
-
color: var(--ink);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
.harness-list {
|
|
311
|
-
list-style: none;
|
|
312
|
-
margin: 0;
|
|
313
|
-
padding: 0;
|
|
314
|
-
}
|
|
315
|
-
.harness-row {
|
|
316
|
-
display: flex;
|
|
317
|
-
align-items: center;
|
|
318
|
-
flex-wrap: wrap;
|
|
319
|
-
gap: 10px;
|
|
320
|
-
padding: 11px 0;
|
|
321
|
-
border-top: 1px solid var(--line);
|
|
322
|
-
}
|
|
323
|
-
.harness-row:first-child {
|
|
324
|
-
border-top: none;
|
|
325
|
-
}
|
|
326
|
-
.harness-name {
|
|
327
|
-
font-weight: 600;
|
|
328
|
-
}
|
|
329
|
-
.harness-version {
|
|
330
|
-
color: var(--muted);
|
|
331
|
-
font-size: 12px;
|
|
332
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
333
|
-
}
|
|
334
|
-
.harness-badge {
|
|
335
|
-
font-size: 11px;
|
|
336
|
-
font-weight: 600;
|
|
337
|
-
text-transform: uppercase;
|
|
338
|
-
letter-spacing: 0.03em;
|
|
339
|
-
padding: 2px 8px;
|
|
340
|
-
border-radius: 999px;
|
|
341
|
-
border: 1px solid currentColor;
|
|
342
|
-
}
|
|
343
|
-
.harness-badge--exposed {
|
|
344
|
-
color: var(--green);
|
|
345
|
-
}
|
|
346
|
-
.harness-badge--detected_not_exposed {
|
|
347
|
-
color: var(--amber);
|
|
348
|
-
}
|
|
349
|
-
.harness-badge--needs_attention {
|
|
350
|
-
color: var(--red);
|
|
351
|
-
}
|
|
352
|
-
.harness-badge--not_detected {
|
|
353
|
-
color: var(--muted);
|
|
354
|
-
}
|
|
355
|
-
.harness-spacer {
|
|
356
|
-
flex: 1;
|
|
357
|
-
}
|
|
358
|
-
/* the per-harness guidance line ("install and sign in…", "run opencode serve…"),
|
|
359
|
-
wrapping to its own line under the row. */
|
|
360
|
-
.harness-detail {
|
|
361
|
-
flex-basis: 100%;
|
|
362
|
-
color: var(--muted);
|
|
363
|
-
font-size: 12.5px;
|
|
364
|
-
margin: 0;
|
|
365
|
-
}
|
|
366
|
-
.harness-detail code {
|
|
367
|
-
font-size: 11.5px;
|
|
368
|
-
}
|
|
369
|
-
/* the inline opencode-URL enable form (URL field + Add). */
|
|
370
|
-
.harness-enable {
|
|
371
|
-
flex-basis: 100%;
|
|
372
|
-
display: flex;
|
|
373
|
-
gap: 8px;
|
|
374
|
-
flex-wrap: wrap;
|
|
375
|
-
margin-top: 4px;
|
|
376
|
-
}
|
|
377
|
-
.harness-enable input {
|
|
378
|
-
font: inherit;
|
|
379
|
-
flex: 1;
|
|
380
|
-
min-width: 180px;
|
|
381
|
-
padding: 5px 9px;
|
|
382
|
-
border-radius: 6px;
|
|
383
|
-
border: 1px solid var(--line);
|
|
384
|
-
background: var(--inset);
|
|
385
|
-
color: var(--ink);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.dispatch-row {
|
|
389
|
-
border-top: 1px solid var(--line);
|
|
390
|
-
padding: 8px 0;
|
|
391
|
-
}
|
|
392
|
-
.dispatch-row:first-child {
|
|
393
|
-
border-top: none;
|
|
394
|
-
}
|
|
395
|
-
.dispatch-head {
|
|
396
|
-
display: flex;
|
|
397
|
-
align-items: center;
|
|
398
|
-
gap: 8px;
|
|
399
|
-
cursor: pointer;
|
|
400
|
-
}
|
|
401
|
-
.dispatch-head .time {
|
|
402
|
-
color: var(--muted);
|
|
403
|
-
font-size: 12px;
|
|
404
|
-
flex: 0 0 auto;
|
|
405
|
-
min-width: 42px;
|
|
406
|
-
}
|
|
407
|
-
.dispatch-head .ws {
|
|
408
|
-
color: var(--muted);
|
|
409
|
-
font-size: 12px;
|
|
410
|
-
flex: 0 0 auto;
|
|
411
|
-
}
|
|
412
|
-
.dispatch-head .preview {
|
|
413
|
-
flex: 1;
|
|
414
|
-
white-space: nowrap;
|
|
415
|
-
overflow: hidden;
|
|
416
|
-
text-overflow: ellipsis;
|
|
417
|
-
}
|
|
418
|
-
.dispatch-head .verdict {
|
|
419
|
-
flex: 0 0 auto;
|
|
420
|
-
font-size: 12px;
|
|
421
|
-
font-variant-numeric: tabular-nums;
|
|
422
|
-
}
|
|
423
|
-
.verdict.ok {
|
|
424
|
-
color: var(--green);
|
|
425
|
-
}
|
|
426
|
-
.verdict.err {
|
|
427
|
-
color: var(--red);
|
|
428
|
-
}
|
|
429
|
-
.verdict.run {
|
|
430
|
-
color: var(--amber);
|
|
431
|
-
}
|
|
432
|
-
.dispatch-detail {
|
|
433
|
-
margin: 6px 0 2px;
|
|
434
|
-
padding: 10px 12px;
|
|
435
|
-
background: var(--inset);
|
|
436
|
-
border-radius: 7px;
|
|
437
|
-
font-size: 13px;
|
|
438
|
-
}
|
|
439
|
-
/* labeled message / reply sections inside the expanded row. */
|
|
440
|
-
.dispatch-detail .d-block + .d-block {
|
|
441
|
-
margin-top: 10px;
|
|
442
|
-
}
|
|
443
|
-
.dispatch-detail .d-label {
|
|
444
|
-
font-size: 11px;
|
|
445
|
-
text-transform: uppercase;
|
|
446
|
-
letter-spacing: 0.04em;
|
|
447
|
-
color: var(--muted);
|
|
448
|
-
margin: 0 0 3px;
|
|
449
|
-
}
|
|
450
|
-
.dispatch-detail .d-body {
|
|
451
|
-
white-space: pre-wrap;
|
|
452
|
-
word-break: break-word;
|
|
453
|
-
}
|
|
454
|
-
.dispatch-detail .d-body.muted {
|
|
455
|
-
color: var(--muted);
|
|
456
|
-
}
|
|
457
|
-
.dispatch-detail .err-text {
|
|
458
|
-
color: var(--red);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
.logs {
|
|
462
|
-
margin: 0;
|
|
463
|
-
max-height: 320px;
|
|
464
|
-
overflow: auto;
|
|
465
|
-
font:
|
|
466
|
-
12px/1.45 ui-monospace,
|
|
467
|
-
SFMono-Regular,
|
|
468
|
-
Menlo,
|
|
469
|
-
monospace;
|
|
470
|
-
white-space: pre-wrap;
|
|
471
|
-
word-break: break-word;
|
|
472
|
-
color: var(--muted);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
.setting {
|
|
476
|
-
display: flex;
|
|
477
|
-
align-items: center;
|
|
478
|
-
gap: 10px;
|
|
479
|
-
padding: 7px 0;
|
|
480
|
-
border-top: 1px solid var(--line);
|
|
481
|
-
}
|
|
482
|
-
.setting:first-of-type {
|
|
483
|
-
border-top: none;
|
|
484
|
-
}
|
|
485
|
-
.setting label {
|
|
486
|
-
flex: 0 0 180px;
|
|
487
|
-
font-weight: 500;
|
|
488
|
-
}
|
|
489
|
-
.readonly {
|
|
490
|
-
color: var(--muted);
|
|
491
|
-
}
|
|
492
|
-
/* green ✓ flashed to the right of a setting after it saves, then cleared. */
|
|
493
|
-
.saved-check {
|
|
494
|
-
color: var(--green);
|
|
495
|
-
font-weight: 700;
|
|
496
|
-
font-size: 14px;
|
|
497
|
-
line-height: 1;
|
|
498
|
-
}
|
|
499
|
-
select {
|
|
500
|
-
font: inherit;
|
|
501
|
-
padding: 4px 8px;
|
|
502
|
-
border-radius: 6px;
|
|
503
|
-
border: 1px solid var(--line);
|
|
504
|
-
background: var(--panel);
|
|
505
|
-
color: var(--ink);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
.version {
|
|
509
|
-
text-align: center;
|
|
510
|
-
color: var(--muted);
|
|
511
|
-
font-size: 12px;
|
|
512
|
-
margin-top: 8px;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
.toast {
|
|
516
|
-
position: fixed;
|
|
517
|
-
left: 50%;
|
|
518
|
-
bottom: 22px;
|
|
519
|
-
transform: translateX(-50%);
|
|
520
|
-
background: var(--ink);
|
|
521
|
-
color: var(--bg);
|
|
522
|
-
padding: 9px 16px;
|
|
523
|
-
border-radius: 8px;
|
|
524
|
-
font-size: 13px;
|
|
525
|
-
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2);
|
|
526
|
-
max-width: 90vw;
|
|
527
|
-
}
|
|
528
|
-
.toast.error {
|
|
529
|
-
background: var(--red);
|
|
530
|
-
color: #fff;
|
|
531
|
-
}
|