@vellumai/assistant 0.6.2 → 0.6.4
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/ARCHITECTURE.md +273 -10
- package/Dockerfile +2 -3
- package/bun.lock +41 -49
- package/bunfig.toml +3 -0
- package/docs/architecture/memory.md +1 -1
- package/docs/backup-troubleshooting.md +52 -0
- package/docs/browser-use-architecture-phase2.md +174 -0
- package/docs/stt-provider-onboarding.md +120 -0
- package/knip.json +12 -2
- package/node_modules/@vellumai/ces-contracts/bun.lock +8 -6
- package/node_modules/@vellumai/ces-contracts/package.json +3 -3
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +1111 -86
- package/package.json +40 -42
- package/scripts/generate-openapi.ts +0 -2
- package/scripts/test.sh +73 -18
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/agent-image-optimize.test.ts +28 -0
- package/src/__tests__/agent-loop.test.ts +123 -0
- package/src/__tests__/anthropic-provider.test.ts +263 -10
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +550 -0
- package/src/__tests__/auto-analysis-prompt.test.ts +50 -0
- package/src/__tests__/browser-fill-credential.test.ts +240 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
- package/src/__tests__/browser-skill-endstate.test.ts +31 -7
- package/src/__tests__/btw-routes.test.ts +7 -0
- package/src/__tests__/call-controller.test.ts +581 -20
- package/src/__tests__/catalog-files.test.ts +1000 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/channel-invite-transport.test.ts +2 -2
- package/src/__tests__/channel-readiness-routes.test.ts +16 -20
- package/src/__tests__/channel-readiness-service.test.ts +12 -7
- package/src/__tests__/checker.test.ts +157 -10
- package/src/__tests__/clawhub-files.test.ts +347 -0
- package/src/__tests__/commit-message-enrichment-service.test.ts +36 -19
- package/src/__tests__/config-analysis.test.ts +100 -0
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +1248 -224
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +339 -0
- package/src/__tests__/config-watcher.test.ts +43 -8
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/contact-store-user-file.test.ts +512 -0
- package/src/__tests__/contacts-write.test.ts +197 -0
- package/src/__tests__/context-overflow-approval.test.ts +16 -1
- package/src/__tests__/context-window-manager.test.ts +88 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +99 -3
- package/src/__tests__/conversation-analysis-routes.test.ts +2 -2
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +290 -0
- package/src/__tests__/conversation-error.test.ts +70 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +12 -4
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +6 -1
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-launcher-skill-regression.test.ts +51 -0
- package/src/__tests__/conversation-list-source.test.ts +145 -0
- package/src/__tests__/conversation-pre-run-repair.test.ts +2 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
- package/src/__tests__/conversation-queue.test.ts +946 -62
- package/src/__tests__/conversation-routes-disk-view.test.ts +275 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +324 -46
- package/src/__tests__/conversation-skill-tools.test.ts +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +33 -0
- package/src/__tests__/conversation-slash-queue.test.ts +89 -18
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -1
- package/src/__tests__/credential-health-service.test.ts +352 -0
- package/src/__tests__/credential-security-invariants.test.ts +6 -3
- package/src/__tests__/credential-vault-unit.test.ts +383 -7
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +42 -18
- package/src/__tests__/cross-provider-web-search.test.ts +146 -35
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/deterministic-verification-control-plane.test.ts +10 -1
- package/src/__tests__/device-id.test.ts +112 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +167 -4
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +1 -3
- package/src/__tests__/email-html-renderer.test.ts +71 -0
- package/src/__tests__/email-invite-adapter.test.ts +36 -32
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/emit-event-signal.test.ts +71 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +222 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +386 -0
- package/src/__tests__/gateway-only-enforcement.test.ts +206 -1
- package/src/__tests__/gateway-only-guard.test.ts +2 -0
- package/src/__tests__/gemini-provider.test.ts +66 -2
- package/src/__tests__/get-skill-detail-audit.test.ts +325 -0
- package/src/__tests__/gmail-archive-fallback.test.ts +193 -0
- package/src/__tests__/gmail-archive-gate.test.ts +246 -0
- package/src/__tests__/gmail-preferences.test.ts +117 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +738 -359
- package/src/__tests__/headless-browser-mode.test.ts +614 -0
- package/src/__tests__/headless-browser-navigate.test.ts +528 -49
- package/src/__tests__/headless-browser-read-tools.test.ts +274 -100
- package/src/__tests__/headless-browser-snapshot.test.ts +250 -77
- package/src/__tests__/heartbeat-service.test.ts +70 -17
- package/src/__tests__/home-state-routes.test.ts +162 -0
- package/src/__tests__/host-bash-proxy.test.ts +145 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +596 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +423 -0
- package/src/__tests__/host-cu-proxy.test.ts +166 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/identity-intro-cache.test.ts +40 -10
- package/src/__tests__/init-feature-flag-overrides.test.ts +38 -112
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +141 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/llm-context-normalization.test.ts +488 -0
- package/src/__tests__/llm-context-route-provider.test.ts +86 -5
- package/src/__tests__/llm-usage-store.test.ts +363 -0
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/media-stream-output.test.ts +555 -0
- package/src/__tests__/media-stream-parser.test.ts +374 -0
- package/src/__tests__/media-stream-server-integration.test.ts +1234 -0
- package/src/__tests__/media-stream-stt-session.test.ts +588 -0
- package/src/__tests__/media-turn-detector.test.ts +440 -0
- package/src/__tests__/message-queue.test.ts +125 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +67 -8
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +109 -7
- package/src/__tests__/migration-import-preflight-http.test.ts +6 -5
- package/src/__tests__/migration-validate-http.test.ts +3 -3
- package/src/__tests__/mock-gateway-ipc.ts +151 -0
- package/src/__tests__/model-intents.test.ts +2 -2
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/oauth-apps-routes.test.ts +18 -12
- package/src/__tests__/oauth-cli.test.ts +709 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +118 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +147 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +52 -14
- package/src/__tests__/oauth-store.test.ts +1465 -176
- package/src/__tests__/oauth2-gateway-transport.test.ts +460 -26
- package/src/__tests__/onboarding-template-contract.test.ts +81 -70
- package/src/__tests__/openai-provider.test.ts +178 -2
- package/src/__tests__/openai-responses-cutover-guard.test.ts +184 -0
- package/src/__tests__/openai-responses-provider.test.ts +1105 -0
- package/src/__tests__/openrouter-token-estimation.test.ts +100 -0
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +32 -3
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/persona-resolver.test.ts +251 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +4 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/platform.test.ts +92 -1
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +343 -0
- package/src/__tests__/prechat-onboarding-contract.test.ts +267 -0
- package/src/__tests__/pricing.test.ts +174 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/qdrant-manager.test.ts +29 -8
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +194 -0
- package/src/__tests__/relationship-state-contract.test.ts +175 -0
- package/src/__tests__/relay-server.test.ts +423 -5
- package/src/__tests__/require-fresh-approval.test.ts +40 -1
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/search-skills-unified.test.ts +118 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/secret-scanner-executor.test.ts +4 -0
- package/src/__tests__/secure-keys.test.ts +107 -0
- package/src/__tests__/send-endpoint-busy.test.ts +8 -1
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +49 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/settings-routes.test.ts +201 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +801 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +738 -0
- package/src/__tests__/skills.test.ts +5 -2
- package/src/__tests__/skillssh-files.test.ts +446 -0
- package/src/__tests__/slack-block-formatting.test.ts +110 -0
- package/src/__tests__/slack-channel-config.test.ts +576 -16
- package/src/__tests__/stt-catalog-parity.test.ts +282 -0
- package/src/__tests__/stt-stream-session.test.ts +535 -0
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +184 -27
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/telephony-stt-routing.test.ts +329 -0
- package/src/__tests__/terminal-tools.test.ts +25 -5
- package/src/__tests__/test-preload.ts +18 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +4 -1
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +9 -5
- package/src/__tests__/tool-executor-shell-integration.test.ts +4 -0
- package/src/__tests__/tool-executor.test.ts +33 -24
- package/src/__tests__/tool-result-truncation.test.ts +36 -0
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +14 -29
- package/src/__tests__/trust-store.test.ts +7 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/tts-catalog-parity.test.ts +345 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +512 -114
- package/src/__tests__/twilio-routes.test.ts +376 -0
- package/src/__tests__/unicode.test.ts +293 -0
- package/src/__tests__/update-bulletin-format.test.ts +59 -0
- package/src/__tests__/update-bulletin.test.ts +206 -5
- package/src/__tests__/usage-routes.test.ts +25 -4
- package/src/__tests__/user-reference.test.ts +46 -61
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -0
- package/src/__tests__/voice-config-update.test.ts +403 -0
- package/src/__tests__/voice-quality.test.ts +434 -19
- package/src/__tests__/workspace-heartbeat-service.test.ts +7 -0
- package/src/__tests__/workspace-migration-033-stt-service-explicit-config.test.ts +547 -0
- package/src/__tests__/workspace-migration-034-remove-calls-voice-transcription-provider.test.ts +596 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +368 -0
- package/src/__tests__/workspace-migration-meets.test.ts +244 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +14 -20
- package/src/__tests__/workspace-policy.test.ts +2 -0
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/image-optimize.ts +24 -12
- package/src/agent/loop.ts +55 -9
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/backup/__tests__/backup-key.test.ts +152 -0
- package/src/backup/__tests__/backup-worker.test.ts +767 -0
- package/src/backup/__tests__/list-snapshots.test.ts +87 -0
- package/src/backup/__tests__/local-writer.test.ts +218 -0
- package/src/backup/__tests__/offsite-writer.test.ts +641 -0
- package/src/backup/__tests__/paths.test.ts +300 -0
- package/src/backup/__tests__/restore.test.ts +498 -0
- package/src/backup/__tests__/snapshot-lock.test.ts +352 -0
- package/src/backup/__tests__/stream-crypt.test.ts +228 -0
- package/src/backup/backup-key.ts +137 -0
- package/src/backup/backup-worker.ts +459 -0
- package/src/backup/list-snapshots.ts +147 -0
- package/src/backup/local-writer.ts +133 -0
- package/src/backup/offsite-writer.ts +222 -0
- package/src/backup/paths.ts +226 -0
- package/src/backup/restore.ts +322 -0
- package/src/backup/snapshot-lock.ts +431 -0
- package/src/backup/stream-crypt.ts +263 -0
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/bundler/package-resolver.ts +4 -0
- package/src/calls/audio-store.ts +11 -5
- package/src/calls/call-controller.ts +226 -71
- package/src/calls/call-domain.ts +9 -0
- package/src/calls/call-speech-output.ts +190 -0
- package/src/calls/call-transport.ts +77 -0
- package/src/calls/media-stream-audio-transcode.ts +173 -0
- package/src/calls/media-stream-output.ts +660 -0
- package/src/calls/media-stream-parser.ts +300 -0
- package/src/calls/media-stream-protocol.ts +166 -0
- package/src/calls/media-stream-server.ts +592 -0
- package/src/calls/media-stream-stt-session.ts +460 -0
- package/src/calls/media-turn-detector.ts +230 -0
- package/src/calls/relay-server.ts +90 -75
- package/src/calls/resolve-call-tts-provider.ts +136 -0
- package/src/calls/telephony-stt-routing.ts +145 -0
- package/src/calls/tts-call-strategy.ts +161 -0
- package/src/calls/tts-text-sanitizer.ts +32 -16
- package/src/calls/twilio-routes.ts +281 -17
- package/src/calls/voice-quality.ts +78 -35
- package/src/calls/voice-session-bridge.ts +8 -1
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +69 -3
- package/src/cli/__tests__/run-assistant-command.ts +11 -1
- package/src/cli/commands/__tests__/backup.test.ts +1165 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +234 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +132 -0
- package/src/cli/commands/__tests__/email-attachment.test.ts +422 -0
- package/src/cli/commands/__tests__/email-download.test.ts +16 -1
- package/src/cli/commands/__tests__/email-list.test.ts +22 -4
- package/src/cli/commands/__tests__/email-register.test.ts +4 -4
- package/src/cli/commands/__tests__/email-send.test.ts +37 -4
- package/src/cli/commands/__tests__/email-status.test.ts +5 -1
- package/src/cli/commands/__tests__/email-unregister.test.ts +34 -5
- package/src/cli/commands/backup.ts +993 -0
- package/src/cli/commands/conversations.ts +77 -0
- package/src/cli/commands/credentials.ts +3 -4
- package/src/cli/commands/domain.ts +210 -0
- package/src/cli/commands/email.ts +273 -16
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +56 -44
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +32 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +330 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +117 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +6 -3
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/mode.ts +12 -3
- package/src/cli/commands/oauth/providers.ts +215 -36
- package/src/cli/commands/oauth/shared.ts +7 -6
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +254 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +6 -0
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +6 -0
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +30 -4
- package/src/config/__tests__/backup-schema.test.ts +134 -0
- package/src/config/assistant-feature-flags.ts +61 -62
- package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +141 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/browser/SKILL.md +30 -5
- package/src/config/bundled-skills/browser/TOOLS.json +123 -0
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-status.ts +12 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +17 -0
- package/src/config/bundled-skills/contacts/SKILL.md +5 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +54 -8
- package/src/config/bundled-skills/gmail/TOOLS.json +33 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +116 -9
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +138 -11
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +59 -0
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +82 -0
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +113 -17
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +3 -9
- package/src/config/bundled-skills/media-processing/TOOLS.json +1 -6
- package/src/config/bundled-skills/media-processing/__tests__/audio-transcribe.test.ts +125 -0
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +181 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess-audio.test.ts +141 -0
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +32 -87
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +8 -4
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +0 -10
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/outlook/SKILL.md +9 -2
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +2 -2
- package/src/config/bundled-skills/phone-calls/SKILL.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +27 -18
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +26 -22
- package/src/config/bundled-skills/slack/SKILL.md +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/bundled-skills/transcribe/SKILL.md +9 -14
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -7
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +256 -0
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +38 -188
- package/src/config/bundled-tool-registry.ts +8 -0
- package/src/config/env-registry.ts +38 -0
- package/src/config/env.ts +49 -4
- package/src/config/feature-flag-registry.json +85 -14
- package/src/config/loader.ts +82 -13
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +81 -15
- package/src/config/schemas/__tests__/stt.test.ts +43 -0
- package/src/config/schemas/analysis.ts +51 -0
- package/src/config/schemas/backup.ts +72 -0
- package/src/config/schemas/calls.ts +1 -26
- package/src/config/schemas/elevenlabs.ts +0 -59
- package/src/config/schemas/filing.ts +47 -7
- package/src/config/schemas/heartbeat.ts +27 -5
- package/src/config/schemas/host-browser.ts +112 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/memory-lifecycle.ts +14 -2
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +52 -0
- package/src/config/schemas/stt.ts +59 -0
- package/src/config/schemas/tts.ts +230 -0
- package/src/config/schemas/updates.ts +14 -0
- package/src/config/skills.ts +4 -0
- package/src/config/types.ts +4 -1
- package/src/contacts/contact-store.ts +56 -11
- package/src/contacts/contacts-write.ts +38 -1
- package/src/context/post-turn-tool-result-truncation.ts +177 -0
- package/src/context/tool-result-truncation.ts +2 -1
- package/src/context/window-manager.ts +61 -10
- package/src/credential-execution/approval-bridge.ts +49 -15
- package/src/credential-execution/executable-discovery.ts +12 -2
- package/src/credential-execution/process-manager.ts +33 -2
- package/src/credential-health/credential-health-service.ts +366 -0
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +324 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +497 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +195 -0
- package/src/daemon/__tests__/lifecycle-startup-ordering.test.ts +127 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +99 -5
- package/src/daemon/context-overflow-approval.ts +5 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +23 -2
- package/src/daemon/conversation-agent-loop.ts +153 -42
- package/src/daemon/conversation-attachments.ts +40 -0
- package/src/daemon/conversation-error.ts +11 -0
- package/src/daemon/conversation-history.ts +40 -6
- package/src/daemon/conversation-launch.ts +220 -0
- package/src/daemon/conversation-lifecycle.ts +59 -9
- package/src/daemon/conversation-messaging.ts +37 -3
- package/src/daemon/conversation-notifiers.ts +5 -0
- package/src/daemon/conversation-process.ts +622 -13
- package/src/daemon/conversation-queue-manager.ts +24 -0
- package/src/daemon/conversation-runtime-assembly.ts +128 -36
- package/src/daemon/conversation-slash.ts +36 -0
- package/src/daemon/conversation-surfaces.ts +131 -40
- package/src/daemon/conversation-tool-setup.ts +99 -8
- package/src/daemon/conversation-usage.ts +7 -4
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +292 -16
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/config-slack-channel.ts +269 -94
- package/src/daemon/handlers/conversations.ts +13 -141
- package/src/daemon/handlers/shared.ts +80 -0
- package/src/daemon/handlers/skills.ts +483 -44
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +192 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +179 -28
- package/src/daemon/message-protocol.ts +13 -0
- package/src/daemon/message-types/conversations.ts +89 -14
- package/src/daemon/message-types/home.ts +40 -0
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/meet.ts +143 -0
- package/src/daemon/message-types/messages.ts +19 -5
- package/src/daemon/message-types/schedules.ts +34 -2
- package/src/daemon/message-types/skills.ts +26 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/server.ts +439 -14
- package/src/daemon/shutdown-handlers.ts +32 -4
- package/src/daemon/shutdown-registry.ts +40 -0
- package/src/daemon/tool-side-effects.ts +15 -0
- package/src/daemon/transport-hints.ts +5 -24
- package/src/email/html-renderer.ts +76 -0
- package/src/heartbeat/heartbeat-service.ts +93 -7
- package/src/home/__tests__/assistant-feed-authoring.test.ts +156 -0
- package/src/home/__tests__/emit-feed-event.test.ts +169 -0
- package/src/home/__tests__/feed-scheduler.test.ts +194 -0
- package/src/home/__tests__/feed-types.test.ts +275 -0
- package/src/home/__tests__/feed-writer.test.ts +688 -0
- package/src/home/__tests__/phase5-exit-criteria.test.ts +212 -0
- package/src/home/__tests__/platform-gmail-digest.test.ts +222 -0
- package/src/home/__tests__/progress-formula.test.ts +213 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +740 -0
- package/src/home/__tests__/rollup-producer.test.ts +398 -0
- package/src/home/assistant-feed-authoring.ts +124 -0
- package/src/home/emit-feed-event.ts +158 -0
- package/src/home/feed-scheduler.ts +247 -0
- package/src/home/feed-types.ts +181 -0
- package/src/home/feed-writer.ts +469 -0
- package/src/home/platform-gmail-digest.ts +163 -0
- package/src/home/progress-formula.ts +86 -0
- package/src/home/relationship-state-writer.ts +824 -0
- package/src/home/relationship-state.ts +143 -0
- package/src/home/rollup-producer.ts +384 -0
- package/src/hooks/runner.ts +7 -0
- package/src/inbound/platform-callback-registration.ts +30 -20
- package/src/inbound/public-ingress-urls.ts +12 -0
- package/src/instrument.ts +1 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +200 -0
- package/src/ipc/cli-client.ts +151 -0
- package/src/ipc/cli-server.ts +234 -0
- package/src/ipc/gateway-client.ts +180 -0
- package/src/ipc/routes/index.ts +5 -0
- package/src/ipc/routes/wake-conversation.ts +19 -0
- package/src/mcp/client.ts +59 -24
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +356 -0
- package/src/memory/__tests__/auto-analysis-guard.test.ts +57 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +232 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +196 -0
- package/src/memory/app-store.ts +31 -1
- package/src/memory/attachments-store.ts +70 -0
- package/src/memory/auto-analysis-enqueue.ts +127 -0
- package/src/memory/auto-analysis-guard.ts +27 -0
- package/src/memory/cleanup-schedule-state.ts +37 -0
- package/src/memory/conversation-analyze-job.ts +73 -0
- package/src/memory/conversation-crud.ts +122 -0
- package/src/memory/conversation-disk-view.ts +7 -0
- package/src/memory/conversation-group-migration.ts +34 -2
- package/src/memory/conversation-queries.ts +6 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +18 -0
- package/src/memory/db-maintenance.ts +108 -0
- package/src/memory/db.ts +1 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +176 -17
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/conversation-graph-memory.ts +15 -0
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/extraction.test.ts +23 -0
- package/src/memory/graph/extraction.ts +8 -0
- package/src/memory/graph/retriever.ts +67 -40
- package/src/memory/graph/scoring.test.ts +186 -0
- package/src/memory/graph/scoring.ts +31 -1
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/graph/tools.ts +1 -1
- package/src/memory/group-crud.ts +6 -1
- package/src/memory/indexer.ts +95 -16
- package/src/memory/job-handlers/cleanup.ts +11 -8
- package/src/memory/job-handlers/conversation-starters.ts +16 -10
- package/src/memory/jobs-store.ts +64 -4
- package/src/memory/jobs-worker.ts +22 -9
- package/src/memory/llm-usage-store.ts +137 -60
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/219-oauth-providers-token-exchange-body-format.ts +15 -0
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +190 -0
- package/src/memory/migrations/221-conversations-archived-at.ts +16 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-manager.ts +43 -16
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/oauth.ts +21 -13
- package/src/memory/usage-buckets.ts +396 -0
- package/src/messaging/providers/gmail/client.ts +57 -6
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +282 -0
- package/src/messaging/providers/slack/adapter.ts +143 -38
- package/src/messaging/providers/slack/client.ts +16 -0
- package/src/messaging/providers/slack/types.ts +4 -0
- package/src/notifications/decision-engine.ts +3 -3
- package/src/notifications/signal.ts +5 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +25 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +26 -9
- package/src/oauth/byo-connection.ts +10 -8
- package/src/oauth/connect-orchestrator.ts +25 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +22 -18
- package/src/oauth/connection.ts +3 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +223 -100
- package/src/oauth/platform-connection.test.ts +101 -3
- package/src/oauth/platform-connection.ts +56 -35
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +133 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +16 -6
- package/src/permissions/defaults.ts +49 -1
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -1
- package/src/permissions/trust-store.ts +3 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/permissions/workspace-policy.ts +3 -0
- package/src/platform/client.test.ts +10 -0
- package/src/platform/sync-identity.ts +129 -0
- package/src/prompts/persona-resolver.ts +126 -2
- package/src/prompts/system-prompt.ts +76 -38
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -105
- package/src/prompts/templates/SOUL.md +3 -1
- package/src/prompts/templates/UPDATES.md +12 -0
- package/src/prompts/templates/channels/slack.md +20 -0
- package/src/prompts/update-bulletin-format.ts +26 -9
- package/src/prompts/update-bulletin.ts +34 -23
- package/src/prompts/user-reference.ts +20 -17
- package/src/providers/__tests__/provider-secret-catalog.test.ts +42 -0
- package/src/providers/anthropic/client.ts +157 -60
- package/src/providers/fireworks/client.ts +2 -2
- package/src/providers/gemini/client.ts +9 -1
- package/src/providers/model-catalog.ts +6 -0
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/ollama/client.ts +2 -2
- package/src/providers/openai/chat-completions-provider.ts +474 -0
- package/src/providers/openai/client.ts +25 -440
- package/src/providers/openai/responses-provider.ts +502 -0
- package/src/providers/openrouter/client.ts +101 -4
- package/src/providers/provider-secret-catalog.ts +139 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/retry.ts +14 -3
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +251 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +828 -0
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +980 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +767 -0
- package/src/providers/speech-to-text/deepgram.test.ts +332 -0
- package/src/providers/speech-to-text/deepgram.ts +115 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +743 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +625 -0
- package/src/providers/speech-to-text/google-gemini.test.ts +226 -0
- package/src/providers/speech-to-text/google-gemini.ts +101 -0
- package/src/providers/speech-to-text/openai-whisper-stream.test.ts +564 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +381 -0
- package/src/providers/speech-to-text/openai-whisper.test.ts +1 -37
- package/src/providers/speech-to-text/openai-whisper.ts +63 -33
- package/src/providers/speech-to-text/provider-catalog.ts +306 -0
- package/src/providers/speech-to-text/resolve.ts +386 -6
- package/src/providers/types.ts +10 -1
- package/src/runtime/AGENTS.md +65 -0
- package/src/runtime/__tests__/agent-wake.test.ts +831 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/__tests__/runtime-mode.test.ts +62 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +481 -0
- package/src/runtime/agent-wake.ts +512 -0
- package/src/runtime/assistant-event-hub.ts +2 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +48 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +33 -9
- package/src/runtime/auth/token-service.ts +56 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/channel-invite-transport.ts +1 -1
- package/src/runtime/channel-invite-transports/email.ts +14 -6
- package/src/runtime/channel-readiness-service.ts +12 -22
- package/src/runtime/chrome-extension-registry.ts +368 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +815 -75
- package/src/runtime/http-types.ts +6 -2
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +198 -0
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +360 -0
- package/src/runtime/migrations/migration-transport.ts +7 -0
- package/src/runtime/migrations/migration-wizard.ts +23 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +96 -1
- package/src/runtime/migrations/vbundle-importer.ts +89 -5
- package/src/runtime/pending-interactions.ts +18 -13
- package/src/runtime/routes/__tests__/backup-routes.test.ts +967 -0
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +507 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +208 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +406 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +474 -0
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +148 -17
- package/src/runtime/routes/app-management-routes.ts +12 -18
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/attachment-routes.test.ts +9 -3
- package/src/runtime/routes/attachment-routes.ts +216 -17
- package/src/runtime/routes/backup-routes.ts +519 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +556 -0
- package/src/runtime/routes/btw-routes.ts +8 -6
- package/src/runtime/routes/contact-routes.test.ts +298 -0
- package/src/runtime/routes/contact-routes.ts +132 -5
- package/src/runtime/routes/conversation-analysis-routes.ts +22 -141
- package/src/runtime/routes/conversation-management-routes.ts +223 -0
- package/src/runtime/routes/conversation-routes.ts +598 -103
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/filing-routes.ts +93 -0
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/home-feed-routes.ts +334 -0
- package/src/runtime/routes/home-state-routes.ts +138 -0
- package/src/runtime/routes/host-browser-routes.ts +268 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-intro-cache.ts +7 -3
- package/src/runtime/routes/identity-routes.ts +262 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +46 -39
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +15 -15
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +137 -0
- package/src/runtime/routes/integrations/slack/__tests__/share.test.ts +179 -0
- package/src/runtime/routes/integrations/slack/channel.ts +11 -3
- package/src/runtime/routes/integrations/slack/share.ts +45 -7
- package/src/runtime/routes/llm-context-normalization.ts +303 -0
- package/src/runtime/routes/log-export-routes.ts +42 -22
- package/src/runtime/routes/memory-item-routes.test.ts +3 -2
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +122 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +31 -102
- package/src/runtime/routes/skills-routes.ts +128 -9
- package/src/runtime/routes/stt-routes.ts +233 -0
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/surface-action-routes.ts +41 -2
- package/src/runtime/routes/tts-routes.ts +108 -24
- package/src/runtime/routes/usage-routes.ts +38 -9
- package/src/runtime/routes/user-route-dispatcher.ts +50 -5
- package/src/runtime/routes/user-routes.ts +13 -1
- package/src/runtime/routes/work-items-routes.ts +8 -1
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/runtime/runtime-mode.ts +33 -0
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +444 -0
- package/src/runtime/services/__tests__/analyze-deps-singleton.test.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-prompt.test.ts +53 -0
- package/src/runtime/services/__tests__/manual-analysis-prompt.test.ts +41 -0
- package/src/runtime/services/analyze-conversation.ts +344 -0
- package/src/runtime/services/analyze-deps-singleton.ts +32 -0
- package/src/runtime/services/auto-analysis-prompt.ts +55 -0
- package/src/runtime/skill-route-registry.ts +49 -0
- package/src/runtime/slack-block-formatting.ts +437 -10
- package/src/schedule/scheduler.ts +57 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +68 -29
- package/src/security/secure-keys.ts +143 -27
- package/src/security/token-manager.ts +31 -10
- package/src/sequence/engine.ts +23 -0
- package/src/sequence/types.ts +1 -1
- package/src/skills/catalog-files.ts +554 -0
- package/src/skills/category-inference.ts +122 -0
- package/src/skills/clawhub-files.ts +213 -0
- package/src/skills/clawhub.ts +84 -23
- package/src/skills/skill-file-provider.ts +40 -0
- package/src/skills/skillssh-files.ts +395 -0
- package/src/skills/skillssh-registry.ts +4 -4
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +392 -0
- package/src/stt/__tests__/types.test.ts +89 -0
- package/src/stt/daemon-batch-transcriber.ts +195 -0
- package/src/stt/stt-stream-session.ts +499 -0
- package/src/stt/types.ts +330 -0
- package/src/stt/wav-encoder.test.ts +373 -0
- package/src/stt/wav-encoder.ts +175 -0
- package/src/subagent/manager.ts +169 -40
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/__tests__/browser-mode.test.ts +119 -0
- package/src/tools/browser/__tests__/browser-status.test.ts +123 -0
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +1787 -342
- package/src/tools/browser/browser-manager.ts +81 -12
- package/src/tools/browser/browser-mode-constants.ts +12 -0
- package/src/tools/browser/browser-mode.ts +92 -0
- package/src/tools/browser/browser-status-constants.ts +33 -0
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1263 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +359 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +1993 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +1007 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +744 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +868 -0
- package/src/tools/browser/cdp-client/errors.ts +49 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +148 -0
- package/src/tools/browser/cdp-client/factory.ts +914 -0
- package/src/tools/browser/cdp-client/index.ts +28 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +120 -0
- package/src/tools/credentials/vault.ts +35 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/network/web-fetch.ts +5 -2
- package/src/tools/network/web-search.ts +5 -2
- package/src/tools/permission-checker.ts +77 -82
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -0
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/shared/shell-output.ts +3 -1
- package/src/tools/side-effects.ts +2 -0
- package/src/tools/skills/sandbox-runner.ts +3 -2
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +15 -0
- package/src/tools/terminal/shell.ts +36 -20
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/tool-manifest.ts +21 -0
- package/src/tools/types.ts +19 -0
- package/src/tools/ui-surface/definitions.ts +6 -1
- package/src/tts/__tests__/provider-adapters.test.ts +834 -0
- package/src/tts/__tests__/provider-catalog-consistency.test.ts +196 -0
- package/src/tts/__tests__/provider-catalog.test.ts +183 -0
- package/src/tts/__tests__/provider-registry.test.ts +90 -0
- package/src/tts/provider-catalog.ts +201 -0
- package/src/tts/provider-registry.ts +73 -0
- package/src/tts/providers/deepgram-provider.ts +219 -0
- package/src/tts/providers/elevenlabs-provider.ts +211 -0
- package/src/tts/providers/fish-audio-provider.ts +183 -0
- package/src/tts/providers/index.ts +42 -0
- package/src/tts/providers/register-builtins.ts +130 -0
- package/src/tts/synthesize-text.ts +110 -0
- package/src/tts/tts-config-resolver.ts +78 -0
- package/src/tts/types.ts +153 -0
- package/src/types/onboarding-context.ts +7 -0
- package/src/util/abort-reasons.ts +58 -0
- package/src/util/device-id.ts +32 -16
- package/src/util/errors.ts +9 -1
- package/src/util/platform.ts +63 -24
- package/src/util/pricing.ts +66 -3
- package/src/util/spawn.ts +1 -1
- package/src/util/truncate.ts +4 -2
- package/src/util/unicode.ts +201 -0
- package/src/version.ts +19 -24
- package/src/watcher/engine.ts +23 -0
- package/src/watcher/watcher-store.ts +31 -0
- package/src/workspace/migrations/003-seed-device-id.ts +9 -3
- package/src/workspace/migrations/017-seed-persona-dirs.ts +68 -4
- package/src/workspace/migrations/029-seed-pkb.ts +1 -1
- package/src/workspace/migrations/031-drop-user-md.ts +317 -0
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +73 -0
- package/src/workspace/migrations/032-tts-provider-unification.ts +227 -0
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +122 -0
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +215 -0
- package/src/workspace/migrations/035-seed-slack-channel-persona.ts +50 -0
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +37 -0
- package/src/workspace/migrations/037-create-meets-dir.ts +61 -0
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/top-level-renderer.ts +31 -1
- package/src/workspace/turn-commit.ts +31 -0
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/email-cli.test.ts +0 -297
- package/src/__tests__/email-service-config-fallback.test.ts +0 -102
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/cli/commands/browser-relay.ts +0 -536
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/email/guardrails.ts +0 -221
- package/src/email/provider.ts +0 -117
- package/src/email/providers/agentmail.ts +0 -361
- package/src/email/providers/index.ts +0 -65
- package/src/email/service.ts +0 -384
- package/src/email/types.ts +0 -126
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/prompts/templates/USER.md +0 -13
- package/src/providers/speech-to-text/types.ts +0 -17
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
readFileSync,
|
|
4
|
+
rmSync,
|
|
5
|
+
unlinkSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
2
8
|
import { join } from "node:path";
|
|
3
9
|
|
|
4
10
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
@@ -83,6 +89,8 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
83
89
|
}
|
|
84
90
|
>();
|
|
85
91
|
private stdoutReaderActive = false;
|
|
92
|
+
private activeEmbeds = 0;
|
|
93
|
+
private disposeRequested = false;
|
|
86
94
|
|
|
87
95
|
private readonly initGuard = new PromiseGuard<void>();
|
|
88
96
|
|
|
@@ -94,6 +102,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
94
102
|
inputs: EmbeddingInput[],
|
|
95
103
|
options?: EmbeddingRequestOptions,
|
|
96
104
|
): Promise<number[][]> {
|
|
105
|
+
if (this.disposeRequested) {
|
|
106
|
+
throw new Error("Local embedding backend is shutting down");
|
|
107
|
+
}
|
|
97
108
|
if (inputs.length === 0) return [];
|
|
98
109
|
|
|
99
110
|
const texts = inputs.map((i) => {
|
|
@@ -106,24 +117,30 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
106
117
|
if (options?.signal?.aborted)
|
|
107
118
|
throw new DOMException("Aborted", "AbortError");
|
|
108
119
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
this.activeEmbeds++;
|
|
121
|
+
try {
|
|
122
|
+
await this.ensureInitialized();
|
|
123
|
+
|
|
124
|
+
const results: number[][] = [];
|
|
125
|
+
const batchSize = 32;
|
|
126
|
+
for (let i = 0; i < texts.length; i += batchSize) {
|
|
127
|
+
if (options?.signal?.aborted)
|
|
128
|
+
throw new DOMException("Aborted", "AbortError");
|
|
129
|
+
const batch = texts.slice(i, i + batchSize);
|
|
130
|
+
const response = await this.sendRequest(batch);
|
|
131
|
+
if (response.error) {
|
|
132
|
+
throw new Error(`Embedding worker error: ${response.error}`);
|
|
133
|
+
}
|
|
134
|
+
if (!response.vectors) {
|
|
135
|
+
throw new Error("Embedding worker returned no vectors");
|
|
136
|
+
}
|
|
137
|
+
results.push(...response.vectors);
|
|
123
138
|
}
|
|
124
|
-
results
|
|
139
|
+
return results;
|
|
140
|
+
} finally {
|
|
141
|
+
this.activeEmbeds--;
|
|
142
|
+
this.disposeIfIdle();
|
|
125
143
|
}
|
|
126
|
-
return results;
|
|
127
144
|
}
|
|
128
145
|
|
|
129
146
|
private sendRequest(texts: string[]): Promise<WorkerResponse> {
|
|
@@ -148,6 +165,11 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
148
165
|
await this.initGuard.run(() => this.initialize());
|
|
149
166
|
}
|
|
150
167
|
|
|
168
|
+
dispose(): void {
|
|
169
|
+
this.disposeRequested = true;
|
|
170
|
+
this.disposeIfIdle();
|
|
171
|
+
}
|
|
172
|
+
|
|
151
173
|
private async initialize(): Promise<void> {
|
|
152
174
|
log.info({ model: this.model }, "Initializing local embedding backend");
|
|
153
175
|
|
|
@@ -199,6 +221,12 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
199
221
|
const embeddingModelsDir = getEmbeddingModelsDir();
|
|
200
222
|
const modelCacheDir = `${embeddingModelsDir}/model-cache`;
|
|
201
223
|
|
|
224
|
+
// Singleton guard: an orphaned embed worker from a previous daemon
|
|
225
|
+
// (e.g. one that crashed without cleanup) may still be running and
|
|
226
|
+
// holding the workspace's PID file. Detect and reclaim it before
|
|
227
|
+
// spawning so we never leave duplicate workers eating CPU/memory.
|
|
228
|
+
this.reclaimStaleWorker(workerPath);
|
|
229
|
+
|
|
202
230
|
log.info(
|
|
203
231
|
{ bunPath, workerPath, model: this.model },
|
|
204
232
|
"Spawning embedding worker process",
|
|
@@ -255,6 +283,8 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
255
283
|
{ pid: proc.pid, model: this.model },
|
|
256
284
|
"Embedding worker process started",
|
|
257
285
|
);
|
|
286
|
+
|
|
287
|
+
this.disposeIfIdle();
|
|
258
288
|
}
|
|
259
289
|
|
|
260
290
|
private drainStderr(stderr: ReadableStream<Uint8Array>): void {
|
|
@@ -355,6 +385,7 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
355
385
|
if (pending) {
|
|
356
386
|
this.pendingRequests.delete(msg.id);
|
|
357
387
|
pending.resolve(msg);
|
|
388
|
+
this.disposeIfIdle();
|
|
358
389
|
}
|
|
359
390
|
}
|
|
360
391
|
}
|
|
@@ -425,4 +456,132 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
425
456
|
// Best-effort
|
|
426
457
|
}
|
|
427
458
|
}
|
|
459
|
+
|
|
460
|
+
/** Read the PID from the on-disk PID file, or null if missing/invalid. */
|
|
461
|
+
private readPidFile(): number | null {
|
|
462
|
+
const path = this.getPidFilePath();
|
|
463
|
+
if (!existsSync(path)) return null;
|
|
464
|
+
try {
|
|
465
|
+
const pid = parseInt(readFileSync(path, "utf-8").trim(), 10);
|
|
466
|
+
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
467
|
+
} catch {
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Verify a PID belongs to this workspace's embed worker before sending
|
|
474
|
+
* signals — defends against PID reuse killing an unrelated process if the
|
|
475
|
+
* original worker exited and the OS recycled the PID.
|
|
476
|
+
*
|
|
477
|
+
* Matching `embed-worker` alone would also match a sibling assistant
|
|
478
|
+
* instance's worker (different VELLUM_WORKSPACE_DIR), so we match against
|
|
479
|
+
* the absolute worker script path, which lives under THIS workspace's
|
|
480
|
+
* embedding-models directory and is therefore unique per instance.
|
|
481
|
+
*/
|
|
482
|
+
private isOurEmbedWorker(pid: number, workerPath: string): boolean {
|
|
483
|
+
try {
|
|
484
|
+
// `-ww` disables column-width truncation. Without it, macOS `ps` clips
|
|
485
|
+
// the command field to the terminal width, which can cut off the
|
|
486
|
+
// workerPath argument and cause this check to spuriously return false
|
|
487
|
+
// for genuine orphans. Same flag is used by daemon-control.ts:123 for
|
|
488
|
+
// exactly this reason.
|
|
489
|
+
const result = Bun.spawnSync({
|
|
490
|
+
cmd: ["ps", "-ww", "-p", String(pid), "-o", "command="],
|
|
491
|
+
stdout: "pipe",
|
|
492
|
+
stderr: "ignore",
|
|
493
|
+
});
|
|
494
|
+
if (result.exitCode !== 0) return false;
|
|
495
|
+
const cmd = new TextDecoder().decode(result.stdout).trim();
|
|
496
|
+
if (!cmd) return false;
|
|
497
|
+
return cmd.includes(workerPath);
|
|
498
|
+
} catch {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* If a previous embed worker is still running for this workspace (orphaned
|
|
505
|
+
* by a crashed daemon, for example), terminate it before spawning a new one
|
|
506
|
+
* so we never end up with duplicate workers competing for the same workspace.
|
|
507
|
+
*
|
|
508
|
+
* Stale PID files (process no longer exists) are silently cleaned up.
|
|
509
|
+
* PIDs that have been recycled to unrelated processes — including embed
|
|
510
|
+
* workers belonging to *other* assistant instances — are left untouched.
|
|
511
|
+
*/
|
|
512
|
+
private reclaimStaleWorker(workerPath: string): void {
|
|
513
|
+
const pid = this.readPidFile();
|
|
514
|
+
if (pid == null) return;
|
|
515
|
+
|
|
516
|
+
// Never signal ourselves — should not happen since the worker is a child
|
|
517
|
+
// process, but guard against logic bugs that would deadlock the daemon.
|
|
518
|
+
if (pid === process.pid) {
|
|
519
|
+
this.removePidFile();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
let isAlive = false;
|
|
524
|
+
try {
|
|
525
|
+
// Signal 0 just probes for liveness without delivering a signal.
|
|
526
|
+
process.kill(pid, 0);
|
|
527
|
+
isAlive = true;
|
|
528
|
+
} catch {
|
|
529
|
+
// ESRCH — no such process. PID file is stale.
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (!isAlive) {
|
|
533
|
+
log.info(
|
|
534
|
+
{ pid, model: this.model },
|
|
535
|
+
"Removing stale embed worker PID file (process no longer exists)",
|
|
536
|
+
);
|
|
537
|
+
this.removePidFile();
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (!this.isOurEmbedWorker(pid, workerPath)) {
|
|
542
|
+
// PID points to something that isn't this workspace's embed worker —
|
|
543
|
+
// either an unrelated process (PID reuse after the original worker
|
|
544
|
+
// exited) or another assistant instance's worker. Either way, don't
|
|
545
|
+
// signal it; just drop the stale file so the new worker can claim it.
|
|
546
|
+
log.warn(
|
|
547
|
+
{ pid, model: this.model },
|
|
548
|
+
"PID file points to a process that is not this workspace's embed worker; clearing without killing",
|
|
549
|
+
);
|
|
550
|
+
this.removePidFile();
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
log.warn(
|
|
555
|
+
{ pid, model: this.model },
|
|
556
|
+
"Found orphaned embed worker from a previous daemon, terminating it",
|
|
557
|
+
);
|
|
558
|
+
try {
|
|
559
|
+
process.kill(pid, "SIGTERM");
|
|
560
|
+
} catch {
|
|
561
|
+
// Race: it exited between the liveness check and the kill — fine.
|
|
562
|
+
}
|
|
563
|
+
this.removePidFile();
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
private disposeIfIdle(): void {
|
|
567
|
+
if (!this.disposeRequested) return;
|
|
568
|
+
if (this.activeEmbeds > 0) return;
|
|
569
|
+
if (this.pendingRequests.size > 0) return;
|
|
570
|
+
if (this.readyResolve || this.readyReject) return;
|
|
571
|
+
|
|
572
|
+
const proc = this.workerProc;
|
|
573
|
+
this.workerProc = null;
|
|
574
|
+
this.stdoutReaderActive = false;
|
|
575
|
+
this.stdoutBuffer = "";
|
|
576
|
+
this.initGuard.reset();
|
|
577
|
+
this.removePidFile();
|
|
578
|
+
|
|
579
|
+
if (!proc) return;
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
proc.kill();
|
|
583
|
+
} catch {
|
|
584
|
+
// Worker may already be exiting
|
|
585
|
+
}
|
|
586
|
+
}
|
|
428
587
|
}
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
// Runs daily (or on demand). Processes nodes in partitions:
|
|
5
5
|
// 1. Recency: nodes from last 7 days — merge duplicates, initial narrative
|
|
6
6
|
// 2. Significance: top N by significance — update narrative arcs
|
|
7
|
-
// 3.
|
|
8
|
-
// 4. Random sample: cross-pollination and pattern detection
|
|
7
|
+
// 3. Random sample: cross-pollination and pattern detection
|
|
9
8
|
//
|
|
10
9
|
// Each partition is a separate LLM call. The LLM produces a MemoryDiff
|
|
11
10
|
// (same format as extraction) that is applied to the graph.
|
|
@@ -91,25 +90,25 @@ Today is ${today}.
|
|
|
91
90
|
|
|
92
91
|
## Your Tasks
|
|
93
92
|
|
|
94
|
-
1. **Merge duplicates**: If two or more nodes describe the same event or fact, merge them into one by:
|
|
93
|
+
1. **Merge duplicates**: If two or more nodes describe the exact same specific event or fact with substantially the same details, merge them into one by:
|
|
95
94
|
- Keeping the richer/more complete version (UPDATE it to incorporate details from duplicates)
|
|
96
95
|
- DELETE the duplicates
|
|
97
96
|
- Preserve the highest significance, reinforcement count, and stability from the merged nodes
|
|
98
|
-
- Create a "supersedes" edge from the surviving node to each deleted node
|
|
97
|
+
- Create a "supersedes" edge from the surviving node to each deleted node
|
|
98
|
+
- Two nodes about the same person or topic but with DIFFERENT details, timestamps, or context are NOT duplicates — leave them both intact.
|
|
99
99
|
|
|
100
|
-
2. **
|
|
100
|
+
2. **Rewrite faded content**: For nodes at "faded" or "gist" fidelity, rewrite their content to be shorter and more abstract — like how a real memory fades. A "faded" memory should be 1-2 sentences. A "gist" memory should be one sentence capturing only the essence.
|
|
101
101
|
|
|
102
102
|
3. **Update narrative roles**: If a node is clearly a turning point, inciting incident, or thesis in a larger story arc, set its narrativeRole and partOfStory.
|
|
103
103
|
|
|
104
|
-
4. **
|
|
105
|
-
|
|
106
|
-
5. **Resolve stale prospective nodes**: If a prospective node (type=prospective) is older than 7 days and has no "resolved-by" edge, it's likely a stale commitment. Downgrade its fidelity to "gist" and rewrite it as a past observation (e.g. "Had planned to X" instead of "Need to X"). If it's already at gist with significance < 0.2, mark it for deletion. If the node has an event_date in the past, clear it by setting event_date to null.
|
|
104
|
+
4. **Resolve stale prospective nodes**: If a prospective node (type=prospective) is older than 7 days and has no "resolved-by" edge, downgrade its fidelity to "gist" and rewrite it as a past observation (e.g. "Had planned to X" instead of "Need to X"). If the node has an event_date in the past, clear it by setting event_date to null.
|
|
107
105
|
|
|
108
106
|
## Constraints
|
|
109
107
|
|
|
110
|
-
- Do NOT create new nodes — consolidation only merges, updates, and
|
|
108
|
+
- Do NOT create new nodes — consolidation only merges, updates, and rewrites
|
|
111
109
|
- Do NOT change a node's type
|
|
112
110
|
- Do NOT increase fidelity (memories only fade, never sharpen)
|
|
111
|
+
- Do NOT delete non-duplicate nodes — only delete the non-survivor in a merge. Fading and eventual cleanup are handled by the decay engine, not consolidation.
|
|
113
112
|
- Preserve first-person prose style in content rewrites
|
|
114
113
|
- When merging, keep the node with higher reinforcementCount as the survivor
|
|
115
114
|
|
|
@@ -159,7 +158,7 @@ const CONSOLIDATE_TOOL_SCHEMA = {
|
|
|
159
158
|
},
|
|
160
159
|
delete_ids: {
|
|
161
160
|
type: "array" as const,
|
|
162
|
-
description: "Node IDs to delete (merged duplicates
|
|
161
|
+
description: "Node IDs to delete (merged duplicates only)",
|
|
163
162
|
items: { type: "string" as const },
|
|
164
163
|
},
|
|
165
164
|
merge_edges: {
|
|
@@ -206,17 +205,6 @@ function getTopSignificanceNodes(
|
|
|
206
205
|
.slice(0, n);
|
|
207
206
|
}
|
|
208
207
|
|
|
209
|
-
function getDecayedNodes(scopeId: string): MemoryNode[] {
|
|
210
|
-
const all = queryNodes({
|
|
211
|
-
scopeId,
|
|
212
|
-
limit: 10000,
|
|
213
|
-
});
|
|
214
|
-
return all.filter(
|
|
215
|
-
(n) =>
|
|
216
|
-
(n.fidelity === "faded" || n.fidelity === "gist") && !isCapabilityNode(n),
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
208
|
function getRandomSample(scopeId: string, n: number = 30): MemoryNode[] {
|
|
221
209
|
const all = queryNodes({
|
|
222
210
|
scopeId,
|
|
@@ -286,7 +274,7 @@ async function identifyDuplicateGroups(
|
|
|
286
274
|
})
|
|
287
275
|
.join("\n");
|
|
288
276
|
|
|
289
|
-
const systemPrompt = `You are scanning a list of memory nodes for DUPLICATES — nodes that describe the same event
|
|
277
|
+
const systemPrompt = `You are scanning a list of memory nodes for DUPLICATES — nodes that describe the exact same specific event or fact. Group duplicates together. Two nodes are duplicates ONLY if they describe the same underlying thing with substantially the same details. Be conservative — nodes about the same person or topic but with different details, timestamps, or context are NOT duplicates. Only include nodes that have at least one true duplicate.`;
|
|
290
278
|
|
|
291
279
|
const response = await provider.sendMessage(
|
|
292
280
|
[userMessage(listing)],
|
|
@@ -657,7 +645,6 @@ export async function runConsolidation(
|
|
|
657
645
|
const partitions: Array<{ name: string; nodes: MemoryNode[] }> = [
|
|
658
646
|
{ name: "recent", nodes: getRecentNodes(scopeId) },
|
|
659
647
|
{ name: "significant", nodes: getTopSignificanceNodes(scopeId) },
|
|
660
|
-
{ name: "decayed", nodes: getDecayedNodes(scopeId) },
|
|
661
648
|
{ name: "random", nodes: getRandomSample(scopeId) },
|
|
662
649
|
];
|
|
663
650
|
|
|
@@ -252,6 +252,21 @@ export class ConversationGraphMemory {
|
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Re-register cached node IDs with the InContextTracker after compaction
|
|
257
|
+
* WITHOUT modifying messages. Use this at post-agent-loop compaction sites
|
|
258
|
+
* where the memory block already survives on the original user message
|
|
259
|
+
* (since `<memory __injected>` is not stripped by stripInjectionsForCompaction).
|
|
260
|
+
*
|
|
261
|
+
* Calling reinjectCachedMemory at these sites would inject a duplicate
|
|
262
|
+
* onto the last user message — which after tool calls is a tool_result,
|
|
263
|
+
* not the original user message.
|
|
264
|
+
*/
|
|
265
|
+
retrackCachedNodes(): void {
|
|
266
|
+
if (this.lastInjectedNodeIds.length === 0) return;
|
|
267
|
+
this.tracker.add(this.lastInjectedNodeIds);
|
|
268
|
+
}
|
|
269
|
+
|
|
255
270
|
/**
|
|
256
271
|
* Main entry point — called on every turn before the LLM sees the messages.
|
|
257
272
|
*
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { AssistantConfig } from "../../config/types.js";
|
|
10
10
|
import { getLogger } from "../../util/logger.js";
|
|
11
11
|
import { getMemoryCheckpoint, setMemoryCheckpoint } from "../checkpoints.js";
|
|
12
|
+
import { maybeEnqueueConversationStartersJob } from "../conversation-starters-cadence.js";
|
|
12
13
|
import { asString } from "../job-utils.js";
|
|
13
14
|
import type { MemoryJob } from "../jobs-store.js";
|
|
14
15
|
import { runGraphExtraction } from "./extraction.js";
|
|
@@ -64,6 +65,20 @@ export async function graphExtractJob(
|
|
|
64
65
|
},
|
|
65
66
|
"Graph extraction job complete",
|
|
66
67
|
);
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
maybeEnqueueConversationStartersJob(scopeId);
|
|
71
|
+
} catch (cadenceErr) {
|
|
72
|
+
log.warn(
|
|
73
|
+
{
|
|
74
|
+
err:
|
|
75
|
+
cadenceErr instanceof Error
|
|
76
|
+
? cadenceErr.message
|
|
77
|
+
: String(cadenceErr),
|
|
78
|
+
},
|
|
79
|
+
"Conversation starters cadence check failed (non-fatal)",
|
|
80
|
+
);
|
|
81
|
+
}
|
|
67
82
|
} catch (err) {
|
|
68
83
|
log.error(
|
|
69
84
|
{ conversationId, err: err instanceof Error ? err.message : String(err) },
|
|
@@ -111,6 +111,29 @@ describe("parseExtractionResponse — node creation", () => {
|
|
|
111
111
|
expect(diff.createNodes[0].stability).toBe(14);
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
+
test("procedural nodes get stability=60", () => {
|
|
115
|
+
const { diff } = parse({
|
|
116
|
+
create_nodes: [
|
|
117
|
+
{
|
|
118
|
+
content: "ffmpeg needs -ac 2 to force stereo output.",
|
|
119
|
+
type: "procedural",
|
|
120
|
+
emotional_charge: {
|
|
121
|
+
valence: 0,
|
|
122
|
+
intensity: 0,
|
|
123
|
+
decay_curve: "linear",
|
|
124
|
+
decay_rate: 0.05,
|
|
125
|
+
},
|
|
126
|
+
significance: 0.5,
|
|
127
|
+
confidence: 0.9,
|
|
128
|
+
source_type: "direct",
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
reinforce_node_ids: [],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(diff.createNodes[0].stability).toBe(60);
|
|
135
|
+
});
|
|
136
|
+
|
|
114
137
|
test("clamps significance to [0, 1]", () => {
|
|
115
138
|
const { diff } = parse({
|
|
116
139
|
create_nodes: [
|
|
@@ -596,6 +596,14 @@ export function parseExtractionResponse(
|
|
|
596
596
|
node.stability = 5;
|
|
597
597
|
}
|
|
598
598
|
|
|
599
|
+
// Procedural nodes (learned skills, how-to knowledge — "ffmpeg needs -ac 2
|
|
600
|
+
// for stereo") encode facts that stay useful long after the moment they
|
|
601
|
+
// were learned. Higher initial stability slows Ebbinghaus decay so they
|
|
602
|
+
// remain retrievable months later without needing explicit reinforcement.
|
|
603
|
+
if (node.type === "procedural") {
|
|
604
|
+
node.stability = 60;
|
|
605
|
+
}
|
|
606
|
+
|
|
599
607
|
diff.createNodes.push(node);
|
|
600
608
|
const nodeIndex = diff.createNodes.length - 1;
|
|
601
609
|
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
computeTemporalBoost,
|
|
26
26
|
PER_TURN_WEIGHTS,
|
|
27
27
|
scoreCandidate,
|
|
28
|
+
weightsForContextLoad,
|
|
28
29
|
} from "./scoring.js";
|
|
29
30
|
import { sampleSerendipity } from "./serendipity.js";
|
|
30
31
|
import { getEdgesForNode, getNodesByIds, queryNodes } from "./store.js";
|
|
@@ -371,8 +372,9 @@ export async function loadContextMemory(
|
|
|
371
372
|
opts: ContextLoadOpts,
|
|
372
373
|
): Promise<ContextLoadResult> {
|
|
373
374
|
const start = Date.now();
|
|
374
|
-
const
|
|
375
|
-
const
|
|
375
|
+
const ctxLoadCfg = opts.config.memory.retrieval.injection.contextLoad;
|
|
376
|
+
const maxNodes = opts.maxNodes ?? ctxLoadCfg.maxNodes;
|
|
377
|
+
const serendipitySlots = opts.serendipitySlots ?? ctxLoadCfg.serendipitySlots;
|
|
376
378
|
const now = new Date();
|
|
377
379
|
const nowMs = now.getTime();
|
|
378
380
|
|
|
@@ -529,15 +531,19 @@ export async function loadContextMemory(
|
|
|
529
531
|
const recency = computeRecencyBoost(node, nowMs);
|
|
530
532
|
|
|
531
533
|
scored.push(
|
|
532
|
-
scoreCandidate(
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
534
|
+
scoreCandidate(
|
|
535
|
+
node,
|
|
536
|
+
{
|
|
537
|
+
semanticSimilarity: semanticSim,
|
|
538
|
+
effectiveSignificance: effectiveSig,
|
|
539
|
+
emotionalIntensity: node.emotionalCharge.intensity,
|
|
540
|
+
temporalBoost: normalizedTemporal,
|
|
541
|
+
recencyBoost: recency,
|
|
542
|
+
triggerBoost,
|
|
543
|
+
activationBoost: activation,
|
|
544
|
+
},
|
|
545
|
+
weightsForContextLoad(node),
|
|
546
|
+
),
|
|
541
547
|
);
|
|
542
548
|
}
|
|
543
549
|
|
|
@@ -547,13 +553,16 @@ export async function loadContextMemory(
|
|
|
547
553
|
// 5b. Reserve slots for skill/CLI capabilities. Queried directly from
|
|
548
554
|
// SQLite — no Qdrant vectors needed — so capabilities surface even on
|
|
549
555
|
// fresh assistants whose embedding jobs haven't completed yet.
|
|
550
|
-
const
|
|
551
|
-
const rawCapabilityNodes =
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
556
|
+
const capabilityReserve = ctxLoadCfg.capabilityReserve;
|
|
557
|
+
const rawCapabilityNodes =
|
|
558
|
+
capabilityReserve > 0
|
|
559
|
+
? queryNodes({
|
|
560
|
+
scopeId: opts.scopeId,
|
|
561
|
+
types: ["procedural"],
|
|
562
|
+
fidelityNot: ["gone"],
|
|
563
|
+
limit: capabilityReserve * 4,
|
|
564
|
+
})
|
|
565
|
+
: [];
|
|
557
566
|
|
|
558
567
|
// Dedup: both seeding systems may create nodes for the same capability.
|
|
559
568
|
// Extract capability ID from content and keep only the first node per ID.
|
|
@@ -574,29 +583,33 @@ export async function loadContextMemory(
|
|
|
574
583
|
|
|
575
584
|
// Rank by semantic similarity when a query vector exists
|
|
576
585
|
let selectedCapabilities: MemoryNode[];
|
|
577
|
-
if (queryVector && capabilityNodes.length >
|
|
586
|
+
if (queryVector && capabilityNodes.length > capabilityReserve) {
|
|
578
587
|
selectedCapabilities = capabilityNodes
|
|
579
588
|
.map((node) => ({ node, sim: semanticCandidateIds.get(node.id) ?? 0 }))
|
|
580
589
|
.sort((a, b) => b.sim - a.sim)
|
|
581
|
-
.slice(0,
|
|
590
|
+
.slice(0, capabilityReserve)
|
|
582
591
|
.map((e) => e.node);
|
|
583
592
|
} else {
|
|
584
|
-
selectedCapabilities = capabilityNodes.slice(0,
|
|
593
|
+
selectedCapabilities = capabilityNodes.slice(0, capabilityReserve);
|
|
585
594
|
}
|
|
586
595
|
|
|
587
596
|
const reservedCapabilities: ScoredNode[] = selectedCapabilities.map(
|
|
588
597
|
(node) => {
|
|
589
598
|
const existing = scored.find((s) => s.node.id === node.id);
|
|
590
599
|
if (existing) return existing;
|
|
591
|
-
return scoreCandidate(
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
+
return scoreCandidate(
|
|
601
|
+
node,
|
|
602
|
+
{
|
|
603
|
+
semanticSimilarity: semanticCandidateIds.get(node.id) ?? 0,
|
|
604
|
+
effectiveSignificance: computeEffectiveSignificance(node, nowMs),
|
|
605
|
+
emotionalIntensity: node.emotionalCharge.intensity,
|
|
606
|
+
temporalBoost: (computeTemporalBoost(node, now) + 1) / 2,
|
|
607
|
+
recencyBoost: 0,
|
|
608
|
+
triggerBoost: 0,
|
|
609
|
+
activationBoost: 0,
|
|
610
|
+
},
|
|
611
|
+
weightsForContextLoad(node),
|
|
612
|
+
);
|
|
600
613
|
},
|
|
601
614
|
);
|
|
602
615
|
|
|
@@ -987,7 +1000,8 @@ export async function retrieveForTurn(
|
|
|
987
1000
|
// 5b. Reserve slots for capability nodes (skills/CLI).
|
|
988
1001
|
// Sourced from vector search candidates — only semantically relevant
|
|
989
1002
|
// capabilities compete for reserved slots.
|
|
990
|
-
const
|
|
1003
|
+
const perTurnCfg = opts.config.memory.retrieval.injection.perTurn;
|
|
1004
|
+
const capabilityReserve = perTurnCfg.capabilityReserve;
|
|
991
1005
|
|
|
992
1006
|
const proceduralCandidates = capabilityCandidates
|
|
993
1007
|
.filter(({ node }) => !opts.tracker.isInContext(node.id))
|
|
@@ -1006,7 +1020,7 @@ export async function retrieveForTurn(
|
|
|
1006
1020
|
}
|
|
1007
1021
|
return true;
|
|
1008
1022
|
})
|
|
1009
|
-
.slice(0,
|
|
1023
|
+
.slice(0, capabilityReserve);
|
|
1010
1024
|
|
|
1011
1025
|
const proceduralScored: ScoredNode[] = rankedProcedural.map(({ node, sim }) =>
|
|
1012
1026
|
scoreCandidate(
|
|
@@ -1033,8 +1047,14 @@ export async function retrieveForTurn(
|
|
|
1033
1047
|
// Sort and apply threshold — pull a wider pool for dedup, then trim
|
|
1034
1048
|
scored.sort((a, b) => b.score - a.score);
|
|
1035
1049
|
const INJECTION_THRESHOLD = 0.3;
|
|
1050
|
+
// Hard cap on candidates fed to the dedup LLM — effectively caps maxNodes
|
|
1036
1051
|
const PRE_DEDUP_POOL = 20;
|
|
1037
|
-
const
|
|
1052
|
+
const maxGeneralNodes = Math.max(
|
|
1053
|
+
0,
|
|
1054
|
+
perTurnCfg.maxNodes -
|
|
1055
|
+
perTurnCfg.serendipitySlots -
|
|
1056
|
+
proceduralInjected.length,
|
|
1057
|
+
);
|
|
1038
1058
|
const pool = scored
|
|
1039
1059
|
.filter((s) => s.score >= INJECTION_THRESHOLD)
|
|
1040
1060
|
.slice(0, PRE_DEDUP_POOL);
|
|
@@ -1042,8 +1062,12 @@ export async function retrieveForTurn(
|
|
|
1042
1062
|
// Dedup + rerank with a fast model when the pool is large enough to warrant it
|
|
1043
1063
|
let injected: ScoredNode[];
|
|
1044
1064
|
let llmDedupApplied = false;
|
|
1045
|
-
if (pool.length >
|
|
1046
|
-
const result = await dedupForTurn(
|
|
1065
|
+
if (pool.length > maxGeneralNodes) {
|
|
1066
|
+
const result = await dedupForTurn(
|
|
1067
|
+
pool,
|
|
1068
|
+
maxGeneralNodes,
|
|
1069
|
+
opts.userLastMessage,
|
|
1070
|
+
);
|
|
1047
1071
|
injected = result.nodes;
|
|
1048
1072
|
llmDedupApplied = result.llmApplied;
|
|
1049
1073
|
} else {
|
|
@@ -1054,17 +1078,17 @@ export async function retrieveForTurn(
|
|
|
1054
1078
|
const generalInjected = injected.filter((s) => !proceduralIds.has(s.node.id));
|
|
1055
1079
|
|
|
1056
1080
|
// Backfill vacated general slots from the remaining pool so we always
|
|
1057
|
-
// return up to
|
|
1081
|
+
// return up to maxGeneralNodes when eligible candidates exist.
|
|
1058
1082
|
// Only skip backfill when LLM dedup genuinely ran — it intentionally rejected
|
|
1059
1083
|
// items as duplicates/irrelevant. When dedupForTurn fell back to a plain
|
|
1060
1084
|
// top-N slice (no provider, tool call failure), backfill is still appropriate.
|
|
1061
|
-
if (generalInjected.length <
|
|
1085
|
+
if (generalInjected.length < maxGeneralNodes && !llmDedupApplied) {
|
|
1062
1086
|
const usedIds = new Set([
|
|
1063
1087
|
...generalInjected.map((s) => s.node.id),
|
|
1064
1088
|
...proceduralIds,
|
|
1065
1089
|
]);
|
|
1066
1090
|
const backfillCandidates = pool.filter((s) => !usedIds.has(s.node.id));
|
|
1067
|
-
const needed =
|
|
1091
|
+
const needed = maxGeneralNodes - generalInjected.length;
|
|
1068
1092
|
for (let i = 0; i < Math.min(needed, backfillCandidates.length); i++) {
|
|
1069
1093
|
generalInjected.push(backfillCandidates[i]);
|
|
1070
1094
|
}
|
|
@@ -1073,11 +1097,14 @@ export async function retrieveForTurn(
|
|
|
1073
1097
|
const allDeterministic = [...generalInjected, ...proceduralInjected];
|
|
1074
1098
|
const deterministicIds = new Set(allDeterministic.map((n) => n.node.id));
|
|
1075
1099
|
|
|
1076
|
-
// Reserve
|
|
1100
|
+
// Reserve serendipity slots from scored candidates not in the deterministic set
|
|
1077
1101
|
const serendipityPool = scored.filter(
|
|
1078
1102
|
(s) => s.score >= INJECTION_THRESHOLD && !deterministicIds.has(s.node.id),
|
|
1079
1103
|
);
|
|
1080
|
-
const serendipityPicks = sampleSerendipity(
|
|
1104
|
+
const serendipityPicks = sampleSerendipity(
|
|
1105
|
+
serendipityPool,
|
|
1106
|
+
perTurnCfg.serendipitySlots,
|
|
1107
|
+
);
|
|
1081
1108
|
const allInjected = [...allDeterministic, ...serendipityPicks];
|
|
1082
1109
|
|
|
1083
1110
|
const TOP_N = 20;
|