@vellumai/assistant 0.9.1-staging.1 → 0.10.0-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/activation-funnel-telemetry.md +24 -18
- 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 +15 -0
- package/openapi.yaml +852 -15
- package/package.json +1 -1
- 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 +59 -7
- package/src/__tests__/agent-loop-compaction-strip.test.ts +17 -16
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- 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__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +174 -30
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-prompt-route.test.ts +1 -0
- package/src/__tests__/credential-security-invariants.test.ts +2 -0
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/dynamic-page-surface.test.ts +51 -0
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- 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__/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 +0 -3
- package/src/__tests__/llm-catalog-parity.test.ts +30 -1
- package/src/__tests__/llm-resolver.test.ts +21 -0
- 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__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +38 -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__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/skill-execute-input.test.ts +5 -0
- 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 +150 -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__/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__/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-verification.test.ts +2 -4
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +0 -1
- package/src/__tests__/weak-open-model.test.ts +30 -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 +33 -33
- 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 +26 -0
- package/src/api/responses/home.ts +26 -0
- 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 +181 -78
- 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-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +57 -5
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +134 -4
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +53 -11
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/merge-plugin-tree.ts +149 -49
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +64 -36
- package/src/cli/program.ts +2 -4
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/workflows/SKILL.md +14 -7
- package/src/config/call-site-defaults.ts +3 -0
- package/src/config/feature-flag-registry.json +49 -18
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/memory-v3-gate.ts +11 -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/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/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +94 -34
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +2 -10
- package/src/contacts/contacts-write.ts +1 -2
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +86 -52
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +100 -19
- 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-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +16 -11
- package/src/daemon/conversation.ts +64 -14
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +5 -10
- package/src/daemon/handlers/config-slack-channel.ts +20 -0
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -20
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.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/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +34 -0
- 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/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-init.ts +10 -0
- package/src/memory/embedding-backend.ts +15 -1
- package/src/memory/jobs-worker.ts +2 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +9 -0
- 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 +10 -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 +30 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -1
- 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/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/slack.ts +55 -73
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +6 -2
- 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 +3 -13
- package/src/notifications/notification-utils.ts +2 -1
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -128
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/index.ts +27 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/index.ts +35 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +75 -7
- 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 +37 -4
- 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/task-progress-nudge/hooks/post-tool-use.ts +2 -12
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +12 -2
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/retry.ts +53 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/__tests__/agent-wake.test.ts +181 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +49 -21
- package/src/runtime/agent-wake.ts +52 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +5 -1
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +1 -2
- 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 +6 -22
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +15 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +35 -13
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- 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-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +37 -12
- 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/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +88 -6
- 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 +40 -7
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +225 -1
- package/src/runtime/routes/workflow-routes.ts +131 -1
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- 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 +11 -4
- 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/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +29 -18
- package/src/tools/document/document-tool.ts +2 -3
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +3 -2
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +4 -3
- package/src/tools/schedule/update.ts +2 -1
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/skills/execute.ts +1 -2
- package/src/tools/subagent/spawn.ts +37 -13
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +17 -10
- package/src/tools/types.ts +9 -0
- package/src/tools/ui-surface/definitions.ts +25 -2
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/platform.ts +8 -1
- package/src/watcher/telemetry.ts +2 -2
- 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 -3
- package/src/workflows/run-manager.ts +64 -0
- 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/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
|
@@ -2,8 +2,13 @@
|
|
|
2
2
|
* NotificationSignal -- the flexible input from producers.
|
|
3
3
|
* Uses free-form event names and structured attention hints that let the
|
|
4
4
|
* decision engine route contextually.
|
|
5
|
+
*
|
|
6
|
+
* All data shapes are defined as Zod schemas — types are derived via
|
|
7
|
+
* `z.infer` so runtime validation and compile-time types stay in sync.
|
|
5
8
|
*/
|
|
6
9
|
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
|
|
7
12
|
import type { ConversationCreateType } from "../memory/conversation-crud.js";
|
|
8
13
|
import type { GuardianQuestionPayload } from "./guardian-question-mode.js";
|
|
9
14
|
|
|
@@ -14,7 +19,11 @@ export const NOTIFICATION_SOURCE_CHANNELS = [
|
|
|
14
19
|
{ id: "vellum", description: "Vellum native client (macOS/iOS)" },
|
|
15
20
|
{ id: "phone", description: "Phone call pipeline" },
|
|
16
21
|
{ id: "telegram", description: "Telegram channel" },
|
|
22
|
+
{ id: "whatsapp", description: "WhatsApp channel" },
|
|
17
23
|
{ id: "slack", description: "Slack channel" },
|
|
24
|
+
{ id: "email", description: "Email channel" },
|
|
25
|
+
{ id: "platform", description: "Platform-managed channel" },
|
|
26
|
+
{ id: "a2a", description: "Agent-to-agent protocol channel" },
|
|
18
27
|
{ id: "scheduler", description: "Scheduled task runner (reminders, cron)" },
|
|
19
28
|
{ id: "watcher", description: "File/event watcher subsystem" },
|
|
20
29
|
] as const;
|
|
@@ -22,6 +31,18 @@ export const NOTIFICATION_SOURCE_CHANNELS = [
|
|
|
22
31
|
export type NotificationSourceChannel =
|
|
23
32
|
(typeof NOTIFICATION_SOURCE_CHANNELS)[number]["id"];
|
|
24
33
|
|
|
34
|
+
/** Typed tuple of all source channel IDs — usable with `z.enum()`. */
|
|
35
|
+
export const NOTIFICATION_SOURCE_CHANNEL_IDS = NOTIFICATION_SOURCE_CHANNELS.map(
|
|
36
|
+
(c) => c.id,
|
|
37
|
+
) as unknown as readonly [
|
|
38
|
+
NotificationSourceChannel,
|
|
39
|
+
...NotificationSourceChannel[],
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export const NotificationSourceChannelSchema = z.enum(
|
|
43
|
+
NOTIFICATION_SOURCE_CHANNEL_IDS,
|
|
44
|
+
);
|
|
45
|
+
|
|
25
46
|
export function isNotificationSourceChannel(
|
|
26
47
|
value: unknown,
|
|
27
48
|
): value is NotificationSourceChannel {
|
|
@@ -114,15 +135,24 @@ export type NotificationSourceEventName =
|
|
|
114
135
|
|
|
115
136
|
// ── Attention hints & routing ──────────────────────────────────────────
|
|
116
137
|
|
|
117
|
-
export
|
|
118
|
-
|
|
119
|
-
urgency: "low" | "medium" | "high" | "critical";
|
|
120
|
-
deadlineAt?: number; // epoch ms
|
|
121
|
-
isAsyncBackground: boolean;
|
|
122
|
-
visibleInSourceNow: boolean;
|
|
123
|
-
}
|
|
138
|
+
export const UrgencySchema = z.enum(["low", "medium", "high", "critical"]);
|
|
139
|
+
export type Urgency = z.infer<typeof UrgencySchema>;
|
|
124
140
|
|
|
125
|
-
export
|
|
141
|
+
export const AttentionHintsSchema = z.object({
|
|
142
|
+
requiresAction: z.boolean(),
|
|
143
|
+
urgency: UrgencySchema,
|
|
144
|
+
deadlineAt: z.number().optional(),
|
|
145
|
+
isAsyncBackground: z.boolean(),
|
|
146
|
+
visibleInSourceNow: z.boolean(),
|
|
147
|
+
});
|
|
148
|
+
export type AttentionHints = z.infer<typeof AttentionHintsSchema>;
|
|
149
|
+
|
|
150
|
+
export const RoutingIntentSchema = z.enum([
|
|
151
|
+
"single_channel",
|
|
152
|
+
"multi_channel",
|
|
153
|
+
"all_channels",
|
|
154
|
+
]);
|
|
155
|
+
export type RoutingIntent = z.infer<typeof RoutingIntentSchema>;
|
|
126
156
|
|
|
127
157
|
// ── Typed context payloads ──────────────────────────────────────────────
|
|
128
158
|
|
|
@@ -140,42 +170,48 @@ export type RoutingIntent = "single_channel" | "multi_channel" | "all_channels";
|
|
|
140
170
|
* This is channel-agnostic by design — any channel's access request that
|
|
141
171
|
* resolves to a non-source-channel guardian gets the same treatment.
|
|
142
172
|
*/
|
|
143
|
-
export
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
export
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
sourceChannel: string;
|
|
152
|
-
conversationExternalId: string;
|
|
153
|
-
actorExternalId: string;
|
|
154
|
-
actorDisplayName: string | null;
|
|
155
|
-
actorUsername: string | null;
|
|
156
|
-
senderIdentifier: string;
|
|
157
|
-
guardianBindingChannel: string | null;
|
|
158
|
-
guardianResolutionSource: GuardianResolutionSource;
|
|
159
|
-
previousMemberStatus: string | null;
|
|
160
|
-
/** Preview of the requester's original message (first ~200 chars). */
|
|
161
|
-
messagePreview: string | null;
|
|
162
|
-
/** Slack-specific: user is from an external workspace (Slack Connect). */
|
|
163
|
-
isStranger?: boolean;
|
|
164
|
-
/** Slack-specific: user is a guest / restricted account. */
|
|
165
|
-
isRestricted?: boolean;
|
|
166
|
-
/** Slack message timestamp (e.g. "1234567890.123456") for permalink construction. */
|
|
167
|
-
messageTs?: string;
|
|
168
|
-
}
|
|
173
|
+
export const GuardianResolutionSourceSchema = z.enum([
|
|
174
|
+
"source-channel-contact",
|
|
175
|
+
"vellum-anchor",
|
|
176
|
+
"none",
|
|
177
|
+
]);
|
|
178
|
+
export type GuardianResolutionSource = z.infer<
|
|
179
|
+
typeof GuardianResolutionSourceSchema
|
|
180
|
+
>;
|
|
169
181
|
|
|
170
|
-
export
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
182
|
+
export const AccessRequestContextPayloadSchema = z.object({
|
|
183
|
+
requestId: z.string(),
|
|
184
|
+
requestCode: z.string(),
|
|
185
|
+
sourceChannel: z.string(),
|
|
186
|
+
conversationExternalId: z.string(),
|
|
187
|
+
actorExternalId: z.string(),
|
|
188
|
+
actorDisplayName: z.string().nullable(),
|
|
189
|
+
actorUsername: z.string().nullable(),
|
|
190
|
+
senderIdentifier: z.string(),
|
|
191
|
+
guardianBindingChannel: z.string().nullable(),
|
|
192
|
+
guardianResolutionSource: GuardianResolutionSourceSchema,
|
|
193
|
+
previousMemberStatus: z.string().nullable(),
|
|
194
|
+
messagePreview: z.string().nullable(),
|
|
195
|
+
isStranger: z.boolean().optional(),
|
|
196
|
+
isRestricted: z.boolean().optional(),
|
|
197
|
+
messageTs: z.string().optional(),
|
|
198
|
+
});
|
|
199
|
+
export type AccessRequestContextPayload = z.infer<
|
|
200
|
+
typeof AccessRequestContextPayloadSchema
|
|
201
|
+
>;
|
|
202
|
+
|
|
203
|
+
export const GuardianChannelActivationPayloadSchema = z.object({
|
|
204
|
+
verificationCode: z.string(),
|
|
205
|
+
sourceChannel: z.string(),
|
|
206
|
+
actorExternalId: z.string(),
|
|
207
|
+
actorDisplayName: z.string().nullable(),
|
|
208
|
+
actorUsername: z.string().nullable(),
|
|
209
|
+
sessionId: z.string(),
|
|
210
|
+
expiresAt: z.number(),
|
|
211
|
+
});
|
|
212
|
+
export type GuardianChannelActivationPayload = z.infer<
|
|
213
|
+
typeof GuardianChannelActivationPayloadSchema
|
|
214
|
+
>;
|
|
179
215
|
|
|
180
216
|
export interface NotificationEventContextPayloadMap {
|
|
181
217
|
"guardian.question": GuardianQuestionPayload;
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core domain types for the unified notification system.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Data shapes are defined as Zod schemas — types derived via `z.infer`
|
|
5
|
+
* so runtime validation and compile-time types stay in sync.
|
|
6
|
+
*
|
|
7
|
+
* Behavioral interfaces (ChannelAdapter) remain as TypeScript interfaces.
|
|
6
8
|
*/
|
|
7
9
|
|
|
10
|
+
import { ApprovalUIMetadataSchema } from "@vellumai/gateway-client";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
8
13
|
import type { ChannelPolicies } from "../channels/config.js";
|
|
9
14
|
import type { ChannelId } from "../channels/types.js";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import type { AttentionHints } from "./signal.js";
|
|
15
|
+
import { AccessRequestPayloadSchema } from "./access-request-copy.js";
|
|
16
|
+
import { UrgencySchema } from "./signal.js";
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* Derived from the channel policy registry: only channels whose
|
|
@@ -22,38 +26,39 @@ export type NotificationChannel = {
|
|
|
22
26
|
}[keyof ChannelPolicies] &
|
|
23
27
|
ChannelId;
|
|
24
28
|
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
messageId
|
|
56
|
-
}
|
|
29
|
+
export const NotificationDeliveryStatusSchema = z.enum([
|
|
30
|
+
"pending",
|
|
31
|
+
"sent",
|
|
32
|
+
"failed",
|
|
33
|
+
"skipped",
|
|
34
|
+
]);
|
|
35
|
+
export type NotificationDeliveryStatus = z.infer<
|
|
36
|
+
typeof NotificationDeliveryStatusSchema
|
|
37
|
+
>;
|
|
38
|
+
|
|
39
|
+
export const NotificationDeliveryResultSchema = z.object({
|
|
40
|
+
channel: z.string(),
|
|
41
|
+
destination: z.string(),
|
|
42
|
+
status: NotificationDeliveryStatusSchema,
|
|
43
|
+
errorCode: z.string().optional(),
|
|
44
|
+
errorMessage: z.string().optional(),
|
|
45
|
+
sentAt: z.number().optional(),
|
|
46
|
+
conversationId: z.string().optional(),
|
|
47
|
+
messageId: z.string().optional(),
|
|
48
|
+
conversationStrategy: z.string().optional(),
|
|
49
|
+
});
|
|
50
|
+
export type NotificationDeliveryResult = z.infer<
|
|
51
|
+
typeof NotificationDeliveryResultSchema
|
|
52
|
+
>;
|
|
53
|
+
|
|
54
|
+
// -- Channel adapter data shapes ----------------------------------------------
|
|
55
|
+
|
|
56
|
+
export const DeliveryResultSchema = z.object({
|
|
57
|
+
success: z.boolean(),
|
|
58
|
+
error: z.string().optional(),
|
|
59
|
+
messageId: z.string().optional(),
|
|
60
|
+
});
|
|
61
|
+
export type DeliveryResult = z.infer<typeof DeliveryResultSchema>;
|
|
57
62
|
|
|
58
63
|
/** Resolved destination for a specific channel. */
|
|
59
64
|
export interface ChannelDestination {
|
|
@@ -70,58 +75,44 @@ export interface ChannelDestination {
|
|
|
70
75
|
* conversations keyed by (sourceChannel, externalChatId).
|
|
71
76
|
*/
|
|
72
77
|
export interface DestinationBindingContext {
|
|
73
|
-
/** The channel this binding belongs to (e.g. "telegram", "slack"). */
|
|
74
78
|
sourceChannel: NotificationChannel;
|
|
75
|
-
/** The channel-specific chat/conversation identifier (e.g. Telegram chat ID, phone number). */
|
|
76
79
|
externalChatId: string;
|
|
77
|
-
/** Optional external user identifier within the chat. */
|
|
78
80
|
externalUserId?: string;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
urgency:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
approvalContext?: ApprovalUIMetadata;
|
|
107
|
-
/**
|
|
108
|
-
* Pre-parsed access request context for `ingress.access_request` signals.
|
|
109
|
-
* Built centrally by the broadcaster so adapters can render structured
|
|
110
|
-
* access-request cards without re-parsing `contextPayload`.
|
|
111
|
-
*/
|
|
112
|
-
accessRequestContext?: ParsedAccessRequestPayload;
|
|
113
|
-
}
|
|
83
|
+
// -- Rendered copy & delivery payload -----------------------------------------
|
|
84
|
+
|
|
85
|
+
export const RenderedChannelCopySchema = z.object({
|
|
86
|
+
title: z.string(),
|
|
87
|
+
body: z.string(),
|
|
88
|
+
deliveryText: z.string().optional(),
|
|
89
|
+
conversationTitle: z.string().optional(),
|
|
90
|
+
conversationSeedMessage: z.string().optional(),
|
|
91
|
+
seedContentBlocks: z.array(z.unknown()).optional(),
|
|
92
|
+
});
|
|
93
|
+
export type RenderedChannelCopy = z.infer<typeof RenderedChannelCopySchema>;
|
|
94
|
+
|
|
95
|
+
export const ChannelDeliveryPayloadSchema = z.object({
|
|
96
|
+
deliveryId: z.string().optional(),
|
|
97
|
+
sourceEventName: z.string(),
|
|
98
|
+
copy: RenderedChannelCopySchema,
|
|
99
|
+
deepLinkTarget: z.record(z.string(), z.unknown()).optional(),
|
|
100
|
+
contextPayload: z.record(z.string(), z.unknown()).optional(),
|
|
101
|
+
urgency: UrgencySchema,
|
|
102
|
+
approvalContext: ApprovalUIMetadataSchema.optional(),
|
|
103
|
+
accessRequestContext: AccessRequestPayloadSchema.optional(),
|
|
104
|
+
});
|
|
105
|
+
export type ChannelDeliveryPayload = z.infer<
|
|
106
|
+
typeof ChannelDeliveryPayloadSchema
|
|
107
|
+
>;
|
|
114
108
|
|
|
115
|
-
/**
|
|
116
|
-
* Patch supplied when an already-delivered notification is edited.
|
|
117
|
-
* Adapters only need to act on `title` and `body` — feed-only fields
|
|
118
|
-
* like `urgency` and `status` are handled by the home-feed patch.
|
|
119
|
-
*/
|
|
120
109
|
export interface ChannelUpdatePayload {
|
|
121
110
|
title?: string;
|
|
122
111
|
body?: string;
|
|
123
112
|
}
|
|
124
113
|
|
|
114
|
+
// -- Channel adapter interface ------------------------------------------------
|
|
115
|
+
|
|
125
116
|
/** Interface that each channel adapter must implement. */
|
|
126
117
|
export interface ChannelAdapter {
|
|
127
118
|
channel: NotificationChannel;
|
|
@@ -129,77 +120,57 @@ export interface ChannelAdapter {
|
|
|
129
120
|
payload: ChannelDeliveryPayload,
|
|
130
121
|
destination: ChannelDestination,
|
|
131
122
|
): Promise<DeliveryResult>;
|
|
132
|
-
/**
|
|
133
|
-
* Optional: edit a previously-sent message in place. Channels that
|
|
134
|
-
* cannot edit (push, email, SMS) omit this and the router treats
|
|
135
|
-
* them as `"unsupported"`. Adapters that implement it use
|
|
136
|
-
* `delivery.messageId` (captured at send time) as the channel-native
|
|
137
|
-
* handle for the in-place update.
|
|
138
|
-
*/
|
|
139
123
|
update?(
|
|
140
124
|
delivery: ChannelUpdateContext,
|
|
141
125
|
patch: ChannelUpdatePayload,
|
|
142
126
|
): Promise<DeliveryResult>;
|
|
143
127
|
}
|
|
144
128
|
|
|
145
|
-
/** Per-delivery state an adapter needs to update a previously-sent message. */
|
|
146
129
|
export interface ChannelUpdateContext {
|
|
147
|
-
/** notification_deliveries.id */
|
|
148
130
|
deliveryId: string;
|
|
149
|
-
/** Channel-native destination (e.g. Slack chat id). */
|
|
150
131
|
destination: string;
|
|
151
|
-
/** Channel-native message identifier captured at send time. */
|
|
152
132
|
messageId: string | null;
|
|
153
133
|
}
|
|
154
134
|
|
|
155
|
-
// -- Decision engine output ---------------------------------------------------
|
|
156
|
-
|
|
157
|
-
/** Rendered notification copy for a single channel. */
|
|
158
|
-
export interface RenderedChannelCopy {
|
|
159
|
-
title: string;
|
|
160
|
-
body: string;
|
|
161
|
-
/** Channel-native delivery text (e.g. Telegram chat message body). */
|
|
162
|
-
deliveryText?: string;
|
|
163
|
-
conversationTitle?: string;
|
|
164
|
-
conversationSeedMessage?: string;
|
|
165
|
-
/**
|
|
166
|
-
* Structured content blocks for the seed message. When present,
|
|
167
|
-
* conversation pairing stores `JSON.stringify(seedContentBlocks)` as the
|
|
168
|
-
* message content instead of the plain-text seed, enabling Surface
|
|
169
|
-
* rendering in the web/macOS/iOS apps.
|
|
170
|
-
*
|
|
171
|
-
* Typically includes a `ui_surface` block (rendered as an interactive
|
|
172
|
-
* card) followed by a `text` block (plain-text fallback for search,
|
|
173
|
-
* backward-compatible clients, and CLI display).
|
|
174
|
-
*/
|
|
175
|
-
seedContentBlocks?: unknown[];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
135
|
// -- Conversation action types ------------------------------------------------
|
|
179
136
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
137
|
+
export const ConversationActionSchema = z.discriminatedUnion("action", [
|
|
138
|
+
z.object({ action: z.literal("start_new") }),
|
|
139
|
+
z.object({
|
|
140
|
+
action: z.literal("reuse_existing"),
|
|
141
|
+
conversationId: z.string(),
|
|
142
|
+
}),
|
|
143
|
+
]);
|
|
144
|
+
export type ConversationAction = z.infer<typeof ConversationActionSchema>;
|
|
184
145
|
|
|
185
|
-
|
|
186
|
-
export interface ConversationActionReuseExisting {
|
|
187
|
-
action: "reuse_existing";
|
|
188
|
-
conversationId: string;
|
|
189
|
-
}
|
|
146
|
+
// -- Decision engine output ---------------------------------------------------
|
|
190
147
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
148
|
+
export const NotificationDecisionSchema = z.object({
|
|
149
|
+
shouldNotify: z.boolean(),
|
|
150
|
+
selectedChannels: z.array(z.string()),
|
|
151
|
+
reasoningSummary: z.string(),
|
|
152
|
+
renderedCopy: z.record(z.string(), RenderedChannelCopySchema),
|
|
153
|
+
conversationActions: z
|
|
154
|
+
.record(z.string(), ConversationActionSchema)
|
|
155
|
+
.optional(),
|
|
156
|
+
deepLinkTarget: z.record(z.string(), z.unknown()).optional(),
|
|
157
|
+
dedupeKey: z.string(),
|
|
158
|
+
confidence: z.number(),
|
|
159
|
+
fallbackUsed: z.boolean(),
|
|
160
|
+
persistedDecisionId: z.string().optional(),
|
|
161
|
+
});
|
|
195
162
|
|
|
196
|
-
/**
|
|
163
|
+
/**
|
|
164
|
+
* Decision engine output. `selectedChannels` and `renderedCopy` are keyed
|
|
165
|
+
* by `NotificationChannel` — narrower than the Zod schema's `string` since
|
|
166
|
+
* `NotificationChannel` is a computed type derived from the channel config
|
|
167
|
+
* registry and cannot be expressed as a Zod enum.
|
|
168
|
+
*/
|
|
197
169
|
export interface NotificationDecision {
|
|
198
170
|
shouldNotify: boolean;
|
|
199
171
|
selectedChannels: NotificationChannel[];
|
|
200
172
|
reasoningSummary: string;
|
|
201
173
|
renderedCopy: Partial<Record<NotificationChannel, RenderedChannelCopy>>;
|
|
202
|
-
/** Per-channel conversation actions decided by the model. Absent channels default to start_new. */
|
|
203
174
|
conversationActions?: Partial<
|
|
204
175
|
Record<NotificationChannel, ConversationAction>
|
|
205
176
|
>;
|
|
@@ -207,6 +178,5 @@ export interface NotificationDecision {
|
|
|
207
178
|
dedupeKey: string;
|
|
208
179
|
confidence: number;
|
|
209
180
|
fallbackUsed: boolean;
|
|
210
|
-
/** UUID of the persisted decision row (set after persistence in the decision engine). */
|
|
211
181
|
persistedDecisionId?: string;
|
|
212
182
|
}
|
|
@@ -125,6 +125,16 @@ mock.module("../ipc/gateway-client.js", () => ({
|
|
|
125
125
|
|
|
126
126
|
// ── Import the module under test AFTER mocks are set up ──────────────────────
|
|
127
127
|
|
|
128
|
+
import {
|
|
129
|
+
mkdtempSync,
|
|
130
|
+
rmSync,
|
|
131
|
+
symlinkSync,
|
|
132
|
+
unlinkSync,
|
|
133
|
+
writeFileSync,
|
|
134
|
+
} from "node:fs";
|
|
135
|
+
import { tmpdir } from "node:os";
|
|
136
|
+
import { join } from "node:path";
|
|
137
|
+
|
|
128
138
|
import {
|
|
129
139
|
check,
|
|
130
140
|
classifyRisk,
|
|
@@ -231,6 +241,47 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
231
241
|
expect(result2.reason).toBe("Cached test");
|
|
232
242
|
});
|
|
233
243
|
|
|
244
|
+
test("file-tool cache misses when a symlink target is retargeted", async () => {
|
|
245
|
+
// File risk depends on filesystem state: the cache key folds in the
|
|
246
|
+
// symlink-resolved target, so the same raw input must NOT return a stale
|
|
247
|
+
// cached result after the symlink is pointed somewhere new.
|
|
248
|
+
const dir = mkdtempSync(join(tmpdir(), "risk-cache-symlink-"));
|
|
249
|
+
try {
|
|
250
|
+
const benign = join(dir, "benign.txt");
|
|
251
|
+
const other = join(dir, "other.txt");
|
|
252
|
+
writeFileSync(benign, "ok");
|
|
253
|
+
writeFileSync(other, "ok");
|
|
254
|
+
const link = join(dir, "link.txt");
|
|
255
|
+
symlinkSync(benign, link);
|
|
256
|
+
|
|
257
|
+
mockIpcClassifyRiskResult = {
|
|
258
|
+
risk: "low",
|
|
259
|
+
reason: "benign",
|
|
260
|
+
matchType: "registry",
|
|
261
|
+
scopeOptions: [],
|
|
262
|
+
};
|
|
263
|
+
const first = await classifyRisk("file_read", { path: link });
|
|
264
|
+
expect(first.level).toBe(RiskLevel.Low);
|
|
265
|
+
|
|
266
|
+
// Retarget the symlink to a different real file; raw input unchanged.
|
|
267
|
+
unlinkSync(link);
|
|
268
|
+
symlinkSync(other, link);
|
|
269
|
+
|
|
270
|
+
mockIpcClassifyRiskResult = {
|
|
271
|
+
risk: "high",
|
|
272
|
+
reason: "now sensitive",
|
|
273
|
+
matchType: "registry",
|
|
274
|
+
scopeOptions: [],
|
|
275
|
+
};
|
|
276
|
+
const second = await classifyRisk("file_read", { path: link });
|
|
277
|
+
// Cache must have missed and re-classified against the new target.
|
|
278
|
+
expect(second.level).toBe(RiskLevel.High);
|
|
279
|
+
expect(second.reason).toBe("now sensitive");
|
|
280
|
+
} finally {
|
|
281
|
+
rmSync(dir, { recursive: true, force: true });
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
|
|
234
285
|
test("preserves commandCandidates from gateway response", async () => {
|
|
235
286
|
mockIpcClassifyRiskResult = {
|
|
236
287
|
risk: "low",
|