@vellumai/assistant 0.4.56 → 0.4.57
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 +10 -10
- package/Dockerfile +3 -0
- package/README.md +11 -11
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/memory.md +3 -4
- package/docs/credential-execution-service.md +13 -20
- package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +7 -7
- package/src/__tests__/anthropic-provider.test.ts +172 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
- package/src/__tests__/approval-cascade.test.ts +2 -2
- package/src/__tests__/approval-routes-http.test.ts +3 -4
- package/src/__tests__/asset-materialize-tool.test.ts +5 -5
- package/src/__tests__/asset-search-tool.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +5 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
- package/src/__tests__/attachments-store.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +5 -3
- package/src/__tests__/browser-skill-endstate.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +2 -2
- package/src/__tests__/callback-handoff-copy.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +31 -32
- package/src/__tests__/chrome-cdp.test.ts +47 -18
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +9 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop.test.ts +11 -4
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +33 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
- package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +23 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +185 -173
- package/src/__tests__/conversation-seed-composer.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +4 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
- package/src/__tests__/conversation-starter-routes.test.ts +291 -0
- package/src/__tests__/conversation-wipe.test.ts +438 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
- package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
- package/src/__tests__/credential-security-e2e.test.ts +20 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +227 -0
- package/src/__tests__/credentials-cli.test.ts +3 -0
- package/src/__tests__/date-context.test.ts +59 -377
- package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/encrypted-store.test.ts +237 -15
- package/src/__tests__/ephemeral-permissions.test.ts +4 -5
- package/src/__tests__/event-bus.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +4 -4
- package/src/__tests__/gemini-provider.test.ts +6 -9
- package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/host-shell-tool.test.ts +6 -6
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/intent-routing.test.ts +51 -99
- package/src/__tests__/invite-routes-http.test.ts +5 -0
- package/src/__tests__/list-messages-attachments.test.ts +1 -1
- package/src/__tests__/managed-proxy-context.test.ts +2 -5
- package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
- package/src/__tests__/media-generate-image.test.ts +32 -15
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
- package/src/__tests__/memory-recall-quality.test.ts +4 -3
- package/src/__tests__/memory-regressions.test.ts +86 -90
- package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
- package/src/__tests__/migration-export-http.test.ts +26 -27
- package/src/__tests__/migration-import-commit-http.test.ts +165 -37
- package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
- package/src/__tests__/migration-validate-http.test.ts +16 -16
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
- package/src/__tests__/notification-broadcaster.test.ts +1 -1
- package/src/__tests__/notification-decision-fallback.test.ts +2 -2
- package/src/__tests__/notification-decision-identity.test.ts +8 -9
- package/src/__tests__/notification-decision-strategy.test.ts +1 -1
- package/src/__tests__/notification-deep-link.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
- package/src/__tests__/onboarding-template-contract.test.ts +23 -59
- package/src/__tests__/provider-error-scenarios.test.ts +154 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
- package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
- package/src/__tests__/provider-registry-ollama.test.ts +5 -2
- package/src/__tests__/qdrant-manager.test.ts +7 -7
- package/src/__tests__/ratelimit.test.ts +0 -74
- package/src/__tests__/recording-handler.test.ts +0 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +46 -2
- package/src/__tests__/schema-transforms.test.ts +114 -54
- package/src/__tests__/secret-onetime-send.test.ts +20 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
- package/src/__tests__/secret-scanner-executor.test.ts +1 -2
- package/src/__tests__/send-endpoint-busy.test.ts +63 -4
- package/src/__tests__/send-notification-tool.test.ts +2 -2
- package/src/__tests__/shell-credential-ref.test.ts +0 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
- package/src/__tests__/skill-memory.test.ts +547 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
- package/src/__tests__/slack-channel-config.test.ts +109 -94
- package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
- package/src/__tests__/swarm-recursion.test.ts +2 -2
- package/src/__tests__/swarm-tool.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +19 -66
- package/src/__tests__/telegram-config.test.ts +121 -0
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trace-emitter.test.ts +8 -1
- package/src/__tests__/trust-store.test.ts +7 -8
- package/src/__tests__/twilio-routes.test.ts +1 -18
- package/src/__tests__/user-reference.test.ts +82 -2
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +3 -3
- package/src/avatar/ascii-renderer.ts +2 -2
- package/src/avatar/png-renderer.ts +2 -2
- package/src/avatar/resvg-lazy.ts +21 -0
- package/src/calls/guardian-dispatch.ts +1 -1
- package/src/calls/relay-access-wait.ts +2 -2
- package/src/calls/twilio-rest.ts +0 -248
- package/src/cli/AGENTS.md +5 -8
- package/src/cli/__tests__/notifications.test.ts +5 -5
- package/src/cli/commands/avatar.ts +64 -2
- package/src/cli/commands/conversations.ts +131 -1
- package/src/cli/commands/credentials.ts +2 -0
- package/src/cli/commands/notifications.ts +3 -3
- package/src/cli.ts +10 -0
- package/src/config/bundled-skills/acp/SKILL.md +5 -5
- package/src/config/bundled-skills/acp/TOOLS.json +6 -6
- package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
- package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
- package/src/config/bundled-skills/browser/SKILL.md +15 -15
- package/src/config/bundled-skills/browser/TOOLS.json +14 -14
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
- package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
- package/src/config/bundled-skills/contacts/SKILL.md +3 -3
- package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
- package/src/config/bundled-skills/document/SKILL.md +4 -4
- package/src/config/bundled-skills/document/TOOLS.json +2 -2
- package/src/config/bundled-skills/followups/TOOLS.json +3 -3
- package/src/config/bundled-skills/gmail/SKILL.md +32 -32
- package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
- package/src/config/bundled-skills/google-calendar/types.ts +1 -1
- package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
- package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
- package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
- package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +29 -25
- package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +3 -3
- package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
- package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
- package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
- package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
- package/src/config/bundled-skills/schedule/SKILL.md +26 -26
- package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
- package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
- package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
- package/src/config/bundled-skills/sequences/SKILL.md +2 -2
- package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
- package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
- package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
- package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
- package/src/config/bundled-skills/slack/SKILL.md +2 -2
- package/src/config/bundled-skills/slack/TOOLS.json +8 -8
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
- package/src/config/bundled-skills/tasks/SKILL.md +1 -1
- package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
- package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
- package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
- package/src/config/bundled-skills/watcher/SKILL.md +4 -4
- package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
- package/src/config/feature-flag-registry.json +33 -17
- package/src/config/schemas/sandbox.ts +1 -1
- package/src/config/schemas/services.ts +13 -3
- package/src/config/schemas/timeouts.ts +0 -10
- package/src/contacts/contact-store.ts +63 -0
- package/src/contacts/contacts-write.ts +1 -1
- package/src/daemon/assistant-attachments.ts +2 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
- package/src/daemon/conversation-agent-loop.ts +7 -30
- package/src/daemon/conversation-error.ts +24 -0
- package/src/daemon/conversation-memory.ts +8 -7
- package/src/daemon/conversation-runtime-assembly.ts +139 -274
- package/src/daemon/conversation-slash.ts +7 -26
- package/src/daemon/conversation-surfaces.ts +14 -0
- package/src/daemon/conversation-tool-setup.ts +9 -8
- package/src/daemon/conversation.ts +2 -0
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +10 -83
- package/src/daemon/handlers/config-channels.ts +12 -2
- package/src/daemon/handlers/config-slack-channel.ts +7 -1
- package/src/daemon/handlers/config-telegram.ts +6 -1
- package/src/daemon/handlers/conversations.ts +2 -2
- package/src/daemon/handlers/skills.ts +4 -0
- package/src/daemon/lifecycle.ts +28 -4
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +1 -5
- package/src/daemon/shutdown-handlers.ts +9 -3
- package/src/daemon/tool-side-effects.ts +40 -0
- package/src/daemon/trace-emitter.ts +25 -2
- package/src/events/domain-events.ts +1 -1
- package/src/events/tool-permission-telemetry-listener.ts +46 -0
- package/src/inbound/platform-callback-registration.ts +0 -18
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +15 -8
- package/src/media/gemini-image-service.ts +125 -21
- package/src/memory/attachments-store.ts +3 -3
- package/src/memory/channel-verification-sessions.ts +6 -6
- package/src/memory/conversation-crud.ts +196 -1
- package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
- package/src/memory/conversation-title-service.ts +2 -3
- package/src/memory/db-init.ts +25 -1
- package/src/memory/invite-store.ts +4 -4
- package/src/memory/items-extractor.ts +4 -4
- package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/jobs-worker.ts +7 -5
- package/src/memory/lifecycle-events-store.ts +63 -0
- package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
- package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
- package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
- package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
- package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
- package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +223 -96
- package/src/memory/retriever.ts +115 -138
- package/src/memory/schema/calls.ts +1 -1
- package/src/memory/schema/contacts.ts +1 -1
- package/src/memory/schema/infrastructure.ts +29 -0
- package/src/memory/schema/memory-core.ts +7 -17
- package/src/memory/schema/notifications.ts +1 -1
- package/src/memory/search/formatting.ts +23 -6
- package/src/memory/search/lexical.ts +2 -0
- package/src/memory/search/semantic.ts +2 -0
- package/src/memory/search/staleness.ts +1 -0
- package/src/memory/search/types.ts +4 -0
- package/src/memory/task-memory-cleanup.ts +96 -6
- package/src/memory/trace-event-store.ts +148 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/emit-signal.ts +4 -4
- package/src/notifications/events-store.ts +4 -4
- package/src/notifications/signal.ts +1 -1
- package/src/oauth/manual-token-connection.ts +49 -25
- package/src/permissions/checker.ts +6 -5
- package/src/permissions/defaults.ts +4 -4
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
- package/src/prompts/cache-boundary.ts +8 -0
- package/src/prompts/system-prompt.ts +105 -634
- package/src/prompts/templates/BOOTSTRAP.md +166 -33
- package/src/prompts/templates/IDENTITY.md +8 -23
- package/src/prompts/templates/SOUL.md +20 -41
- package/src/prompts/templates/USER.md +3 -19
- package/src/prompts/user-reference.ts +14 -16
- package/src/providers/anthropic/client.ts +46 -2
- package/src/providers/gemini/client.ts +6 -9
- package/src/providers/managed-proxy/constants.ts +1 -7
- package/src/providers/managed-proxy/context.ts +0 -1
- package/src/providers/model-intents.ts +5 -5
- package/src/providers/openai/client.ts +10 -1
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/ratelimit.ts +0 -35
- package/src/providers/registry.ts +3 -5
- package/src/providers/retry.ts +18 -1
- package/src/runtime/access-request-helper.ts +1 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/channel-verification-service.ts +1 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/guardian-vellum-migration.ts +63 -1
- package/src/runtime/http-server.ts +8 -4
- package/src/runtime/migrations/vbundle-builder.ts +212 -32
- package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
- package/src/runtime/migrations/vbundle-importer.ts +66 -1
- package/src/runtime/migrations/vbundle-validator.ts +17 -3
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
- package/src/runtime/routes/attachment-routes.ts +2 -2
- package/src/runtime/routes/btw-routes.ts +9 -0
- package/src/runtime/routes/channel-verification-routes.ts +19 -2
- package/src/runtime/routes/conversation-management-routes.ts +55 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +49 -5
- package/src/runtime/routes/conversation-starter-routes.ts +207 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +25 -13
- package/src/runtime/routes/secret-routes.ts +18 -0
- package/src/runtime/routes/settings-routes.ts +8 -8
- package/src/runtime/routes/telemetry-routes.ts +53 -0
- package/src/runtime/routes/trace-event-routes.ts +62 -0
- package/src/runtime/tool-grant-request-helper.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +47 -31
- package/src/security/encrypted-store.ts +263 -78
- package/src/skills/catalog-install.ts +10 -0
- package/src/skills/managed-store.ts +2 -0
- package/src/skills/skill-memory.ts +220 -0
- package/src/subagent/manager.ts +1 -4
- package/src/telemetry/types.ts +10 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/telemetry/usage-telemetry-reporter.ts +51 -4
- package/src/tools/AGENTS.md +11 -11
- package/src/tools/acp/spawn.ts +1 -1
- package/src/tools/apps/executors.ts +8 -8
- package/src/tools/apps/registry.ts +1 -1
- package/src/tools/assets/materialize.ts +6 -6
- package/src/tools/assets/search.ts +10 -10
- package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
- package/src/tools/browser/auth-detector.ts +6 -6
- package/src/tools/browser/browser-execution.ts +13 -13
- package/src/tools/browser/browser-manager.ts +3 -3
- package/src/tools/browser/chrome-cdp.ts +5 -5
- package/src/tools/browser/jit-auth.ts +2 -2
- package/src/tools/browser/network-recorder.test.ts +2 -2
- package/src/tools/browser/network-recorder.ts +3 -3
- package/src/tools/browser/runtime-check.ts +3 -3
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/computer-use/definitions.ts +18 -18
- package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
- package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
- package/src/tools/credentials/broker-types.ts +5 -5
- package/src/tools/credentials/broker.ts +15 -15
- package/src/tools/credentials/metadata-store.ts +2 -2
- package/src/tools/credentials/resolve.ts +1 -1
- package/src/tools/credentials/selection.ts +1 -1
- package/src/tools/credentials/tool-policy.ts +1 -1
- package/src/tools/credentials/vault.ts +115 -25
- package/src/tools/execution-target.ts +2 -2
- package/src/tools/executor.ts +7 -7
- package/src/tools/filesystem/edit.ts +2 -2
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +1 -1
- package/src/tools/host-filesystem/edit.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -1
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +9 -8
- package/src/tools/mcp/mcp-tool-factory.ts +7 -6
- package/src/tools/memory/definitions.ts +6 -5
- package/src/tools/memory/handlers.test.ts +1 -1
- package/src/tools/network/__tests__/web-search.test.ts +3 -3
- package/src/tools/network/domain-normalize.ts +2 -2
- package/src/tools/network/script-proxy/session-manager.ts +10 -10
- package/src/tools/network/web-fetch.ts +1 -1
- package/src/tools/network/web-search.ts +3 -3
- package/src/tools/permission-checker.ts +8 -8
- package/src/tools/registry.ts +7 -7
- package/src/tools/schedule/list.ts +2 -2
- package/src/tools/schema-transforms.ts +31 -21
- package/src/tools/secret-detection-handler.ts +1 -1
- package/src/tools/sensitive-output-placeholders.ts +1 -1
- package/src/tools/shared/filesystem/edit-engine.ts +1 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
- package/src/tools/shared/filesystem/image-read.ts +25 -5
- package/src/tools/shared/filesystem/path-policy.ts +2 -2
- package/src/tools/shared/shell-output.ts +1 -1
- package/src/tools/side-effects.ts +1 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +3 -3
- package/src/tools/skills/sandbox-runner.ts +3 -3
- package/src/tools/subagent/read.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -2
- package/src/tools/swarm/delegate.ts +3 -3
- package/src/tools/system/request-permission.ts +5 -4
- package/src/tools/terminal/backends/native.ts +4 -4
- package/src/tools/terminal/parser.ts +6 -6
- package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
- package/src/tools/terminal/shell.ts +16 -16
- package/src/tools/tool-approval-handler.ts +21 -12
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +3 -3
- package/src/tools/ui-surface/definitions.ts +9 -37
- package/src/tools/watcher/list.ts +1 -1
- package/src/util/logger.ts +7 -2
- package/src/util/retry.ts +29 -1
- package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
- package/src/cli/reference.ts +0 -38
- package/src/memory/job-handlers/capability-cards.ts +0 -420
- package/src/runtime/routes/thread-starter-routes.ts +0 -294
package/src/memory/retriever.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { inArray, sql } from "drizzle-orm";
|
|
1
|
+
import { asc, eq, inArray, sql } from "drizzle-orm";
|
|
2
2
|
|
|
3
3
|
import type { AssistantConfig } from "../config/types.js";
|
|
4
4
|
import { estimateTextTokens } from "../context/token-estimator.js";
|
|
5
|
+
import type { Message } from "../providers/types.js";
|
|
5
6
|
import { getLogger } from "../util/logger.js";
|
|
6
7
|
import {
|
|
7
8
|
abortableSleep,
|
|
@@ -24,8 +25,8 @@ import {
|
|
|
24
25
|
} from "./schema.js";
|
|
25
26
|
import {
|
|
26
27
|
buildTwoLayerInjection,
|
|
28
|
+
CAPABILITY_KINDS,
|
|
27
29
|
IDENTITY_KINDS,
|
|
28
|
-
MEMORY_CONTEXT_ACK,
|
|
29
30
|
PREFERENCE_KINDS,
|
|
30
31
|
} from "./search/formatting.js";
|
|
31
32
|
import { recencySearch } from "./search/lexical.js";
|
|
@@ -354,6 +355,44 @@ export async function buildMemoryRecall(
|
|
|
354
355
|
if (c.text.length > existing.text.length) {
|
|
355
356
|
existing.text = c.text;
|
|
356
357
|
}
|
|
358
|
+
// Propagate metadata that the first source may lack (e.g. legacy
|
|
359
|
+
// Qdrant points missing conversation_id / message_id). The recency
|
|
360
|
+
// source always has these from the DB, so merging fills the gap.
|
|
361
|
+
if (c.conversationId && !existing.conversationId) {
|
|
362
|
+
existing.conversationId = c.conversationId;
|
|
363
|
+
}
|
|
364
|
+
if (c.messageId && !existing.messageId) {
|
|
365
|
+
existing.messageId = c.messageId;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ── Step 5b: Filter out current-conversation segments still in context ──
|
|
370
|
+
// Segments whose source message is still in the conversation's context
|
|
371
|
+
// window are redundant (already visible to the model). However, segments
|
|
372
|
+
// from messages that were removed by context compaction should be kept —
|
|
373
|
+
// those messages are no longer in the conversation history and memory is
|
|
374
|
+
// the only way they can influence the response.
|
|
375
|
+
if (conversationId) {
|
|
376
|
+
const inContextMessageIds = getInContextMessageIds(conversationId);
|
|
377
|
+
if (inContextMessageIds) {
|
|
378
|
+
for (const [key, c] of candidateMap) {
|
|
379
|
+
if (c.type === "segment") {
|
|
380
|
+
if (c.messageId) {
|
|
381
|
+
// Segment has a known source message — filter only if that
|
|
382
|
+
// message is still in the context window.
|
|
383
|
+
if (inContextMessageIds.has(c.messageId)) {
|
|
384
|
+
candidateMap.delete(key);
|
|
385
|
+
}
|
|
386
|
+
} else if (c.conversationId === conversationId) {
|
|
387
|
+
// Segment from the current conversation but missing messageId
|
|
388
|
+
// (e.g. legacy Qdrant points without message_id payload).
|
|
389
|
+
// We can't determine whether it's compacted, so err on the
|
|
390
|
+
// side of filtering to avoid token bloat from redundant segments.
|
|
391
|
+
candidateMap.delete(key);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
357
396
|
}
|
|
358
397
|
|
|
359
398
|
// Compute RRF-style final scores for the merged candidates
|
|
@@ -427,11 +466,15 @@ export async function buildMemoryRecall(
|
|
|
427
466
|
const preferences = afterDemotion.filter(
|
|
428
467
|
(c) => c.tier === 1 && PREFERENCE_KINDS.has(c.kind),
|
|
429
468
|
);
|
|
469
|
+
const capabilities = afterDemotion.filter(
|
|
470
|
+
(c) => c.tier === 1 && CAPABILITY_KINDS.has(c.kind),
|
|
471
|
+
);
|
|
430
472
|
const tier1Candidates = afterDemotion.filter(
|
|
431
473
|
(c) =>
|
|
432
474
|
c.tier === 1 &&
|
|
433
475
|
!IDENTITY_KINDS.has(c.kind) &&
|
|
434
|
-
!PREFERENCE_KINDS.has(c.kind)
|
|
476
|
+
!PREFERENCE_KINDS.has(c.kind) &&
|
|
477
|
+
!CAPABILITY_KINDS.has(c.kind),
|
|
435
478
|
);
|
|
436
479
|
const tier2Candidates = afterDemotion.filter((c) => c.tier === 2);
|
|
437
480
|
|
|
@@ -440,6 +483,7 @@ export async function buildMemoryRecall(
|
|
|
440
483
|
tier1Candidates,
|
|
441
484
|
tier2Candidates,
|
|
442
485
|
preferences,
|
|
486
|
+
capabilities,
|
|
443
487
|
totalBudgetTokens: maxInjectTokens,
|
|
444
488
|
});
|
|
445
489
|
|
|
@@ -448,7 +492,8 @@ export async function buildMemoryRecall(
|
|
|
448
492
|
identityItems.length +
|
|
449
493
|
tier1Candidates.length +
|
|
450
494
|
tier2Candidates.length +
|
|
451
|
-
preferences.length
|
|
495
|
+
preferences.length +
|
|
496
|
+
capabilities.length;
|
|
452
497
|
|
|
453
498
|
const tier1Count = afterDemotion.filter((c) => c.tier === 1).length;
|
|
454
499
|
const tier2Count = afterDemotion.filter((c) => c.tier === 2).length;
|
|
@@ -528,6 +573,52 @@ export async function buildMemoryRecall(
|
|
|
528
573
|
return result;
|
|
529
574
|
}
|
|
530
575
|
|
|
576
|
+
/**
|
|
577
|
+
* Get the set of message IDs that are still in the conversation's context
|
|
578
|
+
* window (i.e., not compacted away). Uses `contextCompactedMessageCount` to
|
|
579
|
+
* determine the offset: messages ordered by createdAt after that count are
|
|
580
|
+
* still visible to the model.
|
|
581
|
+
*
|
|
582
|
+
* Returns `null` if the conversation is not found (deleted, or no DB row).
|
|
583
|
+
*/
|
|
584
|
+
function getInContextMessageIds(conversationId: string): Set<string> | null {
|
|
585
|
+
try {
|
|
586
|
+
const db = getDb();
|
|
587
|
+
|
|
588
|
+
// Look up the conversation's compacted message count
|
|
589
|
+
const conv = db
|
|
590
|
+
.select({
|
|
591
|
+
contextCompactedMessageCount:
|
|
592
|
+
conversations.contextCompactedMessageCount,
|
|
593
|
+
})
|
|
594
|
+
.from(conversations)
|
|
595
|
+
.where(eq(conversations.id, conversationId))
|
|
596
|
+
.get();
|
|
597
|
+
|
|
598
|
+
if (!conv) return null;
|
|
599
|
+
|
|
600
|
+
const offset = conv.contextCompactedMessageCount;
|
|
601
|
+
|
|
602
|
+
// Fetch message IDs ordered by creation time, skipping compacted ones
|
|
603
|
+
const rows = db
|
|
604
|
+
.select({ id: messages.id })
|
|
605
|
+
.from(messages)
|
|
606
|
+
.where(eq(messages.conversationId, conversationId))
|
|
607
|
+
.orderBy(asc(messages.createdAt))
|
|
608
|
+
.all();
|
|
609
|
+
|
|
610
|
+
// Messages up to `offset` have been compacted out of context
|
|
611
|
+
const inContextRows = rows.slice(offset);
|
|
612
|
+
return new Set(inContextRows.map((r) => r.id));
|
|
613
|
+
} catch (err) {
|
|
614
|
+
log.warn(
|
|
615
|
+
{ err },
|
|
616
|
+
"Failed to fetch in-context message IDs; skipping segment filter",
|
|
617
|
+
);
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
531
622
|
/**
|
|
532
623
|
* Enrich item candidates with metadata needed for staleness computation:
|
|
533
624
|
* - firstSeenAt: when the item was first extracted
|
|
@@ -671,146 +762,32 @@ function enrichSourceLabels(candidates: TieredCandidate[]): void {
|
|
|
671
762
|
}
|
|
672
763
|
|
|
673
764
|
/**
|
|
674
|
-
*
|
|
765
|
+
* Inject memory recall as a text content block prepended to the last user
|
|
766
|
+
* message. This follows the same pattern as workspace, temporal, and other
|
|
767
|
+
* runtime injections — the memory context is a text block in the user
|
|
768
|
+
* message rather than a separate synthetic message pair.
|
|
675
769
|
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
* tag (covering cases where the exact text differs slightly due to
|
|
680
|
-
* dynamic content).
|
|
770
|
+
* Stripping is handled by `stripUserTextBlocksByPrefix` matching the
|
|
771
|
+
* `<memory_context __injected>` prefix in `RUNTIME_INJECTION_PREFIXES`, so no
|
|
772
|
+
* dedicated strip function is needed.
|
|
681
773
|
*/
|
|
682
|
-
export function
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
},
|
|
687
|
-
>(
|
|
688
|
-
messages: T[],
|
|
689
|
-
memoryRecallText?: string,
|
|
690
|
-
injectionStrategy?: "prepend_user_block" | "separate_context_message",
|
|
691
|
-
): T[] {
|
|
692
|
-
const recallText = memoryRecallText ?? "";
|
|
693
|
-
if (recallText.trim().length === 0) return messages;
|
|
694
|
-
|
|
695
|
-
const isAck = (msg: T) =>
|
|
696
|
-
msg.role === "assistant" &&
|
|
697
|
-
msg.content.length === 1 &&
|
|
698
|
-
msg.content[0].type === "text" &&
|
|
699
|
-
msg.content[0].text === MEMORY_CONTEXT_ACK;
|
|
700
|
-
|
|
701
|
-
// Check if the recall text uses the <memory_context> XML format
|
|
702
|
-
const isMemoryContextFormat = recallText
|
|
703
|
-
.trimStart()
|
|
704
|
-
.startsWith("<memory_context>");
|
|
705
|
-
|
|
706
|
-
// Helper: does a text block match the recall text?
|
|
707
|
-
const textMatches = (text: string | undefined): boolean => {
|
|
708
|
-
if (!text) return false;
|
|
709
|
-
if (text === recallText) return true;
|
|
710
|
-
// For <memory_context> format, match any block that starts with the tag
|
|
711
|
-
if (
|
|
712
|
-
isMemoryContextFormat &&
|
|
713
|
-
text.trimStart().startsWith("<memory_context>")
|
|
714
|
-
) {
|
|
715
|
-
return true;
|
|
716
|
-
}
|
|
717
|
-
return false;
|
|
718
|
-
};
|
|
719
|
-
|
|
720
|
-
// Prefer the canonical separate_context_message pair: a user message whose
|
|
721
|
-
// sole text block is the recall text, followed by an assistant ack. This
|
|
722
|
-
// must be checked first so that a real user message that happens to contain
|
|
723
|
-
// the same text is not incorrectly removed instead of the synthetic one.
|
|
724
|
-
if (injectionStrategy !== "prepend_user_block") {
|
|
725
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
726
|
-
const msg = messages[i];
|
|
727
|
-
if (msg.role !== "user") continue;
|
|
728
|
-
if (msg.content.length !== 1) continue;
|
|
729
|
-
const block = msg.content[0];
|
|
730
|
-
if (block.type !== "text" || !textMatches(block.text)) continue;
|
|
731
|
-
const next = messages[i + 1];
|
|
732
|
-
if (next && isAck(next)) {
|
|
733
|
-
return [...messages.slice(0, i), ...messages.slice(i + 2)];
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
// Fall back to generic text-match removal: find the last user message
|
|
739
|
-
// containing the recall text block.
|
|
740
|
-
let targetIndex = -1;
|
|
741
|
-
let blockIndex = -1;
|
|
742
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
743
|
-
const msg = messages[i];
|
|
744
|
-
if (msg.role !== "user" || msg.content.length === 0) continue;
|
|
745
|
-
for (let bi = msg.content.length - 1; bi >= 0; bi--) {
|
|
746
|
-
const block = msg.content[bi];
|
|
747
|
-
if (block.type === "text" && textMatches(block.text)) {
|
|
748
|
-
targetIndex = i;
|
|
749
|
-
blockIndex = bi;
|
|
750
|
-
break;
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
if (targetIndex !== -1) break;
|
|
754
|
-
}
|
|
755
|
-
if (targetIndex === -1) return messages;
|
|
756
|
-
|
|
757
|
-
// Strip the adjacent assistant ack when the injection strategy used a
|
|
758
|
-
// separate context message (or is unknown). This mirrors the canonical
|
|
759
|
-
// pair removal above but covers repair-merged cases where the user
|
|
760
|
-
// message has multiple content blocks.
|
|
761
|
-
const ackIndex =
|
|
762
|
-
injectionStrategy !== "prepend_user_block" &&
|
|
763
|
-
targetIndex + 1 < messages.length &&
|
|
764
|
-
isAck(messages[targetIndex + 1])
|
|
765
|
-
? targetIndex + 1
|
|
766
|
-
: -1;
|
|
767
|
-
|
|
768
|
-
const cleaned: T[] = [];
|
|
769
|
-
for (let i = 0; i < messages.length; i++) {
|
|
770
|
-
if (i === ackIndex) continue;
|
|
771
|
-
if (i !== targetIndex) {
|
|
772
|
-
cleaned.push(messages[i]);
|
|
773
|
-
continue;
|
|
774
|
-
}
|
|
775
|
-
const filteredContent = [
|
|
776
|
-
...messages[i].content.slice(0, blockIndex),
|
|
777
|
-
...messages[i].content.slice(blockIndex + 1),
|
|
778
|
-
];
|
|
779
|
-
if (filteredContent.length === 0) continue;
|
|
780
|
-
cleaned.push({ ...messages[i], content: filteredContent } as T);
|
|
781
|
-
}
|
|
782
|
-
return cleaned;
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
/**
|
|
786
|
-
* Inject memory recall as a separate user+assistant message pair before the
|
|
787
|
-
* last user message. This separates memory context from the user's actual
|
|
788
|
-
* query, making it clearer to the model that the memory is background context.
|
|
789
|
-
*/
|
|
790
|
-
export function injectMemoryRecallAsSeparateMessage<
|
|
791
|
-
T extends {
|
|
792
|
-
role: "user" | "assistant";
|
|
793
|
-
content: Array<{ type: string; text?: string }>;
|
|
794
|
-
},
|
|
795
|
-
>(messages: T[], memoryRecallText: string): T[] {
|
|
774
|
+
export function injectMemoryRecallAsUserBlock(
|
|
775
|
+
messages: Message[],
|
|
776
|
+
memoryRecallText: string,
|
|
777
|
+
): Message[] {
|
|
796
778
|
if (memoryRecallText.trim().length === 0) return messages;
|
|
797
779
|
if (messages.length === 0) return messages;
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
// only role and content, so the cast is safe.
|
|
801
|
-
const contextMessage = {
|
|
802
|
-
role: "user" as const,
|
|
803
|
-
content: [{ type: "text" as const, text: memoryRecallText }],
|
|
804
|
-
} as T;
|
|
805
|
-
const ackMessage = {
|
|
806
|
-
role: "assistant" as const,
|
|
807
|
-
content: [{ type: "text" as const, text: MEMORY_CONTEXT_ACK }],
|
|
808
|
-
} as T;
|
|
780
|
+
const userTail = messages[messages.length - 1];
|
|
781
|
+
if (!userTail || userTail.role !== "user") return messages;
|
|
809
782
|
return [
|
|
810
783
|
...messages.slice(0, -1),
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
784
|
+
{
|
|
785
|
+
...userTail,
|
|
786
|
+
content: [
|
|
787
|
+
{ type: "text" as const, text: memoryRecallText },
|
|
788
|
+
...userTail.content,
|
|
789
|
+
],
|
|
790
|
+
},
|
|
814
791
|
];
|
|
815
792
|
}
|
|
816
793
|
|
|
@@ -95,7 +95,7 @@ export const channelVerificationSessions = sqliteTable(
|
|
|
95
95
|
challengeHash: text("challenge_hash").notNull(),
|
|
96
96
|
expiresAt: integer("expires_at").notNull(),
|
|
97
97
|
status: text("status").notNull().default("pending"),
|
|
98
|
-
|
|
98
|
+
sourceConversationId: text("source_conversation_id"),
|
|
99
99
|
consumedByExternalUserId: text("consumed_by_external_user_id"),
|
|
100
100
|
consumedByChatId: text("consumed_by_chat_id"),
|
|
101
101
|
// Outbound session: expected-identity binding
|
|
@@ -69,7 +69,7 @@ export const assistantIngressInvites = sqliteTable(
|
|
|
69
69
|
id: text("id").primaryKey(),
|
|
70
70
|
sourceChannel: text("source_channel").notNull(),
|
|
71
71
|
tokenHash: text("token_hash").notNull(),
|
|
72
|
-
|
|
72
|
+
sourceConversationId: text("source_conversation_id"),
|
|
73
73
|
note: text("note"),
|
|
74
74
|
maxUses: integer("max_uses").notNull().default(1),
|
|
75
75
|
useCount: integer("use_count").notNull().default(0),
|
|
@@ -138,6 +138,12 @@ export const llmUsageEvents = sqliteTable(
|
|
|
138
138
|
],
|
|
139
139
|
);
|
|
140
140
|
|
|
141
|
+
export const lifecycleEvents = sqliteTable("lifecycle_events", {
|
|
142
|
+
id: text("id").primaryKey(),
|
|
143
|
+
eventName: text("event_name").notNull(), // 'app_open' | 'hatch'
|
|
144
|
+
createdAt: integer("created_at").notNull(),
|
|
145
|
+
});
|
|
146
|
+
|
|
141
147
|
export const actorTokenRecords = sqliteTable("actor_token_records", {
|
|
142
148
|
id: text("id").primaryKey(),
|
|
143
149
|
tokenHash: text("token_hash").notNull(),
|
|
@@ -151,6 +157,29 @@ export const actorTokenRecords = sqliteTable("actor_token_records", {
|
|
|
151
157
|
updatedAt: integer("updated_at").notNull(),
|
|
152
158
|
});
|
|
153
159
|
|
|
160
|
+
export const traceEvents = sqliteTable(
|
|
161
|
+
"trace_events",
|
|
162
|
+
{
|
|
163
|
+
eventId: text("event_id").primaryKey(),
|
|
164
|
+
conversationId: text("conversation_id").notNull(),
|
|
165
|
+
requestId: text("request_id"),
|
|
166
|
+
timestampMs: integer("timestamp_ms").notNull(),
|
|
167
|
+
sequence: integer("sequence").notNull(),
|
|
168
|
+
kind: text("kind").notNull(),
|
|
169
|
+
status: text("status"),
|
|
170
|
+
summary: text("summary").notNull(),
|
|
171
|
+
attributesJson: text("attributes_json"), // JSON-serialized attributes
|
|
172
|
+
createdAt: integer("created_at").notNull(),
|
|
173
|
+
},
|
|
174
|
+
(table) => [
|
|
175
|
+
index("idx_trace_events_conversation_id").on(table.conversationId),
|
|
176
|
+
index("idx_trace_events_conversation_timestamp").on(
|
|
177
|
+
table.conversationId,
|
|
178
|
+
table.timestampMs,
|
|
179
|
+
),
|
|
180
|
+
],
|
|
181
|
+
);
|
|
182
|
+
|
|
154
183
|
export const actorRefreshTokenRecords = sqliteTable(
|
|
155
184
|
"actor_refresh_token_records",
|
|
156
185
|
{
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
blob,
|
|
3
3
|
index,
|
|
4
4
|
integer,
|
|
5
|
-
primaryKey,
|
|
6
5
|
real,
|
|
7
6
|
sqliteTable,
|
|
8
7
|
text,
|
|
@@ -150,8 +149,8 @@ export const memoryCheckpoints = sqliteTable("memory_checkpoints", {
|
|
|
150
149
|
updatedAt: integer("updated_at").notNull(),
|
|
151
150
|
});
|
|
152
151
|
|
|
153
|
-
export const
|
|
154
|
-
"
|
|
152
|
+
export const conversationStarters = sqliteTable(
|
|
153
|
+
"conversation_starters",
|
|
155
154
|
{
|
|
156
155
|
id: text("id").primaryKey(),
|
|
157
156
|
label: text("label").notNull(),
|
|
@@ -167,22 +166,13 @@ export const threadStarters = sqliteTable(
|
|
|
167
166
|
createdAt: integer("created_at").notNull(),
|
|
168
167
|
},
|
|
169
168
|
(table) => [
|
|
170
|
-
index("
|
|
169
|
+
index("idx_conversation_starters_batch").on(
|
|
171
170
|
table.generationBatch,
|
|
172
171
|
table.createdAt,
|
|
173
172
|
),
|
|
174
|
-
index("
|
|
173
|
+
index("idx_conversation_starters_card_type").on(
|
|
174
|
+
table.cardType,
|
|
175
|
+
table.scopeId,
|
|
176
|
+
),
|
|
175
177
|
],
|
|
176
178
|
);
|
|
177
|
-
|
|
178
|
-
export const capabilityCardCategories = sqliteTable(
|
|
179
|
-
"capability_card_categories",
|
|
180
|
-
{
|
|
181
|
-
scopeId: text("scope_id").notNull(),
|
|
182
|
-
category: text("category").notNull(),
|
|
183
|
-
relevance: real("relevance").notNull(),
|
|
184
|
-
generationBatch: integer("generation_batch").notNull(),
|
|
185
|
-
createdAt: integer("created_at").notNull(),
|
|
186
|
-
},
|
|
187
|
-
(table) => [primaryKey({ columns: [table.scopeId, table.category] })],
|
|
188
|
-
);
|
|
@@ -13,7 +13,7 @@ export const notificationEvents = sqliteTable("notification_events", {
|
|
|
13
13
|
id: text("id").primaryKey(),
|
|
14
14
|
sourceEventName: text("source_event_name").notNull(),
|
|
15
15
|
sourceChannel: text("source_channel").notNull(),
|
|
16
|
-
|
|
16
|
+
sourceContextId: text("source_context_id").notNull(),
|
|
17
17
|
attentionHintsJson: text("attention_hints_json").notNull().default("{}"),
|
|
18
18
|
payloadJson: text("payload_json").notNull().default("{}"),
|
|
19
19
|
dedupeKey: text("dedupe_key"),
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { estimateTextTokens } from "../../context/token-estimator.js";
|
|
2
2
|
import type { TieredCandidate } from "./tier-classifier.js";
|
|
3
3
|
|
|
4
|
-
/** Marker text used in the assistant acknowledgment of a separate context message. */
|
|
5
|
-
export const MEMORY_CONTEXT_ACK = "[Memory context loaded.]";
|
|
6
|
-
|
|
7
4
|
/**
|
|
8
5
|
* Escape XML-like tag sequences in recalled text to prevent delimiter injection.
|
|
9
6
|
* Recalled content is interpolated verbatim inside `<memory>` wrapper tags,
|
|
@@ -80,6 +77,9 @@ export const IDENTITY_KINDS = new Set(["identity"]);
|
|
|
80
77
|
/** Kinds classified as preferences for the <applicable_preferences> section. */
|
|
81
78
|
export const PREFERENCE_KINDS = new Set(["preference", "constraint"]);
|
|
82
79
|
|
|
80
|
+
/** Kinds classified as capabilities for the <available_capabilities> section. */
|
|
81
|
+
export const CAPABILITY_KINDS = new Set(["capability"]);
|
|
82
|
+
|
|
83
83
|
/** Per-item token budget for tier 1 items. */
|
|
84
84
|
const TIER1_PER_ITEM_TOKENS = 150;
|
|
85
85
|
|
|
@@ -105,6 +105,7 @@ export function buildTwoLayerInjection(params: {
|
|
|
105
105
|
tier1Candidates: TieredCandidate[];
|
|
106
106
|
tier2Candidates: TieredCandidate[];
|
|
107
107
|
preferences: TieredCandidate[];
|
|
108
|
+
capabilities: TieredCandidate[];
|
|
108
109
|
totalBudgetTokens?: number;
|
|
109
110
|
}): string {
|
|
110
111
|
const {
|
|
@@ -112,6 +113,7 @@ export function buildTwoLayerInjection(params: {
|
|
|
112
113
|
tier1Candidates,
|
|
113
114
|
tier2Candidates,
|
|
114
115
|
preferences,
|
|
116
|
+
capabilities,
|
|
115
117
|
totalBudgetTokens,
|
|
116
118
|
} = params;
|
|
117
119
|
|
|
@@ -120,7 +122,8 @@ export function buildTwoLayerInjection(params: {
|
|
|
120
122
|
identityItems.length === 0 &&
|
|
121
123
|
tier1Candidates.length === 0 &&
|
|
122
124
|
tier2Candidates.length === 0 &&
|
|
123
|
-
preferences.length === 0
|
|
125
|
+
preferences.length === 0 &&
|
|
126
|
+
capabilities.length === 0
|
|
124
127
|
) {
|
|
125
128
|
return "";
|
|
126
129
|
}
|
|
@@ -129,7 +132,7 @@ export function buildTwoLayerInjection(params: {
|
|
|
129
132
|
// Reserve tokens for XML wrapper overhead (<memory_context>, section tags,
|
|
130
133
|
// newlines between sections) so the final assembled text stays within budget.
|
|
131
134
|
const WRAPPER_OVERHEAD_TOKENS = estimateTextTokens(
|
|
132
|
-
"<memory_context>\n\n\n\n</memory_context>",
|
|
135
|
+
"<memory_context __injected>\n\n\n\n</memory_context>",
|
|
133
136
|
);
|
|
134
137
|
const SECTION_TAG_TOKENS = estimateTextTokens(
|
|
135
138
|
"<possibly_relevant>\n\n</possibly_relevant>",
|
|
@@ -139,6 +142,7 @@ export function buildTwoLayerInjection(params: {
|
|
|
139
142
|
tier1Candidates.length,
|
|
140
143
|
tier2Candidates.length,
|
|
141
144
|
preferences.length,
|
|
145
|
+
capabilities.length,
|
|
142
146
|
].filter((n) => n > 0).length;
|
|
143
147
|
const structuralOverhead =
|
|
144
148
|
WRAPPER_OVERHEAD_TOKENS + sectionCount * SECTION_TAG_TOKENS;
|
|
@@ -168,6 +172,13 @@ export function buildTwoLayerInjection(params: {
|
|
|
168
172
|
);
|
|
169
173
|
remainingTokens -= estimateTextTokens(preferenceLines.join("\n"));
|
|
170
174
|
|
|
175
|
+
const capabilityLines = renderPlainStatements(
|
|
176
|
+
capabilities,
|
|
177
|
+
TIER1_PER_ITEM_TOKENS,
|
|
178
|
+
remainingTokens,
|
|
179
|
+
);
|
|
180
|
+
remainingTokens -= estimateTextTokens(capabilityLines.join("\n"));
|
|
181
|
+
|
|
171
182
|
// Tier 2 uses remaining budget
|
|
172
183
|
const possiblyRelevantEpisodes = renderEpisodesWithStaleness(
|
|
173
184
|
tier2Candidates,
|
|
@@ -196,6 +207,12 @@ export function buildTwoLayerInjection(params: {
|
|
|
196
207
|
);
|
|
197
208
|
}
|
|
198
209
|
|
|
210
|
+
if (capabilityLines.length > 0) {
|
|
211
|
+
sections.push(
|
|
212
|
+
`<available_capabilities>\n${capabilityLines.join("\n")}\n</available_capabilities>`,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
199
216
|
if (possiblyRelevantEpisodes.length > 0) {
|
|
200
217
|
sections.push(
|
|
201
218
|
`<possibly_relevant>\n${possiblyRelevantEpisodes.join("\n")}\n</possibly_relevant>`,
|
|
@@ -204,7 +221,7 @@ export function buildTwoLayerInjection(params: {
|
|
|
204
221
|
|
|
205
222
|
if (sections.length === 0) return "";
|
|
206
223
|
|
|
207
|
-
return `<memory_context>\n\n${sections.join("\n\n")}\n\n</memory_context>`;
|
|
224
|
+
return `<memory_context __injected>\n\n${sections.join("\n\n")}\n\n</memory_context>`;
|
|
208
225
|
}
|
|
209
226
|
|
|
210
227
|
/**
|
|
@@ -11,6 +11,10 @@ export interface Candidate {
|
|
|
11
11
|
text: string;
|
|
12
12
|
kind: string;
|
|
13
13
|
modality?: "text" | "image" | "audio" | "video";
|
|
14
|
+
/** The conversation this candidate originated from (segments only). */
|
|
15
|
+
conversationId?: string;
|
|
16
|
+
/** The source message ID this candidate was extracted from (segments only). */
|
|
17
|
+
messageId?: string;
|
|
14
18
|
confidence: number;
|
|
15
19
|
importance: number;
|
|
16
20
|
createdAt: number;
|