@xopcai/xopc 0.0.25 → 0.0.27
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/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/agents-w8_jzuiX.js +216 -0
- package/dist/gateway/static/root/assets/agents-w8_jzuiX.js.map +1 -0
- package/dist/gateway/static/root/assets/{apps-page-DbzO48lg.js → apps-page-CBBh_Ww8.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-DbzO48lg.js.map → apps-page-CBBh_Ww8.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DUKRPC7C.js +9 -0
- package/dist/gateway/static/root/assets/{channels-settings-CeGoU9v8.js.map → channels-settings-DUKRPC7C.js.map} +1 -1
- package/dist/gateway/static/root/assets/cron-page-S18t1yG-.js +2 -0
- package/dist/gateway/static/root/assets/{cron-page-DpEYUvxB.js.map → cron-page-S18t1yG-.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-Cvv0F3pa.js → cron-utils-08gdQfl9.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-Cvv0F3pa.js.map → cron-utils-08gdQfl9.js.map} +1 -1
- package/dist/gateway/static/root/assets/dist-C1MrygQH.js +2 -0
- package/dist/gateway/static/root/assets/{dist-C41N3YrO.js.map → dist-C1MrygQH.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CkkYZjNP.js → extension-debug-page-DN3HKUGS.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-CkkYZjNP.js.map → extension-debug-page-DN3HKUGS.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BjUIPVNG.js → extension-page-CoFDHZtZ.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-BjUIPVNG.js.map → extension-page-CoFDHZtZ.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CwuFDOdk.js → extension-settings-page-BcPCu_Go.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-CwuFDOdk.js.map → extension-settings-page-BcPCu_Go.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-OT4cGzon.css +1 -0
- package/dist/gateway/static/root/assets/index-PfkB8N37.js +4734 -0
- package/dist/gateway/static/root/assets/index-PfkB8N37.js.map +1 -0
- package/dist/gateway/static/root/assets/logs-page-DoWe1GWy.js +2 -0
- package/dist/gateway/static/root/assets/{logs-page-BtwGPuw2.js.map → logs-page-DoWe1GWy.js.map} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-2uOYwEwd.js +2 -0
- package/dist/gateway/static/root/assets/{sessions-page-4rKFDn2k.js.map → sessions-page-2uOYwEwd.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-fQWswCuq.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-fQWswCuq.js.map +1 -0
- package/dist/gateway/static/root/assets/skills-page-BmBDCEbY.js +3 -0
- package/dist/gateway/static/root/assets/{skills-page-_siDuHeF.js.map → skills-page-BmBDCEbY.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 +37 -9
- package/dist/src/agent/memory/dreaming/config.js +60 -18
- package/dist/src/agent/memory/dreaming/config.js.map +1 -1
- package/dist/src/agent/memory/dreaming/constants.d.ts +22 -1
- package/dist/src/agent/memory/dreaming/constants.js +26 -2
- package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +5 -6
- package/dist/src/agent/memory/dreaming/deep-promotion.js +90 -156
- package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
- 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 +3 -1
- package/dist/src/agent/memory/dreaming/preview.js +11 -90
- package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
- 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 +20 -0
- package/dist/src/agent/memory/dreaming/short-term-store.js +25 -15
- package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
- 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 +54 -12
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/service.js +54 -28
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/config/schema.d.ts +54 -0
- package/dist/src/config/schema.js +34 -8
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +18 -0
- package/dist/src/gateway/hono/routes/dreaming.js +105 -15
- package/dist/src/gateway/hono/routes/dreaming.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/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-C_bPhtBs.js +0 -216
- package/dist/gateway/static/root/assets/agents-C_bPhtBs.js.map +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CeGoU9v8.js +0 -9
- package/dist/gateway/static/root/assets/cron-page-DpEYUvxB.js +0 -2
- package/dist/gateway/static/root/assets/dist-C41N3YrO.js +0 -2
- package/dist/gateway/static/root/assets/index-DwzwDCjW.js +0 -150
- package/dist/gateway/static/root/assets/index-DwzwDCjW.js.map +0 -1
- package/dist/gateway/static/root/assets/index-dhtHG1nU.css +0 -1
- package/dist/gateway/static/root/assets/logs-page-BtwGPuw2.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-4rKFDn2k.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-iYLSxQYc.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-iYLSxQYc.js.map +0 -1
- package/dist/gateway/static/root/assets/skills-page-_siDuHeF.js +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deep-promotion.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/deep-promotion.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { MEMORY_MD_FILENAME } from './constants.js';\nimport {\n loadDreamingStore,\n saveDreamingStore,\n withDreamingPromotionLock,\n type DreamingStoreEntry,\n} from './short-term-store.js';\nimport { DREAMING_LAST_RUN_RELATIVE } from './constants.js';\n\nconst log = createLogger('Dreaming:Deep');\n\nexport type DreamingDeepConfig = {\n enabled: boolean;\n minScore: number;\n minRecallCount: number;\n limit: number;\n};\n\nexport type DreamingPromotionCandidate = DreamingStoreEntry & {\n avgScore: number;\n score: number;\n};\n\nfunction clampScore(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.max(0, Math.min(1, value));\n}\n\nfunction formatIsoDay(now: Date): string {\n return now.toISOString().slice(0, 10);\n}\n\nfunction compareCandidates(a: DreamingPromotionCandidate, b: DreamingPromotionCandidate): number {\n if (b.score !== a.score) return b.score - a.score;\n if (b.recallCount !== a.recallCount) return b.recallCount - a.recallCount;\n const aMs = Date.parse(a.lastRecalledAt);\n const bMs = Date.parse(b.lastRecalledAt);\n if (Number.isFinite(aMs) || Number.isFinite(bMs)) {\n if (bMs !== aMs) return bMs - aMs;\n }\n return a.path.localeCompare(b.path);\n}\n\nfunction normalizeSnippetForHash(snippet: string): string {\n return snippet\n .trim()\n .replace(/\\s+/g, ' ')\n .replace(/[“”]/g, '\"')\n .replace(/[‘’]/g, \"'\")\n .toLowerCase()\n .slice(0, 512);\n}\n\nfunction snippetHash(snippet: string): string {\n const normalized = normalizeSnippetForHash(snippet);\n return createHash('sha1').update(normalized).digest('hex').slice(0, 12);\n}\n\nfunction markerForPromotion(key: string, hash: string): string {\n // Quote values to allow spaces/colons in key.\n return `<!-- xopc-memory-promotion key=\"${key}\" hash=\"${hash}\" -->`;\n}\n\nfunction extractPromotionMarkers(memoryText: string): { keys: Set<string>; hashes: Set<string> } {\n const keys = new Set<string>();\n const hashes = new Set<string>();\n\n // New format: <!-- xopc-memory-promotion key=\"...\" hash=\"...\" -->\n for (const match of memoryText.matchAll(/<!--\\s*xopc-memory-promotion\\b([\\s\\S]*?)-->/gi)) {\n const body = match[1] ?? '';\n const k = body.match(/\\bkey\\s*=\\s*\"([^\"]+)\"/i)?.[1]?.trim();\n const h = body.match(/\\bhash\\s*=\\s*\"([^\"]+)\"/i)?.[1]?.trim();\n if (k) keys.add(k);\n if (h) hashes.add(h);\n }\n\n // Legacy format: <!-- xopc-memory-promotion:<key> -->\n for (const match of memoryText.matchAll(/<!--\\s*xopc-memory-promotion:([^\\n]+?)\\s*-->/gi)) {\n const key = match[1]?.trim();\n if (key) keys.add(key);\n }\n\n return { keys, hashes };\n}\n\nfunction isContaminatedSnippet(snippet: string): boolean {\n const s = snippet.trim();\n if (!s) return true;\n const lower = s.toLowerCase();\n\n // Obvious tool/system/prompt artifacts.\n const patterns: RegExp[] = [\n /\\b(system|assistant|tool)\\s*:/i,\n /<\\s*(system|assistant|tool)\\b/i,\n /<!--\\s*xopc-memory-promotion\\b/i,\n /tool_call_id|toolcallid|function_call|arguments\\s*:\\s*\\{/i,\n /\"tool\"\\s*:\\s*|\\btool_name\\b|\\btool\\b\\s*results?/i,\n /you are (an|a)\\s+(ai|assistant)|follow these instructions/i,\n /begin\\s+(system prompt|instructions)|end\\s+(system prompt|instructions)/i,\n /```/i,\n /\\b__xopc_/i,\n ];\n if (patterns.some((p) => p.test(s))) return true;\n\n // JSON-ish blocks or obvious dumps.\n const braceCount = (s.match(/[{}[\\]]/g) ?? []).length;\n if (braceCount >= 12) return true;\n\n // Very link-heavy / log-like.\n const urlCount = (lower.match(/https?:\\/\\//g) ?? []).length;\n if (urlCount >= 3) return true;\n\n return false;\n}\n\nasync function readFileLines(fullPath: string): Promise<string[] | null> {\n try {\n const raw = await fs.readFile(fullPath, 'utf-8');\n return raw.split(/\\r?\\n/);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code === 'ENOENT') return null;\n throw err;\n }\n}\n\nfunction sliceRange(lines: string[], startLine: number, endLine: number): string {\n const startIdx = Math.max(0, startLine - 1);\n const endIdx = Math.min(lines.length, endLine);\n if (startIdx >= endIdx) return '';\n return lines\n .slice(startIdx, endIdx)\n .map((l) => l.trim())\n .filter(Boolean)\n .join(' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, 360);\n}\n\nasync function rehydrateSnippet(params: {\n workspaceDir: string;\n candidate: DreamingPromotionCandidate;\n}): Promise<{ snippet: string; startLine: number; endLine: number } | null> {\n const fullPath = path.join(params.workspaceDir, params.candidate.path);\n const lines = await readFileLines(fullPath);\n if (!lines) return null;\n\n const startLine = Math.max(1, Math.floor(params.candidate.startLine));\n const endLine = Math.max(startLine, Math.floor(params.candidate.endLine));\n const snippet = sliceRange(lines, startLine, endLine);\n if (!snippet) return null;\n return { snippet, startLine, endLine };\n}\n\nfunction resolveDefaultConfig(overrides?: Partial<DreamingDeepConfig>): DreamingDeepConfig {\n const enabled = overrides?.enabled === true;\n const minScore = typeof overrides?.minScore === 'number' ? overrides.minScore : 0.8;\n const minRecallCount =\n typeof overrides?.minRecallCount === 'number' ? overrides.minRecallCount : 3;\n const limit = typeof overrides?.limit === 'number' ? overrides.limit : 10;\n return {\n enabled,\n minScore: clampScore(minScore),\n minRecallCount: Math.max(1, Math.floor(minRecallCount)),\n limit: Math.max(0, Math.floor(limit)),\n };\n}\n\ntype DreamingLastRun = {\n version: 1;\n runId: string;\n startedAt: string;\n finishedAt: string;\n ok: boolean;\n reason: string;\n config: DreamingDeepConfig;\n candidates: number;\n applied: number;\n memoryPath: string;\n errorMessage?: string;\n};\n\nasync function writeLastRun(params: { workspaceDir: string; lastRun: DreamingLastRun }): 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\nexport async function runDreamingDeepPromotion(params: {\n workspaceDir: string;\n config?: Partial<DreamingDeepConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n candidates: number;\n applied: number;\n memoryPath: string;\n}> {\n const cfg = resolveDefaultConfig(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `${startedAt}:${process.pid}:${Math.random().toString(16).slice(2)}`;\n const memoryPath = path.join(params.workspaceDir, MEMORY_MD_FILENAME);\n\n if (!cfg.enabled) {\n const finishedAt = new Date().toISOString();\n await writeLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: {\n version: 1,\n runId,\n startedAt,\n finishedAt,\n ok: true,\n reason: 'dreaming mvp disabled',\n config: cfg,\n candidates: 0,\n applied: 0,\n memoryPath,\n },\n }).catch(() => undefined);\n return { ok: true, reason: 'dreaming mvp disabled', candidates: 0, applied: 0, memoryPath };\n }\n if (cfg.limit === 0) {\n const finishedAt = new Date().toISOString();\n await writeLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: {\n version: 1,\n runId,\n startedAt,\n finishedAt,\n ok: true,\n reason: 'dreaming mvp limit=0',\n config: cfg,\n candidates: 0,\n applied: 0,\n memoryPath,\n },\n }).catch(() => undefined);\n return { ok: true, reason: 'dreaming mvp limit=0', candidates: 0, applied: 0, memoryPath };\n }\n\n try {\n const result = await withDreamingPromotionLock(params.workspaceDir, async () => {\n const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });\n\n const all = Object.values(store.entries ?? {}).filter((e): e is DreamingStoreEntry => {\n if (!e || typeof e !== 'object') return false;\n if (e.promotedAt) return false;\n if (!e.path || !e.path.startsWith('memory/')) return false;\n if (e.recallCount < cfg.minRecallCount) return false;\n const avg = e.recallCount > 0 ? e.totalScore / e.recallCount : 0;\n return clampScore(avg) >= cfg.minScore;\n });\n\n const ranked: DreamingPromotionCandidate[] = all\n .map((e) => {\n const avgScore = e.recallCount > 0 ? clampScore(e.totalScore / e.recallCount) : 0;\n // Score: avgScore primary, with mild recallCount reinforcement.\n const reinforcement = clampScore(Math.log1p(e.recallCount) / Math.log1p(10)) * 0.12;\n const score = clampScore(avgScore + reinforcement);\n return { ...e, avgScore, score };\n })\n .sort(compareCandidates)\n .slice(0, cfg.limit);\n\n if (ranked.length === 0) {\n return { ok: true, reason: 'no eligible candidates', candidates: 0, applied: 0, memoryPath };\n }\n\n const existing = await fs.readFile(memoryPath, 'utf-8').catch((err: unknown) => {\n if ((err as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') return '';\n throw err;\n });\n const existingMarkers = extractPromotionMarkers(existing);\n\n const appliedCandidates: Array<{\n key: string;\n hash: string;\n snippet: string;\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n recallCount: number;\n avgScore: number;\n }> = [];\n\n for (const candidate of ranked) {\n if (existingMarkers.keys.has(candidate.key)) {\n // Treat as already applied; mark promotedAt for idempotency and keep going.\n const entry = store.entries[candidate.key];\n if (entry && !entry.promotedAt) {\n entry.promotedAt = now.toISOString();\n }\n continue;\n }\n const rehydrated = await rehydrateSnippet({ workspaceDir: params.workspaceDir, candidate });\n if (!rehydrated) {\n continue;\n }\n if (isContaminatedSnippet(rehydrated.snippet)) {\n continue;\n }\n const hash = snippetHash(rehydrated.snippet);\n if (existingMarkers.hashes.has(hash)) {\n // Already promoted (possibly from a different key/line range). Mark promoted for idempotency.\n const entry = store.entries[candidate.key];\n if (entry && !entry.promotedAt) {\n entry.promotedAt = now.toISOString();\n }\n continue;\n }\n appliedCandidates.push({\n key: candidate.key,\n hash,\n snippet: rehydrated.snippet,\n path: candidate.path,\n startLine: rehydrated.startLine,\n endLine: rehydrated.endLine,\n score: candidate.score,\n recallCount: candidate.recallCount,\n avgScore: candidate.avgScore,\n });\n }\n\n if (appliedCandidates.length === 0) {\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n return {\n ok: true,\n reason: 'candidates were stale or already applied',\n candidates: ranked.length,\n applied: 0,\n memoryPath,\n };\n }\n\n const day = formatIsoDay(now);\n const header = existing.trim().length > 0 ? '' : '# Long-Term Memory\\n\\n';\n const sectionLines: string[] = ['', `## Promoted From Short-Term Memory (${day})`, ''];\n for (const c of appliedCandidates) {\n const src = `${c.path}:${c.startLine}-${c.endLine}`;\n sectionLines.push(markerForPromotion(c.key, c.hash));\n sectionLines.push(\n `- ${c.snippet} [score=${c.score.toFixed(3)} recalls=${c.recallCount} avg=${c.avgScore.toFixed(3)} source=${src}]`,\n );\n }\n sectionLines.push('');\n\n const next = `${header}${existing.endsWith('\\n') || existing.length === 0 ? existing : `${existing}\\n`}${sectionLines.join('\\n')}`;\n await fs.writeFile(memoryPath, next, 'utf-8');\n\n const nowIso = now.toISOString();\n for (const c of appliedCandidates) {\n const entry = store.entries[c.key];\n if (entry) {\n entry.promotedAt = nowIso;\n entry.snippet = c.snippet;\n entry.startLine = c.startLine;\n entry.endLine = c.endLine;\n }\n }\n store.updatedAt = nowIso;\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n\n log.info(\n { workspaceDir: params.workspaceDir, candidates: ranked.length, applied: appliedCandidates.length },\n 'Dreaming deep promotion complete',\n );\n\n return {\n ok: true,\n reason: 'applied promotions',\n candidates: ranked.length,\n applied: appliedCandidates.length,\n memoryPath,\n };\n });\n\n const finishedAt = new Date().toISOString();\n await writeLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: {\n version: 1,\n runId,\n startedAt,\n finishedAt,\n ok: result.ok,\n reason: result.reason,\n config: cfg,\n candidates: result.candidates,\n applied: result.applied,\n memoryPath: result.memoryPath,\n },\n }).catch(() => undefined);\n\n return result;\n } catch (err) {\n const finishedAt = new Date().toISOString();\n const em = err instanceof Error ? err.message : String(err);\n await writeLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: {\n version: 1,\n runId,\n startedAt,\n finishedAt,\n ok: false,\n reason: 'error',\n config: cfg,\n candidates: 0,\n applied: 0,\n memoryPath,\n errorMessage: em,\n },\n }).catch(() => undefined);\n throw err;\n }\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"deep-promotion.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/deep-promotion.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { MEMORY_MD_FILENAME } from './constants.js';\nimport {\n loadDreamingStore,\n saveDreamingStore,\n withDreamingPromotionLock,\n type DreamingStoreEntry,\n} from './short-term-store.js';\nimport {\n DREAMING_LAST_RUN_FORMAT_VERSION,\n emptyDeepPhaseSkipped,\n writeDreamingDeepLastRun,\n type DreamingDeepLastRun,\n type DreamingDeepPhaseSkipped,\n} from './last-run.js';\nimport type { DreamingDeepConfig } from './config.js';\nimport {\n clamp01,\n compareCandidatesByScore,\n computeCandidateScore,\n extractPromotionMarkers,\n isContaminatedSnippet,\n isExpiredEntry,\n isoDay,\n readFileLines,\n resolveDeepDefaults,\n sliceRange,\n snippetHash,\n} from './utils.js';\n\nconst log = createLogger('Dreaming:Deep');\n\nexport type { DreamingDeepConfig } from './config.js';\n\nexport type DreamingPromotionCandidate = DreamingStoreEntry & {\n avgScore: number;\n /** Time-decay-adjusted final score used for ranking. */\n score: number;\n /** Raw recency decay multiplier (0–1). */\n recencyDecay: number;\n};\n\n\nfunction markerForPromotion(key: string, hash: string): string {\n // Quote values to allow spaces/colons in key.\n return `<!-- xopc-memory-promotion key=\"${key}\" hash=\"${hash}\" -->`;\n}\n\n\nasync function rehydrateSnippet(params: {\n workspaceDir: string;\n candidate: DreamingPromotionCandidate;\n}): Promise<{ snippet: string; startLine: number; endLine: number } | null> {\n const fullPath = path.join(params.workspaceDir, params.candidate.path);\n const lines = await readFileLines(fullPath);\n if (!lines) return null;\n\n const startLine = Math.max(1, Math.floor(params.candidate.startLine));\n const endLine = Math.max(startLine, Math.floor(params.candidate.endLine));\n const snippet = sliceRange(lines, startLine, endLine);\n if (!snippet) return null;\n return { snippet, startLine, endLine };\n}\n\n\nfunction buildDeepLastRun(base: {\n runId: string;\n startedAt: string;\n finishedAt: string;\n t0: number;\n ok: boolean;\n reason: string;\n config: DreamingDeepConfig;\n memoryPath: string;\n errorMessage?: string;\n deep: DreamingDeepLastRun['deep'];\n}): DreamingDeepLastRun {\n const durationMs = Math.max(0, Date.now() - base.t0);\n return {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'deep',\n runId: base.runId,\n startedAt: base.startedAt,\n finishedAt: base.finishedAt,\n durationMs,\n ok: base.ok,\n reason: base.reason,\n config: base.config,\n memoryPath: base.memoryPath,\n ...(base.errorMessage ? { errorMessage: base.errorMessage } : {}),\n deep: base.deep,\n };\n}\n\nexport async function runDreamingDeepPromotion(params: {\n workspaceDir: string;\n config?: Partial<DreamingDeepConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n candidates: number;\n applied: number;\n memoryPath: string;\n}> {\n const cfg = resolveDeepDefaults(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `${startedAt}:${process.pid}:${Math.random().toString(16).slice(2)}`;\n const memoryPath = path.join(params.workspaceDir, MEMORY_MD_FILENAME);\n const t0 = Date.now();\n\n // Early exit for disabled or zero-limit configurations.\n const earlyExitReason = !cfg.enabled ? 'dreaming disabled' : cfg.limit === 0 ? 'dreaming limit=0' : null;\n if (earlyExitReason) {\n const finishedAt = new Date().toISOString();\n const empty = emptyDeepPhaseSkipped();\n await writeDreamingDeepLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: buildDeepLastRun({\n runId,\n startedAt,\n finishedAt,\n t0,\n ok: true,\n reason: earlyExitReason,\n config: cfg,\n memoryPath,\n deep: { candidatesRanked: 0, applied: 0, skipped: empty },\n }),\n }).catch(() => undefined);\n return { ok: true, reason: earlyExitReason, candidates: 0, applied: 0, memoryPath };\n }\n\n try {\n const result = await withDreamingPromotionLock(params.workspaceDir, async () => {\n const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });\n\n const nowMs = now.getTime();\n\n const all = Object.values(store.entries ?? {}).filter((e): e is DreamingStoreEntry => {\n if (!e || typeof e !== 'object') return false;\n if (e.promotedAt) return false;\n if (!e.path || !e.path.startsWith('memory/')) return false;\n if (e.recallCount < cfg.minRecallCount) return false;\n // Require minimum unique queries to avoid single-query inflation.\n if ((e.queryHashes?.length ?? 0) < cfg.minUniqueQueries) return false;\n // Expire entries older than maxAgeDays since last recall.\n if (isExpiredEntry(e.lastRecalledAt, nowMs, cfg.maxAgeDays)) return false;\n const avg = e.recallCount > 0 ? e.totalScore / e.recallCount : 0;\n return clamp01(avg) >= cfg.minScore;\n });\n\n const ranked: DreamingPromotionCandidate[] = all\n .map((e) => {\n const { avgScore, score, recencyDecay } = computeCandidateScore(e, nowMs, cfg.recencyHalfLifeDays);\n return { ...e, avgScore, score, recencyDecay };\n })\n .sort(compareCandidatesByScore)\n .slice(0, cfg.limit);\n\n if (ranked.length === 0) {\n const z = emptyDeepPhaseSkipped();\n return { ok: true, reason: 'no eligible candidates', candidates: 0, applied: 0, memoryPath, skipped: z };\n }\n\n const existing = await fs.readFile(memoryPath, 'utf-8').catch((err: unknown) => {\n if ((err as NodeJS.ErrnoException | undefined)?.code === 'ENOENT') return '';\n throw err;\n });\n const existingMarkers = extractPromotionMarkers(existing);\n\n const appliedCandidates: Array<{\n key: string;\n hash: string;\n snippet: string;\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n recallCount: number;\n avgScore: number;\n }> = [];\n\n const skipped: DreamingDeepPhaseSkipped = emptyDeepPhaseSkipped();\n for (const candidate of ranked) {\n if (existingMarkers.keys.has(candidate.key)) {\n skipped.alreadyPromotedKey += 1;\n // Treat as already applied; mark promotedAt for idempotency and keep going.\n const entry = store.entries[candidate.key];\n if (entry && !entry.promotedAt) {\n entry.promotedAt = now.toISOString();\n }\n continue;\n }\n const rehydrated = await rehydrateSnippet({ workspaceDir: params.workspaceDir, candidate });\n if (!rehydrated) {\n skipped.rehydrateFailed += 1;\n continue;\n }\n if (isContaminatedSnippet(rehydrated.snippet)) {\n skipped.contaminated += 1;\n continue;\n }\n const hash = snippetHash(rehydrated.snippet);\n if (existingMarkers.hashes.has(hash)) {\n skipped.hashDuplicate += 1;\n // Already promoted (possibly from a different key/line range). Mark promoted for idempotency.\n const entry = store.entries[candidate.key];\n if (entry && !entry.promotedAt) {\n entry.promotedAt = now.toISOString();\n }\n continue;\n }\n appliedCandidates.push({\n key: candidate.key,\n hash,\n snippet: rehydrated.snippet,\n path: candidate.path,\n startLine: rehydrated.startLine,\n endLine: rehydrated.endLine,\n score: candidate.score,\n recallCount: candidate.recallCount,\n avgScore: candidate.avgScore,\n });\n }\n\n if (appliedCandidates.length === 0) {\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n return {\n ok: true,\n reason: 'candidates were stale or already applied',\n candidates: ranked.length,\n applied: 0,\n memoryPath,\n skipped,\n };\n }\n\n const day = isoDay(now);\n const header = existing.trim().length > 0 ? '' : '# Long-Term Memory\\n\\n';\n const sectionLines: string[] = ['', `## Promoted From Short-Term Memory (${day})`, ''];\n for (const c of appliedCandidates) {\n const src = `${c.path}:${c.startLine}-${c.endLine}`;\n sectionLines.push(markerForPromotion(c.key, c.hash));\n sectionLines.push(\n `- ${c.snippet} [score=${c.score.toFixed(3)} recalls=${c.recallCount} avg=${c.avgScore.toFixed(3)} source=${src}]`,\n );\n }\n sectionLines.push('');\n\n const next = `${header}${existing.endsWith('\\n') || existing.length === 0 ? existing : `${existing}\\n`}${sectionLines.join('\\n')}`;\n await fs.writeFile(memoryPath, next, 'utf-8');\n\n const nowIso = now.toISOString();\n for (const c of appliedCandidates) {\n const entry = store.entries[c.key];\n if (entry) {\n entry.promotedAt = nowIso;\n entry.snippet = c.snippet;\n entry.startLine = c.startLine;\n entry.endLine = c.endLine;\n }\n }\n store.updatedAt = nowIso;\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n\n log.info(\n { workspaceDir: params.workspaceDir, candidates: ranked.length, applied: appliedCandidates.length },\n 'Dreaming deep promotion complete',\n );\n\n return {\n ok: true,\n reason: 'applied promotions',\n candidates: ranked.length,\n applied: appliedCandidates.length,\n memoryPath,\n skipped,\n };\n });\n\n const finishedAt = new Date().toISOString();\n const empty = emptyDeepPhaseSkipped();\n const resultSkipped = 'skipped' in result ? result.skipped : empty;\n await writeDreamingDeepLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: buildDeepLastRun({\n runId,\n startedAt,\n finishedAt,\n t0,\n ok: result.ok,\n reason: result.reason,\n config: cfg,\n memoryPath: result.memoryPath,\n deep: {\n candidatesRanked: result.candidates,\n applied: result.applied,\n skipped: resultSkipped,\n },\n }),\n }).catch(() => undefined);\n\n return {\n ok: result.ok,\n reason: result.reason,\n candidates: result.candidates,\n applied: result.applied,\n memoryPath: result.memoryPath,\n };\n } catch (err) {\n const finishedAt = new Date().toISOString();\n const em = err instanceof Error ? err.message : String(err);\n const z = emptyDeepPhaseSkipped();\n await writeDreamingDeepLastRun({\n workspaceDir: params.workspaceDir,\n lastRun: buildDeepLastRun({\n runId,\n startedAt,\n finishedAt,\n t0,\n ok: false,\n reason: 'error',\n config: cfg,\n memoryPath,\n errorMessage: em,\n deep: { candidatesRanked: 0, applied: 0, skipped: z },\n }),\n }).catch(() => undefined);\n throw err;\n }\n}\n\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type DreamingPhaseId } from './constants.js';
|
|
2
|
+
export type DreamingEventBase = {
|
|
3
|
+
timestamp: string;
|
|
4
|
+
phase: DreamingPhaseId;
|
|
5
|
+
ok: boolean;
|
|
6
|
+
reason: string;
|
|
7
|
+
durationMs: number;
|
|
8
|
+
};
|
|
9
|
+
export type DreamingLightEvent = DreamingEventBase & {
|
|
10
|
+
phase: 'light';
|
|
11
|
+
scannedEntries: number;
|
|
12
|
+
newSignals: number;
|
|
13
|
+
deduped: number;
|
|
14
|
+
};
|
|
15
|
+
export type DreamingDeepEvent = DreamingEventBase & {
|
|
16
|
+
phase: 'deep';
|
|
17
|
+
candidates: number;
|
|
18
|
+
applied: number;
|
|
19
|
+
};
|
|
20
|
+
export type DreamingRemEvent = DreamingEventBase & {
|
|
21
|
+
phase: 'rem';
|
|
22
|
+
patternsDiscovered: number;
|
|
23
|
+
entriesAnalyzed: number;
|
|
24
|
+
};
|
|
25
|
+
export type DreamingEvent = DreamingLightEvent | DreamingDeepEvent | DreamingRemEvent;
|
|
26
|
+
/**
|
|
27
|
+
* Append a single event line to `memory/.dreams/events.jsonl`.
|
|
28
|
+
* Creates the directory and file if they don't exist.
|
|
29
|
+
* Failures are silently ignored so audit logging never blocks execution.
|
|
30
|
+
*/
|
|
31
|
+
export declare function appendDreamingEvent(workspaceDir: string, event: DreamingEvent): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Read the most recent N events from the events log.
|
|
34
|
+
* Returns newest-first. If the file doesn't exist, returns an empty array.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readDreamingEvents(workspaceDir: string, limit?: number): Promise<DreamingEvent[]>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { DREAMING_DIR_RELATIVE, DREAMING_EVENTS_LOG_RELATIVE } from "./constants.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
//#region src/agent/memory/dreaming/events.ts
|
|
5
|
+
/**
|
|
6
|
+
* Append a single event line to `memory/.dreams/events.jsonl`.
|
|
7
|
+
* Creates the directory and file if they don't exist.
|
|
8
|
+
* Failures are silently ignored so audit logging never blocks execution.
|
|
9
|
+
*/
|
|
10
|
+
async function appendDreamingEvent(workspaceDir, event) {
|
|
11
|
+
try {
|
|
12
|
+
const dirPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE);
|
|
13
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
14
|
+
const filePath = path.join(workspaceDir, DREAMING_EVENTS_LOG_RELATIVE);
|
|
15
|
+
const line = JSON.stringify(event) + "\n";
|
|
16
|
+
await fs.appendFile(filePath, line, "utf-8");
|
|
17
|
+
} catch {}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Read the most recent N events from the events log.
|
|
21
|
+
* Returns newest-first. If the file doesn't exist, returns an empty array.
|
|
22
|
+
*/
|
|
23
|
+
async function readDreamingEvents(workspaceDir, limit = 50) {
|
|
24
|
+
const filePath = path.join(workspaceDir, DREAMING_EVENTS_LOG_RELATIVE);
|
|
25
|
+
let raw;
|
|
26
|
+
try {
|
|
27
|
+
raw = await fs.readFile(filePath, "utf-8");
|
|
28
|
+
} catch (err) {
|
|
29
|
+
if (err?.code === "ENOENT") return [];
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
const tail = raw.split("\n").map((line) => line.trim()).filter(Boolean).slice(-Math.abs(limit));
|
|
33
|
+
const events = [];
|
|
34
|
+
for (const line of tail) try {
|
|
35
|
+
const parsed = JSON.parse(line);
|
|
36
|
+
if (parsed && typeof parsed === "object" && parsed.timestamp && parsed.phase) events.push(parsed);
|
|
37
|
+
} catch {}
|
|
38
|
+
events.reverse();
|
|
39
|
+
return events;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { appendDreamingEvent, readDreamingEvents };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/events.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { DREAMING_DIR_RELATIVE, DREAMING_EVENTS_LOG_RELATIVE, type DreamingPhaseId } from './constants.js';\n\n// ── Event types ────────────────────────────────────────────────────────\n\nexport type DreamingEventBase = {\n timestamp: string;\n phase: DreamingPhaseId;\n ok: boolean;\n reason: string;\n durationMs: number;\n};\n\nexport type DreamingLightEvent = DreamingEventBase & {\n phase: 'light';\n scannedEntries: number;\n newSignals: number;\n deduped: number;\n};\n\nexport type DreamingDeepEvent = DreamingEventBase & {\n phase: 'deep';\n candidates: number;\n applied: number;\n};\n\nexport type DreamingRemEvent = DreamingEventBase & {\n phase: 'rem';\n patternsDiscovered: number;\n entriesAnalyzed: number;\n};\n\nexport type DreamingEvent = DreamingLightEvent | DreamingDeepEvent | DreamingRemEvent;\n\n// ── Write ──────────────────────────────────────────────────────────────\n\n/**\n * Append a single event line to `memory/.dreams/events.jsonl`.\n * Creates the directory and file if they don't exist.\n * Failures are silently ignored so audit logging never blocks execution.\n */\nexport async function appendDreamingEvent(workspaceDir: string, event: DreamingEvent): Promise<void> {\n try {\n const dirPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE);\n await fs.mkdir(dirPath, { recursive: true });\n const filePath = path.join(workspaceDir, DREAMING_EVENTS_LOG_RELATIVE);\n const line = JSON.stringify(event) + '\\n';\n await fs.appendFile(filePath, line, 'utf-8');\n } catch {\n // Audit logging must not block or throw.\n }\n}\n\n// ── Read ───────────────────────────────────────────────────────────────\n\n/**\n * Read the most recent N events from the events log.\n * Returns newest-first. If the file doesn't exist, returns an empty array.\n */\nexport async function readDreamingEvents(\n workspaceDir: string,\n limit = 50,\n): Promise<DreamingEvent[]> {\n const filePath = path.join(workspaceDir, DREAMING_EVENTS_LOG_RELATIVE);\n let raw: string;\n try {\n raw = await fs.readFile(filePath, 'utf-8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code === 'ENOENT') return [];\n throw err;\n }\n\n const lines = raw\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean);\n\n // Take the last `limit` lines (newest entries are at the end).\n const tail = lines.slice(-Math.abs(limit));\n\n const events: DreamingEvent[] = [];\n for (const line of tail) {\n try {\n const parsed = JSON.parse(line) as DreamingEvent;\n if (parsed && typeof parsed === 'object' && parsed.timestamp && parsed.phase) {\n events.push(parsed);\n }\n } catch {\n // Skip malformed lines.\n }\n }\n\n // Return newest first.\n events.reverse();\n return events;\n}\n"],"mappings":";;;;;;;;;AA2CA,eAAsB,oBAAoB,cAAsB,OAAqC;AACnG,KAAI;EACF,MAAM,UAAU,KAAK,KAAK,cAAc,sBAAsB;AAC9D,QAAM,GAAG,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;EAC5C,MAAM,WAAW,KAAK,KAAK,cAAc,6BAA6B;EACtE,MAAM,OAAO,KAAK,UAAU,MAAM,GAAG;AACrC,QAAM,GAAG,WAAW,UAAU,MAAM,QAAQ;SACtC;;;;;;AAWV,eAAsB,mBACpB,cACA,QAAQ,IACkB;CAC1B,MAAM,WAAW,KAAK,KAAK,cAAc,6BAA6B;CACtE,IAAI;AACJ,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,UAAU,QAAQ;UACnC,KAAK;AAEZ,MADc,KAA2C,SAC5C,SAAU,QAAO,EAAE;AAChC,QAAM;;CASR,MAAM,OANQ,IACX,MAAM,KAAK,CACX,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAGQ,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC;CAE1C,MAAM,SAA0B,EAAE;AAClC,MAAK,MAAM,QAAQ,KACjB,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,UAAU,OAAO,WAAW,YAAY,OAAO,aAAa,OAAO,MACrE,QAAO,KAAK,OAAO;SAEf;AAMV,QAAO,SAAS;AAChB,QAAO"}
|
|
@@ -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
|
+
}>;
|