@vellumai/assistant 0.12.1 → 0.12.2-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 +4 -0
- package/ARCHITECTURE.md +20 -21
- package/docs/architecture/turn-actor.md +15 -8
- package/docs/guardian-request-flow.md +16 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
- package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
- package/openapi.yaml +360 -51
- package/package.json +3 -1
- package/scripts/smoke-desktop-window-theme.ts +186 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
- package/src/__tests__/anthropic-provider.test.ts +0 -63
- package/src/__tests__/app-compiler.test.ts +6 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
- package/src/__tests__/app-dir-path-guard.test.ts +1 -3
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
- package/src/__tests__/assistant-event-hub.test.ts +44 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
- package/src/__tests__/computer-use-tools.test.ts +19 -7
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +28 -29
- package/src/__tests__/config-watcher.test.ts +23 -8
- 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 +26 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
- package/src/__tests__/conversation-queue.test.ts +48 -207
- package/src/__tests__/conversation-retry-discard.test.ts +54 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +28 -0
- package/src/__tests__/conversation-skill-tools.test.ts +27 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-title-service.test.ts +14 -10
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
- package/src/__tests__/credential-record-retire.test.ts +171 -1
- package/src/__tests__/credential-routes.test.ts +250 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -3
- package/src/__tests__/cu-unified-flow.test.ts +14 -4
- package/src/__tests__/document-sync-tags.test.ts +25 -0
- package/src/__tests__/drain-kick-guard.test.ts +0 -2
- package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/git-porcelain.test.ts +47 -0
- package/src/__tests__/heartbeat-service.test.ts +56 -40
- package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
- package/src/__tests__/host-bash-proxy.test.ts +26 -45
- package/src/__tests__/host-browser-proxy.test.ts +6 -17
- package/src/__tests__/host-cu-proxy.test.ts +596 -0
- package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
- package/src/__tests__/host-file-proxy.test.ts +11 -23
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
- package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
- package/src/__tests__/llm-catalog-parity.test.ts +25 -0
- package/src/__tests__/mcp-auth-routes.test.ts +6 -9
- package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
- package/src/__tests__/mcp-health-check.test.ts +8 -11
- package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
- package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +355 -548
- package/src/__tests__/model-intents.test.ts +3 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
- package/src/__tests__/oauth-commands-routes.test.ts +168 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +22 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-provider.test.ts +1 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/platform-callback-registration.test.ts +8 -16
- package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +14 -0
- package/src/__tests__/qdrant-manager.test.ts +132 -0
- package/src/__tests__/resolve-app.test.ts +135 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +229 -6
- package/src/__tests__/script-proxy-certs.test.ts +35 -0
- package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
- package/src/__tests__/service-account-token.test.ts +247 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skills.test.ts +9 -4
- package/src/__tests__/source-fingerprint.test.ts +184 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +70 -3
- package/src/__tests__/subagent-tools.test.ts +3 -2
- package/src/__tests__/telephony-tts-guard.test.ts +38 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/ui-channel-variants.test.ts +1 -56
- package/src/__tests__/unicode.test.ts +13 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
- package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
- package/src/__tests__/workspace-git-service.test.ts +26 -0
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
- package/src/acp/__tests__/acp-credentials.test.ts +13 -0
- package/src/acp/__tests__/agent-process.test.ts +258 -4
- package/src/acp/__tests__/auth-required.test.ts +96 -0
- package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
- package/src/acp/__tests__/client-handler.test.ts +90 -2
- package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
- package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
- package/src/acp/__tests__/session-manager.test.ts +895 -4
- package/src/acp/acp-claude-oauth.ts +328 -14
- package/src/acp/acp-credentials.ts +19 -0
- package/src/acp/agent-process.test.ts +4 -1
- package/src/acp/agent-process.ts +96 -10
- package/src/acp/auth-required.ts +50 -1
- package/src/acp/auto-install.test.ts +9 -7
- package/src/acp/claude-token-refresh.ts +150 -0
- package/src/acp/client-handler.ts +16 -3
- package/src/acp/model-config.test.ts +166 -0
- package/src/acp/model-config.ts +138 -0
- package/src/acp/prepare-agent-env.ts +21 -6
- package/src/acp/resolve-agent.test.ts +220 -6
- package/src/acp/resolve-agent.ts +88 -23
- package/src/acp/session-manager.test.ts +196 -3
- package/src/acp/session-manager.ts +441 -18
- package/src/acp/types.ts +50 -5
- package/src/agent/loop.ts +1 -0
- package/src/api/events/acp-session-model-update.test.ts +88 -0
- package/src/api/events/acp-session-model-update.ts +46 -0
- package/src/api/events/app-files-changed.ts +4 -3
- package/src/api/events/notification-intent.ts +2 -0
- package/src/api/events/user-message-echo.ts +7 -1
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +1 -1
- package/src/apps/resolve-app.ts +81 -0
- package/src/apps/source-fingerprint.ts +266 -0
- package/src/avatar/identity-avatar.ts +7 -2
- package/src/bundler/app-compiler.ts +15 -0
- package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
- package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
- package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
- package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
- package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
- package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +4 -4
- package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
- package/src/calls/__tests__/voice-control-protocol.test.ts +120 -25
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
- package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
- package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
- package/src/calls/__tests__/voice-session-bridge.test.ts +56 -1
- package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
- package/src/calls/barge-in-guard.ts +118 -0
- package/src/calls/call-constants.ts +24 -4
- package/src/calls/call-controller.ts +499 -199
- package/src/calls/call-transport.ts +16 -0
- package/src/calls/media-stream-output.ts +32 -0
- package/src/calls/media-stream-server.ts +82 -30
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/{live-voice → calls}/progress-narration.ts +2 -2
- package/src/calls/resolve-call-tts-provider.ts +33 -2
- package/src/calls/tts-call-strategy.ts +9 -5
- package/src/calls/types.ts +2 -0
- package/src/calls/voice-control-protocol.ts +155 -21
- package/src/calls/voice-leg-coordinator.ts +189 -0
- package/src/calls/voice-progress-cadence.ts +423 -0
- package/src/calls/voice-session-bridge.ts +92 -72
- package/src/calls/voice-triage-escalate.ts +178 -59
- package/src/cli/commands/__tests__/apps.test.ts +245 -0
- package/src/cli/commands/__tests__/bash.test.ts +53 -0
- package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
- package/src/cli/commands/apps.help.ts +67 -13
- package/src/cli/commands/apps.ts +183 -0
- package/src/cli/commands/bash.help.ts +8 -13
- package/src/cli/commands/bash.ts +7 -25
- package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
- package/src/cli/commands/channels/index.help.ts +70 -2
- package/src/cli/commands/channels/index.ts +16 -3
- package/src/cli/commands/channels/send.ts +128 -0
- package/src/cli/commands/credentials.help.ts +6 -2
- 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/oauth/status.ts +5 -0
- package/src/cli/commands/roadmap.help.ts +5 -1
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +103 -90
- package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
- package/src/config/__tests__/platform-identity.test.ts +255 -0
- package/src/config/__tests__/platform-rehydration.test.ts +99 -9
- package/src/config/acp-agent-write.ts +43 -0
- package/src/config/acp-defaults.test.ts +13 -3
- package/src/config/acp-defaults.ts +23 -6
- package/src/config/acp-schema.test.ts +81 -0
- package/src/config/acp-schema.ts +30 -2
- package/src/config/bundled-skills/acp/SKILL.md +22 -14
- package/src/config/bundled-skills/acp/TOOLS.json +5 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +29 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +99 -0
- package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -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 +67 -139
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
- package/src/config/bundled-skills/schedule/SKILL.md +3 -4
- package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +6 -2
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/env.ts +2 -2
- package/src/config/feature-flag-registry.json +33 -13
- package/src/config/loader.ts +2 -0
- package/src/config/memory-v3-gate.test.ts +31 -0
- package/src/config/memory-v3-gate.ts +20 -16
- package/src/config/platform-identity.ts +201 -0
- package/src/config/platform-rehydration.ts +11 -27
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
- package/src/config/schemas/__tests__/voice.test.ts +148 -0
- package/src/config/schemas/calls.ts +1 -28
- package/src/config/schemas/live-voice.ts +1 -173
- package/src/config/schemas/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +10 -0
- package/src/config/schemas/services.ts +18 -0
- package/src/config/schemas/skills.ts +0 -14
- package/src/config/schemas/voice.ts +150 -0
- package/src/credential-execution/process-manager.test.ts +18 -19
- package/src/credential-health/credential-health-service.ts +11 -17
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
- package/src/daemon/app-change-notify.ts +45 -0
- package/src/daemon/config-watcher.ts +13 -194
- package/src/daemon/conversation-error.ts +3 -2
- package/src/daemon/conversation-media-retry.ts +2 -1
- package/src/daemon/conversation-process.ts +35 -64
- package/src/daemon/conversation-runtime-assembly.ts +20 -7
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +21 -10
- package/src/daemon/conversation-tool-setup.ts +45 -59
- package/src/daemon/conversation.ts +0 -3
- package/src/daemon/dictation-profile-store.ts +2 -1
- package/src/daemon/handlers/shared.ts +2 -1
- package/src/daemon/handlers/skills.ts +6 -3
- package/src/daemon/host-bash-proxy.ts +8 -12
- package/src/daemon/host-browser-proxy.ts +15 -1
- package/src/daemon/host-cu-proxy.ts +224 -19
- package/src/daemon/host-file-proxy.ts +8 -10
- package/src/daemon/host-proxy-preactivation.ts +2 -1
- package/src/daemon/host-transfer-proxy.ts +14 -18
- package/src/daemon/lifecycle.ts +0 -5
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/reaction-history-render.ts +2 -1
- package/src/daemon/shutdown-handlers.ts +1 -9
- package/src/daemon/skill-memory-refresh.ts +64 -0
- package/src/daemon/tool-side-effects.ts +7 -18
- package/src/desktop/__tests__/fake-desktop.ts +122 -0
- package/src/desktop/desktop-chrome-policy.test.ts +79 -0
- package/src/desktop/desktop-chrome-policy.ts +47 -0
- package/src/desktop/desktop-chrome-session.ts +37 -0
- package/src/desktop/desktop-dependencies.test.ts +102 -0
- package/src/desktop/desktop-dependencies.ts +308 -0
- package/src/desktop/desktop-feature.test.ts +18 -0
- package/src/desktop/desktop-feature.ts +19 -0
- package/src/desktop/desktop-panel-config.test.ts +135 -0
- package/src/desktop/desktop-panel-config.ts +149 -0
- package/src/desktop/desktop-session-manager.test.ts +730 -0
- package/src/desktop/desktop-session-manager.ts +850 -0
- package/src/desktop/desktop-stream-bridge.test.ts +395 -0
- package/src/desktop/desktop-stream-bridge.ts +214 -0
- package/src/desktop/desktop-wallpaper.test.ts +191 -0
- package/src/desktop/desktop-wallpaper.ts +113 -0
- package/src/desktop/desktop-window-drag.ts +177 -0
- package/src/desktop/desktop-window-manager-config.test.ts +230 -0
- package/src/desktop/desktop-window-manager-config.ts +238 -0
- package/src/desktop/desktop-window-theme.ts +170 -0
- package/src/heartbeat/heartbeat-service.ts +21 -3
- package/src/home/__tests__/feed-writer.test.ts +22 -0
- package/src/home/feed-writer.ts +11 -2
- package/src/hooks/types.ts +33 -0
- package/src/i18n/AGENTS.md +22 -0
- package/src/i18n/__tests__/i18n.test.ts +108 -0
- package/src/i18n/index.ts +16 -0
- package/src/i18n/locales.ts +93 -0
- package/src/i18n/messages.ts +61 -0
- package/src/i18n/title.ts +25 -0
- package/src/inbound/platform-callback-registration.ts +4 -5
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +121 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +8 -7
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
- package/src/live-voice/__tests__/protocol.test.ts +39 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
- package/src/live-voice/__tests__/session-controls.test.ts +79 -0
- package/src/live-voice/live-voice-photo.ts +25 -6
- package/src/live-voice/live-voice-session.ts +297 -699
- package/src/live-voice/protocol.ts +60 -2
- package/src/live-voice/session-controls.ts +111 -0
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +29 -45
- package/src/mcp/spec-schema.ts +111 -0
- package/src/mcp/startup.ts +8 -4
- package/src/mcp/workspace-mcp-config.ts +188 -0
- package/src/messaging/provider.ts +10 -3
- package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
- package/src/messaging/providers/callback-routing.ts +18 -0
- package/src/messaging/providers/channel-transport.ts +56 -0
- package/src/messaging/providers/discord/transport.ts +17 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
- package/src/messaging/providers/slack/adapter.ts +7 -44
- package/src/messaging/providers/slack/transport.ts +16 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
- package/src/messaging/providers/telegram-bot/client.ts +0 -26
- package/src/messaging/providers/telegram-bot/transport.ts +20 -0
- package/src/messaging/providers/whatsapp/adapter.ts +1 -48
- package/src/messaging/providers/whatsapp/transport.ts +18 -0
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
- package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
- package/src/notifications/adapters/macos.ts +3 -0
- package/src/notifications/assistant-reply-producer.ts +8 -3
- package/src/notifications/conversation-pairing.ts +36 -16
- package/src/notifications/delivered-post-record.ts +11 -1
- package/src/notifications/guardian-feed-projection.ts +125 -5
- package/src/notifications/home-feed-side-effect.ts +55 -7
- package/src/notifications/schedule-result-producer.ts +66 -22
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
- package/src/oauth/byo-connection.test.ts +105 -0
- package/src/oauth/byo-connection.ts +36 -6
- package/src/oauth/connection-resolver.test.ts +100 -0
- package/src/oauth/connection-resolver.ts +120 -3
- package/src/oauth/provider-serializer.ts +9 -0
- package/src/oauth/scope-utils.ts +24 -0
- package/src/oauth/seed-providers.ts +314 -27
- package/src/outbound-proxy/certs.ts +3 -5
- package/src/permissions/checker.test.ts +11 -6
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +71 -63
- package/src/persistence/conversation-lineage.ts +12 -4
- package/src/persistence/conversation-queries.ts +2 -2
- package/src/persistence/conversation-title-placeholders.ts +23 -0
- package/src/persistence/conversation-title-service.ts +9 -26
- package/src/persistence/embeddings/qdrant-manager.ts +163 -18
- 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-cursor.ts +78 -0
- package/src/persistence/message-reads.ts +30 -0
- package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
- package/src/persistence/schema/memory-core.ts +5 -0
- package/src/platform/client.test.ts +4 -2
- package/src/platform/client.ts +2 -10
- package/src/plugin-api/constants.ts +2 -0
- package/src/plugin-api/index.ts +1 -0
- package/src/plugin-api/types.ts +2 -0
- package/src/plugins/defaults/index.ts +2 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +20 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -2
- package/src/plugins/defaults/memory/context-search/format.ts +3 -2
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +6 -3
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +3 -2
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -7
- package/src/plugins/defaults/memory/hooks/init.ts +10 -0
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
- package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
- package/src/plugins/defaults/memory/host-utils.ts +10 -0
- package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +12 -3
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
- package/src/plugins/defaults/memory/startup.ts +28 -2
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
- package/src/plugins/defaults/memory/substrate/page-index.ts +6 -1
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
- package/src/plugins/defaults/memory/v2/reranker.ts +6 -1
- package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
- package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +30 -0
- package/src/plugins/defaults/memory/v3/card.ts +3 -2
- package/src/plugins/defaults/memory/v3/pool-select.ts +5 -3
- package/src/plugins/defaults/memory/v3/sections.ts +9 -3
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +5 -2
- package/src/plugins/defaults/memory/worker.ts +6 -0
- package/src/plugins/mcp-servers.ts +15 -75
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/__tests__/retry-callsite.test.ts +41 -0
- package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
- package/src/providers/anthropic/client.ts +0 -47
- package/src/providers/gemini/client.ts +9 -23
- package/src/providers/gemini-thought-signature.test.ts +63 -0
- package/src/providers/gemini-thought-signature.ts +44 -0
- package/src/providers/inference/__tests__/endpoint-probe.test.ts +42 -3
- package/src/providers/inference/auth.ts +2 -3
- package/src/providers/inference/connection-availability.ts +27 -8
- package/src/providers/inference/endpoint-probe.ts +10 -1
- package/src/providers/inference/resolve-auth.ts +22 -4
- package/src/providers/inference/service-account-token.ts +248 -0
- package/src/providers/model-catalog.ts +34 -0
- package/src/providers/model-intents.ts +10 -5
- package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
- package/src/providers/openai/chat-completions-provider.ts +212 -79
- package/src/providers/openai/codex-models.ts +0 -4
- package/src/providers/openai/google-thought-signature.ts +320 -0
- package/src/providers/opencode/client.test.ts +73 -4
- package/src/providers/opencode/client.ts +60 -3
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/outbound-request-sanitize.ts +96 -0
- package/src/providers/retry.ts +30 -19
- package/src/providers/unparseable-tool-args.ts +5 -1
- package/src/runtime/AGENTS.md +3 -1
- package/src/runtime/__tests__/channel-send.test.ts +443 -0
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -0
- package/src/runtime/__tests__/host-observe.test.ts +40 -1
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
- package/src/runtime/agent-wake.ts +2 -1
- package/src/runtime/assistant-event-hub.ts +21 -3
- package/src/runtime/auth/same-actor.ts +38 -3
- package/src/runtime/channel-send.ts +316 -0
- package/src/runtime/host-observe.ts +11 -1
- package/src/runtime/http-server.ts +160 -151
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
- package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
- package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
- package/src/runtime/routes/acp-routes.test.ts +15 -0
- package/src/runtime/routes/acp-routes.ts +72 -9
- package/src/runtime/routes/app-management-routes.ts +90 -2
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/channel-send-routes.ts +85 -0
- package/src/runtime/routes/conversation-list-routes.ts +14 -3
- package/src/runtime/routes/conversation-query-routes.ts +40 -0
- package/src/runtime/routes/conversation-routes.ts +16 -3
- package/src/runtime/routes/credential-routes.ts +20 -14
- package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
- package/src/runtime/routes/desktop-setup-routes.ts +35 -0
- package/src/runtime/routes/diagnostics-routes.ts +61 -4
- package/src/runtime/routes/events-routes.ts +4 -0
- package/src/runtime/routes/host-cu-routes.ts +6 -0
- package/src/runtime/routes/index.ts +4 -2
- package/src/runtime/routes/log-export-routes.ts +2 -0
- package/src/runtime/routes/mcp-auth-routes.ts +39 -47
- package/src/runtime/routes/migration-routes.ts +6 -20
- package/src/runtime/routes/oauth-commands-routes.ts +50 -0
- package/src/runtime/routes/oauth-providers.ts +7 -0
- package/src/runtime/routes/platform-routes.ts +18 -15
- package/src/runtime/routes/workspace-routes.test.ts +55 -26
- package/src/runtime/routes/workspace-routes.ts +46 -63
- package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
- package/src/runtime/routes/workspace-tree-walk.ts +240 -0
- package/src/runtime/routes/workspace-utils.ts +17 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +16 -3
- package/src/runtime/sync/resource-sync-events.ts +2 -1
- package/src/schedule/run-script.ts +2 -1
- package/src/schedule/schedule-store.ts +9 -2
- package/src/schedule/worker.ts +1 -1
- package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
- package/src/security/ces-http-record-backend.ts +120 -0
- package/src/security/ces-rpc-record-backend.ts +7 -0
- package/src/security/untrusted-content.ts +3 -1
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
- package/src/skills/workspace-skill-md-signature.ts +50 -0
- package/src/subagent/consult-context.ts +12 -25
- package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
- package/src/tools/acp/list-agents.test.ts +3 -1
- package/src/tools/acp/spawn.test.ts +146 -11
- package/src/tools/acp/spawn.ts +21 -3
- package/src/tools/acp/status.test.ts +94 -0
- package/src/tools/acp/status.ts +40 -3
- package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
- package/src/tools/browser/network-recorder.ts +2 -1
- package/src/tools/capability-offer.test.ts +22 -2
- package/src/tools/capability-offer.ts +16 -1
- package/src/tools/computer-use/definitions.ts +121 -2
- package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
- package/src/tools/credentials/metadata-store.ts +100 -0
- package/src/tools/filesystem/search.ts +2 -1
- package/src/tools/host-filesystem/edit.test.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +2 -1
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +2 -1
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +16 -0
- package/src/tools/host-terminal/host-shell.ts +4 -20
- package/src/tools/network/web-search.ts +6 -1
- package/src/tools/policy-context.ts +6 -7
- package/src/tools/skills/scaffold-managed.ts +61 -3
- package/src/tools/subagent/spawn.ts +5 -8
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
- package/src/tools/terminal/sanitized-bash.ts +105 -0
- package/src/tools/ui-surface/channel-variants.ts +10 -59
- package/src/tools/watch/watch-retro-report.ts +0 -8
- package/src/types/host-capabilities.ts +5 -3
- package/src/util/__tests__/language-subtag.test.ts +23 -1
- package/src/util/ca-bundle.ts +13 -0
- package/src/util/language-subtag.ts +16 -0
- package/src/util/platform.ts +8 -0
- package/src/util/unicode.ts +15 -1
- package/src/watch/watch-retro.ts +6 -8
- package/src/watch/watch-timeline.ts +2 -2
- package/src/workflows/run-manager.ts +2 -1
- package/src/workspace/git-porcelain.ts +66 -0
- package/src/workspace/git-service.ts +6 -55
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/app-source-watcher.test.ts +0 -218
- package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
- package/src/__tests__/speaker-identification.test.ts +0 -56
- package/src/calls/speaker-identification.ts +0 -233
- package/src/daemon/app-source-watcher.ts +0 -218
- package/src/messaging/providers/whatsapp/client.ts +0 -29
- package/src/runtime/routes/debug-bash-routes.ts +0 -173
- package/src/util/fs-watcher-error.ts +0 -36
- /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handler for a model-directed text send to a channel chat.
|
|
3
|
+
*
|
|
4
|
+
* POST /v1/channels/send: deliver text to a chat on a channel through the
|
|
5
|
+
* channel's transport, recorded after acknowledgement. The
|
|
6
|
+
* messaging tool's channel branch runs the same function in-process; this
|
|
7
|
+
* route is the door for the CLI and scripts, so the two doors share one
|
|
8
|
+
* seam and one record.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
import { CHANNEL_IDS } from "../../channels/types.js";
|
|
14
|
+
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
15
|
+
import {
|
|
16
|
+
ChannelNotAddressableError,
|
|
17
|
+
ChannelSendFailedError,
|
|
18
|
+
sendChannelText,
|
|
19
|
+
} from "../channel-send.js";
|
|
20
|
+
import { BadGatewayError, BadRequestError } from "./errors.js";
|
|
21
|
+
import { parseBody } from "./parse-body.js";
|
|
22
|
+
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
23
|
+
|
|
24
|
+
const ProactiveTargetSchema = z.object({
|
|
25
|
+
kind: z.literal("chat"),
|
|
26
|
+
chatId: z.string().min(1).describe("Chat id in the channel's own id space"),
|
|
27
|
+
threadId: z
|
|
28
|
+
.string()
|
|
29
|
+
.min(1)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Thread within the chat, in the channel's own id space"),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const ChannelSendRequestSchema = z.object({
|
|
35
|
+
channel: z.enum(CHANNEL_IDS).describe("Channel to send on"),
|
|
36
|
+
target: ProactiveTargetSchema,
|
|
37
|
+
text: z.string().min(1).describe("Text to send"),
|
|
38
|
+
renderRichly: z
|
|
39
|
+
.boolean()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Ask the channel for its rich rendering, where it has one"),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const ChannelSendResponseSchema = z.object({
|
|
45
|
+
channel: z.enum(CHANNEL_IDS),
|
|
46
|
+
chatId: z.string(),
|
|
47
|
+
threadId: z.string().optional(),
|
|
48
|
+
messageIds: z.array(z.string()),
|
|
49
|
+
lastMessageId: z.string(),
|
|
50
|
+
recordedIn: z.string().optional(),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
async function handleChannelSend({ body }: RouteHandlerArgs) {
|
|
54
|
+
const request = parseBody(ChannelSendRequestSchema, body);
|
|
55
|
+
try {
|
|
56
|
+
return await sendChannelText(request);
|
|
57
|
+
} catch (e) {
|
|
58
|
+
if (e instanceof ChannelNotAddressableError) {
|
|
59
|
+
throw new BadRequestError(e.message);
|
|
60
|
+
}
|
|
61
|
+
if (e instanceof ChannelSendFailedError) {
|
|
62
|
+
throw new BadGatewayError(e.message);
|
|
63
|
+
}
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const ROUTES: RouteDefinition[] = [
|
|
69
|
+
{
|
|
70
|
+
operationId: "channels_send_post",
|
|
71
|
+
endpoint: "channels/send",
|
|
72
|
+
method: "POST",
|
|
73
|
+
policy: {
|
|
74
|
+
requiredScopes: ["chat.write"],
|
|
75
|
+
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
76
|
+
},
|
|
77
|
+
summary: "Send text to a channel chat",
|
|
78
|
+
description:
|
|
79
|
+
"Deliver text to a chat on a channel through the channel's transport, recorded after the channel acknowledges it.",
|
|
80
|
+
tags: ["channels"],
|
|
81
|
+
handler: handleChannelSend,
|
|
82
|
+
requestBody: ChannelSendRequestSchema,
|
|
83
|
+
responseBody: ChannelSendResponseSchema,
|
|
84
|
+
},
|
|
85
|
+
];
|
|
@@ -14,6 +14,7 @@ import { z } from "zod";
|
|
|
14
14
|
|
|
15
15
|
import { CHANNEL_IDS } from "../../channels/types.js";
|
|
16
16
|
import { isAssistantInitiatedThreadsEnabled } from "../../config/assistant-initiated-threads-gate.js";
|
|
17
|
+
import { localeFromAcceptLanguage } from "../../i18n/index.js";
|
|
17
18
|
import { channelBindingSchema } from "../../messaging/channel-binding-schema.js";
|
|
18
19
|
import {
|
|
19
20
|
type Confidence,
|
|
@@ -244,7 +245,10 @@ function parseEnumQueryParam<const T extends readonly string[]>(
|
|
|
244
245
|
);
|
|
245
246
|
}
|
|
246
247
|
|
|
247
|
-
function handleListConversations({
|
|
248
|
+
function handleListConversations({
|
|
249
|
+
queryParams = {},
|
|
250
|
+
headers,
|
|
251
|
+
}: RouteHandlerArgs) {
|
|
248
252
|
const limit = Number(queryParams.limit ?? 50);
|
|
249
253
|
const offset = Number(queryParams.offset ?? 0);
|
|
250
254
|
// "background" is the back-compat umbrella (background + scheduled); newer
|
|
@@ -365,6 +369,7 @@ function handleListConversations({ queryParams = {} }: RouteHandlerArgs) {
|
|
|
365
369
|
// Checks in-memory flag first (hot path), falls back to the
|
|
366
370
|
// persisted `processing_started_at` column for cold conversations.
|
|
367
371
|
isProcessing: isConversationProcessing(conversation.id),
|
|
372
|
+
locale: localeFromAcceptLanguage(headers?.["accept-language"]),
|
|
368
373
|
}),
|
|
369
374
|
),
|
|
370
375
|
nextOffset,
|
|
@@ -579,8 +584,14 @@ function handleMarkUnread({ body = {}, headers }: RouteHandlerArgs) {
|
|
|
579
584
|
}
|
|
580
585
|
}
|
|
581
586
|
|
|
582
|
-
function handleGetConversation({
|
|
583
|
-
|
|
587
|
+
function handleGetConversation({
|
|
588
|
+
pathParams = {},
|
|
589
|
+
headers,
|
|
590
|
+
}: RouteHandlerArgs) {
|
|
591
|
+
const detail = buildConversationDetailResponse(
|
|
592
|
+
pathParams.id!,
|
|
593
|
+
localeFromAcceptLanguage(headers?.["accept-language"]),
|
|
594
|
+
);
|
|
584
595
|
if (!detail) {
|
|
585
596
|
throw new NotFoundError(`Conversation ${pathParams.id} not found`);
|
|
586
597
|
}
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
LatencyBreakdownSchema,
|
|
30
30
|
LLMRequestLogEntrySchema,
|
|
31
31
|
} from "../../api/responses/llm-request-log-entry.js";
|
|
32
|
+
import { scrubNulledAcpAgentLeaves } from "../../config/acp-agent-write.js";
|
|
32
33
|
import {
|
|
33
34
|
catalogEntryFor,
|
|
34
35
|
type InputModalities,
|
|
@@ -92,6 +93,7 @@ import {
|
|
|
92
93
|
log,
|
|
93
94
|
} from "../../daemon/handlers/shared.js";
|
|
94
95
|
import { rescheduleHeartbeatIfTimezoneChanged } from "../../heartbeat/heartbeat-service.js";
|
|
96
|
+
import { overlayWorkspaceMcpForConfigRead } from "../../mcp/workspace-mcp-config.js";
|
|
95
97
|
import {
|
|
96
98
|
getAssistantMessageIdsInTurn,
|
|
97
99
|
getConversation,
|
|
@@ -687,6 +689,38 @@ function rejectMcpTransportHeaderWrite(patch: unknown): void {
|
|
|
687
689
|
);
|
|
688
690
|
}
|
|
689
691
|
|
|
692
|
+
const MCP_CONFIG_WRITE_MESSAGE =
|
|
693
|
+
"MCP servers are stored in mcp.json. Use assistant mcp add or assistant mcp remove.";
|
|
694
|
+
|
|
695
|
+
function stripMcpFromConfigWrite(patch: Record<string, unknown>): void {
|
|
696
|
+
if (Object.hasOwn(patch, "mcp")) {
|
|
697
|
+
delete patch.mcp;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function rejectMcpConfigSetPath(path: string, value: unknown): void {
|
|
702
|
+
if (path !== "mcp" && !path.startsWith("mcp.")) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
const relative =
|
|
706
|
+
path === "mcp" ? value : nestPath(path.slice("mcp.".length), value);
|
|
707
|
+
if (patchContainsMcpTransportHeaders({ mcp: relative })) {
|
|
708
|
+
throw new BadRequestError(
|
|
709
|
+
"MCP authentication headers must be managed through MCP server add/update APIs, not generic config writes.",
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
throw new BadRequestError(MCP_CONFIG_WRITE_MESSAGE);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
function nestPath(path: string, value: unknown): unknown {
|
|
716
|
+
const segments = path.split(".");
|
|
717
|
+
let current: unknown = value;
|
|
718
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
719
|
+
current = { [segments[i]!]: current };
|
|
720
|
+
}
|
|
721
|
+
return current;
|
|
722
|
+
}
|
|
723
|
+
|
|
690
724
|
const WireProfileEntry = ProfileEntry.extend({
|
|
691
725
|
supportsVision: z.boolean().optional(),
|
|
692
726
|
invariant: z.boolean().optional(),
|
|
@@ -893,6 +927,7 @@ const ConfigPatchRequestSchema = z
|
|
|
893
927
|
function handleGetConfig() {
|
|
894
928
|
try {
|
|
895
929
|
const config = applyContextDefaultsToRawConfig(loadRawConfig());
|
|
930
|
+
overlayWorkspaceMcpForConfigRead(config);
|
|
896
931
|
sanitizeMcpTransportHeadersForSettingsRead(config);
|
|
897
932
|
overlayEffectiveProfilesForWire(config);
|
|
898
933
|
enrichProfilesForWire(config);
|
|
@@ -1594,6 +1629,7 @@ async function handlePatchConfig({ body }: RouteHandlerArgs) {
|
|
|
1594
1629
|
normalizeManagedProfileWrites(body);
|
|
1595
1630
|
rejectManagedProfileDeletion(body as Record<string, unknown>);
|
|
1596
1631
|
rejectMcpTransportHeaderWrite(body);
|
|
1632
|
+
stripMcpFromConfigWrite(body as Record<string, unknown>);
|
|
1597
1633
|
|
|
1598
1634
|
const raw = loadRawConfig();
|
|
1599
1635
|
const patch = body as Record<string, unknown>;
|
|
@@ -1603,11 +1639,13 @@ async function handlePatchConfig({ body }: RouteHandlerArgs) {
|
|
|
1603
1639
|
}
|
|
1604
1640
|
deepMergeOverwrite(raw, patch);
|
|
1605
1641
|
scrubRemovedServiceModes(raw);
|
|
1642
|
+
scrubNulledAcpAgentLeaves(raw);
|
|
1606
1643
|
seedSttProviderForSparseBlock(raw);
|
|
1607
1644
|
|
|
1608
1645
|
await commitConfigWrite(raw, "patch");
|
|
1609
1646
|
|
|
1610
1647
|
const merged = applyContextDefaultsToRawConfig(loadRawConfig());
|
|
1648
|
+
overlayWorkspaceMcpForConfigRead(merged);
|
|
1611
1649
|
sanitizeMcpTransportHeadersForSettingsRead(merged);
|
|
1612
1650
|
overlayEffectiveProfilesForWire(merged);
|
|
1613
1651
|
enrichProfilesForWire(merged);
|
|
@@ -1670,6 +1708,7 @@ async function handleSetConfig({ body }: RouteHandlerArgs) {
|
|
|
1670
1708
|
stripWireOnlyProfileKeys(patchShape);
|
|
1671
1709
|
normalizeManagedProfileWrites(patchShape);
|
|
1672
1710
|
rejectManagedProfileDeletion(patchShape);
|
|
1711
|
+
rejectMcpConfigSetPath(path, value);
|
|
1673
1712
|
rejectMcpTransportHeaderWrite(patchShape);
|
|
1674
1713
|
|
|
1675
1714
|
const raw = loadRawConfig();
|
|
@@ -1708,6 +1747,7 @@ async function handleSetConfig({ body }: RouteHandlerArgs) {
|
|
|
1708
1747
|
written.source = "managed";
|
|
1709
1748
|
}
|
|
1710
1749
|
}
|
|
1750
|
+
scrubNulledAcpAgentLeaves(raw);
|
|
1711
1751
|
// A SET can create `services.stt` with a leaf like `language` and no
|
|
1712
1752
|
// `provider`, which SttServiceSchema requires whenever the block exists;
|
|
1713
1753
|
// the same seeding that guards PATCH keeps this write's persisted block
|
|
@@ -140,7 +140,10 @@ import {
|
|
|
140
140
|
getOrCreateConversation,
|
|
141
141
|
} from "../../persistence/conversation-key-store.js";
|
|
142
142
|
import { searchConversations } from "../../persistence/conversation-queries.js";
|
|
143
|
-
import {
|
|
143
|
+
import {
|
|
144
|
+
isNoResponseMetadata,
|
|
145
|
+
messageMetadataIsAmbientSightKeep,
|
|
146
|
+
} from "../../persistence/conversation-types.js";
|
|
144
147
|
import { linkRequestLogsToMessage } from "../../persistence/llm-request-log-store.js";
|
|
145
148
|
import { assistantTextVisibilityOf } from "../../persistence/user-facing-content.js";
|
|
146
149
|
import { MEMORY_RETROSPECTIVE_FORK_SOURCE } from "../../plugins/defaults/memory/memory-retrospective-constants.js";
|
|
@@ -159,6 +162,7 @@ import {
|
|
|
159
162
|
getWorkspaceDir,
|
|
160
163
|
getWorkspacePromptPath,
|
|
161
164
|
} from "../../util/platform.js";
|
|
165
|
+
import { safeStringSlice } from "../../util/unicode.js";
|
|
162
166
|
import { assistantEventHub, broadcastMessage } from "../assistant-event-hub.js";
|
|
163
167
|
import { getCurrentSeq } from "../assistant-stream-state.js";
|
|
164
168
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
@@ -1037,6 +1041,9 @@ export async function handleListMessages({
|
|
|
1037
1041
|
let backgroundToolCompletion: ConversationMessage["backgroundToolCompletion"];
|
|
1038
1042
|
let systemCard: boolean | undefined;
|
|
1039
1043
|
let noResponse: boolean | undefined;
|
|
1044
|
+
const cameraFrame = messageMetadataIsAmbientSightKeep(msg.metadata)
|
|
1045
|
+
? true
|
|
1046
|
+
: undefined;
|
|
1040
1047
|
let reaction: ConversationMessage["reaction"];
|
|
1041
1048
|
let providerError: ConversationMessage["providerError"];
|
|
1042
1049
|
let deletedAt: number | undefined;
|
|
@@ -1136,6 +1143,7 @@ export async function handleListMessages({
|
|
|
1136
1143
|
backgroundToolCompletion,
|
|
1137
1144
|
systemCard,
|
|
1138
1145
|
noResponse,
|
|
1146
|
+
cameraFrame,
|
|
1139
1147
|
reaction,
|
|
1140
1148
|
providerError,
|
|
1141
1149
|
slackMessage,
|
|
@@ -1353,6 +1361,7 @@ export async function handleListMessages({
|
|
|
1353
1361
|
: {}),
|
|
1354
1362
|
...(m.systemCard ? { systemCard: true } : {}),
|
|
1355
1363
|
...(m.noResponse ? { noResponse: true } : {}),
|
|
1364
|
+
...(m.cameraFrame ? { cameraFrame: true as const } : {}),
|
|
1356
1365
|
// The row's own marker, so a client gates per-row presentation on what
|
|
1357
1366
|
// this row was written with rather than on the live flag.
|
|
1358
1367
|
...(m.assistantTextVisibility
|
|
@@ -3289,11 +3298,15 @@ async function generateLlmSuggestion(
|
|
|
3289
3298
|
): Promise<string | null> {
|
|
3290
3299
|
const log = (await import("../../util/logger.js")).getLogger("runtime-http");
|
|
3291
3300
|
const truncatedAssistant = escapeXmlContent(
|
|
3292
|
-
assistantText.length > 2000
|
|
3301
|
+
assistantText.length > 2000
|
|
3302
|
+
? safeStringSlice(assistantText, assistantText.length - 2000)
|
|
3303
|
+
: assistantText,
|
|
3293
3304
|
);
|
|
3294
3305
|
const truncatedUser =
|
|
3295
3306
|
priorUserText && priorUserText.length > 500
|
|
3296
|
-
? escapeXmlContent(
|
|
3307
|
+
? escapeXmlContent(
|
|
3308
|
+
safeStringSlice(priorUserText, priorUserText.length - 500),
|
|
3309
|
+
)
|
|
3297
3310
|
: priorUserText
|
|
3298
3311
|
? escapeXmlContent(priorUserText)
|
|
3299
3312
|
: priorUserText;
|
|
@@ -34,7 +34,6 @@ import { credentialKey } from "../../security/credential-key.js";
|
|
|
34
34
|
import {
|
|
35
35
|
deleteSecureKeyAsync,
|
|
36
36
|
getActiveBackendInfoAsync,
|
|
37
|
-
getSecureKeyAsync,
|
|
38
37
|
getSecureKeyResultAsync,
|
|
39
38
|
} from "../../security/secure-keys.js";
|
|
40
39
|
import {
|
|
@@ -43,7 +42,7 @@ import {
|
|
|
43
42
|
deleteCredentialMetadata,
|
|
44
43
|
getCredentialMetadata,
|
|
45
44
|
getCredentialMetadataById,
|
|
46
|
-
|
|
45
|
+
listCredentialRecordsLive,
|
|
47
46
|
} from "../../tools/credentials/metadata-store.js";
|
|
48
47
|
import type { CredentialInjectionTemplate } from "../../tools/credentials/policy-types.js";
|
|
49
48
|
import {
|
|
@@ -228,6 +227,9 @@ function assertNotPlatformManaged(
|
|
|
228
227
|
}
|
|
229
228
|
}
|
|
230
229
|
|
|
230
|
+
const CREDENTIAL_STORE_UNREACHABLE =
|
|
231
|
+
"Credential store is unreachable. Retry in a moment, or check that the credential vault is running.";
|
|
232
|
+
|
|
231
233
|
// ---------------------------------------------------------------------------
|
|
232
234
|
// Handlers
|
|
233
235
|
// ---------------------------------------------------------------------------
|
|
@@ -235,9 +237,14 @@ function assertNotPlatformManaged(
|
|
|
235
237
|
async function handleCredentialsList({ body }: RouteHandlerArgs) {
|
|
236
238
|
const search = (body as { search?: string } | undefined)?.search;
|
|
237
239
|
|
|
240
|
+
const live = await listCredentialRecordsLive();
|
|
241
|
+
if (live.unreachable) {
|
|
242
|
+
throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
|
|
243
|
+
}
|
|
244
|
+
|
|
238
245
|
// Platform-provisioned credentials are not the user's to act on, so they
|
|
239
246
|
// never become a Settings row (and never a click-to-reveal).
|
|
240
|
-
let allMetadata =
|
|
247
|
+
let allMetadata = live.records.filter(
|
|
241
248
|
(m) => !isPlatformManagedCredential(m.service, m.field),
|
|
242
249
|
);
|
|
243
250
|
|
|
@@ -272,7 +279,12 @@ async function handleCredentialsList({ body }: RouteHandlerArgs) {
|
|
|
272
279
|
|
|
273
280
|
const credentials = await Promise.all(
|
|
274
281
|
allMetadata.map(async (m) => {
|
|
275
|
-
const secret = await
|
|
282
|
+
const { value: secret, unreachable } = await getSecureKeyResultAsync(
|
|
283
|
+
credentialKey(m.service, m.field),
|
|
284
|
+
);
|
|
285
|
+
if (unreachable) {
|
|
286
|
+
throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
|
|
287
|
+
}
|
|
276
288
|
const connection = connectionsByProvider.get(m.service);
|
|
277
289
|
return buildCredentialOutput(m, secret, connection);
|
|
278
290
|
}),
|
|
@@ -310,9 +322,7 @@ async function handleCredentialsInspect({ body }: RouteHandlerArgs) {
|
|
|
310
322
|
|
|
311
323
|
if (!lookup.metadata && (secret == null || secret.length === 0)) {
|
|
312
324
|
if (unreachable) {
|
|
313
|
-
throw new InternalError(
|
|
314
|
-
"Credential store is unreachable — ensure the assistant is running",
|
|
315
|
-
);
|
|
325
|
+
throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
|
|
316
326
|
}
|
|
317
327
|
throw new BadRequestError("Credential not found");
|
|
318
328
|
}
|
|
@@ -374,9 +384,7 @@ async function handleCredentialsReveal({ body, headers }: RouteHandlerArgs) {
|
|
|
374
384
|
|
|
375
385
|
if (secret == null || secret.length === 0) {
|
|
376
386
|
if (unreachable) {
|
|
377
|
-
throw new InternalError(
|
|
378
|
-
"Credential store is unreachable — ensure the assistant is running",
|
|
379
|
-
);
|
|
387
|
+
throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
|
|
380
388
|
}
|
|
381
389
|
throw new BadRequestError("Credential not found");
|
|
382
390
|
}
|
|
@@ -552,9 +560,7 @@ async function handleCredentialsDelete({ body }: RouteHandlerArgs) {
|
|
|
552
560
|
|
|
553
561
|
const key = credentialKey(service, field);
|
|
554
562
|
const affectedConnections = assertCredentialNotInUse(key, force === true);
|
|
555
|
-
const
|
|
556
|
-
const deleteResult =
|
|
557
|
-
existing != null ? await deleteSecureKeyAsync(key) : "not-found";
|
|
563
|
+
const deleteResult = await deleteSecureKeyAsync(key);
|
|
558
564
|
|
|
559
565
|
if (deleteResult === "error") {
|
|
560
566
|
throw new InternalError(
|
|
@@ -620,7 +626,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
620
626
|
},
|
|
621
627
|
summary: "List all credentials with metadata",
|
|
622
628
|
description:
|
|
623
|
-
"Return
|
|
629
|
+
"Return credentials from the live credential vault, with OAuth connection info and platform-managed credentials. Fails if the vault is unreachable.",
|
|
624
630
|
tags: ["credentials"],
|
|
625
631
|
requestBody: z.object({
|
|
626
632
|
search: z.string().optional().describe("Filter by substring match"),
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
afterAll,
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
spyOn,
|
|
8
|
+
test,
|
|
9
|
+
} from "bun:test";
|
|
10
|
+
|
|
11
|
+
import { setOverridesForTesting } from "../../__tests__/feature-flag-test-helpers.js";
|
|
12
|
+
import { desktopDependencyInstaller } from "../../desktop/desktop-dependencies.js";
|
|
13
|
+
import { ROUTES } from "./desktop-setup-routes.js";
|
|
14
|
+
import { NotFoundError } from "./errors.js";
|
|
15
|
+
|
|
16
|
+
const originalContainerized = process.env.IS_CONTAINERIZED;
|
|
17
|
+
const status = spyOn(desktopDependencyInstaller, "getStatus");
|
|
18
|
+
const start = spyOn(desktopDependencyInstaller, "start");
|
|
19
|
+
|
|
20
|
+
afterAll(() => {
|
|
21
|
+
status.mockRestore();
|
|
22
|
+
start.mockRestore();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
process.env.IS_CONTAINERIZED = "true";
|
|
27
|
+
status.mockReturnValue({ state: "required" });
|
|
28
|
+
start.mockReturnValue({ state: "installing", stage: "packages" });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
if (originalContainerized === undefined) {
|
|
33
|
+
delete process.env.IS_CONTAINERIZED;
|
|
34
|
+
} else {
|
|
35
|
+
process.env.IS_CONTAINERIZED = originalContainerized;
|
|
36
|
+
}
|
|
37
|
+
setOverridesForTesting({});
|
|
38
|
+
status.mockClear();
|
|
39
|
+
start.mockClear();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("desktop setup route feature gate", () => {
|
|
43
|
+
for (const route of ROUTES) {
|
|
44
|
+
for (const flag of [false, undefined]) {
|
|
45
|
+
test(`${route.method} refuses a disabled or missing flag (${flag}) without touching setup`, () => {
|
|
46
|
+
setOverridesForTesting(
|
|
47
|
+
flag === undefined ? {} : { "assistant-desktop": flag },
|
|
48
|
+
);
|
|
49
|
+
expect(() => route.handler({})).toThrow(NotFoundError);
|
|
50
|
+
expect(status).not.toHaveBeenCalled();
|
|
51
|
+
expect(start).not.toHaveBeenCalled();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
test(`${route.method} refuses non-containerized assistants even with the flag enabled`, () => {
|
|
56
|
+
process.env.IS_CONTAINERIZED = "false";
|
|
57
|
+
setOverridesForTesting({ "assistant-desktop": true });
|
|
58
|
+
expect(() => route.handler({})).toThrow(NotFoundError);
|
|
59
|
+
expect(status).not.toHaveBeenCalled();
|
|
60
|
+
expect(start).not.toHaveBeenCalled();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test(`${route.method} serves setup only with the flag enabled in a container`, () => {
|
|
64
|
+
setOverridesForTesting({ "assistant-desktop": true });
|
|
65
|
+
expect(route.handler({})).toEqual(
|
|
66
|
+
route.method === "GET"
|
|
67
|
+
? { state: "required" }
|
|
68
|
+
: { state: "installing", stage: "packages" },
|
|
69
|
+
);
|
|
70
|
+
expect(route.method === "GET" ? status : start).toHaveBeenCalledTimes(1);
|
|
71
|
+
expect(route.method === "GET" ? start : status).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { getConfig } from "../../config/loader.js";
|
|
4
|
+
import { desktopDependencyInstaller } from "../../desktop/desktop-dependencies.js";
|
|
5
|
+
import { isAssistantDesktopEnabled } from "../../desktop/desktop-feature.js";
|
|
6
|
+
import { GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
|
|
7
|
+
import { NotFoundError } from "./errors.js";
|
|
8
|
+
import type { RouteDefinition } from "./types.js";
|
|
9
|
+
|
|
10
|
+
const statusSchema = z.object({
|
|
11
|
+
state: z.enum(["required", "installing", "ready", "failed", "unsupported"]),
|
|
12
|
+
stage: z.enum(["packages", "chrome", "checking"]).optional(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const ROUTES: RouteDefinition[] = ["GET", "POST"].map((method) => ({
|
|
16
|
+
operationId:
|
|
17
|
+
method === "GET" ? "desktop_setup_status" : "desktop_setup_install",
|
|
18
|
+
endpoint: "desktop/setup",
|
|
19
|
+
method,
|
|
20
|
+
policy: { requiredScopes: [], allowedPrincipalTypes: GATEWAY_PRINCIPALS },
|
|
21
|
+
handler: () => {
|
|
22
|
+
if (!isAssistantDesktopEnabled(getConfig())) {
|
|
23
|
+
throw new NotFoundError("Desktop is not available on this assistant");
|
|
24
|
+
}
|
|
25
|
+
return method === "GET"
|
|
26
|
+
? desktopDependencyInstaller.getStatus()
|
|
27
|
+
: desktopDependencyInstaller.start();
|
|
28
|
+
},
|
|
29
|
+
summary:
|
|
30
|
+
method === "GET"
|
|
31
|
+
? "Get desktop setup status"
|
|
32
|
+
: "Install desktop components",
|
|
33
|
+
tags: ["desktop"],
|
|
34
|
+
responseBody: statusSchema,
|
|
35
|
+
}));
|
|
@@ -22,7 +22,9 @@ import {
|
|
|
22
22
|
getConfiguredProvider,
|
|
23
23
|
userMessage,
|
|
24
24
|
} from "../../providers/provider-send-message.js";
|
|
25
|
+
import { isMaxTokensStopReason } from "../../providers/stop-reasons.js";
|
|
25
26
|
import { getLogger } from "../../util/logger.js";
|
|
27
|
+
import { safeStringSlice } from "../../util/unicode.js";
|
|
26
28
|
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
27
29
|
import { BadRequestError } from "./errors.js";
|
|
28
30
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
@@ -48,7 +50,11 @@ function sanitizeWindowTitle(title: string | undefined): string {
|
|
|
48
50
|
if (!title) {
|
|
49
51
|
return "";
|
|
50
52
|
}
|
|
51
|
-
return
|
|
53
|
+
return safeStringSlice(
|
|
54
|
+
title.replace(/[<>]/g, ""),
|
|
55
|
+
0,
|
|
56
|
+
MAX_WINDOW_TITLE_LENGTH,
|
|
57
|
+
);
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
interface DictationBody {
|
|
@@ -176,9 +182,44 @@ function buildCommandPrompt(body: DictationBody, stylePrompt?: string): string {
|
|
|
176
182
|
return sections.join("\n");
|
|
177
183
|
}
|
|
178
184
|
|
|
179
|
-
function computeMaxTokens(inputLength: number): number {
|
|
185
|
+
export function computeMaxTokens(inputLength: number): number {
|
|
180
186
|
const estimatedInputTokens = Math.ceil(inputLength / 3);
|
|
181
|
-
|
|
187
|
+
// The cleanup tool call carries the whole transcript back in its `text`
|
|
188
|
+
// argument, plus a `reasoning` string and the JSON scaffolding around both,
|
|
189
|
+
// so the budget has to cover well more than the input alone. `max_tokens` is
|
|
190
|
+
// a ceiling rather than a target: a call that stops short of it costs no
|
|
191
|
+
// extra latency.
|
|
192
|
+
return Math.max(512, estimatedInputTokens * 2 + 256);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export type CleanupRejection = "truncated";
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Decide whether the cleanup model's rewrite is safe to use as the payload.
|
|
199
|
+
*
|
|
200
|
+
* The rewrite replaces what the user actually said. A token-cap stop means the
|
|
201
|
+
* tool JSON was cut mid-argument, so however complete the `text` argument
|
|
202
|
+
* happens to look, it is a fragment; the raw transcript is the safer payload
|
|
203
|
+
* then. Unpolished beats wrong.
|
|
204
|
+
*
|
|
205
|
+
* Whether a shorter rewrite still preserved the meaning is the model's call
|
|
206
|
+
* (the prompt asks it to drop fillers and tighten phrasing), so there is no
|
|
207
|
+
* length check here: a deterministic ratio cannot tell a concise cleanup from
|
|
208
|
+
* a summary.
|
|
209
|
+
*/
|
|
210
|
+
export function resolveCleanedDictation(
|
|
211
|
+
raw: string,
|
|
212
|
+
cleaned: string,
|
|
213
|
+
stopReason: string | null | undefined,
|
|
214
|
+
): { text: string; rejected: CleanupRejection | null } {
|
|
215
|
+
const trimmed = cleaned.trim();
|
|
216
|
+
if (!trimmed) {
|
|
217
|
+
return { text: raw, rejected: null };
|
|
218
|
+
}
|
|
219
|
+
if (isMaxTokensStopReason(stopReason)) {
|
|
220
|
+
return { text: raw, rejected: "truncated" };
|
|
221
|
+
}
|
|
222
|
+
return { text: trimmed, rejected: null };
|
|
182
223
|
}
|
|
183
224
|
|
|
184
225
|
interface DictationResult {
|
|
@@ -329,7 +370,23 @@ async function handleDictation(body: DictationBody): Promise<DictationResult> {
|
|
|
329
370
|
...profileMeta,
|
|
330
371
|
};
|
|
331
372
|
}
|
|
332
|
-
const cleanedText =
|
|
373
|
+
const { text: cleanedText, rejected } = resolveCleanedDictation(
|
|
374
|
+
transcription,
|
|
375
|
+
input.text ?? "",
|
|
376
|
+
response.stopReason,
|
|
377
|
+
);
|
|
378
|
+
if (rejected) {
|
|
379
|
+
// Lengths only -- transcript content must never be logged.
|
|
380
|
+
log.warn(
|
|
381
|
+
{
|
|
382
|
+
rejected,
|
|
383
|
+
stopReason: response.stopReason,
|
|
384
|
+
rawChars: transcription.length,
|
|
385
|
+
cleanedChars: input.text?.trim().length ?? 0,
|
|
386
|
+
},
|
|
387
|
+
"Dictation cleanup rejected, using raw transcription",
|
|
388
|
+
);
|
|
389
|
+
}
|
|
333
390
|
const normalizedText = applyDictionary(cleanedText, profile.dictionary);
|
|
334
391
|
return {
|
|
335
392
|
text: normalizedText,
|
|
@@ -445,6 +445,10 @@ export function handleSubscribeAssistantEvents(
|
|
|
445
445
|
? ["host_cu_window_capture" as const]
|
|
446
446
|
: []),
|
|
447
447
|
...(interfaceId === "macos" &&
|
|
448
|
+
headers?.["x-vellum-cu-sequence"] === "1"
|
|
449
|
+
? ["host_cu_sequence" as const]
|
|
450
|
+
: []),
|
|
451
|
+
...(interfaceId === "macos" &&
|
|
448
452
|
headers?.["x-vellum-cu-annotate"] === "1"
|
|
449
453
|
? ["host_cu_annotate" as const]
|
|
450
454
|
: []),
|
|
@@ -36,6 +36,10 @@ const HostCuResultBodySchema = z.object({
|
|
|
36
36
|
executionError: z.string().optional(),
|
|
37
37
|
secondaryWindows: z.string().optional(),
|
|
38
38
|
userGuidance: z.string().optional(),
|
|
39
|
+
timings: z
|
|
40
|
+
.record(z.string(), z.number())
|
|
41
|
+
.describe("Per-phase helper timings in milliseconds")
|
|
42
|
+
.optional(),
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
// ---------------------------------------------------------------------------
|
|
@@ -56,6 +60,7 @@ async function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
|
56
60
|
executionError,
|
|
57
61
|
secondaryWindows,
|
|
58
62
|
userGuidance,
|
|
63
|
+
timings,
|
|
59
64
|
} = parseBody(HostCuResultBodySchema, body);
|
|
60
65
|
|
|
61
66
|
const peeked = pendingInteractions.get(requestId);
|
|
@@ -119,6 +124,7 @@ async function handleHostCuResult({ body, headers }: RouteHandlerArgs) {
|
|
|
119
124
|
executionError,
|
|
120
125
|
secondaryWindows,
|
|
121
126
|
userGuidance,
|
|
127
|
+
timings,
|
|
122
128
|
});
|
|
123
129
|
|
|
124
130
|
return { accepted: true };
|
|
@@ -39,6 +39,7 @@ import { ROUTES as CALL_ROUTES } from "./call-routes.js";
|
|
|
39
39
|
import { ROUTES as CHANNEL_AVAILABILITY_ROUTES } from "./channel-availability-routes.js";
|
|
40
40
|
import { ROUTES as CHANNEL_READINESS_ROUTES } from "./channel-readiness-routes.js";
|
|
41
41
|
import { CHANNEL_ROUTES } from "./channel-route-definitions.js";
|
|
42
|
+
import { ROUTES as CHANNEL_SEND_ROUTES } from "./channel-send-routes.js";
|
|
42
43
|
import { ROUTES as CHANNEL_VERIFICATION_ROUTES } from "./channel-verification-routes.js";
|
|
43
44
|
import { ROUTES as CHATGPT_SUBSCRIPTION_AUTH_ROUTES } from "./chatgpt-subscription-auth-routes.js";
|
|
44
45
|
import { ROUTES as CLIENT_ROUTES } from "./client-routes.js";
|
|
@@ -58,10 +59,10 @@ import { ROUTES as CONVERSATIONS_IMPORT_ROUTES } from "./conversations-import-ro
|
|
|
58
59
|
import { ROUTES as CREDENTIAL_PROMPT_ROUTES } from "./credential-prompt-routes.js";
|
|
59
60
|
import { ROUTES as CREDENTIAL_REQUEST_ROUTES } from "./credential-request-routes.js";
|
|
60
61
|
import { ROUTES as CREDENTIAL_ROUTES } from "./credential-routes.js";
|
|
61
|
-
import { ROUTES as DEBUG_BASH_ROUTES } from "./debug-bash-routes.js";
|
|
62
62
|
import { ROUTES as DEBUG_ROUTES } from "./debug-routes.js";
|
|
63
63
|
import { ROUTES as DEFAULT_PROVIDER_ROUTES } from "./default-provider-routes.js";
|
|
64
64
|
import { ROUTES as DEFER_ROUTES } from "./defer-routes.js";
|
|
65
|
+
import { ROUTES as DESKTOP_SETUP_ROUTES } from "./desktop-setup-routes.js";
|
|
65
66
|
import { ROUTES as DIAGNOSTICS_ROUTES } from "./diagnostics-routes.js";
|
|
66
67
|
import { ROUTES as DISK_PRESSURE_ROUTES } from "./disk-pressure-routes.js";
|
|
67
68
|
import { ROUTES as DOCUMENT_COMMENT_ROUTES } from "./document-comments-routes.js";
|
|
@@ -191,6 +192,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
191
192
|
...CHANNEL_VERIFICATION_ROUTES,
|
|
192
193
|
...CHANNEL_AVAILABILITY_ROUTES,
|
|
193
194
|
...CHANNEL_READINESS_ROUTES,
|
|
195
|
+
...CHANNEL_SEND_ROUTES,
|
|
194
196
|
...BROWSER_ROUTES,
|
|
195
197
|
...BROWSER_TABS_ROUTES,
|
|
196
198
|
...BTW_ROUTES,
|
|
@@ -215,9 +217,9 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
215
217
|
...CONVERSATION_QUERY_ROUTES,
|
|
216
218
|
...CONVERSATION_STARTER_ROUTES,
|
|
217
219
|
...ACTIVATION_ROUTES,
|
|
218
|
-
...DEBUG_BASH_ROUTES,
|
|
219
220
|
...DEBUG_ROUTES,
|
|
220
221
|
...DEFAULT_PROVIDER_ROUTES,
|
|
222
|
+
...DESKTOP_SETUP_ROUTES,
|
|
221
223
|
...DIAGNOSTICS_ROUTES,
|
|
222
224
|
...DISK_PRESSURE_ROUTES,
|
|
223
225
|
...RESOURCE_PRESSURE_ROUTES,
|