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
@@ -0,0 +1,163 @@
1
+ // Subscription quota only. Credentials stay inside the reader; public values are
2
+ // constructed from numeric windows, never spread from a provider response.
3
+ import { readFile } from 'node:fs/promises';
4
+ import { execFile } from 'node:child_process';
5
+ import { createHash } from 'node:crypto';
6
+ import { join } from 'node:path';
7
+
8
+ const percent = n => typeof n === 'number' && Number.isFinite(n) ? Math.min(100, Math.max(0, n)) : null;
9
+ const date = value => {
10
+ if (value == null) return null;
11
+ const ms = typeof value === 'number' ? value * (value < 1e12 ? 1000 : 1) : Date.parse(value);
12
+ return Number.isFinite(ms) && Math.abs(ms) <= 8.64e15 ? new Date(ms).toISOString() : null;
13
+ };
14
+ const unknown = (source = 'unknown', at = Date.now()) => ({ windows: [], remainingPercent: null, limited: null, resetsAt: null, source, fetchedAt: new Date(at).toISOString() });
15
+
16
+ export function normalizeAccountUsage(provider, raw, at = Date.now()) {
17
+ let windows = [], rejected = false;
18
+ if (provider === 'claude-code') {
19
+ windows = ['five_hour', 'seven_day', 'seven_day_opus', 'seven_day_sonnet'].map(kind => ({ kind, usedPercent: percent(raw?.[kind]?.utilization), resetsAt: date(raw?.[kind]?.resets_at) }));
20
+ } else {
21
+ const snapshot = raw?.rateLimits || raw;
22
+ // rateLimitsByLimitId can contain model-specific quotas; the account-wide
23
+ // rateLimits snapshot is the quota shared by the subscription.
24
+ windows = ['primary', 'secondary'].map(kind => ({ kind, usedPercent: percent(snapshot?.[kind]?.usedPercent), resetsAt: date(snapshot?.[kind]?.resetsAt) }));
25
+ rejected = !!snapshot?.rateLimitReachedType || snapshot?.spendControlReached === true || raw?.ordinaryUsageAllowed === false;
26
+ }
27
+ return summarize(windows, provider === 'codex' ? 'codex-app-server' : 'claude-oauth', at, rejected);
28
+ }
29
+
30
+ function summarize(input, source, at, rejected = false) {
31
+ // Once a window resets its old percentage is unknown, not an invented 0%.
32
+ const windows = input.filter(w => (w.usedPercent !== null || w.rejected) && (!w.resetsAt || Date.parse(w.resetsAt) > at));
33
+ if (!windows.length && !rejected) return unknown(source, at);
34
+ const values = windows.map(w => w.usedPercent).filter(n => n !== null);
35
+ const limited = rejected || windows.some(w => w.usedPercent >= 100 || w.rejected);
36
+ const binding = limited ? windows.filter(w => w.usedPercent >= 100 || w.rejected) : windows.filter(w => w.usedPercent === Math.max(...values));
37
+ const resets = binding.map(w => w.resetsAt).filter(Boolean).sort();
38
+ return { windows: windows.map(({ kind, usedPercent, resetsAt }) => ({ kind, usedPercent, resetsAt })), remainingPercent: limited ? 0 : values.length ? 100 - Math.max(...values) : null, limited, resetsAt: limited && binding.some(w => !w.resetsAt) ? null : resets.at(-1) || null, source, fetchedAt: new Date(at).toISOString() };
39
+ }
40
+
41
+ // Matches Claude Code's directory-scoped macOS keychain service (verified in
42
+ // installed CLI 2.1.302, D1). Never refresh or write OAuth credentials here.
43
+ export async function readClaudeUsageToken(row, { env = process.env, platform = process.platform, signal, now = Date.now, read = readFile, keychain = execFile } = {}) {
44
+ const config = row.id !== 'default' || !!env.CLAUDE_CONFIG_DIR;
45
+ const scope = row.id === 'default' && env.CLAUDE_SECURESTORAGE_CONFIG_DIR !== undefined ? env.CLAUDE_SECURESTORAGE_CONFIG_DIR : config ? row.home : '';
46
+ let credentials;
47
+ if (platform === 'darwin') {
48
+ const suffix = scope ? `-${createHash('sha256').update(scope.normalize('NFC')).digest('hex').slice(0, 8)}` : '';
49
+ const user = /^[a-zA-Z0-9._-]+$/.test(env.USER || '') ? env.USER : 'claude-code-user';
50
+ try {
51
+ const value = await new Promise((resolve, reject) => keychain('/usr/bin/security', ['find-generic-password', '-a', user, '-w', '-s', `Claude Code-credentials${suffix}`], { timeout: 1500, maxBuffer: 1024 * 1024, signal }, (error, stdout) => error ? reject(new Error('credential unavailable')) : resolve(stdout)));
52
+ credentials = JSON.parse(value);
53
+ } catch { /* Linux/file fallback is also used by some macOS installs. */ }
54
+ }
55
+ if (!credentials) {
56
+ try { credentials = JSON.parse(await read(join(scope || row.home, '.credentials.json'), { encoding: 'utf8', signal })); } catch { return null; }
57
+ }
58
+ const oauth = credentials?.claudeAiOauth;
59
+ if (!oauth || typeof oauth.accessToken !== 'string' || !oauth.accessToken || (oauth.expiresAt != null && Number(oauth.expiresAt) <= now())) return null;
60
+ return oauth.accessToken;
61
+ }
62
+
63
+ export function createAccountUsage({ accounts = {}, readCodex = null, fetchImpl = fetch, tokenReader = readClaudeUsageToken, now = Date.now, ttlMs = 90_000, timeoutMs = 3500 } = {}) {
64
+ const cache = new Map(), inflight = new Map(), overlays = new Map(), generations = new Map();
65
+ const keyOf = (p, id) => `${p}:${id}`;
66
+ const rowOf = (p, id) => accounts[p]?.describe(id);
67
+ const signature = row => JSON.stringify([row?.mode, row?.signedIn, row?.identity, row?.home]);
68
+ function note(provider, id, raw) {
69
+ const row = rowOf(provider, id);
70
+ if (row?.mode !== 'subscription' || row.signedIn !== true) return;
71
+ const at = now(), key = keyOf(provider, id);
72
+ if (provider === 'claude-code') {
73
+ const info = raw?.rate_limit_info || raw;
74
+ const kind = ['five_hour', 'seven_day', 'seven_day_opus', 'seven_day_sonnet', 'overage'].includes(info?.rateLimitType) ? info.rateLimitType : 'subscription';
75
+ const previous = overlays.get(key);
76
+ const windows = previous?.signature === signature(row) ? previous.windows.filter(w => w.kind !== kind) : [];
77
+ windows.push({ kind, usedPercent: percent(typeof info?.utilization === 'number' ? info.utilization * 100 : null), resetsAt: date(info?.resetsAt), rejected: info?.status === 'rejected', at });
78
+ overlays.set(key, { signature: signature(row), windows, at });
79
+ } else {
80
+ const value = normalizeAccountUsage(provider, raw, at);
81
+ cache.set(key, { signature: signature(row), value, at });
82
+ }
83
+ }
84
+ function overlay(provider, id, value) {
85
+ const item = overlays.get(keyOf(provider, id));
86
+ if (!item || item.signature !== signature(rowOf(provider, id))) return value;
87
+ const probeAt = cache.get(keyOf(provider, id))?.probeAt ?? Date.parse(value.fetchedAt);
88
+ const fresh = item.windows.filter(w => now() - w.at < ttlMs && (!value.windows.length || w.at >= probeAt) && (!w.resetsAt || Date.parse(w.resetsAt) > now()));
89
+ if (!fresh.length) return value;
90
+ const combined = summarize([...value.windows.filter(w => !fresh.some(f => f.kind === w.kind)), ...fresh], 'claude-sdk', now());
91
+ combined.fetchedAt = new Date(Math.max(...fresh.map(w => w.at), value.windows.length ? Date.parse(value.fetchedAt) : 0)).toISOString();
92
+ return combined;
93
+ }
94
+ function peek(provider, id) {
95
+ const row = rowOf(provider, id);
96
+ if (row?.mode === 'apiKey' || row?.mode === 'api') return unknown('not_applicable', now());
97
+ const item = cache.get(keyOf(provider, id));
98
+ const value = item?.signature === signature(row) && now() - item.at < ttlMs ? summarize(item.value.windows, item.value.source, Date.parse(item.value.fetchedAt), item.value.limited && !item.value.windows.some(w => w.usedPercent >= 100)) : unknown('unknown', now());
99
+ // Do not keep a limited window alive after its reset.
100
+ if (value.windows.some(w => w.resetsAt && Date.parse(w.resetsAt) <= now())) return overlay(provider, id, unknown('unknown', now()));
101
+ return overlay(provider, id, value);
102
+ }
103
+ async function read(provider, id, { force = false } = {}) {
104
+ const row = rowOf(provider, id), key = keyOf(provider, id), sig = signature(row);
105
+ const generation = generations.get(key) || 0;
106
+ const flightKey = JSON.stringify([key, sig, generation]);
107
+ if (!row || row.mode !== 'subscription' || row.signedIn !== true) return peek(provider, id);
108
+ const existing = cache.get(key);
109
+ if (!force && existing?.signature === sig && now() - existing.at < ttlMs && !existing.value.windows.some(w => w.resetsAt && Date.parse(w.resetsAt) <= now())) return peek(provider, id);
110
+ if (inflight.has(flightKey)) return inflight.get(flightKey);
111
+ const startedAt = now();
112
+ const job = (async () => {
113
+ const controller = new AbortController(); let timer;
114
+ try {
115
+ const raw = await Promise.race([
116
+ (async () => {
117
+ if (provider === 'codex') return readCodex?.(id, { signal: controller.signal, timeoutMs });
118
+ const token = await tokenReader(row, { signal: controller.signal, now });
119
+ if (!token || controller.signal.aborted) return null;
120
+ const response = await fetchImpl('https://api.anthropic.com/api/oauth/usage', { headers: { Authorization: `Bearer ${token}`, 'anthropic-beta': 'oauth-2025-04-20' }, signal: controller.signal, redirect: 'error' });
121
+ return response.ok ? response.json() : null;
122
+ })(),
123
+ new Promise(resolve => { timer = setTimeout(() => { controller.abort(); resolve(null); }, timeoutMs); }),
124
+ ]);
125
+ const at = now();
126
+ // A passive notification received during the probe is newer.
127
+ if ((generations.get(key) || 0) === generation && signature(rowOf(provider, id)) === sig && (!cache.has(key) || cache.get(key) === existing)) cache.set(key, { signature: sig, value: normalizeAccountUsage(provider, raw, at), at, probeAt: startedAt });
128
+ } catch {
129
+ if ((generations.get(key) || 0) === generation && signature(rowOf(provider, id)) === sig && (!cache.has(key) || cache.get(key) === existing)) cache.set(key, { signature: sig, value: unknown('unknown', now()), at: now(), probeAt: startedAt });
130
+ } finally { clearTimeout(timer); controller.abort(); inflight.delete(flightKey); }
131
+ return peek(provider, id);
132
+ })();
133
+ inflight.set(flightKey, job);
134
+ return job;
135
+ }
136
+ async function refresh(provider = null) {
137
+ await Promise.all(Object.entries(accounts).filter(([p]) => !provider || p === provider).flatMap(([p, service]) => service.list().map(row => read(p, row.id))));
138
+ return list();
139
+ }
140
+ function list() { return Object.fromEntries(Object.entries(accounts).map(([p, service]) => [p, service.listForClient().map(row => ({ ...row, usage: peek(p, row.id) }))])); }
141
+ function invalidate(p, id) { const key = keyOf(p, id); generations.set(key, (generations.get(key) || 0) + 1); cache.delete(key); overlays.delete(key); }
142
+ return { read, peek, note, refresh, list, invalidate };
143
+ }
144
+
145
+ /** Resolve once at route time. Concrete selections stay binding at dispatch. */
146
+ export function chooseUsageAccount(rows, choice, defaultId = 'default') {
147
+ const pinned = rows.find(row => row.id === choice);
148
+ const candidates = rows.filter(row => row.mode === 'subscription' && row.signedIn === true);
149
+ if (choice !== 'auto' && (!pinned || pinned.signedIn === false || pinned.mode !== 'subscription' || !pinned.usage?.limited)) return { row: pinned, reason: null };
150
+ const available = candidates.filter(row => !row.usage?.limited);
151
+ const known = available.filter(row => typeof row.usage?.remainingPercent === 'number');
152
+ const highest = Math.max(...known.map(row => row.usage.remainingPercent));
153
+ const best = known.filter(row => row.usage.remainingPercent === highest);
154
+ let row = (best.length > 1 ? available.find(row => row.id === defaultId) : null) || best.find(row => row.id === defaultId) || best[0];
155
+ if (!row) row = available.find(row => row.id === defaultId) || available[0];
156
+ let reason = choice === 'auto' ? 'account_auto' : 'account_limited';
157
+ if (!available.length && candidates.length) {
158
+ row = [...candidates].sort((a, b) => (Date.parse(a.usage?.resetsAt) || Infinity) - (Date.parse(b.usage?.resetsAt) || Infinity) || Number(b.id === defaultId) - Number(a.id === defaultId))[0];
159
+ reason = 'accounts_all_limited';
160
+ }
161
+ // With no eligible subscription, retain the existing default behavior.
162
+ return { row: row || (choice === 'auto' ? null : pinned), reason };
163
+ }
@@ -0,0 +1,102 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun — Admin sandbox: what it means for each agent (pure)
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // One global setting (lib/agent-sandbox-setting.js, the Assistant's permission
6
+ // menu) decides whether an agent SynaBun starts may use a sandbox whose setup
7
+ // needs Windows administrator approval (a UAC prompt). Off is the default:
8
+ // then nothing SynaBun starts can ask for one. Each provider says here what
9
+ // the setting means for it; a launcher asks this module and never decides by
10
+ // itself. A provider SynaBun can start must have an entry
11
+ // (tests/agent-sandbox-elevation.test.mjs fails otherwise).
12
+ //
13
+ // The setting never changes a provider's sandbox policy (read-only,
14
+ // workspace-write, full access): only which implementation of it may need an
15
+ // administrator. It is a launch override, never written into a config file.
16
+
17
+ export const ADMIN_SANDBOX_DEFAULT = false;
18
+
19
+ const CODEX_SETTING = 'windows.sandbox';
20
+
21
+ export const SANDBOX_ELEVATION = Object.freeze({
22
+ // `windows.sandbox` (Codex 0.163: "elevated" | "unelevated" | "mxc"): "elevated"
23
+ // provisions two local sandbox accounts with codex-windows-sandbox-setup.exe, a
24
+ // UAC prompt once per CODEX_HOME (SynaBun's accounts each have one);
25
+ // "unelevated" is Codex's restricted-token sandbox: no administrator, weaker isolation.
26
+ codex: Object.freeze({
27
+ changes: true,
28
+ setting: CODEX_SETTING,
29
+ off: 'unelevated',
30
+ on: 'elevated',
31
+ reason: 'Codex picks its Windows sandbox with windows.sandbox: "elevated" needs a one-time administrator setup per account, "unelevated" needs none.',
32
+ }),
33
+ // Claude Code 2.1.303 has a Windows sandbox whose one-time install asks for
34
+ // administrator approval, but only `claude sandbox install` or `/sandbox install`
35
+ // starts it: a session never does, and SynaBun never runs either command.
36
+ 'claude-code': Object.freeze({
37
+ changes: false,
38
+ reason: 'Claude Code installs its Windows sandbox only through `claude sandbox install` or `/sandbox install`, which SynaBun never runs; a session never asks for administrator approval by itself.',
39
+ }),
40
+ // OpenCode has no operating-system sandbox: permission rules only (its
41
+ // "sandboxes" are worktree folders).
42
+ opencode: Object.freeze({
43
+ changes: false,
44
+ reason: 'OpenCode has no operating-system sandbox, only permission rules, so nothing it starts needs administrator approval.',
45
+ }),
46
+ });
47
+
48
+ /** Only `true` turns it on: anything else (missing, a string, null) is the default, off. */
49
+ export function normalizeAdminSandbox(value) {
50
+ return value === true;
51
+ }
52
+
53
+ /** Providers the setting changes (['codex']): what the panel's copy may name. */
54
+ export function adminSandboxProviders() {
55
+ return Object.keys(SANDBOX_ELEVATION).filter((provider) => SANDBOX_ELEVATION[provider].changes);
56
+ }
57
+
58
+ /**
59
+ * What a launcher of `provider` adds for the setting: `args` (CLI words, before
60
+ * the subcommand or anywhere an override is taken), `config` (the same as an
61
+ * SDK config object) and `value`. A provider the setting does not change gets
62
+ * nothing to add and its reason. An unknown provider throws: it must declare
63
+ * its mapping in SANDBOX_ELEVATION first.
64
+ */
65
+ export function sandboxElevationFor(provider, adminSandbox) {
66
+ const entry = SANDBOX_ELEVATION[provider];
67
+ if (!entry) throw new Error(`No admin sandbox mapping for provider "${provider}": add it to SANDBOX_ELEVATION.`);
68
+ const on = normalizeAdminSandbox(adminSandbox);
69
+ if (!entry.changes) return { provider, changes: false, adminSandbox: on, value: null, args: [], config: {}, reason: entry.reason };
70
+ const value = on ? entry.on : entry.off;
71
+ return { provider, changes: true, adminSandbox: on, value, args: ['-c', `${entry.setting}=${JSON.stringify(value)}`], config: configAt(entry.setting, value), reason: entry.reason };
72
+ }
73
+
74
+ function configAt(dotted, value) {
75
+ const keys = dotted.split('.');
76
+ const out = {};
77
+ let node = out;
78
+ keys.forEach((key, index) => { node[key] = index === keys.length - 1 ? value : {}; node = node[key]; });
79
+ return out;
80
+ }
81
+
82
+ /** 'elevated' when the setting is on, else 'unelevated'. */
83
+ export function codexWindowsSandbox(adminSandbox) {
84
+ return sandboxElevationFor('codex', adminSandbox).value;
85
+ }
86
+
87
+ /** ['-c', 'windows.sandbox="unelevated"'] (or "elevated"): a Codex launch override. */
88
+ export function codexWindowsSandboxArgs(adminSandbox) {
89
+ return sandboxElevationFor('codex', adminSandbox).args;
90
+ }
91
+
92
+ /** { windows: { sandbox: 'unelevated' } } (or 'elevated'): the same for the Codex SDK's `config`. */
93
+ export function codexWindowsSandboxConfig(adminSandbox) {
94
+ return sandboxElevationFor('codex', adminSandbox).config;
95
+ }
96
+
97
+ /**
98
+ * A Codex process that runs no command and no turn (a probe in a throwaway
99
+ * home: hooks, settings schema, feature switches) needs no sandbox at all: it
100
+ * is always started with the one that needs no administrator, whatever the setting.
101
+ */
102
+ export const CODEX_PROBE_SANDBOX_ARGS = Object.freeze([...codexWindowsSandboxArgs(false)]);
@@ -0,0 +1,57 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun — Admin sandbox: the one global value
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // DATA_HOME/data/agent-sandbox.json ({ adminSandbox, updatedAt }), read live:
6
+ // one value for every agent SynaBun starts, not per session or tab. No file
7
+ // (or one that cannot be read) is the default, off. What the value means for
8
+ // each provider is lib/agent-sandbox-elevation.js. Only the UI changes it
9
+ // (PUT /api/assistant/admin-sandbox answers UI_ONLY to agents); a change
10
+ // reaches every window as `agents:admin-sandbox-changed` and every listener
11
+ // (server.js restarts the idle Codex app-servers there).
12
+
13
+ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
14
+ import { dirname } from 'node:path';
15
+ import { ADMIN_SANDBOX_DEFAULT, adminSandboxProviders, normalizeAdminSandbox } from './agent-sandbox-elevation.js';
16
+
17
+ export const ADMIN_SANDBOX_EVENT = 'agents:admin-sandbox-changed';
18
+
19
+ export function createAdminSandboxSetting({ path, broadcast = () => {}, log = () => {}, now = Date.now } = {}) {
20
+ if (!path) throw new Error('createAdminSandboxSetting requires a path');
21
+ const listeners = new Set();
22
+ let cache = null; // { mtimeMs, value }
23
+
24
+ function read() {
25
+ try {
26
+ const stat = statSync(path);
27
+ if (cache && cache.mtimeMs === stat.mtimeMs) return cache.value;
28
+ const data = JSON.parse(readFileSync(path, 'utf8'));
29
+ const value = normalizeAdminSandbox(data?.adminSandbox);
30
+ cache = { mtimeMs: stat.mtimeMs, value };
31
+ return value;
32
+ } catch {
33
+ return ADMIN_SANDBOX_DEFAULT;
34
+ }
35
+ }
36
+ /** What the UI shows: the value and the providers it changes. */
37
+ function view() {
38
+ return { adminSandbox: read(), providers: adminSandboxProviders() };
39
+ }
40
+ function set(value) {
41
+ const next = normalizeAdminSandbox(value);
42
+ const before = read();
43
+ mkdirSync(dirname(path), { recursive: true });
44
+ const tmp = `${path}.${process.pid}.tmp`;
45
+ writeFileSync(tmp, JSON.stringify({ adminSandbox: next, updatedAt: new Date(now()).toISOString() }, null, 2) + '\n', 'utf8');
46
+ renameSync(tmp, path);
47
+ cache = null;
48
+ const changed = next !== before;
49
+ if (changed) log('agent-sandbox', `admin sandbox ${next ? 'on' : 'off'}`);
50
+ try { broadcast({ type: ADMIN_SANDBOX_EVENT, ...view() }); } catch { /* nobody listening */ }
51
+ if (changed) for (const listener of [...listeners]) { try { listener(next); } catch { /* the listener's own failure */ } }
52
+ return view();
53
+ }
54
+ function subscribe(listener) { listeners.add(listener); return () => listeners.delete(listener); }
55
+
56
+ return { enabled: read, view, set, subscribe, path };
57
+ }