@vellumai/assistant 0.12.3-staging.1 → 0.12.3-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +43 -29
- package/Dockerfile +63 -0
- package/docs/architecture/security.md +10 -5
- package/docs/architecture/turn-actor.md +2 -0
- package/docs/desktop-browser-cli.md +45 -4
- package/docs/live-voice-task-outcomes.md +100 -0
- package/docs/mode-sessions.md +183 -0
- package/docs/voice-input-diagnostics.md +58 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -1
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +38 -7
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +5 -6
- package/node_modules/@vellumai/service-contracts/package.json +2 -1
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/integration-categories.ts +36 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +4 -8
- package/openapi.yaml +665 -14
- package/package.json +1 -1
- package/scripts/smoke-desktop-browser-cli.ts +10 -26
- package/scripts/smoke-desktop-window-theme.ts +2 -3
- package/src/__tests__/agent-loop-output-hooks.test.ts +150 -1
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +87 -19
- package/src/__tests__/annotate-activity-metadata.test.ts +3 -1
- package/src/__tests__/annotate-risk-options.test.ts +2 -0
- package/src/__tests__/answered-question-persistence.test.ts +2 -0
- package/src/__tests__/anthropic-gateway-shared.test.ts +22 -0
- package/src/__tests__/approval-message-composer.test.ts +1 -118
- package/src/__tests__/approval-routes-http.test.ts +3 -0
- package/src/__tests__/assistant-event-hub-connection-history.test.ts +111 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +50 -0
- package/src/__tests__/assistant-event-targeting.test.ts +186 -0
- package/src/__tests__/assistant-stream-state.test.ts +29 -9
- package/src/__tests__/browser-fill-credential.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +4 -1
- package/src/__tests__/build-persisted-content.test.ts +1 -1
- package/src/__tests__/call-conversation-messages.test.ts +5 -0
- package/src/__tests__/call-recovery.test.ts +7 -2
- package/src/__tests__/call-routes-http.test.ts +12 -0
- package/src/__tests__/call-store.test.ts +7 -2
- package/src/__tests__/channel-retry-sweep.test.ts +9 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +2 -0
- package/src/__tests__/checker.test.ts +11 -3
- package/src/__tests__/client-os-metadata-persistence.test.ts +35 -1
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -25
- package/src/__tests__/computer-use-tools.test.ts +1 -233
- package/src/__tests__/config-model-image-provider.test.ts +39 -0
- package/src/__tests__/config-schema.test.ts +16 -0
- package/src/__tests__/config-watcher.test.ts +24 -0
- package/src/__tests__/context-search-agent-runner.test.ts +260 -1
- package/src/__tests__/context-search-fanout.test.ts +1 -1
- package/src/__tests__/context-search-types.test.ts +7 -7
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +8 -2
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +546 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +53 -1
- package/src/__tests__/conversation-evictor.test.ts +62 -37
- package/src/__tests__/conversation-history-boundary-repair-failure.test.ts +174 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +2 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
- package/src/__tests__/conversation-retry-route.test.ts +22 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +2 -0
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +2 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +10 -0
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +2 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -0
- package/src/__tests__/conversation-surface-snapshots.test.ts +543 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +151 -0
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +63 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +23 -0
- package/src/__tests__/conversation-undo.test.ts +61 -0
- package/src/__tests__/credential-execution-client.test.ts +6 -6
- package/src/__tests__/credential-prompt-route.test.ts +35 -3
- package/src/__tests__/cu-unified-flow.test.ts +82 -1
- package/src/__tests__/db-mode-sessions-migration.test.ts +175 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -0
- package/src/__tests__/dm-backfill.test.ts +91 -1
- package/src/__tests__/document-create-route.test.ts +88 -0
- package/src/__tests__/document-sync-tags.test.ts +27 -0
- package/src/__tests__/emit-signal-routing-intent.test.ts +142 -2
- package/src/__tests__/events-tail-route.test.ts +25 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +57 -8
- package/src/__tests__/guardian-action-sweep.test.ts +16 -0
- package/src/__tests__/guardian-dispatch.test.ts +13 -0
- package/src/__tests__/headless-browser-interactions.test.ts +64 -20
- package/src/__tests__/heartbeat-service.test.ts +2 -59
- package/src/__tests__/helpers/mock-conversation.ts +21 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +2 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +5 -0
- package/src/__tests__/host-cu-proxy.test.ts +46 -2
- package/src/__tests__/http-user-message-parity.test.ts +2 -0
- package/src/__tests__/image-credentials.test.ts +49 -0
- package/src/__tests__/image-service-dispatcher.test.ts +45 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
- package/src/__tests__/interrupt-on-send.test.ts +57 -43
- package/src/__tests__/interrupt-turn-note.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +49 -1
- package/src/__tests__/message-provenance-contact-id.test.ts +69 -0
- package/src/__tests__/migration-export-to-gcs.test.ts +142 -0
- package/src/__tests__/mode-session-history.test.ts +245 -0
- package/src/__tests__/mode-session-recovery.test.ts +222 -0
- package/src/__tests__/mode-session-wire.test.ts +141 -0
- package/src/__tests__/notification-guardian-path.test.ts +7 -0
- package/src/__tests__/notification-telegram-adapter.test.ts +2 -2
- package/src/__tests__/notification-vellum-adapter.test.ts +34 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +12 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
- package/src/__tests__/plugin-api-provider.test.ts +5 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +97 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +9 -0
- package/src/__tests__/process-message-display-content.test.ts +56 -0
- package/src/__tests__/reaction-persistence.test.ts +5 -0
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +25 -9
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/scripted-turn-metadata-persistence.test.ts +73 -0
- package/src/__tests__/secret-ingress-http.test.ts +2 -0
- package/src/__tests__/secure-keys.test.ts +43 -1
- package/src/__tests__/send-endpoint-busy.test.ts +163 -1
- package/src/__tests__/server-history-render.test.ts +91 -1
- package/src/__tests__/settings-routes.test.ts +50 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +32 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +1 -2
- package/src/__tests__/subagent-manager-notify.test.ts +1 -2
- package/src/__tests__/subagent-notify-parent.test.ts +146 -39
- package/src/__tests__/subagent-notify-stale-rebuild.test.ts +2 -4
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +2 -0
- package/src/__tests__/thread-backfill.test.ts +53 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +3 -1
- package/src/__tests__/tool-start-timestamp.test.ts +2 -0
- package/src/__tests__/twilio-routes.test.ts +1 -0
- package/src/__tests__/web-search-backend-failure.test.ts +1 -1
- package/src/activation/progress-store.test.ts +12 -7
- package/src/agent/loop.ts +99 -41
- package/src/api/events/assistant-turn-start.ts +3 -0
- package/src/api/events/generation-handoff.ts +2 -0
- package/src/api/events/message-complete.ts +2 -0
- package/src/api/events/notification-conversation-created.ts +14 -16
- package/src/api/events/notification-intent.ts +4 -2
- package/src/api/events/tool-result.ts +85 -0
- package/src/api/events/tool-use-start.ts +3 -0
- package/src/api/events/user-message-echo.ts +3 -0
- package/src/api/index.ts +31 -6
- package/src/api/mode-session.test.ts +131 -0
- package/src/api/mode-session.ts +148 -0
- package/src/api/remember-tool.ts +15 -0
- package/src/api/responses/conversation-message.ts +6 -0
- package/src/approvals/AGENTS.md +4 -2
- package/src/browser/__tests__/operations.test.ts +29 -0
- package/src/browser/operation-meta.ts +2 -1
- package/src/browser/operations.ts +29 -0
- package/src/browser/virtual-desktop-target.ts +2 -8
- package/src/bundler/bundle-signer.ts +1 -3
- package/src/calls/__tests__/barge-in-guard.test.ts +3 -0
- package/src/calls/__tests__/call-controller.test.ts +94 -0
- package/src/calls/__tests__/call-funnel-telemetry.test.ts +204 -0
- package/src/calls/__tests__/voice-control-protocol.test.ts +15 -0
- package/src/calls/__tests__/voice-escalation-judge.test.ts +209 -0
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +168 -0
- package/src/{live-voice/__tests__/live-voice-metrics.test.ts → calls/__tests__/voice-metrics.test.ts} +32 -38
- package/src/calls/__tests__/voice-session-bridge.test.ts +576 -122
- package/src/calls/barge-in-guard.ts +5 -0
- package/src/calls/call-controller.ts +196 -1
- package/src/calls/call-domain.ts +4 -0
- package/src/calls/call-store.ts +87 -2
- package/src/calls/guardian-action-sweep.ts +22 -8
- package/src/calls/media-stream-audio-transcode.ts +1 -3
- package/src/calls/typesafe-noul.ts +156 -0
- package/src/calls/voice-control-protocol.ts +6 -0
- package/src/calls/voice-escalation-judge.ts +145 -0
- package/src/calls/voice-escalation-target.ts +10 -0
- package/src/calls/voice-leg-coordinator.ts +121 -3
- package/src/{live-voice/live-voice-metrics.ts → calls/voice-metrics.ts} +94 -87
- package/src/calls/voice-session-bridge.ts +256 -112
- package/src/calls/voice-triage-escalate.ts +7 -0
- package/src/cli/__tests__/roadmap-cli.test.ts +4 -41
- package/src/cli/commands/__tests__/notifications.test.ts +35 -10
- package/src/cli/commands/browser.help.ts +4 -5
- package/src/cli/commands/browser.ts +0 -1
- package/src/cli/commands/clients.help.ts +46 -0
- package/src/cli/commands/clients.ts +116 -0
- package/src/cli/commands/credentials.help.ts +6 -1
- package/src/cli/commands/notifications.help.ts +16 -2
- package/src/cli/commands/notifications.ts +30 -8
- package/src/cli/commands/roadmap.help.ts +18 -21
- package/src/cli/commands/roadmap.ts +4 -21
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +5 -2
- package/src/cli/lib/bundled-marketplace.json +84 -34
- package/src/cli/lib/plugin-marketplace.ts +8 -0
- package/src/cli/lib/publish-plugin.ts +1 -2
- package/src/config/__tests__/default-provider.test.ts +3 -1
- package/src/config/__tests__/memory-retrospective-schema.test.ts +14 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +89 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +17 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -11
- package/src/config/bundled-skills/sequences/TOOLS.json +1 -5
- package/src/config/call-site-defaults.ts +9 -0
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/profile-text-generation.test.ts +2 -2
- package/src/config/schemas/__tests__/tools.test.ts +31 -0
- package/src/config/schemas/call-site-catalog.ts +14 -0
- package/src/config/schemas/channels.ts +0 -18
- package/src/config/schemas/llm.ts +3 -1
- package/src/config/schemas/mcp.ts +2 -1
- package/src/config/schemas/memory-retrospective.ts +11 -2
- package/src/config/schemas/services.ts +15 -6
- package/src/config/schemas/tools.ts +10 -0
- package/src/config/session-groups-gate.ts +21 -0
- package/src/config/skills.ts +2 -6
- package/src/conversations/__tests__/message-consolidation.test.ts +149 -0
- package/src/conversations/message-consolidation.ts +102 -5
- package/src/credential-execution/ces-connect.test.ts +69 -0
- package/src/credential-execution/ces-connect.ts +115 -0
- package/src/credential-execution/ces-runtime.ts +55 -93
- package/src/credential-execution/executable-discovery.ts +1 -11
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +10 -1
- package/src/daemon/__tests__/inference-profile-notification.test.ts +2 -0
- package/src/daemon/browser-mode-session.test.ts +402 -0
- package/src/daemon/browser-mode-session.ts +186 -0
- package/src/daemon/computer-use-mode-session.test.ts +210 -0
- package/src/daemon/computer-use-mode-session.ts +105 -0
- package/src/daemon/config-watcher.ts +10 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +58 -10
- package/src/daemon/conversation-agent-loop.ts +219 -25
- package/src/daemon/conversation-evictor.ts +5 -24
- package/src/daemon/conversation-history.ts +10 -0
- package/src/daemon/conversation-interrupt-repair.ts +4 -43
- package/src/daemon/conversation-interrupt.ts +7 -11
- package/src/daemon/conversation-messaging.ts +58 -5
- package/src/daemon/conversation-mode-session.test.ts +1667 -0
- package/src/daemon/conversation-mode-session.ts +1008 -0
- package/src/daemon/conversation-process.ts +5 -0
- package/src/daemon/conversation-runtime-assembly.ts +10 -20
- package/src/daemon/conversation-skill-tools.ts +1 -0
- package/src/daemon/conversation-store.ts +4 -4
- package/src/daemon/conversation-surface-snapshots.ts +135 -0
- package/src/daemon/conversation-surfaces.ts +113 -5
- package/src/daemon/conversation-tool-setup.ts +8 -3
- package/src/daemon/conversation.ts +143 -41
- package/src/daemon/handlers/config-model.ts +7 -5
- package/src/daemon/handlers/shared.ts +55 -16
- package/src/daemon/host-cu-proxy.ts +51 -22
- package/src/daemon/lifecycle.ts +30 -13
- package/src/daemon/message-protocol.ts +0 -1
- package/src/daemon/message-provenance.ts +28 -4
- package/src/daemon/mode-session-startup-recovery.ts +23 -0
- package/src/daemon/mode-session-tracking.ts +54 -0
- package/src/daemon/process-message.ts +13 -4
- package/src/daemon/virtual-desktop-context.ts +21 -0
- package/src/desktop/__tests__/fake-desktop.ts +1 -0
- package/src/desktop/desktop-accessibility-script.ts +88 -0
- package/src/desktop/desktop-accessibility.test.ts +160 -0
- package/src/desktop/desktop-accessibility.ts +169 -0
- package/src/desktop/desktop-automation-lease.test.ts +76 -68
- package/src/desktop/desktop-automation-lease.ts +41 -50
- package/src/desktop/desktop-browser-endpoint.ts +4 -0
- package/src/desktop/desktop-computer-use-routing.test.ts +330 -0
- package/src/desktop/desktop-computer-use.test.ts +449 -0
- package/src/desktop/desktop-computer-use.ts +502 -0
- package/src/desktop/desktop-dependencies.ts +47 -293
- package/src/desktop/desktop-display.ts +2 -2
- package/src/desktop/desktop-panel-config.test.ts +13 -3
- package/src/desktop/desktop-panel-config.ts +109 -15
- package/src/desktop/desktop-session-manager.test.ts +69 -21
- package/src/desktop/desktop-session-manager.ts +76 -22
- package/src/desktop/desktop-stream-bridge.test.ts +11 -122
- package/src/desktop/desktop-stream-bridge.ts +6 -8
- package/src/desktop/desktop-window-theme.ts +5 -25
- package/src/desktop/virtual-desktop-feature.ts +52 -2
- package/src/desktop/virtual-desktop-platform.test.ts +5 -9
- package/src/documents/document-store.ts +23 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +22 -26
- package/src/heartbeat/heartbeat-service.ts +5 -33
- package/src/ipc/__tests__/browser-ipc.test.ts +215 -6
- package/src/ipc/assistant-server.ts +2 -0
- package/src/ipc/routes/__tests__/channel-reply-ipc-routes.test.ts +111 -0
- package/src/ipc/routes/channel-reply-ipc-routes.ts +73 -0
- package/src/live-voice/__tests__/continuation-judge.test.ts +151 -0
- package/src/live-voice/__tests__/live-activity-reporter.test.ts +154 -15
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +743 -31
- package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +191 -10
- package/src/live-voice/__tests__/live-voice-session-groups-gate.test.ts +87 -0
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +5 -1
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +41 -0
- package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +1017 -9
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +224 -1
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +101 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +44 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +939 -75
- package/src/live-voice/__tests__/microphone-idle-gate.test.ts +87 -0
- package/src/live-voice/__tests__/session-controls.test.ts +23 -0
- package/src/live-voice/__tests__/task-outcomes.test.ts +117 -0
- package/src/live-voice/__tests__/voice-input-diagnostics.test.ts +117 -0
- package/src/live-voice/camera-mode-session.test.ts +265 -0
- package/src/live-voice/camera-mode-session.ts +277 -0
- package/src/live-voice/continuation-judge.ts +123 -0
- package/src/live-voice/live-activity-reporter.ts +115 -6
- package/src/live-voice/live-voice-manager.ts +36 -1
- package/src/live-voice/live-voice-photo.ts +88 -7
- package/src/live-voice/live-voice-session-manager.ts +15 -0
- package/src/live-voice/live-voice-session.ts +1443 -747
- package/src/live-voice/live-voice-tts.ts +22 -4
- package/src/live-voice/microphone-idle-gate.ts +56 -0
- package/src/live-voice/protocol.ts +171 -4
- package/src/live-voice/session-controls.ts +11 -3
- package/src/live-voice/task-outcomes.ts +131 -0
- package/src/live-voice/voice-input-diagnostics.ts +117 -0
- package/src/mcp/__tests__/manager-tool-caps.test.ts +63 -18
- package/src/mcp/__tests__/tool-caps.test.ts +28 -1
- package/src/mcp/manager.ts +3 -0
- package/src/mcp/tool-caps.ts +12 -4
- package/src/media/__tests__/image-models.test.ts +58 -0
- package/src/media/image-credentials.ts +5 -0
- package/src/media/image-models.ts +52 -0
- package/src/media/image-service.ts +8 -0
- package/src/media/openrouter-image-service.test.ts +133 -0
- package/src/media/openrouter-image-service.ts +153 -0
- package/src/media/types.ts +1 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +65 -11
- package/src/messaging/providers/discord/send.ts +4 -17
- package/src/messaging/providers/discord/transport.ts +2 -2
- package/src/messaging/providers/outlook/client.ts +16 -22
- package/src/messaging/providers/telegram-bot/send.test.ts +236 -1
- package/src/messaging/providers/telegram-bot/send.ts +10 -7
- package/src/messaging/providers/telegram-bot/transport.ts +3 -10
- package/src/messaging/providers/whatsapp/send.test.ts +169 -4
- package/src/monitoring/__tests__/control.test.ts +17 -5
- package/src/monitoring/control.ts +15 -5
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/README.md +83 -99
- package/src/notifications/__tests__/broadcaster.test.ts +1 -1
- package/src/notifications/__tests__/channel-allowlist.test.ts +39 -0
- package/src/notifications/__tests__/copy-composer.test.ts +1 -1
- package/src/notifications/__tests__/decision-engine.test.ts +79 -2
- package/src/notifications/__tests__/deterministic-checks.test.ts +10 -10
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +93 -4
- package/src/notifications/__tests__/notification-utils.test.ts +18 -0
- package/src/notifications/adapters/macos.ts +37 -46
- package/src/notifications/broadcaster.ts +5 -6
- package/src/notifications/channel-allowlist.ts +44 -0
- package/src/notifications/copy-composer.ts +0 -23
- package/src/notifications/decision-engine.ts +24 -14
- package/src/notifications/deterministic-checks.ts +1 -1
- package/src/notifications/emit-signal.ts +123 -37
- package/src/notifications/home-feed-side-effect.ts +9 -7
- package/src/notifications/notification-utils.ts +19 -0
- package/src/notifications/signal.ts +4 -19
- package/src/notifications/types.ts +15 -0
- package/src/oauth/connection-resolver.ts +1 -2
- package/src/oauth/oauth-store.ts +1 -3
- package/src/oauth/provider-serializer.ts +7 -0
- package/src/oauth/seed-providers.ts +30 -0
- package/src/onboarding/onboarding-events-store.ts +99 -12
- package/src/persistence/__tests__/client-connection-events-store.test.ts +322 -0
- package/src/persistence/client-connection-events-store.ts +377 -0
- package/src/persistence/conversation-crud.ts +55 -6
- package/src/persistence/conversation-mode-sessions.test.ts +424 -0
- package/src/persistence/conversation-mode-sessions.ts +460 -0
- package/src/persistence/conversation-queries.ts +6 -19
- package/src/persistence/llm-usage-store.ts +3 -9
- package/src/persistence/message-metadata.ts +25 -0
- package/src/persistence/migrations/381-create-conversation-mode-sessions.ts +41 -0
- package/src/persistence/migrations/382-create-client-connection-events.ts +40 -0
- package/src/persistence/migrations/__tests__/382-create-client-connection-events.test.ts +56 -0
- package/src/persistence/schema/conversations.ts +67 -0
- package/src/persistence/schema/infrastructure.ts +29 -0
- package/src/persistence/steps.ts +17 -0
- package/src/plugin-api/__tests__/plugin-name-env.test.ts +249 -0
- package/src/plugin-api/effective-context-window.ts +33 -0
- package/src/plugin-api/index.ts +24 -5
- package/src/plugin-api/plugin-name-env.ts +125 -0
- package/src/plugin-api/resolve-credential.ts +79 -20
- package/src/plugin-api/vision-support.test.ts +22 -0
- package/src/plugin-api/vision-support.ts +17 -5
- package/src/plugins/__tests__/active-plugin-env.test.ts +136 -0
- package/src/plugins/active-plugin-env.ts +51 -0
- package/src/plugins/defaults/index.ts +24 -0
- package/src/plugins/defaults/memory/__tests__/archive-removal-framing.test.ts +64 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +19 -6
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +9 -12
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +78 -22
- package/src/plugins/defaults/memory/context-search/format.ts +51 -7
- package/src/plugins/defaults/memory/context-search/limits.ts +10 -12
- package/src/plugins/defaults/memory/context-search/recall-input.ts +38 -0
- package/src/plugins/defaults/memory/context-search/search.ts +8 -14
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +1 -0
- package/src/plugins/defaults/memory/context-search/types.ts +1 -11
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +11 -4
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +12 -21
- package/src/plugins/defaults/memory/graph/tools.ts +35 -64
- package/src/plugins/defaults/memory/src/memory-eval-routes.ts +2 -3
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +5 -0
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +2 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +2 -2
- package/src/plugins/defaults/memory/tools.test.ts +124 -9
- package/src/plugins/defaults/memory/tools.ts +38 -11
- package/src/plugins/defaults/memory/v3/__tests__/pool-log-store.test.ts +165 -27
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +626 -27
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +46 -27
- package/src/plugins/defaults/memory/v3/orchestrate.ts +78 -38
- package/src/plugins/defaults/memory/v3/pool-log-store.ts +65 -79
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/pool-select.ts +683 -44
- package/src/plugins/defaults/memory/worker-control.ts +15 -5
- package/src/plugins/defaults/task-progress/__tests__/registration.test.ts +70 -0
- package/src/plugins/defaults/task-progress/__tests__/task-progress-context.test.ts +380 -0
- package/src/plugins/defaults/task-progress/hooks/post-compact.ts +19 -0
- package/src/plugins/defaults/task-progress/hooks/user-prompt-submit.ts +24 -0
- package/src/plugins/defaults/task-progress/package.json +14 -0
- package/src/plugins/defaults/task-progress/src/apply-task-progress-context.ts +93 -0
- package/src/plugins/defaults/task-progress/src/format-task-progress-context.ts +67 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +10 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +18 -0
- package/src/providers/anthropic/client.ts +10 -1
- package/src/providers/anthropic-gateway-shared.ts +6 -0
- package/src/providers/fetch-provider-catalog.ts +11 -0
- package/src/providers/gemini/client.ts +25 -8
- package/src/providers/inference/adapter-factory.ts +1 -1
- package/src/providers/jev/client.test.ts +10 -0
- package/src/providers/jev/client.ts +20 -4
- package/src/providers/model-catalog.ts +4 -3
- package/src/providers/openai/__tests__/chat-completions-extra-body.test.ts +94 -1
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +106 -1
- package/src/providers/openai/__tests__/chat-template-flatten.test.ts +24 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +1 -2
- package/src/providers/openai/chat-completions-provider.ts +100 -29
- package/src/providers/openai/google-thought-signature.ts +0 -6
- package/src/providers/openai/responses-provider.ts +23 -1
- package/src/providers/ratelimit.ts +1 -3
- package/src/providers/search-provider-catalog.ts +24 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +24 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +7 -1
- package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +50 -1
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +11 -0
- package/src/providers/speech-to-text/vellum-managed-flux-realtime.ts +13 -0
- package/src/providers/types.ts +5 -0
- package/src/routes/control.ts +7 -5
- package/src/runtime/AGENTS.md +4 -2
- package/src/runtime/actor-trust-resolver.ts +3 -3
- package/src/runtime/agent-wake.ts +1 -1
- package/src/runtime/approval-message-composer.ts +3 -69
- package/src/runtime/assistant-event-hub.ts +73 -75
- package/src/runtime/assistant-event-publish-options.ts +7 -0
- package/src/runtime/assistant-event-targeting.ts +79 -0
- package/src/runtime/assistant-stream-state.ts +13 -100
- package/src/runtime/background-job-runner.ts +5 -5
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/guardian-action-message-composer.ts +8 -161
- package/src/runtime/guardian-reply-router.ts +28 -32
- package/src/runtime/http-types.ts +6 -0
- package/src/runtime/message-composer-types.ts +3 -61
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +67 -1
- package/src/runtime/migrations/vbundle-builder.ts +24 -1
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -4
- package/src/runtime/migrations/vbundle-import-policy.ts +10 -0
- package/src/runtime/migrations/vbundle-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +4 -1
- package/src/runtime/migrations/vbundle-validator.ts +1 -0
- package/src/runtime/pending-interactions-mode-session.test.ts +62 -0
- package/src/runtime/pending-interactions.ts +29 -0
- package/src/runtime/routes/__tests__/client-history-routes.test.ts +104 -0
- package/src/runtime/routes/__tests__/image-generation-routes.test.ts +97 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/roadmap-routes.test.ts +29 -6
- package/src/runtime/routes/browser-context.ts +31 -11
- package/src/runtime/routes/browser-routes.ts +43 -4
- package/src/runtime/routes/btw-routes.ts +9 -4
- package/src/runtime/routes/client-routes.ts +108 -0
- package/src/runtime/routes/conversation-management-routes.ts +4 -1
- package/src/runtime/routes/conversation-routes.ts +113 -27
- package/src/runtime/routes/credential-prompt-routes.ts +4 -3
- package/src/runtime/routes/credential-routes.ts +1 -2
- package/src/runtime/routes/desktop-setup-routes.test.ts +9 -18
- package/src/runtime/routes/desktop-setup-routes.ts +4 -6
- package/src/runtime/routes/documents-routes.ts +51 -0
- package/src/runtime/routes/email-routes.ts +3 -7
- package/src/runtime/routes/events-routes.ts +75 -54
- package/src/runtime/routes/identity-routes.ts +1 -5
- package/src/runtime/routes/image-generation-routes.ts +8 -14
- package/src/runtime/routes/inbound-message-handler.ts +35 -38
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.test.ts +168 -0
- package/src/runtime/routes/inbound-stages/backfill-sender-provenance.ts +96 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +38 -9
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +2 -5
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +2 -0
- package/src/runtime/routes/llm-context-normalization.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +73 -2
- package/src/runtime/routes/notification-routes.ts +10 -0
- package/src/runtime/routes/oauth-providers.ts +7 -0
- package/src/runtime/routes/plugins-routes.ts +6 -0
- package/src/runtime/routes/roadmap-routes.ts +47 -8
- package/src/runtime/routes/secret-routes.ts +1 -1
- package/src/runtime/routes/settings-routes.ts +10 -4
- package/src/runtime/routes/watcher-routes.ts +1 -3
- package/src/runtime/trust-class.test.ts +7 -6
- package/src/runtime/trust-class.ts +9 -17
- package/src/schedule/__tests__/worker-control.test.ts +36 -5
- package/src/schedule/worker-control.ts +15 -5
- package/src/security/secure-keys.ts +53 -103
- package/src/skills/clawhub.ts +3 -8
- package/src/skills/managed-store.ts +1 -5
- package/src/stt/types.ts +4 -0
- package/src/subagent/notify.ts +54 -34
- package/src/subagent/parent-notification.ts +6 -0
- package/src/telemetry/__tests__/phone-call-funnel.test.ts +72 -0
- package/src/telemetry/phone-call-funnel.ts +144 -0
- package/src/tools/__tests__/tool-schema-root-combinator-guard.test.ts +81 -0
- package/src/tools/ask-question/ask-question-tool.ts +6 -4
- package/src/tools/browser/browser-execution.ts +22 -59
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +561 -39
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +435 -39
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +1 -8
- package/src/tools/client-os.ts +15 -0
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
- package/src/tools/computer-use/target.ts +42 -0
- package/src/tools/document/document-tool.ts +13 -18
- package/src/tools/execution-target.ts +14 -16
- package/src/tools/host-terminal/host-shell.ts +4 -1
- package/src/tools/network/__tests__/web-fetch-tinyfish.test.ts +250 -0
- package/src/tools/network/__tests__/web-search.test.ts +203 -0
- package/src/tools/network/web-fetch.ts +274 -7
- package/src/tools/network/web-search.ts +468 -6
- package/src/tools/permission-checker.ts +3 -3
- package/src/tools/policy-context.ts +3 -1
- package/src/tools/skills/load.ts +2 -1
- package/src/tools/skills/sandbox-runner.ts +11 -2
- package/src/tools/skills/skill-script-runner.ts +7 -0
- package/src/tools/skills/skill-tool-factory.ts +15 -1
- package/src/tools/terminal/__tests__/safe-env.test.ts +11 -0
- package/src/tools/terminal/safe-env.ts +4 -0
- package/src/tools/terminal/shell.ts +2 -0
- package/src/tools/tool-approval-handler.ts +5 -1
- package/src/tools/tool-types.ts +3 -3
- package/src/tools/types.ts +8 -2
- package/src/util/__tests__/worker-process-command.test.ts +5 -4
- package/src/util/abort-reasons.ts +18 -26
- package/src/util/canonicalize-identity.test.ts +21 -0
- package/src/util/canonicalize-identity.ts +16 -0
- package/src/util/errors.ts +13 -3
- package/src/util/provider-error-patterns.ts +3 -0
- package/src/util/worker-process.ts +77 -35
- package/src/workspace/migrations/157-add-desktop-files-launcher.ts +94 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +4 -10
- package/src/workspace/migrations/__tests__/157-add-desktop-files-launcher.test.ts +113 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/computer-use-window-schema.test.ts +0 -24
- package/src/api/events/heartbeat-alert.ts +0 -20
- package/src/daemon/message-types/web-activity.ts +0 -65
- package/src/desktop/desktop-dependencies.test.ts +0 -131
- package/src/tools/computer-use/definitions.ts +0 -607
|
@@ -31,6 +31,10 @@ import {
|
|
|
31
31
|
type ConversationCreatedInfo,
|
|
32
32
|
NotificationBroadcaster,
|
|
33
33
|
} from "./broadcaster.js";
|
|
34
|
+
import {
|
|
35
|
+
intersectChannelAllowlist,
|
|
36
|
+
readChannelAllowlist,
|
|
37
|
+
} from "./channel-allowlist.js";
|
|
34
38
|
import { enforceRoutingIntent, evaluateSignal } from "./decision-engine.js";
|
|
35
39
|
import { updateDecision } from "./decisions-store.js";
|
|
36
40
|
import {
|
|
@@ -51,6 +55,7 @@ import type {
|
|
|
51
55
|
import type {
|
|
52
56
|
NotificationChannel,
|
|
53
57
|
NotificationDeliveryResult,
|
|
58
|
+
NotificationReceiptClass,
|
|
54
59
|
} from "./types.js";
|
|
55
60
|
|
|
56
61
|
const log = getLogger("emit-signal");
|
|
@@ -69,20 +74,27 @@ export function getBroadcaster(): NotificationBroadcaster {
|
|
|
69
74
|
new PlatformPushAdapter(),
|
|
70
75
|
]);
|
|
71
76
|
|
|
72
|
-
// Wire the conversation-created callback so the
|
|
73
|
-
//
|
|
74
|
-
//
|
|
77
|
+
// Wire the conversation-created callback so the event goes out as soon
|
|
78
|
+
// as a vellum notification conversation is paired, before slower channel
|
|
79
|
+
// deliveries (e.g. Telegram) run.
|
|
80
|
+
// A guardian-sensitive conversation's title reaches only the guardian's
|
|
81
|
+
// own connections, the same scoping the vellum adapter applies to the
|
|
82
|
+
// notification itself.
|
|
75
83
|
broadcasterInstance.setOnConversationCreated((info) => {
|
|
76
|
-
broadcastMessage(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
broadcastMessage(
|
|
85
|
+
{
|
|
86
|
+
type: "notification_conversation_created",
|
|
87
|
+
conversationId: info.conversationId,
|
|
88
|
+
title: info.title,
|
|
89
|
+
sourceEventName: info.sourceEventName,
|
|
90
|
+
targetGuardianPrincipalId: info.targetGuardianPrincipalId,
|
|
91
|
+
groupId: info.groupId,
|
|
92
|
+
source: info.source,
|
|
93
|
+
silent: info.silent,
|
|
94
|
+
},
|
|
95
|
+
undefined,
|
|
96
|
+
{ targetActorPrincipalId: info.targetGuardianPrincipalId },
|
|
97
|
+
);
|
|
86
98
|
log.info(
|
|
87
99
|
{
|
|
88
100
|
conversationId: info.conversationId,
|
|
@@ -240,7 +252,9 @@ export interface EmitSignalResult {
|
|
|
240
252
|
deduplicated: boolean;
|
|
241
253
|
dispatched: boolean;
|
|
242
254
|
reason: string;
|
|
255
|
+
selectedChannels: NotificationChannel[];
|
|
243
256
|
deliveryResults: NotificationDeliveryResult[];
|
|
257
|
+
receiptClass: NotificationReceiptClass;
|
|
244
258
|
/**
|
|
245
259
|
* True when the pipeline threw before reaching a verdict. Dispatch, dedupe,
|
|
246
260
|
* suppression, and a blocked deterministic check are all verdicts. Callers
|
|
@@ -250,6 +264,55 @@ export interface EmitSignalResult {
|
|
|
250
264
|
pipelineFailed: boolean;
|
|
251
265
|
}
|
|
252
266
|
|
|
267
|
+
const PROVIDER_RECEIPT_CHANNELS = new Set(["telegram", "slack", "discord"]);
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Strongest proof the emit path can report from adapter results. A vellum
|
|
271
|
+
* `sent` row means the assistant broadcast a `notification_intent`; it is
|
|
272
|
+
* not a client ACK that the OS posted a banner.
|
|
273
|
+
*/
|
|
274
|
+
export function classifyNotificationReceipt(
|
|
275
|
+
results: readonly NotificationDeliveryResult[],
|
|
276
|
+
): NotificationReceiptClass {
|
|
277
|
+
const accepted = results.filter((result) => {
|
|
278
|
+
return result.status === "sent" || result.status === "pending";
|
|
279
|
+
});
|
|
280
|
+
if (
|
|
281
|
+
accepted.some((result) => {
|
|
282
|
+
return PROVIDER_RECEIPT_CHANNELS.has(result.channel);
|
|
283
|
+
})
|
|
284
|
+
) {
|
|
285
|
+
return "provider_accepted";
|
|
286
|
+
}
|
|
287
|
+
if (
|
|
288
|
+
accepted.some((result) => {
|
|
289
|
+
return result.channel === "platform";
|
|
290
|
+
})
|
|
291
|
+
) {
|
|
292
|
+
return "gateway_accepted";
|
|
293
|
+
}
|
|
294
|
+
return "unknown";
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function emitOutcome(
|
|
298
|
+
partial: Omit<
|
|
299
|
+
EmitSignalResult,
|
|
300
|
+
"deliveryResults" | "selectedChannels" | "receiptClass"
|
|
301
|
+
> & {
|
|
302
|
+
deliveryResults?: NotificationDeliveryResult[];
|
|
303
|
+
selectedChannels?: NotificationChannel[];
|
|
304
|
+
},
|
|
305
|
+
): EmitSignalResult {
|
|
306
|
+
const deliveryResults = partial.deliveryResults ?? [];
|
|
307
|
+
const selectedChannels = partial.selectedChannels ?? [];
|
|
308
|
+
return {
|
|
309
|
+
...partial,
|
|
310
|
+
selectedChannels,
|
|
311
|
+
deliveryResults,
|
|
312
|
+
receiptClass: classifyNotificationReceipt(deliveryResults),
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
253
316
|
/**
|
|
254
317
|
* True when at least one channel adapter has already been handed the signal.
|
|
255
318
|
* `sent` is a completed delivery; `pending` is the platform push that passed
|
|
@@ -333,14 +396,13 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
333
396
|
{ signalId, dedupeKey: params.dedupeKey },
|
|
334
397
|
"Signal deduplicated at event store level",
|
|
335
398
|
);
|
|
336
|
-
return {
|
|
399
|
+
return emitOutcome({
|
|
337
400
|
signalId,
|
|
338
401
|
deduplicated: true,
|
|
339
402
|
dispatched: false,
|
|
340
403
|
reason: "Signal deduplicated at event store level",
|
|
341
|
-
deliveryResults: [],
|
|
342
404
|
pipelineFailed: false,
|
|
343
|
-
};
|
|
405
|
+
});
|
|
344
406
|
}
|
|
345
407
|
eventPersisted = true;
|
|
346
408
|
|
|
@@ -357,14 +419,13 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
357
419
|
{ signalId, reason: sourceActiveCheck.reason },
|
|
358
420
|
"Signal suppressed before decision stage (source-active)",
|
|
359
421
|
);
|
|
360
|
-
return {
|
|
422
|
+
return emitOutcome({
|
|
361
423
|
signalId,
|
|
362
424
|
deduplicated: false,
|
|
363
425
|
dispatched: false,
|
|
364
426
|
reason: `Signal suppressed: ${sourceActiveCheck.reason}`,
|
|
365
|
-
deliveryResults: [],
|
|
366
427
|
pipelineFailed: false,
|
|
367
|
-
};
|
|
428
|
+
});
|
|
368
429
|
}
|
|
369
430
|
|
|
370
431
|
// Step 2: Evaluate the signal through the decision engine
|
|
@@ -398,8 +459,31 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
398
459
|
// dispatch rank, so selection order only matters to single_channel
|
|
399
460
|
// enforcement's first-selected fallback (step 2.5b), which must keep
|
|
400
461
|
// the in-app banner rather than a push the server may skip.
|
|
462
|
+
const exclusiveAllowlist = readChannelAllowlist(signal.contextPayload);
|
|
401
463
|
const urgency = signal.attentionHints.urgency;
|
|
402
|
-
if (
|
|
464
|
+
if (exclusiveAllowlist) {
|
|
465
|
+
// Exclusive allowlist wins over the default set, urgent force, and
|
|
466
|
+
// routing-intent expansion. Delivery is the allowlist intersected
|
|
467
|
+
// with connected channels.
|
|
468
|
+
const allowed = intersectChannelAllowlist(
|
|
469
|
+
exclusiveAllowlist,
|
|
470
|
+
connectedChannels,
|
|
471
|
+
);
|
|
472
|
+
const alreadyMatches =
|
|
473
|
+
allowed.length === decision.selectedChannels.length &&
|
|
474
|
+
allowed.every((channel) => {
|
|
475
|
+
return decision.selectedChannels.includes(channel);
|
|
476
|
+
}) &&
|
|
477
|
+
decision.shouldNotify === allowed.length > 0;
|
|
478
|
+
if (!alreadyMatches) {
|
|
479
|
+
decision = {
|
|
480
|
+
...decision,
|
|
481
|
+
selectedChannels: allowed,
|
|
482
|
+
shouldNotify: allowed.length > 0,
|
|
483
|
+
reasoningSummary: `${decision.reasoningSummary} (channelAllowlist: ${allowed.join(", ") || "none available"})`,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
} else if (
|
|
403
487
|
(urgency === "high" || urgency === "critical") &&
|
|
404
488
|
decision.shouldNotify
|
|
405
489
|
) {
|
|
@@ -427,13 +511,16 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
427
511
|
}
|
|
428
512
|
}
|
|
429
513
|
|
|
430
|
-
// Step 2.5b: Enforce routing intent policy (fire-time guard)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
514
|
+
// Step 2.5b: Enforce routing intent policy (fire-time guard).
|
|
515
|
+
// An exclusive allowlist already closed the channel set.
|
|
516
|
+
if (!exclusiveAllowlist) {
|
|
517
|
+
decision = enforceRoutingIntent(
|
|
518
|
+
decision,
|
|
519
|
+
signal.routingIntent,
|
|
520
|
+
connectedChannels,
|
|
521
|
+
signal.sourceChannel,
|
|
522
|
+
);
|
|
523
|
+
}
|
|
437
524
|
|
|
438
525
|
// Step 2.5c: Access-request signals carry a decisionable canonical
|
|
439
526
|
// guardian request created before this emit, and that row suppresses
|
|
@@ -509,22 +596,21 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
509
596
|
{ signalId, reason: checkResult.reason },
|
|
510
597
|
"Signal blocked by deterministic checks",
|
|
511
598
|
);
|
|
512
|
-
return {
|
|
599
|
+
return emitOutcome({
|
|
513
600
|
signalId,
|
|
514
601
|
deduplicated: false,
|
|
515
602
|
dispatched: false,
|
|
516
603
|
reason: `Signal blocked by deterministic checks: ${checkResult.reason}`,
|
|
517
|
-
deliveryResults: [],
|
|
518
604
|
pipelineFailed: false,
|
|
519
|
-
};
|
|
605
|
+
});
|
|
520
606
|
}
|
|
521
607
|
}
|
|
522
608
|
|
|
523
609
|
// Step 4: Dispatch through the broadcaster
|
|
524
610
|
// Note: notification_conversation_created events are emitted eagerly inside
|
|
525
611
|
// the broadcaster as soon as vellum conversation pairing succeeds, rather
|
|
526
|
-
// than after all channel deliveries complete
|
|
527
|
-
//
|
|
612
|
+
// than after all channel deliveries complete, so a slow Telegram delivery
|
|
613
|
+
// cannot delay it.
|
|
528
614
|
const broadcaster = getBroadcaster();
|
|
529
615
|
const dispatchResult = await dispatchDecision(
|
|
530
616
|
signal,
|
|
@@ -562,14 +648,15 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
562
648
|
},
|
|
563
649
|
"Signal pipeline complete",
|
|
564
650
|
);
|
|
565
|
-
return {
|
|
651
|
+
return emitOutcome({
|
|
566
652
|
signalId,
|
|
567
653
|
deduplicated: false,
|
|
568
654
|
dispatched: dispatchResult.dispatched,
|
|
569
655
|
reason: dispatchResult.reason,
|
|
656
|
+
selectedChannels: decision.selectedChannels,
|
|
570
657
|
deliveryResults: dispatchResult.deliveryResults,
|
|
571
658
|
pipelineFailed: false,
|
|
572
|
-
};
|
|
659
|
+
});
|
|
573
660
|
} catch (err) {
|
|
574
661
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
575
662
|
log.error(
|
|
@@ -599,13 +686,12 @@ export async function emitNotificationSignal<TEventName extends string>(
|
|
|
599
686
|
if (params.throwOnError) {
|
|
600
687
|
throw err instanceof Error ? err : new Error(errMsg);
|
|
601
688
|
}
|
|
602
|
-
return {
|
|
689
|
+
return emitOutcome({
|
|
603
690
|
signalId,
|
|
604
691
|
deduplicated: false,
|
|
605
692
|
dispatched: false,
|
|
606
693
|
reason: `Signal pipeline failed: ${errMsg}`,
|
|
607
|
-
deliveryResults: [],
|
|
608
694
|
pipelineFailed: true,
|
|
609
|
-
};
|
|
695
|
+
});
|
|
610
696
|
}
|
|
611
697
|
}
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
import { publishConversationMessagesChanged } from "../runtime/sync/resource-sync-events.js";
|
|
31
31
|
import { getLogger } from "../util/logger.js";
|
|
32
32
|
import { normalizeTitle, stripMarkdown } from "../util/short-title.js";
|
|
33
|
+
import { readChannelAllowlist } from "./channel-allowlist.js";
|
|
33
34
|
import { isConversationSeedSane } from "./conversation-seed-composer.js";
|
|
34
35
|
import { deriveTitle } from "./copy-composer.js";
|
|
35
36
|
import {
|
|
@@ -459,12 +460,10 @@ const EVENT_CATEGORY_MAP: Record<string, FeedItemCategory> = {
|
|
|
459
460
|
|
|
460
461
|
/**
|
|
461
462
|
* Map a signal's source event to a feed category, or nothing when the event
|
|
462
|
-
* has no entry. An unmapped event
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
* category
|
|
466
|
-
* carries none: readers that filter by category skip it, and nothing has
|
|
467
|
-
* to guess.
|
|
463
|
+
* has no entry. An unmapped event, such as a deliberate assistant
|
|
464
|
+
* notification (`assistant.share`), carries no category rather than a
|
|
465
|
+
* catch-all bucket named for our architecture: readers that filter by
|
|
466
|
+
* category skip it, and nothing has to guess.
|
|
468
467
|
*/
|
|
469
468
|
function deriveCategory(
|
|
470
469
|
signal: NotificationSignal,
|
|
@@ -558,7 +557,10 @@ function resolveHomeFeedMirror(
|
|
|
558
557
|
signal.sourceChannel === "assistant_tool" ||
|
|
559
558
|
signal.sourceEventName === "chat.assistant_reply"
|
|
560
559
|
) {
|
|
561
|
-
|
|
560
|
+
const allowlist = readChannelAllowlist(signal.contextPayload);
|
|
561
|
+
if (!allowlist || allowlist.includes("vellum")) {
|
|
562
|
+
return { mirror: true, sourceConversationId, sourceScheduleJobId };
|
|
563
|
+
}
|
|
562
564
|
}
|
|
563
565
|
if (signal.attentionHints.isAsyncBackground) {
|
|
564
566
|
return { mirror: true, sourceConversationId, sourceScheduleJobId };
|
|
@@ -71,6 +71,25 @@ export function readPayloadObject(
|
|
|
71
71
|
return isPlainObject(value) ? value : undefined;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Safely read a string-array property from an unknown-typed payload object.
|
|
76
|
+
* Non-string entries are dropped. Returns `undefined` when the payload is
|
|
77
|
+
* not an object or the key does not hold an array.
|
|
78
|
+
*/
|
|
79
|
+
export function readPayloadStringArray(
|
|
80
|
+
payload: unknown,
|
|
81
|
+
key: string,
|
|
82
|
+
): string[] | undefined {
|
|
83
|
+
if (!isPlainObject(payload)) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const value = payload[key];
|
|
87
|
+
if (!Array.isArray(value)) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
return value.filter((entry): entry is string => typeof entry === "string");
|
|
91
|
+
}
|
|
92
|
+
|
|
74
93
|
/** Truncate `text` to `maxLength`, appending "…" when exceeded. */
|
|
75
94
|
export function truncate(text: string, maxLength: number): string {
|
|
76
95
|
if (text.length <= maxLength) {
|
|
@@ -59,8 +59,9 @@ export function isNotificationSourceChannel(
|
|
|
59
59
|
|
|
60
60
|
export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
61
61
|
{
|
|
62
|
-
id: "
|
|
63
|
-
description:
|
|
62
|
+
id: "assistant.share",
|
|
63
|
+
description:
|
|
64
|
+
"Assistant chose to tell the user something (`assistant notifications send`)",
|
|
64
65
|
},
|
|
65
66
|
{
|
|
66
67
|
id: "schedule.notify",
|
|
@@ -113,28 +114,12 @@ export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
|
113
114
|
id: "watcher.notification",
|
|
114
115
|
description: "Watcher detected a notable event",
|
|
115
116
|
},
|
|
116
|
-
{
|
|
117
|
-
id: "watcher.escalation",
|
|
118
|
-
description: "Watcher event requiring immediate attention",
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
id: "tool_confirmation.required_action",
|
|
122
|
-
description: "Tool requires user confirmation before executing",
|
|
123
|
-
},
|
|
124
117
|
{ id: "activity.complete", description: "Background activity finished" },
|
|
125
118
|
{
|
|
126
119
|
id: "activity.failed",
|
|
127
120
|
description:
|
|
128
121
|
"Background job execution failed (model_provider, exception, or timeout)",
|
|
129
122
|
},
|
|
130
|
-
{
|
|
131
|
-
id: "quick_chat.response_ready",
|
|
132
|
-
description: "Quick chat response ready for review",
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
id: "voice.response_ready",
|
|
136
|
-
description: "Voice response ready for playback",
|
|
137
|
-
},
|
|
138
123
|
{
|
|
139
124
|
id: "credential.health_alert",
|
|
140
125
|
description:
|
|
@@ -251,7 +236,7 @@ export interface NotificationSignal<TEventName extends string = string> {
|
|
|
251
236
|
createdAt: number; // epoch ms
|
|
252
237
|
sourceChannel: NotificationSourceChannel; // see NOTIFICATION_SOURCE_CHANNELS registry
|
|
253
238
|
sourceContextId: string;
|
|
254
|
-
sourceEventName: TEventName; // free-form
|
|
239
|
+
sourceEventName: TEventName; // free-form; see NOTIFICATION_SOURCE_EVENT_NAMES
|
|
255
240
|
contextPayload: NotificationContextPayload<TEventName>;
|
|
256
241
|
attentionHints: AttentionHints;
|
|
257
242
|
/**
|
|
@@ -46,6 +46,21 @@ export type NotificationDeliveryResult = z.infer<
|
|
|
46
46
|
typeof NotificationDeliveryResultSchema
|
|
47
47
|
>;
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Strongest delivery proof the emit path can report. These are receipts,
|
|
51
|
+
* not intents: `client_os_posted` is reserved for a client ACK that the
|
|
52
|
+
* OS banner was posted, which this return path does not observe.
|
|
53
|
+
*/
|
|
54
|
+
export const NotificationReceiptClassSchema = z.enum([
|
|
55
|
+
"provider_accepted",
|
|
56
|
+
"gateway_accepted",
|
|
57
|
+
"client_os_posted",
|
|
58
|
+
"unknown",
|
|
59
|
+
]);
|
|
60
|
+
export type NotificationReceiptClass = z.infer<
|
|
61
|
+
typeof NotificationReceiptClassSchema
|
|
62
|
+
>;
|
|
63
|
+
|
|
49
64
|
// -- Channel adapter data shapes ----------------------------------------------
|
|
50
65
|
|
|
51
66
|
export const DeliveryResultSchema = z.object({
|
|
@@ -467,12 +467,11 @@ async function fetchPlatformConnections(options: {
|
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
const body = (await response.json()) as unknown;
|
|
470
|
-
|
|
470
|
+
return (
|
|
471
471
|
Array.isArray(body)
|
|
472
472
|
? body
|
|
473
473
|
: ((body as Record<string, unknown>).results ?? [])
|
|
474
474
|
) as PlatformConnectionEntry[];
|
|
475
|
-
return connections;
|
|
476
475
|
}
|
|
477
476
|
|
|
478
477
|
/**
|
package/src/oauth/oauth-store.ts
CHANGED
|
@@ -678,8 +678,6 @@ export async function upsertApp(
|
|
|
678
678
|
);
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
-
const defaultCredPath = (appId: string) => oauthAppClientSecretPath(appId);
|
|
682
|
-
|
|
683
681
|
// Verify the credential path points to an existing secret.
|
|
684
682
|
if (clientSecretCredentialPath) {
|
|
685
683
|
const existing = await getSecureKeyAsync(clientSecretCredentialPath);
|
|
@@ -739,7 +737,7 @@ export async function upsertApp(
|
|
|
739
737
|
|
|
740
738
|
const now = Date.now();
|
|
741
739
|
const id = uuid();
|
|
742
|
-
const credPath = clientSecretCredentialPath ??
|
|
740
|
+
const credPath = clientSecretCredentialPath ?? oauthAppClientSecretPath(id);
|
|
743
741
|
|
|
744
742
|
const row = {
|
|
745
743
|
id,
|
|
@@ -19,6 +19,7 @@ export type SerializedProvider = ReturnType<typeof serializeProvider> &
|
|
|
19
19
|
Record<string, unknown>;
|
|
20
20
|
|
|
21
21
|
import { isChannelBotProvider } from "@vellumai/service-contracts/channels";
|
|
22
|
+
import type { IntegrationCategory } from "@vellumai/service-contracts/integration-categories";
|
|
22
23
|
|
|
23
24
|
import { PROVIDER_SEED_DATA } from "./seed-providers.js";
|
|
24
25
|
|
|
@@ -38,6 +39,11 @@ export interface SerializedProviderSummary {
|
|
|
38
39
|
supports_managed_mode: boolean;
|
|
39
40
|
managed_service_is_paid: boolean;
|
|
40
41
|
feature_flag: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Where the integrations catalog files the provider. `null` for a row with
|
|
44
|
+
* no seed entry, such as a provider a user registered by hand.
|
|
45
|
+
*/
|
|
46
|
+
category: IntegrationCategory | null;
|
|
41
47
|
/**
|
|
42
48
|
* Per-tenant providers only (Shopify): what a client must collect before
|
|
43
49
|
* starting a managed connect, since the provider's OAuth endpoints live on
|
|
@@ -173,6 +179,7 @@ export function serializeProviderSummary(
|
|
|
173
179
|
supports_managed_mode: !!row.managedServiceConfigKey,
|
|
174
180
|
managed_service_is_paid: !!row.managedServiceIsPaid,
|
|
175
181
|
feature_flag: row.featureFlag ?? null,
|
|
182
|
+
category: PROVIDER_SEED_DATA[row.provider]?.category ?? null,
|
|
176
183
|
tenant_host: PROVIDER_SEED_DATA[row.provider]?.tenantHost ?? null,
|
|
177
184
|
acts_as: isChannelBotProvider(row.provider) ? "assistant" : "user",
|
|
178
185
|
};
|