@vellumai/assistant 0.8.2 → 0.8.4
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 +11 -12
- package/docker-entrypoint.sh +13 -2
- package/docker-init-apt-root.sh +79 -6
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +945 -36
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +271 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +272 -0
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/compaction-events.test.ts +1 -1
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/compactor-tail-resolution.test.ts +107 -1
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +112 -57
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
- package/src/__tests__/conversation-agent-loop.test.ts +77 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +161 -0
- package/src/__tests__/conversation-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +290 -85
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +6 -0
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/external-plugin-loader.test.ts +91 -19
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/host-app-control-proxy.test.ts +241 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +7 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +9 -2
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +3 -0
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +2 -0
- package/src/__tests__/llm-resolver.test.ts +340 -3
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/managed-profile-guard.test.ts +10 -0
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/openai-provider.test.ts +323 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +3 -3
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
- package/src/__tests__/platform-proxy-context.test.ts +6 -1
- package/src/__tests__/platform.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +3 -3
- package/src/__tests__/plugin-types.test.ts +2 -2
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/provider-catalog-visibility.test.ts +16 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +27 -25
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +57 -101
- package/src/__tests__/terminal-tools.test.ts +11 -1
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-executor.test.ts +90 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +88 -5
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +208 -22
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/browser/operations.ts +15 -0
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +14 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +469 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/memory-v2.ts +308 -0
- package/src/cli/commands/notifications.ts +89 -37
- package/src/cli/commands/plugins.ts +67 -0
- package/src/cli/commands/schedules.ts +297 -5
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/install-from-github.ts +8 -9
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/program.ts +14 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +117 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +124 -0
- package/src/config/feature-flag-registry.json +111 -23
- package/src/config/llm-resolver.ts +66 -1
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -3
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/channels.ts +9 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +14 -0
- package/src/config/schemas/llm.ts +4 -3
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +51 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/context/compactor.ts +80 -13
- package/src/context/token-estimator.ts +72 -31
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -22
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +231 -23
- package/src/daemon/conversation-agent-loop.ts +252 -56
- package/src/daemon/conversation-lifecycle.ts +142 -116
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +144 -75
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +7 -0
- package/src/daemon/conversation.ts +42 -12
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +449 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +80 -0
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-app-control-proxy.ts +69 -18
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/host-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +67 -65
- package/src/daemon/memory-v2-startup.ts +49 -13
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +8 -0
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/messages.ts +68 -1
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/pkb-reminder-builder.test.ts +10 -53
- package/src/daemon/pkb-reminder-builder.ts +4 -19
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +72 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/skill-memory-refresh.ts +5 -1
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +44 -1
- package/src/heartbeat/heartbeat-service.ts +35 -191
- package/src/home/__tests__/feed-types.test.ts +40 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +20 -3
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +94 -0
- package/src/home/suggested-prompts.ts +177 -9
- package/src/ipc/cli-client.ts +147 -45
- package/src/memory/__tests__/conversation-queries.test.ts +220 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +407 -10
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/conversation-queries.ts +87 -1
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +22 -0
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +84 -3
- package/src/memory/graph/conversation-graph-memory.ts +18 -6
- package/src/memory/graph/tools.ts +6 -37
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs-worker.ts +21 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +7 -2
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +4 -22
- package/src/memory/memory-retrospective-job.ts +438 -21
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +26 -8
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/index.ts +20 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +2 -0
- package/src/memory/schema/infrastructure.ts +2 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +221 -17
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/router.test.ts +489 -1
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +69 -29
- package/src/memory/v2/page-index.ts +246 -19
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +18 -3
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +5 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +521 -36
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +111 -44
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +10 -1
- package/src/notifications/home-feed-side-effect.ts +136 -27
- package/src/notifications/signal.ts +0 -4
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +13 -4
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +4 -1
- package/src/plugins/defaults/injectors.ts +118 -26
- package/src/plugins/external-plugin-loader.ts +82 -10
- package/src/plugins/types.ts +16 -7
- package/src/prompts/__tests__/system-prompt.test.ts +44 -45
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +4 -8
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -76
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +51 -10
- package/src/providers/__tests__/inference.test.ts +2 -0
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +63 -13
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +24 -21
- package/src/providers/inference/auth.ts +15 -3
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/connections.ts +85 -5
- package/src/providers/inference/resolve-auth.ts +50 -5
- package/src/providers/model-catalog.ts +244 -242
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +215 -25
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +46 -4
- package/src/providers/platform-proxy/constants.ts +3 -4
- package/src/providers/provider-catalog-visibility.ts +3 -1
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +30 -1
- package/src/providers/types.ts +25 -0
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +212 -57
- package/src/runtime/auth/route-policy.ts +20 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +7 -51
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +121 -5
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/channel-availability-routes.ts +5 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +146 -1
- package/src/runtime/routes/conversation-query-routes.ts +130 -12
- package/src/runtime/routes/conversation-routes.ts +288 -76
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +8 -1
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +14 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +192 -3
- package/src/runtime/routes/integrations/a2a.ts +294 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-v2-routes.ts +217 -0
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/slack-channel-routes.ts +187 -0
- package/src/runtime/routes/subagents-routes.ts +41 -0
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/subagent/manager.ts +2 -0
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
- package/src/tools/browser/browser-execution.ts +93 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
- package/src/tools/browser/cdp-client/factory.ts +87 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
- package/src/tools/browser/cdp-client/types.ts +36 -0
- package/src/tools/browser/pinned-tabs.ts +90 -0
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +128 -2
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +213 -64
- package/src/tools/network/web-search.ts +191 -66
- package/src/tools/registry.ts +2 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +41 -2
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/types/onboarding-context.ts +4 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/platform.ts +0 -5
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatic token refresh for ChatGPT Codex OAuth (subscription auth).
|
|
3
|
+
*
|
|
4
|
+
* OpenAI rotates refresh tokens on every use — concurrent refreshes will
|
|
5
|
+
* invalidate one token. A module-level mutex prevents this race.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { refreshOAuth2Token } from "../../security/oauth2.js";
|
|
9
|
+
import {
|
|
10
|
+
getSecureKeyAsync,
|
|
11
|
+
setSecureKeyAsync,
|
|
12
|
+
} from "../../security/secure-keys.js";
|
|
13
|
+
import { getLogger } from "../../util/logger.js";
|
|
14
|
+
|
|
15
|
+
const log = getLogger("codex-token-refresh");
|
|
16
|
+
|
|
17
|
+
const CODEX_TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
18
|
+
const CODEX_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
19
|
+
|
|
20
|
+
/** Refresh 5 minutes before expiry to avoid using a nearly-expired token. */
|
|
21
|
+
const REFRESH_MARGIN_SECONDS = 300;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Module-level mutex to prevent concurrent refresh races.
|
|
25
|
+
* OpenAI rotates refresh tokens on every use — two concurrent refreshes
|
|
26
|
+
* will invalidate one token.
|
|
27
|
+
*/
|
|
28
|
+
let refreshInFlight: Promise<string | null> | null = null;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Return a valid Codex access token, refreshing transparently if expired.
|
|
32
|
+
*
|
|
33
|
+
* @param credentialPrefix - Credential key prefix, e.g. `"credential/chatgpt"`.
|
|
34
|
+
* The function reads `<prefix>/access_token`, `<prefix>/refresh_token`,
|
|
35
|
+
* and `<prefix>/expires_at` from the credential store.
|
|
36
|
+
* @returns The access token string, or `null` if no token is stored.
|
|
37
|
+
*/
|
|
38
|
+
export async function getValidCodexAccessToken(
|
|
39
|
+
credentialPrefix: string,
|
|
40
|
+
): Promise<string | null> {
|
|
41
|
+
const accessToken = await getSecureKeyAsync(
|
|
42
|
+
`${credentialPrefix}/access_token`,
|
|
43
|
+
);
|
|
44
|
+
if (!accessToken) return null;
|
|
45
|
+
|
|
46
|
+
const expiresAtStr = await getSecureKeyAsync(
|
|
47
|
+
`${credentialPrefix}/expires_at`,
|
|
48
|
+
);
|
|
49
|
+
if (!expiresAtStr) return accessToken; // no expiry info — use token as-is
|
|
50
|
+
|
|
51
|
+
const expiresAt = Number(expiresAtStr);
|
|
52
|
+
const now = Date.now() / 1000;
|
|
53
|
+
|
|
54
|
+
if (now < expiresAt - REFRESH_MARGIN_SECONDS) {
|
|
55
|
+
return accessToken; // token is still fresh
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Token is expired or about to expire — refresh it.
|
|
59
|
+
// Use mutex to prevent concurrent refresh races.
|
|
60
|
+
if (refreshInFlight) {
|
|
61
|
+
return await refreshInFlight;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
refreshInFlight = doRefresh(credentialPrefix);
|
|
65
|
+
try {
|
|
66
|
+
return await refreshInFlight;
|
|
67
|
+
} finally {
|
|
68
|
+
refreshInFlight = null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function doRefresh(credentialPrefix: string): Promise<string | null> {
|
|
73
|
+
const refreshToken = await getSecureKeyAsync(
|
|
74
|
+
`${credentialPrefix}/refresh_token`,
|
|
75
|
+
);
|
|
76
|
+
if (!refreshToken) {
|
|
77
|
+
log.warn("No refresh token available for Codex OAuth");
|
|
78
|
+
// Return the existing access token — it might still work even if expired
|
|
79
|
+
return (
|
|
80
|
+
(await getSecureKeyAsync(`${credentialPrefix}/access_token`)) ?? null
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const result = await refreshOAuth2Token(
|
|
86
|
+
CODEX_TOKEN_URL,
|
|
87
|
+
CODEX_CLIENT_ID,
|
|
88
|
+
refreshToken,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Store the new tokens
|
|
92
|
+
await setSecureKeyAsync(
|
|
93
|
+
`${credentialPrefix}/access_token`,
|
|
94
|
+
result.accessToken,
|
|
95
|
+
);
|
|
96
|
+
if (result.refreshToken) {
|
|
97
|
+
await setSecureKeyAsync(
|
|
98
|
+
`${credentialPrefix}/refresh_token`,
|
|
99
|
+
result.refreshToken,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
if (result.expiresIn) {
|
|
103
|
+
const newExpiresAt = Math.floor(Date.now() / 1000 + result.expiresIn);
|
|
104
|
+
await setSecureKeyAsync(
|
|
105
|
+
`${credentialPrefix}/expires_at`,
|
|
106
|
+
String(newExpiresAt),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
log.info("Codex OAuth token refreshed successfully");
|
|
111
|
+
return result.accessToken;
|
|
112
|
+
} catch (err) {
|
|
113
|
+
log.error({ err }, "Codex OAuth token refresh failed");
|
|
114
|
+
// Return the existing access token as fallback
|
|
115
|
+
return (
|
|
116
|
+
(await getSecureKeyAsync(`${credentialPrefix}/access_token`)) ?? null
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Test helpers
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
/** @internal Test-only: reset the in-flight refresh mutex. */
|
|
126
|
+
export function _resetRefreshMutex(): void {
|
|
127
|
+
refreshInFlight = null;
|
|
128
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { and, eq, isNull } from "drizzle-orm";
|
|
2
|
+
import { z } from "zod";
|
|
2
3
|
|
|
3
4
|
import type { DrizzleDb } from "../../memory/db-connection.js";
|
|
4
5
|
import { providerConnections } from "../../memory/schema/inference.js";
|
|
@@ -6,6 +7,8 @@ import { clearConnectionProviderCache } from "../registry.js";
|
|
|
6
7
|
import {
|
|
7
8
|
type Auth,
|
|
8
9
|
AuthSchema,
|
|
10
|
+
type ConnectionModel,
|
|
11
|
+
ConnectionModelSchema,
|
|
9
12
|
type ConnectionProvider,
|
|
10
13
|
ConnectionProviderSchema,
|
|
11
14
|
type ConnectionStatus,
|
|
@@ -14,6 +17,23 @@ import {
|
|
|
14
17
|
VALID_CONNECTION_PROVIDERS,
|
|
15
18
|
} from "./auth.js";
|
|
16
19
|
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Helpers
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
function parseModelsColumn(raw: string | null): ConnectionModel[] | null {
|
|
25
|
+
if (raw === null || raw === "") return null;
|
|
26
|
+
try {
|
|
27
|
+
const parsed = z.array(ConnectionModelSchema).safeParse(JSON.parse(raw));
|
|
28
|
+
return parsed.success ? parsed.data : null;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const PROVIDERS_REQUIRING_BASE_URL_AND_MODELS: ReadonlySet<string> =
|
|
35
|
+
new Set(["openai-compatible"]);
|
|
36
|
+
|
|
17
37
|
// ---------------------------------------------------------------------------
|
|
18
38
|
// Read
|
|
19
39
|
// ---------------------------------------------------------------------------
|
|
@@ -46,6 +66,8 @@ export function listConnections(
|
|
|
46
66
|
provider: provider.data,
|
|
47
67
|
status,
|
|
48
68
|
label: row.label ?? null,
|
|
69
|
+
baseUrl: row.baseUrl ?? null,
|
|
70
|
+
models: parseModelsColumn(row.models),
|
|
49
71
|
isManaged: MANAGED_CONNECTION_NAMES.has(row.name),
|
|
50
72
|
},
|
|
51
73
|
];
|
|
@@ -77,6 +99,8 @@ export function getConnection(
|
|
|
77
99
|
provider: provider.data,
|
|
78
100
|
status,
|
|
79
101
|
label: row.label ?? null,
|
|
102
|
+
baseUrl: row.baseUrl ?? null,
|
|
103
|
+
models: parseModelsColumn(row.models),
|
|
80
104
|
isManaged: MANAGED_CONNECTION_NAMES.has(row.name),
|
|
81
105
|
};
|
|
82
106
|
}
|
|
@@ -91,22 +115,30 @@ export type CreateConnectionInput = {
|
|
|
91
115
|
auth: Auth;
|
|
92
116
|
status?: ConnectionStatus;
|
|
93
117
|
label?: string | null;
|
|
118
|
+
baseUrl?: string | null;
|
|
119
|
+
models?: ConnectionModel[] | null;
|
|
94
120
|
};
|
|
95
121
|
|
|
96
122
|
export type UpdateConnectionInput = {
|
|
97
123
|
auth: Auth;
|
|
98
124
|
status?: ConnectionStatus;
|
|
99
125
|
label?: string | null;
|
|
126
|
+
baseUrl?: string | null;
|
|
127
|
+
models?: ConnectionModel[] | null;
|
|
100
128
|
};
|
|
101
129
|
|
|
102
130
|
export type ConnectionCreateError =
|
|
103
131
|
| { code: "already_exists" }
|
|
104
132
|
| { code: "invalid_provider"; provider: string }
|
|
105
|
-
| { code: "invalid_auth" }
|
|
133
|
+
| { code: "invalid_auth" }
|
|
134
|
+
| { code: "base_url_required" }
|
|
135
|
+
| { code: "models_required" };
|
|
106
136
|
|
|
107
137
|
export type ConnectionUpdateError =
|
|
108
138
|
| { code: "not_found" }
|
|
109
|
-
| { code: "invalid_auth" }
|
|
139
|
+
| { code: "invalid_auth" }
|
|
140
|
+
| { code: "base_url_required" }
|
|
141
|
+
| { code: "models_required" };
|
|
110
142
|
|
|
111
143
|
export type ConnectionDeleteError =
|
|
112
144
|
| { code: "not_found" }
|
|
@@ -143,6 +175,15 @@ export function createConnection(
|
|
|
143
175
|
|
|
144
176
|
const status = input.status ?? "active";
|
|
145
177
|
const label = input.label ?? null;
|
|
178
|
+
const baseUrl = input.baseUrl ?? null;
|
|
179
|
+
const models = input.models ?? null;
|
|
180
|
+
|
|
181
|
+
if (PROVIDERS_REQUIRING_BASE_URL_AND_MODELS.has(provider)) {
|
|
182
|
+
if (!baseUrl) return { ok: false, error: { code: "base_url_required" } };
|
|
183
|
+
if (!models || models.length === 0) {
|
|
184
|
+
return { ok: false, error: { code: "models_required" } };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
146
187
|
|
|
147
188
|
const now = Date.now();
|
|
148
189
|
db.insert(providerConnections)
|
|
@@ -152,6 +193,8 @@ export function createConnection(
|
|
|
152
193
|
auth: JSON.stringify(authResult.data),
|
|
153
194
|
status,
|
|
154
195
|
label,
|
|
196
|
+
baseUrl,
|
|
197
|
+
models: models === null ? null : JSON.stringify(models),
|
|
155
198
|
createdAt: now,
|
|
156
199
|
updatedAt: now,
|
|
157
200
|
})
|
|
@@ -169,6 +212,8 @@ export function createConnection(
|
|
|
169
212
|
auth: authResult.data,
|
|
170
213
|
status,
|
|
171
214
|
label,
|
|
215
|
+
baseUrl,
|
|
216
|
+
models,
|
|
172
217
|
createdAt: now,
|
|
173
218
|
updatedAt: now,
|
|
174
219
|
isManaged: MANAGED_CONNECTION_NAMES.has(input.name),
|
|
@@ -193,15 +238,34 @@ export function updateConnection(
|
|
|
193
238
|
return { ok: false, error: { code: "invalid_auth" } };
|
|
194
239
|
}
|
|
195
240
|
|
|
241
|
+
const nextBaseUrl =
|
|
242
|
+
input.baseUrl !== undefined ? input.baseUrl : existing.baseUrl;
|
|
243
|
+
const nextModels =
|
|
244
|
+
input.models !== undefined ? input.models : existing.models;
|
|
245
|
+
|
|
246
|
+
if (PROVIDERS_REQUIRING_BASE_URL_AND_MODELS.has(existing.provider)) {
|
|
247
|
+
if (!nextBaseUrl)
|
|
248
|
+
return { ok: false, error: { code: "base_url_required" } };
|
|
249
|
+
if (!nextModels || nextModels.length === 0) {
|
|
250
|
+
return { ok: false, error: { code: "models_required" } };
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
196
254
|
const now = Date.now();
|
|
197
255
|
const setClause: {
|
|
198
256
|
auth: string;
|
|
199
257
|
updatedAt: number;
|
|
200
258
|
status?: string;
|
|
201
259
|
label?: string | null;
|
|
260
|
+
baseUrl?: string | null;
|
|
261
|
+
models?: string | null;
|
|
202
262
|
} = { auth: JSON.stringify(authResult.data), updatedAt: now };
|
|
203
263
|
if (input.status !== undefined) setClause.status = input.status;
|
|
204
264
|
if (input.label !== undefined) setClause.label = input.label;
|
|
265
|
+
if (input.baseUrl !== undefined) setClause.baseUrl = input.baseUrl;
|
|
266
|
+
if (input.models !== undefined)
|
|
267
|
+
setClause.models =
|
|
268
|
+
input.models === null ? null : JSON.stringify(input.models);
|
|
205
269
|
|
|
206
270
|
db.update(providerConnections)
|
|
207
271
|
.set(setClause)
|
|
@@ -218,6 +282,8 @@ export function updateConnection(
|
|
|
218
282
|
auth: authResult.data,
|
|
219
283
|
status: input.status !== undefined ? input.status : existing.status,
|
|
220
284
|
label: input.label !== undefined ? input.label : existing.label,
|
|
285
|
+
baseUrl: nextBaseUrl,
|
|
286
|
+
models: nextModels,
|
|
221
287
|
updatedAt: now,
|
|
222
288
|
},
|
|
223
289
|
};
|
|
@@ -294,6 +360,12 @@ const CANONICAL_CONNECTIONS: Array<{
|
|
|
294
360
|
auth: { type: "platform" },
|
|
295
361
|
label: "Google Gemini",
|
|
296
362
|
},
|
|
363
|
+
{
|
|
364
|
+
name: "fireworks-managed",
|
|
365
|
+
provider: "fireworks",
|
|
366
|
+
auth: { type: "platform" },
|
|
367
|
+
label: "Fireworks",
|
|
368
|
+
},
|
|
297
369
|
];
|
|
298
370
|
|
|
299
371
|
/**
|
|
@@ -330,7 +402,7 @@ export const MANAGED_CONNECTION_NAMES: ReadonlySet<string> = new Set(
|
|
|
330
402
|
*
|
|
331
403
|
* Status handling: the upsert never touches `status` so user customization
|
|
332
404
|
* is preserved across reboots. New rows default to `status: "active"` via the
|
|
333
|
-
* column default. Off-platform installs flip
|
|
405
|
+
* column default. Off-platform installs flip canonical managed rows to
|
|
334
406
|
* `status: "disabled"` ONCE at hatch time via
|
|
335
407
|
* `disableManagedConnectionsForByokHatch` (called from `seedInferenceProfiles`
|
|
336
408
|
* when `isHatch && !isPlatform`); subsequent boots leave whatever the user
|
|
@@ -374,7 +446,7 @@ export function seedCanonicalConnections(db: DrizzleDb): void {
|
|
|
374
446
|
}
|
|
375
447
|
|
|
376
448
|
/**
|
|
377
|
-
* Flip
|
|
449
|
+
* Flip canonical managed connections to `status: "disabled"` at
|
|
378
450
|
* hatch time on BYOK (off-platform) installs.
|
|
379
451
|
*
|
|
380
452
|
* Why hatch-time only: managed connections need platform auth that a fresh
|
|
@@ -389,10 +461,18 @@ export function seedCanonicalConnections(db: DrizzleDb): void {
|
|
|
389
461
|
*
|
|
390
462
|
* Idempotent: a second hatch (workspace reset) re-disables the rows, which
|
|
391
463
|
* is the right call — re-hatch means re-onboard.
|
|
464
|
+
*
|
|
465
|
+
* When onboarding explicitly selected a managed profile, callers may exclude
|
|
466
|
+
* that selected connection so the managed route remains usable for the first
|
|
467
|
+
* post-onboarding message.
|
|
392
468
|
*/
|
|
393
|
-
export function disableManagedConnectionsForByokHatch(
|
|
469
|
+
export function disableManagedConnectionsForByokHatch(
|
|
470
|
+
db: DrizzleDb,
|
|
471
|
+
options: { excludeConnection?: string } = {},
|
|
472
|
+
): void {
|
|
394
473
|
const now = Date.now();
|
|
395
474
|
for (const name of MANAGED_CONNECTION_NAMES) {
|
|
475
|
+
if (name === options.excludeConnection) continue;
|
|
396
476
|
db.update(providerConnections)
|
|
397
477
|
.set({ status: "disabled", updatedAt: now })
|
|
398
478
|
.where(eq(providerConnections.name, name))
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
* Resolves an `Auth` config into a `ResolvedAuth` that adapters consume.
|
|
3
3
|
*
|
|
4
4
|
* Resolution rules:
|
|
5
|
-
* - api_key
|
|
6
|
-
* - platform
|
|
7
|
-
* - none
|
|
8
|
-
* - oauth_subscription
|
|
5
|
+
* - api_key → fetch credential from vault → inject as bearer header
|
|
6
|
+
* - platform → build managed proxy URL and fetch the platform API key
|
|
7
|
+
* - none → pass through with no auth headers
|
|
8
|
+
* - oauth_subscription → fetch OAuth token from vault (with auto-refresh) → inject as bearer header
|
|
9
|
+
* - service_account → reject (v2 not yet shipped)
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
import {
|
|
@@ -13,7 +14,11 @@ import {
|
|
|
13
14
|
resolveManagedProxyContext,
|
|
14
15
|
} from "../../providers/platform-proxy/context.js";
|
|
15
16
|
import { getSecureKeyAsync } from "../../security/secure-keys.js";
|
|
17
|
+
import { getLogger } from "../../util/logger.js";
|
|
16
18
|
import type { Auth, ResolvedAuth } from "./auth.js";
|
|
19
|
+
import { PROVIDERS_REQUIRING_BASE_URL_AND_MODELS } from "./connections.js";
|
|
20
|
+
|
|
21
|
+
const log = getLogger("resolve-auth");
|
|
17
22
|
|
|
18
23
|
export type ResolveAuthError =
|
|
19
24
|
| { code: "credential_not_found"; credential: string }
|
|
@@ -23,9 +28,23 @@ export type ResolveAuthError =
|
|
|
23
28
|
export async function resolveAuth(
|
|
24
29
|
auth: Auth,
|
|
25
30
|
provider: string,
|
|
31
|
+
opts: { baseUrl?: string | null } = {},
|
|
26
32
|
): Promise<
|
|
27
33
|
{ ok: true; resolved: ResolvedAuth } | { ok: false; error: ResolveAuthError }
|
|
28
34
|
> {
|
|
35
|
+
// Defense-in-depth: strip baseUrl for providers that should not accept one.
|
|
36
|
+
// The route layer rejects base_url for non-openai-compatible providers, but
|
|
37
|
+
// this guard catches any code path that bypasses route validation (e.g.
|
|
38
|
+
// corrupted DB rows, direct calls from internal code).
|
|
39
|
+
let safeBaseUrl = opts.baseUrl;
|
|
40
|
+
if (safeBaseUrl && !PROVIDERS_REQUIRING_BASE_URL_AND_MODELS.has(provider)) {
|
|
41
|
+
log.warn(
|
|
42
|
+
{ provider, baseUrl: safeBaseUrl },
|
|
43
|
+
`Stripping baseUrl for provider "${provider}" — base_url is only valid for openai-compatible providers.`,
|
|
44
|
+
);
|
|
45
|
+
safeBaseUrl = null;
|
|
46
|
+
}
|
|
47
|
+
|
|
29
48
|
switch (auth.type) {
|
|
30
49
|
case "api_key": {
|
|
31
50
|
const value = await getSecureKeyAsync(auth.credential);
|
|
@@ -40,6 +59,7 @@ export async function resolveAuth(
|
|
|
40
59
|
resolved: {
|
|
41
60
|
kind: "header",
|
|
42
61
|
headers: { Authorization: `Bearer ${value}` },
|
|
62
|
+
...(safeBaseUrl ? { baseUrl: safeBaseUrl } : {}),
|
|
43
63
|
},
|
|
44
64
|
};
|
|
45
65
|
}
|
|
@@ -63,7 +83,32 @@ export async function resolveAuth(
|
|
|
63
83
|
case "none":
|
|
64
84
|
return { ok: true, resolved: { kind: "none" } };
|
|
65
85
|
|
|
66
|
-
case "oauth_subscription":
|
|
86
|
+
case "oauth_subscription": {
|
|
87
|
+
// Extract the credential prefix from the credential key.
|
|
88
|
+
// The credential field stores "credential/openai-codex/access_token";
|
|
89
|
+
// we need the prefix "credential/openai-codex" for the refresh logic.
|
|
90
|
+
const credentialPrefix = auth.credential.replace(/\/access_token$/, "");
|
|
91
|
+
|
|
92
|
+
const { getValidCodexAccessToken } = await import(
|
|
93
|
+
"./codex-token-refresh.js"
|
|
94
|
+
);
|
|
95
|
+
const token = await getValidCodexAccessToken(credentialPrefix);
|
|
96
|
+
|
|
97
|
+
if (!token) {
|
|
98
|
+
return {
|
|
99
|
+
ok: false,
|
|
100
|
+
error: { code: "credential_not_found", credential: auth.credential },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
ok: true,
|
|
105
|
+
resolved: {
|
|
106
|
+
kind: "header",
|
|
107
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
67
112
|
case "service_account":
|
|
68
113
|
return {
|
|
69
114
|
ok: false,
|