synabun 2.0.7 → 2.0.10

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 (565) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +1 -1
  3. package/THIRD-PARTY-LICENSES.md +46 -4
  4. package/hooks/claude-code/post-plan.mjs +6 -30
  5. package/hooks/claude-code/session-start.mjs +1 -4
  6. package/hooks/claude-code/shared.mjs +106 -72
  7. package/launcher.mjs +9 -3
  8. package/lib/package-processes.js +670 -0
  9. package/lib/runtime-dependencies.js +225 -0
  10. package/lib/start-launcher.js +6 -1
  11. package/mcp-server/dist/services/browser-bench.d.ts +1 -1
  12. package/mcp-server/dist/services/browser-bench.d.ts.map +1 -1
  13. package/mcp-server/dist/services/browser-bench.js +1 -1
  14. package/mcp-server/dist/services/browser-bench.js.map +1 -1
  15. package/mcp-server/dist/services/categories.d.ts +35 -2
  16. package/mcp-server/dist/services/categories.d.ts.map +1 -1
  17. package/mcp-server/dist/services/categories.js +77 -33
  18. package/mcp-server/dist/services/categories.js.map +1 -1
  19. package/mcp-server/dist/services/desktop-bench.d.ts +7 -7
  20. package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -1
  21. package/mcp-server/dist/services/desktop-bench.js +1 -1
  22. package/mcp-server/dist/services/desktop-bench.js.map +1 -1
  23. package/mcp-server/dist/tools/agents.d.ts +1 -1
  24. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  25. package/mcp-server/dist/tools/agents.js +1 -1
  26. package/mcp-server/dist/tools/agents.js.map +1 -1
  27. package/mcp-server/dist/tools/bluesky.js +1 -1
  28. package/mcp-server/dist/tools/bluesky.js.map +1 -1
  29. package/mcp-server/dist/tools/browser-advanced.d.ts +1 -1
  30. package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -1
  31. package/mcp-server/dist/tools/browser-advanced.js +1 -1
  32. package/mcp-server/dist/tools/browser-advanced.js.map +1 -1
  33. package/mcp-server/dist/tools/browser-batch.d.ts +1 -1
  34. package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -1
  35. package/mcp-server/dist/tools/browser-batch.js +1 -1
  36. package/mcp-server/dist/tools/browser-batch.js.map +1 -1
  37. package/mcp-server/dist/tools/browser-cheatsheet.d.ts +1 -1
  38. package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -1
  39. package/mcp-server/dist/tools/browser-cheatsheet.js +1 -1
  40. package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -1
  41. package/mcp-server/dist/tools/browser-interact.d.ts +1 -1
  42. package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -1
  43. package/mcp-server/dist/tools/browser-interact.js +1 -1
  44. package/mcp-server/dist/tools/browser-interact.js.map +1 -1
  45. package/mcp-server/dist/tools/browser-navigate.d.ts +1 -1
  46. package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -1
  47. package/mcp-server/dist/tools/browser-navigate.js +1 -1
  48. package/mcp-server/dist/tools/browser-navigate.js.map +1 -1
  49. package/mcp-server/dist/tools/browser-observe.d.ts +1 -1
  50. package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -1
  51. package/mcp-server/dist/tools/browser-observe.js +1 -1
  52. package/mcp-server/dist/tools/browser-observe.js.map +1 -1
  53. package/mcp-server/dist/tools/card-tools.d.ts +1 -1
  54. package/mcp-server/dist/tools/card-tools.d.ts.map +1 -1
  55. package/mcp-server/dist/tools/card-tools.js +1 -1
  56. package/mcp-server/dist/tools/card-tools.js.map +1 -1
  57. package/mcp-server/dist/tools/category.d.ts +1 -1
  58. package/mcp-server/dist/tools/category.d.ts.map +1 -1
  59. package/mcp-server/dist/tools/category.js +5 -1
  60. package/mcp-server/dist/tools/category.js.map +1 -1
  61. package/mcp-server/dist/tools/choice.d.ts +1 -1
  62. package/mcp-server/dist/tools/choice.d.ts.map +1 -1
  63. package/mcp-server/dist/tools/choice.js +1 -1
  64. package/mcp-server/dist/tools/choice.js.map +1 -1
  65. package/mcp-server/dist/tools/computer.d.ts +1 -1
  66. package/mcp-server/dist/tools/computer.d.ts.map +1 -1
  67. package/mcp-server/dist/tools/computer.js +1 -1
  68. package/mcp-server/dist/tools/computer.js.map +1 -1
  69. package/mcp-server/dist/tools/discord-channel.d.ts +1 -1
  70. package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -1
  71. package/mcp-server/dist/tools/discord-channel.js +1 -1
  72. package/mcp-server/dist/tools/discord-channel.js.map +1 -1
  73. package/mcp-server/dist/tools/discord-guild.d.ts +1 -1
  74. package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -1
  75. package/mcp-server/dist/tools/discord-guild.js +1 -1
  76. package/mcp-server/dist/tools/discord-guild.js.map +1 -1
  77. package/mcp-server/dist/tools/discord-member.d.ts +1 -1
  78. package/mcp-server/dist/tools/discord-member.d.ts.map +1 -1
  79. package/mcp-server/dist/tools/discord-member.js +1 -1
  80. package/mcp-server/dist/tools/discord-member.js.map +1 -1
  81. package/mcp-server/dist/tools/discord-message.d.ts +1 -1
  82. package/mcp-server/dist/tools/discord-message.d.ts.map +1 -1
  83. package/mcp-server/dist/tools/discord-message.js +1 -1
  84. package/mcp-server/dist/tools/discord-message.js.map +1 -1
  85. package/mcp-server/dist/tools/discord-onboarding.d.ts +1 -1
  86. package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -1
  87. package/mcp-server/dist/tools/discord-onboarding.js +1 -1
  88. package/mcp-server/dist/tools/discord-onboarding.js.map +1 -1
  89. package/mcp-server/dist/tools/discord-role.d.ts +1 -1
  90. package/mcp-server/dist/tools/discord-role.d.ts.map +1 -1
  91. package/mcp-server/dist/tools/discord-role.js +1 -1
  92. package/mcp-server/dist/tools/discord-role.js.map +1 -1
  93. package/mcp-server/dist/tools/discord-thread.d.ts +1 -1
  94. package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -1
  95. package/mcp-server/dist/tools/discord-thread.js +1 -1
  96. package/mcp-server/dist/tools/discord-thread.js.map +1 -1
  97. package/mcp-server/dist/tools/discord-webhook.d.ts +1 -1
  98. package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -1
  99. package/mcp-server/dist/tools/discord-webhook.js +1 -1
  100. package/mcp-server/dist/tools/discord-webhook.js.map +1 -1
  101. package/mcp-server/dist/tools/fb-groups.d.ts +1 -1
  102. package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -1
  103. package/mcp-server/dist/tools/fb-groups.js +1 -1
  104. package/mcp-server/dist/tools/fb-groups.js.map +1 -1
  105. package/mcp-server/dist/tools/forget.d.ts +1 -1
  106. package/mcp-server/dist/tools/forget.d.ts.map +1 -1
  107. package/mcp-server/dist/tools/forget.js +1 -1
  108. package/mcp-server/dist/tools/forget.js.map +1 -1
  109. package/mcp-server/dist/tools/git-tools.d.ts +1 -1
  110. package/mcp-server/dist/tools/git-tools.d.ts.map +1 -1
  111. package/mcp-server/dist/tools/git-tools.js +1 -1
  112. package/mcp-server/dist/tools/git-tools.js.map +1 -1
  113. package/mcp-server/dist/tools/gsc/experience.d.ts +1 -1
  114. package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -1
  115. package/mcp-server/dist/tools/gsc/experience.js +1 -1
  116. package/mcp-server/dist/tools/gsc/experience.js.map +1 -1
  117. package/mcp-server/dist/tools/gsc/indexing.d.ts +1 -1
  118. package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -1
  119. package/mcp-server/dist/tools/gsc/indexing.js +1 -1
  120. package/mcp-server/dist/tools/gsc/indexing.js.map +1 -1
  121. package/mcp-server/dist/tools/gsc/inspect.d.ts +1 -1
  122. package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -1
  123. package/mcp-server/dist/tools/gsc/inspect.js +1 -1
  124. package/mcp-server/dist/tools/gsc/inspect.js.map +1 -1
  125. package/mcp-server/dist/tools/gsc/navigate.d.ts +1 -1
  126. package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -1
  127. package/mcp-server/dist/tools/gsc/navigate.js +1 -1
  128. package/mcp-server/dist/tools/gsc/navigate.js.map +1 -1
  129. package/mcp-server/dist/tools/gsc/performance.d.ts +1 -1
  130. package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -1
  131. package/mcp-server/dist/tools/gsc/performance.js +1 -1
  132. package/mcp-server/dist/tools/gsc/performance.js.map +1 -1
  133. package/mcp-server/dist/tools/gsc/settings.d.ts +1 -1
  134. package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -1
  135. package/mcp-server/dist/tools/gsc/settings.js +1 -1
  136. package/mcp-server/dist/tools/gsc/settings.js.map +1 -1
  137. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  138. package/mcp-server/dist/tools/image-tools.d.ts.map +1 -1
  139. package/mcp-server/dist/tools/image-tools.js +1 -1
  140. package/mcp-server/dist/tools/image-tools.js.map +1 -1
  141. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +1 -1
  142. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -1
  143. package/mcp-server/dist/tools/leonardo-browser-tools.js +1 -1
  144. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -1
  145. package/mcp-server/dist/tools/loop.d.ts +1 -1
  146. package/mcp-server/dist/tools/loop.d.ts.map +1 -1
  147. package/mcp-server/dist/tools/loop.js +1 -1
  148. package/mcp-server/dist/tools/loop.js.map +1 -1
  149. package/mcp-server/dist/tools/memories.d.ts +1 -1
  150. package/mcp-server/dist/tools/memories.d.ts.map +1 -1
  151. package/mcp-server/dist/tools/memories.js +1 -1
  152. package/mcp-server/dist/tools/memories.js.map +1 -1
  153. package/mcp-server/dist/tools/morelogin.d.ts +1 -1
  154. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
  155. package/mcp-server/dist/tools/morelogin.js +1 -1
  156. package/mcp-server/dist/tools/morelogin.js.map +1 -1
  157. package/mcp-server/dist/tools/profile.d.ts +1 -1
  158. package/mcp-server/dist/tools/profile.d.ts.map +1 -1
  159. package/mcp-server/dist/tools/profile.js +1 -1
  160. package/mcp-server/dist/tools/profile.js.map +1 -1
  161. package/mcp-server/dist/tools/recall.d.ts +1 -1
  162. package/mcp-server/dist/tools/recall.d.ts.map +1 -1
  163. package/mcp-server/dist/tools/recall.js +1 -1
  164. package/mcp-server/dist/tools/recall.js.map +1 -1
  165. package/mcp-server/dist/tools/reflect.d.ts +1 -1
  166. package/mcp-server/dist/tools/reflect.d.ts.map +1 -1
  167. package/mcp-server/dist/tools/reflect.js +1 -1
  168. package/mcp-server/dist/tools/reflect.js.map +1 -1
  169. package/mcp-server/dist/tools/remember.d.ts +1 -1
  170. package/mcp-server/dist/tools/remember.d.ts.map +1 -1
  171. package/mcp-server/dist/tools/remember.js +13 -11
  172. package/mcp-server/dist/tools/remember.js.map +1 -1
  173. package/mcp-server/dist/tools/restore.d.ts +1 -1
  174. package/mcp-server/dist/tools/restore.d.ts.map +1 -1
  175. package/mcp-server/dist/tools/restore.js +1 -1
  176. package/mcp-server/dist/tools/restore.js.map +1 -1
  177. package/mcp-server/dist/tools/style-guide-tools.d.ts +1 -1
  178. package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -1
  179. package/mcp-server/dist/tools/style-guide-tools.js +1 -1
  180. package/mcp-server/dist/tools/style-guide-tools.js.map +1 -1
  181. package/mcp-server/dist/tools/sync.d.ts +1 -1
  182. package/mcp-server/dist/tools/sync.d.ts.map +1 -1
  183. package/mcp-server/dist/tools/sync.js +1 -1
  184. package/mcp-server/dist/tools/sync.js.map +1 -1
  185. package/mcp-server/dist/tools/tictactoe-tools.d.ts +1 -1
  186. package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -1
  187. package/mcp-server/dist/tools/tictactoe-tools.js +1 -1
  188. package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -1
  189. package/mcp-server/dist/tools/utils.d.ts +1 -1
  190. package/mcp-server/dist/tools/utils.d.ts.map +1 -1
  191. package/mcp-server/dist/tools/utils.js +1 -1
  192. package/mcp-server/dist/tools/utils.js.map +1 -1
  193. package/mcp-server/dist/tools/whatsapp-send-file.d.ts +1 -1
  194. package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -1
  195. package/mcp-server/dist/tools/whatsapp-send-file.js +1 -1
  196. package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -1
  197. package/mcp-server/dist/tools/whiteboard-tools.d.ts +3 -3
  198. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  199. package/mcp-server/dist/tools/whiteboard-tools.js +1 -1
  200. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  201. package/mcp-server/dist/tools/youtube/analytics.d.ts +1 -1
  202. package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -1
  203. package/mcp-server/dist/tools/youtube/analytics.js +1 -1
  204. package/mcp-server/dist/tools/youtube/analytics.js.map +1 -1
  205. package/mcp-server/dist/tools/youtube/download.d.ts +1 -1
  206. package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -1
  207. package/mcp-server/dist/tools/youtube/download.js +1 -1
  208. package/mcp-server/dist/tools/youtube/download.js.map +1 -1
  209. package/mcp-server/dist/tools/youtube/media.d.ts +1 -1
  210. package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -1
  211. package/mcp-server/dist/tools/youtube/media.js +1 -1
  212. package/mcp-server/dist/tools/youtube/media.js.map +1 -1
  213. package/mcp-server/dist/tools/youtube/metadata.d.ts +1 -1
  214. package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -1
  215. package/mcp-server/dist/tools/youtube/metadata.js +1 -1
  216. package/mcp-server/dist/tools/youtube/metadata.js.map +1 -1
  217. package/mcp-server/dist/tools/youtube/navigate.d.ts +1 -1
  218. package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -1
  219. package/mcp-server/dist/tools/youtube/navigate.js +1 -1
  220. package/mcp-server/dist/tools/youtube/navigate.js.map +1 -1
  221. package/mcp-server/dist/tools/youtube/playlist.d.ts +1 -1
  222. package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -1
  223. package/mcp-server/dist/tools/youtube/playlist.js +1 -1
  224. package/mcp-server/dist/tools/youtube/playlist.js.map +1 -1
  225. package/mcp-server/dist/tools/youtube/schedule.d.ts +1 -1
  226. package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -1
  227. package/mcp-server/dist/tools/youtube/schedule.js +1 -1
  228. package/mcp-server/dist/tools/youtube/schedule.js.map +1 -1
  229. package/mcp-server/dist/tools/youtube/source.d.ts +1 -1
  230. package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -1
  231. package/mcp-server/dist/tools/youtube/source.js +1 -1
  232. package/mcp-server/dist/tools/youtube/source.js.map +1 -1
  233. package/mcp-server/dist/tools/youtube/upload.d.ts +1 -1
  234. package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -1
  235. package/mcp-server/dist/tools/youtube/upload.js +4 -9
  236. package/mcp-server/dist/tools/youtube/upload.js.map +1 -1
  237. package/mcp-server/dist/tui.js +16 -4
  238. package/mcp-server/dist/tui.js.map +1 -1
  239. package/mcp-server/package-lock.json +3 -3
  240. package/mcp-server/package.json +3 -3
  241. package/mcp-server/src/services/browser-bench.ts +1 -1
  242. package/mcp-server/src/services/categories.ts +77 -32
  243. package/mcp-server/src/services/desktop-bench.ts +1 -1
  244. package/mcp-server/src/tools/agents.ts +1 -1
  245. package/mcp-server/src/tools/bluesky.ts +1 -1
  246. package/mcp-server/src/tools/browser-advanced.ts +1 -1
  247. package/mcp-server/src/tools/browser-batch.ts +1 -1
  248. package/mcp-server/src/tools/browser-cheatsheet.ts +1 -1
  249. package/mcp-server/src/tools/browser-interact.ts +1 -1
  250. package/mcp-server/src/tools/browser-navigate.ts +1 -1
  251. package/mcp-server/src/tools/browser-observe.ts +1 -1
  252. package/mcp-server/src/tools/card-tools.ts +1 -1
  253. package/mcp-server/src/tools/category.ts +6 -1
  254. package/mcp-server/src/tools/choice.ts +1 -1
  255. package/mcp-server/src/tools/computer.ts +1 -1
  256. package/mcp-server/src/tools/discord-channel.ts +1 -1
  257. package/mcp-server/src/tools/discord-guild.ts +1 -1
  258. package/mcp-server/src/tools/discord-member.ts +1 -1
  259. package/mcp-server/src/tools/discord-message.ts +1 -1
  260. package/mcp-server/src/tools/discord-onboarding.ts +1 -1
  261. package/mcp-server/src/tools/discord-role.ts +1 -1
  262. package/mcp-server/src/tools/discord-thread.ts +1 -1
  263. package/mcp-server/src/tools/discord-webhook.ts +1 -1
  264. package/mcp-server/src/tools/fb-groups.ts +1 -1
  265. package/mcp-server/src/tools/forget.ts +1 -1
  266. package/mcp-server/src/tools/git-tools.ts +1 -1
  267. package/mcp-server/src/tools/gsc/experience.ts +1 -1
  268. package/mcp-server/src/tools/gsc/indexing.ts +1 -1
  269. package/mcp-server/src/tools/gsc/inspect.ts +1 -1
  270. package/mcp-server/src/tools/gsc/navigate.ts +1 -1
  271. package/mcp-server/src/tools/gsc/performance.ts +1 -1
  272. package/mcp-server/src/tools/gsc/settings.ts +1 -1
  273. package/mcp-server/src/tools/image-tools.ts +1 -1
  274. package/mcp-server/src/tools/leonardo-browser-tools.ts +1 -1
  275. package/mcp-server/src/tools/loop.ts +1 -1
  276. package/mcp-server/src/tools/memories.ts +1 -1
  277. package/mcp-server/src/tools/morelogin.ts +1 -1
  278. package/mcp-server/src/tools/profile.ts +1 -1
  279. package/mcp-server/src/tools/recall.ts +1 -1
  280. package/mcp-server/src/tools/reflect.ts +1 -1
  281. package/mcp-server/src/tools/remember.ts +13 -12
  282. package/mcp-server/src/tools/restore.ts +1 -1
  283. package/mcp-server/src/tools/style-guide-tools.ts +1 -1
  284. package/mcp-server/src/tools/sync.ts +1 -1
  285. package/mcp-server/src/tools/tictactoe-tools.ts +1 -1
  286. package/mcp-server/src/tools/utils.ts +1 -1
  287. package/mcp-server/src/tools/whatsapp-send-file.ts +1 -1
  288. package/mcp-server/src/tools/whiteboard-tools.ts +1 -1
  289. package/mcp-server/src/tools/youtube/analytics.ts +1 -1
  290. package/mcp-server/src/tools/youtube/download.ts +1 -1
  291. package/mcp-server/src/tools/youtube/media.ts +1 -1
  292. package/mcp-server/src/tools/youtube/metadata.ts +1 -1
  293. package/mcp-server/src/tools/youtube/navigate.ts +1 -1
  294. package/mcp-server/src/tools/youtube/playlist.ts +1 -1
  295. package/mcp-server/src/tools/youtube/schedule.ts +1 -1
  296. package/mcp-server/src/tools/youtube/source.ts +1 -1
  297. package/mcp-server/src/tools/youtube/upload.ts +4 -12
  298. package/mcp-server/src/tui.ts +22 -9
  299. package/neural-interface/i18n/en.json +236 -7
  300. package/neural-interface/i18n/pt-BR.json +238 -9
  301. package/neural-interface/lib/account-usage.js +5 -3
  302. package/neural-interface/lib/agent-sandbox-elevation.js +102 -0
  303. package/neural-interface/lib/agent-sandbox-setting.js +57 -0
  304. package/neural-interface/lib/app-controls-api.js +161 -0
  305. package/neural-interface/lib/assistant-api.js +40 -7
  306. package/neural-interface/lib/assistant-brains/opencode.js +13 -1
  307. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +44 -0
  308. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +57 -0
  309. package/neural-interface/lib/assistant-catalog.js +17 -2
  310. package/neural-interface/lib/assistant-dispatch.js +3 -0
  311. package/neural-interface/lib/assistant-envelope.js +19 -1
  312. package/neural-interface/lib/assistant-route-gate-codex.js +3 -1
  313. package/neural-interface/lib/assistant-runtime.js +131 -8
  314. package/neural-interface/lib/claude-model-catalog.js +64 -14
  315. package/neural-interface/lib/codex-account-auth.js +4 -2
  316. package/neural-interface/lib/codex-accounts.js +14 -1
  317. package/neural-interface/lib/codex-settings-schema.js +111 -47
  318. package/neural-interface/lib/editor-completion-opencode.js +132 -35
  319. package/neural-interface/lib/exec-loop-command.js +11 -2
  320. package/neural-interface/lib/install-details.js +23 -5
  321. package/neural-interface/lib/launch-cache.js +293 -0
  322. package/neural-interface/lib/login-start.js +524 -0
  323. package/neural-interface/lib/native-loop-providers.js +24 -4
  324. package/neural-interface/lib/native-loop-runtime.js +19 -0
  325. package/neural-interface/lib/opencode-db-schema.js +75 -0
  326. package/neural-interface/lib/opencode-history.js +16 -1
  327. package/neural-interface/lib/opencode-protocol.js +173 -0
  328. package/neural-interface/lib/opencode-provider-view.js +81 -0
  329. package/neural-interface/lib/opencode-runtime-config.js +10 -3
  330. package/neural-interface/lib/opencode-serve-records.js +606 -0
  331. package/neural-interface/lib/opencode-v2-client.js +33 -6
  332. package/neural-interface/lib/opencode-v2-ws-requests.js +19 -5
  333. package/neural-interface/lib/opencode-worker-activity.js +229 -0
  334. package/neural-interface/lib/opencode2-client.js +760 -0
  335. package/neural-interface/lib/opencode2-proxy.js +116 -0
  336. package/neural-interface/lib/opencode2-translate.js +1008 -0
  337. package/neural-interface/lib/process-identity.js +361 -0
  338. package/neural-interface/lib/provider-panel-terminal-auth.js +3 -2
  339. package/neural-interface/lib/session-cache-builder.js +26 -5
  340. package/neural-interface/lib/session-indexer.js +3 -1
  341. package/neural-interface/lib/session-title-generator.js +20 -0
  342. package/neural-interface/lib/style-guide/api.js +4 -3
  343. package/neural-interface/lib/untrusted-file-headers.js +27 -0
  344. package/neural-interface/package-lock.json +1342 -44
  345. package/neural-interface/package.json +5 -1
  346. package/neural-interface/public/index.html +2 -2
  347. package/neural-interface/public/shared/account-menu.js +4 -1
  348. package/neural-interface/public/shared/account-usage.js +62 -2
  349. package/neural-interface/public/shared/account-view.js +2 -1
  350. package/neural-interface/public/shared/agent-runtime-options.js +55 -11
  351. package/neural-interface/public/shared/assistant/asst-account-menu.js +298 -0
  352. package/neural-interface/public/shared/assistant/asst-agents-dock.js +172 -17
  353. package/neural-interface/public/shared/assistant/asst-api.js +18 -3
  354. package/neural-interface/public/shared/assistant/asst-brain-picker.js +424 -152
  355. package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
  356. package/neural-interface/public/shared/assistant/asst-hosts.js +49 -2
  357. package/neural-interface/public/shared/assistant/asst-menu.js +275 -77
  358. package/neural-interface/public/shared/assistant/asst-model-chip.js +135 -0
  359. package/neural-interface/public/shared/assistant/asst-panel.js +236 -35
  360. package/neural-interface/public/shared/assistant/asst-rack-styles.js +28 -10
  361. package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
  362. package/neural-interface/public/shared/assistant/asst-render.js +382 -36
  363. package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
  364. package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
  365. package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
  366. package/neural-interface/public/shared/assistant/asst-scenes.js +528 -0
  367. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
  368. package/neural-interface/public/shared/assistant/asst-state.js +14 -0
  369. package/neural-interface/public/shared/assistant/asst-styles.js +109 -17
  370. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +13 -1
  371. package/neural-interface/public/shared/cc-dropdown.js +480 -0
  372. package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
  373. package/neural-interface/public/shared/cdx/cdx-render.js +15 -3
  374. package/neural-interface/public/shared/cdx/cdx-styles.js +49 -5
  375. package/neural-interface/public/shared/cdx/cdx-tabs.js +152 -35
  376. package/neural-interface/public/shared/cp/cp-markdown.js +4 -57
  377. package/neural-interface/public/shared/data-cache.js +223 -0
  378. package/neural-interface/public/shared/desktop-bridge.js +11 -0
  379. package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
  380. package/neural-interface/public/shared/desktop-titlebar.js +214 -28
  381. package/neural-interface/public/shared/desktop-update-view.js +15 -5
  382. package/neural-interface/public/shared/file-links.js +73 -8
  383. package/neural-interface/public/shared/html-shell.js +74 -80
  384. package/neural-interface/public/shared/launch-prefetch.js +59 -0
  385. package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +3 -2
  386. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +11 -3
  387. package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +54 -17
  388. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +97 -3
  389. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +3 -2
  390. package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
  391. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
  392. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1 -1
  393. package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
  394. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +16 -9
  395. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +60 -0
  396. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +83 -5
  397. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +195 -19
  398. package/neural-interface/public/shared/opencode-providers.js +39 -0
  399. package/neural-interface/public/shared/schedules-view.js +318 -0
  400. package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
  401. package/neural-interface/public/shared/settings/settings-app.js +243 -0
  402. package/neural-interface/public/shared/settings/settings-data.js +88 -0
  403. package/neural-interface/public/shared/settings/settings-ia.js +17 -0
  404. package/neural-interface/public/shared/showcase-privacy.js +2 -1
  405. package/neural-interface/public/shared/sidepanel-session-status.js +49 -0
  406. package/neural-interface/public/shared/styles.css +543 -372
  407. package/neural-interface/public/shared/ui-assistant.js +27 -5
  408. package/neural-interface/public/shared/ui-automation-studio.js +67 -27
  409. package/neural-interface/public/shared/ui-bookmarks.js +2 -1
  410. package/neural-interface/public/shared/ui-claude-panel.js +126 -12
  411. package/neural-interface/public/shared/ui-codex-panel.js +1 -0
  412. package/neural-interface/public/shared/ui-detail.js +6 -6
  413. package/neural-interface/public/shared/ui-explorer.js +2 -0
  414. package/neural-interface/public/shared/ui-file-links.js +1 -0
  415. package/neural-interface/public/shared/ui-image-gallery.js +6 -5
  416. package/neural-interface/public/shared/ui-invite.js +18 -2
  417. package/neural-interface/public/shared/ui-link.js +9 -9
  418. package/neural-interface/public/shared/ui-menubar.js +232 -33
  419. package/neural-interface/public/shared/ui-native-loop-router.js +2 -0
  420. package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
  421. package/neural-interface/public/shared/ui-schedules-studio.js +2099 -869
  422. package/neural-interface/public/shared/ui-sessions.js +15 -4
  423. package/neural-interface/public/shared/ui-settings.js +87 -36
  424. package/neural-interface/public/shared/ui-sidebar.js +4 -4
  425. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
  426. package/neural-interface/public/shared/ui-sidepanel-sessions.js +55 -4
  427. package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
  428. package/neural-interface/public/shared/ui-skills.js +70 -12
  429. package/neural-interface/public/shared/ui-sync.js +9 -0
  430. package/neural-interface/public/shared/ui-terminal.js +36 -20
  431. package/neural-interface/public/shared/ui-trash.js +8 -1
  432. package/neural-interface/public/shared/ui-tutorial-steps.js +7 -3
  433. package/neural-interface/public/shared/ui-tutorial.js +15 -5
  434. package/neural-interface/public/shared/ui-update.js +87 -16
  435. package/neural-interface/public/shared/ui-whiteboard.js +2 -1
  436. package/neural-interface/public/variant/2d/main.js +4 -1
  437. package/neural-interface/public/variant/3d/main.js +3 -0
  438. package/neural-interface/public/vendor/highlight/LICENSE +29 -0
  439. package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
  440. package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
  441. package/neural-interface/public/vendor/highlight/manifest.json +5 -0
  442. package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
  443. package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
  444. package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
  445. package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
  446. package/neural-interface/public/vendor/marked/manifest.json +4 -0
  447. package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
  448. package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
  449. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
  450. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
  451. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
  452. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
  453. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
  454. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
  455. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
  456. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
  457. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
  458. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
  459. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
  460. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
  461. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
  462. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
  463. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
  464. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
  465. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
  466. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
  467. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
  468. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
  469. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
  470. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
  471. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
  472. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
  473. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
  474. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
  475. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
  476. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
  477. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
  478. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
  479. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
  480. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
  481. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
  482. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
  483. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
  484. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
  485. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
  486. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
  487. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
  488. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
  489. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
  490. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
  491. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
  492. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
  493. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
  494. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
  495. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
  496. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
  497. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
  498. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
  499. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
  500. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
  501. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
  502. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
  503. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
  504. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
  505. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
  506. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
  507. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
  508. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
  509. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
  510. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
  511. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
  512. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
  513. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
  514. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
  515. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
  516. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
  517. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
  518. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
  519. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
  520. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
  521. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
  522. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
  523. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
  524. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
  525. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
  526. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
  527. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
  528. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
  529. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
  530. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
  531. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
  532. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
  533. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
  534. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
  535. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
  536. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
  537. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
  538. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
  539. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
  540. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
  541. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
  542. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
  543. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
  544. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
  545. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
  546. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
  547. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
  548. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
  549. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
  550. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
  551. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
  552. package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
  553. package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -0
  554. package/neural-interface/scripts/build-vendor.mjs +84 -3
  555. package/neural-interface/scripts/rebuild-pty.js +14 -2
  556. package/neural-interface/server.js +1279 -372
  557. package/npm-shrinkwrap.json +4424 -0
  558. package/package.json +54 -2
  559. package/postinstall.js +61 -47
  560. package/preuninstall.js +8 -35
  561. package/setup.js +76 -44
  562. package/skills/synabun/modules/idea.md +1 -1
  563. package/skills/synabun/modules/schedule.md +2 -2
  564. package/updater.cmd +2 -2
  565. package/updater.mjs +97 -3
@@ -0,0 +1,135 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Assistant — what the composer's model chip says
3
+ // ═══════════════════════════════════════════
4
+ // The model as a short human name from its catalog label ("Opus 5.5 (1M
5
+ // context)" → "Opus 5.5", "Default (recommended) — Opus 5.5" → "Opus 5.5"),
6
+ // a context tag for a "[1m]" / "[extended]" variant ("1M"), and the forms the
7
+ // chip falls back to when the composer row has no room, longest first: the tag
8
+ // goes first, then the account cue, then the API badge, then the name shortens
9
+ // by whole words, to a form that still names this model alone when there is one
10
+ // ("Opus 5.5" → "Opus", "GPT-6-Luna" → "Luna"). Never a cut word.
11
+ // asst-brain-picker.js draws the first form that fits. DOM-free: node --test loads it.
12
+
13
+ const VARIANT = /\[(1m|extended)\]$/i;
14
+ const VERSION = /^v?\d+(?:\.\d+)*[a-z]?$/i;
15
+
16
+ function str(v) {
17
+ return v == null ? '' : String(v).trim();
18
+ }
19
+
20
+ /** The id without its provider ("anthropic/…"), legacy ":<window>" and variant suffix. */
21
+ function bareId(id) {
22
+ const tail = str(id).split('/').pop() || '';
23
+ return tail.replace(/:\d+$/, '').replace(VARIANT, '');
24
+ }
25
+
26
+ /**
27
+ * The model's short name: { name, raw }. The label's own words without what the
28
+ * chip says otherwise (parentheses: the context, "recommended"); after a dash, the
29
+ * model it runs as. No label (or the id itself): the bare id, `raw` (shown mono).
30
+ */
31
+ export function modelChipName(label, id) {
32
+ let text = str(label);
33
+ if (text && text !== str(id)) {
34
+ const runsAs = text.split(/\s+[—–]\s+/).pop();
35
+ text = str(runsAs.replace(/\s*\([^)]*\)/g, '').replace(/\s+/g, ' '));
36
+ if (text) return { name: text, raw: false };
37
+ }
38
+ const name = bareId(id) || str(id);
39
+ return { name, raw: true };
40
+ }
41
+
42
+ /** "1M", "400K": a context window in tokens, never rounded up. */
43
+ function compactTokens(n) {
44
+ const v = Number(n);
45
+ if (!Number.isFinite(v) || v <= 0) return '';
46
+ if (v >= 1e6) return `${Math.floor(v / 1e5) / 10}M`;
47
+ if (v >= 1e3) return `${Math.floor(v / 1e3)}K`;
48
+ return String(v);
49
+ }
50
+
51
+ /**
52
+ * What tells a context variant from its model ("opus[1m]" → "1M"): its window when
53
+ * the catalog knows it, else "1M" for "[1m]", else the label's own word ("extended").
54
+ * '' for a model that is not a variant.
55
+ */
56
+ export function modelChipTag(id, { contextWindow = null, label = '' } = {}) {
57
+ const m = str(id).match(VARIANT);
58
+ if (!m) return '';
59
+ const tokens = compactTokens(contextWindow);
60
+ if (tokens) return tokens;
61
+ if (m[1].toLowerCase() === '1m') return '1M';
62
+ const note = str(label).match(/\(([^)]*)\)\s*$/);
63
+ return note ? str(note[1].replace(/\bcontext\b/i, '')) : '';
64
+ }
65
+
66
+ // "GPT-6.1-Sol" → ['GPT', '6.1', 'Sol'] with the separators kept: whole words in, whole words out.
67
+ function parts(name) {
68
+ return str(name).match(/[^\s-]+|[\s-]+/g) || [];
69
+ }
70
+ const isSep = (p) => /^[\s-]+$/.test(p);
71
+ const wordsOf = (name) => parts(name).filter(p => !isSep(p)).map(w => w.toLowerCase());
72
+
73
+ /** Whether `words` run in that order, whole, somewhere in `other` ("opus" in "Opus 5.5"). */
74
+ function within(words, other) {
75
+ for (let i = 0; i + words.length <= other.length; i += 1) {
76
+ if (words.every((w, j) => other[i + j] === w)) return true;
77
+ }
78
+ return false;
79
+ }
80
+
81
+ /**
82
+ * The name's shorter forms, whole words only, longest first: `unique` still names this
83
+ * model alone among `names` (the short names of every model the provider lists: "Opus"
84
+ * for "Opus 5.5", "GPT-6.1" for "GPT-6.1-Sol", "Luna" for "GPT-6-Luna" when every
85
+ * "GPT-6" is another model too), `other` drops trailing words whatever they lose
86
+ * ("Sonnet" for "Sonnet 5.5" beside "Sonnet 5"; "GPT-6"). A form never starts with a
87
+ * version ("5.5"), and a suffix is tried only when no shorter prefix is unique.
88
+ */
89
+ export function modelChipShortNames(name, names = []) {
90
+ const all = parts(name);
91
+ const own = wordsOf(name);
92
+ const others = [...new Set((Array.isArray(names) ? names : []).map(str).filter(n => n && n.toLowerCase() !== str(name).toLowerCase()))].map(wordsOf);
93
+ const unique = (form) => { const w = wordsOf(form); return !others.some(o => within(w, o)); };
94
+ const prefixes = [];
95
+ const suffixes = [];
96
+ for (let n = own.length - 1; n >= 1; n -= 1) {
97
+ let seen = 0;
98
+ const cut = all.findIndex(p => !isSep(p) && ++seen > n);
99
+ prefixes.push(all.slice(0, cut).join('').replace(/[\s-]+$/, ''));
100
+ let skip = own.length - n;
101
+ const from = all.findIndex(p => !isSep(p) && skip-- === 0);
102
+ if (!VERSION.test(all[from])) suffixes.push(all.slice(from).join(''));
103
+ }
104
+ const lossless = prefixes.filter(unique);
105
+ const picked = lossless.length ? lossless : suffixes.filter(unique);
106
+ return { unique: picked, other: prefixes.filter(p => !picked.includes(p)) };
107
+ }
108
+
109
+ /**
110
+ * The chip's forms, longest first: [{ name, tag, cue, api }] (tag / cue / api: shown
111
+ * or not). `tag`, `cue` and `api` say whether the chip has one at all; `names` are the
112
+ * provider's models (modelChipShortNames). What goes, in order: the tag, the account
113
+ * cue, the API badge, then the name. A shorter name that still names this model alone
114
+ * loses nothing, so it is tried before the cue and before the badge go; one that
115
+ * loses something only after.
116
+ */
117
+ export function modelChipForms({ name, names = [], tag = false, cue = false, api = false } = {}) {
118
+ const full = str(name);
119
+ const out = [];
120
+ const seen = new Set();
121
+ const add = (n, t, c, a) => {
122
+ const form = { name: n, tag: !!(t && tag), cue: !!(c && cue), api: !!(a && api) };
123
+ const key = JSON.stringify(form);
124
+ if (!seen.has(key)) { seen.add(key); out.push(form); }
125
+ };
126
+ const short = full ? modelChipShortNames(full, names) : { unique: [], other: [] };
127
+ add(full, true, true, true);
128
+ add(full, false, true, true);
129
+ for (const u of short.unique) add(u, false, true, true);
130
+ add(full, false, false, true);
131
+ for (const u of short.unique) add(u, false, false, true);
132
+ add(full, false, false, false);
133
+ for (const n of [...short.unique, ...short.other]) add(n, false, false, false);
134
+ return out;
135
+ }
@@ -51,20 +51,21 @@ import { cachedProjects, createBrainPicker, testDensityLabel } from './asst-brai
51
51
  import { createRovingToolbar } from './asst-roving.js';
52
52
  import { openAccountsManager } from './asst-accounts.js';
53
53
  import { createAgentsDock } from './asst-agents-dock.js';
54
+ import { activityOf } from './asst-scenes.js';
54
55
  import { createUsageGauge } from './asst-usage.js';
55
- import { closeMenu, isMenuOpen, openMenu } from './asst-menu.js';
56
+ import { closeMenu, currentMenuAnchor, isMenuOpen, openMenu } from './asst-menu.js';
56
57
  import { createRouteModeControl, openModelsManager, openRoutesEditor, refreshModelsManager, renderRouteCard, routeModeLabel } from './asst-route.js';
57
58
  import { budgetChipText, budgetSpendText, budgetTone, closeBudgetEditor, createBudgetController, mountBudgetChip, openBudgetEditor } from './asst-budget.js';
58
59
  import { computerRemoteView, createComputerPanel, createComputerToggle, normalizeComputerRemote, openFrameLightbox, closeFrameLightbox, requestDesktopStop } from './asst-computer.js';
59
60
  import {
60
61
  applyLimit, applyLimitPacket, applyUsagePacket, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
61
62
  brainModePatch, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, normalizeTestDensity, projectLabel, providerShortLabel, readStoredBrain, runFromPayload,
62
- serializeTabState, tabStorageKey, userSessionTitle,
63
+ serializeTabState, sessionStatus, tabStorageKey, userSessionTitle,
63
64
  } from './asst-state.js';
64
65
  import {
65
66
  closeAssistantSession, dispatchAssistantRun, escalateAssistantRun, focusAssistantRun, getAssistantRun,
66
67
  fetchManageCatalog, getAssistantRunResult, getAssistantSession, getAssistantSessionUsage, getDesktopStatus, getRouting, killAllAssistantRuns, removeAssistantRun, clearFinishedAssistantRuns,
67
- listAssistantSessions, patchAssistantSession, patchHiddenModels, stopAssistantRun, uploadAssistantAttachment,
68
+ listAssistantSessions, patchAssistantSession, patchHiddenModels, setAdminSandbox, stopAssistantRun, uploadAssistantAttachment,
68
69
  } from './asst-api.js';
69
70
 
70
71
  const ICON_SESSIONS = '<svg viewBox="0 0 24 24"><path d="M3 6h18M3 12h18M3 18h12"/></svg>';
@@ -74,6 +75,7 @@ const ICON_COG = '<svg viewBox="0 0 24 24"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v
74
75
  const ICON_ROUTE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h13l-3-3M20 17H7l3 3"/></svg>';
75
76
  const ICON_COMPUTER = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="12" rx="2"/><path d="M8 20h8M12 16v4"/></svg>';
76
77
  const ICON_CLOSE = '<svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
78
+ const ICON_TRASH = '<svg viewBox="0 0 24 24"><path d="M3 6h18M8 6V4.5A1.5 1.5 0 0 1 9.5 3h5A1.5 1.5 0 0 1 16 4.5V6M18.5 6l-.8 13a2 2 0 0 1-2 1.9H8.3a2 2 0 0 1-2-1.9L5.5 6M10 11v6M14 11v6"/></svg>';
77
79
  const REPLAY_WAIT_MS = 1500; // a replay that stops short of its count is drawn after this long
78
80
 
79
81
  function el(tag, className, text) {
@@ -148,14 +150,17 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
148
150
  usageView: saved?.usageView || null,
149
151
  });
150
152
  Object.assign(st, {
151
- status: 'idle',
153
+ status: 'idle', // the brain's own: its turn, its cards (setStatus)
154
+ workers: { working: 0, waiting: 0 }, // its dispatched agents, from the agents tray (sessionStatus)
155
+ shownStatus: 'idle', // what the host shows: both together (pushStatus)
152
156
  dispatchUsd: 0,
153
157
  serverCost: false,
154
158
  engine: '',
155
159
  sdkVersion: '',
156
160
  routing: null, // server view { mode, effectiveMode, defaultMode, askBelow }
157
- features: { routing: null, computer: null, testDensity: null, rename: null }, // null = unknown yet
161
+ features: { routing: null, computer: null, testDensity: null, rename: null, adminSandbox: null }, // null = unknown yet
158
162
  testDensityEffective: null, // server view: the level in effect
163
+ adminSandbox: null, // server view: the global Admin sandbox setting (every agent)
159
164
  brainCapabilities: null,
160
165
  computerEffective: st.computerUse === true,
161
166
  desktopSupported: null,
@@ -164,6 +169,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
164
169
  desktopProbe: false,
165
170
  routingProbe: false,
166
171
  sessionTitle: String(session?.title || ''), // the server's name (the user's rename, else the first prompt): history + notifications
172
+ // Whether this session holds a chat (a prompt was sent): until then the server keeps it as a draft,
173
+ // New reuses it, and leaving it for another session closes it (nothing of it is stored).
174
+ chatStarted: !!session?.chatStartedAt || Number(session?.turns) > 0,
167
175
  });
168
176
  let recordName = userSessionTitle(session); // the name the session record holds as the user's ('' = never renamed)
169
177
  const controls = new Map(); // requestId → { card, origin, kind }
@@ -314,18 +322,33 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
314
322
  notify(host.notifySource || 'cli', type, notifyLabel(), { sessionId, provider: 'assistant', panel: 'assistant' });
315
323
  }
316
324
 
317
- /** root[data-status] and data-computer drive status styling (the live dot, the Computer switch). */
325
+ /** root[data-status] (the session's status, sessionStatus) and data-computer drive status styling (the live dot, the Computer switch). */
318
326
  function renderStatus() {
319
- root.dataset.status = st.status || 'idle';
327
+ root.dataset.status = st.shownStatus || 'idle';
320
328
  if (st.desktopActive) root.dataset.computer = 'active';
321
329
  else delete root.dataset.computer;
322
330
  }
323
331
 
332
+ /** The brain's own status: its turn ('working', 'done', 'idle') and its cards ('action'). */
324
333
  function setStatus(status) {
325
334
  st.status = status || 'idle';
326
- renderStatus();
335
+ pushStatus(true);
327
336
  syncBlocked();
328
- try { host.setStatus?.(st.status); } catch { /* ignore */ }
337
+ }
338
+
339
+ /**
340
+ * What the host shows (tray pill, header, terminal badge) is the session's status: the brain's own and
341
+ * its dispatched agents' together (asst-state.js sessionStatus), so the gold stays while a worker works
342
+ * after the turn that dispatched it ended, and a worker that waits on you makes the session need you.
343
+ * The brain's own changes always reach the host; a change of the agents' counts only when the status moved.
344
+ */
345
+ function pushStatus(always = false) {
346
+ if (destroyed) return;
347
+ const next = sessionStatus(st.status, st.workers);
348
+ if (!always && next === st.shownStatus) return;
349
+ st.shownStatus = next;
350
+ renderStatus();
351
+ try { host.setStatus?.(next); } catch { /* ignore */ }
329
352
  }
330
353
 
331
354
  /**
@@ -583,6 +606,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
583
606
  // Test density sits right after the permission mode; hidden on a server that does not know it.
584
607
  getTestDensity: () => testDensityView(),
585
608
  onTestDensity: (level) => setTestDensity(level),
609
+ // The global Admin sandbox switch, in the permission menu; hidden on a server that does not serve it.
610
+ getAdminSandbox: () => adminSandboxView(),
611
+ onAdminSandbox: (enabled) => changeAdminSandbox(enabled),
586
612
  // The registered projects arrived: their labels name the project in the fields and the "Fix … in" suggestion.
587
613
  onProjects: () => { picker.render(); renderer.refreshEmpty(); },
588
614
  });
@@ -628,13 +654,24 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
628
654
  onStopAll: () => stopAll(),
629
655
  onRemove: (runId) => removeRun(runId),
630
656
  onClearFinished: () => clearFinished(),
657
+ // A mini scene or a lane: that run's card in the transcript (drawn first when this window never got it).
658
+ onReveal: (runId) => {
659
+ if (renderer.revealRun(runId)) return;
660
+ const run = dock.getRun(runId);
661
+ if (run) { renderer.restoreRuns([run]); renderer.revealRun(runId); }
662
+ },
663
+ // Whatever told the tray (the sync bus, its fetch), the transcript's card and route line follow.
664
+ onRunChange: (run) => renderer.syncRun(run),
631
665
  onToggle: (open) => { st.dockOpen = open; agentsBtn.setAttribute('aria-pressed', open ? 'true' : 'false'); persist(); },
632
666
  onShowAllChange: (showAll) => { st.dockShowAll = showAll; persist(); },
633
- onCountChange: ({ total, active, attention, visible: shown }) => {
667
+ onCountChange: ({ total, active, attention, working = 0, waiting = 0, visible: shown }) => {
634
668
  agentsCount.textContent = String(active || total);
635
669
  agentsCount.classList.toggle('attention', attention > 0);
636
670
  agentsBtn.hidden = !shown;
637
671
  agentsBtn.classList.toggle('attention', attention > 0);
672
+ // Whatever told the tray (this socket, the sync bus, its fetch after a reload): the session's status follows.
673
+ st.workers = { working, waiting };
674
+ pushStatus();
638
675
  },
639
676
  });
640
677
  agentsBtn.setAttribute('aria-pressed', st.dockOpen ? 'true' : 'false');
@@ -773,6 +810,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
773
810
  lockControl(packet.request_id, resolvedLabel(packet.origin, tt('assistant.control.state.answered', 'Answered')));
774
811
  return;
775
812
  case 'reattach_result':
813
+ // Whether a turn runs now: a route the journal left open is that turn's, or nobody's.
814
+ renderer.reattached(!!(packet.ok && packet.running));
776
815
  if (packet.ok) {
777
816
  if (packet.sessionId) st.providerSessionId = packet.sessionId;
778
817
  if (packet.resynced) rehydrate({ force: true });
@@ -801,6 +840,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
801
840
  finishTurn({ aborted: true });
802
841
  return;
803
842
  case 'error': {
843
+ // The server no longer has this session: no error row and no retry loop; the host closes the tab.
844
+ if (packet.code === 'SESSION_NOT_FOUND') { sessionGone(); return; }
804
845
  // A rejected route answer keeps its card open with the message.
805
846
  const routeCard = packet.request_id ? routeCardByRequest(packet.request_id) : null;
806
847
  if (routeCard) { routeCard.fail(packet.message); return; }
@@ -926,6 +967,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
926
967
  if (meta.id && meta.id !== sessionId) return;
927
968
  // The server's title names the conversation (history, notifications); the tab's name is the host's.
928
969
  applyRecordName(meta);
970
+ if (meta.chatStartedAt || Number(meta.turns) > 0) st.chatStarted = true;
929
971
  if (meta.brain && typeof meta.brain === 'object') {
930
972
  const next = normalizeBrain({ ...st.brain, ...meta.brain, provider: meta.brain.provider || meta.brain.brain || st.brain.provider });
931
973
  if (JSON.stringify(next) !== JSON.stringify(st.brain)) { st.brain = next; picker.render(); host.setBrain?.(next); persist(); }
@@ -950,7 +992,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
950
992
  if (typeof meta.features.computer === 'boolean') st.features.computer = meta.features.computer;
951
993
  if (typeof meta.features.testDensity === 'boolean') st.features.testDensity = meta.features.testDensity;
952
994
  if (typeof meta.features.rename === 'boolean') st.features.rename = meta.features.rename;
995
+ if (typeof meta.features.adminSandbox === 'boolean') st.features.adminSandbox = meta.features.adminSandbox;
953
996
  }
997
+ if (typeof meta.adminSandbox === 'boolean') st.adminSandbox = meta.adminSandbox;
954
998
  if ('testDensityExplicit' in meta) st.testDensity = normalizeTestDensity(meta.testDensityExplicit, null);
955
999
  if (meta.testDensity) st.testDensityEffective = normalizeTestDensity(meta.testDensity);
956
1000
  if (typeof meta.computerUse === 'boolean') st.computerEffective = meta.computerUse;
@@ -1066,6 +1110,31 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1066
1110
  if (!quiet) renderer.appendStatus(tt('assistant.status.testDensity', 'Test density: {level}', { level: testDensityLabel(next, t) }));
1067
1111
  }
1068
1112
 
1113
+ /** The global Admin sandbox setting (true / false), or null while the server does not serve it. */
1114
+ function adminSandboxView() {
1115
+ if (st.features.adminSandbox !== true || typeof st.adminSandbox !== 'boolean') return null;
1116
+ return st.adminSandbox;
1117
+ }
1118
+
1119
+ /** Every agent SynaBun starts follows it; every window hears the change (sync:agents:admin-sandbox-changed). */
1120
+ async function changeAdminSandbox(enabled) {
1121
+ const before = st.adminSandbox;
1122
+ st.adminSandbox = enabled === true;
1123
+ picker.render();
1124
+ try {
1125
+ const view = await setAdminSandbox(st.adminSandbox);
1126
+ if (typeof view?.adminSandbox === 'boolean') st.adminSandbox = view.adminSandbox;
1127
+ picker.render();
1128
+ renderer.appendStatus(st.adminSandbox
1129
+ ? tt('assistant.adminSandbox.statusOn', 'Admin sandbox: on. On Windows, Codex may ask for administrator approval once per account to set up its sandbox.')
1130
+ : tt('assistant.adminSandbox.statusOff', 'Admin sandbox: off. No agent SynaBun starts asks for administrator approval for a sandbox.'));
1131
+ } catch (err) {
1132
+ st.adminSandbox = before;
1133
+ picker.render();
1134
+ toast(err?.message || String(err));
1135
+ }
1136
+ }
1137
+
1069
1138
  /** Fresh tabs inherit the last-used test density (like the route mode). */
1070
1139
  function applyLastUsedTestDensity() {
1071
1140
  if (saved || st.features.testDensity !== true || st.testDensity != null) return;
@@ -1312,6 +1381,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1312
1381
  st.turnStartedAt = Date.now();
1313
1382
  setRunning(true);
1314
1383
  sock.send(msg);
1384
+ st.chatStarted = true; // the server stores the session with this prompt
1315
1385
  // Name the conversation like the server will (its first prompt) — not the tab.
1316
1386
  if (!st.userRenamed && (!st.sessionTitle || /^(?:SynaBun|Assistant(?: \d+)?)$/.test(st.sessionTitle))) {
1317
1387
  const guess = String(payload.text || '').split('\n')[0].trim().slice(0, 60);
@@ -1473,15 +1543,34 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1473
1543
  if (!st.running) setRunning(true, { label: tt('assistant.compacting', 'compacting…') });
1474
1544
  }
1475
1545
 
1546
+ /** Nobody chatted in this session yet (and nothing runs in it): New reuses it, leaving it closes it. */
1547
+ function unused() {
1548
+ return !st.chatStarted && !st.running;
1549
+ }
1550
+
1476
1551
  function newSession(provider) {
1477
1552
  const b = provider ? normalizeBrain({ ...st.brain, provider, model: '', effort: null, agent: null, accountId: null }) : st.brain;
1553
+ // This one is still empty: it is the new session (the server keeps one draft, not a pile of them).
1554
+ // /new <provider> switches its brain as the picker does; what only this page showed (/help) is cleared.
1555
+ if (unused() && !destroyed) {
1556
+ if (provider && provider !== st.brain.provider) applyBrain(b, { requiresSwitch: true, field: 'provider' });
1557
+ if (!renderer.isEmpty()) clearTranscript();
1558
+ composer.focus();
1559
+ return;
1560
+ }
1478
1561
  emit('assistant:new', { brain: b, host: hostId });
1479
1562
  }
1480
1563
 
1564
+ /** Open another assistant session; this one goes with it when nobody chatted in it (`replaces`). */
1565
+ function openOther(id) {
1566
+ emit('assistant:resume', { sessionId: id, host: hostId, replaces: unused() ? sessionId : null });
1567
+ }
1568
+
1481
1569
  function resume(id) {
1482
1570
  if (!id) return;
1483
- if (String(id).startsWith('assistant-')) { emit('assistant:resume', { sessionId: id, host: hostId }); return; }
1571
+ if (String(id).startsWith('assistant-')) { if (id !== sessionId) openOther(id); return; }
1484
1572
  sock.send({ type: 'resume', providerSessionId: id });
1573
+ st.chatStarted = true; // a provider conversation: the server stores the session with it
1485
1574
  renderer.appendDivider(tt('assistant.status.resuming', 'resuming {id}', { id: String(id).slice(0, 8) }));
1486
1575
  }
1487
1576
 
@@ -1603,35 +1692,109 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1603
1692
  }
1604
1693
 
1605
1694
  // ── Menus ──
1695
+ /**
1696
+ * The Sessions menu: New, then every session that holds a chat (the server lists no other). Each row
1697
+ * opens its session; its Remove (hover / focus, → from the row, Delete) asks in the row itself, then
1698
+ * removes the session for good: its running turn and agents stop (the question says so), every host
1699
+ * drops its tab, and the session showing here is replaced by a fresh one, as New does.
1700
+ */
1606
1701
  function showSessionsMenu(list) {
1607
- const sessions = (Array.isArray(list) ? list : []).filter(s => s?.id);
1608
- const items = [
1609
- { id: 'new', label: tt('assistant.topbar.new', 'New assistant session'), desc: brainLabel(st.brain), icon: ICON_NEW, onSelect: () => newSession(null) },
1610
- { kind: 'separator' },
1611
- ];
1612
- if (!sessions.length) items.push({ kind: 'info', label: tt('assistant.sessions.empty', 'No other sessions') });
1613
- else items.push({ kind: 'header', label: tt('assistant.sessions.recent', 'Recent') });
1614
- for (const s of sessions.slice(0, 30)) {
1615
- const isCurrent = s.id === sessionId;
1616
- const b = s.brain && typeof s.brain === 'object' ? s.brain : { provider: s.brain, model: s.model, effort: s.effort };
1617
- items.push({
1618
- kind: 'radio',
1619
- id: s.id,
1620
- label: s.title || s.label || s.id,
1621
- desc: [brainLabel(b), relativeTime(s.updatedAt || s.createdAt), s.status].filter(Boolean).join(' · '),
1622
- selected: isCurrent,
1623
- onSelect: () => { if (!isCurrent) emit('assistant:resume', { sessionId: s.id, host: hostId }); },
1624
- });
1625
- }
1626
- openMenu(sessionsBtn, {
1702
+ let sessions = (Array.isArray(list) ? list : []).filter(s => s?.id);
1703
+ let asking = null; // the id of the row that asks "Remove …?"
1704
+ const nameOf = (s) => s.title || s.label || s.id;
1705
+ const build = () => {
1706
+ const items = [
1707
+ { id: 'new', label: tt('assistant.topbar.new', 'New assistant session'), desc: brainLabel(st.brain), icon: ICON_NEW, onSelect: () => newSession(null) },
1708
+ { kind: 'separator' },
1709
+ ];
1710
+ if (!sessions.length) items.push({ kind: 'info', label: tt('assistant.sessions.empty', 'No other sessions') });
1711
+ else items.push({ kind: 'header', label: tt('assistant.sessions.recent', 'Recent') });
1712
+ for (const s of sessions.slice(0, 30)) {
1713
+ const isCurrent = s.id === sessionId;
1714
+ const name = nameOf(s);
1715
+ if (s.id === asking) { items.push(removeQuestion(s, name, isCurrent)); continue; }
1716
+ const b = s.brain && typeof s.brain === 'object' ? s.brain : { provider: s.brain, model: s.model, effort: s.effort };
1717
+ items.push({
1718
+ kind: 'radio',
1719
+ id: s.id,
1720
+ label: name,
1721
+ desc: [brainLabel(b), relativeTime(s.updatedAt || s.createdAt), s.status].filter(Boolean).join(' · '),
1722
+ selected: isCurrent,
1723
+ onSelect: () => { if (!isCurrent) openOther(s.id); },
1724
+ action: {
1725
+ id: `remove:${s.id}`,
1726
+ icon: ICON_TRASH,
1727
+ label: tt('assistant.sessions.removeNamed', 'Remove “{title}”', { title: name }),
1728
+ tooltip: tt('assistant.sessions.remove', 'Remove session'),
1729
+ onSelect: () => ask(s.id),
1730
+ },
1731
+ });
1732
+ }
1733
+ return items;
1734
+ };
1735
+ /** "Remove “name”? …" with Remove and Cancel, in place of the row (it still matches the filter by name). */
1736
+ const removeQuestion = (s, name, isCurrent) => {
1737
+ const runs = Math.max(0, Number(s.activeRuns) || 0);
1738
+ const running = isCurrent ? st.running : s.running === true;
1739
+ const question = [
1740
+ tt('assistant.sessions.removeAsk', 'Remove “{title}” for good?', { title: name }),
1741
+ running ? tt('assistant.sessions.removeStopsTurn', 'Its running turn stops.') : '',
1742
+ runs ? tt('assistant.sessions.removeStopsAgents', 'Its running agents stop ({count}).', { count: runs }) : '',
1743
+ ].filter(Boolean).join(' ');
1744
+ return {
1745
+ kind: 'buttons',
1746
+ id: `ask:${s.id}`,
1747
+ className: 'asst-dd-confirm',
1748
+ label: question,
1749
+ buttons: [
1750
+ { id: `remove-yes:${s.id}`, label: tt('assistant.sessions.removeConfirm', 'Remove'), danger: true, keywords: name, keepOpen: true, onSelect: () => confirmRemove(s, isCurrent) },
1751
+ { id: `remove-no:${s.id}`, label: tt('common.cancel', 'Cancel'), keywords: name, keepOpen: true, onSelect: () => cancel() },
1752
+ ],
1753
+ };
1754
+ };
1755
+ const handle = openMenu(sessionsBtn, {
1627
1756
  title: tt('assistant.topbar.sessions', 'Sessions'),
1628
- items,
1757
+ items: build(),
1629
1758
  role: 'menu',
1630
1759
  placement: 'below',
1631
1760
  width: 300,
1632
1761
  filter: sessions.length > 8,
1633
1762
  filterPlaceholder: tt('assistant.sessions.filter', 'Filter sessions…'),
1763
+ // Esc while a row asks: back to the row, the menu stays open.
1764
+ onEscape: () => { if (!asking) return false; cancel(); return true; },
1634
1765
  });
1766
+ function ask(id) {
1767
+ asking = id;
1768
+ handle?.update({ items: build(), focus: `remove-no:${id}` });
1769
+ }
1770
+ function cancel() {
1771
+ const id = asking;
1772
+ asking = null;
1773
+ handle?.update({ items: build(), focus: id });
1774
+ }
1775
+ function confirmRemove(s, isCurrent) {
1776
+ asking = null;
1777
+ const name = nameOf(s);
1778
+ const done = (result) => {
1779
+ if (result?.ok) return;
1780
+ const text = tt('assistant.sessions.removeFailed', 'Could not remove “{title}”: {error}', { title: name, error: result?.error || tt('assistant.errorGeneric', 'Something went wrong') });
1781
+ if (destroyed) return;
1782
+ renderer.appendError(text);
1783
+ announce(text);
1784
+ };
1785
+ if (isCurrent) {
1786
+ // This panel's own session: a fresh one takes its place (as New), then this one goes.
1787
+ closeMenu();
1788
+ emit('assistant:remove', { sessionId: s.id, fresh: true, brain: st.brain, done });
1789
+ return;
1790
+ }
1791
+ // Another session (open elsewhere or not): its row goes now, and focus stays in the list.
1792
+ const at = sessions.findIndex((row) => row.id === s.id);
1793
+ sessions = sessions.filter((row) => row.id !== s.id);
1794
+ const next = sessions[Math.min(at, sessions.length - 1)];
1795
+ handle?.update({ items: build(), focus: next ? next.id : 'new' });
1796
+ emit('assistant:remove', { sessionId: s.id, fresh: false, done });
1797
+ }
1635
1798
  }
1636
1799
 
1637
1800
  function engineText() {
@@ -1867,6 +2030,18 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1867
2030
  const requestId = msg?.request_id || msg?.requestId;
1868
2031
  if (requestId) lockControl(requestId, resolvedLabel(msg.resolvedBy));
1869
2032
  }));
2033
+ // What this session's workers do right now (Claude and Codex workers stream their events to the page,
2034
+ // OpenCode workers a compact copy of their tool calls: lib/opencode-worker-activity.js):
2035
+ // their stages and the tray's scenes follow the current call.
2036
+ unsubs.push(on('sync:sidepanel:provider-event', (msg) => {
2037
+ const runId = msg?.run?.runId;
2038
+ if (!runId || !dock.getRun(runId)) return;
2039
+ const activity = activityOf(msg.event);
2040
+ if (!activity) return;
2041
+ const stamped = { ...activity, at: Date.now() };
2042
+ renderer.setRunActivity(runId, stamped);
2043
+ dock.setRunActivity(runId, stamped);
2044
+ }));
1870
2045
  unsubs.push(on('sync:assistant:desktop', (msg) => computerPanel.applyDesktop(msg)));
1871
2046
  unsubs.push(on('sync:assistant:desktop-setup', (msg) => computerPanel.applySetup(msg)));
1872
2047
  // Models switched on/off elsewhere: the open Models manager reloads (the menus drop their cache on their own).
@@ -1879,6 +2054,12 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1879
2054
  st.routing = { ...(st.routing || {}), defaultMode: def, effectiveMode: st.routeMode || def };
1880
2055
  routeChip.render();
1881
2056
  }));
2057
+ // The global Admin sandbox setting changed in some window (this one included): every panel shows it.
2058
+ unsubs.push(on('sync:agents:admin-sandbox-changed', (msg) => {
2059
+ if (typeof msg?.adminSandbox !== 'boolean' || msg.adminSandbox === st.adminSandbox) return;
2060
+ st.adminSandbox = msg.adminSandbox;
2061
+ picker.render();
2062
+ }));
1882
2063
  unsubs.push(on('session:info', () => updateGuest()));
1883
2064
  unsubs.push(on('permissions:changed', () => updateGuest()));
1884
2065
 
@@ -1887,6 +2068,19 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1887
2068
  }
1888
2069
 
1889
2070
  // ── Rehydration ──
2071
+ /**
2072
+ * The server no longer has this session: a draft it dropped (a restart before its first prompt, a
2073
+ * page away too long) or one removed while this page missed the broadcast. The tab closes; one that
2074
+ * was showing with no chat in it is replaced by a fresh session (asst-hosts.js gone), never left dead.
2075
+ */
2076
+ let gone = false;
2077
+ function sessionGone() {
2078
+ if (gone || destroyed) return;
2079
+ gone = true;
2080
+ sock.close();
2081
+ emit('assistant:gone', { sessionId, fresh: visible() && unused(), brain: st.brain });
2082
+ }
2083
+
1890
2084
  async function rehydrate({ force = false } = {}) {
1891
2085
  try {
1892
2086
  const data = await getAssistantSession(sessionId);
@@ -1899,7 +2093,11 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1899
2093
  // A conversation with nothing in it yet may be greeted; a restored one never is.
1900
2094
  if (Array.isArray(transcript) && !transcript.length && !(Number(meta?.turns) > 0)) renderer.offerGreeting();
1901
2095
  for (const run of (Array.isArray(data?.runs) ? data.runs : [])) dock.upsertRun(run);
2096
+ // Run cards are not journaled: the runs the tray fetched come back into the transcript, next to the
2097
+ // calls that dispatched them, and a worker that still works is live at once (its stage, its route line).
2098
+ dock.ready.then(() => { if (!destroyed) renderer.restoreRuns(dock.getRuns()); });
1902
2099
  } catch (err) {
2100
+ if (err?.status === 404) { sessionGone(); return; }
1903
2101
  console.warn('[assistant] could not restore the conversation', err);
1904
2102
  renderer.showEmpty();
1905
2103
  }
@@ -1914,7 +2112,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1914
2112
  if (session && typeof session === 'object') applySessionMeta(session);
1915
2113
  else applyFeatures();
1916
2114
  rehydrate().finally(() => {
1917
- if (destroyed) return;
2115
+ if (destroyed || gone) return;
1918
2116
  probeFeatures();
1919
2117
  applyLastUsedRouteMode();
1920
2118
  applyLastUsedTestDensity();
@@ -1954,7 +2152,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1954
2152
  attachPath: (path) => { if (path) { composer.insertText(`\`${path}\` `); composer.focus(); } },
1955
2153
  /** The server's name for the conversation (the user's rename, else the first prompt): tooltips. */
1956
2154
  getConversationTitle: () => st.sessionTitle || '',
1957
- getStatus: () => st.status || 'idle',
2155
+ /** The session's status as its host shows it: the brain's own with its dispatched agents' (sessionStatus). */
2156
+ getStatus: () => st.shownStatus || 'idle',
1958
2157
  focus: () => composer.focus(),
1959
2158
  onShown: () => { syncTabLabel(); renderer.scrollEnd(true); if (visible()) composer.focus(); director.touch(); },
1960
2159
  onHidden: () => { closeMenu(); picker.close(); director.stopTyping(); },
@@ -1975,7 +2174,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1975
2174
  unsubs.forEach(off => { try { off(); } catch { /* ignore */ } });
1976
2175
  document.removeEventListener('keydown', onEscCapture, true);
1977
2176
  surfaces.forEach((node) => { node.removeEventListener('keydown', onRootKey); node.removeEventListener('focusin', onFocusIn); });
1978
- closeMenu();
2177
+ // Its own menu closes; another panel's stays open (its Sessions menu may be what removed this session).
2178
+ const menuAnchor = currentMenuAnchor();
2179
+ if (!menuAnchor || !menuAnchor.isConnected || root.contains(menuAnchor) || barEl.contains(menuAnchor)) closeMenu();
1979
2180
  closeFrameLightbox();
1980
2181
  if (helpModal) { helpModal.remove(); helpModal = null; }
1981
2182
  for (const card of routeCards.values()) card.destroy();