@xopcai/xopc 0.0.25 → 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.
Files changed (90) hide show
  1. package/dist/extensions/telegram/xopc.extension.json +1 -1
  2. package/dist/gateway/static/root/assets/agents-Clv9i1Kb.js +216 -0
  3. package/dist/gateway/static/root/assets/agents-Clv9i1Kb.js.map +1 -0
  4. package/dist/gateway/static/root/assets/{apps-page-DbzO48lg.js → apps-page-DqclV-PP.js} +2 -2
  5. package/dist/gateway/static/root/assets/{apps-page-DbzO48lg.js.map → apps-page-DqclV-PP.js.map} +1 -1
  6. package/dist/gateway/static/root/assets/channels-settings-CLyTYjrz.js +9 -0
  7. package/dist/gateway/static/root/assets/{channels-settings-CeGoU9v8.js.map → channels-settings-CLyTYjrz.js.map} +1 -1
  8. package/dist/gateway/static/root/assets/cron-page-CU8lutMt.js +2 -0
  9. package/dist/gateway/static/root/assets/{cron-page-DpEYUvxB.js.map → cron-page-CU8lutMt.js.map} +1 -1
  10. package/dist/gateway/static/root/assets/{cron-utils-Cvv0F3pa.js → cron-utils-_UjiWax6.js} +2 -2
  11. package/dist/gateway/static/root/assets/{cron-utils-Cvv0F3pa.js.map → cron-utils-_UjiWax6.js.map} +1 -1
  12. package/dist/gateway/static/root/assets/dist-Xqb4IGWC.js +2 -0
  13. package/dist/gateway/static/root/assets/{dist-C41N3YrO.js.map → dist-Xqb4IGWC.js.map} +1 -1
  14. package/dist/gateway/static/root/assets/{extension-debug-page-CkkYZjNP.js → extension-debug-page-CtTUkAmw.js} +2 -2
  15. package/dist/gateway/static/root/assets/{extension-debug-page-CkkYZjNP.js.map → extension-debug-page-CtTUkAmw.js.map} +1 -1
  16. package/dist/gateway/static/root/assets/{extension-page-BjUIPVNG.js → extension-page-C-aQU8qR.js} +2 -2
  17. package/dist/gateway/static/root/assets/{extension-page-BjUIPVNG.js.map → extension-page-C-aQU8qR.js.map} +1 -1
  18. package/dist/gateway/static/root/assets/{extension-settings-page-CwuFDOdk.js → extension-settings-page-b0y9aY-q.js} +2 -2
  19. package/dist/gateway/static/root/assets/{extension-settings-page-CwuFDOdk.js.map → extension-settings-page-b0y9aY-q.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/index-DhSFfSNN.css +1 -0
  21. package/dist/gateway/static/root/assets/index-Gr2HWo-G.js +4734 -0
  22. package/dist/gateway/static/root/assets/index-Gr2HWo-G.js.map +1 -0
  23. package/dist/gateway/static/root/assets/logs-page-DRI33XK4.js +2 -0
  24. package/dist/gateway/static/root/assets/{logs-page-BtwGPuw2.js.map → logs-page-DRI33XK4.js.map} +1 -1
  25. package/dist/gateway/static/root/assets/sessions-page-Cryg-36Z.js +2 -0
  26. package/dist/gateway/static/root/assets/{sessions-page-4rKFDn2k.js.map → sessions-page-Cryg-36Z.js.map} +1 -1
  27. package/dist/gateway/static/root/assets/settings-page-DFNKT9yg.js +2 -0
  28. package/dist/gateway/static/root/assets/settings-page-DFNKT9yg.js.map +1 -0
  29. package/dist/gateway/static/root/assets/skills-page-D4gfh0Ih.js +3 -0
  30. package/dist/gateway/static/root/assets/{skills-page-_siDuHeF.js.map → skills-page-D4gfh0Ih.js.map} +1 -1
  31. package/dist/gateway/static/root/index.html +2 -2
  32. package/dist/package.js +1 -1
  33. package/dist/src/agent/memory/dreaming/config.d.ts +37 -9
  34. package/dist/src/agent/memory/dreaming/config.js +60 -18
  35. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  36. package/dist/src/agent/memory/dreaming/constants.d.ts +22 -1
  37. package/dist/src/agent/memory/dreaming/constants.js +26 -2
  38. package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
  39. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +5 -6
  40. package/dist/src/agent/memory/dreaming/deep-promotion.js +90 -156
  41. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  42. package/dist/src/agent/memory/dreaming/events.d.ts +36 -0
  43. package/dist/src/agent/memory/dreaming/events.js +44 -0
  44. package/dist/src/agent/memory/dreaming/events.js.map +1 -0
  45. package/dist/src/agent/memory/dreaming/last-run.d.ts +80 -0
  46. package/dist/src/agent/memory/dreaming/last-run.js +98 -0
  47. package/dist/src/agent/memory/dreaming/last-run.js.map +1 -0
  48. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +19 -0
  49. package/dist/src/agent/memory/dreaming/light-sweep.js +328 -0
  50. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -0
  51. package/dist/src/agent/memory/dreaming/preview.d.ts +3 -1
  52. package/dist/src/agent/memory/dreaming/preview.js +11 -90
  53. package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
  54. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +21 -0
  55. package/dist/src/agent/memory/dreaming/rem-patterns.js +286 -0
  56. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -0
  57. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +20 -0
  58. package/dist/src/agent/memory/dreaming/short-term-store.js +25 -15
  59. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  60. package/dist/src/agent/memory/dreaming/utils.d.ts +42 -0
  61. package/dist/src/agent/memory/dreaming/utils.js +141 -0
  62. package/dist/src/agent/memory/dreaming/utils.js.map +1 -0
  63. package/dist/src/agent/orchestration/agent-orchestrator.js +54 -12
  64. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  65. package/dist/src/agent/service.js +54 -28
  66. package/dist/src/agent/service.js.map +1 -1
  67. package/dist/src/config/schema.d.ts +54 -0
  68. package/dist/src/config/schema.js +34 -8
  69. package/dist/src/config/schema.js.map +1 -1
  70. package/dist/src/gateway/hono/lib/config-payload.d.ts +18 -0
  71. package/dist/src/gateway/hono/routes/dreaming.js +105 -15
  72. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  73. package/dist/src/gateway/hono/routes/models.js +26 -1
  74. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  75. package/dist/src/gateway/hono/routes/public-gateway.js +1 -0
  76. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  77. package/package.json +1 -1
  78. package/dist/gateway/static/root/assets/agents-C_bPhtBs.js +0 -216
  79. package/dist/gateway/static/root/assets/agents-C_bPhtBs.js.map +0 -1
  80. package/dist/gateway/static/root/assets/channels-settings-CeGoU9v8.js +0 -9
  81. package/dist/gateway/static/root/assets/cron-page-DpEYUvxB.js +0 -2
  82. package/dist/gateway/static/root/assets/dist-C41N3YrO.js +0 -2
  83. package/dist/gateway/static/root/assets/index-DwzwDCjW.js +0 -150
  84. package/dist/gateway/static/root/assets/index-DwzwDCjW.js.map +0 -1
  85. package/dist/gateway/static/root/assets/index-dhtHG1nU.css +0 -1
  86. package/dist/gateway/static/root/assets/logs-page-BtwGPuw2.js +0 -2
  87. package/dist/gateway/static/root/assets/sessions-page-4rKFDn2k.js +0 -2
  88. package/dist/gateway/static/root/assets/settings-page-iYLSxQYc.js +0 -2
  89. package/dist/gateway/static/root/assets/settings-page-iYLSxQYc.js.map +0 -1
  90. package/dist/gateway/static/root/assets/skills-page-_siDuHeF.js +0 -3
@@ -1,3 +1,4 @@
1
+ import { DEFAULT_DEEP_CRON, DEFAULT_LIGHT_CRON, DEFAULT_REM_CRON } from "./constants.js";
1
2
  //#region src/agent/memory/dreaming/config.ts
2
3
  function clampScore(value, fallback) {
3
4
  if (!Number.isFinite(value)) return fallback;
@@ -9,36 +10,77 @@ function toPositiveInt(value, fallback) {
9
10
  const floored = Math.floor(num);
10
11
  return floored > 0 ? floored : fallback;
11
12
  }
13
+ function toNonNegInt(value, fallback) {
14
+ const num = typeof value === "string" ? Number(value) : Number(value);
15
+ if (!Number.isFinite(num)) return fallback;
16
+ const floored = Math.floor(num);
17
+ return floored >= 0 ? floored : fallback;
18
+ }
19
+ function trimmedStringOr(value, fallback) {
20
+ return typeof value === "string" && value.trim() ? value.trim() : fallback;
21
+ }
22
+ function optionalTrimmedString(value) {
23
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
24
+ }
12
25
  /**
13
- * Dreaming config resolver.
26
+ * Resolve the full three-phase dreaming config from the app Config.
14
27
  *
15
- * NOTE: This reads config through `any` so it can ship before the full schema lands.
16
- * Expected shape:
17
- * `agents.defaults.memory.dreaming.{ enabled, frequency, timezone, phases.deep.{minScore,minRecallCount,limit} }`
28
+ * Reads through `any` so it can ship independently of the schema evolution.
29
+ * Expected shape: `agents.defaults.memory.dreaming.{ enabled, frequency, timezone, phases.{light,deep,rem}.* }`
18
30
  */
19
31
  function resolveDreamingConfig(cfg) {
20
32
  const dreaming = cfg?.agents?.defaults?.memory?.dreaming;
21
33
  const enabled = dreaming?.enabled === true;
22
- const frequency = typeof dreaming?.frequency === "string" && dreaming.frequency.trim() ? dreaming.frequency.trim() : "0 3 * * *";
23
- const timezone = typeof dreaming?.timezone === "string" && dreaming.timezone.trim() ? dreaming.timezone.trim() : void 0;
24
- const deep = dreaming?.phases?.deep ?? dreaming?.deep ?? {};
25
- const deepEnabled = deep?.enabled !== false;
26
- const minScore = clampScore(Number(deep?.minScore), .8);
27
- const minRecallCount = toPositiveInt(deep?.minRecallCount, 3);
28
- const limit = toPositiveInt(deep?.limit, 10);
34
+ const frequency = trimmedStringOr(dreaming?.frequency, DEFAULT_DEEP_CRON);
35
+ const timezone = optionalTrimmedString(dreaming?.timezone);
36
+ const lightRaw = dreaming?.phases?.light ?? {};
37
+ const light = {
38
+ enabled: enabled && lightRaw?.enabled !== false,
39
+ cron: trimmedStringOr(lightRaw?.cron, DEFAULT_LIGHT_CRON),
40
+ lookbackDays: toPositiveInt(lightRaw?.lookbackDays, 2),
41
+ limit: toNonNegInt(lightRaw?.limit, 100),
42
+ dedupeSimilarity: clampScore(Number(lightRaw?.dedupeSimilarity), .9)
43
+ };
44
+ const deepRaw = dreaming?.phases?.deep ?? {};
45
+ const deep = {
46
+ enabled: enabled && deepRaw?.enabled !== false,
47
+ cron: trimmedStringOr(deepRaw?.cron, frequency),
48
+ minScore: clampScore(Number(deepRaw?.minScore), .8),
49
+ minRecallCount: toPositiveInt(deepRaw?.minRecallCount, 3),
50
+ minUniqueQueries: toPositiveInt(deepRaw?.minUniqueQueries, 3),
51
+ limit: toNonNegInt(deepRaw?.limit, 10),
52
+ recencyHalfLifeDays: toPositiveInt(deepRaw?.recencyHalfLifeDays, 14),
53
+ maxAgeDays: toPositiveInt(deepRaw?.maxAgeDays, 30)
54
+ };
55
+ const remRaw = dreaming?.phases?.rem ?? {};
56
+ const rem = {
57
+ enabled: enabled && remRaw?.enabled !== false,
58
+ cron: trimmedStringOr(remRaw?.cron, DEFAULT_REM_CRON),
59
+ lookbackDays: toPositiveInt(remRaw?.lookbackDays, 7),
60
+ limit: toNonNegInt(remRaw?.limit, 10),
61
+ minPatternStrength: clampScore(Number(remRaw?.minPatternStrength), .75)
62
+ };
29
63
  return {
30
64
  enabled,
31
65
  frequency,
32
66
  ...timezone ? { timezone } : {},
33
- deep: {
34
- enabled: enabled && deepEnabled,
35
- minScore,
36
- minRecallCount,
37
- limit
38
- }
67
+ phases: {
68
+ light,
69
+ deep,
70
+ rem
71
+ },
72
+ deep
39
73
  };
40
74
  }
75
+ /** Get the cron expression for a specific phase from resolved config. */
76
+ function getPhaseCron(config, phase) {
77
+ return config.phases[phase].cron;
78
+ }
79
+ /** Check if a specific phase is enabled (global + phase-level). */
80
+ function isPhaseEnabled(config, phase) {
81
+ return config.enabled && config.phases[phase].enabled;
82
+ }
41
83
  //#endregion
42
- export { resolveDreamingConfig };
84
+ export { getPhaseCron, isPhaseEnabled, resolveDreamingConfig };
43
85
 
44
86
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":["anyCfg"],"sources":["../../../../../src/agent/memory/dreaming/config.ts"],"sourcesContent":["import type { Config } from '../../../config/schema.js';\n\nexport type DreamingResolvedConfig = {\n enabled: boolean;\n frequency: string;\n timezone?: string;\n deep: {\n enabled: boolean;\n minScore: number;\n minRecallCount: number;\n limit: number;\n };\n};\n\nfunction clampScore(value: number, fallback: number): number {\n if (!Number.isFinite(value)) return fallback;\n return Math.max(0, Math.min(1, value));\n}\n\nfunction toPositiveInt(value: unknown, fallback: number): number {\n const num = typeof value === 'string' ? Number(value) : Number(value);\n if (!Number.isFinite(num)) return fallback;\n const floored = Math.floor(num);\n return floored > 0 ? floored : fallback;\n}\n\n/**\n * Dreaming config resolver.\n *\n * NOTE: This reads config through `any` so it can ship before the full schema lands.\n * Expected shape:\n * `agents.defaults.memory.dreaming.{ enabled, frequency, timezone, phases.deep.{minScore,minRecallCount,limit} }`\n */\nexport function resolveDreamingConfig(cfg: Config | undefined): DreamingResolvedConfig {\n const anyCfg = cfg as any;\n const dreaming = anyCfg?.agents?.defaults?.memory?.dreaming;\n const enabled = dreaming?.enabled === true;\n\n const frequency =\n typeof dreaming?.frequency === 'string' && dreaming.frequency.trim()\n ? dreaming.frequency.trim()\n : '0 3 * * *';\n const timezone =\n typeof dreaming?.timezone === 'string' && dreaming.timezone.trim()\n ? dreaming.timezone.trim()\n : undefined;\n\n const deep = dreaming?.phases?.deep ?? dreaming?.deep ?? {};\n const deepEnabled = deep?.enabled !== false;\n const minScore = clampScore(Number(deep?.minScore), 0.8);\n const minRecallCount = toPositiveInt(deep?.minRecallCount, 3);\n const limit = toPositiveInt(deep?.limit, 10);\n\n return {\n enabled,\n frequency,\n ...(timezone ? { timezone } : {}),\n deep: {\n enabled: enabled && deepEnabled,\n minScore,\n minRecallCount,\n limit,\n },\n };\n}\n\n"],"mappings":";AAcA,SAAS,WAAW,OAAe,UAA0B;AAC3D,KAAI,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO;AACpC,QAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;;AAGxC,SAAS,cAAc,OAAgB,UAA0B;CAC/D,MAAM,MAAM,OAAO,UAAU,WAAW,OAAO,MAAM,GAAG,OAAO,MAAM;AACrE,KAAI,CAAC,OAAO,SAAS,IAAI,CAAE,QAAO;CAClC,MAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,QAAO,UAAU,IAAI,UAAU;;;;;;;;;AAUjC,SAAgB,sBAAsB,KAAiD;CAErF,MAAM,WAAWA,KAAQ,QAAQ,UAAU,QAAQ;CACnD,MAAM,UAAU,UAAU,YAAY;CAEtC,MAAM,YACJ,OAAO,UAAU,cAAc,YAAY,SAAS,UAAU,MAAM,GAChE,SAAS,UAAU,MAAM,GACzB;CACN,MAAM,WACJ,OAAO,UAAU,aAAa,YAAY,SAAS,SAAS,MAAM,GAC9D,SAAS,SAAS,MAAM,GACxB,KAAA;CAEN,MAAM,OAAO,UAAU,QAAQ,QAAQ,UAAU,QAAQ,EAAE;CAC3D,MAAM,cAAc,MAAM,YAAY;CACtC,MAAM,WAAW,WAAW,OAAO,MAAM,SAAS,EAAE,GAAI;CACxD,MAAM,iBAAiB,cAAc,MAAM,gBAAgB,EAAE;CAC7D,MAAM,QAAQ,cAAc,MAAM,OAAO,GAAG;AAE5C,QAAO;EACL;EACA;EACA,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;EAChC,MAAM;GACJ,SAAS,WAAW;GACpB;GACA;GACA;GACD;EACF"}
1
+ {"version":3,"file":"config.js","names":["anyCfg"],"sources":["../../../../../src/agent/memory/dreaming/config.ts"],"sourcesContent":["import type { Config } from '../../../config/schema.js';\nimport {\n DEFAULT_DEEP_CRON,\n DEFAULT_LIGHT_CRON,\n DEFAULT_MAX_AGE_DAYS,\n DEFAULT_RECENCY_HALF_LIFE_DAYS,\n DEFAULT_REM_CRON,\n type DreamingPhaseId,\n} from './constants.js';\n\n// ── Phase config types ─────────────────────────────────────────────────\n\nexport type DreamingLightConfig = {\n enabled: boolean;\n cron: string;\n lookbackDays: number;\n limit: number;\n dedupeSimilarity: number;\n};\n\nexport type DreamingDeepConfig = {\n enabled: boolean;\n cron: string;\n minScore: number;\n minRecallCount: number;\n minUniqueQueries: number;\n limit: number;\n recencyHalfLifeDays: number;\n maxAgeDays: number;\n};\n\nexport type DreamingRemConfig = {\n enabled: boolean;\n cron: string;\n lookbackDays: number;\n limit: number;\n minPatternStrength: number;\n};\n\nexport type DreamingResolvedConfig = {\n enabled: boolean;\n frequency: string;\n timezone?: string;\n phases: {\n light: DreamingLightConfig;\n deep: DreamingDeepConfig;\n rem: DreamingRemConfig;\n };\n deep: DreamingDeepConfig;\n};\n\n// ── Helpers ────────────────────────────────────────────────────────────\n\nfunction clampScore(value: number, fallback: number): number {\n if (!Number.isFinite(value)) return fallback;\n return Math.max(0, Math.min(1, value));\n}\n\nfunction toPositiveInt(value: unknown, fallback: number): number {\n const num = typeof value === 'string' ? Number(value) : Number(value);\n if (!Number.isFinite(num)) return fallback;\n const floored = Math.floor(num);\n return floored > 0 ? floored : fallback;\n}\n\nfunction toNonNegInt(value: unknown, fallback: number): number {\n const num = typeof value === 'string' ? Number(value) : Number(value);\n if (!Number.isFinite(num)) return fallback;\n const floored = Math.floor(num);\n return floored >= 0 ? floored : fallback;\n}\n\nfunction trimmedStringOr(value: unknown, fallback: string): string {\n return typeof value === 'string' && value.trim() ? value.trim() : fallback;\n}\n\nfunction optionalTrimmedString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\n// ── Resolver ───────────────────────────────────────────────────────────\n\n/**\n * Resolve the full three-phase dreaming config from the app Config.\n *\n * Reads through `any` so it can ship independently of the schema evolution.\n * Expected shape: `agents.defaults.memory.dreaming.{ enabled, frequency, timezone, phases.{light,deep,rem}.* }`\n */\nexport function resolveDreamingConfig(cfg: Config | undefined): DreamingResolvedConfig {\n const anyCfg = cfg as any;\n const dreaming = anyCfg?.agents?.defaults?.memory?.dreaming;\n const enabled = dreaming?.enabled === true;\n\n const frequency = trimmedStringOr(dreaming?.frequency, DEFAULT_DEEP_CRON);\n const timezone = optionalTrimmedString(dreaming?.timezone);\n\n // ── Light phase ────────────────────────────────────────────────────\n const lightRaw = dreaming?.phases?.light ?? {};\n const light: DreamingLightConfig = {\n enabled: enabled && lightRaw?.enabled !== false,\n cron: trimmedStringOr(lightRaw?.cron, DEFAULT_LIGHT_CRON),\n lookbackDays: toPositiveInt(lightRaw?.lookbackDays, 2),\n limit: toNonNegInt(lightRaw?.limit, 100),\n dedupeSimilarity: clampScore(Number(lightRaw?.dedupeSimilarity), 0.9),\n };\n\n // ── Deep phase ─────────────────────────────────────────────────────\n const deepRaw = dreaming?.phases?.deep ?? {};\n const deep: DreamingDeepConfig = {\n enabled: enabled && deepRaw?.enabled !== false,\n cron: trimmedStringOr(deepRaw?.cron, frequency),\n minScore: clampScore(Number(deepRaw?.minScore), 0.8),\n minRecallCount: toPositiveInt(deepRaw?.minRecallCount, 3),\n minUniqueQueries: toPositiveInt(deepRaw?.minUniqueQueries, 3),\n limit: toNonNegInt(deepRaw?.limit, 10),\n recencyHalfLifeDays: toPositiveInt(deepRaw?.recencyHalfLifeDays, DEFAULT_RECENCY_HALF_LIFE_DAYS),\n maxAgeDays: toPositiveInt(deepRaw?.maxAgeDays, DEFAULT_MAX_AGE_DAYS),\n };\n\n // ── REM phase ──────────────────────────────────────────────────────\n const remRaw = dreaming?.phases?.rem ?? {};\n const rem: DreamingRemConfig = {\n enabled: enabled && remRaw?.enabled !== false,\n cron: trimmedStringOr(remRaw?.cron, DEFAULT_REM_CRON),\n lookbackDays: toPositiveInt(remRaw?.lookbackDays, 7),\n limit: toNonNegInt(remRaw?.limit, 10),\n minPatternStrength: clampScore(Number(remRaw?.minPatternStrength), 0.75),\n };\n\n return {\n enabled,\n frequency,\n ...(timezone ? { timezone } : {}),\n phases: { light, deep, rem },\n deep,\n };\n}\n\n/** Get the cron expression for a specific phase from resolved config. */\nexport function getPhaseCron(config: DreamingResolvedConfig, phase: DreamingPhaseId): string {\n return config.phases[phase].cron;\n}\n\n/** Check if a specific phase is enabled (global + phase-level). */\nexport function isPhaseEnabled(config: DreamingResolvedConfig, phase: DreamingPhaseId): boolean {\n return config.enabled && config.phases[phase].enabled;\n}\n\n"],"mappings":";;AAqDA,SAAS,WAAW,OAAe,UAA0B;AAC3D,KAAI,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO;AACpC,QAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;;AAGxC,SAAS,cAAc,OAAgB,UAA0B;CAC/D,MAAM,MAAM,OAAO,UAAU,WAAW,OAAO,MAAM,GAAG,OAAO,MAAM;AACrE,KAAI,CAAC,OAAO,SAAS,IAAI,CAAE,QAAO;CAClC,MAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,QAAO,UAAU,IAAI,UAAU;;AAGjC,SAAS,YAAY,OAAgB,UAA0B;CAC7D,MAAM,MAAM,OAAO,UAAU,WAAW,OAAO,MAAM,GAAG,OAAO,MAAM;AACrE,KAAI,CAAC,OAAO,SAAS,IAAI,CAAE,QAAO;CAClC,MAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,QAAO,WAAW,IAAI,UAAU;;AAGlC,SAAS,gBAAgB,OAAgB,UAA0B;AACjE,QAAO,OAAO,UAAU,YAAY,MAAM,MAAM,GAAG,MAAM,MAAM,GAAG;;AAGpE,SAAS,sBAAsB,OAAoC;AACjE,QAAO,OAAO,UAAU,YAAY,MAAM,MAAM,GAAG,MAAM,MAAM,GAAG,KAAA;;;;;;;;AAWpE,SAAgB,sBAAsB,KAAiD;CAErF,MAAM,WAAWA,KAAQ,QAAQ,UAAU,QAAQ;CACnD,MAAM,UAAU,UAAU,YAAY;CAEtC,MAAM,YAAY,gBAAgB,UAAU,WAAW,kBAAkB;CACzE,MAAM,WAAW,sBAAsB,UAAU,SAAS;CAG1D,MAAM,WAAW,UAAU,QAAQ,SAAS,EAAE;CAC9C,MAAM,QAA6B;EACjC,SAAS,WAAW,UAAU,YAAY;EAC1C,MAAM,gBAAgB,UAAU,MAAM,mBAAmB;EACzD,cAAc,cAAc,UAAU,cAAc,EAAE;EACtD,OAAO,YAAY,UAAU,OAAO,IAAI;EACxC,kBAAkB,WAAW,OAAO,UAAU,iBAAiB,EAAE,GAAI;EACtE;CAGD,MAAM,UAAU,UAAU,QAAQ,QAAQ,EAAE;CAC5C,MAAM,OAA2B;EAC/B,SAAS,WAAW,SAAS,YAAY;EACzC,MAAM,gBAAgB,SAAS,MAAM,UAAU;EAC/C,UAAU,WAAW,OAAO,SAAS,SAAS,EAAE,GAAI;EACpD,gBAAgB,cAAc,SAAS,gBAAgB,EAAE;EACzD,kBAAkB,cAAc,SAAS,kBAAkB,EAAE;EAC7D,OAAO,YAAY,SAAS,OAAO,GAAG;EACtC,qBAAqB,cAAc,SAAS,qBAAA,GAAoD;EAChG,YAAY,cAAc,SAAS,YAAA,GAAiC;EACrE;CAGD,MAAM,SAAS,UAAU,QAAQ,OAAO,EAAE;CAC1C,MAAM,MAAyB;EAC7B,SAAS,WAAW,QAAQ,YAAY;EACxC,MAAM,gBAAgB,QAAQ,MAAM,iBAAiB;EACrD,cAAc,cAAc,QAAQ,cAAc,EAAE;EACpD,OAAO,YAAY,QAAQ,OAAO,GAAG;EACrC,oBAAoB,WAAW,OAAO,QAAQ,mBAAmB,EAAE,IAAK;EACzE;AAED,QAAO;EACL;EACA;EACA,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;EAChC,QAAQ;GAAE;GAAO;GAAM;GAAK;EAC5B;EACD;;;AAIH,SAAgB,aAAa,QAAgC,OAAgC;AAC3F,QAAO,OAAO,OAAO,OAAO;;;AAI9B,SAAgB,eAAe,QAAgC,OAAiC;AAC9F,QAAO,OAAO,WAAW,OAAO,OAAO,OAAO"}
@@ -1,8 +1,29 @@
1
+ export type DreamingPhaseId = 'light' | 'deep' | 'rem';
2
+ export declare const DREAMING_PHASES: readonly DreamingPhaseId[];
1
3
  export declare const DREAMING_SWEEP_TOKEN = "__xopc_memory_dreaming_sweep__";
2
- export declare const DREAMING_CRON_NAME = "Memory Dreaming - Deep Promotion";
4
+ export declare const DREAMING_LIGHT_SWEEP_TOKEN = "__xopc_memory_dreaming_light_sweep__";
5
+ export declare const DREAMING_REM_SWEEP_TOKEN = "__xopc_memory_dreaming_rem_sweep__";
3
6
  export declare const DREAMING_CRON_TAG = "[managed-by=xopc.memory.dreaming]";
7
+ export declare const DREAMING_CRON_NAME = "Memory Dreaming - Deep Promotion";
8
+ export declare const DREAMING_LIGHT_CRON_NAME = "Memory Dreaming - Light Sweep";
9
+ export declare const DREAMING_REM_CRON_NAME = "Memory Dreaming - REM Patterns";
10
+ export declare const DEFAULT_DEEP_CRON = "0 3 * * *";
11
+ export declare const DEFAULT_LIGHT_CRON = "0 */6 * * *";
12
+ export declare const DEFAULT_REM_CRON = "0 5 * * 0";
13
+ export declare const DEFAULT_RECENCY_HALF_LIFE_DAYS = 14;
14
+ export declare const DEFAULT_MAX_AGE_DAYS = 30;
15
+ /** Milliseconds in one day (used for time-decay calculations). */
16
+ export declare const MS_PER_DAY = 86400000;
17
+ /** Weight applied to recall-count reinforcement (logarithmic boost). */
18
+ export declare const REINFORCEMENT_WEIGHT = 0.12;
19
+ /** Weight applied to signal-diversity bonus. */
20
+ export declare const DIVERSITY_WEIGHT = 0.08;
21
+ /** Number of signal dimensions used for diversity calculation. */
22
+ export declare const DIVERSITY_DIMENSION_COUNT = 4;
4
23
  export declare const DREAMING_DIR_RELATIVE: string;
5
24
  export declare const SHORT_TERM_RECALL_STORE_RELATIVE: string;
6
25
  export declare const SHORT_TERM_PROMOTION_LOCK_RELATIVE: string;
7
26
  export declare const DREAMING_LAST_RUN_RELATIVE: string;
27
+ export declare const DREAMING_EVENTS_LOG_RELATIVE: string;
8
28
  export declare const MEMORY_MD_FILENAME = "MEMORY.md";
29
+ export declare const DREAMS_MD_FILENAME = "DREAMS.md";
@@ -1,14 +1,38 @@
1
1
  import path from "node:path";
2
2
  //#region src/agent/memory/dreaming/constants.ts
3
+ const DREAMING_PHASES = [
4
+ "light",
5
+ "deep",
6
+ "rem"
7
+ ];
3
8
  const DREAMING_SWEEP_TOKEN = "__xopc_memory_dreaming_sweep__";
4
- const DREAMING_CRON_NAME = "Memory Dreaming - Deep Promotion";
9
+ const DREAMING_LIGHT_SWEEP_TOKEN = "__xopc_memory_dreaming_light_sweep__";
10
+ const DREAMING_REM_SWEEP_TOKEN = "__xopc_memory_dreaming_rem_sweep__";
5
11
  const DREAMING_CRON_TAG = "[managed-by=xopc.memory.dreaming]";
12
+ const DREAMING_CRON_NAME = "Memory Dreaming - Deep Promotion";
13
+ const DREAMING_LIGHT_CRON_NAME = "Memory Dreaming - Light Sweep";
14
+ const DREAMING_REM_CRON_NAME = "Memory Dreaming - REM Patterns";
15
+ const DEFAULT_DEEP_CRON = "0 3 * * *";
16
+ const DEFAULT_LIGHT_CRON = "0 */6 * * *";
17
+ const DEFAULT_REM_CRON = "0 5 * * 0";
18
+ const DEFAULT_RECENCY_HALF_LIFE_DAYS = 14;
19
+ const DEFAULT_MAX_AGE_DAYS = 30;
20
+ /** Milliseconds in one day (used for time-decay calculations). */
21
+ const MS_PER_DAY = 864e5;
22
+ /** Weight applied to recall-count reinforcement (logarithmic boost). */
23
+ const REINFORCEMENT_WEIGHT = .12;
24
+ /** Weight applied to signal-diversity bonus. */
25
+ const DIVERSITY_WEIGHT = .08;
26
+ /** Number of signal dimensions used for diversity calculation. */
27
+ const DIVERSITY_DIMENSION_COUNT = 4;
6
28
  const DREAMING_DIR_RELATIVE = path.join("memory", ".dreams");
7
29
  const SHORT_TERM_RECALL_STORE_RELATIVE = path.join(DREAMING_DIR_RELATIVE, "short-term-recall.json");
8
30
  const SHORT_TERM_PROMOTION_LOCK_RELATIVE = path.join(DREAMING_DIR_RELATIVE, "short-term-promotion.lock");
9
31
  const DREAMING_LAST_RUN_RELATIVE = path.join(DREAMING_DIR_RELATIVE, "last-run.json");
32
+ const DREAMING_EVENTS_LOG_RELATIVE = path.join(DREAMING_DIR_RELATIVE, "events.jsonl");
10
33
  const MEMORY_MD_FILENAME = "MEMORY.md";
34
+ const DREAMS_MD_FILENAME = "DREAMS.md";
11
35
  //#endregion
12
- export { DREAMING_CRON_NAME, DREAMING_CRON_TAG, DREAMING_DIR_RELATIVE, DREAMING_LAST_RUN_RELATIVE, DREAMING_SWEEP_TOKEN, MEMORY_MD_FILENAME, SHORT_TERM_PROMOTION_LOCK_RELATIVE, SHORT_TERM_RECALL_STORE_RELATIVE };
36
+ export { DEFAULT_DEEP_CRON, DEFAULT_LIGHT_CRON, DEFAULT_MAX_AGE_DAYS, DEFAULT_RECENCY_HALF_LIFE_DAYS, DEFAULT_REM_CRON, DIVERSITY_DIMENSION_COUNT, DIVERSITY_WEIGHT, DREAMING_CRON_NAME, DREAMING_CRON_TAG, DREAMING_DIR_RELATIVE, DREAMING_EVENTS_LOG_RELATIVE, DREAMING_LAST_RUN_RELATIVE, DREAMING_LIGHT_CRON_NAME, DREAMING_LIGHT_SWEEP_TOKEN, DREAMING_PHASES, DREAMING_REM_CRON_NAME, DREAMING_REM_SWEEP_TOKEN, DREAMING_SWEEP_TOKEN, DREAMS_MD_FILENAME, MEMORY_MD_FILENAME, MS_PER_DAY, REINFORCEMENT_WEIGHT, SHORT_TERM_PROMOTION_LOCK_RELATIVE, SHORT_TERM_RECALL_STORE_RELATIVE };
13
37
 
14
38
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/constants.ts"],"sourcesContent":["import path from 'node:path';\n\nexport const DREAMING_SWEEP_TOKEN = '__xopc_memory_dreaming_sweep__';\n\nexport const DREAMING_CRON_NAME = 'Memory Dreaming - Deep Promotion';\nexport const DREAMING_CRON_TAG = '[managed-by=xopc.memory.dreaming]';\n\nexport const DREAMING_DIR_RELATIVE = path.join('memory', '.dreams');\nexport const SHORT_TERM_RECALL_STORE_RELATIVE = path.join(DREAMING_DIR_RELATIVE, 'short-term-recall.json');\nexport const SHORT_TERM_PROMOTION_LOCK_RELATIVE = path.join(\n DREAMING_DIR_RELATIVE,\n 'short-term-promotion.lock',\n);\nexport const DREAMING_LAST_RUN_RELATIVE = path.join(DREAMING_DIR_RELATIVE, 'last-run.json');\n\nexport const MEMORY_MD_FILENAME = 'MEMORY.md';\n\n"],"mappings":";;AAEA,MAAa,uBAAuB;AAEpC,MAAa,qBAAqB;AAClC,MAAa,oBAAoB;AAEjC,MAAa,wBAAwB,KAAK,KAAK,UAAU,UAAU;AACnE,MAAa,mCAAmC,KAAK,KAAK,uBAAuB,yBAAyB;AAC1G,MAAa,qCAAqC,KAAK,KACrD,uBACA,4BACD;AACD,MAAa,6BAA6B,KAAK,KAAK,uBAAuB,gBAAgB;AAE3F,MAAa,qBAAqB"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/constants.ts"],"sourcesContent":["import path from 'node:path';\n\n// ── Phase identifiers ──────────────────────────────────────────────────\n\nexport type DreamingPhaseId = 'light' | 'deep' | 'rem';\n\nexport const DREAMING_PHASES: readonly DreamingPhaseId[] = ['light', 'deep', 'rem'] as const;\n\n// ── Sweep tokens (used in cron payloads to trigger each phase) ─────────\n\nexport const DREAMING_SWEEP_TOKEN = '__xopc_memory_dreaming_sweep__';\nexport const DREAMING_LIGHT_SWEEP_TOKEN = '__xopc_memory_dreaming_light_sweep__';\nexport const DREAMING_REM_SWEEP_TOKEN = '__xopc_memory_dreaming_rem_sweep__';\n\n// ── Cron job metadata ──────────────────────────────────────────────────\n\nexport const DREAMING_CRON_TAG = '[managed-by=xopc.memory.dreaming]';\n\nexport const DREAMING_CRON_NAME = 'Memory Dreaming - Deep Promotion';\nexport const DREAMING_LIGHT_CRON_NAME = 'Memory Dreaming - Light Sweep';\nexport const DREAMING_REM_CRON_NAME = 'Memory Dreaming - REM Patterns';\n\n// ── Default cron schedules ─────────────────────────────────────────────\n\nexport const DEFAULT_DEEP_CRON = '0 3 * * *';\nexport const DEFAULT_LIGHT_CRON = '0 */6 * * *';\nexport const DEFAULT_REM_CRON = '0 5 * * 0';\n\n// ── Time-decay defaults ────────────────────────────────────────────────\n\nexport const DEFAULT_RECENCY_HALF_LIFE_DAYS = 14;\nexport const DEFAULT_MAX_AGE_DAYS = 30;\n\n// ── Scoring weights ────────────────────────────────────────────────────\n\n/** Milliseconds in one day (used for time-decay calculations). */\nexport const MS_PER_DAY = 86_400_000;\n\n/** Weight applied to recall-count reinforcement (logarithmic boost). */\nexport const REINFORCEMENT_WEIGHT = 0.12;\n\n/** Weight applied to signal-diversity bonus. */\nexport const DIVERSITY_WEIGHT = 0.08;\n\n/** Number of signal dimensions used for diversity calculation. */\nexport const DIVERSITY_DIMENSION_COUNT = 4;\n\n// ── File paths ─────────────────────────────────────────────────────────\n\nexport const DREAMING_DIR_RELATIVE = path.join('memory', '.dreams');\nexport const SHORT_TERM_RECALL_STORE_RELATIVE = path.join(DREAMING_DIR_RELATIVE, 'short-term-recall.json');\nexport const SHORT_TERM_PROMOTION_LOCK_RELATIVE = path.join(\n DREAMING_DIR_RELATIVE,\n 'short-term-promotion.lock',\n);\nexport const DREAMING_LAST_RUN_RELATIVE = path.join(DREAMING_DIR_RELATIVE, 'last-run.json');\nexport const DREAMING_EVENTS_LOG_RELATIVE = path.join(DREAMING_DIR_RELATIVE, 'events.jsonl');\n\nexport const MEMORY_MD_FILENAME = 'MEMORY.md';\nexport const DREAMS_MD_FILENAME = 'DREAMS.md';\n\n"],"mappings":";;AAMA,MAAa,kBAA8C;CAAC;CAAS;CAAQ;CAAM;AAInF,MAAa,uBAAuB;AACpC,MAAa,6BAA6B;AAC1C,MAAa,2BAA2B;AAIxC,MAAa,oBAAoB;AAEjC,MAAa,qBAAqB;AAClC,MAAa,2BAA2B;AACxC,MAAa,yBAAyB;AAItC,MAAa,oBAAoB;AACjC,MAAa,qBAAqB;AAClC,MAAa,mBAAmB;AAIhC,MAAa,iCAAiC;AAC9C,MAAa,uBAAuB;;AAKpC,MAAa,aAAa;;AAG1B,MAAa,uBAAuB;;AAGpC,MAAa,mBAAmB;;AAGhC,MAAa,4BAA4B;AAIzC,MAAa,wBAAwB,KAAK,KAAK,UAAU,UAAU;AACnE,MAAa,mCAAmC,KAAK,KAAK,uBAAuB,yBAAyB;AAC1G,MAAa,qCAAqC,KAAK,KACrD,uBACA,4BACD;AACD,MAAa,6BAA6B,KAAK,KAAK,uBAAuB,gBAAgB;AAC3F,MAAa,+BAA+B,KAAK,KAAK,uBAAuB,eAAe;AAE5F,MAAa,qBAAqB;AAClC,MAAa,qBAAqB"}
@@ -1,13 +1,12 @@
1
1
  import { type DreamingStoreEntry } from './short-term-store.js';
2
- export type DreamingDeepConfig = {
3
- enabled: boolean;
4
- minScore: number;
5
- minRecallCount: number;
6
- limit: number;
7
- };
2
+ import type { DreamingDeepConfig } from './config.js';
3
+ export type { DreamingDeepConfig } from './config.js';
8
4
  export type DreamingPromotionCandidate = DreamingStoreEntry & {
9
5
  avgScore: number;
6
+ /** Time-decay-adjusted final score used for ranking. */
10
7
  score: number;
8
+ /** Raw recency decay multiplier (0–1). */
9
+ recencyDecay: number;
11
10
  };
12
11
  export declare function runDreamingDeepPromotion(params: {
13
12
  workspaceDir: string;
@@ -1,92 +1,17 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
- import { DREAMING_LAST_RUN_RELATIVE, MEMORY_MD_FILENAME } from "./constants.js";
3
+ import { MEMORY_MD_FILENAME } from "./constants.js";
4
+ import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, isoDay, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
4
5
  import { loadDreamingStore, saveDreamingStore, withDreamingPromotionLock } from "./short-term-store.js";
6
+ import { emptyDeepPhaseSkipped, writeDreamingDeepLastRun } from "./last-run.js";
5
7
  import path from "node:path";
6
8
  import fs from "node:fs/promises";
7
- import { createHash } from "node:crypto";
8
9
  //#region src/agent/memory/dreaming/deep-promotion.ts
9
10
  init_logger();
10
11
  const log = createLogger("Dreaming:Deep");
11
- function clampScore(value) {
12
- if (!Number.isFinite(value)) return 0;
13
- return Math.max(0, Math.min(1, value));
14
- }
15
- function formatIsoDay(now) {
16
- return now.toISOString().slice(0, 10);
17
- }
18
- function compareCandidates(a, b) {
19
- if (b.score !== a.score) return b.score - a.score;
20
- if (b.recallCount !== a.recallCount) return b.recallCount - a.recallCount;
21
- const aMs = Date.parse(a.lastRecalledAt);
22
- const bMs = Date.parse(b.lastRecalledAt);
23
- if (Number.isFinite(aMs) || Number.isFinite(bMs)) {
24
- if (bMs !== aMs) return bMs - aMs;
25
- }
26
- return a.path.localeCompare(b.path);
27
- }
28
- function normalizeSnippetForHash(snippet) {
29
- return snippet.trim().replace(/\s+/g, " ").replace(/[“”]/g, "\"").replace(/[‘’]/g, "'").toLowerCase().slice(0, 512);
30
- }
31
- function snippetHash(snippet) {
32
- const normalized = normalizeSnippetForHash(snippet);
33
- return createHash("sha1").update(normalized).digest("hex").slice(0, 12);
34
- }
35
12
  function markerForPromotion(key, hash) {
36
13
  return `<!-- xopc-memory-promotion key="${key}" hash="${hash}" -->`;
37
14
  }
38
- function extractPromotionMarkers(memoryText) {
39
- const keys = /* @__PURE__ */ new Set();
40
- const hashes = /* @__PURE__ */ new Set();
41
- for (const match of memoryText.matchAll(/<!--\s*xopc-memory-promotion\b([\s\S]*?)-->/gi)) {
42
- const body = match[1] ?? "";
43
- const k = body.match(/\bkey\s*=\s*"([^"]+)"/i)?.[1]?.trim();
44
- const h = body.match(/\bhash\s*=\s*"([^"]+)"/i)?.[1]?.trim();
45
- if (k) keys.add(k);
46
- if (h) hashes.add(h);
47
- }
48
- for (const match of memoryText.matchAll(/<!--\s*xopc-memory-promotion:([^\n]+?)\s*-->/gi)) {
49
- const key = match[1]?.trim();
50
- if (key) keys.add(key);
51
- }
52
- return {
53
- keys,
54
- hashes
55
- };
56
- }
57
- function isContaminatedSnippet(snippet) {
58
- const s = snippet.trim();
59
- if (!s) return true;
60
- const lower = s.toLowerCase();
61
- if ([
62
- /\b(system|assistant|tool)\s*:/i,
63
- /<\s*(system|assistant|tool)\b/i,
64
- /<!--\s*xopc-memory-promotion\b/i,
65
- /tool_call_id|toolcallid|function_call|arguments\s*:\s*\{/i,
66
- /"tool"\s*:\s*|\btool_name\b|\btool\b\s*results?/i,
67
- /you are (an|a)\s+(ai|assistant)|follow these instructions/i,
68
- /begin\s+(system prompt|instructions)|end\s+(system prompt|instructions)/i,
69
- /```/i,
70
- /\b__xopc_/i
71
- ].some((p) => p.test(s))) return true;
72
- if ((s.match(/[{}[\]]/g) ?? []).length >= 12) return true;
73
- if ((lower.match(/https?:\/\//g) ?? []).length >= 3) return true;
74
- return false;
75
- }
76
- async function readFileLines(fullPath) {
77
- try {
78
- return (await fs.readFile(fullPath, "utf-8")).split(/\r?\n/);
79
- } catch (err) {
80
- if (err?.code === "ENOENT") return null;
81
- throw err;
82
- }
83
- }
84
- function sliceRange(lines, startLine, endLine) {
85
- const startIdx = Math.max(0, startLine - 1);
86
- const endIdx = Math.min(lines.length, endLine);
87
- if (startIdx >= endIdx) return "";
88
- return lines.slice(startIdx, endIdx).map((l) => l.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim().slice(0, 360);
89
- }
90
15
  async function rehydrateSnippet(params) {
91
16
  const lines = await readFileLines(path.join(params.workspaceDir, params.candidate.path));
92
17
  if (!lines) return null;
@@ -100,76 +25,55 @@ async function rehydrateSnippet(params) {
100
25
  endLine
101
26
  };
102
27
  }
103
- function resolveDefaultConfig(overrides) {
104
- const enabled = overrides?.enabled === true;
105
- const minScore = typeof overrides?.minScore === "number" ? overrides.minScore : .8;
106
- const minRecallCount = typeof overrides?.minRecallCount === "number" ? overrides.minRecallCount : 3;
107
- const limit = typeof overrides?.limit === "number" ? overrides.limit : 10;
28
+ function buildDeepLastRun(base) {
29
+ const durationMs = Math.max(0, Date.now() - base.t0);
108
30
  return {
109
- enabled,
110
- minScore: clampScore(minScore),
111
- minRecallCount: Math.max(1, Math.floor(minRecallCount)),
112
- limit: Math.max(0, Math.floor(limit))
31
+ version: 2,
32
+ phase: "deep",
33
+ runId: base.runId,
34
+ startedAt: base.startedAt,
35
+ finishedAt: base.finishedAt,
36
+ durationMs,
37
+ ok: base.ok,
38
+ reason: base.reason,
39
+ config: base.config,
40
+ memoryPath: base.memoryPath,
41
+ ...base.errorMessage ? { errorMessage: base.errorMessage } : {},
42
+ deep: base.deep
113
43
  };
114
44
  }
115
- async function writeLastRun(params) {
116
- const fullPath = path.join(params.workspaceDir, DREAMING_LAST_RUN_RELATIVE);
117
- await fs.mkdir(path.dirname(fullPath), { recursive: true });
118
- const tmp = `${fullPath}.${process.pid}.${Date.now()}.tmp`;
119
- await fs.writeFile(tmp, `${JSON.stringify(params.lastRun, null, 2)}\n`, "utf-8");
120
- await fs.rename(tmp, fullPath);
121
- }
122
45
  async function runDreamingDeepPromotion(params) {
123
- const cfg = resolveDefaultConfig(params.config);
46
+ const cfg = resolveDeepDefaults(params.config);
124
47
  const now = params.now ?? /* @__PURE__ */ new Date();
125
48
  const startedAt = now.toISOString();
126
49
  const runId = `${startedAt}:${process.pid}:${Math.random().toString(16).slice(2)}`;
127
50
  const memoryPath = path.join(params.workspaceDir, MEMORY_MD_FILENAME);
128
- if (!cfg.enabled) {
129
- const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
130
- await writeLastRun({
131
- workspaceDir: params.workspaceDir,
132
- lastRun: {
133
- version: 1,
134
- runId,
135
- startedAt,
136
- finishedAt,
137
- ok: true,
138
- reason: "dreaming mvp disabled",
139
- config: cfg,
140
- candidates: 0,
141
- applied: 0,
142
- memoryPath
143
- }
144
- }).catch(() => void 0);
145
- return {
146
- ok: true,
147
- reason: "dreaming mvp disabled",
148
- candidates: 0,
149
- applied: 0,
150
- memoryPath
151
- };
152
- }
153
- if (cfg.limit === 0) {
51
+ const t0 = Date.now();
52
+ const earlyExitReason = !cfg.enabled ? "dreaming disabled" : cfg.limit === 0 ? "dreaming limit=0" : null;
53
+ if (earlyExitReason) {
154
54
  const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
155
- await writeLastRun({
55
+ const empty = emptyDeepPhaseSkipped();
56
+ await writeDreamingDeepLastRun({
156
57
  workspaceDir: params.workspaceDir,
157
- lastRun: {
158
- version: 1,
58
+ lastRun: buildDeepLastRun({
159
59
  runId,
160
60
  startedAt,
161
61
  finishedAt,
62
+ t0,
162
63
  ok: true,
163
- reason: "dreaming mvp limit=0",
64
+ reason: earlyExitReason,
164
65
  config: cfg,
165
- candidates: 0,
166
- applied: 0,
167
- memoryPath
168
- }
66
+ memoryPath,
67
+ deep: {
68
+ candidatesRanked: 0,
69
+ applied: 0,
70
+ skipped: empty
71
+ }
72
+ })
169
73
  }).catch(() => void 0);
170
74
  return {
171
75
  ok: true,
172
- reason: "dreaming mvp limit=0",
76
+ reason: earlyExitReason,
173
77
  candidates: 0,
174
78
  applied: 0,
175
79
  memoryPath
@@ -178,27 +82,31 @@ async function runDreamingDeepPromotion(params) {
178
82
  try {
179
83
  const result = await withDreamingPromotionLock(params.workspaceDir, async () => {
180
84
  const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });
85
+ const nowMs = now.getTime();
181
86
  const ranked = Object.values(store.entries ?? {}).filter((e) => {
182
87
  if (!e || typeof e !== "object") return false;
183
88
  if (e.promotedAt) return false;
184
89
  if (!e.path || !e.path.startsWith("memory/")) return false;
185
90
  if (e.recallCount < cfg.minRecallCount) return false;
186
- return clampScore(e.recallCount > 0 ? e.totalScore / e.recallCount : 0) >= cfg.minScore;
91
+ if ((e.queryHashes?.length ?? 0) < cfg.minUniqueQueries) return false;
92
+ if (isExpiredEntry(e.lastRecalledAt, nowMs, cfg.maxAgeDays)) return false;
93
+ return clamp01(e.recallCount > 0 ? e.totalScore / e.recallCount : 0) >= cfg.minScore;
187
94
  }).map((e) => {
188
- const avgScore = e.recallCount > 0 ? clampScore(e.totalScore / e.recallCount) : 0;
189
- const score = clampScore(avgScore + clampScore(Math.log1p(e.recallCount) / Math.log1p(10)) * .12);
95
+ const { avgScore, score, recencyDecay } = computeCandidateScore(e, nowMs, cfg.recencyHalfLifeDays);
190
96
  return {
191
97
  ...e,
192
98
  avgScore,
193
- score
99
+ score,
100
+ recencyDecay
194
101
  };
195
- }).sort(compareCandidates).slice(0, cfg.limit);
102
+ }).sort(compareCandidatesByScore).slice(0, cfg.limit);
196
103
  if (ranked.length === 0) return {
197
104
  ok: true,
198
105
  reason: "no eligible candidates",
199
106
  candidates: 0,
200
107
  applied: 0,
201
- memoryPath
108
+ memoryPath,
109
+ skipped: emptyDeepPhaseSkipped()
202
110
  };
203
111
  const existing = await fs.readFile(memoryPath, "utf-8").catch((err) => {
204
112
  if (err?.code === "ENOENT") return "";
@@ -206,8 +114,10 @@ async function runDreamingDeepPromotion(params) {
206
114
  });
207
115
  const existingMarkers = extractPromotionMarkers(existing);
208
116
  const appliedCandidates = [];
117
+ const skipped = emptyDeepPhaseSkipped();
209
118
  for (const candidate of ranked) {
210
119
  if (existingMarkers.keys.has(candidate.key)) {
120
+ skipped.alreadyPromotedKey += 1;
211
121
  const entry = store.entries[candidate.key];
212
122
  if (entry && !entry.promotedAt) entry.promotedAt = now.toISOString();
213
123
  continue;
@@ -216,10 +126,17 @@ async function runDreamingDeepPromotion(params) {
216
126
  workspaceDir: params.workspaceDir,
217
127
  candidate
218
128
  });
219
- if (!rehydrated) continue;
220
- if (isContaminatedSnippet(rehydrated.snippet)) continue;
129
+ if (!rehydrated) {
130
+ skipped.rehydrateFailed += 1;
131
+ continue;
132
+ }
133
+ if (isContaminatedSnippet(rehydrated.snippet)) {
134
+ skipped.contaminated += 1;
135
+ continue;
136
+ }
221
137
  const hash = snippetHash(rehydrated.snippet);
222
138
  if (existingMarkers.hashes.has(hash)) {
139
+ skipped.hashDuplicate += 1;
223
140
  const entry = store.entries[candidate.key];
224
141
  if (entry && !entry.promotedAt) entry.promotedAt = now.toISOString();
225
142
  continue;
@@ -246,10 +163,11 @@ async function runDreamingDeepPromotion(params) {
246
163
  reason: "candidates were stale or already applied",
247
164
  candidates: ranked.length,
248
165
  applied: 0,
249
- memoryPath
166
+ memoryPath,
167
+ skipped
250
168
  };
251
169
  }
252
- const day = formatIsoDay(now);
170
+ const day = isoDay(now);
253
171
  const header = existing.trim().length > 0 ? "" : "# Long-Term Memory\n\n";
254
172
  const sectionLines = [
255
173
  "",
@@ -289,44 +207,60 @@ async function runDreamingDeepPromotion(params) {
289
207
  reason: "applied promotions",
290
208
  candidates: ranked.length,
291
209
  applied: appliedCandidates.length,
292
- memoryPath
210
+ memoryPath,
211
+ skipped
293
212
  };
294
213
  });
295
214
  const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
296
- await writeLastRun({
215
+ const empty = emptyDeepPhaseSkipped();
216
+ const resultSkipped = "skipped" in result ? result.skipped : empty;
217
+ await writeDreamingDeepLastRun({
297
218
  workspaceDir: params.workspaceDir,
298
- lastRun: {
299
- version: 1,
219
+ lastRun: buildDeepLastRun({
300
220
  runId,
301
221
  startedAt,
302
222
  finishedAt,
223
+ t0,
303
224
  ok: result.ok,
304
225
  reason: result.reason,
305
226
  config: cfg,
306
- candidates: result.candidates,
307
- applied: result.applied,
308
- memoryPath: result.memoryPath
309
- }
227
+ memoryPath: result.memoryPath,
228
+ deep: {
229
+ candidatesRanked: result.candidates,
230
+ applied: result.applied,
231
+ skipped: resultSkipped
232
+ }
233
+ })
310
234
  }).catch(() => void 0);
311
- return result;
235
+ return {
236
+ ok: result.ok,
237
+ reason: result.reason,
238
+ candidates: result.candidates,
239
+ applied: result.applied,
240
+ memoryPath: result.memoryPath
241
+ };
312
242
  } catch (err) {
313
243
  const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
314
244
  const em = err instanceof Error ? err.message : String(err);
315
- await writeLastRun({
245
+ const z = emptyDeepPhaseSkipped();
246
+ await writeDreamingDeepLastRun({
316
247
  workspaceDir: params.workspaceDir,
317
- lastRun: {
318
- version: 1,
248
+ lastRun: buildDeepLastRun({
319
249
  runId,
320
250
  startedAt,
321
251
  finishedAt,
252
+ t0,
322
253
  ok: false,
323
254
  reason: "error",
324
255
  config: cfg,
325
- candidates: 0,
326
- applied: 0,
327
256
  memoryPath,
328
- errorMessage: em
329
- }
257
+ errorMessage: em,
258
+ deep: {
259
+ candidatesRanked: 0,
260
+ applied: 0,
261
+ skipped: z
262
+ }
263
+ })
330
264
  }).catch(() => void 0);
331
265
  throw err;
332
266
  }