@modusensus/dsh-mneme 0.13.0 → 0.14.0-beta.2
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/LICENSE +21 -21
- package/README.md +830 -828
- package/assets/icon.svg +3 -3
- package/bin/cli.mjs +964 -964
- package/bin/dsh-mneme-choro.mjs +262 -254
- package/bin/dsh-mneme-mcp.mjs +510 -510
- package/bin/dsh-mneme-serve.mjs +151 -151
- package/cordis.patch.yml +21 -21
- package/docs/CONFIGURATION.md +407 -402
- package/docs/CONTINUITY.md +139 -139
- package/docs/DAEMON.md +57 -57
- package/docs/DIRECTORIES.md +114 -114
- package/docs/DISTILL.md +397 -371
- package/docs/DSH-GO.md +97 -97
- package/docs/ENTITIES.md +247 -247
- package/docs/FORGET.md +77 -77
- package/docs/KB.md +110 -110
- package/docs/LOCAL_MODEL.md +222 -222
- package/docs/SEMANTIC.md +256 -256
- package/docs/SHARE.md +552 -552
- package/docs/SLEEP.md +202 -202
- package/docs/STORAGE.md +122 -122
- package/docs/WORKFLOWS.md +366 -366
- package/lib/api-standalone.js +1007 -1007
- package/lib/api.js +3600 -3394
- package/lib/attachment-text.js +122 -122
- package/lib/bootstrap-http.js +105 -105
- package/lib/bootstrap.js +215 -215
- package/lib/candidates.js +454 -454
- package/lib/capabilities.js +819 -819
- package/lib/choro-command.js +111 -111
- package/lib/client.js +14420 -13436
- package/lib/commands.js +95 -95
- package/lib/config-keys.js +144 -144
- package/lib/config.js +1361 -1317
- package/lib/content-hash.js +54 -54
- package/lib/continuity.js +258 -258
- package/lib/date-hint.js +32 -0
- package/lib/diary/auto.js +190 -190
- package/lib/diary/compose.js +440 -440
- package/lib/diary/dir.js +59 -59
- package/lib/diary/export.js +97 -97
- package/lib/diary/index.js +26 -26
- package/lib/diary/library.js +189 -189
- package/lib/diary/qq-inbox.js +142 -142
- package/lib/diary/rollover.js +61 -61
- package/lib/diary/session-provider.js +122 -122
- package/lib/document-index.js +94 -94
- package/lib/document.js +322 -322
- package/lib/dream/clustering.js +123 -123
- package/lib/dream/decisions.js +945 -907
- package/lib/dream/narratives.js +44 -44
- package/lib/dream/sleep.js +2027 -1887
- package/lib/dream/triage.js +139 -0
- package/lib/dream.js +1879 -1764
- package/lib/dsh-go/host.js +162 -162
- package/lib/dsh-go/panel.js +2091 -2091
- package/lib/dsh-go/text.js +342 -342
- package/lib/dsh-go/views/common.js +68 -68
- package/lib/dsh-go/views/entity.js +48 -48
- package/lib/dsh-go/views/memory.js +198 -198
- package/lib/dsh-go/views/root.js +30 -30
- package/lib/dsh-go/views/settings.js +398 -398
- package/lib/dsh-go/views/status.js +51 -51
- package/lib/embedding.js +342 -342
- package/lib/entities/extractor.js +285 -285
- package/lib/fence.js +24 -24
- package/lib/graph/anchoring.js +184 -184
- package/lib/guide.js +74 -74
- package/lib/heat.js +144 -144
- package/lib/hot-memory.js +119 -107
- package/lib/image-describe.js +158 -0
- package/lib/index.js +852 -822
- package/lib/inject.js +656 -639
- package/lib/kb/index.js +309 -309
- package/lib/kb/routes.js +219 -219
- package/lib/kb/tools.js +148 -148
- package/lib/lang.js +607 -584
- package/lib/local-embedder.js +358 -358
- package/lib/maintenance.js +162 -162
- package/lib/memory-source.js +9 -9
- package/lib/mirror.js +330 -330
- package/lib/organize.js +456 -456
- package/lib/peak-hours.js +172 -172
- package/lib/pipeline-activities.js +178 -178
- package/lib/pipeline-attribution.js +165 -165
- package/lib/pipeline-command.js +279 -279
- package/lib/pipeline-confirm.js +142 -142
- package/lib/pipeline-exec.js +174 -174
- package/lib/pipeline-nudge-auto.js +129 -129
- package/lib/pipeline-nudge.js +1623 -1623
- package/lib/pipeline-observations.js +181 -181
- package/lib/pipeline-observe.js +133 -133
- package/lib/pipeline-runner.js +361 -361
- package/lib/pipeline-runs.js +442 -442
- package/lib/pipeline.js +716 -716
- package/lib/placement.js +13 -13
- package/lib/pre-inject-gate.js +354 -354
- package/lib/profile-extract.js +164 -164
- package/lib/profile-facts.js +356 -356
- package/lib/provenance-http.js +251 -251
- package/lib/quality-filter.js +162 -162
- package/lib/recall-stats.js +190 -190
- package/lib/reclaim-http.js +150 -150
- package/lib/reranker.js +269 -269
- package/lib/runtime/adopt.js +176 -176
- package/lib/runtime/closure.js +172 -172
- package/lib/runtime/download.js +247 -247
- package/lib/runtime/layout.js +265 -265
- package/lib/runtime/loader.js +252 -252
- package/lib/runtime/model-fetch.js +361 -361
- package/lib/runtime/provision.js +237 -237
- package/lib/runtime/tarball.js +130 -130
- package/lib/runtime/verify.js +223 -223
- package/lib/safe-slice.js +18 -18
- package/lib/scope-state.js +277 -277
- package/lib/scope.js +187 -187
- package/lib/search/adaptive.js +60 -60
- package/lib/search/bm25.js +96 -96
- package/lib/semantic.js +572 -572
- package/lib/sensitive-scan.js +209 -209
- package/lib/serve.js +228 -228
- package/lib/service.js +3268 -3196
- package/lib/session-gate.js +91 -91
- package/lib/session-usage.js +350 -350
- package/lib/settings.js +827 -802
- package/lib/share-http.js +281 -281
- package/lib/share-import.js +234 -234
- package/lib/share.js +335 -335
- package/lib/store.js +5895 -5662
- package/lib/summarize.js +1388 -1343
- package/lib/tools.js +1370 -1356
- package/lib/user-settings.js +230 -230
- package/lib/vector-index.js +180 -180
- package/lib/version-check.js +122 -122
- package/lib/wiki/claims.js +267 -0
- package/lib/wiki/cli-hint.js +90 -90
- package/lib/wiki/inject.js +164 -164
- package/lib/wiki/partition.js +200 -200
- package/lib/wiki/plan.js +214 -214
- package/lib/wiki/queries.js +640 -474
- package/lib/wiki/render.js +261 -187
- package/lib/wiki/scan.js +371 -371
- package/lib/wiki/t0.js +500 -463
- package/lib/wiki/t1-jobs.js +232 -232
- package/lib/wiki/t1.js +609 -502
- package/lib/write-admission.js +404 -404
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +15 -1
- package/runtime-manifest.json +526 -526
- package/scripts/benchmark-embed.js +201 -201
- package/scripts/benchmark-recall.js +249 -249
- package/scripts/benchmark-rerank.js +166 -166
- package/scripts/build-runtime-manifest.mjs +224 -224
- package/scripts/changelog-prep.mjs +91 -91
- package/scripts/check-sync.js +44 -44
- package/scripts/e2e-dsh.js +220 -220
- package/scripts/mneme-runtime.mjs +277 -277
- package/scripts/publish-gate.mjs +197 -197
- package/scripts/release-docs.mjs +210 -204
- package/scripts/release-notes.mjs +164 -161
- package/scripts/stress-dsh.js +255 -255
- package/scripts/sync-lib.js +47 -47
- package/scripts/sync-test-badge.mjs +69 -69
- package/scripts/test-count-sync.mjs +48 -48
- package/src/api-standalone.js +1007 -1007
- package/src/api.js +3600 -3394
- package/src/attachment-text.js +122 -122
- package/src/bootstrap-http.js +105 -105
- package/src/bootstrap.js +215 -215
- package/src/candidates.js +454 -454
- package/src/capabilities.js +819 -819
- package/src/choro-command.js +111 -111
- package/src/commands.js +95 -95
- package/src/config-keys.js +144 -144
- package/src/config.js +1361 -1317
- package/src/content-hash.js +54 -54
- package/src/continuity.js +258 -258
- package/src/date-hint.js +32 -0
- package/src/diary/auto.js +190 -190
- package/src/diary/compose.js +440 -440
- package/src/diary/dir.js +59 -59
- package/src/diary/export.js +97 -97
- package/src/diary/index.js +26 -26
- package/src/diary/library.js +189 -189
- package/src/diary/qq-inbox.js +142 -142
- package/src/diary/rollover.js +61 -61
- package/src/diary/session-provider.js +122 -122
- package/src/document-index.js +94 -94
- package/src/document.js +322 -322
- package/src/dream/clustering.js +123 -123
- package/src/dream/decisions.js +945 -907
- package/src/dream/narratives.js +44 -44
- package/src/dream/sleep.js +2027 -1887
- package/src/dream/triage.js +139 -0
- package/src/dream.js +1879 -1764
- package/src/dsh-go/host.js +162 -162
- package/src/dsh-go/panel.js +2091 -2091
- package/src/dsh-go/text.js +342 -342
- package/src/dsh-go/views/common.js +68 -68
- package/src/dsh-go/views/entity.js +48 -48
- package/src/dsh-go/views/memory.js +198 -198
- package/src/dsh-go/views/root.js +30 -30
- package/src/dsh-go/views/settings.js +398 -398
- package/src/dsh-go/views/status.js +51 -51
- package/src/embedding.js +342 -342
- package/src/entities/extractor.js +285 -285
- package/src/fence.js +24 -24
- package/src/graph/anchoring.js +184 -184
- package/src/guide.js +74 -74
- package/src/heat.js +144 -144
- package/src/hot-memory.js +119 -107
- package/src/image-describe.js +158 -0
- package/src/index.js +852 -822
- package/src/inject.js +656 -639
- package/src/kb/index.js +309 -309
- package/src/kb/routes.js +219 -219
- package/src/kb/tools.js +148 -148
- package/src/lang.js +607 -584
- package/src/local-embedder.js +358 -358
- package/src/maintenance.js +162 -162
- package/src/memory-source.js +9 -9
- package/src/mirror.js +330 -330
- package/src/organize.js +456 -456
- package/src/peak-hours.js +172 -172
- package/src/pipeline-activities.js +178 -178
- package/src/pipeline-attribution.js +165 -165
- package/src/pipeline-command.js +279 -279
- package/src/pipeline-confirm.js +142 -142
- package/src/pipeline-exec.js +174 -174
- package/src/pipeline-nudge-auto.js +129 -129
- package/src/pipeline-nudge.js +1623 -1623
- package/src/pipeline-observations.js +181 -181
- package/src/pipeline-observe.js +133 -133
- package/src/pipeline-runner.js +361 -361
- package/src/pipeline-runs.js +442 -442
- package/src/pipeline.js +716 -716
- package/src/placement.js +13 -13
- package/src/pre-inject-gate.js +354 -354
- package/src/profile-extract.js +164 -164
- package/src/profile-facts.js +356 -356
- package/src/provenance-http.js +251 -251
- package/src/quality-filter.js +162 -162
- package/src/recall-stats.js +190 -190
- package/src/reclaim-http.js +150 -150
- package/src/reranker.js +269 -269
- package/src/runtime/adopt.js +176 -176
- package/src/runtime/closure.js +172 -172
- package/src/runtime/download.js +247 -247
- package/src/runtime/layout.js +265 -265
- package/src/runtime/loader.js +252 -252
- package/src/runtime/model-fetch.js +361 -361
- package/src/runtime/provision.js +237 -237
- package/src/runtime/tarball.js +130 -130
- package/src/runtime/verify.js +223 -223
- package/src/safe-slice.js +18 -18
- package/src/scope-state.js +277 -277
- package/src/scope.js +187 -187
- package/src/search/adaptive.js +60 -60
- package/src/search/bm25.js +96 -96
- package/src/semantic.js +572 -572
- package/src/sensitive-scan.js +209 -209
- package/src/serve.js +228 -228
- package/src/service.js +3268 -3196
- package/src/session-gate.js +91 -91
- package/src/session-usage.js +350 -350
- package/src/settings.js +827 -802
- package/src/share-http.js +281 -281
- package/src/share-import.js +234 -234
- package/src/share.js +335 -335
- package/src/store.js +5895 -5662
- package/src/summarize.js +1388 -1343
- package/src/tools.js +1370 -1356
- package/src/user-settings.js +230 -230
- package/src/vector-index.js +180 -180
- package/src/version-check.js +122 -122
- package/src/wiki/claims.js +267 -0
- package/src/wiki/cli-hint.js +90 -90
- package/src/wiki/inject.js +164 -164
- package/src/wiki/partition.js +200 -200
- package/src/wiki/plan.js +214 -214
- package/src/wiki/queries.js +640 -474
- package/src/wiki/render.js +261 -187
- package/src/wiki/scan.js +371 -371
- package/src/wiki/t0.js +500 -463
- package/src/wiki/t1-jobs.js +232 -232
- package/src/wiki/t1.js +609 -502
- package/src/write-admission.js +404 -404
- package/test/adaptive-inject-budget.test.js +85 -85
- package/test/api-hardening.test.js +173 -173
- package/test/api-nudge-route.test.js +259 -259
- package/test/api-routes-gaps.test.js +1092 -1092
- package/test/api.test.js +3007 -2988
- package/test/attachment-text.test.js +139 -139
- package/test/audit.test.js +448 -448
- package/test/baseline-persist.test.js +248 -248
- package/test/benchmark.test.js +94 -94
- package/test/bm25-corpus-cache.test.js +145 -145
- package/test/bootstrap.test.js +228 -228
- package/test/candidates.test.js +345 -345
- package/test/capabilities.test.js +577 -577
- package/test/capacity-warning.test.js +262 -262
- package/test/changelog-prep.test.js +125 -125
- package/test/choro-command.test.js +218 -218
- package/test/cli-enums.test.js +37 -37
- package/test/cli-flag-value.test.js +86 -86
- package/test/cli-receive.test.js +390 -390
- package/test/cli-share.test.js +437 -437
- package/test/client-share.test.js +225 -225
- package/test/client.test.js +4595 -4184
- package/test/clustering.test.js +100 -100
- package/test/commands.test.js +106 -106
- package/test/config-keys-routes.test.js +233 -233
- package/test/config.test.js +153 -153
- package/test/conflict-freeze.test.js +344 -344
- package/test/conflict-ledger-enforce.test.js +452 -0
- package/test/conflict-ledger.test.js +242 -0
- package/test/conflict-reviewed.test.js +79 -79
- package/test/content-hash.test.js +204 -204
- package/test/continuity.test.js +452 -452
- package/test/contrast.test.js +432 -320
- package/test/date-hint.test.js +156 -0
- package/test/dedupe-candidate-window.test.js +180 -180
- package/test/dependency-overrides.test.js +78 -78
- package/test/diary-library.test.js +187 -187
- package/test/diary.test.js +576 -576
- package/test/differentiate-feedback.test.js +248 -248
- package/test/distill-tx-embed-gap.test.js +110 -110
- package/test/docs-config-keys.test.js +65 -65
- package/test/document-dir.test.js +233 -233
- package/test/document.test.js +703 -703
- package/test/dream-archive-guardrail.test.js +116 -116
- package/test/dream-baseline-clamp.test.js +174 -0
- package/test/dream-candidate-hybrid.test.js +281 -281
- package/test/dream-coverage-degrade.test.js +86 -86
- package/test/dream-decision-evidence.test.js +314 -314
- package/test/dream-failure-backoff.test.js +173 -173
- package/test/dream-fence.test.js +207 -207
- package/test/dream-maxtokens-fallback.test.js +132 -132
- package/test/dream-merge-guardrail.test.js +219 -219
- package/test/dream-peak-hours.test.js +194 -194
- package/test/dream.test.js +1528 -1528
- package/test/dsh-go-host.test.js +134 -134
- package/test/dsh-go-panel-actions.test.js +854 -854
- package/test/dsh-go-panel.test.js +251 -251
- package/test/embed-ready-poll.test.js +94 -94
- package/test/embed-text-reasons.test.js +112 -112
- package/test/embedding-cache-f32.test.js +276 -276
- package/test/embedding-ready.test.js +226 -226
- package/test/entities.test.js +711 -711
- package/test/entity-recall.test.js +179 -179
- package/test/epistemic.test.js +325 -325
- package/test/failure-query.test.js +147 -147
- package/test/failure-retention.test.js +105 -105
- package/test/fnew-0112.test.js +311 -311
- package/test/fnew-03.test.js +422 -422
- package/test/forget-corrections.test.js +70 -70
- package/test/graph-anchoring.test.js +184 -184
- package/test/graph-api.test.js +333 -209
- package/test/graph-boosted-relations.test.js +189 -189
- package/test/graph-inject-budget.test.js +103 -103
- package/test/graph-multipath.test.js +269 -269
- package/test/graph-passive-confirm.test.js +91 -91
- package/test/graph-weight-evolution.test.js +104 -104
- package/test/heat.test.js +175 -175
- package/test/helpers/dream-mock.js +86 -86
- package/test/helpers/peer-worker.mjs +25 -25
- package/test/helpers/runtime-source.js +60 -60
- package/test/helpers/tar-builder.js +80 -80
- package/test/helpers/write-admission-samples.js +312 -312
- package/test/hot-memory.test.js +259 -211
- package/test/image-description.test.js +271 -0
- package/test/image-memory.test.js +170 -170
- package/test/inject-content-cap.test.js +91 -91
- package/test/inject-first-round-bm25.test.js +89 -89
- package/test/inject-heat.test.js +77 -77
- package/test/inject-parent-gate.test.js +134 -106
- package/test/inject-pin-explicit.test.js +300 -300
- package/test/inject-pin-vector-crowd.test.js +225 -225
- package/test/inject-pools.test.js +195 -195
- package/test/inject-recall.test.js +172 -172
- package/test/inject-rotation.test.js +161 -161
- package/test/inject.test.js +553 -494
- package/test/issue-617-step1-query-and-fusion.test.js +361 -361
- package/test/kb-api-wiring.test.js +128 -128
- package/test/kb-collections.test.js +272 -272
- package/test/kb-routes.test.js +379 -379
- package/test/lang.test.js +98 -98
- package/test/lastrunat-persist.test.js +101 -101
- package/test/lib-smoke.test.js +116 -116
- package/test/llm-audit.test.js +815 -815
- package/test/llm-message-source.test.js +207 -207
- package/test/local-embedder.test.js +292 -292
- package/test/maintenance.test.js +501 -501
- package/test/mcp-stdio.test.js +385 -385
- package/test/mint-source.test.js +311 -311
- package/test/mirror-dirty.test.js +424 -424
- package/test/mirror-edit-digest.test.js +187 -187
- package/test/mirror-generation.test.js +499 -499
- package/test/mirror-types.test.js +208 -208
- package/test/mirror.test.js +249 -249
- package/test/narrative-bars.test.js +162 -162
- package/test/organize-tool.test.js +232 -232
- package/test/organize.test.js +418 -418
- package/test/panel-chart-scale.test.js +90 -0
- package/test/panel-tokens.test.js +245 -0
- package/test/peak-hours-observability.test.js +70 -70
- package/test/peer-blockers.test.js +193 -193
- package/test/persona-addressing.test.js +83 -83
- package/test/persona-api.test.js +172 -172
- package/test/persona-by-session.test.js +568 -568
- package/test/persona-flag.test.js +36 -36
- package/test/persona-inject.test.js +145 -145
- package/test/persona-settings.test.js +198 -198
- package/test/pipeline-activities.test.js +155 -155
- package/test/pipeline-attribution.test.js +175 -175
- package/test/pipeline-command.test.js +243 -243
- package/test/pipeline-confirm.test.js +148 -148
- package/test/pipeline-exec.test.js +172 -172
- package/test/pipeline-nudge-auto.test.js +248 -248
- package/test/pipeline-nudge.test.js +1278 -1278
- package/test/pipeline-observations.test.js +157 -157
- package/test/pipeline-observe.test.js +127 -127
- package/test/pipeline-r1r2.test.js +278 -278
- package/test/pipeline-runner.test.js +468 -468
- package/test/pipeline-runs.test.js +767 -767
- package/test/pipeline.test.js +636 -636
- package/test/placement.test.js +36 -36
- package/test/policy-epoch.test.js +259 -259
- package/test/pre-inject-gate.test.js +444 -444
- package/test/profile-extract.test.js +269 -269
- package/test/profile-facts.test.js +492 -492
- package/test/prompt-stance.test.js +128 -128
- package/test/provenance-http.test.js +367 -367
- package/test/publish-gate.test.js +272 -272
- package/test/quality-backfill.test.js +290 -290
- package/test/quality-filter.test.js +295 -295
- package/test/readme-claims.test.js +113 -113
- package/test/reasoning-effort.test.js +752 -752
- package/test/recall-anti-update.test.js +82 -82
- package/test/recall-evals.test.js +253 -253
- package/test/recall-layer.test.js +326 -326
- package/test/recall-retention.test.js +128 -128
- package/test/recall-stats.test.js +274 -274
- package/test/receipt-chain.test.js +451 -451
- package/test/reclaim-http.test.js +209 -209
- package/test/reflection-update-gate.test.js +129 -129
- package/test/reflection.test.js +226 -226
- package/test/reindex-backfill.test.js +475 -475
- package/test/reindex-scheduler.test.js +369 -369
- package/test/release-docs.test.js +156 -136
- package/test/release-notes.test.js +265 -240
- package/test/release-workflow.test.js +93 -93
- package/test/reranker-single-logit.test.js +73 -73
- package/test/reranker.test.js +197 -197
- package/test/resident-status.test.js +83 -83
- package/test/route-policy.test.js +113 -113
- package/test/runtime-adopt.test.js +206 -206
- package/test/runtime-cli.test.js +89 -89
- package/test/runtime-closure.test.js +193 -193
- package/test/runtime-download.test.js +302 -302
- package/test/runtime-layout.test.js +163 -163
- package/test/runtime-loader.test.js +255 -255
- package/test/runtime-manifest.test.js +159 -159
- package/test/runtime-model-fetch.test.js +348 -348
- package/test/runtime-provision.test.js +101 -101
- package/test/runtime-tarball.test.js +81 -81
- package/test/runtime-verify.test.js +319 -319
- package/test/scope-candidates.test.js +491 -491
- package/test/scope-distill-stamp.test.js +134 -134
- package/test/scope-explicit.test.js +452 -452
- package/test/scope-inject-soft.test.js +106 -106
- package/test/scope-optional-service.test.js +110 -110
- package/test/scope-retrieval.test.js +197 -197
- package/test/scope-state.test.js +610 -610
- package/test/scope-storage.test.js +255 -255
- package/test/scope-strict.test.js +367 -367
- package/test/search-fusion.test.js +90 -90
- package/test/security-doc.test.js +188 -178
- package/test/semantic.test.js +124 -124
- package/test/sensitive-scan.test.js +251 -251
- package/test/serve-bin.test.js +121 -121
- package/test/serve.test.js +258 -258
- package/test/service-search.test.js +174 -174
- package/test/service.test.js +410 -410
- package/test/session-gate.test.js +264 -264
- package/test/session-usage.test.js +317 -317
- package/test/settings.test.js +273 -273
- package/test/share-foreign-rows.test.js +144 -144
- package/test/share-http.test.js +144 -144
- package/test/share-import.test.js +577 -577
- package/test/share-imported-guard.test.js +311 -311
- package/test/share-imported-identity.test.js +111 -111
- package/test/share-pack.test.js +511 -511
- package/test/share-receive-http.test.js +756 -756
- package/test/share-routes.test.js +337 -337
- package/test/share-store.test.js +133 -133
- package/test/share-validate.test.js +101 -101
- package/test/skip-invalid-restore.test.js +262 -262
- package/test/sleep-action-set.test.js +441 -441
- package/test/sleep-catchup.test.js +315 -315
- package/test/sleep-failure-backoff.test.js +156 -156
- package/test/sleep-heat.test.js +174 -174
- package/test/sleep-scheduler-rearm.test.js +89 -89
- package/test/sleep.test.js +1455 -1418
- package/test/standalone-api.test.js +1344 -1344
- package/test/store-vector-cache.test.js +98 -98
- package/test/store-write-path-columns.test.js +191 -191
- package/test/store.test.js +744 -744
- package/test/stress.test.js +209 -209
- package/test/summarize-occurred-at.test.js +127 -127
- package/test/summarize-parse-diagnostics.test.js +75 -75
- package/test/summarize-reasoning-effort.test.js +189 -189
- package/test/summarize.test.js +2251 -2251
- package/test/supersede-state-tracking.test.js +394 -394
- package/test/test-count-sync.test.js +71 -71
- package/test/tool-state-ignore.test.js +65 -65
- package/test/tools-dto-schema-matrix.test.js +398 -398
- package/test/tools-memory-get-schema.test.js +65 -65
- package/test/tools.test.js +585 -585
- package/test/updated-at-semantics.test.js +113 -113
- package/test/user-settings-preview.test.js +127 -127
- package/test/user-settings-segments.test.js +527 -527
- package/test/vector-index.test.js +334 -334
- package/test/version-check.test.js +152 -152
- package/test/webServer-optional.test.js +82 -82
- package/test/wiki-api.test.js +734 -627
- package/test/wiki-claims.test.js +194 -0
- package/test/wiki-cli-hint.test.js +118 -118
- package/test/wiki-inject.test.js +265 -265
- package/test/wiki-partition.test.js +112 -112
- package/test/wiki-plan.test.js +80 -80
- package/test/wiki-provenance.test.js +202 -0
- package/test/wiki-queries.test.js +398 -277
- package/test/wiki-scan.test.js +208 -208
- package/test/wiki-store.test.js +190 -190
- package/test/wiki-t0.test.js +456 -380
- package/test/wiki-t1-jobs.test.js +125 -125
- package/test/wiki-t1.test.js +460 -235
- package/test/wiki-tools.test.js +176 -176
- package/test/workflow-guards.test.js +155 -155
- package/test/write-admission.test.js +668 -668
package/docs/ENTITIES.md
CHANGED
|
@@ -1,247 +1,247 @@
|
|
|
1
|
-
# 实体结构化记忆(Entity Gene,v0.3.0)
|
|
2
|
-
|
|
3
|
-
> dsh-mneme 的**记忆基因**层:从记忆文本里抽取**命名实体**、**带时间轴的属性**、**实体间关系**,并支持按实体/属性精确召回记忆。与 autoDream 联动——update 记录 supersedes、merge 迁移属性归属。
|
|
4
|
-
|
|
5
|
-
v0.3.0 四个阶段全部落地:
|
|
6
|
-
|
|
7
|
-
| 阶段 | 内容 |
|
|
8
|
-
|------|------|
|
|
9
|
-
| P1 | 三表 Schema(entities / entity_attrs / entity_relations)+ 索引 + store CRUD |
|
|
10
|
-
| P2 | LLM 抽取器(JSON 抽取 + resolveEntity 去重 + saveAttr 时间轴 + saveRelation + fail-safe) |
|
|
11
|
-
| P3 | 前缀搜索(`entity:` / `attr:`),attr 精确 = 1.0 > keyword 提及 = 0.7 |
|
|
12
|
-
| P4 | autoDream 联动(applyUpdate 写 supersedes 自引用;applyMerge 迁移 loser attrs) |
|
|
13
|
-
|
|
14
|
-
存储层(建表 + CRUD)**始终可用**,不依赖任何 LLM;只有 `entityExtractionEnabled=true` 时流水线才会自动抽取。
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 一、三表结构
|
|
19
|
-
|
|
20
|
-
所有建表语句在 `src/store.js` 的 `SCHEMA` 中,`CREATE TABLE IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`,对旧库幂等。
|
|
21
|
-
|
|
22
|
-
### `entities` — 命名实体
|
|
23
|
-
|
|
24
|
-
```sql
|
|
25
|
-
CREATE TABLE IF NOT EXISTS entities (
|
|
26
|
-
id TEXT PRIMARY KEY,
|
|
27
|
-
name TEXT NOT NULL, -- 规范化名称(全名/主名)
|
|
28
|
-
type TEXT, -- person|project|concept|technology|organization
|
|
29
|
-
first_seen TEXT NOT NULL, -- 首次出现时间
|
|
30
|
-
last_seen TEXT NOT NULL, -- 最近出现时间
|
|
31
|
-
mention_count INTEGER DEFAULT 1, -- 提及次数(同名去重后递增)
|
|
32
|
-
canonical_memory_id TEXT -- 规范来源记忆(保留位)
|
|
33
|
-
);
|
|
34
|
-
CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name);
|
|
35
|
-
CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### `entity_attrs` — 属性(快照式时间轴)
|
|
39
|
-
|
|
40
|
-
```sql
|
|
41
|
-
CREATE TABLE IF NOT EXISTS entity_attrs (
|
|
42
|
-
id TEXT PRIMARY KEY,
|
|
43
|
-
entity_id TEXT NOT NULL,
|
|
44
|
-
attr_key TEXT NOT NULL,
|
|
45
|
-
attr_value TEXT NOT NULL,
|
|
46
|
-
memory_id TEXT, -- 属性出处记忆
|
|
47
|
-
valid_from TEXT NOT NULL,
|
|
48
|
-
valid_until TEXT, -- NULL = 当前有效
|
|
49
|
-
confidence REAL DEFAULT 1.0,
|
|
50
|
-
source TEXT
|
|
51
|
-
);
|
|
52
|
-
CREATE INDEX IF NOT EXISTS idx_attrs_entity ON entity_attrs(entity_id);
|
|
53
|
-
CREATE INDEX IF NOT EXISTS idx_attrs_key ON entity_attrs(attr_key);
|
|
54
|
-
CREATE INDEX IF NOT EXISTS idx_attrs_valid ON entity_attrs(valid_from, valid_until);
|
|
55
|
-
CREATE INDEX IF NOT EXISTS idx_attrs_memory ON entity_attrs(memory_id);
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### `entity_relations` — 关系(追加式)
|
|
59
|
-
|
|
60
|
-
```sql
|
|
61
|
-
CREATE TABLE IF NOT EXISTS entity_relations (
|
|
62
|
-
id TEXT PRIMARY KEY,
|
|
63
|
-
from_entity TEXT NOT NULL,
|
|
64
|
-
to_entity TEXT NOT NULL,
|
|
65
|
-
relation_type TEXT NOT NULL, -- uses|depends_on|part_of|related_to|supersedes|affective_context(末者仅由 sleep 情感相位写入)
|
|
66
|
-
memory_id TEXT,
|
|
67
|
-
created_at TEXT NOT NULL,
|
|
68
|
-
metadata TEXT -- JSON 自由字段
|
|
69
|
-
);
|
|
70
|
-
CREATE INDEX IF NOT EXISTS idx_relations_from ON entity_relations(from_entity);
|
|
71
|
-
CREATE INDEX IF NOT EXISTS idx_relations_to ON entity_relations(to_entity);
|
|
72
|
-
CREATE INDEX IF NOT EXISTS idx_relations_type ON entity_relations(relation_type);
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## 二、valid_until 时间轴机制
|
|
78
|
-
|
|
79
|
-
属性采用**快照式**写入:同一 `entity_id + attr_key` 只允许**一行当前有效**(`valid_until IS NULL`)。
|
|
80
|
-
|
|
81
|
-
```
|
|
82
|
-
saveAttr(entity=X, key=role, value="前端工程师")
|
|
83
|
-
→ 先把 X/role 的现有有效行 valid_until 置为 now(invalidateOldAttr)
|
|
84
|
-
→ 再插入新行 valid_from=now, valid_until=NULL
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
读取语义:
|
|
88
|
-
|
|
89
|
-
- `getCurrentAttrs(entityId)` — 只返回有效行(`valid_until IS NULL`),即"当前值"
|
|
90
|
-
- `getAttrHistory(entityId)` — 按 valid_from 升序返回全部历史行(含已失效),用于追溯演变
|
|
91
|
-
- `findMemoriesByAttr(key, value)` — 返回携带该属性**当前有效**行的记忆(去重)
|
|
92
|
-
- **value 非空**:精确匹配 `attr_value`
|
|
93
|
-
- **value 为空 / undefined / null**:返回该 `attr_key` 的全部当前有效记忆("`attr:key` 无 `=value`"契约)
|
|
94
|
-
|
|
95
|
-
> ⚠️ 迁移时注意:同一 entity+key 连存两次会**失效前一行**(快照语义)。要保留多条同 key 的当前值,应把它们挂到**不同实体**上。
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## 三、Store CRUD
|
|
100
|
-
|
|
101
|
-
`createStore` 暴露以下实体 API(`src/store.js`):
|
|
102
|
-
|
|
103
|
-
| 方法 | 说明 |
|
|
104
|
-
|------|------|
|
|
105
|
-
| `createEntity({ name, type })` | 建实体,`first_seen=last_seen=now`,`mention_count=1` |
|
|
106
|
-
| `findEntityByName(name)` | 按规范化名称查(去重锚点) |
|
|
107
|
-
| `findEntityById(id)` | 按 id 查 |
|
|
108
|
-
| `updateEntity(id, patch)` | 部分更新;默认 `mention_count+1`、刷新 `last_seen`;可用 `patch.mention_count` 显式覆盖 |
|
|
109
|
-
| `saveAttr({ entity_id, attr_key, attr_value, memory_id, confidence, source })` | 写属性(先失效旧行) |
|
|
110
|
-
| `invalidateOldAttr(entityId, attrKey, now)` | 手动失效;返回受影响行数 |
|
|
111
|
-
| `getCurrentAttrs(entityId)` | 当前有效属性列表 |
|
|
112
|
-
| `getAttrHistory(entityId)` | 全部属性历史(最旧在前) |
|
|
113
|
-
| `getAttrsByMemory(memoryId)` | 某记忆关联的全部属性(autoDream update 用) |
|
|
114
|
-
| `findMemoriesByAttr(key, value)` | 按属性召回记忆(value 空 = 该 key 全部当前有效) |
|
|
115
|
-
| `saveRelation({ from_entity, to_entity, relation_type, memory_id, metadata })` | 追加关系 |
|
|
116
|
-
| `getRelations(entityId)` | 某实体任一侧(from/to)的关系 |
|
|
117
|
-
| `migrateAttrsToMemory(fromId, toId, now)` | 把 from 记忆的属性 memory_id 改指 to(keeper 已有同 entity+key 当前行则失效);返回 `{ migrated, invalidated }` |
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## 四、LLM 抽取器
|
|
122
|
-
|
|
123
|
-
`src/entities/extractor.js` → `extractEntities(memory, { store, config, callLLM })`。
|
|
124
|
-
|
|
125
|
-
### 触发方式
|
|
126
|
-
|
|
127
|
-
`service.saveWithDedupe` 在 **created** 后 fire-and-forget 触发,仅当:
|
|
128
|
-
|
|
129
|
-
1. `config.entityExtractionEnabled === true`
|
|
130
|
-
2. service 已通过 `service.setEntityExtractor(...)` 注入抽取钩子(`index.js` 在插件启动时接好)
|
|
131
|
-
|
|
132
|
-
抽取**异步执行**、失败绝不阻塞记忆写入(fail-safe)。
|
|
133
|
-
|
|
134
|
-
### LLM JSON 契约
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
-
{
|
|
138
|
-
"entities": [
|
|
139
|
-
{"name": "string", "type": "person|project|concept|technology|organization",
|
|
140
|
-
"attrs": [{"key": "string", "value": "string", "confidence": 0.9}]}
|
|
141
|
-
],
|
|
142
|
-
"relations": [
|
|
143
|
-
{"from": "entityName", "to": "entityName", "type": "uses|depends_on|part_of|related_to"}
|
|
144
|
-
]
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
抽取管线:
|
|
149
|
-
|
|
150
|
-
1. `buildSystemPrompt` — 约束上限(`entityExtractionMaxEntities` / `entityExtractionMaxAttrs`)、禁编造、用规范化名
|
|
151
|
-
2. `extractJsonFromText` — 先直接 `JSON.parse`,失败再抓首个 `{...}` 块
|
|
152
|
-
3. `sanitizeExtractedData` — 非法 type → `concept`;**非法 relation type → 拒收**(#619:不再静默降级成 `related_to`,丢弃的类型名进返回值 `rejectedRelationTypes` 并 `logger.warn`,让"模型抽了但类型不认识"在审计里看得见);非法 confidence → 0.9;超限截断;relations 的 from/to 必须引用实体清单
|
|
153
|
-
|
|
154
|
-
> **`affective_context` 不在这条管线里。** 它只有一个写入者:sleep 的情感归因相位(`docs/SLEEP.md` §5)。实体抽取发生在写入当下,手里没有会话边界,判不了"一次场合"和"反复出现的特质";放它进白名单,等于在同一张 `entity_relations` 表里造第二种 schema(没有 `emotion` / `attribution` / `sessionCount`)。抽取器遇到它会当未知类型拒收并 warn。
|
|
155
|
-
4. `resolveEntity` — **同名去重**:`findEntityByName` 命中 → `updateEntity(id, {})`(`mention_count+1`),未命中 → 建新实体
|
|
156
|
-
5. 逐条 `saveAttr`(挂 `memory_id` + `source: "llm_extract"`)→ 逐条 `saveRelation`
|
|
157
|
-
6. 单实体/属性/关系失败只 `skipCount++` 并告警,不中断整批
|
|
158
|
-
|
|
159
|
-
### 返回 / fail-safe
|
|
160
|
-
|
|
161
|
-
```js
|
|
162
|
-
{ ok: true, entities: [{ name, type, attrs, entity_id }], attrs: [...], relations: [...], skipped: n, rejectedRelationTypes: [...] }
|
|
163
|
-
{ ok: false, error: "..." }
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
- 缺失 content、LLM 返回空、JSON 解析失败、sanitize 抛错、`callLLM` reject → 一律 `{ ok: false }`,**绝不向上抛异常**
|
|
167
|
-
- `entityExtractionEnabled=false` 时钩子完全不触发,存储层照常可用
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## 五、搜索:`entity:` / `attr:` 前缀
|
|
172
|
-
|
|
173
|
-
`service.searchMemories` 在 `config.entitySearchEnabled === true`(默认 true)时识别前缀路由:
|
|
174
|
-
|
|
175
|
-
```
|
|
176
|
-
entity:阿尔托 → searchByEntity("阿尔托")
|
|
177
|
-
attr:国籍=芬兰 → searchByAttr("国籍", "芬兰") 精确匹配
|
|
178
|
-
attr:国籍 → searchByAttr("国籍", undefined) 该 key 全部当前有效
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
### searchByEntity 排序
|
|
182
|
-
|
|
183
|
-
**合并优先级:attr 精确关联 = 1.0 > 关键词提及 = 0.7**,attr 命中不覆盖、keyword 只补充召回,最终按 `_score` 降序取 topK:
|
|
184
|
-
|
|
185
|
-
| 来源 | 分数 |
|
|
186
|
-
|------|------|
|
|
187
|
-
| `entity_attrs.memory_id` 精确关联(当前有效) | `_score = 1.0`,`_source = "entity_attr"` |
|
|
188
|
-
| 标题/内容/标签含实体名 | `_score = 0.7`,`_source = "keyword"` |
|
|
189
|
-
|
|
190
|
-
`entitySearchEnabled=false` 时前缀不做路由,按普通关键词搜索(`entity:xxx` 字面串极少命中 → 通常返回空)。
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## 六、autoDream 联动
|
|
195
|
-
|
|
196
|
-
`applyDecisions` 在 `config.entityExtractionEnabled === true` 时启用实体副作用,**仅记录、绝不阻断主流程**:
|
|
197
|
-
|
|
198
|
-
- **applyUpdate(supersedes)**:事务提交成功后,为该记忆关联的每条实体属性建立**自引用** supersedes 关系,表示"此属性版本已被替代":
|
|
199
|
-
|
|
200
|
-
```js
|
|
201
|
-
saveRelation({ from_entity: attr.entity_id, to_entity: attr.entity_id,
|
|
202
|
-
relation_type: "supersedes", memory_id: id,
|
|
203
|
-
metadata: { attr_key, old_value } })
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
- **applyMerge(属性迁移)**:将 loser 记忆关联的 `entity_attrs.memory_id` 迁移到 keeper;若 keeper 已有同 `entity+key` 的当前有效属性,则 loser 行被**失效**(keeper 值优先):
|
|
207
|
-
|
|
208
|
-
```
|
|
209
|
-
{ migrated, invalidated } = store.migrateAttrsToMemory(loserId, keeperId, now)
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
- `entityExtractionEnabled=false` 时两条副作用**完全跳过**(update/merge 本身照常生效)。
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
## 七、配置项
|
|
217
|
-
|
|
218
|
-
| 键 | 默认值 | 说明 |
|
|
219
|
-
|----|--------|------|
|
|
220
|
-
| `entityExtractionEnabled` | `false` | 实体抽取总开关(默认关;存储层恒可用) |
|
|
221
|
-
| `entityExtractionModel` | `""` | 抽取专用模型(空 = 用 agent 默认模型) |
|
|
222
|
-
| `entityExtractionMaxEntities` | `10` | 每次抽取实体数上限 |
|
|
223
|
-
| `entityExtractionMaxAttrs` | `20` | 每实体属性数上限 |
|
|
224
|
-
| `entitySearchEnabled` | `true` | `entity:` / `attr:` 前缀搜索开关 |
|
|
225
|
-
|
|
226
|
-
```yaml
|
|
227
|
-
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
228
|
-
- id: dsh-mneme
|
|
229
|
-
config:
|
|
230
|
-
entityExtractionEnabled: true
|
|
231
|
-
entityExtractionModel: deepseek-chat # 可选,默认用 agent 默认模型
|
|
232
|
-
entitySearchEnabled: true
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## 八、迁移说明
|
|
238
|
-
|
|
239
|
-
- 实体三表在 `createStore` 的 `SCHEMA` 中 `CREATE TABLE IF NOT EXISTS` 创建,**旧库打开自动建表**,幂等(重复打开/重启无副作用,`test/entities.test.js` 有覆盖)。
|
|
240
|
-
- 无需人工迁移数据;现有 `memories` 表不变,实体表是**旁挂**结构。
|
|
241
|
-
- 抽取开启后,新写入的记忆自动补实体;存量记忆可通过触发抽取或后续 backfill 补全(v0.3.0 未内置存量回扫)。
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## 测试
|
|
246
|
-
|
|
247
|
-
`test/entities.test.js`(31 条,node:test):Schema 三表 + 索引 + 旧库幂等迁移 / 实体 CRUD / 属性时间轴(saveAttr 失效旧行、getCurrentAttrs / getAttrHistory)/ `findMemoriesByAttr`(精确匹配 + **空 value 契约** + 过期行排除)/ 抽取器(mock LLM 写入、同名去重、垃圾 JSON / LLM 故障 fail-safe、开关触发)/ 前缀搜索(1.0 > 0.7 排序、attr 精确、attr 空值、开关关闭不路由)/ autoDream(supersedes、merge 迁移与失效、开关关闭跳过)/ fail-safe(抽取失败不阻塞写入)。
|
|
1
|
+
# 实体结构化记忆(Entity Gene,v0.3.0)
|
|
2
|
+
|
|
3
|
+
> dsh-mneme 的**记忆基因**层:从记忆文本里抽取**命名实体**、**带时间轴的属性**、**实体间关系**,并支持按实体/属性精确召回记忆。与 autoDream 联动——update 记录 supersedes、merge 迁移属性归属。
|
|
4
|
+
|
|
5
|
+
v0.3.0 四个阶段全部落地:
|
|
6
|
+
|
|
7
|
+
| 阶段 | 内容 |
|
|
8
|
+
|------|------|
|
|
9
|
+
| P1 | 三表 Schema(entities / entity_attrs / entity_relations)+ 索引 + store CRUD |
|
|
10
|
+
| P2 | LLM 抽取器(JSON 抽取 + resolveEntity 去重 + saveAttr 时间轴 + saveRelation + fail-safe) |
|
|
11
|
+
| P3 | 前缀搜索(`entity:` / `attr:`),attr 精确 = 1.0 > keyword 提及 = 0.7 |
|
|
12
|
+
| P4 | autoDream 联动(applyUpdate 写 supersedes 自引用;applyMerge 迁移 loser attrs) |
|
|
13
|
+
|
|
14
|
+
存储层(建表 + CRUD)**始终可用**,不依赖任何 LLM;只有 `entityExtractionEnabled=true` 时流水线才会自动抽取。
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 一、三表结构
|
|
19
|
+
|
|
20
|
+
所有建表语句在 `src/store.js` 的 `SCHEMA` 中,`CREATE TABLE IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`,对旧库幂等。
|
|
21
|
+
|
|
22
|
+
### `entities` — 命名实体
|
|
23
|
+
|
|
24
|
+
```sql
|
|
25
|
+
CREATE TABLE IF NOT EXISTS entities (
|
|
26
|
+
id TEXT PRIMARY KEY,
|
|
27
|
+
name TEXT NOT NULL, -- 规范化名称(全名/主名)
|
|
28
|
+
type TEXT, -- person|project|concept|technology|organization
|
|
29
|
+
first_seen TEXT NOT NULL, -- 首次出现时间
|
|
30
|
+
last_seen TEXT NOT NULL, -- 最近出现时间
|
|
31
|
+
mention_count INTEGER DEFAULT 1, -- 提及次数(同名去重后递增)
|
|
32
|
+
canonical_memory_id TEXT -- 规范来源记忆(保留位)
|
|
33
|
+
);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(type);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### `entity_attrs` — 属性(快照式时间轴)
|
|
39
|
+
|
|
40
|
+
```sql
|
|
41
|
+
CREATE TABLE IF NOT EXISTS entity_attrs (
|
|
42
|
+
id TEXT PRIMARY KEY,
|
|
43
|
+
entity_id TEXT NOT NULL,
|
|
44
|
+
attr_key TEXT NOT NULL,
|
|
45
|
+
attr_value TEXT NOT NULL,
|
|
46
|
+
memory_id TEXT, -- 属性出处记忆
|
|
47
|
+
valid_from TEXT NOT NULL,
|
|
48
|
+
valid_until TEXT, -- NULL = 当前有效
|
|
49
|
+
confidence REAL DEFAULT 1.0,
|
|
50
|
+
source TEXT
|
|
51
|
+
);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_attrs_entity ON entity_attrs(entity_id);
|
|
53
|
+
CREATE INDEX IF NOT EXISTS idx_attrs_key ON entity_attrs(attr_key);
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_attrs_valid ON entity_attrs(valid_from, valid_until);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_attrs_memory ON entity_attrs(memory_id);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `entity_relations` — 关系(追加式)
|
|
59
|
+
|
|
60
|
+
```sql
|
|
61
|
+
CREATE TABLE IF NOT EXISTS entity_relations (
|
|
62
|
+
id TEXT PRIMARY KEY,
|
|
63
|
+
from_entity TEXT NOT NULL,
|
|
64
|
+
to_entity TEXT NOT NULL,
|
|
65
|
+
relation_type TEXT NOT NULL, -- uses|depends_on|part_of|related_to|supersedes|affective_context(末者仅由 sleep 情感相位写入)
|
|
66
|
+
memory_id TEXT,
|
|
67
|
+
created_at TEXT NOT NULL,
|
|
68
|
+
metadata TEXT -- JSON 自由字段
|
|
69
|
+
);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_relations_from ON entity_relations(from_entity);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_relations_to ON entity_relations(to_entity);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_relations_type ON entity_relations(relation_type);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 二、valid_until 时间轴机制
|
|
78
|
+
|
|
79
|
+
属性采用**快照式**写入:同一 `entity_id + attr_key` 只允许**一行当前有效**(`valid_until IS NULL`)。
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
saveAttr(entity=X, key=role, value="前端工程师")
|
|
83
|
+
→ 先把 X/role 的现有有效行 valid_until 置为 now(invalidateOldAttr)
|
|
84
|
+
→ 再插入新行 valid_from=now, valid_until=NULL
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
读取语义:
|
|
88
|
+
|
|
89
|
+
- `getCurrentAttrs(entityId)` — 只返回有效行(`valid_until IS NULL`),即"当前值"
|
|
90
|
+
- `getAttrHistory(entityId)` — 按 valid_from 升序返回全部历史行(含已失效),用于追溯演变
|
|
91
|
+
- `findMemoriesByAttr(key, value)` — 返回携带该属性**当前有效**行的记忆(去重)
|
|
92
|
+
- **value 非空**:精确匹配 `attr_value`
|
|
93
|
+
- **value 为空 / undefined / null**:返回该 `attr_key` 的全部当前有效记忆("`attr:key` 无 `=value`"契约)
|
|
94
|
+
|
|
95
|
+
> ⚠️ 迁移时注意:同一 entity+key 连存两次会**失效前一行**(快照语义)。要保留多条同 key 的当前值,应把它们挂到**不同实体**上。
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 三、Store CRUD
|
|
100
|
+
|
|
101
|
+
`createStore` 暴露以下实体 API(`src/store.js`):
|
|
102
|
+
|
|
103
|
+
| 方法 | 说明 |
|
|
104
|
+
|------|------|
|
|
105
|
+
| `createEntity({ name, type })` | 建实体,`first_seen=last_seen=now`,`mention_count=1` |
|
|
106
|
+
| `findEntityByName(name)` | 按规范化名称查(去重锚点) |
|
|
107
|
+
| `findEntityById(id)` | 按 id 查 |
|
|
108
|
+
| `updateEntity(id, patch)` | 部分更新;默认 `mention_count+1`、刷新 `last_seen`;可用 `patch.mention_count` 显式覆盖 |
|
|
109
|
+
| `saveAttr({ entity_id, attr_key, attr_value, memory_id, confidence, source })` | 写属性(先失效旧行) |
|
|
110
|
+
| `invalidateOldAttr(entityId, attrKey, now)` | 手动失效;返回受影响行数 |
|
|
111
|
+
| `getCurrentAttrs(entityId)` | 当前有效属性列表 |
|
|
112
|
+
| `getAttrHistory(entityId)` | 全部属性历史(最旧在前) |
|
|
113
|
+
| `getAttrsByMemory(memoryId)` | 某记忆关联的全部属性(autoDream update 用) |
|
|
114
|
+
| `findMemoriesByAttr(key, value)` | 按属性召回记忆(value 空 = 该 key 全部当前有效) |
|
|
115
|
+
| `saveRelation({ from_entity, to_entity, relation_type, memory_id, metadata })` | 追加关系 |
|
|
116
|
+
| `getRelations(entityId)` | 某实体任一侧(from/to)的关系 |
|
|
117
|
+
| `migrateAttrsToMemory(fromId, toId, now)` | 把 from 记忆的属性 memory_id 改指 to(keeper 已有同 entity+key 当前行则失效);返回 `{ migrated, invalidated }` |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 四、LLM 抽取器
|
|
122
|
+
|
|
123
|
+
`src/entities/extractor.js` → `extractEntities(memory, { store, config, callLLM })`。
|
|
124
|
+
|
|
125
|
+
### 触发方式
|
|
126
|
+
|
|
127
|
+
`service.saveWithDedupe` 在 **created** 后 fire-and-forget 触发,仅当:
|
|
128
|
+
|
|
129
|
+
1. `config.entityExtractionEnabled === true`
|
|
130
|
+
2. service 已通过 `service.setEntityExtractor(...)` 注入抽取钩子(`index.js` 在插件启动时接好)
|
|
131
|
+
|
|
132
|
+
抽取**异步执行**、失败绝不阻塞记忆写入(fail-safe)。
|
|
133
|
+
|
|
134
|
+
### LLM JSON 契约
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
{
|
|
138
|
+
"entities": [
|
|
139
|
+
{"name": "string", "type": "person|project|concept|technology|organization",
|
|
140
|
+
"attrs": [{"key": "string", "value": "string", "confidence": 0.9}]}
|
|
141
|
+
],
|
|
142
|
+
"relations": [
|
|
143
|
+
{"from": "entityName", "to": "entityName", "type": "uses|depends_on|part_of|related_to"}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
抽取管线:
|
|
149
|
+
|
|
150
|
+
1. `buildSystemPrompt` — 约束上限(`entityExtractionMaxEntities` / `entityExtractionMaxAttrs`)、禁编造、用规范化名
|
|
151
|
+
2. `extractJsonFromText` — 先直接 `JSON.parse`,失败再抓首个 `{...}` 块
|
|
152
|
+
3. `sanitizeExtractedData` — 非法 type → `concept`;**非法 relation type → 拒收**(#619:不再静默降级成 `related_to`,丢弃的类型名进返回值 `rejectedRelationTypes` 并 `logger.warn`,让"模型抽了但类型不认识"在审计里看得见);非法 confidence → 0.9;超限截断;relations 的 from/to 必须引用实体清单
|
|
153
|
+
|
|
154
|
+
> **`affective_context` 不在这条管线里。** 它只有一个写入者:sleep 的情感归因相位(`docs/SLEEP.md` §5)。实体抽取发生在写入当下,手里没有会话边界,判不了"一次场合"和"反复出现的特质";放它进白名单,等于在同一张 `entity_relations` 表里造第二种 schema(没有 `emotion` / `attribution` / `sessionCount`)。抽取器遇到它会当未知类型拒收并 warn。
|
|
155
|
+
4. `resolveEntity` — **同名去重**:`findEntityByName` 命中 → `updateEntity(id, {})`(`mention_count+1`),未命中 → 建新实体
|
|
156
|
+
5. 逐条 `saveAttr`(挂 `memory_id` + `source: "llm_extract"`)→ 逐条 `saveRelation`
|
|
157
|
+
6. 单实体/属性/关系失败只 `skipCount++` 并告警,不中断整批
|
|
158
|
+
|
|
159
|
+
### 返回 / fail-safe
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
{ ok: true, entities: [{ name, type, attrs, entity_id }], attrs: [...], relations: [...], skipped: n, rejectedRelationTypes: [...] }
|
|
163
|
+
{ ok: false, error: "..." }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- 缺失 content、LLM 返回空、JSON 解析失败、sanitize 抛错、`callLLM` reject → 一律 `{ ok: false }`,**绝不向上抛异常**
|
|
167
|
+
- `entityExtractionEnabled=false` 时钩子完全不触发,存储层照常可用
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 五、搜索:`entity:` / `attr:` 前缀
|
|
172
|
+
|
|
173
|
+
`service.searchMemories` 在 `config.entitySearchEnabled === true`(默认 true)时识别前缀路由:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
entity:阿尔托 → searchByEntity("阿尔托")
|
|
177
|
+
attr:国籍=芬兰 → searchByAttr("国籍", "芬兰") 精确匹配
|
|
178
|
+
attr:国籍 → searchByAttr("国籍", undefined) 该 key 全部当前有效
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### searchByEntity 排序
|
|
182
|
+
|
|
183
|
+
**合并优先级:attr 精确关联 = 1.0 > 关键词提及 = 0.7**,attr 命中不覆盖、keyword 只补充召回,最终按 `_score` 降序取 topK:
|
|
184
|
+
|
|
185
|
+
| 来源 | 分数 |
|
|
186
|
+
|------|------|
|
|
187
|
+
| `entity_attrs.memory_id` 精确关联(当前有效) | `_score = 1.0`,`_source = "entity_attr"` |
|
|
188
|
+
| 标题/内容/标签含实体名 | `_score = 0.7`,`_source = "keyword"` |
|
|
189
|
+
|
|
190
|
+
`entitySearchEnabled=false` 时前缀不做路由,按普通关键词搜索(`entity:xxx` 字面串极少命中 → 通常返回空)。
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 六、autoDream 联动
|
|
195
|
+
|
|
196
|
+
`applyDecisions` 在 `config.entityExtractionEnabled === true` 时启用实体副作用,**仅记录、绝不阻断主流程**:
|
|
197
|
+
|
|
198
|
+
- **applyUpdate(supersedes)**:事务提交成功后,为该记忆关联的每条实体属性建立**自引用** supersedes 关系,表示"此属性版本已被替代":
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
saveRelation({ from_entity: attr.entity_id, to_entity: attr.entity_id,
|
|
202
|
+
relation_type: "supersedes", memory_id: id,
|
|
203
|
+
metadata: { attr_key, old_value } })
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
- **applyMerge(属性迁移)**:将 loser 记忆关联的 `entity_attrs.memory_id` 迁移到 keeper;若 keeper 已有同 `entity+key` 的当前有效属性,则 loser 行被**失效**(keeper 值优先):
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
{ migrated, invalidated } = store.migrateAttrsToMemory(loserId, keeperId, now)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- `entityExtractionEnabled=false` 时两条副作用**完全跳过**(update/merge 本身照常生效)。
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 七、配置项
|
|
217
|
+
|
|
218
|
+
| 键 | 默认值 | 说明 |
|
|
219
|
+
|----|--------|------|
|
|
220
|
+
| `entityExtractionEnabled` | `false` | 实体抽取总开关(默认关;存储层恒可用) |
|
|
221
|
+
| `entityExtractionModel` | `""` | 抽取专用模型(空 = 用 agent 默认模型) |
|
|
222
|
+
| `entityExtractionMaxEntities` | `10` | 每次抽取实体数上限 |
|
|
223
|
+
| `entityExtractionMaxAttrs` | `20` | 每实体属性数上限 |
|
|
224
|
+
| `entitySearchEnabled` | `true` | `entity:` / `attr:` 前缀搜索开关 |
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
228
|
+
- id: dsh-mneme
|
|
229
|
+
config:
|
|
230
|
+
entityExtractionEnabled: true
|
|
231
|
+
entityExtractionModel: deepseek-chat # 可选,默认用 agent 默认模型
|
|
232
|
+
entitySearchEnabled: true
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 八、迁移说明
|
|
238
|
+
|
|
239
|
+
- 实体三表在 `createStore` 的 `SCHEMA` 中 `CREATE TABLE IF NOT EXISTS` 创建,**旧库打开自动建表**,幂等(重复打开/重启无副作用,`test/entities.test.js` 有覆盖)。
|
|
240
|
+
- 无需人工迁移数据;现有 `memories` 表不变,实体表是**旁挂**结构。
|
|
241
|
+
- 抽取开启后,新写入的记忆自动补实体;存量记忆可通过触发抽取或后续 backfill 补全(v0.3.0 未内置存量回扫)。
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 测试
|
|
246
|
+
|
|
247
|
+
`test/entities.test.js`(31 条,node:test):Schema 三表 + 索引 + 旧库幂等迁移 / 实体 CRUD / 属性时间轴(saveAttr 失效旧行、getCurrentAttrs / getAttrHistory)/ `findMemoriesByAttr`(精确匹配 + **空 value 契约** + 过期行排除)/ 抽取器(mock LLM 写入、同名去重、垃圾 JSON / LLM 故障 fail-safe、开关触发)/ 前缀搜索(1.0 > 0.7 排序、attr 精确、attr 空值、开关关闭不路由)/ autoDream(supersedes、merge 迁移与失效、开关关闭跳过)/ fail-safe(抽取失败不阻塞写入)。
|