@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a
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 +19 -35
- 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 +1128 -119
- 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__/agent-loop-pushes-post-hook-prompt.test.ts +306 -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__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-routes-http.test.ts +128 -0
- 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__/compaction-events.test.ts +6 -0
- 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-abort-tool-results.test.ts +6 -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-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-process-callsite.test.ts +6 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +6 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -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-pressure-tools.test.ts +41 -1
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/document-tool-security.test.ts +9 -6
- package/src/__tests__/document-update-default-surface.test.ts +202 -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__/gemini-count-tokens.test.ts +70 -0
- 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-disk-pressure.test.ts +10 -5
- 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__/secret-response-routing.test.ts +35 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
- package/src/__tests__/skill-execute-input.test.ts +177 -1
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- 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__/system-storage-cleanup-skill.test.ts +56 -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 +75 -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/db/status.ts +37 -3
- 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 +400 -14
- 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__/install-from-github.test.ts +31 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -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 +128 -19
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -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/document-editor/SKILL.md +3 -3
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- 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/system-storage-cleanup/SKILL.md +74 -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/__tests__/conversation-tool-setup.test.ts +44 -0
- 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 +53 -19
- package/src/daemon/conversation.ts +131 -20
- 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/memory-v2-startup.test.ts +131 -0
- package/src/daemon/memory-v2-startup.ts +100 -1
- 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/daemon/wake-conversation-ops.ts +1 -0
- 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__/db-logs-attach.test.ts +122 -0
- 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-async-query.ts +20 -2
- package/src/memory/db-connection.ts +49 -5
- 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/permissions/secret-prompter.ts +15 -1
- 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/compaction/window-manager.ts +18 -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/injectors.ts +4 -4
- 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__/count-tokens-forwarding.test.ts +98 -0
- 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/anthropic/client.ts +230 -175
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/call-site-routing.ts +10 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/gemini/client.ts +43 -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/ratelimit.ts +9 -0
- package/src/providers/retry.ts +62 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/types.ts +16 -0
- package/src/providers/usage-tracking.ts +7 -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 +227 -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 +71 -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 +126 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +35 -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 +383 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-routes.ts +40 -9
- 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 +366 -11
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +15 -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 +30 -6
- 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 +99 -2
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +64 -15
- 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 +10 -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/logs-db-path.ts +22 -0
- 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
|
@@ -204,7 +204,7 @@ export function revokeVerificationForChannel(
|
|
|
204
204
|
// revocation becomes a no-op (wrong reason or skipped entirely).
|
|
205
205
|
const contactResult = findContactChannel({
|
|
206
206
|
channelType: resolvedChannel,
|
|
207
|
-
|
|
207
|
+
address: bindingBeforeRevoke.guardianExternalUserId,
|
|
208
208
|
externalChatId: bindingBeforeRevoke.guardianDeliveryChatId,
|
|
209
209
|
});
|
|
210
210
|
|
|
@@ -331,7 +331,10 @@ export async function verifyTrustedContact(
|
|
|
331
331
|
const sessionResult = createOutboundSession({
|
|
332
332
|
channel: verificationChannel,
|
|
333
333
|
expectedChatId: channel.externalChatId,
|
|
334
|
-
expectedExternalUserId:
|
|
334
|
+
expectedExternalUserId:
|
|
335
|
+
channel.address !== channel.externalChatId
|
|
336
|
+
? channel.address
|
|
337
|
+
: undefined,
|
|
335
338
|
identityBindingStatus: "bound",
|
|
336
339
|
destinationAddress: effectiveDestination,
|
|
337
340
|
verificationPurpose: "trusted_contact",
|
|
@@ -404,22 +407,14 @@ export async function verifyTrustedContact(
|
|
|
404
407
|
|
|
405
408
|
// --- Slack verification ---
|
|
406
409
|
if (verificationChannel === "slack") {
|
|
407
|
-
const slackUserId = channel.
|
|
408
|
-
|
|
409
|
-
const hasIdentityBinding = Boolean(
|
|
410
|
-
channel.externalUserId || channel.externalChatId,
|
|
411
|
-
);
|
|
412
|
-
if (!hasIdentityBinding) {
|
|
413
|
-
return {
|
|
414
|
-
success: false,
|
|
415
|
-
error:
|
|
416
|
-
"Slack verification requires an externalUserId or externalChatId for identity binding",
|
|
417
|
-
};
|
|
418
|
-
}
|
|
410
|
+
const slackUserId = channel.address;
|
|
419
411
|
|
|
420
412
|
const sessionResult = createOutboundSession({
|
|
421
413
|
channel: verificationChannel,
|
|
422
|
-
expectedExternalUserId:
|
|
414
|
+
expectedExternalUserId:
|
|
415
|
+
channel.address !== channel.externalChatId
|
|
416
|
+
? channel.address
|
|
417
|
+
: undefined,
|
|
423
418
|
expectedChatId: channel.externalChatId ?? undefined,
|
|
424
419
|
identityBindingStatus: "bound",
|
|
425
420
|
destinationAddress: slackUserId,
|
|
@@ -560,7 +555,11 @@ export async function handleChannelVerificationSession(
|
|
|
560
555
|
const { to, text, subject, assistantId: aid } = result._pendingEmail;
|
|
561
556
|
deliverVerificationEmail(to, text, subject, aid);
|
|
562
557
|
}
|
|
563
|
-
const {
|
|
558
|
+
const {
|
|
559
|
+
_pendingSlackDm: _,
|
|
560
|
+
_pendingEmail: __,
|
|
561
|
+
...publicResult
|
|
562
|
+
} = result;
|
|
564
563
|
broadcastMessage({
|
|
565
564
|
type: "channel_verification_session_response",
|
|
566
565
|
...publicResult,
|
|
@@ -28,6 +28,9 @@ import { log as _log } from "./shared.js";
|
|
|
28
28
|
|
|
29
29
|
// -- Result type --
|
|
30
30
|
|
|
31
|
+
export const SlackThreadMode = z.enum(["mention_only", "mention_then_thread"]);
|
|
32
|
+
export type SlackThreadMode = z.infer<typeof SlackThreadMode>;
|
|
33
|
+
|
|
31
34
|
export const SlackChannelConfigResultSchema = z.object({
|
|
32
35
|
success: z.boolean(),
|
|
33
36
|
hasBotToken: z.boolean(),
|
|
@@ -39,6 +42,7 @@ export const SlackChannelConfigResultSchema = z.object({
|
|
|
39
42
|
teamUrl: z.string().optional(),
|
|
40
43
|
botUserId: z.string().optional(),
|
|
41
44
|
botUsername: z.string().optional(),
|
|
45
|
+
threadMode: SlackThreadMode,
|
|
42
46
|
error: z.string().optional(),
|
|
43
47
|
warning: z.string().optional(),
|
|
44
48
|
});
|
|
@@ -129,6 +133,8 @@ export async function getSlackChannelConfig(): Promise<SlackChannelConfigResult>
|
|
|
129
133
|
ensureUserTokenInjectionTemplates();
|
|
130
134
|
}
|
|
131
135
|
|
|
136
|
+
const { threadMode } = getConfig().slack;
|
|
137
|
+
|
|
132
138
|
return {
|
|
133
139
|
success: true,
|
|
134
140
|
hasBotToken,
|
|
@@ -140,6 +146,7 @@ export async function getSlackChannelConfig(): Promise<SlackChannelConfigResult>
|
|
|
140
146
|
...(teamUrl ? { teamUrl } : {}),
|
|
141
147
|
...(botUserId ? { botUserId } : {}),
|
|
142
148
|
...(botUsername ? { botUsername } : {}),
|
|
149
|
+
threadMode,
|
|
143
150
|
};
|
|
144
151
|
}
|
|
145
152
|
|
|
@@ -166,6 +173,7 @@ async function currentErrorSnapshot(
|
|
|
166
173
|
!!(errConn && errConn.status === "active") &&
|
|
167
174
|
errHasBotToken &&
|
|
168
175
|
errHasAppToken,
|
|
176
|
+
threadMode: getConfig().slack.threadMode,
|
|
169
177
|
error,
|
|
170
178
|
};
|
|
171
179
|
}
|
|
@@ -429,6 +437,7 @@ export async function setSlackChannelConfig(
|
|
|
429
437
|
hasUserToken,
|
|
430
438
|
connected: hasBotToken && hasAppToken,
|
|
431
439
|
...metadata,
|
|
440
|
+
threadMode: getConfig().slack.threadMode,
|
|
432
441
|
...(warning ? { warning } : {}),
|
|
433
442
|
};
|
|
434
443
|
}
|
|
@@ -440,9 +449,8 @@ export async function setSlackChannelConfig(
|
|
|
440
449
|
* the bot_token, app_token, oauth_connection row, and Slack config metadata
|
|
441
450
|
* untouched so the Socket Mode connection stays up. Returns a
|
|
442
451
|
* `SlackChannelConfigResult` reflecting the remaining state. A `not-found`
|
|
443
|
-
* delete outcome is reported as a failure to match the
|
|
444
|
-
*
|
|
445
|
-
* detection).
|
|
452
|
+
* delete outcome is reported as a failure to match the credential delete
|
|
453
|
+
* semantics (callers and automation rely on missing-credential detection).
|
|
446
454
|
*/
|
|
447
455
|
export async function clearSlackUserToken(): Promise<SlackChannelConfigResult> {
|
|
448
456
|
const result = await deleteSecureKeyAsync(
|
|
@@ -467,6 +475,7 @@ export async function clearSlackUserToken(): Promise<SlackChannelConfigResult> {
|
|
|
467
475
|
hasUserToken,
|
|
468
476
|
connected:
|
|
469
477
|
!!(conn && conn.status === "active") && hasBotToken && hasAppToken,
|
|
478
|
+
threadMode: getConfig().slack.threadMode,
|
|
470
479
|
error:
|
|
471
480
|
result === "not-found"
|
|
472
481
|
? "Slack user token not found in secure storage"
|
|
@@ -498,6 +507,7 @@ export async function clearSlackUserToken(): Promise<SlackChannelConfigResult> {
|
|
|
498
507
|
...(teamUrl ? { teamUrl } : {}),
|
|
499
508
|
...(botUserId ? { botUserId } : {}),
|
|
500
509
|
...(botUsername ? { botUsername } : {}),
|
|
510
|
+
threadMode: getConfig().slack.threadMode,
|
|
501
511
|
};
|
|
502
512
|
}
|
|
503
513
|
|
|
@@ -531,6 +541,7 @@ export async function clearSlackChannelConfig(): Promise<SlackChannelConfigResul
|
|
|
531
541
|
hasUserToken,
|
|
532
542
|
connected:
|
|
533
543
|
!!(conn && conn.status === "active") && hasBotToken && hasAppToken,
|
|
544
|
+
threadMode: getConfig().slack.threadMode,
|
|
534
545
|
error: "Failed to delete Slack channel credentials from secure storage",
|
|
535
546
|
};
|
|
536
547
|
}
|
|
@@ -557,5 +568,13 @@ export async function clearSlackChannelConfig(): Promise<SlackChannelConfigResul
|
|
|
557
568
|
hasAppToken: false,
|
|
558
569
|
hasUserToken: false,
|
|
559
570
|
connected: false,
|
|
571
|
+
threadMode: "mention_only",
|
|
560
572
|
};
|
|
561
573
|
}
|
|
574
|
+
|
|
575
|
+
export function patchSlackChannelConfig(threadMode: SlackThreadMode): void {
|
|
576
|
+
const raw = loadRawConfig();
|
|
577
|
+
setNestedValue(raw, "slack.threadMode", threadMode);
|
|
578
|
+
saveRawConfig(raw);
|
|
579
|
+
invalidateConfigCache();
|
|
580
|
+
}
|
|
@@ -3,14 +3,21 @@ import { v4 as uuid } from "uuid";
|
|
|
3
3
|
import { clearAll, getConversation } from "../../memory/conversation-crud.js";
|
|
4
4
|
import { resolveConversationId } from "../../memory/conversation-key-store.js";
|
|
5
5
|
import { broadcastMessage } from "../../runtime/assistant-event-hub.js";
|
|
6
|
+
import { resolveCapabilities } from "../../runtime/capabilities.js";
|
|
6
7
|
import { getSubagentManager } from "../../subagent/index.js";
|
|
7
8
|
import { createAbortReason } from "../../util/abort-reasons.js";
|
|
9
|
+
import { UserError } from "../../util/errors.js";
|
|
8
10
|
import { truncate } from "../../util/truncate.js";
|
|
9
11
|
import { regenerate } from "../conversation-history.js";
|
|
12
|
+
import {
|
|
13
|
+
buildSlashContext,
|
|
14
|
+
formatCleanResult,
|
|
15
|
+
} from "../conversation-process.js";
|
|
10
16
|
import {
|
|
11
17
|
conversationEntries,
|
|
12
18
|
findConversation,
|
|
13
19
|
} from "../conversation-registry.js";
|
|
20
|
+
import { resolveSlash } from "../conversation-slash.js";
|
|
14
21
|
import {
|
|
15
22
|
clearAllActiveConversations,
|
|
16
23
|
getOrCreateConversation,
|
|
@@ -18,6 +25,7 @@ import {
|
|
|
18
25
|
} from "../conversation-store.js";
|
|
19
26
|
import type { ConfirmationResponse } from "../message-protocol.js";
|
|
20
27
|
import { normalizeConversationType } from "../message-protocol.js";
|
|
28
|
+
import { INTERNAL_GUARDIAN_TRUST_CONTEXT } from "../trust-context.js";
|
|
21
29
|
import { log } from "./shared.js";
|
|
22
30
|
|
|
23
31
|
export function handleConfirmationResponse(msg: ConfirmationResponse): void {
|
|
@@ -98,6 +106,12 @@ export function cancelGeneration(conversationId: string): boolean {
|
|
|
98
106
|
// being cancelled, so enqueuing synthetic messages would trigger
|
|
99
107
|
// unwanted model activity after the user pressed stop.
|
|
100
108
|
getSubagentManager().abortAllForParent(conversationId);
|
|
109
|
+
// The processing flag is cleared by the in-flight turn's `finally`, not here.
|
|
110
|
+
// Abort propagates into the provider call and tool execution (and is backed
|
|
111
|
+
// by the agent loop's abort watchdog), so the turn reaches its `finally`
|
|
112
|
+
// within a bounded time and tears down its own state there — which publishes
|
|
113
|
+
// the metadata sync invalidation that drives clients to the authoritative
|
|
114
|
+
// idle state.
|
|
101
115
|
return true;
|
|
102
116
|
}
|
|
103
117
|
|
|
@@ -118,6 +132,99 @@ export async function undoLastMessage(
|
|
|
118
132
|
const removedCount = conversation.undo();
|
|
119
133
|
return { removedCount };
|
|
120
134
|
}
|
|
135
|
+
|
|
136
|
+
export interface MetaSlashCommandResult {
|
|
137
|
+
kind: "clean" | "info";
|
|
138
|
+
/** User-facing text to render (clean stats card or info listing). */
|
|
139
|
+
text: string;
|
|
140
|
+
/** Present for `/clean`: the post-strip context-window usage. */
|
|
141
|
+
contextUsage?: {
|
|
142
|
+
tokens: number;
|
|
143
|
+
maxTokens: number | null;
|
|
144
|
+
fillRatio: number | null;
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Resolve a local meta slash command (`/clean`, `/status`, `/commands`,
|
|
150
|
+
* `/models`) for a conversation without running a turn: no user/assistant
|
|
151
|
+
* messages are persisted and no streaming/turn events are emitted. `/clean`
|
|
152
|
+
* additionally strips runtime injections via `forceClean`.
|
|
153
|
+
*
|
|
154
|
+
* Returns null if the conversation cannot be resolved. Throws `UserError` for
|
|
155
|
+
* commands that are not local meta commands (`/compact`, passthrough) — those
|
|
156
|
+
* must be sent as a normal message so they run a real turn.
|
|
157
|
+
*/
|
|
158
|
+
export async function resolveMetaSlashCommand(
|
|
159
|
+
conversationId: string,
|
|
160
|
+
command: string,
|
|
161
|
+
): Promise<MetaSlashCommandResult | null> {
|
|
162
|
+
const resolvedId = resolveConversationId(conversationId);
|
|
163
|
+
if (!resolvedId) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const conversation = await getOrCreateConversation(resolvedId);
|
|
167
|
+
touchConversation(resolvedId);
|
|
168
|
+
|
|
169
|
+
// Meta commands reload (and, for `/clean`, strip) the in-memory history
|
|
170
|
+
// array. Running that against an in-flight turn would corrupt the messages
|
|
171
|
+
// the active agent loop is iterating over, and mutating trustContext would
|
|
172
|
+
// elevate that turn's actor trust to guardian for subsequent tool calls.
|
|
173
|
+
if (conversation.isProcessing()) {
|
|
174
|
+
throw new UserError(
|
|
175
|
+
`\`${command.trim()}\` cannot run while the assistant is responding.`,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Owner self-maintenance operates on the full (guardian) history. Without a
|
|
180
|
+
// trusted context, `loadFromDb` filters to non-guardian provenance — so a
|
|
181
|
+
// guardian-authored conversation would report 0 preserved / 0 messages.
|
|
182
|
+
// Temporarily apply the guardian context for hydration and restore it
|
|
183
|
+
// afterward so the elevated class never leaks into a later turn's snapshot.
|
|
184
|
+
const priorTrustContext = conversation.trustContext;
|
|
185
|
+
if (!resolveCapabilities(priorTrustContext?.trustClass).canAccessMemory) {
|
|
186
|
+
conversation.setTrustContext(INTERNAL_GUARDIAN_TRUST_CONTEXT);
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
await conversation.ensureActorScopedHistory();
|
|
190
|
+
|
|
191
|
+
const slashResult = await resolveSlash(
|
|
192
|
+
command,
|
|
193
|
+
buildSlashContext(command, conversation),
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
if (slashResult.kind === "clean") {
|
|
197
|
+
const result = await conversation.forceClean();
|
|
198
|
+
return {
|
|
199
|
+
kind: "clean",
|
|
200
|
+
text: formatCleanResult(result),
|
|
201
|
+
contextUsage: {
|
|
202
|
+
tokens: result.estimatedInputTokens,
|
|
203
|
+
maxTokens: result.maxInputTokens,
|
|
204
|
+
fillRatio:
|
|
205
|
+
result.maxInputTokens > 0
|
|
206
|
+
? result.estimatedInputTokens / result.maxInputTokens
|
|
207
|
+
: null,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (slashResult.kind === "unknown") {
|
|
213
|
+
return { kind: "info", text: slashResult.message };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// `compact` / `passthrough` are real turns, not local meta commands.
|
|
217
|
+
throw new UserError(`\`${command.trim()}\` is not a local meta command.`);
|
|
218
|
+
} finally {
|
|
219
|
+
// Only undo the temporary guardian context this handler installed. If a
|
|
220
|
+
// new turn started at an `await` boundary and legitimately updated
|
|
221
|
+
// trustContext, the reference will differ and we leave it alone.
|
|
222
|
+
if (conversation.trustContext === INTERNAL_GUARDIAN_TRUST_CONTEXT) {
|
|
223
|
+
conversation.setTrustContext(priorTrustContext ?? null);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
121
228
|
/**
|
|
122
229
|
* Regenerate the last assistant response for a conversation. The caller provides
|
|
123
230
|
* a `sendEvent` callback for delivering streaming events via HTTP/SSE.
|
|
@@ -9,6 +9,7 @@ import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
|
9
9
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
10
10
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
11
11
|
import { getLogger } from "../util/logger.js";
|
|
12
|
+
import { sleep } from "../util/retry.js";
|
|
12
13
|
import type { HostBrowserRequest } from "./message-types/host-browser.js";
|
|
13
14
|
|
|
14
15
|
/** Distributive omit that preserves union variant fields. */
|
|
@@ -24,6 +25,16 @@ export type HostBrowserInput = DistributiveOmit<
|
|
|
24
25
|
|
|
25
26
|
const log = getLogger("host-browser-proxy");
|
|
26
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Grace window for a flapping extension SSE connection. The Chrome
|
|
30
|
+
* extension's stream can briefly drop and reconnect (MV3 service-worker
|
|
31
|
+
* churn); without a short wait, a dispatch landing in a "down" blip
|
|
32
|
+
* hard-fails even though the extension is effectively connected. Well
|
|
33
|
+
* under the request-layer timeout (default 30s).
|
|
34
|
+
*/
|
|
35
|
+
const EXTENSION_RECONNECT_GRACE_MS = 3_000;
|
|
36
|
+
const EXTENSION_RECONNECT_POLL_MS = 250;
|
|
37
|
+
|
|
27
38
|
/**
|
|
28
39
|
* Extension-only pseudo-CDP methods (Vellum.listTabs, Vellum.selectTab,
|
|
29
40
|
* Vellum.closeTab, Vellum.createTab, Vellum.findTab, Vellum.attach,
|
|
@@ -196,6 +207,36 @@ export class HostBrowserProxy {
|
|
|
196
207
|
);
|
|
197
208
|
}
|
|
198
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Poll until the extension client that dispatch will route to is
|
|
212
|
+
* connected, or `timeoutMs` elapses. Absorbs brief SSE reconnect blips
|
|
213
|
+
* so extension-pinned dispatch doesn't hard-fail on a momentary gap.
|
|
214
|
+
*
|
|
215
|
+
* When `targetClientId` is supplied, waits for that *exact* client —
|
|
216
|
+
* `request()` resolves the target by id, so waiting for any sibling
|
|
217
|
+
* extension (multi-install setups) would return early and still fail.
|
|
218
|
+
* Otherwise waits for any extension owned by the actor, matching the
|
|
219
|
+
* auto-resolution preference. Returns the final availability; callers
|
|
220
|
+
* proceed to dispatch regardless (which still surfaces the typed "no
|
|
221
|
+
* Chrome Extension connected" error if absent).
|
|
222
|
+
*/
|
|
223
|
+
async waitForExtensionClient(
|
|
224
|
+
sourceActorPrincipalId?: string,
|
|
225
|
+
targetClientId?: string,
|
|
226
|
+
timeoutMs = EXTENSION_RECONNECT_GRACE_MS,
|
|
227
|
+
): Promise<boolean> {
|
|
228
|
+
const connected = () =>
|
|
229
|
+
targetClientId != null
|
|
230
|
+
? assistantEventHub.getClientById(targetClientId) !== undefined
|
|
231
|
+
: this.hasExtensionClient(sourceActorPrincipalId);
|
|
232
|
+
const deadline = Date.now() + timeoutMs;
|
|
233
|
+
for (;;) {
|
|
234
|
+
if (connected()) return true;
|
|
235
|
+
if (Date.now() >= deadline) return false;
|
|
236
|
+
await sleep(EXTENSION_RECONNECT_POLL_MS);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
199
240
|
/**
|
|
200
241
|
* Send a host_browser request to the connected extension/macOS bridge.
|
|
201
242
|
*
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
import { loadConfig, mergeDefaultWorkspaceConfig } from "../config/loader.js";
|
|
21
21
|
import type { AssistantConfig } from "../config/schema.js";
|
|
22
22
|
import { seedInferenceProfiles } from "../config/seed-inference-profiles.js";
|
|
23
|
+
import { reconcileFlagGatedProfiles } from "../config/sync-gated-profiles.js";
|
|
23
24
|
import type { CesClient } from "../credential-execution/client.js";
|
|
24
25
|
import { createCesClient } from "../credential-execution/client.js";
|
|
25
26
|
import { refreshManagedConnectionCache } from "../credential-execution/managed-catalog.js";
|
|
@@ -60,6 +61,10 @@ import { sweepConceptPageFrontmatter } from "../memory/v2/frontmatter-sweep.js";
|
|
|
60
61
|
import { emitNotificationSignal } from "../notifications/emit-signal.js";
|
|
61
62
|
import { backfillManualTokenConnections } from "../oauth/manual-token-connection.js";
|
|
62
63
|
import { seedOAuthProviders } from "../oauth/seed-providers.js";
|
|
64
|
+
import {
|
|
65
|
+
startConsentRefresh,
|
|
66
|
+
stopConsentRefresh,
|
|
67
|
+
} from "../platform/consent-cache.js";
|
|
63
68
|
import { ensurePromptFiles } from "../prompts/system-prompt.js";
|
|
64
69
|
import { runProviderConnectionsBackfill } from "../providers/inference/backfill.js";
|
|
65
70
|
import { resolveManagedProxyContext } from "../providers/platform-proxy/context.js";
|
|
@@ -71,7 +76,10 @@ import {
|
|
|
71
76
|
import { RuntimeHttpServer } from "../runtime/http-server.js";
|
|
72
77
|
import { recoverInterruptedImport } from "../runtime/migrations/vbundle-streaming-importer.js";
|
|
73
78
|
import { registerSecretsDeps } from "../runtime/routes/secrets-deps.js";
|
|
74
|
-
import {
|
|
79
|
+
import {
|
|
80
|
+
publishConfigChanged,
|
|
81
|
+
publishConversationListChanged,
|
|
82
|
+
} from "../runtime/sync/resource-sync-events.js";
|
|
75
83
|
import { recoverStaleSchedules } from "../schedule/schedule-recovery.js";
|
|
76
84
|
import { startScheduler } from "../schedule/scheduler.js";
|
|
77
85
|
import {
|
|
@@ -130,6 +138,7 @@ import {
|
|
|
130
138
|
} from "./providers-setup.js";
|
|
131
139
|
import { DaemonServer } from "./server.js";
|
|
132
140
|
import { installShutdownHandlers } from "./shutdown-handlers.js";
|
|
141
|
+
import { registerShutdownHook } from "./shutdown-registry.js";
|
|
133
142
|
import { refreshSkillCapabilityMemories } from "./skill-memory-refresh.js";
|
|
134
143
|
|
|
135
144
|
const log = getLogger("lifecycle");
|
|
@@ -284,9 +293,10 @@ export async function runDaemon(): Promise<void> {
|
|
|
284
293
|
log.info({ version: APP_VERSION }, "Daemon starting");
|
|
285
294
|
|
|
286
295
|
try {
|
|
287
|
-
// Initialize crash reporting eagerly so
|
|
288
|
-
//
|
|
289
|
-
//
|
|
296
|
+
// Initialize crash reporting eagerly so the Sentry client is ready before
|
|
297
|
+
// early startup failures occur. Events are dropped (beforeSend) until the
|
|
298
|
+
// consent gate below confirms share_diagnostics opt-in; dev mode and the
|
|
299
|
+
// legacy local opt-out hard-disable via closeSentry().
|
|
290
300
|
initSentry();
|
|
291
301
|
|
|
292
302
|
ensureDataDir();
|
|
@@ -365,8 +375,23 @@ export async function runDaemon(): Promise<void> {
|
|
|
365
375
|
// this fetch completes, so without this follow-up sync a flag-enabled
|
|
366
376
|
// assistant would not expose the gated tools until a restart (which can lose
|
|
367
377
|
// the same race). Enable-direction only; chained so it sees the fresh cache.
|
|
378
|
+
// Then reconcile flag-gated managed profiles (OS Beta): `seedInferenceProfiles()`
|
|
379
|
+
// runs synchronously earlier in boot before flags are available, so this lands
|
|
380
|
+
// the profile on the same boot once the flag cache is populated. When this
|
|
381
|
+
// reconcile is the call that mutates config (it raced ahead of the gateway
|
|
382
|
+
// flag listener), publish the config invalidation so any client that already
|
|
383
|
+
// fetched `GET /v1/config` refreshes its profile picker.
|
|
384
|
+
// Profiles are reconciled only when flags actually loaded from the gateway:
|
|
385
|
+
// a failed fetch leaves the cache unset and resolves `os-beta` to its
|
|
386
|
+
// registry default `false`, which would remove the user's profile and reset
|
|
387
|
+
// their selection. Tool sync tolerates the default and stays unconditional.
|
|
368
388
|
void initFeatureFlagOverrides()
|
|
369
|
-
.then(() =>
|
|
389
|
+
.then(async (loaded) => {
|
|
390
|
+
await syncFlagGatedTools();
|
|
391
|
+
if (loaded && reconcileFlagGatedProfiles()) {
|
|
392
|
+
publishConfigChanged();
|
|
393
|
+
}
|
|
394
|
+
})
|
|
370
395
|
.catch((err) => log.warn({ err }, "Background feature flag init failed"));
|
|
371
396
|
|
|
372
397
|
startGatewayFlagListener();
|
|
@@ -636,22 +661,27 @@ export async function runDaemon(): Promise<void> {
|
|
|
636
661
|
});
|
|
637
662
|
}
|
|
638
663
|
|
|
639
|
-
// Privacy gating: Sentry crash/error reporting
|
|
640
|
-
//
|
|
641
|
-
// flush. Both are disabled in dev mode.
|
|
642
|
-
//
|
|
664
|
+
// Privacy gating: Sentry crash/error reporting follows the platform owner's
|
|
665
|
+
// share_diagnostics consent; the usage telemetry reporter re-checks
|
|
666
|
+
// share_analytics on every flush. Both are disabled in dev mode. Sentry was
|
|
667
|
+
// initialized early, but beforeSend re-reads getCachedShareDiagnostics() on
|
|
668
|
+
// every event, so it drops events until consent confirms opt-in and honors a
|
|
669
|
+
// later revocation within one refresh cycle (the cache is refreshed by
|
|
670
|
+
// startConsentRefresh() below, mirroring the share_analytics posture).
|
|
643
671
|
const isDevMode = process.env.VELLUM_DEV === "1";
|
|
644
|
-
|
|
645
|
-
|
|
672
|
+
if (isDevMode || config.legacyDiagnosticsOptOut === true) {
|
|
673
|
+
// Dev mode and a preserved legacy local opt-out both disable Sentry
|
|
674
|
+
// unconditionally, without waiting on platform consent.
|
|
646
675
|
await closeSentry();
|
|
647
676
|
}
|
|
648
677
|
|
|
649
678
|
// Construct and start the reporter even when usage collection is disabled:
|
|
650
|
-
// flush() re-checks
|
|
651
|
-
// nothing but advances all watermarks (including the
|
|
652
|
-
// stop()). New opted-out tool_invocations rows are already
|
|
653
|
-
// construction — the audit listener persists NULL telemetry
|
|
654
|
-
// them, which the tool_executed projection filters out — so the
|
|
679
|
+
// flush() re-checks the platform share_analytics consent each cycle and,
|
|
680
|
+
// when opted out, sends nothing but advances all watermarks (including the
|
|
681
|
+
// final flush in stop()). New opted-out tool_invocations rows are already
|
|
682
|
+
// unreportable by construction — the audit listener persists NULL telemetry
|
|
683
|
+
// columns for them, which the tool_executed projection filters out — so the
|
|
684
|
+
// opted-out
|
|
655
685
|
// flushes are defense in depth there (covering rows recorded under builds
|
|
656
686
|
// that predate that write-time gate) and remain the primary guard for the
|
|
657
687
|
// always-on tables without a write-time gate (llm_usage, turn events).
|
|
@@ -665,12 +695,17 @@ export async function runDaemon(): Promise<void> {
|
|
|
665
695
|
telemetryReporter = new UsageTelemetryReporter();
|
|
666
696
|
setUsageTelemetryReporter(telemetryReporter);
|
|
667
697
|
telemetryReporter.start();
|
|
668
|
-
log.info(
|
|
669
|
-
{ collectUsageData: config.collectUsageData },
|
|
670
|
-
"Usage telemetry reporter started",
|
|
671
|
-
);
|
|
698
|
+
log.info("Usage telemetry reporter started");
|
|
672
699
|
}
|
|
673
700
|
|
|
701
|
+
// Refresh the consent cache regardless of dev mode so record-time telemetry
|
|
702
|
+
// writes (gated on getCachedShareAnalytics()) work in dev too. The reporter
|
|
703
|
+
// flush stays dev-gated above, so dev still never sends telemetry to the
|
|
704
|
+
// platform. Fire-and-forget: startConsentRefresh() runs an immediate
|
|
705
|
+
// non-blocking refresh, so the startup hot path is never blocked.
|
|
706
|
+
startConsentRefresh();
|
|
707
|
+
registerShutdownHook("consent-cache", () => stopConsentRefresh());
|
|
708
|
+
|
|
674
709
|
// CES lifecycle — kick off early so CES handshake runs concurrently with
|
|
675
710
|
// provider/tool initialization. The CES sidecar accepts exactly one
|
|
676
711
|
// bootstrap connection, so startup must happen at the process level.
|
|
@@ -1281,13 +1316,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
1281
1316
|
log.warn({ err }, "Assistant symlink installation failed — continuing");
|
|
1282
1317
|
}
|
|
1283
1318
|
|
|
1284
|
-
// Seed preloaded apps (personal landing page) in background (non-blocking).
|
|
1285
|
-
void import("../memory/preloaded-apps.js")
|
|
1286
|
-
.then(({ seedPreloadedApps }) => seedPreloadedApps(config))
|
|
1287
|
-
.catch((err) =>
|
|
1288
|
-
log.warn({ err }, "Preloaded app seeding failed — continuing"),
|
|
1289
|
-
);
|
|
1290
|
-
|
|
1291
1319
|
// Download embedding runtime in background (non-blocking).
|
|
1292
1320
|
// If download fails, local embeddings gracefully fall back to cloud backends.
|
|
1293
1321
|
void (async () => {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for `maybeReseedCapabilitiesAfterManagedCredential` in
|
|
3
|
+
* `memory-v2-startup.ts`.
|
|
4
|
+
*
|
|
5
|
+
* The secrets route calls this when a managed-proxy credential lands, to close
|
|
6
|
+
* the first-boot race where the daemon's startup capability seed (skills + CLI
|
|
7
|
+
* commands) runs before the platform provisions the managed embedding
|
|
8
|
+
* credential — the seed's embed throws and the synthetic capability pages never
|
|
9
|
+
* reach the page index. The reseed must fire only when v2 memory is enabled AND
|
|
10
|
+
* the managed-proxy prerequisites are now satisfied, so self-hosted / BYOK
|
|
11
|
+
* assistants (no managed proxy) are never made to run a doomed embed. When v3 is
|
|
12
|
+
* live it then enqueues a `memory_v3_maintain` job so v3 picks up the capability
|
|
13
|
+
* pages immediately instead of waiting out the 6h maintain backstop.
|
|
14
|
+
*
|
|
15
|
+
* Dynamic-imported collaborators are mocked at module scope; `bun:test`
|
|
16
|
+
* isolates `mock.module` per test file.
|
|
17
|
+
*/
|
|
18
|
+
import { afterEach, describe, expect, mock, test } from "bun:test";
|
|
19
|
+
|
|
20
|
+
import { makeMockLogger } from "../__tests__/helpers/mock-logger.js";
|
|
21
|
+
import type { AssistantConfig } from "../config/schema.js";
|
|
22
|
+
|
|
23
|
+
const proxyState = { prereqs: true };
|
|
24
|
+
const v3State = { live: true };
|
|
25
|
+
const seedSkill = mock(async () => {});
|
|
26
|
+
const seedCli = mock(async () => {});
|
|
27
|
+
const enqueueJob = mock(
|
|
28
|
+
(_type: string, _payload: Record<string, unknown>) => 1,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
mock.module("../util/logger.js", () => ({
|
|
32
|
+
getLogger: () => makeMockLogger(),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
mock.module("../providers/platform-proxy/context.js", () => ({
|
|
36
|
+
hasManagedProxyPrereqs: async () => proxyState.prereqs,
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
mock.module("../config/memory-v3-gate.js", () => ({
|
|
40
|
+
isMemoryV3Live: () => v3State.live,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
mock.module("../memory/jobs-store.js", () => ({
|
|
44
|
+
enqueueMemoryJob: enqueueJob,
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
mock.module("../memory/v2/skill-store.js", () => ({
|
|
48
|
+
seedV2SkillEntries: seedSkill,
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
mock.module("../memory/v2/cli-command-store.js", () => ({
|
|
52
|
+
seedV2CliCommandEntries: seedCli,
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
const { maybeReseedCapabilitiesAfterManagedCredential } =
|
|
56
|
+
await import("./memory-v2-startup.js");
|
|
57
|
+
|
|
58
|
+
function configWithV2(enabled: boolean): AssistantConfig {
|
|
59
|
+
return { memory: { v2: { enabled } } } as unknown as AssistantConfig;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
seedSkill.mockClear();
|
|
64
|
+
seedCli.mockClear();
|
|
65
|
+
enqueueJob.mockClear();
|
|
66
|
+
proxyState.prereqs = true;
|
|
67
|
+
v3State.live = true;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("maybeReseedCapabilitiesAfterManagedCredential", () => {
|
|
71
|
+
test("reseeds both skill and CLI entries when v2 is enabled and managed-proxy prereqs are satisfied", async () => {
|
|
72
|
+
proxyState.prereqs = true;
|
|
73
|
+
|
|
74
|
+
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true));
|
|
75
|
+
|
|
76
|
+
expect(seedSkill).toHaveBeenCalledTimes(1);
|
|
77
|
+
expect(seedCli).toHaveBeenCalledTimes(1);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("enqueues a v3 maintain pass after reseeding when v3 is live", async () => {
|
|
81
|
+
proxyState.prereqs = true;
|
|
82
|
+
v3State.live = true;
|
|
83
|
+
|
|
84
|
+
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true));
|
|
85
|
+
|
|
86
|
+
expect(enqueueJob).toHaveBeenCalledTimes(1);
|
|
87
|
+
expect(enqueueJob).toHaveBeenCalledWith("memory_v3_maintain", {});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("reseeds but does not enqueue a v3 maintain pass when v3 is not live", async () => {
|
|
91
|
+
proxyState.prereqs = true;
|
|
92
|
+
v3State.live = false;
|
|
93
|
+
|
|
94
|
+
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true));
|
|
95
|
+
|
|
96
|
+
expect(seedSkill).toHaveBeenCalledTimes(1);
|
|
97
|
+
expect(seedCli).toHaveBeenCalledTimes(1);
|
|
98
|
+
expect(enqueueJob).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("no-op when v2 memory is disabled", async () => {
|
|
102
|
+
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(false));
|
|
103
|
+
|
|
104
|
+
expect(seedSkill).not.toHaveBeenCalled();
|
|
105
|
+
expect(seedCli).not.toHaveBeenCalled();
|
|
106
|
+
expect(enqueueJob).not.toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("no-op for non-managed assistants (managed-proxy prereqs not satisfied)", async () => {
|
|
110
|
+
proxyState.prereqs = false;
|
|
111
|
+
|
|
112
|
+
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true));
|
|
113
|
+
|
|
114
|
+
expect(seedSkill).not.toHaveBeenCalled();
|
|
115
|
+
expect(seedCli).not.toHaveBeenCalled();
|
|
116
|
+
expect(enqueueJob).not.toHaveBeenCalled();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("swallows a seed failure and still reseeds the other catalog", async () => {
|
|
120
|
+
proxyState.prereqs = true;
|
|
121
|
+
seedSkill.mockImplementationOnce(async () => {
|
|
122
|
+
throw new Error('Embedding backend "gemini" is not configured');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Must not reject — the helper contains each seed's failure so a doomed
|
|
126
|
+
// embed never propagates back to the credential-store caller.
|
|
127
|
+
await maybeReseedCapabilitiesAfterManagedCredential(configWithV2(true));
|
|
128
|
+
|
|
129
|
+
expect(seedCli).toHaveBeenCalledTimes(1);
|
|
130
|
+
});
|
|
131
|
+
});
|