@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
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createStore } from "../src/store.js";
|
|
4
|
-
import { createService } from "../src/service.js";
|
|
5
|
-
|
|
6
|
-
// 这条锁防的是一类「上限形同不存在」的回归:上限判断如果排在会抛错的那次读取
|
|
7
|
-
// 后面,轮询就永远不会停手。
|
|
8
|
-
//
|
|
9
|
-
// service.js 的 setEmbedder 为异步初始化的 embedder 起了个轮询:每 100ms 读一次
|
|
10
|
-
// `emb.ready`,读到 true 或撞上 EMBED_READY_POLL_LIMIT(=30) 就停
|
|
11
|
-
// (注释原文 "~3s ceiling; never poll forever")。但 `ready` 是个 getter
|
|
12
|
-
// —— embedding.js 的 OpenAI embedder 直接读库 —— 于是写成
|
|
13
|
-
// if (emb.ready === true || attempts >= EMBED_READY_POLL_LIMIT) { stop(); }
|
|
14
|
-
// 的整条 `||` 会在左半边当场中断,右半边的天花板永远轮不到:stopEmbedReadyPolling()
|
|
15
|
-
// 不执行,定时器活过上限,并且每 100ms 抛一次未捕获异常。
|
|
16
|
-
//
|
|
17
|
-
// 实测现场(2026-10-14,加蒸馏留存的装配级用例时撞上):fiber.dispose() 走完
|
|
18
|
-
// index.js 的 disposer(末尾一句就是 store.close())之后,每次读 ready 都抛
|
|
19
|
-
// "database is not open" [ERR_INVALID_STATE],5s 内读了 46 次 —— 天花板 31 被
|
|
20
|
-
// 击穿,node --test 进程因此不再退出。一个只在启动时读一次库的 getter,能把
|
|
21
|
-
// 宿主的事件循环钉死;而现有测试全都「装配完不拆」,所以从 v0.7.1 起一直没人碰到。
|
|
22
|
-
//
|
|
23
|
-
// 时序照真实卸载顺序复现:安装时未就绪(轮询启动)→ store.close()(此后每次读
|
|
24
|
-
// ready 都抛)→ 等超过天花板 → 看它停没停手、报了几次。
|
|
25
|
-
const POLL_LIMIT = 30; // 与 src/service.js 的 EMBED_READY_POLL_LIMIT 同值,改那边要改这里
|
|
26
|
-
const POLL_MS = 100;
|
|
27
|
-
const CEILING_READS = 1 + POLL_LIMIT; // setEmbedder 自己读一次,之后每个 tick 一次
|
|
28
|
-
const SETTLE_MS = 400; // 静默这么久没新读取,就认为定时器已经停手
|
|
29
|
-
const DEADLINE_MS = 30000; // 上限:等到这里还没静默就按超时处理
|
|
30
|
-
|
|
31
|
-
// 等「读取次数不再增长」。不能用「睡够 POLL_MS*30 + 600ms 再断言」——
|
|
32
|
-
// 全量 npm test 是多文件并行跑的,CPU 一挤,30 个 tick 未必在 3.6s 内跑完,
|
|
33
|
-
// 断言就会读到 30 而不是 31(2026-10-15 rebase 后在全量跑里实测撞到一次,
|
|
34
|
-
// 单跑 3/3 通过、紧接着全量跑两遍也全绿——纯粹的负载抖动)。
|
|
35
|
-
// 静默判定是可靠的:定时器周期 100ms,而越过上限后 stopEmbedReadyPolling()
|
|
36
|
-
// 会 clearInterval,此后 reads 恒不再变,两者不会混淆。
|
|
37
|
-
async function waitUntilSettled(getReads) {
|
|
38
|
-
const started = Date.now();
|
|
39
|
-
let last = getReads();
|
|
40
|
-
let lastChange = Date.now();
|
|
41
|
-
while (Date.now() - started < DEADLINE_MS) {
|
|
42
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
43
|
-
const now = getReads();
|
|
44
|
-
if (now !== last) {
|
|
45
|
-
last = now;
|
|
46
|
-
lastChange = Date.now();
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
if (Date.now() - lastChange >= SETTLE_MS) return now;
|
|
50
|
-
}
|
|
51
|
-
return getReads();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
test("the embedder ready poll stops at its ceiling even when reading ready throws", async () => {
|
|
55
|
-
const warns = [];
|
|
56
|
-
const store = createStore(":memory:");
|
|
57
|
-
const service = createService({
|
|
58
|
-
store,
|
|
59
|
-
mirror: null,
|
|
60
|
-
config: {},
|
|
61
|
-
logger: { warn: (...args) => warns.push(args) }
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
let reads = 0;
|
|
65
|
-
let closed = false;
|
|
66
|
-
const embedder = {
|
|
67
|
-
get ready() {
|
|
68
|
-
reads++;
|
|
69
|
-
if (closed) {
|
|
70
|
-
// 与 embedding.js 的 OpenAI embedder 同形:getter 内部经 settings 读库。
|
|
71
|
-
store.db.prepare("SELECT count(*) AS c FROM memories").get();
|
|
72
|
-
}
|
|
73
|
-
return false; // 始终「未就绪」:轮询会一直跑下去,除非天花板真的生效
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
service.setEmbedder(embedder);
|
|
78
|
-
assert.equal(reads, 1, "setEmbedder 先读一次 ready,决定要不要起轮询");
|
|
79
|
-
|
|
80
|
-
closed = true;
|
|
81
|
-
store.close(); // 卸载路径的最后一步
|
|
82
|
-
|
|
83
|
-
await waitUntilSettled(() => reads);
|
|
84
|
-
const atCeiling = reads;
|
|
85
|
-
|
|
86
|
-
assert.equal(
|
|
87
|
-
atCeiling,
|
|
88
|
-
CEILING_READS,
|
|
89
|
-
`读 ready 抛错也必须按上限停手(实际读了 ${atCeiling} 次,上限 ${CEILING_READS})`
|
|
90
|
-
);
|
|
91
|
-
assert.equal(reads, atCeiling, "越过天花板之后不许再有读取:定时器必须已经清掉");
|
|
92
|
-
assert.equal(warns.length, 1, "读不出来只报一次,别把 3s 上限变成 30 条刷屏");
|
|
93
|
-
assert.match(String(warns[0][0]), /embedder ready probe failed/);
|
|
94
|
-
});
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { createStore } from "../src/store.js";
|
|
4
|
+
import { createService } from "../src/service.js";
|
|
5
|
+
|
|
6
|
+
// 这条锁防的是一类「上限形同不存在」的回归:上限判断如果排在会抛错的那次读取
|
|
7
|
+
// 后面,轮询就永远不会停手。
|
|
8
|
+
//
|
|
9
|
+
// service.js 的 setEmbedder 为异步初始化的 embedder 起了个轮询:每 100ms 读一次
|
|
10
|
+
// `emb.ready`,读到 true 或撞上 EMBED_READY_POLL_LIMIT(=30) 就停
|
|
11
|
+
// (注释原文 "~3s ceiling; never poll forever")。但 `ready` 是个 getter
|
|
12
|
+
// —— embedding.js 的 OpenAI embedder 直接读库 —— 于是写成
|
|
13
|
+
// if (emb.ready === true || attempts >= EMBED_READY_POLL_LIMIT) { stop(); }
|
|
14
|
+
// 的整条 `||` 会在左半边当场中断,右半边的天花板永远轮不到:stopEmbedReadyPolling()
|
|
15
|
+
// 不执行,定时器活过上限,并且每 100ms 抛一次未捕获异常。
|
|
16
|
+
//
|
|
17
|
+
// 实测现场(2026-10-14,加蒸馏留存的装配级用例时撞上):fiber.dispose() 走完
|
|
18
|
+
// index.js 的 disposer(末尾一句就是 store.close())之后,每次读 ready 都抛
|
|
19
|
+
// "database is not open" [ERR_INVALID_STATE],5s 内读了 46 次 —— 天花板 31 被
|
|
20
|
+
// 击穿,node --test 进程因此不再退出。一个只在启动时读一次库的 getter,能把
|
|
21
|
+
// 宿主的事件循环钉死;而现有测试全都「装配完不拆」,所以从 v0.7.1 起一直没人碰到。
|
|
22
|
+
//
|
|
23
|
+
// 时序照真实卸载顺序复现:安装时未就绪(轮询启动)→ store.close()(此后每次读
|
|
24
|
+
// ready 都抛)→ 等超过天花板 → 看它停没停手、报了几次。
|
|
25
|
+
const POLL_LIMIT = 30; // 与 src/service.js 的 EMBED_READY_POLL_LIMIT 同值,改那边要改这里
|
|
26
|
+
const POLL_MS = 100;
|
|
27
|
+
const CEILING_READS = 1 + POLL_LIMIT; // setEmbedder 自己读一次,之后每个 tick 一次
|
|
28
|
+
const SETTLE_MS = 400; // 静默这么久没新读取,就认为定时器已经停手
|
|
29
|
+
const DEADLINE_MS = 30000; // 上限:等到这里还没静默就按超时处理
|
|
30
|
+
|
|
31
|
+
// 等「读取次数不再增长」。不能用「睡够 POLL_MS*30 + 600ms 再断言」——
|
|
32
|
+
// 全量 npm test 是多文件并行跑的,CPU 一挤,30 个 tick 未必在 3.6s 内跑完,
|
|
33
|
+
// 断言就会读到 30 而不是 31(2026-10-15 rebase 后在全量跑里实测撞到一次,
|
|
34
|
+
// 单跑 3/3 通过、紧接着全量跑两遍也全绿——纯粹的负载抖动)。
|
|
35
|
+
// 静默判定是可靠的:定时器周期 100ms,而越过上限后 stopEmbedReadyPolling()
|
|
36
|
+
// 会 clearInterval,此后 reads 恒不再变,两者不会混淆。
|
|
37
|
+
async function waitUntilSettled(getReads) {
|
|
38
|
+
const started = Date.now();
|
|
39
|
+
let last = getReads();
|
|
40
|
+
let lastChange = Date.now();
|
|
41
|
+
while (Date.now() - started < DEADLINE_MS) {
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
43
|
+
const now = getReads();
|
|
44
|
+
if (now !== last) {
|
|
45
|
+
last = now;
|
|
46
|
+
lastChange = Date.now();
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (Date.now() - lastChange >= SETTLE_MS) return now;
|
|
50
|
+
}
|
|
51
|
+
return getReads();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
test("the embedder ready poll stops at its ceiling even when reading ready throws", async () => {
|
|
55
|
+
const warns = [];
|
|
56
|
+
const store = createStore(":memory:");
|
|
57
|
+
const service = createService({
|
|
58
|
+
store,
|
|
59
|
+
mirror: null,
|
|
60
|
+
config: {},
|
|
61
|
+
logger: { warn: (...args) => warns.push(args) }
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
let reads = 0;
|
|
65
|
+
let closed = false;
|
|
66
|
+
const embedder = {
|
|
67
|
+
get ready() {
|
|
68
|
+
reads++;
|
|
69
|
+
if (closed) {
|
|
70
|
+
// 与 embedding.js 的 OpenAI embedder 同形:getter 内部经 settings 读库。
|
|
71
|
+
store.db.prepare("SELECT count(*) AS c FROM memories").get();
|
|
72
|
+
}
|
|
73
|
+
return false; // 始终「未就绪」:轮询会一直跑下去,除非天花板真的生效
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
service.setEmbedder(embedder);
|
|
78
|
+
assert.equal(reads, 1, "setEmbedder 先读一次 ready,决定要不要起轮询");
|
|
79
|
+
|
|
80
|
+
closed = true;
|
|
81
|
+
store.close(); // 卸载路径的最后一步
|
|
82
|
+
|
|
83
|
+
await waitUntilSettled(() => reads);
|
|
84
|
+
const atCeiling = reads;
|
|
85
|
+
|
|
86
|
+
assert.equal(
|
|
87
|
+
atCeiling,
|
|
88
|
+
CEILING_READS,
|
|
89
|
+
`读 ready 抛错也必须按上限停手(实际读了 ${atCeiling} 次,上限 ${CEILING_READS})`
|
|
90
|
+
);
|
|
91
|
+
assert.equal(reads, atCeiling, "越过天花板之后不许再有读取:定时器必须已经清掉");
|
|
92
|
+
assert.equal(warns.length, 1, "读不出来只报一次,别把 3s 上限变成 30 条刷屏");
|
|
93
|
+
assert.match(String(warns[0][0]), /embedder ready probe failed/);
|
|
94
|
+
});
|
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { embedText, embedTextDetailed, createEmbedder } from "../src/embedding.js";
|
|
4
|
-
|
|
5
|
-
// distill-tx-embed-gap 的"坏了为什么看不出来"半边:embedText 此前把「配置缺」
|
|
6
|
-
// 「网络挂」「超时」「HTTP 4xx/5xx」「响应不是 JSON」「响应没有向量」全部压成
|
|
7
|
-
// null,回执账本只能统一写 embedding-request-returned-no-vector——分诊不可能。
|
|
8
|
-
// embedTextDetailed 把失败模式拆开;embedText 保留旧 null 契约(调用方不变)。
|
|
9
|
-
|
|
10
|
-
const FULL = {
|
|
11
|
-
enabled: true,
|
|
12
|
-
baseUrl: "https://api.example.com/v1",
|
|
13
|
-
apiKey: "sk-test",
|
|
14
|
-
model: "text-embedding-3-small"
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
async function withFetch(impl, fn) {
|
|
18
|
-
const original = globalThis.fetch;
|
|
19
|
-
globalThis.fetch = impl;
|
|
20
|
-
try {
|
|
21
|
-
return await fn();
|
|
22
|
-
} finally {
|
|
23
|
-
globalThis.fetch = original;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
test("detailed: 成功时 reason 为 null,vector 与旧契约一致", async () => {
|
|
28
|
-
await withFetch(async () => ({ ok: true, json: async () => ({ data: [{ embedding: [1, 2, 3] }] }) }), async () => {
|
|
29
|
-
const out = await embedTextDetailed(FULL, "猫咪");
|
|
30
|
-
assert.deepEqual(out.vector, [1, 2, 3]);
|
|
31
|
-
assert.equal(out.reason, null);
|
|
32
|
-
// 旧包装的 null 契约不变
|
|
33
|
-
assert.deepEqual(await embedText(FULL, "猫咪"), [1, 2, 3]);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("detailed: 配置缺失时逐字段点名,不伪装成网络故障", async () => {
|
|
38
|
-
assert.match((await embedTextDetailed({ ...FULL, model: "" }, "x")).reason, /^config-incomplete:model$/);
|
|
39
|
-
assert.match((await embedTextDetailed({ ...FULL, apiKey: "" }, "x")).reason, /^config-incomplete:apiKey$/);
|
|
40
|
-
assert.match((await embedTextDetailed({ ...FULL, baseUrl: "" }, "x")).reason, /^config-incomplete:baseUrl$/);
|
|
41
|
-
assert.match(await embedTextDetailed(FULL, "").then((o) => o.reason), /config-incomplete:text/);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("detailed: HTTP 状态码进 reason(401 钥匙 / 404 路径 / 429 限流)", async () => {
|
|
45
|
-
await withFetch(async () => ({ ok: false, status: 404, text: async () => "Not Found" }), async () => {
|
|
46
|
-
const out = await embedTextDetailed(FULL, "x");
|
|
47
|
-
assert.equal(out.vector, null);
|
|
48
|
-
assert.equal(out.reason, "http-404:Not Found");
|
|
49
|
-
});
|
|
50
|
-
await withFetch(async () => ({ ok: false, status: 429, text: async () => "" }), async () => {
|
|
51
|
-
const out = await embedTextDetailed(FULL, "x");
|
|
52
|
-
assert.equal(out.reason, "http-429", "空响应体不拼尾巴");
|
|
53
|
-
});
|
|
54
|
-
// 旧包装在这些场景全部 null,不抛
|
|
55
|
-
await withFetch(async () => ({ ok: false, status: 401, text: async () => "denied" }), async () => {
|
|
56
|
-
assert.equal(await embedText(FULL, "x"), null);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("detailed: 超时与网络错误分型,不混为一谈", async () => {
|
|
61
|
-
await withFetch(async () => {
|
|
62
|
-
const err = new Error("socket hang up");
|
|
63
|
-
err.name = "TypeError";
|
|
64
|
-
throw err;
|
|
65
|
-
}, async () => {
|
|
66
|
-
const out = await embedTextDetailed(FULL, "x");
|
|
67
|
-
assert.match(out.reason, /^request-failed:network:socket hang up/);
|
|
68
|
-
});
|
|
69
|
-
await withFetch(async () => {
|
|
70
|
-
const err = new Error("The operation was aborted");
|
|
71
|
-
err.name = "TimeoutError";
|
|
72
|
-
throw err;
|
|
73
|
-
}, async () => {
|
|
74
|
-
const out = await embedTextDetailed(FULL, "x");
|
|
75
|
-
assert.match(out.reason, /^request-failed:timeout:/, "慢和不通是两种病");
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("detailed: 响应不是 JSON 与响应没有向量各自有名", async () => {
|
|
80
|
-
await withFetch(async () => ({ ok: true, json: async () => { throw new Error("bad"); } }), async () => {
|
|
81
|
-
const out = await embedTextDetailed(FULL, "x");
|
|
82
|
-
assert.equal(out.reason, "response-not-json");
|
|
83
|
-
});
|
|
84
|
-
await withFetch(async () => ({ ok: true, json: async () => ({ data: [] }) }), async () => {
|
|
85
|
-
const out = await embedTextDetailed(FULL, "x");
|
|
86
|
-
assert.equal(out.reason, "response-no-vector");
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test("embedFor 回执账本带上可区分 reason(不再是统一的 no-vector)", async () => {
|
|
91
|
-
const receipts = [];
|
|
92
|
-
const embedder = createEmbedder({
|
|
93
|
-
store: { setEmbedding() {} },
|
|
94
|
-
settings: { getVectorConfig: () => FULL },
|
|
95
|
-
logger: { info() {}, warn() {} }
|
|
96
|
-
});
|
|
97
|
-
// embedReceipts 在账本上;rejection 已在 schedule() 内消化,这里直接等 schedule promise。
|
|
98
|
-
await withFetch(async () => ({ ok: false, status: 404, text: async () => "no route" }), async () => {
|
|
99
|
-
const r = await embedder.schedule({ id: "m1", title: "t", content: "c" });
|
|
100
|
-
assert.equal(r.status, "failed");
|
|
101
|
-
assert.equal(r.reason, "http-404:no route");
|
|
102
|
-
});
|
|
103
|
-
await withFetch(async () => ({ ok: true, json: async () => ({ data: [{ embedding: [1, 2, 3] }] }) }), async () => {
|
|
104
|
-
const r = await embedder.schedule({ id: "m2", title: "t", content: "c" });
|
|
105
|
-
assert.equal(r.status, "ok");
|
|
106
|
-
assert.equal(r.dim, 3);
|
|
107
|
-
});
|
|
108
|
-
const snap = embedder.embedReceipts();
|
|
109
|
-
assert.equal(snap.totals.failed, 1);
|
|
110
|
-
assert.equal(snap.totals.ok, 1);
|
|
111
|
-
assert.equal(snap.lastFailReason, "http-404:no route", "账本记的是分诊后的原因");
|
|
112
|
-
});
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { embedText, embedTextDetailed, createEmbedder } from "../src/embedding.js";
|
|
4
|
+
|
|
5
|
+
// distill-tx-embed-gap 的"坏了为什么看不出来"半边:embedText 此前把「配置缺」
|
|
6
|
+
// 「网络挂」「超时」「HTTP 4xx/5xx」「响应不是 JSON」「响应没有向量」全部压成
|
|
7
|
+
// null,回执账本只能统一写 embedding-request-returned-no-vector——分诊不可能。
|
|
8
|
+
// embedTextDetailed 把失败模式拆开;embedText 保留旧 null 契约(调用方不变)。
|
|
9
|
+
|
|
10
|
+
const FULL = {
|
|
11
|
+
enabled: true,
|
|
12
|
+
baseUrl: "https://api.example.com/v1",
|
|
13
|
+
apiKey: "sk-test",
|
|
14
|
+
model: "text-embedding-3-small"
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function withFetch(impl, fn) {
|
|
18
|
+
const original = globalThis.fetch;
|
|
19
|
+
globalThis.fetch = impl;
|
|
20
|
+
try {
|
|
21
|
+
return await fn();
|
|
22
|
+
} finally {
|
|
23
|
+
globalThis.fetch = original;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
test("detailed: 成功时 reason 为 null,vector 与旧契约一致", async () => {
|
|
28
|
+
await withFetch(async () => ({ ok: true, json: async () => ({ data: [{ embedding: [1, 2, 3] }] }) }), async () => {
|
|
29
|
+
const out = await embedTextDetailed(FULL, "猫咪");
|
|
30
|
+
assert.deepEqual(out.vector, [1, 2, 3]);
|
|
31
|
+
assert.equal(out.reason, null);
|
|
32
|
+
// 旧包装的 null 契约不变
|
|
33
|
+
assert.deepEqual(await embedText(FULL, "猫咪"), [1, 2, 3]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("detailed: 配置缺失时逐字段点名,不伪装成网络故障", async () => {
|
|
38
|
+
assert.match((await embedTextDetailed({ ...FULL, model: "" }, "x")).reason, /^config-incomplete:model$/);
|
|
39
|
+
assert.match((await embedTextDetailed({ ...FULL, apiKey: "" }, "x")).reason, /^config-incomplete:apiKey$/);
|
|
40
|
+
assert.match((await embedTextDetailed({ ...FULL, baseUrl: "" }, "x")).reason, /^config-incomplete:baseUrl$/);
|
|
41
|
+
assert.match(await embedTextDetailed(FULL, "").then((o) => o.reason), /config-incomplete:text/);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("detailed: HTTP 状态码进 reason(401 钥匙 / 404 路径 / 429 限流)", async () => {
|
|
45
|
+
await withFetch(async () => ({ ok: false, status: 404, text: async () => "Not Found" }), async () => {
|
|
46
|
+
const out = await embedTextDetailed(FULL, "x");
|
|
47
|
+
assert.equal(out.vector, null);
|
|
48
|
+
assert.equal(out.reason, "http-404:Not Found");
|
|
49
|
+
});
|
|
50
|
+
await withFetch(async () => ({ ok: false, status: 429, text: async () => "" }), async () => {
|
|
51
|
+
const out = await embedTextDetailed(FULL, "x");
|
|
52
|
+
assert.equal(out.reason, "http-429", "空响应体不拼尾巴");
|
|
53
|
+
});
|
|
54
|
+
// 旧包装在这些场景全部 null,不抛
|
|
55
|
+
await withFetch(async () => ({ ok: false, status: 401, text: async () => "denied" }), async () => {
|
|
56
|
+
assert.equal(await embedText(FULL, "x"), null);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("detailed: 超时与网络错误分型,不混为一谈", async () => {
|
|
61
|
+
await withFetch(async () => {
|
|
62
|
+
const err = new Error("socket hang up");
|
|
63
|
+
err.name = "TypeError";
|
|
64
|
+
throw err;
|
|
65
|
+
}, async () => {
|
|
66
|
+
const out = await embedTextDetailed(FULL, "x");
|
|
67
|
+
assert.match(out.reason, /^request-failed:network:socket hang up/);
|
|
68
|
+
});
|
|
69
|
+
await withFetch(async () => {
|
|
70
|
+
const err = new Error("The operation was aborted");
|
|
71
|
+
err.name = "TimeoutError";
|
|
72
|
+
throw err;
|
|
73
|
+
}, async () => {
|
|
74
|
+
const out = await embedTextDetailed(FULL, "x");
|
|
75
|
+
assert.match(out.reason, /^request-failed:timeout:/, "慢和不通是两种病");
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("detailed: 响应不是 JSON 与响应没有向量各自有名", async () => {
|
|
80
|
+
await withFetch(async () => ({ ok: true, json: async () => { throw new Error("bad"); } }), async () => {
|
|
81
|
+
const out = await embedTextDetailed(FULL, "x");
|
|
82
|
+
assert.equal(out.reason, "response-not-json");
|
|
83
|
+
});
|
|
84
|
+
await withFetch(async () => ({ ok: true, json: async () => ({ data: [] }) }), async () => {
|
|
85
|
+
const out = await embedTextDetailed(FULL, "x");
|
|
86
|
+
assert.equal(out.reason, "response-no-vector");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("embedFor 回执账本带上可区分 reason(不再是统一的 no-vector)", async () => {
|
|
91
|
+
const receipts = [];
|
|
92
|
+
const embedder = createEmbedder({
|
|
93
|
+
store: { setEmbedding() {} },
|
|
94
|
+
settings: { getVectorConfig: () => FULL },
|
|
95
|
+
logger: { info() {}, warn() {} }
|
|
96
|
+
});
|
|
97
|
+
// embedReceipts 在账本上;rejection 已在 schedule() 内消化,这里直接等 schedule promise。
|
|
98
|
+
await withFetch(async () => ({ ok: false, status: 404, text: async () => "no route" }), async () => {
|
|
99
|
+
const r = await embedder.schedule({ id: "m1", title: "t", content: "c" });
|
|
100
|
+
assert.equal(r.status, "failed");
|
|
101
|
+
assert.equal(r.reason, "http-404:no route");
|
|
102
|
+
});
|
|
103
|
+
await withFetch(async () => ({ ok: true, json: async () => ({ data: [{ embedding: [1, 2, 3] }] }) }), async () => {
|
|
104
|
+
const r = await embedder.schedule({ id: "m2", title: "t", content: "c" });
|
|
105
|
+
assert.equal(r.status, "ok");
|
|
106
|
+
assert.equal(r.dim, 3);
|
|
107
|
+
});
|
|
108
|
+
const snap = embedder.embedReceipts();
|
|
109
|
+
assert.equal(snap.totals.failed, 1);
|
|
110
|
+
assert.equal(snap.totals.ok, 1);
|
|
111
|
+
assert.equal(snap.lastFailReason, "http-404:no route", "账本记的是分诊后的原因");
|
|
112
|
+
});
|