@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +0 -4
- package/ARCHITECTURE.md +12 -11
- package/docs/architecture/turn-actor.md +8 -15
- package/docs/guardian-request-flow.md +0 -16
- package/openapi.yaml +49 -291
- package/package.json +1 -1
- package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
- package/src/__tests__/app-compiler.test.ts +0 -6
- package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
- package/src/__tests__/app-dir-path-guard.test.ts +3 -1
- package/src/__tests__/app-source-watcher.test.ts +218 -0
- package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
- package/src/__tests__/computer-use-tools.test.ts +5 -17
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +29 -28
- package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
- package/src/__tests__/config-watcher.test.ts +8 -23
- package/src/__tests__/connection-model-compat.test.ts +2 -2
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +0 -26
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
- package/src/__tests__/conversation-queue.test.ts +207 -48
- package/src/__tests__/conversation-retry-discard.test.ts +1 -54
- package/src/__tests__/conversation-skill-tools.test.ts +0 -27
- package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
- package/src/__tests__/conversation-title-service.test.ts +10 -14
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
- package/src/__tests__/credential-record-retire.test.ts +1 -171
- package/src/__tests__/credential-routes.test.ts +3 -212
- package/src/__tests__/credential-security-invariants.test.ts +2 -4
- package/src/__tests__/cu-unified-flow.test.ts +2 -8
- package/src/__tests__/document-sync-tags.test.ts +0 -25
- package/src/__tests__/drain-kick-guard.test.ts +2 -0
- package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/host-bash-proxy.test.ts +45 -26
- package/src/__tests__/host-browser-proxy.test.ts +17 -6
- package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
- package/src/__tests__/host-file-proxy.test.ts +23 -11
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
- package/src/__tests__/llm-catalog-parity.test.ts +0 -25
- package/src/__tests__/mcp-auth-routes.test.ts +9 -6
- package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
- package/src/__tests__/mcp-health-check.test.ts +11 -8
- package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
- package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
- package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
- package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
- package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
- package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +548 -355
- package/src/__tests__/model-intents.test.ts +0 -3
- package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/platform-callback-registration.test.ts +16 -8
- package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
- package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
- package/src/__tests__/script-proxy-certs.test.ts +0 -35
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/speaker-identification.test.ts +56 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
- package/src/__tests__/subagent-tools.test.ts +2 -3
- package/src/__tests__/telephony-tts-guard.test.ts +3 -38
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
- package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
- package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
- package/src/__tests__/workspace-git-service.test.ts +0 -26
- package/src/acp/__tests__/agent-process.test.ts +4 -258
- package/src/acp/__tests__/auth-required.test.ts +0 -96
- package/src/acp/__tests__/client-handler.test.ts +2 -90
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
- package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
- package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
- package/src/acp/__tests__/session-manager.test.ts +4 -895
- package/src/acp/agent-process.test.ts +1 -4
- package/src/acp/agent-process.ts +9 -94
- package/src/acp/auth-required.ts +1 -50
- package/src/acp/auto-install.test.ts +7 -9
- package/src/acp/client-handler.ts +3 -16
- package/src/acp/resolve-agent.test.ts +6 -220
- package/src/acp/resolve-agent.ts +23 -88
- package/src/acp/session-manager.test.ts +3 -196
- package/src/acp/session-manager.ts +18 -441
- package/src/acp/types.ts +5 -50
- package/src/api/events/app-files-changed.ts +3 -4
- package/src/api/events/notification-intent.ts +0 -2
- package/src/api/index.ts +0 -6
- package/src/apps/app-store.ts +1 -1
- package/src/bundler/app-compiler.ts +0 -15
- package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
- package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
- package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
- package/src/calls/call-constants.ts +4 -24
- package/src/calls/call-controller.ts +199 -499
- package/src/calls/call-transport.ts +0 -16
- package/src/calls/media-stream-output.ts +0 -32
- package/src/calls/media-stream-server.ts +30 -82
- package/src/calls/media-stream-stt-session.ts +0 -15
- package/src/calls/resolve-call-tts-provider.ts +2 -33
- package/src/calls/speaker-identification.ts +233 -0
- package/src/calls/tts-call-strategy.ts +5 -9
- package/src/calls/types.ts +0 -2
- package/src/calls/voice-control-protocol.ts +21 -53
- package/src/calls/voice-session-bridge.ts +46 -59
- package/src/calls/voice-triage-escalate.ts +56 -175
- package/src/cli/commands/apps.help.ts +13 -67
- package/src/cli/commands/apps.ts +0 -183
- package/src/cli/commands/bash.help.ts +13 -8
- package/src/cli/commands/bash.ts +25 -7
- package/src/cli/commands/channels/index.help.ts +2 -70
- package/src/cli/commands/channels/index.ts +3 -16
- package/src/cli/commands/credentials.help.ts +2 -6
- package/src/cli/commands/credentials.ts +2 -2
- package/src/cli/commands/mcp.help.ts +8 -8
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/roadmap.help.ts +1 -5
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +90 -103
- package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
- package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
- package/src/config/__tests__/platform-rehydration.test.ts +9 -99
- package/src/config/acp-defaults.test.ts +3 -13
- package/src/config/acp-defaults.ts +6 -23
- package/src/config/acp-schema.ts +2 -30
- package/src/config/bundled-skills/acp/SKILL.md +14 -22
- package/src/config/bundled-skills/acp/TOOLS.json +1 -5
- package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/schedule/SKILL.md +4 -3
- package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
- package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/env.ts +2 -2
- package/src/config/feature-flag-registry.json +12 -24
- package/src/config/loader.ts +0 -1
- package/src/config/memory-v3-gate.test.ts +0 -31
- package/src/config/memory-v3-gate.ts +16 -20
- package/src/config/platform-rehydration.ts +27 -11
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
- package/src/config/schemas/calls.ts +28 -1
- package/src/config/schemas/live-voice.ts +173 -1
- package/src/config/schemas/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +0 -10
- package/src/config/schemas/services.ts +0 -8
- package/src/config/schemas/skills.ts +14 -0
- package/src/credential-execution/process-manager.test.ts +19 -18
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
- package/src/daemon/app-source-watcher.ts +218 -0
- package/src/daemon/config-watcher.ts +194 -13
- package/src/daemon/conversation-process.ts +64 -35
- package/src/daemon/conversation-skill-tools.ts +31 -13
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +8 -10
- package/src/daemon/conversation-tool-setup.ts +43 -37
- package/src/daemon/conversation.ts +3 -0
- package/src/daemon/host-bash-proxy.ts +12 -8
- package/src/daemon/host-browser-proxy.ts +1 -15
- package/src/daemon/host-file-proxy.ts +10 -8
- package/src/daemon/host-transfer-proxy.ts +18 -14
- package/src/daemon/lifecycle.ts +5 -0
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/shutdown-handlers.ts +9 -1
- package/src/daemon/skill-memory-refresh.ts +0 -64
- package/src/daemon/tool-side-effects.ts +18 -7
- package/src/home/__tests__/feed-writer.test.ts +0 -22
- package/src/home/feed-writer.ts +2 -11
- package/src/hooks/types.ts +0 -33
- package/src/inbound/platform-callback-registration.ts +5 -4
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
- package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
- package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
- package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
- package/src/live-voice/live-voice-session.ts +693 -213
- package/src/{calls → live-voice}/progress-narration.ts +2 -2
- package/src/live-voice/protocol.ts +2 -0
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +45 -29
- package/src/mcp/startup.ts +4 -8
- package/src/messaging/provider.ts +3 -10
- package/src/messaging/providers/callback-routing.ts +0 -18
- package/src/messaging/providers/channel-transport.ts +0 -56
- package/src/messaging/providers/discord/transport.ts +0 -17
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
- package/src/messaging/providers/slack/adapter.ts +44 -7
- package/src/messaging/providers/slack/transport.ts +0 -16
- package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
- package/src/messaging/providers/telegram-bot/client.ts +26 -0
- package/src/messaging/providers/telegram-bot/transport.ts +0 -20
- package/src/messaging/providers/whatsapp/adapter.ts +48 -1
- package/src/messaging/providers/whatsapp/client.ts +29 -0
- package/src/messaging/providers/whatsapp/transport.ts +0 -18
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
- package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
- package/src/notifications/adapters/macos.ts +0 -3
- package/src/notifications/assistant-reply-producer.ts +3 -8
- package/src/notifications/conversation-pairing.ts +16 -36
- package/src/notifications/delivered-post-record.ts +1 -11
- package/src/notifications/guardian-feed-projection.ts +5 -125
- package/src/notifications/home-feed-side-effect.ts +7 -55
- package/src/notifications/schedule-result-producer.ts +22 -66
- package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
- package/src/oauth/byo-connection.test.ts +0 -45
- package/src/oauth/byo-connection.ts +6 -36
- package/src/oauth/connection-resolver.test.ts +0 -73
- package/src/oauth/connection-resolver.ts +2 -95
- package/src/oauth/seed-providers.ts +0 -165
- package/src/outbound-proxy/certs.ts +5 -3
- package/src/permissions/checker.test.ts +6 -11
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +63 -71
- package/src/persistence/conversation-lineage.ts +4 -12
- package/src/persistence/conversation-title-service.ts +26 -9
- package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
- package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
- package/src/persistence/message-reads.ts +0 -30
- package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
- package/src/persistence/schema/memory-core.ts +0 -5
- package/src/platform/client.test.ts +2 -4
- package/src/platform/client.ts +10 -2
- package/src/plugin-api/constants.ts +0 -2
- package/src/plugin-api/index.ts +0 -1
- package/src/plugin-api/types.ts +0 -2
- package/src/plugins/defaults/index.ts +0 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
- package/src/plugins/defaults/memory/hooks/init.ts +0 -10
- package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
- package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
- package/src/plugins/defaults/memory/startup.ts +1 -6
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
- package/src/plugins/defaults/memory/worker.ts +0 -6
- package/src/plugins/mcp-servers.ts +75 -15
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/gemini/client.ts +23 -9
- package/src/providers/inference/auth.ts +3 -2
- package/src/providers/inference/connection-availability.ts +8 -27
- package/src/providers/inference/resolve-auth.ts +4 -22
- package/src/providers/model-catalog.ts +0 -34
- package/src/providers/model-intents.ts +5 -10
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
- package/src/providers/openai/chat-completions-provider.ts +78 -192
- package/src/providers/openai/codex-models.ts +4 -0
- package/src/runtime/AGENTS.md +0 -2
- package/src/runtime/auth/same-actor.ts +3 -38
- package/src/runtime/http-server.ts +151 -160
- package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
- package/src/runtime/routes/acp-routes.test.ts +0 -15
- package/src/runtime/routes/acp-routes.ts +9 -72
- package/src/runtime/routes/app-management-routes.ts +0 -73
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/conversation-list-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +0 -40
- package/src/runtime/routes/credential-routes.ts +10 -19
- package/src/runtime/routes/debug-bash-routes.ts +173 -0
- package/src/runtime/routes/diagnostics-routes.ts +3 -55
- package/src/runtime/routes/index.ts +2 -4
- package/src/runtime/routes/log-export-routes.ts +0 -2
- package/src/runtime/routes/mcp-auth-routes.ts +47 -39
- package/src/runtime/routes/migration-routes.ts +20 -6
- package/src/runtime/routes/platform-routes.ts +15 -18
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
- package/src/runtime/services/conversation-serializer.ts +3 -16
- package/src/runtime/sync/resource-sync-events.ts +1 -2
- package/src/schedule/worker.ts +1 -1
- package/src/security/ces-rpc-record-backend.ts +0 -7
- package/src/subagent/consult-context.ts +25 -12
- package/src/tools/acp/list-agents.test.ts +1 -3
- package/src/tools/acp/spawn.test.ts +11 -146
- package/src/tools/acp/spawn.ts +3 -21
- package/src/tools/acp/status.ts +3 -40
- package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
- package/src/tools/capability-offer.test.ts +2 -22
- package/src/tools/capability-offer.ts +1 -16
- package/src/tools/computer-use/definitions.ts +2 -4
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
- package/src/tools/credentials/metadata-store.ts +0 -100
- package/src/tools/host-filesystem/edit.test.ts +1 -2
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +1 -2
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +1 -2
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +1 -2
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +0 -16
- package/src/tools/host-terminal/host-shell.ts +20 -4
- package/src/tools/policy-context.ts +7 -6
- package/src/tools/subagent/spawn.ts +8 -5
- package/src/tools/watch/watch-retro-report.ts +8 -0
- package/src/util/__tests__/language-subtag.test.ts +1 -23
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/language-subtag.ts +0 -16
- package/src/util/platform.ts +0 -8
- package/src/workspace/git-service.ts +54 -5
- package/src/workspace/migrations/registry.ts +0 -6
- package/scripts/smoke-desktop-window-theme.ts +0 -186
- package/src/__tests__/git-porcelain.test.ts +0 -47
- package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
- package/src/__tests__/resolve-app.test.ts +0 -135
- package/src/__tests__/service-account-token.test.ts +0 -247
- package/src/__tests__/source-fingerprint.test.ts +0 -184
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
- package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
- package/src/acp/model-config.test.ts +0 -166
- package/src/acp/model-config.ts +0 -138
- package/src/api/events/acp-session-model-update.test.ts +0 -88
- package/src/api/events/acp-session-model-update.ts +0 -46
- package/src/apps/resolve-app.ts +0 -81
- package/src/apps/source-fingerprint.ts +0 -266
- package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
- package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
- package/src/calls/barge-in-guard.ts +0 -118
- package/src/calls/voice-leg-coordinator.ts +0 -189
- package/src/calls/voice-progress-cadence.ts +0 -423
- package/src/cli/commands/__tests__/apps.test.ts +0 -245
- package/src/cli/commands/__tests__/bash.test.ts +0 -53
- package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
- package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
- package/src/cli/commands/channels/send.ts +0 -128
- package/src/config/__tests__/platform-identity.test.ts +0 -255
- package/src/config/acp-agent-write.ts +0 -43
- package/src/config/acp-schema.test.ts +0 -81
- package/src/config/platform-identity.ts +0 -201
- package/src/config/schemas/__tests__/voice.test.ts +0 -148
- package/src/config/schemas/voice.ts +0 -150
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
- package/src/daemon/app-change-notify.ts +0 -45
- package/src/desktop/__tests__/fake-desktop.ts +0 -119
- package/src/desktop/desktop-chrome-policy.test.ts +0 -71
- package/src/desktop/desktop-chrome-policy.ts +0 -42
- package/src/desktop/desktop-dependencies.test.ts +0 -102
- package/src/desktop/desktop-dependencies.ts +0 -306
- package/src/desktop/desktop-feature.test.ts +0 -18
- package/src/desktop/desktop-feature.ts +0 -19
- package/src/desktop/desktop-panel-config.test.ts +0 -135
- package/src/desktop/desktop-panel-config.ts +0 -149
- package/src/desktop/desktop-session-manager.test.ts +0 -627
- package/src/desktop/desktop-session-manager.ts +0 -814
- package/src/desktop/desktop-stream-bridge.test.ts +0 -395
- package/src/desktop/desktop-stream-bridge.ts +0 -214
- package/src/desktop/desktop-wallpaper.test.ts +0 -191
- package/src/desktop/desktop-wallpaper.ts +0 -113
- package/src/desktop/desktop-window-theme.ts +0 -170
- package/src/i18n/AGENTS.md +0 -22
- package/src/i18n/__tests__/i18n.test.ts +0 -108
- package/src/i18n/index.ts +0 -16
- package/src/i18n/locales.ts +0 -93
- package/src/i18n/messages.ts +0 -61
- package/src/i18n/title.ts +0 -25
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
- package/src/mcp/spec-schema.ts +0 -111
- package/src/mcp/workspace-mcp-config.ts +0 -188
- package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
- package/src/persistence/conversation-title-placeholders.ts +0 -23
- package/src/persistence/message-cursor.ts +0 -78
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
- package/src/providers/gemini-thought-signature.test.ts +0 -63
- package/src/providers/gemini-thought-signature.ts +0 -44
- package/src/providers/inference/service-account-token.ts +0 -248
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
- package/src/providers/openai/google-thought-signature.ts +0 -320
- package/src/runtime/__tests__/channel-send.test.ts +0 -443
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
- package/src/runtime/channel-send.ts +0 -316
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
- package/src/runtime/routes/channel-send-routes.ts +0 -85
- package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
- package/src/runtime/routes/desktop-setup-routes.ts +0 -35
- package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
- package/src/security/ces-http-record-backend.ts +0 -120
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
- package/src/skills/workspace-skill-md-signature.ts +0 -50
- package/src/tools/acp/status.test.ts +0 -94
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
- package/src/tools/terminal/sanitized-bash.ts +0 -105
- package/src/util/ca-bundle.ts +0 -13
- package/src/workspace/git-porcelain.ts +0 -66
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
- /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { getConfig } from "../config/loader.js";
|
|
2
2
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
3
3
|
import {
|
|
4
|
+
ambiguousSameUserError,
|
|
4
5
|
enforceSameActorOrErrorResult,
|
|
5
|
-
|
|
6
|
-
unavailableSameUserClientError,
|
|
6
|
+
pickSameUserAutoResolve,
|
|
7
7
|
} from "../runtime/auth/same-actor.js";
|
|
8
8
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
9
9
|
import { formatShellOutput } from "../tools/shared/shell-output.js";
|
|
@@ -93,17 +93,21 @@ export class HostBashProxy extends HostProxyBase<
|
|
|
93
93
|
}
|
|
94
94
|
resolvedTargetClientId = input.targetClientId;
|
|
95
95
|
} else {
|
|
96
|
-
|
|
96
|
+
// Auto-resolve to the unique same-user client. Reject (rather than
|
|
97
|
+
// broadcast) when multiple same-user clients are connected so that
|
|
98
|
+
// a single targeted-style request cannot fan out across every one
|
|
99
|
+
// of the user's machines. Zero same-user matches falls through to
|
|
100
|
+
// the existing untargeted code path.
|
|
101
|
+
const resolved = pickSameUserAutoResolve({
|
|
97
102
|
hub: assistantEventHub,
|
|
98
103
|
capability: "host_bash",
|
|
99
104
|
sourceActorPrincipalId,
|
|
100
105
|
});
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
sourceActorPrincipalId !== undefined
|
|
104
|
-
) {
|
|
105
|
-
return unavailableSameUserClientError("host_bash");
|
|
106
|
+
if (resolved.kind === "ambiguous") {
|
|
107
|
+
return ambiguousSameUserError("host_bash");
|
|
106
108
|
}
|
|
109
|
+
resolvedTargetClientId =
|
|
110
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
// Targeted requests must be bound to the same authenticated user as the
|
|
@@ -5,10 +5,7 @@ import {
|
|
|
5
5
|
assistantEventHub,
|
|
6
6
|
broadcastMessage,
|
|
7
7
|
} from "../runtime/assistant-event-hub.js";
|
|
8
|
-
import {
|
|
9
|
-
enforceSameActorOrErrorResult,
|
|
10
|
-
unavailableSameUserClientError,
|
|
11
|
-
} from "../runtime/auth/same-actor.js";
|
|
8
|
+
import { enforceSameActorOrErrorResult } from "../runtime/auth/same-actor.js";
|
|
12
9
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
13
10
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
14
11
|
import { AssistantError, ErrorCode } from "../util/errors.js";
|
|
@@ -287,17 +284,6 @@ export class HostBrowserProxy {
|
|
|
287
284
|
targetClientId,
|
|
288
285
|
);
|
|
289
286
|
|
|
290
|
-
if (
|
|
291
|
-
preferredClient === undefined &&
|
|
292
|
-
sourceActorPrincipalId !== undefined &&
|
|
293
|
-
targetClientId === undefined
|
|
294
|
-
) {
|
|
295
|
-
if (isExtensionOnlyMethod(input.cdpMethod)) {
|
|
296
|
-
return Promise.resolve(extensionRequiredResult(input.cdpMethod));
|
|
297
|
-
}
|
|
298
|
-
return Promise.resolve(unavailableSameUserClientError("host_browser"));
|
|
299
|
-
}
|
|
300
|
-
|
|
301
287
|
// Same-user enforcement: when the caller's actor is known, refuse to
|
|
302
288
|
// dispatch to a client owned by a different actor. This covers the
|
|
303
289
|
// cross-client exposure case where a web/iOS turn for actor A would
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
broadcastMessage,
|
|
7
7
|
} from "../runtime/assistant-event-hub.js";
|
|
8
8
|
import {
|
|
9
|
+
ambiguousSameUserError,
|
|
9
10
|
enforceSameActorOrErrorResult,
|
|
10
|
-
|
|
11
|
+
pickSameUserAutoResolve,
|
|
11
12
|
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,17 +102,19 @@ export class HostFileProxy {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
} else {
|
|
105
|
-
|
|
105
|
+
// Auto-resolve to the unique same-user client. Reject ambiguous
|
|
106
|
+
// (multi-machine) cases so a single targeted-style request cannot
|
|
107
|
+
// fan out across the user's machines.
|
|
108
|
+
const resolved = pickSameUserAutoResolve({
|
|
106
109
|
hub: assistantEventHub,
|
|
107
110
|
capability: "host_file",
|
|
108
111
|
sourceActorPrincipalId,
|
|
109
112
|
});
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
sourceActorPrincipalId !== undefined
|
|
113
|
-
) {
|
|
114
|
-
return Promise.resolve(unavailableSameUserClientError("host_file"));
|
|
113
|
+
if (resolved.kind === "ambiguous") {
|
|
114
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
115
115
|
}
|
|
116
|
+
resolvedTargetClientId =
|
|
117
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
// Same-user check: targeted host_file requests must be bound to the same
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
broadcastMessage,
|
|
11
11
|
} from "../runtime/assistant-event-hub.js";
|
|
12
12
|
import {
|
|
13
|
+
ambiguousSameUserError,
|
|
13
14
|
enforceSameActorOrErrorResult,
|
|
14
|
-
|
|
15
|
+
pickSameUserAutoResolve,
|
|
15
16
|
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,17 +162,19 @@ export class HostTransferProxy {
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
} else {
|
|
165
|
-
|
|
165
|
+
// Auto-resolve to the unique same-user client; reject ambiguous
|
|
166
|
+
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
167
|
+
// fan out across the user's machines.
|
|
168
|
+
const resolved = pickSameUserAutoResolve({
|
|
166
169
|
hub: assistantEventHub,
|
|
167
170
|
capability: "host_file",
|
|
168
171
|
sourceActorPrincipalId,
|
|
169
172
|
});
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
-
sourceActorPrincipalId !== undefined
|
|
173
|
-
) {
|
|
174
|
-
return Promise.resolve(unavailableSameUserClientError("host_file"));
|
|
173
|
+
if (resolved.kind === "ambiguous") {
|
|
174
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
175
175
|
}
|
|
176
|
+
resolvedTargetClientId =
|
|
177
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
if (resolvedTargetClientId != null) {
|
|
@@ -362,17 +364,19 @@ export class HostTransferProxy {
|
|
|
362
364
|
});
|
|
363
365
|
}
|
|
364
366
|
} else {
|
|
365
|
-
|
|
367
|
+
// Auto-resolve to the unique same-user client; reject ambiguous
|
|
368
|
+
// (multi-machine) cases so a single targeted-style transfer cannot
|
|
369
|
+
// fan out across the user's machines.
|
|
370
|
+
const resolved = pickSameUserAutoResolve({
|
|
366
371
|
hub: assistantEventHub,
|
|
367
372
|
capability: "host_file",
|
|
368
373
|
sourceActorPrincipalId,
|
|
369
374
|
});
|
|
370
|
-
if (
|
|
371
|
-
|
|
372
|
-
sourceActorPrincipalId !== undefined
|
|
373
|
-
) {
|
|
374
|
-
return Promise.resolve(unavailableSameUserClientError("host_file"));
|
|
375
|
+
if (resolved.kind === "ambiguous") {
|
|
376
|
+
return Promise.resolve(ambiguousSameUserError("host_file"));
|
|
375
377
|
}
|
|
378
|
+
resolvedTargetClientId =
|
|
379
|
+
resolved.kind === "match" ? resolved.clientId : undefined;
|
|
376
380
|
}
|
|
377
381
|
|
|
378
382
|
if (resolvedTargetClientId != null) {
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -71,6 +71,7 @@ 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";
|
|
74
75
|
import { startConfigWatcher } from "./config-watcher.js";
|
|
75
76
|
import { startConversationEvictor } from "./conversation-evictor.js";
|
|
76
77
|
import { writePid } from "./daemon-control.js";
|
|
@@ -705,6 +706,10 @@ export async function runDaemon(): Promise<void> {
|
|
|
705
706
|
// config, and broadcast the relevant resource-changed events to clients.
|
|
706
707
|
startConfigWatcher();
|
|
707
708
|
|
|
709
|
+
// Watch app source directories so edits recompile + refresh surfaces across
|
|
710
|
+
// all conversations.
|
|
711
|
+
startAppSourceWatcher();
|
|
712
|
+
|
|
708
713
|
// Start the CLI IPC server. Throws on EADDRINUSE to abort startup when another
|
|
709
714
|
// daemon already holds the socket, so this process never runs background jobs
|
|
710
715
|
// 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 config.json changes or a reload signal
|
|
5
5
|
* file is detected, so the daemon automatically reconnects MCP servers.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { invalidateConfigCache } from "../config/loader.js";
|
|
8
|
+
import { getConfig, invalidateConfigCache } from "../config/loader.js";
|
|
9
9
|
import {
|
|
10
10
|
buildEffectiveMcpConfig,
|
|
11
11
|
pluginMcpServersChangedSinceLastBuild,
|
|
@@ -13,7 +13,6 @@ 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";
|
|
17
16
|
import { createMcpToolsFromServer } from "../tools/mcp/mcp-tool-factory.js";
|
|
18
17
|
import { registerMcpTools, unregisterAllMcpTools } from "../tools/registry.js";
|
|
19
18
|
import { getLogger } from "../util/logger.js";
|
|
@@ -96,15 +95,16 @@ async function doReload(): Promise<McpReloadResult> {
|
|
|
96
95
|
// If the config is broken we abort early, preserving the current
|
|
97
96
|
// working MCP setup instead of leaving zero servers.
|
|
98
97
|
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 config.json does, and both arrive
|
|
106
106
|
// through this same reload.
|
|
107
|
-
const mcpConfig = buildEffectiveMcpConfig(
|
|
107
|
+
const mcpConfig = buildEffectiveMcpConfig(config.mcp);
|
|
108
108
|
const serverIds = Object.keys(mcpConfig.servers);
|
|
109
109
|
|
|
110
110
|
// 3. Restart MCP servers
|
|
@@ -13,7 +13,6 @@ 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",
|
|
17
16
|
assistantTheme: "assistant:self:theme",
|
|
18
17
|
appsList: "apps:list",
|
|
19
18
|
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,
|
|
6
|
+
* host_bash tools, the skill sandbox runner, and the debug-bash route). 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(config.mcp);
|
|
67
67
|
|
|
68
68
|
log.info("Daemon startup: providers and tools initialized");
|
|
69
69
|
}
|
|
@@ -24,7 +24,11 @@ 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 {
|
|
27
|
+
import {
|
|
28
|
+
commitAllPendingWorkspaceChanges,
|
|
29
|
+
stopWorkspaceHeartbeatService,
|
|
30
|
+
} from "../workspace/heartbeat-service.js";
|
|
31
|
+
import { stopAppSourceWatcher } from "./app-source-watcher.js";
|
|
28
32
|
import { stopConfigWatcher } from "./config-watcher.js";
|
|
29
33
|
import { stopConversationEvictor } from "./conversation-evictor.js";
|
|
30
34
|
import { stopConversations } from "./conversation-store.js";
|
|
@@ -94,6 +98,9 @@ async function shutdown(): Promise<void> {
|
|
|
94
98
|
}, 30_000);
|
|
95
99
|
forceTimer.unref();
|
|
96
100
|
|
|
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();
|
|
97
104
|
await stopHeartbeatService();
|
|
98
105
|
|
|
99
106
|
// Stop the periodic consent-cache refresh (a daemon-owned interval).
|
|
@@ -127,6 +134,7 @@ async function shutdown(): Promise<void> {
|
|
|
127
134
|
disposeAcpSessionManager();
|
|
128
135
|
stopConversationEvictor();
|
|
129
136
|
stopConfigWatcher();
|
|
137
|
+
stopAppSourceWatcher();
|
|
130
138
|
stopCliIpcServer();
|
|
131
139
|
stopConversations();
|
|
132
140
|
await stopCes();
|
|
@@ -8,24 +8,16 @@ import {
|
|
|
8
8
|
maybeSeedCapabilitySkills,
|
|
9
9
|
maybeSeedCliCommandCards,
|
|
10
10
|
} from "../plugins/defaults/memory/substrate/boot-maintenance.js";
|
|
11
|
-
import { readWorkspaceSkillMdSignature } from "../skills/workspace-skill-md-signature.js";
|
|
12
11
|
import { getLogger } from "../util/logger.js";
|
|
13
12
|
|
|
14
13
|
const log = getLogger("skill-memory-refresh");
|
|
15
14
|
|
|
16
|
-
/** Poll interval for workspace `SKILL.md` mtimes. Stats only, no tree walk. */
|
|
17
|
-
export const SKILL_MD_MTIME_POLL_MS = 1_500;
|
|
18
|
-
|
|
19
|
-
let lastSignature: string | undefined;
|
|
20
|
-
let pollTimer: ReturnType<typeof setInterval> | undefined;
|
|
21
|
-
|
|
22
15
|
export function refreshSkillCapabilityMemories(
|
|
23
16
|
config: AssistantConfig = getConfig(),
|
|
24
17
|
): void {
|
|
25
18
|
seedSkillGraphNodes();
|
|
26
19
|
maybeSeedCapabilitySkills(config);
|
|
27
20
|
maybeSeedCliCommandCards(config);
|
|
28
|
-
lastSignature = readWorkspaceSkillMdSignature();
|
|
29
21
|
void seedUninstalledCatalogSkillMemories()
|
|
30
22
|
.then(() => {
|
|
31
23
|
// Re-run after the async catalog fetch populates the cache so stale
|
|
@@ -39,59 +31,3 @@ export function refreshSkillCapabilityMemories(
|
|
|
39
31
|
),
|
|
40
32
|
);
|
|
41
33
|
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Reseed skill capability memories when the workspace `SKILL.md` set or
|
|
45
|
-
* mtimes have changed since the last refresh in this process. No-op when the
|
|
46
|
-
* signature is unchanged. First call in a process always reseeds so the
|
|
47
|
-
* memory worker, whose in-process skill cache starts empty, picks up the
|
|
48
|
-
* catalog without waiting for an install path.
|
|
49
|
-
*/
|
|
50
|
-
export function maybeRefreshSkillCapabilityMemoriesFromMtime(): boolean {
|
|
51
|
-
const signature = readWorkspaceSkillMdSignature();
|
|
52
|
-
if (lastSignature !== undefined && signature === lastSignature) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
if (lastSignature !== undefined) {
|
|
56
|
-
log.info("Workspace SKILL.md set changed, reseeding capability memories");
|
|
57
|
-
}
|
|
58
|
-
refreshSkillCapabilityMemories();
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function pollOnce(): void {
|
|
63
|
-
try {
|
|
64
|
-
maybeRefreshSkillCapabilityMemoriesFromMtime();
|
|
65
|
-
} catch (err) {
|
|
66
|
-
log.warn({ err }, "SKILL.md mtime poll failed");
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Start a per-process poll of workspace `SKILL.md` mtimes. Idempotent.
|
|
72
|
-
* The memory worker and the assistant each run this against their own
|
|
73
|
-
* in-process skill caches. Runs once immediately so a worker that has never
|
|
74
|
-
* seeded picks up the catalog without waiting a tick.
|
|
75
|
-
*/
|
|
76
|
-
export function startWorkspaceSkillMdMtimePoll(): void {
|
|
77
|
-
if (pollTimer !== undefined) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
pollOnce();
|
|
81
|
-
pollTimer = setInterval(pollOnce, SKILL_MD_MTIME_POLL_MS);
|
|
82
|
-
pollTimer.unref?.();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function stopWorkspaceSkillMdMtimePoll(): void {
|
|
86
|
-
if (pollTimer === undefined) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
clearInterval(pollTimer);
|
|
90
|
-
pollTimer = undefined;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** @internal Test-only: clear the in-process signature and poll timer. */
|
|
94
|
-
export function _resetSkillMdMtimeStateForTests(): void {
|
|
95
|
-
lastSignature = undefined;
|
|
96
|
-
stopWorkspaceSkillMdMtimePoll();
|
|
97
|
-
}
|
|
@@ -18,15 +18,17 @@ import { invalidateEdgeIndex } from "../plugins/defaults/memory/substrate/edge-i
|
|
|
18
18
|
import { invalidatePageIndex } from "../plugins/defaults/memory/substrate/page-index.js";
|
|
19
19
|
import { getConceptsDir } from "../plugins/defaults/memory/substrate/page-store.js";
|
|
20
20
|
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
publishAppsChanged,
|
|
23
|
+
publishDocumentsChanged,
|
|
24
|
+
} from "../runtime/sync/resource-sync-events.js";
|
|
25
|
+
import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
|
|
22
26
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
23
27
|
import { getLogger } from "../util/logger.js";
|
|
24
28
|
import { getWorkspaceDir } from "../util/platform.js";
|
|
25
|
-
import {
|
|
26
|
-
broadcastAppFilesChanged,
|
|
27
|
-
notifyAppSurfacesChanged,
|
|
28
|
-
} from "./app-change-notify.js";
|
|
29
|
+
import { ensureAppSourceWatcher } from "./app-source-watcher.js";
|
|
29
30
|
import type { Conversation } from "./conversation.js";
|
|
31
|
+
import { refreshSurfacesForApp } from "./conversation-surfaces.js";
|
|
30
32
|
import { isDoordashCommand, updateDoordashProgress } from "./doordash-steps.js";
|
|
31
33
|
|
|
32
34
|
const log = getLogger("tool-side-effects");
|
|
@@ -52,7 +54,7 @@ export type PostExecutionHook = (
|
|
|
52
54
|
* Compilation is the responsibility of the tool executor (see
|
|
53
55
|
* `executeAppCreate`, `executeAppRefresh`): executors own the source→dist
|
|
54
56
|
* transform and surface `compile_errors` in their result when it fails.
|
|
55
|
-
* Post-execution hooks only observe the outcome and notify
|
|
57
|
+
* Post-execution hooks only observe the outcome and notify — they must
|
|
56
58
|
* not re-run a compile because `compileApp()` begins with `rm -rf dist/`
|
|
57
59
|
* and would race with the executor's own output (LUM-1153).
|
|
58
60
|
*/
|
|
@@ -61,7 +63,14 @@ function notifyAppChanged(
|
|
|
61
63
|
appId: string,
|
|
62
64
|
opts?: { fileChange?: boolean; status?: string },
|
|
63
65
|
): void {
|
|
64
|
-
|
|
66
|
+
refreshSurfacesForApp(ctx, appId, opts);
|
|
67
|
+
broadcastAppFilesChanged(appId);
|
|
68
|
+
void updatePublishedAppDeployment(appId);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function broadcastAppFilesChanged(appId: string): void {
|
|
72
|
+
broadcastMessage({ type: "app_files_changed", appId });
|
|
73
|
+
publishAppsChanged();
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
/**
|
|
@@ -119,6 +128,8 @@ registerHook("app_create", (_name, _input, result, { ctx }) => {
|
|
|
119
128
|
log.warn({ err, appId }, "Failed to track conversation ID on app_create");
|
|
120
129
|
}
|
|
121
130
|
|
|
131
|
+
ensureAppSourceWatcher();
|
|
132
|
+
|
|
122
133
|
notifyAppChanged(ctx, appId);
|
|
123
134
|
|
|
124
135
|
// Seed background icon generation from the created app's canonical record
|
|
@@ -459,28 +459,6 @@ describe("feed-writer", () => {
|
|
|
459
459
|
expect(result!.summary).toBe("Fresh summary");
|
|
460
460
|
});
|
|
461
461
|
|
|
462
|
-
test("a status value replaces, and a status updater reads write-time state", async () => {
|
|
463
|
-
await appendFeedItem(makeItem({ id: "item-1" }));
|
|
464
|
-
|
|
465
|
-
const replaced = await patchFeedItemContent("item-1", {
|
|
466
|
-
status: "acted_on",
|
|
467
|
-
});
|
|
468
|
-
expect(replaced!.status).toBe("acted_on");
|
|
469
|
-
|
|
470
|
-
// The updater sees the status as of the write, so a conditional
|
|
471
|
-
// transition cannot overwrite what another writer just set.
|
|
472
|
-
const observed: string[] = [];
|
|
473
|
-
const conditional = await patchFeedItemContent("item-1", {
|
|
474
|
-
status: (existing) => {
|
|
475
|
-
observed.push(existing.status);
|
|
476
|
-
return existing.status === "new" ? "seen" : existing.status;
|
|
477
|
-
},
|
|
478
|
-
});
|
|
479
|
-
expect(observed).toEqual(["acted_on"]);
|
|
480
|
-
expect(conditional!.status).toBe("acted_on");
|
|
481
|
-
expect(readFileJson().items[0]!.status).toBe("acted_on");
|
|
482
|
-
});
|
|
483
|
-
|
|
484
462
|
test("returns null for an unknown id", async () => {
|
|
485
463
|
await appendFeedItem(makeItem({ id: "known" }));
|
|
486
464
|
expect(await patchFeedItemContent("unknown", { title: "x" })).toBeNull();
|
package/src/home/feed-writer.ts
CHANGED
|
@@ -185,13 +185,7 @@ export interface FeedItemContentPatch {
|
|
|
185
185
|
title?: string;
|
|
186
186
|
summary?: string;
|
|
187
187
|
urgency?: FeedItemUrgency;
|
|
188
|
-
|
|
189
|
-
* New status, or an updater applied inside the coalescing queue so it
|
|
190
|
-
* reads the item as of write time. Use the updater for a conditional
|
|
191
|
-
* transition: a plain value would overwrite a status another writer
|
|
192
|
-
* set while the patch sat in the queue.
|
|
193
|
-
*/
|
|
194
|
-
status?: FeedItemStatus | ((existing: FeedItem) => FeedItemStatus);
|
|
188
|
+
status?: FeedItemStatus;
|
|
195
189
|
/**
|
|
196
190
|
* Updater for the item's guardian projection, applied inside the
|
|
197
191
|
* coalescing queue so it reads the projection as of write time (a
|
|
@@ -405,10 +399,7 @@ async function runWrite(): Promise<void> {
|
|
|
405
399
|
updated.urgency = patch.urgency;
|
|
406
400
|
}
|
|
407
401
|
if (patch.status !== undefined) {
|
|
408
|
-
updated.status =
|
|
409
|
-
typeof patch.status === "function"
|
|
410
|
-
? patch.status(existing)
|
|
411
|
-
: patch.status;
|
|
402
|
+
updated.status = patch.status;
|
|
412
403
|
}
|
|
413
404
|
if (patch.guardianRequest !== undefined && existing.guardianRequest) {
|
|
414
405
|
updated.guardianRequest = patch.guardianRequest(existing.guardianRequest);
|
package/src/hooks/types.ts
CHANGED
|
@@ -679,36 +679,3 @@ export interface ConversationDeletedContext
|
|
|
679
679
|
* {@link BaseHookContext}.
|
|
680
680
|
*/
|
|
681
681
|
export type ConversationsClearedContext = BaseHookContext;
|
|
682
|
-
|
|
683
|
-
// ─── Message-deleted hook context ────────────────────────────────────────────
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
* Context passed to the `message-deleted` hook. Fires once per deleted
|
|
687
|
-
* message row, from the shared single-message delete primitive, after the row
|
|
688
|
-
* is removed. Whole-conversation deletes dispatch `conversation-deleted`
|
|
689
|
-
* instead.
|
|
690
|
-
*
|
|
691
|
-
* Fire-and-forget like `conversation-deleted`: the primitive is synchronous
|
|
692
|
-
* and does not wait for the chain. The row is gone by the time a hook runs,
|
|
693
|
-
* so the context carries the row's `createdAt` alongside its id. Together
|
|
694
|
-
* they are the `(createdAt, id)` position the row held, which is what a hook
|
|
695
|
-
* keeping a cursor on that row needs to record once the row can no longer be
|
|
696
|
-
* looked up. The default memory plugin contributes a hook here that stamps
|
|
697
|
-
* its retrospective cursor.
|
|
698
|
-
*/
|
|
699
|
-
export interface MessageDeletedInputContext {
|
|
700
|
-
/** ID of the conversation that owned the row. */
|
|
701
|
-
readonly conversationId: string;
|
|
702
|
-
/** ID of the deleted message row. */
|
|
703
|
-
readonly messageId: string;
|
|
704
|
-
/** The deleted row's `createdAt`. */
|
|
705
|
-
readonly createdAt: number;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
/**
|
|
709
|
-
* The full `message-deleted` context a hook receives: the dispatching call
|
|
710
|
-
* site's {@link MessageDeletedInputContext} plus the pipeline-stamped
|
|
711
|
-
* {@link BaseHookContext} capabilities.
|
|
712
|
-
*/
|
|
713
|
-
export interface MessageDeletedContext
|
|
714
|
-
extends MessageDeletedInputContext, BaseHookContext {}
|
|
@@ -18,10 +18,9 @@
|
|
|
18
18
|
* the platform can register a route that points at this instance.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { getPlatformBaseUrl } from "../config/env.js";
|
|
21
|
+
import { getPlatformAssistantId, getPlatformBaseUrl } from "../config/env.js";
|
|
22
22
|
import { getIsPlatform } from "../config/env-registry.js";
|
|
23
23
|
import { getConfig } from "../config/loader.js";
|
|
24
|
-
import { resolvePlatformAssistantId } from "../config/platform-identity.js";
|
|
25
24
|
import { ipcRegisterWebhookRoute } from "../ipc/gateway-client.js";
|
|
26
25
|
import { credentialKey } from "../security/credential-key.js";
|
|
27
26
|
import { getSecureKeyAsync } from "../security/secure-keys.js";
|
|
@@ -46,11 +45,11 @@ export interface PlatformCallbackRegistrationContext {
|
|
|
46
45
|
|
|
47
46
|
export async function resolvePlatformCallbackRegistrationContext(): Promise<PlatformCallbackRegistrationContext> {
|
|
48
47
|
const platform = getIsPlatform();
|
|
49
|
-
const [storedBaseUrlRaw,
|
|
48
|
+
const [storedBaseUrlRaw, storedAssistantIdRaw, storedAssistantApiKeyRaw] =
|
|
50
49
|
await Promise.all([
|
|
51
50
|
getSecureKeyAsync(credentialKey("vellum", "platform_base_url")),
|
|
51
|
+
getSecureKeyAsync(credentialKey("vellum", "platform_assistant_id")),
|
|
52
52
|
getSecureKeyAsync(credentialKey("vellum", "assistant_api_key")),
|
|
53
|
-
resolvePlatformAssistantId(),
|
|
54
53
|
]);
|
|
55
54
|
|
|
56
55
|
const storedBaseUrl = storedBaseUrlRaw?.trim();
|
|
@@ -58,6 +57,8 @@ export async function resolvePlatformCallbackRegistrationContext(): Promise<Plat
|
|
|
58
57
|
/\/+$/,
|
|
59
58
|
"",
|
|
60
59
|
);
|
|
60
|
+
const assistantId =
|
|
61
|
+
getPlatformAssistantId().trim() || storedAssistantIdRaw?.trim() || "";
|
|
61
62
|
const envAssistantCredential = process.env.ASSISTANT_API_KEY?.trim();
|
|
62
63
|
const assistantCredential =
|
|
63
64
|
storedAssistantApiKeyRaw?.trim() || envAssistantCredential || undefined;
|
|
@@ -329,6 +329,7 @@ describe("LiveVoiceMetricsCollector", () => {
|
|
|
329
329
|
endpointHoldCount: 0,
|
|
330
330
|
endpointDecisionMaxLatencyMs: 95,
|
|
331
331
|
});
|
|
332
|
+
expect(completed).not.toHaveProperty("ackSpoken");
|
|
332
333
|
});
|
|
333
334
|
|
|
334
335
|
test("decisions without a source are attributed to the front door", () => {
|
|
@@ -434,6 +435,7 @@ describe("LiveVoiceMetricsCollector", () => {
|
|
|
434
435
|
expect(completed).not.toHaveProperty("endpointHoldCount");
|
|
435
436
|
expect(completed).not.toHaveProperty("endpointDecisionMaxLatencyMs");
|
|
436
437
|
expect(completed).not.toHaveProperty("endpointDecisionSource");
|
|
438
|
+
expect(completed).not.toHaveProperty("ackSpoken");
|
|
437
439
|
expect(completed).not.toHaveProperty("progressUpdatesSpoken");
|
|
438
440
|
|
|
439
441
|
const aggregateFields = getLiveVoiceMetricsAggregateFields(
|
|
@@ -444,6 +446,7 @@ describe("LiveVoiceMetricsCollector", () => {
|
|
|
444
446
|
expect(aggregateFields).not.toHaveProperty("endpointHoldCount");
|
|
445
447
|
expect(aggregateFields).not.toHaveProperty("endpointDecisionMaxLatencyMs");
|
|
446
448
|
expect(aggregateFields).not.toHaveProperty("endpointDecisionSource");
|
|
449
|
+
expect(aggregateFields).not.toHaveProperty("ackSpoken");
|
|
447
450
|
expect(aggregateFields).not.toHaveProperty("progressUpdatesSpoken");
|
|
448
451
|
});
|
|
449
452
|
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import { describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
VoiceProgressNarrator,
|
|
5
|
-
VoiceProgressTextInput,
|
|
6
|
-
} from "../../calls/progress-narration.js";
|
|
7
|
-
import {
|
|
8
|
-
pickProgressPhrase,
|
|
9
|
-
PROGRESS_FALLBACK_PHRASES,
|
|
10
|
-
PROGRESS_FALLBACK_PHRASES_BY_LANGUAGE,
|
|
11
|
-
} from "../../calls/progress-phrases.js";
|
|
12
3
|
import { sanitizeForTts } from "../../calls/tts-text-sanitizer.js";
|
|
13
4
|
import type {
|
|
14
5
|
VoiceTurnCallbacks,
|
|
@@ -16,9 +7,9 @@ import type {
|
|
|
16
7
|
} from "../../calls/voice-session-bridge.js";
|
|
17
8
|
import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
|
|
18
9
|
import type {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from "../../config/schemas/voice.js";
|
|
10
|
+
LiveVoiceFrontModelConfig,
|
|
11
|
+
LiveVoiceProgressConfig,
|
|
12
|
+
} from "../../config/schemas/live-voice.js";
|
|
22
13
|
import type {
|
|
23
14
|
StreamingTranscriber,
|
|
24
15
|
SttStreamServerEvent,
|
|
@@ -30,6 +21,15 @@ import {
|
|
|
30
21
|
} from "../live-voice-session.js";
|
|
31
22
|
import type { LiveVoiceSessionFactoryContext } from "../live-voice-session-manager.js";
|
|
32
23
|
import type { LiveVoiceTtsOptions } from "../live-voice-tts.js";
|
|
24
|
+
import type {
|
|
25
|
+
VoiceProgressNarrator,
|
|
26
|
+
VoiceProgressTextInput,
|
|
27
|
+
} from "../progress-narration.js";
|
|
28
|
+
import {
|
|
29
|
+
pickProgressPhrase,
|
|
30
|
+
PROGRESS_FALLBACK_PHRASES,
|
|
31
|
+
PROGRESS_FALLBACK_PHRASES_BY_LANGUAGE,
|
|
32
|
+
} from "../progress-phrases.js";
|
|
33
33
|
import {
|
|
34
34
|
createLiveVoiceServerFrameSequencer,
|
|
35
35
|
type LiveVoiceClientStartFrame,
|
|
@@ -142,8 +142,8 @@ function makeProgressNarrator(
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
function progressConfig(
|
|
145
|
-
overrides: Partial<
|
|
146
|
-
): Partial<
|
|
145
|
+
overrides: Partial<LiveVoiceProgressConfig> = {},
|
|
146
|
+
): Partial<LiveVoiceFrontModelConfig> {
|
|
147
147
|
const idleIntervalMs = overrides.idleIntervalMs ?? 60_000;
|
|
148
148
|
return {
|
|
149
149
|
progress: {
|
|
@@ -163,7 +163,7 @@ function progressConfig(
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
function createProgressHarness(options: {
|
|
166
|
-
frontModelConfig: Partial<
|
|
166
|
+
frontModelConfig: Partial<LiveVoiceFrontModelConfig>;
|
|
167
167
|
progressNarrator: VoiceProgressNarrator;
|
|
168
168
|
emitMetrics?: boolean;
|
|
169
169
|
gateTtsText?: (text: string) => Promise<void> | null;
|