@vellumai/assistant 0.4.48 → 0.4.50
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/ARCHITECTURE.md +26 -35
- package/README.md +5 -26
- package/docs/architecture/integrations.md +45 -41
- package/docs/architecture/keychain-broker.md +3 -3
- package/docs/architecture/memory.md +180 -119
- package/docs/runbook-trusted-contacts.md +3 -8
- package/hook-templates/debug-prompt-logger/hook.json +1 -1
- package/hook-templates/debug-prompt-logger/run.sh +1 -3
- package/package.json +2 -2
- package/src/__tests__/actor-token-service.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -1
- package/src/__tests__/anthropic-provider.test.ts +249 -2
- package/src/__tests__/approval-cascade.test.ts +796 -0
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +4 -0
- package/src/__tests__/assistant-attachments.test.ts +12 -34
- package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/canonical-guardian-store.test.ts +95 -0
- package/src/__tests__/channel-guardian.test.ts +0 -2
- package/src/__tests__/channel-readiness-routes.test.ts +15 -6
- package/src/__tests__/channel-readiness-service.test.ts +10 -9
- package/src/__tests__/checker.test.ts +13 -20
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-tools.test.ts +2 -19
- package/src/__tests__/config-schema.test.ts +1 -68
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-image-dimensions.test.ts +332 -0
- package/src/__tests__/context-memory-e2e.test.ts +11 -100
- package/src/__tests__/context-token-estimator.test.ts +196 -13
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +152 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/credential-metadata-store.test.ts +64 -73
- package/src/__tests__/credential-security-e2e.test.ts +1 -0
- package/src/__tests__/credential-security-invariants.test.ts +13 -7
- package/src/__tests__/credential-vault-unit.test.ts +284 -49
- package/src/__tests__/credential-vault.test.ts +150 -16
- package/src/__tests__/credentials-cli.test.ts +71 -0
- package/src/__tests__/cu-unified-flow.test.ts +532 -0
- package/src/__tests__/date-context.test.ts +93 -77
- package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
- package/src/__tests__/heartbeat-service.test.ts +0 -1
- package/src/__tests__/history-repair.test.ts +245 -0
- package/src/__tests__/host-cu-proxy.test.ts +791 -0
- package/src/__tests__/host-shell-tool.test.ts +27 -15
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/ingress-url-consistency.test.ts +14 -21
- package/src/__tests__/integration-status.test.ts +32 -51
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/invite-redemption-service.test.ts +65 -1
- package/src/__tests__/invite-routes-http.test.ts +10 -9
- package/src/__tests__/keychain-broker-client.test.ts +14 -46
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
- package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
- package/src/__tests__/memory-recall-quality.test.ts +244 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
- package/src/__tests__/memory-regressions.test.ts +477 -2841
- package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
- package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
- package/src/__tests__/mime-builder.test.ts +28 -0
- package/src/__tests__/native-web-search.test.ts +1 -0
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/oauth-cli.test.ts +941 -15
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
- package/src/__tests__/oauth-scope-policy.test.ts +4 -6
- package/src/__tests__/oauth-store.test.ts +870 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +0 -1
- package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
- package/src/__tests__/public-ingress-urls.test.ts +15 -21
- package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
- package/src/__tests__/recording-handler.test.ts +3 -4
- package/src/__tests__/registry.test.ts +2 -3
- package/src/__tests__/relay-server.test.ts +46 -1
- package/src/__tests__/runtime-events-sse.test.ts +55 -7
- package/src/__tests__/schedule-store.test.ts +0 -1
- package/src/__tests__/schedule-tools.test.ts +32 -0
- package/src/__tests__/scheduler-recurrence.test.ts +0 -1
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/secret-ingress-handler.test.ts +0 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -0
- package/src/__tests__/secure-keys.test.ts +7 -2
- package/src/__tests__/send-endpoint-busy.test.ts +24 -6
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/session-abort-tool-results.test.ts +1 -14
- package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
- package/src/__tests__/session-agent-loop.test.ts +19 -15
- package/src/__tests__/session-confirmation-signals.test.ts +1 -15
- package/src/__tests__/session-error.test.ts +124 -2
- package/src/__tests__/session-history-web-search.test.ts +918 -0
- package/src/__tests__/session-init.benchmark.test.ts +4 -5
- package/src/__tests__/session-pre-run-repair.test.ts +1 -14
- package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
- package/src/__tests__/session-queue.test.ts +37 -27
- package/src/__tests__/session-runtime-assembly.test.ts +54 -0
- package/src/__tests__/session-slash-known.test.ts +1 -15
- package/src/__tests__/session-slash-queue.test.ts +1 -15
- package/src/__tests__/session-slash-unknown.test.ts +1 -15
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
- package/src/__tests__/session-workspace-injection.test.ts +3 -37
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
- package/src/__tests__/skill-include-graph.test.ts +66 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
- package/src/__tests__/skill-load-tool.test.ts +149 -1
- package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
- package/src/__tests__/skills-install-extract.test.ts +93 -0
- package/src/__tests__/skills-uninstall.test.ts +1 -1
- package/src/__tests__/skills.test.ts +3 -3
- package/src/__tests__/skillssh-registry.test.ts +451 -0
- package/src/__tests__/slack-channel-config.test.ts +67 -3
- package/src/__tests__/slack-share-routes.test.ts +17 -19
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
- package/src/__tests__/terminal-tools.test.ts +4 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
- package/src/__tests__/trust-store.test.ts +7 -13
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +0 -16
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
- package/src/__tests__/voice-invite-redemption.test.ts +32 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/agent/ax-tree-compaction.test.ts +286 -0
- package/src/agent/loop.ts +104 -131
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-request-resolvers.ts +14 -2
- package/src/bundler/compiler-tools.ts +66 -2
- package/src/calls/call-domain.ts +133 -6
- package/src/calls/call-store.ts +6 -0
- package/src/calls/relay-server.ts +52 -18
- package/src/calls/relay-setup-router.ts +17 -1
- package/src/calls/twilio-config.ts +3 -8
- package/src/calls/twilio-routes.ts +1 -2
- package/src/calls/types.ts +3 -1
- package/src/calls/voice-ingress-preflight.ts +1 -1
- package/src/cli/commands/browser-relay.ts +18 -12
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/credentials.ts +101 -15
- package/src/cli/commands/doctor.ts +4 -3
- package/src/cli/commands/mcp.ts +46 -59
- package/src/cli/commands/memory.ts +16 -165
- package/src/cli/commands/oauth/apps.ts +284 -0
- package/src/cli/commands/oauth/connections.ts +633 -0
- package/src/cli/commands/oauth/index.ts +52 -0
- package/src/cli/commands/oauth/providers.ts +256 -0
- package/src/cli/commands/sessions.ts +5 -2
- package/src/cli/commands/skills.ts +177 -339
- package/src/cli/http-client.ts +0 -20
- package/src/cli/main-screen.tsx +2 -2
- package/src/cli/program.ts +6 -11
- package/src/cli/reference.ts +1 -3
- package/src/cli.ts +4 -10
- package/src/config/assistant-feature-flags.ts +0 -3
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
- package/src/config/bundled-skills/computer-use/TOOLS.json +23 -5
- package/src/config/bundled-skills/computer-use/tools/{computer-use-request-control.ts → computer-use-observe.ts} +1 -5
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +21 -16
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -4
- package/src/config/bundled-skills/settings/SKILL.md +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +2 -8
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
- package/src/config/bundled-tool-registry.ts +2 -5
- package/src/config/env-registry.ts +14 -83
- package/src/config/env.ts +11 -50
- package/src/config/feature-flag-registry.json +16 -16
- package/src/config/loader.ts +0 -6
- package/src/config/schema.ts +4 -13
- package/src/config/schemas/memory-lifecycle.ts +0 -9
- package/src/config/schemas/memory-processing.ts +0 -180
- package/src/config/schemas/memory-retrieval.ts +32 -104
- package/src/config/schemas/memory.ts +0 -10
- package/src/config/skills.ts +21 -2
- package/src/config/types.ts +0 -4
- package/src/context/image-dimensions.ts +229 -0
- package/src/context/token-estimator.ts +75 -12
- package/src/context/window-manager.ts +53 -11
- package/src/daemon/assistant-attachments.ts +1 -13
- package/src/daemon/config-watcher.ts +61 -3
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +114 -31
- package/src/daemon/handlers/config-ingress.ts +8 -33
- package/src/daemon/handlers/config-slack-channel.ts +49 -46
- package/src/daemon/handlers/config-telegram.ts +32 -16
- package/src/daemon/handlers/sessions.ts +27 -36
- package/src/daemon/handlers/shared.ts +0 -130
- package/src/daemon/handlers/skills.ts +20 -1
- package/src/daemon/history-repair.ts +72 -8
- package/src/daemon/host-cu-proxy.ts +430 -0
- package/src/daemon/lifecycle.ts +67 -71
- package/src/daemon/mcp-reload-service.ts +2 -2
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/computer-use.ts +1 -129
- package/src/daemon/message-types/host-cu.ts +19 -0
- package/src/daemon/message-types/memory.ts +4 -16
- package/src/daemon/message-types/messages.ts +4 -0
- package/src/daemon/message-types/sessions.ts +4 -0
- package/src/daemon/server.ts +25 -21
- package/src/daemon/session-agent-loop-handlers.ts +40 -0
- package/src/daemon/session-agent-loop.ts +334 -48
- package/src/daemon/session-attachments.ts +1 -2
- package/src/daemon/session-error.ts +89 -6
- package/src/daemon/session-history.ts +17 -7
- package/src/daemon/session-media-retry.ts +6 -2
- package/src/daemon/session-memory.ts +69 -149
- package/src/daemon/session-process.ts +10 -1
- package/src/daemon/session-runtime-assembly.ts +49 -19
- package/src/daemon/session-slash.ts +1 -1
- package/src/daemon/session-surfaces.ts +43 -28
- package/src/daemon/session-tool-setup.ts +9 -10
- package/src/daemon/session.ts +150 -17
- package/src/daemon/tool-side-effects.ts +2 -8
- package/src/daemon/watch-handler.ts +2 -2
- package/src/events/tool-metrics-listener.ts +2 -2
- package/src/hooks/manager.ts +1 -4
- package/src/inbound/public-ingress-urls.ts +7 -7
- package/src/instrument.ts +61 -1
- package/src/logfire.ts +16 -5
- package/src/memory/admin.ts +2 -191
- package/src/memory/canonical-guardian-store.ts +38 -2
- package/src/memory/conversation-crud.ts +0 -33
- package/src/memory/conversation-key-store.ts +21 -0
- package/src/memory/conversation-queries.ts +22 -3
- package/src/memory/db-init.ts +32 -0
- package/src/memory/embedding-backend.ts +84 -8
- package/src/memory/embedding-types.ts +9 -1
- package/src/memory/indexer.ts +7 -46
- package/src/memory/items-extractor.ts +274 -76
- package/src/memory/job-handlers/backfill.ts +2 -127
- package/src/memory/job-handlers/cleanup.ts +2 -16
- package/src/memory/job-handlers/extraction.ts +2 -138
- package/src/memory/job-handlers/index-maintenance.ts +1 -6
- package/src/memory/job-handlers/summarization.ts +3 -148
- package/src/memory/job-utils.ts +21 -59
- package/src/memory/jobs-store.ts +1 -159
- package/src/memory/jobs-worker.ts +9 -52
- package/src/memory/migrations/104-core-indexes.ts +3 -3
- package/src/memory/migrations/149-oauth-tables.ts +62 -0
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
- package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
- package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
- package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
- package/src/memory/migrations/154-drop-fts.ts +20 -0
- package/src/memory/migrations/155-drop-conflicts.ts +7 -0
- package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/qdrant-client.ts +148 -51
- package/src/memory/raw-query.ts +1 -1
- package/src/memory/retriever.test.ts +294 -273
- package/src/memory/retriever.ts +421 -645
- package/src/memory/schema/calls.ts +2 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-core.ts +3 -48
- package/src/memory/schema/oauth.ts +67 -0
- package/src/memory/search/formatting.ts +263 -176
- package/src/memory/search/lexical.ts +1 -254
- package/src/memory/search/ranking.ts +0 -455
- package/src/memory/search/semantic.ts +100 -14
- package/src/memory/search/staleness.ts +47 -0
- package/src/memory/search/tier-classifier.ts +21 -0
- package/src/memory/search/types.ts +15 -77
- package/src/memory/task-memory-cleanup.ts +4 -6
- package/src/messaging/provider.ts +4 -4
- package/src/messaging/providers/gmail/client.ts +82 -2
- package/src/messaging/providers/gmail/mime-builder.ts +17 -7
- package/src/messaging/providers/gmail/people-client.ts +10 -10
- package/src/messaging/providers/telegram-bot/adapter.ts +17 -17
- package/src/messaging/providers/whatsapp/adapter.ts +11 -8
- package/src/messaging/registry.ts +2 -32
- package/src/notifications/copy-composer.ts +0 -5
- package/src/notifications/signal.ts +4 -5
- package/src/oauth/byo-connection.test.ts +133 -25
- package/src/oauth/byo-connection.ts +22 -6
- package/src/oauth/connect-orchestrator.ts +113 -57
- package/src/oauth/connect-types.ts +17 -23
- package/src/oauth/connection-resolver.ts +35 -11
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +104 -0
- package/src/oauth/oauth-store.ts +582 -0
- package/src/oauth/platform-connection.test.ts +29 -0
- package/src/oauth/platform-connection.ts +6 -5
- package/src/oauth/provider-behaviors.ts +124 -0
- package/src/oauth/scope-policy.ts +9 -2
- package/src/oauth/seed-providers.ts +167 -0
- package/src/oauth/token-persistence.ts +81 -77
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +1 -1
- package/src/permissions/prompter.ts +10 -1
- package/src/permissions/trust-store.ts +36 -1
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
- package/src/prompts/system-prompt.ts +46 -42
- package/src/providers/anthropic/client.ts +59 -20
- package/src/providers/retry.ts +1 -27
- package/src/providers/types.ts +7 -1
- package/src/runtime/AGENTS.md +9 -0
- package/src/runtime/auth/route-policy.ts +6 -6
- package/src/runtime/channel-reply-delivery.ts +0 -40
- package/src/runtime/gateway-client.ts +0 -7
- package/src/runtime/guardian-reply-router.ts +24 -22
- package/src/runtime/http-server.ts +10 -8
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/invite-redemption-service.ts +19 -1
- package/src/runtime/invite-service.ts +25 -0
- package/src/runtime/middleware/twilio-validation.ts +1 -11
- package/src/runtime/pending-interactions.ts +14 -12
- package/src/runtime/routes/brain-graph-routes.ts +10 -90
- package/src/runtime/routes/channel-delivery-routes.ts +0 -1
- package/src/runtime/routes/conversation-routes.ts +81 -19
- package/src/runtime/routes/events-routes.ts +21 -11
- package/src/runtime/routes/host-cu-routes.ts +97 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
- package/src/runtime/routes/integrations/slack/share.ts +6 -7
- package/src/runtime/routes/log-export-routes.ts +126 -8
- package/src/runtime/routes/memory-item-routes.test.ts +754 -0
- package/src/runtime/routes/memory-item-routes.ts +503 -0
- package/src/runtime/routes/session-management-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +55 -48
- package/src/runtime/routes/surface-action-routes.ts +1 -1
- package/src/runtime/routes/trust-rules-routes.ts +14 -0
- package/src/runtime/routes/watch-routes.ts +128 -0
- package/src/runtime/routes/workspace-routes.ts +2 -1
- package/src/schedule/integration-status.ts +10 -9
- package/src/security/credential-key.ts +0 -156
- package/src/security/keychain-broker-client.ts +22 -10
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +25 -3
- package/src/security/token-manager.ts +137 -64
- package/src/skills/catalog-install.ts +414 -0
- package/src/skills/include-graph.ts +32 -0
- package/src/skills/skillssh-registry.ts +503 -0
- package/src/telegram/bot-username.ts +2 -3
- package/src/tools/assets/search.ts +5 -1
- package/src/tools/browser/network-recorder.ts +1 -1
- package/src/tools/browser/network-recording-types.ts +1 -1
- package/src/tools/computer-use/definitions.ts +36 -11
- package/src/tools/computer-use/registry.ts +5 -6
- package/src/tools/credentials/broker.ts +1 -2
- package/src/tools/credentials/metadata-store.ts +17 -121
- package/src/tools/credentials/vault.ts +92 -167
- package/src/tools/memory/definitions.ts +4 -13
- package/src/tools/memory/handlers.test.ts +83 -103
- package/src/tools/memory/handlers.ts +50 -85
- package/src/tools/registry.ts +2 -7
- package/src/tools/schedule/create.ts +8 -1
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/skills/load.ts +85 -3
- package/src/tools/watch/watch-state.ts +0 -12
- package/src/util/logger.ts +7 -41
- package/src/util/platform.ts +9 -28
- package/src/watcher/providers/google-calendar.ts +2 -1
- package/src/__tests__/clarification-resolver.test.ts +0 -193
- package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
- package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
- package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
- package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
- package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
- package/src/__tests__/conflict-policy.test.ts +0 -269
- package/src/__tests__/conflict-store.test.ts +0 -372
- package/src/__tests__/contradiction-checker.test.ts +0 -361
- package/src/__tests__/entity-extractor.test.ts +0 -211
- package/src/__tests__/entity-search.test.ts +0 -1117
- package/src/__tests__/profile-compiler.test.ts +0 -392
- package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
- package/src/__tests__/session-conflict-gate.test.ts +0 -1228
- package/src/__tests__/session-profile-injection.test.ts +0 -557
- package/src/cli/commands/dev.ts +0 -129
- package/src/cli/commands/map.ts +0 -391
- package/src/cli/commands/oauth.ts +0 -77
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
- package/src/daemon/computer-use-session.ts +0 -1026
- package/src/daemon/ride-shotgun-handler.ts +0 -569
- package/src/daemon/session-conflict-gate.ts +0 -167
- package/src/daemon/session-dynamic-profile.ts +0 -77
- package/src/memory/clarification-resolver.ts +0 -417
- package/src/memory/conflict-intent.ts +0 -205
- package/src/memory/conflict-policy.ts +0 -127
- package/src/memory/conflict-store.ts +0 -410
- package/src/memory/contradiction-checker.ts +0 -508
- package/src/memory/entity-extractor.ts +0 -535
- package/src/memory/format-recall.ts +0 -47
- package/src/memory/fts-reconciler.ts +0 -165
- package/src/memory/job-handlers/conflict.ts +0 -200
- package/src/memory/profile-compiler.ts +0 -195
- package/src/memory/recall-cache.ts +0 -117
- package/src/memory/search/entity.ts +0 -535
- package/src/memory/search/query-expansion.test.ts +0 -70
- package/src/memory/search/query-expansion.ts +0 -118
- package/src/oauth/provider-base-urls.ts +0 -21
- package/src/oauth/provider-profiles.ts +0 -192
- package/src/prompts/computer-use-prompt.ts +0 -98
- package/src/runtime/routes/computer-use-routes.ts +0 -641
- package/src/runtime/routes/mcp-routes.ts +0 -20
- package/src/runtime/telegram-streaming-delivery.test.ts +0 -729
- package/src/runtime/telegram-streaming-delivery.ts +0 -393
- package/src/tools/computer-use/request-computer-control.ts +0 -56
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* Persists non-secret metadata about credentials (policy, timestamps, IDs)
|
|
5
5
|
* in a versioned JSON file under protected storage. Secret values remain
|
|
6
6
|
* in the secure key backend only.
|
|
7
|
+
*
|
|
8
|
+
* OAuth-specific fields (expiresAt, grantedScopes, oauth2TokenUrl,
|
|
9
|
+
* oauth2ClientId, oauth2TokenEndpointAuthMethod, hasRefreshToken) are now
|
|
10
|
+
* exclusively managed by the SQLite oauth-store and have been removed
|
|
11
|
+
* from this interface as of v5.
|
|
7
12
|
*/
|
|
8
13
|
|
|
9
14
|
import { randomUUID } from "node:crypto";
|
|
@@ -21,26 +26,16 @@ export interface CredentialMetadata {
|
|
|
21
26
|
allowedTools: string[];
|
|
22
27
|
allowedDomains: string[];
|
|
23
28
|
usageDescription?: string;
|
|
24
|
-
expiresAt?: number;
|
|
25
|
-
grantedScopes?: string[];
|
|
26
|
-
/** OAuth2 token endpoint — enables autonomous token refresh without an IntegrationDefinition. */
|
|
27
|
-
oauth2TokenUrl?: string;
|
|
28
|
-
/** OAuth2 client ID — paired with oauth2TokenUrl for refresh. */
|
|
29
|
-
oauth2ClientId?: string;
|
|
30
|
-
/** How the client authenticates at the token endpoint (client_secret_basic or client_secret_post). */
|
|
31
|
-
oauth2TokenEndpointAuthMethod?: string;
|
|
32
29
|
/** Human-friendly name for this credential (e.g. "fal-primary"). */
|
|
33
30
|
alias?: string;
|
|
34
31
|
/** Templates describing how to inject this credential into proxied requests. */
|
|
35
32
|
injectionTemplates?: CredentialInjectionTemplate[];
|
|
36
|
-
/** Whether a refresh token exists in the secure store for this service. */
|
|
37
|
-
hasRefreshToken?: boolean;
|
|
38
33
|
createdAt: number;
|
|
39
34
|
updatedAt: number;
|
|
40
35
|
}
|
|
41
36
|
|
|
42
37
|
/** Current on-disk schema version. */
|
|
43
|
-
const CURRENT_VERSION =
|
|
38
|
+
const CURRENT_VERSION = 5;
|
|
44
39
|
|
|
45
40
|
interface MetadataFile {
|
|
46
41
|
version: typeof CURRENT_VERSION;
|
|
@@ -88,9 +83,10 @@ function isValidCredentialRecord(
|
|
|
88
83
|
}
|
|
89
84
|
|
|
90
85
|
/**
|
|
91
|
-
* Migrate
|
|
86
|
+
* Migrate any record to v5 by stripping OAuth-specific fields that are
|
|
87
|
+
* now exclusively managed by the SQLite oauth-store.
|
|
92
88
|
*/
|
|
93
|
-
function
|
|
89
|
+
function migrateRecordToV5(
|
|
94
90
|
record: Record<string, unknown>,
|
|
95
91
|
): CredentialMetadata {
|
|
96
92
|
return {
|
|
@@ -107,73 +103,15 @@ function migrateRecordV1toV2(
|
|
|
107
103
|
typeof record.usageDescription === "string"
|
|
108
104
|
? record.usageDescription
|
|
109
105
|
: undefined,
|
|
110
|
-
expiresAt:
|
|
111
|
-
typeof record.expiresAt === "number" ? record.expiresAt : undefined,
|
|
112
|
-
grantedScopes: Array.isArray(record.grantedScopes)
|
|
113
|
-
? (record.grantedScopes as string[])
|
|
114
|
-
: undefined,
|
|
115
|
-
oauth2TokenUrl:
|
|
116
|
-
typeof record.oauth2TokenUrl === "string"
|
|
117
|
-
? record.oauth2TokenUrl
|
|
118
|
-
: undefined,
|
|
119
|
-
oauth2ClientId:
|
|
120
|
-
typeof record.oauth2ClientId === "string"
|
|
121
|
-
? record.oauth2ClientId
|
|
122
|
-
: undefined,
|
|
123
|
-
oauth2TokenEndpointAuthMethod:
|
|
124
|
-
typeof record.oauth2TokenEndpointAuthMethod === "string"
|
|
125
|
-
? record.oauth2TokenEndpointAuthMethod
|
|
126
|
-
: undefined,
|
|
127
106
|
alias: typeof record.alias === "string" ? record.alias : undefined,
|
|
128
107
|
injectionTemplates: Array.isArray(record.injectionTemplates)
|
|
129
108
|
? (record.injectionTemplates as CredentialInjectionTemplate[])
|
|
130
109
|
: undefined,
|
|
131
|
-
hasRefreshToken:
|
|
132
|
-
typeof record.hasRefreshToken === "boolean"
|
|
133
|
-
? record.hasRefreshToken
|
|
134
|
-
: undefined,
|
|
135
110
|
createdAt: record.createdAt as number,
|
|
136
111
|
updatedAt: record.updatedAt as number,
|
|
137
112
|
};
|
|
138
113
|
}
|
|
139
114
|
|
|
140
|
-
/**
|
|
141
|
-
* Migrate a v2 record to v3 by stripping the oauth2ClientSecret field.
|
|
142
|
-
* Client secrets are now read exclusively from the secure key store.
|
|
143
|
-
*/
|
|
144
|
-
function migrateRecordV2toV3(record: CredentialMetadata): CredentialMetadata {
|
|
145
|
-
const { oauth2ClientSecret: _removed, ...rest } =
|
|
146
|
-
record as CredentialMetadata & { oauth2ClientSecret?: string };
|
|
147
|
-
return rest;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Migrate v3 credentials to v4:
|
|
152
|
-
* - Delete ghost `refresh_token` metadata records
|
|
153
|
-
* - Set `hasRefreshToken: true` on corresponding `access_token` records
|
|
154
|
-
*/
|
|
155
|
-
function migrateV3toV4(
|
|
156
|
-
credentials: CredentialMetadata[],
|
|
157
|
-
): CredentialMetadata[] {
|
|
158
|
-
// Collect services that had refresh_token ghost records
|
|
159
|
-
const servicesWithRefresh = new Set<string>();
|
|
160
|
-
for (const c of credentials) {
|
|
161
|
-
if (c.field === "refresh_token") {
|
|
162
|
-
servicesWithRefresh.add(c.service);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Remove all refresh_token records and set hasRefreshToken on access_token records
|
|
167
|
-
const filtered = credentials.filter((c) => c.field !== "refresh_token");
|
|
168
|
-
for (const c of filtered) {
|
|
169
|
-
if (c.field === "access_token" && servicesWithRefresh.has(c.service)) {
|
|
170
|
-
c.hasRefreshToken = true;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return filtered;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
115
|
function loadFile(): LoadResult {
|
|
178
116
|
const raw = readTextFileSync(getMetadataPath());
|
|
179
117
|
if (raw == null) {
|
|
@@ -189,7 +127,8 @@ function loadFile(): LoadResult {
|
|
|
189
127
|
fileVersion !== 1 &&
|
|
190
128
|
fileVersion !== 2 &&
|
|
191
129
|
fileVersion !== 3 &&
|
|
192
|
-
fileVersion !== 4
|
|
130
|
+
fileVersion !== 4 &&
|
|
131
|
+
fileVersion !== 5
|
|
193
132
|
) {
|
|
194
133
|
// Unrecognized version (future, fractional, negative, zero) — refuse to touch it
|
|
195
134
|
return { unknownVersion: true };
|
|
@@ -201,24 +140,12 @@ function loadFile(): LoadResult {
|
|
|
201
140
|
const validRecords = rawCredentials.filter(isValidCredentialRecord);
|
|
202
141
|
|
|
203
142
|
if (fileVersion < CURRENT_VERSION) {
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
} else if (fileVersion === 2) {
|
|
211
|
-
credentials = migrateV3toV4(
|
|
212
|
-
(validRecords as unknown as CredentialMetadata[]).map(
|
|
213
|
-
migrateRecordV2toV3,
|
|
214
|
-
),
|
|
215
|
-
);
|
|
216
|
-
} else {
|
|
217
|
-
// fileVersion === 3
|
|
218
|
-
credentials = migrateV3toV4(
|
|
219
|
-
validRecords as unknown as CredentialMetadata[],
|
|
220
|
-
);
|
|
221
|
-
}
|
|
143
|
+
// Migrate all older versions to v5 by stripping OAuth-specific fields
|
|
144
|
+
// and removing ghost refresh_token records
|
|
145
|
+
const filtered = validRecords.filter(
|
|
146
|
+
(r) => (r as Record<string, unknown>).field !== "refresh_token",
|
|
147
|
+
);
|
|
148
|
+
const credentials = filtered.map(migrateRecordToV5);
|
|
222
149
|
const migrated: MetadataFile = { version: CURRENT_VERSION, credentials };
|
|
223
150
|
try {
|
|
224
151
|
saveFile(migrated);
|
|
@@ -272,17 +199,10 @@ export function upsertCredentialMetadata(
|
|
|
272
199
|
allowedTools?: string[];
|
|
273
200
|
allowedDomains?: string[];
|
|
274
201
|
usageDescription?: string;
|
|
275
|
-
/** Pass `null` to explicitly clear a previously-set expiry. */
|
|
276
|
-
expiresAt?: number | null;
|
|
277
|
-
grantedScopes?: string[];
|
|
278
|
-
oauth2TokenUrl?: string;
|
|
279
|
-
oauth2ClientId?: string;
|
|
280
|
-
oauth2TokenEndpointAuthMethod?: string;
|
|
281
202
|
/** Pass `null` to explicitly clear a previously-set alias. */
|
|
282
203
|
alias?: string | null;
|
|
283
204
|
/** Pass `null` to explicitly clear injection templates. */
|
|
284
205
|
injectionTemplates?: CredentialInjectionTemplate[] | null;
|
|
285
|
-
hasRefreshToken?: boolean;
|
|
286
206
|
},
|
|
287
207
|
): CredentialMetadata {
|
|
288
208
|
const result = loadFile();
|
|
@@ -305,22 +225,6 @@ export function upsertCredentialMetadata(
|
|
|
305
225
|
existing.allowedDomains = policy.allowedDomains;
|
|
306
226
|
if (policy?.usageDescription !== undefined)
|
|
307
227
|
existing.usageDescription = policy.usageDescription;
|
|
308
|
-
if (policy?.expiresAt !== undefined) {
|
|
309
|
-
if (policy.expiresAt == null) {
|
|
310
|
-
delete existing.expiresAt;
|
|
311
|
-
} else {
|
|
312
|
-
existing.expiresAt = policy.expiresAt;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
if (policy?.grantedScopes !== undefined)
|
|
316
|
-
existing.grantedScopes = policy.grantedScopes;
|
|
317
|
-
if (policy?.oauth2TokenUrl !== undefined)
|
|
318
|
-
existing.oauth2TokenUrl = policy.oauth2TokenUrl;
|
|
319
|
-
if (policy?.oauth2ClientId !== undefined)
|
|
320
|
-
existing.oauth2ClientId = policy.oauth2ClientId;
|
|
321
|
-
if (policy?.oauth2TokenEndpointAuthMethod !== undefined)
|
|
322
|
-
existing.oauth2TokenEndpointAuthMethod =
|
|
323
|
-
policy.oauth2TokenEndpointAuthMethod;
|
|
324
228
|
if (policy?.alias !== undefined) {
|
|
325
229
|
if (policy.alias == null) {
|
|
326
230
|
delete existing.alias;
|
|
@@ -335,8 +239,6 @@ export function upsertCredentialMetadata(
|
|
|
335
239
|
existing.injectionTemplates = policy.injectionTemplates;
|
|
336
240
|
}
|
|
337
241
|
}
|
|
338
|
-
if (policy?.hasRefreshToken !== undefined)
|
|
339
|
-
existing.hasRefreshToken = policy.hasRefreshToken;
|
|
340
242
|
existing.updatedAt = now;
|
|
341
243
|
saveFile(data);
|
|
342
244
|
return existing;
|
|
@@ -349,14 +251,8 @@ export function upsertCredentialMetadata(
|
|
|
349
251
|
allowedTools: policy?.allowedTools ?? [],
|
|
350
252
|
allowedDomains: policy?.allowedDomains ?? [],
|
|
351
253
|
usageDescription: policy?.usageDescription,
|
|
352
|
-
expiresAt: policy?.expiresAt ?? undefined,
|
|
353
|
-
grantedScopes: policy?.grantedScopes,
|
|
354
|
-
oauth2TokenUrl: policy?.oauth2TokenUrl,
|
|
355
|
-
oauth2ClientId: policy?.oauth2ClientId,
|
|
356
|
-
oauth2TokenEndpointAuthMethod: policy?.oauth2TokenEndpointAuthMethod,
|
|
357
254
|
alias: policy?.alias ?? undefined,
|
|
358
255
|
injectionTemplates: policy?.injectionTemplates ?? undefined,
|
|
359
|
-
hasRefreshToken: policy?.hasRefreshToken,
|
|
360
256
|
createdAt: now,
|
|
361
257
|
updatedAt: now,
|
|
362
258
|
};
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { getConfig } from "../../config/loader.js";
|
|
2
2
|
import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
disconnectOAuthProvider,
|
|
5
|
+
getAppByProviderAndClientId,
|
|
6
|
+
getMostRecentAppByProvider,
|
|
7
|
+
getProvider,
|
|
8
|
+
} from "../../oauth/oauth-store.js";
|
|
9
|
+
import {
|
|
10
|
+
getProviderBehavior,
|
|
5
11
|
resolveService,
|
|
6
12
|
SERVICE_ALIASES,
|
|
7
|
-
} from "../../oauth/provider-
|
|
13
|
+
} from "../../oauth/provider-behaviors.js";
|
|
8
14
|
import { RiskLevel } from "../../permissions/types.js";
|
|
9
15
|
import type { ToolDefinition } from "../../providers/types.js";
|
|
10
16
|
import { buildAssistantEvent } from "../../runtime/assistant-event.js";
|
|
11
17
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
12
18
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
13
|
-
import { credentialKey
|
|
14
|
-
import type { TokenEndpointAuthMethod } from "../../security/oauth2.js";
|
|
19
|
+
import { credentialKey } from "../../security/credential-key.js";
|
|
15
20
|
import {
|
|
16
21
|
deleteSecureKeyAsync,
|
|
17
22
|
getSecureKey,
|
|
@@ -36,50 +41,6 @@ import { toPolicyFromInput, validatePolicyInput } from "./policy-validate.js";
|
|
|
36
41
|
|
|
37
42
|
const log = getLogger("credential-vault");
|
|
38
43
|
|
|
39
|
-
/**
|
|
40
|
-
* Look up a stored OAuth secret (e.g. client_secret) for a service from the
|
|
41
|
-
* secure store. Checks both the canonical and alias service names.
|
|
42
|
-
*/
|
|
43
|
-
function findStoredOAuthSecret(
|
|
44
|
-
service: string,
|
|
45
|
-
field: string,
|
|
46
|
-
): string | undefined {
|
|
47
|
-
const servicesToCheck = [service];
|
|
48
|
-
// Also check the alias if the input is the canonical name, or vice versa
|
|
49
|
-
for (const [alias, canonical] of Object.entries(SERVICE_ALIASES)) {
|
|
50
|
-
if (canonical === service) servicesToCheck.push(alias);
|
|
51
|
-
if (alias === service) servicesToCheck.push(canonical);
|
|
52
|
-
}
|
|
53
|
-
for (const svc of servicesToCheck) {
|
|
54
|
-
const value = getSecureKey(credentialKey(svc, field));
|
|
55
|
-
if (value) return value;
|
|
56
|
-
}
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Look up the stored OAuth client_id for a service from credential metadata.
|
|
62
|
-
* Checks both the canonical and alias service names.
|
|
63
|
-
*/
|
|
64
|
-
function findStoredOAuthClientId(service: string): string | undefined {
|
|
65
|
-
const servicesToCheck = [service];
|
|
66
|
-
for (const [alias, canonical] of Object.entries(SERVICE_ALIASES)) {
|
|
67
|
-
if (canonical === service) servicesToCheck.push(alias);
|
|
68
|
-
if (alias === service) servicesToCheck.push(canonical);
|
|
69
|
-
}
|
|
70
|
-
// Check metadata first (written by oauth2_connect after successful auth)
|
|
71
|
-
for (const svc of servicesToCheck) {
|
|
72
|
-
const meta = getCredentialMetadata(svc, "access_token");
|
|
73
|
-
if (meta?.oauth2ClientId) return meta.oauth2ClientId;
|
|
74
|
-
}
|
|
75
|
-
// Fall back to secure key store (written by credential_store prompt action)
|
|
76
|
-
for (const svc of servicesToCheck) {
|
|
77
|
-
const value = getSecureKey(credentialKey(svc, "client_id"));
|
|
78
|
-
if (value) return value;
|
|
79
|
-
}
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
44
|
class CredentialStoreTool implements Tool {
|
|
84
45
|
name = "credential_store";
|
|
85
46
|
description =
|
|
@@ -151,16 +112,6 @@ class CredentialStoreTool implements Tool {
|
|
|
151
112
|
description:
|
|
152
113
|
'Human-readable description of intended usage (for store/prompt actions), e.g. "GitHub login for pushing changes"',
|
|
153
114
|
},
|
|
154
|
-
auth_url: {
|
|
155
|
-
type: "string",
|
|
156
|
-
description:
|
|
157
|
-
"OAuth2 authorization endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
|
|
158
|
-
},
|
|
159
|
-
token_url: {
|
|
160
|
-
type: "string",
|
|
161
|
-
description:
|
|
162
|
-
"OAuth2 token endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
|
|
163
|
-
},
|
|
164
115
|
scopes: {
|
|
165
116
|
type: "array",
|
|
166
117
|
items: { type: "string" },
|
|
@@ -172,27 +123,11 @@ class CredentialStoreTool implements Tool {
|
|
|
172
123
|
description:
|
|
173
124
|
"OAuth2 client ID (only for oauth2_connect action). If omitted, looked up from previously stored credentials.",
|
|
174
125
|
},
|
|
175
|
-
extra_params: {
|
|
176
|
-
type: "object",
|
|
177
|
-
description:
|
|
178
|
-
"Extra query params for OAuth2 auth URL (only for oauth2_connect action)",
|
|
179
|
-
},
|
|
180
|
-
userinfo_url: {
|
|
181
|
-
type: "string",
|
|
182
|
-
description:
|
|
183
|
-
"Endpoint to fetch account info after OAuth2 auth (only for oauth2_connect action)",
|
|
184
|
-
},
|
|
185
126
|
client_secret: {
|
|
186
127
|
type: "string",
|
|
187
128
|
description:
|
|
188
129
|
"OAuth2 client secret for providers that require it (e.g. Google, Slack). If omitted, looked up from previously stored credentials; if still absent, PKCE-only is used (only for oauth2_connect action)",
|
|
189
130
|
},
|
|
190
|
-
token_endpoint_auth_method: {
|
|
191
|
-
type: "string",
|
|
192
|
-
enum: ["client_secret_basic", "client_secret_post"],
|
|
193
|
-
description:
|
|
194
|
-
'How to send client credentials at the token endpoint: "client_secret_post" (default, in POST body) or "client_secret_basic" (HTTP Basic Auth header). Only for oauth2_connect action.',
|
|
195
|
-
},
|
|
196
131
|
alias: {
|
|
197
132
|
type: "string",
|
|
198
133
|
description:
|
|
@@ -243,7 +178,6 @@ class CredentialStoreTool implements Tool {
|
|
|
243
178
|
input: Record<string, unknown>,
|
|
244
179
|
context: ToolContext,
|
|
245
180
|
): Promise<ToolExecutionResult> {
|
|
246
|
-
migrateKeys();
|
|
247
181
|
const action = input.action as string;
|
|
248
182
|
|
|
249
183
|
switch (action) {
|
|
@@ -517,6 +451,21 @@ class CredentialStoreTool implements Tool {
|
|
|
517
451
|
"metadata delete failed after removing credential",
|
|
518
452
|
);
|
|
519
453
|
}
|
|
454
|
+
// Also clean up any OAuth connection for this service (best-effort)
|
|
455
|
+
try {
|
|
456
|
+
const oauthResult = await disconnectOAuthProvider(service);
|
|
457
|
+
if (oauthResult === "error") {
|
|
458
|
+
log.warn(
|
|
459
|
+
{ service },
|
|
460
|
+
"OAuth disconnect failed after removing credential — secure key deletion error",
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
} catch (err) {
|
|
464
|
+
log.warn(
|
|
465
|
+
{ service, err },
|
|
466
|
+
"OAuth disconnect failed after removing credential",
|
|
467
|
+
);
|
|
468
|
+
}
|
|
520
469
|
return {
|
|
521
470
|
content: `Deleted credential for ${service}/${field}.`,
|
|
522
471
|
isError: false,
|
|
@@ -777,51 +726,42 @@ class CredentialStoreTool implements Tool {
|
|
|
777
726
|
// Resolve aliases (e.g. "gmail" → "integration:gmail")
|
|
778
727
|
const service = resolveService(rawService);
|
|
779
728
|
|
|
780
|
-
//
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
729
|
+
// Code-side behavioral fields (identityVerifier, setup, etc.)
|
|
730
|
+
const behavior = getProviderBehavior(service);
|
|
731
|
+
// Protocol-level config from the DB (authUrl, tokenUrl, scopes, etc.)
|
|
732
|
+
const providerRow = getProvider(service);
|
|
733
|
+
|
|
734
|
+
// Resolve client_id and client_secret.
|
|
735
|
+
// Priority:
|
|
736
|
+
// 1. Explicit input from the caller
|
|
737
|
+
// 2. oauth-store DB — when clientId is already known, look up the
|
|
738
|
+
// matching app so the secret comes from the same app. Only fall
|
|
739
|
+
// back to the most-recent-app heuristic when clientId is unknown.
|
|
740
|
+
let clientId = input.client_id as string | undefined;
|
|
741
|
+
let clientSecret = input.client_secret as string | undefined;
|
|
742
|
+
|
|
743
|
+
if (!clientId || !clientSecret) {
|
|
744
|
+
const dbApp = clientId
|
|
745
|
+
? getAppByProviderAndClientId(service, clientId)
|
|
746
|
+
: getMostRecentAppByProvider(service);
|
|
747
|
+
if (dbApp) {
|
|
748
|
+
if (!clientId) clientId = dbApp.clientId;
|
|
749
|
+
if (!clientSecret) {
|
|
750
|
+
clientSecret = getSecureKey(dbApp.clientSecretCredentialPath);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
790
754
|
|
|
791
755
|
// Early guardrails that stay in vault.ts (credential resolution is vault-specific)
|
|
792
756
|
const inputScopes = input.scopes as string[] | undefined;
|
|
793
757
|
|
|
794
|
-
if (
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
} else {
|
|
800
|
-
// Custom/unknown provider: require authUrl, tokenUrl, scopes from input
|
|
801
|
-
if (!input.auth_url)
|
|
802
|
-
return {
|
|
803
|
-
content:
|
|
804
|
-
"Error: auth_url is required for oauth2_connect action (no well-known config for this service)",
|
|
805
|
-
isError: true,
|
|
806
|
-
};
|
|
807
|
-
if (!input.token_url)
|
|
808
|
-
return {
|
|
809
|
-
content:
|
|
810
|
-
"Error: token_url is required for oauth2_connect action (no well-known config for this service)",
|
|
811
|
-
isError: true,
|
|
812
|
-
};
|
|
813
|
-
if (!inputScopes)
|
|
814
|
-
return {
|
|
815
|
-
content:
|
|
816
|
-
"Error: scopes is required for oauth2_connect action (no well-known config for this service)",
|
|
817
|
-
isError: true,
|
|
818
|
-
};
|
|
758
|
+
if (!providerRow) {
|
|
759
|
+
return {
|
|
760
|
+
content: `Error: no OAuth provider registered for "${service}". Ensure the provider is seeded in the database.`,
|
|
761
|
+
isError: true,
|
|
762
|
+
};
|
|
819
763
|
}
|
|
820
764
|
|
|
821
|
-
const authUrl =
|
|
822
|
-
(input.auth_url as string | undefined) ?? profile?.authUrl;
|
|
823
|
-
const tokenUrl =
|
|
824
|
-
(input.token_url as string | undefined) ?? profile?.tokenUrl;
|
|
825
765
|
if (!clientId)
|
|
826
766
|
return {
|
|
827
767
|
content:
|
|
@@ -833,10 +773,10 @@ class CredentialStoreTool implements Tool {
|
|
|
833
773
|
// agent to collect it from the user rather than letting it improvise
|
|
834
774
|
// browser-automation workarounds that inevitably fail.
|
|
835
775
|
const requiresSecret =
|
|
836
|
-
|
|
837
|
-
!!(
|
|
776
|
+
behavior?.setup?.requiresClientSecret ??
|
|
777
|
+
!!(providerRow.tokenEndpointAuthMethod || providerRow.extraParams);
|
|
838
778
|
if (requiresSecret && !clientSecret) {
|
|
839
|
-
const skillId =
|
|
779
|
+
const skillId = behavior?.setupSkillId;
|
|
840
780
|
const skillHint = skillId
|
|
841
781
|
? `\n\nLoad the "${skillId}" skill for provider-specific instructions on obtaining the client secret.`
|
|
842
782
|
: '\n\nUse credential_store with action "prompt" to securely collect the client_secret from the user before calling oauth2_connect again.';
|
|
@@ -846,25 +786,8 @@ class CredentialStoreTool implements Tool {
|
|
|
846
786
|
};
|
|
847
787
|
}
|
|
848
788
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
} catch {
|
|
852
|
-
return {
|
|
853
|
-
content:
|
|
854
|
-
"Error: credential metadata file has an unrecognized version; cannot store credentials",
|
|
855
|
-
isError: true,
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
const tokenEndpointAuthMethod =
|
|
860
|
-
(input.token_endpoint_auth_method as
|
|
861
|
-
| TokenEndpointAuthMethod
|
|
862
|
-
| undefined) ?? profile?.tokenEndpointAuthMethod;
|
|
863
|
-
|
|
864
|
-
// Delegate to the shared orchestrator.
|
|
865
|
-
// For profile-based providers, pass user scopes as requestedScopes so the
|
|
866
|
-
// scope policy engine (resolveScopes) is invoked. For custom providers,
|
|
867
|
-
// pass scopes directly as an explicit override.
|
|
789
|
+
// Delegate to the shared orchestrator — it resolves authUrl, tokenUrl,
|
|
790
|
+
// extraParams, userinfoUrl, and tokenEndpointAuthMethod from the DB.
|
|
868
791
|
const result = await orchestrateOAuthConnect({
|
|
869
792
|
service: rawService,
|
|
870
793
|
clientId,
|
|
@@ -872,24 +795,7 @@ class CredentialStoreTool implements Tool {
|
|
|
872
795
|
isInteractive: !!context.isInteractive,
|
|
873
796
|
sendToClient: context.sendToClient,
|
|
874
797
|
allowedTools: input.allowed_tools as string[] | undefined,
|
|
875
|
-
|
|
876
|
-
tokenUrl,
|
|
877
|
-
...(profile
|
|
878
|
-
? {
|
|
879
|
-
// Profile-based: let orchestrator resolve scopes via policy engine.
|
|
880
|
-
// Only pass requestedScopes if the user explicitly provided scopes.
|
|
881
|
-
...(inputScopes ? { requestedScopes: inputScopes } : {}),
|
|
882
|
-
}
|
|
883
|
-
: {
|
|
884
|
-
// Custom provider: explicit scopes override (bypasses policy engine)
|
|
885
|
-
scopes: inputScopes,
|
|
886
|
-
}),
|
|
887
|
-
extraParams:
|
|
888
|
-
(input.extra_params as Record<string, string> | undefined) ??
|
|
889
|
-
profile?.extraParams,
|
|
890
|
-
userinfoUrl:
|
|
891
|
-
(input.userinfo_url as string | undefined) ?? profile?.userinfoUrl,
|
|
892
|
-
tokenEndpointAuthMethod,
|
|
798
|
+
...(inputScopes ? { requestedScopes: inputScopes } : {}),
|
|
893
799
|
onDeferredComplete: (deferredResult) => {
|
|
894
800
|
// Emit oauth_connect_result to all connected SSE clients so the
|
|
895
801
|
// UI can update immediately when the deferred browser flow completes.
|
|
@@ -958,8 +864,8 @@ class CredentialStoreTool implements Tool {
|
|
|
958
864
|
};
|
|
959
865
|
}
|
|
960
866
|
const resolvedService = resolveService(rawService);
|
|
961
|
-
const
|
|
962
|
-
if (!
|
|
867
|
+
const descProviderRow = getProvider(resolvedService);
|
|
868
|
+
if (!descProviderRow) {
|
|
963
869
|
return {
|
|
964
870
|
content: `No well-known OAuth config found for "${rawService}". Available services: ${Object.keys(
|
|
965
871
|
SERVICE_ALIASES,
|
|
@@ -968,11 +874,17 @@ class CredentialStoreTool implements Tool {
|
|
|
968
874
|
};
|
|
969
875
|
}
|
|
970
876
|
|
|
877
|
+
const descBehavior = getProviderBehavior(resolvedService);
|
|
878
|
+
|
|
971
879
|
// Compute the redirect URI based on callback transport
|
|
972
880
|
let redirectUri: string;
|
|
973
|
-
const transport =
|
|
974
|
-
|
|
975
|
-
|
|
881
|
+
const transport =
|
|
882
|
+
(descProviderRow.callbackTransport as
|
|
883
|
+
| "loopback"
|
|
884
|
+
| "gateway"
|
|
885
|
+
| null) ?? "gateway";
|
|
886
|
+
if (transport === "loopback" && descProviderRow.loopbackPort) {
|
|
887
|
+
redirectUri = `http://127.0.0.1:${descProviderRow.loopbackPort}/oauth/callback`;
|
|
976
888
|
} else if (transport === "loopback") {
|
|
977
889
|
redirectUri =
|
|
978
890
|
"(automatic — no redirect URI needed, uses random localhost port)";
|
|
@@ -986,26 +898,39 @@ class CredentialStoreTool implements Tool {
|
|
|
986
898
|
redirectUri = `${baseUrl}/webhooks/oauth/callback`;
|
|
987
899
|
} catch {
|
|
988
900
|
redirectUri =
|
|
989
|
-
"(requires
|
|
901
|
+
"(requires ingress.publicBaseUrl — not currently configured)";
|
|
990
902
|
}
|
|
991
903
|
}
|
|
992
904
|
|
|
993
905
|
// Prefer explicit setup metadata, fall back to heuristic
|
|
994
906
|
const requiresClientSecret =
|
|
995
|
-
|
|
996
|
-
!!(
|
|
907
|
+
descBehavior?.setup?.requiresClientSecret ??
|
|
908
|
+
!!(
|
|
909
|
+
descProviderRow.tokenEndpointAuthMethod ||
|
|
910
|
+
descProviderRow.extraParams
|
|
911
|
+
);
|
|
912
|
+
|
|
913
|
+
const descDefaultScopes: string[] = descProviderRow.defaultScopes
|
|
914
|
+
? JSON.parse(descProviderRow.defaultScopes)
|
|
915
|
+
: [];
|
|
997
916
|
|
|
998
917
|
const info: Record<string, unknown> = {
|
|
999
918
|
service: resolvedService,
|
|
1000
|
-
authUrl:
|
|
1001
|
-
tokenUrl:
|
|
1002
|
-
scopes:
|
|
919
|
+
authUrl: descProviderRow.authUrl,
|
|
920
|
+
tokenUrl: descProviderRow.tokenUrl,
|
|
921
|
+
scopes: descDefaultScopes,
|
|
1003
922
|
callbackTransport: transport,
|
|
1004
923
|
redirectUri,
|
|
1005
924
|
requiresClientSecret,
|
|
1006
925
|
};
|
|
1007
|
-
if (
|
|
1008
|
-
if (
|
|
926
|
+
if (descBehavior?.setup) info.setup = descBehavior.setup;
|
|
927
|
+
if (descProviderRow.extraParams) {
|
|
928
|
+
try {
|
|
929
|
+
info.extraParams = JSON.parse(descProviderRow.extraParams);
|
|
930
|
+
} catch {
|
|
931
|
+
// Non-fatal
|
|
932
|
+
}
|
|
933
|
+
}
|
|
1009
934
|
|
|
1010
935
|
return { content: JSON.stringify(info, null, 2), isError: false };
|
|
1011
936
|
}
|
|
@@ -3,7 +3,7 @@ import type { ToolDefinition } from "../../providers/types.js";
|
|
|
3
3
|
export const memoryRecallDefinition: ToolDefinition = {
|
|
4
4
|
name: "memory_recall",
|
|
5
5
|
description:
|
|
6
|
-
"
|
|
6
|
+
"Hybrid search across memory (semantic and recency) for specific information. Use this when you need to recall details about past conversations, decisions, preferences, project context, or any prior knowledge. Returns formatted memory context with item IDs for use with memory_manage.",
|
|
7
7
|
input_schema: {
|
|
8
8
|
type: "object",
|
|
9
9
|
properties: {
|
|
@@ -11,10 +11,6 @@ export const memoryRecallDefinition: ToolDefinition = {
|
|
|
11
11
|
type: "string",
|
|
12
12
|
description: "The search query — be specific and descriptive",
|
|
13
13
|
},
|
|
14
|
-
max_results: {
|
|
15
|
-
type: "number",
|
|
16
|
-
description: "Maximum number of memory items to return (default: 10)",
|
|
17
|
-
},
|
|
18
14
|
scope: {
|
|
19
15
|
type: "string",
|
|
20
16
|
enum: ["default", "conversation"],
|
|
@@ -44,17 +40,12 @@ const memoryManageProperties = {
|
|
|
44
40
|
kind: {
|
|
45
41
|
type: "string" as const,
|
|
46
42
|
enum: [
|
|
43
|
+
"identity",
|
|
47
44
|
"preference",
|
|
48
|
-
"
|
|
45
|
+
"project",
|
|
49
46
|
"decision",
|
|
50
|
-
"
|
|
51
|
-
"relationship",
|
|
47
|
+
"constraint",
|
|
52
48
|
"event",
|
|
53
|
-
"opinion",
|
|
54
|
-
"instruction",
|
|
55
|
-
"style",
|
|
56
|
-
"playbook",
|
|
57
|
-
"learning",
|
|
58
49
|
],
|
|
59
50
|
description: "Category of the memory item (required for save)",
|
|
60
51
|
},
|