@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
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
//
|
|
5
5
|
// Small focused module that holds the gating + dispatch logic for v2-specific
|
|
6
|
-
// startup work invoked from `lifecycle.ts
|
|
6
|
+
// startup work invoked from `lifecycle.ts` (and, for the post-credential
|
|
7
|
+
// capability reseed, from the secrets route). Lives in its own file so the unit
|
|
7
8
|
// test for the gate does not have to mount the entire lifecycle import graph.
|
|
8
9
|
|
|
9
10
|
import type { AssistantConfig } from "../config/schema.js";
|
|
@@ -48,6 +49,104 @@ export function maybeSeedMemoryV2CliCommands(config: AssistantConfig): void {
|
|
|
48
49
|
.catch((err) => log.warn({ err }, "Failed to seed v2 CLI-command entries"));
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Re-seed the v2 skill and CLI-command capability entries once a managed-proxy
|
|
54
|
+
* credential lands, closing the first-boot race where the daemon's startup seed
|
|
55
|
+
* runs before the platform has provisioned the managed embedding credential.
|
|
56
|
+
*
|
|
57
|
+
* On a brand-new managed assistant the memory worker fires the startup seed
|
|
58
|
+
* (`maybeSeedMemoryV2Skills` / `maybeSeedMemoryV2CliCommands`) seconds after
|
|
59
|
+
* boot, but the platform pushes `vellum:assistant_api_key` (the credential the
|
|
60
|
+
* managed Gemini embedding backend needs) tens of seconds later. The seed's
|
|
61
|
+
* `embedWithBackend` call throws `EmbeddingBackendUnavailableError` before the
|
|
62
|
+
* skill/CLI `entries` cache is replaced, so `listSkillEntries()` /
|
|
63
|
+
* `listCliCommandEntries()` stay empty and the synthetic `skills/<id>` and
|
|
64
|
+
* `cli-commands/<name>` rows never reach the page index — leaving the v3 needle
|
|
65
|
+
* finder lane and always-candidate skill pinning with nothing to surface until
|
|
66
|
+
* the next daemon restart. Re-running the seed when the credential arrives
|
|
67
|
+
* restores the capability pages without a restart.
|
|
68
|
+
*
|
|
69
|
+
* Gated on the managed-proxy prerequisites now being satisfied (both the
|
|
70
|
+
* platform base URL and the assistant API key present) so a non-managed
|
|
71
|
+
* credential write — or a partial update that has not yet completed the pair —
|
|
72
|
+
* does not kick a doomed embed. Idempotent: `seedV2SkillEntries` /
|
|
73
|
+
* `seedV2CliCommandEntries` atomically replace their caches, so a redundant
|
|
74
|
+
* reseed (the startup seed already succeeded) is cheap and harmless. The two
|
|
75
|
+
* catalogs are independent, so they reseed in parallel. Callers invoke this
|
|
76
|
+
* detached (`void`) — it must not block the credential-store response.
|
|
77
|
+
*
|
|
78
|
+
* Reseeding alone only repopulates the shared page index — v3 reads its
|
|
79
|
+
* synthetic capability rows from the v2 stores, but its memoized lanes and its
|
|
80
|
+
* `memory_v3_sections` dense store refresh only on the v3 maintain pass (6-hour
|
|
81
|
+
* backstop). So when v3 is live, enqueue a `memory_v3_maintain` job after the
|
|
82
|
+
* reseed: its capability-reconcile stage embeds the freshly-seeded rows into the
|
|
83
|
+
* dense store and its lane-invalidation stage forces a rebuild against the now-
|
|
84
|
+
* populated index, so v3 surfaces the skill/CLI pages within seconds instead of
|
|
85
|
+
* waiting out the backstop.
|
|
86
|
+
*/
|
|
87
|
+
export async function maybeReseedCapabilitiesAfterManagedCredential(
|
|
88
|
+
config: AssistantConfig,
|
|
89
|
+
): Promise<void> {
|
|
90
|
+
if (!config.memory.v2.enabled) return;
|
|
91
|
+
|
|
92
|
+
const { hasManagedProxyPrereqs } =
|
|
93
|
+
await import("../providers/platform-proxy/context.js");
|
|
94
|
+
if (!(await hasManagedProxyPrereqs())) return;
|
|
95
|
+
|
|
96
|
+
// Skills and CLI commands are independent catalogs sharing the unified
|
|
97
|
+
// collection — reseed in parallel, each contained so one catalog's embed
|
|
98
|
+
// failure does not abort the other or reject the detached caller.
|
|
99
|
+
const catalogs: ReadonlyArray<[label: string, seed: () => Promise<void>]> = [
|
|
100
|
+
[
|
|
101
|
+
"skill",
|
|
102
|
+
async () => {
|
|
103
|
+
const { seedV2SkillEntries } =
|
|
104
|
+
await import("../memory/v2/skill-store.js");
|
|
105
|
+
await seedV2SkillEntries({ throwOnError: true });
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
[
|
|
109
|
+
"CLI-command",
|
|
110
|
+
async () => {
|
|
111
|
+
const { seedV2CliCommandEntries } =
|
|
112
|
+
await import("../memory/v2/cli-command-store.js");
|
|
113
|
+
await seedV2CliCommandEntries({ throwOnError: true });
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
await Promise.all(
|
|
119
|
+
catalogs.map(async ([label, seed]) => {
|
|
120
|
+
try {
|
|
121
|
+
await seed();
|
|
122
|
+
log.info(
|
|
123
|
+
`Memory v2 ${label} entries seeded after managed proxy credential update`,
|
|
124
|
+
);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
log.warn(
|
|
127
|
+
{ err },
|
|
128
|
+
`Failed to seed v2 ${label} entries after managed proxy credential update`,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// The stores (and the page index) are now populated; when v3 is live, kick a
|
|
135
|
+
// maintain pass so it embeds the capability rows into `memory_v3_sections` and
|
|
136
|
+
// invalidates its lanes immediately rather than waiting out the 6h backstop.
|
|
137
|
+
const { isMemoryV3Live } = await import("../config/memory-v3-gate.js");
|
|
138
|
+
if (!isMemoryV3Live(config)) return;
|
|
139
|
+
try {
|
|
140
|
+
const { enqueueMemoryJob } = await import("../memory/jobs-store.js");
|
|
141
|
+
enqueueMemoryJob("memory_v3_maintain", {});
|
|
142
|
+
} catch (err) {
|
|
143
|
+
log.warn(
|
|
144
|
+
{ err },
|
|
145
|
+
"Failed to enqueue memory_v3_maintain after managed proxy credential update",
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
51
150
|
/**
|
|
52
151
|
* Build the v2 BM25 corpus stats (per-token document frequencies + avg doc
|
|
53
152
|
* length), then re-seed the v2 skill entries so any skills written during
|
|
@@ -26,6 +26,7 @@ export function parseProvenanceTrustClass(
|
|
|
26
26
|
if (
|
|
27
27
|
trustClass === "guardian" ||
|
|
28
28
|
trustClass === "trusted_contact" ||
|
|
29
|
+
trustClass === "unverified_contact" ||
|
|
29
30
|
trustClass === "unknown"
|
|
30
31
|
) {
|
|
31
32
|
return trustClass;
|
|
@@ -43,6 +44,7 @@ export function filterMessagesForUntrustedActor(
|
|
|
43
44
|
const provenanceTrustClass = parseProvenanceTrustClass(m.metadata);
|
|
44
45
|
return (
|
|
45
46
|
provenanceTrustClass === "trusted_contact" ||
|
|
47
|
+
provenanceTrustClass === "unverified_contact" ||
|
|
46
48
|
provenanceTrustClass === "unknown"
|
|
47
49
|
);
|
|
48
50
|
});
|
|
@@ -462,9 +462,9 @@ export interface ContextCompacted {
|
|
|
462
462
|
* - `summaryCharCount`: length of the produced summary text.
|
|
463
463
|
* - `summaryHeaderCount`: number of `## ` section headers in the summary.
|
|
464
464
|
* - `summaryHadMemoryEcho`: `true` if the summary contains any runtime
|
|
465
|
-
* injection tag (e.g. `<memory`, `<turn_context>`, `<workspace>`).
|
|
466
|
-
*
|
|
467
|
-
*
|
|
465
|
+
* injection tag (e.g. `<memory`, `<turn_context>`, `<workspace>`). The
|
|
466
|
+
* durable summary should be clean prose, so `true` flags an echoed or
|
|
467
|
+
* invented tag worth investigating.
|
|
468
468
|
*/
|
|
469
469
|
summaryCharCount?: number;
|
|
470
470
|
summaryHeaderCount?: number;
|
|
@@ -10,7 +10,6 @@ export { type SyncChangedEvent, SyncChangedEventSchema };
|
|
|
10
10
|
export const SYNC_TAGS = {
|
|
11
11
|
assistantAvatar: "assistant:self:avatar",
|
|
12
12
|
assistantIdentity: "assistant:self:identity",
|
|
13
|
-
assistantIdentityIntro: "assistant:self:identity-intro",
|
|
14
13
|
assistantConfig: "assistant:self:config",
|
|
15
14
|
assistantSounds: "assistant:self:sounds",
|
|
16
15
|
assistantSchedules: "assistant:self:schedules",
|
|
@@ -9,7 +9,11 @@ export type WebSearchProviderId =
|
|
|
9
9
|
| "anthropic-native"
|
|
10
10
|
| "brave"
|
|
11
11
|
| "perplexity"
|
|
12
|
-
| "tavily"
|
|
12
|
+
| "tavily"
|
|
13
|
+
| "firecrawl";
|
|
14
|
+
|
|
15
|
+
/** Provider that backed a `web_fetch` call. `default` is the built-in fetcher. */
|
|
16
|
+
export type WebFetchProviderId = "default" | "firecrawl";
|
|
13
17
|
|
|
14
18
|
export interface WebSearchResultItem {
|
|
15
19
|
rank: number; // 1-indexed
|
|
@@ -35,6 +39,8 @@ export interface WebSearchMetadata {
|
|
|
35
39
|
export interface WebFetchMetadata {
|
|
36
40
|
url: string;
|
|
37
41
|
finalUrl: string;
|
|
42
|
+
/** Provider that served the fetch. Defaults to the built-in fetcher. */
|
|
43
|
+
provider?: WebFetchProviderId;
|
|
38
44
|
status: number;
|
|
39
45
|
contentType?: string;
|
|
40
46
|
byteCount: number;
|
|
@@ -18,6 +18,13 @@ import type { WorkflowRunStatus } from "../../workflows/journal-store.js";
|
|
|
18
18
|
export interface WorkflowProgress {
|
|
19
19
|
type: "workflow_progress";
|
|
20
20
|
runId: string;
|
|
21
|
+
/**
|
|
22
|
+
* Originating conversation id, when launched from one; lets `broadcastMessage`
|
|
23
|
+
* auto-scope + seq-stamp the event to that conversation's SSE stream. Omitted
|
|
24
|
+
* for a conversationless run (e.g. a scheduled workflow), which broadcasts
|
|
25
|
+
* unscoped for raw SSE listeners and the DB record.
|
|
26
|
+
*/
|
|
27
|
+
conversationId?: string;
|
|
21
28
|
/** Latest phase title, when this emission came from a `phase(...)` call. */
|
|
22
29
|
phase?: string;
|
|
23
30
|
/** Run label (the workflow's `meta.name`), for client display. */
|
|
@@ -36,6 +43,13 @@ export interface WorkflowProgress {
|
|
|
36
43
|
export interface WorkflowCompleted {
|
|
37
44
|
type: "workflow_completed";
|
|
38
45
|
runId: string;
|
|
46
|
+
/**
|
|
47
|
+
* Originating conversation id, when launched from one; lets `broadcastMessage`
|
|
48
|
+
* auto-scope + seq-stamp the event to that conversation's SSE stream. Omitted
|
|
49
|
+
* for a conversationless run (e.g. a scheduled workflow), which broadcasts
|
|
50
|
+
* unscoped for raw SSE listeners and the DB record.
|
|
51
|
+
*/
|
|
52
|
+
conversationId?: string;
|
|
39
53
|
status: WorkflowRunStatus;
|
|
40
54
|
agentsSpawned: number;
|
|
41
55
|
inputTokens: number;
|
|
@@ -44,6 +58,74 @@ export interface WorkflowCompleted {
|
|
|
44
58
|
summary?: string;
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
/**
|
|
62
|
+
* A workflow run has started. Emitted once at launch, before any leaf events.
|
|
63
|
+
*/
|
|
64
|
+
export interface WorkflowStarted {
|
|
65
|
+
type: "workflow_started";
|
|
66
|
+
runId: string;
|
|
67
|
+
/**
|
|
68
|
+
* Originating conversation id; lets `broadcastMessage` auto-scope +
|
|
69
|
+
* seq-stamp the event to the conversation's SSE stream.
|
|
70
|
+
*/
|
|
71
|
+
conversationId: string;
|
|
72
|
+
/**
|
|
73
|
+
* Tool-use id of the `skill_execute` block that launched this run, for
|
|
74
|
+
* anchoring the inline workflow card to the exact spawn tool call.
|
|
75
|
+
*/
|
|
76
|
+
toolUseId?: string;
|
|
77
|
+
/** Run label (the workflow's `meta.name`), for client display. */
|
|
78
|
+
label?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* A leaf agent within a workflow run has started. `seq` orders leaves within
|
|
83
|
+
* the run for stable client-side tree placement.
|
|
84
|
+
*/
|
|
85
|
+
export interface WorkflowLeafStarted {
|
|
86
|
+
type: "workflow_leaf_started";
|
|
87
|
+
runId: string;
|
|
88
|
+
/**
|
|
89
|
+
* Originating conversation id; lets `broadcastMessage` auto-scope +
|
|
90
|
+
* seq-stamp the event to the conversation's SSE stream.
|
|
91
|
+
*/
|
|
92
|
+
conversationId: string;
|
|
93
|
+
seq: number;
|
|
94
|
+
/** Leaf label, for client display. */
|
|
95
|
+
label?: string;
|
|
96
|
+
/** Phase the leaf belongs to, when the workflow declares phases. */
|
|
97
|
+
phase?: string;
|
|
98
|
+
/** Short summary of the leaf's prompt, for client display. */
|
|
99
|
+
promptSummary?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* A leaf agent within a workflow run has finished. `seq` matches the
|
|
104
|
+
* corresponding `workflow_leaf_started` event.
|
|
105
|
+
*/
|
|
106
|
+
export interface WorkflowLeafFinished {
|
|
107
|
+
type: "workflow_leaf_finished";
|
|
108
|
+
runId: string;
|
|
109
|
+
/**
|
|
110
|
+
* Originating conversation id; lets `broadcastMessage` auto-scope +
|
|
111
|
+
* seq-stamp the event to the conversation's SSE stream.
|
|
112
|
+
*/
|
|
113
|
+
conversationId: string;
|
|
114
|
+
seq: number;
|
|
115
|
+
status: "completed" | "failed";
|
|
116
|
+
/** Leaf label, for client display. */
|
|
117
|
+
label?: string;
|
|
118
|
+
inputTokens?: number;
|
|
119
|
+
outputTokens?: number;
|
|
120
|
+
/** Short summary of the leaf's result, for client display. */
|
|
121
|
+
resultSummary?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
47
124
|
// --- Domain-level union aliases (consumed by the barrel file) ---
|
|
48
125
|
|
|
49
|
-
export type _WorkflowsServerMessages =
|
|
126
|
+
export type _WorkflowsServerMessages =
|
|
127
|
+
| WorkflowProgress
|
|
128
|
+
| WorkflowCompleted
|
|
129
|
+
| WorkflowStarted
|
|
130
|
+
| WorkflowLeafStarted
|
|
131
|
+
| WorkflowLeafFinished;
|
|
@@ -21,7 +21,6 @@ mock.module("../util/logger.js", () => ({
|
|
|
21
21
|
}));
|
|
22
22
|
|
|
23
23
|
const { parseProcStat, selectReapable } = await import("./orphan-reaper.js");
|
|
24
|
-
const { DaemonConfigSchema } = await import("../config/schemas/platform.js");
|
|
25
24
|
|
|
26
25
|
describe("parseProcStat", () => {
|
|
27
26
|
test("parses a normal stat line", () => {
|
|
@@ -89,24 +88,6 @@ describe("selectReapable", () => {
|
|
|
89
88
|
});
|
|
90
89
|
});
|
|
91
90
|
|
|
92
|
-
describe("daemon.reapOrphanedSubprocesses gate", () => {
|
|
93
|
-
test("defaults to off so the reaper is opt-in", () => {
|
|
94
|
-
// GIVEN a daemon config with the reaper flag unspecified
|
|
95
|
-
// WHEN it is parsed with schema defaults
|
|
96
|
-
const parsed = DaemonConfigSchema.parse({});
|
|
97
|
-
// THEN the reaper is disabled unless explicitly turned on
|
|
98
|
-
expect(parsed.reapOrphanedSubprocesses).toBe(false);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test("honors an explicit opt-in", () => {
|
|
102
|
-
// GIVEN a daemon config that explicitly enables the reaper
|
|
103
|
-
// WHEN it is parsed
|
|
104
|
-
const parsed = DaemonConfigSchema.parse({ reapOrphanedSubprocesses: true });
|
|
105
|
-
// THEN the flag is respected
|
|
106
|
-
expect(parsed.reapOrphanedSubprocesses).toBe(true);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
91
|
// ── Integration: real reparented orphan on Linux ────────────────────────────
|
|
111
92
|
const itLinux = process.platform === "linux" ? test : test.skip;
|
|
112
93
|
|
|
@@ -26,9 +26,7 @@
|
|
|
26
26
|
* macOS dev, or if an init such as tini is ever placed above the daemon),
|
|
27
27
|
* orphans reparent to that init and are reaped there, so there is nothing for
|
|
28
28
|
* this to do. Because the daemon is PID 1, orphans already reparent to it and
|
|
29
|
-
* `PR_SET_CHILD_SUBREAPER` is unnecessary.
|
|
30
|
-
* `daemon.reapOrphanedSubprocesses` config flag (default off) so the behavior
|
|
31
|
-
* can be enabled per workspace for validation before becoming the default.
|
|
29
|
+
* `PR_SET_CHILD_SUBREAPER` is unnecessary.
|
|
32
30
|
*
|
|
33
31
|
* References:
|
|
34
32
|
* - libuv reaps its own children by pid on SIGCHLD (`uv__wait_children`):
|
|
@@ -42,7 +40,6 @@
|
|
|
42
40
|
import { readdirSync, readFileSync } from "node:fs";
|
|
43
41
|
import { dlopen, FFIType, ptr } from "bun:ffi";
|
|
44
42
|
|
|
45
|
-
import { getConfigReadOnly } from "../config/loader.js";
|
|
46
43
|
import { getLogger } from "../util/logger.js";
|
|
47
44
|
|
|
48
45
|
const log = getLogger("orphan-reaper");
|
|
@@ -192,22 +189,9 @@ function reapScan(): void {
|
|
|
192
189
|
}
|
|
193
190
|
}
|
|
194
191
|
|
|
195
|
-
/**
|
|
196
|
-
* Read the opt-in gate from workspace config (`daemon.reapOrphanedSubprocesses`),
|
|
197
|
-
* tolerating a missing or malformed config so startup never fails on it.
|
|
198
|
-
*/
|
|
199
|
-
function isReaperEnabled(): boolean {
|
|
200
|
-
try {
|
|
201
|
-
return getConfigReadOnly().daemon.reapOrphanedSubprocesses;
|
|
202
|
-
} catch {
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
192
|
/**
|
|
208
193
|
* Start the periodic orphan reaper. No-op unless the daemon is PID 1 on Linux
|
|
209
|
-
* (otherwise reparented orphans are reaped by the real init)
|
|
210
|
-
* `daemon.reapOrphanedSubprocesses` config gate is enabled.
|
|
194
|
+
* (otherwise reparented orphans are reaped by the real init).
|
|
211
195
|
*/
|
|
212
196
|
export function startOrphanReaper(): void {
|
|
213
197
|
if (scanTimer) return;
|
|
@@ -218,12 +202,6 @@ export function startOrphanReaper(): void {
|
|
|
218
202
|
);
|
|
219
203
|
return;
|
|
220
204
|
}
|
|
221
|
-
if (!isReaperEnabled()) {
|
|
222
|
-
log.info(
|
|
223
|
-
"Orphan reaper not started: daemon.reapOrphanedSubprocesses is disabled",
|
|
224
|
-
);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
205
|
if (!initWaitpid()) return;
|
|
228
206
|
seenLastScan = new Set();
|
|
229
207
|
scanTimer = setInterval(reapScan, SCAN_INTERVAL_MS);
|
package/src/daemon/server.ts
CHANGED
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
publishAvatarChanged,
|
|
20
20
|
publishConfigChanged,
|
|
21
21
|
publishIdentityChanged,
|
|
22
|
-
publishIdentityIntroChanged,
|
|
23
22
|
publishSoundsConfigUpdated,
|
|
24
23
|
} from "../runtime/sync/resource-sync-events.js";
|
|
25
24
|
import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
|
|
@@ -193,14 +192,6 @@ export class DaemonServer {
|
|
|
193
192
|
}
|
|
194
193
|
}
|
|
195
194
|
|
|
196
|
-
private broadcastIdentityIntroChanged(): void {
|
|
197
|
-
try {
|
|
198
|
-
publishIdentityIntroChanged();
|
|
199
|
-
} catch (err) {
|
|
200
|
-
log.error({ err }, "Failed to broadcast identity intro change");
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
195
|
/** Best-effort sync of the IDENTITY.md name to the platform record. */
|
|
205
196
|
private syncIdentityToPlatform(): void {
|
|
206
197
|
try {
|
|
@@ -313,7 +304,6 @@ export class DaemonServer {
|
|
|
313
304
|
() => this.broadcastAvatarUpdated(),
|
|
314
305
|
() => this.broadcastConfigChanged(),
|
|
315
306
|
() => refreshSkillCapabilityMemories(getConfig()),
|
|
316
|
-
() => this.broadcastIdentityIntroChanged(),
|
|
317
307
|
);
|
|
318
308
|
|
|
319
309
|
this.syncIdentityToPlatform();
|
|
@@ -88,6 +88,10 @@ export interface ToolSetupContext extends SurfaceConversationContext {
|
|
|
88
88
|
taskRunId?: string;
|
|
89
89
|
/** Guardian runtime context for the conversation — trustClass is propagated into ToolContext for control-plane policy enforcement. */
|
|
90
90
|
trustContext?: TrustContext;
|
|
91
|
+
/** Per-turn trust snapshot, captured at turn start. Preferred over the live
|
|
92
|
+
* `trustContext` for mid-turn trust decisions (tool approval, control-plane
|
|
93
|
+
* policy) so a concurrent mutation cannot elevate the in-flight turn. */
|
|
94
|
+
currentTurnTrustContext?: TrustContext;
|
|
91
95
|
/** Voice/call session ID, if the conversation originates from a call. Propagated into ToolContext for scoped grant consumption. */
|
|
92
96
|
callSessionId?: string;
|
|
93
97
|
/** The interface ID of the connected client driving the current turn (e.g. "macos", "chrome-extension"). Propagated into ToolContext for browser backend selection. */
|
|
@@ -13,7 +13,7 @@ export interface TrustContext {
|
|
|
13
13
|
/** Channel through which the inbound message arrived. */
|
|
14
14
|
sourceChannel: ChannelId;
|
|
15
15
|
/** Trust classification -- see {@link TrustClass} for semantics. */
|
|
16
|
-
trustClass:
|
|
16
|
+
trustClass: TrustClass;
|
|
17
17
|
/** Chat/conversation ID for delivering guardian notifications. */
|
|
18
18
|
guardianChatId?: string;
|
|
19
19
|
/** Canonical external user ID of the guardian for this (assistant, channel) binding. */
|
|
@@ -147,6 +147,7 @@ function translateAgentEventToServerMessage(
|
|
|
147
147
|
case "compaction_completed":
|
|
148
148
|
case "history_stripped":
|
|
149
149
|
case "agent_loop_exit":
|
|
150
|
+
case "system_prompt_changed":
|
|
150
151
|
return null;
|
|
151
152
|
case "llm_call_started":
|
|
152
153
|
// The wake path persists its assistant tail via
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getConfig } from "../config/loader.js";
|
|
2
1
|
import {
|
|
3
2
|
recordToolInvocation,
|
|
4
3
|
type ToolInvocationRecord,
|
|
5
4
|
} from "../memory/tool-usage-store.js";
|
|
5
|
+
import { getCachedShareAnalytics } from "../platform/consent-cache.js";
|
|
6
6
|
import { redactJsonStringLeaves } from "../security/redact-json.js";
|
|
7
7
|
import { redactSecrets } from "../security/secret-scanner.js";
|
|
8
8
|
import {
|
|
@@ -168,7 +168,7 @@ function telemetryColumns(
|
|
|
168
168
|
rawInput: string,
|
|
169
169
|
resultBytes: number,
|
|
170
170
|
): TelemetryColumns {
|
|
171
|
-
if (!
|
|
171
|
+
if (!getCachedShareAnalytics()) return NULL_TELEMETRY_COLUMNS;
|
|
172
172
|
return {
|
|
173
173
|
argBytes: event.inputBytes ?? Buffer.byteLength(rawInput, "utf8"),
|
|
174
174
|
resultBytes,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import { type FeedItem } from "../api/responses/home.js";
|
|
4
|
+
import {
|
|
5
|
+
classifyConversationSource,
|
|
6
|
+
enrichFeedItemsWithSource,
|
|
7
|
+
type FeedSourceEnrichmentDeps,
|
|
8
|
+
} from "./feed-source-enrichment.js";
|
|
9
|
+
|
|
10
|
+
function makeItem(partial: Partial<FeedItem> & Pick<FeedItem, "id">): FeedItem {
|
|
11
|
+
return {
|
|
12
|
+
type: "notification",
|
|
13
|
+
priority: 50,
|
|
14
|
+
summary: "summary",
|
|
15
|
+
timestamp: "2026-06-18T00:00:00.000Z",
|
|
16
|
+
createdAt: "2026-06-18T00:00:00.000Z",
|
|
17
|
+
status: "new",
|
|
18
|
+
...partial,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("classifyConversationSource", () => {
|
|
23
|
+
it("maps each known producer source to its coarse type", () => {
|
|
24
|
+
expect(classifyConversationSource("heartbeat")).toBe("heartbeat");
|
|
25
|
+
expect(classifyConversationSource("memory-retrospective")).toBe(
|
|
26
|
+
"memory_consolidation",
|
|
27
|
+
);
|
|
28
|
+
expect(classifyConversationSource("memory-retrospective-fork")).toBe(
|
|
29
|
+
"memory_consolidation",
|
|
30
|
+
);
|
|
31
|
+
expect(classifyConversationSource("schedule")).toBe("schedule");
|
|
32
|
+
expect(classifyConversationSource("auto-analysis")).toBe("auto_analysis");
|
|
33
|
+
expect(classifyConversationSource("user")).toBe("user");
|
|
34
|
+
expect(classifyConversationSource("home-feed")).toBe("user");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("falls through to 'other' for unknown / paired-delivery / empty sources", () => {
|
|
38
|
+
expect(classifyConversationSource("notification")).toBe("other");
|
|
39
|
+
expect(classifyConversationSource("something-else")).toBe("other");
|
|
40
|
+
expect(classifyConversationSource(null)).toBe("other");
|
|
41
|
+
expect(classifyConversationSource(undefined)).toBe("other");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("enrichFeedItemsWithSource", () => {
|
|
46
|
+
const deps = (
|
|
47
|
+
conv: Record<string, { source: string; scheduleJobId: string | null }>,
|
|
48
|
+
schedules: Record<string, string> = {},
|
|
49
|
+
): FeedSourceEnrichmentDeps => ({
|
|
50
|
+
getConversationRow: (id) => conv[id] ?? null,
|
|
51
|
+
getScheduleName: (id) => schedules[id] ?? null,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("classifies a heartbeat item with a static label", () => {
|
|
55
|
+
const [item] = enrichFeedItemsWithSource(
|
|
56
|
+
[makeItem({ id: "n1", conversationId: "c1" })],
|
|
57
|
+
deps({ c1: { source: "heartbeat", scheduleJobId: null } }),
|
|
58
|
+
);
|
|
59
|
+
expect(item.sourceType).toBe("heartbeat");
|
|
60
|
+
expect(item.sourceKey).toBe("heartbeat");
|
|
61
|
+
expect(item.sourceLabel).toBe("Heartbeat");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("classifies a memory-consolidation item", () => {
|
|
65
|
+
const [item] = enrichFeedItemsWithSource(
|
|
66
|
+
[makeItem({ id: "n2", conversationId: "c2" })],
|
|
67
|
+
deps({ c2: { source: "memory-retrospective", scheduleJobId: null } }),
|
|
68
|
+
);
|
|
69
|
+
expect(item.sourceType).toBe("memory_consolidation");
|
|
70
|
+
expect(item.sourceKey).toBe("memory_consolidation");
|
|
71
|
+
expect(item.sourceLabel).toBe("Memory consolidation");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("gives distinct keys and names to two different schedules", () => {
|
|
75
|
+
const [a, b] = enrichFeedItemsWithSource(
|
|
76
|
+
[
|
|
77
|
+
makeItem({ id: "n3", conversationId: "cA" }),
|
|
78
|
+
makeItem({ id: "n4", conversationId: "cB" }),
|
|
79
|
+
],
|
|
80
|
+
deps(
|
|
81
|
+
{
|
|
82
|
+
cA: { source: "schedule", scheduleJobId: "sched-A" },
|
|
83
|
+
cB: { source: "schedule", scheduleJobId: "sched-B" },
|
|
84
|
+
},
|
|
85
|
+
{ "sched-A": "Morning digest", "sched-B": "Evening recap" },
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
expect(a.sourceType).toBe("schedule");
|
|
89
|
+
expect(a.sourceKey).toBe("schedule:sched-A");
|
|
90
|
+
expect(a.sourceLabel).toBe("Morning digest");
|
|
91
|
+
// scheduleId recovered from the conversation row is surfaced in metadata.
|
|
92
|
+
expect(a.metadata?.scheduleId).toBe("sched-A");
|
|
93
|
+
|
|
94
|
+
expect(b.sourceKey).toBe("schedule:sched-B");
|
|
95
|
+
expect(b.sourceLabel).toBe("Evening recap");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("prefers an explicit metadata.scheduleId over the conversation row", () => {
|
|
99
|
+
const [item] = enrichFeedItemsWithSource(
|
|
100
|
+
[
|
|
101
|
+
makeItem({
|
|
102
|
+
id: "n5",
|
|
103
|
+
conversationId: "cX",
|
|
104
|
+
metadata: { scheduleId: "from-payload" },
|
|
105
|
+
}),
|
|
106
|
+
],
|
|
107
|
+
deps(
|
|
108
|
+
{ cX: { source: "schedule", scheduleJobId: "from-row" } },
|
|
109
|
+
{ "from-payload": "Payload schedule" },
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
expect(item.sourceKey).toBe("schedule:from-payload");
|
|
113
|
+
expect(item.sourceLabel).toBe("Payload schedule");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("labels a schedule with no resolvable name as 'Scheduled'", () => {
|
|
117
|
+
const [item] = enrichFeedItemsWithSource(
|
|
118
|
+
[makeItem({ id: "n6", conversationId: "cY" })],
|
|
119
|
+
deps({ cY: { source: "schedule", scheduleJobId: "gone" } }),
|
|
120
|
+
);
|
|
121
|
+
expect(item.sourceKey).toBe("schedule:gone");
|
|
122
|
+
expect(item.sourceLabel).toBe("Scheduled");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("classifies items with no source conversation as 'other'", () => {
|
|
126
|
+
const [item] = enrichFeedItemsWithSource(
|
|
127
|
+
[makeItem({ id: "n7" })],
|
|
128
|
+
deps({}),
|
|
129
|
+
);
|
|
130
|
+
expect(item.sourceType).toBe("other");
|
|
131
|
+
expect(item.sourceKey).toBe("other");
|
|
132
|
+
expect(item.sourceLabel).toBe("Other");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("resolves each distinct conversation at most once", () => {
|
|
136
|
+
const calls: string[] = [];
|
|
137
|
+
enrichFeedItemsWithSource(
|
|
138
|
+
[
|
|
139
|
+
makeItem({ id: "n8", conversationId: "dup" }),
|
|
140
|
+
makeItem({ id: "n9", conversationId: "dup" }),
|
|
141
|
+
],
|
|
142
|
+
{
|
|
143
|
+
getConversationRow: (id) => {
|
|
144
|
+
calls.push(id);
|
|
145
|
+
return { source: "heartbeat", scheduleJobId: null };
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
expect(calls).toEqual(["dup"]);
|
|
150
|
+
});
|
|
151
|
+
});
|