@vellumai/assistant 0.5.5 → 0.5.7
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/.env.example +16 -2
- package/ARCHITECTURE.md +6 -75
- package/Dockerfile +4 -5
- package/README.md +0 -2
- package/bun.lock +0 -414
- package/docs/architecture/keychain-broker.md +45 -240
- package/docs/architecture/security.md +0 -17
- package/docs/credential-execution-service.md +2 -2
- package/node_modules/@vellumai/ces-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +119 -0
- package/node_modules/@vellumai/credential-storage/package.json +1 -0
- package/node_modules/@vellumai/egress-proxy/package.json +1 -0
- package/package.json +2 -3
- package/src/__tests__/actor-token-service.test.ts +1 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
- package/src/__tests__/browser-skill-endstate.test.ts +6 -5
- package/src/__tests__/btw-routes.test.ts +0 -39
- package/src/__tests__/call-domain.test.ts +0 -128
- package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -5
- package/src/__tests__/channel-readiness-service.test.ts +1 -60
- package/src/__tests__/checker.test.ts +4 -2
- package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-schema.test.ts +3 -3
- package/src/__tests__/context-window-manager.test.ts +78 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-skill-tools.test.ts +0 -54
- package/src/__tests__/conversation-title-service.test.ts +117 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
- package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
- package/src/__tests__/credential-security-e2e.test.ts +0 -66
- package/src/__tests__/credential-security-invariants.test.ts +4 -45
- package/src/__tests__/credentials-cli.test.ts +78 -0
- package/src/__tests__/db-migration-rollback.test.ts +2015 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +98 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
- package/src/__tests__/guardian-routing-state.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +6 -7
- package/src/__tests__/http-user-message-parity.test.ts +3 -103
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
- package/src/__tests__/intent-routing.test.ts +0 -13
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
- package/src/__tests__/keychain-broker-client.test.ts +161 -22
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
- package/src/__tests__/memory-regressions.test.ts +8 -30
- package/src/__tests__/migration-export-http.test.ts +2 -2
- package/src/__tests__/migration-import-commit-http.test.ts +2 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
- package/src/__tests__/migration-validate-http.test.ts +2 -2
- package/src/__tests__/non-member-access-request.test.ts +0 -5
- package/src/__tests__/notification-decision-fallback.test.ts +4 -0
- package/src/__tests__/notification-decision-identity.test.ts +4 -0
- package/src/__tests__/permission-types.test.ts +1 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
- package/src/__tests__/qdrant-manager.test.ts +28 -2
- package/src/__tests__/registry.test.ts +0 -6
- package/src/__tests__/require-fresh-approval.test.ts +4 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
- package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
- package/src/__tests__/secure-keys.test.ts +83 -263
- package/src/__tests__/shell-identity.test.ts +96 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
- package/src/__tests__/skill-feature-flags.test.ts +46 -45
- package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
- package/src/__tests__/skill-load-inline-command.test.ts +8 -12
- package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
- package/src/__tests__/skill-load-tool.test.ts +0 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
- package/src/__tests__/skills.test.ts +0 -2
- package/src/__tests__/slack-inbound-verification.test.ts +0 -4
- package/src/__tests__/suggestion-routes.test.ts +1 -32
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
- package/src/__tests__/tool-executor.test.ts +4 -0
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
- package/src/__tests__/update-bulletin.test.ts +0 -2
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -6
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +218 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
- package/src/calls/audio-store.test.ts +97 -0
- package/src/calls/audio-store.ts +205 -0
- package/src/calls/call-controller.ts +85 -7
- package/src/calls/call-domain.ts +3 -0
- package/src/calls/call-store.ts +10 -3
- package/src/calls/fish-audio-client.ts +117 -0
- package/src/calls/relay-server.ts +27 -0
- package/src/calls/twilio-routes.ts +2 -1
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-ingress-preflight.ts +0 -42
- package/src/calls/voice-quality.ts +26 -5
- package/src/calls/voice-session-bridge.ts +6 -12
- package/src/cli/commands/config.ts +1 -4
- package/src/cli/commands/conversations.ts +0 -18
- package/src/cli/commands/credentials.ts +34 -4
- package/src/cli/commands/oauth/index.ts +7 -0
- package/src/cli/commands/oauth/platform.ts +179 -0
- package/src/cli/commands/platform.ts +3 -3
- package/src/config/assistant-feature-flags.ts +186 -5
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
- package/src/config/bundled-tool-registry.ts +1 -11
- package/src/config/env-registry.ts +1 -1
- package/src/config/env.ts +16 -16
- package/src/config/feature-flag-registry.json +48 -16
- package/src/config/loader.ts +98 -31
- package/src/config/schema.ts +4 -25
- package/src/config/schemas/calls.ts +13 -0
- package/src/config/schemas/fish-audio.ts +39 -0
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/platform.ts +1 -1
- package/src/config/schemas/security.ts +4 -4
- package/src/config/types.ts +0 -1
- package/src/contacts/contact-store.ts +39 -0
- package/src/contacts/types.ts +2 -0
- package/src/context/window-manager.ts +53 -2
- package/src/credential-execution/approval-bridge.ts +1 -0
- package/src/credential-execution/executable-discovery.ts +28 -4
- package/src/credential-execution/feature-gates.ts +16 -0
- package/src/credential-execution/process-manager.ts +38 -0
- package/src/daemon/assistant-attachments.ts +9 -0
- package/src/daemon/config-watcher.ts +6 -4
- package/src/daemon/conversation-agent-loop.ts +0 -60
- package/src/daemon/conversation-memory.ts +0 -117
- package/src/daemon/conversation-runtime-assembly.ts +0 -2
- package/src/daemon/conversation-tool-setup.ts +0 -105
- package/src/daemon/conversation.ts +10 -1
- package/src/daemon/handlers/config-vercel.ts +92 -0
- package/src/daemon/handlers/conversations.ts +0 -11
- package/src/daemon/handlers/skills.ts +2 -15
- package/src/daemon/install-symlink.ts +195 -0
- package/src/daemon/lifecycle.ts +229 -96
- package/src/daemon/message-types/conversations.ts +3 -4
- package/src/daemon/message-types/diagnostics.ts +3 -22
- package/src/daemon/message-types/messages.ts +0 -2
- package/src/daemon/message-types/upgrades.ts +8 -0
- package/src/daemon/server.ts +30 -92
- package/src/events/domain-events.ts +2 -1
- package/src/followups/followup-store.ts +5 -2
- package/src/inbound/platform-callback-registration.ts +3 -3
- package/src/instrument.ts +8 -5
- package/src/memory/conversation-crud.ts +0 -236
- package/src/memory/conversation-title-service.ts +76 -11
- package/src/memory/db-init.ts +15 -11
- package/src/memory/indexer.ts +15 -106
- package/src/memory/items-extractor.ts +15 -1
- package/src/memory/job-handlers/conversation-starters.ts +4 -1
- package/src/memory/job-handlers/embedding.ts +0 -79
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +30 -13
- package/src/memory/jobs-worker.ts +31 -27
- package/src/memory/migrations/001-job-deferrals.ts +19 -0
- package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
- package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
- package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
- package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
- package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
- package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
- package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
- package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
- package/src/memory/migrations/116-messages-fts.ts +106 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
- package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
- package/src/memory/migrations/141-rename-verification-table.ts +54 -0
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
- package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
- package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
- package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
- package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
- package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
- package/src/memory/migrations/189-drop-simplified-memory.ts +42 -0
- package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
- package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
- package/src/memory/migrations/index.ts +5 -3
- package/src/memory/migrations/registry.ts +90 -0
- package/src/memory/migrations/validate-migration-state.ts +137 -11
- package/src/memory/qdrant-circuit-breaker.ts +9 -0
- package/src/memory/qdrant-client.ts +4 -6
- package/src/memory/qdrant-manager.ts +64 -7
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/conversations.ts +0 -3
- package/src/memory/schema/index.ts +0 -2
- package/src/messaging/draft-store.ts +2 -2
- package/src/notifications/decision-engine.ts +4 -1
- package/src/oauth/connection-resolver.ts +6 -4
- package/src/permissions/checker.ts +0 -38
- package/src/permissions/defaults.ts +3 -3
- package/src/permissions/shell-identity.ts +76 -22
- package/src/permissions/trust-client.ts +2 -13
- package/src/permissions/trust-store.ts +8 -3
- package/src/permissions/types.ts +4 -2
- package/src/platform/client.ts +35 -7
- package/src/prompts/persona-resolver.ts +138 -0
- package/src/prompts/system-prompt.ts +36 -4
- package/src/prompts/templates/users/default.md +1 -0
- package/src/providers/registry.ts +27 -40
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
- package/src/runtime/auth/external-assistant-id.ts +13 -59
- package/src/runtime/auth/route-policy.ts +29 -1
- package/src/runtime/auth/token-service.ts +53 -15
- package/src/runtime/channel-readiness-service.ts +1 -16
- package/src/runtime/http-server.ts +29 -2
- package/src/runtime/middleware/error-handler.ts +1 -9
- package/src/runtime/routes/audio-routes.ts +40 -0
- package/src/runtime/routes/btw-routes.ts +0 -17
- package/src/runtime/routes/conversation-management-routes.ts +0 -36
- package/src/runtime/routes/conversation-query-routes.ts +106 -2
- package/src/runtime/routes/conversation-routes.ts +4 -43
- package/src/runtime/routes/diagnostics-routes.ts +1 -477
- package/src/runtime/routes/identity-routes.ts +18 -29
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
- package/src/runtime/routes/integrations/vercel.ts +89 -0
- package/src/runtime/routes/log-export-routes.ts +5 -0
- package/src/runtime/routes/memory-item-routes.test.ts +221 -3
- package/src/runtime/routes/memory-item-routes.ts +144 -4
- package/src/runtime/routes/migration-rollback-routes.ts +209 -0
- package/src/runtime/routes/migration-routes.ts +17 -1
- package/src/runtime/routes/notification-routes.ts +58 -0
- package/src/runtime/routes/schedule-routes.ts +65 -0
- package/src/runtime/routes/settings-routes.ts +41 -1
- package/src/runtime/routes/tts-routes.ts +86 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +175 -0
- package/src/runtime/routes/workspace-commit-routes.ts +62 -0
- package/src/runtime/routes/workspace-routes.test.ts +22 -1
- package/src/runtime/routes/workspace-routes.ts +1 -1
- package/src/runtime/routes/workspace-utils.ts +86 -2
- package/src/schedule/schedule-store.ts +0 -21
- package/src/security/ces-credential-client.ts +59 -22
- package/src/security/ces-rpc-credential-backend.ts +85 -0
- package/src/security/credential-backend.ts +12 -88
- package/src/security/keychain-broker-client.ts +10 -2
- package/src/security/secure-keys.ts +94 -113
- package/src/skills/catalog-install.ts +13 -7
- package/src/skills/inline-command-render.ts +5 -1
- package/src/skills/inline-command-runner.ts +30 -2
- package/src/telemetry/usage-telemetry-reporter.ts +4 -2
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/executor.ts +0 -4
- package/src/tools/memory/handlers.ts +1 -129
- package/src/tools/network/script-proxy/session-manager.ts +19 -4
- package/src/tools/network/web-fetch.ts +3 -1
- package/src/tools/permission-checker.ts +18 -0
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +9 -2
- package/src/tools/types.ts +0 -8
- package/src/util/errors.ts +0 -12
- package/src/util/platform.ts +8 -55
- package/src/util/xml.ts +8 -0
- package/src/workspace/git-service.ts +5 -2
- package/src/workspace/heartbeat-service.ts +5 -24
- package/src/workspace/migrations/001-avatar-rename.ts +15 -0
- package/src/workspace/migrations/003-seed-device-id.ts +17 -1
- package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
- package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
- package/src/workspace/migrations/006-services-config.ts +49 -0
- package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
- package/src/workspace/migrations/017-seed-persona-dirs.ts +95 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/runner.ts +106 -2
- package/src/workspace/migrations/types.ts +4 -0
- package/src/__tests__/archive-recall.test.ts +0 -560
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
- package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
- package/src/__tests__/conversation-memory-dirty-tail.test.ts +0 -150
- package/src/__tests__/conversation-switch-memory-reduction.test.ts +0 -474
- package/src/__tests__/db-memory-archive-migration.test.ts +0 -372
- package/src/__tests__/db-memory-brief-state-migration.test.ts +0 -213
- package/src/__tests__/db-memory-reducer-checkpoints.test.ts +0 -273
- package/src/__tests__/diagnostics-export.test.ts +0 -288
- package/src/__tests__/local-gateway-health.test.ts +0 -209
- package/src/__tests__/memory-brief-open-loops.test.ts +0 -530
- package/src/__tests__/memory-brief-time.test.ts +0 -285
- package/src/__tests__/memory-brief-wrapper.test.ts +0 -311
- package/src/__tests__/memory-chunk-archive.test.ts +0 -400
- package/src/__tests__/memory-chunk-dual-write.test.ts +0 -453
- package/src/__tests__/memory-episode-archive.test.ts +0 -370
- package/src/__tests__/memory-episode-dual-write.test.ts +0 -626
- package/src/__tests__/memory-observation-archive.test.ts +0 -375
- package/src/__tests__/memory-observation-dual-write.test.ts +0 -318
- package/src/__tests__/memory-reducer-job.test.ts +0 -538
- package/src/__tests__/memory-reducer-scheduling.test.ts +0 -473
- package/src/__tests__/memory-reducer-store.test.ts +0 -728
- package/src/__tests__/memory-reducer-types.test.ts +0 -707
- package/src/__tests__/memory-reducer.test.ts +0 -704
- package/src/__tests__/memory-simplified-config.test.ts +0 -281
- package/src/__tests__/secret-ingress-handler.test.ts +0 -120
- package/src/__tests__/simplified-memory-e2e.test.ts +0 -666
- package/src/__tests__/simplified-memory-runtime.test.ts +0 -616
- package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
- package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
- package/src/__tests__/swarm-orchestrator.test.ts +0 -463
- package/src/__tests__/swarm-plan-validator.test.ts +0 -384
- package/src/__tests__/swarm-recursion.test.ts +0 -197
- package/src/__tests__/swarm-router-planner.test.ts +0 -234
- package/src/__tests__/swarm-tool.test.ts +0 -185
- package/src/__tests__/swarm-worker-backend.test.ts +0 -144
- package/src/__tests__/swarm-worker-runner.test.ts +0 -288
- package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
- package/src/commands/cc-command-registry.ts +0 -248
- package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
- package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
- package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
- package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
- package/src/config/schemas/memory-simplified.ts +0 -101
- package/src/config/schemas/swarm.ts +0 -82
- package/src/logfire.ts +0 -135
- package/src/memory/archive-recall.ts +0 -516
- package/src/memory/archive-store.ts +0 -400
- package/src/memory/brief-formatting.ts +0 -33
- package/src/memory/brief-open-loops.ts +0 -266
- package/src/memory/brief-time.ts +0 -162
- package/src/memory/brief.ts +0 -75
- package/src/memory/job-handlers/backfill-simplified-memory.ts +0 -462
- package/src/memory/job-handlers/reduce-conversation-memory.ts +0 -229
- package/src/memory/migrations/185-memory-brief-state.ts +0 -52
- package/src/memory/migrations/186-memory-archive.ts +0 -109
- package/src/memory/migrations/187-memory-reducer-checkpoints.ts +0 -19
- package/src/memory/reducer-scheduler.ts +0 -242
- package/src/memory/reducer-store.ts +0 -271
- package/src/memory/reducer-types.ts +0 -106
- package/src/memory/reducer.ts +0 -467
- package/src/memory/schema/memory-archive.ts +0 -121
- package/src/memory/schema/memory-brief.ts +0 -55
- package/src/runtime/local-gateway-health.ts +0 -275
- package/src/security/secret-ingress.ts +0 -68
- package/src/swarm/backend-claude-code.ts +0 -225
- package/src/swarm/checkpoint.ts +0 -137
- package/src/swarm/graph-utils.ts +0 -53
- package/src/swarm/index.ts +0 -55
- package/src/swarm/limits.ts +0 -66
- package/src/swarm/orchestrator.ts +0 -424
- package/src/swarm/plan-validator.ts +0 -117
- package/src/swarm/router-planner.ts +0 -162
- package/src/swarm/router-prompts.ts +0 -39
- package/src/swarm/synthesizer.ts +0 -81
- package/src/swarm/types.ts +0 -72
- package/src/swarm/worker-backend.ts +0 -131
- package/src/swarm/worker-prompts.ts +0 -80
- package/src/swarm/worker-runner.ts +0 -170
- package/src/tools/claude-code/claude-code.ts +0 -610
- package/src/tools/swarm/delegate.ts +0 -205
|
@@ -133,6 +133,8 @@ export async function generateAndPersistConversationTitle(
|
|
|
133
133
|
const result = await runBtwSidechain({
|
|
134
134
|
content: prompt,
|
|
135
135
|
provider,
|
|
136
|
+
systemPrompt: buildTitleSystemPrompt(),
|
|
137
|
+
tools: [],
|
|
136
138
|
maxTokens: config.daemon.titleGenerationMaxTokens,
|
|
137
139
|
modelIntent: "latency-optimized",
|
|
138
140
|
signal,
|
|
@@ -236,6 +238,8 @@ export async function regenerateConversationTitle(
|
|
|
236
238
|
const result = await runBtwSidechain({
|
|
237
239
|
content: prompt,
|
|
238
240
|
provider,
|
|
241
|
+
systemPrompt: buildTitleSystemPrompt(),
|
|
242
|
+
tools: [],
|
|
239
243
|
maxTokens: config.daemon.titleGenerationMaxTokens,
|
|
240
244
|
modelIntent: "latency-optimized",
|
|
241
245
|
signal,
|
|
@@ -277,14 +281,30 @@ export function queueRegenerateConversationTitle(
|
|
|
277
281
|
|
|
278
282
|
// ── Internal helpers ─────────────────────────────────────────────────
|
|
279
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Dedicated system prompt for title generation. Replaces the default
|
|
286
|
+
* assistant system prompt that btw-sidechain would otherwise inject,
|
|
287
|
+
* which caused the model to respond to the conversation content instead
|
|
288
|
+
* of titling it.
|
|
289
|
+
*/
|
|
290
|
+
function buildTitleSystemPrompt(): string {
|
|
291
|
+
return [
|
|
292
|
+
"You generate short conversation titles. Output ONLY the title text — no explanation, no quotes, no markdown, no preamble.",
|
|
293
|
+
"",
|
|
294
|
+
"Rules:",
|
|
295
|
+
"- Maximum 5 words and 40 characters",
|
|
296
|
+
"- Summarize the TOPIC the user is asking about",
|
|
297
|
+
"- Do NOT respond to the conversation content",
|
|
298
|
+
"- Do NOT assess feasibility or comment on capabilities",
|
|
299
|
+
].join("\n");
|
|
300
|
+
}
|
|
301
|
+
|
|
280
302
|
function buildTitlePrompt(
|
|
281
303
|
context?: TitleContext,
|
|
282
304
|
userMessage?: string,
|
|
283
305
|
assistantResponse?: string,
|
|
284
306
|
): string {
|
|
285
|
-
const parts: string[] = [
|
|
286
|
-
"Generate a very short title summarizing the TOPIC of this conversation. Rules: at most 5 words, at most 40 characters, no quotes, no markdown formatting. IMPORTANT: Summarize what the user is asking about — do NOT respond to the message, do NOT assess feasibility, and do NOT comment on your own capabilities.",
|
|
287
|
-
];
|
|
307
|
+
const parts: string[] = [];
|
|
288
308
|
|
|
289
309
|
if (context) {
|
|
290
310
|
const hints: string[] = [];
|
|
@@ -295,12 +315,12 @@ function buildTitlePrompt(
|
|
|
295
315
|
if (context.metadataHints?.length)
|
|
296
316
|
hints.push(`Hints: ${context.metadataHints.join(", ")}`);
|
|
297
317
|
if (hints.length > 0) {
|
|
298
|
-
parts.push("
|
|
318
|
+
parts.push("Metadata:", ...hints, "");
|
|
299
319
|
}
|
|
300
320
|
}
|
|
301
321
|
|
|
302
322
|
if (userMessage) {
|
|
303
|
-
parts.push(
|
|
323
|
+
parts.push(`User: ${truncate(userMessage, 200, "")}`);
|
|
304
324
|
}
|
|
305
325
|
if (assistantResponse) {
|
|
306
326
|
parts.push(`Assistant: ${truncate(assistantResponse, 200, "")}`);
|
|
@@ -338,16 +358,61 @@ function deriveFallbackTitle(context?: TitleContext): string | null {
|
|
|
338
358
|
return null;
|
|
339
359
|
}
|
|
340
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Extract only human-authored text from stored message content for title
|
|
363
|
+
* generation. Unlike extractTextFromStoredMessageContent (which includes
|
|
364
|
+
* tool metadata like "Tool use (...): {...}"), this only extracts:
|
|
365
|
+
* - `text` blocks (the actual conversation content)
|
|
366
|
+
* - `tool_result` string content (topical signal from tool responses)
|
|
367
|
+
* — web_search_tool_result is skipped (structured search data, not topical)
|
|
368
|
+
*
|
|
369
|
+
* Returns empty string for content-block arrays with no extractable text,
|
|
370
|
+
* preventing raw JSON from polluting the title prompt.
|
|
371
|
+
*/
|
|
372
|
+
function extractTextForTitle(raw: string): string {
|
|
373
|
+
try {
|
|
374
|
+
const parsed = JSON.parse(raw);
|
|
375
|
+
if (typeof parsed === "string") return parsed;
|
|
376
|
+
if (!Array.isArray(parsed)) return raw;
|
|
377
|
+
const texts: string[] = [];
|
|
378
|
+
for (const block of parsed) {
|
|
379
|
+
if (!block || typeof block !== "object") continue;
|
|
380
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
381
|
+
texts.push(block.text);
|
|
382
|
+
// guard:allow-tool-result-only — web_search_tool_result has structured
|
|
383
|
+
// search result arrays, not useful for title generation; only plain
|
|
384
|
+
// tool_result string content carries topical signal.
|
|
385
|
+
} else if (block.type === "tool_result") {
|
|
386
|
+
if (typeof block.content === "string") {
|
|
387
|
+
texts.push(block.content);
|
|
388
|
+
} else if (Array.isArray(block.content)) {
|
|
389
|
+
for (const nested of block.content) {
|
|
390
|
+
if (
|
|
391
|
+
nested &&
|
|
392
|
+
typeof nested === "object" &&
|
|
393
|
+
nested.type === "text" &&
|
|
394
|
+
typeof nested.text === "string"
|
|
395
|
+
) {
|
|
396
|
+
texts.push(nested.text);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return texts.join("\n");
|
|
403
|
+
} catch {
|
|
404
|
+
return raw;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
341
408
|
function buildRegenerationPrompt(recentMessages: MessageRow[]): string {
|
|
342
|
-
const parts: string[] = [
|
|
343
|
-
"Generate a very short title summarizing the TOPIC of this conversation based on the recent messages below. Rules: at most 5 words, at most 40 characters, no quotes, no markdown formatting. IMPORTANT: Summarize what the user is asking about — do NOT respond to the messages, do NOT assess feasibility, and do NOT comment on your own capabilities.",
|
|
344
|
-
"",
|
|
345
|
-
"Recent messages:",
|
|
346
|
-
];
|
|
409
|
+
const parts: string[] = ["Recent messages:"];
|
|
347
410
|
|
|
348
411
|
for (const msg of recentMessages) {
|
|
412
|
+
const text = extractTextForTitle(msg.content);
|
|
413
|
+
if (!text) continue;
|
|
349
414
|
const role = msg.role === "user" ? "User" : "Assistant";
|
|
350
|
-
parts.push(`${role}: ${truncate(
|
|
415
|
+
parts.push(`${role}: ${truncate(text, 200, "")}`);
|
|
351
416
|
}
|
|
352
417
|
|
|
353
418
|
return parts.join("\n");
|
package/src/memory/db-init.ts
CHANGED
|
@@ -35,12 +35,14 @@ import {
|
|
|
35
35
|
createTasksAndWorkItemsTables,
|
|
36
36
|
createWatchersAndLogsTables,
|
|
37
37
|
migrateAssistantContactMetadata,
|
|
38
|
+
migrateBackfillAudioAttachmentMimeTypes,
|
|
38
39
|
migrateBackfillContactInteractionStats,
|
|
39
40
|
migrateBackfillGuardianPrincipalId,
|
|
40
41
|
migrateBackfillInlineAttachmentsToDisk,
|
|
41
42
|
migrateBackfillUsageCacheAccounting,
|
|
42
43
|
migrateCallSessionInviteMetadata,
|
|
43
44
|
migrateCallSessionMode,
|
|
45
|
+
migrateCallSessionSkipDisclosure,
|
|
44
46
|
migrateCanonicalGuardianDeliveriesDestinationIndex,
|
|
45
47
|
migrateCanonicalGuardianRequesterChatId,
|
|
46
48
|
migrateCapabilityCardColumns,
|
|
@@ -51,6 +53,7 @@ import {
|
|
|
51
53
|
migrateContactsAssistantId,
|
|
52
54
|
migrateContactsNotesColumn,
|
|
53
55
|
migrateContactsRolePrincipal,
|
|
56
|
+
migrateContactsUserFileColumn,
|
|
54
57
|
migrateConversationForkLineage,
|
|
55
58
|
migrateConversationsThreadTypeIndex,
|
|
56
59
|
migrateCreateThreadStartersTable,
|
|
@@ -66,6 +69,7 @@ import {
|
|
|
66
69
|
migrateDropMemorySegmentFts,
|
|
67
70
|
migrateDropOrphanedMediaTables,
|
|
68
71
|
migrateDropRemindersTable,
|
|
72
|
+
migrateDropSimplifiedMemory,
|
|
69
73
|
migrateDropUsageCompositeIndexes,
|
|
70
74
|
migrateFkCascadeRebuilds,
|
|
71
75
|
migrateGuardianActionFollowup,
|
|
@@ -82,10 +86,7 @@ import {
|
|
|
82
86
|
migrateInviteContactId,
|
|
83
87
|
migrateLlmRequestLogMessageId,
|
|
84
88
|
migrateLlmRequestLogProvider,
|
|
85
|
-
migrateMemoryArchiveTables,
|
|
86
|
-
migrateMemoryBriefState,
|
|
87
89
|
migrateMemoryItemSupersession,
|
|
88
|
-
migrateMemoryReducerCheckpoints,
|
|
89
90
|
migrateMessagesFtsBackfill,
|
|
90
91
|
migrateNormalizePhoneIdentities,
|
|
91
92
|
migrateNotificationDeliveryThreadDecision,
|
|
@@ -488,17 +489,20 @@ export function initializeDb(): void {
|
|
|
488
489
|
// 84. Add nullable conversation fork lineage columns and parent lookup index
|
|
489
490
|
migrateConversationForkLineage(database);
|
|
490
491
|
|
|
491
|
-
// 85.
|
|
492
|
-
|
|
492
|
+
// 85. Add quiet flag to schedule jobs
|
|
493
|
+
migrateScheduleQuietFlag(database);
|
|
493
494
|
|
|
494
|
-
// 86.
|
|
495
|
-
|
|
495
|
+
// 86. Drop simplified-memory tables and reducer checkpoint columns
|
|
496
|
+
migrateDropSimplifiedMemory(database);
|
|
496
497
|
|
|
497
|
-
// 87. Add
|
|
498
|
-
|
|
498
|
+
// 87. Add skip_disclosure column to call_sessions for per-call disclosure control
|
|
499
|
+
migrateCallSessionSkipDisclosure(database);
|
|
499
500
|
|
|
500
|
-
// 88.
|
|
501
|
-
|
|
501
|
+
// 88. Backfill correct MIME types for audio attachments stored as application/octet-stream
|
|
502
|
+
migrateBackfillAudioAttachmentMimeTypes(database);
|
|
503
|
+
|
|
504
|
+
// 89. Add user_file column to contacts for per-user persona file mapping
|
|
505
|
+
migrateContactsUserFileColumn(database);
|
|
502
506
|
|
|
503
507
|
validateMigrationState(database);
|
|
504
508
|
|
package/src/memory/indexer.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { getConfig } from "../config/loader.js";
|
|
|
5
5
|
import type { MemoryConfig } from "../config/types.js";
|
|
6
6
|
import type { TrustClass } from "../runtime/actor-trust-resolver.js";
|
|
7
7
|
import { getLogger } from "../util/logger.js";
|
|
8
|
-
import { computeChunkContentHash } from "./archive-store.js";
|
|
9
8
|
import { getDb } from "./db.js";
|
|
10
9
|
import { selectedBackendSupportsMultimodal } from "./embedding-backend.js";
|
|
11
10
|
import { enqueueMemoryJob } from "./jobs-store.js";
|
|
@@ -13,7 +12,7 @@ import {
|
|
|
13
12
|
extractMediaBlockMeta,
|
|
14
13
|
extractTextFromStoredMessageContent,
|
|
15
14
|
} from "./message-content.js";
|
|
16
|
-
import {
|
|
15
|
+
import { memorySegments } from "./schema.js";
|
|
17
16
|
import { segmentText } from "./segmenter.js";
|
|
18
17
|
|
|
19
18
|
const log = getLogger("memory-indexer");
|
|
@@ -54,12 +53,7 @@ export async function indexMessageNow(
|
|
|
54
53
|
input.provenanceTrustClass === undefined;
|
|
55
54
|
|
|
56
55
|
const text = extractTextFromStoredMessageContent(input.content);
|
|
57
|
-
|
|
58
|
-
const candidateMediaMeta = extractMediaBlockMeta(input.content).filter(
|
|
59
|
-
(b) => b.type === "image",
|
|
60
|
-
);
|
|
61
|
-
const hasMedia = candidateMediaMeta.length > 0;
|
|
62
|
-
if (!hasText && !hasMedia) {
|
|
56
|
+
if (text.length === 0) {
|
|
63
57
|
enqueueMemoryJob("build_conversation_summary", {
|
|
64
58
|
conversationId: input.conversationId,
|
|
65
59
|
});
|
|
@@ -68,13 +62,11 @@ export async function indexMessageNow(
|
|
|
68
62
|
|
|
69
63
|
const db = getDb();
|
|
70
64
|
const now = Date.now();
|
|
71
|
-
const segments =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)
|
|
77
|
-
: [];
|
|
65
|
+
const segments = segmentText(
|
|
66
|
+
text,
|
|
67
|
+
config.segmentation.targetTokens,
|
|
68
|
+
config.segmentation.overlapTokens,
|
|
69
|
+
);
|
|
78
70
|
const shouldExtract =
|
|
79
71
|
input.role === "user" ||
|
|
80
72
|
(input.role === "assistant" && config.extraction.extractFromAssistant);
|
|
@@ -84,6 +76,9 @@ export async function indexMessageNow(
|
|
|
84
76
|
// overhead for messages on non-multimodal backends.
|
|
85
77
|
// selectedBackendSupportsMultimodal requires async key resolution, so we
|
|
86
78
|
// skip it entirely for text-only messages.
|
|
79
|
+
const candidateMediaMeta = extractMediaBlockMeta(input.content).filter(
|
|
80
|
+
(b) => b.type === "image",
|
|
81
|
+
);
|
|
87
82
|
const mediaBlocks =
|
|
88
83
|
candidateMediaMeta.length > 0 &&
|
|
89
84
|
(await selectedBackendSupportsMultimodal(getConfig()))
|
|
@@ -93,10 +88,7 @@ export async function indexMessageNow(
|
|
|
93
88
|
// Wrap all segment inserts and job enqueues in a single transaction so they
|
|
94
89
|
// either all succeed or all roll back, preventing partial/orphaned state.
|
|
95
90
|
let skippedEmbedJobs = 0;
|
|
96
|
-
let skippedChunkEmbedJobs = 0;
|
|
97
|
-
const scopeId = input.scopeId ?? "default";
|
|
98
91
|
db.transaction((tx) => {
|
|
99
|
-
// ── Legacy segment path (kept intact for parallel validation) ───
|
|
100
92
|
for (const segment of segments) {
|
|
101
93
|
const segmentId = buildSegmentId(input.messageId, segment.segmentIndex);
|
|
102
94
|
const hash = createHash("sha256").update(segment.text).digest("hex");
|
|
@@ -117,7 +109,7 @@ export async function indexMessageNow(
|
|
|
117
109
|
segmentIndex: segment.segmentIndex,
|
|
118
110
|
text: segment.text,
|
|
119
111
|
tokenEstimate: segment.tokenEstimate,
|
|
120
|
-
scopeId,
|
|
112
|
+
scopeId: input.scopeId ?? "default",
|
|
121
113
|
contentHash: hash,
|
|
122
114
|
createdAt: input.createdAt,
|
|
123
115
|
updatedAt: now,
|
|
@@ -127,7 +119,7 @@ export async function indexMessageNow(
|
|
|
127
119
|
set: {
|
|
128
120
|
text: segment.text,
|
|
129
121
|
tokenEstimate: segment.tokenEstimate,
|
|
130
|
-
scopeId,
|
|
122
|
+
scopeId: input.scopeId ?? "default",
|
|
131
123
|
contentHash: hash,
|
|
132
124
|
updatedAt: now,
|
|
133
125
|
},
|
|
@@ -141,65 +133,6 @@ export async function indexMessageNow(
|
|
|
141
133
|
}
|
|
142
134
|
}
|
|
143
135
|
|
|
144
|
-
// ── Archive chunk dual-write (mirrors segment boundaries) ──────
|
|
145
|
-
// Create a single observation per message, then create one chunk per
|
|
146
|
-
// segment using the same segmentation boundaries. Chunks are
|
|
147
|
-
// deduplicated by (scopeId, contentHash) via onConflictDoNothing so
|
|
148
|
-
// unchanged content does not enqueue duplicate embed_chunk jobs.
|
|
149
|
-
const observationId = buildObservationId(input.messageId);
|
|
150
|
-
tx.insert(memoryObservations)
|
|
151
|
-
.values({
|
|
152
|
-
id: observationId,
|
|
153
|
-
scopeId,
|
|
154
|
-
conversationId: input.conversationId,
|
|
155
|
-
messageId: input.messageId,
|
|
156
|
-
role: input.role,
|
|
157
|
-
content: hasText ? text : input.content,
|
|
158
|
-
modality: hasMedia ? "multimodal" : "text",
|
|
159
|
-
source: null,
|
|
160
|
-
createdAt: input.createdAt,
|
|
161
|
-
})
|
|
162
|
-
.onConflictDoNothing({ target: memoryObservations.id })
|
|
163
|
-
.run();
|
|
164
|
-
|
|
165
|
-
for (const segment of segments) {
|
|
166
|
-
const chunkId = buildChunkId(input.messageId, segment.segmentIndex);
|
|
167
|
-
const chunkHash = computeChunkContentHash(scopeId, segment.text);
|
|
168
|
-
|
|
169
|
-
// Check if this chunk already exists with the same content hash
|
|
170
|
-
const existingChunk = tx
|
|
171
|
-
.select({ contentHash: memoryChunks.contentHash })
|
|
172
|
-
.from(memoryChunks)
|
|
173
|
-
.where(eq(memoryChunks.id, chunkId))
|
|
174
|
-
.get();
|
|
175
|
-
|
|
176
|
-
tx.insert(memoryChunks)
|
|
177
|
-
.values({
|
|
178
|
-
id: chunkId,
|
|
179
|
-
scopeId,
|
|
180
|
-
observationId,
|
|
181
|
-
content: segment.text,
|
|
182
|
-
tokenEstimate: segment.tokenEstimate,
|
|
183
|
-
contentHash: chunkHash,
|
|
184
|
-
createdAt: input.createdAt,
|
|
185
|
-
})
|
|
186
|
-
.onConflictDoUpdate({
|
|
187
|
-
target: memoryChunks.id,
|
|
188
|
-
set: {
|
|
189
|
-
content: segment.text,
|
|
190
|
-
tokenEstimate: segment.tokenEstimate,
|
|
191
|
-
contentHash: chunkHash,
|
|
192
|
-
},
|
|
193
|
-
})
|
|
194
|
-
.run();
|
|
195
|
-
|
|
196
|
-
if (existingChunk?.contentHash === chunkHash) {
|
|
197
|
-
skippedChunkEmbedJobs++;
|
|
198
|
-
} else {
|
|
199
|
-
enqueueMemoryJob("embed_chunk", { chunkId, scopeId }, Date.now(), tx);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
136
|
// Enqueue embed_attachment jobs for image content blocks when the
|
|
204
137
|
// embedding provider supports multimodal (Gemini only).
|
|
205
138
|
for (const block of mediaBlocks) {
|
|
@@ -214,7 +147,7 @@ export async function indexMessageNow(
|
|
|
214
147
|
if (shouldExtract && isTrustedActor && !input.automated) {
|
|
215
148
|
enqueueMemoryJob(
|
|
216
149
|
"extract_items",
|
|
217
|
-
{ messageId: input.messageId, scopeId },
|
|
150
|
+
{ messageId: input.messageId, scopeId: input.scopeId ?? "default" },
|
|
218
151
|
Date.now(),
|
|
219
152
|
tx,
|
|
220
153
|
);
|
|
@@ -233,12 +166,6 @@ export async function indexMessageNow(
|
|
|
233
166
|
);
|
|
234
167
|
}
|
|
235
168
|
|
|
236
|
-
if (skippedChunkEmbedJobs > 0) {
|
|
237
|
-
log.debug(
|
|
238
|
-
`Skipped ${skippedChunkEmbedJobs}/${segments.length} embed_chunk jobs (content unchanged)`,
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
169
|
if (!isTrustedActor && shouldExtract) {
|
|
243
170
|
log.info(
|
|
244
171
|
`Skipping extraction jobs for untrusted actor (trustClass=${input.provenanceTrustClass})`,
|
|
@@ -250,11 +177,9 @@ export async function indexMessageNow(
|
|
|
250
177
|
}
|
|
251
178
|
|
|
252
179
|
const extractionGated = !isTrustedActor || !!input.automated;
|
|
253
|
-
const segmentEmbedJobs = segments.length - skippedEmbedJobs;
|
|
254
|
-
const chunkEmbedJobs = segments.length - skippedChunkEmbedJobs;
|
|
255
180
|
const enqueuedJobs =
|
|
256
|
-
|
|
257
|
-
|
|
181
|
+
segments.length -
|
|
182
|
+
skippedEmbedJobs +
|
|
258
183
|
mediaBlocks.length +
|
|
259
184
|
(shouldExtract && !extractionGated ? 2 : 1);
|
|
260
185
|
return {
|
|
@@ -288,19 +213,3 @@ export function getRecentSegmentsForConversation(
|
|
|
288
213
|
function buildSegmentId(messageId: string, segmentIndex: number): string {
|
|
289
214
|
return `${messageId}:${segmentIndex}`;
|
|
290
215
|
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Deterministic observation ID derived from the messageId so repeated
|
|
294
|
-
* indexer runs for the same message converge on the same observation row.
|
|
295
|
-
*/
|
|
296
|
-
function buildObservationId(messageId: string): string {
|
|
297
|
-
return `obs:${messageId}`;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Deterministic chunk ID derived from the messageId and segment index so
|
|
302
|
-
* the dual-write path mirrors the legacy segment identity scheme exactly.
|
|
303
|
-
*/
|
|
304
|
-
function buildChunkId(messageId: string, segmentIndex: number): string {
|
|
305
|
-
return `chunk:${messageId}:${segmentIndex}`;
|
|
306
|
-
}
|
|
@@ -3,6 +3,7 @@ import { v4 as uuid } from "uuid";
|
|
|
3
3
|
|
|
4
4
|
import { getConfig } from "../config/loader.js";
|
|
5
5
|
import type { MemoryExtractionConfig } from "../config/types.js";
|
|
6
|
+
import { resolveGuardianPersona } from "../prompts/persona-resolver.js";
|
|
6
7
|
import { buildCoreIdentityContext } from "../prompts/system-prompt.js";
|
|
7
8
|
import {
|
|
8
9
|
createTimeout,
|
|
@@ -150,6 +151,7 @@ function buildExtractionSystemPrompt(
|
|
|
150
151
|
statement: string;
|
|
151
152
|
}>,
|
|
152
153
|
messageRole: string,
|
|
154
|
+
userPersona?: string | null,
|
|
153
155
|
): string {
|
|
154
156
|
// Build the fixed instruction body first so we can measure it and allocate
|
|
155
157
|
// the remaining budget to identity context.
|
|
@@ -206,7 +208,9 @@ IMPORTANT: The message below is from the ASSISTANT, not the user. Do NOT attribu
|
|
|
206
208
|
// ceiling, preventing oversized prompts from exceeding the provider input
|
|
207
209
|
// window (which would cause sendMessage to error and fall back to
|
|
208
210
|
// lower-quality pattern-based extraction).
|
|
209
|
-
const rawIdentityContext = buildCoreIdentityContext(
|
|
211
|
+
const rawIdentityContext = buildCoreIdentityContext(
|
|
212
|
+
userPersona ? { userPersona } : undefined,
|
|
213
|
+
);
|
|
210
214
|
|
|
211
215
|
let prompt = "";
|
|
212
216
|
if (rawIdentityContext) {
|
|
@@ -316,6 +320,7 @@ async function extractItemsWithLLM(
|
|
|
316
320
|
extractionConfig: MemoryExtractionConfig,
|
|
317
321
|
scopeId: string,
|
|
318
322
|
messageRole: string,
|
|
323
|
+
userPersona?: string | null,
|
|
319
324
|
): Promise<ExtractedItem[]> {
|
|
320
325
|
const provider = await getConfiguredProvider();
|
|
321
326
|
if (!provider) {
|
|
@@ -334,6 +339,7 @@ async function extractItemsWithLLM(
|
|
|
334
339
|
const systemPrompt = buildExtractionSystemPrompt(
|
|
335
340
|
existingItems,
|
|
336
341
|
messageRole,
|
|
342
|
+
userPersona,
|
|
337
343
|
);
|
|
338
344
|
|
|
339
345
|
const messagePrefix =
|
|
@@ -532,12 +538,20 @@ export async function extractAndUpsertMemoryItemsForMessage(
|
|
|
532
538
|
const config = getConfig();
|
|
533
539
|
const extractionConfig = config.memory.extraction;
|
|
534
540
|
const effectiveScopeId = scopeId ?? "default";
|
|
541
|
+
|
|
542
|
+
// Resolve the guardian's persona to provide personality-aware extraction
|
|
543
|
+
// context. Currently uses the guardian persona for all conversations —
|
|
544
|
+
// non-guardian conversations are rare and the guardian's persona provides
|
|
545
|
+
// better extraction context than none.
|
|
546
|
+
const userPersona = resolveGuardianPersona();
|
|
547
|
+
|
|
535
548
|
const extracted = extractionConfig.useLLM
|
|
536
549
|
? await extractItemsWithLLM(
|
|
537
550
|
text,
|
|
538
551
|
extractionConfig,
|
|
539
552
|
effectiveScopeId,
|
|
540
553
|
message.role,
|
|
554
|
+
userPersona,
|
|
541
555
|
)
|
|
542
556
|
: extractItemsPatternBased(text, effectiveScopeId);
|
|
543
557
|
|
|
@@ -9,6 +9,7 @@ import { and, desc, eq } from "drizzle-orm";
|
|
|
9
9
|
import { v4 as uuid } from "uuid";
|
|
10
10
|
|
|
11
11
|
import { loadSkillCatalog } from "../../config/skills.js";
|
|
12
|
+
import { resolveGuardianPersona } from "../../prompts/persona-resolver.js";
|
|
12
13
|
import { buildCoreIdentityContext } from "../../prompts/system-prompt.js";
|
|
13
14
|
import {
|
|
14
15
|
createTimeout,
|
|
@@ -171,7 +172,9 @@ async function generateStarters(scopeId: string): Promise<GeneratedStarter[]> {
|
|
|
171
172
|
|
|
172
173
|
// Truncate identity context to prevent oversized prompts when SOUL.md /
|
|
173
174
|
// IDENTITY.md / USER.md are large.
|
|
174
|
-
const rawIdentityContext = buildCoreIdentityContext(
|
|
175
|
+
const rawIdentityContext = buildCoreIdentityContext({
|
|
176
|
+
userPersona: resolveGuardianPersona(),
|
|
177
|
+
});
|
|
175
178
|
const identityContext = rawIdentityContext
|
|
176
179
|
? truncate(rawIdentityContext, 2000, "\n…[truncated]")
|
|
177
180
|
: null;
|
|
@@ -11,10 +11,7 @@ import type { MemoryJob } from "../jobs-store.js";
|
|
|
11
11
|
import { extractMediaBlocks } from "../message-content.js";
|
|
12
12
|
import {
|
|
13
13
|
mediaAssets,
|
|
14
|
-
memoryChunks,
|
|
15
|
-
memoryEpisodes,
|
|
16
14
|
memoryItems,
|
|
17
|
-
memoryObservations,
|
|
18
15
|
memorySegments,
|
|
19
16
|
memorySummaries,
|
|
20
17
|
messages,
|
|
@@ -93,26 +90,6 @@ export async function embedSummaryJob(
|
|
|
93
90
|
);
|
|
94
91
|
}
|
|
95
92
|
|
|
96
|
-
export async function embedChunkJob(
|
|
97
|
-
job: MemoryJob,
|
|
98
|
-
config: AssistantConfig,
|
|
99
|
-
): Promise<void> {
|
|
100
|
-
const chunkId = asString(job.payload.chunkId);
|
|
101
|
-
if (!chunkId) return;
|
|
102
|
-
const db = getDb();
|
|
103
|
-
const chunk = db
|
|
104
|
-
.select()
|
|
105
|
-
.from(memoryChunks)
|
|
106
|
-
.where(eq(memoryChunks.id, chunkId))
|
|
107
|
-
.get();
|
|
108
|
-
if (!chunk) return;
|
|
109
|
-
await embedAndUpsert(config, "chunk", chunk.id, chunk.content, {
|
|
110
|
-
observation_id: chunk.observationId,
|
|
111
|
-
created_at: chunk.createdAt,
|
|
112
|
-
memory_scope_id: chunk.scopeId,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
93
|
export async function embedMediaJob(
|
|
117
94
|
job: MemoryJob,
|
|
118
95
|
config: AssistantConfig,
|
|
@@ -146,40 +123,6 @@ export async function embedMediaJob(
|
|
|
146
123
|
});
|
|
147
124
|
}
|
|
148
125
|
|
|
149
|
-
export async function embedObservationJob(
|
|
150
|
-
job: MemoryJob,
|
|
151
|
-
config: AssistantConfig,
|
|
152
|
-
): Promise<void> {
|
|
153
|
-
const observationId = asString(job.payload.observationId);
|
|
154
|
-
const chunkId = asString(job.payload.chunkId);
|
|
155
|
-
if (!observationId || !chunkId) return;
|
|
156
|
-
|
|
157
|
-
const db = getDb();
|
|
158
|
-
const observation = db
|
|
159
|
-
.select()
|
|
160
|
-
.from(memoryObservations)
|
|
161
|
-
.where(eq(memoryObservations.id, observationId))
|
|
162
|
-
.get();
|
|
163
|
-
if (!observation) return;
|
|
164
|
-
|
|
165
|
-
const chunk = db
|
|
166
|
-
.select()
|
|
167
|
-
.from(memoryChunks)
|
|
168
|
-
.where(eq(memoryChunks.id, chunkId))
|
|
169
|
-
.get();
|
|
170
|
-
if (!chunk) return;
|
|
171
|
-
|
|
172
|
-
await embedAndUpsert(config, "observation", chunk.id, chunk.content, {
|
|
173
|
-
observation_id: observationId,
|
|
174
|
-
conversation_id: observation.conversationId,
|
|
175
|
-
role: observation.role,
|
|
176
|
-
modality: observation.modality,
|
|
177
|
-
source: observation.source,
|
|
178
|
-
created_at: observation.createdAt,
|
|
179
|
-
memory_scope_id: observation.scopeId,
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
|
|
183
126
|
export async function embedAttachmentJob(
|
|
184
127
|
job: MemoryJob,
|
|
185
128
|
config: AssistantConfig,
|
|
@@ -216,25 +159,3 @@ export async function embedAttachmentJob(
|
|
|
216
159
|
memory_scope_id: memoryScopeId,
|
|
217
160
|
});
|
|
218
161
|
}
|
|
219
|
-
|
|
220
|
-
export async function embedEpisodeJob(
|
|
221
|
-
job: MemoryJob,
|
|
222
|
-
config: AssistantConfig,
|
|
223
|
-
): Promise<void> {
|
|
224
|
-
const episodeId = asString(job.payload.episodeId);
|
|
225
|
-
if (!episodeId) return;
|
|
226
|
-
const db = getDb();
|
|
227
|
-
const episode = db
|
|
228
|
-
.select()
|
|
229
|
-
.from(memoryEpisodes)
|
|
230
|
-
.where(eq(memoryEpisodes.id, episodeId))
|
|
231
|
-
.get();
|
|
232
|
-
if (!episode) return;
|
|
233
|
-
const text = `[episode] ${episode.title}: ${episode.summary}`;
|
|
234
|
-
await embedAndUpsert(config, "episode", episode.id, text, {
|
|
235
|
-
conversation_id: episode.conversationId,
|
|
236
|
-
created_at: episode.startAt,
|
|
237
|
-
last_seen_at: episode.endAt,
|
|
238
|
-
memory_scope_id: episode.scopeId,
|
|
239
|
-
});
|
|
240
|
-
}
|
package/src/memory/job-utils.ts
CHANGED
|
@@ -142,7 +142,7 @@ export function truncate(text: string, max: number): string {
|
|
|
142
142
|
|
|
143
143
|
export async function embedAndUpsert(
|
|
144
144
|
config: AssistantConfig,
|
|
145
|
-
targetType: "segment" | "item" | "summary" | "
|
|
145
|
+
targetType: "segment" | "item" | "summary" | "media",
|
|
146
146
|
targetId: string,
|
|
147
147
|
input: EmbeddingInput,
|
|
148
148
|
extraPayload?: Record<string, unknown>,
|