@vellumai/assistant 0.12.1-staging.1 → 0.12.1
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/openapi.yaml +1 -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 +1 -2
- package/src/__tests__/cu-unified-flow.test.ts +2 -8
- 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__/outlook-messaging-provider.test.ts +6 -6
- 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/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/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 +0 -93
- 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/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/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 -8
- 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 +21 -75
- 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/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/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/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__/home-feed-side-effect.test.ts +3 -153
- 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/home-feed-side-effect.ts +7 -55
- 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 +0 -2
- 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/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__/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/diagnostics-routes.ts +3 -55
- package/src/runtime/routes/index.ts +0 -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 +21 -8
- 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__/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__/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 -117
- 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 -144
- 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/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/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
|
@@ -5,11 +5,7 @@
|
|
|
5
5
|
// Two pointers move independently:
|
|
6
6
|
// - `lastProcessedMessageId` advances ONLY when a retrospective run
|
|
7
7
|
// completes successfully (correctness invariant — failures must
|
|
8
|
-
// re-process the same messages on the next attempt).
|
|
9
|
-
// `lastProcessedCreatedAt` is that row's `createdAt` at write time, so the
|
|
10
|
-
// `(createdAt, id)` cursor stays reconstructible after the row itself is
|
|
11
|
-
// deleted: a regenerated reply discards the latest assistant message,
|
|
12
|
-
// which is exactly where the cursor tends to sit.
|
|
8
|
+
// re-process the same messages on the next attempt).
|
|
13
9
|
// - `lastRunAt` advances at the end of every job that actually attempted a
|
|
14
10
|
// run (success or failure). Drives the per-conversation cooldown gate in
|
|
15
11
|
// the trigger-check helper so failing jobs can't loop in tight retries
|
|
@@ -29,39 +25,20 @@
|
|
|
29
25
|
// that connection is unavailable. The memory database has no `conversations`
|
|
30
26
|
// table, so there is no FK cascade — the `conversation-deleted` hook purges the
|
|
31
27
|
// row explicitly instead.
|
|
32
|
-
//
|
|
33
|
-
// `last_processed_created_at` is added to the table by
|
|
34
|
-
// `ensureRetrospectiveCursorColumn`: an idempotent, fail-open ALTER run lazily
|
|
35
|
-
// on first use in each process (daemon, memory worker, CLI) rather than by the
|
|
36
|
-
// global migration chain, which must not gate DB readiness on the memory
|
|
37
|
-
// database. The probe is memoized per memory connection, so a connection
|
|
38
|
-
// replaced by `resetDb()` (restores, imports) is probed again before its
|
|
39
|
-
// first read. When the column cannot be added, reads and writes fall back to
|
|
40
|
-
// the id-only cursor shape and the probe is retried after a short backoff.
|
|
41
28
|
|
|
42
29
|
import { desc, eq } from "drizzle-orm";
|
|
43
30
|
|
|
44
31
|
import type { DrizzleDb } from "../../../persistence/db-connection.js";
|
|
45
|
-
import { messageCreatedAtByIds } from "../../../persistence/message-reads.js";
|
|
46
32
|
import { memoryRetrospectiveState } from "../../../persistence/schema/index.js";
|
|
47
33
|
import { withSqliteRetry } from "./host-utils.js";
|
|
48
34
|
import { getLogger } from "./logging.js";
|
|
49
|
-
import { memoryDbOrNull
|
|
35
|
+
import { memoryDbOrNull } from "./memory-db.js";
|
|
50
36
|
|
|
51
37
|
const log = getLogger("memory-retrospective-state");
|
|
52
38
|
|
|
53
|
-
const TABLE = "memory_retrospective_state";
|
|
54
|
-
const CURSOR_CREATED_AT_COLUMN = "last_processed_created_at";
|
|
55
|
-
|
|
56
39
|
export interface MemoryRetrospectiveState {
|
|
57
40
|
conversationId: string;
|
|
58
41
|
lastProcessedMessageId: string;
|
|
59
|
-
/**
|
|
60
|
-
* `createdAt` of the `lastProcessedMessageId` row when the pointer was
|
|
61
|
-
* written, or null when unknown: rows written before the column existed,
|
|
62
|
-
* and the `""` sentinel. Lets the cursor bound a read after its row is gone.
|
|
63
|
-
*/
|
|
64
|
-
lastProcessedCreatedAt: number | null;
|
|
65
42
|
lastRunAt: number;
|
|
66
43
|
/**
|
|
67
44
|
* Cumulative `remember` contents from prior retrospective passes, oldest
|
|
@@ -122,124 +99,6 @@ function serializeRememberedLog(log: string[]): string | null {
|
|
|
122
99
|
return log.length === 0 ? null : JSON.stringify(log);
|
|
123
100
|
}
|
|
124
101
|
|
|
125
|
-
// ---------------------------------------------------------------------------
|
|
126
|
-
// Cursor timestamp column
|
|
127
|
-
// ---------------------------------------------------------------------------
|
|
128
|
-
|
|
129
|
-
type MemorySqlite = NonNullable<ReturnType<typeof memorySqliteOrNull>>;
|
|
130
|
-
|
|
131
|
-
/** The memory connection the column was confirmed on; any other re-probes. */
|
|
132
|
-
let cursorColumnEnsuredOn: MemorySqlite | null = null;
|
|
133
|
-
/**
|
|
134
|
-
* The connection the last probe failed on and when. The backoff applies to
|
|
135
|
-
* that connection only: a replaced connection is probed at once, so a
|
|
136
|
-
* restore right after a failure still gets the column before its first read.
|
|
137
|
-
*/
|
|
138
|
-
let cursorColumnFailedOn: MemorySqlite | null = null;
|
|
139
|
-
let lastCursorColumnFailureAt = 0;
|
|
140
|
-
/** Backoff before re-probing the same connection after a failed ALTER. */
|
|
141
|
-
const CURSOR_COLUMN_RETRY_MS = 60_000;
|
|
142
|
-
|
|
143
|
-
function isDuplicateColumnError(err: unknown): boolean {
|
|
144
|
-
return err instanceof Error && /duplicate column name/i.test(err.message);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Add `last_processed_created_at` to the state table when it is missing.
|
|
149
|
-
* Idempotent; memoized per memory connection, so a connection replaced by
|
|
150
|
-
* `resetDb()` is probed again and an imported database that lacks the column
|
|
151
|
-
* gets it before its first read. Fail-open: when the ALTER cannot run, the
|
|
152
|
-
* failure is logged, every read and write falls back to the id-only shape,
|
|
153
|
-
* and that connection is probed again after {@link CURSOR_COLUMN_RETRY_MS}.
|
|
154
|
-
* A table the migration chain has not created yet is neither memoized nor a
|
|
155
|
-
* failure.
|
|
156
|
-
*/
|
|
157
|
-
export function ensureRetrospectiveCursorColumn(context: string): boolean {
|
|
158
|
-
const raw = memorySqliteOrNull(context);
|
|
159
|
-
if (!raw) {
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
if (cursorColumnEnsuredOn === raw) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
if (
|
|
166
|
-
cursorColumnFailedOn === raw &&
|
|
167
|
-
Date.now() - lastCursorColumnFailureAt < CURSOR_COLUMN_RETRY_MS
|
|
168
|
-
) {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
const columns = raw.query(`PRAGMA table_info(${TABLE})`).all() as Array<{
|
|
173
|
-
name: string;
|
|
174
|
-
}>;
|
|
175
|
-
if (columns.length === 0) {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
if (!columns.some((column) => column.name === CURSOR_CREATED_AT_COLUMN)) {
|
|
179
|
-
raw.exec(
|
|
180
|
-
`ALTER TABLE ${TABLE} ADD COLUMN ${CURSOR_CREATED_AT_COLUMN} INTEGER`,
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
} catch (err) {
|
|
184
|
-
if (!isDuplicateColumnError(err)) {
|
|
185
|
-
cursorColumnFailedOn = raw;
|
|
186
|
-
lastCursorColumnFailureAt = Date.now();
|
|
187
|
-
log.warn(
|
|
188
|
-
{ err, context },
|
|
189
|
-
"could not add the retrospective cursor timestamp column; cursors fall back to id-only until the next probe",
|
|
190
|
-
);
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
cursorColumnEnsuredOn = raw;
|
|
195
|
-
cursorColumnFailedOn = null;
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Forget the memoized column probe so the next call re-runs it. Intended
|
|
201
|
-
* ONLY for tests that recreate the memory database mid-process.
|
|
202
|
-
*/
|
|
203
|
-
export function _resetRetrospectiveCursorColumnForTests(): void {
|
|
204
|
-
cursorColumnEnsuredOn = null;
|
|
205
|
-
cursorColumnFailedOn = null;
|
|
206
|
-
lastCursorColumnFailureAt = 0;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// ---------------------------------------------------------------------------
|
|
210
|
-
// Reads
|
|
211
|
-
// ---------------------------------------------------------------------------
|
|
212
|
-
|
|
213
|
-
const BASE_COLUMNS = {
|
|
214
|
-
conversationId: memoryRetrospectiveState.conversationId,
|
|
215
|
-
lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
|
|
216
|
-
lastRunAt: memoryRetrospectiveState.lastRunAt,
|
|
217
|
-
rememberedLog: memoryRetrospectiveState.rememberedLog,
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const CURSOR_COLUMNS = {
|
|
221
|
-
...BASE_COLUMNS,
|
|
222
|
-
lastProcessedCreatedAt: memoryRetrospectiveState.lastProcessedCreatedAt,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
interface StateRow {
|
|
226
|
-
conversationId: string;
|
|
227
|
-
lastProcessedMessageId: string;
|
|
228
|
-
lastRunAt: number;
|
|
229
|
-
rememberedLog: string | null;
|
|
230
|
-
lastProcessedCreatedAt?: number | null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function toState(row: StateRow): MemoryRetrospectiveState {
|
|
234
|
-
return {
|
|
235
|
-
conversationId: row.conversationId,
|
|
236
|
-
lastProcessedMessageId: row.lastProcessedMessageId,
|
|
237
|
-
lastProcessedCreatedAt: row.lastProcessedCreatedAt ?? null,
|
|
238
|
-
lastRunAt: row.lastRunAt,
|
|
239
|
-
rememberedLog: parseRememberedLog(row.rememberedLog),
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
102
|
/**
|
|
244
103
|
* Return the `limit` most-recently-run retrospective state rows, newest first.
|
|
245
104
|
*/
|
|
@@ -250,22 +109,23 @@ export function listRetrospectiveStates(
|
|
|
250
109
|
if (!mdb) {
|
|
251
110
|
return [];
|
|
252
111
|
}
|
|
253
|
-
const rows
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
112
|
+
const rows = mdb
|
|
113
|
+
.select({
|
|
114
|
+
conversationId: memoryRetrospectiveState.conversationId,
|
|
115
|
+
lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
|
|
116
|
+
lastRunAt: memoryRetrospectiveState.lastRunAt,
|
|
117
|
+
rememberedLog: memoryRetrospectiveState.rememberedLog,
|
|
118
|
+
})
|
|
119
|
+
.from(memoryRetrospectiveState)
|
|
120
|
+
.orderBy(desc(memoryRetrospectiveState.lastRunAt))
|
|
121
|
+
.limit(limit)
|
|
122
|
+
.all();
|
|
123
|
+
return rows.map((row) => ({
|
|
124
|
+
conversationId: row.conversationId,
|
|
125
|
+
lastProcessedMessageId: row.lastProcessedMessageId,
|
|
126
|
+
lastRunAt: row.lastRunAt,
|
|
127
|
+
rememberedLog: parseRememberedLog(row.rememberedLog),
|
|
128
|
+
}));
|
|
269
129
|
}
|
|
270
130
|
|
|
271
131
|
/**
|
|
@@ -278,45 +138,37 @@ export function getRetrospectiveState(
|
|
|
278
138
|
if (!mdb) {
|
|
279
139
|
return null;
|
|
280
140
|
}
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
141
|
+
const row = mdb
|
|
142
|
+
.select({
|
|
143
|
+
conversationId: memoryRetrospectiveState.conversationId,
|
|
144
|
+
lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
|
|
145
|
+
lastRunAt: memoryRetrospectiveState.lastRunAt,
|
|
146
|
+
rememberedLog: memoryRetrospectiveState.rememberedLog,
|
|
147
|
+
})
|
|
148
|
+
.from(memoryRetrospectiveState)
|
|
149
|
+
.where(eq(memoryRetrospectiveState.conversationId, conversationId))
|
|
150
|
+
.get();
|
|
151
|
+
if (!row) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
conversationId: row.conversationId,
|
|
156
|
+
lastProcessedMessageId: row.lastProcessedMessageId,
|
|
157
|
+
lastRunAt: row.lastRunAt,
|
|
158
|
+
rememberedLog: parseRememberedLog(row.rememberedLog),
|
|
159
|
+
};
|
|
296
160
|
}
|
|
297
161
|
|
|
298
|
-
// ---------------------------------------------------------------------------
|
|
299
|
-
// Writes
|
|
300
|
-
// ---------------------------------------------------------------------------
|
|
301
|
-
|
|
302
162
|
/**
|
|
303
163
|
* Upsert both pointers atomically. Used on successful retrospective runs.
|
|
304
164
|
*
|
|
305
|
-
* `lastProcessedCreatedAt` is the id's companion and is rewritten with every
|
|
306
|
-
* pointer write: an omitted value records "unknown" for the new id rather
|
|
307
|
-
* than keeping the previous row's timestamp.
|
|
308
|
-
*
|
|
309
165
|
* `rememberedLog`, when provided, is written in the same statement so the
|
|
310
166
|
* cumulative dedup log can never drift from the pointer it was computed
|
|
311
167
|
* against. When omitted, the stored log is left untouched (and seeded NULL on
|
|
312
168
|
* first insert).
|
|
313
169
|
*/
|
|
314
170
|
export async function upsertRetrospectiveState(
|
|
315
|
-
args: Omit<
|
|
316
|
-
MemoryRetrospectiveState,
|
|
317
|
-
"rememberedLog" | "lastProcessedCreatedAt"
|
|
318
|
-
> & {
|
|
319
|
-
lastProcessedCreatedAt?: number | null;
|
|
171
|
+
args: Omit<MemoryRetrospectiveState, "rememberedLog"> & {
|
|
320
172
|
rememberedLog?: string[];
|
|
321
173
|
},
|
|
322
174
|
): Promise<void> {
|
|
@@ -324,9 +176,6 @@ export async function upsertRetrospectiveState(
|
|
|
324
176
|
if (!mdb) {
|
|
325
177
|
return;
|
|
326
178
|
}
|
|
327
|
-
const withCursor = ensureRetrospectiveCursorColumn(
|
|
328
|
-
"upsertRetrospectiveState",
|
|
329
|
-
);
|
|
330
179
|
const serializedLog =
|
|
331
180
|
args.rememberedLog === undefined
|
|
332
181
|
? undefined
|
|
@@ -336,16 +185,12 @@ export async function upsertRetrospectiveState(
|
|
|
336
185
|
// on first insert).
|
|
337
186
|
const set: {
|
|
338
187
|
lastProcessedMessageId: string;
|
|
339
|
-
lastProcessedCreatedAt?: number | null;
|
|
340
188
|
lastRunAt: number;
|
|
341
189
|
rememberedLog?: string | null;
|
|
342
190
|
} = {
|
|
343
191
|
lastProcessedMessageId: args.lastProcessedMessageId,
|
|
344
192
|
lastRunAt: args.lastRunAt,
|
|
345
193
|
};
|
|
346
|
-
if (withCursor) {
|
|
347
|
-
set.lastProcessedCreatedAt = args.lastProcessedCreatedAt ?? null;
|
|
348
|
-
}
|
|
349
194
|
if (serializedLog !== undefined) {
|
|
350
195
|
set.rememberedLog = serializedLog;
|
|
351
196
|
}
|
|
@@ -358,9 +203,6 @@ export async function upsertRetrospectiveState(
|
|
|
358
203
|
lastProcessedMessageId: args.lastProcessedMessageId,
|
|
359
204
|
lastRunAt: args.lastRunAt,
|
|
360
205
|
rememberedLog: serializedLog ?? null,
|
|
361
|
-
...(withCursor
|
|
362
|
-
? { lastProcessedCreatedAt: args.lastProcessedCreatedAt ?? null }
|
|
363
|
-
: {}),
|
|
364
206
|
})
|
|
365
207
|
.onConflictDoUpdate({
|
|
366
208
|
target: memoryRetrospectiveState.conversationId,
|
|
@@ -374,46 +216,6 @@ export async function upsertRetrospectiveState(
|
|
|
374
216
|
);
|
|
375
217
|
}
|
|
376
218
|
|
|
377
|
-
/**
|
|
378
|
-
* The copied source row that sits latest at or before `bound` in
|
|
379
|
-
* `(createdAt, id)` order, as its forked id and `createdAt`, or null when
|
|
380
|
-
* every copied row lies after the bound. Reads the source rows through the
|
|
381
|
-
* fork transaction's handle.
|
|
382
|
-
*/
|
|
383
|
-
function latestCopiedRowAtOrBefore(
|
|
384
|
-
database: DrizzleDb,
|
|
385
|
-
forkedMessageIds: Map<string, string>,
|
|
386
|
-
bound: { createdAt: number; id: string },
|
|
387
|
-
): { forkedId: string; createdAt: number } | null {
|
|
388
|
-
const createdAtBySourceId = messageCreatedAtByIds(
|
|
389
|
-
[...forkedMessageIds.keys()],
|
|
390
|
-
{ db: database },
|
|
391
|
-
);
|
|
392
|
-
let best: { sourceId: string; createdAt: number } | null = null;
|
|
393
|
-
for (const [sourceId, createdAt] of createdAtBySourceId) {
|
|
394
|
-
const atOrBefore =
|
|
395
|
-
createdAt < bound.createdAt ||
|
|
396
|
-
(createdAt === bound.createdAt && sourceId <= bound.id);
|
|
397
|
-
if (!atOrBefore) {
|
|
398
|
-
continue;
|
|
399
|
-
}
|
|
400
|
-
const later =
|
|
401
|
-
best === null ||
|
|
402
|
-
createdAt > best.createdAt ||
|
|
403
|
-
(createdAt === best.createdAt && sourceId > best.sourceId);
|
|
404
|
-
if (later) {
|
|
405
|
-
best = { sourceId, createdAt };
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (best === null) {
|
|
409
|
-
return null;
|
|
410
|
-
}
|
|
411
|
-
const forkedId = forkedMessageIds.get(best.sourceId);
|
|
412
|
-
return forkedId === undefined
|
|
413
|
-
? null
|
|
414
|
-
: { forkedId, createdAt: best.createdAt };
|
|
415
|
-
}
|
|
416
|
-
|
|
417
219
|
/**
|
|
418
220
|
* Carry the source conversation's retrospective state into a forked child so
|
|
419
221
|
* the fork doesn't re-process content the parent already covered. Synchronous
|
|
@@ -427,23 +229,18 @@ function latestCopiedRowAtOrBefore(
|
|
|
427
229
|
* succeeded) → child pointer is also `""`.
|
|
428
230
|
* - source pointer is within the copied range (`forkedMessageIds` has it) →
|
|
429
231
|
* child pointer is the mapped forked message ID.
|
|
430
|
-
* - source pointer is not in `forkedMessageIds`
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
* - source pointer is not in `forkedMessageIds` and has no stored
|
|
435
|
-
* `createdAt` → child pointer is the last copied message's mapped ID, on
|
|
436
|
-
* the assumption it lies past the fork boundary.
|
|
232
|
+
* - source pointer is past the fork boundary (not in `forkedMessageIds`) →
|
|
233
|
+
* child pointer is the last copied message's mapped ID. All copied
|
|
234
|
+
* messages have already been retro'd by the source, so the child should
|
|
235
|
+
* wait for new post-fork messages before its first retro fires.
|
|
437
236
|
*
|
|
438
|
-
* `lastProcessedCreatedAt` is read from the forked pointer's row through
|
|
439
|
-
* `database`, the fork transaction's main-DB handle, which is the only handle
|
|
440
|
-
* the freshly copied rows are visible through.
|
|
441
237
|
* `lastRunAt` is copied verbatim — the cooldown gate inherits from source.
|
|
442
238
|
* `rememberedLog` is copied verbatim — the parent's saves remain the child's
|
|
443
239
|
* dedup baseline.
|
|
444
240
|
*
|
|
445
|
-
* The
|
|
446
|
-
*
|
|
241
|
+
* The row lives on the memory connection, so this reads/writes there rather
|
|
242
|
+
* than on the main fork transaction's handle — the `database` arg is unused
|
|
243
|
+
* now, and an unavailable memory database is a best-effort no-op.
|
|
447
244
|
*/
|
|
448
245
|
export function forkRetrospectiveState(args: {
|
|
449
246
|
database: DrizzleDb;
|
|
@@ -453,7 +250,6 @@ export function forkRetrospectiveState(args: {
|
|
|
453
250
|
lastCopiedSourceMessageId: string | null;
|
|
454
251
|
}): void {
|
|
455
252
|
const {
|
|
456
|
-
database,
|
|
457
253
|
sourceConversationId,
|
|
458
254
|
forkedConversationId,
|
|
459
255
|
forkedMessageIds,
|
|
@@ -466,84 +262,47 @@ export function forkRetrospectiveState(args: {
|
|
|
466
262
|
return;
|
|
467
263
|
}
|
|
468
264
|
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
)
|
|
479
|
-
.get()
|
|
480
|
-
: mdb
|
|
481
|
-
.select(BASE_COLUMNS)
|
|
482
|
-
.from(memoryRetrospectiveState)
|
|
483
|
-
.where(
|
|
484
|
-
eq(memoryRetrospectiveState.conversationId, sourceConversationId),
|
|
485
|
-
)
|
|
486
|
-
.get();
|
|
265
|
+
const sourceRow = mdb
|
|
266
|
+
.select({
|
|
267
|
+
lastProcessedMessageId: memoryRetrospectiveState.lastProcessedMessageId,
|
|
268
|
+
lastRunAt: memoryRetrospectiveState.lastRunAt,
|
|
269
|
+
rememberedLog: memoryRetrospectiveState.rememberedLog,
|
|
270
|
+
})
|
|
271
|
+
.from(memoryRetrospectiveState)
|
|
272
|
+
.where(eq(memoryRetrospectiveState.conversationId, sourceConversationId))
|
|
273
|
+
.get();
|
|
487
274
|
if (!sourceRow) {
|
|
488
275
|
return;
|
|
489
276
|
}
|
|
490
277
|
|
|
491
|
-
const sourcePointer = sourceRow.lastProcessedMessageId;
|
|
492
|
-
const sourceCreatedAt = sourceRow.lastProcessedCreatedAt ?? null;
|
|
493
278
|
let forkedPointer = "";
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const mapped = forkedMessageIds.get(sourcePointer);
|
|
279
|
+
if (sourceRow.lastProcessedMessageId !== "") {
|
|
280
|
+
const mapped = forkedMessageIds.get(sourceRow.lastProcessedMessageId);
|
|
497
281
|
if (mapped !== undefined) {
|
|
498
282
|
forkedPointer = mapped;
|
|
499
|
-
forkedCreatedAt =
|
|
500
|
-
messageCreatedAtByIds([forkedPointer], { db: database }).get(
|
|
501
|
-
forkedPointer,
|
|
502
|
-
) ?? null;
|
|
503
|
-
} else if (sourceCreatedAt !== null) {
|
|
504
|
-
// The source pointer is not among the copied rows: either its row
|
|
505
|
-
// was deleted (a regenerated reply) or it lies past the copied range.
|
|
506
|
-
// Its stored `(createdAt, id)` bound still says where it sat, so the
|
|
507
|
-
// child takes the latest copied row at or before that bound. Copied
|
|
508
|
-
// rows after it (a replacement reply, later turns) stay unprocessed;
|
|
509
|
-
// a bound before every copied row leaves the child at "nothing
|
|
510
|
-
// processed yet".
|
|
511
|
-
const placed = latestCopiedRowAtOrBefore(database, forkedMessageIds, {
|
|
512
|
-
createdAt: sourceCreatedAt,
|
|
513
|
-
id: sourcePointer,
|
|
514
|
-
});
|
|
515
|
-
if (placed) {
|
|
516
|
-
forkedPointer = placed.forkedId;
|
|
517
|
-
forkedCreatedAt = placed.createdAt;
|
|
518
|
-
}
|
|
519
283
|
} else if (lastCopiedSourceMessageId !== null) {
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
//
|
|
523
|
-
// messages.
|
|
284
|
+
// Source pointer is past the fork boundary — everything copied has
|
|
285
|
+
// already been processed by the source, so clamp to the last copied
|
|
286
|
+
// message so the fork waits for new post-fork messages.
|
|
524
287
|
forkedPointer = forkedMessageIds.get(lastCopiedSourceMessageId) ?? "";
|
|
525
|
-
forkedCreatedAt =
|
|
526
|
-
forkedPointer === ""
|
|
527
|
-
? null
|
|
528
|
-
: (messageCreatedAtByIds([forkedPointer], { db: database }).get(
|
|
529
|
-
forkedPointer,
|
|
530
|
-
) ?? null);
|
|
531
288
|
}
|
|
532
289
|
}
|
|
533
290
|
|
|
534
|
-
const values = {
|
|
535
|
-
lastProcessedMessageId: forkedPointer,
|
|
536
|
-
lastRunAt: sourceRow.lastRunAt,
|
|
537
|
-
rememberedLog: sourceRow.rememberedLog,
|
|
538
|
-
...(withCursor ? { lastProcessedCreatedAt: forkedCreatedAt } : {}),
|
|
539
|
-
};
|
|
540
|
-
|
|
541
291
|
mdb
|
|
542
292
|
.insert(memoryRetrospectiveState)
|
|
543
|
-
.values({
|
|
293
|
+
.values({
|
|
294
|
+
conversationId: forkedConversationId,
|
|
295
|
+
lastProcessedMessageId: forkedPointer,
|
|
296
|
+
lastRunAt: sourceRow.lastRunAt,
|
|
297
|
+
rememberedLog: sourceRow.rememberedLog,
|
|
298
|
+
})
|
|
544
299
|
.onConflictDoUpdate({
|
|
545
300
|
target: memoryRetrospectiveState.conversationId,
|
|
546
|
-
set:
|
|
301
|
+
set: {
|
|
302
|
+
lastProcessedMessageId: forkedPointer,
|
|
303
|
+
lastRunAt: sourceRow.lastRunAt,
|
|
304
|
+
rememberedLog: sourceRow.rememberedLog,
|
|
305
|
+
},
|
|
547
306
|
})
|
|
548
307
|
.run();
|
|
549
308
|
} catch (err) {
|
|
@@ -78,7 +78,6 @@ import { conversations } from "../../../persistence/schema/index.js";
|
|
|
78
78
|
import { getLogger } from "./logging.js";
|
|
79
79
|
import { countRetrospectiveMessagesAfter } from "./memory-retrospective-accounting.js";
|
|
80
80
|
import { MEMORY_RETROSPECTIVE_SOURCES } from "./memory-retrospective-constants.js";
|
|
81
|
-
import { retrospectiveCursor } from "./memory-retrospective-cursor.js";
|
|
82
81
|
import { enqueueMemoryRetrospectiveIfEnabled } from "./memory-retrospective-enqueue.js";
|
|
83
82
|
import { getRetrospectiveState } from "./memory-retrospective-state.js";
|
|
84
83
|
|
|
@@ -274,7 +273,7 @@ export async function runRetrospectiveSweep(
|
|
|
274
273
|
|
|
275
274
|
const unprocessed = countRetrospectiveMessagesAfter(
|
|
276
275
|
conversationId,
|
|
277
|
-
|
|
276
|
+
state?.lastProcessedMessageId ?? null,
|
|
278
277
|
);
|
|
279
278
|
if (unprocessed === 0) {
|
|
280
279
|
continue;
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
// (success or failure). Prevents tight retry loops across trigger
|
|
10
10
|
// types.
|
|
11
11
|
// 2. Interval threshold: time since last attempt >= `timeThresholdMs`.
|
|
12
|
-
// 3. Message count threshold: new messages since
|
|
13
|
-
//
|
|
14
|
-
// the cursor's row being deleted) >= `messageThreshold`.
|
|
12
|
+
// 3. Message count threshold: new messages since `lastProcessedMessageId`
|
|
13
|
+
// >= `messageThreshold`.
|
|
15
14
|
//
|
|
16
15
|
// First-run case (no state row) skips the cooldown — `lastRunAt = 0` so the
|
|
17
16
|
// gap is effectively `Infinity`. The interval threshold trips immediately;
|
|
@@ -25,7 +24,6 @@
|
|
|
25
24
|
import type { AssistantConfig } from "../../../config/types.js";
|
|
26
25
|
import { getLogger } from "./logging.js";
|
|
27
26
|
import { countRetrospectiveMessagesAfter } from "./memory-retrospective-accounting.js";
|
|
28
|
-
import { retrospectiveCursor } from "./memory-retrospective-cursor.js";
|
|
29
27
|
import { enqueueMemoryRetrospectiveIfEnabled } from "./memory-retrospective-enqueue.js";
|
|
30
28
|
import { getRetrospectiveState } from "./memory-retrospective-state.js";
|
|
31
29
|
|
|
@@ -85,7 +83,7 @@ export function maybeEnqueueRetrospective(
|
|
|
85
83
|
const state = getRetrospectiveState(conversationId);
|
|
86
84
|
const newMessageCount = countRetrospectiveMessagesAfter(
|
|
87
85
|
conversationId,
|
|
88
|
-
|
|
86
|
+
state?.lastProcessedMessageId ?? null,
|
|
89
87
|
);
|
|
90
88
|
if (newMessageCount === 0) {
|
|
91
89
|
return;
|
|
@@ -28,10 +28,7 @@ import { join } from "node:path";
|
|
|
28
28
|
import { usesConceptPageMemory } from "../../../config/memory-v3-gate.js";
|
|
29
29
|
import type { AssistantConfig } from "../../../config/schema.js";
|
|
30
30
|
import { reconcileEmbeddingIdentity } from "../../../daemon/embedding-reconcile.js";
|
|
31
|
-
import {
|
|
32
|
-
refreshSkillCapabilityMemories,
|
|
33
|
-
startWorkspaceSkillMdMtimePoll,
|
|
34
|
-
} from "../../../daemon/skill-memory-refresh.js";
|
|
31
|
+
import { refreshSkillCapabilityMemories } from "../../../daemon/skill-memory-refresh.js";
|
|
35
32
|
import { selectEmbeddingBackend } from "../../../persistence/embeddings/embedding-backend.js";
|
|
36
33
|
import {
|
|
37
34
|
initMessagesLexicalIndex,
|
|
@@ -266,8 +263,6 @@ export async function runMemoryStartup(config: AssistantConfig): Promise<void> {
|
|
|
266
263
|
log.warn({ err }, "Graph capability seeding failed — continuing");
|
|
267
264
|
}
|
|
268
265
|
|
|
269
|
-
startWorkspaceSkillMdMtimePoll();
|
|
270
|
-
|
|
271
266
|
// ---- v1 (legacy engine) — delete with v1 ----
|
|
272
267
|
// Auto-bootstrap: if the graph has no non-procedural nodes but historical
|
|
273
268
|
// segments exist, enqueue a one-time graph_bootstrap job to populate the
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { setConfig } from "../../../../../__tests__/helpers/set-config.js";
|
|
8
8
|
import type { SkillCapabilityInput } from "../skill-content.js";
|
|
9
9
|
|
|
10
10
|
describe("buildSkillContent", () => {
|
|
@@ -90,12 +90,14 @@ describe("augmentMcpSetupDescription", () => {
|
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
test("appends 'Configured: <names>' for mcp-setup with configured servers", async () => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
setConfig("mcp", {
|
|
94
|
+
servers: {
|
|
95
|
+
"example-server": {
|
|
96
|
+
transport: { type: "stdio", command: "example-cmd" },
|
|
97
|
+
},
|
|
98
|
+
"another-server": {
|
|
99
|
+
transport: { type: "stdio", command: "another-cmd" },
|
|
100
|
+
},
|
|
99
101
|
},
|
|
100
102
|
});
|
|
101
103
|
const { augmentMcpSetupDescription } = await import("../skill-content.js");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getConfig } from "../../../../config/loader.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Generic input for building capability statements: the capability fields of
|
|
@@ -92,7 +92,7 @@ export function augmentMcpSetupDescription(
|
|
|
92
92
|
if (input.id !== "mcp-setup") {
|
|
93
93
|
return input;
|
|
94
94
|
}
|
|
95
|
-
const servers =
|
|
95
|
+
const servers = getConfig().mcp?.servers;
|
|
96
96
|
if (!servers) {
|
|
97
97
|
return input;
|
|
98
98
|
}
|