@edspencer/paddock 0.69.0 → 0.70.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 (76) hide show
  1. package/package.json +1 -1
  2. package/packages/server/dist/agent-errors.js +7 -1
  3. package/packages/server/dist/cli/paddock.js +12 -7
  4. package/packages/server/dist/config.d.ts +7 -5
  5. package/packages/server/dist/config.js +0 -1
  6. package/packages/server/dist/instance-config.js +1 -2
  7. package/packages/server/dist/recovery-config.d.ts +0 -6
  8. package/packages/server/dist/recovery-config.js +0 -4
  9. package/packages/server/package.json +1 -1
  10. package/packages/web/dist/assets/{Chip-B8UU8Zpr.js → Chip-C8a-t439.js} +1 -1
  11. package/packages/web/dist/assets/DiscoverPage-C1khyCvD.js +2 -0
  12. package/packages/web/dist/assets/{DiscoverView-CKN93BnT.js → DiscoverView-DS_Z9xKH.js} +1 -1
  13. package/packages/web/dist/assets/{InstanceConfigPage-COc2rsu6.js → InstanceConfigPage-B1ei1FDo.js} +1 -1
  14. package/packages/web/dist/assets/{MarkdownRenderer-BlUYSdHR.js → MarkdownRenderer-DCj_ZwVG.js} +1 -1
  15. package/packages/web/dist/assets/{ProjectMenu-Davm1-P7.js → ProjectMenu-B7dGZSFB.js} +1 -1
  16. package/packages/web/dist/assets/{ProjectRedirect-COrC7Yvg.js → ProjectRedirect-bstvMvM9.js} +1 -1
  17. package/packages/web/dist/assets/{ProjectView-WIODXM93.js → ProjectView-iuiUIoIl.js} +11 -11
  18. package/packages/web/dist/assets/{ProjectsGrid-CfDehr5s.js → ProjectsGrid-DKvySDUQ.js} +1 -1
  19. package/packages/web/dist/assets/{RootHome-DniHfYAw.js → RootHome-CD_37qb-.js} +1 -1
  20. package/packages/web/dist/assets/{Surfaces-GzOkJJHQ.js → Surfaces-1dBayrsj.js} +1 -1
  21. package/packages/web/dist/assets/{arc-_I2xwzbW.js → arc-BJPb3ViJ.js} +1 -1
  22. package/packages/web/dist/assets/{architectureDiagram-3BPJPVTR-GW4T_vCB.js → architectureDiagram-3BPJPVTR-PkLOC5wV.js} +1 -1
  23. package/packages/web/dist/assets/{blockDiagram-GPEHLZMM-rpMzVG3O.js → blockDiagram-GPEHLZMM-IPduhNH-.js} +1 -1
  24. package/packages/web/dist/assets/{c4Diagram-AAUBKEIU-CwxpNlW3.js → c4Diagram-AAUBKEIU-dKTYV1Vq.js} +1 -1
  25. package/packages/web/dist/assets/channel-BhrgMiqg.js +2 -0
  26. package/packages/web/dist/assets/{chunk-2J33WTMH-BG9SyFJ-.js → chunk-2J33WTMH-B5C6geyg.js} +1 -1
  27. package/packages/web/dist/assets/{chunk-4BX2VUAB-DJlbnTd4.js → chunk-4BX2VUAB-1BRhFRhF.js} +1 -1
  28. package/packages/web/dist/assets/{chunk-55IACEB6-C-VMlU4m.js → chunk-55IACEB6-DNv-sTiI.js} +1 -1
  29. package/packages/web/dist/assets/{chunk-727SXJPM-Wigu1170.js → chunk-727SXJPM-CWezuVkx.js} +1 -1
  30. package/packages/web/dist/assets/{chunk-AQP2D5EJ-C5CFWtjs.js → chunk-AQP2D5EJ-Bt4yEQnu.js} +1 -1
  31. package/packages/web/dist/assets/{chunk-FMBD7UC4-hQaZU9Hi.js → chunk-FMBD7UC4-lb_8q4JY.js} +1 -1
  32. package/packages/web/dist/assets/{chunk-ND2GUHAM-AMO00QGi.js → chunk-ND2GUHAM-DOwgGlQ_.js} +1 -1
  33. package/packages/web/dist/assets/{chunk-QZHKN3VN-T3F7CT-B.js → chunk-QZHKN3VN-BanKpY4q.js} +1 -1
  34. package/packages/web/dist/assets/classDiagram-4FO5ZUOK-Ho1IMdjg.js +2 -0
  35. package/packages/web/dist/assets/classDiagram-v2-Q7XG4LA2-Ho1IMdjg.js +2 -0
  36. package/packages/web/dist/assets/{core-D1JA8p71.js → core-CAsyoNAa.js} +1 -1
  37. package/packages/web/dist/assets/{cose-bilkent-S5V4N54A-C_fPZY7X.js → cose-bilkent-S5V4N54A-sVaVkwMI.js} +1 -1
  38. package/packages/web/dist/assets/{dagre-BM42HDAG-nLjMp3c7.js → dagre-BM42HDAG-C9pKHSMo.js} +1 -1
  39. package/packages/web/dist/assets/{diagram-2AECGRRQ-qYzVcYYg.js → diagram-2AECGRRQ-CHdrmCfX.js} +1 -1
  40. package/packages/web/dist/assets/{diagram-5GNKFQAL-DVFKMWv0.js → diagram-5GNKFQAL-4UTa2Dfa.js} +1 -1
  41. package/packages/web/dist/assets/{diagram-KO2AKTUF-B8T7qnCR.js → diagram-KO2AKTUF-NidpfVwW.js} +1 -1
  42. package/packages/web/dist/assets/{diagram-LMA3HP47-9-_-MiG8.js → diagram-LMA3HP47-ictQj03T.js} +1 -1
  43. package/packages/web/dist/assets/{diagram-OG6HWLK6-D4eE55Vg.js → diagram-OG6HWLK6-B7dTLMHC.js} +1 -1
  44. package/packages/web/dist/assets/{erDiagram-TEJ5UH35-adlALhlq.js → erDiagram-TEJ5UH35-C2QYYzJ8.js} +1 -1
  45. package/packages/web/dist/assets/{flowDiagram-I6XJVG4X-jhJEXK0D.js → flowDiagram-I6XJVG4X-D2rcjSZ9.js} +1 -1
  46. package/packages/web/dist/assets/{ganttDiagram-6RSMTGT7-CHGNR8Fk.js → ganttDiagram-6RSMTGT7-BQcXTYzg.js} +1 -1
  47. package/packages/web/dist/assets/{gitGraphDiagram-PVQCEYII-tBQ_60zD.js → gitGraphDiagram-PVQCEYII-DwB2Vqxa.js} +1 -1
  48. package/packages/web/dist/assets/index-BNzTD4hA.css +1 -0
  49. package/packages/web/dist/assets/{index-Djl4krRr.js → index-BeuEs7dL.js} +2 -2
  50. package/packages/web/dist/assets/{infoDiagram-5YYISTIA-D_LJZit4.js → infoDiagram-5YYISTIA-BoK4Mawg.js} +1 -1
  51. package/packages/web/dist/assets/{ishikawaDiagram-YF4QCWOH-CLsVMtFo.js → ishikawaDiagram-YF4QCWOH-DPP9svhg.js} +1 -1
  52. package/packages/web/dist/assets/{journeyDiagram-JHISSGLW-DKLfsczG.js → journeyDiagram-JHISSGLW-TrggodYk.js} +1 -1
  53. package/packages/web/dist/assets/{kanban-definition-UN3LZRKU-CG1dRRin.js → kanban-definition-UN3LZRKU-Bh69hRSR.js} +1 -1
  54. package/packages/web/dist/assets/{linear-Bc0TsEWL.js → linear-C1iYMpBz.js} +1 -1
  55. package/packages/web/dist/assets/{mermaid.core-7NBz7_-Q.js → mermaid.core-BZDABcuq.js} +4 -4
  56. package/packages/web/dist/assets/{mindmap-definition-RKZ34NQL-DD-2NsoA.js → mindmap-definition-RKZ34NQL-DTJON3dS.js} +1 -1
  57. package/packages/web/dist/assets/{pieDiagram-4H26LBE5-BTYpRP3j.js → pieDiagram-4H26LBE5-BxtFV74I.js} +1 -1
  58. package/packages/web/dist/assets/{quadrantDiagram-W4KKPZXB-DScmlT0o.js → quadrantDiagram-W4KKPZXB-D2Ar8kmO.js} +1 -1
  59. package/packages/web/dist/assets/{requirementDiagram-4Y6WPE33-BzLuYCY3.js → requirementDiagram-4Y6WPE33-DiLSfeSQ.js} +1 -1
  60. package/packages/web/dist/assets/{sankeyDiagram-5OEKKPKP-CH9nUHfL.js → sankeyDiagram-5OEKKPKP-D_CRQc7j.js} +1 -1
  61. package/packages/web/dist/assets/{sequenceDiagram-3UESZ5HK-vQjaE3Ay.js → sequenceDiagram-3UESZ5HK-DjtfcRNV.js} +1 -1
  62. package/packages/web/dist/assets/{stateDiagram-AJRCARHV-C76FMvr4.js → stateDiagram-AJRCARHV-CzEtmYLV.js} +1 -1
  63. package/packages/web/dist/assets/stateDiagram-v2-BHNVJYJU-pM8fIOir.js +2 -0
  64. package/packages/web/dist/assets/{timeline-definition-PNZ67QCA-zjhYOHh7.js → timeline-definition-PNZ67QCA-DXKspEG3.js} +1 -1
  65. package/packages/web/dist/assets/{vennDiagram-CIIHVFJN-BpyreyjG.js → vennDiagram-CIIHVFJN-B_tXRMHH.js} +1 -1
  66. package/packages/web/dist/assets/{wardley-L42UT6IY-CugQjZZ8.js → wardley-L42UT6IY-DNaNoaJm.js} +1 -1
  67. package/packages/web/dist/assets/{wardleyDiagram-YWT4CUSO-CTpxg9iQ.js → wardleyDiagram-YWT4CUSO-BuVDpC8s.js} +1 -1
  68. package/packages/web/dist/assets/{xychartDiagram-2RQKCTM6-COJLOF01.js → xychartDiagram-2RQKCTM6-Cqtew2PA.js} +1 -1
  69. package/packages/web/dist/index.html +2 -2
  70. package/packages/web/dist/sw.js +1 -1
  71. package/packages/web/dist/assets/DiscoverPage-vz1s8GYQ.js +0 -2
  72. package/packages/web/dist/assets/channel-nPAjQX8p.js +0 -2
  73. package/packages/web/dist/assets/classDiagram-4FO5ZUOK-DuI-4XNG.js +0 -2
  74. package/packages/web/dist/assets/classDiagram-v2-Q7XG4LA2-DuI-4XNG.js +0 -2
  75. package/packages/web/dist/assets/index-CJT1g4_p.css +0 -1
  76. package/packages/web/dist/assets/stateDiagram-v2-BHNVJYJU-CWy9AQvb.js +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edspencer/paddock",
3
- "version": "0.69.0",
3
+ "version": "0.70.0",
4
4
  "description": "Project-first launchpad for Claude Code: server-hosted, persistent, resumable sessions organized by project.",
5
5
  "keywords": [
6
6
  "claude",
@@ -44,8 +44,14 @@ const KNOWN_CAUSES = [
44
44
  // Anchored to `claude` specifically. A bare /ENOENT/ would claim a missing
45
45
  // CLI for any file the engine failed to open, which is a confident wrong
46
46
  // answer — worse than the raw error it replaces.
47
+ //
48
+ // Name only what actually reads PATH (#771): the CLI runtime. The sweeper
49
+ // is always on it; triggers and chat turns only on `driveMode: batch`. An
50
+ // earlier wording said "the sweeper and triggers", which sent an operator
51
+ // on the default `session` mode to check the wrong thing.
47
52
  pattern: /ENOENT[^\n]{0,40}claude|claude: (command )?not found/i,
48
- cause: "the `claude` CLI is not on PATH (needed by the sweeper and triggers)",
53
+ cause: "the `claude` CLI is not on PATH (needed by the sweeper, and by " +
54
+ "triggers/turns on `driveMode: batch`)",
49
55
  },
50
56
  ];
51
57
  /**
@@ -78,14 +78,19 @@ function readVersion() {
78
78
  /**
79
79
  * Put our bundled `claude` on PATH for child processes.
80
80
  *
81
- * Chat turns do NOT need this: they run herdctl's SDK runtime, which resolves
82
- * the binary from the Claude Agent SDK's own platform package via
83
- * `require.resolve` and never consults PATH. But the post-turn sweeper and all
84
- * triggers are one-shot `trigger()` calls on the CLI runtime, which does
85
- * `execa("claude", …)` — by name, without execa's `preferLocal`, so a local
86
- * install is invisible to it unless PATH says otherwise.
81
+ * Chat turns do NOT need this on the default `driveMode: session`: they run
82
+ * herdctl's SDK runtime, which resolves the binary from the Claude Agent SDK's
83
+ * own platform package via `require.resolve` and never consults PATH. The
84
+ * post-turn sweeper is the one unconditional user: always a one-shot
85
+ * `trigger()` call on the CLI runtime, which does `execa("claude", …)` — by
86
+ * name, without execa's `preferLocal`, so a local install is invisible to it
87
+ * unless PATH says otherwise. Triggers join it there only on `driveMode:
88
+ * batch`: a trigger resolves its drive mode exactly like a chat does
89
+ * (per-project override else `cfg.driveMode` — `resolveDriveMode` in
90
+ * ws-triggers.ts), so on a stock instance no trigger consults PATH either.
87
91
  *
88
- * Without this, chats work and every sweep/trigger fails (logged, non-fatal).
92
+ * Without this, chats work and every sweep fails (logged, non-fatal) — plus
93
+ * every trigger and turn on `driveMode: batch`.
89
94
  */
90
95
  function addBundledBinsToPath() {
91
96
  const owner = findUp(path.join("node_modules", ".bin"));
@@ -386,11 +386,14 @@ export interface PaddockConfig {
386
386
  warnings: string[];
387
387
  };
388
388
  /**
389
- * Instance default for the hook-management MCP (Epic G / G5, GG-4) — the
390
- * `mcp__paddock_manage__{list,set,remove}_hook` tools that let a project agent
391
- * declare/edit/delete its own event hooks. A sibling of {@link selfMcpWriteEnabled}:
389
+ * Instance default for the hook-management MCP (Epic G / G5, GG-4) — now the
390
+ * unified TRIGGER tools `mcp__paddock_manage__{list_triggers,set_trigger,
391
+ * remove_trigger,run_trigger}` that let a project agent declare/edit/delete/fire
392
+ * its own triggers. Epic T / T3 collapsed the former `*_hook` and `*_schedule`
393
+ * verbs into these; the flag and its env var kept the `hooks` spelling.
394
+ * A sibling of {@link selfMcpWriteEnabled}:
392
395
  * OFF by default (opt-in), and only surfaces when the self-MCP write tools are also
393
- * present (the hook tools live on the same injected server, appended in the write
396
+ * present (the trigger tools live on the same injected server, appended in the write
394
397
  * block). Driven by `PADDOCK_HOOKS_MCP`; accepts 1/true/yes. A per-project
395
398
  * `hooksMcpEnabled` override wins at dispatch (resolved via
396
399
  * {@link import("./hook-config.js").resolveHooksMcpEnabled}), the same
@@ -580,7 +583,6 @@ export interface PaddockConfigFile {
580
583
  autoReDrive?: boolean | string;
581
584
  debounceMs?: number | string;
582
585
  maxRetries?: number | string;
583
- limboTimeoutMs?: number | string;
584
586
  };
585
587
  /**
586
588
  * Inbound composer-attachment config (issue #328). Every field optional; a
@@ -456,7 +456,6 @@ function loadRecoveryConfig(file) {
456
456
  autoReDrive: loadRecoveryBool("PADDOCK_RECOVERY_AUTODRIVE", f.autoReDrive, DEFAULT_RECOVERY.autoReDrive),
457
457
  debounceMs: loadRecoveryInt("PADDOCK_RECOVERY_DEBOUNCE_MS", f.debounceMs, DEFAULT_RECOVERY.debounceMs),
458
458
  maxRetries: loadRecoveryInt("PADDOCK_RECOVERY_MAX_RETRIES", f.maxRetries, DEFAULT_RECOVERY.maxRetries),
459
- limboTimeoutMs: loadRecoveryInt("PADDOCK_RECOVERY_LIMBO_MS", f.limboTimeoutMs, DEFAULT_RECOVERY.limboTimeoutMs),
460
459
  };
461
460
  }
462
461
  /**
@@ -254,7 +254,7 @@ export const FIELDS = [
254
254
  { key: "environmentPrompt", group: "capabilities", label: "Environment prompt", help: "Appended to every keeper turn's system prompt: what the agent should know about rendering into Paddock rather than a terminal. Clear it to append nothing.", type: "text", envVars: ["PADDOCK_ENVIRONMENT_PROMPT"], envShadowWhenDefined: true, default: DEFAULT_ENVIRONMENT_PROMPT, editable: true, coerce: promptText },
255
255
  { key: "selfMcpEnabled", group: "capabilities", label: "Self-management MCP (read)", help: "Let keepers list/read projects and other chats.", type: "boolean", envVars: ["PADDOCK_SELF_MCP"], default: false, editable: true, coerce: asBool },
256
256
  { key: "selfMcpWriteEnabled", group: "capabilities", label: "Self-management MCP (write)", help: "Let keepers create/fork/message chats (needs read enabled too).", type: "boolean", envVars: ["PADDOCK_SELF_MCP_WRITE"], default: false, editable: true, coerce: asBool },
257
- { key: "selfMcpProjectsEnabled", group: "capabilities", label: "Self-management MCP (projects)", help: "Let keepers create whole new projects, cloning a repo when repo-backed (needs self-MCP write).", type: "boolean", envVars: ["PADDOCK_SELF_MCP_PROJECTS"], default: false, editable: true, coerce: asBool },
257
+ { key: "selfMcpProjectsEnabled", group: "capabilities", label: "Self-management MCP (projects)", help: "Let keepers create new projects and promote existing ones — including a git clone of a repo URL the agent supplies (needs self-MCP write).", type: "boolean", envVars: ["PADDOCK_SELF_MCP_PROJECTS"], default: false, editable: true, coerce: asBool },
258
258
  { key: "maxSpawnDepth", group: "capabilities", label: "Max spawn depth", help: "How deep a spawn tree may grow before children lose the self-MCP.", type: "number", envVars: ["PADDOCK_MAX_SPAWN_DEPTH"], default: DEFAULT_MAX_SPAWN_DEPTH, editable: true, coerce: spawnDepth },
259
259
  { key: "scheduleMutationEnabled", group: "capabilities", label: "Schedule mutation", help: "Allow programmatic schedule add/remove at runtime.", type: "boolean", envVars: ["PADDOCK_SCHEDULE_MUTATION"], default: false, editable: true, coerce: asBool },
260
260
  { key: "hooksMcpEnabled", group: "capabilities", label: "Hooks MCP", help: "Let agents declare/edit their own event hooks (needs self-MCP write).", type: "boolean", envVars: ["PADDOCK_HOOKS_MCP"], default: false, editable: true, coerce: asBool },
@@ -264,7 +264,6 @@ export const FIELDS = [
264
264
  { key: "recovery.autoReDrive", group: "recovery", label: "Auto re-drive", type: "boolean", envVars: ["PADDOCK_RECOVERY_AUTODRIVE"], default: DEFAULT_RECOVERY.autoReDrive, editable: true, coerce: asBool },
265
265
  { key: "recovery.debounceMs", group: "recovery", label: "Debounce (ms)", type: "number", envVars: ["PADDOCK_RECOVERY_DEBOUNCE_MS"], default: DEFAULT_RECOVERY.debounceMs, editable: true, coerce: nonNegInt },
266
266
  { key: "recovery.maxRetries", group: "recovery", label: "Max retries", type: "number", envVars: ["PADDOCK_RECOVERY_MAX_RETRIES"], default: DEFAULT_RECOVERY.maxRetries, editable: true, coerce: nonNegInt },
267
- { key: "recovery.limboTimeoutMs", group: "recovery", label: "Limbo timeout (ms)", type: "number", envVars: ["PADDOCK_RECOVERY_LIMBO_MS"], default: DEFAULT_RECOVERY.limboTimeoutMs, editable: true, coerce: nonNegInt },
268
267
  // Attachments (issue #328).
269
268
  { key: "attachments.enabled", group: "attachments", label: "Enabled", type: "boolean", envVars: ["PADDOCK_ATTACHMENTS_ENABLED"], default: DEFAULT_ATTACHMENTS.enabled, editable: true, coerce: asBool },
270
269
  { key: "attachments.maxFileSizeMb", group: "attachments", label: "Max file size (MB)", type: "number", envVars: ["PADDOCK_ATTACHMENTS_MAX_FILE_SIZE_MB"], default: DEFAULT_ATTACHMENTS.maxFileSizeMb, editable: true, coerce: posInt },
@@ -67,12 +67,6 @@ export interface RecoveryConfig {
67
67
  * `PADDOCK_RECOVERY_MAX_RETRIES`.
68
68
  */
69
69
  maxRetries: number;
70
- /**
71
- * Layer 2 backstop — if a kept-alive keeper session shows no activity for this
72
- * many ms after a killed-task notification, surface it as stuck. `0` disables
73
- * the backstop (the default). Env `PADDOCK_RECOVERY_LIMBO_MS`.
74
- */
75
- limboTimeoutMs: number;
76
70
  }
77
71
  /**
78
72
  * A per-project recovery override as stored in `project.yaml` — every field
@@ -43,7 +43,6 @@ export const DEFAULT_RECOVERY = Object.freeze({
43
43
  autoReDrive: false,
44
44
  debounceMs: 5000,
45
45
  maxRetries: 1,
46
- limboTimeoutMs: 0,
47
46
  });
48
47
  /** The `<status>` values a killed-at-turn-boundary task notification carries. */
49
48
  const TERMINATED_STATUSES = new Set(["killed", "stopped"]);
@@ -81,8 +80,6 @@ export function sanitizeRecoveryOverride(value) {
81
80
  out.debounceMs = o.debounceMs;
82
81
  if (isNonNegativeInt(o.maxRetries))
83
82
  out.maxRetries = o.maxRetries;
84
- if (isNonNegativeInt(o.limboTimeoutMs))
85
- out.limboTimeoutMs = o.limboTimeoutMs;
86
83
  return Object.keys(out).length > 0 ? out : undefined;
87
84
  }
88
85
  /**
@@ -100,6 +97,5 @@ export function resolveRecoveryConfig(override, instanceDefault) {
100
97
  autoReDrive: clean.autoReDrive ?? instanceDefault.autoReDrive,
101
98
  debounceMs: clean.debounceMs ?? instanceDefault.debounceMs,
102
99
  maxRetries: clean.maxRetries ?? instanceDefault.maxRetries,
103
- limboTimeoutMs: clean.limboTimeoutMs ?? instanceDefault.limboTimeoutMs,
104
100
  };
105
101
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paddock/server",
3
- "version": "0.69.0",
3
+ "version": "0.70.0",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -1,2 +1,2 @@
1
- import{j as r,l as t,r as d}from"./index-Djl4krRr.js";const u=["w-full rounded-lg border border-edge-strong bg-surface-sunken px-3 py-2 text-sm text-fg","outline-none motion-fast transition-[border-color,box-shadow]","focus:border-accent focus:ring-2 focus:ring-accent/25","disabled:cursor-not-allowed disabled:opacity-60","aria-[invalid=true]:border-danger aria-[invalid=true]:focus:ring-danger/25"].join(" ");function p({className:e,...s}){return r.jsx("input",{className:t(u,e),...s})}function m({className:e,...s}){return r.jsx("textarea",{className:t(u,"resize-y",e),...s})}function h({className:e,...s}){return r.jsx("select",{className:t(u,e),...s})}function j({checked:e,onChange:s,label:a,disabled:n,id:o,className:c}){const i=d.useId(),l=o??i;return r.jsxs("label",{htmlFor:l,className:t("relative inline-block shrink-0 cursor-pointer",c),children:[r.jsx("input",{id:l,type:"checkbox","aria-label":a,className:"peer sr-only",checked:e,disabled:n,onChange:x=>s(x.target.checked)}),r.jsx("span",{className:t("block h-[18px] w-8 rounded-full bg-edge-strong","motion-fast transition-colors","after:absolute after:left-0.5 after:top-0.5 after:h-3.5 after:w-3.5 after:rounded-full","after:bg-surface-raised after:shadow-2xs after:transition-transform after:content-['']","peer-checked:bg-accent-solid peer-checked:after:translate-x-3.5","peer-focus-visible:ring-2 peer-focus-visible:ring-accent/50","peer-disabled:opacity-50")})]})}function w({label:e,description:s,indeterminate:a=!1,className:n,...o}){const c=d.useRef(null);d.useEffect(()=>{c.current&&(c.current.indeterminate=a)},[a]);const i=r.jsx("input",{ref:c,type:"checkbox",...a?{"aria-checked":"mixed"}:{},className:t("h-4 w-4 shrink-0 cursor-pointer rounded border-edge-strong accent-[var(--accent-solid)]","disabled:cursor-not-allowed disabled:opacity-50",e?"mt-0.5":"",n),...o});return e?r.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-sm text-fg",children:[i,r.jsxs("span",{className:"min-w-0",children:[e,s&&r.jsx("span",{className:"block text-xs leading-snug text-fg-muted",children:s})]})]}):i}const f={neutral:"bg-surface-active text-fg-muted",accent:"bg-accent-soft text-accent",success:"bg-success-soft text-success",warn:"bg-warn-soft text-warn",danger:"bg-danger-soft text-danger",info:"bg-info-soft text-info",lineage:"bg-lineage-soft text-lineage"},g={neutral:"bg-fg-subtle",accent:"bg-accent-solid",success:"bg-success-solid",warn:"bg-warn-solid",danger:"bg-danger-solid",info:"bg-info-solid",lineage:"bg-lineage-solid"};function N({tone:e="neutral",shape:s="tag",size:a="md",dot:n=!1,icon:o,title:c,className:i,children:l}){return r.jsxs("span",{title:c,className:t("inline-flex items-center gap-1 font-medium leading-none",s==="pill"?"rounded-full px-2 py-0.5":"rounded-md px-1.5 py-0.5",a==="sm"?"text-3xs":"text-2xs",f[e],i),children:[n&&r.jsx("span",{className:t("h-1.5 w-1.5 shrink-0 rounded-full",g[e])}),o,l]})}function k({tone:e="neutral",pulse:s=!1,className:a}){return r.jsx("span",{className:t("inline-block h-2 w-2 shrink-0 rounded-full",g[e],s&&"animate-pulse",a)})}function y({tone:e="info",icon:s,className:a,children:n}){const o={neutral:"border-edge",accent:"border-accent-edge",success:"border-success-edge",warn:"border-warn-edge",danger:"border-danger-edge",info:"border-info-edge",lineage:"border-lineage-edge"};return r.jsxs("div",{role:e==="danger"?"alert":void 0,className:t("flex items-start gap-2 rounded-lg border px-3 py-2 text-sm",f[e],o[e],a),children:[s&&r.jsx("span",{className:"mt-0.5 shrink-0",children:s}),r.jsx("div",{className:"min-w-0",children:n})]})}export{N as C,p as I,k as S,j as T,y as a,h as b,m as c,w as d};
1
+ import{j as r,l as t,r as d}from"./index-BeuEs7dL.js";const u=["w-full rounded-lg border border-edge-strong bg-surface-sunken px-3 py-2 text-sm text-fg","outline-none motion-fast transition-[border-color,box-shadow]","focus:border-accent focus:ring-2 focus:ring-accent/25","disabled:cursor-not-allowed disabled:opacity-60","aria-[invalid=true]:border-danger aria-[invalid=true]:focus:ring-danger/25"].join(" ");function p({className:e,...s}){return r.jsx("input",{className:t(u,e),...s})}function m({className:e,...s}){return r.jsx("textarea",{className:t(u,"resize-y",e),...s})}function h({className:e,...s}){return r.jsx("select",{className:t(u,e),...s})}function j({checked:e,onChange:s,label:a,disabled:n,id:o,className:c}){const i=d.useId(),l=o??i;return r.jsxs("label",{htmlFor:l,className:t("relative inline-block shrink-0 cursor-pointer",c),children:[r.jsx("input",{id:l,type:"checkbox","aria-label":a,className:"peer sr-only",checked:e,disabled:n,onChange:x=>s(x.target.checked)}),r.jsx("span",{className:t("block h-[18px] w-8 rounded-full bg-edge-strong","motion-fast transition-colors","after:absolute after:left-0.5 after:top-0.5 after:h-3.5 after:w-3.5 after:rounded-full","after:bg-surface-raised after:shadow-2xs after:transition-transform after:content-['']","peer-checked:bg-accent-solid peer-checked:after:translate-x-3.5","peer-focus-visible:ring-2 peer-focus-visible:ring-accent/50","peer-disabled:opacity-50")})]})}function w({label:e,description:s,indeterminate:a=!1,className:n,...o}){const c=d.useRef(null);d.useEffect(()=>{c.current&&(c.current.indeterminate=a)},[a]);const i=r.jsx("input",{ref:c,type:"checkbox",...a?{"aria-checked":"mixed"}:{},className:t("h-4 w-4 shrink-0 cursor-pointer rounded border-edge-strong accent-[var(--accent-solid)]","disabled:cursor-not-allowed disabled:opacity-50",e?"mt-0.5":"",n),...o});return e?r.jsxs("label",{className:"flex cursor-pointer items-start gap-2 text-sm text-fg",children:[i,r.jsxs("span",{className:"min-w-0",children:[e,s&&r.jsx("span",{className:"block text-xs leading-snug text-fg-muted",children:s})]})]}):i}const f={neutral:"bg-surface-active text-fg-muted",accent:"bg-accent-soft text-accent",success:"bg-success-soft text-success",warn:"bg-warn-soft text-warn",danger:"bg-danger-soft text-danger",info:"bg-info-soft text-info",lineage:"bg-lineage-soft text-lineage"},g={neutral:"bg-fg-subtle",accent:"bg-accent-solid",success:"bg-success-solid",warn:"bg-warn-solid",danger:"bg-danger-solid",info:"bg-info-solid",lineage:"bg-lineage-solid"};function N({tone:e="neutral",shape:s="tag",size:a="md",dot:n=!1,icon:o,title:c,className:i,children:l}){return r.jsxs("span",{title:c,className:t("inline-flex items-center gap-1 font-medium leading-none",s==="pill"?"rounded-full px-2 py-0.5":"rounded-md px-1.5 py-0.5",a==="sm"?"text-3xs":"text-2xs",f[e],i),children:[n&&r.jsx("span",{className:t("h-1.5 w-1.5 shrink-0 rounded-full",g[e])}),o,l]})}function k({tone:e="neutral",pulse:s=!1,className:a}){return r.jsx("span",{className:t("inline-block h-2 w-2 shrink-0 rounded-full",g[e],s&&"animate-pulse",a)})}function y({tone:e="info",icon:s,className:a,children:n}){const o={neutral:"border-edge",accent:"border-accent-edge",success:"border-success-edge",warn:"border-warn-edge",danger:"border-danger-edge",info:"border-info-edge",lineage:"border-lineage-edge"};return r.jsxs("div",{role:e==="danger"?"alert":void 0,className:t("flex items-start gap-2 rounded-lg border px-3 py-2 text-sm",f[e],o[e],a),children:[s&&r.jsx("span",{className:"mt-0.5 shrink-0",children:s}),r.jsx("div",{className:"min-w-0",children:n})]})}export{N as C,p as I,k as S,j as T,y as a,h as b,m as c,w as d};
2
2
 
@@ -0,0 +1,2 @@
1
+ import{j as r}from"./index-BeuEs7dL.js";import{D as o}from"./DiscoverView-DS_Z9xKH.js";import"./Surfaces-1dBayrsj.js";import"./Chip-C8a-t439.js";function s(){return r.jsx(o,{})}export{s as DiscoverPage};
2
+
@@ -1,2 +1,2 @@
1
- import{a as ne,u as re,H as ae,r as l,b as P,j as s,M as oe,E as ie,D as Q,J as U,K as ce,l as F,O as de,h as le}from"./index-Djl4krRr.js";import{E as O,B as R,C as he}from"./Surfaces-GzOkJJHQ.js";import{a as W,d as M,C as T,T as K}from"./Chip-B8UU8Zpr.js";function ue(e){const t={};for(const r of e)t[r.path]={checked:!0,expanded:!1,loading:!1,error:null};return t}function pe(e){if(!e.sessions||!e.selected)return e.checked?"on":"off";const t=e.sessions.sessions.length,r=e.selected.size;return t===0||r===0?"off":r===t?"on":"mixed"}function C(e,t){return e.sessions&&e.selected?e.selected.size:e.checked?t.sessionCount:0}function me(e,t){return t.reduce((r,a)=>r+C(e[a.path]??z(),a),0)}function xe(e,t){return t.filter(r=>C(e[r.path]??z(),r)>0)}function fe(e,t,r){const a=e[t];if(!a)return e;const n={...a,checked:r};return a.sessions&&(n.selected=r?new Set(a.sessions.sessions.map(d=>d.sessionId)):new Set),{...e,[t]:n}}function ge(e,t,r){const a=e[t];if(!a||!a.sessions)return e;const n=new Set(a.selected??[]);return n.delete(r)||n.add(r),{...e,[t]:{...a,selected:n,checked:n.size>0}}}function je(e,t,r){const a=e[t];if(!a)return e;const n=a.checked?new Set(r.sessions.map(d=>d.sessionId)):new Set;return{...e,[t]:{...a,sessions:r,selected:n,loading:!1,error:null}}}function D(e,t,r){const a=e[t];return a?{...e,[t]:{...a,...r}}:e}function be(e,t){const r=e??z();return C(r,t)===0?null:r.sessions&&r.selected?{sessionIds:[...r.selected]}:{}}function z(){return{checked:!1,expanded:!1,loading:!1,error:null}}function ye(e){return e.error!==void 0?e.stage==="create"?"danger":"warn":e.adopted>0?"success":"warn"}async function we(e,t,r){let a;try{a=await e.createProject({name:t.name,slug:t.suggestedSlug,path:t.path,managed:!1})}catch(n){return{stage:"create",adopted:0,skipped:[],error:V(n)}}try{const n=await e.adoptChats(a.slug,{sourceCwd:a.workingDir,...r.sessionIds?{sessionIds:r.sessionIds}:{}});return{project:a,adopted:n.adopted.length,skipped:n.skipped}}catch(n){return{stage:"import",project:a,adopted:0,skipped:[],error:V(n)}}}async function Ne(e,t,r){const a=[];for(const n of t){r(n.candidate.path,"running");const d=await we(e,n.candidate,n.plan);a.push(d),r(n.candidate.path,"done",d)}return a}const ve={sidechain:"sub-agent transcript","already-adopted":"already imported","destination-exists":"a chat with that id already exists here","attributed-to-run":"belongs to a Paddock run",unreadable:"transcript unreadable","placement-failed":"copy failed","record-failed":"could not be recorded"};function J(e){if(e.length===0)return"";const t=[...new Set(e.map(r=>ve[r.reason]??r.reason))];return`${e.length} skipped (${t.join(", ")})`}function ke(e,t){var h;if(e.stage==="create")return`Couldn't create the project: ${e.error}`;const r=((h=e.project)==null?void 0:h.slug)??t.suggestedSlug;if(e.stage==="import")return`Project “${r}” was created, but importing its chats failed: ${e.error}. It is there and empty — you can import them from the project itself.`;if(e.adopted===0){const m=J(e.skipped);return t.recordedPath!==void 0?`Project “${r}” was created but no chats came with it. Its transcripts record ${t.recordedPath}, a different spelling of ${t.path}, and an import matches on the exact path.`:m?`Project “${r}” was created but no chats came with it — ${m}.`:`Project “${r}” was created but no chats came with it.`}const a=e.adopted,n=J(e.skipped),d=`Imported ${a} chat${a===1?"":"s"} into “${r}”`;return n?`${d} — ${n}.`:`${d}.`}function V(e){return e instanceof Error?e.message:String(e)}function ze({firstRun:e=!1,onLeave:t}){const r=ne(),{refresh:a}=re(),n=ae(),[d,h]=l.useState(!1),[m,c]=l.useState(!1),[x,$]=l.useState(null),[g,u]=l.useState(null),[v,I]=l.useState(!0),[j,w]=l.useState({}),[k,A]=l.useState(!1),[X,H]=l.useState({}),[E,B]=l.useState({}),[S,Y]=l.useState(!1);l.useEffect(()=>{let o=!0;return I(!0),u(null),P.discover({includeNonGit:d,includeOutsideHome:m}).then(i=>{o&&($(i),w(ue(i.candidates)),I(!1))}).catch(i=>{o&&(u(i instanceof Error?i.message:"Discovery failed"),I(!1))}),()=>{o=!1}},[d,m]);const y=(x==null?void 0:x.candidates)??[],G=l.useMemo(()=>me(j,y),[j,y]),b=l.useMemo(()=>xe(j,y),[j,y]),Z=l.useCallback(o=>{w(p=>{const f=p[o.path];if(!f)return p;const N=D(p,o.path,{expanded:!f.expanded});return f.expanded||f.sessions||f.loading?N:D(N,o.path,{loading:!0,error:null})});const i=j[o.path];!i||i.expanded||i.sessions||i.loading||P.discoverSessions(o.path).then(p=>w(f=>je(f,o.path,p))).catch(p=>w(f=>D(f,o.path,{loading:!1,error:p instanceof Error?p.message:"Could not read this directory's sessions"})))},[j]),L=l.useCallback(async()=>{if(k)return;A(!0),H(Object.fromEntries(b.map(i=>[i.path,"pending"]))),B({});const o=b.map(i=>({candidate:i,plan:be(j[i.path],i)??{}}));await Ne(P,o,(i,p,f)=>{H(N=>({...N,[i]:p})),f&&B(N=>({...N,[i]:f}))}),A(!1),Y(!0),await a()},[b,j,k,a]),ee=l.useCallback(async()=>{await a(),t==null||t(),r("/")},[r,a,t]),se=Object.values(E).reduce((o,i)=>o+i.adopted,0),te=Object.values(E).filter(o=>o.project).length;return s.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[s.jsxs("header",{className:"pt-safe flex items-center gap-2 border-b border-edge px-3 pb-2.5 sm:px-6 lg:py-4",children:[s.jsx("button",{type:"button",onClick:()=>n==null?void 0:n.openNav(),"aria-label":"Open menu",className:"btn-subtle -ml-1 shrink-0 px-2 py-1.5 lg:hidden",children:s.jsx(oe,{width:20,height:20})}),s.jsx(ie,{width:18,height:18,className:"shrink-0 text-fg-subtle"}),s.jsx("h1",{className:"text-md font-semibold tracking-tight",children:"Discover"})]}),s.jsx("div",{className:"flex-1 overflow-y-auto overscroll-contain",children:s.jsxs("div",{className:"mx-auto max-w-3xl px-6 py-6",children:[s.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:e?"Nothing here yet — but you have probably already been using Claude Code in a terminal. These directories have history Paddock can bring in as projects.":"Directories on this machine with existing Claude Code history. Importing one links it as a project and copies its conversations in; your own history is never moved or deleted."}),S&&s.jsx(Ie,{imported:se,projects:te,onGetStarted:ee}),g!==null&&s.jsx(W,{tone:"danger",icon:s.jsx(Q,{width:16,height:16}),children:g}),v&&s.jsx(Ee,{}),!v&&g===null&&x!==null&&s.jsxs(s.Fragment,{children:[x.scanned===0?s.jsx($e,{claudeHome:x.claudeHome}):y.length===0?s.jsx(O,{variant:"panel",icon:s.jsx(U,{width:22,height:22}),title:"Nothing left to import",body:"Every directory with Claude Code history on this machine is already a project, or was filtered out."}):s.jsx("ul",{className:"space-y-2",children:y.map(o=>s.jsx(Se,{candidate:o,row:j[o.path],status:X[o.path],outcome:E[o.path],locked:k||S,onToggleRow:i=>w(p=>fe(p,o.path,i)),onToggleSession:i=>w(p=>ge(p,o.path,i)),onToggleExpanded:()=>Z(o)},o.path))}),!S&&s.jsx(Ce,{result:x,includeNonGit:d,includeOutsideHome:m,disabled:k,onIncludeNonGit:h,onIncludeOutsideHome:c}),y.length>0&&!S&&s.jsxs("div",{className:"mt-5 flex items-center justify-between gap-3 border-t border-edge pt-4",children:[s.jsxs("span",{className:"text-sm text-fg-muted",children:[G," conversation",G===1?"":"s"," from ",b.length," director",b.length===1?"y":"ies"]}),s.jsxs(R,{variant:"primary",onClick:()=>void L(),disabled:b.length===0,loading:k,loadingLabel:"Importing…",children:["Import ",b.length," project",b.length===1?"":"s"]})]})]})]})})]})}function Se({candidate:e,row:t,status:r,outcome:a,locked:n,onToggleRow:d,onToggleSession:h,onToggleExpanded:m}){const c=t??{checked:!1,expanded:!1,loading:!1,error:null},x=pe(c),$=C(c,e),g=a?ye(a):null;return s.jsx("li",{children:s.jsxs(he,{flush:!0,className:F("overflow-hidden",g==="success"&&"border-success-edge bg-success-soft",g==="warn"&&"border-warn-edge bg-warn-soft",g==="danger"&&"border-danger-edge bg-danger-soft",r==="running"&&"border-accent-edge"),"data-testid":`discover-row-${e.suggestedSlug}`,"data-tone":g??void 0,children:[s.jsxs("div",{className:"flex items-start gap-3 px-3 py-2.5",children:[s.jsx(M,{className:"mt-1",checked:x==="on",indeterminate:x==="mixed",disabled:n,"aria-label":`Import ${e.path}`,onChange:u=>d(u.target.checked)}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsx("code",{className:"block break-all text-sm text-fg",children:e.path}),s.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-fg-muted",children:[s.jsxs("span",{className:"tabular",children:[e.sessionCount," conversation",e.sessionCount===1?"":"s"]}),e.filteredCount>0&&s.jsxs("span",{className:"tabular",title:"Empty, slash-command-only or sweeper transcripts, withheld as noise",children:["· ",e.filteredCount," filtered out"]}),e.lastSessionAt!==void 0&&s.jsxs("span",{className:"tabular",children:["· last ",q(e.lastSessionAt)]}),e.gitRemote!==void 0&&s.jsx(T,{tone:"lineage",size:"sm",children:e.gitRemote}),!e.hasGit&&s.jsx(T,{tone:"neutral",size:"sm",children:"no git"}),!e.insideHome&&s.jsx(T,{tone:"neutral",size:"sm",children:"outside home"})]}),e.recordedPath!==void 0&&s.jsx(W,{tone:"warn",className:"mt-2",icon:s.jsx(Q,{width:14,height:14}),children:s.jsxs("span",{className:"text-xs",children:["These transcripts record"," ",s.jsx("code",{className:"break-all",children:e.recordedPath})," — a different spelling of this path. The import matches on the exact path, so it may bring nothing in."]})}),a&&s.jsx("p",{className:F("mt-2 text-xs",g==="success"&&"text-success",g==="warn"&&"text-warn",g==="danger"&&"text-danger"),children:ke(a,e)}),r==="running"&&!a&&s.jsx("p",{className:"mt-2 text-xs text-fg-muted",children:"Importing…"})]}),s.jsxs("span",{className:"flex shrink-0 items-center gap-1",children:[s.jsx("span",{className:"tabular text-xs text-fg-subtle",children:$}),s.jsx(R,{size:"icon-sm",variant:"subtle","aria-label":c.expanded?"Hide conversations":"Show conversations","aria-expanded":c.expanded,onClick:m,children:c.expanded?s.jsx(de,{width:14,height:14}):s.jsx(le,{width:14,height:14})})]})]}),c.expanded&&s.jsxs("div",{className:"border-t border-edge px-3 py-2",children:[c.loading&&s.jsx("p",{className:"py-2 text-xs text-fg-muted",children:"Reading transcripts…"}),c.error!==null&&s.jsx("p",{className:"py-2 text-xs text-danger",children:c.error}),c.sessions&&c.sessions.sessions.length===0&&s.jsx("p",{className:"py-2 text-xs text-fg-muted",children:"Nothing importable here any more — it may have been imported since the scan."}),c.sessions&&c.sessions.sessions.length>0&&s.jsx("ul",{className:"space-y-1",children:c.sessions.sessions.map(u=>{var v;return s.jsx("li",{children:s.jsxs("label",{className:"flex cursor-pointer items-start gap-2 rounded-lg px-2 py-1.5 transition-colors hover:bg-surface-hover",children:[s.jsx(M,{checked:((v=c.selected)==null?void 0:v.has(u.sessionId))??!1,disabled:n,"aria-label":_(u),onChange:()=>h(u.sessionId)}),s.jsxs("span",{className:"min-w-0 flex-1",children:[s.jsx("span",{className:"block truncate text-xs text-fg",children:_(u)}),s.jsxs("span",{className:"tabular mt-0.5 block text-3xs text-fg-muted",children:[q(u.mtime)," · ",Te(u.sizeBytes)]})]})]})},u.sessionId)})}),c.sessions&&c.sessions.filtered.length>0&&s.jsxs("p",{className:"mt-2 px-2 text-3xs text-fg-subtle",children:[c.sessions.filtered.length," more withheld as noise (",[...new Set(c.sessions.filtered.map(u=>u.reason))].join(", "),")."]})]})]})})}function Ce({result:e,includeNonGit:t,includeOutsideHome:r,disabled:a,onIncludeNonGit:n,onIncludeOutsideHome:d}){const h=e.excluded["no-git"]??0,m=e.excluded["outside-home"]??0,c=h>0||t,x=m>0||r;return e.scanned===0?null:s.jsxs("div",{className:"mt-5 space-y-2 border-t border-edge pt-4",children:[s.jsx("p",{className:"text-xs text-fg-muted",children:Pe(e)}),c&&s.jsxs("div",{className:"flex items-center gap-2 text-xs text-fg-muted",children:[s.jsx(K,{checked:t,disabled:a,onChange:n,label:"Also offer directories without a git repository"}),s.jsxs("span",{children:["Also offer directories without a git repository",h>0&&` (${h} hidden)`]})]}),x&&s.jsxs("div",{className:"flex items-center gap-2 text-xs text-fg-muted",children:[s.jsx(K,{checked:r,disabled:a,onChange:d,label:"Also offer directories outside your home directory"}),s.jsxs("span",{children:["Also offer directories outside ",s.jsx("code",{children:e.homeDir}),m>0&&` (${m} hidden)`]})]})]})}function $e({claudeHome:e}){return s.jsx(O,{variant:"panel",icon:s.jsx(ce,{width:22,height:22}),title:"No Claude Code history on this machine",body:s.jsxs(s.Fragment,{children:["Nothing has been recorded under ",s.jsx("code",{className:"break-all",children:e}),". That is normal for a container, whose Claude home is its own rather than yours — bind-mount your history there and re-open this page, or import it headlessly with"," ",s.jsx("code",{children:"npm run import-chats"}),"."]})})}function Ie({imported:e,projects:t,onGetStarted:r}){return s.jsx("div",{className:"mb-6",children:s.jsx(O,{variant:"panel",icon:s.jsx(U,{width:22,height:22}),title:t===0?"Nothing was imported":`${t} project${t===1?"":"s"}, ${e} conversation${e===1?"":"s"}`,body:t===0?"Every row failed. Each one says why below.":"They are in the sidebar now. Anything that did not land says why below.",action:s.jsx(R,{variant:"primary",onClick:()=>void r(),children:"Get started"})})})}function Ee(){return s.jsx("div",{className:"space-y-2","aria-label":"Scanning",role:"status",children:[0,1,2].map(e=>s.jsx("div",{className:"h-16 animate-pulse rounded-2xl bg-surface-active"},e))})}function Pe(e){const t=[],r=[["temp-root",n=>`${n} in temp directories`],["no-git",n=>`${n} without a git repository`],["outside-home",n=>`${n} outside your home directory`],["already-managed",n=>`${n} already a project`],["no-sessions",n=>`${n} with nothing importable`],["no-recorded-cwd",n=>`${n} with no recorded directory`],["missing",n=>`${n} no longer on disk`],["home-root",n=>`${n} your home directory itself`],["system-path",n=>`${n} system directories`],["paddock-internal",n=>`${n} inside Paddock's own data`]];for(const[n,d]of r){const h=e.excluded[n];h!==void 0&&h>0&&t.push(d(h))}const a=`${e.scanned} transcript folder${e.scanned===1?"":"s"} scanned`;return t.length===0?`${a}.`:`${a}; skipped ${t.join(", ")}.`}function _(e){var a,n;const t=(a=e.autoName)==null?void 0:a.trim();if(t!==void 0&&t!=="")return t;const r=(n=e.preview)==null?void 0:n.trim();return r!==void 0&&r!==""?r:e.sessionId}function q(e){const t=new Date(e);return Number.isNaN(t.getTime())?"unknown date":t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function Te(e){return e<1024?`${e} B`:e<1024*1024?`${Math.round(e/1024)} kB`:`${(e/(1024*1024)).toFixed(1)} MB`}export{ze as D};
1
+ import{a as ne,u as re,H as ae,r as l,b as P,j as s,M as oe,E as ie,D as Q,J as U,K as ce,l as F,O as de,h as le}from"./index-BeuEs7dL.js";import{E as O,B as R,C as he}from"./Surfaces-1dBayrsj.js";import{a as W,d as M,C as T,T as K}from"./Chip-C8a-t439.js";function ue(e){const t={};for(const r of e)t[r.path]={checked:!0,expanded:!1,loading:!1,error:null};return t}function pe(e){if(!e.sessions||!e.selected)return e.checked?"on":"off";const t=e.sessions.sessions.length,r=e.selected.size;return t===0||r===0?"off":r===t?"on":"mixed"}function C(e,t){return e.sessions&&e.selected?e.selected.size:e.checked?t.sessionCount:0}function me(e,t){return t.reduce((r,a)=>r+C(e[a.path]??z(),a),0)}function xe(e,t){return t.filter(r=>C(e[r.path]??z(),r)>0)}function fe(e,t,r){const a=e[t];if(!a)return e;const n={...a,checked:r};return a.sessions&&(n.selected=r?new Set(a.sessions.sessions.map(d=>d.sessionId)):new Set),{...e,[t]:n}}function ge(e,t,r){const a=e[t];if(!a||!a.sessions)return e;const n=new Set(a.selected??[]);return n.delete(r)||n.add(r),{...e,[t]:{...a,selected:n,checked:n.size>0}}}function je(e,t,r){const a=e[t];if(!a)return e;const n=a.checked?new Set(r.sessions.map(d=>d.sessionId)):new Set;return{...e,[t]:{...a,sessions:r,selected:n,loading:!1,error:null}}}function D(e,t,r){const a=e[t];return a?{...e,[t]:{...a,...r}}:e}function be(e,t){const r=e??z();return C(r,t)===0?null:r.sessions&&r.selected?{sessionIds:[...r.selected]}:{}}function z(){return{checked:!1,expanded:!1,loading:!1,error:null}}function ye(e){return e.error!==void 0?e.stage==="create"?"danger":"warn":e.adopted>0?"success":"warn"}async function we(e,t,r){let a;try{a=await e.createProject({name:t.name,slug:t.suggestedSlug,path:t.path,managed:!1})}catch(n){return{stage:"create",adopted:0,skipped:[],error:V(n)}}try{const n=await e.adoptChats(a.slug,{sourceCwd:a.workingDir,...r.sessionIds?{sessionIds:r.sessionIds}:{}});return{project:a,adopted:n.adopted.length,skipped:n.skipped}}catch(n){return{stage:"import",project:a,adopted:0,skipped:[],error:V(n)}}}async function Ne(e,t,r){const a=[];for(const n of t){r(n.candidate.path,"running");const d=await we(e,n.candidate,n.plan);a.push(d),r(n.candidate.path,"done",d)}return a}const ve={sidechain:"sub-agent transcript","already-adopted":"already imported","destination-exists":"a chat with that id already exists here","attributed-to-run":"belongs to a Paddock run",unreadable:"transcript unreadable","placement-failed":"copy failed","record-failed":"could not be recorded"};function J(e){if(e.length===0)return"";const t=[...new Set(e.map(r=>ve[r.reason]??r.reason))];return`${e.length} skipped (${t.join(", ")})`}function ke(e,t){var h;if(e.stage==="create")return`Couldn't create the project: ${e.error}`;const r=((h=e.project)==null?void 0:h.slug)??t.suggestedSlug;if(e.stage==="import")return`Project “${r}” was created, but importing its chats failed: ${e.error}. It is there and empty — you can import them from the project itself.`;if(e.adopted===0){const m=J(e.skipped);return t.recordedPath!==void 0?`Project “${r}” was created but no chats came with it. Its transcripts record ${t.recordedPath}, a different spelling of ${t.path}, and an import matches on the exact path.`:m?`Project “${r}” was created but no chats came with it — ${m}.`:`Project “${r}” was created but no chats came with it.`}const a=e.adopted,n=J(e.skipped),d=`Imported ${a} chat${a===1?"":"s"} into “${r}”`;return n?`${d} — ${n}.`:`${d}.`}function V(e){return e instanceof Error?e.message:String(e)}function ze({firstRun:e=!1,onLeave:t}){const r=ne(),{refresh:a}=re(),n=ae(),[d,h]=l.useState(!1),[m,c]=l.useState(!1),[x,$]=l.useState(null),[g,u]=l.useState(null),[v,I]=l.useState(!0),[j,w]=l.useState({}),[k,A]=l.useState(!1),[X,H]=l.useState({}),[E,B]=l.useState({}),[S,Y]=l.useState(!1);l.useEffect(()=>{let o=!0;return I(!0),u(null),P.discover({includeNonGit:d,includeOutsideHome:m}).then(i=>{o&&($(i),w(ue(i.candidates)),I(!1))}).catch(i=>{o&&(u(i instanceof Error?i.message:"Discovery failed"),I(!1))}),()=>{o=!1}},[d,m]);const y=(x==null?void 0:x.candidates)??[],G=l.useMemo(()=>me(j,y),[j,y]),b=l.useMemo(()=>xe(j,y),[j,y]),Z=l.useCallback(o=>{w(p=>{const f=p[o.path];if(!f)return p;const N=D(p,o.path,{expanded:!f.expanded});return f.expanded||f.sessions||f.loading?N:D(N,o.path,{loading:!0,error:null})});const i=j[o.path];!i||i.expanded||i.sessions||i.loading||P.discoverSessions(o.path).then(p=>w(f=>je(f,o.path,p))).catch(p=>w(f=>D(f,o.path,{loading:!1,error:p instanceof Error?p.message:"Could not read this directory's sessions"})))},[j]),L=l.useCallback(async()=>{if(k)return;A(!0),H(Object.fromEntries(b.map(i=>[i.path,"pending"]))),B({});const o=b.map(i=>({candidate:i,plan:be(j[i.path],i)??{}}));await Ne(P,o,(i,p,f)=>{H(N=>({...N,[i]:p})),f&&B(N=>({...N,[i]:f}))}),A(!1),Y(!0),await a()},[b,j,k,a]),ee=l.useCallback(async()=>{await a(),t==null||t(),r("/")},[r,a,t]),se=Object.values(E).reduce((o,i)=>o+i.adopted,0),te=Object.values(E).filter(o=>o.project).length;return s.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[s.jsxs("header",{className:"pt-safe flex items-center gap-2 border-b border-edge px-3 pb-2.5 sm:px-6 lg:py-4",children:[s.jsx("button",{type:"button",onClick:()=>n==null?void 0:n.openNav(),"aria-label":"Open menu",className:"btn-subtle -ml-1 shrink-0 px-2 py-1.5 lg:hidden",children:s.jsx(oe,{width:20,height:20})}),s.jsx(ie,{width:18,height:18,className:"shrink-0 text-fg-subtle"}),s.jsx("h1",{className:"text-md font-semibold tracking-tight",children:"Discover"})]}),s.jsx("div",{className:"flex-1 overflow-y-auto overscroll-contain",children:s.jsxs("div",{className:"mx-auto max-w-3xl px-6 py-6",children:[s.jsx("p",{className:"mb-5 text-sm text-fg-muted",children:e?"Nothing here yet — but you have probably already been using Claude Code in a terminal. These directories have history Paddock can bring in as projects.":"Directories on this machine with existing Claude Code history. Importing one links it as a project and copies its conversations in; your own history is never moved or deleted."}),S&&s.jsx(Ie,{imported:se,projects:te,onGetStarted:ee}),g!==null&&s.jsx(W,{tone:"danger",icon:s.jsx(Q,{width:16,height:16}),children:g}),v&&s.jsx(Ee,{}),!v&&g===null&&x!==null&&s.jsxs(s.Fragment,{children:[x.scanned===0?s.jsx($e,{claudeHome:x.claudeHome}):y.length===0?s.jsx(O,{variant:"panel",icon:s.jsx(U,{width:22,height:22}),title:"Nothing left to import",body:"Every directory with Claude Code history on this machine is already a project, or was filtered out."}):s.jsx("ul",{className:"space-y-2",children:y.map(o=>s.jsx(Se,{candidate:o,row:j[o.path],status:X[o.path],outcome:E[o.path],locked:k||S,onToggleRow:i=>w(p=>fe(p,o.path,i)),onToggleSession:i=>w(p=>ge(p,o.path,i)),onToggleExpanded:()=>Z(o)},o.path))}),!S&&s.jsx(Ce,{result:x,includeNonGit:d,includeOutsideHome:m,disabled:k,onIncludeNonGit:h,onIncludeOutsideHome:c}),y.length>0&&!S&&s.jsxs("div",{className:"mt-5 flex items-center justify-between gap-3 border-t border-edge pt-4",children:[s.jsxs("span",{className:"text-sm text-fg-muted",children:[G," conversation",G===1?"":"s"," from ",b.length," director",b.length===1?"y":"ies"]}),s.jsxs(R,{variant:"primary",onClick:()=>void L(),disabled:b.length===0,loading:k,loadingLabel:"Importing…",children:["Import ",b.length," project",b.length===1?"":"s"]})]})]})]})})]})}function Se({candidate:e,row:t,status:r,outcome:a,locked:n,onToggleRow:d,onToggleSession:h,onToggleExpanded:m}){const c=t??{checked:!1,expanded:!1,loading:!1,error:null},x=pe(c),$=C(c,e),g=a?ye(a):null;return s.jsx("li",{children:s.jsxs(he,{flush:!0,className:F("overflow-hidden",g==="success"&&"border-success-edge bg-success-soft",g==="warn"&&"border-warn-edge bg-warn-soft",g==="danger"&&"border-danger-edge bg-danger-soft",r==="running"&&"border-accent-edge"),"data-testid":`discover-row-${e.suggestedSlug}`,"data-tone":g??void 0,children:[s.jsxs("div",{className:"flex items-start gap-3 px-3 py-2.5",children:[s.jsx(M,{className:"mt-1",checked:x==="on",indeterminate:x==="mixed",disabled:n,"aria-label":`Import ${e.path}`,onChange:u=>d(u.target.checked)}),s.jsxs("div",{className:"min-w-0 flex-1",children:[s.jsx("code",{className:"block break-all text-sm text-fg",children:e.path}),s.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-fg-muted",children:[s.jsxs("span",{className:"tabular",children:[e.sessionCount," conversation",e.sessionCount===1?"":"s"]}),e.filteredCount>0&&s.jsxs("span",{className:"tabular",title:"Empty, slash-command-only or sweeper transcripts, withheld as noise",children:["· ",e.filteredCount," filtered out"]}),e.lastSessionAt!==void 0&&s.jsxs("span",{className:"tabular",children:["· last ",q(e.lastSessionAt)]}),e.gitRemote!==void 0&&s.jsx(T,{tone:"lineage",size:"sm",children:e.gitRemote}),!e.hasGit&&s.jsx(T,{tone:"neutral",size:"sm",children:"no git"}),!e.insideHome&&s.jsx(T,{tone:"neutral",size:"sm",children:"outside home"})]}),e.recordedPath!==void 0&&s.jsx(W,{tone:"warn",className:"mt-2",icon:s.jsx(Q,{width:14,height:14}),children:s.jsxs("span",{className:"text-xs",children:["These transcripts record"," ",s.jsx("code",{className:"break-all",children:e.recordedPath})," — a different spelling of this path. The import matches on the exact path, so it may bring nothing in."]})}),a&&s.jsx("p",{className:F("mt-2 text-xs",g==="success"&&"text-success",g==="warn"&&"text-warn",g==="danger"&&"text-danger"),children:ke(a,e)}),r==="running"&&!a&&s.jsx("p",{className:"mt-2 text-xs text-fg-muted",children:"Importing…"})]}),s.jsxs("span",{className:"flex shrink-0 items-center gap-1",children:[s.jsx("span",{className:"tabular text-xs text-fg-subtle",children:$}),s.jsx(R,{size:"icon-sm",variant:"subtle","aria-label":c.expanded?"Hide conversations":"Show conversations","aria-expanded":c.expanded,onClick:m,children:c.expanded?s.jsx(de,{width:14,height:14}):s.jsx(le,{width:14,height:14})})]})]}),c.expanded&&s.jsxs("div",{className:"border-t border-edge px-3 py-2",children:[c.loading&&s.jsx("p",{className:"py-2 text-xs text-fg-muted",children:"Reading transcripts…"}),c.error!==null&&s.jsx("p",{className:"py-2 text-xs text-danger",children:c.error}),c.sessions&&c.sessions.sessions.length===0&&s.jsx("p",{className:"py-2 text-xs text-fg-muted",children:"Nothing importable here any more — it may have been imported since the scan."}),c.sessions&&c.sessions.sessions.length>0&&s.jsx("ul",{className:"space-y-1",children:c.sessions.sessions.map(u=>{var v;return s.jsx("li",{children:s.jsxs("label",{className:"flex cursor-pointer items-start gap-2 rounded-lg px-2 py-1.5 transition-colors hover:bg-surface-hover",children:[s.jsx(M,{checked:((v=c.selected)==null?void 0:v.has(u.sessionId))??!1,disabled:n,"aria-label":_(u),onChange:()=>h(u.sessionId)}),s.jsxs("span",{className:"min-w-0 flex-1",children:[s.jsx("span",{className:"block truncate text-xs text-fg",children:_(u)}),s.jsxs("span",{className:"tabular mt-0.5 block text-3xs text-fg-muted",children:[q(u.mtime)," · ",Te(u.sizeBytes)]})]})]})},u.sessionId)})}),c.sessions&&c.sessions.filtered.length>0&&s.jsxs("p",{className:"mt-2 px-2 text-3xs text-fg-subtle",children:[c.sessions.filtered.length," more withheld as noise (",[...new Set(c.sessions.filtered.map(u=>u.reason))].join(", "),")."]})]})]})})}function Ce({result:e,includeNonGit:t,includeOutsideHome:r,disabled:a,onIncludeNonGit:n,onIncludeOutsideHome:d}){const h=e.excluded["no-git"]??0,m=e.excluded["outside-home"]??0,c=h>0||t,x=m>0||r;return e.scanned===0?null:s.jsxs("div",{className:"mt-5 space-y-2 border-t border-edge pt-4",children:[s.jsx("p",{className:"text-xs text-fg-muted",children:Pe(e)}),c&&s.jsxs("div",{className:"flex items-center gap-2 text-xs text-fg-muted",children:[s.jsx(K,{checked:t,disabled:a,onChange:n,label:"Also offer directories without a git repository"}),s.jsxs("span",{children:["Also offer directories without a git repository",h>0&&` (${h} hidden)`]})]}),x&&s.jsxs("div",{className:"flex items-center gap-2 text-xs text-fg-muted",children:[s.jsx(K,{checked:r,disabled:a,onChange:d,label:"Also offer directories outside your home directory"}),s.jsxs("span",{children:["Also offer directories outside ",s.jsx("code",{children:e.homeDir}),m>0&&` (${m} hidden)`]})]})]})}function $e({claudeHome:e}){return s.jsx(O,{variant:"panel",icon:s.jsx(ce,{width:22,height:22}),title:"No Claude Code history on this machine",body:s.jsxs(s.Fragment,{children:["Nothing has been recorded under ",s.jsx("code",{className:"break-all",children:e}),". That is normal for a container, whose Claude home is its own rather than yours — bind-mount your history there and re-open this page, or import it headlessly with"," ",s.jsx("code",{children:"npm run import-chats"}),"."]})})}function Ie({imported:e,projects:t,onGetStarted:r}){return s.jsx("div",{className:"mb-6",children:s.jsx(O,{variant:"panel",icon:s.jsx(U,{width:22,height:22}),title:t===0?"Nothing was imported":`${t} project${t===1?"":"s"}, ${e} conversation${e===1?"":"s"}`,body:t===0?"Every row failed. Each one says why below.":"They are in the sidebar now. Anything that did not land says why below.",action:s.jsx(R,{variant:"primary",onClick:()=>void r(),children:"Get started"})})})}function Ee(){return s.jsx("div",{className:"space-y-2","aria-label":"Scanning",role:"status",children:[0,1,2].map(e=>s.jsx("div",{className:"h-16 animate-pulse rounded-2xl bg-surface-active"},e))})}function Pe(e){const t=[],r=[["temp-root",n=>`${n} in temp directories`],["no-git",n=>`${n} without a git repository`],["outside-home",n=>`${n} outside your home directory`],["already-managed",n=>`${n} already a project`],["no-sessions",n=>`${n} with nothing importable`],["no-recorded-cwd",n=>`${n} with no recorded directory`],["missing",n=>`${n} no longer on disk`],["home-root",n=>`${n} your home directory itself`],["system-path",n=>`${n} system directories`],["paddock-internal",n=>`${n} inside Paddock's own data`]];for(const[n,d]of r){const h=e.excluded[n];h!==void 0&&h>0&&t.push(d(h))}const a=`${e.scanned} transcript folder${e.scanned===1?"":"s"} scanned`;return t.length===0?`${a}.`:`${a}; skipped ${t.join(", ")}.`}function _(e){var a,n;const t=(a=e.autoName)==null?void 0:a.trim();if(t!==void 0&&t!=="")return t;const r=(n=e.preview)==null?void 0:n.trim();return r!==void 0&&r!==""?r:e.sessionId}function q(e){const t=new Date(e);return Number.isNaN(t.getTime())?"unknown date":t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function Te(e){return e<1024?`${e} B`:e<1024*1024?`${Math.round(e/1024)} kB`:`${(e/(1024*1024)).toFixed(1)} MB`}export{ze as D};
2
2
 
@@ -1,2 +1,2 @@
1
- import{r as c,n as W,s as Z,A as ee,p as pe,j as e,q as ae,l as g,t as ie,v as be,w as je,x as le,y as ve,z as ye,b as L,D as oe,E as we,X as Ne,F as ke,G as Ce,H as Se,M as Ae,I as Ee}from"./index-Djl4krRr.js";import{B as R,S as te}from"./Surfaces-GzOkJJHQ.js";import{C as ce,S as O,I as B,a as Re,T as Me,b as $e,c as Pe}from"./Chip-B8UU8Zpr.js";const Ie=Array.from({length:72},(t,n)=>n*5),S=[...ie].sort((t,n)=>t.hue-n.hue),_=(t,n)=>Math.min(Math.abs(t-n),360-Math.abs(t-n));function ne(t){const n=S.reduce((r,a)=>_(a.hue,t)<_(r.hue,t)?a:r);if(_(n.hue,t)<=8)return n.name;const s=S.find(r=>r.hue>t)??S[0];return`between ${S[(S.indexOf(s)-1+S.length)%S.length].name} and ${s.name}`}function Fe({theme:t,dark:n,hue:s,className:o}){const r=c.useRef(null);return c.useLayoutEffect(()=>{const a=r.current;a&&(s===null?je(a):le(s,a))},[t,n,s]),e.jsx("div",{ref:r,"data-theme":t,className:g("overflow-hidden rounded-lg border border-edge",n&&"dark",o),children:e.jsxs("div",{className:"flex h-full items-center gap-2 bg-surface p-2",children:[e.jsxs("div",{className:"flex-1 rounded-md border border-edge-subtle bg-surface-raised p-1.5",children:[e.jsx("div",{className:"h-1 w-4/5 rounded-full bg-fg"}),e.jsx("div",{className:"mt-1 h-1 w-3/5 rounded-full bg-fg-subtle"})]}),e.jsx("div",{className:"grid h-6 w-6 shrink-0 place-items-center rounded-md bg-accent-solid",children:e.jsx("div",{className:"h-1 w-3 rounded-full bg-accent-fg"})})]})})}function Te({hexes:t,hue:n,active:s,onCommit:o}){const r=c.useRef(null),a=c.useRef(null),m=c.useRef(null),x=c.useRef(0),h=c.useRef(null),p=c.useRef(!1),j=c.useRef(null),u=c.useMemo(()=>{if(t.length===0)return;const d=t.map((b,y)=>`${b} ${(y/t.length*100).toFixed(2)}%`);return d.push(`${t[0]} 100%`),`linear-gradient(to right, ${d.join(", ")})`},[t]),f=c.useCallback(d=>{a.current&&(a.current.style.left=`${d/360*100}%`),m.current&&(m.current.textContent=ne(d))},[]);c.useEffect(()=>{p.current||f(n)},[n,f]);const N=d=>{var M;const b=(M=r.current)==null?void 0:M.getBoundingClientRect();if(!b||b.width===0)return 0;const y=Math.min(1,Math.max(0,(d-b.left)/b.width));return Math.round(y*360)%360},w=c.useCallback(d=>{h.current=d,!x.current&&(x.current=requestAnimationFrame(()=>{x.current=0;const b=h.current;h.current=null,b!==null&&(f(b),le(b,document.documentElement,{context:j.current??void 0,live:!0}))}))},[f]);c.useEffect(()=>()=>cancelAnimationFrame(x.current),[]);const F=d=>{p.current=!1,j.current=null,cancelAnimationFrame(x.current),x.current=0,h.current=null,o(d)};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mt-2 flex items-baseline justify-between gap-2",children:[e.jsx("span",{className:"text-3xs text-fg-subtle",children:"Drag along the strip"}),e.jsx("span",{ref:m,className:"text-3xs font-medium text-fg-muted","aria-hidden":!0})]}),e.jsx("div",{ref:r,role:"slider",tabIndex:0,"aria-label":"Accent colour","aria-valuemin":0,"aria-valuemax":359,"aria-valuenow":n,"aria-valuetext":s?ne(n):"the theme’s own colour",onPointerDown:d=>{d.currentTarget.setPointerCapture(d.pointerId),p.current=!0,j.current=ve(),w(N(d.clientX))},onPointerMove:d=>{p.current&&w(N(d.clientX))},onPointerUp:d=>{p.current&&F(N(d.clientX))},onPointerCancel:()=>{p.current&&F(n)},onKeyDown:d=>{const b=d.key==="PageUp"||d.key==="PageDown"?15:d.shiftKey?10:2;let y=null;d.key==="ArrowLeft"||d.key==="ArrowDown"||d.key==="PageDown"?y=(n-b+360)%360:d.key==="ArrowRight"||d.key==="ArrowUp"||d.key==="PageUp"?y=(n+b)%360:d.key==="Home"?y=0:d.key==="End"&&(y=359),y!==null&&(d.preventDefault(),o(y))},style:{backgroundImage:u,touchAction:"none"},className:g("relative mt-1 h-8 cursor-pointer rounded-lg border border-edge shadow-xs select-none","focus-visible:focus-ring"),children:e.jsx("div",{ref:a,"aria-hidden":!0,style:{left:`${n/360*100}%`},className:g("pointer-events-none absolute top-1/2 h-[calc(100%+6px)] w-1.5 -translate-x-1/2 -translate-y-1/2 rounded-full","border border-fg bg-surface-raised shadow-sm",!s&&"opacity-0")})})]})}function Le({className:t}){const[n,s]=c.useState(W),[o,r]=c.useState(null),a=typeof document<"u"&&document.documentElement.classList.contains("dark"),m=c.useRef(n),x=c.useCallback(u=>{const f={...m.current,...u};m.current=f,s(f),r(Z(f))},[]);c.useEffect(()=>{const u=f=>r(f.detail);return window.addEventListener(ee,u),r(Z(W())),()=>window.removeEventListener(ee,u)},[]);const h=c.useMemo(()=>pe(Ie),[n.theme,a,o==null?void 0:o.mode]),p=(o==null?void 0:o.hue)??0,j=n.hue!==null;return e.jsxs("div",{className:g("space-y-5",t),children:[e.jsxs("fieldset",{children:[e.jsx("legend",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Theme"}),e.jsx("div",{className:g("mt-2 grid gap-2","grid-cols-2 sm:grid-cols-4"),children:ae.map(u=>{const f=n.theme===u.id;return e.jsxs("button",{type:"button","aria-pressed":f,title:`${u.label} — ${u.blurb}`,onClick:()=>x({theme:u.id}),className:g("motion-fast rounded-xl border text-left transition-[border-color,box-shadow]","focus-visible:focus-ring","p-1.5",f?"border-accent-edge bg-accent-soft shadow-xs":"border-edge bg-surface-raised hover:border-edge-strong"),children:[e.jsx(Fe,{theme:u.id,dark:a,hue:n.hue,className:"h-10"}),e.jsxs("div",{className:"mt-1.5 min-w-0 px-0.5 pb-0.5",children:[e.jsx("span",{className:"block truncate text-xs font-semibold text-fg",children:u.label}),e.jsx("span",{className:"mt-0.5 line-clamp-2 text-3xs leading-snug text-fg-muted",children:u.blurb})]})]},u.id)})})]}),e.jsxs("div",{className:g("grid gap-5 lg:grid-cols-[minmax(0,1fr)_15rem] lg:items-start"),children:[e.jsxs("fieldset",{children:[e.jsx("legend",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Accent colour"}),e.jsx("p",{className:"mt-1 text-3xs leading-snug text-fg-subtle",children:"Pick any colour. The theme adjusts it so buttons and labels stay readable in both light and dark."}),e.jsx(Te,{hexes:h,hue:p,active:j,onCommit:u=>x({hue:u})}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-1",children:[e.jsx("button",{type:"button",onClick:()=>x({hue:null}),"aria-pressed":!j,className:g("motion-fast rounded-md border px-2 py-1 text-3xs transition-colors","focus-visible:focus-ring",j?"border-edge text-fg-muted hover:border-edge-strong hover:text-fg":"border-accent-edge bg-accent-soft text-accent"),children:"Theme’s own"}),ie.map(u=>{const f=j&&Math.abs(p-u.hue)<2.5;return e.jsxs("button",{type:"button","aria-pressed":f,onClick:()=>x({hue:u.hue}),className:g("motion-fast inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-3xs transition-colors","focus-visible:focus-ring",f?"border-edge-strong bg-surface-active text-fg":"border-edge text-fg-muted hover:border-edge-strong hover:text-fg"),children:[e.jsx("span",{"aria-hidden":!0,className:"h-2.5 w-2.5 rounded-full",style:{backgroundColor:h[Math.round(u.hue/5)%h.length]}}),u.name]},u.name)})]})]}),e.jsxs("fieldset",{children:[e.jsx("legend",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Tint the background"}),e.jsx("p",{className:"mt-1 text-3xs leading-snug text-fg-subtle",children:"Colours the whole page a little, not just the buttons. Useful for telling two Paddock instances apart at a glance."}),e.jsx("div",{className:"mt-2 inline-flex rounded-lg border border-edge p-0.5",children:be.map(u=>e.jsx("button",{type:"button","aria-pressed":n.tint===u.level,onClick:()=>x({tint:u.level}),className:g("motion-fast rounded-md px-2.5 py-1 text-3xs transition-colors","focus-visible:focus-ring",n.tint===u.level?"bg-surface-active font-medium text-fg":"text-fg-muted hover:text-fg"),children:u.label},u.level))})]})]}),e.jsx(Oe,{})]})}function Oe(){return e.jsxs("div",{children:[e.jsx("p",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Preview"}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2 rounded-xl border border-edge bg-surface p-3",children:[e.jsx(R,{variant:"primary",size:"sm",children:"Send"}),e.jsx(R,{variant:"ghost",size:"sm",children:"Cancel"}),e.jsx(R,{variant:"link",size:"sm",children:"A link"}),e.jsx("span",{className:"inline-flex items-center gap-1 rounded-md border border-accent-edge bg-accent-soft px-1.5 py-0.5 text-2xs font-medium text-accent",children:"accent chip"}),e.jsx(ce,{tone:"accent",shape:"pill",dot:!0,children:"running"}),e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-2xs text-fg-subtle",children:[e.jsx("span",{className:"h-4 w-4 rounded-md border border-edge bg-accent-solid-hover","aria-hidden":!0}),"hovered"]}),e.jsxs("span",{className:"ml-auto inline-flex items-center gap-1.5",children:[e.jsx(O,{tone:"success"}),e.jsx(O,{tone:"warn"}),e.jsx(O,{tone:"danger"}),e.jsx(O,{tone:"info"}),e.jsx("span",{className:"text-2xs text-fg-subtle",children:"status hues (theme’s, not yours)"})]})]})]})}const z="mx-auto w-full max-w-4xl",De="sm:w-64";function Ve(){const[t,n]=c.useState(null),[s,o]=c.useState(!0),[r,a]=c.useState(null),[m,x]=c.useState({}),[h,p]=c.useState(!1),[j,u]=c.useState(null),[f,N]=c.useState(!1),[w,F]=c.useState(""),[d,b]=c.useState(!1),[y,M]=c.useState(null),K=c.useRef(null),de=ye("(min-width: 1024px)");c.useEffect(()=>{let i=!0;return o(!0),L.getInstanceConfig().then(l=>{i&&(n(l),a(null))}).catch(l=>i&&a(l instanceof Error?l.message:String(l))).finally(()=>i&&o(!1)),()=>{i=!1}},[]);const ue=(i,l)=>{N(!1),u(null),x(v=>({...v,[i]:l}))},me=i=>se(i,m),H=c.useMemo(()=>t?t.groups.flatMap(i=>i.fields):[],[t]),k=c.useMemo(()=>H.filter(i=>i.editable&&!i.envOverridden).filter(i=>Object.prototype.hasOwnProperty.call(m,i.key)).filter(i=>!re(m[i.key],q(i))).map(i=>i.key),[H,m]),X=c.useMemo(()=>new Set(k),[k]),C=c.useMemo(()=>{if(!t)return[];const i=w.trim().toLowerCase(),l=[];for(const v of t.groups){const P=i!==""&&v.label.toLowerCase().includes(i),I=v.fields.filter(A=>{const T=se(A,m);return d&&re(T,A.default)?!1:i===""||P?!0:Ye(A).includes(i)});I.length>0&&l.push({...v,fields:I})}return l},[t,w,d,m]),J=C.reduce((i,l)=>i+l.fields.length,0),xe=w.trim()!==""||d,U=!d&&(w.trim()===""||We.includes(w.trim().toLowerCase())),$=c.useMemo(()=>U?[V,...C]:C,[U,C]),he=C.some(i=>i.fields.some(l=>l.envOverridden)),Y=Qe(C,X);c.useEffect(()=>{const i=K.current;if(!i||$.length===0)return;const l=$.map(P=>P.id),v=()=>{const P=i.getBoundingClientRect().top;let I=l[0];for(const A of l){const T=document.getElementById(D(A));if(T)if(T.getBoundingClientRect().top-P<=80)I=A;else break}M(I)};return v(),i.addEventListener("scroll",v,{passive:!0}),()=>i.removeEventListener("scroll",v)},[$]);const Q=i=>{var v;const l=document.getElementById(D(i));(v=l==null?void 0:l.scrollIntoView)==null||v.call(l,{behavior:"smooth",block:"start"}),M(i)},fe=async()=>{if(k.length===0||!t)return;const i={};for(const l of k)i[l]=m[l];p(!0),u(null);try{await L.updateInstanceConfig(i,t.configVersion);const l=await L.getInstanceConfig();n(l),x({}),N(!0)}catch(l){if(l instanceof Ce&&l.status===409)try{n(await L.getInstanceConfig())}catch{}u(l instanceof Error?l.message:String(l))}finally{p(!1)}},ge=()=>{x({}),u(null),N(!1)};return e.jsxs("div",{className:"flex min-h-0 flex-1",children:[t&&e.jsx(Be,{groups:$,active:y,onJump:Q,dirtyCount:Y}),e.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1 flex-col",children:[t&&e.jsx("div",{className:"border-b border-edge px-4 py-2.5 sm:px-6",children:e.jsxs("div",{className:z,children:[e.jsx(Ue,{query:w,onQuery:F,modifiedOnly:d,onModifiedOnly:b,visibleCount:J,totalCount:H.length,filtering:xe,autoFocus:de}),e.jsx(He,{groups:$,active:y,onJump:Q,dirtyCount:Y})]})}),e.jsx("div",{ref:K,className:"min-h-0 flex-1 overflow-y-auto px-4 py-5 sm:px-6",children:e.jsxs("div",{className:z,children:[U&&e.jsx("div",{className:"mb-8 border-b border-edge pb-7",children:e.jsx(te,{id:D(V.id),title:V.label,description:V.description,variant:"rule",first:!0,children:e.jsx(Le,{})})}),e.jsx(_e,{saved:f,configPath:t==null?void 0:t.configPath,restartRequired:(t==null?void 0:t.restartRequired)??!1,fileError:t==null?void 0:t.configFileError}),s&&e.jsx("p",{className:"text-sm text-fg-muted",children:"Loading…"}),r&&e.jsxs("p",{className:"text-sm text-danger",role:"alert",children:["Failed to load settings: ",r]}),t&&he&&e.jsx(ze,{}),t&&J===0&&e.jsxs("p",{className:"py-8 text-center text-sm text-fg-muted",children:["No settings match"," ",w.trim()?e.jsxs(e.Fragment,{children:["“",e.jsx("span",{className:"font-medium",children:w.trim()}),"”"]}):"this filter","."]}),C.map(i=>e.jsx(te,{id:D(i.id),title:i.label,description:i.description,variant:"card",flush:!0,children:e.jsx("div",{className:"divide-y divide-edge-subtle",children:i.fields.map(l=>e.jsx(Ge,{field:l,value:me(l),dirty:X.has(l.key),onChange:v=>ue(l.key,v)},l.key))})},i.id))]})}),t&&e.jsx("footer",{className:"border-t border-edge px-4 py-3 sm:px-6",children:e.jsxs("div",{className:`${z} flex items-center gap-3`,children:[j&&e.jsxs("span",{className:"flex min-w-0 items-center gap-1.5 text-sm text-danger",role:"alert",children:[e.jsx(oe,{width:14,height:14,className:"shrink-0"}),e.jsx("span",{className:"truncate",children:j})]}),e.jsx("span",{className:"ml-auto shrink-0 text-xs tabular text-fg-subtle",children:k.length>0?`${k.length} unsaved change${k.length===1?"":"s"}`:"No changes"}),e.jsx(R,{variant:"subtle",onClick:ge,disabled:k.length===0||h,children:"Reset"}),e.jsx(R,{variant:"primary",onClick:fe,disabled:k.length===0,loading:h,loadingLabel:"Saving…",children:"Save changes"})]})})]})]})}function Be({groups:t,active:n,onJump:s,dirtyCount:o}){return e.jsx("nav",{"aria-label":"Config sections",className:"hidden w-52 shrink-0 overflow-y-auto border-r border-edge px-2 py-4 lg:block",children:e.jsx("ul",{className:"space-y-0.5",children:t.map(r=>{const a=r.id===n,m=o[r.id]??0;return e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>s(r.id),"aria-current":a?"true":void 0,className:g("motion-fast flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-sm transition-colors",a?"bg-surface-selected font-medium text-fg":"text-fg-muted hover:bg-surface-hover hover:text-fg"),children:[e.jsx("span",{className:"min-w-0 flex-1 truncate",children:r.label}),m>0&&e.jsx("span",{className:"h-1.5 w-1.5 shrink-0 rounded-full bg-accent-solid","aria-label":`${m} unsaved`}),r.fields.length>0&&e.jsx("span",{className:"shrink-0 text-2xs tabular text-fg-subtle",children:r.fields.length})]})},r.id)})})})}function He({groups:t,active:n,onJump:s,dirtyCount:o}){return t.length===0?null:e.jsx("nav",{"aria-label":"Config sections",className:"-mx-1 mt-2 flex gap-1 overflow-x-auto px-1 pb-0.5 lg:hidden",children:t.map(r=>{const a=r.id===n,m=o[r.id]??0;return e.jsxs("button",{type:"button",onClick:()=>s(r.id),"aria-current":a?"true":void 0,className:g("motion-fast flex shrink-0 items-center gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors",a?"bg-surface-selected font-medium text-fg":"text-fg-muted hover:bg-surface-hover hover:text-fg"),children:[r.label,m>0&&e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-accent-solid","aria-label":`${m} unsaved`})]},r.id)})})}function Ue({query:t,onQuery:n,modifiedOnly:s,onModifiedOnly:o,visibleCount:r,totalCount:a,filtering:m,autoFocus:x}){return e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"relative min-w-0 flex-1 sm:max-w-sm",children:[e.jsx(we,{width:14,height:14,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-fg-subtle"}),e.jsx(B,{type:"search","aria-label":"Search settings",placeholder:"Search settings, keys, env vars…",className:"h-8 py-0 pl-8 pr-7 [&::-webkit-search-cancel-button]:appearance-none",value:t,autoFocus:x,onChange:h=>n(h.target.value),onKeyDown:h=>{h.key==="Escape"&&t!==""&&(h.preventDefault(),n(""))}}),t!==""&&e.jsx("button",{type:"button","aria-label":"Clear search",onClick:()=>n(""),className:"absolute right-2 top-1/2 -translate-y-1/2 text-fg-subtle hover:text-fg",children:e.jsx(Ne,{width:13,height:13})})]}),e.jsx("button",{type:"button","aria-pressed":s,onClick:()=>o(!s),className:g("motion-fast shrink-0 rounded-md border px-2.5 py-1 text-xs transition-colors",s?"border-accent-edge bg-accent-soft text-accent":"border-edge text-fg-muted hover:text-fg"),children:"Modified only"}),e.jsx("span",{className:"shrink-0 text-xs tabular text-fg-subtle",children:m?`${r} of ${a}`:`${a} settings`})]})}function _e({saved:t,configPath:n,restartRequired:s,fileError:o}){const r=o?"danger":t?"success":"warn";return e.jsx(Re,{tone:r,className:"mb-5 leading-snug",icon:r==="success"?e.jsx(ke,{width:15,height:15}):e.jsx(oe,{width:15,height:15}),children:e.jsx("span",{role:"status",children:o?e.jsxs(e.Fragment,{children:[e.jsxs("strong",{children:["Could not read ",G(n),"."]})," ",o," — the values below are the running instance's; what a restart would load is unknown until the file parses."]}):t?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"Saved to disk."})," These changes take effect only after the server restarts."]}):s?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"Restart pending."})," ",e.jsx("code",{className:"font-mono text-xs",children:G(n)})," holds changes the running instance has not picked up — the fields below marked"," ",e.jsx(E,{tone:"warn",children:"restart"})," differ from what is in force right now."]}):e.jsxs(e.Fragment,{children:["Changes here are written to"," ",e.jsx("code",{className:"font-mono text-xs",children:G(n)})," and take effect only after the server restarts — the running instance keeps its current config until then."]})})})}function ze(){return e.jsxs("p",{className:"mb-5 text-xs leading-snug text-fg-muted",children:["Settings marked ",e.jsx(E,{tone:"neutral",children:"env"})," are overridden by an environment variable, which wins over this file — edit that variable (and restart) to change them."]})}function Ge({field:t,value:n,dirty:s,onChange:o}){const r=!t.editable||t.envOverridden,a=`cfg-${t.key}`,m=t.help?`${a}-help`:void 0,x=t.type==="boolean",h=c.useMemo(()=>Je(t,q(t)),[t]),p=x&&!r,j=!t.help&&!t.envOverridden&&!t.pendingRestart,u=j?"items-center":"items-start",f=j?"sm:items-center":"sm:items-start",N=r?e.jsx(Xe,{field:t,value:n}):x?e.jsx(Me,{id:a,checked:!!n,onChange:o,label:t.label}):e.jsx(Ke,{field:t,value:n,onChange:o,inputId:a,describedBy:m});return e.jsxs("div",{className:"relative px-4 py-3",children:[s&&e.jsx("span",{"aria-hidden":!0,className:"absolute inset-y-2 left-0 w-0.5 rounded-full bg-accent-solid"}),e.jsxs("div",{className:g(h?"":p?`flex gap-4 ${u}`:`sm:flex sm:gap-6 ${f}`),children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("label",{htmlFor:r?void 0:a,className:"text-sm font-medium text-fg",children:t.label}),t.sensitive&&e.jsx(E,{tone:"warn",children:"sensitive"}),t.envOverridden&&e.jsx(E,{tone:"neutral",title:`Overridden by environment variable ${t.envVar} — edit that env var (and restart) to change it.`,children:"env"}),!t.editable&&!t.envOverridden&&e.jsx(E,{tone:"neutral",children:"read-only"}),t.pendingRestart&&e.jsx(E,{tone:"warn",title:"The config file and the running instance disagree on this field — restart to apply.",children:"restart"})]}),t.help&&e.jsx("p",{id:m,className:"mt-0.5 text-xs leading-snug text-fg-muted",children:t.help}),t.envOverridden&&e.jsx("p",{className:"mt-1 truncate font-mono text-2xs text-fg-subtle",children:t.envVar}),t.pendingRestart&&e.jsxs("p",{className:"mt-1 text-2xs leading-snug text-warn",children:["In force now: ",e.jsx("span",{className:"font-mono",children:qe(t.value)})]})]}),e.jsx("div",{className:g(h?"mt-2":p?"flex shrink-0 justify-end":`mt-2 sm:mt-0 sm:shrink-0 ${De}`),children:N})]})]})}function qe(t){if(t==null||t==="")return"(not set)";const s=(Array.isArray(t)?t.join(", "):String(t)).replace(/\s+/g," ").trim();return s.length>60?`${s.slice(0,60)}…`:s}function E({children:t,tone:n,title:s}){return e.jsx(ce,{tone:n,size:"sm",title:s,className:"uppercase tracking-wide",children:t})}function Ke({field:t,value:n,onChange:s,inputId:o,describedBy:r}){if(t.type==="enum")return e.jsx($e,{id:o,"aria-describedby":r,value:String(n??""),onChange:a=>s(a.target.value),children:(t.enumValues??[]).map(a=>e.jsx("option",{value:a,children:a},a))});if(t.type==="number")return e.jsx(B,{id:o,type:"number","aria-describedby":r,className:"tabular",value:n==null?"":String(n),placeholder:t.default===null?"default":String(t.default),onChange:a=>s(a.target.value===""?null:Number(a.target.value))});if(t.type==="text"){const a=n==null||n===t.default,m=n==null?String(t.default??""):String(n),x=typeof t.default=="string"&&!a;return e.jsxs("div",{children:[e.jsx(Pe,{id:o,"aria-describedby":r,className:"min-h-[7rem] font-mono text-xs leading-relaxed",rows:6,spellCheck:!1,value:m,onChange:h=>s(h.target.value)}),e.jsxs("div",{className:"mt-1 flex items-center justify-between gap-3 text-xs text-fg-muted",children:[e.jsx("span",{children:a?"Using the built-in default.":n===""?"Empty — nothing will be appended.":`${m.length.toLocaleString()} characters.`}),x&&e.jsx(R,{variant:"link",size:"sm",className:"shrink-0",onClick:()=>s(null),children:"Restore default"})]})]})}if(t.type==="string-list"){const a=Array.isArray(n)?n.join(", "):String(n??"");return e.jsx(B,{id:o,type:"text","aria-describedby":r,value:a,onChange:m=>s(m.target.value.split(",").map(x=>x.trim()).filter(Boolean))})}return e.jsx(B,{id:o,type:"text","aria-describedby":r,value:n==null?"":String(n),placeholder:t.default===null?"":String(t.default),onChange:a=>s(a.target.value)})}function Xe({field:t,value:n}){const s="rounded-lg bg-surface-sunken px-3 py-2 font-mono text-xs text-fg-muted";return t.type==="boolean"?e.jsx("div",{className:s,children:n?"true":"false"}):n==null||n===""?e.jsx("div",{className:s,children:e.jsx("span",{className:"italic text-fg-subtle",children:t.type==="text"&&n===""?"(empty — nothing appended)":"(not set)"})}):t.type==="text"?e.jsx("div",{className:g(s,"max-h-40 overflow-y-auto whitespace-pre-wrap leading-relaxed"),children:String(n)}):e.jsx("div",{className:g(s,"break-all"),children:Array.isArray(n)?n.join(", "):String(n)})}function Je(t,n){return t.type==="text"||t.type==="string-list"?!0:(Array.isArray(n)?n.join(", "):n==null?"":String(n)).length>38}function Ye(t){return[t.label,t.key,t.help,t.envVar,...t.enumValues??[]].filter(Boolean).join(" ").toLowerCase()}function Qe(t,n){const s={};for(const o of t)s[o.id]=o.fields.filter(r=>n.has(r.key)).length;return s}const D=t=>`cfg-section-${t}`,V={id:"appearance",label:"Appearance",description:"Theme and accent colour for this browser. Applies immediately — no save, no restart.",fields:[]},We=["appearance theme themes colour color accent tint dark light font",...ae.map(t=>t.id)].join(" ");function q(t){return t.pendingValue===void 0?t.value:t.pendingValue}function se(t,n){return Object.prototype.hasOwnProperty.call(n,t.key)?n[t.key]:q(t)}function re(t,n){return Array.isArray(t)&&Array.isArray(n)?t.length===n.length&&t.every((s,o)=>s===n[o]):t===n}function G(t){if(!t)return"paddock.config.yaml";const n=t.split("/");return n[n.length-1]||t}function nt(){const t=Se(),n=(t==null?void 0:t.openNav)??(()=>{});return e.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[e.jsxs("header",{className:"pt-safe flex items-center gap-2 border-b border-edge px-3 pb-2.5 sm:px-6 lg:py-4",children:[e.jsx("button",{type:"button",onClick:n,"aria-label":"Open menu",className:"btn-subtle -ml-1 shrink-0 px-2 py-1.5 lg:hidden",children:e.jsx(Ae,{width:20,height:20})}),e.jsx(Ee,{width:18,height:18,className:"shrink-0 text-fg-subtle"}),e.jsx("h1",{className:"text-md font-semibold tracking-tight",children:"Config"})]}),e.jsx(Ve,{})]})}export{nt as InstanceConfigPage};
1
+ import{r as c,n as W,s as Z,A as ee,p as pe,j as e,q as ae,l as g,t as ie,v as be,w as je,x as le,y as ve,z as ye,b as L,D as oe,E as we,X as Ne,F as ke,G as Ce,H as Se,M as Ae,I as Ee}from"./index-BeuEs7dL.js";import{B as R,S as te}from"./Surfaces-1dBayrsj.js";import{C as ce,S as O,I as B,a as Re,T as Me,b as $e,c as Pe}from"./Chip-C8a-t439.js";const Ie=Array.from({length:72},(t,n)=>n*5),S=[...ie].sort((t,n)=>t.hue-n.hue),_=(t,n)=>Math.min(Math.abs(t-n),360-Math.abs(t-n));function ne(t){const n=S.reduce((r,a)=>_(a.hue,t)<_(r.hue,t)?a:r);if(_(n.hue,t)<=8)return n.name;const s=S.find(r=>r.hue>t)??S[0];return`between ${S[(S.indexOf(s)-1+S.length)%S.length].name} and ${s.name}`}function Fe({theme:t,dark:n,hue:s,className:o}){const r=c.useRef(null);return c.useLayoutEffect(()=>{const a=r.current;a&&(s===null?je(a):le(s,a))},[t,n,s]),e.jsx("div",{ref:r,"data-theme":t,className:g("overflow-hidden rounded-lg border border-edge",n&&"dark",o),children:e.jsxs("div",{className:"flex h-full items-center gap-2 bg-surface p-2",children:[e.jsxs("div",{className:"flex-1 rounded-md border border-edge-subtle bg-surface-raised p-1.5",children:[e.jsx("div",{className:"h-1 w-4/5 rounded-full bg-fg"}),e.jsx("div",{className:"mt-1 h-1 w-3/5 rounded-full bg-fg-subtle"})]}),e.jsx("div",{className:"grid h-6 w-6 shrink-0 place-items-center rounded-md bg-accent-solid",children:e.jsx("div",{className:"h-1 w-3 rounded-full bg-accent-fg"})})]})})}function Te({hexes:t,hue:n,active:s,onCommit:o}){const r=c.useRef(null),a=c.useRef(null),m=c.useRef(null),x=c.useRef(0),h=c.useRef(null),p=c.useRef(!1),j=c.useRef(null),u=c.useMemo(()=>{if(t.length===0)return;const d=t.map((b,y)=>`${b} ${(y/t.length*100).toFixed(2)}%`);return d.push(`${t[0]} 100%`),`linear-gradient(to right, ${d.join(", ")})`},[t]),f=c.useCallback(d=>{a.current&&(a.current.style.left=`${d/360*100}%`),m.current&&(m.current.textContent=ne(d))},[]);c.useEffect(()=>{p.current||f(n)},[n,f]);const N=d=>{var M;const b=(M=r.current)==null?void 0:M.getBoundingClientRect();if(!b||b.width===0)return 0;const y=Math.min(1,Math.max(0,(d-b.left)/b.width));return Math.round(y*360)%360},w=c.useCallback(d=>{h.current=d,!x.current&&(x.current=requestAnimationFrame(()=>{x.current=0;const b=h.current;h.current=null,b!==null&&(f(b),le(b,document.documentElement,{context:j.current??void 0,live:!0}))}))},[f]);c.useEffect(()=>()=>cancelAnimationFrame(x.current),[]);const F=d=>{p.current=!1,j.current=null,cancelAnimationFrame(x.current),x.current=0,h.current=null,o(d)};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mt-2 flex items-baseline justify-between gap-2",children:[e.jsx("span",{className:"text-3xs text-fg-subtle",children:"Drag along the strip"}),e.jsx("span",{ref:m,className:"text-3xs font-medium text-fg-muted","aria-hidden":!0})]}),e.jsx("div",{ref:r,role:"slider",tabIndex:0,"aria-label":"Accent colour","aria-valuemin":0,"aria-valuemax":359,"aria-valuenow":n,"aria-valuetext":s?ne(n):"the theme’s own colour",onPointerDown:d=>{d.currentTarget.setPointerCapture(d.pointerId),p.current=!0,j.current=ve(),w(N(d.clientX))},onPointerMove:d=>{p.current&&w(N(d.clientX))},onPointerUp:d=>{p.current&&F(N(d.clientX))},onPointerCancel:()=>{p.current&&F(n)},onKeyDown:d=>{const b=d.key==="PageUp"||d.key==="PageDown"?15:d.shiftKey?10:2;let y=null;d.key==="ArrowLeft"||d.key==="ArrowDown"||d.key==="PageDown"?y=(n-b+360)%360:d.key==="ArrowRight"||d.key==="ArrowUp"||d.key==="PageUp"?y=(n+b)%360:d.key==="Home"?y=0:d.key==="End"&&(y=359),y!==null&&(d.preventDefault(),o(y))},style:{backgroundImage:u,touchAction:"none"},className:g("relative mt-1 h-8 cursor-pointer rounded-lg border border-edge shadow-xs select-none","focus-visible:focus-ring"),children:e.jsx("div",{ref:a,"aria-hidden":!0,style:{left:`${n/360*100}%`},className:g("pointer-events-none absolute top-1/2 h-[calc(100%+6px)] w-1.5 -translate-x-1/2 -translate-y-1/2 rounded-full","border border-fg bg-surface-raised shadow-sm",!s&&"opacity-0")})})]})}function Le({className:t}){const[n,s]=c.useState(W),[o,r]=c.useState(null),a=typeof document<"u"&&document.documentElement.classList.contains("dark"),m=c.useRef(n),x=c.useCallback(u=>{const f={...m.current,...u};m.current=f,s(f),r(Z(f))},[]);c.useEffect(()=>{const u=f=>r(f.detail);return window.addEventListener(ee,u),r(Z(W())),()=>window.removeEventListener(ee,u)},[]);const h=c.useMemo(()=>pe(Ie),[n.theme,a,o==null?void 0:o.mode]),p=(o==null?void 0:o.hue)??0,j=n.hue!==null;return e.jsxs("div",{className:g("space-y-5",t),children:[e.jsxs("fieldset",{children:[e.jsx("legend",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Theme"}),e.jsx("div",{className:g("mt-2 grid gap-2","grid-cols-2 sm:grid-cols-4"),children:ae.map(u=>{const f=n.theme===u.id;return e.jsxs("button",{type:"button","aria-pressed":f,title:`${u.label} — ${u.blurb}`,onClick:()=>x({theme:u.id}),className:g("motion-fast rounded-xl border text-left transition-[border-color,box-shadow]","focus-visible:focus-ring","p-1.5",f?"border-accent-edge bg-accent-soft shadow-xs":"border-edge bg-surface-raised hover:border-edge-strong"),children:[e.jsx(Fe,{theme:u.id,dark:a,hue:n.hue,className:"h-10"}),e.jsxs("div",{className:"mt-1.5 min-w-0 px-0.5 pb-0.5",children:[e.jsx("span",{className:"block truncate text-xs font-semibold text-fg",children:u.label}),e.jsx("span",{className:"mt-0.5 line-clamp-2 text-3xs leading-snug text-fg-muted",children:u.blurb})]})]},u.id)})})]}),e.jsxs("div",{className:g("grid gap-5 lg:grid-cols-[minmax(0,1fr)_15rem] lg:items-start"),children:[e.jsxs("fieldset",{children:[e.jsx("legend",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Accent colour"}),e.jsx("p",{className:"mt-1 text-3xs leading-snug text-fg-subtle",children:"Pick any colour. The theme adjusts it so buttons and labels stay readable in both light and dark."}),e.jsx(Te,{hexes:h,hue:p,active:j,onCommit:u=>x({hue:u})}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-1",children:[e.jsx("button",{type:"button",onClick:()=>x({hue:null}),"aria-pressed":!j,className:g("motion-fast rounded-md border px-2 py-1 text-3xs transition-colors","focus-visible:focus-ring",j?"border-edge text-fg-muted hover:border-edge-strong hover:text-fg":"border-accent-edge bg-accent-soft text-accent"),children:"Theme’s own"}),ie.map(u=>{const f=j&&Math.abs(p-u.hue)<2.5;return e.jsxs("button",{type:"button","aria-pressed":f,onClick:()=>x({hue:u.hue}),className:g("motion-fast inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-3xs transition-colors","focus-visible:focus-ring",f?"border-edge-strong bg-surface-active text-fg":"border-edge text-fg-muted hover:border-edge-strong hover:text-fg"),children:[e.jsx("span",{"aria-hidden":!0,className:"h-2.5 w-2.5 rounded-full",style:{backgroundColor:h[Math.round(u.hue/5)%h.length]}}),u.name]},u.name)})]})]}),e.jsxs("fieldset",{children:[e.jsx("legend",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Tint the background"}),e.jsx("p",{className:"mt-1 text-3xs leading-snug text-fg-subtle",children:"Colours the whole page a little, not just the buttons. Useful for telling two Paddock instances apart at a glance."}),e.jsx("div",{className:"mt-2 inline-flex rounded-lg border border-edge p-0.5",children:be.map(u=>e.jsx("button",{type:"button","aria-pressed":n.tint===u.level,onClick:()=>x({tint:u.level}),className:g("motion-fast rounded-md px-2.5 py-1 text-3xs transition-colors","focus-visible:focus-ring",n.tint===u.level?"bg-surface-active font-medium text-fg":"text-fg-muted hover:text-fg"),children:u.label},u.level))})]})]}),e.jsx(Oe,{})]})}function Oe(){return e.jsxs("div",{children:[e.jsx("p",{className:"text-2xs font-semibold uppercase tracking-wide text-fg-muted",children:"Preview"}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2 rounded-xl border border-edge bg-surface p-3",children:[e.jsx(R,{variant:"primary",size:"sm",children:"Send"}),e.jsx(R,{variant:"ghost",size:"sm",children:"Cancel"}),e.jsx(R,{variant:"link",size:"sm",children:"A link"}),e.jsx("span",{className:"inline-flex items-center gap-1 rounded-md border border-accent-edge bg-accent-soft px-1.5 py-0.5 text-2xs font-medium text-accent",children:"accent chip"}),e.jsx(ce,{tone:"accent",shape:"pill",dot:!0,children:"running"}),e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-2xs text-fg-subtle",children:[e.jsx("span",{className:"h-4 w-4 rounded-md border border-edge bg-accent-solid-hover","aria-hidden":!0}),"hovered"]}),e.jsxs("span",{className:"ml-auto inline-flex items-center gap-1.5",children:[e.jsx(O,{tone:"success"}),e.jsx(O,{tone:"warn"}),e.jsx(O,{tone:"danger"}),e.jsx(O,{tone:"info"}),e.jsx("span",{className:"text-2xs text-fg-subtle",children:"status hues (theme’s, not yours)"})]})]})]})}const z="mx-auto w-full max-w-4xl",De="sm:w-64";function Ve(){const[t,n]=c.useState(null),[s,o]=c.useState(!0),[r,a]=c.useState(null),[m,x]=c.useState({}),[h,p]=c.useState(!1),[j,u]=c.useState(null),[f,N]=c.useState(!1),[w,F]=c.useState(""),[d,b]=c.useState(!1),[y,M]=c.useState(null),K=c.useRef(null),de=ye("(min-width: 1024px)");c.useEffect(()=>{let i=!0;return o(!0),L.getInstanceConfig().then(l=>{i&&(n(l),a(null))}).catch(l=>i&&a(l instanceof Error?l.message:String(l))).finally(()=>i&&o(!1)),()=>{i=!1}},[]);const ue=(i,l)=>{N(!1),u(null),x(v=>({...v,[i]:l}))},me=i=>se(i,m),H=c.useMemo(()=>t?t.groups.flatMap(i=>i.fields):[],[t]),k=c.useMemo(()=>H.filter(i=>i.editable&&!i.envOverridden).filter(i=>Object.prototype.hasOwnProperty.call(m,i.key)).filter(i=>!re(m[i.key],q(i))).map(i=>i.key),[H,m]),X=c.useMemo(()=>new Set(k),[k]),C=c.useMemo(()=>{if(!t)return[];const i=w.trim().toLowerCase(),l=[];for(const v of t.groups){const P=i!==""&&v.label.toLowerCase().includes(i),I=v.fields.filter(A=>{const T=se(A,m);return d&&re(T,A.default)?!1:i===""||P?!0:Ye(A).includes(i)});I.length>0&&l.push({...v,fields:I})}return l},[t,w,d,m]),J=C.reduce((i,l)=>i+l.fields.length,0),xe=w.trim()!==""||d,U=!d&&(w.trim()===""||We.includes(w.trim().toLowerCase())),$=c.useMemo(()=>U?[V,...C]:C,[U,C]),he=C.some(i=>i.fields.some(l=>l.envOverridden)),Y=Qe(C,X);c.useEffect(()=>{const i=K.current;if(!i||$.length===0)return;const l=$.map(P=>P.id),v=()=>{const P=i.getBoundingClientRect().top;let I=l[0];for(const A of l){const T=document.getElementById(D(A));if(T)if(T.getBoundingClientRect().top-P<=80)I=A;else break}M(I)};return v(),i.addEventListener("scroll",v,{passive:!0}),()=>i.removeEventListener("scroll",v)},[$]);const Q=i=>{var v;const l=document.getElementById(D(i));(v=l==null?void 0:l.scrollIntoView)==null||v.call(l,{behavior:"smooth",block:"start"}),M(i)},fe=async()=>{if(k.length===0||!t)return;const i={};for(const l of k)i[l]=m[l];p(!0),u(null);try{await L.updateInstanceConfig(i,t.configVersion);const l=await L.getInstanceConfig();n(l),x({}),N(!0)}catch(l){if(l instanceof Ce&&l.status===409)try{n(await L.getInstanceConfig())}catch{}u(l instanceof Error?l.message:String(l))}finally{p(!1)}},ge=()=>{x({}),u(null),N(!1)};return e.jsxs("div",{className:"flex min-h-0 flex-1",children:[t&&e.jsx(Be,{groups:$,active:y,onJump:Q,dirtyCount:Y}),e.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1 flex-col",children:[t&&e.jsx("div",{className:"border-b border-edge px-4 py-2.5 sm:px-6",children:e.jsxs("div",{className:z,children:[e.jsx(Ue,{query:w,onQuery:F,modifiedOnly:d,onModifiedOnly:b,visibleCount:J,totalCount:H.length,filtering:xe,autoFocus:de}),e.jsx(He,{groups:$,active:y,onJump:Q,dirtyCount:Y})]})}),e.jsx("div",{ref:K,className:"min-h-0 flex-1 overflow-y-auto px-4 py-5 sm:px-6",children:e.jsxs("div",{className:z,children:[U&&e.jsx("div",{className:"mb-8 border-b border-edge pb-7",children:e.jsx(te,{id:D(V.id),title:V.label,description:V.description,variant:"rule",first:!0,children:e.jsx(Le,{})})}),e.jsx(_e,{saved:f,configPath:t==null?void 0:t.configPath,restartRequired:(t==null?void 0:t.restartRequired)??!1,fileError:t==null?void 0:t.configFileError}),s&&e.jsx("p",{className:"text-sm text-fg-muted",children:"Loading…"}),r&&e.jsxs("p",{className:"text-sm text-danger",role:"alert",children:["Failed to load settings: ",r]}),t&&he&&e.jsx(ze,{}),t&&J===0&&e.jsxs("p",{className:"py-8 text-center text-sm text-fg-muted",children:["No settings match"," ",w.trim()?e.jsxs(e.Fragment,{children:["“",e.jsx("span",{className:"font-medium",children:w.trim()}),"”"]}):"this filter","."]}),C.map(i=>e.jsx(te,{id:D(i.id),title:i.label,description:i.description,variant:"card",flush:!0,children:e.jsx("div",{className:"divide-y divide-edge-subtle",children:i.fields.map(l=>e.jsx(Ge,{field:l,value:me(l),dirty:X.has(l.key),onChange:v=>ue(l.key,v)},l.key))})},i.id))]})}),t&&e.jsx("footer",{className:"border-t border-edge px-4 py-3 sm:px-6",children:e.jsxs("div",{className:`${z} flex items-center gap-3`,children:[j&&e.jsxs("span",{className:"flex min-w-0 items-center gap-1.5 text-sm text-danger",role:"alert",children:[e.jsx(oe,{width:14,height:14,className:"shrink-0"}),e.jsx("span",{className:"truncate",children:j})]}),e.jsx("span",{className:"ml-auto shrink-0 text-xs tabular text-fg-subtle",children:k.length>0?`${k.length} unsaved change${k.length===1?"":"s"}`:"No changes"}),e.jsx(R,{variant:"subtle",onClick:ge,disabled:k.length===0||h,children:"Reset"}),e.jsx(R,{variant:"primary",onClick:fe,disabled:k.length===0,loading:h,loadingLabel:"Saving…",children:"Save changes"})]})})]})]})}function Be({groups:t,active:n,onJump:s,dirtyCount:o}){return e.jsx("nav",{"aria-label":"Config sections",className:"hidden w-52 shrink-0 overflow-y-auto border-r border-edge px-2 py-4 lg:block",children:e.jsx("ul",{className:"space-y-0.5",children:t.map(r=>{const a=r.id===n,m=o[r.id]??0;return e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>s(r.id),"aria-current":a?"true":void 0,className:g("motion-fast flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-sm transition-colors",a?"bg-surface-selected font-medium text-fg":"text-fg-muted hover:bg-surface-hover hover:text-fg"),children:[e.jsx("span",{className:"min-w-0 flex-1 truncate",children:r.label}),m>0&&e.jsx("span",{className:"h-1.5 w-1.5 shrink-0 rounded-full bg-accent-solid","aria-label":`${m} unsaved`}),r.fields.length>0&&e.jsx("span",{className:"shrink-0 text-2xs tabular text-fg-subtle",children:r.fields.length})]})},r.id)})})})}function He({groups:t,active:n,onJump:s,dirtyCount:o}){return t.length===0?null:e.jsx("nav",{"aria-label":"Config sections",className:"-mx-1 mt-2 flex gap-1 overflow-x-auto px-1 pb-0.5 lg:hidden",children:t.map(r=>{const a=r.id===n,m=o[r.id]??0;return e.jsxs("button",{type:"button",onClick:()=>s(r.id),"aria-current":a?"true":void 0,className:g("motion-fast flex shrink-0 items-center gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors",a?"bg-surface-selected font-medium text-fg":"text-fg-muted hover:bg-surface-hover hover:text-fg"),children:[r.label,m>0&&e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-accent-solid","aria-label":`${m} unsaved`})]},r.id)})})}function Ue({query:t,onQuery:n,modifiedOnly:s,onModifiedOnly:o,visibleCount:r,totalCount:a,filtering:m,autoFocus:x}){return e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"relative min-w-0 flex-1 sm:max-w-sm",children:[e.jsx(we,{width:14,height:14,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-fg-subtle"}),e.jsx(B,{type:"search","aria-label":"Search settings",placeholder:"Search settings, keys, env vars…",className:"h-8 py-0 pl-8 pr-7 [&::-webkit-search-cancel-button]:appearance-none",value:t,autoFocus:x,onChange:h=>n(h.target.value),onKeyDown:h=>{h.key==="Escape"&&t!==""&&(h.preventDefault(),n(""))}}),t!==""&&e.jsx("button",{type:"button","aria-label":"Clear search",onClick:()=>n(""),className:"absolute right-2 top-1/2 -translate-y-1/2 text-fg-subtle hover:text-fg",children:e.jsx(Ne,{width:13,height:13})})]}),e.jsx("button",{type:"button","aria-pressed":s,onClick:()=>o(!s),className:g("motion-fast shrink-0 rounded-md border px-2.5 py-1 text-xs transition-colors",s?"border-accent-edge bg-accent-soft text-accent":"border-edge text-fg-muted hover:text-fg"),children:"Modified only"}),e.jsx("span",{className:"shrink-0 text-xs tabular text-fg-subtle",children:m?`${r} of ${a}`:`${a} settings`})]})}function _e({saved:t,configPath:n,restartRequired:s,fileError:o}){const r=o?"danger":t?"success":"warn";return e.jsx(Re,{tone:r,className:"mb-5 leading-snug",icon:r==="success"?e.jsx(ke,{width:15,height:15}):e.jsx(oe,{width:15,height:15}),children:e.jsx("span",{role:"status",children:o?e.jsxs(e.Fragment,{children:[e.jsxs("strong",{children:["Could not read ",G(n),"."]})," ",o," — the values below are the running instance's; what a restart would load is unknown until the file parses."]}):t?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"Saved to disk."})," These changes take effect only after the server restarts."]}):s?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:"Restart pending."})," ",e.jsx("code",{className:"font-mono text-xs",children:G(n)})," holds changes the running instance has not picked up — the fields below marked"," ",e.jsx(E,{tone:"warn",children:"restart"})," differ from what is in force right now."]}):e.jsxs(e.Fragment,{children:["Changes here are written to"," ",e.jsx("code",{className:"font-mono text-xs",children:G(n)})," and take effect only after the server restarts — the running instance keeps its current config until then."]})})})}function ze(){return e.jsxs("p",{className:"mb-5 text-xs leading-snug text-fg-muted",children:["Settings marked ",e.jsx(E,{tone:"neutral",children:"env"})," are overridden by an environment variable, which wins over this file — edit that variable (and restart) to change them."]})}function Ge({field:t,value:n,dirty:s,onChange:o}){const r=!t.editable||t.envOverridden,a=`cfg-${t.key}`,m=t.help?`${a}-help`:void 0,x=t.type==="boolean",h=c.useMemo(()=>Je(t,q(t)),[t]),p=x&&!r,j=!t.help&&!t.envOverridden&&!t.pendingRestart,u=j?"items-center":"items-start",f=j?"sm:items-center":"sm:items-start",N=r?e.jsx(Xe,{field:t,value:n}):x?e.jsx(Me,{id:a,checked:!!n,onChange:o,label:t.label}):e.jsx(Ke,{field:t,value:n,onChange:o,inputId:a,describedBy:m});return e.jsxs("div",{className:"relative px-4 py-3",children:[s&&e.jsx("span",{"aria-hidden":!0,className:"absolute inset-y-2 left-0 w-0.5 rounded-full bg-accent-solid"}),e.jsxs("div",{className:g(h?"":p?`flex gap-4 ${u}`:`sm:flex sm:gap-6 ${f}`),children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[e.jsx("label",{htmlFor:r?void 0:a,className:"text-sm font-medium text-fg",children:t.label}),t.sensitive&&e.jsx(E,{tone:"warn",children:"sensitive"}),t.envOverridden&&e.jsx(E,{tone:"neutral",title:`Overridden by environment variable ${t.envVar} — edit that env var (and restart) to change it.`,children:"env"}),!t.editable&&!t.envOverridden&&e.jsx(E,{tone:"neutral",children:"read-only"}),t.pendingRestart&&e.jsx(E,{tone:"warn",title:"The config file and the running instance disagree on this field — restart to apply.",children:"restart"})]}),t.help&&e.jsx("p",{id:m,className:"mt-0.5 text-xs leading-snug text-fg-muted",children:t.help}),t.envOverridden&&e.jsx("p",{className:"mt-1 truncate font-mono text-2xs text-fg-subtle",children:t.envVar}),t.pendingRestart&&e.jsxs("p",{className:"mt-1 text-2xs leading-snug text-warn",children:["In force now: ",e.jsx("span",{className:"font-mono",children:qe(t.value)})]})]}),e.jsx("div",{className:g(h?"mt-2":p?"flex shrink-0 justify-end":`mt-2 sm:mt-0 sm:shrink-0 ${De}`),children:N})]})]})}function qe(t){if(t==null||t==="")return"(not set)";const s=(Array.isArray(t)?t.join(", "):String(t)).replace(/\s+/g," ").trim();return s.length>60?`${s.slice(0,60)}…`:s}function E({children:t,tone:n,title:s}){return e.jsx(ce,{tone:n,size:"sm",title:s,className:"uppercase tracking-wide",children:t})}function Ke({field:t,value:n,onChange:s,inputId:o,describedBy:r}){if(t.type==="enum")return e.jsx($e,{id:o,"aria-describedby":r,value:String(n??""),onChange:a=>s(a.target.value),children:(t.enumValues??[]).map(a=>e.jsx("option",{value:a,children:a},a))});if(t.type==="number")return e.jsx(B,{id:o,type:"number","aria-describedby":r,className:"tabular",value:n==null?"":String(n),placeholder:t.default===null?"default":String(t.default),onChange:a=>s(a.target.value===""?null:Number(a.target.value))});if(t.type==="text"){const a=n==null||n===t.default,m=n==null?String(t.default??""):String(n),x=typeof t.default=="string"&&!a;return e.jsxs("div",{children:[e.jsx(Pe,{id:o,"aria-describedby":r,className:"min-h-[7rem] font-mono text-xs leading-relaxed",rows:6,spellCheck:!1,value:m,onChange:h=>s(h.target.value)}),e.jsxs("div",{className:"mt-1 flex items-center justify-between gap-3 text-xs text-fg-muted",children:[e.jsx("span",{children:a?"Using the built-in default.":n===""?"Empty — nothing will be appended.":`${m.length.toLocaleString()} characters.`}),x&&e.jsx(R,{variant:"link",size:"sm",className:"shrink-0",onClick:()=>s(null),children:"Restore default"})]})]})}if(t.type==="string-list"){const a=Array.isArray(n)?n.join(", "):String(n??"");return e.jsx(B,{id:o,type:"text","aria-describedby":r,value:a,onChange:m=>s(m.target.value.split(",").map(x=>x.trim()).filter(Boolean))})}return e.jsx(B,{id:o,type:"text","aria-describedby":r,value:n==null?"":String(n),placeholder:t.default===null?"":String(t.default),onChange:a=>s(a.target.value)})}function Xe({field:t,value:n}){const s="rounded-lg bg-surface-sunken px-3 py-2 font-mono text-xs text-fg-muted";return t.type==="boolean"?e.jsx("div",{className:s,children:n?"true":"false"}):n==null||n===""?e.jsx("div",{className:s,children:e.jsx("span",{className:"italic text-fg-subtle",children:t.type==="text"&&n===""?"(empty — nothing appended)":"(not set)"})}):t.type==="text"?e.jsx("div",{className:g(s,"max-h-40 overflow-y-auto whitespace-pre-wrap leading-relaxed"),children:String(n)}):e.jsx("div",{className:g(s,"break-all"),children:Array.isArray(n)?n.join(", "):String(n)})}function Je(t,n){return t.type==="text"||t.type==="string-list"?!0:(Array.isArray(n)?n.join(", "):n==null?"":String(n)).length>38}function Ye(t){return[t.label,t.key,t.help,t.envVar,...t.enumValues??[]].filter(Boolean).join(" ").toLowerCase()}function Qe(t,n){const s={};for(const o of t)s[o.id]=o.fields.filter(r=>n.has(r.key)).length;return s}const D=t=>`cfg-section-${t}`,V={id:"appearance",label:"Appearance",description:"Theme and accent colour for this browser. Applies immediately — no save, no restart.",fields:[]},We=["appearance theme themes colour color accent tint dark light font",...ae.map(t=>t.id)].join(" ");function q(t){return t.pendingValue===void 0?t.value:t.pendingValue}function se(t,n){return Object.prototype.hasOwnProperty.call(n,t.key)?n[t.key]:q(t)}function re(t,n){return Array.isArray(t)&&Array.isArray(n)?t.length===n.length&&t.every((s,o)=>s===n[o]):t===n}function G(t){if(!t)return"paddock.config.yaml";const n=t.split("/");return n[n.length-1]||t}function nt(){const t=Se(),n=(t==null?void 0:t.openNav)??(()=>{});return e.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[e.jsxs("header",{className:"pt-safe flex items-center gap-2 border-b border-edge px-3 pb-2.5 sm:px-6 lg:py-4",children:[e.jsx("button",{type:"button",onClick:n,"aria-label":"Open menu",className:"btn-subtle -ml-1 shrink-0 px-2 py-1.5 lg:hidden",children:e.jsx(Ae,{width:20,height:20})}),e.jsx(Ee,{width:18,height:18,className:"shrink-0 text-fg-subtle"}),e.jsx("h1",{className:"text-md font-semibold tracking-tight",children:"Config"})]}),e.jsx(Ve,{})]})}export{nt as InstanceConfigPage};
2
2