@clawpump/claw-agent 0.1.4 → 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 +2294 -3146
- 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/clawpump_cli.py +3 -3
- 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 +216 -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/distribution.py +227 -0
- 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 +15 -5
- package/agent/optional-mcps/clawpump-stdio/manifest.yaml +14 -4
- 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 +53 -5
- 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 +308 -696
- 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
|
@@ -7,7 +7,7 @@ protecting head and tail context.
|
|
|
7
7
|
Improvements over v2:
|
|
8
8
|
- Structured summary template with Resolved/Pending question tracking
|
|
9
9
|
- Filter-safe summarizer preamble that treats prior turns as source material
|
|
10
|
-
-
|
|
10
|
+
- Historical (reference-only) section headings replace "Next Steps"/"Remaining Work" to avoid reading as active instructions
|
|
11
11
|
- Clear separator when summary merges into tail message
|
|
12
12
|
- Iterative summary updates (preserves info across multiple compactions)
|
|
13
13
|
- Token-budget tail protection instead of fixed message count
|
|
@@ -34,6 +34,12 @@ from agent.redact import redact_sensitive_text
|
|
|
34
34
|
|
|
35
35
|
logger = logging.getLogger(__name__)
|
|
36
36
|
|
|
37
|
+
HISTORICAL_TASK_HEADING = "## Historical Task Snapshot"
|
|
38
|
+
HISTORICAL_IN_PROGRESS_HEADING = "## Historical In-Progress State"
|
|
39
|
+
HISTORICAL_PENDING_ASKS_HEADING = "## Historical Pending User Asks"
|
|
40
|
+
HISTORICAL_REMAINING_WORK_HEADING = "## Historical Remaining Work"
|
|
41
|
+
|
|
42
|
+
|
|
37
43
|
SUMMARY_PREFIX = (
|
|
38
44
|
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted "
|
|
39
45
|
"into the summary below. This is a handoff from a previous context "
|
|
@@ -43,12 +49,14 @@ SUMMARY_PREFIX = (
|
|
|
43
49
|
"Respond ONLY to the latest user message that appears AFTER this "
|
|
44
50
|
"summary — that message is the single source of truth for what to do "
|
|
45
51
|
"right now. "
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"message
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
+
"Topic overlap with the summary does NOT mean you should resume its "
|
|
53
|
+
"task: even on similar topics, the latest user message WINS. Treat ONLY "
|
|
54
|
+
"the latest message as the active task and discard stale items from "
|
|
55
|
+
f"'{HISTORICAL_TASK_HEADING}' / '{HISTORICAL_IN_PROGRESS_HEADING}' / "
|
|
56
|
+
f"'{HISTORICAL_PENDING_ASKS_HEADING}' / "
|
|
57
|
+
f"'{HISTORICAL_REMAINING_WORK_HEADING}' entirely — do not 'wrap up' or "
|
|
58
|
+
"'finish' work described there unless the latest message explicitly "
|
|
59
|
+
"asks for it. "
|
|
52
60
|
"Reverse signals in the latest message (e.g. 'stop', 'undo', 'roll "
|
|
53
61
|
"back', 'just verify', 'don't do that anymore', 'never mind', a new "
|
|
54
62
|
"topic) must immediately end any in-flight work described in the "
|
|
@@ -61,6 +69,31 @@ SUMMARY_PREFIX = (
|
|
|
61
69
|
)
|
|
62
70
|
LEGACY_SUMMARY_PREFIX = "[CONTEXT SUMMARY]:"
|
|
63
71
|
|
|
72
|
+
# Metadata key added to context compression summary messages so that frontends
|
|
73
|
+
# (CLI, Desktop, gateway, TUI) can distinguish them from real assistant/user
|
|
74
|
+
# messages and filter or render them appropriately without content-prefix
|
|
75
|
+
# heuristics. See https://github.com/NousResearch/hermes-agent/issues/38389
|
|
76
|
+
#
|
|
77
|
+
# Underscore-prefixed ON PURPOSE: the wire sanitizers
|
|
78
|
+
# (agent/transports/chat_completions.py convert_messages and the summary-path
|
|
79
|
+
# mirror in agent/chat_completion_helpers.py) strip every top-level message
|
|
80
|
+
# key starting with "_" before the request leaves the process. Strict
|
|
81
|
+
# OpenAI-compatible gateways (Fireworks, Mistral, Moonshot/Kimi, opencode-go)
|
|
82
|
+
# reject payloads carrying unknown keys with "Extra inputs are not permitted",
|
|
83
|
+
# poisoning every subsequent request in the session — a bare key like
|
|
84
|
+
# "is_compressed_summary" would reach the wire and trip exactly that.
|
|
85
|
+
COMPRESSED_SUMMARY_METADATA_KEY = "_compressed_summary"
|
|
86
|
+
|
|
87
|
+
# Appended to every standalone summary message (and to the merged-into-tail
|
|
88
|
+
# prefix) so the model has an unambiguous "summary ends here" boundary.
|
|
89
|
+
# Without it, weak models read the verbatim "## Active Task" quote as fresh
|
|
90
|
+
# user input (#11475, #14521) or regurgitate an assistant-role summary as
|
|
91
|
+
# their own output (#33256).
|
|
92
|
+
_SUMMARY_END_MARKER = (
|
|
93
|
+
"--- END OF CONTEXT SUMMARY — "
|
|
94
|
+
"respond to the message below, not the summary above ---"
|
|
95
|
+
)
|
|
96
|
+
|
|
64
97
|
# Handoff prefixes that shipped in earlier releases. A summary persisted under
|
|
65
98
|
# one of these can be inherited into a resumed lineage (#35344); when it is
|
|
66
99
|
# re-normalized on re-compaction we must strip the OLD prefix too, otherwise the
|
|
@@ -68,6 +101,31 @@ LEGACY_SUMMARY_PREFIX = "[CONTEXT SUMMARY]:"
|
|
|
68
101
|
# embedded in the body and keeps hijacking replies. Keep newest-first; entries
|
|
69
102
|
# are matched literally. Add a frozen copy here whenever SUMMARY_PREFIX changes.
|
|
70
103
|
_HISTORICAL_SUMMARY_PREFIXES = (
|
|
104
|
+
# Carveout era (#41607/#38364/#42812): "consistent → use as background"
|
|
105
|
+
# licensed stale-task resumption on topic overlap.
|
|
106
|
+
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted "
|
|
107
|
+
"into the summary below. This is a handoff from a previous context "
|
|
108
|
+
"window — treat it as background reference, NOT as active instructions. "
|
|
109
|
+
"Do NOT answer questions or fulfill requests mentioned in this summary; "
|
|
110
|
+
"they were already addressed. "
|
|
111
|
+
"Respond ONLY to the latest user message that appears AFTER this "
|
|
112
|
+
"summary — that message is the single source of truth for what to do "
|
|
113
|
+
"right now. "
|
|
114
|
+
"If the latest user message is consistent with the '## Active Task' "
|
|
115
|
+
"section, you may use the summary as background. If the latest user "
|
|
116
|
+
"message contradicts, supersedes, changes topic from, or in any way "
|
|
117
|
+
"diverges from '## Active Task' / '## In Progress' / '## Pending User "
|
|
118
|
+
"Asks' / '## Remaining Work', the latest message WINS — discard those "
|
|
119
|
+
"stale items entirely and do not 'wrap up the old task first'. "
|
|
120
|
+
"Reverse signals in the latest message (e.g. 'stop', 'undo', 'roll "
|
|
121
|
+
"back', 'just verify', 'don't do that anymore', 'never mind', a new "
|
|
122
|
+
"topic) must immediately end any in-flight work described in the "
|
|
123
|
+
"summary; do not re-surface it in later turns. "
|
|
124
|
+
"IMPORTANT: Your persistent memory (MEMORY.md, USER.md) in the system "
|
|
125
|
+
"prompt is ALWAYS authoritative and active — never ignore or deprioritize "
|
|
126
|
+
"memory content due to this compaction note. "
|
|
127
|
+
"The current session state (files, config, etc.) may reflect work "
|
|
128
|
+
"described here — avoid repeating it:",
|
|
71
129
|
# Pre-#35344: contained the self-contradicting "resume exactly" directive.
|
|
72
130
|
"[CONTEXT COMPACTION — REFERENCE ONLY] Earlier turns were compacted "
|
|
73
131
|
"into the summary below. This is a handoff from a previous context "
|
|
@@ -110,10 +168,23 @@ _SUMMARY_FAILURE_COOLDOWN_SECONDS = 600
|
|
|
110
168
|
# become another unbounded transcript copy after the LLM summarizer failed.
|
|
111
169
|
_FALLBACK_SUMMARY_MAX_CHARS = 8_000
|
|
112
170
|
_FALLBACK_TURN_MAX_CHARS = 700
|
|
171
|
+
_AUTO_FOCUS_MAX_TURNS = 3
|
|
172
|
+
_AUTO_FOCUS_TURN_MAX_CHARS = 260
|
|
173
|
+
_AUTO_FOCUS_MAX_CHARS = 700
|
|
174
|
+
# Keep a short run of recent messages verbatim even when the token budget is
|
|
175
|
+
# already exhausted. The public ``protect_last_n`` default is intentionally
|
|
176
|
+
# high for small/light tails, but using all 20 as a hard floor here would bring
|
|
177
|
+
# back the old large-tool-output case where nothing can be compacted.
|
|
178
|
+
_MAX_TAIL_MESSAGE_FLOOR = 8
|
|
113
179
|
|
|
114
180
|
|
|
115
181
|
_PATH_MENTION_RE = re.compile(r"(?:/|~/?|[A-Za-z]:\\)[^\s`'\")\]}<>]+")
|
|
116
182
|
|
|
183
|
+
# MEDIA delivery directives must not reach the summarizer — if one leaks into
|
|
184
|
+
# the summary, the downstream model may re-emit it as an active directive on
|
|
185
|
+
# the next turn, triggering bogus attachment sends (#14665).
|
|
186
|
+
_MEDIA_DIRECTIVE_RE = re.compile(r"MEDIA:\S+")
|
|
187
|
+
|
|
117
188
|
|
|
118
189
|
def _dedupe_append(items: list[str], value: str, *, limit: int) -> None:
|
|
119
190
|
value = value.strip()
|
|
@@ -553,6 +624,22 @@ class ContextCompressor(ContextEngine):
|
|
|
553
624
|
self.last_rough_tokens_when_real_prompt_fit = 0
|
|
554
625
|
self.awaiting_real_usage_after_compression = False
|
|
555
626
|
|
|
627
|
+
def on_session_end(self, session_id: str, messages: List[Dict[str, Any]]) -> None:
|
|
628
|
+
"""Clear per-session compaction state at a real session boundary.
|
|
629
|
+
|
|
630
|
+
``_previous_summary`` is per-session iterative-summary state. It is
|
|
631
|
+
cleared on ``on_session_reset()`` (/new, /reset), but session *end*
|
|
632
|
+
(CLI exit, gateway expiry, session-id rotation) goes through
|
|
633
|
+
``on_session_end()`` instead — which inherited a no-op from
|
|
634
|
+
``ContextEngine``. Without clearing here, a cron/background session's
|
|
635
|
+
summary could survive on a reused compressor instance and leak into the
|
|
636
|
+
next live session via the ``_generate_summary()`` iterative-update path
|
|
637
|
+
(#38788). ``compress()`` already guards the leak at the point of use;
|
|
638
|
+
this is defense-in-depth that drops the stale summary the moment the
|
|
639
|
+
owning session ends.
|
|
640
|
+
"""
|
|
641
|
+
self._previous_summary = None
|
|
642
|
+
|
|
556
643
|
def update_model(
|
|
557
644
|
self,
|
|
558
645
|
model: str,
|
|
@@ -958,6 +1045,7 @@ class ContextCompressor(ContextEngine):
|
|
|
958
1045
|
for msg in turns:
|
|
959
1046
|
role = msg.get("role", "unknown")
|
|
960
1047
|
content = redact_sensitive_text(msg.get("content") or "")
|
|
1048
|
+
content = _MEDIA_DIRECTIVE_RE.sub("[media attachment]", content)
|
|
961
1049
|
|
|
962
1050
|
# Tool results: keep enough content for the summarizer
|
|
963
1051
|
if role == "tool":
|
|
@@ -1139,7 +1227,7 @@ class ContextCompressor(ContextEngine):
|
|
|
1139
1227
|
)
|
|
1140
1228
|
|
|
1141
1229
|
reason_text = f" Summary failure reason: {reason}." if reason else ""
|
|
1142
|
-
body = f"""
|
|
1230
|
+
body = f"""{HISTORICAL_TASK_HEADING}
|
|
1143
1231
|
{active_task}
|
|
1144
1232
|
|
|
1145
1233
|
## Goal
|
|
@@ -1156,7 +1244,7 @@ Recovered from a deterministic fallback because the LLM context summarizer was u
|
|
|
1156
1244
|
## Active State
|
|
1157
1245
|
Unknown from deterministic fallback. Inspect current repository/session state if needed.
|
|
1158
1246
|
|
|
1159
|
-
|
|
1247
|
+
{HISTORICAL_IN_PROGRESS_HEADING}
|
|
1160
1248
|
{active_task}
|
|
1161
1249
|
|
|
1162
1250
|
## Blocked
|
|
@@ -1168,13 +1256,13 @@ None recoverable from deterministic fallback.
|
|
|
1168
1256
|
## Resolved Questions
|
|
1169
1257
|
None recoverable from deterministic fallback.
|
|
1170
1258
|
|
|
1171
|
-
|
|
1259
|
+
{HISTORICAL_PENDING_ASKS_HEADING}
|
|
1172
1260
|
{active_task}
|
|
1173
1261
|
|
|
1174
1262
|
## Relevant Files
|
|
1175
1263
|
{_bullets(relevant_files, limit=12)}
|
|
1176
1264
|
|
|
1177
|
-
|
|
1265
|
+
{HISTORICAL_REMAINING_WORK_HEADING}
|
|
1178
1266
|
Continue from the most recent unfulfilled user ask and protected tail messages. Verify state with tools before making claims.
|
|
1179
1267
|
|
|
1180
1268
|
## Last Dropped Turns
|
|
@@ -1247,6 +1335,19 @@ Summary generation was unavailable, so this is a best-effort deterministic fallb
|
|
|
1247
1335
|
summary_budget = self._compute_summary_budget(turns_to_summarize)
|
|
1248
1336
|
content_to_summarize = self._serialize_for_summary(turns_to_summarize)
|
|
1249
1337
|
|
|
1338
|
+
# Current date for temporal anchoring (see ## Temporal Anchoring below).
|
|
1339
|
+
# Date-only granularity matches system_prompt.py:337 (PR #20451) and the
|
|
1340
|
+
# user's configured timezone via hermes_time.now(). The compaction summary
|
|
1341
|
+
# is a mid-conversation message that is NOT part of the cached prefix, so a
|
|
1342
|
+
# date here never affects prompt-cache stability. Resolved defensively —
|
|
1343
|
+
# a clock failure must never block compaction.
|
|
1344
|
+
try:
|
|
1345
|
+
from hermes_time import now as _hermes_now
|
|
1346
|
+
|
|
1347
|
+
_today_str = _hermes_now().strftime("%Y-%m-%d")
|
|
1348
|
+
except Exception: # pragma: no cover - clock resolution is best-effort
|
|
1349
|
+
_today_str = ""
|
|
1350
|
+
|
|
1250
1351
|
# Preamble shared by both first-compaction and iterative-update prompts.
|
|
1251
1352
|
# Keep the wording deliberately plain: Azure/OpenAI-compatible content
|
|
1252
1353
|
# filters have flagged stronger "injection" / "do not respond" framing.
|
|
@@ -1264,8 +1365,26 @@ Summary generation was unavailable, so this is a best-effort deterministic fallb
|
|
|
1264
1365
|
"do not preserve their values."
|
|
1265
1366
|
)
|
|
1266
1367
|
|
|
1368
|
+
# Temporal anchoring directive. Rewrites relative / still-pending-sounding
|
|
1369
|
+
# references into absolute, dated, past-tense facts so a resumed
|
|
1370
|
+
# conversation does not re-issue completed actions. Only emitted when the
|
|
1371
|
+
# current date resolved successfully; otherwise the rule is omitted so the
|
|
1372
|
+
# summarizer is never handed an empty date placeholder.
|
|
1373
|
+
if _today_str:
|
|
1374
|
+
_temporal_anchoring_rule = (
|
|
1375
|
+
f"\nTEMPORAL ANCHORING: The current date is {_today_str}. When an "
|
|
1376
|
+
"action has already been carried out, phrase it as a completed, "
|
|
1377
|
+
"dated, past-tense fact rather than an open instruction. For "
|
|
1378
|
+
'example, rewrite "email John about the proposal" as "Sent the '
|
|
1379
|
+
f'proposal email to John on {_today_str}." Never leave a finished '
|
|
1380
|
+
"action worded as if it still needs doing, and never invent a date "
|
|
1381
|
+
"for work that has not happened yet.\n"
|
|
1382
|
+
)
|
|
1383
|
+
else:
|
|
1384
|
+
_temporal_anchoring_rule = ""
|
|
1385
|
+
|
|
1267
1386
|
# Shared structured template (used by both paths).
|
|
1268
|
-
_template_sections = f"""
|
|
1387
|
+
_template_sections = f"""{HISTORICAL_TASK_HEADING}
|
|
1269
1388
|
[THE SINGLE MOST IMPORTANT FIELD. Capture the user's most recent unfulfilled
|
|
1270
1389
|
input verbatim — the exact words they used. This includes:
|
|
1271
1390
|
- Explicit task assignments ("refactor the auth module")
|
|
@@ -1312,7 +1431,7 @@ Be specific with file paths, commands, line numbers, and results.]
|
|
|
1312
1431
|
- Any running processes or servers
|
|
1313
1432
|
- Environment details that matter]
|
|
1314
1433
|
|
|
1315
|
-
|
|
1434
|
+
{HISTORICAL_IN_PROGRESS_HEADING}
|
|
1316
1435
|
[Work currently underway — what was being done when compaction fired]
|
|
1317
1436
|
|
|
1318
1437
|
## Blocked
|
|
@@ -1324,20 +1443,20 @@ Be specific with file paths, commands, line numbers, and results.]
|
|
|
1324
1443
|
## Resolved Questions
|
|
1325
1444
|
[Questions the user asked that were ALREADY answered — include the answer so it is not repeated]
|
|
1326
1445
|
|
|
1327
|
-
|
|
1328
|
-
[Questions or requests from the user that have NOT yet been answered or fulfilled. If none, write "None."]
|
|
1446
|
+
{HISTORICAL_PENDING_ASKS_HEADING}
|
|
1447
|
+
[Questions or requests from the user that have NOT yet been answered or fulfilled. These are STALE — they were from the compacted turns. Write them here for reference only. The agent must NOT act on them unless the latest user message explicitly requests it. If none, write "None."]
|
|
1329
1448
|
|
|
1330
1449
|
## Relevant Files
|
|
1331
1450
|
[Files read, modified, or created — with brief note on each]
|
|
1332
1451
|
|
|
1333
|
-
|
|
1334
|
-
[What remains to be done — framed as context
|
|
1452
|
+
{HISTORICAL_REMAINING_WORK_HEADING}
|
|
1453
|
+
[What remains to be done — framed as STALE context for reference only. The agent must NOT resume this work unless the latest user message explicitly asks for it.]
|
|
1335
1454
|
|
|
1336
1455
|
## Critical Context
|
|
1337
1456
|
[Any specific values, error messages, configuration details, or data that would be lost without explicit preservation. NEVER include API keys, tokens, passwords, or credentials — write [REDACTED] instead.]
|
|
1338
1457
|
|
|
1339
1458
|
Target ~{summary_budget} tokens. Be CONCRETE — include file paths, command outputs, error messages, line numbers, and specific values. Avoid vague descriptions like "made some changes" — say exactly what changed.
|
|
1340
|
-
|
|
1459
|
+
{_temporal_anchoring_rule}
|
|
1341
1460
|
Write only the summary body. Do not include any preamble or prefix."""
|
|
1342
1461
|
|
|
1343
1462
|
if self._previous_summary:
|
|
@@ -1374,7 +1493,7 @@ Use this exact structure:
|
|
|
1374
1493
|
prompt += f"""
|
|
1375
1494
|
|
|
1376
1495
|
FOCUS TOPIC: "{focus_topic}"
|
|
1377
|
-
|
|
1496
|
+
This compaction should PRIORITISE preserving all information related to the focus topic above. For content related to "{focus_topic}", include full detail — exact values, file paths, command outputs, error messages, and decisions. For content NOT related to the focus topic, summarise more aggressively (brief one-liners or omit if truly irrelevant). The focus topic sections should receive roughly 60-70% of the summary token budget. Even for the focus topic, NEVER preserve API keys, tokens, passwords, or credentials — use [REDACTED]."""
|
|
1378
1497
|
|
|
1379
1498
|
try:
|
|
1380
1499
|
call_kwargs = {
|
|
@@ -1527,7 +1646,13 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1527
1646
|
text = (summary or "").strip()
|
|
1528
1647
|
for prefix in (SUMMARY_PREFIX, LEGACY_SUMMARY_PREFIX, *_HISTORICAL_SUMMARY_PREFIXES):
|
|
1529
1648
|
if text.startswith(prefix):
|
|
1530
|
-
|
|
1649
|
+
text = text[len(prefix):].lstrip()
|
|
1650
|
+
break
|
|
1651
|
+
# Strip the trailing end marker too — a rehydrated handoff body that
|
|
1652
|
+
# keeps it would leak the boundary directive into the iterative-update
|
|
1653
|
+
# summarizer prompt (and the marker is re-appended on insertion anyway).
|
|
1654
|
+
if text.endswith(_SUMMARY_END_MARKER):
|
|
1655
|
+
text = text[: -len(_SUMMARY_END_MARKER)].rstrip()
|
|
1531
1656
|
return text
|
|
1532
1657
|
|
|
1533
1658
|
@classmethod
|
|
@@ -1543,6 +1668,52 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1543
1668
|
return True
|
|
1544
1669
|
return any(text.startswith(p) for p in _HISTORICAL_SUMMARY_PREFIXES)
|
|
1545
1670
|
|
|
1671
|
+
@staticmethod
|
|
1672
|
+
def _has_compressed_summary_metadata(message: Any) -> bool:
|
|
1673
|
+
"""Return True if *message* carries the compressed-summary flag.
|
|
1674
|
+
|
|
1675
|
+
Callers (frontends, CLI, gateway) can use this to distinguish context
|
|
1676
|
+
compaction summaries from real assistant or user messages without
|
|
1677
|
+
relying on content-prefix heuristics. The flag is in-process only —
|
|
1678
|
+
the wire sanitizers strip underscore-prefixed keys before API calls.
|
|
1679
|
+
"""
|
|
1680
|
+
if not isinstance(message, dict):
|
|
1681
|
+
return False
|
|
1682
|
+
return bool(message.get(COMPRESSED_SUMMARY_METADATA_KEY))
|
|
1683
|
+
|
|
1684
|
+
@classmethod
|
|
1685
|
+
def _derive_auto_focus_topic(
|
|
1686
|
+
cls,
|
|
1687
|
+
messages: List[Dict[str, Any]],
|
|
1688
|
+
) -> Optional[str]:
|
|
1689
|
+
"""Infer a compact focus hint from the most recent real user turns."""
|
|
1690
|
+
candidates: list[str] = []
|
|
1691
|
+
for idx in range(len(messages) - 1, -1, -1):
|
|
1692
|
+
msg = messages[idx]
|
|
1693
|
+
if msg.get("role") != "user":
|
|
1694
|
+
continue
|
|
1695
|
+
content = msg.get("content")
|
|
1696
|
+
if cls._is_context_summary_content(content):
|
|
1697
|
+
continue
|
|
1698
|
+
text = redact_sensitive_text(_content_text_for_contains(content).strip())
|
|
1699
|
+
if not text:
|
|
1700
|
+
continue
|
|
1701
|
+
text = " ".join(text.split())
|
|
1702
|
+
if len(text) > _AUTO_FOCUS_TURN_MAX_CHARS:
|
|
1703
|
+
text = text[: _AUTO_FOCUS_TURN_MAX_CHARS - 1].rstrip() + "…"
|
|
1704
|
+
candidates.append(text)
|
|
1705
|
+
if len(candidates) >= _AUTO_FOCUS_MAX_TURNS:
|
|
1706
|
+
break
|
|
1707
|
+
|
|
1708
|
+
if not candidates:
|
|
1709
|
+
return None
|
|
1710
|
+
|
|
1711
|
+
candidates.reverse()
|
|
1712
|
+
focus = "Recent user focus:\n" + "\n".join(f"- {item}" for item in candidates)
|
|
1713
|
+
if len(focus) > _AUTO_FOCUS_MAX_CHARS:
|
|
1714
|
+
focus = focus[: _AUTO_FOCUS_MAX_CHARS - 1].rstrip() + "…"
|
|
1715
|
+
return focus
|
|
1716
|
+
|
|
1546
1717
|
@classmethod
|
|
1547
1718
|
def _find_latest_context_summary(
|
|
1548
1719
|
cls,
|
|
@@ -1695,6 +1866,105 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1695
1866
|
return i
|
|
1696
1867
|
return -1
|
|
1697
1868
|
|
|
1869
|
+
def _find_last_assistant_message_idx(
|
|
1870
|
+
self, messages: List[Dict[str, Any]], head_end: int
|
|
1871
|
+
) -> int:
|
|
1872
|
+
"""Return the index of the last user-visible assistant reply at or
|
|
1873
|
+
after *head_end*, or -1.
|
|
1874
|
+
|
|
1875
|
+
A "user-visible reply" is an assistant message with non-empty
|
|
1876
|
+
textual content — i.e. one that the WebUI / TUI / SessionsPage
|
|
1877
|
+
rendered as a bubble the operator could read. We deliberately
|
|
1878
|
+
skip assistant messages that contain only ``tool_calls`` (and
|
|
1879
|
+
no text), because those render as small "calling tool X"
|
|
1880
|
+
indicators and aren't what the reporter means by "the output
|
|
1881
|
+
of the last message you sent" (#29824).
|
|
1882
|
+
|
|
1883
|
+
Falling back to the most recent assistant message of ANY kind
|
|
1884
|
+
only kicks in when no content-bearing assistant message exists
|
|
1885
|
+
in the compressible region — typically a fresh session that
|
|
1886
|
+
just started a multi-step tool sequence with no prior reply
|
|
1887
|
+
to anchor. In that case the agent fix is a no-op and the
|
|
1888
|
+
existing user-message anchor carries the load.
|
|
1889
|
+
"""
|
|
1890
|
+
last_any = -1
|
|
1891
|
+
for i in range(len(messages) - 1, head_end - 1, -1):
|
|
1892
|
+
msg = messages[i]
|
|
1893
|
+
if msg.get("role") != "assistant":
|
|
1894
|
+
continue
|
|
1895
|
+
if last_any < 0:
|
|
1896
|
+
last_any = i
|
|
1897
|
+
content = msg.get("content")
|
|
1898
|
+
if isinstance(content, str) and content.strip():
|
|
1899
|
+
return i
|
|
1900
|
+
if isinstance(content, list):
|
|
1901
|
+
# Multimodal / Anthropic-style content: look for any
|
|
1902
|
+
# text block with non-empty text.
|
|
1903
|
+
for part in content:
|
|
1904
|
+
if isinstance(part, dict):
|
|
1905
|
+
text = part.get("text") or part.get("content")
|
|
1906
|
+
if isinstance(text, str) and text.strip():
|
|
1907
|
+
return i
|
|
1908
|
+
return last_any
|
|
1909
|
+
|
|
1910
|
+
def _ensure_last_assistant_message_in_tail(
|
|
1911
|
+
self,
|
|
1912
|
+
messages: List[Dict[str, Any]],
|
|
1913
|
+
cut_idx: int,
|
|
1914
|
+
head_end: int,
|
|
1915
|
+
) -> int:
|
|
1916
|
+
"""Guarantee the most recent assistant message is in the protected tail.
|
|
1917
|
+
|
|
1918
|
+
WebUI / TUI / SessionsPage bug (#29824). Without this anchor,
|
|
1919
|
+
``_find_tail_cut_by_tokens`` can leave the user's most recent
|
|
1920
|
+
visible assistant response inside the compressed middle region —
|
|
1921
|
+
especially when the conversation has a single oversized tool
|
|
1922
|
+
result or a long stretch of tool-call/result pairs after the
|
|
1923
|
+
last assistant reply. The summariser then rolls that reply up
|
|
1924
|
+
into the single ``[CONTEXT COMPACTION — REFERENCE ONLY]`` block
|
|
1925
|
+
persisted as ``role="user"`` or ``role="assistant"``. From the
|
|
1926
|
+
operator's perspective the WebUI session viewer
|
|
1927
|
+
(``web/src/pages/SessionsPage.tsx``) and the TUI chat panel
|
|
1928
|
+
both suddenly show the opaque "Context compaction" block in the
|
|
1929
|
+
slot where they were just reading the assistant's actual reply:
|
|
1930
|
+
|
|
1931
|
+
User: "i cant see the output of the last message you
|
|
1932
|
+
sent, i did see it previously, however now see
|
|
1933
|
+
'context compaction'"
|
|
1934
|
+
|
|
1935
|
+
Mirror of ``_ensure_last_user_message_in_tail`` but anchors on
|
|
1936
|
+
the last assistant-role message. Re-runs the tool-group
|
|
1937
|
+
alignment so we don't split a ``tool_call`` / ``tool_result``
|
|
1938
|
+
group that immediately precedes the anchored message — orphaned
|
|
1939
|
+
tool messages would otherwise be removed by
|
|
1940
|
+
``_sanitize_tool_pairs`` and trigger the same data-loss symptom
|
|
1941
|
+
we're trying to prevent.
|
|
1942
|
+
"""
|
|
1943
|
+
last_asst_idx = self._find_last_assistant_message_idx(messages, head_end)
|
|
1944
|
+
if last_asst_idx < 0:
|
|
1945
|
+
# No assistant message in the compressible region — nothing
|
|
1946
|
+
# to anchor (single-turn pre-reply state, etc.).
|
|
1947
|
+
return cut_idx
|
|
1948
|
+
if last_asst_idx >= cut_idx:
|
|
1949
|
+
# Already in the tail — the token-budget walk did the right
|
|
1950
|
+
# thing on its own.
|
|
1951
|
+
return cut_idx
|
|
1952
|
+
# Pull cut_idx back to the assistant message, then re-align so
|
|
1953
|
+
# we don't split a tool group that immediately precedes it
|
|
1954
|
+
# (e.g. an ``assistant(tool_calls)`` → ``tool(result)`` →
|
|
1955
|
+
# ``assistant(final reply)`` sequence would otherwise leave the
|
|
1956
|
+
# ``tool`` orphan when cut lands at the final reply).
|
|
1957
|
+
new_cut = self._align_boundary_backward(messages, last_asst_idx)
|
|
1958
|
+
if not self.quiet_mode:
|
|
1959
|
+
logger.debug(
|
|
1960
|
+
"Anchoring tail cut to last assistant message at index %d "
|
|
1961
|
+
"(was %d, aligned to %d) to keep the previously-visible "
|
|
1962
|
+
"reply out of the compaction summary (#29824)",
|
|
1963
|
+
last_asst_idx, cut_idx, new_cut,
|
|
1964
|
+
)
|
|
1965
|
+
# Safety: never go back into the head region.
|
|
1966
|
+
return max(new_cut, head_end + 1)
|
|
1967
|
+
|
|
1698
1968
|
def _ensure_last_user_message_in_tail(
|
|
1699
1969
|
self,
|
|
1700
1970
|
messages: List[Dict[str, Any]],
|
|
@@ -1706,7 +1976,7 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1706
1976
|
Context compressor bug (#10896): ``_align_boundary_backward`` can pull
|
|
1707
1977
|
``cut_idx`` past a user message when it tries to keep tool_call/result
|
|
1708
1978
|
groups together. If the last user message ends up in the *compressed*
|
|
1709
|
-
middle region the LLM summariser writes it into "Pending User Asks",
|
|
1979
|
+
middle region the LLM summariser writes it into "Historical Pending User Asks",
|
|
1710
1980
|
but ``SUMMARY_PREFIX`` tells the next model to respond only to user
|
|
1711
1981
|
messages *after* the summary — so the task effectively disappears from
|
|
1712
1982
|
the active context, causing the agent to stall, repeat completed work,
|
|
@@ -1753,11 +2023,12 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1753
2023
|
derived from ``summary_target_ratio * context_length``, so it
|
|
1754
2024
|
scales automatically with the model's context window.
|
|
1755
2025
|
|
|
1756
|
-
Token budget is the primary criterion. A
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
2026
|
+
Token budget is the primary criterion. A bounded message-count floor
|
|
2027
|
+
keeps a short run of recent turns verbatim even when the budget is
|
|
2028
|
+
exhausted, but the budget is allowed to exceed by up to 1.5x to avoid
|
|
2029
|
+
cutting inside an oversized message (tool output, file read, etc.). If
|
|
2030
|
+
even that floor exceeds 1.5x the budget, the cut is placed right after
|
|
2031
|
+
the head so compression still runs.
|
|
1761
2032
|
|
|
1762
2033
|
Never cuts inside a tool_call/result group. Always ensures the most
|
|
1763
2034
|
recent user message is in the tail (see ``_ensure_last_user_message_in_tail``).
|
|
@@ -1765,8 +2036,19 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1765
2036
|
if token_budget is None:
|
|
1766
2037
|
token_budget = self.tail_token_budget
|
|
1767
2038
|
n = len(messages)
|
|
1768
|
-
# Hard minimum: always keep
|
|
1769
|
-
|
|
2039
|
+
# Hard minimum: always keep a bounded recent-message floor in the tail.
|
|
2040
|
+
# ``protect_last_n`` remains a minimum up to the cap; the cap avoids
|
|
2041
|
+
# preserving a whole run of bulky tool outputs on every compaction.
|
|
2042
|
+
available_tail = max(0, n - head_end - 1)
|
|
2043
|
+
min_tail_floor = max(3, min(self.protect_last_n, _MAX_TAIL_MESSAGE_FLOOR))
|
|
2044
|
+
# Leave at least two non-head messages available to summarize on short
|
|
2045
|
+
# transcripts; otherwise compression can replace a tiny middle with a
|
|
2046
|
+
# summary and save no messages at all.
|
|
2047
|
+
compressible_tail_cap = max(3, available_tail - 2)
|
|
2048
|
+
min_tail = (
|
|
2049
|
+
min(min_tail_floor, compressible_tail_cap, available_tail)
|
|
2050
|
+
if available_tail > 1 else 0
|
|
2051
|
+
)
|
|
1770
2052
|
soft_ceiling = int(token_budget * 1.5)
|
|
1771
2053
|
accumulated = 0
|
|
1772
2054
|
cut_idx = n # start from beyond the end
|
|
@@ -1787,6 +2069,41 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1787
2069
|
accumulated += msg_tokens
|
|
1788
2070
|
cut_idx = i
|
|
1789
2071
|
|
|
2072
|
+
# If the backward walk never broke early because the entire transcript
|
|
2073
|
+
# fits within soft_ceiling, accumulated now holds the total transcript
|
|
2074
|
+
# size. Without intervention _ensure_last_user_message_in_tail pushes
|
|
2075
|
+
# cut_idx forward to include the last user message, and the caller's
|
|
2076
|
+
# compress_start >= compress_end guard either returns unchanged (no-op)
|
|
2077
|
+
# or compresses a single message — both of which trigger the infinite
|
|
2078
|
+
# compaction loop described in #40803.
|
|
2079
|
+
#
|
|
2080
|
+
# Fix: when the whole transcript fits in soft_ceiling, compute a
|
|
2081
|
+
# meaningful cut point using the raw (non-inflated) budget so that
|
|
2082
|
+
# compression actually summarizes a worthwhile middle section.
|
|
2083
|
+
if cut_idx <= head_end and accumulated <= soft_ceiling and accumulated > 0:
|
|
2084
|
+
# The entire compressable region fits in the soft ceiling.
|
|
2085
|
+
# Re-walk with the raw budget (no 1.5x multiplier) to find a
|
|
2086
|
+
# split that gives the summarizer something useful.
|
|
2087
|
+
raw_budget = token_budget
|
|
2088
|
+
raw_accumulated = 0
|
|
2089
|
+
for j in range(n - 1, head_end - 1, -1):
|
|
2090
|
+
raw_msg = messages[j]
|
|
2091
|
+
raw_content = raw_msg.get("content") or ""
|
|
2092
|
+
raw_len = _content_length_for_budget(raw_content)
|
|
2093
|
+
raw_tok = raw_len // _CHARS_PER_TOKEN + 10
|
|
2094
|
+
for tc in raw_msg.get("tool_calls") or []:
|
|
2095
|
+
if isinstance(tc, dict):
|
|
2096
|
+
args = tc.get("function", {}).get("arguments", "")
|
|
2097
|
+
raw_tok += len(args) // _CHARS_PER_TOKEN
|
|
2098
|
+
if raw_accumulated + raw_tok > raw_budget and (n - j) >= min_tail:
|
|
2099
|
+
cut_idx = j
|
|
2100
|
+
break
|
|
2101
|
+
raw_accumulated += raw_tok
|
|
2102
|
+
cut_idx = j
|
|
2103
|
+
# If the raw-budget walk also consumed everything (very small
|
|
2104
|
+
# transcript), fall through — the existing fallback logic below
|
|
2105
|
+
# will still force a minimal cut after head_end.
|
|
2106
|
+
|
|
1790
2107
|
# Ensure we protect at least min_tail messages
|
|
1791
2108
|
fallback_cut = n - min_tail
|
|
1792
2109
|
cut_idx = min(cut_idx, fallback_cut)
|
|
@@ -1803,6 +2120,13 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1803
2120
|
# active task is never lost to compression (fixes #10896).
|
|
1804
2121
|
cut_idx = self._ensure_last_user_message_in_tail(messages, cut_idx, head_end)
|
|
1805
2122
|
|
|
2123
|
+
# Ensure the most recent assistant message is always in the tail
|
|
2124
|
+
# so the previously-visible reply isn't silently rolled into the
|
|
2125
|
+
# ``[CONTEXT COMPACTION — REFERENCE ONLY]`` block (fixes #29824).
|
|
2126
|
+
# Each anchor only walks ``cut_idx`` backward, so chaining them is
|
|
2127
|
+
# monotonic — the tail can only grow, never shrink.
|
|
2128
|
+
cut_idx = self._ensure_last_assistant_message_in_tail(messages, cut_idx, head_end)
|
|
2129
|
+
|
|
1806
2130
|
return max(cut_idx, head_end + 1)
|
|
1807
2131
|
|
|
1808
2132
|
# ------------------------------------------------------------------
|
|
@@ -1889,6 +2213,21 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1889
2213
|
compress_end = self._find_tail_cut_by_tokens(messages, compress_start)
|
|
1890
2214
|
|
|
1891
2215
|
if compress_start >= compress_end:
|
|
2216
|
+
# No compressable window — the entire transcript fits within
|
|
2217
|
+
# the tail budget (soft_ceiling). Without recording this as
|
|
2218
|
+
# an ineffective compression the anti-thrashing guard in
|
|
2219
|
+
# should_compress() never fires and every subsequent turn
|
|
2220
|
+
# re-triggers a no-op compression loop. (#40803)
|
|
2221
|
+
self._ineffective_compression_count += 1
|
|
2222
|
+
self._last_compression_savings_pct = 0.0
|
|
2223
|
+
if not self.quiet_mode:
|
|
2224
|
+
logger.warning(
|
|
2225
|
+
"Compression skipped: compress_start (%d) >= compress_end (%d) "
|
|
2226
|
+
"— transcript fits within tail budget, nothing to compress. "
|
|
2227
|
+
"ineffective_compression_count=%d",
|
|
2228
|
+
compress_start, compress_end,
|
|
2229
|
+
self._ineffective_compression_count,
|
|
2230
|
+
)
|
|
1892
2231
|
return messages
|
|
1893
2232
|
|
|
1894
2233
|
turns_to_summarize = messages[compress_start:compress_end]
|
|
@@ -1909,6 +2248,13 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1909
2248
|
if summary_body and not self._previous_summary:
|
|
1910
2249
|
self._previous_summary = summary_body
|
|
1911
2250
|
turns_to_summarize = messages[max(compress_start, summary_idx + 1):compress_end]
|
|
2251
|
+
elif self._previous_summary:
|
|
2252
|
+
# No handoff summary found in the current messages, but
|
|
2253
|
+
# _previous_summary is non-empty — it was set by a different
|
|
2254
|
+
# (now-ended) session (e.g., a cron job, a prior /new). Discard
|
|
2255
|
+
# it so _generate_summary() does not inject cross-session content
|
|
2256
|
+
# into the summarizer prompt via the iterative-update path.
|
|
2257
|
+
self._previous_summary = None
|
|
1912
2258
|
|
|
1913
2259
|
if not self.quiet_mode:
|
|
1914
2260
|
logger.info(
|
|
@@ -1933,7 +2279,8 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
1933
2279
|
)
|
|
1934
2280
|
|
|
1935
2281
|
# Phase 3: Generate structured summary
|
|
1936
|
-
|
|
2282
|
+
summary_focus_topic = focus_topic or self._derive_auto_focus_topic(messages)
|
|
2283
|
+
summary = self._generate_summary(turns_to_summarize, focus_topic=summary_focus_topic)
|
|
1937
2284
|
|
|
1938
2285
|
# If summary generation failed, behavior splits on
|
|
1939
2286
|
# ``abort_on_summary_failure`` (config: compression.abort_on_summary_failure):
|
|
@@ -2013,32 +2360,33 @@ The user has requested that this compaction PRIORITISE preserving all informatio
|
|
|
2013
2360
|
|
|
2014
2361
|
# When the summary lands as a standalone role="user" message,
|
|
2015
2362
|
# weak models read the verbatim "## Active Task" quote of a past
|
|
2016
|
-
# user request as fresh input (#11475, #14521).
|
|
2017
|
-
#
|
|
2018
|
-
#
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
"respond to the message below, not the summary above ---"
|
|
2024
|
-
)
|
|
2363
|
+
# user request as fresh input (#11475, #14521).
|
|
2364
|
+
# When it lands as role="assistant", models may regurgitate the
|
|
2365
|
+
# summary text as their own output (#33256). In both cases, append
|
|
2366
|
+
# the explicit end marker so the model has a clear "summary ends
|
|
2367
|
+
# here, respond to the message below" signal.
|
|
2368
|
+
if not _merge_summary_into_tail:
|
|
2369
|
+
summary = summary + "\n\n" + _SUMMARY_END_MARKER
|
|
2025
2370
|
|
|
2026
2371
|
if not _merge_summary_into_tail:
|
|
2027
|
-
compressed.append({
|
|
2372
|
+
compressed.append({
|
|
2373
|
+
"role": summary_role,
|
|
2374
|
+
"content": summary,
|
|
2375
|
+
COMPRESSED_SUMMARY_METADATA_KEY: True,
|
|
2376
|
+
})
|
|
2028
2377
|
|
|
2029
2378
|
for i in range(compress_end, n_messages):
|
|
2030
2379
|
msg = messages[i].copy()
|
|
2031
2380
|
if _merge_summary_into_tail and i == compress_end:
|
|
2032
|
-
merged_prefix =
|
|
2033
|
-
summary
|
|
2034
|
-
+ "\n\n--- END OF CONTEXT SUMMARY — "
|
|
2035
|
-
"respond to the message below, not the summary above ---\n\n"
|
|
2036
|
-
)
|
|
2381
|
+
merged_prefix = summary + "\n\n" + _SUMMARY_END_MARKER + "\n\n"
|
|
2037
2382
|
msg["content"] = _append_text_to_content(
|
|
2038
2383
|
msg.get("content"),
|
|
2039
2384
|
merged_prefix,
|
|
2040
2385
|
prepend=True,
|
|
2041
2386
|
)
|
|
2387
|
+
# Mark the merged message so frontends can identify it as
|
|
2388
|
+
# containing a compression summary prefix.
|
|
2389
|
+
msg[COMPRESSED_SUMMARY_METADATA_KEY] = True
|
|
2042
2390
|
_merge_summary_into_tail = False
|
|
2043
2391
|
compressed.append(msg)
|
|
2044
2392
|
|