@desplega.ai/agent-swarm 2.7.5 → 2.7.7

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 (319) hide show
  1. package/dist/{acp-adapter-g3ads55s.js → acp-adapter-7b4vk3h5.js} +5 -4
  2. package/dist/{actions-zwfykqqk.js → actions-3tt153af.js} +18 -17
  3. package/dist/{amp-adapter-z3s0ssdt.js → amp-adapter-njpts0yr.js} +1 -1
  4. package/dist/{anthropic-messages-x4q6rfq5.js → anthropic-messages-xey2skwx.js} +7 -7
  5. package/dist/{app-vmp4fgep.js → app-nky4378f.js} +3 -3
  6. package/dist/{assistant-vwde653f.js → assistant-jnb669pa.js} +24 -22
  7. package/dist/{azure-openai-responses-s1w5n70z.js → azure-openai-responses-26t7j9ra.js} +5 -5
  8. package/dist/{boot-reembed-375t7tbk.js → boot-reembed-9mgvaztt.js} +1 -1
  9. package/dist/{boot-reembed-gq9rcpnj.js → boot-reembed-qs2djdej.js} +1 -1
  10. package/dist/{boot-scrub-sweep-nd938kyf.js → boot-scrub-sweep-yjpdj7s1.js} +3 -3
  11. package/dist/{boot-seeds-aykx51v3.js → boot-seeds-5cm6ambd.js} +4 -4
  12. package/dist/{boxd-k1j26g3h.js → boxd-nv507va8.js} +5 -5
  13. package/dist/{claude-adapter-8j4hm099.js → claude-adapter-fn287zmm.js} +5 -4
  14. package/dist/{claude-managed-setup-0wyynpn1.js → claude-managed-setup-wtdz2mj2.js} +1 -1
  15. package/dist/{claude-sdk-session-q6wj5hmy.js → claude-sdk-session-x91kqyhm.js} +9677 -9514
  16. package/dist/{cli-j3jvnpe8.js → cli-08bmz9z9.js} +1 -1
  17. package/dist/{cli-gjr2y2xk.js → cli-0agcv1v5.js} +4 -1
  18. package/dist/{cli-y24sc29k.js → cli-1c6tzt8g.js} +30 -8
  19. package/dist/{cli-mjzynrse.js → cli-35rsp8ye.js} +1 -1
  20. package/dist/{cli-rpm2sgv0.js → cli-3fg0bdcv.js} +19 -2
  21. package/dist/{cli-nn4d8dne.js → cli-5b456bpf.js} +2 -2
  22. package/dist/{cli-bhjt02p8.js → cli-5jnhv72d.js} +1 -1
  23. package/dist/{cli-fqzx7gwa.js → cli-5zx699j9.js} +2 -2
  24. package/dist/{cli-hf6zt5m6.js → cli-69szn7w7.js} +17 -1
  25. package/dist/{cli-vqypxzh4.js → cli-6g0hb4cp.js} +8 -8
  26. package/dist/{cli-tqgg40ek.js → cli-6pfd54vx.js} +9 -8
  27. package/dist/{cli-bsn8nhrq.js → cli-6vcp76qk.js} +3 -3
  28. package/dist/{cli-zppwg9p9.js → cli-72v799xn.js} +1 -1
  29. package/dist/cli-82j36f2m.js +45 -0
  30. package/dist/{cli-hn9hxmz9.js → cli-8305gbq0.js} +29 -16
  31. package/dist/{cli-z8eh3ex8.js → cli-8sckt74b.js} +8 -8
  32. package/dist/{cli-bnz7a7qf.js → cli-95jzxcp3.js} +1 -1
  33. package/dist/{cli-0bxqnvq9.js → cli-adeegh7d.js} +29 -7
  34. package/dist/{cli-g61qxmge.js → cli-afkqkrtw.js} +3 -3
  35. package/dist/{cli-7a42nfy0.js → cli-ayayvfg4.js} +24 -4
  36. package/dist/{cli-bqt1mptt.js → cli-az48n0nr.js} +4 -4
  37. package/dist/{cli-z6jkx23q.js → cli-bfv7vdg6.js} +9 -9
  38. package/dist/{cli-pywf3eh5.js → cli-caj33vcq.js} +5 -5
  39. package/dist/{cli-5pag6rmn.js → cli-cb2a8pna.js} +1 -1
  40. package/dist/{cli-wvaawacd.js → cli-cppkf404.js} +5236 -72
  41. package/dist/{cli-mry0qzym.js → cli-ddaanqkd.js} +123 -10
  42. package/dist/{cli-0gey5fzy.js → cli-e0kmphd6.js} +2 -2
  43. package/dist/{cli-zh3fp8v2.js → cli-e46hg0xw.js} +1 -1
  44. package/dist/{cli-jm2vfpfd.js → cli-e5bzrn01.js} +1 -1
  45. package/dist/{cli-qxnf8z2z.js → cli-excnnjg2.js} +165 -153
  46. package/dist/{cli-71ptav7x.js → cli-ferkkrg9.js} +1 -1
  47. package/dist/{cli-vpf89f34.js → cli-fmjd0t1y.js} +3 -3
  48. package/dist/{cli-rm6hqj3z.js → cli-fyt2g4wd.js} +33 -139
  49. package/dist/cli-g08zdaec.js +55 -0
  50. package/dist/{cli-ehq736cn.js → cli-g7s47cc5.js} +4 -4
  51. package/dist/{cli-82ae98pz.js → cli-gz6q4eve.js} +3 -3
  52. package/dist/{cli-82jg7fp9.js → cli-he5nxaa8.js} +1 -1
  53. package/dist/{cli-rqkxrmgw.js → cli-je518txm.js} +39 -14
  54. package/dist/{cli-8hs41zy2.js → cli-jtjtabxe.js} +1 -1
  55. package/dist/{cli-611a1294.js → cli-k0wwfqbg.js} +18 -1
  56. package/dist/{cli-nzxr556s.js → cli-k1nje3v3.js} +38 -43
  57. package/dist/{cli-3h4nhjn8.js → cli-k8196sh2.js} +9 -7
  58. package/dist/{cli-afrrppsw.js → cli-k899ehvh.js} +2 -2
  59. package/dist/{cli-0731hvbw.js → cli-m0da8j35.js} +23 -9
  60. package/dist/cli-m2z8jagn.js +12078 -0
  61. package/dist/{cli-8veytvbh.js → cli-mkk9rnzz.js} +5 -5
  62. package/dist/{cli-7wspm5gm.js → cli-n6bv12jn.js} +528 -6
  63. package/dist/{cli-spknvxbq.js → cli-nmzhp1b5.js} +14 -12
  64. package/dist/{cli-p599f1qm.js → cli-p82cnnjq.js} +1 -1
  65. package/dist/{cli-xtjhfmpc.js → cli-pc6n7fre.js} +1 -1
  66. package/dist/{cli-vbyfwh92.js → cli-pjctyea3.js} +2 -2
  67. package/dist/{cli-nmbmy64z.js → cli-pq73h5mz.js} +3 -3
  68. package/dist/{cli-aa6yxc7m.js → cli-pz4rk021.js} +1 -1
  69. package/dist/{cli-7wcyk2s5.js → cli-q3tkegby.js} +1 -1
  70. package/dist/cli-qghe0h66.js +67 -0
  71. package/dist/{cli-6s7vdcta.js → cli-qh4d4tvk.js} +4 -4
  72. package/dist/{cli-mmwm7zbf.js → cli-rtt8g4v9.js} +1 -1
  73. package/dist/{cli-kg8hchyg.js → cli-sa02jsqt.js} +1 -1
  74. package/dist/{cli-1h3wcpbw.js → cli-snpj5zbj.js} +2 -2
  75. package/dist/{cli-a7v854rf.js → cli-tgrv9cjx.js} +263 -12
  76. package/dist/{cli-a47xy8eq.js → cli-vz22fyqv.js} +186 -54
  77. package/dist/{cli-1ayk1eas.js → cli-wk5yrfwd.js} +285 -42
  78. package/dist/{cli-1338796d.js → cli-ws19768n.js} +1755 -119
  79. package/dist/{cli-70r77n04.js → cli-xae4g51r.js} +1 -1
  80. package/dist/{cli-gf5hbmdr.js → cli-yjdgea32.js} +3 -3
  81. package/dist/{cli-xbkdm710.js → cli-yndmfxb3.js} +3 -3
  82. package/dist/{cli-rhw40jgb.js → cli-yyj3j5m4.js} +2 -2
  83. package/dist/cli.js +26 -25
  84. package/dist/{cloudflare-workers-ai-system-one-bm60fjm0.js → cloudflare-workers-ai-system-one-ef2a980q.js} +2 -2
  85. package/dist/{codex-adapter-q6k3gnyg.js → codex-adapter-cf2yxe9m.js} +3 -2
  86. package/dist/{codex-hook-9efm2x1m.js → codex-hook-a0c6g6t6.js} +1 -1
  87. package/dist/{codex-session-runner-3mwmk3d9.js → codex-session-runner-6vfzdgbd.js} +3 -2
  88. package/dist/{commands-evrenjn9.js → commands-t3mfy7vn.js} +9 -3
  89. package/dist/{controller-xjp8vswh.js → controller-q7xrbaz0.js} +8 -3
  90. package/dist/{controllers-connect-pp5jnxvc.js → controllers-connect-c6nm70kg.js} +20 -19
  91. package/dist/{cursor-adapter-yf47w4t0.js → cursor-adapter-ftd81ga8.js} +1 -1
  92. package/dist/{db-zxpw6aht.js → db-dk572x25.js} +3 -3
  93. package/dist/{db-rgfsh91f.js → db-vemtpmcc.js} +14 -4
  94. package/dist/{devtools-82fzqra8.js → devtools-qxfgbsqz.js} +1 -1
  95. package/dist/{dispatcher-smasgws7.js → dispatcher-kh7ecxh9.js} +17 -16
  96. package/dist/{docker-rrjhaqt9.js → docker-c1a3gqmf.js} +89 -22
  97. package/dist/{dsh-adapter-ftyy8dnp.js → dsh-adapter-v8628r89.js} +1 -1
  98. package/dist/{e2b-w1p0bnpm.js → e2b-fr12yccx.js} +5 -5
  99. package/dist/{e2b-qcaj675y.js → e2b-x6ywzak3.js} +3 -3
  100. package/dist/{easter-egg-3d-yyts7p16.js → easter-egg-3d-nenw4x63.js} +1 -1
  101. package/dist/{embedding-space-1z0mbg95.js → embedding-space-0jepb239.js} +6 -6
  102. package/dist/{embeddings-ygeg7tm7.js → embeddings-xxt49yxg.js} +1 -1
  103. package/dist/{execute-14qhqp4d.js → execute-1mhw6e4x.js} +1 -1
  104. package/dist/{external-channel-ttgrs3sx.js → external-channel-55v12e60.js} +2 -2
  105. package/dist/{fx-adapter-gt6pncj2.js → fx-adapter-bs8wqrk5.js} +6 -5
  106. package/dist/{google-generative-ai-yvmdxyxa.js → google-generative-ai-v94hr7h0.js} +5 -5
  107. package/dist/{google-vertex-jrtdh9gs.js → google-vertex-g7vr6cf8.js} +5 -5
  108. package/dist/{grok-adapter-sm4m5k4g.js → grok-adapter-gpjqmkcq.js} +6 -5
  109. package/dist/handlers-zxmp1ta4.js +32 -0
  110. package/dist/{heartbeat-qahz4p62.js → heartbeat-k42svnr0.js} +20 -19
  111. package/dist/{hook-4fd5wq5w.js → hook-114m7hap.js} +4 -3
  112. package/dist/{hook-kj3d398m.js → hook-6nphweh0.js} +24 -9
  113. package/dist/{http-1ted0j1k.js → http-r8cc4wz7.js} +1196 -211
  114. package/dist/index-a8phxqnk.js +37 -0
  115. package/dist/{index-q4b917zs.js → index-e3s8wmxy.js} +1 -1
  116. package/dist/{index-6rq3r5zb.js → index-fpk4bcd9.js} +1 -1
  117. package/dist/{index-5rk6rfzr.js → index-fvzke5kx.js} +1 -1
  118. package/dist/index-k6h00t4c.js +30 -0
  119. package/dist/{index-7v51awbn.js → index-nh3wyqdt.js} +1027 -577
  120. package/dist/{index-yqhz88yy.js → index-pxn30mse.js} +8 -8
  121. package/dist/index-xrz7te8h.js +33 -0
  122. package/dist/{keepalive-6cf311t5.js → keepalive-x060nt9p.js} +3 -3
  123. package/dist/lead-956sd2yc.js +71 -0
  124. package/dist/{maintenance-a4bm1bmt.js → maintenance-2xxfexhf.js} +1 -1
  125. package/dist/{mistral-conversations-4pmwj1c0.js → mistral-conversations-3gjpdb4b.js} +4 -4
  126. package/dist/{oauth-refresh-sweep-3h0dfw1k.js → oauth-refresh-sweep-fckc4ar5.js} +2 -2
  127. package/dist/{onboard-myn5hraa.js → onboard-zc48j237.js} +5 -5
  128. package/dist/{openai-codex-responses-44j573nm.js → openai-codex-responses-8pbxq9h5.js} +5 -5
  129. package/dist/{openai-completions-a4gee2a8.js → openai-completions-rm00s912.js} +4 -4
  130. package/dist/{openai-decisions-w4qkrcar.js → openai-decisions-8v957r2r.js} +1 -1
  131. package/dist/{openai-responses-rbp6h5kr.js → openai-responses-agxpf96k.js} +5 -5
  132. package/dist/{opencode-adapter-p2nkb5am.js → opencode-adapter-r690h1cr.js} +4 -3
  133. package/dist/{otel-impl-a1a0ef6b.js → otel-impl-r5xbh81q.js} +4 -4
  134. package/dist/{pi-mono-adapter-rzmpb72a.js → pi-mono-adapter-c7v8sdec.js} +7 -6
  135. package/dist/{pricing-refresh-83drrnxj.js → pricing-refresh-3pmre11v.js} +3 -3
  136. package/dist/{rbac-roles-s8y6ecb5.js → rbac-roles-3vbshwsb.js} +1 -1
  137. package/dist/{rbac-roles-0fb6e7pj.js → rbac-roles-910mmkgz.js} +2 -2
  138. package/dist/{render-v2-twmbgrz4.js → render-v2-pxykkbab.js} +3 -3
  139. package/dist/{resume-zfqc36xj.js → resume-adda0bwy.js} +6 -6
  140. package/dist/{runtime-qwggdpqr.js → runtime-fnbm7stk.js} +1 -1
  141. package/dist/{session-access-sc9pn9da.js → session-access-2fvamrdc.js} +4 -4
  142. package/dist/{session-source-backfill-qh07xr8g.js → session-source-backfill-08xvv0sm.js} +2 -2
  143. package/dist/{setup-4fr0m7a1.js → setup-1aqmvmh1.js} +3 -3
  144. package/dist/{typesafe-system-one-5mavm259.js → typesafe-system-one-0bmqcxfg.js} +2 -2
  145. package/dist/{virtual-modules-fh4ha15b.js → virtual-modules-d2pjk9j1.js} +5 -5
  146. package/dist/{work-objects-0wr8zxct.js → work-objects-9s0yrm5j.js} +20 -19
  147. package/dist/{worker-follow-up-ktyyazyp.js → worker-follow-up-3q78fqmr.js} +17 -16
  148. package/dist/worker-y15hy08h.js +71 -0
  149. package/openapi.json +289 -4
  150. package/package.json +9 -8
  151. package/src/apps/definition.ts +6 -5
  152. package/src/be/db/page-theme-tokens.ts +12 -0
  153. package/src/be/db/script-runs.ts +23 -0
  154. package/src/be/db/tasks/read.ts +131 -4
  155. package/src/be/db/tasks/write.ts +19 -0
  156. package/src/be/db-client.ts +114 -11
  157. package/src/be/db.ts +49 -6
  158. package/src/be/memory/providers/sqlite-store.ts +49 -12
  159. package/src/be/migrations/260_runtime_pool_cache.sql +20 -0
  160. package/src/be/migrations/262_session_visibility_indexes.sql +18 -0
  161. package/src/be/migrations/263_task_list_filter_index.sql +11 -0
  162. package/src/be/migrations/264_slack_thread_cover_index.sql +9 -0
  163. package/src/be/migrations/266_script_runs_source_task.sql +11 -0
  164. package/src/be/migrations/269_pages_design_system.sql +23 -0
  165. package/src/be/runtime-pools/cache-cleanup.ts +109 -0
  166. package/src/be/runtime-pools/db.ts +65 -6
  167. package/src/be/runtime-pools/remote-controller.ts +5 -0
  168. package/src/be/runtime-pools/supervisor.ts +33 -2
  169. package/src/be/scripts/typecheck.ts +22 -0
  170. package/src/be/seed/schedules-seeder.ts +0 -10
  171. package/src/be/seed-scripts/catalog/catalog-report.inline.ts +2 -0
  172. package/src/be/seed-scripts/catalog/catalog-report.ts +2 -0
  173. package/src/be/seed-scripts/catalog/memory-eval.ts +2 -0
  174. package/src/be/seed-scripts/catalog/swarm-update-check.ts +150 -0
  175. package/src/be/seed-scripts/catalog/task-failure-audit.ts +5 -1
  176. package/src/be/seed-scripts/index.ts +9 -0
  177. package/src/be/seed-skills/bundled-files.generated.json +3 -3
  178. package/src/be/swarm-config-guard.ts +32 -0
  179. package/src/be/task-auto-title-listener.ts +127 -0
  180. package/src/commands/controller.ts +4 -0
  181. package/src/commands/entrypoint-api-readiness.ts +74 -0
  182. package/src/commands/onboard/agent-fs-version.ts +1 -1
  183. package/src/commands/profile-sync.ts +151 -16
  184. package/src/commands/runner.ts +15 -7
  185. package/src/hooks/hook.ts +20 -9
  186. package/src/http/index.ts +4 -1
  187. package/src/http/list-total-cache.ts +14 -7
  188. package/src/http/memory.ts +38 -9
  189. package/src/http/pages-public.ts +93 -129
  190. package/src/http/pages.ts +94 -21
  191. package/src/http/script-runs.ts +174 -5
  192. package/src/http/status.ts +10 -2
  193. package/src/http/tasks.ts +4 -2
  194. package/src/pages/browser-sdk.ts +48 -21
  195. package/src/pages/color-literals.ts +115 -0
  196. package/src/pages/page-head.ts +766 -0
  197. package/src/pages/version.ts +3 -0
  198. package/src/providers/amp-adapter.ts +1 -1
  199. package/src/providers/codex-adapter.ts +1 -0
  200. package/src/providers/codex-app-server.ts +27 -1
  201. package/src/providers/fx-adapter.ts +1 -1
  202. package/src/providers/pi-mono-extension.ts +30 -15
  203. package/src/runtime-providers/controller-protocol.ts +14 -1
  204. package/src/runtime-providers/controller.ts +5 -0
  205. package/src/runtime-providers/docker.ts +108 -23
  206. package/src/runtime-providers/types.ts +16 -0
  207. package/src/script-workflows/workflow-ctx.ts +8 -0
  208. package/src/scripts-runtime/types/stdlib.d.ts +22 -0
  209. package/src/scripts-runtime/types/swarm-sdk.d.ts +22 -0
  210. package/src/server-user.ts +1 -0
  211. package/src/slack/commands.ts +5 -1
  212. package/src/slack/handlers.ts +37 -2
  213. package/src/slack/left-threads.ts +27 -4
  214. package/src/tasks/follow-up-gate.ts +318 -0
  215. package/src/tasks/follow-up-redelegation-guard.ts +155 -0
  216. package/src/tasks/worker-follow-up.ts +21 -1
  217. package/src/tests/claude-artifacts-read-script.test.ts +209 -0
  218. package/src/tests/codex-app-server.test.ts +59 -0
  219. package/src/tests/codex-gateway-route.test.ts +50 -1
  220. package/src/tests/create-page-tool.test.ts +501 -0
  221. package/src/tests/db-client-busy-retry.test.ts +81 -0
  222. package/src/tests/db-client.test.ts +21 -0
  223. package/src/tests/db-task-read-contract.test.ts +9 -2
  224. package/src/tests/db-task-write-contract.test.ts +7 -1
  225. package/src/tests/db-tasks-read.test.ts +21 -0
  226. package/src/tests/entrypoint-api-readiness.test.ts +416 -210
  227. package/src/tests/explicit-model-validation.test.ts +14 -8
  228. package/src/tests/fixtures/pages/head-v1.html +56 -0
  229. package/src/tests/follow-up-gate-shadow.test.ts +513 -0
  230. package/src/tests/follow-up-redelivery-guard.test.ts +432 -202
  231. package/src/tests/identity-field-budget.test.ts +1 -1
  232. package/src/tests/internal-ai/credentials.test.ts +62 -0
  233. package/src/tests/internal-ai/task-title.test.ts +283 -0
  234. package/src/tests/list-total-cache.test.ts +27 -2
  235. package/src/tests/memory-fts-populate.test.ts +11 -9
  236. package/src/tests/memory-retrieval-purge.test.ts +80 -0
  237. package/src/tests/merge-gate-detect-changes.test.ts +145 -0
  238. package/src/tests/migration-260-runtime-pool-cache.test.ts +118 -0
  239. package/src/tests/page-proxy.test.ts +1 -1
  240. package/src/tests/page-session-dev-cookie.test.ts +188 -0
  241. package/src/tests/pages-frame-ancestors.test.ts +28 -1
  242. package/src/tests/pages-head-v2.test.ts +534 -0
  243. package/src/tests/pages-http.test.ts +330 -0
  244. package/src/tests/pages-public-html.test.ts +43 -0
  245. package/src/tests/pages-storage.test.ts +182 -0
  246. package/src/tests/pages-versioning.test.ts +72 -0
  247. package/src/tests/profile-sync-stale-writeback.test.ts +334 -0
  248. package/src/tests/profile-sync.test.ts +11 -15
  249. package/src/tests/query-audit-plans.test.ts +27 -0
  250. package/src/tests/runtime-cache-cleanup.test.ts +367 -0
  251. package/src/tests/runtime-e2b-pools.test.ts +41 -0
  252. package/src/tests/runtime-pools-db.test.ts +98 -0
  253. package/src/tests/runtime-pools-http.test.ts +29 -0
  254. package/src/tests/runtime-providers-docker.test.ts +253 -0
  255. package/src/tests/runtime-remote-controller.test.ts +66 -2
  256. package/src/tests/runtime-supervisor.test.ts +66 -2
  257. package/src/tests/scheduled-task-required-params-migration.test.ts +3 -1
  258. package/src/tests/script-connections.test.ts +13 -0
  259. package/src/tests/script-runs-http.test.ts +684 -2
  260. package/src/tests/seed-registry.test.ts +28 -6
  261. package/src/tests/seed-schedules.test.ts +61 -8
  262. package/src/tests/seed-scripts.test.ts +168 -2
  263. package/src/tests/slack-leave-thread.test.ts +145 -5
  264. package/src/tests/slack-render-v2-query-plans.test.ts +24 -2
  265. package/src/tests/status.test.ts +11 -0
  266. package/src/tests/swarm-diff.test.ts +121 -2
  267. package/src/tests/task-auto-title-config-guard.test.ts +37 -0
  268. package/src/tests/task-auto-title-listener.test.ts +165 -0
  269. package/src/tests/tasks-readable-row.test.ts +155 -0
  270. package/src/tests/theme-import.test.ts +758 -0
  271. package/src/tests/themes-page-theme.test.ts +155 -0
  272. package/src/tests/themes-presets.test.ts +172 -0
  273. package/src/tests/workflow-script-principal.test.ts +2 -1
  274. package/src/themes/classics.ts +949 -0
  275. package/src/themes/import.ts +420 -0
  276. package/src/themes/page-fields.ts +40 -0
  277. package/src/themes/page-theme.ts +102 -0
  278. package/src/themes/presets.ts +561 -0
  279. package/src/themes/tokens.ts +218 -0
  280. package/src/tools/app-upsert.ts +1 -1
  281. package/src/tools/create-page.ts +118 -12
  282. package/src/tools/send-task.ts +35 -47
  283. package/src/tools/slack-leave-thread.ts +1 -1
  284. package/src/tools/task-dedup.ts +45 -21
  285. package/src/tools/utils.ts +33 -0
  286. package/src/types.ts +83 -3
  287. package/src/utils/constants.ts +19 -0
  288. package/src/utils/follow-up-gate-schedule-ids.ts +13 -0
  289. package/src/utils/internal-ai/credentials.ts +146 -93
  290. package/src/utils/internal-ai/index.ts +10 -0
  291. package/src/utils/internal-ai/models.ts +18 -0
  292. package/src/utils/internal-ai/task-title.ts +282 -0
  293. package/src/utils/page-session.ts +37 -0
  294. package/templates/schedules/daily-status-report/content.md +88 -2
  295. package/templates/schedules/daily-swarm-update-check/content.md +16 -40
  296. package/templates/skills/apps/SKILL.md +1 -1
  297. package/templates/skills/apps/content.md +1 -1
  298. package/templates/skills/composio-google-docs/content.md +10 -0
  299. package/templates/skills/heartbeat-runbook/content.md +1 -1
  300. package/templates/skills/pages/config.json +1 -1
  301. package/templates/skills/pages/content.md +539 -86
  302. package/templates/skills/pages/files/examples/annotated-pr.html +21 -12
  303. package/templates/skills/pages/files/examples/multiplayer-board.html +41 -41
  304. package/templates/skills/pages/files/examples/report-page.html +125 -124
  305. package/templates/skills/script-workflows/content.md +19 -1
  306. package/templates/skills/swarm-docs/content.md +1 -0
  307. package/templates/skills/swarm-scripts/SKILL.md +2 -0
  308. package/templates/skills/swarm-scripts/content.md +2 -0
  309. package/dist/cli-2pnswgh8.js +0 -189
  310. package/dist/cli-dznrgaep.js +0 -30
  311. package/dist/cli-w3hcrxht.js +0 -6985
  312. package/dist/handlers-vwmba1m2.js +0 -31
  313. package/dist/index-5r71rf98.js +0 -32
  314. package/dist/index-anmwxs87.js +0 -29
  315. package/dist/index-spp0ra5c.js +0 -36
  316. package/dist/lead-fjy418cw.js +0 -69
  317. package/dist/worker-0c5tyzqe.js +0 -69
  318. package/templates/schedules/daily-workflow-health-audit/config.json +0 -19
  319. package/templates/schedules/daily-workflow-health-audit/content.md +0 -191
@@ -0,0 +1,766 @@
1
+ /**
2
+ * The `<head>` that `/p/:id` injects into an HTML page, one per design
3
+ * version (`page.designVersion`):
4
+ *
5
+ * - 1: `PAGE_HEAD_V1`, the original head. Frozen.
6
+ * - 2: `buildPageHeadV2()`, the swarm design system: theme tokens (see
7
+ * `src/themes/page-theme.ts`), element defaults and `swarm-*` primitives in
8
+ * cascade layers, and the pinned Tailwind v4 browser build.
9
+ */
10
+ import { type ResolvedPageTheme, renderPageThemeCss } from "../themes/page-theme";
11
+ import { PAGE_THEME_TOKENS } from "../themes/tokens";
12
+
13
+ /** Query param: the viewer's dashboard preset id. Read by design version 2 only. */
14
+ export const PAGE_THEME_PARAM = "__swarm-theme";
15
+ /** Query param: `dark` renders the dark tokens. Read by design version 2 only. */
16
+ export const PAGE_MODE_PARAM = "__swarm-mode";
17
+
18
+ /**
19
+ * Design version 1, FROZEN: never change it. Pages with designVersion 1 must
20
+ * keep rendering as they did when they were written. Design changes go to
21
+ * `buildPageHeadV2` (or to a new design version).
22
+ *
23
+ * Default `<head>` injection: `<base>` so links escape the iframe, Tailwind
24
+ * Play CDN so agent pages can use utility classes out of the box, Space
25
+ * Grotesk / Space Mono fonts to match the swarm SPA, a small reset that
26
+ * makes pages theme-aware (light by default) so an agent who writes zero CSS
27
+ * still gets a presentable page, and finally the Browser SDK so
28
+ * `window.swarmSdk` works.
29
+ *
30
+ * Agent-provided styles can override these defaults. Tailwind utilities stay
31
+ * available, but its Preflight reset is disabled to preserve browser heading,
32
+ * margin, and list styles.
33
+ */
34
+ export const PAGE_HEAD_V1 = `<base target="_blank">
35
+ <link rel="preconnect" href="https://fonts.googleapis.com">
36
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
37
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
38
+ <script src="https://cdn.tailwindcss.com"></script>
39
+ <script>
40
+ if (window.tailwind) {
41
+ window.tailwind.config = { corePlugins: { preflight: false } };
42
+ }
43
+ </script>
44
+ <style>
45
+ *, ::before, ::after { box-sizing: border-box; border: 0 solid #e5e7eb; }
46
+ hr { border-top-width: 1px; }
47
+ img, video { display: block; max-width: 100%; height: auto; }
48
+ button, input, optgroup, select, textarea, ::file-selector-button { font: inherit; }
49
+ :root {
50
+ color-scheme: light;
51
+ --swarm-bg: #fbfbfa;
52
+ --swarm-card: #ffffff;
53
+ --swarm-border: #e5e7eb;
54
+ --swarm-text: #111827;
55
+ --swarm-muted: #6b7280;
56
+ --swarm-primary: #3b82f6;
57
+ }
58
+ html, body { background: var(--swarm-bg); color: var(--swarm-text); }
59
+ body {
60
+ font-family: "Space Grotesk", system-ui, sans-serif;
61
+ margin: 0;
62
+ padding: 24px;
63
+ line-height: 1.5;
64
+ }
65
+ code, pre, kbd, samp { font-family: "Space Mono", ui-monospace, monospace; }
66
+ a { color: var(--swarm-primary); }
67
+ ::selection { background: var(--swarm-primary); color: #fff; }
68
+ @media print {
69
+ /* Override theme variables so built-in primitives (swarm-diff, swarm-card)
70
+ that read var(--swarm-card) / var(--swarm-border) etc. inline-styled
71
+ backgrounds also flip to light. Without this, diff cards stay dark navy
72
+ on print. */
73
+ :root {
74
+ --swarm-bg: #ffffff;
75
+ --swarm-card: #ffffff;
76
+ --swarm-border: #cccccc;
77
+ --swarm-text: #000000;
78
+ --swarm-muted: #555555;
79
+ }
80
+ html, body { background: white !important; color: black !important; }
81
+ a { color: black !important; text-decoration: underline; }
82
+ /* Hide any swarm chrome the agent (or built-in primitives) tagged with
83
+ .no-print. Use this class on annotation badges, jump-list nav, anything
84
+ that shouldn't appear in the PDF export. */
85
+ .no-print { display: none !important; }
86
+ /* Avoid page-break inside cards / diff blocks. */
87
+ .swarm-card, swarm-diff { break-inside: avoid; }
88
+ }
89
+ </style>`;
90
+
91
+ // ─── Design version 2 ───────────────────────────────────────────────────────
92
+
93
+ /** Pinned Tailwind v4 browser build. Bump the version and the hash together. */
94
+ const TAILWIND_BROWSER_SRC =
95
+ "https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.3.3/dist/index.global.js";
96
+ const TAILWIND_BROWSER_INTEGRITY =
97
+ "sha384-2ql948lIdLcGEE0/qxNiudyTjgauA3RDJERu5xW75kFCvSl5a9odyQYCb6tEjnmB";
98
+
99
+ /**
100
+ * `<base target="_blank">` would open an in-page `#id` link in a new tab. On
101
+ * click (capture phase, so before page handlers), this gives such a link
102
+ * `target="_self"` when it has no target. `setAttribute` also works on SVG
103
+ * links.
104
+ */
105
+ const IN_PAGE_LINK_SCRIPT = `<script>document.addEventListener("click", function (event) {
106
+ var link = event.target && event.target.closest && event.target.closest('a[href^="#"]:not([target])');
107
+ if (link) link.setAttribute("target", "_self");
108
+ }, true);</script>`;
109
+
110
+ const FONT_LINKS = `<link rel="preconnect" href="https://fonts.googleapis.com">
111
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
112
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">`;
113
+
114
+ /**
115
+ * The Tailwind source. Theme and utilities only: Preflight stays off, so the
116
+ * element defaults below survive. `inline reference` maps each token utility
117
+ * (`bg-primary`, `rounded-xl`, `font-mono`) to `var(<token>)` and emits no
118
+ * variable of its own, so the unlayered theme CSS stays the one source.
119
+ */
120
+ const TAILWIND_SOURCE = [
121
+ '@import "tailwindcss/theme" layer(theme);',
122
+ '@import "tailwindcss/utilities" layer(utilities);',
123
+ "@custom-variant dark (&:where(.dark, .dark *));",
124
+ "@theme inline reference {",
125
+ ...PAGE_THEME_TOKENS.map((token) => ` ${token}: var(${token});`),
126
+ "}",
127
+ ].join("\n");
128
+
129
+ /**
130
+ * Adds the Tailwind source as a `text/tailwindcss` style element at run time
131
+ * (see `buildPageHeadV2`, item 6). The source is a JSON string with `<`
132
+ * escaped, so it cannot close the script.
133
+ */
134
+ const TAILWIND_SOURCE_SCRIPT = `<script>(function () {
135
+ var style = document.createElement("style");
136
+ style.type = "text/tailwindcss";
137
+ style.textContent = ${JSON.stringify(TAILWIND_SOURCE).replace(/</g, "\\u003c")};
138
+ document.head.appendChild(style);
139
+ })();</script>`;
140
+
141
+ // One look, two selectors each: the plain element (`@layer base`) and the
142
+ // primitive class (`@layer components`). Both are 36px tall, like the
143
+ // dashboard controls. Only `background-color` is set, so the select arrow
144
+ // (a background image) survives. The base font reset for controls puts its
145
+ // elements in `:where()`, so its zero specificity lets these looks win by
146
+ // source order (a pseudo-element cannot go inside `:where()`).
147
+ const CONTROL_LOOK = `min-width: 0;
148
+ padding: 7px 12px;
149
+ font-size: 14px;
150
+ line-height: 20px;
151
+ color: var(--color-foreground);
152
+ background-color: var(--color-card);
153
+ border: 1px solid var(--color-input);
154
+ border-radius: var(--radius-md);
155
+ transition: border-color 150ms, box-shadow 150ms;`;
156
+
157
+ const BUTTON_LOOK = `display: inline-flex;
158
+ align-items: center;
159
+ justify-content: center;
160
+ gap: 8px;
161
+ padding: 7px 14px;
162
+ font-size: 14px;
163
+ font-weight: 500;
164
+ line-height: 20px;
165
+ color: var(--color-foreground);
166
+ background-color: var(--color-card);
167
+ border: 1px solid var(--color-input);
168
+ border-radius: var(--radius-md);
169
+ text-decoration: none;
170
+ white-space: nowrap;
171
+ cursor: pointer;
172
+ transition: color 150ms, background-color 150ms, border-color 150ms, box-shadow 150ms;`;
173
+
174
+ const FOCUS_RING = `outline: none;
175
+ border-color: var(--color-ring);
176
+ box-shadow: 0 0 0 2px color-mix(in oklab, var(--color-ring) 60%, transparent);`;
177
+
178
+ const TEXT_CONTROLS = `:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="button"], [type="submit"], [type="reset"], [type="image"], [type="hidden"]), select, textarea)`;
179
+ const BUTTON_CONTROLS = `:where(button, input[type="button"], input[type="submit"], input[type="reset"])`;
180
+
181
+ /**
182
+ * The edge shadow of `.swarm-table-wrap`. The wrap paints it at each side with
183
+ * `background-attachment: scroll`, and covers it with card-colored gradients
184
+ * that scroll with the table (`local`). A side shows its shadow only when
185
+ * columns are hidden past it.
186
+ */
187
+ const EDGE_SHADOW = "color-mix(in oklab, var(--color-foreground) 14%, transparent)";
188
+
189
+ /**
190
+ * The status tones of `.swarm-badge`, `.swarm-callout` and `.swarm-metric`
191
+ * (`data-tone`). Each sets a soft color and a text-safe strong color.
192
+ */
193
+ const TONES: ReadonlyArray<readonly [tone: string, soft: string, strong: string]> = [
194
+ ["neutral", "--color-status-neutral", "--color-status-neutral-strong"],
195
+ ["primary", "--color-primary", "--color-primary"],
196
+ ...["success", "warning", "error", "info", "pending", "paused", "active"].map(
197
+ (tone) => [tone, `--color-status-${tone}`, `--color-status-${tone}-strong`] as const,
198
+ ),
199
+ ];
200
+
201
+ const TONE_RULES = TONES.map(
202
+ ([tone, soft, strong]) =>
203
+ ` :is(.swarm-badge, .swarm-callout, .swarm-metric)[data-tone="${tone}"] {\n --swarm-tone: var(${soft});\n --swarm-tone-strong: var(${strong});\n }`,
204
+ ).join("\n");
205
+
206
+ /**
207
+ * Element defaults (`@layer base`), primitives (`@layer components`) and the
208
+ * print rules (unlayered). Every color is a theme token. Taste bar: the Hive
209
+ * dashboard (`apps/ui/DESIGN.md`): quiet chrome, whitespace and uppercase
210
+ * micro-labels for separation, two-tier borders, soft pills, one accent, no
211
+ * shadows.
212
+ */
213
+ const PAGE_DESIGN_CSS = `@layer base {
214
+ *, ::before, ::after, ::backdrop, ::file-selector-button {
215
+ box-sizing: border-box;
216
+ border: 0 solid var(--color-border);
217
+ }
218
+ html {
219
+ color: var(--color-foreground);
220
+ -webkit-text-size-adjust: 100%;
221
+ text-size-adjust: 100%;
222
+ tab-size: 4;
223
+ }
224
+ body {
225
+ margin: 0;
226
+ padding: 24px;
227
+ background-color: var(--color-background);
228
+ color: var(--color-foreground);
229
+ font-family: var(--font-sans), ui-sans-serif, system-ui, sans-serif;
230
+ font-size: 15px;
231
+ line-height: 1.55;
232
+ -webkit-font-smoothing: antialiased;
233
+ -moz-osx-font-smoothing: grayscale;
234
+ }
235
+ @media (max-width: 640px) {
236
+ body { padding: 16px; }
237
+ }
238
+ :focus-visible {
239
+ outline: 2px solid var(--color-ring);
240
+ outline-offset: 2px;
241
+ }
242
+ h1, h2, h3, h4, h5, h6 {
243
+ margin: 0;
244
+ font-weight: 600;
245
+ text-wrap: balance;
246
+ }
247
+ h1 { margin: 0 0 12px; font-size: 30px; line-height: 1.2; letter-spacing: -0.02em; }
248
+ h2 { margin: 40px 0 12px; font-size: 20px; line-height: 1.3; letter-spacing: -0.015em; }
249
+ h3 { margin: 28px 0 8px; font-size: 16px; line-height: 1.4; letter-spacing: -0.01em; }
250
+ h4 { margin: 24px 0 6px; font-size: 15px; line-height: 1.45; }
251
+ h5, h6 { margin: 20px 0 6px; font-size: 13px; line-height: 1.45; }
252
+ p { margin: 0 0 12px; text-wrap: pretty; }
253
+ ul, ol { margin: 0 0 12px; padding-left: 1.5em; }
254
+ li { margin: 4px 0; }
255
+ li > ul, li > ol { margin: 4px 0 0; }
256
+ li::marker { color: var(--color-muted-foreground); }
257
+ dl, figure, blockquote, pre, table, details, fieldset, form { margin: 0 0 16px; }
258
+ dt { font-weight: 500; }
259
+ dd { margin: 0 0 8px; }
260
+ :where(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; }
261
+ :where(p, ul, ol, dl, dd, figure, blockquote, pre, table, details, fieldset, form):last-child { margin-bottom: 0; }
262
+ a {
263
+ color: var(--color-primary);
264
+ text-decoration-line: underline;
265
+ text-decoration-thickness: 1px;
266
+ text-decoration-color: color-mix(in oklab, currentColor 35%, transparent);
267
+ text-underline-offset: 3px;
268
+ }
269
+ a:hover { text-decoration-color: currentColor; }
270
+ hr {
271
+ height: 0;
272
+ margin: 32px 0;
273
+ color: inherit;
274
+ border-top: 1px solid var(--color-border-subtle);
275
+ }
276
+ b, strong { font-weight: 600; }
277
+ mark {
278
+ padding: 0 2px;
279
+ color: inherit;
280
+ background-color: color-mix(in oklab, var(--color-status-pending) 35%, transparent);
281
+ border-radius: 2px;
282
+ }
283
+ code, kbd, samp, pre {
284
+ font-family: var(--font-mono), ui-monospace, SFMono-Regular, Menlo, monospace;
285
+ font-size: 0.85em;
286
+ }
287
+ code {
288
+ padding: 0.1em 0.35em;
289
+ background-color: var(--color-muted);
290
+ border-radius: var(--radius-sm);
291
+ -webkit-box-decoration-break: clone;
292
+ box-decoration-break: clone;
293
+ }
294
+ kbd {
295
+ padding: 0.05em 0.4em;
296
+ background-color: var(--color-card);
297
+ border: 1px solid var(--color-border);
298
+ border-bottom-width: 2px;
299
+ border-radius: var(--radius-sm);
300
+ }
301
+ pre {
302
+ padding: 12px 14px;
303
+ overflow: auto;
304
+ line-height: 1.6;
305
+ background-color: var(--color-surface);
306
+ border: 1px solid var(--color-border);
307
+ border-radius: var(--radius-lg);
308
+ }
309
+ pre code {
310
+ padding: 0;
311
+ font-size: inherit;
312
+ background-color: transparent;
313
+ border-radius: 0;
314
+ }
315
+ blockquote {
316
+ padding: 2px 0 2px 16px;
317
+ color: var(--color-muted-foreground);
318
+ border-left: 2px solid var(--color-border);
319
+ }
320
+ summary {
321
+ cursor: pointer;
322
+ font-weight: 500;
323
+ }
324
+ summary::marker { color: var(--color-muted-foreground); }
325
+ details[open] > summary { margin-bottom: 8px; }
326
+ img, video {
327
+ display: block;
328
+ max-width: 100%;
329
+ height: auto;
330
+ }
331
+ figcaption {
332
+ margin-top: 8px;
333
+ font-size: 13px;
334
+ color: var(--color-muted-foreground);
335
+ }
336
+ table {
337
+ width: 100%;
338
+ border-collapse: collapse;
339
+ font-size: 14px;
340
+ font-variant-numeric: tabular-nums;
341
+ }
342
+ caption {
343
+ padding-bottom: 8px;
344
+ font-size: 13px;
345
+ text-align: left;
346
+ color: var(--color-muted-foreground);
347
+ }
348
+ th, td {
349
+ padding: 8px 12px;
350
+ text-align: left;
351
+ vertical-align: middle;
352
+ border-bottom: 1px solid var(--color-border-subtle);
353
+ }
354
+ th {
355
+ font-size: 11px;
356
+ font-weight: 500;
357
+ line-height: 1.45;
358
+ letter-spacing: 0.05em;
359
+ text-transform: uppercase;
360
+ vertical-align: bottom;
361
+ color: var(--color-muted-foreground);
362
+ border-bottom-color: var(--color-border);
363
+ }
364
+ th[scope="row"] {
365
+ font-size: inherit;
366
+ letter-spacing: normal;
367
+ text-transform: none;
368
+ vertical-align: middle;
369
+ color: inherit;
370
+ border-bottom-color: var(--color-border-subtle);
371
+ }
372
+ tfoot :is(td, th) {
373
+ font-weight: 600;
374
+ border-top: 1px solid var(--color-border);
375
+ }
376
+ tbody:has(+ tfoot) > tr:last-child > :is(td, th) { border-bottom-color: var(--color-border); }
377
+ :where(button, input, optgroup, select, textarea), ::file-selector-button {
378
+ font: inherit;
379
+ font-feature-settings: inherit;
380
+ font-variation-settings: inherit;
381
+ letter-spacing: inherit;
382
+ color: inherit;
383
+ }
384
+ ${TEXT_CONTROLS} {
385
+ ${CONTROL_LOOK}
386
+ }
387
+ ${TEXT_CONTROLS}:focus-visible {
388
+ ${FOCUS_RING}
389
+ }
390
+ :where(input, select, textarea)::placeholder {
391
+ color: var(--color-muted-foreground);
392
+ opacity: 1;
393
+ }
394
+ :where(input, select, textarea, button):disabled {
395
+ cursor: not-allowed;
396
+ opacity: 0.5;
397
+ }
398
+ :where(input, select, textarea)[aria-invalid="true"] { border-color: var(--color-destructive); }
399
+ textarea {
400
+ min-height: 80px;
401
+ line-height: 1.5;
402
+ resize: vertical;
403
+ }
404
+ select:not([multiple], [size]) {
405
+ appearance: none;
406
+ padding-right: 32px;
407
+ background-image:
408
+ linear-gradient(45deg, transparent 50%, var(--color-muted-foreground) 50%),
409
+ linear-gradient(135deg, var(--color-muted-foreground) 50%, transparent 50%);
410
+ background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
411
+ background-size: 5px 5px;
412
+ background-repeat: no-repeat;
413
+ }
414
+ ${BUTTON_CONTROLS} {
415
+ ${BUTTON_LOOK}
416
+ }
417
+ ${BUTTON_CONTROLS}:hover:not(:disabled) {
418
+ color: var(--color-accent-foreground);
419
+ background-color: var(--color-accent);
420
+ }
421
+ ${BUTTON_CONTROLS}:focus-visible {
422
+ ${FOCUS_RING}
423
+ }
424
+ ::file-selector-button {
425
+ margin-right: 12px;
426
+ padding: 4px 10px;
427
+ font-size: 13px;
428
+ font-weight: 500;
429
+ color: var(--color-foreground);
430
+ background-color: var(--color-card);
431
+ border: 1px solid var(--color-input);
432
+ border-radius: var(--radius-sm);
433
+ cursor: pointer;
434
+ }
435
+ input[type="checkbox"], input[type="radio"], input[type="range"], progress {
436
+ accent-color: var(--color-primary);
437
+ }
438
+ fieldset {
439
+ min-width: 0;
440
+ padding: 12px 16px 16px;
441
+ border: 1px solid var(--color-border);
442
+ border-radius: var(--radius-lg);
443
+ }
444
+ legend {
445
+ padding: 0 6px;
446
+ font-size: 13px;
447
+ font-weight: 500;
448
+ color: var(--color-muted-foreground);
449
+ }
450
+ label:has(input, select, textarea), label[for] { cursor: pointer; }
451
+ ::selection {
452
+ color: var(--color-primary-foreground);
453
+ background-color: var(--color-primary);
454
+ }
455
+ }
456
+
457
+ @layer components {
458
+ .swarm-page {
459
+ max-width: 1120px;
460
+ margin-inline: auto;
461
+ padding-block: 8px 24px;
462
+ }
463
+ .swarm-eyebrow {
464
+ margin: 0 0 8px;
465
+ font-size: 11px;
466
+ font-weight: 500;
467
+ line-height: 1.45;
468
+ letter-spacing: 0.08em;
469
+ text-transform: uppercase;
470
+ color: var(--color-muted-foreground);
471
+ }
472
+ .swarm-lede {
473
+ max-width: 68ch;
474
+ margin: 0 0 16px;
475
+ font-size: 17px;
476
+ line-height: 1.55;
477
+ color: var(--color-muted-foreground);
478
+ text-wrap: pretty;
479
+ }
480
+ .swarm-section { margin-block: 40px; }
481
+ .swarm-section:last-child { margin-bottom: 0; }
482
+ .swarm-section > :first-child { margin-top: 0; }
483
+
484
+ .swarm-metrics {
485
+ display: grid;
486
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 148px), 1fr));
487
+ gap: 12px;
488
+ margin: 24px 0;
489
+ }
490
+ .swarm-metric {
491
+ display: flex;
492
+ flex-direction: column;
493
+ gap: 4px;
494
+ min-width: 0;
495
+ padding: 14px 16px;
496
+ color: var(--color-card-foreground);
497
+ background-color: var(--color-card);
498
+ border: 1px solid var(--color-border);
499
+ border-radius: var(--radius-xl);
500
+ }
501
+ .swarm-metric-value {
502
+ font-size: 26px;
503
+ font-weight: 600;
504
+ line-height: 1.15;
505
+ letter-spacing: -0.02em;
506
+ font-variant-numeric: tabular-nums;
507
+ overflow-wrap: anywhere;
508
+ }
509
+ .swarm-metric[data-tone] .swarm-metric-value { color: var(--swarm-tone-strong); }
510
+ .swarm-metric-label {
511
+ font-size: 12px;
512
+ line-height: 1.45;
513
+ color: var(--color-muted-foreground);
514
+ }
515
+
516
+ .swarm-panel, .swarm-card {
517
+ padding: 20px;
518
+ color: var(--color-card-foreground);
519
+ background-color: var(--color-card);
520
+ border: 1px solid var(--color-border);
521
+ border-radius: var(--radius-xl);
522
+ }
523
+ :is(.swarm-panel, .swarm-card) > :first-child { margin-top: 0; }
524
+ :is(.swarm-panel, .swarm-card) > :last-child { margin-bottom: 0; }
525
+
526
+ .swarm-badge {
527
+ --swarm-tone: var(--color-status-neutral);
528
+ --swarm-tone-strong: var(--color-status-neutral-strong);
529
+ display: inline-flex;
530
+ align-items: center;
531
+ gap: 6px;
532
+ height: 22px;
533
+ padding: 0 8px;
534
+ font-size: 12px;
535
+ font-weight: 500;
536
+ line-height: 1;
537
+ white-space: nowrap;
538
+ vertical-align: middle;
539
+ color: var(--swarm-tone-strong);
540
+ background-color: color-mix(in oklab, var(--swarm-tone) 16%, transparent);
541
+ border: 1px solid color-mix(in oklab, var(--swarm-tone) 28%, transparent);
542
+ border-radius: 999px;
543
+ }
544
+ .swarm-badge[data-dot]::before {
545
+ content: "";
546
+ flex: none;
547
+ width: 6px;
548
+ height: 6px;
549
+ background: var(--swarm-dot, currentColor);
550
+ border-radius: 999px;
551
+ }
552
+
553
+ .swarm-table-wrap {
554
+ max-height: min(70vh, 720px);
555
+ margin: 0 0 16px;
556
+ overflow: auto;
557
+ background:
558
+ linear-gradient(to right, var(--color-card) 30%, transparent) left / 40px 100% no-repeat local,
559
+ linear-gradient(to left, var(--color-card) 30%, transparent) right / 40px 100% no-repeat local,
560
+ linear-gradient(to right, ${EDGE_SHADOW}, transparent) left / 14px 100% no-repeat scroll,
561
+ linear-gradient(to left, ${EDGE_SHADOW}, transparent) right / 14px 100% no-repeat scroll,
562
+ var(--color-card);
563
+ border: 1px solid var(--color-border);
564
+ border-radius: var(--radius-xl);
565
+ }
566
+ .swarm-table-wrap:last-child { margin-bottom: 0; }
567
+ .swarm-table-wrap > table { margin: 0; }
568
+ .swarm-table {
569
+ width: 100%;
570
+ border-collapse: separate;
571
+ border-spacing: 0;
572
+ font-size: 13px;
573
+ line-height: 1.45;
574
+ font-variant-numeric: tabular-nums;
575
+ }
576
+ .swarm-table :is(th, td) { padding: 8px 12px; }
577
+ .swarm-table thead th {
578
+ position: sticky;
579
+ top: 0;
580
+ z-index: 1;
581
+ padding-block: 10px 8px;
582
+ white-space: nowrap;
583
+ background-color: var(--color-card);
584
+ }
585
+ .swarm-table tbody tr:hover > :is(td, th) { background-color: color-mix(in oklab, var(--color-accent) 70%, transparent); }
586
+ .swarm-table-wrap > .swarm-table > :last-child > tr:last-child > :is(td, th) { border-bottom: 0; }
587
+ :is(td, th).num {
588
+ text-align: right;
589
+ white-space: nowrap;
590
+ font-variant-numeric: tabular-nums;
591
+ }
592
+ :is(td, th).nowrap { white-space: nowrap; }
593
+ .swarm-diff-root :is(table, th, td) { margin: 0; border: 0; }
594
+
595
+ .swarm-button {
596
+ ${BUTTON_LOOK}
597
+ }
598
+ .swarm-button:hover {
599
+ color: var(--color-accent-foreground);
600
+ background-color: var(--color-accent);
601
+ }
602
+ .swarm-button[data-variant="primary"] {
603
+ color: var(--color-primary-foreground);
604
+ background-color: var(--color-primary);
605
+ border-color: transparent;
606
+ }
607
+ .swarm-button[data-variant="primary"]:hover {
608
+ color: var(--color-primary-foreground);
609
+ background-color: color-mix(in oklab, var(--color-primary) 90%, transparent);
610
+ }
611
+ .swarm-button[data-variant="ghost"] {
612
+ background-color: transparent;
613
+ border-color: transparent;
614
+ }
615
+ .swarm-button[data-variant="ghost"]:hover { background-color: var(--color-accent); }
616
+ .swarm-button:focus-visible {
617
+ ${FOCUS_RING}
618
+ }
619
+ .swarm-button:is(:disabled, [aria-disabled="true"]) {
620
+ opacity: 0.5;
621
+ pointer-events: none;
622
+ }
623
+
624
+ .swarm-input {
625
+ ${CONTROL_LOOK}
626
+ }
627
+ .swarm-input:focus-visible {
628
+ ${FOCUS_RING}
629
+ }
630
+ select.swarm-input:not([multiple], [size]) { padding-right: 32px; }
631
+
632
+ .swarm-toolbar {
633
+ display: flex;
634
+ flex-wrap: wrap;
635
+ align-items: center;
636
+ gap: 8px;
637
+ margin: 0 0 12px;
638
+ }
639
+ .swarm-toolbar > :is(input[type="search"], input[type="text"], input:not([type])) { flex: 1 1 260px; }
640
+
641
+ .swarm-segmented {
642
+ display: inline-flex;
643
+ align-items: center;
644
+ gap: 2px;
645
+ height: 36px;
646
+ padding: 2px;
647
+ vertical-align: middle;
648
+ background-color: color-mix(in oklab, var(--color-muted) 40%, transparent);
649
+ border: 1px solid var(--color-border);
650
+ border-radius: var(--radius-md);
651
+ }
652
+ .swarm-segmented > :is(button, a) {
653
+ display: inline-flex;
654
+ align-items: center;
655
+ justify-content: center;
656
+ gap: 6px;
657
+ height: 100%;
658
+ padding: 0 12px;
659
+ font-size: 12px;
660
+ font-weight: 500;
661
+ line-height: 1;
662
+ white-space: nowrap;
663
+ text-decoration: none;
664
+ color: var(--color-muted-foreground);
665
+ background-color: transparent;
666
+ border: 0;
667
+ border-radius: calc(var(--radius-md) - 3px);
668
+ box-shadow: none;
669
+ cursor: pointer;
670
+ transition: color 150ms, background-color 150ms;
671
+ }
672
+ .swarm-segmented > :is(button, a):hover {
673
+ color: var(--color-foreground);
674
+ background-color: transparent;
675
+ }
676
+ .swarm-segmented > :is([aria-pressed="true"], [data-active]:not([data-active="false"])) {
677
+ color: var(--color-primary-foreground);
678
+ background-color: var(--color-primary);
679
+ }
680
+ .swarm-segmented > :is(button, a):focus-visible {
681
+ outline: none;
682
+ box-shadow: 0 0 0 2px color-mix(in oklab, var(--color-ring) 60%, transparent);
683
+ }
684
+
685
+ .swarm-callout {
686
+ --swarm-tone: var(--color-status-info);
687
+ --swarm-tone-strong: var(--color-status-info-strong);
688
+ margin: 0 0 12px;
689
+ padding: 12px 16px;
690
+ color: var(--color-foreground);
691
+ background-color: color-mix(in oklab, var(--swarm-tone) 12%, transparent);
692
+ border: 1px solid color-mix(in oklab, var(--swarm-tone) 40%, transparent);
693
+ border-radius: var(--radius-lg);
694
+ }
695
+ .swarm-callout:last-child { margin-bottom: 0; }
696
+ .swarm-callout > :first-child { margin-top: 0; }
697
+ .swarm-callout > :last-child { margin-bottom: 0; }
698
+
699
+ .swarm-kv {
700
+ display: grid;
701
+ grid-template-columns: minmax(96px, max-content) minmax(0, 1fr);
702
+ gap: 8px 20px;
703
+ margin: 0 0 16px;
704
+ font-size: 14px;
705
+ }
706
+ .swarm-kv:last-child { margin-bottom: 0; }
707
+ .swarm-kv > dt {
708
+ font-weight: 400;
709
+ color: var(--color-muted-foreground);
710
+ }
711
+ .swarm-kv > dd {
712
+ min-width: 0;
713
+ margin: 0;
714
+ overflow-wrap: anywhere;
715
+ }
716
+
717
+ ${TONE_RULES}
718
+ }
719
+
720
+ @media print {
721
+ html, body { background: white !important; color: black !important; }
722
+ a:not(.swarm-button) { color: black !important; text-decoration: underline; }
723
+ .no-print { display: none !important; }
724
+ .swarm-panel, .swarm-card, swarm-diff, .swarm-metric { break-inside: avoid; }
725
+ .swarm-table-wrap { max-height: none; overflow: visible; }
726
+ .swarm-table { font-size: 12px; }
727
+ .swarm-table :is(th, td):not(.num) { white-space: normal; }
728
+ .swarm-table thead th { position: static; }
729
+ tfoot { display: table-row-group; }
730
+ }`;
731
+
732
+ /**
733
+ * The design version 2 head. Order matters:
734
+ * 1. `<base>` so links escape the iframe, and the click handler that keeps
735
+ * in-page `#id` links in the page.
736
+ * 2. The layer order statement, as the FIRST style element: layers rank by
737
+ * first mention, so base < components < Tailwind utilities, whatever order
738
+ * the sheets load in. Unlayered CSS (the theme, the page's own styles)
739
+ * beats every layer.
740
+ * 3. Fonts. 4. Theme tokens (unlayered). 5. Element defaults and primitives.
741
+ * 6. The Tailwind source, before the script, so the first compile already
742
+ * skips Preflight. A script creates its `text/tailwindcss` style element:
743
+ * the browser preload scanner reads `@import` in any `<style>` in the
744
+ * markup, whatever its type, and would fetch `tailwindcss/theme` relative
745
+ * to the page. 7. The pinned Tailwind script (SRI).
746
+ * 8. In dark mode, the `.dark` class, set before the body renders.
747
+ */
748
+ export function buildPageHeadV2({
749
+ theme,
750
+ mode,
751
+ }: {
752
+ theme: ResolvedPageTheme;
753
+ mode: "light" | "dark";
754
+ }): string {
755
+ return [
756
+ '<base target="_blank">',
757
+ IN_PAGE_LINK_SCRIPT,
758
+ "<style>@layer properties, theme, base, components, utilities;</style>",
759
+ FONT_LINKS,
760
+ `<style id="swarm-theme">\n${renderPageThemeCss(theme)}\n</style>`,
761
+ `<style id="swarm-design">\n${PAGE_DESIGN_CSS}\n</style>`,
762
+ TAILWIND_SOURCE_SCRIPT,
763
+ `<script src="${TAILWIND_BROWSER_SRC}" integrity="${TAILWIND_BROWSER_INTEGRITY}" crossorigin="anonymous"></script>`,
764
+ ...(mode === "dark" ? ['<script>document.documentElement.classList.add("dark")</script>'] : []),
765
+ ].join("\n");
766
+ }