@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
|
@@ -7,22 +7,7 @@ export const DESKTOP_APP_DOWNLOAD_URL = "https://www.vellum.ai/downloads";
|
|
|
7
7
|
export const CHROME_WEB_STORE_INSTALL_URL =
|
|
8
8
|
"https://chromewebstore.google.com/detail/vellum-assistant-browser/hphbdmpffeigpcdjkckleobjmhhokpne";
|
|
9
9
|
|
|
10
|
-
export const DESKTOP_APP_INSTALL_HINT = `
|
|
11
|
-
|
|
12
|
-
export type DesktopAppCapability = "files" | "screen" | "shell" | "apps";
|
|
13
|
-
|
|
14
|
-
const DESKTOP_APP_CAPABILITY_ACTION: Record<DesktopAppCapability, string> = {
|
|
15
|
-
files: "access files on your computer",
|
|
16
|
-
screen: "view or control your screen",
|
|
17
|
-
shell: "run commands on your computer",
|
|
18
|
-
apps: "control apps on your computer",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export function formatDesktopAppRequired(
|
|
22
|
-
capability: DesktopAppCapability,
|
|
23
|
-
): string {
|
|
24
|
-
return `Error: The Vellum desktop app is needed to ${DESKTOP_APP_CAPABILITY_ACTION[capability]}. ${DESKTOP_APP_INSTALL_HINT}`;
|
|
25
|
-
}
|
|
10
|
+
export const DESKTOP_APP_INSTALL_HINT = `Install the Vellum desktop app: ${DESKTOP_APP_DOWNLOAD_URL}`;
|
|
26
11
|
|
|
27
12
|
/** User-facing install step for status userActions and command-failure hints. */
|
|
28
13
|
export const CHROME_EXTENSION_INSTALL_HINT = `Install the Vellum Assistant Chrome extension from the Chrome Web Store: ${CHROME_WEB_STORE_INSTALL_URL}`;
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { RiskLevel } from "../../permissions/types.js";
|
|
11
|
-
import { formatDesktopAppRequired } from "../capability-offer.js";
|
|
12
11
|
import type {
|
|
13
12
|
ToolContext,
|
|
14
13
|
ToolDefinition,
|
|
@@ -32,7 +31,7 @@ function proxyExecute(toolName: string) {
|
|
|
32
31
|
): Promise<ToolExecutionResult> => {
|
|
33
32
|
if (!context.proxyToolResolver) {
|
|
34
33
|
return {
|
|
35
|
-
content:
|
|
34
|
+
content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires a connected desktop client.`,
|
|
36
35
|
isError: true,
|
|
37
36
|
};
|
|
38
37
|
}
|
|
@@ -457,8 +456,7 @@ export const computerUseObserveTool = {
|
|
|
457
456
|
type: "integer",
|
|
458
457
|
minimum: 1,
|
|
459
458
|
maximum: 4294967295,
|
|
460
|
-
description:
|
|
461
|
-
"macOS only: capture this native CGWindowID instead of the desktop, including only its accessibility tree. Obtain a current native window ID first; do not guess or use a browser tab ID. Applies to this observation only, not subsequent actions. Requires a desktop helper with window-capture support. Screenshot coordinates are window-relative; use accessibility element IDs for later actions, not desktop scaling.",
|
|
459
|
+
description: "macOS only: capture this native CGWindowID instead of the desktop, including only its accessibility tree. Obtain a current native window ID first; do not guess or use a browser tab ID. Applies to this observation only, not subsequent actions. Requires a desktop helper with window-capture support. Screenshot coordinates are window-relative; use accessibility element IDs for later actions, not desktop scaling.",
|
|
462
460
|
},
|
|
463
461
|
target_client_id: {
|
|
464
462
|
type: "string",
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* the proxy resolver, which forwards the call to the connected desktop client.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { formatDesktopAppRequired } from "../capability-offer.js";
|
|
9
8
|
import { throwIfCancelled } from "../shared/abort.js";
|
|
10
9
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
11
10
|
|
|
@@ -46,7 +45,7 @@ export function forwardComputerUseProxyTool(
|
|
|
46
45
|
}
|
|
47
46
|
if (!context.proxyToolResolver) {
|
|
48
47
|
return Promise.resolve({
|
|
49
|
-
content:
|
|
48
|
+
content: `Cannot execute ${toolName}: no proxy resolver available. This tool requires a connected desktop client.`,
|
|
50
49
|
isError: true,
|
|
51
50
|
});
|
|
52
51
|
}
|
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
} from "@vellumai/credential-storage";
|
|
21
21
|
import type { CredentialRecord } from "@vellumai/service-contracts/credential-rpc";
|
|
22
22
|
|
|
23
|
-
import { createCesHttpRecordBackendIfConfigured } from "../../security/ces-http-record-backend.js";
|
|
24
23
|
import type { CredentialRecordBackend } from "../../security/ces-rpc-record-backend.js";
|
|
25
24
|
import { getLogger } from "../../util/logger.js";
|
|
26
25
|
import type { CredentialInjectionTemplate } from "./policy-types.js";
|
|
@@ -56,11 +55,6 @@ const CES_MEMORY_PATH = "ces-in-memory-credential-metadata";
|
|
|
56
55
|
let _store: StaticCredentialMetadataStore | undefined;
|
|
57
56
|
let _overridePath: string | null = null;
|
|
58
57
|
let _recordBackend: CredentialRecordBackend | undefined;
|
|
59
|
-
/**
|
|
60
|
-
* Test override for the CES HTTP listing fallback. `undefined` uses the
|
|
61
|
-
* production factory. `null` disables HTTP fallback.
|
|
62
|
-
*/
|
|
63
|
-
let _httpRecordBackendOverride: CredentialRecordBackend | null | undefined;
|
|
64
58
|
let _cesRecordsLoaded = false;
|
|
65
59
|
let _cesLoad: Promise<void> | undefined;
|
|
66
60
|
let _cesLoadGeneration = 0;
|
|
@@ -261,93 +255,6 @@ export function listCredentialMetadata(): CredentialMetadata[] {
|
|
|
261
255
|
return getStore().list() as CredentialMetadata[];
|
|
262
256
|
}
|
|
263
257
|
|
|
264
|
-
export type CredentialRecordListResult = {
|
|
265
|
-
records: CredentialMetadata[];
|
|
266
|
-
unreachable: boolean;
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
type ListedCredentialRecords = Array<{
|
|
270
|
-
account: string;
|
|
271
|
-
record: CredentialRecord;
|
|
272
|
-
}>;
|
|
273
|
-
|
|
274
|
-
function backendIsAvailable(backend: CredentialRecordBackend): boolean {
|
|
275
|
-
try {
|
|
276
|
-
return backend.isAvailable();
|
|
277
|
-
} catch {
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
async function listFromRecordBackend(
|
|
283
|
-
backend: CredentialRecordBackend,
|
|
284
|
-
): Promise<ListedCredentialRecords | null> {
|
|
285
|
-
if (!backendIsAvailable(backend)) {
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
return backend.list();
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
function resolveHttpRecordBackend(): CredentialRecordBackend | null {
|
|
292
|
-
if (_httpRecordBackendOverride !== undefined) {
|
|
293
|
-
return _httpRecordBackendOverride;
|
|
294
|
-
}
|
|
295
|
-
return createCesHttpRecordBackendIfConfigured();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
async function listFromHttpFallback(): Promise<ListedCredentialRecords | null> {
|
|
299
|
-
const httpBackend = resolveHttpRecordBackend();
|
|
300
|
-
if (!httpBackend) {
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
return listFromRecordBackend(httpBackend);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Live catalog from the credential record backend. Does not read the
|
|
308
|
-
* daemon in-process cache, so an outage cannot be mistaken for an empty
|
|
309
|
-
* vault. `unreachable` is true when the backend is missing, down, or
|
|
310
|
-
* the list RPC fails, and CES HTTP failover is also unavailable.
|
|
311
|
-
*
|
|
312
|
-
* When the attached backend is CES RPC (or none is attached), listing
|
|
313
|
-
* fails over to CES HTTP in containerized deployments so a down RPC
|
|
314
|
-
* socket does not hide a healthy vault sidecar. A successful empty
|
|
315
|
-
* catalog (`[]`) does not fall through to HTTP.
|
|
316
|
-
*
|
|
317
|
-
* The file-backed test store is the catalog when a test override path is set.
|
|
318
|
-
*/
|
|
319
|
-
export async function listCredentialRecordsLive(): Promise<CredentialRecordListResult> {
|
|
320
|
-
if (_overridePath) {
|
|
321
|
-
return {
|
|
322
|
-
records: getStore().list() as CredentialMetadata[],
|
|
323
|
-
unreachable: false,
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
if (_recordBackend) {
|
|
327
|
-
const remote = await listFromRecordBackend(_recordBackend);
|
|
328
|
-
if (remote !== null) {
|
|
329
|
-
return {
|
|
330
|
-
records: remote.map((entry) => entry.record as CredentialMetadata),
|
|
331
|
-
unreachable: false,
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
if (_recordBackend.name !== "ces-rpc") {
|
|
335
|
-
return { records: [], unreachable: true };
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
const httpRemote = await listFromHttpFallback();
|
|
339
|
-
if (httpRemote !== null) {
|
|
340
|
-
log.warn(
|
|
341
|
-
"CES RPC credential record list unavailable. Failing over to CES HTTP.",
|
|
342
|
-
);
|
|
343
|
-
return {
|
|
344
|
-
records: httpRemote.map((entry) => entry.record as CredentialMetadata),
|
|
345
|
-
unreachable: false,
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
return { records: [], unreachable: true };
|
|
349
|
-
}
|
|
350
|
-
|
|
351
258
|
/**
|
|
352
259
|
* Delete metadata for a credential.
|
|
353
260
|
*/
|
|
@@ -380,10 +287,3 @@ export function _setMetadataPath(path: string | null): void {
|
|
|
380
287
|
}
|
|
381
288
|
}
|
|
382
289
|
}
|
|
383
|
-
|
|
384
|
-
/** @internal Test-only: override the CES HTTP listing fallback. */
|
|
385
|
-
export function _setHttpRecordBackendForTests(
|
|
386
|
-
backend: CredentialRecordBackend | null | undefined,
|
|
387
|
-
): void {
|
|
388
|
-
_httpRecordBackendOverride = backend;
|
|
389
|
-
}
|
|
@@ -71,9 +71,8 @@ describe("host_file_edit cross-client guards", () => {
|
|
|
71
71
|
);
|
|
72
72
|
expect(result.isError).toBe(true);
|
|
73
73
|
expect(result.content).toContain(
|
|
74
|
-
"
|
|
74
|
+
"no client with host_file capability is connected",
|
|
75
75
|
);
|
|
76
|
-
expect(result.content).toContain("https://www.vellum.ai/downloads");
|
|
77
76
|
});
|
|
78
77
|
|
|
79
78
|
test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
|
|
@@ -4,7 +4,7 @@ import { supportsHostProxy } from "../../channels/types.js";
|
|
|
4
4
|
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
5
5
|
import { RiskLevel } from "../../permissions/types.js";
|
|
6
6
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
7
|
-
import {
|
|
7
|
+
import { desktopClientName } from "../client-os.js";
|
|
8
8
|
import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
|
|
9
9
|
import { formatEditDiff } from "../shared/filesystem/format-diff.js";
|
|
10
10
|
import { hostPolicy } from "../shared/filesystem/path-policy.js";
|
|
@@ -115,7 +115,7 @@ export const hostFileEditTool = {
|
|
|
115
115
|
!HostFileProxy.instance.isAvailable()
|
|
116
116
|
) {
|
|
117
117
|
return {
|
|
118
|
-
content:
|
|
118
|
+
content: `Error: no client with host_file capability is connected. Connect a ${desktopClientName(context)} client to use host_file from a non-desktop interface.`,
|
|
119
119
|
isError: true,
|
|
120
120
|
};
|
|
121
121
|
}
|
|
@@ -67,9 +67,8 @@ describe("host_file_read cross-client guards", () => {
|
|
|
67
67
|
);
|
|
68
68
|
expect(result.isError).toBe(true);
|
|
69
69
|
expect(result.content).toContain(
|
|
70
|
-
"
|
|
70
|
+
"no client with host_file capability is connected",
|
|
71
71
|
);
|
|
72
|
-
expect(result.content).toContain("https://www.vellum.ai/downloads");
|
|
73
72
|
});
|
|
74
73
|
|
|
75
74
|
test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
|
|
@@ -6,7 +6,7 @@ import { supportsHostProxy } from "../../channels/types.js";
|
|
|
6
6
|
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
7
7
|
import { RiskLevel } from "../../permissions/types.js";
|
|
8
8
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
9
|
-
import {
|
|
9
|
+
import { desktopClientName } from "../client-os.js";
|
|
10
10
|
import {
|
|
11
11
|
AUDIO_EXTENSIONS,
|
|
12
12
|
readAudioFile,
|
|
@@ -121,7 +121,7 @@ export const hostFileReadTool = {
|
|
|
121
121
|
!HostFileProxy.instance.isAvailable()
|
|
122
122
|
) {
|
|
123
123
|
return {
|
|
124
|
-
content:
|
|
124
|
+
content: `Error: no client with host_file capability is connected. Connect a ${desktopClientName(context)} client to use host_file from a non-desktop interface.`,
|
|
125
125
|
isError: true,
|
|
126
126
|
};
|
|
127
127
|
}
|
|
@@ -335,9 +335,8 @@ describe("host_file_transfer cross-client guards", () => {
|
|
|
335
335
|
|
|
336
336
|
expect(result.isError).toBe(true);
|
|
337
337
|
expect(result.content).toContain(
|
|
338
|
-
"
|
|
338
|
+
"no client with host_file capability is connected",
|
|
339
339
|
);
|
|
340
|
-
expect(result.content).toContain("https://www.vellum.ai/downloads");
|
|
341
340
|
expect(toSandboxCalls.length).toBe(0);
|
|
342
341
|
});
|
|
343
342
|
|
|
@@ -6,7 +6,7 @@ import { supportsHostProxy } from "../../channels/types.js";
|
|
|
6
6
|
import { HostTransferProxy } from "../../daemon/host-transfer-proxy.js";
|
|
7
7
|
import { RiskLevel } from "../../permissions/types.js";
|
|
8
8
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
9
|
-
import {
|
|
9
|
+
import { desktopClientName } from "../client-os.js";
|
|
10
10
|
import { declareDaemonActivityField } from "../schema-transforms.js";
|
|
11
11
|
import { sandboxPolicy } from "../shared/filesystem/path-policy.js";
|
|
12
12
|
import type {
|
|
@@ -126,7 +126,7 @@ export const hostFileTransferTool = {
|
|
|
126
126
|
!HostTransferProxy.instance.isAvailable()
|
|
127
127
|
) {
|
|
128
128
|
return {
|
|
129
|
-
content:
|
|
129
|
+
content: `Error: no client with host_file capability is connected. Connect a ${desktopClientName(context)} client to use host_file from a non-desktop interface.`,
|
|
130
130
|
isError: true,
|
|
131
131
|
};
|
|
132
132
|
}
|
|
@@ -67,9 +67,8 @@ describe("host_file_write cross-client guards", () => {
|
|
|
67
67
|
);
|
|
68
68
|
expect(result.isError).toBe(true);
|
|
69
69
|
expect(result.content).toContain(
|
|
70
|
-
"
|
|
70
|
+
"no client with host_file capability is connected",
|
|
71
71
|
);
|
|
72
|
-
expect(result.content).toContain("https://www.vellum.ai/downloads");
|
|
73
72
|
});
|
|
74
73
|
|
|
75
74
|
test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
|
|
@@ -4,7 +4,7 @@ import { supportsHostProxy } from "../../channels/types.js";
|
|
|
4
4
|
import { HostFileProxy } from "../../daemon/host-file-proxy.js";
|
|
5
5
|
import { RiskLevel } from "../../permissions/types.js";
|
|
6
6
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
7
|
-
import {
|
|
7
|
+
import { desktopClientName } from "../client-os.js";
|
|
8
8
|
import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
|
|
9
9
|
import { formatWriteSummary } from "../shared/filesystem/format-diff.js";
|
|
10
10
|
import { hostPolicy } from "../shared/filesystem/path-policy.js";
|
|
@@ -90,7 +90,7 @@ export const hostFileWriteTool = {
|
|
|
90
90
|
!HostFileProxy.instance.isAvailable()
|
|
91
91
|
) {
|
|
92
92
|
return {
|
|
93
|
-
content:
|
|
93
|
+
content: `Error: no client with host_file capability is connected. Connect a ${desktopClientName(context)} client to use host_file from a non-desktop interface.`,
|
|
94
94
|
isError: true,
|
|
95
95
|
};
|
|
96
96
|
}
|
|
@@ -170,22 +170,6 @@ afterEach(() => {
|
|
|
170
170
|
mockProxyAvailable = false;
|
|
171
171
|
});
|
|
172
172
|
|
|
173
|
-
describe("host_bash unavailable desktop-app recovery", () => {
|
|
174
|
-
test("offers the desktop app download when a web turn has no host connection", async () => {
|
|
175
|
-
const result = await hostShellTool.execute(
|
|
176
|
-
{ command: "pwd" },
|
|
177
|
-
makeContext({ transportInterface: "web" }),
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
expect(result.isError).toBe(true);
|
|
181
|
-
expect(result.content).toContain(
|
|
182
|
-
"The Vellum desktop app is needed to run commands on your computer",
|
|
183
|
-
);
|
|
184
|
-
expect(result.content).toContain("https://www.vellum.ai/downloads");
|
|
185
|
-
expect(result.content).toContain("Open it, then retry.");
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
173
|
// ---------------------------------------------------------------------------
|
|
190
174
|
// Proxy path — background: true
|
|
191
175
|
// ---------------------------------------------------------------------------
|
|
@@ -18,7 +18,10 @@ import { getConfig } from "../../config/loader.js";
|
|
|
18
18
|
import { HostBashProxy } from "../../daemon/host-bash-proxy.js";
|
|
19
19
|
import { RiskLevel } from "../../permissions/types.js";
|
|
20
20
|
import { wakeAgentForOpportunity } from "../../runtime/agent-wake.js";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
assistantEventHub,
|
|
23
|
+
broadcastMessage,
|
|
24
|
+
} from "../../runtime/assistant-event-hub.js";
|
|
22
25
|
import { conversationRevealNonce } from "../../runtime/reveal-nonce.js";
|
|
23
26
|
import { redactSecrets } from "../../security/secret-scanner.js";
|
|
24
27
|
import {
|
|
@@ -36,7 +39,7 @@ import {
|
|
|
36
39
|
registerBackgroundTool,
|
|
37
40
|
removeBackgroundTool,
|
|
38
41
|
} from "../background-tool-registry.js";
|
|
39
|
-
import {
|
|
42
|
+
import { desktopClientName } from "../client-os.js";
|
|
40
43
|
import {
|
|
41
44
|
attachBoundedStdio,
|
|
42
45
|
MAX_OUTPUT_LENGTH,
|
|
@@ -139,7 +142,7 @@ export const hostShellInputSchema = z.looseObject({
|
|
|
139
142
|
target_client_id: z
|
|
140
143
|
.string()
|
|
141
144
|
.describe(
|
|
142
|
-
"
|
|
145
|
+
"ID of the specific client to execute this command on. Required when multiple clients support host_bash; omit when only one client is connected. Obtain IDs from `assistant clients list --capability host_bash`.",
|
|
143
146
|
)
|
|
144
147
|
.optional()
|
|
145
148
|
.catch(undefined),
|
|
@@ -200,7 +203,20 @@ export const hostShellTool = {
|
|
|
200
203
|
const config = getConfig();
|
|
201
204
|
const { shellDefaultTimeoutSec, shellMaxTimeoutSec } = config.timeouts;
|
|
202
205
|
|
|
206
|
+
// Guard: non-host-proxy interfaces need an explicit target when multiple
|
|
207
|
+
// capable clients are connected to avoid ambiguous untargeted broadcasts.
|
|
203
208
|
const transportInterface = context.transportInterface;
|
|
209
|
+
if (
|
|
210
|
+
targetClientId == null &&
|
|
211
|
+
transportInterface != null &&
|
|
212
|
+
!supportsHostProxy(transportInterface) &&
|
|
213
|
+
assistantEventHub.listClientsByCapability("host_bash").length > 1
|
|
214
|
+
) {
|
|
215
|
+
return {
|
|
216
|
+
content: `Error: multiple clients support host_bash. Specify which client to use with \`target_client_id\`. Run \`assistant clients list --capability host_bash\` to see client IDs and labels.`,
|
|
217
|
+
isError: true,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
204
220
|
|
|
205
221
|
// Guard: non-host-proxy interfaces with no capable clients connected.
|
|
206
222
|
if (
|
|
@@ -210,7 +226,7 @@ export const hostShellTool = {
|
|
|
210
226
|
!HostBashProxy.instance.isAvailable()
|
|
211
227
|
) {
|
|
212
228
|
return {
|
|
213
|
-
content:
|
|
229
|
+
content: `Error: no client with host_bash capability is connected. Connect a ${desktopClientName(context)} client to use host_bash from a non-desktop interface.`,
|
|
214
230
|
isError: true,
|
|
215
231
|
};
|
|
216
232
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getConfig } from "../config/loader.js";
|
|
2
|
-
import {
|
|
2
|
+
import { isV3TierActive } from "../config/memory-v3-gate.js";
|
|
3
3
|
import type { ExecutionContext } from "../permissions/approval-policy.js";
|
|
4
4
|
import type { ChannelPermissionCoordinates } from "../permissions/channel-permission-query.js";
|
|
5
5
|
import type { PolicyContext } from "../permissions/types.js";
|
|
@@ -63,11 +63,12 @@ export function buildPolicyContext(
|
|
|
63
63
|
requestOrigin: context?.requestOrigin,
|
|
64
64
|
...channelCoordinatesFromToolContext(context),
|
|
65
65
|
requesterContactId: context?.requesterContactId,
|
|
66
|
-
// Precompute the
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
// inactive just by reading
|
|
70
|
-
|
|
66
|
+
// Precompute the proc-to-skills gate — the v3 tier being active, i.e.
|
|
67
|
+
// memory on AND v3 live — here so the permission checker, a leaf module
|
|
68
|
+
// that must not read config, can deny the memory-retrospective
|
|
69
|
+
// skill-authoring grant whenever the feature is inactive just by reading
|
|
70
|
+
// this boolean.
|
|
71
|
+
procToSkillsActive: isV3TierActive(getConfig()),
|
|
71
72
|
};
|
|
72
73
|
|
|
73
74
|
const ownerKind = getToolOwner(tool.name)?.kind;
|
|
@@ -484,9 +484,9 @@ function spawnCancelledResult(label: string): ToolExecutionResult {
|
|
|
484
484
|
* repeat-spawn guard folds, so a consult has to record it the same way every
|
|
485
485
|
* other spawn does or the guard could never match one consult against another.
|
|
486
486
|
*
|
|
487
|
-
* The context pack is best effort:
|
|
488
|
-
*
|
|
489
|
-
* section
|
|
487
|
+
* The context pack is best effort: the parent conversation is looked up only
|
|
488
|
+
* for its warm skill catalog, so an unresolvable one (e.g. evicted) costs the
|
|
489
|
+
* skills section of the pack and nothing else.
|
|
490
490
|
*
|
|
491
491
|
* The budget is the advisor's alone. It is the only spawn the agent may issue
|
|
492
492
|
* unprompted and the only one that runs on the premium profile, so it is the
|
|
@@ -502,18 +502,21 @@ async function buildAdvisorFields(
|
|
|
502
502
|
maxRuntimeMs: number;
|
|
503
503
|
maxToolCalls: number;
|
|
504
504
|
}> {
|
|
505
|
+
const parentConversation = findConversation(context.conversationId);
|
|
505
506
|
// Situational awareness for the advisor: the parent's live tool set, the
|
|
506
507
|
// full skill catalog, and its workspace. Assembled off the per-turn
|
|
507
508
|
// ToolContext snapshot (trust, channel) so the personal-memory sections are
|
|
508
509
|
// gated exactly like the runtime injectors. A null pack just means the
|
|
509
|
-
// consult runs on the brief alone.
|
|
510
|
-
// `loadSkillCatalog()` inside the context pack, not a conversation snapshot.
|
|
510
|
+
// consult runs on the brief alone.
|
|
511
511
|
const situationalContext = await buildAdvisorContext({
|
|
512
512
|
conversationId: context.conversationId,
|
|
513
513
|
workingDir: context.workingDir,
|
|
514
514
|
allowedToolNames: context.allowedToolNames,
|
|
515
515
|
trustClass: context.trustClass,
|
|
516
516
|
enabledPluginSet: context.enabledPluginSet,
|
|
517
|
+
// The parent's warm per-turn catalog keeps the synchronous on-disk catalog
|
|
518
|
+
// scan out of the spawn path.
|
|
519
|
+
skillCatalog: parentConversation?.skillProjectionCache?.catalog,
|
|
517
520
|
});
|
|
518
521
|
return {
|
|
519
522
|
requestText: advisorRequestText(objective, situationalContext),
|
|
@@ -14,6 +14,14 @@ import type {
|
|
|
14
14
|
/**
|
|
15
15
|
* How a watch retrospective hands its report to the daemon.
|
|
16
16
|
*
|
|
17
|
+
* **The card cannot come from `ui_show`.** A retrospective runs as a
|
|
18
|
+
* `clientless` wake, which pins the turn non-interactive, and
|
|
19
|
+
* `conversation-tool-setup` gates the whole `ui_surface` tool family on a
|
|
20
|
+
* client being present (`return channelCapabilities?.supportsDynamicUi ??
|
|
21
|
+
* !hasNoClient`). So `ui_show` is not merely denied in this turn, it is absent
|
|
22
|
+
* from the tool set, and a retrospective told to call it can only report that
|
|
23
|
+
* it cannot. This tool is an ordinary one and passes that gate untouched.
|
|
24
|
+
*
|
|
17
25
|
* **It records; it does not render.** The executor validates the payload and
|
|
18
26
|
* returns, and nothing here writes to the conversation. What makes the card is
|
|
19
27
|
* `watch-retro.ts` reading this call back out of the turn's own history once
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
baseLanguageSubtag,
|
|
5
|
-
fixedPhraseLanguage,
|
|
6
|
-
localizedOrDefault,
|
|
7
|
-
} from "../language-subtag.js";
|
|
3
|
+
import { baseLanguageSubtag, localizedOrDefault } from "../language-subtag.js";
|
|
8
4
|
|
|
9
5
|
describe("baseLanguageSubtag", () => {
|
|
10
6
|
test("lowercases a bare tag", () => {
|
|
@@ -56,21 +52,3 @@ describe("localizedOrDefault", () => {
|
|
|
56
52
|
expect(localizedOrDefault(table, "__proto__", "fallback")).toBe("fallback");
|
|
57
53
|
});
|
|
58
54
|
});
|
|
59
|
-
|
|
60
|
-
describe("fixedPhraseLanguage", () => {
|
|
61
|
-
const table = { en: "one", es: "uno" };
|
|
62
|
-
|
|
63
|
-
test("pins English when the speaker's language has no table entry", () => {
|
|
64
|
-
expect(fixedPhraseLanguage(table, "ko")).toBe("en");
|
|
65
|
-
expect(fixedPhraseLanguage(table, "ar-EG")).toBe("en");
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("rides the speaker's language when the table covers it", () => {
|
|
69
|
-
expect(fixedPhraseLanguage(table, "es")).toBeUndefined();
|
|
70
|
-
expect(fixedPhraseLanguage(table, "es-419")).toBeUndefined();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("carries no hint when the language is unknown", () => {
|
|
74
|
-
expect(fixedPhraseLanguage(table, undefined)).toBeUndefined();
|
|
75
|
-
});
|
|
76
|
-
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared `'error'`-event handler for `fs.watch()` FSWatchers.
|
|
3
|
+
*
|
|
4
|
+
* An `FSWatcher` is an EventEmitter. When the underlying inotify/FSEvents
|
|
5
|
+
* backend fails *after* the watch was established — e.g. ENOSPC when the
|
|
6
|
+
* kernel's `fs.inotify.max_user_watches` limit is exhausted while walking a
|
|
7
|
+
* recursive watch into a large subtree (a plugin's `node_modules`), or ENXIO
|
|
8
|
+
* when a Unix socket file appears in a watched directory — the failure is
|
|
9
|
+
* delivered asynchronously as an `'error'` event rather than a synchronous
|
|
10
|
+
* throw from `watch()`. An emitter with no `'error'` listener rethrows, which
|
|
11
|
+
* surfaces as an `uncaughtException` and takes the whole daemon down (→
|
|
12
|
+
* CrashLoopBackOff).
|
|
13
|
+
*
|
|
14
|
+
* Attaching this handler degrades the failure to "this watcher stops
|
|
15
|
+
* delivering events", in line with the daemon startup philosophy: a subsystem
|
|
16
|
+
* failure must never crash the process.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { FSWatcher } from "node:fs";
|
|
20
|
+
|
|
21
|
+
import type { Logger } from "pino";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Attach a resilient `'error'` listener so async FSWatcher failures are logged
|
|
25
|
+
* instead of crashing the process. Pass the owning module's logger and the
|
|
26
|
+
* watched directory for diagnostic context.
|
|
27
|
+
*/
|
|
28
|
+
export function attachFsWatcherErrorHandler(
|
|
29
|
+
watcher: FSWatcher,
|
|
30
|
+
log: Logger,
|
|
31
|
+
dir: string,
|
|
32
|
+
): void {
|
|
33
|
+
watcher.on("error", (err) => {
|
|
34
|
+
log.warn({ err, dir }, "FSWatcher error (non-fatal, continuing)");
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -41,19 +41,3 @@ export function localizedOrDefault<T>(
|
|
|
41
41
|
? (table[baseLanguageSubtag(language)!] as T)
|
|
42
42
|
: fallback;
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The TTS language hint for a fixed phrase picked from a localized table:
|
|
47
|
-
* "en" when the speaker has a language the table does not cover (the
|
|
48
|
-
* picker fell back to English text, which must not be synthesized under
|
|
49
|
-
* an ar/ko/ta hint), undefined otherwise (the phrase rides the speaker's
|
|
50
|
-
* language, or carries no hint at all when the language is unknown).
|
|
51
|
-
*/
|
|
52
|
-
export function fixedPhraseLanguage(
|
|
53
|
-
table: Readonly<Record<string, unknown>>,
|
|
54
|
-
language: string | undefined,
|
|
55
|
-
): string | undefined {
|
|
56
|
-
return language !== undefined && !hasLocalizedEntry(table, language)
|
|
57
|
-
? "en"
|
|
58
|
-
: undefined;
|
|
59
|
-
}
|
package/src/util/platform.ts
CHANGED
|
@@ -470,14 +470,6 @@ export function getWorkspaceConfigPath(): string {
|
|
|
470
470
|
return join(getWorkspaceDir(), "config.json");
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
/** Filename for the user-owned Agent Plugins MCP document. */
|
|
474
|
-
export const WORKSPACE_MCP_FILENAME = "mcp.json";
|
|
475
|
-
|
|
476
|
-
/** Returns $VELLUM_WORKSPACE_DIR/mcp.json */
|
|
477
|
-
export function getWorkspaceMcpConfigPath(): string {
|
|
478
|
-
return join(getWorkspaceDir(), WORKSPACE_MCP_FILENAME);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
473
|
/** Returns $VELLUM_WORKSPACE_DIR/skills */
|
|
482
474
|
export function getWorkspaceSkillsDir(): string {
|
|
483
475
|
return join(getWorkspaceDir(), "skills");
|