@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
|
@@ -159,31 +159,3 @@ describe("serializeConversationSummary · enabledPlugins", () => {
|
|
|
159
159
|
expect("enabledPlugins" in summary).toBe(false);
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
|
-
|
|
163
|
-
describe("serializeConversationSummary · title keys", () => {
|
|
164
|
-
test("resolves a stored title key for the locale", () => {
|
|
165
|
-
const summary = serializeConversationSummary({
|
|
166
|
-
conversation: makeConversationRow({
|
|
167
|
-
title: "conversation.title.generating",
|
|
168
|
-
}),
|
|
169
|
-
displayMeta: { displayOrder: null, isPinned: false, groupId: null },
|
|
170
|
-
parentCache: new Map(),
|
|
171
|
-
isProcessing: false,
|
|
172
|
-
locale: "es",
|
|
173
|
-
});
|
|
174
|
-
expect(summary.title).toBe("Generando título...");
|
|
175
|
-
expect("titleState" in summary).toBe(false);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
test("passes a stored display string through", () => {
|
|
179
|
-
const summary = serialize(
|
|
180
|
-
makeConversationRow({ title: "Untitled Conversation" }),
|
|
181
|
-
);
|
|
182
|
-
expect(summary.title).toBe("Untitled Conversation");
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test("passes a custom title through", () => {
|
|
186
|
-
const summary = serialize(makeConversationRow({ title: "Weekly planning" }));
|
|
187
|
-
expect(summary.title).toBe("Weekly planning");
|
|
188
|
-
});
|
|
189
|
-
});
|
|
@@ -8,10 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
import { parseChannelId } from "../../channels/types.js";
|
|
10
10
|
import { normalizeConversationType } from "../../daemon/message-types/shared.js";
|
|
11
|
-
import {
|
|
12
|
-
resolveConversationTitle,
|
|
13
|
-
type SupportedLocale,
|
|
14
|
-
} from "../../i18n/index.js";
|
|
15
11
|
import { buildChannelBindingMetadata } from "../../messaging/channel-binding-metadata.js";
|
|
16
12
|
import {
|
|
17
13
|
type AttentionState,
|
|
@@ -82,7 +78,6 @@ interface ForkLineage {
|
|
|
82
78
|
function buildForkLineage(
|
|
83
79
|
conversation: ConversationRow,
|
|
84
80
|
parentCache: Map<string, ConversationRow | null>,
|
|
85
|
-
locale?: SupportedLocale,
|
|
86
81
|
): ForkLineage {
|
|
87
82
|
const parentConversationId = conversation.forkParentConversationId;
|
|
88
83
|
const parentMessageId = conversation.forkParentMessageId;
|
|
@@ -106,7 +101,7 @@ function buildForkLineage(
|
|
|
106
101
|
forkParent: {
|
|
107
102
|
conversationId: parentConversationId,
|
|
108
103
|
messageId: parentMessageId,
|
|
109
|
-
title:
|
|
104
|
+
title: parentConversation.title ?? "Untitled",
|
|
110
105
|
},
|
|
111
106
|
};
|
|
112
107
|
}
|
|
@@ -183,11 +178,6 @@ export function serializeConversationSummary(params: {
|
|
|
183
178
|
* with no daemon-store coupling.
|
|
184
179
|
*/
|
|
185
180
|
isProcessing: boolean;
|
|
186
|
-
/**
|
|
187
|
-
* Locale used to resolve stored title keys. Omitted locale is English
|
|
188
|
-
* inside {@link resolveConversationTitle}.
|
|
189
|
-
*/
|
|
190
|
-
locale?: SupportedLocale;
|
|
191
181
|
}) {
|
|
192
182
|
const {
|
|
193
183
|
conversation,
|
|
@@ -196,15 +186,14 @@ export function serializeConversationSummary(params: {
|
|
|
196
186
|
displayMeta,
|
|
197
187
|
parentCache,
|
|
198
188
|
isProcessing,
|
|
199
|
-
locale,
|
|
200
189
|
} = params;
|
|
201
190
|
const originChannel = parseChannelId(conversation.originChannel);
|
|
202
191
|
const assistantAttention = buildAssistantAttention(attentionState);
|
|
203
|
-
const forkLineage = buildForkLineage(conversation, parentCache
|
|
192
|
+
const forkLineage = buildForkLineage(conversation, parentCache);
|
|
204
193
|
|
|
205
194
|
return {
|
|
206
195
|
id: conversation.id,
|
|
207
|
-
title:
|
|
196
|
+
title: conversation.title ?? "Untitled",
|
|
208
197
|
createdAt: conversation.createdAt,
|
|
209
198
|
updatedAt: conversation.updatedAt,
|
|
210
199
|
lastMessageAt: conversation.lastMessageAt,
|
|
@@ -264,7 +253,6 @@ export function serializeConversationSummary(params: {
|
|
|
264
253
|
*/
|
|
265
254
|
export function buildConversationDetailResponse(
|
|
266
255
|
conversationId: string,
|
|
267
|
-
locale?: SupportedLocale,
|
|
268
256
|
): { conversation: ReturnType<typeof serializeConversationSummary> } | null {
|
|
269
257
|
const conversation = getConversation(conversationId);
|
|
270
258
|
if (!conversation || conversation.conversationType === "private") {
|
|
@@ -286,7 +274,6 @@ export function buildConversationDetailResponse(
|
|
|
286
274
|
// Checks in-memory flag first (hot path), falls back to the
|
|
287
275
|
// persisted `processing_started_at` column for cold conversations.
|
|
288
276
|
isProcessing: isConversationProcessing(conversation.id),
|
|
289
|
-
locale,
|
|
290
277
|
}),
|
|
291
278
|
};
|
|
292
279
|
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
conversationMetadataSyncTag,
|
|
5
5
|
SYNC_TAGS,
|
|
6
6
|
} from "../../daemon/message-types/sync.js";
|
|
7
|
-
import { resolveConversationTitle } from "../../i18n/index.js";
|
|
8
7
|
import { syncAvatarToPlatform } from "../../platform/sync-avatar.js";
|
|
9
8
|
import { getAvatarImagePath } from "../../util/platform.js";
|
|
10
9
|
import { broadcastMessage } from "../assistant-event-hub.js";
|
|
@@ -258,7 +257,7 @@ export function publishConversationTitleChanged(
|
|
|
258
257
|
{
|
|
259
258
|
type: "conversation_title_updated",
|
|
260
259
|
conversationId,
|
|
261
|
-
title
|
|
260
|
+
title,
|
|
262
261
|
},
|
|
263
262
|
conversationId,
|
|
264
263
|
);
|
package/src/schedule/worker.ts
CHANGED
|
@@ -195,7 +195,7 @@ async function main(): Promise<void> {
|
|
|
195
195
|
//
|
|
196
196
|
// Bounded by MCP_STARTUP_GRACE_MS: unreachable servers must not hold the
|
|
197
197
|
// schedules that do not use them. The connect runs on past the deadline.
|
|
198
|
-
const mcpStartup = startConfiguredMcpServers();
|
|
198
|
+
const mcpStartup = startConfiguredMcpServers(getConfig().mcp);
|
|
199
199
|
await Promise.race([
|
|
200
200
|
mcpStartup,
|
|
201
201
|
// Unref'd so a connect that beats the deadline leaves nothing pending.
|
|
@@ -11,11 +11,6 @@ import { getLogger } from "../util/logger.js";
|
|
|
11
11
|
const log = getLogger("ces-rpc-record-backend");
|
|
12
12
|
|
|
13
13
|
export interface CredentialRecordBackend {
|
|
14
|
-
/**
|
|
15
|
-
* Transport id. `"ces-rpc"` is the attached CES socket backend; live
|
|
16
|
-
* catalog listing fails over to CES HTTP when that transport is down.
|
|
17
|
-
*/
|
|
18
|
-
readonly name?: string;
|
|
19
14
|
isAvailable(): boolean;
|
|
20
15
|
get(account: string): Promise<CredentialRecord | undefined>;
|
|
21
16
|
set(account: string, record: CredentialRecord): Promise<boolean>;
|
|
@@ -34,8 +29,6 @@ export interface CredentialRecordBackend {
|
|
|
34
29
|
}
|
|
35
30
|
|
|
36
31
|
export class CesRpcRecordBackend implements CredentialRecordBackend {
|
|
37
|
-
readonly name = "ces-rpc";
|
|
38
|
-
|
|
39
32
|
constructor(private readonly client: CesClient) {}
|
|
40
33
|
|
|
41
34
|
isAvailable(): boolean {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
import { readdir } from "node:fs/promises";
|
|
34
34
|
import { join } from "node:path";
|
|
35
35
|
|
|
36
|
+
import type { SkillSummary } from "../config/skills.js";
|
|
36
37
|
import type { TrustContext } from "../daemon/trust-context-types.js";
|
|
37
38
|
import type { TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
38
39
|
import { truncate as truncateText } from "../util/truncate.js";
|
|
@@ -55,6 +56,15 @@ export interface AdvisorContextSources {
|
|
|
55
56
|
* from the catalog section, mirroring the `skill_load` gate.
|
|
56
57
|
*/
|
|
57
58
|
enabledPluginSet?: ReadonlySet<string> | null;
|
|
59
|
+
/**
|
|
60
|
+
* Pre-resolved skill catalog, typically the parent conversation's warm
|
|
61
|
+
* `skillProjectionCache.catalog`. Passing it keeps the synchronous on-disk
|
|
62
|
+
* catalog scan out of the consult path (and matches the catalog view the
|
|
63
|
+
* parent turn's tool projection used). When absent, the section falls back
|
|
64
|
+
* to a fresh `loadSkillCatalog()` scan, the same call every agent turn's
|
|
65
|
+
* projection already makes.
|
|
66
|
+
*/
|
|
67
|
+
skillCatalog?: readonly SkillSummary[];
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
/** Cap a block so the assembled context never balloons the consult prompt. */
|
|
@@ -104,6 +114,7 @@ async function buildToolsSection(
|
|
|
104
114
|
*/
|
|
105
115
|
async function buildSkillsSection(
|
|
106
116
|
enabledPluginSet: ReadonlySet<string> | null | undefined,
|
|
117
|
+
preResolvedCatalog: readonly SkillSummary[] | undefined,
|
|
107
118
|
): Promise<string | null> {
|
|
108
119
|
try {
|
|
109
120
|
const [
|
|
@@ -119,17 +130,19 @@ async function buildSkillsSection(
|
|
|
119
130
|
]);
|
|
120
131
|
const config = getConfig();
|
|
121
132
|
const pluginScope = enabledPluginSet ?? null;
|
|
122
|
-
const catalog = loadSkillCatalog().filter(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
+
const catalog = (preResolvedCatalog ?? loadSkillCatalog()).filter(
|
|
134
|
+
(skill) => {
|
|
135
|
+
if (
|
|
136
|
+
pluginScope !== null &&
|
|
137
|
+
skill.owner?.kind === "plugin" &&
|
|
138
|
+
!pluginScope.has(skill.owner.id)
|
|
139
|
+
) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const flagKey = skillFlagKey(skill);
|
|
143
|
+
return !flagKey || isAssistantFeatureFlagEnabled(flagKey, config);
|
|
144
|
+
},
|
|
145
|
+
);
|
|
133
146
|
if (catalog.length === 0) {
|
|
134
147
|
return null;
|
|
135
148
|
}
|
|
@@ -371,7 +384,7 @@ export async function buildAdvisorContext(
|
|
|
371
384
|
const sections = await Promise.all(
|
|
372
385
|
[
|
|
373
386
|
buildToolsSection(sources.allowedToolNames),
|
|
374
|
-
buildSkillsSection(sources.enabledPluginSet),
|
|
387
|
+
buildSkillsSection(sources.enabledPluginSet, sources.skillCatalog),
|
|
375
388
|
buildWorkspaceSection(sources),
|
|
376
389
|
].map((section) => withSectionTimeout(section, sectionTimeoutMs)),
|
|
377
390
|
);
|
|
@@ -90,9 +90,7 @@ describe("executeAcpListAgents", () => {
|
|
|
90
90
|
const codex = parsed.agents.find((a: { id: string }) => a.id === "codex");
|
|
91
91
|
expect(codex.available).toBe(false);
|
|
92
92
|
expect(codex.unavailableReason).toBe("'codex-acp' is not on PATH");
|
|
93
|
-
expect(codex.setupHint).toBe(
|
|
94
|
-
"bun add -g @agentclientprotocol/codex-acp@1.10.0",
|
|
95
|
-
);
|
|
93
|
+
expect(codex.setupHint).toBe("bun add -g @agentclientprotocol/codex-acp");
|
|
96
94
|
|
|
97
95
|
const claude = parsed.agents.find((a: { id: string }) => a.id === "claude");
|
|
98
96
|
expect(claude.available).toBe(true);
|
|
@@ -124,22 +124,11 @@ const spawnMock = mock(
|
|
|
124
124
|
_cwd: string,
|
|
125
125
|
_parentConversationId: string,
|
|
126
126
|
_sendToVellum: (msg: unknown) => void,
|
|
127
|
-
|
|
128
|
-
)
|
|
129
|
-
acpSessionId:
|
|
130
|
-
protocolSessionId:
|
|
131
|
-
|
|
132
|
-
effectiveModel?: string;
|
|
133
|
-
modelWarning?: string;
|
|
134
|
-
}> => {
|
|
135
|
-
const requestedModel = _options?.model?.trim() || undefined;
|
|
136
|
-
return {
|
|
137
|
-
acpSessionId: "acp-session-test",
|
|
138
|
-
protocolSessionId: "proto-session-test",
|
|
139
|
-
requestedModel,
|
|
140
|
-
effectiveModel: "opus",
|
|
141
|
-
};
|
|
142
|
-
},
|
|
127
|
+
_parentToolUseId?: string,
|
|
128
|
+
) => ({
|
|
129
|
+
acpSessionId: "acp-session-test",
|
|
130
|
+
protocolSessionId: "proto-session-test",
|
|
131
|
+
}),
|
|
143
132
|
);
|
|
144
133
|
|
|
145
134
|
// Spread the real module's exports so transitive importers that pull other
|
|
@@ -212,8 +201,6 @@ describe("executeAcpSpawn - happy path", () => {
|
|
|
212
201
|
const payload = JSON.parse(result.content);
|
|
213
202
|
expect(payload.acpSessionId).toBe("acp-session-test");
|
|
214
203
|
expect(payload.status).toBe("running");
|
|
215
|
-
expect(payload.requestedModel).toBeNull();
|
|
216
|
-
expect(payload.effectiveModel).toBe("opus");
|
|
217
204
|
// The real adapter binary is spawned (no `bun x` wrapper).
|
|
218
205
|
const agentConfigArg = spawnMock.mock.calls[0][1] as { command: string };
|
|
219
206
|
expect(agentConfigArg.command).toBe("claude-agent-acp");
|
|
@@ -227,10 +214,8 @@ describe("executeAcpSpawn - happy path", () => {
|
|
|
227
214
|
|
|
228
215
|
expect(result.isError).toBe(false);
|
|
229
216
|
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
230
|
-
//
|
|
231
|
-
expect(spawnMock.mock.calls[0][6]).
|
|
232
|
-
parentToolUseId: "toolu_abc123",
|
|
233
|
-
});
|
|
217
|
+
// parentToolUseId is the 7th positional arg to spawn().
|
|
218
|
+
expect(spawnMock.mock.calls[0][6]).toBe("toolu_abc123");
|
|
234
219
|
});
|
|
235
220
|
|
|
236
221
|
test("default-profile fallback when user config is empty", async () => {
|
|
@@ -287,7 +272,7 @@ describe("executeAcpSpawn — input validation", () => {
|
|
|
287
272
|
expect(result.isError).toBe(true);
|
|
288
273
|
expect(result.content).toContain("claude-agent-acp is not on PATH");
|
|
289
274
|
expect(result.content).toContain(
|
|
290
|
-
"bun add -g @agentclientprotocol/claude-agent-acp
|
|
275
|
+
"bun add -g @agentclientprotocol/claude-agent-acp",
|
|
291
276
|
);
|
|
292
277
|
expect(execFileMock).not.toHaveBeenCalled();
|
|
293
278
|
expect(spawnMock).not.toHaveBeenCalled();
|
|
@@ -324,7 +309,7 @@ describe("executeAcpSpawn: sandboxed bun auto-install on missing binary", () =>
|
|
|
324
309
|
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
325
310
|
const payload = JSON.parse(result.content);
|
|
326
311
|
expect(payload.message).toContain(
|
|
327
|
-
"Installed @agentclientprotocol/claude-agent-acp
|
|
312
|
+
"Installed @agentclientprotocol/claude-agent-acp automatically.",
|
|
328
313
|
);
|
|
329
314
|
// The real binary was spawned with cwd = the project dir and token
|
|
330
315
|
// injected (trusted-binary config, no resolution at spawn).
|
|
@@ -345,7 +330,7 @@ describe("executeAcpSpawn: sandboxed bun auto-install on missing binary", () =>
|
|
|
345
330
|
expect(args).toEqual([
|
|
346
331
|
"add",
|
|
347
332
|
"--global",
|
|
348
|
-
"@agentclientprotocol/claude-agent-acp
|
|
333
|
+
"@agentclientprotocol/claude-agent-acp",
|
|
349
334
|
]);
|
|
350
335
|
});
|
|
351
336
|
|
|
@@ -434,7 +419,7 @@ describe("executeAcpSpawn: sandboxed bun auto-install on missing binary", () =>
|
|
|
434
419
|
expect(result.isError).toBe(true);
|
|
435
420
|
expect(result.content).toContain("claude-agent-acp is not on PATH");
|
|
436
421
|
expect(result.content).toContain(
|
|
437
|
-
"bun add -g @agentclientprotocol/claude-agent-acp
|
|
422
|
+
"bun add -g @agentclientprotocol/claude-agent-acp",
|
|
438
423
|
);
|
|
439
424
|
expect(result.content).toContain("auto-install failed");
|
|
440
425
|
expect(result.content).toContain("EACCES");
|
|
@@ -473,126 +458,6 @@ describe("executeAcpSpawn — per-agent resume hint", () => {
|
|
|
473
458
|
});
|
|
474
459
|
});
|
|
475
460
|
|
|
476
|
-
describe("executeAcpSpawn - model selection", () => {
|
|
477
|
-
test("threads the requested model into manager.spawn's options", async () => {
|
|
478
|
-
const result = await executeAcpSpawn(
|
|
479
|
-
{ agent: "claude", task: "do something", model: "opus" },
|
|
480
|
-
{ ...makeContext(), toolUseId: "toolu_model" },
|
|
481
|
-
);
|
|
482
|
-
|
|
483
|
-
expect(result.isError).toBe(false);
|
|
484
|
-
expect(spawnMock.mock.calls[0][6]).toEqual({
|
|
485
|
-
parentToolUseId: "toolu_model",
|
|
486
|
-
model: "opus",
|
|
487
|
-
});
|
|
488
|
-
const payload = JSON.parse(result.content);
|
|
489
|
-
expect(payload.requestedModel).toBe("opus");
|
|
490
|
-
expect(payload.effectiveModel).toBe("opus");
|
|
491
|
-
expect(payload.message).toContain(
|
|
492
|
-
'The top-level ACP session reports "opus" as its effective model.',
|
|
493
|
-
);
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
test("reports the manager-normalized requested model", async () => {
|
|
497
|
-
const result = await executeAcpSpawn(
|
|
498
|
-
{ agent: "claude", task: "do something", model: " opus " },
|
|
499
|
-
makeContext(),
|
|
500
|
-
);
|
|
501
|
-
|
|
502
|
-
expect(spawnMock.mock.calls[0][6]).toEqual({
|
|
503
|
-
parentToolUseId: undefined,
|
|
504
|
-
model: " opus ",
|
|
505
|
-
});
|
|
506
|
-
expect(JSON.parse(result.content).requestedModel).toBe("opus");
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
test("a null model is treated as omitted", async () => {
|
|
510
|
-
const result = await executeAcpSpawn(
|
|
511
|
-
{ agent: "claude", task: "do something", model: null },
|
|
512
|
-
makeContext(),
|
|
513
|
-
);
|
|
514
|
-
|
|
515
|
-
expect(result.isError).toBe(false);
|
|
516
|
-
const options = spawnMock.mock.calls[0][6] as { model?: string };
|
|
517
|
-
expect(options.model).toBeUndefined();
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
test("a modelWarning from the spawn is relayed in the result message", async () => {
|
|
521
|
-
spawnMock.mockImplementationOnce(async () => ({
|
|
522
|
-
acpSessionId: "acp-session-test",
|
|
523
|
-
protocolSessionId: "proto-session-test",
|
|
524
|
-
requestedModel: "nope",
|
|
525
|
-
effectiveModel: "opus",
|
|
526
|
-
modelWarning: "Unknown model: nope",
|
|
527
|
-
}));
|
|
528
|
-
|
|
529
|
-
const result = await executeAcpSpawn(
|
|
530
|
-
{ agent: "claude", task: "do something", model: "nope" },
|
|
531
|
-
makeContext(),
|
|
532
|
-
);
|
|
533
|
-
|
|
534
|
-
expect(result.isError).toBe(false);
|
|
535
|
-
const payload = JSON.parse(result.content);
|
|
536
|
-
expect(payload.message).toContain(
|
|
537
|
-
"The requested model was not applied: Unknown model: nope",
|
|
538
|
-
);
|
|
539
|
-
expect(payload.requestedModel).toBe("nope");
|
|
540
|
-
expect(payload.effectiveModel).toBe("opus");
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
test("the note relays a no-selector warning without calling it a refusal", async () => {
|
|
544
|
-
spawnMock.mockImplementationOnce(async () => ({
|
|
545
|
-
acpSessionId: "acp-session-test",
|
|
546
|
-
protocolSessionId: "proto-session-test",
|
|
547
|
-
requestedModel: "opus",
|
|
548
|
-
modelWarning:
|
|
549
|
-
'Agent "claude" does not support model selection, so the session is running on the agent\'s own model.',
|
|
550
|
-
}));
|
|
551
|
-
|
|
552
|
-
const result = await executeAcpSpawn(
|
|
553
|
-
{ agent: "claude", task: "do something", model: "opus" },
|
|
554
|
-
makeContext(),
|
|
555
|
-
);
|
|
556
|
-
|
|
557
|
-
const payload = JSON.parse(result.content);
|
|
558
|
-
expect(payload.message).toContain("does not support model selection");
|
|
559
|
-
expect(payload.message).not.toContain("refused");
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
test("no model note when the spawn reports no warning", async () => {
|
|
563
|
-
const result = await executeAcpSpawn(
|
|
564
|
-
{ agent: "claude", task: "do something", model: "opus" },
|
|
565
|
-
makeContext(),
|
|
566
|
-
);
|
|
567
|
-
|
|
568
|
-
expect(result.isError).toBe(false);
|
|
569
|
-
const payload = JSON.parse(result.content);
|
|
570
|
-
expect(payload.message).not.toContain(
|
|
571
|
-
"The requested model was not applied",
|
|
572
|
-
);
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
test("reports when the adapter does not identify the effective model", async () => {
|
|
576
|
-
spawnMock.mockImplementationOnce(async () => ({
|
|
577
|
-
acpSessionId: "acp-session-test",
|
|
578
|
-
protocolSessionId: "proto-session-test",
|
|
579
|
-
requestedModel: "sonnet",
|
|
580
|
-
}));
|
|
581
|
-
|
|
582
|
-
const result = await executeAcpSpawn(
|
|
583
|
-
{ agent: "claude", task: "do something", model: "sonnet" },
|
|
584
|
-
makeContext(),
|
|
585
|
-
);
|
|
586
|
-
|
|
587
|
-
const payload = JSON.parse(result.content);
|
|
588
|
-
expect(payload.requestedModel).toBe("sonnet");
|
|
589
|
-
expect(payload.effectiveModel).toBeNull();
|
|
590
|
-
expect(payload.message).toContain(
|
|
591
|
-
"The top-level ACP session did not report an effective model.",
|
|
592
|
-
);
|
|
593
|
-
});
|
|
594
|
-
});
|
|
595
|
-
|
|
596
461
|
// ---------------------------------------------------------------------------
|
|
597
462
|
// executeAcpSpawn — CLAUDE_CODE_OAUTH_TOKEN env injection + preflight
|
|
598
463
|
//
|
package/src/tools/acp/spawn.ts
CHANGED
|
@@ -37,7 +37,6 @@ export const acpSpawnInputSchema = z.looseObject({
|
|
|
37
37
|
agent: nullAsOmitted(z.string()),
|
|
38
38
|
task: nullAsOmitted(z.string()),
|
|
39
39
|
cwd: nullAsOmitted(z.string()),
|
|
40
|
-
model: nullAsOmitted(z.string()),
|
|
41
40
|
});
|
|
42
41
|
|
|
43
42
|
/**
|
|
@@ -67,7 +66,6 @@ export async function executeAcpSpawn(
|
|
|
67
66
|
}
|
|
68
67
|
const agent = parsedInput.data.agent || "claude";
|
|
69
68
|
const task = parsedInput.data.task;
|
|
70
|
-
const model = parsedInput.data.model;
|
|
71
69
|
|
|
72
70
|
if (!task) {
|
|
73
71
|
return { content: '"task" is required.', isError: true };
|
|
@@ -126,20 +124,14 @@ export async function executeAcpSpawn(
|
|
|
126
124
|
// Recheck: the auto-install and the agent-env preparation above are both
|
|
127
125
|
// awaits, and this is the point a long-lived subprocess starts.
|
|
128
126
|
throwIfCancelled(context);
|
|
129
|
-
const {
|
|
130
|
-
acpSessionId,
|
|
131
|
-
protocolSessionId,
|
|
132
|
-
requestedModel,
|
|
133
|
-
effectiveModel,
|
|
134
|
-
modelWarning,
|
|
135
|
-
} = await manager.spawn(
|
|
127
|
+
const { acpSessionId, protocolSessionId } = await manager.spawn(
|
|
136
128
|
agent,
|
|
137
129
|
agentConfig,
|
|
138
130
|
task,
|
|
139
131
|
cwd,
|
|
140
132
|
context.conversationId,
|
|
141
133
|
sendToClient,
|
|
142
|
-
|
|
134
|
+
context.toolUseId,
|
|
143
135
|
// The manager rechecks after its own protocol handshake and session
|
|
144
136
|
// creation, so a turn stopped in that window tears the child process
|
|
145
137
|
// down instead of handing it the task.
|
|
@@ -158,26 +150,16 @@ export async function executeAcpSpawn(
|
|
|
158
150
|
const installNote = autoInstalledPackage
|
|
159
151
|
? ` Installed ${autoInstalledPackage} automatically.`
|
|
160
152
|
: "";
|
|
161
|
-
// Relayed verbatim: the warning already distinguishes an adapter with no
|
|
162
|
-
// selector from one that refused the value.
|
|
163
|
-
const modelNote = modelWarning
|
|
164
|
-
? ` The requested model was not applied: ${modelWarning}`
|
|
165
|
-
: "";
|
|
166
|
-
const effectiveModelNote = effectiveModel
|
|
167
|
-
? ` The top-level ACP session reports "${effectiveModel}" as its effective model.`
|
|
168
|
-
: " The top-level ACP session did not report an effective model.";
|
|
169
153
|
const payload = JSON.stringify({
|
|
170
154
|
acpSessionId,
|
|
171
155
|
protocolSessionId,
|
|
172
156
|
agent,
|
|
173
157
|
cwd,
|
|
174
|
-
requestedModel: requestedModel ?? null,
|
|
175
|
-
effectiveModel: effectiveModel ?? null,
|
|
176
158
|
status: "running",
|
|
177
159
|
message:
|
|
178
160
|
`ACP agent "${agent}" spawned (session: ${protocolSessionId}). ` +
|
|
179
161
|
`Results stream back via SSE. You will be notified when it completes.` +
|
|
180
|
-
`${installNote}${
|
|
162
|
+
`${installNote}${resumeHint}`,
|
|
181
163
|
});
|
|
182
164
|
|
|
183
165
|
return { content: payload, isError: false };
|
package/src/tools/acp/status.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
import { getAcpSessionManager } from "../../acp/index.js";
|
|
4
|
-
import type { AcpSessionState } from "../../acp/types.js";
|
|
5
4
|
import {
|
|
6
5
|
invalidToolInputResult,
|
|
7
6
|
nullAsOmitted,
|
|
@@ -17,40 +16,6 @@ export const acpStatusInputSchema = z.looseObject({
|
|
|
17
16
|
acp_session_id: nullAsOmitted(z.string()),
|
|
18
17
|
});
|
|
19
18
|
|
|
20
|
-
/**
|
|
21
|
-
* The session fields worth spending LLM context on. An allowlist rather than
|
|
22
|
-
* an omission: `availableModels` is a picker for the human surfaces (HTTP and
|
|
23
|
-
* SSE) that says nothing the agent can act on, and a field added to
|
|
24
|
-
* `AcpSessionState` for those surfaces should not reach this one by default.
|
|
25
|
-
* `model` stays: which model a session is running on is answerable.
|
|
26
|
-
*/
|
|
27
|
-
function projectSession(state: AcpSessionState) {
|
|
28
|
-
return {
|
|
29
|
-
id: state.id,
|
|
30
|
-
agentId: state.agentId,
|
|
31
|
-
acpSessionId: state.acpSessionId,
|
|
32
|
-
parentConversationId: state.parentConversationId,
|
|
33
|
-
status: state.status,
|
|
34
|
-
startedAt: state.startedAt,
|
|
35
|
-
completedAt: state.completedAt,
|
|
36
|
-
error: state.error,
|
|
37
|
-
stopReason: state.stopReason,
|
|
38
|
-
task: state.task,
|
|
39
|
-
parentToolUseId: state.parentToolUseId,
|
|
40
|
-
authErrorCode: state.authErrorCode,
|
|
41
|
-
authErrorCredential: state.authErrorCredential,
|
|
42
|
-
latestUsage: state.latestUsage,
|
|
43
|
-
model: state.model,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Projects either shape `getStatus` answers with. */
|
|
48
|
-
function projectStatus(status: AcpSessionState | AcpSessionState[]): unknown {
|
|
49
|
-
return Array.isArray(status)
|
|
50
|
-
? status.map(projectSession)
|
|
51
|
-
: projectSession(status);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
19
|
export async function executeAcpStatus(
|
|
55
20
|
input: Record<string, unknown>,
|
|
56
21
|
_context: ToolContext,
|
|
@@ -64,8 +29,9 @@ export async function executeAcpStatus(
|
|
|
64
29
|
|
|
65
30
|
try {
|
|
66
31
|
if (acpSessionId) {
|
|
32
|
+
const state = manager.getStatus(acpSessionId);
|
|
67
33
|
return {
|
|
68
|
-
content: JSON.stringify(
|
|
34
|
+
content: JSON.stringify(state),
|
|
69
35
|
isError: false,
|
|
70
36
|
};
|
|
71
37
|
}
|
|
@@ -76,10 +42,7 @@ export async function executeAcpStatus(
|
|
|
76
42
|
return { content: "No ACP sessions found.", isError: false };
|
|
77
43
|
}
|
|
78
44
|
|
|
79
|
-
return {
|
|
80
|
-
content: JSON.stringify(projectStatus(allStates)),
|
|
81
|
-
isError: false,
|
|
82
|
-
};
|
|
45
|
+
return { content: JSON.stringify(allStates), isError: false };
|
|
83
46
|
} catch (err) {
|
|
84
47
|
const msg = err instanceof Error ? err.message : String(err);
|
|
85
48
|
return { content: msg, isError: true };
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* the proxy resolver, which forwards the call to the connected 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
|
|
|
@@ -33,7 +32,7 @@ export function forwardAppControlProxyTool(
|
|
|
33
32
|
}
|
|
34
33
|
if (!context.proxyToolResolver) {
|
|
35
34
|
return Promise.resolve({
|
|
36
|
-
content:
|
|
35
|
+
content: `Cannot execute ${toolName}: no proxy resolver available. This tool requires a connected client.`,
|
|
37
36
|
isError: true,
|
|
38
37
|
});
|
|
39
38
|
}
|
|
@@ -4,26 +4,11 @@ import {
|
|
|
4
4
|
appendLoggedInBrowserOffer,
|
|
5
5
|
CHROME_WEB_STORE_INSTALL_URL,
|
|
6
6
|
DESKTOP_APP_DOWNLOAD_URL,
|
|
7
|
-
formatDesktopAppRequired,
|
|
8
7
|
formatLoggedInBrowserOffer,
|
|
9
8
|
isPhoneSurface,
|
|
10
9
|
shouldOfferLoggedInBrowser,
|
|
11
10
|
} from "./capability-offer.js";
|
|
12
11
|
|
|
13
|
-
describe("formatDesktopAppRequired", () => {
|
|
14
|
-
test("offers a direct desktop-app download and retry step", () => {
|
|
15
|
-
const message = formatDesktopAppRequired("shell");
|
|
16
|
-
|
|
17
|
-
expect(message).toContain(
|
|
18
|
-
"The Vellum desktop app is needed to run commands on your computer",
|
|
19
|
-
);
|
|
20
|
-
expect(message).toContain(DESKTOP_APP_DOWNLOAD_URL);
|
|
21
|
-
expect(message).toContain("Open it, then retry.");
|
|
22
|
-
expect(message).not.toContain("client");
|
|
23
|
-
expect(message).not.toContain("daemon");
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
12
|
describe("isPhoneSurface", () => {
|
|
28
13
|
test("is true for iOS transport and mobile client OS", () => {
|
|
29
14
|
expect(isPhoneSurface({ transportInterface: "ios" })).toBe(true);
|
|
@@ -64,9 +49,7 @@ describe("shouldOfferLoggedInBrowser", () => {
|
|
|
64
49
|
expect(shouldOfferLoggedInBrowser('Invalid browser_mode "bogus"')).toBe(
|
|
65
50
|
false,
|
|
66
51
|
);
|
|
67
|
-
expect(shouldOfferLoggedInBrowser("url must use http or https")).toBe(
|
|
68
|
-
false,
|
|
69
|
-
);
|
|
52
|
+
expect(shouldOfferLoggedInBrowser("url must use http or https")).toBe(false);
|
|
70
53
|
});
|
|
71
54
|
});
|
|
72
55
|
|
|
@@ -88,7 +71,6 @@ describe("formatLoggedInBrowserOffer", () => {
|
|
|
88
71
|
});
|
|
89
72
|
expect(offer).toContain("no in-app browser");
|
|
90
73
|
expect(offer).toContain("Do not describe a browser panel");
|
|
91
|
-
expect(offer).toContain("Mac or Windows PC");
|
|
92
74
|
expect(offer).toContain(DESKTOP_APP_DOWNLOAD_URL);
|
|
93
75
|
expect(offer).toContain(CHROME_WEB_STORE_INSTALL_URL);
|
|
94
76
|
});
|
|
@@ -96,9 +78,7 @@ describe("formatLoggedInBrowserOffer", () => {
|
|
|
96
78
|
|
|
97
79
|
describe("appendLoggedInBrowserOffer", () => {
|
|
98
80
|
test("appends the offer once", () => {
|
|
99
|
-
const once = appendLoggedInBrowserOffer(
|
|
100
|
-
"Error: Navigation failed: timeout",
|
|
101
|
-
);
|
|
81
|
+
const once = appendLoggedInBrowserOffer("Error: Navigation failed: timeout");
|
|
102
82
|
expect(once).toContain("Error: Navigation failed: timeout");
|
|
103
83
|
expect(once).toContain(DESKTOP_APP_DOWNLOAD_URL);
|
|
104
84
|
const twice = appendLoggedInBrowserOffer(once);
|