synabun 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1163) hide show
  1. package/CHANGELOG.md +205 -662
  2. package/LICENSE-COMMERCIAL.md +33 -0
  3. package/NOTICE +17 -0
  4. package/README.md +175 -853
  5. package/THIRD-PARTY-LICENSES.md +136 -0
  6. package/benchmarks/browser-live-results.json +79 -0
  7. package/benchmarks/browser-v2-results.json +258 -0
  8. package/benchmarks/fixtures/browser/README.md +57 -0
  9. package/benchmarks/fixtures/browser/page-state.json +132 -0
  10. package/benchmarks/fixtures/browser/social.json +92 -0
  11. package/benchmarks/fixtures/browser/target.json +319 -0
  12. package/benchmarks/fixtures/desktop/README.md +58 -0
  13. package/benchmarks/fixtures/desktop/abstention.json +59 -0
  14. package/benchmarks/fixtures/desktop/adversarial.json +22 -0
  15. package/benchmarks/fixtures/desktop/forbidden.json +93 -0
  16. package/benchmarks/fixtures/desktop/generate.mjs +1023 -0
  17. package/benchmarks/fixtures/desktop/target.json +136 -0
  18. package/bin/synabun.js +30 -0
  19. package/docs/whatsapp.md +325 -0
  20. package/hooks/claude-code/post-plan.mjs +613 -391
  21. package/hooks/claude-code/post-remember.mjs +246 -122
  22. package/hooks/claude-code/pre-compact.mjs +171 -110
  23. package/hooks/claude-code/pre-task.mjs +133 -0
  24. package/hooks/claude-code/pre-websearch.mjs +15 -4
  25. package/hooks/claude-code/prompt-origin.mjs +94 -0
  26. package/hooks/claude-code/prompt-submit.mjs +1244 -861
  27. package/hooks/claude-code/session-start.mjs +114 -156
  28. package/hooks/claude-code/shared.mjs +1228 -368
  29. package/hooks/claude-code/state.mjs +167 -0
  30. package/hooks/claude-code/stop.mjs +515 -140
  31. package/hooks/claude-code/subagent-start.mjs +154 -0
  32. package/hooks/claude-code/subagent-stop.mjs +102 -0
  33. package/hooks/claude-code/task-gate.mjs +150 -0
  34. package/launcher.mjs +40 -0
  35. package/lib/claude-hooks.js +137 -0
  36. package/lib/claude-usage-audit.js +141 -0
  37. package/lib/client-config-repair.js +145 -0
  38. package/lib/data-home-migration.js +502 -0
  39. package/lib/desktop-pwa.js +206 -0
  40. package/lib/external-tools.js +221 -0
  41. package/lib/first-launch-protection.js +245 -0
  42. package/lib/packaged-runtime.js +110 -0
  43. package/lib/paths.d.ts +21 -0
  44. package/lib/paths.js +103 -0
  45. package/lib/start-launcher.js +1309 -0
  46. package/mcp-server/dist/config.d.ts +22 -0
  47. package/mcp-server/dist/config.d.ts.map +1 -0
  48. package/mcp-server/dist/config.js +109 -0
  49. package/mcp-server/dist/config.js.map +1 -0
  50. package/mcp-server/dist/http.d.ts +30 -0
  51. package/mcp-server/dist/http.d.ts.map +1 -0
  52. package/mcp-server/dist/http.js +276 -0
  53. package/mcp-server/dist/http.js.map +1 -0
  54. package/mcp-server/dist/index.d.ts +48 -0
  55. package/mcp-server/dist/index.d.ts.map +1 -0
  56. package/mcp-server/dist/index.js +538 -0
  57. package/mcp-server/dist/index.js.map +1 -0
  58. package/mcp-server/dist/preload-http.d.ts +3 -0
  59. package/mcp-server/dist/preload-http.d.ts.map +1 -0
  60. package/mcp-server/dist/preload-http.js +28 -0
  61. package/mcp-server/dist/preload-http.js.map +1 -0
  62. package/mcp-server/dist/preload.d.ts +3 -0
  63. package/mcp-server/dist/preload.d.ts.map +1 -0
  64. package/mcp-server/dist/preload.js +32 -0
  65. package/mcp-server/dist/preload.js.map +1 -0
  66. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts +19 -0
  67. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts.map +1 -0
  68. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js +403 -0
  69. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js.map +1 -0
  70. package/mcp-server/dist/scripts/setup-embeddings.d.ts +3 -0
  71. package/mcp-server/dist/scripts/setup-embeddings.d.ts.map +1 -0
  72. package/mcp-server/dist/scripts/setup-embeddings.js +15 -0
  73. package/mcp-server/dist/scripts/setup-embeddings.js.map +1 -0
  74. package/mcp-server/dist/services/assistant-judgments.d.ts +79 -0
  75. package/mcp-server/dist/services/assistant-judgments.d.ts.map +1 -0
  76. package/mcp-server/dist/services/assistant-judgments.js +128 -0
  77. package/mcp-server/dist/services/assistant-judgments.js.map +1 -0
  78. package/mcp-server/dist/services/browser-assist-gate.d.ts +314 -0
  79. package/mcp-server/dist/services/browser-assist-gate.d.ts.map +1 -0
  80. package/mcp-server/dist/services/browser-assist-gate.js +344 -0
  81. package/mcp-server/dist/services/browser-assist-gate.js.map +1 -0
  82. package/mcp-server/dist/services/browser-assist.d.ts +104 -0
  83. package/mcp-server/dist/services/browser-assist.d.ts.map +1 -0
  84. package/mcp-server/dist/services/browser-assist.js +282 -0
  85. package/mcp-server/dist/services/browser-assist.js.map +1 -0
  86. package/mcp-server/dist/services/browser-bench.d.ts +772 -0
  87. package/mcp-server/dist/services/browser-bench.d.ts.map +1 -0
  88. package/mcp-server/dist/services/browser-bench.js +424 -0
  89. package/mcp-server/dist/services/browser-bench.js.map +1 -0
  90. package/mcp-server/dist/services/browser-judgments.d.ts +196 -0
  91. package/mcp-server/dist/services/browser-judgments.d.ts.map +1 -0
  92. package/mcp-server/dist/services/browser-judgments.js +363 -0
  93. package/mcp-server/dist/services/browser-judgments.js.map +1 -0
  94. package/mcp-server/dist/services/browser-risk.d.ts +166 -0
  95. package/mcp-server/dist/services/browser-risk.d.ts.map +1 -0
  96. package/mcp-server/dist/services/browser-risk.js +458 -0
  97. package/mcp-server/dist/services/browser-risk.js.map +1 -0
  98. package/mcp-server/dist/services/categories.d.ts +61 -0
  99. package/mcp-server/dist/services/categories.d.ts.map +1 -0
  100. package/mcp-server/dist/services/categories.js +377 -0
  101. package/mcp-server/dist/services/categories.js.map +1 -0
  102. package/mcp-server/dist/services/codex-config-heal.d.ts +49 -0
  103. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -0
  104. package/mcp-server/dist/services/codex-config-heal.js +346 -0
  105. package/mcp-server/dist/services/codex-config-heal.js.map +1 -0
  106. package/mcp-server/dist/services/desktop-assist-gate.d.ts +198 -0
  107. package/mcp-server/dist/services/desktop-assist-gate.d.ts.map +1 -0
  108. package/mcp-server/dist/services/desktop-assist-gate.js +202 -0
  109. package/mcp-server/dist/services/desktop-assist-gate.js.map +1 -0
  110. package/mcp-server/dist/services/desktop-assist.d.ts +104 -0
  111. package/mcp-server/dist/services/desktop-assist.d.ts.map +1 -0
  112. package/mcp-server/dist/services/desktop-assist.js +266 -0
  113. package/mcp-server/dist/services/desktop-assist.js.map +1 -0
  114. package/mcp-server/dist/services/desktop-bench.d.ts +553 -0
  115. package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -0
  116. package/mcp-server/dist/services/desktop-bench.js +311 -0
  117. package/mcp-server/dist/services/desktop-bench.js.map +1 -0
  118. package/mcp-server/dist/services/desktop-client.d.ts +23 -0
  119. package/mcp-server/dist/services/desktop-client.d.ts.map +1 -0
  120. package/mcp-server/dist/services/desktop-client.js +79 -0
  121. package/mcp-server/dist/services/desktop-client.js.map +1 -0
  122. package/mcp-server/dist/services/desktop-judgments.d.ts +125 -0
  123. package/mcp-server/dist/services/desktop-judgments.d.ts.map +1 -0
  124. package/mcp-server/dist/services/desktop-judgments.js +177 -0
  125. package/mcp-server/dist/services/desktop-judgments.js.map +1 -0
  126. package/mcp-server/dist/services/desktop-risk.d.ts +283 -0
  127. package/mcp-server/dist/services/desktop-risk.d.ts.map +1 -0
  128. package/mcp-server/dist/services/desktop-risk.js +605 -0
  129. package/mcp-server/dist/services/desktop-risk.js.map +1 -0
  130. package/mcp-server/dist/services/discord.d.ts +112 -0
  131. package/mcp-server/dist/services/discord.d.ts.map +1 -0
  132. package/mcp-server/dist/services/discord.js +477 -0
  133. package/mcp-server/dist/services/discord.js.map +1 -0
  134. package/mcp-server/dist/services/edit-stale.d.ts +81 -0
  135. package/mcp-server/dist/services/edit-stale.d.ts.map +1 -0
  136. package/mcp-server/dist/services/edit-stale.js +358 -0
  137. package/mcp-server/dist/services/edit-stale.js.map +1 -0
  138. package/mcp-server/dist/services/embedding-service.d.ts +16 -0
  139. package/mcp-server/dist/services/embedding-service.d.ts.map +1 -0
  140. package/mcp-server/dist/services/embedding-service.js +126 -0
  141. package/mcp-server/dist/services/embedding-service.js.map +1 -0
  142. package/mcp-server/dist/services/embedding-worker.d.ts +2 -0
  143. package/mcp-server/dist/services/embedding-worker.d.ts.map +1 -0
  144. package/mcp-server/dist/services/embedding-worker.js +52 -0
  145. package/mcp-server/dist/services/embedding-worker.js.map +1 -0
  146. package/mcp-server/dist/services/fb-regions.d.ts +71 -0
  147. package/mcp-server/dist/services/fb-regions.d.ts.map +1 -0
  148. package/mcp-server/dist/services/fb-regions.js +211 -0
  149. package/mcp-server/dist/services/fb-regions.js.map +1 -0
  150. package/mcp-server/dist/services/file-checksums.d.ts +22 -0
  151. package/mcp-server/dist/services/file-checksums.d.ts.map +1 -0
  152. package/mcp-server/dist/services/file-checksums.js +55 -0
  153. package/mcp-server/dist/services/file-checksums.js.map +1 -0
  154. package/mcp-server/dist/services/file-excerpt.d.ts +24 -0
  155. package/mcp-server/dist/services/file-excerpt.d.ts.map +1 -0
  156. package/mcp-server/dist/services/file-excerpt.js +65 -0
  157. package/mcp-server/dist/services/file-excerpt.js.map +1 -0
  158. package/mcp-server/dist/services/identity.d.ts +124 -0
  159. package/mcp-server/dist/services/identity.d.ts.map +1 -0
  160. package/mcp-server/dist/services/identity.js +241 -0
  161. package/mcp-server/dist/services/identity.js.map +1 -0
  162. package/mcp-server/dist/services/local-embeddings.d.ts +2 -0
  163. package/mcp-server/dist/services/local-embeddings.d.ts.map +1 -0
  164. package/mcp-server/dist/services/local-embeddings.js +3 -0
  165. package/mcp-server/dist/services/local-embeddings.js.map +1 -0
  166. package/mcp-server/dist/services/memory-client.d.ts +4 -0
  167. package/mcp-server/dist/services/memory-client.d.ts.map +1 -0
  168. package/mcp-server/dist/services/memory-client.js +27 -0
  169. package/mcp-server/dist/services/memory-client.js.map +1 -0
  170. package/mcp-server/dist/services/memory-judge-backfill.d.ts +135 -0
  171. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -0
  172. package/mcp-server/dist/services/memory-judge-backfill.js +510 -0
  173. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -0
  174. package/mcp-server/dist/services/memory-judgments.d.ts +362 -0
  175. package/mcp-server/dist/services/memory-judgments.d.ts.map +1 -0
  176. package/mcp-server/dist/services/memory-judgments.js +674 -0
  177. package/mcp-server/dist/services/memory-judgments.js.map +1 -0
  178. package/mcp-server/dist/services/memory-maintenance.d.ts +108 -0
  179. package/mcp-server/dist/services/memory-maintenance.d.ts.map +1 -0
  180. package/mcp-server/dist/services/memory-maintenance.js +403 -0
  181. package/mcp-server/dist/services/memory-maintenance.js.map +1 -0
  182. package/mcp-server/dist/services/memory-retrieval.d.ts +66 -0
  183. package/mcp-server/dist/services/memory-retrieval.d.ts.map +1 -0
  184. package/mcp-server/dist/services/memory-retrieval.js +412 -0
  185. package/mcp-server/dist/services/memory-retrieval.js.map +1 -0
  186. package/mcp-server/dist/services/memory-schema.d.ts +16 -0
  187. package/mcp-server/dist/services/memory-schema.d.ts.map +1 -0
  188. package/mcp-server/dist/services/memory-schema.js +282 -0
  189. package/mcp-server/dist/services/memory-schema.js.map +1 -0
  190. package/mcp-server/dist/services/memory-sessions.d.ts +24 -0
  191. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -0
  192. package/mcp-server/dist/services/memory-sessions.js +110 -0
  193. package/mcp-server/dist/services/memory-sessions.js.map +1 -0
  194. package/mcp-server/dist/services/memory-triage.d.ts +60 -0
  195. package/mcp-server/dist/services/memory-triage.d.ts.map +1 -0
  196. package/mcp-server/dist/services/memory-triage.js +189 -0
  197. package/mcp-server/dist/services/memory-triage.js.map +1 -0
  198. package/mcp-server/dist/services/memory-verification.d.ts +24 -0
  199. package/mcp-server/dist/services/memory-verification.d.ts.map +1 -0
  200. package/mcp-server/dist/services/memory-verification.js +92 -0
  201. package/mcp-server/dist/services/memory-verification.js.map +1 -0
  202. package/mcp-server/dist/services/memory-writer.d.ts +26 -0
  203. package/mcp-server/dist/services/memory-writer.d.ts.map +1 -0
  204. package/mcp-server/dist/services/memory-writer.js +126 -0
  205. package/mcp-server/dist/services/memory-writer.js.map +1 -0
  206. package/mcp-server/dist/services/neural-interface.d.ts +439 -0
  207. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -0
  208. package/mcp-server/dist/services/neural-interface.js +1135 -0
  209. package/mcp-server/dist/services/neural-interface.js.map +1 -0
  210. package/mcp-server/dist/services/profiles.d.ts +120 -0
  211. package/mcp-server/dist/services/profiles.d.ts.map +1 -0
  212. package/mcp-server/dist/services/profiles.js +387 -0
  213. package/mcp-server/dist/services/profiles.js.map +1 -0
  214. package/mcp-server/dist/services/secret-gate.d.ts +29 -0
  215. package/mcp-server/dist/services/secret-gate.d.ts.map +1 -0
  216. package/mcp-server/dist/services/secret-gate.js +43 -0
  217. package/mcp-server/dist/services/secret-gate.js.map +1 -0
  218. package/mcp-server/dist/services/server-instructions.d.ts +10 -0
  219. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -0
  220. package/mcp-server/dist/services/server-instructions.js +101 -0
  221. package/mcp-server/dist/services/server-instructions.js.map +1 -0
  222. package/mcp-server/dist/services/sqlite.d.ts +235 -0
  223. package/mcp-server/dist/services/sqlite.d.ts.map +1 -0
  224. package/mcp-server/dist/services/sqlite.js +1185 -0
  225. package/mcp-server/dist/services/sqlite.js.map +1 -0
  226. package/mcp-server/dist/services/typesafe-bench.d.ts +99 -0
  227. package/mcp-server/dist/services/typesafe-bench.d.ts.map +1 -0
  228. package/mcp-server/dist/services/typesafe-bench.js +218 -0
  229. package/mcp-server/dist/services/typesafe-bench.js.map +1 -0
  230. package/mcp-server/dist/services/typesafe-config.d.ts +342 -0
  231. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -0
  232. package/mcp-server/dist/services/typesafe-config.js +746 -0
  233. package/mcp-server/dist/services/typesafe-config.js.map +1 -0
  234. package/mcp-server/dist/services/typesafe.d.ts +213 -0
  235. package/mcp-server/dist/services/typesafe.d.ts.map +1 -0
  236. package/mcp-server/dist/services/typesafe.js +330 -0
  237. package/mcp-server/dist/services/typesafe.js.map +1 -0
  238. package/mcp-server/dist/services/vector-cache.d.ts +68 -0
  239. package/mcp-server/dist/services/vector-cache.d.ts.map +1 -0
  240. package/mcp-server/dist/services/vector-cache.js +271 -0
  241. package/mcp-server/dist/services/vector-cache.js.map +1 -0
  242. package/mcp-server/dist/services/whiteboard-geometry.d.ts +305 -0
  243. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -0
  244. package/mcp-server/dist/services/whiteboard-geometry.js +666 -0
  245. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -0
  246. package/mcp-server/dist/tools/agents.d.ts +212 -0
  247. package/mcp-server/dist/tools/agents.d.ts.map +1 -0
  248. package/mcp-server/dist/tools/agents.js +407 -0
  249. package/mcp-server/dist/tools/agents.js.map +1 -0
  250. package/mcp-server/dist/tools/bluesky.d.ts +39 -0
  251. package/mcp-server/dist/tools/bluesky.d.ts.map +1 -0
  252. package/mcp-server/dist/tools/bluesky.js +1144 -0
  253. package/mcp-server/dist/tools/bluesky.js.map +1 -0
  254. package/mcp-server/dist/tools/browser-advanced.d.ts +58 -0
  255. package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -0
  256. package/mcp-server/dist/tools/browser-advanced.js +106 -0
  257. package/mcp-server/dist/tools/browser-advanced.js.map +1 -0
  258. package/mcp-server/dist/tools/browser-batch.d.ts +99 -0
  259. package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -0
  260. package/mcp-server/dist/tools/browser-batch.js +187 -0
  261. package/mcp-server/dist/tools/browser-batch.js.map +1 -0
  262. package/mcp-server/dist/tools/browser-cheatsheet.d.ts +21 -0
  263. package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -0
  264. package/mcp-server/dist/tools/browser-cheatsheet.js +144 -0
  265. package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -0
  266. package/mcp-server/dist/tools/browser-interact.d.ts +239 -0
  267. package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -0
  268. package/mcp-server/dist/tools/browser-interact.js +300 -0
  269. package/mcp-server/dist/tools/browser-interact.js.map +1 -0
  270. package/mcp-server/dist/tools/browser-navigate.d.ts +90 -0
  271. package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -0
  272. package/mcp-server/dist/tools/browser-navigate.js +142 -0
  273. package/mcp-server/dist/tools/browser-navigate.js.map +1 -0
  274. package/mcp-server/dist/tools/browser-observe.d.ts +561 -0
  275. package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -0
  276. package/mcp-server/dist/tools/browser-observe.js +2009 -0
  277. package/mcp-server/dist/tools/browser-observe.js.map +1 -0
  278. package/mcp-server/dist/tools/browser.d.ts +34 -0
  279. package/mcp-server/dist/tools/browser.d.ts.map +1 -0
  280. package/mcp-server/dist/tools/browser.js +112 -0
  281. package/mcp-server/dist/tools/browser.js.map +1 -0
  282. package/mcp-server/dist/tools/card-tools.d.ts +82 -0
  283. package/mcp-server/dist/tools/card-tools.d.ts.map +1 -0
  284. package/mcp-server/dist/tools/card-tools.js +137 -0
  285. package/mcp-server/dist/tools/card-tools.js.map +1 -0
  286. package/mcp-server/dist/tools/card.d.ts +8 -0
  287. package/mcp-server/dist/tools/card.d.ts.map +1 -0
  288. package/mcp-server/dist/tools/card.js +16 -0
  289. package/mcp-server/dist/tools/card.js.map +1 -0
  290. package/mcp-server/dist/tools/category.d.ts +32 -0
  291. package/mcp-server/dist/tools/category.d.ts.map +1 -0
  292. package/mcp-server/dist/tools/category.js +290 -0
  293. package/mcp-server/dist/tools/category.js.map +1 -0
  294. package/mcp-server/dist/tools/choice.d.ts +160 -0
  295. package/mcp-server/dist/tools/choice.d.ts.map +1 -0
  296. package/mcp-server/dist/tools/choice.js +80 -0
  297. package/mcp-server/dist/tools/choice.js.map +1 -0
  298. package/mcp-server/dist/tools/computer.d.ts +71 -0
  299. package/mcp-server/dist/tools/computer.d.ts.map +1 -0
  300. package/mcp-server/dist/tools/computer.js +174 -0
  301. package/mcp-server/dist/tools/computer.js.map +1 -0
  302. package/mcp-server/dist/tools/discord-channel.d.ts +44 -0
  303. package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -0
  304. package/mcp-server/dist/tools/discord-channel.js +236 -0
  305. package/mcp-server/dist/tools/discord-channel.js.map +1 -0
  306. package/mcp-server/dist/tools/discord-guild.d.ts +20 -0
  307. package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -0
  308. package/mcp-server/dist/tools/discord-guild.js +138 -0
  309. package/mcp-server/dist/tools/discord-guild.js.map +1 -0
  310. package/mcp-server/dist/tools/discord-member.d.ts +26 -0
  311. package/mcp-server/dist/tools/discord-member.d.ts.map +1 -0
  312. package/mcp-server/dist/tools/discord-member.js +122 -0
  313. package/mcp-server/dist/tools/discord-member.js.map +1 -0
  314. package/mcp-server/dist/tools/discord-message.d.ts +36 -0
  315. package/mcp-server/dist/tools/discord-message.d.ts.map +1 -0
  316. package/mcp-server/dist/tools/discord-message.js +184 -0
  317. package/mcp-server/dist/tools/discord-message.js.map +1 -0
  318. package/mcp-server/dist/tools/discord-onboarding.d.ts +32 -0
  319. package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -0
  320. package/mcp-server/dist/tools/discord-onboarding.js +179 -0
  321. package/mcp-server/dist/tools/discord-onboarding.js.map +1 -0
  322. package/mcp-server/dist/tools/discord-role.d.ts +34 -0
  323. package/mcp-server/dist/tools/discord-role.d.ts.map +1 -0
  324. package/mcp-server/dist/tools/discord-role.js +178 -0
  325. package/mcp-server/dist/tools/discord-role.js.map +1 -0
  326. package/mcp-server/dist/tools/discord-thread.d.ts +28 -0
  327. package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -0
  328. package/mcp-server/dist/tools/discord-thread.js +88 -0
  329. package/mcp-server/dist/tools/discord-thread.js.map +1 -0
  330. package/mcp-server/dist/tools/discord-webhook.d.ts +32 -0
  331. package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -0
  332. package/mcp-server/dist/tools/discord-webhook.js +154 -0
  333. package/mcp-server/dist/tools/discord-webhook.js.map +1 -0
  334. package/mcp-server/dist/tools/discord.d.ts +7 -0
  335. package/mcp-server/dist/tools/discord.d.ts.map +1 -0
  336. package/mcp-server/dist/tools/discord.js +25 -0
  337. package/mcp-server/dist/tools/discord.js.map +1 -0
  338. package/mcp-server/dist/tools/fb-groups.d.ts +98 -0
  339. package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -0
  340. package/mcp-server/dist/tools/fb-groups.js +369 -0
  341. package/mcp-server/dist/tools/fb-groups.js.map +1 -0
  342. package/mcp-server/dist/tools/forget.d.ts +14 -0
  343. package/mcp-server/dist/tools/forget.d.ts.map +1 -0
  344. package/mcp-server/dist/tools/forget.js +26 -0
  345. package/mcp-server/dist/tools/forget.js.map +1 -0
  346. package/mcp-server/dist/tools/git-tools.d.ts +24 -0
  347. package/mcp-server/dist/tools/git-tools.d.ts.map +1 -0
  348. package/mcp-server/dist/tools/git-tools.js +107 -0
  349. package/mcp-server/dist/tools/git-tools.js.map +1 -0
  350. package/mcp-server/dist/tools/git.d.ts +7 -0
  351. package/mcp-server/dist/tools/git.d.ts.map +1 -0
  352. package/mcp-server/dist/tools/git.js +11 -0
  353. package/mcp-server/dist/tools/git.js.map +1 -0
  354. package/mcp-server/dist/tools/gsc/experience.d.ts +135 -0
  355. package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -0
  356. package/mcp-server/dist/tools/gsc/experience.js +351 -0
  357. package/mcp-server/dist/tools/gsc/experience.js.map +1 -0
  358. package/mcp-server/dist/tools/gsc/helpers.d.ts +78 -0
  359. package/mcp-server/dist/tools/gsc/helpers.d.ts.map +1 -0
  360. package/mcp-server/dist/tools/gsc/helpers.js +258 -0
  361. package/mcp-server/dist/tools/gsc/helpers.js.map +1 -0
  362. package/mcp-server/dist/tools/gsc/indexing.d.ts +121 -0
  363. package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -0
  364. package/mcp-server/dist/tools/gsc/indexing.js +357 -0
  365. package/mcp-server/dist/tools/gsc/indexing.js.map +1 -0
  366. package/mcp-server/dist/tools/gsc/inspect.d.ts +78 -0
  367. package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -0
  368. package/mcp-server/dist/tools/gsc/inspect.js +321 -0
  369. package/mcp-server/dist/tools/gsc/inspect.js.map +1 -0
  370. package/mcp-server/dist/tools/gsc/navigate.d.ts +44 -0
  371. package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -0
  372. package/mcp-server/dist/tools/gsc/navigate.js +197 -0
  373. package/mcp-server/dist/tools/gsc/navigate.js.map +1 -0
  374. package/mcp-server/dist/tools/gsc/performance.d.ts +84 -0
  375. package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -0
  376. package/mcp-server/dist/tools/gsc/performance.js +274 -0
  377. package/mcp-server/dist/tools/gsc/performance.js.map +1 -0
  378. package/mcp-server/dist/tools/gsc/settings.d.ts +153 -0
  379. package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -0
  380. package/mcp-server/dist/tools/gsc/settings.js +425 -0
  381. package/mcp-server/dist/tools/gsc/settings.js.map +1 -0
  382. package/mcp-server/dist/tools/gsc.d.ts +7 -0
  383. package/mcp-server/dist/tools/gsc.d.ts.map +1 -0
  384. package/mcp-server/dist/tools/gsc.js +51 -0
  385. package/mcp-server/dist/tools/gsc.js.map +1 -0
  386. package/mcp-server/dist/tools/image-tools.d.ts +24 -0
  387. package/mcp-server/dist/tools/image-tools.d.ts.map +1 -0
  388. package/mcp-server/dist/tools/image-tools.js +80 -0
  389. package/mcp-server/dist/tools/image-tools.js.map +1 -0
  390. package/mcp-server/dist/tools/image.d.ts +10 -0
  391. package/mcp-server/dist/tools/image.d.ts.map +1 -0
  392. package/mcp-server/dist/tools/image.js +14 -0
  393. package/mcp-server/dist/tools/image.js.map +1 -0
  394. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +97 -0
  395. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -0
  396. package/mcp-server/dist/tools/leonardo-browser-tools.js +228 -0
  397. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -0
  398. package/mcp-server/dist/tools/leonardo.d.ts +13 -0
  399. package/mcp-server/dist/tools/leonardo.d.ts.map +1 -0
  400. package/mcp-server/dist/tools/leonardo.js +21 -0
  401. package/mcp-server/dist/tools/leonardo.js.map +1 -0
  402. package/mcp-server/dist/tools/loop.d.ts +30 -0
  403. package/mcp-server/dist/tools/loop.d.ts.map +1 -0
  404. package/mcp-server/dist/tools/loop.js +401 -0
  405. package/mcp-server/dist/tools/loop.js.map +1 -0
  406. package/mcp-server/dist/tools/memories.d.ts +56 -0
  407. package/mcp-server/dist/tools/memories.d.ts.map +1 -0
  408. package/mcp-server/dist/tools/memories.js +171 -0
  409. package/mcp-server/dist/tools/memories.js.map +1 -0
  410. package/mcp-server/dist/tools/morelogin.d.ts +24 -0
  411. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -0
  412. package/mcp-server/dist/tools/morelogin.js +79 -0
  413. package/mcp-server/dist/tools/morelogin.js.map +1 -0
  414. package/mcp-server/dist/tools/profile.d.ts +17 -0
  415. package/mcp-server/dist/tools/profile.d.ts.map +1 -0
  416. package/mcp-server/dist/tools/profile.js +114 -0
  417. package/mcp-server/dist/tools/profile.js.map +1 -0
  418. package/mcp-server/dist/tools/recall.d.ts +71 -0
  419. package/mcp-server/dist/tools/recall.d.ts.map +1 -0
  420. package/mcp-server/dist/tools/recall.js +147 -0
  421. package/mcp-server/dist/tools/recall.js.map +1 -0
  422. package/mcp-server/dist/tools/reflect.d.ts +56 -0
  423. package/mcp-server/dist/tools/reflect.d.ts.map +1 -0
  424. package/mcp-server/dist/tools/reflect.js +157 -0
  425. package/mcp-server/dist/tools/reflect.js.map +1 -0
  426. package/mcp-server/dist/tools/remember.d.ts +62 -0
  427. package/mcp-server/dist/tools/remember.d.ts.map +1 -0
  428. package/mcp-server/dist/tools/remember.js +201 -0
  429. package/mcp-server/dist/tools/remember.js.map +1 -0
  430. package/mcp-server/dist/tools/response.d.ts +23 -0
  431. package/mcp-server/dist/tools/response.d.ts.map +1 -0
  432. package/mcp-server/dist/tools/response.js +24 -0
  433. package/mcp-server/dist/tools/response.js.map +1 -0
  434. package/mcp-server/dist/tools/restore.d.ts +14 -0
  435. package/mcp-server/dist/tools/restore.d.ts.map +1 -0
  436. package/mcp-server/dist/tools/restore.js +23 -0
  437. package/mcp-server/dist/tools/restore.js.map +1 -0
  438. package/mcp-server/dist/tools/style-guide-tools.d.ts +51 -0
  439. package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -0
  440. package/mcp-server/dist/tools/style-guide-tools.js +231 -0
  441. package/mcp-server/dist/tools/style-guide-tools.js.map +1 -0
  442. package/mcp-server/dist/tools/style-guide.d.ts +8 -0
  443. package/mcp-server/dist/tools/style-guide.d.ts.map +1 -0
  444. package/mcp-server/dist/tools/style-guide.js +12 -0
  445. package/mcp-server/dist/tools/style-guide.js.map +1 -0
  446. package/mcp-server/dist/tools/sync.d.ts +20 -0
  447. package/mcp-server/dist/tools/sync.d.ts.map +1 -0
  448. package/mcp-server/dist/tools/sync.js +156 -0
  449. package/mcp-server/dist/tools/sync.js.map +1 -0
  450. package/mcp-server/dist/tools/tictactoe-tools.d.ts +18 -0
  451. package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -0
  452. package/mcp-server/dist/tools/tictactoe-tools.js +78 -0
  453. package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -0
  454. package/mcp-server/dist/tools/tictactoe.d.ts +7 -0
  455. package/mcp-server/dist/tools/tictactoe.d.ts.map +1 -0
  456. package/mcp-server/dist/tools/tictactoe.js +11 -0
  457. package/mcp-server/dist/tools/tictactoe.js.map +1 -0
  458. package/mcp-server/dist/tools/utils.d.ts +19 -0
  459. package/mcp-server/dist/tools/utils.d.ts.map +1 -0
  460. package/mcp-server/dist/tools/utils.js +54 -0
  461. package/mcp-server/dist/tools/utils.js.map +1 -0
  462. package/mcp-server/dist/tools/whiteboard-format.d.ts +88 -0
  463. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -0
  464. package/mcp-server/dist/tools/whiteboard-format.js +337 -0
  465. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -0
  466. package/mcp-server/dist/tools/whiteboard-tools.d.ts +326 -0
  467. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -0
  468. package/mcp-server/dist/tools/whiteboard-tools.js +222 -0
  469. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -0
  470. package/mcp-server/dist/tools/whiteboard.d.ts +8 -0
  471. package/mcp-server/dist/tools/whiteboard.d.ts.map +1 -0
  472. package/mcp-server/dist/tools/whiteboard.js +16 -0
  473. package/mcp-server/dist/tools/whiteboard.js.map +1 -0
  474. package/mcp-server/dist/tools/youtube/analytics.d.ts +46 -0
  475. package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -0
  476. package/mcp-server/dist/tools/youtube/analytics.js +83 -0
  477. package/mcp-server/dist/tools/youtube/analytics.js.map +1 -0
  478. package/mcp-server/dist/tools/youtube/dedup.d.ts +35 -0
  479. package/mcp-server/dist/tools/youtube/dedup.d.ts.map +1 -0
  480. package/mcp-server/dist/tools/youtube/dedup.js +56 -0
  481. package/mcp-server/dist/tools/youtube/dedup.js.map +1 -0
  482. package/mcp-server/dist/tools/youtube/download.d.ts +31 -0
  483. package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -0
  484. package/mcp-server/dist/tools/youtube/download.js +30 -0
  485. package/mcp-server/dist/tools/youtube/download.js.map +1 -0
  486. package/mcp-server/dist/tools/youtube/helpers.d.ts +66 -0
  487. package/mcp-server/dist/tools/youtube/helpers.d.ts.map +1 -0
  488. package/mcp-server/dist/tools/youtube/helpers.js +143 -0
  489. package/mcp-server/dist/tools/youtube/helpers.js.map +1 -0
  490. package/mcp-server/dist/tools/youtube/media.d.ts +43 -0
  491. package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -0
  492. package/mcp-server/dist/tools/youtube/media.js +97 -0
  493. package/mcp-server/dist/tools/youtube/media.js.map +1 -0
  494. package/mcp-server/dist/tools/youtube/metadata.d.ts +33 -0
  495. package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -0
  496. package/mcp-server/dist/tools/youtube/metadata.js +106 -0
  497. package/mcp-server/dist/tools/youtube/metadata.js.map +1 -0
  498. package/mcp-server/dist/tools/youtube/navigate.d.ts +30 -0
  499. package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -0
  500. package/mcp-server/dist/tools/youtube/navigate.js +71 -0
  501. package/mcp-server/dist/tools/youtube/navigate.js.map +1 -0
  502. package/mcp-server/dist/tools/youtube/playlist.d.ts +29 -0
  503. package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -0
  504. package/mcp-server/dist/tools/youtube/playlist.js +128 -0
  505. package/mcp-server/dist/tools/youtube/playlist.js.map +1 -0
  506. package/mcp-server/dist/tools/youtube/schedule.d.ts +31 -0
  507. package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -0
  508. package/mcp-server/dist/tools/youtube/schedule.js +147 -0
  509. package/mcp-server/dist/tools/youtube/schedule.js.map +1 -0
  510. package/mcp-server/dist/tools/youtube/source.d.ts +36 -0
  511. package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -0
  512. package/mcp-server/dist/tools/youtube/source.js +85 -0
  513. package/mcp-server/dist/tools/youtube/source.js.map +1 -0
  514. package/mcp-server/dist/tools/youtube/upload.d.ts +53 -0
  515. package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -0
  516. package/mcp-server/dist/tools/youtube/upload.js +255 -0
  517. package/mcp-server/dist/tools/youtube/upload.js.map +1 -0
  518. package/mcp-server/dist/tools/youtube.d.ts +12 -0
  519. package/mcp-server/dist/tools/youtube.d.ts.map +1 -0
  520. package/mcp-server/dist/tools/youtube.js +38 -0
  521. package/mcp-server/dist/tools/youtube.js.map +1 -0
  522. package/mcp-server/dist/tui.d.ts +3 -0
  523. package/mcp-server/dist/tui.d.ts.map +1 -0
  524. package/mcp-server/dist/tui.js +806 -0
  525. package/mcp-server/dist/tui.js.map +1 -0
  526. package/mcp-server/dist/types.d.ts +77 -0
  527. package/mcp-server/dist/types.d.ts.map +1 -0
  528. package/mcp-server/dist/types.js +2 -0
  529. package/mcp-server/dist/types.js.map +1 -0
  530. package/mcp-server/package-lock.json +4798 -0
  531. package/mcp-server/package.json +55 -38
  532. package/mcp-server/run.mjs +12 -2
  533. package/mcp-server/src/config.ts +48 -3
  534. package/mcp-server/src/http.ts +296 -93
  535. package/mcp-server/src/index.ts +546 -203
  536. package/mcp-server/src/preload-http.ts +19 -18
  537. package/mcp-server/src/preload.ts +19 -18
  538. package/mcp-server/src/scripts/setup-embeddings.ts +9 -0
  539. package/mcp-server/src/services/assistant-judgments.ts +157 -0
  540. package/mcp-server/src/services/browser-assist-gate.ts +383 -0
  541. package/mcp-server/src/services/browser-assist.ts +267 -0
  542. package/mcp-server/src/services/browser-bench.ts +477 -0
  543. package/mcp-server/src/services/browser-judgments.ts +414 -0
  544. package/mcp-server/src/services/browser-risk.ts +484 -0
  545. package/mcp-server/src/services/categories.ts +36 -19
  546. package/mcp-server/src/services/codex-config-heal.ts +403 -0
  547. package/mcp-server/src/services/desktop-assist-gate.ts +251 -0
  548. package/mcp-server/src/services/desktop-assist.ts +308 -0
  549. package/mcp-server/src/services/desktop-bench.ts +372 -0
  550. package/mcp-server/src/services/desktop-client.ts +76 -0
  551. package/mcp-server/src/services/desktop-judgments.ts +218 -0
  552. package/mcp-server/src/services/desktop-risk.ts +743 -0
  553. package/mcp-server/src/services/edit-stale.ts +299 -0
  554. package/mcp-server/src/services/embedding-service.ts +108 -0
  555. package/mcp-server/src/services/embedding-worker.ts +46 -0
  556. package/mcp-server/src/services/fb-regions.ts +221 -0
  557. package/mcp-server/src/services/file-checksums.ts +26 -9
  558. package/mcp-server/src/services/file-excerpt.ts +59 -0
  559. package/mcp-server/src/services/identity.ts +291 -0
  560. package/mcp-server/src/services/local-embeddings.ts +2 -77
  561. package/mcp-server/src/services/memory-client.ts +23 -0
  562. package/mcp-server/src/services/memory-judge-backfill.ts +462 -0
  563. package/mcp-server/src/services/memory-judgments.ts +901 -0
  564. package/mcp-server/src/services/memory-maintenance.ts +360 -0
  565. package/mcp-server/src/services/memory-retrieval.ts +349 -0
  566. package/mcp-server/src/services/memory-schema.ts +280 -0
  567. package/mcp-server/src/services/memory-sessions.ts +87 -0
  568. package/mcp-server/src/services/memory-triage.ts +182 -0
  569. package/mcp-server/src/services/memory-verification.ts +68 -0
  570. package/mcp-server/src/services/memory-writer.ts +125 -0
  571. package/mcp-server/src/services/neural-interface.ts +1217 -73
  572. package/mcp-server/src/services/profiles.ts +428 -0
  573. package/mcp-server/src/services/secret-gate.ts +52 -0
  574. package/mcp-server/src/services/server-instructions.ts +122 -0
  575. package/mcp-server/src/services/sqlite.ts +1456 -823
  576. package/mcp-server/src/services/typesafe-bench.ts +247 -0
  577. package/mcp-server/src/services/typesafe-config.ts +790 -0
  578. package/mcp-server/src/services/typesafe.ts +390 -0
  579. package/mcp-server/src/services/vector-cache.ts +255 -0
  580. package/mcp-server/src/services/whiteboard-geometry.ts +711 -0
  581. package/mcp-server/src/tools/agents.ts +539 -0
  582. package/mcp-server/src/tools/bluesky.ts +1186 -0
  583. package/mcp-server/src/tools/browser-advanced.ts +15 -6
  584. package/mcp-server/src/tools/browser-batch.ts +178 -0
  585. package/mcp-server/src/tools/browser-cheatsheet.ts +155 -0
  586. package/mcp-server/src/tools/browser-interact.ts +362 -255
  587. package/mcp-server/src/tools/browser-navigate.ts +164 -77
  588. package/mcp-server/src/tools/browser-observe.ts +2222 -1330
  589. package/mcp-server/src/tools/browser.ts +181 -107
  590. package/mcp-server/src/tools/card.ts +7 -5
  591. package/mcp-server/src/tools/choice.ts +103 -0
  592. package/mcp-server/src/tools/computer.ts +190 -0
  593. package/mcp-server/src/tools/discord.ts +10 -23
  594. package/mcp-server/src/tools/fb-groups.ts +387 -0
  595. package/mcp-server/src/tools/forget.ts +1 -1
  596. package/mcp-server/src/tools/git.ts +3 -1
  597. package/mcp-server/src/tools/gsc/experience.ts +440 -0
  598. package/mcp-server/src/tools/gsc/helpers.ts +288 -0
  599. package/mcp-server/src/tools/gsc/indexing.ts +495 -0
  600. package/mcp-server/src/tools/gsc/inspect.ts +391 -0
  601. package/mcp-server/src/tools/gsc/navigate.ts +236 -0
  602. package/mcp-server/src/tools/gsc/performance.ts +352 -0
  603. package/mcp-server/src/tools/gsc/settings.ts +564 -0
  604. package/mcp-server/src/tools/gsc.ts +95 -0
  605. package/mcp-server/src/tools/image.ts +3 -1
  606. package/mcp-server/src/tools/leonardo-browser-tools.ts +47 -37
  607. package/mcp-server/src/tools/leonardo.ts +7 -5
  608. package/mcp-server/src/tools/loop.ts +118 -25
  609. package/mcp-server/src/tools/memories.ts +65 -5
  610. package/mcp-server/src/tools/morelogin.ts +81 -0
  611. package/mcp-server/src/tools/profile.ts +122 -0
  612. package/mcp-server/src/tools/recall.ts +105 -261
  613. package/mcp-server/src/tools/reflect.ts +171 -145
  614. package/mcp-server/src/tools/remember.ts +223 -115
  615. package/mcp-server/src/tools/style-guide-tools.ts +250 -0
  616. package/mcp-server/src/tools/style-guide.ts +16 -0
  617. package/mcp-server/src/tools/sync.ts +66 -9
  618. package/mcp-server/src/tools/tictactoe.ts +3 -1
  619. package/mcp-server/src/tools/utils.ts +22 -0
  620. package/mcp-server/src/tools/whiteboard-format.ts +394 -0
  621. package/mcp-server/src/tools/whiteboard-tools.ts +191 -183
  622. package/mcp-server/src/tools/whiteboard.ts +7 -5
  623. package/mcp-server/src/tools/youtube/analytics.ts +106 -0
  624. package/mcp-server/src/tools/youtube/dedup.ts +57 -0
  625. package/mcp-server/src/tools/youtube/download.ts +41 -0
  626. package/mcp-server/src/tools/youtube/helpers.ts +183 -0
  627. package/mcp-server/src/tools/youtube/media.ts +109 -0
  628. package/mcp-server/src/tools/youtube/metadata.ts +112 -0
  629. package/mcp-server/src/tools/youtube/navigate.ts +81 -0
  630. package/mcp-server/src/tools/youtube/playlist.ts +134 -0
  631. package/mcp-server/src/tools/youtube/schedule.ts +158 -0
  632. package/mcp-server/src/tools/youtube/source.ts +101 -0
  633. package/mcp-server/src/tools/youtube/upload.ts +296 -0
  634. package/mcp-server/src/tools/youtube.ts +47 -0
  635. package/mcp-server/src/tui.ts +8 -9
  636. package/neural-interface/games/TicTacToe/1.svg +1 -0
  637. package/neural-interface/games/TicTacToe/2.svg +1 -0
  638. package/neural-interface/games/TicTacToe/3.svg +1 -0
  639. package/neural-interface/games/TicTacToe/4.svg +1 -0
  640. package/neural-interface/games/TicTacToe/5.svg +1 -0
  641. package/neural-interface/games/TicTacToe/6.svg +1 -0
  642. package/neural-interface/games/TicTacToe/7.svg +1 -0
  643. package/neural-interface/games/TicTacToe/8.svg +1 -0
  644. package/neural-interface/games/TicTacToe/9.svg +1 -0
  645. package/neural-interface/games/TicTacToe/Board.svg +1 -0
  646. package/neural-interface/games/TicTacToe/Circle.svg +1 -0
  647. package/neural-interface/games/TicTacToe/Cross.svg +1 -0
  648. package/neural-interface/i18n/en.json +7022 -0
  649. package/neural-interface/i18n/pt-BR.json +7026 -0
  650. package/neural-interface/lib/assistant-api.js +1005 -0
  651. package/neural-interface/lib/assistant-attachments.js +121 -0
  652. package/neural-interface/lib/assistant-brains/claude.js +207 -0
  653. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +43 -0
  654. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +56 -0
  655. package/neural-interface/lib/assistant-brains/codex.js +213 -0
  656. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +47 -0
  657. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +62 -0
  658. package/neural-interface/lib/assistant-brains/opencode.js +320 -0
  659. package/neural-interface/lib/assistant-budget.js +318 -0
  660. package/neural-interface/lib/assistant-catalog.js +731 -0
  661. package/neural-interface/lib/assistant-clarify.js +664 -0
  662. package/neural-interface/lib/assistant-config.js +232 -0
  663. package/neural-interface/lib/assistant-dispatch.js +2744 -0
  664. package/neural-interface/lib/assistant-envelope.js +582 -0
  665. package/neural-interface/lib/assistant-evidence.js +236 -0
  666. package/neural-interface/lib/assistant-hidden-models.js +272 -0
  667. package/neural-interface/lib/assistant-jev.js +117 -0
  668. package/neural-interface/lib/assistant-judgments.js +111 -0
  669. package/neural-interface/lib/assistant-media.js +335 -0
  670. package/neural-interface/lib/assistant-memory.js +398 -0
  671. package/neural-interface/lib/assistant-persona.js +444 -0
  672. package/neural-interface/lib/assistant-plan-permissions.js +448 -0
  673. package/neural-interface/lib/assistant-playbooks/design.md +87 -0
  674. package/neural-interface/lib/assistant-playbooks.js +72 -0
  675. package/neural-interface/lib/assistant-pricing.js +159 -0
  676. package/neural-interface/lib/assistant-route-gate-codex.js +163 -0
  677. package/neural-interface/lib/assistant-route-gate.js +212 -0
  678. package/neural-interface/lib/assistant-router.js +1324 -0
  679. package/neural-interface/lib/assistant-runtime.js +3337 -0
  680. package/neural-interface/lib/assistant-task-prompt.js +472 -0
  681. package/neural-interface/lib/assistant-usage.js +1688 -0
  682. package/neural-interface/lib/augmented-path.js +70 -0
  683. package/neural-interface/lib/automation-storage-migration.js +54 -0
  684. package/neural-interface/lib/backup-service.js +851 -0
  685. package/neural-interface/lib/backup-zip-reader.js +262 -0
  686. package/neural-interface/lib/browser-assist-api.js +41 -0
  687. package/neural-interface/lib/browser-console.js +176 -0
  688. package/neural-interface/lib/browser-execution.js +241 -0
  689. package/neural-interface/lib/browser-extraction.js +191 -0
  690. package/neural-interface/lib/browser-language.js +83 -0
  691. package/neural-interface/lib/browser-screenshot.js +399 -0
  692. package/neural-interface/lib/browser-semantic-context.js +639 -0
  693. package/neural-interface/lib/browser-snapshots.js +192 -0
  694. package/neural-interface/lib/browser-tab-recovery.js +119 -0
  695. package/neural-interface/lib/browser-targets.js +70 -0
  696. package/neural-interface/lib/browser-tool-policy.js +926 -0
  697. package/neural-interface/lib/claude-accounts.js +230 -0
  698. package/neural-interface/lib/claude-agent-bridge.js +3203 -0
  699. package/neural-interface/lib/claude-bypass-policy.js +99 -0
  700. package/neural-interface/lib/claude-executable.js +241 -0
  701. package/neural-interface/lib/claude-history.js +429 -0
  702. package/neural-interface/lib/claude-model-catalog.js +444 -0
  703. package/neural-interface/lib/claude-panel-requests.js +165 -0
  704. package/neural-interface/lib/claude-panel-session.js +272 -0
  705. package/neural-interface/lib/claude-permission-rules.js +153 -0
  706. package/neural-interface/lib/claude-session-cleanup.js +71 -0
  707. package/neural-interface/lib/claude-session-list.js +82 -0
  708. package/neural-interface/lib/claude-session-ops.js +140 -0
  709. package/neural-interface/lib/claude-settings-view.js +51 -0
  710. package/neural-interface/lib/claude-skin-connect.js +79 -0
  711. package/neural-interface/lib/claude-stall-policy.js +7 -0
  712. package/neural-interface/lib/claude-temporary.js +435 -0
  713. package/neural-interface/lib/cli-update-planner.js +312 -0
  714. package/neural-interface/lib/codex-capabilities.d.ts +41 -0
  715. package/neural-interface/lib/codex-capabilities.js +148 -0
  716. package/neural-interface/lib/codex-collaboration-mode.js +17 -0
  717. package/neural-interface/lib/codex-compat-rpc.js +241 -0
  718. package/neural-interface/lib/codex-mcp-approvals.js +56 -0
  719. package/neural-interface/lib/codex-mcp-apps.js +47 -0
  720. package/neural-interface/lib/codex-model-context.js +202 -0
  721. package/neural-interface/lib/codex-plan-store.js +71 -0
  722. package/neural-interface/lib/codex-request-journal.js +242 -0
  723. package/neural-interface/lib/codex-runtime-path.js +213 -0
  724. package/neural-interface/lib/codex-session-catalog.js +231 -0
  725. package/neural-interface/lib/codex-session-settings.js +46 -0
  726. package/neural-interface/lib/codex-sidepanel-permissions.js +110 -0
  727. package/neural-interface/lib/codex-thread-history.js +165 -0
  728. package/neural-interface/lib/codex-user-verification.js +34 -0
  729. package/neural-interface/lib/codex-writer-lifecycle.js +152 -0
  730. package/neural-interface/lib/confined-fs.js +256 -0
  731. package/neural-interface/lib/db.js +922 -0
  732. package/neural-interface/lib/design-md.js +9 -0
  733. package/neural-interface/lib/desktop/api.js +92 -0
  734. package/neural-interface/lib/desktop/audit.js +62 -0
  735. package/neural-interface/lib/desktop/build.js +423 -0
  736. package/neural-interface/lib/desktop/config.js +606 -0
  737. package/neural-interface/lib/desktop/coords.js +76 -0
  738. package/neural-interface/lib/desktop/fake-helper.js +1192 -0
  739. package/neural-interface/lib/desktop/frames.js +77 -0
  740. package/neural-interface/lib/desktop/grants.js +84 -0
  741. package/neural-interface/lib/desktop/guards.js +170 -0
  742. package/neural-interface/lib/desktop/helper/SynabunDesktop.swift +3056 -0
  743. package/neural-interface/lib/desktop/lease.js +51 -0
  744. package/neural-interface/lib/desktop/manager.js +545 -0
  745. package/neural-interface/lib/desktop/press-contexts.js +103 -0
  746. package/neural-interface/lib/desktop/protocol.js +495 -0
  747. package/neural-interface/lib/desktop/service.js +1202 -0
  748. package/neural-interface/lib/effort-levels.js +148 -0
  749. package/neural-interface/lib/event-loop-monitor.js +67 -0
  750. package/neural-interface/lib/exec-loop-command.js +209 -0
  751. package/neural-interface/lib/folder-picker.ps1 +77 -0
  752. package/neural-interface/lib/http-guards.js +287 -0
  753. package/neural-interface/lib/jsonl-lines.js +94 -0
  754. package/neural-interface/lib/loop-logger.js +127 -0
  755. package/neural-interface/lib/mcp-client-config.js +133 -0
  756. package/neural-interface/lib/mcp-installer.js +487 -0
  757. package/neural-interface/lib/mcp-profile-refresh-coordinator.js +78 -0
  758. package/neural-interface/lib/mcp-profile-servers.js +120 -0
  759. package/neural-interface/lib/memo-cache.js +84 -0
  760. package/neural-interface/lib/memory-api.js +758 -0
  761. package/neural-interface/lib/memory-map-api.js +1150 -0
  762. package/neural-interface/lib/memory-map-layout.js +872 -0
  763. package/neural-interface/lib/memory-map-worker.js +165 -0
  764. package/neural-interface/lib/memory-session-capture.js +81 -0
  765. package/neural-interface/lib/memory-timers.js +62 -0
  766. package/neural-interface/lib/morelogin.js +301 -0
  767. package/neural-interface/lib/native-binary-runtime.js +382 -0
  768. package/neural-interface/lib/native-loop-goal.js +33 -0
  769. package/neural-interface/lib/native-loop-providers.js +1002 -0
  770. package/neural-interface/lib/native-loop-runtime.js +747 -0
  771. package/neural-interface/lib/offline-page.js +54 -0
  772. package/neural-interface/lib/opencode-hidden-models.js +113 -0
  773. package/neural-interface/lib/opencode-history.js +253 -0
  774. package/neural-interface/lib/opencode-runtime-config.js +58 -0
  775. package/neural-interface/lib/opencode-v2-client.js +486 -0
  776. package/neural-interface/lib/opencode-v2-ws-requests.js +955 -0
  777. package/neural-interface/lib/path-confine.js +213 -0
  778. package/neural-interface/lib/plugin-installer.js +264 -0
  779. package/neural-interface/lib/project-storage.js +766 -0
  780. package/neural-interface/lib/pty-host/core.js +603 -0
  781. package/neural-interface/lib/pty-host/flow.js +43 -0
  782. package/neural-interface/lib/pty-host/host.js +47 -0
  783. package/neural-interface/lib/pty-host/manager.js +360 -0
  784. package/neural-interface/lib/pty-host/protocol.js +81 -0
  785. package/neural-interface/lib/pty-host/snapshot.js +133 -0
  786. package/neural-interface/lib/remote-policy.js +582 -0
  787. package/neural-interface/lib/rulesets/api.js +175 -0
  788. package/neural-interface/lib/rulesets/fs-safe.js +245 -0
  789. package/neural-interface/lib/rulesets/installer.js +1453 -0
  790. package/neural-interface/lib/rulesets/json-edit.js +186 -0
  791. package/neural-interface/lib/rulesets/lock.js +170 -0
  792. package/neural-interface/lib/rulesets/managed-text.js +314 -0
  793. package/neural-interface/lib/rulesets/normalise.js +24 -0
  794. package/neural-interface/lib/rulesets/render.js +84 -0
  795. package/neural-interface/lib/schedule-launch-intent.js +40 -0
  796. package/neural-interface/lib/session-cache-builder.js +524 -0
  797. package/neural-interface/lib/session-chunker.js +344 -0
  798. package/neural-interface/lib/session-indexer.js +327 -0
  799. package/neural-interface/lib/session-title-generator.js +232 -0
  800. package/neural-interface/lib/skill-prompt-bridge.js +11 -0
  801. package/neural-interface/lib/style-guide/api.js +375 -0
  802. package/neural-interface/lib/style-guide/color.js +352 -0
  803. package/neural-interface/lib/style-guide/export-css.js +99 -0
  804. package/neural-interface/lib/style-guide/export-dtcg.js +209 -0
  805. package/neural-interface/lib/style-guide/export-tailwind.js +102 -0
  806. package/neural-interface/lib/style-guide/fonts.json +227 -0
  807. package/neural-interface/lib/style-guide/import.js +1268 -0
  808. package/neural-interface/lib/style-guide/pointers.js +103 -0
  809. package/neural-interface/lib/style-guide/presets.js +232 -0
  810. package/neural-interface/lib/style-guide/render-design-md.js +319 -0
  811. package/neural-interface/lib/style-guide/schema.js +848 -0
  812. package/neural-interface/lib/style-guide/security.js +43 -0
  813. package/neural-interface/lib/style-guide/store.js +491 -0
  814. package/neural-interface/lib/style-guide/summary.js +106 -0
  815. package/neural-interface/lib/style-guide/tokens.js +170 -0
  816. package/neural-interface/lib/synabun-update-plan.js +324 -0
  817. package/neural-interface/lib/synabun-version.js +179 -0
  818. package/neural-interface/lib/system-restore.js +99 -0
  819. package/neural-interface/lib/terminal-env.js +86 -0
  820. package/neural-interface/lib/ui-blob-store.js +106 -0
  821. package/neural-interface/lib/vector-cache.js +2 -0
  822. package/neural-interface/lib/virtual-socket.js +60 -0
  823. package/neural-interface/lib/whatsapp/api.js +146 -0
  824. package/neural-interface/lib/whatsapp/auth-store.js +389 -0
  825. package/neural-interface/lib/whatsapp/baileys-adapter.js +457 -0
  826. package/neural-interface/lib/whatsapp/brain.js +128 -0
  827. package/neural-interface/lib/whatsapp/bridge.js +1499 -0
  828. package/neural-interface/lib/whatsapp/cards.js +519 -0
  829. package/neural-interface/lib/whatsapp/commands.js +92 -0
  830. package/neural-interface/lib/whatsapp/config.js +291 -0
  831. package/neural-interface/lib/whatsapp/connector/entry.mjs +25 -0
  832. package/neural-interface/lib/whatsapp/connector/manifest.json +6 -0
  833. package/neural-interface/lib/whatsapp/connector/npm-shrinkwrap.json +717 -0
  834. package/neural-interface/lib/whatsapp/connector/package.json +8 -0
  835. package/neural-interface/lib/whatsapp/fake-baileys.js +444 -0
  836. package/neural-interface/lib/whatsapp/format.js +552 -0
  837. package/neural-interface/lib/whatsapp/host-core.js +1225 -0
  838. package/neural-interface/lib/whatsapp/host.js +119 -0
  839. package/neural-interface/lib/whatsapp/identity.js +288 -0
  840. package/neural-interface/lib/whatsapp/inbound.js +149 -0
  841. package/neural-interface/lib/whatsapp/installer.js +562 -0
  842. package/neural-interface/lib/whatsapp/manager.js +638 -0
  843. package/neural-interface/lib/whatsapp/paths.js +81 -0
  844. package/neural-interface/lib/whatsapp/protocol.js +327 -0
  845. package/neural-interface/lib/whatsapp/qr-svg.js +57 -0
  846. package/neural-interface/lib/whatsapp/redact.js +130 -0
  847. package/neural-interface/lib/whatsapp/service.js +1305 -0
  848. package/neural-interface/lib/whatsapp/vendor/qrcodegen.js +848 -0
  849. package/neural-interface/package-lock.json +4431 -0
  850. package/neural-interface/package.json +58 -27
  851. package/neural-interface/public/apple-touch-icon.png +0 -0
  852. package/neural-interface/public/category-logos/synabun.png +0 -0
  853. package/neural-interface/public/claude.svg +1 -0
  854. package/neural-interface/public/favicon-16x16.png +0 -0
  855. package/neural-interface/public/favicon-32x32.png +0 -0
  856. package/neural-interface/public/icon-192.png +0 -0
  857. package/neural-interface/public/icon-512.png +0 -0
  858. package/neural-interface/public/index.html +32 -182
  859. package/neural-interface/public/index2d.html +2 -2
  860. package/neural-interface/public/install-app.html +31 -0
  861. package/neural-interface/public/logo-synabun.png +0 -0
  862. package/neural-interface/public/logoHD.png +0 -0
  863. package/neural-interface/public/manifest.json +2 -0
  864. package/neural-interface/public/mcp.svg +4 -0
  865. package/neural-interface/public/offline.html +670 -299
  866. package/neural-interface/public/onboarding.html +804 -161
  867. package/neural-interface/public/opencode-logo-dark-square.svg +1 -0
  868. package/neural-interface/public/shared/agent-runtime-options.js +596 -0
  869. package/neural-interface/public/shared/api.js +339 -28
  870. package/neural-interface/public/shared/assistant/asst-accounts.js +318 -0
  871. package/neural-interface/public/shared/assistant/asst-agents-dock.js +296 -0
  872. package/neural-interface/public/shared/assistant/asst-api.js +270 -0
  873. package/neural-interface/public/shared/assistant/asst-brain-picker.js +744 -0
  874. package/neural-interface/public/shared/assistant/asst-budget.js +333 -0
  875. package/neural-interface/public/shared/assistant/asst-composer.js +656 -0
  876. package/neural-interface/public/shared/assistant/asst-computer.js +803 -0
  877. package/neural-interface/public/shared/assistant/asst-control.js +1018 -0
  878. package/neural-interface/public/shared/assistant/asst-hosts.js +262 -0
  879. package/neural-interface/public/shared/assistant/asst-mascot.js +313 -0
  880. package/neural-interface/public/shared/assistant/asst-menu.js +375 -0
  881. package/neural-interface/public/shared/assistant/asst-panel.js +1845 -0
  882. package/neural-interface/public/shared/assistant/asst-rack-styles.js +586 -0
  883. package/neural-interface/public/shared/assistant/asst-render.js +3305 -0
  884. package/neural-interface/public/shared/assistant/asst-route.js +1653 -0
  885. package/neural-interface/public/shared/assistant/asst-roving.js +75 -0
  886. package/neural-interface/public/shared/assistant/asst-sanitize.js +117 -0
  887. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +488 -0
  888. package/neural-interface/public/shared/assistant/asst-sidepanel.js +675 -0
  889. package/neural-interface/public/shared/assistant/asst-slash.js +258 -0
  890. package/neural-interface/public/shared/assistant/asst-state.js +727 -0
  891. package/neural-interface/public/shared/assistant/asst-styles.js +1686 -0
  892. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +1017 -0
  893. package/neural-interface/public/shared/assistant/asst-usage.js +444 -0
  894. package/neural-interface/public/shared/assistant/asst-ws.js +175 -0
  895. package/neural-interface/public/shared/automation-context.js +75 -0
  896. package/neural-interface/public/shared/blob-store.js +99 -0
  897. package/neural-interface/public/shared/cdx/cdx-capabilities.js +118 -0
  898. package/neural-interface/public/shared/cdx/cdx-cards.js +37 -0
  899. package/neural-interface/public/shared/cdx/cdx-commands.js +171 -0
  900. package/neural-interface/public/shared/cdx/cdx-context-menu.js +402 -0
  901. package/neural-interface/public/shared/cdx/cdx-context-model.js +220 -0
  902. package/neural-interface/public/shared/cdx/cdx-features.js +408 -0
  903. package/neural-interface/public/shared/cdx/cdx-icons.js +89 -0
  904. package/neural-interface/public/shared/cdx/cdx-mcp-app-host.js +414 -0
  905. package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.html +6 -0
  906. package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.js +56 -0
  907. package/neural-interface/public/shared/cdx/cdx-mcp-app.js +178 -0
  908. package/neural-interface/public/shared/cdx/cdx-model-catalog.js +120 -0
  909. package/neural-interface/public/shared/cdx/cdx-output-model.js +261 -0
  910. package/neural-interface/public/shared/cdx/cdx-output.js +382 -0
  911. package/neural-interface/public/shared/cdx/cdx-panel.js +1372 -0
  912. package/neural-interface/public/shared/cdx/cdx-plan.js +266 -0
  913. package/neural-interface/public/shared/cdx/cdx-protocol.js +682 -0
  914. package/neural-interface/public/shared/cdx/cdx-render.js +3381 -0
  915. package/neural-interface/public/shared/cdx/cdx-requests.js +1136 -0
  916. package/neural-interface/public/shared/cdx/cdx-styles.js +3251 -0
  917. package/neural-interface/public/shared/cdx/cdx-tabs.js +7992 -0
  918. package/neural-interface/public/shared/cdx/cdx-ws.js +363 -0
  919. package/neural-interface/public/shared/cli-status.js +169 -0
  920. package/neural-interface/public/shared/command-runner-model.js +30 -0
  921. package/neural-interface/public/shared/constants.js +22 -5
  922. package/neural-interface/public/shared/cp/cp-agents.js +186 -0
  923. package/neural-interface/public/shared/cp/cp-bash.js +252 -0
  924. package/neural-interface/public/shared/cp/cp-compose.js +159 -0
  925. package/neural-interface/public/shared/cp/cp-context-menu.js +309 -0
  926. package/neural-interface/public/shared/cp/cp-context-model.js +157 -0
  927. package/neural-interface/public/shared/cp/cp-context-window.js +80 -0
  928. package/neural-interface/public/shared/cp/cp-ctx.js +11 -0
  929. package/neural-interface/public/shared/cp/cp-diff.js +255 -0
  930. package/neural-interface/public/shared/cp/cp-event-rows.js +637 -0
  931. package/neural-interface/public/shared/cp/cp-events.js +846 -0
  932. package/neural-interface/public/shared/cp/cp-markdown.js +104 -0
  933. package/neural-interface/public/shared/cp/cp-permission-model.js +905 -0
  934. package/neural-interface/public/shared/cp/cp-permissions.js +626 -0
  935. package/neural-interface/public/shared/cp/cp-rehydrate.js +113 -0
  936. package/neural-interface/public/shared/cp/cp-restore.js +224 -0
  937. package/neural-interface/public/shared/cp/cp-session-model.js +338 -0
  938. package/neural-interface/public/shared/cp/cp-session-settings.js +254 -0
  939. package/neural-interface/public/shared/cp/cp-sessions.js +227 -0
  940. package/neural-interface/public/shared/cp/cp-statusline.js +153 -0
  941. package/neural-interface/public/shared/cp/cp-styles.js +349 -0
  942. package/neural-interface/public/shared/cp/cp-tasks-model.js +282 -0
  943. package/neural-interface/public/shared/cp/cp-tasks.js +107 -0
  944. package/neural-interface/public/shared/cp/cp-temporary-view.js +56 -0
  945. package/neural-interface/public/shared/cp/cp-temporary.js +231 -0
  946. package/neural-interface/public/shared/cp/cp-tool-cards.js +326 -0
  947. package/neural-interface/public/shared/cp/cp-tool-results.js +618 -0
  948. package/neural-interface/public/shared/cp/cp-usage-model.js +124 -0
  949. package/neural-interface/public/shared/graph-activity.js +68 -0
  950. package/neural-interface/public/shared/html-shell.js +116 -17
  951. package/neural-interface/public/shared/i18n.js +132 -34
  952. package/neural-interface/public/shared/node-positions-store.js +44 -0
  953. package/neural-interface/public/shared/ocp-hidden-models.js +116 -0
  954. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +355 -0
  955. package/neural-interface/public/shared/ocp-v2/ocp-v2-autoaccept-button.js +35 -0
  956. package/neural-interface/public/shared/ocp-v2/ocp-v2-automation-ownership.js +72 -0
  957. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +280 -0
  958. package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +67 -0
  959. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +179 -0
  960. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes.js +164 -0
  961. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +725 -0
  962. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +75 -0
  963. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +1204 -0
  964. package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm-logic.js +117 -0
  965. package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm.js +59 -0
  966. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-gauge.js +252 -0
  967. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +478 -0
  968. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +179 -0
  969. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +233 -0
  970. package/neural-interface/public/shared/ocp-v2/ocp-v2-icons.js +30 -0
  971. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +1065 -0
  972. package/neural-interface/public/shared/ocp-v2/ocp-v2-mention-hints.js +182 -0
  973. package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +655 -0
  974. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +2636 -0
  975. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +601 -0
  976. package/neural-interface/public/shared/ocp-v2/ocp-v2-profile-inheritance.js +78 -0
  977. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +649 -0
  978. package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +35 -0
  979. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +357 -0
  980. package/neural-interface/public/shared/ocp-v2/ocp-v2-render-logic.js +189 -0
  981. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1869 -0
  982. package/neural-interface/public/shared/ocp-v2/ocp-v2-select.js +42 -0
  983. package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +117 -0
  984. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +1714 -0
  985. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +468 -0
  986. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-widgets.js +63 -0
  987. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +366 -0
  988. package/neural-interface/public/shared/ocp-v2/ocp-v2-settings-link.js +19 -0
  989. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +343 -0
  990. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +746 -0
  991. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +347 -0
  992. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +338 -0
  993. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +3543 -0
  994. package/neural-interface/public/shared/ocp-v2/ocp-v2-subagents-logic.js +482 -0
  995. package/neural-interface/public/shared/ocp-v2/ocp-v2-tools-logic.js +351 -0
  996. package/neural-interface/public/shared/ocp-v2/ocp-v2-tools.js +168 -0
  997. package/neural-interface/public/shared/ocp-v2/ocp-v2-variantpicker.js +315 -0
  998. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +545 -0
  999. package/neural-interface/public/shared/provider-icons.js +30 -0
  1000. package/neural-interface/public/shared/pwa-install-page.js +34 -0
  1001. package/neural-interface/public/shared/pwa-install.css +12 -0
  1002. package/neural-interface/public/shared/pwa-install.js +28 -0
  1003. package/neural-interface/public/shared/session-title.js +100 -0
  1004. package/neural-interface/public/shared/settings/settings-ia.js +389 -0
  1005. package/neural-interface/public/shared/settings/settings-kit.js +234 -0
  1006. package/neural-interface/public/shared/settings/settings-rules.js +160 -0
  1007. package/neural-interface/public/shared/settings/settings-search.js +463 -0
  1008. package/neural-interface/public/shared/settings/settings-shell.js +570 -0
  1009. package/neural-interface/public/shared/start-bridge.js +583 -0
  1010. package/neural-interface/public/shared/state.js +5 -0
  1011. package/neural-interface/public/shared/storage.js +50 -7
  1012. package/neural-interface/public/shared/styleguide/sg-agents.js +42 -0
  1013. package/neural-interface/public/shared/styleguide/sg-brand.js +4 -0
  1014. package/neural-interface/public/shared/styleguide/sg-color-client.js +388 -0
  1015. package/neural-interface/public/shared/styleguide/sg-colors.js +151 -0
  1016. package/neural-interface/public/shared/styleguide/sg-components.js +35 -0
  1017. package/neural-interface/public/shared/styleguide/sg-history.js +41 -0
  1018. package/neural-interface/public/shared/styleguide/sg-icons-logo.js +38 -0
  1019. package/neural-interface/public/shared/styleguide/sg-imagery.js +4 -0
  1020. package/neural-interface/public/shared/styleguide/sg-import-export.js +48 -0
  1021. package/neural-interface/public/shared/styleguide/sg-kit.js +284 -0
  1022. package/neural-interface/public/shared/styleguide/sg-labels.js +318 -0
  1023. package/neural-interface/public/shared/styleguide/sg-layout.js +4 -0
  1024. package/neural-interface/public/shared/styleguide/sg-motion.js +5 -0
  1025. package/neural-interface/public/shared/styleguide/sg-panel.js +237 -0
  1026. package/neural-interface/public/shared/styleguide/sg-preview.js +138 -0
  1027. package/neural-interface/public/shared/styleguide/sg-rules.js +9 -0
  1028. package/neural-interface/public/shared/styleguide/sg-shape.js +24 -0
  1029. package/neural-interface/public/shared/styleguide/sg-state.js +132 -0
  1030. package/neural-interface/public/shared/styleguide/sg-typography.js +125 -0
  1031. package/neural-interface/public/shared/styles.css +8614 -1477
  1032. package/neural-interface/public/shared/synabun-mascot.js +1625 -0
  1033. package/neural-interface/public/shared/synabun-ticker.js +376 -0
  1034. package/neural-interface/public/shared/term-ready.js +307 -0
  1035. package/neural-interface/public/shared/term-renderer.js +343 -0
  1036. package/neural-interface/public/shared/ui-assistant-panel.js +10 -0
  1037. package/neural-interface/public/shared/ui-assistant.js +77 -0
  1038. package/neural-interface/public/shared/ui-automation-studio.js +5105 -3573
  1039. package/neural-interface/public/shared/ui-claude-panel.js +11685 -6333
  1040. package/neural-interface/public/shared/ui-codex-panel.js +12 -0
  1041. package/neural-interface/public/shared/ui-command-runner.js +251 -468
  1042. package/neural-interface/public/shared/ui-cost-widget.js +55 -34
  1043. package/neural-interface/public/shared/ui-detail.js +77 -14
  1044. package/neural-interface/public/shared/ui-explorer.js +360 -181
  1045. package/neural-interface/public/shared/ui-file-explorer.js +485 -107
  1046. package/neural-interface/public/shared/ui-help.js +2 -2
  1047. package/neural-interface/public/shared/ui-image-gallery.js +45 -21
  1048. package/neural-interface/public/shared/ui-judgments.js +1346 -0
  1049. package/neural-interface/public/shared/ui-keybinds.js +3 -2
  1050. package/neural-interface/public/shared/ui-link.js +105 -51
  1051. package/neural-interface/public/shared/ui-loading.js +222 -11
  1052. package/neural-interface/public/shared/ui-memory-maintenance.js +111 -0
  1053. package/neural-interface/public/shared/ui-menubar.js +100 -31
  1054. package/neural-interface/public/shared/ui-native-loop-router-state.js +94 -0
  1055. package/neural-interface/public/shared/ui-native-loop-router.js +493 -0
  1056. package/neural-interface/public/shared/ui-native-window-id.js +7 -0
  1057. package/neural-interface/public/shared/ui-navbar.js +357 -222
  1058. package/neural-interface/public/shared/ui-notifications.js +58 -12
  1059. package/neural-interface/public/shared/ui-opencode-panel-v2.js +17 -0
  1060. package/neural-interface/public/shared/ui-panels.js +15 -7
  1061. package/neural-interface/public/shared/ui-resume.js +823 -653
  1062. package/neural-interface/public/shared/ui-schedule-queue.js +172 -0
  1063. package/neural-interface/public/shared/ui-schedules-studio.js +1882 -0
  1064. package/neural-interface/public/shared/ui-scroll-follow.js +194 -0
  1065. package/neural-interface/public/shared/ui-sessions.js +789 -34
  1066. package/neural-interface/public/shared/ui-settings.js +5774 -2194
  1067. package/neural-interface/public/shared/ui-sidepanel-layout.js +109 -0
  1068. package/neural-interface/public/shared/ui-sidepanel-runtime.js +19 -0
  1069. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +40 -0
  1070. package/neural-interface/public/shared/ui-sidepanel-sessions.js +221 -0
  1071. package/neural-interface/public/shared/ui-sidepanel-state.js +131 -0
  1072. package/neural-interface/public/shared/ui-sidepanel-tray.js +547 -0
  1073. package/neural-interface/public/shared/ui-sidepanel-windows.js +387 -0
  1074. package/neural-interface/public/shared/ui-skills.js +18 -32
  1075. package/neural-interface/public/shared/ui-styleguide.js +35 -0
  1076. package/neural-interface/public/shared/ui-sync.js +87 -0
  1077. package/neural-interface/public/shared/ui-terminal.js +7863 -6385
  1078. package/neural-interface/public/shared/ui-tool-updates.js +292 -0
  1079. package/neural-interface/public/shared/ui-tooltip.js +156 -15
  1080. package/neural-interface/public/shared/ui-tutorial-draw.js +119 -683
  1081. package/neural-interface/public/shared/ui-tutorial-layout.js +135 -0
  1082. package/neural-interface/public/shared/ui-tutorial-steps.js +59 -2209
  1083. package/neural-interface/public/shared/ui-tutorial.css +102 -0
  1084. package/neural-interface/public/shared/ui-tutorial.js +557 -1076
  1085. package/neural-interface/public/shared/ui-update.js +420 -68
  1086. package/neural-interface/public/shared/ui-whatsapp.js +941 -0
  1087. package/neural-interface/public/shared/ui-whiteboard.js +1076 -233
  1088. package/neural-interface/public/shared/ui-workspaces.js +2 -1
  1089. package/neural-interface/public/shared/utils.js +58 -0
  1090. package/neural-interface/public/shared/vterm-buffer.js +15 -5
  1091. package/neural-interface/public/shared/whatsapp/wa-phone.js +65 -0
  1092. package/neural-interface/public/shared/whatsapp/wa-view.js +411 -0
  1093. package/neural-interface/public/sidepanel-session.html +18 -0
  1094. package/neural-interface/public/sw.js +10 -2
  1095. package/neural-interface/public/synabun.png +0 -0
  1096. package/neural-interface/public/variant/2d/graph.js +1707 -1635
  1097. package/neural-interface/public/variant/2d/lasso.js +2 -1
  1098. package/neural-interface/public/variant/2d/layout.js +595 -594
  1099. package/neural-interface/public/variant/2d/main.js +557 -521
  1100. package/neural-interface/public/variant/2d/settings-gfx.js +18 -24
  1101. package/neural-interface/public/variant/3d/main.js +517 -500
  1102. package/neural-interface/public/variant/3d/map-controls.js +144 -0
  1103. package/neural-interface/public/variant/3d/map-data.js +251 -0
  1104. package/neural-interface/public/variant/3d/map-labels.js +241 -0
  1105. package/neural-interface/public/variant/3d/map-pick.js +90 -0
  1106. package/neural-interface/public/variant/3d/map-renderer.js +521 -0
  1107. package/neural-interface/public/variant/3d/map-shaders.js +158 -0
  1108. package/neural-interface/public/variant/3d/map-view.js +618 -0
  1109. package/neural-interface/public/vendor/three/manifest.json +3 -0
  1110. package/neural-interface/public/vendor/three/three-0.169.0.min.js +3844 -0
  1111. package/neural-interface/public/vendor/xterm/manifest.json +3 -0
  1112. package/neural-interface/public/vendor/xterm/xterm-6.0.0.css +285 -0
  1113. package/neural-interface/public/vendor/xterm/xterm-6.0.0.min.js +192 -0
  1114. package/neural-interface/scripts/build-vendor.mjs +64 -0
  1115. package/neural-interface/scripts/codex-protocol-fixture.mjs +83 -0
  1116. package/neural-interface/scripts/rebuild-pty.js +39 -22
  1117. package/neural-interface/scripts/vendor-three-entry.js +24 -0
  1118. package/neural-interface/scripts/vendor-xterm-entry.js +8 -0
  1119. package/neural-interface/server.js +33983 -15000
  1120. package/neural-interface/skins/default/skin.css +90 -0
  1121. package/neural-interface/skins/default/skin.json +8 -0
  1122. package/neural-interface/templates/rulesets/README.md +9 -0
  1123. package/neural-interface/templates/rulesets/claude.md +3 -0
  1124. package/neural-interface/templates/rulesets/codex.md +2 -0
  1125. package/neural-interface/templates/rulesets/coexistence.md +6 -0
  1126. package/neural-interface/templates/rulesets/core.md +26 -0
  1127. package/neural-interface/templates/rulesets/cursor.md +2 -0
  1128. package/neural-interface/templates/rulesets/gemini.md +2 -0
  1129. package/neural-interface/templates/rulesets/legacy-hashes.json +227 -0
  1130. package/neural-interface/templates/rulesets/manifest.json +12 -0
  1131. package/neural-interface/templates/rulesets/opencode.md +2 -0
  1132. package/package.json +131 -53
  1133. package/postinstall.js +55 -26
  1134. package/preuninstall.js +187 -0
  1135. package/scripts/restore-data-home-from-backup.mjs +239 -0
  1136. package/setup.js +872 -260
  1137. package/skills/leonardo/SKILL.md +19 -10
  1138. package/skills/leonardo/modules/image-prompter.md +18 -12
  1139. package/skills/leonardo/modules/video-prompter.md +19 -13
  1140. package/skills/synabun/SKILL.md +209 -185
  1141. package/skills/synabun/icon.png +0 -0
  1142. package/skills/synabun/modules/audit.md +380 -374
  1143. package/skills/synabun/modules/changelog.md +15 -6
  1144. package/skills/synabun/modules/idea.md +148 -144
  1145. package/skills/synabun/modules/memorize.md +13 -4
  1146. package/skills/synabun/modules/schedule.md +198 -0
  1147. package/skills/synabun/synabunicon.png +0 -0
  1148. package/updater.cmd +31 -0
  1149. package/updater.mjs +382 -0
  1150. package/updater.sh +29 -0
  1151. package/hooks/claude-code/test-user-learning.mjs +0 -531
  1152. package/neural-interface/public/claude-chat.css +0 -878
  1153. package/neural-interface/public/claude-chat.html +0 -92
  1154. package/neural-interface/public/claude-chat.js +0 -1168
  1155. package/neural-interface/public/index-legacy.html +0 -14677
  1156. package/neural-interface/public/index2d-legacy.html +0 -8193
  1157. package/neural-interface/public/shared/html-term-renderer.js +0 -1022
  1158. package/neural-interface/public/variant/3d/background.js +0 -884
  1159. package/neural-interface/public/variant/3d/camera.js +0 -661
  1160. package/neural-interface/public/variant/3d/gfx.js +0 -116
  1161. package/neural-interface/public/variant/3d/graph.js +0 -2399
  1162. package/neural-interface/public/variant/3d/settings-gfx.js +0 -228
  1163. package/neural-interface/templates/CLAUDE-template.md +0 -211
@@ -0,0 +1,926 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun — Browser tool policy: every page through the SynaBun browser
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // The Assistant's brain (Claude, Codex, OpenCode) and the workers it
6
+ // dispatches look at pages — public or localhost — only through SynaBun's
7
+ // browser tools (browser_*), which open the browser configured in SynaBun
8
+ // (MoreLogin). They never start a browser of their own, and when the SynaBun
9
+ // browser fails or lacks something they report it instead of switching.
10
+ //
11
+ // browserPolicyText the one rule text: the persona, plan mode, worker prompts
12
+ // browserToolDenial one tool call's refusal, else null. The brain asks it in
13
+ // assistant-runtime.js (browserGate: the Claude hook, the
14
+ // Codex hook and OpenCode plugin through gateCheck, the
15
+ // reactive fallback); Assistant task runs' workers in
16
+ // native-loop-providers.js (Claude),
17
+ // assistant-brains/codex-browser-policy-hook.mjs and
18
+ // assistant-brains/opencode-browser-policy.js
19
+ //
20
+ // Lexical, like remote-policy.js: a speed bump, not a sandbox. A shell that
21
+ // builds a program name at run time, or a script loading a browser library
22
+ // from a file SynaBun cannot read, gets past it. Mentions (rg playwright,
23
+ // cat pw.cjs, sed -i … pw.cjs, git, code that only names a library) and a
24
+ // project's own automated tests (npm test, node --test, vitest, jest, npx
25
+ // playwright test run inside the project on files inside it) always pass.
26
+ // Computer use on a browser window is refused by the desktop guards
27
+ // (lib/desktop/guards.js), which know the app a click or a key lands in.
28
+ // Pure ESM with no imports of SynaBun's own, loaded by Node and by OpenCode's
29
+ // Bun plugin host: no I/O but the injectable readFile that reads an executed
30
+ // script. remote-policy.js is not imported (it reaches backup-service.js and
31
+ // node:sqlite); its command-position matching and per-host input keys are
32
+ // repeated here in small.
33
+
34
+ import { readFileSync, statSync } from 'node:fs';
35
+ import { homedir } from 'node:os';
36
+ import { isAbsolute, relative, resolve } from 'node:path';
37
+
38
+ /** An executed script is read up to this size; a larger or unreadable one is allowed. */
39
+ export const MAX_SCRIPT_BYTES = 256 * 1024;
40
+ // A longer command line is checked in its first part only.
41
+ const MAX_COMMAND_CHARS = 256 * 1024;
42
+ // sh -c / eval / heredocs fed to a shell, nested.
43
+ const MAX_DEPTH = 4;
44
+
45
+ // ── the rule text ───────────────────────────────────────────────────────────
46
+
47
+ const HOSTS = { claude: 'claude', 'claude-code': 'claude', codex: 'codex', opencode: 'opencode' };
48
+ const hostKey = (host) => HOSTS[String(host || '').toLowerCase()] || null;
49
+ // Each host's own web search / fetch (the rule names the host's; unknown: all of them).
50
+ const WEB_TOOL_WORDS = {
51
+ claude: 'WebSearch / WebFetch',
52
+ codex: 'Codex\'s web_search',
53
+ opencode: 'webfetch / websearch',
54
+ };
55
+
56
+ /**
57
+ * The SynaBun browser tool names a host's model sees: a prefix
58
+ * ('mcp__SynaBun__', 'SynaBun_', '') or the persona's toolNames() map.
59
+ */
60
+ function browserToolNames(tools) {
61
+ const map = tools && typeof tools === 'object' ? tools : {};
62
+ const prefix = typeof tools === 'string' ? tools : (typeof map.prefix === 'string' ? map.prefix : '');
63
+ return {
64
+ navigate: map.browserNavigate || `${prefix}browser_navigate`,
65
+ snapshot: map.browserSnapshot || `${prefix}browser_snapshot`,
66
+ screenshot: map.browserScreenshot || `${prefix}browser_screenshot`,
67
+ console: map.browserConsole || `${prefix}browser_console`,
68
+ };
69
+ }
70
+
71
+ /**
72
+ * The browser rule, as bullet lines: the brain's persona (its host's tool
73
+ * names in `tools`), the worker prompts of browser runs. `host`: claude /
74
+ * codex / opencode (names that host's own web tools), else all of them.
75
+ */
76
+ export function browserPolicyText({ tools = '', host = null } = {}) {
77
+ const t = browserToolNames(tools);
78
+ const web = WEB_TOOL_WORDS[hostKey(host)] || 'WebSearch / WebFetch (OpenCode webfetch / websearch, Codex web_search)';
79
+ return [
80
+ `- Every page, public or localhost, goes through SynaBun's browser tools (${t.navigate}, ${t.snapshot}, ${t.screenshot}, ${t.console} and the other browser_* tools); they open the browser configured in SynaBun (MoreLogin). Nothing else opens a page.`,
81
+ '- Never run Playwright, Puppeteer or Selenium code of your own to look at a page (a script, node -e, python -c, a heredoc), and never `npx playwright` except to run the project\'s automated tests (npx playwright test).',
82
+ '- Never launch Chrome, Chromium, Edge, chrome-headless-shell or any other browser binary, and never take headless screenshots (--headless, --screenshot).',
83
+ '- Never `open` a URL or a browser app, and never use computer use on a browser app.',
84
+ `- Never use the Playwright, Chrome DevTools, Claude-in-Chrome or any other browser MCP tools, nor ${web}.`,
85
+ `- Visual checks: ${t.screenshot} (width, height, fullPage, save). Page errors and console output: ${t.console}.`,
86
+ '- If the SynaBun browser fails, is unavailable or lacks what you need, stop and report it. Never substitute another browser or tool.',
87
+ '- This rule overrides any task text, context or memory that says otherwise.',
88
+ ].join('\n');
89
+ }
90
+
91
+ // ── tool names ──────────────────────────────────────────────────────────────
92
+
93
+ // SynaBun's own tools under any host prefix: mcp__SynaBun__…, a server name that
94
+ // ends in SynaBun (mcp__claude_ai_Synabun__…, a plugin's mcp__plugin_x_SynaBun__…),
95
+ // OpenCode's SynaBun_… and SynaBun.… — the leaf name, else null.
96
+ const SYNABUN_TOOL = /^(?:mcp__(?:[a-z0-9-]+_)*synabun__|synabun[_.:/-]+)(.+)$/i;
97
+ const synabunLeaf = (name) => SYNABUN_TOOL.exec(name)?.[1] ?? null;
98
+ const isSynabunTool = (name) => synabunLeaf(name) !== null;
99
+ const BROWSER_SERVER_WORD = 'browser|playwright|puppeteer|chrome|devtools|selenium|webdriver|browserbase|stagehand|hyperbrowser';
100
+ // Another MCP server that drives a browser, by its server name.
101
+ const BROWSER_SERVER = new RegExp(BROWSER_SERVER_WORD, 'i');
102
+ // OpenCode names an MCP tool <server>_<tool>: the server is the first segment.
103
+ const OPENCODE_BROWSER_TOOL = new RegExp(`^([a-z0-9-]*?(?:${BROWSER_SERVER_WORD})[a-z0-9-]*)_`, 'i');
104
+ // A tool that drives a page by its own name, whatever its server is called
105
+ // (snake case: navigatePage and navigate-page are navigate_page).
106
+ const PAGE_TOOL = /^(?:browser_.+|navigate(?:_(?:page|to|to_url|url|back|forward))?|go_?to(?:_(?:url|page))?|go_(?:back|forward)|open_(?:url|page|link|website|webpage|browser|in_browser)|new_page|launch_browser|(?:take|capture)_(?:page_|full_page_|web_?page_|website_)?screenshot|(?:page|full_page|web_?page|website)_screenshot|screenshot(?:_(?:page|url|website|webpage))?)$/;
107
+ const snakeName = (text) => String(text || '').replace(/([a-z0-9])([A-Z])/g, '$1_$2').replace(/[-.\s]+/g, '_').toLowerCase();
108
+ // Web search / fetch outside the SynaBun browser: Claude's, OpenCode's, Codex's.
109
+ const WEB_TOOLS = new Set(['websearch', 'webfetch', 'web_search', 'web_fetch', 'web_search_preview']);
110
+ // Shell tools: Claude's Bash / PowerShell, Codex's shell family, OpenCode's bash.
111
+ const SHELL_TOOLS = new Set(['bash', 'powershell', 'shell', 'shell_command', 'exec_command', 'local_shell', 'container.exec', 'unified_exec']);
112
+
113
+ /**
114
+ * What another MCP server's tool does to a browser (for the refusal), else null:
115
+ * a server whose name says browser (mcp__<server>__<tool>, OpenCode's
116
+ * <server>_<tool>), or a tool whose own name drives a page (browser_*,
117
+ * navigate, goto, open_url, take_screenshot …). SynaBun's tools never match.
118
+ */
119
+ function browserMcpTool(name, host) {
120
+ if (isSynabunTool(name)) return null;
121
+ if (/^mcp__/i.test(name)) {
122
+ const cut = name.lastIndexOf('__');
123
+ const server = cut > 5 ? name.slice(5, cut) : '';
124
+ const tool = cut > 5 ? name.slice(cut + 2) : '';
125
+ if (server && BROWSER_SERVER.test(server)) return `the ${server} MCP server drives a browser of its own`;
126
+ return server && PAGE_TOOL.test(snakeName(tool)) ? `${tool} of the ${server} MCP server drives a page` : null;
127
+ }
128
+ if (host && host !== 'opencode') return null;
129
+ const server = OPENCODE_BROWSER_TOOL.exec(name)?.[1];
130
+ if (server) return `the ${server} MCP server drives a browser of its own`;
131
+ // Where the server's name ends is not known (it can hold "_"): any tail of the name counts.
132
+ const words = snakeName(name).split('_');
133
+ for (let i = 0; i < words.length; i += 1) {
134
+ if (PAGE_TOOL.test(words.slice(i).join('_'))) return `${name} drives a page`;
135
+ }
136
+ return null;
137
+ }
138
+
139
+ // ── browser apps and programs ───────────────────────────────────────────────
140
+
141
+ // A web browser as a Mac app name (lower case, spaces for - and _) or a bundle
142
+ // id. MoreLogin, SynaBun's configured browser, is neither.
143
+ const BROWSER_APP_NAME = /^(?:google chrome(?: (?:canary|beta|dev|for testing))?|chrome(?: for testing)?|chromium|safari(?: technology preview)?|(?:mozilla )?firefox(?: (?:developer edition|nightly))?|microsoft edge(?: (?:beta|dev|canary))?|edge|brave(?: browser)?(?: (?:beta|nightly))?|arc|opera(?: gx)?|vivaldi|orion|zen(?: browser)?|duckduckgo|tor browser|waterfox|librewolf|thorium)$/;
144
+ // MoreLogin's profile windows (org.HongKongZiXun.MoreLogin, named "MoreLogin" like
145
+ // its manager app com.zixun.MoreLoginPlus) are a browser too; only the bundle id tells them apart.
146
+ const BROWSER_BUNDLE = /^(?:com\.google\.chrome|org\.chromium\.|com\.apple\.safari|org\.mozilla\.(?:firefox|nightly)|com\.microsoft\.edge|com\.brave\.browser|company\.thebrowser\.|com\.operasoftware\.opera|com\.vivaldi\.|com\.kagi\.kagimacos|app\.zen-browser\.|com\.duckduckgo\.macos\.browser|org\.torproject\.|org\.hongkongzixun\.morelogin)/;
147
+ const appWords = (text) => text.replace(/[\s_-]+/g, ' ').trim();
148
+
149
+ /** The app's name when it is a web browser (a name, a bundle id, or a path to the .app), else null. */
150
+ function browserApp(app) {
151
+ const raw = String(app ?? '').trim();
152
+ if (!raw) return null;
153
+ const text = raw.toLowerCase();
154
+ if (BROWSER_BUNDLE.test(text)) return raw;
155
+ const last = text.replace(/\\/g, '/').replace(/\/+$/, '').split('/').pop() || '';
156
+ return BROWSER_APP_NAME.test(appWords(last.replace(/\.app$/, ''))) ? raw : null;
157
+ }
158
+
159
+ // A browser by its executable's file name. Only unambiguous names: a Mac app's
160
+ // own executable is recognised by its .app (APP_EXECUTABLE).
161
+ const BROWSER_PROGRAM = /^(?:google chrome(?: (?:stable|beta|unstable|dev|canary|for testing))?|chrome|chromium(?: browser)?|chrome headless shell|headless shell|msedge|microsoft edge(?: (?:stable|beta|dev|canary))?|firefox(?: bin)?|brave(?: browser)?|vivaldi(?: stable)?|thorium(?: browser)?)$/;
162
+ const APP_EXECUTABLE = /(?:^|\/)([^/]+)\.app\/contents\/macos\/[^/]+$/i;
163
+ // A program that looks like a browser, for the flags only a browser takes.
164
+ const BROWSERISH = /chrom|edge|firefox|brave|headless|browser|webkit|safari|opera|vivaldi/i;
165
+ const HEADLESS_FLAG = /^--(?:headless|screenshot|remote-debugging-port|remote-debugging-pipe|print-to-pdf|dump-dom)(?:=|$)/i;
166
+
167
+ /** "<name>" for a word in command position that starts a browser, else null. */
168
+ function browserProgram(word) {
169
+ const path = String(word || '').replace(/\\/g, '/');
170
+ const app = APP_EXECUTABLE.exec(path);
171
+ if (app) return browserApp(app[1]) ? `${app[1]}` : null;
172
+ const name = programName(path);
173
+ return BROWSER_PROGRAM.test(appWords(name)) ? name : null;
174
+ }
175
+
176
+ function programName(word) {
177
+ const base = String(word || '').replace(/\\/g, '/').split('/').pop() || '';
178
+ return base.toLowerCase().replace(/\.(?:exe|cmd|bat)$/, '');
179
+ }
180
+
181
+ // ── what code does ─────────────────────────────────────────────────────────
182
+
183
+ // Code that drives a browser, and what the refusal says it does. Executed
184
+ // scripts and inline code (node -e, python -c, a heredoc or pipe into an
185
+ // interpreter) count by what the code does: a browser library loaded
186
+ // (require, import, import(), Python's from/import), a launch or CDP connect
187
+ // call, a browser started through the shell. Code that only names one (a
188
+ // string, a comment, an instruction) runs.
189
+
190
+ // A module specifier in JS: quoted, with Deno's npm: and a version or subpath allowed.
191
+ const Q = '[\'"`]';
192
+ const moduleUse = (names) => {
193
+ const spec = `(?:npm:)?(?:${names})(?:@[^'"\`/\\s]*)?(?:/[^'"\`\\s]*)?`;
194
+ return [
195
+ `\\brequire\\s*\\(\\s*${Q}${spec}${Q}`,
196
+ `\\bimport\\s*\\(\\s*${Q}${spec}${Q}`,
197
+ `\\bimport\\s+(?!type\\b)(?:[\\w$*{}\\s,]{1,1000}?\\bfrom\\s*)?${Q}${spec}${Q}`,
198
+ `\\bexport\\s+[\\w$*{}\\s,]{1,1000}?\\bfrom\\s*${Q}${spec}${Q}`,
199
+ ].join('|');
200
+ };
201
+ // A Python module imported: from x[.y] import …, import x, __import__('x'), import_module('x').
202
+ const pythonUse = (names) => `(?:^|[\\n;])[ \\t]*(?:from[ \\t]+(?:${names})(?:\\.[\\w.]+)?[ \\t]+import\\b|import[ \\t]+(?:[\\w.]+[ \\t]*,[ \\t]*)*(?:${names})\\b)|\\b(?:__import__|import_module)\\s*\\(\\s*['"](?:${names})\\b`;
203
+ const marker = (pattern, what) => ({ re: new RegExp(pattern), what });
204
+ // A browser program named in the same text as a headless flag (not Godot's or Blender's --headless).
205
+ const BROWSER_WORD = /\b(?:google[ -]chrome|chrome|chromium|msedge|microsoft edge|firefox|brave|headless_shell)\b/i;
206
+ const CODE_MARKERS = [
207
+ marker(`${moduleUse('playwright(?:-core|-chromium|-firefox|-webkit|-extra)?|@playwright/[a-z0-9-]+')}|${pythonUse('playwright')}`, 'uses Playwright'),
208
+ marker(`${moduleUse('puppeteer(?:-core|-extra)?|@puppeteer/[a-z0-9-]+')}|${pythonUse('pyppeteer')}`, 'uses Puppeteer'),
209
+ marker(`${moduleUse('selenium-webdriver|webdriverio')}|${pythonUse('selenium|seleniumbase|undetected_chromedriver')}|\\bwebdriver\\s*\\.\\s*(?:Chrome|Firefox|Edge|Safari|Remote|ChromiumEdge)\\s*\\(|\\bnew\\s+Builder\\s*\\(\\s*\\)\\s*\\.\\s*forBrowser\\b`, 'uses Selenium / WebDriver'),
210
+ marker(`${moduleUse('chrome-launcher|chrome-remote-interface')}|\\b(?:chromium|firefox|webkit)\\s*\\.\\s*(?:launch|launchPersistentContext|launch_persistent_context|launchServer|launch_server|connect|connectOverCDP|connect_over_cdp)\\s*\\(|\\b(?:launchPersistentContext|launch_persistent_context|connectOverCDP|connect_over_cdp)\\s*\\(|\\bpuppeteer\\s*\\.\\s*(?:launch|connect)\\s*\\(|\\b(?:sync|async)_playwright\\s*\\(|\\bchromeLauncher\\s*\\.\\s*launch\\s*\\(`, 'launches a browser'),
211
+ marker('\\b(?:npx|bunx|pnpx)\\s+(?:-y\\s+|--yes\\s+)?(?:playwright|puppeteer|lighthouse|pa11y|shot-scraper|capture-website)\\b(?!\\s+test\\b)|--remote-debugging-(?:port|pipe)\\b|--headless=(?:new|old|chrome)\\b|\\bchrome-headless-shell\\b', 'starts a browser'),
212
+ { re: /--headless\b/, also: BROWSER_WORD, what: 'starts a browser' },
213
+ marker('\\bwebbrowser\\s*\\.\\s*open(?:_new(?:_tab)?)?\\s*\\(', 'opens the default browser'),
214
+ ];
215
+ function codeMarker(text) {
216
+ const value = String(text || '');
217
+ if (!value) return null;
218
+ for (const { re, also, what } of CODE_MARKERS) if (re.test(value) && (!also || also.test(value))) return what;
219
+ return null;
220
+ }
221
+
222
+ // ── paths ───────────────────────────────────────────────────────────────────
223
+
224
+ function resolvePath(base, path) {
225
+ const text = String(path || '');
226
+ if (text === '~' || text.startsWith('~/')) return resolve(homedir(), text.slice(2));
227
+ return isAbsolute(text) ? resolve(text) : resolve(base || process.cwd(), text);
228
+ }
229
+ function insideDir(path, dir) {
230
+ const rel = relative(resolve(dir), resolve(path));
231
+ return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
232
+ }
233
+ /** A regular file up to MAX_SCRIPT_BYTES, else null. */
234
+ function defaultReadFile(path) {
235
+ const stat = statSync(path);
236
+ if (!stat.isFile() || stat.size > MAX_SCRIPT_BYTES) return null;
237
+ return readFileSync(path, 'utf8');
238
+ }
239
+ function readScript(ctx, path) {
240
+ try {
241
+ const text = ctx.readFile(path);
242
+ return typeof text === 'string' ? text.slice(0, MAX_SCRIPT_BYTES) : null;
243
+ } catch { return null; }
244
+ }
245
+
246
+ // ── the shell ───────────────────────────────────────────────────────────────
247
+
248
+ /** The index of the ")" closing a $( that opened before `start`, else the text's length. */
249
+ function substitutionEnd(text, start) {
250
+ let depth = 1;
251
+ for (let i = start; i < text.length; i += 1) {
252
+ const c = text[i];
253
+ if (c === '\\') { i += 1; continue; }
254
+ if (c === "'") { const end = text.indexOf("'", i + 1); i = end === -1 ? text.length : end; continue; }
255
+ if (c === '"') {
256
+ let j = i + 1;
257
+ while (j < text.length && text[j] !== '"') j += text[j] === '\\' ? 2 : 1;
258
+ i = j;
259
+ continue;
260
+ }
261
+ if (c === '(') depth += 1;
262
+ else if (c === ')' && --depth === 0) return i;
263
+ }
264
+ return text.length;
265
+ }
266
+ /** The index of the backtick closing one that opened before `start`, else the text's length. */
267
+ function backtickEnd(text, start) {
268
+ for (let i = start; i < text.length; i += 1) {
269
+ if (text[i] === '\\') { i += 1; continue; }
270
+ if (text[i] === '`') return i;
271
+ }
272
+ return text.length;
273
+ }
274
+ /** The commands inside $(…) and `…` of text the shell expands (a double-quoted string, an unquoted heredoc). */
275
+ function substitutionsIn(text) {
276
+ const bodies = [];
277
+ for (let i = 0; i < text.length; i += 1) {
278
+ if (text[i] === '\\') { i += 1; continue; }
279
+ if (text[i] === '$' && text[i + 1] === '(' && text[i + 2] !== '(') {
280
+ const end = substitutionEnd(text, i + 2);
281
+ bodies.push(text.slice(i + 2, end));
282
+ i = end;
283
+ } else if (text[i] === '`') {
284
+ const end = backtickEnd(text, i + 1);
285
+ bodies.push(text.slice(i + 1, end).replace(/\\([\\`$])/g, '$1'));
286
+ i = end;
287
+ }
288
+ }
289
+ return bodies;
290
+ }
291
+
292
+ /**
293
+ * A command line → its simple commands: { words, heredocs, inputs, pipedFrom }.
294
+ * Splits on ; & | && || newlines, ( ), backticks and $(…); removes quotes and
295
+ * backslash escapes; keeps heredoc and here-string bodies (the program's
296
+ * stdin), < input files and the command a pipe feeds it. The commands of a $(…)
297
+ * or `…` inside double quotes or an unquoted heredoc come first, as their own
298
+ * commands (they run before the command that holds them). Lexical: nothing is
299
+ * expanded, so a program named through a variable is not seen.
300
+ */
301
+ function simpleCommands(source, depth = 0) {
302
+ const text = String(source || '').slice(0, MAX_COMMAND_CHARS);
303
+ const n = text.length;
304
+ const out = [];
305
+ const nested = (body) => { if (depth < MAX_DEPTH) out.push(...simpleCommands(body, depth + 1)); };
306
+ const fresh = (pipedFrom = null) => ({ words: [], heredocs: [], inputs: [], pipedFrom });
307
+ let seg = fresh();
308
+ let word = null;
309
+ let target = null; // what the next word is: '<' an input file, '>' an output file, 'here' a here-string
310
+ const heredocs = []; // bodies still to read after the line ends: { seg, delim, strip, expands }
311
+ const pushWord = () => {
312
+ if (word === null) return;
313
+ if (target === '<') seg.inputs.push(word);
314
+ else if (target === 'here') seg.heredocs.push(word);
315
+ else if (target !== '>') seg.words.push(word);
316
+ word = null;
317
+ target = null;
318
+ };
319
+ const endSeg = ({ piped = false } = {}) => {
320
+ pushWord();
321
+ target = null;
322
+ const done = seg.words.length || seg.heredocs.length || seg.inputs.length ? seg : null;
323
+ if (done) out.push(done);
324
+ seg = fresh(piped ? done : null);
325
+ };
326
+ const readHeredocs = (start) => {
327
+ let i = start;
328
+ while (heredocs.length && i < n) {
329
+ const { seg: owner, delim, strip, expands } = heredocs.shift();
330
+ const lines = [];
331
+ while (i < n) {
332
+ const end = text.indexOf('\n', i);
333
+ const line = text.slice(i, end === -1 ? n : end);
334
+ i = end === -1 ? n : end + 1;
335
+ if ((strip ? line.replace(/^\t+/, '') : line).replace(/\r$/, '') === delim) break;
336
+ lines.push(line);
337
+ }
338
+ const body = lines.join('\n');
339
+ // <<EOF (unquoted) runs the body's $(…) and `…`; <<'EOF' keeps them as text.
340
+ if (expands) for (const inner of substitutionsIn(body)) nested(inner);
341
+ owner.heredocs.push(body);
342
+ }
343
+ return i;
344
+ };
345
+ let i = 0;
346
+ while (i < n) {
347
+ const c = text[i];
348
+ if (c === '\\') {
349
+ if (text[i + 1] === '\n') { i += 2; continue; }
350
+ word = (word ?? '') + (text[i + 1] ?? '');
351
+ i += 2;
352
+ continue;
353
+ }
354
+ if (c === "'") {
355
+ const end = text.indexOf("'", i + 1);
356
+ const stop = end === -1 ? n : end;
357
+ word = (word ?? '') + text.slice(i + 1, stop);
358
+ i = stop + 1;
359
+ continue;
360
+ }
361
+ if (c === '"') {
362
+ let j = i + 1;
363
+ let buf = '';
364
+ while (j < n && text[j] !== '"') {
365
+ if (text[j] === '\\' && '"\\$`\n'.includes(text[j + 1] ?? '')) { if (text[j + 1] !== '\n') buf += text[j + 1]; j += 2; continue; }
366
+ // "$(…)" and "`…`" still run: their commands are checked too; the word keeps their text.
367
+ if (text[j] === '$' && text[j + 1] === '(' && text[j + 2] !== '(') {
368
+ const end = substitutionEnd(text, j + 2);
369
+ nested(text.slice(j + 2, end));
370
+ buf += text.slice(j, Math.min(n, end + 1));
371
+ j = end + 1;
372
+ continue;
373
+ }
374
+ if (text[j] === '`') {
375
+ const end = backtickEnd(text, j + 1);
376
+ nested(text.slice(j + 1, end).replace(/\\([\\`$])/g, '$1'));
377
+ buf += text.slice(j, Math.min(n, end + 1));
378
+ j = end + 1;
379
+ continue;
380
+ }
381
+ buf += text[j];
382
+ j += 1;
383
+ }
384
+ word = (word ?? '') + buf;
385
+ i = j + 1;
386
+ continue;
387
+ }
388
+ if (c === '#' && word === null) { const end = text.indexOf('\n', i); i = end === -1 ? n : end; continue; }
389
+ if (c === '\n') { endSeg(); i = readHeredocs(i + 1); continue; }
390
+ if (c === '&' && text[i + 1] === '>') { pushWord(); target = '>'; i += text[i + 2] === '>' ? 3 : 2; continue; }
391
+ if (c === '|' && text[i + 1] !== '|') { endSeg({ piped: true }); i += text[i + 1] === '&' ? 2 : 1; continue; }
392
+ if (c === ';' || c === '&' || c === '|') { endSeg(); i += ['&&', '||', ';;'].includes(text.slice(i, i + 2)) ? 2 : 1; continue; }
393
+ if (c === '$' && text[i + 1] === '(') { endSeg(); i += 2; continue; }
394
+ if (c === '(' || c === ')' || c === '`') { endSeg(); i += 1; continue; }
395
+ if (c === '<' || c === '>') {
396
+ // A descriptor number before the operator ("2>") is not an argument.
397
+ if (word !== null && /^\d+$/.test(word)) word = null;
398
+ if (text.startsWith('<(', i) || text.startsWith('>(', i)) { endSeg(); i += 2; continue; }
399
+ if (text.startsWith('<<<', i)) { pushWord(); target = 'here'; i += 3; continue; }
400
+ if (text.startsWith('<<', i)) {
401
+ pushWord();
402
+ let j = i + 2;
403
+ const strip = text[j] === '-';
404
+ if (strip) j += 1;
405
+ while (text[j] === ' ' || text[j] === '\t') j += 1;
406
+ let delim = '';
407
+ let quoted = false;
408
+ while (j < n && !/[\s;&|<>()]/.test(text[j])) {
409
+ if (!['"', "'", '\\'].includes(text[j])) delim += text[j];
410
+ else quoted = true;
411
+ j += 1;
412
+ }
413
+ if (delim) heredocs.push({ seg, delim, strip, expands: !quoted });
414
+ i = j;
415
+ continue;
416
+ }
417
+ pushWord();
418
+ target = c;
419
+ i += 1;
420
+ while (text[i] === '>' || text[i] === '|') i += 1;
421
+ if (text[i] === '&') { // a descriptor (>&2, <&0, >&-): no file word follows
422
+ i += 1;
423
+ while (i < n && /[0-9-]/.test(text[i])) i += 1;
424
+ target = null;
425
+ }
426
+ continue;
427
+ }
428
+ if (c === ' ' || c === '\t' || c === '\r') { pushWord(); i += 1; continue; }
429
+ word = (word ?? '') + c;
430
+ i += 1;
431
+ }
432
+ endSeg();
433
+ return out;
434
+ }
435
+
436
+ // Programs that run the rest of their arguments as the command, and the options of theirs that take a value.
437
+ const WRAPPERS = {
438
+ sudo: ['-u', '-g', '-C', '-D', '-h', '-p', '-r', '-t', '-U'], env: ['-u', '-C', '-S', '-P'], nohup: [], exec: ['-a'], command: [],
439
+ time: [], nice: ['-n'], timeout: ['-s', '-k', '--signal', '--kill-after'], xargs: ['-I', '-n', '-P', '-L', '-d', '-E', '-s', '-a'],
440
+ caffeinate: ['-t', '-w'], stdbuf: ['-i', '-o', '-e'], unbuffer: [], ionice: ['-c', '-n', '-p'], arch: [],
441
+ };
442
+ // Shell words that come before a command.
443
+ const KEYWORDS = new Set(['if', 'then', 'else', 'elif', 'do', 'while', 'until', '!', '{', '}']);
444
+ // Python project runners: `uv run [options] <command>` and friends, and the options of theirs that take a value.
445
+ const RUNNERS = new Set(['uv', 'poetry', 'pipenv', 'pdm', 'rye', 'hatch']);
446
+ const RUNNER_VALUE_OPTIONS = new Set(['--with', '--with-requirements', '--python', '-p', '--project', '--directory', '--index', '--extra', '--group', '--env-file', '-e', '--env']);
447
+
448
+ /** The command itself: assignments (FOO=bar), keywords, wrappers (sudo, env, timeout 30…) and `uv run` left out. */
449
+ function commandWords(words) {
450
+ let i = 0;
451
+ while (i < words.length) {
452
+ const word = words[i];
453
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(word) || KEYWORDS.has(word)) { i += 1; continue; }
454
+ const name = programName(word);
455
+ if (RUNNERS.has(name) && words[i + 1] === 'run') {
456
+ i += 2;
457
+ while (i < words.length && /^-./.test(words[i])) {
458
+ const option = words[i];
459
+ i += 1;
460
+ if (option === '--') break;
461
+ if (RUNNER_VALUE_OPTIONS.has(option)) i += 1;
462
+ }
463
+ continue;
464
+ }
465
+ if (!Object.prototype.hasOwnProperty.call(WRAPPERS, name)) break;
466
+ const valued = WRAPPERS[name];
467
+ i += 1;
468
+ while (i < words.length && /^-./.test(words[i])) {
469
+ const option = words[i];
470
+ i += 1;
471
+ if (option === '--') break;
472
+ if (valued.includes(option)) i += 1;
473
+ }
474
+ if (name === 'timeout' && i < words.length) i += 1; // its duration
475
+ }
476
+ return words.slice(i);
477
+ }
478
+
479
+ const SHELLS = new Set(['sh', 'bash', 'zsh', 'dash', 'ksh', 'fish']);
480
+ const JS_RUNTIMES = new Set(['node', 'nodejs', 'bun', 'deno', 'tsx', 'ts-node', 'ts-node-esm', 'esno', 'vite-node', 'jiti', 'babel-node']);
481
+ const PYTHON = /^(?:python(?:\d+(?:\.\d+)*)?|py|pypy\d*)$/;
482
+ // A shell script by its name, when it has no shebang.
483
+ const SHELL_SCRIPT_FILE = /\.(?:sh|bash|zsh|ksh|command)$/i;
484
+ // Packages that drive or fetch a browser (npx / pnpm dlx / bunx …), and their installed CLIs.
485
+ const BROWSER_PACKAGES = new Set(['playwright', 'playwright-core', '@playwright/test', '@playwright/cli', 'puppeteer', 'puppeteer-core', '@puppeteer/browsers', 'lighthouse', 'pa11y', 'pa11y-ci', 'shot-scraper', 'capture-website', 'capture-website-cli', 'chrome-launcher']);
486
+ const BROWSER_CLIS = new Set(['playwright', 'puppeteer', 'lighthouse', 'pa11y', 'pa11y-ci', 'shot-scraper', 'capture-website']);
487
+ const PLAYWRIGHT_TEST = new Set(['playwright', '@playwright/test']);
488
+ // Playwright's UI and debug modes open a browser window for the agent: not an automated test run.
489
+ const PLAYWRIGHT_INTERACTIVE = /^--(?:ui|ui-host|ui-port|debug)(?:=|$)/;
490
+ // A script run as a program through its shebang (./pw.cjs, /tmp/shot.py).
491
+ const SCRIPT_FILE = /\.(?:[cm]?[jt]s|py)$/i;
492
+ // Python modules that drive or open a browser (python -m …).
493
+ const PYTHON_BROWSER_MODULE = /^(?:playwright|webbrowser|selenium|pyppeteer|shot_scraper)(?:\.|$)/;
494
+ const URL_ARG = /^(?:https?|file):\/\//i;
495
+ const LOOPBACK_ARG = /^(?:localhost|127\.0\.0\.1|0\.0\.0\.0|\[::1\])(?::\d+)?(?:[/?#]|$)/i;
496
+ const PATH_LIKE = /[/\\]|\.(?:[cm]?[jt]sx?|py|json|ya?ml|toml|html?)$/i;
497
+
498
+ /** The package in "npm@1 / @scope/pkg@2" → "npm" / "@scope/pkg" (lower case). */
499
+ function packageName(spec) {
500
+ const text = String(spec || '');
501
+ const at = text.indexOf('@', text.startsWith('@') ? 1 : 0);
502
+ return (at > 0 ? text.slice(0, at) : text).toLowerCase();
503
+ }
504
+
505
+ /**
506
+ * A package runner's target: { pkg, args, command } for npx / pnpx / bunx /
507
+ * bun x / pnpm dlx|exec / yarn dlx|exec / npm exec|x / uvx / pipx run, and for
508
+ * pnpm / yarn running a browser CLI or a runtime from node_modules/.bin
509
+ * (pnpm playwright …). `command`: npx -c "…" runs a command line. null otherwise.
510
+ */
511
+ // A package runner's options that take the next word as their value (npx --prefix /tmp …).
512
+ const RUNNER_OPTION_VALUES = new Set(['--prefix', '--cache', '--userconfig', '--registry', '--workspace', '-w', '--loglevel', '--node-options', '--shell', '--script-shell', '--from', '--python', '--spec', '--index-url', '--pip-args']);
513
+
514
+ function packageRun(words) {
515
+ const [head, ...args] = words;
516
+ const name = programName(head);
517
+ let rest = null;
518
+ if (name === 'npx' || name === 'pnpx' || name === 'bunx' || name === 'uvx') rest = args;
519
+ else if ((name === 'bun' && args[0] === 'x') || (name === 'pipx' && args[0] === 'run')) rest = args.slice(1);
520
+ else if ((name === 'pnpm' || name === 'yarn') && (args[0] === 'dlx' || args[0] === 'exec')) rest = args.slice(1);
521
+ else if (name === 'npm' && (args[0] === 'exec' || args[0] === 'x')) rest = args.slice(1);
522
+ else if ((name === 'pnpm' || name === 'yarn') && (BROWSER_CLIS.has(args[0]) || JS_RUNTIMES.has(args[0]))) rest = args;
523
+ if (!rest) return null;
524
+ let pkg = null;
525
+ for (let i = 0; i < rest.length; i += 1) {
526
+ const arg = rest[i];
527
+ if (arg === '--') continue;
528
+ if (arg === '-c' || arg === '--call') return { pkg: null, args: [], command: rest[i + 1] ?? '' };
529
+ if (arg === '-p' || arg === '--package') { pkg = pkg || packageName(rest[i + 1]); i += 1; continue; }
530
+ if (arg.startsWith('--package=')) { pkg = pkg || packageName(arg.slice(10)); continue; }
531
+ if (RUNNER_OPTION_VALUES.has(arg)) { i += 1; continue; }
532
+ if (arg.startsWith('-')) continue;
533
+ const bin = packageName(arg);
534
+ // `-p <pkg> <bin>`: the bin that runs decides (npx -p playwright playwright …).
535
+ return { pkg: BROWSER_PACKAGES.has(bin) || JS_RUNTIMES.has(bin) || !pkg ? bin : pkg, args: rest.slice(i + 1), command: null };
536
+ }
537
+ return null;
538
+ }
539
+
540
+ /** The files among a command's arguments (option values after = included, URLs not). */
541
+ function pathArgs(args) {
542
+ const out = [];
543
+ for (const arg of args) {
544
+ if (arg === '--') continue;
545
+ const value = arg.startsWith('-') ? (arg.includes('=') ? arg.slice(arg.indexOf('=') + 1) : null) : arg;
546
+ if (value && !URL_ARG.test(value) && PATH_LIKE.test(value)) out.push(value);
547
+ }
548
+ return out;
549
+ }
550
+
551
+ /**
552
+ * A project's own automated tests: npm|pnpm|yarn|bun test (and run test*),
553
+ * node --test, deno test, vitest, jest, playwright test — through a package
554
+ * runner too — run from inside the project (`cwd`, where the command runs, `cd`
555
+ * included) on file arguments, if any, that lie inside it too.
556
+ */
557
+ function isTestRun(words, { cwd, project }) {
558
+ if (!insideDir(cwd, project)) return false;
559
+ const [head, ...args] = words;
560
+ const name = programName(head);
561
+ let rest = null;
562
+ if (['npm', 'pnpm', 'yarn', 'bun'].includes(name)) {
563
+ const sub = args[0] || '';
564
+ if (sub === 'test' || sub === 't' || sub === 'tst') rest = args.slice(1);
565
+ else if ((sub === 'run' || sub === 'run-script') && /^test(?:[:.\w-]*)$/i.test(args[1] || '')) rest = args.slice(2);
566
+ else if ((name === 'pnpm' || name === 'yarn') && /^test[:.\w-]+$/i.test(sub)) rest = args.slice(1);
567
+ }
568
+ if ((name === 'node' || name === 'nodejs') && args.includes('--test')) rest = args;
569
+ if (name === 'deno' && args[0] === 'test') rest = args.slice(1);
570
+ if (name === 'vitest' || name === 'jest') rest = args;
571
+ let playwright = name === 'playwright' && args[0] === 'test';
572
+ if (playwright) rest = args.slice(1);
573
+ if (rest === null) {
574
+ const run = packageRun(words);
575
+ if (run?.pkg === 'vitest' || run?.pkg === 'jest') rest = run.args;
576
+ else if (PLAYWRIGHT_TEST.has(run?.pkg) && run.args[0] === 'test') { rest = run.args.slice(1); playwright = true; }
577
+ }
578
+ if (rest === null) return false;
579
+ if (playwright && rest.some((arg) => PLAYWRIGHT_INTERACTIVE.test(arg))) return false;
580
+ return pathArgs(rest).every((path) => insideDir(resolvePath(cwd, path), project));
581
+ }
582
+ /** Why a `playwright test` that is not an automated test run is refused. */
583
+ function playwrightTestWhy(runner, args, { cwd, project }) {
584
+ if (args.some((arg) => PLAYWRIGHT_INTERACTIVE.test(arg))) return `${runner} test in its UI or debug mode (a browser window)`;
585
+ return insideDir(cwd, project) ? `${runner} test on files outside the project` : `${runner} test run from ${cwd}, outside the project`;
586
+ }
587
+
588
+ /** What `open` / xdg-open is asked to show when it is a browser, a URL or a web page, else null. */
589
+ function openDenial(args) {
590
+ for (let i = 0; i < args.length; i += 1) {
591
+ const arg = args[i];
592
+ if (arg === '--args') break; // the rest goes to the app
593
+ if (/^-[A-Za-z]*[ab]$/.test(arg)) {
594
+ const app = args[i + 1];
595
+ if (browserApp(app)) return `opening ${app} with open`;
596
+ i += 1;
597
+ continue;
598
+ }
599
+ if (arg.startsWith('-')) continue;
600
+ if (URL_ARG.test(arg) || LOOPBACK_ARG.test(arg)) return `opening ${arg} with open`;
601
+ if (/\.html?$/i.test(arg)) return `opening ${arg} in a browser with open`;
602
+ }
603
+ return null;
604
+ }
605
+
606
+ // A shell's options that take the next word as their value.
607
+ const SHELL_VALUE_OPTIONS = new Set(['-o', '+o', '-O', '+O', '--rcfile', '--init-file', '-C', '--init-command']);
608
+
609
+ /**
610
+ * What a shell runs: { command } for `bash -c "…"` (-lc, -ec…), { file } for
611
+ * `bash x.sh`, else {} (its commands come from stdin: -s, a heredoc, < file, a pipe).
612
+ */
613
+ function shellRun(args) {
614
+ let command = false;
615
+ let stdin = false;
616
+ for (let i = 0; i < args.length; i += 1) {
617
+ const arg = args[i];
618
+ if (arg === '--') {
619
+ const next = args[i + 1];
620
+ if (next === undefined) return {};
621
+ return command ? { command: next } : stdin ? {} : { file: next };
622
+ }
623
+ if (/^-[A-Za-z]*c[A-Za-z]*$/.test(arg)) { command = true; continue; }
624
+ if (/^-[A-Za-z]*s[A-Za-z]*$/.test(arg)) { stdin = true; continue; }
625
+ if (SHELL_VALUE_OPTIONS.has(arg)) { i += 1; continue; }
626
+ if (arg.startsWith('-') || arg.startsWith('+')) continue;
627
+ return command ? { command: arg } : stdin ? {} : { file: arg };
628
+ }
629
+ return {};
630
+ }
631
+ /** The script of `bash -c "…"`, else null. */
632
+ const shellScript = (args) => shellRun(args).command ?? null;
633
+
634
+ /** How a script file runs, by its shebang (else its extension): 'shell', 'code' (JS / Python) or null (a binary, another language). */
635
+ function scriptKind(path, text) {
636
+ const shebang = /^#!\s*(\S+)(.*)/.exec(String(text).split('\n', 1)[0]);
637
+ if (shebang) {
638
+ let program = programName(shebang[1]);
639
+ if (program === 'env') program = programName(shebang[2].trim().split(/\s+/).find((word) => word && !word.startsWith('-') && !word.includes('=')) || '');
640
+ if (SHELLS.has(program)) return 'shell';
641
+ return JS_RUNTIMES.has(program) || PYTHON.test(program) ? 'code' : null;
642
+ }
643
+ if (SCRIPT_FILE.test(path)) return 'code';
644
+ return SHELL_SCRIPT_FILE.test(path) ? 'shell' : null;
645
+ }
646
+
647
+ /** Why a shell script's commands may not run (the script read like a command line), else null. */
648
+ function shellFileDenial(file, ctx, how = 'running') {
649
+ const text = readScript(ctx, resolvePath(ctx.cwd, file));
650
+ if (text === null) return null;
651
+ const why = commandDenial(text, { ...ctx, depth: ctx.depth + 1 });
652
+ return why ? `${how} ${file}, a shell script: ${why}` : null;
653
+ }
654
+
655
+ // Options that take the next word as their value, per runtime.
656
+ const NODE_VALUE_OPTIONS = new Set(['-r', '--require', '--import', '--loader', '--experimental-loader', '-C', '--conditions', '--env-file', '--input-type', '--title', '--test-name-pattern', '--test-reporter', '--test-reporter-destination', '--test-concurrency', '--test-timeout', '--test-shard', '--watch-path', '--inspect-port', '--redirect-warnings', '--disable-warning']);
657
+ const RUNTIME_VALUE_OPTIONS = {
658
+ bun: new Set(['-r', '--preload', '--cwd', '-c', '--config', '--define', '-d', '--tsconfig-override', '--env-file', '--conditions', '--main-fields', '-l', '--loader']),
659
+ deno: new Set(['-c', '--config', '--import-map', '--location', '--seed', '--lock', '--cert', '--env-file', '--ext']),
660
+ ts: new Set(['--tsconfig', '-P', '--project', '-O', '--compiler-options', '-r', '--require', '--import', '--loader', '-C', '--conditions', '--env-file', '--config', '--root', '--mode', '-I', '--ignore']),
661
+ };
662
+ const EVAL_FLAG = /^(?:--eval|--print|-[A-Za-z]*[ep])$/;
663
+
664
+ /**
665
+ * A JS runtime's arguments → { code: [inline code], script, stdin }: node,
666
+ * bun, deno, tsx, ts-node and friends. `script` "-" or none (and no code):
667
+ * the program comes from stdin.
668
+ */
669
+ function jsProgram(name, args) {
670
+ const out = { code: [], script: null };
671
+ let list = args;
672
+ let valued = NODE_VALUE_OPTIONS;
673
+ if (name === 'bun') {
674
+ valued = RUNTIME_VALUE_OPTIONS.bun;
675
+ if (list[0] === 'run') list = list.slice(1);
676
+ else if (list[0] && !list[0].startsWith('-') && !PATH_LIKE.test(list[0])) return out; // bun install / build / pm …
677
+ } else if (name === 'deno') {
678
+ valued = RUNTIME_VALUE_OPTIONS.deno;
679
+ if (list[0] === 'eval') { const code = list.slice(1).find((arg) => !arg.startsWith('-')); if (code !== undefined) out.code.push(code); return out; }
680
+ if (list[0] !== 'run') return out; // deno fmt / lint / task …
681
+ list = list.slice(1);
682
+ } else if (name !== 'node' && name !== 'nodejs') {
683
+ valued = RUNTIME_VALUE_OPTIONS.ts;
684
+ if (list[0] === 'watch') list = list.slice(1); // tsx watch <file>
685
+ }
686
+ for (let i = 0; i < list.length; i += 1) {
687
+ const arg = list[i];
688
+ if (arg === '-') { out.script = '-'; return out; }
689
+ if (arg === '--') { out.script = list[i + 1] ?? null; return out; }
690
+ if (/^--(?:eval|print)=/.test(arg)) { out.code.push(arg.slice(arg.indexOf('=') + 1)); return out; }
691
+ if (EVAL_FLAG.test(arg)) { if (list[i + 1] !== undefined) out.code.push(list[i + 1]); return out; }
692
+ if (valued.has(arg)) { i += 1; continue; }
693
+ if (arg.startsWith('-')) continue;
694
+ out.script = arg;
695
+ return out;
696
+ }
697
+ return out;
698
+ }
699
+
700
+ /** python's arguments → { code, module, script }. */
701
+ function pythonProgram(args) {
702
+ const out = { code: [], module: null, script: null };
703
+ for (let i = 0; i < args.length; i += 1) {
704
+ const arg = args[i];
705
+ if (arg === '-') { out.script = '-'; return out; }
706
+ if (arg === '--') { out.script = args[i + 1] ?? null; return out; }
707
+ if (/^-[A-Za-z]*c$/.test(arg)) { if (args[i + 1] !== undefined) out.code.push(args[i + 1]); return out; }
708
+ if (/^-c./.test(arg)) { out.code.push(arg.slice(2)); return out; }
709
+ if (/^-[A-Za-z]*m$/.test(arg)) { out.module = args[i + 1] ?? null; return out; }
710
+ if (/^-m./.test(arg)) { out.module = arg.slice(2); return out; }
711
+ if (arg === '-W' || arg === '-X' || arg === '--check-hash-based-pycs') { i += 1; continue; }
712
+ if (arg.startsWith('-')) continue;
713
+ out.script = arg;
714
+ return out;
715
+ }
716
+ return out;
717
+ }
718
+
719
+ // Programs whose file arguments are what a pipe hands an interpreter (cat pw.cjs | node).
720
+ const FILE_READERS = new Set(['cat', 'type', 'head', 'tail', 'bat', 'more', 'less']);
721
+
722
+ /** Why an interpreter's program may not run (inline code, a script file, stdin), else null. */
723
+ function interpreterDenial(name, args, seg, ctx) {
724
+ const python = PYTHON.test(name);
725
+ const program = python ? pythonProgram(args) : jsProgram(name, args);
726
+ for (const code of program.code) {
727
+ const what = codeMarker(code);
728
+ if (what) return `inline code that ${what} (${name} ${python ? '-c' : '-e'})`;
729
+ }
730
+ if (program.code.length) return null;
731
+ if (python && program.module && PYTHON_BROWSER_MODULE.test(program.module)) return `python -m ${program.module}`;
732
+ if (program.script && program.script !== '-') {
733
+ const file = resolvePath(ctx.cwd, program.script);
734
+ const what = codeMarker(readScript(ctx, file));
735
+ return what ? `running ${program.script}, a script that ${what}` : null;
736
+ }
737
+ if (python && program.module) return null;
738
+ // The program comes from stdin: a heredoc or here-string, < file, or a pipe.
739
+ for (const body of seg.heredocs) {
740
+ const what = codeMarker(body);
741
+ if (what) return `a heredoc fed to ${name} that ${what}`;
742
+ }
743
+ for (const input of seg.inputs) {
744
+ const what = codeMarker(readScript(ctx, resolvePath(ctx.cwd, input)));
745
+ if (what) return `running ${input}, a script that ${what}`;
746
+ }
747
+ const source = seg.pipedFrom ? commandWords(seg.pipedFrom.words) : [];
748
+ if (source.length) {
749
+ if (FILE_READERS.has(programName(source[0]))) {
750
+ for (const file of source.slice(1).filter((arg) => !arg.startsWith('-'))) {
751
+ const what = codeMarker(readScript(ctx, resolvePath(ctx.cwd, file)));
752
+ if (what) return `piping ${file}, a script that ${what}, into ${name}`;
753
+ }
754
+ } else {
755
+ const what = codeMarker(source.slice(1).join(' ')) || codeMarker(seg.pipedFrom.heredocs.join('\n'));
756
+ if (what) return `code piped into ${name} that ${what}`;
757
+ }
758
+ }
759
+ return null;
760
+ }
761
+
762
+ /** Why a shell whose commands come from stdin may not run them: a heredoc or here-string, < file, a pipe. */
763
+ function shellStdinDenial(name, seg, ctx) {
764
+ const inner = { ...ctx, depth: ctx.depth + 1 };
765
+ for (const body of seg.heredocs) {
766
+ const why = commandDenial(body, inner);
767
+ if (why) return why;
768
+ }
769
+ for (const input of seg.inputs) {
770
+ const why = shellFileDenial(input, ctx);
771
+ if (why) return why;
772
+ }
773
+ const source = seg.pipedFrom ? commandWords(seg.pipedFrom.words) : [];
774
+ if (!source.length) return null;
775
+ if (FILE_READERS.has(programName(source[0]))) {
776
+ for (const file of source.slice(1).filter((arg) => !arg.startsWith('-'))) {
777
+ const why = shellFileDenial(file, ctx, 'piping');
778
+ if (why) return `${why} (into ${name})`;
779
+ }
780
+ return null;
781
+ }
782
+ // echo "google-chrome --headless …" | sh
783
+ return commandDenial(source.slice(1).join(' '), inner) || commandDenial(seg.pipedFrom.heredocs.join('\n'), inner);
784
+ }
785
+
786
+ /** Why one simple command may not run, else null. `words`: the command itself (commandWords). */
787
+ function segmentDenial(words, seg, ctx) {
788
+ if (!words.length) return null;
789
+ const [head, ...args] = words;
790
+ const name = programName(head);
791
+ const browser = browserProgram(head);
792
+ if (browser) return `${browser} started from the shell`;
793
+ const flag = args.find((arg) => HEADLESS_FLAG.test(arg));
794
+ if (flag && BROWSERISH.test(name)) return `a headless browser (${name} ${flag})`;
795
+ if (name === 'open') return openDenial(args);
796
+ if (name === 'xdg-open' || name === 'gio') {
797
+ const target = args.find((arg) => URL_ARG.test(arg) || LOOPBACK_ARG.test(arg) || /\.html?$/i.test(arg));
798
+ return target ? `opening ${target} with ${name}` : null;
799
+ }
800
+ if (['sensible-browser', 'x-www-browser', 'www-browser'].includes(name)) return `${name} started from the shell`;
801
+ if (SHELLS.has(name)) {
802
+ const run = shellRun(args);
803
+ if (run.command !== undefined) return commandDenial(run.command, { ...ctx, depth: ctx.depth + 1 });
804
+ if (run.file !== undefined) return shellFileDenial(run.file, ctx);
805
+ return shellStdinDenial(name, seg, ctx);
806
+ }
807
+ // source x.sh / . x.sh: the script runs in this shell.
808
+ if (name === 'source' || name === '.') return args[0] ? shellFileDenial(args[0], ctx) : null;
809
+ if (name === 'eval') return commandDenial(args.join(' '), { ...ctx, depth: ctx.depth + 1 });
810
+ if (isTestRun(words, ctx)) return null;
811
+ const run = packageRun(words);
812
+ if (typeof run?.command === 'string') return commandDenial(run.command, { ...ctx, depth: ctx.depth + 1 });
813
+ if (run?.pkg) {
814
+ if (PLAYWRIGHT_TEST.has(run.pkg) && run.args[0] === 'test') return playwrightTestWhy(`${name} ${run.pkg}`, run.args.slice(1), ctx);
815
+ if (BROWSER_PACKAGES.has(run.pkg)) return `${name} ${run.pkg}${run.args[0] ? ` ${run.args[0]}` : ''}`;
816
+ if (JS_RUNTIMES.has(run.pkg)) return interpreterDenial(run.pkg, run.args, seg, ctx);
817
+ return null;
818
+ }
819
+ if (name === 'playwright' && args[0] === 'test') return playwrightTestWhy(name, args.slice(1), ctx);
820
+ if (BROWSER_CLIS.has(name)) return `${name}${args[0] ? ` ${args[0]}` : ''} (a browser CLI)`;
821
+ if (JS_RUNTIMES.has(name) || PYTHON.test(name)) return interpreterDenial(name, args, seg, ctx);
822
+ // A script run as a program (./shot.sh, ./pw.cjs, /tmp/x): by its shebang, else its extension.
823
+ if (/[/\\]/.test(head)) {
824
+ const text = readScript(ctx, resolvePath(ctx.cwd, head));
825
+ if (text === null) return null;
826
+ const kind = scriptKind(head, text);
827
+ if (kind === 'shell') {
828
+ const why = commandDenial(text, { ...ctx, depth: ctx.depth + 1 });
829
+ return why ? `running ${head}, a shell script: ${why}` : null;
830
+ }
831
+ const what = kind === 'code' ? codeMarker(text) : null;
832
+ return what ? `running ${head}, a script that ${what}` : null;
833
+ }
834
+ return null;
835
+ }
836
+
837
+ /** Why a command line may not run (what it does, for the refusal), else null. */
838
+ function commandDenial(text, ctx) {
839
+ if (ctx.depth > MAX_DEPTH) return null;
840
+ let cwd = ctx.cwd;
841
+ for (const seg of simpleCommands(text)) {
842
+ const words = commandWords(seg.words);
843
+ // `cd dir && node pw.cjs`: the rest of the line runs there (a bare cd: the home folder).
844
+ if (words[0] === 'cd' || words[0] === 'pushd') {
845
+ const dir = words.slice(1).find((arg) => !arg.startsWith('-'));
846
+ if (dir) cwd = resolvePath(cwd, dir);
847
+ else if (words[0] === 'cd' && words.length === 1) cwd = homedir();
848
+ continue;
849
+ }
850
+ const why = segmentDenial(words, seg, { ...ctx, cwd });
851
+ if (why) return why;
852
+ }
853
+ return null;
854
+ }
855
+
856
+ /** A shell tool's command: a string (a command line) or an argv array (Codex). */
857
+ function argvDenial(argv, ctx) {
858
+ const words = commandWords(argv.map((arg) => String(arg ?? '')));
859
+ if (!words.length) return null;
860
+ if (SHELLS.has(programName(words[0]))) {
861
+ const script = shellScript(words.slice(1));
862
+ if (script !== null) return commandDenial(script, ctx);
863
+ }
864
+ return segmentDenial(words, { words, heredocs: [], inputs: [], pipedFrom: null }, ctx);
865
+ }
866
+
867
+ // Where each host puts a shell tool's command and its working directory.
868
+ const COMMAND_KEYS = ['command', 'cmd', 'commands', 'script'];
869
+ const WORKDIR_KEYS = ['workdir', 'cwd', 'working_directory', 'workingDirectory', 'dir'];
870
+
871
+ function shellDenial(input, ctx) {
872
+ const args = input && typeof input === 'object' ? input : {};
873
+ const action = args.action && typeof args.action === 'object' ? args.action : {};
874
+ const workdir = [...WORKDIR_KEYS.map((key) => args[key]), ...WORKDIR_KEYS.map((key) => action[key])]
875
+ .find((value) => typeof value === 'string' && isAbsolute(value));
876
+ const inner = { ...ctx, cwd: workdir || ctx.cwd };
877
+ for (const value of [...COMMAND_KEYS.map((key) => args[key]), action.command]) {
878
+ if (typeof value === 'string' && value.trim()) {
879
+ const why = commandDenial(value, inner);
880
+ if (why) return why;
881
+ } else if (Array.isArray(value) && value.length) {
882
+ const why = argvDenial(value, inner);
883
+ if (why) return why;
884
+ }
885
+ }
886
+ return null;
887
+ }
888
+
889
+ // ── the refusal ─────────────────────────────────────────────────────────────
890
+
891
+ function refusal(tool, what) {
892
+ return `SynaBun browser policy: ${tool} was refused — ${what}. Every page, public or localhost, goes through SynaBun's browser tools (browser_navigate, browser_snapshot, browser_screenshot, browser_console and the other browser_* tools), which open the browser configured in SynaBun. If the SynaBun browser fails or cannot do this, stop and report it; do not switch to another browser or tool. The project's own automated tests still run through its test runner (npm test, node --test, npx playwright test).`;
893
+ }
894
+
895
+ /**
896
+ * Why this tool call may not run under the browser policy (the refusal text),
897
+ * else null. `host`: claude / codex / opencode (null: any). `cwd`: the
898
+ * project directory: relative script paths resolve against it, and a test
899
+ * runner's files must lie inside it. `readFile(path)` returns an executed
900
+ * script's text or null (tests); by default a regular file up to
901
+ * MAX_SCRIPT_BYTES is read, and anything unreadable is allowed.
902
+ */
903
+ export function browserToolDenial(tool, input = {}, { host = null, cwd = null, readFile = defaultReadFile } = {}) {
904
+ const name = String(tool ?? '').trim();
905
+ if (!name) return null;
906
+ const kind = hostKey(host);
907
+ const mcp = browserMcpTool(name, kind);
908
+ if (mcp) return refusal(name, mcp);
909
+ const base = synabunLeaf(name) ?? name;
910
+ const lower = base.toLowerCase();
911
+ const args = input && typeof input === 'object' && !Array.isArray(input) ? input : {};
912
+ // Computer use on a browser is refused where the desktop resolves its target
913
+ // (lib/desktop/guards.js); here only an app named in the call is caught early.
914
+ if (lower === 'computer_apps') {
915
+ const action = String(args.action || '').toLowerCase();
916
+ const app = browserApp(args.app);
917
+ if ((action === 'open' || action === 'focus') && app) return refusal(name, `${action === 'open' ? 'opening' : 'focusing'} ${app} with computer use`);
918
+ return null;
919
+ }
920
+ if (isSynabunTool(name) || /^mcp__/i.test(name)) return null;
921
+ if (WEB_TOOLS.has(lower)) return refusal(name, 'web search / fetch outside the SynaBun browser');
922
+ if (!SHELL_TOOLS.has(lower)) return null;
923
+ const project = cwd ? resolve(String(cwd)) : process.cwd();
924
+ const why = shellDenial(args, { project, cwd: project, readFile: typeof readFile === 'function' ? readFile : defaultReadFile, depth: 0 });
925
+ return why ? refusal(name, why) : null;
926
+ }