@clawpump/claw-agent 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/.dockerignore +67 -0
- package/agent/.envrc +1 -1
- package/agent/.gitattributes +8 -0
- package/agent/AGENTS.md +216 -4
- package/agent/CONTRIBUTING.md +46 -8
- package/agent/Dockerfile +78 -35
- package/agent/MANIFEST.in +2 -0
- package/agent/README.md +12 -5
- package/agent/README.ur-pk.md +261 -0
- package/agent/README.zh-CN.md +11 -8
- package/agent/SECURITY.md +5 -4
- package/agent/acp_adapter/provenance.py +127 -0
- package/agent/acp_adapter/server.py +112 -5
- package/agent/acp_adapter/session.py +1 -6
- package/agent/acp_registry/agent.json +2 -2
- package/agent/agent/account_usage.py +313 -1
- package/agent/agent/agent_init.py +140 -37
- package/agent/agent/agent_runtime_helpers.py +342 -83
- package/agent/agent/anthropic_adapter.py +320 -33
- package/agent/agent/auxiliary_client.py +525 -105
- package/agent/agent/background_review.py +157 -19
- package/agent/agent/bedrock_adapter.py +71 -6
- package/agent/agent/billing_view.py +295 -0
- package/agent/agent/chat_completion_helpers.py +229 -4
- package/agent/agent/codex_responses_adapter.py +86 -10
- package/agent/agent/codex_runtime.py +153 -1
- package/agent/agent/coding_context.py +738 -0
- package/agent/agent/context_compressor.py +392 -44
- package/agent/agent/context_references.py +34 -1
- package/agent/agent/conversation_compression.py +159 -22
- package/agent/agent/conversation_loop.py +643 -908
- package/agent/agent/copilot_acp_client.py +4 -11
- package/agent/agent/credential_pool.py +5 -3
- package/agent/agent/credits_tracker.py +794 -0
- package/agent/agent/curator.py +91 -18
- package/agent/agent/curator_backup.py +26 -10
- package/agent/agent/display.py +42 -1
- package/agent/agent/error_classifier.py +52 -3
- package/agent/agent/errors.py +3 -0
- package/agent/agent/file_safety.py +0 -17
- package/agent/agent/gemini_native_adapter.py +31 -1
- package/agent/agent/i18n.py +48 -4
- package/agent/agent/image_gen_provider.py +74 -5
- package/agent/agent/image_routing.py +29 -0
- package/agent/agent/insights.py +8 -17
- package/agent/agent/lsp/install.py +3 -0
- package/agent/agent/memory_manager.py +326 -31
- package/agent/agent/message_content.py +50 -0
- package/agent/agent/model_metadata.py +214 -3
- package/agent/agent/moonshot_schema.py +8 -1
- package/agent/agent/onboarding.py +60 -0
- package/agent/agent/prompt_builder.py +327 -37
- package/agent/agent/redact.py +1 -0
- package/agent/agent/runtime_cwd.py +34 -5
- package/agent/agent/secret_scope.py +205 -0
- package/agent/agent/secret_sources/bitwarden.py +34 -2
- package/agent/agent/skill_commands.py +90 -1
- package/agent/agent/skill_preprocessing.py +1 -0
- package/agent/agent/skill_utils.py +209 -36
- package/agent/agent/ssl_guard.py +94 -0
- package/agent/agent/system_prompt.py +133 -5
- package/agent/agent/tool_executor.py +496 -70
- package/agent/agent/transports/anthropic.py +83 -21
- package/agent/agent/transports/chat_completions.py +94 -5
- package/agent/agent/transports/codex.py +67 -2
- package/agent/agent/transports/codex_app_server.py +1 -0
- package/agent/agent/transports/codex_app_server_session.py +30 -0
- package/agent/agent/transports/types.py +12 -0
- package/agent/agent/turn_context.py +408 -0
- package/agent/agent/turn_finalizer.py +428 -0
- package/agent/agent/turn_retry_state.py +68 -0
- package/agent/agent/usage_pricing.py +3 -0
- package/agent/apps/bootstrap-installer/package.json +6 -5
- package/agent/apps/bootstrap-installer/src/routes/failure.tsx +12 -5
- package/agent/apps/bootstrap-installer/src/routes/progress.tsx +1 -3
- package/agent/apps/bootstrap-installer/src/store.ts +3 -2
- package/agent/apps/bootstrap-installer/src-tauri/src/bootstrap.rs +172 -7
- package/agent/apps/bootstrap-installer/src-tauri/src/events.rs +14 -1
- package/agent/apps/bootstrap-installer/src-tauri/src/paths.rs +29 -0
- package/agent/apps/bootstrap-installer/src-tauri/src/powershell.rs +93 -3
- package/agent/apps/bootstrap-installer/src-tauri/src/update.rs +695 -39
- package/agent/apps/bootstrap-installer/tsconfig.json +3 -4
- package/agent/apps/desktop/DESIGN.md +167 -0
- package/agent/apps/desktop/README.md +20 -16
- package/agent/apps/desktop/assets/icon.icns +0 -0
- package/agent/apps/desktop/assets/icon.ico +0 -0
- package/agent/apps/desktop/assets/icon.png +0 -0
- package/agent/apps/desktop/electron/backend-env.cjs +112 -0
- package/agent/apps/desktop/electron/backend-env.test.cjs +111 -0
- package/agent/apps/desktop/electron/backend-probes.test.cjs +3 -1
- package/agent/apps/desktop/electron/backend-ready.cjs +66 -0
- package/agent/apps/desktop/electron/bootstrap-platform.cjs +52 -0
- package/agent/apps/desktop/electron/bootstrap-platform.test.cjs +59 -1
- package/agent/apps/desktop/electron/bootstrap-runner.cjs +176 -38
- package/agent/apps/desktop/electron/bootstrap-runner.test.cjs +112 -1
- package/agent/apps/desktop/electron/connection-config.cjs +288 -0
- package/agent/apps/desktop/electron/connection-config.test.cjs +396 -0
- package/agent/apps/desktop/electron/dashboard-token.cjs +99 -0
- package/agent/apps/desktop/electron/dashboard-token.test.cjs +142 -0
- package/agent/apps/desktop/electron/desktop-uninstall.cjs +232 -0
- package/agent/apps/desktop/electron/desktop-uninstall.test.cjs +246 -0
- package/agent/apps/desktop/electron/entitlements.mac.inherit.plist +2 -0
- package/agent/apps/desktop/electron/fs-read-dir.cjs +109 -0
- package/agent/apps/desktop/electron/fs-read-dir.test.cjs +364 -0
- package/agent/apps/desktop/electron/gateway-ws-probe.cjs +188 -0
- package/agent/apps/desktop/electron/gateway-ws-probe.test.cjs +122 -0
- package/agent/apps/desktop/electron/git-root.cjs +54 -0
- package/agent/apps/desktop/electron/git-root.test.cjs +40 -0
- package/agent/apps/desktop/electron/git-worktrees.cjs +174 -0
- package/agent/apps/desktop/electron/hardening.cjs +123 -28
- package/agent/apps/desktop/electron/hardening.test.cjs +163 -0
- package/agent/apps/desktop/electron/main.cjs +3121 -331
- package/agent/apps/desktop/electron/oauth-net-request.cjs +20 -0
- package/agent/apps/desktop/electron/oauth-net-request.test.cjs +34 -0
- package/agent/apps/desktop/electron/preload.cjs +52 -2
- package/agent/apps/desktop/electron/session-windows.cjs +124 -0
- package/agent/apps/desktop/electron/session-windows.test.cjs +199 -0
- package/agent/apps/desktop/electron/update-rebuild.cjs +29 -0
- package/agent/apps/desktop/electron/update-rebuild.test.cjs +55 -0
- package/agent/apps/desktop/electron/update-remote.cjs +56 -0
- package/agent/apps/desktop/electron/update-remote.test.cjs +78 -0
- package/agent/apps/desktop/electron/vscode-marketplace.cjs +331 -0
- package/agent/apps/desktop/electron/vscode-marketplace.test.cjs +113 -0
- package/agent/apps/desktop/electron/windows-child-process.test.cjs +57 -0
- package/agent/apps/desktop/electron/windows-user-env.cjs +76 -0
- package/agent/apps/desktop/electron/windows-user-env.test.cjs +90 -0
- package/agent/apps/desktop/electron/workspace-cwd.cjs +38 -0
- package/agent/apps/desktop/electron/workspace-cwd.test.cjs +45 -0
- package/agent/apps/desktop/eslint.config.mjs +0 -3
- package/agent/apps/desktop/index.html +27 -2
- package/agent/apps/desktop/package.json +31 -11
- package/agent/apps/desktop/pr-assets/session-source-folders.png +0 -0
- package/agent/apps/desktop/public/apple-touch-icon.png +0 -0
- package/agent/apps/desktop/public/nous-girl.jpg +0 -0
- package/agent/apps/desktop/scripts/assert-dist-built.cjs +70 -0
- package/agent/apps/desktop/scripts/assert-dist-built.test.cjs +84 -0
- package/agent/apps/desktop/scripts/before-pack.cjs +78 -0
- package/agent/apps/desktop/scripts/before-pack.test.cjs +53 -0
- package/agent/apps/desktop/scripts/diag-scroll-reset.mjs +229 -0
- package/agent/apps/desktop/scripts/patch-electron-builder-mac-binary.cjs +64 -0
- package/agent/apps/desktop/scripts/run-electron-builder.cjs +57 -0
- package/agent/apps/desktop/src/app/agents/index.tsx +53 -45
- package/agent/apps/desktop/src/app/artifacts/index.tsx +102 -83
- package/agent/apps/desktop/src/app/chat/chat-drop-overlay.tsx +29 -8
- package/agent/apps/desktop/src/app/chat/chat-swap-overlay.tsx +47 -0
- package/agent/apps/desktop/src/app/chat/composer/attachments.tsx +81 -45
- package/agent/apps/desktop/src/app/chat/composer/completion-drawer.tsx +13 -24
- package/agent/apps/desktop/src/app/chat/composer/context-menu.tsx +138 -88
- package/agent/apps/desktop/src/app/chat/composer/controls.tsx +138 -90
- package/agent/apps/desktop/src/app/chat/composer/enter-submit-dom-race.test.tsx +218 -0
- package/agent/apps/desktop/src/app/chat/composer/focus.ts +32 -0
- package/agent/apps/desktop/src/app/chat/composer/help-hint.tsx +38 -25
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-live-completion-adapter.ts +7 -0
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-mic-recorder.ts +22 -12
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-slash-completions.ts +142 -14
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-voice-conversation.ts +14 -11
- package/agent/apps/desktop/src/app/chat/composer/hooks/use-voice-recorder.ts +9 -6
- package/agent/apps/desktop/src/app/chat/composer/ime-composition-dom-repro.test.tsx +108 -0
- package/agent/apps/desktop/src/app/chat/composer/index.tsx +930 -180
- package/agent/apps/desktop/src/app/chat/composer/inline-refs.ts +136 -32
- package/agent/apps/desktop/src/app/chat/composer/model-pill.tsx +86 -0
- package/agent/apps/desktop/src/app/chat/composer/queue-panel.tsx +54 -75
- package/agent/apps/desktop/src/app/chat/composer/rich-editor.test.ts +117 -1
- package/agent/apps/desktop/src/app/chat/composer/rich-editor.ts +117 -6
- package/agent/apps/desktop/src/app/chat/composer/slash-nav-dom-repro.test.tsx +186 -0
- package/agent/apps/desktop/src/app/chat/composer/status-stack/index.tsx +202 -0
- package/agent/apps/desktop/src/app/chat/composer/status-stack/status-row.tsx +155 -0
- package/agent/apps/desktop/src/app/chat/composer/text-utils.test.ts +104 -0
- package/agent/apps/desktop/src/app/chat/composer/text-utils.ts +37 -9
- package/agent/apps/desktop/src/app/chat/composer/trigger-popover.test.tsx +50 -0
- package/agent/apps/desktop/src/app/chat/composer/trigger-popover.tsx +105 -40
- package/agent/apps/desktop/src/app/chat/composer/types.ts +5 -0
- package/agent/apps/desktop/src/app/chat/composer/url-dialog.tsx +11 -15
- package/agent/apps/desktop/src/app/chat/composer/voice-activity.tsx +8 -4
- package/agent/apps/desktop/src/app/chat/hooks/use-composer-actions.test.ts +57 -0
- package/agent/apps/desktop/src/app/chat/hooks/use-composer-actions.ts +70 -16
- package/agent/apps/desktop/src/app/chat/hooks/use-file-drop-zone.ts +52 -16
- package/agent/apps/desktop/src/app/chat/index.tsx +234 -81
- package/agent/apps/desktop/src/app/chat/perf-probe.tsx +69 -21
- package/agent/apps/desktop/src/app/chat/right-rail/preview-console.tsx +44 -40
- package/agent/apps/desktop/src/app/chat/right-rail/preview-file.tsx +71 -25
- package/agent/apps/desktop/src/app/chat/right-rail/preview-pane.test.tsx +40 -1
- package/agent/apps/desktop/src/app/chat/right-rail/preview-pane.tsx +55 -53
- package/agent/apps/desktop/src/app/chat/right-rail/preview.tsx +35 -17
- package/agent/apps/desktop/src/app/chat/scroll-to-bottom-button.test.tsx +67 -0
- package/agent/apps/desktop/src/app/chat/scroll-to-bottom-button.tsx +74 -0
- package/agent/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx +356 -0
- package/agent/apps/desktop/src/app/chat/sidebar/index.tsx +1189 -364
- package/agent/apps/desktop/src/app/chat/sidebar/load-more-row.tsx +30 -0
- package/agent/apps/desktop/src/app/chat/sidebar/order.test.ts +21 -0
- package/agent/apps/desktop/src/app/chat/sidebar/order.ts +17 -0
- package/agent/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx +524 -0
- package/agent/apps/desktop/src/app/chat/sidebar/session-actions-menu.tsx +80 -45
- package/agent/apps/desktop/src/app/chat/sidebar/session-row.tsx +120 -25
- package/agent/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx +7 -13
- package/agent/apps/desktop/src/app/chat/sidebar/workspace-groups.test.ts +149 -0
- package/agent/apps/desktop/src/app/chat/sidebar/workspace-groups.ts +326 -0
- package/agent/apps/desktop/src/app/chat/thread-loading.ts +7 -2
- package/agent/apps/desktop/src/app/command-center/index.tsx +320 -581
- package/agent/apps/desktop/src/app/command-palette/index.tsx +681 -0
- package/agent/apps/desktop/src/app/command-palette/marketplace-theme-page.tsx +157 -0
- package/agent/apps/desktop/src/app/cron/index.tsx +392 -324
- package/agent/apps/desktop/src/app/cron/job-state.ts +29 -0
- package/agent/apps/desktop/src/app/desktop-controller.tsx +618 -123
- package/agent/apps/desktop/src/app/floating-hud.ts +22 -0
- package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx +265 -0
- package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts +260 -14
- package/agent/apps/desktop/src/app/gateway/hooks/use-gateway-request.ts +48 -4
- package/agent/apps/desktop/src/app/hooks/use-keybinds.ts +270 -0
- package/agent/apps/desktop/src/app/hooks/use-refresh-hotkey.ts +45 -0
- package/agent/apps/desktop/src/app/layout-constants.ts +19 -0
- package/agent/apps/desktop/src/app/messaging/index.tsx +136 -241
- package/agent/apps/desktop/src/app/messaging/platform-icon.tsx +95 -0
- package/agent/apps/desktop/src/app/model-visibility-overlay.tsx +31 -0
- package/agent/apps/desktop/src/app/overlays/overlay-search-input.tsx +18 -62
- package/agent/apps/desktop/src/app/overlays/overlay-split-layout.tsx +59 -7
- package/agent/apps/desktop/src/app/overlays/overlay-view.tsx +9 -5
- package/agent/apps/desktop/src/app/page-search-shell.tsx +42 -20
- package/agent/apps/desktop/src/app/profiles/create-profile-dialog.tsx +165 -0
- package/agent/apps/desktop/src/app/profiles/delete-profile-dialog.tsx +65 -0
- package/agent/apps/desktop/src/app/profiles/index.tsx +174 -199
- package/agent/apps/desktop/src/app/profiles/rename-profile-dialog.tsx +125 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/dnd-manager.ts +27 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/ipc.test.ts +100 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/ipc.ts +12 -18
- package/agent/apps/desktop/src/app/right-sidebar/files/remote-picker.tsx +177 -0
- package/agent/apps/desktop/src/app/right-sidebar/files/tree.tsx +35 -21
- package/agent/apps/desktop/src/app/right-sidebar/files/use-project-tree.test.ts +75 -3
- package/agent/apps/desktop/src/app/right-sidebar/files/use-project-tree.ts +152 -5
- package/agent/apps/desktop/src/app/right-sidebar/index.test.tsx +75 -0
- package/agent/apps/desktop/src/app/right-sidebar/index.tsx +166 -129
- package/agent/apps/desktop/src/app/right-sidebar/store.ts +19 -4
- package/agent/apps/desktop/src/app/right-sidebar/terminal/buffer.ts +65 -0
- package/agent/apps/desktop/src/app/right-sidebar/terminal/index.tsx +29 -34
- package/agent/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx +18 -6
- package/agent/apps/desktop/src/app/right-sidebar/terminal/selection.ts +93 -32
- package/agent/apps/desktop/src/app/right-sidebar/terminal/use-terminal-session.ts +381 -119
- package/agent/apps/desktop/src/app/routes.ts +9 -0
- package/agent/apps/desktop/src/app/session/hooks/use-cwd-actions.ts +17 -7
- package/agent/apps/desktop/src/app/session/hooks/use-message-stream.ts +365 -47
- package/agent/apps/desktop/src/app/session/hooks/use-model-controls.test.tsx +198 -0
- package/agent/apps/desktop/src/app/session/hooks/use-model-controls.ts +70 -34
- package/agent/apps/desktop/src/app/session/hooks/use-prompt-actions.test.tsx +1061 -0
- package/agent/apps/desktop/src/app/session/hooks/use-prompt-actions.ts +1143 -165
- package/agent/apps/desktop/src/app/session/hooks/use-route-resume.test.tsx +341 -2
- package/agent/apps/desktop/src/app/session/hooks/use-route-resume.ts +176 -5
- package/agent/apps/desktop/src/app/session/hooks/use-session-actions.test.tsx +259 -0
- package/agent/apps/desktop/src/app/session/hooks/use-session-actions.ts +452 -149
- package/agent/apps/desktop/src/app/session/hooks/use-session-state-cache.test.tsx +327 -0
- package/agent/apps/desktop/src/app/session/hooks/use-session-state-cache.ts +133 -4
- package/agent/apps/desktop/src/app/session-picker-overlay.tsx +32 -0
- package/agent/apps/desktop/src/app/session-switcher.tsx +107 -0
- package/agent/apps/desktop/src/app/settings/about-settings.tsx +45 -36
- package/agent/apps/desktop/src/app/settings/appearance-settings.tsx +243 -162
- package/agent/apps/desktop/src/app/settings/config-settings.tsx +86 -66
- package/agent/apps/desktop/src/app/settings/constants.ts +459 -122
- package/agent/apps/desktop/src/app/settings/credential-key-ui.tsx +373 -0
- package/agent/apps/desktop/src/app/settings/env-credentials.tsx +198 -0
- package/agent/apps/desktop/src/app/settings/env-var-actions-menu.tsx +136 -0
- package/agent/apps/desktop/src/app/settings/field-copy.ts +56 -0
- package/agent/apps/desktop/src/app/settings/gateway-settings.tsx +385 -72
- package/agent/apps/desktop/src/app/settings/helpers.test.ts +156 -1
- package/agent/apps/desktop/src/app/settings/helpers.ts +30 -2
- package/agent/apps/desktop/src/app/settings/index.tsx +118 -84
- package/agent/apps/desktop/src/app/settings/keys-settings.tsx +62 -419
- package/agent/apps/desktop/src/app/settings/mcp-settings.tsx +65 -60
- package/agent/apps/desktop/src/app/settings/model-settings.test.tsx +129 -5
- package/agent/apps/desktop/src/app/settings/model-settings.tsx +370 -65
- package/agent/apps/desktop/src/app/settings/notifications-settings.tsx +150 -0
- package/agent/apps/desktop/src/app/settings/primitives.tsx +5 -11
- package/agent/apps/desktop/src/app/settings/provider-config-panel.test.tsx +142 -0
- package/agent/apps/desktop/src/app/settings/provider-config-panel.tsx +182 -0
- package/agent/apps/desktop/src/app/settings/providers-settings.test.tsx +171 -0
- package/agent/apps/desktop/src/app/settings/providers-settings.tsx +471 -0
- package/agent/apps/desktop/src/app/settings/sessions-settings.tsx +183 -71
- package/agent/apps/desktop/src/app/settings/toolset-config-panel.test.tsx +135 -1
- package/agent/apps/desktop/src/app/settings/toolset-config-panel.tsx +180 -57
- package/agent/apps/desktop/src/app/settings/types.ts +9 -6
- package/agent/apps/desktop/src/app/settings/uninstall-section.tsx +185 -0
- package/agent/apps/desktop/src/app/settings/use-deep-link-highlight.ts +60 -0
- package/agent/apps/desktop/src/app/shell/app-shell.tsx +59 -13
- package/agent/apps/desktop/src/app/shell/gateway-menu-panel.tsx +37 -32
- package/agent/apps/desktop/src/app/shell/hooks/use-overlay-routing.ts +6 -3
- package/agent/apps/desktop/src/app/shell/hooks/use-statusbar-items.tsx +212 -53
- package/agent/apps/desktop/src/app/shell/keybind-panel.tsx +215 -0
- package/agent/apps/desktop/src/app/shell/model-edit-submenu.test.tsx +84 -0
- package/agent/apps/desktop/src/app/shell/model-edit-submenu.tsx +244 -0
- package/agent/apps/desktop/src/app/shell/model-menu-panel.tsx +392 -0
- package/agent/apps/desktop/src/app/shell/statusbar-controls.tsx +23 -33
- package/agent/apps/desktop/src/app/shell/titlebar-controls.tsx +79 -95
- package/agent/apps/desktop/src/app/shell/titlebar.ts +8 -2
- package/agent/apps/desktop/src/app/skills/index.test.tsx +11 -0
- package/agent/apps/desktop/src/app/skills/index.tsx +79 -64
- package/agent/apps/desktop/src/app/types.ts +85 -0
- package/agent/apps/desktop/src/app/updates-overlay.tsx +110 -105
- package/agent/apps/desktop/src/components/assistant-ui/ansi-text.tsx +34 -0
- package/agent/apps/desktop/src/components/assistant-ui/block-direction.test.tsx +129 -0
- package/agent/apps/desktop/src/components/assistant-ui/clarify-tool.tsx +102 -81
- package/agent/apps/desktop/src/components/assistant-ui/directive-text.tsx +92 -15
- package/agent/apps/desktop/src/components/assistant-ui/markdown-text.test.ts +38 -0
- package/agent/apps/desktop/src/components/assistant-ui/markdown-text.tsx +304 -45
- package/agent/apps/desktop/src/components/assistant-ui/message-render-boundary.test.tsx +80 -0
- package/agent/apps/desktop/src/components/assistant-ui/message-render-boundary.tsx +48 -0
- package/agent/apps/desktop/src/components/assistant-ui/streaming.test.tsx +142 -90
- package/agent/apps/desktop/src/components/assistant-ui/thread-list.tsx +337 -0
- package/agent/apps/desktop/src/components/assistant-ui/thread.tsx +667 -190
- package/agent/apps/desktop/src/components/assistant-ui/tool-approval-group.test.tsx +299 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-approval.test.tsx +133 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-approval.tsx +239 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-fallback-model.test.ts +31 -0
- package/agent/apps/desktop/src/components/assistant-ui/tool-fallback-model.ts +152 -134
- package/agent/apps/desktop/src/components/assistant-ui/tool-fallback.tsx +142 -150
- package/agent/apps/desktop/src/components/assistant-ui/tooltip-icon-button.tsx +14 -12
- package/agent/apps/desktop/src/components/assistant-ui/user-message-edit.test.tsx +141 -0
- package/agent/apps/desktop/src/components/assistant-ui/user-message-text.tsx +152 -0
- package/agent/apps/desktop/src/components/boot-failure-overlay.tsx +150 -33
- package/agent/apps/desktop/src/components/boot-failure-reauth.test.ts +100 -0
- package/agent/apps/desktop/src/components/boot-failure-reauth.ts +81 -0
- package/agent/apps/desktop/src/components/brand-mark.tsx +19 -0
- package/agent/apps/desktop/src/components/chat/code-card.tsx +1 -1
- package/agent/apps/desktop/src/components/chat/composer-dock.ts +31 -0
- package/agent/apps/desktop/src/components/chat/diff-lines.tsx +1 -1
- package/agent/apps/desktop/src/components/chat/disclosure-row.tsx +13 -3
- package/agent/apps/desktop/src/components/chat/expandable-block.tsx +52 -0
- package/agent/apps/desktop/src/components/chat/generated-image-result.tsx +174 -0
- package/agent/apps/desktop/src/components/chat/image-generation-placeholder.tsx +70 -37
- package/agent/apps/desktop/src/components/chat/intro.tsx +8 -7
- package/agent/apps/desktop/src/components/chat/preview-attachment.tsx +4 -2
- package/agent/apps/desktop/src/components/chat/shiki-highlighter.test.ts +37 -0
- package/agent/apps/desktop/src/components/chat/shiki-highlighter.tsx +96 -22
- package/agent/apps/desktop/src/components/chat/status-row.tsx +70 -0
- package/agent/apps/desktop/src/components/chat/status-section.tsx +42 -0
- package/agent/apps/desktop/src/components/chat/terminal-output.tsx +54 -0
- package/agent/apps/desktop/src/components/chat/zoomable-image.tsx +70 -109
- package/agent/apps/desktop/src/components/desktop-install-overlay.tsx +154 -84
- package/agent/apps/desktop/src/components/desktop-onboarding-overlay.test.tsx +38 -8
- package/agent/apps/desktop/src/components/desktop-onboarding-overlay.tsx +789 -233
- package/agent/apps/desktop/src/components/error-boundary.tsx +77 -0
- package/agent/apps/desktop/src/components/gateway-connecting-overlay.test.tsx +144 -0
- package/agent/apps/desktop/src/components/gateway-connecting-overlay.tsx +7 -1
- package/agent/apps/desktop/src/components/haptics-provider.tsx +24 -0
- package/agent/apps/desktop/src/components/language-switcher.test.tsx +53 -0
- package/agent/apps/desktop/src/components/language-switcher.tsx +175 -0
- package/agent/apps/desktop/src/components/model-picker.tsx +42 -40
- package/agent/apps/desktop/src/components/model-visibility-dialog.tsx +166 -0
- package/agent/apps/desktop/src/components/notifications.tsx +48 -27
- package/agent/apps/desktop/src/components/pane-shell/index.ts +1 -1
- package/agent/apps/desktop/src/components/pane-shell/pane-shell.tsx +146 -9
- package/agent/apps/desktop/src/components/prompt-overlays.tsx +234 -0
- package/agent/apps/desktop/src/components/session-picker.tsx +108 -0
- package/agent/apps/desktop/src/components/ui/action-status.tsx +25 -0
- package/agent/apps/desktop/src/components/ui/badge.tsx +35 -0
- package/agent/apps/desktop/src/components/ui/button.tsx +37 -13
- package/agent/apps/desktop/src/components/ui/confirm-dialog.tsx +109 -0
- package/agent/apps/desktop/src/components/ui/control.ts +25 -0
- package/agent/apps/desktop/src/components/ui/copy-button.test.tsx +36 -0
- package/agent/apps/desktop/src/components/ui/copy-button.tsx +38 -27
- package/agent/apps/desktop/src/components/ui/dialog.tsx +39 -11
- package/agent/apps/desktop/src/components/ui/dropdown-menu.tsx +98 -24
- package/agent/apps/desktop/src/components/ui/error-state.tsx +50 -0
- package/agent/apps/desktop/src/components/ui/fade-text.tsx +9 -2
- package/agent/apps/desktop/src/components/ui/{braille-spinner.tsx → glyph-spinner.tsx} +15 -13
- package/agent/apps/desktop/src/components/ui/input.tsx +5 -2
- package/agent/apps/desktop/src/components/ui/kbd.tsx +83 -12
- package/agent/apps/desktop/src/components/ui/log-view.tsx +19 -0
- package/agent/apps/desktop/src/components/ui/pagination.tsx +12 -5
- package/agent/apps/desktop/src/components/ui/popover.tsx +44 -0
- package/agent/apps/desktop/src/components/ui/search-field.tsx +80 -0
- package/agent/apps/desktop/src/components/ui/segmented-control.tsx +51 -0
- package/agent/apps/desktop/src/components/ui/select.tsx +10 -3
- package/agent/apps/desktop/src/components/ui/sheet.tsx +8 -2
- package/agent/apps/desktop/src/components/ui/sidebar.tsx +18 -25
- package/agent/apps/desktop/src/components/ui/switch.tsx +38 -15
- package/agent/apps/desktop/src/components/ui/textarea.tsx +4 -11
- package/agent/apps/desktop/src/components/ui/tool-icon.tsx +65 -0
- package/agent/apps/desktop/src/components/ui/tooltip.tsx +31 -4
- package/agent/apps/desktop/src/fonts/JetBrainsMono-Bold.woff2 +0 -0
- package/agent/apps/desktop/src/fonts/JetBrainsMono-Italic.woff2 +0 -0
- package/agent/apps/desktop/src/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/agent/apps/desktop/src/global.d.ts +181 -4
- package/agent/apps/desktop/src/hermes.test.ts +60 -0
- package/agent/apps/desktop/src/hermes.ts +190 -13
- package/agent/apps/desktop/src/hooks/use-image-download.ts +85 -0
- package/agent/apps/desktop/src/hooks/use-resize-observer.ts +13 -4
- package/agent/apps/desktop/src/hooks/use-worktree-info.ts +68 -0
- package/agent/apps/desktop/src/i18n/catalog.ts +12 -0
- package/agent/apps/desktop/src/i18n/context.test.tsx +232 -0
- package/agent/apps/desktop/src/i18n/context.tsx +183 -0
- package/agent/apps/desktop/src/i18n/define-locale.ts +41 -0
- package/agent/apps/desktop/src/i18n/en.ts +1921 -0
- package/agent/apps/desktop/src/i18n/index.ts +20 -0
- package/agent/apps/desktop/src/i18n/ja.ts +2053 -0
- package/agent/apps/desktop/src/i18n/languages.test.ts +43 -0
- package/agent/apps/desktop/src/i18n/languages.ts +86 -0
- package/agent/apps/desktop/src/i18n/runtime.test.ts +75 -0
- package/agent/apps/desktop/src/i18n/runtime.ts +53 -0
- package/agent/apps/desktop/src/i18n/types.ts +1559 -0
- package/agent/apps/desktop/src/i18n/zh-hant.ts +1992 -0
- package/agent/apps/desktop/src/i18n/zh.ts +2099 -0
- package/agent/apps/desktop/src/lib/ansi.test.ts +123 -0
- package/agent/apps/desktop/src/lib/ansi.ts +186 -0
- package/agent/apps/desktop/src/lib/chat-messages.test.ts +79 -0
- package/agent/apps/desktop/src/lib/chat-messages.ts +68 -29
- package/agent/apps/desktop/src/lib/chat-runtime.test.ts +65 -1
- package/agent/apps/desktop/src/lib/chat-runtime.ts +39 -3
- package/agent/apps/desktop/src/lib/completion-sound.ts +519 -0
- package/agent/apps/desktop/src/lib/desktop-fs.test.ts +116 -0
- package/agent/apps/desktop/src/lib/desktop-fs.ts +113 -0
- package/agent/apps/desktop/src/lib/desktop-slash-commands.test.ts +89 -6
- package/agent/apps/desktop/src/lib/desktop-slash-commands.ts +270 -131
- package/agent/apps/desktop/src/lib/external-link.test.tsx +27 -0
- package/agent/apps/desktop/src/lib/external-link.tsx +9 -2
- package/agent/apps/desktop/src/lib/gateway-events.test.ts +27 -0
- package/agent/apps/desktop/src/lib/gateway-events.ts +16 -0
- package/agent/apps/desktop/src/lib/gateway-ws-url.test.ts +78 -0
- package/agent/apps/desktop/src/lib/gateway-ws-url.ts +91 -0
- package/agent/apps/desktop/src/lib/generated-images.test.ts +97 -0
- package/agent/apps/desktop/src/lib/generated-images.ts +116 -0
- package/agent/apps/desktop/src/lib/haptics.ts +17 -0
- package/agent/apps/desktop/src/lib/icons.ts +10 -2
- package/agent/apps/desktop/src/lib/keybinds/actions.ts +137 -0
- package/agent/apps/desktop/src/lib/keybinds/combo.test.ts +86 -0
- package/agent/apps/desktop/src/lib/keybinds/combo.ts +195 -0
- package/agent/apps/desktop/src/lib/local-preview.ts +23 -2
- package/agent/apps/desktop/src/lib/markdown-preprocess.ts +20 -7
- package/agent/apps/desktop/src/lib/media.remote.test.ts +90 -0
- package/agent/apps/desktop/src/lib/media.ts +40 -1
- package/agent/apps/desktop/src/lib/model-status-label.test.ts +59 -0
- package/agent/apps/desktop/src/lib/model-status-label.ts +122 -0
- package/agent/apps/desktop/src/lib/mutable-ref.ts +6 -0
- package/agent/apps/desktop/src/lib/profile-color.ts +58 -0
- package/agent/apps/desktop/src/lib/query-client.ts +13 -0
- package/agent/apps/desktop/src/lib/remend-tail.test.ts +105 -0
- package/agent/apps/desktop/src/lib/remend-tail.ts +108 -0
- package/agent/apps/desktop/src/lib/session-export.ts +6 -3
- package/agent/apps/desktop/src/lib/session-ids.test.ts +44 -0
- package/agent/apps/desktop/src/lib/session-ids.ts +26 -0
- package/agent/apps/desktop/src/lib/session-search.test.ts +66 -0
- package/agent/apps/desktop/src/lib/session-search.ts +21 -0
- package/agent/apps/desktop/src/lib/session-source.ts +126 -0
- package/agent/apps/desktop/src/lib/storage.test.ts +25 -0
- package/agent/apps/desktop/src/lib/storage.ts +35 -1
- package/agent/apps/desktop/src/lib/todos.test.ts +46 -1
- package/agent/apps/desktop/src/lib/todos.ts +37 -0
- package/agent/apps/desktop/src/lib/tool-result-summary.ts +5 -1
- package/agent/apps/desktop/src/lib/update-copy.test.ts +38 -0
- package/agent/apps/desktop/src/lib/update-copy.ts +44 -0
- package/agent/apps/desktop/src/lib/use-enter-animation.ts +2 -2
- package/agent/apps/desktop/src/lib/yolo-session.ts +50 -0
- package/agent/apps/desktop/src/main.tsx +19 -19
- package/agent/apps/desktop/src/store/boot.ts +4 -3
- package/agent/apps/desktop/src/store/clarify.test.ts +81 -0
- package/agent/apps/desktop/src/store/clarify.ts +50 -13
- package/agent/apps/desktop/src/store/command-palette.ts +20 -0
- package/agent/apps/desktop/src/store/compaction.test.ts +53 -0
- package/agent/apps/desktop/src/store/compaction.ts +38 -0
- package/agent/apps/desktop/src/store/completion-sound.ts +32 -0
- package/agent/apps/desktop/src/store/composer-input-history.test.ts +147 -0
- package/agent/apps/desktop/src/store/composer-input-history.ts +158 -0
- package/agent/apps/desktop/src/store/composer-queue.test.ts +68 -0
- package/agent/apps/desktop/src/store/composer-queue.ts +76 -0
- package/agent/apps/desktop/src/store/composer-status.test.ts +99 -0
- package/agent/apps/desktop/src/store/composer-status.ts +277 -0
- package/agent/apps/desktop/src/store/composer.test.ts +106 -0
- package/agent/apps/desktop/src/store/composer.ts +116 -0
- package/agent/apps/desktop/src/store/cron.ts +19 -0
- package/agent/apps/desktop/src/store/gateway.ts +280 -6
- package/agent/apps/desktop/src/store/keybinds.ts +143 -0
- package/agent/apps/desktop/src/store/layout.ts +107 -9
- package/agent/apps/desktop/src/store/model-presets.test.ts +51 -0
- package/agent/apps/desktop/src/store/model-presets.ts +86 -0
- package/agent/apps/desktop/src/store/model-visibility.test.ts +99 -0
- package/agent/apps/desktop/src/store/model-visibility.ts +161 -0
- package/agent/apps/desktop/src/store/native-notifications.test.ts +192 -0
- package/agent/apps/desktop/src/store/native-notifications.ts +203 -0
- package/agent/apps/desktop/src/store/notifications.ts +10 -7
- package/agent/apps/desktop/src/store/onboarding.test.ts +271 -1
- package/agent/apps/desktop/src/store/onboarding.ts +268 -38
- package/agent/apps/desktop/src/store/preview.ts +10 -1
- package/agent/apps/desktop/src/store/profile.test.ts +89 -0
- package/agent/apps/desktop/src/store/profile.ts +395 -0
- package/agent/apps/desktop/src/store/prompts.test.ts +127 -0
- package/agent/apps/desktop/src/store/prompts.ts +117 -0
- package/agent/apps/desktop/src/store/session-switcher.test.ts +115 -0
- package/agent/apps/desktop/src/store/session-switcher.ts +128 -0
- package/agent/apps/desktop/src/store/session-sync.ts +25 -0
- package/agent/apps/desktop/src/store/session.test.ts +268 -2
- package/agent/apps/desktop/src/store/session.ts +392 -18
- package/agent/apps/desktop/src/store/subagents.ts +3 -0
- package/agent/apps/desktop/src/store/system-actions.ts +48 -0
- package/agent/apps/desktop/src/store/thread-scroll.ts +58 -5
- package/agent/apps/desktop/src/store/todos.test.ts +47 -0
- package/agent/apps/desktop/src/store/todos.ts +64 -0
- package/agent/apps/desktop/src/store/tool-dismiss.ts +45 -0
- package/agent/apps/desktop/src/store/translucency.ts +38 -0
- package/agent/apps/desktop/src/store/updates.test.ts +187 -2
- package/agent/apps/desktop/src/store/updates.ts +268 -18
- package/agent/apps/desktop/src/store/windows.test.ts +143 -0
- package/agent/apps/desktop/src/store/windows.ts +115 -0
- package/agent/apps/desktop/src/styles.css +510 -119
- package/agent/apps/desktop/src/themes/color.ts +142 -0
- package/agent/apps/desktop/src/themes/context.tsx +128 -75
- package/agent/apps/desktop/src/themes/install.test.ts +119 -0
- package/agent/apps/desktop/src/themes/install.ts +95 -0
- package/agent/apps/desktop/src/themes/presets.test.ts +33 -0
- package/agent/apps/desktop/src/themes/presets.ts +13 -4
- package/agent/apps/desktop/src/themes/profile-theme.test.ts +41 -0
- package/agent/apps/desktop/src/themes/types.ts +35 -0
- package/agent/apps/desktop/src/themes/user-themes.test.ts +63 -0
- package/agent/apps/desktop/src/themes/user-themes.ts +122 -0
- package/agent/apps/desktop/src/themes/vscode.test.ts +171 -0
- package/agent/apps/desktop/src/themes/vscode.ts +343 -0
- package/agent/apps/desktop/src/types/hermes.ts +138 -1
- package/agent/apps/desktop/tsconfig.json +2 -2
- package/agent/apps/desktop/vite.config.ts +18 -0
- package/agent/apps/shared/package.json +1 -1
- package/agent/apps/shared/src/json-rpc-gateway.ts +63 -2
- package/agent/apps/shared/tsconfig.json +2 -2
- package/agent/cli-config.yaml.example +78 -1
- package/agent/cli.py +2177 -3162
- package/agent/cron/blueprint_catalog.py +713 -0
- package/agent/cron/jobs.py +226 -110
- package/agent/cron/scheduler.py +468 -193
- package/agent/cron/scheduler_provider.py +177 -0
- package/agent/cron/scripts/__init__.py +1 -0
- package/agent/cron/scripts/classify_items.py +226 -0
- package/agent/cron/suggestion_catalog.py +154 -0
- package/agent/cron/suggestions.py +257 -0
- package/agent/docs/chronos-managed-cron-contract.md +196 -0
- package/agent/docs/design/profile-builder.md +146 -0
- package/agent/docs/middleware/README.md +260 -0
- package/agent/docs/observability/README.md +316 -0
- package/agent/docs/plans/2026-06-09-003-fix-telegram-stream-overflow-continuations-plan.md +240 -0
- package/agent/docs/rca-ssl-cacert-post-git-pull.md +54 -0
- package/agent/docs/relay-connector-contract.md +285 -0
- package/agent/gateway/authz_mixin.py +536 -0
- package/agent/gateway/channel_directory.py +65 -3
- package/agent/gateway/config.py +222 -12
- package/agent/gateway/display_config.py +10 -0
- package/agent/gateway/hooks.py +17 -0
- package/agent/gateway/kanban_watchers.py +1146 -0
- package/agent/gateway/message_timestamps.py +166 -0
- package/agent/gateway/platforms/ADDING_A_PLATFORM.md +29 -0
- package/agent/gateway/platforms/api_server.py +216 -38
- package/agent/gateway/platforms/base.py +210 -58
- package/agent/gateway/platforms/email.py +122 -12
- package/agent/gateway/platforms/feishu.py +80 -11
- package/agent/gateway/platforms/feishu_meeting_invite.py +212 -0
- package/agent/gateway/platforms/matrix.py +1498 -297
- package/agent/gateway/platforms/qqbot/adapter.py +6 -0
- package/agent/gateway/platforms/signal.py +8 -0
- package/agent/gateway/platforms/slack.py +308 -12
- package/agent/gateway/platforms/telegram.py +831 -24
- package/agent/gateway/platforms/webhook.py +109 -21
- package/agent/gateway/platforms/weixin.py +113 -2
- package/agent/gateway/platforms/whatsapp.py +94 -288
- package/agent/gateway/platforms/whatsapp_cloud.py +1956 -0
- package/agent/gateway/platforms/whatsapp_common.py +367 -0
- package/agent/gateway/platforms/yuanbao.py +608 -191
- package/agent/gateway/platforms/yuanbao_proto.py +232 -23
- package/agent/gateway/relay/__init__.py +375 -0
- package/agent/gateway/relay/adapter.py +222 -0
- package/agent/gateway/relay/auth.py +168 -0
- package/agent/gateway/relay/descriptor.py +118 -0
- package/agent/gateway/relay/transport.py +101 -0
- package/agent/gateway/relay/ws_transport.py +327 -0
- package/agent/gateway/response_filters.py +53 -0
- package/agent/gateway/rich_sent_store.py +80 -0
- package/agent/gateway/run.py +2940 -5001
- package/agent/gateway/session.py +109 -8
- package/agent/gateway/session_context.py +22 -4
- package/agent/gateway/slash_commands.py +3854 -0
- package/agent/gateway/status.py +141 -21
- package/agent/gateway/stream_consumer.py +288 -31
- package/agent/hermes-already-has-routines.md +1 -1
- package/agent/hermes_cli/__init__.py +62 -17
- package/agent/hermes_cli/_parser.py +30 -0
- package/agent/hermes_cli/_subprocess_compat.py +61 -0
- package/agent/hermes_cli/active_sessions.py +320 -0
- package/agent/hermes_cli/auth.py +707 -59
- package/agent/hermes_cli/auth_commands.py +39 -22
- package/agent/hermes_cli/backup.py +109 -7
- package/agent/hermes_cli/banner.py +88 -0
- package/agent/hermes_cli/blueprint_cmd.py +318 -0
- package/agent/hermes_cli/cli_agent_setup_mixin.py +684 -0
- package/agent/hermes_cli/cli_commands_mixin.py +2293 -0
- package/agent/hermes_cli/commands.py +215 -91
- package/agent/hermes_cli/config.py +967 -130
- package/agent/hermes_cli/container_boot.py +76 -11
- package/agent/hermes_cli/cron.py +5 -11
- package/agent/hermes_cli/curator.py +21 -0
- package/agent/hermes_cli/dashboard_auth/__init__.py +2 -0
- package/agent/hermes_cli/dashboard_auth/base.py +62 -0
- package/agent/hermes_cli/dashboard_auth/cookies.py +32 -19
- package/agent/hermes_cli/dashboard_auth/login_page.py +156 -6
- package/agent/hermes_cli/dashboard_auth/middleware.py +28 -4
- package/agent/hermes_cli/dashboard_auth/prefix.py +46 -2
- package/agent/hermes_cli/dashboard_auth/public_paths.py +6 -0
- package/agent/hermes_cli/dashboard_auth/routes.py +158 -2
- package/agent/hermes_cli/dashboard_auth/ws_tickets.py +85 -11
- package/agent/hermes_cli/dashboard_register.py +427 -0
- package/agent/hermes_cli/debug.py +155 -50
- package/agent/hermes_cli/doctor.py +255 -14
- package/agent/hermes_cli/dump.py +60 -6
- package/agent/hermes_cli/env_loader.py +33 -0
- package/agent/hermes_cli/gateway.py +755 -103
- package/agent/hermes_cli/gateway_enroll.py +250 -0
- package/agent/hermes_cli/gateway_windows.py +254 -11
- package/agent/hermes_cli/gui_uninstall.py +285 -0
- package/agent/hermes_cli/inventory.py +105 -4
- package/agent/hermes_cli/kanban.py +58 -71
- package/agent/hermes_cli/kanban_db.py +391 -14
- package/agent/hermes_cli/kanban_decompose.py +2 -2
- package/agent/hermes_cli/kanban_specify.py +3 -1
- package/agent/hermes_cli/logs.py +2 -0
- package/agent/hermes_cli/main.py +2889 -5287
- package/agent/hermes_cli/managed_scope.py +214 -0
- package/agent/hermes_cli/managed_uv.py +254 -0
- package/agent/hermes_cli/mcp_catalog.py +6 -3
- package/agent/hermes_cli/mcp_config.py +145 -21
- package/agent/hermes_cli/mcp_security.py +96 -0
- package/agent/hermes_cli/mcp_startup.py +32 -3
- package/agent/hermes_cli/memory_providers.py +149 -0
- package/agent/hermes_cli/memory_setup.py +97 -42
- package/agent/hermes_cli/middleware.py +313 -0
- package/agent/hermes_cli/model_catalog.py +31 -0
- package/agent/hermes_cli/model_cost_guard.py +134 -0
- package/agent/hermes_cli/model_normalize.py +2 -1
- package/agent/hermes_cli/model_setup_flows.py +2759 -0
- package/agent/hermes_cli/model_switch.py +242 -27
- package/agent/hermes_cli/models.py +284 -44
- package/agent/hermes_cli/nous_account.py +33 -6
- package/agent/hermes_cli/nous_billing.py +406 -0
- package/agent/hermes_cli/nous_subscription.py +202 -5
- package/agent/hermes_cli/platforms.py +1 -0
- package/agent/hermes_cli/plugins.py +218 -18
- package/agent/hermes_cli/plugins_cmd.py +249 -105
- package/agent/hermes_cli/portal_cli.py +56 -16
- package/agent/hermes_cli/profile_distribution.py +6 -1
- package/agent/hermes_cli/profiles.py +283 -32
- package/agent/hermes_cli/provider_catalog.py +170 -0
- package/agent/hermes_cli/providers.py +4 -1
- package/agent/hermes_cli/pty_bridge.py +53 -4
- package/agent/hermes_cli/runtime_provider.py +216 -34
- package/agent/hermes_cli/secret_prompt.py +4 -4
- package/agent/hermes_cli/secrets_cli.py +24 -0
- package/agent/hermes_cli/send_cmd.py +28 -2
- package/agent/hermes_cli/service_manager.py +166 -19
- package/agent/hermes_cli/session_listing.py +97 -0
- package/agent/hermes_cli/setup.py +158 -94
- package/agent/hermes_cli/setup_whatsapp_cloud.py +541 -0
- package/agent/hermes_cli/skills_config.py +8 -2
- package/agent/hermes_cli/skills_hub.py +149 -7
- package/agent/hermes_cli/status.py +2 -2
- package/agent/hermes_cli/subcommands/__init__.py +18 -0
- package/agent/hermes_cli/subcommands/_shared.py +29 -0
- package/agent/hermes_cli/subcommands/acp.py +52 -0
- package/agent/hermes_cli/subcommands/auth.py +109 -0
- package/agent/hermes_cli/subcommands/backup.py +38 -0
- package/agent/hermes_cli/subcommands/claw.py +92 -0
- package/agent/hermes_cli/subcommands/config.py +49 -0
- package/agent/hermes_cli/subcommands/cron.py +163 -0
- package/agent/hermes_cli/subcommands/dashboard.py +143 -0
- package/agent/hermes_cli/subcommands/debug.py +77 -0
- package/agent/hermes_cli/subcommands/doctor.py +35 -0
- package/agent/hermes_cli/subcommands/dump.py +28 -0
- package/agent/hermes_cli/subcommands/gateway.py +332 -0
- package/agent/hermes_cli/subcommands/gui.py +63 -0
- package/agent/hermes_cli/subcommands/hooks.py +77 -0
- package/agent/hermes_cli/subcommands/import_cmd.py +31 -0
- package/agent/hermes_cli/subcommands/insights.py +25 -0
- package/agent/hermes_cli/subcommands/login.py +78 -0
- package/agent/hermes_cli/subcommands/logout.py +28 -0
- package/agent/hermes_cli/subcommands/logs.py +78 -0
- package/agent/hermes_cli/subcommands/mcp.py +108 -0
- package/agent/hermes_cli/subcommands/memory.py +53 -0
- package/agent/hermes_cli/subcommands/model.py +72 -0
- package/agent/hermes_cli/subcommands/pairing.py +36 -0
- package/agent/hermes_cli/subcommands/plugins.py +94 -0
- package/agent/hermes_cli/subcommands/postinstall.py +23 -0
- package/agent/hermes_cli/subcommands/profile.py +203 -0
- package/agent/hermes_cli/subcommands/prompt_size.py +36 -0
- package/agent/hermes_cli/subcommands/security.py +62 -0
- package/agent/hermes_cli/subcommands/setup.py +58 -0
- package/agent/hermes_cli/subcommands/skills.py +298 -0
- package/agent/hermes_cli/subcommands/slack.py +60 -0
- package/agent/hermes_cli/subcommands/status.py +28 -0
- package/agent/hermes_cli/subcommands/tools.py +95 -0
- package/agent/hermes_cli/subcommands/uninstall.py +41 -0
- package/agent/hermes_cli/subcommands/update.py +70 -0
- package/agent/hermes_cli/subcommands/version.py +18 -0
- package/agent/hermes_cli/subcommands/webhook.py +76 -0
- package/agent/hermes_cli/subcommands/whatsapp.py +22 -0
- package/agent/hermes_cli/suggestions_cmd.py +153 -0
- package/agent/hermes_cli/telegram_managed_bot.py +358 -0
- package/agent/hermes_cli/tips.py +3 -4
- package/agent/hermes_cli/tools_config.py +155 -28
- package/agent/hermes_cli/uninstall.py +231 -35
- package/agent/hermes_cli/web_server.py +6190 -973
- package/agent/hermes_cli/win_pty_bridge.py +179 -0
- package/agent/hermes_cli/write_approval_commands.py +209 -0
- package/agent/hermes_constants.py +164 -33
- package/agent/hermes_logging.py +74 -2
- package/agent/hermes_state.py +919 -106
- package/agent/hermes_time.py +20 -0
- package/agent/locales/af.yaml +23 -0
- package/agent/locales/de.yaml +23 -0
- package/agent/locales/en.yaml +20 -0
- package/agent/locales/es.yaml +23 -0
- package/agent/locales/fr.yaml +23 -0
- package/agent/locales/ga.yaml +23 -0
- package/agent/locales/hu.yaml +23 -0
- package/agent/locales/it.yaml +23 -0
- package/agent/locales/ja.yaml +23 -0
- package/agent/locales/ko.yaml +23 -0
- package/agent/locales/pt.yaml +23 -0
- package/agent/locales/ru.yaml +23 -0
- package/agent/locales/tr.yaml +23 -0
- package/agent/locales/uk.yaml +23 -0
- package/agent/locales/zh-hant.yaml +23 -0
- package/agent/locales/zh.yaml +23 -0
- package/agent/model_tools.py +204 -40
- package/agent/optional-mcps/clawpump/manifest.yaml +4 -2
- package/agent/optional-mcps/clawpump-stdio/manifest.yaml +2 -0
- package/agent/optional-mcps/unreal-engine/manifest.yaml +54 -0
- package/agent/optional-skills/blockchain/hyperliquid/SKILL.md +2 -2
- package/agent/optional-skills/blockchain/hyperliquid/scripts/hyperliquid_client.py +1 -1
- package/agent/optional-skills/creative/kanban-video-orchestrator/SKILL.md +1 -1
- package/agent/optional-skills/creative/kanban-video-orchestrator/assets/setup.sh.tmpl +4 -3
- package/agent/optional-skills/creative/kanban-video-orchestrator/references/kanban-setup.md +6 -4
- package/agent/optional-skills/creative/kanban-video-orchestrator/references/tool-matrix.md +2 -2
- package/agent/{skills/software-development → optional-skills/devops}/hermes-s6-container-supervision/SKILL.md +2 -0
- package/agent/optional-skills/devops/watchers/SKILL.md +1 -1
- package/agent/optional-skills/devops/watchers/scripts/watch_github.py +2 -1
- package/agent/optional-skills/payments/mpp-agent/SKILL.md +124 -0
- package/agent/optional-skills/payments/stripe-link-cli/SKILL.md +184 -0
- package/agent/optional-skills/payments/stripe-projects/SKILL.md +120 -0
- package/agent/optional-skills/productivity/canvas/SKILL.md +1 -1
- package/agent/optional-skills/productivity/canvas/scripts/canvas_api.py +4 -1
- package/agent/optional-skills/productivity/shop/SKILL.md +224 -0
- package/agent/optional-skills/productivity/shop/references/catalog-mcp.md +236 -0
- package/agent/optional-skills/productivity/shop/references/direct-api.md +278 -0
- package/agent/optional-skills/productivity/shop/references/legal.md +3 -0
- package/agent/optional-skills/productivity/shop/references/safety.md +36 -0
- package/agent/optional-skills/productivity/shopify/SKILL.md +1 -1
- package/agent/optional-skills/productivity/siyuan/SKILL.md +1 -1
- package/agent/optional-skills/productivity/telephony/SKILL.md +4 -4
- package/agent/optional-skills/productivity/telephony/scripts/telephony.py +15 -15
- package/agent/optional-skills/security/1password/SKILL.md +1 -1
- package/agent/{skills/red-teaming → optional-skills/security}/godmode/SKILL.md +3 -4
- package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/auto_jailbreak.py +3 -1
- package/agent/optional-skills/software-development/rest-graphql-debug/SKILL.md +1 -1
- package/agent/{skills → optional-skills}/software-development/subagent-driven-development/SKILL.md +5 -5
- package/agent/package-lock.json +4082 -7907
- package/agent/package.json +18 -3
- package/agent/plugins/browser/firecrawl/provider.py +4 -1
- package/agent/plugins/cron/__init__.py +344 -0
- package/agent/plugins/cron/chronos/__init__.py +241 -0
- package/agent/plugins/cron/chronos/_nas_client.py +123 -0
- package/agent/plugins/cron/chronos/plugin.yaml +9 -0
- package/agent/plugins/cron/chronos/verify.py +103 -0
- package/agent/plugins/dashboard_auth/basic/__init__.py +491 -0
- package/agent/plugins/dashboard_auth/basic/plugin.yaml +7 -0
- package/agent/plugins/dashboard_auth/nous/__init__.py +12 -14
- package/agent/plugins/dashboard_auth/self_hosted/__init__.py +736 -0
- package/agent/plugins/dashboard_auth/self_hosted/plugin.yaml +8 -0
- package/agent/plugins/disk-cleanup/disk_cleanup.py +100 -20
- package/agent/plugins/google_meet/audio_bridge.py +4 -0
- package/agent/plugins/google_meet/meet_bot.py +7 -1
- package/agent/plugins/hermes-achievements/dashboard/dist/index.js +9 -15
- package/agent/plugins/image_gen/fal/__init__.py +35 -6
- package/agent/plugins/image_gen/krea/__init__.py +56 -13
- package/agent/plugins/image_gen/openai/__init__.py +122 -24
- package/agent/plugins/image_gen/openai-codex/__init__.py +28 -2
- package/agent/plugins/image_gen/xai/__init__.py +92 -12
- package/agent/plugins/kanban/dashboard/dist/index.js +63 -48
- package/agent/plugins/kanban/dashboard/plugin_api.py +39 -35
- package/agent/plugins/memory/__init__.py +48 -5
- package/agent/plugins/memory/byterover/__init__.py +1 -0
- package/agent/plugins/memory/hindsight/README.md +1 -1
- package/agent/plugins/memory/hindsight/__init__.py +138 -24
- package/agent/plugins/memory/hindsight/plugin.yaml +1 -1
- package/agent/plugins/memory/honcho/README.md +13 -10
- package/agent/plugins/memory/honcho/cli.py +247 -122
- package/agent/plugins/memory/honcho/client.py +112 -102
- package/agent/plugins/memory/openviking/README.md +12 -1
- package/agent/plugins/memory/openviking/__init__.py +2281 -107
- package/agent/plugins/memory/openviking/plugin.yaml +1 -2
- package/agent/plugins/memory/supermemory/README.md +22 -10
- package/agent/plugins/memory/supermemory/__init__.py +142 -37
- package/agent/plugins/memory/supermemory/plugin.yaml +1 -1
- package/agent/plugins/model-providers/anthropic/__init__.py +1 -0
- package/agent/plugins/model-providers/bedrock/__init__.py +1 -0
- package/agent/plugins/model-providers/copilot-acp/__init__.py +1 -0
- package/agent/plugins/model-providers/custom/__init__.py +8 -2
- package/agent/plugins/model-providers/kimi-coding/__init__.py +16 -7
- package/agent/plugins/model-providers/minimax/__init__.py +60 -8
- package/agent/plugins/model-providers/opencode-zen/__init__.py +12 -3
- package/agent/plugins/model-providers/openrouter/__init__.py +75 -4
- package/agent/plugins/model-providers/xiaomi/__init__.py +2 -0
- package/agent/plugins/model-providers/zai/__init__.py +1 -0
- package/agent/plugins/observability/langfuse/__init__.py +147 -14
- package/agent/plugins/observability/nemo_relay/README.md +559 -0
- package/agent/plugins/observability/nemo_relay/__init__.py +962 -0
- package/agent/plugins/observability/nemo_relay/plugin.yaml +20 -0
- package/agent/plugins/platforms/discord/adapter.py +932 -61
- package/agent/plugins/platforms/discord/voice_mixer.py +379 -0
- package/agent/plugins/platforms/google_chat/adapter.py +9 -3
- package/agent/plugins/platforms/google_chat/oauth.py +1 -1
- package/agent/plugins/platforms/homeassistant/__init__.py +3 -0
- package/agent/{gateway/platforms/homeassistant.py → plugins/platforms/homeassistant/adapter.py} +128 -0
- package/agent/plugins/platforms/homeassistant/plugin.yaml +22 -0
- package/agent/plugins/platforms/irc/adapter.py +4 -1
- package/agent/plugins/platforms/line/adapter.py +16 -1
- package/agent/plugins/platforms/mattermost/adapter.py +100 -24
- package/agent/plugins/platforms/photon/README.md +179 -0
- package/agent/plugins/platforms/photon/__init__.py +4 -0
- package/agent/plugins/platforms/photon/adapter.py +1586 -0
- package/agent/plugins/platforms/photon/auth.py +1046 -0
- package/agent/plugins/platforms/photon/cli.py +439 -0
- package/agent/plugins/platforms/photon/plugin.yaml +88 -0
- package/agent/plugins/platforms/photon/sidecar/README.md +52 -0
- package/agent/plugins/platforms/photon/sidecar/index.mjs +720 -0
- package/agent/plugins/platforms/photon/sidecar/package-lock.json +1730 -0
- package/agent/plugins/platforms/photon/sidecar/package.json +25 -0
- package/agent/plugins/platforms/photon/sidecar/patch-spectrum-mixed-attachments.mjs +155 -0
- package/agent/plugins/platforms/raft/__init__.py +3 -0
- package/agent/plugins/platforms/raft/adapter.py +774 -0
- package/agent/plugins/platforms/raft/plugin.yaml +19 -0
- package/agent/plugins/platforms/simplex/adapter.py +777 -220
- package/agent/plugins/platforms/simplex/plugin.yaml +21 -2
- package/agent/plugins/platforms/teams/adapter.py +175 -5
- package/agent/plugins/plugin_utils.py +135 -0
- package/agent/plugins/video_gen/fal/__init__.py +10 -3
- package/agent/plugins/web/searxng/provider.py +15 -2
- package/agent/plugins/web/xai/provider.py +2 -2
- package/agent/providers/base.py +22 -3
- package/agent/pyproject.toml +115 -21
- package/agent/run_agent.py +733 -39
- package/agent/scripts/build_skills_index.py +51 -19
- package/agent/scripts/check_subprocess_stdin.py +177 -0
- package/agent/scripts/contributor_audit.py +2 -0
- package/agent/scripts/docker_config_migrate.py +67 -0
- package/agent/scripts/install.cmd +3 -3
- package/agent/scripts/install.ps1 +580 -154
- package/agent/scripts/install.sh +402 -185
- package/agent/scripts/lib/node-bootstrap.sh +39 -4
- package/agent/scripts/release.py +183 -0
- package/agent/scripts/run_tests.sh +1 -0
- package/agent/scripts/run_tests_parallel.py +18 -23
- package/agent/scripts/whatsapp-bridge/bridge.js +25 -4
- package/agent/setup.py +59 -0
- package/agent/skills/autonomous-ai-agents/codex/SKILL.md +19 -0
- package/agent/skills/autonomous-ai-agents/hermes-agent/SKILL.md +10 -3
- package/agent/skills/{mcp/native-mcp/SKILL.md → autonomous-ai-agents/hermes-agent/references/native-mcp.md} +0 -13
- package/agent/skills/{devops/webhook-subscriptions/SKILL.md → autonomous-ai-agents/hermes-agent/references/webhooks.md} +1 -11
- package/agent/skills/clawpump/SKILL.md +4 -1
- package/agent/skills/devops/kanban-orchestrator/SKILL.md +1 -0
- package/agent/skills/devops/kanban-worker/SKILL.md +1 -0
- package/agent/skills/github/github-auth/SKILL.md +2 -2
- package/agent/skills/github/github-auth/scripts/gh-env.sh +2 -2
- package/agent/skills/github/github-code-review/SKILL.md +2 -2
- package/agent/skills/github/github-issues/SKILL.md +2 -2
- package/agent/skills/github/github-pr-workflow/SKILL.md +2 -2
- package/agent/skills/github/github-repo-management/SKILL.md +2 -2
- package/agent/skills/media/gif-search/SKILL.md +1 -1
- package/agent/skills/media/youtube-content/SKILL.md +10 -7
- package/agent/skills/media/youtube-content/scripts/fetch_transcript.py +3 -3
- package/agent/skills/note-taking/obsidian/SKILL.md +1 -1
- package/agent/skills/productivity/airtable/SKILL.md +2 -2
- package/agent/skills/productivity/google-workspace/scripts/setup.py +33 -7
- package/agent/skills/productivity/notion/SKILL.md +2 -2
- package/agent/skills/productivity/teams-meeting-pipeline/SKILL.md +1 -1
- package/agent/skills/research/llm-wiki/SKILL.md +1 -1
- package/agent/skills/social-media/xurl/SKILL.md +9 -0
- package/agent/skills/software-development/hermes-agent-skill-authoring/SKILL.md +1 -1
- package/agent/skills/software-development/plan/SKILL.md +285 -5
- package/agent/skills/software-development/requesting-code-review/SKILL.md +2 -2
- package/agent/skills/software-development/simplify-code/SKILL.md +212 -0
- package/agent/skills/software-development/spike/SKILL.md +2 -2
- package/agent/skills/software-development/systematic-debugging/SKILL.md +1 -1
- package/agent/skills/software-development/test-driven-development/SKILL.md +1 -1
- package/agent/tools/approval.py +302 -4
- package/agent/tools/async_delegation.py +386 -0
- package/agent/tools/blueprints.py +325 -0
- package/agent/tools/browser_cdp_tool.py +3 -3
- package/agent/tools/browser_tool.py +34 -6
- package/agent/tools/checkpoint_manager.py +31 -1
- package/agent/tools/clarify_tool.py +55 -5
- package/agent/tools/code_execution_tool.py +31 -14
- package/agent/tools/computer_use/cua_backend.py +81 -3
- package/agent/tools/computer_use/tool.py +79 -5
- package/agent/tools/computer_use/vision_routing.py +55 -3
- package/agent/tools/credential_files.py +31 -12
- package/agent/tools/cronjob_tools.py +30 -20
- package/agent/tools/delegate_tool.py +356 -31
- package/agent/tools/env_probe.py +1 -0
- package/agent/tools/environments/docker.py +163 -8
- package/agent/tools/environments/file_sync.py +2 -1
- package/agent/tools/environments/local.py +74 -23
- package/agent/tools/environments/singularity.py +4 -1
- package/agent/tools/environments/ssh.py +78 -11
- package/agent/tools/file_operations.py +277 -41
- package/agent/tools/file_tools.py +166 -28
- package/agent/tools/image_generation_tool.py +515 -29
- package/agent/tools/kanban_tools.py +99 -0
- package/agent/tools/lazy_deps.py +33 -2
- package/agent/tools/mcp_oauth.py +5 -5
- package/agent/tools/mcp_oauth_manager.py +7 -5
- package/agent/tools/mcp_tool.py +840 -33
- package/agent/tools/memory_tool.py +335 -38
- package/agent/tools/osv_check.py +15 -1
- package/agent/tools/process_registry.py +155 -11
- package/agent/tools/read_extract.py +248 -0
- package/agent/tools/read_terminal_tool.py +93 -0
- package/agent/tools/schema_sanitizer.py +38 -0
- package/agent/tools/send_message_tool.py +163 -49
- package/agent/tools/session_search_tool.py +189 -7
- package/agent/tools/skill_manager_tool.py +202 -3
- package/agent/tools/skill_usage.py +52 -4
- package/agent/tools/skills_hub.py +184 -44
- package/agent/tools/skills_sync.py +232 -5
- package/agent/tools/skills_tool.py +125 -11
- package/agent/tools/terminal_tool.py +148 -26
- package/agent/tools/tirith_security.py +2 -0
- package/agent/tools/todo_tool.py +32 -1
- package/agent/tools/transcription_tools.py +13 -5
- package/agent/tools/tts_tool.py +332 -38
- package/agent/tools/url_safety.py +52 -1
- package/agent/tools/vision_tools.py +124 -39
- package/agent/tools/voice_mode.py +4 -3
- package/agent/tools/web_tools.py +45 -15
- package/agent/tools/write_approval.py +493 -0
- package/agent/toolsets.py +34 -10
- package/agent/trajectory_compressor.py +81 -10
- package/agent/tui_gateway/entry.py +43 -6
- package/agent/tui_gateway/server.py +3335 -330
- package/agent/tui_gateway/slash_worker.py +61 -0
- package/agent/tui_gateway/ws.py +67 -9
- package/agent/ui-tui/eslint.config.mjs +0 -4
- package/agent/ui-tui/package.json +6 -6
- package/agent/ui-tui/packages/hermes-ink/package.json +1 -1
- package/agent/ui-tui/packages/hermes-ink/src/ink/app-mouse.test.ts +34 -1
- package/agent/ui-tui/packages/hermes-ink/src/ink/app-rawmode-mouse.test.ts +91 -0
- package/agent/ui-tui/packages/hermes-ink/src/ink/components/App.tsx +35 -2
- package/agent/ui-tui/packages/hermes-ink/src/ink/events/input-event.ts +4 -11
- package/agent/ui-tui/packages/hermes-ink/src/ink/parse-keypress.test.ts +23 -57
- package/agent/ui-tui/packages/hermes-ink/src/ink/parse-keypress.ts +11 -135
- package/agent/ui-tui/packages/hermes-ink/src/ink/termio/tokenize.test.ts +185 -0
- package/agent/ui-tui/packages/hermes-ink/src/ink/termio/tokenize.ts +37 -3
- package/agent/ui-tui/packages/hermes-ink/src/utils/execFileNoThrow.ts +5 -5
- package/agent/ui-tui/src/__tests__/appChromeStatusRule.test.tsx +217 -0
- package/agent/ui-tui/src/__tests__/appChromeStatusRuleDevCredits.test.tsx +73 -0
- package/agent/ui-tui/src/__tests__/approvalAction.test.ts +11 -0
- package/agent/ui-tui/src/__tests__/billingCommand.test.ts +301 -0
- package/agent/ui-tui/src/__tests__/blockLayout.test.ts +122 -0
- package/agent/ui-tui/src/__tests__/brandingMcpCount.test.ts +111 -0
- package/agent/ui-tui/src/__tests__/completionApply.test.ts +51 -0
- package/agent/ui-tui/src/__tests__/createGatewayEventHandler.test.ts +487 -2
- package/agent/ui-tui/src/__tests__/createSlashHandler.test.ts +54 -0
- package/agent/ui-tui/src/__tests__/creditsCommand.test.ts +144 -0
- package/agent/ui-tui/src/__tests__/gatewayClient.test.ts +120 -99
- package/agent/ui-tui/src/__tests__/gracefulExit.test.ts +11 -0
- package/agent/ui-tui/src/__tests__/memoryMonitor.test.ts +102 -0
- package/agent/ui-tui/src/__tests__/paths.test.ts +41 -1
- package/agent/ui-tui/src/__tests__/terminalModes.test.ts +22 -0
- package/agent/ui-tui/src/__tests__/text.test.ts +23 -0
- package/agent/ui-tui/src/__tests__/textInputFastEcho.test.ts +37 -0
- package/agent/ui-tui/src/__tests__/turnControllerNotice.test.ts +43 -0
- package/agent/ui-tui/src/__tests__/useInputHandlers.test.ts +38 -1
- package/agent/ui-tui/src/__tests__/virtualHeights.test.ts +8 -0
- package/agent/ui-tui/src/app/createGatewayEventHandler.ts +102 -7
- package/agent/ui-tui/src/app/interfaces.ts +64 -1
- package/agent/ui-tui/src/app/overlayStore.ts +18 -2
- package/agent/ui-tui/src/app/slash/commands/billing.ts +332 -0
- package/agent/ui-tui/src/app/slash/commands/core.ts +31 -2
- package/agent/ui-tui/src/app/slash/commands/credits.ts +57 -0
- package/agent/ui-tui/src/app/slash/commands/ops.ts +28 -0
- package/agent/ui-tui/src/app/slash/commands/session.ts +32 -4
- package/agent/ui-tui/src/app/slash/registry.ts +4 -0
- package/agent/ui-tui/src/app/turnController.ts +145 -2
- package/agent/ui-tui/src/app/uiStore.ts +2 -0
- package/agent/ui-tui/src/app/useInputHandlers.ts +42 -4
- package/agent/ui-tui/src/app/useMainApp.ts +54 -8
- package/agent/ui-tui/src/app/useSessionLifecycle.ts +40 -31
- package/agent/ui-tui/src/app/useSubmission.ts +23 -31
- package/agent/ui-tui/src/components/appChrome.tsx +112 -5
- package/agent/ui-tui/src/components/appLayout.tsx +9 -0
- package/agent/ui-tui/src/components/appOverlays.tsx +25 -1
- package/agent/ui-tui/src/components/billingOverlay.tsx +684 -0
- package/agent/ui-tui/src/components/branding.tsx +15 -3
- package/agent/ui-tui/src/components/messageLine.tsx +25 -3
- package/agent/ui-tui/src/components/pluginsHub.tsx +238 -0
- package/agent/ui-tui/src/components/prompts.tsx +31 -17
- package/agent/ui-tui/src/components/streamingAssistant.tsx +63 -55
- package/agent/ui-tui/src/components/textInput.tsx +16 -0
- package/agent/ui-tui/src/config/env.ts +12 -0
- package/agent/ui-tui/src/config/limits.ts +13 -0
- package/agent/ui-tui/src/domain/blockLayout.ts +146 -0
- package/agent/ui-tui/src/domain/paths.ts +24 -0
- package/agent/ui-tui/src/domain/slash.ts +40 -0
- package/agent/ui-tui/src/entry.tsx +35 -4
- package/agent/ui-tui/src/gatewayClient.ts +22 -10
- package/agent/ui-tui/src/gatewayTypes.ts +130 -1
- package/agent/ui-tui/src/lib/gracefulExit.ts +24 -4
- package/agent/ui-tui/src/lib/memory.test.ts +162 -0
- package/agent/ui-tui/src/lib/memory.ts +60 -1
- package/agent/ui-tui/src/lib/memoryMonitor.ts +79 -4
- package/agent/ui-tui/src/lib/osc52.ts +1 -1
- package/agent/ui-tui/src/lib/text.test.ts +32 -1
- package/agent/ui-tui/src/lib/text.ts +29 -2
- package/agent/ui-tui/src/lib/virtualHeights.ts +13 -0
- package/agent/ui-tui/src/types.ts +5 -0
- package/agent/ui-tui/tsconfig.build.json +0 -1
- package/agent/ui-tui/tsconfig.json +2 -1
- package/agent/utils.py +66 -2
- package/agent/uv.lock +300 -684
- package/agent/web/index.html +2 -2
- package/agent/web/package.json +11 -6
- package/agent/web/public/claw-bg.webp +0 -0
- package/agent/web/public/claw-logo.webp +0 -0
- package/agent/web/src/App.tsx +138 -48
- package/agent/web/src/components/AutomationBlueprints.tsx +225 -0
- package/agent/web/src/components/Backdrop.tsx +15 -0
- package/agent/web/src/components/ChatSessionList.tsx +260 -0
- package/agent/web/src/components/ChatSidebar.tsx +262 -78
- package/agent/web/src/components/ConfirmDialog.tsx +122 -0
- package/agent/web/src/components/ModelPickerDialog.tsx +111 -16
- package/agent/web/src/components/ModelReloadConfirm.tsx +40 -0
- package/agent/web/src/components/ProfileScopeBanner.tsx +30 -0
- package/agent/web/src/components/ProfileSwitcher.tsx +67 -0
- package/agent/web/src/components/ReasoningPicker.tsx +167 -0
- package/agent/web/src/components/SkillEditorDialog.tsx +215 -0
- package/agent/web/src/components/ThemeSwitcher.tsx +119 -4
- package/agent/web/src/components/ToolsetConfigDrawer.tsx +457 -0
- package/agent/web/src/contexts/PageHeaderProvider.tsx +7 -4
- package/agent/web/src/contexts/ProfileProvider.tsx +137 -0
- package/agent/web/src/contexts/SystemActions.tsx +6 -8
- package/agent/web/src/contexts/profile-context.ts +19 -0
- package/agent/web/src/contexts/useProfileScope.ts +6 -0
- package/agent/web/src/i18n/af.ts +5 -4
- package/agent/web/src/i18n/de.ts +5 -4
- package/agent/web/src/i18n/en.ts +58 -4
- package/agent/web/src/i18n/es.ts +5 -3
- package/agent/web/src/i18n/fr.ts +5 -3
- package/agent/web/src/i18n/ga.ts +5 -4
- package/agent/web/src/i18n/hu.ts +5 -4
- package/agent/web/src/i18n/it.ts +5 -4
- package/agent/web/src/i18n/ja.ts +5 -4
- package/agent/web/src/i18n/ko.ts +5 -4
- package/agent/web/src/i18n/pt.ts +5 -3
- package/agent/web/src/i18n/ru.ts +5 -4
- package/agent/web/src/i18n/tr.ts +5 -4
- package/agent/web/src/i18n/types.ts +59 -1
- package/agent/web/src/i18n/uk.ts +5 -3
- package/agent/web/src/i18n/zh-hant.ts +5 -4
- package/agent/web/src/i18n/zh.ts +5 -4
- package/agent/web/src/index.css +2 -2
- package/agent/web/src/lib/api.ts +819 -52
- package/agent/web/src/lib/dashboard-flags.ts +16 -7
- package/agent/web/src/lib/reasoning-effort.test.ts +48 -0
- package/agent/web/src/lib/reasoning-effort.ts +36 -0
- package/agent/web/src/lib/session-refresh.test.ts +21 -0
- package/agent/web/src/lib/session-refresh.ts +26 -0
- package/agent/web/src/pages/ChannelsPage.tsx +529 -68
- package/agent/web/src/pages/ChatPage.tsx +249 -56
- package/agent/web/src/pages/ConfigPage.tsx +11 -1
- package/agent/web/src/pages/CronPage.tsx +219 -31
- package/agent/web/src/pages/EnvPage.tsx +25 -6
- package/agent/web/src/pages/FilesPage.tsx +525 -0
- package/agent/web/src/pages/McpPage.tsx +80 -3
- package/agent/web/src/pages/ModelsPage.tsx +97 -12
- package/agent/web/src/pages/PluginsPage.tsx +1 -1
- package/agent/web/src/pages/ProfileBuilderPage.tsx +611 -0
- package/agent/web/src/pages/ProfilesPage.tsx +1038 -172
- package/agent/web/src/pages/SessionsPage.tsx +144 -13
- package/agent/web/src/pages/SkillsPage.tsx +851 -70
- package/agent/web/src/pages/SystemPage.tsx +340 -4
- package/agent/web/src/pages/WalletPage.tsx +401 -0
- package/agent/web/src/pages/WebhooksPage.tsx +145 -15
- package/agent/web/src/pages/X402Page.tsx +207 -0
- package/agent/web/src/plugins/registry.ts +28 -11
- package/agent/web/src/plugins/sdk.d.ts +160 -0
- package/agent/web/src/themes/context.tsx +112 -5
- package/agent/web/src/themes/fonts.ts +167 -0
- package/agent/web/src/themes/index.ts +7 -0
- package/agent/web/tsconfig.app.json +0 -1
- package/agent/web/vite.config.ts +1 -8
- package/agent/web/vitest.config.ts +16 -0
- package/package.json +1 -1
- package/agent/apps/desktop/package-lock.json +0 -18363
- package/agent/apps/desktop/src/app/chat/composer/skin-slash-popover.tsx +0 -56
- package/agent/apps/desktop/src/components/assistant-ui/thread-virtualizer.tsx +0 -382
- package/agent/apps/desktop/src/components/assistant-ui/todo-tool.tsx +0 -109
- package/agent/apps/desktop/src/components/chat/generated-image-context.tsx +0 -19
- package/agent/optional-skills/productivity/shop-app/SKILL.md +0 -340
- package/agent/skills/autonomous-ai-agents/kanban-codex-lane/SKILL.md +0 -277
- package/agent/skills/autonomous-ai-agents/kanban-codex-lane/templates/pmb-codex-lane-prompt.md +0 -57
- package/agent/skills/diagramming/DESCRIPTION.md +0 -3
- package/agent/skills/domain/DESCRIPTION.md +0 -24
- package/agent/skills/gifs/DESCRIPTION.md +0 -3
- package/agent/skills/inference-sh/DESCRIPTION.md +0 -19
- package/agent/skills/mcp/DESCRIPTION.md +0 -3
- package/agent/skills/media/spotify/SKILL.md +0 -135
- package/agent/skills/mlops/training/DESCRIPTION.md +0 -3
- package/agent/skills/mlops/vector-databases/DESCRIPTION.md +0 -3
- package/agent/skills/productivity/linear/SKILL.md +0 -380
- package/agent/skills/productivity/linear/scripts/linear_api.py +0 -445
- package/agent/skills/software-development/debugging-hermes-tui-commands/SKILL.md +0 -152
- package/agent/skills/software-development/writing-plans/SKILL.md +0 -297
- package/agent/ui-tui/package-lock.json +0 -7449
- package/agent/ui-tui/packages/hermes-ink/package-lock.json +0 -1289
- package/agent/web/package-lock.json +0 -8887
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/PORT_NOTES.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/prompts/system.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/macaron.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/mono-ink.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/neon.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/palettes/warm.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/prompt-construction.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/style-presets.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/blueprint.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/chalkboard.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/editorial.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/elegant.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/fantasy-animation.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/flat-doodle.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/flat.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/ink-notes.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/intuition-machine.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/minimal.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/nature.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/notion.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/pixel-art.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/playful.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/retro.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/scientific.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/screen-print.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/sketch-notes.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/sketch.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/vector-illustration.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/vintage.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/warm.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles/watercolor.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/styles.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/usage.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-article-illustrator/references/workflow.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/PORT_NOTES.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/analysis-framework.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/chalk.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/ink-brush.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/ligne-claire.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/manga.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/minimalist.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/art-styles/realistic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/auto-selection.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/base-prompt.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/character-template.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/cinematic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/dense.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/four-panel.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/mixed.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/splash.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/standard.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/layouts/webtoon.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/ohmsha-guide.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/partial-workflows.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/concept-story.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/four-panel.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/ohmsha.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/shoujo.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/presets/wuxia.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/storyboard-template.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/action.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/dramatic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/energetic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/neutral.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/romantic.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/vintage.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/tones/warm.md +0 -0
- /package/agent/{skills → optional-skills}/creative/baoyu-comic/references/workflow.md +0 -0
- /package/agent/{skills → optional-skills}/creative/creative-ideation/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/creative-ideation/references/full-prompt-library.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/ATTRIBUTION.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/references/palettes.md +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/__init__.py +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/palettes.py +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/pixel_art.py +0 -0
- /package/agent/{skills → optional-skills}/creative/pixel-art/scripts/pixel_art_video.py +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/SKILL.md +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/references/analysis-modules.md +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/references/methods-guide.md +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/abliteration-config.yaml +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/analysis-study.yaml +0 -0
- /package/agent/{skills/mlops/inference → optional-skills/mlops}/obliteratus/templates/batch-abliteration.yaml +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/DESCRIPTION.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/SKILL.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/references/examples.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/references/modules.md +0 -0
- /package/agent/{skills → optional-skills}/mlops/research/dspy/references/optimizers.md +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/references/jailbreak-templates.md +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/references/refusal-detection.md +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/godmode_race.py +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/load_godmode.py +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/scripts/parseltongue.py +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/templates/prefill-subtle.json +0 -0
- /package/agent/{skills/red-teaming → optional-skills/security}/godmode/templates/prefill.json +0 -0
- /package/agent/{skills → optional-skills}/software-development/subagent-driven-development/references/context-budget-discipline.md +0 -0
- /package/agent/{skills → optional-skills}/software-development/subagent-driven-development/references/gates-taxonomy.md +0 -0
|
@@ -21,6 +21,12 @@ The failure modes we've seen in the wild:
|
|
|
21
21
|
optional fields (common Pydantic/MCP shape). Anthropic rejects these at
|
|
22
22
|
the top of ``input_schema``; collapse them to the non-null branch.
|
|
23
23
|
* Unconstrained ``additionalProperties`` on objects with empty properties.
|
|
24
|
+
* ``default`` (and other annotation keywords) alongside ``$ref`` — strict
|
|
25
|
+
backends (Fireworks-hosted Kimi, JSON Schema draft-07 validators) reject
|
|
26
|
+
sibling keywords at the same level as ``$ref``. Common MCP/Pydantic shape
|
|
27
|
+
after nullable-union collapse::
|
|
28
|
+
|
|
29
|
+
{"$ref": "#/$defs/Foo", "default": null}
|
|
24
30
|
|
|
25
31
|
This module walks the final tool schema tree (after MCP-level normalization
|
|
26
32
|
and any per-tool dynamic rebuilds) and fixes the known-hostile constructs
|
|
@@ -90,6 +96,35 @@ def _sanitize_single_tool(tool: dict) -> dict:
|
|
|
90
96
|
fn["parameters"] = _strip_top_level_combinators(
|
|
91
97
|
fn["parameters"], path=fn.get("name", "<tool>")
|
|
92
98
|
)
|
|
99
|
+
fn["parameters"] = _strip_ref_siblings(fn["parameters"])
|
|
100
|
+
return out
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Sibling keywords strict JSON Schema validators reject alongside ``$ref``.
|
|
104
|
+
_REF_FORBIDDEN_SIBLINGS = frozenset({"default"})
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _strip_ref_siblings(node: Any) -> Any:
|
|
108
|
+
"""Drop forbidden sibling keywords from nodes that carry ``$ref``.
|
|
109
|
+
|
|
110
|
+
Fireworks (and other draft-07-strict backends) fail tool requests with::
|
|
111
|
+
|
|
112
|
+
JSON Schema not supported: keyword(s) ['default'] not allowed at
|
|
113
|
+
the same level as $ref.
|
|
114
|
+
|
|
115
|
+
Nullable-union collapse and MCP ingestion can leave ``default`` on a
|
|
116
|
+
``$ref`` node; strip it recursively.
|
|
117
|
+
"""
|
|
118
|
+
if isinstance(node, list):
|
|
119
|
+
return [_strip_ref_siblings(item) for item in node]
|
|
120
|
+
if not isinstance(node, dict):
|
|
121
|
+
return node
|
|
122
|
+
|
|
123
|
+
out = {key: _strip_ref_siblings(value) for key, value in node.items()}
|
|
124
|
+
if "$ref" in out:
|
|
125
|
+
for key in _REF_FORBIDDEN_SIBLINGS:
|
|
126
|
+
if key in out:
|
|
127
|
+
out.pop(key, None)
|
|
93
128
|
return out
|
|
94
129
|
|
|
95
130
|
|
|
@@ -185,6 +220,9 @@ def strip_nullable_unions(
|
|
|
185
220
|
replacement.setdefault("nullable", True)
|
|
186
221
|
for meta_key in ("title", "description", "default", "examples"):
|
|
187
222
|
if meta_key in stripped and meta_key not in replacement:
|
|
223
|
+
# ``default`` is illegal alongside ``$ref`` on strict backends.
|
|
224
|
+
if meta_key == "default" and "$ref" in replacement:
|
|
225
|
+
continue
|
|
188
226
|
replacement[meta_key] = stripped[meta_key]
|
|
189
227
|
return strip_nullable_unions(replacement, keep_nullable_hint=keep_nullable_hint)
|
|
190
228
|
return stripped
|
|
@@ -38,8 +38,16 @@ _NUMERIC_TOPIC_RE = _TELEGRAM_TOPIC_TARGET_RE
|
|
|
38
38
|
# below and falls through to channel-name resolution, which has no way to
|
|
39
39
|
# resolve a raw phone number. Keeping the '+' preserves the E.164 form that
|
|
40
40
|
# downstream adapters (signal, etc.) expect.
|
|
41
|
-
_PHONE_PLATFORMS = frozenset({"signal", "sms", "whatsapp"})
|
|
41
|
+
_PHONE_PLATFORMS = frozenset({"photon", "signal", "sms", "whatsapp"})
|
|
42
42
|
_E164_TARGET_RE = re.compile(r"^\s*\+(\d{7,15})\s*$")
|
|
43
|
+
# WhatsApp JIDs: group chats (<digits>@g.us), individual users
|
|
44
|
+
# (<phone>@s.whatsapp.net), linked identities (<id>@lid), and broadcast /
|
|
45
|
+
# newsletter chats. These are explicit native targets the bridge accepts
|
|
46
|
+
# verbatim — they must NOT fall through to home-channel resolution.
|
|
47
|
+
_WHATSAPP_JID_RE = re.compile(
|
|
48
|
+
r"^\s*[\w-]+@(?:g\.us|s\.whatsapp\.net|lid|broadcast|newsletter)\s*$",
|
|
49
|
+
re.IGNORECASE,
|
|
50
|
+
)
|
|
43
51
|
# Email addresses — a valid email like "user@domain.com" should be treated as
|
|
44
52
|
# an explicit target for the email platform, not fall through to channel-name
|
|
45
53
|
# resolution which has no way to resolve a raw address.
|
|
@@ -138,16 +146,24 @@ SEND_MESSAGE_SCHEMA = {
|
|
|
138
146
|
"properties": {
|
|
139
147
|
"action": {
|
|
140
148
|
"type": "string",
|
|
141
|
-
"enum": ["send", "list"],
|
|
142
|
-
"description": "Action to perform. 'send' (default) sends a message. 'list' returns all available channels/contacts across connected platforms."
|
|
149
|
+
"enum": ["send", "list", "react", "unreact"],
|
|
150
|
+
"description": "Action to perform. 'send' (default) sends a message. 'list' returns all available channels/contacts across connected platforms. 'react' attaches an emoji reaction to a message (platforms that support it, e.g. photon/iMessage tapbacks). 'unreact' retracts a previously-added reaction."
|
|
143
151
|
},
|
|
144
152
|
"target": {
|
|
145
153
|
"type": "string",
|
|
146
|
-
"description": "Delivery target. Format: 'platform' (uses home channel), 'platform:#channel-name', 'platform:chat_id', or 'platform:chat_id:thread_id' for Telegram topics and Discord threads. Examples: 'telegram', 'telegram:-1001234567890:17585', 'discord:999888777:555444333', 'discord:#bot-home', 'slack:#engineering', 'signal:+155****4567', 'matrix:!roomid:server.org', 'matrix:@user:server.org', 'yuanbao:direct:<account_id>' (DM), 'yuanbao:group:<group_code>' (group chat)"
|
|
154
|
+
"description": "Delivery target. Format: 'platform' (uses home channel), 'platform:#channel-name', 'platform:chat_id', or 'platform:chat_id:thread_id' for Telegram topics and Discord threads. Examples: 'telegram', 'telegram:-1001234567890:17585', 'discord:999888777:555444333', 'discord:#bot-home', 'slack:#engineering', 'signal:+155****4567', 'matrix:!roomid:server.org', 'matrix:@user:server.org', 'ntfy:alerts-channel' (explicit ntfy topic), 'yuanbao:direct:<account_id>' (DM), 'yuanbao:group:<group_code>' (group chat)"
|
|
147
155
|
},
|
|
148
156
|
"message": {
|
|
149
157
|
"type": "string",
|
|
150
158
|
"description": "The message text to send. To send an image or file, include MEDIA:<local_path> (e.g. 'MEDIA:/tmp/report.pdf') in the message — the platform will deliver it as a native media attachment."
|
|
159
|
+
},
|
|
160
|
+
"emoji": {
|
|
161
|
+
"type": "string",
|
|
162
|
+
"description": "For action='react': the emoji to react with (e.g. '❤️'). On iMessage, ❤️👍👎😂‼️❓ render as native tapbacks; other emoji use custom-emoji reactions."
|
|
163
|
+
},
|
|
164
|
+
"message_id": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"description": "For action='react'/'unreact': id of the message to react to. Omit to target the most recent message received in that chat (usually the one being replied to)."
|
|
151
167
|
}
|
|
152
168
|
},
|
|
153
169
|
"required": []
|
|
@@ -162,6 +178,12 @@ def send_message_tool(args, **kw):
|
|
|
162
178
|
if action == "list":
|
|
163
179
|
return _handle_list()
|
|
164
180
|
|
|
181
|
+
if action == "react":
|
|
182
|
+
return _handle_react(args)
|
|
183
|
+
|
|
184
|
+
if action == "unreact":
|
|
185
|
+
return _handle_react(args, remove=True)
|
|
186
|
+
|
|
165
187
|
return _handle_send(args)
|
|
166
188
|
|
|
167
189
|
|
|
@@ -174,6 +196,98 @@ def _handle_list():
|
|
|
174
196
|
return json.dumps(_error(f"Failed to load channel directory: {e}"))
|
|
175
197
|
|
|
176
198
|
|
|
199
|
+
def _handle_react(args, remove=False):
|
|
200
|
+
"""Attach (or with ``remove=True`` retract) an emoji reaction on a message
|
|
201
|
+
via a live gateway adapter.
|
|
202
|
+
|
|
203
|
+
Only adapters that expose ``add_reaction(chat_id, emoji, message_id)`` /
|
|
204
|
+
``remove_reaction(chat_id, message_id)`` coroutines support this (e.g.
|
|
205
|
+
photon/iMessage tapbacks). Requires the gateway to be running in this
|
|
206
|
+
process — there is no standalone fallback, since reacting needs the
|
|
207
|
+
adapter's live message-id state.
|
|
208
|
+
"""
|
|
209
|
+
target = args.get("target", "")
|
|
210
|
+
emoji = (args.get("emoji") or "").strip()
|
|
211
|
+
message_id = (args.get("message_id") or "").strip() or None
|
|
212
|
+
if not target or (not remove and not emoji):
|
|
213
|
+
return tool_error(
|
|
214
|
+
"Both 'target' and 'emoji' are required when action='react'"
|
|
215
|
+
if not remove
|
|
216
|
+
else "'target' is required when action='unreact'"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
parts = target.split(":", 1)
|
|
220
|
+
platform_name = parts[0].strip().lower()
|
|
221
|
+
target_ref = parts[1].strip() if len(parts) > 1 else None
|
|
222
|
+
chat_id = None
|
|
223
|
+
if target_ref:
|
|
224
|
+
chat_id, _thread_id, _ = _parse_target_ref(platform_name, target_ref)
|
|
225
|
+
if not chat_id:
|
|
226
|
+
try:
|
|
227
|
+
from gateway.channel_directory import resolve_channel_name
|
|
228
|
+
resolved = resolve_channel_name(platform_name, target_ref)
|
|
229
|
+
except Exception:
|
|
230
|
+
resolved = None
|
|
231
|
+
# Opaque platform-native ids (e.g. photon space GUIDs like
|
|
232
|
+
# 'any;-;+1555...') match no parser pattern and no directory
|
|
233
|
+
# entry — pass them through verbatim; the adapter validates.
|
|
234
|
+
chat_id = resolved or target_ref
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
from gateway.config import Platform, load_gateway_config
|
|
238
|
+
platform = Platform(platform_name)
|
|
239
|
+
except (ValueError, KeyError):
|
|
240
|
+
return tool_error(f"Unknown platform: {platform_name}")
|
|
241
|
+
|
|
242
|
+
if not chat_id:
|
|
243
|
+
try:
|
|
244
|
+
config = load_gateway_config()
|
|
245
|
+
home = config.get_home_channel(platform)
|
|
246
|
+
except Exception:
|
|
247
|
+
home = None
|
|
248
|
+
if not home:
|
|
249
|
+
return tool_error(
|
|
250
|
+
f"No chat specified and no home channel set for {platform_name}. "
|
|
251
|
+
f"Use '{platform_name}:chat_id'."
|
|
252
|
+
)
|
|
253
|
+
chat_id = home.chat_id
|
|
254
|
+
|
|
255
|
+
runner = None
|
|
256
|
+
try:
|
|
257
|
+
from gateway.run import _gateway_runner_ref
|
|
258
|
+
runner = _gateway_runner_ref()
|
|
259
|
+
except Exception:
|
|
260
|
+
runner = None
|
|
261
|
+
adapter = runner.adapters.get(platform) if runner is not None else None
|
|
262
|
+
if adapter is None:
|
|
263
|
+
return tool_error(
|
|
264
|
+
f"Reactions require a live {platform_name} adapter in the running "
|
|
265
|
+
"gateway (not available from cron/standalone contexts)."
|
|
266
|
+
)
|
|
267
|
+
fn_name = "remove_reaction" if remove else "add_reaction"
|
|
268
|
+
react_fn = getattr(adapter, fn_name, None)
|
|
269
|
+
if not callable(react_fn):
|
|
270
|
+
return tool_error(
|
|
271
|
+
f"Platform '{platform_name}' does not support message reactions."
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
try:
|
|
275
|
+
from model_tools import _run_async
|
|
276
|
+
if remove:
|
|
277
|
+
result = _run_async(
|
|
278
|
+
react_fn(chat_id=chat_id, message_id=message_id)
|
|
279
|
+
)
|
|
280
|
+
else:
|
|
281
|
+
result = _run_async(
|
|
282
|
+
react_fn(chat_id=chat_id, emoji=emoji, message_id=message_id)
|
|
283
|
+
)
|
|
284
|
+
except Exception as e:
|
|
285
|
+
return json.dumps(_error(f"Reaction failed: {e}"))
|
|
286
|
+
if isinstance(result, dict):
|
|
287
|
+
return json.dumps(result)
|
|
288
|
+
return json.dumps({"success": bool(result)})
|
|
289
|
+
|
|
290
|
+
|
|
177
291
|
def _handle_send(args):
|
|
178
292
|
"""Send a message to a platform target."""
|
|
179
293
|
target = args.get("target", "")
|
|
@@ -395,10 +509,20 @@ def _parse_target_ref(platform_name: str, target_ref: str):
|
|
|
395
509
|
if target_ref.strip().isdigit():
|
|
396
510
|
return f"group:{target_ref.strip()}", None, True
|
|
397
511
|
return None, None, False
|
|
512
|
+
if platform_name == "ntfy":
|
|
513
|
+
topic = target_ref.strip()
|
|
514
|
+
if topic:
|
|
515
|
+
return topic, None, True
|
|
398
516
|
if platform_name == "email":
|
|
399
517
|
match = _EMAIL_TARGET_RE.fullmatch(target_ref)
|
|
400
518
|
if match:
|
|
401
519
|
return target_ref.strip(), None, True
|
|
520
|
+
if platform_name == "whatsapp":
|
|
521
|
+
# Native WhatsApp JIDs (group @g.us, user @s.whatsapp.net, @lid, etc.)
|
|
522
|
+
# are explicit targets — pass through verbatim. E.164 '+' numbers fall
|
|
523
|
+
# through to the _PHONE_PLATFORMS handler below.
|
|
524
|
+
if _WHATSAPP_JID_RE.fullmatch(target_ref):
|
|
525
|
+
return target_ref.strip(), None, True
|
|
402
526
|
if platform_name in _PHONE_PLATFORMS:
|
|
403
527
|
match = _E164_TARGET_RE.fullmatch(target_ref)
|
|
404
528
|
if match:
|
|
@@ -502,6 +626,7 @@ async def _send_via_adapter(
|
|
|
502
626
|
the runner weakref is ``None``).
|
|
503
627
|
3. A descriptive error explaining both options.
|
|
504
628
|
"""
|
|
629
|
+
platform_name = platform.value if hasattr(platform, "value") else str(platform)
|
|
505
630
|
runner = None
|
|
506
631
|
try:
|
|
507
632
|
from gateway.run import _gateway_runner_ref
|
|
@@ -516,7 +641,13 @@ async def _send_via_adapter(
|
|
|
516
641
|
adapter = None
|
|
517
642
|
if adapter is not None:
|
|
518
643
|
try:
|
|
519
|
-
metadata = {
|
|
644
|
+
metadata = {}
|
|
645
|
+
if thread_id:
|
|
646
|
+
metadata["thread_id"] = thread_id
|
|
647
|
+
if platform_name == "ntfy" and chat_id:
|
|
648
|
+
metadata["publish_topic"] = chat_id
|
|
649
|
+
if not metadata:
|
|
650
|
+
metadata = None
|
|
520
651
|
result = await adapter.send(chat_id=chat_id, content=chunk, metadata=metadata)
|
|
521
652
|
except asyncio.CancelledError:
|
|
522
653
|
raise
|
|
@@ -526,7 +657,6 @@ async def _send_via_adapter(
|
|
|
526
657
|
return {"success": True, "message_id": result.message_id}
|
|
527
658
|
return {"error": f"Adapter send failed: {result.error}"}
|
|
528
659
|
|
|
529
|
-
platform_name = platform.value if hasattr(platform, "value") else str(platform)
|
|
530
660
|
entry = None
|
|
531
661
|
try:
|
|
532
662
|
from gateway.platform_registry import platform_registry
|
|
@@ -578,6 +708,16 @@ async def _send_to_platform(platform, pconfig, chat_id, message, thread_id=None,
|
|
|
578
708
|
(preserves code-block boundaries, adds part indicators).
|
|
579
709
|
"""
|
|
580
710
|
from gateway.config import Platform
|
|
711
|
+
|
|
712
|
+
media_files = media_files or []
|
|
713
|
+
|
|
714
|
+
# Weixin handles text/media delivery inside its native helper and does not
|
|
715
|
+
# need the optional platform adapter imports below. Keep this branch early
|
|
716
|
+
# so a Weixin send is not blocked by unrelated optional dependencies (for
|
|
717
|
+
# example lark-oapi's heavy Feishu import path).
|
|
718
|
+
if platform == Platform.WEIXIN:
|
|
719
|
+
return await _send_weixin(pconfig, chat_id, message, media_files=media_files)
|
|
720
|
+
|
|
581
721
|
from gateway.platforms.base import BasePlatformAdapter, utf16_len
|
|
582
722
|
from gateway.platforms.slack import SlackAdapter
|
|
583
723
|
|
|
@@ -595,8 +735,6 @@ async def _send_to_platform(platform, pconfig, chat_id, message, thread_id=None,
|
|
|
595
735
|
except ImportError:
|
|
596
736
|
_feishu_available = False
|
|
597
737
|
|
|
598
|
-
media_files = media_files or []
|
|
599
|
-
|
|
600
738
|
if platform == Platform.SLACK and message:
|
|
601
739
|
try:
|
|
602
740
|
slack_adapter = SlackAdapter.__new__(SlackAdapter)
|
|
@@ -653,10 +791,6 @@ async def _send_to_platform(platform, pconfig, chat_id, message, thread_id=None,
|
|
|
653
791
|
last_result = result
|
|
654
792
|
return last_result
|
|
655
793
|
|
|
656
|
-
# --- Weixin: use the native one-shot adapter helper for text + media ---
|
|
657
|
-
if platform == Platform.WEIXIN:
|
|
658
|
-
return await _send_weixin(pconfig, chat_id, message, media_files=media_files)
|
|
659
|
-
|
|
660
794
|
# --- Discord: chunked delivery via the registry's standalone_sender_fn.
|
|
661
795
|
# The plugin's ``_standalone_send`` (registered in
|
|
662
796
|
# plugins/platforms/discord/adapter.py) handles forum channels, threads,
|
|
@@ -767,7 +901,7 @@ async def _send_to_platform(platform, pconfig, chat_id, message, thread_id=None,
|
|
|
767
901
|
last_result = None
|
|
768
902
|
for chunk in chunks:
|
|
769
903
|
if platform == Platform.SLACK:
|
|
770
|
-
result = await _send_slack(pconfig.token, chat_id, chunk)
|
|
904
|
+
result = await _send_slack(pconfig.token, chat_id, chunk, thread_ts=thread_id)
|
|
771
905
|
elif platform == Platform.WHATSAPP:
|
|
772
906
|
result = await _send_whatsapp(pconfig.extra, chat_id, chunk)
|
|
773
907
|
elif platform == Platform.SIGNAL:
|
|
@@ -778,8 +912,6 @@ async def _send_to_platform(platform, pconfig, chat_id, message, thread_id=None,
|
|
|
778
912
|
result = await _send_sms(pconfig.api_key, chat_id, chunk)
|
|
779
913
|
elif platform == Platform.MATRIX:
|
|
780
914
|
result = await _send_matrix(pconfig.token, pconfig.extra, chat_id, chunk)
|
|
781
|
-
elif platform == Platform.HOMEASSISTANT:
|
|
782
|
-
result = await _send_homeassistant(pconfig.token, pconfig.extra, chat_id, chunk)
|
|
783
915
|
elif platform == Platform.DINGTALK:
|
|
784
916
|
result = await _send_dingtalk(pconfig.extra, chat_id, chunk)
|
|
785
917
|
elif platform == Platform.FEISHU:
|
|
@@ -1049,7 +1181,7 @@ async def _send_telegram(token, chat_id, message, media_files=None, thread_id=No
|
|
|
1049
1181
|
return _error(f"Telegram send failed: {e}")
|
|
1050
1182
|
|
|
1051
1183
|
|
|
1052
|
-
async def _send_slack(token, chat_id, message):
|
|
1184
|
+
async def _send_slack(token, chat_id, message, thread_ts=None):
|
|
1053
1185
|
"""Send via Slack Web API."""
|
|
1054
1186
|
try:
|
|
1055
1187
|
import aiohttp
|
|
@@ -1063,6 +1195,8 @@ async def _send_slack(token, chat_id, message):
|
|
|
1063
1195
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
|
1064
1196
|
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30), **_sess_kw) as session:
|
|
1065
1197
|
payload = {"channel": chat_id, "text": message, "mrkdwn": True}
|
|
1198
|
+
if thread_ts:
|
|
1199
|
+
payload["thread_ts"] = thread_ts
|
|
1066
1200
|
async with session.post(url, headers=headers, json=payload, **_req_kw) as resp:
|
|
1067
1201
|
data = await resp.json()
|
|
1068
1202
|
if data.get("ok"):
|
|
@@ -1474,29 +1608,6 @@ async def _send_matrix_via_adapter(pconfig, chat_id, message, media_files=None,
|
|
|
1474
1608
|
pass
|
|
1475
1609
|
|
|
1476
1610
|
|
|
1477
|
-
async def _send_homeassistant(token, extra, chat_id, message):
|
|
1478
|
-
"""Send via Home Assistant notify service."""
|
|
1479
|
-
try:
|
|
1480
|
-
import aiohttp
|
|
1481
|
-
except ImportError:
|
|
1482
|
-
return {"error": "aiohttp not installed. Run: pip install aiohttp"}
|
|
1483
|
-
try:
|
|
1484
|
-
hass_url = (extra.get("url") or os.getenv("HASS_URL", "")).rstrip("/")
|
|
1485
|
-
token = token or os.getenv("HASS_TOKEN", "")
|
|
1486
|
-
if not hass_url or not token:
|
|
1487
|
-
return {"error": "Home Assistant not configured (HASS_URL, HASS_TOKEN required)"}
|
|
1488
|
-
url = f"{hass_url}/api/services/notify/notify"
|
|
1489
|
-
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
|
1490
|
-
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30)) as session:
|
|
1491
|
-
async with session.post(url, headers=headers, json={"message": message, "target": chat_id}) as resp:
|
|
1492
|
-
if resp.status not in {200, 201}:
|
|
1493
|
-
body = await resp.text()
|
|
1494
|
-
return _error(f"Home Assistant API error ({resp.status}): {body}")
|
|
1495
|
-
return {"success": True, "platform": "homeassistant", "chat_id": chat_id}
|
|
1496
|
-
except Exception as e:
|
|
1497
|
-
return _error(f"Home Assistant send failed: {e}")
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
1611
|
async def _send_dingtalk(extra, chat_id, message):
|
|
1501
1612
|
"""Send via DingTalk robot webhook.
|
|
1502
1613
|
|
|
@@ -1788,13 +1899,16 @@ async def _send_yuanbao(chat_id, message, media_files=None):
|
|
|
1788
1899
|
|
|
1789
1900
|
|
|
1790
1901
|
# --- Registry ---
|
|
1791
|
-
from tools.registry import
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
)
|
|
1902
|
+
from tools.registry import tool_error
|
|
1903
|
+
|
|
1904
|
+
# NOTE: ``send_message`` is intentionally NOT registered as an agent-callable
|
|
1905
|
+
# model tool. The agent should not decide on its own to fire off cross-platform
|
|
1906
|
+
# messages or reactions. The send engine in this module (``_send_to_platform``,
|
|
1907
|
+
# ``_send_via_adapter``, ``_parse_target_ref``, the per-platform ``_send_*``
|
|
1908
|
+
# helpers) remains the shared transport used by:
|
|
1909
|
+
# - cron delivery (cron/scheduler.py)
|
|
1910
|
+
# - the ``hermes send`` CLI command (hermes_cli/send_cmd.py)
|
|
1911
|
+
# - the gateway kanban notifier (dashboard-toggled, outside agent control)
|
|
1912
|
+
# - the standalone MCP server (mcp_serve.py), which is an opt-in surface
|
|
1913
|
+
# Those callers import the helpers directly; none of them need the registry
|
|
1914
|
+
# entry.
|
|
@@ -34,9 +34,10 @@ import logging
|
|
|
34
34
|
from typing import Any, Dict, List, Optional, Union
|
|
35
35
|
|
|
36
36
|
# Sources that are excluded from session browsing/searching by default.
|
|
37
|
-
# Third-party integrations tag their sessions with HERMES_SESSION_SOURCE=tool
|
|
38
|
-
#
|
|
39
|
-
|
|
37
|
+
# Third-party integrations tag their sessions with HERMES_SESSION_SOURCE=tool;
|
|
38
|
+
# delegate subagent runs are tagged "subagent" — neither belongs in the
|
|
39
|
+
# user's session history.
|
|
40
|
+
_HIDDEN_SESSION_SOURCES = ("subagent", "tool")
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def _format_timestamp(ts: Union[int, float, str, None]) -> str:
|
|
@@ -107,6 +108,122 @@ def _shape_message(m: Dict[str, Any], anchor_id: Optional[int] = None) -> Dict[s
|
|
|
107
108
|
return {k: v for k, v in entry.items() if v is not None or k in ("content",)}
|
|
108
109
|
|
|
109
110
|
|
|
111
|
+
def _resolve_profile_db(profile: str):
|
|
112
|
+
"""Open another profile's ``state.db`` read-only, or None for the current one.
|
|
113
|
+
|
|
114
|
+
The desktop's ``@session:<profile>/<id>`` links always carry the source
|
|
115
|
+
profile, so a linked session from profile B can be read while the agent
|
|
116
|
+
runs in profile A. ``read_only=True`` (mode=ro) takes no write lock — safe
|
|
117
|
+
to point at a live profile's DB, including our own. Returns None when no
|
|
118
|
+
profile is given (use the caller's default db).
|
|
119
|
+
"""
|
|
120
|
+
if profile is None or not str(profile).strip():
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
from hermes_cli import profiles as profiles_mod
|
|
124
|
+
from hermes_state import SessionDB
|
|
125
|
+
|
|
126
|
+
canon = profiles_mod.normalize_profile_name(profile)
|
|
127
|
+
profiles_mod.validate_profile_name(canon)
|
|
128
|
+
if not profiles_mod.profile_exists(canon):
|
|
129
|
+
raise ValueError(f"profile '{canon}' does not exist")
|
|
130
|
+
|
|
131
|
+
return SessionDB(db_path=profiles_mod.get_profile_dir(canon) / "state.db", read_only=True)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _locate_session_db(session_id: str):
|
|
135
|
+
"""Scan every profile's ``state.db`` (read-only) for a session id.
|
|
136
|
+
|
|
137
|
+
Returns ``(db, profile_name)`` for the first profile that owns the id, or
|
|
138
|
+
``(None, None)``. Session ids are globally unique (timestamp + random hex),
|
|
139
|
+
so the first hit is authoritative. This is the safety net for linked-session
|
|
140
|
+
reads where the model dropped the owning profile from the link and passed a
|
|
141
|
+
bare id — we find it wherever it actually lives instead of failing.
|
|
142
|
+
"""
|
|
143
|
+
from pathlib import Path
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
from hermes_cli import profiles as profiles_mod
|
|
147
|
+
from hermes_state import SessionDB
|
|
148
|
+
except Exception:
|
|
149
|
+
return None, None
|
|
150
|
+
|
|
151
|
+
targets = [("default", profiles_mod.get_profile_dir("default"))]
|
|
152
|
+
try:
|
|
153
|
+
targets += [(info.name, info.path) for info in profiles_mod.list_profiles()]
|
|
154
|
+
except Exception:
|
|
155
|
+
logging.debug("list_profiles failed during session locate", exc_info=True)
|
|
156
|
+
|
|
157
|
+
seen: set = set()
|
|
158
|
+
for name, home in targets:
|
|
159
|
+
db_path = Path(home) / "state.db"
|
|
160
|
+
key = str(db_path)
|
|
161
|
+
if key in seen or not db_path.exists():
|
|
162
|
+
continue
|
|
163
|
+
seen.add(key)
|
|
164
|
+
try:
|
|
165
|
+
pdb = SessionDB(db_path=db_path, read_only=True)
|
|
166
|
+
except Exception:
|
|
167
|
+
continue
|
|
168
|
+
try:
|
|
169
|
+
if pdb.get_session(session_id):
|
|
170
|
+
return pdb, name
|
|
171
|
+
except Exception:
|
|
172
|
+
logging.debug("get_session probe failed for %s in %s", session_id, name, exc_info=True)
|
|
173
|
+
pdb.close()
|
|
174
|
+
|
|
175
|
+
return None, None
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _read_session(db, session_id: str, head: int = 20, tail: int = 10) -> str:
|
|
179
|
+
"""Read shape: dump a whole session by id (head + tail when large).
|
|
180
|
+
|
|
181
|
+
Serves the linked-session case — the user dropped an @session reference and
|
|
182
|
+
the agent wants the transcript. Bounded payload: small sessions return in
|
|
183
|
+
full, large ones return the first ``head`` and last ``tail`` messages with a
|
|
184
|
+
pointer to scroll the middle.
|
|
185
|
+
"""
|
|
186
|
+
try:
|
|
187
|
+
meta = db.get_session(session_id) or {}
|
|
188
|
+
except Exception as e:
|
|
189
|
+
logging.debug("get_session failed for %s: %s", session_id, e, exc_info=True)
|
|
190
|
+
meta = {}
|
|
191
|
+
if not meta:
|
|
192
|
+
return tool_error(f"session_id not found: {session_id}", success=False)
|
|
193
|
+
|
|
194
|
+
try:
|
|
195
|
+
rows = db.get_messages(session_id)
|
|
196
|
+
except Exception as e:
|
|
197
|
+
logging.error("get_messages failed for %s: %s", session_id, e, exc_info=True)
|
|
198
|
+
return tool_error(f"failed to load session: {e}", success=False)
|
|
199
|
+
|
|
200
|
+
shaped = [_shape_message(m) for m in rows]
|
|
201
|
+
total = len(shaped)
|
|
202
|
+
truncated = total > head + tail
|
|
203
|
+
window = shaped[:head] + shaped[-tail:] if truncated else shaped
|
|
204
|
+
|
|
205
|
+
response = {
|
|
206
|
+
"success": True,
|
|
207
|
+
"mode": "read",
|
|
208
|
+
"session_id": session_id,
|
|
209
|
+
"session_meta": {
|
|
210
|
+
"when": _format_timestamp(meta.get("started_at")),
|
|
211
|
+
"source": meta.get("source"),
|
|
212
|
+
"model": meta.get("model"),
|
|
213
|
+
"title": meta.get("title"),
|
|
214
|
+
},
|
|
215
|
+
"message_count": total,
|
|
216
|
+
"truncated": truncated,
|
|
217
|
+
"messages": window,
|
|
218
|
+
}
|
|
219
|
+
if truncated:
|
|
220
|
+
response["message"] = (
|
|
221
|
+
f"Session has {total} messages; showing first {head} + last {tail}. "
|
|
222
|
+
"Pass around_message_id (any id above) to scroll the middle."
|
|
223
|
+
)
|
|
224
|
+
return json.dumps(response, ensure_ascii=False)
|
|
225
|
+
|
|
226
|
+
|
|
110
227
|
def _list_recent_sessions(db, limit: int, current_session_id: str = None) -> str:
|
|
111
228
|
"""Return metadata for the most recent sessions (no LLM calls, no FTS5)."""
|
|
112
229
|
try:
|
|
@@ -387,15 +504,19 @@ def session_search(
|
|
|
387
504
|
window: int = 5,
|
|
388
505
|
# Discovery shape
|
|
389
506
|
sort: str = None,
|
|
507
|
+
# Cross-profile (any shape)
|
|
508
|
+
profile: str = None,
|
|
390
509
|
) -> str:
|
|
391
510
|
"""Single-shape tool. Mode inferred from which args are set.
|
|
392
511
|
|
|
393
512
|
Discovery: pass ``query``.
|
|
394
513
|
Scroll: pass ``session_id`` + ``around_message_id``.
|
|
514
|
+
Read: pass ``session_id`` (no anchor) — dumps the whole session.
|
|
395
515
|
Browse: pass nothing.
|
|
396
516
|
|
|
397
|
-
|
|
398
|
-
|
|
517
|
+
Pass ``profile`` to read another profile's sessions (e.g. resolving an
|
|
518
|
+
``@session:<profile>/<id>`` link). Scroll wins over read/discovery when an
|
|
519
|
+
anchor is set — the agent has asked for a specific slice.
|
|
399
520
|
"""
|
|
400
521
|
if db is None:
|
|
401
522
|
try:
|
|
@@ -406,6 +527,30 @@ def session_search(
|
|
|
406
527
|
from hermes_state import format_session_db_unavailable
|
|
407
528
|
return tool_error(format_session_db_unavailable(), success=False)
|
|
408
529
|
|
|
530
|
+
# Normalise a raw `@session:<profile>/<id>` link value passed as session_id.
|
|
531
|
+
# Session ids never contain "/", so a slash unambiguously means profile/id —
|
|
532
|
+
# always strip the prefix off the id, and adopt the embedded profile only
|
|
533
|
+
# when one wasn't passed explicitly. Handles every permutation the model
|
|
534
|
+
# might send (full value as id, with or without a separate profile=).
|
|
535
|
+
if isinstance(session_id, str) and "/" in session_id:
|
|
536
|
+
emb_profile, _, emb_id = session_id.partition("/")
|
|
537
|
+
if emb_id:
|
|
538
|
+
session_id = emb_id
|
|
539
|
+
if emb_profile and (profile is None or not str(profile).strip()):
|
|
540
|
+
profile = emb_profile
|
|
541
|
+
|
|
542
|
+
# Cross-profile read: swap in the named profile's DB (read-only) for every
|
|
543
|
+
# shape below. The current-session-lineage guards no longer apply across
|
|
544
|
+
# profiles, but they key off ids that won't collide, so they stay inert.
|
|
545
|
+
if profile is not None and str(profile).strip():
|
|
546
|
+
try:
|
|
547
|
+
profile_db = _resolve_profile_db(profile)
|
|
548
|
+
except Exception as e:
|
|
549
|
+
return tool_error(f"profile '{profile}': {e}", success=False)
|
|
550
|
+
if profile_db is not None:
|
|
551
|
+
db = profile_db
|
|
552
|
+
current_session_id = None
|
|
553
|
+
|
|
409
554
|
# Scroll shape takes precedence — explicit anchor beats any query.
|
|
410
555
|
if (isinstance(session_id, str) and session_id.strip()) and around_message_id is not None:
|
|
411
556
|
return _scroll(
|
|
@@ -416,6 +561,27 @@ def session_search(
|
|
|
416
561
|
current_session_id=current_session_id,
|
|
417
562
|
)
|
|
418
563
|
|
|
564
|
+
# Read shape: a session_id with no anchor → dump the whole session.
|
|
565
|
+
if isinstance(session_id, str) and session_id.strip():
|
|
566
|
+
sid = session_id.strip()
|
|
567
|
+
result = _read_session(db, sid)
|
|
568
|
+
if json.loads(result).get("success"):
|
|
569
|
+
return result
|
|
570
|
+
|
|
571
|
+
# Miss in the target profile — the model may have dropped the owning
|
|
572
|
+
# profile from the link. Scan every profile and read it from wherever
|
|
573
|
+
# it lives, tagging the profile it was found in.
|
|
574
|
+
located, owner = _locate_session_db(sid)
|
|
575
|
+
if located is not None:
|
|
576
|
+
try:
|
|
577
|
+
found = json.loads(_read_session(located, sid))
|
|
578
|
+
finally:
|
|
579
|
+
located.close()
|
|
580
|
+
if found.get("success"):
|
|
581
|
+
found["profile"] = owner
|
|
582
|
+
return json.dumps(found, ensure_ascii=False)
|
|
583
|
+
return result
|
|
584
|
+
|
|
419
585
|
# Limit clamp [1, 10]
|
|
420
586
|
if not isinstance(limit, int):
|
|
421
587
|
try:
|
|
@@ -465,7 +631,7 @@ SESSION_SEARCH_SCHEMA = {
|
|
|
465
631
|
"Search past sessions stored in the local session DB, or scroll inside one. "
|
|
466
632
|
"FTS5-backed retrieval over the SQLite message store. No LLM calls — every "
|
|
467
633
|
"shape returns actual messages from the DB.\n\n"
|
|
468
|
-
"
|
|
634
|
+
"FOUR CALLING SHAPES\n\n"
|
|
469
635
|
" 1) DISCOVERY — pass `query`:\n"
|
|
470
636
|
" session_search(query=\"auth refactor\", limit=3)\n"
|
|
471
637
|
" Runs FTS5, dedupes hits by session lineage, returns the top N sessions. "
|
|
@@ -491,7 +657,13 @@ SESSION_SEARCH_SCHEMA = {
|
|
|
491
657
|
" - The boundary message appears in both windows — orientation marker.\n"
|
|
492
658
|
" - When messages_before or messages_after is < window, you're at the "
|
|
493
659
|
"start or end of the session.\n\n"
|
|
494
|
-
" 3)
|
|
660
|
+
" 3) READ — pass `session_id` only (no around_message_id):\n"
|
|
661
|
+
" session_search(session_id=\"...\", profile=\"work\")\n"
|
|
662
|
+
" Dumps the whole session by id (first 20 + last 10 messages when "
|
|
663
|
+
"large). This is how you resolve an `@session:<profile>/<id>` link the "
|
|
664
|
+
"user dropped into the chat: split the value on `/` into profile + id "
|
|
665
|
+
"and call session_search(session_id=id, profile=profile).\n\n"
|
|
666
|
+
" 4) BROWSE — no args:\n"
|
|
495
667
|
" session_search()\n"
|
|
496
668
|
" Returns recent sessions chronologically: titles, previews, timestamps. "
|
|
497
669
|
"Use when the user asks \"what was I working on\" without naming a topic.\n\n"
|
|
@@ -573,6 +745,15 @@ SESSION_SEARCH_SCHEMA = {
|
|
|
573
745
|
"behaviour) or 'tool' to search tool output only."
|
|
574
746
|
),
|
|
575
747
|
},
|
|
748
|
+
"profile": {
|
|
749
|
+
"type": "string",
|
|
750
|
+
"description": (
|
|
751
|
+
"Optional. Read sessions from another Hermes profile's database "
|
|
752
|
+
"(read-only). Use when resolving an `@session:<profile>/<id>` link: "
|
|
753
|
+
"pass the profile segment here with session_id as the id segment. "
|
|
754
|
+
"Omit to use the current profile."
|
|
755
|
+
),
|
|
756
|
+
},
|
|
576
757
|
},
|
|
577
758
|
"required": [],
|
|
578
759
|
},
|
|
@@ -594,6 +775,7 @@ registry.register(
|
|
|
594
775
|
around_message_id=args.get("around_message_id"),
|
|
595
776
|
window=args.get("window", 5),
|
|
596
777
|
sort=args.get("sort"),
|
|
778
|
+
profile=args.get("profile"),
|
|
597
779
|
db=kw.get("db"),
|
|
598
780
|
current_session_id=kw.get("current_session_id"),
|
|
599
781
|
),
|