@vellumai/assistant 0.6.1 → 0.6.3
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/bun.lock +40 -40
- package/bunfig.toml +3 -0
- package/docker-entrypoint.sh +12 -2
- package/docs/architecture/memory.md +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +184 -69
- package/package.json +41 -41
- package/scripts/generate-openapi.ts +1 -2
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/assistant-event-hub.test.ts +30 -0
- package/src/__tests__/browser-fill-credential.test.ts +229 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/catalog-files.test.ts +862 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/checker.test.ts +104 -170
- package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +125 -48
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/context-overflow-approval.test.ts +21 -6
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +1 -1
- package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
- package/src/__tests__/conversation-directories-parse.test.ts +105 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-queue.test.ts +45 -2
- package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +4 -4
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +2 -2
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/gemini-provider.test.ts +2 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +707 -371
- package/src/__tests__/headless-browser-navigate.test.ts +389 -47
- package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
- package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
- package/src/__tests__/host-bash-proxy.test.ts +150 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
- package/src/__tests__/host-cu-proxy.test.ts +171 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
- package/src/__tests__/inline-command-runner.test.ts +7 -5
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/log-export-workspace.test.ts +190 -0
- package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +61 -2
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +101 -1
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/navigate-settings-tab.test.ts +14 -1
- package/src/__tests__/notification-broadcaster.test.ts +65 -0
- package/src/__tests__/oauth-apps-routes.test.ts +17 -12
- package/src/__tests__/oauth-cli.test.ts +707 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +50 -14
- package/src/__tests__/oauth-store.test.ts +1386 -182
- package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
- package/src/__tests__/onboarding-template-contract.test.ts +74 -55
- package/src/__tests__/openai-provider.test.ts +2 -2
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/pkb-autoinject.test.ts +96 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/require-fresh-approval.test.ts +40 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
- package/src/__tests__/slack-channel-config.test.ts +12 -15
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +72 -1
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/terminal-sandbox.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +11 -5
- package/src/__tests__/test-preload.ts +14 -0
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +62 -0
- package/src/__tests__/trust-store.test.ts +4 -4
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
- package/src/__tests__/workspace-policy.test.ts +2 -7
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/loop.ts +12 -35
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +55 -0
- package/src/cli/__tests__/run-assistant-command.ts +34 -7
- package/src/cli/__tests__/unknown-command.test.ts +33 -0
- package/src/cli/commands/browser-relay.ts +339 -409
- package/src/cli/commands/credentials.ts +3 -3
- package/src/cli/commands/default-action.ts +68 -1
- package/src/cli/commands/email.ts +18 -13
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +16 -2
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/providers.ts +200 -36
- package/src/cli/commands/oauth/shared.ts +5 -5
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +10 -3
- package/src/config/assistant-feature-flags.ts +59 -55
- package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/contacts/SKILL.md +3 -0
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +12 -7
- package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
- package/src/config/bundled-skills/outlook/SKILL.md +7 -0
- package/src/config/bundled-skills/settings/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/env-registry.ts +14 -0
- package/src/config/env.ts +21 -0
- package/src/config/feature-flag-registry.json +46 -7
- package/src/config/loader.ts +56 -1
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +46 -5
- package/src/config/schemas/host-browser.ts +66 -0
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +16 -0
- package/src/config/types.ts +0 -1
- package/src/context/post-turn-tool-result-truncation.ts +176 -0
- package/src/context/window-manager.ts +19 -1
- package/src/credential-execution/approval-bridge.ts +49 -16
- package/src/credential-execution/managed-catalog.ts +3 -7
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +6 -2
- package/src/daemon/context-overflow-approval.ts +5 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
- package/src/daemon/conversation-agent-loop.ts +74 -19
- package/src/daemon/conversation-attachments.ts +40 -1
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +66 -3
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +159 -20
- package/src/daemon/conversation-surfaces.ts +78 -12
- package/src/daemon/conversation-tool-setup.ts +74 -11
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +227 -11
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/conversations.ts +9 -139
- package/src/daemon/handlers/shared.ts +65 -0
- package/src/daemon/handlers/skills.ts +232 -37
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +191 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +86 -12
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/conversations.ts +59 -13
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/messages.ts +5 -6
- package/src/daemon/message-types/notifications.ts +12 -0
- package/src/daemon/message-types/settings.ts +12 -0
- package/src/daemon/message-types/skills.ts +10 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/server.ts +112 -35
- package/src/daemon/tool-side-effects.ts +6 -0
- package/src/daemon/transport-hints.ts +14 -0
- package/src/inbound/platform-callback-registration.ts +18 -17
- package/src/index.ts +1 -1
- package/src/mcp/client.ts +59 -24
- package/src/memory/app-store.ts +31 -1
- package/src/memory/conversation-crud.ts +38 -10
- package/src/memory/conversation-directories.ts +39 -0
- package/src/memory/conversation-group-migration.ts +65 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +12 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +177 -18
- package/src/memory/graph/capability-seed.ts +3 -5
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/retriever.ts +40 -22
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/group-crud.ts +25 -9
- package/src/memory/llm-usage-store.ts +45 -4
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +1 -0
- package/src/memory/schema/oauth.ts +18 -13
- package/src/messaging/provider.ts +1 -1
- package/src/notifications/broadcaster.ts +6 -0
- package/src/notifications/conversation-pairing.ts +12 -4
- package/src/notifications/emit-signal.ts +14 -0
- package/src/notifications/signal.ts +11 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +8 -8
- package/src/oauth/byo-connection.ts +7 -7
- package/src/oauth/connect-orchestrator.ts +23 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +16 -16
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +214 -100
- package/src/oauth/platform-connection.test.ts +5 -5
- package/src/oauth/platform-connection.ts +4 -4
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +127 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +7 -8
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/platform/client.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -21
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -96
- package/src/prompts/templates/SOUL.md +11 -11
- package/src/providers/anthropic/client.ts +1 -0
- package/src/providers/types.ts +1 -1
- package/src/runtime/AGENTS.md +23 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/assistant-event-hub.ts +24 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +6 -7
- package/src/runtime/auth/token-service.ts +8 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/chrome-extension-registry.ts +332 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +425 -70
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
- package/src/runtime/migrations/migration-transport.ts +6 -0
- package/src/runtime/migrations/migration-wizard.ts +22 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
- package/src/runtime/migrations/vbundle-importer.ts +55 -5
- package/src/runtime/pending-interactions.ts +29 -13
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/browser-cdp-routes.ts +229 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
- package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
- package/src/runtime/routes/conversation-management-routes.ts +108 -0
- package/src/runtime/routes/conversation-routes.ts +308 -28
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/group-routes.ts +22 -8
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/host-browser-routes.ts +279 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-routes.ts +259 -16
- package/src/runtime/routes/log-export/AGENTS.md +104 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
- package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
- package/src/runtime/routes/log-export-routes.ts +60 -25
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +87 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +9 -97
- package/src/runtime/routes/skills-routes.ts +52 -2
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/usage-routes.ts +8 -7
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/schedule/scheduler.ts +7 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +42 -25
- package/src/security/secure-keys.ts +118 -25
- package/src/security/token-manager.ts +23 -10
- package/src/skills/catalog-files.ts +492 -0
- package/src/skills/inline-command-runner.ts +12 -14
- package/src/subagent/manager.ts +131 -26
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +645 -340
- package/src/tools/browser/browser-manager.ts +36 -12
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
- package/src/tools/browser/cdp-client/errors.ts +34 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
- package/src/tools/browser/cdp-client/factory.ts +204 -0
- package/src/tools/browser/cdp-client/index.ts +14 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +52 -0
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/permission-checker.ts +77 -100
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -1
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/skills/sandbox-runner.ts +3 -6
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
- package/src/tools/terminal/sandbox.ts +4 -1
- package/src/tools/terminal/shell.ts +24 -21
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/types.ts +2 -3
- package/src/util/platform.ts +14 -19
- package/src/watcher/provider-types.ts +1 -1
- package/src/workspace/migrations/029-seed-pkb.ts +1 -0
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/top-level-renderer.ts +19 -1
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -21,6 +21,11 @@ import { invalidateConfigCache } from "../../config/loader.js";
|
|
|
21
21
|
import { getDb, resetDb } from "../../memory/db-connection.js";
|
|
22
22
|
import { validateMigrationState } from "../../memory/migrations/validate-migration-state.js";
|
|
23
23
|
import { clearCache as clearTrustCache } from "../../permissions/trust-store.js";
|
|
24
|
+
import {
|
|
25
|
+
bulkSetSecureKeysAsync,
|
|
26
|
+
getSecureKeyResultAsync,
|
|
27
|
+
listSecureKeysAsync,
|
|
28
|
+
} from "../../security/secure-keys.js";
|
|
24
29
|
import { getLogger } from "../../util/logger.js";
|
|
25
30
|
import {
|
|
26
31
|
getDbPath,
|
|
@@ -34,7 +39,10 @@ import {
|
|
|
34
39
|
analyzeImport,
|
|
35
40
|
DefaultPathResolver,
|
|
36
41
|
} from "../migrations/vbundle-import-analyzer.js";
|
|
37
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
commitImport,
|
|
44
|
+
extractCredentialsFromBundle,
|
|
45
|
+
} from "../migrations/vbundle-importer.js";
|
|
38
46
|
import { validateVBundle } from "../migrations/vbundle-validator.js";
|
|
39
47
|
|
|
40
48
|
const log = getLogger("migration-routes");
|
|
@@ -146,6 +154,27 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
|
|
|
146
154
|
let cleanup: (() => Promise<void>) | undefined;
|
|
147
155
|
|
|
148
156
|
try {
|
|
157
|
+
// Read all stored credentials to include in the export bundle
|
|
158
|
+
const credentialList = await listSecureKeysAsync();
|
|
159
|
+
const credentials: Array<{ account: string; value: string }> = [];
|
|
160
|
+
if (credentialList.unreachable) {
|
|
161
|
+
log.warn(
|
|
162
|
+
"Credential store is unreachable — export will not include credentials",
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
for (const account of credentialList.accounts) {
|
|
166
|
+
const result = await getSecureKeyResultAsync(account);
|
|
167
|
+
if (result.unreachable) {
|
|
168
|
+
log.warn(
|
|
169
|
+
{ account },
|
|
170
|
+
"Credential store unreachable when reading credential — skipping",
|
|
171
|
+
);
|
|
172
|
+
} else if (result.value != null) {
|
|
173
|
+
credentials.push({ account, value: result.value });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
149
178
|
const result = await streamExportVBundle({
|
|
150
179
|
// hooksDir is intentionally omitted — hooks now live under workspace/hooks/
|
|
151
180
|
// and are included in the workspace walk. Passing hooksDir separately would
|
|
@@ -153,6 +182,7 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
|
|
|
153
182
|
workspaceDir: getWorkspaceDir(),
|
|
154
183
|
source: "runtime-export",
|
|
155
184
|
description,
|
|
185
|
+
credentials,
|
|
156
186
|
checkpoint: () => {
|
|
157
187
|
const dbPath = getDbPath();
|
|
158
188
|
try {
|
|
@@ -196,6 +226,7 @@ export async function handleMigrationExport(req: Request): Promise<Response> {
|
|
|
196
226
|
"Content-Length": String(size),
|
|
197
227
|
"X-Vbundle-Schema-Version": manifest.schema_version,
|
|
198
228
|
"X-Vbundle-Manifest-Sha256": manifest.manifest_sha256,
|
|
229
|
+
"X-Vbundle-Credentials-Included": String(credentials.length),
|
|
199
230
|
},
|
|
200
231
|
});
|
|
201
232
|
} catch (err) {
|
|
@@ -444,6 +475,57 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
444
475
|
);
|
|
445
476
|
}
|
|
446
477
|
|
|
478
|
+
// Import credentials from the bundle into CES (non-blocking — failures
|
|
479
|
+
// are logged as warnings but do not fail the overall import).
|
|
480
|
+
let credentialsImported:
|
|
481
|
+
| {
|
|
482
|
+
total: number;
|
|
483
|
+
succeeded: number;
|
|
484
|
+
failed: number;
|
|
485
|
+
failedAccounts: string[];
|
|
486
|
+
}
|
|
487
|
+
| undefined;
|
|
488
|
+
|
|
489
|
+
if (validation.entries) {
|
|
490
|
+
const bundleCredentials = extractCredentialsFromBundle(
|
|
491
|
+
validation.entries,
|
|
492
|
+
validation.manifest!,
|
|
493
|
+
);
|
|
494
|
+
if (bundleCredentials.length > 0) {
|
|
495
|
+
try {
|
|
496
|
+
const credResults = await bulkSetSecureKeysAsync(bundleCredentials);
|
|
497
|
+
const failedResults = credResults.filter((r) => !r.ok);
|
|
498
|
+
if (failedResults.length > 0) {
|
|
499
|
+
log.warn(
|
|
500
|
+
{ failed: failedResults.map((f) => f.account) },
|
|
501
|
+
"Some credentials failed to import",
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
log.info(
|
|
505
|
+
{ total: bundleCredentials.length, failed: failedResults.length },
|
|
506
|
+
"Credential import complete",
|
|
507
|
+
);
|
|
508
|
+
const succeeded = bundleCredentials.length - failedResults.length;
|
|
509
|
+
credentialsImported = {
|
|
510
|
+
total: bundleCredentials.length,
|
|
511
|
+
succeeded,
|
|
512
|
+
failed: failedResults.length,
|
|
513
|
+
failedAccounts: failedResults.map((f) => f.account),
|
|
514
|
+
};
|
|
515
|
+
if (failedResults.length > 0) {
|
|
516
|
+
result.report.warnings.push(
|
|
517
|
+
`Imported ${succeeded} credential(s), ${failedResults.length} failed`,
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
} catch (err) {
|
|
521
|
+
log.warn({ err }, "Credential import failed entirely");
|
|
522
|
+
result.report.warnings.push(
|
|
523
|
+
`Credential import failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
447
529
|
// Invalidate in-process caches so imported settings.json and trust.json take effect
|
|
448
530
|
invalidateConfigCache();
|
|
449
531
|
clearTrustCache();
|
|
@@ -463,7 +545,10 @@ export async function handleMigrationImport(req: Request): Promise<Response> {
|
|
|
463
545
|
// Don't fail the import if validation itself errors
|
|
464
546
|
}
|
|
465
547
|
|
|
466
|
-
return Response.json(
|
|
548
|
+
return Response.json({
|
|
549
|
+
...result.report,
|
|
550
|
+
...(credentialsImported ? { credentialsImported } : {}),
|
|
551
|
+
});
|
|
467
552
|
} catch (err) {
|
|
468
553
|
log.error({ err }, "Unexpected error during import commit");
|
|
469
554
|
return httpError(
|
|
@@ -60,8 +60,8 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
60
60
|
endpoint: "oauth/apps",
|
|
61
61
|
method: "GET",
|
|
62
62
|
handler: ({ url }) => {
|
|
63
|
-
const
|
|
64
|
-
if (!
|
|
63
|
+
const provider = url.searchParams.get("provider_key");
|
|
64
|
+
if (!provider) {
|
|
65
65
|
return httpError(
|
|
66
66
|
"BAD_REQUEST",
|
|
67
67
|
"provider_key query parameter is required",
|
|
@@ -70,20 +70,18 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const allApps = listApps();
|
|
73
|
-
const filtered = allApps.filter(
|
|
74
|
-
(row) => row.providerKey === providerKey,
|
|
75
|
-
);
|
|
73
|
+
const filtered = allApps.filter((row) => row.provider === provider);
|
|
76
74
|
|
|
77
|
-
const providerRow = getProvider(
|
|
78
|
-
const
|
|
75
|
+
const providerRow = getProvider(provider);
|
|
76
|
+
const providerSummary = providerRow
|
|
79
77
|
? serializeProviderSummary(providerRow)
|
|
80
78
|
: null;
|
|
81
79
|
|
|
82
80
|
return Response.json({
|
|
83
|
-
provider,
|
|
81
|
+
provider: providerSummary,
|
|
84
82
|
apps: filtered.map((row) => ({
|
|
85
83
|
id: row.id,
|
|
86
|
-
provider_key: row.
|
|
84
|
+
provider_key: row.provider,
|
|
87
85
|
client_id: row.clientId,
|
|
88
86
|
created_at: row.createdAt,
|
|
89
87
|
updated_at: row.updatedAt,
|
|
@@ -138,7 +136,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
138
136
|
{
|
|
139
137
|
app: {
|
|
140
138
|
id: app.id,
|
|
141
|
-
provider_key: app.
|
|
139
|
+
provider_key: app.provider,
|
|
142
140
|
client_id: app.clientId,
|
|
143
141
|
created_at: app.createdAt,
|
|
144
142
|
updated_at: app.updatedAt,
|
|
@@ -165,9 +163,9 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
165
163
|
}
|
|
166
164
|
|
|
167
165
|
// Disconnect all connections for this app first to clean up tokens.
|
|
168
|
-
const connections = listConnections(app.
|
|
166
|
+
const connections = listConnections(app.provider, app.clientId);
|
|
169
167
|
for (const conn of connections) {
|
|
170
|
-
await disconnectOAuthProvider(app.
|
|
168
|
+
await disconnectOAuthProvider(app.provider, app.clientId, conn.id);
|
|
171
169
|
}
|
|
172
170
|
|
|
173
171
|
await deleteApp(params.id);
|
|
@@ -190,12 +188,12 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
190
188
|
);
|
|
191
189
|
}
|
|
192
190
|
|
|
193
|
-
const connections = listConnections(app.
|
|
191
|
+
const connections = listConnections(app.provider, app.clientId);
|
|
194
192
|
|
|
195
193
|
return Response.json({
|
|
196
194
|
connections: connections.map((row) => ({
|
|
197
195
|
id: row.id,
|
|
198
|
-
provider_key: row.
|
|
196
|
+
provider_key: row.provider,
|
|
199
197
|
account_info: row.accountInfo,
|
|
200
198
|
granted_scopes: parseGrantedScopes(row.grantedScopes),
|
|
201
199
|
status: row.status,
|
|
@@ -223,7 +221,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
223
221
|
}
|
|
224
222
|
|
|
225
223
|
const result = await disconnectOAuthProvider(
|
|
226
|
-
conn.
|
|
224
|
+
conn.provider,
|
|
227
225
|
undefined,
|
|
228
226
|
conn.id,
|
|
229
227
|
);
|
|
@@ -282,7 +280,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
282
280
|
const clientSecret = await getAppClientSecret(app);
|
|
283
281
|
|
|
284
282
|
const result = await orchestrateOAuthConnect({
|
|
285
|
-
service: app.
|
|
283
|
+
service: app.provider,
|
|
286
284
|
clientId: app.clientId,
|
|
287
285
|
clientSecret,
|
|
288
286
|
requestedScopes: body.scopes,
|
|
@@ -292,7 +290,7 @@ export function oauthAppsRouteDefinitions(): RouteDefinition[] {
|
|
|
292
290
|
|
|
293
291
|
if (result.success && result.deferred) {
|
|
294
292
|
return Response.json({
|
|
295
|
-
auth_url: result.
|
|
293
|
+
auth_url: result.authorizeUrl,
|
|
296
294
|
state: result.state,
|
|
297
295
|
});
|
|
298
296
|
}
|
|
@@ -44,6 +44,10 @@ export function oauthProvidersRouteDefinitions(): RouteDefinition[] {
|
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
// GET /v1/oauth/providers/:providerKey — Get a single provider.
|
|
47
|
+
// The path parameter name `providerKey` is preserved for backward
|
|
48
|
+
// compatibility with the published OpenAPI spec (operationId
|
|
49
|
+
// `oauth_providers_by_providerKey_get`). The actual URL the client hits
|
|
50
|
+
// (`/v1/oauth/providers/google`) is unchanged either way.
|
|
47
51
|
{
|
|
48
52
|
endpoint: "oauth/providers/:providerKey",
|
|
49
53
|
method: "GET",
|
|
@@ -25,6 +25,10 @@ import type { RouteDefinition } from "../http-router.js";
|
|
|
25
25
|
import type { SendMessageDeps } from "../http-types.js";
|
|
26
26
|
|
|
27
27
|
const log = getLogger("schedule-routes");
|
|
28
|
+
const SCHEDULE_GUARDIAN_TRUST_CONTEXT = {
|
|
29
|
+
sourceChannel: "vellum",
|
|
30
|
+
trustClass: "guardian",
|
|
31
|
+
} as const;
|
|
28
32
|
|
|
29
33
|
// ---------------------------------------------------------------------------
|
|
30
34
|
// Handlers
|
|
@@ -202,17 +206,23 @@ async function handleRunScheduleNow(
|
|
|
202
206
|
);
|
|
203
207
|
}
|
|
204
208
|
const conversation =
|
|
205
|
-
await sendMessageDeps.getOrCreateConversation(conversationId
|
|
209
|
+
await sendMessageDeps.getOrCreateConversation(conversationId, {
|
|
210
|
+
trustContext: SCHEDULE_GUARDIAN_TRUST_CONTEXT,
|
|
211
|
+
});
|
|
206
212
|
conversation.taskRunId = taskRunId;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
try {
|
|
214
|
+
await conversation.processMessage(
|
|
215
|
+
message,
|
|
216
|
+
[],
|
|
217
|
+
() => {}, // no event callback for HTTP mode
|
|
218
|
+
undefined,
|
|
219
|
+
undefined,
|
|
220
|
+
undefined,
|
|
221
|
+
{ isInteractive: false },
|
|
222
|
+
);
|
|
223
|
+
} finally {
|
|
224
|
+
conversation.taskRunId = undefined;
|
|
225
|
+
}
|
|
216
226
|
},
|
|
217
227
|
);
|
|
218
228
|
|
|
@@ -276,7 +286,10 @@ async function handleRunScheduleNow(
|
|
|
276
286
|
throw new Error("sendMessageDeps not available for schedule execution");
|
|
277
287
|
}
|
|
278
288
|
const activeConversation =
|
|
279
|
-
await sendMessageDeps.getOrCreateConversation(conversationId
|
|
289
|
+
await sendMessageDeps.getOrCreateConversation(conversationId, {
|
|
290
|
+
trustContext: SCHEDULE_GUARDIAN_TRUST_CONTEXT,
|
|
291
|
+
});
|
|
292
|
+
activeConversation.taskRunId = undefined;
|
|
280
293
|
await activeConversation.processMessage(
|
|
281
294
|
schedule.message,
|
|
282
295
|
[],
|
|
@@ -12,16 +12,11 @@ import { join } from "node:path";
|
|
|
12
12
|
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
|
|
15
|
-
import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
|
|
16
15
|
import {
|
|
17
16
|
getPlatformBaseUrl,
|
|
18
17
|
setIngressPublicBaseUrl,
|
|
19
18
|
} from "../../config/env.js";
|
|
20
|
-
import {
|
|
21
|
-
getConfig,
|
|
22
|
-
loadRawConfig,
|
|
23
|
-
saveRawConfig,
|
|
24
|
-
} from "../../config/loader.js";
|
|
19
|
+
import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
|
|
25
20
|
import { loadSkillCatalog } from "../../config/skills.js";
|
|
26
21
|
import {
|
|
27
22
|
computeGatewayTarget,
|
|
@@ -41,12 +36,6 @@ import {
|
|
|
41
36
|
generateAllowlistOptions,
|
|
42
37
|
generateScopeOptions,
|
|
43
38
|
} from "../../permissions/checker.js";
|
|
44
|
-
import {
|
|
45
|
-
getMode,
|
|
46
|
-
onModeChanged,
|
|
47
|
-
setAskBeforeActing,
|
|
48
|
-
setHostAccess,
|
|
49
|
-
} from "../../permissions/permission-mode-store.js";
|
|
50
39
|
import { getSecureKeyAsync } from "../../security/secure-keys.js";
|
|
51
40
|
import { parseToolManifestFile } from "../../skills/tool-manifest.js";
|
|
52
41
|
import {
|
|
@@ -72,24 +61,6 @@ import { resolveWorkspacePath } from "./workspace-utils.js";
|
|
|
72
61
|
|
|
73
62
|
const log = getLogger("settings-routes");
|
|
74
63
|
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
// Permission mode SSE broadcast
|
|
77
|
-
// ---------------------------------------------------------------------------
|
|
78
|
-
|
|
79
|
-
onModeChanged((mode) => {
|
|
80
|
-
assistantEventHub
|
|
81
|
-
.publish(
|
|
82
|
-
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
83
|
-
type: "permission_mode_update",
|
|
84
|
-
askBeforeActing: mode.askBeforeActing,
|
|
85
|
-
hostAccess: mode.hostAccess,
|
|
86
|
-
}),
|
|
87
|
-
)
|
|
88
|
-
.catch((err) => {
|
|
89
|
-
log.warn({ err }, "Failed to publish permission_mode_update event");
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
64
|
// ---------------------------------------------------------------------------
|
|
94
65
|
// Voice config
|
|
95
66
|
// ---------------------------------------------------------------------------
|
|
@@ -240,7 +211,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
240
211
|
try {
|
|
241
212
|
// For HTTP, we cannot send `open_url` mid-request. The auth URL is
|
|
242
213
|
// returned to the client to open.
|
|
243
|
-
let
|
|
214
|
+
let authorizeUrl: string | undefined;
|
|
244
215
|
|
|
245
216
|
const result = await orchestrateOAuthConnect({
|
|
246
217
|
service,
|
|
@@ -250,7 +221,7 @@ async function handleOAuthConnectStart(body: {
|
|
|
250
221
|
callbackTransport: "loopback",
|
|
251
222
|
isInteractive: true,
|
|
252
223
|
openUrl: (url: string) => {
|
|
253
|
-
|
|
224
|
+
authorizeUrl = url;
|
|
254
225
|
},
|
|
255
226
|
onDeferredComplete: (deferredResult) => {
|
|
256
227
|
// Prefer accountInfo from oauth-store when available.
|
|
@@ -309,7 +280,9 @@ async function handleOAuthConnectStart(body: {
|
|
|
309
280
|
return Response.json({
|
|
310
281
|
ok: true,
|
|
311
282
|
deferred: true,
|
|
312
|
-
authUrl
|
|
283
|
+
// Wire key stays `authUrl` for backward compatibility with existing
|
|
284
|
+
// clients; the internal field on `result` is `authorizeUrl`.
|
|
285
|
+
authUrl: result.authorizeUrl,
|
|
313
286
|
});
|
|
314
287
|
}
|
|
315
288
|
|
|
@@ -326,7 +299,9 @@ async function handleOAuthConnectStart(body: {
|
|
|
326
299
|
ok: true,
|
|
327
300
|
grantedScopes: result.grantedScopes,
|
|
328
301
|
accountInfo: responseAccountInfo,
|
|
329
|
-
|
|
302
|
+
// Wire key stays `authUrl` for backward compatibility with existing
|
|
303
|
+
// clients; the local variable was renamed to `authorizeUrl`.
|
|
304
|
+
...(authorizeUrl ? { authUrl: authorizeUrl } : {}),
|
|
330
305
|
});
|
|
331
306
|
} catch (err) {
|
|
332
307
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -921,68 +896,5 @@ export function settingsRouteDefinitions(): RouteDefinition[] {
|
|
|
921
896
|
}
|
|
922
897
|
},
|
|
923
898
|
},
|
|
924
|
-
|
|
925
|
-
// Permission mode (GET always available; PUT gated on feature flag)
|
|
926
|
-
{
|
|
927
|
-
endpoint: "permission-mode",
|
|
928
|
-
method: "GET",
|
|
929
|
-
policyKey: "permission-mode:GET",
|
|
930
|
-
summary: "Get permission mode",
|
|
931
|
-
description:
|
|
932
|
-
"Return the current two-axis permission mode (askBeforeActing, hostAccess).",
|
|
933
|
-
tags: ["settings"],
|
|
934
|
-
responseBody: z.object({
|
|
935
|
-
askBeforeActing: z.boolean(),
|
|
936
|
-
hostAccess: z.boolean(),
|
|
937
|
-
}),
|
|
938
|
-
handler: () => {
|
|
939
|
-
const mode = getMode();
|
|
940
|
-
return Response.json({
|
|
941
|
-
askBeforeActing: mode.askBeforeActing,
|
|
942
|
-
hostAccess: mode.hostAccess,
|
|
943
|
-
});
|
|
944
|
-
},
|
|
945
|
-
},
|
|
946
|
-
{
|
|
947
|
-
endpoint: "permission-mode",
|
|
948
|
-
method: "PUT",
|
|
949
|
-
policyKey: "permission-mode",
|
|
950
|
-
summary: "Update permission mode",
|
|
951
|
-
description:
|
|
952
|
-
"Update the two-axis permission mode. Requires the permission-controls-v2 feature flag.",
|
|
953
|
-
tags: ["settings"],
|
|
954
|
-
requestBody: z.object({
|
|
955
|
-
askBeforeActing: z.boolean().optional(),
|
|
956
|
-
hostAccess: z.boolean().optional(),
|
|
957
|
-
}),
|
|
958
|
-
responseBody: z.object({
|
|
959
|
-
askBeforeActing: z.boolean(),
|
|
960
|
-
hostAccess: z.boolean(),
|
|
961
|
-
}),
|
|
962
|
-
handler: async ({ req }) => {
|
|
963
|
-
const config = getConfig();
|
|
964
|
-
if (!isAssistantFeatureFlagEnabled("permission-controls-v2", config)) {
|
|
965
|
-
return httpError("NOT_FOUND", "Not found", 404);
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
const body = (await req.json()) as {
|
|
969
|
-
askBeforeActing?: boolean;
|
|
970
|
-
hostAccess?: boolean;
|
|
971
|
-
};
|
|
972
|
-
|
|
973
|
-
if (typeof body.askBeforeActing === "boolean") {
|
|
974
|
-
setAskBeforeActing(body.askBeforeActing);
|
|
975
|
-
}
|
|
976
|
-
if (typeof body.hostAccess === "boolean") {
|
|
977
|
-
setHostAccess(body.hostAccess);
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
const mode = getMode();
|
|
981
|
-
return Response.json({
|
|
982
|
-
askBeforeActing: mode.askBeforeActing,
|
|
983
|
-
hostAccess: mode.hostAccess,
|
|
984
|
-
});
|
|
985
|
-
},
|
|
986
|
-
},
|
|
987
899
|
];
|
|
988
900
|
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
draftSkill,
|
|
20
20
|
enableSkill,
|
|
21
21
|
getSkill,
|
|
22
|
+
getSkillFileContent,
|
|
22
23
|
getSkillFiles,
|
|
23
24
|
inspectSkill,
|
|
24
25
|
installSkill,
|
|
@@ -151,6 +152,55 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
151
152
|
},
|
|
152
153
|
},
|
|
153
154
|
|
|
155
|
+
// The router uses strict anchored-regex matching, so this route is never
|
|
156
|
+
// ambiguous with skills/:id/files.
|
|
157
|
+
{
|
|
158
|
+
endpoint: "skills/:id/files/content",
|
|
159
|
+
method: "GET",
|
|
160
|
+
policyKey: "skills",
|
|
161
|
+
summary: "Get skill file content",
|
|
162
|
+
description:
|
|
163
|
+
"Return the content of a single file belonging to an installed or catalog skill.",
|
|
164
|
+
tags: ["skills"],
|
|
165
|
+
queryParams: [
|
|
166
|
+
{
|
|
167
|
+
name: "path",
|
|
168
|
+
schema: { type: "string" },
|
|
169
|
+
required: true,
|
|
170
|
+
description: "Relative path of the file within the skill directory",
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
responseBody: z.object({
|
|
174
|
+
path: z.string(),
|
|
175
|
+
name: z.string(),
|
|
176
|
+
size: z.number().int(),
|
|
177
|
+
mimeType: z.string(),
|
|
178
|
+
isBinary: z.boolean(),
|
|
179
|
+
content: z.string().nullable(),
|
|
180
|
+
}),
|
|
181
|
+
handler: async ({ params, url }) => {
|
|
182
|
+
const path = url.searchParams.get("path");
|
|
183
|
+
if (!path) {
|
|
184
|
+
return httpError(
|
|
185
|
+
"BAD_REQUEST",
|
|
186
|
+
"path query parameter is required",
|
|
187
|
+
400,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const result = await getSkillFileContent(params.id, path, ctx());
|
|
191
|
+
if ("error" in result) {
|
|
192
|
+
if (result.status === 400) {
|
|
193
|
+
return httpError("BAD_REQUEST", result.error, 400);
|
|
194
|
+
}
|
|
195
|
+
if (result.status === 404) {
|
|
196
|
+
return httpError("NOT_FOUND", result.error, 404);
|
|
197
|
+
}
|
|
198
|
+
return httpError("INTERNAL_ERROR", result.error, 500);
|
|
199
|
+
}
|
|
200
|
+
return Response.json(result);
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
|
|
154
204
|
{
|
|
155
205
|
endpoint: "skills/:id/files",
|
|
156
206
|
method: "GET",
|
|
@@ -158,8 +208,8 @@ export function skillRouteDefinitions(deps: SkillRouteDeps): RouteDefinition[] {
|
|
|
158
208
|
summary: "Get skill files",
|
|
159
209
|
description: "Return skill metadata and directory contents.",
|
|
160
210
|
tags: ["skills"],
|
|
161
|
-
handler: ({ params }) => {
|
|
162
|
-
const result = getSkillFiles(params.id, ctx());
|
|
211
|
+
handler: async ({ params }) => {
|
|
212
|
+
const result = await getSkillFiles(params.id, ctx());
|
|
163
213
|
if ("error" in result) {
|
|
164
214
|
if (result.status === 404) {
|
|
165
215
|
return httpError("NOT_FOUND", result.error, 404);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
|
|
10
|
-
import { getMessages } from "../../memory/conversation-crud.js";
|
|
10
|
+
import { getMessages, type MessageRow } from "../../memory/conversation-crud.js";
|
|
11
11
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
12
12
|
import { getLogger } from "../../util/logger.js";
|
|
13
13
|
import { httpError } from "../http-errors.js";
|
|
@@ -31,16 +31,25 @@ export interface SubagentDetailResult {
|
|
|
31
31
|
content: string;
|
|
32
32
|
toolName?: string;
|
|
33
33
|
isError?: boolean;
|
|
34
|
+
messageId?: string;
|
|
34
35
|
}>;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
const FORK_DIRECTIVE_RE =
|
|
39
|
+
/^⎯⎯⎯ FORK TASK ⎯⎯⎯\n[\s\S]*?Complete this task directly and return only your findings:\n\n([\s\S]*?)\n⎯⎯⎯+$/;
|
|
40
|
+
|
|
41
|
+
function stripForkDirectiveFraming(text: string): string {
|
|
42
|
+
const match = FORK_DIRECTIVE_RE.exec(text);
|
|
43
|
+
return match ? match[1] : text;
|
|
44
|
+
}
|
|
45
|
+
|
|
37
46
|
/**
|
|
38
47
|
* Parse raw message rows into subagent detail events. Extracted as a pure
|
|
39
48
|
* function so it can be unit-tested without a database.
|
|
40
49
|
*/
|
|
41
50
|
export function parseSubagentMessages(
|
|
42
51
|
subagentId: string,
|
|
43
|
-
messages:
|
|
52
|
+
messages: MessageRow[],
|
|
44
53
|
): SubagentDetailResult {
|
|
45
54
|
// Extract objective from the first user message
|
|
46
55
|
let objective: string | undefined;
|
|
@@ -53,7 +62,7 @@ export function parseSubagentMessages(
|
|
|
53
62
|
(b: Record<string, unknown>) => isRecord(b) && b.type === "text",
|
|
54
63
|
);
|
|
55
64
|
if (textBlock && typeof textBlock.text === "string") {
|
|
56
|
-
objective = textBlock.text;
|
|
65
|
+
objective = stripForkDirectiveFraming(textBlock.text);
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
68
|
} catch {
|
|
@@ -62,12 +71,7 @@ export function parseSubagentMessages(
|
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
// Extract events from both assistant and user messages.
|
|
65
|
-
const events:
|
|
66
|
-
type: string;
|
|
67
|
-
content: string;
|
|
68
|
-
toolName?: string;
|
|
69
|
-
isError?: boolean;
|
|
70
|
-
}> = [];
|
|
74
|
+
const events: SubagentDetailResult["events"] = [];
|
|
71
75
|
const pendingTools = new Map<string, string>();
|
|
72
76
|
for (const m of messages) {
|
|
73
77
|
if (m.role !== "assistant" && m.role !== "user") continue;
|
|
@@ -86,7 +90,7 @@ export function parseSubagentMessages(
|
|
|
86
90
|
block.type === "text" &&
|
|
87
91
|
typeof block.text === "string"
|
|
88
92
|
) {
|
|
89
|
-
events.push({ type: "text", content: block.text });
|
|
93
|
+
events.push({ type: "text", content: block.text, messageId: m.id });
|
|
90
94
|
} else if (block.type === "tool_use") {
|
|
91
95
|
const name = typeof block.name === "string" ? block.name : "unknown";
|
|
92
96
|
const input = isRecord(block.input)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* GET /v1/usage/totals?from=&to= — aggregate totals for a time range
|
|
5
5
|
* GET /v1/usage/daily?from=&to= — per-day buckets for a time range
|
|
6
|
-
* GET /v1/usage/breakdown?from=&to=&groupBy= — grouped breakdown (actor, provider, model)
|
|
6
|
+
* GET /v1/usage/breakdown?from=&to=&groupBy= — grouped breakdown (actor, provider, model, or conversation)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { z } from "zod";
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { httpError } from "../http-errors.js";
|
|
18
18
|
import type { RouteDefinition } from "../http-router.js";
|
|
19
19
|
|
|
20
|
-
const VALID_GROUP_BY = new Set(["actor", "provider", "model"]);
|
|
20
|
+
const VALID_GROUP_BY = new Set(["actor", "provider", "model", "conversation"]);
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Parse and validate the `from` and `to` epoch-millis query parameters.
|
|
@@ -137,7 +137,7 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
137
137
|
method: "GET",
|
|
138
138
|
summary: "Get usage breakdown",
|
|
139
139
|
description:
|
|
140
|
-
"Return grouped usage breakdown (by actor, provider, or
|
|
140
|
+
"Return grouped usage breakdown (by actor, provider, model, or conversation).",
|
|
141
141
|
tags: ["usage"],
|
|
142
142
|
queryParams: [
|
|
143
143
|
{
|
|
@@ -153,7 +153,8 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
153
153
|
{
|
|
154
154
|
name: "groupBy",
|
|
155
155
|
schema: { type: "string" },
|
|
156
|
-
description:
|
|
156
|
+
description:
|
|
157
|
+
"Group by: actor, provider, model, or conversation (required)",
|
|
157
158
|
},
|
|
158
159
|
],
|
|
159
160
|
responseBody: z.object({
|
|
@@ -167,21 +168,21 @@ export function usageRouteDefinitions(): RouteDefinition[] {
|
|
|
167
168
|
if (!groupBy) {
|
|
168
169
|
return httpError(
|
|
169
170
|
"BAD_REQUEST",
|
|
170
|
-
'Missing required query parameter: "groupBy" (one of: actor, provider, model)',
|
|
171
|
+
'Missing required query parameter: "groupBy" (one of: actor, provider, model, conversation)',
|
|
171
172
|
400,
|
|
172
173
|
);
|
|
173
174
|
}
|
|
174
175
|
if (!VALID_GROUP_BY.has(groupBy)) {
|
|
175
176
|
return httpError(
|
|
176
177
|
"BAD_REQUEST",
|
|
177
|
-
`Invalid "groupBy" value: "${groupBy}". Must be one of: actor, provider, model`,
|
|
178
|
+
`Invalid "groupBy" value: "${groupBy}". Must be one of: actor, provider, model, conversation`,
|
|
178
179
|
400,
|
|
179
180
|
);
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
const breakdown = getUsageGroupBreakdown(
|
|
183
184
|
range,
|
|
184
|
-
groupBy as "actor" | "provider" | "model",
|
|
185
|
+
groupBy as "actor" | "provider" | "model" | "conversation",
|
|
185
186
|
);
|
|
186
187
|
return Response.json({ breakdown });
|
|
187
188
|
},
|