@coreplane/switchboard 1.225.0 → 1.226.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.
Files changed (28) hide show
  1. package/dist/assets/package-lock.json +3 -3
  2. package/dist/assets/package.json +1 -1
  3. package/dist/assets/source.json +3 -3
  4. package/dist/assets/src/agents/registry.ts +1 -1
  5. package/dist/assets/src/core/chatMessage.ts +77 -0
  6. package/dist/assets/src/{providers/types.ts → core/provider.ts} +21 -71
  7. package/dist/assets/src/core/reviewVerdict.ts +1 -1
  8. package/dist/assets/src/core/runEvents.ts +22 -3
  9. package/dist/assets/src/core/runLedger/sessionLog.ts +1 -1
  10. package/dist/assets/src/core/runLedger/transcript.ts +1 -1
  11. package/dist/assets/src/core/runLedger/types.ts +2 -1
  12. package/dist/assets/web/dist/.vite/manifest.json +20 -20
  13. package/dist/assets/web/dist/assets/CostsPage-5pl3HB2F.js +2 -0
  14. package/dist/assets/web/dist/assets/{ResidentDetailPage-Cu4Ve2j4.js → ResidentDetailPage-BBOpejGX.js} +1 -1
  15. package/dist/assets/web/dist/assets/{ResidentsIndexPage-_QIDVyOj.js → ResidentsIndexPage-B8kFWHpB.js} +1 -1
  16. package/dist/assets/web/dist/assets/RunRoutePage-COWeVtIE.js +12 -0
  17. package/dist/assets/web/dist/assets/{RunsIndexPage-JQvnDmo0.js → RunsIndexPage-BjH93cKx.js} +1 -1
  18. package/dist/assets/web/dist/assets/{ScheduledPage-DEVRWqZi.js → ScheduledPage-grlNKvCA.js} +1 -1
  19. package/dist/assets/web/dist/assets/{StatusDot-BDAKF1Bp.js → StatusDot-BQNoaXO6.js} +1 -1
  20. package/dist/assets/web/dist/assets/{Tooltip-BFncyNUQ.js → Tooltip-DVCeIzaa.js} +1 -1
  21. package/dist/assets/web/dist/assets/{dist-DJfQXPjH.js → dist-B5Wfk-oY.js} +1 -1
  22. package/dist/assets/web/dist/assets/{main-BjhiJxQq.js → main-CN0U7d6s.js} +2 -2
  23. package/dist/assets/web/dist/assets/main-xLAsdkfB.css +1 -0
  24. package/dist/cli.js +1228 -930
  25. package/package.json +1 -1
  26. package/dist/assets/web/dist/assets/CostsPage-BlPwsI2T.js +0 -3
  27. package/dist/assets/web/dist/assets/RunRoutePage-DxgcHX-0.js +0 -12
  28. package/dist/assets/web/dist/assets/main-DymOuq2l.css +0 -1
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "switchboard",
3
- "version": "1.225.0",
3
+ "version": "1.226.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "switchboard",
9
- "version": "1.225.0",
9
+ "version": "1.226.0",
10
10
  "license": "Apache-2.0",
11
11
  "workspaces": [
12
12
  "web",
@@ -17685,7 +17685,7 @@
17685
17685
  },
17686
17686
  "packages/switchboard": {
17687
17687
  "name": "@coreplane/switchboard",
17688
- "version": "1.225.0",
17688
+ "version": "1.226.0",
17689
17689
  "license": "Apache-2.0",
17690
17690
  "dependencies": {
17691
17691
  "@anthropic-ai/sdk": "^0.124.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchboard",
3
- "version": "1.225.0",
3
+ "version": "1.226.0",
4
4
  "private": true,
5
5
  "description": "Mention it in Slack and an agent reviews the PR, ships the fix, or answers the question — on the model you choose, with its tools running where you decide.",
6
6
  "license": "Apache-2.0",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.225.0",
3
- "commit": "83ce8e676d098de42d9166b03d0faa76ef1c31cc",
4
- "builtAt": "2026-09-15T17:51:59.818Z"
2
+ "version": "1.226.0",
3
+ "commit": "994440466168ef0a5b2446eadcb6c56c59e52580",
4
+ "builtAt": "2026-09-15T18:47:52.793Z"
5
5
  }
@@ -1,6 +1,6 @@
1
1
  // Agent definitions. An agent is a system prompt + toolset + machine class + wall-clock budget.
2
2
  import type { Effort } from "../effort.js";
3
- import type { CacheTtl } from "../providers/types.js";
3
+ import type { CacheTtl } from "../core/provider.js";
4
4
  import { BASH_TIMEOUT_MAX_MS } from "../execution/bashTimeout.js";
5
5
  import { CONTRACT_HEADING, CONTRACT_SECTION_HEADINGS, PR_TITLE_GUARD } from "../core/ship/contract.js";
6
6
  // Which model runs it is resolved separately by the config layers, so any
@@ -0,0 +1,77 @@
1
+ // The conversation vocabulary: a turn (`ChatMessage`), the parts a turn is
2
+ // made of (`ContentPart`) and what a tool result carries (`ToolResultContent`),
3
+ // with the two helpers every reader of a tool result shares — its text
4
+ // rendering and the cap on what the model receives. Provider-neutral: the run
5
+ // ledger, the dispatcher's seed, the session log, the pi mirror and the model
6
+ // providers (pi's library in the bot, the native adapters until record 0032's
7
+ // series deletes them) all speak it, and no vendor's wire shape leaks in.
8
+ // Moved here from `src/providers/types.ts` so the vocabulary outlives the
9
+ // native provider layer (docs/decisions/0032-pi-is-the-harness-the-native-loop-retires.md,
10
+ // step 5 of the series).
11
+
12
+ export type ContentPart =
13
+ | { type: "text"; text: string }
14
+ | { type: "image"; mediaType: string; data: string } // data is base64, no data: prefix
15
+ | { type: "document"; mediaType: string; data: string; name?: string } // PDF; data is base64
16
+ | { type: "tool_use"; id: string; name: string; input: unknown }
17
+ | { type: "tool_result"; toolUseId: string; content: ToolResultContent; isError?: boolean }
18
+ /** The model's own reasoning, as the provider returned it. Opaque to the
19
+ * runner (never shown, never redacted — `collectText` skips it) and echoed
20
+ * back byte-for-byte in the next request: Anthropic verifies `signature`
21
+ * and rejects a modified or reordered block, and dropping them breaks the
22
+ * turn on Claude Fable 5 (docs/reference/specs/run-loop.md item 11). Providers without
23
+ * the concept drop them on the way out. */
24
+ | { type: "thinking"; thinking: string; signature: string }
25
+ | { type: "redacted_thinking"; data: string };
26
+
27
+ /** What a tool may hand back: plain text, or a list of text/image/document
28
+ * parts when the result is something the model should *see* (e.g. web_fetch
29
+ * on an image or PDF URL). Each provider adapter decides how much of a parts
30
+ * list its wire format can carry inside the tool result and hoists the rest
31
+ * into the surrounding user turn. */
32
+ export type ToolResultPart = Extract<ContentPart, { type: "text" | "image" | "document" }>;
33
+ export type ToolResultContent = string | ToolResultPart[];
34
+
35
+ /** Text rendering of a tool result for logs, summaries, and text-only wire
36
+ * formats: text parts verbatim, binary parts as a one-line descriptor (never
37
+ * the base64 payload). */
38
+ export function toolResultText(content: ToolResultContent): string {
39
+ if (typeof content === "string") return content;
40
+ return content
41
+ .map((p) => {
42
+ if (p.type === "text") return p.text;
43
+ if (p.type === "image") return `[image ${p.mediaType}, ${base64Bytes(p.data)} bytes]`;
44
+ return `[document ${p.name ?? "document"} (${p.mediaType}), ${base64Bytes(p.data)} bytes]`;
45
+ })
46
+ .join("\n");
47
+ }
48
+
49
+ /** The most text ONE tool result may hand the model, whatever the tool. Each
50
+ * tool caps its own output where it knows the shape (bash 120k, GitHub files
51
+ * 200k, web pages 40k with paging); this is the ceiling behind all of them, so
52
+ * a tool that forgets — or a new one — can never fill the context in one
53
+ * call (a 1 MB `web_fetch` result is ~300k tokens — enough to kill the run).
54
+ * Sized to the bash cap: the largest a tool legitimately returns. */
55
+ export const MAX_TOOL_RESULT_CHARS = 120_000;
56
+
57
+ /** Pure: the tool result the model actually receives. Text over the cap is cut
58
+ * with a visible note (never silently); image/document parts ride through —
59
+ * they are bounded by their own byte caps and are not text. */
60
+ export function capToolResultContent(content: ToolResultContent, cap = MAX_TOOL_RESULT_CHARS): ToolResultContent {
61
+ const capText = (text: string): string =>
62
+ text.length > cap
63
+ ? `${text.slice(0, cap)}\n…[tool result truncated: ${text.length - cap} of ${text.length} characters cut — ask for a narrower slice]`
64
+ : text;
65
+ if (typeof content === "string") return capText(content);
66
+ return content.map((p) => (p.type === "text" ? { ...p, text: capText(p.text) } : p));
67
+ }
68
+
69
+ function base64Bytes(b64: string): number {
70
+ const padding = b64.endsWith("==") ? 2 : b64.endsWith("=") ? 1 : 0;
71
+ return Math.floor((b64.length * 3) / 4) - padding;
72
+ }
73
+
74
+ export interface ChatMessage {
75
+ role: "user" | "assistant";
76
+ content: ContentPart[];
77
+ }
@@ -1,22 +1,21 @@
1
- import type { Effort } from "../effort.js";
2
-
3
- // Provider-neutral chat types. Each provider adapter maps these to its own
4
- // wire format, so agents and the runner never depend on a specific vendor.
1
+ // A model provider as the bot sees one: the completion vocabulary — a
2
+ // `Provider` whose `complete` takes a `CompletionRequest` and answers a
3
+ // `CompletionResult` with its `TokenUsage`, and the tool definition a request
4
+ // carries (`ToolDef`) — the `providers:` block of
5
+ // `config.yaml` a provider is built from (`ProviderConfig`) and the
6
+ // `<provider>/<model>` ref that names one (`parseModelRef`). Implemented by
7
+ // pi's model library in the bot process (`src/core/harness/piAi.ts`) for the
8
+ // calls made outside a run loop, and by the native adapters in
9
+ // `src/providers/` until record 0032's series deletes them; the model proxy
10
+ // meters a run's calls in the same `TokenUsage`. Moved here from
11
+ // `src/providers/types.ts` so the vocabulary outlives the native provider layer
12
+ // (docs/decisions/0032-pi-is-the-harness-the-native-loop-retires.md, step 5 of
13
+ // the series). A leaf over ./chatMessage.ts and ../effort.ts: the run ledger's
14
+ // Node-free contract reads `ToolDef` from here, and nothing under src/tools/
15
+ // comes with it into the memory Worker's build.
5
16
 
6
- export type ContentPart =
7
- | { type: "text"; text: string }
8
- | { type: "image"; mediaType: string; data: string } // data is base64, no data: prefix
9
- | { type: "document"; mediaType: string; data: string; name?: string } // PDF; data is base64
10
- | { type: "tool_use"; id: string; name: string; input: unknown }
11
- | { type: "tool_result"; toolUseId: string; content: ToolResultContent; isError?: boolean }
12
- /** The model's own reasoning, as the provider returned it. Opaque to the
13
- * runner (never shown, never redacted — `collectText` skips it) and echoed
14
- * back byte-for-byte in the next request: Anthropic verifies `signature`
15
- * and rejects a modified or reordered block, and dropping them breaks the
16
- * turn on Claude Fable 5 (docs/reference/specs/run-loop.md item 11). Providers without
17
- * the concept drop them on the way out. */
18
- | { type: "thinking"; thinking: string; signature: string }
19
- | { type: "redacted_thinking"; data: string };
17
+ import type { Effort } from "../effort.js";
18
+ import type { ChatMessage, ContentPart } from "./chatMessage.js";
20
19
 
21
20
  /** How long a prompt-cache entry written by a request stays warm. `5m` is
22
21
  * refreshed by every read (strictly cheaper while turns start < 5 min apart);
@@ -24,62 +23,13 @@ export type ContentPart =
24
23
  * coding run, where a 5m entry would expire between requests. */
25
24
  export type CacheTtl = "5m" | "1h";
26
25
 
27
- /** What a tool may hand back: plain text, or a list of text/image/document
28
- * parts when the result is something the model should *see* (e.g. web_fetch
29
- * on an image or PDF URL). Each provider adapter decides how much of a parts
30
- * list its wire format can carry inside the tool result and hoists the rest
31
- * into the surrounding user turn. */
32
- export type ToolResultPart = Extract<ContentPart, { type: "text" | "image" | "document" }>;
33
- export type ToolResultContent = string | ToolResultPart[];
34
-
35
- /** Text rendering of a tool result for logs, summaries, and text-only wire
36
- * formats: text parts verbatim, binary parts as a one-line descriptor (never
37
- * the base64 payload). */
38
- export function toolResultText(content: ToolResultContent): string {
39
- if (typeof content === "string") return content;
40
- return content
41
- .map((p) => {
42
- if (p.type === "text") return p.text;
43
- if (p.type === "image") return `[image ${p.mediaType}, ${base64Bytes(p.data)} bytes]`;
44
- return `[document ${p.name ?? "document"} (${p.mediaType}), ${base64Bytes(p.data)} bytes]`;
45
- })
46
- .join("\n");
47
- }
48
-
49
- /** The most text ONE tool result may hand the model, whatever the tool. Each
50
- * tool caps its own output where it knows the shape (bash 120k, GitHub files
51
- * 200k, web pages 40k with paging); this is the ceiling behind all of them, so
52
- * a tool that forgets — or a new one — can never fill the context in one
53
- * call (a 1 MB `web_fetch` result is ~300k tokens — enough to kill the run).
54
- * Sized to the bash cap: the largest a tool legitimately returns. */
55
- export const MAX_TOOL_RESULT_CHARS = 120_000;
56
-
57
- /** Pure: the tool result the model actually receives. Text over the cap is cut
58
- * with a visible note (never silently); image/document parts ride through —
59
- * they are bounded by their own byte caps and are not text. */
60
- export function capToolResultContent(content: ToolResultContent, cap = MAX_TOOL_RESULT_CHARS): ToolResultContent {
61
- const capText = (text: string): string =>
62
- text.length > cap
63
- ? `${text.slice(0, cap)}\n…[tool result truncated: ${text.length - cap} of ${text.length} characters cut — ask for a narrower slice]`
64
- : text;
65
- if (typeof content === "string") return capText(content);
66
- return content.map((p) => (p.type === "text" ? { ...p, text: capText(p.text) } : p));
67
- }
68
-
69
- function base64Bytes(b64: string): number {
70
- const padding = b64.endsWith("==") ? 2 : b64.endsWith("=") ? 1 : 0;
71
- return Math.floor((b64.length * 3) / 4) - padding;
72
- }
73
-
74
- export interface ChatMessage {
75
- role: "user" | "assistant";
76
- content: ContentPart[];
77
- }
78
-
26
+ /** A tool as the model is told it: the name, the description and the JSON
27
+ * Schema of its input. A request carries a list of these; a `RunnableTool`
28
+ * (src/tools/runnableTool.ts) is one with its `run`; the relay serves them to
29
+ * pi's extension and the run ledger records the list a step saw. */
79
30
  export interface ToolDef {
80
31
  name: string;
81
32
  description: string;
82
- // JSON Schema for the tool input
83
33
  inputSchema: Record<string, unknown>;
84
34
  }
85
35
 
@@ -4,7 +4,7 @@
4
4
  // workflow) approves a PR when the review App's review body STARTS WITH the
5
5
  // exact token `LGTM:`. That token must therefore never depend on how the model happens to
6
6
  // phrase its opening line. The model states its judgement through the
7
- // structured `submit_verdict` tool (src/tools/workspace.ts); this module turns
7
+ // structured `submit_verdict` tool (src/tools/submit.ts); this module turns
8
8
  // that structured value into the first line of the posted body:
9
9
  //
10
10
  // approve → "LGTM: <summary>"
@@ -378,6 +378,13 @@ export type RunEvent =
378
378
  | {
379
379
  type: "input";
380
380
  text: string;
381
+ /** The message this turn is: the platform's id of the message (Slack's
382
+ * `ts`), the run id for a request from a channel with none (CLI, HTTP,
383
+ * MCP), the inbox seq or arrival time for a follow-up with none (a
384
+ * parent's steer). A received `artifact` names the same id, so the page
385
+ * puts a file on the card of the message it arrived with by data, never
386
+ * by the order the events happened to be recorded in (live-view.md item 26). */
387
+ messageId: string;
381
388
  /** Where the request came from, for the Request block: the channel and
382
389
  * user display names and a link back to the triggering message —
383
390
  * whatever the adapter supplied (all optional) — and, for a follow-up a
@@ -435,9 +442,8 @@ export type RunEvent =
435
442
  * credential that expires or leaks, and the parser refuses a payload that
436
443
  * tries. A side fact beside the tool pair that moved the file (like
437
444
  * `skill_use`), never a step; the friction analyzer ignores it. */
438
- | {
445
+ | ({
439
446
  type: "artifact";
440
- direction: "in" | "out";
441
447
  /** The store key (`src/artifacts/keys.ts`): `runs/<runId>/out/<seq>-<basename>` or `threads/<thread>/in/<ts>/<i>-<basename>`. */
442
448
  key: string;
443
449
  /** The file's name as the person sees it (the Slack filename, the tool's `name`). */
@@ -446,7 +452,20 @@ export type RunEvent =
446
452
  contentType: string;
447
453
  seq?: number;
448
454
  at?: number;
449
- }
455
+ } & (
456
+ | {
457
+ direction: "in";
458
+ /** The `input` event this file arrived with — the same `messageId`
459
+ * (live-view.md item 26); a file re-pulled from an earlier message
460
+ * of the thread names the request it was pulled for. */
461
+ messageId: string;
462
+ }
463
+ | {
464
+ direction: "out";
465
+ /** The `tool_call` (`attach_file`) that posted it — its `callId`. */
466
+ callId: string;
467
+ }
468
+ ))
450
469
  /** A skill was loaded into the model's context (docs/reference/specs/skills.md). Emitted
451
470
  * by the `use_skill` tool on a successful load — alongside, not instead of,
452
471
  * its `tool_call`/`tool_result` pair — so skill use is a first-class fact in
@@ -6,7 +6,7 @@
6
6
  // text the full-text index sees for a row, the byte policy's choice of what to
7
7
  // drop, the tail cut a follow-up seeds from, and the sweep's drop decision.
8
8
 
9
- import type { ChatMessage, ContentPart } from "../../providers/types.js";
9
+ import type { ChatMessage, ContentPart } from "../chatMessage.js";
10
10
  import { DEFAULT_RETENTION_POLICY, utf8ByteLength } from "../runRecord.js";
11
11
  import type { StoredRow } from "./transcript.js";
12
12
 
@@ -6,7 +6,7 @@
6
6
  // once and referenced, so a 20 MB PDF in the seed is one attachment row, not
7
7
  // a 20 MB part row.
8
8
 
9
- import type { ChatMessage, ContentPart } from "../../providers/types.js";
9
+ import type { ChatMessage, ContentPart } from "../chatMessage.js";
10
10
  import { utf8ByteLength } from "../runRecord.js";
11
11
  import {
12
12
  ATTACHMENT_REF_BYTES,
@@ -3,7 +3,8 @@
3
3
  // Worker so the next bot generation can resume it. Node-free — imported by the
4
4
  // bot and by `deploy/cloudflare-memory/worker.ts` alike, the way runRecord.ts is.
5
5
 
6
- import type { ChatMessage, ToolDef } from "../../providers/types.js";
6
+ import type { ChatMessage } from "../chatMessage.js";
7
+ import type { ToolDef } from "../provider.js";
7
8
  import type { ChannelVisibility } from "../authz/types.js";
8
9
  import type { RunProfile } from "../../config/profile.js";
9
10
  import type { RunEvent } from "../runEvents.js";
@@ -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-DJfQXPjH.js",
31
+ "file": "assets/dist-B5Wfk-oY.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-BDAKF1Bp.js": {
2566
- "file": "assets/StatusDot-BDAKF1Bp.js",
2565
+ "_StatusDot-BQNoaXO6.js": {
2566
+ "file": "assets/StatusDot-BQNoaXO6.js",
2567
2567
  "name": "StatusDot",
2568
2568
  "imports": [
2569
2569
  "_seed-DeKSHrt2.js",
2570
- "_Tooltip-BFncyNUQ.js"
2570
+ "_Tooltip-DVCeIzaa.js"
2571
2571
  ]
2572
2572
  },
2573
- "_Tooltip-BFncyNUQ.js": {
2574
- "file": "assets/Tooltip-BFncyNUQ.js",
2573
+ "_Tooltip-DVCeIzaa.js": {
2574
+ "file": "assets/Tooltip-DVCeIzaa.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-BjhiJxQq.js",
2792
+ "file": "assets/main-CN0U7d6s.js",
2793
2793
  "name": "main",
2794
2794
  "src": "src/main.ts",
2795
2795
  "isEntry": true,
@@ -2807,7 +2807,7 @@
2807
2807
  "_NotFoundPage-BzWS4Ca1.js"
2808
2808
  ],
2809
2809
  "css": [
2810
- "assets/main-DymOuq2l.css"
2810
+ "assets/main-xLAsdkfB.css"
2811
2811
  ],
2812
2812
  "assets": [
2813
2813
  "assets/instrument-sans-latin-ext-wght-normal-B5bTHO_g.woff2",
@@ -2820,7 +2820,7 @@
2820
2820
  ]
2821
2821
  },
2822
2822
  "src/pages/CostsPage.vue": {
2823
- "file": "assets/CostsPage-BlPwsI2T.js",
2823
+ "file": "assets/CostsPage-5pl3HB2F.js",
2824
2824
  "name": "CostsPage",
2825
2825
  "src": "src/pages/CostsPage.vue",
2826
2826
  "isDynamicEntry": true,
@@ -2841,19 +2841,19 @@
2841
2841
  ]
2842
2842
  },
2843
2843
  "src/pages/ResidentDetailPage.vue": {
2844
- "file": "assets/ResidentDetailPage-Cu4Ve2j4.js",
2844
+ "file": "assets/ResidentDetailPage-BBOpejGX.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-BDAKF1Bp.js",
2851
+ "_StatusDot-BQNoaXO6.js",
2852
2852
  "_residentDiskBudget-BMBKlYRH.js"
2853
2853
  ]
2854
2854
  },
2855
2855
  "src/pages/ResidentsIndexPage.vue": {
2856
- "file": "assets/ResidentsIndexPage-_QIDVyOj.js",
2856
+ "file": "assets/ResidentsIndexPage-B8kFWHpB.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-BDAKF1Bp.js",
2864
+ "_StatusDot-BQNoaXO6.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-DxgcHX-0.js",
2870
+ "file": "assets/RunRoutePage-COWeVtIE.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-BFncyNUQ.js",
2877
+ "_Tooltip-DVCeIzaa.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-JQvnDmo0.js",
2893
+ "file": "assets/RunsIndexPage-BjH93cKx.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-BFncyNUQ.js",
2900
+ "_Tooltip-DVCeIzaa.js",
2901
2901
  "_wallClock-61NpVkY6.js",
2902
2902
  "_RunsTabs-DEICQ4FY.js",
2903
- "_StatusDot-BDAKF1Bp.js",
2903
+ "_StatusDot-BQNoaXO6.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-DEVRWqZi.js",
2910
+ "file": "assets/ScheduledPage-grlNKvCA.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-BFncyNUQ.js",
2917
+ "_Tooltip-DVCeIzaa.js",
2918
2918
  "_wallClock-61NpVkY6.js",
2919
2919
  "_RunsTabs-DEICQ4FY.js",
2920
2920
  "_indexFormat-B-pd4r7Y.js",
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./AppShell-lYVcj-k7.js";import{Ci as t,Lr as n,Xt as r,_n as i,ci as a,cn as o,gn as s,ir as c,ln as l,on as u,r as d,sn as f,un as p,ur as m,vi as h,wi as g,xi as _,yn as v}from"./seed-DeKSHrt2.js";var y=`Durable Objects`,b=`Workers · storage · R2`,x=`LLM (Anthropic)`,S=(e,t=2)=>`$${e.toFixed(t)}`,C=e=>e.workersUsd+e.doRowsUsd+e.doStorageUsd+e.r2Usd+e.workflowsUsd;function ee(e){let t=[];for(let n of e.days)for(let e of Object.keys(n.containers))t.includes(e)||t.push(e);return e.days.some(e=>Object.keys(e.durableObjects).length>0)&&t.push(y),e.days.some(e=>C(e)>0)&&t.push(b),e.llmAvailable&&t.push(x),t}function w(e,t){return t===`Durable Objects`?Object.values(e.durableObjects).reduce((e,t)=>e+t,0)+e.doRequestsUsd:t===`Workers · storage · R2`?C(e):t===`LLM (Anthropic)`?e.llmUsd:e.containers[t]?.total??0}var T=30.4;function te(e){let t=e.range.partialLastDay?e.days.slice(0,-1):e.days,n=e.range.partialLastDay?e.days[e.days.length-1]:void 0,r=t[t.length-1],i=t.slice(-7),a=i.length?i.reduce((e,t)=>e+t.total,0)/i.length:void 0,o=e.account.cloudUsd>0?Math.round(e.totals.cloudUsd/e.account.cloudUsd*100):0;return{...r?{yesterday:{date:r.date,total:r.total}}:{},...n?{today:{date:n.date,total:n.total}}:{},...a===void 0?{}:{avg7:a},projection:O(e,t,n),llm:{range:e.totals.llmUsd,...r?{yesterday:r.llmUsd}:{},...n?{today:{usd:n.llmUsd,estimated:n.llmEstimated}}:{}},accountShare:o}}var E=e=>e.reduce((e,t)=>e+t,0)/e.length;function D(e,t){let n=Date.parse(`${t.date}T00:00:00Z`),r=(e.generatedAt-n)/864e5;return Math.min(1,Math.max(1/24,Number.isFinite(r)?r:1))}function O(e,t,n){let r=n?D(e,n):1,i=t.slice(-7),a=0,o=`full-days`;i.length?a=E(i.map(e=>e.cloudUsd)):n&&(a=n.cloudUsd/r,o=`today`);let s=0,c=`none`,l=0;if(e.llmAvailable){let e=t.findIndex(e=>e.llmUsd>0),i=e===-1?[]:t.slice(e).slice(-7);i.length?(s=E(i.map(e=>e.llmUsd)),c=`closed-days`,l=i.length):n&&n.llmUsd>0&&(s=n.llmUsd/r,c=`today`)}return{monthUsd:(a+s)*T,cloudRate:a,llmRate:s,cloudBasis:o,llmBasis:c,llmClosedDays:l}}function ne(e){let t=`https://dash.cloudflare.com/${e.account.id}`;return{account:t,billing:`${t}/billing`,containers:`${t}/workers/containers`,durableObjects:`${t}/workers/durable-objects`,workers:`${t}/workers-and-pages`,r2:`${t}/r2/overview`,workflows:`${t}/workers/workflows`,worker:e=>`${t}/workers/services/view/${encodeURIComponent(e)}/production/metrics`,bucket:e=>`${t}/r2/default/buckets/${encodeURIComponent(e)}`,anthropic:`https://platform.claude.com/cost`}}var k=e=>e.account.name??`${e.account.id.slice(0,8)}…`;function A(e,t,n){let r=[`${e.date} · total ${S(e.total)}${n?` (partial day)`:``}`];for(let n of t){let t=w(e,n);t<=0||r.push(`${n} ${S(t)}${n===`LLM (Anthropic)`&&e.llmEstimated?` (estimate)`:``}`)}return r.join(`
2
+ `)}function j(e){let t=new Date(`${e}T00:00:00Z`);return Number.isNaN(t.getTime())?e:`${[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`][t.getUTCMonth()]} ${t.getUTCDate()}`}function M(e,t,n){let r=t.map(t=>({series:t,usd:w(e,t),estimated:t===`LLM (Anthropic)`&&e.llmEstimated})).filter(e=>e.usd>0).sort((e,t)=>t.usd-e.usd);return{date:e.date,label:j(e.date),partial:n,total:e.total,rows:r}}function N(e,t){let n={t:12,r:12,b:30,l:48},r=960-n.l-n.r,i=260-n.t-n.b,a=e.days,o=Math.max(1e-9,...a.map(e=>e.total))*1.08,s=r/Math.max(1,a.length),c=Math.min(10,s*.28),l=e=>n.t+i-e/o*i,u=Array.from({length:5},(e,t)=>{let n=o/4*t;return{y:Number(l(n).toFixed(1)),label:S(n)}}),d=[],f=[],p=[];return a.forEach((r,o)=>{let u=0,m=n.l+o*s+c/2,h=s-c;f.push({x:Number((n.l+o*s).toFixed(1)),y:n.t,width:Number(s.toFixed(1)),height:i,title:A(r,t,e.range.partialLastDay&&o===a.length-1),tip:M(r,t,e.range.partialLastDay&&o===a.length-1)}),t.forEach((e,t)=>{let n=w(r,e);if(n<=0)return;let i=l(u+n),a=l(u),o=Math.max(0,a-i-2);d.push({seriesIndex:t,x:Number(m.toFixed(1)),y:Number(i.toFixed(1)),width:Number(h.toFixed(1)),height:Number(o.toFixed(1))}),u+=n}),(a.length<=16||o%Math.ceil(a.length/16)===0)&&p.push({x:Number((m+h/2).toFixed(1)),label:r.date.slice(5)})}),{width:960,height:260,gridLines:u,segments:d,dayHovers:f,dayLabels:p,axisY:Number(l(0).toFixed(1)),marginLeft:n.l,marginRight:n.r}}function re(e){let t=e.totals.byResource,n=[[`Memory (provisioned while awake)`,t.memory],[`vCPU (active use only)`,t.cpu],[`Durable Object duration + requests`,t.durableObjects],[`Disk (provisioned while awake)`,t.disk],[`Workers requests + CPU`,t.workers],[`Durable Object SQLite rows`,t.doRows],[`Durable Object SQLite storage`,t.doStorage],[`R2 storage + operations`,t.r2],[`Workflow steps + state`,t.workflows]],r=n.reduce((e,t)=>e+t[1],0)||1;return n.map(([e,t])=>({label:e,usd:t,percent:t/r*100}))}var P=[`fill-[#4478b8] dark:fill-[#7aa7e0]`,`fill-[#c8823b] dark:fill-[#e0a95a]`,`fill-[#4c8c57] dark:fill-[#6fae7a]`,`fill-[#b8963e] dark:fill-[#d4b45a]`,`fill-[#b0568c] dark:fill-[#d489b8]`,`fill-[#6b7bcc] dark:fill-[#98a5e6]`,`fill-[#d05252] dark:fill-[#e07a74]`,`fill-[#3e8e96] dark:fill-[#6fb9c0]`],F=[`bg-[#4478b8] dark:bg-[#7aa7e0]`,`bg-[#c8823b] dark:bg-[#e0a95a]`,`bg-[#4c8c57] dark:bg-[#6fae7a]`,`bg-[#b8963e] dark:bg-[#d4b45a]`,`bg-[#b0568c] dark:bg-[#d489b8]`,`bg-[#6b7bcc] dark:bg-[#98a5e6]`,`bg-[#d05252] dark:bg-[#e07a74]`,`bg-[#3e8e96] dark:bg-[#6fb9c0]`],I={class:`overflow-x-auto`},L=[`viewBox`],R=[`x1`,`x2`,`y1`,`y2`],z=[`x`,`y`],B=[`x`,`y`,`width`,`height`],V=[`aria-label`,`x`,`y`,`width`,`height`,`onPointerenter`,`onPointermove`],H=[`x`,`y`],U=[`x1`,`x2`,`y1`,`y2`],W={class:`tip-head mb-1.5 flex items-baseline justify-between gap-3 border-b border-muted pb-1.5`},G={class:`font-medium text-highlighted`},K={key:0,class:`ml-1.5 font-normal text-dimmed`},q={class:`font-medium text-highlighted`},J={class:`tip-name truncate text-muted`},Y={class:`text-highlighted`},X={class:`tip-usd`},ie={key:0,class:`ml-1 text-dimmed`},Z=256,Q=12,ae=v({__name:`CostChart`,props:{report:{},series:{}},setup(e){let n=e,i=u(()=>N(n.report,n.series)),o=e=>44+e*20,d=a(null),v=a(null);function y(e,t){let n=v.value,r=n?.getBoundingClientRect(),i=t.clientX-(r?.left??0),a=t.clientY-(r?.top??0),s=n?.clientWidth??0,c=n?.clientHeight??0,l=o(e.tip.rows.length),u=s>0&&i+Q+Z>s,f=c>0&&a+Q+l>c;d.value={x:Math.max(0,u?i-Q-Z:i+Q),y:Math.max(0,f?a-Q-l:a+Q),data:e.tip}}return(e,n)=>(c(),p(`div`,{ref_key:`host`,ref:v,class:`chart-host relative`},[f(`div`,I,[(c(),p(`svg`,{class:`block h-auto w-full font-mono`,viewBox:`0 0 ${i.value.width} ${i.value.height}`,role:`img`,"aria-label":`Daily cost, stacked by component`},[(c(!0),p(r,null,m(i.value.gridLines,(e,t)=>(c(),p(r,{key:`g${t}`},[f(`line`,{class:`stroke-(--ui-border-muted)`,x1:i.value.marginLeft,x2:i.value.width-i.value.marginRight,y1:e.y,y2:e.y},null,8,R),f(`text`,{class:`fill-(--ui-text-dimmed) text-[11px] tabular-nums`,x:i.value.marginLeft-8,y:e.y+4,"text-anchor":`end`},g(e.label),9,z)],64))),128)),(c(!0),p(r,null,m(i.value.segments,(e,t)=>(c(),p(`rect`,{key:`s${t}`,class:_([`seg hover:opacity-85`,h(P)[e.seriesIndex%h(P).length]]),x:e.x,y:e.y,width:e.width,height:e.height},null,10,B))),128)),(c(!0),p(r,null,m(i.value.dayHovers,(e,t)=>(c(),p(`rect`,{key:`h${t}`,class:`day fill-transparent`,role:`img`,"aria-label":e.title,x:e.x,y:e.y,width:e.width,height:e.height,onPointerenter:t=>y(e,t),onPointermove:t=>y(e,t),onPointerleave:n[0]||=e=>d.value=null},null,40,V))),128)),(c(!0),p(r,null,m(i.value.dayLabels,(e,t)=>(c(),p(`text`,{key:`d${t}`,class:`fill-(--ui-text-dimmed) text-[11px]`,x:e.x,y:i.value.height-10,"text-anchor":`middle`},g(e.label),9,H))),128)),f(`line`,{class:`stroke-(--ui-border)`,x1:i.value.marginLeft,x2:i.value.width-i.value.marginRight,y1:i.value.axisY,y2:i.value.axisY},null,8,U)],8,L))]),d.value?(c(),p(`div`,{key:0,class:`chart-tip pointer-events-none absolute z-10 w-64 rounded-md border border-default bg-elevated px-3 py-2 font-mono text-xs tabular-nums whitespace-nowrap shadow-lg`,role:`tooltip`,style:t({left:`${d.value.x}px`,top:`${d.value.y}px`})},[f(`div`,W,[f(`span`,G,[s(g(d.value.data.label),1),d.value.data.partial?(c(),p(`span`,K,`partial day`)):l(``,!0)]),f(`span`,q,g(h(S)(d.value.data.total)),1)]),(c(!0),p(r,null,m(d.value.data.rows,e=>(c(),p(`div`,{key:e.series,class:`tip-row flex items-baseline justify-between gap-3 leading-5`},[f(`span`,J,g(e.series),1),f(`span`,Y,[f(`span`,X,g(h(S)(e.usd)),1),e.estimated?(c(),p(`span`,ie,`est.`)):l(``,!0)])]))),128))],4)):l(``,!0)],512))}}),oe={class:`mb-4 flex flex-wrap items-center gap-x-4 gap-y-2`},se={class:`flex items-center gap-1`,"aria-label":`Range`},ce={key:0,class:`rounded-md bg-accented px-2.5 py-1 font-mono text-xs font-medium tabular-nums text-highlighted`,"aria-current":`page`},le=[`href`],ue={key:0,class:`flex items-center gap-1`,"aria-label":`Cost groups`},de={key:0,class:`rounded-md bg-accented px-2.5 py-1 text-xs font-medium text-highlighted`,"aria-current":`page`},fe=[`href`],pe={class:`font-mono text-sm tabular-nums text-muted`},me={class:`mb-5 grid grid-cols-[repeat(auto-fit,minmax(190px,1fr))] gap-3`},he={key:0,class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},ge={class:`font-mono text-2xl font-medium tabular-nums`},_e={class:`text-xs text-muted`},ve={key:1,class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},ye={class:`font-mono text-2xl font-medium tabular-nums`},be={class:`text-xs text-muted`},xe={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},Se={class:`font-mono text-2xl font-medium tabular-nums`},Ce={class:`text-xs text-muted`},we={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},Te={class:`font-mono text-2xl font-medium tabular-nums`},Ee={class:`text-xs text-muted`},De={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},Oe={class:`font-mono text-2xl font-medium tabular-nums`},ke={class:`text-xs text-muted`},Ae={class:`grid gap-0.5 rounded-lg border border-default bg-elevated px-4 py-3.5`},je={class:`font-mono text-2xl font-medium tabular-nums`},Me={class:`text-xs text-muted`},Ne=[`href`,`title`],Pe=[`href`],Fe={class:`mb-5 grid gap-3 rounded-lg border border-default bg-elevated px-5 py-4`},Ie={class:`flex flex-wrap items-baseline justify-between gap-x-4 gap-y-2`},Le={class:`legend flex flex-wrap gap-x-4 gap-y-1.5 text-xs text-muted`},Re=[`href`,`title`],ze={key:0,class:`text-xs text-warn`},Be={key:1,class:`text-xs text-muted`},Ve={class:`mb-5 grid gap-3 rounded-lg border border-default bg-elevated px-5 py-4`},He={class:`w-full border-collapse font-mono text-[0.8125rem] tabular-nums`},Ue={class:`px-2.5 py-1.5`},We=[`href`],Ge={class:`px-2.5 py-1.5 text-right`},Ke={class:`px-2.5 py-1.5 text-right`},qe={class:`w-2/5 px-2.5 py-1.5`},Je={class:`mb-5 grid gap-3 rounded-lg border border-default bg-elevated px-5 py-4`},Ye={open:``},Xe={class:`mt-2.5 overflow-x-auto`},Ze={class:`data w-full min-w-[38rem] border-collapse whitespace-nowrap font-mono text-[0.8125rem] tabular-nums`},Qe=[`title`],$e={key:0,class:`text-xs text-dimmed`},et={key:1,class:`text-xs text-dimmed`},tt={class:`border-b border-muted px-2.5 py-1.5 text-right font-medium`},$={class:`text-xs text-muted`},nt={class:`rounded bg-accented px-1 py-0.5`},rt={class:`border-t border-default pt-3.5 text-xs text-dimmed`},it={class:`mt-2 grid gap-1.5`},at=[`href`],ot={key:2},st=[`href`],ct={key:2},lt=[`href`],ut=[`href`],dt=v({__name:`CostsPage`,setup(a){let v=d(`costs`),y=u(()=>v?.report??null),b=u(()=>v?.groups??[]),x=u(()=>y.value?ee(y.value):[]),C=u(()=>y.value?te(y.value):null),T=u(()=>y.value?re(y.value):[]),E=u(()=>y.value?ne(y.value):null),D=u(()=>y.value?k(y.value):``);function O(e){let t=E.value;if(t){if(/^(Memory|vCPU|Disk)/.test(e))return t.containers;if(e.startsWith(`Durable Object`))return t.durableObjects;if(e.startsWith(`Workers`))return t.workers;if(e.startsWith(`R2`))return t.r2;if(e.startsWith(`Workflow`))return t.workflows}}function A(e){let t=E.value;if(t)return e===`LLM (Anthropic)`?t.anthropic:e===`Durable Objects`?t.durableObjects:e===`Workers · storage · R2`?t.workers:t.containers}let j=u(()=>{let e=y.value,t=C.value;if(!e||!t)return``;let n=t.projection,r=`cloud ${S(n.cloudRate)}/day`,i=n.cloudBasis===`today`?`cloud from today so far`:`cloud from the last 7 full days`;if(!e.llmAvailable)return`${r} × 30.4 · ${i} · before plan fees and included allowances`;let a=`LLM ${S(n.llmRate)}/day`,o=n.llmBasis===`closed-days`?`LLM from ${n.llmClosedDays} closed day${n.llmClosedDays===1?``:`s`}`:n.llmBasis===`today`?`LLM from today so far`:`no LLM spend in range`;return`${r} + ${a} · × 30.4 · ${n.cloudBasis===`today`&&n.llmBasis===`today`?`both from today so far`:`${i} · ${o}`}`}),M=u(()=>y.value?[...y.value.days].reverse():[]),N=[1,7,30,90],P=e=>e===1?`today`:`${e}d`,I=u(()=>{let e=y.value,t=C.value;if(!e||!t)return``;if(!e.llmAvailable)return`LLM spend not configured`;let n=[];return t.llm.yesterday!==void 0&&n.push(`yesterday ${S(t.llm.yesterday)}`),t.llm.today&&n.push(`today ${S(t.llm.today.usd)}${t.llm.today.estimated?` (estimate)`:``}`),n.length?n.join(` · `):`in range`});function L(e){let t=new Date(`${e}T00:00:00Z`);return Number.isNaN(t.getTime())?e:`${[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`][t.getUTCMonth()]} ${t.getUTCDate()}`}return(a,u)=>y.value&&C.value?(c(),o(e,{key:0,title:`${y.value.label} spend`,nav:`costs`},{default:n(()=>[f(`div`,oe,[f(`nav`,se,[(c(),p(r,null,m(N,e=>(c(),p(r,{key:e},[e===y.value.range.days?(c(),p(`span`,ce,g(P(e)),1)):(c(),p(`a`,{key:1,class:`rounded-md px-2.5 py-1 font-mono text-xs tabular-nums text-muted no-underline hover:bg-elevated hover:text-highlighted`,href:`/costs/${y.value.group}?days=${e}`},g(P(e)),9,le))],64))),64))]),b.value.length>1?(c(),p(`nav`,ue,[(c(!0),p(r,null,m(b.value,e=>(c(),p(r,{key:e},[e===y.value.group?(c(),p(`span`,de,g(e),1)):(c(),p(`a`,{key:1,class:`rounded-md px-2.5 py-1 text-xs text-muted no-underline hover:bg-elevated hover:text-highlighted`,href:`/costs/${e}`},g(e),9,fe))],64))),128))])):l(``,!0),f(`p`,pe,[s(g(L(y.value.range.from))+` → `+g(L(y.value.range.to))+` · `+g(y.value.range.days)+`d`,1),y.value.range.partialLastDay?(c(),p(r,{key:0},[s(` · today partial`)],64)):l(``,!0)])]),f(`section`,me,[C.value.yesterday?(c(),p(`div`,he,[u[0]||=f(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Yesterday`,-1),f(`span`,ge,g(h(S)(C.value.yesterday.total)),1),f(`span`,_e,g(C.value.yesterday.date)+` · last full day`,1)])):(c(),p(`div`,ve,[u[1]||=f(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Today so far`,-1),f(`span`,ye,g(C.value.today?h(S)(C.value.today.total):`—`),1),f(`span`,be,g(C.value.today?`${C.value.today.date} · partial day, UTC`:`no day in range`),1)])),f(`div`,xe,[u[2]||=f(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`7-day average`,-1),f(`span`,Se,g(C.value.avg7===void 0?`—`:h(S)(C.value.avg7)),1),f(`span`,Ce,g(C.value.avg7===void 0?`no full day yet in this range`:`per day, full days only`),1)]),f(`div`,we,[u[3]||=f(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Projected month`,-1),f(`span`,Te,g(h(S)(C.value.projection.monthUsd,0)),1),f(`span`,Ee,g(j.value),1)]),f(`div`,De,[u[4]||=f(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`LLM spend`,-1),f(`span`,Oe,g(y.value.llmAvailable?h(S)(C.value.llm.range):`—`),1),f(`span`,ke,g(I.value),1)]),f(`div`,Ae,[u[6]||=f(`span`,{class:`font-mono text-[0.6875rem] font-medium uppercase tracking-widest text-dimmed`},`Share of account`,-1),f(`span`,je,g(C.value.accountShare)+`%`,1),f(`span`,Me,[s(g(h(S)(y.value.totals.cloudUsd))+` of `+g(h(S)(y.value.account.cloudUsd))+` on `,1),E.value?(c(),p(`a`,{key:0,class:`text-primary hover:underline`,href:E.value.account,target:`_blank`,rel:`noopener noreferrer`,title:`Cloudflare account ${y.value.account.id}`},g(D.value),9,Ne)):l(``,!0),u[5]||=s(` · Cloudflare spend in range · `,-1),E.value?(c(),p(`a`,{key:1,class:`text-primary hover:underline`,href:E.value.billing,target:`_blank`,rel:`noopener noreferrer`},`billing`,8,Pe)):l(``,!0)])])]),f(`section`,Fe,[f(`div`,Ie,[u[7]||=f(`div`,null,[f(`h2`,{class:`text-[0.9375rem] font-medium`},`Daily cost`),f(`p`,{class:`text-sm text-muted`},`Stacked by component · USD list price`)],-1),f(`div`,Le,[(c(!0),p(r,null,m(x.value,(e,t)=>(c(),p(`a`,{key:e,class:`inline-flex items-center gap-1.5 no-underline hover:text-highlighted hover:underline`,href:A(e),target:`_blank`,rel:`noopener noreferrer`,title:`Open where ${e} is billed`},[f(`i`,{class:_([`inline-block size-2.5 rounded-xs`,h(F)[t%h(F).length]])},null,2),s(g(e),1)],8,Re))),128))])]),i(ae,{report:y.value,series:x.value},null,8,[`report`,`series`]),y.value.llmAvailable?y.value.days.some(e=>e.llmEstimated)?(c(),p(`p`,Be,[u[9]||=s(` A day the Anthropic cost report has not closed yet (today, and yesterday until a few hours after midnight UTC) shows its LLM figure as an estimate: the hourly usage report priced at list. The closed days are the cost report itself. `,-1),y.value.days.some(e=>e.llmUnpricedTokens>0)?(c(),p(r,{key:0},[s(` Some tokens ran under a model this page has no price for and are not in the estimate. `)],64)):l(``,!0)])):l(``,!0):(c(),p(`p`,ze,[...u[8]||=[s(` LLM spend not configured — set `,-1),f(`code`,null,`ANTHROPIC_ADMIN_KEY`,-1),s(` and the group's `,-1),f(`code`,null,`anthropicWorkspaceId`,-1),s(` to layer it in. `,-1)]]))]),f(`section`,Ve,[u[10]||=f(`div`,null,[f(`h2`,{class:`text-[0.9375rem] font-medium`},`What each cloud dollar buys`)],-1),f(`table`,He,[f(`tbody`,null,[(c(!0),p(r,null,m(T.value,e=>(c(),p(`tr`,{key:e.label,class:`border-b border-muted`},[f(`td`,Ue,[O(e.label)?(c(),p(`a`,{key:0,class:`no-underline hover:text-highlighted hover:underline`,href:O(e.label),target:`_blank`,rel:`noopener noreferrer`,title:`Open where this is billed on Cloudflare`},g(e.label),9,We)):(c(),p(r,{key:1},[s(g(e.label),1)],64))]),f(`td`,Ge,g(h(S)(e.usd)),1),f(`td`,Ke,g(Math.round(e.percent))+`%`,1),f(`td`,qe,[f(`i`,{class:`block h-2.5 rounded-xs bg-primary opacity-75`,style:t({width:`${e.percent.toFixed(1)}%`})},null,4)])]))),128))])])]),f(`section`,Je,[f(`details`,Ye,[u[13]||=f(`summary`,{class:`cursor-pointer text-sm text-muted`},`Table view — daily cost by component (USD)`,-1),f(`div`,Xe,[f(`table`,Ze,[f(`thead`,null,[f(`tr`,null,[u[11]||=f(`th`,{class:`border-b border-muted bg-(--ui-bg-muted) px-2.5 py-1.5 text-left text-xs font-medium text-muted`},` Date `,-1),(c(!0),p(r,null,m(x.value,e=>(c(),p(`th`,{key:e,class:`border-b border-muted bg-(--ui-bg-muted) px-2.5 py-1.5 text-right text-xs font-medium text-muted`},g(e),1))),128)),u[12]||=f(`th`,{class:`border-b border-muted bg-(--ui-bg-muted) px-2.5 py-1.5 text-right text-xs font-medium text-muted`},` Total `,-1)])]),f(`tbody`,null,[(c(!0),p(r,null,m(M.value,e=>(c(),p(`tr`,{key:e.date},[f(`td`,{class:`border-b border-muted px-2.5 py-1.5`,title:e.date},[s(g(L(e.date))+` `,1),y.value.range.partialLastDay&&e.date===y.value.range.to?(c(),p(`span`,$e,`(partial day`+g(e.llmEstimated?` · LLM estimated`:``)+`)`,1)):e.llmEstimated?(c(),p(`span`,et,`(LLM estimated)`)):l(``,!0)],8,Qe),(c(!0),p(r,null,m(x.value,t=>(c(),p(`td`,{key:t,class:`border-b border-muted px-2.5 py-1.5 text-right`},g(h(S)(h(w)(e,t),3)),1))),128)),f(`td`,tt,g(h(S)(e.total,3)),1)]))),128))])])])]),f(`p`,$,[u[14]||=s(` Machine-readable twin: `,-1),f(`code`,nt,`GET /costs/`+g(y.value.group)+`.json`,1),u[15]||=s(` (same Access gate). `,-1)])]),f(`footer`,rt,[f(`details`,null,[u[23]||=f(`summary`,{class:`cursor-pointer text-muted`},`How these numbers are computed`,-1),f(`div`,it,[u[21]||=f(`div`,null,[f(`b`,null,`Live.`),s(` Both billing sources are read live from this page — nothing cached, nothing stored. Cloudflare bills vCPU on active use only; memory and disk bill on the provisioned size for every second a container is awake. LLM spend is the Anthropic Admin API cost report for this group's workspace (gross, USD); a day the cost report has not closed is the Admin API usage report, hourly, priced at Anthropic list per model (input, output, cache writes, cache reads) and marked as an estimate. `)],-1),u[22]||=f(`div`,null,[f(`b`,null,`Method.`),s(` Cloudflare GraphQL Analytics, every meter a Workers deployment is billed on: `),f(`code`,null,`containersUsageAdaptiveGroups`),s(` (cpuTimeSec, allocatedMemory, allocatedDisk per app per UTC day), `),f(`code`,null,`durableObjectsPeriodicGroups`),s(` (billable `),f(`code`,null,`duration`),s(` GB-s and SQLite rows read and written per namespace), `),f(`code`,null,`durableObjectsInvocationsAdaptiveGroups`),s(` (requests per namespace), `),f(`code`,null,`durableObjectsSqlStorageGroups`),s(` (bytes stored), `),f(`code`,null,`workersInvocationsAdaptive`),s(` (requests, CPU time), `),f(`code`,null,`r2StorageAdaptiveGroups`),s(` and `),f(`code`,null,`r2OperationsAdaptiveGroups`),s(` (bytes stored, class A/B operations). Prices: vCPU $0.000020/s, memory $0.0000025/GiB-s, disk $0.00000007/GB-s, DO duration $12.50 per million GB-s, DO requests $0.15/M, SQLite rows $0.001/M read and $1.00/M written, DO storage $0.20/GB-month, Workers $0.30/M requests and $0.02/M CPU-ms, R2 $0.015/GB-month, $4.50/M class A and $0.36/M class B (deletes free). Storage is the day's peak, prorated over a 30.44-day month. Gross list price — plan fees and included allowances are not subtracted; Workers Logs volume has no analytics dataset and is not priced. `)],-1),f(`div`,null,[u[16]||=f(`b`,null,`Scope.`,-1),u[17]||=s(` Attributed to this group: the Workers `,-1),(c(!0),p(r,null,m(y.value.attribution.workers,(e,t)=>(c(),p(r,{key:e},[t>0?(c(),p(r,{key:0},[s(`, `)],64)):l(``,!0),E.value?(c(),p(`a`,{key:1,class:`font-mono hover:underline`,href:E.value.worker(e),target:`_blank`,rel:`noopener noreferrer`},g(e),9,at)):(c(),p(`code`,ot,g(e),1))],64))),128)),s(`, every Durable Object namespace they host (`+g(Object.keys(y.value.attribution.durableObjectNamespaces).length)+`), the R2 buckets named after them (`,1),(c(!0),p(r,null,m(Object.keys(y.value.attribution.r2Buckets),(e,t)=>(c(),p(r,{key:e},[t>0?(c(),p(r,{key:0},[s(`, `)],64)):l(``,!0),E.value?(c(),p(`a`,{key:1,class:`font-mono hover:underline`,href:E.value.bucket(e),target:`_blank`,rel:`noopener noreferrer`},g(e),9,st)):(c(),p(`code`,ct,g(e),1))],64))),128)),Object.keys(y.value.attribution.r2Buckets).length===0?(c(),p(r,{key:0},[s(`none`)],64)):l(``,!0),u[18]||=s(`), and the container apps mapped in `,-1),f(`code`,null,`costs.groups.`+g(y.value.group),1),s(` (`+g(Object.keys(y.value.attribution.containerApps).length)+`). Everything else in the account is priced the same way into the account total, which is what "share of account" divides by. Every figure above links to where it is billed: the `,1),E.value?(c(),p(`a`,{key:1,class:`hover:underline`,href:E.value.account,target:`_blank`,rel:`noopener noreferrer`},`Cloudflare dashboard`,8,lt)):l(``,!0),u[19]||=s(` for the account `,-1),f(`code`,null,g(y.value.account.id),1),s(g(y.value.account.name?` (${y.value.account.name})`:``)+`, and `,1),E.value?(c(),p(`a`,{key:2,class:`hover:underline`,href:E.value.anthropic,target:`_blank`,rel:`noopener noreferrer`},`Anthropic's cost page`,8,ut)):l(``,!0),u[20]||=s(` for the LLM line. `,-1)])])])])]),_:1},8,[`title`])):l(``,!0)}});export{dt 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 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-BDAKF1Bp.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-BQNoaXO6.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-BDAKF1Bp.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};
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-BQNoaXO6.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};