@snoai/memory 1.2.8 → 1.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +97 -47
- 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 +1 -1
- 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 +2 -2
- 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-Bb9w8j4f.js → log-site-catalog.generated-C9RmyAA0.js} +227 -192
- 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-DSP8cXik.js → memory-runtime-HibOMCFa.js} +482 -297
- 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--SrMdT3P.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-BZpdv93Y.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-DsXWpJYU.js → rem-batch-executor-8x4FBLtW.js} +1 -1
- package/dist/{rem-trigger-DZaplx_E.js → rem-trigger-DmRERTNH.js} +1672 -1003
- package/dist/{retriever-ZoLvPRHq.js → retriever-BXQmJMh0.js} +16 -3
- package/dist/{retriever-DQdyGlkr.d.ts → retriever-BpxV-0fB.d.ts} +8 -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-Dw34jY1d.js → server-CCduS_Ea.js} +17 -320
- package/dist/sidecar/main.js +11 -4
- package/dist/sno-station-mem-runtime-dependencies-AdFFr3bU.d.ts +31 -0
- package/dist/{sno-station-mem-runtime-dependencies-DAMOKR9y.js → sno-station-mem-runtime-dependencies-CexFtaY6.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,6 +1,6 @@
|
|
|
1
1
|
import { CHUNKING_VERSION, DEFAULT_BM25_WEIGHT, DEFAULT_RECALL_LIFECYCLE, DEFAULT_RERANK_MODEL, DEFAULT_RERANK_TIMEOUT_MS, DEFAULT_VECTOR_WEIGHT, IMPORTANCE_WEIGHT_BASE, LIGHTWEIGHT_COSINE_WEIGHT, LIGHTWEIGHT_FUSION_WEIGHT, LIGHTWEIGHT_RERANK_PENALTY, MMR_LAMBDA, RECENCY_WEIGHT, RERANK_BLEND_CROSS, RERANK_BLEND_VECTOR, TIME_DECAY_FLOOR, experimentCandidatePoolOverride, experimentMmrDisabled } from "./internal/config/index.js";
|
|
2
2
|
import "./internal/engine/shared/types.js";
|
|
3
|
-
import { RetrievalError } from "./internal/engine/shared/errors.js";
|
|
3
|
+
import { EmbeddingError, RetrievalError } from "./internal/engine/shared/errors.js";
|
|
4
4
|
import { o as isMemoryExpired, s as parseInsightMetadata } from "./memory-metadata-codec-DL1sbJiN.js";
|
|
5
5
|
import { clamp01 } from "./internal/engine/shared/utils.js";
|
|
6
6
|
import { i as memoryOperationSignal } from "./operation-cancellation-CTKWwNHk.js";
|
|
@@ -375,6 +375,19 @@ function collectParallelStage(results, key, fallbackIds) {
|
|
|
375
375
|
}
|
|
376
376
|
//#endregion
|
|
377
377
|
//#region src/engine/retrieval/retriever-search-modes.ts
|
|
378
|
+
/**
|
|
379
|
+
* Ordinary long prose is chunked and averaged by the embedder. Text it cannot cut under the model's limit (a pasted log or hash
|
|
380
|
+
* dump) is rejected, and would fail the whole recall, so only then is the query cut to the limit; keyword search still sees all of it.
|
|
381
|
+
*/
|
|
382
|
+
async function embedQuery(embedder, query) {
|
|
383
|
+
await embedder.warmup();
|
|
384
|
+
try {
|
|
385
|
+
return await embedder.embed(query);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
if (!(error instanceof EmbeddingError)) throw error;
|
|
388
|
+
return embedder.embed(embedder.truncateToTokens(query, 512));
|
|
389
|
+
}
|
|
390
|
+
}
|
|
378
391
|
Object.assign(MemoryRetriever.prototype, {
|
|
379
392
|
async aggregationComplete(context, trace) {
|
|
380
393
|
trace?.startStage("aggregation_evidence", []);
|
|
@@ -420,7 +433,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
420
433
|
return mapped;
|
|
421
434
|
},
|
|
422
435
|
async vectorOnly(context, trace) {
|
|
423
|
-
const vector = await this.embedder
|
|
436
|
+
const vector = await embedQuery(this.embedder, context.query);
|
|
424
437
|
this.throwIfAborted(context);
|
|
425
438
|
const searchLimit = this.config.temporalExpiry ? Math.max(this.config.candidatePoolSize, context.limit * 2) : context.limit;
|
|
426
439
|
trace?.startStage("vector_search", []);
|
|
@@ -463,7 +476,7 @@ Object.assign(MemoryRetriever.prototype, {
|
|
|
463
476
|
},
|
|
464
477
|
async precisionRecall(context, trace) {
|
|
465
478
|
trace?.startStage("embed_query", []);
|
|
466
|
-
const queryVector = await this.embedder
|
|
479
|
+
const queryVector = await embedQuery(this.embedder, context.query);
|
|
467
480
|
trace?.endStage([]);
|
|
468
481
|
this.throwIfAborted(context);
|
|
469
482
|
const bm25Query = context.query;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { h as MemoryCategory, l as DecayScore, r as AggregationQuery, u as DecayableMemory, x as RetrievalResult, y as MemorySearchResult } from "./types-
|
|
2
|
-
import { sn as RecallLifecycleConfig } from "./index-
|
|
1
|
+
import { h as MemoryCategory, l as DecayScore, r as AggregationQuery, u as DecayableMemory, x as RetrievalResult, y as MemorySearchResult } from "./types-Ae3a8562.js";
|
|
2
|
+
import { sn as RecallLifecycleConfig } from "./index-Pb9LrHgL.js";
|
|
3
3
|
import { t as Embedder } from "./embedding-provider-client-vynZMuit.js";
|
|
4
4
|
import "./trace-C1JxMfs-.js";
|
|
5
|
-
import "./memory-metadata-codec-
|
|
6
|
-
import { K as RemFacetPolicy } from "./index-
|
|
7
|
-
import { C as MemoryStore } from "./memory-store-base-
|
|
8
|
-
import "./store-
|
|
9
|
-
import { n as AccessTracker } from "./access-tracker-
|
|
10
|
-
import { r as TierPromoter } from "./memory-tier-promoter-
|
|
5
|
+
import "./memory-metadata-codec-wVAuoKrG.js";
|
|
6
|
+
import { K as RemFacetPolicy } from "./index-DPfJrOFD.js";
|
|
7
|
+
import { C as MemoryStore } from "./memory-store-base-Bk2dOKED.js";
|
|
8
|
+
import "./store-BDIAl2cc.js";
|
|
9
|
+
import { n as AccessTracker } from "./access-tracker-BOPHSJjf.js";
|
|
10
|
+
import { r as TierPromoter } from "./memory-tier-promoter-MkZPQ8u1.js";
|
|
11
11
|
import "@snoai/utils/logger";
|
|
12
12
|
//#region src/engine/retrieval/retrieval-trace.d.ts
|
|
13
13
|
/** @file retrieval-trace.ts
|
|
@@ -5,8 +5,9 @@ import path from "node:path";
|
|
|
5
5
|
import { appendFile } from "node:fs/promises";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
|
-
import { appendFileSync, createReadStream, existsSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { appendFileSync, closeSync, createReadStream, existsSync, fsyncSync, mkdirSync, openSync, readSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { createInterface } from "node:readline";
|
|
10
|
+
import { StringDecoder } from "node:string_decoder";
|
|
10
11
|
//#region src/engine/operations/jsonl-lines.ts
|
|
11
12
|
const log = createLogger("sno-station-mem:jsonl");
|
|
12
13
|
/** Preserve complete records without materializing an unbounded log as one string. */
|
|
@@ -131,6 +132,7 @@ function enqueueAuditWrite(auditPath, line) {
|
|
|
131
132
|
const next = (auditWriteQueues.get(auditPath) ?? Promise.resolve(true)).catch(() => void 0).then(async () => {
|
|
132
133
|
mkdirSync(path.dirname(auditPath), { recursive: true });
|
|
133
134
|
await appendFile(auditPath, line);
|
|
135
|
+
compactAuditLog(auditPath);
|
|
134
136
|
return true;
|
|
135
137
|
}).catch((error) => {
|
|
136
138
|
createLogger("sno-station-mem:audit").error("Audit entry append failed", { error }, {
|
|
@@ -151,6 +153,104 @@ function enqueueAuditWrite(auditPath, line) {
|
|
|
151
153
|
function getAuditPath(stateDir) {
|
|
152
154
|
return path.join(stateDir, "audit.jsonl");
|
|
153
155
|
}
|
|
156
|
+
/** Retain the recent tail and two days of REM replay evidence when the audit exceeds 16 MiB. */
|
|
157
|
+
function compactAuditLog(auditPath) {
|
|
158
|
+
try {
|
|
159
|
+
compactAuditFile(auditPath);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
createLogger("sno-station-mem:audit").error("Audit compaction failed; existing records retained", { error }, {
|
|
162
|
+
event_name: "memory.audit.compact.failed",
|
|
163
|
+
file: "packages/memory/src/engine/operations/runtime-audit-log.ts",
|
|
164
|
+
function: "compactAuditLog",
|
|
165
|
+
site_id: "memory.audit.compact.failed"
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function compactAuditFile(auditPath) {
|
|
170
|
+
if (!existsSync(auditPath) || statSync(auditPath).size <= 16777216) return;
|
|
171
|
+
const fd = openSync(auditPath, "r");
|
|
172
|
+
const retained = [];
|
|
173
|
+
const openAttempts = /* @__PURE__ */ new Map();
|
|
174
|
+
let tail;
|
|
175
|
+
let size = 0;
|
|
176
|
+
try {
|
|
177
|
+
size = statSync(auditPath).size;
|
|
178
|
+
const tailStart = Math.max(0, size - 8388608);
|
|
179
|
+
tail = Buffer.alloc(size - tailStart);
|
|
180
|
+
const tailRead = readSync(fd, tail, 0, tail.length, tailStart);
|
|
181
|
+
tail = tail.subarray(0, tailRead);
|
|
182
|
+
const newline = tail.indexOf(10);
|
|
183
|
+
const prefixEnd = newline < 0 ? size : tailStart + newline + 1;
|
|
184
|
+
tail = newline < 0 ? Buffer.alloc(0) : tail.subarray(newline + 1);
|
|
185
|
+
const cutoff = (/* @__PURE__ */ new Date(Date.now() - 1728e5)).toISOString();
|
|
186
|
+
const buffer = Buffer.alloc(65536);
|
|
187
|
+
let position = 0;
|
|
188
|
+
let pending = "";
|
|
189
|
+
let linePosition = 0;
|
|
190
|
+
const decoder = new StringDecoder("utf8");
|
|
191
|
+
let oversized = false;
|
|
192
|
+
while (position < prefixEnd) {
|
|
193
|
+
const count = readSync(fd, buffer, 0, Math.min(buffer.length, prefixEnd - position), position);
|
|
194
|
+
if (count === 0) break;
|
|
195
|
+
position += count;
|
|
196
|
+
const parts = (pending + decoder.write(buffer.subarray(0, count))).split("\n");
|
|
197
|
+
pending = parts.pop() ?? "";
|
|
198
|
+
for (const line of parts) {
|
|
199
|
+
if (oversized) {
|
|
200
|
+
oversized = false;
|
|
201
|
+
linePosition++;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
const entry = JSON.parse(line);
|
|
206
|
+
if (isRecord(entry) && typeof entry["event"] === "string" && entry["event"].startsWith("rem_") && typeof entry["timestamp"] === "string" && entry["timestamp"] >= cutoff && (entry["event"] !== "rem_trigger_evaluated" || isRecord(entry["details"]) && entry["details"]["row"] === "dispatch")) retained.push({
|
|
207
|
+
position: linePosition,
|
|
208
|
+
line: line + "\n"
|
|
209
|
+
});
|
|
210
|
+
if (isRecord(entry) && isRecord(entry["details"])) {
|
|
211
|
+
const id = entry["details"]["audit_operation_id"];
|
|
212
|
+
if (typeof id === "string" && entry["decision"] === "mutation-attempt-open") openAttempts.set(id, {
|
|
213
|
+
position: linePosition,
|
|
214
|
+
line: line + "\n"
|
|
215
|
+
});
|
|
216
|
+
if (typeof id === "string" && entry["details"]["mutation_outcome"] !== void 0) openAttempts.delete(id);
|
|
217
|
+
}
|
|
218
|
+
} catch {}
|
|
219
|
+
linePosition++;
|
|
220
|
+
}
|
|
221
|
+
if (pending.length > 1048576 || oversized) {
|
|
222
|
+
pending = "";
|
|
223
|
+
oversized = true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} finally {
|
|
227
|
+
closeSync(fd);
|
|
228
|
+
}
|
|
229
|
+
const temporary = `${auditPath}.${randomUUID()}.tmp`;
|
|
230
|
+
try {
|
|
231
|
+
writeFileSync(temporary, [...retained, ...openAttempts.values()].sort((a, b) => a.position - b.position).map((record) => record.line).join(""), { mode: 384 });
|
|
232
|
+
appendFileSync(temporary, tail);
|
|
233
|
+
const output = openSync(temporary, "r+");
|
|
234
|
+
try {
|
|
235
|
+
fsyncSync(output);
|
|
236
|
+
} finally {
|
|
237
|
+
closeSync(output);
|
|
238
|
+
}
|
|
239
|
+
const grown = statSync(auditPath).size;
|
|
240
|
+
if (grown > size) {
|
|
241
|
+
const late = Buffer.alloc(grown - size);
|
|
242
|
+
const source = openSync(auditPath, "r");
|
|
243
|
+
try {
|
|
244
|
+
appendFileSync(temporary, late.subarray(0, readSync(source, late, 0, late.length, size)));
|
|
245
|
+
} finally {
|
|
246
|
+
closeSync(source);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
renameSync(temporary, auditPath);
|
|
250
|
+
} finally {
|
|
251
|
+
rmSync(temporary, { force: true });
|
|
252
|
+
}
|
|
253
|
+
}
|
|
154
254
|
/** Returns cost path from audit log state state without side effects. */
|
|
155
255
|
function getCostPath(stateDir) {
|
|
156
256
|
return path.join(stateDir, "cost.jsonl");
|
|
@@ -217,6 +317,7 @@ function appendAuditEntrySync(stateDir, entry) {
|
|
|
217
317
|
...prepared,
|
|
218
318
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
219
319
|
})}\n`);
|
|
320
|
+
compactAuditLog(auditPath);
|
|
220
321
|
} catch (error) {
|
|
221
322
|
createLogger("sno-station-mem:audit").error("memory.audit.append.failed", { error }, {
|
|
222
323
|
event_name: "memory.audit.append.failed",
|
|
@@ -427,4 +528,4 @@ async function flushAuditWrites() {
|
|
|
427
528
|
await Promise.allSettled(pending);
|
|
428
529
|
}
|
|
429
530
|
//#endregion
|
|
430
|
-
export {
|
|
531
|
+
export { currentMutationAttemptId as a, getCostPath as c, runWithMemoryAuditSync as d, runWithMutationAttempt as f, compactAuditLog as i, recoverInterruptedMutationAttempts as l, appendAuditEntryStrict as n, flushAuditWrites as o, readJsonlLines as p, appendAuditEntrySync as r, getAuditPath as s, appendAuditEntry as t, runWithMemoryAudit as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./paths-
|
|
1
|
+
import "./paths-DmmPxD_v.js";
|
|
2
2
|
//#region src/engine/operations/runtime-audit-log.d.ts
|
|
3
3
|
type AuditEvent = "tool_call" | "hook_trigger" | "kill_switch" | "startup" | "error" | "auto_recall" | "ambient_learning" | "session_summary" | "envelope_strip" | "storage_integrity" | "memory_injected" | "memory_searched" | "memory_read" | "memory_updated" | "memory_superseded" | "memory_deleted" | "memory_purged" | "rem_trigger_evaluated" | "rem_triggered" | "rem_completed" | "rem_failed";
|
|
4
4
|
type AuditStatus = "ok" | "error" | "skipped" | "partial";
|
|
@@ -125,6 +125,8 @@ interface MutationAttemptRunOptions<T> {
|
|
|
125
125
|
}
|
|
126
126
|
/** Returns audit path from audit log state state without side effects. */
|
|
127
127
|
declare function getAuditPath(stateDir: string): string;
|
|
128
|
+
/** Retain the recent tail and two days of REM replay evidence when the audit exceeds 16 MiB. */
|
|
129
|
+
declare function compactAuditLog(auditPath: string): void;
|
|
128
130
|
/** Returns cost path from audit log state state without side effects. */
|
|
129
131
|
declare function getCostPath(stateDir: string): string;
|
|
130
132
|
/** Persists audit entry through the single audit log state write path. */
|
|
@@ -146,4 +148,4 @@ declare function runWithMemoryAuditSync<T, E extends MemoryAuditEvent>(options:
|
|
|
146
148
|
/** Implements flush audit writes as the local audit log state operation. */
|
|
147
149
|
declare function flushAuditWrites(): Promise<void>;
|
|
148
150
|
//#endregion
|
|
149
|
-
export { runWithMutationAttempt as S,
|
|
151
|
+
export { runWithMutationAttempt as C, runWithMemoryAuditSync as S, flushAuditWrites as _, MemoryAuditEvent as a, recoverInterruptedMutationAttempts as b, MutationAttemptCompletion as c, MutationAttemptWriter as d, appendAuditEntry as f, currentMutationAttemptId as g, compactAuditLog as h, MemoryAuditDetailsByEvent as i, MutationAttemptOutcome as l, appendAuditEntrySync as m, AuditEvent as n, MemoryAuditRunOptions as o, appendAuditEntryStrict as p, AuditStatus as r, MemoryAuditSyncRunOptions as s, AuditEntry as t, MutationAttemptRunOptions as u, getAuditPath as v, runWithMemoryAudit as x, getCostPath as y };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as SCOPE_PATTERNS, i as isSystemBypassId, o as shouldWarnLegacyFallbackBypassId } from "./memory-scope-policy
|
|
1
|
+
import { c as SCOPE_PATTERNS, i as isSystemBypassId, o as shouldWarnLegacyFallbackBypassId } from "./memory-scope-policy--TiLZnrE.js";
|
|
2
2
|
import { createLogger, privateLogReference } from "@snoai/utils/logger";
|
|
3
3
|
//#region src/engine/security/scope-helpers.ts
|
|
4
4
|
/** @file scope-helpers.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Ar as MEMORY_ERROR_STATUS, C as getSnoStationMemStateDir, Fr as memoryMethod, Mr as MEMORY_ROUTES, Nr as MEMORY_SKIN_HEADER, S as getSidecarSocketPath, _ as readRemTestHoldMs, c as REM_SIDECAR_ORIGIN, d as getRemDiscoveryPath, f as getRemJobJournalPath, g as readRemOperationalConfig, i as REM_JOBS_PATH_PREFIX, kr as MEMORY_DEFAULT_SKIN_ID, l as REM_SOURCE, nr as MEMORY_SHUTDOWN_TIMEOUT_MS, r as REM_CORRELATION_ID_HEADER, s as REM_SIDECAR_HOST, u as getRemChassisJournalPath, v as SettingsUnavailableError, y as getDiscoveryPath } from "./config-
|
|
1
|
+
import { At as getAuditPath, Dt as appendAuditEntryStrict, K as REM_BUILT_OPERATION_TYPES, Ot as compactAuditLog, Pt as readJsonlLines, bt as ModelCallRefusedError, d as RemJobStore, f as parseRemJobStats, n as remNeedsHost, q as parseRemOperationType } from "./rem-trigger-DmRERTNH.js";
|
|
2
|
+
import { Ar as MEMORY_ERROR_STATUS, C as getSnoStationMemStateDir, Fr as memoryMethod, Mr as MEMORY_ROUTES, Nr as MEMORY_SKIN_HEADER, S as getSidecarSocketPath, _ as readRemTestHoldMs, c as REM_SIDECAR_ORIGIN, d as getRemDiscoveryPath, f as getRemJobJournalPath, g as readRemOperationalConfig, i as REM_JOBS_PATH_PREFIX, kr as MEMORY_DEFAULT_SKIN_ID, l as REM_SOURCE, nr as MEMORY_SHUTDOWN_TIMEOUT_MS, r as REM_CORRELATION_ID_HEADER, s as REM_SIDECAR_HOST, u as getRemChassisJournalPath, v as SettingsUnavailableError, y as getDiscoveryPath } from "./config-C7LzSWhG.js";
|
|
3
3
|
import { t as ContractError } from "./error-D-wb-rZw.js";
|
|
4
4
|
import { setImmediate } from "node:timers/promises";
|
|
5
5
|
import { createLogger, currentLogContext, effectiveLogLevel, emitDiagnostic } from "@snoai/utils/logger";
|
|
@@ -80,7 +80,7 @@ function readRequestBody(request, signal) {
|
|
|
80
80
|
}
|
|
81
81
|
//#endregion
|
|
82
82
|
//#region src/sidecar/memory-routes.ts
|
|
83
|
-
const log$
|
|
83
|
+
const log$1 = createLogger("sno-station-mem:memory-routes");
|
|
84
84
|
async function serveMemoryRoute(request, response, pathname, openPool, activeTasks) {
|
|
85
85
|
const method = memoryMethod(pathname);
|
|
86
86
|
if (!method || request.method !== "POST") return false;
|
|
@@ -123,7 +123,7 @@ async function serveMemoryRoute(request, response, pathname, openPool, activeTas
|
|
|
123
123
|
}));
|
|
124
124
|
return true;
|
|
125
125
|
}
|
|
126
|
-
log$
|
|
126
|
+
log$1.error("Memory engine request failed", {
|
|
127
127
|
method,
|
|
128
128
|
skinId,
|
|
129
129
|
error,
|
|
@@ -208,318 +208,9 @@ var RemChassisJournal = class {
|
|
|
208
208
|
} finally {
|
|
209
209
|
await handle.close();
|
|
210
210
|
}
|
|
211
|
-
if (!journalAlreadyExisted) await syncDirectory$2(parent);
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
async function syncDirectory$2(directory) {
|
|
215
|
-
if (process.platform === "win32") return;
|
|
216
|
-
const handle = await open(directory, "r");
|
|
217
|
-
try {
|
|
218
|
-
await handle.sync();
|
|
219
|
-
} finally {
|
|
220
|
-
await handle.close();
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region src/sidecar/rem-job-store.ts
|
|
225
|
-
/** @file rem-job-store.ts
|
|
226
|
-
* @purpose Persists append-only REM job state transitions.
|
|
227
|
-
* @boundary Durable local JSONL journal used by the standalone REM sidecar.
|
|
228
|
-
*/
|
|
229
|
-
const log$1 = createLogger("sno-station-mem:rem-jobs");
|
|
230
|
-
const remJobStateSchema = z.enum([
|
|
231
|
-
"queued",
|
|
232
|
-
"running",
|
|
233
|
-
"done",
|
|
234
|
-
"failed",
|
|
235
|
-
"skipped"
|
|
236
|
-
]);
|
|
237
|
-
const remJobMeasurementsSchema = z.object({
|
|
238
|
-
rows_considered: z.number().int().nonnegative(),
|
|
239
|
-
pairs_built: z.number().int().nonnegative().optional(),
|
|
240
|
-
pair_cap_binding: z.boolean().optional(),
|
|
241
|
-
model_calls: z.number().int().nonnegative(),
|
|
242
|
-
model_tokens: z.number().int().nonnegative(),
|
|
243
|
-
wall_ms: z.number().int().nonnegative()
|
|
244
|
-
}).strict();
|
|
245
|
-
const remJobStatsSchema = z.object({
|
|
246
|
-
operations: z.number().int().nonnegative(),
|
|
247
|
-
applied_count: z.number().int().nonnegative().optional(),
|
|
248
|
-
actionable_candidate_count: z.number().int().nonnegative().optional(),
|
|
249
|
-
applied_fraction: z.number().min(0).max(1).nullable().optional(),
|
|
250
|
-
scan: z.object({
|
|
251
|
-
scope: z.string().min(1),
|
|
252
|
-
candidate_count: z.number().int().nonnegative(),
|
|
253
|
-
stamped_skipped_count: z.number().int().nonnegative().optional(),
|
|
254
|
-
actionable_candidate_count: z.number().int().nonnegative().optional()
|
|
255
|
-
}).strict().optional(),
|
|
256
|
-
parse_failure_count: z.number().int().nonnegative().optional(),
|
|
257
|
-
top_refusal_reasons: z.array(z.string().min(1)).max(2).optional(),
|
|
258
|
-
measured: remJobMeasurementsSchema.optional(),
|
|
259
|
-
by_operation: z.array(z.object({
|
|
260
|
-
operation: z.string().min(1),
|
|
261
|
-
applied_count: z.number().int().nonnegative(),
|
|
262
|
-
actionable_candidate_count: z.number().int().nonnegative(),
|
|
263
|
-
candidate_count: z.number().int().nonnegative(),
|
|
264
|
-
parse_failure_count: z.number().int().nonnegative(),
|
|
265
|
-
top_refusal_reasons: z.array(z.string().min(1)).max(2),
|
|
266
|
-
measured: remJobMeasurementsSchema
|
|
267
|
-
}).strict()).min(1).optional()
|
|
268
|
-
}).strict();
|
|
269
|
-
function parseRemJobStats(value) {
|
|
270
|
-
const parsed = remJobStatsSchema.safeParse(value);
|
|
271
|
-
return parsed.success ? parsed.data : void 0;
|
|
272
|
-
}
|
|
273
|
-
const remWaveJobSchema = z.object({
|
|
274
|
-
payloadVersion: z.literal(1),
|
|
275
|
-
waveId: z.string().min(1),
|
|
276
|
-
correlationId: z.string().min(1),
|
|
277
|
-
scope: z.string().min(1),
|
|
278
|
-
requestedOperations: z.array(z.string().min(1)).min(1),
|
|
279
|
-
state: remJobStateSchema,
|
|
280
|
-
startedAt: z.string().datetime().nullable(),
|
|
281
|
-
finishedAt: z.string().datetime().nullable(),
|
|
282
|
-
stats: remJobStatsSchema,
|
|
283
|
-
error: z.string().min(1).optional()
|
|
284
|
-
}).strict();
|
|
285
|
-
const legacyJobSchema = z.object({
|
|
286
|
-
job_id: z.string().min(1),
|
|
287
|
-
state: remJobStateSchema,
|
|
288
|
-
type: z.string().min(1),
|
|
289
|
-
scope: z.string().min(1),
|
|
290
|
-
started_at: z.string().datetime().nullable(),
|
|
291
|
-
finished_at: z.string().datetime().nullable(),
|
|
292
|
-
stats: remJobStatsSchema,
|
|
293
|
-
error: z.string().min(1).optional(),
|
|
294
|
-
correlation_id: z.string().min(1)
|
|
295
|
-
}).strict();
|
|
296
|
-
const OPERATION_ORDER = [
|
|
297
|
-
"rem-replace",
|
|
298
|
-
"rem-update",
|
|
299
|
-
"rem-distill",
|
|
300
|
-
"rem-retire"
|
|
301
|
-
];
|
|
302
|
-
var RemJobStore = class RemJobStore {
|
|
303
|
-
journalPath;
|
|
304
|
-
onDurableTransition;
|
|
305
|
-
jobs = /* @__PURE__ */ new Map();
|
|
306
|
-
persistedJobs = /* @__PURE__ */ new Set();
|
|
307
|
-
mergeKeys = /* @__PURE__ */ new Map();
|
|
308
|
-
operationQueue = Promise.resolve();
|
|
309
|
-
constructor(journalPath, onDurableTransition) {
|
|
310
|
-
this.journalPath = journalPath;
|
|
311
|
-
this.onDurableTransition = onDurableTransition;
|
|
312
|
-
}
|
|
313
|
-
static async open(journalPath, onDurableTransition = () => void 0) {
|
|
314
|
-
const store = new RemJobStore(journalPath, onDurableTransition);
|
|
315
|
-
await store.migrateLegacyJournal().catch((error) => store.reportFailure(error));
|
|
316
|
-
await store.load();
|
|
317
|
-
return store;
|
|
318
|
-
}
|
|
319
|
-
isPersisted(jobId) {
|
|
320
|
-
return this.persistedJobs.has(jobId);
|
|
321
|
-
}
|
|
322
|
-
get(jobId) {
|
|
323
|
-
const job = this.jobs.get(jobId);
|
|
324
|
-
return job === void 0 ? void 0 : toRemJob(job);
|
|
325
|
-
}
|
|
326
|
-
nonTerminalJobs() {
|
|
327
|
-
return Array.from(this.jobs.values()).filter((job) => job.state === "queued" || job.state === "running").map(toRemJob);
|
|
328
|
-
}
|
|
329
|
-
async createQueued(type, scope, correlationId) {
|
|
330
|
-
return this.enqueue(async () => {
|
|
331
|
-
const requestedOperations = canonicalOperations(typeof type === "string" ? [type] : type);
|
|
332
|
-
if (requestedOperations.length === 0) throw new Error("REM wave requires at least one supported operation");
|
|
333
|
-
const mergeKey = `${correlationId}\0${scope}`;
|
|
334
|
-
const existingId = this.mergeKeys.get(mergeKey);
|
|
335
|
-
const existing = existingId === void 0 ? void 0 : this.jobs.get(existingId);
|
|
336
|
-
if (existing !== void 0 && existing.state === "queued") {
|
|
337
|
-
const mergedOperations = canonicalOperations([...existing.requestedOperations, ...requestedOperations]);
|
|
338
|
-
if (mergedOperations.length === existing.requestedOperations.length) return {
|
|
339
|
-
created: false,
|
|
340
|
-
job: toRemJob(existing)
|
|
341
|
-
};
|
|
342
|
-
const updated = remWaveJobSchema.parse({
|
|
343
|
-
...existing,
|
|
344
|
-
requestedOperations: mergedOperations
|
|
345
|
-
});
|
|
346
|
-
const durable = await this.persist(updated);
|
|
347
|
-
this.jobs.set(updated.waveId, updated);
|
|
348
|
-
if (durable) this.onDurableTransition(toRemJob(updated));
|
|
349
|
-
return {
|
|
350
|
-
created: false,
|
|
351
|
-
job: toRemJob(updated)
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
if (existing !== void 0 && existing.state !== "skipped" && requestedOperations.every((operation) => existing.requestedOperations.includes(operation))) return {
|
|
355
|
-
created: false,
|
|
356
|
-
job: toRemJob(existing)
|
|
357
|
-
};
|
|
358
|
-
const job = remWaveJobSchema.parse({
|
|
359
|
-
payloadVersion: 1,
|
|
360
|
-
waveId: `rem-wave-${randomUUID()}`,
|
|
361
|
-
correlationId,
|
|
362
|
-
scope,
|
|
363
|
-
requestedOperations,
|
|
364
|
-
state: "queued",
|
|
365
|
-
startedAt: null,
|
|
366
|
-
finishedAt: null,
|
|
367
|
-
stats: { operations: 0 }
|
|
368
|
-
});
|
|
369
|
-
const durable = await this.persist(job);
|
|
370
|
-
this.jobs.set(job.waveId, job);
|
|
371
|
-
this.mergeKeys.set(mergeKey, job.waveId);
|
|
372
|
-
const outward = toRemJob(job);
|
|
373
|
-
if (durable) this.onDurableTransition(outward);
|
|
374
|
-
return {
|
|
375
|
-
created: true,
|
|
376
|
-
job: outward
|
|
377
|
-
};
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
async transition(jobId, transition) {
|
|
381
|
-
return this.enqueue(async () => {
|
|
382
|
-
const current = this.jobs.get(jobId);
|
|
383
|
-
if (!current) throw new Error(`REM job not found: ${jobId}`);
|
|
384
|
-
const next = remWaveJobSchema.parse({
|
|
385
|
-
...current,
|
|
386
|
-
state: transition.state,
|
|
387
|
-
...transition.started_at === void 0 ? {} : { startedAt: transition.started_at },
|
|
388
|
-
...transition.finished_at === void 0 ? {} : { finishedAt: transition.finished_at },
|
|
389
|
-
...transition.stats === void 0 ? {} : { stats: transition.stats },
|
|
390
|
-
...transition.error === void 0 ? {} : { error: transition.error }
|
|
391
|
-
});
|
|
392
|
-
const durable = await this.persist(next);
|
|
393
|
-
this.jobs.set(jobId, next);
|
|
394
|
-
const outward = toRemJob(next);
|
|
395
|
-
if (durable) this.onDurableTransition(outward);
|
|
396
|
-
return outward;
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
async load() {
|
|
400
|
-
if (!existsSync(this.journalPath)) return;
|
|
401
|
-
const bytes = await readFile(this.journalPath);
|
|
402
|
-
const lines = bytes.toString("utf8").split("\n");
|
|
403
|
-
const endsWithNewline = bytes.length === 0 || bytes[bytes.length - 1] === 10;
|
|
404
|
-
for (const [index, line] of lines.entries()) {
|
|
405
|
-
if (!line) continue;
|
|
406
|
-
if (!endsWithNewline && index === lines.length - 1) {
|
|
407
|
-
const lastNewline = bytes.lastIndexOf(10);
|
|
408
|
-
await this.truncateJournal(lastNewline < 0 ? 0 : lastNewline + 1);
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
try {
|
|
412
|
-
const parsed = JSON.parse(line);
|
|
413
|
-
const job = remWaveJobSchema.parse(parsed);
|
|
414
|
-
this.jobs.set(job.waveId, job);
|
|
415
|
-
this.mergeKeys.set(`${job.correlationId}\0${job.scope}`, job.waveId);
|
|
416
|
-
} catch (error) {
|
|
417
|
-
log$1.error("rem.journal.failed", {
|
|
418
|
-
path: this.journalPath,
|
|
419
|
-
line: index + 1,
|
|
420
|
-
error
|
|
421
|
-
}, {
|
|
422
|
-
event_name: "rem.journal.failed",
|
|
423
|
-
file: "packages/memory/src/sidecar/rem-job-store.ts",
|
|
424
|
-
function: "load",
|
|
425
|
-
site_id: "rem-job-store.load.invalid-line"
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
async migrateLegacyJournal() {
|
|
431
|
-
const legacyPath = path.join(path.dirname(this.journalPath), "rem-jobs.jsonl");
|
|
432
|
-
if (!existsSync(legacyPath)) return;
|
|
433
|
-
const latest = /* @__PURE__ */ new Map();
|
|
434
|
-
for await (const line of readJsonlLines(legacyPath)) try {
|
|
435
|
-
const parsed = JSON.parse(line);
|
|
436
|
-
const job = legacyJobSchema.parse(parsed);
|
|
437
|
-
latest.set(job.job_id, job);
|
|
438
|
-
} catch (error) {
|
|
439
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
440
|
-
this.reportFailure(reason);
|
|
441
|
-
}
|
|
442
|
-
const interrupted = [...latest.values()].filter((job) => job.state === "queued" || job.state === "running");
|
|
443
|
-
if (interrupted.length > 0) {
|
|
444
|
-
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
445
|
-
const handle = await open(legacyPath, "a");
|
|
446
|
-
try {
|
|
447
|
-
for (const job of interrupted) await handle.writeFile(`${JSON.stringify({
|
|
448
|
-
...job,
|
|
449
|
-
state: "failed",
|
|
450
|
-
finished_at: finishedAt,
|
|
451
|
-
error: "sidecar_upgrade_interrupted"
|
|
452
|
-
})}\n`, "utf8");
|
|
453
|
-
await handle.sync();
|
|
454
|
-
} finally {
|
|
455
|
-
await handle.close();
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
await rename(legacyPath, path.join(path.dirname(legacyPath), "rem-jobs.v0.jsonl"));
|
|
459
|
-
}
|
|
460
|
-
reportFailure(error) {
|
|
461
|
-
log$1.error("rem.journal.failed", {
|
|
462
|
-
error,
|
|
463
|
-
path: this.journalPath
|
|
464
|
-
}, {
|
|
465
|
-
event_name: "rem.journal.failed",
|
|
466
|
-
file: "packages/memory/src/sidecar/rem-job-store.ts",
|
|
467
|
-
function: "reportFailure",
|
|
468
|
-
site_id: "rem.journal.failed"
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
async persist(job) {
|
|
472
|
-
this.persistedJobs.delete(job.waveId);
|
|
473
|
-
await this.append(job);
|
|
474
|
-
this.persistedJobs.add(job.waveId);
|
|
475
|
-
return true;
|
|
476
|
-
}
|
|
477
|
-
async truncateJournal(length) {
|
|
478
|
-
const handle = await open(this.journalPath, "r+");
|
|
479
|
-
try {
|
|
480
|
-
await handle.truncate(length);
|
|
481
|
-
await handle.sync();
|
|
482
|
-
} finally {
|
|
483
|
-
await handle.close();
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
async append(job) {
|
|
487
|
-
const parent = path.dirname(this.journalPath);
|
|
488
|
-
await mkdir(parent, { recursive: true });
|
|
489
|
-
const journalAlreadyExisted = existsSync(this.journalPath);
|
|
490
|
-
const handle = await open(this.journalPath, "a");
|
|
491
|
-
try {
|
|
492
|
-
await handle.writeFile(`${JSON.stringify(job)}\n`, "utf8");
|
|
493
|
-
await handle.sync();
|
|
494
|
-
} finally {
|
|
495
|
-
await handle.close();
|
|
496
|
-
}
|
|
497
211
|
if (!journalAlreadyExisted) await syncDirectory$1(parent);
|
|
498
212
|
}
|
|
499
|
-
enqueue(operation) {
|
|
500
|
-
const result = this.operationQueue.then(operation);
|
|
501
|
-
this.operationQueue = result.then(() => void 0, () => void 0);
|
|
502
|
-
return result;
|
|
503
|
-
}
|
|
504
213
|
};
|
|
505
|
-
function canonicalOperations(operations) {
|
|
506
|
-
const unique = new Set(operations);
|
|
507
|
-
return OPERATION_ORDER.filter((operation) => unique.has(operation));
|
|
508
|
-
}
|
|
509
|
-
function toRemJob(job) {
|
|
510
|
-
return {
|
|
511
|
-
job_id: job.waveId,
|
|
512
|
-
state: job.state,
|
|
513
|
-
type: job.requestedOperations[0] ?? "rem-replace",
|
|
514
|
-
scope: job.scope,
|
|
515
|
-
started_at: job.startedAt,
|
|
516
|
-
finished_at: job.finishedAt,
|
|
517
|
-
stats: job.stats,
|
|
518
|
-
...job.error === void 0 ? {} : { error: job.error },
|
|
519
|
-
correlation_id: job.correlationId,
|
|
520
|
-
requested_operations: [...job.requestedOperations]
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
214
|
async function syncDirectory$1(directory) {
|
|
524
215
|
if (process.platform === "win32") return;
|
|
525
216
|
const handle = await open(directory, "r");
|
|
@@ -643,7 +334,7 @@ async function startOwnedRemSidecar() {
|
|
|
643
334
|
async open() {
|
|
644
335
|
if (currentMemory) return currentMemory;
|
|
645
336
|
if (settingsError) throw settingsError;
|
|
646
|
-
openingMemory ??= import("./memory-runtime-
|
|
337
|
+
openingMemory ??= import("./memory-runtime-HibOMCFa.js").then((module) => module.MemoryRuntimePool.open()).then((pool) => {
|
|
647
338
|
currentMemory = pool;
|
|
648
339
|
if (stopping) pool.stopTimers();
|
|
649
340
|
return pool;
|
|
@@ -1038,7 +729,7 @@ async function runChassisJob(store, journal, waveId, holdMs, runtime) {
|
|
|
1038
729
|
cleanRefusalReasons.push(reason);
|
|
1039
730
|
await appendChassisRefusal(journal, queued, operation, "refused", reason);
|
|
1040
731
|
}
|
|
1041
|
-
const { runRemProductionOrderedWave } = await import("./rem-batch-executor-
|
|
732
|
+
const { runRemProductionOrderedWave } = await import("./rem-batch-executor-8x4FBLtW.js");
|
|
1042
733
|
const result = enabledOperations.length === 0 ? {
|
|
1043
734
|
decision: "allow",
|
|
1044
735
|
reasonCode: null,
|
|
@@ -1167,11 +858,15 @@ async function runChassisJob(store, journal, waveId, holdMs, runtime) {
|
|
|
1167
858
|
}
|
|
1168
859
|
async function persistCompletedJob(store, job, stats) {
|
|
1169
860
|
const auditPersisted = await auditRem("rem_completed", job, { stats });
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
861
|
+
try {
|
|
862
|
+
await store.transition(job.job_id, {
|
|
863
|
+
state: "done",
|
|
864
|
+
finished_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
865
|
+
stats
|
|
866
|
+
});
|
|
867
|
+
} catch (error) {
|
|
868
|
+
reportSidecarFailure("completion-job-journal", error);
|
|
869
|
+
}
|
|
1175
870
|
if (store.isPersisted(job.job_id)) return "job_journal";
|
|
1176
871
|
if (auditPersisted) return "completed_audit";
|
|
1177
872
|
reportSidecarFailure("completion-persistence", /* @__PURE__ */ new Error("completed work has no durable completion receipt"));
|
|
@@ -1268,6 +963,8 @@ async function recoverInterruptedJobs(store, completedJobStats, jobs) {
|
|
|
1268
963
|
}
|
|
1269
964
|
async function readCompletedJobStats(wantedJobs) {
|
|
1270
965
|
const completed = /* @__PURE__ */ new Map();
|
|
966
|
+
if (wantedJobs.size === 0) return completed;
|
|
967
|
+
compactAuditLog(getAuditPath(getSnoStationMemStateDir()));
|
|
1271
968
|
for await (const line of readJsonlLines(getAuditPath(getSnoStationMemStateDir()))) {
|
|
1272
969
|
if (line.length === 0) continue;
|
|
1273
970
|
try {
|
package/dist/sidecar/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jr as MEMORY_RECONNECT_INTERVAL_MS, m as isRemTraceEnabled, p as getRemTraceLogPath, v as SettingsUnavailableError } from "../config-
|
|
1
|
+
import { jr as MEMORY_RECONNECT_INTERVAL_MS, m as isRemTraceEnabled, p as getRemTraceLogPath, v as SettingsUnavailableError } from "../config-C7LzSWhG.js";
|
|
2
2
|
import { setTimeout } from "node:timers/promises";
|
|
3
3
|
import { addLogFileTarget, closeLogger, createLogger } from "@snoai/utils/logger";
|
|
4
4
|
//#region src/sidecar/main.ts
|
|
@@ -6,9 +6,9 @@ import { addLogFileTarget, closeLogger, createLogger } from "@snoai/utils/logger
|
|
|
6
6
|
* @purpose Boots the standalone local REM sidecar process.
|
|
7
7
|
* @boundary Process environment, sidecar lifecycle, and local request-log destination.
|
|
8
8
|
*/
|
|
9
|
-
const { startRemSidecar, DuplicateSidecarError } = await import("../server-
|
|
9
|
+
const { startRemSidecar, DuplicateSidecarError } = await import("../server-CCduS_Ea.js");
|
|
10
10
|
let sidecar;
|
|
11
|
-
|
|
11
|
+
for (let attempt = 1; !sidecar; attempt++) try {
|
|
12
12
|
sidecar = await startRemSidecar();
|
|
13
13
|
} catch (error) {
|
|
14
14
|
if (error instanceof DuplicateSidecarError) {
|
|
@@ -16,12 +16,19 @@ while (!sidecar) try {
|
|
|
16
16
|
process.exit(0);
|
|
17
17
|
}
|
|
18
18
|
if (error instanceof SettingsUnavailableError) throw error;
|
|
19
|
-
createLogger("sno-station-mem:sidecar").error("Memory service startup failed;
|
|
19
|
+
createLogger("sno-station-mem:sidecar").error(attempt >= 3 ? "Memory service startup failed after three attempts; stopping" : "Memory service startup failed; retrying", {
|
|
20
|
+
error,
|
|
21
|
+
attempt
|
|
22
|
+
}, {
|
|
20
23
|
event_name: "memory.sidecar.startup.failed",
|
|
21
24
|
file: "packages/memory/src/sidecar/main.ts",
|
|
22
25
|
function: "<module>",
|
|
23
26
|
site_id: "sidecar.main.startup.failed"
|
|
24
27
|
});
|
|
28
|
+
if (attempt >= 3) {
|
|
29
|
+
await closeLogger();
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
25
32
|
await setTimeout(MEMORY_RECONNECT_INTERVAL_MS);
|
|
26
33
|
}
|
|
27
34
|
if (isRemTraceEnabled()) addLogFileTarget(getRemTraceLogPath());
|