openclaw-hybrid-memory 2026.5.310 → 2026.6.10
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/api/plugin-runtime.ts +2 -0
- package/backends/facts-db/contradictions.ts +1 -1
- package/cli/cmd-extract-directives.ts +225 -11
- package/cli/cmd-extract-proposals.ts +5 -6
- package/cli/cmd-extract-reinforcement.ts +71 -0
- package/cli/cmd-feedback.ts +15 -9
- package/cli/commands/manage/register-reflection-pipeline.ts +247 -13
- package/cli/commands/manage/register-storage-maintenance.ts +224 -15
- package/cli/commands/manage/storage-stats-helpers.ts +13 -2
- package/cli/context.ts +9 -19
- package/cli/distill.ts +31 -1
- package/cli/register.ts +28 -38
- package/dist/api/plugin-runtime.js.map +1 -1
- package/dist/backends/agent-health-store.js.map +1 -1
- package/dist/backends/apitap-store.js.map +1 -1
- package/dist/backends/audit-store.js.map +1 -1
- package/dist/backends/base-sqlite-store.js.map +1 -1
- package/dist/backends/cost-tracker.js.map +1 -1
- package/dist/backends/credentials-db.js +2 -3
- package/dist/backends/credentials-db.js.map +1 -1
- package/dist/backends/crystallization-store.js.map +1 -1
- package/dist/backends/edict-store.js.map +1 -1
- package/dist/backends/event-bus.js.map +1 -1
- package/dist/backends/event-log.js.map +1 -1
- package/dist/backends/facts-db/cache-manager.js.map +1 -1
- package/dist/backends/facts-db/clusters.js.map +1 -1
- package/dist/backends/facts-db/contradictions.js +1 -1
- package/dist/backends/facts-db/contradictions.js.map +1 -1
- package/dist/backends/facts-db/crud.js.map +1 -1
- package/dist/backends/facts-db/db-connection.js.map +1 -1
- package/dist/backends/facts-db/entity-autolink.js.map +1 -1
- package/dist/backends/facts-db/entity-layer.js.map +1 -1
- package/dist/backends/facts-db/episodes.js.map +1 -1
- package/dist/backends/facts-db/fact-queries.js.map +1 -1
- package/dist/backends/facts-db/fact-read-queries.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer1.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer2.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer3.js.map +1 -1
- package/dist/backends/facts-db/fts-text.js.map +1 -1
- package/dist/backends/facts-db/generated-skills/policy.js.map +1 -1
- package/dist/backends/facts-db/generated-skills.js.map +1 -1
- package/dist/backends/facts-db/housekeeping.js.map +1 -1
- package/dist/backends/facts-db/links.js.map +1 -1
- package/dist/backends/facts-db/maintenance.js.map +1 -1
- package/dist/backends/facts-db/procedures/crud.js.map +1 -1
- package/dist/backends/facts-db/procedures/internal.js.map +1 -1
- package/dist/backends/facts-db/procedures/promotion.js.map +1 -1
- package/dist/backends/facts-db/procedures/search.js.map +1 -1
- package/dist/backends/facts-db/procedures/stats.js.map +1 -1
- package/dist/backends/facts-db/reinforcement.js.map +1 -1
- package/dist/backends/facts-db/row-mapper.js.map +1 -1
- package/dist/backends/facts-db/scan-cursors.js.map +1 -1
- package/dist/backends/facts-db/schema-bootstrap.js.map +1 -1
- package/dist/backends/facts-db/scope-sql.js.map +1 -1
- package/dist/backends/facts-db/search.js.map +1 -1
- package/dist/backends/facts-db/stats.js.map +1 -1
- package/dist/backends/facts-db/types.js.map +1 -1
- package/dist/backends/facts-db/variants.js.map +1 -1
- package/dist/backends/identity-reflection-store.js.map +1 -1
- package/dist/backends/issue-store.js.map +1 -1
- package/dist/backends/learnings-db.js.map +1 -1
- package/dist/backends/migrations/facts-migrations.js.map +1 -1
- package/dist/backends/migrations/procedures.js.map +1 -1
- package/dist/backends/narratives-db.js.map +1 -1
- package/dist/backends/persona-state-store.js.map +1 -1
- package/dist/backends/proposals-db.js.map +1 -1
- package/dist/backends/scope-filter-sql.js.map +1 -1
- package/dist/backends/sqlite-schema-meta.js.map +1 -1
- package/dist/backends/tool-proposal-store.js.map +1 -1
- package/dist/backends/vector-db/constants.js.map +1 -1
- package/dist/backends/vector-db/path-utils.js.map +1 -1
- package/dist/backends/vector-db/runtime-locks.js.map +1 -1
- package/dist/backends/vector-db/vector-db-class.js.map +1 -1
- package/dist/backends/wal.js.map +1 -1
- package/dist/backends/workflow-store.js.map +1 -1
- package/dist/benchmark/shadow-eval.js.map +1 -1
- package/dist/cli/active-tasks.js.map +1 -1
- package/dist/cli/backup.js.map +1 -1
- package/dist/cli/benchmark.js.map +1 -1
- package/dist/cli/cmd-backfill.js.map +1 -1
- package/dist/cli/cmd-config.js.map +1 -1
- package/dist/cli/cmd-credentials.js.map +1 -1
- package/dist/cli/cmd-demo.js.map +1 -1
- package/dist/cli/cmd-distill.js.map +1 -1
- package/dist/cli/cmd-doctor.js.map +1 -1
- package/dist/cli/cmd-examples.js.map +1 -1
- package/dist/cli/cmd-extract-daily.js.map +1 -1
- package/dist/cli/cmd-extract-directives.js +141 -10
- package/dist/cli/cmd-extract-directives.js.map +1 -1
- package/dist/cli/cmd-extract-procedures.js.map +1 -1
- package/dist/cli/cmd-extract-proposals.js +3 -2
- package/dist/cli/cmd-extract-proposals.js.map +1 -1
- package/dist/cli/cmd-extract-reinforcement.js +39 -0
- package/dist/cli/cmd-extract-reinforcement.js.map +1 -1
- package/dist/cli/cmd-extract-sessions.js.map +1 -1
- package/dist/cli/cmd-feedback.js +9 -4
- package/dist/cli/cmd-feedback.js.map +1 -1
- package/dist/cli/cmd-health.js.map +1 -1
- package/dist/cli/cmd-providers.js.map +1 -1
- package/dist/cli/cmd-selfcorrection.js.map +1 -1
- package/dist/cli/cmd-setup.js.map +1 -1
- package/dist/cli/cmd-status.js.map +1 -1
- package/dist/cli/cmd-store.js.map +1 -1
- package/dist/cli/cmd-user-friendly.js.map +1 -1
- package/dist/cli/cmd-verify.js.map +1 -1
- package/dist/cli/commands/manage/bindings.js.map +1 -1
- package/dist/cli/commands/manage/dream-cycle-followup.js.map +1 -1
- package/dist/cli/commands/manage/maintenance-heartbeat.js.map +1 -1
- package/dist/cli/commands/manage/register-agents-audit-runall.js.map +1 -1
- package/dist/cli/commands/manage/register-analyze-maintenance-logs.js.map +1 -1
- package/dist/cli/commands/manage/register-budget-proposals.js.map +1 -1
- package/dist/cli/commands/manage/register-config-cli.js.map +1 -1
- package/dist/cli/commands/manage/register-corrections-and-pipeline.js.map +1 -1
- package/dist/cli/commands/manage/register-corrections.js.map +1 -1
- package/dist/cli/commands/manage/register-council.js.map +1 -1
- package/dist/cli/commands/manage/register-credentials-scope.js.map +1 -1
- package/dist/cli/commands/manage/register-digest.js.map +1 -1
- package/dist/cli/commands/manage/register-lifecycle.js.map +1 -1
- package/dist/cli/commands/manage/register-procedure-lifecycle.js.map +1 -1
- package/dist/cli/commands/manage/register-reconcile-cron-ledgers.js.map +1 -1
- package/dist/cli/commands/manage/register-reflection-pipeline.js +144 -7
- package/dist/cli/commands/manage/register-reflection-pipeline.js.map +1 -1
- package/dist/cli/commands/manage/register-self-correction-feedback.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-and-stats.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-entities-decay.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-graph-audit.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-maintenance.js +152 -9
- package/dist/cli/commands/manage/register-storage-maintenance.js.map +1 -1
- package/dist/cli/commands/manage/register-validate-cron-exit.js.map +1 -1
- package/dist/cli/commands/manage/storage-stats-helpers.js +10 -3
- package/dist/cli/commands/manage/storage-stats-helpers.js.map +1 -1
- package/dist/cli/commands/register-manage-commands.js.map +1 -1
- package/dist/cli/config-feature-summaries.js.map +1 -1
- package/dist/cli/config-output-sink.js.map +1 -1
- package/dist/cli/distill-session-jsonl.js.map +1 -1
- package/dist/cli/distill.js +10 -1
- package/dist/cli/distill.js.map +1 -1
- package/dist/cli/global-verbose.js.map +1 -1
- package/dist/cli/goals.js.map +1 -1
- package/dist/cli/hybrid-mem-commander-utils.js.map +1 -1
- package/dist/cli/install/config-merge.js.map +1 -1
- package/dist/cli/install/cron-jobs.js.map +1 -1
- package/dist/cli/install/embedding-detect.js.map +1 -1
- package/dist/cli/install/run-install.js.map +1 -1
- package/dist/cli/install/workspace.js.map +1 -1
- package/dist/cli/proposals.js.map +1 -1
- package/dist/cli/register.js.map +1 -1
- package/dist/cli/shared.js.map +1 -1
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/task-queue-status.js.map +1 -1
- package/dist/cli/verified.js.map +1 -1
- package/dist/cli/verify/fact-count.js.map +1 -1
- package/dist/cli/verify/openclaw-config.js.map +1 -1
- package/dist/cli/verify/plugin-config-credentials.js.map +1 -1
- package/dist/cli/verify/sections/config-cron.js.map +1 -1
- package/dist/cli/verify/sections/embeddings.js.map +1 -1
- package/dist/cli/verify/sections/infrastructure.js.map +1 -1
- package/dist/cli/verify/sections/llm-models.js.map +1 -1
- package/dist/cli/verify/sections/reconcile.js.map +1 -1
- package/dist/cli/verify/verify-run-state.js.map +1 -1
- package/dist/cli/verify-llm-azure-auth.js.map +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/config/hybrid-schema.js.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/maintenance-fallback-policy.js.map +1 -1
- package/dist/config/parsers/capture.js.map +1 -1
- package/dist/config/parsers/core.js.map +1 -1
- package/dist/config/parsers/features.js.map +1 -1
- package/dist/config/parsers/index.js.map +1 -1
- package/dist/config/parsers/maintenance.js.map +1 -1
- package/dist/config/parsers/retrieval.js.map +1 -1
- package/dist/config/parsers/sensors.js.map +1 -1
- package/dist/config/skill-sections.js.map +1 -1
- package/dist/config/skill-size-limits.js.map +1 -1
- package/dist/config/types/agents.js.map +1 -1
- package/dist/config/types/bootstrap.js.map +1 -1
- package/dist/config/types/core.js.map +1 -1
- package/dist/config/types/index.js.map +1 -1
- package/dist/config/utils.js.map +1 -1
- package/dist/index-help.js.map +1 -1
- package/dist/index-testing-exports.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/hook-resolution-api.js.map +1 -1
- package/dist/lifecycle/hooks.js +0 -1
- package/dist/lifecycle/hooks.js.map +1 -1
- package/dist/lifecycle/resolve-agent-id.js.map +1 -1
- package/dist/lifecycle/session-state.js.map +1 -1
- package/dist/lifecycle/stage-active-task.js.map +1 -1
- package/dist/lifecycle/stage-auth-failure.js.map +1 -1
- package/dist/lifecycle/stage-capture/run-capture.js.map +1 -1
- package/dist/lifecycle/stage-capture.js.map +1 -1
- package/dist/lifecycle/stage-cleanup.js.map +1 -1
- package/dist/lifecycle/stage-credential-hint.js.map +1 -1
- package/dist/lifecycle/stage-frustration.js.map +1 -1
- package/dist/lifecycle/stage-goal-stewardship.js.map +1 -1
- package/dist/lifecycle/stage-goal-subagent.js.map +1 -1
- package/dist/lifecycle/stage-injection.js +1 -1
- package/dist/lifecycle/stage-injection.js.map +1 -1
- package/dist/lifecycle/stage-recall/run-recall.js.map +1 -1
- package/dist/lifecycle/stage-recall.js.map +1 -1
- package/dist/lifecycle/stage-setup.js.map +1 -1
- package/dist/routes/dashboard/collectors.js.map +1 -1
- package/dist/routes/dashboard/html.js.map +1 -1
- package/dist/routes/dashboard/server.js.map +1 -1
- package/dist/routes/dashboard-graph.js.map +1 -1
- package/dist/routes/graphql-resolvers.js.map +1 -1
- package/dist/routes/graphql-server.js.map +1 -1
- package/dist/services/active-task-checkpoint.js.map +1 -1
- package/dist/services/active-task-injection.js.map +1 -1
- package/dist/services/active-task.js.map +1 -1
- package/dist/services/adaptive-catch-up-pacing.js +25 -0
- package/dist/services/adaptive-catch-up-pacing.js.map +1 -0
- package/dist/services/adaptive-maintenance-llm.js.map +1 -1
- package/dist/services/adaptive-model-limits.js.map +1 -1
- package/dist/services/ambient-retrieval.js.map +1 -1
- package/dist/services/apitap-service.js.map +1 -1
- package/dist/services/audit-health-exit-info.js.map +1 -1
- package/dist/services/audit-health-json.js.map +1 -1
- package/dist/services/auth-failure-detect.js.map +1 -1
- package/dist/services/auto-capture.js.map +1 -1
- package/dist/services/auto-classifier.js.map +1 -1
- package/dist/services/auto-skills-audit.js.map +1 -1
- package/dist/services/bootstrap-optional.js.map +1 -1
- package/dist/services/bootstrap-priority.js.map +1 -1
- package/dist/services/bootstrap.js.map +1 -1
- package/dist/services/capture-provenance.js.map +1 -1
- package/dist/services/capture-utils.js.map +1 -1
- package/dist/services/chat.js +22 -3
- package/dist/services/chat.js.map +1 -1
- package/dist/services/classification-scope.js.map +1 -1
- package/dist/services/classification.js.map +1 -1
- package/dist/services/cli-sql-dump.js.map +1 -1
- package/dist/services/consolidation.js.map +1 -1
- package/dist/services/context-audit.js +1 -1
- package/dist/services/context-audit.js.map +1 -1
- package/dist/services/context-budget.js.map +1 -1
- package/dist/services/context-engine.js.map +1 -1
- package/dist/services/contextual-variants.js.map +1 -1
- package/dist/services/continuous-verifier.js.map +1 -1
- package/dist/services/contradiction-adjudicator.js.map +1 -1
- package/dist/services/cost-context.js.map +1 -1
- package/dist/services/cost-feature-labels.js.map +1 -1
- package/dist/services/credential-migration.js.map +1 -1
- package/dist/services/credential-scanner.js.map +1 -1
- package/dist/services/credential-validation.js.map +1 -1
- package/dist/services/cron-exit-validator.js.map +1 -1
- package/dist/services/cron-guard.js.map +1 -1
- package/dist/services/cron-job-bash-harness.js +52 -5
- package/dist/services/cron-job-bash-harness.js.map +1 -1
- package/dist/services/cron-maintenance-reconciler.js +1 -3
- package/dist/services/cron-maintenance-reconciler.js.map +1 -1
- package/dist/services/cross-agent-learning.js.map +1 -1
- package/dist/services/crystallization-proposer.js.map +1 -1
- package/dist/services/dedupe-policy.js.map +1 -1
- package/dist/services/deprecated-cron-commands.js.map +1 -1
- package/dist/services/directive-extract.js.map +1 -1
- package/dist/services/document-chunker.js.map +1 -1
- package/dist/services/document-grader.js.map +1 -1
- package/dist/services/dream-cycle.js.map +1 -1
- package/dist/services/embedding-migration.js.map +1 -1
- package/dist/services/embedding-registry.js.map +1 -1
- package/dist/services/embeddings/chain-provider.js.map +1 -1
- package/dist/services/embeddings/factory.js.map +1 -1
- package/dist/services/embeddings/fallback-provider.js.map +1 -1
- package/dist/services/embeddings/ollama-provider.js.map +1 -1
- package/dist/services/embeddings/onnx-provider.js.map +1 -1
- package/dist/services/embeddings/openai-provider.js.map +1 -1
- package/dist/services/embeddings/shared.js +3 -3
- package/dist/services/embeddings/shared.js.map +1 -1
- package/dist/services/embeddings/types.js.map +1 -1
- package/dist/services/entity-enrichment-adaptive.js +128 -0
- package/dist/services/entity-enrichment-adaptive.js.map +1 -0
- package/dist/services/entity-enrichment-cli.js +389 -42
- package/dist/services/entity-enrichment-cli.js.map +1 -1
- package/dist/services/entity-enrichment.js +31 -5
- package/dist/services/entity-enrichment.js.map +1 -1
- package/dist/services/error-reporter/noisy-errors.js.map +1 -1
- package/dist/services/error-reporter/sanitize.js.map +1 -1
- package/dist/services/error-reporter.js.map +1 -1
- package/dist/services/event-hub-repair.js.map +1 -1
- package/dist/services/export-memory.js.map +1 -1
- package/dist/services/fact-extraction.js.map +1 -1
- package/dist/services/feedback-effectiveness.js.map +1 -1
- package/dist/services/find-duplicates.js.map +1 -1
- package/dist/services/frustration-detector.js.map +1 -1
- package/dist/services/fts-search.js.map +1 -1
- package/dist/services/gap-detector.js.map +1 -1
- package/dist/services/generated-skill-lifecycle.js.map +1 -1
- package/dist/services/generated-skill-validation.js.map +1 -1
- package/dist/services/goal-active-task-mirror.js.map +1 -1
- package/dist/services/goal-circuit-breaker.js.map +1 -1
- package/dist/services/goal-health.js.map +1 -1
- package/dist/services/goal-registry.js.map +1 -1
- package/dist/services/goal-stewardship-heartbeat.js.map +1 -1
- package/dist/services/goal-stewardship-llm-triage.js.map +1 -1
- package/dist/services/goal-stewardship-verify-cron.js.map +1 -1
- package/dist/services/goal-stewardship.js.map +1 -1
- package/dist/services/goal-subagent.js.map +1 -1
- package/dist/services/graph-retrieval.js.map +1 -1
- package/dist/services/humanizer-score.js.map +1 -1
- package/dist/services/hybrid-mem-cron-default-job-steps.js.map +1 -1
- package/dist/services/hyde-helper.js.map +1 -1
- package/dist/services/identity-reflection.js.map +1 -1
- package/dist/services/implicit-feedback-extract.js.map +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/ingest-utils.js.map +1 -1
- package/dist/services/intent-template.js.map +1 -1
- package/dist/services/json-array-parser.js.map +1 -1
- package/dist/services/knowledge-gaps.js.map +1 -1
- package/dist/services/language-keywords-build.js.map +1 -1
- package/dist/services/lifecycle/github-adapter.js.map +1 -1
- package/dist/services/llm-rate-limit-headers.js +1 -2
- package/dist/services/llm-rate-limit-headers.js.map +1 -1
- package/dist/services/maintenance-auto-fix.js.map +1 -1
- package/dist/services/maintenance-log-analyzer.js +7 -1
- package/dist/services/maintenance-log-analyzer.js.map +1 -1
- package/dist/services/maintenance-timestamp.js.map +1 -1
- package/dist/services/memory-diagnostics.js.map +1 -1
- package/dist/services/memory-index.js.map +1 -1
- package/dist/services/merge-results.js.map +1 -1
- package/dist/services/model-capabilities.js.map +1 -1
- package/dist/services/model-pricing.js.map +1 -1
- package/dist/services/narrative-recall.js.map +1 -1
- package/dist/services/openclaw-session-artifact.js.map +1 -1
- package/dist/services/passive-observer.js.map +1 -1
- package/dist/services/pattern-detector-hash.js.map +1 -1
- package/dist/services/pattern-detector.js.map +1 -1
- package/dist/services/pending-autopilot/foundation.js.map +1 -1
- package/dist/services/pending-autopilot/redaction.js.map +1 -1
- package/dist/services/pending-autopilot/store.js.map +1 -1
- package/dist/services/pending-autopilot/types.js.map +1 -1
- package/dist/services/pending-digest-autopilot-cron.js.map +1 -1
- package/dist/services/pending-digest-autopilot.js.map +1 -1
- package/dist/services/pending-review-digest.js.map +1 -1
- package/dist/services/persona-proposal-triage.js.map +1 -1
- package/dist/services/persona-state-promotion.js.map +1 -1
- package/dist/services/post-compaction-recall.js.map +1 -1
- package/dist/services/pre-consolidation-flush.js.map +1 -1
- package/dist/services/pre-finalization-guard.js.map +1 -1
- package/dist/services/procedure-cluster.js.map +1 -1
- package/dist/services/procedure-extractor.js.map +1 -1
- package/dist/services/procedure-promotion/duplicate-skill-cache.js.map +1 -1
- package/dist/services/procedure-promotion-policy.js.map +1 -1
- package/dist/services/procedure-selection-metrics.js.map +1 -1
- package/dist/services/procedure-skill-eval.js.map +1 -1
- package/dist/services/procedure-skill-generator.js.map +1 -1
- package/dist/services/procedure-skill-recipe.js.map +1 -1
- package/dist/services/procedure-skill-shrink.js.map +1 -1
- package/dist/services/procedure-skill-workflow.js.map +1 -1
- package/dist/services/provenance.js.map +1 -1
- package/dist/services/public-export-bundle.js.map +1 -1
- package/dist/services/python-bridge.js.map +1 -1
- package/dist/services/query-expander.js.map +1 -1
- package/dist/services/query-validator.js.map +1 -1
- package/dist/services/recall-pipeline.js.map +1 -1
- package/dist/services/recall-timing.js.map +1 -1
- package/dist/services/recent-http-attempts.js.map +1 -1
- package/dist/services/reflection/shared.js.map +1 -1
- package/dist/services/reflection.js.map +1 -1
- package/dist/services/reinforcement-extract.js.map +1 -1
- package/dist/services/reranker.js.map +1 -1
- package/dist/services/responses-adapter.js.map +1 -1
- package/dist/services/retrieval-aliases.js.map +1 -1
- package/dist/services/retrieval-mode-policy.js.map +1 -1
- package/dist/services/retrieval-orchestrator/packing.js.map +1 -1
- package/dist/services/retrieval-orchestrator.d.ts +2 -3
- package/dist/services/retrieval-orchestrator.js.map +1 -1
- package/dist/services/rrf-fusion.js.map +1 -1
- package/dist/services/self-correction-extract.js.map +1 -1
- package/dist/services/session-observability.js.map +1 -1
- package/dist/services/session-pre-filter.js.map +1 -1
- package/dist/services/shortest-path.js.map +1 -1
- package/dist/services/skill-allowed-tools.js.map +1 -1
- package/dist/services/skill-creator-validator.js.map +1 -1
- package/dist/services/skill-crystallizer-helpers.js.map +1 -1
- package/dist/services/skill-crystallizer.js.map +1 -1
- package/dist/services/skill-description-builder.js.map +1 -1
- package/dist/services/skill-eval-synthesizer.js.map +1 -1
- package/dist/services/skill-examples-builder.js.map +1 -1
- package/dist/services/skill-frontmatter.js.map +1 -1
- package/dist/services/skill-name-validator.js.map +1 -1
- package/dist/services/skill-prompt-injection.js.map +1 -1
- package/dist/services/skill-reference-sidecar.js.map +1 -1
- package/dist/services/skill-script-bundler.js.map +1 -1
- package/dist/services/skill-validator.js.map +1 -1
- package/dist/services/startup-memory-attribution.js.map +1 -1
- package/dist/services/task-hygiene.js.map +1 -1
- package/dist/services/task-ledger/canonical.js.map +1 -1
- package/dist/services/task-ledger-facts.js.map +1 -1
- package/dist/services/task-queue-leases.js.map +1 -1
- package/dist/services/task-queue-watchdog.js.map +1 -1
- package/dist/services/tool-effectiveness.js.map +1 -1
- package/dist/services/tool-proposer.js.map +1 -1
- package/dist/services/tools-md-section.js.map +1 -1
- package/dist/services/topic-clusters.js.map +1 -1
- package/dist/services/trajectory-tracker.js.map +1 -1
- package/dist/services/vector-backend-observability.js.map +1 -1
- package/dist/services/vector-lifecycle-audit.js.map +1 -1
- package/dist/services/vector-maintenance.js.map +1 -1
- package/dist/services/vector-search.js.map +1 -1
- package/dist/services/verification-store.js.map +1 -1
- package/dist/services/verified-fact-triage.js.map +1 -1
- package/dist/services/wal-helpers.js.map +1 -1
- package/dist/services/workflow-tracker.js.map +1 -1
- package/dist/setup/bootstrap-databases.js.map +1 -1
- package/dist/setup/cli-context/cli-services.js.map +1 -1
- package/dist/setup/cli-context/help-text.js.map +1 -1
- package/dist/setup/cli-context/metadata.js.map +1 -1
- package/dist/setup/cli-context/register-cli-with-help.js.map +1 -1
- package/dist/setup/cli-context/register-full.js.map +1 -1
- package/dist/setup/cli-context/register-help.js.map +1 -1
- package/dist/setup/cost-instrumentation.js.map +1 -1
- package/dist/setup/hybrid-memory-generation-state.js.map +1 -1
- package/dist/setup/hybrid-memory-reload-coordinator.js +13 -13
- package/dist/setup/hybrid-memory-reload-coordinator.js.map +1 -1
- package/dist/setup/plugin-service.js.map +1 -1
- package/dist/setup/provider-router.js.map +1 -1
- package/dist/setup/register-context-engine.js.map +1 -1
- package/dist/setup/register-hooks.js.map +1 -1
- package/dist/setup/register-plugin.js +25 -21
- package/dist/setup/register-plugin.js.map +1 -1
- package/dist/setup/register-tools.js.map +1 -1
- package/dist/setup/reregister-policy.js +2 -2
- package/dist/setup/reregister-policy.js.map +1 -1
- package/dist/setup/tool-installers.js.map +1 -1
- package/dist/setup/workspace-bootstrap.js.map +1 -1
- package/dist/src/worker/narratives.js.map +1 -1
- package/dist/tools/apitap-tools.js.map +1 -1
- package/dist/tools/credential-tools.js.map +1 -1
- package/dist/tools/crystallization-tools.js.map +1 -1
- package/dist/tools/dashboard-routes.js.map +1 -1
- package/dist/tools/document-tools.js.map +1 -1
- package/dist/tools/goal-tools.js.map +1 -1
- package/dist/tools/graph-tools.js.map +1 -1
- package/dist/tools/issue-tools.js.map +1 -1
- package/dist/tools/memory/build-runtime.js.map +1 -1
- package/dist/tools/memory/helpers.js.map +1 -1
- package/dist/tools/memory/register-checkpoint-tools.js.map +1 -1
- package/dist/tools/memory/register-directory-tools.js.map +1 -1
- package/dist/tools/memory/register-edict-tools.js.map +1 -1
- package/dist/tools/memory/register-episode-tools.js.map +1 -1
- package/dist/tools/memory/register-recall-tools.js.map +1 -1
- package/dist/tools/memory/register-store-tools.js.map +1 -1
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/persona-tools.js.map +1 -1
- package/dist/tools/provenance-tools.js.map +1 -1
- package/dist/tools/public-api-routes.js.map +1 -1
- package/dist/tools/safe-register-http-route.js.map +1 -1
- package/dist/tools/self-extension-tools.js.map +1 -1
- package/dist/tools/task-hygiene-tools.js.map +1 -1
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/verification-tools.js.map +1 -1
- package/dist/tools/workflow-tools.js.map +1 -1
- package/dist/types/issue-types.js.map +1 -1
- package/dist/types/learnings-types.js.map +1 -1
- package/dist/types/memory.js.map +1 -1
- package/dist/utils/apim-gateway-fetch.js.map +1 -1
- package/dist/utils/atomic-write.js.map +1 -1
- package/dist/utils/auth-failover.js.map +1 -1
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/compaction-model-watchdog.js.map +1 -1
- package/dist/utils/consolidation-controls.js.map +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/date-detector.js.map +1 -1
- package/dist/utils/dates.js.map +1 -1
- package/dist/utils/decay.js.map +1 -1
- package/dist/utils/duration.js.map +1 -1
- package/dist/utils/embed-call.js.map +1 -1
- package/dist/utils/entity-lookup-resolve.js.map +1 -1
- package/dist/utils/entity-mention-quality.js.map +1 -1
- package/dist/utils/entity-stopwords.js.map +1 -1
- package/dist/utils/env-manager.js.map +1 -1
- package/dist/utils/error-tracking.js.map +1 -1
- package/dist/utils/event-loop-yield.js.map +1 -1
- package/dist/utils/extract-last-user-message.js.map +1 -1
- package/dist/utils/extraction-from-template.js.map +1 -1
- package/dist/utils/fact-embeddings.js.map +1 -1
- package/dist/utils/file-snapshot.js.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/gh-repo-arg.js.map +1 -1
- package/dist/utils/hybrid-mem-json-cli.js.map +1 -1
- package/dist/utils/language-keywords.js.map +1 -1
- package/dist/utils/lifecycle-generation.js.map +1 -1
- package/dist/utils/llm-json-array.js.map +1 -1
- package/dist/utils/llm-selection.js.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/model-provider-family.js.map +1 -1
- package/dist/utils/model-tier.js.map +1 -1
- package/dist/utils/openclaw-agent-defaults.js.map +1 -1
- package/dist/utils/path.js.map +1 -1
- package/dist/utils/plugin-root.js.map +1 -1
- package/dist/utils/plugin-update-check.js.map +1 -1
- package/dist/utils/procedure-risk.js.map +1 -1
- package/dist/utils/progress-indicators.js.map +1 -1
- package/dist/utils/prompt-loader.js.map +1 -1
- package/dist/utils/provenance.js.map +1 -1
- package/dist/utils/provider-detection.js.map +1 -1
- package/dist/utils/registration-superseded.js.map +1 -1
- package/dist/utils/salience.js.map +1 -1
- package/dist/utils/sanitize-messages.js.map +1 -1
- package/dist/utils/scope-filter.js.map +1 -1
- package/dist/utils/skill-discovery.js.map +1 -1
- package/dist/utils/sqlite-file-perms.js.map +1 -1
- package/dist/utils/sqlite-outcome-compat.js.map +1 -1
- package/dist/utils/sqlite-transaction.js.map +1 -1
- package/dist/utils/stable-stringify.js.map +1 -1
- package/dist/utils/subagent-ended-utils.js.map +1 -1
- package/dist/utils/tags.js.map +1 -1
- package/dist/utils/text.js.map +1 -1
- package/dist/utils/timeout.js.map +1 -1
- package/dist/utils/typebox.js.map +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/wal-replay.js.map +1 -1
- package/dist/versionInfo.js.map +1 -1
- package/index.ts +2 -2
- package/lifecycle/hooks.ts +0 -1
- package/npm-shrinkwrap.json +487 -186
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/services/adaptive-catch-up-pacing.ts +28 -0
- package/services/chat.ts +34 -1
- package/services/cron-job-bash-harness.ts +52 -5
- package/services/embeddings/shared.ts +5 -2
- package/services/entity-enrichment-adaptive.ts +245 -0
- package/services/entity-enrichment-cli.ts +553 -47
- package/services/entity-enrichment.ts +43 -2
- package/services/llm-rate-limit-headers.ts +1 -4
- package/services/maintenance-log-analyzer.ts +13 -9
- package/services/reinforcement-extract.ts +19 -0
- package/setup/hybrid-memory-reload-coordinator.ts +26 -0
- package/setup/register-plugin.ts +62 -32
- package/setup/reregister-policy.ts +10 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-store-tools.js","names":[],"sources":["../../../tools/memory/register-store-tools.ts"],"sourcesContent":["/**\n * Memory Tool Registrations\n *\n * Tool definitions for memory recall, storage, promotion, and deletion.\n * Extracted from index.ts for better modularity.\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport { stringEnum } from \"../../utils/typebox.js\";\n\nimport { categoryToEventType } from \"../../backends/event-log.js\";\nimport {\n DECAY_CLASSES,\n type DecayClass,\n type MemoryCategory,\n getCronModelConfig,\n getDefaultCronModel,\n getMemoryCategories,\n isCompactVerbosity,\n} from \"../../config.js\";\nimport { VAULT_POINTER_PREFIX, isCredentialLike, tryParseCredentialForVault } from \"../../services/auto-capture.js\";\nimport { classifyMemoryOperation } from \"../../services/classification.js\";\nimport { AllEmbeddingProvidersFailed, shouldSuppressEmbeddingError } from \"../../services/embeddings.js\";\nimport { extractEntityMentionsWithLlm } from \"../../services/entity-enrichment.js\";\nimport { addOperationBreadcrumb, capturePluginError } from \"../../services/error-reporter.js\";\nimport { extractStructuredFields } from \"../../services/fact-extraction.js\";\nimport { storeAliases } from \"../../services/retrieval-aliases.js\";\nimport { validateScopedClassificationTarget } from \"../../services/classification-scope.js\";\nimport { shouldAutoVerify } from \"../../services/verification-store.js\";\nimport { cleanupEvictedVector, deleteVectorForFactId } from \"../../services/vector-maintenance.js\";\nimport type { MemoryEntry } from \"../../types/memory.js\";\nimport { MEMORY_SCOPES } from \"../../types/memory.js\";\nimport { detectFutureDate } from \"../../utils/date-detector.js\";\nimport { embedCallWithTimeoutAndRetry } from \"../../utils/embed-call.js\";\nimport { extractTags } from \"../../utils/tags.js\";\nimport { truncateForStorage } from \"../../utils/text.js\";\nimport type { MemoryToolRuntime } from \"./runtime.js\";\n\nexport function registerStoreTools(runtime: MemoryToolRuntime): void {\n const {\n factsDb,\n edictStore,\n vectorDb,\n cfg,\n embeddings,\n openai,\n credentialsDb,\n eventLog,\n narrativesDb,\n provenanceService,\n aliasDb,\n embeddingRegistry,\n verificationStore,\n lastProgressiveIndexIds,\n currentAgentIdRef,\n pendingLLMWarnings,\n variantQueue,\n buildToolScopeFilter,\n walWrite,\n walRemove,\n findSimilarByEmbedding,\n auditStore,\n api,\n auditAppend,\n agentIdForAudit,\n maybeRefreshProjectActiveTaskProjection,\n storeActiveCanonicalVector,\n storeRegistryEmbeddings,\n isEdictWriteToolEnabled,\n sanitizeScopeParam,\n } = runtime;\n\n api.registerTool(\n {\n name: \"memory_store\",\n label: \"Memory Store\",\n description:\n \"Save important information in long-term memory. Stores to both structured (SQLite) and semantic (LanceDB) backends.\",\n parameters: Type.Object({\n text: Type.String({ description: \"Information to remember\" }),\n why: Type.Optional(\n Type.String({\n description:\n \"Optional lineage context: why this memory matters (decision rationale, file impact, blocker context, etc.).\",\n }),\n ),\n importance: Type.Optional(\n Type.Number({\n description:\n \"Importance 0-1 (default: 0.5). Higher values signal facts that should survive longer during decay.\",\n }),\n ),\n category: Type.Optional(stringEnum(getMemoryCategories() as unknown as readonly string[])),\n entity: Type.Optional(\n Type.String({\n description: \"Entity name (person, project, tool, etc.)\",\n }),\n ),\n key: Type.Optional(\n Type.String({\n description: \"Structured key (e.g. 'birthday', 'email')\",\n }),\n ),\n value: Type.Optional(\n Type.String({\n description: \"Structured value (e.g. 'Nov 13', 'john@example.com')\",\n }),\n ),\n decayClass: Type.Optional(\n Object.assign(stringEnum(DECAY_CLASSES as unknown as readonly string[]), {\n description:\n \"Decay class defining half-life: durable (~3mo), normal (~2w), short (~2d), session (~1d), ephemeral (~4h), permanent (no decay). Legacy aliases: stable=durable, active=normal, checkpoint=ephemeral.\",\n }),\n ),\n tags: Type.Optional(\n Type.Array(Type.String(), {\n description: \"Topic tags for sharper retrieval (e.g. nibe, zigbee). Auto-inferred if omitted.\",\n }),\n ),\n supersedes: Type.Optional(\n Type.String({\n description:\n \"Fact id this one supersedes (replaces). Marks the old fact as superseded and links the new one.\",\n }),\n ),\n scope: Type.Optional(stringEnum(MEMORY_SCOPES as unknown as readonly string[])),\n scopeTarget: Type.Optional(\n Type.String({\n description:\n \"Scope target (userId, agentId, or sessionId). Required when scope is user, agent, or session.\",\n }),\n ),\n verification_tier: Type.Optional(\n Type.String({\n description:\n \"Optional verification tier override (e.g. 'critical') to force verification store enrollment.\",\n }),\n ),\n decayFreezeUntil: Type.Optional(\n Type.Number({\n description:\n \"Unix epoch seconds until which confidence decay is paused. Auto-detected from future dates in text if omitted.\",\n }),\n ),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n try {\n const {\n text,\n why,\n importance = 0.5,\n category = \"other\",\n entity: paramEntity,\n key: paramKey,\n value: paramValue,\n decayClass: paramDecayClass,\n tags: paramTags,\n supersedes,\n scope: paramScope,\n scopeTarget: paramScopeTarget,\n verification_tier: verificationTier,\n decayFreezeUntil: paramDecayFreezeUntil,\n } = params as {\n text: string;\n why?: string;\n importance?: number;\n category?: MemoryCategory;\n entity?: string;\n key?: string;\n value?: string;\n decayClass?: DecayClass;\n tags?: string[];\n supersedes?: string;\n scope?: \"global\" | \"user\" | \"agent\" | \"session\";\n scopeTarget?: string;\n verification_tier?: string;\n decayFreezeUntil?: number;\n };\n\n // --- Early input validation (must run before any side effects) ---\n if (text.trim().length === 0) {\n return {\n content: [{ type: \"text\", text: \"memory_store: text must not be empty or whitespace.\" }],\n details: { error: \"invalid_text\" },\n };\n }\n\n let textToStore = text;\n textToStore = truncateForStorage(textToStore, cfg.captureMaxChars);\n\n const importanceValue = importance as number;\n if (!Number.isFinite(importanceValue) || importanceValue < 0 || importanceValue > 1) {\n return {\n content: [\n {\n type: \"text\",\n text: `memory_store: importance must be a finite number in [0, 1]; got ${importanceValue}.`,\n },\n ],\n details: { error: \"invalid_importance\" },\n };\n }\n\n if (paramDecayFreezeUntil != null && (!Number.isFinite(paramDecayFreezeUntil) || paramDecayFreezeUntil < 0)) {\n return {\n content: [\n {\n type: \"text\",\n text: `memory_store: decayFreezeUntil must be a non-negative finite epoch seconds value; got ${paramDecayFreezeUntil}.`,\n },\n ],\n details: { error: \"invalid_decay_freeze_until\" },\n };\n }\n // --- End early validation ---\n\n const provenanceSessionId = api.context?.sessionId ?? null;\n const recordActiveStoreProvenance = (factId: string, sourceText?: string) => {\n if (!provenanceService || !cfg.provenance.enabled) return;\n try {\n provenanceService.addEdge(factId, {\n edgeType: \"DERIVED_FROM\",\n sourceType: \"active_store\",\n sourceId: provenanceSessionId ?? \"unknown-session\",\n sourceText,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"provenance\",\n operation: \"memory-store-provenance\",\n factId,\n });\n }\n };\n\n const extracted = extractStructuredFields(textToStore, category as MemoryCategory);\n const entity = paramEntity || extracted.entity;\n const key = paramKey || extracted.key;\n const value = paramValue || extracted.value;\n\n if (factsDb.hasDuplicate(textToStore, \"conversation\", { category, entity, key, value })) {\n return {\n content: [{ type: \"text\", text: \"Similar memory already exists.\" }],\n details: { action: \"duplicate\" },\n };\n }\n\n // FR-006: Compute scope early so it's available for classify-before-write UPDATE path; normal path may overwrite with multiAgent logic below\n let scope: \"global\" | \"user\" | \"agent\" | \"session\" = paramScope ?? \"global\";\n let scopeTarget: string | null = scope === \"global\" ? null : (paramScopeTarget?.trim() ?? null);\n if (scope !== \"global\" && !scopeTarget) {\n return {\n content: [\n {\n type: \"text\",\n text: `Scope \"${scope}\" requires scopeTarget (userId, agentId, or sessionId).`,\n },\n ],\n details: { error: \"scope_target_required\" },\n };\n }\n\n const explicitVerificationTier = (verificationTier ?? \"\").trim().toLowerCase();\n\n const maybeAutoVerify = (\n factId: string,\n factText: string,\n autoTags: string[],\n autoEntity?: string | null,\n autoKey?: string | null,\n autoValue?: string | null,\n ) => {\n if (!cfg.verification.enabled || !verificationStore) return;\n const shouldEnroll =\n explicitVerificationTier === \"critical\" ||\n (cfg.verification.autoClassify &&\n shouldAutoVerify({\n text: factText,\n category,\n tags: autoTags,\n entity: autoEntity,\n key: autoKey,\n value: autoValue,\n verificationTier: verificationTier ?? null,\n }));\n if (!shouldEnroll) return;\n try {\n const verifiedBy = explicitVerificationTier === \"critical\" ? \"agent\" : \"system\";\n verificationStore.verify(factId, factText, verifiedBy);\n } catch (err) {\n api.logger.warn?.(`memory-hybrid: auto-verify failed for ${factId}: ${err}`);\n }\n };\n\n if (isCredentialLike(textToStore, entity, key, value)) {\n if (cfg.credentials.enabled && credentialsDb) {\n const parsed = tryParseCredentialForVault(textToStore, entity, key, value, {\n requirePatternMatch: cfg.credentials.autoCapture?.requirePatternMatch === true,\n });\n if (parsed) {\n const stored = credentialsDb.storeIfNew({\n service: parsed.service,\n type: parsed.type,\n value: parsed.secretValue,\n url: parsed.url,\n notes: parsed.notes,\n });\n if (!stored) {\n return {\n content: [\n { type: \"text\", text: `Credential already in vault for ${parsed.service} (${parsed.type}).` },\n ],\n details: { action: \"credential_skipped_duplicate\", service: parsed.service, type: parsed.type },\n };\n }\n const pointerText = `Credential for ${parsed.service} (${parsed.type}) — stored in secure vault. Use credential_get(service=\"${parsed.service}\", type=\"${parsed.type}\") to retrieve.`;\n const pointerValue = `${VAULT_POINTER_PREFIX}${parsed.service}:${parsed.type}`;\n const pointerStoreResult = factsDb.storeWithResult({\n text: pointerText,\n why,\n category: \"technical\" as MemoryCategory,\n importance,\n entity: \"Credentials\",\n key: parsed.service,\n value: pointerValue,\n source: \"conversation\",\n decayClass: paramDecayClass ?? \"permanent\",\n tags: [\"auth\", ...extractTags(pointerText, \"Credentials\")],\n provenanceSession: provenanceSessionId,\n extractionMethod: \"active\",\n extractionConfidence: importance,\n });\n const pointerEntry = pointerStoreResult.entry;\n // Guard: if the pointer was rejected by the pre-store guard, undo the vault store and return rejected artifact\n if (pointerStoreResult.rejected) {\n try {\n credentialsDb.delete(parsed.service, parsed.type as any);\n } catch (_cleanupErr) {\n // best-effort cleanup\n }\n return {\n content: [{ type: \"text\", text: \"Credential-like content rejected by pre-store guard.\" }],\n details: { action: \"credential_rejected_artifact\" },\n };\n }\n await cleanupEvictedVector({\n vectorDb,\n evictedFactId: pointerStoreResult.evictedFactId,\n logger: api.logger,\n context: \"memory-store-credential-pointer\",\n });\n recordActiveStoreProvenance(pointerEntry.id, pointerText);\n try {\n addOperationBreadcrumb(\"vector\", \"store-credential-pointer\");\n const vector = await embedCallWithTimeoutAndRetry(\n () => embeddings.embed(pointerText),\n \"memory-tools:store-credential-pointer\",\n );\n await storeActiveCanonicalVector({\n factId: pointerEntry.id,\n text: pointerText,\n why,\n vector,\n importance,\n category: \"technical\",\n });\n await storeRegistryEmbeddings({\n factsDb,\n embeddingRegistry,\n embeddings,\n factId: pointerEntry.id,\n text: pointerText,\n vector,\n logger: api.logger,\n operation: \"store-credential-pointer\",\n });\n } catch (err) {\n // AllEmbeddingProvidersFailed is expected when no providers are configured — don't report to Sentry.\n if (!(err instanceof AllEmbeddingProvidersFailed)) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"vector\",\n operation: \"store-credential-pointer\",\n phase: \"runtime\",\n backend: \"lancedb\",\n });\n }\n api.logger.warn(`memory-hybrid: vector store failed: ${err}`);\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Credential stored in vault for ${parsed.service} (${parsed.type}). Pointer saved in memory.`,\n },\n ],\n details: {\n action: \"credential_vault\",\n id: pointerEntry.id,\n service: parsed.service,\n type: parsed.type,\n },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: \"Credential-like content detected but could not be parsed as a structured credential; not stored (vault is enabled).\",\n },\n ],\n details: { action: \"credential_skipped\" },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: \"Credential-like content detected. Ordinary memory storage is blocked while the credential vault is disabled or unavailable. Enable credentials vault and retry.\",\n },\n ],\n details: { action: \"credential_blocked_no_vault\" },\n };\n }\n\n const tags =\n paramTags && paramTags.length > 0\n ? paramTags.map((t) => t.trim().toLowerCase()).filter(Boolean)\n : extractTags(textToStore, entity);\n\n const summaryThreshold = cfg.autoRecall.summaryThreshold;\n const summary =\n summaryThreshold > 0 && textToStore.length > summaryThreshold\n ? `${textToStore.slice(0, cfg.autoRecall.summaryMaxChars).trim()}…`\n : undefined;\n\n // Generate vector first (needed for WAL and storage)\n let vector: number[] | undefined;\n try {\n vector = await embedCallWithTimeoutAndRetry(\n () => embeddings.embed(textToStore),\n \"memory-tools:store-embed\",\n );\n } catch (err) {\n if (err instanceof AllEmbeddingProvidersFailed) {\n // Graceful degradation: store the fact without a vector.\n // The fact is still findable by structured/keyword search.\n api.logger.warn(\"memory-hybrid: Stored fact without embeddings — all providers unavailable\");\n } else if (shouldSuppressEmbeddingError(err)) {\n // Ollama circuit breaker, 429, config errors, etc. — expected noise (#937); don't send to GlitchTip.\n api.logger.warn(`memory-hybrid: embedding skipped (expected): ${err}`);\n } else {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"embeddings\",\n operation: \"store-embed\",\n phase: \"runtime\",\n });\n api.logger.warn(`memory-hybrid: embedding generation failed: ${err}`);\n }\n }\n\n // Classify the operation before storing (use embedding similarity)\n if (cfg.store.classifyBeforeWrite) {\n let similarFacts: MemoryEntry[] = [];\n if (vector) {\n similarFacts = await findSimilarByEmbedding(vectorDb, factsDb, vector, 5, 0.3, {\n scope,\n scopeTarget,\n });\n }\n if (similarFacts.length === 0) {\n similarFacts = factsDb.findSimilarForClassification(textToStore, entity, key, 5, scope, scopeTarget);\n }\n if (similarFacts.length > 0) {\n const classification = await classifyMemoryOperation(\n textToStore,\n entity,\n key,\n similarFacts,\n openai,\n cfg.store.classifyModel ?? getDefaultCronModel(getCronModelConfig(cfg), \"nano\"),\n api.logger,\n );\n\n if (classification.action === \"NOOP\") {\n return {\n content: [{ type: \"text\", text: `Already known: ${classification.reason}` }],\n details: { action: \"noop\", reason: classification.reason },\n };\n }\n\n if (classification.action === \"DELETE\" && classification.targetId) {\n const target = validateScopedClassificationTarget({\n targetId: classification.targetId,\n candidates: similarFacts,\n getById: (id) => factsDb.getById(id),\n scope,\n scopeTarget,\n warn: (message) => api.logger.warn?.(message),\n warnMessage: `memory-hybrid: blocked cross-scope or unknown memory_store DELETE target ${classification.targetId}`,\n });\n if (target) {\n factsDb.supersede(classification.targetId, null);\n aliasDb?.deleteByFactId(classification.targetId);\n await deleteVectorForFactId({\n vectorDb,\n factId: classification.targetId,\n logger: api.logger,\n context: \"store-delete-action\",\n });\n return {\n content: [\n { type: \"text\", text: `Retracted fact ${classification.targetId}: ${classification.reason}` },\n ],\n details: { action: \"delete\", targetId: classification.targetId, reason: classification.reason },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Blocked delete target ${classification.targetId}: failed scope/candidate validation.`,\n },\n ],\n details: { action: \"noop\", reason: \"blocked-delete-target-validation\" },\n };\n }\n\n if (classification.action === \"UPDATE\" && classification.targetId) {\n const oldFact = validateScopedClassificationTarget({\n targetId: classification.targetId,\n candidates: similarFacts,\n getById: (id) => factsDb.getById(id),\n scope,\n scopeTarget,\n warn: (message) => api.logger.warn?.(message),\n warnMessage: `memory-hybrid: blocked cross-scope or unknown memory_store UPDATE target ${classification.targetId}`,\n });\n if (oldFact) {\n const walEntryId = await walWrite(\n \"update\",\n {\n text: textToStore,\n why,\n category,\n importance: Math.max(importance, oldFact.importance),\n entity: entity || oldFact.entity,\n key: key || oldFact.key,\n value: value || oldFact.value,\n source: \"conversation\",\n decayClass: paramDecayClass ?? oldFact.decayClass,\n summary,\n tags,\n vector,\n embeddingModelName: vector ? embeddings.modelName : undefined,\n scope,\n scopeTarget,\n },\n api.logger,\n classification.targetId,\n );\n\n const nowSec = Math.floor(Date.now() / 1000);\n const updateStoreResult = factsDb.storeWithResult({\n text: textToStore,\n why,\n category: category as MemoryCategory,\n importance: Math.max(importance, oldFact.importance),\n entity: entity || oldFact.entity,\n key: key || oldFact.key,\n value: value || oldFact.value,\n source: \"conversation\",\n decayClass: paramDecayClass ?? oldFact.decayClass,\n summary,\n tags,\n validFrom: nowSec,\n supersedesId: classification.targetId,\n scope,\n scopeTarget,\n sourceSessions: api.context?.sessionId ?? undefined,\n provenanceSession: provenanceSessionId,\n extractionMethod: \"active\",\n extractionConfidence: Math.max(importance, oldFact.importance),\n });\n const newEntry = updateStoreResult.entry;\n // Guard: skip post-store ops when pre-store guard blocked the write (#1560, #1561)\n if (!updateStoreResult.skipped) {\n await cleanupEvictedVector({\n vectorDb,\n evictedFactId: updateStoreResult.evictedFactId,\n logger: api.logger,\n context: \"memory-store-update\",\n });\n recordActiveStoreProvenance(newEntry.id, textToStore);\n factsDb.supersede(classification.targetId, newEntry.id);\n aliasDb?.deleteByFactId(classification.targetId);\n await deleteVectorForFactId({\n vectorDb,\n factId: classification.targetId,\n logger: api.logger,\n context: \"store-update-delete-superseded\",\n });\n maybeAutoVerify(\n newEntry.id,\n textToStore,\n newEntry.tags ?? tags,\n newEntry.entity,\n newEntry.key,\n newEntry.value,\n );\n\n const finalImportance = Math.max(importance, oldFact.importance);\n try {\n if (vector) {\n await storeActiveCanonicalVector({\n factId: newEntry.id,\n text: textToStore,\n why,\n vector,\n importance: finalImportance,\n category,\n });\n }\n await storeRegistryEmbeddings({\n factsDb,\n embeddingRegistry,\n embeddings,\n factId: newEntry.id,\n text: textToStore,\n vector,\n logger: api.logger,\n operation: \"store-update-supersede\",\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"vector\",\n operation: \"store-update-supersede\",\n phase: \"runtime\",\n backend: \"lancedb\",\n });\n api.logger.warn(`memory-hybrid: vector store failed: ${err}`);\n }\n\n await maybeRefreshProjectActiveTaskProjection(newEntry.category, newEntry.id, newEntry.scope);\n\n // Issue #159: enqueue contextual variant generation (non-blocking)\n if (variantQueue) {\n variantQueue.enqueue({ factId: newEntry.id, text: textToStore, category: category as string });\n }\n\n api.logger.info?.(\n `memory-hybrid: UPDATE — superseded ${classification.targetId} with ${newEntry.id}: ${classification.reason}`,\n );\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: `Updated: superseded old fact with \"${textToStore.slice(0, 100)}${textToStore.length > 100 ? \"...\" : \"\"}\"${entity ? ` [entity: ${entity}]` : \"\"} [decay: ${newEntry.decayClass}] (reason: ${classification.reason})`,\n },\n ],\n details: {\n action: \"updated\",\n id: newEntry.id,\n why: why ?? undefined,\n superseded: classification.targetId,\n reason: classification.reason,\n backend: \"both\",\n decayClass: newEntry.decayClass,\n },\n };\n }\n // WAL cleanup for skipped update path\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: `Store blocked by pre-store guard (category: ${category}).`,\n },\n ],\n details: { action: \"skipped\", reason: \"blocked-by-guard\", category },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Blocked update target ${classification.targetId}: failed scope/candidate validation.`,\n },\n ],\n details: { action: \"noop\", reason: \"blocked-update-target-validation\" },\n };\n }\n // action === \"ADD\" falls through to normal store\n }\n }\n\n // Resolve final scope before WAL write so the WAL entry captures the complete scope\n // metadata. Without this, a crash between WAL write and DB commit would cause replay\n // to default scoped facts to global scope (issue #1574).\n // Smart default scope based on agent identity and config (FR-006: overwrite for normal path when not explicit)\n if (paramScope) {\n // Explicit scope parameter always takes precedence\n scope = paramScope;\n scopeTarget = scope === \"global\" ? null : (paramScopeTarget?.trim() ?? null);\n } else {\n // Auto-determine scope based on multiAgent config\n const agentId = currentAgentIdRef.value || cfg.multiAgent.orchestratorId;\n const isOrchestrator = agentId === cfg.multiAgent.orchestratorId;\n\n // Strict agent scoping: throw if agent detection failed in agent/auto mode\n if (\n cfg.multiAgent.strictAgentScoping &&\n !currentAgentIdRef.value &&\n (cfg.multiAgent.defaultStoreScope === \"agent\" || cfg.multiAgent.defaultStoreScope === \"auto\")\n ) {\n throw new Error(\n `Agent detection failed (currentAgentId is null) and multiAgent.strictAgentScoping is enabled. Cannot auto-determine scope for defaultStoreScope=\"${cfg.multiAgent.defaultStoreScope}\". Fix: ensure agent_id is provided in session context, or disable strictAgentScoping.`,\n );\n }\n\n if (cfg.multiAgent.defaultStoreScope === \"global\") {\n // Backward compatible: always global\n scope = \"global\";\n scopeTarget = null;\n } else if (cfg.multiAgent.defaultStoreScope === \"agent\") {\n // Always agent-scoped (for fully isolated setups)\n scope = \"agent\";\n scopeTarget = agentId;\n } else {\n // \"auto\" mode: orchestrator → global, specialists → agent\n if (isOrchestrator) {\n scope = \"global\";\n scopeTarget = null;\n } else {\n scope = \"agent\";\n scopeTarget = agentId;\n }\n }\n }\n\n // Final validation: if scope requires a target but none is available, fall back to global\n // (unless strictAgentScoping already threw above)\n if (scope !== \"global\" && !scopeTarget) {\n if (paramScope) {\n // User explicitly requested non-global scope but didn't provide target\n return {\n content: [\n {\n type: \"text\",\n text: `Scope \"${scope}\" requires scopeTarget (userId, agentId, or sessionId). Provide scopeTarget parameter or use scope=\"global\".`,\n },\n ],\n details: { error: \"scope_target_required\" },\n };\n }\n // Auto-determined scope ended up without target (shouldn't happen with current logic,\n // but handle gracefully by falling back to global)\n scope = \"global\";\n scopeTarget = null;\n }\n\n const walEntryId = await walWrite(\n \"store\",\n {\n text: textToStore,\n why,\n category,\n importance,\n entity,\n key,\n value,\n source: \"conversation\",\n decayClass: paramDecayClass,\n summary,\n tags,\n vector,\n embeddingModelName: vector ? embeddings.modelName : undefined,\n scope,\n scopeTarget,\n },\n api.logger,\n );\n const decayFreezeUntil =\n paramDecayFreezeUntil != null && Number.isFinite(paramDecayFreezeUntil)\n ? paramDecayFreezeUntil\n : detectFutureDate(textToStore, cfg.futureDateProtection ?? { enabled: false });\n\n const nowSec = Math.floor(Date.now() / 1000);\n const storeSessionId = api.context?.sessionId ?? null;\n const storeResult = factsDb.storeWithResult({\n text: textToStore,\n why,\n category: category as MemoryCategory,\n importance,\n entity,\n key,\n value,\n source: \"conversation\",\n decayClass: paramDecayClass,\n summary,\n tags,\n scope,\n scopeTarget,\n sourceSessions: storeSessionId ?? undefined,\n provenanceSession: provenanceSessionId,\n extractionMethod: \"active\",\n extractionConfidence: importance,\n decayFreezeUntil: decayFreezeUntil ?? undefined,\n ...(supersedes?.trim() ? { validFrom: nowSec, supersedesId: supersedes.trim() } : {}),\n });\n const entry = storeResult.entry;\n // Guard: skip post-store ops when pre-store guard blocked the write (#1560, #1561)\n if (!storeResult.skipped) {\n await cleanupEvictedVector({\n vectorDb,\n evictedFactId: storeResult.evictedFactId,\n logger: api.logger,\n context: \"memory-store\",\n });\n recordActiveStoreProvenance(entry.id, textToStore);\n if (supersedes?.trim()) {\n const supersededId = supersedes.trim();\n factsDb.supersede(supersededId, entry.id);\n aliasDb?.deleteByFactId(supersededId);\n await deleteVectorForFactId({\n vectorDb,\n factId: supersededId,\n logger: api.logger,\n context: \"store-manual-supersede\",\n });\n }\n\n try {\n addOperationBreadcrumb(\"vector\", \"store-fact\");\n if (vector) {\n await storeActiveCanonicalVector({\n factId: entry.id,\n text: textToStore,\n why,\n vector,\n importance,\n category,\n });\n }\n await storeRegistryEmbeddings({\n factsDb,\n embeddingRegistry,\n embeddings,\n factId: entry.id,\n text: textToStore,\n vector,\n logger: api.logger,\n operation: \"store-fact\",\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"vector\",\n operation: \"store-fact\",\n phase: \"runtime\",\n backend: \"lancedb\",\n });\n api.logger.warn(`memory-hybrid: vector store failed: ${err}`);\n }\n\n await maybeRefreshProjectActiveTaskProjection(entry.category, entry.id, entry.scope);\n\n // Issue #150: write event to episodic event log\n if (eventLog) {\n try {\n const eventType = categoryToEventType(category);\n eventLog.append({\n sessionId: api.context?.sessionId ?? \"unknown\",\n timestamp: new Date().toISOString(),\n eventType,\n content: {\n text: textToStore.slice(0, 500),\n factId: entry.id,\n category,\n importance,\n source: \"memory_store\",\n },\n entities: entity ? [entity] : undefined,\n });\n } catch {\n // Non-fatal\n }\n }\n\n // Issue #159: enqueue contextual variant generation (non-blocking)\n if (variantQueue) {\n variantQueue.enqueue({ factId: entry.id, text: textToStore, category: category as string });\n }\n\n // Issue #149: generate and store retrieval aliases (non-blocking)\n if (cfg.aliases?.enabled && aliasDb && importance >= 0.5) {\n const aliasModel = cfg.aliases.model ?? getDefaultCronModel(getCronModelConfig(cfg), \"nano\");\n void storeAliases(entry.id, textToStore, cfg.aliases, aliasModel, openai, embeddings, aliasDb, (msg) =>\n api.logger.warn(msg),\n ).catch((err) => {\n api.logger.warn(`memory-hybrid: alias generation failed: ${err}`);\n });\n }\n\n // Contradiction detection (Issue #157): check for same entity+key, different value\n // Pass the stored fact's scope so detection stays within the same scope boundary.\n const contradictions = factsDb.detectContradictions(\n entry.id,\n entity ?? null,\n key ?? null,\n value ?? null,\n entry.scope ?? null,\n entry.scopeTarget ?? null,\n );\n for (const { contradictionId, oldFactId } of contradictions) {\n if (eventLog) {\n eventLog.append({\n sessionId: api.context?.sessionId ?? \"unknown\",\n timestamp: new Date().toISOString(),\n eventType: \"correction\",\n content: {\n type: \"contradiction_detected\",\n contradictionId,\n newFactId: entry.id,\n oldFactId,\n entity: entity ?? null,\n key: key ?? null,\n newValue: value ?? null,\n },\n entities: entity ? [entity] : undefined,\n });\n }\n }\n\n // Auto-link to similar facts when enabled\n let autoLinked = 0;\n if (cfg.graph.enabled && cfg.graph.autoLink) {\n const entryScope = entry.scope ?? \"global\";\n const entryScopeTarget = entryScope === \"global\" ? null : (entry.scopeTarget ?? null);\n const similar = factsDb.findSimilarForClassification(\n textToStore,\n entity ?? null,\n key ?? null,\n cfg.graph.autoLinkLimit,\n entryScope,\n entryScopeTarget,\n );\n for (const s of similar) {\n if (s.id === entry.id) continue;\n factsDb.createLink(entry.id, s.id, \"RELATED_TO\", cfg.graph.autoLinkMinScore);\n autoLinked++;\n }\n }\n\n // Entity-based auto-linking (Issue #154): known-entity matching, IP NER,\n // temporal co-occurrence, and supersession detection.\n let entityAutoLinked = 0;\n let autoSupersededIds: string[] = [];\n if (cfg.graph.enabled && cfg.graph.autoLink) {\n const sessionId = api.context?.sessionId ?? null;\n const result = factsDb.autoLinkEntities(\n entry.id,\n textToStore,\n entity ?? null,\n key ?? null,\n sessionId,\n {\n coOccurrenceWeight: cfg.graph.coOccurrenceWeight,\n autoSupersede: cfg.graph.autoSupersede,\n },\n entry.scope ?? null,\n entry.scopeTarget ?? null,\n );\n entityAutoLinked = result.linkedCount;\n autoSupersededIds = result.supersededIds;\n if (autoSupersededIds.length > 0) {\n api.logger.info?.(\n `memory-hybrid: autoSupersede — superseded [${autoSupersededIds.join(\", \")}] with ${entry.id}`,\n );\n }\n }\n\n // NER + contact/org layer (#985–#987): async enrichment after graph auto-link; uses franc + LLM.\n if (cfg.graph.enabled) {\n const enrichModel = getDefaultCronModel(getCronModelConfig(cfg), \"nano\");\n void extractEntityMentionsWithLlm(textToStore, openai, enrichModel, {\n stopWords: cfg.entityExtraction.stopWords,\n })\n .then(({ mentions, detectedLang }) => {\n factsDb.applyEntityEnrichment(entry.id, mentions, detectedLang);\n })\n .catch((err) => {\n const msg = err instanceof Error ? (err.stack ?? err.message) : String(err);\n api.logger.warn?.(`memory-hybrid: entity enrichment failed: ${msg}`);\n });\n }\n\n const totalLinked = autoLinked + entityAutoLinked;\n const verbosity = cfg.verbosity ?? \"normal\";\n let storedMsg: string;\n if (isCompactVerbosity(verbosity)) {\n // Quiet: only report the ID and any warnings (contradictions are important)\n storedMsg = `Stored: ${entry.id}${\n contradictions.length > 0\n ? ` (⚠️ contradicts ${contradictions.length} existing fact${contradictions.length === 1 ? \"\" : \"s\"})`\n : \"\"\n }`;\n } else {\n // normal / verbose: full details (verbose adds scope/category info)\n storedMsg = `Stored: \"${textToStore.slice(0, 100)}${textToStore.length > 100 ? \"...\" : \"\"}\"${entity ? ` [entity: ${entity}]` : \"\"} [decay: ${entry.decayClass}]${supersedes?.trim() ? \" (supersedes previous fact)\" : \"\"}${totalLinked > 0 ? ` (linked to ${totalLinked} related fact${totalLinked === 1 ? \"\" : \"s\"})` : \"\"}${\n autoSupersededIds.length > 0\n ? ` (auto-superseded ${autoSupersededIds.length} fact${autoSupersededIds.length === 1 ? \"\" : \"s\"})`\n : \"\"\n }${\n contradictions.length > 0\n ? ` (⚠️ contradicts ${contradictions.length} existing fact${contradictions.length === 1 ? \"\" : \"s\"})`\n : \"\"\n }`;\n if (verbosity === \"verbose\") {\n storedMsg += ` [id: ${entry.id}]`;\n if (entry.scope)\n storedMsg += ` [scope: ${entry.scope}${entry.scopeTarget ? `/${entry.scopeTarget}` : \"\"}]`;\n }\n }\n\n auditAppend({\n agentId: agentIdForAudit(),\n action: \"memory_store\",\n target: `memory #${entry.id}`,\n outcome: \"success\",\n sessionId: api.context?.sessionId ?? undefined,\n context: { category },\n });\n\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: storedMsg,\n },\n ],\n details: {\n action: supersedes?.trim() ? \"updated\" : \"created\",\n id: entry.id,\n why: why ?? undefined,\n backend: \"both\",\n decayClass: entry.decayClass,\n ...(supersedes?.trim() ? { superseded: supersedes.trim() } : {}),\n ...(totalLinked > 0 ? { autoLinked: totalLinked } : {}),\n ...(autoSupersededIds.length > 0 ? { autoSuperseded: autoSupersededIds } : {}),\n ...(contradictions.length > 0\n ? {\n contradictions: contradictions.map((c) => ({\n contradictionId: c.contradictionId,\n oldFactId: c.oldFactId,\n })),\n }\n : {}),\n ...(decayFreezeUntil != null ? { decayFreezeUntil } : {}),\n },\n };\n }\n // WAL cleanup and return for skipped store path (Bug fix #1560, #1561)\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: `Store blocked by pre-store guard (category: ${category}).`,\n },\n ],\n details: { action: \"skipped\", reason: \"blocked-by-guard\", category },\n };\n } catch (err) {\n auditAppend({\n agentId: agentIdForAudit(),\n action: \"memory_store\",\n target: undefined,\n outcome: \"failed\",\n error: err instanceof Error ? err.message : String(err),\n sessionId: api.context?.sessionId ?? undefined,\n });\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"memory\",\n operation: \"memory-store\",\n phase: \"runtime\",\n });\n throw err;\n }\n },\n },\n { name: \"memory_store\" },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"register-store-tools.js","names":[],"sources":["../../../tools/memory/register-store-tools.ts"],"sourcesContent":["/**\n * Memory Tool Registrations\n *\n * Tool definitions for memory recall, storage, promotion, and deletion.\n * Extracted from index.ts for better modularity.\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport { stringEnum } from \"../../utils/typebox.js\";\n\nimport { categoryToEventType } from \"../../backends/event-log.js\";\nimport {\n DECAY_CLASSES,\n type DecayClass,\n type MemoryCategory,\n getCronModelConfig,\n getDefaultCronModel,\n getMemoryCategories,\n isCompactVerbosity,\n} from \"../../config.js\";\nimport { VAULT_POINTER_PREFIX, isCredentialLike, tryParseCredentialForVault } from \"../../services/auto-capture.js\";\nimport { classifyMemoryOperation } from \"../../services/classification.js\";\nimport { AllEmbeddingProvidersFailed, shouldSuppressEmbeddingError } from \"../../services/embeddings.js\";\nimport { extractEntityMentionsWithLlm } from \"../../services/entity-enrichment.js\";\nimport { addOperationBreadcrumb, capturePluginError } from \"../../services/error-reporter.js\";\nimport { extractStructuredFields } from \"../../services/fact-extraction.js\";\nimport { storeAliases } from \"../../services/retrieval-aliases.js\";\nimport { validateScopedClassificationTarget } from \"../../services/classification-scope.js\";\nimport { shouldAutoVerify } from \"../../services/verification-store.js\";\nimport { cleanupEvictedVector, deleteVectorForFactId } from \"../../services/vector-maintenance.js\";\nimport type { MemoryEntry } from \"../../types/memory.js\";\nimport { MEMORY_SCOPES } from \"../../types/memory.js\";\nimport { detectFutureDate } from \"../../utils/date-detector.js\";\nimport { embedCallWithTimeoutAndRetry } from \"../../utils/embed-call.js\";\nimport { extractTags } from \"../../utils/tags.js\";\nimport { truncateForStorage } from \"../../utils/text.js\";\nimport type { MemoryToolRuntime } from \"./runtime.js\";\n\nexport function registerStoreTools(runtime: MemoryToolRuntime): void {\n const {\n factsDb,\n edictStore,\n vectorDb,\n cfg,\n embeddings,\n openai,\n credentialsDb,\n eventLog,\n narrativesDb,\n provenanceService,\n aliasDb,\n embeddingRegistry,\n verificationStore,\n lastProgressiveIndexIds,\n currentAgentIdRef,\n pendingLLMWarnings,\n variantQueue,\n buildToolScopeFilter,\n walWrite,\n walRemove,\n findSimilarByEmbedding,\n auditStore,\n api,\n auditAppend,\n agentIdForAudit,\n maybeRefreshProjectActiveTaskProjection,\n storeActiveCanonicalVector,\n storeRegistryEmbeddings,\n isEdictWriteToolEnabled,\n sanitizeScopeParam,\n } = runtime;\n\n api.registerTool(\n {\n name: \"memory_store\",\n label: \"Memory Store\",\n description:\n \"Save important information in long-term memory. Stores to both structured (SQLite) and semantic (LanceDB) backends.\",\n parameters: Type.Object({\n text: Type.String({ description: \"Information to remember\" }),\n why: Type.Optional(\n Type.String({\n description:\n \"Optional lineage context: why this memory matters (decision rationale, file impact, blocker context, etc.).\",\n }),\n ),\n importance: Type.Optional(\n Type.Number({\n description:\n \"Importance 0-1 (default: 0.5). Higher values signal facts that should survive longer during decay.\",\n }),\n ),\n category: Type.Optional(stringEnum(getMemoryCategories() as unknown as readonly string[])),\n entity: Type.Optional(\n Type.String({\n description: \"Entity name (person, project, tool, etc.)\",\n }),\n ),\n key: Type.Optional(\n Type.String({\n description: \"Structured key (e.g. 'birthday', 'email')\",\n }),\n ),\n value: Type.Optional(\n Type.String({\n description: \"Structured value (e.g. 'Nov 13', 'john@example.com')\",\n }),\n ),\n decayClass: Type.Optional(\n Object.assign(stringEnum(DECAY_CLASSES as unknown as readonly string[]), {\n description:\n \"Decay class defining half-life: durable (~3mo), normal (~2w), short (~2d), session (~1d), ephemeral (~4h), permanent (no decay). Legacy aliases: stable=durable, active=normal, checkpoint=ephemeral.\",\n }),\n ),\n tags: Type.Optional(\n Type.Array(Type.String(), {\n description: \"Topic tags for sharper retrieval (e.g. nibe, zigbee). Auto-inferred if omitted.\",\n }),\n ),\n supersedes: Type.Optional(\n Type.String({\n description:\n \"Fact id this one supersedes (replaces). Marks the old fact as superseded and links the new one.\",\n }),\n ),\n scope: Type.Optional(stringEnum(MEMORY_SCOPES as unknown as readonly string[])),\n scopeTarget: Type.Optional(\n Type.String({\n description:\n \"Scope target (userId, agentId, or sessionId). Required when scope is user, agent, or session.\",\n }),\n ),\n verification_tier: Type.Optional(\n Type.String({\n description:\n \"Optional verification tier override (e.g. 'critical') to force verification store enrollment.\",\n }),\n ),\n decayFreezeUntil: Type.Optional(\n Type.Number({\n description:\n \"Unix epoch seconds until which confidence decay is paused. Auto-detected from future dates in text if omitted.\",\n }),\n ),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n try {\n const {\n text,\n why,\n importance = 0.5,\n category = \"other\",\n entity: paramEntity,\n key: paramKey,\n value: paramValue,\n decayClass: paramDecayClass,\n tags: paramTags,\n supersedes,\n scope: paramScope,\n scopeTarget: paramScopeTarget,\n verification_tier: verificationTier,\n decayFreezeUntil: paramDecayFreezeUntil,\n } = params as {\n text: string;\n why?: string;\n importance?: number;\n category?: MemoryCategory;\n entity?: string;\n key?: string;\n value?: string;\n decayClass?: DecayClass;\n tags?: string[];\n supersedes?: string;\n scope?: \"global\" | \"user\" | \"agent\" | \"session\";\n scopeTarget?: string;\n verification_tier?: string;\n decayFreezeUntil?: number;\n };\n\n // --- Early input validation (must run before any side effects) ---\n if (text.trim().length === 0) {\n return {\n content: [{ type: \"text\", text: \"memory_store: text must not be empty or whitespace.\" }],\n details: { error: \"invalid_text\" },\n };\n }\n\n let textToStore = text;\n textToStore = truncateForStorage(textToStore, cfg.captureMaxChars);\n\n const importanceValue = importance as number;\n if (!Number.isFinite(importanceValue) || importanceValue < 0 || importanceValue > 1) {\n return {\n content: [\n {\n type: \"text\",\n text: `memory_store: importance must be a finite number in [0, 1]; got ${importanceValue}.`,\n },\n ],\n details: { error: \"invalid_importance\" },\n };\n }\n\n if (paramDecayFreezeUntil != null && (!Number.isFinite(paramDecayFreezeUntil) || paramDecayFreezeUntil < 0)) {\n return {\n content: [\n {\n type: \"text\",\n text: `memory_store: decayFreezeUntil must be a non-negative finite epoch seconds value; got ${paramDecayFreezeUntil}.`,\n },\n ],\n details: { error: \"invalid_decay_freeze_until\" },\n };\n }\n // --- End early validation ---\n\n const provenanceSessionId = api.context?.sessionId ?? null;\n const recordActiveStoreProvenance = (factId: string, sourceText?: string) => {\n if (!provenanceService || !cfg.provenance.enabled) return;\n try {\n provenanceService.addEdge(factId, {\n edgeType: \"DERIVED_FROM\",\n sourceType: \"active_store\",\n sourceId: provenanceSessionId ?? \"unknown-session\",\n sourceText,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"provenance\",\n operation: \"memory-store-provenance\",\n factId,\n });\n }\n };\n\n const extracted = extractStructuredFields(textToStore, category as MemoryCategory);\n const entity = paramEntity || extracted.entity;\n const key = paramKey || extracted.key;\n const value = paramValue || extracted.value;\n\n if (factsDb.hasDuplicate(textToStore, \"conversation\", { category, entity, key, value })) {\n return {\n content: [{ type: \"text\", text: \"Similar memory already exists.\" }],\n details: { action: \"duplicate\" },\n };\n }\n\n // FR-006: Compute scope early so it's available for classify-before-write UPDATE path; normal path may overwrite with multiAgent logic below\n let scope: \"global\" | \"user\" | \"agent\" | \"session\" = paramScope ?? \"global\";\n let scopeTarget: string | null = scope === \"global\" ? null : (paramScopeTarget?.trim() ?? null);\n if (scope !== \"global\" && !scopeTarget) {\n return {\n content: [\n {\n type: \"text\",\n text: `Scope \"${scope}\" requires scopeTarget (userId, agentId, or sessionId).`,\n },\n ],\n details: { error: \"scope_target_required\" },\n };\n }\n\n const explicitVerificationTier = (verificationTier ?? \"\").trim().toLowerCase();\n\n const maybeAutoVerify = (\n factId: string,\n factText: string,\n autoTags: string[],\n autoEntity?: string | null,\n autoKey?: string | null,\n autoValue?: string | null,\n ) => {\n if (!cfg.verification.enabled || !verificationStore) return;\n const shouldEnroll =\n explicitVerificationTier === \"critical\" ||\n (cfg.verification.autoClassify &&\n shouldAutoVerify({\n text: factText,\n category,\n tags: autoTags,\n entity: autoEntity,\n key: autoKey,\n value: autoValue,\n verificationTier: verificationTier ?? null,\n }));\n if (!shouldEnroll) return;\n try {\n const verifiedBy = explicitVerificationTier === \"critical\" ? \"agent\" : \"system\";\n verificationStore.verify(factId, factText, verifiedBy);\n } catch (err) {\n api.logger.warn?.(`memory-hybrid: auto-verify failed for ${factId}: ${err}`);\n }\n };\n\n if (isCredentialLike(textToStore, entity, key, value)) {\n if (cfg.credentials.enabled && credentialsDb) {\n const parsed = tryParseCredentialForVault(textToStore, entity, key, value, {\n requirePatternMatch: cfg.credentials.autoCapture?.requirePatternMatch === true,\n });\n if (parsed) {\n const stored = credentialsDb.storeIfNew({\n service: parsed.service,\n type: parsed.type,\n value: parsed.secretValue,\n url: parsed.url,\n notes: parsed.notes,\n });\n if (!stored) {\n return {\n content: [\n { type: \"text\", text: `Credential already in vault for ${parsed.service} (${parsed.type}).` },\n ],\n details: { action: \"credential_skipped_duplicate\", service: parsed.service, type: parsed.type },\n };\n }\n const pointerText = `Credential for ${parsed.service} (${parsed.type}) — stored in secure vault. Use credential_get(service=\"${parsed.service}\", type=\"${parsed.type}\") to retrieve.`;\n const pointerValue = `${VAULT_POINTER_PREFIX}${parsed.service}:${parsed.type}`;\n const pointerStoreResult = factsDb.storeWithResult({\n text: pointerText,\n why,\n category: \"technical\" as MemoryCategory,\n importance,\n entity: \"Credentials\",\n key: parsed.service,\n value: pointerValue,\n source: \"conversation\",\n decayClass: paramDecayClass ?? \"permanent\",\n tags: [\"auth\", ...extractTags(pointerText, \"Credentials\")],\n provenanceSession: provenanceSessionId,\n extractionMethod: \"active\",\n extractionConfidence: importance,\n });\n const pointerEntry = pointerStoreResult.entry;\n // Guard: if the pointer was rejected by the pre-store guard, undo the vault store and return rejected artifact\n if (pointerStoreResult.rejected) {\n try {\n credentialsDb.delete(parsed.service, parsed.type as any);\n } catch (_cleanupErr) {\n // best-effort cleanup\n }\n return {\n content: [{ type: \"text\", text: \"Credential-like content rejected by pre-store guard.\" }],\n details: { action: \"credential_rejected_artifact\" },\n };\n }\n await cleanupEvictedVector({\n vectorDb,\n evictedFactId: pointerStoreResult.evictedFactId,\n logger: api.logger,\n context: \"memory-store-credential-pointer\",\n });\n recordActiveStoreProvenance(pointerEntry.id, pointerText);\n try {\n addOperationBreadcrumb(\"vector\", \"store-credential-pointer\");\n const vector = await embedCallWithTimeoutAndRetry(\n () => embeddings.embed(pointerText),\n \"memory-tools:store-credential-pointer\",\n );\n await storeActiveCanonicalVector({\n factId: pointerEntry.id,\n text: pointerText,\n why,\n vector,\n importance,\n category: \"technical\",\n });\n await storeRegistryEmbeddings({\n factsDb,\n embeddingRegistry,\n embeddings,\n factId: pointerEntry.id,\n text: pointerText,\n vector,\n logger: api.logger,\n operation: \"store-credential-pointer\",\n });\n } catch (err) {\n // AllEmbeddingProvidersFailed is expected when no providers are configured — don't report to Sentry.\n if (!(err instanceof AllEmbeddingProvidersFailed)) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"vector\",\n operation: \"store-credential-pointer\",\n phase: \"runtime\",\n backend: \"lancedb\",\n });\n }\n api.logger.warn(`memory-hybrid: vector store failed: ${err}`);\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Credential stored in vault for ${parsed.service} (${parsed.type}). Pointer saved in memory.`,\n },\n ],\n details: {\n action: \"credential_vault\",\n id: pointerEntry.id,\n service: parsed.service,\n type: parsed.type,\n },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: \"Credential-like content detected but could not be parsed as a structured credential; not stored (vault is enabled).\",\n },\n ],\n details: { action: \"credential_skipped\" },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: \"Credential-like content detected. Ordinary memory storage is blocked while the credential vault is disabled or unavailable. Enable credentials vault and retry.\",\n },\n ],\n details: { action: \"credential_blocked_no_vault\" },\n };\n }\n\n const tags =\n paramTags && paramTags.length > 0\n ? paramTags.map((t) => t.trim().toLowerCase()).filter(Boolean)\n : extractTags(textToStore, entity);\n\n const summaryThreshold = cfg.autoRecall.summaryThreshold;\n const summary =\n summaryThreshold > 0 && textToStore.length > summaryThreshold\n ? `${textToStore.slice(0, cfg.autoRecall.summaryMaxChars).trim()}…`\n : undefined;\n\n // Generate vector first (needed for WAL and storage)\n let vector: number[] | undefined;\n try {\n vector = await embedCallWithTimeoutAndRetry(\n () => embeddings.embed(textToStore),\n \"memory-tools:store-embed\",\n );\n } catch (err) {\n if (err instanceof AllEmbeddingProvidersFailed) {\n // Graceful degradation: store the fact without a vector.\n // The fact is still findable by structured/keyword search.\n api.logger.warn(\"memory-hybrid: Stored fact without embeddings — all providers unavailable\");\n } else if (shouldSuppressEmbeddingError(err)) {\n // Ollama circuit breaker, 429, config errors, etc. — expected noise (#937); don't send to GlitchTip.\n api.logger.warn(`memory-hybrid: embedding skipped (expected): ${err}`);\n } else {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"embeddings\",\n operation: \"store-embed\",\n phase: \"runtime\",\n });\n api.logger.warn(`memory-hybrid: embedding generation failed: ${err}`);\n }\n }\n\n // Classify the operation before storing (use embedding similarity)\n if (cfg.store.classifyBeforeWrite) {\n let similarFacts: MemoryEntry[] = [];\n if (vector) {\n similarFacts = await findSimilarByEmbedding(vectorDb, factsDb, vector, 5, 0.3, {\n scope,\n scopeTarget,\n });\n }\n if (similarFacts.length === 0) {\n similarFacts = factsDb.findSimilarForClassification(textToStore, entity, key, 5, scope, scopeTarget);\n }\n if (similarFacts.length > 0) {\n const classification = await classifyMemoryOperation(\n textToStore,\n entity,\n key,\n similarFacts,\n openai,\n cfg.store.classifyModel ?? getDefaultCronModel(getCronModelConfig(cfg), \"nano\"),\n api.logger,\n );\n\n if (classification.action === \"NOOP\") {\n return {\n content: [{ type: \"text\", text: `Already known: ${classification.reason}` }],\n details: { action: \"noop\", reason: classification.reason },\n };\n }\n\n if (classification.action === \"DELETE\" && classification.targetId) {\n const target = validateScopedClassificationTarget({\n targetId: classification.targetId,\n candidates: similarFacts,\n getById: (id) => factsDb.getById(id),\n scope,\n scopeTarget,\n warn: (message) => api.logger.warn?.(message),\n warnMessage: `memory-hybrid: blocked cross-scope or unknown memory_store DELETE target ${classification.targetId}`,\n });\n if (target) {\n factsDb.supersede(classification.targetId, null);\n aliasDb?.deleteByFactId(classification.targetId);\n await deleteVectorForFactId({\n vectorDb,\n factId: classification.targetId,\n logger: api.logger,\n context: \"store-delete-action\",\n });\n return {\n content: [\n { type: \"text\", text: `Retracted fact ${classification.targetId}: ${classification.reason}` },\n ],\n details: { action: \"delete\", targetId: classification.targetId, reason: classification.reason },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Blocked delete target ${classification.targetId}: failed scope/candidate validation.`,\n },\n ],\n details: { action: \"noop\", reason: \"blocked-delete-target-validation\" },\n };\n }\n\n if (classification.action === \"UPDATE\" && classification.targetId) {\n const oldFact = validateScopedClassificationTarget({\n targetId: classification.targetId,\n candidates: similarFacts,\n getById: (id) => factsDb.getById(id),\n scope,\n scopeTarget,\n warn: (message) => api.logger.warn?.(message),\n warnMessage: `memory-hybrid: blocked cross-scope or unknown memory_store UPDATE target ${classification.targetId}`,\n });\n if (oldFact) {\n const walEntryId = await walWrite(\n \"update\",\n {\n text: textToStore,\n why,\n category,\n importance: Math.max(importance, oldFact.importance),\n entity: entity || oldFact.entity,\n key: key || oldFact.key,\n value: value || oldFact.value,\n source: \"conversation\",\n decayClass: paramDecayClass ?? oldFact.decayClass,\n summary,\n tags,\n vector,\n embeddingModelName: vector ? embeddings.modelName : undefined,\n scope,\n scopeTarget,\n },\n api.logger,\n classification.targetId,\n );\n\n const nowSec = Math.floor(Date.now() / 1000);\n const updateStoreResult = factsDb.storeWithResult({\n text: textToStore,\n why,\n category: category as MemoryCategory,\n importance: Math.max(importance, oldFact.importance),\n entity: entity || oldFact.entity,\n key: key || oldFact.key,\n value: value || oldFact.value,\n source: \"conversation\",\n decayClass: paramDecayClass ?? oldFact.decayClass,\n summary,\n tags,\n validFrom: nowSec,\n supersedesId: classification.targetId,\n scope,\n scopeTarget,\n sourceSessions: api.context?.sessionId ?? undefined,\n provenanceSession: provenanceSessionId,\n extractionMethod: \"active\",\n extractionConfidence: Math.max(importance, oldFact.importance),\n });\n const newEntry = updateStoreResult.entry;\n // Guard: skip post-store ops when pre-store guard blocked the write (#1560, #1561)\n if (!updateStoreResult.skipped) {\n await cleanupEvictedVector({\n vectorDb,\n evictedFactId: updateStoreResult.evictedFactId,\n logger: api.logger,\n context: \"memory-store-update\",\n });\n recordActiveStoreProvenance(newEntry.id, textToStore);\n factsDb.supersede(classification.targetId, newEntry.id);\n aliasDb?.deleteByFactId(classification.targetId);\n await deleteVectorForFactId({\n vectorDb,\n factId: classification.targetId,\n logger: api.logger,\n context: \"store-update-delete-superseded\",\n });\n maybeAutoVerify(\n newEntry.id,\n textToStore,\n newEntry.tags ?? tags,\n newEntry.entity,\n newEntry.key,\n newEntry.value,\n );\n\n const finalImportance = Math.max(importance, oldFact.importance);\n try {\n if (vector) {\n await storeActiveCanonicalVector({\n factId: newEntry.id,\n text: textToStore,\n why,\n vector,\n importance: finalImportance,\n category,\n });\n }\n await storeRegistryEmbeddings({\n factsDb,\n embeddingRegistry,\n embeddings,\n factId: newEntry.id,\n text: textToStore,\n vector,\n logger: api.logger,\n operation: \"store-update-supersede\",\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"vector\",\n operation: \"store-update-supersede\",\n phase: \"runtime\",\n backend: \"lancedb\",\n });\n api.logger.warn(`memory-hybrid: vector store failed: ${err}`);\n }\n\n await maybeRefreshProjectActiveTaskProjection(newEntry.category, newEntry.id, newEntry.scope);\n\n // Issue #159: enqueue contextual variant generation (non-blocking)\n if (variantQueue) {\n variantQueue.enqueue({ factId: newEntry.id, text: textToStore, category: category as string });\n }\n\n api.logger.info?.(\n `memory-hybrid: UPDATE — superseded ${classification.targetId} with ${newEntry.id}: ${classification.reason}`,\n );\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: `Updated: superseded old fact with \"${textToStore.slice(0, 100)}${textToStore.length > 100 ? \"...\" : \"\"}\"${entity ? ` [entity: ${entity}]` : \"\"} [decay: ${newEntry.decayClass}] (reason: ${classification.reason})`,\n },\n ],\n details: {\n action: \"updated\",\n id: newEntry.id,\n why: why ?? undefined,\n superseded: classification.targetId,\n reason: classification.reason,\n backend: \"both\",\n decayClass: newEntry.decayClass,\n },\n };\n }\n // WAL cleanup for skipped update path\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: `Store blocked by pre-store guard (category: ${category}).`,\n },\n ],\n details: { action: \"skipped\", reason: \"blocked-by-guard\", category },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Blocked update target ${classification.targetId}: failed scope/candidate validation.`,\n },\n ],\n details: { action: \"noop\", reason: \"blocked-update-target-validation\" },\n };\n }\n // action === \"ADD\" falls through to normal store\n }\n }\n\n // Resolve final scope before WAL write so the WAL entry captures the complete scope\n // metadata. Without this, a crash between WAL write and DB commit would cause replay\n // to default scoped facts to global scope (issue #1574).\n // Smart default scope based on agent identity and config (FR-006: overwrite for normal path when not explicit)\n if (paramScope) {\n // Explicit scope parameter always takes precedence\n scope = paramScope;\n scopeTarget = scope === \"global\" ? null : (paramScopeTarget?.trim() ?? null);\n } else {\n // Auto-determine scope based on multiAgent config\n const agentId = currentAgentIdRef.value || cfg.multiAgent.orchestratorId;\n const isOrchestrator = agentId === cfg.multiAgent.orchestratorId;\n\n // Strict agent scoping: throw if agent detection failed in agent/auto mode\n if (\n cfg.multiAgent.strictAgentScoping &&\n !currentAgentIdRef.value &&\n (cfg.multiAgent.defaultStoreScope === \"agent\" || cfg.multiAgent.defaultStoreScope === \"auto\")\n ) {\n throw new Error(\n `Agent detection failed (currentAgentId is null) and multiAgent.strictAgentScoping is enabled. Cannot auto-determine scope for defaultStoreScope=\"${cfg.multiAgent.defaultStoreScope}\". Fix: ensure agent_id is provided in session context, or disable strictAgentScoping.`,\n );\n }\n\n if (cfg.multiAgent.defaultStoreScope === \"global\") {\n // Backward compatible: always global\n scope = \"global\";\n scopeTarget = null;\n } else if (cfg.multiAgent.defaultStoreScope === \"agent\") {\n // Always agent-scoped (for fully isolated setups)\n scope = \"agent\";\n scopeTarget = agentId;\n } else {\n // \"auto\" mode: orchestrator → global, specialists → agent\n if (isOrchestrator) {\n scope = \"global\";\n scopeTarget = null;\n } else {\n scope = \"agent\";\n scopeTarget = agentId;\n }\n }\n }\n\n // Final validation: if scope requires a target but none is available, fall back to global\n // (unless strictAgentScoping already threw above)\n if (scope !== \"global\" && !scopeTarget) {\n if (paramScope) {\n // User explicitly requested non-global scope but didn't provide target\n return {\n content: [\n {\n type: \"text\",\n text: `Scope \"${scope}\" requires scopeTarget (userId, agentId, or sessionId). Provide scopeTarget parameter or use scope=\"global\".`,\n },\n ],\n details: { error: \"scope_target_required\" },\n };\n }\n // Auto-determined scope ended up without target (shouldn't happen with current logic,\n // but handle gracefully by falling back to global)\n scope = \"global\";\n scopeTarget = null;\n }\n\n const walEntryId = await walWrite(\n \"store\",\n {\n text: textToStore,\n why,\n category,\n importance,\n entity,\n key,\n value,\n source: \"conversation\",\n decayClass: paramDecayClass,\n summary,\n tags,\n vector,\n embeddingModelName: vector ? embeddings.modelName : undefined,\n scope,\n scopeTarget,\n },\n api.logger,\n );\n const decayFreezeUntil =\n paramDecayFreezeUntil != null && Number.isFinite(paramDecayFreezeUntil)\n ? paramDecayFreezeUntil\n : detectFutureDate(textToStore, cfg.futureDateProtection ?? { enabled: false });\n\n const nowSec = Math.floor(Date.now() / 1000);\n const storeSessionId = api.context?.sessionId ?? null;\n const storeResult = factsDb.storeWithResult({\n text: textToStore,\n why,\n category: category as MemoryCategory,\n importance,\n entity,\n key,\n value,\n source: \"conversation\",\n decayClass: paramDecayClass,\n summary,\n tags,\n scope,\n scopeTarget,\n sourceSessions: storeSessionId ?? undefined,\n provenanceSession: provenanceSessionId,\n extractionMethod: \"active\",\n extractionConfidence: importance,\n decayFreezeUntil: decayFreezeUntil ?? undefined,\n ...(supersedes?.trim() ? { validFrom: nowSec, supersedesId: supersedes.trim() } : {}),\n });\n const entry = storeResult.entry;\n // Guard: skip post-store ops when pre-store guard blocked the write (#1560, #1561)\n if (!storeResult.skipped) {\n await cleanupEvictedVector({\n vectorDb,\n evictedFactId: storeResult.evictedFactId,\n logger: api.logger,\n context: \"memory-store\",\n });\n recordActiveStoreProvenance(entry.id, textToStore);\n if (supersedes?.trim()) {\n const supersededId = supersedes.trim();\n factsDb.supersede(supersededId, entry.id);\n aliasDb?.deleteByFactId(supersededId);\n await deleteVectorForFactId({\n vectorDb,\n factId: supersededId,\n logger: api.logger,\n context: \"store-manual-supersede\",\n });\n }\n\n try {\n addOperationBreadcrumb(\"vector\", \"store-fact\");\n if (vector) {\n await storeActiveCanonicalVector({\n factId: entry.id,\n text: textToStore,\n why,\n vector,\n importance,\n category,\n });\n }\n await storeRegistryEmbeddings({\n factsDb,\n embeddingRegistry,\n embeddings,\n factId: entry.id,\n text: textToStore,\n vector,\n logger: api.logger,\n operation: \"store-fact\",\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"vector\",\n operation: \"store-fact\",\n phase: \"runtime\",\n backend: \"lancedb\",\n });\n api.logger.warn(`memory-hybrid: vector store failed: ${err}`);\n }\n\n await maybeRefreshProjectActiveTaskProjection(entry.category, entry.id, entry.scope);\n\n // Issue #150: write event to episodic event log\n if (eventLog) {\n try {\n const eventType = categoryToEventType(category);\n eventLog.append({\n sessionId: api.context?.sessionId ?? \"unknown\",\n timestamp: new Date().toISOString(),\n eventType,\n content: {\n text: textToStore.slice(0, 500),\n factId: entry.id,\n category,\n importance,\n source: \"memory_store\",\n },\n entities: entity ? [entity] : undefined,\n });\n } catch {\n // Non-fatal\n }\n }\n\n // Issue #159: enqueue contextual variant generation (non-blocking)\n if (variantQueue) {\n variantQueue.enqueue({ factId: entry.id, text: textToStore, category: category as string });\n }\n\n // Issue #149: generate and store retrieval aliases (non-blocking)\n if (cfg.aliases?.enabled && aliasDb && importance >= 0.5) {\n const aliasModel = cfg.aliases.model ?? getDefaultCronModel(getCronModelConfig(cfg), \"nano\");\n void storeAliases(entry.id, textToStore, cfg.aliases, aliasModel, openai, embeddings, aliasDb, (msg) =>\n api.logger.warn(msg),\n ).catch((err) => {\n api.logger.warn(`memory-hybrid: alias generation failed: ${err}`);\n });\n }\n\n // Contradiction detection (Issue #157): check for same entity+key, different value\n // Pass the stored fact's scope so detection stays within the same scope boundary.\n const contradictions = factsDb.detectContradictions(\n entry.id,\n entity ?? null,\n key ?? null,\n value ?? null,\n entry.scope ?? null,\n entry.scopeTarget ?? null,\n );\n for (const { contradictionId, oldFactId } of contradictions) {\n if (eventLog) {\n eventLog.append({\n sessionId: api.context?.sessionId ?? \"unknown\",\n timestamp: new Date().toISOString(),\n eventType: \"correction\",\n content: {\n type: \"contradiction_detected\",\n contradictionId,\n newFactId: entry.id,\n oldFactId,\n entity: entity ?? null,\n key: key ?? null,\n newValue: value ?? null,\n },\n entities: entity ? [entity] : undefined,\n });\n }\n }\n\n // Auto-link to similar facts when enabled\n let autoLinked = 0;\n if (cfg.graph.enabled && cfg.graph.autoLink) {\n const entryScope = entry.scope ?? \"global\";\n const entryScopeTarget = entryScope === \"global\" ? null : (entry.scopeTarget ?? null);\n const similar = factsDb.findSimilarForClassification(\n textToStore,\n entity ?? null,\n key ?? null,\n cfg.graph.autoLinkLimit,\n entryScope,\n entryScopeTarget,\n );\n for (const s of similar) {\n if (s.id === entry.id) continue;\n factsDb.createLink(entry.id, s.id, \"RELATED_TO\", cfg.graph.autoLinkMinScore);\n autoLinked++;\n }\n }\n\n // Entity-based auto-linking (Issue #154): known-entity matching, IP NER,\n // temporal co-occurrence, and supersession detection.\n let entityAutoLinked = 0;\n let autoSupersededIds: string[] = [];\n if (cfg.graph.enabled && cfg.graph.autoLink) {\n const sessionId = api.context?.sessionId ?? null;\n const result = factsDb.autoLinkEntities(\n entry.id,\n textToStore,\n entity ?? null,\n key ?? null,\n sessionId,\n {\n coOccurrenceWeight: cfg.graph.coOccurrenceWeight,\n autoSupersede: cfg.graph.autoSupersede,\n },\n entry.scope ?? null,\n entry.scopeTarget ?? null,\n );\n entityAutoLinked = result.linkedCount;\n autoSupersededIds = result.supersededIds;\n if (autoSupersededIds.length > 0) {\n api.logger.info?.(\n `memory-hybrid: autoSupersede — superseded [${autoSupersededIds.join(\", \")}] with ${entry.id}`,\n );\n }\n }\n\n // NER + contact/org layer (#985–#987): async enrichment after graph auto-link; uses franc + LLM.\n if (cfg.graph.enabled) {\n const enrichModel = getDefaultCronModel(getCronModelConfig(cfg), \"nano\");\n void extractEntityMentionsWithLlm(textToStore, openai, enrichModel, {\n stopWords: cfg.entityExtraction.stopWords,\n })\n .then(({ mentions, detectedLang }) => {\n factsDb.applyEntityEnrichment(entry.id, mentions, detectedLang);\n })\n .catch((err) => {\n const msg = err instanceof Error ? (err.stack ?? err.message) : String(err);\n api.logger.warn?.(`memory-hybrid: entity enrichment failed: ${msg}`);\n });\n }\n\n const totalLinked = autoLinked + entityAutoLinked;\n const verbosity = cfg.verbosity ?? \"normal\";\n let storedMsg: string;\n if (isCompactVerbosity(verbosity)) {\n // Quiet: only report the ID and any warnings (contradictions are important)\n storedMsg = `Stored: ${entry.id}${\n contradictions.length > 0\n ? ` (⚠️ contradicts ${contradictions.length} existing fact${contradictions.length === 1 ? \"\" : \"s\"})`\n : \"\"\n }`;\n } else {\n // normal / verbose: full details (verbose adds scope/category info)\n storedMsg = `Stored: \"${textToStore.slice(0, 100)}${textToStore.length > 100 ? \"...\" : \"\"}\"${entity ? ` [entity: ${entity}]` : \"\"} [decay: ${entry.decayClass}]${supersedes?.trim() ? \" (supersedes previous fact)\" : \"\"}${totalLinked > 0 ? ` (linked to ${totalLinked} related fact${totalLinked === 1 ? \"\" : \"s\"})` : \"\"}${\n autoSupersededIds.length > 0\n ? ` (auto-superseded ${autoSupersededIds.length} fact${autoSupersededIds.length === 1 ? \"\" : \"s\"})`\n : \"\"\n }${\n contradictions.length > 0\n ? ` (⚠️ contradicts ${contradictions.length} existing fact${contradictions.length === 1 ? \"\" : \"s\"})`\n : \"\"\n }`;\n if (verbosity === \"verbose\") {\n storedMsg += ` [id: ${entry.id}]`;\n if (entry.scope)\n storedMsg += ` [scope: ${entry.scope}${entry.scopeTarget ? `/${entry.scopeTarget}` : \"\"}]`;\n }\n }\n\n auditAppend({\n agentId: agentIdForAudit(),\n action: \"memory_store\",\n target: `memory #${entry.id}`,\n outcome: \"success\",\n sessionId: api.context?.sessionId ?? undefined,\n context: { category },\n });\n\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: storedMsg,\n },\n ],\n details: {\n action: supersedes?.trim() ? \"updated\" : \"created\",\n id: entry.id,\n why: why ?? undefined,\n backend: \"both\",\n decayClass: entry.decayClass,\n ...(supersedes?.trim() ? { superseded: supersedes.trim() } : {}),\n ...(totalLinked > 0 ? { autoLinked: totalLinked } : {}),\n ...(autoSupersededIds.length > 0 ? { autoSuperseded: autoSupersededIds } : {}),\n ...(contradictions.length > 0\n ? {\n contradictions: contradictions.map((c) => ({\n contradictionId: c.contradictionId,\n oldFactId: c.oldFactId,\n })),\n }\n : {}),\n ...(decayFreezeUntil != null ? { decayFreezeUntil } : {}),\n },\n };\n }\n // WAL cleanup and return for skipped store path (Bug fix #1560, #1561)\n await walRemove(walEntryId, api.logger);\n return {\n content: [\n {\n type: \"text\",\n text: `Store blocked by pre-store guard (category: ${category}).`,\n },\n ],\n details: { action: \"skipped\", reason: \"blocked-by-guard\", category },\n };\n } catch (err) {\n auditAppend({\n agentId: agentIdForAudit(),\n action: \"memory_store\",\n target: undefined,\n outcome: \"failed\",\n error: err instanceof Error ? err.message : String(err),\n sessionId: api.context?.sessionId ?? undefined,\n });\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"memory\",\n operation: \"memory-store\",\n phase: \"runtime\",\n });\n throw err;\n }\n },\n },\n { name: \"memory_store\" },\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-tools.js","names":[],"sources":["../../tools/memory-tools.ts"],"sourcesContent":["/**\n * Memory Tool Registrations — orchestrator re-exporting split modules under tools/memory/.\n */\n\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { BuildToolScopeFilterFn, FindSimilarByEmbeddingFn } from \"../api/memory-plugin-api.js\";\nimport { buildMemoryToolRuntime } from \"./memory/build-runtime.js\";\nimport { registerCheckpointTools } from \"./memory/register-checkpoint-tools.js\";\nimport { registerDirectoryTools } from \"./memory/register-directory-tools.js\";\nimport { registerEdictTools } from \"./memory/register-edict-tools.js\";\nimport { registerEpisodeTools } from \"./memory/register-episode-tools.js\";\nimport { registerRecallTools } from \"./memory/register-recall-tools.js\";\nimport { registerStoreTools } from \"./memory/register-store-tools.js\";\nimport { resolveMemoryToolsContext } from \"./memory/helpers.js\";\nimport type { BoundWalRemoveFn, BoundWalWriteFn, MemoryToolsContext } from \"./memory/types.js\";\n\nexport type { BoundWalRemoveFn, BoundWalWriteFn, MemoryToolsContext } from \"./memory/types.js\";\n\nexport function registerMemoryTools(ctx: MemoryToolsContext, api: ClawdbotPluginApi): void;\nexport function registerMemoryTools(\n ctx: Omit<MemoryToolsContext, \"buildToolScopeFilter\" | \"walWrite\" | \"walRemove\" | \"findSimilarByEmbedding\"> & {\n wal?: unknown;\n },\n api: ClawdbotPluginApi,\n buildToolScopeFilter: BuildToolScopeFilterFn,\n walWrite: BoundWalWriteFn,\n walRemove: BoundWalRemoveFn,\n findSimilarByEmbedding: FindSimilarByEmbeddingFn,\n): void;\nexport function registerMemoryTools(\n ctx:\n | MemoryToolsContext\n | (Omit<MemoryToolsContext, \"buildToolScopeFilter\" | \"walWrite\" | \"walRemove\" | \"findSimilarByEmbedding\"> & {\n wal?: unknown;\n }),\n api: ClawdbotPluginApi,\n legacyBuildToolScopeFilter?: BuildToolScopeFilterFn,\n legacyWalWrite?: BoundWalWriteFn,\n legacyWalRemove?: BoundWalRemoveFn,\n legacyFindSimilarByEmbedding?: FindSimilarByEmbeddingFn,\n): void {\n const resolvedContext = resolveMemoryToolsContext(\n ctx as Parameters<typeof resolveMemoryToolsContext>[0],\n legacyBuildToolScopeFilter,\n legacyWalWrite,\n legacyWalRemove,\n legacyFindSimilarByEmbedding,\n );\n const runtime = buildMemoryToolRuntime(resolvedContext, api);\n registerRecallTools(runtime);\n registerStoreTools(runtime);\n registerDirectoryTools(runtime);\n registerCheckpointTools(runtime);\n registerEpisodeTools(runtime);\n registerEdictTools(runtime);\n}\n"],"mappings":";;;;;;;;;AA6BA,SAAgB,oBACd,KAKA,KACA,4BACA,gBACA,iBACA,8BACM;CAQN,MAAM,UAAU,uBAPQ,0BACtB,KACA,4BACA,gBACA,iBACA,
|
|
1
|
+
{"version":3,"file":"memory-tools.js","names":[],"sources":["../../tools/memory-tools.ts"],"sourcesContent":["/**\n * Memory Tool Registrations — orchestrator re-exporting split modules under tools/memory/.\n */\n\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { BuildToolScopeFilterFn, FindSimilarByEmbeddingFn } from \"../api/memory-plugin-api.js\";\nimport { buildMemoryToolRuntime } from \"./memory/build-runtime.js\";\nimport { registerCheckpointTools } from \"./memory/register-checkpoint-tools.js\";\nimport { registerDirectoryTools } from \"./memory/register-directory-tools.js\";\nimport { registerEdictTools } from \"./memory/register-edict-tools.js\";\nimport { registerEpisodeTools } from \"./memory/register-episode-tools.js\";\nimport { registerRecallTools } from \"./memory/register-recall-tools.js\";\nimport { registerStoreTools } from \"./memory/register-store-tools.js\";\nimport { resolveMemoryToolsContext } from \"./memory/helpers.js\";\nimport type { BoundWalRemoveFn, BoundWalWriteFn, MemoryToolsContext } from \"./memory/types.js\";\n\nexport type { BoundWalRemoveFn, BoundWalWriteFn, MemoryToolsContext } from \"./memory/types.js\";\n\nexport function registerMemoryTools(ctx: MemoryToolsContext, api: ClawdbotPluginApi): void;\nexport function registerMemoryTools(\n ctx: Omit<MemoryToolsContext, \"buildToolScopeFilter\" | \"walWrite\" | \"walRemove\" | \"findSimilarByEmbedding\"> & {\n wal?: unknown;\n },\n api: ClawdbotPluginApi,\n buildToolScopeFilter: BuildToolScopeFilterFn,\n walWrite: BoundWalWriteFn,\n walRemove: BoundWalRemoveFn,\n findSimilarByEmbedding: FindSimilarByEmbeddingFn,\n): void;\nexport function registerMemoryTools(\n ctx:\n | MemoryToolsContext\n | (Omit<MemoryToolsContext, \"buildToolScopeFilter\" | \"walWrite\" | \"walRemove\" | \"findSimilarByEmbedding\"> & {\n wal?: unknown;\n }),\n api: ClawdbotPluginApi,\n legacyBuildToolScopeFilter?: BuildToolScopeFilterFn,\n legacyWalWrite?: BoundWalWriteFn,\n legacyWalRemove?: BoundWalRemoveFn,\n legacyFindSimilarByEmbedding?: FindSimilarByEmbeddingFn,\n): void {\n const resolvedContext = resolveMemoryToolsContext(\n ctx as Parameters<typeof resolveMemoryToolsContext>[0],\n legacyBuildToolScopeFilter,\n legacyWalWrite,\n legacyWalRemove,\n legacyFindSimilarByEmbedding,\n );\n const runtime = buildMemoryToolRuntime(resolvedContext, api);\n registerRecallTools(runtime);\n registerStoreTools(runtime);\n registerDirectoryTools(runtime);\n registerCheckpointTools(runtime);\n registerEpisodeTools(runtime);\n registerEdictTools(runtime);\n}\n"],"mappings":";;;;;;;;;AA6BA,SAAgB,oBACd,KAKA,KACA,4BACA,gBACA,iBACA,8BACM;CAQN,MAAM,UAAU,uBAPQ,0BACtB,KACA,4BACA,gBACA,iBACA,4BAEmD,GAAG,GAAG;CAC3D,oBAAoB,OAAO;CAC3B,mBAAmB,OAAO;CAC1B,uBAAuB,OAAO;CAC9B,wBAAwB,OAAO;CAC/B,qBAAqB,OAAO;CAC5B,mBAAmB,OAAO;AAC5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persona-tools.js","names":[],"sources":["../../tools/persona-tools.ts"],"sourcesContent":["/**\n * Persona Proposals Tools\n * Tools for proposing and managing changes to identity files (SOUL.md, IDENTITY.md, USER.md)\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { ProposalsDB } from \"../backends/proposals-db.js\";\nimport { applyApprovedProposal } from \"../cli/proposals.js\";\nimport { type HybridMemoryConfig, PROPOSAL_STATUSES, isCompactVerbosity } from \"../config.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport { SECONDS_PER_DAY } from \"../utils/constants.js\";\nimport { getFileSnapshot } from \"../utils/file-snapshot.js\";\nimport { stringEnum } from \"../utils/typebox.js\";\n\nexport interface PluginContext {\n proposalsDb?: ProposalsDB;\n cfg: HybridMemoryConfig;\n resolvedSqlitePath: string;\n}\n\n/**\n * Register persona proposal tools (persona_propose, persona_proposals_list)\n * Only registers if cfg.personaProposals.enabled && proposalsDb is available\n */\nexport function registerPersonaTools(ctx: PluginContext, api: ClawdbotPluginApi) {\n const { proposalsDb, cfg, resolvedSqlitePath } = ctx;\n\n // Only register if persona proposals are enabled and database is available\n if (!cfg.personaProposals.enabled || !proposalsDb) {\n return;\n }\n\n // Shared helper: audit trail logging (used by both tools and CLI commands)\n const auditProposal = async (\n action: string,\n proposalId: string,\n details?: any,\n logger?: { warn?: (msg: string) => void; error?: (msg: string) => void },\n ) => {\n const auditDir = join(dirname(resolvedSqlitePath), \"decisions\");\n await mkdir(auditDir, { recursive: true });\n const timestamp = new Date().toISOString();\n const entry = {\n timestamp,\n action,\n proposalId,\n ...details,\n };\n const auditPath = join(auditDir, `proposal-${proposalId}.jsonl`);\n try {\n await writeFile(auditPath, `${JSON.stringify(entry)}\\n`, { flag: \"a\" });\n } catch (err) {\n const msg = `Audit log write failed: ${err}`;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"persona-proposal-audit\",\n subsystem: \"proposals\",\n proposalId,\n });\n if (logger?.warn) {\n logger.warn(`memory-hybrid: ${msg}`);\n } else if (logger?.error) {\n logger.error(msg);\n }\n }\n };\n\n // Helper: rate limiting check\n const checkRateLimit = (): { allowed: boolean; count: number; limit: number } => {\n const weekInDays = 7;\n const count = proposalsDb?.countRecentProposals(weekInDays);\n const limit = cfg.personaProposals.maxProposalsPerWeek;\n return { allowed: count < limit, count, limit };\n };\n\n api.registerTool(\n {\n name: \"persona_propose\",\n label: \"Propose Persona Change\",\n description:\n \"Propose a change to identity files (SOUL.md, IDENTITY.md, USER.md) based on observed patterns. By default requires human approval; if personaProposals.autoApply is enabled, proposals are applied automatically. Rate-limited to prevent spam.\",\n parameters: Type.Object({\n targetFile: stringEnum(cfg.personaProposals.allowedFiles),\n title: Type.String({\n description: \"Short title for the proposal (e.g., 'Add tone-matching guidance')\",\n }),\n observation: Type.String({\n description:\n \"What pattern or behavior you observed (e.g., 'Over ~50 interactions, user responds better to bullet points')\",\n }),\n suggestedChange: Type.String({\n description: \"The specific change to make to the file (be precise about location and wording)\",\n }),\n confidence: Type.Number({\n description: \"Confidence score 0-1 (must be >= minConfidence from config)\",\n minimum: 0,\n maximum: 1,\n }),\n evidenceSessions: Type.Array(Type.String(), {\n description: \"List of session IDs or references that support this proposal\",\n }),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n const { targetFile, title, observation, suggestedChange, confidence, evidenceSessions } = params as {\n targetFile: string;\n title: string;\n observation: string;\n suggestedChange: string;\n confidence: number;\n evidenceSessions: string[];\n };\n\n // Field length validation (prevent database bloat and file corruption)\n const MAX_TITLE_LENGTH = 200;\n const MAX_OBSERVATION_LENGTH = 5000;\n const MAX_SUGGESTED_CHANGE_LENGTH = 10000;\n\n if (title.length > MAX_TITLE_LENGTH) {\n return {\n content: [\n {\n type: \"text\",\n text: `Title too long: ${title.length} chars (max: ${MAX_TITLE_LENGTH})`,\n },\n ],\n details: { error: \"title_too_long\", length: title.length, max: MAX_TITLE_LENGTH },\n };\n }\n\n if (observation.length > MAX_OBSERVATION_LENGTH) {\n return {\n content: [\n {\n type: \"text\",\n text: `Observation too long: ${observation.length} chars (max: ${MAX_OBSERVATION_LENGTH})`,\n },\n ],\n details: { error: \"observation_too_long\", length: observation.length, max: MAX_OBSERVATION_LENGTH },\n };\n }\n\n if (suggestedChange.length > MAX_SUGGESTED_CHANGE_LENGTH) {\n return {\n content: [\n {\n type: \"text\",\n text: `Suggested change too long: ${suggestedChange.length} chars (max: ${MAX_SUGGESTED_CHANGE_LENGTH})`,\n },\n ],\n details: {\n error: \"suggested_change_too_long\",\n length: suggestedChange.length,\n max: MAX_SUGGESTED_CHANGE_LENGTH,\n },\n };\n }\n\n // Rate limiting\n const rateCheck = checkRateLimit();\n if (!rateCheck.allowed) {\n return {\n content: [\n {\n type: \"text\",\n text: `Rate limit exceeded: ${rateCheck.count}/${rateCheck.limit} proposals this week. Try again later.`,\n },\n ],\n details: { error: \"rate_limit_exceeded\", ...rateCheck },\n };\n }\n\n // Confidence check\n if (confidence < cfg.personaProposals.minConfidence) {\n return {\n content: [\n {\n type: \"text\",\n text: `Confidence ${confidence} is below minimum ${cfg.personaProposals.minConfidence}. Gather more evidence before proposing.`,\n },\n ],\n details: { error: \"confidence_too_low\", confidence, minRequired: cfg.personaProposals.minConfidence },\n };\n }\n\n // Evidence validation: check count and content quality\n if (evidenceSessions.length < cfg.personaProposals.minSessionEvidence) {\n return {\n content: [\n {\n type: \"text\",\n text: `Need at least ${cfg.personaProposals.minSessionEvidence} session evidence (provided: ${evidenceSessions.length})`,\n },\n ],\n details: {\n error: \"insufficient_evidence\",\n provided: evidenceSessions.length,\n minRequired: cfg.personaProposals.minSessionEvidence,\n },\n };\n }\n\n // Validate evidence session content (non-empty, unique)\n const invalidSessions = evidenceSessions.filter((s) => typeof s !== \"string\" || s.trim().length === 0);\n if (invalidSessions.length > 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Evidence sessions must be non-empty strings. Found ${invalidSessions.length} invalid entries.`,\n },\n ],\n details: { error: \"invalid_evidence_sessions\", invalidCount: invalidSessions.length },\n };\n }\n\n // Check for duplicate evidence sessions (without trimming to preserve exact matches)\n const uniqueSessions = new Set(evidenceSessions);\n if (uniqueSessions.size !== evidenceSessions.length) {\n return {\n content: [\n {\n type: \"text\",\n text: `Evidence sessions must be unique. Found ${evidenceSessions.length - uniqueSessions.size} duplicate(s).`,\n },\n ],\n details: {\n error: \"duplicate_evidence_sessions\",\n duplicateCount: evidenceSessions.length - uniqueSessions.size,\n },\n };\n }\n\n // Calculate expiry\n const expiresAt =\n cfg.personaProposals.proposalTTLDays > 0\n ? Math.floor(Date.now() / 1000) + cfg.personaProposals.proposalTTLDays * 24 * 3600\n : null;\n\n // Create proposal\n const snapshot = getFileSnapshot(api.resolvePath(targetFile));\n const proposal = proposalsDb?.create({\n targetFile,\n title,\n observation,\n suggestedChange,\n confidence,\n evidenceSessions,\n expiresAt,\n targetMtimeMs: snapshot?.mtimeMs ?? null,\n targetHash: snapshot?.hash ?? null,\n });\n\n await auditProposal(\n \"created\",\n proposal.id,\n {\n targetFile,\n title,\n confidence,\n evidenceCount: evidenceSessions.length,\n },\n api.logger,\n );\n\n api.logger.info(`memory-hybrid: persona proposal created — ${proposal.id} (${title})`);\n\n if (cfg.personaProposals.autoApply) {\n proposalsDb?.updateStatus(proposal.id, \"approved\", \"auto\");\n await auditProposal(\n \"approved\",\n proposal.id,\n {\n reviewedBy: \"auto\",\n previousStatus: \"pending\",\n newStatus: \"approved\",\n reason: \"autoApply\",\n },\n api.logger,\n );\n const applyCtx = {\n proposalsDb: proposalsDb!,\n cfg,\n resolvedSqlitePath,\n api: { logger: api.logger },\n };\n const applyResult = await applyApprovedProposal(applyCtx, proposal.id);\n const applyVerbosity = cfg.verbosity ?? \"normal\";\n if (applyResult.ok) {\n api.logger.info(\n `memory-hybrid: persona proposal auto-applied — ${proposal.id} → ${applyResult.targetFile}`,\n );\n if (isCompactVerbosity(applyVerbosity)) {\n // Quiet: only emit ID + file, suppress change preview\n return {\n content: [\n {\n type: \"text\",\n text: `Applied: ${proposal.id} → ${applyResult.targetFile}.`,\n },\n ],\n details: {\n proposalId: proposal.id,\n status: \"applied\",\n targetFile: applyResult.targetFile,\n backupPath: applyResult.backupPath,\n },\n };\n }\n const changePreview =\n applyResult.suggestedChange.length > 500\n ? `${applyResult.suggestedChange.slice(0, 500)}…`\n : applyResult.suggestedChange;\n return {\n content: [\n {\n type: \"text\",\n text: `Proposal ${proposal.id} created and automatically applied to ${applyResult.targetFile}.\\nTitle: ${title}\\nBackup: ${applyResult.backupPath}\\n\\nChange applied (truncated to 500 chars):\\n${changePreview}`,\n },\n ],\n details: {\n proposalId: proposal.id,\n status: \"applied\",\n targetFile: applyResult.targetFile,\n backupPath: applyResult.backupPath,\n },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: isCompactVerbosity(applyVerbosity)\n ? `Proposal ${proposal.id}: apply failed — ${applyResult.error}`\n : `Proposal ${proposal.id} was approved automatically but applying to the file failed: ${applyResult.error}\\n\\nYou can run \\`openclaw proposals apply ${proposal.id}\\` after fixing the issue.`,\n },\n ],\n details: { proposalId: proposal.id, status: \"approved\", applyError: applyResult.error },\n };\n }\n\n const verbosity = cfg.verbosity ?? \"normal\";\n if (isCompactVerbosity(verbosity)) {\n // Quiet: ID and status only — no verbose details\n return {\n content: [\n {\n type: \"text\",\n text: `Proposal ${proposal.id}: pending.`,\n },\n ],\n details: { proposalId: proposal.id, status: \"pending\", expiresAt: proposal.expiresAt },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Proposal created: ${proposal.id}\\nTitle: ${title}\\nTarget: ${targetFile}\\nStatus: pending\\n\\nAwaiting human review. Use persona_proposals_list to view all pending proposals.`,\n },\n ],\n details: { proposalId: proposal.id, status: \"pending\", expiresAt: proposal.expiresAt },\n };\n },\n },\n { name: \"persona_propose\" },\n );\n\n api.registerTool(\n {\n name: \"persona_proposals_list\",\n label: \"List Persona Proposals\",\n description:\n \"List all persona proposals, optionally filtered by status (pending/approved/rejected/applied) or target file.\",\n parameters: Type.Object({\n status: Type.Optional(stringEnum(PROPOSAL_STATUSES)),\n targetFile: Type.Optional(Type.String()),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n const { status, targetFile } = params as { status?: string; targetFile?: string };\n const verbosity = cfg.verbosity ?? \"normal\";\n\n let proposals = proposalsDb?.list({ status, targetFile });\n\n // Quiet mode: suppress freshly-created pending proposals (< 24h old) to reduce noise,\n // but keep all non-pending proposals (approved/rejected/applied/wont-fix) visible.\n // Only apply quiet filter when no explicit status was provided by the user\n if (isCompactVerbosity(verbosity) && !status) {\n const oneDayAgo = Math.floor(Date.now() / 1000) - SECONDS_PER_DAY;\n proposals = proposals.filter((p) => p.status !== \"pending\" || p.createdAt < oneDayAgo);\n }\n\n if (proposals.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: isCompactVerbosity(verbosity)\n ? \"No pending proposals awaiting review.\"\n : \"No proposals found matching filters.\",\n },\n ],\n details: { count: 0, filters: { status, targetFile } },\n };\n }\n\n const lines = proposals.map((p) => {\n const age = Math.floor((Date.now() / 1000 - p.createdAt) / SECONDS_PER_DAY);\n const expires = p.expiresAt ? Math.floor((p.expiresAt - Date.now() / 1000) / SECONDS_PER_DAY) : null;\n if (isCompactVerbosity(verbosity)) {\n // Compact: one line per proposal with just the actionable info\n const expireStr = expires !== null ? ` (expires ${expires}d)` : \"\";\n return `[${p.status.toUpperCase()}] ${p.id} — ${p.title}${expireStr}`;\n }\n return `[${p.status.toUpperCase()}] ${p.id}\\n Title: ${p.title}\\n Target: ${p.targetFile}\\n Confidence: ${p.confidence}\\n Evidence: ${p.evidenceSessions.length} sessions\\n Age: ${age}d${expires !== null ? `, expires in ${expires}d` : \"\"}\\n Observation: ${p.observation.length > 120 ? `${p.observation.slice(0, 120)}...` : p.observation}`;\n });\n\n const pendingCount = proposals.filter((p) => p.status === \"pending\").length;\n const summaryText = isCompactVerbosity(verbosity)\n ? pendingCount > 0\n ? `${proposals.length} proposal(s) (${pendingCount} awaiting review):\\n${lines.join(\"\\n\")}`\n : `${proposals.length} proposal(s):\\n${lines.join(\"\\n\")}`\n : `Found ${proposals.length} proposal(s):\\n\\n${lines.join(\"\\n\\n\")}`;\n\n return {\n content: [\n {\n type: \"text\",\n text: summaryText,\n },\n ],\n details: {\n count: proposals.length,\n proposals: proposals.map((p) => ({ id: p.id, status: p.status, title: p.title, targetFile: p.targetFile })),\n },\n };\n },\n },\n { name: \"persona_proposals_list\" },\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,qBAAqB,KAAoB,KAAwB;CAC/E,MAAM,EAAE,aAAa,KAAK,uBAAuB;CAGjD,IAAI,CAAC,IAAI,iBAAiB,WAAW,CAAC,aACpC;CAIF,MAAM,gBAAgB,OACpB,QACA,YACA,SACA,WACG;EACH,MAAM,WAAW,KAAK,QAAQ,mBAAmB,EAAE,YAAY;EAC/D,MAAM,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;EAE1C,MAAM,QAAQ;GACZ,4BAFgB,IAAI,MAAM,EAAC,aAElB;GACT;GACA;GACA,GAAG;GACJ;EACD,MAAM,YAAY,KAAK,UAAU,YAAY,WAAW,QAAQ;EAChE,IAAI;GACF,MAAM,UAAU,WAAW,GAAG,KAAK,UAAU,MAAM,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC;WAChE,KAAK;GACZ,MAAM,MAAM,2BAA2B;GACvC,mBAAmB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,EAAE;IACtE,WAAW;IACX,WAAW;IACX;IACD,CAAC;GACF,IAAI,QAAQ,MACV,OAAO,KAAK,kBAAkB,MAAM;QAC/B,IAAI,QAAQ,OACjB,OAAO,MAAM,IAAI;;;CAMvB,MAAM,uBAA2E;EAE/E,MAAM,QAAQ,aAAa,qBAAqB,EAAW;EAC3D,MAAM,QAAQ,IAAI,iBAAiB;EACnC,OAAO;GAAE,SAAS,QAAQ;GAAO;GAAO;GAAO;;CAGjD,IAAI,aACF;EACE,MAAM;EACN,OAAO;EACP,aACE;EACF,YAAY,KAAK,OAAO;GACtB,YAAY,WAAW,IAAI,iBAAiB,aAAa;GACzD,OAAO,KAAK,OAAO,EACjB,aAAa,qEACd,CAAC;GACF,aAAa,KAAK,OAAO,EACvB,aACE,gHACH,CAAC;GACF,iBAAiB,KAAK,OAAO,EAC3B,aAAa,mFACd,CAAC;GACF,YAAY,KAAK,OAAO;IACtB,aAAa;IACb,SAAS;IACT,SAAS;IACV,CAAC;GACF,kBAAkB,KAAK,MAAM,KAAK,QAAQ,EAAE,EAC1C,aAAa,gEACd,CAAC;GACH,CAAC;EACF,MAAM,QAAQ,aAAqB,QAAiC;GAClE,MAAM,EAAE,YAAY,OAAO,aAAa,iBAAiB,YAAY,qBAAqB;GAU1F,MAAM,mBAAmB;GACzB,MAAM,yBAAyB;GAC/B,MAAM,8BAA8B;GAEpC,IAAI,MAAM,SAAS,kBACjB,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,mBAAmB,MAAM,OAAO,eAAe,iBAAiB;KACvE,CACF;IACD,SAAS;KAAE,OAAO;KAAkB,QAAQ,MAAM;KAAQ,KAAK;KAAkB;IAClF;GAGH,IAAI,YAAY,SAAS,wBACvB,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,yBAAyB,YAAY,OAAO,eAAe,uBAAuB;KACzF,CACF;IACD,SAAS;KAAE,OAAO;KAAwB,QAAQ,YAAY;KAAQ,KAAK;KAAwB;IACpG;GAGH,IAAI,gBAAgB,SAAS,6BAC3B,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,8BAA8B,gBAAgB,OAAO,eAAe,4BAA4B;KACvG,CACF;IACD,SAAS;KACP,OAAO;KACP,QAAQ,gBAAgB;KACxB,KAAK;KACN;IACF;GAIH,MAAM,YAAY,gBAAgB;GAClC,IAAI,CAAC,UAAU,SACb,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,wBAAwB,UAAU,MAAM,GAAG,UAAU,MAAM;KAClE,CACF;IACD,SAAS;KAAE,OAAO;KAAuB,GAAG;KAAW;IACxD;GAIH,IAAI,aAAa,IAAI,iBAAiB,eACpC,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,cAAc,WAAW,oBAAoB,IAAI,iBAAiB,cAAc;KACvF,CACF;IACD,SAAS;KAAE,OAAO;KAAsB;KAAY,aAAa,IAAI,iBAAiB;KAAe;IACtG;GAIH,IAAI,iBAAiB,SAAS,IAAI,iBAAiB,oBACjD,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,iBAAiB,IAAI,iBAAiB,mBAAmB,+BAA+B,iBAAiB,OAAO;KACvH,CACF;IACD,SAAS;KACP,OAAO;KACP,UAAU,iBAAiB;KAC3B,aAAa,IAAI,iBAAiB;KACnC;IACF;GAIH,MAAM,kBAAkB,iBAAiB,QAAQ,MAAM,OAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE;GACtG,IAAI,gBAAgB,SAAS,GAC3B,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,sDAAsD,gBAAgB,OAAO;KACpF,CACF;IACD,SAAS;KAAE,OAAO;KAA6B,cAAc,gBAAgB;KAAQ;IACtF;GAIH,MAAM,iBAAiB,IAAI,IAAI,iBAAiB;GAChD,IAAI,eAAe,SAAS,iBAAiB,QAC3C,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,2CAA2C,iBAAiB,SAAS,eAAe,KAAK;KAChG,CACF;IACD,SAAS;KACP,OAAO;KACP,gBAAgB,iBAAiB,SAAS,eAAe;KAC1D;IACF;GAIH,MAAM,YACJ,IAAI,iBAAiB,kBAAkB,IACnC,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG,IAAI,iBAAiB,kBAAkB,KAAK,OAC5E;GAGN,MAAM,WAAW,gBAAgB,IAAI,YAAY,WAAW,CAAC;GAC7D,MAAM,WAAW,aAAa,OAAO;IACnC;IACA;IACA;IACA;IACA;IACA;IACA;IACA,eAAe,UAAU,WAAW;IACpC,YAAY,UAAU,QAAQ;IAC/B,CAAC;GAEF,MAAM,cACJ,WACA,SAAS,IACT;IACE;IACA;IACA;IACA,eAAe,iBAAiB;IACjC,EACD,IAAI,OACL;GAED,IAAI,OAAO,KAAK,6CAA6C,SAAS,GAAG,IAAI,MAAM,GAAG;GAEtF,IAAI,IAAI,iBAAiB,WAAW;IAClC,aAAa,aAAa,SAAS,IAAI,YAAY,OAAO;IAC1D,MAAM,cACJ,YACA,SAAS,IACT;KACE,YAAY;KACZ,gBAAgB;KAChB,WAAW;KACX,QAAQ;KACT,EACD,IAAI,OACL;IAOD,MAAM,cAAc,MAAM,sBAAsB;KALjC;KACb;KACA;KACA,KAAK,EAAE,QAAQ,IAAI,QAAQ;KAE2B,EAAE,SAAS,GAAG;IACtE,MAAM,iBAAiB,IAAI,aAAa;IACxC,IAAI,YAAY,IAAI;KAClB,IAAI,OAAO,KACT,kDAAkD,SAAS,GAAG,KAAK,YAAY,aAChF;KACD,IAAI,mBAAmB,eAAe,EAEpC,OAAO;MACL,SAAS,CACP;OACE,MAAM;OACN,MAAM,YAAY,SAAS,GAAG,KAAK,YAAY,WAAW;OAC3D,CACF;MACD,SAAS;OACP,YAAY,SAAS;OACrB,QAAQ;OACR,YAAY,YAAY;OACxB,YAAY,YAAY;OACzB;MACF;KAEH,MAAM,gBACJ,YAAY,gBAAgB,SAAS,MACjC,GAAG,YAAY,gBAAgB,MAAM,GAAG,IAAI,CAAC,KAC7C,YAAY;KAClB,OAAO;MACL,SAAS,CACP;OACE,MAAM;OACN,MAAM,YAAY,SAAS,GAAG,wCAAwC,YAAY,WAAW,YAAY,MAAM,YAAY,YAAY,WAAW,gDAAgD;OACnM,CACF;MACD,SAAS;OACP,YAAY,SAAS;OACrB,QAAQ;OACR,YAAY,YAAY;OACxB,YAAY,YAAY;OACzB;MACF;;IAEH,OAAO;KACL,SAAS,CACP;MACE,MAAM;MACN,MAAM,mBAAmB,eAAe,GACpC,YAAY,SAAS,GAAG,mBAAmB,YAAY,UACvD,YAAY,SAAS,GAAG,+DAA+D,YAAY,MAAM,6CAA6C,SAAS,GAAG;MACvK,CACF;KACD,SAAS;MAAE,YAAY,SAAS;MAAI,QAAQ;MAAY,YAAY,YAAY;MAAO;KACxF;;GAIH,IAAI,mBADc,IAAI,aAAa,SACF,EAE/B,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,YAAY,SAAS,GAAG;KAC/B,CACF;IACD,SAAS;KAAE,YAAY,SAAS;KAAI,QAAQ;KAAW,WAAW,SAAS;KAAW;IACvF;GAEH,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,qBAAqB,SAAS,GAAG,WAAW,MAAM,YAAY,WAAW;KAChF,CACF;IACD,SAAS;KAAE,YAAY,SAAS;KAAI,QAAQ;KAAW,WAAW,SAAS;KAAW;IACvF;;EAEJ,EACD,EAAE,MAAM,mBAAmB,CAC5B;CAED,IAAI,aACF;EACE,MAAM;EACN,OAAO;EACP,aACE;EACF,YAAY,KAAK,OAAO;GACtB,QAAQ,KAAK,SAAS,WAAW,kBAAkB,CAAC;GACpD,YAAY,KAAK,SAAS,KAAK,QAAQ,CAAC;GACzC,CAAC;EACF,MAAM,QAAQ,aAAqB,QAAiC;GAClE,MAAM,EAAE,QAAQ,eAAe;GAC/B,MAAM,YAAY,IAAI,aAAa;GAEnC,IAAI,YAAY,aAAa,KAAK;IAAE;IAAQ;IAAY,CAAC;GAKzD,IAAI,mBAAmB,UAAU,IAAI,CAAC,QAAQ;IAC5C,MAAM,YAAY,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG;IAClD,YAAY,UAAU,QAAQ,MAAM,EAAE,WAAW,aAAa,EAAE,YAAY,UAAU;;GAGxF,IAAI,UAAU,WAAW,GACvB,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAAM,mBAAmB,UAAU,GAC/B,0CACA;KACL,CACF;IACD,SAAS;KAAE,OAAO;KAAG,SAAS;MAAE;MAAQ;MAAY;KAAE;IACvD;GAGH,MAAM,QAAQ,UAAU,KAAK,MAAM;IACjC,MAAM,MAAM,KAAK,OAAO,KAAK,KAAK,GAAG,MAAO,EAAE,aAAa,gBAAgB;IAC3E,MAAM,UAAU,EAAE,YAAY,KAAK,OAAO,EAAE,YAAY,KAAK,KAAK,GAAG,OAAQ,gBAAgB,GAAG;IAChG,IAAI,mBAAmB,UAAU,EAAE;KAEjC,MAAM,YAAY,YAAY,OAAO,aAAa,QAAQ,MAAM;KAChE,OAAO,IAAI,EAAE,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,QAAQ;;IAE5D,OAAO,IAAI,EAAE,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,aAAa,EAAE,MAAM,cAAc,EAAE,WAAW,kBAAkB,EAAE,WAAW,gBAAgB,EAAE,iBAAiB,OAAO,oBAAoB,IAAI,GAAG,YAAY,OAAO,gBAAgB,QAAQ,KAAK,GAAG,mBAAmB,EAAE,YAAY,SAAS,MAAM,GAAG,EAAE,YAAY,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE;KAC1U;GAEF,MAAM,eAAe,UAAU,QAAQ,MAAM,EAAE,WAAW,UAAU,CAAC;GAOrE,OAAO;IACL,SAAS,CACP;KACE,MAAM;KACN,MAVc,mBAAmB,UAAU,GAC7C,eAAe,IACb,GAAG,UAAU,OAAO,gBAAgB,aAAa,sBAAsB,MAAM,KAAK,KAAK,KACvF,GAAG,UAAU,OAAO,iBAAiB,MAAM,KAAK,KAAK,KACvD,SAAS,UAAU,OAAO,mBAAmB,MAAM,KAAK,OAAO;KAO9D,CACF;IACD,SAAS;KACP,OAAO,UAAU;KACjB,WAAW,UAAU,KAAK,OAAO;MAAE,IAAI,EAAE;MAAI,QAAQ,EAAE;MAAQ,OAAO,EAAE;MAAO,YAAY,EAAE;MAAY,EAAE;KAC5G;IACF;;EAEJ,EACD,EAAE,MAAM,0BAA0B,CACnC"}
|
|
1
|
+
{"version":3,"file":"persona-tools.js","names":[],"sources":["../../tools/persona-tools.ts"],"sourcesContent":["/**\n * Persona Proposals Tools\n * Tools for proposing and managing changes to identity files (SOUL.md, IDENTITY.md, USER.md)\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\nimport type { ProposalsDB } from \"../backends/proposals-db.js\";\nimport { applyApprovedProposal } from \"../cli/proposals.js\";\nimport { type HybridMemoryConfig, PROPOSAL_STATUSES, isCompactVerbosity } from \"../config.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport { SECONDS_PER_DAY } from \"../utils/constants.js\";\nimport { getFileSnapshot } from \"../utils/file-snapshot.js\";\nimport { stringEnum } from \"../utils/typebox.js\";\n\nexport interface PluginContext {\n proposalsDb?: ProposalsDB;\n cfg: HybridMemoryConfig;\n resolvedSqlitePath: string;\n}\n\n/**\n * Register persona proposal tools (persona_propose, persona_proposals_list)\n * Only registers if cfg.personaProposals.enabled && proposalsDb is available\n */\nexport function registerPersonaTools(ctx: PluginContext, api: ClawdbotPluginApi) {\n const { proposalsDb, cfg, resolvedSqlitePath } = ctx;\n\n // Only register if persona proposals are enabled and database is available\n if (!cfg.personaProposals.enabled || !proposalsDb) {\n return;\n }\n\n // Shared helper: audit trail logging (used by both tools and CLI commands)\n const auditProposal = async (\n action: string,\n proposalId: string,\n details?: any,\n logger?: { warn?: (msg: string) => void; error?: (msg: string) => void },\n ) => {\n const auditDir = join(dirname(resolvedSqlitePath), \"decisions\");\n await mkdir(auditDir, { recursive: true });\n const timestamp = new Date().toISOString();\n const entry = {\n timestamp,\n action,\n proposalId,\n ...details,\n };\n const auditPath = join(auditDir, `proposal-${proposalId}.jsonl`);\n try {\n await writeFile(auditPath, `${JSON.stringify(entry)}\\n`, { flag: \"a\" });\n } catch (err) {\n const msg = `Audit log write failed: ${err}`;\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"persona-proposal-audit\",\n subsystem: \"proposals\",\n proposalId,\n });\n if (logger?.warn) {\n logger.warn(`memory-hybrid: ${msg}`);\n } else if (logger?.error) {\n logger.error(msg);\n }\n }\n };\n\n // Helper: rate limiting check\n const checkRateLimit = (): { allowed: boolean; count: number; limit: number } => {\n const weekInDays = 7;\n const count = proposalsDb?.countRecentProposals(weekInDays);\n const limit = cfg.personaProposals.maxProposalsPerWeek;\n return { allowed: count < limit, count, limit };\n };\n\n api.registerTool(\n {\n name: \"persona_propose\",\n label: \"Propose Persona Change\",\n description:\n \"Propose a change to identity files (SOUL.md, IDENTITY.md, USER.md) based on observed patterns. By default requires human approval; if personaProposals.autoApply is enabled, proposals are applied automatically. Rate-limited to prevent spam.\",\n parameters: Type.Object({\n targetFile: stringEnum(cfg.personaProposals.allowedFiles),\n title: Type.String({\n description: \"Short title for the proposal (e.g., 'Add tone-matching guidance')\",\n }),\n observation: Type.String({\n description:\n \"What pattern or behavior you observed (e.g., 'Over ~50 interactions, user responds better to bullet points')\",\n }),\n suggestedChange: Type.String({\n description: \"The specific change to make to the file (be precise about location and wording)\",\n }),\n confidence: Type.Number({\n description: \"Confidence score 0-1 (must be >= minConfidence from config)\",\n minimum: 0,\n maximum: 1,\n }),\n evidenceSessions: Type.Array(Type.String(), {\n description: \"List of session IDs or references that support this proposal\",\n }),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n const { targetFile, title, observation, suggestedChange, confidence, evidenceSessions } = params as {\n targetFile: string;\n title: string;\n observation: string;\n suggestedChange: string;\n confidence: number;\n evidenceSessions: string[];\n };\n\n // Field length validation (prevent database bloat and file corruption)\n const MAX_TITLE_LENGTH = 200;\n const MAX_OBSERVATION_LENGTH = 5000;\n const MAX_SUGGESTED_CHANGE_LENGTH = 10000;\n\n if (title.length > MAX_TITLE_LENGTH) {\n return {\n content: [\n {\n type: \"text\",\n text: `Title too long: ${title.length} chars (max: ${MAX_TITLE_LENGTH})`,\n },\n ],\n details: { error: \"title_too_long\", length: title.length, max: MAX_TITLE_LENGTH },\n };\n }\n\n if (observation.length > MAX_OBSERVATION_LENGTH) {\n return {\n content: [\n {\n type: \"text\",\n text: `Observation too long: ${observation.length} chars (max: ${MAX_OBSERVATION_LENGTH})`,\n },\n ],\n details: { error: \"observation_too_long\", length: observation.length, max: MAX_OBSERVATION_LENGTH },\n };\n }\n\n if (suggestedChange.length > MAX_SUGGESTED_CHANGE_LENGTH) {\n return {\n content: [\n {\n type: \"text\",\n text: `Suggested change too long: ${suggestedChange.length} chars (max: ${MAX_SUGGESTED_CHANGE_LENGTH})`,\n },\n ],\n details: {\n error: \"suggested_change_too_long\",\n length: suggestedChange.length,\n max: MAX_SUGGESTED_CHANGE_LENGTH,\n },\n };\n }\n\n // Rate limiting\n const rateCheck = checkRateLimit();\n if (!rateCheck.allowed) {\n return {\n content: [\n {\n type: \"text\",\n text: `Rate limit exceeded: ${rateCheck.count}/${rateCheck.limit} proposals this week. Try again later.`,\n },\n ],\n details: { error: \"rate_limit_exceeded\", ...rateCheck },\n };\n }\n\n // Confidence check\n if (confidence < cfg.personaProposals.minConfidence) {\n return {\n content: [\n {\n type: \"text\",\n text: `Confidence ${confidence} is below minimum ${cfg.personaProposals.minConfidence}. Gather more evidence before proposing.`,\n },\n ],\n details: { error: \"confidence_too_low\", confidence, minRequired: cfg.personaProposals.minConfidence },\n };\n }\n\n // Evidence validation: check count and content quality\n if (evidenceSessions.length < cfg.personaProposals.minSessionEvidence) {\n return {\n content: [\n {\n type: \"text\",\n text: `Need at least ${cfg.personaProposals.minSessionEvidence} session evidence (provided: ${evidenceSessions.length})`,\n },\n ],\n details: {\n error: \"insufficient_evidence\",\n provided: evidenceSessions.length,\n minRequired: cfg.personaProposals.minSessionEvidence,\n },\n };\n }\n\n // Validate evidence session content (non-empty, unique)\n const invalidSessions = evidenceSessions.filter((s) => typeof s !== \"string\" || s.trim().length === 0);\n if (invalidSessions.length > 0) {\n return {\n content: [\n {\n type: \"text\",\n text: `Evidence sessions must be non-empty strings. Found ${invalidSessions.length} invalid entries.`,\n },\n ],\n details: { error: \"invalid_evidence_sessions\", invalidCount: invalidSessions.length },\n };\n }\n\n // Check for duplicate evidence sessions (without trimming to preserve exact matches)\n const uniqueSessions = new Set(evidenceSessions);\n if (uniqueSessions.size !== evidenceSessions.length) {\n return {\n content: [\n {\n type: \"text\",\n text: `Evidence sessions must be unique. Found ${evidenceSessions.length - uniqueSessions.size} duplicate(s).`,\n },\n ],\n details: {\n error: \"duplicate_evidence_sessions\",\n duplicateCount: evidenceSessions.length - uniqueSessions.size,\n },\n };\n }\n\n // Calculate expiry\n const expiresAt =\n cfg.personaProposals.proposalTTLDays > 0\n ? Math.floor(Date.now() / 1000) + cfg.personaProposals.proposalTTLDays * 24 * 3600\n : null;\n\n // Create proposal\n const snapshot = getFileSnapshot(api.resolvePath(targetFile));\n const proposal = proposalsDb?.create({\n targetFile,\n title,\n observation,\n suggestedChange,\n confidence,\n evidenceSessions,\n expiresAt,\n targetMtimeMs: snapshot?.mtimeMs ?? null,\n targetHash: snapshot?.hash ?? null,\n });\n\n await auditProposal(\n \"created\",\n proposal.id,\n {\n targetFile,\n title,\n confidence,\n evidenceCount: evidenceSessions.length,\n },\n api.logger,\n );\n\n api.logger.info(`memory-hybrid: persona proposal created — ${proposal.id} (${title})`);\n\n if (cfg.personaProposals.autoApply) {\n proposalsDb?.updateStatus(proposal.id, \"approved\", \"auto\");\n await auditProposal(\n \"approved\",\n proposal.id,\n {\n reviewedBy: \"auto\",\n previousStatus: \"pending\",\n newStatus: \"approved\",\n reason: \"autoApply\",\n },\n api.logger,\n );\n const applyCtx = {\n proposalsDb: proposalsDb!,\n cfg,\n resolvedSqlitePath,\n api: { logger: api.logger },\n };\n const applyResult = await applyApprovedProposal(applyCtx, proposal.id);\n const applyVerbosity = cfg.verbosity ?? \"normal\";\n if (applyResult.ok) {\n api.logger.info(\n `memory-hybrid: persona proposal auto-applied — ${proposal.id} → ${applyResult.targetFile}`,\n );\n if (isCompactVerbosity(applyVerbosity)) {\n // Quiet: only emit ID + file, suppress change preview\n return {\n content: [\n {\n type: \"text\",\n text: `Applied: ${proposal.id} → ${applyResult.targetFile}.`,\n },\n ],\n details: {\n proposalId: proposal.id,\n status: \"applied\",\n targetFile: applyResult.targetFile,\n backupPath: applyResult.backupPath,\n },\n };\n }\n const changePreview =\n applyResult.suggestedChange.length > 500\n ? `${applyResult.suggestedChange.slice(0, 500)}…`\n : applyResult.suggestedChange;\n return {\n content: [\n {\n type: \"text\",\n text: `Proposal ${proposal.id} created and automatically applied to ${applyResult.targetFile}.\\nTitle: ${title}\\nBackup: ${applyResult.backupPath}\\n\\nChange applied (truncated to 500 chars):\\n${changePreview}`,\n },\n ],\n details: {\n proposalId: proposal.id,\n status: \"applied\",\n targetFile: applyResult.targetFile,\n backupPath: applyResult.backupPath,\n },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: isCompactVerbosity(applyVerbosity)\n ? `Proposal ${proposal.id}: apply failed — ${applyResult.error}`\n : `Proposal ${proposal.id} was approved automatically but applying to the file failed: ${applyResult.error}\\n\\nYou can run \\`openclaw proposals apply ${proposal.id}\\` after fixing the issue.`,\n },\n ],\n details: { proposalId: proposal.id, status: \"approved\", applyError: applyResult.error },\n };\n }\n\n const verbosity = cfg.verbosity ?? \"normal\";\n if (isCompactVerbosity(verbosity)) {\n // Quiet: ID and status only — no verbose details\n return {\n content: [\n {\n type: \"text\",\n text: `Proposal ${proposal.id}: pending.`,\n },\n ],\n details: { proposalId: proposal.id, status: \"pending\", expiresAt: proposal.expiresAt },\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: `Proposal created: ${proposal.id}\\nTitle: ${title}\\nTarget: ${targetFile}\\nStatus: pending\\n\\nAwaiting human review. Use persona_proposals_list to view all pending proposals.`,\n },\n ],\n details: { proposalId: proposal.id, status: \"pending\", expiresAt: proposal.expiresAt },\n };\n },\n },\n { name: \"persona_propose\" },\n );\n\n api.registerTool(\n {\n name: \"persona_proposals_list\",\n label: \"List Persona Proposals\",\n description:\n \"List all persona proposals, optionally filtered by status (pending/approved/rejected/applied) or target file.\",\n parameters: Type.Object({\n status: Type.Optional(stringEnum(PROPOSAL_STATUSES)),\n targetFile: Type.Optional(Type.String()),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n const { status, targetFile } = params as { status?: string; targetFile?: string };\n const verbosity = cfg.verbosity ?? \"normal\";\n\n let proposals = proposalsDb?.list({ status, targetFile });\n\n // Quiet mode: suppress freshly-created pending proposals (< 24h old) to reduce noise,\n // but keep all non-pending proposals (approved/rejected/applied/wont-fix) visible.\n // Only apply quiet filter when no explicit status was provided by the user\n if (isCompactVerbosity(verbosity) && !status) {\n const oneDayAgo = Math.floor(Date.now() / 1000) - SECONDS_PER_DAY;\n proposals = proposals.filter((p) => p.status !== \"pending\" || p.createdAt < oneDayAgo);\n }\n\n if (proposals.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: isCompactVerbosity(verbosity)\n ? \"No pending proposals awaiting review.\"\n : \"No proposals found matching filters.\",\n },\n ],\n details: { count: 0, filters: { status, targetFile } },\n };\n }\n\n const lines = proposals.map((p) => {\n const age = Math.floor((Date.now() / 1000 - p.createdAt) / SECONDS_PER_DAY);\n const expires = p.expiresAt ? Math.floor((p.expiresAt - Date.now() / 1000) / SECONDS_PER_DAY) : null;\n if (isCompactVerbosity(verbosity)) {\n // Compact: one line per proposal with just the actionable info\n const expireStr = expires !== null ? ` (expires ${expires}d)` : \"\";\n return `[${p.status.toUpperCase()}] ${p.id} — ${p.title}${expireStr}`;\n }\n return `[${p.status.toUpperCase()}] ${p.id}\\n Title: ${p.title}\\n Target: ${p.targetFile}\\n Confidence: ${p.confidence}\\n Evidence: ${p.evidenceSessions.length} sessions\\n Age: ${age}d${expires !== null ? `, expires in ${expires}d` : \"\"}\\n Observation: ${p.observation.length > 120 ? `${p.observation.slice(0, 120)}...` : p.observation}`;\n });\n\n const pendingCount = proposals.filter((p) => p.status === \"pending\").length;\n const summaryText = isCompactVerbosity(verbosity)\n ? pendingCount > 0\n ? `${proposals.length} proposal(s) (${pendingCount} awaiting review):\\n${lines.join(\"\\n\")}`\n : `${proposals.length} proposal(s):\\n${lines.join(\"\\n\")}`\n : `Found ${proposals.length} proposal(s):\\n\\n${lines.join(\"\\n\\n\")}`;\n\n return {\n content: [\n {\n type: \"text\",\n text: summaryText,\n },\n ],\n details: {\n count: proposals.length,\n proposals: proposals.map((p) => ({ id: p.id, status: p.status, title: p.title, targetFile: p.targetFile })),\n },\n };\n },\n },\n { name: \"persona_proposals_list\" },\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provenance-tools.js","names":[],"sources":["../../tools/provenance-tools.ts"],"sourcesContent":["/**\n * Provenance Tool Registrations\n *\n * Tool definitions for provenance tracing.\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\n\nimport type { EventLog } from \"../backends/event-log.js\";\nimport type { FactsDB } from \"../backends/facts-db.js\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport { extractEventText } from \"../services/dream-cycle.js\";\nimport type { ProvenanceEdgeType, ProvenanceService, ProvenanceSourceType } from \"../services/provenance.js\";\n\ninterface PluginContext {\n factsDb: FactsDB;\n eventLog: EventLog | null;\n provenanceService: ProvenanceService;\n cfg: HybridMemoryConfig;\n}\n\ntype DerivedFromEntry = {\n event_id: string;\n event_text: string;\n timestamp?: string;\n source_type?: string;\n fact_chain?: ProvenanceChainOutput | null;\n};\n\ntype ProvenanceChainOutput = {\n fact: { id: string; text: string; confidence: number };\n source: {\n session_id?: string;\n timestamp?: string;\n turn: number | null;\n extraction_method?: string;\n extraction_confidence?: number;\n };\n derivedFrom: DerivedFromEntry[];\n consolidationChain: ProvenanceChainOutput[];\n};\n\nfunction buildDerivedFrom(\n edges: Array<{\n edgeType: ProvenanceEdgeType;\n sourceType: ProvenanceSourceType;\n sourceId: string;\n sourceText?: string;\n createdAt: string;\n }>,\n factsDb: FactsDB,\n eventLog: EventLog | null,\n provenanceService: ProvenanceService,\n visited: Set<string>,\n depth: number,\n maxDepth: number,\n): DerivedFromEntry[] {\n return edges\n .filter((e) => e.edgeType === \"DERIVED_FROM\")\n .map((edge) => {\n let eventText = edge.sourceText ?? \"\";\n let timestamp = edge.createdAt;\n if (edge.sourceType === \"event_log\" && eventLog) {\n const event = eventLog.getById(edge.sourceId);\n if (event) {\n const extracted = extractEventText(event);\n if (extracted) eventText = extracted;\n timestamp = event.timestamp ?? timestamp;\n }\n }\n\n let factChain: ProvenanceChainOutput | null = null;\n if (depth < maxDepth) {\n const sourceFact = factsDb.getById(edge.sourceId);\n if (sourceFact) {\n factChain = buildProvenanceChain(\n factsDb,\n eventLog,\n provenanceService,\n edge.sourceId,\n visited,\n edge.sourceText ?? sourceFact.text,\n depth + 1,\n maxDepth,\n );\n }\n }\n\n return {\n event_id: edge.sourceId,\n event_text: eventText,\n timestamp,\n source_type: edge.sourceType,\n fact_chain: factChain,\n };\n });\n}\n\nfunction buildProvenanceChain(\n factsDb: FactsDB,\n eventLog: EventLog | null,\n provenanceService: ProvenanceService,\n factId: string,\n visited: Set<string>,\n fallbackText?: string,\n depth = 0,\n maxDepth = 10,\n): ProvenanceChainOutput {\n if (depth >= maxDepth) {\n return {\n fact: { id: factId, text: fallbackText ?? \"\", confidence: 0 },\n source: { turn: null },\n derivedFrom: [],\n consolidationChain: [],\n };\n }\n if (visited.has(factId)) {\n return {\n fact: { id: factId, text: fallbackText ?? \"\", confidence: 0 },\n source: { turn: null },\n derivedFrom: [],\n consolidationChain: [],\n };\n }\n visited.add(factId);\n\n const chain = provenanceService.getProvenance(factId, factsDb.getRawDb());\n const factEntry = factsDb.getById(factId);\n const sourceTimestamp = factEntry ? new Date(factEntry.createdAt * 1000).toISOString() : undefined;\n\n const factText = chain.fact.text || fallbackText || \"\";\n\n const consolidationChain = chain.edges\n .filter((e) => e.edgeType === \"CONSOLIDATED_FROM\")\n .map((edge) =>\n buildProvenanceChain(\n factsDb,\n eventLog,\n provenanceService,\n edge.sourceId,\n visited,\n edge.sourceText ?? undefined,\n depth + 1,\n maxDepth,\n ),\n );\n\n return {\n fact: {\n id: chain.fact.id,\n text: factText,\n confidence: chain.fact.confidence ?? 0,\n },\n source: {\n session_id: chain.source.sessionId,\n timestamp: sourceTimestamp,\n turn: chain.source.turn ?? null,\n extraction_method: chain.source.extractionMethod,\n extraction_confidence: chain.source.extractionConfidence,\n },\n derivedFrom: buildDerivedFrom(chain.edges, factsDb, eventLog, provenanceService, visited, depth, maxDepth),\n consolidationChain,\n };\n}\n\n/**\n * Register provenance-related tools with the plugin API.\n */\nexport function registerProvenanceTools(ctx: PluginContext, api: ClawdbotPluginApi): void {\n const { factsDb, eventLog, provenanceService, cfg } = ctx;\n\n api.registerTool(\n {\n name: \"memory_provenance\",\n label: \"Memory Provenance\",\n description: \"Return the full provenance chain for a memory fact.\",\n parameters: Type.Object({\n factId: Type.String({ description: \"Fact id to trace\" }),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n if (!cfg.provenance.enabled) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Provenance tracing is disabled. Enable provenance.enabled to use memory_provenance.\",\n },\n ],\n details: { error: \"provenance_disabled\" },\n };\n }\n const { factId } = params as { factId: string };\n const fact = factsDb.getById(factId);\n if (!fact) {\n return {\n content: [{ type: \"text\", text: `Fact not found: ${factId}` }],\n details: { error: \"not_found\", id: factId },\n };\n }\n\n const chain = buildProvenanceChain(factsDb, eventLog, provenanceService, factId, new Set<string>());\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(chain, null, 2) }],\n details: { provenance: chain },\n };\n },\n },\n { name: \"memory_provenance\" },\n );\n}\n"],"mappings":";;;;;;;;AA2CA,SAAS,iBACP,OAOA,SACA,UACA,mBACA,SACA,OACA,UACoB;CACpB,OAAO,MACJ,QAAQ,MAAM,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"provenance-tools.js","names":[],"sources":["../../tools/provenance-tools.ts"],"sourcesContent":["/**\n * Provenance Tool Registrations\n *\n * Tool definitions for provenance tracing.\n */\n\nimport { Type } from \"@sinclair/typebox\";\nimport type { ClawdbotPluginApi } from \"openclaw/plugin-sdk/core\";\n\nimport type { EventLog } from \"../backends/event-log.js\";\nimport type { FactsDB } from \"../backends/facts-db.js\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport { extractEventText } from \"../services/dream-cycle.js\";\nimport type { ProvenanceEdgeType, ProvenanceService, ProvenanceSourceType } from \"../services/provenance.js\";\n\ninterface PluginContext {\n factsDb: FactsDB;\n eventLog: EventLog | null;\n provenanceService: ProvenanceService;\n cfg: HybridMemoryConfig;\n}\n\ntype DerivedFromEntry = {\n event_id: string;\n event_text: string;\n timestamp?: string;\n source_type?: string;\n fact_chain?: ProvenanceChainOutput | null;\n};\n\ntype ProvenanceChainOutput = {\n fact: { id: string; text: string; confidence: number };\n source: {\n session_id?: string;\n timestamp?: string;\n turn: number | null;\n extraction_method?: string;\n extraction_confidence?: number;\n };\n derivedFrom: DerivedFromEntry[];\n consolidationChain: ProvenanceChainOutput[];\n};\n\nfunction buildDerivedFrom(\n edges: Array<{\n edgeType: ProvenanceEdgeType;\n sourceType: ProvenanceSourceType;\n sourceId: string;\n sourceText?: string;\n createdAt: string;\n }>,\n factsDb: FactsDB,\n eventLog: EventLog | null,\n provenanceService: ProvenanceService,\n visited: Set<string>,\n depth: number,\n maxDepth: number,\n): DerivedFromEntry[] {\n return edges\n .filter((e) => e.edgeType === \"DERIVED_FROM\")\n .map((edge) => {\n let eventText = edge.sourceText ?? \"\";\n let timestamp = edge.createdAt;\n if (edge.sourceType === \"event_log\" && eventLog) {\n const event = eventLog.getById(edge.sourceId);\n if (event) {\n const extracted = extractEventText(event);\n if (extracted) eventText = extracted;\n timestamp = event.timestamp ?? timestamp;\n }\n }\n\n let factChain: ProvenanceChainOutput | null = null;\n if (depth < maxDepth) {\n const sourceFact = factsDb.getById(edge.sourceId);\n if (sourceFact) {\n factChain = buildProvenanceChain(\n factsDb,\n eventLog,\n provenanceService,\n edge.sourceId,\n visited,\n edge.sourceText ?? sourceFact.text,\n depth + 1,\n maxDepth,\n );\n }\n }\n\n return {\n event_id: edge.sourceId,\n event_text: eventText,\n timestamp,\n source_type: edge.sourceType,\n fact_chain: factChain,\n };\n });\n}\n\nfunction buildProvenanceChain(\n factsDb: FactsDB,\n eventLog: EventLog | null,\n provenanceService: ProvenanceService,\n factId: string,\n visited: Set<string>,\n fallbackText?: string,\n depth = 0,\n maxDepth = 10,\n): ProvenanceChainOutput {\n if (depth >= maxDepth) {\n return {\n fact: { id: factId, text: fallbackText ?? \"\", confidence: 0 },\n source: { turn: null },\n derivedFrom: [],\n consolidationChain: [],\n };\n }\n if (visited.has(factId)) {\n return {\n fact: { id: factId, text: fallbackText ?? \"\", confidence: 0 },\n source: { turn: null },\n derivedFrom: [],\n consolidationChain: [],\n };\n }\n visited.add(factId);\n\n const chain = provenanceService.getProvenance(factId, factsDb.getRawDb());\n const factEntry = factsDb.getById(factId);\n const sourceTimestamp = factEntry ? new Date(factEntry.createdAt * 1000).toISOString() : undefined;\n\n const factText = chain.fact.text || fallbackText || \"\";\n\n const consolidationChain = chain.edges\n .filter((e) => e.edgeType === \"CONSOLIDATED_FROM\")\n .map((edge) =>\n buildProvenanceChain(\n factsDb,\n eventLog,\n provenanceService,\n edge.sourceId,\n visited,\n edge.sourceText ?? undefined,\n depth + 1,\n maxDepth,\n ),\n );\n\n return {\n fact: {\n id: chain.fact.id,\n text: factText,\n confidence: chain.fact.confidence ?? 0,\n },\n source: {\n session_id: chain.source.sessionId,\n timestamp: sourceTimestamp,\n turn: chain.source.turn ?? null,\n extraction_method: chain.source.extractionMethod,\n extraction_confidence: chain.source.extractionConfidence,\n },\n derivedFrom: buildDerivedFrom(chain.edges, factsDb, eventLog, provenanceService, visited, depth, maxDepth),\n consolidationChain,\n };\n}\n\n/**\n * Register provenance-related tools with the plugin API.\n */\nexport function registerProvenanceTools(ctx: PluginContext, api: ClawdbotPluginApi): void {\n const { factsDb, eventLog, provenanceService, cfg } = ctx;\n\n api.registerTool(\n {\n name: \"memory_provenance\",\n label: \"Memory Provenance\",\n description: \"Return the full provenance chain for a memory fact.\",\n parameters: Type.Object({\n factId: Type.String({ description: \"Fact id to trace\" }),\n }),\n async execute(_toolCallId: string, params: Record<string, unknown>) {\n if (!cfg.provenance.enabled) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Provenance tracing is disabled. Enable provenance.enabled to use memory_provenance.\",\n },\n ],\n details: { error: \"provenance_disabled\" },\n };\n }\n const { factId } = params as { factId: string };\n const fact = factsDb.getById(factId);\n if (!fact) {\n return {\n content: [{ type: \"text\", text: `Fact not found: ${factId}` }],\n details: { error: \"not_found\", id: factId },\n };\n }\n\n const chain = buildProvenanceChain(factsDb, eventLog, provenanceService, factId, new Set<string>());\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(chain, null, 2) }],\n details: { provenance: chain },\n };\n },\n },\n { name: \"memory_provenance\" },\n );\n}\n"],"mappings":"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"}
|