synabun 2.0.0 → 2.0.7

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 (507) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/NOTICE +5 -0
  3. package/README.md +2 -1
  4. package/THIRD-PARTY-LICENSES.md +59 -0
  5. package/benchmarks/fixtures/browser/README.md +1 -1
  6. package/benchmarks/fixtures/desktop/README.md +1 -1
  7. package/docs/whatsapp.md +153 -18
  8. package/hooks/claude-code/pre-compact.mjs +11 -0
  9. package/hooks/claude-code/prompt-submit.mjs +60 -184
  10. package/hooks/claude-code/session-start.mjs +73 -16
  11. package/hooks/claude-code/shared.mjs +26 -3
  12. package/hooks/claude-code/stop.mjs +5 -5
  13. package/lib/child-path.js +303 -0
  14. package/lib/claude-hooks.js +2 -1
  15. package/lib/data-home-migration.js +2 -0
  16. package/lib/desktop-app.js +265 -0
  17. package/lib/external-tools.js +7 -3
  18. package/lib/log-redact.js +102 -0
  19. package/lib/packaged-runtime.js +138 -11
  20. package/lib/start-launcher.js +88 -1
  21. package/mcp-server/dist/http.d.ts +3 -1
  22. package/mcp-server/dist/http.d.ts.map +1 -1
  23. package/mcp-server/dist/http.js +15 -4
  24. package/mcp-server/dist/http.js.map +1 -1
  25. package/mcp-server/dist/index.d.ts.map +1 -1
  26. package/mcp-server/dist/index.js +9 -6
  27. package/mcp-server/dist/index.js.map +1 -1
  28. package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
  29. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
  30. package/mcp-server/dist/services/budget-judgments.js +153 -0
  31. package/mcp-server/dist/services/budget-judgments.js.map +1 -0
  32. package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
  33. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  34. package/mcp-server/dist/services/codex-config-heal.js +41 -4
  35. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  36. package/mcp-server/dist/services/identity.d.ts +11 -0
  37. package/mcp-server/dist/services/identity.d.ts.map +1 -1
  38. package/mcp-server/dist/services/identity.js +24 -0
  39. package/mcp-server/dist/services/identity.js.map +1 -1
  40. package/mcp-server/dist/services/neural-interface.d.ts +13 -0
  41. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  42. package/mcp-server/dist/services/neural-interface.js +34 -2
  43. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  44. package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
  45. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
  46. package/mcp-server/dist/services/typesafe-config.js +4 -1
  47. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  48. package/mcp-server/dist/tools/agents.d.ts +10 -7
  49. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  50. package/mcp-server/dist/tools/agents.js +34 -13
  51. package/mcp-server/dist/tools/agents.js.map +1 -1
  52. package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
  53. package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
  54. package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
  55. package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
  56. package/mcp-server/dist/tui.js +2 -1
  57. package/mcp-server/dist/tui.js.map +1 -1
  58. package/mcp-server/dist/version.d.ts +5 -0
  59. package/mcp-server/dist/version.d.ts.map +1 -0
  60. package/mcp-server/dist/version.js +21 -0
  61. package/mcp-server/dist/version.js.map +1 -0
  62. package/mcp-server/package-lock.json +2 -2
  63. package/mcp-server/package.json +1 -3
  64. package/mcp-server/run.mjs +15 -9
  65. package/mcp-server/src/http.ts +18 -3
  66. package/mcp-server/src/index.ts +9 -6
  67. package/mcp-server/src/services/budget-judgments.ts +183 -0
  68. package/mcp-server/src/services/codex-config-heal.ts +35 -4
  69. package/mcp-server/src/services/identity.ts +27 -0
  70. package/mcp-server/src/services/neural-interface.ts +34 -2
  71. package/mcp-server/src/services/typesafe-config.ts +4 -1
  72. package/mcp-server/src/tools/agents.ts +33 -14
  73. package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
  74. package/mcp-server/src/tui.ts +2 -1
  75. package/mcp-server/src/version.ts +22 -0
  76. package/neural-interface/i18n/en.json +2126 -209
  77. package/neural-interface/i18n/pt-BR.json +2123 -207
  78. package/neural-interface/lib/account-usage.js +163 -0
  79. package/neural-interface/lib/assistant-api.js +316 -57
  80. package/neural-interface/lib/assistant-brains/claude.js +19 -2
  81. package/neural-interface/lib/assistant-brains/codex.js +3 -0
  82. package/neural-interface/lib/assistant-brains/opencode.js +17 -4
  83. package/neural-interface/lib/assistant-budget-planner.js +390 -0
  84. package/neural-interface/lib/assistant-budget-split.js +408 -0
  85. package/neural-interface/lib/assistant-budget.js +94 -95
  86. package/neural-interface/lib/assistant-catalog.js +179 -27
  87. package/neural-interface/lib/assistant-config.js +91 -14
  88. package/neural-interface/lib/assistant-dispatch.js +494 -138
  89. package/neural-interface/lib/assistant-hidden-models.js +393 -66
  90. package/neural-interface/lib/assistant-jev.js +26 -3
  91. package/neural-interface/lib/assistant-memory.js +24 -10
  92. package/neural-interface/lib/assistant-persona.js +73 -12
  93. package/neural-interface/lib/assistant-plan-permissions.js +8 -1
  94. package/neural-interface/lib/assistant-pricing.js +21 -6
  95. package/neural-interface/lib/assistant-route-accounts.js +14 -0
  96. package/neural-interface/lib/assistant-route-gate.js +19 -3
  97. package/neural-interface/lib/assistant-router.js +373 -42
  98. package/neural-interface/lib/assistant-runtime.js +488 -59
  99. package/neural-interface/lib/assistant-task-prompt.js +13 -3
  100. package/neural-interface/lib/assistant-test-density.js +142 -0
  101. package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
  102. package/neural-interface/lib/assistant-user-context.js +908 -0
  103. package/neural-interface/lib/assistant-user-knowledge.js +328 -0
  104. package/neural-interface/lib/assistant-user-learn.js +404 -0
  105. package/neural-interface/lib/assistant-user-threads.js +226 -0
  106. package/neural-interface/lib/assistant-user-writer.js +183 -0
  107. package/neural-interface/lib/augmented-path.js +317 -53
  108. package/neural-interface/lib/browser-background-tab.js +134 -0
  109. package/neural-interface/lib/browser-screenshot.js +678 -61
  110. package/neural-interface/lib/claude-accounts.js +342 -31
  111. package/neural-interface/lib/claude-agent-bridge.js +123 -9
  112. package/neural-interface/lib/claude-executable.js +6 -1
  113. package/neural-interface/lib/claude-model-catalog.js +33 -5
  114. package/neural-interface/lib/claude-panel-auth.js +221 -0
  115. package/neural-interface/lib/claude-profile-api-key.js +62 -0
  116. package/neural-interface/lib/claude-temporary.js +46 -7
  117. package/neural-interface/lib/cli-install-api.js +137 -0
  118. package/neural-interface/lib/cli-install.js +797 -0
  119. package/neural-interface/lib/cli-path.js +130 -0
  120. package/neural-interface/lib/cli-resolver.js +744 -0
  121. package/neural-interface/lib/cli-update-planner.js +143 -7
  122. package/neural-interface/lib/cloudflared/install.js +533 -0
  123. package/neural-interface/lib/cloudflared/manager.js +545 -0
  124. package/neural-interface/lib/cloudflared/pins.js +115 -0
  125. package/neural-interface/lib/cloudflared/pins.json +63 -0
  126. package/neural-interface/lib/cloudflared/tunnel.js +265 -0
  127. package/neural-interface/lib/codex-account-auth.js +178 -0
  128. package/neural-interface/lib/codex-accounts.js +489 -0
  129. package/neural-interface/lib/codex-capabilities.js +2 -1
  130. package/neural-interface/lib/codex-compat-rpc.js +8 -2
  131. package/neural-interface/lib/codex-mcp-approvals.js +5 -1
  132. package/neural-interface/lib/codex-panel-auth.js +62 -0
  133. package/neural-interface/lib/codex-session-settings.js +1 -1
  134. package/neural-interface/lib/codex-settings-schema.js +120 -0
  135. package/neural-interface/lib/desktop/config.js +3 -0
  136. package/neural-interface/lib/editor-completion-endpoint.js +264 -0
  137. package/neural-interface/lib/editor-completion-opencode.js +436 -0
  138. package/neural-interface/lib/editor-completion.js +714 -0
  139. package/neural-interface/lib/editor-config.js +149 -0
  140. package/neural-interface/lib/editor-files-api.js +268 -0
  141. package/neural-interface/lib/editor-git-api.js +134 -0
  142. package/neural-interface/lib/file-explorer-api.js +1039 -0
  143. package/neural-interface/lib/file-explorer-system.js +355 -0
  144. package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
  145. package/neural-interface/lib/file-explorer-watch.js +239 -0
  146. package/neural-interface/lib/git-bash/bzip2.js +339 -0
  147. package/neural-interface/lib/git-bash/claude-settings.js +73 -0
  148. package/neural-interface/lib/git-bash/extract-worker.js +34 -0
  149. package/neural-interface/lib/git-bash/install.js +529 -0
  150. package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
  151. package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
  152. package/neural-interface/lib/git-bash/manager.js +268 -0
  153. package/neural-interface/lib/git-bash/pins.js +206 -0
  154. package/neural-interface/lib/git-bash/pins.json +34 -0
  155. package/neural-interface/lib/git-bash/resolver.js +194 -0
  156. package/neural-interface/lib/git-diff-api.js +103 -0
  157. package/neural-interface/lib/git-read.js +234 -0
  158. package/neural-interface/lib/greeting/api.js +89 -0
  159. package/neural-interface/lib/greeting/budgets.js +90 -0
  160. package/neural-interface/lib/greeting/engine.js +461 -0
  161. package/neural-interface/lib/greeting/facts.js +320 -0
  162. package/neural-interface/lib/greeting/sources.js +252 -0
  163. package/neural-interface/lib/greeting/writer.js +139 -0
  164. package/neural-interface/lib/http-guards.js +189 -13
  165. package/neural-interface/lib/install-details.js +145 -0
  166. package/neural-interface/lib/machine-names.js +88 -0
  167. package/neural-interface/lib/mcp-installer.js +14 -2
  168. package/neural-interface/lib/memory-api.js +31 -7
  169. package/neural-interface/lib/native-loop-providers.js +26 -8
  170. package/neural-interface/lib/native-loop-runtime.js +9 -4
  171. package/neural-interface/lib/os-path.js +319 -0
  172. package/neural-interface/lib/plugin-installer.js +4 -2
  173. package/neural-interface/lib/project-storage.js +5 -7
  174. package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
  175. package/neural-interface/lib/provider-panel-terminal-auth.js +95 -0
  176. package/neural-interface/lib/pty-host/core.js +2 -1
  177. package/neural-interface/lib/pty-host/manager.js +27 -2
  178. package/neural-interface/lib/remote-policy.js +20 -11
  179. package/neural-interface/lib/request-gate.js +589 -0
  180. package/neural-interface/lib/session-title-generator.js +4 -3
  181. package/neural-interface/lib/system-about.js +340 -0
  182. package/neural-interface/lib/system-activity.js +66 -0
  183. package/neural-interface/lib/terminal-env.js +11 -3
  184. package/neural-interface/lib/terminal-path.js +55 -0
  185. package/neural-interface/lib/ui-blob-api.js +108 -0
  186. package/neural-interface/lib/ui-blob-store.js +68 -0
  187. package/neural-interface/lib/virtual-socket.js +12 -1
  188. package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
  189. package/neural-interface/lib/whatsapp/bridge.js +78 -34
  190. package/neural-interface/lib/whatsapp/commands.js +13 -14
  191. package/neural-interface/lib/whatsapp/config.js +134 -20
  192. package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
  193. package/neural-interface/lib/whatsapp/host-core.js +168 -35
  194. package/neural-interface/lib/whatsapp/inbound.js +5 -3
  195. package/neural-interface/lib/whatsapp/local-file.js +524 -0
  196. package/neural-interface/lib/whatsapp/manager.js +92 -32
  197. package/neural-interface/lib/whatsapp/paths.js +11 -1
  198. package/neural-interface/lib/whatsapp/protocol.js +65 -5
  199. package/neural-interface/lib/whatsapp/redact.js +63 -0
  200. package/neural-interface/lib/whatsapp/service.js +343 -91
  201. package/neural-interface/lib/whatsapp/transcription.js +463 -0
  202. package/neural-interface/package-lock.json +701 -2
  203. package/neural-interface/package.json +13 -2
  204. package/neural-interface/public/index.html +2 -0
  205. package/neural-interface/public/index2d.html +2 -0
  206. package/neural-interface/public/install-app.html +9 -6
  207. package/neural-interface/public/offline.html +19 -3
  208. package/neural-interface/public/onboarding.html +107 -2
  209. package/neural-interface/public/shared/account-i18n.js +7 -0
  210. package/neural-interface/public/shared/account-menu.js +539 -0
  211. package/neural-interface/public/shared/account-usage.js +19 -0
  212. package/neural-interface/public/shared/account-view.js +335 -0
  213. package/neural-interface/public/shared/agent-runtime-options.js +50 -14
  214. package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
  215. package/neural-interface/public/shared/assistant/asst-api.js +32 -2
  216. package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
  217. package/neural-interface/public/shared/assistant/asst-brain-picker.js +430 -81
  218. package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
  219. package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
  220. package/neural-interface/public/shared/assistant/asst-mascot.js +140 -61
  221. package/neural-interface/public/shared/assistant/asst-menu.js +27 -11
  222. package/neural-interface/public/shared/assistant/asst-panel.js +198 -42
  223. package/neural-interface/public/shared/assistant/asst-render.js +197 -23
  224. package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
  225. package/neural-interface/public/shared/assistant/asst-route.js +95 -343
  226. package/neural-interface/public/shared/assistant/asst-routes-editor.js +534 -0
  227. package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
  228. package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
  229. package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
  230. package/neural-interface/public/shared/assistant/asst-state.js +186 -2
  231. package/neural-interface/public/shared/assistant/asst-styles.js +247 -11
  232. package/neural-interface/public/shared/blob-store.js +111 -22
  233. package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
  234. package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
  235. package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
  236. package/neural-interface/public/shared/cdx/cdx-panel.js +80 -118
  237. package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
  238. package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
  239. package/neural-interface/public/shared/cdx/cdx-styles.js +164 -107
  240. package/neural-interface/public/shared/cdx/cdx-tabs.js +348 -668
  241. package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
  242. package/neural-interface/public/shared/claude-account-view.js +3 -0
  243. package/neural-interface/public/shared/cli-install-view.js +392 -0
  244. package/neural-interface/public/shared/cli-status.js +282 -22
  245. package/neural-interface/public/shared/constants.js +6 -1
  246. package/neural-interface/public/shared/cp/cp-events.js +2 -1
  247. package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
  248. package/neural-interface/public/shared/cp/cp-styles.js +61 -0
  249. package/neural-interface/public/shared/desktop-bridge.js +39 -0
  250. package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
  251. package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
  252. package/neural-interface/public/shared/desktop-titlebar.js +153 -0
  253. package/neural-interface/public/shared/desktop-update-view.js +462 -0
  254. package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
  255. package/neural-interface/public/shared/editor/editor-ai.js +619 -0
  256. package/neural-interface/public/shared/editor/editor-commands.js +212 -0
  257. package/neural-interface/public/shared/editor/editor-compare.js +103 -0
  258. package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
  259. package/neural-interface/public/shared/editor/editor-doc.js +257 -0
  260. package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
  261. package/neural-interface/public/shared/editor/editor-git.js +95 -0
  262. package/neural-interface/public/shared/editor/editor-languages.js +156 -0
  263. package/neural-interface/public/shared/editor/editor-lint.js +229 -0
  264. package/neural-interface/public/shared/editor/editor-loader.js +51 -0
  265. package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
  266. package/neural-interface/public/shared/editor/editor-menu.js +233 -0
  267. package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
  268. package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
  269. package/neural-interface/public/shared/editor/editor-palette.js +125 -0
  270. package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
  271. package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
  272. package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
  273. package/neural-interface/public/shared/editor/editor-safety.js +500 -0
  274. package/neural-interface/public/shared/editor/editor-search.js +352 -0
  275. package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
  276. package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
  277. package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
  278. package/neural-interface/public/shared/editor/editor-theme.js +244 -0
  279. package/neural-interface/public/shared/editor/editor-view.js +332 -0
  280. package/neural-interface/public/shared/explorer/fx-api.js +216 -0
  281. package/neural-interface/public/shared/explorer/fx-links.js +204 -0
  282. package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
  283. package/neural-interface/public/shared/explorer/fx-main.js +865 -0
  284. package/neural-interface/public/shared/explorer/fx-names.js +87 -0
  285. package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
  286. package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
  287. package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
  288. package/neural-interface/public/shared/file-links.js +339 -0
  289. package/neural-interface/public/shared/git-bash-view.js +145 -0
  290. package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
  291. package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
  292. package/neural-interface/public/shared/html-shell.js +161 -165
  293. package/neural-interface/public/shared/i18n.js +19 -1
  294. package/neural-interface/public/shared/install-details-view.js +86 -0
  295. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
  296. package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
  297. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +131 -17
  298. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
  299. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +22 -0
  300. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +158 -0
  301. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
  302. package/neural-interface/public/shared/pwa-install-page.js +32 -2
  303. package/neural-interface/public/shared/pwa-install.css +3 -3
  304. package/neural-interface/public/shared/pwa-install.js +100 -1
  305. package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
  306. package/neural-interface/public/shared/settings/settings-about.js +254 -0
  307. package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
  308. package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
  309. package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
  310. package/neural-interface/public/shared/settings/settings-ia.js +33 -4
  311. package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
  312. package/neural-interface/public/shared/showcase-privacy.js +489 -0
  313. package/neural-interface/public/shared/start-bridge.js +238 -19
  314. package/neural-interface/public/shared/storage.js +30 -3
  315. package/neural-interface/public/shared/styles.css +1710 -770
  316. package/neural-interface/public/shared/synabun-mascot.js +68 -58
  317. package/neural-interface/public/shared/tunnel-view.js +167 -0
  318. package/neural-interface/public/shared/ui-claude-panel.js +369 -229
  319. package/neural-interface/public/shared/ui-cli-banner.js +355 -0
  320. package/neural-interface/public/shared/ui-detail.js +15 -0
  321. package/neural-interface/public/shared/ui-explorer.js +22 -0
  322. package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
  323. package/neural-interface/public/shared/ui-file-links.js +103 -0
  324. package/neural-interface/public/shared/ui-git-bash.js +124 -0
  325. package/neural-interface/public/shared/ui-help.js +26 -0
  326. package/neural-interface/public/shared/ui-invite.js +126 -116
  327. package/neural-interface/public/shared/ui-judgments.js +10 -1
  328. package/neural-interface/public/shared/ui-keybinds.js +4 -0
  329. package/neural-interface/public/shared/ui-loading.js +187 -19
  330. package/neural-interface/public/shared/ui-menubar.js +25 -33
  331. package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
  332. package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
  333. package/neural-interface/public/shared/ui-navbar.js +48 -22
  334. package/neural-interface/public/shared/ui-provider-auth.js +104 -0
  335. package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
  336. package/neural-interface/public/shared/ui-sessions.js +9 -3
  337. package/neural-interface/public/shared/ui-settings.js +509 -490
  338. package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
  339. package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
  340. package/neural-interface/public/shared/ui-sync.js +22 -0
  341. package/neural-interface/public/shared/ui-terminal.js +40 -5
  342. package/neural-interface/public/shared/ui-tool-updates.js +5 -0
  343. package/neural-interface/public/shared/ui-tunnel.js +130 -0
  344. package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
  345. package/neural-interface/public/shared/ui-update.js +594 -5
  346. package/neural-interface/public/shared/ui-whatsapp.js +21 -6
  347. package/neural-interface/public/shared/ui-whiteboard.js +12 -0
  348. package/neural-interface/public/shared/ui-worker-end.js +245 -0
  349. package/neural-interface/public/shared/ui-workspaces.js +41 -27
  350. package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
  351. package/neural-interface/public/shared/worker-end.js +253 -0
  352. package/neural-interface/public/sw.js +2 -2
  353. package/neural-interface/public/variant/2d/main.js +10 -1
  354. package/neural-interface/public/variant/3d/main.js +10 -1
  355. package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
  356. package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
  357. package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
  358. package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
  359. package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
  360. package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
  361. package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
  362. package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
  363. package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
  364. package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
  365. package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
  366. package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
  367. package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
  368. package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
  369. package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
  370. package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
  371. package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
  372. package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
  373. package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
  374. package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
  375. package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
  376. package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
  377. package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
  378. package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
  379. package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
  380. package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
  381. package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
  382. package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
  383. package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
  384. package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
  385. package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
  386. package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
  387. package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
  388. package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
  389. package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
  390. package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
  391. package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
  392. package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
  393. package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
  394. package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
  395. package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
  396. package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
  397. package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
  398. package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
  399. package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
  400. package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
  401. package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
  402. package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
  403. package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
  404. package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
  405. package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
  406. package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
  407. package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
  408. package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
  409. package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
  410. package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
  411. package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
  412. package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
  413. package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
  414. package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
  415. package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
  416. package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
  417. package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
  418. package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
  419. package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
  420. package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
  421. package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
  422. package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
  423. package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
  424. package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
  425. package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
  426. package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
  427. package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
  428. package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
  429. package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
  430. package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
  431. package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
  432. package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
  433. package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
  434. package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
  435. package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
  436. package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
  437. package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
  438. package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
  439. package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
  440. package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
  441. package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
  442. package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
  443. package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
  444. package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
  445. package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
  446. package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
  447. package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
  448. package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
  449. package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
  450. package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
  451. package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
  452. package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
  453. package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
  454. package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
  455. package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
  456. package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
  457. package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
  458. package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
  459. package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
  460. package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
  461. package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
  462. package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
  463. package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
  464. package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
  465. package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
  466. package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
  467. package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
  468. package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
  469. package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
  470. package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
  471. package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
  472. package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
  473. package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
  474. package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
  475. package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
  476. package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
  477. package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
  478. package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
  479. package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
  480. package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
  481. package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
  482. package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
  483. package/neural-interface/scripts/build-vendor.mjs +78 -2
  484. package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
  485. package/neural-interface/server.js +2085 -1629
  486. package/neural-interface/templates/rulesets/README.md +1 -1
  487. package/package.json +5 -8
  488. package/setup.js +53 -15
  489. package/benchmarks/browser-live-results.json +0 -79
  490. package/benchmarks/browser-v2-results.json +0 -258
  491. package/neural-interface/lib/codex-capabilities.d.ts +0 -41
  492. package/neural-interface/public/category-logos/claude.svg +0 -1
  493. package/neural-interface/public/category-logos/gemini-color.svg +0 -1
  494. package/neural-interface/public/category-logos/openai.svg +0 -1
  495. package/neural-interface/public/category-logos/synabun.png +0 -0
  496. package/neural-interface/public/claude.svg +0 -1
  497. package/neural-interface/public/gallery.svg +0 -6
  498. package/neural-interface/public/leonardoai.svg +0 -1
  499. package/neural-interface/public/mcp.svg +0 -4
  500. package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
  501. package/neural-interface/public/pin-svgrepo-com.svg +0 -25
  502. package/neural-interface/public/sessionicon.svg +0 -8
  503. package/neural-interface/public/toolbar-album.svg +0 -8
  504. package/neural-interface/public/toolbar-question.svg +0 -6
  505. package/neural-interface/public/toolbar-sessions.svg +0 -6
  506. package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
  507. package/skills/synabun/synabunicon.png +0 -0
@@ -0,0 +1,231 @@
1
+ import { t, getLocale } from '../i18n.js';
2
+ import { accountSummary } from '../account-view.js';
3
+ import { configChanges, configRestriction, configValue, SESSION_CONFIG_FIELDS, sessionSettings, modelServiceTiers, capabilityAvailability } from './cdx-commands.js';
4
+ import { mountCodexAccountSecurity } from './cdx-features.js';
5
+
6
+ const overrideValue = (field, value) => field === 'sandboxPolicy' && value ? ({ readOnly: 'read-only', workspaceWrite: 'workspace-write', dangerFullAccess: 'danger-full-access' })[value.type] ?? null : value;
7
+ const tr = (key, params) => t(`codexSettings.${key}`, params);
8
+ const el = (tag, cls, text) => { const node = document.createElement(tag); if (cls) node.className = cls; if (text != null) node.textContent = text; return node; };
9
+ const metadata = [
10
+ ['model', 'model', 'models'], ['review_model', 'reviewModel', 'models'],
11
+ ['model_reasoning_effort', 'effort', 'models'], ['model_reasoning_summary', 'summary', 'models'],
12
+ ['service_tier', 'serviceTier', 'models'], ['personality', 'personality', 'models'],
13
+ ['approval_policy', 'approval', 'permissions'], ['sandbox_mode', 'sandbox', 'permissions'],
14
+ ['web_search', 'webSearch', 'tools'], ['model_provider', 'provider', 'advanced'],
15
+ ['model_verbosity', 'verbosity', 'advanced'], ['model_context_window', 'contextWindow', 'advanced'],
16
+ ['model_auto_compact_token_limit', 'autoCompact', 'advanced'],
17
+ ];
18
+ export function codexSettingsDefinitions(schema, models, cfg) {
19
+ const model = models.find(m => (m.model || m.id) === cfg.model) || models.find(m => m.isDefault) || models[0];
20
+ const modelOptions = models.map(m => ({ value: m.model || m.id, label: m.displayName || m.label || m.model || m.id }));
21
+ return metadata.flatMap(([key, label, section]) => {
22
+ const field = schema.fields?.[key]; if (!field) return [];
23
+ if (key === 'service_tier' && cfg.model_provider && cfg.model_provider !== 'openai') return [];
24
+ let options = (field.values || []).map(value => ({ value, label: tr(`values.${value}`) === `codexSettings.values.${value}` ? value : tr(`values.${value}`) }));
25
+ if (key === 'model' || key === 'review_model') options = modelOptions;
26
+ if (key === 'model_reasoning_effort') options = (model?.supportedReasoningEfforts || []).map(e => ({ value: e.reasoningEffort, label: e.reasoningEffort }));
27
+ if (key === 'service_tier') options = modelServiceTiers(model);
28
+ if (key === 'personality' && !model?.supportsPersonality) return [];
29
+ // The provider list is configured locally. Built-in OpenAI plus named providers.
30
+ if (key === 'model_provider') options = [...new Set(['openai', ...Object.keys(cfg.model_providers || {}), cfg.model_provider].filter(Boolean))].map(value => ({ value, label: value }));
31
+ if (field.type !== 'number' && !options.length) return [];
32
+ return [{ key, label: tr(label), section, type: field.type, options: [{ value: '', label: tr('default') }, ...options] }];
33
+ });
34
+ }
35
+
36
+ export async function mountCodexSettings({ host, tab, request, capabilities, account, models, normalizeConfig, manageAccount, authenticate, onSaved }) {
37
+ if (host.querySelector('.cxp-settings-overlay')) return;
38
+ const previousFocus = document.activeElement;
39
+ const overlay = el('div', 'cxp-settings-overlay');
40
+ const panel = el('div', 'cxp-settings-panel'); panel.setAttribute('role', 'dialog'); panel.setAttribute('aria-modal', 'true'); panel.setAttribute('aria-label', tr('title'));
41
+ const header = el('div', 'cxp-settings-header');
42
+ const close = el('button', 'cxp-settings-close', '×'); close.setAttribute('aria-label', tr('close'));
43
+ const dismiss = () => { overlay.remove(); if (previousFocus?.isConnected) previousFocus.focus(); };
44
+ close.onclick = dismiss; header.append(el('span', '', tr('title')), close);
45
+ const body = el('div', 'cxp-settings-body'); const sections = {};
46
+ for (const key of ['account', 'models', 'permissions', 'tools', 'advanced']) {
47
+ const group = el(key === 'advanced' ? 'details' : 'section', 'cxp-settings-section'); group.dataset.section = key;
48
+ group.append(el(key === 'advanced' ? 'summary' : 'h3', 'cxp-settings-section-title', tr(key)));
49
+ const content = el('div', 'cxp-settings-group'); group.append(content); sections[key] = content; body.append(group);
50
+ }
51
+ const result = el('div', 'cxp-settings-result'); result.setAttribute('role', 'status');
52
+ const footer = el('div', 'cxp-settings-footer');
53
+ panel.append(header, body, footer); overlay.append(panel); host.append(overlay);
54
+ const error = message => { result.textContent = tr('error', { message }); result.dataset.error = 'true'; };
55
+ overlay.onclick = event => { if (event.target === overlay) dismiss(); };
56
+ overlay.onkeydown = event => {
57
+ if (event.key === 'Escape') { event.stopPropagation(); dismiss(); }
58
+ if (event.key === 'Tab') {
59
+ const controls = [...panel.querySelectorAll('button,select,input,summary,a[href]')].filter(n => !n.disabled && n.getClientRects().length);
60
+ if (event.shiftKey && document.activeElement === controls[0]) { event.preventDefault(); controls.at(-1)?.focus(); }
61
+ else if (!event.shiftKey && document.activeElement === controls.at(-1)) { event.preventDefault(); controls[0]?.focus(); }
62
+ }
63
+ };
64
+ close.focus();
65
+ footer.append(result);
66
+ const action = (label, fn) => {
67
+ const button = el('button', 'cxp-btn cxp-btn-sm', label); button.type = 'button';
68
+ button.onclick = async () => { button.disabled = true; try { await fn(); } catch (failure) { error(failure.message); } finally { if (button.isConnected) button.disabled = false; } };
69
+ return button;
70
+ };
71
+ sections.account.append(el('div', 'cxp-settings-loading', tr('loading')));
72
+ try {
73
+ const [configData, mcpData, permissions, limits, requirements, accountData] = await Promise.allSettled([
74
+ request('config_read', { cwd: tab.project || null, threadId: tab.threadId || null }), request('mcp_status'),
75
+ request('permission_roots_list'), request('rate_limits_read'), request('config_requirements'),
76
+ request('account_read'),
77
+ ]);
78
+ if (!overlay.isConnected || tab.closed) return;
79
+ sections.account.replaceChildren();
80
+ const details = el('div', 'cxp-settings-account-details'); details.dataset.codexAccountDetails = 'true';
81
+ const currentAccount = accountData.status === 'fulfilled' ? (accountData.value?.accountState || account) : account;
82
+ details.append(el('div', 'cxp-settings-value', currentAccount ? accountSummary(currentAccount, 'codex') : tr('defaultAccount')));
83
+ const rateLimits = limits.status === 'fulfilled' ? limits.value?.rateLimits : null;
84
+ const buckets = Object.values(rateLimits?.rateLimitsByLimitId || {});
85
+ if (!buckets.length && rateLimits?.rateLimits) buckets.push(rateLimits.rateLimits);
86
+ for (const bucket of buckets) {
87
+ const percent = bucket.primary?.usedPercent;
88
+ if (!Number.isFinite(percent)) continue;
89
+ const time = bucket.primary?.resetsAt ? new Date(bucket.primary.resetsAt * 1000).toLocaleString(getLocale()) : tr('unknown');
90
+ details.append(el('div', 'cxp-settings-hint', tr('usage', { name: bucket.limitName || bucket.limitId || 'Codex', percent: Math.round(percent), time })));
91
+ }
92
+ details.append(action(tr('manage'), () => { dismiss(); manageAccount(); })); sections.account.append(details);
93
+ await mountCodexAccountSecurity({ host: sections.account, experimentalHost: sections.advanced, request, tab, capabilities });
94
+ const runtime = tab.codexRuntime || {};
95
+ sections.advanced.append(el('div', 'cxp-settings-hint cxp-settings-runtime', tr('runtime', { cli: runtime.cliVersion || tr('unknown'), sdk: runtime.sdkVersion || tr('unknown'), protocol: runtime.protocolBaseline || tr('unknown') })));
96
+ if (runtime.codexBin) sections.advanced.append(el('div', 'cxp-settings-hint', runtime.codexBin));
97
+ const mcp = el('div', ''); mcp.id = 'cxp-settings-mcp'; sections.tools.append(el('h4', 'cxp-settings-subtitle', tr('mcp')), mcp);
98
+ async function renderMcp(data) {
99
+ if (data.error) throw new Error(data.error);
100
+ mcp.replaceChildren();
101
+ for (const server of data.servers || []) {
102
+ const row = el('div', 'cxp-mcp-row');
103
+ const statusKey = server.requiresOAuth ? 'loginRequired' : server.status === 'running' ? 'running' : 'configured';
104
+ const status = el('span', 'cxp-mcp-status', tr(statusKey)); status.dataset.status = server.status;
105
+ row.append(el('span', 'cxp-mcp-name', server.name), status);
106
+ if (server.alwaysAllowed) row.append(el('span', 'cxp-mcp-status', tr('alwaysAllowed')));
107
+ row.append(
108
+ action(tr('refresh'), async () => { await request('mcp_refresh', { name: server.name }); await renderMcp(await request('mcp_status')); }));
109
+ if (server.alwaysAllowed) row.append(action(tr('revoke'), async () => {
110
+ await request('mcp_approval_set', { name: server.name, approvalMode: 'prompt' }); await renderMcp(await request('mcp_status'));
111
+ }));
112
+ if (server.requiresOAuth) row.append(action(tr('authenticate'), () => authenticate(server.name)));
113
+ mcp.append(row);
114
+ }
115
+ if (!mcp.childElementCount) mcp.append(el('div', 'cxp-settings-hint', tr('noMcp')));
116
+ }
117
+ if (mcpData.status === 'fulfilled') await renderMcp(mcpData.value); else error(mcpData.reason.message);
118
+ const roots = el('div', ''); roots.id = 'cxp-settings-permissions';
119
+ sections.permissions.append(el('h4', 'cxp-settings-subtitle', tr('folders')), roots);
120
+ async function renderRoots(data) {
121
+ if (data.error) throw new Error(data.error);
122
+ roots.replaceChildren(); const fs = data.permissions?.filesystem || {};
123
+ for (const access of ['write', 'read']) for (const path of fs[access] || []) {
124
+ const row = el('div', 'cxp-mcp-row'); const name = el('span', 'cxp-mcp-name cxp-permission-root-path', path); name.title = path;
125
+ row.append(name, el('span', 'cxp-mcp-status', tr(access)), action(tr('revoke'), async () => {
126
+ await request('permission_root_remove', { access, path }); await renderRoots(await request('permission_roots_list'));
127
+ })); roots.append(row);
128
+ }
129
+ if (!roots.childElementCount) roots.append(el('div', 'cxp-settings-hint', tr('none')));
130
+ }
131
+ if (permissions.status === 'fulfilled') await renderRoots(permissions.value); else error(permissions.reason.message);
132
+ if (configData.status !== 'fulfilled' || configData.value.error) throw new Error(configData.value?.error || configData.reason.message);
133
+ let cfg = normalizeConfig(configData.value.config).effective;
134
+ let overrides = Object.fromEntries(Object.entries(SESSION_CONFIG_FIELDS).filter(([, field]) => Object.hasOwn(configData.value.sessionOverrides || {}, field)).map(([key, field]) => [key, overrideValue(field, configData.value.sessionOverrides[field])]));
135
+ const schema = configData.value.settingsSchema;
136
+ if (!schema?.fields) throw new Error(tr('noSchema'));
137
+ const modelList = await models();
138
+ let defs = [], inputs = {}, restrictions = {};
139
+ const fields = {};
140
+ for (const key of ['models', 'permissions', 'tools', 'advanced']) { fields[key] = el('div', 'cxp-config-form'); sections[key].prepend(fields[key]); }
141
+ const scopeRow = el('label', 'cxp-config-row cxp-settings-scope'); scopeRow.append(el('span', '', tr('applyTo')));
142
+ const scope = el('select', 'cxp-config-input'); scope.id = 'cxp-settings-scope'; scope.setAttribute('aria-label', tr('applyTo'));
143
+ for (const [value, label] of [['saved', 'savedDefaults'], ['session', 'currentThread']]) { const o = el('option', '', tr(label)); o.value = value; o.disabled = value === 'session' && (!tab.threadId || !capabilityAvailability(capabilities, 'thread_settings_update').supported); scope.append(o); }
144
+ scopeRow.append(scope); body.prepend(scopeRow);
145
+ const scopeHint = el('div', 'cxp-settings-hint cxp-settings-scope-hint', tr('scopeHint')); scopeRow.after(scopeHint);
146
+ const featureHost = el('details', 'cxp-settings-features'); featureHost.append(el('summary', 'cxp-settings-subtitle', tr('features'))); sections.tools.append(featureHost);
147
+ const featureInputs = {};
148
+ for (const feature of schema.features || []) {
149
+ if (!['stable', 'beta'].includes(feature.stage) || feature.configurable === false) continue;
150
+ const row = el('label', 'cxp-config-row'); row.append(el('span', 'cxp-config-label', feature.name));
151
+ const input = el('button', 'cxp-settings-toggle'); input.type = 'button'; input.setAttribute('role', 'switch'); input.setAttribute('aria-label', feature.name); input.dataset.feature = feature.name;
152
+ const restriction = configRestriction(requirements.status === 'fulfilled' ? requirements.value : {}, `features.${feature.name}`);
153
+ input.dataset.fixed = String(typeof restriction.fixed === 'boolean');
154
+ const set = value => { input.dataset.enabled = String(value); input.setAttribute('aria-checked', String(value)); input.textContent = tr(value ? 'on' : 'off'); };
155
+ set(typeof restriction.fixed === 'boolean' ? restriction.fixed : feature.enabled);
156
+ input.onclick = () => set(input.dataset.enabled !== 'true'); row.append(input); featureHost.append(row); featureInputs[feature.name] = { input, feature, set };
157
+ }
158
+ const save = action(tr('saveDefaults'), async () => {
159
+ result.textContent = tr('saving'); delete result.dataset.error;
160
+ const current = scope.value === 'session' ? { ...cfg, ...overrides } : cfg;
161
+ const patch = configChanges(defs, inputs, current);
162
+ let featureEdits = {};
163
+ if (scope.value === 'session') {
164
+ if (tab.running) throw new Error(tr('busy'));
165
+ if (Object.keys(patch).length) await request('thread_settings_update', { threadId: tab.threadId, cwd: tab.project || null, ...sessionSettings(patch) });
166
+ } else {
167
+ const enablement = Object.fromEntries(Object.values(featureInputs).filter(({ input, feature }) => !input.disabled && (input.dataset.enabled === 'true') !== feature.enabled).map(({ input, feature }) => [feature.name, input.dataset.enabled === 'true']));
168
+ featureEdits = enablement;
169
+ const config = { ...patch, ...Object.fromEntries(Object.entries(enablement).map(([key, value]) => [`features.${key}`, value])) };
170
+ if (Object.keys(config).length) await request('config_write', { config, cwd: tab.project || null });
171
+ }
172
+ // Always re-read the runtime. Never report success from an optimistic UI copy.
173
+ const read = await request('config_read', { cwd: tab.project || null, threadId: tab.threadId || null });
174
+ if (read.error) throw new Error(read.error);
175
+ cfg = normalizeConfig(read.config).effective;
176
+ overrides = Object.fromEntries(Object.entries(SESSION_CONFIG_FIELDS).filter(([, field]) => Object.hasOwn(read.sessionOverrides || {}, field)).map(([key, field]) => [key, overrideValue(field, read.sessionOverrides[field])]));
177
+ for (const { input, feature, set } of Object.values(featureInputs)) {
178
+ const actual = read.settingsSchema?.features?.find(f => f.name === feature.name);
179
+ if (actual) { feature.enabled = actual.enabled; set(actual.enabled); }
180
+ }
181
+ renderFields(); onSaved({ scope: scope.value, patch, overrides });
182
+ const effective = scope.value === 'session' ? { ...cfg, ...overrides } : cfg;
183
+ const unapplied = Object.entries(patch).filter(([key, value]) => JSON.stringify(configValue(effective, key) ?? null) !== JSON.stringify(value));
184
+ for (const [key, value] of Object.entries(featureEdits)) if (featureInputs[key]?.feature.enabled !== value) unapplied.push([key]);
185
+ if (unapplied.length) throw new Error(tr('notApplied', { keys: unapplied.map(([key]) => key).join(', ') }));
186
+ result.textContent = tr('saved');
187
+ }); save.classList.add('cxp-config-save'); footer.prepend(save);
188
+ function renderFields(selection) {
189
+ const visible = scope.value === 'session' ? { ...cfg, ...overrides } : cfg;
190
+ const values = selection || visible;
191
+ defs = codexSettingsDefinitions(schema, modelList, values); inputs = {}; restrictions = {};
192
+ for (const node of Object.values(fields)) node.replaceChildren();
193
+ for (const def of defs) {
194
+ if (scope.value === 'session' && !SESSION_CONFIG_FIELDS[def.key]) continue;
195
+ const row = el('div', 'cxp-config-row'); const label = el('label', 'cxp-config-label', def.label);
196
+ const input = el(def.type === 'number' ? 'input' : 'select', 'cxp-config-input');
197
+ input.id = `cxp-setting-${def.key}`; input.dataset.configKey = def.key; label.htmlFor = input.id;
198
+ const value = configValue(values, def.key);
199
+ if (def.type === 'number') { input.type = 'number'; input.min = '1'; input.step = '1'; input.placeholder = tr('default'); }
200
+ else {
201
+ for (const option of def.options) { const o = el('option', '', option.label); o.value = option.value; input.append(o); }
202
+ if (value != null && !def.options.some(o => o.value === String(value))) {
203
+ const o = el('option', '', tr('configured', { value: typeof value === 'object' ? JSON.stringify(value) : value })); o.value = typeof value === 'object' ? JSON.stringify(value) : String(value); input.append(o); input.dataset.originalValue = JSON.stringify(value);
204
+ }
205
+ }
206
+ input.value = value == null ? '' : typeof value === 'object' ? JSON.stringify(value) : String(value);
207
+ const restriction = configRestriction(requirements.status === 'fulfilled' ? requirements.value : {}, def.key);
208
+ restrictions[def.key] = restriction;
209
+ input.disabled = Object.hasOwn(restriction, 'fixed');
210
+ for (const o of input.options || []) if (o.value && restriction.allowed && !restriction.allowed.some(v => JSON.stringify(v) === JSON.stringify(o.value))) o.disabled = true;
211
+ const layer = normalizeConfig(configData.value.config).layers[def.key];
212
+ if (layer || restriction.reason) input.title = tr(restriction.reason ? 'managed' : 'source', { layer });
213
+ inputs[def.key] = input; row.append(label, input);
214
+ if (def.type === 'number') row.append(el('span', 'cxp-settings-unit', tr('tokens')));
215
+ fields[def.section].append(row);
216
+ }
217
+ const modelInput = inputs.model;
218
+ if (modelInput) modelInput.onchange = () => {
219
+ const draft = { ...values };
220
+ for (const def of defs) if (inputs[def.key]) draft[def.key] = inputs[def.key].value || null;
221
+ draft.model_reasoning_effort = null; draft.service_tier = null; renderFields(draft);
222
+ };
223
+ for (const { input } of Object.values(featureInputs)) input.disabled = scope.value === 'session' || input.dataset.fixed === 'true';
224
+ featureHost.hidden = scope.value === 'session';
225
+ for (const key of ['models', 'permissions', 'tools', 'advanced']) sections[key].closest('.cxp-settings-section').hidden = scope.value === 'session' && !fields[key].childElementCount;
226
+ save.textContent = tr(scope.value === 'session' ? 'applyThread' : 'saveDefaults');
227
+ }
228
+ scope.onchange = () => renderFields(); renderFields();
229
+ } catch (failure) { error(failure.message); }
230
+ return { overlay, sections };
231
+ }
@@ -10,11 +10,13 @@ export function injectStyles() {
10
10
  tokens (docs/codex-sidepanel.md → Visual language). Add a value here
11
11
  before using it anywhere else. The lightbox, the minimized pill and
12
12
  the Context settings popover live outside the panel, so they carry the
13
- tokens too. */
13
+ tokens too, as does the header account menu (account-menu.js), whose
14
+ --acct-* values read them. */
14
15
  .codex-panel,
15
16
  .cxp-lightbox,
16
17
  .cxp-session-pill,
17
- .cxp-ctxpop {
18
+ .cxp-ctxpop,
19
+ .acct-menu--codex {
18
20
  /* Surfaces: one treatment per level */
19
21
  --cxp-shell: rgba(16, 18, 22, 0.92);
20
22
  --cxp-shell-border: rgba(255,255,255,0.08);
@@ -135,7 +137,7 @@ export function injectStyles() {
135
137
  outline-offset: 2px;
136
138
  }
137
139
  /* Inside clipping containers the ring sits on the element instead of around it. */
138
- .codex-panel :is(.cxp-fold-summary, .cxp-reasoning summary, .cxp-effort-menu-item, .cxp-account-row-main, .cxp-account-row-remove, .cxp-image-chip-remove, .cxp-sess-rename, .cxp-sess-archive-btn, .cxp-sess-unarchive-btn, .cxp-sess-search-input, .cxp-session-btn, .cxp-header-rename):focus-visible {
140
+ .codex-panel :is(.cxp-fold-summary, .cxp-reasoning summary, .cxp-effort-menu-item, .cxp-image-chip-remove, .cxp-sess-rename, .cxp-sess-archive-btn, .cxp-sess-unarchive-btn, .cxp-sess-search-input, .cxp-session-btn, .cxp-header-rename):focus-visible {
139
141
  outline-offset: -2px;
140
142
  }
141
143
  .cxp-resize-handle {
@@ -254,6 +256,8 @@ export function injectStyles() {
254
256
  margin-left: auto;
255
257
  flex-shrink: 0;
256
258
  }
259
+ /* The header account menu's trigger (account-menu.js) gives way before the session name does. */
260
+ .cxp-actions:has(> .acct-menu-trigger) { flex-shrink: 1; min-width: 0; }
257
261
  .cxp-btn {
258
262
  width: 24px;
259
263
  height: 24px;
@@ -840,97 +844,6 @@ export function injectStyles() {
840
844
  color: var(--cxp-text-3);
841
845
  }
842
846
 
843
- /* ── Account menu (under the header; opened from the Context settings popover) ── */
844
- .cxp-account-menu {
845
- position: absolute;
846
- top: calc(100% + 6px);
847
- right: 8px;
848
- min-width: 230px;
849
- max-width: 300px;
850
- background: var(--cxp-pop);
851
- border: 1px solid var(--cxp-border);
852
- border-radius: var(--cxp-radius-md);
853
- box-shadow: var(--cxp-shadow-pop);
854
- padding: 6px;
855
- z-index: 50;
856
- display: none;
857
- flex-direction: column;
858
- gap: 2px;
859
- }
860
- .cxp-account-menu.open { display: flex; }
861
- .cxp-account-empty {
862
- padding: 8px 10px;
863
- font-size: var(--cxp-fs-sm);
864
- color: var(--cxp-text-3);
865
- }
866
- .cxp-account-row {
867
- display: flex;
868
- align-items: stretch;
869
- gap: 2px;
870
- border-radius: var(--cxp-radius-sm);
871
- overflow: hidden;
872
- }
873
- .cxp-account-row.active { background: var(--cxp-surface-2); }
874
- .cxp-account-row-main {
875
- display: flex;
876
- align-items: center;
877
- gap: 8px;
878
- flex: 1;
879
- min-width: 0;
880
- padding: 7px 9px;
881
- background: transparent;
882
- border: none;
883
- cursor: pointer;
884
- text-align: left;
885
- font-family: var(--cxp-font);
886
- color: var(--cxp-text);
887
- }
888
- .cxp-account-row-main:hover { background: var(--cxp-surface-1); }
889
- .cxp-account-check {
890
- width: 12px;
891
- flex-shrink: 0;
892
- color: var(--cxp-text);
893
- font-size: var(--cxp-fs-sm);
894
- }
895
- .cxp-account-row-text { display: flex; flex-direction: column; min-width: 0; }
896
- .cxp-account-row-label {
897
- font-size: var(--cxp-fs-md);
898
- overflow: hidden;
899
- text-overflow: ellipsis;
900
- white-space: nowrap;
901
- }
902
- .cxp-account-row-sub {
903
- font-size: var(--cxp-fs-xs);
904
- color: var(--cxp-text-3);
905
- overflow: hidden;
906
- text-overflow: ellipsis;
907
- white-space: nowrap;
908
- }
909
- .cxp-account-row-remove {
910
- flex-shrink: 0;
911
- width: 26px;
912
- background: transparent;
913
- border: none;
914
- color: var(--cxp-text-3);
915
- cursor: pointer;
916
- font-size: var(--cxp-fs-sm);
917
- transition: color var(--cxp-dur-fast), background var(--cxp-dur-fast);
918
- }
919
- .cxp-account-row-remove:hover { color: var(--cxp-danger); background: var(--cxp-surface-1); }
920
- .cxp-account-add {
921
- margin-top: 4px;
922
- padding: 8px 10px;
923
- background: transparent;
924
- border: 1px dashed var(--cxp-border-strong);
925
- border-radius: var(--cxp-radius-sm);
926
- color: var(--cxp-text-2);
927
- font-size: var(--cxp-fs-sm);
928
- font-family: var(--cxp-font);
929
- cursor: pointer;
930
- text-align: center;
931
- transition: color var(--cxp-dur-fast), background var(--cxp-dur-fast);
932
- }
933
- .cxp-account-add:hover { background: var(--cxp-surface-1); color: var(--cxp-text); }
934
847
 
935
848
  /* ── Context settings: the header cog and its popover (cdx-context-menu.js) ──
936
849
  One grammar: a 28px head (title, at most one action) and 28px rows (label
@@ -1133,12 +1046,16 @@ export function injectStyles() {
1133
1046
  .cxp-empty-logo svg { width: 32px; height: 32px; }
1134
1047
  .cxp-empty-name { font-size: var(--cxp-fs-lg); font-weight: 500; color: var(--cxp-text-3); }
1135
1048
  .cxp-empty-status { font-size: var(--cxp-fs-sm); color: var(--cxp-text-3); line-height: 1.5; min-height: 1em; }
1049
+ /* The CLI banner (ui-cli-banner.js): Codex not installed (with Install),
1050
+ being installed, failed to install, or found but failed to start. A
1051
+ left edge in the colour of what it says; the Install button is the
1052
+ panel's solid action. */
1136
1053
  .cxp-cli-banner {
1137
1054
  flex-shrink: 0;
1138
1055
  display: grid;
1139
- grid-template-columns: auto 1fr auto;
1056
+ grid-template-columns: auto minmax(0, 1fr);
1140
1057
  gap: 10px;
1141
- align-items: center;
1058
+ align-items: start;
1142
1059
  margin: 6px 8px 0;
1143
1060
  padding: 10px 12px;
1144
1061
  border: 1px solid var(--cxp-border);
@@ -1150,6 +1067,11 @@ export function injectStyles() {
1150
1067
  position: relative;
1151
1068
  z-index: 5;
1152
1069
  }
1070
+ .cxp-cli-banner [hidden] { display: none !important; }
1071
+ .cxp-cli-banner--broken,
1072
+ .cxp-cli-banner--failed { box-shadow: inset 2px 0 0 var(--cxp-danger); }
1073
+ .cxp-cli-banner--installing { box-shadow: inset 2px 0 0 var(--cxp-running); }
1074
+ .cxp-cli-banner--done { box-shadow: inset 2px 0 0 var(--cxp-success); }
1153
1075
  .cxp-cli-banner-icon {
1154
1076
  width: 22px; height: 22px;
1155
1077
  display: flex; align-items: center; justify-content: center;
@@ -1158,30 +1080,81 @@ export function injectStyles() {
1158
1080
  color: var(--cxp-warning);
1159
1081
  font-weight: 700;
1160
1082
  }
1161
- .cxp-cli-banner-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
1083
+ .cxp-cli-banner--broken .cxp-cli-banner-icon,
1084
+ .cxp-cli-banner--failed .cxp-cli-banner-icon { border-color: var(--cxp-danger); color: var(--cxp-danger); }
1085
+ .cxp-cli-banner--installing .cxp-cli-banner-icon { border-color: var(--cxp-running); color: var(--cxp-running); animation: cxp-working 1.2s ease-in-out infinite; }
1086
+ .cxp-cli-banner--done .cxp-cli-banner-icon { border-color: var(--cxp-success); color: var(--cxp-success); }
1087
+ .cxp-cli-banner--nudge { animation: cxp-cli-nudge 0.5s var(--cxp-ease); }
1088
+ @keyframes cxp-cli-nudge { 0%, 100% { transform: none; } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
1089
+ .cxp-cli-banner-text { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
1162
1090
  .cxp-cli-banner-title {
1163
1091
  font-size: var(--cxp-fs-md); font-weight: 600;
1164
1092
  color: var(--cxp-text);
1165
1093
  }
1166
- .cxp-cli-banner-body {
1094
+ .cxp-cli-banner-body,
1095
+ .cxp-cli-banner-note,
1096
+ .cxp-cli-banner-step {
1167
1097
  font-size: var(--cxp-fs-sm);
1168
1098
  color: var(--cxp-text-2);
1169
- word-break: break-word;
1099
+ overflow-wrap: anywhere;
1170
1100
  }
1171
- .cxp-cli-banner-body code {
1172
- padding: 1px 4px;
1101
+ .cxp-cli-banner-command { display: flex; align-items: flex-start; gap: 6px; }
1102
+ .cxp-cli-banner-command code,
1103
+ .cxp-cli-banner-error code {
1104
+ flex: 1;
1105
+ min-width: 0;
1106
+ padding: 3px 6px;
1173
1107
  background: var(--cxp-surface-2);
1174
1108
  border-radius: var(--cxp-radius-sm);
1175
1109
  font-family: var(--cxp-mono);
1176
1110
  font-size: var(--cxp-fs-sm);
1177
1111
  color: var(--cxp-text);
1112
+ white-space: pre-wrap;
1113
+ word-break: break-all;
1114
+ user-select: text;
1178
1115
  }
1179
- .cxp-cli-banner-actions { display: flex; gap: 6px; }
1180
- .cxp-cli-banner-link, .cxp-cli-banner-recheck {
1181
- display: inline-flex; align-items: center; gap: 4px;
1182
- padding: 4px 9px;
1116
+ .cxp-cli-banner-error code { display: block; max-height: 96px; overflow: auto; }
1117
+ .cxp-cli-banner-copy {
1118
+ flex-shrink: 0;
1119
+ height: 22px;
1120
+ padding: 0 8px;
1121
+ border: 1px solid var(--cxp-border-strong);
1122
+ border-radius: var(--cxp-radius-sm);
1123
+ background: transparent;
1124
+ color: var(--cxp-text-2);
1125
+ font-family: inherit;
1183
1126
  font-size: var(--cxp-fs-sm);
1127
+ cursor: pointer;
1128
+ }
1129
+ .cxp-cli-banner-copy:hover { color: var(--cxp-text); background: var(--cxp-surface-2); }
1130
+ .cxp-cli-banner-progress { display: flex; flex-direction: column; gap: 4px; }
1131
+ .cxp-cli-banner-bar { height: 3px; border-radius: 2px; background: var(--cxp-surface-2); overflow: hidden; }
1132
+ .cxp-cli-banner-bar > span { display: block; height: 100%; width: 0; background: var(--cxp-running); transition: width var(--cxp-dur-fast) var(--cxp-ease); }
1133
+ .cxp-cli-banner-log {
1134
+ margin: 0;
1135
+ max-height: 84px;
1136
+ overflow: auto;
1137
+ padding: 4px 6px;
1138
+ background: var(--cxp-surface-1);
1139
+ border-radius: var(--cxp-radius-sm);
1140
+ font-family: var(--cxp-mono);
1141
+ font-size: var(--cxp-fs-xs);
1142
+ line-height: 1.45;
1143
+ color: var(--cxp-text-3);
1144
+ white-space: pre-wrap;
1145
+ word-break: break-all;
1146
+ }
1147
+ .cxp-cli-banner-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
1148
+ .cxp-cli-banner-install,
1149
+ .cxp-cli-banner-link,
1150
+ .cxp-cli-banner-path, .cxp-cli-banner-recheck,
1151
+ .cxp-cli-banner-dismiss {
1152
+ display: inline-flex; align-items: center; gap: 4px;
1153
+ height: 24px;
1154
+ padding: 0 10px;
1155
+ font-size: var(--cxp-fs-md);
1184
1156
  font-weight: 500;
1157
+ line-height: 1;
1185
1158
  border-radius: var(--cxp-radius-md);
1186
1159
  border: 1px solid var(--cxp-border-strong);
1187
1160
  background: transparent;
@@ -1192,10 +1165,27 @@ export function injectStyles() {
1192
1165
  font-family: inherit;
1193
1166
  transition: background var(--cxp-dur-fast);
1194
1167
  }
1195
- .cxp-cli-banner-link:hover, .cxp-cli-banner-recheck:hover {
1168
+ .cxp-cli-banner-install {
1169
+ background: var(--cxp-solid);
1170
+ border-color: var(--cxp-solid);
1171
+ color: var(--cxp-on-solid);
1172
+ }
1173
+ .cxp-cli-banner-install:hover:not(:disabled) { background: var(--cxp-solid-hover); border-color: var(--cxp-solid-hover); }
1174
+ .cxp-cli-banner-link:hover,
1175
+ .cxp-cli-banner-path:hover:not(:disabled), .cxp-cli-banner-recheck:hover:not(:disabled),
1176
+ .cxp-cli-banner-dismiss:hover {
1196
1177
  background: var(--cxp-surface-2);
1197
1178
  }
1198
- .cxp-cli-banner-recheck:disabled { opacity: 0.5; cursor: default; }
1179
+ .cxp-cli-banner-install:disabled,
1180
+ .cxp-cli-banner-path:disabled, .cxp-cli-banner-recheck:disabled { opacity: 0.5; cursor: default; }
1181
+ .cxp-cli-banner button:focus-visible,
1182
+ .cxp-cli-banner a:focus-visible { outline: 2px solid var(--cxp-focus); outline-offset: 2px; }
1183
+ @media (prefers-reduced-motion: reduce) {
1184
+ .cxp-cli-banner--installing .cxp-cli-banner-icon,
1185
+ .cxp-cli-banner--nudge { animation: none; }
1186
+ .cxp-cli-banner--nudge { box-shadow: inset 2px 0 0 var(--cxp-warning), 0 0 0 1px var(--cxp-warning); }
1187
+ .cxp-cli-banner-bar > span { transition: none; }
1188
+ }
1199
1189
  .codex-panel.cxp-cli-blocked .cxp-send { opacity: 0.4 !important; cursor: not-allowed !important; }
1200
1190
  .codex-panel.cxp-cli-blocked .cxp-input { opacity: 0.7; }
1201
1191
 
@@ -2442,6 +2432,42 @@ export function injectStyles() {
2442
2432
  .cxp-post-plan-utilities .cxp-request-btn { flex: 1; justify-content: center; }
2443
2433
  }
2444
2434
 
2435
+ /* ── A dispatched worker's end (ui-worker-end.js): the post-plan header and note in the
2436
+ compaction card's hairline frame, in the transcript column. The title says the state in words. ── */
2437
+ .cxp-worker-end {
2438
+ display: grid;
2439
+ gap: var(--cxp-space-2);
2440
+ min-width: 0;
2441
+ margin: var(--cxp-space-2) var(--cxp-space-2) var(--cxp-space-3) calc(var(--cxp-space-2) + 24px + var(--cxp-space-2));
2442
+ padding: var(--cxp-space-3) var(--cxp-space-4);
2443
+ border: 1px solid var(--cxp-border-strong);
2444
+ border-radius: var(--cxp-radius-md);
2445
+ font-family: var(--cxp-font);
2446
+ }
2447
+ .cxp-worker-end[data-tone="ok"] .cxp-post-plan-header { color: var(--cxp-success); }
2448
+ .cxp-worker-end[data-tone="warn"] .cxp-post-plan-header { color: var(--cxp-warning); }
2449
+ .cxp-worker-end[data-tone="err"] .cxp-post-plan-header { color: var(--cxp-danger); }
2450
+ .cxp-worker-end .cxp-post-plan-note { overflow-wrap: anywhere; }
2451
+ .cxp-worker-end .worker-end-meta {
2452
+ font-family: var(--cxp-mono);
2453
+ font-size: var(--cxp-fs-xs);
2454
+ color: var(--cxp-text-3);
2455
+ }
2456
+ .cxp-worker-end .worker-end-note {
2457
+ font-size: var(--cxp-fs-sm);
2458
+ line-height: var(--cxp-lh-tight);
2459
+ color: var(--cxp-text-3);
2460
+ }
2461
+ .cxp-worker-end .worker-end-actions { display: flex; margin-top: var(--cxp-space-1); }
2462
+ .cxp-worker-end .cxp-request-btn:focus-visible {
2463
+ outline: 2px solid var(--cxp-focus);
2464
+ outline-offset: 2px;
2465
+ }
2466
+ @media (max-width: 390px) {
2467
+ .cxp-worker-end { margin-left: var(--cxp-space-2); padding: var(--cxp-space-3); }
2468
+ .cxp-worker-end .cxp-request-btn { flex: 1; justify-content: center; }
2469
+ }
2470
+
2445
2471
  /* ── Composer ── */
2446
2472
  .cxp-bottom {
2447
2473
  flex-shrink: 0;
@@ -2911,6 +2937,37 @@ export function injectStyles() {
2911
2937
  opacity: 0.4;
2912
2938
  cursor: default;
2913
2939
  }
2940
+ /* Codex Settings: scoped compact groups and consistent native controls. */
2941
+ .cxp-settings-panel { display: flex; flex-direction: column; overflow: hidden; }
2942
+ .cxp-settings-body { overflow-y: auto; min-height: 0; }
2943
+ .cxp-settings-header { flex: none; font-size: var(--cxp-fs-md); padding: 12px 14px; }
2944
+ .cxp-settings-section { padding: 12px 0; margin: 0; }
2945
+ .cxp-settings-section .cxp-settings-section { border: 0; }
2946
+ .cxp-settings-section[hidden], .cxp-settings-features[hidden] { display: none; }
2947
+ .cxp-settings-section-title { font-size: var(--cxp-fs-sm); text-transform: none; letter-spacing: 0; color: var(--cxp-text-2); margin: 0 0 8px; }
2948
+ details.cxp-settings-section > summary, .cxp-settings-features > summary { cursor: pointer; }
2949
+ .cxp-settings-section:not([open]) > summary { margin-bottom: 0; }
2950
+ .cxp-settings-subtitle { font-size: var(--cxp-fs-xs); font-weight: 500; color: var(--cxp-text-3); margin: 10px 0 6px; }
2951
+ .cxp-config-row { border: 0; padding: 4px 0; min-width: 0; }
2952
+ .cxp-config-label { text-align: left; flex-basis: 42%; font-size: var(--cxp-fs-sm); color: var(--cxp-text-2); overflow-wrap: anywhere; }
2953
+ .cxp-settings-panel .cxp-config-input { min-height: 26px; padding: 3px 6px; border-radius: var(--cxp-radius-sm); background: var(--cxp-surface-1); }
2954
+ .cxp-settings-panel .cxp-config-input option { background: var(--cxp-pop); color: var(--cxp-text); }
2955
+ .cxp-settings-scope { gap: 12px; }
2956
+ .cxp-settings-scope-hint { margin-bottom: 8px; }
2957
+ .cxp-settings-footer { flex: none; border-top: 1px solid var(--cxp-border); padding: 10px 14px; background: var(--cxp-pop); }
2958
+ .cxp-settings-footer .cxp-config-save { margin: 0; width: 100%; text-transform: none; letter-spacing: 0; padding: 6px 10px; }
2959
+ .cxp-settings-result { font-size: var(--cxp-fs-xs); color: var(--cxp-text-3); overflow-wrap: anywhere; }
2960
+ .cxp-settings-result:not(:empty) { padding-top: 6px; }
2961
+ .cxp-settings-result[data-error=true] { color: var(--cxp-danger); }
2962
+ .cxp-settings-unit { font-size: var(--cxp-fs-xs); color: var(--cxp-text-3); }
2963
+ .cxp-settings-toggle { margin-left: auto; min-width: 70px; padding: 3px 8px; border: 1px solid var(--cxp-border-input); border-radius: var(--cxp-radius-sm); color: var(--cxp-text-3); background: var(--cxp-surface-1); font: inherit; cursor: pointer; }
2964
+ .cxp-settings-toggle[data-enabled=true] { color: var(--cxp-text); background: var(--cxp-surface-3); border-color: var(--cxp-text-3); }
2965
+ .cxp-settings-toggle:disabled { opacity: .45; cursor: default; }
2966
+ .cxp-settings-features { margin-top: 10px; }
2967
+ .cxp-settings-features .cxp-config-label { flex-basis: auto; }
2968
+ .cxp-settings-runtime { margin-top: 12px; }
2969
+ .cxp-settings-panel .cxp-mcp-row { flex-wrap: wrap; border: 0; padding: 4px 0; }
2970
+ .cxp-config-warning { padding: 8px 12px; color: var(--cxp-warning); font-size: var(--cxp-fs-xs); white-space: pre-wrap; }
2914
2971
  .cxp-config-layer {
2915
2972
  font-size: var(--cxp-fs-xs);
2916
2973
  color: var(--cxp-text-3);