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,480 @@
1
+ // The app's custom dropdown (DESIGN.md "Settings custom dropdown", `.cc-dropdown`): a hidden
2
+ // <input id> holds the value, a trigger button shows the choice, a menu lists the choices.
3
+ // settings-kit.js dropdown() writes the same markup for Settings; this module writes it with its
4
+ // ARIA and drives every dropdown under a root from one set of listeners, so markup drawn again
5
+ // with innerHTML needs no wiring of its own.
6
+ //
7
+ // Every dropdown in SynaBun is this one: a native <select> is not allowed (tests/no-native-select.test.mjs).
8
+ // Adding one, as the Schedules window (ui-schedules-studio.js) does:
9
+ // 1. Markup: dropdownHTML(id, [{ value, label, selected }], { labelledBy }); in Settings, settings-kit.js dropdown().
10
+ // 2. Wiring: wireDropdowns(container, { signal }) once; markup drawn later needs nothing more.
11
+ // 3. Reading: the hidden input's `.value`, and its `change` event (it bubbles), as with a <select>.
12
+ // 4. Changing: setDropdownItems(input, entries), setDropdownValue(input, value), setDropdownDisabled(input, on).
13
+ // 5. Focusing it or marking it invalid: controlOf(input) is its trigger.
14
+ //
15
+ // To the code around it, it reads like a <select>: the input's `.value` is the choice, and a
16
+ // choice the user makes fires `input` and `change` on the input (bubbling). Choices are
17
+ // `{ value, label, selected, disabled }` (labels are text), or `{ group, options }` for a heading.
18
+ // The chosen one is the last marked `selected`, else the first that is not disabled: a <select>'s
19
+ // rule, so a list rebuilt from saved data shows what was saved. setDropdownItems() is
20
+ // `select.innerHTML = …`, setDropdownValue() is `select.value = …`; neither fires an event.
21
+ //
22
+ // Keyboard and ARIA are the WAI-ARIA select-only combobox: the focus stays on the trigger and the
23
+ // highlighted option is its aria-activedescendant. Enter, Space or an arrow opens; arrows, Home,
24
+ // End, Page Up/Down and typing move; Enter or Space chooses; Escape closes without a change; Tab
25
+ // closes and moves on, the choice as it was. An open menu is placed `fixed` against its trigger,
26
+ // so a scrolling pane never cuts it off, and kept inside the box that clips it (a window).
27
+
28
+ const ARROW = '<svg class="cc-dropdown-arrow" viewBox="0 0 24 24" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>';
29
+ const GAP = 4; // between the trigger and its menu
30
+ const EDGE = 6; // the least room left between a menu and the edge of what clips it
31
+ const PAGE = 10; // options a Page Up/Down moves
32
+ const TYPE_PAUSE = 500; // ms between keys that still extend a type-ahead search
33
+
34
+ const esc = (value) => String(value ?? '').replace(/[&<>"']/g, (c) => ({
35
+ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;',
36
+ }[c]));
37
+
38
+ // ── What decides (no DOM) ──
39
+
40
+ /** The options of a list of entries, headings left out, in their order. */
41
+ export function flatOptions(entries) {
42
+ const out = [];
43
+ for (const entry of entries || []) {
44
+ if (entry && Array.isArray(entry.options)) out.push(...entry.options.filter(Boolean));
45
+ else if (entry) out.push(entry);
46
+ }
47
+ return out;
48
+ }
49
+
50
+ /** The chosen option as a <select> picks it: the last marked selected, else the first enabled; -1 for none. */
51
+ export function chosenIndex(options) {
52
+ let last = -1;
53
+ options.forEach((option, i) => { if (option.selected) last = i; });
54
+ return last >= 0 ? last : options.findIndex(option => !option.disabled);
55
+ }
56
+
57
+ /** The first or last option that is not disabled; -1 for none. */
58
+ export function edgeIndex(options, which) {
59
+ if (which === 'first') return options.findIndex(option => !option.disabled);
60
+ for (let i = options.length - 1; i >= 0; i--) if (!options[i].disabled) return i;
61
+ return -1;
62
+ }
63
+
64
+ /** `steps` enabled options away from `from` (negative: up), stopping at the ends. From none, the first or last. */
65
+ export function stepIndex(options, from, steps) {
66
+ if (from < 0 || from >= options.length) return edgeIndex(options, steps < 0 ? 'last' : 'first');
67
+ const dir = Math.sign(steps) || 1;
68
+ let left = Math.abs(steps) || 1;
69
+ let found = from;
70
+ for (let i = from + dir; i >= 0 && i < options.length; i += dir) {
71
+ if (options[i].disabled) continue;
72
+ found = i;
73
+ if (--left === 0) break;
74
+ }
75
+ return found;
76
+ }
77
+
78
+ /**
79
+ * Type-ahead: the option whose label starts with what was typed, searching on from the highlighted
80
+ * one and round. One letter typed again moves on to the next option with that letter, as a <select> does.
81
+ */
82
+ export function matchIndex(options, typed, from = -1) {
83
+ const query = String(typed || '').toLocaleLowerCase();
84
+ if (!query) return -1;
85
+ const repeated = [...query].every(c => c === query[0]);
86
+ const needle = repeated ? query[0] : query;
87
+ const n = options.length;
88
+ const start = repeated ? from + 1 : Math.max(from, 0);
89
+ for (let k = 0; k < n; k++) {
90
+ const i = (((start + k) % n) + n) % n;
91
+ const option = options[i];
92
+ if (!option.disabled && String(option.label ?? '').trim().toLocaleLowerCase().startsWith(needle)) return i;
93
+ }
94
+ return -1;
95
+ }
96
+
97
+ // ── Markup ──
98
+
99
+ function optionHTML(id, option, index, chosen) {
100
+ const label = String(option.label ?? '');
101
+ const active = index === chosen;
102
+ return `<div class="cc-dropdown-item${active ? ' active' : ''}" id="${esc(id)}-opt-${index}" role="option" aria-selected="${active}"`
103
+ + `${option.disabled ? ' aria-disabled="true"' : ''} data-value="${esc(option.value ?? '')}" data-index="${index}" title="${esc(label)}">${esc(label)}</div>`;
104
+ }
105
+
106
+ /** The menu's options (and headings) for `entries`, the `chosen` index marked. */
107
+ export function menuHTML(id, entries, chosen = chosenIndex(flatOptions(entries))) {
108
+ let index = 0;
109
+ let group = 0;
110
+ return (entries || []).filter(Boolean).map((entry) => {
111
+ if (!Array.isArray(entry.options)) return optionHTML(id, entry, index++, chosen);
112
+ const headId = `${id}-grp-${group++}`;
113
+ const options = entry.options.filter(Boolean).map(option => optionHTML(id, option, index++, chosen)).join('');
114
+ return `<div class="cc-dropdown-optgroup" role="group" aria-labelledby="${esc(headId)}"><div class="cc-dropdown-group" id="${esc(headId)}" role="presentation">${esc(entry.group ?? '')}</div>${options}</div>`;
115
+ }).join('');
116
+ }
117
+
118
+ /**
119
+ * A dropdown: the hidden input (`id`, with `inputAttrs`) and the `.cc-dropdown` it belongs to.
120
+ * Name it with `labelledBy` (the id of its visible label) or `label`. `classes` and `attrs` go on
121
+ * the `.cc-dropdown`.
122
+ */
123
+ export function dropdownHTML(id, entries, { classes = '', labelledBy = '', label = '', attrs = '', inputAttrs = '', disabled = false } = {}) {
124
+ const options = flatOptions(entries);
125
+ const chosen = chosenIndex(options);
126
+ const current = chosen >= 0 ? options[chosen] : null;
127
+ const name = labelledBy ? ` aria-labelledby="${esc(labelledBy)}"` : label ? ` aria-label="${esc(label)}"` : '';
128
+ const text = String(current?.label ?? '');
129
+ return `<input type="hidden" id="${esc(id)}" value="${esc(current?.value ?? '')}"${disabled ? ' disabled' : ''}${inputAttrs ? ` ${inputAttrs}` : ''}>`
130
+ + `<div class="cc-dropdown${classes ? ` ${classes}` : ''}${disabled ? ' disabled' : ''}" data-for="${esc(id)}"${attrs ? ` ${attrs}` : ''}>`
131
+ + `<button type="button" class="cc-dropdown-trigger" id="${esc(id)}-trigger" role="combobox" aria-haspopup="listbox" aria-expanded="false" aria-controls="${esc(id)}-menu"${name}${disabled ? ' disabled' : ''}>`
132
+ + `<span class="cc-dropdown-value" title="${esc(text)}">${esc(text)}</span>${ARROW}</button>`
133
+ + `<div class="cc-dropdown-menu" id="${esc(id)}-menu" role="listbox"${name} tabindex="-1">${menuHTML(id, entries, chosen)}</div>`
134
+ + '</div>';
135
+ }
136
+
137
+ // ── The DOM: finding the parts ──
138
+
139
+ const partsOf = (dd) => ({
140
+ trigger: dd.querySelector(':scope > .cc-dropdown-trigger'),
141
+ menu: dd.querySelector(':scope > .cc-dropdown-menu'),
142
+ label: dd.querySelector(':scope > .cc-dropdown-trigger .cc-dropdown-value'),
143
+ input: dd.dataset.for ? document.getElementById(dd.dataset.for) : null,
144
+ });
145
+ const itemsOf = (dd) => [...(partsOf(dd).menu?.querySelectorAll('.cc-dropdown-item') || [])];
146
+ const optionsOf = (items) => items.map(el => ({ value: el.dataset.value ?? '', label: el.textContent, disabled: el.getAttribute('aria-disabled') === 'true' }));
147
+ const highlightedOf = (items) => items.findIndex(el => el.classList.contains('highlight'));
148
+ const chosenOf = (items) => items.findIndex(el => el.classList.contains('active'));
149
+ const isOpen = (dd) => !!dd?.classList.contains('open');
150
+
151
+ /** The `.cc-dropdown` of a hidden input, or null. */
152
+ export function dropdownOf(input) {
153
+ if (!input?.id) return null;
154
+ const next = input.nextElementSibling;
155
+ if (next?.classList.contains('cc-dropdown') && next.dataset.for === input.id) return next;
156
+ return document.querySelector(`.cc-dropdown[data-for="${CSS.escape(input.id)}"]`);
157
+ }
158
+
159
+ /** What takes the focus for a field: a dropdown's trigger for its hidden input, else the element itself. */
160
+ export function controlOf(el) {
161
+ const dd = el && el.type === 'hidden' ? dropdownOf(el) : null;
162
+ return (dd && partsOf(dd).trigger) || el;
163
+ }
164
+
165
+ // Markup written by settings-kit.js dropdown() has no roles or ids: they are added when it opens.
166
+ function ensureAria(dd) {
167
+ const { trigger, menu, input } = partsOf(dd);
168
+ const base = input?.id || dd.dataset.for || 'cc-dropdown';
169
+ if (!trigger.hasAttribute('role')) trigger.setAttribute('role', 'combobox');
170
+ if (!menu.id) menu.id = `${base}-menu`;
171
+ trigger.setAttribute('aria-controls', menu.id);
172
+ if (!menu.hasAttribute('role')) menu.setAttribute('role', 'listbox');
173
+ itemsOf(dd).forEach((el, i) => {
174
+ if (!el.id) el.id = `${base}-opt-${i}`;
175
+ if (!el.hasAttribute('role')) el.setAttribute('role', 'option');
176
+ el.setAttribute('aria-selected', String(el.classList.contains('active')));
177
+ });
178
+ }
179
+
180
+ // ── Choosing, opening, closing ──
181
+
182
+ function showChosen(dd, index) {
183
+ const { label, input } = partsOf(dd);
184
+ const items = itemsOf(dd);
185
+ items.forEach((el, i) => {
186
+ el.classList.toggle('active', i === index);
187
+ el.setAttribute('aria-selected', String(i === index));
188
+ });
189
+ const item = items[index];
190
+ if (input) input.value = item ? item.dataset.value ?? '' : '';
191
+ if (label) {
192
+ label.textContent = item ? item.textContent : '';
193
+ label.title = label.textContent;
194
+ }
195
+ }
196
+
197
+ function highlight(dd, index) {
198
+ const { trigger, menu } = partsOf(dd);
199
+ const items = itemsOf(dd);
200
+ items.forEach((el, i) => el.classList.toggle('highlight', i === index));
201
+ const item = items[index];
202
+ if (!item) { trigger?.removeAttribute('aria-activedescendant'); return; }
203
+ trigger?.setAttribute('aria-activedescendant', item.id);
204
+ // The menu scrolls itself; scrollIntoView would also move the panes and the window behind it.
205
+ const box = menu.getBoundingClientRect();
206
+ const row = item.getBoundingClientRect();
207
+ if (row.top < box.top + menu.clientTop) menu.scrollTop -= box.top + menu.clientTop - row.top;
208
+ else if (row.bottom > box.top + menu.clientTop + menu.clientHeight) menu.scrollTop += row.bottom - (box.top + menu.clientTop + menu.clientHeight);
209
+ }
210
+
211
+ // What a fixed menu is placed against and cut off by: the nearest ancestor that is a containing
212
+ // block for fixed boxes (a transform, a filter, containment: a floating window), else the viewport.
213
+ function fixedContainer(el) {
214
+ for (let node = el.parentElement; node && node !== document.documentElement; node = node.parentElement) {
215
+ const cs = getComputedStyle(node);
216
+ if (cs.transform !== 'none' || cs.perspective !== 'none' || cs.filter !== 'none'
217
+ || (cs.backdropFilter && cs.backdropFilter !== 'none') || (cs.webkitBackdropFilter && cs.webkitBackdropFilter !== 'none')
218
+ || /paint|layout|strict|content/.test(cs.contain || '') || (cs.containerType && cs.containerType !== 'normal')
219
+ || /transform|perspective|filter/.test(cs.willChange || '')) return node;
220
+ }
221
+ return null;
222
+ }
223
+
224
+ function place(dd) {
225
+ const { trigger, menu } = partsOf(dd);
226
+ const style = menu.style;
227
+ Object.assign(style, { position: 'fixed', left: '0px', top: '0px', right: 'auto', bottom: 'auto', width: 'auto', maxHeight: 'none', minWidth: '0px', maxWidth: 'none' });
228
+ const origin = menu.getBoundingClientRect(); // where the containing block's (0, 0) is on screen
229
+ const t = trigger.getBoundingClientRect();
230
+ let room = { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
231
+ const box = fixedContainer(dd);
232
+ if (box) {
233
+ const cs = getComputedStyle(box);
234
+ if (cs.overflowX !== 'visible' || cs.overflowY !== 'visible') {
235
+ const r = box.getBoundingClientRect();
236
+ room = { left: Math.max(room.left, r.left), top: Math.max(room.top, r.top), right: Math.min(room.right, r.right), bottom: Math.min(room.bottom, r.bottom) };
237
+ }
238
+ }
239
+ room = { left: room.left + EDGE, top: room.top + EDGE, right: room.right - EDGE, bottom: room.bottom - EDGE };
240
+ const roomWidth = Math.max(0, room.right - room.left);
241
+ style.maxWidth = `${roomWidth}px`;
242
+ style.minWidth = `${Math.min(t.width, roomWidth)}px`;
243
+ const height = menu.offsetHeight;
244
+ const below = room.bottom - t.bottom - GAP;
245
+ const above = t.top - GAP - room.top;
246
+ const down = height <= below || below >= above;
247
+ const space = Math.max(0, down ? below : above);
248
+ if (height > space) style.maxHeight = `${space}px`;
249
+ const shown = Math.min(height, space);
250
+ const width = menu.offsetWidth;
251
+ const left = Math.max(room.left, Math.min(t.left, room.right - width));
252
+ const top = down ? t.bottom + GAP : t.top - GAP - shown;
253
+ style.left = `${Math.round(left - origin.left)}px`;
254
+ style.top = `${Math.round(top - origin.top)}px`;
255
+ dd.classList.toggle('drop-up', !down);
256
+ dd._ccPlacedAt = { left: t.left, top: t.top };
257
+ }
258
+
259
+ // Has the trigger moved since its menu was placed (a pane scrolled under it)?
260
+ function moved(dd) {
261
+ const at = dd._ccPlacedAt;
262
+ const now = partsOf(dd).trigger?.getBoundingClientRect();
263
+ return !at || !now || Math.abs(now.left - at.left) > 1 || Math.abs(now.top - at.top) > 1;
264
+ }
265
+
266
+ function open(dd, index = null) {
267
+ const { trigger } = partsOf(dd);
268
+ if (!trigger || trigger.disabled || dd.classList.contains('disabled')) return;
269
+ for (const other of document.querySelectorAll('.cc-dropdown.open')) if (other !== dd) close(other);
270
+ ensureAria(dd);
271
+ dd.classList.add('open');
272
+ trigger.setAttribute('aria-expanded', 'true');
273
+ if (document.activeElement !== trigger) trigger.focus({ preventScroll: true });
274
+ place(dd);
275
+ const items = itemsOf(dd);
276
+ const options = optionsOf(items);
277
+ const chosen = chosenOf(items);
278
+ highlight(dd, index ?? (chosen >= 0 && !options[chosen].disabled ? chosen : edgeIndex(options, 'first')));
279
+ }
280
+
281
+ function close(dd, { focus = false } = {}) {
282
+ const { trigger, menu } = partsOf(dd);
283
+ dd.classList.remove('open', 'drop-up');
284
+ trigger?.setAttribute('aria-expanded', 'false');
285
+ trigger?.removeAttribute('aria-activedescendant');
286
+ for (const el of itemsOf(dd)) el.classList.remove('highlight');
287
+ menu?.removeAttribute('style');
288
+ dd._ccPlacedAt = null;
289
+ if (focus && trigger?.isConnected) trigger.focus({ preventScroll: true });
290
+ }
291
+
292
+ /** The user's choice: shown, the menu closed, the focus on the trigger, then `input` and `change` when it changed. */
293
+ function choose(dd, index) {
294
+ const items = itemsOf(dd);
295
+ const item = items[index];
296
+ const { input } = partsOf(dd);
297
+ if (!item || item.getAttribute('aria-disabled') === 'true') { close(dd, { focus: true }); return; }
298
+ const changed = !!input && input.value !== (item.dataset.value ?? '');
299
+ showChosen(dd, index);
300
+ close(dd, { focus: true });
301
+ // After the focus is back: a listener that draws the form again finds the trigger focused.
302
+ if (changed) {
303
+ input.dispatchEvent(new Event('input', { bubbles: true }));
304
+ input.dispatchEvent(new Event('change', { bubbles: true }));
305
+ }
306
+ }
307
+
308
+ // ── What the code around it calls ──
309
+
310
+ /** `select.innerHTML = …`: new choices; the chosen one by the <select> rule; an open menu stays open. No event. */
311
+ export function setDropdownItems(input, entries) {
312
+ const dd = dropdownOf(input);
313
+ if (!dd) return;
314
+ const { menu } = partsOf(dd);
315
+ const wasOpen = isOpen(dd);
316
+ const before = wasOpen ? itemsOf(dd)[highlightedOf(itemsOf(dd))]?.dataset.value : undefined;
317
+ const options = flatOptions(entries);
318
+ const chosen = chosenIndex(options);
319
+ menu.innerHTML = menuHTML(input.id, entries, chosen);
320
+ showChosen(dd, chosen);
321
+ if (!wasOpen) return;
322
+ place(dd);
323
+ const items = itemsOf(dd);
324
+ const again = before === undefined ? -1 : items.findIndex(el => el.dataset.value === before);
325
+ highlight(dd, again >= 0 ? again : chosen);
326
+ }
327
+
328
+ /** `select.value = …`: the first choice with that value, or none (the value is then ''). No event. */
329
+ export function setDropdownValue(input, value) {
330
+ const dd = dropdownOf(input);
331
+ if (!dd) { if (input) input.value = value ?? ''; return; }
332
+ showChosen(dd, itemsOf(dd).findIndex(el => el.dataset.value === String(value ?? '')));
333
+ }
334
+
335
+ /** `select.disabled = …`: the input, the trigger and the look. A disabled dropdown closes. */
336
+ export function setDropdownDisabled(input, disabled) {
337
+ const dd = dropdownOf(input);
338
+ if (input) input.disabled = !!disabled;
339
+ if (!dd) return;
340
+ if (disabled && isOpen(dd)) close(dd);
341
+ dd.classList.toggle('disabled', !!disabled);
342
+ const { trigger } = partsOf(dd);
343
+ if (trigger) trigger.disabled = !!disabled;
344
+ }
345
+
346
+ /** Closes every open dropdown under `root`; true when one was open. `focus` puts the focus back on its trigger. */
347
+ export function closeDropdowns(root = document, { focus = false } = {}) {
348
+ const open = [...root.querySelectorAll('.cc-dropdown.open')];
349
+ for (const dd of open) close(dd, { focus });
350
+ return open.length > 0;
351
+ }
352
+
353
+ /**
354
+ * Drives every `.cc-dropdown` under `root`, now and drawn later. `signal` (an AbortSignal) takes
355
+ * the listeners off again, the document's and the window's too.
356
+ */
357
+ export function wireDropdowns(root, { signal } = {}) {
358
+ const on = (target, type, handler, options = {}) => target.addEventListener(type, handler, { ...options, signal });
359
+ let typed = '';
360
+ let typedAt = 0;
361
+ let swallowSpaceUp = false;
362
+
363
+ const typeAhead = (dd, char) => {
364
+ const now = Date.now();
365
+ typed = (now - typedAt > TYPE_PAUSE ? '' : typed) + char;
366
+ typedAt = now;
367
+ const items = itemsOf(dd);
368
+ const index = matchIndex(optionsOf(items), typed, highlightedOf(items));
369
+ if (index >= 0) highlight(dd, index);
370
+ };
371
+ const typing = () => !!typed && Date.now() - typedAt <= TYPE_PAUSE;
372
+ // Each opening starts a search of its own: letters typed before it closed do not carry over.
373
+ const show = (dd, index) => { typed = ''; open(dd, index); };
374
+ const printable = (e) => e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && e.key !== ' ';
375
+
376
+ on(root, 'click', (e) => {
377
+ const item = e.target.closest?.('.cc-dropdown-item');
378
+ if (item && root.contains(item)) {
379
+ const dd = item.closest('.cc-dropdown');
380
+ if (item.getAttribute('aria-disabled') !== 'true') choose(dd, itemsOf(dd).indexOf(item));
381
+ return;
382
+ }
383
+ const trigger = e.target.closest?.('.cc-dropdown-trigger');
384
+ if (!trigger || !root.contains(trigger)) return;
385
+ const dd = trigger.closest('.cc-dropdown');
386
+ if (isOpen(dd)) close(dd, { focus: true }); else show(dd);
387
+ });
388
+
389
+ // The focus stays on the trigger while a choice is clicked.
390
+ on(root, 'mousedown', (e) => { if (e.target.closest?.('.cc-dropdown-menu')) e.preventDefault(); });
391
+ on(root, 'mouseover', (e) => {
392
+ const item = e.target.closest?.('.cc-dropdown-item');
393
+ if (!item || item.getAttribute('aria-disabled') === 'true') return;
394
+ const dd = item.closest('.cc-dropdown');
395
+ if (isOpen(dd)) highlight(dd, itemsOf(dd).indexOf(item));
396
+ });
397
+
398
+ on(root, 'keydown', (e) => {
399
+ const trigger = e.target.closest?.('.cc-dropdown-trigger');
400
+ if (!trigger || !root.contains(trigger) || trigger.disabled) return;
401
+ const dd = trigger.closest('.cc-dropdown');
402
+ const items = itemsOf(dd);
403
+ const options = optionsOf(items);
404
+ const current = highlightedOf(items);
405
+ if (!isOpen(dd)) {
406
+ if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(e.key)) {
407
+ e.preventDefault();
408
+ if (e.key === ' ') swallowSpaceUp = true;
409
+ show(dd);
410
+ } else if (e.key === 'Home' || e.key === 'End') {
411
+ e.preventDefault();
412
+ show(dd, edgeIndex(options, e.key === 'Home' ? 'first' : 'last'));
413
+ } else if (printable(e)) {
414
+ e.preventDefault();
415
+ show(dd);
416
+ typeAhead(dd, e.key);
417
+ }
418
+ return;
419
+ }
420
+ switch (e.key) {
421
+ case 'ArrowDown':
422
+ case 'ArrowUp':
423
+ e.preventDefault();
424
+ if (e.altKey && e.key === 'ArrowUp') choose(dd, current);
425
+ else highlight(dd, stepIndex(options, current, e.key === 'ArrowDown' ? 1 : -1));
426
+ break;
427
+ case 'PageDown':
428
+ case 'PageUp':
429
+ e.preventDefault();
430
+ highlight(dd, stepIndex(options, current, e.key === 'PageDown' ? PAGE : -PAGE));
431
+ break;
432
+ case 'Home':
433
+ case 'End':
434
+ e.preventDefault();
435
+ highlight(dd, edgeIndex(options, e.key === 'Home' ? 'first' : 'last'));
436
+ break;
437
+ case 'Enter':
438
+ e.preventDefault();
439
+ choose(dd, current);
440
+ break;
441
+ case ' ':
442
+ e.preventDefault();
443
+ swallowSpaceUp = true;
444
+ if (typing()) typeAhead(dd, ' '); else choose(dd, current);
445
+ break;
446
+ case 'Escape':
447
+ e.preventDefault();
448
+ e.stopPropagation();
449
+ close(dd, { focus: true });
450
+ break;
451
+ case 'Tab':
452
+ close(dd); // the focus moves on as usual; the choice stays as it was
453
+ break;
454
+ default:
455
+ if (printable(e)) { e.preventDefault(); typeAhead(dd, e.key); }
456
+ }
457
+ });
458
+ // A Space that opened or chose must not also click the trigger when it is let go.
459
+ on(root, 'keyup', (e) => {
460
+ if (e.key === ' ' && swallowSpaceUp) { swallowSpaceUp = false; e.preventDefault(); }
461
+ });
462
+
463
+ on(root, 'focusout', (e) => {
464
+ const dd = e.target.closest?.('.cc-dropdown');
465
+ if (dd && isOpen(dd) && !dd.contains(e.relatedTarget)) close(dd);
466
+ });
467
+ on(document, 'pointerdown', (e) => {
468
+ for (const dd of root.querySelectorAll('.cc-dropdown.open')) if (!dd.contains(e.target)) close(dd);
469
+ }, { capture: true });
470
+ // A pane that scrolls the trigger away from its menu closes the menu. A scroll event arrives a frame
471
+ // late, so one from before the menu opened (a click that first scrolled its trigger into view)
472
+ // finds the trigger where the menu was placed, and is let be.
473
+ on(document, 'scroll', (e) => {
474
+ for (const dd of root.querySelectorAll('.cc-dropdown.open')) {
475
+ const target = e.target === document ? document.documentElement : e.target;
476
+ if (!partsOf(dd).menu.contains(target) && target.contains?.(dd) && moved(dd)) close(dd);
477
+ }
478
+ }, { capture: true });
479
+ on(window, 'resize', () => closeDropdowns(root));
480
+ }
@@ -10,6 +10,7 @@ import { createStickyScrollController, getStickyScrollController } from '../ui-s
10
10
  import { wireFileLinks } from '../ui-file-links.js';
11
11
  import { trackWorkerEnd } from '../ui-worker-end.js';
12
12
  import { isDispatchedRun } from '../worker-end.js';
13
+ import { runAwaitsAnswer } from '../sidepanel-session-status.js';
13
14
  import { injectStyles } from './cdx-styles.js';
14
15
  import { mountContextMenu } from './cdx-context-menu.js';
15
16
  import { teardownMcpApps } from './cdx-mcp-app-host.js';
@@ -261,7 +262,7 @@ function buildPanel() {
261
262
  panel.innerHTML = `
262
263
  <div class="cxp-resize-handle"></div>
263
264
  <div class="cxp-header">
264
- <button class="cxp-session-btn" id="cxp-session-btn" type="button">
265
+ <button class="cxp-session-btn" id="cxp-session-btn" type="button" title="${esc(_sessionLabel)}">
265
266
  <span class="cxp-session-label" id="cxp-session-label">${esc(_sessionLabel)}</span>
266
267
  <span class="cxp-dd-arrow">&#x25BE;</span>
267
268
  </button>
@@ -1204,6 +1205,15 @@ export function isCodexPanelOpen() {
1204
1205
  return _visible;
1205
1206
  }
1206
1207
 
1208
+ /**
1209
+ * Boot the panel without showing it (ui-sidepanel-tray.js, when a tab saved while it worked comes back
1210
+ * after a reload): the tabs that were working reattach at once (restoreTabs), so their pills say what
1211
+ * the threads do now.
1212
+ */
1213
+ export function bootCodexPanel() {
1214
+ ensurePanel();
1215
+ }
1216
+
1207
1217
  export async function toggleCodexPanel() {
1208
1218
  ensurePanel();
1209
1219
  if (_visible) {
@@ -1252,10 +1262,12 @@ export async function attachCodexAutomation(run, {
1252
1262
  }, { autoSwitch: false });
1253
1263
  }
1254
1264
  if (!tab) return { ok: false, reason: 'tab_limit' };
1255
- // A task-mode worker between turns (waiting for a follow-up) is alive, not working.
1265
+ // A task-mode worker between turns (waiting for a follow-up) is alive, not working; one whose turn ended
1266
+ // on a question needs you, like one with an approval card up (setRunning and renderPills repaint).
1256
1267
  const working = running && run.turnState !== 'idle' && run.turnState !== 'terminal';
1257
1268
  tab.automationRunId = run.runId;
1258
1269
  tab.automationActive = running;
1270
+ tab.automationAwaits = runAwaitsAnswer(run);
1259
1271
  tab.automationOwnerId = nativeLoopWindowId;
1260
1272
  tab.threadId = threadId;
1261
1273
  tab.project = run.cwd || tab.project;
@@ -16,7 +16,8 @@ import { bindExpandableCard, setCardExpanded } from './cdx-cards.js';
16
16
  import { mountMcpAppCard } from './cdx-mcp-app-host.js';
17
17
  import { OUTPUT_LIMITS, boundedText, jsonAnswer, prettyJsonFences, readableStructuredValue, fileChangeDiffs, parseUnifiedDiff, deduplicateTurnDiff } from './cdx-output-model.js';
18
18
  import { renderReadableOutput, renderReadableBlock, cleanOutputBlocks, hydrateOutputControls, observeOutputBlocks, renderDiffView, restoreDiffViews } from './cdx-output.js';
19
- import { fileLinkTitle, fillFileLinkCopy, isInsideRoots, parseFileLinkTarget } from '../file-links.js';
19
+ import { fileLinkTitle, fillFileLinkCopy, isInsideRoots, parseFileLinkTarget, readFileLink } from '../file-links.js';
20
+ import { sanitizeHtmlString } from '../assistant/asst-sanitize.js';
20
21
  export { setCardExpanded } from './cdx-cards.js';
21
22
 
22
23
  // ── Shared context (set by cdx-tabs via setRenderContext) ──
@@ -98,6 +99,11 @@ export function esc(s) {
98
99
  // streaming delta tick. Memoize so identical text — unchanged messages
99
100
  // elsewhere in the transcript that get re-rendered anyway — returns cached
100
101
  // HTML without re-parsing.
102
+ //
103
+ // What a model writes is not ours, and marked passes raw HTML through: an
104
+ // `<img onerror>` in a reply would run in SynaBun's origin with no click. Every
105
+ // Markdown sink of the panel takes md()'s output, so it goes through the
106
+ // allowlist sanitiser the Assistant, Claude and OpenCode panels use, here, once.
101
107
  const _mdCache = new Map();
102
108
  const _MD_CACHE_LIMIT = 512;
103
109
  let _mdRenderer = null;
@@ -134,6 +140,9 @@ export function md(text) {
134
140
  try { html = parser.call(renderer, prettyJsonFences(key)); }
135
141
  catch { html = markdownFallback(key); }
136
142
  }
143
+ // A page with no DOM to sanitise in, or a sanitiser that fails, gets escaped text: never raw HTML.
144
+ try { html = sanitizeHtmlString(html); }
145
+ catch { html = markdownFallback(key); }
137
146
  if (_mdCache.size >= _MD_CACHE_LIMIT) {
138
147
  const firstKey = _mdCache.keys().next().value;
139
148
  if (firstKey !== undefined) _mdCache.delete(firstKey);
@@ -409,8 +418,11 @@ function openInEditorTitle(target) {
409
418
 
410
419
  export function markProjectFileAnchors(container) {
411
420
  if (!container) return;
412
- container.querySelectorAll('a[href]').forEach((link) => {
413
- const target = projectFileTarget(link.getAttribute('href'));
421
+ // A path the sanitiser kept as written (data-file-target) is the link's target: its href, when it has one, is
422
+ // that path resolved against the page.
423
+ container.querySelectorAll('a[href], a[data-file-target]').forEach((link) => {
424
+ const read = readFileLink(link);
425
+ const target = read && projectFileTarget(read.raw);
414
426
  if (!target) return;
415
427
  link.classList.add('cxp-file-link');
416
428
  link.dataset.projectFilePath = target.path;
@@ -168,7 +168,15 @@ export function injectStyles() {
168
168
  align-items: center;
169
169
  background: var(--cxp-surface-1);
170
170
  z-index: 3;
171
- }
171
+ /* A query container measured in controls: 1em is one header button (24px
172
+ docked, the window's control size when detached, which follows the font
173
+ scale), so the thresholds at the end of this section hold at any scale.
174
+ Nothing in the row inherits it; the session menu takes the panel's back. */
175
+ container: cxp-header / inline-size;
176
+ font-size: 24px;
177
+ }
178
+ .sp-sidepanel.sp-floating > .cxp-header { font-size: var(--fw-header-control-size); }
179
+ .cxp-header > .cxp-session-menu { font-size: 1rem; }
172
180
  .cxp-session-btn {
173
181
  background: var(--cxp-surface-1);
174
182
  border: none;
@@ -182,10 +190,14 @@ export function injectStyles() {
182
190
  padding: 5px 10px;
183
191
  border-radius: var(--cxp-radius-md) 0 0 var(--cxp-radius-md);
184
192
  transition: background var(--cxp-dur-fast), color var(--cxp-dur-fast);
185
- max-width: 100%;
193
+ /* The session name keeps a readable 88px (about 8 characters, or its own
194
+ width if shorter) and gives way first above that: it grows only into the
195
+ room the pencil and the actions leave, so a long name never pushes them.
196
+ Narrower, the container queries let it go down to 32px (the caret). */
197
+ flex: 1 0 88px;
198
+ min-width: 32px;
199
+ max-width: max-content;
186
200
  overflow: hidden;
187
- flex-shrink: 1;
188
- min-width: 0;
189
201
  }
190
202
  .cxp-session-btn:hover {
191
203
  background: var(--cxp-surface-2);
@@ -231,6 +243,8 @@ export function injectStyles() {
231
243
  cursor: pointer;
232
244
  transition: background var(--cxp-dur-fast), color var(--cxp-dur-fast);
233
245
  flex-shrink: 0;
246
+ /* The actions' own gap, kept when the name fills the row. */
247
+ margin-right: 3px;
234
248
  }
235
249
  .cxp-header-rename:hover:not(:disabled) {
236
250
  color: var(--cxp-text);
@@ -256,8 +270,34 @@ export function injectStyles() {
256
270
  margin-left: auto;
257
271
  flex-shrink: 0;
258
272
  }
259
- /* The header account menu's trigger (account-menu.js) gives way before the session name does. */
273
+ /* The header buttons never shrink. The account menu's trigger (account-menu.js)
274
+ is the one piece of the actions that gives way, once the session name is at
275
+ its readable 88px, down to its compact 64px, and truncates. */
276
+ .cxp-actions > * { flex-shrink: 0; }
260
277
  .cxp-actions:has(> .acct-menu-trigger) { flex-shrink: 1; min-width: 0; }
278
+ .cxp-actions > .acct-menu-trigger { flex-shrink: 1; }
279
+ /* Narrow headers, in order: the trigger stays at its compact 64px and the name
280
+ goes from 88px down to its caret; then the trigger is hidden (the cog's
281
+ Account row still opens its menu). Room counted in controls (em) plus px:
282
+ docked, the pencil and six buttons are 7em with 21px of gaps; detached, the
283
+ move handle makes 8em, the window's 6px gaps 39px, the name's floor is 1em.
284
+ Thresholds: name + 64px trigger + that row. */
285
+ @container cxp-header (width < calc(7em + 173px)) {
286
+ .codex-panel:not(.sp-floating) > .cxp-header .cxp-session-btn { flex: 1 1 0; }
287
+ .codex-panel:not(.sp-floating) > .cxp-header > .cxp-actions { flex-shrink: 0; }
288
+ .codex-panel:not(.sp-floating) > .cxp-header .acct-menu-trigger { flex: 0 0 64px; width: 64px; }
289
+ }
290
+ @container cxp-header (width < calc(7em + 117px)) {
291
+ .codex-panel:not(.sp-floating) > .cxp-header .acct-menu-trigger { display: none; }
292
+ }
293
+ @container cxp-header (width < calc(8em + 191px)) {
294
+ .codex-panel.sp-floating > .cxp-header .cxp-session-btn { flex: 1 1 0; }
295
+ .codex-panel.sp-floating > .cxp-header > .cxp-actions { flex-shrink: 0; }
296
+ .codex-panel.sp-floating > .cxp-header .acct-menu-trigger { flex: 0 0 64px; width: 64px; }
297
+ }
298
+ @container cxp-header (width < calc(9em + 103px)) {
299
+ .codex-panel.sp-floating > .cxp-header .acct-menu-trigger { display: none; }
300
+ }
261
301
  .cxp-btn {
262
302
  width: 24px;
263
303
  height: 24px;
@@ -2684,6 +2724,10 @@ export function injectStyles() {
2684
2724
  animation: cxp-working 1.6s ease-in-out infinite;
2685
2725
  flex-shrink: 0;
2686
2726
  }
2727
+ /* A session that waits on you (an approval or a question card): the warn hairline and mark of
2728
+ the Assistant's and a detached window's pills, in place of the working look (paintTrayPill). */
2729
+ .cxp-session-pill.cxp-pill-attention { border-color: color-mix(in srgb, var(--cxp-warning) 42%, transparent); }
2730
+ .cxp-session-pill.cxp-pill-attention .term-minimized-pill-icon { color: var(--cxp-warning); }
2687
2731
  .cxp-hint {
2688
2732
  margin-top: 8px;
2689
2733
  font-size: var(--cxp-fs-xs);