@snoai/memory 1.2.9 → 1.2.11
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/README.md +4 -4
- package/dist/{access-tracker-D1e-2-Bb.d.ts → access-tracker-BOPHSJjf.d.ts} +4 -4
- package/dist/{adapter-TCrv5P-C.d.ts → adapter-lyb6RaQE.d.ts} +2 -2
- package/dist/{atomic-memory-extraction-C0n0wHzt.d.ts → atomic-memory-extraction-B_XpkhMd.d.ts} +7 -5
- package/dist/{atomic-memory-extraction-BG42OXou.js → atomic-memory-extraction-o2v8mp7G.js} +109 -50
- package/dist/{b-profile-section-dictionary-provider-y3DMQ518.d.ts → b-profile-section-dictionary-provider-BK5NBs-y.d.ts} +1 -1
- package/dist/{capture-policy-detector-BY7v5Cq1.d.ts → capture-policy-detector-BvVGmxxX.d.ts} +1 -1
- package/dist/{classifier-DnbbtwTS.d.ts → classifier-CXQxJJPP.d.ts} +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/{coding-skin-_Qu3INZD.js → coding-skin-azRXA51Z.js} +2 -1
- package/dist/coding-skin.d.ts +1 -0
- package/dist/coding-skin.js +2 -2
- package/dist/{config-BCZRhUvW.js → config-C7LzSWhG.js} +9 -4
- package/dist/{connection-C9YD5sgm.js → connection-PQcq3TPO.js} +1 -1
- package/dist/{derived-suppression-cache-BLAH0nB9.d.ts → derived-suppression-cache-Ckwjey7I.d.ts} +1 -1
- package/dist/diagnostic-encoder.js +1 -1
- package/dist/{index-dQMkc_6y.d.ts → index-CsPUNkcm.d.ts} +2 -2
- package/dist/{index-BO4RU_mc.d.ts → index-DPfJrOFD.d.ts} +1 -1
- package/dist/{index-DL8AVj0Z.d.ts → index-Pb9LrHgL.d.ts} +4 -5
- package/dist/index.d.ts +12 -9
- package/dist/index.js +106 -51
- package/dist/internal/config/index.d.ts +1 -1
- package/dist/internal/config/index.js +4 -5
- package/dist/internal/config/plugin-config-schema.d.ts +1 -1
- package/dist/internal/config/plugin-config-schema.js +1 -1
- package/dist/internal/config/product-mode.d.ts +1 -1
- package/dist/internal/config/settings.d.ts +1 -1
- package/dist/internal/config/settings.js +4 -4
- package/dist/internal/config/skin-defaults.d.ts +1 -1
- package/dist/internal/contract/profile.d.ts +1 -1
- package/dist/internal/contract/routes.d.ts +1 -1
- package/dist/internal/engine/bindings/memory-cli-shared.d.ts +4 -4
- package/dist/internal/engine/bindings/memory-forget-tool.js +1 -1
- package/dist/internal/engine/bindings/memory-list-tool.js +1 -1
- package/dist/internal/engine/bindings/memory-recall-tool.js +2 -2
- package/dist/internal/engine/bindings/memory-reflection-resolve-tool.js +1 -1
- package/dist/internal/engine/bindings/memory-stats-tool.js +2 -2
- package/dist/internal/engine/bindings/memory-store-tool.js +4 -4
- package/dist/internal/engine/bindings/memory-tool-access.d.ts +1 -1
- package/dist/internal/engine/bindings/memory-tool-access.js +1 -1
- package/dist/internal/engine/bindings/memory-tool-results.d.ts +1 -1
- package/dist/internal/engine/bindings/memory-tool-results.js +1 -1
- package/dist/internal/engine/bindings/memory-tool-schemas.d.ts +5 -5
- package/dist/internal/engine/bindings/memory-tool-schemas.js +1 -1
- package/dist/internal/engine/bindings/memory-update-tool.js +3 -3
- package/dist/internal/engine/bindings/sno-station-mem-ambient-learning-hook.d.ts +4 -4
- package/dist/internal/engine/bindings/sno-station-mem-ambient-learning-hook.js +4 -4
- package/dist/internal/engine/bindings/sno-station-mem-auto-recall-hook.d.ts +4 -4
- package/dist/internal/engine/bindings/sno-station-mem-auto-recall-hook.js +3 -3
- package/dist/internal/engine/bindings/sno-station-mem-insight-distill-factory.d.ts +6 -6
- package/dist/internal/engine/bindings/sno-station-mem-insight-distill-factory.js +7 -5
- package/dist/internal/engine/bindings/sno-station-mem-message-transcript.js +2 -2
- package/dist/internal/engine/bindings/sno-station-mem-reset-hook.d.ts +3 -3
- package/dist/internal/engine/bindings/sno-station-mem-runtime-mode.d.ts +1 -1
- package/dist/internal/engine/bindings/sno-station-mem-runtime-mode.js +3 -3
- package/dist/internal/engine/extraction/atomic-memory-extraction.d.ts +1 -1
- package/dist/internal/engine/extraction/atomic-memory-extraction.js +1 -1
- package/dist/internal/engine/extraction/b-profile-section-dictionary-provider.d.ts +1 -1
- package/dist/internal/engine/extraction/b-profile-section-rekey.d.ts +5 -5
- package/dist/internal/engine/extraction/capture-policy-detector.d.ts +1 -1
- package/dist/internal/engine/extraction/memory-metadata-codec.d.ts +2 -2
- package/dist/internal/engine/extraction/memory-temporality-classifier.d.ts +1 -1
- package/dist/internal/engine/extraction/memory-temporality-classifier.js +1 -1
- package/dist/internal/engine/observability/adapter.d.ts +1 -1
- package/dist/internal/engine/observability/memory-snapshot.d.ts +1 -1
- package/dist/internal/engine/observability/observable-embedder.d.ts +1 -1
- package/dist/internal/engine/observability/observable-llm-client.d.ts +1 -1
- package/dist/internal/engine/observability/observable-llm-client.js +0 -2
- package/dist/internal/engine/observability/observable-memory-store.d.ts +1 -1
- package/dist/internal/engine/observability/observable-memory-store.js +2 -2
- package/dist/internal/engine/observability/observable-retriever.d.ts +1 -1
- package/dist/internal/engine/observability/observable-retriever.js +2 -2
- package/dist/internal/engine/observability/runtime-diagnostics.d.ts +1 -1
- package/dist/internal/engine/observability/runtime-diagnostics.js +3 -3
- package/dist/internal/engine/operations/daily-spend-estimator.js +1 -1
- package/dist/internal/engine/operations/memory-tier-promoter.d.ts +1 -1
- package/dist/internal/engine/operations/runtime-audit-log.d.ts +3 -3
- package/dist/internal/engine/operations/runtime-audit-log.js +2 -2
- package/dist/internal/engine/provider/provider-registration.d.ts +4 -4
- package/dist/internal/engine/provider/provider-row-renderer.d.ts +1 -1
- package/dist/internal/engine/reflection/reflection-command-hooks.d.ts +1 -1
- package/dist/internal/engine/reflection/reflection-command-hooks.js +1 -1
- package/dist/internal/engine/reflection/reflection-deps.d.ts +1 -1
- package/dist/internal/engine/reflection/reflection-embedded-generator.d.ts +1 -1
- package/dist/internal/engine/reflection/reflection-embedded-generator.js +1 -1
- package/dist/internal/engine/reflection/reflection-injection-hooks.d.ts +1 -1
- package/dist/internal/engine/reflection/reflection-injection-hooks.js +1 -1
- package/dist/internal/engine/reflection/reflection-lifecycle-hooks.d.ts +1 -1
- package/dist/internal/engine/reflection/reflection-lifecycle-hooks.js +1 -1
- package/dist/internal/engine/reflection/strategy-hook-runner.d.ts +3 -3
- package/dist/internal/engine/reflection/strategy-hook-runner.js +2 -2
- package/dist/internal/engine/rem/classifier.d.ts +1 -1
- package/dist/internal/engine/rem/index.d.ts +2 -2
- package/dist/internal/engine/rem/index.js +9 -7
- package/dist/internal/engine/retrieval/access-tracker.d.ts +1 -1
- package/dist/internal/engine/retrieval/retriever.d.ts +1 -1
- package/dist/internal/engine/retrieval/retriever.js +1 -1
- package/dist/internal/engine/security/memory-scope-policy.js +1 -1
- package/dist/internal/engine/security/scopes.js +2 -2
- package/dist/internal/engine/shared/memory-kind-policy.d.ts +1 -1
- package/dist/internal/engine/shared/paths.d.ts +2 -2
- package/dist/internal/engine/shared/types.d.ts +2 -2
- package/dist/internal/engine/shared/types.js +1 -1
- package/dist/internal/engine/shared/utils.d.ts +1 -1
- package/dist/internal/engine/shared/utils.js +2 -3
- package/dist/internal/engine/telemetry/memory-telemetry-api.js +2 -2
- package/dist/internal/engine/telemetry/observe-ledger.d.ts +1 -1
- package/dist/internal/engine/telemetry/observe-ledger.js +46 -19
- package/dist/internal/model/llm-client.d.ts +2 -2
- package/dist/internal/model/llm-client.js +1 -1
- package/dist/internal/model/llm-mode-routing.d.ts +1 -1
- package/dist/internal/model/llm-mode-routing.js +1 -1
- package/dist/internal/store/atomic-memory-cutover-sql.js +1 -1
- package/dist/internal/store/connection.js +1 -1
- package/dist/internal/store/maintenance.d.ts +2 -2
- package/dist/internal/store/maintenance.js +444 -40
- package/dist/internal/store/memory-kinds-cutover-migrator.js +1 -1
- package/dist/internal/store/migrations.js +1 -1
- package/dist/internal/store/store.d.ts +2 -2
- package/dist/internal/store/store.js +1 -1
- package/dist/{llm-client-RqmOEQkg.d.ts → llm-client-BTaUVmDe.d.ts} +1 -1
- package/dist/{llm-client-fVrzPcyz.js → llm-client-ConEyQEs.js} +51 -12
- package/dist/{log-site-catalog.generated-By86ZBRB.js → log-site-catalog.generated-Dzgj9o5c.js} +230 -195
- package/dist/log-site-catalog.json +1 -1
- package/dist/{memory-kind-policy-BOGb8thm.d.ts → memory-kind-policy-ClQEXeOL.d.ts} +1 -1
- package/dist/{memory-metadata-codec-DcSqjbWR.d.ts → memory-metadata-codec-wVAuoKrG.d.ts} +1 -1
- package/dist/{memory-runtime-CbuNkL0G.js → memory-runtime-C8ZIW2WL.js} +495 -304
- package/dist/{memory-scope-policy-DICSCURA.js → memory-scope-policy--TiLZnrE.js} +2 -2
- package/dist/{memory-snapshot-C5BnJ2rO.d.ts → memory-snapshot-uTdxJnIh.d.ts} +2 -2
- package/dist/{memory-store-base-z593oJ4h.d.ts → memory-store-base-Bk2dOKED.d.ts} +5 -6
- package/dist/{memory-store-shared-DqpWJXZZ.js → memory-store-shared-CURizQIy.js} +1 -1
- package/dist/{memory-telemetry-receipts-YsxbwOAf.js → memory-telemetry-receipts-cjIQGwdp.js} +5 -1
- package/dist/{memory-temporality-classifier-SzlUCgTj.d.ts → memory-temporality-classifier-CcxfHYoT.d.ts} +1 -1
- package/dist/{memory-temporality-classifier-CeSOL2vq.js → memory-temporality-classifier-MBJyJdvB.js} +2 -2
- package/dist/{memory-tier-promoter-Z7jprFB7.d.ts → memory-tier-promoter-MkZPQ8u1.d.ts} +1 -1
- package/dist/memory-tool-dependencies-CWnD5mia.d.ts +14 -0
- package/dist/{memory-tool-dependencies-CnaGABQG.js → memory-tool-dependencies-DUMY8SwB.js} +3 -3
- package/dist/{model-call-table-BZJQkbKX.js → model-call-table-BE97f37s.js} +6 -1
- package/dist/{observable-embedder-DjhGxHx2.d.ts → observable-embedder-CGr3Zejf.d.ts} +1 -1
- package/dist/{observable-llm-client-CLJLMmwA.d.ts → observable-llm-client-CXUA7Gi3.d.ts} +3 -3
- package/dist/{observable-memory-store-B48HV2NK.d.ts → observable-memory-store-BwwKcUzf.d.ts} +4 -4
- package/dist/{observable-retriever-CAdHncKh.d.ts → observable-retriever-bJbG9WtJ.d.ts} +5 -5
- package/dist/paths-DmmPxD_v.d.ts +1 -0
- package/dist/{plugin-config-schema-VBSPGEG3.d.ts → plugin-config-schema-BrhMvnXJ.d.ts} +3 -1
- package/dist/{plugin-config-schema-hIfZTELX.js → plugin-config-schema-Di-uKTP0.js} +1 -1
- package/dist/{profile-CQNCtVIu.d.ts → profile-CF5oDjR7.d.ts} +1 -1
- package/dist/{profile-section-writer-joJEIYhF.js → profile-section-writer-CmNa95uN.js} +3 -3
- package/dist/{reflection-command-hooks-Cl0ShtbF.d.ts → reflection-command-hooks-CM2mWb69.d.ts} +4 -4
- package/dist/{reflection-command-hooks-CG8n1GNK.js → reflection-command-hooks-CnTj8cKL.js} +3 -3
- package/dist/{reflection-deps-B0_cPBZt.d.ts → reflection-deps-B5I0nYZS.d.ts} +2 -2
- package/dist/{reflection-embedded-generator-C5kA0T0v.d.ts → reflection-embedded-generator-CogQIBcG.d.ts} +3 -3
- package/dist/{reflection-embedded-generator-D342_5o_.js → reflection-embedded-generator-DR525Moy.js} +1 -1
- package/dist/{reflection-injection-hooks-CtgcjLGx.d.ts → reflection-injection-hooks-BnbfZqpj.d.ts} +4 -4
- package/dist/{reflection-lifecycle-hooks-Pd7P9wya.d.ts → reflection-lifecycle-hooks-DMDhtidj.d.ts} +3 -3
- package/dist/{rem-batch-executor-ryxxkzQp.js → rem-batch-executor-DbV8Y-B-.js} +1 -1
- package/dist/{rem-consumer-retrieval-CR0dtcHR.js → rem-consumer-retrieval-CDMSCJYI.js} +2 -1
- package/dist/{rem-trigger-Dz_Jrr9p.js → rem-trigger-BSrGyG0s.js} +1666 -1010
- package/dist/{retriever-BXQmJMh0.js → retriever-Bzz6H8Mn.js} +2 -2
- package/dist/{retriever-DQdyGlkr.d.ts → retriever-DyxY59Lg.d.ts} +10 -8
- package/dist/{runtime-audit-log-BCeujlEp.js → runtime-audit-log-DK6xAYxh.js} +103 -2
- package/dist/{runtime-audit-log-Bn3JLBPj.d.ts → runtime-audit-log-DdhLlTxi.d.ts} +4 -2
- package/dist/{scopes-CSOn6zdd.js → scopes-a4Kly9n7.js} +1 -1
- package/dist/{server-DFLEPkQA.js → server-CjwHZY1P.js} +17 -320
- package/dist/sidecar/main.js +11 -4
- package/dist/sno-station-mem-runtime-dependencies-BZjUo6Jr.d.ts +31 -0
- package/dist/{sno-station-mem-runtime-dependencies-CY-XDHxU.js → sno-station-mem-runtime-dependencies-DlvM6mL7.js} +9 -9
- package/dist/{store-DKndKig1.d.ts → store-BDIAl2cc.d.ts} +1 -1
- package/dist/{store-CUk-jEGA.js → store-BQxkgJTX.js} +31 -23
- package/dist/{strategy-hook-runner-BSk_o6Yt.d.ts → strategy-hook-runner-DT9emgCZ.d.ts} +7 -7
- package/dist/{strategy-hook-runner-CWApiUZW.js → strategy-hook-runner-SvyyGBXw.js} +1 -1
- package/dist/{types-Del9J7UB.d.ts → types-Ae3a8562.d.ts} +1 -1
- package/dist/{utils-Ctb9aevJ.d.ts → utils-CDw2ttQf.d.ts} +2 -3
- package/package.json +2 -2
- package/settings.default.json +4 -4
- package/dist/memory-tool-dependencies-CJNppsKh.d.ts +0 -14
- package/dist/paths-D3dEsoE4.d.ts +0 -1
- package/dist/sno-station-mem-runtime-dependencies-8CRIkARK.d.ts +0 -31
- package/dist/{unplaced-candidate-migration-CbQHzcEM.js → unplaced-candidate-migration-BCcdQkcx.js} +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { $ as FIXED_IDX_MEMORY_ACTIVE_TASK_EVIDENCE_INSTANCE, $n as MAX_CHUNK_FETCH_LIMIT, $t as FIXED_VEC_MEMORY, At as FIXED_MEMORY_PROVIDER_AGENT_MAPPINGS, B as FIXED_EXTERNAL_VALUE_51, C as getSnoStationMemStateDir, Cn as CHUNK_TARGET_TOKENS, Cr as LOCAL_EMBEDDING_CACHE_DIR_DEFAULT, Ct as FIXED_MEMORY_CHUNKS_MEM_IDX, D as settingsToPluginConfig, Dn as DEFAULT_RECALL_LIFECYCLE, Dr as ensureModelDownloaded, Dt as FIXED_MEMORY_MEMORIES_FACT_ID_UPDATE_GUARD, En as DEFAULT_IMPORTANCE, Er as LocalEmbedProvider, Et as FIXED_MEMORY_MEMORIES_FACT_ID_INSERT_GUARD, Fn as EMBEDDER_DIM, Ft as FIXED_MEMORY_SNO_EXTRACT_CHAT, G as FIXED_EXTERNAL_VALUE_56, Gt as FIXED_PROTOCOL_VALUE_69, H as FIXED_EXTERNAL_VALUE_53, Hn as HEAD_EXTRACT_OVERLAP_DROP_RATIO, In as EMBEDDER_MODEL_DEFAULT, J as FIXED_EXTERNAL_VALUE_62, Jn as LIGHTWEIGHT_FUSION_WEIGHT, K as FIXED_EXTERNAL_VALUE_57, Kn as INTRA_MEMORY_COSINE_THRESHOLD, Kt as FIXED_PROTOCOL_VALUE_73, Ln as EMBEDDER_PROVIDER_DEFAULT, Lt as FIXED_MEMORY_TASK_LIFECYCLE_COMMANDS, Mn as DEFAULT_RERANK_TIMEOUT_MS, Mt as FIXED_MEMORY_PROVIDER_PROJECT_MAPPINGS, N as observeAgentId, O as MODEL_CALLS, Ot as FIXED_MEMORY_MIGRATION_MARKERS, Pn as DEFAULT_VECTOR_WEIGHT, Pr as REM_SIDECAR_TOKEN_HEADER, Q as FIXED_IDX_MEMORY_ACTIVE_TASK_CURRENT_REVISION, Rn as EVAL_QA_TRACES_FILENAME, Rt as FIXED_MEMORY_UNPLACED_CANDIDATES, Sn as CHUNK_OVERLAP_TOKENS, Sr as CachedEmbeddingProvider, St as FIXED_MEMORY_CHUNKS_MEM_FACET_IDX, T as readSettings, Tn as DEFAULT_BM25_WEIGHT, Tt as FIXED_MEMORY_MEMORIES, U as FIXED_EXTERNAL_VALUE_54, Un as HEAD_EXTRACT_TOKEN_BUDGET, V as FIXED_EXTERNAL_VALUE_52, Vn as HEAD_EXTRACT_MIN_CONTENT_TOKENS, W as FIXED_EXTERNAL_VALUE_55, Wn as IMPORTANCE_WEIGHT_BASE, X as FIXED_EXTERNAL_VALUE_9, Y as FIXED_EXTERNAL_VALUE_8, Yn as LIGHTWEIGHT_RERANK_PENALTY, Z as FIXED_IDX_MEMORY, _n as BONUS_TOTAL_INVARIANT, _t as FIXED_MEMORY_CHUNKS_AD, a as REM_MODEL_OUTPUT_TOKEN_CAP, ar as MULTI_HIT_BONUS_CAP, at as FIXED_IDX_MEMORY_MEMORIES_PROJECT, bn as CHUNK_MAX_TOKENS, br as experimentMmrDisabled, bt as FIXED_MEMORY_CHUNKS_FTS, cr as RECENCY_WEIGHT, ct as FIXED_IDX_MEMORY_MEMORIES_PROJECT_TIMESTAMP, d as getRemDiscoveryPath, dr as RERANK_BLEND_CROSS, dt as FIXED_MEMORY_ACTIVE_TASK_INSTANCES, en as FIXED_VEC_MEMORY_CHUNKS, er as MAX_LIST_LIMIT, et as FIXED_IDX_MEMORY_ACTIVE_TASK_INSTANCES_PROJECTION, fr as RERANK_BLEND_VECTOR, ft as FIXED_MEMORY_ACTIVE_TASK_MIGRATION_EVIDENCE, g as readRemOperationalConfig, gt as FIXED_MEMORY_CHUNKS, hr as TIME_DECAY_FLOOR, ht as FIXED_MEMORY_ACTIVE_TASK_TRANSITIONS, in as PERSISTED_PROVIDER_SYSTEM, ir as MMR_LAMBDA, it as FIXED_IDX_MEMORY_MEMORIES_LANE_PROJECT, jn as DEFAULT_RERANK_MODEL, jt as FIXED_MEMORY_PROVIDER_PROJECT_AGENTS, k as modelCallDestination, kt as FIXED_MEMORY_PROFILE_RECOVERY_ENTRIES, ln as ADJACENCY_BONUS_CAP, lt as FIXED_MEMORY, mt as FIXED_MEMORY_ACTIVE_TASK_REVISIONS, nn as PERSISTED_CONTENT_HASH_V1, nt as FIXED_IDX_MEMORY_MEMORIES_CONTENT_HASH, o as REM_RUN_PATH, on as llmRoutingConfigSchema, or as MULTI_HIT_BONUS_PER_HIT, ot as FIXED_IDX_MEMORY_MEMORIES_PROJECT_CONTENT_HASH, pr as RETRIEVAL_STORAGE_CHUNK_PROFILE, pt as FIXED_MEMORY_ACTIVE_TASK_MIGRATION_MANIFESTS, q as FIXED_EXTERNAL_VALUE_58, qn as LIGHTWEIGHT_COSINE_WEIGHT, r as REM_CORRELATION_ID_HEADER, rn as PERSISTED_CONTENT_HASH_V3, rt as FIXED_IDX_MEMORY_MEMORIES_FACT_ID, s as REM_SIDECAR_HOST, sn as SUPPORTED_LOCALES, st as FIXED_IDX_MEMORY_MEMORIES_PROJECT_FACT_KEY_ACTIVE, tn as PERSISTED_CANDIDATE_HASH_V1, tt as FIXED_IDX_MEMORY_MEMORIES_CATEGORY, un as ADJACENCY_BONUS_PER_PAIR, ut as FIXED_MEMORY_ACTIVE_TASK_EVIDENCE, vn as CACHE_TTL_MS, vt as FIXED_MEMORY_CHUNKS_AI, wn as CHUNK_TOKENIZER_MODE, wr as LOCAL_EMBEDDING_MODEL, wt as FIXED_MEMORY_EXTRACTION_TIMESTAMPS, xn as CHUNK_MIN_TOKENS, xt as FIXED_MEMORY_CHUNKS_MEMORY_ID_IDX, yn as CHUNKING_VERSION$1, yr as experimentCandidatePoolOverride, yt as FIXED_MEMORY_CHUNKS_AU, z as FIXED_EXTERNAL_VALUE_49 } from "./config-
|
|
1
|
+
import { $ as FIXED_IDX_MEMORY_ACTIVE_TASK_EVIDENCE_INSTANCE, $n as MAX_CHUNK_FETCH_LIMIT, $t as FIXED_VEC_MEMORY, At as FIXED_MEMORY_PROVIDER_AGENT_MAPPINGS, B as FIXED_EXTERNAL_VALUE_51, C as getSnoStationMemStateDir, Cn as CHUNK_TARGET_TOKENS, Cr as LOCAL_EMBEDDING_CACHE_DIR_DEFAULT, Ct as FIXED_MEMORY_CHUNKS_MEM_IDX, D as settingsToPluginConfig, Dn as DEFAULT_RECALL_LIFECYCLE, Dr as ensureModelDownloaded, Dt as FIXED_MEMORY_MEMORIES_FACT_ID_UPDATE_GUARD, En as DEFAULT_IMPORTANCE, Er as LocalEmbedProvider, Et as FIXED_MEMORY_MEMORIES_FACT_ID_INSERT_GUARD, Fn as EMBEDDER_DIM, Ft as FIXED_MEMORY_SNO_EXTRACT_CHAT, G as FIXED_EXTERNAL_VALUE_56, Gt as FIXED_PROTOCOL_VALUE_69, H as FIXED_EXTERNAL_VALUE_53, Hn as HEAD_EXTRACT_OVERLAP_DROP_RATIO, In as EMBEDDER_MODEL_DEFAULT, J as FIXED_EXTERNAL_VALUE_62, Jn as LIGHTWEIGHT_FUSION_WEIGHT, K as FIXED_EXTERNAL_VALUE_57, Kn as INTRA_MEMORY_COSINE_THRESHOLD, Kt as FIXED_PROTOCOL_VALUE_73, Ln as EMBEDDER_PROVIDER_DEFAULT, Lt as FIXED_MEMORY_TASK_LIFECYCLE_COMMANDS, Mn as DEFAULT_RERANK_TIMEOUT_MS, Mt as FIXED_MEMORY_PROVIDER_PROJECT_MAPPINGS, N as observeAgentId, O as MODEL_CALLS, Ot as FIXED_MEMORY_MIGRATION_MARKERS, Pn as DEFAULT_VECTOR_WEIGHT, Pr as REM_SIDECAR_TOKEN_HEADER, Q as FIXED_IDX_MEMORY_ACTIVE_TASK_CURRENT_REVISION, Rn as EVAL_QA_TRACES_FILENAME, Rt as FIXED_MEMORY_UNPLACED_CANDIDATES, Sn as CHUNK_OVERLAP_TOKENS, Sr as CachedEmbeddingProvider, St as FIXED_MEMORY_CHUNKS_MEM_FACET_IDX, T as readSettings, Tn as DEFAULT_BM25_WEIGHT, Tt as FIXED_MEMORY_MEMORIES, U as FIXED_EXTERNAL_VALUE_54, Un as HEAD_EXTRACT_TOKEN_BUDGET, V as FIXED_EXTERNAL_VALUE_52, Vn as HEAD_EXTRACT_MIN_CONTENT_TOKENS, W as FIXED_EXTERNAL_VALUE_55, Wn as IMPORTANCE_WEIGHT_BASE, X as FIXED_EXTERNAL_VALUE_9, Y as FIXED_EXTERNAL_VALUE_8, Yn as LIGHTWEIGHT_RERANK_PENALTY, Z as FIXED_IDX_MEMORY, _n as BONUS_TOTAL_INVARIANT, _t as FIXED_MEMORY_CHUNKS_AD, a as REM_MODEL_OUTPUT_TOKEN_CAP, ar as MULTI_HIT_BONUS_CAP, at as FIXED_IDX_MEMORY_MEMORIES_PROJECT, bn as CHUNK_MAX_TOKENS, br as experimentMmrDisabled, bt as FIXED_MEMORY_CHUNKS_FTS, cr as RECENCY_WEIGHT, ct as FIXED_IDX_MEMORY_MEMORIES_PROJECT_TIMESTAMP, d as getRemDiscoveryPath, dr as RERANK_BLEND_CROSS, dt as FIXED_MEMORY_ACTIVE_TASK_INSTANCES, en as FIXED_VEC_MEMORY_CHUNKS, er as MAX_LIST_LIMIT, et as FIXED_IDX_MEMORY_ACTIVE_TASK_INSTANCES_PROJECTION, fr as RERANK_BLEND_VECTOR, ft as FIXED_MEMORY_ACTIVE_TASK_MIGRATION_EVIDENCE, g as readRemOperationalConfig, gt as FIXED_MEMORY_CHUNKS, hr as TIME_DECAY_FLOOR, ht as FIXED_MEMORY_ACTIVE_TASK_TRANSITIONS, in as PERSISTED_PROVIDER_SYSTEM, ir as MMR_LAMBDA, it as FIXED_IDX_MEMORY_MEMORIES_LANE_PROJECT, jn as DEFAULT_RERANK_MODEL, jt as FIXED_MEMORY_PROVIDER_PROJECT_AGENTS, k as modelCallDestination, kt as FIXED_MEMORY_PROFILE_RECOVERY_ENTRIES, ln as ADJACENCY_BONUS_CAP, lt as FIXED_MEMORY, mt as FIXED_MEMORY_ACTIVE_TASK_REVISIONS, nn as PERSISTED_CONTENT_HASH_V1, nt as FIXED_IDX_MEMORY_MEMORIES_CONTENT_HASH, o as REM_RUN_PATH, on as llmRoutingConfigSchema, or as MULTI_HIT_BONUS_PER_HIT, ot as FIXED_IDX_MEMORY_MEMORIES_PROJECT_CONTENT_HASH, pr as RETRIEVAL_STORAGE_CHUNK_PROFILE, pt as FIXED_MEMORY_ACTIVE_TASK_MIGRATION_MANIFESTS, q as FIXED_EXTERNAL_VALUE_58, qn as LIGHTWEIGHT_COSINE_WEIGHT, r as REM_CORRELATION_ID_HEADER, rn as PERSISTED_CONTENT_HASH_V3, rt as FIXED_IDX_MEMORY_MEMORIES_FACT_ID, s as REM_SIDECAR_HOST, sn as SUPPORTED_LOCALES, st as FIXED_IDX_MEMORY_MEMORIES_PROJECT_FACT_KEY_ACTIVE, tn as PERSISTED_CANDIDATE_HASH_V1, tt as FIXED_IDX_MEMORY_MEMORIES_CATEGORY, un as ADJACENCY_BONUS_PER_PAIR, ut as FIXED_MEMORY_ACTIVE_TASK_EVIDENCE, vn as CACHE_TTL_MS, vt as FIXED_MEMORY_CHUNKS_AI, wn as CHUNK_TOKENIZER_MODE, wr as LOCAL_EMBEDDING_MODEL, wt as FIXED_MEMORY_EXTRACTION_TIMESTAMPS, xn as CHUNK_MIN_TOKENS, xt as FIXED_MEMORY_CHUNKS_MEMORY_ID_IDX, yn as CHUNKING_VERSION$1, yr as experimentCandidatePoolOverride, yt as FIXED_MEMORY_CHUNKS_AU, z as FIXED_EXTERNAL_VALUE_49 } from "./config-C7LzSWhG.js";
|
|
2
2
|
import { createLogger, createLogger as createLogger$1, currentLogContext, privateLogReference, withLogContext } from "@snoai/utils/logger";
|
|
3
3
|
import path, { dirname, join, resolve } from "node:path";
|
|
4
|
-
import { appendFileSync, createReadStream, existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { appendFileSync, closeSync, createReadStream, existsSync, fstatSync, fsyncSync, ftruncateSync, mkdirSync, openSync, readFileSync, readSync, realpathSync, renameSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
|
|
5
5
|
import { arch, availableParallelism, platform } from "node:os";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { LRUCache } from "lru-cache";
|
|
@@ -13,10 +13,11 @@ import { getDek, openEncryptedDb, openEncryptedDbReadonly } from "@snoai/sqlite-
|
|
|
13
13
|
import { appendFile, mkdir, open, readFile, rename, rm } from "node:fs/promises";
|
|
14
14
|
import { Temporal } from "@js-temporal/polyfill";
|
|
15
15
|
import { redactForStorage, sanitizeContentIngress, sanitizeStructuredJsonForStorage } from "@snoai/content-sanitizer";
|
|
16
|
+
import { createInterface } from "node:readline";
|
|
17
|
+
import { StringDecoder } from "node:string_decoder";
|
|
16
18
|
import { CallPipeline, ConfigRegistryManager, KeyPool, loadLlmixTrustManifest, registryRootOptionsFromTrustManifest } from "@snoai/llmix";
|
|
17
19
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
18
20
|
import { Mutex } from "async-mutex";
|
|
19
|
-
import { createInterface } from "node:readline";
|
|
20
21
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
21
22
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
|
22
23
|
import { index, integer, primaryKey, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
@@ -37,7 +38,7 @@ var __exportAll = (all, no_symbols) => {
|
|
|
37
38
|
};
|
|
38
39
|
//#endregion
|
|
39
40
|
//#region src/engine/telemetry/observe-ledger.ts
|
|
40
|
-
const log$
|
|
41
|
+
const log$24 = createLogger("sno-station-mem:observe-ledger");
|
|
41
42
|
const rowSchema = z.object({
|
|
42
43
|
ts_ms: z.number().int().nonnegative(),
|
|
43
44
|
agent_id: z.string().transform(observeAgentId).optional(),
|
|
@@ -54,7 +55,7 @@ function observeLedgerSyncedPath(profileDir) {
|
|
|
54
55
|
}
|
|
55
56
|
function warn(observe, message) {
|
|
56
57
|
if (observe.logger) observe.logger.warn(message);
|
|
57
|
-
else log$
|
|
58
|
+
else log$24.warn(message, void 0, {
|
|
58
59
|
event_name: "observe.ledger.failed",
|
|
59
60
|
file: "packages/memory/src/engine/telemetry/observe-ledger.ts",
|
|
60
61
|
function: "forwardObserveLedger",
|
|
@@ -79,25 +80,52 @@ function consumeRows(profileDir, observe, batchSize) {
|
|
|
79
80
|
rows,
|
|
80
81
|
offset
|
|
81
82
|
};
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
offset
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
rows.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
83
|
+
const fd = openSync(path, "r+");
|
|
84
|
+
try {
|
|
85
|
+
const size = fstatSync(fd).size;
|
|
86
|
+
if (offset > size) {
|
|
87
|
+
warn(observe, `offset beyond ledger: ${offset} > ${size}`);
|
|
88
|
+
offset = 0;
|
|
89
|
+
writeFileSync(syncedPath, "0", { mode: 384 });
|
|
90
|
+
}
|
|
91
|
+
const buffer = Buffer.alloc(65536);
|
|
92
|
+
let position = offset;
|
|
93
|
+
let pending = Buffer.alloc(0);
|
|
94
|
+
while (rows.length < batchSize && position < size) {
|
|
95
|
+
const count = readSync(fd, buffer, 0, Math.min(buffer.length, size - position), position);
|
|
96
|
+
if (count === 0) break;
|
|
97
|
+
position += count;
|
|
98
|
+
pending = Buffer.concat([pending, buffer.subarray(0, count)]);
|
|
99
|
+
let consumed = 0;
|
|
100
|
+
while (rows.length < batchSize) {
|
|
101
|
+
const newline = pending.indexOf(10, consumed);
|
|
102
|
+
if (newline === -1) break;
|
|
103
|
+
const end = offset + newline - consumed + 1;
|
|
104
|
+
rows.push({
|
|
105
|
+
start: offset,
|
|
106
|
+
end,
|
|
107
|
+
text: pending.toString("utf8", consumed, newline)
|
|
108
|
+
});
|
|
109
|
+
offset = end;
|
|
110
|
+
consumed = newline + 1;
|
|
111
|
+
}
|
|
112
|
+
pending = pending.subarray(consumed);
|
|
113
|
+
}
|
|
114
|
+
if (offset >= 1048576 && size - offset <= 65536) {
|
|
115
|
+
let source = offset;
|
|
116
|
+
for (let end = fstatSync(fd).size; source < end; end = fstatSync(fd).size) while (source < end) {
|
|
117
|
+
const count = readSync(fd, buffer, 0, Math.min(buffer.length, end - source), source);
|
|
118
|
+
if (count === 0) break;
|
|
119
|
+
writeSync(fd, buffer, 0, count, source - offset);
|
|
120
|
+
source += count;
|
|
121
|
+
}
|
|
122
|
+
ftruncateSync(fd, source - offset);
|
|
123
|
+
offset = 0;
|
|
124
|
+
}
|
|
125
|
+
if (rows.length) writeFileSync(syncedPath, String(offset), { mode: 384 });
|
|
126
|
+
} finally {
|
|
127
|
+
closeSync(fd);
|
|
99
128
|
}
|
|
100
|
-
if (rows.length) writeFileSync(syncedPath, String(offset), { mode: 384 });
|
|
101
129
|
return {
|
|
102
130
|
rows,
|
|
103
131
|
offset
|
|
@@ -141,7 +169,7 @@ async function forwardObserveLedgerUntilIdle(options) {
|
|
|
141
169
|
//#endregion
|
|
142
170
|
//#region src/engine/operation-cancellation.ts
|
|
143
171
|
const operations = new AsyncLocalStorage();
|
|
144
|
-
const log$
|
|
172
|
+
const log$23 = createLogger("sno-station-mem:cancellation");
|
|
145
173
|
/** Carries cancellation through the existing nested extraction and reflection writers. */
|
|
146
174
|
async function withMemoryOperation(method, signal, run) {
|
|
147
175
|
const operation = {
|
|
@@ -157,7 +185,7 @@ async function withMemoryOperation(method, signal, run) {
|
|
|
157
185
|
signal?.throwIfAborted();
|
|
158
186
|
return result;
|
|
159
187
|
} finally {
|
|
160
|
-
if (signal?.aborted) log$
|
|
188
|
+
if (signal?.aborted) log$23.error("memory.operation.aborted", {
|
|
161
189
|
method,
|
|
162
190
|
outcome: "aborted",
|
|
163
191
|
writes: operation.writes
|
|
@@ -5828,6 +5856,18 @@ function bytesToF32(bytes) {
|
|
|
5828
5856
|
function stableHash(text) {
|
|
5829
5857
|
return createHash("sha256").update(text).digest("hex");
|
|
5830
5858
|
}
|
|
5859
|
+
/**
|
|
5860
|
+
* Return a short, secret-redacted, whitespace-collapsed preview of `text` for
|
|
5861
|
+
* audit logs. Previews are enabled by default and pass through `redactSecrets`
|
|
5862
|
+
* before they are persisted in audit.jsonl on disk.
|
|
5863
|
+
*/
|
|
5864
|
+
function debugContentPreview(text, enabled, maxChars = 80) {
|
|
5865
|
+
if (!enabled) return void 0;
|
|
5866
|
+
if (!text) return void 0;
|
|
5867
|
+
const collapsed = redactSecrets(text).replace(/\s+/g, " ").trim();
|
|
5868
|
+
if (collapsed.length === 0) return void 0;
|
|
5869
|
+
return collapsed.length > maxChars ? `${collapsed.slice(0, maxChars)}...` : collapsed;
|
|
5870
|
+
}
|
|
5831
5871
|
z.object({ source: z.object({ commit: z.string().min(1) }) });
|
|
5832
5872
|
//#endregion
|
|
5833
5873
|
//#region config/skin-defaults.ts
|
|
@@ -5847,165 +5887,675 @@ const CODING_SKIN_CHILD_DEADLINE_MS = 11e4;
|
|
|
5847
5887
|
const CODING_SKIN_SESSION_QUERY = "standing decisions, open tasks, conventions and known pitfalls for this repository";
|
|
5848
5888
|
const CODING_SKIN_LEDGER_MAX_CHARS = 12e3;
|
|
5849
5889
|
//#endregion
|
|
5850
|
-
//#region src/
|
|
5851
|
-
const
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
"
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5890
|
+
//#region src/engine/operations/jsonl-lines.ts
|
|
5891
|
+
const log$22 = createLogger("sno-station-mem:jsonl");
|
|
5892
|
+
/** Preserve complete records without materializing an unbounded log as one string. */
|
|
5893
|
+
async function* readJsonlLines(file) {
|
|
5894
|
+
const stream = createReadStream(file, { encoding: "utf8" });
|
|
5895
|
+
const lines = createInterface({
|
|
5896
|
+
input: stream,
|
|
5897
|
+
crlfDelay: Infinity
|
|
5898
|
+
});
|
|
5899
|
+
try {
|
|
5900
|
+
for await (const line of lines) if (line.trim()) yield line;
|
|
5901
|
+
} catch (error) {
|
|
5902
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
|
|
5903
|
+
log$22.error("jsonl.read.failed", {
|
|
5904
|
+
file,
|
|
5905
|
+
error
|
|
5906
|
+
}, {
|
|
5907
|
+
event_name: "memory.jsonl.read.failed",
|
|
5908
|
+
file: "packages/memory/src/engine/operations/jsonl-lines.ts",
|
|
5909
|
+
function: "readJsonlLines",
|
|
5910
|
+
site_id: "memory.jsonl.read.failed"
|
|
5911
|
+
});
|
|
5912
|
+
} finally {
|
|
5913
|
+
lines.close();
|
|
5914
|
+
stream.destroy();
|
|
5915
|
+
}
|
|
5859
5916
|
}
|
|
5860
|
-
|
|
5861
|
-
|
|
5917
|
+
//#endregion
|
|
5918
|
+
//#region src/engine/operations/runtime-audit-log.ts
|
|
5919
|
+
/** @file runtime-audit-log.ts
|
|
5920
|
+
* @purpose Records audit events for operational visibility and safety-sensitive actions.
|
|
5921
|
+
* @boundary Plugin runtime events and filesystem-backed audit persistence.
|
|
5922
|
+
* @see sno-station-mem-plugin-runtime.ts, memory-tool-registration.ts, errors.ts.
|
|
5923
|
+
*/
|
|
5924
|
+
const auditWriteQueues = /* @__PURE__ */ new Map();
|
|
5925
|
+
const memoryAuditScope = new AsyncLocalStorage();
|
|
5926
|
+
const mutationAttemptScope = new AsyncLocalStorage();
|
|
5927
|
+
const mutationRecoveryPromises = /* @__PURE__ */ new Map();
|
|
5928
|
+
const MEMORY_AUDIT_COMMON_KEYS = [
|
|
5929
|
+
"operation",
|
|
5930
|
+
"audit_phase",
|
|
5931
|
+
"audit_operation_id"
|
|
5932
|
+
];
|
|
5933
|
+
const MUTATION_AUDIT_DETAIL_KEYS = [
|
|
5934
|
+
"mutation_writer",
|
|
5935
|
+
"mutation_subject",
|
|
5936
|
+
"mutation_outcome",
|
|
5937
|
+
"refusal_reason"
|
|
5938
|
+
];
|
|
5939
|
+
const MEMORY_AUDIT_ALLOWED_DETAIL_KEYS = {
|
|
5940
|
+
memory_injected: /* @__PURE__ */ new Set([
|
|
5941
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
5942
|
+
"scope",
|
|
5943
|
+
"category",
|
|
5944
|
+
"lane",
|
|
5945
|
+
"count",
|
|
5946
|
+
"memory_ids",
|
|
5947
|
+
"write_outcome",
|
|
5948
|
+
"created_count",
|
|
5949
|
+
"existing_count"
|
|
5950
|
+
]),
|
|
5951
|
+
memory_searched: /* @__PURE__ */ new Set([
|
|
5952
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
5953
|
+
"scope",
|
|
5954
|
+
"query_kind",
|
|
5955
|
+
"requested_count",
|
|
5956
|
+
"result_count",
|
|
5957
|
+
"memory_ids"
|
|
5958
|
+
]),
|
|
5959
|
+
memory_read: /* @__PURE__ */ new Set([
|
|
5960
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
5961
|
+
"scope",
|
|
5962
|
+
"requested_count",
|
|
5963
|
+
"result_count",
|
|
5964
|
+
"memory_ids",
|
|
5965
|
+
"requested_fact_id",
|
|
5966
|
+
"resolved_fact_id",
|
|
5967
|
+
"fact_ids",
|
|
5968
|
+
"found",
|
|
5969
|
+
"outcome"
|
|
5970
|
+
]),
|
|
5971
|
+
memory_updated: /* @__PURE__ */ new Set([
|
|
5972
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
5973
|
+
...MUTATION_AUDIT_DETAIL_KEYS,
|
|
5974
|
+
"scope",
|
|
5975
|
+
"requested_count",
|
|
5976
|
+
"result_count",
|
|
5977
|
+
"memory_ids",
|
|
5978
|
+
"outcome",
|
|
5979
|
+
"migration_status",
|
|
5980
|
+
"rewritten_rows",
|
|
5981
|
+
"checked_rows"
|
|
5982
|
+
]),
|
|
5983
|
+
memory_superseded: /* @__PURE__ */ new Set([
|
|
5984
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
5985
|
+
...MUTATION_AUDIT_DETAIL_KEYS,
|
|
5986
|
+
"scope",
|
|
5987
|
+
"replacement_memory_id",
|
|
5988
|
+
"closed_memory_ids",
|
|
5989
|
+
"write_outcome"
|
|
5990
|
+
]),
|
|
5991
|
+
memory_deleted: /* @__PURE__ */ new Set([
|
|
5992
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
5993
|
+
"scope",
|
|
5994
|
+
"deleted_memory_ids",
|
|
5995
|
+
"delete_reason",
|
|
5996
|
+
"count",
|
|
5997
|
+
"outcome",
|
|
5998
|
+
"removed_files"
|
|
5999
|
+
]),
|
|
6000
|
+
memory_purged: /* @__PURE__ */ new Set([
|
|
6001
|
+
...MEMORY_AUDIT_COMMON_KEYS,
|
|
6002
|
+
"target_fact_id",
|
|
6003
|
+
"purged_fact_ids",
|
|
6004
|
+
"failed_fact_ids",
|
|
6005
|
+
"status",
|
|
6006
|
+
"blocked_reason"
|
|
6007
|
+
])
|
|
6008
|
+
};
|
|
6009
|
+
/** Implements enqueue audit write as the local audit log state operation. */
|
|
6010
|
+
function enqueueAuditWrite(auditPath, line) {
|
|
6011
|
+
const next = (auditWriteQueues.get(auditPath) ?? Promise.resolve(true)).catch(() => void 0).then(async () => {
|
|
6012
|
+
mkdirSync(path.dirname(auditPath), { recursive: true });
|
|
6013
|
+
await appendFile(auditPath, line);
|
|
6014
|
+
compactAuditLog(auditPath);
|
|
6015
|
+
return true;
|
|
6016
|
+
}).catch((error) => {
|
|
6017
|
+
createLogger("sno-station-mem:audit").error("Audit entry append failed", { error }, {
|
|
6018
|
+
event_name: "memory.audit.append.failed",
|
|
6019
|
+
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
6020
|
+
function: "enqueueAuditWrite",
|
|
6021
|
+
site_id: "memory.audit.append.failed"
|
|
6022
|
+
});
|
|
6023
|
+
return false;
|
|
6024
|
+
});
|
|
6025
|
+
auditWriteQueues.set(auditPath, next);
|
|
6026
|
+
next.finally(() => {
|
|
6027
|
+
if (auditWriteQueues.get(auditPath) === next) auditWriteQueues.delete(auditPath);
|
|
6028
|
+
});
|
|
6029
|
+
return next;
|
|
5862
6030
|
}
|
|
5863
|
-
|
|
5864
|
-
|
|
6031
|
+
/** Returns audit path from audit log state state without side effects. */
|
|
6032
|
+
function getAuditPath(stateDir) {
|
|
6033
|
+
return path.join(stateDir, "audit.jsonl");
|
|
5865
6034
|
}
|
|
5866
|
-
|
|
5867
|
-
|
|
6035
|
+
/** Retain the recent tail and two days of REM replay evidence when the audit exceeds 16 MiB. */
|
|
6036
|
+
function compactAuditLog(auditPath) {
|
|
6037
|
+
try {
|
|
6038
|
+
compactAuditFile(auditPath);
|
|
6039
|
+
} catch (error) {
|
|
6040
|
+
createLogger("sno-station-mem:audit").error("Audit compaction failed; existing records retained", { error }, {
|
|
6041
|
+
event_name: "memory.audit.compact.failed",
|
|
6042
|
+
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
6043
|
+
function: "compactAuditLog",
|
|
6044
|
+
site_id: "memory.audit.compact.failed"
|
|
6045
|
+
});
|
|
6046
|
+
}
|
|
5868
6047
|
}
|
|
5869
|
-
function
|
|
5870
|
-
|
|
6048
|
+
function compactAuditFile(auditPath) {
|
|
6049
|
+
if (!existsSync(auditPath) || statSync(auditPath).size <= 16777216) return;
|
|
6050
|
+
const fd = openSync(auditPath, "r");
|
|
6051
|
+
const retained = [];
|
|
6052
|
+
const openAttempts = /* @__PURE__ */ new Map();
|
|
6053
|
+
let tail;
|
|
6054
|
+
let size = 0;
|
|
6055
|
+
try {
|
|
6056
|
+
size = statSync(auditPath).size;
|
|
6057
|
+
const tailStart = Math.max(0, size - 8388608);
|
|
6058
|
+
tail = Buffer.alloc(size - tailStart);
|
|
6059
|
+
const tailRead = readSync(fd, tail, 0, tail.length, tailStart);
|
|
6060
|
+
tail = tail.subarray(0, tailRead);
|
|
6061
|
+
const newline = tail.indexOf(10);
|
|
6062
|
+
const prefixEnd = newline < 0 ? size : tailStart + newline + 1;
|
|
6063
|
+
tail = newline < 0 ? Buffer.alloc(0) : tail.subarray(newline + 1);
|
|
6064
|
+
const cutoff = (/* @__PURE__ */ new Date(Date.now() - 1728e5)).toISOString();
|
|
6065
|
+
const buffer = Buffer.alloc(65536);
|
|
6066
|
+
let position = 0;
|
|
6067
|
+
let pending = "";
|
|
6068
|
+
let linePosition = 0;
|
|
6069
|
+
const decoder = new StringDecoder("utf8");
|
|
6070
|
+
let oversized = false;
|
|
6071
|
+
while (position < prefixEnd) {
|
|
6072
|
+
const count = readSync(fd, buffer, 0, Math.min(buffer.length, prefixEnd - position), position);
|
|
6073
|
+
if (count === 0) break;
|
|
6074
|
+
position += count;
|
|
6075
|
+
const parts = (pending + decoder.write(buffer.subarray(0, count))).split("\n");
|
|
6076
|
+
pending = parts.pop() ?? "";
|
|
6077
|
+
for (const line of parts) {
|
|
6078
|
+
if (oversized) {
|
|
6079
|
+
oversized = false;
|
|
6080
|
+
linePosition++;
|
|
6081
|
+
continue;
|
|
6082
|
+
}
|
|
6083
|
+
try {
|
|
6084
|
+
const entry = JSON.parse(line);
|
|
6085
|
+
if (isRecord$1(entry) && typeof entry["event"] === "string" && entry["event"].startsWith("rem_") && typeof entry["timestamp"] === "string" && entry["timestamp"] >= cutoff && (entry["event"] !== "rem_trigger_evaluated" || isRecord$1(entry["details"]) && entry["details"]["row"] === "dispatch")) retained.push({
|
|
6086
|
+
position: linePosition,
|
|
6087
|
+
line: line + "\n"
|
|
6088
|
+
});
|
|
6089
|
+
if (isRecord$1(entry) && isRecord$1(entry["details"])) {
|
|
6090
|
+
const id = entry["details"]["audit_operation_id"];
|
|
6091
|
+
if (typeof id === "string" && entry["decision"] === "mutation-attempt-open") openAttempts.set(id, {
|
|
6092
|
+
position: linePosition,
|
|
6093
|
+
line: line + "\n"
|
|
6094
|
+
});
|
|
6095
|
+
if (typeof id === "string" && entry["details"]["mutation_outcome"] !== void 0) openAttempts.delete(id);
|
|
6096
|
+
}
|
|
6097
|
+
} catch {}
|
|
6098
|
+
linePosition++;
|
|
6099
|
+
}
|
|
6100
|
+
if (pending.length > 1048576 || oversized) {
|
|
6101
|
+
pending = "";
|
|
6102
|
+
oversized = true;
|
|
6103
|
+
}
|
|
6104
|
+
}
|
|
6105
|
+
} finally {
|
|
6106
|
+
closeSync(fd);
|
|
6107
|
+
}
|
|
6108
|
+
const temporary = `${auditPath}.${randomUUID()}.tmp`;
|
|
6109
|
+
try {
|
|
6110
|
+
writeFileSync(temporary, [...retained, ...openAttempts.values()].sort((a, b) => a.position - b.position).map((record) => record.line).join(""), { mode: 384 });
|
|
6111
|
+
appendFileSync(temporary, tail);
|
|
6112
|
+
const output = openSync(temporary, "r+");
|
|
6113
|
+
try {
|
|
6114
|
+
fsyncSync(output);
|
|
6115
|
+
} finally {
|
|
6116
|
+
closeSync(output);
|
|
6117
|
+
}
|
|
6118
|
+
const grown = statSync(auditPath).size;
|
|
6119
|
+
if (grown > size) {
|
|
6120
|
+
const late = Buffer.alloc(grown - size);
|
|
6121
|
+
const source = openSync(auditPath, "r");
|
|
6122
|
+
try {
|
|
6123
|
+
appendFileSync(temporary, late.subarray(0, readSync(source, late, 0, late.length, size)));
|
|
6124
|
+
} finally {
|
|
6125
|
+
closeSync(source);
|
|
6126
|
+
}
|
|
6127
|
+
}
|
|
6128
|
+
renameSync(temporary, auditPath);
|
|
6129
|
+
} finally {
|
|
6130
|
+
rmSync(temporary, { force: true });
|
|
6131
|
+
}
|
|
5871
6132
|
}
|
|
5872
|
-
function
|
|
5873
|
-
|
|
5874
|
-
if (isCredentialExpiredMessage(message)) return "credential-expired";
|
|
5875
|
-
if (status === 401 || status === 403 || isAuthMessage(message)) return "auth";
|
|
5876
|
-
if (isExhaustedMessage(message)) return "exhausted";
|
|
5877
|
-
if (status === 429 || isThrottleMessage(message)) return "throttle";
|
|
5878
|
-
if (status !== void 0 && (status === 404 || status === 408 || status >= 500)) return "transport";
|
|
5879
|
-
return "unknown";
|
|
6133
|
+
function isRecord$1(value) {
|
|
6134
|
+
return typeof value === "object" && value !== null;
|
|
5880
6135
|
}
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
6136
|
+
function isMemoryAuditEvent(event) {
|
|
6137
|
+
return event.startsWith("memory_");
|
|
6138
|
+
}
|
|
6139
|
+
function redactAuditValue(value) {
|
|
6140
|
+
if (typeof value === "string") return redactSecrets(value);
|
|
6141
|
+
if (Array.isArray(value)) return value.map(redactAuditValue);
|
|
6142
|
+
if (!isRecord$1(value)) return value;
|
|
6143
|
+
const redacted = {};
|
|
6144
|
+
for (const [key, child] of Object.entries(value)) redacted[key] = redactAuditValue(child);
|
|
6145
|
+
return redacted;
|
|
6146
|
+
}
|
|
6147
|
+
function prepareAuditEntry(entry) {
|
|
6148
|
+
if (!isMemoryAuditEvent(entry.event) || entry.details?.["audit_phase"] === void 0) return entry;
|
|
6149
|
+
const allowed = MEMORY_AUDIT_ALLOWED_DETAIL_KEYS[entry.event];
|
|
6150
|
+
const details = {};
|
|
6151
|
+
for (const [key, value] of Object.entries(entry.details)) if (allowed.has(key)) details[key] = value;
|
|
6152
|
+
else createLogger("sno-station-mem:audit").error("memory.audit.detail.unknown", {
|
|
6153
|
+
event: entry.event,
|
|
6154
|
+
key
|
|
6155
|
+
}, {
|
|
6156
|
+
event_name: "memory.audit.detail.unknown",
|
|
6157
|
+
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
6158
|
+
function: "prepareAuditEntry",
|
|
6159
|
+
site_id: "memory.audit.detail.unknown"
|
|
6160
|
+
});
|
|
5885
6161
|
return {
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
6162
|
+
...entry,
|
|
6163
|
+
...entry.scope === void 0 ? {} : { scope: redactSecrets(entry.scope) },
|
|
6164
|
+
details: redactAuditValue(details)
|
|
5889
6165
|
};
|
|
5890
6166
|
}
|
|
5891
|
-
|
|
5892
|
-
|
|
6167
|
+
/** Persists audit entry through the single audit log state write path. */
|
|
6168
|
+
function appendAuditEntry(stateDir, entry) {
|
|
6169
|
+
const auditPath = getAuditPath(stateDir);
|
|
6170
|
+
const prepared = prepareAuditEntry(entry);
|
|
6171
|
+
enqueueAuditWrite(auditPath, `${JSON.stringify({
|
|
6172
|
+
...prepared,
|
|
6173
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6174
|
+
})}\n`);
|
|
5893
6175
|
}
|
|
5894
|
-
|
|
5895
|
-
|
|
6176
|
+
/** Waits for the audit append; failures are logged without blocking the operation. */
|
|
6177
|
+
async function appendAuditEntryStrict(stateDir, entry) {
|
|
6178
|
+
const auditPath = getAuditPath(stateDir);
|
|
6179
|
+
const prepared = prepareAuditEntry(entry);
|
|
6180
|
+
return enqueueAuditWrite(auditPath, `${JSON.stringify({
|
|
6181
|
+
...prepared,
|
|
6182
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6183
|
+
})}\n`);
|
|
5896
6184
|
}
|
|
5897
|
-
/**
|
|
5898
|
-
function
|
|
5899
|
-
|
|
6185
|
+
/** Attempts a synchronous audit append and logs a failure. */
|
|
6186
|
+
function appendAuditEntrySync(stateDir, entry) {
|
|
6187
|
+
const auditPath = getAuditPath(stateDir);
|
|
6188
|
+
const prepared = prepareAuditEntry(entry);
|
|
6189
|
+
try {
|
|
6190
|
+
mkdirSync(path.dirname(auditPath), { recursive: true });
|
|
6191
|
+
appendFileSync(auditPath, `${JSON.stringify({
|
|
6192
|
+
...prepared,
|
|
6193
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6194
|
+
})}\n`);
|
|
6195
|
+
compactAuditLog(auditPath);
|
|
6196
|
+
} catch (error) {
|
|
6197
|
+
createLogger("sno-station-mem:audit").error("memory.audit.append.failed", { error }, {
|
|
6198
|
+
event_name: "memory.audit.append.failed",
|
|
6199
|
+
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
6200
|
+
function: "appendAuditEntrySync",
|
|
6201
|
+
site_id: "memory.audit.sync.failed"
|
|
6202
|
+
});
|
|
6203
|
+
}
|
|
5900
6204
|
}
|
|
5901
|
-
|
|
5902
|
-
//#region src/model/llmix-registry.ts
|
|
5903
|
-
/** @file llmix-registry.ts
|
|
5904
|
-
* @purpose Loads the bundled signed LLMIx registry for sno-station-mem.
|
|
5905
|
-
* @boundary Trust-anchor verification and package-relative asset resolution only.
|
|
5906
|
-
*/
|
|
5907
|
-
const SNO_STATION_MEM_RELEASE_ANCHOR_URL = FIXED_EXTERNAL_VALUE_8;
|
|
5908
|
-
const SNO_STATION_MEM_RELEASE_KEY_ID = FIXED_EXTERNAL_VALUE_9;
|
|
5909
|
-
const SNO_STATION_MEM_RELEASE_ANCHOR_ATTEMPTS = 2;
|
|
5910
|
-
const SNO_STATION_MEM_RELEASE_ANCHOR_RETRY_DELAY_MS = 50;
|
|
5911
|
-
const ALLOWED_HTTP_ENDPOINT_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
5912
|
-
function parsePresetId(preset) {
|
|
5913
|
-
const [module, presetName] = preset.split("/");
|
|
5914
|
-
if (!module || !presetName) throw new Error(`sno-station-mem llm-client: invalid LLMIx preset id "${preset}"`);
|
|
6205
|
+
function memoryAuditDetails(operation, phase, operationId, details) {
|
|
5915
6206
|
return {
|
|
5916
|
-
|
|
5917
|
-
|
|
6207
|
+
...details,
|
|
6208
|
+
operation,
|
|
6209
|
+
audit_phase: phase,
|
|
6210
|
+
audit_operation_id: operationId
|
|
5918
6211
|
};
|
|
5919
6212
|
}
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
6213
|
+
/** Records the start and outcome without using audit availability as admission. */
|
|
6214
|
+
async function runWithMemoryAudit(options) {
|
|
6215
|
+
if (memoryAuditScope.getStore()) return options.run();
|
|
6216
|
+
return memoryAuditScope.run(true, async () => {
|
|
6217
|
+
const operationId = randomUUID();
|
|
6218
|
+
await appendAuditEntryStrict(options.stateDir, {
|
|
6219
|
+
event: options.event,
|
|
6220
|
+
scope: options.scope,
|
|
6221
|
+
resultStatus: "partial",
|
|
6222
|
+
details: memoryAuditDetails(options.operation, "started", operationId, options.startedDetails)
|
|
6223
|
+
});
|
|
6224
|
+
let result;
|
|
6225
|
+
try {
|
|
6226
|
+
result = await options.run();
|
|
6227
|
+
} catch (error) {
|
|
6228
|
+
await appendAuditEntryStrict(options.stateDir, {
|
|
6229
|
+
event: options.event,
|
|
6230
|
+
scope: options.scope,
|
|
6231
|
+
resultStatus: "error",
|
|
6232
|
+
errorCode: "memory_operation_failed",
|
|
6233
|
+
details: memoryAuditDetails(options.operation, "failed", operationId, options.startedDetails)
|
|
6234
|
+
});
|
|
6235
|
+
throw error;
|
|
6236
|
+
}
|
|
6237
|
+
await appendAuditEntryStrict(options.stateDir, {
|
|
6238
|
+
event: options.event,
|
|
6239
|
+
scope: options.scope,
|
|
6240
|
+
resultStatus: "ok",
|
|
6241
|
+
details: memoryAuditDetails(options.operation, "completed", operationId, options.completedDetails(result))
|
|
6242
|
+
});
|
|
6243
|
+
return result;
|
|
6244
|
+
});
|
|
5923
6245
|
}
|
|
5924
|
-
function
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
6246
|
+
async function readOpenMutationAttempts(stateDir) {
|
|
6247
|
+
const auditPath = getAuditPath(stateDir);
|
|
6248
|
+
if (!existsSync(auditPath)) return [];
|
|
6249
|
+
const openAttempts = /* @__PURE__ */ new Map();
|
|
6250
|
+
for await (const line of readJsonlLines(auditPath)) {
|
|
6251
|
+
if (!line.trim()) continue;
|
|
6252
|
+
let parsed;
|
|
6253
|
+
try {
|
|
6254
|
+
parsed = JSON.parse(line);
|
|
6255
|
+
} catch {
|
|
6256
|
+
continue;
|
|
6257
|
+
}
|
|
6258
|
+
if (!isRecord$1(parsed) || !isRecord$1(parsed["details"])) continue;
|
|
6259
|
+
const event = parsed["event"];
|
|
6260
|
+
const decision = parsed["decision"];
|
|
6261
|
+
const details = parsed["details"];
|
|
6262
|
+
const attemptId = details["audit_operation_id"];
|
|
6263
|
+
if (typeof attemptId !== "string") continue;
|
|
6264
|
+
if (details["mutation_outcome"] !== void 0) {
|
|
6265
|
+
openAttempts.delete(attemptId);
|
|
6266
|
+
continue;
|
|
6267
|
+
}
|
|
6268
|
+
if (decision !== "mutation-attempt-open" || details["audit_phase"] !== "started" || event !== "memory_updated" && event !== "memory_superseded" || typeof details["operation"] !== "string" || details["mutation_writer"] !== "profile-section" && details["mutation_writer"] !== "task-lifecycle" && details["mutation_writer"] !== "legacy-profile-refusal") continue;
|
|
6269
|
+
openAttempts.set(attemptId, {
|
|
6270
|
+
event,
|
|
6271
|
+
operation: details["operation"],
|
|
6272
|
+
attemptId,
|
|
6273
|
+
writer: details["mutation_writer"],
|
|
6274
|
+
...typeof details["mutation_subject"] === "string" ? { subject: details["mutation_subject"] } : {}
|
|
6275
|
+
});
|
|
5930
6276
|
}
|
|
5931
|
-
|
|
5932
|
-
if (parsed.protocol === "https:" && parsed.hostname.toLowerCase() === "api.openai.com") throw new Error("sno-station-mem llm-client: direct api.openai.com transport is forbidden; use local ccproxy or an explicit custom endpoint");
|
|
5933
|
-
if (!preservePath) return parsed.origin;
|
|
5934
|
-
const base = parsed.toString();
|
|
5935
|
-
return base.endsWith("/") ? base : `${base}/`;
|
|
5936
|
-
}
|
|
5937
|
-
function packageRootFromImportMeta() {
|
|
5938
|
-
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
5939
|
-
const bundledRoot = path.resolve(moduleDir, "..");
|
|
5940
|
-
return [bundledRoot, path.resolve(moduleDir, "../..")].find(hasBundledRegistryAssets) ?? bundledRoot;
|
|
5941
|
-
}
|
|
5942
|
-
function hasBundledRegistryAssets(packageRoot) {
|
|
5943
|
-
return existsSync(path.join(packageRoot, "config", "llm", "current.json")) && existsSync(path.join(packageRoot, "config", "llm.trust.json"));
|
|
6277
|
+
return [...openAttempts.values()];
|
|
5944
6278
|
}
|
|
5945
|
-
function
|
|
5946
|
-
const registryDir = path.join(packageRoot, "config", "llm");
|
|
5947
|
-
const trustManifestPath = path.join(packageRoot, "config", "llm.trust.json");
|
|
5948
|
-
if (!hasBundledRegistryAssets(packageRoot)) throw new Error("sno-station-mem LLMIx registry assets are missing from the installed package");
|
|
6279
|
+
function mutationAuditDetails(input) {
|
|
5949
6280
|
return {
|
|
5950
|
-
|
|
5951
|
-
|
|
6281
|
+
operation: input.operation,
|
|
6282
|
+
audit_phase: input.phase,
|
|
6283
|
+
audit_operation_id: input.attemptId,
|
|
6284
|
+
mutation_writer: input.writer,
|
|
6285
|
+
...input.subject === void 0 ? {} : { mutation_subject: input.subject },
|
|
6286
|
+
...input.outcome === void 0 ? {} : { mutation_outcome: input.outcome },
|
|
6287
|
+
...input.refusalReason === void 0 ? {} : { refusal_reason: input.refusalReason }
|
|
5952
6288
|
};
|
|
5953
6289
|
}
|
|
5954
|
-
function
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
if (!isJsonObject(document) || document.id !== "did:web:www.sno.ai") return null;
|
|
5959
|
-
const methods = document.verificationMethod;
|
|
5960
|
-
if (!Array.isArray(methods)) return null;
|
|
5961
|
-
for (const method of methods) {
|
|
5962
|
-
if (!isJsonObject(method) || method.id !== SNO_STATION_MEM_RELEASE_KEY_ID) continue;
|
|
5963
|
-
const jwk = method.publicKeyJwk;
|
|
5964
|
-
if (isJsonObject(jwk) && jwk.kty === "OKP" && jwk.crv === "Ed25519" && typeof jwk.x === "string") return jwk;
|
|
5965
|
-
}
|
|
5966
|
-
return null;
|
|
6290
|
+
function mutationAuditStatus(outcome) {
|
|
6291
|
+
if (outcome === "failed" || outcome === "interrupted-unknown") return "error";
|
|
6292
|
+
if (outcome.startsWith("refused-")) return "skipped";
|
|
6293
|
+
return "ok";
|
|
5967
6294
|
}
|
|
5968
|
-
function
|
|
5969
|
-
const
|
|
5970
|
-
|
|
5971
|
-
|
|
6295
|
+
async function closeMutationAttempt(stateDir, attempt, completion) {
|
|
6296
|
+
const phase = completion.outcome === "failed" || completion.outcome === "interrupted-unknown" ? "failed" : "completed";
|
|
6297
|
+
await appendAuditEntryStrict(stateDir, {
|
|
6298
|
+
event: attempt.event,
|
|
6299
|
+
resultStatus: mutationAuditStatus(completion.outcome),
|
|
6300
|
+
decision: completion.outcome,
|
|
6301
|
+
details: mutationAuditDetails({
|
|
6302
|
+
operation: attempt.operation,
|
|
6303
|
+
phase,
|
|
6304
|
+
attemptId: attempt.attemptId,
|
|
6305
|
+
writer: attempt.writer,
|
|
6306
|
+
...attempt.subject === void 0 ? {} : { subject: attempt.subject },
|
|
6307
|
+
outcome: completion.outcome,
|
|
6308
|
+
...completion.refusalReason === void 0 ? {} : { refusalReason: completion.refusalReason }
|
|
6309
|
+
})
|
|
5972
6310
|
});
|
|
5973
|
-
return verify(null, Buffer$1.from(paeBytes), publicKey, Buffer$1.from(signature, "base64"));
|
|
5974
|
-
}
|
|
5975
|
-
function releaseAnchorFailureMessage(error) {
|
|
5976
|
-
if (!isJsonObject(error) || !isJsonObject(error.details)) return null;
|
|
5977
|
-
const cause = error.details.cause;
|
|
5978
|
-
if (typeof cause !== "string") return null;
|
|
5979
|
-
return cause.includes("sno-station-mem LLMIx release anchor fetch") ? cause : null;
|
|
5980
6311
|
}
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
const
|
|
5985
|
-
|
|
5986
|
-
controller.abort();
|
|
5987
|
-
reject(/* @__PURE__ */ new Error(`sno-station-mem LLMIx release anchor fetch timed out after ${timeoutMs}ms`));
|
|
5988
|
-
}, timeoutMs);
|
|
5989
|
-
});
|
|
5990
|
-
try {
|
|
5991
|
-
return await Promise.race([fetchImpl(SNO_STATION_MEM_RELEASE_ANCHOR_URL, { signal: controller.signal }), timeoutPromise]);
|
|
5992
|
-
} finally {
|
|
5993
|
-
if (timeout !== void 0) clearTimeout(timeout);
|
|
5994
|
-
}
|
|
6312
|
+
/** Closes mutation attempts whose process stopped before a terminal audit record was written. */
|
|
6313
|
+
async function recoverInterruptedMutationAttempts(stateDir) {
|
|
6314
|
+
const attempts = await readOpenMutationAttempts(stateDir);
|
|
6315
|
+
for (const attempt of attempts) await closeMutationAttempt(stateDir, attempt, { outcome: "interrupted-unknown" });
|
|
6316
|
+
return attempts.map((attempt) => attempt.attemptId);
|
|
5995
6317
|
}
|
|
5996
|
-
function
|
|
5997
|
-
|
|
6318
|
+
function ensureMutationRecovery(stateDir) {
|
|
6319
|
+
const existing = mutationRecoveryPromises.get(stateDir);
|
|
6320
|
+
if (existing) return existing;
|
|
6321
|
+
const recovery = recoverInterruptedMutationAttempts(stateDir).then(() => void 0);
|
|
6322
|
+
mutationRecoveryPromises.set(stateDir, recovery);
|
|
6323
|
+
return recovery;
|
|
5998
6324
|
}
|
|
5999
|
-
|
|
6000
|
-
|
|
6325
|
+
/** Runs one mutation under a durable open record and exactly one terminal outcome. */
|
|
6326
|
+
async function runWithMutationAttempt(options) {
|
|
6327
|
+
if (mutationAttemptScope.getStore()) return options.run();
|
|
6328
|
+
await ensureMutationRecovery(options.stateDir);
|
|
6329
|
+
const attempt = {
|
|
6330
|
+
event: options.event,
|
|
6331
|
+
operation: options.operation,
|
|
6332
|
+
attemptId: randomUUID(),
|
|
6333
|
+
writer: options.writer,
|
|
6334
|
+
...options.subject === void 0 ? {} : { subject: options.subject }
|
|
6335
|
+
};
|
|
6336
|
+
return mutationAttemptScope.run(attempt.attemptId, async () => {
|
|
6337
|
+
await appendAuditEntryStrict(options.stateDir, {
|
|
6338
|
+
event: options.event,
|
|
6339
|
+
resultStatus: "partial",
|
|
6340
|
+
decision: "mutation-attempt-open",
|
|
6341
|
+
details: mutationAuditDetails({
|
|
6342
|
+
operation: attempt.operation,
|
|
6343
|
+
phase: "started",
|
|
6344
|
+
attemptId: attempt.attemptId,
|
|
6345
|
+
writer: attempt.writer,
|
|
6346
|
+
...attempt.subject === void 0 ? {} : { subject: attempt.subject }
|
|
6347
|
+
})
|
|
6348
|
+
});
|
|
6349
|
+
let result;
|
|
6001
6350
|
try {
|
|
6002
|
-
|
|
6003
|
-
if (attempt === SNO_STATION_MEM_RELEASE_ANCHOR_ATTEMPTS || !isTransientAnchorResponse(response)) return response;
|
|
6351
|
+
result = await options.run();
|
|
6004
6352
|
} catch (error) {
|
|
6005
|
-
|
|
6353
|
+
await closeMutationAttempt(options.stateDir, attempt, options.failedOutcome?.(error) ?? { outcome: "failed" });
|
|
6354
|
+
throw error;
|
|
6006
6355
|
}
|
|
6007
|
-
await
|
|
6008
|
-
|
|
6356
|
+
await closeMutationAttempt(options.stateDir, attempt, options.completedOutcome(result));
|
|
6357
|
+
return result;
|
|
6358
|
+
});
|
|
6359
|
+
}
|
|
6360
|
+
/** Returns the durable identifier owned by the current mutation boundary. */
|
|
6361
|
+
function currentMutationAttemptId() {
|
|
6362
|
+
const attemptId = mutationAttemptScope.getStore();
|
|
6363
|
+
if (!attemptId) throw new Error("mutation attempt identifier requested outside a mutation boundary");
|
|
6364
|
+
return attemptId;
|
|
6365
|
+
}
|
|
6366
|
+
/** Runs a synchronous memory operation only after its durable start record is persisted. */
|
|
6367
|
+
function runWithMemoryAuditSync(options) {
|
|
6368
|
+
if (memoryAuditScope.getStore()) return options.run();
|
|
6369
|
+
return memoryAuditScope.run(true, () => {
|
|
6370
|
+
const operationId = randomUUID();
|
|
6371
|
+
appendAuditEntrySync(options.stateDir, {
|
|
6372
|
+
event: options.event,
|
|
6373
|
+
scope: options.scope,
|
|
6374
|
+
resultStatus: "partial",
|
|
6375
|
+
details: memoryAuditDetails(options.operation, "started", operationId, options.startedDetails)
|
|
6376
|
+
});
|
|
6377
|
+
let result;
|
|
6378
|
+
try {
|
|
6379
|
+
result = options.run();
|
|
6380
|
+
} catch (error) {
|
|
6381
|
+
appendAuditEntrySync(options.stateDir, {
|
|
6382
|
+
event: options.event,
|
|
6383
|
+
scope: options.scope,
|
|
6384
|
+
resultStatus: "error",
|
|
6385
|
+
errorCode: "memory_operation_failed",
|
|
6386
|
+
details: memoryAuditDetails(options.operation, "failed", operationId, options.startedDetails)
|
|
6387
|
+
});
|
|
6388
|
+
throw error;
|
|
6389
|
+
}
|
|
6390
|
+
appendAuditEntrySync(options.stateDir, {
|
|
6391
|
+
event: options.event,
|
|
6392
|
+
scope: options.scope,
|
|
6393
|
+
resultStatus: "ok",
|
|
6394
|
+
details: memoryAuditDetails(options.operation, "completed", operationId, options.completedDetails(result))
|
|
6395
|
+
});
|
|
6396
|
+
return result;
|
|
6397
|
+
});
|
|
6398
|
+
}
|
|
6399
|
+
//#endregion
|
|
6400
|
+
//#region src/model/llm-failure.ts
|
|
6401
|
+
const CREDENTIAL_CATEGORIES = /* @__PURE__ */ new Set([
|
|
6402
|
+
"auth",
|
|
6403
|
+
"credential-expired",
|
|
6404
|
+
"credential-revoked"
|
|
6405
|
+
]);
|
|
6406
|
+
const TERMINAL_CATEGORIES = /* @__PURE__ */ new Set([...CREDENTIAL_CATEGORIES, "exhausted"]);
|
|
6407
|
+
function isCredentialRevokedMessage(message) {
|
|
6408
|
+
return /oauth token refresh failed for openai:.*\binvalid_grant\b.*\btoken revoked\b/i.test(message);
|
|
6409
|
+
}
|
|
6410
|
+
function isCredentialExpiredMessage(message) {
|
|
6411
|
+
return /\bexpired access token\b/i.test(message);
|
|
6412
|
+
}
|
|
6413
|
+
function isAuthMessage(message) {
|
|
6414
|
+
return /\b(?:401|403)\b/.test(message) || /unauthori[sz]ed/i.test(message) || /no api key found/i.test(message) || /(?:invalid|incorrect) api[- ]?key/i.test(message) || /(?:invalid|expired) (?:access |oauth )?token/i.test(message) || /(?:api[- ]?key|token).*(?:invalid|expired|rejected)/i.test(message) || /credential (?:is )?(?:invalid|expired|rejected)/i.test(message) || /no (?:valid )?credential (?:found|available|configured)/i.test(message) || /re-?authenticate/i.test(message) || /no authentication configured/i.test(message);
|
|
6415
|
+
}
|
|
6416
|
+
function isExhaustedMessage(message) {
|
|
6417
|
+
return /you(?:'|’)ve reached your codex subscription usage limit/i.test(message);
|
|
6418
|
+
}
|
|
6419
|
+
function isThrottleMessage(message) {
|
|
6420
|
+
return /\b429\b/.test(message) || /rate.?limit/i.test(message) || /quota/i.test(message);
|
|
6421
|
+
}
|
|
6422
|
+
function categoryOf(status, message) {
|
|
6423
|
+
if (isCredentialRevokedMessage(message)) return "credential-revoked";
|
|
6424
|
+
if (isCredentialExpiredMessage(message)) return "credential-expired";
|
|
6425
|
+
if (status === 401 || status === 403 || isAuthMessage(message)) return "auth";
|
|
6426
|
+
if (isExhaustedMessage(message)) return "exhausted";
|
|
6427
|
+
if (status === 429 || isThrottleMessage(message)) return "throttle";
|
|
6428
|
+
if (status !== void 0 && (status === 404 || status === 408 || status >= 500)) return "transport";
|
|
6429
|
+
return "unknown";
|
|
6430
|
+
}
|
|
6431
|
+
/** Classifies one failed model call from whatever the transport surfaced: a status, a message, or both. */
|
|
6432
|
+
function classifyLlmFailure(input) {
|
|
6433
|
+
const category = categoryOf(input.status, input.message ?? "");
|
|
6434
|
+
const terminal = TERMINAL_CATEGORIES.has(category);
|
|
6435
|
+
return {
|
|
6436
|
+
category,
|
|
6437
|
+
terminal,
|
|
6438
|
+
endpointRefused: terminal || input.status === 404 || input.status === 503
|
|
6439
|
+
};
|
|
6440
|
+
}
|
|
6441
|
+
function isCredentialFailure(category) {
|
|
6442
|
+
return CREDENTIAL_CATEGORIES.has(category);
|
|
6443
|
+
}
|
|
6444
|
+
function isTerminalLlmFailure$1(category) {
|
|
6445
|
+
return TERMINAL_CATEGORIES.has(category);
|
|
6446
|
+
}
|
|
6447
|
+
/** A status worth one more attempt against the same endpoint. */
|
|
6448
|
+
function isTransientLlmStatus(status) {
|
|
6449
|
+
return status === 408 || status === 429 || status >= 500;
|
|
6450
|
+
}
|
|
6451
|
+
//#endregion
|
|
6452
|
+
//#region src/model/llmix-registry.ts
|
|
6453
|
+
/** @file llmix-registry.ts
|
|
6454
|
+
* @purpose Loads the bundled signed LLMIx registry for sno-station-mem.
|
|
6455
|
+
* @boundary Trust-anchor verification and package-relative asset resolution only.
|
|
6456
|
+
*/
|
|
6457
|
+
const SNO_STATION_MEM_RELEASE_ANCHOR_URL = FIXED_EXTERNAL_VALUE_8;
|
|
6458
|
+
const SNO_STATION_MEM_RELEASE_KEY_ID = FIXED_EXTERNAL_VALUE_9;
|
|
6459
|
+
const SNO_STATION_MEM_RELEASE_ANCHOR_ATTEMPTS = 2;
|
|
6460
|
+
const SNO_STATION_MEM_RELEASE_ANCHOR_RETRY_DELAY_MS = 50;
|
|
6461
|
+
const ALLOWED_HTTP_ENDPOINT_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
|
|
6462
|
+
function parsePresetId(preset) {
|
|
6463
|
+
const [module, presetName] = preset.split("/");
|
|
6464
|
+
if (!module || !presetName) throw new Error(`sno-station-mem llm-client: invalid LLMIx preset id "${preset}"`);
|
|
6465
|
+
return {
|
|
6466
|
+
module,
|
|
6467
|
+
preset: presetName
|
|
6468
|
+
};
|
|
6469
|
+
}
|
|
6470
|
+
function assertSupportedProvider(provider) {
|
|
6471
|
+
if (provider === "openai" || provider === "openrouter" || provider === "sno-gpu") return provider;
|
|
6472
|
+
throw new Error(`sno-station-mem llm-client: unsupported LLMIx provider "${provider}"`);
|
|
6473
|
+
}
|
|
6474
|
+
function resolveEndpointBase(baseSource, preservePath) {
|
|
6475
|
+
let parsed;
|
|
6476
|
+
try {
|
|
6477
|
+
parsed = new URL(baseSource);
|
|
6478
|
+
} catch {
|
|
6479
|
+
throw new Error(`sno-station-mem llm-client: invalid extraction.llm.baseURL "${baseSource}"`);
|
|
6480
|
+
}
|
|
6481
|
+
if (parsed.protocol !== "https:" && !ALLOWED_HTTP_ENDPOINT_HOSTS.has(parsed.hostname)) throw new Error("sno-station-mem llm-client: extraction.llm.baseURL must use https");
|
|
6482
|
+
if (parsed.protocol === "https:" && parsed.hostname.toLowerCase() === "api.openai.com") throw new Error("sno-station-mem llm-client: direct api.openai.com transport is forbidden; use local ccproxy or an explicit custom endpoint");
|
|
6483
|
+
if (!preservePath) return parsed.origin;
|
|
6484
|
+
const base = parsed.toString();
|
|
6485
|
+
return base.endsWith("/") ? base : `${base}/`;
|
|
6486
|
+
}
|
|
6487
|
+
function packageRootFromImportMeta() {
|
|
6488
|
+
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
6489
|
+
const bundledRoot = path.resolve(moduleDir, "..");
|
|
6490
|
+
return [bundledRoot, path.resolve(moduleDir, "../..")].find(hasBundledRegistryAssets) ?? bundledRoot;
|
|
6491
|
+
}
|
|
6492
|
+
function hasBundledRegistryAssets(packageRoot) {
|
|
6493
|
+
return existsSync(path.join(packageRoot, "config", "llm", "current.json")) && existsSync(path.join(packageRoot, "config", "llm.trust.json"));
|
|
6494
|
+
}
|
|
6495
|
+
function resolveBundledLlmixRegistryPaths(packageRoot = packageRootFromImportMeta()) {
|
|
6496
|
+
const registryDir = path.join(packageRoot, "config", "llm");
|
|
6497
|
+
const trustManifestPath = path.join(packageRoot, "config", "llm.trust.json");
|
|
6498
|
+
if (!hasBundledRegistryAssets(packageRoot)) throw new Error("sno-station-mem LLMIx registry assets are missing from the installed package");
|
|
6499
|
+
return {
|
|
6500
|
+
registryDir,
|
|
6501
|
+
trustManifestPath
|
|
6502
|
+
};
|
|
6503
|
+
}
|
|
6504
|
+
function isJsonObject(value) {
|
|
6505
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6506
|
+
}
|
|
6507
|
+
function readPublicKeyJwk(document) {
|
|
6508
|
+
if (!isJsonObject(document) || document.id !== "did:web:www.sno.ai") return null;
|
|
6509
|
+
const methods = document.verificationMethod;
|
|
6510
|
+
if (!Array.isArray(methods)) return null;
|
|
6511
|
+
for (const method of methods) {
|
|
6512
|
+
if (!isJsonObject(method) || method.id !== SNO_STATION_MEM_RELEASE_KEY_ID) continue;
|
|
6513
|
+
const jwk = method.publicKeyJwk;
|
|
6514
|
+
if (isJsonObject(jwk) && jwk.kty === "OKP" && jwk.crv === "Ed25519" && typeof jwk.x === "string") return jwk;
|
|
6515
|
+
}
|
|
6516
|
+
return null;
|
|
6517
|
+
}
|
|
6518
|
+
function verifyEd25519(jwk, paeBytes, signature) {
|
|
6519
|
+
const publicKey = createPublicKey({
|
|
6520
|
+
key: jwk,
|
|
6521
|
+
format: "jwk"
|
|
6522
|
+
});
|
|
6523
|
+
return verify(null, Buffer$1.from(paeBytes), publicKey, Buffer$1.from(signature, "base64"));
|
|
6524
|
+
}
|
|
6525
|
+
function releaseAnchorFailureMessage(error) {
|
|
6526
|
+
if (!isJsonObject(error) || !isJsonObject(error.details)) return null;
|
|
6527
|
+
const cause = error.details.cause;
|
|
6528
|
+
if (typeof cause !== "string") return null;
|
|
6529
|
+
return cause.includes("sno-station-mem LLMIx release anchor fetch") ? cause : null;
|
|
6530
|
+
}
|
|
6531
|
+
async function fetchReleaseAnchorOnce(fetchImpl, timeoutMs) {
|
|
6532
|
+
const controller = new AbortController();
|
|
6533
|
+
let timeout;
|
|
6534
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
6535
|
+
timeout = setTimeout(() => {
|
|
6536
|
+
controller.abort();
|
|
6537
|
+
reject(/* @__PURE__ */ new Error(`sno-station-mem LLMIx release anchor fetch timed out after ${timeoutMs}ms`));
|
|
6538
|
+
}, timeoutMs);
|
|
6539
|
+
});
|
|
6540
|
+
try {
|
|
6541
|
+
return await Promise.race([fetchImpl(SNO_STATION_MEM_RELEASE_ANCHOR_URL, { signal: controller.signal }), timeoutPromise]);
|
|
6542
|
+
} finally {
|
|
6543
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
6544
|
+
}
|
|
6545
|
+
}
|
|
6546
|
+
function isTransientAnchorResponse(response) {
|
|
6547
|
+
return isTransientLlmStatus(response.status);
|
|
6548
|
+
}
|
|
6549
|
+
async function fetchReleaseAnchor(fetchImpl, timeoutMs) {
|
|
6550
|
+
for (let attempt = 1; attempt <= SNO_STATION_MEM_RELEASE_ANCHOR_ATTEMPTS; attempt++) {
|
|
6551
|
+
try {
|
|
6552
|
+
const response = await fetchReleaseAnchorOnce(fetchImpl, timeoutMs);
|
|
6553
|
+
if (attempt === SNO_STATION_MEM_RELEASE_ANCHOR_ATTEMPTS || !isTransientAnchorResponse(response)) return response;
|
|
6554
|
+
} catch (error) {
|
|
6555
|
+
if (attempt === SNO_STATION_MEM_RELEASE_ANCHOR_ATTEMPTS) throw error;
|
|
6556
|
+
}
|
|
6557
|
+
await new Promise((resolve) => setTimeout(resolve, SNO_STATION_MEM_RELEASE_ANCHOR_RETRY_DELAY_MS));
|
|
6558
|
+
}
|
|
6009
6559
|
throw new Error("sno-station-mem LLMIx release anchor fetch exhausted");
|
|
6010
6560
|
}
|
|
6011
6561
|
function createSnoMemSnoStationMemDidWebVerifier(fetchImpl = globalThis.fetch, options = {}) {
|
|
@@ -6051,7 +6601,10 @@ function materializeBundledLlmixEndpoint(input) {
|
|
|
6051
6601
|
if (!path) throw new Error(`sno-station-mem llm-client: signed endpoint path missing from preset ${input.preset.preset}`);
|
|
6052
6602
|
return {
|
|
6053
6603
|
url: new URL(path, resolveEndpointBase(input.baseSource, input.preset.provider !== "sno-gpu")).toString(),
|
|
6054
|
-
preset: input.preset
|
|
6604
|
+
preset: input.preset.provider === "sno-gpu" && path === "/extract/profile/v1/completions" ? {
|
|
6605
|
+
...input.preset,
|
|
6606
|
+
model: "b-profile"
|
|
6607
|
+
} : input.preset
|
|
6055
6608
|
};
|
|
6056
6609
|
}
|
|
6057
6610
|
async function resolveConfiguredBundledLlmixEndpoint(input) {
|
|
@@ -6672,6 +7225,7 @@ function normalizeMemoryLlmRequest(value) {
|
|
|
6672
7225
|
const emptyReplyAttempts = raw.emptyReplyAttempts;
|
|
6673
7226
|
if (emptyReplyAttempts !== void 0 && (!Number.isInteger(emptyReplyAttempts) || Number(emptyReplyAttempts) < 1 || Number(emptyReplyAttempts) > EMPTY_REPLY_ATTEMPTS)) throw new Error(`sno-station-mem llm-client: emptyReplyAttempts must be an integer from 1 to ${EMPTY_REPLY_ATTEMPTS}`);
|
|
6674
7227
|
const enableThinking = raw.enableThinking;
|
|
7228
|
+
const takeProviderAttempt = raw.takeProviderAttempt;
|
|
6675
7229
|
if (enableThinking !== void 0 && typeof enableThinking !== "boolean") throw new Error("sno-station-mem llm-client: enableThinking must be a boolean");
|
|
6676
7230
|
const signal = raw.signal;
|
|
6677
7231
|
if (signal !== void 0 && !hasAbortSignalShape(signal)) throw new Error("sno-station-mem llm-client: signal must be an AbortSignal");
|
|
@@ -6685,6 +7239,7 @@ function normalizeMemoryLlmRequest(value) {
|
|
|
6685
7239
|
...maxTokens !== void 0 ? { maxTokens: Number(maxTokens) } : {},
|
|
6686
7240
|
...emptyReplyAttempts !== void 0 ? { emptyReplyAttempts: Number(emptyReplyAttempts) } : {},
|
|
6687
7241
|
...enableThinking !== void 0 ? { enableThinking } : {},
|
|
7242
|
+
...typeof takeProviderAttempt === "function" ? { takeProviderAttempt: () => takeProviderAttempt() === true } : {},
|
|
6688
7243
|
...requestId !== void 0 ? { requestId } : {},
|
|
6689
7244
|
...typeof raw.promptTemplateHash === "string" && /^[a-f0-9]{64}$/.test(raw.promptTemplateHash) ? { promptTemplateHash: raw.promptTemplateHash } : {},
|
|
6690
7245
|
...typeof raw.extractionSkillHash === "string" && /^[a-f0-9]{64}$/.test(raw.extractionSkillHash) ? { extractionSkillHash: raw.extractionSkillHash } : {},
|
|
@@ -6692,7 +7247,9 @@ function normalizeMemoryLlmRequest(value) {
|
|
|
6692
7247
|
};
|
|
6693
7248
|
}
|
|
6694
7249
|
function textSystemContent(request) {
|
|
6695
|
-
|
|
7250
|
+
const occasion = MODEL_CALLS[request.callId].occasion;
|
|
7251
|
+
if (occasion === "conflictAdjudication") return CONFLICT_ADJUDICATION_SYSTEM_CONTENT;
|
|
7252
|
+
return occasion === "memoryExtract" ? JSON_SYSTEM_CONTENT : REFLECTION_TEXT_SYSTEM_CONTENT;
|
|
6696
7253
|
}
|
|
6697
7254
|
/** Creates the LLM client facade with provider routing, key rotation, and JSON parsing. */
|
|
6698
7255
|
function createLlmClient(config) {
|
|
@@ -6722,8 +7279,29 @@ function createLlmClient(config) {
|
|
|
6722
7279
|
}
|
|
6723
7280
|
return endpointPromise;
|
|
6724
7281
|
};
|
|
7282
|
+
const providerBudget = new AsyncLocalStorage();
|
|
6725
7283
|
const pipeline = new CallPipeline({
|
|
6726
|
-
dispatch:
|
|
7284
|
+
dispatch: async (context) => {
|
|
7285
|
+
const budget = providerBudget.getStore();
|
|
7286
|
+
if (!budget) return callProvider(context);
|
|
7287
|
+
const timeoutMs = Math.floor(budget.deadlineMs - performance.now());
|
|
7288
|
+
if (timeoutMs <= 0) throw Object.assign(/* @__PURE__ */ new Error("Request deadline exhausted before provider dispatch"), { statusCode: 499 });
|
|
7289
|
+
if (budget.remaining <= 0 || budget.takeProviderAttempt && !budget.takeProviderAttempt()) throw Object.assign(/* @__PURE__ */ new Error("Provider request attempts exhausted"), { statusCode: 499 });
|
|
7290
|
+
budget.remaining -= 1;
|
|
7291
|
+
const providerConfig = context.config;
|
|
7292
|
+
const dispatchConfig = {
|
|
7293
|
+
...providerConfig,
|
|
7294
|
+
timeoutMs,
|
|
7295
|
+
...providerConfig.rawCompletion ? { rawCompletion: {
|
|
7296
|
+
...providerConfig.rawCompletion,
|
|
7297
|
+
timeoutMs
|
|
7298
|
+
} } : {}
|
|
7299
|
+
};
|
|
7300
|
+
return callProvider({
|
|
7301
|
+
...context,
|
|
7302
|
+
config: dispatchConfig
|
|
7303
|
+
});
|
|
7304
|
+
},
|
|
6727
7305
|
maxRetries: 2,
|
|
6728
7306
|
retryBaseMs: 100,
|
|
6729
7307
|
retryMaxDelayMs: 500,
|
|
@@ -6795,6 +7373,7 @@ function createLlmClient(config) {
|
|
|
6795
7373
|
if (transport === "agent-host-seam") {
|
|
6796
7374
|
const agentPort = config.agentPort;
|
|
6797
7375
|
if (!agentPort) throw new LlmClientTerminalError("transport", `sno-station-mem: llm-client [${request.callId}] AgentLlmPort is unavailable`);
|
|
7376
|
+
if (request.takeProviderAttempt && !request.takeProviderAttempt()) return null;
|
|
6798
7377
|
config.onTransportAttempt?.({
|
|
6799
7378
|
callId: request.callId,
|
|
6800
7379
|
destination,
|
|
@@ -7037,13 +7616,18 @@ function createLlmClient(config) {
|
|
|
7037
7616
|
* result is returned untouched — it means no call was made, not that the model said nothing.
|
|
7038
7617
|
*/
|
|
7039
7618
|
const requestContentRetryingEmpty = async (state, request, systemContent, deadlineMs, prompt = request.prompt) => {
|
|
7040
|
-
|
|
7619
|
+
const budget = {
|
|
7620
|
+
remaining: EMPTY_REPLY_ATTEMPTS,
|
|
7621
|
+
deadlineMs,
|
|
7622
|
+
takeProviderAttempt: request.takeProviderAttempt
|
|
7623
|
+
};
|
|
7624
|
+
let content = await providerBudget.run(budget, () => requestContent(state, request, systemContent, prompt));
|
|
7041
7625
|
let usage = state.usage;
|
|
7042
7626
|
try {
|
|
7043
7627
|
checkMemoryOperation();
|
|
7044
7628
|
const attemptLimit = request.emptyReplyAttempts ?? EMPTY_REPLY_ATTEMPTS;
|
|
7045
7629
|
for (let attempt = 2; attempt <= attemptLimit; attempt += 1) {
|
|
7046
|
-
if (content === null || content.raw.trim().length > 0) break;
|
|
7630
|
+
if (content === null || content.raw.trim().length > 0 || budget.remaining <= 0) break;
|
|
7047
7631
|
const remainingMs = deadlineMs - performance.now();
|
|
7048
7632
|
if (remainingMs <= 0) break;
|
|
7049
7633
|
log$20.debug("Retrying empty model reply", {
|
|
@@ -7057,10 +7641,10 @@ function createLlmClient(config) {
|
|
|
7057
7641
|
function: "requestContentRetryingEmpty",
|
|
7058
7642
|
site_id: "shared.llm-client.requestContentRetryingEmpty.cd874fefff"
|
|
7059
7643
|
});
|
|
7060
|
-
content = await requestContent(state, {
|
|
7644
|
+
content = await providerBudget.run(budget, () => requestContent(state, {
|
|
7061
7645
|
...request,
|
|
7062
7646
|
timeoutMs: remainingMs
|
|
7063
|
-
}, systemContent, prompt);
|
|
7647
|
+
}, systemContent, prompt));
|
|
7064
7648
|
usage = addUsage(usage, state.usage);
|
|
7065
7649
|
checkMemoryOperation();
|
|
7066
7650
|
}
|
|
@@ -7085,6 +7669,7 @@ function createLlmClient(config) {
|
|
|
7085
7669
|
if (snoError !== void 0) throw snoError;
|
|
7086
7670
|
return content;
|
|
7087
7671
|
}
|
|
7672
|
+
const remainingMs = Math.floor(deadlineMs - performance.now());
|
|
7088
7673
|
const originalLastError = state.error;
|
|
7089
7674
|
const originalLastUsage = state.usage;
|
|
7090
7675
|
const source = snoError instanceof Error ? snoError.message : originalLastError ?? "";
|
|
@@ -7096,21 +7681,25 @@ function createLlmClient(config) {
|
|
|
7096
7681
|
else if (!config.apiKey?.trim()) snoFailure = "missing_key";
|
|
7097
7682
|
const operationId = config.operationId ?? memoryOperationId();
|
|
7098
7683
|
let hostFailure = "empty_reply";
|
|
7099
|
-
if (
|
|
7684
|
+
if (remainingMs <= 0) hostFailure = "deadline_exhausted";
|
|
7685
|
+
else if (!config.agentPort) hostFailure = "port_unavailable";
|
|
7100
7686
|
else if ([
|
|
7101
7687
|
"E10",
|
|
7102
7688
|
"P1",
|
|
7103
7689
|
"REM1"
|
|
7104
7690
|
].includes(request.callId) && !request.hostPrompt) hostFailure = "host_prompt_missing";
|
|
7105
7691
|
else try {
|
|
7106
|
-
const host = await requestContent(state,
|
|
7692
|
+
const host = await requestContent(state, {
|
|
7693
|
+
...request,
|
|
7694
|
+
timeoutMs: remainingMs
|
|
7695
|
+
}, systemContent, request.hostPrompt ?? request.prompt, "host");
|
|
7107
7696
|
if (host?.raw.trim()) {
|
|
7108
7697
|
log$20.info("Sno model call answered by host", {
|
|
7109
7698
|
call_id: request.callId,
|
|
7110
7699
|
operation_id: operationId,
|
|
7111
7700
|
sno_failure: snoFailure,
|
|
7112
7701
|
host_outcome: "answered",
|
|
7113
|
-
timeout_ms:
|
|
7702
|
+
timeout_ms: remainingMs
|
|
7114
7703
|
}, {
|
|
7115
7704
|
event_name: "memory.llm_client.fallback",
|
|
7116
7705
|
file: "packages/memory/src/model/llm-client.ts",
|
|
@@ -7122,7 +7711,7 @@ function createLlmClient(config) {
|
|
|
7122
7711
|
}
|
|
7123
7712
|
if (host === null) hostFailure = "host_error";
|
|
7124
7713
|
} catch (error) {
|
|
7125
|
-
if (request.signal?.aborted) throw error;
|
|
7714
|
+
if (request.signal?.aborted || error instanceof ModelCallRefusedError) throw error;
|
|
7126
7715
|
hostFailure = error instanceof LlmClientTerminalError ? error.category : "transport";
|
|
7127
7716
|
}
|
|
7128
7717
|
state.error = originalLastError;
|
|
@@ -7267,7 +7856,7 @@ function createLlmClient(config) {
|
|
|
7267
7856
|
//#region src/engine/security/scope-policy-types.ts
|
|
7268
7857
|
const DEFAULT_SCOPE_CONFIG = {
|
|
7269
7858
|
default: "global",
|
|
7270
|
-
definitions: { global: { description: "
|
|
7859
|
+
definitions: { global: { description: "Knowledge used by all your agents" } },
|
|
7271
7860
|
agentAccess: {},
|
|
7272
7861
|
extraAccessibleScopes: []
|
|
7273
7862
|
};
|
|
@@ -7361,7 +7950,7 @@ var MemoryScopePolicy = class {
|
|
|
7361
7950
|
},
|
|
7362
7951
|
extraAccessibleScopes: normalizeExtraAccessibleScopes(config.extraAccessibleScopes ?? DEFAULT_SCOPE_CONFIG.extraAccessibleScopes)
|
|
7363
7952
|
};
|
|
7364
|
-
if (!this.config.definitions.global) this.config.definitions.global = { description: "
|
|
7953
|
+
if (!this.config.definitions.global) this.config.definitions.global = { description: "Knowledge used by all your agents" };
|
|
7365
7954
|
this.validateConfiguration();
|
|
7366
7955
|
}
|
|
7367
7956
|
validateConfiguration() {
|
|
@@ -14313,495 +14902,85 @@ async function resolveMemoryDate(input) {
|
|
|
14313
14902
|
function: "resolveMemoryDate",
|
|
14314
14903
|
site_id: "date-resolution.model_unavailable"
|
|
14315
14904
|
});
|
|
14316
|
-
return {
|
|
14317
|
-
...unresolved,
|
|
14318
|
-
stage: {
|
|
14319
|
-
modelCalled: true,
|
|
14320
|
-
reason
|
|
14321
|
-
}
|
|
14322
|
-
};
|
|
14323
|
-
}
|
|
14324
|
-
const stage = {
|
|
14325
|
-
modelCalled: true,
|
|
14326
|
-
reason: reply.reason
|
|
14327
|
-
};
|
|
14328
|
-
const calculated = calculateCalendarTime(reply.time, anchor, unresolved.timezone);
|
|
14329
|
-
log$17.info("Memory date resolution completed", {
|
|
14330
|
-
model_called: true,
|
|
14331
|
-
resolved: calculated !== null
|
|
14332
|
-
}, {
|
|
14333
|
-
event_name: "sno_station_mem.date-resolution.date.resolution.stage",
|
|
14334
|
-
file: "packages/memory/src/engine/extraction/date-resolution.ts",
|
|
14335
|
-
function: "resolveMemoryDate",
|
|
14336
|
-
site_id: "date-resolution.resolveMemoryDate.1224fa35b2"
|
|
14337
|
-
});
|
|
14338
|
-
if (reply.time.kind === "none") return {
|
|
14339
|
-
...unresolved,
|
|
14340
|
-
interval: {
|
|
14341
|
-
type: "static",
|
|
14342
|
-
resolutionStatus: "static"
|
|
14343
|
-
},
|
|
14344
|
-
stage
|
|
14345
|
-
};
|
|
14346
|
-
if (!calculated) return {
|
|
14347
|
-
...unresolved,
|
|
14348
|
-
stage
|
|
14349
|
-
};
|
|
14350
|
-
return {
|
|
14351
|
-
interval: {
|
|
14352
|
-
type: "bounded",
|
|
14353
|
-
resolutionStatus: "resolved",
|
|
14354
|
-
from: calculated.from,
|
|
14355
|
-
until: calculated.until,
|
|
14356
|
-
phrase: input.expression ?? input.text,
|
|
14357
|
-
date: calculated.label,
|
|
14358
|
-
precision: calculated.precision,
|
|
14359
|
-
timezone: calculated.timezone
|
|
14360
|
-
},
|
|
14361
|
-
timestamp: unresolved.timestamp,
|
|
14362
|
-
timezone: unresolved.timezone,
|
|
14363
|
-
stage
|
|
14364
|
-
};
|
|
14365
|
-
}
|
|
14366
|
-
//#endregion
|
|
14367
|
-
//#region src/engine/extraction/memory-temporality-classifier.ts
|
|
14368
|
-
function parseSessionTimestamp(sessionDateTime) {
|
|
14369
|
-
return parseIsoDateTimeMs(sessionDateTime);
|
|
14370
|
-
}
|
|
14371
|
-
function serializeIntervalMetadata(category, interval) {
|
|
14372
|
-
if (interval.type === "static") return {
|
|
14373
|
-
memory_temporal_type: "static",
|
|
14374
|
-
temporal_resolution_status: "static"
|
|
14375
|
-
};
|
|
14376
|
-
const base = {
|
|
14377
|
-
memory_temporal_type: "dynamic",
|
|
14378
|
-
temporal_resolution_status: interval.resolutionStatus
|
|
14379
|
-
};
|
|
14380
|
-
if ("phrase" in interval && interval.phrase) base.temporal_phrase = interval.phrase;
|
|
14381
|
-
if (interval.type === "instant") {
|
|
14382
|
-
if (category === "episodic") base.event_at = interval.at;
|
|
14383
|
-
base.valid_from = interval.at;
|
|
14384
|
-
} else if (interval.type === "bounded") {
|
|
14385
|
-
base.valid_from = interval.from;
|
|
14386
|
-
if (category === "episodic") base.valid_until = interval.until;
|
|
14387
|
-
if (interval.date !== void 0) base.temporal_date = interval.date;
|
|
14388
|
-
if (interval.precision !== void 0) base.temporal_precision = interval.precision;
|
|
14389
|
-
if (interval.timezone !== void 0) base.temporal_timezone = interval.timezone;
|
|
14390
|
-
} else if (interval.type === "ongoing") {
|
|
14391
|
-
base.valid_from = interval.from;
|
|
14392
|
-
if (interval.until !== void 0) base.valid_until = interval.until;
|
|
14393
|
-
}
|
|
14394
|
-
return base;
|
|
14395
|
-
}
|
|
14396
|
-
//#endregion
|
|
14397
|
-
//#region src/engine/operations/jsonl-lines.ts
|
|
14398
|
-
const log$16 = createLogger("sno-station-mem:jsonl");
|
|
14399
|
-
/** Preserve complete records without materializing an unbounded log as one string. */
|
|
14400
|
-
async function* readJsonlLines(file) {
|
|
14401
|
-
const stream = createReadStream(file, { encoding: "utf8" });
|
|
14402
|
-
const lines = createInterface({
|
|
14403
|
-
input: stream,
|
|
14404
|
-
crlfDelay: Infinity
|
|
14405
|
-
});
|
|
14406
|
-
try {
|
|
14407
|
-
for await (const line of lines) if (line.trim()) yield line;
|
|
14408
|
-
} catch (error) {
|
|
14409
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
|
|
14410
|
-
log$16.error("jsonl.read.failed", {
|
|
14411
|
-
file,
|
|
14412
|
-
error
|
|
14413
|
-
}, {
|
|
14414
|
-
event_name: "memory.jsonl.read.failed",
|
|
14415
|
-
file: "packages/memory/src/engine/operations/jsonl-lines.ts",
|
|
14416
|
-
function: "readJsonlLines",
|
|
14417
|
-
site_id: "memory.jsonl.read.failed"
|
|
14418
|
-
});
|
|
14419
|
-
} finally {
|
|
14420
|
-
lines.close();
|
|
14421
|
-
stream.destroy();
|
|
14422
|
-
}
|
|
14423
|
-
}
|
|
14424
|
-
//#endregion
|
|
14425
|
-
//#region src/engine/operations/runtime-audit-log.ts
|
|
14426
|
-
/** @file runtime-audit-log.ts
|
|
14427
|
-
* @purpose Records audit events for operational visibility and safety-sensitive actions.
|
|
14428
|
-
* @boundary Plugin runtime events and filesystem-backed audit persistence.
|
|
14429
|
-
* @see sno-station-mem-plugin-runtime.ts, memory-tool-registration.ts, errors.ts.
|
|
14430
|
-
*/
|
|
14431
|
-
const auditWriteQueues = /* @__PURE__ */ new Map();
|
|
14432
|
-
const memoryAuditScope = new AsyncLocalStorage();
|
|
14433
|
-
const mutationAttemptScope = new AsyncLocalStorage();
|
|
14434
|
-
const mutationRecoveryPromises = /* @__PURE__ */ new Map();
|
|
14435
|
-
const MEMORY_AUDIT_COMMON_KEYS = [
|
|
14436
|
-
"operation",
|
|
14437
|
-
"audit_phase",
|
|
14438
|
-
"audit_operation_id"
|
|
14439
|
-
];
|
|
14440
|
-
const MUTATION_AUDIT_DETAIL_KEYS = [
|
|
14441
|
-
"mutation_writer",
|
|
14442
|
-
"mutation_subject",
|
|
14443
|
-
"mutation_outcome",
|
|
14444
|
-
"refusal_reason"
|
|
14445
|
-
];
|
|
14446
|
-
const MEMORY_AUDIT_ALLOWED_DETAIL_KEYS = {
|
|
14447
|
-
memory_injected: /* @__PURE__ */ new Set([
|
|
14448
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14449
|
-
"scope",
|
|
14450
|
-
"category",
|
|
14451
|
-
"lane",
|
|
14452
|
-
"count",
|
|
14453
|
-
"memory_ids",
|
|
14454
|
-
"write_outcome",
|
|
14455
|
-
"created_count",
|
|
14456
|
-
"existing_count"
|
|
14457
|
-
]),
|
|
14458
|
-
memory_searched: /* @__PURE__ */ new Set([
|
|
14459
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14460
|
-
"scope",
|
|
14461
|
-
"query_kind",
|
|
14462
|
-
"requested_count",
|
|
14463
|
-
"result_count",
|
|
14464
|
-
"memory_ids"
|
|
14465
|
-
]),
|
|
14466
|
-
memory_read: /* @__PURE__ */ new Set([
|
|
14467
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14468
|
-
"scope",
|
|
14469
|
-
"requested_count",
|
|
14470
|
-
"result_count",
|
|
14471
|
-
"memory_ids",
|
|
14472
|
-
"requested_fact_id",
|
|
14473
|
-
"resolved_fact_id",
|
|
14474
|
-
"fact_ids",
|
|
14475
|
-
"found",
|
|
14476
|
-
"outcome"
|
|
14477
|
-
]),
|
|
14478
|
-
memory_updated: /* @__PURE__ */ new Set([
|
|
14479
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14480
|
-
...MUTATION_AUDIT_DETAIL_KEYS,
|
|
14481
|
-
"scope",
|
|
14482
|
-
"requested_count",
|
|
14483
|
-
"result_count",
|
|
14484
|
-
"memory_ids",
|
|
14485
|
-
"outcome",
|
|
14486
|
-
"migration_status",
|
|
14487
|
-
"rewritten_rows",
|
|
14488
|
-
"checked_rows"
|
|
14489
|
-
]),
|
|
14490
|
-
memory_superseded: /* @__PURE__ */ new Set([
|
|
14491
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14492
|
-
...MUTATION_AUDIT_DETAIL_KEYS,
|
|
14493
|
-
"scope",
|
|
14494
|
-
"replacement_memory_id",
|
|
14495
|
-
"closed_memory_ids",
|
|
14496
|
-
"write_outcome"
|
|
14497
|
-
]),
|
|
14498
|
-
memory_deleted: /* @__PURE__ */ new Set([
|
|
14499
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14500
|
-
"scope",
|
|
14501
|
-
"deleted_memory_ids",
|
|
14502
|
-
"delete_reason",
|
|
14503
|
-
"count",
|
|
14504
|
-
"outcome",
|
|
14505
|
-
"removed_files"
|
|
14506
|
-
]),
|
|
14507
|
-
memory_purged: /* @__PURE__ */ new Set([
|
|
14508
|
-
...MEMORY_AUDIT_COMMON_KEYS,
|
|
14509
|
-
"target_fact_id",
|
|
14510
|
-
"purged_fact_ids",
|
|
14511
|
-
"failed_fact_ids",
|
|
14512
|
-
"status",
|
|
14513
|
-
"blocked_reason"
|
|
14514
|
-
])
|
|
14515
|
-
};
|
|
14516
|
-
/** Implements enqueue audit write as the local audit log state operation. */
|
|
14517
|
-
function enqueueAuditWrite(auditPath, line) {
|
|
14518
|
-
const next = (auditWriteQueues.get(auditPath) ?? Promise.resolve(true)).catch(() => void 0).then(async () => {
|
|
14519
|
-
mkdirSync(path.dirname(auditPath), { recursive: true });
|
|
14520
|
-
await appendFile(auditPath, line);
|
|
14521
|
-
return true;
|
|
14522
|
-
}).catch((error) => {
|
|
14523
|
-
createLogger("sno-station-mem:audit").error("Audit entry append failed", { error }, {
|
|
14524
|
-
event_name: "memory.audit.append.failed",
|
|
14525
|
-
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
14526
|
-
function: "enqueueAuditWrite",
|
|
14527
|
-
site_id: "memory.audit.append.failed"
|
|
14528
|
-
});
|
|
14529
|
-
return false;
|
|
14530
|
-
});
|
|
14531
|
-
auditWriteQueues.set(auditPath, next);
|
|
14532
|
-
next.finally(() => {
|
|
14533
|
-
if (auditWriteQueues.get(auditPath) === next) auditWriteQueues.delete(auditPath);
|
|
14534
|
-
});
|
|
14535
|
-
return next;
|
|
14536
|
-
}
|
|
14537
|
-
/** Returns audit path from audit log state state without side effects. */
|
|
14538
|
-
function getAuditPath(stateDir) {
|
|
14539
|
-
return path.join(stateDir, "audit.jsonl");
|
|
14540
|
-
}
|
|
14541
|
-
function isRecord$1(value) {
|
|
14542
|
-
return typeof value === "object" && value !== null;
|
|
14543
|
-
}
|
|
14544
|
-
function isMemoryAuditEvent(event) {
|
|
14545
|
-
return event.startsWith("memory_");
|
|
14546
|
-
}
|
|
14547
|
-
function redactAuditValue(value) {
|
|
14548
|
-
if (typeof value === "string") return redactSecrets(value);
|
|
14549
|
-
if (Array.isArray(value)) return value.map(redactAuditValue);
|
|
14550
|
-
if (!isRecord$1(value)) return value;
|
|
14551
|
-
const redacted = {};
|
|
14552
|
-
for (const [key, child] of Object.entries(value)) redacted[key] = redactAuditValue(child);
|
|
14553
|
-
return redacted;
|
|
14554
|
-
}
|
|
14555
|
-
function prepareAuditEntry(entry) {
|
|
14556
|
-
if (!isMemoryAuditEvent(entry.event) || entry.details?.["audit_phase"] === void 0) return entry;
|
|
14557
|
-
const allowed = MEMORY_AUDIT_ALLOWED_DETAIL_KEYS[entry.event];
|
|
14558
|
-
const details = {};
|
|
14559
|
-
for (const [key, value] of Object.entries(entry.details)) if (allowed.has(key)) details[key] = value;
|
|
14560
|
-
else createLogger("sno-station-mem:audit").error("memory.audit.detail.unknown", {
|
|
14561
|
-
event: entry.event,
|
|
14562
|
-
key
|
|
14563
|
-
}, {
|
|
14564
|
-
event_name: "memory.audit.detail.unknown",
|
|
14565
|
-
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
14566
|
-
function: "prepareAuditEntry",
|
|
14567
|
-
site_id: "memory.audit.detail.unknown"
|
|
14568
|
-
});
|
|
14569
|
-
return {
|
|
14570
|
-
...entry,
|
|
14571
|
-
...entry.scope === void 0 ? {} : { scope: redactSecrets(entry.scope) },
|
|
14572
|
-
details: redactAuditValue(details)
|
|
14573
|
-
};
|
|
14574
|
-
}
|
|
14575
|
-
/** Persists audit entry through the single audit log state write path. */
|
|
14576
|
-
function appendAuditEntry(stateDir, entry) {
|
|
14577
|
-
const auditPath = getAuditPath(stateDir);
|
|
14578
|
-
const prepared = prepareAuditEntry(entry);
|
|
14579
|
-
enqueueAuditWrite(auditPath, `${JSON.stringify({
|
|
14580
|
-
...prepared,
|
|
14581
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
14582
|
-
})}\n`);
|
|
14583
|
-
}
|
|
14584
|
-
/** Waits for the audit append; failures are logged without blocking the operation. */
|
|
14585
|
-
async function appendAuditEntryStrict(stateDir, entry) {
|
|
14586
|
-
const auditPath = getAuditPath(stateDir);
|
|
14587
|
-
const prepared = prepareAuditEntry(entry);
|
|
14588
|
-
return enqueueAuditWrite(auditPath, `${JSON.stringify({
|
|
14589
|
-
...prepared,
|
|
14590
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
14591
|
-
})}\n`);
|
|
14592
|
-
}
|
|
14593
|
-
/** Attempts a synchronous audit append and logs a failure. */
|
|
14594
|
-
function appendAuditEntrySync(stateDir, entry) {
|
|
14595
|
-
const auditPath = getAuditPath(stateDir);
|
|
14596
|
-
const prepared = prepareAuditEntry(entry);
|
|
14597
|
-
try {
|
|
14598
|
-
mkdirSync(path.dirname(auditPath), { recursive: true });
|
|
14599
|
-
appendFileSync(auditPath, `${JSON.stringify({
|
|
14600
|
-
...prepared,
|
|
14601
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
14602
|
-
})}\n`);
|
|
14603
|
-
} catch (error) {
|
|
14604
|
-
createLogger("sno-station-mem:audit").error("memory.audit.append.failed", { error }, {
|
|
14605
|
-
event_name: "memory.audit.append.failed",
|
|
14606
|
-
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
14607
|
-
function: "appendAuditEntrySync",
|
|
14608
|
-
site_id: "memory.audit.sync.failed"
|
|
14609
|
-
});
|
|
14610
|
-
}
|
|
14611
|
-
}
|
|
14612
|
-
function memoryAuditDetails(operation, phase, operationId, details) {
|
|
14613
|
-
return {
|
|
14614
|
-
...details,
|
|
14615
|
-
operation,
|
|
14616
|
-
audit_phase: phase,
|
|
14617
|
-
audit_operation_id: operationId
|
|
14618
|
-
};
|
|
14619
|
-
}
|
|
14620
|
-
/** Records the start and outcome without using audit availability as admission. */
|
|
14621
|
-
async function runWithMemoryAudit(options) {
|
|
14622
|
-
if (memoryAuditScope.getStore()) return options.run();
|
|
14623
|
-
return memoryAuditScope.run(true, async () => {
|
|
14624
|
-
const operationId = randomUUID();
|
|
14625
|
-
await appendAuditEntryStrict(options.stateDir, {
|
|
14626
|
-
event: options.event,
|
|
14627
|
-
scope: options.scope,
|
|
14628
|
-
resultStatus: "partial",
|
|
14629
|
-
details: memoryAuditDetails(options.operation, "started", operationId, options.startedDetails)
|
|
14630
|
-
});
|
|
14631
|
-
let result;
|
|
14632
|
-
try {
|
|
14633
|
-
result = await options.run();
|
|
14634
|
-
} catch (error) {
|
|
14635
|
-
await appendAuditEntryStrict(options.stateDir, {
|
|
14636
|
-
event: options.event,
|
|
14637
|
-
scope: options.scope,
|
|
14638
|
-
resultStatus: "error",
|
|
14639
|
-
errorCode: "memory_operation_failed",
|
|
14640
|
-
details: memoryAuditDetails(options.operation, "failed", operationId, options.startedDetails)
|
|
14641
|
-
});
|
|
14642
|
-
throw error;
|
|
14643
|
-
}
|
|
14644
|
-
await appendAuditEntryStrict(options.stateDir, {
|
|
14645
|
-
event: options.event,
|
|
14646
|
-
scope: options.scope,
|
|
14647
|
-
resultStatus: "ok",
|
|
14648
|
-
details: memoryAuditDetails(options.operation, "completed", operationId, options.completedDetails(result))
|
|
14649
|
-
});
|
|
14650
|
-
return result;
|
|
14651
|
-
});
|
|
14652
|
-
}
|
|
14653
|
-
async function readOpenMutationAttempts(stateDir) {
|
|
14654
|
-
const auditPath = getAuditPath(stateDir);
|
|
14655
|
-
if (!existsSync(auditPath)) return [];
|
|
14656
|
-
const openAttempts = /* @__PURE__ */ new Map();
|
|
14657
|
-
for await (const line of readJsonlLines(auditPath)) {
|
|
14658
|
-
if (!line.trim()) continue;
|
|
14659
|
-
let parsed;
|
|
14660
|
-
try {
|
|
14661
|
-
parsed = JSON.parse(line);
|
|
14662
|
-
} catch {
|
|
14663
|
-
continue;
|
|
14664
|
-
}
|
|
14665
|
-
if (!isRecord$1(parsed) || !isRecord$1(parsed["details"])) continue;
|
|
14666
|
-
const event = parsed["event"];
|
|
14667
|
-
const decision = parsed["decision"];
|
|
14668
|
-
const details = parsed["details"];
|
|
14669
|
-
const attemptId = details["audit_operation_id"];
|
|
14670
|
-
if (typeof attemptId !== "string") continue;
|
|
14671
|
-
if (details["mutation_outcome"] !== void 0) {
|
|
14672
|
-
openAttempts.delete(attemptId);
|
|
14673
|
-
continue;
|
|
14674
|
-
}
|
|
14675
|
-
if (decision !== "mutation-attempt-open" || details["audit_phase"] !== "started" || event !== "memory_updated" && event !== "memory_superseded" || typeof details["operation"] !== "string" || details["mutation_writer"] !== "profile-section" && details["mutation_writer"] !== "task-lifecycle" && details["mutation_writer"] !== "legacy-profile-refusal") continue;
|
|
14676
|
-
openAttempts.set(attemptId, {
|
|
14677
|
-
event,
|
|
14678
|
-
operation: details["operation"],
|
|
14679
|
-
attemptId,
|
|
14680
|
-
writer: details["mutation_writer"],
|
|
14681
|
-
...typeof details["mutation_subject"] === "string" ? { subject: details["mutation_subject"] } : {}
|
|
14682
|
-
});
|
|
14905
|
+
return {
|
|
14906
|
+
...unresolved,
|
|
14907
|
+
stage: {
|
|
14908
|
+
modelCalled: true,
|
|
14909
|
+
reason
|
|
14910
|
+
}
|
|
14911
|
+
};
|
|
14683
14912
|
}
|
|
14684
|
-
|
|
14685
|
-
|
|
14686
|
-
|
|
14687
|
-
return {
|
|
14688
|
-
operation: input.operation,
|
|
14689
|
-
audit_phase: input.phase,
|
|
14690
|
-
audit_operation_id: input.attemptId,
|
|
14691
|
-
mutation_writer: input.writer,
|
|
14692
|
-
...input.subject === void 0 ? {} : { mutation_subject: input.subject },
|
|
14693
|
-
...input.outcome === void 0 ? {} : { mutation_outcome: input.outcome },
|
|
14694
|
-
...input.refusalReason === void 0 ? {} : { refusal_reason: input.refusalReason }
|
|
14913
|
+
const stage = {
|
|
14914
|
+
modelCalled: true,
|
|
14915
|
+
reason: reply.reason
|
|
14695
14916
|
};
|
|
14696
|
-
|
|
14697
|
-
|
|
14698
|
-
|
|
14699
|
-
|
|
14700
|
-
|
|
14701
|
-
|
|
14702
|
-
|
|
14703
|
-
|
|
14704
|
-
|
|
14705
|
-
event: attempt.event,
|
|
14706
|
-
resultStatus: mutationAuditStatus(completion.outcome),
|
|
14707
|
-
decision: completion.outcome,
|
|
14708
|
-
details: mutationAuditDetails({
|
|
14709
|
-
operation: attempt.operation,
|
|
14710
|
-
phase,
|
|
14711
|
-
attemptId: attempt.attemptId,
|
|
14712
|
-
writer: attempt.writer,
|
|
14713
|
-
...attempt.subject === void 0 ? {} : { subject: attempt.subject },
|
|
14714
|
-
outcome: completion.outcome,
|
|
14715
|
-
...completion.refusalReason === void 0 ? {} : { refusalReason: completion.refusalReason }
|
|
14716
|
-
})
|
|
14917
|
+
const calculated = calculateCalendarTime(reply.time, anchor, unresolved.timezone);
|
|
14918
|
+
log$17.info("Memory date resolution completed", {
|
|
14919
|
+
model_called: true,
|
|
14920
|
+
resolved: calculated !== null
|
|
14921
|
+
}, {
|
|
14922
|
+
event_name: "sno_station_mem.date-resolution.date.resolution.stage",
|
|
14923
|
+
file: "packages/memory/src/engine/extraction/date-resolution.ts",
|
|
14924
|
+
function: "resolveMemoryDate",
|
|
14925
|
+
site_id: "date-resolution.resolveMemoryDate.1224fa35b2"
|
|
14717
14926
|
});
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
return
|
|
14731
|
-
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14927
|
+
if (reply.time.kind === "none") return {
|
|
14928
|
+
...unresolved,
|
|
14929
|
+
interval: {
|
|
14930
|
+
type: "static",
|
|
14931
|
+
resolutionStatus: "static"
|
|
14932
|
+
},
|
|
14933
|
+
stage
|
|
14934
|
+
};
|
|
14935
|
+
if (!calculated) return {
|
|
14936
|
+
...unresolved,
|
|
14937
|
+
stage
|
|
14938
|
+
};
|
|
14939
|
+
return {
|
|
14940
|
+
interval: {
|
|
14941
|
+
type: "bounded",
|
|
14942
|
+
resolutionStatus: "resolved",
|
|
14943
|
+
from: calculated.from,
|
|
14944
|
+
until: calculated.until,
|
|
14945
|
+
phrase: input.expression ?? input.text,
|
|
14946
|
+
date: calculated.label,
|
|
14947
|
+
precision: calculated.precision,
|
|
14948
|
+
timezone: calculated.timezone
|
|
14949
|
+
},
|
|
14950
|
+
timestamp: unresolved.timestamp,
|
|
14951
|
+
timezone: unresolved.timezone,
|
|
14952
|
+
stage
|
|
14742
14953
|
};
|
|
14743
|
-
return mutationAttemptScope.run(attempt.attemptId, async () => {
|
|
14744
|
-
await appendAuditEntryStrict(options.stateDir, {
|
|
14745
|
-
event: options.event,
|
|
14746
|
-
resultStatus: "partial",
|
|
14747
|
-
decision: "mutation-attempt-open",
|
|
14748
|
-
details: mutationAuditDetails({
|
|
14749
|
-
operation: attempt.operation,
|
|
14750
|
-
phase: "started",
|
|
14751
|
-
attemptId: attempt.attemptId,
|
|
14752
|
-
writer: attempt.writer,
|
|
14753
|
-
...attempt.subject === void 0 ? {} : { subject: attempt.subject }
|
|
14754
|
-
})
|
|
14755
|
-
});
|
|
14756
|
-
let result;
|
|
14757
|
-
try {
|
|
14758
|
-
result = await options.run();
|
|
14759
|
-
} catch (error) {
|
|
14760
|
-
await closeMutationAttempt(options.stateDir, attempt, options.failedOutcome?.(error) ?? { outcome: "failed" });
|
|
14761
|
-
throw error;
|
|
14762
|
-
}
|
|
14763
|
-
await closeMutationAttempt(options.stateDir, attempt, options.completedOutcome(result));
|
|
14764
|
-
return result;
|
|
14765
|
-
});
|
|
14766
14954
|
}
|
|
14767
|
-
|
|
14768
|
-
|
|
14769
|
-
|
|
14770
|
-
|
|
14771
|
-
return attemptId;
|
|
14955
|
+
//#endregion
|
|
14956
|
+
//#region src/engine/extraction/memory-temporality-classifier.ts
|
|
14957
|
+
function parseSessionTimestamp(sessionDateTime) {
|
|
14958
|
+
return parseIsoDateTimeMs(sessionDateTime);
|
|
14772
14959
|
}
|
|
14773
|
-
|
|
14774
|
-
|
|
14775
|
-
|
|
14776
|
-
|
|
14777
|
-
|
|
14778
|
-
|
|
14779
|
-
|
|
14780
|
-
|
|
14781
|
-
|
|
14782
|
-
|
|
14783
|
-
|
|
14784
|
-
|
|
14785
|
-
|
|
14786
|
-
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14790
|
-
|
|
14791
|
-
|
|
14792
|
-
|
|
14793
|
-
|
|
14794
|
-
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
appendAuditEntrySync(options.stateDir, {
|
|
14798
|
-
event: options.event,
|
|
14799
|
-
scope: options.scope,
|
|
14800
|
-
resultStatus: "ok",
|
|
14801
|
-
details: memoryAuditDetails(options.operation, "completed", operationId, options.completedDetails(result))
|
|
14802
|
-
});
|
|
14803
|
-
return result;
|
|
14804
|
-
});
|
|
14960
|
+
function serializeIntervalMetadata(category, interval) {
|
|
14961
|
+
if (interval.type === "static") return {
|
|
14962
|
+
memory_temporal_type: "static",
|
|
14963
|
+
temporal_resolution_status: "static"
|
|
14964
|
+
};
|
|
14965
|
+
const base = {
|
|
14966
|
+
memory_temporal_type: "dynamic",
|
|
14967
|
+
temporal_resolution_status: interval.resolutionStatus
|
|
14968
|
+
};
|
|
14969
|
+
if ("phrase" in interval && interval.phrase) base.temporal_phrase = interval.phrase;
|
|
14970
|
+
if (interval.type === "instant") {
|
|
14971
|
+
if (category === "episodic") base.event_at = interval.at;
|
|
14972
|
+
base.valid_from = interval.at;
|
|
14973
|
+
} else if (interval.type === "bounded") {
|
|
14974
|
+
base.valid_from = interval.from;
|
|
14975
|
+
if (category === "episodic") base.valid_until = interval.until;
|
|
14976
|
+
if (interval.date !== void 0) base.temporal_date = interval.date;
|
|
14977
|
+
if (interval.precision !== void 0) base.temporal_precision = interval.precision;
|
|
14978
|
+
if (interval.timezone !== void 0) base.temporal_timezone = interval.timezone;
|
|
14979
|
+
} else if (interval.type === "ongoing") {
|
|
14980
|
+
base.valid_from = interval.from;
|
|
14981
|
+
if (interval.until !== void 0) base.valid_until = interval.until;
|
|
14982
|
+
}
|
|
14983
|
+
return base;
|
|
14805
14984
|
}
|
|
14806
14985
|
createLogger("sno-station-mem:scopes");
|
|
14807
14986
|
//#endregion
|
|
@@ -15763,12 +15942,14 @@ function createVerdictGeneration(database, input) {
|
|
|
15763
15942
|
generation_id, pair_id, left_row_id, right_row_id, sort_key,
|
|
15764
15943
|
claim_state, attempt_count, progress_state, refusal_reason, inherited_from_generation_id
|
|
15765
15944
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
15766
|
-
const inheritedRefusal =
|
|
15767
|
-
|
|
15768
|
-
|
|
15945
|
+
const inheritedRefusal = database.prepare(`SELECT pair.attempt_count, pair.refusal_reason, pair.generation_id
|
|
15946
|
+
FROM nodix_rem_scan_pairs AS pair
|
|
15947
|
+
JOIN nodix_rem_scan_generations AS generation USING (generation_id)
|
|
15948
|
+
WHERE pair.pair_id = ? AND pair.progress_state = 'refused'
|
|
15949
|
+
ORDER BY generation.rowid DESC LIMIT 1`);
|
|
15769
15950
|
for (const pair of input.pairs) {
|
|
15770
|
-
const inherited = inheritedRefusal
|
|
15771
|
-
insertPair.run(input.generationId, pair.pairId, pair.leftRowId, pair.rightRowId, pair.sortKey, "unvisited", inherited?.attempt_count ?? 0, inherited ? "refused" : "pending", inherited?.refusal_reason ?? null, inherited
|
|
15951
|
+
const inherited = inheritedRefusal.get(pair.pairId);
|
|
15952
|
+
insertPair.run(input.generationId, pair.pairId, pair.leftRowId, pair.rightRowId, pair.sortKey, "unvisited", inherited?.attempt_count ?? 0, inherited ? "refused" : "pending", inherited?.refusal_reason ?? null, inherited?.generation_id ?? null);
|
|
15772
15953
|
}
|
|
15773
15954
|
}).immediate();
|
|
15774
15955
|
}
|
|
@@ -15803,7 +15984,7 @@ function listVerdictPairs(database, generationId) {
|
|
|
15803
15984
|
}
|
|
15804
15985
|
function readClosedVerdictPairIds(database, pairIds) {
|
|
15805
15986
|
const rows = database.prepare(`SELECT DISTINCT pair_id FROM nodix_rem_scan_pairs
|
|
15806
|
-
WHERE progress_state
|
|
15987
|
+
WHERE progress_state IN ('closed', 'exhausted') AND pair_id IN (SELECT value FROM json_each(?))`).all(JSON.stringify(pairIds));
|
|
15807
15988
|
return new Set(rows.map((row) => row.pair_id));
|
|
15808
15989
|
}
|
|
15809
15990
|
function claimNextPair(database, input) {
|
|
@@ -15816,7 +15997,7 @@ function claimNextPair(database, input) {
|
|
|
15816
15997
|
reserved_tokens, attempt_count, progress_state, refusal_reason, inherited_from_generation_id
|
|
15817
15998
|
FROM nodix_rem_scan_pairs
|
|
15818
15999
|
WHERE generation_id = ? AND claim_state = 'unvisited'
|
|
15819
|
-
ORDER BY
|
|
16000
|
+
ORDER BY attempt_count, sort_key, pair_id
|
|
15820
16001
|
LIMIT 1`).get(input.generationId);
|
|
15821
16002
|
if (!pair) return void 0;
|
|
15822
16003
|
if (asRunResult(database.prepare(`UPDATE nodix_rem_scan_pairs SET
|
|
@@ -17838,7 +18019,7 @@ function loadSqliteVecExtension(database) {
|
|
|
17838
18019
|
* idempotent, so an interrupted move simply completes on the next boot.
|
|
17839
18020
|
* @boundary Reads and writes only those two tables through the caller's handle.
|
|
17840
18021
|
*/
|
|
17841
|
-
const log$
|
|
18022
|
+
const log$15 = createLogger("unplaced-candidate-migration");
|
|
17842
18023
|
/**
|
|
17843
18024
|
* Legacy rows are keyed on their own row id, not on the live writer's basis.
|
|
17844
18025
|
* Two legacy rows can carry byte-identical payloads and reasons and still be
|
|
@@ -17881,7 +18062,7 @@ function migrateUnplacedCandidates(sqlite) {
|
|
|
17881
18062
|
}
|
|
17882
18063
|
return moved;
|
|
17883
18064
|
})();
|
|
17884
|
-
log$
|
|
18065
|
+
log$15.warn("relocated non-active memory rows into the unplaced-candidate table", { moved }, {
|
|
17885
18066
|
event_name: FIXED_EXTERNAL_VALUE_62,
|
|
17886
18067
|
file: "packages/memory/src/store/unplaced-candidate-migration.ts",
|
|
17887
18068
|
function: "migrateUnplacedCandidates",
|
|
@@ -17896,7 +18077,7 @@ function migrateUnplacedCandidates(sqlite) {
|
|
|
17896
18077
|
* @boundary Filesystem safety, database pragmas, migrations, and runtime loading.
|
|
17897
18078
|
* @see sqlite-runtime.ts, schema.ts, store.ts.
|
|
17898
18079
|
*/
|
|
17899
|
-
const log$
|
|
18080
|
+
const log$14 = createLogger("sno-station-mem:db");
|
|
17900
18081
|
function parseVecTableDimension(sql) {
|
|
17901
18082
|
if (!/create\s+virtual\s+table/i.test(sql) || !/using\s+vec0/i.test(sql)) throw new StorageError(`nodix_memory_chunk_vectors exists but is not a sqlite-vec virtual table: ${sql}`);
|
|
17902
18083
|
const token = sql.match(/embedding\s+float\[(\d+)\]/i)?.[1];
|
|
@@ -17935,7 +18116,7 @@ function ensureChunkVecTable(db, vectorDim) {
|
|
|
17935
18116
|
const existing = readChunkVecTableState(db);
|
|
17936
18117
|
if (existing && (existing.dimension !== vectorDim || !existing.hasPartitionKey)) {
|
|
17937
18118
|
if (existing.rowCount > 0) {
|
|
17938
|
-
log$
|
|
18119
|
+
log$14.error("storage.vector.configuration.mismatch", {
|
|
17939
18120
|
vectorDim,
|
|
17940
18121
|
existing
|
|
17941
18122
|
}, {
|
|
@@ -17975,7 +18156,7 @@ function loadSimpleTokenizer(db) {
|
|
|
17975
18156
|
db.loadExtension(extensionPath);
|
|
17976
18157
|
db.prepare("SELECT jieba_dict(?)").get(dictPath);
|
|
17977
18158
|
db.exec("CREATE VIRTUAL TABLE temp.nodix_simple_tokenizer_smoke USING fts5(x, tokenize='simple 0'); DROP TABLE temp.nodix_simple_tokenizer_smoke;");
|
|
17978
|
-
log$
|
|
18159
|
+
log$14.info("simple-tokenizer loaded", {
|
|
17979
18160
|
platform,
|
|
17980
18161
|
extensionPath
|
|
17981
18162
|
}, {
|
|
@@ -18005,7 +18186,7 @@ function resolveMigrationsDir() {
|
|
|
18005
18186
|
const MIGRATIONS_DIR = resolveMigrationsDir();
|
|
18006
18187
|
/** Implements init db as the local SQLite connection setup operation. */
|
|
18007
18188
|
function initDb(dbPath, vectorDim) {
|
|
18008
|
-
log$
|
|
18189
|
+
log$14.info("initializing database", {
|
|
18009
18190
|
dbPath,
|
|
18010
18191
|
vectorDim
|
|
18011
18192
|
}, {
|
|
@@ -18022,7 +18203,7 @@ function initDb(dbPath, vectorDim) {
|
|
|
18022
18203
|
run();
|
|
18023
18204
|
pending.delete(step);
|
|
18024
18205
|
} catch (error) {
|
|
18025
|
-
log$
|
|
18206
|
+
log$14.error("storage.setup.failed", {
|
|
18026
18207
|
step,
|
|
18027
18208
|
error
|
|
18028
18209
|
}, {
|
|
@@ -18081,7 +18262,7 @@ function ensureColumn(database, tableName, columnName, declaration) {
|
|
|
18081
18262
|
* @boundary SQLite schema, embedding vectors, FTS, and metadata invariants.
|
|
18082
18263
|
* @see connection.ts, schema.ts, retriever.ts.
|
|
18083
18264
|
*/
|
|
18084
|
-
const log$
|
|
18265
|
+
const log$13 = createLogger("sno-station-mem:store");
|
|
18085
18266
|
/**
|
|
18086
18267
|
* Reflection v3: discriminator added to content-hash input when the
|
|
18087
18268
|
* row carries a `metadata.mappedKind`. Two rows with same projectId + same store
|
|
@@ -18191,7 +18372,11 @@ function loadMemoryTelemetryKeySet(options) {
|
|
|
18191
18372
|
historic: /* @__PURE__ */ new Map()
|
|
18192
18373
|
};
|
|
18193
18374
|
const key = options.key;
|
|
18194
|
-
if (!key || key.trim().length === 0)
|
|
18375
|
+
if (!key || key.trim().length === 0) return {
|
|
18376
|
+
enabled: true,
|
|
18377
|
+
current: null,
|
|
18378
|
+
historic: new Map(options.historicKeys.map((value, index) => [index + 1, value]))
|
|
18379
|
+
};
|
|
18195
18380
|
const currentKeyVersion = options.currentKeyVersion ?? options.historicKeys.length + 1;
|
|
18196
18381
|
if (!Number.isInteger(currentKeyVersion) || currentKeyVersion <= 0) throw new Error("memory telemetry current key version must be a positive integer");
|
|
18197
18382
|
return {
|
|
@@ -18348,7 +18533,7 @@ function verification(status, receipt) {
|
|
|
18348
18533
|
}
|
|
18349
18534
|
//#endregion
|
|
18350
18535
|
//#region src/engine/telemetry/memory-telemetry-events.ts
|
|
18351
|
-
const log$
|
|
18536
|
+
const log$12 = createLogger("sno-station-mem:memory-telemetry-events");
|
|
18352
18537
|
var MemoryTelemetryEventWriter = class {
|
|
18353
18538
|
sqlite;
|
|
18354
18539
|
enabled;
|
|
@@ -18381,28 +18566,40 @@ var MemoryTelemetryEventWriter = class {
|
|
|
18381
18566
|
historicKeys: options.config?.historicKeys ?? [],
|
|
18382
18567
|
currentKeyVersion: options.config?.currentKeyVersion
|
|
18383
18568
|
});
|
|
18384
|
-
this.receiptService = options.config?.receiptService ?? createMemoryTelemetryReceiptService(keySet);
|
|
18569
|
+
this.receiptService = options.config?.receiptService ?? (keySet.current ? createMemoryTelemetryReceiptService(keySet) : null);
|
|
18385
18570
|
} catch (error) {
|
|
18386
|
-
log$
|
|
18387
|
-
event_name: "
|
|
18571
|
+
log$12.warn("memory telemetry signing unavailable; recording unsigned events", { error }, {
|
|
18572
|
+
event_name: "memory.telemetry.signing.unavailable",
|
|
18388
18573
|
file: "packages/memory/src/engine/telemetry/memory-telemetry-events.ts",
|
|
18389
18574
|
function: "<anonymous callback>",
|
|
18390
18575
|
site_id: "memory-telemetry-events.<anonymous callback>.23cfef2d08"
|
|
18391
18576
|
});
|
|
18392
|
-
this.enabled = false;
|
|
18393
18577
|
this.receiptService = null;
|
|
18394
18578
|
}
|
|
18395
18579
|
}
|
|
18396
18580
|
writeReceiptEvent(input) {
|
|
18397
18581
|
if (!this.enabled) return;
|
|
18398
18582
|
const timestampMs = input.timestampMs ?? Date.now();
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
|
|
18583
|
+
let receipt;
|
|
18584
|
+
try {
|
|
18585
|
+
receipt = this.receiptService?.sign({
|
|
18586
|
+
factId: input.factId,
|
|
18587
|
+
contentHash: input.contentHash,
|
|
18588
|
+
timestampMs
|
|
18589
|
+
});
|
|
18590
|
+
} catch (error) {
|
|
18591
|
+
log$12.warn("memory telemetry signing failed; recording unsigned event", { error }, {
|
|
18592
|
+
event_name: "memory.telemetry.signing.failed",
|
|
18593
|
+
file: "packages/memory/src/engine/telemetry/memory-telemetry-events.ts",
|
|
18594
|
+
function: "writeReceiptEvent",
|
|
18595
|
+
site_id: "memory.telemetry.signing.failed"
|
|
18596
|
+
});
|
|
18597
|
+
}
|
|
18598
|
+
const metadata = validateMemoryTelemetryMetadata(input.eventType, {
|
|
18599
|
+
...input.metadata,
|
|
18600
|
+
...input.eventType === "create" ? { receipt_status: receipt ? "signed" : "unsigned" } : {}
|
|
18403
18601
|
});
|
|
18404
|
-
|
|
18405
|
-
this.insertReceiptEventStatement.run(input.eventType, input.factId, input.memoryKind, timestampMs, this.agentId, input.projectId, input.sourceEventId ?? null, input.derivedFrom ? JSON.stringify(input.derivedFrom) : null, receipt.contentHash, receipt.receiptHmac, receipt.keyVersion, JSON.stringify(metadata));
|
|
18602
|
+
this.insertReceiptEventStatement.run(input.eventType, input.factId, input.memoryKind, timestampMs, this.agentId, input.projectId, input.sourceEventId ?? null, input.derivedFrom ? JSON.stringify(input.derivedFrom) : null, input.contentHash, receipt?.receiptHmac ?? null, receipt?.keyVersion ?? null, JSON.stringify(metadata));
|
|
18406
18603
|
}
|
|
18407
18604
|
writeLifecycleEvent(input) {
|
|
18408
18605
|
if (!this.enabled) return;
|
|
@@ -18414,10 +18611,6 @@ var MemoryTelemetryEventWriter = class {
|
|
|
18414
18611
|
if (!this.enabled) return null;
|
|
18415
18612
|
return this.readLatestReceiptEventIdStatement.get(factId)?.id ?? null;
|
|
18416
18613
|
}
|
|
18417
|
-
requireReceiptService() {
|
|
18418
|
-
if (!this.receiptService) throw new Error("memory telemetry receipt service is unavailable");
|
|
18419
|
-
return this.receiptService;
|
|
18420
|
-
}
|
|
18421
18614
|
};
|
|
18422
18615
|
//#endregion
|
|
18423
18616
|
//#region src/store/rem-update-stamp-migration.ts
|
|
@@ -18761,7 +18954,7 @@ var MemoryStore = class {
|
|
|
18761
18954
|
sqlite.close();
|
|
18762
18955
|
throw error;
|
|
18763
18956
|
}
|
|
18764
|
-
log$
|
|
18957
|
+
log$13.info("memory store initialized", {
|
|
18765
18958
|
dbPath: config.dbPath,
|
|
18766
18959
|
vectorDim: this.vectorDim,
|
|
18767
18960
|
hasFtsSupport: this.hasFtsSupport
|
|
@@ -18920,7 +19113,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
18920
19113
|
} catch (error) {
|
|
18921
19114
|
failedRows++;
|
|
18922
19115
|
if (firstFailure === void 0 && error instanceof Error) firstFailure = error;
|
|
18923
|
-
log$
|
|
19116
|
+
log$13.warn("legacy memory chunk backfill skipped row", {
|
|
18924
19117
|
memory_id: row.id,
|
|
18925
19118
|
error
|
|
18926
19119
|
}, {
|
|
@@ -18970,7 +19163,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
18970
19163
|
this.backfillFailureCount = 0;
|
|
18971
19164
|
this.backfillNextRetryAt = 0;
|
|
18972
19165
|
this.backfillLastFailureAt = 0;
|
|
18973
|
-
if (count > 0) log$
|
|
19166
|
+
if (count > 0) log$13.info("backfilled legacy memory chunks", { count }, {
|
|
18974
19167
|
event_name: "sno_station_mem.memory-store-backfill.backfilled.legacy.memory.chunks",
|
|
18975
19168
|
file: "packages/memory/src/store/memory-store-backfill.ts",
|
|
18976
19169
|
function: "<anonymous callback>",
|
|
@@ -18983,7 +19176,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
18983
19176
|
this.backfillLastFailureAt = failedAt;
|
|
18984
19177
|
const retryInMs = this.backfillFailureCount < 3 ? CHUNK_BACKFILL_RETRY_BASE_MS * 2 ** (this.backfillFailureCount - 1) : null;
|
|
18985
19178
|
this.backfillNextRetryAt = retryInMs === null ? Number.POSITIVE_INFINITY : failedAt + retryInMs;
|
|
18986
|
-
log$
|
|
19179
|
+
log$13.warn("legacy memory chunk backfill failed", {
|
|
18987
19180
|
attempt: this.backfillFailureCount,
|
|
18988
19181
|
maxAttempts: 3,
|
|
18989
19182
|
retryInMs,
|
|
@@ -19281,7 +19474,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
19281
19474
|
const entry = readEntry(this, key);
|
|
19282
19475
|
if (entry.state !== "pending_reprocess" || entry.reprocessReason === null) throw new StorageError(`Cannot reopen atomic extraction from state '${entry.state}'`);
|
|
19283
19476
|
if (entry.reprocessAttemptCount >= attemptCap) {
|
|
19284
|
-
log$
|
|
19477
|
+
log$13.error("atomic extraction chunk stuck at reprocess attempt cap", {
|
|
19285
19478
|
product_session_reference: privateLogReference(key.conversationId),
|
|
19286
19479
|
chunk_hash: key.chunkHash,
|
|
19287
19480
|
version: key.pipelineVersion,
|
|
@@ -21111,7 +21304,7 @@ function canTrustedWrite(kind) {
|
|
|
21111
21304
|
* @purpose Validates and normalizes memory-kind metadata before direct store writes.
|
|
21112
21305
|
* @boundary Storage write chokepoint only; extraction owns metadata semantics.
|
|
21113
21306
|
*/
|
|
21114
|
-
const log$
|
|
21307
|
+
const log$10 = createLogger("sno-station-mem:active-task-shape-alarm");
|
|
21115
21308
|
function validateAtomicCardWrite(input) {
|
|
21116
21309
|
if (input.category !== "state") return;
|
|
21117
21310
|
if (input.subject === null || !input.subject.startsWith("entity:") || input.subject.length === 7) throw new StorageError("state memory requires a non-empty entity subject");
|
|
@@ -21155,7 +21348,7 @@ function formatCause(error) {
|
|
|
21155
21348
|
return error instanceof Error ? error.message : String(error);
|
|
21156
21349
|
}
|
|
21157
21350
|
function shapeAlarm(operation, reason) {
|
|
21158
|
-
log$
|
|
21351
|
+
log$10.error("Active task shape validation failed", {
|
|
21159
21352
|
operation,
|
|
21160
21353
|
reason_code: reason.replace(/[^a-z0-9]+/gi, "_").toLowerCase()
|
|
21161
21354
|
}, {
|
|
@@ -21600,7 +21793,7 @@ async function readAtomicArrivalRetirementCandidateSet(store, input) {
|
|
|
21600
21793
|
};
|
|
21601
21794
|
const scoreById = scoreCandidatesBySimilarity(store, await store.embedder.embed(nominatedRow.text), candidates.map(({ id }) => id));
|
|
21602
21795
|
const ranked = candidates.sort((left, right) => (scoreById.get(right.id) ?? Number.NEGATIVE_INFINITY) - (scoreById.get(left.id) ?? Number.NEGATIVE_INFINITY) || left.id.localeCompare(right.id));
|
|
21603
|
-
if (ranked.length >
|
|
21796
|
+
if (ranked.length > 3) appendArrivalRetirementJournal(store, {
|
|
21604
21797
|
jobId: input.jobId,
|
|
21605
21798
|
nominatedRowId: nominatedRow.id,
|
|
21606
21799
|
outcome: "no-action",
|
|
@@ -21608,12 +21801,12 @@ async function readAtomicArrivalRetirementCandidateSet(store, input) {
|
|
|
21608
21801
|
actionsApplied: 0,
|
|
21609
21802
|
detail: {
|
|
21610
21803
|
nominatedRowId: nominatedRow.id,
|
|
21611
|
-
omittedCount: ranked.length -
|
|
21804
|
+
omittedCount: ranked.length - 3
|
|
21612
21805
|
}
|
|
21613
21806
|
});
|
|
21614
21807
|
return {
|
|
21615
21808
|
nominatedRow: judgedRow(nominatedRow),
|
|
21616
|
-
candidateRows: ranked.slice(0,
|
|
21809
|
+
candidateRows: ranked.slice(0, 3).map(judgedRow)
|
|
21617
21810
|
};
|
|
21618
21811
|
}
|
|
21619
21812
|
function journalAtomicArrivalRetirementRefusal(store, input) {
|
|
@@ -23542,7 +23735,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
23542
23735
|
async store(entry) {
|
|
23543
23736
|
const safeEntry = sanitizeStoreInput(entry);
|
|
23544
23737
|
const lane = safeEntry.lane ?? "active";
|
|
23545
|
-
log$
|
|
23738
|
+
log$13.debug("storing memory", {
|
|
23546
23739
|
category: safeEntry.category,
|
|
23547
23740
|
projectId: safeEntry.projectId
|
|
23548
23741
|
}, {
|
|
@@ -23585,7 +23778,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
23585
23778
|
if (writeIdentity) {
|
|
23586
23779
|
const alreadyWritten = this.findByExtractionIdempotencyKey(projectId, writeIdentity);
|
|
23587
23780
|
if (alreadyWritten) {
|
|
23588
|
-
log$
|
|
23781
|
+
log$13.debug("idempotency key match, skipping store", {
|
|
23589
23782
|
projectId,
|
|
23590
23783
|
memory_id: alreadyWritten.id
|
|
23591
23784
|
}, {
|
|
@@ -23599,7 +23792,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
23599
23792
|
}
|
|
23600
23793
|
const earlyDup = this.readExistingByHash(projectId, hash, category);
|
|
23601
23794
|
if (earlyDup && !canRevive(earlyDup)) {
|
|
23602
|
-
log$
|
|
23795
|
+
log$13.debug("content hash match, skipping store", {
|
|
23603
23796
|
projectId,
|
|
23604
23797
|
memory_id: earlyDup.id
|
|
23605
23798
|
}, {
|
|
@@ -23616,7 +23809,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
23616
23809
|
if (writeIdentity) {
|
|
23617
23810
|
const alreadyWritten = this.findByExtractionIdempotencyKey(projectId, writeIdentity);
|
|
23618
23811
|
if (alreadyWritten) {
|
|
23619
|
-
log$
|
|
23812
|
+
log$13.debug("idempotency key match, skipping store", {
|
|
23620
23813
|
projectId,
|
|
23621
23814
|
memory_id: alreadyWritten.id
|
|
23622
23815
|
}, {
|
|
@@ -23630,7 +23823,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
23630
23823
|
}
|
|
23631
23824
|
const existing = this.readExistingByHash(projectId, hash, category);
|
|
23632
23825
|
if (existing && !canRevive(existing)) {
|
|
23633
|
-
log$
|
|
23826
|
+
log$13.debug("content hash match, skipping store", {
|
|
23634
23827
|
projectId,
|
|
23635
23828
|
memory_id: existing.id
|
|
23636
23829
|
}, {
|
|
@@ -23940,7 +24133,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
23940
24133
|
assertProfileRecoveryWrite(args.profileRecovery);
|
|
23941
24134
|
const { activeFactGuard, activeTaskProjectionGuard, closes, preserveExisting, reviveInvalidatedExisting } = args;
|
|
23942
24135
|
const create = sanitizeStoreInput(args.create);
|
|
23943
|
-
log$
|
|
24136
|
+
log$13.debug("supersede write", {
|
|
23944
24137
|
category: create.category,
|
|
23945
24138
|
projectId: create.projectId,
|
|
23946
24139
|
closes: closes.length
|
|
@@ -24720,7 +24913,7 @@ function mergeMetadata(current, patch) {
|
|
|
24720
24913
|
Object.assign(MemoryStore.prototype, {
|
|
24721
24914
|
async update(id, changes) {
|
|
24722
24915
|
const countRecordTokens = await recordTokenCounter(this.embedder);
|
|
24723
|
-
log$
|
|
24916
|
+
log$13.debug("updating memory", { memory_id: id }, {
|
|
24724
24917
|
event_name: "sno_station_mem.memory-store-update-api.updating.memory",
|
|
24725
24918
|
file: "packages/memory/src/store/memory-store-update-api.ts",
|
|
24726
24919
|
function: "update",
|
|
@@ -24845,7 +25038,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
24845
25038
|
});
|
|
24846
25039
|
},
|
|
24847
25040
|
async updateTier(memoryId, newTier, options) {
|
|
24848
|
-
log$
|
|
25041
|
+
log$13.debug("updating tier", {
|
|
24849
25042
|
memory_id: memoryId,
|
|
24850
25043
|
tier: newTier
|
|
24851
25044
|
}, {
|
|
@@ -24867,7 +25060,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
24867
25060
|
});
|
|
24868
25061
|
},
|
|
24869
25062
|
async updateMetadata(memoryId, patch) {
|
|
24870
|
-
log$
|
|
25063
|
+
log$13.debug("updating metadata", { memory_id: memoryId }, {
|
|
24871
25064
|
event_name: "sno_station_mem.memory-store-update-api.updating.metadata",
|
|
24872
25065
|
file: "packages/memory/src/store/memory-store-update-api.ts",
|
|
24873
25066
|
function: "updateMetadata",
|
|
@@ -24885,7 +25078,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
24885
25078
|
});
|
|
24886
25079
|
},
|
|
24887
25080
|
async resolveReflectionItem(memoryId, opts) {
|
|
24888
|
-
log$
|
|
25081
|
+
log$13.debug("resolving reflection item", { memory_id: memoryId }, {
|
|
24889
25082
|
event_name: "sno_station_mem.memory-store-update-api.resolving.reflection.item",
|
|
24890
25083
|
file: "packages/memory/src/store/memory-store-update-api.ts",
|
|
24891
25084
|
function: "resolveReflectionItem",
|
|
@@ -24920,7 +25113,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
24920
25113
|
*/
|
|
24921
25114
|
async applyMetadataDeltas(entries) {
|
|
24922
25115
|
if (entries.length === 0) return;
|
|
24923
|
-
log$
|
|
25116
|
+
log$13.debug("applying metadata deltas", { count: entries.length }, {
|
|
24924
25117
|
event_name: "sno_station_mem.memory-store-update-api.applying.metadata.deltas",
|
|
24925
25118
|
file: "packages/memory/src/store/memory-store-update-api.ts",
|
|
24926
25119
|
function: "applyMetadataDeltas",
|
|
@@ -24944,7 +25137,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
24944
25137
|
});
|
|
24945
25138
|
},
|
|
24946
25139
|
async applyMetadataDelta(memoryId, deltaFn) {
|
|
24947
|
-
log$
|
|
25140
|
+
log$13.debug("applying metadata delta", { memory_id: memoryId }, {
|
|
24948
25141
|
event_name: "sno_station_mem.memory-store-update-api.applying.metadata.delta",
|
|
24949
25142
|
file: "packages/memory/src/store/memory-store-update-api.ts",
|
|
24950
25143
|
function: "applyMetadataDelta",
|
|
@@ -24965,7 +25158,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
24965
25158
|
});
|
|
24966
25159
|
//#endregion
|
|
24967
25160
|
//#region src/store/memory-store-rem-api.ts
|
|
24968
|
-
const log$
|
|
25161
|
+
const log$8 = createLogger("sno-station-mem:rem-write");
|
|
24969
25162
|
Object.assign(MemoryStore.prototype, { async applyRemTextVersion(input) {
|
|
24970
25163
|
if (input.reason.trim().length === 0) throw new Error("mutation reason is required");
|
|
24971
25164
|
if (input.idempotencyKey !== void 0 && input.idempotencyKey.trim().length === 0) throw new Error("REM idempotency key must be non-empty");
|
|
@@ -24996,7 +25189,7 @@ Object.assign(MemoryStore.prototype, { async applyRemTextVersion(input) {
|
|
|
24996
25189
|
});
|
|
24997
25190
|
} catch (error) {
|
|
24998
25191
|
if (completedMutation === void 0) throw error;
|
|
24999
|
-
log$
|
|
25192
|
+
log$8.error("rem_write_completion_audit_failed", {
|
|
25000
25193
|
error,
|
|
25001
25194
|
row_id: input.rowId
|
|
25002
25195
|
}, {
|
|
@@ -25105,7 +25298,7 @@ async function applyTransaction(store, input, chunks) {
|
|
|
25105
25298
|
}
|
|
25106
25299
|
});
|
|
25107
25300
|
} catch (error) {
|
|
25108
|
-
log$
|
|
25301
|
+
log$8.error("rem_write_receipt_failed", {
|
|
25109
25302
|
error,
|
|
25110
25303
|
row_id: existing.id
|
|
25111
25304
|
}, {
|
|
@@ -25312,7 +25505,7 @@ function buildChunkSearchResults(vecRows, metaRows, limit, minScore) {
|
|
|
25312
25505
|
Object.assign(MemoryStore.prototype, {
|
|
25313
25506
|
async searchChunksSemantic(vector, opts = {}) {
|
|
25314
25507
|
if (!this.db.vectorSearchAvailable) {
|
|
25315
|
-
log$
|
|
25508
|
+
log$13.error("storage.vector.search.unavailable", { dbPath: this.dbPath }, {
|
|
25316
25509
|
event_name: "storage.vector.search.unavailable",
|
|
25317
25510
|
file: "packages/memory/src/store/memory-store-chunk-search.ts",
|
|
25318
25511
|
function: "searchChunksSemantic",
|
|
@@ -25335,7 +25528,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25335
25528
|
const metaRows = readSemanticMetaRows(this.sqlite, vecRows, opts);
|
|
25336
25529
|
const results = buildChunkSearchResults(vecRows, metaRows, limit, minScore);
|
|
25337
25530
|
if (results.length >= limit || vecRows.length < candidateBudget) {
|
|
25338
|
-
log$
|
|
25531
|
+
log$13.debug("chunk semantic search", {
|
|
25339
25532
|
limit,
|
|
25340
25533
|
projectIdFilter: opts.projectIdFilter,
|
|
25341
25534
|
vecCandidates: vecRows.length,
|
|
@@ -25355,7 +25548,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25355
25548
|
candidateBudget = Math.min(candidateBudget * SEMANTIC_CANDIDATE_GROWTH_FACTOR, vectorRowCount);
|
|
25356
25549
|
}
|
|
25357
25550
|
} catch (error) {
|
|
25358
|
-
log$
|
|
25551
|
+
log$13.error("chunk semantic search failed", {
|
|
25359
25552
|
error,
|
|
25360
25553
|
limit,
|
|
25361
25554
|
projectIdFilter: opts.projectIdFilter,
|
|
@@ -25420,7 +25613,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25420
25613
|
rank: index + 1
|
|
25421
25614
|
});
|
|
25422
25615
|
});
|
|
25423
|
-
log$
|
|
25616
|
+
log$13.debug("chunk keyword search", {
|
|
25424
25617
|
query_length: safeQuery?.length ?? "unavailable",
|
|
25425
25618
|
limit,
|
|
25426
25619
|
minScore,
|
|
@@ -25433,7 +25626,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25433
25626
|
});
|
|
25434
25627
|
return results;
|
|
25435
25628
|
} catch (error) {
|
|
25436
|
-
log$
|
|
25629
|
+
log$13.error("chunk keyword search failed", {
|
|
25437
25630
|
error,
|
|
25438
25631
|
query_length: safeQuery?.length ?? "unavailable",
|
|
25439
25632
|
limit,
|
|
@@ -25609,7 +25802,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25609
25802
|
if (results.length >= limit) break;
|
|
25610
25803
|
}
|
|
25611
25804
|
this.attachSnippets(results, opts.facetPolicy);
|
|
25612
|
-
log$
|
|
25805
|
+
log$13.debug("semantic search (memory-level wrapper)", {
|
|
25613
25806
|
limit,
|
|
25614
25807
|
chunkLimit,
|
|
25615
25808
|
projectIdFilter: opts.projectIdFilter,
|
|
@@ -25655,7 +25848,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25655
25848
|
if (results.length >= limit) break;
|
|
25656
25849
|
}
|
|
25657
25850
|
this.attachSnippets(results, opts.facetPolicy);
|
|
25658
|
-
log$
|
|
25851
|
+
log$13.debug("keyword search (memory-level wrapper)", {
|
|
25659
25852
|
limit,
|
|
25660
25853
|
chunkLimit,
|
|
25661
25854
|
projectIdFilter: opts.projectIdFilter,
|
|
@@ -25686,7 +25879,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25686
25879
|
neighborAfter: 2
|
|
25687
25880
|
});
|
|
25688
25881
|
} catch (err) {
|
|
25689
|
-
log$
|
|
25882
|
+
log$13.warn("snippet expand window failed; falling back to entry text", {
|
|
25690
25883
|
memory_id: result.entry.id,
|
|
25691
25884
|
chunkIndex: result.chunkIndex,
|
|
25692
25885
|
totalChunks,
|
|
@@ -25826,7 +26019,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25826
26019
|
}
|
|
25827
26020
|
return metadata;
|
|
25828
26021
|
} catch (e) {
|
|
25829
|
-
log$
|
|
26022
|
+
log$13.warn("malformed metadata JSON", {
|
|
25830
26023
|
memory_id: memoryId,
|
|
25831
26024
|
error: e
|
|
25832
26025
|
}, {
|
|
@@ -25890,7 +26083,7 @@ function writeDeleteEvents(internals, rows, reason) {
|
|
|
25890
26083
|
}
|
|
25891
26084
|
Object.assign(MemoryStore.prototype, {
|
|
25892
26085
|
async delete(idOrPrefix, options) {
|
|
25893
|
-
log$
|
|
26086
|
+
log$13.info("deleting memories", { idOrPrefix }, {
|
|
25894
26087
|
event_name: "sno_station_mem.memory-store-admin-api.deleting.memories",
|
|
25895
26088
|
file: "packages/memory/src/store/memory-store-admin-api.ts",
|
|
25896
26089
|
function: "delete",
|
|
@@ -25915,7 +26108,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25915
26108
|
async deleteMany(ids, options) {
|
|
25916
26109
|
const uniqueIds = Array.from(new Set(ids));
|
|
25917
26110
|
if (uniqueIds.length === 0) return 0;
|
|
25918
|
-
log$
|
|
26111
|
+
log$13.info("deleting many memories", { count: uniqueIds.length }, {
|
|
25919
26112
|
event_name: "sno_station_mem.memory-store-admin-api.deleting.many.memories",
|
|
25920
26113
|
file: "packages/memory/src/store/memory-store-admin-api.ts",
|
|
25921
26114
|
function: "deleteMany",
|
|
@@ -25949,7 +26142,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
25949
26142
|
}).immediate();
|
|
25950
26143
|
},
|
|
25951
26144
|
async bulkDelete(filter, options) {
|
|
25952
|
-
log$
|
|
26145
|
+
log$13.info("bulk delete", {
|
|
25953
26146
|
projectId: filter.projectId,
|
|
25954
26147
|
category: filter.category
|
|
25955
26148
|
}, {
|
|
@@ -26020,7 +26213,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
26020
26213
|
unplacedParams.push(filter.category);
|
|
26021
26214
|
}
|
|
26022
26215
|
this.sqlite.prepare(`DELETE FROM nodix_unplaced_memory_candidates${unplacedWhere.length > 0 ? ` WHERE ${unplacedWhere.join(" AND ")}` : ""}`).run(...unplacedParams);
|
|
26023
|
-
if (truncated) log$
|
|
26216
|
+
if (truncated) log$13.warn("bulk delete reached safety iteration cap", {
|
|
26024
26217
|
projectId: filter.projectId,
|
|
26025
26218
|
category: filter.category,
|
|
26026
26219
|
deleted,
|
|
@@ -26063,7 +26256,7 @@ Object.assign(MemoryStore.prototype, {
|
|
|
26063
26256
|
this.sqlite.exec("PRAGMA optimize");
|
|
26064
26257
|
this.sqlite.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
26065
26258
|
} catch (error) {
|
|
26066
|
-
log$
|
|
26259
|
+
log$13.warn("sqlite close-time maintenance failed", { error }, {
|
|
26067
26260
|
event_name: "sno_station_mem.memory-store-admin-api.sqlite.close.time.maintenance.failed",
|
|
26068
26261
|
file: "packages/memory/src/store/memory-store-admin-api.ts",
|
|
26069
26262
|
function: "closeSqlite",
|
|
@@ -26159,7 +26352,7 @@ function truncateToTokens(text, maxTokens, countTokens) {
|
|
|
26159
26352
|
* @see store.ts, retriever.ts.
|
|
26160
26353
|
*/
|
|
26161
26354
|
/** Local ONNX embedding with an LRU cache and oversized-text chunking. */
|
|
26162
|
-
const log$
|
|
26355
|
+
const log$7 = createLogger("sno-station-mem:embed");
|
|
26163
26356
|
var Embedder = class {
|
|
26164
26357
|
provider;
|
|
26165
26358
|
chunkingEnabled;
|
|
@@ -26189,7 +26382,7 @@ var Embedder = class {
|
|
|
26189
26382
|
maxSize: 256,
|
|
26190
26383
|
ttlMs: CACHE_TTL_MS
|
|
26191
26384
|
});
|
|
26192
|
-
log$
|
|
26385
|
+
log$7.info("embedder initialized", {
|
|
26193
26386
|
provider: providerKind,
|
|
26194
26387
|
model: this.model,
|
|
26195
26388
|
dimensions: this.dimensions,
|
|
@@ -26249,7 +26442,7 @@ var Embedder = class {
|
|
|
26249
26442
|
if (pieceTokens > 512) throw new EmbeddingError(`Embedder chunk of ${pieceTokens} tokens exceeds DEFAULT_MAX_CONTEXT_TOKENS (512)`);
|
|
26250
26443
|
}
|
|
26251
26444
|
if (chunks.length <= 1) return this.embedDirect(chunks[0] ?? text);
|
|
26252
|
-
log$
|
|
26445
|
+
log$7.warn("legacy chunker invoked (embedding-API safety net)", {
|
|
26253
26446
|
chunks: chunks.length,
|
|
26254
26447
|
totalTokens: tokens,
|
|
26255
26448
|
maxTokens: 512
|
|
@@ -26267,7 +26460,7 @@ var Embedder = class {
|
|
|
26267
26460
|
const vector = await this.provider.embed(text);
|
|
26268
26461
|
return this.toFloat32(vector);
|
|
26269
26462
|
} catch (error) {
|
|
26270
|
-
log$
|
|
26463
|
+
log$7.error("passage embedding failed", {
|
|
26271
26464
|
textLength: text.length,
|
|
26272
26465
|
error
|
|
26273
26466
|
}, {
|
|
@@ -26282,7 +26475,7 @@ var Embedder = class {
|
|
|
26282
26475
|
/** Implements embed many as the local embedding generation operation. */
|
|
26283
26476
|
async embedMany(values) {
|
|
26284
26477
|
await this.awaitWarmup();
|
|
26285
|
-
log$
|
|
26478
|
+
log$7.debug("batch embedding", { count: values.length }, {
|
|
26286
26479
|
event_name: "sno_station_mem.embedding-provider-client.batch.embedding",
|
|
26287
26480
|
file: "packages/memory/src/engine/extraction/embedding-provider-client.ts",
|
|
26288
26481
|
function: "embedMany",
|
|
@@ -26293,7 +26486,7 @@ var Embedder = class {
|
|
|
26293
26486
|
if (vectors.length !== values.length) throw new EmbeddingError(`Embedding provider returned ${vectors.length} vectors for ${values.length} inputs`);
|
|
26294
26487
|
return vectors.map((v) => this.toFloat32(v));
|
|
26295
26488
|
} catch (error) {
|
|
26296
|
-
log$
|
|
26489
|
+
log$7.error("batch embedding failed", {
|
|
26297
26490
|
count: values.length,
|
|
26298
26491
|
error
|
|
26299
26492
|
}, {
|
|
@@ -26332,14 +26525,14 @@ var Embedder = class {
|
|
|
26332
26525
|
if (this.modelDownload) await ensureModelDownloaded(this.modelDownload);
|
|
26333
26526
|
const vector = await this.provider.embed("warmup");
|
|
26334
26527
|
if (vector.length !== this.dimensions) throw new EmbeddingError(`Embedder warmup dimension mismatch: expected ${this.dimensions}, got ${vector.length}`);
|
|
26335
|
-
log$
|
|
26528
|
+
log$7.info("embedder warmup ok", { dimensions: this.dimensions }, {
|
|
26336
26529
|
event_name: "sno_station_mem.embedding-provider-client.embedder.warmup.ok",
|
|
26337
26530
|
file: "packages/memory/src/engine/extraction/embedding-provider-client.ts",
|
|
26338
26531
|
function: "<anonymous callback>",
|
|
26339
26532
|
site_id: "embedding-provider-client.<anonymous callback>.32cc9ec43e"
|
|
26340
26533
|
});
|
|
26341
26534
|
} catch (error) {
|
|
26342
|
-
log$
|
|
26535
|
+
log$7.error("embedder warmup failed", { error }, {
|
|
26343
26536
|
event_name: "sno_station_mem.embedding-provider-client.embedder.warmup.failed",
|
|
26344
26537
|
file: "packages/memory/src/engine/extraction/embedding-provider-client.ts",
|
|
26345
26538
|
function: "<anonymous callback>",
|
|
@@ -26377,7 +26570,7 @@ function createEmbedder(config, stateDir) {
|
|
|
26377
26570
|
* run-dir provided via `EVAL_TRACE_DIR` (env). Phase 0 instrumentation
|
|
26378
26571
|
* (MRR/Recall, gold-rank, miss classification) remains explicitly waived.
|
|
26379
26572
|
*/
|
|
26380
|
-
const log$
|
|
26573
|
+
const log$6 = createLogger("sno-station-mem:eval-trace");
|
|
26381
26574
|
/**
|
|
26382
26575
|
* Returns true when the eval-trace surface should write. Reads the env var at
|
|
26383
26576
|
* call time so harness-flipped values take effect without a re-import.
|
|
@@ -26412,7 +26605,7 @@ function appendQaTrace(trace, traceDirOverride) {
|
|
|
26412
26605
|
context: currentLogContext()
|
|
26413
26606
|
})}\n`, "utf8");
|
|
26414
26607
|
} catch (err) {
|
|
26415
|
-
log$
|
|
26608
|
+
log$6.warn("failed to append qa trace", { error: err }, {
|
|
26416
26609
|
event_name: "sno_station_mem.trace.failed.to.append.qa.trace",
|
|
26417
26610
|
file: "packages/memory/src/engine/eval/trace.ts",
|
|
26418
26611
|
function: "appendQaTrace",
|
|
@@ -26482,7 +26675,7 @@ function sha256Hex(input) {
|
|
|
26482
26675
|
* Tracks memory access patterns to support reinforcement-based decay.
|
|
26483
26676
|
* Frequently accessed memories decay more slowly (longer effective half-life).
|
|
26484
26677
|
*/
|
|
26485
|
-
const log$
|
|
26678
|
+
const log$5 = createLogger("sno-station-mem:access-tracker");
|
|
26486
26679
|
const MIN_ACCESS_COUNT = 0;
|
|
26487
26680
|
const LEGACY_MAX_ACCESS_COUNT = 1e4;
|
|
26488
26681
|
/** Default debounce interval before flushing pending writes (5 seconds) */
|
|
@@ -26631,7 +26824,7 @@ var AccessTracker = class {
|
|
|
26631
26824
|
this.clearTimer();
|
|
26632
26825
|
if (this.flushPromise) await this.flushPromise;
|
|
26633
26826
|
if (this.pending.size > 0) await this.doFlush();
|
|
26634
|
-
if (this.pending.size > 0) log$
|
|
26827
|
+
if (this.pending.size > 0) log$5.warn("destroying with pending writes", { pendingCount: this.pending.size }, {
|
|
26635
26828
|
event_name: "sno_station_mem.access-tracker.destroying.with.pending.writes",
|
|
26636
26829
|
file: "packages/memory/src/engine/retrieval/access-tracker.ts",
|
|
26637
26830
|
function: "destroy",
|
|
@@ -26666,7 +26859,7 @@ var AccessTracker = class {
|
|
|
26666
26859
|
const failures = (this.writeFailures.get(id) ?? 0) + 1;
|
|
26667
26860
|
if (failures >= MAX_WRITE_FAILURES_PER_ID) {
|
|
26668
26861
|
this.writeFailures.delete(id);
|
|
26669
|
-
log$
|
|
26862
|
+
log$5.warn("dropping access delta after repeated write failures", {
|
|
26670
26863
|
memory_id: id,
|
|
26671
26864
|
failures,
|
|
26672
26865
|
error: err
|
|
@@ -26681,7 +26874,7 @@ var AccessTracker = class {
|
|
|
26681
26874
|
this.writeFailures.set(id, failures);
|
|
26682
26875
|
this.pending.set(id, (this.pending.get(id) ?? 0) + delta);
|
|
26683
26876
|
}
|
|
26684
|
-
log$
|
|
26877
|
+
log$5.warn("access flush batch failed", {
|
|
26685
26878
|
batchSize: batch.size,
|
|
26686
26879
|
error: err,
|
|
26687
26880
|
committed_count: 0
|
|
@@ -26713,7 +26906,7 @@ var AccessTracker = class {
|
|
|
26713
26906
|
if (prevLast > 0 && now - prevLast < this.recallLifecycle.accessRateLimitMs) return void 0;
|
|
26714
26907
|
if (prevCount > ceiling && !this.clampedOnce.has(id)) {
|
|
26715
26908
|
this.clampedOnce.add(id);
|
|
26716
|
-
log$
|
|
26909
|
+
log$5.warn("legacy access count clamped to ceiling", {
|
|
26717
26910
|
memory_id: id,
|
|
26718
26911
|
previousCount: prevCount,
|
|
26719
26912
|
ceiling
|
|
@@ -27071,7 +27264,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27071
27264
|
});
|
|
27072
27265
|
//#endregion
|
|
27073
27266
|
//#region src/engine/retrieval/retrieval-scoring-utils.ts
|
|
27074
|
-
const log$
|
|
27267
|
+
const log$4 = createLogger$1("sno-station-mem:retriever");
|
|
27075
27268
|
function dotProduct(a, b) {
|
|
27076
27269
|
let sum = 0;
|
|
27077
27270
|
const len = a.length;
|
|
@@ -27139,7 +27332,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27139
27332
|
aggregationIncomplete: result.aggregationIncomplete
|
|
27140
27333
|
}));
|
|
27141
27334
|
trace?.endStage(mapped.map((result) => result.entry.id), mapped.map((result) => result.score));
|
|
27142
|
-
log$
|
|
27335
|
+
log$4.info("aggregation evidence served", {
|
|
27143
27336
|
rows: mapped.length,
|
|
27144
27337
|
scopeRows: mapped[0]?.scopeRowCount ?? 0,
|
|
27145
27338
|
readingBudget: context.limit,
|
|
@@ -27231,14 +27424,14 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27231
27424
|
throw new RetrievalError("Both vector and keyword search failed", vectorSettled.reason);
|
|
27232
27425
|
}
|
|
27233
27426
|
let vectorResults = vectorSettled.status === "fulfilled" ? vectorSettled.value : [];
|
|
27234
|
-
if (vectorSettled.status === "rejected") log$
|
|
27427
|
+
if (vectorSettled.status === "rejected") log$4.warn("vector search branch failed, using keyword-only", { error: vectorError }, {
|
|
27235
27428
|
event_name: "memory.retriever_search_modes.diagnostic",
|
|
27236
27429
|
file: "packages/memory/src/engine/retrieval/retriever-search-modes.ts",
|
|
27237
27430
|
function: "precisionRecall",
|
|
27238
27431
|
site_id: "retrieval.retriever-search-modes.precisionRecall.97b8770f50"
|
|
27239
27432
|
});
|
|
27240
27433
|
let keywordResults = keywordSettled.status === "fulfilled" ? keywordSettled.value : [];
|
|
27241
|
-
if (keywordSettled.status === "rejected") log$
|
|
27434
|
+
if (keywordSettled.status === "rejected") log$4.warn("keyword search branch failed, using vector-only", { error: keywordError }, {
|
|
27242
27435
|
event_name: "memory.retriever_search_modes.diagnostic",
|
|
27243
27436
|
file: "packages/memory/src/engine/retrieval/retriever-search-modes.ts",
|
|
27244
27437
|
function: "precisionRecall",
|
|
@@ -27256,7 +27449,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27256
27449
|
trace?.startStage("rrf_fusion", [...vectorResults.map((r) => r.entry.id), ...keywordResults.map((r) => r.entry.id)]);
|
|
27257
27450
|
let fused = this.rrfFuse(vectorResults, keywordResults);
|
|
27258
27451
|
trace?.endStage(fused.map((r) => r.entry.id), fused.map((r) => r.score));
|
|
27259
|
-
log$
|
|
27452
|
+
log$4.debug("precision recall search", {
|
|
27260
27453
|
vectorCount: vectorResults.length,
|
|
27261
27454
|
keywordCount: keywordResults.length,
|
|
27262
27455
|
fusedCount: fused.length,
|
|
@@ -27558,7 +27751,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27558
27751
|
if (this.config.rerank === "lightweight" || !this.config.rerankApiKey) return { candidates: this.rerankLightweight(candidates, queryVector) };
|
|
27559
27752
|
const rerankEndpoint = this.config.rerankEndpoint ?? RERANK_DEFAULT_ENDPOINTS[provider];
|
|
27560
27753
|
if (!rerankEndpoint) {
|
|
27561
|
-
log$
|
|
27754
|
+
log$4.warn("rerank skipped: no endpoint for provider", { provider }, {
|
|
27562
27755
|
event_name: "memory.retriever_rerank.diagnostic",
|
|
27563
27756
|
file: "packages/memory/src/engine/retrieval/retriever-rerank.ts",
|
|
27564
27757
|
function: "rerank",
|
|
@@ -27582,7 +27775,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27582
27775
|
const queryTokens = this.embedder.countTokens(query);
|
|
27583
27776
|
const documentTokenBudget = 509 - queryTokens;
|
|
27584
27777
|
if (documentTokenBudget <= 0) {
|
|
27585
|
-
log$
|
|
27778
|
+
log$4.warn("rerank skipped: the query alone fills the reranker token window", {
|
|
27586
27779
|
queryTokens,
|
|
27587
27780
|
window: 512,
|
|
27588
27781
|
templateTokens: 3
|
|
@@ -27606,7 +27799,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27606
27799
|
if (bounded !== c.entry.text) truncatedCandidates += 1;
|
|
27607
27800
|
return bounded;
|
|
27608
27801
|
});
|
|
27609
|
-
if (truncatedCandidates > 0) log$
|
|
27802
|
+
if (truncatedCandidates > 0) log$4.warn("rerank candidates were cut to the document budget the query left", {
|
|
27610
27803
|
truncatedCandidates,
|
|
27611
27804
|
documentTokenBudget,
|
|
27612
27805
|
queryTokens
|
|
@@ -27643,7 +27836,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27643
27836
|
const target = Math.max(1, Math.floor(allowed * localPairTokens / named.inputTokens) - queryTokens);
|
|
27644
27837
|
return this.embedder.truncateToTokens(text, target);
|
|
27645
27838
|
});
|
|
27646
|
-
log$
|
|
27839
|
+
log$4.warn("rerank batch refused over its token window; resending the named texts cut to fit", {
|
|
27647
27840
|
status: response.status,
|
|
27648
27841
|
overLongCount: refusal.overLong.length,
|
|
27649
27842
|
maxInputTokens: refusal.maxInputTokens,
|
|
@@ -27657,7 +27850,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27657
27850
|
});
|
|
27658
27851
|
continue;
|
|
27659
27852
|
}
|
|
27660
|
-
log$
|
|
27853
|
+
log$4.warn("rerank API failed, using pre-rerank results", {
|
|
27661
27854
|
status: response.status,
|
|
27662
27855
|
endpoint_hash: createHash("sha256").update(rerankEndpoint).digest("hex"),
|
|
27663
27856
|
retryAfter,
|
|
@@ -27674,7 +27867,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27674
27867
|
}
|
|
27675
27868
|
const parsed = parseRerankResponse(provider, data);
|
|
27676
27869
|
if (!parsed) {
|
|
27677
|
-
log$
|
|
27870
|
+
log$4.warn("rerank API returned unparseable response", {
|
|
27678
27871
|
provider,
|
|
27679
27872
|
endpoint_hash: createHash("sha256").update(rerankEndpoint).digest("hex"),
|
|
27680
27873
|
batchStart: start
|
|
@@ -27742,7 +27935,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27742
27935
|
score: clamp01(this.getRerankSourceScore(r) * LIGHTWEIGHT_RERANK_PENALTY, 0)
|
|
27743
27936
|
}));
|
|
27744
27937
|
const merged = [...reranked, ...unreturned].sort((a, b) => b.score - a.score);
|
|
27745
|
-
log$
|
|
27938
|
+
log$4.debug("reranked", {
|
|
27746
27939
|
totalCandidateCount: candidates.length,
|
|
27747
27940
|
sentToRerankCount: toRerank.length,
|
|
27748
27941
|
returnedCount: reranked.length,
|
|
@@ -27766,7 +27959,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27766
27959
|
let reason;
|
|
27767
27960
|
if (isRerankTimeout(error)) {
|
|
27768
27961
|
reason = "timeout";
|
|
27769
|
-
log$
|
|
27962
|
+
log$4.warn("rerank API timed out, using pre-rerank results", {
|
|
27770
27963
|
timeoutMs: rerankTimeoutMs,
|
|
27771
27964
|
attempts: RERANK_TRANSIENT_ATTEMPTS
|
|
27772
27965
|
}, {
|
|
@@ -27777,7 +27970,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27777
27970
|
});
|
|
27778
27971
|
} else {
|
|
27779
27972
|
reason = "request_error";
|
|
27780
|
-
log$
|
|
27973
|
+
log$4.warn("rerank error, using pre-rerank results", {
|
|
27781
27974
|
error,
|
|
27782
27975
|
attempts: RERANK_TRANSIENT_ATTEMPTS
|
|
27783
27976
|
}, {
|
|
@@ -27836,7 +28029,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27836
28029
|
}
|
|
27837
28030
|
};
|
|
27838
28031
|
});
|
|
27839
|
-
if (dimMismatchCount > 0) log$
|
|
28032
|
+
if (dimMismatchCount > 0) log$4.warn("lightweight rerank: chunk vector dim mismatch on some candidates", {
|
|
27840
28033
|
dimMismatchCount,
|
|
27841
28034
|
queryDim: queryVector.length
|
|
27842
28035
|
}, {
|
|
@@ -27845,7 +28038,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
27845
28038
|
function: "rerankLightweight",
|
|
27846
28039
|
site_id: "retrieval.retriever-rerank.rerankLightweight.70eb2031f1"
|
|
27847
28040
|
});
|
|
27848
|
-
log$
|
|
28041
|
+
log$4.debug("lightweight rerank applied", {
|
|
27849
28042
|
candidateCount: candidates.length,
|
|
27850
28043
|
blendedCount,
|
|
27851
28044
|
fusionWeight: wF,
|
|
@@ -28243,7 +28436,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28243
28436
|
...input,
|
|
28244
28437
|
signal: memoryOperationSignal(input.signal)
|
|
28245
28438
|
});
|
|
28246
|
-
log$
|
|
28439
|
+
log$4.info("retrieval started", {
|
|
28247
28440
|
queryLength: context.query.length,
|
|
28248
28441
|
limit: context.limit,
|
|
28249
28442
|
mode: this.config.mode,
|
|
@@ -28266,7 +28459,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28266
28459
|
const beforeFinalFilter = results.length;
|
|
28267
28460
|
results = results.filter((result) => this.store.isMemoryOnFactSurface(result.entry.id));
|
|
28268
28461
|
this.throwIfAborted(context);
|
|
28269
|
-
if (!isExplicitAggregation && this._accessTracker && (this._recallLifecycle?.autoRecallAccessTracking === true || context.source === "manual") && results.length > 0) this._accessTracker.recordAccess(results.map((r) => r.entry.id));
|
|
28462
|
+
if (!isExplicitAggregation && context.trackAccess !== false && this._accessTracker && (this._recallLifecycle?.autoRecallAccessTracking === true || context.source === "manual") && results.length > 0) this._accessTracker.recordAccess(results.map((r) => r.entry.id));
|
|
28270
28463
|
if (!isExplicitAggregation && this._recallLifecycle?.tierPromoter && this._tierPromoter && results.length > 0) await this.evaluateTopKTierTransitions(results);
|
|
28271
28464
|
const mode = isExplicitAggregation ? "aggregation" : this.config.mode === "vector" || !this.store.hasFtsSupport ? "vector" : "precision-recall";
|
|
28272
28465
|
const finalTrace = trace?.finalize(context.query, mode);
|
|
@@ -28317,7 +28510,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28317
28510
|
...traceMetadata && { traceMetadata }
|
|
28318
28511
|
});
|
|
28319
28512
|
}
|
|
28320
|
-
log$
|
|
28513
|
+
log$4.info("Memory retrieval completed", {
|
|
28321
28514
|
store_reference: privateLogReference(this.store.dbPath),
|
|
28322
28515
|
outcome: results.length ? "success" : "empty_success",
|
|
28323
28516
|
duration_ms: performance.now() - started,
|
|
@@ -28344,7 +28537,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28344
28537
|
});
|
|
28345
28538
|
return results;
|
|
28346
28539
|
} catch (error) {
|
|
28347
|
-
log$
|
|
28540
|
+
log$4.error("Memory retrieval failed", {
|
|
28348
28541
|
outcome: "failed",
|
|
28349
28542
|
error,
|
|
28350
28543
|
duration_ms: performance.now() - started
|
|
@@ -28383,10 +28576,10 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28383
28576
|
this.throwIfAborted(context);
|
|
28384
28577
|
const mode = isExplicitAggregation ? "aggregation" : this.config.mode === "vector" || !this.store.hasFtsSupport ? "vector" : "precision-recall";
|
|
28385
28578
|
const finalTrace = trace.finalize(context.query, mode);
|
|
28386
|
-
if (!isExplicitAggregation && this._accessTracker && (this._recallLifecycle?.autoRecallAccessTracking === true || context.source === "manual") && results.length > 0) this._accessTracker.recordAccess(results.map((r) => r.entry.id));
|
|
28579
|
+
if (!isExplicitAggregation && context.trackAccess !== false && this._accessTracker && (this._recallLifecycle?.autoRecallAccessTracking === true || context.source === "manual") && results.length > 0) this._accessTracker.recordAccess(results.map((r) => r.entry.id));
|
|
28387
28580
|
if (!isExplicitAggregation && this._recallLifecycle?.tierPromoter && this._tierPromoter && results.length > 0) await this.evaluateTopKTierTransitions(results);
|
|
28388
28581
|
if (this._statsCollector) this._statsCollector.recordQuery(finalTrace, context.source ?? "debug");
|
|
28389
|
-
log$
|
|
28582
|
+
log$4.info("Traced memory retrieval completed", {
|
|
28390
28583
|
outcome: results.length ? "success" : "empty_success",
|
|
28391
28584
|
store_reference: privateLogReference(this.store.dbPath),
|
|
28392
28585
|
duration_ms: performance.now() - started,
|
|
@@ -28411,7 +28604,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28411
28604
|
trace: finalTrace
|
|
28412
28605
|
};
|
|
28413
28606
|
} catch (error) {
|
|
28414
|
-
log$
|
|
28607
|
+
log$4.error("Traced memory retrieval failed", {
|
|
28415
28608
|
outcome: "failed",
|
|
28416
28609
|
error,
|
|
28417
28610
|
duration_ms: performance.now() - started
|
|
@@ -28474,18 +28667,393 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
28474
28667
|
if (!transition || transition.toTier === tier) continue;
|
|
28475
28668
|
await this.store.updateTier(entry.id, transition.toTier, { writerAuthority: "offline-family" });
|
|
28476
28669
|
} catch (error) {
|
|
28477
|
-
log$
|
|
28478
|
-
memoryId: r.entry.id,
|
|
28479
|
-
error
|
|
28480
|
-
}, {
|
|
28481
|
-
event_name: "memory.retrieval.tier.failed",
|
|
28482
|
-
file: "packages/memory/src/engine/retrieval/retriever-execution.ts",
|
|
28483
|
-
function: "evaluateTopKTierTransitions",
|
|
28484
|
-
site_id: "memory.retrieval.tier.failed"
|
|
28485
|
-
});
|
|
28670
|
+
log$4.warn("tier evaluation failed for memory", {
|
|
28671
|
+
memoryId: r.entry.id,
|
|
28672
|
+
error
|
|
28673
|
+
}, {
|
|
28674
|
+
event_name: "memory.retrieval.tier.failed",
|
|
28675
|
+
file: "packages/memory/src/engine/retrieval/retriever-execution.ts",
|
|
28676
|
+
function: "evaluateTopKTierTransitions",
|
|
28677
|
+
site_id: "memory.retrieval.tier.failed"
|
|
28678
|
+
});
|
|
28679
|
+
}
|
|
28680
|
+
}
|
|
28681
|
+
});
|
|
28682
|
+
//#endregion
|
|
28683
|
+
//#region src/sidecar/rem-job-store.ts
|
|
28684
|
+
/** @file rem-job-store.ts
|
|
28685
|
+
* @purpose Persists append-only REM job state transitions.
|
|
28686
|
+
* @boundary Durable local JSONL journal used by the standalone REM sidecar.
|
|
28687
|
+
*/
|
|
28688
|
+
const log$3 = createLogger("sno-station-mem:rem-jobs");
|
|
28689
|
+
const remJobStateSchema = z.enum([
|
|
28690
|
+
"queued",
|
|
28691
|
+
"running",
|
|
28692
|
+
"done",
|
|
28693
|
+
"failed",
|
|
28694
|
+
"skipped"
|
|
28695
|
+
]);
|
|
28696
|
+
const remJobMeasurementsSchema = z.object({
|
|
28697
|
+
rows_considered: z.number().int().nonnegative(),
|
|
28698
|
+
pairs_built: z.number().int().nonnegative().optional(),
|
|
28699
|
+
pair_cap_binding: z.boolean().optional(),
|
|
28700
|
+
model_calls: z.number().int().nonnegative(),
|
|
28701
|
+
model_tokens: z.number().int().nonnegative(),
|
|
28702
|
+
wall_ms: z.number().int().nonnegative()
|
|
28703
|
+
}).strict();
|
|
28704
|
+
const remJobStatsSchema = z.object({
|
|
28705
|
+
operations: z.number().int().nonnegative(),
|
|
28706
|
+
applied_count: z.number().int().nonnegative().optional(),
|
|
28707
|
+
actionable_candidate_count: z.number().int().nonnegative().optional(),
|
|
28708
|
+
applied_fraction: z.number().min(0).max(1).nullable().optional(),
|
|
28709
|
+
scan: z.object({
|
|
28710
|
+
scope: z.string().min(1),
|
|
28711
|
+
candidate_count: z.number().int().nonnegative(),
|
|
28712
|
+
stamped_skipped_count: z.number().int().nonnegative().optional(),
|
|
28713
|
+
actionable_candidate_count: z.number().int().nonnegative().optional()
|
|
28714
|
+
}).strict().optional(),
|
|
28715
|
+
parse_failure_count: z.number().int().nonnegative().optional(),
|
|
28716
|
+
top_refusal_reasons: z.array(z.string().min(1)).max(2).optional(),
|
|
28717
|
+
measured: remJobMeasurementsSchema.optional(),
|
|
28718
|
+
by_operation: z.array(z.object({
|
|
28719
|
+
operation: z.string().min(1),
|
|
28720
|
+
applied_count: z.number().int().nonnegative(),
|
|
28721
|
+
actionable_candidate_count: z.number().int().nonnegative(),
|
|
28722
|
+
candidate_count: z.number().int().nonnegative(),
|
|
28723
|
+
parse_failure_count: z.number().int().nonnegative(),
|
|
28724
|
+
top_refusal_reasons: z.array(z.string().min(1)).max(2),
|
|
28725
|
+
measured: remJobMeasurementsSchema
|
|
28726
|
+
}).strict()).min(1).optional()
|
|
28727
|
+
}).strict();
|
|
28728
|
+
function parseRemJobStats(value) {
|
|
28729
|
+
const parsed = remJobStatsSchema.safeParse(value);
|
|
28730
|
+
return parsed.success ? parsed.data : void 0;
|
|
28731
|
+
}
|
|
28732
|
+
const remWaveJobSchema = z.object({
|
|
28733
|
+
payloadVersion: z.literal(1),
|
|
28734
|
+
waveId: z.string().min(1),
|
|
28735
|
+
correlationId: z.string().min(1),
|
|
28736
|
+
scope: z.string().min(1),
|
|
28737
|
+
requestedOperations: z.array(z.string().min(1)).min(1),
|
|
28738
|
+
state: remJobStateSchema,
|
|
28739
|
+
startedAt: z.string().datetime().nullable(),
|
|
28740
|
+
finishedAt: z.string().datetime().nullable(),
|
|
28741
|
+
stats: remJobStatsSchema,
|
|
28742
|
+
error: z.string().min(1).optional()
|
|
28743
|
+
}).strict();
|
|
28744
|
+
const legacyJobSchema = z.object({
|
|
28745
|
+
job_id: z.string().min(1),
|
|
28746
|
+
state: remJobStateSchema,
|
|
28747
|
+
type: z.string().min(1),
|
|
28748
|
+
scope: z.string().min(1),
|
|
28749
|
+
started_at: z.string().datetime().nullable(),
|
|
28750
|
+
finished_at: z.string().datetime().nullable(),
|
|
28751
|
+
stats: remJobStatsSchema,
|
|
28752
|
+
error: z.string().min(1).optional(),
|
|
28753
|
+
correlation_id: z.string().min(1)
|
|
28754
|
+
}).strict();
|
|
28755
|
+
const OPERATION_ORDER = [
|
|
28756
|
+
"rem-replace",
|
|
28757
|
+
"rem-update",
|
|
28758
|
+
"rem-distill",
|
|
28759
|
+
"rem-retire"
|
|
28760
|
+
];
|
|
28761
|
+
var RemJobStore = class RemJobStore {
|
|
28762
|
+
journalPath;
|
|
28763
|
+
onDurableTransition;
|
|
28764
|
+
jobs = /* @__PURE__ */ new Map();
|
|
28765
|
+
persistedJobs = /* @__PURE__ */ new Set();
|
|
28766
|
+
mergeKeys = /* @__PURE__ */ new Map();
|
|
28767
|
+
operationQueue = Promise.resolve();
|
|
28768
|
+
journalRecords = 0;
|
|
28769
|
+
constructor(journalPath, onDurableTransition) {
|
|
28770
|
+
this.journalPath = journalPath;
|
|
28771
|
+
this.onDurableTransition = onDurableTransition;
|
|
28772
|
+
}
|
|
28773
|
+
static async open(journalPath, onDurableTransition = () => void 0) {
|
|
28774
|
+
const store = new RemJobStore(journalPath, onDurableTransition);
|
|
28775
|
+
await store.migrateLegacyJournal().catch((error) => store.reportFailure(error));
|
|
28776
|
+
await store.load();
|
|
28777
|
+
return store;
|
|
28778
|
+
}
|
|
28779
|
+
isPersisted(jobId) {
|
|
28780
|
+
return this.persistedJobs.has(jobId);
|
|
28781
|
+
}
|
|
28782
|
+
get(jobId) {
|
|
28783
|
+
const job = this.jobs.get(jobId);
|
|
28784
|
+
return job === void 0 ? void 0 : toRemJob(job);
|
|
28785
|
+
}
|
|
28786
|
+
static async readCompletedJobs(journalPath) {
|
|
28787
|
+
const completed = /* @__PURE__ */ new Map();
|
|
28788
|
+
for await (const line of readJsonlLines(journalPath)) try {
|
|
28789
|
+
const parsed = remWaveJobSchema.parse(JSON.parse(line));
|
|
28790
|
+
if (parsed.state === "done") completed.set(parsed.waveId, toRemJob(parsed));
|
|
28791
|
+
else completed.delete(parsed.waveId);
|
|
28792
|
+
} catch (error) {
|
|
28793
|
+
log$3.error("rem.journal.failed", {
|
|
28794
|
+
error,
|
|
28795
|
+
path: journalPath
|
|
28796
|
+
}, {
|
|
28797
|
+
event_name: "rem.journal.failed",
|
|
28798
|
+
file: "packages/memory/src/sidecar/rem-job-store.ts",
|
|
28799
|
+
function: "readCompletedJobs",
|
|
28800
|
+
site_id: "rem-job-store.readCompletedJobs.invalid-line"
|
|
28801
|
+
});
|
|
28802
|
+
}
|
|
28803
|
+
return [...completed.values()];
|
|
28804
|
+
}
|
|
28805
|
+
nonTerminalJobs() {
|
|
28806
|
+
return Array.from(this.jobs.values()).filter((job) => job.state === "queued" || job.state === "running").map(toRemJob);
|
|
28807
|
+
}
|
|
28808
|
+
async createQueued(type, scope, correlationId) {
|
|
28809
|
+
return this.enqueue(async () => {
|
|
28810
|
+
const requestedOperations = canonicalOperations(typeof type === "string" ? [type] : type);
|
|
28811
|
+
if (requestedOperations.length === 0) throw new Error("REM wave requires at least one supported operation");
|
|
28812
|
+
const mergeKey = `${correlationId}\0${scope}`;
|
|
28813
|
+
const existingId = this.mergeKeys.get(mergeKey);
|
|
28814
|
+
const existing = existingId === void 0 ? void 0 : this.jobs.get(existingId);
|
|
28815
|
+
if (existing !== void 0 && existing.state === "queued") {
|
|
28816
|
+
const mergedOperations = canonicalOperations([...existing.requestedOperations, ...requestedOperations]);
|
|
28817
|
+
if (mergedOperations.length === existing.requestedOperations.length) return {
|
|
28818
|
+
created: false,
|
|
28819
|
+
job: toRemJob(existing)
|
|
28820
|
+
};
|
|
28821
|
+
const updated = remWaveJobSchema.parse({
|
|
28822
|
+
...existing,
|
|
28823
|
+
requestedOperations: mergedOperations
|
|
28824
|
+
});
|
|
28825
|
+
const durable = await this.persist(updated);
|
|
28826
|
+
this.jobs.set(updated.waveId, updated);
|
|
28827
|
+
if (durable) this.onDurableTransition(toRemJob(updated));
|
|
28828
|
+
return {
|
|
28829
|
+
created: false,
|
|
28830
|
+
job: toRemJob(updated)
|
|
28831
|
+
};
|
|
28832
|
+
}
|
|
28833
|
+
if (existing !== void 0 && existing.state !== "skipped" && existing.state !== "failed" && requestedOperations.every((operation) => existing.requestedOperations.includes(operation))) return {
|
|
28834
|
+
created: false,
|
|
28835
|
+
job: toRemJob(existing)
|
|
28836
|
+
};
|
|
28837
|
+
const job = remWaveJobSchema.parse({
|
|
28838
|
+
payloadVersion: 1,
|
|
28839
|
+
waveId: `rem-wave-${randomUUID()}`,
|
|
28840
|
+
correlationId,
|
|
28841
|
+
scope,
|
|
28842
|
+
requestedOperations,
|
|
28843
|
+
state: "queued",
|
|
28844
|
+
startedAt: null,
|
|
28845
|
+
finishedAt: null,
|
|
28846
|
+
stats: { operations: 0 }
|
|
28847
|
+
});
|
|
28848
|
+
const durable = await this.persist(job);
|
|
28849
|
+
this.jobs.set(job.waveId, job);
|
|
28850
|
+
this.mergeKeys.set(mergeKey, job.waveId);
|
|
28851
|
+
const outward = toRemJob(job);
|
|
28852
|
+
if (durable) this.onDurableTransition(outward);
|
|
28853
|
+
return {
|
|
28854
|
+
created: true,
|
|
28855
|
+
job: outward
|
|
28856
|
+
};
|
|
28857
|
+
});
|
|
28858
|
+
}
|
|
28859
|
+
async transition(jobId, transition) {
|
|
28860
|
+
return this.enqueue(async () => {
|
|
28861
|
+
const current = this.jobs.get(jobId);
|
|
28862
|
+
if (!current) throw new Error(`REM job not found: ${jobId}`);
|
|
28863
|
+
const next = remWaveJobSchema.parse({
|
|
28864
|
+
...current,
|
|
28865
|
+
state: transition.state,
|
|
28866
|
+
...transition.started_at === void 0 ? {} : { startedAt: transition.started_at },
|
|
28867
|
+
...transition.finished_at === void 0 ? {} : { finishedAt: transition.finished_at },
|
|
28868
|
+
...transition.stats === void 0 ? {} : { stats: transition.stats },
|
|
28869
|
+
...transition.error === void 0 ? {} : { error: transition.error }
|
|
28870
|
+
});
|
|
28871
|
+
if (next.state === "done") this.jobs.set(jobId, next);
|
|
28872
|
+
const durable = await this.persist(next);
|
|
28873
|
+
this.jobs.set(jobId, next);
|
|
28874
|
+
const outward = toRemJob(next);
|
|
28875
|
+
if (durable) this.onDurableTransition(outward);
|
|
28876
|
+
return outward;
|
|
28877
|
+
});
|
|
28878
|
+
}
|
|
28879
|
+
async load() {
|
|
28880
|
+
if (!existsSync(this.journalPath)) return;
|
|
28881
|
+
await this.removeTornTail();
|
|
28882
|
+
let index = 0;
|
|
28883
|
+
for await (const line of readJsonlLines(this.journalPath)) {
|
|
28884
|
+
index++;
|
|
28885
|
+
this.journalRecords++;
|
|
28886
|
+
try {
|
|
28887
|
+
const job = remWaveJobSchema.parse(JSON.parse(line));
|
|
28888
|
+
this.jobs.set(job.waveId, job);
|
|
28889
|
+
this.mergeKeys.set(`${job.correlationId}\0${job.scope}`, job.waveId);
|
|
28890
|
+
} catch (error) {
|
|
28891
|
+
log$3.error("rem.journal.failed", {
|
|
28892
|
+
path: this.journalPath,
|
|
28893
|
+
line: index,
|
|
28894
|
+
error
|
|
28895
|
+
}, {
|
|
28896
|
+
event_name: "rem.journal.failed",
|
|
28897
|
+
file: "packages/memory/src/sidecar/rem-job-store.ts",
|
|
28898
|
+
function: "load",
|
|
28899
|
+
site_id: "rem-job-store.load.invalid-line"
|
|
28900
|
+
});
|
|
28901
|
+
}
|
|
28902
|
+
}
|
|
28903
|
+
if (this.journalRecords >= 256) await this.compact().catch((error) => this.reportFailure(error));
|
|
28904
|
+
}
|
|
28905
|
+
async removeTornTail() {
|
|
28906
|
+
const handle = await open(this.journalPath, "r");
|
|
28907
|
+
let committed = (await handle.stat()).size;
|
|
28908
|
+
const buffer = Buffer.alloc(65536);
|
|
28909
|
+
try {
|
|
28910
|
+
while (committed > 0) {
|
|
28911
|
+
const start = Math.max(0, committed - buffer.length);
|
|
28912
|
+
const { bytesRead } = await handle.read(buffer, 0, committed - start, start);
|
|
28913
|
+
const newline = buffer.subarray(0, bytesRead).lastIndexOf(10);
|
|
28914
|
+
if (newline >= 0) {
|
|
28915
|
+
committed = start + newline + 1;
|
|
28916
|
+
break;
|
|
28917
|
+
}
|
|
28918
|
+
committed = start;
|
|
28919
|
+
}
|
|
28920
|
+
if (committed < (await handle.stat()).size) await this.truncateJournal(committed);
|
|
28921
|
+
} finally {
|
|
28922
|
+
await handle.close();
|
|
28923
|
+
}
|
|
28924
|
+
}
|
|
28925
|
+
async compact() {
|
|
28926
|
+
const cutoff = (/* @__PURE__ */ new Date(Date.now() - 1728e5)).toISOString();
|
|
28927
|
+
const retained = [...this.jobs.values()].filter((job) => job.state === "queued" || job.state === "running" || (job.finishedAt ?? job.startedAt ?? "") >= cutoff);
|
|
28928
|
+
const temporary = `${this.journalPath}.${randomUUID()}.tmp`;
|
|
28929
|
+
const handle = await open(temporary, "wx", 384);
|
|
28930
|
+
try {
|
|
28931
|
+
try {
|
|
28932
|
+
for (const job of retained) await handle.writeFile(`${JSON.stringify(job)}\n`, "utf8");
|
|
28933
|
+
await handle.sync();
|
|
28934
|
+
} finally {
|
|
28935
|
+
await handle.close();
|
|
28936
|
+
}
|
|
28937
|
+
await rename(temporary, this.journalPath);
|
|
28938
|
+
await syncDirectory$1(path.dirname(this.journalPath));
|
|
28939
|
+
const retainedIds = new Set(retained.map((job) => job.waveId));
|
|
28940
|
+
for (const id of this.jobs.keys()) if (!retainedIds.has(id)) {
|
|
28941
|
+
this.jobs.delete(id);
|
|
28942
|
+
this.persistedJobs.delete(id);
|
|
28943
|
+
}
|
|
28944
|
+
for (const [key, id] of this.mergeKeys) if (!retainedIds.has(id)) this.mergeKeys.delete(key);
|
|
28945
|
+
this.journalRecords = 0;
|
|
28946
|
+
} finally {
|
|
28947
|
+
await rm(temporary, { force: true });
|
|
28948
|
+
}
|
|
28949
|
+
}
|
|
28950
|
+
async migrateLegacyJournal() {
|
|
28951
|
+
const legacyPath = path.join(path.dirname(this.journalPath), "rem-jobs.jsonl");
|
|
28952
|
+
if (!existsSync(legacyPath)) return;
|
|
28953
|
+
const latest = /* @__PURE__ */ new Map();
|
|
28954
|
+
for await (const line of readJsonlLines(legacyPath)) try {
|
|
28955
|
+
const parsed = JSON.parse(line);
|
|
28956
|
+
const job = legacyJobSchema.parse(parsed);
|
|
28957
|
+
latest.set(job.job_id, job);
|
|
28958
|
+
} catch (error) {
|
|
28959
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
28960
|
+
this.reportFailure(reason);
|
|
28961
|
+
}
|
|
28962
|
+
const interrupted = [...latest.values()].filter((job) => job.state === "queued" || job.state === "running");
|
|
28963
|
+
if (interrupted.length > 0) {
|
|
28964
|
+
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
28965
|
+
const handle = await open(legacyPath, "a");
|
|
28966
|
+
try {
|
|
28967
|
+
for (const job of interrupted) await handle.writeFile(`${JSON.stringify({
|
|
28968
|
+
...job,
|
|
28969
|
+
state: "failed",
|
|
28970
|
+
finished_at: finishedAt,
|
|
28971
|
+
error: "sidecar_upgrade_interrupted"
|
|
28972
|
+
})}\n`, "utf8");
|
|
28973
|
+
await handle.sync();
|
|
28974
|
+
} finally {
|
|
28975
|
+
await handle.close();
|
|
28976
|
+
}
|
|
28486
28977
|
}
|
|
28978
|
+
await rename(legacyPath, path.join(path.dirname(legacyPath), "rem-jobs.v0.jsonl"));
|
|
28487
28979
|
}
|
|
28488
|
-
|
|
28980
|
+
reportFailure(error) {
|
|
28981
|
+
log$3.error("rem.journal.failed", {
|
|
28982
|
+
error,
|
|
28983
|
+
path: this.journalPath
|
|
28984
|
+
}, {
|
|
28985
|
+
event_name: "rem.journal.failed",
|
|
28986
|
+
file: "packages/memory/src/sidecar/rem-job-store.ts",
|
|
28987
|
+
function: "reportFailure",
|
|
28988
|
+
site_id: "rem.journal.failed"
|
|
28989
|
+
});
|
|
28990
|
+
}
|
|
28991
|
+
async persist(job) {
|
|
28992
|
+
this.persistedJobs.delete(job.waveId);
|
|
28993
|
+
await this.append(job);
|
|
28994
|
+
this.persistedJobs.add(job.waveId);
|
|
28995
|
+
this.journalRecords++;
|
|
28996
|
+
if (this.journalRecords >= 256) {
|
|
28997
|
+
this.jobs.set(job.waveId, job);
|
|
28998
|
+
await this.compact().catch((error) => this.reportFailure(error));
|
|
28999
|
+
}
|
|
29000
|
+
return true;
|
|
29001
|
+
}
|
|
29002
|
+
async truncateJournal(length) {
|
|
29003
|
+
const handle = await open(this.journalPath, "r+");
|
|
29004
|
+
try {
|
|
29005
|
+
await handle.truncate(length);
|
|
29006
|
+
await handle.sync();
|
|
29007
|
+
} finally {
|
|
29008
|
+
await handle.close();
|
|
29009
|
+
}
|
|
29010
|
+
}
|
|
29011
|
+
async append(job) {
|
|
29012
|
+
const parent = path.dirname(this.journalPath);
|
|
29013
|
+
await mkdir(parent, { recursive: true });
|
|
29014
|
+
const journalAlreadyExisted = existsSync(this.journalPath);
|
|
29015
|
+
const handle = await open(this.journalPath, "a");
|
|
29016
|
+
try {
|
|
29017
|
+
await handle.writeFile(`${JSON.stringify(job)}\n`, "utf8");
|
|
29018
|
+
await handle.sync();
|
|
29019
|
+
} finally {
|
|
29020
|
+
await handle.close();
|
|
29021
|
+
}
|
|
29022
|
+
if (!journalAlreadyExisted) await syncDirectory$1(parent);
|
|
29023
|
+
}
|
|
29024
|
+
enqueue(operation) {
|
|
29025
|
+
const result = this.operationQueue.then(operation);
|
|
29026
|
+
this.operationQueue = result.then(() => void 0, () => void 0);
|
|
29027
|
+
return result;
|
|
29028
|
+
}
|
|
29029
|
+
};
|
|
29030
|
+
function canonicalOperations(operations) {
|
|
29031
|
+
const unique = new Set(operations);
|
|
29032
|
+
return OPERATION_ORDER.filter((operation) => unique.has(operation));
|
|
29033
|
+
}
|
|
29034
|
+
function toRemJob(job) {
|
|
29035
|
+
return {
|
|
29036
|
+
job_id: job.waveId,
|
|
29037
|
+
state: job.state,
|
|
29038
|
+
type: job.requestedOperations[0] ?? "rem-replace",
|
|
29039
|
+
scope: job.scope,
|
|
29040
|
+
started_at: job.startedAt,
|
|
29041
|
+
finished_at: job.finishedAt,
|
|
29042
|
+
stats: job.stats,
|
|
29043
|
+
...job.error === void 0 ? {} : { error: job.error },
|
|
29044
|
+
correlation_id: job.correlationId,
|
|
29045
|
+
requested_operations: [...job.requestedOperations]
|
|
29046
|
+
};
|
|
29047
|
+
}
|
|
29048
|
+
async function syncDirectory$1(directory) {
|
|
29049
|
+
if (process.platform === "win32") return;
|
|
29050
|
+
const handle = await open(directory, "r");
|
|
29051
|
+
try {
|
|
29052
|
+
await handle.sync();
|
|
29053
|
+
} finally {
|
|
29054
|
+
await handle.close();
|
|
29055
|
+
}
|
|
29056
|
+
}
|
|
28489
29057
|
//#endregion
|
|
28490
29058
|
//#region src/sidecar/rem-entry-foundations.ts
|
|
28491
29059
|
const sha256Schema = z.string().regex(/^[0-9a-f]{64}$/u);
|
|
@@ -29368,6 +29936,10 @@ async function runRemProductionOrderedWave(input) {
|
|
|
29368
29936
|
agentPort: input.agentPort,
|
|
29369
29937
|
...input.implementationVersion === void 0 ? {} : { implementationVersion: input.implementationVersion }
|
|
29370
29938
|
});
|
|
29939
|
+
if (result.hostRefusal) {
|
|
29940
|
+
if (!(result.actionsApplied > 0 || repository.listJournal(waveId).some((entry) => entry.actionsApplied > 0 || entry.outcome === "no-action" && entry.verdicts > 0))) throw result.hostRefusal;
|
|
29941
|
+
refusal = result.hostRefusal;
|
|
29942
|
+
}
|
|
29371
29943
|
results.push({
|
|
29372
29944
|
operation: jobType,
|
|
29373
29945
|
...result
|
|
@@ -29376,7 +29948,10 @@ async function runRemProductionOrderedWave(input) {
|
|
|
29376
29948
|
}
|
|
29377
29949
|
}]
|
|
29378
29950
|
}))[jobType] === "failed") stageFailed = true;
|
|
29379
|
-
if (refusal)
|
|
29951
|
+
if (refusal) {
|
|
29952
|
+
if (refusal.destination !== "host" || stageFailed) throw refusal;
|
|
29953
|
+
break;
|
|
29954
|
+
}
|
|
29380
29955
|
}
|
|
29381
29956
|
} finally {
|
|
29382
29957
|
journalDatabase.db.close();
|
|
@@ -29407,7 +29982,7 @@ async function runRemProductionOrderedWave(input) {
|
|
|
29407
29982
|
candidateCount: Math.max(0, ...results.map((result) => result.candidateCount)),
|
|
29408
29983
|
stampedSkippedCount: results.reduce((total, result) => total + result.stampedSkippedCount, 0),
|
|
29409
29984
|
parseFailureCount: results.reduce((total, result) => total + result.parseFailureCount, 0),
|
|
29410
|
-
topRefusalReasons: [
|
|
29985
|
+
topRefusalReasons: [.../* @__PURE__ */ new Set([...refusal ? [`host-refused:${refusal.callId}`] : [], ...results.flatMap((result) => result.topRefusalReasons)])].slice(0, 2),
|
|
29411
29986
|
measurements: {
|
|
29412
29987
|
rowsConsidered: Math.max(0, ...results.map((result) => result.measurements.rowsConsidered)),
|
|
29413
29988
|
pairsBuilt: results.reduce((total, result) => total + result.measurements.pairsBuilt, 0),
|
|
@@ -29512,7 +30087,7 @@ async function runRemBatchJobUnlocked(input) {
|
|
|
29512
30087
|
terminalState: "done",
|
|
29513
30088
|
appliedFraction,
|
|
29514
30089
|
parseFailureCount,
|
|
29515
|
-
topRefusalReasons
|
|
30090
|
+
topRefusalReasons: [...result.hostRefusal ? [`host-refused:${result.hostRefusal.callId}`] : [], ...topRefusalReasons].slice(0, 2)
|
|
29516
30091
|
};
|
|
29517
30092
|
return completed;
|
|
29518
30093
|
} finally {
|
|
@@ -29752,230 +30327,264 @@ function createRemUpdateBudget(configuration) {
|
|
|
29752
30327
|
};
|
|
29753
30328
|
}
|
|
29754
30329
|
function recordRemUpdateModelCall(budget, prompt) {
|
|
30330
|
+
if (budget.modelCalls >= (budget.configuration?.budgets.maxPairs ?? 0)) return false;
|
|
29755
30331
|
budget.modelCalls += 1;
|
|
29756
30332
|
budget.tokens += countTokens(prompt) + REM_MODEL_OUTPUT_TOKEN_CAP;
|
|
30333
|
+
return true;
|
|
29757
30334
|
}
|
|
29758
30335
|
async function runUpdate(input) {
|
|
29759
30336
|
const budget = createRemUpdateBudget(input.configuration);
|
|
29760
|
-
|
|
29761
|
-
|
|
29762
|
-
|
|
29763
|
-
|
|
29764
|
-
|
|
29765
|
-
const configurationSha256 = input.configuration === void 0 ? "0".repeat(64) : deriveRemConfigurationSha256(input.configuration);
|
|
29766
|
-
const recovery = createSnoStationMemRemRecovery(input.runtime.database);
|
|
29767
|
-
const mutationExecutor = createSnoStationMemRemMutationExecutor({
|
|
29768
|
-
database: input.runtime.database,
|
|
29769
|
-
jobType: input.jobType,
|
|
29770
|
-
configurationSha256,
|
|
29771
|
-
liveContentionRetries: input.configuration?.retries.liveContentionRetries ?? 0,
|
|
29772
|
-
recovery,
|
|
29773
|
-
applyTextVersion: (write, verification) => ports.conflict.writeTextVersion({
|
|
29774
|
-
...write,
|
|
29775
|
-
verification
|
|
29776
|
-
})
|
|
29777
|
-
});
|
|
29778
|
-
await mutationExecutor.recoverPendingAttempts();
|
|
29779
|
-
const relationEffects = await runProductionUpdateRelations({
|
|
29780
|
-
...input,
|
|
29781
|
-
budget,
|
|
29782
|
-
candidates,
|
|
29783
|
-
configurationSha256,
|
|
29784
|
-
mutationExecutor,
|
|
29785
|
-
recovery
|
|
29786
|
-
});
|
|
29787
|
-
let actionsApplied = relationEffects.actionsApplied;
|
|
29788
|
-
let verdicts = relationEffects.verdicts;
|
|
29789
|
-
let llmCalls = relationEffects.llmCalls;
|
|
29790
|
-
let successfulLlmCalls = relationEffects.successfulLlmCalls;
|
|
29791
|
-
let lastRefusalReason = relationEffects.lastRefusalReason;
|
|
29792
|
-
const stampedRowIds = new Set(input.stampedRows.map((row) => row.id));
|
|
29793
|
-
const owned = candidates.filter((candidate) => candidate.owner === "restate" && !stampedRowIds.has(candidate.id) && !relationEffects.handledRowIds.has(candidate.id));
|
|
29794
|
-
for (const stampedRow of input.stampedRows) {
|
|
29795
|
-
if (relationEffects.handledRowIds.has(stampedRow.id)) continue;
|
|
29796
|
-
appendRefusal(input.repository, input.jobId, input.jobType, stampedRow.id, "already_stamped");
|
|
29797
|
-
}
|
|
29798
|
-
for (const [index, candidate] of owned.entries()) {
|
|
29799
|
-
const claimed = claimCandidate(input.repository, candidate, "restate");
|
|
29800
|
-
if (!claimed) continue;
|
|
29801
|
-
log$1.info("update_progress", {
|
|
29802
|
-
job_id: input.jobId,
|
|
29803
|
-
current: index + 1,
|
|
29804
|
-
total: owned.length,
|
|
29805
|
-
row_id: candidate.id
|
|
29806
|
-
}, {
|
|
29807
|
-
event_name: "sno_station_mem.rem-batch-executor.update.progress",
|
|
29808
|
-
file: "packages/memory/src/sidecar/rem-batch-executor.ts",
|
|
29809
|
-
function: "runUpdate",
|
|
29810
|
-
site_id: "rem-batch-executor.runUpdate.dbf2a836db"
|
|
30337
|
+
try {
|
|
30338
|
+
const candidates = input.candidates;
|
|
30339
|
+
const ports = createSnoStationMemRemPorts({
|
|
30340
|
+
database: input.runtime.database,
|
|
30341
|
+
memoryStore: input.runtime.store
|
|
29811
30342
|
});
|
|
29812
|
-
|
|
29813
|
-
|
|
29814
|
-
|
|
29815
|
-
|
|
29816
|
-
|
|
29817
|
-
|
|
29818
|
-
|
|
29819
|
-
|
|
29820
|
-
|
|
29821
|
-
|
|
29822
|
-
|
|
29823
|
-
|
|
29824
|
-
|
|
29825
|
-
|
|
29826
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
|
|
29830
|
-
|
|
29831
|
-
|
|
29832
|
-
|
|
29833
|
-
|
|
29834
|
-
|
|
29835
|
-
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
|
|
29839
|
-
|
|
29840
|
-
|
|
29841
|
-
|
|
30343
|
+
const configurationSha256 = input.configuration === void 0 ? "0".repeat(64) : deriveRemConfigurationSha256(input.configuration);
|
|
30344
|
+
const recovery = createSnoStationMemRemRecovery(input.runtime.database);
|
|
30345
|
+
const mutationExecutor = createSnoStationMemRemMutationExecutor({
|
|
30346
|
+
database: input.runtime.database,
|
|
30347
|
+
jobType: input.jobType,
|
|
30348
|
+
configurationSha256,
|
|
30349
|
+
liveContentionRetries: input.configuration?.retries.liveContentionRetries ?? 0,
|
|
30350
|
+
recovery,
|
|
30351
|
+
applyTextVersion: (write, verification) => ports.conflict.writeTextVersion({
|
|
30352
|
+
...write,
|
|
30353
|
+
verification
|
|
30354
|
+
})
|
|
30355
|
+
});
|
|
30356
|
+
await mutationExecutor.recoverPendingAttempts();
|
|
30357
|
+
const relationEffects = await runProductionUpdateRelations({
|
|
30358
|
+
...input,
|
|
30359
|
+
budget,
|
|
30360
|
+
candidates,
|
|
30361
|
+
configurationSha256,
|
|
30362
|
+
mutationExecutor,
|
|
30363
|
+
recovery
|
|
30364
|
+
});
|
|
30365
|
+
let actionsApplied = relationEffects.actionsApplied;
|
|
30366
|
+
let verdicts = relationEffects.verdicts;
|
|
30367
|
+
let llmCalls = relationEffects.llmCalls;
|
|
30368
|
+
let successfulLlmCalls = relationEffects.successfulLlmCalls;
|
|
30369
|
+
let lastRefusalReason = relationEffects.lastRefusalReason;
|
|
30370
|
+
const stampedRowIds = new Set(input.stampedRows.map((row) => row.id));
|
|
30371
|
+
const owned = candidates.filter((candidate) => candidate.owner === "restate" && !stampedRowIds.has(candidate.id) && !relationEffects.handledRowIds.has(candidate.id));
|
|
30372
|
+
for (const stampedRow of input.stampedRows) {
|
|
30373
|
+
if (relationEffects.handledRowIds.has(stampedRow.id)) continue;
|
|
30374
|
+
appendRefusal(input.repository, input.jobId, input.jobType, stampedRow.id, "already_stamped");
|
|
30375
|
+
}
|
|
30376
|
+
for (const [index, candidate] of owned.entries()) {
|
|
30377
|
+
const claimed = claimCandidate(input.repository, candidate, "restate");
|
|
30378
|
+
if (!claimed) continue;
|
|
30379
|
+
log$1.info("update_progress", {
|
|
29842
30380
|
job_id: input.jobId,
|
|
29843
|
-
|
|
29844
|
-
|
|
29845
|
-
|
|
30381
|
+
current: index + 1,
|
|
30382
|
+
total: owned.length,
|
|
30383
|
+
row_id: candidate.id
|
|
29846
30384
|
}, {
|
|
29847
|
-
event_name: "sno_station_mem.rem-batch-executor.update.
|
|
30385
|
+
event_name: "sno_station_mem.rem-batch-executor.update.progress",
|
|
29848
30386
|
file: "packages/memory/src/sidecar/rem-batch-executor.ts",
|
|
29849
30387
|
function: "runUpdate",
|
|
29850
|
-
site_id: "rem-batch-executor.runUpdate.
|
|
30388
|
+
site_id: "rem-batch-executor.runUpdate.dbf2a836db"
|
|
29851
30389
|
});
|
|
29852
|
-
|
|
29853
|
-
if (
|
|
29854
|
-
|
|
29855
|
-
|
|
30390
|
+
try {
|
|
30391
|
+
if (candidate.state === "ambiguous") {
|
|
30392
|
+
lastRefusalReason = "ambiguous_unresolved";
|
|
30393
|
+
appendRefusal(input.repository, input.jobId, input.jobType, candidate.id, "ambiguous_unresolved");
|
|
30394
|
+
completeCandidate(input.repository, claimed, candidate.content_hash, input.jobId, input.jobType);
|
|
30395
|
+
continue;
|
|
29856
30396
|
}
|
|
29857
|
-
|
|
29858
|
-
|
|
29859
|
-
|
|
29860
|
-
|
|
29861
|
-
|
|
29862
|
-
successfulLlmCalls += 1;
|
|
29863
|
-
const verificationPrompt = renderRemUpdateVerificationPrompt({
|
|
29864
|
-
judgmentSkill: REM_UPDATE_JUDGMENT_SKILL.verification,
|
|
29865
|
-
source: candidate.text,
|
|
29866
|
-
proposedCurrent: decision.proposedCurrent,
|
|
29867
|
-
retiredValues: decision.retiredValues
|
|
29868
|
-
});
|
|
29869
|
-
recordRemUpdateModelCall(budget, verificationPrompt);
|
|
29870
|
-
llmCalls += 1;
|
|
29871
|
-
const verificationReply = await completeJsonStage(input.runtime, "rem-update-verification", verificationPrompt);
|
|
29872
|
-
const verification = decideRemUpdateVerification(typeof verificationReply === "string" ? verificationReply : JSON.stringify(verificationReply) ?? "");
|
|
29873
|
-
log$1.info("update_verification_evaluated", {
|
|
29874
|
-
job_id: input.jobId,
|
|
29875
|
-
row_id: candidate.id,
|
|
29876
|
-
outcome: verification.outcome,
|
|
29877
|
-
...verification.outcome === "refuse" ? { reason: verification.reason } : {}
|
|
29878
|
-
}, {
|
|
29879
|
-
event_name: "sno_station_mem.rem-batch-executor.update.verification.evaluated",
|
|
29880
|
-
file: "packages/memory/src/sidecar/rem-batch-executor.ts",
|
|
29881
|
-
function: "runUpdate",
|
|
29882
|
-
site_id: "rem-batch-executor.runUpdate.7ffc737c24"
|
|
29883
|
-
});
|
|
29884
|
-
if (verification.outcome === "refuse") {
|
|
29885
|
-
if (verification.reason !== "model_response_invalid") {
|
|
29886
|
-
successfulLlmCalls += 1;
|
|
29887
|
-
verdicts += 1;
|
|
30397
|
+
if (candidate.state !== "transition") {
|
|
30398
|
+
lastRefusalReason = "row_not_owned";
|
|
30399
|
+
releaseCandidate(input.repository, claimed);
|
|
30400
|
+
appendRefusal(input.repository, input.jobId, input.jobType, candidate.id, "row_not_owned");
|
|
30401
|
+
continue;
|
|
29888
30402
|
}
|
|
29889
|
-
|
|
29890
|
-
|
|
29891
|
-
|
|
29892
|
-
|
|
29893
|
-
|
|
29894
|
-
|
|
29895
|
-
|
|
29896
|
-
|
|
29897
|
-
|
|
29898
|
-
|
|
29899
|
-
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
|
|
29904
|
-
|
|
29905
|
-
|
|
29906
|
-
|
|
29907
|
-
|
|
30403
|
+
if (candidate.category !== "profile" && candidate.category !== "episodic" && candidate.category !== "state") {
|
|
30404
|
+
lastRefusalReason = "missing_row_kind";
|
|
30405
|
+
releaseCandidate(input.repository, claimed);
|
|
30406
|
+
appendRefusal(input.repository, input.jobId, input.jobType, candidate.id, "missing_row_kind");
|
|
30407
|
+
continue;
|
|
30408
|
+
}
|
|
30409
|
+
const enumeratedMembers = enumerateRemUpdateMembers(candidate.text);
|
|
30410
|
+
const prompt = renderRemUpdateJudgmentPrompt({
|
|
30411
|
+
judgmentSkill: REM_UPDATE_JUDGMENT_SKILL.rewrite,
|
|
30412
|
+
source: candidate.text,
|
|
30413
|
+
...enumeratedMembers.length === 0 ? {} : { enumeratedMembers }
|
|
30414
|
+
});
|
|
30415
|
+
if (!recordRemUpdateModelCall(budget, prompt)) {
|
|
30416
|
+
releaseCandidate(input.repository, claimed);
|
|
30417
|
+
break;
|
|
30418
|
+
}
|
|
30419
|
+
llmCalls += 1;
|
|
30420
|
+
const reply = await completeJsonStage(input.runtime, "rem-update-judgment", prompt);
|
|
30421
|
+
const decision = decideRemUpdateFromReply(typeof reply === "string" ? reply : JSON.stringify(reply) ?? "");
|
|
30422
|
+
log$1.info("update_decision_evaluated", {
|
|
30423
|
+
job_id: input.jobId,
|
|
30424
|
+
row_id: candidate.id,
|
|
30425
|
+
outcome: decision.outcome,
|
|
30426
|
+
...decision.outcome === "refuse" ? { reason: decision.reason } : { retired_value_count: decision.retiredValues.length }
|
|
30427
|
+
}, {
|
|
30428
|
+
event_name: "sno_station_mem.rem-batch-executor.update.decision.evaluated",
|
|
30429
|
+
file: "packages/memory/src/sidecar/rem-batch-executor.ts",
|
|
30430
|
+
function: "runUpdate",
|
|
30431
|
+
site_id: "rem-batch-executor.runUpdate.7dfc387204"
|
|
30432
|
+
});
|
|
30433
|
+
if (decision.outcome === "refuse") {
|
|
30434
|
+
if (decision.reason !== "model_response_invalid") {
|
|
30435
|
+
successfulLlmCalls += 1;
|
|
30436
|
+
if (decision.reason !== "no_retired_fact") verdicts += 1;
|
|
30437
|
+
}
|
|
30438
|
+
lastRefusalReason = decision.reason;
|
|
30439
|
+
releaseCandidate(input.repository, claimed);
|
|
30440
|
+
appendRefusal(input.repository, input.jobId, input.jobType, candidate.id, decision.reason);
|
|
30441
|
+
continue;
|
|
30442
|
+
}
|
|
30443
|
+
successfulLlmCalls += 1;
|
|
30444
|
+
const verificationPrompt = renderRemUpdateVerificationPrompt({
|
|
30445
|
+
judgmentSkill: REM_UPDATE_JUDGMENT_SKILL.verification,
|
|
30446
|
+
source: candidate.text,
|
|
30447
|
+
proposedCurrent: decision.proposedCurrent,
|
|
30448
|
+
retiredValues: decision.retiredValues
|
|
30449
|
+
});
|
|
30450
|
+
if (!recordRemUpdateModelCall(budget, verificationPrompt)) {
|
|
30451
|
+
releaseCandidate(input.repository, claimed);
|
|
30452
|
+
break;
|
|
30453
|
+
}
|
|
30454
|
+
llmCalls += 1;
|
|
30455
|
+
const verificationReply = await completeJsonStage(input.runtime, "rem-update-verification", verificationPrompt);
|
|
30456
|
+
const verification = decideRemUpdateVerification(typeof verificationReply === "string" ? verificationReply : JSON.stringify(verificationReply) ?? "");
|
|
30457
|
+
log$1.info("update_verification_evaluated", {
|
|
30458
|
+
job_id: input.jobId,
|
|
30459
|
+
row_id: candidate.id,
|
|
30460
|
+
outcome: verification.outcome,
|
|
30461
|
+
...verification.outcome === "refuse" ? { reason: verification.reason } : {}
|
|
30462
|
+
}, {
|
|
30463
|
+
event_name: "sno_station_mem.rem-batch-executor.update.verification.evaluated",
|
|
30464
|
+
file: "packages/memory/src/sidecar/rem-batch-executor.ts",
|
|
30465
|
+
function: "runUpdate",
|
|
30466
|
+
site_id: "rem-batch-executor.runUpdate.7ffc737c24"
|
|
30467
|
+
});
|
|
30468
|
+
if (verification.outcome === "refuse") {
|
|
30469
|
+
if (verification.reason !== "model_response_invalid") {
|
|
30470
|
+
successfulLlmCalls += 1;
|
|
30471
|
+
verdicts += 1;
|
|
30472
|
+
}
|
|
30473
|
+
lastRefusalReason = verification.reason;
|
|
30474
|
+
releaseCandidate(input.repository, claimed);
|
|
30475
|
+
appendRefusal(input.repository, input.jobId, input.jobType, candidate.id, verification.reason);
|
|
30476
|
+
continue;
|
|
30477
|
+
}
|
|
30478
|
+
successfulLlmCalls += 1;
|
|
30479
|
+
verdicts += 1;
|
|
30480
|
+
const rewriteConfig = {
|
|
30481
|
+
implementationVersion: input.implementationVersion ?? "rem-update-v1",
|
|
30482
|
+
memoryKind: candidate.category,
|
|
30483
|
+
locale: candidate.locale,
|
|
30484
|
+
localeResource: getRemUpdateLocaleResource(candidate.locale)
|
|
30485
|
+
};
|
|
30486
|
+
const updateStamp = deriveRemUpdateStamp({
|
|
30487
|
+
source: candidate.text,
|
|
30488
|
+
...rewriteConfig
|
|
30489
|
+
});
|
|
30490
|
+
const evidenceId = `rem-update:${input.jobId}:${candidate.id}:rewrite`;
|
|
30491
|
+
input.runtime.database.prepare(`INSERT OR REPLACE INTO nodix_rem_write_verdicts(
|
|
29908
30492
|
evidence_id, winner_row_id, loser_row_id, target_row_id,
|
|
29909
30493
|
retired_fact_atoms_json, recorded_at
|
|
29910
30494
|
) VALUES (?, ?, ?, ?, ?, ?)`).run(evidenceId, candidate.id, candidate.id, candidate.id, JSON.stringify([candidate.text]), ports.clock.now());
|
|
29911
|
-
|
|
29912
|
-
|
|
29913
|
-
|
|
29914
|
-
rowId: candidate.id,
|
|
29915
|
-
writer: "writeTextVersion",
|
|
29916
|
-
authorization: {
|
|
30495
|
+
const handle = await mutationExecutor.openAttempt({
|
|
30496
|
+
jobId: input.jobId,
|
|
30497
|
+
stage: "rem-update",
|
|
29917
30498
|
rowId: candidate.id,
|
|
29918
|
-
|
|
29919
|
-
|
|
29920
|
-
|
|
29921
|
-
|
|
30499
|
+
writer: "writeTextVersion",
|
|
30500
|
+
authorization: {
|
|
30501
|
+
rowId: candidate.id,
|
|
30502
|
+
preWriteContentSha256: candidate.content_hash,
|
|
30503
|
+
proposedTextSha256: sha256(decision.proposedCurrent),
|
|
30504
|
+
evidenceId,
|
|
30505
|
+
configurationSha256
|
|
30506
|
+
}
|
|
30507
|
+
});
|
|
30508
|
+
const resolution = await mutationExecutor.mutateAttempt(handle, {
|
|
30509
|
+
kind: "writeTextVersion",
|
|
30510
|
+
replacementText: decision.proposedCurrent,
|
|
30511
|
+
historyText: candidate.text,
|
|
30512
|
+
supersededItems: decision.retiredValues,
|
|
30513
|
+
sourceVersion: candidate.text,
|
|
30514
|
+
rewriteConfig,
|
|
30515
|
+
idempotencyKey: updateStamp,
|
|
30516
|
+
reason: "REM update accepted the model judgment and mechanical source checks.",
|
|
30517
|
+
timestamp: ports.clock.now()
|
|
30518
|
+
});
|
|
30519
|
+
const outcome = await mutationExecutor.closeAttempt(handle, resolution);
|
|
30520
|
+
if (outcome.outcome !== "succeeded") {
|
|
30521
|
+
releaseCandidate(input.repository, claimed);
|
|
30522
|
+
appendRefusal(input.repository, input.jobId, input.jobType, candidate.id, outcome.reasonCode ?? "mutation_failed");
|
|
30523
|
+
continue;
|
|
29922
30524
|
}
|
|
29923
|
-
|
|
29924
|
-
|
|
29925
|
-
|
|
29926
|
-
|
|
29927
|
-
historyText: candidate.text,
|
|
29928
|
-
supersededItems: decision.retiredValues,
|
|
29929
|
-
sourceVersion: candidate.text,
|
|
29930
|
-
rewriteConfig,
|
|
29931
|
-
idempotencyKey: updateStamp,
|
|
29932
|
-
reason: "REM update accepted the model judgment and mechanical source checks.",
|
|
29933
|
-
timestamp: ports.clock.now()
|
|
29934
|
-
});
|
|
29935
|
-
const outcome = await mutationExecutor.closeAttempt(handle, resolution);
|
|
29936
|
-
if (outcome.outcome !== "succeeded") {
|
|
30525
|
+
if (outcome.postWriteContentSha256 === null) throw new Error("successful REM write attempt omitted its post-write content hash");
|
|
30526
|
+
actionsApplied += 1;
|
|
30527
|
+
completeCandidate(input.repository, claimed, outcome.postWriteContentSha256, input.jobId, input.jobType);
|
|
30528
|
+
} catch (error) {
|
|
29937
30529
|
releaseCandidate(input.repository, claimed);
|
|
29938
|
-
|
|
29939
|
-
continue;
|
|
30530
|
+
throw error;
|
|
29940
30531
|
}
|
|
29941
|
-
if (outcome.postWriteContentSha256 === null) throw new Error("successful REM write attempt omitted its post-write content hash");
|
|
29942
|
-
actionsApplied += 1;
|
|
29943
|
-
completeCandidate(input.repository, claimed, outcome.postWriteContentSha256, input.jobId, input.jobType);
|
|
29944
|
-
} catch (error) {
|
|
29945
|
-
releaseCandidate(input.repository, claimed);
|
|
29946
|
-
throw error;
|
|
29947
30532
|
}
|
|
30533
|
+
if (llmCalls > 0 && successfulLlmCalls === 0) throw new Error(`REM LLM calls all failed: ${lastRefusalReason ?? input.runtime.llm.getLastError() ?? "unknown"}`);
|
|
30534
|
+
const updateRows = appliedUnitStatistics(owned.length, actionsApplied - relationEffects.actionsApplied);
|
|
30535
|
+
const relationPairs = appliedUnitStatistics(relationEffects.pairsScanned, relationEffects.actionsApplied);
|
|
30536
|
+
input.repository.appendJournal(input.jobId, input.jobType, {
|
|
30537
|
+
stage: "update-rows",
|
|
30538
|
+
outcome: updateRows.applied > 0 ? "done" : "no-action",
|
|
30539
|
+
pairsScanned: updateRows.considered,
|
|
30540
|
+
verdicts: 0,
|
|
30541
|
+
actionsApplied: updateRows.applied
|
|
30542
|
+
});
|
|
30543
|
+
input.repository.appendJournal(input.jobId, input.jobType, {
|
|
30544
|
+
stage: "update-relation-pairs",
|
|
30545
|
+
outcome: relationPairs.applied > 0 ? "done" : "no-action",
|
|
30546
|
+
pairsScanned: relationPairs.considered,
|
|
30547
|
+
verdicts: 0,
|
|
30548
|
+
actionsApplied: relationPairs.applied
|
|
30549
|
+
});
|
|
30550
|
+
return {
|
|
30551
|
+
...journal(input.jobType, relationEffects.pairsScanned, verdicts, actionsApplied),
|
|
30552
|
+
updateRows,
|
|
30553
|
+
relationPairs,
|
|
30554
|
+
measurements: {
|
|
30555
|
+
rowsConsidered: candidates.length,
|
|
30556
|
+
pairsBuilt: 0,
|
|
30557
|
+
pairCapBinding: budget.modelCalls >= (input.configuration?.budgets.maxPairs ?? 0),
|
|
30558
|
+
modelCalls: budget.modelCalls,
|
|
30559
|
+
modelTokens: budget.tokens,
|
|
30560
|
+
wallMs: Date.now() - budget.startedAtMs
|
|
30561
|
+
}
|
|
30562
|
+
};
|
|
30563
|
+
} catch (error) {
|
|
30564
|
+
if (!(error instanceof ModelCallRefusedError) || error.destination !== "host") throw error;
|
|
30565
|
+
const entries = input.repository.listJournal(input.jobId, input.jobType);
|
|
30566
|
+
const applied = input.runtime.database.prepare(`SELECT count(*) AS count FROM (
|
|
30567
|
+
SELECT row_id FROM nodix_rem_write_attempts
|
|
30568
|
+
WHERE job_id = ? AND stage LIKE 'rem-update%' AND outcome = 'succeeded'
|
|
30569
|
+
AND writer IN ('softClose', 'writeTextVersion')
|
|
30570
|
+
UNION
|
|
30571
|
+
SELECT json_extract(detail, '$.targetRowId') FROM nodix_rem_journal
|
|
30572
|
+
WHERE job_id = ? AND job_type = 'rem-update' AND outcome = 'done'
|
|
30573
|
+
AND stage LIKE 'update-retirement-target:%'
|
|
30574
|
+
)`).get(input.jobId, input.jobId);
|
|
30575
|
+
return {
|
|
30576
|
+
...journal(input.jobType, entries.reduce((total, entry) => total + entry.pairsScanned, 0), entries.reduce((total, entry) => total + entry.verdicts, 0), applied.count),
|
|
30577
|
+
hostRefusal: error,
|
|
30578
|
+
measurements: {
|
|
30579
|
+
rowsConsidered: input.candidates.length,
|
|
30580
|
+
pairsBuilt: 0,
|
|
30581
|
+
pairCapBinding: true,
|
|
30582
|
+
modelCalls: budget.modelCalls,
|
|
30583
|
+
modelTokens: budget.tokens,
|
|
30584
|
+
wallMs: Date.now() - budget.startedAtMs
|
|
30585
|
+
}
|
|
30586
|
+
};
|
|
29948
30587
|
}
|
|
29949
|
-
if (llmCalls > 0 && successfulLlmCalls === 0) throw new Error(`REM LLM calls all failed: ${lastRefusalReason ?? input.runtime.llm.getLastError() ?? "unknown"}`);
|
|
29950
|
-
const updateRows = appliedUnitStatistics(owned.length, actionsApplied - relationEffects.actionsApplied);
|
|
29951
|
-
const relationPairs = appliedUnitStatistics(relationEffects.pairsScanned, relationEffects.actionsApplied);
|
|
29952
|
-
input.repository.appendJournal(input.jobId, input.jobType, {
|
|
29953
|
-
stage: "update-rows",
|
|
29954
|
-
outcome: updateRows.applied > 0 ? "done" : "no-action",
|
|
29955
|
-
pairsScanned: updateRows.considered,
|
|
29956
|
-
verdicts: 0,
|
|
29957
|
-
actionsApplied: updateRows.applied
|
|
29958
|
-
});
|
|
29959
|
-
input.repository.appendJournal(input.jobId, input.jobType, {
|
|
29960
|
-
stage: "update-relation-pairs",
|
|
29961
|
-
outcome: relationPairs.applied > 0 ? "done" : "no-action",
|
|
29962
|
-
pairsScanned: relationPairs.considered,
|
|
29963
|
-
verdicts: 0,
|
|
29964
|
-
actionsApplied: relationPairs.applied
|
|
29965
|
-
});
|
|
29966
|
-
return {
|
|
29967
|
-
...journal(input.jobType, relationEffects.pairsScanned, verdicts, actionsApplied),
|
|
29968
|
-
updateRows,
|
|
29969
|
-
relationPairs,
|
|
29970
|
-
measurements: {
|
|
29971
|
-
rowsConsidered: candidates.length,
|
|
29972
|
-
pairsBuilt: 0,
|
|
29973
|
-
pairCapBinding: false,
|
|
29974
|
-
modelCalls: budget.modelCalls,
|
|
29975
|
-
modelTokens: budget.tokens,
|
|
29976
|
-
wallMs: Date.now() - budget.startedAtMs
|
|
29977
|
-
}
|
|
29978
|
-
};
|
|
29979
30588
|
}
|
|
29980
30589
|
function appliedUnitStatistics(considered, applied) {
|
|
29981
30590
|
return {
|
|
@@ -30004,6 +30613,7 @@ async function runProductionUpdateRelations(input) {
|
|
|
30004
30613
|
let successfulLlmCalls = 0;
|
|
30005
30614
|
let verdicts = 0;
|
|
30006
30615
|
for (let workIndex = 0; workIndex < relationWork.length; workIndex += 1) {
|
|
30616
|
+
if (input.budget.modelCalls >= input.configuration.budgets.maxPairs) break;
|
|
30007
30617
|
const work = relationWork[workIndex];
|
|
30008
30618
|
if (work === void 0) continue;
|
|
30009
30619
|
const { candidates } = work;
|
|
@@ -30011,6 +30621,7 @@ async function runProductionUpdateRelations(input) {
|
|
|
30011
30621
|
let retirementApplied = retirementPair !== void 0;
|
|
30012
30622
|
const nominatedRows = candidates.filter((candidate) => candidate.owner === "restate" || candidate.state === "pure-negation").sort((left, right) => compareMemorySourceOrder(rowOrderKey(right), rowOrderKey(left)) || right.id.localeCompare(left.id));
|
|
30013
30623
|
for (const nominatedRow of retirementPair === void 0 ? nominatedRows : []) {
|
|
30624
|
+
if (input.budget.modelCalls >= input.configuration.budgets.maxPairs) break;
|
|
30014
30625
|
if (handledRowIds.has(nominatedRow.id)) continue;
|
|
30015
30626
|
const candidateSet = await buildRemRetirementCandidateSet({
|
|
30016
30627
|
runtime: input.runtime,
|
|
@@ -30072,7 +30683,7 @@ async function runProductionUpdateRelations(input) {
|
|
|
30072
30683
|
predecessorTexts: [prior.text],
|
|
30073
30684
|
successorTexts: linked.map((candidate) => candidate.text)
|
|
30074
30685
|
});
|
|
30075
|
-
recordRemUpdateModelCall(input.budget, prompt);
|
|
30686
|
+
if (!recordRemUpdateModelCall(input.budget, prompt)) break;
|
|
30076
30687
|
llmCalls += 1;
|
|
30077
30688
|
const reply = await completeTextStage(input.runtime, "rem-update-relation-judgment", prompt);
|
|
30078
30689
|
let relation = decideRemUpdateRelationFromReply(reply ?? "");
|
|
@@ -30112,7 +30723,7 @@ async function runProductionUpdateRelations(input) {
|
|
|
30112
30723
|
source: prior.text,
|
|
30113
30724
|
supersedingText: relationCandidate.text
|
|
30114
30725
|
});
|
|
30115
|
-
recordRemUpdateModelCall(input.budget, rewritePrompt);
|
|
30726
|
+
if (!recordRemUpdateModelCall(input.budget, rewritePrompt)) break;
|
|
30116
30727
|
llmCalls += 1;
|
|
30117
30728
|
const rewriteReply = await completeJsonStage(input.runtime, "rem-update-judgment", rewritePrompt);
|
|
30118
30729
|
const rewrite = decideRemUpdateFromReply(typeof rewriteReply === "string" ? rewriteReply : JSON.stringify(rewriteReply) ?? "");
|
|
@@ -30133,7 +30744,7 @@ async function runProductionUpdateRelations(input) {
|
|
|
30133
30744
|
proposedCurrent: rewrite.proposedCurrent,
|
|
30134
30745
|
retiredValues: rewrite.retiredValues
|
|
30135
30746
|
});
|
|
30136
|
-
recordRemUpdateModelCall(input.budget, verificationPrompt);
|
|
30747
|
+
if (!recordRemUpdateModelCall(input.budget, verificationPrompt)) break;
|
|
30137
30748
|
llmCalls += 1;
|
|
30138
30749
|
const verificationReply = await completeJsonStage(input.runtime, "rem-update-verification", verificationPrompt);
|
|
30139
30750
|
const verification = decideRemUpdateVerification(typeof verificationReply === "string" ? verificationReply : JSON.stringify(verificationReply) ?? "");
|
|
@@ -30165,7 +30776,7 @@ async function runProductionUpdateRelations(input) {
|
|
|
30165
30776
|
retiredValues: [prior.text],
|
|
30166
30777
|
retractionText: retraction.text
|
|
30167
30778
|
});
|
|
30168
|
-
recordRemUpdateModelCall(input.budget, verificationPrompt);
|
|
30779
|
+
if (!recordRemUpdateModelCall(input.budget, verificationPrompt)) break;
|
|
30169
30780
|
llmCalls += 1;
|
|
30170
30781
|
const verificationReply = await completeJsonStage(input.runtime, "rem-update-verification", verificationPrompt);
|
|
30171
30782
|
const verification = decideRemUpdateVerification(typeof verificationReply === "string" ? verificationReply : JSON.stringify(verificationReply) ?? "");
|
|
@@ -30383,7 +30994,7 @@ async function runRemRetirementTargetGate(input) {
|
|
|
30383
30994
|
text: candidate.text
|
|
30384
30995
|
}))
|
|
30385
30996
|
});
|
|
30386
|
-
recordRemUpdateModelCall(input.budget, prompt);
|
|
30997
|
+
if (!recordRemUpdateModelCall(input.budget, prompt)) break;
|
|
30387
30998
|
llmCalls += 1;
|
|
30388
30999
|
let reply = null;
|
|
30389
31000
|
try {
|
|
@@ -31158,7 +31769,19 @@ async function runReplace(input) {
|
|
|
31158
31769
|
claimToken: candidate.claimToken
|
|
31159
31770
|
}));
|
|
31160
31771
|
}
|
|
31161
|
-
throw error;
|
|
31772
|
+
if (!(error instanceof ModelCallRefusedError) || error.destination !== "host") throw error;
|
|
31773
|
+
return {
|
|
31774
|
+
...journal(input.jobType, pairsScanned, verdicts, actionsApplied),
|
|
31775
|
+
hostRefusal: error,
|
|
31776
|
+
measurements: {
|
|
31777
|
+
rowsConsidered: input.candidates.length,
|
|
31778
|
+
pairsBuilt: indexedPairs.length,
|
|
31779
|
+
pairCapBinding: true,
|
|
31780
|
+
modelCalls: llmCalls,
|
|
31781
|
+
modelTokens,
|
|
31782
|
+
wallMs: Date.now() - startedAtMs
|
|
31783
|
+
}
|
|
31784
|
+
};
|
|
31162
31785
|
}
|
|
31163
31786
|
for (const candidate of participatingClaimed) {
|
|
31164
31787
|
const modified = completedContentHashes.has(candidate.id) || closedRowIds.has(candidate.id);
|
|
@@ -31316,7 +31939,7 @@ async function buildRemReplaceCandidateQueue(input) {
|
|
|
31316
31939
|
vectors = lookup.readVectors(projectCurrent.map((row) => row.id));
|
|
31317
31940
|
currentVectors.set(candidate.project_id, vectors);
|
|
31318
31941
|
}
|
|
31319
|
-
found = pairWithNearest(pairs, candidate, projectCurrent, vector, vectors,
|
|
31942
|
+
found = pairWithNearest(pairs, candidate, projectCurrent, vector, vectors, 3) || found;
|
|
31320
31943
|
}
|
|
31321
31944
|
matches = await lookup.searchSemantic(vector, {
|
|
31322
31945
|
category: candidate.category,
|
|
@@ -32028,6 +32651,28 @@ async function evaluateScope(input, auditStateDir, state, scope, candidateCount,
|
|
|
32028
32651
|
}
|
|
32029
32652
|
const correlationId = remAutomaticCorrelationId(trigger, scope, trigger === "daily" ? nextDue.toISOString() : localDate);
|
|
32030
32653
|
const priorAttempts = scopeState.attempts.identity === correlationId ? scopeState.attempts.count : 0;
|
|
32654
|
+
if (priorAttempts >= 3) {
|
|
32655
|
+
await recordDecision(auditStateDir, scope, "skipped", {
|
|
32656
|
+
row: "attempt-limit",
|
|
32657
|
+
trigger,
|
|
32658
|
+
local_date: localDate,
|
|
32659
|
+
correlation_id: correlationId,
|
|
32660
|
+
attempts: priorAttempts
|
|
32661
|
+
});
|
|
32662
|
+
const nextState = replaceScopeState(state, scope, {
|
|
32663
|
+
...scopeState,
|
|
32664
|
+
last_volume_pass_date: localDate,
|
|
32665
|
+
attempts: {
|
|
32666
|
+
identity: null,
|
|
32667
|
+
count: 0
|
|
32668
|
+
}
|
|
32669
|
+
});
|
|
32670
|
+
await writeRemTriggerStateAtomic(input.stateDir, nextState);
|
|
32671
|
+
return {
|
|
32672
|
+
state: nextState,
|
|
32673
|
+
dispatched: false
|
|
32674
|
+
};
|
|
32675
|
+
}
|
|
32031
32676
|
await recordDecision(auditStateDir, scope, "ok", {
|
|
32032
32677
|
row: "dispatch",
|
|
32033
32678
|
trigger,
|
|
@@ -32122,6 +32767,40 @@ async function dispatchRemWave(input, scope, correlationId) {
|
|
|
32122
32767
|
});
|
|
32123
32768
|
}
|
|
32124
32769
|
async function applyCompletedBaselines(auditStateDir, triggerStateDir, state) {
|
|
32770
|
+
const durableCorrelations = /* @__PURE__ */ new Set();
|
|
32771
|
+
try {
|
|
32772
|
+
const completedJobs = await RemJobStore.readCompletedJobs(path.join(triggerStateDir, "rem-wave-jobs.jsonl"));
|
|
32773
|
+
for (const job of completedJobs) {
|
|
32774
|
+
durableCorrelations.add(job.correlation_id);
|
|
32775
|
+
const current = state.scopes[job.scope];
|
|
32776
|
+
if (!current || !job.correlation_id.startsWith("rem-auto-") || !job.started_at) continue;
|
|
32777
|
+
const localDate = localDateAt(new Date(job.started_at), current.schedule_zone);
|
|
32778
|
+
const measured = job.stats.measured;
|
|
32779
|
+
const completedScope = {
|
|
32780
|
+
...current,
|
|
32781
|
+
last_pass_at: job.started_at > current.last_pass_at ? job.started_at : current.last_pass_at,
|
|
32782
|
+
last_volume_pass_date: localDate > (current.last_volume_pass_date ?? "") ? localDate : current.last_volume_pass_date,
|
|
32783
|
+
...current.attempts.identity === job.correlation_id ? { attempts: {
|
|
32784
|
+
identity: null,
|
|
32785
|
+
count: 0
|
|
32786
|
+
} } : {},
|
|
32787
|
+
...measured?.pair_cap_binding === false ? { last_covered_count: measured.rows_considered } : {}
|
|
32788
|
+
};
|
|
32789
|
+
if (JSON.stringify(current) === JSON.stringify(completedScope)) continue;
|
|
32790
|
+
state = replaceScopeState(state, job.scope, completedScope);
|
|
32791
|
+
await writeRemTriggerStateAtomic(triggerStateDir, state);
|
|
32792
|
+
}
|
|
32793
|
+
} catch (error) {
|
|
32794
|
+
log.warn("REM completion jobs could not be read", {
|
|
32795
|
+
error,
|
|
32796
|
+
outcome: "partial"
|
|
32797
|
+
}, {
|
|
32798
|
+
event_name: "sidecar.trigger.completion_jobs.read.failed",
|
|
32799
|
+
file: "packages/memory/src/sidecar/rem-trigger.ts",
|
|
32800
|
+
function: "applyCompletedBaselines",
|
|
32801
|
+
site_id: "sidecar.trigger.completion_jobs.read.failed"
|
|
32802
|
+
});
|
|
32803
|
+
}
|
|
32125
32804
|
let content;
|
|
32126
32805
|
try {
|
|
32127
32806
|
content = await readAuditTail(getAuditPath(auditStateDir));
|
|
@@ -32140,7 +32819,6 @@ async function applyCompletedBaselines(auditStateDir, triggerStateDir, state) {
|
|
|
32140
32819
|
return state;
|
|
32141
32820
|
}
|
|
32142
32821
|
const dispatched = /* @__PURE__ */ new Map();
|
|
32143
|
-
const triesByCorrelation = /* @__PURE__ */ new Map();
|
|
32144
32822
|
let nextState = state;
|
|
32145
32823
|
let malformedCount = 0;
|
|
32146
32824
|
for (const line of content.split("\n")) {
|
|
@@ -32162,28 +32840,6 @@ async function applyCompletedBaselines(auditStateDir, triggerStateDir, state) {
|
|
|
32162
32840
|
});
|
|
32163
32841
|
continue;
|
|
32164
32842
|
}
|
|
32165
|
-
if (entry["event"] === "rem_skipped" && typeof correlationId === "string") {
|
|
32166
|
-
const skipped = dispatched.get(correlationId);
|
|
32167
|
-
const tries = (triesByCorrelation.get(correlationId) ?? 0) + (typeof details?.["destination"] === "string" ? 1 : 0);
|
|
32168
|
-
triesByCorrelation.set(correlationId, tries);
|
|
32169
|
-
const skippedScopeState = skipped ? nextState.scopes[skipped.scope] : void 0;
|
|
32170
|
-
if (skipped && skippedScopeState && tries >= 3 && isLocalDate(skipped.localDate) && (skippedScopeState.last_volume_pass_date ?? "") < skipped.localDate) nextState = replaceScopeState(nextState, skipped.scope, {
|
|
32171
|
-
...skippedScopeState,
|
|
32172
|
-
last_volume_pass_date: skipped.localDate,
|
|
32173
|
-
attempts: {
|
|
32174
|
-
identity: null,
|
|
32175
|
-
count: 0
|
|
32176
|
-
}
|
|
32177
|
-
});
|
|
32178
|
-
else if (skipped && skippedScopeState?.attempts.identity === correlationId) nextState = replaceScopeState(nextState, skipped.scope, {
|
|
32179
|
-
...skippedScopeState,
|
|
32180
|
-
attempts: {
|
|
32181
|
-
identity: null,
|
|
32182
|
-
count: 0
|
|
32183
|
-
}
|
|
32184
|
-
});
|
|
32185
|
-
continue;
|
|
32186
|
-
}
|
|
32187
32843
|
if (entry["event"] === "rem_failed" && details?.["source"] === "sidecar" && typeof correlationId === "string") {
|
|
32188
32844
|
const failed = dispatched.get(correlationId);
|
|
32189
32845
|
const failedScopeState = failed ? nextState.scopes[failed.scope] : void 0;
|
|
@@ -32197,15 +32853,15 @@ async function applyCompletedBaselines(auditStateDir, triggerStateDir, state) {
|
|
|
32197
32853
|
});
|
|
32198
32854
|
continue;
|
|
32199
32855
|
}
|
|
32200
|
-
if (entry["event"] !== "rem_completed" || typeof correlationId !== "string") continue;
|
|
32856
|
+
if (entry["event"] !== "rem_completed" || typeof correlationId !== "string" || durableCorrelations.has(correlationId)) continue;
|
|
32201
32857
|
const dispatch = dispatched.get(correlationId);
|
|
32202
32858
|
if (dispatch === void 0 || state.scopes[dispatch.scope] === void 0 || entry["scope"] !== dispatch.scope) continue;
|
|
32203
32859
|
const currentScopeState = requiredScopeState(nextState, dispatch.scope);
|
|
32204
32860
|
let completedScopeState = {
|
|
32205
32861
|
...currentScopeState,
|
|
32206
|
-
...dispatch.trigger === "daily" && isValidInstant(dispatch.passAt) ? { last_pass_at: dispatch.passAt } : {},
|
|
32207
|
-
...dispatch.trigger === "daily" && isLocalDate(dispatch.localDate) ? { last_volume_pass_date: dispatch.localDate } : {},
|
|
32208
|
-
...dispatch.trigger === "volume" && isLocalDate(dispatch.localDate) ? { last_volume_pass_date: dispatch.localDate } : {},
|
|
32862
|
+
...dispatch.trigger === "daily" && isValidInstant(dispatch.passAt) && dispatch.passAt > currentScopeState.last_pass_at ? { last_pass_at: dispatch.passAt } : {},
|
|
32863
|
+
...dispatch.trigger === "daily" && isLocalDate(dispatch.localDate) && dispatch.localDate > (currentScopeState.last_volume_pass_date ?? "") ? { last_volume_pass_date: dispatch.localDate } : {},
|
|
32864
|
+
...dispatch.trigger === "volume" && isLocalDate(dispatch.localDate) && dispatch.localDate > (currentScopeState.last_volume_pass_date ?? "") ? { last_volume_pass_date: dispatch.localDate } : {},
|
|
32209
32865
|
...currentScopeState.attempts.identity === correlationId ? { attempts: {
|
|
32210
32866
|
identity: null,
|
|
32211
32867
|
count: 0
|
|
@@ -32213,7 +32869,7 @@ async function applyCompletedBaselines(auditStateDir, triggerStateDir, state) {
|
|
|
32213
32869
|
};
|
|
32214
32870
|
const measured = asRecord(asRecord(details?.["stats"])?.["measured"]);
|
|
32215
32871
|
const rowsConsidered = measured?.["rows_considered"];
|
|
32216
|
-
if (measured?.["pair_cap_binding"] === false && Number.isInteger(rowsConsidered) && Number(rowsConsidered) >= 0) completedScopeState = {
|
|
32872
|
+
if ((!isValidInstant(dispatch.passAt) || dispatch.passAt >= currentScopeState.last_pass_at) && measured?.["pair_cap_binding"] === false && Number.isInteger(rowsConsidered) && Number(rowsConsidered) >= 0) completedScopeState = {
|
|
32217
32873
|
...completedScopeState,
|
|
32218
32874
|
last_covered_count: Number(rowsConsidered)
|
|
32219
32875
|
};
|
|
@@ -32409,4 +33065,4 @@ function errorMessage(error) {
|
|
|
32409
33065
|
return error instanceof Error ? error.message : String(error);
|
|
32410
33066
|
}
|
|
32411
33067
|
//#endregion
|
|
32412
|
-
export {
|
|
33068
|
+
export { renderAdapterAChatPrompt as $, MEMORY_CATEGORIES as $t, journalAtomicArrivalRetirementRefusal as A, getAuditPath as At, StaleSupersedeTargetError as B, debugContentPreview as Bt, buildTaskLifecycleCommandClaim as C, withMemoryOperation as Cn, withProviderResponses as Ct, normalizeEntityName as D, appendAuditEntryStrict as Dt, listAtomicMemoryEntityCandidates as E, appendAuditEntry as Et, normalizeTopicToSectionName as F, CODING_SKIN_LEDGER_MAX_CHARS as Ft, loadSqliteVecExtension as G, redactSecrets as Gt, validateMemoryTelemetryMetadata as H, stripHtmlTags as Ht, getSnoStationMemDataDir as I, CODING_SKIN_SESSION_QUERY as It, adapterAViewFromRecord as J, stringifyInsightMetadata as Jt, REM_BUILT_OPERATION_TYPES as K, buildInsightMetadata as Kt, AtomicExtractionCompletedElsewhere as L, HOST_MODEL_DEADLINE_HEADER as Lt, recordTokenCounter as M, runWithMemoryAuditSync as Mt, canExtractorWrite as N, runWithMutationAttempt as Nt, recordAtomicEntityIdentityJournal as O, compactAuditLog as Ot, canonicalizeProfileSectionName as P, readJsonlLines as Pt, prospectiveProfileView as Q, AGGREGATION_OPERATIONS as Qt, normalizeMemoryRelationPredicate as R, clamp01 as Rt, admitTaskLifecycleAssertion as S, memoryOperationSignal as Sn, isTerminalLlmFailure as St, resolveHookAgentId as T, isTerminalLlmFailure$1 as Tt, randomUUID$1 as U, stripRoleLabelPrefix as Ut, TaskLifecycleStaleResolutionError as V, stableHash as Vt, readChunkVecTableState as W, truncateGraphemes as Wt, orderAdapterAPair as X, parseIsoDateTimeMs as Xt, isAdapterAVerdictReply as Y, normalizeIsoDateTimeString as Yt, parseAdapterAChatVerdict as Z, deriveFactKey as Zt, acceptsTaskLifecycleJudgment as _, initSqliteRuntime as _n, createScopePolicy as _t, enumerateRemCandidateScopes as a, atomicExtractionSkillReference as an, resolveMemoryDate as at, resolveTaskLifecycle as b, checkMemoryOperation as bn, ModelCallRefusedError as bt, runRemProductionOrderedWave as c, state_vocabulary_default as cn, buildIndexedText as ct, RemJobStore as d, calendarInstructionSchema as dn, ALL_RESOURCES as dt, normalizeCategory as en, renderAdapterAPrompt as et, parseRemJobStats as f, isCalendarLabel as fn, RESOURCES_BY_LOCALE as ft, Embedder as g, isMemoryTelemetryEventType as gn, MemoryScopePolicy as gt, AccessTracker as h, MEMORY_TELEMETRY_DELETE_REASONS as hn, StorageError as ht, createRemModelStageResponsePort as i, ATOMIC_EXTRACTION_SKILL_HASH as in, serializeIntervalMetadata as it, readAtomicArrivalRetirementCandidateSet as j, runWithMemoryAudit as jt, closeAtomicArrivalRetirementTargets as k, currentMutationAttemptId as kt, runWithCanonicalStoreWriteMutex as l, relations as ln, stripEnvelopeMetadata as lt, DEFAULT_RETRIEVAL_CONFIG as m, attribute_dictionary_default as mn, SnoStationMemError as mt, remNeedsHost as n, resolveLlmRoute as nn, readMemorySourceOrderOrOldest as nt, readCandidates as o, modelReplyJsonCandidates as on, unresolvedMemoryDate as ot, MemoryRetriever as p, sessionZoneCarriedBy as pn, RetrievalError as pt, parseRemOperationType as q, parseInsightMetadata as qt, buildRemReplaceCandidateQueue as r, ATOMIC_EXTRACTION_SKILL as rn, parseSessionTimestamp as rt, runRemBatchJob as s, readModelReplyJson as sn, boundSectionContent as st, evaluateRemAutomaticTriggers as t, pickLlmRoutingConfig as tn, compareMemorySourceOrder as tt, selectRemUpdateRelationCandidates as u, calculateCalendarTime as un, normalizeAmbientLearningText as ut, buildTaskLifecycleCandidateSet as v, openSqliteDatabase as vn, parseAgentIdFromSessionKey$1 as vt, resolveTaskLifecycleEffectiveTime as w, forwardObserveLedgerUntilIdle as wn, classifyLlmFailure as wt, taskLifecycleCandidateSetVersion as x, memoryFileWrite as xn, createLlmClient as xt, findUniqueActiveTaskByDescription as y, openSqliteDatabaseReadonly as yn, LlmClientTerminalError as yt, MemoryStore as z, clampInt as zt };
|