@modusensus/dsh-mneme 0.14.0-beta.1 → 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 -830
- package/assets/icon.svg +3 -3
- package/bin/cli.mjs +964 -964
- package/bin/dsh-mneme-choro.mjs +262 -262
- 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 -404
- 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 -3600
- 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 -14322
- package/lib/commands.js +95 -95
- package/lib/config-keys.js +144 -144
- package/lib/config.js +1361 -1344
- 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 -945
- package/lib/dream/narratives.js +44 -44
- package/lib/dream/sleep.js +2027 -2027
- package/lib/dream/triage.js +139 -139
- package/lib/dream.js +1879 -1879
- 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 -119
- package/lib/image-describe.js +158 -0
- package/lib/index.js +852 -852
- package/lib/inject.js +656 -651
- 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 -595
- 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 -3268
- package/lib/session-gate.js +91 -91
- package/lib/session-usage.js +350 -350
- package/lib/settings.js +827 -817
- 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 -5895
- 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 -267
- 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 -640
- package/lib/wiki/render.js +261 -261
- package/lib/wiki/scan.js +371 -371
- package/lib/wiki/t0.js +500 -500
- package/lib/wiki/t1-jobs.js +232 -232
- package/lib/wiki/t1.js +609 -609
- package/lib/write-admission.js +404 -404
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +1 -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 -210
- package/scripts/release-notes.mjs +164 -164
- 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 -3600
- 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 -1344
- 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 -945
- package/src/dream/narratives.js +44 -44
- package/src/dream/sleep.js +2027 -2027
- package/src/dream/triage.js +139 -139
- package/src/dream.js +1879 -1879
- 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 -119
- package/src/image-describe.js +158 -0
- package/src/index.js +852 -852
- package/src/inject.js +656 -651
- 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 -595
- 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 -3268
- package/src/session-gate.js +91 -91
- package/src/session-usage.js +350 -350
- package/src/settings.js +827 -817
- 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 -5895
- 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 -267
- 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 -640
- package/src/wiki/render.js +261 -261
- package/src/wiki/scan.js +371 -371
- package/src/wiki/t0.js +500 -500
- package/src/wiki/t1-jobs.js +232 -232
- package/src/wiki/t1.js +609 -609
- 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 -2998
- 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 -4425
- 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 -452
- package/test/conflict-ledger.test.js +242 -242
- 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 -432
- 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 -174
- 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 -333
- 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 -259
- 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 -109
- 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 -553
- 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 -90
- package/test/panel-tokens.test.js +245 -245
- 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 -156
- package/test/release-notes.test.js +265 -265
- 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 -188
- 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 -1455
- 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 -734
- package/test/wiki-claims.test.js +194 -194
- 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 -202
- package/test/wiki-queries.test.js +398 -398
- package/test/wiki-scan.test.js +208 -208
- package/test/wiki-store.test.js +190 -190
- package/test/wiki-t0.test.js +456 -456
- package/test/wiki-t1-jobs.test.js +125 -125
- package/test/wiki-t1.test.js +460 -460
- package/test/wiki-tools.test.js +176 -176
- package/test/workflow-guards.test.js +155 -155
- package/test/write-admission.test.js +668 -668
|
@@ -1,198 +1,198 @@
|
|
|
1
|
-
// Persona settings (user_settings "persona" key) — v1.2 多卡模型。
|
|
2
|
-
// Locks: legacy v1 single-object reads as default; byAgent cards round-trip;
|
|
3
|
-
// corruption returns empty store without throwing; unknown fields dropped.
|
|
4
|
-
// Whitelist lock guards the #254-style pit: a flag missing from
|
|
5
|
-
// FEATURE_FLAG_BOOLEANS would make the panel toggle silently ineffective.
|
|
6
|
-
import test from "node:test";
|
|
7
|
-
import assert from "node:assert/strict";
|
|
8
|
-
import { createStore } from "../src/store.js";
|
|
9
|
-
import { createSettings } from "../src/settings.js";
|
|
10
|
-
import { resolvePersonaCard } from "../src/user-settings.js";
|
|
11
|
-
|
|
12
|
-
function setup() {
|
|
13
|
-
const store = createStore(":memory:");
|
|
14
|
-
const settings = createSettings(store.db);
|
|
15
|
-
return { store, settings };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
test("persona defaults to empty store; default card round-trips via single-object form", () => {
|
|
19
|
-
const { store, settings } = setup();
|
|
20
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
21
|
-
const input = {
|
|
22
|
-
name: "Amarre",
|
|
23
|
-
personality: "轻松幽默,讲解用类比",
|
|
24
|
-
replyStyle: "先给结论再解释",
|
|
25
|
-
enabled: false,
|
|
26
|
-
provenance: { sourceMemoryIds: [], generatedAt: "", reviewedByUser: false }
|
|
27
|
-
};
|
|
28
|
-
settings.setPersona(input);
|
|
29
|
-
const got = settings.getPersona();
|
|
30
|
-
assert.deepEqual(got.default, input);
|
|
31
|
-
assert.deepEqual(got.byAgent, {});
|
|
32
|
-
store.close();
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test("default card write drops unknown fields", () => {
|
|
36
|
-
const { store, settings } = setup();
|
|
37
|
-
settings.setPersona({ name: "Amarre", sneaky: "field" });
|
|
38
|
-
const got = settings.getPersona();
|
|
39
|
-
assert.equal(got.default.name, "Amarre");
|
|
40
|
-
assert.equal("sneaky" in got.default, false);
|
|
41
|
-
store.close();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("persona read of corrupt JSON returns empty store without throwing", () => {
|
|
45
|
-
const { store, settings } = setup();
|
|
46
|
-
settings.setPersona({ name: "seed" });
|
|
47
|
-
// 直改底层键模拟损坏(面板口径:坏值显示为空、可重写,不抛错)
|
|
48
|
-
store.db.prepare("UPDATE user_settings SET value = ? WHERE key = 'persona'").run("not json at all");
|
|
49
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
50
|
-
store.close();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test("persona read of non-object JSON (array/number) returns empty store", () => {
|
|
54
|
-
const { store, settings } = setup();
|
|
55
|
-
store.db.prepare("INSERT INTO user_settings (key, value) VALUES ('persona', '[1,2]')").run();
|
|
56
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
57
|
-
store.db.prepare("UPDATE user_settings SET value = '42' WHERE key = 'persona'").run();
|
|
58
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
59
|
-
store.close();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("setPersona tolerates non-object input (writes empty persona)", () => {
|
|
63
|
-
const { store, settings } = setup();
|
|
64
|
-
settings.setPersona(null);
|
|
65
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
66
|
-
settings.setPersona("nope");
|
|
67
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
68
|
-
store.close();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// ---- v1.2 多卡模型:{ default, byAgent },旧单对象读作 default 兼容 ----------
|
|
72
|
-
|
|
73
|
-
test("v1 legacy single-object persona reads as default (zero migration)", () => {
|
|
74
|
-
const { store, settings } = setup();
|
|
75
|
-
// 直写 v1 形(单对象)模拟存量库
|
|
76
|
-
store.db.prepare("INSERT INTO user_settings (key, value) VALUES ('persona', ?)")
|
|
77
|
-
.run(JSON.stringify({ name: "Amarre", personality: "轻松幽默", enabled: true }));
|
|
78
|
-
const got = settings.getPersona();
|
|
79
|
-
assert.equal(got.default.name, "Amarre");
|
|
80
|
-
assert.equal(got.default.enabled, true);
|
|
81
|
-
assert.deepEqual(got.byAgent, {});
|
|
82
|
-
store.close();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// 寻址口径住在 src/user-settings.js(注入与面板预览共用一份),不在 settings 里——
|
|
86
|
-
// settings 只存卡。原来那两个 getPersonaFor 用例因此改指向 resolvePersonaCard:
|
|
87
|
-
// 断言的是同一件事,但落在唯一那份实现上。
|
|
88
|
-
test("byAgent card round-trips via setPersonaFor/resolvePersonaCard", () => {
|
|
89
|
-
const { store, settings } = setup();
|
|
90
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", personality: "冷危占有", enabled: true });
|
|
91
|
-
assert.deepEqual(resolvePersonaCard(settings, "zephyr").card, { name: "泽菲尔", personality: "冷危占有", enabled: true });
|
|
92
|
-
assert.equal(resolvePersonaCard(settings, "zephyr").source, "byAgent");
|
|
93
|
-
// default 仍在且未被影响
|
|
94
|
-
assert.deepEqual(settings.getPersona().default, {});
|
|
95
|
-
// 卡列表含 zephyr
|
|
96
|
-
assert.deepEqual(settings.listPersonas(), ["zephyr"]);
|
|
97
|
-
store.close();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test("缺省寻址:身份没建卡、或卡被关掉,都落 default", () => {
|
|
101
|
-
const { store, settings } = setup();
|
|
102
|
-
settings.setPersona({ name: "Amarre", enabled: true }); // 单对象形写 default
|
|
103
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: false }); // 卡存在但关
|
|
104
|
-
assert.equal(resolvePersonaCard(settings, "unknown-bot").card.name, "Amarre");
|
|
105
|
-
// 身份卡存在但 enabled=false → 落 default(兜底优先,不注入半张卡)
|
|
106
|
-
assert.equal(resolvePersonaCard(settings, "zephyr").card.name, "Amarre");
|
|
107
|
-
// 身份缺失(null/空串)→ default
|
|
108
|
-
assert.equal(resolvePersonaCard(settings, null).card.name, "Amarre");
|
|
109
|
-
assert.equal(resolvePersonaCard(settings, "").card.name, "Amarre");
|
|
110
|
-
store.close();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("strict 寻址:身份没建卡与卡被关掉都不注入,无名会话仍用 default", () => {
|
|
114
|
-
const { store, settings } = setup();
|
|
115
|
-
settings.setPersona({ name: "Amarre", enabled: true });
|
|
116
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: false });
|
|
117
|
-
const strict = { strict: true };
|
|
118
|
-
for (const id of ["unknown-bot", "zephyr"]) {
|
|
119
|
-
const { card, source } = resolvePersonaCard(settings, id, strict);
|
|
120
|
-
assert.equal(source, "none", `${id} 在严格寻址下不该拿到任何卡`);
|
|
121
|
-
assert.deepEqual(card, {});
|
|
122
|
-
}
|
|
123
|
-
// 开着的身份卡照样命中(strict 不改变命中语义)
|
|
124
|
-
settings.setPersonaFor("mentor", { name: "导师", enabled: true });
|
|
125
|
-
assert.equal(resolvePersonaCard(settings, "mentor", strict).source, "byAgent");
|
|
126
|
-
// 解析不到身份 = default 卡的受众,strict 不动这一格
|
|
127
|
-
assert.equal(resolvePersonaCard(settings, null, strict).card.name, "Amarre");
|
|
128
|
-
store.close();
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
test("setPersona single-object form merges default and keeps byAgent", () => {
|
|
132
|
-
const { store, settings } = setup();
|
|
133
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: true });
|
|
134
|
-
settings.setPersona({ name: "Amarre-新", enabled: true }); // 单对象形
|
|
135
|
-
const got = settings.getPersona();
|
|
136
|
-
assert.equal(got.default.name, "Amarre-新");
|
|
137
|
-
assert.equal(got.byAgent.zephyr.name, "泽菲尔", "byAgent must survive a legacy-form write");
|
|
138
|
-
store.close();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test("removePersona deletes byAgent card but default is protected", () => {
|
|
142
|
-
const { store, settings } = setup();
|
|
143
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: true });
|
|
144
|
-
assert.equal(settings.removePersona("zephyr"), true);
|
|
145
|
-
assert.deepEqual(settings.listPersonas(), []);
|
|
146
|
-
assert.equal(settings.removePersona("default"), false, "default card cannot be removed");
|
|
147
|
-
assert.equal(settings.removePersona("ghost"), false);
|
|
148
|
-
store.close();
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("corrupt multi-card JSON reads as empty store without throwing", () => {
|
|
152
|
-
const { store, settings } = setup();
|
|
153
|
-
settings.setPersona({ name: "seed" });
|
|
154
|
-
store.db.prepare("UPDATE user_settings SET value = ? WHERE key = 'persona'").run("broken {");
|
|
155
|
-
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
156
|
-
store.close();
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
test("personaEnabled is in the feature-flag boolean whitelist", () => {
|
|
160
|
-
const { store, settings } = setup();
|
|
161
|
-
// 写侧逐键校验的合并写:未知键抛 TypeError,白名单键可用——
|
|
162
|
-
// 这条锁防「白名单漏登记 → 面板开关静默失效」(#254 同型坑)。
|
|
163
|
-
settings.setFeatureFlags({ personaEnabled: true });
|
|
164
|
-
assert.equal(settings.getFeatureFlags().personaEnabled, true);
|
|
165
|
-
assert.throws(() => settings.setFeatureFlags({ notARealFlag: true }), TypeError);
|
|
166
|
-
store.close();
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test("strict 寻址:一张身份卡都没建时仍回落 default(#587 的例外)", () => {
|
|
170
|
-
// 两种处境必须分开:
|
|
171
|
-
// A) 建了身份卡、只是没这一张 → strict 下不注入(见上一条用例,行为不变)
|
|
172
|
-
// B) 一张身份卡都没建 → default 是用户手里唯一那张卡,strict 不许把它关死
|
|
173
|
-
// DS Bot 这类宿主里所有 bot 会话共用 agentPreset "standard",用户按 bot 名字建卡
|
|
174
|
-
// 永远不命中,于是必然落进 B——此时按 none 处理等于把唯一那张卡静默废掉。
|
|
175
|
-
const { store, settings } = setup();
|
|
176
|
-
settings.setPersona({ name: "Amarre", enabled: true });
|
|
177
|
-
assert.deepEqual(settings.getPersona().byAgent, {}, "前提:byAgent 整体为空");
|
|
178
|
-
const { card, source } = resolvePersonaCard(settings, "standard", { strict: true });
|
|
179
|
-
assert.equal(source, "default", "一张卡都没建时严格寻址仍回落 default");
|
|
180
|
-
assert.equal(card.name, "Amarre");
|
|
181
|
-
// 建了任意一张身份卡之后,例外立即失效——兜底退回严格语义
|
|
182
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: true });
|
|
183
|
-
assert.equal(resolvePersonaCard(settings, "standard", { strict: true }).source, "none");
|
|
184
|
-
// 而这张卡自己仍然命中
|
|
185
|
-
assert.equal(resolvePersonaCard(settings, "zephyr", { strict: true }).source, "byAgent");
|
|
186
|
-
store.close();
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("strict 寻址:身份卡存在但全被关掉,仍算「建过卡」——例外只看有没有键", () => {
|
|
190
|
-
// 例外判的是 byAgent 的键数,不是「有没有可用的卡」:一张 enabled=false 的卡
|
|
191
|
-
// 也算「用户已经做过分区」,此时不该再拿 default 去兜。这条锁住判据不会被
|
|
192
|
-
// 改成「有可用卡才算建过」,否则关掉唯一那张身份卡会重新落回 default。
|
|
193
|
-
const { store, settings } = setup();
|
|
194
|
-
settings.setPersona({ name: "Amarre", enabled: true });
|
|
195
|
-
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: false });
|
|
196
|
-
assert.equal(resolvePersonaCard(settings, "standard", { strict: true }).source, "none");
|
|
197
|
-
store.close();
|
|
198
|
-
});
|
|
1
|
+
// Persona settings (user_settings "persona" key) — v1.2 多卡模型。
|
|
2
|
+
// Locks: legacy v1 single-object reads as default; byAgent cards round-trip;
|
|
3
|
+
// corruption returns empty store without throwing; unknown fields dropped.
|
|
4
|
+
// Whitelist lock guards the #254-style pit: a flag missing from
|
|
5
|
+
// FEATURE_FLAG_BOOLEANS would make the panel toggle silently ineffective.
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { createStore } from "../src/store.js";
|
|
9
|
+
import { createSettings } from "../src/settings.js";
|
|
10
|
+
import { resolvePersonaCard } from "../src/user-settings.js";
|
|
11
|
+
|
|
12
|
+
function setup() {
|
|
13
|
+
const store = createStore(":memory:");
|
|
14
|
+
const settings = createSettings(store.db);
|
|
15
|
+
return { store, settings };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test("persona defaults to empty store; default card round-trips via single-object form", () => {
|
|
19
|
+
const { store, settings } = setup();
|
|
20
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
21
|
+
const input = {
|
|
22
|
+
name: "Amarre",
|
|
23
|
+
personality: "轻松幽默,讲解用类比",
|
|
24
|
+
replyStyle: "先给结论再解释",
|
|
25
|
+
enabled: false,
|
|
26
|
+
provenance: { sourceMemoryIds: [], generatedAt: "", reviewedByUser: false }
|
|
27
|
+
};
|
|
28
|
+
settings.setPersona(input);
|
|
29
|
+
const got = settings.getPersona();
|
|
30
|
+
assert.deepEqual(got.default, input);
|
|
31
|
+
assert.deepEqual(got.byAgent, {});
|
|
32
|
+
store.close();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("default card write drops unknown fields", () => {
|
|
36
|
+
const { store, settings } = setup();
|
|
37
|
+
settings.setPersona({ name: "Amarre", sneaky: "field" });
|
|
38
|
+
const got = settings.getPersona();
|
|
39
|
+
assert.equal(got.default.name, "Amarre");
|
|
40
|
+
assert.equal("sneaky" in got.default, false);
|
|
41
|
+
store.close();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("persona read of corrupt JSON returns empty store without throwing", () => {
|
|
45
|
+
const { store, settings } = setup();
|
|
46
|
+
settings.setPersona({ name: "seed" });
|
|
47
|
+
// 直改底层键模拟损坏(面板口径:坏值显示为空、可重写,不抛错)
|
|
48
|
+
store.db.prepare("UPDATE user_settings SET value = ? WHERE key = 'persona'").run("not json at all");
|
|
49
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
50
|
+
store.close();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("persona read of non-object JSON (array/number) returns empty store", () => {
|
|
54
|
+
const { store, settings } = setup();
|
|
55
|
+
store.db.prepare("INSERT INTO user_settings (key, value) VALUES ('persona', '[1,2]')").run();
|
|
56
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
57
|
+
store.db.prepare("UPDATE user_settings SET value = '42' WHERE key = 'persona'").run();
|
|
58
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
59
|
+
store.close();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("setPersona tolerates non-object input (writes empty persona)", () => {
|
|
63
|
+
const { store, settings } = setup();
|
|
64
|
+
settings.setPersona(null);
|
|
65
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
66
|
+
settings.setPersona("nope");
|
|
67
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
68
|
+
store.close();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// ---- v1.2 多卡模型:{ default, byAgent },旧单对象读作 default 兼容 ----------
|
|
72
|
+
|
|
73
|
+
test("v1 legacy single-object persona reads as default (zero migration)", () => {
|
|
74
|
+
const { store, settings } = setup();
|
|
75
|
+
// 直写 v1 形(单对象)模拟存量库
|
|
76
|
+
store.db.prepare("INSERT INTO user_settings (key, value) VALUES ('persona', ?)")
|
|
77
|
+
.run(JSON.stringify({ name: "Amarre", personality: "轻松幽默", enabled: true }));
|
|
78
|
+
const got = settings.getPersona();
|
|
79
|
+
assert.equal(got.default.name, "Amarre");
|
|
80
|
+
assert.equal(got.default.enabled, true);
|
|
81
|
+
assert.deepEqual(got.byAgent, {});
|
|
82
|
+
store.close();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 寻址口径住在 src/user-settings.js(注入与面板预览共用一份),不在 settings 里——
|
|
86
|
+
// settings 只存卡。原来那两个 getPersonaFor 用例因此改指向 resolvePersonaCard:
|
|
87
|
+
// 断言的是同一件事,但落在唯一那份实现上。
|
|
88
|
+
test("byAgent card round-trips via setPersonaFor/resolvePersonaCard", () => {
|
|
89
|
+
const { store, settings } = setup();
|
|
90
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", personality: "冷危占有", enabled: true });
|
|
91
|
+
assert.deepEqual(resolvePersonaCard(settings, "zephyr").card, { name: "泽菲尔", personality: "冷危占有", enabled: true });
|
|
92
|
+
assert.equal(resolvePersonaCard(settings, "zephyr").source, "byAgent");
|
|
93
|
+
// default 仍在且未被影响
|
|
94
|
+
assert.deepEqual(settings.getPersona().default, {});
|
|
95
|
+
// 卡列表含 zephyr
|
|
96
|
+
assert.deepEqual(settings.listPersonas(), ["zephyr"]);
|
|
97
|
+
store.close();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("缺省寻址:身份没建卡、或卡被关掉,都落 default", () => {
|
|
101
|
+
const { store, settings } = setup();
|
|
102
|
+
settings.setPersona({ name: "Amarre", enabled: true }); // 单对象形写 default
|
|
103
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: false }); // 卡存在但关
|
|
104
|
+
assert.equal(resolvePersonaCard(settings, "unknown-bot").card.name, "Amarre");
|
|
105
|
+
// 身份卡存在但 enabled=false → 落 default(兜底优先,不注入半张卡)
|
|
106
|
+
assert.equal(resolvePersonaCard(settings, "zephyr").card.name, "Amarre");
|
|
107
|
+
// 身份缺失(null/空串)→ default
|
|
108
|
+
assert.equal(resolvePersonaCard(settings, null).card.name, "Amarre");
|
|
109
|
+
assert.equal(resolvePersonaCard(settings, "").card.name, "Amarre");
|
|
110
|
+
store.close();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("strict 寻址:身份没建卡与卡被关掉都不注入,无名会话仍用 default", () => {
|
|
114
|
+
const { store, settings } = setup();
|
|
115
|
+
settings.setPersona({ name: "Amarre", enabled: true });
|
|
116
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: false });
|
|
117
|
+
const strict = { strict: true };
|
|
118
|
+
for (const id of ["unknown-bot", "zephyr"]) {
|
|
119
|
+
const { card, source } = resolvePersonaCard(settings, id, strict);
|
|
120
|
+
assert.equal(source, "none", `${id} 在严格寻址下不该拿到任何卡`);
|
|
121
|
+
assert.deepEqual(card, {});
|
|
122
|
+
}
|
|
123
|
+
// 开着的身份卡照样命中(strict 不改变命中语义)
|
|
124
|
+
settings.setPersonaFor("mentor", { name: "导师", enabled: true });
|
|
125
|
+
assert.equal(resolvePersonaCard(settings, "mentor", strict).source, "byAgent");
|
|
126
|
+
// 解析不到身份 = default 卡的受众,strict 不动这一格
|
|
127
|
+
assert.equal(resolvePersonaCard(settings, null, strict).card.name, "Amarre");
|
|
128
|
+
store.close();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("setPersona single-object form merges default and keeps byAgent", () => {
|
|
132
|
+
const { store, settings } = setup();
|
|
133
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: true });
|
|
134
|
+
settings.setPersona({ name: "Amarre-新", enabled: true }); // 单对象形
|
|
135
|
+
const got = settings.getPersona();
|
|
136
|
+
assert.equal(got.default.name, "Amarre-新");
|
|
137
|
+
assert.equal(got.byAgent.zephyr.name, "泽菲尔", "byAgent must survive a legacy-form write");
|
|
138
|
+
store.close();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("removePersona deletes byAgent card but default is protected", () => {
|
|
142
|
+
const { store, settings } = setup();
|
|
143
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: true });
|
|
144
|
+
assert.equal(settings.removePersona("zephyr"), true);
|
|
145
|
+
assert.deepEqual(settings.listPersonas(), []);
|
|
146
|
+
assert.equal(settings.removePersona("default"), false, "default card cannot be removed");
|
|
147
|
+
assert.equal(settings.removePersona("ghost"), false);
|
|
148
|
+
store.close();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("corrupt multi-card JSON reads as empty store without throwing", () => {
|
|
152
|
+
const { store, settings } = setup();
|
|
153
|
+
settings.setPersona({ name: "seed" });
|
|
154
|
+
store.db.prepare("UPDATE user_settings SET value = ? WHERE key = 'persona'").run("broken {");
|
|
155
|
+
assert.deepEqual(settings.getPersona(), { default: {}, byAgent: {}, bySession: {} });
|
|
156
|
+
store.close();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("personaEnabled is in the feature-flag boolean whitelist", () => {
|
|
160
|
+
const { store, settings } = setup();
|
|
161
|
+
// 写侧逐键校验的合并写:未知键抛 TypeError,白名单键可用——
|
|
162
|
+
// 这条锁防「白名单漏登记 → 面板开关静默失效」(#254 同型坑)。
|
|
163
|
+
settings.setFeatureFlags({ personaEnabled: true });
|
|
164
|
+
assert.equal(settings.getFeatureFlags().personaEnabled, true);
|
|
165
|
+
assert.throws(() => settings.setFeatureFlags({ notARealFlag: true }), TypeError);
|
|
166
|
+
store.close();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("strict 寻址:一张身份卡都没建时仍回落 default(#587 的例外)", () => {
|
|
170
|
+
// 两种处境必须分开:
|
|
171
|
+
// A) 建了身份卡、只是没这一张 → strict 下不注入(见上一条用例,行为不变)
|
|
172
|
+
// B) 一张身份卡都没建 → default 是用户手里唯一那张卡,strict 不许把它关死
|
|
173
|
+
// DS Bot 这类宿主里所有 bot 会话共用 agentPreset "standard",用户按 bot 名字建卡
|
|
174
|
+
// 永远不命中,于是必然落进 B——此时按 none 处理等于把唯一那张卡静默废掉。
|
|
175
|
+
const { store, settings } = setup();
|
|
176
|
+
settings.setPersona({ name: "Amarre", enabled: true });
|
|
177
|
+
assert.deepEqual(settings.getPersona().byAgent, {}, "前提:byAgent 整体为空");
|
|
178
|
+
const { card, source } = resolvePersonaCard(settings, "standard", { strict: true });
|
|
179
|
+
assert.equal(source, "default", "一张卡都没建时严格寻址仍回落 default");
|
|
180
|
+
assert.equal(card.name, "Amarre");
|
|
181
|
+
// 建了任意一张身份卡之后,例外立即失效——兜底退回严格语义
|
|
182
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: true });
|
|
183
|
+
assert.equal(resolvePersonaCard(settings, "standard", { strict: true }).source, "none");
|
|
184
|
+
// 而这张卡自己仍然命中
|
|
185
|
+
assert.equal(resolvePersonaCard(settings, "zephyr", { strict: true }).source, "byAgent");
|
|
186
|
+
store.close();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("strict 寻址:身份卡存在但全被关掉,仍算「建过卡」——例外只看有没有键", () => {
|
|
190
|
+
// 例外判的是 byAgent 的键数,不是「有没有可用的卡」:一张 enabled=false 的卡
|
|
191
|
+
// 也算「用户已经做过分区」,此时不该再拿 default 去兜。这条锁住判据不会被
|
|
192
|
+
// 改成「有可用卡才算建过」,否则关掉唯一那张身份卡会重新落回 default。
|
|
193
|
+
const { store, settings } = setup();
|
|
194
|
+
settings.setPersona({ name: "Amarre", enabled: true });
|
|
195
|
+
settings.setPersonaFor("zephyr", { name: "泽菲尔", enabled: false });
|
|
196
|
+
assert.equal(resolvePersonaCard(settings, "standard", { strict: true }).source, "none");
|
|
197
|
+
store.close();
|
|
198
|
+
});
|