synabun 2.0.10 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (517) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +25 -2
  3. package/THIRD-PARTY-LICENSES.md +22 -0
  4. package/bin/synabun.js +71 -24
  5. package/docs/whatsapp.md +2 -2
  6. package/hooks/claude-code/pre-websearch.mjs +12 -1
  7. package/hooks/claude-code/shared.mjs +5 -0
  8. package/hooks/claude-code/stop.mjs +1 -1
  9. package/lib/claude-hooks.js +172 -18
  10. package/lib/client-config-repair.js +17 -8
  11. package/lib/desktop-app.js +7 -1
  12. package/lib/external-tools.js +1 -1
  13. package/lib/first-launch-protection.js +57 -12
  14. package/lib/mcp-dist.js +176 -0
  15. package/lib/release-npm-ci.mjs +138 -0
  16. package/lib/release-publish.mjs +91 -0
  17. package/lib/release-scan.mjs +50 -0
  18. package/lib/server-crash-record.js +123 -0
  19. package/lib/server-exit.js +318 -0
  20. package/lib/server-supervisor.js +508 -0
  21. package/lib/start-launcher.js +37 -4
  22. package/lib/tools-cli.js +45 -0
  23. package/lib/update-snapshot.js +228 -0
  24. package/lib/virustotal.mjs +192 -0
  25. package/lib/windows-crash-event.js +269 -0
  26. package/mcp-server/dist/http.d.ts +20 -1
  27. package/mcp-server/dist/http.d.ts.map +1 -1
  28. package/mcp-server/dist/http.js +59 -12
  29. package/mcp-server/dist/http.js.map +1 -1
  30. package/mcp-server/dist/index.d.ts +33 -27
  31. package/mcp-server/dist/index.d.ts.map +1 -1
  32. package/mcp-server/dist/index.js +128 -143
  33. package/mcp-server/dist/index.js.map +1 -1
  34. package/mcp-server/dist/preload.js +1 -1
  35. package/mcp-server/dist/preload.js.map +1 -1
  36. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  37. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  38. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  39. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  40. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  41. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  42. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  43. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  44. package/mcp-server/dist/services/neural-interface.d.ts +16 -10
  45. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  46. package/mcp-server/dist/services/neural-interface.js +67 -11
  47. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  48. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  49. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  50. package/mcp-server/dist/services/server-instructions.js +20 -62
  51. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  52. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  53. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  54. package/mcp-server/dist/services/tool-catalog.js +339 -0
  55. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  56. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  57. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  58. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  59. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  60. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  61. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  62. package/mcp-server/dist/services/tool-list.js +334 -0
  63. package/mcp-server/dist/services/tool-list.js.map +1 -0
  64. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  65. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  66. package/mcp-server/dist/services/tool-runtime.js +400 -0
  67. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  68. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  69. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  70. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  71. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  72. package/mcp-server/dist/tools/agents.d.ts +10 -10
  73. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  74. package/mcp-server/dist/tools/agents.js +22 -13
  75. package/mcp-server/dist/tools/agents.js.map +1 -1
  76. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  77. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  78. package/mcp-server/dist/tools/image-tools.js +1 -1
  79. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  80. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  81. package/mcp-server/dist/tools/skill-tools.js +639 -0
  82. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  83. package/mcp-server/dist/tools/skill.d.ts +7 -0
  84. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  85. package/mcp-server/dist/tools/skill.js +11 -0
  86. package/mcp-server/dist/tools/skill.js.map +1 -0
  87. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  88. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  89. package/mcp-server/dist/tools/tool-groups.js +147 -0
  90. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  91. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  92. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  93. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  94. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  95. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  96. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  97. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  98. package/mcp-server/package-lock.json +2 -2
  99. package/mcp-server/package.json +1 -1
  100. package/mcp-server/src/http.ts +75 -12
  101. package/mcp-server/src/index.ts +147 -154
  102. package/mcp-server/src/preload.ts +12 -12
  103. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  104. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  105. package/mcp-server/src/services/neural-interface.ts +79 -20
  106. package/mcp-server/src/services/server-instructions.ts +27 -63
  107. package/mcp-server/src/services/tool-catalog.ts +403 -0
  108. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  109. package/mcp-server/src/services/tool-list.ts +410 -0
  110. package/mcp-server/src/services/tool-runtime.ts +457 -0
  111. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  112. package/mcp-server/src/tools/agents.ts +22 -14
  113. package/mcp-server/src/tools/image-tools.ts +1 -1
  114. package/mcp-server/src/tools/skill-tools.ts +589 -0
  115. package/mcp-server/src/tools/skill.ts +13 -0
  116. package/mcp-server/src/tools/tool-groups.ts +164 -0
  117. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  118. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  119. package/neural-interface/i18n/en.json +3463 -200
  120. package/neural-interface/i18n/pt-BR.json +3411 -151
  121. package/neural-interface/lib/assistant-api.js +127 -28
  122. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  123. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  124. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  125. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  126. package/neural-interface/lib/assistant-brains/opencode.js +120 -54
  127. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
  128. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
  129. package/neural-interface/lib/assistant-catalog.js +6 -7
  130. package/neural-interface/lib/assistant-dispatch.js +871 -156
  131. package/neural-interface/lib/assistant-envelope.js +3 -1
  132. package/neural-interface/lib/assistant-persona.js +80 -11
  133. package/neural-interface/lib/assistant-plan-permissions.js +10 -9
  134. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  135. package/neural-interface/lib/assistant-route-gate.js +6 -4
  136. package/neural-interface/lib/assistant-router.js +13 -8
  137. package/neural-interface/lib/assistant-runtime.js +56 -18
  138. package/neural-interface/lib/assistant-task-prompt.js +78 -14
  139. package/neural-interface/lib/assistant-tools.js +51 -0
  140. package/neural-interface/lib/backup-service.js +620 -3
  141. package/neural-interface/lib/backup-zip-reader.js +10 -5
  142. package/neural-interface/lib/backup-zip-writer.js +257 -0
  143. package/neural-interface/lib/browser-execution.js +10 -2
  144. package/neural-interface/lib/browser-guard-cdp.js +83 -0
  145. package/neural-interface/lib/browser-network-guard.js +284 -0
  146. package/neural-interface/lib/browser-policy-roots.js +64 -0
  147. package/neural-interface/lib/browser-tool-policy.js +186 -31
  148. package/neural-interface/lib/claude-agent-bridge.js +4 -2
  149. package/neural-interface/lib/claude-hooks-status.js +103 -0
  150. package/neural-interface/lib/claude-temporary.js +5 -11
  151. package/neural-interface/lib/cli-install.js +18 -138
  152. package/neural-interface/lib/cli-resolver.js +4 -1
  153. package/neural-interface/lib/cli-update-planner.js +32 -31
  154. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  155. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  156. package/neural-interface/lib/codex-worker-app-server.js +172 -0
  157. package/neural-interface/lib/confined-fs.js +30 -3
  158. package/neural-interface/lib/crash-notice-api.js +98 -0
  159. package/neural-interface/lib/editor-completion-opencode.js +68 -68
  160. package/neural-interface/lib/exec-loop-command.js +4 -8
  161. package/neural-interface/lib/http-guards.js +8 -2
  162. package/neural-interface/lib/install-details.js +4 -1
  163. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  164. package/neural-interface/lib/mcp-client-config.js +0 -29
  165. package/neural-interface/lib/mcp-external-servers.js +323 -0
  166. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  167. package/neural-interface/lib/morelogin.js +30 -0
  168. package/neural-interface/lib/native-loop-providers.js +547 -47
  169. package/neural-interface/lib/native-loop-runtime.js +268 -41
  170. package/neural-interface/lib/opencode-config.js +557 -0
  171. package/neural-interface/lib/opencode-db-schema.js +17 -34
  172. package/neural-interface/lib/opencode-history.js +48 -218
  173. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  174. package/neural-interface/lib/opencode-native-boundary.js +44 -0
  175. package/neural-interface/lib/opencode-protocol.js +249 -112
  176. package/neural-interface/lib/opencode-runtime-config.js +32 -22
  177. package/neural-interface/lib/opencode-serve-records.js +39 -21
  178. package/neural-interface/lib/opencode-v2-client.js +48 -153
  179. package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
  180. package/neural-interface/lib/opencode-worker-data.js +27 -0
  181. package/neural-interface/lib/opencode2-client.js +73 -37
  182. package/neural-interface/lib/opencode2-proxy.js +23 -63
  183. package/neural-interface/lib/opencode2-translate.js +51 -2
  184. package/neural-interface/lib/owner-authority.js +249 -0
  185. package/neural-interface/lib/page-session.js +275 -0
  186. package/neural-interface/lib/peer-identity.js +763 -0
  187. package/neural-interface/lib/request-gate.js +17 -2
  188. package/neural-interface/lib/rulesets/api.js +1 -1
  189. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  190. package/neural-interface/lib/rulesets/installer.js +92 -27
  191. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  192. package/neural-interface/lib/session-cache-builder.js +17 -30
  193. package/neural-interface/lib/session-title-generator.js +58 -36
  194. package/neural-interface/lib/skills/api-v2.js +495 -0
  195. package/neural-interface/lib/skills/bundle.js +418 -0
  196. package/neural-interface/lib/skills/catalog.js +294 -0
  197. package/neural-interface/lib/skills/creation-api.js +191 -0
  198. package/neural-interface/lib/skills/creation-brief.js +247 -0
  199. package/neural-interface/lib/skills/creation-sources.js +267 -0
  200. package/neural-interface/lib/skills/creation.js +843 -0
  201. package/neural-interface/lib/skills/deploy.js +564 -0
  202. package/neural-interface/lib/skills/digest.js +119 -0
  203. package/neural-interface/lib/skills/discover.js +111 -0
  204. package/neural-interface/lib/skills/draft-confinement.js +214 -0
  205. package/neural-interface/lib/skills/eval-confinement.js +397 -0
  206. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  207. package/neural-interface/lib/skills/eval-trace.js +119 -0
  208. package/neural-interface/lib/skills/evals-api.js +212 -0
  209. package/neural-interface/lib/skills/evals.js +1573 -0
  210. package/neural-interface/lib/skills/export.js +200 -0
  211. package/neural-interface/lib/skills/frontmatter.js +64 -0
  212. package/neural-interface/lib/skills/health.js +75 -0
  213. package/neural-interface/lib/skills/json-edit.js +165 -0
  214. package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
  215. package/neural-interface/lib/skills/known-bridges.js +96 -0
  216. package/neural-interface/lib/skills/library.js +823 -0
  217. package/neural-interface/lib/skills/local-store.js +21 -0
  218. package/neural-interface/lib/skills/migration.js +433 -0
  219. package/neural-interface/lib/skills/operations.js +45 -0
  220. package/neural-interface/lib/skills/ownership.js +427 -0
  221. package/neural-interface/lib/skills/packages.js +88 -0
  222. package/neural-interface/lib/skills/reviews.js +212 -0
  223. package/neural-interface/lib/skills/revision.js +80 -0
  224. package/neural-interface/lib/skills/roots.js +262 -0
  225. package/neural-interface/lib/skills/runtime-checks.js +355 -0
  226. package/neural-interface/lib/skills/scan-assets.js +252 -0
  227. package/neural-interface/lib/skills/scan-context.js +26 -0
  228. package/neural-interface/lib/skills/scan-shell.js +324 -0
  229. package/neural-interface/lib/skills/scan.js +364 -0
  230. package/neural-interface/lib/skills/scanners.js +54 -0
  231. package/neural-interface/lib/skills/service.js +522 -0
  232. package/neural-interface/lib/skills/telemetry.js +113 -0
  233. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  234. package/neural-interface/lib/tool-lists.js +124 -0
  235. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  236. package/neural-interface/lib/worker-confinement.js +1192 -0
  237. package/neural-interface/lib/worker-guard-setting.js +56 -0
  238. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  239. package/neural-interface/lib/worker-relay-ports.js +227 -0
  240. package/neural-interface/lib/worker-resume.js +229 -0
  241. package/neural-interface/lib/worker-sandbox.js +299 -0
  242. package/neural-interface/package-lock.json +18 -12
  243. package/neural-interface/package.json +2 -2
  244. package/neural-interface/public/index.html +3 -1
  245. package/neural-interface/public/index2d.html +19 -11
  246. package/neural-interface/public/onboarding.html +2 -2
  247. package/neural-interface/public/shared/account-menu.js +8 -5
  248. package/neural-interface/public/shared/agent-runtime-options.js +35 -19
  249. package/neural-interface/public/shared/api.js +1527 -1336
  250. package/neural-interface/public/shared/app-frame.js +192 -0
  251. package/neural-interface/public/shared/assistant/asst-agents-dock.js +33 -2
  252. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  253. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  254. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  255. package/neural-interface/public/shared/assistant/asst-brain-picker.js +49 -35
  256. package/neural-interface/public/shared/assistant/asst-control.js +157 -26
  257. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  258. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  259. package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
  260. package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
  261. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  262. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  263. package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
  264. package/neural-interface/public/shared/assistant/asst-panel.js +106 -11
  265. package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
  266. package/neural-interface/public/shared/assistant/asst-render.js +401 -77
  267. package/neural-interface/public/shared/assistant/asst-route.js +83 -12
  268. package/neural-interface/public/shared/assistant/asst-scenes.js +2 -0
  269. package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
  270. package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
  271. package/neural-interface/public/shared/assistant/asst-state.js +11 -15
  272. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  273. package/neural-interface/public/shared/assistant/asst-styles.js +59 -21
  274. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +156 -16
  275. package/neural-interface/public/shared/automation-context.js +5 -2
  276. package/neural-interface/public/shared/cc-dropdown.js +89 -19
  277. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  278. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  279. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  280. package/neural-interface/public/shared/cdx/cdx-output.js +8 -7
  281. package/neural-interface/public/shared/cdx/cdx-panel.js +45 -149
  282. package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
  283. package/neural-interface/public/shared/cdx/cdx-render.js +47 -29
  284. package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
  285. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  286. package/neural-interface/public/shared/cdx/cdx-styles.js +11 -3
  287. package/neural-interface/public/shared/cdx/cdx-tabs.js +52 -39
  288. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  289. package/neural-interface/public/shared/cli-install-view.js +4 -8
  290. package/neural-interface/public/shared/cli-status.js +2 -2
  291. package/neural-interface/public/shared/constants.js +2 -2
  292. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  293. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  294. package/neural-interface/public/shared/context-menu-model.js +366 -0
  295. package/neural-interface/public/shared/context-menu.js +372 -0
  296. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  297. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  298. package/neural-interface/public/shared/desktop-update-view.js +20 -0
  299. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  300. package/neural-interface/public/shared/html-shell.js +9 -11
  301. package/neural-interface/public/shared/i18n.js +2 -0
  302. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  303. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  304. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  305. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
  306. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  307. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  308. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  309. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  310. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  311. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  312. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  313. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +47 -252
  314. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  315. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
  316. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +6 -21
  317. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
  318. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  319. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
  320. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  321. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  322. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  323. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  324. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +0 -21
  325. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  326. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +14 -47
  327. package/neural-interface/public/shared/page-session.js +96 -0
  328. package/neural-interface/public/shared/registry.js +5 -3
  329. package/neural-interface/public/shared/retired-2d.js +3 -0
  330. package/neural-interface/public/shared/schedules-view.js +195 -61
  331. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  332. package/neural-interface/public/shared/settings/settings-data.js +3 -1
  333. package/neural-interface/public/shared/settings/settings-ia.js +6 -6
  334. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  335. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  336. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  337. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  338. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  339. package/neural-interface/public/shared/skills/ss-creation.js +219 -0
  340. package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
  341. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  342. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  343. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  344. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  345. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  346. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  347. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  348. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  349. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  350. package/neural-interface/public/shared/skills/ss-lint.js +141 -0
  351. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  352. package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
  353. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  354. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  355. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  356. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  357. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  358. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  359. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  360. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
  361. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  362. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  363. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  364. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  365. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  366. package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
  367. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  368. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  369. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  370. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  371. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  372. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  373. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
  374. package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
  375. package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
  376. package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
  377. package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
  378. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  379. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  380. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  381. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  382. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  383. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  384. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  385. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  386. package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
  387. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  388. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  389. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  390. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
  391. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  392. package/neural-interface/public/shared/styles.css +1525 -1779
  393. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  394. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  395. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  396. package/neural-interface/public/shared/tool-list-view.js +112 -0
  397. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  398. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  399. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  400. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  401. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  402. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  403. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  404. package/neural-interface/public/shared/tour/tour.css +144 -0
  405. package/neural-interface/public/shared/ui-automation-studio.js +91 -128
  406. package/neural-interface/public/shared/ui-claude-panel.js +77 -5
  407. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  408. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  409. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  410. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  411. package/neural-interface/public/shared/ui-detail.js +15 -3
  412. package/neural-interface/public/shared/ui-image-gallery.js +50 -47
  413. package/neural-interface/public/shared/ui-keybinds.js +26 -1
  414. package/neural-interface/public/shared/ui-menubar.js +8 -18
  415. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  416. package/neural-interface/public/shared/ui-native-loop-router.js +7 -1
  417. package/neural-interface/public/shared/ui-navbar.js +4 -24
  418. package/neural-interface/public/shared/ui-panels.js +96 -65
  419. package/neural-interface/public/shared/ui-schedules-studio.js +507 -423
  420. package/neural-interface/public/shared/ui-sessions.js +5 -3
  421. package/neural-interface/public/shared/ui-settings.js +594 -462
  422. package/neural-interface/public/shared/ui-sidepanel-sessions.js +1 -1
  423. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  424. package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
  425. package/neural-interface/public/shared/ui-skills.js +33 -2830
  426. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  427. package/neural-interface/public/shared/ui-sync.js +15 -5
  428. package/neural-interface/public/shared/ui-terminal.js +124 -180
  429. package/neural-interface/public/shared/ui-tool-updates.js +3 -1
  430. package/neural-interface/public/shared/ui-tooltip.js +10 -5
  431. package/neural-interface/public/shared/ui-trash.js +6 -4
  432. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  433. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  434. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
  435. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  436. package/neural-interface/public/shared/ui-tutorial.js +285 -509
  437. package/neural-interface/public/shared/ui-update.js +38 -2
  438. package/neural-interface/public/shared/ui-whiteboard.js +311 -58
  439. package/neural-interface/public/shared/ui-worker-end.js +4 -0
  440. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  441. package/neural-interface/public/shared/view-variant.js +66 -0
  442. package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
  443. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  444. package/neural-interface/public/shared/worker-end.js +10 -3
  445. package/neural-interface/public/shared/worker-restart.js +12 -0
  446. package/neural-interface/public/sidepanel-session.html +1 -1
  447. package/neural-interface/public/variant/2d/background.js +2 -1
  448. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  449. package/neural-interface/public/variant/2d/graph.js +42 -20
  450. package/neural-interface/public/variant/2d/hulls.js +14 -9
  451. package/neural-interface/public/variant/2d/lasso.js +11 -7
  452. package/neural-interface/public/variant/2d/main.js +32 -1
  453. package/neural-interface/public/variant/2d/minimap.js +11 -13
  454. package/neural-interface/public/variant/3d/main.js +69 -6
  455. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  456. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  457. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  458. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  459. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  460. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  461. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  462. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  463. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  464. package/neural-interface/scripts/build-vendor.mjs +32 -0
  465. package/neural-interface/server.js +3934 -2454
  466. package/neural-interface/templates/rulesets/core.md +1 -1
  467. package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
  468. package/neural-interface/templates/rulesets/manifest.json +8 -8
  469. package/npm-shrinkwrap.json +18 -12
  470. package/package.json +16 -3
  471. package/postinstall.js +9 -4
  472. package/preuninstall.js +1 -1
  473. package/setup.js +97 -322
  474. package/skills/skill-forge/SKILL.md +177 -0
  475. package/skills/skill-forge/evals/evals.json +54 -0
  476. package/skills/skill-forge/references/package.md +105 -0
  477. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  478. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  479. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  480. package/skills/synabun/SKILL.md +10 -7
  481. package/skills/synabun/modules/audit.md +1 -5
  482. package/skills/synabun/modules/changelog.md +1 -5
  483. package/skills/synabun/modules/idea.md +1 -1
  484. package/skills/synabun/modules/memorize.md +6 -9
  485. package/skills/synabun/modules/schedule.md +4 -4
  486. package/mcp-server/dist/services/profiles.d.ts +0 -120
  487. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  488. package/mcp-server/dist/services/profiles.js +0 -387
  489. package/mcp-server/dist/services/profiles.js.map +0 -1
  490. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  491. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  492. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  493. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  494. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  495. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  496. package/mcp-server/dist/tools/leonardo.js +0 -21
  497. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  498. package/mcp-server/dist/tools/profile.d.ts +0 -17
  499. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  500. package/mcp-server/dist/tools/profile.js +0 -114
  501. package/mcp-server/dist/tools/profile.js.map +0 -1
  502. package/mcp-server/src/services/profiles.ts +0 -428
  503. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  504. package/mcp-server/src/tools/leonardo.ts +0 -30
  505. package/mcp-server/src/tools/profile.ts +0 -122
  506. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  507. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  508. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  509. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  510. package/skills/leonardo/SKILL.md +0 -168
  511. package/skills/leonardo/icon.svg +0 -1
  512. package/skills/leonardo/modules/browser-guide.md +0 -378
  513. package/skills/leonardo/modules/image-prompter.md +0 -283
  514. package/skills/leonardo/modules/model-advisor.md +0 -100
  515. package/skills/leonardo/modules/prompt-library.md +0 -110
  516. package/skills/leonardo/modules/style-guide.md +0 -186
  517. package/skills/leonardo/modules/video-prompter.md +0 -317
@@ -345,32 +345,62 @@ export function injectAssistantStyles() {
345
345
  .asst-transcript > .asst-status + .asst-status,
346
346
  .asst-transcript > .asst-route-line + .asst-route-line { margin-top: 4px; }
347
347
  .asst-transcript > .asst-working { margin-top: 8px; }
348
+ /* The open card waits at the bottom (asst-ask-tail.js): under every row that arrives after it,
349
+ above the "Working…" row, until it is answered and goes back under its message. */
350
+ .asst-ask-tail { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
351
+ .asst-ask-tail > * { margin-top: 0; }
352
+ /* The card sheet is injected after this one: restate its own gap margin at its specificity. */
353
+ .asst-ask-tail > .asst-followups.asst-ask,
354
+ .asst-ask-tail > .asst-control.asst-ask { margin-top: 0; }
348
355
 
349
- /* ── Empty state ────────────────────────────────────────────────── */
356
+ /* ── Empty state ────────────────────────────────────────────────────
357
+ One column, one hierarchy: the character and the heading, then the
358
+ starters as ghost rows (a prop glyph and a label, no capsule and no
359
+ seam: a faint fill with the md corners only while hovered or
360
+ focused), then the context line (Project · Budget) as quiet sm text
361
+ controls that open the toolbar's own menus (an open menu alone
362
+ wears the gold on-state). The rows and the line come in staggered
363
+ (--i, 40 ms apart), recede while the composer holds a draft, and
364
+ the picked starter keeps the gold on-state until the draft is
365
+ cleared. All of it static under reduced motion (the blanket at the
366
+ end). */
350
367
  .asst-empty {
351
368
  display: flex;
352
369
  flex-direction: column;
353
370
  align-items: center;
354
371
  justify-content: center;
355
- gap: 10px;
372
+ gap: 6px;
356
373
  min-height: 100%;
357
374
  padding: 16px 4px;
358
375
  text-align: center;
359
376
  }
360
- .asst-empty-title { color: var(--asst-text); font-family: var(--ff-heading, inherit); font-size: 20px; font-weight: 600; letter-spacing: -.01em; }
361
- .asst-empty-body { max-width: 440px; color: var(--asst-text-3); font-size: 13px; line-height: 1.55; }
362
- /* The greeting (public/shared/greeting/) takes the lead's place when there is one. */
377
+ @keyframes asst-empty-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
378
+ .asst-empty-title { margin-bottom: 8px; color: var(--asst-text); font-family: var(--ff-heading, inherit); font-size: 20px; font-weight: 600; letter-spacing: -.01em; animation: asst-empty-in var(--asst-dur-moderate) var(--asst-ease-enter) backwards; }
379
+ /* The greeting (public/shared/greeting/) sits between the heading and the starters. */
363
380
  .asst-empty-greet { display: contents; }
364
- .asst-empty.has-greeting .asst-empty-body { display: none; }
365
- .asst-suggestions { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; max-width: 560px; margin-top: 6px; }
366
- .asst-chip.asst-suggestion { --cap-h: var(--asst-pill-h-md); --cap-r: var(--asst-pill-r-md); --cap-px: var(--asst-pill-px-md); --cap-fs: 12px; justify-content: flex-start; text-align: left; }
381
+ .asst-suggestions { display: flex; flex-direction: column; align-items: stretch; gap: 2px; width: min(100%, 380px); margin-top: 2px; }
382
+ .asst-chip.asst-suggestion { --cap-h: var(--asst-pill-h-md); --cap-r: var(--asst-pill-r-md); --cap-px: var(--asst-pill-px-md); --cap-fs: 12.5px; --cap-gap: 10px; justify-content: flex-start; max-width: none; height: auto; min-height: var(--cap-h); padding: 5px var(--cap-px); background: transparent; box-shadow: none; color: var(--asst-text-2); text-align: left; white-space: normal; line-height: 1.3; animation: asst-empty-in var(--asst-dur-moderate) var(--asst-ease-enter) backwards; animation-delay: calc(var(--i, 0) * 40ms); }
383
+ .asst-chip.asst-suggestion .asst-chip-text { white-space: normal; overflow: visible; text-overflow: clip; }
367
384
  .asst-chip.asst-suggestion > .asst-icon svg { width: 20px; height: 14px; }
368
- .asst-chip.asst-suggestion > .asst-icon { color: var(--asst-text-3); }
369
- .asst-chip.asst-suggestion:is(:hover, :focus-visible) > .asst-icon { color: var(--asst-text); }
370
- /* Project and Budget: shared md capsules under the lead, like the suggestions. */
371
- .asst-empty-project { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; max-width: 100%; }
372
- .asst-dd.asst-empty-control-btn { max-width: min(100%, 360px); }
373
- .asst-empty-control-btn .asst-dd-label { max-width: 30ch; }
385
+ .asst-suggestions .asst-chip.asst-suggestion > .asst-icon:not([hidden]) { margin: 0; padding: 0; box-shadow: none; color: var(--asst-text-3); }
386
+ .asst-suggestions .asst-chip.asst-suggestion:is(:hover, :focus-visible) { background: var(--asst-fill-1); box-shadow: none; color: var(--asst-text); }
387
+ .asst-suggestions .asst-chip.asst-suggestion:is(:hover, :focus-visible) > .asst-icon { box-shadow: none; color: var(--asst-text); }
388
+ .asst-suggestions .asst-chip.asst-suggestion.is-picked { background: var(--asst-pill-on-fill); box-shadow: inset 0 0 0 1px var(--asst-pill-on-ring); color: var(--asst-text); }
389
+ .asst-suggestions .asst-chip.asst-suggestion.is-picked > .asst-icon { color: var(--asst-brand); }
390
+ .asst-empty.is-drafting .asst-chip.asst-suggestion:not(.is-picked):not(:hover):not(:focus-visible) { opacity: .55; }
391
+ /* A starter's quiet aside (the Workspace tour's "· 2 min"): the row's own font, the faint tone. */
392
+ .asst-suggestions .asst-chip.asst-suggestion .asst-chip-meta { flex-shrink: 0; margin-left: 2px; color: var(--asst-text-4); font: inherit; font-size: 11.5px; white-space: nowrap; }
393
+ .asst-suggestions .asst-chip.asst-suggestion .asst-chip-meta::before { content: '· '; }
394
+ /* The context line: the toolbar's Project field drawn once more, and Budget, as quiet sm text controls. */
395
+ .asst-empty-project { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 2px 8px; max-width: 100%; margin-top: 10px; animation: asst-empty-in var(--asst-dur-moderate) var(--asst-ease-enter) backwards; animation-delay: calc(var(--i, 0) * 40ms); }
396
+ .asst-empty-project .asst-dd.asst-empty-control-btn { --cap-h: var(--asst-pill-h-sm); --cap-r: var(--asst-pill-r-sm); --cap-px: var(--asst-pill-px-xs); --cap-gap: 4px; --cap-icon: 12px; --cap-fs: 11.5px; isolation: isolate; max-width: min(100%, 320px); color: var(--asst-text-2); }
397
+ .asst-empty-project .asst-dd.asst-empty-control-btn::after { content: ''; position: absolute; inset: -2px; z-index: -1; border-radius: inherit; }
398
+ .asst-empty-project .asst-dd.asst-empty-control-btn:not([aria-expanded="true"]) { background: transparent; box-shadow: none; }
399
+ .asst-empty-project .asst-dd.asst-empty-control-btn:hover:not([aria-expanded="true"]) { background: var(--asst-fill-1); color: var(--asst-text); }
400
+ .asst-empty-project .asst-dd.asst-empty-control-btn[aria-expanded="true"] { color: var(--asst-text); }
401
+ .asst-empty-project .asst-dd.asst-empty-control-btn > .asst-icon:not([hidden]) { margin: 0; padding: 0; box-shadow: none; color: var(--asst-text-3); }
402
+ .asst-empty-project .asst-dd.asst-empty-control-btn:is(:hover, [aria-expanded="true"]) > .asst-icon:not([hidden]) { box-shadow: none; }
403
+ .asst-empty-project .asst-dd.asst-empty-control-btn .asst-dd-label { max-width: 24ch; }
374
404
  .asst-empty-project-key { flex-shrink: 0; color: var(--asst-text-3); font-weight: 400; }
375
405
 
376
406
  /* ── Messages ───────────────────────────────────────────────────── */
@@ -998,6 +1028,12 @@ export function injectAssistantStyles() {
998
1028
  .asst-usage-run-tokens { color: var(--asst-text-3); font-family: var(--asst-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
999
1029
 
1000
1030
  /* The provider's usage limit: one line under the gauge, replaced in place (never a transcript row). */
1031
+ .asst-route-fields { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
1032
+ .asst-route-fields .asst-dd { min-width: 0; max-width: 100%; }
1033
+ .asst-route-fields .asst-dd-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
1034
+ .asst-limit-dock { position: sticky; bottom: 0; flex: none; z-index: 2; background: var(--asst-bg); }
1035
+ .asst-limit-dock[hidden] { display: none; }
1036
+ .asst-limit-dock .asst-limit-wait { margin: 8px 12px; }
1001
1037
  .asst-limit {
1002
1038
  flex: 0 0 auto;
1003
1039
  display: flex;
@@ -1327,6 +1363,8 @@ export function injectAssistantStyles() {
1327
1363
  .asst-control-plan-body { min-width: 0; }
1328
1364
  .asst-control-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
1329
1365
 
1366
+ /* Follow-ups and the question cards are drawn by the mascot: their sheet is asst-ask-styles.js. */
1367
+
1330
1368
  /* Route card */
1331
1369
  .asst-route-summary { color: var(--asst-text); }
1332
1370
  .asst-route-reasons { margin-top: -4px; color: var(--asst-text-3); font-size: 11.5px; }
@@ -1399,6 +1437,8 @@ export function injectAssistantStyles() {
1399
1437
  /* Deny / Decline: a neutral ghost with ✕ (red only ever means failed). */
1400
1438
  .asst-btn-danger { background: transparent; box-shadow: inset 0 0 0 1px var(--asst-line-2); color: var(--asst-text-2); }
1401
1439
  .asst-btn-danger:hover:not(:disabled) { background: var(--asst-fill-1); box-shadow: inset 0 0 0 1px var(--asst-text-3); color: var(--asst-text); }
1440
+ /* "Stop all" armed: it waits for a second press (asst-agents-dock.js), in the attention tone. */
1441
+ .asst-dock-stopall[data-armed="true"], .asst-dock-stopall[data-armed="true"]:hover:not(:disabled) { background: var(--asst-fill-1); box-shadow: inset 0 0 0 1px var(--asst-pill-warn-ring); color: var(--asst-warn); }
1402
1442
  .asst-btn-icon { display: inline-flex; margin-left: -2px; }
1403
1443
  .asst-btn-icon svg { width: 12px; height: 12px; }
1404
1444
 
@@ -1412,7 +1452,7 @@ export function injectAssistantStyles() {
1412
1452
  .assistant-panel :is(.asp-header, .asp-body) :is(button, [role="button"], [tabindex]):focus-visible,
1413
1453
  .asp-session-pill:focus-visible,
1414
1454
  .asp-session-pill .term-minimized-pill-close:focus-visible,
1415
- :is(.asst-control-cmd, .asst-control-deny-msg, .asst-control-custom):focus-visible {
1455
+ :is(.asst-control-cmd, .asst-control-deny-msg, .asst-control-custom, .asst-ask-input):focus-visible {
1416
1456
  outline: 2px solid var(--asst-focus);
1417
1457
  outline-offset: 1px;
1418
1458
  }
@@ -1959,11 +1999,9 @@ export function injectAssistantStyles() {
1959
1999
  @container asst (max-width: 400px) {
1960
2000
  .asst-root > * { --asst-inline: 6px; }
1961
2001
  :is(.asst-cost, .asst-bar-group[data-group="context"]) { display: none !important; }
1962
- .asst-suggestions { flex-direction: column; align-items: stretch; width: 100%; }
1963
- .asst-chip.asst-suggestion { justify-content: flex-start; max-width: none; }
1964
- .asst-empty-project { width: 100%; }
1965
- .asst-dd.asst-empty-control-btn { flex: 1 1 auto; justify-content: flex-start; max-width: none; }
1966
- .asst-empty-control-btn .asst-dd-label { flex: 1 1 auto; max-width: none; text-align: start; }
2002
+ .asst-empty { padding-inline: 0; }
2003
+ .asst-suggestions { width: 100%; }
2004
+ .asst-empty-project .asst-dd.asst-empty-control-btn { max-width: 100%; }
1967
2005
  .asst-msg.msg-user .asst-msg-content { max-width: 92%; }
1968
2006
  .asst-route-opt-sub { display: none; }
1969
2007
  .asst-run-main { flex-wrap: wrap; row-gap: 2px; }
@@ -1978,7 +2016,7 @@ export function injectAssistantStyles() {
1978
2016
  }
1979
2017
  @container asst (max-height: 260px) {
1980
2018
  /* the toolbar stays: it carries the controls */
1981
- :is(.asst-empty-body, .asst-empty-mascot, .asst-empty-project, .asst-suggestions, .asst-empty-greet) { display: none !important; }
2019
+ :is(.asst-empty-mascot, .asst-empty-project, .asst-suggestions, .asst-empty-greet) { display: none !important; }
1982
2020
  .asst-empty { gap: 4px; padding: 4px; }
1983
2021
  .asst-empty-title { font-size: 14px; }
1984
2022
  .asst-bottom { margin-top: 6px; }
@@ -181,11 +181,18 @@ export function capitalize(text) {
181
181
  return s ? s[0].toLocaleUpperCase() + s.slice(1) : s;
182
182
  }
183
183
 
184
+ /** A letter or a digit: what a cut must keep some of. */
185
+ const CONTENT = /[\p{L}\p{N}]/u;
186
+ /** The "…" a text ends on (a clipped query, `"…"`), with the quote or bracket after it. */
187
+ const END_CUT = /…([^\p{L}\p{N}…]*)$/u;
188
+
184
189
  /**
185
190
  * Cut `text` in the middle so it fits `max` chars, keeping at least `minTail`
186
191
  * tail chars and cutting at token boundaries (spaces, slashes) when one is near.
187
- * One cut, shorter than the text: never a head and a tail that overlap, and a
188
- * token the text already shortened ("…/name") that the cut meets goes with it.
192
+ * One cut, shorter than the text: never a head and a tail that overlap. What it
193
+ * shows has one "…": the cut takes in every "…" the text already has (a token
194
+ * the summary shortened, "…/name"; its clipped end), so the head comes from
195
+ * before the first of them and the tail from after the last.
189
196
  */
190
197
  export function middleEllipsis(text, max = 96, minTail = 24) {
191
198
  const s = str(text);
@@ -194,28 +201,133 @@ export function middleEllipsis(text, max = 96, minTail = 24) {
194
201
  // A cut that keeps this much removes nothing: under a small `max` the budget rises to minTail + 6,
195
202
  // past a short text's end, and the head and the tail overlapped ("$ np…npm test" of "$ npm test").
196
203
  if (s.length <= budget + 1) return s;
197
- let tailStart = s.length - minTail;
198
- // Pull the tail back to the token boundary before it, within a third of the budget.
199
- const floor = s.length - Math.max(minTail, Math.floor(budget / 3) + minTail);
200
- for (let i = tailStart; i > floor && i > 0; i -= 1) {
204
+ const first = s.indexOf('…');
205
+ const last = s.lastIndexOf('…');
206
+ const headEnd = first < 0 ? s.length : first;
207
+ const tailFrom = last < 0 ? 0 : last + 1;
208
+ // "…words…" (a thought's tail that ends on its own "…"): nothing to keep on either side of the cuts (headEllipsis).
209
+ if (first >= 0 && !CONTENT.test(s.slice(0, headEnd)) && !CONTENT.test(s.slice(tailFrom))) return headEllipsis(s, max);
210
+ let tailStart = Math.max(tailFrom, s.length - minTail);
211
+ // A head that stops at the text's first "…" leaves the rest of the budget to the tail.
212
+ if (headEnd < budget - (s.length - tailStart)) tailStart = Math.max(tailFrom, s.length - (budget - headEnd));
213
+ // Pull the tail back to the token boundary before it, within a third of the budget and short of all of it
214
+ // (a char of head, or the cut runs one past `max`).
215
+ const floor = s.length - Math.min(budget - 1, Math.max(minTail, Math.floor(budget / 3) + minTail));
216
+ let atBoundary = false;
217
+ for (let i = tailStart; i > floor && i > tailFrom && i > 0; i -= 1) {
201
218
  const c = s[i - 1];
202
- if (c === ' ') { tailStart = i; break; }
203
- if (c === '/') { tailStart = i - 1; break; }
219
+ if (c === ' ') { tailStart = i; atBoundary = true; break; }
220
+ if (c === '/') { tailStart = i - 1; atBoundary = true; break; }
221
+ }
222
+ // None near enough behind a tail that opens inside a word: it starts at the next boundary instead, when
223
+ // that keeps half of it ("$ node --test…b.mjs c.mjs", never "…r.mjs b.mjs c.mjs").
224
+ if (!atBoundary && tailStart > tailFrom) {
225
+ const rest = s.slice(tailStart);
226
+ const next = rest.search(/[\s/]/);
227
+ if (next > 0 && next <= rest.length / 2 && CONTENT.test(rest.slice(next))) tailStart += rest[next] === '/' ? next : next + 1;
204
228
  }
205
229
  const tail = s.slice(tailStart);
206
- let head = s.slice(0, Math.max(1, budget - tail.length));
230
+ let head = s.slice(0, Math.min(headEnd, Math.max(1, budget - tail.length)));
207
231
  const cut = Math.max(head.lastIndexOf(' '), head.lastIndexOf('/'));
208
232
  if (cut >= head.length * 0.6) head = head.slice(0, head[cut] === '/' ? cut + 1 : cut);
209
233
  return joinCut(head, tail);
210
234
  }
211
235
 
212
- /** `head…tail`, one "…": a shortened token's own "…" beside the cut is dropped ("…/…/x.js" read as two cuts). */
236
+ /**
237
+ * "…ender-events.browser.mjs": the last `max` chars, from a token boundary when one is near. One "…":
238
+ * a "…" the text already has in that tail goes with the cut ("…--test …/x.js" reads "…/x.js"). A text
239
+ * that ends on its own "…" (a clipped query) has no tail to keep: its head stays (middleEllipsis); one
240
+ * that starts and ends on one ("…words…") loses the end's.
241
+ */
242
+ export function headEllipsis(text, max) {
243
+ let s = str(text);
244
+ if (s.length <= max) return s;
245
+ if (END_CUT.test(s)) {
246
+ if (CONTENT.test(s.slice(0, s.indexOf('…')))) return middleEllipsis(s, max, Math.min(8, max - 1));
247
+ s = s.replace(/…[^\p{L}\p{N}]*$/u, m => m.replace(/…/g, ''));
248
+ if (s.length <= max) return s;
249
+ }
250
+ let tail = s.slice(s.length - Math.max(8, max - 1));
251
+ const own = tail.lastIndexOf('…'); // followed by a word: the text no longer ends on one
252
+ if (own >= 0) return joinCut('', tail.slice(own));
253
+ const cut = tail.search(/[\s/]/);
254
+ // A fragment of a word before the first boundary goes too, when that keeps half the tail ("…c.mjs", never "…ker-stage.mjs c.mjs").
255
+ const inWord = !/[\s/]/.test(s[s.length - tail.length - 1] ?? ' ');
256
+ if (inWord && cut > 0 && cut <= tail.length / 2 && CONTENT.test(tail.slice(cut))) tail = tail.slice(tail[cut] === '/' ? cut : cut + 1);
257
+ return joinCut('', tail);
258
+ }
259
+
260
+ /** `head…tail`, one "…": a shortened token's own "…" beside the cut is dropped ("…/…/x.js" read as two cuts), and so is the space next to it. */
213
261
  export function joinCut(head, tail) {
214
262
  const h = str(head).trimEnd().replace(/\/?…\/?$/, '').trimEnd();
215
- const t = str(tail).trimStart().replace(/^\/?…/, '');
263
+ const t = str(tail).trimStart().replace(/^\/?…/, '').trimStart();
216
264
  return `${h}…${t}`;
217
265
  }
218
266
 
267
+ // A URL or a path in a subject wraps at its separators, never mid-word (wrapRuns).
268
+ const URL_START = /^[a-z][a-z0-9+.-]*:\/\//i;
269
+ const HOST_OR_FILE = /^[\p{L}\p{N}_~@%+…-]+(?:\.[\p{L}\p{N}_~@%+…-]+)+(?::\d+(?:[-:]\d+)?)?$/u; // a file may end on its lines, ":131-191"
270
+ const TOKEN_LEAD = /^[("'“‘[<{]+/;
271
+ const TOKEN_TRAIL = /[)"'”’\]>},;:!?.]+$/;
272
+ const PATH_MIN = 12; // a shorter token wraps whole, as a word does
273
+ const LONG_PIECE = 20; // a longer segment also breaks inside it
274
+ const MIN_PIECE = 3; // "~/", "…/", "./" stay with the piece after them
275
+
276
+ function isPathToken(tok) {
277
+ if (tok.length < PATH_MIN || !CONTENT.test(tok)) return false;
278
+ return URL_START.test(tok) || /[/\\]/.test(tok) || HOST_OR_FILE.test(tok);
279
+ }
280
+
281
+ /**
282
+ * A URL or path as the pieces a line may break between: after "/" (a run of
283
+ * slashes, "https://", stays whole); in a segment over LONG_PIECE chars, also
284
+ * before "?" or "#" and after "-", "_", "=" or "&" when a letter follows, and
285
+ * before "." only in a piece still that long ("queue.browser.mjs" keeps its
286
+ * extension). A piece under MIN_PIECE chars, and a scheme ("https://"), joins
287
+ * its neighbour. The pieces join to `tok`.
288
+ */
289
+ export function pathPieces(tok) {
290
+ const s = str(tok);
291
+ const long = (p) => p.replace(/[/\\]+$/, '').length > LONG_PIECE;
292
+ const pieces = [];
293
+ for (const part of s.match(/[^/\\]*[/\\]+|[^/\\]+$/g) || [s]) {
294
+ if (!long(part)) { pieces.push(part); continue; }
295
+ for (const p of part.split(/(?=[?#])|(?<=[-_=&])(?=\p{L})/u).filter(Boolean)) pieces.push(...(long(p) ? p.split(/(?=\.)/).filter(Boolean) : [p]));
296
+ }
297
+ const leans = (p) => p.length < MIN_PIECE || /^[a-z][a-z0-9+.-]*:\/+$/i.test(p);
298
+ const out = [];
299
+ for (const piece of pieces) {
300
+ if (out.length && (leans(out[out.length - 1]) || piece.length < MIN_PIECE)) out[out.length - 1] += piece;
301
+ else out.push(piece);
302
+ }
303
+ return out;
304
+ }
305
+
306
+ /**
307
+ * Where a bubble subject may wrap: its URL and path tokens (a scheme, a slash,
308
+ * or a dotted host or file name, PATH_MIN chars or more; quotes, brackets and
309
+ * the sentence's punctuation around them left out) as `{ text, pieces }` that
310
+ * break only between their pieces (pathPieces); the rest as `{ text }`, which
311
+ * wraps as any text does. The runs' texts join to `text`.
312
+ */
313
+ export function wrapRuns(text) {
314
+ const s = str(text);
315
+ const runs = [];
316
+ let at = 0;
317
+ for (const m of s.matchAll(/\S+/g)) {
318
+ const lead = m[0].match(TOKEN_LEAD)?.[0] || '';
319
+ const rest = m[0].slice(lead.length);
320
+ const core = rest.slice(0, rest.length - (rest.match(TOKEN_TRAIL)?.[0].length || 0));
321
+ if (!isPathToken(core)) continue;
322
+ const start = m.index + lead.length;
323
+ if (start > at) runs.push({ text: s.slice(at, start) });
324
+ runs.push({ text: core, pieces: pathPieces(core) });
325
+ at = start + core.length;
326
+ }
327
+ if (at < s.length) runs.push({ text: s.slice(at) });
328
+ return runs;
329
+ }
330
+
219
331
  /** A path's last two folders and its basename: `shared/assistant/asst-render.js`. */
220
332
  export function splitPath(path) {
221
333
  const clean = str(path).replace(/\\/g, '/').replace(/\/+$/, '');
@@ -274,14 +386,39 @@ export function commandCore(cmd) {
274
386
  return s;
275
387
  }
276
388
 
389
+ /** A path token's file name with what wraps it: `--config=` or a quote before, `;` or a quote after it. */
390
+ function fileNameOf(tok) {
391
+ const lead = tok.match(/^(?:[^/\\=]*=)?["'(]*/)[0];
392
+ const rest = tok.slice(lead.length);
393
+ const trail = rest.match(/[)"'\];,]*$/)[0];
394
+ const path = rest.slice(0, rest.length - trail.length);
395
+ const base = path.replace(/[/\\]+$/, '').split(/[/\\]/).pop();
396
+ return base ? { lead, base: `${base}${/[/\\]$/.test(path) ? '/' : ''}`, trail } : null;
397
+ }
398
+
277
399
  /**
278
400
  * The command a bubble says: its core (commandCore), the home directory shown
279
401
  * as ~/, whitespace collapsed and tokens over 28 chars cut in the middle.
402
+ * `oneCut` (the stage bubble): one "…" at most, however many paths it shortens.
403
+ * The first path over 28 chars spends it on its dropped folders; a later one
404
+ * keeps its file name, unmarked ("…/a.mjs b.mjs c.mjs"); every other token
405
+ * (a bare file name, a flag) stays whole. A "…" of the command's own counts.
280
406
  */
281
- export function summarizeCommand(cmd) {
407
+ export function summarizeCommand(cmd, { oneCut = false } = {}) {
282
408
  let s = commandCore(cmd);
283
409
  s = s.replace(HOME_RE, '$1~').replace(/(^|[\s"'=:(])\$HOME(?=\/|$|[\s"'])/g, '$1~');
284
- return s.split(' ').map(tok => shortenToken(tok, 28)).join(' ');
410
+ if (!oneCut) return s.split(' ').map(tok => shortenToken(tok, 28)).join(' ');
411
+ let spent = s.includes('…');
412
+ return s.split(' ').map((tok) => {
413
+ if (tok.length <= 28 || !/[/\\]/.test(tok)) return tok;
414
+ const file = fileNameOf(tok);
415
+ if (!file) return tok;
416
+ if (spent) return `${file.lead}${file.base}${file.trail}`;
417
+ spent = true;
418
+ const short = shortenToken(tok, 28);
419
+ if (short.includes('…/')) return short;
420
+ return `${file.lead}…${tok.includes('/') ? '/' : '\\'}${file.base}${file.trail}`; // never a file name cut in its middle
421
+ }).join(' ');
285
422
  }
286
423
 
287
424
  /** The command a shell call ran: `command` or `cmd`, as a string (Codex sends argv arrays). */
@@ -596,6 +733,7 @@ export function urlSubject(url) {
596
733
  /**
597
734
  * The bubble for one call: { verb, text, detail?, mono, segments?, meta[], caption, copy, tag }.
598
735
  * `detail` (computer calls) is what the call's own row shows when it differs from the bubble's subject.
736
+ * `stage` (commands) is the stage bubble's subject: `text` with one "…" at most (summarizeCommand `oneCut`).
599
737
  * `call`: { name, kind, input, result, state, memories?, app? }.
600
738
  * `ctx`: { t, runLabel(call), runState(call), describeComputer(input, name) }.
601
739
  */
@@ -614,6 +752,7 @@ export function sayCall(call, ctx = {}) {
614
752
  out.verb = 'run';
615
753
  out.text = `$ ${summarizeCommand(cmd)}`;
616
754
  out.full = `$ ${str(cmd).replace(/\s+/g, ' ').trim()}`; // the literal line: the title and the opened bubble
755
+ if (cmd.trim()) out.stage = `$ ${summarizeCommand(cmd, { oneCut: true })}`; // the stage bubble's: one "…" at most
617
756
  out.mono = true;
618
757
  out.copy = cmd;
619
758
  out.caption = firstString(input.description);
@@ -765,7 +904,7 @@ export function sayCall(call, ctx = {}) {
765
904
  case 'think': {
766
905
  out.verb = 'think';
767
906
  const text = str(call?.text).replace(/\s+/g, ' ').trim();
768
- out.text = text ? (text.length > 80 ? `…${text.slice(-79)}` : text) : '…';
907
+ out.text = text ? headEllipsis(text, 80) : '…'; // the tail: one "…", a "…" of the thought's own in it goes with the cut
769
908
  out.muted = true;
770
909
  break;
771
910
  }
@@ -807,7 +946,8 @@ export function targetKey(call) {
807
946
 
808
947
  /**
809
948
  * The subject parallel calls of one kind share: "a.js, b.js +1" for reads and
810
- * edits, "$ npm test +1" for commands; "server.js ×2" for a re-read.
949
+ * edits, "$ npm test +1" for commands (one "…" at most, as the stage says a
950
+ * command); "server.js ×2" for a re-read.
811
951
  * `calls`: the calls running side by side (the bubble's own call last);
812
952
  * `all`: every call of the row (for re-reads). Empty when one subject says it.
813
953
  */
@@ -825,7 +965,7 @@ export function groupSubject(kind, calls, all = calls) {
825
965
  if (list.length >= 2) {
826
966
  if (kind === 'shell') {
827
967
  const cmd = commandOf(list[list.length - 1].input);
828
- return cmd ? `$ ${summarizeCommand(cmd)} +${list.length - 1}` : '';
968
+ return cmd ? `$ ${summarizeCommand(cmd, { oneCut: true })} +${list.length - 1}` : '';
829
969
  }
830
970
  const names = [...new Set(list.map(nameOf).filter(Boolean))];
831
971
  if (names.length >= 2) return `${names[0]}, ${names[1]}${names.length > 2 ? ` +${names.length - 2}` : ''}`;
@@ -59,14 +59,17 @@ export function claudeAutomationSupportsOneMillion(model) {
59
59
  return !/(haiku|claude-3|opus-4-[0-5](?:-|$)|opus-4-\d{8}|opus-4$)/.test(id);
60
60
  }
61
61
 
62
+ // `size` is the window as a short label ("272K"), '' when unknown: a page that words the choice in
63
+ // another language puts it in its own sentence (the Schedules window).
62
64
  export function automationContextOptions(profile, modelId, models = []) {
63
65
  const id = normalizeAutomationSelection(profile, modelId).model;
64
66
  const model = models.find((entry) => entry?.id === id);
65
67
  const baseSize = contextSizeLabel(model?.contextWindow);
66
- const options = [{ id: 'default', label: baseSize ? `Default (${baseSize})` : 'Provider default' }];
68
+ const options = [{ id: 'default', label: baseSize ? `Default (${baseSize})` : 'Provider default', size: baseSize }];
67
69
  if (profile === 'codex' && model?.supportsExtendedContext === true
68
70
  && Number(model.maxContextWindow) > Number(model.contextWindow)) {
69
- options.push({ id: 'extended', label: `Extended (${contextSizeLabel(model.maxContextWindow)})` });
71
+ const size = contextSizeLabel(model.maxContextWindow);
72
+ options.push({ id: 'extended', label: `Extended (${size})`, size });
70
73
  } else if (profile === 'claude-code'
71
74
  && (models.some((entry) => entry?.id === `${id}[1m]`) || claudeAutomationSupportsOneMillion(model))) {
72
75
  options.push({ id: '1m', label: '1M' });