@xopcai/xopc 0.0.24 → 0.0.26
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/extensions/feishu/xopc.extension.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/agents-Clv9i1Kb.js +216 -0
- package/dist/gateway/static/root/assets/agents-Clv9i1Kb.js.map +1 -0
- package/dist/gateway/static/root/assets/{apps-page-tZz69XM3.js → apps-page-DqclV-PP.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-tZz69XM3.js.map → apps-page-DqclV-PP.js.map} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-BAvk9-aK.js → channels-settings-CLyTYjrz.js} +3 -3
- package/dist/gateway/static/root/assets/{channels-settings-BAvk9-aK.js.map → channels-settings-CLyTYjrz.js.map} +1 -1
- package/dist/gateway/static/root/assets/cron-page-CU8lutMt.js +2 -0
- package/dist/gateway/static/root/assets/{cron-page-CANqvhK7.js.map → cron-page-CU8lutMt.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-DyOO6TdN.js → cron-utils-_UjiWax6.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-DyOO6TdN.js.map → cron-utils-_UjiWax6.js.map} +1 -1
- package/dist/gateway/static/root/assets/dist-Xqb4IGWC.js +2 -0
- package/dist/gateway/static/root/assets/{dist-Brod9LF3.js.map → dist-Xqb4IGWC.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CDD7ozsC.js → extension-debug-page-CtTUkAmw.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-CDD7ozsC.js.map → extension-debug-page-CtTUkAmw.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-UUFMjoWf.js → extension-page-C-aQU8qR.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-UUFMjoWf.js.map → extension-page-C-aQU8qR.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CP9JNc4m.js → extension-settings-page-b0y9aY-q.js} +2 -2
- package/dist/gateway/static/root/assets/extension-settings-page-b0y9aY-q.js.map +1 -0
- package/dist/gateway/static/root/assets/index-DhSFfSNN.css +1 -0
- package/dist/gateway/static/root/assets/index-Gr2HWo-G.js +4734 -0
- package/dist/gateway/static/root/assets/index-Gr2HWo-G.js.map +1 -0
- package/dist/gateway/static/root/assets/logs-page-DRI33XK4.js +2 -0
- package/dist/gateway/static/root/assets/{logs-page-Cr0eCGb4.js.map → logs-page-DRI33XK4.js.map} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-Cryg-36Z.js +2 -0
- package/dist/gateway/static/root/assets/{sessions-page-DwLHN5GJ.js.map → sessions-page-Cryg-36Z.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-DFNKT9yg.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-DFNKT9yg.js.map +1 -0
- package/dist/gateway/static/root/assets/skills-page-D4gfh0Ih.js +3 -0
- package/dist/gateway/static/root/assets/{skills-page-DgBYvH6B.js.map → skills-page-D4gfh0Ih.js.map} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/memory/dreaming/config.d.ts +48 -0
- package/dist/src/agent/memory/dreaming/config.js +86 -0
- package/dist/src/agent/memory/dreaming/config.js.map +1 -0
- package/dist/src/agent/memory/dreaming/constants.d.ts +29 -0
- package/dist/src/agent/memory/dreaming/constants.js +38 -0
- package/dist/src/agent/memory/dreaming/constants.js.map +1 -0
- package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +21 -0
- package/dist/src/agent/memory/dreaming/deep-promotion.js +271 -0
- package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -0
- package/dist/src/agent/memory/dreaming/events.d.ts +36 -0
- package/dist/src/agent/memory/dreaming/events.js +44 -0
- package/dist/src/agent/memory/dreaming/events.js.map +1 -0
- package/dist/src/agent/memory/dreaming/last-run.d.ts +80 -0
- package/dist/src/agent/memory/dreaming/last-run.js +98 -0
- package/dist/src/agent/memory/dreaming/last-run.js.map +1 -0
- package/dist/src/agent/memory/dreaming/light-sweep.d.ts +19 -0
- package/dist/src/agent/memory/dreaming/light-sweep.js +328 -0
- package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -0
- package/dist/src/agent/memory/dreaming/preview.d.ts +28 -0
- package/dist/src/agent/memory/dreaming/preview.js +97 -0
- package/dist/src/agent/memory/dreaming/preview.js.map +1 -0
- package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +21 -0
- package/dist/src/agent/memory/dreaming/rem-patterns.js +286 -0
- package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -0
- package/dist/src/agent/memory/dreaming/short-term-store.d.ts +65 -0
- package/dist/src/agent/memory/dreaming/short-term-store.js +197 -0
- package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -0
- package/dist/src/agent/memory/dreaming/utils.d.ts +42 -0
- package/dist/src/agent/memory/dreaming/utils.js +141 -0
- package/dist/src/agent/memory/dreaming/utils.js.map +1 -0
- package/dist/src/agent/orchestration/agent-orchestrator.js +59 -0
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/service.d.ts +6 -0
- package/dist/src/agent/service.js +78 -0
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.d.ts +7 -0
- package/dist/src/agent/tools/dreaming-tool.js +102 -0
- package/dist/src/agent/tools/dreaming-tool.js.map +1 -0
- package/dist/src/agent/tools/factory.js +5 -0
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/memory-tool.js +9 -2
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/config/schema.d.ts +93 -0
- package/dist/src/config/schema.js +42 -1
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +31 -0
- package/dist/src/gateway/hono/routes/config.js +48 -0
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.d.ts +3 -0
- package/dist/src/gateway/hono/routes/dreaming.js +288 -0
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -0
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +26 -1
- package/dist/src/gateway/hono/routes/models.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +1 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/service.js +7 -0
- package/dist/src/gateway/service.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-CiZMJZRp.js +0 -216
- package/dist/gateway/static/root/assets/agents-CiZMJZRp.js.map +0 -1
- package/dist/gateway/static/root/assets/cron-page-CANqvhK7.js +0 -2
- package/dist/gateway/static/root/assets/dist-Brod9LF3.js +0 -2
- package/dist/gateway/static/root/assets/extension-settings-page-CP9JNc4m.js.map +0 -1
- package/dist/gateway/static/root/assets/index-BZvlG48D.js +0 -150
- package/dist/gateway/static/root/assets/index-BZvlG48D.js.map +0 -1
- package/dist/gateway/static/root/assets/index-DxkgyT8R.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-Cr0eCGb4.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-DwLHN5GJ.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-B3O3R0E4.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-B3O3R0E4.js.map +0 -1
- package/dist/gateway/static/root/assets/skills-page-DgBYvH6B.js +0 -3
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { DreamingDeepConfig, DreamingLightConfig, DreamingRemConfig } from './config.js';
|
|
2
|
+
export declare const DREAMING_LAST_RUN_FORMAT_VERSION: 2;
|
|
3
|
+
export type { DreamingDeepConfig } from './config.js';
|
|
4
|
+
export type DreamingDeepPhaseSkipped = {
|
|
5
|
+
alreadyPromotedKey: number;
|
|
6
|
+
rehydrateFailed: number;
|
|
7
|
+
contaminated: number;
|
|
8
|
+
hashDuplicate: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* On-disk / API shape for `memory/.dreams/last-run.json` (deep promotion sweep).
|
|
12
|
+
*/
|
|
13
|
+
export type DreamingDeepLastRun = {
|
|
14
|
+
version: typeof DREAMING_LAST_RUN_FORMAT_VERSION;
|
|
15
|
+
phase: 'deep';
|
|
16
|
+
runId: string;
|
|
17
|
+
startedAt: string;
|
|
18
|
+
finishedAt: string;
|
|
19
|
+
durationMs: number;
|
|
20
|
+
ok: boolean;
|
|
21
|
+
reason: string;
|
|
22
|
+
config: DreamingDeepConfig;
|
|
23
|
+
memoryPath: string;
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
deep: {
|
|
26
|
+
candidatesRanked: number;
|
|
27
|
+
applied: number;
|
|
28
|
+
skipped: DreamingDeepPhaseSkipped;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* On-disk shape for light sweep last-run.
|
|
33
|
+
*/
|
|
34
|
+
export type DreamingLightLastRun = {
|
|
35
|
+
version: typeof DREAMING_LAST_RUN_FORMAT_VERSION;
|
|
36
|
+
phase: 'light';
|
|
37
|
+
runId: string;
|
|
38
|
+
startedAt: string;
|
|
39
|
+
finishedAt: string;
|
|
40
|
+
durationMs: number;
|
|
41
|
+
ok: boolean;
|
|
42
|
+
reason: string;
|
|
43
|
+
config: DreamingLightConfig;
|
|
44
|
+
light: {
|
|
45
|
+
scannedEntries: number;
|
|
46
|
+
newSignals: number;
|
|
47
|
+
deduped: number;
|
|
48
|
+
};
|
|
49
|
+
errorMessage?: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* On-disk shape for REM pattern last-run.
|
|
53
|
+
*/
|
|
54
|
+
export type DreamingRemLastRun = {
|
|
55
|
+
version: typeof DREAMING_LAST_RUN_FORMAT_VERSION;
|
|
56
|
+
phase: 'rem';
|
|
57
|
+
runId: string;
|
|
58
|
+
startedAt: string;
|
|
59
|
+
finishedAt: string;
|
|
60
|
+
durationMs: number;
|
|
61
|
+
ok: boolean;
|
|
62
|
+
reason: string;
|
|
63
|
+
config: DreamingRemConfig;
|
|
64
|
+
rem: {
|
|
65
|
+
patternsDiscovered: number;
|
|
66
|
+
entriesAnalyzed: number;
|
|
67
|
+
};
|
|
68
|
+
errorMessage?: string;
|
|
69
|
+
};
|
|
70
|
+
/** Union of all phase last-run shapes. */
|
|
71
|
+
export type DreamingLastRun = DreamingDeepLastRun | DreamingLightLastRun | DreamingRemLastRun;
|
|
72
|
+
/**
|
|
73
|
+
* Parse `last-run.json`. Only the current on-disk format (`version: 2`, `phase: 'deep'`) is accepted.
|
|
74
|
+
*/
|
|
75
|
+
export declare function parseDreamingLastRunFile(raw: unknown): DreamingDeepLastRun | null;
|
|
76
|
+
export declare function emptyDeepPhaseSkipped(): DreamingDeepPhaseSkipped;
|
|
77
|
+
export declare function writeDreamingDeepLastRun(params: {
|
|
78
|
+
workspaceDir: string;
|
|
79
|
+
lastRun: DreamingDeepLastRun;
|
|
80
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { DREAMING_LAST_RUN_RELATIVE } from "./constants.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
//#region src/agent/memory/dreaming/last-run.ts
|
|
5
|
+
const DREAMING_LAST_RUN_FORMAT_VERSION = 2;
|
|
6
|
+
function isRecord(v) {
|
|
7
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
8
|
+
}
|
|
9
|
+
function asNonNegInt(v) {
|
|
10
|
+
if (typeof v === "number" && Number.isFinite(v)) return Math.max(0, Math.floor(v));
|
|
11
|
+
if (typeof v === "string" && v.trim() && Number.isFinite(Number(v))) return Math.max(0, Math.floor(Number(v)));
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
function asDreamingDeepConfig(v) {
|
|
15
|
+
if (!isRecord(v)) return null;
|
|
16
|
+
return {
|
|
17
|
+
enabled: v.enabled === true,
|
|
18
|
+
cron: typeof v.cron === "string" ? v.cron : "0 3 * * *",
|
|
19
|
+
minScore: typeof v.minScore === "number" && Number.isFinite(v.minScore) ? v.minScore : 0,
|
|
20
|
+
minRecallCount: asNonNegInt(v.minRecallCount) || 1,
|
|
21
|
+
minUniqueQueries: asNonNegInt(v.minUniqueQueries) || 3,
|
|
22
|
+
limit: asNonNegInt(v.limit),
|
|
23
|
+
recencyHalfLifeDays: asNonNegInt(v.recencyHalfLifeDays) || 14,
|
|
24
|
+
maxAgeDays: asNonNegInt(v.maxAgeDays) || 30
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const EMPTY_SKIPPED = {
|
|
28
|
+
alreadyPromotedKey: 0,
|
|
29
|
+
rehydrateFailed: 0,
|
|
30
|
+
contaminated: 0,
|
|
31
|
+
hashDuplicate: 0
|
|
32
|
+
};
|
|
33
|
+
function parseSkippedStrict(raw) {
|
|
34
|
+
if (!isRecord(raw)) return null;
|
|
35
|
+
if (typeof raw.alreadyPromotedKey !== "number" || !Number.isFinite(raw.alreadyPromotedKey) || typeof raw.rehydrateFailed !== "number" || !Number.isFinite(raw.rehydrateFailed) || typeof raw.contaminated !== "number" || !Number.isFinite(raw.contaminated) || typeof raw.hashDuplicate !== "number" || !Number.isFinite(raw.hashDuplicate)) return null;
|
|
36
|
+
return {
|
|
37
|
+
alreadyPromotedKey: Math.max(0, Math.floor(raw.alreadyPromotedKey)),
|
|
38
|
+
rehydrateFailed: Math.max(0, Math.floor(raw.rehydrateFailed)),
|
|
39
|
+
contaminated: Math.max(0, Math.floor(raw.contaminated)),
|
|
40
|
+
hashDuplicate: Math.max(0, Math.floor(raw.hashDuplicate))
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse `last-run.json`. Only the current on-disk format (`version: 2`, `phase: 'deep'`) is accepted.
|
|
45
|
+
*/
|
|
46
|
+
function parseDreamingLastRunFile(raw) {
|
|
47
|
+
if (!isRecord(raw)) return null;
|
|
48
|
+
if (raw.version !== 2 || raw.phase !== "deep") return null;
|
|
49
|
+
if (typeof raw.runId !== "string" || !raw.runId.trim()) return null;
|
|
50
|
+
if (typeof raw.startedAt !== "string" || typeof raw.finishedAt !== "string") return null;
|
|
51
|
+
if (!raw.startedAt.trim() || !raw.finishedAt.trim()) return null;
|
|
52
|
+
if (typeof raw.durationMs !== "number" || !Number.isFinite(raw.durationMs) || raw.durationMs < 0) return null;
|
|
53
|
+
if (raw.ok !== true && raw.ok !== false) return null;
|
|
54
|
+
if (typeof raw.reason !== "string") return null;
|
|
55
|
+
const config = asDreamingDeepConfig(raw.config);
|
|
56
|
+
if (!config) return null;
|
|
57
|
+
if (typeof raw.memoryPath !== "string" || !raw.memoryPath.trim()) return null;
|
|
58
|
+
const deepRaw = raw.deep;
|
|
59
|
+
if (!isRecord(deepRaw)) return null;
|
|
60
|
+
if (typeof deepRaw.candidatesRanked !== "number" || !Number.isFinite(deepRaw.candidatesRanked)) return null;
|
|
61
|
+
if (typeof deepRaw.applied !== "number" || !Number.isFinite(deepRaw.applied)) return null;
|
|
62
|
+
const skipped = parseSkippedStrict(deepRaw.skipped);
|
|
63
|
+
if (!skipped) return null;
|
|
64
|
+
const err = raw.errorMessage;
|
|
65
|
+
const errMsg = typeof err === "string" && err.trim() ? err.trim() : void 0;
|
|
66
|
+
return {
|
|
67
|
+
version: 2,
|
|
68
|
+
phase: "deep",
|
|
69
|
+
runId: raw.runId.trim(),
|
|
70
|
+
startedAt: raw.startedAt,
|
|
71
|
+
finishedAt: raw.finishedAt,
|
|
72
|
+
durationMs: Math.max(0, Math.floor(raw.durationMs)),
|
|
73
|
+
ok: raw.ok === true,
|
|
74
|
+
reason: raw.reason,
|
|
75
|
+
config,
|
|
76
|
+
memoryPath: raw.memoryPath,
|
|
77
|
+
...errMsg ? { errorMessage: errMsg } : {},
|
|
78
|
+
deep: {
|
|
79
|
+
candidatesRanked: Math.max(0, Math.floor(deepRaw.candidatesRanked)),
|
|
80
|
+
applied: Math.max(0, Math.floor(deepRaw.applied)),
|
|
81
|
+
skipped
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function emptyDeepPhaseSkipped() {
|
|
86
|
+
return { ...EMPTY_SKIPPED };
|
|
87
|
+
}
|
|
88
|
+
async function writeDreamingDeepLastRun(params) {
|
|
89
|
+
const fullPath = path.join(params.workspaceDir, DREAMING_LAST_RUN_RELATIVE);
|
|
90
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
91
|
+
const tmp = `${fullPath}.${process.pid}.${Date.now()}.tmp`;
|
|
92
|
+
await fs.writeFile(tmp, `${JSON.stringify(params.lastRun, null, 2)}\n`, "utf-8");
|
|
93
|
+
await fs.rename(tmp, fullPath);
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { DREAMING_LAST_RUN_FORMAT_VERSION, emptyDeepPhaseSkipped, parseDreamingLastRunFile, writeDreamingDeepLastRun };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=last-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"last-run.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/last-run.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { DREAMING_LAST_RUN_RELATIVE } from './constants.js';\nimport type { DreamingDeepConfig, DreamingLightConfig, DreamingRemConfig } from './config.js';\n\nexport const DREAMING_LAST_RUN_FORMAT_VERSION = 2 as const;\n\nexport type { DreamingDeepConfig } from './config.js';\n\nexport type DreamingDeepPhaseSkipped = {\n alreadyPromotedKey: number;\n rehydrateFailed: number;\n contaminated: number;\n hashDuplicate: number;\n};\n\n/**\n * On-disk / API shape for `memory/.dreams/last-run.json` (deep promotion sweep).\n */\nexport type DreamingDeepLastRun = {\n version: typeof DREAMING_LAST_RUN_FORMAT_VERSION;\n phase: 'deep';\n runId: string;\n startedAt: string;\n finishedAt: string;\n durationMs: number;\n ok: boolean;\n reason: string;\n config: DreamingDeepConfig;\n memoryPath: string;\n errorMessage?: string;\n deep: {\n candidatesRanked: number;\n applied: number;\n skipped: DreamingDeepPhaseSkipped;\n };\n};\n\n/**\n * On-disk shape for light sweep last-run.\n */\nexport type DreamingLightLastRun = {\n version: typeof DREAMING_LAST_RUN_FORMAT_VERSION;\n phase: 'light';\n runId: string;\n startedAt: string;\n finishedAt: string;\n durationMs: number;\n ok: boolean;\n reason: string;\n config: DreamingLightConfig;\n light: {\n scannedEntries: number;\n newSignals: number;\n deduped: number;\n };\n errorMessage?: string;\n};\n\n/**\n * On-disk shape for REM pattern last-run.\n */\nexport type DreamingRemLastRun = {\n version: typeof DREAMING_LAST_RUN_FORMAT_VERSION;\n phase: 'rem';\n runId: string;\n startedAt: string;\n finishedAt: string;\n durationMs: number;\n ok: boolean;\n reason: string;\n config: DreamingRemConfig;\n rem: {\n patternsDiscovered: number;\n entriesAnalyzed: number;\n };\n errorMessage?: string;\n};\n\n/** Union of all phase last-run shapes. */\nexport type DreamingLastRun = DreamingDeepLastRun | DreamingLightLastRun | DreamingRemLastRun;\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction asNonNegInt(v: unknown): number {\n if (typeof v === 'number' && Number.isFinite(v)) return Math.max(0, Math.floor(v));\n if (typeof v === 'string' && v.trim() && Number.isFinite(Number(v))) {\n return Math.max(0, Math.floor(Number(v)));\n }\n return 0;\n}\n\nfunction asDreamingDeepConfig(v: unknown): DreamingDeepConfig | null {\n if (!isRecord(v)) return null;\n return {\n enabled: v.enabled === true,\n cron: typeof v.cron === 'string' ? v.cron : '0 3 * * *',\n minScore: typeof v.minScore === 'number' && Number.isFinite(v.minScore) ? v.minScore : 0,\n minRecallCount: asNonNegInt(v.minRecallCount) || 1,\n minUniqueQueries: asNonNegInt(v.minUniqueQueries) || 3,\n limit: asNonNegInt(v.limit),\n recencyHalfLifeDays: asNonNegInt(v.recencyHalfLifeDays) || 14,\n maxAgeDays: asNonNegInt(v.maxAgeDays) || 30,\n };\n}\n\nconst EMPTY_SKIPPED: DreamingDeepPhaseSkipped = {\n alreadyPromotedKey: 0,\n rehydrateFailed: 0,\n contaminated: 0,\n hashDuplicate: 0,\n};\n\nfunction parseSkippedStrict(raw: unknown): DreamingDeepPhaseSkipped | null {\n if (!isRecord(raw)) return null;\n if (\n typeof raw.alreadyPromotedKey !== 'number' ||\n !Number.isFinite(raw.alreadyPromotedKey) ||\n typeof raw.rehydrateFailed !== 'number' ||\n !Number.isFinite(raw.rehydrateFailed) ||\n typeof raw.contaminated !== 'number' ||\n !Number.isFinite(raw.contaminated) ||\n typeof raw.hashDuplicate !== 'number' ||\n !Number.isFinite(raw.hashDuplicate)\n ) {\n return null;\n }\n return {\n alreadyPromotedKey: Math.max(0, Math.floor(raw.alreadyPromotedKey)),\n rehydrateFailed: Math.max(0, Math.floor(raw.rehydrateFailed)),\n contaminated: Math.max(0, Math.floor(raw.contaminated)),\n hashDuplicate: Math.max(0, Math.floor(raw.hashDuplicate)),\n };\n}\n\n/**\n * Parse `last-run.json`. Only the current on-disk format (`version: 2`, `phase: 'deep'`) is accepted.\n */\nexport function parseDreamingLastRunFile(raw: unknown): DreamingDeepLastRun | null {\n if (!isRecord(raw)) return null;\n if (raw.version !== DREAMING_LAST_RUN_FORMAT_VERSION || raw.phase !== 'deep') return null;\n\n if (typeof raw.runId !== 'string' || !raw.runId.trim()) return null;\n if (typeof raw.startedAt !== 'string' || typeof raw.finishedAt !== 'string') return null;\n if (!raw.startedAt.trim() || !raw.finishedAt.trim()) return null;\n\n if (typeof raw.durationMs !== 'number' || !Number.isFinite(raw.durationMs) || raw.durationMs < 0) {\n return null;\n }\n if (raw.ok !== true && raw.ok !== false) return null;\n if (typeof raw.reason !== 'string') return null;\n\n const config = asDreamingDeepConfig(raw.config);\n if (!config) return null;\n if (typeof raw.memoryPath !== 'string' || !raw.memoryPath.trim()) return null;\n\n const deepRaw = raw.deep;\n if (!isRecord(deepRaw)) return null;\n if (typeof deepRaw.candidatesRanked !== 'number' || !Number.isFinite(deepRaw.candidatesRanked)) {\n return null;\n }\n if (typeof deepRaw.applied !== 'number' || !Number.isFinite(deepRaw.applied)) return null;\n const skipped = parseSkippedStrict(deepRaw.skipped);\n if (!skipped) return null;\n\n const err = raw.errorMessage;\n const errMsg = typeof err === 'string' && err.trim() ? err.trim() : undefined;\n\n return {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'deep',\n runId: raw.runId.trim(),\n startedAt: raw.startedAt,\n finishedAt: raw.finishedAt,\n durationMs: Math.max(0, Math.floor(raw.durationMs)),\n ok: raw.ok === true,\n reason: raw.reason,\n config,\n memoryPath: raw.memoryPath,\n ...(errMsg ? { errorMessage: errMsg } : {}),\n deep: {\n candidatesRanked: Math.max(0, Math.floor(deepRaw.candidatesRanked)),\n applied: Math.max(0, Math.floor(deepRaw.applied)),\n skipped,\n },\n };\n}\n\nexport function emptyDeepPhaseSkipped(): DreamingDeepPhaseSkipped {\n return { ...EMPTY_SKIPPED };\n}\n\nexport async function writeDreamingDeepLastRun(params: {\n workspaceDir: string;\n lastRun: DreamingDeepLastRun;\n}): Promise<void> {\n const fullPath = path.join(params.workspaceDir, DREAMING_LAST_RUN_RELATIVE);\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n const tmp = `${fullPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(params.lastRun, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, fullPath);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DreamingLightConfig } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scan recent daily memory files (memory/YYYY-MM-DD.md) and collect signal
|
|
4
|
+
* entries into the short-term store. Deduplicates near-identical snippets
|
|
5
|
+
* using trigram similarity.
|
|
6
|
+
*
|
|
7
|
+
* This is the "light sleep" phase: fast, frequent, cheap.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runLightSweep(params: {
|
|
10
|
+
workspaceDir: string;
|
|
11
|
+
config?: Partial<DreamingLightConfig>;
|
|
12
|
+
now?: Date;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
ok: boolean;
|
|
15
|
+
reason: string;
|
|
16
|
+
scannedEntries: number;
|
|
17
|
+
newSignals: number;
|
|
18
|
+
deduped: number;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { createLogger } from "../../../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../../../utils/logger.js";
|
|
3
|
+
import { DREAMING_DIR_RELATIVE } from "./constants.js";
|
|
4
|
+
import { buildEntryKey, isoDay, normalizeMemoryPath, normalizeSnippetForHash, snippetHash } from "./utils.js";
|
|
5
|
+
import { bumpEntryPhaseSignal, loadDreamingStore, saveDreamingStore } from "./short-term-store.js";
|
|
6
|
+
import "./last-run.js";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import fs from "node:fs/promises";
|
|
9
|
+
//#region src/agent/memory/dreaming/light-sweep.ts
|
|
10
|
+
init_logger();
|
|
11
|
+
const log = createLogger("Dreaming:Light");
|
|
12
|
+
function isDailyMemoryFile(filename) {
|
|
13
|
+
return /^\d{4}-\d{2}-\d{2}\.md$/i.test(filename);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Cosine-ish similarity via character n-gram overlap.
|
|
17
|
+
* Fast and deterministic — no embeddings required.
|
|
18
|
+
*/
|
|
19
|
+
function trigramSimilarity(textA, textB) {
|
|
20
|
+
const normalizedA = normalizeSnippetForHash(textA);
|
|
21
|
+
const normalizedB = normalizeSnippetForHash(textB);
|
|
22
|
+
if (!normalizedA || !normalizedB) return 0;
|
|
23
|
+
if (normalizedA === normalizedB) return 1;
|
|
24
|
+
const gramsA = buildTrigramSet(normalizedA);
|
|
25
|
+
const gramsB = buildTrigramSet(normalizedB);
|
|
26
|
+
if (gramsA.size === 0 || gramsB.size === 0) return 0;
|
|
27
|
+
let intersection = 0;
|
|
28
|
+
for (const gram of gramsA) if (gramsB.has(gram)) intersection += 1;
|
|
29
|
+
return intersection / Math.sqrt(gramsA.size * gramsB.size);
|
|
30
|
+
}
|
|
31
|
+
function buildTrigramSet(text) {
|
|
32
|
+
const grams = /* @__PURE__ */ new Set();
|
|
33
|
+
for (let i = 0; i <= text.length - 3; i++) grams.add(text.slice(i, i + 3));
|
|
34
|
+
return grams;
|
|
35
|
+
}
|
|
36
|
+
function resolveConfig(overrides) {
|
|
37
|
+
return {
|
|
38
|
+
enabled: overrides?.enabled === true,
|
|
39
|
+
cron: typeof overrides?.cron === "string" ? overrides.cron : "0 */6 * * *",
|
|
40
|
+
lookbackDays: Math.max(1, Math.floor(Number(overrides?.lookbackDays) || 2)),
|
|
41
|
+
limit: Math.max(0, Math.floor(Number(overrides?.limit) || 100)),
|
|
42
|
+
dedupeSimilarity: Math.max(0, Math.min(1, Number(overrides?.dedupeSimilarity) || .9))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Scan recent daily memory files (memory/YYYY-MM-DD.md) and collect signal
|
|
47
|
+
* entries into the short-term store. Deduplicates near-identical snippets
|
|
48
|
+
* using trigram similarity.
|
|
49
|
+
*
|
|
50
|
+
* This is the "light sleep" phase: fast, frequent, cheap.
|
|
51
|
+
*/
|
|
52
|
+
async function runLightSweep(params) {
|
|
53
|
+
const cfg = resolveConfig(params.config);
|
|
54
|
+
const now = params.now ?? /* @__PURE__ */ new Date();
|
|
55
|
+
const startedAt = now.toISOString();
|
|
56
|
+
const runId = `light:${startedAt}:${process.pid}`;
|
|
57
|
+
const startMs = Date.now();
|
|
58
|
+
if (!cfg.enabled) {
|
|
59
|
+
await writeLastRun(params.workspaceDir, {
|
|
60
|
+
runId,
|
|
61
|
+
startedAt,
|
|
62
|
+
cfg,
|
|
63
|
+
ok: true,
|
|
64
|
+
reason: "light sweep disabled",
|
|
65
|
+
startMs,
|
|
66
|
+
light: {
|
|
67
|
+
scannedEntries: 0,
|
|
68
|
+
newSignals: 0,
|
|
69
|
+
deduped: 0
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
reason: "light sweep disabled",
|
|
75
|
+
scannedEntries: 0,
|
|
76
|
+
newSignals: 0,
|
|
77
|
+
deduped: 0
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const recentFiles = await listRecentDailyFiles(path.join(params.workspaceDir, "memory"), cfg.lookbackDays, now);
|
|
82
|
+
if (recentFiles.length === 0) {
|
|
83
|
+
await writeLastRun(params.workspaceDir, {
|
|
84
|
+
runId,
|
|
85
|
+
startedAt,
|
|
86
|
+
cfg,
|
|
87
|
+
ok: true,
|
|
88
|
+
reason: "no recent daily files",
|
|
89
|
+
startMs,
|
|
90
|
+
light: {
|
|
91
|
+
scannedEntries: 0,
|
|
92
|
+
newSignals: 0,
|
|
93
|
+
deduped: 0
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
ok: true,
|
|
98
|
+
reason: "no recent daily files",
|
|
99
|
+
scannedEntries: 0,
|
|
100
|
+
newSignals: 0,
|
|
101
|
+
deduped: 0
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const allChunks = [];
|
|
105
|
+
for (const filePath of recentFiles) {
|
|
106
|
+
const chunks = await parseFileChunks(filePath, params.workspaceDir);
|
|
107
|
+
allChunks.push(...chunks);
|
|
108
|
+
}
|
|
109
|
+
if (allChunks.length === 0) {
|
|
110
|
+
await writeLastRun(params.workspaceDir, {
|
|
111
|
+
runId,
|
|
112
|
+
startedAt,
|
|
113
|
+
cfg,
|
|
114
|
+
ok: true,
|
|
115
|
+
reason: "no chunks found in daily files",
|
|
116
|
+
startMs,
|
|
117
|
+
light: {
|
|
118
|
+
scannedEntries: 0,
|
|
119
|
+
newSignals: 0,
|
|
120
|
+
deduped: 0
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
ok: true,
|
|
125
|
+
reason: "no chunks found in daily files",
|
|
126
|
+
scannedEntries: 0,
|
|
127
|
+
newSignals: 0,
|
|
128
|
+
deduped: 0
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const { unique, deduped } = deduplicateChunks(allChunks, cfg.dedupeSimilarity);
|
|
132
|
+
const capped = unique.slice(0, cfg.limit);
|
|
133
|
+
const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });
|
|
134
|
+
let newSignals = 0;
|
|
135
|
+
const dayBucket = isoDay(now);
|
|
136
|
+
const nowIso = now.toISOString();
|
|
137
|
+
for (const chunk of capped) {
|
|
138
|
+
const key = buildEntryKey({
|
|
139
|
+
path: chunk.path,
|
|
140
|
+
startLine: chunk.startLine,
|
|
141
|
+
endLine: chunk.endLine
|
|
142
|
+
});
|
|
143
|
+
const existing = store.entries[key];
|
|
144
|
+
if (existing) {
|
|
145
|
+
bumpEntryPhaseSignal(existing, "lightHits");
|
|
146
|
+
bumpEntryPhaseSignal(existing, "dailyCount");
|
|
147
|
+
existing.snippet = chunk.text.slice(0, 360);
|
|
148
|
+
existing.lastRecalledAt = nowIso;
|
|
149
|
+
} else {
|
|
150
|
+
store.entries[key] = {
|
|
151
|
+
key,
|
|
152
|
+
path: chunk.path,
|
|
153
|
+
startLine: chunk.startLine,
|
|
154
|
+
endLine: chunk.endLine,
|
|
155
|
+
snippet: chunk.text.slice(0, 360),
|
|
156
|
+
recallCount: 0,
|
|
157
|
+
dailyCount: 1,
|
|
158
|
+
groundedCount: 0,
|
|
159
|
+
lightHits: 1,
|
|
160
|
+
remHits: 0,
|
|
161
|
+
phaseHitCount: 1,
|
|
162
|
+
totalSignalCount: 1,
|
|
163
|
+
totalScore: 0,
|
|
164
|
+
maxScore: 0,
|
|
165
|
+
queryHashes: [],
|
|
166
|
+
recallDays: [dayBucket],
|
|
167
|
+
firstRecalledAt: nowIso,
|
|
168
|
+
lastRecalledAt: nowIso
|
|
169
|
+
};
|
|
170
|
+
newSignals += 1;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
store.updatedAt = nowIso;
|
|
174
|
+
await saveDreamingStore({
|
|
175
|
+
workspaceDir: params.workspaceDir,
|
|
176
|
+
store
|
|
177
|
+
});
|
|
178
|
+
log.info({
|
|
179
|
+
workspaceDir: params.workspaceDir,
|
|
180
|
+
scanned: allChunks.length,
|
|
181
|
+
newSignals,
|
|
182
|
+
deduped
|
|
183
|
+
}, "Light sweep complete");
|
|
184
|
+
await writeLastRun(params.workspaceDir, {
|
|
185
|
+
runId,
|
|
186
|
+
startedAt,
|
|
187
|
+
cfg,
|
|
188
|
+
ok: true,
|
|
189
|
+
reason: "light sweep complete",
|
|
190
|
+
startMs,
|
|
191
|
+
light: {
|
|
192
|
+
scannedEntries: allChunks.length,
|
|
193
|
+
newSignals,
|
|
194
|
+
deduped
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
ok: true,
|
|
199
|
+
reason: "light sweep complete",
|
|
200
|
+
scannedEntries: allChunks.length,
|
|
201
|
+
newSignals,
|
|
202
|
+
deduped
|
|
203
|
+
};
|
|
204
|
+
} catch (err) {
|
|
205
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
206
|
+
log.error({
|
|
207
|
+
err,
|
|
208
|
+
errorMessage,
|
|
209
|
+
workspaceDir: params.workspaceDir
|
|
210
|
+
}, `Light sweep failed: ${errorMessage}`);
|
|
211
|
+
await writeLastRun(params.workspaceDir, {
|
|
212
|
+
runId,
|
|
213
|
+
startedAt,
|
|
214
|
+
cfg,
|
|
215
|
+
ok: false,
|
|
216
|
+
reason: `light sweep error: ${errorMessage}`,
|
|
217
|
+
startMs,
|
|
218
|
+
light: {
|
|
219
|
+
scannedEntries: 0,
|
|
220
|
+
newSignals: 0,
|
|
221
|
+
deduped: 0
|
|
222
|
+
},
|
|
223
|
+
errorMessage
|
|
224
|
+
}).catch(() => void 0);
|
|
225
|
+
return {
|
|
226
|
+
ok: false,
|
|
227
|
+
reason: errorMessage,
|
|
228
|
+
scannedEntries: 0,
|
|
229
|
+
newSignals: 0,
|
|
230
|
+
deduped: 0
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async function listRecentDailyFiles(memoryDir, lookbackDays, now) {
|
|
235
|
+
let entries;
|
|
236
|
+
try {
|
|
237
|
+
entries = await fs.readdir(memoryDir);
|
|
238
|
+
} catch (err) {
|
|
239
|
+
if (err?.code === "ENOENT") return [];
|
|
240
|
+
throw err;
|
|
241
|
+
}
|
|
242
|
+
const cutoff = new Date(now);
|
|
243
|
+
cutoff.setDate(cutoff.getDate() - lookbackDays);
|
|
244
|
+
const cutoffDay = isoDay(cutoff);
|
|
245
|
+
return entries.filter((name) => isDailyMemoryFile(name)).filter((name) => {
|
|
246
|
+
return name.replace(/\.md$/i, "") >= cutoffDay;
|
|
247
|
+
}).sort().map((name) => path.join(memoryDir, name));
|
|
248
|
+
}
|
|
249
|
+
async function parseFileChunks(filePath, workspaceDir) {
|
|
250
|
+
let raw;
|
|
251
|
+
try {
|
|
252
|
+
raw = await fs.readFile(filePath, "utf-8");
|
|
253
|
+
} catch {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
const relativePath = normalizeMemoryPath(path.relative(workspaceDir, filePath));
|
|
257
|
+
const lines = raw.split(/\r?\n/);
|
|
258
|
+
const chunks = [];
|
|
259
|
+
let chunkStartLine = 1;
|
|
260
|
+
let currentLines = [];
|
|
261
|
+
for (let i = 0; i < lines.length; i++) {
|
|
262
|
+
const trimmed = lines[i].trim();
|
|
263
|
+
if (trimmed.length === 0) {
|
|
264
|
+
if (currentLines.length > 0) {
|
|
265
|
+
const text = currentLines.join(" ").replace(/\s+/g, " ").trim();
|
|
266
|
+
if (text.length >= 20) chunks.push({
|
|
267
|
+
path: relativePath,
|
|
268
|
+
startLine: chunkStartLine,
|
|
269
|
+
endLine: chunkStartLine + currentLines.length - 1,
|
|
270
|
+
text: text.slice(0, 360),
|
|
271
|
+
hash: snippetHash(text)
|
|
272
|
+
});
|
|
273
|
+
currentLines = [];
|
|
274
|
+
}
|
|
275
|
+
chunkStartLine = i + 2;
|
|
276
|
+
} else {
|
|
277
|
+
if (currentLines.length === 0) chunkStartLine = i + 1;
|
|
278
|
+
currentLines.push(trimmed);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (currentLines.length > 0) {
|
|
282
|
+
const text = currentLines.join(" ").replace(/\s+/g, " ").trim();
|
|
283
|
+
if (text.length >= 20) chunks.push({
|
|
284
|
+
path: relativePath,
|
|
285
|
+
startLine: chunkStartLine,
|
|
286
|
+
endLine: chunkStartLine + currentLines.length - 1,
|
|
287
|
+
text: text.slice(0, 360),
|
|
288
|
+
hash: snippetHash(text)
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
return chunks;
|
|
292
|
+
}
|
|
293
|
+
function deduplicateChunks(chunks, threshold) {
|
|
294
|
+
const unique = [];
|
|
295
|
+
let deduped = 0;
|
|
296
|
+
for (const chunk of chunks) if (unique.some((existing) => existing.hash === chunk.hash || trigramSimilarity(existing.text, chunk.text) >= threshold)) deduped += 1;
|
|
297
|
+
else unique.push(chunk);
|
|
298
|
+
return {
|
|
299
|
+
unique,
|
|
300
|
+
deduped
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
async function writeLastRun(workspaceDir, params) {
|
|
304
|
+
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
305
|
+
const durationMs = Math.max(0, Date.now() - params.startMs);
|
|
306
|
+
const lastRun = {
|
|
307
|
+
version: 2,
|
|
308
|
+
phase: "light",
|
|
309
|
+
runId: params.runId,
|
|
310
|
+
startedAt: params.startedAt,
|
|
311
|
+
finishedAt,
|
|
312
|
+
durationMs,
|
|
313
|
+
ok: params.ok,
|
|
314
|
+
reason: params.reason,
|
|
315
|
+
config: params.cfg,
|
|
316
|
+
light: params.light,
|
|
317
|
+
...params.errorMessage ? { errorMessage: params.errorMessage } : {}
|
|
318
|
+
};
|
|
319
|
+
const lastRunPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE, "last-run-light.json");
|
|
320
|
+
await fs.mkdir(path.dirname(lastRunPath), { recursive: true });
|
|
321
|
+
const tmp = `${lastRunPath}.${process.pid}.${Date.now()}.tmp`;
|
|
322
|
+
await fs.writeFile(tmp, `${JSON.stringify(lastRun, null, 2)}\n`, "utf-8");
|
|
323
|
+
await fs.rename(tmp, lastRunPath);
|
|
324
|
+
}
|
|
325
|
+
//#endregion
|
|
326
|
+
export { runLightSweep };
|
|
327
|
+
|
|
328
|
+
//# sourceMappingURL=light-sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"light-sweep.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/light-sweep.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { DREAMING_DIR_RELATIVE } from './constants.js';\nimport type { DreamingLightConfig } from './config.js';\nimport {\n bumpEntryPhaseSignal,\n loadDreamingStore,\n saveDreamingStore,\n} from './short-term-store.js';\nimport {\n buildEntryKey,\n isoDay,\n normalizeMemoryPath,\n normalizeSnippetForHash,\n snippetHash,\n} from './utils.js';\nimport {\n DREAMING_LAST_RUN_FORMAT_VERSION,\n type DreamingLightLastRun,\n} from './last-run.js';\n\nconst log = createLogger('Dreaming:Light');\n\n// ── Helpers ────────────────────────────────────────────────────────────\n\nfunction isDailyMemoryFile(filename: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}\\.md$/i.test(filename);\n}\n\n/**\n * Cosine-ish similarity via character n-gram overlap.\n * Fast and deterministic — no embeddings required.\n */\nfunction trigramSimilarity(textA: string, textB: string): number {\n const normalizedA = normalizeSnippetForHash(textA);\n const normalizedB = normalizeSnippetForHash(textB);\n if (!normalizedA || !normalizedB) return 0;\n if (normalizedA === normalizedB) return 1;\n\n const gramsA = buildTrigramSet(normalizedA);\n const gramsB = buildTrigramSet(normalizedB);\n if (gramsA.size === 0 || gramsB.size === 0) return 0;\n\n let intersection = 0;\n for (const gram of gramsA) {\n if (gramsB.has(gram)) intersection += 1;\n }\n return intersection / Math.sqrt(gramsA.size * gramsB.size);\n}\n\nfunction buildTrigramSet(text: string): Set<string> {\n const grams = new Set<string>();\n for (let i = 0; i <= text.length - 3; i++) {\n grams.add(text.slice(i, i + 3));\n }\n return grams;\n}\n\n// ── Light sweep config defaults ────────────────────────────────────────\n\nfunction resolveConfig(overrides?: Partial<DreamingLightConfig>): DreamingLightConfig {\n return {\n enabled: overrides?.enabled === true,\n cron: typeof overrides?.cron === 'string' ? overrides.cron : '0 */6 * * *',\n lookbackDays: Math.max(1, Math.floor(Number(overrides?.lookbackDays) || 2)),\n limit: Math.max(0, Math.floor(Number(overrides?.limit) || 100)),\n dedupeSimilarity: Math.max(0, Math.min(1, Number(overrides?.dedupeSimilarity) || 0.9)),\n };\n}\n\n// ── Core light sweep ───────────────────────────────────────────────────\n\ntype LightSweepChunk = {\n path: string;\n startLine: number;\n endLine: number;\n text: string;\n hash: string;\n};\n\n/**\n * Scan recent daily memory files (memory/YYYY-MM-DD.md) and collect signal\n * entries into the short-term store. Deduplicates near-identical snippets\n * using trigram similarity.\n *\n * This is the \"light sleep\" phase: fast, frequent, cheap.\n */\nexport async function runLightSweep(params: {\n workspaceDir: string;\n config?: Partial<DreamingLightConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n scannedEntries: number;\n newSignals: number;\n deduped: number;\n}> {\n const cfg = resolveConfig(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `light:${startedAt}:${process.pid}`;\n const startMs = Date.now();\n\n if (!cfg.enabled) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'light sweep disabled', startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason: 'light sweep disabled', scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n\n try {\n const memoryDir = path.join(params.workspaceDir, 'memory');\n const recentFiles = await listRecentDailyFiles(memoryDir, cfg.lookbackDays, now);\n\n if (recentFiles.length === 0) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'no recent daily files', startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason: 'no recent daily files', scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n\n // Parse chunks from daily files.\n const allChunks: LightSweepChunk[] = [];\n for (const filePath of recentFiles) {\n const chunks = await parseFileChunks(filePath, params.workspaceDir);\n allChunks.push(...chunks);\n }\n\n if (allChunks.length === 0) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'no chunks found in daily files', startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason: 'no chunks found in daily files', scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n\n // Deduplicate chunks by trigram similarity.\n const { unique, deduped } = deduplicateChunks(allChunks, cfg.dedupeSimilarity);\n const capped = unique.slice(0, cfg.limit);\n\n // Merge into the short-term store, bumping lightHits + dailyCount.\n const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });\n let newSignals = 0;\n const dayBucket = isoDay(now);\n const nowIso = now.toISOString();\n\n for (const chunk of capped) {\n const key = buildEntryKey({ path: chunk.path, startLine: chunk.startLine, endLine: chunk.endLine });\n const existing = store.entries[key];\n\n if (existing) {\n bumpEntryPhaseSignal(existing, 'lightHits');\n bumpEntryPhaseSignal(existing, 'dailyCount');\n existing.snippet = chunk.text.slice(0, 360);\n existing.lastRecalledAt = nowIso;\n } else {\n store.entries[key] = {\n key,\n path: chunk.path,\n startLine: chunk.startLine,\n endLine: chunk.endLine,\n snippet: chunk.text.slice(0, 360),\n recallCount: 0,\n dailyCount: 1,\n groundedCount: 0,\n lightHits: 1,\n remHits: 0,\n phaseHitCount: 1,\n totalSignalCount: 1,\n totalScore: 0,\n maxScore: 0,\n queryHashes: [],\n recallDays: [dayBucket],\n firstRecalledAt: nowIso,\n lastRecalledAt: nowIso,\n };\n newSignals += 1;\n }\n }\n\n store.updatedAt = nowIso;\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n\n log.info(\n { workspaceDir: params.workspaceDir, scanned: allChunks.length, newSignals, deduped },\n 'Light sweep complete',\n );\n\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'light sweep complete', startMs,\n light: { scannedEntries: allChunks.length, newSignals, deduped },\n });\n\n return { ok: true, reason: 'light sweep complete', scannedEntries: allChunks.length, newSignals, deduped };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage, workspaceDir: params.workspaceDir }, `Light sweep failed: ${errorMessage}`);\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: false, reason: `light sweep error: ${errorMessage}`, startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 }, errorMessage,\n }).catch(() => undefined);\n return { ok: false, reason: errorMessage, scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n}\n\n// ── File scanning ──────────────────────────────────────────────────────\n\nasync function listRecentDailyFiles(memoryDir: string, lookbackDays: number, now: Date): Promise<string[]> {\n let entries: string[];\n try {\n entries = await fs.readdir(memoryDir);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return [];\n throw err;\n }\n\n const cutoff = new Date(now);\n cutoff.setDate(cutoff.getDate() - lookbackDays);\n const cutoffDay = isoDay(cutoff);\n\n return entries\n .filter((name) => isDailyMemoryFile(name))\n .filter((name) => {\n const day = name.replace(/\\.md$/i, '');\n return day >= cutoffDay;\n })\n .sort()\n .map((name) => path.join(memoryDir, name));\n}\n\nasync function parseFileChunks(filePath: string, workspaceDir: string): Promise<LightSweepChunk[]> {\n let raw: string;\n try {\n raw = await fs.readFile(filePath, 'utf-8');\n } catch {\n return [];\n }\n\n const relativePath = normalizeMemoryPath(path.relative(workspaceDir, filePath));\n const lines = raw.split(/\\r?\\n/);\n const chunks: LightSweepChunk[] = [];\n\n // Split into paragraph-level chunks (separated by blank lines).\n let chunkStartLine = 1;\n let currentLines: string[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (trimmed.length === 0) {\n if (currentLines.length > 0) {\n const text = currentLines.join(' ').replace(/\\s+/g, ' ').trim();\n if (text.length >= 20) {\n chunks.push({\n path: relativePath,\n startLine: chunkStartLine,\n endLine: chunkStartLine + currentLines.length - 1,\n text: text.slice(0, 360),\n hash: snippetHash(text),\n });\n }\n currentLines = [];\n }\n chunkStartLine = i + 2; // next non-blank line (1-indexed)\n } else {\n if (currentLines.length === 0) chunkStartLine = i + 1;\n currentLines.push(trimmed);\n }\n }\n\n // Flush remaining.\n if (currentLines.length > 0) {\n const text = currentLines.join(' ').replace(/\\s+/g, ' ').trim();\n if (text.length >= 20) {\n chunks.push({\n path: relativePath,\n startLine: chunkStartLine,\n endLine: chunkStartLine + currentLines.length - 1,\n text: text.slice(0, 360),\n hash: snippetHash(text),\n });\n }\n }\n\n return chunks;\n}\n\n// ── Deduplication ──────────────────────────────────────────────────────\n\nfunction deduplicateChunks(\n chunks: LightSweepChunk[],\n threshold: number,\n): { unique: LightSweepChunk[]; deduped: number } {\n const unique: LightSweepChunk[] = [];\n let deduped = 0;\n\n for (const chunk of chunks) {\n const isDuplicate = unique.some(\n (existing) => existing.hash === chunk.hash || trigramSimilarity(existing.text, chunk.text) >= threshold,\n );\n if (isDuplicate) {\n deduped += 1;\n } else {\n unique.push(chunk);\n }\n }\n\n return { unique, deduped };\n}\n\n// ── Last-run writer ────────────────────────────────────────────────────\n\nasync function writeLastRun(\n workspaceDir: string,\n params: {\n runId: string;\n startedAt: string;\n cfg: DreamingLightConfig;\n ok: boolean;\n reason: string;\n startMs: number;\n light: DreamingLightLastRun['light'];\n errorMessage?: string;\n },\n): Promise<void> {\n const finishedAt = new Date().toISOString();\n const durationMs = Math.max(0, Date.now() - params.startMs);\n\n const lastRun: DreamingLightLastRun = {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'light',\n runId: params.runId,\n startedAt: params.startedAt,\n finishedAt,\n durationMs,\n ok: params.ok,\n reason: params.reason,\n config: params.cfg,\n light: params.light,\n ...(params.errorMessage ? { errorMessage: params.errorMessage } : {}),\n };\n\n const lastRunPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE, 'last-run-light.json');\n await fs.mkdir(path.dirname(lastRunPath), { recursive: true });\n const tmp = `${lastRunPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(lastRun, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, lastRunPath);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DreamingDeepConfig } from './config.js';
|
|
2
|
+
type PreviewItem = {
|
|
3
|
+
key: string;
|
|
4
|
+
hash: string;
|
|
5
|
+
snippet: string;
|
|
6
|
+
path: string;
|
|
7
|
+
startLine: number;
|
|
8
|
+
endLine: number;
|
|
9
|
+
score: number;
|
|
10
|
+
avgScore: number;
|
|
11
|
+
recallCount: number;
|
|
12
|
+
recencyDecay: number;
|
|
13
|
+
alreadyPromotedByKey: boolean;
|
|
14
|
+
alreadyPromotedByHash: boolean;
|
|
15
|
+
skippedReason: string | null;
|
|
16
|
+
};
|
|
17
|
+
export declare function previewDreamingDeepPromotion(params: {
|
|
18
|
+
workspaceDir: string;
|
|
19
|
+
config?: Partial<DreamingDeepConfig>;
|
|
20
|
+
limit?: number;
|
|
21
|
+
now?: Date;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
ok: boolean;
|
|
24
|
+
reason: string;
|
|
25
|
+
items: PreviewItem[];
|
|
26
|
+
memoryPath: string;
|
|
27
|
+
}>;
|
|
28
|
+
export {};
|