@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-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/AGENTS.md +0 -4
- package/ARCHITECTURE.md +12 -11
- package/docs/architecture/turn-actor.md +8 -15
- package/docs/guardian-request-flow.md +0 -16
- package/openapi.yaml +49 -291
- package/package.json +1 -1
- package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
- package/src/__tests__/app-compiler.test.ts +0 -6
- package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
- package/src/__tests__/app-dir-path-guard.test.ts +3 -1
- package/src/__tests__/app-source-watcher.test.ts +218 -0
- package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
- package/src/__tests__/computer-use-tools.test.ts +5 -17
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +29 -28
- package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
- package/src/__tests__/config-watcher.test.ts +8 -23
- package/src/__tests__/connection-model-compat.test.ts +2 -2
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +0 -26
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
- package/src/__tests__/conversation-queue.test.ts +207 -48
- package/src/__tests__/conversation-retry-discard.test.ts +1 -54
- package/src/__tests__/conversation-skill-tools.test.ts +0 -27
- package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
- package/src/__tests__/conversation-title-service.test.ts +10 -14
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
- package/src/__tests__/credential-record-retire.test.ts +1 -171
- package/src/__tests__/credential-routes.test.ts +3 -212
- package/src/__tests__/credential-security-invariants.test.ts +2 -4
- package/src/__tests__/cu-unified-flow.test.ts +2 -8
- package/src/__tests__/document-sync-tags.test.ts +0 -25
- package/src/__tests__/drain-kick-guard.test.ts +2 -0
- package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/host-bash-proxy.test.ts +45 -26
- package/src/__tests__/host-browser-proxy.test.ts +17 -6
- package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
- package/src/__tests__/host-file-proxy.test.ts +23 -11
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
- package/src/__tests__/llm-catalog-parity.test.ts +0 -25
- package/src/__tests__/mcp-auth-routes.test.ts +9 -6
- package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
- package/src/__tests__/mcp-health-check.test.ts +11 -8
- package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
- package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
- package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
- package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
- package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
- package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +548 -355
- package/src/__tests__/model-intents.test.ts +0 -3
- package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/platform-callback-registration.test.ts +16 -8
- package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
- package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
- package/src/__tests__/script-proxy-certs.test.ts +0 -35
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/speaker-identification.test.ts +56 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
- package/src/__tests__/subagent-tools.test.ts +2 -3
- package/src/__tests__/telephony-tts-guard.test.ts +3 -38
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
- package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
- package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
- package/src/__tests__/workspace-git-service.test.ts +0 -26
- package/src/acp/__tests__/agent-process.test.ts +4 -258
- package/src/acp/__tests__/auth-required.test.ts +0 -96
- package/src/acp/__tests__/client-handler.test.ts +2 -90
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
- package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
- package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
- package/src/acp/__tests__/session-manager.test.ts +4 -895
- package/src/acp/agent-process.test.ts +1 -4
- package/src/acp/agent-process.ts +9 -94
- package/src/acp/auth-required.ts +1 -50
- package/src/acp/auto-install.test.ts +7 -9
- package/src/acp/client-handler.ts +3 -16
- package/src/acp/resolve-agent.test.ts +6 -220
- package/src/acp/resolve-agent.ts +23 -88
- package/src/acp/session-manager.test.ts +3 -196
- package/src/acp/session-manager.ts +18 -441
- package/src/acp/types.ts +5 -50
- package/src/api/events/app-files-changed.ts +3 -4
- package/src/api/events/notification-intent.ts +0 -2
- package/src/api/index.ts +0 -6
- package/src/apps/app-store.ts +1 -1
- package/src/bundler/app-compiler.ts +0 -15
- package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
- package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
- package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
- package/src/calls/call-constants.ts +4 -24
- package/src/calls/call-controller.ts +199 -499
- package/src/calls/call-transport.ts +0 -16
- package/src/calls/media-stream-output.ts +0 -32
- package/src/calls/media-stream-server.ts +30 -82
- package/src/calls/media-stream-stt-session.ts +0 -15
- package/src/calls/resolve-call-tts-provider.ts +2 -33
- package/src/calls/speaker-identification.ts +233 -0
- package/src/calls/tts-call-strategy.ts +5 -9
- package/src/calls/types.ts +0 -2
- package/src/calls/voice-control-protocol.ts +21 -53
- package/src/calls/voice-session-bridge.ts +46 -59
- package/src/calls/voice-triage-escalate.ts +56 -175
- package/src/cli/commands/apps.help.ts +13 -67
- package/src/cli/commands/apps.ts +0 -183
- package/src/cli/commands/bash.help.ts +13 -8
- package/src/cli/commands/bash.ts +25 -7
- package/src/cli/commands/channels/index.help.ts +2 -70
- package/src/cli/commands/channels/index.ts +3 -16
- package/src/cli/commands/credentials.help.ts +2 -6
- package/src/cli/commands/credentials.ts +2 -2
- package/src/cli/commands/mcp.help.ts +8 -8
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/roadmap.help.ts +1 -5
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +90 -103
- package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
- package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
- package/src/config/__tests__/platform-rehydration.test.ts +9 -99
- package/src/config/acp-defaults.test.ts +3 -13
- package/src/config/acp-defaults.ts +6 -23
- package/src/config/acp-schema.ts +2 -30
- package/src/config/bundled-skills/acp/SKILL.md +14 -22
- package/src/config/bundled-skills/acp/TOOLS.json +1 -5
- package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +4 -3
- package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
- package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/env.ts +2 -2
- package/src/config/feature-flag-registry.json +12 -24
- package/src/config/loader.ts +0 -1
- package/src/config/memory-v3-gate.test.ts +0 -31
- package/src/config/memory-v3-gate.ts +16 -20
- package/src/config/platform-rehydration.ts +27 -11
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
- package/src/config/schemas/calls.ts +28 -1
- package/src/config/schemas/live-voice.ts +173 -1
- package/src/config/schemas/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +0 -10
- package/src/config/schemas/services.ts +0 -8
- package/src/config/schemas/skills.ts +14 -0
- package/src/credential-execution/process-manager.test.ts +19 -18
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
- package/src/daemon/app-source-watcher.ts +218 -0
- package/src/daemon/config-watcher.ts +194 -13
- package/src/daemon/conversation-process.ts +64 -35
- package/src/daemon/conversation-skill-tools.ts +31 -13
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +8 -10
- package/src/daemon/conversation-tool-setup.ts +43 -37
- package/src/daemon/conversation.ts +3 -0
- package/src/daemon/host-bash-proxy.ts +12 -8
- package/src/daemon/host-browser-proxy.ts +1 -15
- package/src/daemon/host-file-proxy.ts +10 -8
- package/src/daemon/host-transfer-proxy.ts +18 -14
- package/src/daemon/lifecycle.ts +5 -0
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/shutdown-handlers.ts +9 -1
- package/src/daemon/skill-memory-refresh.ts +0 -64
- package/src/daemon/tool-side-effects.ts +18 -7
- package/src/home/__tests__/feed-writer.test.ts +0 -22
- package/src/home/feed-writer.ts +2 -11
- package/src/hooks/types.ts +0 -33
- package/src/inbound/platform-callback-registration.ts +5 -4
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
- package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
- package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
- package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
- package/src/live-voice/live-voice-session.ts +693 -213
- package/src/{calls → live-voice}/progress-narration.ts +2 -2
- package/src/live-voice/protocol.ts +2 -0
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +45 -29
- package/src/mcp/startup.ts +4 -8
- package/src/messaging/provider.ts +3 -10
- package/src/messaging/providers/callback-routing.ts +0 -18
- package/src/messaging/providers/channel-transport.ts +0 -56
- package/src/messaging/providers/discord/transport.ts +0 -17
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
- package/src/messaging/providers/slack/adapter.ts +44 -7
- package/src/messaging/providers/slack/transport.ts +0 -16
- package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
- package/src/messaging/providers/telegram-bot/client.ts +26 -0
- package/src/messaging/providers/telegram-bot/transport.ts +0 -20
- package/src/messaging/providers/whatsapp/adapter.ts +48 -1
- package/src/messaging/providers/whatsapp/client.ts +29 -0
- package/src/messaging/providers/whatsapp/transport.ts +0 -18
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
- package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
- package/src/notifications/adapters/macos.ts +0 -3
- package/src/notifications/assistant-reply-producer.ts +3 -8
- package/src/notifications/conversation-pairing.ts +16 -36
- package/src/notifications/delivered-post-record.ts +1 -11
- package/src/notifications/guardian-feed-projection.ts +5 -125
- package/src/notifications/home-feed-side-effect.ts +7 -55
- package/src/notifications/schedule-result-producer.ts +22 -66
- package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
- package/src/oauth/byo-connection.test.ts +0 -45
- package/src/oauth/byo-connection.ts +6 -36
- package/src/oauth/connection-resolver.test.ts +0 -73
- package/src/oauth/connection-resolver.ts +2 -95
- package/src/oauth/seed-providers.ts +0 -165
- package/src/outbound-proxy/certs.ts +5 -3
- package/src/permissions/checker.test.ts +6 -11
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +63 -71
- package/src/persistence/conversation-lineage.ts +4 -12
- package/src/persistence/conversation-title-service.ts +26 -9
- package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
- package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
- package/src/persistence/message-reads.ts +0 -30
- package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
- package/src/persistence/schema/memory-core.ts +0 -5
- package/src/platform/client.test.ts +2 -4
- package/src/platform/client.ts +10 -2
- package/src/plugin-api/constants.ts +0 -2
- package/src/plugin-api/index.ts +0 -1
- package/src/plugin-api/types.ts +0 -2
- package/src/plugins/defaults/index.ts +0 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
- package/src/plugins/defaults/memory/hooks/init.ts +0 -10
- package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
- package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
- package/src/plugins/defaults/memory/startup.ts +1 -6
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
- package/src/plugins/defaults/memory/worker.ts +0 -6
- package/src/plugins/mcp-servers.ts +75 -15
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/gemini/client.ts +23 -9
- package/src/providers/inference/auth.ts +3 -2
- package/src/providers/inference/connection-availability.ts +8 -27
- package/src/providers/inference/resolve-auth.ts +4 -22
- package/src/providers/model-catalog.ts +0 -34
- package/src/providers/model-intents.ts +5 -10
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
- package/src/providers/openai/chat-completions-provider.ts +78 -192
- package/src/providers/openai/codex-models.ts +4 -0
- package/src/runtime/AGENTS.md +0 -2
- package/src/runtime/auth/same-actor.ts +3 -38
- package/src/runtime/http-server.ts +151 -160
- package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
- package/src/runtime/routes/acp-routes.test.ts +0 -15
- package/src/runtime/routes/acp-routes.ts +9 -72
- package/src/runtime/routes/app-management-routes.ts +0 -73
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +0 -40
- package/src/runtime/routes/credential-routes.ts +10 -19
- package/src/runtime/routes/debug-bash-routes.ts +173 -0
- package/src/runtime/routes/diagnostics-routes.ts +3 -55
- package/src/runtime/routes/index.ts +2 -4
- package/src/runtime/routes/log-export-routes.ts +0 -2
- package/src/runtime/routes/mcp-auth-routes.ts +47 -39
- package/src/runtime/routes/migration-routes.ts +20 -6
- package/src/runtime/routes/platform-routes.ts +15 -18
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
- package/src/runtime/services/conversation-serializer.ts +3 -16
- package/src/runtime/sync/resource-sync-events.ts +1 -2
- package/src/schedule/worker.ts +1 -1
- package/src/security/ces-rpc-record-backend.ts +0 -7
- package/src/subagent/consult-context.ts +25 -12
- package/src/tools/acp/list-agents.test.ts +1 -3
- package/src/tools/acp/spawn.test.ts +11 -146
- package/src/tools/acp/spawn.ts +3 -21
- package/src/tools/acp/status.ts +3 -40
- package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
- package/src/tools/capability-offer.test.ts +2 -22
- package/src/tools/capability-offer.ts +1 -16
- package/src/tools/computer-use/definitions.ts +2 -4
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
- package/src/tools/credentials/metadata-store.ts +0 -100
- package/src/tools/host-filesystem/edit.test.ts +1 -2
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +1 -2
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +1 -2
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +1 -2
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +0 -16
- package/src/tools/host-terminal/host-shell.ts +20 -4
- package/src/tools/policy-context.ts +7 -6
- package/src/tools/subagent/spawn.ts +8 -5
- package/src/tools/watch/watch-retro-report.ts +8 -0
- package/src/util/__tests__/language-subtag.test.ts +1 -23
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/language-subtag.ts +0 -16
- package/src/util/platform.ts +0 -8
- package/src/workspace/git-service.ts +54 -5
- package/src/workspace/migrations/registry.ts +0 -6
- package/scripts/smoke-desktop-window-theme.ts +0 -186
- package/src/__tests__/git-porcelain.test.ts +0 -47
- package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
- package/src/__tests__/resolve-app.test.ts +0 -135
- package/src/__tests__/service-account-token.test.ts +0 -247
- package/src/__tests__/source-fingerprint.test.ts +0 -184
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
- package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
- package/src/acp/model-config.test.ts +0 -166
- package/src/acp/model-config.ts +0 -138
- package/src/api/events/acp-session-model-update.test.ts +0 -88
- package/src/api/events/acp-session-model-update.ts +0 -46
- package/src/apps/resolve-app.ts +0 -81
- package/src/apps/source-fingerprint.ts +0 -266
- package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
- package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
- package/src/calls/barge-in-guard.ts +0 -118
- package/src/calls/voice-leg-coordinator.ts +0 -189
- package/src/calls/voice-progress-cadence.ts +0 -423
- package/src/cli/commands/__tests__/apps.test.ts +0 -245
- package/src/cli/commands/__tests__/bash.test.ts +0 -53
- package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
- package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
- package/src/cli/commands/channels/send.ts +0 -128
- package/src/config/__tests__/platform-identity.test.ts +0 -255
- package/src/config/acp-agent-write.ts +0 -43
- package/src/config/acp-schema.test.ts +0 -81
- package/src/config/platform-identity.ts +0 -201
- package/src/config/schemas/__tests__/voice.test.ts +0 -148
- package/src/config/schemas/voice.ts +0 -150
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
- package/src/daemon/app-change-notify.ts +0 -45
- package/src/desktop/__tests__/fake-desktop.ts +0 -119
- package/src/desktop/desktop-chrome-policy.test.ts +0 -71
- package/src/desktop/desktop-chrome-policy.ts +0 -42
- package/src/desktop/desktop-dependencies.test.ts +0 -102
- package/src/desktop/desktop-dependencies.ts +0 -306
- package/src/desktop/desktop-feature.test.ts +0 -18
- package/src/desktop/desktop-feature.ts +0 -19
- package/src/desktop/desktop-panel-config.test.ts +0 -135
- package/src/desktop/desktop-panel-config.ts +0 -149
- package/src/desktop/desktop-session-manager.test.ts +0 -627
- package/src/desktop/desktop-session-manager.ts +0 -814
- package/src/desktop/desktop-stream-bridge.test.ts +0 -395
- package/src/desktop/desktop-stream-bridge.ts +0 -214
- package/src/desktop/desktop-wallpaper.test.ts +0 -191
- package/src/desktop/desktop-wallpaper.ts +0 -113
- package/src/desktop/desktop-window-theme.ts +0 -170
- package/src/i18n/AGENTS.md +0 -22
- package/src/i18n/__tests__/i18n.test.ts +0 -108
- package/src/i18n/index.ts +0 -16
- package/src/i18n/locales.ts +0 -93
- package/src/i18n/messages.ts +0 -61
- package/src/i18n/title.ts +0 -25
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
- package/src/mcp/spec-schema.ts +0 -111
- package/src/mcp/workspace-mcp-config.ts +0 -188
- package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
- package/src/persistence/conversation-title-placeholders.ts +0 -23
- package/src/persistence/message-cursor.ts +0 -78
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
- package/src/providers/gemini-thought-signature.test.ts +0 -63
- package/src/providers/gemini-thought-signature.ts +0 -44
- package/src/providers/inference/service-account-token.ts +0 -248
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
- package/src/providers/openai/google-thought-signature.ts +0 -320
- package/src/runtime/__tests__/channel-send.test.ts +0 -443
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
- package/src/runtime/channel-send.ts +0 -316
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
- package/src/runtime/routes/channel-send-routes.ts +0 -85
- package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
- package/src/runtime/routes/desktop-setup-routes.ts +0 -35
- package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
- package/src/security/ces-http-record-backend.ts +0 -120
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
- package/src/skills/workspace-skill-md-signature.ts +0 -50
- package/src/tools/acp/status.test.ts +0 -94
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
- package/src/tools/terminal/sanitized-bash.ts +0 -105
- package/src/util/ca-bundle.ts +0 -13
- package/src/workspace/git-porcelain.ts +0 -66
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
- /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { basename } from "node:path";
|
|
3
3
|
|
|
4
|
+
import { isChannelId } from "../../../../channels/types.js";
|
|
4
5
|
import type { OutboundAttachment } from "../../../../messaging/provider-types.js";
|
|
5
6
|
import {
|
|
6
7
|
createDraft,
|
|
@@ -15,10 +16,11 @@ import {
|
|
|
15
16
|
toOutlookFileAttachments,
|
|
16
17
|
} from "../../../../messaging/providers/outlook/client.js";
|
|
17
18
|
import type { OutlookDraftMessage } from "../../../../messaging/providers/outlook/types.js";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from "../../../../
|
|
19
|
+
import { resolveProactiveHomeConversation } from "../../../../notifications/conversation-pairing.js";
|
|
20
|
+
import { recordDeliveredChannelPost } from "../../../../notifications/delivered-post-record.js";
|
|
21
|
+
import { getConversation } from "../../../../persistence/conversation-crud.js";
|
|
22
|
+
import { syncMessageToDisk } from "../../../../persistence/conversation-disk-view.js";
|
|
23
|
+
import { normalizeExternalThreadId } from "../../../../persistence/external-conversation-store.js";
|
|
22
24
|
import {
|
|
23
25
|
isAbortLikeError,
|
|
24
26
|
throwIfCancelled,
|
|
@@ -27,6 +29,7 @@ import type {
|
|
|
27
29
|
ToolContext,
|
|
28
30
|
ToolExecutionResult,
|
|
29
31
|
} from "../../../../tools/types.js";
|
|
32
|
+
import { getLogger } from "../../../../util/logger.js";
|
|
30
33
|
import { guessMimeType } from "../../../../util/mime-type.js";
|
|
31
34
|
import {
|
|
32
35
|
err,
|
|
@@ -39,6 +42,8 @@ import {
|
|
|
39
42
|
resolveProvider,
|
|
40
43
|
} from "./shared.js";
|
|
41
44
|
|
|
45
|
+
const log = getLogger("messaging-send");
|
|
46
|
+
|
|
42
47
|
/** Read attachment files from disk into in-memory parts for outbound sending. */
|
|
43
48
|
async function readAttachments(paths: string[]): Promise<OutboundAttachment[]> {
|
|
44
49
|
return Promise.all(
|
|
@@ -53,6 +58,123 @@ async function readAttachments(paths: string[]): Promise<OutboundAttachment[]> {
|
|
|
53
58
|
/** Email providers that accept file attachments on outbound sends. */
|
|
54
59
|
const ATTACHMENT_CAPABLE_PLATFORMS = new Set(["gmail", "outlook"]);
|
|
55
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Record a message the provider just accepted where the chat's proactive
|
|
63
|
+
* posts live, so the chat's own conversation and `recall` can see what was
|
|
64
|
+
* sent from elsewhere (a scheduled run, another conversation).
|
|
65
|
+
*
|
|
66
|
+
* Only channel providers have such a home; an email send is tool-mediated
|
|
67
|
+
* and has no chat conversation. The row is written after the provider
|
|
68
|
+
* returned the message id, never before, and carries that id on its
|
|
69
|
+
* envelope and in `channel_outbound_posts` like every other post the daemon
|
|
70
|
+
* makes.
|
|
71
|
+
*
|
|
72
|
+
* A send into the sending turn's own chat writes no row: its tool call and
|
|
73
|
+
* result already sit in that conversation's history, and a second assistant
|
|
74
|
+
* row beside the tool pair would break history repair. Whether the send is
|
|
75
|
+
* "its own" is decided by the delivered target against the turn, not by the
|
|
76
|
+
* home: the turn arrived on a channel, in a chat, in a thread (the turn-local
|
|
77
|
+
* snapshot on the tool context), and a post the provider delivered to exactly
|
|
78
|
+
* that place is a same-conversation send even when the chat's home resolves
|
|
79
|
+
* elsewhere. The delivered thread is the one the provider reports, not the
|
|
80
|
+
* one requested: a provider that ignores the request lands the post in the
|
|
81
|
+
* thread-less chat, and the record must say so; a post into a thread is
|
|
82
|
+
* recorded in the thread's own conversation, where its replies arrive. The home
|
|
83
|
+
* comparison stays as the second test, for a sender that arrived through no
|
|
84
|
+
* channel but is the home. The post is then in the outbound index only
|
|
85
|
+
* through no path, which is the same class as a raw API send and is deferred
|
|
86
|
+
* with it.
|
|
87
|
+
*
|
|
88
|
+
* Failures here never fail the send: the message is already out.
|
|
89
|
+
*/
|
|
90
|
+
async function recordSentChannelPost(params: {
|
|
91
|
+
providerId: string;
|
|
92
|
+
externalChatId: string;
|
|
93
|
+
/** The thread the provider delivered into, as it reported it. */
|
|
94
|
+
deliveredThreadId: string | undefined;
|
|
95
|
+
text: string;
|
|
96
|
+
providerMessageId: string;
|
|
97
|
+
sender: ToolContext;
|
|
98
|
+
}): Promise<void> {
|
|
99
|
+
const { providerId, externalChatId, sender } = params;
|
|
100
|
+
if (!isChannelId(providerId) || !params.providerMessageId) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
if (
|
|
105
|
+
isSendIntoOwnChat(
|
|
106
|
+
sender,
|
|
107
|
+
providerId,
|
|
108
|
+
externalChatId,
|
|
109
|
+
params.deliveredThreadId,
|
|
110
|
+
)
|
|
111
|
+
) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const home = await resolveProactiveHomeConversation({
|
|
115
|
+
sourceChannel: providerId,
|
|
116
|
+
externalChatId,
|
|
117
|
+
threadId: params.deliveredThreadId,
|
|
118
|
+
source: "notification",
|
|
119
|
+
conversationType: "background",
|
|
120
|
+
title: `Messages to ${externalChatId}`,
|
|
121
|
+
});
|
|
122
|
+
if (home.conversationId === sender.conversationId) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const recorded = await recordDeliveredChannelPost({
|
|
126
|
+
conversationId: home.conversationId,
|
|
127
|
+
channel: providerId,
|
|
128
|
+
externalChatId,
|
|
129
|
+
...(params.deliveredThreadId
|
|
130
|
+
? { threadId: params.deliveredThreadId }
|
|
131
|
+
: {}),
|
|
132
|
+
text: params.text,
|
|
133
|
+
providerMessageId: params.providerMessageId,
|
|
134
|
+
crossPostedFrom: sender.conversationId,
|
|
135
|
+
});
|
|
136
|
+
const homeConversation = getConversation(home.conversationId);
|
|
137
|
+
if (homeConversation) {
|
|
138
|
+
syncMessageToDisk(
|
|
139
|
+
home.conversationId,
|
|
140
|
+
recorded.messageId,
|
|
141
|
+
homeConversation.createdAt,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
log.warn(
|
|
146
|
+
{ err: e, provider: providerId, externalChatId },
|
|
147
|
+
"Failed to record the sent message in the chat's conversation",
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* True when the delivered chat and thread are the ones the sending turn
|
|
154
|
+
* arrived in. Reads the turn-local snapshot the tool context carries
|
|
155
|
+
* (`executionChannel`, `requesterChatId`, `sourceThreadId`), never the live
|
|
156
|
+
* binding, which a concurrent inbound can rewrite while this call runs.
|
|
157
|
+
* Thread ids compare in the binding store's normalized form, so an absent
|
|
158
|
+
* thread on both sides matches and a thread-less delivery never matches a
|
|
159
|
+
* turn that arrived in a thread.
|
|
160
|
+
*/
|
|
161
|
+
function isSendIntoOwnChat(
|
|
162
|
+
sender: ToolContext,
|
|
163
|
+
channel: string,
|
|
164
|
+
externalChatId: string,
|
|
165
|
+
deliveredThreadId: string | undefined,
|
|
166
|
+
): boolean {
|
|
167
|
+
if (!sender.executionChannel || !sender.requesterChatId) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
return (
|
|
171
|
+
sender.executionChannel === channel &&
|
|
172
|
+
sender.requesterChatId === externalChatId &&
|
|
173
|
+
normalizeExternalThreadId(sender.sourceThreadId) ===
|
|
174
|
+
normalizeExternalThreadId(deliveredThreadId)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
56
178
|
export async function run(
|
|
57
179
|
input: Record<string, unknown>,
|
|
58
180
|
context: ToolContext,
|
|
@@ -75,62 +197,9 @@ export async function run(
|
|
|
75
197
|
throwIfCancelled(context);
|
|
76
198
|
|
|
77
199
|
try {
|
|
78
|
-
|
|
79
|
-
// through the transport, which is the one send implementation for that
|
|
80
|
-
// channel, records what it sent, and reaches channels with no messaging
|
|
81
|
-
// provider at all. A platform named outright is checked first; one
|
|
82
|
-
// auto-detected from the connected providers is checked the same way.
|
|
83
|
-
const namedChannel =
|
|
84
|
-
platform && isProactivelyAddressable(platform) ? platform : undefined;
|
|
85
|
-
const provider = namedChannel ? undefined : await resolveProvider(platform);
|
|
86
|
-
const channel =
|
|
87
|
-
namedChannel ??
|
|
88
|
-
(provider && isProactivelyAddressable(provider.id)
|
|
89
|
-
? provider.id
|
|
90
|
-
: undefined);
|
|
91
|
-
|
|
92
|
-
if (channel) {
|
|
93
|
-
if (attachmentPaths?.length) {
|
|
94
|
-
return err("Attachments are only supported on Gmail and Outlook.");
|
|
95
|
-
}
|
|
96
|
-
// A channel's transport sends as the channel's one bot identity, so an
|
|
97
|
-
// account cannot select where the send goes out from. Refusing is
|
|
98
|
-
// safer than silently sending from the default account.
|
|
99
|
-
if (input.account) {
|
|
100
|
-
return err(
|
|
101
|
-
`account does not apply to ${channel}: a channel send goes out as the channel's own bot.`,
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
// Recheck: provider resolution above is an await, and this posts to
|
|
105
|
-
// the channel.
|
|
106
|
-
throwIfCancelled(context);
|
|
107
|
-
const sent = await sendChannelText({
|
|
108
|
-
channel,
|
|
109
|
-
target: {
|
|
110
|
-
kind: "chat",
|
|
111
|
-
chatId: conversationId,
|
|
112
|
-
...(threadId ? { threadId } : {}),
|
|
113
|
-
},
|
|
114
|
-
text,
|
|
115
|
-
renderRichly: true,
|
|
116
|
-
assistantId: context.assistantId,
|
|
117
|
-
sender: {
|
|
118
|
-
conversationId: context.conversationId,
|
|
119
|
-
executionChannel: context.executionChannel,
|
|
120
|
-
requesterChatId: context.requesterChatId,
|
|
121
|
-
sourceThreadId: context.sourceThreadId,
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
const threadSuffix = sent.threadId
|
|
125
|
-
? `, "thread_id": "${sent.threadId}"`
|
|
126
|
-
: "";
|
|
127
|
-
return ok(`Message sent (ID: ${sent.lastMessageId}${threadSuffix}).`);
|
|
128
|
-
}
|
|
129
|
-
if (!provider) {
|
|
130
|
-
throw new Error(`Messaging provider "${platform}" not found.`);
|
|
131
|
-
}
|
|
200
|
+
const provider = await resolveProvider(platform);
|
|
132
201
|
|
|
133
|
-
// Reject attachments on platforms that can't carry them.
|
|
202
|
+
// Reject attachments on platforms that can't carry them (e.g. Telegram, WhatsApp).
|
|
134
203
|
if (
|
|
135
204
|
attachmentPaths?.length &&
|
|
136
205
|
!ATTACHMENT_CAPABLE_PLATFORMS.has(provider.id)
|
|
@@ -357,14 +426,7 @@ export async function run(
|
|
|
357
426
|
);
|
|
358
427
|
}
|
|
359
428
|
|
|
360
|
-
//
|
|
361
|
-
// for instance). Its send is tool-mediated and has no chat conversation
|
|
362
|
-
// to record in.
|
|
363
|
-
if (!provider.sendMessage) {
|
|
364
|
-
return err(
|
|
365
|
-
`${provider.displayName} cannot send from here: it has no send of its own and no channel transport to address.`,
|
|
366
|
-
);
|
|
367
|
-
}
|
|
429
|
+
// Non-email platforms
|
|
368
430
|
const attachments = attachmentPaths?.length
|
|
369
431
|
? await readAttachments(attachmentPaths)
|
|
370
432
|
: undefined;
|
|
@@ -380,6 +442,16 @@ export async function run(
|
|
|
380
442
|
const threadSuffix = result.threadId
|
|
381
443
|
? `, "thread_id": "${result.threadId}"`
|
|
382
444
|
: "";
|
|
445
|
+
|
|
446
|
+
await recordSentChannelPost({
|
|
447
|
+
providerId: provider.id,
|
|
448
|
+
externalChatId: conversationId,
|
|
449
|
+
deliveredThreadId: result.threadId,
|
|
450
|
+
text,
|
|
451
|
+
providerMessageId: result.id,
|
|
452
|
+
sender: context,
|
|
453
|
+
});
|
|
454
|
+
|
|
383
455
|
return ok(`Message sent (ID: ${result.id}${threadSuffix}).`);
|
|
384
456
|
} catch (e) {
|
|
385
457
|
// A cancelled turn is not a send failure: let it reach the executor's
|
|
@@ -23,7 +23,7 @@ sqlite3 "$VELLUM_WORKSPACE_DIR/data/db/assistant.db" \
|
|
|
23
23
|
|
|
24
24
|
This returns all messages in chronological order with:
|
|
25
25
|
|
|
26
|
-
- `role: "user"` - caller speech and system events
|
|
26
|
+
- `role: "user"` - caller speech (prefixed with `[SPEAKER]` tags) and system events
|
|
27
27
|
- `role: "assistant"` - assistant responses, including `text` content and any `tool_use`/`tool_result` blocks
|
|
28
28
|
|
|
29
29
|
## Quick one-liner for the most recent call
|
|
@@ -209,6 +209,7 @@ When you mention a schedule or a conversation it owns in Vellum chat, write a ma
|
|
|
209
209
|
|
|
210
210
|
Use these paths only in Vellum chat. Do not use them in Slack, Telegram, Discord, email, or notifications. Those surfaces cannot navigate `/assistant/...` routes.
|
|
211
211
|
|
|
212
|
+
|
|
212
213
|
### Anchored & Ambiguous Relative Time
|
|
213
214
|
|
|
214
215
|
Phrases like "at the 45 minute mark", "at the top of the hour", "at noon", or "20 minutes in" are **clock-position or anchored relative time** expressions. Do NOT treat them as offsets from now.
|
|
@@ -255,13 +256,13 @@ Write the delivery step into the `message` when you create the schedule — not
|
|
|
255
256
|
|
|
256
257
|
A schedule whose message has no delivery step is not finished. Before calling `schedule_create` in `execute` mode, read your own message back and check that it says where the output goes.
|
|
257
258
|
|
|
258
|
-
There is a safety net, and it is not a substitute for the above. When an execute-mode run finishes with user-facing output and
|
|
259
|
+
There is a safety net, and it is not a substitute for the above. When an execute-mode run finishes with user-facing output and delivered nothing — no `assistant notifications send`, no `messaging_send`, no Slack `chat.postMessage` — the assistant sends a notification carrying the run's final reply, so a schedule can no longer run and leave no trace. It fires on the raw reply — whatever the run happened to end on, at whatever length. An authored delivery step gets a title and body you chose, sent at the moment you chose. Rely on the net and you get the machine's guess instead.
|
|
259
260
|
|
|
260
261
|
Choose the right delivery tool based on the content:
|
|
261
262
|
|
|
262
|
-
- **Rich content** (digests, summaries, reports):
|
|
263
|
+
- **Rich content** (digests, summaries, reports): For Gmail, use `messaging_send` with the target platform and conversation ID. For Slack, call `chat.postMessage` through `assistant oauth request`, with the provider the **slack** skill says to pass for posting on this workspace (`slack_channel` when the bot is set up; where only the `slack` integration exists, the skill says to tell the user before posting as them), never through `curl` or a revealed token. This preserves the full content and posts directly.
|
|
263
264
|
- **Short alerts** (status updates, completion notices): Use `assistant notifications send` via `bash` to let the notification router pick the best channel. Note: the router's decision engine rewrites content into short alerts, so it is not suitable for rich content.
|
|
264
265
|
|
|
265
266
|
Example schedule message for a Slack digest:
|
|
266
267
|
|
|
267
|
-
> "Scan my Slack channels for the last 24 hours using `assistant oauth request` for every Slack Web API
|
|
268
|
+
> "Scan my Slack channels for the last 24 hours using `assistant oauth request` for every Slack Web API call, with the provider the slack skill names for this workspace, then post the summary with `chat.postMessage` through the same command to the channel the user named."
|
|
@@ -124,14 +124,7 @@ their ear. Silence is the cue that it is their turn.
|
|
|
124
124
|
|
|
125
125
|
**Advance on evidence, not on time.** Move to the next step when a fresh
|
|
126
126
|
picture shows this one done, or when they tell you it is. Do not move on
|
|
127
|
-
because a plausible amount of time has passed.
|
|
128
|
-
|
|
129
|
-
The most direct telling is automatic. When the user clicks the control an
|
|
130
|
-
arrow is pointing at, a message arrives as their turn saying they clicked it,
|
|
131
|
-
by name, and that mark comes down on its own. Treat it as the step done: say
|
|
132
|
-
what comes next and point at it. Nothing arrives for a click anywhere else,
|
|
133
|
-
and nothing arrives for a ring, so for those the picture and their words are
|
|
134
|
-
still the evidence. If the next picture shows the
|
|
127
|
+
because a plausible amount of time has passed. If the next picture shows the
|
|
135
128
|
step not done, or done to the wrong thing, point at the same place again with
|
|
136
129
|
a shorter caption and say what you saw. Pointing at the next step while the
|
|
137
130
|
previous one is still open is how someone ends up two steps behind a mark.
|
|
@@ -53,10 +53,7 @@ describe("screen_point_at", () => {
|
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
expect(result.isError).toBe(true);
|
|
56
|
-
expect(result.content).toContain(
|
|
57
|
-
"The Vellum desktop app is needed to view or control your screen",
|
|
58
|
-
);
|
|
59
|
-
expect(result.content).toContain("https://www.vellum.ai/downloads");
|
|
56
|
+
expect(result.content).toContain("connected desktop client");
|
|
60
57
|
});
|
|
61
58
|
|
|
62
59
|
/** Drawing on the user's screen is a side effect a stopped turn must not have. */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"tools": [
|
|
4
4
|
{
|
|
5
5
|
"name": "scaffold_managed_skill",
|
|
6
|
-
"description": "Create or update a managed skill in {workspaceDir}/skills. The skill becomes available for skill_load when a valid top-level SKILL.md is written under the skill directory. Never persist a skill without explicit user consent. Before persisting, test the snippet: write to a temp file with bash and run with `bun run /tmp/vellum-eval/snippet.ts`. Iterate up to 3 attempts, then ask the user. Clean up temp files after. Do not use file_write for temp files outside the working directory.",
|
|
6
|
+
"description": "Create or update a managed skill in {workspaceDir}/skills. The skill becomes available for skill_load when a valid top-level SKILL.md is written under the skill directory. Never persist a skill without explicit user consent. Before persisting, test the snippet: write to a temp file with bash and run with `bun run /tmp/vellum-eval/snippet.ts`. Iterate up to 3 attempts, then ask the user. Clean up temp files after. Do not use file_write for temp files outside the working directory. After a skill is written, the next turn may run in a recreated conversation due to file-watcher eviction - continue normally.",
|
|
7
7
|
"category": "skills",
|
|
8
8
|
"risk": "high",
|
|
9
9
|
"input_schema": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
"name": "delete_managed_skill",
|
|
95
|
-
"description": "Delete a managed skill directory from {workspaceDir}/skills. Never delete a skill without explicit user confirmation.",
|
|
95
|
+
"description": "Delete a managed skill directory from {workspaceDir}/skills. Never delete a skill without explicit user confirmation. After deletion, the next turn may run in a recreated conversation due to file-watcher eviction - continue normally.",
|
|
96
96
|
"category": "skills",
|
|
97
97
|
"risk": "high",
|
|
98
98
|
"input_schema": {
|
|
@@ -137,7 +137,7 @@ const VELLUM_PROFILE_IMPLS: ProfileImpls = {
|
|
|
137
137
|
// The managed latency class, also what the live-voice front model runs on.
|
|
138
138
|
// Its leading tokens are the turn-taking verdict, so what this profile
|
|
139
139
|
// optimizes is the tail of time-to-first-token rather than the median: a
|
|
140
|
-
// verdict slower than `
|
|
140
|
+
// verdict slower than `liveVoice.frontModel.endpointDecisionTimeoutMs`
|
|
141
141
|
// trips the speculative fail-open commit in live-voice-session.ts, which
|
|
142
142
|
// is audible dead air.
|
|
143
143
|
//
|
package/src/config/env.ts
CHANGED
|
@@ -229,8 +229,8 @@ export function setPlatformAssistantId(value: string | undefined): void {
|
|
|
229
229
|
* Platform assistant ID — UUID of this assistant on the platform.
|
|
230
230
|
*
|
|
231
231
|
* Resolved from the in-memory override (populated by providers-setup
|
|
232
|
-
* rehydration
|
|
233
|
-
* platform pushes the value).
|
|
232
|
+
* rehydration from the credential store at daemon startup, or by
|
|
233
|
+
* secret-routes when the platform pushes the value).
|
|
234
234
|
*/
|
|
235
235
|
export function getPlatformAssistantId(): string {
|
|
236
236
|
return _platformAssistantIdOverride ?? "";
|
|
@@ -29,6 +29,18 @@
|
|
|
29
29
|
"description": "Enable user-hosted onboarding flow",
|
|
30
30
|
"defaultEnabled": false
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
"id": "proactive-tips",
|
|
34
|
+
"scope": "client",
|
|
35
|
+
"key": "proactive-tips",
|
|
36
|
+
"label": "Proactive Tips",
|
|
37
|
+
"description": "Gates the dismissible proactive tip card in the web sidebar. String-valued so future A/B arms can be added as new values.",
|
|
38
|
+
"defaultEnabled": "off",
|
|
39
|
+
"values": [
|
|
40
|
+
"off",
|
|
41
|
+
"on"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
32
44
|
{
|
|
33
45
|
"id": "vision-mode",
|
|
34
46
|
"scope": "client",
|
|
@@ -442,14 +454,6 @@
|
|
|
442
454
|
"description": "Native notifications show the assistant's avatar as the icon with the assistant's name on line one. Same key the platform reads for APNs/FCM sender blocks.",
|
|
443
455
|
"defaultEnabled": false
|
|
444
456
|
},
|
|
445
|
-
{
|
|
446
|
-
"id": "local-notification-avatar",
|
|
447
|
-
"scope": "client",
|
|
448
|
-
"key": "local-notification-avatar",
|
|
449
|
-
"label": "Local Notification Avatar",
|
|
450
|
-
"description": "Shows the assistant name and avatar in notifications posted locally by native clients and supported browsers. Independent of remote push avatar presentation.",
|
|
451
|
-
"defaultEnabled": false
|
|
452
|
-
},
|
|
453
457
|
{
|
|
454
458
|
"id": "channel-conversation-sidecar",
|
|
455
459
|
"scope": "client",
|
|
@@ -474,14 +478,6 @@
|
|
|
474
478
|
"description": "Gates the seeded Figma OAuth provider. When off, the provider is hidden from GET /v1/oauth/providers, its get-by-id route, and the connect/update routes, so it cannot be listed or connected from the CLI, gateway, or web integrations list. The row is still seeded into oauth_providers on startup, and existing connections keep injecting credentials; only its visibility changes.",
|
|
475
479
|
"defaultEnabled": false
|
|
476
480
|
},
|
|
477
|
-
{
|
|
478
|
-
"id": "shopify-oauth",
|
|
479
|
-
"scope": "assistant",
|
|
480
|
-
"key": "shopify-oauth",
|
|
481
|
-
"label": "Shopify Integration",
|
|
482
|
-
"description": "Gates the seeded Shopify OAuth provider. When off, the provider is hidden from GET /v1/oauth/providers, its get-by-id route, and the connect/update routes, so it cannot be listed or connected from the CLI, gateway, or web integrations list. The row is still seeded into oauth_providers on startup, and existing connections keep injecting credentials; only its visibility changes. Off by default because Shopify is the first per-tenant provider: connecting needs the merchant's myshopify.com domain, and the shop-domain input in the clients ships separately from the seed.",
|
|
483
|
-
"defaultEnabled": false
|
|
484
|
-
},
|
|
485
481
|
{
|
|
486
482
|
"id": "chatgpt-device-code-login",
|
|
487
483
|
"scope": "client",
|
|
@@ -527,14 +523,6 @@
|
|
|
527
523
|
"label": "Send User Message Tool",
|
|
528
524
|
"description": "Route all user-facing assistant text through the send_user_message tool instead of streamed assistant text",
|
|
529
525
|
"defaultEnabled": false
|
|
530
|
-
},
|
|
531
|
-
{
|
|
532
|
-
"id": "assistant-desktop",
|
|
533
|
-
"scope": "assistant",
|
|
534
|
-
"key": "assistant-desktop",
|
|
535
|
-
"label": "Assistant Desktop",
|
|
536
|
-
"description": "Streams an interactive desktop from a containerized assistant pod to the web client over /v1/desktop/stream. Off: no desktop affordance is rendered. On: the chat header offers a desktop panel that views and controls the pod's display.",
|
|
537
|
-
"defaultEnabled": false
|
|
538
526
|
}
|
|
539
527
|
]
|
|
540
528
|
}
|
package/src/config/loader.ts
CHANGED
|
@@ -180,7 +180,6 @@ export function getDeploymentContextDefaults(): Record<string, unknown> {
|
|
|
180
180
|
"discord-oauth": managed,
|
|
181
181
|
"hubspot-oauth": managed,
|
|
182
182
|
"monday-oauth": managed,
|
|
183
|
-
"shopify-oauth": managed,
|
|
184
183
|
"stripe-link-oauth": managed,
|
|
185
184
|
"figma-oauth": managed,
|
|
186
185
|
"eventbrite-oauth": managed,
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
isMemoryV1Active,
|
|
7
7
|
isMemoryV2ExplicitlyDisabled,
|
|
8
8
|
isMemoryV3Live,
|
|
9
|
-
isSkillImprovementActive,
|
|
10
9
|
isV2InjectionEngineActive,
|
|
11
10
|
isV3TierActive,
|
|
12
11
|
usesConceptPageMemory,
|
|
@@ -56,16 +55,12 @@ function makeConfig(
|
|
|
56
55
|
enabled: TriState,
|
|
57
56
|
v2Enabled: TriState,
|
|
58
57
|
v3Live: TriState,
|
|
59
|
-
skillImprovement?: boolean,
|
|
60
58
|
): AssistantConfig {
|
|
61
59
|
return {
|
|
62
60
|
memory: {
|
|
63
61
|
...(enabled === undefined ? {} : { enabled }),
|
|
64
62
|
...(v2Enabled === undefined ? {} : { v2: { enabled: v2Enabled } }),
|
|
65
63
|
...(v3Live === undefined ? {} : { v3: { live: v3Live } }),
|
|
66
|
-
...(skillImprovement === undefined
|
|
67
|
-
? {}
|
|
68
|
-
: { retrospective: { skillImprovement } }),
|
|
69
64
|
},
|
|
70
65
|
} as AssistantConfig;
|
|
71
66
|
}
|
|
@@ -301,32 +296,6 @@ describe("v1-staleness guard is one condition", () => {
|
|
|
301
296
|
* proc-to-skills alias of `isMemoryV3Live` (which did not). One predicate now
|
|
302
297
|
* answers for both features.
|
|
303
298
|
*/
|
|
304
|
-
describe("skill improvement gate", () => {
|
|
305
|
-
test("defaults on for a live v3 tier", () => {
|
|
306
|
-
expect(isSkillImprovementActive(makeConfig(true, undefined, true))).toBe(
|
|
307
|
-
true,
|
|
308
|
-
);
|
|
309
|
-
expect(isSkillImprovementActive(makeConfig(undefined, undefined, true))).toBe(
|
|
310
|
-
true,
|
|
311
|
-
);
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
test("explicit opt-out disables skill improvement without disabling v3", () => {
|
|
315
|
-
const config = makeConfig(true, undefined, true, false);
|
|
316
|
-
|
|
317
|
-
expect(isV3TierActive(config)).toBe(true);
|
|
318
|
-
expect(isSkillImprovementActive(config)).toBe(false);
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
test("requires the live v3 tier even when explicitly enabled", () => {
|
|
322
|
-
const v2Config = makeConfig(true, true, false, true);
|
|
323
|
-
const memoryOffConfig = makeConfig(false, undefined, true, true);
|
|
324
|
-
|
|
325
|
-
expect(isSkillImprovementActive(v2Config)).toBe(false);
|
|
326
|
-
expect(isSkillImprovementActive(memoryOffConfig)).toBe(false);
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
|
|
330
299
|
describe("v3 tier is one condition", () => {
|
|
331
300
|
test("memory off suppresses the v3 tier even with memory.v3.live set", () => {
|
|
332
301
|
const config = makeConfig(false, undefined, true);
|
|
@@ -81,32 +81,28 @@ export function isMemoryV3Live(config: AssistantConfig): boolean {
|
|
|
81
81
|
* FEATURE asks this predicate; only the injection-suppression checks that must
|
|
82
82
|
* mirror the raw `memory.v3.live` key ask {@link isMemoryV3Live} directly.
|
|
83
83
|
*
|
|
84
|
-
* The
|
|
85
|
-
* (`supported`) and the cheap `graph_supported` bit on `GET /memory/stats`
|
|
86
|
-
* must agree with whether the graph can build from the v3 concept-page
|
|
87
|
-
* substrate.
|
|
84
|
+
* The two features gated on it, and why they must agree:
|
|
88
85
|
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
86
|
+
* - The memory concept graph — the single source of truth for both
|
|
87
|
+
* `GET /memory-graph` (`supported`) and the cheap `graph_supported` bit on
|
|
88
|
+
* `GET /memory/stats`, so the advertised capability and the actual build can
|
|
89
|
+
* never drift. The graph builds off the v3 concept-page substrate.
|
|
90
|
+
* - Procedural-memory-as-skills — the retrospective's skill-authoring step and
|
|
91
|
+
* its permission grant. Scoped to the v3 tier because skill retrieval rides
|
|
92
|
+
* the v3 lanes and the usage-prune stage lives in the v3 maintain job. That
|
|
93
|
+
* prune ships observe-first: with `memory.maintenance.skillPruneDays` at its
|
|
94
|
+
* default (`null`) it reports stale assistant-authored skills
|
|
95
|
+
* (`prunableSkills`) but deletes none — so a v3-tier assistant authors skills
|
|
96
|
+
* without an automatic retirement bound until a positive `skillPruneDays` is
|
|
97
|
+
* configured.
|
|
98
|
+
*
|
|
99
|
+
* Both write into memory on the user's behalf, so both honor the Memory
|
|
100
|
+
* opt-out identically: one predicate, one answer.
|
|
92
101
|
*/
|
|
93
102
|
export function isV3TierActive(config: AssistantConfig): boolean {
|
|
94
103
|
return isMemoryEnabled(config) && isMemoryV3Live(config);
|
|
95
104
|
}
|
|
96
105
|
|
|
97
|
-
/**
|
|
98
|
-
* Whether a retrospective may turn observed procedures into managed skills.
|
|
99
|
-
* This requires the v3 tier because skills are retrieved through its memory
|
|
100
|
-
* substrate, and it honors the retrospective-specific opt-out without
|
|
101
|
-
* disabling ordinary retrospective fact retention.
|
|
102
|
-
*/
|
|
103
|
-
export function isSkillImprovementActive(config: AssistantConfig): boolean {
|
|
104
|
-
return (
|
|
105
|
-
isV3TierActive(config) &&
|
|
106
|
-
config.memory?.retrospective?.skillImprovement !== false
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
106
|
/**
|
|
111
107
|
* Minimal structural view of the memory config the concept-page gate reads.
|
|
112
108
|
* Accepting the shape (rather than the full `MemoryConfig`) lets call sites
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Rehydrate the in-memory platform identity/URL overrides
|
|
2
|
+
* Rehydrate the in-memory platform identity/URL overrides from the credential
|
|
3
|
+
* store at process startup.
|
|
3
4
|
*
|
|
4
5
|
* These overrides (`setPlatformBaseUrl` and the platform ID setters in
|
|
5
6
|
* `config/env.ts`) are normally only populated at runtime by the secret-routes
|
|
@@ -9,17 +10,18 @@
|
|
|
9
10
|
* environment default (e.g. dev-platform) while the credential store holds the
|
|
10
11
|
* real production values, and requests are sent to the wrong environment.
|
|
11
12
|
*
|
|
12
|
-
* Bound platform ids come from `POST /v1/internal/assistants/validate/`,
|
|
13
|
-
* which trades the assistant API key for assistant/organization/user ids.
|
|
14
|
-
*
|
|
15
13
|
* Each field is best-effort: a credential-store read failure is logged and
|
|
16
14
|
* skipped so a single missing value never blocks startup.
|
|
17
15
|
*/
|
|
18
16
|
import { credentialKey } from "../security/credential-key.js";
|
|
19
17
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
20
18
|
import { getLogger } from "../util/logger.js";
|
|
21
|
-
import {
|
|
22
|
-
|
|
19
|
+
import {
|
|
20
|
+
setPlatformAssistantId,
|
|
21
|
+
setPlatformBaseUrl,
|
|
22
|
+
setPlatformOrganizationId,
|
|
23
|
+
setPlatformUserId,
|
|
24
|
+
} from "./env.js";
|
|
23
25
|
|
|
24
26
|
const log = getLogger("platform-rehydration");
|
|
25
27
|
|
|
@@ -45,16 +47,30 @@ async function rehydrateField(
|
|
|
45
47
|
|
|
46
48
|
/**
|
|
47
49
|
* Rehydrate the platform base URL and the related platform IDs (assistant,
|
|
48
|
-
* organization, user)
|
|
50
|
+
* organization, user) from the credential store into their in-memory
|
|
51
|
+
* overrides. Safe to call more than once.
|
|
49
52
|
*/
|
|
50
53
|
export async function rehydratePlatformCredentials(): Promise<void> {
|
|
51
|
-
// Base URL first so managed proxy activation
|
|
52
|
-
// the
|
|
54
|
+
// Base URL first so managed proxy activation resolves the correct
|
|
55
|
+
// environment for the ID lookups and every request that follows.
|
|
53
56
|
await rehydrateField(
|
|
54
57
|
"platform_base_url",
|
|
55
58
|
setPlatformBaseUrl,
|
|
56
59
|
"platform base URL",
|
|
57
60
|
);
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
await rehydrateField(
|
|
62
|
+
"platform_assistant_id",
|
|
63
|
+
setPlatformAssistantId,
|
|
64
|
+
"platform assistant ID",
|
|
65
|
+
);
|
|
66
|
+
await rehydrateField(
|
|
67
|
+
"platform_organization_id",
|
|
68
|
+
setPlatformOrganizationId,
|
|
69
|
+
"platform organization ID",
|
|
70
|
+
);
|
|
71
|
+
await rehydrateField(
|
|
72
|
+
"platform_user_id",
|
|
73
|
+
setPlatformUserId,
|
|
74
|
+
"platform user ID",
|
|
75
|
+
);
|
|
60
76
|
}
|
package/src/config/schema.ts
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
AuditLogConfigSchema,
|
|
42
42
|
LogFileConfigSchema,
|
|
43
43
|
} from "./schemas/logging.js";
|
|
44
|
+
import { McpConfigSchema } from "./schemas/mcp.js";
|
|
44
45
|
import { MemoryConfigSchema } from "./schemas/memory.js";
|
|
45
46
|
import { MigrationsConfigSchema } from "./schemas/migrations.js";
|
|
46
47
|
import { MonitoringConfigSchema } from "./schemas/monitoring.js";
|
|
@@ -61,7 +62,6 @@ import {
|
|
|
61
62
|
} from "./schemas/timeouts.js";
|
|
62
63
|
import { ToolsConfigSchema } from "./schemas/tools.js";
|
|
63
64
|
import { UserRoutesConfigSchema } from "./schemas/user-routes.js";
|
|
64
|
-
import { VoiceConfigSchema } from "./schemas/voice.js";
|
|
65
65
|
import { WorkflowsConfigSchema } from "./schemas/workflows.js";
|
|
66
66
|
import { WorkspaceGitConfigSchema } from "./schemas/workspace-git.js";
|
|
67
67
|
|
|
@@ -108,6 +108,7 @@ export const AssistantConfigSchema = z.object({
|
|
|
108
108
|
),
|
|
109
109
|
journal: JournalConfigSchema.default(JournalConfigSchema.parse({})),
|
|
110
110
|
backup: BackupConfigSchema.default(BackupConfigSchema.parse({})),
|
|
111
|
+
mcp: McpConfigSchema.default(McpConfigSchema.parse({})),
|
|
111
112
|
acp: AcpConfigSchema.default(AcpConfigSchema.parse({})),
|
|
112
113
|
skills: SkillsConfigSchema.default(SkillsConfigSchema.parse({})),
|
|
113
114
|
workspaceGit: WorkspaceGitConfigSchema.default(
|
|
@@ -118,7 +119,6 @@ export const AssistantConfigSchema = z.object({
|
|
|
118
119
|
twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
|
|
119
120
|
calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
|
|
120
121
|
liveVoice: LiveVoiceConfigSchema.default(LiveVoiceConfigSchema.parse({})),
|
|
121
|
-
voice: VoiceConfigSchema.default(VoiceConfigSchema.parse({})),
|
|
122
122
|
sight: SightConfigSchema.default(SightConfigSchema.parse({})),
|
|
123
123
|
whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
|
|
124
124
|
telegram: TelegramConfigSchema.default(TelegramConfigSchema.parse({})),
|