synabun 2.0.5 → 2.0.9

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 (527) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +2 -1
  3. package/THIRD-PARTY-LICENSES.md +13 -0
  4. package/docs/whatsapp.md +151 -16
  5. package/hooks/claude-code/post-plan.mjs +6 -30
  6. package/hooks/claude-code/session-start.mjs +1 -4
  7. package/hooks/claude-code/shared.mjs +112 -75
  8. package/lib/child-path.js +303 -0
  9. package/lib/claude-hooks.js +2 -1
  10. package/lib/data-home-migration.js +2 -0
  11. package/lib/desktop-app.js +265 -0
  12. package/lib/external-tools.js +7 -3
  13. package/lib/log-redact.js +102 -0
  14. package/lib/package-processes.js +670 -0
  15. package/lib/packaged-runtime.js +138 -11
  16. package/lib/runtime-dependencies.js +225 -0
  17. package/mcp-server/dist/http.d.ts +3 -1
  18. package/mcp-server/dist/http.d.ts.map +1 -1
  19. package/mcp-server/dist/http.js +15 -4
  20. package/mcp-server/dist/http.js.map +1 -1
  21. package/mcp-server/dist/index.d.ts.map +1 -1
  22. package/mcp-server/dist/index.js +9 -6
  23. package/mcp-server/dist/index.js.map +1 -1
  24. package/mcp-server/dist/services/browser-bench.d.ts +1 -1
  25. package/mcp-server/dist/services/browser-bench.d.ts.map +1 -1
  26. package/mcp-server/dist/services/browser-bench.js +1 -1
  27. package/mcp-server/dist/services/browser-bench.js.map +1 -1
  28. package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
  29. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
  30. package/mcp-server/dist/services/budget-judgments.js +153 -0
  31. package/mcp-server/dist/services/budget-judgments.js.map +1 -0
  32. package/mcp-server/dist/services/categories.d.ts +35 -2
  33. package/mcp-server/dist/services/categories.d.ts.map +1 -1
  34. package/mcp-server/dist/services/categories.js +77 -33
  35. package/mcp-server/dist/services/categories.js.map +1 -1
  36. package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
  37. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  38. package/mcp-server/dist/services/codex-config-heal.js +41 -4
  39. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  40. package/mcp-server/dist/services/desktop-bench.d.ts +7 -7
  41. package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -1
  42. package/mcp-server/dist/services/desktop-bench.js +1 -1
  43. package/mcp-server/dist/services/desktop-bench.js.map +1 -1
  44. package/mcp-server/dist/services/identity.d.ts +11 -0
  45. package/mcp-server/dist/services/identity.d.ts.map +1 -1
  46. package/mcp-server/dist/services/identity.js +24 -0
  47. package/mcp-server/dist/services/identity.js.map +1 -1
  48. package/mcp-server/dist/services/neural-interface.d.ts +13 -0
  49. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  50. package/mcp-server/dist/services/neural-interface.js +34 -2
  51. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  52. package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
  53. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
  54. package/mcp-server/dist/services/typesafe-config.js +4 -1
  55. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  56. package/mcp-server/dist/tools/agents.d.ts +11 -8
  57. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  58. package/mcp-server/dist/tools/agents.js +35 -14
  59. package/mcp-server/dist/tools/agents.js.map +1 -1
  60. package/mcp-server/dist/tools/bluesky.js +1 -1
  61. package/mcp-server/dist/tools/bluesky.js.map +1 -1
  62. package/mcp-server/dist/tools/browser-advanced.d.ts +1 -1
  63. package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -1
  64. package/mcp-server/dist/tools/browser-advanced.js +1 -1
  65. package/mcp-server/dist/tools/browser-advanced.js.map +1 -1
  66. package/mcp-server/dist/tools/browser-batch.d.ts +1 -1
  67. package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -1
  68. package/mcp-server/dist/tools/browser-batch.js +1 -1
  69. package/mcp-server/dist/tools/browser-batch.js.map +1 -1
  70. package/mcp-server/dist/tools/browser-cheatsheet.d.ts +1 -1
  71. package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -1
  72. package/mcp-server/dist/tools/browser-cheatsheet.js +1 -1
  73. package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -1
  74. package/mcp-server/dist/tools/browser-interact.d.ts +1 -1
  75. package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -1
  76. package/mcp-server/dist/tools/browser-interact.js +1 -1
  77. package/mcp-server/dist/tools/browser-interact.js.map +1 -1
  78. package/mcp-server/dist/tools/browser-navigate.d.ts +1 -1
  79. package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -1
  80. package/mcp-server/dist/tools/browser-navigate.js +1 -1
  81. package/mcp-server/dist/tools/browser-navigate.js.map +1 -1
  82. package/mcp-server/dist/tools/browser-observe.d.ts +1 -1
  83. package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -1
  84. package/mcp-server/dist/tools/browser-observe.js +1 -1
  85. package/mcp-server/dist/tools/browser-observe.js.map +1 -1
  86. package/mcp-server/dist/tools/card-tools.d.ts +1 -1
  87. package/mcp-server/dist/tools/card-tools.d.ts.map +1 -1
  88. package/mcp-server/dist/tools/card-tools.js +1 -1
  89. package/mcp-server/dist/tools/card-tools.js.map +1 -1
  90. package/mcp-server/dist/tools/category.d.ts +1 -1
  91. package/mcp-server/dist/tools/category.d.ts.map +1 -1
  92. package/mcp-server/dist/tools/category.js +5 -1
  93. package/mcp-server/dist/tools/category.js.map +1 -1
  94. package/mcp-server/dist/tools/choice.d.ts +1 -1
  95. package/mcp-server/dist/tools/choice.d.ts.map +1 -1
  96. package/mcp-server/dist/tools/choice.js +1 -1
  97. package/mcp-server/dist/tools/choice.js.map +1 -1
  98. package/mcp-server/dist/tools/computer.d.ts +1 -1
  99. package/mcp-server/dist/tools/computer.d.ts.map +1 -1
  100. package/mcp-server/dist/tools/computer.js +1 -1
  101. package/mcp-server/dist/tools/computer.js.map +1 -1
  102. package/mcp-server/dist/tools/discord-channel.d.ts +1 -1
  103. package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -1
  104. package/mcp-server/dist/tools/discord-channel.js +1 -1
  105. package/mcp-server/dist/tools/discord-channel.js.map +1 -1
  106. package/mcp-server/dist/tools/discord-guild.d.ts +1 -1
  107. package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -1
  108. package/mcp-server/dist/tools/discord-guild.js +1 -1
  109. package/mcp-server/dist/tools/discord-guild.js.map +1 -1
  110. package/mcp-server/dist/tools/discord-member.d.ts +1 -1
  111. package/mcp-server/dist/tools/discord-member.d.ts.map +1 -1
  112. package/mcp-server/dist/tools/discord-member.js +1 -1
  113. package/mcp-server/dist/tools/discord-member.js.map +1 -1
  114. package/mcp-server/dist/tools/discord-message.d.ts +1 -1
  115. package/mcp-server/dist/tools/discord-message.d.ts.map +1 -1
  116. package/mcp-server/dist/tools/discord-message.js +1 -1
  117. package/mcp-server/dist/tools/discord-message.js.map +1 -1
  118. package/mcp-server/dist/tools/discord-onboarding.d.ts +1 -1
  119. package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -1
  120. package/mcp-server/dist/tools/discord-onboarding.js +1 -1
  121. package/mcp-server/dist/tools/discord-onboarding.js.map +1 -1
  122. package/mcp-server/dist/tools/discord-role.d.ts +1 -1
  123. package/mcp-server/dist/tools/discord-role.d.ts.map +1 -1
  124. package/mcp-server/dist/tools/discord-role.js +1 -1
  125. package/mcp-server/dist/tools/discord-role.js.map +1 -1
  126. package/mcp-server/dist/tools/discord-thread.d.ts +1 -1
  127. package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -1
  128. package/mcp-server/dist/tools/discord-thread.js +1 -1
  129. package/mcp-server/dist/tools/discord-thread.js.map +1 -1
  130. package/mcp-server/dist/tools/discord-webhook.d.ts +1 -1
  131. package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -1
  132. package/mcp-server/dist/tools/discord-webhook.js +1 -1
  133. package/mcp-server/dist/tools/discord-webhook.js.map +1 -1
  134. package/mcp-server/dist/tools/fb-groups.d.ts +1 -1
  135. package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -1
  136. package/mcp-server/dist/tools/fb-groups.js +1 -1
  137. package/mcp-server/dist/tools/fb-groups.js.map +1 -1
  138. package/mcp-server/dist/tools/forget.d.ts +1 -1
  139. package/mcp-server/dist/tools/forget.d.ts.map +1 -1
  140. package/mcp-server/dist/tools/forget.js +1 -1
  141. package/mcp-server/dist/tools/forget.js.map +1 -1
  142. package/mcp-server/dist/tools/git-tools.d.ts +1 -1
  143. package/mcp-server/dist/tools/git-tools.d.ts.map +1 -1
  144. package/mcp-server/dist/tools/git-tools.js +1 -1
  145. package/mcp-server/dist/tools/git-tools.js.map +1 -1
  146. package/mcp-server/dist/tools/gsc/experience.d.ts +1 -1
  147. package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -1
  148. package/mcp-server/dist/tools/gsc/experience.js +1 -1
  149. package/mcp-server/dist/tools/gsc/experience.js.map +1 -1
  150. package/mcp-server/dist/tools/gsc/indexing.d.ts +1 -1
  151. package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -1
  152. package/mcp-server/dist/tools/gsc/indexing.js +1 -1
  153. package/mcp-server/dist/tools/gsc/indexing.js.map +1 -1
  154. package/mcp-server/dist/tools/gsc/inspect.d.ts +1 -1
  155. package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -1
  156. package/mcp-server/dist/tools/gsc/inspect.js +1 -1
  157. package/mcp-server/dist/tools/gsc/inspect.js.map +1 -1
  158. package/mcp-server/dist/tools/gsc/navigate.d.ts +1 -1
  159. package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -1
  160. package/mcp-server/dist/tools/gsc/navigate.js +1 -1
  161. package/mcp-server/dist/tools/gsc/navigate.js.map +1 -1
  162. package/mcp-server/dist/tools/gsc/performance.d.ts +1 -1
  163. package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -1
  164. package/mcp-server/dist/tools/gsc/performance.js +1 -1
  165. package/mcp-server/dist/tools/gsc/performance.js.map +1 -1
  166. package/mcp-server/dist/tools/gsc/settings.d.ts +1 -1
  167. package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -1
  168. package/mcp-server/dist/tools/gsc/settings.js +1 -1
  169. package/mcp-server/dist/tools/gsc/settings.js.map +1 -1
  170. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  171. package/mcp-server/dist/tools/image-tools.d.ts.map +1 -1
  172. package/mcp-server/dist/tools/image-tools.js +1 -1
  173. package/mcp-server/dist/tools/image-tools.js.map +1 -1
  174. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +1 -1
  175. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -1
  176. package/mcp-server/dist/tools/leonardo-browser-tools.js +1 -1
  177. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -1
  178. package/mcp-server/dist/tools/loop.d.ts +1 -1
  179. package/mcp-server/dist/tools/loop.d.ts.map +1 -1
  180. package/mcp-server/dist/tools/loop.js +1 -1
  181. package/mcp-server/dist/tools/loop.js.map +1 -1
  182. package/mcp-server/dist/tools/memories.d.ts +1 -1
  183. package/mcp-server/dist/tools/memories.d.ts.map +1 -1
  184. package/mcp-server/dist/tools/memories.js +1 -1
  185. package/mcp-server/dist/tools/memories.js.map +1 -1
  186. package/mcp-server/dist/tools/morelogin.d.ts +1 -1
  187. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
  188. package/mcp-server/dist/tools/morelogin.js +1 -1
  189. package/mcp-server/dist/tools/morelogin.js.map +1 -1
  190. package/mcp-server/dist/tools/profile.d.ts +1 -1
  191. package/mcp-server/dist/tools/profile.d.ts.map +1 -1
  192. package/mcp-server/dist/tools/profile.js +1 -1
  193. package/mcp-server/dist/tools/profile.js.map +1 -1
  194. package/mcp-server/dist/tools/recall.d.ts +1 -1
  195. package/mcp-server/dist/tools/recall.d.ts.map +1 -1
  196. package/mcp-server/dist/tools/recall.js +1 -1
  197. package/mcp-server/dist/tools/recall.js.map +1 -1
  198. package/mcp-server/dist/tools/reflect.d.ts +1 -1
  199. package/mcp-server/dist/tools/reflect.d.ts.map +1 -1
  200. package/mcp-server/dist/tools/reflect.js +1 -1
  201. package/mcp-server/dist/tools/reflect.js.map +1 -1
  202. package/mcp-server/dist/tools/remember.d.ts +1 -1
  203. package/mcp-server/dist/tools/remember.d.ts.map +1 -1
  204. package/mcp-server/dist/tools/remember.js +13 -11
  205. package/mcp-server/dist/tools/remember.js.map +1 -1
  206. package/mcp-server/dist/tools/restore.d.ts +1 -1
  207. package/mcp-server/dist/tools/restore.d.ts.map +1 -1
  208. package/mcp-server/dist/tools/restore.js +1 -1
  209. package/mcp-server/dist/tools/restore.js.map +1 -1
  210. package/mcp-server/dist/tools/style-guide-tools.d.ts +1 -1
  211. package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -1
  212. package/mcp-server/dist/tools/style-guide-tools.js +1 -1
  213. package/mcp-server/dist/tools/style-guide-tools.js.map +1 -1
  214. package/mcp-server/dist/tools/sync.d.ts +1 -1
  215. package/mcp-server/dist/tools/sync.d.ts.map +1 -1
  216. package/mcp-server/dist/tools/sync.js +1 -1
  217. package/mcp-server/dist/tools/sync.js.map +1 -1
  218. package/mcp-server/dist/tools/tictactoe-tools.d.ts +1 -1
  219. package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -1
  220. package/mcp-server/dist/tools/tictactoe-tools.js +1 -1
  221. package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -1
  222. package/mcp-server/dist/tools/utils.d.ts +1 -1
  223. package/mcp-server/dist/tools/utils.d.ts.map +1 -1
  224. package/mcp-server/dist/tools/utils.js +1 -1
  225. package/mcp-server/dist/tools/utils.js.map +1 -1
  226. package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
  227. package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
  228. package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
  229. package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
  230. package/mcp-server/dist/tools/whiteboard-tools.d.ts +3 -3
  231. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  232. package/mcp-server/dist/tools/whiteboard-tools.js +1 -1
  233. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  234. package/mcp-server/dist/tools/youtube/analytics.d.ts +1 -1
  235. package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -1
  236. package/mcp-server/dist/tools/youtube/analytics.js +1 -1
  237. package/mcp-server/dist/tools/youtube/analytics.js.map +1 -1
  238. package/mcp-server/dist/tools/youtube/download.d.ts +1 -1
  239. package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -1
  240. package/mcp-server/dist/tools/youtube/download.js +1 -1
  241. package/mcp-server/dist/tools/youtube/download.js.map +1 -1
  242. package/mcp-server/dist/tools/youtube/media.d.ts +1 -1
  243. package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -1
  244. package/mcp-server/dist/tools/youtube/media.js +1 -1
  245. package/mcp-server/dist/tools/youtube/media.js.map +1 -1
  246. package/mcp-server/dist/tools/youtube/metadata.d.ts +1 -1
  247. package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -1
  248. package/mcp-server/dist/tools/youtube/metadata.js +1 -1
  249. package/mcp-server/dist/tools/youtube/metadata.js.map +1 -1
  250. package/mcp-server/dist/tools/youtube/navigate.d.ts +1 -1
  251. package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -1
  252. package/mcp-server/dist/tools/youtube/navigate.js +1 -1
  253. package/mcp-server/dist/tools/youtube/navigate.js.map +1 -1
  254. package/mcp-server/dist/tools/youtube/playlist.d.ts +1 -1
  255. package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -1
  256. package/mcp-server/dist/tools/youtube/playlist.js +1 -1
  257. package/mcp-server/dist/tools/youtube/playlist.js.map +1 -1
  258. package/mcp-server/dist/tools/youtube/schedule.d.ts +1 -1
  259. package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -1
  260. package/mcp-server/dist/tools/youtube/schedule.js +1 -1
  261. package/mcp-server/dist/tools/youtube/schedule.js.map +1 -1
  262. package/mcp-server/dist/tools/youtube/source.d.ts +1 -1
  263. package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -1
  264. package/mcp-server/dist/tools/youtube/source.js +1 -1
  265. package/mcp-server/dist/tools/youtube/source.js.map +1 -1
  266. package/mcp-server/dist/tools/youtube/upload.d.ts +1 -1
  267. package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -1
  268. package/mcp-server/dist/tools/youtube/upload.js +4 -9
  269. package/mcp-server/dist/tools/youtube/upload.js.map +1 -1
  270. package/mcp-server/dist/tui.js +18 -5
  271. package/mcp-server/dist/tui.js.map +1 -1
  272. package/mcp-server/dist/version.d.ts +5 -0
  273. package/mcp-server/dist/version.d.ts.map +1 -0
  274. package/mcp-server/dist/version.js +21 -0
  275. package/mcp-server/dist/version.js.map +1 -0
  276. package/mcp-server/package-lock.json +3 -3
  277. package/mcp-server/package.json +3 -3
  278. package/mcp-server/run.mjs +15 -9
  279. package/mcp-server/src/http.ts +18 -3
  280. package/mcp-server/src/index.ts +9 -6
  281. package/mcp-server/src/services/browser-bench.ts +1 -1
  282. package/mcp-server/src/services/budget-judgments.ts +183 -0
  283. package/mcp-server/src/services/categories.ts +77 -32
  284. package/mcp-server/src/services/codex-config-heal.ts +35 -4
  285. package/mcp-server/src/services/desktop-bench.ts +1 -1
  286. package/mcp-server/src/services/identity.ts +27 -0
  287. package/mcp-server/src/services/neural-interface.ts +34 -2
  288. package/mcp-server/src/services/typesafe-config.ts +4 -1
  289. package/mcp-server/src/tools/agents.ts +34 -15
  290. package/mcp-server/src/tools/bluesky.ts +1 -1
  291. package/mcp-server/src/tools/browser-advanced.ts +1 -1
  292. package/mcp-server/src/tools/browser-batch.ts +1 -1
  293. package/mcp-server/src/tools/browser-cheatsheet.ts +1 -1
  294. package/mcp-server/src/tools/browser-interact.ts +1 -1
  295. package/mcp-server/src/tools/browser-navigate.ts +1 -1
  296. package/mcp-server/src/tools/browser-observe.ts +1 -1
  297. package/mcp-server/src/tools/card-tools.ts +1 -1
  298. package/mcp-server/src/tools/category.ts +6 -1
  299. package/mcp-server/src/tools/choice.ts +1 -1
  300. package/mcp-server/src/tools/computer.ts +1 -1
  301. package/mcp-server/src/tools/discord-channel.ts +1 -1
  302. package/mcp-server/src/tools/discord-guild.ts +1 -1
  303. package/mcp-server/src/tools/discord-member.ts +1 -1
  304. package/mcp-server/src/tools/discord-message.ts +1 -1
  305. package/mcp-server/src/tools/discord-onboarding.ts +1 -1
  306. package/mcp-server/src/tools/discord-role.ts +1 -1
  307. package/mcp-server/src/tools/discord-thread.ts +1 -1
  308. package/mcp-server/src/tools/discord-webhook.ts +1 -1
  309. package/mcp-server/src/tools/fb-groups.ts +1 -1
  310. package/mcp-server/src/tools/forget.ts +1 -1
  311. package/mcp-server/src/tools/git-tools.ts +1 -1
  312. package/mcp-server/src/tools/gsc/experience.ts +1 -1
  313. package/mcp-server/src/tools/gsc/indexing.ts +1 -1
  314. package/mcp-server/src/tools/gsc/inspect.ts +1 -1
  315. package/mcp-server/src/tools/gsc/navigate.ts +1 -1
  316. package/mcp-server/src/tools/gsc/performance.ts +1 -1
  317. package/mcp-server/src/tools/gsc/settings.ts +1 -1
  318. package/mcp-server/src/tools/image-tools.ts +1 -1
  319. package/mcp-server/src/tools/leonardo-browser-tools.ts +1 -1
  320. package/mcp-server/src/tools/loop.ts +1 -1
  321. package/mcp-server/src/tools/memories.ts +1 -1
  322. package/mcp-server/src/tools/morelogin.ts +1 -1
  323. package/mcp-server/src/tools/profile.ts +1 -1
  324. package/mcp-server/src/tools/recall.ts +1 -1
  325. package/mcp-server/src/tools/reflect.ts +1 -1
  326. package/mcp-server/src/tools/remember.ts +13 -12
  327. package/mcp-server/src/tools/restore.ts +1 -1
  328. package/mcp-server/src/tools/style-guide-tools.ts +1 -1
  329. package/mcp-server/src/tools/sync.ts +1 -1
  330. package/mcp-server/src/tools/tictactoe-tools.ts +1 -1
  331. package/mcp-server/src/tools/utils.ts +1 -1
  332. package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
  333. package/mcp-server/src/tools/whiteboard-tools.ts +1 -1
  334. package/mcp-server/src/tools/youtube/analytics.ts +1 -1
  335. package/mcp-server/src/tools/youtube/download.ts +1 -1
  336. package/mcp-server/src/tools/youtube/media.ts +1 -1
  337. package/mcp-server/src/tools/youtube/metadata.ts +1 -1
  338. package/mcp-server/src/tools/youtube/navigate.ts +1 -1
  339. package/mcp-server/src/tools/youtube/playlist.ts +1 -1
  340. package/mcp-server/src/tools/youtube/schedule.ts +1 -1
  341. package/mcp-server/src/tools/youtube/source.ts +1 -1
  342. package/mcp-server/src/tools/youtube/upload.ts +4 -12
  343. package/mcp-server/src/tui.ts +24 -10
  344. package/mcp-server/src/version.ts +22 -0
  345. package/neural-interface/i18n/en.json +645 -57
  346. package/neural-interface/i18n/pt-BR.json +644 -56
  347. package/neural-interface/lib/account-usage.js +163 -0
  348. package/neural-interface/lib/agent-sandbox-elevation.js +102 -0
  349. package/neural-interface/lib/agent-sandbox-setting.js +57 -0
  350. package/neural-interface/lib/assistant-api.js +274 -52
  351. package/neural-interface/lib/assistant-brains/claude.js +15 -2
  352. package/neural-interface/lib/assistant-brains/codex.js +3 -0
  353. package/neural-interface/lib/assistant-brains/opencode.js +17 -4
  354. package/neural-interface/lib/assistant-budget-planner.js +390 -0
  355. package/neural-interface/lib/assistant-budget-split.js +408 -0
  356. package/neural-interface/lib/assistant-budget.js +94 -95
  357. package/neural-interface/lib/assistant-config.js +62 -14
  358. package/neural-interface/lib/assistant-dispatch.js +432 -125
  359. package/neural-interface/lib/assistant-jev.js +26 -3
  360. package/neural-interface/lib/assistant-persona.js +68 -11
  361. package/neural-interface/lib/assistant-plan-permissions.js +8 -1
  362. package/neural-interface/lib/assistant-route-accounts.js +14 -0
  363. package/neural-interface/lib/assistant-route-gate-codex.js +3 -1
  364. package/neural-interface/lib/assistant-route-gate.js +19 -3
  365. package/neural-interface/lib/assistant-router.js +373 -42
  366. package/neural-interface/lib/assistant-runtime.js +312 -48
  367. package/neural-interface/lib/assistant-user-writer.js +4 -2
  368. package/neural-interface/lib/augmented-path.js +317 -53
  369. package/neural-interface/lib/claude-accounts.js +342 -31
  370. package/neural-interface/lib/claude-agent-bridge.js +90 -3
  371. package/neural-interface/lib/claude-executable.js +6 -1
  372. package/neural-interface/lib/claude-model-catalog.js +3 -3
  373. package/neural-interface/lib/claude-panel-auth.js +221 -0
  374. package/neural-interface/lib/claude-profile-api-key.js +62 -0
  375. package/neural-interface/lib/cli-install-api.js +137 -0
  376. package/neural-interface/lib/cli-install.js +797 -0
  377. package/neural-interface/lib/cli-path.js +130 -0
  378. package/neural-interface/lib/cli-resolver.js +744 -0
  379. package/neural-interface/lib/cli-update-planner.js +143 -7
  380. package/neural-interface/lib/codex-account-auth.js +180 -0
  381. package/neural-interface/lib/codex-accounts.js +502 -0
  382. package/neural-interface/lib/codex-capabilities.js +2 -1
  383. package/neural-interface/lib/codex-compat-rpc.js +8 -2
  384. package/neural-interface/lib/codex-mcp-approvals.js +5 -1
  385. package/neural-interface/lib/codex-panel-auth.js +62 -0
  386. package/neural-interface/lib/codex-session-settings.js +1 -1
  387. package/neural-interface/lib/codex-settings-schema.js +122 -0
  388. package/neural-interface/lib/desktop/config.js +3 -0
  389. package/neural-interface/lib/exec-loop-command.js +3 -1
  390. package/neural-interface/lib/git-bash/bzip2.js +339 -0
  391. package/neural-interface/lib/git-bash/claude-settings.js +73 -0
  392. package/neural-interface/lib/git-bash/extract-worker.js +34 -0
  393. package/neural-interface/lib/git-bash/install.js +529 -0
  394. package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
  395. package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
  396. package/neural-interface/lib/git-bash/manager.js +268 -0
  397. package/neural-interface/lib/git-bash/pins.js +206 -0
  398. package/neural-interface/lib/git-bash/pins.json +34 -0
  399. package/neural-interface/lib/git-bash/resolver.js +194 -0
  400. package/neural-interface/lib/git-read.js +34 -2
  401. package/neural-interface/lib/install-details.js +163 -0
  402. package/neural-interface/lib/mcp-installer.js +14 -2
  403. package/neural-interface/lib/native-loop-providers.js +22 -4
  404. package/neural-interface/lib/native-loop-runtime.js +9 -4
  405. package/neural-interface/lib/os-path.js +319 -0
  406. package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
  407. package/neural-interface/lib/provider-panel-terminal-auth.js +96 -0
  408. package/neural-interface/lib/pty-host/core.js +2 -1
  409. package/neural-interface/lib/pty-host/manager.js +27 -2
  410. package/neural-interface/lib/remote-policy.js +20 -11
  411. package/neural-interface/lib/session-indexer.js +3 -1
  412. package/neural-interface/lib/session-title-generator.js +6 -3
  413. package/neural-interface/lib/system-about.js +340 -0
  414. package/neural-interface/lib/system-activity.js +66 -0
  415. package/neural-interface/lib/terminal-env.js +11 -3
  416. package/neural-interface/lib/terminal-path.js +55 -0
  417. package/neural-interface/lib/virtual-socket.js +12 -1
  418. package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
  419. package/neural-interface/lib/whatsapp/bridge.js +78 -34
  420. package/neural-interface/lib/whatsapp/commands.js +13 -14
  421. package/neural-interface/lib/whatsapp/config.js +134 -20
  422. package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
  423. package/neural-interface/lib/whatsapp/host-core.js +168 -35
  424. package/neural-interface/lib/whatsapp/inbound.js +5 -3
  425. package/neural-interface/lib/whatsapp/local-file.js +524 -0
  426. package/neural-interface/lib/whatsapp/manager.js +92 -32
  427. package/neural-interface/lib/whatsapp/paths.js +11 -1
  428. package/neural-interface/lib/whatsapp/protocol.js +65 -5
  429. package/neural-interface/lib/whatsapp/redact.js +63 -0
  430. package/neural-interface/lib/whatsapp/service.js +343 -91
  431. package/neural-interface/lib/whatsapp/transcription.js +463 -0
  432. package/neural-interface/package-lock.json +2 -2
  433. package/neural-interface/package.json +1 -1
  434. package/neural-interface/public/index.html +2 -0
  435. package/neural-interface/public/index2d.html +2 -0
  436. package/neural-interface/public/offline.html +16 -1
  437. package/neural-interface/public/onboarding.html +96 -2
  438. package/neural-interface/public/shared/account-i18n.js +7 -0
  439. package/neural-interface/public/shared/account-menu.js +542 -0
  440. package/neural-interface/public/shared/account-usage.js +79 -0
  441. package/neural-interface/public/shared/account-view.js +336 -0
  442. package/neural-interface/public/shared/agent-runtime-options.js +28 -8
  443. package/neural-interface/public/shared/assistant/asst-account-menu.js +298 -0
  444. package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
  445. package/neural-interface/public/shared/assistant/asst-api.js +39 -2
  446. package/neural-interface/public/shared/assistant/asst-brain-picker.js +288 -32
  447. package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
  448. package/neural-interface/public/shared/assistant/asst-mascot.js +126 -7
  449. package/neural-interface/public/shared/assistant/asst-menu.js +219 -80
  450. package/neural-interface/public/shared/assistant/asst-model-chip.js +135 -0
  451. package/neural-interface/public/shared/assistant/asst-panel.js +87 -16
  452. package/neural-interface/public/shared/assistant/asst-render.js +38 -7
  453. package/neural-interface/public/shared/assistant/asst-route.js +72 -14
  454. package/neural-interface/public/shared/assistant/asst-routes-editor.js +45 -6
  455. package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
  456. package/neural-interface/public/shared/assistant/asst-state.js +1 -1
  457. package/neural-interface/public/shared/assistant/asst-styles.js +160 -29
  458. package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
  459. package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
  460. package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
  461. package/neural-interface/public/shared/cdx/cdx-panel.js +49 -108
  462. package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
  463. package/neural-interface/public/shared/cdx/cdx-styles.js +172 -111
  464. package/neural-interface/public/shared/cdx/cdx-tabs.js +264 -664
  465. package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
  466. package/neural-interface/public/shared/claude-account-view.js +3 -0
  467. package/neural-interface/public/shared/cli-install-view.js +392 -0
  468. package/neural-interface/public/shared/cli-status.js +282 -22
  469. package/neural-interface/public/shared/cp/cp-events.js +2 -1
  470. package/neural-interface/public/shared/cp/cp-styles.js +46 -0
  471. package/neural-interface/public/shared/desktop-bridge.js +39 -0
  472. package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
  473. package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
  474. package/neural-interface/public/shared/desktop-titlebar.js +153 -0
  475. package/neural-interface/public/shared/desktop-update-view.js +462 -0
  476. package/neural-interface/public/shared/editor/editor-panel.js +1 -1
  477. package/neural-interface/public/shared/explorer/fx-main.js +1 -1
  478. package/neural-interface/public/shared/git-bash-view.js +145 -0
  479. package/neural-interface/public/shared/html-shell.js +1 -0
  480. package/neural-interface/public/shared/i18n.js +19 -1
  481. package/neural-interface/public/shared/install-details-view.js +86 -0
  482. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -1
  483. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +36 -1
  484. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +17 -0
  485. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +169 -2
  486. package/neural-interface/public/shared/pwa-install-page.js +3 -1
  487. package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
  488. package/neural-interface/public/shared/settings/settings-about.js +254 -0
  489. package/neural-interface/public/shared/settings/settings-ia.js +15 -0
  490. package/neural-interface/public/shared/showcase-privacy.js +490 -0
  491. package/neural-interface/public/shared/storage.js +30 -3
  492. package/neural-interface/public/shared/styles.css +281 -32
  493. package/neural-interface/public/shared/synabun-mascot.js +48 -2
  494. package/neural-interface/public/shared/ui-claude-panel.js +262 -217
  495. package/neural-interface/public/shared/ui-cli-banner.js +355 -0
  496. package/neural-interface/public/shared/ui-explorer.js +2 -0
  497. package/neural-interface/public/shared/ui-git-bash.js +124 -0
  498. package/neural-interface/public/shared/ui-judgments.js +10 -1
  499. package/neural-interface/public/shared/ui-loading.js +30 -6
  500. package/neural-interface/public/shared/ui-menubar.js +13 -3
  501. package/neural-interface/public/shared/ui-navbar.js +3 -1
  502. package/neural-interface/public/shared/ui-provider-auth.js +104 -0
  503. package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
  504. package/neural-interface/public/shared/ui-sessions.js +9 -3
  505. package/neural-interface/public/shared/ui-settings.js +55 -3
  506. package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
  507. package/neural-interface/public/shared/ui-sync.js +8 -0
  508. package/neural-interface/public/shared/ui-terminal.js +17 -0
  509. package/neural-interface/public/shared/ui-tool-updates.js +5 -0
  510. package/neural-interface/public/shared/ui-update.js +598 -7
  511. package/neural-interface/public/shared/ui-whatsapp.js +21 -6
  512. package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
  513. package/neural-interface/public/shared/worker-end.js +2 -0
  514. package/neural-interface/public/sw.js +1 -1
  515. package/neural-interface/public/variant/2d/main.js +10 -1
  516. package/neural-interface/public/variant/3d/main.js +10 -1
  517. package/neural-interface/scripts/rebuild-pty.js +14 -2
  518. package/neural-interface/server.js +1384 -679
  519. package/npm-shrinkwrap.json +4424 -0
  520. package/package.json +57 -2
  521. package/postinstall.js +61 -47
  522. package/preuninstall.js +8 -35
  523. package/setup.js +80 -47
  524. package/skills/synabun/modules/idea.md +1 -1
  525. package/skills/synabun/modules/schedule.md +1 -1
  526. package/updater.cmd +2 -2
  527. package/updater.mjs +97 -3
@@ -110,11 +110,22 @@ export function detectInstallSource(binPath) {
110
110
  if (p.includes('/.bun/')) return 'bun';
111
111
  if (p.includes('/pnpm/') || p.includes('/.local/share/pnpm/')) return 'pnpm';
112
112
  if (p.includes('/.yarn/') || p.includes('/yarn/global/')) return 'yarn';
113
- if (p.includes('/.volta/')) return 'volta';
113
+ if (p.includes('/.volta/') || p.includes('/appdata/local/volta/')) return 'volta';
114
114
 
115
- // Tool-owned installers.
115
+ // Version managers that install tools themselves (`mise use -g
116
+ // github:anomalyco/opencode`, an asdf plugin). A package npm installed
117
+ // under a Node they manage is still npm's: the npm of that Node updates it.
118
+ if ((p.includes('/mise/') || p.includes('/.asdf/')) && !p.includes('/node_modules/')) {
119
+ return p.includes('/.asdf/') ? 'asdf' : 'mise';
120
+ }
121
+
122
+ // Tool-owned installers. The native installer's launcher (~/.local/bin/claude)
123
+ // is a link into ~/.local/share/claude/versions/, and the Codex installer's
124
+ // into ~/.codex/packages/standalone/ (on Windows behind
125
+ // %LOCALAPPDATA%\Programs\OpenAI\Codex\bin): the followed path is what arrives here.
116
126
  if (p.includes('/.opencode/')) return 'standalone';
117
- if (p.includes('/.claude/local/') || p.includes('/anthropicclaude/')) return 'native';
127
+ if (p.includes('/.codex/packages/standalone/') || p.includes('/programs/openai/codex/')) return 'standalone';
128
+ if (p.includes('/.claude/local/') || p.includes('/anthropicclaude/') || p.includes('/.local/share/claude/')) return 'native';
118
129
 
119
130
  // Windows package managers — before the Program Files native rule, since
120
131
  // scoop/choco shims can live under a user profile that also matches.
@@ -126,12 +137,39 @@ export function detectInstallSource(binPath) {
126
137
  if (/\/\.local\/bin\//.test(p)) return 'native';
127
138
  if (/\/program files( \(x86\))?\//.test(p)) return 'native';
128
139
 
129
- // Generic npm global — LAST.
140
+ // Generic npm global — LAST of the package managers.
130
141
  if (p.includes('/node_modules/')) return 'npm';
131
142
 
143
+ // Built from source with cargo, a snap, and a Linux package (apt, dnf, rpm,
144
+ // pacman, apk), which lives in the system's own folders and is updated by
145
+ // that package manager with the system's other software.
146
+ if (p.includes('/.cargo/bin/')) return 'cargo';
147
+ if (p.startsWith('/snap/')) return 'snap';
148
+ if (/^\/(?:usr\/(?:bin|lib|lib64|libexec|share)|bin)\//.test(p)) return 'system';
149
+
132
150
  return 'other';
133
151
  }
134
152
 
153
+ /**
154
+ * The install source of a found CLI, from the path it was found at and the
155
+ * path that link leads to. A version manager's shim (mise, asdf), Volta's,
156
+ * Scoop's, Chocolatey's and WinGet's links say who owns the tool only by where
157
+ * they are: what they lead to is the manager's own program (a mise shim is a
158
+ * link to mise) or a copy somewhere else.
159
+ */
160
+ export function detectInstallSourceOf({ path: found = null, realPath = null } = {}) {
161
+ const p = String(found || '').replace(/\\/g, '/').toLowerCase();
162
+ if (p) {
163
+ if (p.includes('/mise/shims/')) return 'mise';
164
+ if (p.includes('/.asdf/shims/')) return 'asdf';
165
+ if (p.includes('/.volta/bin/') || p.includes('/appdata/local/volta/bin/')) return 'volta';
166
+ if (p.includes('/scoop/shims/')) return 'scoop';
167
+ if (p.includes('/chocolatey/bin/')) return 'choco';
168
+ if (p.includes('/winget/links/')) return 'winget';
169
+ }
170
+ return detectInstallSource(realPath || found);
171
+ }
172
+
135
173
  /**
136
174
  * Derive the Homebrew token from a Caskroom/Cellar path, e.g.
137
175
  * /opt/homebrew/Caskroom/claude-code/2.1.224/claude -> claude-code
@@ -153,15 +191,53 @@ export function resolveBrewToken(toolKey, binPath) {
153
191
  return brewTokenFromPath(binPath) || BREW_FALLBACK_TOKENS[toolKey] || toolKey;
154
192
  }
155
193
 
194
+ /** The command each tool is started with, as its self-updater names it. */
195
+ const TOOL_COMMANDS = {
196
+ 'claude-code': 'claude',
197
+ 'codex': 'codex',
198
+ 'opencode': 'opencode',
199
+ 'gemini': 'gemini',
200
+ };
201
+
202
+ /**
203
+ * A file path as one word of a command typed into a terminal tab: single
204
+ * quotes for a POSIX shell, double quotes for cmd.exe (a Windows file name
205
+ * cannot hold a double quote). A path that needs no quoting is left as it is.
206
+ */
207
+ export function quoteCommandPath(file, platform = process.platform) {
208
+ const value = String(file || '');
209
+ if (platform === 'win32') return /[\s&()^%!;,=]/.test(value) ? `"${value}"` : value;
210
+ return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
211
+ }
212
+
156
213
  /**
157
214
  * Build the command that actually updates a tool, given how it was installed.
158
215
  * Returns null when there is no safe automated path (e.g. winget with no
159
216
  * self-updater) — the caller should show a "use your installer" hint instead.
217
+ *
218
+ * `binPath`: the CLI SynaBun found (lib/cli-resolver.js). A self-updater is
219
+ * then started by that path rather than by name, so the update reaches the
220
+ * very installation the panels use, also when a terminal's PATH does not name
221
+ * its folder (a Windows server started before the CLI was installed, a folder
222
+ * found among the known install locations).
160
223
  */
161
- export function buildUpdateCommand(toolKey, installSource, { brewToken = null } = {}) {
224
+ export function buildUpdateCommand(toolKey, installSource, { brewToken = null, binPath = null, platform = null } = {}) {
225
+ const command = planUpdateCommand(toolKey, installSource, { brewToken, platform });
226
+ const name = TOOL_COMMANDS[toolKey];
227
+ if (!command || !binPath || !name) return command;
228
+ if (command !== name && !command.startsWith(`${name} `)) return command;
229
+ return `${quoteCommandPath(binPath, platform || process.platform)}${command.slice(name.length)}`;
230
+ }
231
+
232
+ function planUpdateCommand(toolKey, installSource, { brewToken = null, platform = null } = {}) {
162
233
  const npmPkg = NPM_PKGS[toolKey];
163
234
  const selfUpdate = SELF_UPDATERS[toolKey] || null;
164
235
 
236
+ // A version manager, cargo, a snap or the system's package manager owns the
237
+ // binary: only it can replace it, and SynaBun does not drive any of them
238
+ // (the system's needs an administrator). The caller shows a hint.
239
+ if (['mise', 'asdf', 'cargo', 'snap', 'system'].includes(installSource)) return null;
240
+
165
241
  // A package manager owns the binary — only that manager can replace it.
166
242
  if (isBrewSource(installSource)) {
167
243
  const token = brewToken || BREW_FALLBACK_TOKENS[toolKey] || toolKey;
@@ -193,7 +269,11 @@ export function buildUpdateCommand(toolKey, installSource, { brewToken = null }
193
269
  return null;
194
270
  case 'standalone':
195
271
  // The tool's own installer put it here, so its own updater is right.
196
- return toolKey === 'opencode' ? 'opencode upgrade --method curl' : selfUpdate;
272
+ // OpenCode's `curl` method runs its bash install script, which Windows
273
+ // does not have: a copy in %USERPROFILE%\.opencode\bin there came from
274
+ // the release archive (lib/cli-install.js) and has no updater to call.
275
+ if (toolKey === 'opencode') return platform === 'win32' ? null : 'opencode upgrade --method curl';
276
+ return selfUpdate;
197
277
  case 'native':
198
278
  return selfUpdate;
199
279
  default:
@@ -281,17 +361,56 @@ export function installSourceLabel(source) {
281
361
  case 'winget': return 'winget';
282
362
  case 'scoop': return 'Scoop';
283
363
  case 'choco': return 'Chocolatey';
364
+ case 'mise': return 'mise';
365
+ case 'asdf': return 'asdf';
366
+ case 'cargo': return 'cargo';
367
+ case 'snap': return 'snap';
368
+ case 'system': return 'your system\'s package manager';
284
369
  default: return 'your installer';
285
370
  }
286
371
  }
287
372
 
373
+ /**
374
+ * The install command each vendor documents first for an operating system
375
+ * (checked 2026-10-17): Anthropic's native installer (code.claude.com/docs/en/setup),
376
+ * OpenAI's standalone installer (learn.chatgpt.com/docs/codex/cli), OpenCode's
377
+ * install script (opencode.ai/docs; on Windows, where the script does not run,
378
+ * npm, the first method its docs list that works in any terminal). These are
379
+ * the same official sources the Install button runs (lib/cli-install.js).
380
+ */
381
+ export function vendorInstallCommand(toolKey, platform = process.platform) {
382
+ const windows = platform === 'win32';
383
+ switch (toolKey) {
384
+ case 'claude-code':
385
+ return windows ? 'irm https://claude.ai/install.ps1 | iex' : 'curl -fsSL https://claude.ai/install.sh | bash';
386
+ case 'codex':
387
+ return windows
388
+ ? 'powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"'
389
+ : 'curl -fsSL https://chatgpt.com/codex/install.sh | sh';
390
+ case 'opencode':
391
+ return windows ? `npm install -g ${NPM_PKGS.opencode}` : 'curl -fsSL https://opencode.ai/install | bash';
392
+ default:
393
+ return NPM_PKGS[toolKey] ? `npm install -g ${NPM_PKGS[toolKey]}` : '';
394
+ }
395
+ }
396
+
288
397
  /**
289
398
  * The command that INSTALLS a tool that is missing. Mirrors the update
290
399
  * matrix so a Homebrew user is not told to `npm install -g`, which would
291
400
  * create a second, conflicting install.
401
+ *
402
+ * With `platform`, a machine that shows no package manager of its own (and,
403
+ * for Claude Code, one that uses npm: Anthropic recommends its native
404
+ * installer over the npm package) is told the vendor's own installer for
405
+ * that system (vendorInstallCommand), and a Windows machine that uses Scoop,
406
+ * Chocolatey or WinGet is told the one each vendor publishes there.
292
407
  */
293
- export function buildInstallCommand(toolKey, installSource = 'unknown') {
408
+ export function buildInstallCommand(toolKey, installSource = 'unknown', { platform = null } = {}) {
294
409
  const npmPkg = NPM_PKGS[toolKey];
410
+ if (platform && !isBrewSource(installSource)) {
411
+ const own = platformInstallCommand(toolKey, installSource, platform);
412
+ if (own) return own;
413
+ }
295
414
  if (isBrewSource(installSource)) {
296
415
  const token = BREW_FALLBACK_TOKENS[toolKey] || toolKey;
297
416
  // Use the package's OWN flavour, not the one inferred from sibling tools:
@@ -310,3 +429,20 @@ export function buildInstallCommand(toolKey, installSource = 'unknown') {
310
429
  default: return `npm install -g ${npmPkg}`;
311
430
  }
312
431
  }
432
+
433
+ /** buildInstallCommand's answer for one operating system, or null to use its package-manager table. */
434
+ function platformInstallCommand(toolKey, installSource, platform) {
435
+ const windows = platform === 'win32';
436
+ const vendor = vendorInstallCommand(toolKey, platform);
437
+ if (toolKey === 'claude-code') {
438
+ if (windows && installSource === 'winget') return 'winget install Anthropic.ClaudeCode';
439
+ return vendor;
440
+ }
441
+ if (toolKey === 'opencode' && windows) {
442
+ if (installSource === 'scoop') return 'scoop install opencode';
443
+ if (installSource === 'choco') return 'choco install opencode';
444
+ }
445
+ // A JavaScript package manager this machine already uses: keep to it.
446
+ if (['npm', 'bun', 'pnpm', 'yarn', 'volta'].includes(installSource)) return null;
447
+ return vendor || null;
448
+ }
@@ -0,0 +1,180 @@
1
+ // Codex account sign-in state and changes (docs/codex-sidepanel.md → Codex
2
+ // accounts). Codex owns its ChatGPT login and its store; SynaBun owns only the
3
+ // API key it keeps per account (lib/codex-accounts.js). This adapter asks
4
+ // Codex what an account's own store holds (`account/read` from an app-server
5
+ // started under that account), signs a credential out, saves a pasted key
6
+ // after OpenAI accepts it, and changes an account's mode, each through
7
+ // `changeCredentials` so the account's idle panel processes restart under the
8
+ // new credential and busy ones refuse the change.
9
+ import { spawn } from 'node:child_process';
10
+ import { verifyOpenAiApiKey } from './claude-profile-api-key.js';
11
+ import { validateProviderApiKey } from './provider-panel-api-key-auth.js';
12
+ import { applyCodexLaunchEnv, codexLaunchArgs } from './codex-accounts.js';
13
+
14
+ const fail = (message, status = 409, code = null) => Object.assign(new Error(message), { status, ...(code ? { code } : {}) });
15
+
16
+ export function createCodexAccountAuth({
17
+ accounts,
18
+ codexBin = () => 'codex',
19
+ env = () => process.env,
20
+ spawnProcess = spawn,
21
+ prepareConfig = () => {},
22
+ statusTimeoutMs = 15_000,
23
+ verifyKey = verifyOpenAiApiKey,
24
+ changeCredentials = async (_id, change) => change(),
25
+ } = {}) {
26
+ if (!accounts) throw new Error('createCodexAccountAuth requires accounts');
27
+ function account(id) {
28
+ if (typeof id !== 'string' || !/^[a-z0-9-]{1,64}$/.test(id)) throw fail('Unknown Codex account', 404);
29
+ const row = accounts.profileFor(id);
30
+ if (!row || row.id !== id) throw fail('Unknown Codex account', 404);
31
+ return row;
32
+ }
33
+ // Codex run under the account's own store: inherited credentials out, its
34
+ // CODEX_HOME in, never the key SynaBun holds (that is not Codex's store).
35
+ // The launch's overrides (the Windows sandbox of the Admin sandbox setting) follow the subcommand.
36
+ function launch(id, words) {
37
+ account(id);
38
+ const plan = accounts.launchFor(id);
39
+ if (!plan.ok) throw fail(plan.message, 404);
40
+ prepareConfig(plan.home);
41
+ let file = codexBin();
42
+ if (!file) throw fail('Codex CLI not found. Install Codex to sign in.', 503);
43
+ const args = [...words, ...codexLaunchArgs(plan)];
44
+ const script = /\.[cm]?js$/i.test(file);
45
+ const shell = process.platform === 'win32' && /\.(cmd|bat)$/i.test(file);
46
+ const proc = spawnProcess(script ? process.execPath : file, script ? [file, ...args] : args, {
47
+ env: { ...applyCodexLaunchEnv(env(), { unset: plan.unset, env: plan.env }), NO_COLOR: '1' },
48
+ stdio: ['pipe', 'pipe', 'pipe'], shell, windowsHide: true,
49
+ });
50
+ proc.stdin?.on('error', () => {});
51
+ return proc;
52
+ }
53
+ /** What Codex says the account's own store holds: { account: { type, email, planType } | null }. Never a credential. */
54
+ function nativeRead(id, method, params, { signal, timeoutMs = statusTimeoutMs } = {}) {
55
+ return new Promise((resolve, reject) => {
56
+ let proc;
57
+ try { proc = launch(id, ['app-server']); } catch (error) { reject(error); return; }
58
+ let buffer = '', settled = false, nextId = 1;
59
+ const waiting = new Map();
60
+ const finish = (error, result) => {
61
+ if (settled) return;
62
+ settled = true; clearTimeout(timer); signal?.removeEventListener('abort', abort);
63
+ try { proc.stdin.end(); } catch {}
64
+ try { proc.kill(); } catch {}
65
+ error ? reject(error) : resolve(result);
66
+ };
67
+ const abort = () => finish(new Error('Codex account read cancelled.'));
68
+ const timer = setTimeout(() => finish(new Error('Codex did not answer in time. Try Refresh.')), timeoutMs);
69
+ timer.unref?.();
70
+ signal?.addEventListener('abort', abort, { once: true });
71
+ if (signal?.aborted) { abort(); return; }
72
+ const call = (method, params) => new Promise((ok, no) => {
73
+ const callId = nextId++;
74
+ waiting.set(callId, { ok, no });
75
+ try { proc.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', id: callId, method, params })}\n`); }
76
+ catch (error) { waiting.delete(callId); no(error); }
77
+ });
78
+ proc.stdout.setEncoding?.('utf8');
79
+ proc.stdout.on('data', (chunk) => {
80
+ buffer = (buffer + chunk).slice(-1_048_576);
81
+ let index;
82
+ while ((index = buffer.indexOf('\n')) >= 0) {
83
+ const line = buffer.slice(0, index).trim();
84
+ buffer = buffer.slice(index + 1);
85
+ if (!line) continue;
86
+ let msg;
87
+ try { msg = JSON.parse(line); } catch { continue; }
88
+ if (msg.id === undefined || msg.method) continue;
89
+ const entry = waiting.get(msg.id);
90
+ if (!entry) continue;
91
+ waiting.delete(msg.id);
92
+ if (msg.error) entry.no(new Error('Codex could not read the account.'));
93
+ else entry.ok(msg.result);
94
+ }
95
+ });
96
+ proc.stderr.on('data', () => {}); // Never forward CLI output: it can carry credential details.
97
+ proc.on('error', () => finish(new Error('Could not start Codex. Check its installation.')));
98
+ proc.on('close', () => finish(new Error('Codex closed before it answered.')));
99
+ (async () => {
100
+ try {
101
+ await call('initialize', { clientInfo: { name: 'synabun-codex-accounts', title: 'SynaBun Codex accounts', version: '0.0.1' } });
102
+ proc.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', method: 'initialized' })}\n`);
103
+ finish(null, await call(method, params));
104
+ } catch (error) { finish(error); }
105
+ })();
106
+ });
107
+ }
108
+ async function nativeStatus(id) {
109
+ const result = await nativeRead(id, 'account/read', { refreshToken: false });
110
+ const native = result?.account && typeof result.account === 'object' ? result.account : null;
111
+ return { account: native ? { type: native.type || null, email: native.email || null, planType: native.planType || null } : null };
112
+ }
113
+ const rateLimits = (id, options) => nativeRead(id, 'account/rateLimits/read', {}, options);
114
+ // `codex logout` in the account's home: Codex removes its own login (auth.json or its keyring entry).
115
+ function nativeLogout(id) {
116
+ return new Promise((resolve, reject) => {
117
+ let proc, timer;
118
+ try { proc = launch(id, ['logout']); } catch { reject(fail('Could not sign out of Codex. Try again.', 500)); return; }
119
+ let settled = false;
120
+ const finish = (ok) => { if (settled) return; settled = true; clearTimeout(timer); ok ? resolve() : reject(fail('Could not sign out of Codex. Try again.', 500)); };
121
+ proc.stdout.on('data', () => {}); proc.stderr.on('data', () => {});
122
+ proc.on('error', () => finish(false));
123
+ proc.on('close', (code) => finish(code === 0));
124
+ timer = setTimeout(() => { try { proc.kill(); } catch {} finish(false); }, statusTimeoutMs);
125
+ timer.unref?.();
126
+ });
127
+ }
128
+ /** The account as every surface shows it, after asking Codex about its own store. */
129
+ async function read(id) {
130
+ account(id);
131
+ let failure = null;
132
+ try { await accounts.refreshStatus([id], { force: true }); } catch (error) { failure = error; }
133
+ account(id);
134
+ const row = accounts.describeForClient(id);
135
+ if (failure && !row) throw failure;
136
+ return { accountId: id, account: row };
137
+ }
138
+ const pending = new Set();
139
+ async function guarded(id, work) {
140
+ account(id);
141
+ if (pending.has(id)) throw fail('Another sign-in change for this account is still running.');
142
+ pending.add(id);
143
+ try { return await work(); } finally { pending.delete(id); }
144
+ }
145
+ async function signInApiKey(id, key) {
146
+ account(id); key = validateProviderApiKey('codex', key);
147
+ try {
148
+ return await guarded(id, async () => {
149
+ await verifyKey(key);
150
+ account(id); // A removed account is never recreated by a late answer.
151
+ await changeCredentials(id, () => { account(id); accounts.saveApiKey(id, key); });
152
+ });
153
+ } finally { key = null; }
154
+ }
155
+ // `credential`: 'apiKey' removes the account's key (SynaBun's file, or Codex's own stored key),
156
+ // 'subscription' runs Codex's own logout in the account's home, 'all' both.
157
+ async function signOut(id, credential = 'all') {
158
+ account(id);
159
+ if (!['all', 'apiKey', 'subscription'].includes(credential)) throw fail('Choose which sign-in to remove.', 400);
160
+ return guarded(id, () => changeCredentials(id, async () => {
161
+ const row = accounts.describe(id);
162
+ const ownKey = row?.apiKey?.source === 'synabun';
163
+ const codexKey = row?.apiKey?.source === 'codex';
164
+ if (credential === 'apiKey' && !row?.apiKey?.present && !row?.apiKey?.error) throw fail(`${row?.label || id} has no API key.`);
165
+ if (credential === 'subscription' && codexKey) throw fail(`${row.label} has no ChatGPT sign-in: Codex holds an API key for it.`);
166
+ if (credential !== 'subscription' && (ownKey || row?.apiKey?.error)) accounts.clearApiKey(id);
167
+ // Codex's own store is cleared for a ChatGPT sign-out, or for a key Codex itself holds.
168
+ if (credential === 'subscription' || (credential === 'all' && !ownKey) || (credential === 'apiKey' && codexKey)) {
169
+ await nativeLogout(id);
170
+ accounts.noteNativeStatus(id, { account: null });
171
+ }
172
+ return accounts.describeForClient(id);
173
+ }));
174
+ }
175
+ /** What the account's sessions use from now on: its idle panel processes restart under it. */
176
+ async function setMode(id, mode) {
177
+ return guarded(id, () => changeCredentials(id, () => accounts.setMode(id, mode)));
178
+ }
179
+ return { read, nativeStatus, rateLimits, signInApiKey, signOut, setMode };
180
+ }