@vellumai/assistant 0.9.0 → 0.10.0-staging.2
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 +18 -34
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +976 -63
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/skill-execute-input.test.ts +51 -1
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +49 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +197 -4
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +105 -17
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +27 -14
- package/src/daemon/conversation.ts +66 -14
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/retry.ts +53 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +181 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +52 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +15 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +240 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +202 -3
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +2 -3
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +33 -0
- package/src/tools/subagent/spawn.ts +61 -12
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +9 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -41,7 +41,11 @@ function resetTables(): void {
|
|
|
41
41
|
|
|
42
42
|
async function addImageMessage(
|
|
43
43
|
conversationId: string,
|
|
44
|
-
provenanceTrustClass:
|
|
44
|
+
provenanceTrustClass:
|
|
45
|
+
| "guardian"
|
|
46
|
+
| "trusted_contact"
|
|
47
|
+
| "unverified_contact"
|
|
48
|
+
| "unknown",
|
|
45
49
|
filename: string,
|
|
46
50
|
): Promise<void> {
|
|
47
51
|
const inserted = await addMessage(
|
|
@@ -109,4 +113,20 @@ describe("collectImageManifest trust filtering", () => {
|
|
|
109
113
|
expect(filenames).toContain("contact.png");
|
|
110
114
|
expect(filenames).not.toContain("guardian-secret.png");
|
|
111
115
|
});
|
|
116
|
+
|
|
117
|
+
test("unverified_contact actor manifest excludes guardian images but keeps unverified-provenance images", async () => {
|
|
118
|
+
// GIVEN a conversation with a guardian image and an unverified-contact image
|
|
119
|
+
const conv = createConversation();
|
|
120
|
+
await addImageMessage(conv.id, "guardian", "guardian-secret.png");
|
|
121
|
+
await addImageMessage(conv.id, "unverified_contact", "unverified.png");
|
|
122
|
+
|
|
123
|
+
// WHEN the manifest is built for an unverified_contact actor
|
|
124
|
+
const manifest = collectImageManifest(conv.id, "unverified_contact");
|
|
125
|
+
|
|
126
|
+
// THEN the unverified-provenance image is listed and the guardian image
|
|
127
|
+
// is excluded — unverified_contact is treated as untrusted downstream.
|
|
128
|
+
const filenames = manifest.map((e) => e.filename);
|
|
129
|
+
expect(filenames).toContain("unverified.png");
|
|
130
|
+
expect(filenames).not.toContain("guardian-secret.png");
|
|
131
|
+
});
|
|
112
132
|
});
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The compaction summary call bounds its own input to the context window.
|
|
3
|
+
*
|
|
4
|
+
* With no tool pair to anchor an emergency split, an overflow recovery routes
|
|
5
|
+
* the full conversation straight into `runAssistantDrivenCompaction`. If that
|
|
6
|
+
* history exceeds the window, the summary call must front-truncate its own
|
|
7
|
+
* request or it overflows in turn and recovery stalls. Below the window the
|
|
8
|
+
* request is sent untouched so its prefix stays byte-aligned with the agent's
|
|
9
|
+
* warm cache (the budget-path cache reuse must not regress).
|
|
10
|
+
*/
|
|
11
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
function makeLoggerStub(): Record<string, unknown> {
|
|
14
|
+
const stub: Record<string, unknown> = {};
|
|
15
|
+
for (const m of [
|
|
16
|
+
"info",
|
|
17
|
+
"warn",
|
|
18
|
+
"error",
|
|
19
|
+
"debug",
|
|
20
|
+
"trace",
|
|
21
|
+
"fatal",
|
|
22
|
+
"silent",
|
|
23
|
+
"child",
|
|
24
|
+
]) {
|
|
25
|
+
stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
|
|
26
|
+
}
|
|
27
|
+
return stub;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
mock.module("../util/logger.js", () => ({
|
|
31
|
+
getLogger: () => makeLoggerStub(),
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
mock.module("../memory/conversation-crud.js", () => ({
|
|
35
|
+
getMessages: () => [],
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
mock.module("../memory/attachments-store.js", () => ({
|
|
39
|
+
getAttachmentMetadataForMessage: () => [],
|
|
40
|
+
getAttachmentContent: () => null,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
mock.module("../memory/llm-request-log-store.js", () => ({
|
|
44
|
+
recordRequestLog: () => {},
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
import { runAssistantDrivenCompaction } from "../context/compactor.js";
|
|
48
|
+
import { estimatePromptTokens } from "../context/token-estimator.js";
|
|
49
|
+
import type { Message, Provider } from "../providers/types.js";
|
|
50
|
+
|
|
51
|
+
const TRUNCATION_MARKER = "summary covers only the visible portion";
|
|
52
|
+
|
|
53
|
+
function turnTimestamp(turn: number): string {
|
|
54
|
+
const hour = String(10 + Math.floor(turn / 60)).padStart(2, "0");
|
|
55
|
+
const minute = String(turn % 60).padStart(2, "0");
|
|
56
|
+
return `2026-05-21 (Thursday) ${hour}:${minute}:00 -05:00 (America/Chicago)`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function userTurn(turn: number, body: string): Message {
|
|
60
|
+
return {
|
|
61
|
+
role: "user",
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: `<turn_context>\ncurrent_time: ${turnTimestamp(
|
|
66
|
+
turn,
|
|
67
|
+
)}\n</turn_context>\n[U${turn}] ${body}`,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function assistantTurn(turn: number, body: string): Message {
|
|
74
|
+
return {
|
|
75
|
+
role: "assistant",
|
|
76
|
+
content: [{ type: "text", text: `[A${turn}] ${body}` }],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const SUMMARY = "Earlier turns summarized in the assistant's own voice.";
|
|
81
|
+
|
|
82
|
+
function compactionResponse(tailTurn: number, preview: string): string {
|
|
83
|
+
return `<compaction_result>
|
|
84
|
+
<summary>
|
|
85
|
+
${SUMMARY}
|
|
86
|
+
</summary>
|
|
87
|
+
<key_state>
|
|
88
|
+
- Nothing critical pending.
|
|
89
|
+
</key_state>
|
|
90
|
+
<tail_start timestamp="${turnTimestamp(tailTurn)}" preview="${preview}" />
|
|
91
|
+
</compaction_result>`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function makeCapturingProvider(response: string): {
|
|
95
|
+
provider: Provider;
|
|
96
|
+
lastRequest: () => Message[] | null;
|
|
97
|
+
} {
|
|
98
|
+
let captured: Message[] | null = null;
|
|
99
|
+
const provider: Provider = {
|
|
100
|
+
name: "mock-provider",
|
|
101
|
+
sendMessage: async (messages: Message[]) => {
|
|
102
|
+
captured = messages;
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: "text", text: response }],
|
|
105
|
+
model: "mock-model",
|
|
106
|
+
usage: { inputTokens: 100, outputTokens: 50 },
|
|
107
|
+
stopReason: "end_turn",
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
return { provider, lastRequest: () => captured };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function estimate(messages: Message[]): number {
|
|
115
|
+
return estimatePromptTokens(messages, "system", {
|
|
116
|
+
providerName: "mock-provider",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
describe("runAssistantDrivenCompaction — summary call self-truncation", () => {
|
|
121
|
+
test("front-truncates the outbound request when the full history exceeds the context window", async () => {
|
|
122
|
+
// GIVEN a tool-pair-free history whose estimate exceeds the window, so an
|
|
123
|
+
// overflow recovery would route it straight into the summary call.
|
|
124
|
+
const messages: Message[] = [];
|
|
125
|
+
for (let i = 0; i < 40; i++) {
|
|
126
|
+
messages.push(
|
|
127
|
+
userTurn(
|
|
128
|
+
i,
|
|
129
|
+
"Heavy user turn body that carries real weight. ".repeat(8),
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
messages.push(
|
|
133
|
+
assistantTurn(
|
|
134
|
+
i,
|
|
135
|
+
"Heavy assistant reply that also carries weight. ".repeat(8),
|
|
136
|
+
),
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const maxInputTokens = 10_000;
|
|
141
|
+
// Budget mirrors compactor.compactionPrefixBudget: window minus the
|
|
142
|
+
// instruction reserve (800) and the 15% output reserve.
|
|
143
|
+
const prefixBudget =
|
|
144
|
+
maxInputTokens - 800 - Math.floor(maxInputTokens * 0.15);
|
|
145
|
+
expect(estimate(messages)).toBeGreaterThan(prefixBudget);
|
|
146
|
+
|
|
147
|
+
const { provider, lastRequest } = makeCapturingProvider(
|
|
148
|
+
compactionResponse(38, "Heavy user turn body"),
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
// WHEN the summary call runs against that oversized history.
|
|
152
|
+
const result = await runAssistantDrivenCompaction({
|
|
153
|
+
conversationId: "conv-test",
|
|
154
|
+
messages,
|
|
155
|
+
provider,
|
|
156
|
+
systemPrompt: "system",
|
|
157
|
+
compaction: { enabled: true, autoThreshold: 0.7 },
|
|
158
|
+
maxInputTokens,
|
|
159
|
+
force: true,
|
|
160
|
+
previousEstimatedInputTokens: 90_000,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(result.compacted).toBe(true);
|
|
164
|
+
|
|
165
|
+
// THEN the request actually sent fits within the context window.
|
|
166
|
+
const sent = lastRequest();
|
|
167
|
+
expect(sent).not.toBeNull();
|
|
168
|
+
expect(estimate(sent ?? [])).toBeLessThan(maxInputTokens);
|
|
169
|
+
|
|
170
|
+
// AND it opens with a marker noting the dropped leading messages so the
|
|
171
|
+
// model knows the summary covers only the visible portion.
|
|
172
|
+
const firstBlock = sent?.[0]?.content[0];
|
|
173
|
+
const firstText = firstBlock && "text" in firstBlock ? firstBlock.text : "";
|
|
174
|
+
expect(firstText).toContain(TRUNCATION_MARKER);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("sends the full history untouched when it already fits below the budget", async () => {
|
|
178
|
+
// GIVEN a small history whose estimate is well under the window — the
|
|
179
|
+
// common budget-triggered compaction.
|
|
180
|
+
const messages: Message[] = [];
|
|
181
|
+
for (let i = 0; i < 8; i++) {
|
|
182
|
+
messages.push(userTurn(i, "short user turn body"));
|
|
183
|
+
messages.push(assistantTurn(i, "short assistant reply body"));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const maxInputTokens = 200_000;
|
|
187
|
+
const prefixBudget =
|
|
188
|
+
maxInputTokens - 800 - Math.floor(maxInputTokens * 0.15);
|
|
189
|
+
expect(estimate(messages)).toBeLessThan(prefixBudget);
|
|
190
|
+
|
|
191
|
+
const { provider, lastRequest } = makeCapturingProvider(
|
|
192
|
+
compactionResponse(6, "short user turn body"),
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
// WHEN the summary call runs against the below-budget history.
|
|
196
|
+
const result = await runAssistantDrivenCompaction({
|
|
197
|
+
conversationId: "conv-test",
|
|
198
|
+
messages,
|
|
199
|
+
provider,
|
|
200
|
+
systemPrompt: "system",
|
|
201
|
+
compaction: { enabled: true, autoThreshold: 0.7 },
|
|
202
|
+
maxInputTokens,
|
|
203
|
+
force: true,
|
|
204
|
+
previousEstimatedInputTokens: 90_000,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
expect(result.compacted).toBe(true);
|
|
208
|
+
|
|
209
|
+
// THEN no truncation marker is prepended and the request carries every
|
|
210
|
+
// history message plus the single instruction, with the leading message
|
|
211
|
+
// byte-identical to the original — keeping the prefix cache warm.
|
|
212
|
+
const sent = lastRequest();
|
|
213
|
+
expect(sent).not.toBeNull();
|
|
214
|
+
expect(sent?.length).toBe(messages.length + 1);
|
|
215
|
+
const firstBlock = sent?.[0]?.content[0];
|
|
216
|
+
const firstText = firstBlock && "text" in firstBlock ? firstBlock.text : "";
|
|
217
|
+
expect(firstText).not.toContain(TRUNCATION_MARKER);
|
|
218
|
+
const originalFirst = messages[0]?.content[0];
|
|
219
|
+
expect(firstText).toBe(
|
|
220
|
+
originalFirst && "text" in originalFirst ? originalFirst.text : "",
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
@@ -75,7 +75,12 @@ import {
|
|
|
75
75
|
loadConfig,
|
|
76
76
|
mergeDefaultWorkspaceConfig,
|
|
77
77
|
} from "../config/loader.js";
|
|
78
|
-
import {
|
|
78
|
+
import {
|
|
79
|
+
MANAGED_PROFILE_NAMES,
|
|
80
|
+
materializeProfile,
|
|
81
|
+
OS_BETA_PROFILE_TEMPLATE,
|
|
82
|
+
seedInferenceProfiles,
|
|
83
|
+
} from "../config/seed-inference-profiles.js";
|
|
79
84
|
import type { DrizzleDb } from "../memory/db-connection.js";
|
|
80
85
|
import { migrateCreateProviderConnections } from "../memory/migrations/243-provider-connections.js";
|
|
81
86
|
import { migrateProviderConnectionStatusLabel } from "../memory/migrations/244-provider-connection-status-label.js";
|
|
@@ -417,6 +422,24 @@ describe("loadConfig startup behavior", () => {
|
|
|
417
422
|
expect(raw.memory?.jobs?.workerConcurrency).toBe(4);
|
|
418
423
|
});
|
|
419
424
|
|
|
425
|
+
test("strips daemon.reapOrphanedSubprocesses from existing user configs", () => {
|
|
426
|
+
// `daemon.reapOrphanedSubprocesses` is a deprecated opt-in flag: the
|
|
427
|
+
// orphan-subprocess reaper runs by default whenever the daemon is PID 1 on
|
|
428
|
+
// Linux. Existing configs that have it written to disk should load cleanly
|
|
429
|
+
// with the field silently stripped.
|
|
430
|
+
writeConfig({
|
|
431
|
+
provider: "anthropic",
|
|
432
|
+
daemon: { reapOrphanedSubprocesses: true, standaloneRecording: false },
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
loadConfig();
|
|
436
|
+
|
|
437
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
438
|
+
expect(raw.daemon?.reapOrphanedSubprocesses).toBeUndefined();
|
|
439
|
+
// Sibling fields under daemon are preserved
|
|
440
|
+
expect(raw.daemon?.standaloneRecording).toBe(false);
|
|
441
|
+
});
|
|
442
|
+
|
|
420
443
|
test("still writes a default config on first launch when file is absent", () => {
|
|
421
444
|
// Discoverability: when no config.json exists, write one populated with
|
|
422
445
|
// all schema defaults so users can see and edit available options.
|
|
@@ -462,9 +485,11 @@ describe("loadConfig startup behavior", () => {
|
|
|
462
485
|
"anthropic-personal",
|
|
463
486
|
);
|
|
464
487
|
// Managed profiles exist as well.
|
|
465
|
-
expect(config.llm.profiles.balanced?.model).toBe(
|
|
488
|
+
expect(config.llm.profiles.balanced?.model).toBe(
|
|
489
|
+
"accounts/fireworks/models/minimax-m3",
|
|
490
|
+
);
|
|
466
491
|
expect(config.llm.profiles.balanced?.provider_connection).toBe(
|
|
467
|
-
"
|
|
492
|
+
"fireworks-managed",
|
|
468
493
|
);
|
|
469
494
|
|
|
470
495
|
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
@@ -473,7 +498,9 @@ describe("loadConfig startup behavior", () => {
|
|
|
473
498
|
model: "claude-opus-4-7",
|
|
474
499
|
});
|
|
475
500
|
expect(raw.llm.activeProfile).toBe("custom-balanced");
|
|
476
|
-
expect(raw.llm.profiles.balanced.model).toBe(
|
|
501
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
502
|
+
"accounts/fireworks/models/minimax-m3",
|
|
503
|
+
);
|
|
477
504
|
});
|
|
478
505
|
|
|
479
506
|
test("on-platform hatch seeds only managed profiles", () => {
|
|
@@ -501,9 +528,11 @@ describe("loadConfig startup behavior", () => {
|
|
|
501
528
|
const config = loadConfig();
|
|
502
529
|
|
|
503
530
|
expect(config.llm.activeProfile).toBe("balanced");
|
|
504
|
-
expect(config.llm.profiles.balanced?.model).toBe(
|
|
531
|
+
expect(config.llm.profiles.balanced?.model).toBe(
|
|
532
|
+
"accounts/fireworks/models/minimax-m3",
|
|
533
|
+
);
|
|
505
534
|
expect(config.llm.profiles.balanced?.provider_connection).toBe(
|
|
506
|
-
"
|
|
535
|
+
"fireworks-managed",
|
|
507
536
|
);
|
|
508
537
|
// No user profiles created on platform.
|
|
509
538
|
expect(config.llm.profiles["custom-balanced"]).toBeUndefined();
|
|
@@ -545,10 +574,10 @@ describe("loadConfig startup behavior", () => {
|
|
|
545
574
|
expect(raw.llm.profiles["custom-balanced"].provider_connection).toBe(
|
|
546
575
|
"anthropic-personal",
|
|
547
576
|
);
|
|
548
|
-
// Managed balanced profile is seeded for
|
|
549
|
-
expect(raw.llm.profiles.balanced.provider).toBe("
|
|
577
|
+
// Managed balanced profile is seeded for fireworks-managed (MiniMax M3).
|
|
578
|
+
expect(raw.llm.profiles.balanced.provider).toBe("fireworks");
|
|
550
579
|
expect(raw.llm.profiles.balanced.provider_connection).toBe(
|
|
551
|
-
"
|
|
580
|
+
"fireworks-managed",
|
|
552
581
|
);
|
|
553
582
|
});
|
|
554
583
|
|
|
@@ -582,9 +611,9 @@ describe("loadConfig startup behavior", () => {
|
|
|
582
611
|
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
583
612
|
// On-platform: no user profiles created, active resets to managed balanced.
|
|
584
613
|
expect(raw.llm.activeProfile).toBe("balanced");
|
|
585
|
-
expect(raw.llm.profiles.balanced.provider).toBe("
|
|
614
|
+
expect(raw.llm.profiles.balanced.provider).toBe("fireworks");
|
|
586
615
|
expect(raw.llm.profiles.balanced.provider_connection).toBe(
|
|
587
|
-
"
|
|
616
|
+
"fireworks-managed",
|
|
588
617
|
);
|
|
589
618
|
// The old custom-balanced is preserved on disk but no longer active.
|
|
590
619
|
expect(raw.llm.profiles["custom-balanced"].provider).toBe("openai");
|
|
@@ -636,10 +665,10 @@ describe("loadConfig startup behavior", () => {
|
|
|
636
665
|
"gpt-5.4-nano",
|
|
637
666
|
);
|
|
638
667
|
|
|
639
|
-
// Managed profiles are also seeded (balanced uses
|
|
640
|
-
expect(raw.llm.profiles.balanced.provider).toBe("
|
|
668
|
+
// Managed profiles are also seeded (balanced uses Fireworks/MiniMax M3).
|
|
669
|
+
expect(raw.llm.profiles.balanced.provider).toBe("fireworks");
|
|
641
670
|
expect(raw.llm.profiles.balanced.provider_connection).toBe(
|
|
642
|
-
"
|
|
671
|
+
"fireworks-managed",
|
|
643
672
|
);
|
|
644
673
|
expect(raw.llm.profiles.balanced.source).toBe("managed");
|
|
645
674
|
expect(raw.llm.profiles["quality-optimized"].provider).toBe("anthropic");
|
|
@@ -667,13 +696,84 @@ describe("loadConfig startup behavior", () => {
|
|
|
667
696
|
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
668
697
|
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
669
698
|
|
|
670
|
-
expect(raw.llm.profiles.balanced.model).toBe(
|
|
699
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
700
|
+
"accounts/fireworks/models/minimax-m3",
|
|
701
|
+
);
|
|
702
|
+
expect(raw.llm.profiles.balanced.provider_connection).toBe(
|
|
703
|
+
"fireworks-managed",
|
|
704
|
+
);
|
|
705
|
+
expect(raw.llm.activeProfile).toBe("balanced");
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
test("on-platform managed profiles reconcile to the code template on every boot", () => {
|
|
709
|
+
// Headline behavior: on-platform installs now reconcile managed profile
|
|
710
|
+
// content from the code template on every boot (same as off-platform), so
|
|
711
|
+
// model/config updates ship in a release without a workspace migration.
|
|
712
|
+
process.env.IS_PLATFORM = "true";
|
|
713
|
+
|
|
714
|
+
writeConfig({
|
|
715
|
+
llm: {
|
|
716
|
+
profiles: {
|
|
717
|
+
balanced: {
|
|
718
|
+
source: "managed",
|
|
719
|
+
provider: "anthropic",
|
|
720
|
+
model: "old-model-from-previous-release",
|
|
721
|
+
maxTokens: 1,
|
|
722
|
+
provider_connection: "anthropic-managed",
|
|
723
|
+
},
|
|
724
|
+
},
|
|
725
|
+
activeProfile: "balanced",
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
// Non-hatch boot (no overlay). Content is refreshed from the template.
|
|
730
|
+
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
731
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
732
|
+
|
|
733
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
734
|
+
"accounts/fireworks/models/minimax-m3",
|
|
735
|
+
);
|
|
736
|
+
expect(raw.llm.profiles.balanced.maxTokens).toBe(32000);
|
|
737
|
+
expect(raw.llm.profiles.balanced.topP).toBe(0.95);
|
|
671
738
|
expect(raw.llm.profiles.balanced.provider_connection).toBe(
|
|
672
|
-
"
|
|
739
|
+
"fireworks-managed",
|
|
673
740
|
);
|
|
674
741
|
expect(raw.llm.activeProfile).toBe("balanced");
|
|
675
742
|
});
|
|
676
743
|
|
|
744
|
+
test("on-platform reseed preserves user-edited label and status on managed profiles", () => {
|
|
745
|
+
// The only two fields a user may override on a managed profile — label and
|
|
746
|
+
// status — survive the on-platform reconcile, exactly as off-platform.
|
|
747
|
+
process.env.IS_PLATFORM = "true";
|
|
748
|
+
|
|
749
|
+
writeConfig({
|
|
750
|
+
llm: {
|
|
751
|
+
profiles: {
|
|
752
|
+
balanced: {
|
|
753
|
+
source: "managed",
|
|
754
|
+
provider: "anthropic",
|
|
755
|
+
model: "old-model-from-previous-release",
|
|
756
|
+
provider_connection: "anthropic-managed",
|
|
757
|
+
label: "My Default",
|
|
758
|
+
status: "disabled",
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
activeProfile: "balanced",
|
|
762
|
+
},
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
766
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
767
|
+
|
|
768
|
+
// Content refreshes from the template...
|
|
769
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
770
|
+
"accounts/fireworks/models/minimax-m3",
|
|
771
|
+
);
|
|
772
|
+
// ...but the user's label and status overrides are preserved.
|
|
773
|
+
expect(raw.llm.profiles.balanced.label).toBe("My Default");
|
|
774
|
+
expect(raw.llm.profiles.balanced.status).toBe("disabled");
|
|
775
|
+
});
|
|
776
|
+
|
|
677
777
|
test("off-platform reseed preserves user-edited label on managed profiles (Codex P1 on PR #30362)", () => {
|
|
678
778
|
// Simulate a user who renamed the managed "balanced" profile via
|
|
679
779
|
// PUT /v1/config/llm/profiles/balanced { label: "My Default" }.
|
|
@@ -696,7 +796,9 @@ describe("loadConfig startup behavior", () => {
|
|
|
696
796
|
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
697
797
|
|
|
698
798
|
// Model still gets the new template value (provider-controlled).
|
|
699
|
-
expect(raw.llm.profiles.balanced.model).toBe(
|
|
799
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
800
|
+
"accounts/fireworks/models/minimax-m3",
|
|
801
|
+
);
|
|
700
802
|
// But the user's label override is preserved across the reseed.
|
|
701
803
|
expect(raw.llm.profiles.balanced.label).toBe("My Default");
|
|
702
804
|
});
|
|
@@ -724,7 +826,51 @@ describe("loadConfig startup behavior", () => {
|
|
|
724
826
|
|
|
725
827
|
expect(raw.llm.profiles.balanced.status).toBe("disabled");
|
|
726
828
|
// Model still refreshes — only label/status are user-owned.
|
|
727
|
-
expect(raw.llm.profiles.balanced.model).toBe(
|
|
829
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
830
|
+
"accounts/fireworks/models/minimax-m3",
|
|
831
|
+
);
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
test("reseed preserves user-edited topP on managed profiles", () => {
|
|
835
|
+
// Simulate a user who overrode topP on the managed "balanced" profile via
|
|
836
|
+
// PUT /v1/config/llm/profiles/balanced { topP: 0.5 }. The override must
|
|
837
|
+
// survive the reconcile instead of reverting to the template's 0.95.
|
|
838
|
+
writeConfig({
|
|
839
|
+
llm: {
|
|
840
|
+
profiles: {
|
|
841
|
+
balanced: {
|
|
842
|
+
source: "managed",
|
|
843
|
+
provider: "anthropic",
|
|
844
|
+
model: "old-model-from-previous-release",
|
|
845
|
+
provider_connection: "anthropic-managed",
|
|
846
|
+
topP: 0.5,
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
activeProfile: "balanced",
|
|
850
|
+
},
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
854
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
855
|
+
|
|
856
|
+
// The user's topP override is preserved across the reseed (not reverted to
|
|
857
|
+
// the template default of 0.95).
|
|
858
|
+
expect(raw.llm.profiles.balanced.topP).toBe(0.5);
|
|
859
|
+
// Model still refreshes — topP is user-owned, the rest is template-owned.
|
|
860
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
861
|
+
"accounts/fireworks/models/minimax-m3",
|
|
862
|
+
);
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
test("reseed seeds the template topP on a fresh managed balanced profile", () => {
|
|
866
|
+
// No previous on-disk entry → the balanced profile materializes with the
|
|
867
|
+
// template's topP default of 0.95.
|
|
868
|
+
writeConfig({ llm: {} });
|
|
869
|
+
|
|
870
|
+
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
871
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
872
|
+
|
|
873
|
+
expect(raw.llm.profiles.balanced.topP).toBe(0.95);
|
|
728
874
|
});
|
|
729
875
|
|
|
730
876
|
test("off-platform reseed preserves an explicit null label (user cleared it)", () => {
|
|
@@ -765,12 +911,20 @@ describe("loadConfig startup behavior", () => {
|
|
|
765
911
|
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
766
912
|
|
|
767
913
|
expect(raw.llm.profiles.balanced.label).toBe("Balanced (Managed)");
|
|
768
|
-
expect(raw.llm.profiles.balanced.model).toBe(
|
|
914
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
915
|
+
"accounts/fireworks/models/minimax-m3",
|
|
916
|
+
);
|
|
769
917
|
// Status is unset by default — must not appear as `undefined`.
|
|
770
918
|
expect("status" in raw.llm.profiles.balanced).toBe(false);
|
|
771
919
|
});
|
|
772
920
|
|
|
773
|
-
test("platform
|
|
921
|
+
test("platform overlay fragment wins its hatch boot, then content reconciles to the code template (label preserved)", () => {
|
|
922
|
+
// The overlay is authoritative for the boot it is supplied: its `balanced`
|
|
923
|
+
// fragment lands verbatim and is never polluted by template fields it omits
|
|
924
|
+
// (no maxTokens/thinking leak in). On the next boot — overlay archived —
|
|
925
|
+
// managed profile *content* reconciles to the code template, since the
|
|
926
|
+
// templates are the single source of truth for content. Only the
|
|
927
|
+
// user/overlay-set `label` survives the reconcile.
|
|
774
928
|
process.env.IS_PLATFORM = "true";
|
|
775
929
|
|
|
776
930
|
writeConfig({
|
|
@@ -824,6 +978,7 @@ describe("loadConfig startup behavior", () => {
|
|
|
824
978
|
const config = loadConfig();
|
|
825
979
|
const mainAgentConfig = resolveCallSiteConfig("mainAgent", config.llm);
|
|
826
980
|
|
|
981
|
+
// Hatch boot: overlay fragment is preserved verbatim (preserveProfileNames).
|
|
827
982
|
expect(config.llm.activeProfile).toBe("balanced");
|
|
828
983
|
expect(config.llm.profiles.balanced).toEqual({
|
|
829
984
|
source: "managed",
|
|
@@ -844,16 +999,26 @@ describe("loadConfig startup behavior", () => {
|
|
|
844
999
|
expect(raw.llm.profiles.balanced.maxTokens).toBeUndefined();
|
|
845
1000
|
expect(raw.llm.profiles.balanced.thinking).toBeUndefined();
|
|
846
1001
|
|
|
1002
|
+
// Next boot, no overlay: content reconciles to the fireworks-managed code
|
|
1003
|
+
// template; only the overlay-set label is carried across.
|
|
847
1004
|
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
848
1005
|
|
|
849
1006
|
const afterRestart = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
850
1007
|
expect(afterRestart.llm.activeProfile).toBe("balanced");
|
|
851
|
-
expect(afterRestart.llm.profiles.balanced).
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1008
|
+
expect(afterRestart.llm.profiles.balanced.provider).toBe("fireworks");
|
|
1009
|
+
expect(afterRestart.llm.profiles.balanced.provider_connection).toBe(
|
|
1010
|
+
"fireworks-managed",
|
|
1011
|
+
);
|
|
1012
|
+
expect(afterRestart.llm.profiles.balanced.model).toBe(
|
|
1013
|
+
"accounts/fireworks/models/minimax-m3",
|
|
1014
|
+
);
|
|
1015
|
+
expect(afterRestart.llm.profiles.balanced.maxTokens).toBe(32000);
|
|
1016
|
+
expect(afterRestart.llm.profiles.balanced.thinking).toEqual({
|
|
1017
|
+
enabled: true,
|
|
1018
|
+
streamThinking: true,
|
|
856
1019
|
});
|
|
1020
|
+
// The user/overlay-set label is the one field that survives the reconcile.
|
|
1021
|
+
expect(afterRestart.llm.profiles.balanced.label).toBe("Platform Balanced");
|
|
857
1022
|
});
|
|
858
1023
|
|
|
859
1024
|
test("quarantines corrupt config before merging hatch overlay", () => {
|
|
@@ -892,7 +1057,9 @@ describe("loadConfig startup behavior", () => {
|
|
|
892
1057
|
// Off-platform hatch: user profiles are active.
|
|
893
1058
|
expect(raw.llm.activeProfile).toBe("custom-balanced");
|
|
894
1059
|
expect(raw.llm.profiles["custom-balanced"].provider).toBe("anthropic");
|
|
895
|
-
expect(raw.llm.profiles.balanced.model).toBe(
|
|
1060
|
+
expect(raw.llm.profiles.balanced.model).toBe(
|
|
1061
|
+
"accounts/fireworks/models/minimax-m3",
|
|
1062
|
+
);
|
|
896
1063
|
});
|
|
897
1064
|
|
|
898
1065
|
test("still quarantines corrupt JSON", () => {
|
|
@@ -989,6 +1156,11 @@ describe("seedInferenceProfiles BYOK-mode managed profile labels", () => {
|
|
|
989
1156
|
|
|
990
1157
|
// Personal profiles keep their bare labels — they're the daily driver.
|
|
991
1158
|
expect(config.llm.profiles["custom-balanced"]?.label).toBe("Balanced");
|
|
1159
|
+
|
|
1160
|
+
// top_p is scoped to the managed Balanced profile only; the BYOK
|
|
1161
|
+
// custom-balanced profile must not pick it up.
|
|
1162
|
+
expect(config.llm.profiles.balanced?.topP).toBe(0.95);
|
|
1163
|
+
expect(config.llm.profiles["custom-balanced"]?.topP).toBeUndefined();
|
|
992
1164
|
});
|
|
993
1165
|
|
|
994
1166
|
test("off-platform hatch initializes managed profile status to 'disabled'", () => {
|
|
@@ -1036,7 +1208,7 @@ describe("seedInferenceProfiles BYOK-mode managed profile labels", () => {
|
|
|
1036
1208
|
|
|
1037
1209
|
expect(raw.llm.activeProfile).toBe("balanced");
|
|
1038
1210
|
expect(raw.llm.profiles.balanced.provider_connection).toBe(
|
|
1039
|
-
"
|
|
1211
|
+
"fireworks-managed",
|
|
1040
1212
|
);
|
|
1041
1213
|
expect("status" in raw.llm.profiles.balanced).toBe(false);
|
|
1042
1214
|
// Connections exist (status is no longer a connection-level concept).
|
|
@@ -1283,3 +1455,72 @@ describe("seedInferenceProfiles BYOK-mode managed profile labels", () => {
|
|
|
1283
1455
|
expect(config.llm.profiles.balanced?.label).toBe("Balanced (Managed)");
|
|
1284
1456
|
});
|
|
1285
1457
|
});
|
|
1458
|
+
|
|
1459
|
+
// ---------------------------------------------------------------------------
|
|
1460
|
+
// Tests: OS Beta flag-gated managed profile. The template is defined but
|
|
1461
|
+
// intentionally NOT part of MANAGED_PROFILE_TEMPLATES, so seedInferenceProfiles
|
|
1462
|
+
// must never create it. A later PR reconciles it in/out based on the `os-beta`
|
|
1463
|
+
// feature flag.
|
|
1464
|
+
// ---------------------------------------------------------------------------
|
|
1465
|
+
|
|
1466
|
+
describe("OS Beta managed profile template", () => {
|
|
1467
|
+
beforeEach(() => {
|
|
1468
|
+
ensureTestDir();
|
|
1469
|
+
const resetPaths = [
|
|
1470
|
+
CONFIG_PATH,
|
|
1471
|
+
join(WORKSPACE_DIR, "default-config.json"),
|
|
1472
|
+
join(WORKSPACE_DIR, "hatch-overlay.json"),
|
|
1473
|
+
join(WORKSPACE_DIR, "keys.enc"),
|
|
1474
|
+
join(WORKSPACE_DIR, "data"),
|
|
1475
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
1476
|
+
];
|
|
1477
|
+
for (const path of resetPaths) {
|
|
1478
|
+
if (existsSync(path)) {
|
|
1479
|
+
rmSync(path, { recursive: true, force: true });
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
ensureTestDir();
|
|
1483
|
+
setStorePathForTesting(join(WORKSPACE_DIR, "keys.enc"));
|
|
1484
|
+
delete process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH;
|
|
1485
|
+
delete process.env.IS_PLATFORM;
|
|
1486
|
+
invalidateConfigCache();
|
|
1487
|
+
});
|
|
1488
|
+
|
|
1489
|
+
afterEach(() => {
|
|
1490
|
+
setStorePathForTesting(null);
|
|
1491
|
+
delete process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH;
|
|
1492
|
+
delete process.env.IS_PLATFORM;
|
|
1493
|
+
invalidateConfigCache();
|
|
1494
|
+
});
|
|
1495
|
+
|
|
1496
|
+
test("seedInferenceProfiles does not create an os-beta profile", () => {
|
|
1497
|
+
writeConfig({ llm: { default: { provider: "anthropic" } } });
|
|
1498
|
+
|
|
1499
|
+
mergeDefaultConfigAndSeedInferenceProfiles();
|
|
1500
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
1501
|
+
|
|
1502
|
+
expect(raw.llm.profiles["os-beta"]).toBeUndefined();
|
|
1503
|
+
expect((raw.llm.profileOrder as string[]).includes("os-beta")).toBe(false);
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1506
|
+
test("MANAGED_PROFILE_NAMES contains os-beta", () => {
|
|
1507
|
+
expect(MANAGED_PROFILE_NAMES.has("os-beta")).toBe(true);
|
|
1508
|
+
});
|
|
1509
|
+
|
|
1510
|
+
test("materializeProfile honors the explicit OS Beta model", () => {
|
|
1511
|
+
const entry = materializeProfile(
|
|
1512
|
+
OS_BETA_PROFILE_TEMPLATE,
|
|
1513
|
+
"fireworks",
|
|
1514
|
+
"fireworks-managed",
|
|
1515
|
+
);
|
|
1516
|
+
|
|
1517
|
+
expect(entry.model).toBe("accounts/fireworks/models/glm-5p2");
|
|
1518
|
+
expect(entry.provider_connection).toBe("fireworks-managed");
|
|
1519
|
+
expect(entry.provider).toBe("fireworks");
|
|
1520
|
+
expect(entry.label).toBe("OS Beta");
|
|
1521
|
+
expect(entry.source).toBe("managed");
|
|
1522
|
+
expect(entry.maxTokens).toBe(32000);
|
|
1523
|
+
expect(entry.effort).toBe("high");
|
|
1524
|
+
expect(entry.thinking?.enabled).toBe(true);
|
|
1525
|
+
});
|
|
1526
|
+
});
|