synabun 2.0.10 → 2.2.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 (656) hide show
  1. package/CHANGELOG.md +207 -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 +13 -13
  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 +30 -17
  11. package/lib/desktop-app.js +7 -1
  12. package/lib/external-tools.js +7 -6
  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 +302 -0
  24. package/lib/virustotal.mjs +203 -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/budget-judgments.d.ts +1 -1
  37. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
  38. package/mcp-server/dist/services/budget-judgments.js +5 -3
  39. package/mcp-server/dist/services/budget-judgments.js.map +1 -1
  40. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  41. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  42. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  43. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  44. package/mcp-server/dist/services/identity.d.ts +2 -2
  45. package/mcp-server/dist/services/identity.js +2 -2
  46. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  47. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  48. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  49. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  50. package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
  51. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
  52. package/mcp-server/dist/services/memory-sessions.js +28 -2
  53. package/mcp-server/dist/services/memory-sessions.js.map +1 -1
  54. package/mcp-server/dist/services/neural-interface.d.ts +18 -11
  55. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  56. package/mcp-server/dist/services/neural-interface.js +67 -11
  57. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  58. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  59. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  60. package/mcp-server/dist/services/server-instructions.js +22 -63
  61. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  62. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  63. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  64. package/mcp-server/dist/services/tool-catalog.js +339 -0
  65. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  66. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  67. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  68. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  69. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  70. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  71. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  72. package/mcp-server/dist/services/tool-list.js +334 -0
  73. package/mcp-server/dist/services/tool-list.js.map +1 -0
  74. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  75. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  76. package/mcp-server/dist/services/tool-runtime.js +400 -0
  77. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  78. package/mcp-server/dist/services/typesafe-config.js +1 -1
  79. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  80. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  81. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  82. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  83. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  84. package/mcp-server/dist/tools/agents.d.ts +14 -14
  85. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  86. package/mcp-server/dist/tools/agents.js +29 -19
  87. package/mcp-server/dist/tools/agents.js.map +1 -1
  88. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  89. package/mcp-server/dist/tools/choice.d.ts +6 -0
  90. package/mcp-server/dist/tools/choice.d.ts.map +1 -1
  91. package/mcp-server/dist/tools/choice.js +18 -13
  92. package/mcp-server/dist/tools/choice.js.map +1 -1
  93. package/mcp-server/dist/tools/git-tools.js +2 -2
  94. package/mcp-server/dist/tools/git-tools.js.map +1 -1
  95. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  96. package/mcp-server/dist/tools/image-tools.js +1 -1
  97. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
  98. package/mcp-server/dist/tools/morelogin.js +9 -6
  99. package/mcp-server/dist/tools/morelogin.js.map +1 -1
  100. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  101. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  102. package/mcp-server/dist/tools/skill-tools.js +642 -0
  103. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  104. package/mcp-server/dist/tools/skill.d.ts +7 -0
  105. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  106. package/mcp-server/dist/tools/skill.js +11 -0
  107. package/mcp-server/dist/tools/skill.js.map +1 -0
  108. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  109. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  110. package/mcp-server/dist/tools/tool-groups.js +147 -0
  111. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  112. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  113. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  114. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  115. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  116. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  117. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  118. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  119. package/mcp-server/package-lock.json +2 -2
  120. package/mcp-server/package.json +1 -1
  121. package/mcp-server/src/http.ts +75 -12
  122. package/mcp-server/src/index.ts +147 -154
  123. package/mcp-server/src/preload.ts +12 -12
  124. package/mcp-server/src/services/budget-judgments.ts +5 -3
  125. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  126. package/mcp-server/src/services/identity.ts +2 -2
  127. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  128. package/mcp-server/src/services/memory-sessions.ts +24 -3
  129. package/mcp-server/src/services/neural-interface.ts +81 -21
  130. package/mcp-server/src/services/server-instructions.ts +29 -64
  131. package/mcp-server/src/services/tool-catalog.ts +403 -0
  132. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  133. package/mcp-server/src/services/tool-list.ts +410 -0
  134. package/mcp-server/src/services/tool-runtime.ts +457 -0
  135. package/mcp-server/src/services/typesafe-config.ts +1 -1
  136. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  137. package/mcp-server/src/tools/agents.ts +29 -20
  138. package/mcp-server/src/tools/choice.ts +17 -12
  139. package/mcp-server/src/tools/git-tools.ts +2 -2
  140. package/mcp-server/src/tools/image-tools.ts +1 -1
  141. package/mcp-server/src/tools/morelogin.ts +6 -4
  142. package/mcp-server/src/tools/skill-tools.ts +592 -0
  143. package/mcp-server/src/tools/skill.ts +13 -0
  144. package/mcp-server/src/tools/tool-groups.ts +164 -0
  145. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  146. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  147. package/neural-interface/i18n/en.json +3953 -228
  148. package/neural-interface/i18n/pt-BR.json +3901 -179
  149. package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
  150. package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
  151. package/neural-interface/lib/antigravity/acp-connection.js +299 -0
  152. package/neural-interface/lib/antigravity/bypass.js +100 -0
  153. package/neural-interface/lib/antigravity/catalog.js +273 -0
  154. package/neural-interface/lib/antigravity/home.js +260 -0
  155. package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
  156. package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
  157. package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
  158. package/neural-interface/lib/antigravity/policy.js +74 -0
  159. package/neural-interface/lib/antigravity/tool-call.js +178 -0
  160. package/neural-interface/lib/antigravity/transcripts.js +252 -0
  161. package/neural-interface/lib/antigravity/usage.js +43 -0
  162. package/neural-interface/lib/assistant-api.js +128 -28
  163. package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
  164. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  165. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  166. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  167. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  168. package/neural-interface/lib/assistant-brains/opencode.js +120 -54
  169. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
  170. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
  171. package/neural-interface/lib/assistant-budget-planner.js +7 -3
  172. package/neural-interface/lib/assistant-budget-split.js +42 -15
  173. package/neural-interface/lib/assistant-catalog.js +81 -15
  174. package/neural-interface/lib/assistant-config.js +6 -3
  175. package/neural-interface/lib/assistant-dispatch.js +1073 -200
  176. package/neural-interface/lib/assistant-envelope.js +156 -2
  177. package/neural-interface/lib/assistant-evidence.js +80 -0
  178. package/neural-interface/lib/assistant-hidden-models.js +7 -5
  179. package/neural-interface/lib/assistant-persona.js +93 -19
  180. package/neural-interface/lib/assistant-plan-permissions.js +25 -9
  181. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  182. package/neural-interface/lib/assistant-route-gate.js +6 -4
  183. package/neural-interface/lib/assistant-router.js +245 -38
  184. package/neural-interface/lib/assistant-runtime.js +214 -30
  185. package/neural-interface/lib/assistant-task-prompt.js +87 -21
  186. package/neural-interface/lib/assistant-tools.js +51 -0
  187. package/neural-interface/lib/assistant-usage.js +29 -0
  188. package/neural-interface/lib/backup-service.js +626 -4
  189. package/neural-interface/lib/backup-zip-reader.js +10 -5
  190. package/neural-interface/lib/backup-zip-writer.js +257 -0
  191. package/neural-interface/lib/browser-execution.js +10 -2
  192. package/neural-interface/lib/browser-guard-cdp.js +84 -0
  193. package/neural-interface/lib/browser-network-guard.js +476 -0
  194. package/neural-interface/lib/browser-policy-roots.js +64 -0
  195. package/neural-interface/lib/browser-tool-policy.js +198 -38
  196. package/neural-interface/lib/claude-agent-bridge.js +11 -2
  197. package/neural-interface/lib/claude-history-cache.js +210 -0
  198. package/neural-interface/lib/claude-hooks-status.js +103 -0
  199. package/neural-interface/lib/claude-model-catalog.js +5 -1
  200. package/neural-interface/lib/claude-temporary.js +5 -11
  201. package/neural-interface/lib/cli-install-api.js +1 -1
  202. package/neural-interface/lib/cli-install.js +163 -154
  203. package/neural-interface/lib/cli-resolver.js +13 -3
  204. package/neural-interface/lib/cli-update-planner.js +52 -41
  205. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  206. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  207. package/neural-interface/lib/codex-rollout-reader.js +52 -0
  208. package/neural-interface/lib/codex-worker-app-server.js +191 -0
  209. package/neural-interface/lib/confined-fs.js +30 -3
  210. package/neural-interface/lib/crash-notice-api.js +98 -0
  211. package/neural-interface/lib/editor-completion-opencode.js +68 -68
  212. package/neural-interface/lib/editor-git-api.js +3 -20
  213. package/neural-interface/lib/exec-loop-command.js +13 -10
  214. package/neural-interface/lib/file-explorer-api.js +74 -40
  215. package/neural-interface/lib/file-explorer-watch.js +9 -3
  216. package/neural-interface/lib/git-bash/install.js +52 -6
  217. package/neural-interface/lib/git-bash/manager.js +59 -17
  218. package/neural-interface/lib/git-bash/pins.js +12 -0
  219. package/neural-interface/lib/git-read.js +2 -2
  220. package/neural-interface/lib/git-status-runner.js +390 -0
  221. package/neural-interface/lib/git-status-watchdog.js +40 -0
  222. package/neural-interface/lib/greeting/budgets.js +1 -0
  223. package/neural-interface/lib/greeting/engine.js +2 -2
  224. package/neural-interface/lib/greeting/sources.js +10 -12
  225. package/neural-interface/lib/greeting/writer.js +1 -1
  226. package/neural-interface/lib/http-guards.js +8 -2
  227. package/neural-interface/lib/install-details.js +4 -1
  228. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  229. package/neural-interface/lib/mcp-client-config.js +35 -33
  230. package/neural-interface/lib/mcp-external-servers.js +332 -0
  231. package/neural-interface/lib/mcp-installer.js +2 -1
  232. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  233. package/neural-interface/lib/memory-session-capture.js +17 -3
  234. package/neural-interface/lib/morelogin.js +177 -25
  235. package/neural-interface/lib/native-loop-providers.js +965 -66
  236. package/neural-interface/lib/native-loop-runtime.js +290 -42
  237. package/neural-interface/lib/opencode-config.js +557 -0
  238. package/neural-interface/lib/opencode-db-schema.js +17 -34
  239. package/neural-interface/lib/opencode-history.js +48 -218
  240. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  241. package/neural-interface/lib/opencode-native-boundary.js +53 -0
  242. package/neural-interface/lib/opencode-protocol.js +249 -112
  243. package/neural-interface/lib/opencode-runtime-config.js +32 -22
  244. package/neural-interface/lib/opencode-serve-records.js +39 -21
  245. package/neural-interface/lib/opencode-v2-client.js +48 -153
  246. package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
  247. package/neural-interface/lib/opencode-worker-data.js +27 -0
  248. package/neural-interface/lib/opencode2-client.js +73 -37
  249. package/neural-interface/lib/opencode2-proxy.js +23 -63
  250. package/neural-interface/lib/opencode2-translate.js +51 -2
  251. package/neural-interface/lib/owner-authority.js +249 -0
  252. package/neural-interface/lib/page-session.js +275 -0
  253. package/neural-interface/lib/path-confine.js +12 -9
  254. package/neural-interface/lib/peer-identity.js +793 -0
  255. package/neural-interface/lib/pty-host/core.js +28 -1
  256. package/neural-interface/lib/pty-host/lifetime.js +12 -0
  257. package/neural-interface/lib/pty-host/manager.js +12 -1
  258. package/neural-interface/lib/remote-policy.js +1 -1
  259. package/neural-interface/lib/request-gate.js +20 -2
  260. package/neural-interface/lib/rulesets/api.js +7 -6
  261. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  262. package/neural-interface/lib/rulesets/installer.js +180 -36
  263. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  264. package/neural-interface/lib/rulesets/render.js +1 -1
  265. package/neural-interface/lib/session-cache-builder.js +81 -31
  266. package/neural-interface/lib/session-title-generator.js +58 -36
  267. package/neural-interface/lib/skills/api-v2.js +495 -0
  268. package/neural-interface/lib/skills/bundle.js +418 -0
  269. package/neural-interface/lib/skills/catalog.js +298 -0
  270. package/neural-interface/lib/skills/creation-api.js +191 -0
  271. package/neural-interface/lib/skills/creation-brief.js +247 -0
  272. package/neural-interface/lib/skills/creation-sources.js +285 -0
  273. package/neural-interface/lib/skills/creation.js +843 -0
  274. package/neural-interface/lib/skills/deploy.js +569 -0
  275. package/neural-interface/lib/skills/digest.js +119 -0
  276. package/neural-interface/lib/skills/discover.js +111 -0
  277. package/neural-interface/lib/skills/draft-confinement.js +216 -0
  278. package/neural-interface/lib/skills/eval-confinement.js +399 -0
  279. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  280. package/neural-interface/lib/skills/eval-trace.js +135 -0
  281. package/neural-interface/lib/skills/evals-api.js +212 -0
  282. package/neural-interface/lib/skills/evals.js +1573 -0
  283. package/neural-interface/lib/skills/export.js +203 -0
  284. package/neural-interface/lib/skills/frontmatter.js +64 -0
  285. package/neural-interface/lib/skills/health.js +75 -0
  286. package/neural-interface/lib/skills/json-edit.js +165 -0
  287. package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
  288. package/neural-interface/lib/skills/known-bridges.js +96 -0
  289. package/neural-interface/lib/skills/library.js +823 -0
  290. package/neural-interface/lib/skills/local-store.js +21 -0
  291. package/neural-interface/lib/skills/migration.js +433 -0
  292. package/neural-interface/lib/skills/operations.js +45 -0
  293. package/neural-interface/lib/skills/ownership.js +427 -0
  294. package/neural-interface/lib/skills/packages.js +88 -0
  295. package/neural-interface/lib/skills/reviews.js +212 -0
  296. package/neural-interface/lib/skills/revision.js +80 -0
  297. package/neural-interface/lib/skills/roots.js +269 -0
  298. package/neural-interface/lib/skills/runtime-checks.js +358 -0
  299. package/neural-interface/lib/skills/scan-assets.js +252 -0
  300. package/neural-interface/lib/skills/scan-context.js +26 -0
  301. package/neural-interface/lib/skills/scan-shell.js +324 -0
  302. package/neural-interface/lib/skills/scan.js +364 -0
  303. package/neural-interface/lib/skills/scanners.js +54 -0
  304. package/neural-interface/lib/skills/service.js +530 -0
  305. package/neural-interface/lib/skills/telemetry.js +119 -0
  306. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  307. package/neural-interface/lib/synabun-version.js +1 -1
  308. package/neural-interface/lib/system-activity.js +1 -1
  309. package/neural-interface/lib/tool-lists.js +124 -0
  310. package/neural-interface/lib/whatsapp/brain.js +7 -3
  311. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  312. package/neural-interface/lib/whatsapp/cards.js +22 -9
  313. package/neural-interface/lib/whatsapp/config.js +1 -1
  314. package/neural-interface/lib/worker-confinement.js +1268 -0
  315. package/neural-interface/lib/worker-guard-setting.js +56 -0
  316. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  317. package/neural-interface/lib/worker-question.js +74 -0
  318. package/neural-interface/lib/worker-relay-ports.js +227 -0
  319. package/neural-interface/lib/worker-resume.js +238 -0
  320. package/neural-interface/lib/worker-sandbox.js +329 -0
  321. package/neural-interface/package-lock.json +34 -12
  322. package/neural-interface/package.json +3 -2
  323. package/neural-interface/public/index.html +3 -1
  324. package/neural-interface/public/index2d.html +19 -11
  325. package/neural-interface/public/onboarding.html +3 -3
  326. package/neural-interface/public/shared/account-menu.js +8 -5
  327. package/neural-interface/public/shared/agent-runtime-options.js +125 -31
  328. package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
  329. package/neural-interface/public/shared/agy/agy-client.js +266 -0
  330. package/neural-interface/public/shared/agy/agy-commands.js +120 -0
  331. package/neural-interface/public/shared/agy/agy-copy.js +326 -0
  332. package/neural-interface/public/shared/agy/agy-diff.js +161 -0
  333. package/neural-interface/public/shared/agy/agy-events.js +469 -0
  334. package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
  335. package/neural-interface/public/shared/agy/agy-options.js +232 -0
  336. package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
  337. package/neural-interface/public/shared/agy/agy-render.js +392 -0
  338. package/neural-interface/public/shared/agy/agy-setup.js +149 -0
  339. package/neural-interface/public/shared/agy/agy-styles.js +604 -0
  340. package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
  341. package/neural-interface/public/shared/api.js +1527 -1336
  342. package/neural-interface/public/shared/app-frame.js +192 -0
  343. package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
  344. package/neural-interface/public/shared/assistant/asst-api.js +1 -1
  345. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  346. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  347. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  348. package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
  349. package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
  350. package/neural-interface/public/shared/assistant/asst-control.js +205 -26
  351. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  352. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  353. package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
  354. package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
  355. package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
  356. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  357. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  358. package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
  359. package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
  360. package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
  361. package/neural-interface/public/shared/assistant/asst-render.js +445 -82
  362. package/neural-interface/public/shared/assistant/asst-route.js +304 -53
  363. package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
  364. package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
  365. package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
  366. package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
  367. package/neural-interface/public/shared/assistant/asst-state.js +87 -24
  368. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  369. package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
  370. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
  371. package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
  372. package/neural-interface/public/shared/automation-context.js +5 -2
  373. package/neural-interface/public/shared/cc-dropdown.js +89 -19
  374. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  375. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  376. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  377. package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
  378. package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
  379. package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
  380. package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
  381. package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
  382. package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
  383. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  384. package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
  385. package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
  386. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  387. package/neural-interface/public/shared/cli-install-controller.js +218 -0
  388. package/neural-interface/public/shared/cli-install-view.js +11 -12
  389. package/neural-interface/public/shared/cli-status.js +11 -10
  390. package/neural-interface/public/shared/constants.js +5 -4
  391. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  392. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  393. package/neural-interface/public/shared/context-menu-model.js +367 -0
  394. package/neural-interface/public/shared/context-menu.js +372 -0
  395. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  396. package/neural-interface/public/shared/cp/cp-restore.js +162 -0
  397. package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
  398. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  399. package/neural-interface/public/shared/desktop-bridge.js +17 -0
  400. package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
  401. package/neural-interface/public/shared/desktop-titlebar.js +13 -4
  402. package/neural-interface/public/shared/desktop-update-view.js +21 -0
  403. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  404. package/neural-interface/public/shared/explorer/fx-api.js +4 -4
  405. package/neural-interface/public/shared/explorer/fx-links.js +3 -3
  406. package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
  407. package/neural-interface/public/shared/explorer/fx-main.js +48 -16
  408. package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
  409. package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
  410. package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
  411. package/neural-interface/public/shared/html-shell.js +30 -15
  412. package/neural-interface/public/shared/i18n.js +2 -0
  413. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  414. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  415. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  416. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
  417. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  418. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  419. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  420. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  421. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  422. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  423. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  424. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
  425. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  426. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
  427. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
  428. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
  429. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
  430. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  431. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
  432. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  433. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  434. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  435. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  436. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
  437. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  438. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
  439. package/neural-interface/public/shared/page-session.js +96 -0
  440. package/neural-interface/public/shared/provider-icons.js +4 -2
  441. package/neural-interface/public/shared/registry.js +5 -3
  442. package/neural-interface/public/shared/retired-2d.js +3 -0
  443. package/neural-interface/public/shared/schedules-view.js +195 -61
  444. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  445. package/neural-interface/public/shared/settings/settings-data.js +3 -1
  446. package/neural-interface/public/shared/settings/settings-ia.js +6 -6
  447. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  448. package/neural-interface/public/shared/settings/settings-rules.js +2 -2
  449. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  450. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  451. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  452. package/neural-interface/public/shared/showcase-privacy.js +6 -1
  453. package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
  454. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  455. package/neural-interface/public/shared/skills/ss-creation.js +222 -0
  456. package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
  457. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  458. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  459. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  460. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  461. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  462. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  463. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  464. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  465. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  466. package/neural-interface/public/shared/skills/ss-lint.js +149 -0
  467. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  468. package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
  469. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  470. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  471. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  472. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  473. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  474. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  475. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  476. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
  477. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  478. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  479. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  480. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  481. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  482. package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
  483. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  484. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  485. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  486. package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
  487. package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
  488. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  489. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  490. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  491. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
  492. package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
  493. package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
  494. package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
  495. package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
  496. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  497. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  498. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  499. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  500. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  501. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  502. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  503. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  504. package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
  505. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  506. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  507. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  508. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
  509. package/neural-interface/public/shared/state.js +1 -1
  510. package/neural-interface/public/shared/streaming-markdown.js +58 -0
  511. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  512. package/neural-interface/public/shared/styles.css +1822 -1756
  513. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  514. package/neural-interface/public/shared/text-cache.js +29 -0
  515. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  516. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  517. package/neural-interface/public/shared/tool-list-view.js +112 -0
  518. package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
  519. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  520. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  521. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  522. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  523. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  524. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  525. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  526. package/neural-interface/public/shared/tour/tour.css +144 -0
  527. package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
  528. package/neural-interface/public/shared/ui-assistant.js +2 -0
  529. package/neural-interface/public/shared/ui-automation-studio.js +111 -140
  530. package/neural-interface/public/shared/ui-claude-panel.js +376 -82
  531. package/neural-interface/public/shared/ui-cli-banner.js +23 -167
  532. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  533. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  534. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  535. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  536. package/neural-interface/public/shared/ui-detail.js +15 -3
  537. package/neural-interface/public/shared/ui-file-explorer.js +48 -6
  538. package/neural-interface/public/shared/ui-file-links.js +2 -2
  539. package/neural-interface/public/shared/ui-games.js +2 -2
  540. package/neural-interface/public/shared/ui-image-gallery.js +50 -47
  541. package/neural-interface/public/shared/ui-judgments.js +1 -1
  542. package/neural-interface/public/shared/ui-keybinds.js +33 -2
  543. package/neural-interface/public/shared/ui-link.js +3 -3
  544. package/neural-interface/public/shared/ui-menubar.js +10 -20
  545. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  546. package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
  547. package/neural-interface/public/shared/ui-navbar.js +49 -24
  548. package/neural-interface/public/shared/ui-notifications.js +1 -0
  549. package/neural-interface/public/shared/ui-panels.js +96 -65
  550. package/neural-interface/public/shared/ui-resume.js +9 -7
  551. package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
  552. package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
  553. package/neural-interface/public/shared/ui-sessions.js +27 -15
  554. package/neural-interface/public/shared/ui-settings.js +683 -526
  555. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
  556. package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
  557. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  558. package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
  559. package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
  560. package/neural-interface/public/shared/ui-skills.js +33 -2830
  561. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  562. package/neural-interface/public/shared/ui-sync.js +15 -5
  563. package/neural-interface/public/shared/ui-terminal.js +270 -190
  564. package/neural-interface/public/shared/ui-tool-updates.js +6 -4
  565. package/neural-interface/public/shared/ui-tooltip.js +81 -51
  566. package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
  567. package/neural-interface/public/shared/ui-trash.js +6 -4
  568. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  569. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  570. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
  571. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  572. package/neural-interface/public/shared/ui-tutorial.js +285 -509
  573. package/neural-interface/public/shared/ui-update.js +38 -2
  574. package/neural-interface/public/shared/ui-whiteboard.js +312 -59
  575. package/neural-interface/public/shared/ui-worker-end.js +5 -1
  576. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  577. package/neural-interface/public/shared/view-variant.js +66 -0
  578. package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
  579. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  580. package/neural-interface/public/shared/worker-end.js +10 -3
  581. package/neural-interface/public/shared/worker-questions.js +34 -0
  582. package/neural-interface/public/shared/worker-restart.js +12 -0
  583. package/neural-interface/public/sidepanel-session.html +2 -2
  584. package/neural-interface/public/variant/2d/background.js +2 -1
  585. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  586. package/neural-interface/public/variant/2d/graph.js +42 -20
  587. package/neural-interface/public/variant/2d/hulls.js +14 -9
  588. package/neural-interface/public/variant/2d/lasso.js +11 -7
  589. package/neural-interface/public/variant/2d/main.js +32 -1
  590. package/neural-interface/public/variant/2d/minimap.js +11 -13
  591. package/neural-interface/public/variant/3d/main.js +69 -6
  592. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  593. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  594. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  595. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  596. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  597. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  598. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  599. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  600. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  601. package/neural-interface/scripts/build-vendor.mjs +32 -0
  602. package/neural-interface/server.js +4553 -2855
  603. package/neural-interface/templates/rulesets/README.md +1 -1
  604. package/neural-interface/templates/rulesets/core.md +1 -1
  605. package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
  606. package/neural-interface/templates/rulesets/manifest.json +8 -8
  607. package/npm-shrinkwrap.json +34 -12
  608. package/package.json +17 -3
  609. package/postinstall.js +9 -4
  610. package/preuninstall.js +1 -1
  611. package/setup.js +97 -322
  612. package/skills/skill-forge/SKILL.md +177 -0
  613. package/skills/skill-forge/evals/evals.json +54 -0
  614. package/skills/skill-forge/references/package.md +105 -0
  615. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  616. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  617. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  618. package/skills/synabun/SKILL.md +10 -7
  619. package/skills/synabun/modules/audit.md +1 -5
  620. package/skills/synabun/modules/changelog.md +1 -5
  621. package/skills/synabun/modules/idea.md +1 -1
  622. package/skills/synabun/modules/memorize.md +6 -9
  623. package/skills/synabun/modules/schedule.md +6 -6
  624. package/mcp-server/dist/services/profiles.d.ts +0 -120
  625. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  626. package/mcp-server/dist/services/profiles.js +0 -387
  627. package/mcp-server/dist/services/profiles.js.map +0 -1
  628. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  629. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  630. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  631. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  632. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  633. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  634. package/mcp-server/dist/tools/leonardo.js +0 -21
  635. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  636. package/mcp-server/dist/tools/profile.d.ts +0 -17
  637. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  638. package/mcp-server/dist/tools/profile.js +0 -114
  639. package/mcp-server/dist/tools/profile.js.map +0 -1
  640. package/mcp-server/src/services/profiles.ts +0 -428
  641. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  642. package/mcp-server/src/tools/leonardo.ts +0 -30
  643. package/mcp-server/src/tools/profile.ts +0 -122
  644. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  645. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  646. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  647. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  648. package/skills/leonardo/SKILL.md +0 -168
  649. package/skills/leonardo/icon.svg +0 -1
  650. package/skills/leonardo/modules/browser-guide.md +0 -378
  651. package/skills/leonardo/modules/image-prompter.md +0 -283
  652. package/skills/leonardo/modules/model-advisor.md +0 -100
  653. package/skills/leonardo/modules/prompt-library.md +0 -110
  654. package/skills/leonardo/modules/style-guide.md +0 -186
  655. package/skills/leonardo/modules/video-prompter.md +0 -317
  656. /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
@@ -14,7 +14,7 @@ const TOOL_ELEMENTS = {
14
14
  'claude-code': { toolbar: 'claude-update-badge', menu: 'claude-menu-update-badge' },
15
15
  'codex': { toolbar: 'codex-update-badge', menu: 'codex-menu-update-badge' },
16
16
  'opencode': { toolbar: 'opencode-update-badge', menu: 'opencode-menu-update-badge' },
17
- 'gemini': { toolbar: null, menu: 'gemini-menu-update-badge' },
17
+ 'antigravity': { toolbar: 'antigravity-update-badge', menu: 'antigravity-menu-update-badge' },
18
18
  };
19
19
 
20
20
  // Parent elements whose tooltips are updated when an update badge is visible.
@@ -22,14 +22,14 @@ const PARENT_ELEMENTS = {
22
22
  'claude-code': { toolbar: 'topright-claude-panel-btn', menu: 'menu-terminal-claude' },
23
23
  'codex': { toolbar: 'topright-codex-panel-btn', menu: 'menu-terminal-codex' },
24
24
  'opencode': { toolbar: 'topright-opencode-panel-btn', menu: 'menu-terminal-opencode' },
25
- 'gemini': { toolbar: null, menu: 'menu-terminal-gemini' },
25
+ 'antigravity': { toolbar: 'topright-antigravity-panel-btn', menu: 'menu-terminal-antigravity' },
26
26
  };
27
27
 
28
28
  const TOOL_LABELS = {
29
29
  'claude-code': 'Claude Code',
30
30
  'codex': 'Codex',
31
31
  'opencode': 'OpenCode',
32
- 'gemini': 'Gemini CLI',
32
+ 'antigravity': 'Antigravity CLI',
33
33
  };
34
34
 
35
35
  // Cached server response so click handlers can read per-tool updateCommand
@@ -239,7 +239,9 @@ function _toastEsc(s) {
239
239
  }
240
240
 
241
241
  export function showUpdateToast({ updates, errors, onClick } = {}) {
242
- document.querySelectorAll('.update-check-toast').forEach(el => el.remove());
242
+ // One update toast at a time; the notice after an automatic restart (ui-crash-notice.js) wears the same toast
243
+ // and stays until it is dismissed.
244
+ document.querySelectorAll('.update-check-toast').forEach(el => { if (!el.classList.contains('crash-notice')) el.remove(); });
243
245
 
244
246
  const toast = document.createElement('div');
245
247
  toast.className = 'update-check-toast';
@@ -3,15 +3,25 @@
3
3
  // Body-appended, overflow-proof tooltip for data-tooltip attributes
4
4
  // ═══════════════════════════════════════════
5
5
 
6
+ import { boundsForPoint, frameRect } from './app-frame.js';
7
+ import { isWindowsPlatform } from './desktop-bridge.js';
8
+
6
9
  /**
7
10
  * Initialize the tooltip system.
8
11
  * Creates a body-appended tooltip element and delegates
9
12
  * mouseover/mouseout on any [data-tooltip] elements.
10
13
  */
11
14
  export function initTooltip() {
15
+ if (document.documentElement?.classList) {
16
+ document.documentElement.classList.toggle('platform-win32', isWindowsPlatform(globalThis.window));
17
+ }
12
18
  const tip = document.createElement('div');
13
19
  tip.className = 'ui-tooltip';
14
- tip.innerHTML = '<span class="ui-tooltip-arrow"></span><span class="ui-tooltip-text"></span>';
20
+ const arrowEl = document.createElement('span');
21
+ arrowEl.className = 'ui-tooltip-arrow';
22
+ const textEl = document.createElement('span');
23
+ textEl.className = 'ui-tooltip-text';
24
+ tip.append(arrowEl, textEl);
15
25
  document.body.appendChild(tip);
16
26
 
17
27
  let showTimer = null;
@@ -27,7 +37,12 @@ export function initTooltip() {
27
37
  // control's tooltip over the open menu: while one is open, the control stays
28
38
  // quiet.
29
39
  const OPEN_MENU_INSIDE = '.cp-dropdown.open > .cp-dd-menu, .cxp-dropdown.open > .cxp-dd-menu, .ocpv2-dropdown.open > .ocpv2-dd-menu';
30
- function openMenuInside(el) { return !!el.querySelector(OPEN_MENU_INSIDE); }
40
+ function openMenuInside(el) {
41
+ if (el.classList?.contains('term-minimized-pill') || el.classList?.contains('term-minimized-pill-close')) return false;
42
+ return !!el.querySelector(OPEN_MENU_INSIDE);
43
+ }
44
+
45
+ const rectKey = (r) => r.left + ',' + r.top + ',' + r.width + ',' + r.height;
31
46
 
32
47
  // Swap the placement class only: a reposition (the follow loop below) must keep .visible.
33
48
  function setPlacement(placement) {
@@ -35,24 +50,27 @@ export function initTooltip() {
35
50
  tip.classList.add(placement);
36
51
  }
37
52
 
38
- function positionTip(el) {
39
- const r = el.getBoundingClientRect();
53
+ function positionTip(el, knownRect = null) {
54
+ const r = knownRect || el.getBoundingClientRect();
40
55
  const tw = tip.offsetWidth;
41
56
  const th = tip.offsetHeight;
42
57
  const gap = 8;
43
58
  const preferred = el.getAttribute('data-tooltip-pos');
59
+ // Kept inside the app frame for a control in it; one on the bar or an explorer keeps the window.
60
+ const b = boundsForPoint(frameRect(), r.left + r.width / 2, r.top + r.height / 2)
61
+ || { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
44
62
 
45
63
  // Left-side placement (session dropdowns in sidepanels)
46
64
  // Anchor to the left edge of the containing sidepanel so tooltip always appears fully outside
47
65
  if (preferred === 'left') {
48
- const panel = el.closest('.claude-panel, .codex-panel, .ocp-panel, .assistant-panel, .menubar-dropdown--resume');
66
+ const panel = el.closest('.claude-panel, .codex-panel, .ocp-panel, .agy-panel, .assistant-panel, .menubar-dropdown--resume');
49
67
  const anchorLeft = panel ? panel.getBoundingClientRect().left : r.left;
50
- if (anchorLeft - gap - tw > 4) {
68
+ if (anchorLeft - gap - tw > b.left + 4) {
51
69
  setPlacement('left');
52
70
  tip.style.top = (r.top + r.height / 2 - th / 2) + 'px';
53
71
  tip.style.left = (anchorLeft - gap - tw) + 'px';
54
72
  tip.style.setProperty('--arrow-y', (th / 2) + 'px');
55
- return;
73
+ return { rect: r, width: tw };
56
74
  }
57
75
  }
58
76
 
@@ -60,31 +78,32 @@ export function initTooltip() {
60
78
  const inWbToolbar = !!el.closest('#wb-toolbar');
61
79
  const rightAnchor = el.closest('.menubar-dropdown--resume');
62
80
  const anchorRight = rightAnchor ? rightAnchor.getBoundingClientRect().right : r.right;
63
- if ((preferred === 'right' || inWbToolbar) && anchorRight + gap + tw < window.innerWidth - 4) {
81
+ if ((preferred === 'right' || inWbToolbar) && anchorRight + gap + tw < b.right - 4) {
64
82
  setPlacement('right');
65
83
  tip.style.top = (r.top + r.height / 2 - th / 2) + 'px';
66
84
  tip.style.left = (anchorRight + gap) + 'px';
67
85
  tip.style.setProperty('--arrow-y', (th / 2) + 'px');
68
- return;
86
+ return { rect: r, width: tw };
69
87
  }
70
88
 
71
89
  // Elements near the top (title bar) → force below
72
90
  const forceBelow = preferred === 'below' || el.closest('#title-bar');
73
91
  let top = forceBelow ? r.bottom + gap : r.top - th - gap;
74
92
  let placement = forceBelow ? 'below' : 'above';
75
- if (!forceBelow && top < 4) {
93
+ if (!forceBelow && top < b.top + 4) {
76
94
  top = r.bottom + gap;
77
95
  placement = 'below';
78
96
  }
79
97
  let left = r.left + r.width / 2 - tw / 2;
80
- if (left < 4) left = 4;
81
- if (left + tw > window.innerWidth - 4) left = window.innerWidth - 4 - tw;
98
+ if (left + tw > b.right - 4) left = b.right - 4 - tw;
99
+ if (left < b.left + 4) left = b.left + 4;
82
100
  setPlacement(placement);
83
101
  tip.style.top = top + 'px';
84
102
  tip.style.left = left + 'px';
85
103
  const arrowLeft = r.left + r.width / 2 - left;
86
104
  tip.style.setProperty('--arrow-x', arrowLeft + 'px');
87
105
  tip.style.setProperty('--arrow-y', '');
106
+ return { rect: r, width: tw };
88
107
  }
89
108
 
90
109
  function suppressTitle(el) {
@@ -93,10 +112,16 @@ export function initTooltip() {
93
112
  el._savedTitle = el.getAttribute('title');
94
113
  el.removeAttribute('title');
95
114
  }
96
- el.querySelectorAll('[title]').forEach(child => {
97
- child._savedTitle = child.getAttribute('title');
98
- child.removeAttribute('title');
99
- });
115
+ const titledChildren = [...el.querySelectorAll('[title]')];
116
+ if (titledChildren.length) {
117
+ el._savedTitleNodes = titledChildren;
118
+ for (const child of titledChildren) {
119
+ child._savedTitle = child.getAttribute('title');
120
+ child.removeAttribute('title');
121
+ }
122
+ } else {
123
+ delete el._savedTitleNodes;
124
+ }
100
125
  }
101
126
 
102
127
  function restoreTitle(el) {
@@ -104,12 +129,15 @@ export function initTooltip() {
104
129
  el.setAttribute('title', el._savedTitle);
105
130
  delete el._savedTitle;
106
131
  }
107
- el.querySelectorAll('*').forEach(child => {
108
- if (child._savedTitle !== undefined) {
109
- child.setAttribute('title', child._savedTitle);
110
- delete child._savedTitle;
132
+ if (el._savedTitleNodes) {
133
+ for (const child of el._savedTitleNodes) {
134
+ if (child._savedTitle !== undefined) {
135
+ child.setAttribute('title', child._savedTitle);
136
+ delete child._savedTitle;
137
+ }
111
138
  }
112
- });
139
+ delete el._savedTitleNodes;
140
+ }
113
141
  }
114
142
 
115
143
  function show(el) {
@@ -117,7 +145,6 @@ export function initTooltip() {
117
145
  if (!text || openMenuInside(el)) return;
118
146
  clearTimeout(hideTimer);
119
147
  suppressTitle(el);
120
- const textEl = tip.querySelector('.ui-tooltip-text');
121
148
  const nlIdx = text.indexOf('\n');
122
149
  if (nlIdx !== -1) {
123
150
  let main = text.slice(0, nlIdx);
@@ -136,37 +163,22 @@ export function initTooltip() {
136
163
  }
137
164
  currentTarget = el;
138
165
  tip.style.display = 'block';
139
- tip.offsetHeight; // force reflow so dimensions are measurable
140
- positionTip(el);
166
+ const { rect: initialRect, width: initialWidth } = positionTip(el);
141
167
  tip.classList.add('visible');
142
- // Re-position on next frame — first show after display:none can mis-measure
143
- requestAnimationFrame(() => {
144
- if (currentTarget === el) {
145
- positionTip(el);
146
- tip.classList.add('visible');
147
- }
148
- });
149
- // Some targets resize on hover (e.g. tray pill label expands max-width
150
- // 100→300px over ~300ms). Without follow-up positioning, the tooltip
151
- // stays anchored to the un-expanded rect and the pill grows leftward
152
- // over it. Drive a rAF loop for the duration of any size/position
153
- // transition so the tooltip tracks the target.
154
- const followFor = 360; // ms — upper bound, slightly longer than the longest pill transition
155
- const stopAt = performance.now() + followFor;
156
- // Self-terminate once the target stops moving: a static target (the vast
157
- // majority of tooltips) settles in ~2 frames instead of running the full
158
- // 360ms rAF/getBoundingClientRect loop, while an animating pill keeps being
159
- // followed until it settles or the cap is hit.
160
- let lastRectKey = '';
168
+
169
+ // Follow targets that actually animate their geometry on hover (via transitionrun),
170
+ // without polling static targets across multiple rAFs.
171
+ const followFor = 360;
172
+ let stopAt = 0;
173
+ let lastRectKey = rectKey(initialRect);
161
174
  let stableTicks = 0;
162
175
  const tick = () => {
163
176
  repositionRafId = 0;
164
177
  if (currentTarget !== el) return;
165
- positionTip(el);
166
- const r = el.getBoundingClientRect();
167
- const key = r.left + ',' + r.top + ',' + r.width + ',' + r.height;
178
+ const { rect: r } = positionTip(el);
179
+ const key = rectKey(r);
168
180
  if (key === lastRectKey) {
169
- if (++stableTicks >= 2) return; // target settled — stop early
181
+ if (++stableTicks >= 2) return;
170
182
  } else {
171
183
  stableTicks = 0;
172
184
  lastRectKey = key;
@@ -179,6 +191,8 @@ export function initTooltip() {
179
191
  if (currentTarget !== el) return;
180
192
  if (event.target !== el && !el.contains(event.target)) return;
181
193
  if (!/width|max-width|transform|margin|padding|left|right|top|bottom/.test(event.propertyName || '')) return;
194
+ stopAt = performance.now() + followFor;
195
+ stableTicks = 0;
182
196
  if (!repositionRafId) repositionRafId = requestAnimationFrame(tick);
183
197
  };
184
198
  repositionEndHandler = (event) => {
@@ -188,9 +202,25 @@ export function initTooltip() {
188
202
  };
189
203
  el.addEventListener('transitionrun', repositionRunHandler);
190
204
  el.addEventListener('transitionend', repositionEndHandler);
191
- // Kick off one immediate rAF in case the transition already started on
192
- // mouseenter before our listeners attached.
193
- if (!repositionRafId) repositionRafId = requestAnimationFrame(tick);
205
+
206
+ // One check on the next frame (a single rect read): metrics that settle after display:none, or a
207
+ // hover transition that began before the listeners above were attached (the 16-20 ms show delay).
208
+ if (!repositionRafId) {
209
+ repositionRafId = requestAnimationFrame(() => {
210
+ repositionRafId = 0;
211
+ if (currentTarget !== el) return;
212
+ const r = el.getBoundingClientRect();
213
+ const key = rectKey(r);
214
+ if (key !== lastRectKey || tip.offsetWidth !== initialWidth) {
215
+ lastRectKey = key;
216
+ positionTip(el, r);
217
+ if (key !== rectKey(initialRect)) {
218
+ stopAt = performance.now() + followFor;
219
+ repositionRafId = requestAnimationFrame(tick);
220
+ }
221
+ }
222
+ });
223
+ }
194
224
  }
195
225
 
196
226
  function hide() {
@@ -225,7 +255,7 @@ export function initTooltip() {
225
255
  clearTimeout(hideTimer);
226
256
  if (currentTarget) {
227
257
  hide();
228
- show(el);
258
+ showTimer = setTimeout(() => show(el), 16);
229
259
  } else {
230
260
  showTimer = setTimeout(() => show(el), 20);
231
261
  }
@@ -0,0 +1,233 @@
1
+ // ═══════════════════════════════════════════
2
+ // The top-right toolbar's overflow: one row, always.
3
+ // When the row is wider than its band (#topright-controls' max-width), the lowest-priority buttons leave the row,
4
+ // from the start of OVERFLOW_ORDER (topright-overflow-logic.js), and are listed in the ⋯ menu (#topright-overflow-btn) instead: icon, label,
5
+ // badge and active state copied from the button each time the menu opens, a click forwarded to the button itself,
6
+ // so every handler stays the button's own. The workspace switcher and the ⋯ never leave the row; the tools toggle
7
+ // leaves it last of all, in a band too narrow for anything else.
8
+ // An item that opens a dropdown of its own (bookmarks, share) is pinned back into the row before it is clicked, so
9
+ // its dropdown hangs where it always does; the pin is let go when its dropdown closes.
10
+ // ═══════════════════════════════════════════
11
+
12
+ import { emit, on } from './state.js';
13
+ import { t } from './i18n.js';
14
+ import { OVERFLOW_ORDER, overflowCount, clampDropdownX } from './topright-overflow-logic.js';
15
+
16
+ export { OVERFLOW_ORDER, overflowCount };
17
+
18
+ // The element that leaves the row for each entry (a button inside an overlay goes with its overlay) and the button
19
+ // the menu forwards to.
20
+ const ROW_ITEM = { 'topright-bookmarks-btn': 'bookmarks-overlay', 'invite-overlay': 'invite-overlay' };
21
+ const BUTTON = { 'invite-overlay': 'invite-btn' };
22
+ const DROPDOWN = { 'topright-bookmarks-btn': 'bookmarks-dropdown', 'invite-overlay': 'invite-dropdown' };
23
+
24
+ const labelOf = (btn) => btn.getAttribute('aria-label') || btn.dataset.tooltip || btn.title || btn.id;
25
+
26
+ export function initToprightOverflow() {
27
+ const $ = (id) => document.getElementById(id);
28
+ const controls = $('topright-controls');
29
+ const inner = $('topright-inner');
30
+ const group = $('topright-buttons');
31
+ const moreBtn = $('topright-overflow-btn');
32
+ const menu = $('topright-overflow-menu');
33
+ if (!controls || !inner || !group || !moreBtn || !menu) return null;
34
+
35
+ const entries = OVERFLOW_ORDER.map((id) => ({
36
+ id,
37
+ item: $(ROW_ITEM[id] || id),
38
+ button: $(BUTTON[id] || id),
39
+ dropdown: DROPDOWN[id] ? $(DROPDOWN[id]) : null,
40
+ })).filter((e) => e.item && e.button);
41
+ let pinned = null;
42
+ let open = false;
43
+
44
+ const shownInRow = (el) => el.offsetParent !== null || getComputedStyle(el).display !== 'none';
45
+ const isOverflowed = (e) => e.item.classList.contains('tr-overflowed');
46
+
47
+ // The dividers of the dock: one with no shown tool after it (up to the next divider or the end) goes too.
48
+ const tidyDividers = () => {
49
+ for (const div of inner.querySelectorAll(':scope > .tr-divider')) {
50
+ let el = div.nextElementSibling;
51
+ let any = false;
52
+ while (el && !el.classList.contains('tr-divider')) {
53
+ if (!el.classList.contains('tr-overflowed') && el.style.display !== 'none') { any = true; break; }
54
+ el = el.nextElementSibling;
55
+ }
56
+ div.classList.toggle('tr-overflowed', !any);
57
+ }
58
+ };
59
+
60
+ const fit = () => {
61
+ for (const e of entries) e.item.classList.remove('tr-overflowed');
62
+ for (const div of inner.querySelectorAll(':scope > .tr-divider')) div.classList.remove('tr-overflowed');
63
+ const available = parseFloat(getComputedStyle(controls).maxWidth);
64
+ const gap = parseFloat(getComputedStyle(controls).columnGap) || 0;
65
+ const innerGap = parseFloat(getComputedStyle(inner).columnGap) || 0;
66
+ const groupGap = parseFloat(getComputedStyle(group).columnGap) || 0;
67
+ const dockShown = !controls.classList.contains('tools-hidden');
68
+ // the row as it would be with everything in it and no ⋯ (the ⋯ is left out, not hidden: hiding it here would
69
+ // change the bar's class and wake the observers again)
70
+ const moreShown = controls.classList.contains('has-overflow') ? moreBtn.getBoundingClientRect().width + groupGap : 0;
71
+ const total = (dockShown ? inner.getBoundingClientRect().width + gap : 0) + group.getBoundingClientRect().width - moreShown;
72
+ if (!Number.isFinite(available)) return;
73
+ const widths = entries.map((e) => {
74
+ if (!shownInRow(e.item) || e.item.style.display === 'none') return 0;
75
+ const inDock = inner.contains(e.item);
76
+ if (inDock && !dockShown) return 0;
77
+ return e.item.getBoundingClientRect().width + (inDock ? innerGap : groupGap);
78
+ });
79
+ const menuWidth = 32 + groupGap;
80
+ const pinnedIdx = pinned ? [entries.indexOf(pinned)] : [];
81
+ const { hidden } = overflowCount({ total, available, widths, menuWidth, pinned: pinnedIdx });
82
+ for (const i of hidden) entries[i].item.classList.add('tr-overflowed');
83
+ // The dock's dividers: the 2px margins and gaps they free are not counted above, so the row only gets narrower.
84
+ tidyDividers();
85
+ if (controls.classList.contains('has-overflow') !== hidden.length > 0) controls.classList.toggle('has-overflow', hidden.length > 0);
86
+ if (!hidden.length && open) close();
87
+ else if (open) render();
88
+ };
89
+
90
+ let frame = 0;
91
+ const schedule = () => {
92
+ if (frame) return;
93
+ frame = requestAnimationFrame(() => { frame = 0; fit(); });
94
+ };
95
+
96
+ const render = () => {
97
+ menu.textContent = '';
98
+ // in the row's own order, as they would stand in it
99
+ const listed = entries.filter(isOverflowed)
100
+ .sort((a, b) => (a.item.compareDocumentPosition(b.item) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1));
101
+ for (const e of listed) {
102
+ const row = document.createElement('button');
103
+ row.type = 'button';
104
+ row.className = 'topright-overflow-item';
105
+ row.setAttribute('role', 'menuitem');
106
+ row.dataset.target = e.id;
107
+ if (e.button.classList.contains('active')) row.classList.add('active');
108
+ const icon = document.createElement('span');
109
+ icon.className = 'topright-overflow-icon';
110
+ const svg = e.button.querySelector('svg');
111
+ if (svg) icon.appendChild(svg.cloneNode(true));
112
+ const label = document.createElement('span');
113
+ label.className = 'topright-overflow-label';
114
+ label.textContent = labelOf(e.button);
115
+ row.append(icon, label);
116
+ const badge = e.button.querySelector('.count-badge');
117
+ const text = badge?.textContent.trim();
118
+ if (badge && text && getComputedStyle(badge).display !== 'none') {
119
+ const b = document.createElement('span');
120
+ b.className = `${badge.className} topright-overflow-badge`;
121
+ b.removeAttribute('id');
122
+ b.textContent = text;
123
+ row.appendChild(b);
124
+ }
125
+ row.addEventListener('click', () => activate(e));
126
+ menu.appendChild(row);
127
+ }
128
+ };
129
+
130
+ const items = () => [...menu.querySelectorAll('.topright-overflow-item')];
131
+
132
+ function openMenu(focusFirst) {
133
+ emit('panel:close-all-dropdowns');
134
+ render();
135
+ open = true;
136
+ menu.hidden = false;
137
+ moreBtn.setAttribute('aria-expanded', 'true');
138
+ moreBtn.classList.add('active');
139
+ if (focusFirst) items()[0]?.focus();
140
+ }
141
+ function close(refocus) {
142
+ if (!open) return;
143
+ open = false;
144
+ menu.hidden = true;
145
+ moreBtn.setAttribute('aria-expanded', 'false');
146
+ moreBtn.classList.remove('active');
147
+ if (refocus) moreBtn.focus();
148
+ }
149
+
150
+ function activate(e) {
151
+ close();
152
+ if (e.dropdown) {
153
+ pinned = e;
154
+ fit();
155
+ // let go of the pin once its dropdown closes
156
+ const watch = new MutationObserver(() => {
157
+ if (e.dropdown.style.display === 'none') { watch.disconnect(); if (pinned === e) { pinned = null; schedule(); } }
158
+ });
159
+ watch.observe(e.dropdown, { attributes: true, attributeFilter: ['style'] });
160
+ setTimeout(() => e.button.click(), 0);
161
+ return;
162
+ }
163
+ e.button.click();
164
+ }
165
+
166
+ moreBtn.addEventListener('click', (ev) => {
167
+ ev.stopPropagation();
168
+ if (open) close(); else openMenu(ev.detail === 0);
169
+ });
170
+ moreBtn.addEventListener('keydown', (ev) => {
171
+ if (ev.key === 'ArrowDown' || ev.key === 'ArrowUp') { ev.preventDefault(); if (!open) openMenu(false); const list = items(); (ev.key === 'ArrowUp' ? list.at(-1) : list[0])?.focus(); }
172
+ });
173
+ menu.addEventListener('keydown', (ev) => {
174
+ const list = items();
175
+ const at = list.indexOf(document.activeElement);
176
+ if (ev.key === 'ArrowDown') { ev.preventDefault(); list[(at + 1) % list.length]?.focus(); }
177
+ else if (ev.key === 'ArrowUp') { ev.preventDefault(); list[(at - 1 + list.length) % list.length]?.focus(); }
178
+ else if (ev.key === 'Home') { ev.preventDefault(); list[0]?.focus(); }
179
+ else if (ev.key === 'End') { ev.preventDefault(); list.at(-1)?.focus(); }
180
+ else if (ev.key === 'Tab') close();
181
+ });
182
+ document.addEventListener('keydown', (ev) => { if (open && ev.key === 'Escape') { ev.stopPropagation(); close(true); } }, true);
183
+ document.addEventListener('pointerdown', (ev) => { if (open && !menu.contains(ev.target) && !moreBtn.contains(ev.target)) close(); }, true);
184
+ on('panel:close-all-dropdowns', () => close());
185
+
186
+ moreBtn.setAttribute('aria-label', t('toolbar.more'));
187
+ moreBtn.dataset.tooltip = t('toolbar.more');
188
+
189
+ // Live: the band (window, side panels, explorers, Focus Mode) and the row's own contents.
190
+ const ro = new ResizeObserver(schedule);
191
+ ro.observe(document.documentElement);
192
+ ro.observe(controls);
193
+ for (const e of entries) ro.observe(e.item);
194
+ ro.observe(inner.querySelector('#workspace-overlay') || inner);
195
+ new MutationObserver(schedule).observe(document.documentElement, { attributes: true, attributeFilter: ['style', 'class'] });
196
+ new MutationObserver(schedule).observe(document.body, { attributes: true, attributeFilter: ['style', 'class'] });
197
+ new MutationObserver(schedule).observe(controls, { attributes: true, attributeFilter: ['class'] });
198
+ for (const e of entries) new MutationObserver(schedule).observe(e.item, { attributes: true, attributeFilter: ['style'] });
199
+ const bg = $('static-bg');
200
+ if (bg) new MutationObserver(schedule).observe(bg, { attributes: true, attributeFilter: ['class'] });
201
+ // The dropdowns of the bar, kept whole on screen: right of the band's clip (sidebar, Focus Mode rail and left
202
+ // panels + 20px, as #topright-controls' clip-path) and left of the viewport's edge, as wide as that room at most.
203
+ const EDGE = 8;
204
+ const place = (dd) => {
205
+ dd.style.translate = '';
206
+ dd.style.maxWidth = '';
207
+ if (dd.style.display === 'none' || !dd.isConnected) return;
208
+ const sidebar = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--sidebar-total-width')) || 0;
209
+ const minLeft = Math.max(EDGE, sidebar + 20);
210
+ const maxRight = document.documentElement.clientWidth - EDGE;
211
+ let r = dd.getBoundingClientRect();
212
+ const first = clampDropdownX({ left: r.left, width: r.width, minLeft, maxRight });
213
+ if (first.maxWidth !== null) { dd.style.maxWidth = `${first.maxWidth}px`; r = dd.getBoundingClientRect(); }
214
+ const { shift } = clampDropdownX({ left: r.left, width: r.width, minLeft, maxRight });
215
+ if (shift) dd.style.translate = `${shift}px 0`;
216
+ };
217
+ const dropdowns = ['ws-dropdown', 'bookmarks-dropdown', 'invite-dropdown'].map((id) => $(id)).filter(Boolean);
218
+ for (const dd of dropdowns) {
219
+ // its own writes change the style too: act on a change of shown / hidden only
220
+ let shown = dd.style.display !== 'none';
221
+ new MutationObserver(() => {
222
+ const now = dd.style.display !== 'none';
223
+ if (now !== shown) { shown = now; place(dd); }
224
+ }).observe(dd, { attributes: true, attributeFilter: ['style'] });
225
+ }
226
+ let placing = 0;
227
+ const placeOpen = () => { cancelAnimationFrame(placing); placing = requestAnimationFrame(() => dropdowns.forEach(place)); };
228
+ window.addEventListener('resize', placeOpen);
229
+ new ResizeObserver(placeOpen).observe(controls);
230
+ window.addEventListener('resize', schedule);
231
+ fit();
232
+ return { fit, close };
233
+ }
@@ -9,6 +9,7 @@ import { fetchTrash, restoreFromTrash, purgeTrash, deleteMemoryPermanent } from
9
9
  import { formatTrashAge, formatMemoryContent } from './utils.js';
10
10
  import { storage } from './storage.js';
11
11
  import { isGuest, hasPermission, showGuestToast } from './ui-sync.js';
12
+ import { centeredInFrame, frameRect } from './app-frame.js';
12
13
 
13
14
  const $ = (id) => document.getElementById(id);
14
15
 
@@ -96,7 +97,7 @@ function openTrashPanel() {
96
97
  return;
97
98
  }
98
99
  const existing = $('trash-window');
99
- if (existing) { existing.style.zIndex = '50101'; return; }
100
+ if (existing) { existing.style.zIndex = '49901'; return; }
100
101
 
101
102
  trashPanelOpen = true;
102
103
  trashSelectedId = null;
@@ -110,12 +111,13 @@ function openTrashPanel() {
110
111
  const saved = JSON.parse(storage.getItem('neural-panel-trash-window') || 'null');
111
112
  if (saved) {
112
113
  if (saved.left && saved.left !== 'auto') win.style.left = saved.left;
113
- if (saved.top) win.style.top = Math.max(48, parseInt(saved.top)) + 'px';
114
+ if (saved.top) win.style.top = Math.max(frameRect().top, parseInt(saved.top)) + 'px';
114
115
  if (saved.width) win.style.width = saved.width;
115
116
  if (saved.height) win.style.height = saved.height;
116
117
  } else {
117
- win.style.left = Math.max(20, (window.innerWidth - 640) / 2) + 'px';
118
- win.style.top = Math.max(48, (window.innerHeight - 480) / 2) + 'px';
118
+ const at = centeredInFrame(640, 480); // in the app frame
119
+ win.style.left = at.left + 'px';
120
+ win.style.top = at.top + 'px';
119
121
  }
120
122
 
121
123
  win.innerHTML = `