@vellumai/assistant 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +11 -12
- package/docker-entrypoint.sh +13 -2
- package/docker-init-apt-root.sh +79 -6
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +945 -36
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +271 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +272 -0
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/background-workers-disk-pressure.test.ts +2 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/compaction-events.test.ts +1 -1
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/compactor-tail-resolution.test.ts +107 -1
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/context-token-estimator.test.ts +112 -57
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +54 -3
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +31 -6
- package/src/__tests__/conversation-agent-loop.test.ts +77 -3
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +161 -0
- package/src/__tests__/conversation-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-load-cleaned-at.test.ts +279 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +290 -85
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +6 -0
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/external-plugin-loader.test.ts +91 -19
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/host-app-control-proxy.test.ts +241 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +7 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +9 -2
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +17 -16
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +3 -0
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +2 -0
- package/src/__tests__/llm-resolver.test.ts +340 -3
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/managed-profile-guard.test.ts +10 -0
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/openai-provider.test.ts +323 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +3 -3
- package/src/__tests__/openai-responses-provider.test.ts +4 -4
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +190 -0
- package/src/__tests__/platform-proxy-context.test.ts +6 -1
- package/src/__tests__/platform.test.ts +0 -3
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +3 -3
- package/src/__tests__/plugin-types.test.ts +2 -2
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/provider-catalog-visibility.test.ts +16 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +27 -25
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/system-prompt.test.ts +57 -101
- package/src/__tests__/terminal-tools.test.ts +11 -1
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-executor.test.ts +90 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +88 -5
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +208 -22
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/browser/operations.ts +15 -0
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +14 -0
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +9 -12
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +469 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/memory-v2.ts +308 -0
- package/src/cli/commands/notifications.ts +89 -37
- package/src/cli/commands/plugins.ts +67 -0
- package/src/cli/commands/schedules.ts +297 -5
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/install-from-github.ts +8 -9
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/program.ts +14 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +117 -1
- package/src/config/bundled-skills/document-editor/SKILL.md +115 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +240 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +22 -12
- package/src/config/call-site-defaults.ts +124 -0
- package/src/config/feature-flag-registry.json +111 -23
- package/src/config/llm-resolver.ts +66 -1
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +7 -3
- package/src/config/schemas/call-site-catalog.ts +21 -0
- package/src/config/schemas/channels.ts +9 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +14 -0
- package/src/config/schemas/llm.ts +4 -3
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +51 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/context/compactor.ts +80 -13
- package/src/context/token-estimator.ts +72 -31
- package/src/context/window-manager.ts +25 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -22
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +231 -23
- package/src/daemon/conversation-agent-loop.ts +252 -56
- package/src/daemon/conversation-lifecycle.ts +142 -116
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +144 -75
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +7 -0
- package/src/daemon/conversation.ts +42 -12
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +449 -0
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +80 -0
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-app-control-proxy.ts +69 -18
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/host-transfer-proxy.ts +1 -1
- package/src/daemon/lifecycle.ts +67 -65
- package/src/daemon/memory-v2-startup.ts +49 -13
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +8 -0
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/messages.ts +68 -1
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/pkb-reminder-builder.test.ts +10 -53
- package/src/daemon/pkb-reminder-builder.ts +4 -19
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +72 -12
- package/src/daemon/query-complexity-router.ts +75 -0
- package/src/daemon/skill-memory-refresh.ts +5 -1
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +44 -1
- package/src/heartbeat/heartbeat-service.ts +35 -191
- package/src/home/__tests__/feed-types.test.ts +40 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +20 -3
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +94 -0
- package/src/home/suggested-prompts.ts +177 -9
- package/src/ipc/cli-client.ts +147 -45
- package/src/memory/__tests__/conversation-queries.test.ts +220 -0
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +407 -10
- package/src/memory/conversation-crud.ts +133 -43
- package/src/memory/conversation-queries.ts +87 -1
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +22 -0
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +84 -3
- package/src/memory/graph/conversation-graph-memory.ts +18 -6
- package/src/memory/graph/tools.ts +6 -37
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs-worker.ts +21 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +7 -2
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +4 -22
- package/src/memory/memory-retrospective-job.ts +438 -21
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +26 -8
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/index.ts +20 -0
- package/src/memory/migrations/registry.ts +33 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +2 -0
- package/src/memory/schema/infrastructure.ts +2 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +221 -17
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/router.test.ts +489 -1
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +69 -29
- package/src/memory/v2/page-index.ts +246 -19
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/router.ts +209 -55
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +18 -3
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +5 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +521 -36
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +111 -44
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +10 -1
- package/src/notifications/home-feed-side-effect.ts +136 -27
- package/src/notifications/signal.ts +0 -4
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +13 -4
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +4 -1
- package/src/plugins/defaults/injectors.ts +118 -26
- package/src/plugins/external-plugin-loader.ts +82 -10
- package/src/plugins/types.ts +16 -7
- package/src/prompts/__tests__/system-prompt.test.ts +44 -45
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +4 -8
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/sections.ts +32 -14
- package/src/prompts/system-prompt.ts +105 -76
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +13 -5
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +51 -10
- package/src/providers/__tests__/inference.test.ts +2 -0
- package/src/providers/anthropic/client.ts +132 -5
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +63 -13
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +24 -21
- package/src/providers/inference/auth.ts +15 -3
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/connections.ts +85 -5
- package/src/providers/inference/resolve-auth.ts +50 -5
- package/src/providers/model-catalog.ts +244 -242
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +215 -25
- package/src/providers/openai/responses-provider.ts +9 -3
- package/src/providers/openrouter/client.ts +46 -4
- package/src/providers/platform-proxy/constants.ts +3 -4
- package/src/providers/provider-catalog-visibility.ts +3 -1
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +30 -1
- package/src/providers/types.ts +25 -0
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +212 -57
- package/src/runtime/auth/route-policy.ts +20 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +7 -51
- package/src/runtime/pending-interactions.ts +51 -8
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +121 -5
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +271 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/channel-availability-routes.ts +5 -0
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +146 -1
- package/src/runtime/routes/conversation-query-routes.ts +130 -12
- package/src/runtime/routes/conversation-routes.ts +288 -76
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +8 -1
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +14 -4
- package/src/runtime/routes/inference-provider-connection-routes.ts +192 -3
- package/src/runtime/routes/integrations/a2a.ts +294 -0
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-v2-routes.ts +217 -0
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/slack-channel-routes.ts +187 -0
- package/src/runtime/routes/subagents-routes.ts +41 -0
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/subagent/manager.ts +2 -0
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +80 -0
- package/src/tools/browser/browser-execution.ts +93 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +10 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +15 -1
- package/src/tools/browser/cdp-client/factory.ts +87 -3
- package/src/tools/browser/cdp-client/local-cdp-client.ts +9 -0
- package/src/tools/browser/cdp-client/types.ts +36 -0
- package/src/tools/browser/pinned-tabs.ts +90 -0
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +128 -2
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +213 -64
- package/src/tools/network/web-search.ts +191 -66
- package/src/tools/registry.ts +2 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/types.ts +41 -2
- package/src/tools/ui-surface/definitions.ts +3 -1
- package/src/types/onboarding-context.ts +4 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/platform.ts +0 -5
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -95,97 +95,6 @@ describe("notification decision fallback copy", () => {
|
|
|
95
95
|
);
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
test("enforces guardian-facing popup copy for heartbeat alerts", async () => {
|
|
99
|
-
configuredProvider = { sendMessage: async () => ({}) };
|
|
100
|
-
extractedToolUse = {
|
|
101
|
-
input: {
|
|
102
|
-
shouldNotify: true,
|
|
103
|
-
selectedChannels: ["vellum"],
|
|
104
|
-
reasoningSummary: "Heartbeat found a useful follow-up.",
|
|
105
|
-
renderedCopy: {
|
|
106
|
-
vellum: {
|
|
107
|
-
title: "Heartbeat Follow-up",
|
|
108
|
-
body: "The daily tracker is ready; consider reminding the guardian to review it before the next check-in.",
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
dedupeKey: "heartbeat:test",
|
|
112
|
-
confidence: 0.9,
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const decision = await evaluateSignal(
|
|
117
|
-
makeSignal({
|
|
118
|
-
sourceEventName: "heartbeat.alert",
|
|
119
|
-
sourceChannel: "watcher",
|
|
120
|
-
contextPayload: {
|
|
121
|
-
summary:
|
|
122
|
-
"The daily tracker is ready; consider reminding the guardian to review it before the next check-in.",
|
|
123
|
-
conversationTitle: "Running Habit Tracking",
|
|
124
|
-
},
|
|
125
|
-
attentionHints: {
|
|
126
|
-
requiresAction: true,
|
|
127
|
-
urgency: "medium",
|
|
128
|
-
isAsyncBackground: true,
|
|
129
|
-
visibleInSourceNow: false,
|
|
130
|
-
},
|
|
131
|
-
}),
|
|
132
|
-
["vellum"] as NotificationChannel[],
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
expect(decision.fallbackUsed).toBe(false);
|
|
136
|
-
expect(decision.renderedCopy.vellum?.title).toBe("Heartbeat Alert");
|
|
137
|
-
expect(decision.renderedCopy.vellum?.body).toBe(
|
|
138
|
-
"I found something worth your attention in a heartbeat check. Open the conversation for details.",
|
|
139
|
-
);
|
|
140
|
-
expect(decision.renderedCopy.vellum?.body).not.toContain(
|
|
141
|
-
"reminding the guardian",
|
|
142
|
-
);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test("keeps direct guardian-facing heartbeat copy", async () => {
|
|
146
|
-
configuredProvider = { sendMessage: async () => ({}) };
|
|
147
|
-
extractedToolUse = {
|
|
148
|
-
input: {
|
|
149
|
-
shouldNotify: true,
|
|
150
|
-
selectedChannels: ["vellum"],
|
|
151
|
-
reasoningSummary: "Heartbeat found a useful follow-up.",
|
|
152
|
-
renderedCopy: {
|
|
153
|
-
vellum: {
|
|
154
|
-
title: "Tracker Ready",
|
|
155
|
-
body: "Your daily tracker is ready. Review it before the next check-in.",
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
dedupeKey: "heartbeat:direct-copy-test",
|
|
159
|
-
confidence: 0.9,
|
|
160
|
-
},
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
const decision = await evaluateSignal(
|
|
164
|
-
makeSignal({
|
|
165
|
-
sourceEventName: "heartbeat.alert",
|
|
166
|
-
sourceChannel: "watcher",
|
|
167
|
-
contextPayload: {
|
|
168
|
-
summary:
|
|
169
|
-
"The daily tracker is ready; consider reminding the guardian to review it before the next check-in.",
|
|
170
|
-
conversationTitle: "Running Habit Tracking",
|
|
171
|
-
},
|
|
172
|
-
attentionHints: {
|
|
173
|
-
requiresAction: true,
|
|
174
|
-
urgency: "medium",
|
|
175
|
-
isAsyncBackground: true,
|
|
176
|
-
visibleInSourceNow: false,
|
|
177
|
-
},
|
|
178
|
-
}),
|
|
179
|
-
["vellum"] as NotificationChannel[],
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
expect(decision.fallbackUsed).toBe(false);
|
|
183
|
-
expect(decision.renderedCopy.vellum?.title).toBe("Tracker Ready");
|
|
184
|
-
expect(decision.renderedCopy.vellum?.body).toBe(
|
|
185
|
-
"Your daily tracker is ready. Review it before the next check-in.",
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
98
|
test("enforces free-text answer instructions for guardian.question when requestCode exists", async () => {
|
|
190
99
|
const signal = makeSignal({
|
|
191
100
|
contextPayload: {
|
|
@@ -147,7 +147,10 @@ describe("notification decision strategy", () => {
|
|
|
147
147
|
expect(copy.telegram!.deliveryText).toBe("Take out the trash");
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
test("unknown event name produces generic copy with
|
|
150
|
+
test("unknown event name produces generic copy with empty body", () => {
|
|
151
|
+
// The event-name-derived body fallback was removed; the deterministic
|
|
152
|
+
// `checkRenderedCopyQuality` check in deterministic-checks.ts will
|
|
153
|
+
// suppress notifications that end up with an empty body.
|
|
151
154
|
const signal = makeSignal({
|
|
152
155
|
sourceEventName: "some_novel.event",
|
|
153
156
|
attentionHints: {
|
|
@@ -161,12 +164,16 @@ describe("notification decision strategy", () => {
|
|
|
161
164
|
const copy = composeFallbackCopy(signal, channels);
|
|
162
165
|
expect(copy.vellum).toBeDefined();
|
|
163
166
|
expect(copy.vellum!.title).toBe("Notification");
|
|
164
|
-
expect(copy.vellum!.body).
|
|
165
|
-
|
|
166
|
-
|
|
167
|
+
expect(copy.vellum!.body).toBe("");
|
|
168
|
+
// Telegram deliveryText falls back to title when body is empty; the
|
|
169
|
+
// checkRenderedCopyQuality check still suppresses on empty body.
|
|
170
|
+
expect(copy.telegram!.body).toBe("");
|
|
167
171
|
});
|
|
168
172
|
|
|
169
|
-
test("unknown event name without urgency produces
|
|
173
|
+
test("unknown event name without urgency also produces empty body", () => {
|
|
174
|
+
// The event-name-derived body fallback was removed; the deterministic
|
|
175
|
+
// `checkRenderedCopyQuality` check in deterministic-checks.ts will
|
|
176
|
+
// suppress notifications that end up with an empty body.
|
|
170
177
|
const signal = makeSignal({
|
|
171
178
|
sourceEventName: "background.sync_complete",
|
|
172
179
|
attentionHints: {
|
|
@@ -179,10 +186,8 @@ describe("notification decision strategy", () => {
|
|
|
179
186
|
|
|
180
187
|
const copy = composeFallbackCopy(signal, channels);
|
|
181
188
|
expect(copy.vellum).toBeDefined();
|
|
182
|
-
expect(copy.vellum!.
|
|
183
|
-
expect(copy.vellum!.body).
|
|
184
|
-
// Dots and underscores in event name are replaced with spaces
|
|
185
|
-
expect(copy.vellum!.body).toContain("background sync complete");
|
|
189
|
+
expect(copy.vellum!.title).toBe("Notification");
|
|
190
|
+
expect(copy.vellum!.body).toBe("");
|
|
186
191
|
});
|
|
187
192
|
|
|
188
193
|
test("fallback copy is generated for every requested channel", () => {
|
|
@@ -373,28 +378,6 @@ describe("notification decision strategy", () => {
|
|
|
373
378
|
"A guardian question needs your attention",
|
|
374
379
|
);
|
|
375
380
|
});
|
|
376
|
-
|
|
377
|
-
test("heartbeat.alert fallback avoids intermediary-instruction popup copy", () => {
|
|
378
|
-
const signal = makeSignal({
|
|
379
|
-
sourceEventName: "heartbeat.alert",
|
|
380
|
-
contextPayload: {
|
|
381
|
-
summary:
|
|
382
|
-
"The daily tracker is ready; consider reminding the guardian to review it before the next check-in.",
|
|
383
|
-
conversationTitle: "Running Habit Tracking",
|
|
384
|
-
},
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
const copy = composeFallbackCopy(signal, channels);
|
|
388
|
-
expect(copy.vellum).toBeDefined();
|
|
389
|
-
expect(copy.vellum!.title).toBe("Heartbeat Alert");
|
|
390
|
-
expect(copy.vellum!.body).toBe(
|
|
391
|
-
"I found something worth your attention in a heartbeat check. Open the conversation for details.",
|
|
392
|
-
);
|
|
393
|
-
expect(copy.vellum!.conversationSeedMessage).toContain(
|
|
394
|
-
"consider reminding the guardian",
|
|
395
|
-
);
|
|
396
|
-
expect(copy.telegram!.deliveryText).toBe(copy.vellum!.body);
|
|
397
|
-
});
|
|
398
381
|
});
|
|
399
382
|
|
|
400
383
|
// -- NotificationChannel type correctness ----------------------------------
|
|
@@ -156,6 +156,7 @@ describe("notification deep-link metadata", () => {
|
|
|
156
156
|
conversationId: "conv-123",
|
|
157
157
|
conversationType: "notification",
|
|
158
158
|
},
|
|
159
|
+
urgency: "medium",
|
|
159
160
|
},
|
|
160
161
|
{ channel: "vellum" },
|
|
161
162
|
);
|
|
@@ -179,6 +180,7 @@ describe("notification deep-link metadata", () => {
|
|
|
179
180
|
{
|
|
180
181
|
sourceEventName: "test.event",
|
|
181
182
|
copy: { title: "Alert", body: "No deep link" },
|
|
183
|
+
urgency: "medium",
|
|
182
184
|
},
|
|
183
185
|
{ channel: "vellum" },
|
|
184
186
|
);
|
|
@@ -199,6 +201,7 @@ describe("notification deep-link metadata", () => {
|
|
|
199
201
|
sourceEventName: "guardian.question",
|
|
200
202
|
copy: { title: "Guardian Question", body: "What is the code?" },
|
|
201
203
|
deepLinkTarget: { conversationId },
|
|
204
|
+
urgency: "medium",
|
|
202
205
|
},
|
|
203
206
|
{ channel: "vellum" },
|
|
204
207
|
);
|
|
@@ -215,6 +218,7 @@ describe("notification deep-link metadata", () => {
|
|
|
215
218
|
{
|
|
216
219
|
sourceEventName: "test.event",
|
|
217
220
|
copy: { title: "T", body: "B" },
|
|
221
|
+
urgency: "medium",
|
|
218
222
|
},
|
|
219
223
|
{ channel: "vellum" },
|
|
220
224
|
);
|
|
@@ -231,6 +235,7 @@ describe("notification deep-link metadata", () => {
|
|
|
231
235
|
{
|
|
232
236
|
sourceEventName: "test.event",
|
|
233
237
|
copy: { title: "T", body: "B" },
|
|
238
|
+
urgency: "medium",
|
|
234
239
|
},
|
|
235
240
|
{ channel: "vellum" },
|
|
236
241
|
);
|
|
@@ -247,6 +252,7 @@ describe("notification deep-link metadata", () => {
|
|
|
247
252
|
{
|
|
248
253
|
sourceEventName: "guardian.question",
|
|
249
254
|
copy: { title: "Alert", body: "Body" },
|
|
255
|
+
urgency: "medium",
|
|
250
256
|
},
|
|
251
257
|
{ channel: "vellum" },
|
|
252
258
|
);
|
|
@@ -268,6 +274,7 @@ describe("notification deep-link metadata", () => {
|
|
|
268
274
|
conversationId: "conv-task-run-42",
|
|
269
275
|
workItemId: "work-item-7",
|
|
270
276
|
},
|
|
277
|
+
urgency: "medium",
|
|
271
278
|
},
|
|
272
279
|
{ channel: "vellum" },
|
|
273
280
|
);
|
|
@@ -287,6 +294,7 @@ describe("notification deep-link metadata", () => {
|
|
|
287
294
|
sourceEventName: "guardian.question",
|
|
288
295
|
copy: { title: "Question", body: "Body" },
|
|
289
296
|
deepLinkTarget: { conversationId: "conv-1", messageId: "msg-1" },
|
|
297
|
+
urgency: "medium",
|
|
290
298
|
},
|
|
291
299
|
{ channel: "vellum" },
|
|
292
300
|
);
|
|
@@ -309,6 +317,7 @@ describe("notification deep-link metadata", () => {
|
|
|
309
317
|
sourceEventName: "schedule.notify",
|
|
310
318
|
copy: { title: "Reminder", body: "Take out the trash" },
|
|
311
319
|
deepLinkTarget: { conversationId: "conv-new-convo-001" },
|
|
320
|
+
urgency: "medium",
|
|
312
321
|
},
|
|
313
322
|
{ channel: "vellum" },
|
|
314
323
|
);
|
|
@@ -332,6 +341,7 @@ describe("notification deep-link metadata", () => {
|
|
|
332
341
|
body: "Still need to take out the trash",
|
|
333
342
|
},
|
|
334
343
|
deepLinkTarget: { conversationId: "conv-reused-convo-042" },
|
|
344
|
+
urgency: "medium",
|
|
335
345
|
},
|
|
336
346
|
{ channel: "vellum" },
|
|
337
347
|
);
|
|
@@ -358,6 +368,7 @@ describe("notification deep-link metadata", () => {
|
|
|
358
368
|
conversationId: stableConversationId,
|
|
359
369
|
messageId: "msg-seed-1",
|
|
360
370
|
},
|
|
371
|
+
urgency: "medium",
|
|
361
372
|
},
|
|
362
373
|
{ channel: "vellum" },
|
|
363
374
|
);
|
|
@@ -371,6 +382,7 @@ describe("notification deep-link metadata", () => {
|
|
|
371
382
|
conversationId: stableConversationId,
|
|
372
383
|
messageId: "msg-seed-2",
|
|
373
384
|
},
|
|
385
|
+
urgency: "medium",
|
|
374
386
|
},
|
|
375
387
|
{ channel: "vellum" },
|
|
376
388
|
);
|
|
@@ -402,6 +414,7 @@ describe("notification deep-link metadata", () => {
|
|
|
402
414
|
sourceEventName: "schedule.notify",
|
|
403
415
|
copy: { title: "Reminder", body: "First" },
|
|
404
416
|
deepLinkTarget: { conversationId, messageId: "msg-a" },
|
|
417
|
+
urgency: "medium",
|
|
405
418
|
},
|
|
406
419
|
{ channel: "vellum" },
|
|
407
420
|
);
|
|
@@ -411,6 +424,7 @@ describe("notification deep-link metadata", () => {
|
|
|
411
424
|
sourceEventName: "schedule.notify",
|
|
412
425
|
copy: { title: "Reminder", body: "Second" },
|
|
413
426
|
deepLinkTarget: { conversationId, messageId: "msg-b" },
|
|
427
|
+
urgency: "medium",
|
|
414
428
|
},
|
|
415
429
|
{ channel: "vellum" },
|
|
416
430
|
);
|
|
@@ -442,6 +456,7 @@ describe("notification deep-link metadata", () => {
|
|
|
442
456
|
sourceEventName: "activity.complete",
|
|
443
457
|
copy: { title: "Activity", body },
|
|
444
458
|
deepLinkTarget: { conversationId: boundConvId },
|
|
459
|
+
urgency: "medium",
|
|
445
460
|
},
|
|
446
461
|
{ channel: "vellum" },
|
|
447
462
|
);
|
|
@@ -31,8 +31,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
31
31
|
}),
|
|
32
32
|
}));
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
34
|
const emitCalls: unknown[] = [];
|
|
37
35
|
let mockConversationCreated: ConversationCreatedInfo | null = null;
|
|
38
36
|
let mockEmitResult: {
|
|
@@ -189,6 +187,7 @@ describe("ASK_GUARDIAN canonical notification path", () => {
|
|
|
189
187
|
conversationId: "conv-from-thread-callback",
|
|
190
188
|
title: "Guardian question",
|
|
191
189
|
sourceEventName: "guardian.question",
|
|
190
|
+
silent: false,
|
|
192
191
|
};
|
|
193
192
|
mockEmitResult = {
|
|
194
193
|
signalId: "sig-2",
|
|
@@ -37,7 +37,8 @@ interface FetchCall {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const fetchCalls: FetchCall[] = [];
|
|
40
|
-
const fetchResponses: Array<{ ok: boolean; status: number; body?: string }> =
|
|
40
|
+
const fetchResponses: Array<{ ok: boolean; status: number; body?: string }> =
|
|
41
|
+
[];
|
|
41
42
|
let clientAvailable = true;
|
|
42
43
|
|
|
43
44
|
mock.module("../platform/client.js", () => ({
|
|
@@ -84,6 +85,7 @@ function makePayload(
|
|
|
84
85
|
copy: { title: "Reminder", body: "Check the oven!" },
|
|
85
86
|
deepLinkTarget: { type: "conversation", id: "conv-1" },
|
|
86
87
|
contextPayload: { jobId: "job-1" },
|
|
88
|
+
urgency: "medium",
|
|
87
89
|
...overrides,
|
|
88
90
|
};
|
|
89
91
|
}
|
|
@@ -118,9 +120,7 @@ describe("PlatformPushAdapter", () => {
|
|
|
118
120
|
expect(fetchCalls).toHaveLength(1);
|
|
119
121
|
|
|
120
122
|
const call = fetchCalls[0]!;
|
|
121
|
-
expect(call.path).toBe(
|
|
122
|
-
"/v1/assistants/test-assistant-id/push/dispatch/",
|
|
123
|
-
);
|
|
123
|
+
expect(call.path).toBe("/v1/assistants/test-assistant-id/push/dispatch/");
|
|
124
124
|
expect(call.method).toBe("POST");
|
|
125
125
|
expect(call.body.delivery_id).toBe("delivery-uuid-1");
|
|
126
126
|
expect(call.body.source_event_name).toBe("schedule.notify");
|
|
@@ -216,6 +216,7 @@ describe("PlatformPushAdapter", () => {
|
|
|
216
216
|
const payload: ChannelDeliveryPayload = {
|
|
217
217
|
sourceEventName: "schedule.notify",
|
|
218
218
|
copy: { title: "Hi", body: "Hello" },
|
|
219
|
+
urgency: "medium",
|
|
219
220
|
};
|
|
220
221
|
|
|
221
222
|
const result = await adapter.send(payload, makeDestination());
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
4
|
+
import { VellumAdapter } from "../notifications/adapters/macos.js";
|
|
5
|
+
import type {
|
|
6
|
+
ChannelDeliveryPayload,
|
|
7
|
+
ChannelDestination,
|
|
8
|
+
} from "../notifications/types.js";
|
|
9
|
+
|
|
10
|
+
function makePayload(
|
|
11
|
+
overrides?: Partial<ChannelDeliveryPayload>,
|
|
12
|
+
): ChannelDeliveryPayload {
|
|
13
|
+
return {
|
|
14
|
+
deliveryId: "delivery-uuid-1",
|
|
15
|
+
sourceEventName: "schedule.notify",
|
|
16
|
+
copy: { title: "Reminder", body: "Hello" },
|
|
17
|
+
urgency: "medium",
|
|
18
|
+
...overrides,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function makeDestination(
|
|
23
|
+
overrides?: Partial<ChannelDestination>,
|
|
24
|
+
): ChannelDestination {
|
|
25
|
+
return {
|
|
26
|
+
channel: "vellum",
|
|
27
|
+
...overrides,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function captureBroadcast(): {
|
|
32
|
+
adapter: VellumAdapter;
|
|
33
|
+
sent: ServerMessage[];
|
|
34
|
+
} {
|
|
35
|
+
const sent: ServerMessage[] = [];
|
|
36
|
+
const adapter = new VellumAdapter((msg) => sent.push(msg));
|
|
37
|
+
return { adapter, sent };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe("VellumAdapter silent flag", () => {
|
|
41
|
+
test("non-urgent (low) urgency broadcasts silent: true", async () => {
|
|
42
|
+
const { adapter, sent } = captureBroadcast();
|
|
43
|
+
const result = await adapter.send(
|
|
44
|
+
makePayload({ urgency: "low" }),
|
|
45
|
+
makeDestination(),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(result.success).toBe(true);
|
|
49
|
+
expect(sent).toHaveLength(1);
|
|
50
|
+
const intent = sent[0] as Extract<
|
|
51
|
+
ServerMessage,
|
|
52
|
+
{ type: "notification_intent" }
|
|
53
|
+
>;
|
|
54
|
+
expect(intent.type).toBe("notification_intent");
|
|
55
|
+
expect(intent.silent).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("non-urgent (medium) urgency broadcasts silent: true", async () => {
|
|
59
|
+
const { adapter, sent } = captureBroadcast();
|
|
60
|
+
await adapter.send(makePayload({ urgency: "medium" }), makeDestination());
|
|
61
|
+
|
|
62
|
+
const intent = sent[0] as Extract<
|
|
63
|
+
ServerMessage,
|
|
64
|
+
{ type: "notification_intent" }
|
|
65
|
+
>;
|
|
66
|
+
expect(intent.silent).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("urgent (high) urgency broadcasts silent: false", async () => {
|
|
70
|
+
const { adapter, sent } = captureBroadcast();
|
|
71
|
+
await adapter.send(makePayload({ urgency: "high" }), makeDestination());
|
|
72
|
+
|
|
73
|
+
const intent = sent[0] as Extract<
|
|
74
|
+
ServerMessage,
|
|
75
|
+
{ type: "notification_intent" }
|
|
76
|
+
>;
|
|
77
|
+
expect(intent.silent).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("critical urgency broadcasts silent: false", async () => {
|
|
81
|
+
const { adapter, sent } = captureBroadcast();
|
|
82
|
+
await adapter.send(makePayload({ urgency: "critical" }), makeDestination());
|
|
83
|
+
|
|
84
|
+
const intent = sent[0] as Extract<
|
|
85
|
+
ServerMessage,
|
|
86
|
+
{ type: "notification_intent" }
|
|
87
|
+
>;
|
|
88
|
+
expect(intent.silent).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("broadcasts title, body, deepLinkTarget, and deliveryId verbatim", async () => {
|
|
92
|
+
const { adapter, sent } = captureBroadcast();
|
|
93
|
+
await adapter.send(
|
|
94
|
+
makePayload({
|
|
95
|
+
deliveryId: "delivery-xyz",
|
|
96
|
+
copy: { title: "T", body: "B" },
|
|
97
|
+
deepLinkTarget: { conversationId: "conv-abc" },
|
|
98
|
+
urgency: "high",
|
|
99
|
+
}),
|
|
100
|
+
makeDestination(),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const intent = sent[0] as Extract<
|
|
104
|
+
ServerMessage,
|
|
105
|
+
{ type: "notification_intent" }
|
|
106
|
+
>;
|
|
107
|
+
expect(intent.deliveryId).toBe("delivery-xyz");
|
|
108
|
+
expect(intent.title).toBe("T");
|
|
109
|
+
expect(intent.body).toBe("B");
|
|
110
|
+
expect(intent.deepLinkMetadata).toEqual({ conversationId: "conv-abc" });
|
|
111
|
+
expect(intent.silent).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|