@humwick/server 0.130.0 → 0.130.2

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 (486) hide show
  1. package/README.md +5 -0
  2. package/docs/guides/tools-administration.md +6 -1
  3. package/docs/guides/tools-coordination.md +1 -0
  4. package/docs/guides/tools-tasks.md +8 -0
  5. package/docs/guides/workflows.md +58 -0
  6. package/docs/openapi.json +414 -1
  7. package/package.json +8 -17
  8. package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
  9. package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
  10. package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
  11. package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
  12. package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
  13. package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
  14. package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
  15. package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
  16. package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
  17. package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
  18. package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
  19. package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
  20. package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
  21. package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
  22. package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
  23. package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
  24. package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
  25. package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
  26. package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
  27. package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
  28. package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
  29. package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
  30. package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
  31. package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
  32. package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
  33. package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
  34. package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
  35. package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
  36. package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
  37. package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
  38. package/public/assets/fleet-C7jQWbw2.js +2 -0
  39. package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
  40. package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
  41. package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
  42. package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
  43. package/public/assets/index-CRHep3M9.js +15 -0
  44. package/public/assets/index-MYAIwYTX.css +2 -0
  45. package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
  46. package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
  47. package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
  48. package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
  49. package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
  50. package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
  51. package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
  52. package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
  53. package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
  54. package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
  55. package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
  56. package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
  57. package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
  58. package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
  59. package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
  60. package/public/assets/projects-Br2Bd2h1.js +2 -0
  61. package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
  62. package/public/assets/provider-display-DsuWMvVL.js +2 -0
  63. package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
  64. package/public/assets/run-card-CpKqRbhg.js +2 -0
  65. package/public/assets/scroll-text-BKXS1ahr.js +2 -0
  66. package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
  67. package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
  68. package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
  69. package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
  70. package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
  71. package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
  72. package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
  73. package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
  74. package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
  75. package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
  76. package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
  77. package/public/assets/token-estimate-Co-Jdphh.js +2 -0
  78. package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
  79. package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
  80. package/public/assets/use-project-list-59LheVP7.js +2 -0
  81. package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
  82. package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
  83. package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
  84. package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
  85. package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
  86. package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
  87. package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
  88. package/public/cosmos.html +4 -4
  89. package/public/index.html +31 -29
  90. package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
  91. package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
  92. package/runner/src/adapters/claude-effort.ts +2 -4
  93. package/runner/src/adapters/codex-launch-config.ts +4 -5
  94. package/runner/src/adapters/codex.ts +1 -1
  95. package/runner/src/adapters/opencode-provider.ts +7 -22
  96. package/runner/src/adapters/opencode.ts +4 -4
  97. package/runner/src/agent-runner/credentials.ts +42 -12
  98. package/runner/src/agent-runner/inbox.ts +27 -0
  99. package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
  100. package/runner/src/bin/claude.ts +4 -0
  101. package/runner/src/bin/codex.ts +4 -0
  102. package/runner/src/bin/opencode.ts +4 -0
  103. package/runner/src/index.ts +5 -2
  104. package/runner/src/provider-setup.ts +34 -0
  105. package/runner/src/providers.ts +2 -1
  106. package/runner/src/runner-core.ts +18 -23
  107. package/runner/src/spawn-input.ts +2 -1
  108. package/runner/src/test-run-dedup.ts +59 -56
  109. package/scripts/cd-config.ts +24 -3
  110. package/scripts/gate-run-lease.ts +10 -7
  111. package/scripts/gate.sh +5 -1
  112. package/src/branch-land-notice.ts +93 -0
  113. package/src/branch-landed.ts +7 -76
  114. package/src/bus.ts +19 -20
  115. package/src/cd-deploy-notify.ts +30 -2
  116. package/src/cd-host-lag-notify.ts +7 -6
  117. package/src/ci/incidents.ts +2 -2
  118. package/src/ci/monitor.ts +5 -8
  119. package/src/ci/root-missing.ts +2 -7
  120. package/src/ci/transition-notify.ts +7 -39
  121. package/src/cli/cd-pauses.ts +19 -0
  122. package/src/cli/orchestrator.ts +1 -1
  123. package/src/cli/state.ts +2 -19
  124. package/src/cli/task-edit.ts +22 -0
  125. package/src/cli/task.ts +3 -1
  126. package/src/cli/workflow.ts +8 -2
  127. package/src/commands-db.ts +10 -6
  128. package/src/commands-write.ts +8 -0
  129. package/src/config-store-write.ts +13 -1
  130. package/src/config-store.ts +25 -14
  131. package/src/db/activity-async.ts +6 -1
  132. package/src/db/activity-write-ops.ts +13 -1
  133. package/src/db/activity.ts +1 -14
  134. package/src/db/agent-lifecycle-write-ops.ts +1 -0
  135. package/src/db/agent-meta.ts +2 -2
  136. package/src/db/agent-ownership-write-ops.ts +4 -0
  137. package/src/db/agent-search.ts +1 -15
  138. package/src/db/agents-async.ts +58 -7
  139. package/src/db/agents-write-ops.ts +28 -5
  140. package/src/db/agents.ts +81 -54
  141. package/src/db/artifacts-write-ops.ts +8 -3
  142. package/src/db/bus-outbox-write-ops.ts +1 -0
  143. package/src/db/channels-write-ops.ts +4 -0
  144. package/src/db/ci-incidents-async.ts +5 -5
  145. package/src/db/ci-incidents-write-ops.ts +2 -2
  146. package/src/db/claude-api-budget-ops.ts +5 -5
  147. package/src/db/claude-app-oauth.ts +4 -4
  148. package/src/db/codex-reset-consumes-write-ops.ts +3 -0
  149. package/src/db/command-row.ts +10 -2
  150. package/src/db/commands-list-query.ts +2 -0
  151. package/src/db/commands-spawn-read.ts +1 -1
  152. package/src/db/commands-write-ops.ts +21 -0
  153. package/src/db/config-store-write-ops.ts +9 -2
  154. package/src/db/continuation-archives-async.ts +5 -0
  155. package/src/db/continuation-archives-write-ops.ts +9 -0
  156. package/src/db/continuations.ts +2 -2
  157. package/src/db/db-writer-worker.ts +8 -1
  158. package/src/db/delivery-write-ops.ts +5 -0
  159. package/src/db/deploy-events-async.ts +1 -0
  160. package/src/db/deploy-events-read-ops.ts +2 -1
  161. package/src/db/deploy-events.ts +35 -4
  162. package/src/db/hosts-registration.ts +10 -2
  163. package/src/db/hosts-write-ops.ts +14 -0
  164. package/src/db/hosts.ts +9 -6
  165. package/src/db/inbox-write-ops.ts +4 -0
  166. package/src/db/inbox.ts +0 -14
  167. package/src/db/index.ts +2 -0
  168. package/src/db/insights-write-ops.ts +1 -0
  169. package/src/db/integrations-async.ts +8 -0
  170. package/src/db/integrations-ops.ts +15 -0
  171. package/src/db/integrations.ts +15 -21
  172. package/src/db/issue-lifecycle.ts +3 -4
  173. package/src/db/issue-refs-async.ts +20 -0
  174. package/src/db/issue-refs-write-ops.ts +29 -0
  175. package/src/db/issue-refs.ts +7 -8
  176. package/src/db/long-running-work.ts +2 -2
  177. package/src/db/macos-privacy.ts +1 -1
  178. package/src/db/main-connection-writes.ts +23 -2
  179. package/src/db/maintenance-job-reconcile.ts +61 -0
  180. package/src/db/maintenance-job-runs-async.ts +14 -0
  181. package/src/db/maintenance-job-write-ops.ts +9 -0
  182. package/src/db/mappers.ts +2 -14
  183. package/src/db/merge-lease.ts +1 -15
  184. package/src/db/message-reads-write-ops.ts +3 -0
  185. package/src/db/message-write-ops.ts +4 -0
  186. package/src/db/migrations.ts +7 -15
  187. package/src/db/orchestrators-async.ts +7 -3
  188. package/src/db/orchestrators-write-ops.ts +7 -1
  189. package/src/db/orchestrators.ts +21 -77
  190. package/src/db/pairs.ts +1 -13
  191. package/src/db/project-profile-instructions.ts +50 -0
  192. package/src/db/prompt-versions-ops.ts +1 -0
  193. package/src/db/prompt-versions.ts +9 -2
  194. package/src/db/provider-catalog-write-ops.ts +4 -4
  195. package/src/db/provider-config-history.ts +8 -3
  196. package/src/db/provider-flap-messages-write-ops.ts +1 -0
  197. package/src/db/provider-model-seed.ts +34 -0
  198. package/src/db/provider-quota-lease-write-ops.ts +1 -0
  199. package/src/db/provider-quota-write-ops.ts +2 -0
  200. package/src/db/provisioning-write-ops.ts +9 -8
  201. package/src/db/read-op-marshaling-fixtures.ts +5 -0
  202. package/src/db/read-ops.ts +4 -0
  203. package/src/db/routing-policy.ts +3 -4
  204. package/src/db/schema.ts +9 -3
  205. package/src/db/secrets-broker-write-ops.ts +5 -5
  206. package/src/db/secrets-vault-write.ts +7 -7
  207. package/src/db/services-write-ops.ts +3 -0
  208. package/src/db/spawn-delegation-state.ts +11 -4
  209. package/src/db/spawn-tree-cleanup.ts +3 -0
  210. package/src/db/stats-async.ts +4 -3
  211. package/src/db/task-entity.ts +23 -2
  212. package/src/db/task-list.ts +3 -1
  213. package/src/db/tasks.ts +1 -17
  214. package/src/db/team-spawn-delegation.ts +1 -1
  215. package/src/db/teams-write-ops.ts +4 -4
  216. package/src/db/timer-cutover-write-ops.ts +7 -0
  217. package/src/db/timer-ingress-write-ops.ts +9 -0
  218. package/src/db/timer-ingress.ts +7 -1
  219. package/src/db/timer-operator-write-ops.ts +14 -0
  220. package/src/db/timer-transfer-write-ops.ts +4 -0
  221. package/src/db/timer-write-ops.ts +14 -0
  222. package/src/db/token-db-write-ops.ts +21 -0
  223. package/src/db/token-standing.ts +15 -11
  224. package/src/db/user-settings-write-ops.ts +1 -0
  225. package/src/db/vault-backup.ts +2 -2
  226. package/src/db/vault-expiry.ts +2 -2
  227. package/src/db/vault-health.ts +3 -3
  228. package/src/db/vault-token-ops.ts +8 -8
  229. package/src/db/web-tool-call-ops.ts +3 -3
  230. package/src/db/workflow-contact.ts +1 -1
  231. package/src/db/workflow-task-read-ops.ts +30 -0
  232. package/src/db/write-ops.ts +15 -1
  233. package/src/db/writer-fault-seam.ts +5 -2
  234. package/src/db/writer-gateway.ts +21 -12
  235. package/src/dispatch-availability.ts +10 -6
  236. package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
  237. package/src/host/disk-alert.ts +121 -0
  238. package/src/lifecycle-manager.ts +3 -2
  239. package/src/maintenance/cd-watcher.ts +3 -3
  240. package/src/maintenance/critical-job-watchdog.ts +16 -17
  241. package/src/maintenance/index.ts +1 -0
  242. package/src/maintenance/jobs.ts +3 -2
  243. package/src/maintenance/scheduler.ts +84 -128
  244. package/src/maintenance/stalled-delivery-pager.ts +6 -5
  245. package/src/maintenance/workspaces.ts +1 -1
  246. package/src/managed-policy.ts +31 -27
  247. package/src/mcp/index.ts +5 -2
  248. package/src/mcp/output-descriptions.ts +8 -8
  249. package/src/mcp/presentation.ts +4 -4
  250. package/src/mcp/project-profile-instructions.ts +32 -0
  251. package/src/mcp/tool-groups.ts +1 -1
  252. package/src/mcp/tools-spawn.ts +4 -3
  253. package/src/mcp-agent-action.ts +1 -2
  254. package/src/mcp-host-tools.ts +1 -1
  255. package/src/mcp-issue-ref-tools.ts +12 -11
  256. package/src/mcp-maintenance-tools.ts +2 -2
  257. package/src/mcp-profile-trust-tools.ts +4 -4
  258. package/src/mcp-provider-catalog.ts +2 -2
  259. package/src/mcp-task-tools.ts +11 -5
  260. package/src/mcp-team-template-tools.ts +3 -3
  261. package/src/mcp-workflow-tools.ts +10 -3
  262. package/src/notification-types.ts +2 -1
  263. package/src/operator-alarm.ts +26 -11
  264. package/src/package-pack.ts +42 -39
  265. package/src/project-instructions.ts +4 -0
  266. package/src/project-profile-instruction-text.ts +6 -0
  267. package/src/project-profile-instructions.ts +20 -0
  268. package/src/provider-catalog-store.ts +3 -49
  269. package/src/provider-config-store.ts +12 -11
  270. package/src/provider-model-seed.ts +1 -18
  271. package/src/provider-quota-config-store.ts +5 -4
  272. package/src/provider-secrets.test-fixture.ts +3 -3
  273. package/src/recipe-runner.ts +2 -2
  274. package/src/repo-config-source.ts +10 -4
  275. package/src/routes/agent-profiles.ts +6 -6
  276. package/src/routes/agents-spawn.ts +1 -1
  277. package/src/routes/agents.ts +6 -6
  278. package/src/routes/commands-listing.ts +4 -0
  279. package/src/routes/commands.ts +2 -2
  280. package/src/routes/continuation-archives.ts +2 -2
  281. package/src/routes/host-resource-control.ts +4 -1
  282. package/src/routes/index.ts +10 -1
  283. package/src/routes/integrations.ts +24 -50
  284. package/src/routes/issue-refs.ts +7 -7
  285. package/src/routes/orchestrator-bootstrap.ts +3 -3
  286. package/src/routes/orchestrator-host-registration.ts +2 -2
  287. package/src/routes/orchestrator-host-utilization.ts +3 -1
  288. package/src/routes/orchestrator-proxy.ts +2 -2
  289. package/src/routes/orchestrator.ts +4 -4
  290. package/src/routes/project-profile-instructions.ts +27 -0
  291. package/src/routes/project-trust.ts +2 -2
  292. package/src/routes/provider-config.ts +9 -8
  293. package/src/routes/provider-quota-config.ts +2 -2
  294. package/src/routes/settings.ts +5 -5
  295. package/src/routes/stats.ts +6 -6
  296. package/src/routes/task-http.ts +15 -1
  297. package/src/routes/task-issues.ts +11 -26
  298. package/src/routes/tasks.ts +22 -53
  299. package/src/routes/team-templates.ts +5 -5
  300. package/src/routes/teams-config.ts +2 -2
  301. package/src/routes/tokens.ts +12 -5
  302. package/src/routes/workflows.ts +20 -5
  303. package/src/routing-policy-normalize.ts +1 -2
  304. package/src/routing-step-defaults.ts +0 -2
  305. package/src/runner-token-mint-limit.ts +63 -0
  306. package/src/runtime-grant.ts +4 -2
  307. package/src/runtime-tokens.ts +50 -9
  308. package/src/security.ts +13 -20
  309. package/src/server-background.ts +1 -1
  310. package/src/server.ts +5 -2
  311. package/src/services/host-utilization.ts +23 -0
  312. package/src/services/idle-epics.ts +5 -6
  313. package/src/services/issue-lifecycle.ts +57 -61
  314. package/src/services/issue-refs.ts +9 -13
  315. package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
  316. package/src/services/kernel-timers-ingress.ts +1 -1
  317. package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
  318. package/src/services/landed-ancestry.ts +19 -3
  319. package/src/services/memory-areas.ts +15 -51
  320. package/src/services/plan-ci-notice.ts +57 -0
  321. package/src/services/plan-ci-recovery.ts +2 -55
  322. package/src/services/plan-wake-digest.ts +1 -0
  323. package/src/services/profile-trust.ts +4 -3
  324. package/src/services/project-config-read.ts +70 -0
  325. package/src/services/project-profile-instructions.ts +54 -0
  326. package/src/services/provisioning-harness/budget-baseline.json +4 -4
  327. package/src/services/restart-spawn.ts +61 -49
  328. package/src/services/self-care-state.ts +2 -1
  329. package/src/services/self-effort.ts +5 -5
  330. package/src/services/send-message.ts +5 -1
  331. package/src/services/spawn-agent.ts +13 -2
  332. package/src/services/spawn-chain-inspector.ts +6 -13
  333. package/src/services/spawn-policy.ts +68 -0
  334. package/src/services/spawn-tree-cleanup.ts +2 -2
  335. package/src/services/task-dispatch.ts +3 -0
  336. package/src/services/task-state-reconcile.ts +6 -14
  337. package/src/services/team-templates.ts +9 -8
  338. package/src/services/transient-agent-reaper.ts +3 -1
  339. package/src/services/workflow-auto-start.ts +25 -13
  340. package/src/services/workflow-ci-main.ts +1 -1
  341. package/src/services/workflow-deferred-cleanup.ts +4 -2
  342. package/src/services/workflow-effect-driver.ts +2 -0
  343. package/src/services/workflow-effects.ts +18 -11
  344. package/src/services/workflow-land-notice.ts +10 -0
  345. package/src/services/workflow-pause-text.ts +43 -0
  346. package/src/services/workflow-reconcile.ts +13 -11
  347. package/src/services/workflow-run-view.ts +2 -0
  348. package/src/services/workflow-runs.ts +29 -13
  349. package/src/services/workflow-supervisor-state.ts +5 -0
  350. package/src/services/workflow-supervisor.ts +7 -3
  351. package/src/settings/registry.ts +1 -2
  352. package/src/spawn-command.ts +4 -4
  353. package/src/spawn-models.ts +10 -12
  354. package/src/spawn-placement.ts +1 -1
  355. package/src/spawn-targets.ts +1 -1
  356. package/src/startup-context-injection.ts +1 -0
  357. package/src/state-adoption/cd-cutover.ts +53 -7
  358. package/src/state-adoption/fleet-cutover.ts +35 -0
  359. package/src/state-adoption/fleet-plan.ts +36 -0
  360. package/src/state-adoption/index.ts +2 -2
  361. package/src/state-adoption/linux-plan.ts +2 -2
  362. package/src/state-adoption/linux.ts +2 -2
  363. package/src/state-adoption/macos-plan.ts +2 -2
  364. package/src/state-adoption/macos.ts +1 -1
  365. package/src/steward.ts +7 -6
  366. package/src/task-dispatch-live.ts +1 -1
  367. package/src/task-dispatcher.ts +1 -1
  368. package/src/teams-config-store.ts +4 -3
  369. package/src/token-db-write.ts +10 -0
  370. package/src/workspace-command-settle.ts +2 -1
  371. package/src/workspace-steward-wake.ts +2 -2
  372. package/node_modules/@humwick/kernel/LICENSE +0 -167
  373. package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
  374. package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
  375. package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
  376. package/node_modules/@humwick/kernel/config.ts +0 -111
  377. package/node_modules/@humwick/kernel/contract.ts +0 -572
  378. package/node_modules/@humwick/kernel/control-authz.ts +0 -281
  379. package/node_modules/@humwick/kernel/control.ts +0 -645
  380. package/node_modules/@humwick/kernel/effects.ts +0 -493
  381. package/node_modules/@humwick/kernel/event-log.ts +0 -319
  382. package/node_modules/@humwick/kernel/http-transport.ts +0 -384
  383. package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
  384. package/node_modules/@humwick/kernel/identity.ts +0 -248
  385. package/node_modules/@humwick/kernel/index.ts +0 -28
  386. package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
  387. package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
  388. package/node_modules/@humwick/kernel/landing.ts +0 -953
  389. package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
  390. package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
  391. package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
  392. package/node_modules/@humwick/kernel/message-authority.ts +0 -281
  393. package/node_modules/@humwick/kernel/module-host.ts +0 -722
  394. package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
  395. package/node_modules/@humwick/kernel/package.json +0 -47
  396. package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
  397. package/node_modules/@humwick/kernel/persistence.ts +0 -510
  398. package/node_modules/@humwick/kernel/registry.ts +0 -60
  399. package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
  400. package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
  401. package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
  402. package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
  403. package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
  404. package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
  405. package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
  406. package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
  407. package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
  408. package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
  409. package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
  410. package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
  411. package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
  412. package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
  413. package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
  414. package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
  415. package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
  416. package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
  417. package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
  418. package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
  419. package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
  420. package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
  421. package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
  422. package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
  423. package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
  424. package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
  425. package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
  426. package/node_modules/@humwick/offload/LICENSE +0 -167
  427. package/node_modules/@humwick/offload/README.md +0 -57
  428. package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
  429. package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
  430. package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
  431. package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
  432. package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
  433. package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
  434. package/node_modules/@humwick/offload/dist/envelope.js +0 -80
  435. package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
  436. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
  437. package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
  438. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
  439. package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
  440. package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
  441. package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
  442. package/node_modules/@humwick/offload/dist/index.js +0 -5
  443. package/node_modules/@humwick/offload/dist/index.js.map +0 -1
  444. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
  445. package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
  446. package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
  447. package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
  448. package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
  449. package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
  450. package/node_modules/@humwick/offload/dist/types.js +0 -176
  451. package/node_modules/@humwick/offload/dist/types.js.map +0 -1
  452. package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
  453. package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
  454. package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
  455. package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
  456. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
  457. package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
  458. package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
  459. package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
  460. package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
  461. package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
  462. package/node_modules/@humwick/offload/dist/worker.js +0 -1
  463. package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
  464. package/node_modules/@humwick/offload/package.json +0 -46
  465. package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
  466. package/node_modules/@humwick/offload/src/envelope.ts +0 -92
  467. package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
  468. package/node_modules/@humwick/offload/src/index.ts +0 -4
  469. package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
  470. package/node_modules/@humwick/offload/src/types.ts +0 -235
  471. package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
  472. package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
  473. package/node_modules/@humwick/offload/src/worker.ts +0 -5
  474. package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
  475. package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
  476. package/public/assets/fleet-BL4UXS_k.js +0 -2
  477. package/public/assets/index-B7ZerHLY.css +0 -2
  478. package/public/assets/index-BK0WV6hF.js +0 -15
  479. package/public/assets/projects-B_lmcqfO.js +0 -2
  480. package/public/assets/provider-display-DbLWpP3j.js +0 -2
  481. package/public/assets/run-card-CO_bguQf.js +0 -2
  482. package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
  483. package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
  484. package/runner/src/gate-run-lease-probe.ts +0 -38
  485. package/src/db/claude-catalog-reconcile.ts +0 -27
  486. package/src/routing-model-aliases.ts +0 -21
@@ -1,463 +0,0 @@
1
- import { beginRun, errorForExit, finishLog, recordResult, startLog, type RunContext } from "./envelope.js";
2
- import { OffloadError, StrikeCounter, normalizeError, validateTimeout, type OffloadDefaults, type OffloadEnvelope } from "./types.js";
3
-
4
- export interface WorkerPoolOptions extends OffloadDefaults {
5
- /** A module that default-exports `(input, { taskName }) => output`. Prefer a file URL. */
6
- worker: URL | string;
7
- size?: number;
8
- }
9
-
10
- export interface WorkerPoolStats {
11
- busy: number;
12
- idle: number;
13
- queued: number;
14
- }
15
-
16
- export interface WorkerPool {
17
- run<In, Out>(taskName: string, input: In, env?: OffloadEnvelope): Promise<Out>;
18
- readonly stats: WorkerPoolStats;
19
- readonly offThread: true;
20
- destroy(): Promise<void>;
21
- }
22
-
23
- type Job = {
24
- id: number;
25
- taskName: string;
26
- input: unknown;
27
- env?: OffloadEnvelope;
28
- /**
29
- * `retrySafe` snapshotted at submission. The envelope is the CALLER's mutable object, so reading
30
- * `env.retrySafe` at worker-death time lets a caller flip a default at-most-once job into a
31
- * retryable one (or vice versa) mid-flight, re-running its side effect (#1822 HIGH — TOCTOU).
32
- * Everything after submission reads THIS, never `env`.
33
- */
34
- retrySafe: boolean;
35
- /**
36
- * The effective timeout budget (ms) snapshotted and validated at submission, for the same reason
37
- * as `retrySafe`: recomputing it from the mutable envelope at each (re-)dispatch let a caller
38
- * erase or add a deadline after the fact (#1822 MED). `undefined` means no deadline. The absolute
39
- * `deadlineAt` is derived from this, never from `env`.
40
- */
41
- timeoutMs?: number;
42
- /** Set when the caller's signal aborted while this job was still queued; skipped by dispatch. */
43
- cancelled: boolean;
44
- /** How many times this job has been re-dispatched after a worker death (retrySafe only). */
45
- redispatches: number;
46
- /**
47
- * Absolute deadline (performance.now() ms) fixed at the FIRST execution start, so a retrySafe
48
- * re-dispatch continues the original deadline instead of restarting it (#1822 MED-2). Unset
49
- * until the first start, and only when the job has a timeout.
50
- */
51
- deadlineAt?: number;
52
- /** Drops the while-queued abort listener once the job leaves the queue. */
53
- releaseQueued(): void;
54
- resolve(value: unknown): void;
55
- reject(error: OffloadError): void;
56
- };
57
-
58
- type Active = Job & {
59
- context: ReturnType<typeof beginRun>;
60
- startedAt: number;
61
- removeAbort(): void;
62
- settled: boolean;
63
- };
64
-
65
- type Slot = { worker: Worker; active?: Active; generation: number; replacing: boolean };
66
-
67
- // For a RETRY-SAFE job (env.retrySafe), a worker death with the job in flight is absorbed by
68
- // re-dispatching to a fresh worker up to this many times. Reaching the limit means the job's OWN
69
- // execution repeatedly killed the worker (a real fault), so it is then charged and still
70
- // escalates. A non-retry-safe (default) job is never re-dispatched — it runs at most once
71
- // (#1822 HIGH-1). See onWorkerDeath.
72
- const MAX_JOB_REDISPATCHES = 2;
73
-
74
- /**
75
- * Fixed native Bun Worker pool. A deadline or abort replaces the whole worker because
76
- * CPU-bound synchronous code cannot observe a cancellation message while it is busy.
77
- */
78
- export function createWorkerPool(options: WorkerPoolOptions): WorkerPool {
79
- const size = options.size ?? Math.max(1, (navigator.hardwareConcurrency || 2) - 1);
80
- if (!Number.isSafeInteger(size) || size < 1) throw new RangeError("size must be a positive integer");
81
- const workerModule = options.worker instanceof URL ? options.worker.href : options.worker;
82
- const slots: Slot[] = [];
83
- const queued: Job[] = [];
84
- const counter = new StrikeCounter(options.escalationThreshold, options.escalationWindowAttempts);
85
- let nextId = 1;
86
- let destroyed = false;
87
- let destroyPromise: Promise<void> | undefined;
88
- let dispatching = false;
89
- let compactionScheduled = false;
90
- let cancelledQueued = 0;
91
-
92
- const createSlot = (): Slot => {
93
- const slot: Slot = { worker: undefined as unknown as Worker, generation: 0, replacing: false };
94
- spawnInto(slot);
95
- return slot;
96
- };
97
-
98
- // A worker that dies while idle (OOM kill, external SIGKILL, a crash between jobs) leaves a
99
- // dead handle in the slot. Respawn it so the next run() gets a live worker; nobody is charged
100
- // because no job was running (#1822 item 2). There is deliberately NO revival breaker: a tight
101
- // spawn-death loop would require the worker BOOTSTRAP itself to fail to load repeatedly, which
102
- // cannot happen through the public API (the bootstrap is this package's own module), so a
103
- // breaker for it is disproportionate surface (#1822 F3 — simplified). A job that races this
104
- // revival is protected by re-dispatch (onWorkerDeath), never by counting idle deaths.
105
- const reviveIdle = (slot: Slot): void => {
106
- if (destroyed || slot.replacing) return;
107
- void replace(slot);
108
- };
109
-
110
- const spawnInto = (slot: Slot): void => {
111
- if (destroyed) return;
112
- const generation = ++slot.generation;
113
- // `.js` is intentional: package consumers execute the compiled dist asset. Bun maps this
114
- // to the sibling TypeScript source while running the workspace directly in development.
115
- const worker = new Worker(new URL("./worker-runtime.js", import.meta.url), { type: "module" });
116
- slot.worker = worker;
117
- worker.onmessage = (event: MessageEvent<{ id: number; ok?: boolean; value?: unknown; error?: { message: string; code?: string } }>) => {
118
- if (slot.generation !== generation) return;
119
- const active = slot.active;
120
- if (!active || active.id !== event.data.id) return;
121
- if (event.data.ok) settle(slot, active, undefined, event.data.value);
122
- else settle(slot, active, new OffloadError({
123
- kind: "worker-error", taskName: active.taskName, code: event.data.error?.code, message: event.data.error?.message ?? "Worker task failed",
124
- }));
125
- };
126
- worker.onerror = (event: ErrorEvent) => {
127
- if (slot.generation !== generation) return;
128
- const active = slot.active;
129
- if (!active) { reviveIdle(slot); return; }
130
- // An uncaught error is by definition an abnormal termination attributable to the running job.
131
- onWorkerDeath(slot, active, new OffloadError({ kind: "worker-error", taskName: active.taskName, message: event.message || "Worker errored", cause: event.error }), true);
132
- };
133
- // Bun reports process.exit(), OOM, and hard crashes through `close` without an `error` event.
134
- // Reclaiming the slot here is essential when a caller omitted a timeout — and when the slot is
135
- // idle, so a later run() never inherits the dead worker (#1822 item 2). The close event carries
136
- // the exit `code`: 0 is a clean exit the worker CHOSE (not the job's fault); anything else is an
137
- // abnormal termination attributable to the in-flight job (#1822 MED-4). A missing code is
138
- // treated as abnormal — the safe default is to preserve escalation, not to drop it.
139
- worker.addEventListener("close", (event) => {
140
- if (slot.generation !== generation) return;
141
- const active = slot.active;
142
- if (!active) { reviveIdle(slot); return; }
143
- const code = (event as { code?: number }).code;
144
- const clean = code === 0;
145
- onWorkerDeath(slot, active, errorForExit(active.taskName, clean ? undefined : String(code)), !clean);
146
- });
147
- };
148
-
149
- const settle = (slot: Slot, active: Active, error?: OffloadError, value?: unknown): void => {
150
- if (active.settled) return;
151
- active.settled = true;
152
- active.context.cleanup();
153
- active.removeAbort();
154
- slot.active = undefined;
155
- const labels = active.env?.labels ?? {};
156
- const logger = active.env?.logger ?? options.logger;
157
- finishLog(logger, "worker", active.taskName, labels, active.startedAt, error);
158
- void recordResult({
159
- counter, taskName: active.taskName, backend: "worker", labels, error,
160
- sink: active.env?.onEscalate ?? options.onEscalate, logger,
161
- });
162
- if (error) active.reject(error); else active.resolve(value);
163
- dispatch();
164
- };
165
-
166
- // `error` is omitted only when reviving an idle slot: with no active job there is nothing to
167
- // settle and nobody to charge, so the slot is simply respawned (#1822 item 2).
168
- const replace = async (slot: Slot, error?: OffloadError): Promise<void> => {
169
- if (slot.replacing) return;
170
- slot.replacing = true;
171
- const active = slot.active;
172
- if (active && error) settle(slot, active, error);
173
- const old = slot.worker;
174
- slot.generation += 1;
175
- try { await old.terminate(); } catch { /* worker is already gone */ }
176
- if (!destroyed) {
177
- spawnInto(slot);
178
- slot.replacing = false;
179
- dispatch();
180
- }
181
- };
182
-
183
- /** Fails exactly one job without touching the slot it was about to occupy. */
184
- const failJob = (job: Job, error: OffloadError): void => {
185
- // Every terminal path must be visible in the structured stream, including the ones that
186
- // never reached startLog — otherwise the failure that used to wedge the pool is silent.
187
- finishLog(job.env?.logger ?? options.logger, "worker", job.taskName, job.env?.labels ?? {}, performance.now(), error);
188
- job.reject(error);
189
- void recordResult({
190
- counter, taskName: job.taskName, backend: "worker", labels: job.env?.labels ?? {}, error,
191
- sink: job.env?.onEscalate ?? options.onEscalate, logger: job.env?.logger ?? options.logger,
192
- });
193
- };
194
-
195
- // Attaches the while-queued abort wiring and enqueues a job. Shared by run() and redispatch()
196
- // so a re-dispatched job re-arms its abort handling exactly like a fresh one. `front` puts an
197
- // innocent, re-dispatched job ahead of newer work so its retry is prompt.
198
- const enqueue = (job: Job, front = false): void => {
199
- const labels = job.env?.labels ?? {};
200
- const logger = job.env?.logger ?? options.logger;
201
- const signal = job.env?.signal;
202
- if (signal?.aborted) {
203
- const error = new OffloadError({ kind: "aborted", taskName: job.taskName, message: `${job.taskName} was aborted`, cause: signal.reason });
204
- finishLog(logger, "worker", job.taskName, labels, performance.now(), error);
205
- job.reject(error);
206
- return;
207
- }
208
- if (signal) {
209
- // Without this, a job aborted while queued waits for a slot to free before it is
210
- // rejected — unbounded when the occupying worker has no deadline (#1809 P1-8).
211
- const onQueuedAbort = (): void => {
212
- if (job.cancelled) return;
213
- job.cancelled = true;
214
- cancelledQueued += 1;
215
- scheduleCompaction();
216
- const error = new OffloadError({ kind: "aborted", taskName: job.taskName, message: `${job.taskName} was aborted`, cause: signal.reason });
217
- // An abort that lands mid-run logs `offload failed kind=aborted`; one that lands
218
- // while queued must not be the single asymmetric case that logs nothing.
219
- finishLog(logger, "worker", job.taskName, labels, performance.now(), error);
220
- job.reject(error);
221
- };
222
- signal.addEventListener("abort", onQueuedAbort, { once: true });
223
- job.releaseQueued = () => signal.removeEventListener("abort", onQueuedAbort);
224
- }
225
- if (front) queued.unshift(job); else queued.push(job);
226
- dispatch();
227
- };
228
-
229
- // Fails a job WITHOUT charging a strike, for a death that is not attributable to the job's own
230
- // execution (an idle-death race — the job never ran). Still logged so the stream is complete.
231
- const failJobUncharged = (job: Job, error: OffloadError): void => {
232
- finishLog(job.env?.logger ?? options.logger, "worker", job.taskName, job.env?.labels ?? {}, performance.now(), error);
233
- job.reject(error);
234
- };
235
-
236
- // A worker died with `active` still in flight and unsettled. Two axes decide the outcome:
237
- // - RE-RUN? Only a retry-safe (idempotent) job may re-run, and only while it has retries left.
238
- // A default job runs AT MOST ONCE, so it is never re-dispatched (#1822 HIGH-1) — re-running
239
- // a side-effecting job would repeat its effect. A retry-safe job re-dispatches on ANY death
240
- // (clean or abnormal) while retries remain, since re-running it is safe by construction.
241
- // - CHARGE? Only when the death is ATTRIBUTABLE to the job's own execution, decided from the
242
- // worker's EXIT MANNER observed by the pool: an abnormal termination (non-zero exit, signal,
243
- // or uncaught error) with this job in flight is charged; a clean exit (code 0 — the worker
244
- // chose to stop) or a job that never reached a worker (postMessage threw) is an idle-race /
245
- // infra event, not a task fault, and is rejected WITHOUT a strike. Exit manner is used instead
246
- // of a worker-sent execution-start frame precisely because that frame can be LOST when a hard
247
- // crash races it, which would let a job that reliably crashes its worker escape escalation
248
- // forever (#1822 MED-4). `attributable` already covers retry-exhaustion: a retry-safe job that
249
- // crashes every worker exhausts its retries on an abnormal death, so that final death charges.
250
- const onWorkerDeath = (slot: Slot, active: Active, error: OffloadError, attributable: boolean): void => {
251
- const retrySafe = active.retrySafe;
252
- if (retrySafe && active.redispatches < MAX_JOB_REDISPATCHES) { redispatch(slot, active); return; }
253
- if (attributable) {
254
- // `replace` settles the still-attached active job with the error, charging it once.
255
- void replace(slot, error);
256
- return;
257
- }
258
- // Clean exit / never executed → do not charge. Detach, respawn a fresh worker, reject the caller.
259
- slot.active = undefined;
260
- active.removeAbort();
261
- active.context.cleanup();
262
- void replace(slot);
263
- failJobUncharged(active, error);
264
- };
265
-
266
- // Detaches a retry-safe job from a dead slot, respawns a fresh worker there, and re-queues the
267
- // SAME caller promise so an idempotent job that raced a worker death runs cleanly. The absolute
268
- // deadline is carried on the job, so the retry continues the original deadline (#1822 MED-2).
269
- const redispatch = (slot: Slot, active: Active): void => {
270
- slot.active = undefined;
271
- active.removeAbort();
272
- active.context.cleanup();
273
- const job: Job = {
274
- id: active.id, taskName: active.taskName, input: active.input, env: active.env,
275
- retrySafe: active.retrySafe, timeoutMs: active.timeoutMs,
276
- cancelled: false, redispatches: active.redispatches + 1, deadlineAt: active.deadlineAt,
277
- releaseQueued: () => {}, resolve: active.resolve, reject: active.reject,
278
- };
279
- // Respawn FIRST so the slot is marked `replacing` synchronously and dispatch cannot hand the
280
- // re-queued job straight back to the same corpse; replace()'s own dispatch then serves it.
281
- void replace(slot);
282
- enqueue(job, true);
283
- };
284
-
285
- const start = (slot: Slot, job: Job): void => {
286
- job.releaseQueued();
287
- let context: RunContext | undefined;
288
- let removeAbort: (() => void) | undefined;
289
- try {
290
- // Fix the deadline at the FIRST execution and carry it, so a retry-safe re-dispatch
291
- // continues the original deadline rather than restarting the full timeout (#1822 MED-2).
292
- // The budget comes from the SUBMISSION-TIME snapshot (`job.timeoutMs`), never from the
293
- // mutable envelope, so a caller cannot erase or add a deadline after submission (#1822 MED).
294
- const baseTimeoutMs = job.timeoutMs;
295
- let effectiveTimeoutMs = baseTimeoutMs;
296
- if (baseTimeoutMs !== undefined) {
297
- if (job.deadlineAt === undefined) job.deadlineAt = performance.now() + baseTimeoutMs;
298
- const remaining = job.deadlineAt - performance.now();
299
- if (remaining <= 0) {
300
- // The absolute deadline set on the first execution has already elapsed. A re-dispatch
301
- // must NOT be granted a fresh run past it (the old `Math.max(1, …)` handed out a 1ms
302
- // execution AFTER expiry — #1822 MED). A genuine timeout is attributable, so charge it.
303
- failJob(job, new OffloadError({ kind: "timeout", taskName: job.taskName, message: `${job.taskName} timed out after ${baseTimeoutMs}ms` }));
304
- return;
305
- }
306
- effectiveTimeoutMs = remaining;
307
- }
308
- // Pass the ALREADY-RESOLVED timeout as the authoritative override, so beginRun installs
309
- // exactly it and re-reads neither the envelope NOR the mutable pool default at dispatch —
310
- // a post-submission mutation of either cannot add or erase this job's deadline (#1822 MED).
311
- // `null` (not `undefined`) carries "no deadline" so beginRun does not mistake it for "no
312
- // argument" and fall back to the default. The live envelope is still passed for its signal.
313
- context = beginRun(job.taskName, job.env, options, undefined, effectiveTimeoutMs ?? null);
314
- if (context.signal.aborted) {
315
- const error = context.abortError();
316
- context.cleanup();
317
- failJob(job, error);
318
- return;
319
- }
320
- const run = context;
321
- const onAbort = () => { void replace(slot, run.abortError()); };
322
- run.signal.addEventListener("abort", onAbort, { once: true });
323
- removeAbort = () => run.signal.removeEventListener("abort", onAbort);
324
- const active: Active = {
325
- ...job, context: run, removeAbort, settled: false,
326
- startedAt: startLog(job.env?.logger ?? options.logger, "worker", job.taskName, job.env?.labels ?? {}),
327
- };
328
- slot.active = active;
329
- try {
330
- slot.worker.postMessage({ id: job.id, taskName: job.taskName, input: job.input, worker: workerModule });
331
- } catch (error) {
332
- // postMessage throws when the worker died between dispatch and here (an idle-death race):
333
- // the job never reached a worker, so it is NOT attributable — re-dispatch it (retrySafe)
334
- // or reject it uncharged rather than charge it for a death it did not cause (#1822 F2).
335
- onWorkerDeath(slot, active, normalizeError(job.taskName, error, "worker-error"), false);
336
- }
337
- } catch (error) {
338
- // Anything that throws while starting (an invalid deadline, a hostile logger) must fail
339
- // ONLY this job. Letting it escape leaves the slot idle with the queue stuck (#1809 P0-1),
340
- // and the caller must still see an OffloadError rather than the raw RangeError.
341
- removeAbort?.();
342
- context?.cleanup();
343
- if (slot.active?.id === job.id) slot.active = undefined;
344
- failJob(job, normalizeError(job.taskName, error, "rejected"));
345
- }
346
- };
347
-
348
- /**
349
- * Iterative on purpose: the previous version recursed through `start()` for every
350
- * pre-aborted job, so a mass abort over a deep queue blew the stack (#1809 P0-2).
351
- * The guard makes the nested `dispatch()` calls on the settle path no-ops — the loop
352
- * below re-reads slot and queue state on every turn, so no wakeup is lost.
353
- */
354
- const dispatch = (): void => {
355
- if (destroyed || dispatching) return;
356
- dispatching = true;
357
- try {
358
- while (!destroyed && queued.length) {
359
- const job = queued[0] as Job;
360
- if (job.cancelled) {
361
- queued.shift();
362
- cancelledQueued -= 1;
363
- continue;
364
- }
365
- const slot = slots.find((candidate) => !candidate.active && !candidate.replacing);
366
- if (!slot) break;
367
- queued.shift();
368
- start(slot, job);
369
- }
370
- } finally {
371
- dispatching = false;
372
- }
373
- };
374
-
375
- /**
376
- * A mass abort marks jobs in place — splicing each one out would be quadratic over a
377
- * deep queue — so the dead entries are swept once per batch instead.
378
- */
379
- const scheduleCompaction = (): void => {
380
- if (compactionScheduled) return;
381
- compactionScheduled = true;
382
- queueMicrotask(() => {
383
- compactionScheduled = false;
384
- if (cancelledQueued <= 0) return;
385
- const kept = queued.filter((job) => !job.cancelled);
386
- queued.length = 0;
387
- for (const job of kept) queued.push(job);
388
- cancelledQueued = 0;
389
- });
390
- };
391
-
392
- for (let index = 0; index < size; index += 1) slots.push(createSlot());
393
-
394
- return {
395
- offThread: true,
396
- get stats(): WorkerPoolStats {
397
- const busy = slots.filter((slot) => slot.active).length;
398
- return { busy, idle: slots.length - busy, queued: queued.length - cancelledQueued };
399
- },
400
- run<In, Out>(taskName: string, input: In, env?: OffloadEnvelope): Promise<Out> {
401
- const labels = env?.labels ?? {};
402
- const logger = env?.logger ?? options.logger;
403
- // Rejecting before the run ever starts is still a terminal outcome, so it gets the same
404
- // one line in the structured stream that every other settle path emits.
405
- const rejectBeforeStart = (error: OffloadError): Promise<never> => {
406
- finishLog(logger, "worker", taskName, labels, performance.now(), error);
407
- return Promise.reject(error);
408
- };
409
- if (destroyed) return rejectBeforeStart(new OffloadError({ kind: "worker-exit", taskName, message: "Worker pool has been destroyed" }));
410
- // Validated here rather than at dispatch so an invalid deadline fails the caller fast,
411
- // with the OffloadError every backend promises, even when a slot is free (#1809 P0-1). The
412
- // validated value is SNAPSHOTTED onto the job so the deadline it drives is fixed at
413
- // submission and immune to a later envelope mutation (#1822 MED).
414
- let timeoutMs: number | undefined;
415
- try {
416
- timeoutMs = validateTimeout(env?.timeoutMs ?? options.defaultTimeoutMs);
417
- } catch (error) {
418
- const normalized = normalizeError(taskName, error, "rejected");
419
- // Counted as a strike like the other two backends do for the same input: an invalid
420
- // deadline is a genuine caller failure, not a cancellation.
421
- void recordResult({ counter, taskName, backend: "worker", labels, error: normalized, sink: env?.onEscalate ?? options.onEscalate, logger });
422
- return rejectBeforeStart(normalized);
423
- }
424
- // `retrySafe` is snapshotted here too, for the same reason (#1822 HIGH): the pool must decide
425
- // re-dispatch from the caller's intent AT SUBMISSION, not from whatever `env` holds when a
426
- // worker later dies.
427
- const retrySafe = env?.retrySafe === true;
428
- return new Promise<Out>((resolve, reject) => {
429
- const job: Job = { id: nextId++, taskName, input, env, retrySafe, timeoutMs, cancelled: false, redispatches: 0, releaseQueued: () => {}, resolve, reject };
430
- enqueue(job);
431
- });
432
- },
433
- destroy(): Promise<void> {
434
- if (destroyPromise) return destroyPromise;
435
- destroyed = true;
436
- // The split below is INTENTIONAL — do not unify the two.
437
- // Cancelled-at-destroy is `aborted`, matching what the async and subprocess runners
438
- // already report for teardown: only `aborted` is strike-exempt, so anything else
439
- // charges a strike per in-flight job and a pool sitting at its threshold false-pages
440
- // on the orderly shutdown every adopter runs. A `run()` arriving AFTER destroy() is a
441
- // different event — caller misuse against a dead pool — and deliberately keeps its own
442
- // distinguishable `worker-exit` kind.
443
- const error = (taskName: string) => new OffloadError({ kind: "aborted", taskName, message: `${taskName} was cancelled: worker pool destroyed` });
444
- while (queued.length) {
445
- const job = queued.shift();
446
- if (!job) continue;
447
- job.releaseQueued();
448
- if (job.cancelled) continue;
449
- const cancellation = error(job.taskName);
450
- finishLog(job.env?.logger ?? options.logger, "worker", job.taskName, job.env?.labels ?? {}, performance.now(), cancellation);
451
- job.reject(cancellation);
452
- }
453
- cancelledQueued = 0;
454
- const workers = slots.map(async (slot) => {
455
- if (slot.active) settle(slot, slot.active, error(slot.active.taskName));
456
- slot.generation += 1;
457
- try { await slot.worker.terminate(); } catch { /* already stopped */ }
458
- });
459
- destroyPromise = Promise.all(workers).then(() => undefined);
460
- return destroyPromise;
461
- },
462
- };
463
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Bootstrap used by WorkerPool. Worker entry modules default-export a task function;
3
- * keeping the protocol here makes worker entrypoints tiny and free of pool machinery.
4
- */
5
- type WorkerTask = (input: unknown, context: { taskName: string }) => unknown | Promise<unknown>;
6
- type TaskMessage = { id: number; taskName: string; input: unknown; worker: string };
7
-
8
- function serialize(error: unknown): { name: string; message: string; code?: string; stack?: string } {
9
- const value = error as { name?: unknown; message?: unknown; code?: unknown; stack?: unknown };
10
- return {
11
- name: typeof value?.name === "string" ? value.name : "Error",
12
- message: typeof value?.message === "string" ? value.message : String(error),
13
- code: typeof value?.code === "string" ? value.code : undefined,
14
- stack: typeof value?.stack === "string" ? value.stack : undefined,
15
- };
16
- }
17
-
18
- self.onmessage = async (event: MessageEvent<TaskMessage>) => {
19
- const { id, taskName, input, worker } = event.data;
20
- try {
21
- const module = await import(worker) as { default?: WorkerTask };
22
- if (typeof module.default !== "function") throw new TypeError(`Worker module ${worker} must default-export a task function`);
23
- // No execution-start handshake is sent: the pool attributes a later worker death from the
24
- // worker's EXIT MANNER (a clean exit vs an abnormal/crash termination it observes on the exit
25
- // event), which cannot be lost the way an in-band frame can when a hard crash races it (#1822
26
- // MED-4). See onWorkerDeath in worker-pool.ts.
27
- const value = await module.default(input, { taskName });
28
- self.postMessage({ id, ok: true, value });
29
- } catch (error) {
30
- self.postMessage({ id, ok: false, error: serialize(error) });
31
- }
32
- };
@@ -1,5 +0,0 @@
1
- /** Types for modules consumed by `createWorkerPool`; default-export this function. */
2
- export type OffloadWorkerTask<In = unknown, Out = unknown> = (
3
- input: In,
4
- context: { taskName: string },
5
- ) => Out | Promise<Out>;
@@ -1,2 +0,0 @@
1
- import{T as e}from"./display-CfO7rTuF.js";function t(t,n){return!!n&&n.status!==`offline`&&!e(t,n)}export{t};
2
- //# sourceMappingURL=agent-liveness-DyqxfB-t.js.map
@@ -1,2 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{p as t,u as n}from"./dist-DeW2Y1R5.js";import{t as r}from"./store-BvtFdlGX.js";import{M as i,r as a,t as o}from"./provider-display-DbLWpP3j.js";import{a as s,i as c,n as l,o as u,r as d,s as f,t as p}from"./dialog-uuJ9_geR.js";import{t as m}from"./copy-DFxhHRtV.js";import{t as h}from"./download-KgtpDbt5.js";import{t as g}from"./eye-BAP6fHrX.js";import{n as _,t as v}from"./user-cog-CKcouW1J.js";import{t as y}from"./loader-circle-BfPd4kOD.js";import{t as b}from"./pencil-B1Hf2V_J.js";import{t as x}from"./plus-D5Ek4e2S.js";import{t as S}from"./trash-2-FbcSq927.js";import{t as C}from"./button-Do6Z3vvn.js";import{t as w}from"./badge-DqJRtj_p.js";var T=e(t(),1),E=n();function D(e){let t=o(),n=e.provider??``;return n&&n!==`any`&&t.includes(n)?n:t[0]??n}function O(e){if(Array.isArray(e))return e.map(O);if(e&&typeof e==`object`){let t={};for(let[n,r]of Object.entries(e))n===`files`&&Array.isArray(r)?t[n]=r.map(e=>{if(e&&typeof e==`object`&&typeof e.content==`string`){let t=e.content;return{...e,content:`<${t.length} chars elided>`}}return O(e)}):t[n]=O(r);return t}return e}function k({profile:e,open:t,onOpenChange:n}){let m=r(e=>e.apiCall),[g,_]=(0,T.useState)(()=>D(e)),[v,b]=(0,T.useState)(!1),[x,S]=(0,T.useState)(null),[w,k]=(0,T.useState)(null),A=(0,T.useCallback)(async t=>{b(!0),S(null);try{let n=await m(`GET`,`/agent-profiles/${encodeURIComponent(e.name)}/resolved?provider=${t}`);k(n.profile)}catch(e){k(null),S(i(e))}finally{b(!1)}},[m,e.name]);(0,T.useEffect)(()=>{if(t){let t=D(e);_(t),A(t)}},[t,e,A]);function j(e){e!==g&&(_(e),A(e))}function M(){if(!w)return;let t=new Blob([JSON.stringify(w,null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`${e.name}.${g}.resolved.json`,document.body.appendChild(r),r.click(),r.remove(),URL.revokeObjectURL(n)}let N=w?JSON.stringify(O(w),null,2):``;return(0,E.jsx)(p,{open:t,onOpenChange:n,children:(0,E.jsxs)(d,{className:`max-w-3xl`,children:[(0,E.jsxs)(u,{children:[(0,E.jsxs)(f,{className:`font-mono text-sm`,children:[e.name,` — resolved projection`]}),(0,E.jsxs)(c,{children:[`The fully-resolved agent-profile projection (`,(0,E.jsx)(`code`,{children:`withResolvedProvisioning`}),`) for the selected provider. File contents are elided below; download the full JSON for the complete bundle.`]})]}),(0,E.jsxs)(l,{className:`space-y-3`,children:[(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,E.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`Provider`}),(0,E.jsx)(`div`,{className:`flex items-center gap-1`,children:o().map(e=>(0,E.jsx)(C,{variant:e===g?`default`:`outline`,size:`sm`,className:`h-7 px-3 text-xs`,disabled:v,onClick:()=>j(e),children:a(e)},e))}),(0,E.jsx)(`div`,{className:`flex-1`}),(0,E.jsxs)(C,{size:`sm`,className:`h-7 gap-1 text-xs`,disabled:v||!w,onClick:M,children:[(0,E.jsx)(h,{className:`h-3.5 w-3.5`}),`Download full JSON`]})]}),(0,E.jsx)(`div`,{className:`min-h-[16rem] rounded-md border border-border bg-muted/30 p-3`,children:v?(0,E.jsxs)(`div`,{className:`flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,E.jsx)(y,{className:`h-3.5 w-3.5 animate-spin`}),`Resolving projection…`]}):x?(0,E.jsx)(`div`,{className:`text-xs text-destructive`,children:x}):w?(0,E.jsx)(`pre`,{className:`whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed`,children:N}):(0,E.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:`No projection available.`})})]}),(0,E.jsx)(s,{children:(0,E.jsx)(C,{variant:`outline`,size:`sm`,onClick:()=>n(!1),children:`Close`})})]})})}function A({relay:e}){return(0,E.jsx)(`div`,{className:`flex items-center gap-1`,children:[{key:`ctx`,on:e.context},{key:`skl`,on:e.skills},{key:`plg`,on:e.plugins},{key:`stl`,on:e.statusLine}].map(e=>(0,E.jsx)(`span`,{className:`inline-block h-1.5 w-1.5 rounded-full ${e.on?`bg-tone-success`:`bg-muted-foreground/30`}`,title:`${e.key}: ${e.on?`on`:`off`}`},e.key))})}function j({profile:e}){let t=r(e=>e.openProfileModal),n=r(e=>e.deleteProfile),i=e.builtIn===!0,[a,o]=(0,T.useState)(!1);return(0,E.jsxs)(`div`,{className:`group flex flex-col gap-3 rounded-lg border border-border bg-card p-4`,children:[(0,E.jsxs)(`div`,{className:`flex flex-wrap items-start gap-x-2 gap-y-1`,children:[(0,E.jsxs)(`div`,{className:`min-w-[10rem] flex-1`,children:[(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-2 gap-y-1`,children:[(0,E.jsx)(`span`,{className:`text-base leading-none`,"aria-hidden":!0,children:e.icon?.trim()||`•`}),(0,E.jsx)(`span`,{className:`min-w-0 font-mono text-sm font-medium [overflow-wrap:anywhere]`,children:e.name}),i&&(0,E.jsx)(w,{variant:`secondary`,className:`text-[10px]`,children:`Built-in`}),e.overridden&&(0,E.jsx)(w,{variant:`outline`,className:`text-[10px] border-tone-warning/30 bg-tone-warning/10 text-tone-warning-fg`,children:`Overridden`})]}),e.description&&(0,E.jsx)(`p`,{className:`mt-0.5 text-xs text-muted-foreground line-clamp-2`,children:e.description})]}),(0,E.jsxs)(`div`,{className:`ml-auto flex shrink-0 items-center gap-0.5 opacity-100 transition-opacity [@media(hover:hover)]:sm:opacity-0 [@media(hover:hover)]:sm:group-hover:opacity-100 [@media(hover:hover)]:sm:group-focus-within:opacity-100`,children:[(0,E.jsx)(C,{variant:`ghost`,size:`icon-sm`,className:`h-7 w-7`,title:`View`,onClick:()=>t(`view`,e),children:(0,E.jsx)(g,{className:`h-3.5 w-3.5`})}),(0,E.jsx)(C,{variant:`ghost`,size:`icon-sm`,className:`h-7 w-7`,title:`Edit`,onClick:()=>t(`edit`,e),children:(0,E.jsx)(b,{className:`h-3.5 w-3.5`})}),(0,E.jsx)(C,{variant:`ghost`,size:`icon-sm`,className:`h-7 w-7`,title:`Duplicate`,onClick:()=>t(`duplicate`,e),children:(0,E.jsx)(m,{className:`h-3.5 w-3.5`})}),(0,E.jsx)(C,{variant:`ghost`,size:`icon-sm`,className:`h-7 w-7`,title:`Resolved projection`,onClick:()=>o(!0),children:(0,E.jsx)(_,{className:`h-3.5 w-3.5`})}),(!i||e.overridden)&&(0,E.jsx)(C,{variant:`ghost`,size:`icon-sm`,className:`h-7 w-7 text-destructive`,title:i?`Reset to default`:`Delete`,onClick:()=>n(e),children:(0,E.jsx)(S,{className:`h-3.5 w-3.5`})})]})]}),(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5 text-[10px]`,children:[(0,E.jsx)(w,{variant:`outline`,children:e.provider||`any`}),(0,E.jsxs)(w,{variant:`outline`,children:[`fs: `,e.permissions.filesystem]}),e.permissions.mode&&(0,E.jsx)(w,{variant:`outline`,children:e.permissions.mode})]}),(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-1 text-[10px] text-muted-foreground`,children:[(0,E.jsxs)(`span`,{className:`flex items-center gap-1`,children:[`Relay `,(0,E.jsx)(A,{relay:e.relay})]}),e.instructions.globalInstructions===`ignore`&&(0,E.jsx)(`span`,{className:`text-tone-warning-fg`,children:`global: ignore`}),Object.keys(e.env||{}).length>0&&(0,E.jsxs)(`span`,{children:[Object.keys(e.env).length,` env vars`]})]}),(0,E.jsx)(k,{profile:e,open:a,onOpenChange:o})]})}function M(){let e=r(e=>e.agentProfiles),t=r(e=>e.openProfileModal),n=e.filter(e=>e.builtIn),i=e.filter(e=>!e.builtIn);return(0,E.jsxs)(`div`,{className:`space-y-4`,children:[(0,E.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,E.jsxs)(`div`,{className:`flex items-center gap-2 text-lg font-semibold`,children:[(0,E.jsx)(v,{className:`h-5 w-5 text-primary`}),`Agent Profiles`]}),(0,E.jsx)(w,{variant:`outline`,children:e.length}),(0,E.jsx)(`div`,{className:`flex-1`}),(0,E.jsxs)(C,{size:`sm`,className:`gap-1`,onClick:()=>t(`create`),children:[(0,E.jsx)(x,{className:`h-3.5 w-3.5`}),`Create Profile`]})]}),n.length>0&&(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`h3`,{className:`mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wider`,children:`Built-in`}),(0,E.jsx)(`div`,{className:`grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3`,children:n.map(e=>(0,E.jsx)(j,{profile:e},e.name))})]}),i.length>0&&(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`h3`,{className:`mb-2 text-xs font-medium text-muted-foreground uppercase tracking-wider`,children:`Custom`}),(0,E.jsx)(`div`,{className:`grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3`,children:i.map(e=>(0,E.jsx)(j,{profile:e},e.name))})]}),e.length===0&&(0,E.jsx)(`div`,{className:`py-12 text-center text-sm text-muted-foreground`,children:`No agent profiles found. Create one to configure agent behavior.`})]})}export{M as AgentProfilesView};
2
- //# sourceMappingURL=agent-profiles-BpI_jTxq.js.map
@@ -1,2 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{o as t,p as n,u as r}from"./dist-DeW2Y1R5.js";import{Ct as i,E as a,t as o}from"./store-BvtFdlGX.js";import"./provider-display-DbLWpP3j.js";import{h as s}from"./display-CfO7rTuF.js";import{t as c}from"./host-mTgRw7xh.js";import{t as l}from"./chevron-right-iljytE0x.js";import{t as u}from"./cpu-Dndy84IU.js";import{t as d}from"./git-merge-C7eIG425.js";import{t as f}from"./globe-Cl5fXtqs.js";import{t as p}from"./layers-DEfClY-v.js";import{t as m}from"./loader-circle-BfPd4kOD.js";import{t as h}from"./pencil-B1Hf2V_J.js";import{t as ee}from"./rocket-BmO1qSu-.js";import{t as te}from"./triangle-alert-BBNhfgMi.js";import{t as ne}from"./users-C7B3u9jv.js";import{t as g}from"./button-Do6Z3vvn.js";import{t as _}from"./badge-DqJRtj_p.js";import{t as v}from"./input-CsTB6jIx.js";import{a as re,c as y,i as ie,l as b,n as ae,o as x,r as oe,s as S,t as C,u as w}from"./fleet-metrics-BkHP-P3R.js";import{i as T,o as E,r as D,s as O,t as k}from"./card-C4QJ4hCW.js";var A=e(n(),1),j=r(),M={ok:`text-tone-success-fg`,warn:`text-tone-warning-fg`,crit:`text-tone-danger-fg`,idle:`text-tone-neutral-fg`},N={ok:`stroke-tone-success`,warn:`stroke-tone-warning`,crit:`stroke-tone-danger`,idle:`stroke-tone-neutral`},P={ok:`bg-tone-success`,warn:`bg-tone-warning`,crit:`bg-tone-danger`,idle:`bg-tone-neutral`},F=20,I=2*Math.PI*F;function L({label:e,pct:n,tone:r,center:i,sub:a,title:o}){let s=n===void 0?0:C(n),c=I*(1-s/100);return(0,j.jsxs)(`div`,{className:`flex flex-col items-center gap-1 min-w-0`,title:o,children:[(0,j.jsxs)(`div`,{className:`relative h-[60px] w-[60px]`,children:[(0,j.jsxs)(`svg`,{viewBox:`0 0 48 48`,role:`img`,"aria-label":`${e} ${i}`,className:`h-full w-full -rotate-90`,children:[(0,j.jsx)(`circle`,{cx:`24`,cy:`24`,r:F,fill:`none`,strokeWidth:`4.5`,className:`stroke-foreground/10`}),n===void 0?null:(0,j.jsx)(`circle`,{cx:`24`,cy:`24`,r:F,fill:`none`,strokeWidth:`4.5`,strokeLinecap:`round`,"data-testid":`ring-${e.toLowerCase()}`,"data-pct":Math.round(s),className:t(N[r],`motion-safe:animate-fleet-ring-in motion-safe:transition-[stroke-dashoffset] motion-safe:duration-700`),style:{strokeDasharray:I,strokeDashoffset:c,"--ring-c":I}})]}),(0,j.jsx)(`span`,{className:t(`absolute inset-0 flex items-center justify-center text-[13px] font-semibold tabular-nums`,M[r]),children:i})]}),(0,j.jsx)(`div`,{className:`text-[10px] uppercase tracking-wider text-muted-foreground leading-none`,children:e}),a?(0,j.jsx)(`div`,{className:`text-[10px] text-muted-foreground/80 leading-none truncate max-w-full tabular-nums`,children:a}):null]})}function se({tone:e,live:n,title:r}){return(0,j.jsxs)(`span`,{className:`relative flex h-3 w-3 items-center justify-center shrink-0`,title:r,role:`img`,"aria-label":r,children:[n?(0,j.jsx)(`span`,{className:t(`absolute inline-flex h-full w-full rounded-full opacity-50 motion-safe:animate-fleet-ping`,P[e])}):null,(0,j.jsx)(`span`,{className:t(`relative inline-flex h-2.5 w-2.5 rounded-full ring-2 ring-card`,P[e])})]})}var R={idle:1,normal:1,busy:2,saturated:3,blocked:4};function ce({band:e,tone:n,title:r}){let i=R[e]??0;return(0,j.jsx)(`span`,{className:`inline-flex items-end gap-[3px] h-3.5`,title:r,role:`img`,"aria-label":`pressure ${e}`,children:[1,2,3,4].map(e=>(0,j.jsx)(`span`,{className:t(`w-[3px] rounded-sm transition-colors`,e<=i?P[n]:`bg-foreground/15`),style:{height:`${25+e*18}%`}},e))})}function le({cells:e,active:n,queued:r}){let i=t=>t<e.own?`bg-tone-sky`:t<e.own+e.other?`bg-tone-warning`:t<e.own+e.other+e.unattributed?`bg-tone-success`:``;return(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-[3px]`,"data-testid":`gate-cells`,children:[Array.from({length:e.total},(e,r)=>{let a=i(r);return(0,j.jsx)(`span`,{className:t(`h-3 w-3 rounded-[3px]`,a?[a,n&&`motion-safe:animate-fleet-breathe`]:`bg-foreground/10`),style:a&&n?{animationDelay:`${r%6*160}ms`}:void 0},r)}),r>0?(0,j.jsx)(`span`,{className:`ml-1.5 flex items-center gap-[3px]`,title:`${r} queued ${r===1?`gate`:`gates`}`,children:Array.from({length:Math.min(r,6)},(e,t)=>(0,j.jsx)(`span`,{className:`h-3 w-3 rounded-[3px] border border-dashed border-tone-warning/80 motion-safe:animate-fleet-breathe`},t))}):null]})}function z({dots:e,tone:n,active:r,queued:i=0}){return(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-[3px]`,children:[Array.from({length:e.filled},(e,i)=>(0,j.jsx)(`span`,{className:t(`h-2 w-2 rounded-full`,P[n],r&&`motion-safe:animate-fleet-breathe`),style:r?{animationDelay:`${i%6*200}ms`}:void 0},`f${i}`)),Array.from({length:e.empty},(e,t)=>(0,j.jsx)(`span`,{className:`h-2 w-2 rounded-full bg-foreground/10`},`e${t}`)),Array.from({length:e.over},(e,t)=>(0,j.jsx)(`span`,{className:`h-2 w-2 rounded-full bg-tone-danger ring-1 ring-tone-danger/40`},`o${t}`)),Array.from({length:Math.min(i,6)},(e,t)=>(0,j.jsx)(`span`,{className:`h-2 w-2 rounded-full border border-dashed border-tone-warning/80 motion-safe:animate-fleet-breathe`},`q${t}`))]})}function B({icon:e,label:t,right:n,children:r,title:i}){return(0,j.jsxs)(`div`,{className:`space-y-1.5`,title:i,children:[(0,j.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-muted-foreground`,children:[e,(0,j.jsx)(`span`,{children:t}),(0,j.jsx)(`span`,{className:`ml-auto normal-case tracking-normal tabular-nums text-foreground/80 text-[11px]`,children:n})]}),r]})}function ue({label:e,icon:n,checked:r,saving:i,disabled:a,title:o,onChange:s}){return(0,j.jsxs)(`label`,{title:o,"data-state":r?`on`:`off`,"data-saving":i||void 0,className:t(`group/toggle flex select-none items-center gap-1.5 rounded-full border py-0.5 pl-1.5 pr-1 text-[11px] font-medium transition-colors`,`focus-within:ring-2 focus-within:ring-ring/50`,r?`border-tone-success/30 bg-tone-success/10 text-tone-success-fg`:`border-foreground/10 bg-foreground/[0.03] text-muted-foreground`,a?`cursor-wait`:`cursor-pointer hover:border-foreground/25`,i&&`motion-safe:animate-fleet-breathe`),children:[(0,j.jsx)(`input`,{type:`checkbox`,role:`switch`,className:`peer sr-only`,checked:r,disabled:a,onChange:s}),(0,j.jsx)(`span`,{"aria-hidden":!0,className:`flex items-center`,children:i?(0,j.jsx)(m,{className:`h-3 w-3 motion-safe:animate-spin`}):n}),(0,j.jsx)(`span`,{children:e}),(0,j.jsx)(`span`,{"aria-hidden":!0,className:t(`relative h-3.5 w-6 rounded-full transition-colors`,r?`bg-tone-success`:`bg-foreground/20`),children:(0,j.jsx)(`span`,{className:t(`absolute top-0.5 h-2.5 w-2.5 rounded-full bg-white shadow-sm transition-all`,r?`left-[calc(100%-0.75rem)]`:`left-0.5`)})})]})}var V={"systemd-user-scope":`Linux cgroup (systemd scope)`,"delegated-cgroup":`Linux cgroup (delegated)`,taskpolicy:`macOS background QoS`,nice:`nice priority`,"admission-only":`Admission only`},H={land:`Land`,iterate:`Iterate`,validation:`Validation`};function U(e){let t=e.cpuQuotaAvailable?`soft CPU shares${e.cpuLimit===void 0?``:` · ceiling ${W(e.cpuLimit)} CPUs`}`:`no CPU control${e.priority?` · priority ${e.priority}`:``}`;return{label:V[e.mechanism],detail:t,degraded:e.mechanism===`nice`||e.mechanism===`admission-only`,reason:e.reason}}function W(e){return String(Math.round(e*10)/10)}function G(e){let t=e/1024**3;return t>=1?`${Math.round(t*10)/10} GB`:`${Math.round(e/1024**2)} MB`}function K(e){return e?e.replace(/\/+$/,``).split(`/`).at(-1)||e:`unknown repository`}function q(e,t){let n=e.resource_control,r=n?.sampledAt??e.sampled_at;if(e.state===`unavailable`||!r||t-r>6e4)return{state:`unknown`};if(!n)return{state:`off`};let i=U(n),a=[`agent`,`land`].flatMap(e=>n.paths?.[e]?[{name:e,view:U(n.paths[e])}]:[]),o=(n.work??[]).map(e=>({id:e.id,repository:K(e.repository),repositoryPath:e.repository,kind:e.kind,state:e.state})),s=[...i.degraded?[`${i.label}: ${i.reason??`CPU quota unavailable`}`]:[],...a.filter(e=>e.view.degraded).map(e=>`${e.name===`agent`?`Agent`:`Land`} path, ${e.view.label}: ${e.view.reason??`CPU quota unavailable`}`)];return{state:`on`,mechanism:i,paths:a,usableCpus:W(n.usableCpus),gateCpus:W(n.gateCpus),memory:G(n.memoryBytes),slots:n.slots,held:n.held,waiters:n.waiters,iterateOverflow:n.iterateOverflow,kinds:n.kinds?c.map(e=>({kind:e,label:H[e],...n.kinds[e],cpus:W(n.kinds[e].cpus)})):void 0,work:o,hiddenWork:Math.max(0,n.held+n.waiters-o.length),degradations:s}}var J={landSlots:`Land slots`,validationSlots:`Validation slots`,runCpus:`CPUs per run`,runMemory:`Memory per run (GiB)`};function Y({host:e,field:t}){let n=o(e=>e.setHostGateBudget),[r,i]=(0,A.useState)(null),[a,s]=(0,A.useState)(!1),c=e.policy?.[t]??(t===`landSlots`?e.policy?.gateBudget??e.gate_budget:t===`validationSlots`?e.policy?.validationGateBudget:void 0)??null,l=t===`runMemory`?1024**3:1,u=r??(c===null?``:String(c/l)),d=u.trim()===``?null:Number(u)*l,f=t===`landSlots`||t===`validationSlots`,p=d===null||Number.isFinite(d)&&d>0&&(t===`runCpus`?d>=.01&&d<=1e3:Number.isSafeInteger(d)&&(!f||d<=1e3)),m=r!==null&&d!==c,h=async r=>{let a={[t]:r};t===`landSlots`&&(a.gateBudget=null),t===`validationSlots`&&(a.validationGateBudget=null),t===`runCpus`&&(a.landGateCpus=null,a.validationGateCpus=null),s(!0);try{await n(e.id,a)&&i(null)}finally{s(!1)}};return(0,j.jsxs)(`form`,{className:`space-y-1`,onSubmit:e=>{e.preventDefault(),p&&m&&h(d)},children:[(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,j.jsx)(`label`,{htmlFor:`${t}-${e.id}`,className:`text-[11px] text-muted-foreground`,children:J[t]}),(0,j.jsx)(v,{id:`${t}-${e.id}`,inputMode:`decimal`,className:`h-7 w-20 text-center tabular-nums`,value:u,placeholder:`auto`,disabled:a,"aria-invalid":!p,onChange:e=>i(e.target.value)}),(0,j.jsx)(g,{type:`submit`,size:`sm`,variant:`outline`,className:`h-7 text-xs`,"aria-label":`Apply ${J[t]}`,disabled:!p||!m||a,children:a?`Saving…`:`Apply`}),c===null?null:(0,j.jsx)(g,{type:`button`,size:`sm`,variant:`ghost`,className:`h-7 text-xs`,disabled:a,"aria-label":`Use automatic ${J[t]}`,onClick:()=>void h(null),children:`Use automatic`})]}),p?null:(0,j.jsx)(`p`,{className:`text-[10px] text-tone-danger-fg`,children:f?`Whole number 1–1000, or empty.`:t===`runCpus`?`0.01–1000 CPUs, or empty.`:`Positive memory in GiB, or empty.`})]})}function X({host:e}){return(0,j.jsxs)(`div`,{className:`space-y-2`,"aria-label":`Gate pool settings`,children:[Object.keys(J).map(t=>(0,j.jsx)(Y,{host:e,field:t},t)),(0,j.jsx)(`p`,{className:`text-[10px] text-muted-foreground`,children:`Empty uses fleet or hardware defaults. Land and validation slots add up to one shared pool. CPUs per run is a soft share; memory per run is a hard limit.`})]})}function de({host:e}){let n=q(e,Date.now()),r=n.state===`on`?`${n.held} held · ${n.waiters} queued`:n.state===`off`?`off`:`no data`;return(0,j.jsx)(B,{icon:(0,j.jsx)(u,{className:`w-3 h-3`}),label:`Resource control`,right:r,title:`Built-in host resource control: how this host limits gate CPU, what it has admitted, and the gate budget`,children:(0,j.jsxs)(`div`,{className:`space-y-2 text-[11px]`,"data-testid":`resource-control`,children:[n.state===`unknown`?(0,j.jsx)(`p`,{className:`text-muted-foreground`,children:`Unknown: no fresh sample from this host's orchestrator.`}):n.state===`off`?(0,j.jsxs)(`p`,{className:`text-muted-foreground`,"data-testid":`resource-control-off`,children:[`Off on this host. Set `,(0,j.jsx)(`code`,{className:`break-all`,children:`AGENT_RELAY_HOST_RESOURCE_CONTROL=1`}),` on its orchestrator to enable shared admission and CPU limits; until then gates use per-repository leases.`]}):(0,j.jsxs)(j.Fragment,{children:[(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,j.jsx)(_,{variant:`secondary`,className:`text-[10px]`,"data-testid":`resource-mechanism`,children:n.mechanism.label}),(0,j.jsx)(`span`,{className:`text-muted-foreground`,children:n.mechanism.detail})]}),(0,j.jsxs)(`dl`,{className:`grid grid-cols-3 gap-2 tabular-nums`,children:[(0,j.jsxs)(`div`,{children:[(0,j.jsx)(`dt`,{className:`text-[10px] uppercase tracking-wider text-muted-foreground`,children:`CPUs`}),(0,j.jsxs)(`dd`,{children:[n.gateCpus,` of `,n.usableCpus]})]}),(0,j.jsxs)(`div`,{children:[(0,j.jsx)(`dt`,{className:`text-[10px] uppercase tracking-wider text-muted-foreground`,children:`Memory`}),(0,j.jsx)(`dd`,{children:n.memory})]}),(0,j.jsxs)(`div`,{children:[(0,j.jsx)(`dt`,{className:`text-[10px] uppercase tracking-wider text-muted-foreground`,children:`Shared pool`}),(0,j.jsxs)(`dd`,{children:[n.held,` / `,n.slots,n.iterateOverflow?` +${n.iterateOverflow} iterate`:``]})]})]}),n.kinds?(0,j.jsxs)(`div`,{className:`space-y-1`,children:[(0,j.jsxs)(`p`,{className:`text-muted-foreground`,children:[`One pool for all gates. A free slot goes to lands first, then iterate, then validation.`,n.iterateOverflow?` Iterate may use ${n.iterateOverflow} extra slot when the pool is full.`:``]}),(0,j.jsx)(`ul`,{"aria-label":`Gate kinds`,className:`space-y-0.5 tabular-nums`,children:n.kinds.map(e=>(0,j.jsxs)(`li`,{children:[e.label,`: `,e.held,` held · `,e.waiters,` queued · `,e.cpus,` CPUs per run (soft)`]},e.kind))})]}):(0,j.jsx)(`p`,{className:`text-muted-foreground`,children:`Pool detail not reported by this orchestrator.`}),n.degradations.map(e=>(0,j.jsxs)(`div`,{"data-testid":`resource-degraded`,className:`flex items-start gap-1.5 rounded-md bg-tone-warning/10 px-2 py-1.5 leading-snug text-tone-warning-fg`,children:[(0,j.jsx)(te,{className:`w-3 h-3 mt-px shrink-0`}),(0,j.jsxs)(`span`,{className:`min-w-0 break-words`,children:[`Degraded. `,e]})]},e)),n.paths.length>1||n.paths.some(e=>e.view.label!==n.mechanism.label)?(0,j.jsx)(`ul`,{className:`space-y-0.5 text-muted-foreground`,children:n.paths.map(e=>(0,j.jsxs)(`li`,{children:[e.name===`agent`?`Agents`:`Lands`,`: `,e.view.label,` · `,e.view.detail]},e.name))}):null,n.work.length>0?(0,j.jsxs)(`ul`,{className:`space-y-1`,"aria-label":`Held and queued gates`,children:[n.work.map(e=>(0,j.jsxs)(`li`,{"data-testid":`resource-work`,"data-state":e.state,className:`flex min-w-0 items-center gap-1.5`,children:[(0,j.jsx)(`span`,{className:t(`shrink-0 rounded-full border px-1.5 text-[10px] font-medium`,e.state===`held`?`border-tone-success/30 bg-tone-success/10 text-tone-success-fg`:`border-dashed border-tone-warning/80 text-tone-warning-fg`),children:e.state}),(0,j.jsx)(`span`,{className:`shrink-0 text-muted-foreground`,children:e.kind}),(0,j.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,title:e.repositoryPath??e.id,children:e.repository})]},e.id)),n.hiddenWork>0?(0,j.jsxs)(`li`,{className:`text-muted-foreground`,children:[`+`,n.hiddenWork,` more not listed`]}):null]}):n.held+n.waiters>0?(0,j.jsxs)(`p`,{className:`text-muted-foreground`,children:[n.held+n.waiters,` gates in flight; detail not reported by this orchestrator.`]}):(0,j.jsx)(`p`,{className:`text-muted-foreground`,children:`No gates held or queued.`})]}),e.resource_control?.gateLimits?.enabled?(0,j.jsxs)(`p`,{className:`text-muted-foreground`,children:[`Gate cap: `,e.resource_control.gateLimits.gateRunCapMs/6e4,` min · Slot hold cap: `,e.resource_control.gateLimits.slotHoldCapMs/6e4,` min`]}):null,Object.keys(e.gate_reservations??{}).length>0?(0,j.jsx)(`ul`,{"aria-label":`Project reserved gate slots`,className:`space-y-0.5 text-muted-foreground`,children:Object.entries(e.gate_reservations).map(([e,t])=>(0,j.jsxs)(`li`,{children:[e,`: `,t,` reserved gate slot`,t===1?``:`s`]},e))}):null,e.gate_reservation_warning?(0,j.jsx)(`p`,{role:`alert`,className:`text-tone-warning-fg`,children:e.gate_reservation_warning}):null,(0,j.jsx)(X,{host:e})]})})}function fe({session:e,now:t}){let n=o(t=>t.agentsById[e.agentId]),r=o(t=>t.orchestrators.find(t=>t.id===e.orchestratorId)?.hostname),i=o(e=>e.openAgentDetail),a=n?.label||n?.name||e.agentId;return(0,j.jsxs)(`li`,{className:`flex flex-wrap items-center gap-x-4 gap-y-1 py-2 text-sm`,"data-testid":`browser-fleet-row`,"data-session-id":e.id,children:[n?(0,j.jsx)(`button`,{type:`button`,className:`min-w-0 max-w-full truncate font-medium hover:underline`,onClick:()=>i(n),children:a}):(0,j.jsx)(`span`,{className:`min-w-0 max-w-full truncate font-medium`,children:a}),(0,j.jsx)(`span`,{className:`text-muted-foreground`,title:e.orchestratorId,children:r??e.orchestratorId}),(0,j.jsx)(_,{variant:`outline`,className:`text-[11px]`,children:e.status}),(0,j.jsxs)(`span`,{className:`tabular-nums text-muted-foreground`,title:new Date(e.createdAt).toLocaleString(),children:[`open `,s(t,e.createdAt)]}),(0,j.jsxs)(`span`,{className:`tabular-nums text-muted-foreground`,title:`Time since the agent last used this browser, as of the host's last report`,children:[`idle `,e.status===`running`&&e.lastActivityAt?s(t,e.lastActivityAt):`—`]}),(0,j.jsx)(`span`,{className:`ml-auto`,children:(0,j.jsx)(w,{session:e,label:`Stop the browser of ${a}`})})]})}function pe(){window.location.hash=`settings/agents`,o.getState().switchView(`settings`)}function Z(){let e=o(e=>e.browser),t=i();if(!e?.enabled)return null;let n=Object.values(e.sessions).filter(a).sort((e,t)=>t.createdAt-e.createdAt),r=e.limits;return(0,j.jsxs)(k,{size:`sm`,"data-testid":`browser-fleet`,children:[(0,j.jsxs)(E,{children:[(0,j.jsxs)(O,{className:`flex items-center gap-2 text-sm`,children:[(0,j.jsx)(f,{className:`size-4`}),`Browser sessions`]}),(0,j.jsxs)(T,{className:`flex flex-wrap items-center gap-x-2 text-xs`,children:[r?(0,j.jsxs)(`span`,{"data-testid":`browser-fleet-limits`,children:[`Up to `,r.perAgent,` per agent and `,r.perHost,` per host. An idle browser stops after `,r.idleTimeoutMinutes,` min.`]}):(0,j.jsx)(`span`,{children:`Headless browsers that agents run on their hosts.`}),(0,j.jsx)(g,{variant:`link`,size:`sm`,className:`h-auto p-0 text-xs`,onClick:pe,children:`Change limits`})]})]}),(0,j.jsx)(D,{children:e.fleetError?(0,j.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:e.fleetError}):n.length===0?(0,j.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`No browser is open.`}):(0,j.jsx)(`ul`,{className:`divide-y`,children:n.map(e=>(0,j.jsx)(fe,{session:e,now:t},e.id))})})]})}var me={healthy:`ok`,degraded:`warn`,unavailable:`crit`};function he(e){return e===`idle`||e===`normal`?`ok`:e===`busy`?`warn`:e===`saturated`||e===`blocked`?`crit`:`idle`}function Q({label:e,children:t}){return(0,j.jsxs)(`div`,{className:`flex justify-between gap-3`,children:[(0,j.jsx)(`dt`,{className:`text-muted-foreground`,children:e}),(0,j.jsx)(`dd`,{className:`text-right text-foreground tabular-nums`,children:t})]})}function $({host:e}){let n=o(e=>e.setHostAdmission),[r,i]=(0,A.useState)(null),a=async t=>{i(t);try{await n(e.id,{[t]:e.policy?.[t]===!1})}finally{i(null)}},s=o(e=>e.openHostEdit),c=o(e=>e.fetchHostProviders),u=o(t=>ie(t.orchestrators,e.id)),f=o(e=>e.acceptHostHardware),m=e.state!==`unavailable`&&!!e.gates_sampled_at&&Date.now()-e.gates_sampled_at<=6e4,v=(e.landing_slots?.queued??0)-(e.landing_slots?.wait_reasons?.reduce((e,t)=>e+t.count,0)??0),C=m?e.gate_capacity:void 0,w=e.state===`unavailable`?void 0:e.gate_arming,T=e.system_tags.includes(`conflict:pending`),N=e.enabled?me[e.state]??`idle`:`idle`,F=re(e.cpu_utilization),I=b(x(e.used_ram),x(e.total_ram)),R=x(e.total_storage),V=x(e.free_storage),H=R&&V!==void 0?b(R-V,R):void 0,U=e=>e===void 0?`—`:`${Math.round(e)}%`,W=m?e.running_gates:void 0,G=(C?.reservations??C?.reservedCores??W??0)>0,K=C?oe(C):W===void 0?`unknown`:`${W} running`,q=e.agent_slots?.used??e.live_agents,J=e.agent_slots?.max,Y=J!==void 0&&q>J,X=e.landing_slots,fe=(X?.used??0)>0,pe=e.policy?.spawnEnabled===!1||e.policy?.gatesEnabled===!1,Z=e.band_reason??e.band,$=e.project_toolchain,ge=[e.band&&e.band!==`normal`&&e.band_reason&&!e.state_details?.includes(e.band_reason)?{text:e.band_reason,tone:`idle`}:null,e.state_details?{text:e.state_details,tone:`warn`}:null,e.identity.matched?null:{text:`${e.identity.cause} ${e.identity.remedy}`,tone:`crit`},w?.state===`unarmed`?{text:`Gate capacity NOT ARMED (${w.cause}): gates run uncapped. ${w.reason??``}`,tone:`crit`}:null,$?.resolver?.error?{text:`Project toolchains refused: ${$.resolver.error}`,tone:`crit`}:null].filter(e=>e!==null);return(0,j.jsxs)(k,{className:t(`relative gap-3 transition-shadow hover:shadow-md`,!e.enabled&&`opacity-60`),children:[(0,j.jsx)(`div`,{className:t(`absolute inset-x-0 top-0 h-0.5`,P[N],`opacity-70`),"aria-hidden":!0}),(0,j.jsxs)(E,{className:`pb-0 pt-1 px-4`,children:[(0,j.jsxs)(`div`,{className:`flex items-start gap-2.5`,children:[(0,j.jsx)(`div`,{className:`pt-1.5`,children:(0,j.jsx)(se,{tone:N,live:e.enabled&&e.state===`healthy`,title:`${e.enabled?e.state:`disabled`}`})}),(0,j.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,j.jsx)(O,{className:`text-sm font-semibold truncate`,children:e.label}),(0,j.jsxs)(`div`,{className:`text-[11px] text-muted-foreground mt-0.5 truncate`,children:[e.os,e.os_version?` ${e.os_version}`:``,` · `,e.cpu_cores,`c / `,e.cpu_threads,`t`]})]}),(0,j.jsxs)(`div`,{className:`flex items-center gap-1.5 shrink-0 pt-0.5`,children:[(0,j.jsx)(`span`,{className:`sr-only`,children:e.state}),e.band?(0,j.jsxs)(j.Fragment,{children:[(0,j.jsx)(ce,{band:e.band,tone:he(e.band),title:Z}),(0,j.jsx)(`span`,{className:t(`text-[10px] font-medium`,M[he(e.band)]),title:Z,children:e.band})]}):null]})]}),(e.tags.length>0||e.system_tags.length>0)&&(0,j.jsxs)(`div`,{className:`flex flex-wrap gap-1 pt-2`,children:[e.tags.map(e=>(0,j.jsx)(_,{variant:`secondary`,className:`text-[10px]`,children:e},`tag-${e}`)),e.system_tags.map(e=>(0,j.jsx)(_,{variant:`outline`,className:`text-[10px] text-muted-foreground`,children:e},`stag-${e}`))]})]}),(0,j.jsxs)(D,{className:`px-4 space-y-3.5`,children:[(0,j.jsxs)(`div`,{className:`grid grid-cols-3 gap-2 rounded-lg bg-foreground/[0.03] py-3 px-1`,children:[(0,j.jsx)(L,{label:`CPU`,pct:F,tone:y(F),center:U(F),sub:e.free_threads===void 0?void 0:`${e.free_threads} free`,title:`CPU utilization ${e.cpu_utilization??`unknown`}: busy share of all cores${e.cpu_pressure?` · CPU pressure ${e.cpu_pressure} (share of time tasks wait for a CPU)`:``}${e.free_threads===void 0?``:` · ${e.free_threads} free threads`}`}),(0,j.jsx)(L,{label:`RAM`,pct:I,tone:y(I),center:U(I),sub:e.used_ram?`${e.used_ram} / ${e.total_ram}`:e.total_ram,title:`RAM ${e.used_ram??`unknown`} used of ${e.total_ram}${e.usable_ram?` · ${e.usable_ram} available`:``}`}),(0,j.jsx)(L,{label:`Disk`,pct:H,tone:y(H),center:U(H),sub:e.free_storage?`${e.free_storage} free`:e.total_storage,title:`Disk ${e.free_storage??`unknown`} free of ${e.total_storage}`})]}),(0,j.jsx)(B,{icon:(0,j.jsx)(p,{className:`w-3 h-3`}),label:`Gates`,right:K,title:`Gate slots: one cell per CPU core of host gate capacity; blue = Relay's gates, amber = other users' gates, dashed = queued`,children:C?(0,j.jsx)(le,{cells:ae(C),active:G,queued:C.queued}):(0,j.jsx)(`div`,{className:`h-3 rounded-[3px] bg-foreground/10`})}),(0,j.jsx)(de,{host:e}),(0,j.jsxs)(`div`,{className:`grid grid-cols-2 gap-x-4 gap-y-3`,children:[(0,j.jsx)(B,{icon:(0,j.jsx)(ne,{className:`w-3 h-3`}),label:`Agents`,right:J===void 0?q:`${q} / ${J}`,title:J===void 0?`${q} live agents`:`${q} / ${J} ${e.agent_slots?.cap_source===`operator`?`cap`:`default cap`}`,children:(0,j.jsx)(z,{dots:S(q,J),tone:Y?`crit`:`ok`,active:q>0})}),X?(0,j.jsx)(B,{icon:(0,j.jsx)(d,{className:`w-3 h-3`}),label:`Landing`,right:`${X.used} / ${X.max}${X.queued>0?` +${X.queued}`:``}`,title:`Landing admission: ${X.used} / ${X.max} slots, ${X.queued} queued`,children:(0,j.jsx)(z,{dots:S(X.used,X.max),tone:`ok`,active:fe,queued:X.queued})}):null]}),ge.map(e=>(0,j.jsxs)(`div`,{className:t(`flex items-start gap-1.5 rounded-md px-2 py-1.5 text-[11px] leading-snug`,e.tone===`crit`?`bg-tone-danger/10 text-tone-danger-fg`:e.tone===`warn`?`bg-tone-warning/10 text-tone-warning-fg`:`bg-foreground/5 text-muted-foreground`),children:[(0,j.jsx)(te,{className:`w-3 h-3 mt-px shrink-0`}),(0,j.jsx)(`span`,{title:e.text,children:e.text})]},e.text)),(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5 text-[11px]`,children:[[`spawnEnabled`,`gatesEnabled`].map(t=>(0,j.jsx)(ue,{label:t===`spawnEnabled`?`Spawns`:`Gates`,icon:t===`spawnEnabled`?(0,j.jsx)(ee,{className:`h-3 w-3`}):(0,j.jsx)(p,{className:`h-3 w-3`}),checked:e.policy?.[t]!==!1,saving:r===t,disabled:r!==null,title:t===`spawnEnabled`?`Spawns: whether new agents may start on this host. Off drains it — running agents continue.`:`Gates: whether this host may run test gates and landings. Off drains it — running gates finish.`,onChange:()=>void a(t)},t)),(0,j.jsxs)(`div`,{className:`ml-auto flex gap-1.5`,children:[T?(0,j.jsx)(g,{size:`sm`,variant:`outline`,className:`h-7 text-xs`,onClick:()=>void f(e.id),children:`Accept new hardware / same host`}):null,(0,j.jsxs)(g,{size:`sm`,variant:`ghost`,className:`h-7 text-xs gap-1`,onClick:()=>{u&&c(u),s(e)},children:[(0,j.jsx)(h,{className:`w-3 h-3`}),`Edit host`]})]})]}),pe?(0,j.jsxs)(`div`,{className:`text-xs text-tone-warning-fg`,children:[`Draining: `,e.live_agents,` live agents · `,W??`unknown`,` running gates`]}):null,(0,j.jsxs)(`details`,{className:`group text-xs`,children:[(0,j.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center gap-1 text-[11px] text-muted-foreground hover:text-foreground`,children:[(0,j.jsx)(l,{className:`w-3 h-3 transition-transform group-open:rotate-90`}),`Details`]}),(0,j.jsxs)(`dl`,{className:`mt-2 space-y-1`,children:[(0,j.jsx)(Q,{label:`RAM`,children:e.total_ram}),(0,j.jsx)(Q,{label:`Storage`,children:e.total_storage}),(0,j.jsxs)(Q,{label:`CPU`,children:[e.cpu_type,e.cpu_model?` ${e.cpu_model}`:``]}),(0,j.jsxs)(Q,{label:`Cores/Threads`,children:[e.cpu_cores,`c / `,e.cpu_threads,`t`]}),(0,j.jsx)(Q,{label:`CPU utilization`,children:e.cpu_utilization??`—`}),e.cpu_pressure?(0,j.jsx)(Q,{label:`CPU pressure (PSI)`,children:e.cpu_pressure}):null,e.free_threads===void 0?null:(0,j.jsx)(Q,{label:`Free threads`,children:e.free_threads}),e.used_ram?(0,j.jsx)(Q,{label:`Used RAM`,children:e.used_ram}):null,e.usable_ram?(0,j.jsx)(Q,{label:`Avail RAM`,children:e.usable_ram}):null,e.free_storage?(0,j.jsx)(Q,{label:`Free disk`,children:e.free_storage}):null,(0,j.jsx)(Q,{label:`Agents`,children:J===void 0?q:`${q} / ${J} ${e.agent_slots?.cap_source===`operator`?`cap`:`default cap`}`}),X?(0,j.jsxs)(Q,{label:`Landing admission`,children:[X.used,` / `,X.max,` `,X.cap_source===`operator`?`slots`:`default slots`,X.wait_reasons?.length?X.wait_reasons.map(e=>` · ${e.count} ${e.reason}`).join(``):``,v>0?` · ${v} queued lands`:``]}):null,(0,j.jsx)(Q,{label:`Gates`,children:K}),$?(0,j.jsx)(Q,{label:`Project toolchains`,children:$.resolver?`mise${$.resolver.miseVersion?` ${$.resolver.miseVersion}`:``}${$.resolver.error?` (unavailable)`:``}`:`off`}):null,Object.entries($?.projects??{}).map(([e,t])=>(0,j.jsx)(Q,{label:(0,j.jsx)(`span`,{title:e,children:e.split(`/`).filter(Boolean).at(-1)??e}),children:t},e))]})]})]})]})}function ge(){let e=o(e=>e.hosts),t=o(e=>e.hostsLoading),n=o(e=>e.fetchHosts),r=e.filter(e=>e.enabled).length;return(0,j.jsxs)(`div`,{className:`space-y-4`,children:[(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,j.jsxs)(`div`,{children:[(0,j.jsx)(`h2`,{className:`text-base font-semibold`,children:`Fleet`}),(0,j.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Registered hosts, hardware, and live load`})]}),(0,j.jsxs)(`div`,{className:`flex items-center gap-2 ml-auto`,children:[(0,j.jsxs)(_,{variant:`outline`,className:`text-xs`,children:[r,` enabled`]}),(0,j.jsx)(g,{size:`sm`,variant:`outline`,disabled:t,onClick:()=>void n(),children:t?`Refreshing…`:`Refresh`})]})]}),e.length===0?(0,j.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:t?`Loading hosts…`:`No hosts registered.`}):(0,j.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4`,children:e.map(e=>(0,j.jsx)($,{host:e},e.id))}),(0,j.jsx)(Z,{})]})}export{ge as FleetView};
2
- //# sourceMappingURL=fleet-BL4UXS_k.js.map