@remnic/plugin-openclaw 1.0.10 → 1.0.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/dist/{calibration-674TDQNV.js → calibration-WCHOK6DX.js} +12 -4
- package/dist/capsule-cli-TFKLAG3S.js +329 -0
- package/dist/capsule-crypto-K3IRTKRH.js +17 -0
- package/dist/capsule-export-CVA3CKUQ.js +265 -0
- package/dist/capsule-import-CFX7BY5W.js +16 -0
- package/dist/capsule-merge-7RVOHJK3.js +189 -0
- package/dist/{causal-chain-OKDZSDEB.js → causal-chain-WYN5QOPS.js} +3 -2
- package/dist/{causal-consolidation-5BEXLQV5.js → causal-consolidation-JD6KJJH6.js} +16 -12
- package/dist/{causal-retrieval-3BKBXVXD.js → causal-retrieval-NZHQOZOE.js} +6 -5
- package/dist/{causal-trajectory-graph-RQIT37DN.js → causal-trajectory-graph-VBPE2WPM.js} +1 -1
- package/dist/chunk-37NKFWSO.js +233 -0
- package/dist/chunk-3G7FAF6S.js +60 -0
- package/dist/{chunk-Z7GRLVK3.js → chunk-3GUF7RQI.js} +235 -19
- package/dist/chunk-3I7RHWYT.js +214 -0
- package/dist/chunk-4G2XCSD2.js +186 -0
- package/dist/chunk-6IWEAUN6.js +148 -0
- package/dist/{chunk-LN5UZQVG.js → chunk-6UFI73TJ.js} +5 -3
- package/dist/chunk-7OQEPGQF.js +529 -0
- package/dist/chunk-B52XADV3.js +244 -0
- package/dist/chunk-BU5KJVWF.js +78 -0
- package/dist/chunk-CXM7EBAO.js +289 -0
- package/dist/chunk-ETJZRIAM.js +227 -0
- package/dist/chunk-FQRSVYY4.js +110 -0
- package/dist/chunk-HRGFO6AW.js +349 -0
- package/dist/chunk-I6B2W2IY.js +47 -0
- package/dist/chunk-JZBOXOUC.js +259 -0
- package/dist/chunk-K7EUBNDD.js +185 -0
- package/dist/chunk-L4PRBB2A.js +1860 -0
- package/dist/chunk-MBIFE6SA.js +250 -0
- package/dist/chunk-N7EOZY6F.js +400 -0
- package/dist/chunk-NKVIN6RD.js +118 -0
- package/dist/chunk-OEI7GLV2.js +17 -0
- package/dist/{chunk-S2ISS4AH.js → chunk-P3DIW2SD.js} +10 -10
- package/dist/{chunk-7TENHBV2.js → chunk-RQCTMECT.js} +10 -48
- package/dist/chunk-SSFTU6LP.js +182 -0
- package/dist/{chunk-BXTMZDRT.js → chunk-SVSQAG6M.js} +7 -5
- package/dist/chunk-TLVIQLB4.js +874 -0
- package/dist/{chunk-JJSNPSCD.js → chunk-TNH24SF6.js} +352 -50
- package/dist/chunk-TVKKIS53.js +720 -0
- package/dist/{chunk-YHH3SXKD.js → chunk-WPINX4MF.js} +1 -59
- package/dist/{chunk-HCFFXBLV.js → chunk-XMSDA5WA.js} +5 -1861
- package/dist/chunk-YGGGUTG3.js +125 -0
- package/dist/chunk-YGXXBRV7.js +10 -0
- package/dist/cipher-VHAFCG7Z.js +27 -0
- package/dist/dreams-ledger-3I52ISYR.js +285 -0
- package/dist/{engine-65C2J63X.js → engine-VMTFKFGO.js} +5 -2
- package/dist/{fallback-llm-LVK5PDIM.js → fallback-llm-WCWNGIQ3.js} +2 -1
- package/dist/first-start-migration-I24M2JEE.js +258 -0
- package/dist/forget-NI4RBDPB.js +68 -0
- package/dist/fs-utils-PZRI2HDZ.js +29 -0
- package/dist/graph-edge-decay-5CVKWBYH.js +203 -0
- package/dist/index.js +9775 -2900
- package/dist/kdf-H5B23ZM2.js +25 -0
- package/dist/memory-governance-DWGFV4FX.js +25 -0
- package/dist/metadata-JAGIWHEA.js +20 -0
- package/dist/migrate-from-identity-anchor-N3354WMP.js +7 -0
- package/dist/path-5LCUBAAZ.js +8 -0
- package/dist/peers-JF2I6RCR.js +43 -0
- package/dist/purge-XN2VSPZ2.js +204 -0
- package/dist/secure-store-FWJ7LBPH.js +149 -0
- package/dist/state-PVISYXRH.js +7 -0
- package/dist/state-store-LP5BO6SF.js +15 -0
- package/dist/{storage-DM4ZGOCN.js → storage-T2OGFUF4.js} +3 -1
- package/dist/tier-stats-IZNW66NC.js +147 -0
- package/dist/trace-NJESSGH7.js +289 -0
- package/dist/tui-MGK2LYJY.js +12 -0
- package/dist/types-H5R5D3WF.js +30 -0
- package/openclaw.plugin.json +519 -4
- package/package.json +1 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// ../remnic-core/src/secure-store/cipher.ts
|
|
2
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
3
|
+
var ENVELOPE_VERSION = 1;
|
|
4
|
+
var IV_LENGTH = 12;
|
|
5
|
+
var AUTH_TAG_LENGTH = 16;
|
|
6
|
+
var ENVELOPE_SALT_LENGTH = 16;
|
|
7
|
+
var AES_KEY_LENGTH = 32;
|
|
8
|
+
var ENVELOPE_LAYOUT = Object.freeze({
|
|
9
|
+
version: 0,
|
|
10
|
+
salt: 1,
|
|
11
|
+
iv: 1 + ENVELOPE_SALT_LENGTH,
|
|
12
|
+
authTag: 1 + ENVELOPE_SALT_LENGTH + IV_LENGTH,
|
|
13
|
+
ciphertext: 1 + ENVELOPE_SALT_LENGTH + IV_LENGTH + AUTH_TAG_LENGTH
|
|
14
|
+
});
|
|
15
|
+
var ENVELOPE_HEADER_SIZE = ENVELOPE_LAYOUT.ciphertext;
|
|
16
|
+
function assertAesKey(key) {
|
|
17
|
+
if (!(key instanceof Uint8Array)) {
|
|
18
|
+
throw new Error("key must be a Uint8Array");
|
|
19
|
+
}
|
|
20
|
+
if (key.length !== AES_KEY_LENGTH) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`AES-256-GCM requires a ${AES_KEY_LENGTH}-byte key, got ${key.length}`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function seal(key, salt, plaintext, options = {}) {
|
|
27
|
+
assertAesKey(key);
|
|
28
|
+
if (!(salt instanceof Uint8Array) || salt.length !== ENVELOPE_SALT_LENGTH) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`salt must be ${ENVELOPE_SALT_LENGTH} bytes, got ${salt?.length ?? "non-buffer"}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (!(plaintext instanceof Uint8Array)) {
|
|
34
|
+
throw new Error("plaintext must be a Uint8Array");
|
|
35
|
+
}
|
|
36
|
+
let iv;
|
|
37
|
+
if (options.iv) {
|
|
38
|
+
if (options.iv.length !== IV_LENGTH) {
|
|
39
|
+
throw new Error(`iv must be ${IV_LENGTH} bytes, got ${options.iv.length}`);
|
|
40
|
+
}
|
|
41
|
+
iv = options.iv;
|
|
42
|
+
} else {
|
|
43
|
+
iv = randomBytes(IV_LENGTH);
|
|
44
|
+
}
|
|
45
|
+
const cipher = createCipheriv("aes-256-gcm", Buffer.from(key), Buffer.from(iv), {
|
|
46
|
+
authTagLength: AUTH_TAG_LENGTH
|
|
47
|
+
});
|
|
48
|
+
const headerAad = buildHeaderAad(salt);
|
|
49
|
+
const finalAad = options.aad ? Buffer.concat([headerAad, Buffer.from(options.aad)]) : headerAad;
|
|
50
|
+
cipher.setAAD(finalAad);
|
|
51
|
+
const ciphertext = Buffer.concat([cipher.update(Buffer.from(plaintext)), cipher.final()]);
|
|
52
|
+
const authTag = cipher.getAuthTag();
|
|
53
|
+
if (authTag.length !== AUTH_TAG_LENGTH) {
|
|
54
|
+
throw new Error(`unexpected auth tag length: ${authTag.length}`);
|
|
55
|
+
}
|
|
56
|
+
const envelope = Buffer.alloc(ENVELOPE_HEADER_SIZE + ciphertext.length);
|
|
57
|
+
envelope.writeUInt8(ENVELOPE_VERSION, ENVELOPE_LAYOUT.version);
|
|
58
|
+
Buffer.from(salt).copy(envelope, ENVELOPE_LAYOUT.salt);
|
|
59
|
+
Buffer.from(iv).copy(envelope, ENVELOPE_LAYOUT.iv);
|
|
60
|
+
authTag.copy(envelope, ENVELOPE_LAYOUT.authTag);
|
|
61
|
+
ciphertext.copy(envelope, ENVELOPE_LAYOUT.ciphertext);
|
|
62
|
+
return envelope;
|
|
63
|
+
}
|
|
64
|
+
function parseEnvelope(envelope) {
|
|
65
|
+
if (!(envelope instanceof Uint8Array)) {
|
|
66
|
+
throw new Error("envelope must be a Uint8Array");
|
|
67
|
+
}
|
|
68
|
+
if (envelope.length < ENVELOPE_HEADER_SIZE) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`envelope too short: need \u2265 ${ENVELOPE_HEADER_SIZE} bytes, got ${envelope.length}`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const buf = Buffer.from(envelope.buffer, envelope.byteOffset, envelope.byteLength);
|
|
74
|
+
const version = buf.readUInt8(ENVELOPE_LAYOUT.version);
|
|
75
|
+
if (version !== ENVELOPE_VERSION) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`unsupported envelope version: ${version} (this build supports ${ENVELOPE_VERSION})`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
version,
|
|
82
|
+
salt: buf.subarray(ENVELOPE_LAYOUT.salt, ENVELOPE_LAYOUT.salt + ENVELOPE_SALT_LENGTH),
|
|
83
|
+
iv: buf.subarray(ENVELOPE_LAYOUT.iv, ENVELOPE_LAYOUT.iv + IV_LENGTH),
|
|
84
|
+
authTag: buf.subarray(
|
|
85
|
+
ENVELOPE_LAYOUT.authTag,
|
|
86
|
+
ENVELOPE_LAYOUT.authTag + AUTH_TAG_LENGTH
|
|
87
|
+
),
|
|
88
|
+
ciphertext: buf.subarray(ENVELOPE_LAYOUT.ciphertext)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function open(key, envelope, options = {}) {
|
|
92
|
+
assertAesKey(key);
|
|
93
|
+
const parsed = parseEnvelope(envelope);
|
|
94
|
+
const decipher = createDecipheriv("aes-256-gcm", Buffer.from(key), parsed.iv, {
|
|
95
|
+
authTagLength: AUTH_TAG_LENGTH
|
|
96
|
+
});
|
|
97
|
+
decipher.setAuthTag(parsed.authTag);
|
|
98
|
+
const headerAad = buildHeaderAad(parsed.salt);
|
|
99
|
+
const finalAad = options.aad ? Buffer.concat([headerAad, Buffer.from(options.aad)]) : headerAad;
|
|
100
|
+
decipher.setAAD(finalAad);
|
|
101
|
+
return Buffer.concat([decipher.update(parsed.ciphertext), decipher.final()]);
|
|
102
|
+
}
|
|
103
|
+
function buildHeaderAad(salt) {
|
|
104
|
+
const out = Buffer.alloc(1 + ENVELOPE_SALT_LENGTH);
|
|
105
|
+
out.writeUInt8(ENVELOPE_VERSION, 0);
|
|
106
|
+
Buffer.from(salt).copy(out, 1);
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
function generateSalt() {
|
|
110
|
+
return randomBytes(ENVELOPE_SALT_LENGTH);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export {
|
|
114
|
+
ENVELOPE_VERSION,
|
|
115
|
+
IV_LENGTH,
|
|
116
|
+
AUTH_TAG_LENGTH,
|
|
117
|
+
ENVELOPE_SALT_LENGTH,
|
|
118
|
+
AES_KEY_LENGTH,
|
|
119
|
+
ENVELOPE_LAYOUT,
|
|
120
|
+
ENVELOPE_HEADER_SIZE,
|
|
121
|
+
seal,
|
|
122
|
+
parseEnvelope,
|
|
123
|
+
open,
|
|
124
|
+
generateSalt
|
|
125
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AES_KEY_LENGTH,
|
|
3
|
+
AUTH_TAG_LENGTH,
|
|
4
|
+
ENVELOPE_HEADER_SIZE,
|
|
5
|
+
ENVELOPE_LAYOUT,
|
|
6
|
+
ENVELOPE_SALT_LENGTH,
|
|
7
|
+
ENVELOPE_VERSION,
|
|
8
|
+
IV_LENGTH,
|
|
9
|
+
generateSalt,
|
|
10
|
+
open,
|
|
11
|
+
parseEnvelope,
|
|
12
|
+
seal
|
|
13
|
+
} from "./chunk-YGGGUTG3.js";
|
|
14
|
+
import "./chunk-MLKGABMK.js";
|
|
15
|
+
export {
|
|
16
|
+
AES_KEY_LENGTH,
|
|
17
|
+
AUTH_TAG_LENGTH,
|
|
18
|
+
ENVELOPE_HEADER_SIZE,
|
|
19
|
+
ENVELOPE_LAYOUT,
|
|
20
|
+
ENVELOPE_SALT_LENGTH,
|
|
21
|
+
ENVELOPE_VERSION,
|
|
22
|
+
IV_LENGTH,
|
|
23
|
+
generateSalt,
|
|
24
|
+
open,
|
|
25
|
+
parseEnvelope,
|
|
26
|
+
seal
|
|
27
|
+
};
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import "./chunk-MLKGABMK.js";
|
|
2
|
+
|
|
3
|
+
// ../remnic-core/src/maintenance/dreams-ledger.ts
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { appendFile, lstat, mkdir, readdir, readFile } from "fs/promises";
|
|
6
|
+
function dreamsLedgerPath(memoryDir) {
|
|
7
|
+
return path.join(memoryDir, "state", "dreams-ledger.jsonl");
|
|
8
|
+
}
|
|
9
|
+
async function appendDreamsLedgerEntry(memoryDir, entry) {
|
|
10
|
+
const ledgerPath = dreamsLedgerPath(memoryDir);
|
|
11
|
+
await mkdir(path.dirname(ledgerPath), { recursive: true });
|
|
12
|
+
await appendFile(ledgerPath, JSON.stringify(entry) + "\n", "utf-8");
|
|
13
|
+
}
|
|
14
|
+
async function readDreamsLedgerEntries(memoryDir) {
|
|
15
|
+
const ledgerPath = dreamsLedgerPath(memoryDir);
|
|
16
|
+
let raw;
|
|
17
|
+
try {
|
|
18
|
+
raw = await readFile(ledgerPath, "utf-8");
|
|
19
|
+
} catch (err) {
|
|
20
|
+
const code = err.code;
|
|
21
|
+
if (code === "ENOENT") return [];
|
|
22
|
+
throw err;
|
|
23
|
+
}
|
|
24
|
+
const entries = [];
|
|
25
|
+
for (const line of raw.split("\n")) {
|
|
26
|
+
const trimmed = line.trim();
|
|
27
|
+
if (!trimmed) continue;
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(trimmed);
|
|
30
|
+
if (typeof parsed !== "object" || parsed === null) continue;
|
|
31
|
+
if (typeof parsed.phase === "string" && (parsed.phase === "lightSleep" || parsed.phase === "rem" || parsed.phase === "deepSleep") && typeof parsed.startedAt === "string" && typeof parsed.completedAt === "string" && typeof parsed.durationMs === "number" && typeof parsed.itemsProcessed === "number") {
|
|
32
|
+
entries.push({
|
|
33
|
+
schemaVersion: 1,
|
|
34
|
+
startedAt: parsed.startedAt,
|
|
35
|
+
completedAt: parsed.completedAt,
|
|
36
|
+
durationMs: parsed.durationMs,
|
|
37
|
+
phase: parsed.phase,
|
|
38
|
+
itemsProcessed: parsed.itemsProcessed,
|
|
39
|
+
dryRun: parsed.dryRun === true,
|
|
40
|
+
trigger: parsed.trigger === "manual" ? "manual" : "scheduled",
|
|
41
|
+
notes: typeof parsed.notes === "string" ? parsed.notes : void 0
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return entries;
|
|
48
|
+
}
|
|
49
|
+
var ALL_PHASES = ["lightSleep", "rem", "deepSleep"];
|
|
50
|
+
var MAX_WINDOW_HOURS = 24 * 365 * 100;
|
|
51
|
+
function normalizeDreamsStatusWindowHours(value, fallback = 24) {
|
|
52
|
+
const raw = value === void 0 || value === null ? fallback : value;
|
|
53
|
+
if (typeof raw !== "number" || !Number.isFinite(raw) || !Number.isInteger(raw) || raw < 1 || raw > MAX_WINDOW_HOURS) {
|
|
54
|
+
throw new RangeError(`windowHours must be a positive integer no greater than ${MAX_WINDOW_HOURS}`);
|
|
55
|
+
}
|
|
56
|
+
return raw;
|
|
57
|
+
}
|
|
58
|
+
async function getDreamsStatus(memoryDir, windowHours = 24, now = /* @__PURE__ */ new Date()) {
|
|
59
|
+
const boundedWindowHours = normalizeDreamsStatusWindowHours(windowHours);
|
|
60
|
+
const nowMs = now.getTime();
|
|
61
|
+
if (!Number.isFinite(nowMs)) {
|
|
62
|
+
throw new RangeError("now must be a valid Date");
|
|
63
|
+
}
|
|
64
|
+
const windowMs = boundedWindowHours * 60 * 60 * 1e3;
|
|
65
|
+
const windowStart = new Date(nowMs - windowMs);
|
|
66
|
+
const windowEnd = now;
|
|
67
|
+
if (!Number.isFinite(windowStart.getTime())) {
|
|
68
|
+
throw new RangeError("windowHours produces an invalid status window");
|
|
69
|
+
}
|
|
70
|
+
const entries = await readDreamsLedgerEntries(memoryDir);
|
|
71
|
+
const windowEntries = entries.filter((e) => {
|
|
72
|
+
const ts = Date.parse(e.completedAt);
|
|
73
|
+
return Number.isFinite(ts) && ts >= windowStart.getTime() && ts < windowEnd.getTime();
|
|
74
|
+
});
|
|
75
|
+
const statusMap = /* @__PURE__ */ new Map();
|
|
76
|
+
for (const phase of ALL_PHASES) {
|
|
77
|
+
statusMap.set(phase, {
|
|
78
|
+
phase,
|
|
79
|
+
runCount: 0,
|
|
80
|
+
totalDurationMs: 0,
|
|
81
|
+
totalItemsProcessed: 0,
|
|
82
|
+
lastRunAt: null,
|
|
83
|
+
lastDurationMs: null
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
for (const entry of windowEntries) {
|
|
87
|
+
const status = statusMap.get(entry.phase);
|
|
88
|
+
if (!status) continue;
|
|
89
|
+
status.runCount += 1;
|
|
90
|
+
status.totalDurationMs += entry.durationMs;
|
|
91
|
+
status.totalItemsProcessed += entry.itemsProcessed;
|
|
92
|
+
if (status.lastRunAt === null || Date.parse(entry.completedAt) > Date.parse(status.lastRunAt)) {
|
|
93
|
+
status.lastRunAt = entry.completedAt;
|
|
94
|
+
status.lastDurationMs = entry.durationMs;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
windowStart: windowStart.toISOString(),
|
|
99
|
+
windowEnd: windowEnd.toISOString(),
|
|
100
|
+
phases: {
|
|
101
|
+
lightSleep: statusMap.get("lightSleep"),
|
|
102
|
+
rem: statusMap.get("rem"),
|
|
103
|
+
deepSleep: statusMap.get("deepSleep")
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
async function recordDreamsPhaseRun(options) {
|
|
108
|
+
const startedAt = options.startedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
109
|
+
const completedAt = options.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
110
|
+
const durationMs = Math.max(0, Date.parse(completedAt) - Date.parse(startedAt));
|
|
111
|
+
const ledgerEntry = {
|
|
112
|
+
schemaVersion: 1,
|
|
113
|
+
startedAt,
|
|
114
|
+
completedAt,
|
|
115
|
+
durationMs: Number.isFinite(durationMs) ? durationMs : 0,
|
|
116
|
+
phase: options.phase,
|
|
117
|
+
itemsProcessed: Math.max(0, Math.floor(options.itemsProcessed)),
|
|
118
|
+
dryRun: options.dryRun === true,
|
|
119
|
+
trigger: options.trigger,
|
|
120
|
+
notes: options.notes
|
|
121
|
+
};
|
|
122
|
+
if (!ledgerEntry.dryRun) {
|
|
123
|
+
await appendDreamsLedgerEntry(options.memoryDir, ledgerEntry);
|
|
124
|
+
}
|
|
125
|
+
return ledgerEntry;
|
|
126
|
+
}
|
|
127
|
+
async function runDreamsPhase(options, governanceRunner, phaseRunner) {
|
|
128
|
+
const { memoryDir, phase, dryRun = false } = options;
|
|
129
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
130
|
+
let itemsProcessed = 0;
|
|
131
|
+
let notes;
|
|
132
|
+
if (phase === "lightSleep") {
|
|
133
|
+
if (!dryRun) {
|
|
134
|
+
if (!phaseRunner) {
|
|
135
|
+
throw new Error("light-sleep manual runs require a phase runner");
|
|
136
|
+
}
|
|
137
|
+
const result = await phaseRunner({ memoryDir, phase });
|
|
138
|
+
itemsProcessed = Math.max(0, Math.floor(result.itemsProcessed));
|
|
139
|
+
notes = result.notes ?? `scored ${itemsProcessed} memories`;
|
|
140
|
+
} else {
|
|
141
|
+
try {
|
|
142
|
+
const ledgerPath = path.join(memoryDir, "state", "observation-ledger", "rebuilt-observations.jsonl");
|
|
143
|
+
let raw = "";
|
|
144
|
+
try {
|
|
145
|
+
raw = await readFile(ledgerPath, "utf-8");
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
const lines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
149
|
+
const cutoff = Date.now() - 24 * 60 * 60 * 1e3;
|
|
150
|
+
itemsProcessed = lines.filter((line) => {
|
|
151
|
+
try {
|
|
152
|
+
const obj = JSON.parse(line);
|
|
153
|
+
const timestamp = typeof obj.ts === "string" ? obj.ts : typeof obj.timestamp === "string" ? obj.timestamp : null;
|
|
154
|
+
if (!timestamp) return false;
|
|
155
|
+
const ms = Date.parse(timestamp);
|
|
156
|
+
return Number.isFinite(ms) && ms >= cutoff;
|
|
157
|
+
} catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}).length;
|
|
161
|
+
notes = `dry-run: would score ${itemsProcessed} observation entries`;
|
|
162
|
+
} catch (err) {
|
|
163
|
+
throw new Error(`light-sleep scan failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
} else if (phase === "rem") {
|
|
167
|
+
if (!dryRun) {
|
|
168
|
+
if (!phaseRunner) {
|
|
169
|
+
throw new Error("REM manual runs require a phase runner");
|
|
170
|
+
}
|
|
171
|
+
const result = await phaseRunner({ memoryDir, phase });
|
|
172
|
+
itemsProcessed = Math.max(0, Math.floor(result.itemsProcessed));
|
|
173
|
+
notes = result.notes ?? `REM pass assessed ${itemsProcessed} memories`;
|
|
174
|
+
} else {
|
|
175
|
+
try {
|
|
176
|
+
const stateFilePath = path.join(memoryDir, "state", "semantic-consolidation-last-run.json");
|
|
177
|
+
let lastRunAt = null;
|
|
178
|
+
try {
|
|
179
|
+
const stateRaw = await readFile(stateFilePath, "utf-8");
|
|
180
|
+
const stateData = JSON.parse(stateRaw);
|
|
181
|
+
lastRunAt = stateData.lastRunAt ?? null;
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
184
|
+
const memFiles = await listMemoryFiles(memoryDir);
|
|
185
|
+
itemsProcessed = memFiles.length;
|
|
186
|
+
notes = `dry-run: ${itemsProcessed} memories would enter REM consolidation pass${lastRunAt ? ` (last run: ${lastRunAt})` : " (never run)"}`;
|
|
187
|
+
} catch (err) {
|
|
188
|
+
throw new Error(`REM scan failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
if (governanceRunner) {
|
|
193
|
+
try {
|
|
194
|
+
const result = await governanceRunner({ memoryDir, dryRun });
|
|
195
|
+
itemsProcessed = result.scannedMemories;
|
|
196
|
+
notes = result.notes ?? (dryRun ? `dry-run: ${result.appliedActionCount} actions proposed` : `${result.appliedActionCount} actions applied`);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
throw new Error(`deep-sleep governance run failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
const memFiles = await listMemoryFiles(memoryDir);
|
|
202
|
+
itemsProcessed = memFiles.length;
|
|
203
|
+
notes = dryRun ? `dry-run: ${itemsProcessed} memories eligible for deep-sleep governance` : `assessed ${itemsProcessed} memories for deep-sleep governance`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
207
|
+
const durationMs = Math.max(0, Date.parse(completedAt) - Date.parse(startedAt));
|
|
208
|
+
let ledgerEntry;
|
|
209
|
+
try {
|
|
210
|
+
ledgerEntry = await recordDreamsPhaseRun({
|
|
211
|
+
memoryDir,
|
|
212
|
+
startedAt,
|
|
213
|
+
completedAt,
|
|
214
|
+
phase,
|
|
215
|
+
itemsProcessed,
|
|
216
|
+
dryRun,
|
|
217
|
+
trigger: "manual",
|
|
218
|
+
notes
|
|
219
|
+
});
|
|
220
|
+
} catch {
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
phase,
|
|
224
|
+
dryRun,
|
|
225
|
+
durationMs: ledgerEntry?.durationMs ?? durationMs,
|
|
226
|
+
itemsProcessed,
|
|
227
|
+
notes,
|
|
228
|
+
ledgerEntry
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function summarizeGovernanceResultForDreams(govResult, dryRun) {
|
|
232
|
+
const proposedCount = govResult.proposedActions.length;
|
|
233
|
+
const appliedCount = govResult.appliedActions.length;
|
|
234
|
+
const scannedCount = typeof govResult.summary?.scannedMemories === "number" && Number.isFinite(govResult.summary.scannedMemories) ? Math.max(0, Math.floor(govResult.summary.scannedMemories)) : govResult.reviewQueue.length;
|
|
235
|
+
return {
|
|
236
|
+
scannedMemories: scannedCount,
|
|
237
|
+
appliedActionCount: appliedCount,
|
|
238
|
+
notes: dryRun ? `shadow mode: ${proposedCount} actions proposed` : `applied ${appliedCount} actions`
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
async function listMemoryFiles(memoryDir) {
|
|
242
|
+
const out = [];
|
|
243
|
+
try {
|
|
244
|
+
const root = await lstat(memoryDir);
|
|
245
|
+
if (root.isSymbolicLink()) {
|
|
246
|
+
throw new Error(`memoryDir must not be a symlink: ${memoryDir}`);
|
|
247
|
+
}
|
|
248
|
+
if (!root.isDirectory()) return out;
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (err instanceof Error && /must not be a symlink/.test(err.message)) {
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
async function walk(dir) {
|
|
256
|
+
let entries;
|
|
257
|
+
try {
|
|
258
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
259
|
+
} catch {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
for (const entry of entries) {
|
|
263
|
+
if (entry.isSymbolicLink()) continue;
|
|
264
|
+
const full = path.join(dir, entry.name);
|
|
265
|
+
if (entry.isDirectory()) {
|
|
266
|
+
if (entry.name === "state" || entry.name === "archive" || entry.name === "namespaces" || entry.name === ".git") continue;
|
|
267
|
+
await walk(full);
|
|
268
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
269
|
+
out.push(full);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
await walk(memoryDir);
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
export {
|
|
277
|
+
appendDreamsLedgerEntry,
|
|
278
|
+
dreamsLedgerPath,
|
|
279
|
+
getDreamsStatus,
|
|
280
|
+
normalizeDreamsStatusWindowHours,
|
|
281
|
+
readDreamsLedgerEntries,
|
|
282
|
+
recordDreamsPhaseRun,
|
|
283
|
+
runDreamsPhase,
|
|
284
|
+
summarizeGovernanceResultForDreams
|
|
285
|
+
};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CompoundingEngine,
|
|
3
3
|
defaultTierMigrationCycleBudget
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-L4PRBB2A.js";
|
|
5
|
+
import "./chunk-XMSDA5WA.js";
|
|
6
|
+
import "./chunk-TNH24SF6.js";
|
|
6
7
|
import "./chunk-6OJAU466.js";
|
|
8
|
+
import "./chunk-3I7RHWYT.js";
|
|
7
9
|
import "./chunk-UFU5GGGA.js";
|
|
10
|
+
import "./chunk-YGGGUTG3.js";
|
|
8
11
|
import "./chunk-MLKGABMK.js";
|
|
9
12
|
export {
|
|
10
13
|
CompoundingEngine,
|