@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
|
@@ -42,6 +42,11 @@ const MAX_HISTORY_ENTRIES = 10;
|
|
|
42
42
|
const LOOP_DETECTION_WINDOW = 3;
|
|
43
43
|
const CONSECUTIVE_UNCHANGED_WARNING_THRESHOLD = 2;
|
|
44
44
|
|
|
45
|
+
const SEQUENCE_TOOL = "computer_use_sequence";
|
|
46
|
+
|
|
47
|
+
const SCREENSHOT_OMITTED_MESSAGE =
|
|
48
|
+
"Screenshot omitted: the accessibility tree above is current. Pass include_screenshot: true on computer_use_observe to see the screen.";
|
|
49
|
+
|
|
45
50
|
// computer_use_key combos that change only selection/cursor/clipboard state.
|
|
46
51
|
// The AX tree models none of these, so they always produce an empty diff —
|
|
47
52
|
// exempt them from the "NO VISIBLE EFFECT" signal (mirrors computer_use_wait).
|
|
@@ -113,6 +118,8 @@ export interface CuObservationResult {
|
|
|
113
118
|
executionResult?: string;
|
|
114
119
|
executionError?: string;
|
|
115
120
|
userGuidance?: string;
|
|
121
|
+
/** Per-phase helper timings in milliseconds, absent on older helpers. */
|
|
122
|
+
timings?: Record<string, number>;
|
|
116
123
|
}
|
|
117
124
|
|
|
118
125
|
export interface ActionRecord {
|
|
@@ -161,6 +168,40 @@ function actionSignature(record: ActionRecord): string {
|
|
|
161
168
|
return `${record.toolName}:${JSON.stringify(record.input)}`;
|
|
162
169
|
}
|
|
163
170
|
|
|
171
|
+
/**
|
|
172
|
+
* The key a desktop's first look is tracked under. An untargeted request has
|
|
173
|
+
* no client id, so it gets a key no real id can take.
|
|
174
|
+
*/
|
|
175
|
+
function observedTargetKey(targetClientId: string | undefined): string {
|
|
176
|
+
return targetClientId === undefined
|
|
177
|
+
? "\u0000untargeted"
|
|
178
|
+
: `client:${targetClientId}`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Whether `input` scopes the observation to one window or display. */
|
|
182
|
+
function hasCaptureTarget(input: Record<string, unknown>): boolean {
|
|
183
|
+
return (
|
|
184
|
+
Object.hasOwn(input, "capture_window_id") ||
|
|
185
|
+
Object.hasOwn(input, "captureWindowId") ||
|
|
186
|
+
Object.hasOwn(input, "captureDisplayId")
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Whether the resolved client claimed `capability` on its connection. An
|
|
192
|
+
* untargeted request has no client to vouch for it, so it never qualifies.
|
|
193
|
+
*/
|
|
194
|
+
function clientAdvertises(
|
|
195
|
+
targetClientId: string | undefined,
|
|
196
|
+
capability: "host_cu_window_capture" | "host_cu_sequence",
|
|
197
|
+
): boolean {
|
|
198
|
+
const client =
|
|
199
|
+
targetClientId == null
|
|
200
|
+
? undefined
|
|
201
|
+
: assistantEventHub.getClientById(targetClientId);
|
|
202
|
+
return client?.capabilities.includes(capability) ?? false;
|
|
203
|
+
}
|
|
204
|
+
|
|
164
205
|
// ---------------------------------------------------------------------------
|
|
165
206
|
// HostCuProxy
|
|
166
207
|
// ---------------------------------------------------------------------------
|
|
@@ -172,8 +213,41 @@ export class HostCuProxy {
|
|
|
172
213
|
private _previousAXTree: string | undefined;
|
|
173
214
|
private _consecutiveUnchangedSteps = 0;
|
|
174
215
|
private _actionHistory: ActionRecord[] = [];
|
|
175
|
-
/**
|
|
176
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Desktops an unscoped observation has come back from since the last reset,
|
|
218
|
+
* keyed by `observedTargetKey`. A first look is per desktop: having seen one
|
|
219
|
+
* machine says nothing about another the conversation switches to.
|
|
220
|
+
*/
|
|
221
|
+
private _observedTargets = new Set<string>();
|
|
222
|
+
/**
|
|
223
|
+
* Bumped on every reset. A request carries the value it was dispatched
|
|
224
|
+
* under, so an observation that lands after a reset cannot restore state
|
|
225
|
+
* that reset cleared.
|
|
226
|
+
*/
|
|
227
|
+
private _resetGeneration = 0;
|
|
228
|
+
/**
|
|
229
|
+
* Desktops a request has been sent to since the last reset, keyed by
|
|
230
|
+
* `observedTargetKey`, so the end of a task can reach each one.
|
|
231
|
+
*/
|
|
232
|
+
private _dispatchedTargets = new Map<string, string | undefined>();
|
|
233
|
+
/**
|
|
234
|
+
* Owned request IDs mapped to whether their observation is scoped, whether
|
|
235
|
+
* the helper was told to skip the screenshot, and when the request was
|
|
236
|
+
* dispatched. The dispatch time gives the round trip, which is the part of
|
|
237
|
+
* a step the helper's own timings cannot see.
|
|
238
|
+
*/
|
|
239
|
+
private _ownedRequests = new Map<
|
|
240
|
+
string,
|
|
241
|
+
{
|
|
242
|
+
scoped: boolean;
|
|
243
|
+
screenshotSkipped: boolean;
|
|
244
|
+
targetKey: string;
|
|
245
|
+
resetGeneration: number;
|
|
246
|
+
dispatchedAt: number;
|
|
247
|
+
toolName: string;
|
|
248
|
+
step: number;
|
|
249
|
+
}
|
|
250
|
+
>();
|
|
177
251
|
|
|
178
252
|
constructor(maxSteps = loadConfig().maxStepsPerSession) {
|
|
179
253
|
this._maxSteps = maxSteps;
|
|
@@ -288,11 +362,7 @@ export class HostCuProxy {
|
|
|
288
362
|
}
|
|
289
363
|
// Never dispatch this option to a legacy executor: it would forward the
|
|
290
364
|
// unknown snake-case key and silently capture the entire desktop.
|
|
291
|
-
|
|
292
|
-
resolvedTargetClientId == null
|
|
293
|
-
? undefined
|
|
294
|
-
: assistantEventHub.getClientById(resolvedTargetClientId);
|
|
295
|
-
if (!client?.capabilities.includes("host_cu_window_capture")) {
|
|
365
|
+
if (!clientAdvertises(resolvedTargetClientId, "host_cu_window_capture")) {
|
|
296
366
|
return Promise.resolve({
|
|
297
367
|
content:
|
|
298
368
|
"Window-only observation requires a connected client advertising host_cu_window_capture; update the desktop app before retrying. No capture was requested.",
|
|
@@ -300,14 +370,40 @@ export class HostCuProxy {
|
|
|
300
370
|
});
|
|
301
371
|
}
|
|
302
372
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
373
|
+
// An older helper answers an unknown tool name as done, which would end
|
|
374
|
+
// the session with nothing run.
|
|
375
|
+
if (
|
|
376
|
+
toolName === SEQUENCE_TOOL &&
|
|
377
|
+
!clientAdvertises(resolvedTargetClientId, "host_cu_sequence")
|
|
378
|
+
) {
|
|
379
|
+
return Promise.resolve({
|
|
380
|
+
content:
|
|
381
|
+
"Batched actions require a desktop app that supports computer_use_sequence; update the desktop app, or send the actions one at a time. Nothing was run.",
|
|
382
|
+
isError: true,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
const scopedObservation = hasCaptureTarget(input);
|
|
307
386
|
if (scopedObservation) {
|
|
308
387
|
this._previousAXTree = undefined;
|
|
309
388
|
this._consecutiveUnchangedSteps = 0;
|
|
310
389
|
}
|
|
390
|
+
const targetKey = observedTargetKey(resolvedTargetClientId);
|
|
391
|
+
// Pointing never reaches the helper's capture path, so its input goes out
|
|
392
|
+
// as given. Every other request carries the screenshot decision made now,
|
|
393
|
+
// at dispatch, and never the model-facing snake_case key.
|
|
394
|
+
let dispatchInput = input;
|
|
395
|
+
let screenshotSkipped = false;
|
|
396
|
+
if (toolName !== POINT_AT_PROXY_TOOL) {
|
|
397
|
+
const { include_screenshot: _includeScreenshot, ...rest } = input;
|
|
398
|
+
screenshotSkipped = !this.shouldAttachScreenshot(
|
|
399
|
+
toolName,
|
|
400
|
+
input,
|
|
401
|
+
targetKey,
|
|
402
|
+
);
|
|
403
|
+
dispatchInput = screenshotSkipped
|
|
404
|
+
? { ...rest, includeScreenshot: false }
|
|
405
|
+
: rest;
|
|
406
|
+
}
|
|
311
407
|
const requestId = uuid();
|
|
312
408
|
|
|
313
409
|
return new Promise<ToolExecutionResult>((resolve, reject) => {
|
|
@@ -351,7 +447,16 @@ export class HostCuProxy {
|
|
|
351
447
|
detachAbort = () => signal.removeEventListener("abort", onAbort);
|
|
352
448
|
}
|
|
353
449
|
|
|
354
|
-
this.
|
|
450
|
+
this._dispatchedTargets.set(targetKey, resolvedTargetClientId);
|
|
451
|
+
this._ownedRequests.set(requestId, {
|
|
452
|
+
scoped: scopedObservation,
|
|
453
|
+
screenshotSkipped,
|
|
454
|
+
targetKey,
|
|
455
|
+
resetGeneration: this._resetGeneration,
|
|
456
|
+
dispatchedAt: Date.now(),
|
|
457
|
+
toolName,
|
|
458
|
+
step: stepNumber,
|
|
459
|
+
});
|
|
355
460
|
|
|
356
461
|
pendingInteractions.register(requestId, {
|
|
357
462
|
conversationId,
|
|
@@ -375,7 +480,7 @@ export class HostCuProxy {
|
|
|
375
480
|
requestId,
|
|
376
481
|
conversationId,
|
|
377
482
|
toolName,
|
|
378
|
-
input,
|
|
483
|
+
input: dispatchInput,
|
|
379
484
|
stepNumber,
|
|
380
485
|
reasoning,
|
|
381
486
|
...(resolvedTargetClientId != null
|
|
@@ -403,7 +508,8 @@ export class HostCuProxy {
|
|
|
403
508
|
requestId: string,
|
|
404
509
|
observation: CuObservationResult,
|
|
405
510
|
): ToolExecutionResult | undefined {
|
|
406
|
-
const
|
|
511
|
+
const owned = this._ownedRequests.get(requestId);
|
|
512
|
+
const scopedObservation = owned?.scoped ?? false;
|
|
407
513
|
this._ownedRequests.delete(requestId);
|
|
408
514
|
const interaction = pendingInteractions.resolve(requestId, "answered");
|
|
409
515
|
if (!interaction?.rpcResolve) {
|
|
@@ -411,9 +517,33 @@ export class HostCuProxy {
|
|
|
411
517
|
return undefined;
|
|
412
518
|
}
|
|
413
519
|
|
|
520
|
+
// Label the line from what this request was dispatched with, never from
|
|
521
|
+
// current proxy state. One model response can dispatch several CU tools,
|
|
522
|
+
// and the agent loop runs them concurrently, so a later call can advance
|
|
523
|
+
// the history and the step count before an earlier observation lands.
|
|
524
|
+
// Reading them here would file each measurement under whichever tool was
|
|
525
|
+
// dispatched last, and would mislabel computer_use_point_at, which never
|
|
526
|
+
// records an action at all.
|
|
527
|
+
if (owned) {
|
|
528
|
+
log.info(
|
|
529
|
+
{
|
|
530
|
+
requestId,
|
|
531
|
+
toolName: owned.toolName,
|
|
532
|
+
step: owned.step,
|
|
533
|
+
roundTripMs: Date.now() - owned.dispatchedAt,
|
|
534
|
+
...(observation.timings ? { helper: observation.timings } : {}),
|
|
535
|
+
},
|
|
536
|
+
"Host CU step timings",
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
|
|
414
540
|
// A targeted snapshot has no comparable action/diff baseline; neither it
|
|
415
541
|
// nor the first desktop observation after it can imply "no visible effect".
|
|
416
|
-
|
|
542
|
+
// A response dispatched before the last reset belongs to a finished run,
|
|
543
|
+
// so it must not change any state the new run has started building.
|
|
544
|
+
const fromCurrentRun =
|
|
545
|
+
owned === undefined || owned.resetGeneration === this._resetGeneration;
|
|
546
|
+
if (scopedObservation && fromCurrentRun) {
|
|
417
547
|
this._previousAXTree = undefined;
|
|
418
548
|
this._consecutiveUnchangedSteps = 0;
|
|
419
549
|
}
|
|
@@ -421,10 +551,24 @@ export class HostCuProxy {
|
|
|
421
551
|
const comparableObservation = scopedObservation
|
|
422
552
|
? { ...observation, axDiff: undefined, secondaryWindows: undefined }
|
|
423
553
|
: observation;
|
|
424
|
-
|
|
554
|
+
// Pointing observes nothing, so its response leaves the screen state alone.
|
|
555
|
+
if (
|
|
556
|
+
fromCurrentRun &&
|
|
557
|
+
!scopedObservation &&
|
|
558
|
+
owned?.toolName !== POINT_AT_PROXY_TOOL
|
|
559
|
+
) {
|
|
425
560
|
this.updateStateFromObservation(comparableObservation);
|
|
561
|
+
// A desktop has had its first look only once pixels from it arrived,
|
|
562
|
+
// so a failed capture leaves the next request asking again.
|
|
563
|
+
if (owned && observation.screenshot) {
|
|
564
|
+
this._observedTargets.add(owned.targetKey);
|
|
565
|
+
}
|
|
426
566
|
}
|
|
427
|
-
const result = this.formatObservation(
|
|
567
|
+
const result = this.formatObservation(
|
|
568
|
+
comparableObservation,
|
|
569
|
+
prevAXTree,
|
|
570
|
+
owned?.screenshotSkipped ?? false,
|
|
571
|
+
);
|
|
428
572
|
interaction.rpcResolve(result);
|
|
429
573
|
return result;
|
|
430
574
|
}
|
|
@@ -454,12 +598,65 @@ export class HostCuProxy {
|
|
|
454
598
|
}
|
|
455
599
|
}
|
|
456
600
|
|
|
601
|
+
/**
|
|
602
|
+
* Finish the task: tell every desktop this task drove that it is over, then
|
|
603
|
+
* reset. The notice rides `host_cu_cancel` with a fresh request ID, which
|
|
604
|
+
* matches nothing in flight; the helper treats any cancel as the run
|
|
605
|
+
* stopping and puts the pointer back where the user left it, instead of
|
|
606
|
+
* waiting out its idle fallback.
|
|
607
|
+
*/
|
|
608
|
+
endTask(conversationId: string): void {
|
|
609
|
+
for (const targetClientId of this._dispatchedTargets.values()) {
|
|
610
|
+
try {
|
|
611
|
+
broadcastMessage(
|
|
612
|
+
{
|
|
613
|
+
type: "host_cu_cancel",
|
|
614
|
+
requestId: uuid(),
|
|
615
|
+
conversationId,
|
|
616
|
+
...(targetClientId != null ? { targetClientId } : {}),
|
|
617
|
+
},
|
|
618
|
+
conversationId,
|
|
619
|
+
{ targetClientId },
|
|
620
|
+
);
|
|
621
|
+
} catch {
|
|
622
|
+
// Best-effort: the helper still returns the pointer after its idle delay.
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
this.reset();
|
|
626
|
+
}
|
|
627
|
+
|
|
457
628
|
/** Reset all CU state. Called on terminal tools (computer_use_done, etc.). */
|
|
458
629
|
reset(): void {
|
|
630
|
+
this._dispatchedTargets.clear();
|
|
459
631
|
this._stepCount = 0;
|
|
460
632
|
this._previousAXTree = undefined;
|
|
461
633
|
this._consecutiveUnchangedSteps = 0;
|
|
462
634
|
this._actionHistory = [];
|
|
635
|
+
this._observedTargets.clear();
|
|
636
|
+
this._resetGeneration++;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Whether the request about to be dispatched should carry a screenshot. The
|
|
641
|
+
* accessibility tree comes back every step. Pixels come back after every
|
|
642
|
+
* action, so the model sees what its action did, on the first look since
|
|
643
|
+
* the last reset, for a window- or display-scoped capture, and when the
|
|
644
|
+
* model asks for them. Only a plain observation leaves whether the tree is
|
|
645
|
+
* enough to the model.
|
|
646
|
+
*/
|
|
647
|
+
private shouldAttachScreenshot(
|
|
648
|
+
toolName: string,
|
|
649
|
+
input: Record<string, unknown>,
|
|
650
|
+
targetKey: string,
|
|
651
|
+
): boolean {
|
|
652
|
+
if (toolName !== "computer_use_observe") {
|
|
653
|
+
return true;
|
|
654
|
+
}
|
|
655
|
+
return (
|
|
656
|
+
!this._observedTargets.has(targetKey) ||
|
|
657
|
+
hasCaptureTarget(input) ||
|
|
658
|
+
input.include_screenshot === true
|
|
659
|
+
);
|
|
463
660
|
}
|
|
464
661
|
|
|
465
662
|
// ---------------------------------------------------------------------------
|
|
@@ -474,6 +671,7 @@ export class HostCuProxy {
|
|
|
474
671
|
formatObservation(
|
|
475
672
|
obs: CuObservationResult,
|
|
476
673
|
previousAXTree?: string,
|
|
674
|
+
screenshotSkipped = false,
|
|
477
675
|
): ToolExecutionResult {
|
|
478
676
|
const prevTree = previousAXTree;
|
|
479
677
|
const parts: string[] = [];
|
|
@@ -552,6 +750,15 @@ export class HostCuProxy {
|
|
|
552
750
|
parts.push(...screenshotMeta);
|
|
553
751
|
}
|
|
554
752
|
|
|
753
|
+
// Only a deliberate omission is announced, and only beside a tree the line
|
|
754
|
+
// can point at. A step that asked for pixels and got none is a capture
|
|
755
|
+
// failure, which this line must not disguise. A refused or failed step
|
|
756
|
+
// still carries the line, since that is where asking for pixels helps most.
|
|
757
|
+
const isError = obs.executionError != null;
|
|
758
|
+
if (screenshotSkipped && !obs.screenshot && obs.axTree) {
|
|
759
|
+
parts.push("", SCREENSHOT_OMITTED_MESSAGE);
|
|
760
|
+
}
|
|
761
|
+
|
|
555
762
|
const content = parts.join("\n").trim() || "Action executed";
|
|
556
763
|
|
|
557
764
|
const contentBlocks: ContentBlock[] = [];
|
|
@@ -566,8 +773,6 @@ export class HostCuProxy {
|
|
|
566
773
|
});
|
|
567
774
|
}
|
|
568
775
|
|
|
569
|
-
const isError = obs.executionError != null;
|
|
570
|
-
|
|
571
776
|
return {
|
|
572
777
|
content: isError
|
|
573
778
|
? `Action failed: ${obs.executionError}\n\n${content}`
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
broadcastMessage,
|
|
7
7
|
} from "../runtime/assistant-event-hub.js";
|
|
8
8
|
import {
|
|
9
|
-
ambiguousSameUserError,
|
|
10
9
|
enforceSameActorOrErrorResult,
|
|
11
|
-
|
|
10
|
+
pickMostRecentSameUserClient,
|
|
12
11
|
snapshotHostProxyActorPrincipalId,
|
|
12
|
+
unavailableSameUserClientError,
|
|
13
13
|
} from "../runtime/auth/same-actor.js";
|
|
14
14
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
15
15
|
import { readAudioBase64 } from "../tools/shared/filesystem/audio-read.js";
|
|
@@ -102,19 +102,17 @@ export class HostFileProxy {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
} else {
|
|
105
|
-
|
|
106
|
-
// (multi-machine) cases so a single targeted-style request cannot
|
|
107
|
-
// fan out across the user's machines.
|
|
108
|
-
const resolved = pickSameUserAutoResolve({
|
|
105
|
+
resolvedTargetClientId = pickMostRecentSameUserClient({
|
|
109
106
|
hub: assistantEventHub,
|
|
110
107
|
capability: "host_file",
|
|
111
108
|
sourceActorPrincipalId,
|
|
112
109
|
});
|
|
113
|
-
if (
|
|
114
|
-
|
|
110
|
+
if (
|
|
111
|
+
resolvedTargetClientId === undefined &&
|
|
112
|
+
sourceActorPrincipalId !== undefined
|
|
113
|
+
) {
|
|
114
|
+
return Promise.resolve(unavailableSameUserClientError("host_file"));
|
|
115
115
|
}
|
|
116
|
-
resolvedTargetClientId =
|
|
117
|
-
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
// Same-user check: targeted host_file requests must be bound to the same
|
|
@@ -105,12 +105,13 @@ export const HOST_PROXY_SKILL_PREACTIVATIONS: ReadonlyArray<{
|
|
|
105
105
|
*/
|
|
106
106
|
/**
|
|
107
107
|
* Capabilities a client asks for on its connection rather than getting from
|
|
108
|
-
* what it is.
|
|
108
|
+
* what it is. Each rides the host_cu transport and is answered only by a
|
|
109
109
|
* macOS build new enough to send the header (`events-routes.ts`), so the
|
|
110
110
|
* interface alone cannot say whether one is really there.
|
|
111
111
|
*/
|
|
112
112
|
const NEGOTIATED_CAPABILITIES: ReadonlySet<HostProxyCapability> = new Set([
|
|
113
113
|
"host_cu_window_capture",
|
|
114
|
+
"host_cu_sequence",
|
|
114
115
|
"host_cu_annotate",
|
|
115
116
|
]);
|
|
116
117
|
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
broadcastMessage,
|
|
11
11
|
} from "../runtime/assistant-event-hub.js";
|
|
12
12
|
import {
|
|
13
|
-
ambiguousSameUserError,
|
|
14
13
|
enforceSameActorOrErrorResult,
|
|
15
|
-
|
|
14
|
+
pickMostRecentSameUserClient,
|
|
16
15
|
snapshotHostProxyActorPrincipalId,
|
|
16
|
+
unavailableSameUserClientError,
|
|
17
17
|
} from "../runtime/auth/same-actor.js";
|
|
18
18
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
19
19
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
@@ -162,19 +162,17 @@ export class HostTransferProxy {
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
} else {
|
|
165
|
-
|
|
166
|
-
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
167
|
-
// fan out across the user's machines.
|
|
168
|
-
const resolved = pickSameUserAutoResolve({
|
|
165
|
+
resolvedTargetClientId = pickMostRecentSameUserClient({
|
|
169
166
|
hub: assistantEventHub,
|
|
170
167
|
capability: "host_file",
|
|
171
168
|
sourceActorPrincipalId,
|
|
172
169
|
});
|
|
173
|
-
if (
|
|
174
|
-
|
|
170
|
+
if (
|
|
171
|
+
resolvedTargetClientId === undefined &&
|
|
172
|
+
sourceActorPrincipalId !== undefined
|
|
173
|
+
) {
|
|
174
|
+
return Promise.resolve(unavailableSameUserClientError("host_file"));
|
|
175
175
|
}
|
|
176
|
-
resolvedTargetClientId =
|
|
177
|
-
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
178
176
|
}
|
|
179
177
|
|
|
180
178
|
if (resolvedTargetClientId != null) {
|
|
@@ -364,19 +362,17 @@ export class HostTransferProxy {
|
|
|
364
362
|
});
|
|
365
363
|
}
|
|
366
364
|
} else {
|
|
367
|
-
|
|
368
|
-
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
369
|
-
// fan out across the user's machines.
|
|
370
|
-
const resolved = pickSameUserAutoResolve({
|
|
365
|
+
resolvedTargetClientId = pickMostRecentSameUserClient({
|
|
371
366
|
hub: assistantEventHub,
|
|
372
367
|
capability: "host_file",
|
|
373
368
|
sourceActorPrincipalId,
|
|
374
369
|
});
|
|
375
|
-
if (
|
|
376
|
-
|
|
370
|
+
if (
|
|
371
|
+
resolvedTargetClientId === undefined &&
|
|
372
|
+
sourceActorPrincipalId !== undefined
|
|
373
|
+
) {
|
|
374
|
+
return Promise.resolve(unavailableSameUserClientError("host_file"));
|
|
377
375
|
}
|
|
378
|
-
resolvedTargetClientId =
|
|
379
|
-
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
380
376
|
}
|
|
381
377
|
|
|
382
378
|
if (resolvedTargetClientId != null) {
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -71,7 +71,6 @@ import { ensureCompleteCustomProfiles } from "../workspace/custom-profile-ensure
|
|
|
71
71
|
import { ensureDefaultProvider } from "../workspace/default-provider-ensure.js";
|
|
72
72
|
import { WORKSPACE_MIGRATIONS } from "../workspace/migrations/registry.js";
|
|
73
73
|
import { runWorkspaceMigrations } from "../workspace/migrations/runner.js";
|
|
74
|
-
import { startAppSourceWatcher } from "./app-source-watcher.js";
|
|
75
74
|
import { startConfigWatcher } from "./config-watcher.js";
|
|
76
75
|
import { startConversationEvictor } from "./conversation-evictor.js";
|
|
77
76
|
import { writePid } from "./daemon-control.js";
|
|
@@ -706,10 +705,6 @@ export async function runDaemon(): Promise<void> {
|
|
|
706
705
|
// config, and broadcast the relevant resource-changed events to clients.
|
|
707
706
|
startConfigWatcher();
|
|
708
707
|
|
|
709
|
-
// Watch app source directories so edits recompile + refresh surfaces across
|
|
710
|
-
// all conversations.
|
|
711
|
-
startAppSourceWatcher();
|
|
712
|
-
|
|
713
708
|
// Start the CLI IPC server. Throws on EADDRINUSE to abort startup when another
|
|
714
709
|
// daemon already holds the socket, so this process never runs background jobs
|
|
715
710
|
// against the shared database as an unmanageable duplicate.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared MCP reload business logic.
|
|
3
3
|
*
|
|
4
|
-
* Called by the ConfigWatcher when
|
|
4
|
+
* Called by the ConfigWatcher when mcp.json changes or a reload signal
|
|
5
5
|
* file is detected, so the daemon automatically reconnects MCP servers.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { invalidateConfigCache } from "../config/loader.js";
|
|
9
9
|
import {
|
|
10
10
|
buildEffectiveMcpConfig,
|
|
11
11
|
pluginMcpServersChangedSinceLastBuild,
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { getMcpServerManager } from "../mcp/manager.js";
|
|
14
14
|
import { migrateLegacyMcpHeaders } from "../mcp/mcp-header-store.js";
|
|
15
15
|
import { signalMcpReloaded } from "../mcp/reload-signal.js";
|
|
16
|
+
import { loadWorkspaceMcpConfig } from "../mcp/workspace-mcp-config.js";
|
|
16
17
|
import { createMcpToolsFromServer } from "../tools/mcp/mcp-tool-factory.js";
|
|
17
18
|
import { registerMcpTools, unregisterAllMcpTools } from "../tools/registry.js";
|
|
18
19
|
import { getLogger } from "../util/logger.js";
|
|
@@ -95,16 +96,15 @@ async function doReload(): Promise<McpReloadResult> {
|
|
|
95
96
|
// If the config is broken we abort early, preserving the current
|
|
96
97
|
// working MCP setup instead of leaving zero servers.
|
|
97
98
|
invalidateConfigCache();
|
|
98
|
-
const config = getConfig();
|
|
99
99
|
|
|
100
100
|
// 2. Stop existing MCP servers + unregister their tools
|
|
101
101
|
await manager.stop();
|
|
102
102
|
unregisterAllMcpTools();
|
|
103
103
|
|
|
104
104
|
// Plugins are re-read here too: installing or removing one changes the
|
|
105
|
-
// server set exactly like editing
|
|
105
|
+
// server set exactly like editing mcp.json does, and both arrive
|
|
106
106
|
// through this same reload.
|
|
107
|
-
const mcpConfig = buildEffectiveMcpConfig(
|
|
107
|
+
const mcpConfig = buildEffectiveMcpConfig(loadWorkspaceMcpConfig());
|
|
108
108
|
const serverIds = Object.keys(mcpConfig.servers);
|
|
109
109
|
|
|
110
110
|
// 3. Restart MCP servers
|
|
@@ -13,6 +13,7 @@ export const SYNC_TAGS = {
|
|
|
13
13
|
assistantConfig: "assistant:self:config",
|
|
14
14
|
assistantSounds: "assistant:self:sounds",
|
|
15
15
|
assistantSchedules: "assistant:self:schedules",
|
|
16
|
+
assistantDesktop: "assistant:self:desktop",
|
|
16
17
|
assistantTheme: "assistant:self:theme",
|
|
17
18
|
appsList: "apps:list",
|
|
18
19
|
documentsList: "documents:list",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Tools run commands in their own process group (`detached: true`) and, on
|
|
5
5
|
* timeout/abort, group-kill with `process.kill(-pgid, SIGKILL)` (the bash and
|
|
6
|
-
* host_bash tools, the skill sandbox runner
|
|
6
|
+
* host_bash tools, and the skill sandbox runner). The
|
|
7
7
|
* immediate child is reaped by Bun/libuv, but its descendants — e.g. git's
|
|
8
8
|
* transport helpers or a skill runner's `bun` process — were never spawned by
|
|
9
9
|
* the daemon, so when the group dies they reparent to PID 1. When the daemon
|
|
@@ -63,7 +63,7 @@ export async function initializeProvidersAndTools(
|
|
|
63
63
|
// Start MCP servers — workspace-configured and plugin-declared alike —
|
|
64
64
|
// and register their tools. Shared with the schedule worker, which hosts
|
|
65
65
|
// agent turns in its own process and so needs its own connections.
|
|
66
|
-
await startConfiguredMcpServers(
|
|
66
|
+
await startConfiguredMcpServers();
|
|
67
67
|
|
|
68
68
|
log.info("Daemon startup: providers and tools initialized");
|
|
69
69
|
}
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
unwrapExternalContentForDisplay,
|
|
29
29
|
wrapUntrustedContent,
|
|
30
30
|
} from "../security/untrusted-content.js";
|
|
31
|
+
import { safeStringSlice } from "../util/unicode.js";
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Slack-style emoji names render in colon form. Anything else (a unicode
|
|
@@ -53,7 +54,7 @@ function snippetOf(text: string): string {
|
|
|
53
54
|
if (flat.length <= TARGET_SNIPPET_MAX_CHARS) {
|
|
54
55
|
return flat;
|
|
55
56
|
}
|
|
56
|
-
return `${flat
|
|
57
|
+
return `${safeStringSlice(flat, 0, TARGET_SNIPPET_MAX_CHARS)}...`;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
|
@@ -24,11 +24,7 @@ import { browserManager } from "../tools/browser/browser-manager.js";
|
|
|
24
24
|
import { getLogger } from "../util/logger.js";
|
|
25
25
|
import { APP_VERSION } from "../version.js";
|
|
26
26
|
import { getEnrichmentService } from "../workspace/commit-message-enrichment-service.js";
|
|
27
|
-
import {
|
|
28
|
-
commitAllPendingWorkspaceChanges,
|
|
29
|
-
stopWorkspaceHeartbeatService,
|
|
30
|
-
} from "../workspace/heartbeat-service.js";
|
|
31
|
-
import { stopAppSourceWatcher } from "./app-source-watcher.js";
|
|
27
|
+
import { commitAllPendingWorkspaceChanges } from "../workspace/heartbeat-service.js";
|
|
32
28
|
import { stopConfigWatcher } from "./config-watcher.js";
|
|
33
29
|
import { stopConversationEvictor } from "./conversation-evictor.js";
|
|
34
30
|
import { stopConversations } from "./conversation-store.js";
|
|
@@ -98,9 +94,6 @@ async function shutdown(): Promise<void> {
|
|
|
98
94
|
}, 30_000);
|
|
99
95
|
forceTimer.unref();
|
|
100
96
|
|
|
101
|
-
// Workspace git heartbeat timer lives in the monitor process. This
|
|
102
|
-
// in-process stop is a no-op unless the singleton was started here.
|
|
103
|
-
await stopWorkspaceHeartbeatService();
|
|
104
97
|
await stopHeartbeatService();
|
|
105
98
|
|
|
106
99
|
// Stop the periodic consent-cache refresh (a daemon-owned interval).
|
|
@@ -134,7 +127,6 @@ async function shutdown(): Promise<void> {
|
|
|
134
127
|
disposeAcpSessionManager();
|
|
135
128
|
stopConversationEvictor();
|
|
136
129
|
stopConfigWatcher();
|
|
137
|
-
stopAppSourceWatcher();
|
|
138
130
|
stopCliIpcServer();
|
|
139
131
|
stopConversations();
|
|
140
132
|
await stopCes();
|