@clawpump/claw-agent 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +6190 -973
  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 +4 -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
@@ -185,6 +185,47 @@ function Write-Err {
185
185
  Write-Host "[X] $Message" -ForegroundColor Red
186
186
  }
187
187
 
188
+ function Invoke-NativeWithRelaxedErrorAction {
189
+ param([scriptblock]$Script)
190
+
191
+ $prevEAP = $ErrorActionPreference
192
+ $ErrorActionPreference = "Continue"
193
+ try {
194
+ & $Script
195
+ } finally {
196
+ $ErrorActionPreference = $prevEAP
197
+ }
198
+ }
199
+
200
+ # Inspect npm output for a TLS-trust failure and, if found, print actionable
201
+ # remediation. npm/Node surface corporate MITM proxies and missing root CAs as
202
+ # "unable to get local issuer certificate" / "self-signed certificate in
203
+ # certificate chain" / UNABLE_TO_GET_ISSUER_CERT_LOCALLY -- most commonly while
204
+ # Electron's install.js postinstall downloads the Electron binary. The reporter
205
+ # usually misreads this as an admin-rights or generic install failure (see
206
+ # issue #38016), so detect it once here and route every npm stage through this
207
+ # hint. Returns $true when a cert error was detected (caller may adjust its own
208
+ # messaging), $false otherwise.
209
+ function Show-NpmCertHint {
210
+ param([string]$NpmOutput)
211
+ if (-not $NpmOutput) { return $false }
212
+ $isCertError = $NpmOutput -match "unable to get local issuer certificate" `
213
+ -or $NpmOutput -match "self.signed certificate" `
214
+ -or $NpmOutput -match "UNABLE_TO_GET_ISSUER_CERT_LOCALLY" `
215
+ -or $NpmOutput -match "SELF_SIGNED_CERT_IN_CHAIN" `
216
+ -or $NpmOutput -match "CERT_HAS_EXPIRED"
217
+ if (-not $isCertError) { return $false }
218
+ Write-Warn "This looks like a TLS certificate-trust failure, not a permissions problem."
219
+ Write-Info " A corporate proxy or antivirus is likely intercepting HTTPS and presenting a"
220
+ Write-Info " certificate Node.js doesn't trust. To fix, point Node at your org's root CA:"
221
+ Write-Info " 1. Get the corporate root CA as a .pem/.crt from your IT team."
222
+ Write-Info " 2. setx NODE_EXTRA_CA_CERTS `"C:\path\to\corp-ca.pem`""
223
+ Write-Info " 3. Open a NEW terminal (so the env var takes effect) and re-run the installer."
224
+ Write-Info " Quick (less secure) alternative -- disable TLS verification just for the install:"
225
+ Write-Info " npm config set strict-ssl false (re-enable afterwards: npm config set strict-ssl true)"
226
+ return $true
227
+ }
228
+
188
229
  # --- Ensure-mode helpers ---
189
230
 
190
231
  function Resolve-NpmCmd {
@@ -252,6 +293,7 @@ function Install-AgentBrowser {
252
293
  $npmDetail = Get-Content $npmLog -Raw -ErrorAction SilentlyContinue
253
294
  Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
254
295
  Write-Err "npm install -g failed (exit $npmExit): $npmDetail"
296
+ Show-NpmCertHint $npmDetail | Out-Null
255
297
  throw "npm install failed"
256
298
  }
257
299
  Remove-Item $npmLog -Force -ErrorAction SilentlyContinue
@@ -288,79 +330,77 @@ function Install-AgentBrowser {
288
330
  # Dependency checks
289
331
  # ============================================================================
290
332
 
333
+ # Resolve the PowerShell host executable used to spawn child PowerShell
334
+ # processes (the astral uv installer below). We must NOT hardcode the bare
335
+ # name `powershell`: it names *Windows PowerShell* and only resolves when its
336
+ # System32 directory is on PATH. When install.ps1 is run under PowerShell 7+
337
+ # (`pwsh`) -- or any session where `powershell` isn't on PATH -- a bare
338
+ # `powershell` spawn dies with "The term 'powershell' is not recognized",
339
+ # aborting uv installation (field report: Windows install stuck, uv install
340
+ # failed with exactly that message). Prefer the absolute path of the host we
341
+ # are already running in (PATH-independent), then fall back to whichever of
342
+ # powershell/pwsh is resolvable, and only then to the bare name.
343
+ function Get-PowerShellHostExe {
344
+ try {
345
+ $hostExe = (Get-Process -Id $PID).Path
346
+ if ($hostExe -and (Test-Path $hostExe)) {
347
+ $leaf = Split-Path $hostExe -Leaf
348
+ # Only trust the current host when it is a real PowerShell CLI
349
+ # (not e.g. powershell_ise.exe or an embedded host that can't take
350
+ # `-ExecutionPolicy`/`-Command`).
351
+ if ($leaf -match '^(?i:powershell|pwsh)\.exe$') { return $hostExe }
352
+ }
353
+ } catch { }
354
+ foreach ($candidate in @("powershell", "pwsh")) {
355
+ $cmd = Get-Command $candidate -CommandType Application -ErrorAction SilentlyContinue |
356
+ Select-Object -First 1
357
+ if ($cmd -and $cmd.Source) { return $cmd.Source }
358
+ }
359
+ # Last-ditch: hand back the bare name so the spawn surfaces its own error.
360
+ return "powershell"
361
+ }
362
+
291
363
  function Install-Uv {
292
- Write-Info "Checking for uv package manager..."
293
-
294
- # Check if uv is already available
295
- if (Get-Command uv -ErrorAction SilentlyContinue) {
296
- $version = uv --version
297
- $script:UvCmd = "uv"
298
- Write-Success "uv found ($version)"
364
+ # Hermes owns its own uv at $HermesHome\bin\uv.exe. Always install there —
365
+ # no PATH probing, no conda guards, no multi-location resolution chains.
366
+ # The runtime update path (hermes_cli/managed_uv.py) looks in the same
367
+ # place, so install.ps1 and `hermes update` stay in sync.
368
+ $managedUv = Join-Path $HermesHome "bin\uv.exe"
369
+
370
+ if (Test-Path $managedUv) {
371
+ $script:UvCmd = $managedUv
372
+ $version = & $managedUv --version
373
+ Write-Success "Managed uv found ($version)"
299
374
  return $true
300
375
  }
301
-
302
- # Check common install locations
303
- $uvPaths = @(
304
- "$env:USERPROFILE\.local\bin\uv.exe",
305
- "$env:USERPROFILE\.cargo\bin\uv.exe"
306
- )
307
- foreach ($uvPath in $uvPaths) {
308
- if (Test-Path $uvPath) {
309
- $script:UvCmd = $uvPath
310
- $version = & $uvPath --version
311
- Write-Success "uv found at $uvPath ($version)"
312
- return $true
313
- }
314
- }
315
-
316
- # Install uv
317
- Write-Info "Installing uv (fast Python package manager)..."
318
- # Capture EAP outside the try block so the catch's restore call always
319
- # has a meaningful value -- if the assignment lived inside try and the
320
- # try body threw before reaching it, the catch would see $prevEAP
321
- # unset and leave EAP at whatever the previous protected call set.
376
+
377
+ Write-Info "Installing managed uv into $HermesHome\bin ..."
378
+ New-Item -ItemType Directory -Path (Join-Path $HermesHome "bin") -Force | Out-Null
379
+
380
+ # UV_INSTALL_DIR tells the astral installer to place the binary
381
+ # directly into $HermesHome\bin instead of ~/.local/bin.
322
382
  $prevEAP = $ErrorActionPreference
323
383
  try {
324
- # Relax ErrorActionPreference around the nested astral installer.
325
- # The astral installer (a separate `powershell -c "irm ... | iex"`)
326
- # writes download progress to stderr. With $ErrorActionPreference
327
- # = "Stop" set at the top of this script, PowerShell wraps stderr
328
- # lines from native commands (which `powershell -c` is, from our
329
- # perspective) as ErrorRecord objects when captured via 2>&1, then
330
- # throws a terminating exception on the first one -- even though
331
- # uv installs successfully and the child exits 0. Same fix
332
- # pattern Test-Python uses for `uv python install`; verify success
333
- # via Test-Path on the expected binary afterwards, which is more
334
- # reliable than exit-code/stderr signal anyway.
335
384
  $ErrorActionPreference = "Continue"
336
- powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" 2>&1 | Out-Null
385
+ $env:UV_INSTALL_DIR = Join-Path $HermesHome "bin"
386
+ # Spawn via the resolved host exe (see Get-PowerShellHostExe) rather
387
+ # than a bare `powershell`, which isn't guaranteed to be on PATH under
388
+ # PowerShell 7 / pwsh-only setups.
389
+ $psHostExe = Get-PowerShellHostExe
390
+ & $psHostExe -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" 2>&1 | Out-Null
337
391
  $ErrorActionPreference = $prevEAP
338
392
 
339
- # Find the installed binary
340
- $uvExe = "$env:USERPROFILE\.local\bin\uv.exe"
341
- if (-not (Test-Path $uvExe)) {
342
- $uvExe = "$env:USERPROFILE\.cargo\bin\uv.exe"
343
- }
344
- if (-not (Test-Path $uvExe)) {
345
- # Refresh PATH and try again
346
- $env:Path = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
347
- if (Get-Command uv -ErrorAction SilentlyContinue) {
348
- $uvExe = (Get-Command uv).Source
349
- }
350
- }
351
-
352
- if (Test-Path $uvExe) {
353
- $script:UvCmd = $uvExe
354
- $version = & $uvExe --version
355
- Write-Success "uv installed ($version)"
393
+ if (Test-Path $managedUv) {
394
+ $script:UvCmd = $managedUv
395
+ $version = & $managedUv --version
396
+ Write-Success "Managed uv installed ($version)"
356
397
  return $true
357
398
  }
358
-
359
- Write-Err "uv installed but not found on PATH"
360
- Write-Info "Try restarting your terminal and re-running"
399
+
400
+ Write-Err "uv installed but not found at $managedUv"
401
+ Write-Info "Install manually: https://docs.astral.sh/uv/getting-started/installation/"
361
402
  return $false
362
403
  } catch {
363
- # Restore EAP in case the try block threw before the assignment
364
404
  if ($prevEAP) { $ErrorActionPreference = $prevEAP }
365
405
  Write-Err "Failed to install uv: $_"
366
406
  Write-Info "Install manually: https://docs.astral.sh/uv/getting-started/installation/"
@@ -385,11 +425,9 @@ function Sync-EnvPath {
385
425
  # in a fresh powershell process, so $script:UvCmd set by Install-Uv in a
386
426
  # prior process is not visible here. Later stages (Test-Python,
387
427
  # Install-Venv, Install-Dependencies, Install-PlatformSdks) call this
388
- # at the top to populate $script:UvCmd from PATH or known install paths.
389
- # Throws if uv is not findable -- the caller's stage then surfaces a
390
- # clean error via the stage-driver's try/catch. Fast path is a single
391
- # Get-Command call when uv is on PATH (the common case after Stage-Uv
392
- # ran path-modifying installs in a sibling process).
428
+ # at the top to populate $script:UvCmd from the managed location.
429
+ # Throws if uv is not findable the caller's stage then surfaces a
430
+ # clean error via the stage-driver's try/catch.
393
431
  function Resolve-UvCmd {
394
432
  # Already resolved (default invocation path: Install-Uv ran earlier
395
433
  # in the same process and set $script:UvCmd).
@@ -404,9 +442,15 @@ function Resolve-UvCmd {
404
442
  # Stale; fall through to re-discover.
405
443
  }
406
444
 
407
- # Try PATH first (covers `winget install astral.uv`, manual installs,
408
- # and the post-Install-Uv state where uv.exe lives in
409
- # %USERPROFILE%\.local\bin which the installer added to PATH).
445
+ # Check the managed location first this is where Install-Uv puts it.
446
+ $managedUv = Join-Path $HermesHome "bin\uv.exe"
447
+ if (Test-Path $managedUv) {
448
+ $script:UvCmd = $managedUv
449
+ return
450
+ }
451
+
452
+ # Fall back to PATH (covers edge cases where the installer ran in a
453
+ # sibling process and HERMES_HOME wasn't propagated).
410
454
  if (Get-Command uv -ErrorAction SilentlyContinue) {
411
455
  $script:UvCmd = "uv"
412
456
  return
@@ -420,16 +464,7 @@ function Resolve-UvCmd {
420
464
  return
421
465
  }
422
466
 
423
- # Check the well-known install locations the astral.sh installer drops
424
- # uv into. Mirrors the probe order Install-Uv uses.
425
- foreach ($uvPath in @("$env:USERPROFILE\.local\bin\uv.exe", "$env:USERPROFILE\.cargo\bin\uv.exe")) {
426
- if (Test-Path $uvPath) {
427
- $script:UvCmd = $uvPath
428
- return
429
- }
430
- }
431
-
432
- throw "uv is not installed or not on PATH. Run install.ps1 -Stage uv first."
467
+ throw "uv is not installed. Run install.ps1 -Stage uv first."
433
468
  }
434
469
 
435
470
  function Test-Python {
@@ -755,19 +790,39 @@ function Set-GitBashEnvVar {
755
790
  Write-Info "If needed, set HERMES_GIT_BASH_PATH manually to your bash.exe path."
756
791
  }
757
792
 
793
+ # The desktop build runs Vite ^8, which refuses to start on Node outside
794
+ # `^20.19 || >=22.12` -- older Node lacks node:util.styleText, so `vite build`
795
+ # crashes with a SyntaxError that surfaces only as the opaque "Build desktop
796
+ # app ... exit code 1" install failure. Returns $true when a `node --version`
797
+ # string clears that floor.
798
+ function Test-NodeVersionOk {
799
+ param([string]$Version)
800
+ try {
801
+ $v = [version]($Version -replace '^v', '' -replace '-.*$', '')
802
+ } catch {
803
+ return $false
804
+ }
805
+ if ($v.Major -eq 20 -and $v.Minor -ge 19) { return $true }
806
+ if ($v.Major -ge 22 -and ($v.Major -gt 22 -or $v.Minor -ge 12)) { return $true }
807
+ return $false
808
+ }
809
+
758
810
  function Test-Node {
759
811
  Write-Info "Checking Node.js (for browser tools)..."
760
812
 
761
813
  if (Get-Command node -ErrorAction SilentlyContinue) {
762
814
  $version = node --version
763
- Write-Success "Node.js $version found"
764
- $script:HasNode = $true
765
- return $true
815
+ if (Test-NodeVersionOk $version) {
816
+ Write-Success "Node.js $version found"
817
+ $script:HasNode = $true
818
+ return $true
819
+ }
820
+ Write-Warn "Node.js $version is too old for the desktop build (need ^20.19 or >=22.12)"
766
821
  }
767
822
 
768
- # Check our own managed install from a previous run
823
+ # Prefer a Hermes-managed Node from a previous run over a too-old system one.
769
824
  $managedNode = "$HermesHome\node\node.exe"
770
- if (Test-Path $managedNode) {
825
+ if ((Test-Path $managedNode) -and (Test-NodeVersionOk (& $managedNode --version))) {
771
826
  $version = & $managedNode --version
772
827
  $env:Path = "$HermesHome\node;$env:Path"
773
828
  Write-Success "Node.js $version found (Hermes-managed)"
@@ -775,7 +830,7 @@ function Test-Node {
775
830
  return $true
776
831
  }
777
832
 
778
- Write-Info "Node.js not found -- installing Node.js $NodeVersion LTS..."
833
+ Write-Info "Installing Hermes-managed Node.js $NodeVersion LTS..."
779
834
 
780
835
  # Try the portable-zip path FIRST -- no UAC, no admin, no winget MSI.
781
836
  # winget install OpenJS.NodeJS.LTS triggers a system-wide MSI install
@@ -883,6 +938,42 @@ function Test-Node {
883
938
  return $true
884
939
  }
885
940
 
941
+ function Update-ProcessPathForPackages {
942
+ # Make freshly-installed shims (rg.exe, ffmpeg.exe) visible to Get-Command in
943
+ # THIS process without spawning a new shell, by folding the persisted
944
+ # User+Machine hives plus winget's alias-shim directory into $env:Path.
945
+ # Called after every package-manager attempt (winget/choco/scoop): previously
946
+ # PATH was only refreshed inside the winget branch, so a successful
947
+ # choco/scoop fallback -- or any install on a box without winget -- could be
948
+ # misreported as "not installed".
949
+ #
950
+ # MERGE rather than overwrite: start from the existing process PATH so any
951
+ # process-only entries added earlier in this installer run survive, then
952
+ # APPEND hive/winget-Links entries not already present (case-insensitive,
953
+ # order-preserving dedupe). A wholesale replace would silently drop those
954
+ # process-only entries.
955
+ $candidates = @()
956
+ $candidates += $env:Path
957
+ $candidates += [Environment]::GetEnvironmentVariable("Path", "User")
958
+ $candidates += [Environment]::GetEnvironmentVariable("Path", "Machine")
959
+ $wingetLinks = Join-Path $env:LOCALAPPDATA "Microsoft\WinGet\Links"
960
+ if (Test-Path $wingetLinks) {
961
+ $candidates += $wingetLinks
962
+ }
963
+ $seen = New-Object System.Collections.Generic.HashSet[string] ([StringComparer]::OrdinalIgnoreCase)
964
+ $ordered = New-Object System.Collections.Generic.List[string]
965
+ foreach ($chunk in $candidates) {
966
+ if ([string]::IsNullOrEmpty($chunk)) { continue }
967
+ foreach ($entry in $chunk.Split(';')) {
968
+ $trimmed = $entry.Trim()
969
+ if ($trimmed -and $seen.Add($trimmed)) {
970
+ $ordered.Add($trimmed)
971
+ }
972
+ }
973
+ }
974
+ $env:Path = [string]::Join(';', $ordered)
975
+ }
976
+
886
977
  function Install-SystemPackages {
887
978
  $script:HasRipgrep = $false
888
979
  $script:HasFfmpeg = $false
@@ -952,25 +1043,33 @@ function Install-SystemPackages {
952
1043
  try {
953
1044
  $output = winget install --exact --id $pkg --source winget --silent `
954
1045
  --accept-package-agreements --accept-source-agreements 2>&1
1046
+ $code = $LASTEXITCODE
955
1047
  $output | Out-File -FilePath $log -Encoding utf8
956
- "winget exit: $LASTEXITCODE" | Out-File -FilePath $log -Encoding utf8 -Append
1048
+ "winget exit: $code" | Out-File -FilePath $log -Encoding utf8 -Append
1049
+ # 0x8A15002B (-1978335189) = APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE.
1050
+ # winget treats `install` on a package it already has registered as
1051
+ # an *upgrade*, finds no newer version, and bails with this code --
1052
+ # even when the binary is gone from disk/PATH (stale registration,
1053
+ # files removed outside winget, or a missing alias shim). We KNOW the
1054
+ # command was missing (that's why we're here), so a plain install
1055
+ # dead-ends forever. Force a reinstall to repair the registration so
1056
+ # the shim reappears.
1057
+ if ($code -eq -1978335189) {
1058
+ "-> already-installed/no-upgrade; retrying with --force" | Out-File -FilePath $log -Encoding utf8 -Append
1059
+ $output = winget install --exact --id $pkg --source winget --silent --force `
1060
+ --accept-package-agreements --accept-source-agreements 2>&1
1061
+ $output | Out-File -FilePath $log -Encoding utf8 -Append
1062
+ "winget exit (force): $LASTEXITCODE" | Out-File -FilePath $log -Encoding utf8 -Append
1063
+ }
957
1064
  } catch {
958
1065
  $_ | Out-File -FilePath $log -Encoding utf8 -Append
959
1066
  "winget exit: <exception>" | Out-File -FilePath $log -Encoding utf8 -Append
960
1067
  }
961
1068
  }
962
- # Refresh PATH from both env-var hives AND winget's alias shim directory.
963
- # winget exposes packages via "command line aliases" in %LOCALAPPDATA%\
964
- # Microsoft\WinGet\Links, which is added to PATH by the AppExecutionAlias
965
- # machinery only in *newly-spawned* shells -- not the current process.
966
- # Without this addition, Get-Command rg below would falsely return null
967
- # immediately after a successful install.
968
- $wingetLinks = Join-Path $env:LOCALAPPDATA "Microsoft\WinGet\Links"
969
- $envPath = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")
970
- if (Test-Path $wingetLinks) {
971
- $envPath = "$envPath;$wingetLinks"
972
- }
973
- $env:Path = $envPath
1069
+ # Refresh PATH so packages winget exposed via "command line aliases" in
1070
+ # %LOCALAPPDATA%\Microsoft\WinGet\Links (added to PATH only in
1071
+ # newly-spawned shells, not this process) are visible to Get-Command below.
1072
+ Update-ProcessPathForPackages
974
1073
  if ($needRipgrep -and (Get-Command rg -ErrorAction SilentlyContinue)) {
975
1074
  Write-Success "ripgrep installed"
976
1075
  $script:HasRipgrep = $true
@@ -996,6 +1095,7 @@ function Install-SystemPackages {
996
1095
  foreach ($pkg in $chocoPkgs) {
997
1096
  try { choco install $pkg -y 2>&1 | Out-Null } catch { }
998
1097
  }
1098
+ Update-ProcessPathForPackages
999
1099
  if ($needRipgrep -and (Get-Command rg -ErrorAction SilentlyContinue)) {
1000
1100
  Write-Success "ripgrep installed via chocolatey"
1001
1101
  $script:HasRipgrep = $true
@@ -1014,6 +1114,7 @@ function Install-SystemPackages {
1014
1114
  foreach ($pkg in $scoopPkgs) {
1015
1115
  try { scoop install $pkg 2>&1 | Out-Null } catch { }
1016
1116
  }
1117
+ Update-ProcessPathForPackages
1017
1118
  if ($needRipgrep -and (Get-Command rg -ErrorAction SilentlyContinue)) {
1018
1119
  Write-Success "ripgrep installed via scoop"
1019
1120
  $script:HasRipgrep = $true
@@ -1051,9 +1152,10 @@ function Install-Repository {
1051
1152
  # directory OR a symlink OR a submodule-style gitfile -- and also when
1052
1153
  # it's a broken stub left over from a failed previous install (e.g.
1053
1154
  # a partial Remove-Item that couldn't delete a locked index.lock).
1054
- # Validate the repo properly by asking git itself. Two checks
1055
- # belt-and-braces: rev-parse AND git status. If either fails the
1056
- # repo is broken and we fall through to a fresh clone.
1155
+ # Validate the repo properly by asking git itself. Three checks
1156
+ # belt-and-braces: rev-parse (work tree), git status, and a resolvable
1157
+ # HEAD (an initial commit). If any fails the repo is broken and we
1158
+ # fall through to a fresh clone.
1057
1159
  $repoValid = $false
1058
1160
  if (Test-Path "$InstallDir\.git") {
1059
1161
  Push-Location $InstallDir
@@ -1068,7 +1170,17 @@ function Install-Repository {
1068
1170
  $null = & git -c windows.appendAtomically=false status --short 2>&1
1069
1171
  $statusOk = ($LASTEXITCODE -eq 0)
1070
1172
 
1071
- if ($revParseOk -and $statusOk) {
1173
+ # An interrupted previous clone leaves a repo with NO initial
1174
+ # commit. rev-parse/status still succeed there, but the update
1175
+ # path's `git stash` (and later `git checkout`) abort with
1176
+ # "You do not have the initial commit yet" and fail the install
1177
+ # (#40998). Require a resolvable HEAD so such partial checkouts
1178
+ # are treated as broken and re-cloned fresh below.
1179
+ $global:LASTEXITCODE = 0
1180
+ $null = & git -c windows.appendAtomically=false rev-parse --verify HEAD 2>&1
1181
+ $hasCommit = ($LASTEXITCODE -eq 0)
1182
+
1183
+ if ($revParseOk -and $statusOk -and $hasCommit) {
1072
1184
  $repoValid = $true
1073
1185
  }
1074
1186
  } catch {}
@@ -1084,8 +1196,47 @@ function Install-Repository {
1084
1196
  # EAP=Stop. We rely on $LASTEXITCODE for actual failures.
1085
1197
  $prevEAP = $ErrorActionPreference
1086
1198
  $ErrorActionPreference = "Continue"
1199
+ $autostashRef = ""
1087
1200
  try {
1088
- git -c windows.appendAtomically=false fetch origin
1201
+ # This is a MANAGED checkout, not a repo the user edits. Git for
1202
+ # Windows defaults to core.autocrlf=true, which renormalizes the
1203
+ # repo's LF-only text files to CRLF in the working tree -- so
1204
+ # tracked files (.envrc, AGENTS.md, agent/*.py, workflows, ...)
1205
+ # show as locally modified even though nobody touched them. A
1206
+ # bare `git checkout` then aborts with "Your local changes would
1207
+ # be overwritten by checkout", which is exactly the failure GUI
1208
+ # users hit on update. Pin autocrlf=false so the dirt is never
1209
+ # created in the first place.
1210
+ git -c windows.appendAtomically=false config core.autocrlf false 2>$null
1211
+ # Preserve any real local changes before the checkout instead of
1212
+ # discarding them with `reset --hard HEAD`. The old hard reset
1213
+ # silently destroyed agent-edited source on managed clones (the
1214
+ # #38542 data-loss class). Stash + restore mirrors install.sh:
1215
+ # nothing is lost, and a failed restore leaves the work in a
1216
+ # git stash for manual recovery. Untracked files are included so
1217
+ # agent-created dirs (e.g. tinker-atropos/) survive too.
1218
+ $statusOut = git -c windows.appendAtomically=false status --porcelain 2>$null
1219
+ if (-not [string]::IsNullOrWhiteSpace(($statusOut -join "`n"))) {
1220
+ # A previously interrupted update can leave the index with
1221
+ # unmerged entries. In that state `git stash` aborts with
1222
+ # "could not write index" and the following `git checkout`
1223
+ # aborts with "you need to resolve your current index first"
1224
+ # -- the GUI "git checkout main failed (exit 1)" install
1225
+ # failure. Clear the conflict markers with `git reset` first:
1226
+ # working-tree changes are kept (and stashed just below); only
1227
+ # the index conflict state is dropped. Mirrors the `hermes
1228
+ # update` path (#4735).
1229
+ $unmergedOut = git -c windows.appendAtomically=false ls-files --unmerged 2>$null
1230
+ if (-not [string]::IsNullOrWhiteSpace(($unmergedOut -join "`n"))) {
1231
+ Write-Info "Clearing unmerged index entries from a previous conflict..."
1232
+ git -c windows.appendAtomically=false reset -q 2>$null
1233
+ }
1234
+ $stashName = "hermes-install-autostash-" + (Get-Date -Format "yyyyMMdd-HHmmss")
1235
+ Write-Info "Local changes detected, stashing before update..."
1236
+ git -c windows.appendAtomically=false stash push --include-untracked -m "$stashName"
1237
+ if ($LASTEXITCODE -eq 0) { $autostashRef = "stash@{0}" }
1238
+ }
1239
+ git -c windows.appendAtomically=false fetch origin $Branch
1089
1240
  if ($LASTEXITCODE -ne 0) { throw "git fetch failed (exit $LASTEXITCODE)" }
1090
1241
  # Precedence: Commit > Tag > Branch. Commit and Tag check
1091
1242
  # out as detached HEAD intentionally -- they're meant to be
@@ -1103,25 +1254,80 @@ function Install-Repository {
1103
1254
  } else {
1104
1255
  git -c windows.appendAtomically=false checkout $Branch
1105
1256
  if ($LASTEXITCODE -ne 0) { throw "git checkout $Branch failed (exit $LASTEXITCODE)" }
1106
- git -c windows.appendAtomically=false pull origin $Branch
1257
+ git -c windows.appendAtomically=false pull --ff-only origin $Branch
1107
1258
  if ($LASTEXITCODE -ne 0) { throw "git pull failed (exit $LASTEXITCODE)" }
1108
1259
  }
1260
+
1261
+ if ($autostashRef) {
1262
+ # Default to restoring so work is never silently dropped.
1263
+ # Only prompt when we're certain a human can answer: an
1264
+ # interactive session AND a real, non-redirected console on
1265
+ # both stdin and stdout. The desktop "Update" button and
1266
+ # bootstrap run the installer without a usable console -- in
1267
+ # those cases Read-Host would hang or return empty, so we
1268
+ # skip the prompt and just restore (the safe default).
1269
+ $restoreNow = $true
1270
+ $hasConsole = $false
1271
+ try {
1272
+ $hasConsole = (
1273
+ [Environment]::UserInteractive `
1274
+ -and (-not [Console]::IsInputRedirected) `
1275
+ -and (-not [Console]::IsOutputRedirected) `
1276
+ -and ($Host.Name -eq "ConsoleHost")
1277
+ )
1278
+ } catch { $hasConsole = $false }
1279
+ if ($hasConsole) {
1280
+ Write-Warn "Local changes were stashed before updating."
1281
+ Write-Warn "Restoring them may reapply local customizations onto the updated codebase."
1282
+ $restoreAnswer = Read-Host "Restore local changes now? [Y/n]"
1283
+ if ($restoreAnswer -match '^(n|no)$') { $restoreNow = $false }
1284
+ }
1285
+
1286
+ if ($restoreNow) {
1287
+ Write-Info "Restoring local changes..."
1288
+ git -c windows.appendAtomically=false stash apply $autostashRef
1289
+ if ($LASTEXITCODE -eq 0) {
1290
+ git -c windows.appendAtomically=false stash drop $autostashRef 2>$null
1291
+ Write-Warn "Local changes were restored on top of the updated codebase."
1292
+ Write-Warn "Review git diff / git status if Hermes behaves unexpectedly."
1293
+ } else {
1294
+ Write-Err "Update succeeded, but restoring local changes failed. Your changes are still preserved in git stash."
1295
+ Write-Info "Resolve manually with: git stash apply $autostashRef"
1296
+ throw "git stash apply failed after update"
1297
+ }
1298
+ } else {
1299
+ Write-Info "Skipped restoring local changes."
1300
+ Write-Info "Your changes are still preserved in git stash."
1301
+ Write-Info "Restore manually with: git stash apply $autostashRef"
1302
+ }
1303
+ $autostashRef = ""
1304
+ }
1109
1305
  } finally {
1306
+ if ($autostashRef) {
1307
+ # We stashed but never reached the restore block (a fetch/
1308
+ # checkout/pull failure threw). Leave the stash in place and
1309
+ # tell the user how to recover it -- never silently drop it.
1310
+ Write-Warn "Update did not complete. Your local changes are preserved in git stash."
1311
+ Write-Info "Restore manually with: git stash apply $autostashRef"
1312
+ }
1110
1313
  $ErrorActionPreference = $prevEAP
1111
1314
  Pop-Location
1112
1315
  }
1113
1316
  $didUpdate = $true
1114
1317
  } else {
1115
- # Directory exists but isn't a usable git repo. Wipe it and
1116
- # fall through to a fresh clone. A leftover ``.git`` stub from
1117
- # a partial uninstall used to lock the installer into the
1118
- # "update" branch forever, emitting three ``fatal: not a git
1119
- # repository`` errors and failing with "not in a git directory".
1120
- Write-Warn "Existing directory at $InstallDir is not a valid git repo -- replacing it."
1318
+ # Directory exists but isn't a usable git repo -- e.g. an
1319
+ # interrupted clone with no initial commit (#40998), or a leftover
1320
+ # ``.git`` stub from a partial uninstall that used to lock the
1321
+ # installer into the "update" branch forever. Move it aside rather
1322
+ # than deleting it -- never destroy a directory the user might still
1323
+ # want -- and fall through to a fresh clone.
1324
+ $backupDir = "$InstallDir.broken-" + (Get-Date -Format "yyyyMMdd-HHmmss")
1325
+ Write-Warn "Existing directory at $InstallDir is not a valid git repo."
1326
+ Write-Warn "Moving it aside to $backupDir before re-cloning."
1121
1327
  try {
1122
- Remove-Item -Recurse -Force $InstallDir -ErrorAction Stop
1328
+ Move-Item -LiteralPath $InstallDir -Destination $backupDir -ErrorAction Stop
1123
1329
  } catch {
1124
- Write-Err "Could not remove $InstallDir : $_"
1330
+ Write-Err "Could not move $InstallDir aside : $_"
1125
1331
  Write-Info "Close any programs that might be using files in $InstallDir (editors,"
1126
1332
  Write-Info "terminals, running hermes processes) and try again."
1127
1333
  throw
@@ -1146,7 +1352,7 @@ function Install-Repository {
1146
1352
  Write-Info "Trying SSH clone..."
1147
1353
  $env:GIT_SSH_COMMAND = "ssh -o BatchMode=yes -o ConnectTimeout=5"
1148
1354
  try {
1149
- git -c windows.appendAtomically=false clone --branch $Branch --recurse-submodules $RepoUrlSsh $InstallDir
1355
+ Invoke-NativeWithRelaxedErrorAction { git -c windows.appendAtomically=false clone --depth 1 --branch $Branch $RepoUrlSsh $InstallDir }
1150
1356
  if ($LASTEXITCODE -eq 0) { $cloneSuccess = $true }
1151
1357
  } catch { }
1152
1358
  $env:GIT_SSH_COMMAND = $null
@@ -1155,7 +1361,7 @@ function Install-Repository {
1155
1361
  if (Test-Path $InstallDir) { Remove-Item -Recurse -Force $InstallDir -ErrorAction SilentlyContinue }
1156
1362
  Write-Info "SSH failed, trying HTTPS..."
1157
1363
  try {
1158
- git -c windows.appendAtomically=false clone --branch $Branch --recurse-submodules $RepoUrlHttps $InstallDir
1364
+ Invoke-NativeWithRelaxedErrorAction { git -c windows.appendAtomically=false clone --depth 1 --branch $Branch $RepoUrlHttps $InstallDir }
1159
1365
  if ($LASTEXITCODE -eq 0) { $cloneSuccess = $true }
1160
1366
  } catch { }
1161
1367
  }
@@ -1219,6 +1425,11 @@ function Install-Repository {
1219
1425
  # Set per-repo config (harmless if it fails)
1220
1426
  Push-Location $InstallDir
1221
1427
  git -c windows.appendAtomically=false config windows.appendAtomically false 2>$null
1428
+ # Pin autocrlf=false on the managed clone so git never renormalizes the
1429
+ # repo's LF text files to CRLF in the working tree. Without this, the very
1430
+ # next `hermes update` checkout aborts on a "dirty" tree the user never
1431
+ # touched (see the update path above).
1432
+ git -c windows.appendAtomically=false config core.autocrlf false 2>$null
1222
1433
 
1223
1434
  # Post-clone pin: when a clone (or ZIP-fallback init) just landed us on
1224
1435
  # $Branch's tip, honour the higher-precedence $Commit / $Tag by checking
@@ -1251,16 +1462,6 @@ function Install-Repository {
1251
1462
  }
1252
1463
  }
1253
1464
 
1254
- # Ensure submodules are initialized and updated
1255
- Write-Info "Initializing submodules..."
1256
- git -c windows.appendAtomically=false submodule update --init --recursive 2>$null
1257
- if ($LASTEXITCODE -ne 0) {
1258
- Write-Warn "Submodule init failed (terminal/RL tools may need manual setup)"
1259
- } else {
1260
- Write-Success "Submodules ready"
1261
- }
1262
- Pop-Location
1263
-
1264
1465
  Write-Success "Repository ready"
1265
1466
  }
1266
1467
 
@@ -1276,12 +1477,45 @@ function Install-Venv {
1276
1477
 
1277
1478
  if (Test-Path "venv") {
1278
1479
  Write-Info "Virtual environment already exists, recreating..."
1480
+ # On Windows, native Python extensions (e.g. _bcrypt.pyd) are loaded as
1481
+ # DLLs by any running hermes process. Windows denies deletion of loaded
1482
+ # DLLs, so kill any hermes.exe tree before removing the venv.
1483
+ if ($env:OS -eq "Windows_NT") {
1484
+ $myPid = $PID
1485
+ Write-Info "Stopping any running hermes processes before recreating venv..."
1486
+ & taskkill /F /T /IM hermes.exe /FI "PID ne $myPid" 2>$null | Out-Null
1487
+ Start-Sleep -Milliseconds 800
1488
+ }
1279
1489
  Remove-Item -Recurse -Force "venv"
1280
1490
  }
1281
1491
 
1282
- # uv creates the venv and pins the Python version in one step
1283
- & $UvCmd venv venv --python $PythonVersion
1284
-
1492
+ # uv creates the venv and pins the Python version in one step. uv emits
1493
+ # normal progress such as "Using CPython ..." on stderr; under Windows
1494
+ # PowerShell 5.1 with EAP=Stop that stderr is a NativeCommandError unless
1495
+ # we temporarily relax EAP and trust $LASTEXITCODE for real failures.
1496
+ Invoke-NativeWithRelaxedErrorAction { & $UvCmd venv venv --python $PythonVersion }
1497
+ # Relaxing EAP above means a *genuine* uv-venv failure (exit != 0) no longer
1498
+ # aborts on its own. Capture $LASTEXITCODE immediately and fail fast, so the
1499
+ # `venv` stage can't falsely report success (and Invoke-Stage can't emit
1500
+ # ok=true) when the venv was never created.
1501
+ $venvExitCode = $LASTEXITCODE
1502
+ if ($venvExitCode -ne 0) {
1503
+ Pop-Location
1504
+ throw "Failed to create virtual environment (uv venv exited with $venvExitCode)"
1505
+ }
1506
+
1507
+ # Neutralize any inherited UV_PYTHON (e.g. $env:UV_PYTHON = "3.14" left in
1508
+ # the user's shell). uv honours UV_PYTHON over an existing venv for the
1509
+ # later `uv sync` / `uv pip install` tiers, so without this it would
1510
+ # silently delete this 3.11 venv and recreate it at the inherited version
1511
+ # -- building Rust transitives that have no wheel for that version from
1512
+ # source via maturin, which fails. Pinning UV_PYTHON to the interpreter we
1513
+ # just created forces every subsequent uv command onto it.
1514
+ $venvPythonExe = Join-Path $InstallDir "venv\Scripts\python.exe"
1515
+ if (Test-Path $venvPythonExe) {
1516
+ $env:UV_PYTHON = $venvPythonExe
1517
+ }
1518
+
1285
1519
  Pop-Location
1286
1520
 
1287
1521
  Write-Success "Virtual environment ready (Python $PythonVersion)"
@@ -1297,6 +1531,20 @@ function Install-Dependencies {
1297
1531
  $env:VIRTUAL_ENV = "$InstallDir\venv"
1298
1532
  }
1299
1533
 
1534
+ # Re-pin UV_PYTHON to the venv interpreter. Install-Venv already does this,
1535
+ # but the bootstrap runs install stages (venv, python-deps) as separate
1536
+ # processes, so the env var set in Install-Venv does NOT survive into a
1537
+ # separate python-deps invocation. Re-deriving it here covers that path.
1538
+ # Without it, an inherited $env:UV_PYTHON = "3.14" makes the uv sync/pip
1539
+ # tiers below recreate the venv at 3.14 and fail the maturin source build
1540
+ # (no cp314 wheels yet).
1541
+ if (-not $NoVenv) {
1542
+ $venvPythonExe = Join-Path $InstallDir "venv\Scripts\python.exe"
1543
+ if (Test-Path $venvPythonExe) {
1544
+ $env:UV_PYTHON = $venvPythonExe
1545
+ }
1546
+ }
1547
+
1300
1548
  # Hash-verified install (Tier 0) -- when uv.lock is present, prefer
1301
1549
  # `uv sync --locked`. The lockfile records SHA256 hashes for every
1302
1550
  # transitive dependency, so a compromised transitive (different hash
@@ -1324,7 +1572,7 @@ function Install-Dependencies {
1324
1572
  # in the wrong directory and imports fail with ModuleNotFoundError.
1325
1573
  # (Mirrors the same flag in scripts/install.sh::install_deps.)
1326
1574
  $env:UV_PROJECT_ENVIRONMENT = "$InstallDir\venv"
1327
- & $UvCmd sync --extra all --locked
1575
+ Invoke-NativeWithRelaxedErrorAction { & $UvCmd sync --extra all --locked }
1328
1576
  if ($LASTEXITCODE -eq 0) {
1329
1577
  Write-Success "Main package installed (hash-verified via uv.lock)"
1330
1578
  $script:InstalledTier = "hash-verified (uv.lock)"
@@ -1399,7 +1647,7 @@ except Exception:
1399
1647
  if (-not $skipPipFallback) {
1400
1648
  foreach ($tier in $installTiers) {
1401
1649
  Write-Info "Trying tier: $($tier.Name) ..."
1402
- & $UvCmd pip install -e $tier.Spec
1650
+ Invoke-NativeWithRelaxedErrorAction { & $UvCmd pip install -e $tier.Spec }
1403
1651
  if ($LASTEXITCODE -eq 0) {
1404
1652
  Write-Success "Main package installed ($($tier.Name))"
1405
1653
  $script:InstalledTier = $tier.Name
@@ -1604,7 +1852,7 @@ function Write-BootstrapMarker {
1604
1852
  function Copy-ConfigTemplates {
1605
1853
  Write-Info "Setting up configuration files..."
1606
1854
 
1607
- # Create ~/.hermes directory structure
1855
+ # Create the HERMES_HOME directory structure ($HermesHome, default %LOCALAPPDATA%\hermes)
1608
1856
  New-Item -ItemType Directory -Force -Path "$HermesHome\cron" | Out-Null
1609
1857
  New-Item -ItemType Directory -Force -Path "$HermesHome\sessions" | Out-Null
1610
1858
  New-Item -ItemType Directory -Force -Path "$HermesHome\logs" | Out-Null
@@ -1622,13 +1870,13 @@ function Copy-ConfigTemplates {
1622
1870
  $examplePath = "$InstallDir\.env.example"
1623
1871
  if (Test-Path $examplePath) {
1624
1872
  Copy-Item $examplePath $envPath
1625
- Write-Success "Created ~/.hermes/.env from template"
1873
+ Write-Success "Created $envPath from template"
1626
1874
  } else {
1627
1875
  New-Item -ItemType File -Force -Path $envPath | Out-Null
1628
- Write-Success "Created ~/.hermes/.env"
1876
+ Write-Success "Created $envPath"
1629
1877
  }
1630
1878
  } else {
1631
- Write-Info "~/.hermes/.env already exists, keeping it"
1879
+ Write-Info "$envPath already exists, keeping it"
1632
1880
  }
1633
1881
 
1634
1882
  # Create config.yaml
@@ -1637,10 +1885,10 @@ function Copy-ConfigTemplates {
1637
1885
  $examplePath = "$InstallDir\cli-config.yaml.example"
1638
1886
  if (Test-Path $examplePath) {
1639
1887
  Copy-Item $examplePath $configPath
1640
- Write-Success "Created ~/.hermes/config.yaml from template"
1888
+ Write-Success "Created $configPath from template"
1641
1889
  }
1642
1890
  } else {
1643
- Write-Info "~/.hermes/config.yaml already exists, keeping it"
1891
+ Write-Info "$configPath already exists, keeping it"
1644
1892
  }
1645
1893
 
1646
1894
  # Create SOUL.md if it doesn't exist (global persona file).
@@ -1673,25 +1921,25 @@ Delete the contents (or this file) to use the default personality.
1673
1921
  "@
1674
1922
  $utf8NoBom = New-Object System.Text.UTF8Encoding($false)
1675
1923
  [System.IO.File]::WriteAllText($soulPath, $soulContent, $utf8NoBom)
1676
- Write-Success "Created ~/.hermes/SOUL.md (edit to customize personality)"
1924
+ Write-Success "Created $soulPath (edit to customize personality)"
1677
1925
  }
1678
1926
 
1679
- Write-Success "Configuration directory ready: ~/.hermes/"
1927
+ Write-Success "Configuration directory ready: $HermesHome"
1680
1928
 
1681
- # Seed bundled skills into ~/.hermes/skills/ (manifest-based, one-time per skill)
1682
- Write-Info "Syncing bundled skills to ~/.hermes/skills/ ..."
1929
+ # Seed bundled skills into $HermesHome\skills (manifest-based, one-time per skill)
1930
+ Write-Info "Syncing bundled skills to $HermesHome\skills ..."
1683
1931
  $pythonExe = "$InstallDir\venv\Scripts\python.exe"
1684
1932
  if (Test-Path $pythonExe) {
1685
1933
  try {
1686
1934
  & $pythonExe "$InstallDir\tools\skills_sync.py" 2>$null
1687
- Write-Success "Skills synced to ~/.hermes/skills/"
1935
+ Write-Success "Skills synced to $HermesHome\skills"
1688
1936
  } catch {
1689
1937
  # Fallback: simple directory copy
1690
1938
  $bundledSkills = "$InstallDir\skills"
1691
1939
  $userSkills = "$HermesHome\skills"
1692
1940
  if ((Test-Path $bundledSkills) -and -not (Get-ChildItem $userSkills -Exclude '.bundled_manifest' -ErrorAction SilentlyContinue)) {
1693
1941
  Copy-Item -Path "$bundledSkills\*" -Destination $userSkills -Recurse -Force -ErrorAction SilentlyContinue
1694
- Write-Success "Skills copied to ~/.hermes/skills/"
1942
+ Write-Success "Skills copied to $HermesHome\skills"
1695
1943
  }
1696
1944
  }
1697
1945
  }
@@ -1796,6 +2044,7 @@ function Install-NodeDeps {
1796
2044
  Write-Host " $line" -ForegroundColor DarkGray
1797
2045
  }
1798
2046
  Write-Info " Full log: $logPath"
2047
+ Show-NpmCertHint $errText | Out-Null
1799
2048
  }
1800
2049
  }
1801
2050
  Write-Info "Run manually later: cd `"$installDir`"; npm install"
@@ -1921,6 +2170,124 @@ function Install-NodeDeps {
1921
2170
  }
1922
2171
  }
1923
2172
 
2173
+ # Clear the cached Electron download + any half-written unpacked output so the
2174
+ # next `npm run pack` re-downloads and re-stages from scratch. A corrupt zip in
2175
+ # the per-user Electron download cache - most often a partial download resumed
2176
+ # into the same file, leaving concatenated junk - makes electron-builder's
2177
+ # `app-builder unpack-electron` extract a tree MISSING the electron binary, so
2178
+ # the final `electron` -> `Hermes` rename dies with ENOENT and every re-run
2179
+ # repeats the broken extraction forever.
2180
+ #
2181
+ # We deliberately do not validate the zip ourselves: the common
2182
+ # prepended/concatenated-junk corruption slips past naive checks, so a
2183
+ # self-rolled gate would skip the real-world case. We unconditionally drop the
2184
+ # cached electron-*.zip (loose copy and any @electron/get hash-subdir copy) plus
2185
+ # the stale unpacked dir, then let the caller retry once - @electron/get
2186
+ # re-downloads with its own SHASUM verification, the real source of truth.
2187
+ #
2188
+ # Returns the removed paths. Best-effort: never throws.
2189
+ function Clear-ElectronBuildCache {
2190
+ param([string]$DesktopDir)
2191
+ $removed = @()
2192
+
2193
+ # Per-user Electron download cache dirs, honoring the overrides @electron/get
2194
+ # respects, then the Windows default (%LOCALAPPDATA%\electron\Cache).
2195
+ $cacheDirs = @()
2196
+ if ($env:electron_config_cache) { $cacheDirs += $env:electron_config_cache }
2197
+ if ($env:ELECTRON_CACHE) { $cacheDirs += $env:ELECTRON_CACHE }
2198
+ if ($env:LOCALAPPDATA) { $cacheDirs += (Join-Path $env:LOCALAPPDATA 'electron\Cache') }
2199
+ $cacheDirs += (Join-Path $HOME 'AppData\Local\electron\Cache')
2200
+
2201
+ foreach ($dir in $cacheDirs) {
2202
+ if (-not (Test-Path -LiteralPath $dir)) { continue }
2203
+ # Recurse: the bad copy may be the top-level zip OR a copy inside an
2204
+ # @electron/get hash subdir.
2205
+ $removed += @(Get-ChildItem -LiteralPath $dir -Recurse -Filter 'electron-*.zip' -File -ErrorAction SilentlyContinue | ForEach-Object {
2206
+ try { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction Stop; $_.FullName } catch { }
2207
+ })
2208
+ }
2209
+
2210
+ # A half-written unpacked dir from an interrupted prior pack poisons the
2211
+ # rename even after the zip is fixed (win-unpacked / win-arm64-unpacked).
2212
+ $releaseDir = Join-Path $DesktopDir 'release'
2213
+ if (Test-Path -LiteralPath $releaseDir) {
2214
+ $removed += @(Get-ChildItem -LiteralPath $releaseDir -Directory -Filter '*-unpacked' -ErrorAction SilentlyContinue | ForEach-Object {
2215
+ try { Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction Stop; $_.FullName } catch { }
2216
+ })
2217
+ }
2218
+
2219
+ return $removed
2220
+ }
2221
+
2222
+ # Last-resort Electron mirror after GitHub download fails (#47266).
2223
+ $script:DesktopElectronFallbackMirror = "https://npmmirror.com/mirrors/electron/"
2224
+
2225
+ # Electron package dir — workspace-local nest first, then root hoist.
2226
+ function Get-ElectronDir {
2227
+ param([string]$InstallDir)
2228
+ $desktopLocal = Join-Path $InstallDir 'apps\desktop\node_modules\electron'
2229
+ if (Test-Path -LiteralPath $desktopLocal) { return $desktopLocal }
2230
+ return (Join-Path $InstallDir 'node_modules\electron')
2231
+ }
2232
+
2233
+ # True when dist/ holds a usable Electron binary (#38673 / run-electron-builder.cjs).
2234
+ function Test-ElectronDist {
2235
+ param([string]$InstallDir)
2236
+ $electronDir = Get-ElectronDir -InstallDir $InstallDir
2237
+ $distExe = Join-Path $electronDir 'dist\electron.exe'
2238
+ return (Test-Path -LiteralPath $distExe)
2239
+ }
2240
+
2241
+ # Best-effort: run electron/install.js to populate dist/ (optional mirror).
2242
+ function Restore-ElectronDist {
2243
+ param([string]$InstallDir, [string]$Mirror)
2244
+ if (Test-ElectronDist -InstallDir $InstallDir) { return $true }
2245
+
2246
+ $electronDir = Get-ElectronDir -InstallDir $InstallDir
2247
+ $distExe = Join-Path $electronDir 'dist\electron.exe'
2248
+ $installer = Join-Path $electronDir 'install.js'
2249
+ if (-not (Test-Path -LiteralPath $installer)) { return $false }
2250
+ $node = Get-Command node -ErrorAction SilentlyContinue
2251
+ if (-not $node) { return $false }
2252
+
2253
+ $distDir = Join-Path $electronDir 'dist'
2254
+ if (Test-Path -LiteralPath $distDir) {
2255
+ Remove-Item -LiteralPath $distDir -Recurse -Force -ErrorAction SilentlyContinue
2256
+ }
2257
+ Remove-Item -LiteralPath (Join-Path $electronDir 'path.txt') -Force -ErrorAction SilentlyContinue
2258
+
2259
+ $prevMirror = $env:ELECTRON_MIRROR
2260
+ if ($Mirror) { $env:ELECTRON_MIRROR = $Mirror }
2261
+ try {
2262
+ # Out-Host so the downloader's progress shows on the console WITHOUT
2263
+ # leaking into this function's return value (PowerShell returns every
2264
+ # object left on the output stream, so a bare pipe here would make the
2265
+ # boolean below ambiguous).
2266
+ & $node.Source $installer 2>&1 | ForEach-Object { "$_" } | Out-Host
2267
+ } catch {
2268
+ } finally {
2269
+ $env:ELECTRON_MIRROR = $prevMirror
2270
+ }
2271
+ return (Test-Path -LiteralPath $distExe)
2272
+ }
2273
+
2274
+ function Test-ElectronPkgStagedMissingDist {
2275
+ param([string]$InstallDir)
2276
+ $electronDir = Get-ElectronDir -InstallDir $InstallDir
2277
+ return (
2278
+ (Test-Path -LiteralPath (Join-Path $electronDir 'package.json')) -and
2279
+ (Test-Path -LiteralPath (Join-Path $electronDir 'install.js')) -and
2280
+ (-not (Test-ElectronDist -InstallDir $InstallDir))
2281
+ )
2282
+ }
2283
+
2284
+ function Try-RestoreElectronDist {
2285
+ param([string]$InstallDir)
2286
+ if (Restore-ElectronDist -InstallDir $InstallDir) { return $true }
2287
+ if ($env:ELECTRON_MIRROR) { return $false }
2288
+ return Restore-ElectronDist -InstallDir $InstallDir -Mirror $script:DesktopElectronFallbackMirror
2289
+ }
2290
+
1924
2291
  function Install-Desktop {
1925
2292
  # Build apps/desktop into a launchable Hermes.exe. Only called from
1926
2293
  # Stage-Desktop, which is itself only included in the manifest when
@@ -1939,16 +2306,17 @@ function Install-Desktop {
1939
2306
  # so an "unpacked" build (electron-builder --dir) is enough — we
1940
2307
  # don't need to produce an NSIS/MSI artifact here.
1941
2308
 
1942
- if (-not $HasNode) {
1943
- # Cross-process driver mode: each `-Stage NAME` invocation runs in a
1944
- # fresh PowerShell process, so $script:HasNode set by Stage-Node
1945
- # in the previous process isn't visible. Re-detect rather than
1946
- # trusting the global.
1947
- if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
1948
- Write-Warn "Skipping desktop build (Node.js / npm not on PATH)"
1949
- $script:_StageSkippedReason = "Node.js not available"
1950
- return
1951
- }
2309
+ # Always re-resolve Node here. Stages run in separate PowerShell processes,
2310
+ # so $script:HasNode from Stage-Node isn't visible; more importantly Test-Node
2311
+ # enforces the build floor (^20.19 || >=22.12) and prepends the Hermes-managed
2312
+ # Node to PATH, so the build never runs on a too-old system Node -- the cause
2313
+ # of the opaque "Build desktop app ... exit code 1" failure (Vite crashes on
2314
+ # old Node).
2315
+ Test-Node | Out-Null
2316
+ if (-not (Get-Command npm -ErrorAction SilentlyContinue)) {
2317
+ Write-Warn "Skipping desktop build (Node.js / npm not on PATH)"
2318
+ $script:_StageSkippedReason = "Node.js not available"
2319
+ return
1952
2320
  }
1953
2321
 
1954
2322
  $desktopDir = "$InstallDir\apps\desktop"
@@ -1991,13 +2359,40 @@ function Install-Desktop {
1991
2359
  # captures every stdout/stderr line as it's emitted, so we don't
1992
2360
  # need a side TEMP log file — the installer's bootstrap log
1993
2361
  # IS the artifact a support engineer reads.
1994
- & $npmExe install 2>&1 | ForEach-Object { "$_" }
2362
+ #
2363
+ # Prefer `npm ci`: it wipes node_modules and reinstalls from the
2364
+ # lockfile, always producing a complete tree. Bare `npm install`
2365
+ # can report "up to date" against a stale
2366
+ # node_modules\.package-lock.json marker while node_modules is
2367
+ # actually empty (Windows workspace-hoisting flake), leaving
2368
+ # tsc/typescript unresolved so `npm run pack`'s `tsc -b` dies with
2369
+ # no obvious cause. Fall back to `npm install` only if `npm ci`
2370
+ # fails (lockfile out of sync / very old npm without ci).
2371
+ #
2372
+ # Tee the merged output into $npmOut while still emitting every line
2373
+ # live. We don't need a side log file (the bootstrap streaming sink
2374
+ # is the artifact), but on failure we scan $npmOut for the TLS-trust
2375
+ # signature so corporate-proxy users get the NODE_EXTRA_CA_CERTS hint
2376
+ # instead of an opaque "exit 1" (issue #38016).
2377
+ & $npmExe ci 2>&1 | ForEach-Object { "$_" } | Tee-Object -Variable npmOut
1995
2378
  $code = $LASTEXITCODE
2379
+ if ($code -ne 0) {
2380
+ Write-Info " npm ci failed (exit $code) -- retrying with npm install..."
2381
+ & $npmExe install 2>&1 | ForEach-Object { "$_" } | Tee-Object -Variable npmOut
2382
+ $code = $LASTEXITCODE
2383
+ }
1996
2384
  $ErrorActionPreference = $prevEAP
1997
2385
  if ($code -ne 0) {
1998
- throw "desktop workspace npm install failed (exit $code) -- see lines above for cause"
2386
+ if (Test-ElectronPkgStagedMissingDist -InstallDir $InstallDir) {
2387
+ Write-Warn "Desktop dependency install failed with a missing Electron dist; attempting self-heal..."
2388
+ Try-RestoreElectronDist -InstallDir $InstallDir | Out-Null
2389
+ } else {
2390
+ Show-NpmCertHint ($npmOut -join "`n") | Out-Null
2391
+ throw "desktop workspace npm install failed (exit $code) -- see lines above for cause"
2392
+ }
2393
+ } else {
2394
+ Write-Success "Desktop workspace dependencies installed"
1999
2395
  }
2000
- Write-Success "Desktop workspace dependencies installed"
2001
2396
  } catch {
2002
2397
  if ($prevEAP) { $ErrorActionPreference = $prevEAP }
2003
2398
  Pop-Location
@@ -2039,6 +2434,37 @@ function Install-Desktop {
2039
2434
  $env:WIN_CSC_KEY_PASSWORD = ""
2040
2435
  & $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
2041
2436
  $code = $LASTEXITCODE
2437
+ if ($code -ne 0) {
2438
+ $purged = @()
2439
+ $restored = $false
2440
+ if (-not (Test-ElectronDist -InstallDir $InstallDir)) {
2441
+ $purged = @(Clear-ElectronBuildCache -DesktopDir $desktopDir)
2442
+ $restored = Restore-ElectronDist -InstallDir $InstallDir
2443
+ }
2444
+ if ($restored) {
2445
+ Write-Warn "Desktop build failed - refreshed the Electron download, retrying once:"
2446
+ foreach ($p in $purged) { Write-Info " - $p" }
2447
+ & $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
2448
+ $code = $LASTEXITCODE
2449
+ }
2450
+ }
2451
+ if ($code -ne 0 -and -not $env:ELECTRON_MIRROR) {
2452
+ $mirror = $script:DesktopElectronFallbackMirror
2453
+ Write-Warn "Desktop build still failing - the Electron download from GitHub looks blocked."
2454
+ Write-Warn "Re-downloading Electron via a public mirror ($mirror), then rebuilding:"
2455
+ Write-Info " (set ELECTRON_MIRROR yourself to use a different/trusted mirror)"
2456
+ if (-not (Test-ElectronDist -InstallDir $InstallDir)) {
2457
+ Restore-ElectronDist -InstallDir $InstallDir -Mirror $mirror | Out-Null
2458
+ }
2459
+ $prevMirror = $env:ELECTRON_MIRROR
2460
+ $env:ELECTRON_MIRROR = $mirror
2461
+ try {
2462
+ & $npmExe run pack 2>&1 | ForEach-Object { "$_" } | Tee-Object -FilePath $buildLog
2463
+ $code = $LASTEXITCODE
2464
+ } finally {
2465
+ $env:ELECTRON_MIRROR = $prevMirror
2466
+ }
2467
+ }
2042
2468
  $ErrorActionPreference = $prevEAP
2043
2469
  if ($code -ne 0) {
2044
2470
  $errText = Get-Content $buildLog -Raw -ErrorAction SilentlyContinue