@vellumai/assistant 0.8.4 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +33 -1
- package/ARCHITECTURE.md +3 -3
- package/bunfig.toml +6 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/docs/credential-execution-service.md +6 -6
- package/docs/plugins.md +4 -3
- package/knip.json +2 -1
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
- package/openapi.yaml +2748 -216
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +3 -2
- package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
- package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/annotate-risk-options.test.ts +1 -0
- package/src/__tests__/anthropic-provider.test.ts +34 -37
- package/src/__tests__/approval-cascade.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +9 -13
- package/src/__tests__/assert-not-live-db.ts +79 -0
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
- package/src/__tests__/audit-log-rotation.test.ts +72 -18
- package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
- package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
- package/src/__tests__/browser-skill-endstate.test.ts +3 -3
- package/src/__tests__/btw-routes.test.ts +5 -5
- package/src/__tests__/call-controller.test.ts +3 -3
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +3 -2
- package/src/__tests__/channel-guardian.test.ts +6 -5
- package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
- package/src/__tests__/channel-reply-delivery.test.ts +35 -0
- package/src/__tests__/channel-retry-sweep.test.ts +320 -3
- package/src/__tests__/checker.test.ts +18 -27
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/compaction-trail-store.test.ts +264 -0
- package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
- package/src/__tests__/computer-use-tools.test.ts +14 -18
- package/src/__tests__/config-loader-backfill.test.ts +13 -28
- package/src/__tests__/config-loader-corrupt.test.ts +5 -5
- package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
- package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
- package/src/__tests__/config-schema.test.ts +10 -10
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/connection-model-compat.test.ts +83 -0
- package/src/__tests__/contacts-tools.test.ts +3 -2
- package/src/__tests__/context-token-estimator.test.ts +22 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
- package/src/__tests__/conversation-agent-loop.test.ts +581 -54
- package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
- package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
- package/src/__tests__/conversation-attention-store.test.ts +101 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +61 -0
- package/src/__tests__/conversation-fork-crud.test.ts +239 -15
- package/src/__tests__/conversation-fork-route.test.ts +3 -2
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
- package/src/__tests__/conversation-lifecycle.test.ts +53 -11
- package/src/__tests__/conversation-list-source.test.ts +3 -2
- package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
- package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
- package/src/__tests__/conversation-pairing.test.ts +53 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
- package/src/__tests__/conversation-process-callsite.test.ts +1 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +333 -291
- package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
- package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
- package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
- package/src/__tests__/conversation-skill-tools.test.ts +40 -147
- package/src/__tests__/conversation-slash-queue.test.ts +84 -32
- package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
- package/src/__tests__/conversation-speed-override.test.ts +1 -0
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
- package/src/__tests__/conversation-sync-tags.test.ts +218 -35
- package/src/__tests__/conversation-title-service.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
- package/src/__tests__/conversation-usage.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
- package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
- package/src/__tests__/credential-broker-server-use.test.ts +5 -5
- package/src/__tests__/credential-execution-client.test.ts +72 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-health-service.test.ts +252 -3
- package/src/__tests__/credential-security-invariants.test.ts +6 -5
- package/src/__tests__/credential-vault-unit.test.ts +21 -21
- package/src/__tests__/credential-vault.test.ts +5 -5
- package/src/__tests__/cross-provider-web-search.test.ts +56 -2
- package/src/__tests__/db-connection-isolation.test.ts +7 -6
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
- package/src/__tests__/db-test-helpers.ts +58 -0
- package/src/__tests__/disk-pressure-guard.test.ts +58 -41
- package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
- package/src/__tests__/disk-pressure-routes.test.ts +0 -33
- package/src/__tests__/disk-pressure-tools.test.ts +0 -4
- package/src/__tests__/dm-persistence.test.ts +26 -40
- package/src/__tests__/document-create-dedupe.test.ts +189 -0
- package/src/__tests__/document-find-replace.test.ts +3 -2
- package/src/__tests__/document-tool-security.test.ts +81 -2
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
- package/src/__tests__/encrypted-store.test.ts +11 -9
- package/src/__tests__/feature-flag-test-helpers.ts +53 -0
- package/src/__tests__/filing-service.test.ts +1 -0
- package/src/__tests__/first-greeting.test.ts +62 -12
- package/src/__tests__/gateway-flag-listener.test.ts +236 -0
- package/src/__tests__/gemini-provider.test.ts +104 -0
- package/src/__tests__/guardian-action-sweep.test.ts +3 -2
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +10 -7
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
- package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
- package/src/__tests__/heartbeat-service.test.ts +5 -0
- package/src/__tests__/helpers/mock-logger.ts +26 -0
- package/src/__tests__/host-bash-routes.test.ts +1 -0
- package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
- package/src/__tests__/host-shell-tool.test.ts +6 -5
- package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
- package/src/__tests__/http-conversation-lineage.test.ts +3 -2
- package/src/__tests__/http-user-message-parity.test.ts +29 -7
- package/src/__tests__/identity-intro-cache.test.ts +133 -22
- package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
- package/src/__tests__/inference-profile-reaper.test.ts +3 -2
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/injector-disk-pressure.test.ts +3 -17
- package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
- package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
- package/src/__tests__/llm-context-normalization.test.ts +42 -0
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +408 -9
- package/src/__tests__/llm-schema.test.ts +1 -1
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
- package/src/__tests__/mcp-abort-signal.test.ts +16 -2
- package/src/__tests__/mcp-client-auth.test.ts +14 -0
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/messaging-send-tool.test.ts +1 -0
- package/src/__tests__/migration-import-from-url.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +18 -2
- package/src/__tests__/model-intents.test.ts +4 -6
- package/src/__tests__/native-web-search.test.ts +30 -2
- package/src/__tests__/notification-deep-link.test.ts +62 -0
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/oauth-commands-routes.test.ts +37 -0
- package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
- package/src/__tests__/oauth-store.test.ts +3 -2
- package/src/__tests__/onboarding-template-contract.test.ts +4 -3
- package/src/__tests__/openai-provider.test.ts +54 -9
- package/src/__tests__/openai-responses-provider.test.ts +176 -14
- package/src/__tests__/openrouter-provider-only.test.ts +27 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
- package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
- package/src/__tests__/persistence-pipeline.test.ts +139 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -2
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +11 -13
- package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/process-message-background-slack.test.ts +21 -16
- package/src/__tests__/process-message-display-content.test.ts +19 -22
- package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
- package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
- package/src/__tests__/provider-registry-ollama.test.ts +45 -22
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/recording-handler.test.ts +1 -0
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
- package/src/__tests__/registry.test.ts +84 -84
- package/src/__tests__/relay-server.test.ts +10 -10
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/schedule-store.test.ts +16 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
- package/src/__tests__/secret-ingress-http.test.ts +5 -1
- package/src/__tests__/secure-keys.test.ts +3 -3
- package/src/__tests__/send-endpoint-busy.test.ts +81 -42
- package/src/__tests__/server-history-render.test.ts +4 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
- package/src/__tests__/skill-feature-flags.test.ts +16 -18
- package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
- package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
- package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
- package/src/__tests__/skill-tool-factory.test.ts +97 -96
- package/src/__tests__/slack-channel-config.test.ts +3 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
- package/src/__tests__/subagent-disposal.test.ts +27 -8
- package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
- package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
- package/src/__tests__/subagent-manager-notify.test.ts +20 -8
- package/src/__tests__/subagent-notify-parent.test.ts +6 -5
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
- package/src/__tests__/subagent-tools.test.ts +2 -1
- package/src/__tests__/suggestion-routes.test.ts +2 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +183 -131
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/test-preload-verifier.ts +68 -0
- package/src/__tests__/test-preload.ts +32 -39
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
- package/src/__tests__/tool-executor.test.ts +64 -72
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +3 -2
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/validate-input.test.ts +381 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
- package/src/__tests__/voice-session-bridge.test.ts +37 -28
- package/src/__tests__/workspace-git-service.test.ts +6 -5
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
- package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +6 -7
- package/src/agent/loop.ts +88 -0
- package/src/api/README.md +127 -0
- package/src/api/constants/call-sites.ts +27 -0
- package/src/api/events/assistant-outbound-attachment.ts +51 -0
- package/src/api/events/assistant-text-delta.ts +32 -0
- package/src/api/events/assistant-turn-start.ts +33 -0
- package/src/api/events/document-comment-created.ts +48 -0
- package/src/api/events/document-comment-deleted.ts +24 -0
- package/src/api/events/document-comment-reopened.ts +25 -0
- package/src/api/events/document-comment-resolved.ts +27 -0
- package/src/api/events/generation-cancelled.ts +24 -0
- package/src/api/events/generation-handoff.ts +41 -0
- package/src/api/events/message-complete.ts +42 -0
- package/src/api/events/open-url.ts +30 -0
- package/src/api/events/relationship-state-updated.ts +25 -0
- package/src/api/events/tool-use-start.ts +32 -0
- package/src/api/index.ts +129 -0
- package/src/api/package.json +10 -0
- package/src/api/responses/llm-context-response.ts +39 -0
- package/src/api/responses/llm-request-log-entry.ts +93 -0
- package/src/api/responses/memory-recall-log.ts +65 -0
- package/src/api/responses/memory-v2-activation-log.ts +78 -0
- package/src/background-wake/background-wake-routes.test.ts +868 -0
- package/src/background-wake/platform-client.test.ts +308 -0
- package/src/background-wake/platform-client.ts +167 -0
- package/src/background-wake/publisher.ts +91 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/background-wake/wake-intent-hooks.test.ts +282 -0
- package/src/calls/guardian-dispatch.ts +1 -0
- package/src/calls/voice-session-bridge.ts +4 -4
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/__tests__/notifications.test.ts +184 -40
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
- package/src/cli/commands/channels/index.ts +229 -0
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +176 -1
- package/src/cli/commands/memory-v3-render.ts +491 -0
- package/src/cli/commands/memory-v3.ts +567 -0
- package/src/cli/commands/notifications.ts +365 -55
- package/src/cli/lib/open-browser.ts +7 -2
- package/src/cli/program.ts +4 -0
- package/src/config/assistant-feature-flags.ts +39 -46
- package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
- package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/call-site-defaults.ts +8 -7
- package/src/config/feature-flag-cache.ts +86 -0
- package/src/config/feature-flag-registry.json +33 -17
- package/src/config/llm-context-resolution.ts +10 -1
- package/src/config/llm-resolver.ts +121 -15
- package/src/config/loader.ts +4 -5
- package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
- package/src/config/schemas/call-site-catalog.ts +21 -7
- package/src/config/schemas/heartbeat.ts +1 -1
- package/src/config/schemas/llm.ts +102 -2
- package/src/config/schemas/memory-v2.ts +272 -0
- package/src/config/schemas/memory.ts +2 -1
- package/src/config/schemas/services.ts +6 -2
- package/src/config/seed-inference-profiles.ts +36 -16
- package/src/context/compactor.ts +52 -0
- package/src/context/token-estimator.ts +10 -5
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/credential-execution/executable-discovery.ts +40 -0
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +125 -40
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
- package/src/daemon/conversation-agent-loop.ts +244 -90
- package/src/daemon/conversation-error.ts +64 -6
- package/src/daemon/conversation-lifecycle.ts +27 -22
- package/src/daemon/conversation-messaging.ts +84 -43
- package/src/daemon/conversation-process.ts +74 -37
- package/src/daemon/conversation-runtime-assembly.ts +38 -17
- package/src/daemon/conversation-skill-tools.ts +14 -30
- package/src/daemon/conversation-surfaces.ts +69 -34
- package/src/daemon/conversation-tool-setup.ts +77 -32
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +40 -75
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/daemon-skill-host.ts +9 -2
- package/src/daemon/disk-pressure-guard.ts +39 -29
- package/src/daemon/first-greeting.ts +31 -13
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +11 -3
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +4 -4
- package/src/daemon/host-file-proxy.ts +4 -4
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +10 -10
- package/src/daemon/lifecycle.ts +29 -26
- package/src/daemon/mcp-reload-service.ts +1 -1
- package/src/daemon/meet-manifest-loader.ts +11 -24
- package/src/daemon/message-types/conversations.ts +22 -27
- package/src/daemon/message-types/document-comments.ts +8 -44
- package/src/daemon/message-types/home.ts +2 -14
- package/src/daemon/message-types/integrations.ts +2 -7
- package/src/daemon/message-types/messages.ts +25 -48
- package/src/daemon/message-types/subagents.ts +6 -0
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/process-message.ts +9 -9
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +16 -0
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +62 -0
- package/src/daemon/tool-setup-types.ts +7 -0
- package/src/daemon/wake-target-adapter.ts +10 -0
- package/src/documents/document-store.ts +38 -0
- package/src/export/__tests__/transcript-formatter.test.ts +1 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
- package/src/heartbeat/heartbeat-service.ts +63 -0
- package/src/home/__tests__/feed-writer.test.ts +161 -0
- package/src/home/__tests__/post-connect-feed.test.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +55 -59
- package/src/home/feed-writer.ts +146 -7
- package/src/home/home-greeting.ts +0 -9
- package/src/home/suggested-prompts.ts +27 -154
- package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
- package/src/ipc/gateway-client.test.ts +4 -1
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
- package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
- package/src/ipc/skill-routes/memory.ts +4 -3
- package/src/ipc/skill-routes/registries.ts +35 -40
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-attention-store.ts +17 -3
- package/src/memory/conversation-crud.ts +423 -182
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-connection.ts +29 -19
- package/src/memory/db-init.ts +14 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/db-singleton.ts +77 -0
- package/src/memory/delivery-channels.ts +82 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/graph/retriever.test.ts +3 -3
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/job-handlers/embedding.test.ts +3 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +66 -22
- package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
- package/src/memory/llm-request-log-source-local.ts +31 -0
- package/src/memory/llm-request-log-source.ts +40 -2
- package/src/memory/llm-request-log-store.ts +228 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-enqueue.ts +8 -1
- package/src/memory/memory-retrospective-job.ts +5 -0
- package/src/memory/memory-v2-activation-log-store.ts +110 -7
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
- package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
- package/src/memory/migrations/index.ts +19 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/schema/conversations.ts +10 -2
- package/src/memory/schema/inference.ts +0 -1
- package/src/memory/schema/infrastructure.ts +21 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
- package/src/memory/v2/__tests__/injection.test.ts +127 -98
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +171 -3
- package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +128 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +240 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +112 -0
- package/src/memory/v2/harness/trace.ts +64 -0
- package/src/memory/v2/injection.ts +21 -15
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +171 -18
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
- package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +706 -0
- package/src/memory/v3/__tests__/filter.test.ts +560 -0
- package/src/memory/v3/__tests__/gate.test.ts +637 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
- package/src/memory/v3/__tests__/loop.test.ts +775 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +489 -0
- package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +508 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
- package/src/memory/v3/__tests__/validate.test.ts +277 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/coretrieval-seed.ts +240 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +286 -0
- package/src/memory/v3/filter.ts +286 -0
- package/src/memory/v3/gate.ts +349 -0
- package/src/memory/v3/index-composition.ts +126 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +430 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +431 -0
- package/src/memory/v3/shadow-diff.ts +287 -0
- package/src/memory/v3/shadow-middleware.ts +347 -0
- package/src/memory/v3/traversal.ts +211 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +356 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +323 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/adapters/slack.ts +45 -11
- package/src/notifications/broadcaster.ts +114 -63
- package/src/notifications/conversation-pairing.ts +23 -3
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/decisions-store.ts +32 -1
- package/src/notifications/deliveries-store.ts +45 -0
- package/src/notifications/edit-notification.ts +201 -0
- package/src/notifications/emit-signal.ts +40 -50
- package/src/notifications/signal.ts +10 -0
- package/src/notifications/types.ts +37 -0
- package/src/oauth/byo-connection.test.ts +67 -3
- package/src/oauth/byo-connection.ts +32 -5
- package/src/oauth/connect-orchestrator.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +76 -0
- package/src/oauth/connection-resolver.ts +49 -10
- package/src/oauth/manual-token-connection.ts +51 -3
- package/src/oauth/seed-providers.ts +3 -0
- package/src/permissions/approval-policy.test.ts +19 -5
- package/src/permissions/approval-policy.ts +14 -3
- package/src/permissions/checker.ts +21 -8
- package/src/permissions/prompter.ts +3 -3
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +2 -2
- package/src/platform/client.test.ts +24 -1
- package/src/platform/client.ts +8 -0
- package/src/platform/feature-gate.ts +15 -0
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +20 -19
- package/src/plugins/defaults/persistence.ts +25 -6
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +68 -29
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/proactive-artifact/job.test.ts +1 -0
- package/src/prompts/__tests__/system-prompt.test.ts +4 -4
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +39 -7
- package/src/prompts/system-prompt.ts +84 -221
- package/src/prompts/template-detection.ts +10 -4
- package/src/prompts/templates/BOOTSTRAP.md +9 -13
- package/src/prompts/templates/IDENTITY.md +0 -2
- package/src/prompts/templates/system-sections.ts +230 -8
- package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
- package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +32 -66
- package/src/providers/call-site-routing.ts +42 -6
- package/src/providers/connection-model-compat.ts +61 -0
- package/src/providers/connection-resolution.ts +47 -14
- package/src/providers/fireworks/client.ts +1 -0
- package/src/providers/gemini/client.ts +70 -6
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
- package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
- package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/inference/auth.ts +0 -8
- package/src/providers/inference/connections.ts +3 -66
- package/src/providers/inference/resolve-auth.ts +2 -3
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +78 -1
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
- package/src/providers/openai/chat-completions-provider.ts +116 -15
- package/src/providers/openai/codex-models.ts +20 -0
- package/src/providers/openai/responses-provider.ts +87 -30
- package/src/providers/openrouter/client.ts +13 -8
- package/src/providers/provider-send-message.ts +20 -5
- package/src/providers/registry.ts +48 -8
- package/src/providers/retry.ts +50 -7
- package/src/providers/search-provider-catalog.ts +17 -9
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/types.ts +9 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +1 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
- package/src/runtime/access-request-helper.ts +1 -0
- package/src/runtime/agent-wake.ts +1 -0
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +46 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/channel-readiness-service.ts +68 -0
- package/src/runtime/channel-reply-delivery.ts +23 -0
- package/src/runtime/channel-retry-sweep.ts +47 -14
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/http-types.ts +0 -2
- package/src/runtime/migrations/vbundle-builder.ts +12 -4
- package/src/runtime/pending-interactions.ts +0 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
- package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
- package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
- package/src/runtime/routes/acp-routes-list.test.ts +3 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/app-management-routes.ts +111 -4
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +356 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +4 -10
- package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
- package/src/runtime/routes/conversation-list-routes.ts +159 -4
- package/src/runtime/routes/conversation-management-routes.ts +108 -26
- package/src/runtime/routes/conversation-query-routes.ts +200 -44
- package/src/runtime/routes/conversation-routes.ts +409 -521
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/conversations-import-routes.ts +19 -6
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/documents-routes.ts +10 -1
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +35 -8
- package/src/runtime/routes/home-feed-routes.ts +129 -0
- package/src/runtime/routes/host-browser-routes.ts +10 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/identity-intro-cache.ts +61 -16
- package/src/runtime/routes/identity-routes.ts +30 -9
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
- package/src/runtime/routes/index.ts +10 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
- package/src/runtime/routes/integrations/vercel.ts +15 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/llm-context-normalization.ts +7 -2
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +215 -5
- package/src/runtime/routes/memory-v3-routes.ts +474 -0
- package/src/runtime/routes/migration-routes.ts +32 -28
- package/src/runtime/routes/notification-routes.ts +63 -1
- package/src/runtime/routes/oauth-commands-routes.ts +6 -1
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +5 -4
- package/src/runtime/routes/surface-action-routes.ts +1 -38
- package/src/runtime/routes/surface-content-routes.ts +12 -5
- package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
- package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
- package/src/runtime/slack-dm-text-delivery.ts +177 -0
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/tool-grant-request-helper.ts +1 -0
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/schedule/schedule-store.ts +8 -1
- package/src/schedule/scheduler.ts +111 -15
- package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
- package/src/security/encrypted-store.ts +7 -16
- package/src/security/store-path-override.ts +61 -0
- package/src/signals/user-message.ts +5 -8
- package/src/skills/validate-input.ts +177 -0
- package/src/subagent/manager.ts +13 -13
- package/src/subagent/types.ts +6 -0
- package/src/tasks/tool-sanitizer.ts +2 -2
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +36 -28
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
- package/src/tools/browser/browser-execution.ts +16 -3
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
- package/src/tools/browser/cdp-client/factory.ts +100 -17
- package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
- package/src/tools/browser/cdp-client/types.ts +65 -0
- package/src/tools/browser/pinned-tabs.ts +96 -40
- package/src/tools/computer-use/definitions.ts +282 -336
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-tool.ts +189 -7
- package/src/tools/execution-target.ts +18 -23
- package/src/tools/executor.ts +24 -56
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.test.ts +1 -0
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.test.ts +1 -0
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.test.ts +31 -6
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.test.ts +1 -0
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -10
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
- package/src/tools/network/__tests__/web-search.test.ts +211 -3
- package/src/tools/network/managed-search-proxy.ts +183 -0
- package/src/tools/network/web-fetch.ts +3 -9
- package/src/tools/network/web-search.ts +224 -76
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/registry.ts +150 -123
- package/src/tools/schedule/create.ts +1 -1
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +18 -44
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/subagent/spawn.ts +3 -0
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +10 -4
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/tool-name-aliases.ts +72 -14
- package/src/tools/types.ts +32 -101
- package/src/tools/ui-surface/definitions.ts +104 -108
- package/src/types/onboarding-context.ts +6 -0
- package/src/usage/attribution.ts +32 -1
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/browser.ts +7 -2
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -2
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/daemon/query-complexity-router.ts +0 -75
- package/src/prompts/cache-boundary.ts +0 -8
|
@@ -14,8 +14,9 @@ import { v4 as uuid } from "uuid";
|
|
|
14
14
|
import { getDeliverableChannels } from "../channels/config.js";
|
|
15
15
|
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
16
16
|
import type { ConversationCreateType } from "../memory/conversation-crud.js";
|
|
17
|
+
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
17
18
|
import { getLogger } from "../util/logger.js";
|
|
18
|
-
import {
|
|
19
|
+
import { VellumAdapter } from "./adapters/macos.js";
|
|
19
20
|
import { PlatformPushAdapter } from "./adapters/platform.js";
|
|
20
21
|
import { SlackAdapter } from "./adapters/slack.js";
|
|
21
22
|
import { TelegramAdapter } from "./adapters/telegram.js";
|
|
@@ -49,56 +50,38 @@ const log = getLogger("emit-signal");
|
|
|
49
50
|
// ── Broadcaster singleton ──────────────────────────────────────────────
|
|
50
51
|
|
|
51
52
|
let broadcasterInstance: NotificationBroadcaster | null = null;
|
|
52
|
-
let registeredBroadcastFn: BroadcastFn | null = null;
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
* Register the broadcast function so the vellum adapter can deliver
|
|
56
|
-
* notifications to connected clients. Must be called once during
|
|
57
|
-
* daemon startup (before any signals are emitted).
|
|
58
|
-
*/
|
|
59
|
-
export function registerBroadcastFn(fn: BroadcastFn): void {
|
|
60
|
-
registeredBroadcastFn = fn;
|
|
61
|
-
// Reset the broadcaster so it picks up the new broadcast function
|
|
62
|
-
broadcasterInstance = null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function getBroadcaster(): NotificationBroadcaster {
|
|
54
|
+
export function getBroadcaster(): NotificationBroadcaster {
|
|
66
55
|
if (!broadcasterInstance) {
|
|
67
|
-
|
|
56
|
+
broadcasterInstance = new NotificationBroadcaster([
|
|
57
|
+
new VellumAdapter(broadcastMessage),
|
|
68
58
|
new TelegramAdapter(),
|
|
69
59
|
new SlackAdapter(),
|
|
70
60
|
new PlatformPushAdapter(),
|
|
71
|
-
];
|
|
72
|
-
if (registeredBroadcastFn) {
|
|
73
|
-
adapters.unshift(new VellumAdapter(registeredBroadcastFn));
|
|
74
|
-
}
|
|
75
|
-
broadcasterInstance = new NotificationBroadcaster(adapters);
|
|
61
|
+
]);
|
|
76
62
|
|
|
77
63
|
// Wire the conversation-created callback so the macOS client is notified
|
|
78
64
|
// immediately when a vellum notification conversation is paired — before
|
|
79
65
|
// slower channel deliveries (e.g. Telegram) delay the push.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
source: info.source,
|
|
91
|
-
silent: info.silent,
|
|
92
|
-
});
|
|
93
|
-
log.info(
|
|
94
|
-
{
|
|
95
|
-
conversationId: info.conversationId,
|
|
96
|
-
guardianScoped: info.targetGuardianPrincipalId != null,
|
|
97
|
-
},
|
|
98
|
-
"Emitted notification_conversation_created push event",
|
|
99
|
-
);
|
|
66
|
+
broadcasterInstance.setOnConversationCreated((info) => {
|
|
67
|
+
broadcastMessage({
|
|
68
|
+
type: "notification_conversation_created",
|
|
69
|
+
conversationId: info.conversationId,
|
|
70
|
+
title: info.title,
|
|
71
|
+
sourceEventName: info.sourceEventName,
|
|
72
|
+
targetGuardianPrincipalId: info.targetGuardianPrincipalId,
|
|
73
|
+
groupId: info.groupId,
|
|
74
|
+
source: info.source,
|
|
75
|
+
silent: info.silent,
|
|
100
76
|
});
|
|
101
|
-
|
|
77
|
+
log.info(
|
|
78
|
+
{
|
|
79
|
+
conversationId: info.conversationId,
|
|
80
|
+
guardianScoped: info.targetGuardianPrincipalId != null,
|
|
81
|
+
},
|
|
82
|
+
"Emitted notification_conversation_created push event",
|
|
83
|
+
);
|
|
84
|
+
});
|
|
102
85
|
}
|
|
103
86
|
return broadcasterInstance;
|
|
104
87
|
}
|
|
@@ -115,18 +98,15 @@ function getConnectedChannels(): NotificationChannel[] {
|
|
|
115
98
|
switch (channel) {
|
|
116
99
|
case "vellum":
|
|
117
100
|
// Vellum is always considered connected (the local transport is
|
|
118
|
-
// always available when the
|
|
101
|
+
// always available when the assistant is running).
|
|
119
102
|
channels.push(channel);
|
|
120
103
|
break;
|
|
121
104
|
case "platform":
|
|
122
|
-
// Platform push is connected
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
if (registeredBroadcastFn) {
|
|
128
|
-
channels.push(channel);
|
|
129
|
-
}
|
|
105
|
+
// Platform push is treated as connected at the decision-engine
|
|
106
|
+
// layer; the actual delivery path lazily resolves
|
|
107
|
+
// `VellumPlatformClient.create()` in `PlatformPushAdapter.send()`
|
|
108
|
+
// and reports a delivery failure when credentials are absent.
|
|
109
|
+
channels.push(channel);
|
|
130
110
|
break;
|
|
131
111
|
case "telegram": {
|
|
132
112
|
// A binding-based channel is connected when the guardian has an
|
|
@@ -208,6 +188,15 @@ export interface EmitSignalParams<TEventName extends string = string> {
|
|
|
208
188
|
source?: string;
|
|
209
189
|
conversationType?: ConversationCreateType;
|
|
210
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* When true, the vellum-channel delivery materializes a fresh conversation
|
|
193
|
+
* to host the notification (and any follow-up interaction). Set this only
|
|
194
|
+
* for flows where the conversation IS the interaction surface — e.g.
|
|
195
|
+
* guardian.question, tool grant requests, ingress access requests. Passive
|
|
196
|
+
* notifications leave this unset; they surface via the home feed and link
|
|
197
|
+
* back to their originating conversation via `sourceContextId`.
|
|
198
|
+
*/
|
|
199
|
+
requiresConversation?: boolean;
|
|
211
200
|
}
|
|
212
201
|
|
|
213
202
|
export interface EmitSignalResult {
|
|
@@ -243,6 +232,7 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
243
232
|
routingHints: params.routingHints,
|
|
244
233
|
conversationAffinityHint: params.conversationAffinityHint,
|
|
245
234
|
conversationMetadata: params.conversationMetadata,
|
|
235
|
+
requiresConversation: params.requiresConversation,
|
|
246
236
|
};
|
|
247
237
|
|
|
248
238
|
try {
|
|
@@ -213,4 +213,14 @@ export interface NotificationSignal<TEventName extends string = string> {
|
|
|
213
213
|
source?: string;
|
|
214
214
|
conversationType?: ConversationCreateType;
|
|
215
215
|
};
|
|
216
|
+
/**
|
|
217
|
+
* When true, the vellum-channel delivery materializes a fresh conversation
|
|
218
|
+
* to host the notification (and any follow-up interaction). Set this only
|
|
219
|
+
* for flows where the conversation IS the interaction surface — e.g.
|
|
220
|
+
* guardian.question, tool grant requests, ingress access requests. Passive
|
|
221
|
+
* notifications (scheduler fired, watcher alert, activity complete, etc.)
|
|
222
|
+
* should leave this unset; they surface via the home feed and link back
|
|
223
|
+
* to their originating conversation via `sourceContextId`.
|
|
224
|
+
*/
|
|
225
|
+
requiresConversation?: boolean;
|
|
216
226
|
}
|
|
@@ -45,6 +45,12 @@ export interface NotificationDeliveryResult {
|
|
|
45
45
|
export interface DeliveryResult {
|
|
46
46
|
success: boolean;
|
|
47
47
|
error?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Channel-native message identifier captured at send time (e.g. Slack `ts`).
|
|
50
|
+
* Persisted onto `notification_deliveries.messageId` so later edits can
|
|
51
|
+
* target the same message via `ChannelAdapter.update()`.
|
|
52
|
+
*/
|
|
53
|
+
messageId?: string;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
/** Resolved destination for a specific channel. */
|
|
@@ -91,6 +97,16 @@ export interface ChannelDeliveryPayload {
|
|
|
91
97
|
urgency: AttentionHints["urgency"];
|
|
92
98
|
}
|
|
93
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Patch supplied when an already-delivered notification is edited.
|
|
102
|
+
* Adapters only need to act on `title` and `body` — feed-only fields
|
|
103
|
+
* like `urgency` and `status` are handled by the home-feed patch.
|
|
104
|
+
*/
|
|
105
|
+
export interface ChannelUpdatePayload {
|
|
106
|
+
title?: string;
|
|
107
|
+
body?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
94
110
|
/** Interface that each channel adapter must implement. */
|
|
95
111
|
export interface ChannelAdapter {
|
|
96
112
|
channel: NotificationChannel;
|
|
@@ -98,6 +114,27 @@ export interface ChannelAdapter {
|
|
|
98
114
|
payload: ChannelDeliveryPayload,
|
|
99
115
|
destination: ChannelDestination,
|
|
100
116
|
): Promise<DeliveryResult>;
|
|
117
|
+
/**
|
|
118
|
+
* Optional: edit a previously-sent message in place. Channels that
|
|
119
|
+
* cannot edit (push, email, SMS) omit this and the router treats
|
|
120
|
+
* them as `"unsupported"`. Adapters that implement it use
|
|
121
|
+
* `delivery.messageId` (captured at send time) as the channel-native
|
|
122
|
+
* handle for the in-place update.
|
|
123
|
+
*/
|
|
124
|
+
update?(
|
|
125
|
+
delivery: ChannelUpdateContext,
|
|
126
|
+
patch: ChannelUpdatePayload,
|
|
127
|
+
): Promise<DeliveryResult>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Per-delivery state an adapter needs to update a previously-sent message. */
|
|
131
|
+
export interface ChannelUpdateContext {
|
|
132
|
+
/** notification_deliveries.id */
|
|
133
|
+
deliveryId: string;
|
|
134
|
+
/** Channel-native destination (e.g. Slack chat id). */
|
|
135
|
+
destination: string;
|
|
136
|
+
/** Channel-native message identifier captured at send time. */
|
|
137
|
+
messageId: string | null;
|
|
101
138
|
}
|
|
102
139
|
|
|
103
140
|
// -- Decision engine output ---------------------------------------------------
|
|
@@ -28,7 +28,7 @@ mock.module("../util/logger.js", () => ({
|
|
|
28
28
|
// Use encrypted backend with a temp store path
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
|
|
31
|
-
import {
|
|
31
|
+
import { setStorePathForTesting } from "../__tests__/encrypted-store-test-helpers.js";
|
|
32
32
|
import { _resetBackend } from "../security/secure-keys.js";
|
|
33
33
|
|
|
34
34
|
const TEST_DIR = join(
|
|
@@ -130,6 +130,7 @@ mock.module("./oauth-store.js", () => ({
|
|
|
130
130
|
// Imports (after mocks)
|
|
131
131
|
// ---------------------------------------------------------------------------
|
|
132
132
|
|
|
133
|
+
import { credentialKey } from "../security/credential-key.js";
|
|
133
134
|
import { setSecureKeyAsync } from "../security/secure-keys.js";
|
|
134
135
|
import {
|
|
135
136
|
_resetInflightRefreshes,
|
|
@@ -163,7 +164,7 @@ afterAll(() => {
|
|
|
163
164
|
});
|
|
164
165
|
|
|
165
166
|
beforeEach(() => {
|
|
166
|
-
|
|
167
|
+
setStorePathForTesting(STORE_PATH);
|
|
167
168
|
_setMetadataPath(join(TEST_DIR, "metadata.json"));
|
|
168
169
|
_resetBackend();
|
|
169
170
|
_resetRefreshBreakers();
|
|
@@ -251,11 +252,22 @@ function createConnection(service = "google"): BYOOAuthConnection {
|
|
|
251
252
|
return new BYOOAuthConnection({
|
|
252
253
|
id: `conn-${service}`,
|
|
253
254
|
provider: service,
|
|
254
|
-
baseUrl:
|
|
255
|
+
baseUrl:
|
|
256
|
+
service === "telegram"
|
|
257
|
+
? "https://api.telegram.org"
|
|
258
|
+
: "https://gmail.googleapis.com/gmail/v1/users/me",
|
|
255
259
|
accountInfo: null,
|
|
256
260
|
});
|
|
257
261
|
}
|
|
258
262
|
|
|
263
|
+
async function setupTelegramCredential() {
|
|
264
|
+
await setupCredential("telegram");
|
|
265
|
+
await setSecureKeyAsync(
|
|
266
|
+
credentialKey("telegram", "bot_token"),
|
|
267
|
+
"telegram-test-token",
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
259
271
|
// ---------------------------------------------------------------------------
|
|
260
272
|
// Tests
|
|
261
273
|
// ---------------------------------------------------------------------------
|
|
@@ -437,6 +449,58 @@ describe("BYOOAuthConnection", () => {
|
|
|
437
449
|
expect(headers.get("X-Custom-Header")).toBe("custom-value");
|
|
438
450
|
expect(headers.get("Authorization")).toBe("Bearer test-access-token");
|
|
439
451
|
});
|
|
452
|
+
|
|
453
|
+
test("uses Telegram Bot API token URL format without Bearer auth", async () => {
|
|
454
|
+
await setupTelegramCredential();
|
|
455
|
+
const conn = createConnection("telegram");
|
|
456
|
+
|
|
457
|
+
const result = await conn.request({
|
|
458
|
+
method: "GET",
|
|
459
|
+
path: "/getMe",
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
expect(result.status).toBe(200);
|
|
463
|
+
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
464
|
+
|
|
465
|
+
const [url, init] = mockFetch.mock.calls[0];
|
|
466
|
+
expect(url).toBe("https://api.telegram.org/bottelegram-test-token/getMe");
|
|
467
|
+
const headers = (init as RequestInit).headers as Headers;
|
|
468
|
+
expect(headers.has("Authorization")).toBe(false);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
test("does not double-prefix Telegram paths that already include bot token", async () => {
|
|
472
|
+
await setupTelegramCredential();
|
|
473
|
+
const conn = createConnection("telegram");
|
|
474
|
+
|
|
475
|
+
await conn.request({
|
|
476
|
+
method: "GET",
|
|
477
|
+
path: "/bottelegram-test-token/getMe",
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
const [url, init] = mockFetch.mock.calls[0];
|
|
481
|
+
expect(url).toBe("https://api.telegram.org/bottelegram-test-token/getMe");
|
|
482
|
+
const headers = (init as RequestInit).headers as Headers;
|
|
483
|
+
expect(headers.has("Authorization")).toBe(false);
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
test("returns Telegram 401 responses without OAuth refresh", async () => {
|
|
487
|
+
await setupTelegramCredential();
|
|
488
|
+
const conn = createConnection("telegram");
|
|
489
|
+
const refreshCallsBefore = mockRefreshOAuth2Token.mock.calls.length;
|
|
490
|
+
|
|
491
|
+
globalThis.fetch = mock(() =>
|
|
492
|
+
Promise.resolve(new Response("Unauthorized", { status: 401 })),
|
|
493
|
+
) as unknown as typeof fetch;
|
|
494
|
+
|
|
495
|
+
const result = await conn.request({
|
|
496
|
+
method: "GET",
|
|
497
|
+
path: "/getMe",
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
expect(result.status).toBe(401);
|
|
501
|
+
expect(result.body).toBe("Unauthorized");
|
|
502
|
+
expect(mockRefreshOAuth2Token.mock.calls.length).toBe(refreshCallsBefore);
|
|
503
|
+
});
|
|
440
504
|
});
|
|
441
505
|
|
|
442
506
|
describe("proactive token refresh", () => {
|
|
@@ -46,7 +46,11 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
46
46
|
this.provider,
|
|
47
47
|
async (token) => {
|
|
48
48
|
const effectiveBaseUrl = req.baseUrl ?? this.baseUrl;
|
|
49
|
-
|
|
49
|
+
const isTelegram = this.provider === "telegram";
|
|
50
|
+
const requestPath = isTelegram
|
|
51
|
+
? buildTelegramBotApiPath(req.path, token)
|
|
52
|
+
: req.path;
|
|
53
|
+
let fullUrl = `${effectiveBaseUrl}${requestPath}`;
|
|
50
54
|
|
|
51
55
|
if (req.query && Object.keys(req.query).length > 0) {
|
|
52
56
|
const params = new URLSearchParams();
|
|
@@ -60,8 +64,12 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
60
64
|
fullUrl += `?${params.toString()}`;
|
|
61
65
|
}
|
|
62
66
|
|
|
67
|
+
const logUrl = isTelegram
|
|
68
|
+
? redactTelegramBotTokenFromUrl(fullUrl, token)
|
|
69
|
+
: fullUrl;
|
|
70
|
+
|
|
63
71
|
log.debug(
|
|
64
|
-
{ method: req.method, url:
|
|
72
|
+
{ method: req.method, url: logUrl, provider: this.provider },
|
|
65
73
|
"Making authenticated request",
|
|
66
74
|
);
|
|
67
75
|
|
|
@@ -76,18 +84,23 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
76
84
|
headers.set(key, value);
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
|
-
|
|
87
|
+
if (!isTelegram) {
|
|
88
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
89
|
+
}
|
|
80
90
|
|
|
81
91
|
const resp = await fetch(fullUrl, {
|
|
82
92
|
method: req.method,
|
|
83
93
|
headers,
|
|
84
94
|
body: req.body ? JSON.stringify(req.body) : undefined,
|
|
85
95
|
signal: req.signal
|
|
86
|
-
? AbortSignal.any([
|
|
96
|
+
? AbortSignal.any([
|
|
97
|
+
req.signal,
|
|
98
|
+
AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
99
|
+
])
|
|
87
100
|
: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
88
101
|
});
|
|
89
102
|
|
|
90
|
-
if (resp.status === 401) {
|
|
103
|
+
if (resp.status === 401 && !isTelegram) {
|
|
91
104
|
// Throw with a status property so withValidToken detects the 401
|
|
92
105
|
// and triggers its refresh-and-retry logic.
|
|
93
106
|
const err = new Error(`HTTP 401 from ${this.provider}`);
|
|
@@ -108,6 +121,20 @@ export class BYOOAuthConnection implements OAuthConnection {
|
|
|
108
121
|
}
|
|
109
122
|
}
|
|
110
123
|
|
|
124
|
+
function buildTelegramBotApiPath(path: string, token: string): string {
|
|
125
|
+
if (path.startsWith("/bot")) return path;
|
|
126
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
127
|
+
return `/bot${token}${normalizedPath}`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function redactTelegramBotTokenFromUrl(url: string, token: string): string {
|
|
131
|
+
const redactedStoredToken = url.split(token).join("[REDACTED]");
|
|
132
|
+
return redactedStoredToken.replace(
|
|
133
|
+
/\/bot[^/?#]+(?=\/|[?#]|$)/g,
|
|
134
|
+
"/bot[REDACTED]",
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
111
138
|
async function buildResponse(resp: Response): Promise<OAuthConnectionResponse> {
|
|
112
139
|
const headers: Record<string, string> = {};
|
|
113
140
|
resp.headers.forEach((value, key) => {
|
|
@@ -64,6 +64,12 @@ export interface OAuthConnectOptions {
|
|
|
64
64
|
openUrl?: (url: string) => void;
|
|
65
65
|
/** Send a message to the client (e.g. open_url). */
|
|
66
66
|
sendToClient?: (msg: { type: string; [key: string]: unknown }) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Conversation this connect flow belongs to. When set and `sendToClient`
|
|
69
|
+
* is used, the emitted `open_url` event carries it on the inner message
|
|
70
|
+
* so downstream consumers can route per-conversation.
|
|
71
|
+
*/
|
|
72
|
+
conversationId?: string;
|
|
67
73
|
|
|
68
74
|
/**
|
|
69
75
|
* Callback transport to use for the OAuth redirect.
|
|
@@ -331,6 +337,9 @@ export async function orchestrateOAuthConnect(
|
|
|
331
337
|
type: "open_url",
|
|
332
338
|
url,
|
|
333
339
|
title: `Connect ${options.service}`,
|
|
340
|
+
...(options.conversationId
|
|
341
|
+
? { conversationId: options.conversationId }
|
|
342
|
+
: {}),
|
|
334
343
|
});
|
|
335
344
|
} else {
|
|
336
345
|
log.warn(
|
|
@@ -9,6 +9,7 @@ let mockConnection: Record<string, unknown> | undefined;
|
|
|
9
9
|
let mockAccessToken: string | undefined;
|
|
10
10
|
let mockConfig: Record<string, unknown> = {};
|
|
11
11
|
let mockPlatformClient: Record<string, unknown> | null = null;
|
|
12
|
+
let syncManualTokenCalls: string[] = [];
|
|
12
13
|
|
|
13
14
|
// ---------------------------------------------------------------------------
|
|
14
15
|
// Module mocks (must precede imports of the module under test)
|
|
@@ -47,6 +48,15 @@ mock.module("./credential-token-resolver.js", () => ({
|
|
|
47
48
|
}),
|
|
48
49
|
}));
|
|
49
50
|
|
|
51
|
+
mock.module("./manual-token-connection.js", () => ({
|
|
52
|
+
syncManualTokenConnection: async (provider: string) => {
|
|
53
|
+
syncManualTokenCalls.push(provider);
|
|
54
|
+
if (provider === "telegram" && mockConnection?.provider === "telegram") {
|
|
55
|
+
mockConnection.accountInfo = "@example_bot";
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
}));
|
|
59
|
+
|
|
50
60
|
mock.module("../config/loader.js", () => ({
|
|
51
61
|
getConfig: () => mockConfig,
|
|
52
62
|
}));
|
|
@@ -92,6 +102,7 @@ function setupDefaults(): void {
|
|
|
92
102
|
mockProvider = {
|
|
93
103
|
provider: "google",
|
|
94
104
|
baseUrl: "https://gmail.googleapis.com/gmail/v1/users/me",
|
|
105
|
+
authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
95
106
|
managedServiceConfigKey: null,
|
|
96
107
|
};
|
|
97
108
|
mockConnection = {
|
|
@@ -121,6 +132,7 @@ function setupDefaults(): void {
|
|
|
121
132
|
},
|
|
122
133
|
};
|
|
123
134
|
mockPlatformClient = makeMockClient();
|
|
135
|
+
syncManualTokenCalls = [];
|
|
124
136
|
}
|
|
125
137
|
|
|
126
138
|
// ---------------------------------------------------------------------------
|
|
@@ -159,6 +171,42 @@ describe("resolveOAuthConnection", () => {
|
|
|
159
171
|
expect(result.accountInfo).toBe("user@example.com");
|
|
160
172
|
});
|
|
161
173
|
|
|
174
|
+
test("managed path falls back to displayed account label when account_identifier does not match", async () => {
|
|
175
|
+
mockProvider!.managedServiceConfigKey = "google-oauth";
|
|
176
|
+
const fetchPaths: string[] = [];
|
|
177
|
+
mockPlatformClient = {
|
|
178
|
+
...makeMockClient(),
|
|
179
|
+
fetch: mock(async (path: string) => {
|
|
180
|
+
fetchPaths.push(path);
|
|
181
|
+
if (path.includes("account_identifier=alice%40example.com")) {
|
|
182
|
+
return new Response(JSON.stringify({ results: [] }), { status: 200 });
|
|
183
|
+
}
|
|
184
|
+
return new Response(
|
|
185
|
+
JSON.stringify({
|
|
186
|
+
results: [
|
|
187
|
+
{
|
|
188
|
+
id: "platform-conn-1",
|
|
189
|
+
account_label: "alice@example.com",
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
}),
|
|
193
|
+
{ status: 200 },
|
|
194
|
+
);
|
|
195
|
+
}),
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const result = await resolveOAuthConnection("google", {
|
|
199
|
+
account: "alice@example.com",
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
expect(result).toBeInstanceOf(PlatformOAuthConnection);
|
|
203
|
+
expect(result.accountInfo).toBe("alice@example.com");
|
|
204
|
+
expect(fetchPaths).toEqual([
|
|
205
|
+
"/v1/assistants/asst-123/oauth/connections/?provider=google&status=ACTIVE&account_identifier=alice%40example.com",
|
|
206
|
+
"/v1/assistants/asst-123/oauth/connections/?provider=google&status=ACTIVE",
|
|
207
|
+
]);
|
|
208
|
+
});
|
|
209
|
+
|
|
162
210
|
test("returns PlatformOAuthConnection when GitHub is in managed mode", async () => {
|
|
163
211
|
mockProvider!.provider = "github";
|
|
164
212
|
mockProvider!.managedServiceConfigKey = "github-oauth";
|
|
@@ -216,6 +264,34 @@ describe("resolveOAuthConnection", () => {
|
|
|
216
264
|
}),
|
|
217
265
|
).rejects.toThrow(/No active OAuth connection found/);
|
|
218
266
|
});
|
|
267
|
+
|
|
268
|
+
test("BYO path reconciles manual-token providers before exact account lookup", async () => {
|
|
269
|
+
mockProvider = {
|
|
270
|
+
provider: "telegram",
|
|
271
|
+
baseUrl: "https://api.telegram.org",
|
|
272
|
+
authorizeUrl: "urn:manual-token",
|
|
273
|
+
managedServiceConfigKey: null,
|
|
274
|
+
};
|
|
275
|
+
mockConnection = {
|
|
276
|
+
id: "conn-telegram",
|
|
277
|
+
provider: "telegram",
|
|
278
|
+
oauthAppId: "app-telegram",
|
|
279
|
+
accountInfo: null,
|
|
280
|
+
grantedScopes: JSON.stringify([]),
|
|
281
|
+
status: "active",
|
|
282
|
+
clientId: "manual-config",
|
|
283
|
+
};
|
|
284
|
+
mockAccessToken = "telegram-test-token";
|
|
285
|
+
|
|
286
|
+
const result = await resolveOAuthConnection("telegram", {
|
|
287
|
+
account: "@example_bot",
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
expect(syncManualTokenCalls).toEqual(["telegram"]);
|
|
291
|
+
expect(mockConnection.accountInfo).toBe("@example_bot");
|
|
292
|
+
expect(result).toBeInstanceOf(BYOOAuthConnection);
|
|
293
|
+
expect(result.id).toBe("conn-telegram");
|
|
294
|
+
});
|
|
219
295
|
});
|
|
220
296
|
|
|
221
297
|
describe("resolveEffectiveBaseUrl", () => {
|
|
@@ -9,6 +9,7 @@ import { getLogger } from "../util/logger.js";
|
|
|
9
9
|
import { BYOOAuthConnection } from "./byo-connection.js";
|
|
10
10
|
import type { OAuthConnection } from "./connection.js";
|
|
11
11
|
import { getConnectionAccessTokenResult } from "./credential-token-resolver.js";
|
|
12
|
+
import { syncManualTokenConnection } from "./manual-token-connection.js";
|
|
12
13
|
import { getActiveConnection, getProvider } from "./oauth-store.js";
|
|
13
14
|
import { PlatformOAuthConnection } from "./platform-connection.js";
|
|
14
15
|
|
|
@@ -82,6 +83,10 @@ export async function resolveOAuthConnection(
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
// BYO path — requires a local connection row, access token, and base URL.
|
|
86
|
+
if (providerRow?.authorizeUrl === "urn:manual-token") {
|
|
87
|
+
await syncManualTokenConnection(provider);
|
|
88
|
+
}
|
|
89
|
+
|
|
85
90
|
const conn = getActiveConnection(provider, { clientId, account });
|
|
86
91
|
if (!conn) {
|
|
87
92
|
const filters = [
|
|
@@ -185,20 +190,26 @@ interface ResolvePlatformConnectionIdOptions {
|
|
|
185
190
|
account?: string;
|
|
186
191
|
}
|
|
187
192
|
|
|
193
|
+
interface PlatformConnectionEntry {
|
|
194
|
+
id: string;
|
|
195
|
+
account_label?: string | null;
|
|
196
|
+
}
|
|
197
|
+
|
|
188
198
|
/**
|
|
189
|
-
* Fetch
|
|
190
|
-
*
|
|
199
|
+
* Fetch active platform connections for a managed provider by calling the
|
|
200
|
+
* List Connections endpoint.
|
|
191
201
|
*/
|
|
192
|
-
async function
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
202
|
+
async function fetchPlatformConnections(options: {
|
|
203
|
+
client: VellumPlatformClient;
|
|
204
|
+
provider: string;
|
|
205
|
+
accountIdentifier?: string;
|
|
206
|
+
}): Promise<PlatformConnectionEntry[]> {
|
|
207
|
+
const { client, provider, accountIdentifier } = options;
|
|
197
208
|
const params = new URLSearchParams();
|
|
198
209
|
params.set("provider", provider);
|
|
199
210
|
params.set("status", "ACTIVE");
|
|
200
|
-
if (
|
|
201
|
-
params.set("account_identifier",
|
|
211
|
+
if (accountIdentifier) {
|
|
212
|
+
params.set("account_identifier", accountIdentifier);
|
|
202
213
|
}
|
|
203
214
|
|
|
204
215
|
const path = `/v1/assistants/${client.platformAssistantId}/oauth/connections/?${params.toString()}`;
|
|
@@ -219,7 +230,35 @@ async function resolvePlatformConnectionId(
|
|
|
219
230
|
Array.isArray(body)
|
|
220
231
|
? body
|
|
221
232
|
: ((body as Record<string, unknown>).results ?? [])
|
|
222
|
-
) as
|
|
233
|
+
) as PlatformConnectionEntry[];
|
|
234
|
+
return connections;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Fetch the platform-side connection ID for a managed provider by calling
|
|
239
|
+
* the List Connections endpoint.
|
|
240
|
+
*/
|
|
241
|
+
async function resolvePlatformConnectionId(
|
|
242
|
+
options: ResolvePlatformConnectionIdOptions,
|
|
243
|
+
): Promise<string> {
|
|
244
|
+
const { client, provider, account } = options;
|
|
245
|
+
|
|
246
|
+
let connections = await fetchPlatformConnections({
|
|
247
|
+
client,
|
|
248
|
+
provider,
|
|
249
|
+
accountIdentifier: account,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
if (account && connections.length === 0) {
|
|
253
|
+
const unfilteredConnections = await fetchPlatformConnections({
|
|
254
|
+
client,
|
|
255
|
+
provider,
|
|
256
|
+
});
|
|
257
|
+
connections = unfilteredConnections.filter(
|
|
258
|
+
(connection) =>
|
|
259
|
+
connection.account_label === account || connection.id === account,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
223
262
|
|
|
224
263
|
if (connections.length === 0) {
|
|
225
264
|
throw new Error(
|