@spencerboucher/switchyard 0.7.0 → 0.9.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 (149) hide show
  1. package/README.md +3 -3
  2. package/dist/bridge/lines.js +33 -0
  3. package/dist/bridge/switchyard-terminal.js +155 -23
  4. package/dist/switchyard.mjs +3879 -2658
  5. package/dist/terminal/holder.js +142 -51
  6. package/package.json +1 -1
  7. package/web-dist/apple-touch-icon.png +0 -0
  8. package/web-dist/assets/AutomationView-D7Syv1En.js +2 -0
  9. package/web-dist/assets/AutomationView-D7Syv1En.js.map +1 -0
  10. package/web-dist/assets/Checkbox-D6tRfEeI.js +2 -0
  11. package/web-dist/assets/Checkbox-D6tRfEeI.js.map +1 -0
  12. package/web-dist/assets/Copy-B6XSAIUd.js +2 -0
  13. package/web-dist/assets/Copy-B6XSAIUd.js.map +1 -0
  14. package/web-dist/assets/DangerZone-DfYlxDC1.js +2 -0
  15. package/web-dist/assets/DangerZone-DfYlxDC1.js.map +1 -0
  16. package/web-dist/assets/Field-D-Ty7fKT.js +2 -0
  17. package/web-dist/assets/Field-D-Ty7fKT.js.map +1 -0
  18. package/web-dist/assets/InteractionCard-DF1EcSpm.js +6 -0
  19. package/web-dist/assets/InteractionCard-DF1EcSpm.js.map +1 -0
  20. package/web-dist/assets/Menu-BfOszNC4.js +2 -0
  21. package/web-dist/assets/Menu-BfOszNC4.js.map +1 -0
  22. package/web-dist/assets/Overlay-DUQwh6_b.js +2 -0
  23. package/web-dist/assets/Overlay-DUQwh6_b.js.map +1 -0
  24. package/web-dist/assets/Priority-CHmzfoHg.js +2 -0
  25. package/web-dist/assets/Priority-CHmzfoHg.js.map +1 -0
  26. package/web-dist/assets/{SegmentedControl-D-2BCZzd.js → SegmentedControl-C_hEVQMB.js} +2 -2
  27. package/web-dist/assets/{SegmentedControl-D-2BCZzd.js.map → SegmentedControl-C_hEVQMB.js.map} +1 -1
  28. package/web-dist/assets/Select-Cfql4Nwu.js +2 -0
  29. package/web-dist/assets/Select-Cfql4Nwu.js.map +1 -0
  30. package/web-dist/assets/Switch-DBfzmqkm.js +2 -0
  31. package/web-dist/assets/Switch-DBfzmqkm.js.map +1 -0
  32. package/web-dist/assets/Tabs-BNuL3_Et.js +184 -0
  33. package/web-dist/assets/Tabs-BNuL3_Et.js.map +1 -0
  34. package/web-dist/assets/TextArea-CKybrQyn.js +2 -0
  35. package/web-dist/assets/TextArea-CKybrQyn.js.map +1 -0
  36. package/web-dist/assets/TextLink-OzzyP2-p.js +2 -0
  37. package/web-dist/assets/TextLink-OzzyP2-p.js.map +1 -0
  38. package/web-dist/assets/arrow-down-C-iLrN8I.js +2 -0
  39. package/web-dist/assets/arrow-down-C-iLrN8I.js.map +1 -0
  40. package/web-dist/assets/arrow-up-Dj-VTKx4.js +2 -0
  41. package/web-dist/assets/arrow-up-Dj-VTKx4.js.map +1 -0
  42. package/web-dist/assets/attention-V86Gye3I.js +2 -0
  43. package/web-dist/assets/attention-V86Gye3I.js.map +1 -0
  44. package/web-dist/assets/automations-Cw5Gacgm.js +2 -0
  45. package/web-dist/assets/automations-Cw5Gacgm.js.map +1 -0
  46. package/web-dist/assets/board-B8X7TYYR.js +10 -0
  47. package/web-dist/assets/board-B8X7TYYR.js.map +1 -0
  48. package/web-dist/assets/code-BKroYJmR.js +12 -0
  49. package/web-dist/assets/code-BKroYJmR.js.map +1 -0
  50. package/web-dist/assets/describe-D6KLGKWa.js +5 -0
  51. package/web-dist/assets/describe-D6KLGKWa.js.map +1 -0
  52. package/web-dist/assets/enroll-DwT7AcuS.js +2 -0
  53. package/web-dist/assets/enroll-DwT7AcuS.js.map +1 -0
  54. package/web-dist/assets/index-B3F7WcYf.css +2 -0
  55. package/web-dist/assets/index-hxvDvCS7.js +12 -0
  56. package/web-dist/assets/index-hxvDvCS7.js.map +1 -0
  57. package/web-dist/assets/logic-B46fwD-8.js +2 -0
  58. package/web-dist/assets/logic-B46fwD-8.js.map +1 -0
  59. package/web-dist/assets/more-DQR5uu1c.js +2 -0
  60. package/web-dist/assets/more-DQR5uu1c.js.map +1 -0
  61. package/web-dist/assets/queue-DUg1rS8t.js +2 -0
  62. package/web-dist/assets/queue-DUg1rS8t.js.map +1 -0
  63. package/web-dist/assets/repo-XzzzEI0d.js +2 -0
  64. package/web-dist/assets/repo-XzzzEI0d.js.map +1 -0
  65. package/web-dist/assets/server-BqZ-w6M8.js +2 -0
  66. package/web-dist/assets/server-BqZ-w6M8.js.map +1 -0
  67. package/web-dist/assets/settings-DyUu0tJM.js +8 -0
  68. package/web-dist/assets/settings-DyUu0tJM.js.map +1 -0
  69. package/web-dist/assets/states-ZhrxQa3K.js +56 -0
  70. package/web-dist/assets/states-ZhrxQa3K.js.map +1 -0
  71. package/web-dist/assets/terminal-BOV_MXPZ.js +2 -0
  72. package/web-dist/assets/terminal-BOV_MXPZ.js.map +1 -0
  73. package/web-dist/assets/terminal-login-S5CAd5xA.js +2 -0
  74. package/web-dist/assets/terminal-login-S5CAd5xA.js.map +1 -0
  75. package/web-dist/assets/useBackTo-BIrCq3W2.js +2 -0
  76. package/web-dist/assets/useBackTo-BIrCq3W2.js.map +1 -0
  77. package/web-dist/assets/useNow-Dj7oEiwn.js +2 -0
  78. package/web-dist/assets/useNow-Dj7oEiwn.js.map +1 -0
  79. package/web-dist/assets/useResource-CDGSq2At.js +2 -0
  80. package/web-dist/assets/useResource-CDGSq2At.js.map +1 -0
  81. package/web-dist/icon-192.png +0 -0
  82. package/web-dist/icon-512.png +0 -0
  83. package/web-dist/icon.svg +20 -8
  84. package/web-dist/index.html +3 -4
  85. package/web-dist/manifest.webmanifest +1 -1
  86. package/web-dist/maskable-512.png +0 -0
  87. package/web-dist/sw.js +1 -1
  88. package/web-dist/sw.js.map +1 -1
  89. package/web-dist/assets/AutomationView-BIW_pO0M.js +0 -2
  90. package/web-dist/assets/AutomationView-BIW_pO0M.js.map +0 -1
  91. package/web-dist/assets/Badge-BiDp7NKI.js +0 -2
  92. package/web-dist/assets/Badge-BiDp7NKI.js.map +0 -1
  93. package/web-dist/assets/InteractionCard-CWxyDv81.js +0 -6
  94. package/web-dist/assets/InteractionCard-CWxyDv81.js.map +0 -1
  95. package/web-dist/assets/Menu-BDt1bxwz.js +0 -2
  96. package/web-dist/assets/Menu-BDt1bxwz.js.map +0 -1
  97. package/web-dist/assets/Tabs-ByiPklAw.js +0 -184
  98. package/web-dist/assets/Tabs-ByiPklAw.js.map +0 -1
  99. package/web-dist/assets/TextArea-BYr88SnV.js +0 -2
  100. package/web-dist/assets/TextArea-BYr88SnV.js.map +0 -1
  101. package/web-dist/assets/arrow-left-C6YWM6y6.js +0 -2
  102. package/web-dist/assets/arrow-left-C6YWM6y6.js.map +0 -1
  103. package/web-dist/assets/attention-Bya8XHKI.js +0 -2
  104. package/web-dist/assets/attention-Bya8XHKI.js.map +0 -1
  105. package/web-dist/assets/automations-DiXKRcnE.js +0 -2
  106. package/web-dist/assets/automations-DiXKRcnE.js.map +0 -1
  107. package/web-dist/assets/board-BrLaJwLJ.js +0 -10
  108. package/web-dist/assets/board-BrLaJwLJ.js.map +0 -1
  109. package/web-dist/assets/code-DKLO8bzz.js +0 -11
  110. package/web-dist/assets/code-DKLO8bzz.js.map +0 -1
  111. package/web-dist/assets/copy-oWgGHmkS.js +0 -2
  112. package/web-dist/assets/copy-oWgGHmkS.js.map +0 -1
  113. package/web-dist/assets/describe-DnvH6_fl.js +0 -5
  114. package/web-dist/assets/describe-DnvH6_fl.js.map +0 -1
  115. package/web-dist/assets/dist-BE_V9dwJ.js +0 -56
  116. package/web-dist/assets/dist-BE_V9dwJ.js.map +0 -1
  117. package/web-dist/assets/enroll-DUDpbJoB.js +0 -2
  118. package/web-dist/assets/enroll-DUDpbJoB.js.map +0 -1
  119. package/web-dist/assets/index-DvRcMGEe.css +0 -2
  120. package/web-dist/assets/index-vIzH1m8u.js +0 -11
  121. package/web-dist/assets/index-vIzH1m8u.js.map +0 -1
  122. package/web-dist/assets/logic-xb-QF00E.js +0 -2
  123. package/web-dist/assets/logic-xb-QF00E.js.map +0 -1
  124. package/web-dist/assets/more-BP5x45cs.js +0 -2
  125. package/web-dist/assets/more-BP5x45cs.js.map +0 -1
  126. package/web-dist/assets/now--XjJC37b.js +0 -2
  127. package/web-dist/assets/now--XjJC37b.js.map +0 -1
  128. package/web-dist/assets/plus-BLP-wIYD.js +0 -2
  129. package/web-dist/assets/plus-BLP-wIYD.js.map +0 -1
  130. package/web-dist/assets/save-DEvZPWlS.js +0 -2
  131. package/web-dist/assets/save-DEvZPWlS.js.map +0 -1
  132. package/web-dist/assets/send-BKjswHxB.js +0 -2
  133. package/web-dist/assets/send-BKjswHxB.js.map +0 -1
  134. package/web-dist/assets/server-SxFxIScj.js +0 -2
  135. package/web-dist/assets/server-SxFxIScj.js.map +0 -1
  136. package/web-dist/assets/settings-D8T1esWq.js +0 -7
  137. package/web-dist/assets/settings-D8T1esWq.js.map +0 -1
  138. package/web-dist/assets/shared-CZ7fcu_B.js +0 -3
  139. package/web-dist/assets/shared-CZ7fcu_B.js.map +0 -1
  140. package/web-dist/assets/sliders-horizontal-DAoirila.js +0 -2
  141. package/web-dist/assets/sliders-horizontal-DAoirila.js.map +0 -1
  142. package/web-dist/assets/states--geW2Ntl.js +0 -2
  143. package/web-dist/assets/states--geW2Ntl.js.map +0 -1
  144. package/web-dist/assets/terminal-login-BJxV78au.js +0 -2
  145. package/web-dist/assets/terminal-login-BJxV78au.js.map +0 -1
  146. package/web-dist/assets/trash-C6X2OLrI.js +0 -2
  147. package/web-dist/assets/trash-C6X2OLrI.js.map +0 -1
  148. package/web-dist/assets/useNow-jxdoOC_1.js +0 -2
  149. package/web-dist/assets/useNow-jxdoOC_1.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"useNow-jxdoOC_1.js","names":["useId","useState","_Fragment","Filter","useMemo","useState","useRef","useCallback","useRef","__toESM","require_react","require_jsx_runtime","Badge","useProjects","apiDelete","useHosts","isApiError","apiPatch","useSyncStore","apiPost","apiGet","errorMessage","InteractionPending","UnsupportedCapability","HostUnavailable","Button","ErrorState","Search","CirclePlay","CirclePause","toast","X","ROUTES","Sheet","TextInput","Dialog","PRIORITY_LABELS","__iconData","Funnel","createLucideIcon","import_react","base","id","asTask","res","r","upsertTask","task","prev","s","createTask","body","updateTask","patch","deleteTask","_gone","rest","moveTask","taskAction","action","query","requestChanges","fetchEligibility","signal","fetchRuns","setDispatchPaused","paused","needsConfirmation","needsRunningChoice","d","BOARD_COLUMNS","STATE_LABELS","DEFAULT_FILTERS","normalizeFilters","v","raw","p","activeFilterChips","chips","f","x","q","hostName","taskHostId","runs","matchesFilters","ctx","sortTasks","out","tasks","sort","b","a","buildColumns","t","k","visibleColumns","TRANSITIONS","isRunActive","run","unresolvedForDone","reasons","checksRequired","failing","c","planMove","to","from","invalidReason","moveTargets","positionFor","list","column","movingId","beforeId","idx","next","WAIT_LABELS","eligibilityText","previewEligibility","input","project","state","unmet","hostId","host","openAttentionByTask","m","attention","dependencySummary","open","import_jsx_runtime","selectCls","ProjectSelect","projects","cn","className","board","e","SearchBox","SortSelect","CompletedToggle","DispatchToggle","busy","setBusy","Icon","compact","FilterFields","hosts","togglePriority","onChange","value","on","i","l","h","withSort","FilterButton","setOpen","draft","setDraft","count","Surface","mobile","FilterChips","includeSearch","BoardNotices","interactions","offlineIds","sessionIds","pend","nowErr","notices","offline","pending","useResource","data","setData","error","setError","loading","setLoading","key","nonce","setNonce","fetcherRef","fetcher","ctrl","opts","n","useNow","enabled","first","reload"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/funnel.mjs","../../src/features/board/api.ts","../../src/features/board/logic.ts","../../src/features/board/BoardChrome.tsx","../../src/features/board/useResource.ts","../../src/features/now/useNow.ts"],"sourcesContent":["/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"funnel\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z\",\n key: \"sc7q7i\"\n }\n ]\n ],\n aliases: [\"filter\"]\n};\n__iconData.node;\nconst Funnel = createLucideIcon(__iconData);\n\nexport { __iconData, Funnel as default };\n//# sourceMappingURL=funnel.mjs.map\n","import type { Eligibility, Run, Task, TaskState } from \"@switchyard/protocol\";\nimport { apiDelete, apiGet, apiPatch, apiPost, isApiError } from \"../../sync/api\";\nimport { useSyncStore } from \"../../sync/store\";\n\n/** REST helpers for tasks. Results are written to the store once acknowledged (no optimistic success). */\n\nconst base = (id: string) => `/api/tasks/${encodeURIComponent(id)}`;\n\nfunction asTask(res: unknown): Task | null {\n if (!res || typeof res !== \"object\") return null;\n const r = res as { task?: Task; id?: string; state?: string };\n if (r.task && typeof r.task === \"object\") return r.task;\n if (typeof r.id === \"string\" && typeof r.state === \"string\") return r as Task;\n return null;\n}\n\n/** Store the acknowledged task unless a newer version already arrived over the socket. */\nexport function upsertTask(res: unknown): Task | null {\n const task = asTask(res);\n if (!task) return null;\n useSyncStore.setState((s) => {\n const prev = s.tasks[task.id];\n if (prev && prev.updatedAt > task.updatedAt) return {};\n return { tasks: { ...s.tasks, [task.id]: task } };\n });\n return task;\n}\n\nexport interface CreateTaskBody {\n projectId: string;\n title: string;\n objective: string;\n acceptanceCriteria: string[];\n dependencies: string[];\n priority: 0 | 1 | 2 | 3;\n state: \"backlog\" | \"ready\";\n notBefore?: string | null;\n policy?: Partial<Task[\"policy\"]>;\n}\n\nexport async function createTask(body: CreateTaskBody): Promise<Task> {\n const res = await apiPost<unknown>(\"/api/tasks\", body);\n const t = upsertTask(res);\n if (!t) throw new Error(\"The coordinator returned an unexpected response\");\n return t;\n}\n\nexport async function updateTask(id: string, patch: Record<string, unknown>): Promise<Task | null> {\n return upsertTask(await apiPatch<unknown>(base(id), patch));\n}\n\nexport async function deleteTask(id: string): Promise<void> {\n await apiDelete(base(id));\n useSyncStore.setState((s) => {\n if (!s.tasks[id]) return {};\n const { [id]: _gone, ...rest } = s.tasks;\n return { tasks: rest };\n });\n}\n\nexport interface MoveBody {\n to: TaskState;\n confirm?: boolean;\n onRunning?: \"pause\" | \"stop\";\n position?: number;\n}\n\nexport async function moveTask(id: string, body: MoveBody): Promise<Task | null> {\n return upsertTask(await apiPost<unknown>(`${base(id)}/move`, body));\n}\n\nexport type TaskAction = \"run-now\" | \"accept\" | \"new-attempt\" | \"reopen\" | \"cancel\";\n\nexport async function taskAction(\n id: string,\n action: TaskAction,\n body?: unknown,\n query?: string,\n): Promise<Task | null> {\n return upsertTask(await apiPost<unknown>(`${base(id)}/${action}${query ?? \"\"}`, body));\n}\n\nexport async function requestChanges(id: string, feedback: string[]): Promise<Task | null> {\n return upsertTask(await apiPost<unknown>(`${base(id)}/request-changes`, { feedback }));\n}\n\nexport function fetchEligibility(id: string, signal?: AbortSignal): Promise<Eligibility> {\n return apiGet<Eligibility>(`${base(id)}/eligibility`, undefined, signal);\n}\n\nexport async function fetchRuns(id: string, signal?: AbortSignal): Promise<Run[]> {\n const res = await apiGet<Run[] | { runs: Run[] }>(`${base(id)}/runs`, undefined, signal);\n return Array.isArray(res) ? res : (res.runs ?? []);\n}\n\nexport async function setDispatchPaused(paused: boolean): Promise<void> {\n await apiPost(\"/api/dispatch/pause\", { paused });\n useSyncStore.setState({ dispatchPaused: paused });\n}\n\n/** A 409 that asks the user to confirm (e.g. Done with unresolved checks). */\nexport function needsConfirmation(e: unknown): boolean {\n if (!isApiError(e)) return false;\n if (e.status !== 409 && e.code !== \"invalid_transition\") return false;\n const d = e.details as { needsConfirm?: boolean; needsChoice?: boolean } | undefined;\n return d?.needsConfirm === true || /confirm/i.test(e.message);\n}\n\n/** A 409 that asks for the running-work choice (pause automation or stop execution). */\nexport function needsRunningChoice(e: unknown): boolean {\n if (!isApiError(e)) return false;\n const d = e.details as\n | { needsChoice?: boolean; onRunning?: boolean; choices?: unknown }\n | undefined;\n return (\n Array.isArray(d?.choices) ||\n d?.needsChoice === true ||\n d?.onRunning === true ||\n /pause automation or stop execution/i.test(e.message)\n );\n}\n","import type {\n AttentionItem,\n Eligibility,\n Host,\n Priority,\n Project,\n Run,\n Task,\n TaskState,\n} from \"@switchyard/protocol\";\nimport { PRIORITY_LABELS } from \"@switchyard/protocol\";\n\n/**\n * Pure board helpers (filters, sorting, move planning, eligibility wording).\n * Kept free of React so they are unit-testable.\n */\n\nexport const BOARD_COLUMNS: TaskState[] = [\"backlog\", \"ready\", \"in_progress\", \"review\", \"done\"];\n\nexport const STATE_LABELS: Record<TaskState, string> = {\n backlog: \"Backlog\",\n ready: \"Ready\",\n in_progress: \"In progress\",\n review: \"Review\",\n done: \"Done\",\n canceled: \"Canceled\",\n};\n\nexport type BoardSort = \"priority\" | \"updated\" | \"created\";\n\nexport interface BoardFilters {\n search: string;\n priorities: Priority[];\n hostId: string | null;\n attentionOnly: boolean;\n blockedOnly: boolean;\n showCanceled: boolean;\n showCompleted: boolean;\n sort: BoardSort;\n}\n\nexport const DEFAULT_FILTERS: BoardFilters = {\n search: \"\",\n priorities: [],\n hostId: null,\n attentionOnly: false,\n blockedOnly: false,\n showCanceled: false,\n showCompleted: true,\n sort: \"priority\",\n};\n\nexport function normalizeFilters(raw: unknown): BoardFilters {\n const v = (raw && typeof raw === \"object\" ? raw : {}) as Partial<BoardFilters>;\n return {\n search: typeof v.search === \"string\" ? v.search : \"\",\n priorities: Array.isArray(v.priorities)\n ? (v.priorities.filter((p) => [0, 1, 2, 3].includes(p as number)) as Priority[])\n : [],\n hostId: typeof v.hostId === \"string\" ? v.hostId : null,\n attentionOnly: v.attentionOnly === true,\n blockedOnly: v.blockedOnly === true,\n showCanceled: v.showCanceled === true,\n showCompleted: v.showCompleted !== false,\n sort: v.sort === \"updated\" || v.sort === \"created\" ? v.sort : \"priority\",\n };\n}\n\nexport interface ActiveFilterChip {\n key: string;\n label: string;\n clear: (f: BoardFilters) => BoardFilters;\n}\n\n/** Removable chips for every non-default filter (search shown separately on desktop). */\nexport function activeFilterChips(\n f: BoardFilters,\n hostName: (id: string) => string,\n): ActiveFilterChip[] {\n const chips: ActiveFilterChip[] = [];\n if (f.search.trim())\n chips.push({\n key: \"search\",\n label: `Search: ${f.search.trim()}`,\n clear: (x) => ({ ...x, search: \"\" }),\n });\n for (const p of f.priorities)\n chips.push({\n key: `priority-${p}`,\n label: `Priority: ${PRIORITY_LABELS[p]}`,\n clear: (x) => ({ ...x, priorities: x.priorities.filter((q) => q !== p) }),\n });\n if (f.hostId)\n chips.push({\n key: \"host\",\n label: `Host: ${hostName(f.hostId)}`,\n clear: (x) => ({ ...x, hostId: null }),\n });\n if (f.attentionOnly)\n chips.push({\n key: \"attention\",\n label: \"Needs attention\",\n clear: (x) => ({ ...x, attentionOnly: false }),\n });\n if (f.blockedOnly)\n chips.push({ key: \"blocked\", label: \"Blocked\", clear: (x) => ({ ...x, blockedOnly: false }) });\n if (f.showCanceled)\n chips.push({\n key: \"canceled\",\n label: \"Including canceled\",\n clear: (x) => ({ ...x, showCanceled: false }),\n });\n return chips;\n}\n\nexport interface FilterContext {\n projectId: string | null;\n runs: Record<string, Run>;\n /** Task ids with open attention. */\n attentionTaskIds: Set<string>;\n}\n\n/** The host a task runs (or will run) on: current run, explicit policy, or nothing. */\nexport function taskHostId(task: Task, runs: Record<string, Run>): string | null {\n const run = task.currentRunId ? runs[task.currentRunId] : undefined;\n return run?.hostId ?? task.policy.hostId ?? null;\n}\n\nexport function matchesFilters(task: Task, f: BoardFilters, ctx: FilterContext): boolean {\n if (task.hiddenFromBoard) return false;\n if (ctx.projectId && task.projectId !== ctx.projectId) return false;\n if (task.state === \"canceled\" && !f.showCanceled) return false;\n const q = f.search.trim().toLowerCase();\n if (q && !`${task.title}\\n${task.objective}`.toLowerCase().includes(q)) return false;\n if (f.priorities.length > 0 && !f.priorities.includes(task.priority)) return false;\n if (f.hostId && taskHostId(task, ctx.runs) !== f.hostId) return false;\n if (f.attentionOnly && !ctx.attentionTaskIds.has(task.id)) return false;\n if (f.blockedOnly && !task.blocked) return false;\n return true;\n}\n\nexport function sortTasks(tasks: Task[], sort: BoardSort): Task[] {\n const out = [...tasks];\n if (sort === \"updated\") out.sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt));\n else if (sort === \"created\") out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n else\n out.sort(\n (a, b) =>\n a.priority - b.priority ||\n a.position - b.position ||\n a.createdAt.localeCompare(b.createdAt),\n );\n return out;\n}\n\nexport type Columns = Record<TaskState, Task[]>;\n\nexport function buildColumns(\n tasks: Record<string, Task>,\n f: BoardFilters,\n ctx: FilterContext,\n): Columns {\n const out: Columns = {\n backlog: [],\n ready: [],\n in_progress: [],\n review: [],\n done: [],\n canceled: [],\n };\n for (const t of Object.values(tasks)) if (matchesFilters(t, f, ctx)) out[t.state].push(t);\n for (const k of Object.keys(out) as TaskState[]) out[k] = sortTasks(out[k], f.sort);\n return out;\n}\n\nexport function visibleColumns(f: BoardFilters): TaskState[] {\n return f.showCanceled ? [...BOARD_COLUMNS, \"canceled\"] : BOARD_COLUMNS;\n}\n\n/* ------------------------------------------------------------------ */\n/* Move planning */\n/* ------------------------------------------------------------------ */\n\n/** Client mirror of the coordinator's transition table (plans: tasks/state.ts). */\nexport const TRANSITIONS: Record<TaskState, TaskState[]> = {\n backlog: [\"ready\", \"canceled\"],\n ready: [\"backlog\", \"in_progress\", \"canceled\"],\n in_progress: [\"review\", \"ready\", \"backlog\", \"canceled\", \"done\"],\n review: [\"in_progress\", \"done\", \"ready\", \"canceled\"],\n done: [\"ready\", \"backlog\"],\n canceled: [\"backlog\"],\n};\n\nexport type MovePlan =\n | { kind: \"noop\" }\n | { kind: \"invalid\"; reason: string }\n /** Plain move (POST /move). */\n | { kind: \"move\" }\n /** Ready to In progress means \"Run now\" (dispatcher only). */\n | { kind: \"run_now\" }\n /** Review to In progress starts a new attempt. */\n | { kind: \"new_attempt\" }\n /** Running work moved backward: the user chooses pause automation or stop execution. */\n | { kind: \"choose_running\" }\n /** Moving to Done with unresolved criteria/checks: confirm acceptance. */\n | { kind: \"confirm_done\"; reasons: string[] };\n\n/** True while a run is live (dispatching, running, waiting, checking). */\nexport function isRunActive(run: Run | undefined | null): boolean {\n return (\n !!run &&\n [\"queued\", \"dispatching\", \"uncertain\", \"running\", \"waiting_input\", \"checking\"].includes(\n run.state,\n )\n );\n}\n\n/** Why moving to Done needs explicit acceptance; empty when nothing is unresolved. */\nexport function unresolvedForDone(task: Task, run: Run | undefined | null): string[] {\n const reasons: string[] = [];\n if (task.state !== \"review\") reasons.push(\"The task has not been through review.\");\n if (task.acceptanceCriteria.length > 0)\n reasons.push(\n `${task.acceptanceCriteria.length} acceptance ${\n task.acceptanceCriteria.length === 1 ? \"criterion has\" : \"criteria have\"\n } not been confirmed.`,\n );\n const checksRequired = (task.policy.completion.checks?.length ?? 0) > 0;\n const failing = run?.checks.filter((c) => c.exitCode !== 0) ?? [];\n if (failing.length > 0)\n reasons.push(`Checks failing: ${failing.map((c) => c.command).join(\", \")}.`);\n else if (checksRequired && (!run || run.checks.length === 0))\n reasons.push(\"Required checks have not run.\");\n if (task.policy.completion.requireHumanReview && task.state === \"review\")\n reasons.push(\"Human review is required: moving to Done accepts the work.\");\n return reasons;\n}\n\nexport function planMove(task: Task, to: TaskState, run?: Run | null): MovePlan {\n if (task.state === to) return { kind: \"noop\" };\n const from = task.state;\n if (!TRANSITIONS[from].includes(to)) {\n return { kind: \"invalid\", reason: invalidReason(from, to) };\n }\n if (from === \"ready\" && to === \"in_progress\") return { kind: \"run_now\" };\n if (from === \"review\" && to === \"in_progress\") return { kind: \"new_attempt\" };\n if (from === \"in_progress\" && (to === \"ready\" || to === \"backlog\")) {\n return { kind: \"choose_running\" };\n }\n if (to === \"done\") {\n const reasons = unresolvedForDone(task, run);\n if (reasons.length > 0) return { kind: \"confirm_done\", reasons };\n }\n return { kind: \"move\" };\n}\n\nfunction invalidReason(from: TaskState, to: TaskState): string {\n const f = STATE_LABELS[from];\n const t = STATE_LABELS[to];\n if (to === \"in_progress\")\n return from === \"backlog\"\n ? \"A Backlog task cannot start directly. Move it to Ready first; the dispatcher starts it when it is eligible.\"\n : `${f} tasks cannot be moved to In progress. Only the dispatcher starts work (Run now from Ready).`;\n if (to === \"review\")\n return \"Only a finished run moves a task to Review. Run the task, or use Done to accept it.\";\n if (from === \"canceled\") return \"A canceled task can only be restored to Backlog.\";\n if (from === \"done\" && to === \"canceled\")\n return \"A Done task cannot be canceled. Reopen it first.\";\n if (from === \"backlog\" && to === \"done\")\n return \"A Backlog task cannot be marked Done. Make it ready and review its work first.\";\n if (from === \"ready\" && to === \"done\")\n return \"A task that has not run cannot be marked Done. Run it, or cancel it.\";\n return `Moving from ${f} to ${t} is not allowed.`;\n}\n\n/** Valid targets for \"Move to…\" menus, excluding the current state. */\nexport function moveTargets(task: Task): TaskState[] {\n return TRANSITIONS[task.state];\n}\n\n/* ------------------------------------------------------------------ */\n/* Positions */\n/* ------------------------------------------------------------------ */\n\n/** Position that places a card before `beforeId` (or at the end) in a sorted column. */\nexport function positionFor(column: Task[], beforeId: string | null, movingId: string): number {\n const list = column.filter((t) => t.id !== movingId);\n if (list.length === 0) return 1;\n if (beforeId === null) return list[list.length - 1]!.position + 1;\n const idx = list.findIndex((t) => t.id === beforeId);\n if (idx < 0) return list[list.length - 1]!.position + 1;\n const next = list[idx]!.position;\n const prev = idx > 0 ? list[idx - 1]!.position : next - 2;\n return (prev + next) / 2;\n}\n\n/* ------------------------------------------------------------------ */\n/* Eligibility */\n/* ------------------------------------------------------------------ */\n\nexport type WaitReason = Extract<Eligibility, { eligible: false }>[\"wait\"];\n\nexport const WAIT_LABELS: Record<WaitReason, string> = {\n dependency: \"Waiting on dependencies\",\n host_offline: \"Host offline\",\n project_limit: \"Project run limit reached\",\n workspace_occupied: \"Workspace occupied\",\n scheduled_time: \"Scheduled for later\",\n invalid_configuration: \"Invalid configuration\",\n dispatch_paused: \"Dispatch paused\",\n project_automation_disabled: \"Project automation is off\",\n not_ready: \"Not ready\",\n already_dispatched: \"Already dispatched\",\n retry_backoff: \"Retrying after a failure\",\n};\n\nexport function eligibilityText(e: Eligibility): string {\n if (e.eligible) return `Will start automatically on ${e.hostName}`;\n return `Will wait: ${e.message || WAIT_LABELS[e.wait]}`;\n}\n\nexport interface PreviewInput {\n project: Project | undefined;\n hostId: string | null;\n dependencies: string[];\n notBefore?: string | null;\n}\n\nexport interface PreviewState {\n hosts: Record<string, Host>;\n tasks: Record<string, Task>;\n dispatchPaused: boolean;\n /** Tasks currently running per project (for the project limit). */\n runningByProject: Record<string, number>;\n}\n\n/**\n * Client-side eligibility estimate for a task that does not exist yet (or\n * when the coordinator returns `not_ready` for a Backlog task). The\n * coordinator's dispatcher stays authoritative.\n */\nexport function previewEligibility(input: PreviewInput, state: PreviewState): Eligibility {\n const { project } = input;\n if (!project)\n return { eligible: false, wait: \"invalid_configuration\", message: \"Choose a project\" };\n if (state.dispatchPaused)\n return {\n eligible: false,\n wait: \"dispatch_paused\",\n message: \"Dispatch is paused; resume it to start new work\",\n };\n if (!project.automationEnabled)\n return {\n eligible: false,\n wait: \"project_automation_disabled\",\n message: `Automation is off for ${project.name}`,\n };\n const unmet = input.dependencies\n .map((id) => state.tasks[id])\n .filter((t): t is Task => !!t && t.state !== \"done\");\n if (unmet.length > 0)\n return {\n eligible: false,\n wait: \"dependency\",\n message: `Waiting on ${unmet.map((t) => t.title).join(\", \")}`,\n };\n if (input.notBefore && Date.parse(input.notBefore) > Date.now())\n return {\n eligible: false,\n wait: \"scheduled_time\",\n message: `Scheduled for ${new Date(input.notBefore).toLocaleString()}`,\n };\n const hostId = input.hostId ?? project.defaultHostId;\n const host = hostId ? state.hosts[hostId] : undefined;\n if (!host || host.revokedAt)\n return {\n eligible: false,\n wait: \"invalid_configuration\",\n message: \"No host is configured for this project\",\n };\n if (!host.piCompatible)\n return {\n eligible: false,\n wait: \"invalid_configuration\",\n message: `Pi on ${host.name} is not compatible`,\n };\n if (host.connectivity !== \"connected\")\n return { eligible: false, wait: \"host_offline\", message: `${host.name} is offline` };\n if ((state.runningByProject[project.id] ?? 0) >= project.maxConcurrentRuns)\n return {\n eligible: false,\n wait: \"project_limit\",\n message: `${project.name} already runs ${project.maxConcurrentRuns} of ${project.maxConcurrentRuns} allowed tasks`,\n };\n return { eligible: true, hostId: host.id, hostName: host.name };\n}\n\n/* ------------------------------------------------------------------ */\n/* Card text */\n/* ------------------------------------------------------------------ */\n\nexport function openAttentionByTask(\n attention: Record<string, AttentionItem>,\n): Map<string, AttentionItem[]> {\n const m = new Map<string, AttentionItem[]>();\n for (const a of Object.values(attention)) {\n if (a.resolvedAt || !a.taskId) continue;\n const list = m.get(a.taskId) ?? [];\n list.push(a);\n m.set(a.taskId, list);\n }\n return m;\n}\n\nexport function dependencySummary(task: Task, tasks: Record<string, Task>): string | null {\n const n = task.dependencies.length;\n if (n === 0) return null;\n const open = task.dependencies.filter((id) => tasks[id]?.state !== \"done\").length;\n const base = `${n} ${n === 1 ? \"dependency\" : \"dependencies\"}`;\n return open > 0 ? `${base} (${open} open)` : `${base} (all done)`;\n}\n","import type { Priority } from \"@switchyard/protocol\";\nimport { PRIORITY_LABELS } from \"@switchyard/protocol\";\nimport { CirclePause, CirclePlay, Filter, Search, X } from \"lucide-react\";\nimport { type ReactNode, useId, useMemo, useState } from \"react\";\nimport { ROUTES } from \"../../app/routes\";\nimport { Badge } from \"../../components/ui/Badge\";\nimport { Button } from \"../../components/ui/Button\";\nimport { Dialog, Sheet } from \"../../components/ui/Overlay\";\nimport {\n ErrorState,\n HostUnavailable,\n InteractionPending,\n UnsupportedCapability,\n} from \"../../components/ui/states\";\nimport { TextInput } from \"../../components/ui/TextArea\";\nimport { toast } from \"../../components/ui/Toast\";\nimport { cn } from \"../../lib/cn\";\nimport { errorMessage, isApiError } from \"../../sync/api\";\nimport { useHosts, useProjects, useSyncStore } from \"../../sync/store\";\nimport { setDispatchPaused } from \"./api\";\nimport { activeFilterChips, type BoardFilters, type BoardSort, DEFAULT_FILTERS } from \"./logic\";\nimport type { BoardState } from \"./useBoard\";\n\nconst selectCls =\n \"tap h-9 min-w-0 rounded-md border border-border bg-surface px-2 text-base text-text md:text-sm\";\n\nexport function ProjectSelect({ board, className }: { board: BoardState; className?: string }) {\n const projects = useProjects();\n const id = useId();\n return (\n <div className={cn(\"flex min-w-0 items-center gap-2\", className)}>\n <label htmlFor={id} className=\"sr-only\">\n Project\n </label>\n <select\n id={id}\n className={cn(selectCls, \"w-full max-w-56\")}\n value={board.projectId ?? \"\"}\n onChange={(e) => board.setProjectId(e.target.value || null)}\n >\n <option value=\"\">All projects</option>\n {projects.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n </div>\n );\n}\n\nexport function SearchBox({ board, className }: { board: BoardState; className?: string }) {\n const id = useId();\n return (\n <div className={cn(\"relative min-w-0\", className)}>\n <label htmlFor={id} className=\"sr-only\">\n Search tasks\n </label>\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-subtle\"\n />\n <TextInput\n id={id}\n type=\"search\"\n placeholder=\"Search tasks\"\n className=\"pl-8\"\n value={board.filters.search}\n onChange={(e) => board.setFilters({ ...board.filters, search: e.target.value })}\n />\n </div>\n );\n}\n\nexport function SortSelect({ board }: { board: BoardState }) {\n const id = useId();\n return (\n <div className=\"flex items-center gap-1.5 text-sm\">\n <label htmlFor={id} className=\"text-muted\">\n Sort\n </label>\n <select\n id={id}\n className={selectCls}\n value={board.filters.sort}\n onChange={(e) => board.setFilters({ ...board.filters, sort: e.target.value as BoardSort })}\n >\n <option value=\"priority\">Priority</option>\n <option value=\"updated\">Recently updated</option>\n <option value=\"created\">Newest</option>\n </select>\n </div>\n );\n}\n\nexport function CompletedToggle({ board }: { board: BoardState }) {\n return (\n <label className=\"tap inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={board.filters.showCompleted}\n onChange={(e) => board.setFilters({ ...board.filters, showCompleted: e.target.checked })}\n />\n Show completed\n </label>\n );\n}\n\n/** Automation enabled/paused status and the pause/resume toggle (never terminates active runs). */\nexport function DispatchToggle({ compact }: { compact?: boolean }) {\n const paused = useSyncStore((s) => s.dispatchPaused);\n const [busy, setBusy] = useState(false);\n const Icon = paused ? CirclePause : CirclePlay;\n return (\n <div className=\"flex min-w-0 flex-wrap items-center gap-2 text-sm\">\n <span\n role=\"status\"\n className={cn(\n \"inline-flex items-center gap-1.5 font-medium\",\n paused ? \"text-warning\" : \"text-success\",\n )}\n >\n <Icon aria-hidden className=\"size-4\" />\n <span className=\"text-text\">{paused ? \"Automation paused\" : \"Automation enabled\"}</span>\n </span>\n <Button\n size=\"sm\"\n busy={busy}\n onClick={async () => {\n setBusy(true);\n try {\n await setDispatchPaused(!paused);\n toast.success(\n paused\n ? \"Dispatch resumed. Ready tasks start when eligible.\"\n : \"Dispatch paused. Running work continues; nothing new starts.\",\n );\n } catch (e) {\n toast.error(`Could not ${paused ? \"resume\" : \"pause\"} dispatch: ${errorMessage(e)}`);\n } finally {\n setBusy(false);\n }\n }}\n >\n {paused ? \"Resume dispatch\" : compact ? \"Pause\" : \"Pause dispatch\"}\n </Button>\n </div>\n );\n}\n\nfunction FilterFields({\n value,\n onChange,\n withSort,\n}: {\n value: BoardFilters;\n onChange: (f: BoardFilters) => void;\n withSort?: boolean;\n}) {\n const hosts = useHosts();\n const id = useId();\n const togglePriority = (p: Priority, on: boolean) =>\n onChange({\n ...value,\n priorities: on ? [...value.priorities, p] : value.priorities.filter((x) => x !== p),\n });\n return (\n <div className=\"flex flex-col gap-4\">\n <fieldset className=\"flex flex-col gap-1\">\n <legend className=\"mb-1 text-sm font-medium\">Priority</legend>\n <div className=\"flex flex-wrap gap-x-4\">\n {PRIORITY_LABELS.map((l, i) => (\n <label key={l} className=\"tap inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={value.priorities.includes(i as Priority)}\n onChange={(e) => togglePriority(i as Priority, e.target.checked)}\n />\n {l}\n </label>\n ))}\n </div>\n </fieldset>\n <div className=\"flex flex-col gap-1\">\n <label htmlFor={`${id}-host`} className=\"text-sm font-medium\">\n Host\n </label>\n <select\n id={`${id}-host`}\n className={selectCls}\n value={value.hostId ?? \"\"}\n onChange={(e) => onChange({ ...value, hostId: e.target.value || null })}\n >\n <option value=\"\">Any host</option>\n {hosts.map((h) => (\n <option key={h.id} value={h.id}>\n {h.name}\n </option>\n ))}\n </select>\n </div>\n <fieldset className=\"flex flex-col gap-1\">\n <legend className=\"mb-1 text-sm font-medium\">Show</legend>\n <label className=\"tap inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={value.attentionOnly}\n onChange={(e) => onChange({ ...value, attentionOnly: e.target.checked })}\n />\n Only tasks that need attention\n </label>\n <label className=\"tap inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={value.blockedOnly}\n onChange={(e) => onChange({ ...value, blockedOnly: e.target.checked })}\n />\n Only blocked tasks\n </label>\n <label className=\"tap inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={value.showCanceled}\n onChange={(e) => onChange({ ...value, showCanceled: e.target.checked })}\n />\n Canceled tasks\n </label>\n <label className=\"tap inline-flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={value.showCompleted}\n onChange={(e) => onChange({ ...value, showCompleted: e.target.checked })}\n />\n Completed tasks\n </label>\n </fieldset>\n {withSort && (\n <div className=\"flex flex-col gap-1\">\n <label htmlFor={`${id}-sort`} className=\"text-sm font-medium\">\n Sort\n </label>\n <select\n id={`${id}-sort`}\n className={selectCls}\n value={value.sort}\n onChange={(e) => onChange({ ...value, sort: e.target.value as BoardSort })}\n >\n <option value=\"priority\">Priority</option>\n <option value=\"updated\">Recently updated</option>\n <option value=\"created\">Newest</option>\n </select>\n </div>\n )}\n </div>\n );\n}\n\n/** Filters button: a dialog on desktop, a sheet on mobile. Applies on \"Show results\". */\nexport function FilterButton({ board, mobile }: { board: BoardState; mobile?: boolean }) {\n const [open, setOpen] = useState(false);\n const [draft, setDraft] = useState(board.filters);\n const hosts = useSyncStore((s) => s.hosts);\n const count = activeFilterChips(board.filters, (id) => hosts[id]?.name ?? \"host\").filter(\n (c) => c.key !== \"search\",\n ).length;\n const Surface = mobile ? Sheet : Dialog;\n return (\n <>\n <Button\n icon={<Filter className=\"size-4\" />}\n onClick={() => {\n setDraft(board.filters);\n setOpen(true);\n }}\n aria-label={count ? `Filters, ${count} active` : \"Filters\"}\n >\n Filters\n {count > 0 && <Badge tone=\"accent\">{count}</Badge>}\n </Button>\n <Surface\n open={open}\n onClose={() => setOpen(false)}\n title=\"Filter tasks\"\n footer={\n <>\n <Button\n variant=\"ghost\"\n onClick={() => setDraft({ ...DEFAULT_FILTERS, search: draft.search })}\n >\n Reset\n </Button>\n <Button\n variant=\"primary\"\n onClick={() => {\n board.setFilters(draft);\n setOpen(false);\n }}\n >\n Show results\n </Button>\n </>\n }\n >\n <FilterFields value={draft} onChange={setDraft} withSort={mobile} />\n </Surface>\n </>\n );\n}\n\n/** Active filters as removable chips. */\nexport function FilterChips({\n board,\n includeSearch,\n}: {\n board: BoardState;\n includeSearch?: boolean;\n}) {\n const hosts = useSyncStore((s) => s.hosts);\n const chips = activeFilterChips(board.filters, (id) => hosts[id]?.name ?? \"Unknown host\").filter(\n (c) => includeSearch || c.key !== \"search\",\n );\n if (chips.length === 0) return null;\n return (\n <ul\n data-testid=\"filter-chips\"\n aria-label=\"Active filters\"\n className=\"flex min-w-0 flex-wrap gap-1.5\"\n >\n {chips.map((c) => (\n <li key={c.key} className=\"min-w-0\">\n <button\n type=\"button\"\n onClick={() => board.setFilters(c.clear(board.filters))}\n aria-label={`Remove filter ${c.label}`}\n className=\"tap inline-flex max-w-full items-center gap-1 rounded-full border border-border bg-surface-2 px-2.5 py-0.5 text-xs font-medium\"\n >\n <span className=\"truncate\">{c.label}</span>\n <X aria-hidden className=\"size-3.5 shrink-0\" />\n </button>\n </li>\n ))}\n {chips.length > 1 && (\n <li>\n <button\n type=\"button\"\n className=\"tap rounded px-2 py-0.5 text-xs font-medium text-accent\"\n onClick={() => board.setFilters({ ...DEFAULT_FILTERS, sort: board.filters.sort })}\n >\n Clear all\n </button>\n </li>\n )}\n </ul>\n );\n}\n\n/** Host unavailable, pending interactions and queue-detail problems above the board (spec 18). */\nexport function BoardNotices({ board }: { board: BoardState }) {\n const tasks = useSyncStore((s) => s.tasks);\n const runs = useSyncStore((s) => s.runs);\n const hosts = useSyncStore((s) => s.hosts);\n const interactions = useSyncStore((s) => s.interactions);\n const { offline, pending } = useMemo(() => {\n const offlineIds = new Set<string>();\n const sessionIds = new Set<string>();\n for (const t of Object.values(tasks)) {\n if (board.projectId && t.projectId !== board.projectId) continue;\n if (t.sessionId) sessionIds.add(t.sessionId);\n const run = t.currentRunId ? runs[t.currentRunId] : undefined;\n if (t.state === \"in_progress\" && run?.hostId) {\n const h = hosts[run.hostId];\n if (h && h.connectivity !== \"connected\") offlineIds.add(h.id);\n }\n }\n const pend = Object.values(interactions)\n .filter((i) => i.state === \"pending\" && sessionIds.has(i.sessionId))\n .sort((a, b) => a.createdAt.localeCompare(b.createdAt));\n return { offline: [...offlineIds].map((id) => hosts[id]!), pending: pend };\n }, [tasks, runs, hosts, interactions, board.projectId]);\n\n const nowErr = board.now.error;\n const notices: ReactNode[] = [];\n for (const h of offline)\n notices.push(\n <HostUnavailable\n key={`host-${h.id}`}\n compact\n hostName={h.name}\n connectivity={h.connectivity === \"reconnecting\" ? \"reconnecting\" : \"unreachable\"}\n lastSeenAt={h.lastSeenAt}\n detail=\"Its In progress tasks keep their last known state; nothing is restarted elsewhere.\"\n />,\n );\n if (pending.length > 0)\n notices.push(\n <InteractionPending\n key=\"pending\"\n count={pending.length}\n to={ROUTES.interaction(pending[0]!.sessionId, pending[0]!.id)}\n label={\n pending.length === 1\n ? \"A task needs your answer\"\n : `${pending.length} questions need your answer`\n }\n />,\n );\n if (nowErr !== null && nowErr !== undefined) {\n if (isApiError(nowErr) && nowErr.status === 404)\n notices.push(\n <UnsupportedCapability\n key=\"now\"\n capability=\"Queue details\"\n reason=\"This coordinator does not report why Ready tasks are waiting.\"\n />,\n );\n else\n notices.push(\n <ErrorState\n key=\"now\"\n compact\n title=\"Could not load the dispatch queue\"\n error={errorMessage(nowErr)}\n onRetry={board.now.reload}\n />,\n );\n }\n if (notices.length === 0) return null;\n return <div className=\"flex flex-col gap-2 px-4 pt-2\">{notices}</div>;\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface Resource<T> {\n data: T | undefined;\n error: unknown;\n loading: boolean;\n /** Refetch; keeps the last data while loading. */\n reload: () => void;\n}\n\n/**\n * Fetch a REST resource. `key` changes trigger a refetch; null skips fetching.\n * Errors keep the last good data so views can show last-known state.\n */\nexport function useResource<T>(\n key: string | null,\n fetcher: (signal: AbortSignal) => Promise<T>,\n opts: { refreshMs?: number } = {},\n): Resource<T> {\n const [data, setData] = useState<T | undefined>(undefined);\n const [error, setError] = useState<unknown>(null);\n const [loading, setLoading] = useState(key !== null);\n const [nonce, setNonce] = useState(0);\n const fetcherRef = useRef(fetcher);\n fetcherRef.current = fetcher;\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: nonce forces a reload\n useEffect(() => {\n if (key === null) {\n setLoading(false);\n return;\n }\n const ctrl = new AbortController();\n setLoading(true);\n fetcherRef\n .current(ctrl.signal)\n .then((d) => {\n if (ctrl.signal.aborted) return;\n setData(d);\n setError(null);\n })\n .catch((e) => {\n if (ctrl.signal.aborted || (e instanceof DOMException && e.name === \"AbortError\")) return;\n setError(e);\n })\n .finally(() => {\n if (!ctrl.signal.aborted) setLoading(false);\n });\n return () => ctrl.abort();\n }, [key, nonce]);\n\n useEffect(() => {\n if (!opts.refreshMs || key === null) return;\n const t = setInterval(() => {\n if (document.visibilityState === \"visible\") setNonce((n) => n + 1);\n }, opts.refreshMs);\n return () => clearInterval(t);\n }, [opts.refreshMs, key]);\n\n const reload = useCallback(() => setNonce((n) => n + 1), []);\n return { data, error, loading, reload };\n}\n","import type { NowResponse } from \"@switchyard/protocol\";\nimport { useEffect, useRef } from \"react\";\nimport { apiGet } from \"../../sync/api\";\nimport { useSyncStore } from \"../../sync/store\";\nimport { type Resource, useResource } from \"../board/useResource\";\n\n/**\n * GET /api/now: running runs, queued Ready tasks with their wait reason and\n * the dispatch-paused flag. Refetches when tasks/runs change (debounced) and\n * every 15 s while visible.\n */\nexport function useNow(enabled = true): Resource<NowResponse> {\n const res = useResource<NowResponse>(\n enabled ? \"now\" : null,\n (signal) => apiGet<NowResponse>(\"/api/now\", undefined, signal),\n { refreshMs: 15_000 },\n );\n const tasks = useSyncStore((s) => s.tasks);\n const runs = useSyncStore((s) => s.runs);\n const paused = useSyncStore((s) => s.dispatchPaused);\n const first = useRef(true);\n const { reload } = res;\n // biome-ignore lint/correctness/useExhaustiveDependencies: refetch on entity changes\n useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n if (!enabled) return;\n const t = setTimeout(reload, 500);\n return () => clearTimeout(t);\n }, [tasks, runs, paused, enabled, reload]);\n return res;\n}\n"],"ignoreList":[0],"mappings":"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"}