@coreplane/switchboard 1.227.0 → 1.228.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/deploy/cloudflare-memory/worker.ts +157 -3
- package/dist/assets/deploy/cloudflare-resident/worker.ts +129 -14
- package/dist/assets/deploy/cloudflare-sandbox/Dockerfile +22 -18
- package/dist/assets/deploy/cloudflare-sandbox/package.json +1 -1
- package/dist/assets/deploy/cloudflare-sandbox/runtime-supervisor.sh +11 -10
- package/dist/assets/deploy/cloudflare-sandbox/worker.ts +332 -299
- package/dist/assets/deploy/cloudflare-sandbox/wrangler.template.jsonc +2 -2
- package/dist/assets/package-lock.json +7 -48
- package/dist/assets/package.json +1 -1
- package/dist/assets/project.json +2 -2
- package/dist/assets/source.json +3 -3
- package/dist/assets/src/agents/registry.ts +15 -0
- package/dist/assets/src/core/coordinator/contract.ts +6 -0
- package/dist/assets/src/core/coordinator/driver.ts +8 -6
- package/dist/assets/src/core/runEvents.ts +34 -1
- package/dist/assets/src/core/runFriction.ts +2 -1
- package/dist/assets/src/core/runRecord.ts +46 -3
- package/dist/assets/src/core/runUsage.ts +199 -0
- package/dist/assets/src/core/ship/coordinator.ts +4 -2
- package/dist/assets/src/execution/residentRebind.ts +84 -7
- package/dist/assets/src/execution/sandboxErrors.ts +14 -38
- package/dist/assets/src/execution/sandboxLifecycle.ts +78 -0
- package/dist/assets/web/dist/.vite/manifest.json +18 -18
- package/dist/assets/web/dist/assets/{ResidentDetailPage-Chvll3wy.js → ResidentDetailPage-B1Q9pabX.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentsIndexPage-B5f8IwGF.js → ResidentsIndexPage-CP7U_4aK.js} +1 -1
- package/dist/assets/web/dist/assets/{RunRoutePage-CRvmCuXh.js → RunRoutePage-dCC25f_b.js} +4 -4
- package/dist/assets/web/dist/assets/{RunsIndexPage-BTJuKFTv.js → RunsIndexPage-Cgp4t4C8.js} +1 -1
- package/dist/assets/web/dist/assets/{ScheduledPage-BVfgUBvP.js → ScheduledPage-DthDA2xG.js} +1 -1
- package/dist/assets/web/dist/assets/{StatusDot-CFXbAw7S.js → StatusDot-DDc88Kbs.js} +1 -1
- package/dist/assets/web/dist/assets/{Tooltip-DcHMtbHJ.js → Tooltip-CBapNhsh.js} +1 -1
- package/dist/assets/web/dist/assets/{dist-DKhqHu0V.js → dist-BnwSD1cL.js} +1 -1
- package/dist/assets/web/dist/assets/{main-CveRd2yk.js → main-ZhQGbZ2E.js} +2 -2
- package/dist/cli.js +808 -155
- package/package.json +1 -1
- package/dist/assets/src/execution/sandboxKeepalive.ts +0 -118
|
@@ -424,7 +424,9 @@ export interface UnitPipelineInput {
|
|
|
424
424
|
/** Each child preset's own wall-clock budget (its `maxMinutes`), the number a
|
|
425
425
|
* round's budget is clipped from — supplied by the bot, which holds the registry. */
|
|
426
426
|
childMinutes: Readonly<Record<ChildPreset, number>>;
|
|
427
|
-
/** Who merges: the
|
|
427
|
+
/** Who merges: the instance's `merge` field as the plan route answers it —
|
|
428
|
+
* `runner` (a seeded plan, under its grant) or `person` (a task, or a
|
|
429
|
+
* record without the field). */
|
|
428
430
|
merge: "runner" | "person";
|
|
429
431
|
/** Resume at review: an open pull request of ship's own the requester named. */
|
|
430
432
|
resume?: { pr: number; headSha?: string; url?: string };
|
|
@@ -1102,7 +1104,7 @@ export function renderUnitReport(s: UnitPipelineState): string {
|
|
|
1102
1104
|
`✅ Merge-ready after ${rounds}: ${e.pr.url}`,
|
|
1103
1105
|
verdictLine,
|
|
1104
1106
|
declinedLine,
|
|
1105
|
-
"Remaining gate: a person's merge — the runner merges only
|
|
1107
|
+
"Remaining gate: a person's merge — the runner merges only when the instance's `merge` field says runner, and ship never approves.",
|
|
1106
1108
|
].join("\n");
|
|
1107
1109
|
case "merge_refused":
|
|
1108
1110
|
return join([
|
|
@@ -65,6 +65,66 @@ export function parseRefByDefault(value: unknown): ParsedRefByDefault {
|
|
|
65
65
|
return { error: "refByDefault must be a boolean when present" };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/** A branch a run pushed and the pull request it heads — what the run's
|
|
69
|
+
* release hands the resident (`/detach` body `pushed`), read off the run's
|
|
70
|
+
* own `pr_opened` events. */
|
|
71
|
+
export interface PushedBranch {
|
|
72
|
+
ref: string;
|
|
73
|
+
pr: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** The same fact as the binding remembers it, with when it was told. */
|
|
77
|
+
export interface OwnBranch extends PushedBranch {
|
|
78
|
+
at: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The most branches one release may hand over: a run pushes a handful at most. */
|
|
82
|
+
export const PUSHED_MAX = 20;
|
|
83
|
+
/** The most branches a binding remembers: the newest are kept. */
|
|
84
|
+
export const OWN_BRANCHES_MAX = 50;
|
|
85
|
+
|
|
86
|
+
export type ParsedPushed = { pushed: PushedBranch[] } | { error: string };
|
|
87
|
+
|
|
88
|
+
const PUSHED_ERROR = "pushed must be a list of {ref: <branch>, pr: <positive integer>} when present";
|
|
89
|
+
|
|
90
|
+
/** `/detach` body field `pushed`: absent → nothing (the body every bot always
|
|
91
|
+
* sent); a list of up to `PUSHED_MAX` well-formed `{ref, pr}` → itself;
|
|
92
|
+
* anything else → a 400-shaped error. Each ref's PATTERN is the Worker's to
|
|
93
|
+
* check (`parseRef`), like every ref. */
|
|
94
|
+
export function parsePushed(value: unknown): ParsedPushed {
|
|
95
|
+
if (value === undefined) return { pushed: [] };
|
|
96
|
+
if (!Array.isArray(value) || value.length > PUSHED_MAX) return { error: PUSHED_ERROR };
|
|
97
|
+
const pushed: PushedBranch[] = [];
|
|
98
|
+
for (const entry of value) {
|
|
99
|
+
if (typeof entry !== "object" || entry === null) return { error: PUSHED_ERROR };
|
|
100
|
+
const { ref, pr } = entry as { ref?: unknown; pr?: unknown };
|
|
101
|
+
if (typeof ref !== "string" || ref.length === 0) return { error: PUSHED_ERROR };
|
|
102
|
+
if (typeof pr !== "number" || !Number.isSafeInteger(pr) || pr <= 0) return { error: PUSHED_ERROR };
|
|
103
|
+
pushed.push({ ref, pr });
|
|
104
|
+
}
|
|
105
|
+
return { pushed };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** The binding's memory after a release: every branch handed over is
|
|
109
|
+
* remembered once — a branch pushed again moves to the end with its current
|
|
110
|
+
* pull request and time — and only the newest `OWN_BRANCHES_MAX` are kept.
|
|
111
|
+
* Stored BEFORE any eviction decision, so the fact survives the tree. */
|
|
112
|
+
export function rememberOwnBranches(
|
|
113
|
+
existing: readonly OwnBranch[] | undefined,
|
|
114
|
+
pushed: readonly PushedBranch[],
|
|
115
|
+
at: string,
|
|
116
|
+
): OwnBranch[] {
|
|
117
|
+
const refs = new Set(pushed.map((p) => p.ref));
|
|
118
|
+
const kept = (existing ?? []).filter((b) => !refs.has(b.ref));
|
|
119
|
+
const added = pushed.map((p) => ({ ref: p.ref, pr: p.pr, at }));
|
|
120
|
+
return [...kept, ...added].slice(-OWN_BRANCHES_MAX);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Whether the thread's own runs pushed `ref`, as the binding remembers it. */
|
|
124
|
+
export function isOwnBranch(binding: { ownBranches?: readonly OwnBranch[] }, ref: string): boolean {
|
|
125
|
+
return (binding.ownBranches ?? []).some((b) => b.ref === ref);
|
|
126
|
+
}
|
|
127
|
+
|
|
68
128
|
/** How a binding's ref was chosen: the repo default for want of a named
|
|
69
129
|
* branch, or a branch someone named. */
|
|
70
130
|
export type BoundBy = "default" | "name";
|
|
@@ -109,6 +169,8 @@ export interface RebindableBinding {
|
|
|
109
169
|
evicted?: boolean;
|
|
110
170
|
boundBy?: BoundBy;
|
|
111
171
|
rebound?: Rebound;
|
|
172
|
+
/** The branches the thread's own runs pushed, handed over at each release. */
|
|
173
|
+
ownBranches?: OwnBranch[];
|
|
112
174
|
}
|
|
113
175
|
|
|
114
176
|
export type RebindPlan =
|
|
@@ -117,8 +179,14 @@ export type RebindPlan =
|
|
|
117
179
|
| { kind: "none" }
|
|
118
180
|
/** The binding alone rules it out; nothing on disk is consulted. */
|
|
119
181
|
| { kind: "refuse"; refused: RebindRefused }
|
|
120
|
-
/** The binding allows it; the tree decides
|
|
121
|
-
|
|
182
|
+
/** The binding allows it and has a live tree; the tree decides
|
|
183
|
+
* (`rebindVerdict`). `own`: the thread's own runs pushed the branch, so a
|
|
184
|
+
* tree that turns out missing may still be recreated at it. */
|
|
185
|
+
| { kind: "measure"; from: string; to: string; pr: number; own: boolean }
|
|
186
|
+
/** The binding allows it, its tree was evicted, and the thread's own runs
|
|
187
|
+
* pushed the branch: the binding moves and the attach recreates the tree
|
|
188
|
+
* at the branch — once the mirror is known to hold it. */
|
|
189
|
+
| { kind: "recreate"; from: string; to: string; pr: number };
|
|
122
190
|
|
|
123
191
|
export function rebindRefused(plan: { to: string; pr: number }, reason: RebindRefusal, why: string): RebindRefused {
|
|
124
192
|
return { to: plan.to, pr: plan.pr, reason, why };
|
|
@@ -157,17 +225,19 @@ export function rebindPlan(input: {
|
|
|
157
225
|
),
|
|
158
226
|
};
|
|
159
227
|
}
|
|
228
|
+
const own = isOwnBranch(binding, plan.to);
|
|
160
229
|
if (binding.evicted || !binding.user) {
|
|
230
|
+
if (own) return { kind: "recreate", from: binding.ref, ...plan };
|
|
161
231
|
return {
|
|
162
232
|
kind: "refuse",
|
|
163
233
|
refused: rebindRefused(
|
|
164
234
|
plan,
|
|
165
235
|
"branch-absent",
|
|
166
|
-
|
|
236
|
+
`the thread's worktree was evicted and none of its runs pushed ${JSON.stringify(plan.to)}; only a branch this thread's own run pushed moves it`,
|
|
167
237
|
),
|
|
168
238
|
};
|
|
169
239
|
}
|
|
170
|
-
return { kind: "measure", from: binding.ref, ...plan };
|
|
240
|
+
return { kind: "measure", from: binding.ref, ...plan, own };
|
|
171
241
|
}
|
|
172
242
|
|
|
173
243
|
/** What the attach measured about the thread's tree, as the thread user. Each
|
|
@@ -185,17 +255,24 @@ export interface RebindTreeFacts {
|
|
|
185
255
|
dirty?: boolean;
|
|
186
256
|
}
|
|
187
257
|
|
|
188
|
-
export type RebindVerdict =
|
|
258
|
+
export type RebindVerdict =
|
|
259
|
+
/** Check the branch out in the existing tree. */
|
|
260
|
+
| { kind: "rebind" }
|
|
261
|
+
/** The tree is gone (a slept container) and the thread's own runs pushed the
|
|
262
|
+
* branch: move the binding and let the attach recreate the tree at it. */
|
|
263
|
+
| { kind: "recreate" }
|
|
264
|
+
| { kind: "refuse"; refused: RebindRefused };
|
|
189
265
|
|
|
190
266
|
/** The tree's verdict on a measured plan. */
|
|
191
|
-
export function rebindVerdict(plan: { to: string; pr: number }, tree: RebindTreeFacts): RebindVerdict {
|
|
267
|
+
export function rebindVerdict(plan: { to: string; pr: number; own?: boolean }, tree: RebindTreeFacts): RebindVerdict {
|
|
192
268
|
if (!tree.exists) {
|
|
269
|
+
if (plan.own === true) return { kind: "recreate" };
|
|
193
270
|
return {
|
|
194
271
|
kind: "refuse",
|
|
195
272
|
refused: rebindRefused(
|
|
196
273
|
plan,
|
|
197
274
|
"branch-absent",
|
|
198
|
-
|
|
275
|
+
`the thread's worktree is missing and none of its runs pushed ${JSON.stringify(plan.to)}; the branch cannot be verified there`,
|
|
199
276
|
),
|
|
200
277
|
};
|
|
201
278
|
}
|
|
@@ -90,16 +90,6 @@ export function isFleetBusyError(err: unknown): boolean {
|
|
|
90
90
|
);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
/** The 0.12.x Durable Object's answer while its container is still booting:
|
|
94
|
-
* no session exists yet and nothing ran, so the SAME request can be re-sent
|
|
95
|
-
* after a short pause — the one retry the Worker still does itself. */
|
|
96
|
-
export const CONTAINER_STARTING_PATTERN = /^Container is starting\. Please retry in a moment\.?$/i;
|
|
97
|
-
|
|
98
|
-
export function isContainerStarting(err: unknown): boolean {
|
|
99
|
-
const { message } = thrownShape(err);
|
|
100
|
-
return !!message && CONTAINER_STARTING_PATTERN.test(message.trim());
|
|
101
|
-
}
|
|
102
|
-
|
|
103
93
|
/** The Worker's answer on /read and /write (sent as HTTP 503): the named
|
|
104
94
|
* reason plus an `error` that keeps the SDK's own message as the cause, so
|
|
105
95
|
* the logs and the model can still see what the platform actually said. */
|
|
@@ -160,35 +150,21 @@ export function thrownText(shape: ThrownShape): string {
|
|
|
160
150
|
|
|
161
151
|
// ---- A runtime that did not answer (docs/reference/specs/execution.md item 9) ----
|
|
162
152
|
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// server exited
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
// on. The Worker reads the body first and names the condition instead.
|
|
153
|
+
// Every command and file operation reaches the container through the SDK's
|
|
154
|
+
// control connection to the container's port. When nothing answers there —
|
|
155
|
+
// the SDK's server exited, or the image's PID 1 is starting it again — the
|
|
156
|
+
// SDK's connect aborts after 30 s with a bare `The operation was aborted`:
|
|
157
|
+
// no container, no cause, nothing a card can act on. The Durable Object
|
|
158
|
+
// names the condition instead, with the facts a reader needs.
|
|
170
159
|
|
|
171
160
|
/** The named reason the Worker answers with, like `fleet-busy`: a machine
|
|
172
|
-
* token the executor
|
|
161
|
+
* token the executor matches on, never the SDK's text. */
|
|
173
162
|
export const RUNTIME_UNREACHABLE_REASON = "runtime-unreachable" as const;
|
|
174
163
|
|
|
175
164
|
/** The name the Worker's typed error carries across the Durable Object RPC
|
|
176
165
|
* boundary (which keeps `name`/`message` and drops the prototype). */
|
|
177
166
|
export const RUNTIME_UNREACHABLE_ERROR_NAME = "SandboxRuntimeUnreachableError";
|
|
178
167
|
|
|
179
|
-
/** The base class's two plain-text 500 bodies for a failed proxy to the
|
|
180
|
-
* container's port: the fetch itself failed (nothing listening — the server
|
|
181
|
-
* exited, or has not come back yet), and a connection lost mid-request. A
|
|
182
|
-
* JSON 500 from the server itself is neither: that server was alive. */
|
|
183
|
-
const PROXY_FAILURE_BODIES: readonly RegExp[] = [
|
|
184
|
-
/^Error proxying request to container\b/,
|
|
185
|
-
/^Container suddenly disconnected\b/,
|
|
186
|
-
];
|
|
187
|
-
|
|
188
|
-
export function isRuntimeProxyFailure(status: number, body: string): boolean {
|
|
189
|
-
return status === 500 && PROXY_FAILURE_BODIES.some((re) => re.test(body.trim()));
|
|
190
|
-
}
|
|
191
|
-
|
|
192
168
|
export interface RuntimeUnreachableFacts {
|
|
193
169
|
/** The Durable Object's id — the same word the `containers` log dataset carries as the container id. */
|
|
194
170
|
containerId: string;
|
|
@@ -196,7 +172,7 @@ export interface RuntimeUnreachableFacts {
|
|
|
196
172
|
running: boolean | undefined;
|
|
197
173
|
/** The Worker's `@cloudflare/sandbox` pin, which is also the image tag. */
|
|
198
174
|
sdkVersion: string;
|
|
199
|
-
/** The
|
|
175
|
+
/** The SDK's own text, verbatim: what it saw. */
|
|
200
176
|
cause: string;
|
|
201
177
|
}
|
|
202
178
|
|
|
@@ -209,13 +185,13 @@ export function runtimeUnreachableMessage(f: RuntimeUnreachableFacts): string {
|
|
|
209
185
|
return (
|
|
210
186
|
`${RUNTIME_UNREACHABLE_REASON}: the sandbox container's runtime did not answer ` +
|
|
211
187
|
`(container ${f.containerId}, sandbox SDK ${f.sdkVersion}; the platform reports the container ${platform}) — ` +
|
|
212
|
-
"
|
|
213
|
-
|
|
188
|
+
"nothing ran; if the container still runs, /workspace is intact and its runtime is being started again: " +
|
|
189
|
+
`wait a moment, then retry (${f.cause.trim() || "no detail from the SDK"})`
|
|
214
190
|
);
|
|
215
191
|
}
|
|
216
192
|
|
|
217
|
-
/** The Worker's typed error for a
|
|
218
|
-
*
|
|
193
|
+
/** The Worker's typed error for a silent control port: built inside the
|
|
194
|
+
* Durable Object with its facts, read by the fetch handler on the other side
|
|
219
195
|
* of the RPC boundary, so it is matched by name and by its message token,
|
|
220
196
|
* never by `instanceof`. */
|
|
221
197
|
export class SandboxRuntimeUnreachableError extends Error {
|
|
@@ -245,8 +221,8 @@ export function runtimeUnreachableAnswer(message: string): {
|
|
|
245
221
|
|
|
246
222
|
/** The `/exec` answer, in-body under the streamed HTTP 200 like every other exec
|
|
247
223
|
* failure: the dual `error` + exit-127/stderr shape (item 3) plus the reason.
|
|
248
|
-
* Never re-sent by anyone:
|
|
249
|
-
*
|
|
224
|
+
* Never re-sent by anyone: the executor re-sends nothing in-body, and the
|
|
225
|
+
* text tells the model to wait, then retry. */
|
|
250
226
|
export function runtimeUnreachableExecAnswer(message: string): {
|
|
251
227
|
error: string;
|
|
252
228
|
reason: typeof RUNTIME_UNREACHABLE_REASON;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// The per-thread sandbox's lifecycle facts the Worker and the bot share
|
|
2
|
+
// (docs/reference/specs/execution.md items 1, 2 and 9): how long an idle
|
|
3
|
+
// container stays warm, and how a container replaced or restarted under a
|
|
4
|
+
// command is recognized and named. Deliberately free of node: imports so
|
|
5
|
+
// wrangler can bundle it into the sandbox Worker.
|
|
6
|
+
|
|
7
|
+
/** How long an IDLE container stays warm before the Durable Object stops it,
|
|
8
|
+
* in the Container class's own `<n>[smh]` grammar. Idle means idle: the SDK
|
|
9
|
+
* renews the activity timeout every second while a command's stream is open
|
|
10
|
+
* (its control connection's busy poll), so a running command never counts
|
|
11
|
+
* toward it. 5 minutes frees a finished thread's slot (`max_instances`)
|
|
12
|
+
* sooner than the SDK default (10 min), while a follow-up inside 5 minutes
|
|
13
|
+
* still lands on the same warm workspace; a later one re-clones, which is the
|
|
14
|
+
* documented per-thread degradation (item 1). */
|
|
15
|
+
export const SANDBOX_SLEEP_AFTER = "5m";
|
|
16
|
+
|
|
17
|
+
/** The texts the SDK produces when the container is torn down under a
|
|
18
|
+
* command, across generations. 0.3.x: the exec handler's generic wrapper (its
|
|
19
|
+
* real cause, "Session terminated", sat in a field the client discarded), the
|
|
20
|
+
* cause itself, and the stale-session answer the same attempt got once the
|
|
21
|
+
* sessions were cleared. 0.12.x: the typed `SessionTerminatedError` text
|
|
22
|
+
* (`Session '<id>' shell exited (exit code: <n>)`) and the
|
|
23
|
+
* `OperationInterruptedError` text for a container that stopped under a
|
|
24
|
+
* pending call, and the disconnect text for a sandbox `destroy()`ed under a
|
|
25
|
+
* pending call. Anything else — a transport error, a file-op failure — is
|
|
26
|
+
* never recycle-shaped, whenever it arrives. */
|
|
27
|
+
const RECYCLE_SHAPED: readonly RegExp[] = [
|
|
28
|
+
/^Command execution failed$/,
|
|
29
|
+
/^Session terminated$/i,
|
|
30
|
+
/^Session '[^']*' not found$/i,
|
|
31
|
+
/^Session '[^']*' shell exited \(exit code: -?\d+\)$/i,
|
|
32
|
+
/^The sandbox container stopped while the operation was pending\.?$/i,
|
|
33
|
+
/^The sandbox was destroyed while the operation was pending\.?$/i,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/** The typed errors that MEAN the container's runtime went away under the
|
|
37
|
+
* call, across the 0.12 and 0.13 lines. Matched by name, not `instanceof`:
|
|
38
|
+
* the fetch handler sees them after the Durable Object RPC boundary, which
|
|
39
|
+
* keeps `name`/`message` and drops the prototype (inside the Durable Object,
|
|
40
|
+
* `instanceof` holds and decides first). */
|
|
41
|
+
export const RECYCLE_ERROR_NAMES: readonly string[] = [
|
|
42
|
+
"SessionTerminatedError",
|
|
43
|
+
"OperationInterruptedError",
|
|
44
|
+
"StaleProcessHandleError",
|
|
45
|
+
"RuntimeIdentityInactiveError",
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/** Type first, text second: a typed recycle error, or a recycle-shaped text. */
|
|
49
|
+
export function isRecycleError(err: { name?: string; message?: string }): boolean {
|
|
50
|
+
if (err.name && RECYCLE_ERROR_NAMES.includes(err.name)) return true;
|
|
51
|
+
return !!err.message && RECYCLE_SHAPED.some((re) => re.test(err.message!.trim()));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Grace inside which a recycle-shaped TEXT is taken at face value: a session
|
|
55
|
+
* that fails to start does so in seconds, not minutes. A typed recycle error
|
|
56
|
+
* needs no grace — the SDK is stating the runtime went away. */
|
|
57
|
+
const RECYCLE_SUSPECT_AFTER_MS = 60_000;
|
|
58
|
+
|
|
59
|
+
/** The message `/exec` puts in-body when a command's failure looks like the
|
|
60
|
+
* container's runtime went away under it: a typed recycle error (`certain`),
|
|
61
|
+
* or a recycle-shaped text that arrived more than a minute into THIS attempt
|
|
62
|
+
* (a startup failure shows in seconds). Any other text, however late, is
|
|
63
|
+
* returned unchanged — timing alone never rewords an unrelated error. The
|
|
64
|
+
* exit code stays 127: it IS an infra failure and the command did not finish,
|
|
65
|
+
* so a faked exit 124 would tell the model to shorten a command that was
|
|
66
|
+
* never the problem. What the workspace holds afterwards depends on what
|
|
67
|
+
* went away: a replaced container has an empty `/workspace` (re-clone); a
|
|
68
|
+
* runtime the image's PID 1 started again (item 21) left it intact. The text
|
|
69
|
+
* says to look before assuming either. */
|
|
70
|
+
export function recycledMidCommandMessage(elapsedMs: number, msg: string, certain = false): string {
|
|
71
|
+
const shaped = RECYCLE_SHAPED.some((re) => re.test(msg.trim()));
|
|
72
|
+
if (!certain && (!shaped || elapsedMs <= RECYCLE_SUSPECT_AFTER_MS)) return msg;
|
|
73
|
+
const secs = Math.round(elapsedMs / 1_000);
|
|
74
|
+
return (
|
|
75
|
+
`sandbox recycled mid-command after ${secs}s — the container's runtime was replaced or restarted under the command, which did not finish; ` +
|
|
76
|
+
`check /workspace before continuing: it is empty if the container was replaced (re-clone), intact if only its runtime restarted (${msg})`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"src": "../node_modules/@fontsource-variable/jetbrains-mono/files/jetbrains-mono-vietnamese-wght-normal.woff2"
|
|
29
29
|
},
|
|
30
30
|
"../node_modules/@pierre/diffs/dist/index.js": {
|
|
31
|
-
"file": "assets/dist-
|
|
31
|
+
"file": "assets/dist-BnwSD1cL.js",
|
|
32
32
|
"name": "dist",
|
|
33
33
|
"src": "../node_modules/@pierre/diffs/dist/index.js",
|
|
34
34
|
"isDynamicEntry": true,
|
|
@@ -2562,16 +2562,16 @@
|
|
|
2562
2562
|
"_seed-DeKSHrt2.js"
|
|
2563
2563
|
]
|
|
2564
2564
|
},
|
|
2565
|
-
"_StatusDot-
|
|
2566
|
-
"file": "assets/StatusDot-
|
|
2565
|
+
"_StatusDot-DDc88Kbs.js": {
|
|
2566
|
+
"file": "assets/StatusDot-DDc88Kbs.js",
|
|
2567
2567
|
"name": "StatusDot",
|
|
2568
2568
|
"imports": [
|
|
2569
2569
|
"_seed-DeKSHrt2.js",
|
|
2570
|
-
"_Tooltip-
|
|
2570
|
+
"_Tooltip-CBapNhsh.js"
|
|
2571
2571
|
]
|
|
2572
2572
|
},
|
|
2573
|
-
"_Tooltip-
|
|
2574
|
-
"file": "assets/Tooltip-
|
|
2573
|
+
"_Tooltip-CBapNhsh.js": {
|
|
2574
|
+
"file": "assets/Tooltip-CBapNhsh.js",
|
|
2575
2575
|
"name": "Tooltip",
|
|
2576
2576
|
"imports": [
|
|
2577
2577
|
"_AppShell-lYVcj-k7.js",
|
|
@@ -2789,7 +2789,7 @@
|
|
|
2789
2789
|
]
|
|
2790
2790
|
},
|
|
2791
2791
|
"src/main.ts": {
|
|
2792
|
-
"file": "assets/main-
|
|
2792
|
+
"file": "assets/main-ZhQGbZ2E.js",
|
|
2793
2793
|
"name": "main",
|
|
2794
2794
|
"src": "src/main.ts",
|
|
2795
2795
|
"isEntry": true,
|
|
@@ -2841,19 +2841,19 @@
|
|
|
2841
2841
|
]
|
|
2842
2842
|
},
|
|
2843
2843
|
"src/pages/ResidentDetailPage.vue": {
|
|
2844
|
-
"file": "assets/ResidentDetailPage-
|
|
2844
|
+
"file": "assets/ResidentDetailPage-B1Q9pabX.js",
|
|
2845
2845
|
"name": "ResidentDetailPage",
|
|
2846
2846
|
"src": "src/pages/ResidentDetailPage.vue",
|
|
2847
2847
|
"isDynamicEntry": true,
|
|
2848
2848
|
"imports": [
|
|
2849
2849
|
"_AppShell-lYVcj-k7.js",
|
|
2850
2850
|
"_seed-DeKSHrt2.js",
|
|
2851
|
-
"_StatusDot-
|
|
2851
|
+
"_StatusDot-DDc88Kbs.js",
|
|
2852
2852
|
"_residentDiskBudget-BMBKlYRH.js"
|
|
2853
2853
|
]
|
|
2854
2854
|
},
|
|
2855
2855
|
"src/pages/ResidentsIndexPage.vue": {
|
|
2856
|
-
"file": "assets/ResidentsIndexPage-
|
|
2856
|
+
"file": "assets/ResidentsIndexPage-CP7U_4aK.js",
|
|
2857
2857
|
"name": "ResidentsIndexPage",
|
|
2858
2858
|
"src": "src/pages/ResidentsIndexPage.vue",
|
|
2859
2859
|
"isDynamicEntry": true,
|
|
@@ -2861,20 +2861,20 @@
|
|
|
2861
2861
|
"_AppShell-lYVcj-k7.js",
|
|
2862
2862
|
"_seed-DeKSHrt2.js",
|
|
2863
2863
|
"_wallClock-61NpVkY6.js",
|
|
2864
|
-
"_StatusDot-
|
|
2864
|
+
"_StatusDot-DDc88Kbs.js",
|
|
2865
2865
|
"_residentDiskBudget-BMBKlYRH.js",
|
|
2866
2866
|
"_indexFormat-B-pd4r7Y.js"
|
|
2867
2867
|
]
|
|
2868
2868
|
},
|
|
2869
2869
|
"src/pages/RunRoutePage.vue": {
|
|
2870
|
-
"file": "assets/RunRoutePage-
|
|
2870
|
+
"file": "assets/RunRoutePage-dCC25f_b.js",
|
|
2871
2871
|
"name": "RunRoutePage",
|
|
2872
2872
|
"src": "src/pages/RunRoutePage.vue",
|
|
2873
2873
|
"isDynamicEntry": true,
|
|
2874
2874
|
"imports": [
|
|
2875
2875
|
"_AppShell-lYVcj-k7.js",
|
|
2876
2876
|
"_seed-DeKSHrt2.js",
|
|
2877
|
-
"_Tooltip-
|
|
2877
|
+
"_Tooltip-CBapNhsh.js",
|
|
2878
2878
|
"src/main.ts",
|
|
2879
2879
|
"_wallClock-61NpVkY6.js",
|
|
2880
2880
|
"_NotFoundPage-BzWS4Ca1.js",
|
|
@@ -2890,31 +2890,31 @@
|
|
|
2890
2890
|
]
|
|
2891
2891
|
},
|
|
2892
2892
|
"src/pages/RunsIndexPage.vue": {
|
|
2893
|
-
"file": "assets/RunsIndexPage-
|
|
2893
|
+
"file": "assets/RunsIndexPage-Cgp4t4C8.js",
|
|
2894
2894
|
"name": "RunsIndexPage",
|
|
2895
2895
|
"src": "src/pages/RunsIndexPage.vue",
|
|
2896
2896
|
"isDynamicEntry": true,
|
|
2897
2897
|
"imports": [
|
|
2898
2898
|
"_AppShell-lYVcj-k7.js",
|
|
2899
2899
|
"_seed-DeKSHrt2.js",
|
|
2900
|
-
"_Tooltip-
|
|
2900
|
+
"_Tooltip-CBapNhsh.js",
|
|
2901
2901
|
"_wallClock-61NpVkY6.js",
|
|
2902
2902
|
"_RunsTabs-DEICQ4FY.js",
|
|
2903
|
-
"_StatusDot-
|
|
2903
|
+
"_StatusDot-DDc88Kbs.js",
|
|
2904
2904
|
"_indexFormat-B-pd4r7Y.js",
|
|
2905
2905
|
"_favicon-CWPcvWvp.js",
|
|
2906
2906
|
"_localIso-L06jV29p.js"
|
|
2907
2907
|
]
|
|
2908
2908
|
},
|
|
2909
2909
|
"src/pages/ScheduledPage.vue": {
|
|
2910
|
-
"file": "assets/ScheduledPage-
|
|
2910
|
+
"file": "assets/ScheduledPage-DthDA2xG.js",
|
|
2911
2911
|
"name": "ScheduledPage",
|
|
2912
2912
|
"src": "src/pages/ScheduledPage.vue",
|
|
2913
2913
|
"isDynamicEntry": true,
|
|
2914
2914
|
"imports": [
|
|
2915
2915
|
"_AppShell-lYVcj-k7.js",
|
|
2916
2916
|
"_seed-DeKSHrt2.js",
|
|
2917
|
-
"_Tooltip-
|
|
2917
|
+
"_Tooltip-CBapNhsh.js",
|
|
2918
2918
|
"_wallClock-61NpVkY6.js",
|
|
2919
2919
|
"_RunsTabs-DEICQ4FY.js",
|
|
2920
2920
|
"_indexFormat-B-pd4r7Y.js",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as ee,on as s,r as c,sn as l,un as u,ur as d,vi as f,wi as p,yn as te}from"./seed-DeKSHrt2.js";import{t as m}from"./StatusDot-CFXbAw7S.js";import{a as ne,c as re,d as ie,f as h,i as g,l as ae,n as oe,o as se,r as ce,s as _,t as le,u as ue}from"./residentDiskBudget-BMBKlYRH.js";var de={class:`mt-4 first:mt-0`},fe={class:`w-full border-collapse font-mono text-[0.8125rem]`},pe={class:`border-t border-muted`},me={class:`px-2 py-1 align-top`},v={class:`ml-1.5 font-medium`},y={class:`border-t border-muted`},b={class:`break-all px-2 py-1 align-top`},x={key:0},S={key:1,class:`text-dimmed`},C={class:`border-t border-muted`},w={class:`break-all px-2 py-1 align-top`},T={key:0},E={key:1,class:`text-dimmed`},D={class:`border-t border-muted`},O={class:`break-all px-2 py-1 align-top`},k={key:0},A={key:1,class:`text-dimmed`},j={class:`border-t border-muted`},M={class:`break-all px-2 py-1 align-top`},N={key:0},P={key:1,class:`text-dimmed`},F={class:`border-t border-muted`},I={class:`break-all px-2 py-1 align-top`},L={key:1,class:`text-dimmed`},R={class:`mt-4`},z={class:`w-full border-collapse font-mono text-[0.8125rem]`},he={class:`border-t border-muted`},ge={class:`break-all px-2 py-1 align-top`},_e=[`href`],ve={key:1},ye={class:`border-t border-muted`},be={class:`break-all px-2 py-1 align-top`},xe={class:`border-t border-muted`},Se={class:`break-all px-2 py-1 align-top`},Ce=[`href`],we={key:1},Te={key:2,class:`text-dimmed`},Ee={class:`border-t border-muted`},De={class:`break-all px-2 py-1 align-top`},Oe={key:0},ke={key:1,class:`text-dimmed`},Ae={class:`border-t border-muted`},je={class:`break-all px-2 py-1 align-top`},Me={key:0},Ne={key:1,class:`text-dimmed`},Pe={class:`border-t border-muted`},Fe={class:`break-all px-2 py-1 align-top`},Ie={key:0},Le={key:1,class:`text-dimmed`},Re={class:`mt-4`},ze={class:`w-full border-collapse font-mono text-[0.8125rem]`},Be={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ve={class:`break-all px-2 py-1 align-top`},He={class:`w-full border-collapse font-mono text-[0.8125rem]`},Ue={class:`w-32 break-all px-2 py-1 align-top text-muted sm:w-96 sm:break-words`},We={class:`px-2 py-1 align-top`},Ge={key:1,class:`text-xs text-muted`},Ke={class:`mt-4`},qe={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Je={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ye={class:`break-all px-2 py-1 align-top`},Xe={key:0},B={key:1,class:`text-dimmed`},Ze={key:1,class:`text-xs text-muted`},Qe={class:`mt-4`},$e={class:`mb-1 text-xs text-muted`},et={class:`overflow-x-auto`},tt={class:`w-full border-collapse font-mono text-[0.8125rem]`},nt={class:`break-all px-2 py-1 align-top`},rt={key:0,class:`text-xs text-muted`},it={class:`break-all px-2 py-1 align-top`},at=[`href`],ot={key:1},st={key:2,class:`text-dimmed`},ct={class:`break-all px-2 py-1 align-top`},lt={key:0},ut={key:1,class:`text-dimmed`},dt={key:2},ft={key:3,class:`text-dimmed`},pt={class:`break-all px-2 py-1 align-top`},mt={key:0},ht={key:1,class:`text-dimmed`},gt={key:2},_t={key:3,class:`text-dimmed`},vt={key:1,class:`text-xs text-muted`},yt={class:`mt-4`},bt={class:`w-full border-collapse font-mono text-[0.8125rem]`},xt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},St={class:`px-2 py-1 align-top`},Ct={class:`mt-4`},wt={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Tt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Et={class:`break-all px-2 py-1 align-top`},Dt={class:`text-xs text-muted`},Ot={key:1,class:`text-xs text-muted`},kt={class:`mt-4`},At={class:`w-full border-collapse font-mono text-[0.8125rem]`},jt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Mt={class:`break-all px-2 py-1 align-top`},Nt={key:0},Pt={key:1,class:`text-dimmed`},Ft={class:`mt-4 text-xs text-muted`},It={class:`rounded bg-elevated px-1 py-0.5`},Lt={class:`rounded bg-elevated px-1 py-0.5`},Rt={class:`rounded bg-elevated px-1 py-0.5`},V=te({__name:`ResidentDetailPage`,setup(te){let V=c(`resident`),H=s(()=>V?.record??{}),U=s(()=>ae(H.value)),W=s(()=>ue(H.value)||(V?.slug??``)),G=s(()=>h(U.value.sha)),K=s(()=>se.test(W.value)?`https://github.com/${W.value}`:void 0),q=s(()=>K.value&&/^[0-9a-f]{7,40}$/.test(G.value)?`${K.value}/commit/${G.value}`:void 0),J=s(()=>{let e=U.value.snapshot;return e&&typeof e==`object`?_(e):void 0}),zt=s(()=>_(U.value.schedules)),Y=s(()=>{let e=_(H.value.commands),t=_(H.value.effects);return Object.keys(e).sort().map(n=>({name:n,command:h(e[n]),effect:h(t[n])||`readonly`}))}),X=s(()=>{let e=U.value.threads;return(Array.isArray(e)?e.map(_):[]).map(e=>{let t=h(e.sha);return{threadKey:h(e.threadKey)||`?`,ref:h(e.ref)||`?`,sha:t?t.slice(0,8):``,commitHref:K.value&&/^[0-9a-f]{7,40}$/.test(t)?`${K.value}/commit/${t}`:void 0,user:h(e.user),deps:h(e.deps),boundAt:h(e.boundAt),lastAttachAt:h(e.lastAttachAt),evicted:e.evicted===!0,evictedAt:h(e.evictedAt),evictedWhy:h(e.evictedWhy)}}).sort((e,t)=>t.lastAttachAt.localeCompare(e.lastAttachAt))}),Z=s(()=>X.value.filter(e=>!e.evicted).length),Q=s(()=>{let e=U.value.lastRestore;return e?JSON.stringify(e):``}),$=s(()=>re(H.value)),Bt=s(()=>typeof H.value.diskBudgetMb==`number`?H.value.diskBudgetMb:void 0),Vt=s(()=>{let e=$.value;if(!e)return[];let t=le(e),{freeKiB:n,capped:r,capacityKiB:i}=oe(e,Bt.value),a=n-t.totalKiB,o=t=>{let n=ne(e.parts,t);return n===null?`? (checkout not measured)`:n===0?`?`:`${Math.max(0,Math.floor(a/n))} more (${g(n)} each)`};return[[`used / total`,ce(e)],[`free`,`${g(n)}${r?` under the ${g(i)} diskBudgetMb cap`:``}`],[`reserve`,`${g(t.totalKiB)} (snapshot staging ${g(t.stagingKiB)} + floor ${g(t.floorKiB)})`],[`headroom`,`${g(Math.max(0,a))} — room for ${o(`hardlink`)} hardlinked trees, ${o(`reconcile`)} lockfile-diverged (reconciling)`],[`measured`,e.at||`—`]]}),Ht=s(()=>{let e=$.value;if(!e)return[];let t=[[`mirror`,g(e.parts.mirror)],[`checkout deps (node_modules)`,g(e.parts.deps)],[`checkout (history + tree + build)`,g(e.parts.checkout)]];for(let[n,r]of Object.entries(e.parts.threads).sort((e,t)=>t[1]-e[1]))t.push([`thread ${n}`,g(r)]);for(let[n,r]of Object.entries(e.parts.homes).sort((e,t)=>t[1]-e[1]))r>=1024&&t.push([`home ${n}`,g(r)]);return t.push([`other (image, /tmp, …)`,g(e.parts.other)]),t});return(s,c)=>(o(),i(e,{title:W.value||`Resident`,nav:`residents`},{leading:t(()=>[...c[0]||=[l(`a`,{class:`back text-sm text-muted no-underline hover:text-primary`,href:`/residents`},`← All residents`,-1)]]),default:t(()=>[l(`section`,de,[c[8]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Lifecycle`,-1),l(`table`,fe,[l(`tbody`,null,[l(`tr`,pe,[c[1]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state`,-1),l(`td`,me,[r(m,{tone:f(ie)(U.value.state),label:U.value.state},null,8,[`tone`,`label`]),l(`span`,v,p(U.value.state),1)])]),l(`tr`,y,[c[2]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`reason`,-1),l(`td`,b,[U.value.reason?(o(),u(`span`,x,p(U.value.reason),1)):(o(),u(`span`,S,`—`))])]),l(`tr`,C,[c[3]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh error`,-1),l(`td`,w,[f(h)(U.value.lastRefreshError)?(o(),u(`span`,T,p(f(h)(U.value.lastRefreshError)),1)):(o(),u(`span`,E,`—`))])]),l(`tr`,D,[c[4]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last restore`,-1),l(`td`,O,[Q.value?(o(),u(`span`,k,p(Q.value),1)):(o(),u(`span`,A,`—`))])]),l(`tr`,j,[c[5]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state updated`,-1),l(`td`,M,[f(h)(U.value.updatedAt)?(o(),u(`span`,N,p(f(h)(U.value.updatedAt)),1)):(o(),u(`span`,P,`—`))])]),l(`tr`,F,[c[7]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`idle since`,-1),l(`td`,I,[f(h)(U.value.idleSince)?(o(),u(n,{key:0},[a(p(f(h)(U.value.idleSince))+` `,1),c[6]||=l(`span`,{class:`text-xs text-muted`},`(refresh parked; container may sleep)`,-1)],64)):(o(),u(`span`,L,`awake`))])])])])]),l(`section`,R,[c[15]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pinned facts`,-1),l(`table`,z,[l(`tbody`,null,[l(`tr`,he,[c[9]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`repository`,-1),l(`td`,ge,[K.value?(o(),u(`a`,{key:0,class:`text-primary`,href:K.value},p(K.value),9,_e)):(o(),u(`span`,ve,p(f(h)(H.value.resource)||`—`),1))])]),l(`tr`,ye,[c[10]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`default ref`,-1),l(`td`,be,p(f(h)(U.value.defaultRef)||f(h)(H.value.defaultRef)||`—`),1)]),l(`tr`,xe,[c[11]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`pinned sha`,-1),l(`td`,Se,[q.value?(o(),u(`a`,{key:0,class:`text-primary`,href:q.value},p(G.value),9,Ce)):G.value?(o(),u(`span`,we,p(G.value),1)):(o(),u(`span`,Te,`—`))])]),l(`tr`,Ee,[c[12]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`lockfile hash`,-1),l(`td`,De,[f(h)(U.value.lockfileHash)?(o(),u(`span`,Oe,p(f(h)(U.value.lockfileHash)),1)):(o(),u(`span`,ke,`—`))])]),l(`tr`,Ae,[c[13]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`provisioned`,-1),l(`td`,je,[f(h)(U.value.provisionedAt)?(o(),u(`span`,Me,p(f(h)(U.value.provisionedAt)),1)):(o(),u(`span`,Ne,`—`))])]),l(`tr`,Pe,[c[14]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh`,-1),l(`td`,Fe,[f(h)(U.value.lastRefreshAt)?(o(),u(`span`,Ie,p(f(h)(U.value.lastRefreshAt)),1)):(o(),u(`span`,Le,`—`))])])])])]),l(`section`,Re,[c[17]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Disk`,-1),$.value?(o(),u(n,{key:0},[l(`table`,ze,[l(`tbody`,null,[(o(!0),u(n,null,d(Vt.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Be,p(e),1),l(`td`,Ve,p(t),1)]))),128))])]),c[16]||=l(`p`,{class:`mb-1 mt-2 text-xs text-muted`},` components (one du, hardlinks counted once — a thread tree shows only what it does not share with the checkout) `,-1),l(`table`,He,[l(`tbody`,null,[(o(!0),u(n,null,d(Ht.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Ue,p(e),1),l(`td`,We,p(t),1)]))),128))])])],64)):(o(),u(`p`,Ge,` not measured yet — the first refresh cycle or attach of this container measures it `))]),l(`section`,Ke,[c[18]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Snapshot stamp`,-1),J.value?(o(),u(`table`,qe,[l(`tbody`,null,[(o(),u(n,null,d([`ref`,`sha`,`lockfileHash`,`createdAt`,`mirrorBackupId`,`checkoutBackupId`],e=>l(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Je,p(e),1),l(`td`,Ye,[f(h)(J.value[e])?(o(),u(`span`,Xe,p(f(h)(J.value[e])),1)):(o(),u(`span`,B,`—`))])])),64))])])):(o(),u(`p`,Ze,`no snapshot recorded`))]),l(`section`,Qe,[c[22]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Thread worktrees`,-1),X.value.length>0?(o(),u(n,{key:0},[l(`p`,$e,p(Z.value)+` live · `+p(X.value.length-Z.value)+` evicted`,1),l(`div`,et,[l(`table`,tt,[l(`tbody`,null,[c[21]||=l(`tr`,{class:`text-xs text-muted`},[l(`td`,{class:`px-2 py-1`},`thread`),l(`td`,{class:`px-2 py-1`},`ref · sha`),l(`td`,{class:`px-2 py-1`},`user · deps`),l(`td`,{class:`px-2 py-1`},`bound · last attach`)],-1),(o(!0),u(n,null,d(X.value,e=>(o(),u(`tr`,{key:e.threadKey,class:`border-t border-muted`},[l(`td`,nt,[e.evicted?(o(),u(`span`,rt,[a(`evicted `+p(e.evictedAt||`—`),1),e.evictedWhy?(o(),u(n,{key:0},[a(` · `+p(e.evictedWhy),1)],64)):ee(``,!0)])):(o(),i(m,{key:1,tone:`green`,label:`live`,tip:`live`})),a(` `+p(e.threadKey),1)]),l(`td`,it,[a(p(e.ref)+` · `,1),e.commitHref?(o(),u(`a`,{key:0,class:`text-primary`,href:e.commitHref},p(e.sha),9,at)):e.sha?(o(),u(`span`,ot,p(e.sha),1)):(o(),u(`span`,st,`—`))]),l(`td`,ct,[e.user?(o(),u(`span`,lt,p(e.user),1)):(o(),u(`span`,ut,`—`)),c[19]||=a(` · `,-1),e.deps?(o(),u(`span`,dt,p(e.deps),1)):(o(),u(`span`,ft,`—`))]),l(`td`,pt,[e.boundAt?(o(),u(`span`,mt,p(e.boundAt),1)):(o(),u(`span`,ht,`—`)),c[20]||=a(` · `,-1),e.lastAttachAt?(o(),u(`span`,gt,p(e.lastAttachAt),1)):(o(),u(`span`,_t,`—`))])]))),128))])])])],64)):(o(),u(`p`,vt,`no thread worktrees`))]),l(`section`,yt,[c[23]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pending schedules`,-1),l(`table`,bt,[l(`tbody`,null,[(o(),u(n,null,d([[`refresh`,`refresh`],[`provision run`,`provisionRun`],[`provision deadline`,`provisionDeadline`]],([e,t])=>l(`tr`,{key:t,class:`border-t border-muted`},[l(`td`,xt,p(e),1),l(`td`,St,p(f(h)(zt.value[t]??0)||`0`),1)])),64))])])]),l(`section`,Ct,[c[25]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Command table`,-1),Y.value.length>0?(o(),u(`table`,wt,[l(`tbody`,null,[(o(!0),u(n,null,d(Y.value,e=>(o(),u(`tr`,{key:e.name,class:`border-t border-muted`},[l(`td`,Tt,p(e.name),1),l(`td`,Et,[l(`code`,null,p(e.command),1),c[24]||=a(),l(`span`,Dt,p(e.effect),1)])]))),128))])])):(o(),u(`p`,Ot,`no command table`))]),l(`section`,kt,[c[26]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Registry settings`,-1),l(`table`,At,[l(`tbody`,null,[(o(!0),u(n,null,d([[`onboarded`,f(h)(H.value.onboardedAt)],[`record updated`,f(h)(H.value.updatedAt)],[`provisioning timeout (ms)`,f(h)(H.value.provisioningTimeoutMs)],[`disk budget (MB)`,f(h)(H.value.diskBudgetMb)],[`worktree TTL (days)`,f(h)(H.value.worktreeTtlDays??7)]],([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,jt,p(e),1),l(`td`,Mt,[t?(o(),u(`span`,Nt,p(t),1)):(o(),u(`span`,Pt,`—`))])]))),128))])])]),l(`p`,Ft,[c[27]||=a(` Manage from chat: `,-1),l(`code`,It,`repo rebuild `+p(W.value),1),c[28]||=a(` · `,-1),l(`code`,Lt,`repo reconfigure `+p(W.value)+` …`,1),c[29]||=a(` · `,-1),l(`code`,Rt,`repo offboard `+p(W.value)+` --dry-run`,1)])]),_:1},8,[`title`]))}});export{V as default};
|
|
1
|
+
import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as ee,on as s,r as c,sn as l,un as u,ur as d,vi as f,wi as p,yn as te}from"./seed-DeKSHrt2.js";import{t as m}from"./StatusDot-DDc88Kbs.js";import{a as ne,c as re,d as ie,f as h,i as g,l as ae,n as oe,o as se,r as ce,s as _,t as le,u as ue}from"./residentDiskBudget-BMBKlYRH.js";var de={class:`mt-4 first:mt-0`},fe={class:`w-full border-collapse font-mono text-[0.8125rem]`},pe={class:`border-t border-muted`},me={class:`px-2 py-1 align-top`},v={class:`ml-1.5 font-medium`},y={class:`border-t border-muted`},b={class:`break-all px-2 py-1 align-top`},x={key:0},S={key:1,class:`text-dimmed`},C={class:`border-t border-muted`},w={class:`break-all px-2 py-1 align-top`},T={key:0},E={key:1,class:`text-dimmed`},D={class:`border-t border-muted`},O={class:`break-all px-2 py-1 align-top`},k={key:0},A={key:1,class:`text-dimmed`},j={class:`border-t border-muted`},M={class:`break-all px-2 py-1 align-top`},N={key:0},P={key:1,class:`text-dimmed`},F={class:`border-t border-muted`},I={class:`break-all px-2 py-1 align-top`},L={key:1,class:`text-dimmed`},R={class:`mt-4`},z={class:`w-full border-collapse font-mono text-[0.8125rem]`},he={class:`border-t border-muted`},ge={class:`break-all px-2 py-1 align-top`},_e=[`href`],ve={key:1},ye={class:`border-t border-muted`},be={class:`break-all px-2 py-1 align-top`},xe={class:`border-t border-muted`},Se={class:`break-all px-2 py-1 align-top`},Ce=[`href`],we={key:1},Te={key:2,class:`text-dimmed`},Ee={class:`border-t border-muted`},De={class:`break-all px-2 py-1 align-top`},Oe={key:0},ke={key:1,class:`text-dimmed`},Ae={class:`border-t border-muted`},je={class:`break-all px-2 py-1 align-top`},Me={key:0},Ne={key:1,class:`text-dimmed`},Pe={class:`border-t border-muted`},Fe={class:`break-all px-2 py-1 align-top`},Ie={key:0},Le={key:1,class:`text-dimmed`},Re={class:`mt-4`},ze={class:`w-full border-collapse font-mono text-[0.8125rem]`},Be={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ve={class:`break-all px-2 py-1 align-top`},He={class:`w-full border-collapse font-mono text-[0.8125rem]`},Ue={class:`w-32 break-all px-2 py-1 align-top text-muted sm:w-96 sm:break-words`},We={class:`px-2 py-1 align-top`},Ge={key:1,class:`text-xs text-muted`},Ke={class:`mt-4`},qe={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Je={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Ye={class:`break-all px-2 py-1 align-top`},Xe={key:0},B={key:1,class:`text-dimmed`},Ze={key:1,class:`text-xs text-muted`},Qe={class:`mt-4`},$e={class:`mb-1 text-xs text-muted`},et={class:`overflow-x-auto`},tt={class:`w-full border-collapse font-mono text-[0.8125rem]`},nt={class:`break-all px-2 py-1 align-top`},rt={key:0,class:`text-xs text-muted`},it={class:`break-all px-2 py-1 align-top`},at=[`href`],ot={key:1},st={key:2,class:`text-dimmed`},ct={class:`break-all px-2 py-1 align-top`},lt={key:0},ut={key:1,class:`text-dimmed`},dt={key:2},ft={key:3,class:`text-dimmed`},pt={class:`break-all px-2 py-1 align-top`},mt={key:0},ht={key:1,class:`text-dimmed`},gt={key:2},_t={key:3,class:`text-dimmed`},vt={key:1,class:`text-xs text-muted`},yt={class:`mt-4`},bt={class:`w-full border-collapse font-mono text-[0.8125rem]`},xt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},St={class:`px-2 py-1 align-top`},Ct={class:`mt-4`},wt={key:0,class:`w-full border-collapse font-mono text-[0.8125rem]`},Tt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Et={class:`break-all px-2 py-1 align-top`},Dt={class:`text-xs text-muted`},Ot={key:1,class:`text-xs text-muted`},kt={class:`mt-4`},At={class:`w-full border-collapse font-mono text-[0.8125rem]`},jt={class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},Mt={class:`break-all px-2 py-1 align-top`},Nt={key:0},Pt={key:1,class:`text-dimmed`},Ft={class:`mt-4 text-xs text-muted`},It={class:`rounded bg-elevated px-1 py-0.5`},Lt={class:`rounded bg-elevated px-1 py-0.5`},Rt={class:`rounded bg-elevated px-1 py-0.5`},V=te({__name:`ResidentDetailPage`,setup(te){let V=c(`resident`),H=s(()=>V?.record??{}),U=s(()=>ae(H.value)),W=s(()=>ue(H.value)||(V?.slug??``)),G=s(()=>h(U.value.sha)),K=s(()=>se.test(W.value)?`https://github.com/${W.value}`:void 0),q=s(()=>K.value&&/^[0-9a-f]{7,40}$/.test(G.value)?`${K.value}/commit/${G.value}`:void 0),J=s(()=>{let e=U.value.snapshot;return e&&typeof e==`object`?_(e):void 0}),zt=s(()=>_(U.value.schedules)),Y=s(()=>{let e=_(H.value.commands),t=_(H.value.effects);return Object.keys(e).sort().map(n=>({name:n,command:h(e[n]),effect:h(t[n])||`readonly`}))}),X=s(()=>{let e=U.value.threads;return(Array.isArray(e)?e.map(_):[]).map(e=>{let t=h(e.sha);return{threadKey:h(e.threadKey)||`?`,ref:h(e.ref)||`?`,sha:t?t.slice(0,8):``,commitHref:K.value&&/^[0-9a-f]{7,40}$/.test(t)?`${K.value}/commit/${t}`:void 0,user:h(e.user),deps:h(e.deps),boundAt:h(e.boundAt),lastAttachAt:h(e.lastAttachAt),evicted:e.evicted===!0,evictedAt:h(e.evictedAt),evictedWhy:h(e.evictedWhy)}}).sort((e,t)=>t.lastAttachAt.localeCompare(e.lastAttachAt))}),Z=s(()=>X.value.filter(e=>!e.evicted).length),Q=s(()=>{let e=U.value.lastRestore;return e?JSON.stringify(e):``}),$=s(()=>re(H.value)),Bt=s(()=>typeof H.value.diskBudgetMb==`number`?H.value.diskBudgetMb:void 0),Vt=s(()=>{let e=$.value;if(!e)return[];let t=le(e),{freeKiB:n,capped:r,capacityKiB:i}=oe(e,Bt.value),a=n-t.totalKiB,o=t=>{let n=ne(e.parts,t);return n===null?`? (checkout not measured)`:n===0?`?`:`${Math.max(0,Math.floor(a/n))} more (${g(n)} each)`};return[[`used / total`,ce(e)],[`free`,`${g(n)}${r?` under the ${g(i)} diskBudgetMb cap`:``}`],[`reserve`,`${g(t.totalKiB)} (snapshot staging ${g(t.stagingKiB)} + floor ${g(t.floorKiB)})`],[`headroom`,`${g(Math.max(0,a))} — room for ${o(`hardlink`)} hardlinked trees, ${o(`reconcile`)} lockfile-diverged (reconciling)`],[`measured`,e.at||`—`]]}),Ht=s(()=>{let e=$.value;if(!e)return[];let t=[[`mirror`,g(e.parts.mirror)],[`checkout deps (node_modules)`,g(e.parts.deps)],[`checkout (history + tree + build)`,g(e.parts.checkout)]];for(let[n,r]of Object.entries(e.parts.threads).sort((e,t)=>t[1]-e[1]))t.push([`thread ${n}`,g(r)]);for(let[n,r]of Object.entries(e.parts.homes).sort((e,t)=>t[1]-e[1]))r>=1024&&t.push([`home ${n}`,g(r)]);return t.push([`other (image, /tmp, …)`,g(e.parts.other)]),t});return(s,c)=>(o(),i(e,{title:W.value||`Resident`,nav:`residents`},{leading:t(()=>[...c[0]||=[l(`a`,{class:`back text-sm text-muted no-underline hover:text-primary`,href:`/residents`},`← All residents`,-1)]]),default:t(()=>[l(`section`,de,[c[8]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Lifecycle`,-1),l(`table`,fe,[l(`tbody`,null,[l(`tr`,pe,[c[1]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state`,-1),l(`td`,me,[r(m,{tone:f(ie)(U.value.state),label:U.value.state},null,8,[`tone`,`label`]),l(`span`,v,p(U.value.state),1)])]),l(`tr`,y,[c[2]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`reason`,-1),l(`td`,b,[U.value.reason?(o(),u(`span`,x,p(U.value.reason),1)):(o(),u(`span`,S,`—`))])]),l(`tr`,C,[c[3]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh error`,-1),l(`td`,w,[f(h)(U.value.lastRefreshError)?(o(),u(`span`,T,p(f(h)(U.value.lastRefreshError)),1)):(o(),u(`span`,E,`—`))])]),l(`tr`,D,[c[4]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last restore`,-1),l(`td`,O,[Q.value?(o(),u(`span`,k,p(Q.value),1)):(o(),u(`span`,A,`—`))])]),l(`tr`,j,[c[5]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`state updated`,-1),l(`td`,M,[f(h)(U.value.updatedAt)?(o(),u(`span`,N,p(f(h)(U.value.updatedAt)),1)):(o(),u(`span`,P,`—`))])]),l(`tr`,F,[c[7]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`idle since`,-1),l(`td`,I,[f(h)(U.value.idleSince)?(o(),u(n,{key:0},[a(p(f(h)(U.value.idleSince))+` `,1),c[6]||=l(`span`,{class:`text-xs text-muted`},`(refresh parked; container may sleep)`,-1)],64)):(o(),u(`span`,L,`awake`))])])])])]),l(`section`,R,[c[15]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pinned facts`,-1),l(`table`,z,[l(`tbody`,null,[l(`tr`,he,[c[9]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`repository`,-1),l(`td`,ge,[K.value?(o(),u(`a`,{key:0,class:`text-primary`,href:K.value},p(K.value),9,_e)):(o(),u(`span`,ve,p(f(h)(H.value.resource)||`—`),1))])]),l(`tr`,ye,[c[10]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`default ref`,-1),l(`td`,be,p(f(h)(U.value.defaultRef)||f(h)(H.value.defaultRef)||`—`),1)]),l(`tr`,xe,[c[11]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`pinned sha`,-1),l(`td`,Se,[q.value?(o(),u(`a`,{key:0,class:`text-primary`,href:q.value},p(G.value),9,Ce)):G.value?(o(),u(`span`,we,p(G.value),1)):(o(),u(`span`,Te,`—`))])]),l(`tr`,Ee,[c[12]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`lockfile hash`,-1),l(`td`,De,[f(h)(U.value.lockfileHash)?(o(),u(`span`,Oe,p(f(h)(U.value.lockfileHash)),1)):(o(),u(`span`,ke,`—`))])]),l(`tr`,Ae,[c[13]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`provisioned`,-1),l(`td`,je,[f(h)(U.value.provisionedAt)?(o(),u(`span`,Me,p(f(h)(U.value.provisionedAt)),1)):(o(),u(`span`,Ne,`—`))])]),l(`tr`,Pe,[c[14]||=l(`td`,{class:`w-32 px-2 py-1 align-top text-muted sm:w-48 sm:whitespace-nowrap`},`last refresh`,-1),l(`td`,Fe,[f(h)(U.value.lastRefreshAt)?(o(),u(`span`,Ie,p(f(h)(U.value.lastRefreshAt)),1)):(o(),u(`span`,Le,`—`))])])])])]),l(`section`,Re,[c[17]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Disk`,-1),$.value?(o(),u(n,{key:0},[l(`table`,ze,[l(`tbody`,null,[(o(!0),u(n,null,d(Vt.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Be,p(e),1),l(`td`,Ve,p(t),1)]))),128))])]),c[16]||=l(`p`,{class:`mb-1 mt-2 text-xs text-muted`},` components (one du, hardlinks counted once — a thread tree shows only what it does not share with the checkout) `,-1),l(`table`,He,[l(`tbody`,null,[(o(!0),u(n,null,d(Ht.value,([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Ue,p(e),1),l(`td`,We,p(t),1)]))),128))])])],64)):(o(),u(`p`,Ge,` not measured yet — the first refresh cycle or attach of this container measures it `))]),l(`section`,Ke,[c[18]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Snapshot stamp`,-1),J.value?(o(),u(`table`,qe,[l(`tbody`,null,[(o(),u(n,null,d([`ref`,`sha`,`lockfileHash`,`createdAt`,`mirrorBackupId`,`checkoutBackupId`],e=>l(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,Je,p(e),1),l(`td`,Ye,[f(h)(J.value[e])?(o(),u(`span`,Xe,p(f(h)(J.value[e])),1)):(o(),u(`span`,B,`—`))])])),64))])])):(o(),u(`p`,Ze,`no snapshot recorded`))]),l(`section`,Qe,[c[22]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Thread worktrees`,-1),X.value.length>0?(o(),u(n,{key:0},[l(`p`,$e,p(Z.value)+` live · `+p(X.value.length-Z.value)+` evicted`,1),l(`div`,et,[l(`table`,tt,[l(`tbody`,null,[c[21]||=l(`tr`,{class:`text-xs text-muted`},[l(`td`,{class:`px-2 py-1`},`thread`),l(`td`,{class:`px-2 py-1`},`ref · sha`),l(`td`,{class:`px-2 py-1`},`user · deps`),l(`td`,{class:`px-2 py-1`},`bound · last attach`)],-1),(o(!0),u(n,null,d(X.value,e=>(o(),u(`tr`,{key:e.threadKey,class:`border-t border-muted`},[l(`td`,nt,[e.evicted?(o(),u(`span`,rt,[a(`evicted `+p(e.evictedAt||`—`),1),e.evictedWhy?(o(),u(n,{key:0},[a(` · `+p(e.evictedWhy),1)],64)):ee(``,!0)])):(o(),i(m,{key:1,tone:`green`,label:`live`,tip:`live`})),a(` `+p(e.threadKey),1)]),l(`td`,it,[a(p(e.ref)+` · `,1),e.commitHref?(o(),u(`a`,{key:0,class:`text-primary`,href:e.commitHref},p(e.sha),9,at)):e.sha?(o(),u(`span`,ot,p(e.sha),1)):(o(),u(`span`,st,`—`))]),l(`td`,ct,[e.user?(o(),u(`span`,lt,p(e.user),1)):(o(),u(`span`,ut,`—`)),c[19]||=a(` · `,-1),e.deps?(o(),u(`span`,dt,p(e.deps),1)):(o(),u(`span`,ft,`—`))]),l(`td`,pt,[e.boundAt?(o(),u(`span`,mt,p(e.boundAt),1)):(o(),u(`span`,ht,`—`)),c[20]||=a(` · `,-1),e.lastAttachAt?(o(),u(`span`,gt,p(e.lastAttachAt),1)):(o(),u(`span`,_t,`—`))])]))),128))])])])],64)):(o(),u(`p`,vt,`no thread worktrees`))]),l(`section`,yt,[c[23]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Pending schedules`,-1),l(`table`,bt,[l(`tbody`,null,[(o(),u(n,null,d([[`refresh`,`refresh`],[`provision run`,`provisionRun`],[`provision deadline`,`provisionDeadline`]],([e,t])=>l(`tr`,{key:t,class:`border-t border-muted`},[l(`td`,xt,p(e),1),l(`td`,St,p(f(h)(zt.value[t]??0)||`0`),1)])),64))])])]),l(`section`,Ct,[c[25]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Command table`,-1),Y.value.length>0?(o(),u(`table`,wt,[l(`tbody`,null,[(o(!0),u(n,null,d(Y.value,e=>(o(),u(`tr`,{key:e.name,class:`border-t border-muted`},[l(`td`,Tt,p(e.name),1),l(`td`,Et,[l(`code`,null,p(e.command),1),c[24]||=a(),l(`span`,Dt,p(e.effect),1)])]))),128))])])):(o(),u(`p`,Ot,`no command table`))]),l(`section`,kt,[c[26]||=l(`h2`,{class:`mb-1.5 font-mono text-xs font-medium uppercase tracking-wider text-muted`},`Registry settings`,-1),l(`table`,At,[l(`tbody`,null,[(o(!0),u(n,null,d([[`onboarded`,f(h)(H.value.onboardedAt)],[`record updated`,f(h)(H.value.updatedAt)],[`provisioning timeout (ms)`,f(h)(H.value.provisioningTimeoutMs)],[`disk budget (MB)`,f(h)(H.value.diskBudgetMb)],[`worktree TTL (days)`,f(h)(H.value.worktreeTtlDays??7)]],([e,t])=>(o(),u(`tr`,{key:e,class:`border-t border-muted`},[l(`td`,jt,p(e),1),l(`td`,Mt,[t?(o(),u(`span`,Nt,p(t),1)):(o(),u(`span`,Pt,`—`))])]))),128))])])]),l(`p`,Ft,[c[27]||=a(` Manage from chat: `,-1),l(`code`,It,`repo rebuild `+p(W.value),1),c[28]||=a(` · `,-1),l(`code`,Lt,`repo reconfigure `+p(W.value)+` …`,1),c[29]||=a(` · `,-1),l(`code`,Rt,`repo offboard `+p(W.value)+` --dry-run`,1)])]),_:1},8,[`title`]))}});export{V as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as s,mr as c,on as l,r as u,sn as d,un as f,ur as p,wi as m,xi as h,yn as g}from"./seed-DeKSHrt2.js";import{n as _}from"./wallClock-61NpVkY6.js";import{t as v}from"./StatusDot-
|
|
1
|
+
import{t as e}from"./AppShell-lYVcj-k7.js";import{Lr as t,Xt as n,_n as r,cn as i,gn as a,ir as o,ln as s,mr as c,on as l,r as u,sn as d,un as f,ur as p,wi as m,xi as h,yn as g}from"./seed-DeKSHrt2.js";import{n as _}from"./wallClock-61NpVkY6.js";import{t as v}from"./StatusDot-DDc88Kbs.js";import{c as y,d as b,f as x,l as S,o as C,r as w,u as T}from"./residentDiskBudget-BMBKlYRH.js";import{n as E}from"./indexFormat-B-pd4r7Y.js";var D={class:`mb-2 text-xs text-muted`},O={class:`m-0 list-none p-0`},k={class:`font-mono font-medium text-primary`},A={class:`font-medium`},j=[`title`],M=[`title`],N={key:0,class:`basis-full pl-5 text-xs text-warn`},P={key:1,class:`px-2 py-1.5 text-muted`},F=g({__name:`ResidentsIndexPage`,setup(g){let F=u(`residents`),I=_(),L=l(()=>(F?.residents??[]).map((e,t)=>{let n=e,r=T(n),i=S(n),a=x(i.sha),o=x(i.lastRefreshAt),s=o?Date.parse(o):NaN,c=y(n);return{key:`${r||`?`}-${t}`,display:r||x(n.resource)||`?`,state:i.state,tone:b(i.state),reason:i.reason,ref:x(n.defaultRef)||`?`,sha:a?a.slice(0,8):``,refreshed:o,refreshedLabel:Number.isFinite(s)?E(s,I):o,disk:c?w(c):``,diskAt:c?.at??``,href:C.test(r)?`/residents/${r}`:null}})),R=l(()=>x(F?.cap)||`?`),z=l(()=>x(F?.count)||String(L.value.length));return(l,u)=>(o(),i(e,{title:`Resident repos`,nav:`residents`},{default:t(()=>[L.value.length>0?(o(),f(n,{key:0},[d(`p`,D,m(z.value)+`/`+m(R.value)+` resident slots in use · live registry read, not cached `,1),d(`ul`,O,[(o(!0),f(n,null,p(L.value,e=>(o(),f(`li`,{key:e.key,class:`border-b border-muted first:border-t`},[(o(),i(c(e.href?`a`:`span`),{class:h([`row flex flex-wrap items-center gap-2.5 rounded-md px-2 py-1.5 text-inherit no-underline`,e.href?`hover:bg-elevated`:``]),href:e.href??void 0},{default:t(()=>[r(v,{tone:e.tone,label:e.state,tip:e.state},null,8,[`tone`,`label`,`tip`]),d(`span`,k,m(e.display),1),d(`span`,A,m(e.state),1),d(`span`,{class:`font-mono text-xs text-muted max-sm:basis-full max-sm:pl-5`,title:e.refreshed||void 0},[a(` ref `+m(e.ref),1),e.sha?(o(),f(n,{key:0},[a(` · sha `+m(e.sha),1)],64)):s(``,!0),e.refreshedLabel?(o(),f(n,{key:1},[a(` · refreshed `+m(e.refreshedLabel),1)],64)):s(``,!0),e.disk?(o(),f(n,{key:2},[u[0]||=a(` · `,-1),d(`span`,{title:e.diskAt?`measured ${e.diskAt}`:void 0},`disk `+m(e.disk),9,M)],64)):s(``,!0)],8,j),e.reason?(o(),f(`span`,N,m(e.reason),1)):s(``,!0)]),_:2},1032,[`class`,`href`]))]))),128))])],64)):(o(),f(`p`,P,[a(` No repos onboarded (0/`+m(R.value)+`). Onboard one from chat: `,1),u[1]||=d(`code`,{class:`rounded bg-elevated px-1.5 py-0.5`},`repo onboard <owner/name>`,-1),u[2]||=a(`. `,-1)]))]),_:1}))}});export{F as default};
|