@clawpump/claw-agent 0.1.5 → 0.1.6

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 (1212) hide show
  1. package/agent/.dockerignore +67 -0
  2. package/agent/.envrc +1 -1
  3. package/agent/.gitattributes +8 -0
  4. package/agent/AGENTS.md +216 -4
  5. package/agent/CONTRIBUTING.md +46 -8
  6. package/agent/Dockerfile +78 -35
  7. package/agent/MANIFEST.in +2 -0
  8. package/agent/README.md +12 -5
  9. package/agent/README.ur-pk.md +261 -0
  10. package/agent/README.zh-CN.md +11 -8
  11. package/agent/SECURITY.md +5 -4
  12. package/agent/acp_adapter/provenance.py +127 -0
  13. package/agent/acp_adapter/server.py +112 -5
  14. package/agent/acp_adapter/session.py +1 -6
  15. package/agent/acp_registry/agent.json +2 -2
  16. package/agent/agent/account_usage.py +313 -1
  17. package/agent/agent/agent_init.py +140 -37
  18. package/agent/agent/agent_runtime_helpers.py +342 -83
  19. package/agent/agent/anthropic_adapter.py +320 -33
  20. package/agent/agent/auxiliary_client.py +525 -105
  21. package/agent/agent/background_review.py +157 -19
  22. package/agent/agent/bedrock_adapter.py +71 -6
  23. package/agent/agent/billing_view.py +295 -0
  24. package/agent/agent/chat_completion_helpers.py +229 -4
  25. package/agent/agent/codex_responses_adapter.py +86 -10
  26. package/agent/agent/codex_runtime.py +153 -1
  27. package/agent/agent/coding_context.py +738 -0
  28. package/agent/agent/context_compressor.py +392 -44
  29. package/agent/agent/context_references.py +34 -1
  30. package/agent/agent/conversation_compression.py +159 -22
  31. package/agent/agent/conversation_loop.py +643 -908
  32. package/agent/agent/copilot_acp_client.py +4 -11
  33. package/agent/agent/credential_pool.py +5 -3
  34. package/agent/agent/credits_tracker.py +794 -0
  35. package/agent/agent/curator.py +91 -18
  36. package/agent/agent/curator_backup.py +26 -10
  37. package/agent/agent/display.py +42 -1
  38. package/agent/agent/error_classifier.py +52 -3
  39. package/agent/agent/errors.py +3 -0
  40. package/agent/agent/file_safety.py +0 -17
  41. package/agent/agent/gemini_native_adapter.py +31 -1
  42. package/agent/agent/i18n.py +48 -4
  43. package/agent/agent/image_gen_provider.py +74 -5
  44. package/agent/agent/image_routing.py +29 -0
  45. package/agent/agent/insights.py +8 -17
  46. package/agent/agent/lsp/install.py +3 -0
  47. package/agent/agent/memory_manager.py +326 -31
  48. package/agent/agent/message_content.py +50 -0
  49. package/agent/agent/model_metadata.py +214 -3
  50. package/agent/agent/moonshot_schema.py +8 -1
  51. package/agent/agent/onboarding.py +60 -0
  52. package/agent/agent/prompt_builder.py +327 -37
  53. package/agent/agent/redact.py +1 -0
  54. package/agent/agent/runtime_cwd.py +34 -5
  55. package/agent/agent/secret_scope.py +205 -0
  56. package/agent/agent/secret_sources/bitwarden.py +34 -2
  57. package/agent/agent/skill_commands.py +90 -1
  58. package/agent/agent/skill_preprocessing.py +1 -0
  59. package/agent/agent/skill_utils.py +209 -36
  60. package/agent/agent/ssl_guard.py +94 -0
  61. package/agent/agent/system_prompt.py +133 -5
  62. package/agent/agent/tool_executor.py +496 -70
  63. package/agent/agent/transports/anthropic.py +83 -21
  64. package/agent/agent/transports/chat_completions.py +94 -5
  65. package/agent/agent/transports/codex.py +67 -2
  66. package/agent/agent/transports/codex_app_server.py +1 -0
  67. package/agent/agent/transports/codex_app_server_session.py +30 -0
  68. package/agent/agent/transports/types.py +12 -0
  69. package/agent/agent/turn_context.py +408 -0
  70. package/agent/agent/turn_finalizer.py +428 -0
  71. package/agent/agent/turn_retry_state.py +68 -0
  72. package/agent/agent/usage_pricing.py +3 -0
  73. package/agent/apps/bootstrap-installer/package.json +6 -5
  74. package/agent/apps/bootstrap-installer/src/routes/failure.tsx +12 -5
  75. package/agent/apps/bootstrap-installer/src/routes/progress.tsx +1 -3
  76. package/agent/apps/bootstrap-installer/src/store.ts +3 -2
  77. package/agent/apps/bootstrap-installer/src-tauri/src/bootstrap.rs +172 -7
  78. package/agent/apps/bootstrap-installer/src-tauri/src/events.rs +14 -1
  79. package/agent/apps/bootstrap-installer/src-tauri/src/paths.rs +29 -0
  80. package/agent/apps/bootstrap-installer/src-tauri/src/powershell.rs +93 -3
  81. package/agent/apps/bootstrap-installer/src-tauri/src/update.rs +695 -39
  82. package/agent/apps/bootstrap-installer/tsconfig.json +3 -4
  83. package/agent/apps/desktop/DESIGN.md +167 -0
  84. package/agent/apps/desktop/README.md +20 -16
  85. package/agent/apps/desktop/assets/icon.icns +0 -0
  86. package/agent/apps/desktop/assets/icon.ico +0 -0
  87. package/agent/apps/desktop/assets/icon.png +0 -0
  88. package/agent/apps/desktop/electron/backend-env.cjs +112 -0
  89. package/agent/apps/desktop/electron/backend-env.test.cjs +111 -0
  90. package/agent/apps/desktop/electron/backend-probes.test.cjs +3 -1
  91. package/agent/apps/desktop/electron/backend-ready.cjs +66 -0
  92. package/agent/apps/desktop/electron/bootstrap-platform.cjs +52 -0
  93. package/agent/apps/desktop/electron/bootstrap-platform.test.cjs +59 -1
  94. package/agent/apps/desktop/electron/bootstrap-runner.cjs +176 -38
  95. package/agent/apps/desktop/electron/bootstrap-runner.test.cjs +112 -1
  96. package/agent/apps/desktop/electron/connection-config.cjs +288 -0
  97. package/agent/apps/desktop/electron/connection-config.test.cjs +396 -0
  98. package/agent/apps/desktop/electron/dashboard-token.cjs +99 -0
  99. package/agent/apps/desktop/electron/dashboard-token.test.cjs +142 -0
  100. package/agent/apps/desktop/electron/desktop-uninstall.cjs +232 -0
  101. package/agent/apps/desktop/electron/desktop-uninstall.test.cjs +246 -0
  102. package/agent/apps/desktop/electron/entitlements.mac.inherit.plist +2 -0
  103. package/agent/apps/desktop/electron/fs-read-dir.cjs +109 -0
  104. package/agent/apps/desktop/electron/fs-read-dir.test.cjs +364 -0
  105. package/agent/apps/desktop/electron/gateway-ws-probe.cjs +188 -0
  106. package/agent/apps/desktop/electron/gateway-ws-probe.test.cjs +122 -0
  107. package/agent/apps/desktop/electron/git-root.cjs +54 -0
  108. package/agent/apps/desktop/electron/git-root.test.cjs +40 -0
  109. package/agent/apps/desktop/electron/git-worktrees.cjs +174 -0
  110. package/agent/apps/desktop/electron/hardening.cjs +123 -28
  111. package/agent/apps/desktop/electron/hardening.test.cjs +163 -0
  112. package/agent/apps/desktop/electron/main.cjs +3121 -331
  113. package/agent/apps/desktop/electron/oauth-net-request.cjs +20 -0
  114. package/agent/apps/desktop/electron/oauth-net-request.test.cjs +34 -0
  115. package/agent/apps/desktop/electron/preload.cjs +52 -2
  116. package/agent/apps/desktop/electron/session-windows.cjs +124 -0
  117. package/agent/apps/desktop/electron/session-windows.test.cjs +199 -0
  118. package/agent/apps/desktop/electron/update-rebuild.cjs +29 -0
  119. package/agent/apps/desktop/electron/update-rebuild.test.cjs +55 -0
  120. package/agent/apps/desktop/electron/update-remote.cjs +56 -0
  121. package/agent/apps/desktop/electron/update-remote.test.cjs +78 -0
  122. package/agent/apps/desktop/electron/vscode-marketplace.cjs +331 -0
  123. package/agent/apps/desktop/electron/vscode-marketplace.test.cjs +113 -0
  124. package/agent/apps/desktop/electron/windows-child-process.test.cjs +57 -0
  125. package/agent/apps/desktop/electron/windows-user-env.cjs +76 -0
  126. package/agent/apps/desktop/electron/windows-user-env.test.cjs +90 -0
  127. package/agent/apps/desktop/electron/workspace-cwd.cjs +38 -0
  128. package/agent/apps/desktop/electron/workspace-cwd.test.cjs +45 -0
  129. package/agent/apps/desktop/eslint.config.mjs +0 -3
  130. package/agent/apps/desktop/index.html +27 -2
  131. package/agent/apps/desktop/package.json +31 -11
  132. package/agent/apps/desktop/pr-assets/session-source-folders.png +0 -0
  133. package/agent/apps/desktop/public/apple-touch-icon.png +0 -0
  134. package/agent/apps/desktop/public/nous-girl.jpg +0 -0
  135. package/agent/apps/desktop/scripts/assert-dist-built.cjs +70 -0
  136. package/agent/apps/desktop/scripts/assert-dist-built.test.cjs +84 -0
  137. package/agent/apps/desktop/scripts/before-pack.cjs +78 -0
  138. package/agent/apps/desktop/scripts/before-pack.test.cjs +53 -0
  139. package/agent/apps/desktop/scripts/diag-scroll-reset.mjs +229 -0
  140. package/agent/apps/desktop/scripts/patch-electron-builder-mac-binary.cjs +64 -0
  141. package/agent/apps/desktop/scripts/run-electron-builder.cjs +57 -0
  142. package/agent/apps/desktop/src/app/agents/index.tsx +53 -45
  143. package/agent/apps/desktop/src/app/artifacts/index.tsx +102 -83
  144. package/agent/apps/desktop/src/app/chat/chat-drop-overlay.tsx +29 -8
  145. package/agent/apps/desktop/src/app/chat/chat-swap-overlay.tsx +47 -0
  146. package/agent/apps/desktop/src/app/chat/composer/attachments.tsx +81 -45
  147. package/agent/apps/desktop/src/app/chat/composer/completion-drawer.tsx +13 -24
  148. package/agent/apps/desktop/src/app/chat/composer/context-menu.tsx +138 -88
  149. package/agent/apps/desktop/src/app/chat/composer/controls.tsx +138 -90
  150. package/agent/apps/desktop/src/app/chat/composer/enter-submit-dom-race.test.tsx +218 -0
  151. package/agent/apps/desktop/src/app/chat/composer/focus.ts +32 -0
  152. package/agent/apps/desktop/src/app/chat/composer/help-hint.tsx +38 -25
  153. package/agent/apps/desktop/src/app/chat/composer/hooks/use-live-completion-adapter.ts +7 -0
  154. package/agent/apps/desktop/src/app/chat/composer/hooks/use-mic-recorder.ts +22 -12
  155. package/agent/apps/desktop/src/app/chat/composer/hooks/use-slash-completions.ts +142 -14
  156. package/agent/apps/desktop/src/app/chat/composer/hooks/use-voice-conversation.ts +14 -11
  157. package/agent/apps/desktop/src/app/chat/composer/hooks/use-voice-recorder.ts +9 -6
  158. package/agent/apps/desktop/src/app/chat/composer/ime-composition-dom-repro.test.tsx +108 -0
  159. package/agent/apps/desktop/src/app/chat/composer/index.tsx +930 -180
  160. package/agent/apps/desktop/src/app/chat/composer/inline-refs.ts +136 -32
  161. package/agent/apps/desktop/src/app/chat/composer/model-pill.tsx +86 -0
  162. package/agent/apps/desktop/src/app/chat/composer/queue-panel.tsx +54 -75
  163. package/agent/apps/desktop/src/app/chat/composer/rich-editor.test.ts +117 -1
  164. package/agent/apps/desktop/src/app/chat/composer/rich-editor.ts +117 -6
  165. package/agent/apps/desktop/src/app/chat/composer/slash-nav-dom-repro.test.tsx +186 -0
  166. package/agent/apps/desktop/src/app/chat/composer/status-stack/index.tsx +202 -0
  167. package/agent/apps/desktop/src/app/chat/composer/status-stack/status-row.tsx +155 -0
  168. package/agent/apps/desktop/src/app/chat/composer/text-utils.test.ts +104 -0
  169. package/agent/apps/desktop/src/app/chat/composer/text-utils.ts +37 -9
  170. package/agent/apps/desktop/src/app/chat/composer/trigger-popover.test.tsx +50 -0
  171. package/agent/apps/desktop/src/app/chat/composer/trigger-popover.tsx +105 -40
  172. package/agent/apps/desktop/src/app/chat/composer/types.ts +5 -0
  173. package/agent/apps/desktop/src/app/chat/composer/url-dialog.tsx +11 -15
  174. package/agent/apps/desktop/src/app/chat/composer/voice-activity.tsx +8 -4
  175. package/agent/apps/desktop/src/app/chat/hooks/use-composer-actions.test.ts +57 -0
  176. package/agent/apps/desktop/src/app/chat/hooks/use-composer-actions.ts +70 -16
  177. package/agent/apps/desktop/src/app/chat/hooks/use-file-drop-zone.ts +52 -16
  178. package/agent/apps/desktop/src/app/chat/index.tsx +234 -81
  179. package/agent/apps/desktop/src/app/chat/perf-probe.tsx +69 -21
  180. package/agent/apps/desktop/src/app/chat/right-rail/preview-console.tsx +44 -40
  181. package/agent/apps/desktop/src/app/chat/right-rail/preview-file.tsx +71 -25
  182. package/agent/apps/desktop/src/app/chat/right-rail/preview-pane.test.tsx +40 -1
  183. package/agent/apps/desktop/src/app/chat/right-rail/preview-pane.tsx +55 -53
  184. package/agent/apps/desktop/src/app/chat/right-rail/preview.tsx +35 -17
  185. package/agent/apps/desktop/src/app/chat/scroll-to-bottom-button.test.tsx +67 -0
  186. package/agent/apps/desktop/src/app/chat/scroll-to-bottom-button.tsx +74 -0
  187. package/agent/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx +356 -0
  188. package/agent/apps/desktop/src/app/chat/sidebar/index.tsx +1189 -364
  189. package/agent/apps/desktop/src/app/chat/sidebar/load-more-row.tsx +30 -0
  190. package/agent/apps/desktop/src/app/chat/sidebar/order.test.ts +21 -0
  191. package/agent/apps/desktop/src/app/chat/sidebar/order.ts +17 -0
  192. package/agent/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx +524 -0
  193. package/agent/apps/desktop/src/app/chat/sidebar/session-actions-menu.tsx +80 -45
  194. package/agent/apps/desktop/src/app/chat/sidebar/session-row.tsx +120 -25
  195. package/agent/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx +7 -13
  196. package/agent/apps/desktop/src/app/chat/sidebar/workspace-groups.test.ts +149 -0
  197. package/agent/apps/desktop/src/app/chat/sidebar/workspace-groups.ts +326 -0
  198. package/agent/apps/desktop/src/app/chat/thread-loading.ts +7 -2
  199. package/agent/apps/desktop/src/app/command-center/index.tsx +320 -581
  200. package/agent/apps/desktop/src/app/command-palette/index.tsx +681 -0
  201. package/agent/apps/desktop/src/app/command-palette/marketplace-theme-page.tsx +157 -0
  202. package/agent/apps/desktop/src/app/cron/index.tsx +392 -324
  203. package/agent/apps/desktop/src/app/cron/job-state.ts +29 -0
  204. package/agent/apps/desktop/src/app/desktop-controller.tsx +618 -123
  205. package/agent/apps/desktop/src/app/floating-hud.ts +22 -0
  206. package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx +265 -0
  207. package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts +260 -14
  208. package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-request.ts +48 -4
  209. package/agent/apps/desktop/src/app/hooks/use-keybinds.ts +270 -0
  210. package/agent/apps/desktop/src/app/hooks/use-refresh-hotkey.ts +45 -0
  211. package/agent/apps/desktop/src/app/layout-constants.ts +19 -0
  212. package/agent/apps/desktop/src/app/messaging/index.tsx +136 -241
  213. package/agent/apps/desktop/src/app/messaging/platform-icon.tsx +95 -0
  214. package/agent/apps/desktop/src/app/model-visibility-overlay.tsx +31 -0
  215. package/agent/apps/desktop/src/app/overlays/overlay-search-input.tsx +18 -62
  216. package/agent/apps/desktop/src/app/overlays/overlay-split-layout.tsx +59 -7
  217. package/agent/apps/desktop/src/app/overlays/overlay-view.tsx +9 -5
  218. package/agent/apps/desktop/src/app/page-search-shell.tsx +42 -20
  219. package/agent/apps/desktop/src/app/profiles/create-profile-dialog.tsx +165 -0
  220. package/agent/apps/desktop/src/app/profiles/delete-profile-dialog.tsx +65 -0
  221. package/agent/apps/desktop/src/app/profiles/index.tsx +174 -199
  222. package/agent/apps/desktop/src/app/profiles/rename-profile-dialog.tsx +125 -0
  223. package/agent/apps/desktop/src/app/right-sidebar/files/dnd-manager.ts +27 -0
  224. package/agent/apps/desktop/src/app/right-sidebar/files/ipc.test.ts +100 -0
  225. package/agent/apps/desktop/src/app/right-sidebar/files/ipc.ts +12 -18
  226. package/agent/apps/desktop/src/app/right-sidebar/files/remote-picker.tsx +177 -0
  227. package/agent/apps/desktop/src/app/right-sidebar/files/tree.tsx +35 -21
  228. package/agent/apps/desktop/src/app/right-sidebar/files/use-project-tree.test.ts +75 -3
  229. package/agent/apps/desktop/src/app/right-sidebar/files/use-project-tree.ts +152 -5
  230. package/agent/apps/desktop/src/app/right-sidebar/index.test.tsx +75 -0
  231. package/agent/apps/desktop/src/app/right-sidebar/index.tsx +166 -129
  232. package/agent/apps/desktop/src/app/right-sidebar/store.ts +19 -4
  233. package/agent/apps/desktop/src/app/right-sidebar/terminal/buffer.ts +65 -0
  234. package/agent/apps/desktop/src/app/right-sidebar/terminal/index.tsx +29 -34
  235. package/agent/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx +18 -6
  236. package/agent/apps/desktop/src/app/right-sidebar/terminal/selection.ts +93 -32
  237. package/agent/apps/desktop/src/app/right-sidebar/terminal/use-terminal-session.ts +381 -119
  238. package/agent/apps/desktop/src/app/routes.ts +9 -0
  239. package/agent/apps/desktop/src/app/session/hooks/use-cwd-actions.ts +17 -7
  240. package/agent/apps/desktop/src/app/session/hooks/use-message-stream.ts +365 -47
  241. package/agent/apps/desktop/src/app/session/hooks/use-model-controls.test.tsx +198 -0
  242. package/agent/apps/desktop/src/app/session/hooks/use-model-controls.ts +70 -34
  243. package/agent/apps/desktop/src/app/session/hooks/use-prompt-actions.test.tsx +1061 -0
  244. package/agent/apps/desktop/src/app/session/hooks/use-prompt-actions.ts +1143 -165
  245. package/agent/apps/desktop/src/app/session/hooks/use-route-resume.test.tsx +341 -2
  246. package/agent/apps/desktop/src/app/session/hooks/use-route-resume.ts +176 -5
  247. package/agent/apps/desktop/src/app/session/hooks/use-session-actions.test.tsx +259 -0
  248. package/agent/apps/desktop/src/app/session/hooks/use-session-actions.ts +452 -149
  249. package/agent/apps/desktop/src/app/session/hooks/use-session-state-cache.test.tsx +327 -0
  250. package/agent/apps/desktop/src/app/session/hooks/use-session-state-cache.ts +133 -4
  251. package/agent/apps/desktop/src/app/session-picker-overlay.tsx +32 -0
  252. package/agent/apps/desktop/src/app/session-switcher.tsx +107 -0
  253. package/agent/apps/desktop/src/app/settings/about-settings.tsx +45 -36
  254. package/agent/apps/desktop/src/app/settings/appearance-settings.tsx +243 -162
  255. package/agent/apps/desktop/src/app/settings/config-settings.tsx +86 -66
  256. package/agent/apps/desktop/src/app/settings/constants.ts +459 -122
  257. package/agent/apps/desktop/src/app/settings/credential-key-ui.tsx +373 -0
  258. package/agent/apps/desktop/src/app/settings/env-credentials.tsx +198 -0
  259. package/agent/apps/desktop/src/app/settings/env-var-actions-menu.tsx +136 -0
  260. package/agent/apps/desktop/src/app/settings/field-copy.ts +56 -0
  261. package/agent/apps/desktop/src/app/settings/gateway-settings.tsx +385 -72
  262. package/agent/apps/desktop/src/app/settings/helpers.test.ts +156 -1
  263. package/agent/apps/desktop/src/app/settings/helpers.ts +30 -2
  264. package/agent/apps/desktop/src/app/settings/index.tsx +118 -84
  265. package/agent/apps/desktop/src/app/settings/keys-settings.tsx +62 -419
  266. package/agent/apps/desktop/src/app/settings/mcp-settings.tsx +65 -60
  267. package/agent/apps/desktop/src/app/settings/model-settings.test.tsx +129 -5
  268. package/agent/apps/desktop/src/app/settings/model-settings.tsx +370 -65
  269. package/agent/apps/desktop/src/app/settings/notifications-settings.tsx +150 -0
  270. package/agent/apps/desktop/src/app/settings/primitives.tsx +5 -11
  271. package/agent/apps/desktop/src/app/settings/provider-config-panel.test.tsx +142 -0
  272. package/agent/apps/desktop/src/app/settings/provider-config-panel.tsx +182 -0
  273. package/agent/apps/desktop/src/app/settings/providers-settings.test.tsx +171 -0
  274. package/agent/apps/desktop/src/app/settings/providers-settings.tsx +471 -0
  275. package/agent/apps/desktop/src/app/settings/sessions-settings.tsx +183 -71
  276. package/agent/apps/desktop/src/app/settings/toolset-config-panel.test.tsx +135 -1
  277. package/agent/apps/desktop/src/app/settings/toolset-config-panel.tsx +180 -57
  278. package/agent/apps/desktop/src/app/settings/types.ts +9 -6
  279. package/agent/apps/desktop/src/app/settings/uninstall-section.tsx +185 -0
  280. package/agent/apps/desktop/src/app/settings/use-deep-link-highlight.ts +60 -0
  281. package/agent/apps/desktop/src/app/shell/app-shell.tsx +59 -13
  282. package/agent/apps/desktop/src/app/shell/gateway-menu-panel.tsx +37 -32
  283. package/agent/apps/desktop/src/app/shell/hooks/use-overlay-routing.ts +6 -3
  284. package/agent/apps/desktop/src/app/shell/hooks/use-statusbar-items.tsx +212 -53
  285. package/agent/apps/desktop/src/app/shell/keybind-panel.tsx +215 -0
  286. package/agent/apps/desktop/src/app/shell/model-edit-submenu.test.tsx +84 -0
  287. package/agent/apps/desktop/src/app/shell/model-edit-submenu.tsx +244 -0
  288. package/agent/apps/desktop/src/app/shell/model-menu-panel.tsx +392 -0
  289. package/agent/apps/desktop/src/app/shell/statusbar-controls.tsx +23 -33
  290. package/agent/apps/desktop/src/app/shell/titlebar-controls.tsx +79 -95
  291. package/agent/apps/desktop/src/app/shell/titlebar.ts +8 -2
  292. package/agent/apps/desktop/src/app/skills/index.test.tsx +11 -0
  293. package/agent/apps/desktop/src/app/skills/index.tsx +79 -64
  294. package/agent/apps/desktop/src/app/types.ts +85 -0
  295. package/agent/apps/desktop/src/app/updates-overlay.tsx +110 -105
  296. package/agent/apps/desktop/src/components/assistant-ui/ansi-text.tsx +34 -0
  297. package/agent/apps/desktop/src/components/assistant-ui/block-direction.test.tsx +129 -0
  298. package/agent/apps/desktop/src/components/assistant-ui/clarify-tool.tsx +102 -81
  299. package/agent/apps/desktop/src/components/assistant-ui/directive-text.tsx +92 -15
  300. package/agent/apps/desktop/src/components/assistant-ui/markdown-text.test.ts +38 -0
  301. package/agent/apps/desktop/src/components/assistant-ui/markdown-text.tsx +304 -45
  302. package/agent/apps/desktop/src/components/assistant-ui/message-render-boundary.test.tsx +80 -0
  303. package/agent/apps/desktop/src/components/assistant-ui/message-render-boundary.tsx +48 -0
  304. package/agent/apps/desktop/src/components/assistant-ui/streaming.test.tsx +142 -90
  305. package/agent/apps/desktop/src/components/assistant-ui/thread-list.tsx +337 -0
  306. package/agent/apps/desktop/src/components/assistant-ui/thread.tsx +667 -190
  307. package/agent/apps/desktop/src/components/assistant-ui/tool-approval-group.test.tsx +299 -0
  308. package/agent/apps/desktop/src/components/assistant-ui/tool-approval.test.tsx +133 -0
  309. package/agent/apps/desktop/src/components/assistant-ui/tool-approval.tsx +239 -0
  310. package/agent/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts +31 -0
  311. package/agent/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts +152 -134
  312. package/agent/apps/desktop/src/components/assistant-ui/tool-fallback.tsx +142 -150
  313. package/agent/apps/desktop/src/components/assistant-ui/tooltip-icon-button.tsx +14 -12
  314. package/agent/apps/desktop/src/components/assistant-ui/user-message-edit.test.tsx +141 -0
  315. package/agent/apps/desktop/src/components/assistant-ui/user-message-text.tsx +152 -0
  316. package/agent/apps/desktop/src/components/boot-failure-overlay.tsx +150 -33
  317. package/agent/apps/desktop/src/components/boot-failure-reauth.test.ts +100 -0
  318. package/agent/apps/desktop/src/components/boot-failure-reauth.ts +81 -0
  319. package/agent/apps/desktop/src/components/brand-mark.tsx +19 -0
  320. package/agent/apps/desktop/src/components/chat/code-card.tsx +1 -1
  321. package/agent/apps/desktop/src/components/chat/composer-dock.ts +31 -0
  322. package/agent/apps/desktop/src/components/chat/diff-lines.tsx +1 -1
  323. package/agent/apps/desktop/src/components/chat/disclosure-row.tsx +13 -3
  324. package/agent/apps/desktop/src/components/chat/expandable-block.tsx +52 -0
  325. package/agent/apps/desktop/src/components/chat/generated-image-result.tsx +174 -0
  326. package/agent/apps/desktop/src/components/chat/image-generation-placeholder.tsx +70 -37
  327. package/agent/apps/desktop/src/components/chat/intro.tsx +8 -7
  328. package/agent/apps/desktop/src/components/chat/preview-attachment.tsx +4 -2
  329. package/agent/apps/desktop/src/components/chat/shiki-highlighter.test.ts +37 -0
  330. package/agent/apps/desktop/src/components/chat/shiki-highlighter.tsx +96 -22
  331. package/agent/apps/desktop/src/components/chat/status-row.tsx +70 -0
  332. package/agent/apps/desktop/src/components/chat/status-section.tsx +42 -0
  333. package/agent/apps/desktop/src/components/chat/terminal-output.tsx +54 -0
  334. package/agent/apps/desktop/src/components/chat/zoomable-image.tsx +70 -109
  335. package/agent/apps/desktop/src/components/desktop-install-overlay.tsx +154 -84
  336. package/agent/apps/desktop/src/components/desktop-onboarding-overlay.test.tsx +38 -8
  337. package/agent/apps/desktop/src/components/desktop-onboarding-overlay.tsx +789 -233
  338. package/agent/apps/desktop/src/components/error-boundary.tsx +77 -0
  339. package/agent/apps/desktop/src/components/gateway-connecting-overlay.test.tsx +144 -0
  340. package/agent/apps/desktop/src/components/gateway-connecting-overlay.tsx +7 -1
  341. package/agent/apps/desktop/src/components/haptics-provider.tsx +24 -0
  342. package/agent/apps/desktop/src/components/language-switcher.test.tsx +53 -0
  343. package/agent/apps/desktop/src/components/language-switcher.tsx +175 -0
  344. package/agent/apps/desktop/src/components/model-picker.tsx +42 -40
  345. package/agent/apps/desktop/src/components/model-visibility-dialog.tsx +166 -0
  346. package/agent/apps/desktop/src/components/notifications.tsx +48 -27
  347. package/agent/apps/desktop/src/components/pane-shell/index.ts +1 -1
  348. package/agent/apps/desktop/src/components/pane-shell/pane-shell.tsx +146 -9
  349. package/agent/apps/desktop/src/components/prompt-overlays.tsx +234 -0
  350. package/agent/apps/desktop/src/components/session-picker.tsx +108 -0
  351. package/agent/apps/desktop/src/components/ui/action-status.tsx +25 -0
  352. package/agent/apps/desktop/src/components/ui/badge.tsx +35 -0
  353. package/agent/apps/desktop/src/components/ui/button.tsx +37 -13
  354. package/agent/apps/desktop/src/components/ui/confirm-dialog.tsx +109 -0
  355. package/agent/apps/desktop/src/components/ui/control.ts +25 -0
  356. package/agent/apps/desktop/src/components/ui/copy-button.test.tsx +36 -0
  357. package/agent/apps/desktop/src/components/ui/copy-button.tsx +38 -27
  358. package/agent/apps/desktop/src/components/ui/dialog.tsx +39 -11
  359. package/agent/apps/desktop/src/components/ui/dropdown-menu.tsx +98 -24
  360. package/agent/apps/desktop/src/components/ui/error-state.tsx +50 -0
  361. package/agent/apps/desktop/src/components/ui/fade-text.tsx +9 -2
  362. package/agent/apps/desktop/src/components/ui/{braille-spinner.tsx → glyph-spinner.tsx} +15 -13
  363. package/agent/apps/desktop/src/components/ui/input.tsx +5 -2
  364. package/agent/apps/desktop/src/components/ui/kbd.tsx +83 -12
  365. package/agent/apps/desktop/src/components/ui/log-view.tsx +19 -0
  366. package/agent/apps/desktop/src/components/ui/pagination.tsx +12 -5
  367. package/agent/apps/desktop/src/components/ui/popover.tsx +44 -0
  368. package/agent/apps/desktop/src/components/ui/search-field.tsx +80 -0
  369. package/agent/apps/desktop/src/components/ui/segmented-control.tsx +51 -0
  370. package/agent/apps/desktop/src/components/ui/select.tsx +10 -3
  371. package/agent/apps/desktop/src/components/ui/sheet.tsx +8 -2
  372. package/agent/apps/desktop/src/components/ui/sidebar.tsx +18 -25
  373. package/agent/apps/desktop/src/components/ui/switch.tsx +38 -15
  374. package/agent/apps/desktop/src/components/ui/textarea.tsx +4 -11
  375. package/agent/apps/desktop/src/components/ui/tool-icon.tsx +65 -0
  376. package/agent/apps/desktop/src/components/ui/tooltip.tsx +31 -4
  377. package/agent/apps/desktop/src/fonts/JetBrainsMono-Bold.woff2 +0 -0
  378. package/agent/apps/desktop/src/fonts/JetBrainsMono-Italic.woff2 +0 -0
  379. package/agent/apps/desktop/src/fonts/JetBrainsMono-Regular.woff2 +0 -0
  380. package/agent/apps/desktop/src/global.d.ts +181 -4
  381. package/agent/apps/desktop/src/hermes.test.ts +60 -0
  382. package/agent/apps/desktop/src/hermes.ts +190 -13
  383. package/agent/apps/desktop/src/hooks/use-image-download.ts +85 -0
  384. package/agent/apps/desktop/src/hooks/use-resize-observer.ts +13 -4
  385. package/agent/apps/desktop/src/hooks/use-worktree-info.ts +68 -0
  386. package/agent/apps/desktop/src/i18n/catalog.ts +12 -0
  387. package/agent/apps/desktop/src/i18n/context.test.tsx +232 -0
  388. package/agent/apps/desktop/src/i18n/context.tsx +183 -0
  389. package/agent/apps/desktop/src/i18n/define-locale.ts +41 -0
  390. package/agent/apps/desktop/src/i18n/en.ts +1921 -0
  391. package/agent/apps/desktop/src/i18n/index.ts +20 -0
  392. package/agent/apps/desktop/src/i18n/ja.ts +2053 -0
  393. package/agent/apps/desktop/src/i18n/languages.test.ts +43 -0
  394. package/agent/apps/desktop/src/i18n/languages.ts +86 -0
  395. package/agent/apps/desktop/src/i18n/runtime.test.ts +75 -0
  396. package/agent/apps/desktop/src/i18n/runtime.ts +53 -0
  397. package/agent/apps/desktop/src/i18n/types.ts +1559 -0
  398. package/agent/apps/desktop/src/i18n/zh-hant.ts +1992 -0
  399. package/agent/apps/desktop/src/i18n/zh.ts +2099 -0
  400. package/agent/apps/desktop/src/lib/ansi.test.ts +123 -0
  401. package/agent/apps/desktop/src/lib/ansi.ts +186 -0
  402. package/agent/apps/desktop/src/lib/chat-messages.test.ts +79 -0
  403. package/agent/apps/desktop/src/lib/chat-messages.ts +68 -29
  404. package/agent/apps/desktop/src/lib/chat-runtime.test.ts +65 -1
  405. package/agent/apps/desktop/src/lib/chat-runtime.ts +39 -3
  406. package/agent/apps/desktop/src/lib/completion-sound.ts +519 -0
  407. package/agent/apps/desktop/src/lib/desktop-fs.test.ts +116 -0
  408. package/agent/apps/desktop/src/lib/desktop-fs.ts +113 -0
  409. package/agent/apps/desktop/src/lib/desktop-slash-commands.test.ts +89 -6
  410. package/agent/apps/desktop/src/lib/desktop-slash-commands.ts +270 -131
  411. package/agent/apps/desktop/src/lib/external-link.test.tsx +27 -0
  412. package/agent/apps/desktop/src/lib/external-link.tsx +9 -2
  413. package/agent/apps/desktop/src/lib/gateway-events.test.ts +27 -0
  414. package/agent/apps/desktop/src/lib/gateway-events.ts +16 -0
  415. package/agent/apps/desktop/src/lib/gateway-ws-url.test.ts +78 -0
  416. package/agent/apps/desktop/src/lib/gateway-ws-url.ts +91 -0
  417. package/agent/apps/desktop/src/lib/generated-images.test.ts +97 -0
  418. package/agent/apps/desktop/src/lib/generated-images.ts +116 -0
  419. package/agent/apps/desktop/src/lib/haptics.ts +17 -0
  420. package/agent/apps/desktop/src/lib/icons.ts +10 -2
  421. package/agent/apps/desktop/src/lib/keybinds/actions.ts +137 -0
  422. package/agent/apps/desktop/src/lib/keybinds/combo.test.ts +86 -0
  423. package/agent/apps/desktop/src/lib/keybinds/combo.ts +195 -0
  424. package/agent/apps/desktop/src/lib/local-preview.ts +23 -2
  425. package/agent/apps/desktop/src/lib/markdown-preprocess.ts +20 -7
  426. package/agent/apps/desktop/src/lib/media.remote.test.ts +90 -0
  427. package/agent/apps/desktop/src/lib/media.ts +40 -1
  428. package/agent/apps/desktop/src/lib/model-status-label.test.ts +59 -0
  429. package/agent/apps/desktop/src/lib/model-status-label.ts +122 -0
  430. package/agent/apps/desktop/src/lib/mutable-ref.ts +6 -0
  431. package/agent/apps/desktop/src/lib/profile-color.ts +58 -0
  432. package/agent/apps/desktop/src/lib/query-client.ts +13 -0
  433. package/agent/apps/desktop/src/lib/remend-tail.test.ts +105 -0
  434. package/agent/apps/desktop/src/lib/remend-tail.ts +108 -0
  435. package/agent/apps/desktop/src/lib/session-export.ts +6 -3
  436. package/agent/apps/desktop/src/lib/session-ids.test.ts +44 -0
  437. package/agent/apps/desktop/src/lib/session-ids.ts +26 -0
  438. package/agent/apps/desktop/src/lib/session-search.test.ts +66 -0
  439. package/agent/apps/desktop/src/lib/session-search.ts +21 -0
  440. package/agent/apps/desktop/src/lib/session-source.ts +126 -0
  441. package/agent/apps/desktop/src/lib/storage.test.ts +25 -0
  442. package/agent/apps/desktop/src/lib/storage.ts +35 -1
  443. package/agent/apps/desktop/src/lib/todos.test.ts +46 -1
  444. package/agent/apps/desktop/src/lib/todos.ts +37 -0
  445. package/agent/apps/desktop/src/lib/tool-result-summary.ts +5 -1
  446. package/agent/apps/desktop/src/lib/update-copy.test.ts +38 -0
  447. package/agent/apps/desktop/src/lib/update-copy.ts +44 -0
  448. package/agent/apps/desktop/src/lib/use-enter-animation.ts +2 -2
  449. package/agent/apps/desktop/src/lib/yolo-session.ts +50 -0
  450. package/agent/apps/desktop/src/main.tsx +19 -19
  451. package/agent/apps/desktop/src/store/boot.ts +4 -3
  452. package/agent/apps/desktop/src/store/clarify.test.ts +81 -0
  453. package/agent/apps/desktop/src/store/clarify.ts +50 -13
  454. package/agent/apps/desktop/src/store/command-palette.ts +20 -0
  455. package/agent/apps/desktop/src/store/compaction.test.ts +53 -0
  456. package/agent/apps/desktop/src/store/compaction.ts +38 -0
  457. package/agent/apps/desktop/src/store/completion-sound.ts +32 -0
  458. package/agent/apps/desktop/src/store/composer-input-history.test.ts +147 -0
  459. package/agent/apps/desktop/src/store/composer-input-history.ts +158 -0
  460. package/agent/apps/desktop/src/store/composer-queue.test.ts +68 -0
  461. package/agent/apps/desktop/src/store/composer-queue.ts +76 -0
  462. package/agent/apps/desktop/src/store/composer-status.test.ts +99 -0
  463. package/agent/apps/desktop/src/store/composer-status.ts +277 -0
  464. package/agent/apps/desktop/src/store/composer.test.ts +106 -0
  465. package/agent/apps/desktop/src/store/composer.ts +116 -0
  466. package/agent/apps/desktop/src/store/cron.ts +19 -0
  467. package/agent/apps/desktop/src/store/gateway.ts +280 -6
  468. package/agent/apps/desktop/src/store/keybinds.ts +143 -0
  469. package/agent/apps/desktop/src/store/layout.ts +107 -9
  470. package/agent/apps/desktop/src/store/model-presets.test.ts +51 -0
  471. package/agent/apps/desktop/src/store/model-presets.ts +86 -0
  472. package/agent/apps/desktop/src/store/model-visibility.test.ts +99 -0
  473. package/agent/apps/desktop/src/store/model-visibility.ts +161 -0
  474. package/agent/apps/desktop/src/store/native-notifications.test.ts +192 -0
  475. package/agent/apps/desktop/src/store/native-notifications.ts +203 -0
  476. package/agent/apps/desktop/src/store/notifications.ts +10 -7
  477. package/agent/apps/desktop/src/store/onboarding.test.ts +271 -1
  478. package/agent/apps/desktop/src/store/onboarding.ts +268 -38
  479. package/agent/apps/desktop/src/store/preview.ts +10 -1
  480. package/agent/apps/desktop/src/store/profile.test.ts +89 -0
  481. package/agent/apps/desktop/src/store/profile.ts +395 -0
  482. package/agent/apps/desktop/src/store/prompts.test.ts +127 -0
  483. package/agent/apps/desktop/src/store/prompts.ts +117 -0
  484. package/agent/apps/desktop/src/store/session-switcher.test.ts +115 -0
  485. package/agent/apps/desktop/src/store/session-switcher.ts +128 -0
  486. package/agent/apps/desktop/src/store/session-sync.ts +25 -0
  487. package/agent/apps/desktop/src/store/session.test.ts +268 -2
  488. package/agent/apps/desktop/src/store/session.ts +392 -18
  489. package/agent/apps/desktop/src/store/subagents.ts +3 -0
  490. package/agent/apps/desktop/src/store/system-actions.ts +48 -0
  491. package/agent/apps/desktop/src/store/thread-scroll.ts +58 -5
  492. package/agent/apps/desktop/src/store/todos.test.ts +47 -0
  493. package/agent/apps/desktop/src/store/todos.ts +64 -0
  494. package/agent/apps/desktop/src/store/tool-dismiss.ts +45 -0
  495. package/agent/apps/desktop/src/store/translucency.ts +38 -0
  496. package/agent/apps/desktop/src/store/updates.test.ts +187 -2
  497. package/agent/apps/desktop/src/store/updates.ts +268 -18
  498. package/agent/apps/desktop/src/store/windows.test.ts +143 -0
  499. package/agent/apps/desktop/src/store/windows.ts +115 -0
  500. package/agent/apps/desktop/src/styles.css +510 -119
  501. package/agent/apps/desktop/src/themes/color.ts +142 -0
  502. package/agent/apps/desktop/src/themes/context.tsx +128 -75
  503. package/agent/apps/desktop/src/themes/install.test.ts +119 -0
  504. package/agent/apps/desktop/src/themes/install.ts +95 -0
  505. package/agent/apps/desktop/src/themes/presets.test.ts +33 -0
  506. package/agent/apps/desktop/src/themes/presets.ts +13 -4
  507. package/agent/apps/desktop/src/themes/profile-theme.test.ts +41 -0
  508. package/agent/apps/desktop/src/themes/types.ts +35 -0
  509. package/agent/apps/desktop/src/themes/user-themes.test.ts +63 -0
  510. package/agent/apps/desktop/src/themes/user-themes.ts +122 -0
  511. package/agent/apps/desktop/src/themes/vscode.test.ts +171 -0
  512. package/agent/apps/desktop/src/themes/vscode.ts +343 -0
  513. package/agent/apps/desktop/src/types/hermes.ts +138 -1
  514. package/agent/apps/desktop/tsconfig.json +2 -2
  515. package/agent/apps/desktop/vite.config.ts +18 -0
  516. package/agent/apps/shared/package.json +1 -1
  517. package/agent/apps/shared/src/json-rpc-gateway.ts +63 -2
  518. package/agent/apps/shared/tsconfig.json +2 -2
  519. package/agent/cli-config.yaml.example +78 -1
  520. package/agent/cli.py +2177 -3162
  521. package/agent/cron/blueprint_catalog.py +713 -0
  522. package/agent/cron/jobs.py +226 -110
  523. package/agent/cron/scheduler.py +468 -193
  524. package/agent/cron/scheduler_provider.py +177 -0
  525. package/agent/cron/scripts/__init__.py +1 -0
  526. package/agent/cron/scripts/classify_items.py +226 -0
  527. package/agent/cron/suggestion_catalog.py +154 -0
  528. package/agent/cron/suggestions.py +257 -0
  529. package/agent/docs/chronos-managed-cron-contract.md +196 -0
  530. package/agent/docs/design/profile-builder.md +146 -0
  531. package/agent/docs/middleware/README.md +260 -0
  532. package/agent/docs/observability/README.md +316 -0
  533. package/agent/docs/plans/2026-06-09-003-fix-telegram-stream-overflow-continuations-plan.md +240 -0
  534. package/agent/docs/rca-ssl-cacert-post-git-pull.md +54 -0
  535. package/agent/docs/relay-connector-contract.md +285 -0
  536. package/agent/gateway/authz_mixin.py +536 -0
  537. package/agent/gateway/channel_directory.py +65 -3
  538. package/agent/gateway/config.py +222 -12
  539. package/agent/gateway/display_config.py +10 -0
  540. package/agent/gateway/hooks.py +17 -0
  541. package/agent/gateway/kanban_watchers.py +1146 -0
  542. package/agent/gateway/message_timestamps.py +166 -0
  543. package/agent/gateway/platforms/ADDING_A_PLATFORM.md +29 -0
  544. package/agent/gateway/platforms/api_server.py +216 -38
  545. package/agent/gateway/platforms/base.py +210 -58
  546. package/agent/gateway/platforms/email.py +122 -12
  547. package/agent/gateway/platforms/feishu.py +80 -11
  548. package/agent/gateway/platforms/feishu_meeting_invite.py +212 -0
  549. package/agent/gateway/platforms/matrix.py +1498 -297
  550. package/agent/gateway/platforms/qqbot/adapter.py +6 -0
  551. package/agent/gateway/platforms/signal.py +8 -0
  552. package/agent/gateway/platforms/slack.py +308 -12
  553. package/agent/gateway/platforms/telegram.py +831 -24
  554. package/agent/gateway/platforms/webhook.py +109 -21
  555. package/agent/gateway/platforms/weixin.py +113 -2
  556. package/agent/gateway/platforms/whatsapp.py +94 -288
  557. package/agent/gateway/platforms/whatsapp_cloud.py +1956 -0
  558. package/agent/gateway/platforms/whatsapp_common.py +367 -0
  559. package/agent/gateway/platforms/yuanbao.py +608 -191
  560. package/agent/gateway/platforms/yuanbao_proto.py +232 -23
  561. package/agent/gateway/relay/__init__.py +375 -0
  562. package/agent/gateway/relay/adapter.py +222 -0
  563. package/agent/gateway/relay/auth.py +168 -0
  564. package/agent/gateway/relay/descriptor.py +118 -0
  565. package/agent/gateway/relay/transport.py +101 -0
  566. package/agent/gateway/relay/ws_transport.py +327 -0
  567. package/agent/gateway/response_filters.py +53 -0
  568. package/agent/gateway/rich_sent_store.py +80 -0
  569. package/agent/gateway/run.py +2940 -5001
  570. package/agent/gateway/session.py +109 -8
  571. package/agent/gateway/session_context.py +22 -4
  572. package/agent/gateway/slash_commands.py +3854 -0
  573. package/agent/gateway/status.py +141 -21
  574. package/agent/gateway/stream_consumer.py +288 -31
  575. package/agent/hermes-already-has-routines.md +1 -1
  576. package/agent/hermes_cli/__init__.py +62 -17
  577. package/agent/hermes_cli/_parser.py +30 -0
  578. package/agent/hermes_cli/_subprocess_compat.py +61 -0
  579. package/agent/hermes_cli/active_sessions.py +320 -0
  580. package/agent/hermes_cli/auth.py +707 -59
  581. package/agent/hermes_cli/auth_commands.py +39 -22
  582. package/agent/hermes_cli/backup.py +109 -7
  583. package/agent/hermes_cli/banner.py +88 -0
  584. package/agent/hermes_cli/blueprint_cmd.py +318 -0
  585. package/agent/hermes_cli/cli_agent_setup_mixin.py +684 -0
  586. package/agent/hermes_cli/cli_commands_mixin.py +2293 -0
  587. package/agent/hermes_cli/commands.py +215 -91
  588. package/agent/hermes_cli/config.py +967 -130
  589. package/agent/hermes_cli/container_boot.py +76 -11
  590. package/agent/hermes_cli/cron.py +5 -11
  591. package/agent/hermes_cli/curator.py +21 -0
  592. package/agent/hermes_cli/dashboard_auth/__init__.py +2 -0
  593. package/agent/hermes_cli/dashboard_auth/base.py +62 -0
  594. package/agent/hermes_cli/dashboard_auth/cookies.py +32 -19
  595. package/agent/hermes_cli/dashboard_auth/login_page.py +156 -6
  596. package/agent/hermes_cli/dashboard_auth/middleware.py +28 -4
  597. package/agent/hermes_cli/dashboard_auth/prefix.py +46 -2
  598. package/agent/hermes_cli/dashboard_auth/public_paths.py +6 -0
  599. package/agent/hermes_cli/dashboard_auth/routes.py +158 -2
  600. package/agent/hermes_cli/dashboard_auth/ws_tickets.py +85 -11
  601. package/agent/hermes_cli/dashboard_register.py +427 -0
  602. package/agent/hermes_cli/debug.py +155 -50
  603. package/agent/hermes_cli/doctor.py +255 -14
  604. package/agent/hermes_cli/dump.py +60 -6
  605. package/agent/hermes_cli/env_loader.py +33 -0
  606. package/agent/hermes_cli/gateway.py +755 -103
  607. package/agent/hermes_cli/gateway_enroll.py +250 -0
  608. package/agent/hermes_cli/gateway_windows.py +254 -11
  609. package/agent/hermes_cli/gui_uninstall.py +285 -0
  610. package/agent/hermes_cli/inventory.py +105 -4
  611. package/agent/hermes_cli/kanban.py +58 -71
  612. package/agent/hermes_cli/kanban_db.py +391 -14
  613. package/agent/hermes_cli/kanban_decompose.py +2 -2
  614. package/agent/hermes_cli/kanban_specify.py +3 -1
  615. package/agent/hermes_cli/logs.py +2 -0
  616. package/agent/hermes_cli/main.py +2889 -5287
  617. package/agent/hermes_cli/managed_scope.py +214 -0
  618. package/agent/hermes_cli/managed_uv.py +254 -0
  619. package/agent/hermes_cli/mcp_catalog.py +6 -3
  620. package/agent/hermes_cli/mcp_config.py +145 -21
  621. package/agent/hermes_cli/mcp_security.py +96 -0
  622. package/agent/hermes_cli/mcp_startup.py +32 -3
  623. package/agent/hermes_cli/memory_providers.py +149 -0
  624. package/agent/hermes_cli/memory_setup.py +97 -42
  625. package/agent/hermes_cli/middleware.py +313 -0
  626. package/agent/hermes_cli/model_catalog.py +31 -0
  627. package/agent/hermes_cli/model_cost_guard.py +134 -0
  628. package/agent/hermes_cli/model_normalize.py +2 -1
  629. package/agent/hermes_cli/model_setup_flows.py +2759 -0
  630. package/agent/hermes_cli/model_switch.py +242 -27
  631. package/agent/hermes_cli/models.py +284 -44
  632. package/agent/hermes_cli/nous_account.py +33 -6
  633. package/agent/hermes_cli/nous_billing.py +406 -0
  634. package/agent/hermes_cli/nous_subscription.py +202 -5
  635. package/agent/hermes_cli/platforms.py +1 -0
  636. package/agent/hermes_cli/plugins.py +218 -18
  637. package/agent/hermes_cli/plugins_cmd.py +249 -105
  638. package/agent/hermes_cli/portal_cli.py +56 -16
  639. package/agent/hermes_cli/profile_distribution.py +6 -1
  640. package/agent/hermes_cli/profiles.py +283 -32
  641. package/agent/hermes_cli/provider_catalog.py +170 -0
  642. package/agent/hermes_cli/providers.py +4 -1
  643. package/agent/hermes_cli/pty_bridge.py +53 -4
  644. package/agent/hermes_cli/runtime_provider.py +216 -34
  645. package/agent/hermes_cli/secret_prompt.py +4 -4
  646. package/agent/hermes_cli/secrets_cli.py +24 -0
  647. package/agent/hermes_cli/send_cmd.py +28 -2
  648. package/agent/hermes_cli/service_manager.py +166 -19
  649. package/agent/hermes_cli/session_listing.py +97 -0
  650. package/agent/hermes_cli/setup.py +158 -94
  651. package/agent/hermes_cli/setup_whatsapp_cloud.py +541 -0
  652. package/agent/hermes_cli/skills_config.py +8 -2
  653. package/agent/hermes_cli/skills_hub.py +149 -7
  654. package/agent/hermes_cli/status.py +2 -2
  655. package/agent/hermes_cli/subcommands/__init__.py +18 -0
  656. package/agent/hermes_cli/subcommands/_shared.py +29 -0
  657. package/agent/hermes_cli/subcommands/acp.py +52 -0
  658. package/agent/hermes_cli/subcommands/auth.py +109 -0
  659. package/agent/hermes_cli/subcommands/backup.py +38 -0
  660. package/agent/hermes_cli/subcommands/claw.py +92 -0
  661. package/agent/hermes_cli/subcommands/config.py +49 -0
  662. package/agent/hermes_cli/subcommands/cron.py +163 -0
  663. package/agent/hermes_cli/subcommands/dashboard.py +143 -0
  664. package/agent/hermes_cli/subcommands/debug.py +77 -0
  665. package/agent/hermes_cli/subcommands/doctor.py +35 -0
  666. package/agent/hermes_cli/subcommands/dump.py +28 -0
  667. package/agent/hermes_cli/subcommands/gateway.py +332 -0
  668. package/agent/hermes_cli/subcommands/gui.py +63 -0
  669. package/agent/hermes_cli/subcommands/hooks.py +77 -0
  670. package/agent/hermes_cli/subcommands/import_cmd.py +31 -0
  671. package/agent/hermes_cli/subcommands/insights.py +25 -0
  672. package/agent/hermes_cli/subcommands/login.py +78 -0
  673. package/agent/hermes_cli/subcommands/logout.py +28 -0
  674. package/agent/hermes_cli/subcommands/logs.py +78 -0
  675. package/agent/hermes_cli/subcommands/mcp.py +108 -0
  676. package/agent/hermes_cli/subcommands/memory.py +53 -0
  677. package/agent/hermes_cli/subcommands/model.py +72 -0
  678. package/agent/hermes_cli/subcommands/pairing.py +36 -0
  679. package/agent/hermes_cli/subcommands/plugins.py +94 -0
  680. package/agent/hermes_cli/subcommands/postinstall.py +23 -0
  681. package/agent/hermes_cli/subcommands/profile.py +203 -0
  682. package/agent/hermes_cli/subcommands/prompt_size.py +36 -0
  683. package/agent/hermes_cli/subcommands/security.py +62 -0
  684. package/agent/hermes_cli/subcommands/setup.py +58 -0
  685. package/agent/hermes_cli/subcommands/skills.py +298 -0
  686. package/agent/hermes_cli/subcommands/slack.py +60 -0
  687. package/agent/hermes_cli/subcommands/status.py +28 -0
  688. package/agent/hermes_cli/subcommands/tools.py +95 -0
  689. package/agent/hermes_cli/subcommands/uninstall.py +41 -0
  690. package/agent/hermes_cli/subcommands/update.py +70 -0
  691. package/agent/hermes_cli/subcommands/version.py +18 -0
  692. package/agent/hermes_cli/subcommands/webhook.py +76 -0
  693. package/agent/hermes_cli/subcommands/whatsapp.py +22 -0
  694. package/agent/hermes_cli/suggestions_cmd.py +153 -0
  695. package/agent/hermes_cli/telegram_managed_bot.py +358 -0
  696. package/agent/hermes_cli/tips.py +3 -4
  697. package/agent/hermes_cli/tools_config.py +155 -28
  698. package/agent/hermes_cli/uninstall.py +231 -35
  699. package/agent/hermes_cli/web_server.py +6188 -975
  700. package/agent/hermes_cli/win_pty_bridge.py +179 -0
  701. package/agent/hermes_cli/write_approval_commands.py +209 -0
  702. package/agent/hermes_constants.py +164 -33
  703. package/agent/hermes_logging.py +74 -2
  704. package/agent/hermes_state.py +919 -106
  705. package/agent/hermes_time.py +20 -0
  706. package/agent/locales/af.yaml +23 -0
  707. package/agent/locales/de.yaml +23 -0
  708. package/agent/locales/en.yaml +20 -0
  709. package/agent/locales/es.yaml +23 -0
  710. package/agent/locales/fr.yaml +23 -0
  711. package/agent/locales/ga.yaml +23 -0
  712. package/agent/locales/hu.yaml +23 -0
  713. package/agent/locales/it.yaml +23 -0
  714. package/agent/locales/ja.yaml +23 -0
  715. package/agent/locales/ko.yaml +23 -0
  716. package/agent/locales/pt.yaml +23 -0
  717. package/agent/locales/ru.yaml +23 -0
  718. package/agent/locales/tr.yaml +23 -0
  719. package/agent/locales/uk.yaml +23 -0
  720. package/agent/locales/zh-hant.yaml +23 -0
  721. package/agent/locales/zh.yaml +23 -0
  722. package/agent/model_tools.py +204 -40
  723. package/agent/optional-mcps/clawpump/manifest.yaml +4 -2
  724. package/agent/optional-mcps/clawpump-stdio/manifest.yaml +2 -0
  725. package/agent/optional-mcps/unreal-engine/manifest.yaml +54 -0
  726. package/agent/optional-skills/blockchain/hyperliquid/SKILL.md +2 -2
  727. package/agent/optional-skills/blockchain/hyperliquid/scripts/hyperliquid_client.py +1 -1
  728. package/agent/optional-skills/creative/kanban-video-orchestrator/SKILL.md +1 -1
  729. package/agent/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl +4 -3
  730. package/agent/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md +6 -4
  731. package/agent/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md +2 -2
  732. package/agent/{skills/software-development → optional-skills/devops}/hermes-s6-container-supervision/SKILL.md +2 -0
  733. package/agent/optional-skills/devops/watchers/SKILL.md +1 -1
  734. package/agent/optional-skills/devops/watchers/scripts/watch_github.py +2 -1
  735. package/agent/optional-skills/payments/mpp-agent/SKILL.md +124 -0
  736. package/agent/optional-skills/payments/stripe-link-cli/SKILL.md +184 -0
  737. package/agent/optional-skills/payments/stripe-projects/SKILL.md +120 -0
  738. package/agent/optional-skills/productivity/canvas/SKILL.md +1 -1
  739. package/agent/optional-skills/productivity/canvas/scripts/canvas_api.py +4 -1
  740. package/agent/optional-skills/productivity/shop/SKILL.md +224 -0
  741. package/agent/optional-skills/productivity/shop/references/catalog-mcp.md +236 -0
  742. package/agent/optional-skills/productivity/shop/references/direct-api.md +278 -0
  743. package/agent/optional-skills/productivity/shop/references/legal.md +3 -0
  744. package/agent/optional-skills/productivity/shop/references/safety.md +36 -0
  745. package/agent/optional-skills/productivity/shopify/SKILL.md +1 -1
  746. package/agent/optional-skills/productivity/siyuan/SKILL.md +1 -1
  747. package/agent/optional-skills/productivity/telephony/SKILL.md +4 -4
  748. package/agent/optional-skills/productivity/telephony/scripts/telephony.py +15 -15
  749. package/agent/optional-skills/security/1password/SKILL.md +1 -1
  750. package/agent/{skills/red-teaming → optional-skills/security}/godmode/SKILL.md +3 -4
  751. package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/auto_jailbreak.py +3 -1
  752. package/agent/optional-skills/software-development/rest-graphql-debug/SKILL.md +1 -1
  753. package/agent/{skills → optional-skills}/software-development/subagent-driven-development/SKILL.md +5 -5
  754. package/agent/package-lock.json +4082 -7907
  755. package/agent/package.json +18 -3
  756. package/agent/plugins/browser/firecrawl/provider.py +4 -1
  757. package/agent/plugins/cron/__init__.py +344 -0
  758. package/agent/plugins/cron/chronos/__init__.py +241 -0
  759. package/agent/plugins/cron/chronos/_nas_client.py +123 -0
  760. package/agent/plugins/cron/chronos/plugin.yaml +9 -0
  761. package/agent/plugins/cron/chronos/verify.py +103 -0
  762. package/agent/plugins/dashboard_auth/basic/__init__.py +491 -0
  763. package/agent/plugins/dashboard_auth/basic/plugin.yaml +7 -0
  764. package/agent/plugins/dashboard_auth/nous/__init__.py +12 -14
  765. package/agent/plugins/dashboard_auth/self_hosted/__init__.py +736 -0
  766. package/agent/plugins/dashboard_auth/self_hosted/plugin.yaml +8 -0
  767. package/agent/plugins/disk-cleanup/disk_cleanup.py +100 -20
  768. package/agent/plugins/google_meet/audio_bridge.py +4 -0
  769. package/agent/plugins/google_meet/meet_bot.py +7 -1
  770. package/agent/plugins/hermes-achievements/dashboard/dist/index.js +9 -15
  771. package/agent/plugins/image_gen/fal/__init__.py +35 -6
  772. package/agent/plugins/image_gen/krea/__init__.py +56 -13
  773. package/agent/plugins/image_gen/openai/__init__.py +122 -24
  774. package/agent/plugins/image_gen/openai-codex/__init__.py +28 -2
  775. package/agent/plugins/image_gen/xai/__init__.py +92 -12
  776. package/agent/plugins/kanban/dashboard/dist/index.js +63 -48
  777. package/agent/plugins/kanban/dashboard/plugin_api.py +39 -35
  778. package/agent/plugins/memory/__init__.py +48 -5
  779. package/agent/plugins/memory/byterover/__init__.py +1 -0
  780. package/agent/plugins/memory/hindsight/README.md +1 -1
  781. package/agent/plugins/memory/hindsight/__init__.py +138 -24
  782. package/agent/plugins/memory/hindsight/plugin.yaml +1 -1
  783. package/agent/plugins/memory/honcho/README.md +13 -10
  784. package/agent/plugins/memory/honcho/cli.py +247 -122
  785. package/agent/plugins/memory/honcho/client.py +112 -102
  786. package/agent/plugins/memory/openviking/README.md +12 -1
  787. package/agent/plugins/memory/openviking/__init__.py +2281 -107
  788. package/agent/plugins/memory/openviking/plugin.yaml +1 -2
  789. package/agent/plugins/memory/supermemory/README.md +22 -10
  790. package/agent/plugins/memory/supermemory/__init__.py +142 -37
  791. package/agent/plugins/memory/supermemory/plugin.yaml +1 -1
  792. package/agent/plugins/model-providers/anthropic/__init__.py +1 -0
  793. package/agent/plugins/model-providers/bedrock/__init__.py +1 -0
  794. package/agent/plugins/model-providers/copilot-acp/__init__.py +1 -0
  795. package/agent/plugins/model-providers/custom/__init__.py +8 -2
  796. package/agent/plugins/model-providers/kimi-coding/__init__.py +16 -7
  797. package/agent/plugins/model-providers/minimax/__init__.py +60 -8
  798. package/agent/plugins/model-providers/opencode-zen/__init__.py +12 -3
  799. package/agent/plugins/model-providers/openrouter/__init__.py +75 -4
  800. package/agent/plugins/model-providers/xiaomi/__init__.py +2 -0
  801. package/agent/plugins/model-providers/zai/__init__.py +1 -0
  802. package/agent/plugins/observability/langfuse/__init__.py +147 -14
  803. package/agent/plugins/observability/nemo_relay/README.md +559 -0
  804. package/agent/plugins/observability/nemo_relay/__init__.py +962 -0
  805. package/agent/plugins/observability/nemo_relay/plugin.yaml +20 -0
  806. package/agent/plugins/platforms/discord/adapter.py +932 -61
  807. package/agent/plugins/platforms/discord/voice_mixer.py +379 -0
  808. package/agent/plugins/platforms/google_chat/adapter.py +9 -3
  809. package/agent/plugins/platforms/google_chat/oauth.py +1 -1
  810. package/agent/plugins/platforms/homeassistant/__init__.py +3 -0
  811. package/agent/{gateway/platforms/homeassistant.py → plugins/platforms/homeassistant/adapter.py} +128 -0
  812. package/agent/plugins/platforms/homeassistant/plugin.yaml +22 -0
  813. package/agent/plugins/platforms/irc/adapter.py +4 -1
  814. package/agent/plugins/platforms/line/adapter.py +16 -1
  815. package/agent/plugins/platforms/mattermost/adapter.py +100 -24
  816. package/agent/plugins/platforms/photon/README.md +179 -0
  817. package/agent/plugins/platforms/photon/__init__.py +4 -0
  818. package/agent/plugins/platforms/photon/adapter.py +1586 -0
  819. package/agent/plugins/platforms/photon/auth.py +1046 -0
  820. package/agent/plugins/platforms/photon/cli.py +439 -0
  821. package/agent/plugins/platforms/photon/plugin.yaml +88 -0
  822. package/agent/plugins/platforms/photon/sidecar/README.md +52 -0
  823. package/agent/plugins/platforms/photon/sidecar/index.mjs +720 -0
  824. package/agent/plugins/platforms/photon/sidecar/package-lock.json +1730 -0
  825. package/agent/plugins/platforms/photon/sidecar/package.json +25 -0
  826. package/agent/plugins/platforms/photon/sidecar/patch-spectrum-mixed-attachments.mjs +155 -0
  827. package/agent/plugins/platforms/raft/__init__.py +3 -0
  828. package/agent/plugins/platforms/raft/adapter.py +774 -0
  829. package/agent/plugins/platforms/raft/plugin.yaml +19 -0
  830. package/agent/plugins/platforms/simplex/adapter.py +777 -220
  831. package/agent/plugins/platforms/simplex/plugin.yaml +21 -2
  832. package/agent/plugins/platforms/teams/adapter.py +175 -5
  833. package/agent/plugins/plugin_utils.py +135 -0
  834. package/agent/plugins/video_gen/fal/__init__.py +10 -3
  835. package/agent/plugins/web/searxng/provider.py +15 -2
  836. package/agent/plugins/web/xai/provider.py +2 -2
  837. package/agent/providers/base.py +22 -3
  838. package/agent/pyproject.toml +115 -21
  839. package/agent/run_agent.py +733 -39
  840. package/agent/scripts/build_skills_index.py +51 -19
  841. package/agent/scripts/check_subprocess_stdin.py +177 -0
  842. package/agent/scripts/contributor_audit.py +2 -0
  843. package/agent/scripts/docker_config_migrate.py +67 -0
  844. package/agent/scripts/install.cmd +3 -3
  845. package/agent/scripts/install.ps1 +580 -154
  846. package/agent/scripts/install.sh +402 -185
  847. package/agent/scripts/lib/node-bootstrap.sh +39 -4
  848. package/agent/scripts/release.py +183 -0
  849. package/agent/scripts/run_tests.sh +1 -0
  850. package/agent/scripts/run_tests_parallel.py +18 -23
  851. package/agent/scripts/whatsapp-bridge/bridge.js +25 -4
  852. package/agent/setup.py +59 -0
  853. package/agent/skills/autonomous-ai-agents/codex/SKILL.md +19 -0
  854. package/agent/skills/autonomous-ai-agents/hermes-agent/SKILL.md +10 -3
  855. package/agent/skills/{mcp/native-mcp/SKILL.md → autonomous-ai-agents/hermes-agent/references/native-mcp.md} +0 -13
  856. package/agent/skills/{devops/webhook-subscriptions/SKILL.md → autonomous-ai-agents/hermes-agent/references/webhooks.md} +1 -11
  857. package/agent/skills/clawpump/SKILL.md +3 -1
  858. package/agent/skills/devops/kanban-orchestrator/SKILL.md +1 -0
  859. package/agent/skills/devops/kanban-worker/SKILL.md +1 -0
  860. package/agent/skills/github/github-auth/SKILL.md +2 -2
  861. package/agent/skills/github/github-auth/scripts/gh-env.sh +2 -2
  862. package/agent/skills/github/github-code-review/SKILL.md +2 -2
  863. package/agent/skills/github/github-issues/SKILL.md +2 -2
  864. package/agent/skills/github/github-pr-workflow/SKILL.md +2 -2
  865. package/agent/skills/github/github-repo-management/SKILL.md +2 -2
  866. package/agent/skills/media/gif-search/SKILL.md +1 -1
  867. package/agent/skills/media/youtube-content/SKILL.md +10 -7
  868. package/agent/skills/media/youtube-content/scripts/fetch_transcript.py +3 -3
  869. package/agent/skills/note-taking/obsidian/SKILL.md +1 -1
  870. package/agent/skills/productivity/airtable/SKILL.md +2 -2
  871. package/agent/skills/productivity/google-workspace/scripts/setup.py +33 -7
  872. package/agent/skills/productivity/notion/SKILL.md +2 -2
  873. package/agent/skills/productivity/teams-meeting-pipeline/SKILL.md +1 -1
  874. package/agent/skills/research/llm-wiki/SKILL.md +1 -1
  875. package/agent/skills/social-media/xurl/SKILL.md +9 -0
  876. package/agent/skills/software-development/hermes-agent-skill-authoring/SKILL.md +1 -1
  877. package/agent/skills/software-development/plan/SKILL.md +285 -5
  878. package/agent/skills/software-development/requesting-code-review/SKILL.md +2 -2
  879. package/agent/skills/software-development/simplify-code/SKILL.md +212 -0
  880. package/agent/skills/software-development/spike/SKILL.md +2 -2
  881. package/agent/skills/software-development/systematic-debugging/SKILL.md +1 -1
  882. package/agent/skills/software-development/test-driven-development/SKILL.md +1 -1
  883. package/agent/tools/approval.py +302 -4
  884. package/agent/tools/async_delegation.py +386 -0
  885. package/agent/tools/blueprints.py +325 -0
  886. package/agent/tools/browser_cdp_tool.py +3 -3
  887. package/agent/tools/browser_tool.py +34 -6
  888. package/agent/tools/checkpoint_manager.py +31 -1
  889. package/agent/tools/clarify_tool.py +55 -5
  890. package/agent/tools/code_execution_tool.py +31 -14
  891. package/agent/tools/computer_use/cua_backend.py +81 -3
  892. package/agent/tools/computer_use/tool.py +79 -5
  893. package/agent/tools/computer_use/vision_routing.py +55 -3
  894. package/agent/tools/credential_files.py +31 -12
  895. package/agent/tools/cronjob_tools.py +30 -20
  896. package/agent/tools/delegate_tool.py +356 -31
  897. package/agent/tools/env_probe.py +1 -0
  898. package/agent/tools/environments/docker.py +163 -8
  899. package/agent/tools/environments/file_sync.py +2 -1
  900. package/agent/tools/environments/local.py +74 -23
  901. package/agent/tools/environments/singularity.py +4 -1
  902. package/agent/tools/environments/ssh.py +78 -11
  903. package/agent/tools/file_operations.py +277 -41
  904. package/agent/tools/file_tools.py +166 -28
  905. package/agent/tools/image_generation_tool.py +515 -29
  906. package/agent/tools/kanban_tools.py +99 -0
  907. package/agent/tools/lazy_deps.py +33 -2
  908. package/agent/tools/mcp_oauth.py +5 -5
  909. package/agent/tools/mcp_oauth_manager.py +7 -5
  910. package/agent/tools/mcp_tool.py +840 -33
  911. package/agent/tools/memory_tool.py +335 -38
  912. package/agent/tools/osv_check.py +15 -1
  913. package/agent/tools/process_registry.py +155 -11
  914. package/agent/tools/read_extract.py +248 -0
  915. package/agent/tools/read_terminal_tool.py +93 -0
  916. package/agent/tools/schema_sanitizer.py +38 -0
  917. package/agent/tools/send_message_tool.py +163 -49
  918. package/agent/tools/session_search_tool.py +189 -7
  919. package/agent/tools/skill_manager_tool.py +202 -3
  920. package/agent/tools/skill_usage.py +52 -4
  921. package/agent/tools/skills_hub.py +184 -44
  922. package/agent/tools/skills_sync.py +232 -5
  923. package/agent/tools/skills_tool.py +125 -11
  924. package/agent/tools/terminal_tool.py +148 -26
  925. package/agent/tools/tirith_security.py +2 -0
  926. package/agent/tools/todo_tool.py +32 -1
  927. package/agent/tools/transcription_tools.py +13 -5
  928. package/agent/tools/tts_tool.py +332 -38
  929. package/agent/tools/url_safety.py +52 -1
  930. package/agent/tools/vision_tools.py +124 -39
  931. package/agent/tools/voice_mode.py +4 -3
  932. package/agent/tools/web_tools.py +45 -15
  933. package/agent/tools/write_approval.py +493 -0
  934. package/agent/toolsets.py +34 -10
  935. package/agent/trajectory_compressor.py +81 -10
  936. package/agent/tui_gateway/entry.py +43 -6
  937. package/agent/tui_gateway/server.py +3335 -330
  938. package/agent/tui_gateway/slash_worker.py +61 -0
  939. package/agent/tui_gateway/ws.py +67 -9
  940. package/agent/ui-tui/eslint.config.mjs +0 -4
  941. package/agent/ui-tui/package.json +6 -6
  942. package/agent/ui-tui/packages/hermes-ink/package.json +1 -1
  943. package/agent/ui-tui/packages/hermes-ink/src/ink/app-mouse.test.ts +34 -1
  944. package/agent/ui-tui/packages/hermes-ink/src/ink/app-rawmode-mouse.test.ts +91 -0
  945. package/agent/ui-tui/packages/hermes-ink/src/ink/components/App.tsx +35 -2
  946. package/agent/ui-tui/packages/hermes-ink/src/ink/events/input-event.ts +4 -11
  947. package/agent/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts +23 -57
  948. package/agent/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts +11 -135
  949. package/agent/ui-tui/packages/hermes-ink/src/ink/termio/tokenize.test.ts +185 -0
  950. package/agent/ui-tui/packages/hermes-ink/src/ink/termio/tokenize.ts +37 -3
  951. package/agent/ui-tui/packages/hermes-ink/src/utils/execFileNoThrow.ts +5 -5
  952. package/agent/ui-tui/src/__tests__/appChromeStatusRule.test.tsx +217 -0
  953. package/agent/ui-tui/src/__tests__/appChromeStatusRuleDevCredits.test.tsx +73 -0
  954. package/agent/ui-tui/src/__tests__/approvalAction.test.ts +11 -0
  955. package/agent/ui-tui/src/__tests__/billingCommand.test.ts +301 -0
  956. package/agent/ui-tui/src/__tests__/blockLayout.test.ts +122 -0
  957. package/agent/ui-tui/src/__tests__/brandingMcpCount.test.ts +111 -0
  958. package/agent/ui-tui/src/__tests__/completionApply.test.ts +51 -0
  959. package/agent/ui-tui/src/__tests__/createGatewayEventHandler.test.ts +487 -2
  960. package/agent/ui-tui/src/__tests__/createSlashHandler.test.ts +54 -0
  961. package/agent/ui-tui/src/__tests__/creditsCommand.test.ts +144 -0
  962. package/agent/ui-tui/src/__tests__/gatewayClient.test.ts +120 -99
  963. package/agent/ui-tui/src/__tests__/gracefulExit.test.ts +11 -0
  964. package/agent/ui-tui/src/__tests__/memoryMonitor.test.ts +102 -0
  965. package/agent/ui-tui/src/__tests__/paths.test.ts +41 -1
  966. package/agent/ui-tui/src/__tests__/terminalModes.test.ts +22 -0
  967. package/agent/ui-tui/src/__tests__/text.test.ts +23 -0
  968. package/agent/ui-tui/src/__tests__/textInputFastEcho.test.ts +37 -0
  969. package/agent/ui-tui/src/__tests__/turnControllerNotice.test.ts +43 -0
  970. package/agent/ui-tui/src/__tests__/useInputHandlers.test.ts +38 -1
  971. package/agent/ui-tui/src/__tests__/virtualHeights.test.ts +8 -0
  972. package/agent/ui-tui/src/app/createGatewayEventHandler.ts +102 -7
  973. package/agent/ui-tui/src/app/interfaces.ts +64 -1
  974. package/agent/ui-tui/src/app/overlayStore.ts +18 -2
  975. package/agent/ui-tui/src/app/slash/commands/billing.ts +332 -0
  976. package/agent/ui-tui/src/app/slash/commands/core.ts +31 -2
  977. package/agent/ui-tui/src/app/slash/commands/credits.ts +57 -0
  978. package/agent/ui-tui/src/app/slash/commands/ops.ts +28 -0
  979. package/agent/ui-tui/src/app/slash/commands/session.ts +32 -4
  980. package/agent/ui-tui/src/app/slash/registry.ts +4 -0
  981. package/agent/ui-tui/src/app/turnController.ts +145 -2
  982. package/agent/ui-tui/src/app/uiStore.ts +2 -0
  983. package/agent/ui-tui/src/app/useInputHandlers.ts +42 -4
  984. package/agent/ui-tui/src/app/useMainApp.ts +54 -8
  985. package/agent/ui-tui/src/app/useSessionLifecycle.ts +40 -31
  986. package/agent/ui-tui/src/app/useSubmission.ts +23 -31
  987. package/agent/ui-tui/src/components/appChrome.tsx +112 -5
  988. package/agent/ui-tui/src/components/appLayout.tsx +9 -0
  989. package/agent/ui-tui/src/components/appOverlays.tsx +25 -1
  990. package/agent/ui-tui/src/components/billingOverlay.tsx +684 -0
  991. package/agent/ui-tui/src/components/branding.tsx +15 -3
  992. package/agent/ui-tui/src/components/messageLine.tsx +25 -3
  993. package/agent/ui-tui/src/components/pluginsHub.tsx +238 -0
  994. package/agent/ui-tui/src/components/prompts.tsx +31 -17
  995. package/agent/ui-tui/src/components/streamingAssistant.tsx +63 -55
  996. package/agent/ui-tui/src/components/textInput.tsx +16 -0
  997. package/agent/ui-tui/src/config/env.ts +12 -0
  998. package/agent/ui-tui/src/config/limits.ts +13 -0
  999. package/agent/ui-tui/src/domain/blockLayout.ts +146 -0
  1000. package/agent/ui-tui/src/domain/paths.ts +24 -0
  1001. package/agent/ui-tui/src/domain/slash.ts +40 -0
  1002. package/agent/ui-tui/src/entry.tsx +35 -4
  1003. package/agent/ui-tui/src/gatewayClient.ts +22 -10
  1004. package/agent/ui-tui/src/gatewayTypes.ts +130 -1
  1005. package/agent/ui-tui/src/lib/gracefulExit.ts +24 -4
  1006. package/agent/ui-tui/src/lib/memory.test.ts +162 -0
  1007. package/agent/ui-tui/src/lib/memory.ts +60 -1
  1008. package/agent/ui-tui/src/lib/memoryMonitor.ts +79 -4
  1009. package/agent/ui-tui/src/lib/osc52.ts +1 -1
  1010. package/agent/ui-tui/src/lib/text.test.ts +32 -1
  1011. package/agent/ui-tui/src/lib/text.ts +29 -2
  1012. package/agent/ui-tui/src/lib/virtualHeights.ts +13 -0
  1013. package/agent/ui-tui/src/types.ts +5 -0
  1014. package/agent/ui-tui/tsconfig.build.json +0 -1
  1015. package/agent/ui-tui/tsconfig.json +2 -1
  1016. package/agent/utils.py +66 -2
  1017. package/agent/uv.lock +300 -684
  1018. package/agent/web/index.html +2 -2
  1019. package/agent/web/package.json +11 -6
  1020. package/agent/web/public/claw-bg.webp +0 -0
  1021. package/agent/web/public/claw-logo.webp +0 -0
  1022. package/agent/web/src/App.tsx +138 -48
  1023. package/agent/web/src/components/AutomationBlueprints.tsx +225 -0
  1024. package/agent/web/src/components/Backdrop.tsx +15 -0
  1025. package/agent/web/src/components/ChatSessionList.tsx +260 -0
  1026. package/agent/web/src/components/ChatSidebar.tsx +262 -78
  1027. package/agent/web/src/components/ConfirmDialog.tsx +122 -0
  1028. package/agent/web/src/components/ModelPickerDialog.tsx +111 -16
  1029. package/agent/web/src/components/ModelReloadConfirm.tsx +40 -0
  1030. package/agent/web/src/components/ProfileScopeBanner.tsx +30 -0
  1031. package/agent/web/src/components/ProfileSwitcher.tsx +67 -0
  1032. package/agent/web/src/components/ReasoningPicker.tsx +167 -0
  1033. package/agent/web/src/components/SkillEditorDialog.tsx +215 -0
  1034. package/agent/web/src/components/ThemeSwitcher.tsx +119 -4
  1035. package/agent/web/src/components/ToolsetConfigDrawer.tsx +457 -0
  1036. package/agent/web/src/contexts/PageHeaderProvider.tsx +7 -4
  1037. package/agent/web/src/contexts/ProfileProvider.tsx +137 -0
  1038. package/agent/web/src/contexts/SystemActions.tsx +6 -8
  1039. package/agent/web/src/contexts/profile-context.ts +19 -0
  1040. package/agent/web/src/contexts/useProfileScope.ts +6 -0
  1041. package/agent/web/src/i18n/af.ts +5 -4
  1042. package/agent/web/src/i18n/de.ts +5 -4
  1043. package/agent/web/src/i18n/en.ts +58 -4
  1044. package/agent/web/src/i18n/es.ts +5 -3
  1045. package/agent/web/src/i18n/fr.ts +5 -3
  1046. package/agent/web/src/i18n/ga.ts +5 -4
  1047. package/agent/web/src/i18n/hu.ts +5 -4
  1048. package/agent/web/src/i18n/it.ts +5 -4
  1049. package/agent/web/src/i18n/ja.ts +5 -4
  1050. package/agent/web/src/i18n/ko.ts +5 -4
  1051. package/agent/web/src/i18n/pt.ts +5 -3
  1052. package/agent/web/src/i18n/ru.ts +5 -4
  1053. package/agent/web/src/i18n/tr.ts +5 -4
  1054. package/agent/web/src/i18n/types.ts +59 -1
  1055. package/agent/web/src/i18n/uk.ts +5 -3
  1056. package/agent/web/src/i18n/zh-hant.ts +5 -4
  1057. package/agent/web/src/i18n/zh.ts +5 -4
  1058. package/agent/web/src/index.css +2 -2
  1059. package/agent/web/src/lib/api.ts +819 -52
  1060. package/agent/web/src/lib/dashboard-flags.ts +16 -7
  1061. package/agent/web/src/lib/reasoning-effort.test.ts +48 -0
  1062. package/agent/web/src/lib/reasoning-effort.ts +36 -0
  1063. package/agent/web/src/lib/session-refresh.test.ts +21 -0
  1064. package/agent/web/src/lib/session-refresh.ts +26 -0
  1065. package/agent/web/src/pages/ChannelsPage.tsx +529 -68
  1066. package/agent/web/src/pages/ChatPage.tsx +249 -56
  1067. package/agent/web/src/pages/ConfigPage.tsx +11 -1
  1068. package/agent/web/src/pages/CronPage.tsx +219 -31
  1069. package/agent/web/src/pages/EnvPage.tsx +25 -6
  1070. package/agent/web/src/pages/FilesPage.tsx +525 -0
  1071. package/agent/web/src/pages/McpPage.tsx +80 -3
  1072. package/agent/web/src/pages/ModelsPage.tsx +97 -12
  1073. package/agent/web/src/pages/PluginsPage.tsx +1 -1
  1074. package/agent/web/src/pages/ProfileBuilderPage.tsx +611 -0
  1075. package/agent/web/src/pages/ProfilesPage.tsx +1038 -172
  1076. package/agent/web/src/pages/SessionsPage.tsx +144 -13
  1077. package/agent/web/src/pages/SkillsPage.tsx +851 -70
  1078. package/agent/web/src/pages/SystemPage.tsx +340 -4
  1079. package/agent/web/src/pages/WalletPage.tsx +401 -0
  1080. package/agent/web/src/pages/WebhooksPage.tsx +145 -15
  1081. package/agent/web/src/pages/X402Page.tsx +207 -0
  1082. package/agent/web/src/plugins/registry.ts +28 -11
  1083. package/agent/web/src/plugins/sdk.d.ts +160 -0
  1084. package/agent/web/src/themes/context.tsx +112 -5
  1085. package/agent/web/src/themes/fonts.ts +167 -0
  1086. package/agent/web/src/themes/index.ts +7 -0
  1087. package/agent/web/tsconfig.app.json +0 -1
  1088. package/agent/web/vite.config.ts +1 -8
  1089. package/agent/web/vitest.config.ts +16 -0
  1090. package/package.json +1 -1
  1091. package/agent/apps/desktop/package-lock.json +0 -18363
  1092. package/agent/apps/desktop/src/app/chat/composer/skin-slash-popover.tsx +0 -56
  1093. package/agent/apps/desktop/src/components/assistant-ui/thread-virtualizer.tsx +0 -382
  1094. package/agent/apps/desktop/src/components/assistant-ui/todo-tool.tsx +0 -109
  1095. package/agent/apps/desktop/src/components/chat/generated-image-context.tsx +0 -19
  1096. package/agent/optional-skills/productivity/shop-app/SKILL.md +0 -340
  1097. package/agent/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +0 -277
  1098. package/agent/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +0 -57
  1099. package/agent/skills/diagramming/DESCRIPTION.md +0 -3
  1100. package/agent/skills/domain/DESCRIPTION.md +0 -24
  1101. package/agent/skills/gifs/DESCRIPTION.md +0 -3
  1102. package/agent/skills/inference-sh/DESCRIPTION.md +0 -19
  1103. package/agent/skills/mcp/DESCRIPTION.md +0 -3
  1104. package/agent/skills/media/spotify/SKILL.md +0 -135
  1105. package/agent/skills/mlops/training/DESCRIPTION.md +0 -3
  1106. package/agent/skills/mlops/vector-databases/DESCRIPTION.md +0 -3
  1107. package/agent/skills/productivity/linear/SKILL.md +0 -380
  1108. package/agent/skills/productivity/linear/scripts/linear_api.py +0 -445
  1109. package/agent/skills/software-development/debugging-hermes-tui-commands/SKILL.md +0 -152
  1110. package/agent/skills/software-development/writing-plans/SKILL.md +0 -297
  1111. package/agent/ui-tui/package-lock.json +0 -7449
  1112. package/agent/ui-tui/packages/hermes-ink/package-lock.json +0 -1289
  1113. package/agent/web/package-lock.json +0 -8887
  1114. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/PORT_NOTES.md +0 -0
  1115. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/SKILL.md +0 -0
  1116. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/prompts/system.md +0 -0
  1117. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/macaron.md +0 -0
  1118. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/mono-ink.md +0 -0
  1119. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/neon.md +0 -0
  1120. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/warm.md +0 -0
  1121. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/prompt-construction.md +0 -0
  1122. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/style-presets.md +0 -0
  1123. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/blueprint.md +0 -0
  1124. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/chalkboard.md +0 -0
  1125. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/editorial.md +0 -0
  1126. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/elegant.md +0 -0
  1127. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/fantasy-animation.md +0 -0
  1128. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/flat-doodle.md +0 -0
  1129. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/flat.md +0 -0
  1130. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/ink-notes.md +0 -0
  1131. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/intuition-machine.md +0 -0
  1132. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/minimal.md +0 -0
  1133. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/nature.md +0 -0
  1134. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/notion.md +0 -0
  1135. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/pixel-art.md +0 -0
  1136. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/playful.md +0 -0
  1137. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/retro.md +0 -0
  1138. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/scientific.md +0 -0
  1139. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/screen-print.md +0 -0
  1140. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/sketch-notes.md +0 -0
  1141. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/sketch.md +0 -0
  1142. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/vector-illustration.md +0 -0
  1143. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/vintage.md +0 -0
  1144. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/warm.md +0 -0
  1145. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/watercolor.md +0 -0
  1146. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles.md +0 -0
  1147. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/usage.md +0 -0
  1148. /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/workflow.md +0 -0
  1149. /package/agent/{skills → optional-skills}/creative/baoyu-comic/PORT_NOTES.md +0 -0
  1150. /package/agent/{skills → optional-skills}/creative/baoyu-comic/SKILL.md +0 -0
  1151. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/analysis-framework.md +0 -0
  1152. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/chalk.md +0 -0
  1153. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/ink-brush.md +0 -0
  1154. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/ligne-claire.md +0 -0
  1155. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/manga.md +0 -0
  1156. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/minimalist.md +0 -0
  1157. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/realistic.md +0 -0
  1158. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/auto-selection.md +0 -0
  1159. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/base-prompt.md +0 -0
  1160. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/character-template.md +0 -0
  1161. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/cinematic.md +0 -0
  1162. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/dense.md +0 -0
  1163. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/four-panel.md +0 -0
  1164. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/mixed.md +0 -0
  1165. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/splash.md +0 -0
  1166. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/standard.md +0 -0
  1167. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/webtoon.md +0 -0
  1168. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/ohmsha-guide.md +0 -0
  1169. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/partial-workflows.md +0 -0
  1170. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/concept-story.md +0 -0
  1171. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/four-panel.md +0 -0
  1172. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/ohmsha.md +0 -0
  1173. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/shoujo.md +0 -0
  1174. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/wuxia.md +0 -0
  1175. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/storyboard-template.md +0 -0
  1176. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/action.md +0 -0
  1177. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/dramatic.md +0 -0
  1178. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/energetic.md +0 -0
  1179. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/neutral.md +0 -0
  1180. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/romantic.md +0 -0
  1181. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/vintage.md +0 -0
  1182. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/warm.md +0 -0
  1183. /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/workflow.md +0 -0
  1184. /package/agent/{skills → optional-skills}/creative/creative-ideation/SKILL.md +0 -0
  1185. /package/agent/{skills → optional-skills}/creative/creative-ideation/references/full-prompt-library.md +0 -0
  1186. /package/agent/{skills → optional-skills}/creative/pixel-art/ATTRIBUTION.md +0 -0
  1187. /package/agent/{skills → optional-skills}/creative/pixel-art/SKILL.md +0 -0
  1188. /package/agent/{skills → optional-skills}/creative/pixel-art/references/palettes.md +0 -0
  1189. /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/__init__.py +0 -0
  1190. /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/palettes.py +0 -0
  1191. /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/pixel_art.py +0 -0
  1192. /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/pixel_art_video.py +0 -0
  1193. /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/SKILL.md +0 -0
  1194. /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/references/analysis-modules.md +0 -0
  1195. /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/references/methods-guide.md +0 -0
  1196. /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/abliteration-config.yaml +0 -0
  1197. /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/analysis-study.yaml +0 -0
  1198. /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/batch-abliteration.yaml +0 -0
  1199. /package/agent/{skills → optional-skills}/mlops/research/DESCRIPTION.md +0 -0
  1200. /package/agent/{skills → optional-skills}/mlops/research/dspy/SKILL.md +0 -0
  1201. /package/agent/{skills → optional-skills}/mlops/research/dspy/references/examples.md +0 -0
  1202. /package/agent/{skills → optional-skills}/mlops/research/dspy/references/modules.md +0 -0
  1203. /package/agent/{skills → optional-skills}/mlops/research/dspy/references/optimizers.md +0 -0
  1204. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/references/jailbreak-templates.md +0 -0
  1205. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/references/refusal-detection.md +0 -0
  1206. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/godmode_race.py +0 -0
  1207. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/load_godmode.py +0 -0
  1208. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/parseltongue.py +0 -0
  1209. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/templates/prefill-subtle.json +0 -0
  1210. /package/agent/{skills/red-teaming → optional-skills/security}/godmode/templates/prefill.json +0 -0
  1211. /package/agent/{skills → optional-skills}/software-development/subagent-driven-development/references/context-budget-discipline.md +0 -0
  1212. /package/agent/{skills → optional-skills}/software-development/subagent-driven-development/references/gates-taxonomy.md +0 -0
@@ -1,6 +1,6 @@
1
1
  import { useStore } from '@nanostores/react'
2
2
  import { useQueryClient } from '@tanstack/react-query'
3
- import { lazy, Suspense, useCallback, useEffect, useRef } from 'react'
3
+ import { lazy, Suspense, useCallback, useEffect, useMemo, useRef } from 'react'
4
4
  import { Navigate, Route, Routes, useLocation, useNavigate, useParams } from 'react-router-dom'
5
5
 
6
6
  import { BootFailureOverlay } from '@/components/boot-failure-overlay'
@@ -8,12 +8,23 @@ import { DesktopInstallOverlay } from '@/components/desktop-install-overlay'
8
8
  import { DesktopOnboardingOverlay } from '@/components/desktop-onboarding-overlay'
9
9
  import { GatewayConnectingOverlay } from '@/components/gateway-connecting-overlay'
10
10
  import { Pane, PaneMain } from '@/components/pane-shell'
11
+ import { useMediaQuery } from '@/hooks/use-media-query'
11
12
  import { useSkinCommand } from '@/themes/use-skin-command'
12
13
 
13
14
  import { formatRefValue } from '../components/assistant-ui/directive-text'
14
- import { getSessionMessages, listSessions } from '../hermes'
15
- import { preserveLocalAssistantErrors, toChatMessages } from '../lib/chat-messages'
15
+ import { getCronJobs, getSessionMessages, listAllProfileSessions, type SessionInfo, triggerCronJob } from '../hermes'
16
+ import { type ChatMessage, chatMessageText, preserveLocalAssistantErrors, toChatMessages } from '../lib/chat-messages'
17
+ import { storedSessionIdForNotification } from '../lib/session-ids'
16
18
  import {
19
+ isMessagingSource,
20
+ LOCAL_SESSION_SOURCE_IDS,
21
+ MESSAGING_SESSION_SOURCE_IDS,
22
+ normalizeSessionSource
23
+ } from '../lib/session-source'
24
+ import { latestSessionTodos } from '../lib/todos'
25
+ import { setCronFocusJobId, setCronJobs } from '../store/cron'
26
+ import {
27
+ $panesFlipped,
17
28
  $pinnedSessionIds,
18
29
  $sessionsLimit,
19
30
  bumpSessionsLimit,
@@ -21,33 +32,62 @@ import {
21
32
  FILE_BROWSER_MAX_WIDTH,
22
33
  FILE_BROWSER_MIN_WIDTH,
23
34
  pinSession,
35
+ setSidebarOverlayMounted,
24
36
  SIDEBAR_DEFAULT_WIDTH,
25
37
  SIDEBAR_MAX_WIDTH,
38
+ SIDEBAR_SESSIONS_PAGE_SIZE,
26
39
  unpinSession
27
40
  } from '../store/layout'
41
+ import { respondToApprovalAction } from '../store/native-notifications'
28
42
  import { $filePreviewTarget, $previewTarget, closeActiveRightRailTab } from '../store/preview'
43
+ import {
44
+ $activeGatewayProfile,
45
+ $freshSessionRequest,
46
+ $profileScope,
47
+ ALL_PROFILES,
48
+ normalizeProfileKey,
49
+ refreshActiveProfile
50
+ } from '../store/profile'
29
51
  import {
30
52
  $activeSessionId,
31
53
  $currentCwd,
32
54
  $freshDraftReady,
33
55
  $gatewayState,
56
+ $messages,
57
+ $messagingSessions,
58
+ $resumeFailedSessionId,
59
+ $resumeExhaustedSessionId,
34
60
  $selectedStoredSessionId,
35
61
  $sessions,
62
+ $workingSessionIds,
63
+ CRON_SECTION_LIMIT,
64
+ getRecentlySettledSessionIds,
65
+ mergeSessionPage,
66
+ MESSAGING_SECTION_LIMIT,
36
67
  sessionPinId,
37
68
  setAwaitingResponse,
38
69
  setBusy,
70
+ setCronSessions,
39
71
  setCurrentBranch,
40
72
  setCurrentCwd,
41
73
  setCurrentModel,
42
74
  setCurrentProvider,
43
75
  setMessages,
76
+ setMessagingPlatformTotals,
77
+ setMessagingSessions,
78
+ setMessagingTruncated,
79
+ setSessionProfileTotals,
44
80
  setSessions,
45
81
  setSessionsLoading,
46
82
  setSessionsTotal
47
83
  } from '../store/session'
84
+ import { onSessionsChanged } from '../store/session-sync'
85
+ import { clearSessionTodos, setSessionTodos, todoListActive } from '../store/todos'
48
86
  import { openUpdatesWindow, startUpdatePoller, stopUpdatePoller } from '../store/updates'
87
+ import { isSecondaryWindow } from '../store/windows'
49
88
 
50
89
  import { ChatView } from './chat'
90
+ import { requestComposerFocus, requestComposerInsert } from './chat/composer/focus'
51
91
  import { useComposerActions } from './chat/hooks/use-composer-actions'
52
92
  import {
53
93
  ChatPreviewRail,
@@ -56,13 +96,19 @@ import {
56
96
  PREVIEW_RAIL_PANE_WIDTH
57
97
  } from './chat/right-rail'
58
98
  import { ChatSidebar } from './chat/sidebar'
99
+ import { CommandPalette } from './command-palette'
59
100
  import { useGatewayBoot } from './gateway/hooks/use-gateway-boot'
60
101
  import { useGatewayRequest } from './gateway/hooks/use-gateway-request'
102
+ import { useKeybinds } from './hooks/use-keybinds'
103
+ import { SIDEBAR_COLLAPSE_MEDIA_QUERY } from './layout-constants'
61
104
  import { ModelPickerOverlay } from './model-picker-overlay'
105
+ import { ModelVisibilityOverlay } from './model-visibility-overlay'
62
106
  import { RightSidebarPane } from './right-sidebar'
63
107
  import { $terminalTakeover } from './right-sidebar/store'
64
108
  import { PersistentTerminal, TerminalSlot } from './right-sidebar/terminal/persistent'
65
- import { NEW_CHAT_ROUTE, routeSessionId, sessionRoute } from './routes'
109
+ import { CRON_ROUTE, NEW_CHAT_ROUTE, routeSessionId, sessionRoute, SETTINGS_ROUTE } from './routes'
110
+ import { SessionPickerOverlay } from './session-picker-overlay'
111
+ import { SessionSwitcher } from './session-switcher'
66
112
  import { useContextSuggestions } from './session/hooks/use-context-suggestions'
67
113
  import { useCwdActions } from './session/hooks/use-cwd-actions'
68
114
  import { useHermesConfig } from './session/hooks/use-hermes-config'
@@ -77,6 +123,7 @@ import { AppShell } from './shell/app-shell'
77
123
  import { useOverlayRouting } from './shell/hooks/use-overlay-routing'
78
124
  import { useStatusSnapshot } from './shell/hooks/use-status-snapshot'
79
125
  import { useStatusbarItems } from './shell/hooks/use-statusbar-items'
126
+ import { ModelMenuPanel } from './shell/model-menu-panel'
80
127
  import type { StatusbarItem } from './shell/statusbar-controls'
81
128
  import type { TitlebarTool } from './shell/titlebar-controls'
82
129
  import { useGroupRegistry } from './shell/use-group-registry'
@@ -91,6 +138,58 @@ const ProfilesView = lazy(async () => ({ default: (await import('./profiles')).P
91
138
  const SettingsView = lazy(async () => ({ default: (await import('./settings')).SettingsView }))
92
139
  const SkillsView = lazy(async () => ({ default: (await import('./skills')).SkillsView }))
93
140
 
141
+ // Latest cron-job sessions surfaced in the collapsed "Cron jobs" section. The
142
+ // Cron sessions are written by a background scheduler tick (the desktop
143
+ // backend), so no user action signals the UI. Poll the bounded cron list on
144
+ // this cadence while the app is open + visible so new runs surface promptly
145
+ // instead of waiting for the next user-triggered refreshSessions().
146
+ const CRON_POLL_INTERVAL_MS = 30_000
147
+ // The recents list is local-only: cron rows have their own section, and each
148
+ // messaging platform (telegram, discord, …) is fetched separately into its own
149
+ // self-managed sidebar section (refreshMessagingSessions). Excluding both here
150
+ // keeps "Load more" paging through interactive local chats instead of
151
+ // interleaving gateway threads that bury them.
152
+ const SIDEBAR_EXCLUDED_SOURCES = ['cron', 'subagent', 'tool', ...MESSAGING_SESSION_SOURCE_IDS]
153
+ // The messaging slice is the inverse: drop cron + every local source so only
154
+ // external-platform conversations remain, then split per platform in the UI.
155
+ const MESSAGING_EXCLUDED_SOURCES = ['cron', ...LOCAL_SESSION_SOURCE_IDS]
156
+
157
+ // Cheap signature compare so the poll only swaps the atom (and re-renders the
158
+ // sidebar) when the visible cron rows actually changed.
159
+ function sameCronSignature(a: SessionInfo[], b: SessionInfo[]): boolean {
160
+ if (a.length !== b.length) {
161
+ return false
162
+ }
163
+
164
+ return a.every((session, i) => session.id === b[i]?.id && session.title === b[i]?.title)
165
+ }
166
+
167
+ // Rows a session refresh must preserve even if the aggregator omits them:
168
+ // in-flight first turns (message_count 0), pinned rows aged off the page, the
169
+ // actively-viewed chat (its "working" flag clears a beat before the aggregator
170
+ // sees the persisted row), and sessions whose turn just settled (same race, but
171
+ // for a chat the user has already navigated away from). Pass `scope` to only
172
+ // keep the active row when it belongs to the profile being paged.
173
+ function sessionsToKeep(scope?: string): Set<string> {
174
+ const keep = new Set<string>([
175
+ ...$workingSessionIds.get(),
176
+ ...$pinnedSessionIds.get(),
177
+ ...getRecentlySettledSessionIds()
178
+ ])
179
+
180
+ const active = $selectedStoredSessionId.get()
181
+
182
+ if (active) {
183
+ const session = scope ? $sessions.get().find(s => s.id === active) : null
184
+
185
+ if (!scope || !session || normalizeProfileKey(session.profile) === scope) {
186
+ keep.add(active)
187
+ }
188
+ }
189
+
190
+ return keep
191
+ }
192
+
94
193
  export function DesktopController() {
95
194
  const queryClient = useQueryClient()
96
195
  const location = useLocation()
@@ -104,10 +203,18 @@ export function DesktopController() {
104
203
  const activeSessionId = useStore($activeSessionId)
105
204
  const currentCwd = useStore($currentCwd)
106
205
  const freshDraftReady = useStore($freshDraftReady)
206
+ const resumeFailedSessionId = useStore($resumeFailedSessionId)
207
+ const resumeExhaustedSessionId = useStore($resumeExhaustedSessionId)
107
208
  const filePreviewTarget = useStore($filePreviewTarget)
108
209
  const previewTarget = useStore($previewTarget)
109
210
  const selectedStoredSessionId = useStore($selectedStoredSessionId)
110
211
  const terminalTakeover = useStore($terminalTakeover)
212
+ const panesFlipped = useStore($panesFlipped)
213
+ const profileScope = useStore($profileScope)
214
+ // Below SIDEBAR_COLLAPSE_BREAKPOINT_PX there's no room for a docked rail —
215
+ // collapse both sidebars (without touching their stored open state) so the
216
+ // hover-reveal overlay becomes the way in. Restores once it's wide again.
217
+ const narrowViewport = useMediaQuery(SIDEBAR_COLLAPSE_MEDIA_QUERY)
111
218
 
112
219
  const routedSessionId = routeSessionId(location.pathname)
113
220
  const routeToken = `${location.pathname}:${location.search}:${location.hash}`
@@ -121,14 +228,16 @@ export function DesktopController() {
121
228
  closeOverlayToPreviousRoute,
122
229
  commandCenterInitialSection,
123
230
  commandCenterOpen,
231
+ cronOpen,
124
232
  currentView,
125
233
  openAgents,
126
234
  openCommandCenterSection,
235
+ profilesOpen,
127
236
  settingsOpen,
128
237
  toggleCommandCenter
129
238
  } = useOverlayRouting()
130
239
 
131
- const terminalTakeoverActive = chatOpen && terminalTakeover
240
+ const terminalSidebarOpen = chatOpen && terminalTakeover
132
241
 
133
242
  const titlebarToolGroups = useGroupRegistry<TitlebarTool>()
134
243
  const statusbarItemGroups = useGroupRegistry<StatusbarItem>()
@@ -168,6 +277,60 @@ export function DesktopController() {
168
277
  }
169
278
  }, [])
170
279
 
280
+ // Notification click: the main process already focused the window; jump to its
281
+ // session. Notifications are tagged with the gateway *runtime* session id, but
282
+ // the chat route is keyed by the *stored* id — navigating with the runtime id
283
+ // resumes a non-existent stored session ("session not found") and strands the
284
+ // user. Translate runtime -> stored before navigating.
285
+ useEffect(() => {
286
+ const unsubscribe = window.hermesDesktop?.onFocusSession?.(sessionId => {
287
+ if (sessionId) {
288
+ navigate(sessionRoute(storedSessionIdForNotification(sessionId, runtimeIdByStoredSessionIdRef.current)))
289
+ }
290
+ })
291
+
292
+ return () => unsubscribe?.()
293
+ }, [navigate, runtimeIdByStoredSessionIdRef])
294
+
295
+ // Notification action button (Approve/Reject) — resolve in place, no navigation.
296
+ useEffect(() => {
297
+ const unsubscribe = window.hermesDesktop?.onNotificationAction?.(({ actionId, sessionId }) => {
298
+ void respondToApprovalAction(sessionId ?? null, actionId)
299
+ })
300
+
301
+ return () => unsubscribe?.()
302
+ }, [])
303
+
304
+ // hermes:// deep links (e.g. a docs "Send to App" button for an automation blueprint).
305
+ // Build the equivalent /blueprint slash command from the payload and drop
306
+ // it into the composer — the user reviews/edits, then sends; the agent (or
307
+ // the shared command handler) creates the job. Signal readiness so a link
308
+ // that arrived during boot is flushed exactly once.
309
+ useEffect(() => {
310
+ const unsubscribe = window.hermesDesktop?.onDeepLink?.(payload => {
311
+ if (!payload || payload.kind !== 'blueprint' || !payload.name) {
312
+ return
313
+ }
314
+
315
+ const slots = Object.entries(payload.params || {})
316
+ .map(([k, v]) => {
317
+ const sval = /\s/.test(v) ? `"${v.replace(/"/g, '\\"')}"` : v
318
+
319
+ return `${k}=${sval}`
320
+ })
321
+ .join(' ')
322
+
323
+ const command = `/blueprint ${payload.name}${slots ? ' ' + slots : ''}`
324
+ requestComposerInsert(command, { mode: 'block', target: 'main' })
325
+ requestComposerFocus('main')
326
+ })
327
+
328
+ // Tell the main process the renderer is ready to receive deep links.
329
+ void window.hermesDesktop?.signalDeepLinkReady?.()
330
+
331
+ return () => unsubscribe?.()
332
+ }, [])
333
+
171
334
  useEffect(() => {
172
335
  const onKeyDown = (event: KeyboardEvent) => {
173
336
  if (!$filePreviewTarget.get() && !$previewTarget.get()) {
@@ -191,6 +354,81 @@ export function DesktopController() {
191
354
  }
192
355
  }, [])
193
356
 
357
+ // Cron-job sessions as their own list (latest N). Independent of the recents
358
+ // page so the two never compete for slots. Cheap + bounded. Kept (even though
359
+ // the sidebar now lists cron *jobs*, not run sessions) so a pinned cron run
360
+ // still resolves into the Pinned section via sessionByAnyId.
361
+ const refreshCronSessions = useCallback(async () => {
362
+ try {
363
+ const { sessions } = await listAllProfileSessions(CRON_SECTION_LIMIT, 1, 'exclude', 'recent', 'all', {
364
+ source: 'cron'
365
+ })
366
+
367
+ setCronSessions(prev => (sameCronSignature(prev, sessions) ? prev : sessions))
368
+ } catch {
369
+ // Non-fatal: the cron section just stays empty/stale.
370
+ }
371
+ }, [])
372
+
373
+ // Messaging-platform sessions as their own slice, fetched separately from
374
+ // local recents so each platform renders a self-managed section and never
375
+ // competes with local chats for the recents page budget. One combined fetch
376
+ // seeds every platform; the sidebar splits the rows per source.
377
+ const refreshMessagingSessions = useCallback(async () => {
378
+ try {
379
+ const result = await listAllProfileSessions(MESSAGING_SECTION_LIMIT, 1, 'exclude', 'recent', 'all', {
380
+ excludeSources: MESSAGING_EXCLUDED_SOURCES
381
+ })
382
+
383
+ // Drop any non-messaging source the broad exclude didn't catch (custom
384
+ // sources) — those stay in local recents, not a platform section.
385
+ const rows = result.sessions.filter(s => isMessagingSource(s.source))
386
+
387
+ setMessagingSessions(prev => (sameCronSignature(prev, rows) ? prev : rows))
388
+ // Hit the cap → at least one platform may have more on disk than loaded,
389
+ // so platform sections offer their own per-platform "load more".
390
+ setMessagingTruncated(result.sessions.length >= MESSAGING_SECTION_LIMIT)
391
+ } catch {
392
+ // Non-fatal: the messaging sections just stay empty/stale.
393
+ }
394
+ }, [])
395
+
396
+ // Page a single platform's section independently (mirrors the per-profile
397
+ // pager): fetch that source's next window and merge it back in place, leaving
398
+ // every other platform's rows untouched. Resolves the platform's exact total.
399
+ const loadMoreMessagingForPlatform = useCallback(async (platform: string) => {
400
+ const inPlatform = (s: SessionInfo) => normalizeSessionSource(s.source) === platform
401
+ const loaded = $messagingSessions.get().filter(inPlatform).length
402
+
403
+ const result = await listAllProfileSessions(loaded + SIDEBAR_SESSIONS_PAGE_SIZE, 1, 'exclude', 'recent', 'all', {
404
+ source: platform
405
+ })
406
+
407
+ const incoming = result.sessions.filter(s => normalizeSessionSource(s.source) === platform)
408
+
409
+ setMessagingSessions(prev => [
410
+ ...prev.filter(s => !inPlatform(s)),
411
+ ...mergeSessionPage(prev.filter(inPlatform), incoming, sessionsToKeep())
412
+ ])
413
+
414
+ const total = result.total ?? incoming.length
415
+ setMessagingPlatformTotals(prev => ({ ...prev, [platform]: Math.max(total, incoming.length) }))
416
+ }, [])
417
+
418
+ // Cron *jobs* drive the sidebar "Cron jobs" section. Jobs are created
419
+ // synchronously (agent tool call or the cron UI), so refreshing here right
420
+ // after an agent turn surfaces a new job immediately; the interval poll keeps
421
+ // next-run/state fresh as the scheduler advances them.
422
+ const refreshCronJobs = useCallback(async () => {
423
+ try {
424
+ const jobs = await getCronJobs()
425
+
426
+ setCronJobs(jobs)
427
+ } catch {
428
+ // Non-fatal: the cron section just keeps its last-known jobs.
429
+ }
430
+ }, [])
431
+
194
432
  const refreshSessions = useCallback(async () => {
195
433
  const requestId = refreshSessionsRequestRef.current + 1
196
434
  refreshSessionsRequestRef.current = requestId
@@ -198,27 +436,78 @@ export function DesktopController() {
198
436
 
199
437
  try {
200
438
  const limit = $sessionsLimit.get()
439
+
201
440
  // Require at least one message so abandoned/empty "Untitled" drafts (one
202
441
  // was created per TUI/desktop launch before the lazy-create fix) don't
203
442
  // clutter the sidebar.
204
- const result = await listSessions(limit, 1)
443
+ // Unified cross-profile list (served read-only off each profile's
444
+ // state.db; no per-profile backend is spawned). Single-profile users get
445
+ // the same rows tagged profile="default". Cron sessions are excluded here
446
+ // and fetched separately (refreshCronSessions) so the scheduler's
447
+ // always-newest rows can't consume the recents page budget.
448
+ // Scope the fetch to the active profile (not always 'all') so a profile
449
+ // with few recent sessions isn't windowed out of the cross-profile
450
+ // recency page — the empty-history-on-profile-switch bug.
451
+ const sessionProfile = profileScope === ALL_PROFILES ? 'all' : profileScope
452
+
453
+ const result = await listAllProfileSessions(limit, 1, 'exclude', 'recent', sessionProfile, {
454
+ excludeSources: SIDEBAR_EXCLUDED_SOURCES
455
+ })
205
456
 
206
457
  if (refreshSessionsRequestRef.current === requestId) {
207
- setSessions(result.sessions)
458
+ setSessions(prev => mergeSessionPage(prev, result.sessions, sessionsToKeep()))
208
459
  setSessionsTotal(typeof result.total === 'number' ? result.total : result.sessions.length)
460
+ setSessionProfileTotals(result.profile_totals ?? {})
209
461
  }
210
462
  } finally {
211
463
  if (refreshSessionsRequestRef.current === requestId) {
212
464
  setSessionsLoading(false)
213
465
  }
214
466
  }
215
- }, [])
467
+
468
+ void refreshCronSessions()
469
+ void refreshCronJobs()
470
+ void refreshMessagingSessions()
471
+ }, [profileScope, refreshCronSessions, refreshCronJobs, refreshMessagingSessions])
216
472
 
217
473
  const loadMoreSessions = useCallback(() => {
218
474
  bumpSessionsLimit()
219
475
  void refreshSessions()
220
476
  }, [refreshSessions])
221
477
 
478
+ // Another window mutated the shared session list (e.g. a chat started in the
479
+ // pop-out). Re-pull so the sidebar reflects it. Pop-outs have no sidebar, so
480
+ // only real windows bother.
481
+ useEffect(() => {
482
+ if (isSecondaryWindow()) {
483
+ return
484
+ }
485
+
486
+ return onSessionsChanged(() => void refreshSessions().catch(() => undefined))
487
+ }, [refreshSessions])
488
+
489
+ // ALL-profiles view pages one profile at a time: fetch that profile's next
490
+ // page and merge it in place, leaving every other profile's rows untouched.
491
+ const loadMoreSessionsForProfile = useCallback(async (profile: string) => {
492
+ const key = normalizeProfileKey(profile)
493
+ const inKey = (s: SessionInfo) => normalizeProfileKey(s.profile) === key
494
+ const loaded = $sessions.get().filter(inKey).length
495
+
496
+ const result = await listAllProfileSessions(loaded + SIDEBAR_SESSIONS_PAGE_SIZE, 1, 'exclude', 'recent', key, {
497
+ excludeSources: SIDEBAR_EXCLUDED_SOURCES
498
+ })
499
+
500
+ const keep = sessionsToKeep(key)
501
+
502
+ setSessions(prev => [
503
+ ...prev.filter(s => !inKey(s)),
504
+ ...mergeSessionPage(prev.filter(inKey), result.sessions, keep)
505
+ ])
506
+
507
+ const total = result.profile_totals?.[key] ?? result.total ?? result.sessions.length
508
+ setSessionProfileTotals(prev => ({ ...prev, [key]: Math.max(total, result.sessions.length) }))
509
+ }, [])
510
+
222
511
  const toggleSelectedPin = useCallback(() => {
223
512
  const sessionId = $selectedStoredSessionId.get()
224
513
 
@@ -274,6 +563,22 @@ export function DesktopController() {
274
563
  requestGateway
275
564
  })
276
565
 
566
+ const openProviderSettings = useCallback(() => {
567
+ navigate(`${SETTINGS_ROUTE}?tab=providers`)
568
+ }, [navigate])
569
+
570
+ const modelMenuContent = useMemo(
571
+ () =>
572
+ gatewayState === 'open' ? (
573
+ <ModelMenuPanel
574
+ gateway={gatewayRef.current || undefined}
575
+ onSelectModel={selectModel}
576
+ requestGateway={requestGateway}
577
+ />
578
+ ) : null,
579
+ [gatewayRef, gatewayState, requestGateway, selectModel]
580
+ )
581
+
277
582
  useContextSuggestions({
278
583
  activeSessionId,
279
584
  activeSessionIdRef,
@@ -292,18 +597,34 @@ export function DesktopController() {
292
597
  return
293
598
  }
294
599
 
600
+ const storedProfile = $sessions
601
+ .get()
602
+ .find(session => session.id === storedSessionId || session._lineage_root_id === storedSessionId)?.profile
603
+
295
604
  for (let index = 0; index < Math.max(1, attempts); index += 1) {
296
605
  try {
297
- const latest = await getSessionMessages(storedSessionId)
606
+ const latest = await getSessionMessages(storedSessionId, storedProfile)
607
+ const messages = toChatMessages(latest.messages)
298
608
  updateSessionState(
299
609
  runtimeSessionId,
300
610
  state => ({
301
611
  ...state,
302
- messages: preserveLocalAssistantErrors(toChatMessages(latest.messages), state.messages)
612
+ messages: preserveLocalAssistantErrors(messages, state.messages)
303
613
  }),
304
614
  storedSessionId
305
615
  )
306
616
 
617
+ // Seed the status stack's todo group from history — but only while
618
+ // the plan is still in flight, so reopening an old chat doesn't pin
619
+ // its finished todo list above the composer forever.
620
+ const todos = latestSessionTodos(messages)
621
+
622
+ if (todos && todoListActive(todos)) {
623
+ setSessionTodos(runtimeSessionId, todos)
624
+ } else {
625
+ clearSessionTodos(runtimeSessionId)
626
+ }
627
+
307
628
  return
308
629
  } catch {
309
630
  // Best-effort fallback when live stream payloads are empty.
@@ -323,6 +644,7 @@ export function DesktopController() {
323
644
  queryClient,
324
645
  refreshHermesConfig,
325
646
  refreshSessions,
647
+ sessionStateByRuntimeIdRef,
326
648
  updateSessionState
327
649
  })
328
650
 
@@ -362,30 +684,48 @@ export function DesktopController() {
362
684
  updateSessionState
363
685
  })
364
686
 
687
+ // Single global listener for every rebindable hotkey (incl. profile switching)
688
+ // plus the on-screen keybind editor's capture mode.
689
+ useKeybinds({
690
+ startFreshSession: startFreshSessionDraft,
691
+ toggleCommandCenter,
692
+ toggleSelectedPin
693
+ })
694
+
695
+ // A profile switch/create drops to a fresh new-session draft so the previously
696
+ // open session doesn't bleed across contexts. Skip the initial value.
697
+ const freshSessionRequest = useStore($freshSessionRequest)
698
+ const lastFreshRef = useRef(freshSessionRequest)
699
+
365
700
  useEffect(() => {
366
- const onKeyDown = (event: KeyboardEvent) => {
367
- const target = event.target as HTMLElement | null
701
+ if (freshSessionRequest === lastFreshRef.current) {
702
+ return
703
+ }
368
704
 
369
- const editing =
370
- target?.isContentEditable ||
371
- target instanceof HTMLInputElement ||
372
- target instanceof HTMLTextAreaElement ||
373
- target instanceof HTMLSelectElement
705
+ lastFreshRef.current = freshSessionRequest
706
+ startFreshSessionDraft()
707
+ }, [freshSessionRequest, startFreshSessionDraft])
374
708
 
375
- if (editing || event.defaultPrevented || event.repeat || event.altKey || event.ctrlKey || event.metaKey) {
376
- return
377
- }
709
+ // Swapping the live gateway to another profile must re-pull that profile's
710
+ // global model + active-profile pill. Both are nanostores, so the blanket
711
+ // invalidateQueries() the profile store fires on swap doesn't touch them —
712
+ // without this the statusbar keeps showing the previous profile's model
713
+ // (the "forgets the LLM setting" report). gatewayState stays 'open' across a
714
+ // swap (background sockets persist), so the open→open effect won't re-run.
715
+ const activeGatewayProfile = useStore($activeGatewayProfile)
716
+ const lastGatewayProfileRef = useRef(activeGatewayProfile)
378
717
 
379
- if (event.shiftKey && event.code === 'KeyN') {
380
- event.preventDefault()
381
- startFreshSessionDraft()
382
- }
718
+ useEffect(() => {
719
+ if (activeGatewayProfile === lastGatewayProfileRef.current) {
720
+ return
383
721
  }
384
722
 
385
- window.addEventListener('keydown', onKeyDown)
386
-
387
- return () => window.removeEventListener('keydown', onKeyDown)
388
- }, [startFreshSessionDraft])
723
+ lastGatewayProfileRef.current = activeGatewayProfile
724
+ // Force: the new profile has its own default, so reseed even if the composer
725
+ // already shows the previous profile's model.
726
+ void refreshCurrentModel(true)
727
+ void refreshActiveProfile()
728
+ }, [activeGatewayProfile, refreshCurrentModel])
389
729
 
390
730
  const composer = useComposerActions({
391
731
  activeSessionId,
@@ -406,6 +746,49 @@ export function DesktopController() {
406
746
  [branchCurrentSession, refreshSessions]
407
747
  )
408
748
 
749
+ // Clear a failed turn's red error banner from the transcript. Errors are
750
+ // renderer-local state (never persisted), so dismissing is purely a view +
751
+ // session-cache edit. A message that errored before emitting any visible
752
+ // text is a bare error placeholder → drop it entirely; one that streamed
753
+ // partial output then failed keeps its content and just sheds the error.
754
+ // Both the per-runtime cache AND the live $messages view must be updated:
755
+ // `preserveLocalAssistantErrors` re-grafts any still-errored message it
756
+ // finds in the view onto the next session.info flush, so clearing only the
757
+ // cache would let the heartbeat resurrect the banner.
758
+ const dismissError = useCallback(
759
+ (messageId: string) => {
760
+ const runtimeSessionId = activeSessionIdRef.current
761
+
762
+ if (!runtimeSessionId) {
763
+ return
764
+ }
765
+
766
+ const clearErrorIn = (messages: ChatMessage[]): ChatMessage[] =>
767
+ messages.flatMap(message => {
768
+ if (message.id !== messageId || !message.error) {
769
+ return [message]
770
+ }
771
+
772
+ if (!chatMessageText(message).trim() && !message.parts.some(part => part.type !== 'text')) {
773
+ return []
774
+ }
775
+
776
+ return [{ ...message, error: undefined, pending: false }]
777
+ })
778
+
779
+ // View first: the flush below reads $messages as the "current" baseline
780
+ // for error preservation, so the banner must be gone from it before the
781
+ // cache update triggers a re-sync.
782
+ setMessages(clearErrorIn($messages.get()))
783
+
784
+ updateSessionState(runtimeSessionId, state => ({
785
+ ...state,
786
+ messages: clearErrorIn(state.messages)
787
+ }))
788
+ },
789
+ [activeSessionIdRef, updateSessionState]
790
+ )
791
+
409
792
  const startSessionInWorkspace = useCallback(
410
793
  (path: null | string) => {
411
794
  startFreshSessionDraft()
@@ -431,20 +814,30 @@ export function DesktopController() {
431
814
 
432
815
  const handleSkinCommand = useSkinCommand()
433
816
 
434
- const { cancelRun, editMessage, handleThreadMessagesChange, reloadFromMessage, submitText, transcribeVoiceAudio } =
435
- usePromptActions({
436
- activeSessionId,
437
- activeSessionIdRef,
438
- branchCurrentSession: branchInNewChat,
439
- busyRef,
440
- createBackendSessionForSend,
441
- handleSkinCommand,
442
- requestGateway,
443
- selectedStoredSessionIdRef,
444
- startFreshSessionDraft,
445
- sttEnabled,
446
- updateSessionState
447
- })
817
+ const {
818
+ cancelRun,
819
+ editMessage,
820
+ handleThreadMessagesChange,
821
+ reloadFromMessage,
822
+ restoreToMessage,
823
+ steerPrompt,
824
+ submitText,
825
+ transcribeVoiceAudio
826
+ } = usePromptActions({
827
+ activeSessionId,
828
+ activeSessionIdRef,
829
+ branchCurrentSession: branchInNewChat,
830
+ busyRef,
831
+ createBackendSessionForSend,
832
+ handleSkinCommand,
833
+ refreshSessions,
834
+ requestGateway,
835
+ resumeStoredSession: resumeSession,
836
+ selectedStoredSessionIdRef,
837
+ startFreshSessionDraft,
838
+ sttEnabled,
839
+ updateSessionState
840
+ })
448
841
 
449
842
  useGatewayBoot({
450
843
  handleGatewayEvent: handleDesktopGatewayEvent,
@@ -461,10 +854,41 @@ export function DesktopController() {
461
854
  useEffect(() => {
462
855
  if (gatewayState === 'open') {
463
856
  void refreshCurrentModel()
857
+ void refreshActiveProfile()
464
858
  void refreshSessions().catch(() => undefined)
465
859
  }
466
860
  }, [gatewayState, refreshCurrentModel, refreshSessions])
467
861
 
862
+ // Keep the cron jobs section live without a user action: the scheduler ticks
863
+ // in the background (advancing next-run/state and creating runs), so poll the
864
+ // job list on an interval (and on tab re-focus) while connected.
865
+ useEffect(() => {
866
+ if (gatewayState !== 'open') {
867
+ return
868
+ }
869
+
870
+ const tick = () => {
871
+ if (document.visibilityState === 'visible') {
872
+ void refreshCronJobs()
873
+ }
874
+ }
875
+
876
+ const intervalId = window.setInterval(tick, CRON_POLL_INTERVAL_MS)
877
+ document.addEventListener('visibilitychange', tick)
878
+
879
+ return () => {
880
+ window.clearInterval(intervalId)
881
+ document.removeEventListener('visibilitychange', tick)
882
+ }
883
+ }, [gatewayState, refreshCronJobs])
884
+
885
+ useEffect(() => {
886
+ if (gatewayState === 'open' && !activeSessionId && freshDraftReady) {
887
+ void refreshCurrentModel()
888
+ void refreshHermesConfig()
889
+ }
890
+ }, [activeSessionId, freshDraftReady, gatewayState, refreshCurrentModel, refreshHermesConfig])
891
+
468
892
  useRouteResume({
469
893
  activeSessionId,
470
894
  activeSessionIdRef,
@@ -474,6 +898,8 @@ export function DesktopController() {
474
898
  gatewayState,
475
899
  locationPathname: location.pathname,
476
900
  resumeSession,
901
+ resumeFailedSessionId,
902
+ resumeExhaustedSessionId,
477
903
  routedSessionId,
478
904
  runtimeIdByStoredSessionIdRef,
479
905
  selectedStoredSessionId,
@@ -483,6 +909,7 @@ export function DesktopController() {
483
909
 
484
910
  const { leftStatusbarItems, statusbarItems } = useStatusbarItems({
485
911
  agentsOpen,
912
+ chatOpen,
486
913
  commandCenterOpen,
487
914
  extraLeftItems: statusbarItemGroups.flat.left,
488
915
  extraRightItems: statusbarItemGroups.flat.right,
@@ -490,7 +917,9 @@ export function DesktopController() {
490
917
  gatewayState,
491
918
  inferenceStatus,
492
919
  openAgents,
920
+ freshDraftReady,
493
921
  openCommandCenterSection,
922
+ requestGateway,
494
923
  statusSnapshot,
495
924
  toggleCommandCenter
496
925
  })
@@ -500,32 +929,53 @@ export function DesktopController() {
500
929
  currentView={currentView}
501
930
  onArchiveSession={sessionId => void archiveSession(sessionId)}
502
931
  onDeleteSession={sessionId => void removeSession(sessionId)}
932
+ onLoadMoreMessaging={loadMoreMessagingForPlatform}
933
+ onLoadMoreProfileSessions={loadMoreSessionsForProfile}
503
934
  onLoadMoreSessions={loadMoreSessions}
935
+ onManageCronJob={jobId => {
936
+ setCronFocusJobId(jobId)
937
+ navigate(CRON_ROUTE)
938
+ }}
504
939
  onNavigate={selectSidebarItem}
505
940
  onNewSessionInWorkspace={startSessionInWorkspace}
506
941
  onResumeSession={sessionId => navigate(sessionRoute(sessionId))}
942
+ onTriggerCronJob={jobId => {
943
+ void triggerCronJob(jobId)
944
+ .then(() => refreshCronJobs())
945
+ .catch(() => undefined)
946
+ }}
507
947
  />
508
948
  )
509
949
 
950
+ // One PTY-backed terminal mounted forever; <TerminalSlot /> placeholders decide
951
+ // where it shows. Lives in main's stacking context (not the root overlay layer)
952
+ // so pane resize handles still paint above it. Toggling never rebuilds the shell.
953
+ const mainOverlays = (
954
+ <PersistentTerminal cwd={currentCwd} onAddSelectionToChat={composer.addTerminalSelectionAttachment} />
955
+ )
956
+
510
957
  const overlays = (
511
958
  <>
512
- <DesktopInstallOverlay />
513
- {/* One PTY-backed terminal mounted forever; <TerminalSlot /> placeholders
514
- decide where it shows. Toggling fullscreen never rebuilds the shell. */}
515
- <PersistentTerminal cwd={currentCwd} onAddSelectionToChat={composer.addTerminalSelectionAttachment} />
516
- <DesktopOnboardingOverlay
517
- enabled={gatewayState === 'open'}
518
- onCompleted={() => {
519
- void refreshHermesConfig()
520
- void refreshCurrentModel()
521
- void queryClient.invalidateQueries({ queryKey: ['model-options'] })
522
- }}
523
- requestGateway={requestGateway}
524
- />
959
+ {!isSecondaryWindow() && <DesktopInstallOverlay />}
960
+ {!isSecondaryWindow() && (
961
+ <DesktopOnboardingOverlay
962
+ enabled={gatewayState === 'open'}
963
+ onCompleted={() => {
964
+ void refreshHermesConfig()
965
+ void refreshCurrentModel()
966
+ void queryClient.invalidateQueries({ queryKey: ['model-options'] })
967
+ }}
968
+ requestGateway={requestGateway}
969
+ />
970
+ )}
525
971
  <ModelPickerOverlay gateway={gatewayRef.current || undefined} onSelect={selectModel} />
972
+ <SessionPickerOverlay onResume={resumeSession} />
973
+ <ModelVisibilityOverlay gateway={gatewayRef.current || undefined} onOpenProviders={openProviderSettings} />
526
974
  <UpdatesOverlay />
527
975
  <GatewayConnectingOverlay />
528
976
  <BootFailureOverlay />
977
+ <CommandPalette />
978
+ <SessionSwitcher />
529
979
 
530
980
  {settingsOpen && (
531
981
  <Suspense fallback={null}>
@@ -565,6 +1015,21 @@ export function DesktopController() {
565
1015
  <AgentsView onClose={closeOverlayToPreviousRoute} />
566
1016
  </Suspense>
567
1017
  )}
1018
+
1019
+ {cronOpen && (
1020
+ <Suspense fallback={null}>
1021
+ <CronView
1022
+ onClose={closeOverlayToPreviousRoute}
1023
+ onOpenSession={sessionId => navigate(sessionRoute(sessionId))}
1024
+ />
1025
+ </Suspense>
1026
+ )}
1027
+
1028
+ {profilesOpen && (
1029
+ <Suspense fallback={null}>
1030
+ <ProfilesView onClose={closeOverlayToPreviousRoute} />
1031
+ </Suspense>
1032
+ )}
568
1033
  </>
569
1034
  )
570
1035
 
@@ -572,17 +1037,19 @@ export function DesktopController() {
572
1037
  <ChatView
573
1038
  gateway={gatewayRef.current}
574
1039
  maxVoiceRecordingSeconds={voiceMaxRecordingSeconds}
1040
+ modelMenuContent={modelMenuContent}
575
1041
  onAddContextRef={composer.addContextRefAttachment}
576
1042
  onAddUrl={url => composer.addContextRefAttachment(`@url:${formatRefValue(url)}`, url)}
577
1043
  onAttachDroppedItems={composer.attachDroppedItems}
578
1044
  onAttachImageBlob={composer.attachImageBlob}
579
- onBranchInNewChat={messageId => void branchInNewChat(messageId)}
1045
+ onBranchInNewChat={branchInNewChat}
580
1046
  onCancel={cancelRun}
581
1047
  onDeleteSelectedSession={() => {
582
1048
  if (selectedStoredSessionId) {
583
1049
  void removeSession(selectedStoredSessionId)
584
1050
  }
585
1051
  }}
1052
+ onDismissError={dismissError}
586
1053
  onEdit={editMessage}
587
1054
  onPasteClipboardImage={() => void composer.pasteClipboardImage()}
588
1055
  onPickFiles={() => void composer.pickContextPaths('file')}
@@ -590,6 +1057,9 @@ export function DesktopController() {
590
1057
  onPickImages={() => void composer.pickImages()}
591
1058
  onReload={reloadFromMessage}
592
1059
  onRemoveAttachment={id => void composer.removeAttachment(id)}
1060
+ onRestoreToMessage={restoreToMessage}
1061
+ onRetryResume={sessionId => void resumeSession(sessionId, true)}
1062
+ onSteer={steerPrompt}
593
1063
  onSubmit={submitText}
594
1064
  onThreadMessagesChange={handleThreadMessagesChange}
595
1065
  onToggleSelectedPin={toggleSelectedPin}
@@ -597,38 +1067,100 @@ export function DesktopController() {
597
1067
  />
598
1068
  )
599
1069
 
600
- const takeoverTerminalView = (
601
- <div className="relative flex h-full min-h-0 min-w-0 flex-col overflow-hidden bg-(--ui-chat-surface-background) pt-(--titlebar-height)">
602
- <TerminalSlot />
603
- </div>
1070
+ // Flipped layout mirrors the default: sessions sidebar → right, file
1071
+ // browser + preview rail left. Same panes, swapped sides.
1072
+ const sidebarSide = panesFlipped ? 'right' : 'left'
1073
+ const railSide = panesFlipped ? 'left' : 'right'
1074
+
1075
+ const previewPane = (
1076
+ <Pane
1077
+ disabled={!chatOpen || (!previewTarget && !filePreviewTarget)}
1078
+ id="preview"
1079
+ key="preview"
1080
+ maxWidth={PREVIEW_RAIL_MAX_WIDTH}
1081
+ minWidth={PREVIEW_RAIL_MIN_WIDTH}
1082
+ resizable
1083
+ side={railSide}
1084
+ width={PREVIEW_RAIL_PANE_WIDTH}
1085
+ >
1086
+ {chatOpen ? (
1087
+ <ChatPreviewRail onRestartServer={restartPreviewServer} setTitlebarToolGroup={setTitlebarToolGroup} />
1088
+ ) : null}
1089
+ </Pane>
1090
+ )
1091
+
1092
+ const fileBrowserPane = (
1093
+ <Pane
1094
+ defaultOpen={false}
1095
+ disabled={!chatOpen}
1096
+ forceCollapsed={narrowViewport}
1097
+ hoverReveal
1098
+ id="file-browser"
1099
+ key="file-browser"
1100
+ maxWidth={FILE_BROWSER_MAX_WIDTH}
1101
+ minWidth={FILE_BROWSER_MIN_WIDTH}
1102
+ resizable
1103
+ side={railSide}
1104
+ width={FILE_BROWSER_DEFAULT_WIDTH}
1105
+ >
1106
+ <RightSidebarPane
1107
+ onActivateFile={path => composer.insertContextPathInlineRef(path)}
1108
+ onActivateFolder={path => composer.insertContextPathInlineRef(path, true)}
1109
+ onChangeCwd={changeSessionCwd}
1110
+ />
1111
+ </Pane>
1112
+ )
1113
+
1114
+ const terminalPane = (
1115
+ <Pane
1116
+ defaultOpen
1117
+ disabled={!terminalSidebarOpen}
1118
+ divider
1119
+ id="terminal-sidebar"
1120
+ key="terminal-sidebar"
1121
+ maxWidth="80vw"
1122
+ minWidth="22vw"
1123
+ resizable
1124
+ side={railSide}
1125
+ width="42vw"
1126
+ >
1127
+ <div className="relative flex h-full min-h-0 min-w-0 flex-col overflow-hidden bg-(--ui-editor-surface-background) pt-(--titlebar-height)">
1128
+ <TerminalSlot />
1129
+ </div>
1130
+ </Pane>
604
1131
  )
605
1132
 
606
1133
  return (
607
1134
  <AppShell
608
- commandCenterOpen={commandCenterOpen}
609
1135
  leftStatusbarItems={leftStatusbarItems}
610
1136
  leftTitlebarTools={titlebarToolGroups.flat.left}
611
- onOpenSearch={() => openCommandCenterSection('sessions')}
1137
+ mainOverlays={mainOverlays}
612
1138
  onOpenSettings={openSettings}
613
1139
  overlays={overlays}
1140
+ previewPaneOpen={chatOpen && Boolean(previewTarget || filePreviewTarget)}
614
1141
  statusbarItems={statusbarItems}
1142
+ terminalPaneOpen={terminalSidebarOpen}
615
1143
  titlebarTools={titlebarToolGroups.flat.right}
616
1144
  >
617
- <Pane
618
- disabled={terminalTakeoverActive}
619
- id="chat-sidebar"
620
- maxWidth={SIDEBAR_MAX_WIDTH}
621
- minWidth={SIDEBAR_DEFAULT_WIDTH}
622
- resizable
623
- side="left"
624
- width={`${SIDEBAR_DEFAULT_WIDTH}px`}
625
- >
626
- {sidebar}
627
- </Pane>
1145
+ {!isSecondaryWindow() && (
1146
+ <Pane
1147
+ forceCollapsed={narrowViewport}
1148
+ hoverReveal
1149
+ id="chat-sidebar"
1150
+ maxWidth={SIDEBAR_MAX_WIDTH}
1151
+ minWidth={SIDEBAR_DEFAULT_WIDTH}
1152
+ onOverlayActiveChange={setSidebarOverlayMounted}
1153
+ resizable
1154
+ side={sidebarSide}
1155
+ width={`${SIDEBAR_DEFAULT_WIDTH}px`}
1156
+ >
1157
+ {sidebar}
1158
+ </Pane>
1159
+ )}
628
1160
  <PaneMain>
629
1161
  <Routes>
630
- <Route element={terminalTakeoverActive ? takeoverTerminalView : chatView} index />
631
- <Route element={terminalTakeoverActive ? takeoverTerminalView : chatView} path=":sessionId" />
1162
+ <Route element={chatView} index />
1163
+ <Route element={chatView} path=":sessionId" />
632
1164
  <Route
633
1165
  element={
634
1166
  <Suspense fallback={null}>
@@ -653,25 +1185,8 @@ export function DesktopController() {
653
1185
  }
654
1186
  path="artifacts"
655
1187
  />
656
- <Route
657
- element={
658
- <Suspense fallback={null}>
659
- <CronView setStatusbarItemGroup={setStatusbarItemGroup} />
660
- </Suspense>
661
- }
662
- path="cron"
663
- />
664
- <Route
665
- element={
666
- <Suspense fallback={null}>
667
- <ProfilesView
668
- setStatusbarItemGroup={setStatusbarItemGroup}
669
- setTitlebarToolGroup={setTitlebarToolGroup}
670
- />
671
- </Suspense>
672
- }
673
- path="profiles"
674
- />
1188
+ <Route element={null} path="cron" />
1189
+ <Route element={null} path="profiles" />
675
1190
  <Route element={null} path="settings" />
676
1191
  <Route element={null} path="command-center" />
677
1192
  <Route element={null} path="agents" />
@@ -680,35 +1195,15 @@ export function DesktopController() {
680
1195
  <Route element={<Navigate replace to={NEW_CHAT_ROUTE} />} path="*" />
681
1196
  </Routes>
682
1197
  </PaneMain>
683
- <Pane
684
- disabled={!chatOpen || (!previewTarget && !filePreviewTarget)}
685
- id="preview"
686
- maxWidth={PREVIEW_RAIL_MAX_WIDTH}
687
- minWidth={PREVIEW_RAIL_MIN_WIDTH}
688
- resizable
689
- side="right"
690
- width={PREVIEW_RAIL_PANE_WIDTH}
691
- >
692
- {chatOpen ? (
693
- <ChatPreviewRail onRestartServer={restartPreviewServer} setTitlebarToolGroup={setTitlebarToolGroup} />
694
- ) : null}
695
- </Pane>
696
- <Pane
697
- defaultOpen={false}
698
- disabled={!chatOpen}
699
- id="file-browser"
700
- maxWidth={FILE_BROWSER_MAX_WIDTH}
701
- minWidth={FILE_BROWSER_MIN_WIDTH}
702
- resizable
703
- side="right"
704
- width={FILE_BROWSER_DEFAULT_WIDTH}
705
- >
706
- <RightSidebarPane
707
- onActivateFile={composer.attachContextFilePath}
708
- onActivateFolder={composer.attachContextFolderPath}
709
- onChangeCwd={changeSessionCwd}
710
- />
711
- </Pane>
1198
+ {/*
1199
+ Order within a side maps to column order. Default (rail on the right):
1200
+ main | terminal | preview | file-browser. Flipped (rail on the left):
1201
+ mirror to file-browser | preview | terminal | main so terminal stays
1202
+ adjacent to the chat.
1203
+ */}
1204
+ {panesFlipped ? fileBrowserPane : terminalPane}
1205
+ {previewPane}
1206
+ {panesFlipped ? terminalPane : fileBrowserPane}
712
1207
  </AppShell>
713
1208
  )
714
1209
  }