@clawpump/claw-agent 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/.dockerignore +67 -0
- package/agent/.envrc +1 -1
- package/agent/.gitattributes +8 -0
- package/agent/AGENTS.md +216 -4
- package/agent/CONTRIBUTING.md +46 -8
- package/agent/Dockerfile +78 -35
- package/agent/MANIFEST.in +2 -0
- package/agent/README.md +12 -5
- package/agent/README.ur-pk.md +261 -0
- package/agent/README.zh-CN.md +11 -8
- package/agent/SECURITY.md +5 -4
- package/agent/acp_adapter/provenance.py +127 -0
- package/agent/acp_adapter/server.py +112 -5
- package/agent/acp_adapter/session.py +1 -6
- package/agent/acp_registry/agent.json +2 -2
- package/agent/agent/account_usage.py +313 -1
- package/agent/agent/agent_init.py +140 -37
- package/agent/agent/agent_runtime_helpers.py +342 -83
- package/agent/agent/anthropic_adapter.py +320 -33
- package/agent/agent/auxiliary_client.py +525 -105
- package/agent/agent/background_review.py +157 -19
- package/agent/agent/bedrock_adapter.py +71 -6
- package/agent/agent/billing_view.py +295 -0
- package/agent/agent/chat_completion_helpers.py +229 -4
- package/agent/agent/codex_responses_adapter.py +86 -10
- package/agent/agent/codex_runtime.py +153 -1
- package/agent/agent/coding_context.py +738 -0
- package/agent/agent/context_compressor.py +392 -44
- package/agent/agent/context_references.py +34 -1
- package/agent/agent/conversation_compression.py +159 -22
- package/agent/agent/conversation_loop.py +643 -908
- package/agent/agent/copilot_acp_client.py +4 -11
- package/agent/agent/credential_pool.py +5 -3
- package/agent/agent/credits_tracker.py +794 -0
- package/agent/agent/curator.py +91 -18
- package/agent/agent/curator_backup.py +26 -10
- package/agent/agent/display.py +42 -1
- package/agent/agent/error_classifier.py +52 -3
- package/agent/agent/errors.py +3 -0
- package/agent/agent/file_safety.py +0 -17
- package/agent/agent/gemini_native_adapter.py +31 -1
- package/agent/agent/i18n.py +48 -4
- package/agent/agent/image_gen_provider.py +74 -5
- package/agent/agent/image_routing.py +29 -0
- package/agent/agent/insights.py +8 -17
- package/agent/agent/lsp/install.py +3 -0
- package/agent/agent/memory_manager.py +326 -31
- package/agent/agent/message_content.py +50 -0
- package/agent/agent/model_metadata.py +214 -3
- package/agent/agent/moonshot_schema.py +8 -1
- package/agent/agent/onboarding.py +60 -0
- package/agent/agent/prompt_builder.py +327 -37
- package/agent/agent/redact.py +1 -0
- package/agent/agent/runtime_cwd.py +34 -5
- package/agent/agent/secret_scope.py +205 -0
- package/agent/agent/secret_sources/bitwarden.py +34 -2
- package/agent/agent/skill_commands.py +90 -1
- package/agent/agent/skill_preprocessing.py +1 -0
- package/agent/agent/skill_utils.py +209 -36
- package/agent/agent/ssl_guard.py +94 -0
- package/agent/agent/system_prompt.py +133 -5
- package/agent/agent/tool_executor.py +496 -70
- package/agent/agent/transports/anthropic.py +83 -21
- package/agent/agent/transports/chat_completions.py +94 -5
- package/agent/agent/transports/codex.py +67 -2
- package/agent/agent/transports/codex_app_server.py +1 -0
- package/agent/agent/transports/codex_app_server_session.py +30 -0
- package/agent/agent/transports/types.py +12 -0
- package/agent/agent/turn_context.py +408 -0
- package/agent/agent/turn_finalizer.py +428 -0
- package/agent/agent/turn_retry_state.py +68 -0
- package/agent/agent/usage_pricing.py +3 -0
- package/agent/apps/bootstrap-installer/package.json +6 -5
- package/agent/apps/bootstrap-installer/src/routes/failure.tsx +12 -5
- package/agent/apps/bootstrap-installer/src/routes/progress.tsx +1 -3
- package/agent/apps/bootstrap-installer/src/store.ts +3 -2
- package/agent/apps/bootstrap-installer/src-tauri/src/bootstrap.rs +172 -7
- package/agent/apps/bootstrap-installer/src-tauri/src/events.rs +14 -1
- package/agent/apps/bootstrap-installer/src-tauri/src/paths.rs +29 -0
- package/agent/apps/bootstrap-installer/src-tauri/src/powershell.rs +93 -3
- package/agent/apps/bootstrap-installer/src-tauri/src/update.rs +695 -39
- package/agent/apps/bootstrap-installer/tsconfig.json +3 -4
- package/agent/apps/desktop/DESIGN.md +167 -0
- package/agent/apps/desktop/README.md +20 -16
- package/agent/apps/desktop/assets/icon.icns +0 -0
- package/agent/apps/desktop/assets/icon.ico +0 -0
- package/agent/apps/desktop/assets/icon.png +0 -0
- package/agent/apps/desktop/electron/backend-env.cjs +112 -0
- package/agent/apps/desktop/electron/backend-env.test.cjs +111 -0
- package/agent/apps/desktop/electron/backend-probes.test.cjs +3 -1
- package/agent/apps/desktop/electron/backend-ready.cjs +66 -0
- package/agent/apps/desktop/electron/bootstrap-platform.cjs +52 -0
- package/agent/apps/desktop/electron/bootstrap-platform.test.cjs +59 -1
- package/agent/apps/desktop/electron/bootstrap-runner.cjs +176 -38
- package/agent/apps/desktop/electron/bootstrap-runner.test.cjs +112 -1
- package/agent/apps/desktop/electron/connection-config.cjs +288 -0
- package/agent/apps/desktop/electron/connection-config.test.cjs +396 -0
- package/agent/apps/desktop/electron/dashboard-token.cjs +99 -0
- package/agent/apps/desktop/electron/dashboard-token.test.cjs +142 -0
- package/agent/apps/desktop/electron/desktop-uninstall.cjs +232 -0
- package/agent/apps/desktop/electron/desktop-uninstall.test.cjs +246 -0
- package/agent/apps/desktop/electron/entitlements.mac.inherit.plist +2 -0
- package/agent/apps/desktop/electron/fs-read-dir.cjs +109 -0
- package/agent/apps/desktop/electron/fs-read-dir.test.cjs +364 -0
- package/agent/apps/desktop/electron/gateway-ws-probe.cjs +188 -0
- package/agent/apps/desktop/electron/gateway-ws-probe.test.cjs +122 -0
- package/agent/apps/desktop/electron/git-root.cjs +54 -0
- package/agent/apps/desktop/electron/git-root.test.cjs +40 -0
- package/agent/apps/desktop/electron/git-worktrees.cjs +174 -0
- package/agent/apps/desktop/electron/hardening.cjs +123 -28
- package/agent/apps/desktop/electron/hardening.test.cjs +163 -0
- package/agent/apps/desktop/electron/main.cjs +3121 -331
- package/agent/apps/desktop/electron/oauth-net-request.cjs +20 -0
- package/agent/apps/desktop/electron/oauth-net-request.test.cjs +34 -0
- package/agent/apps/desktop/electron/preload.cjs +52 -2
- package/agent/apps/desktop/electron/session-windows.cjs +124 -0
- package/agent/apps/desktop/electron/session-windows.test.cjs +199 -0
- package/agent/apps/desktop/electron/update-rebuild.cjs +29 -0
- package/agent/apps/desktop/electron/update-rebuild.test.cjs +55 -0
- package/agent/apps/desktop/electron/update-remote.cjs +56 -0
- package/agent/apps/desktop/electron/update-remote.test.cjs +78 -0
- package/agent/apps/desktop/electron/vscode-marketplace.cjs +331 -0
- package/agent/apps/desktop/electron/vscode-marketplace.test.cjs +113 -0
- package/agent/apps/desktop/electron/windows-child-process.test.cjs +57 -0
- package/agent/apps/desktop/electron/windows-user-env.cjs +76 -0
- package/agent/apps/desktop/electron/windows-user-env.test.cjs +90 -0
- package/agent/apps/desktop/electron/workspace-cwd.cjs +38 -0
- package/agent/apps/desktop/electron/workspace-cwd.test.cjs +45 -0
- package/agent/apps/desktop/eslint.config.mjs +0 -3
- package/agent/apps/desktop/index.html +27 -2
- package/agent/apps/desktop/package.json +31 -11
- package/agent/apps/desktop/pr-assets/session-source-folders.png +0 -0
- package/agent/apps/desktop/public/apple-touch-icon.png +0 -0
- package/agent/apps/desktop/public/nous-girl.jpg +0 -0
- package/agent/apps/desktop/scripts/assert-dist-built.cjs +70 -0
- package/agent/apps/desktop/scripts/assert-dist-built.test.cjs +84 -0
- package/agent/apps/desktop/scripts/before-pack.cjs +78 -0
- package/agent/apps/desktop/scripts/before-pack.test.cjs +53 -0
- package/agent/apps/desktop/scripts/diag-scroll-reset.mjs +229 -0
- package/agent/apps/desktop/scripts/patch-electron-builder-mac-binary.cjs +64 -0
- package/agent/apps/desktop/scripts/run-electron-builder.cjs +57 -0
- package/agent/apps/desktop/src/app/agents/index.tsx +53 -45
- package/agent/apps/desktop/src/app/artifacts/index.tsx +102 -83
- package/agent/apps/desktop/src/app/chat/chat-drop-overlay.tsx +29 -8
- package/agent/apps/desktop/src/app/chat/chat-swap-overlay.tsx +47 -0
- package/agent/apps/desktop/src/app/chat/composer/attachments.tsx +81 -45
- package/agent/apps/desktop/src/app/chat/composer/completion-drawer.tsx +13 -24
- package/agent/apps/desktop/src/app/chat/composer/context-menu.tsx +138 -88
- package/agent/apps/desktop/src/app/chat/composer/controls.tsx +138 -90
- package/agent/apps/desktop/src/app/chat/composer/enter-submit-dom-race.test.tsx +218 -0
- package/agent/apps/desktop/src/app/chat/composer/focus.ts +32 -0
- package/agent/apps/desktop/src/app/chat/composer/help-hint.tsx +38 -25
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-live-completion-adapter.ts +7 -0
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-mic-recorder.ts +22 -12
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-slash-completions.ts +142 -14
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-voice-conversation.ts +14 -11
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-voice-recorder.ts +9 -6
- package/agent/apps/desktop/src/app/chat/composer/ime-composition-dom-repro.test.tsx +108 -0
- package/agent/apps/desktop/src/app/chat/composer/index.tsx +930 -180
- package/agent/apps/desktop/src/app/chat/composer/inline-refs.ts +136 -32
- package/agent/apps/desktop/src/app/chat/composer/model-pill.tsx +86 -0
- package/agent/apps/desktop/src/app/chat/composer/queue-panel.tsx +54 -75
- package/agent/apps/desktop/src/app/chat/composer/rich-editor.test.ts +117 -1
- package/agent/apps/desktop/src/app/chat/composer/rich-editor.ts +117 -6
- package/agent/apps/desktop/src/app/chat/composer/slash-nav-dom-repro.test.tsx +186 -0
- package/agent/apps/desktop/src/app/chat/composer/status-stack/index.tsx +202 -0
- package/agent/apps/desktop/src/app/chat/composer/status-stack/status-row.tsx +155 -0
- package/agent/apps/desktop/src/app/chat/composer/text-utils.test.ts +104 -0
- package/agent/apps/desktop/src/app/chat/composer/text-utils.ts +37 -9
- package/agent/apps/desktop/src/app/chat/composer/trigger-popover.test.tsx +50 -0
- package/agent/apps/desktop/src/app/chat/composer/trigger-popover.tsx +105 -40
- package/agent/apps/desktop/src/app/chat/composer/types.ts +5 -0
- package/agent/apps/desktop/src/app/chat/composer/url-dialog.tsx +11 -15
- package/agent/apps/desktop/src/app/chat/composer/voice-activity.tsx +8 -4
- package/agent/apps/desktop/src/app/chat/hooks/use-composer-actions.test.ts +57 -0
- package/agent/apps/desktop/src/app/chat/hooks/use-composer-actions.ts +70 -16
- package/agent/apps/desktop/src/app/chat/hooks/use-file-drop-zone.ts +52 -16
- package/agent/apps/desktop/src/app/chat/index.tsx +234 -81
- package/agent/apps/desktop/src/app/chat/perf-probe.tsx +69 -21
- package/agent/apps/desktop/src/app/chat/right-rail/preview-console.tsx +44 -40
- package/agent/apps/desktop/src/app/chat/right-rail/preview-file.tsx +71 -25
- package/agent/apps/desktop/src/app/chat/right-rail/preview-pane.test.tsx +40 -1
- package/agent/apps/desktop/src/app/chat/right-rail/preview-pane.tsx +55 -53
- package/agent/apps/desktop/src/app/chat/right-rail/preview.tsx +35 -17
- package/agent/apps/desktop/src/app/chat/scroll-to-bottom-button.test.tsx +67 -0
- package/agent/apps/desktop/src/app/chat/scroll-to-bottom-button.tsx +74 -0
- package/agent/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx +356 -0
- package/agent/apps/desktop/src/app/chat/sidebar/index.tsx +1189 -364
- package/agent/apps/desktop/src/app/chat/sidebar/load-more-row.tsx +30 -0
- package/agent/apps/desktop/src/app/chat/sidebar/order.test.ts +21 -0
- package/agent/apps/desktop/src/app/chat/sidebar/order.ts +17 -0
- package/agent/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx +524 -0
- package/agent/apps/desktop/src/app/chat/sidebar/session-actions-menu.tsx +80 -45
- package/agent/apps/desktop/src/app/chat/sidebar/session-row.tsx +120 -25
- package/agent/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx +7 -13
- package/agent/apps/desktop/src/app/chat/sidebar/workspace-groups.test.ts +149 -0
- package/agent/apps/desktop/src/app/chat/sidebar/workspace-groups.ts +326 -0
- package/agent/apps/desktop/src/app/chat/thread-loading.ts +7 -2
- package/agent/apps/desktop/src/app/command-center/index.tsx +320 -581
- package/agent/apps/desktop/src/app/command-palette/index.tsx +681 -0
- package/agent/apps/desktop/src/app/command-palette/marketplace-theme-page.tsx +157 -0
- package/agent/apps/desktop/src/app/cron/index.tsx +392 -324
- package/agent/apps/desktop/src/app/cron/job-state.ts +29 -0
- package/agent/apps/desktop/src/app/desktop-controller.tsx +618 -123
- package/agent/apps/desktop/src/app/floating-hud.ts +22 -0
- package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx +265 -0
- package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts +260 -14
- package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-request.ts +48 -4
- package/agent/apps/desktop/src/app/hooks/use-keybinds.ts +270 -0
- package/agent/apps/desktop/src/app/hooks/use-refresh-hotkey.ts +45 -0
- package/agent/apps/desktop/src/app/layout-constants.ts +19 -0
- package/agent/apps/desktop/src/app/messaging/index.tsx +136 -241
- package/agent/apps/desktop/src/app/messaging/platform-icon.tsx +95 -0
- package/agent/apps/desktop/src/app/model-visibility-overlay.tsx +31 -0
- package/agent/apps/desktop/src/app/overlays/overlay-search-input.tsx +18 -62
- package/agent/apps/desktop/src/app/overlays/overlay-split-layout.tsx +59 -7
- package/agent/apps/desktop/src/app/overlays/overlay-view.tsx +9 -5
- package/agent/apps/desktop/src/app/page-search-shell.tsx +42 -20
- package/agent/apps/desktop/src/app/profiles/create-profile-dialog.tsx +165 -0
- package/agent/apps/desktop/src/app/profiles/delete-profile-dialog.tsx +65 -0
- package/agent/apps/desktop/src/app/profiles/index.tsx +174 -199
- package/agent/apps/desktop/src/app/profiles/rename-profile-dialog.tsx +125 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/dnd-manager.ts +27 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/ipc.test.ts +100 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/ipc.ts +12 -18
- package/agent/apps/desktop/src/app/right-sidebar/files/remote-picker.tsx +177 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/tree.tsx +35 -21
- package/agent/apps/desktop/src/app/right-sidebar/files/use-project-tree.test.ts +75 -3
- package/agent/apps/desktop/src/app/right-sidebar/files/use-project-tree.ts +152 -5
- package/agent/apps/desktop/src/app/right-sidebar/index.test.tsx +75 -0
- package/agent/apps/desktop/src/app/right-sidebar/index.tsx +166 -129
- package/agent/apps/desktop/src/app/right-sidebar/store.ts +19 -4
- package/agent/apps/desktop/src/app/right-sidebar/terminal/buffer.ts +65 -0
- package/agent/apps/desktop/src/app/right-sidebar/terminal/index.tsx +29 -34
- package/agent/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx +18 -6
- package/agent/apps/desktop/src/app/right-sidebar/terminal/selection.ts +93 -32
- package/agent/apps/desktop/src/app/right-sidebar/terminal/use-terminal-session.ts +381 -119
- package/agent/apps/desktop/src/app/routes.ts +9 -0
- package/agent/apps/desktop/src/app/session/hooks/use-cwd-actions.ts +17 -7
- package/agent/apps/desktop/src/app/session/hooks/use-message-stream.ts +365 -47
- package/agent/apps/desktop/src/app/session/hooks/use-model-controls.test.tsx +198 -0
- package/agent/apps/desktop/src/app/session/hooks/use-model-controls.ts +70 -34
- package/agent/apps/desktop/src/app/session/hooks/use-prompt-actions.test.tsx +1061 -0
- package/agent/apps/desktop/src/app/session/hooks/use-prompt-actions.ts +1143 -165
- package/agent/apps/desktop/src/app/session/hooks/use-route-resume.test.tsx +341 -2
- package/agent/apps/desktop/src/app/session/hooks/use-route-resume.ts +176 -5
- package/agent/apps/desktop/src/app/session/hooks/use-session-actions.test.tsx +259 -0
- package/agent/apps/desktop/src/app/session/hooks/use-session-actions.ts +452 -149
- package/agent/apps/desktop/src/app/session/hooks/use-session-state-cache.test.tsx +327 -0
- package/agent/apps/desktop/src/app/session/hooks/use-session-state-cache.ts +133 -4
- package/agent/apps/desktop/src/app/session-picker-overlay.tsx +32 -0
- package/agent/apps/desktop/src/app/session-switcher.tsx +107 -0
- package/agent/apps/desktop/src/app/settings/about-settings.tsx +45 -36
- package/agent/apps/desktop/src/app/settings/appearance-settings.tsx +243 -162
- package/agent/apps/desktop/src/app/settings/config-settings.tsx +86 -66
- package/agent/apps/desktop/src/app/settings/constants.ts +459 -122
- package/agent/apps/desktop/src/app/settings/credential-key-ui.tsx +373 -0
- package/agent/apps/desktop/src/app/settings/env-credentials.tsx +198 -0
- package/agent/apps/desktop/src/app/settings/env-var-actions-menu.tsx +136 -0
- package/agent/apps/desktop/src/app/settings/field-copy.ts +56 -0
- package/agent/apps/desktop/src/app/settings/gateway-settings.tsx +385 -72
- package/agent/apps/desktop/src/app/settings/helpers.test.ts +156 -1
- package/agent/apps/desktop/src/app/settings/helpers.ts +30 -2
- package/agent/apps/desktop/src/app/settings/index.tsx +118 -84
- package/agent/apps/desktop/src/app/settings/keys-settings.tsx +62 -419
- package/agent/apps/desktop/src/app/settings/mcp-settings.tsx +65 -60
- package/agent/apps/desktop/src/app/settings/model-settings.test.tsx +129 -5
- package/agent/apps/desktop/src/app/settings/model-settings.tsx +370 -65
- package/agent/apps/desktop/src/app/settings/notifications-settings.tsx +150 -0
- package/agent/apps/desktop/src/app/settings/primitives.tsx +5 -11
- package/agent/apps/desktop/src/app/settings/provider-config-panel.test.tsx +142 -0
- package/agent/apps/desktop/src/app/settings/provider-config-panel.tsx +182 -0
- package/agent/apps/desktop/src/app/settings/providers-settings.test.tsx +171 -0
- package/agent/apps/desktop/src/app/settings/providers-settings.tsx +471 -0
- package/agent/apps/desktop/src/app/settings/sessions-settings.tsx +183 -71
- package/agent/apps/desktop/src/app/settings/toolset-config-panel.test.tsx +135 -1
- package/agent/apps/desktop/src/app/settings/toolset-config-panel.tsx +180 -57
- package/agent/apps/desktop/src/app/settings/types.ts +9 -6
- package/agent/apps/desktop/src/app/settings/uninstall-section.tsx +185 -0
- package/agent/apps/desktop/src/app/settings/use-deep-link-highlight.ts +60 -0
- package/agent/apps/desktop/src/app/shell/app-shell.tsx +59 -13
- package/agent/apps/desktop/src/app/shell/gateway-menu-panel.tsx +37 -32
- package/agent/apps/desktop/src/app/shell/hooks/use-overlay-routing.ts +6 -3
- package/agent/apps/desktop/src/app/shell/hooks/use-statusbar-items.tsx +212 -53
- package/agent/apps/desktop/src/app/shell/keybind-panel.tsx +215 -0
- package/agent/apps/desktop/src/app/shell/model-edit-submenu.test.tsx +84 -0
- package/agent/apps/desktop/src/app/shell/model-edit-submenu.tsx +244 -0
- package/agent/apps/desktop/src/app/shell/model-menu-panel.tsx +392 -0
- package/agent/apps/desktop/src/app/shell/statusbar-controls.tsx +23 -33
- package/agent/apps/desktop/src/app/shell/titlebar-controls.tsx +79 -95
- package/agent/apps/desktop/src/app/shell/titlebar.ts +8 -2
- package/agent/apps/desktop/src/app/skills/index.test.tsx +11 -0
- package/agent/apps/desktop/src/app/skills/index.tsx +79 -64
- package/agent/apps/desktop/src/app/types.ts +85 -0
- package/agent/apps/desktop/src/app/updates-overlay.tsx +110 -105
- package/agent/apps/desktop/src/components/assistant-ui/ansi-text.tsx +34 -0
- package/agent/apps/desktop/src/components/assistant-ui/block-direction.test.tsx +129 -0
- package/agent/apps/desktop/src/components/assistant-ui/clarify-tool.tsx +102 -81
- package/agent/apps/desktop/src/components/assistant-ui/directive-text.tsx +92 -15
- package/agent/apps/desktop/src/components/assistant-ui/markdown-text.test.ts +38 -0
- package/agent/apps/desktop/src/components/assistant-ui/markdown-text.tsx +304 -45
- package/agent/apps/desktop/src/components/assistant-ui/message-render-boundary.test.tsx +80 -0
- package/agent/apps/desktop/src/components/assistant-ui/message-render-boundary.tsx +48 -0
- package/agent/apps/desktop/src/components/assistant-ui/streaming.test.tsx +142 -90
- package/agent/apps/desktop/src/components/assistant-ui/thread-list.tsx +337 -0
- package/agent/apps/desktop/src/components/assistant-ui/thread.tsx +667 -190
- package/agent/apps/desktop/src/components/assistant-ui/tool-approval-group.test.tsx +299 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-approval.test.tsx +133 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-approval.tsx +239 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts +31 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts +152 -134
- package/agent/apps/desktop/src/components/assistant-ui/tool-fallback.tsx +142 -150
- package/agent/apps/desktop/src/components/assistant-ui/tooltip-icon-button.tsx +14 -12
- package/agent/apps/desktop/src/components/assistant-ui/user-message-edit.test.tsx +141 -0
- package/agent/apps/desktop/src/components/assistant-ui/user-message-text.tsx +152 -0
- package/agent/apps/desktop/src/components/boot-failure-overlay.tsx +150 -33
- package/agent/apps/desktop/src/components/boot-failure-reauth.test.ts +100 -0
- package/agent/apps/desktop/src/components/boot-failure-reauth.ts +81 -0
- package/agent/apps/desktop/src/components/brand-mark.tsx +19 -0
- package/agent/apps/desktop/src/components/chat/code-card.tsx +1 -1
- package/agent/apps/desktop/src/components/chat/composer-dock.ts +31 -0
- package/agent/apps/desktop/src/components/chat/diff-lines.tsx +1 -1
- package/agent/apps/desktop/src/components/chat/disclosure-row.tsx +13 -3
- package/agent/apps/desktop/src/components/chat/expandable-block.tsx +52 -0
- package/agent/apps/desktop/src/components/chat/generated-image-result.tsx +174 -0
- package/agent/apps/desktop/src/components/chat/image-generation-placeholder.tsx +70 -37
- package/agent/apps/desktop/src/components/chat/intro.tsx +8 -7
- package/agent/apps/desktop/src/components/chat/preview-attachment.tsx +4 -2
- package/agent/apps/desktop/src/components/chat/shiki-highlighter.test.ts +37 -0
- package/agent/apps/desktop/src/components/chat/shiki-highlighter.tsx +96 -22
- package/agent/apps/desktop/src/components/chat/status-row.tsx +70 -0
- package/agent/apps/desktop/src/components/chat/status-section.tsx +42 -0
- package/agent/apps/desktop/src/components/chat/terminal-output.tsx +54 -0
- package/agent/apps/desktop/src/components/chat/zoomable-image.tsx +70 -109
- package/agent/apps/desktop/src/components/desktop-install-overlay.tsx +154 -84
- package/agent/apps/desktop/src/components/desktop-onboarding-overlay.test.tsx +38 -8
- package/agent/apps/desktop/src/components/desktop-onboarding-overlay.tsx +789 -233
- package/agent/apps/desktop/src/components/error-boundary.tsx +77 -0
- package/agent/apps/desktop/src/components/gateway-connecting-overlay.test.tsx +144 -0
- package/agent/apps/desktop/src/components/gateway-connecting-overlay.tsx +7 -1
- package/agent/apps/desktop/src/components/haptics-provider.tsx +24 -0
- package/agent/apps/desktop/src/components/language-switcher.test.tsx +53 -0
- package/agent/apps/desktop/src/components/language-switcher.tsx +175 -0
- package/agent/apps/desktop/src/components/model-picker.tsx +42 -40
- package/agent/apps/desktop/src/components/model-visibility-dialog.tsx +166 -0
- package/agent/apps/desktop/src/components/notifications.tsx +48 -27
- package/agent/apps/desktop/src/components/pane-shell/index.ts +1 -1
- package/agent/apps/desktop/src/components/pane-shell/pane-shell.tsx +146 -9
- package/agent/apps/desktop/src/components/prompt-overlays.tsx +234 -0
- package/agent/apps/desktop/src/components/session-picker.tsx +108 -0
- package/agent/apps/desktop/src/components/ui/action-status.tsx +25 -0
- package/agent/apps/desktop/src/components/ui/badge.tsx +35 -0
- package/agent/apps/desktop/src/components/ui/button.tsx +37 -13
- package/agent/apps/desktop/src/components/ui/confirm-dialog.tsx +109 -0
- package/agent/apps/desktop/src/components/ui/control.ts +25 -0
- package/agent/apps/desktop/src/components/ui/copy-button.test.tsx +36 -0
- package/agent/apps/desktop/src/components/ui/copy-button.tsx +38 -27
- package/agent/apps/desktop/src/components/ui/dialog.tsx +39 -11
- package/agent/apps/desktop/src/components/ui/dropdown-menu.tsx +98 -24
- package/agent/apps/desktop/src/components/ui/error-state.tsx +50 -0
- package/agent/apps/desktop/src/components/ui/fade-text.tsx +9 -2
- package/agent/apps/desktop/src/components/ui/{braille-spinner.tsx → glyph-spinner.tsx} +15 -13
- package/agent/apps/desktop/src/components/ui/input.tsx +5 -2
- package/agent/apps/desktop/src/components/ui/kbd.tsx +83 -12
- package/agent/apps/desktop/src/components/ui/log-view.tsx +19 -0
- package/agent/apps/desktop/src/components/ui/pagination.tsx +12 -5
- package/agent/apps/desktop/src/components/ui/popover.tsx +44 -0
- package/agent/apps/desktop/src/components/ui/search-field.tsx +80 -0
- package/agent/apps/desktop/src/components/ui/segmented-control.tsx +51 -0
- package/agent/apps/desktop/src/components/ui/select.tsx +10 -3
- package/agent/apps/desktop/src/components/ui/sheet.tsx +8 -2
- package/agent/apps/desktop/src/components/ui/sidebar.tsx +18 -25
- package/agent/apps/desktop/src/components/ui/switch.tsx +38 -15
- package/agent/apps/desktop/src/components/ui/textarea.tsx +4 -11
- package/agent/apps/desktop/src/components/ui/tool-icon.tsx +65 -0
- package/agent/apps/desktop/src/components/ui/tooltip.tsx +31 -4
- package/agent/apps/desktop/src/fonts/JetBrainsMono-Bold.woff2 +0 -0
- package/agent/apps/desktop/src/fonts/JetBrainsMono-Italic.woff2 +0 -0
- package/agent/apps/desktop/src/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/agent/apps/desktop/src/global.d.ts +181 -4
- package/agent/apps/desktop/src/hermes.test.ts +60 -0
- package/agent/apps/desktop/src/hermes.ts +190 -13
- package/agent/apps/desktop/src/hooks/use-image-download.ts +85 -0
- package/agent/apps/desktop/src/hooks/use-resize-observer.ts +13 -4
- package/agent/apps/desktop/src/hooks/use-worktree-info.ts +68 -0
- package/agent/apps/desktop/src/i18n/catalog.ts +12 -0
- package/agent/apps/desktop/src/i18n/context.test.tsx +232 -0
- package/agent/apps/desktop/src/i18n/context.tsx +183 -0
- package/agent/apps/desktop/src/i18n/define-locale.ts +41 -0
- package/agent/apps/desktop/src/i18n/en.ts +1921 -0
- package/agent/apps/desktop/src/i18n/index.ts +20 -0
- package/agent/apps/desktop/src/i18n/ja.ts +2053 -0
- package/agent/apps/desktop/src/i18n/languages.test.ts +43 -0
- package/agent/apps/desktop/src/i18n/languages.ts +86 -0
- package/agent/apps/desktop/src/i18n/runtime.test.ts +75 -0
- package/agent/apps/desktop/src/i18n/runtime.ts +53 -0
- package/agent/apps/desktop/src/i18n/types.ts +1559 -0
- package/agent/apps/desktop/src/i18n/zh-hant.ts +1992 -0
- package/agent/apps/desktop/src/i18n/zh.ts +2099 -0
- package/agent/apps/desktop/src/lib/ansi.test.ts +123 -0
- package/agent/apps/desktop/src/lib/ansi.ts +186 -0
- package/agent/apps/desktop/src/lib/chat-messages.test.ts +79 -0
- package/agent/apps/desktop/src/lib/chat-messages.ts +68 -29
- package/agent/apps/desktop/src/lib/chat-runtime.test.ts +65 -1
- package/agent/apps/desktop/src/lib/chat-runtime.ts +39 -3
- package/agent/apps/desktop/src/lib/completion-sound.ts +519 -0
- package/agent/apps/desktop/src/lib/desktop-fs.test.ts +116 -0
- package/agent/apps/desktop/src/lib/desktop-fs.ts +113 -0
- package/agent/apps/desktop/src/lib/desktop-slash-commands.test.ts +89 -6
- package/agent/apps/desktop/src/lib/desktop-slash-commands.ts +270 -131
- package/agent/apps/desktop/src/lib/external-link.test.tsx +27 -0
- package/agent/apps/desktop/src/lib/external-link.tsx +9 -2
- package/agent/apps/desktop/src/lib/gateway-events.test.ts +27 -0
- package/agent/apps/desktop/src/lib/gateway-events.ts +16 -0
- package/agent/apps/desktop/src/lib/gateway-ws-url.test.ts +78 -0
- package/agent/apps/desktop/src/lib/gateway-ws-url.ts +91 -0
- package/agent/apps/desktop/src/lib/generated-images.test.ts +97 -0
- package/agent/apps/desktop/src/lib/generated-images.ts +116 -0
- package/agent/apps/desktop/src/lib/haptics.ts +17 -0
- package/agent/apps/desktop/src/lib/icons.ts +10 -2
- package/agent/apps/desktop/src/lib/keybinds/actions.ts +137 -0
- package/agent/apps/desktop/src/lib/keybinds/combo.test.ts +86 -0
- package/agent/apps/desktop/src/lib/keybinds/combo.ts +195 -0
- package/agent/apps/desktop/src/lib/local-preview.ts +23 -2
- package/agent/apps/desktop/src/lib/markdown-preprocess.ts +20 -7
- package/agent/apps/desktop/src/lib/media.remote.test.ts +90 -0
- package/agent/apps/desktop/src/lib/media.ts +40 -1
- package/agent/apps/desktop/src/lib/model-status-label.test.ts +59 -0
- package/agent/apps/desktop/src/lib/model-status-label.ts +122 -0
- package/agent/apps/desktop/src/lib/mutable-ref.ts +6 -0
- package/agent/apps/desktop/src/lib/profile-color.ts +58 -0
- package/agent/apps/desktop/src/lib/query-client.ts +13 -0
- package/agent/apps/desktop/src/lib/remend-tail.test.ts +105 -0
- package/agent/apps/desktop/src/lib/remend-tail.ts +108 -0
- package/agent/apps/desktop/src/lib/session-export.ts +6 -3
- package/agent/apps/desktop/src/lib/session-ids.test.ts +44 -0
- package/agent/apps/desktop/src/lib/session-ids.ts +26 -0
- package/agent/apps/desktop/src/lib/session-search.test.ts +66 -0
- package/agent/apps/desktop/src/lib/session-search.ts +21 -0
- package/agent/apps/desktop/src/lib/session-source.ts +126 -0
- package/agent/apps/desktop/src/lib/storage.test.ts +25 -0
- package/agent/apps/desktop/src/lib/storage.ts +35 -1
- package/agent/apps/desktop/src/lib/todos.test.ts +46 -1
- package/agent/apps/desktop/src/lib/todos.ts +37 -0
- package/agent/apps/desktop/src/lib/tool-result-summary.ts +5 -1
- package/agent/apps/desktop/src/lib/update-copy.test.ts +38 -0
- package/agent/apps/desktop/src/lib/update-copy.ts +44 -0
- package/agent/apps/desktop/src/lib/use-enter-animation.ts +2 -2
- package/agent/apps/desktop/src/lib/yolo-session.ts +50 -0
- package/agent/apps/desktop/src/main.tsx +19 -19
- package/agent/apps/desktop/src/store/boot.ts +4 -3
- package/agent/apps/desktop/src/store/clarify.test.ts +81 -0
- package/agent/apps/desktop/src/store/clarify.ts +50 -13
- package/agent/apps/desktop/src/store/command-palette.ts +20 -0
- package/agent/apps/desktop/src/store/compaction.test.ts +53 -0
- package/agent/apps/desktop/src/store/compaction.ts +38 -0
- package/agent/apps/desktop/src/store/completion-sound.ts +32 -0
- package/agent/apps/desktop/src/store/composer-input-history.test.ts +147 -0
- package/agent/apps/desktop/src/store/composer-input-history.ts +158 -0
- package/agent/apps/desktop/src/store/composer-queue.test.ts +68 -0
- package/agent/apps/desktop/src/store/composer-queue.ts +76 -0
- package/agent/apps/desktop/src/store/composer-status.test.ts +99 -0
- package/agent/apps/desktop/src/store/composer-status.ts +277 -0
- package/agent/apps/desktop/src/store/composer.test.ts +106 -0
- package/agent/apps/desktop/src/store/composer.ts +116 -0
- package/agent/apps/desktop/src/store/cron.ts +19 -0
- package/agent/apps/desktop/src/store/gateway.ts +280 -6
- package/agent/apps/desktop/src/store/keybinds.ts +143 -0
- package/agent/apps/desktop/src/store/layout.ts +107 -9
- package/agent/apps/desktop/src/store/model-presets.test.ts +51 -0
- package/agent/apps/desktop/src/store/model-presets.ts +86 -0
- package/agent/apps/desktop/src/store/model-visibility.test.ts +99 -0
- package/agent/apps/desktop/src/store/model-visibility.ts +161 -0
- package/agent/apps/desktop/src/store/native-notifications.test.ts +192 -0
- package/agent/apps/desktop/src/store/native-notifications.ts +203 -0
- package/agent/apps/desktop/src/store/notifications.ts +10 -7
- package/agent/apps/desktop/src/store/onboarding.test.ts +271 -1
- package/agent/apps/desktop/src/store/onboarding.ts +268 -38
- package/agent/apps/desktop/src/store/preview.ts +10 -1
- package/agent/apps/desktop/src/store/profile.test.ts +89 -0
- package/agent/apps/desktop/src/store/profile.ts +395 -0
- package/agent/apps/desktop/src/store/prompts.test.ts +127 -0
- package/agent/apps/desktop/src/store/prompts.ts +117 -0
- package/agent/apps/desktop/src/store/session-switcher.test.ts +115 -0
- package/agent/apps/desktop/src/store/session-switcher.ts +128 -0
- package/agent/apps/desktop/src/store/session-sync.ts +25 -0
- package/agent/apps/desktop/src/store/session.test.ts +268 -2
- package/agent/apps/desktop/src/store/session.ts +392 -18
- package/agent/apps/desktop/src/store/subagents.ts +3 -0
- package/agent/apps/desktop/src/store/system-actions.ts +48 -0
- package/agent/apps/desktop/src/store/thread-scroll.ts +58 -5
- package/agent/apps/desktop/src/store/todos.test.ts +47 -0
- package/agent/apps/desktop/src/store/todos.ts +64 -0
- package/agent/apps/desktop/src/store/tool-dismiss.ts +45 -0
- package/agent/apps/desktop/src/store/translucency.ts +38 -0
- package/agent/apps/desktop/src/store/updates.test.ts +187 -2
- package/agent/apps/desktop/src/store/updates.ts +268 -18
- package/agent/apps/desktop/src/store/windows.test.ts +143 -0
- package/agent/apps/desktop/src/store/windows.ts +115 -0
- package/agent/apps/desktop/src/styles.css +510 -119
- package/agent/apps/desktop/src/themes/color.ts +142 -0
- package/agent/apps/desktop/src/themes/context.tsx +128 -75
- package/agent/apps/desktop/src/themes/install.test.ts +119 -0
- package/agent/apps/desktop/src/themes/install.ts +95 -0
- package/agent/apps/desktop/src/themes/presets.test.ts +33 -0
- package/agent/apps/desktop/src/themes/presets.ts +13 -4
- package/agent/apps/desktop/src/themes/profile-theme.test.ts +41 -0
- package/agent/apps/desktop/src/themes/types.ts +35 -0
- package/agent/apps/desktop/src/themes/user-themes.test.ts +63 -0
- package/agent/apps/desktop/src/themes/user-themes.ts +122 -0
- package/agent/apps/desktop/src/themes/vscode.test.ts +171 -0
- package/agent/apps/desktop/src/themes/vscode.ts +343 -0
- package/agent/apps/desktop/src/types/hermes.ts +138 -1
- package/agent/apps/desktop/tsconfig.json +2 -2
- package/agent/apps/desktop/vite.config.ts +18 -0
- package/agent/apps/shared/package.json +1 -1
- package/agent/apps/shared/src/json-rpc-gateway.ts +63 -2
- package/agent/apps/shared/tsconfig.json +2 -2
- package/agent/cli-config.yaml.example +78 -1
- package/agent/cli.py +2177 -3162
- package/agent/cron/blueprint_catalog.py +713 -0
- package/agent/cron/jobs.py +226 -110
- package/agent/cron/scheduler.py +468 -193
- package/agent/cron/scheduler_provider.py +177 -0
- package/agent/cron/scripts/__init__.py +1 -0
- package/agent/cron/scripts/classify_items.py +226 -0
- package/agent/cron/suggestion_catalog.py +154 -0
- package/agent/cron/suggestions.py +257 -0
- package/agent/docs/chronos-managed-cron-contract.md +196 -0
- package/agent/docs/design/profile-builder.md +146 -0
- package/agent/docs/middleware/README.md +260 -0
- package/agent/docs/observability/README.md +316 -0
- package/agent/docs/plans/2026-06-09-003-fix-telegram-stream-overflow-continuations-plan.md +240 -0
- package/agent/docs/rca-ssl-cacert-post-git-pull.md +54 -0
- package/agent/docs/relay-connector-contract.md +285 -0
- package/agent/gateway/authz_mixin.py +536 -0
- package/agent/gateway/channel_directory.py +65 -3
- package/agent/gateway/config.py +222 -12
- package/agent/gateway/display_config.py +10 -0
- package/agent/gateway/hooks.py +17 -0
- package/agent/gateway/kanban_watchers.py +1146 -0
- package/agent/gateway/message_timestamps.py +166 -0
- package/agent/gateway/platforms/ADDING_A_PLATFORM.md +29 -0
- package/agent/gateway/platforms/api_server.py +216 -38
- package/agent/gateway/platforms/base.py +210 -58
- package/agent/gateway/platforms/email.py +122 -12
- package/agent/gateway/platforms/feishu.py +80 -11
- package/agent/gateway/platforms/feishu_meeting_invite.py +212 -0
- package/agent/gateway/platforms/matrix.py +1498 -297
- package/agent/gateway/platforms/qqbot/adapter.py +6 -0
- package/agent/gateway/platforms/signal.py +8 -0
- package/agent/gateway/platforms/slack.py +308 -12
- package/agent/gateway/platforms/telegram.py +831 -24
- package/agent/gateway/platforms/webhook.py +109 -21
- package/agent/gateway/platforms/weixin.py +113 -2
- package/agent/gateway/platforms/whatsapp.py +94 -288
- package/agent/gateway/platforms/whatsapp_cloud.py +1956 -0
- package/agent/gateway/platforms/whatsapp_common.py +367 -0
- package/agent/gateway/platforms/yuanbao.py +608 -191
- package/agent/gateway/platforms/yuanbao_proto.py +232 -23
- package/agent/gateway/relay/__init__.py +375 -0
- package/agent/gateway/relay/adapter.py +222 -0
- package/agent/gateway/relay/auth.py +168 -0
- package/agent/gateway/relay/descriptor.py +118 -0
- package/agent/gateway/relay/transport.py +101 -0
- package/agent/gateway/relay/ws_transport.py +327 -0
- package/agent/gateway/response_filters.py +53 -0
- package/agent/gateway/rich_sent_store.py +80 -0
- package/agent/gateway/run.py +2940 -5001
- package/agent/gateway/session.py +109 -8
- package/agent/gateway/session_context.py +22 -4
- package/agent/gateway/slash_commands.py +3854 -0
- package/agent/gateway/status.py +141 -21
- package/agent/gateway/stream_consumer.py +288 -31
- package/agent/hermes-already-has-routines.md +1 -1
- package/agent/hermes_cli/__init__.py +62 -17
- package/agent/hermes_cli/_parser.py +30 -0
- package/agent/hermes_cli/_subprocess_compat.py +61 -0
- package/agent/hermes_cli/active_sessions.py +320 -0
- package/agent/hermes_cli/auth.py +707 -59
- package/agent/hermes_cli/auth_commands.py +39 -22
- package/agent/hermes_cli/backup.py +109 -7
- package/agent/hermes_cli/banner.py +88 -0
- package/agent/hermes_cli/blueprint_cmd.py +318 -0
- package/agent/hermes_cli/cli_agent_setup_mixin.py +684 -0
- package/agent/hermes_cli/cli_commands_mixin.py +2293 -0
- package/agent/hermes_cli/commands.py +215 -91
- package/agent/hermes_cli/config.py +967 -130
- package/agent/hermes_cli/container_boot.py +76 -11
- package/agent/hermes_cli/cron.py +5 -11
- package/agent/hermes_cli/curator.py +21 -0
- package/agent/hermes_cli/dashboard_auth/__init__.py +2 -0
- package/agent/hermes_cli/dashboard_auth/base.py +62 -0
- package/agent/hermes_cli/dashboard_auth/cookies.py +32 -19
- package/agent/hermes_cli/dashboard_auth/login_page.py +156 -6
- package/agent/hermes_cli/dashboard_auth/middleware.py +28 -4
- package/agent/hermes_cli/dashboard_auth/prefix.py +46 -2
- package/agent/hermes_cli/dashboard_auth/public_paths.py +6 -0
- package/agent/hermes_cli/dashboard_auth/routes.py +158 -2
- package/agent/hermes_cli/dashboard_auth/ws_tickets.py +85 -11
- package/agent/hermes_cli/dashboard_register.py +427 -0
- package/agent/hermes_cli/debug.py +155 -50
- package/agent/hermes_cli/doctor.py +255 -14
- package/agent/hermes_cli/dump.py +60 -6
- package/agent/hermes_cli/env_loader.py +33 -0
- package/agent/hermes_cli/gateway.py +755 -103
- package/agent/hermes_cli/gateway_enroll.py +250 -0
- package/agent/hermes_cli/gateway_windows.py +254 -11
- package/agent/hermes_cli/gui_uninstall.py +285 -0
- package/agent/hermes_cli/inventory.py +105 -4
- package/agent/hermes_cli/kanban.py +58 -71
- package/agent/hermes_cli/kanban_db.py +391 -14
- package/agent/hermes_cli/kanban_decompose.py +2 -2
- package/agent/hermes_cli/kanban_specify.py +3 -1
- package/agent/hermes_cli/logs.py +2 -0
- package/agent/hermes_cli/main.py +2889 -5287
- package/agent/hermes_cli/managed_scope.py +214 -0
- package/agent/hermes_cli/managed_uv.py +254 -0
- package/agent/hermes_cli/mcp_catalog.py +6 -3
- package/agent/hermes_cli/mcp_config.py +145 -21
- package/agent/hermes_cli/mcp_security.py +96 -0
- package/agent/hermes_cli/mcp_startup.py +32 -3
- package/agent/hermes_cli/memory_providers.py +149 -0
- package/agent/hermes_cli/memory_setup.py +97 -42
- package/agent/hermes_cli/middleware.py +313 -0
- package/agent/hermes_cli/model_catalog.py +31 -0
- package/agent/hermes_cli/model_cost_guard.py +134 -0
- package/agent/hermes_cli/model_normalize.py +2 -1
- package/agent/hermes_cli/model_setup_flows.py +2759 -0
- package/agent/hermes_cli/model_switch.py +242 -27
- package/agent/hermes_cli/models.py +284 -44
- package/agent/hermes_cli/nous_account.py +33 -6
- package/agent/hermes_cli/nous_billing.py +406 -0
- package/agent/hermes_cli/nous_subscription.py +202 -5
- package/agent/hermes_cli/platforms.py +1 -0
- package/agent/hermes_cli/plugins.py +218 -18
- package/agent/hermes_cli/plugins_cmd.py +249 -105
- package/agent/hermes_cli/portal_cli.py +56 -16
- package/agent/hermes_cli/profile_distribution.py +6 -1
- package/agent/hermes_cli/profiles.py +283 -32
- package/agent/hermes_cli/provider_catalog.py +170 -0
- package/agent/hermes_cli/providers.py +4 -1
- package/agent/hermes_cli/pty_bridge.py +53 -4
- package/agent/hermes_cli/runtime_provider.py +216 -34
- package/agent/hermes_cli/secret_prompt.py +4 -4
- package/agent/hermes_cli/secrets_cli.py +24 -0
- package/agent/hermes_cli/send_cmd.py +28 -2
- package/agent/hermes_cli/service_manager.py +166 -19
- package/agent/hermes_cli/session_listing.py +97 -0
- package/agent/hermes_cli/setup.py +158 -94
- package/agent/hermes_cli/setup_whatsapp_cloud.py +541 -0
- package/agent/hermes_cli/skills_config.py +8 -2
- package/agent/hermes_cli/skills_hub.py +149 -7
- package/agent/hermes_cli/status.py +2 -2
- package/agent/hermes_cli/subcommands/__init__.py +18 -0
- package/agent/hermes_cli/subcommands/_shared.py +29 -0
- package/agent/hermes_cli/subcommands/acp.py +52 -0
- package/agent/hermes_cli/subcommands/auth.py +109 -0
- package/agent/hermes_cli/subcommands/backup.py +38 -0
- package/agent/hermes_cli/subcommands/claw.py +92 -0
- package/agent/hermes_cli/subcommands/config.py +49 -0
- package/agent/hermes_cli/subcommands/cron.py +163 -0
- package/agent/hermes_cli/subcommands/dashboard.py +143 -0
- package/agent/hermes_cli/subcommands/debug.py +77 -0
- package/agent/hermes_cli/subcommands/doctor.py +35 -0
- package/agent/hermes_cli/subcommands/dump.py +28 -0
- package/agent/hermes_cli/subcommands/gateway.py +332 -0
- package/agent/hermes_cli/subcommands/gui.py +63 -0
- package/agent/hermes_cli/subcommands/hooks.py +77 -0
- package/agent/hermes_cli/subcommands/import_cmd.py +31 -0
- package/agent/hermes_cli/subcommands/insights.py +25 -0
- package/agent/hermes_cli/subcommands/login.py +78 -0
- package/agent/hermes_cli/subcommands/logout.py +28 -0
- package/agent/hermes_cli/subcommands/logs.py +78 -0
- package/agent/hermes_cli/subcommands/mcp.py +108 -0
- package/agent/hermes_cli/subcommands/memory.py +53 -0
- package/agent/hermes_cli/subcommands/model.py +72 -0
- package/agent/hermes_cli/subcommands/pairing.py +36 -0
- package/agent/hermes_cli/subcommands/plugins.py +94 -0
- package/agent/hermes_cli/subcommands/postinstall.py +23 -0
- package/agent/hermes_cli/subcommands/profile.py +203 -0
- package/agent/hermes_cli/subcommands/prompt_size.py +36 -0
- package/agent/hermes_cli/subcommands/security.py +62 -0
- package/agent/hermes_cli/subcommands/setup.py +58 -0
- package/agent/hermes_cli/subcommands/skills.py +298 -0
- package/agent/hermes_cli/subcommands/slack.py +60 -0
- package/agent/hermes_cli/subcommands/status.py +28 -0
- package/agent/hermes_cli/subcommands/tools.py +95 -0
- package/agent/hermes_cli/subcommands/uninstall.py +41 -0
- package/agent/hermes_cli/subcommands/update.py +70 -0
- package/agent/hermes_cli/subcommands/version.py +18 -0
- package/agent/hermes_cli/subcommands/webhook.py +76 -0
- package/agent/hermes_cli/subcommands/whatsapp.py +22 -0
- package/agent/hermes_cli/suggestions_cmd.py +153 -0
- package/agent/hermes_cli/telegram_managed_bot.py +358 -0
- package/agent/hermes_cli/tips.py +3 -4
- package/agent/hermes_cli/tools_config.py +155 -28
- package/agent/hermes_cli/uninstall.py +231 -35
- package/agent/hermes_cli/web_server.py +6188 -975
- package/agent/hermes_cli/win_pty_bridge.py +179 -0
- package/agent/hermes_cli/write_approval_commands.py +209 -0
- package/agent/hermes_constants.py +164 -33
- package/agent/hermes_logging.py +74 -2
- package/agent/hermes_state.py +919 -106
- package/agent/hermes_time.py +20 -0
- package/agent/locales/af.yaml +23 -0
- package/agent/locales/de.yaml +23 -0
- package/agent/locales/en.yaml +20 -0
- package/agent/locales/es.yaml +23 -0
- package/agent/locales/fr.yaml +23 -0
- package/agent/locales/ga.yaml +23 -0
- package/agent/locales/hu.yaml +23 -0
- package/agent/locales/it.yaml +23 -0
- package/agent/locales/ja.yaml +23 -0
- package/agent/locales/ko.yaml +23 -0
- package/agent/locales/pt.yaml +23 -0
- package/agent/locales/ru.yaml +23 -0
- package/agent/locales/tr.yaml +23 -0
- package/agent/locales/uk.yaml +23 -0
- package/agent/locales/zh-hant.yaml +23 -0
- package/agent/locales/zh.yaml +23 -0
- package/agent/model_tools.py +204 -40
- package/agent/optional-mcps/clawpump/manifest.yaml +4 -2
- package/agent/optional-mcps/clawpump-stdio/manifest.yaml +2 -0
- package/agent/optional-mcps/unreal-engine/manifest.yaml +54 -0
- package/agent/optional-skills/blockchain/hyperliquid/SKILL.md +2 -2
- package/agent/optional-skills/blockchain/hyperliquid/scripts/hyperliquid_client.py +1 -1
- package/agent/optional-skills/creative/kanban-video-orchestrator/SKILL.md +1 -1
- package/agent/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl +4 -3
- package/agent/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md +6 -4
- package/agent/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md +2 -2
- package/agent/{skills/software-development → optional-skills/devops}/hermes-s6-container-supervision/SKILL.md +2 -0
- package/agent/optional-skills/devops/watchers/SKILL.md +1 -1
- package/agent/optional-skills/devops/watchers/scripts/watch_github.py +2 -1
- package/agent/optional-skills/payments/mpp-agent/SKILL.md +124 -0
- package/agent/optional-skills/payments/stripe-link-cli/SKILL.md +184 -0
- package/agent/optional-skills/payments/stripe-projects/SKILL.md +120 -0
- package/agent/optional-skills/productivity/canvas/SKILL.md +1 -1
- package/agent/optional-skills/productivity/canvas/scripts/canvas_api.py +4 -1
- package/agent/optional-skills/productivity/shop/SKILL.md +224 -0
- package/agent/optional-skills/productivity/shop/references/catalog-mcp.md +236 -0
- package/agent/optional-skills/productivity/shop/references/direct-api.md +278 -0
- package/agent/optional-skills/productivity/shop/references/legal.md +3 -0
- package/agent/optional-skills/productivity/shop/references/safety.md +36 -0
- package/agent/optional-skills/productivity/shopify/SKILL.md +1 -1
- package/agent/optional-skills/productivity/siyuan/SKILL.md +1 -1
- package/agent/optional-skills/productivity/telephony/SKILL.md +4 -4
- package/agent/optional-skills/productivity/telephony/scripts/telephony.py +15 -15
- package/agent/optional-skills/security/1password/SKILL.md +1 -1
- package/agent/{skills/red-teaming → optional-skills/security}/godmode/SKILL.md +3 -4
- package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/auto_jailbreak.py +3 -1
- package/agent/optional-skills/software-development/rest-graphql-debug/SKILL.md +1 -1
- package/agent/{skills → optional-skills}/software-development/subagent-driven-development/SKILL.md +5 -5
- package/agent/package-lock.json +4082 -7907
- package/agent/package.json +18 -3
- package/agent/plugins/browser/firecrawl/provider.py +4 -1
- package/agent/plugins/cron/__init__.py +344 -0
- package/agent/plugins/cron/chronos/__init__.py +241 -0
- package/agent/plugins/cron/chronos/_nas_client.py +123 -0
- package/agent/plugins/cron/chronos/plugin.yaml +9 -0
- package/agent/plugins/cron/chronos/verify.py +103 -0
- package/agent/plugins/dashboard_auth/basic/__init__.py +491 -0
- package/agent/plugins/dashboard_auth/basic/plugin.yaml +7 -0
- package/agent/plugins/dashboard_auth/nous/__init__.py +12 -14
- package/agent/plugins/dashboard_auth/self_hosted/__init__.py +736 -0
- package/agent/plugins/dashboard_auth/self_hosted/plugin.yaml +8 -0
- package/agent/plugins/disk-cleanup/disk_cleanup.py +100 -20
- package/agent/plugins/google_meet/audio_bridge.py +4 -0
- package/agent/plugins/google_meet/meet_bot.py +7 -1
- package/agent/plugins/hermes-achievements/dashboard/dist/index.js +9 -15
- package/agent/plugins/image_gen/fal/__init__.py +35 -6
- package/agent/plugins/image_gen/krea/__init__.py +56 -13
- package/agent/plugins/image_gen/openai/__init__.py +122 -24
- package/agent/plugins/image_gen/openai-codex/__init__.py +28 -2
- package/agent/plugins/image_gen/xai/__init__.py +92 -12
- package/agent/plugins/kanban/dashboard/dist/index.js +63 -48
- package/agent/plugins/kanban/dashboard/plugin_api.py +39 -35
- package/agent/plugins/memory/__init__.py +48 -5
- package/agent/plugins/memory/byterover/__init__.py +1 -0
- package/agent/plugins/memory/hindsight/README.md +1 -1
- package/agent/plugins/memory/hindsight/__init__.py +138 -24
- package/agent/plugins/memory/hindsight/plugin.yaml +1 -1
- package/agent/plugins/memory/honcho/README.md +13 -10
- package/agent/plugins/memory/honcho/cli.py +247 -122
- package/agent/plugins/memory/honcho/client.py +112 -102
- package/agent/plugins/memory/openviking/README.md +12 -1
- package/agent/plugins/memory/openviking/__init__.py +2281 -107
- package/agent/plugins/memory/openviking/plugin.yaml +1 -2
- package/agent/plugins/memory/supermemory/README.md +22 -10
- package/agent/plugins/memory/supermemory/__init__.py +142 -37
- package/agent/plugins/memory/supermemory/plugin.yaml +1 -1
- package/agent/plugins/model-providers/anthropic/__init__.py +1 -0
- package/agent/plugins/model-providers/bedrock/__init__.py +1 -0
- package/agent/plugins/model-providers/copilot-acp/__init__.py +1 -0
- package/agent/plugins/model-providers/custom/__init__.py +8 -2
- package/agent/plugins/model-providers/kimi-coding/__init__.py +16 -7
- package/agent/plugins/model-providers/minimax/__init__.py +60 -8
- package/agent/plugins/model-providers/opencode-zen/__init__.py +12 -3
- package/agent/plugins/model-providers/openrouter/__init__.py +75 -4
- package/agent/plugins/model-providers/xiaomi/__init__.py +2 -0
- package/agent/plugins/model-providers/zai/__init__.py +1 -0
- package/agent/plugins/observability/langfuse/__init__.py +147 -14
- package/agent/plugins/observability/nemo_relay/README.md +559 -0
- package/agent/plugins/observability/nemo_relay/__init__.py +962 -0
- package/agent/plugins/observability/nemo_relay/plugin.yaml +20 -0
- package/agent/plugins/platforms/discord/adapter.py +932 -61
- package/agent/plugins/platforms/discord/voice_mixer.py +379 -0
- package/agent/plugins/platforms/google_chat/adapter.py +9 -3
- package/agent/plugins/platforms/google_chat/oauth.py +1 -1
- package/agent/plugins/platforms/homeassistant/__init__.py +3 -0
- package/agent/{gateway/platforms/homeassistant.py → plugins/platforms/homeassistant/adapter.py} +128 -0
- package/agent/plugins/platforms/homeassistant/plugin.yaml +22 -0
- package/agent/plugins/platforms/irc/adapter.py +4 -1
- package/agent/plugins/platforms/line/adapter.py +16 -1
- package/agent/plugins/platforms/mattermost/adapter.py +100 -24
- package/agent/plugins/platforms/photon/README.md +179 -0
- package/agent/plugins/platforms/photon/__init__.py +4 -0
- package/agent/plugins/platforms/photon/adapter.py +1586 -0
- package/agent/plugins/platforms/photon/auth.py +1046 -0
- package/agent/plugins/platforms/photon/cli.py +439 -0
- package/agent/plugins/platforms/photon/plugin.yaml +88 -0
- package/agent/plugins/platforms/photon/sidecar/README.md +52 -0
- package/agent/plugins/platforms/photon/sidecar/index.mjs +720 -0
- package/agent/plugins/platforms/photon/sidecar/package-lock.json +1730 -0
- package/agent/plugins/platforms/photon/sidecar/package.json +25 -0
- package/agent/plugins/platforms/photon/sidecar/patch-spectrum-mixed-attachments.mjs +155 -0
- package/agent/plugins/platforms/raft/__init__.py +3 -0
- package/agent/plugins/platforms/raft/adapter.py +774 -0
- package/agent/plugins/platforms/raft/plugin.yaml +19 -0
- package/agent/plugins/platforms/simplex/adapter.py +777 -220
- package/agent/plugins/platforms/simplex/plugin.yaml +21 -2
- package/agent/plugins/platforms/teams/adapter.py +175 -5
- package/agent/plugins/plugin_utils.py +135 -0
- package/agent/plugins/video_gen/fal/__init__.py +10 -3
- package/agent/plugins/web/searxng/provider.py +15 -2
- package/agent/plugins/web/xai/provider.py +2 -2
- package/agent/providers/base.py +22 -3
- package/agent/pyproject.toml +115 -21
- package/agent/run_agent.py +733 -39
- package/agent/scripts/build_skills_index.py +51 -19
- package/agent/scripts/check_subprocess_stdin.py +177 -0
- package/agent/scripts/contributor_audit.py +2 -0
- package/agent/scripts/docker_config_migrate.py +67 -0
- package/agent/scripts/install.cmd +3 -3
- package/agent/scripts/install.ps1 +580 -154
- package/agent/scripts/install.sh +402 -185
- package/agent/scripts/lib/node-bootstrap.sh +39 -4
- package/agent/scripts/release.py +183 -0
- package/agent/scripts/run_tests.sh +1 -0
- package/agent/scripts/run_tests_parallel.py +18 -23
- package/agent/scripts/whatsapp-bridge/bridge.js +25 -4
- package/agent/setup.py +59 -0
- package/agent/skills/autonomous-ai-agents/codex/SKILL.md +19 -0
- package/agent/skills/autonomous-ai-agents/hermes-agent/SKILL.md +10 -3
- package/agent/skills/{mcp/native-mcp/SKILL.md → autonomous-ai-agents/hermes-agent/references/native-mcp.md} +0 -13
- package/agent/skills/{devops/webhook-subscriptions/SKILL.md → autonomous-ai-agents/hermes-agent/references/webhooks.md} +1 -11
- package/agent/skills/clawpump/SKILL.md +3 -1
- package/agent/skills/devops/kanban-orchestrator/SKILL.md +1 -0
- package/agent/skills/devops/kanban-worker/SKILL.md +1 -0
- package/agent/skills/github/github-auth/SKILL.md +2 -2
- package/agent/skills/github/github-auth/scripts/gh-env.sh +2 -2
- package/agent/skills/github/github-code-review/SKILL.md +2 -2
- package/agent/skills/github/github-issues/SKILL.md +2 -2
- package/agent/skills/github/github-pr-workflow/SKILL.md +2 -2
- package/agent/skills/github/github-repo-management/SKILL.md +2 -2
- package/agent/skills/media/gif-search/SKILL.md +1 -1
- package/agent/skills/media/youtube-content/SKILL.md +10 -7
- package/agent/skills/media/youtube-content/scripts/fetch_transcript.py +3 -3
- package/agent/skills/note-taking/obsidian/SKILL.md +1 -1
- package/agent/skills/productivity/airtable/SKILL.md +2 -2
- package/agent/skills/productivity/google-workspace/scripts/setup.py +33 -7
- package/agent/skills/productivity/notion/SKILL.md +2 -2
- package/agent/skills/productivity/teams-meeting-pipeline/SKILL.md +1 -1
- package/agent/skills/research/llm-wiki/SKILL.md +1 -1
- package/agent/skills/social-media/xurl/SKILL.md +9 -0
- package/agent/skills/software-development/hermes-agent-skill-authoring/SKILL.md +1 -1
- package/agent/skills/software-development/plan/SKILL.md +285 -5
- package/agent/skills/software-development/requesting-code-review/SKILL.md +2 -2
- package/agent/skills/software-development/simplify-code/SKILL.md +212 -0
- package/agent/skills/software-development/spike/SKILL.md +2 -2
- package/agent/skills/software-development/systematic-debugging/SKILL.md +1 -1
- package/agent/skills/software-development/test-driven-development/SKILL.md +1 -1
- package/agent/tools/approval.py +302 -4
- package/agent/tools/async_delegation.py +386 -0
- package/agent/tools/blueprints.py +325 -0
- package/agent/tools/browser_cdp_tool.py +3 -3
- package/agent/tools/browser_tool.py +34 -6
- package/agent/tools/checkpoint_manager.py +31 -1
- package/agent/tools/clarify_tool.py +55 -5
- package/agent/tools/code_execution_tool.py +31 -14
- package/agent/tools/computer_use/cua_backend.py +81 -3
- package/agent/tools/computer_use/tool.py +79 -5
- package/agent/tools/computer_use/vision_routing.py +55 -3
- package/agent/tools/credential_files.py +31 -12
- package/agent/tools/cronjob_tools.py +30 -20
- package/agent/tools/delegate_tool.py +356 -31
- package/agent/tools/env_probe.py +1 -0
- package/agent/tools/environments/docker.py +163 -8
- package/agent/tools/environments/file_sync.py +2 -1
- package/agent/tools/environments/local.py +74 -23
- package/agent/tools/environments/singularity.py +4 -1
- package/agent/tools/environments/ssh.py +78 -11
- package/agent/tools/file_operations.py +277 -41
- package/agent/tools/file_tools.py +166 -28
- package/agent/tools/image_generation_tool.py +515 -29
- package/agent/tools/kanban_tools.py +99 -0
- package/agent/tools/lazy_deps.py +33 -2
- package/agent/tools/mcp_oauth.py +5 -5
- package/agent/tools/mcp_oauth_manager.py +7 -5
- package/agent/tools/mcp_tool.py +840 -33
- package/agent/tools/memory_tool.py +335 -38
- package/agent/tools/osv_check.py +15 -1
- package/agent/tools/process_registry.py +155 -11
- package/agent/tools/read_extract.py +248 -0
- package/agent/tools/read_terminal_tool.py +93 -0
- package/agent/tools/schema_sanitizer.py +38 -0
- package/agent/tools/send_message_tool.py +163 -49
- package/agent/tools/session_search_tool.py +189 -7
- package/agent/tools/skill_manager_tool.py +202 -3
- package/agent/tools/skill_usage.py +52 -4
- package/agent/tools/skills_hub.py +184 -44
- package/agent/tools/skills_sync.py +232 -5
- package/agent/tools/skills_tool.py +125 -11
- package/agent/tools/terminal_tool.py +148 -26
- package/agent/tools/tirith_security.py +2 -0
- package/agent/tools/todo_tool.py +32 -1
- package/agent/tools/transcription_tools.py +13 -5
- package/agent/tools/tts_tool.py +332 -38
- package/agent/tools/url_safety.py +52 -1
- package/agent/tools/vision_tools.py +124 -39
- package/agent/tools/voice_mode.py +4 -3
- package/agent/tools/web_tools.py +45 -15
- package/agent/tools/write_approval.py +493 -0
- package/agent/toolsets.py +34 -10
- package/agent/trajectory_compressor.py +81 -10
- package/agent/tui_gateway/entry.py +43 -6
- package/agent/tui_gateway/server.py +3335 -330
- package/agent/tui_gateway/slash_worker.py +61 -0
- package/agent/tui_gateway/ws.py +67 -9
- package/agent/ui-tui/eslint.config.mjs +0 -4
- package/agent/ui-tui/package.json +6 -6
- package/agent/ui-tui/packages/hermes-ink/package.json +1 -1
- package/agent/ui-tui/packages/hermes-ink/src/ink/app-mouse.test.ts +34 -1
- package/agent/ui-tui/packages/hermes-ink/src/ink/app-rawmode-mouse.test.ts +91 -0
- package/agent/ui-tui/packages/hermes-ink/src/ink/components/App.tsx +35 -2
- package/agent/ui-tui/packages/hermes-ink/src/ink/events/input-event.ts +4 -11
- package/agent/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts +23 -57
- package/agent/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts +11 -135
- package/agent/ui-tui/packages/hermes-ink/src/ink/termio/tokenize.test.ts +185 -0
- package/agent/ui-tui/packages/hermes-ink/src/ink/termio/tokenize.ts +37 -3
- package/agent/ui-tui/packages/hermes-ink/src/utils/execFileNoThrow.ts +5 -5
- package/agent/ui-tui/src/__tests__/appChromeStatusRule.test.tsx +217 -0
- package/agent/ui-tui/src/__tests__/appChromeStatusRuleDevCredits.test.tsx +73 -0
- package/agent/ui-tui/src/__tests__/approvalAction.test.ts +11 -0
- package/agent/ui-tui/src/__tests__/billingCommand.test.ts +301 -0
- package/agent/ui-tui/src/__tests__/blockLayout.test.ts +122 -0
- package/agent/ui-tui/src/__tests__/brandingMcpCount.test.ts +111 -0
- package/agent/ui-tui/src/__tests__/completionApply.test.ts +51 -0
- package/agent/ui-tui/src/__tests__/createGatewayEventHandler.test.ts +487 -2
- package/agent/ui-tui/src/__tests__/createSlashHandler.test.ts +54 -0
- package/agent/ui-tui/src/__tests__/creditsCommand.test.ts +144 -0
- package/agent/ui-tui/src/__tests__/gatewayClient.test.ts +120 -99
- package/agent/ui-tui/src/__tests__/gracefulExit.test.ts +11 -0
- package/agent/ui-tui/src/__tests__/memoryMonitor.test.ts +102 -0
- package/agent/ui-tui/src/__tests__/paths.test.ts +41 -1
- package/agent/ui-tui/src/__tests__/terminalModes.test.ts +22 -0
- package/agent/ui-tui/src/__tests__/text.test.ts +23 -0
- package/agent/ui-tui/src/__tests__/textInputFastEcho.test.ts +37 -0
- package/agent/ui-tui/src/__tests__/turnControllerNotice.test.ts +43 -0
- package/agent/ui-tui/src/__tests__/useInputHandlers.test.ts +38 -1
- package/agent/ui-tui/src/__tests__/virtualHeights.test.ts +8 -0
- package/agent/ui-tui/src/app/createGatewayEventHandler.ts +102 -7
- package/agent/ui-tui/src/app/interfaces.ts +64 -1
- package/agent/ui-tui/src/app/overlayStore.ts +18 -2
- package/agent/ui-tui/src/app/slash/commands/billing.ts +332 -0
- package/agent/ui-tui/src/app/slash/commands/core.ts +31 -2
- package/agent/ui-tui/src/app/slash/commands/credits.ts +57 -0
- package/agent/ui-tui/src/app/slash/commands/ops.ts +28 -0
- package/agent/ui-tui/src/app/slash/commands/session.ts +32 -4
- package/agent/ui-tui/src/app/slash/registry.ts +4 -0
- package/agent/ui-tui/src/app/turnController.ts +145 -2
- package/agent/ui-tui/src/app/uiStore.ts +2 -0
- package/agent/ui-tui/src/app/useInputHandlers.ts +42 -4
- package/agent/ui-tui/src/app/useMainApp.ts +54 -8
- package/agent/ui-tui/src/app/useSessionLifecycle.ts +40 -31
- package/agent/ui-tui/src/app/useSubmission.ts +23 -31
- package/agent/ui-tui/src/components/appChrome.tsx +112 -5
- package/agent/ui-tui/src/components/appLayout.tsx +9 -0
- package/agent/ui-tui/src/components/appOverlays.tsx +25 -1
- package/agent/ui-tui/src/components/billingOverlay.tsx +684 -0
- package/agent/ui-tui/src/components/branding.tsx +15 -3
- package/agent/ui-tui/src/components/messageLine.tsx +25 -3
- package/agent/ui-tui/src/components/pluginsHub.tsx +238 -0
- package/agent/ui-tui/src/components/prompts.tsx +31 -17
- package/agent/ui-tui/src/components/streamingAssistant.tsx +63 -55
- package/agent/ui-tui/src/components/textInput.tsx +16 -0
- package/agent/ui-tui/src/config/env.ts +12 -0
- package/agent/ui-tui/src/config/limits.ts +13 -0
- package/agent/ui-tui/src/domain/blockLayout.ts +146 -0
- package/agent/ui-tui/src/domain/paths.ts +24 -0
- package/agent/ui-tui/src/domain/slash.ts +40 -0
- package/agent/ui-tui/src/entry.tsx +35 -4
- package/agent/ui-tui/src/gatewayClient.ts +22 -10
- package/agent/ui-tui/src/gatewayTypes.ts +130 -1
- package/agent/ui-tui/src/lib/gracefulExit.ts +24 -4
- package/agent/ui-tui/src/lib/memory.test.ts +162 -0
- package/agent/ui-tui/src/lib/memory.ts +60 -1
- package/agent/ui-tui/src/lib/memoryMonitor.ts +79 -4
- package/agent/ui-tui/src/lib/osc52.ts +1 -1
- package/agent/ui-tui/src/lib/text.test.ts +32 -1
- package/agent/ui-tui/src/lib/text.ts +29 -2
- package/agent/ui-tui/src/lib/virtualHeights.ts +13 -0
- package/agent/ui-tui/src/types.ts +5 -0
- package/agent/ui-tui/tsconfig.build.json +0 -1
- package/agent/ui-tui/tsconfig.json +2 -1
- package/agent/utils.py +66 -2
- package/agent/uv.lock +300 -684
- package/agent/web/index.html +2 -2
- package/agent/web/package.json +11 -6
- package/agent/web/public/claw-bg.webp +0 -0
- package/agent/web/public/claw-logo.webp +0 -0
- package/agent/web/src/App.tsx +138 -48
- package/agent/web/src/components/AutomationBlueprints.tsx +225 -0
- package/agent/web/src/components/Backdrop.tsx +15 -0
- package/agent/web/src/components/ChatSessionList.tsx +260 -0
- package/agent/web/src/components/ChatSidebar.tsx +262 -78
- package/agent/web/src/components/ConfirmDialog.tsx +122 -0
- package/agent/web/src/components/ModelPickerDialog.tsx +111 -16
- package/agent/web/src/components/ModelReloadConfirm.tsx +40 -0
- package/agent/web/src/components/ProfileScopeBanner.tsx +30 -0
- package/agent/web/src/components/ProfileSwitcher.tsx +67 -0
- package/agent/web/src/components/ReasoningPicker.tsx +167 -0
- package/agent/web/src/components/SkillEditorDialog.tsx +215 -0
- package/agent/web/src/components/ThemeSwitcher.tsx +119 -4
- package/agent/web/src/components/ToolsetConfigDrawer.tsx +457 -0
- package/agent/web/src/contexts/PageHeaderProvider.tsx +7 -4
- package/agent/web/src/contexts/ProfileProvider.tsx +137 -0
- package/agent/web/src/contexts/SystemActions.tsx +6 -8
- package/agent/web/src/contexts/profile-context.ts +19 -0
- package/agent/web/src/contexts/useProfileScope.ts +6 -0
- package/agent/web/src/i18n/af.ts +5 -4
- package/agent/web/src/i18n/de.ts +5 -4
- package/agent/web/src/i18n/en.ts +58 -4
- package/agent/web/src/i18n/es.ts +5 -3
- package/agent/web/src/i18n/fr.ts +5 -3
- package/agent/web/src/i18n/ga.ts +5 -4
- package/agent/web/src/i18n/hu.ts +5 -4
- package/agent/web/src/i18n/it.ts +5 -4
- package/agent/web/src/i18n/ja.ts +5 -4
- package/agent/web/src/i18n/ko.ts +5 -4
- package/agent/web/src/i18n/pt.ts +5 -3
- package/agent/web/src/i18n/ru.ts +5 -4
- package/agent/web/src/i18n/tr.ts +5 -4
- package/agent/web/src/i18n/types.ts +59 -1
- package/agent/web/src/i18n/uk.ts +5 -3
- package/agent/web/src/i18n/zh-hant.ts +5 -4
- package/agent/web/src/i18n/zh.ts +5 -4
- package/agent/web/src/index.css +2 -2
- package/agent/web/src/lib/api.ts +819 -52
- package/agent/web/src/lib/dashboard-flags.ts +16 -7
- package/agent/web/src/lib/reasoning-effort.test.ts +48 -0
- package/agent/web/src/lib/reasoning-effort.ts +36 -0
- package/agent/web/src/lib/session-refresh.test.ts +21 -0
- package/agent/web/src/lib/session-refresh.ts +26 -0
- package/agent/web/src/pages/ChannelsPage.tsx +529 -68
- package/agent/web/src/pages/ChatPage.tsx +249 -56
- package/agent/web/src/pages/ConfigPage.tsx +11 -1
- package/agent/web/src/pages/CronPage.tsx +219 -31
- package/agent/web/src/pages/EnvPage.tsx +25 -6
- package/agent/web/src/pages/FilesPage.tsx +525 -0
- package/agent/web/src/pages/McpPage.tsx +80 -3
- package/agent/web/src/pages/ModelsPage.tsx +97 -12
- package/agent/web/src/pages/PluginsPage.tsx +1 -1
- package/agent/web/src/pages/ProfileBuilderPage.tsx +611 -0
- package/agent/web/src/pages/ProfilesPage.tsx +1038 -172
- package/agent/web/src/pages/SessionsPage.tsx +144 -13
- package/agent/web/src/pages/SkillsPage.tsx +851 -70
- package/agent/web/src/pages/SystemPage.tsx +340 -4
- package/agent/web/src/pages/WalletPage.tsx +401 -0
- package/agent/web/src/pages/WebhooksPage.tsx +145 -15
- package/agent/web/src/pages/X402Page.tsx +207 -0
- package/agent/web/src/plugins/registry.ts +28 -11
- package/agent/web/src/plugins/sdk.d.ts +160 -0
- package/agent/web/src/themes/context.tsx +112 -5
- package/agent/web/src/themes/fonts.ts +167 -0
- package/agent/web/src/themes/index.ts +7 -0
- package/agent/web/tsconfig.app.json +0 -1
- package/agent/web/vite.config.ts +1 -8
- package/agent/web/vitest.config.ts +16 -0
- package/package.json +1 -1
- package/agent/apps/desktop/package-lock.json +0 -18363
- package/agent/apps/desktop/src/app/chat/composer/skin-slash-popover.tsx +0 -56
- package/agent/apps/desktop/src/components/assistant-ui/thread-virtualizer.tsx +0 -382
- package/agent/apps/desktop/src/components/assistant-ui/todo-tool.tsx +0 -109
- package/agent/apps/desktop/src/components/chat/generated-image-context.tsx +0 -19
- package/agent/optional-skills/productivity/shop-app/SKILL.md +0 -340
- package/agent/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +0 -277
- package/agent/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +0 -57
- package/agent/skills/diagramming/DESCRIPTION.md +0 -3
- package/agent/skills/domain/DESCRIPTION.md +0 -24
- package/agent/skills/gifs/DESCRIPTION.md +0 -3
- package/agent/skills/inference-sh/DESCRIPTION.md +0 -19
- package/agent/skills/mcp/DESCRIPTION.md +0 -3
- package/agent/skills/media/spotify/SKILL.md +0 -135
- package/agent/skills/mlops/training/DESCRIPTION.md +0 -3
- package/agent/skills/mlops/vector-databases/DESCRIPTION.md +0 -3
- package/agent/skills/productivity/linear/SKILL.md +0 -380
- package/agent/skills/productivity/linear/scripts/linear_api.py +0 -445
- package/agent/skills/software-development/debugging-hermes-tui-commands/SKILL.md +0 -152
- package/agent/skills/software-development/writing-plans/SKILL.md +0 -297
- package/agent/ui-tui/package-lock.json +0 -7449
- package/agent/ui-tui/packages/hermes-ink/package-lock.json +0 -1289
- package/agent/web/package-lock.json +0 -8887
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/PORT_NOTES.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/prompts/system.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/macaron.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/mono-ink.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/neon.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/warm.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/prompt-construction.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/style-presets.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/blueprint.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/chalkboard.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/editorial.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/elegant.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/fantasy-animation.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/flat-doodle.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/flat.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/ink-notes.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/intuition-machine.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/minimal.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/nature.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/notion.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/pixel-art.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/playful.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/retro.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/scientific.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/screen-print.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/sketch-notes.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/sketch.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/vector-illustration.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/vintage.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/warm.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/watercolor.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/usage.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/workflow.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/PORT_NOTES.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/analysis-framework.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/chalk.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/ink-brush.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/ligne-claire.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/manga.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/minimalist.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/realistic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/auto-selection.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/base-prompt.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/character-template.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/cinematic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/dense.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/four-panel.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/mixed.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/splash.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/standard.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/webtoon.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/ohmsha-guide.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/partial-workflows.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/concept-story.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/four-panel.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/ohmsha.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/shoujo.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/wuxia.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/storyboard-template.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/action.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/dramatic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/energetic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/neutral.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/romantic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/vintage.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/warm.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/workflow.md +0 -0
- /package/agent/{skills → optional-skills}/creative/creative-ideation/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/creative-ideation/references/full-prompt-library.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/ATTRIBUTION.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/references/palettes.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/__init__.py +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/palettes.py +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/pixel_art.py +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/pixel_art_video.py +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/SKILL.md +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/references/analysis-modules.md +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/references/methods-guide.md +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/abliteration-config.yaml +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/analysis-study.yaml +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/batch-abliteration.yaml +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/DESCRIPTION.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/references/examples.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/references/modules.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/references/optimizers.md +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/references/jailbreak-templates.md +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/references/refusal-detection.md +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/godmode_race.py +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/load_godmode.py +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/parseltongue.py +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/templates/prefill-subtle.json +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/templates/prefill.json +0 -0
- /package/agent/{skills → optional-skills}/software-development/subagent-driven-development/references/context-budget-discipline.md +0 -0
- /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
|
-
|
|
293
|
-
|
|
294
|
-
#
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
-
|
|
303
|
-
$
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
|
360
|
-
Write-Info "
|
|
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
|
|
389
|
-
# Throws if uv is not findable
|
|
390
|
-
# clean error via the stage-driver's try/catch.
|
|
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
|
-
#
|
|
408
|
-
|
|
409
|
-
|
|
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
|
-
|
|
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
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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
|
-
#
|
|
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 "
|
|
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: $
|
|
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
|
|
963
|
-
#
|
|
964
|
-
#
|
|
965
|
-
|
|
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.
|
|
1055
|
-
# belt-and-braces: rev-parse
|
|
1056
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
1116
|
-
#
|
|
1117
|
-
# a partial uninstall used to lock the
|
|
1118
|
-
# "update" branch forever
|
|
1119
|
-
#
|
|
1120
|
-
|
|
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
|
-
|
|
1328
|
+
Move-Item -LiteralPath $InstallDir -Destination $backupDir -ErrorAction Stop
|
|
1123
1329
|
} catch {
|
|
1124
|
-
Write-Err "Could not
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
1876
|
+
Write-Success "Created $envPath"
|
|
1629
1877
|
}
|
|
1630
1878
|
} else {
|
|
1631
|
-
Write-Info "
|
|
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
|
|
1888
|
+
Write-Success "Created $configPath from template"
|
|
1641
1889
|
}
|
|
1642
1890
|
} else {
|
|
1643
|
-
Write-Info "
|
|
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
|
|
1924
|
+
Write-Success "Created $soulPath (edit to customize personality)"
|
|
1677
1925
|
}
|
|
1678
1926
|
|
|
1679
|
-
Write-Success "Configuration directory ready:
|
|
1927
|
+
Write-Success "Configuration directory ready: $HermesHome"
|
|
1680
1928
|
|
|
1681
|
-
# Seed bundled skills into
|
|
1682
|
-
Write-Info "Syncing bundled skills to
|
|
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
|
|
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
|
|
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
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|