@xopcai/xopc 0.0.140 → 0.0.141

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 (162) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DtONoxBN.js → agent-avatar-dicebear-BRTCpm3t.js} +1 -1
  4. package/dist/gateway/static/root/assets/agents-Bd863Akz.js +2 -0
  5. package/dist/gateway/static/root/assets/{app-management-settings-panel-BRBxLECY.js → app-management-settings-panel-DaMMZBAT.js} +1 -1
  6. package/dist/gateway/static/root/assets/{appearance-settings-ChvyuSEt.js → appearance-settings-BXHThPyM.js} +1 -1
  7. package/dist/gateway/static/root/assets/{apps-page-DgHWTnjs.js → apps-page-B4omjLxa.js} +1 -1
  8. package/dist/gateway/static/root/assets/{archive-plugin-CdIoagem.js → archive-plugin-izB-4N4L.js} +1 -1
  9. package/dist/gateway/static/root/assets/{attachment-load-Ch411Kht.js → attachment-load-CJihXa5y.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automation-suggestion-card-SVq27yw2.js → automation-suggestion-card-fgtj5Gek.js} +1 -1
  11. package/dist/gateway/static/root/assets/{automations-page-CFt5Ik4q.js → automations-page-Dz2mgjIR.js} +1 -1
  12. package/dist/gateway/static/root/assets/{binary-plugins-D8cV-emn.js → binary-plugins-D3VUeG8s.js} +1 -1
  13. package/dist/gateway/static/root/assets/{block-editor-CXDkby6y.js → block-editor-KnA0sLI3.js} +1 -1
  14. package/dist/gateway/static/root/assets/{browser-settings-page-ColJPwer.js → browser-settings-page-DZZz5v_i.js} +1 -1
  15. package/dist/gateway/static/root/assets/{capability-presets-api-DLxI--Ge.js → capability-presets-api-D8rRNhc6.js} +1 -1
  16. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-DKyRbnlH.js → capability-presets-settings-panel-sCHojZr4.js} +1 -1
  17. package/dist/gateway/static/root/assets/{channel-recipient-api-DllrPmp-.js → channel-recipient-api-BWgqwC5h.js} +1 -1
  18. package/dist/gateway/static/root/assets/{channels-settings-BDLHV3Jx.js → channels-settings-UyVSnf9s.js} +1 -1
  19. package/dist/gateway/static/root/assets/channels-status-swr-CB5FzcLf.js +1 -0
  20. package/dist/gateway/static/root/assets/{connectors-page-CA752gY8.js → connectors-page-BzhHiUO4.js} +1 -1
  21. package/dist/gateway/static/root/assets/{desktop-pet-Bz9ommjr.js → desktop-pet-CzdqX001.js} +1 -1
  22. package/dist/gateway/static/root/assets/{desktop-pet-settings-BnLgxgoR.js → desktop-pet-settings-DqqUPC7G.js} +1 -1
  23. package/dist/gateway/static/root/assets/{directory-picker-path-field-DLsCwFaf.js → directory-picker-path-field-PzlO5tSM.js} +1 -1
  24. package/dist/gateway/static/root/assets/{dreaming-settings-BzkF1-XT.js → dreaming-settings-BmL54kQq.js} +1 -1
  25. package/dist/gateway/static/root/assets/{extension-debug-page-CdERvf3L.js → extension-debug-page-DcW8Ie3r.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-D1fz474Z.js → extension-page-DT5cpace.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-settings-page-DoQMkNOK.js → extension-settings-page-CbMk4GhQ.js} +1 -1
  28. package/dist/gateway/static/root/assets/{fetch-BID89uCH.js → fetch-06q5eCMA.js} +1 -1
  29. package/dist/gateway/static/root/assets/{gateway-config-api-Rygo8UAs.js → gateway-config-api-4VXUJtLz.js} +1 -1
  30. package/dist/gateway/static/root/assets/{gateway-settings-kb8KIeQL.js → gateway-settings-CdghmKHJ.js} +1 -1
  31. package/dist/gateway/static/root/assets/{gateway-startup-retry-BkrLLlpE.js → gateway-startup-retry-2f7_vsv7.js} +1 -1
  32. package/dist/gateway/static/root/assets/{goal-create-dialog-DVAHnifk.js → goal-create-dialog-CAlsM9MP.js} +1 -1
  33. package/dist/gateway/static/root/assets/{goal-detail-page-BuOEQZn_.js → goal-detail-page-CLPa4F2y.js} +1 -1
  34. package/dist/gateway/static/root/assets/{goals-config-api-BuY6-l0a.js → goals-config-api-BpuQTufF.js} +1 -1
  35. package/dist/gateway/static/root/assets/{goals-page-WV4cHvD-.js → goals-page-B2VpdzfH.js} +1 -1
  36. package/dist/gateway/static/root/assets/{goals-settings-DoH5fZWo.js → goals-settings-CW1NwxvV.js} +1 -1
  37. package/dist/gateway/static/root/assets/{heartbeat-settings-BqDs48B-.js → heartbeat-settings-C86k5tff.js} +1 -1
  38. package/dist/gateway/static/root/assets/{index-CrPRlGMg.js → index-ehajXmqL.js} +31 -31
  39. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D51yogNZ.js → keyboard-shortcuts-settings-8xwKEhui.js} +1 -1
  40. package/dist/gateway/static/root/assets/{logs-page-CL22jleU.js → logs-page-C_BMONOO.js} +1 -1
  41. package/dist/gateway/static/root/assets/{markdown-split-CSt32FWE.js → markdown-split-zS4KLNAf.js} +1 -1
  42. package/dist/gateway/static/root/assets/{media-plugins-ByItHxBj.js → media-plugins-_BgNJ9_7.js} +1 -1
  43. package/dist/gateway/static/root/assets/{messages-DbNQuFdA.js → messages-B-8CqAeX.js} +2 -2
  44. package/dist/gateway/static/root/assets/{models-hub-panel-BkV9hDc-.js → models-hub-panel-Do_cwNjF.js} +1 -1
  45. package/dist/gateway/static/root/assets/{notes-page-BK9yydrL.js → notes-page-5IdlPHaX.js} +1 -1
  46. package/dist/gateway/static/root/assets/{notes-workbench-Dd0v-hK2.js → notes-workbench-0KsRZJIZ.js} +2 -2
  47. package/dist/gateway/static/root/assets/{page-tabs-DOfMaq_L.js → page-tabs-B7sGQkgU.js} +1 -1
  48. package/dist/gateway/static/root/assets/{preview-open-alternatives-BArxASu7.js → preview-open-alternatives-D1ri4s_O.js} +1 -1
  49. package/dist/gateway/static/root/assets/{project-detail-page-DSPhB3do.js → project-detail-page-Dk2zB1gy.js} +1 -1
  50. package/dist/gateway/static/root/assets/{projects-page-C-fZk1f7.js → projects-page-CJQntm2G.js} +1 -1
  51. package/dist/gateway/static/root/assets/{remote-access-hub-BGaVc3t7.js → remote-access-hub-CHeZZg7O.js} +1 -1
  52. package/dist/gateway/static/root/assets/{save-bar-controls-BRxlkhG8.js → save-bar-controls-BClrOinh.js} +1 -1
  53. package/dist/gateway/static/root/assets/{schedule-field-BzM1iyOc.js → schedule-field-CL7YTwLV.js} +1 -1
  54. package/dist/gateway/static/root/assets/{schema-form-ChVcm0DX.js → schema-form-ww4PiIje.js} +1 -1
  55. package/dist/gateway/static/root/assets/{sessions-page-DbnzgQOP.js → sessions-page-9Hb_r0AG.js} +1 -1
  56. package/dist/gateway/static/root/assets/settings-advanced-gate-PmzVFvAv.js +1 -0
  57. package/dist/gateway/static/root/assets/{settings-collapsible-section-BcD9xrvY.js → settings-collapsible-section-D9gEEVm2.js} +1 -1
  58. package/dist/gateway/static/root/assets/{settings-form-section-Cu30CXVl.js → settings-form-section-DGeEoBkb.js} +1 -1
  59. package/dist/gateway/static/root/assets/{settings-loading-skeleton-Cfd37IYb.js → settings-loading-skeleton-BXUeMR37.js} +1 -1
  60. package/dist/gateway/static/root/assets/{settings-page-EINHyzLo.js → settings-page-C5G2klUB.js} +1 -1
  61. package/dist/gateway/static/root/assets/{settings-page-layout-C15zixct.js → settings-page-layout-CEepfbCa.js} +1 -1
  62. package/dist/gateway/static/root/assets/{setup-status-panel-Bu7SdpD4.js → setup-status-panel-oQ8OLnw3.js} +1 -1
  63. package/dist/gateway/static/root/assets/{share-preview-page-CjjAFV-v.js → share-preview-page-CXtDHMSi.js} +1 -1
  64. package/dist/gateway/static/root/assets/{shares-settings-06IYvwDt.js → shares-settings-BlNoairj.js} +1 -1
  65. package/dist/gateway/static/root/assets/skill-reload-api-BYV5x1KO.js +1 -0
  66. package/dist/gateway/static/root/assets/{skills-page-3W2-wDyO.js → skills-page-ClBcKQZP.js} +1 -1
  67. package/dist/gateway/static/root/assets/{system-settings-panel-DlQMtzPf.js → system-settings-panel-W6MBJXrr.js} +1 -1
  68. package/dist/gateway/static/root/assets/{typed-models-lib-BS1BwExE.js → typed-models-lib-BkODXN7T.js} +1 -1
  69. package/dist/gateway/static/root/assets/{use-channel-catalog-EA4hfbsP.js → use-channel-catalog-CTbwLZXc.js} +1 -1
  70. package/dist/gateway/static/root/assets/{user-profile-settings-panel-B7RCdmSp.js → user-profile-settings-panel-CeC308-E.js} +1 -1
  71. package/dist/gateway/static/root/assets/{utils-BrhEgVaa.js → utils-ZxrKHxyb.js} +1 -1
  72. package/dist/gateway/static/root/assets/{voice-api-key-field-BPn1ZEga.js → voice-api-key-field-BE57S-nS.js} +1 -1
  73. package/dist/gateway/static/root/assets/{work-item-detail-page-BQGTTsz1.js → work-item-detail-page-Di1ww5Aa.js} +1 -1
  74. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-na-N4jZ6.js → workflow-run-setup-panel-CzK84i-B.js} +1 -1
  75. package/dist/gateway/static/root/assets/{workflow-start-dialog-BZCY7N42.js → workflow-start-dialog-CtLTtNUB.js} +1 -1
  76. package/dist/gateway/static/root/assets/{workflows-page-CjeVDs4h.js → workflows-page-CZFZdua9.js} +1 -1
  77. package/dist/gateway/static/root/index.html +4 -4
  78. package/dist/package.js +1 -1
  79. package/dist/src/agent/agent-manager.js +13 -21
  80. package/dist/src/agent/agent-manager.js.map +1 -1
  81. package/dist/src/agent/background-review/run-background-review.js +1 -0
  82. package/dist/src/agent/background-review/run-background-review.js.map +1 -1
  83. package/dist/src/agent/memory/access-policy.d.ts +12 -0
  84. package/dist/src/agent/memory/access-policy.js +44 -0
  85. package/dist/src/agent/memory/access-policy.js.map +1 -0
  86. package/dist/src/agent/memory/builtin-provider.d.ts +4 -1
  87. package/dist/src/agent/memory/builtin-provider.js +51 -16
  88. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  89. package/dist/src/agent/memory/context/planner.d.ts +1 -0
  90. package/dist/src/agent/memory/context/planner.js +9 -5
  91. package/dist/src/agent/memory/context/planner.js.map +1 -1
  92. package/dist/src/agent/memory/create-memory-manager.d.ts +1 -1
  93. package/dist/src/agent/memory/create-memory-manager.js +8 -5
  94. package/dist/src/agent/memory/create-memory-manager.js.map +1 -1
  95. package/dist/src/agent/memory/dreaming/config.d.ts +2 -0
  96. package/dist/src/agent/memory/dreaming/config.js +13 -1
  97. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  98. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +2 -0
  99. package/dist/src/agent/memory/dreaming/deep-promotion.js +24 -3
  100. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  101. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -0
  102. package/dist/src/agent/memory/dreaming/light-sweep.js +184 -16
  103. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  104. package/dist/src/agent/memory/dreaming/promotion-lifecycle.d.ts +30 -0
  105. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js +85 -0
  106. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js.map +1 -0
  107. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +4 -0
  108. package/dist/src/agent/memory/dreaming/rem-patterns.js +76 -53
  109. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  110. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +10 -0
  111. package/dist/src/agent/memory/dreaming/short-term-store.js +157 -79
  112. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  113. package/dist/src/agent/memory/manager.d.ts +7 -0
  114. package/dist/src/agent/memory/manager.js +31 -6
  115. package/dist/src/agent/memory/manager.js.map +1 -1
  116. package/dist/src/agent/memory/memory-config.d.ts +1 -1
  117. package/dist/src/agent/memory/memory-config.js +3 -3
  118. package/dist/src/agent/memory/memory-config.js.map +1 -1
  119. package/dist/src/agent/memory/sensitivity.d.ts +3 -0
  120. package/dist/src/agent/memory/sensitivity.js +13 -0
  121. package/dist/src/agent/memory/sensitivity.js.map +1 -0
  122. package/dist/src/agent/memory/understanding/service.js +10 -14
  123. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  124. package/dist/src/agent/memory/user-context-coordinator.d.ts +1 -0
  125. package/dist/src/agent/memory/user-context-coordinator.js +2 -0
  126. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  127. package/dist/src/agent/orchestration/agent-orchestrator.js +8 -1
  128. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  129. package/dist/src/agent/tools/dreaming-tool.js +3 -12
  130. package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
  131. package/dist/src/agent/tools/factory.js +14 -2
  132. package/dist/src/agent/tools/factory.js.map +1 -1
  133. package/dist/src/agent/tools/memory-tool.d.ts +3 -0
  134. package/dist/src/agent/tools/memory-tool.js +6 -3
  135. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  136. package/dist/src/agent/workspace-runtime/registry.d.ts +6 -6
  137. package/dist/src/agent/workspace-runtime/registry.js +19 -12
  138. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  139. package/dist/src/agent-manifest/schema.d.ts +4 -0
  140. package/dist/src/agent-manifest/schema.js +2 -1
  141. package/dist/src/agent-manifest/schema.js.map +1 -1
  142. package/dist/src/agent-runtime/index.js +1 -1
  143. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  144. package/dist/src/config/schema.d.ts +4 -0
  145. package/dist/src/gateway/hono/lib/config-payload.d.ts +2 -0
  146. package/dist/src/gateway/hono/routes/dreaming.js +28 -21
  147. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  148. package/dist/src/gateway/hono/routes/memory.js +16 -4
  149. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  150. package/dist/src/storage/sqlite/fts.d.ts +6 -0
  151. package/dist/src/storage/sqlite/fts.js +70 -1
  152. package/dist/src/storage/sqlite/fts.js.map +1 -1
  153. package/dist/src/storage/sqlite/memory-index-repository.js +16 -7
  154. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  155. package/dist/src/storage/sqlite/memory-records-repository.d.ts +18 -0
  156. package/dist/src/storage/sqlite/memory-records-repository.js +55 -8
  157. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  158. package/package.json +1 -1
  159. package/dist/gateway/static/root/assets/agents-Dl9EWnUh.js +0 -2
  160. package/dist/gateway/static/root/assets/channels-status-swr-EUwWYx8l.js +0 -1
  161. package/dist/gateway/static/root/assets/settings-advanced-gate-CuDBoz5k.js +0 -1
  162. package/dist/gateway/static/root/assets/skill-reload-api-0ODH0DXl.js +0 -1
@@ -1,7 +1,9 @@
1
+ import { init_agent_session_key, normalizeAgentId } from "../../routing/agent-session-key.js";
1
2
  import { appendMemorySignal, deleteMemoryRecord, getMemoryRecord, listMemoryRecords, searchMemoryRecords, upsertMemoryRecord } from "../../storage/sqlite/memory-records-repository.js";
2
3
  import "../../storage/sqlite/index.js";
3
4
  import { memoryGet, memorySearch } from "../prompt/memory/index.js";
4
5
  //#region src/agent/memory/builtin-provider.ts
6
+ init_agent_session_key();
5
7
  /**
6
8
  * Builtin local memory provider backed by profile memory, agent-home curated files,
7
9
  * and the local SQLite FTS index.
@@ -24,15 +26,16 @@ var BuiltinMemoryProvider = class {
24
26
  };
25
27
  workspaceDir = "";
26
28
  agentId = "main";
27
- constructor(store) {
29
+ constructor(store, accessPolicy) {
28
30
  this.store = store;
31
+ this.accessPolicy = accessPolicy;
29
32
  }
30
33
  isAvailable() {
31
34
  return true;
32
35
  }
33
36
  async initialize(_sessionId, options) {
34
37
  this.workspaceDir = options?.workspace ?? options?.agentWorkspace ?? this.store.workspaceDir;
35
- this.agentId = String(options?.agentId ?? this.agentId);
38
+ this.agentId = normalizeAgentId(String(options?.agentId ?? this.agentId));
36
39
  }
37
40
  systemPromptBlock() {
38
41
  return "";
@@ -42,24 +45,27 @@ var BuiltinMemoryProvider = class {
42
45
  return [];
43
46
  }
44
47
  async search(request) {
45
- const agentId = request.scope?.agentId ?? this.agentId;
46
48
  const workspaceId = request.scope?.workspaceId ?? this.workspaceDir;
47
- const recordHits = searchMemoryRecords({
49
+ const recordHits = (this.accessPolicy?.readableAgentIds ?? [this.agentId]).flatMap((ownerAgentId) => searchMemoryRecords({
48
50
  query: request.query,
49
- agentId,
50
- workspaceId,
51
+ agentId: ownerAgentId,
52
+ workspaceId: ownerAgentId === this.agentId ? workspaceId : void 0,
53
+ visibleToSessionKey: request.scope?.sessionKey,
54
+ unscopedSessionOnly: request.scope?.sessionKey == null,
55
+ visibleToProjectId: request.scope?.projectId,
56
+ unscopedProjectOnly: request.scope?.projectId == null,
51
57
  providerId: this.id,
52
58
  kinds: request.kinds,
53
59
  maxResults: request.maxResults,
54
60
  minScore: request.minScore
55
- });
61
+ })).filter((result) => this.canReadRecord(result.record, request.scope)).sort((left, right) => right.score - left.score).slice(0, request.maxResults ?? 5);
56
62
  if (recordHits.length > 0) return recordHits;
57
63
  return (await memorySearch(this.workspaceDir, request.query, {
58
64
  maxResults: request.maxResults,
59
65
  minScore: request.minScore,
60
66
  memoriesDir: this.store.memoriesDir,
61
67
  userMemoryPath: this.store.userMemoryPath,
62
- agentId
68
+ agentId: this.agentId
63
69
  })).map((entry) => {
64
70
  const start = entry.lineNumbers[0] ?? 1;
65
71
  const end = entry.lineNumbers[entry.lineNumbers.length - 1] ?? start;
@@ -70,7 +76,7 @@ var BuiltinMemoryProvider = class {
70
76
  id,
71
77
  providerId: this.id,
72
78
  kind,
73
- agentId,
79
+ agentId: this.agentId,
74
80
  workspaceId,
75
81
  content: entry.lines,
76
82
  source: {
@@ -96,7 +102,8 @@ var BuiltinMemoryProvider = class {
96
102
  async read(request) {
97
103
  if (request.id && !request.path) {
98
104
  const existing = getMemoryRecord(request.id);
99
- if (existing) return { record: existing };
105
+ if (existing && this.canReadRecord(existing, request.scope)) return { record: existing };
106
+ if (existing) return null;
100
107
  }
101
108
  const result = memoryGet(this.workspaceDir, request.path ?? request.id ?? "", request.from, request.lines, this.store.memoriesDir, this.store.userMemoryPath);
102
109
  if (!result) return null;
@@ -106,7 +113,7 @@ var BuiltinMemoryProvider = class {
106
113
  id: `${path}#L${result.lineNumbers.start}-L${result.lineNumbers.end}`,
107
114
  providerId: this.id,
108
115
  kind: inferKindFromPath(path),
109
- agentId: request.scope?.agentId ?? this.agentId,
116
+ agentId: this.agentId,
110
117
  workspaceId: request.scope?.workspaceId ?? this.workspaceDir,
111
118
  content: result.content,
112
119
  source: {
@@ -132,6 +139,8 @@ var BuiltinMemoryProvider = class {
132
139
  providerId: this.id,
133
140
  agentId: request.scope?.agentId ?? this.agentId,
134
141
  workspaceId: request.scope?.workspaceId ?? this.workspaceDir,
142
+ visibleToSessionKey: request.scope?.sessionKey,
143
+ visibleToProjectId: request.scope?.projectId,
135
144
  kind: request.kind,
136
145
  status: request.status,
137
146
  canonicalKey: request.canonicalKey,
@@ -154,22 +163,33 @@ var BuiltinMemoryProvider = class {
154
163
  }
155
164
  async write(request) {
156
165
  const target = request.target ?? (request.kind === "user_profile" ? "user" : "memory");
166
+ const ownerAgentId = normalizeAgentId(request.scope?.agentId ?? this.agentId);
167
+ const isCrossAgentWrite = ownerAgentId !== this.agentId;
168
+ if (isCrossAgentWrite && request.status !== "candidate") return {
169
+ success: false,
170
+ error: "Cross-agent writes must be submitted as candidates"
171
+ };
172
+ if (isCrossAgentWrite && !this.accessPolicy?.canSubmitCandidate(ownerAgentId)) return {
173
+ success: false,
174
+ error: "Cross-agent candidate submission is not allowed"
175
+ };
157
176
  if (request.status === "candidate") return {
158
177
  success: true,
159
178
  message: "Memory candidate added to inbox",
160
179
  record: upsertMemoryRecord({
161
180
  providerId: this.id,
162
181
  kind: request.kind,
163
- agentId: request.scope?.agentId ?? this.agentId,
164
- workspaceId: request.scope?.workspaceId ?? this.workspaceDir,
165
- sessionKey: request.scope?.sessionKey,
182
+ agentId: ownerAgentId,
183
+ workspaceId: isCrossAgentWrite ? request.scope?.workspaceId : request.scope?.workspaceId ?? this.workspaceDir,
184
+ sessionKey: isCrossAgentWrite ? void 0 : request.scope?.sessionKey,
185
+ projectId: isCrossAgentWrite ? void 0 : request.scope?.projectId,
166
186
  content: request.content,
167
187
  source: {
168
188
  ...request.source ?? {},
169
189
  provider: this.id
170
190
  },
171
191
  confidence: request.confidence,
172
- tags: request.tags,
192
+ tags: isCrossAgentWrite ? [...request.tags ?? [], `shared-from:${this.agentId}`] : request.tags,
173
193
  status: "candidate",
174
194
  sensitivity: request.sensitivity,
175
195
  canonicalKey: request.canonicalKey,
@@ -198,7 +218,7 @@ var BuiltinMemoryProvider = class {
198
218
  id: `curated:${target}:${Date.now()}`,
199
219
  providerId: this.id,
200
220
  kind: request.kind,
201
- agentId: request.scope?.agentId ?? this.agentId,
221
+ agentId: this.agentId,
202
222
  workspaceId: request.scope?.workspaceId ?? this.workspaceDir,
203
223
  sessionKey: request.scope?.sessionKey,
204
224
  content: request.content,
@@ -225,6 +245,10 @@ var BuiltinMemoryProvider = class {
225
245
  }
226
246
  async update(request) {
227
247
  const target = request.target ?? "memory";
248
+ if (((request.id ? getMemoryRecord(request.id) : null)?.scope.agentId ?? request.scope?.agentId ?? this.agentId) !== this.agentId) return {
249
+ success: false,
250
+ error: "Cross-agent memory updates are not allowed"
251
+ };
228
252
  const result = await this.store.replace(target, request.matchText ?? request.id ?? "", request.content);
229
253
  if (!result.success) return {
230
254
  success: false,
@@ -273,6 +297,10 @@ var BuiltinMemoryProvider = class {
273
297
  }
274
298
  async delete(request) {
275
299
  const target = request.target ?? "memory";
300
+ if (((request.id ? getMemoryRecord(request.id) : null)?.scope.agentId ?? request.scope?.agentId ?? this.agentId) !== this.agentId) return {
301
+ success: false,
302
+ error: "Cross-agent memory deletion is not allowed"
303
+ };
276
304
  const result = await this.store.remove(target, request.matchText ?? request.id ?? "");
277
305
  if (!result.success) return {
278
306
  success: false,
@@ -304,6 +332,13 @@ var BuiltinMemoryProvider = class {
304
332
  });
305
333
  }
306
334
  async shutdown() {}
335
+ canReadRecord(record, scope) {
336
+ if (this.accessPolicy) return this.accessPolicy.canReadRecord(record, scope);
337
+ if (record.scope.agentId !== this.agentId) return false;
338
+ if (record.scope.sessionKey && record.scope.sessionKey !== scope?.sessionKey) return false;
339
+ if (record.scope.projectId && record.scope.projectId !== scope?.projectId) return false;
340
+ return true;
341
+ }
307
342
  };
308
343
  function inferKindFromPath(path) {
309
344
  const normalized = path.replace(/\\/g, "/");
@@ -1 +1 @@
1
- {"version":3,"file":"builtin-provider.js","names":[],"sources":["../../../../src/agent/memory/builtin-provider.ts"],"sourcesContent":["import type { BuiltinMemoryStore } from './builtin-memory-store.js';\nimport type { MemoryProvider, MemoryProviderInitOptions } from './provider.js';\nimport { memoryGet, memorySearch } from '../prompt/memory/index.js';\nimport {\n appendMemorySignal,\n deleteMemoryRecord,\n getMemoryRecord,\n listMemoryRecords,\n searchMemoryRecords,\n upsertMemoryRecord,\n} from '../../storage/sqlite/index.js';\nimport type {\n MemoryDeleteRequest,\n MemoryListRequest,\n MemoryReadRequest,\n MemoryReadResult,\n MemoryRecord,\n MemorySearchRequest,\n MemorySearchResult,\n MemoryUpdateRequest,\n MemoryWriteRequest,\n MemoryWriteResult,\n MemorySyncEvent,\n} from './types.js';\n\n/**\n * Builtin local memory provider backed by profile memory, agent-home curated files,\n * and the local SQLite FTS index.\n */\nexport class BuiltinMemoryProvider implements MemoryProvider {\n readonly id = 'local';\n readonly displayName = 'Local Knowledge Store';\n readonly capabilities = {\n search: true,\n read: true,\n write: true,\n update: true,\n delete: true,\n keywordSearch: true,\n semanticSearch: false,\n hybridSearch: false,\n citations: true,\n sync: false,\n local: true,\n };\n\n private workspaceDir = '';\n private agentId = 'main';\n\n constructor(private readonly store: BuiltinMemoryStore) {}\n\n isAvailable(): boolean {\n return true;\n }\n\n async initialize(_sessionId: string, options?: MemoryProviderInitOptions): Promise<void> {\n this.workspaceDir = options?.workspace ?? options?.agentWorkspace ?? this.store.workspaceDir;\n this.agentId = String(options?.agentId ?? this.agentId);\n }\n\n systemPromptBlock(): string {\n return '';\n }\n\n queuePrefetch(): void {}\n\n getToolSchemas() {\n return [];\n }\n\n async search(request: MemorySearchRequest): Promise<MemorySearchResult[]> {\n const agentId = request.scope?.agentId ?? this.agentId;\n const workspaceId = request.scope?.workspaceId ?? this.workspaceDir;\n const recordHits = searchMemoryRecords({\n query: request.query,\n agentId,\n workspaceId,\n providerId: this.id,\n kinds: request.kinds,\n maxResults: request.maxResults,\n minScore: request.minScore,\n });\n if (recordHits.length > 0) {\n return recordHits;\n }\n\n const results = await memorySearch(this.workspaceDir, request.query, {\n maxResults: request.maxResults,\n minScore: request.minScore,\n memoriesDir: this.store.memoriesDir,\n userMemoryPath: this.store.userMemoryPath,\n agentId,\n });\n return results.map((entry) => {\n const start = entry.lineNumbers[0] ?? 1;\n const end = entry.lineNumbers[entry.lineNumbers.length - 1] ?? start;\n const id = `${entry.file}#L${start}-L${end}`;\n const kind = inferKindFromPath(entry.file);\n const record = upsertMemoryRecord({\n id,\n providerId: this.id,\n kind,\n agentId,\n workspaceId,\n content: entry.lines,\n source: {\n provider: this.id,\n path: entry.file,\n lineStart: start,\n lineEnd: end,\n },\n confidence: entry.score,\n });\n return {\n record,\n score: entry.score,\n snippet: entry.lines,\n citation: {\n providerId: this.id,\n recordId: id,\n path: entry.file,\n lineStart: start,\n lineEnd: end,\n },\n };\n });\n }\n\n async read(request: MemoryReadRequest): Promise<MemoryReadResult | null> {\n if (request.id && !request.path) {\n const existing = getMemoryRecord(request.id);\n if (existing) {\n return { record: existing };\n }\n }\n const result = memoryGet(\n this.workspaceDir,\n request.path ?? request.id ?? '',\n request.from,\n request.lines,\n this.store.memoriesDir,\n this.store.userMemoryPath,\n );\n if (!result) return null;\n const path = request.path ?? request.id ?? '';\n const record = upsertMemoryRecord({\n id: `${path}#L${result.lineNumbers.start}-L${result.lineNumbers.end}`,\n providerId: this.id,\n kind: inferKindFromPath(path),\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n content: result.content,\n source: {\n provider: this.id,\n path,\n lineStart: result.lineNumbers.start,\n lineEnd: result.lineNumbers.end,\n },\n });\n return {\n record,\n lineNumbers: result.lineNumbers,\n };\n }\n\n async get(id: string): Promise<MemoryRecord | null> {\n const parsed = parseLineAddress(id);\n const result = await this.read({\n path: parsed.path,\n from: parsed.lineStart,\n lines: parsed.lineEnd != null ? parsed.lineEnd - parsed.lineStart + 1 : undefined,\n });\n return result?.record ?? null;\n }\n\n async list(request: MemoryListRequest): Promise<MemoryRecord[]> {\n const records = listMemoryRecords({\n providerId: this.id,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n kind: request.kind,\n status: request.status,\n canonicalKey: request.canonicalKey,\n limit: 200,\n });\n if (records.length > 0 || request.kind || request.status || request.canonicalKey) {\n return request.target\n ? records.filter((record) => targetForKind(record.kind) === request.target)\n : records;\n }\n\n const target = request.target ?? (request.kind === 'user_profile' ? 'user' : 'memory');\n return this.store.getLiveEntries(target).map((content, index) =>\n upsertMemoryRecord({\n id: `curated:${target}:${index + 1}`,\n providerId: this.id,\n kind: target === 'user' ? 'user_profile' : 'agent_note',\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n content,\n source: {\n provider: this.id,\n path: sourcePathForTarget(target),\n },\n }),\n );\n }\n\n async write(request: MemoryWriteRequest): Promise<MemoryWriteResult> {\n const target = request.target ?? (request.kind === 'user_profile' ? 'user' : 'memory');\n if (request.status === 'candidate') {\n const record = upsertMemoryRecord({\n providerId: this.id,\n kind: request.kind,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n sessionKey: request.scope?.sessionKey,\n content: request.content,\n source: {\n ...(request.source ?? {}),\n provider: this.id,\n },\n confidence: request.confidence,\n tags: request.tags,\n status: 'candidate',\n sensitivity: request.sensitivity,\n canonicalKey: request.canonicalKey,\n explicitness: request.explicitness,\n durability: request.durability,\n importance: request.importance,\n disclosurePolicy: request.disclosurePolicy,\n evidence: request.evidence,\n validFrom: request.validFrom,\n validTo: request.validTo,\n reviewAfter: request.reviewAfter,\n expiresAt: request.expiresAt,\n supersedesRecordId: request.supersedesRecordId,\n conflictGroupId: request.conflictGroupId,\n });\n return {\n success: true,\n message: 'Memory candidate added to inbox',\n record,\n };\n }\n const result = await this.store.add(target, request.content);\n if (!result.success) return { success: false, error: result.error };\n return {\n success: true,\n message: result.message,\n record: upsertMemoryRecord({\n id: `curated:${target}:${Date.now()}`,\n providerId: this.id,\n kind: request.kind,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n sessionKey: request.scope?.sessionKey,\n content: request.content,\n source: {\n ...(request.source ?? {}),\n provider: this.id,\n path: sourcePathForTarget(target),\n },\n tags: request.tags,\n canonicalKey: request.canonicalKey,\n explicitness: request.explicitness,\n durability: request.durability,\n importance: request.importance,\n disclosurePolicy: request.disclosurePolicy,\n evidence: request.evidence,\n validFrom: request.validFrom,\n validTo: request.validTo,\n reviewAfter: request.reviewAfter,\n expiresAt: request.expiresAt,\n supersedesRecordId: request.supersedesRecordId,\n conflictGroupId: request.conflictGroupId,\n }),\n };\n }\n\n async update(request: MemoryUpdateRequest): Promise<MemoryWriteResult> {\n const target = request.target ?? 'memory';\n const result = await this.store.replace(target, request.matchText ?? request.id ?? '', request.content);\n if (!result.success) return { success: false, error: result.error };\n if (request.id) {\n const existing = getMemoryRecord(request.id);\n upsertMemoryRecord({\n id: request.id,\n providerId: this.id,\n kind: existing?.kind ?? (target === 'user' ? 'user_profile' : 'agent_note'),\n agentId: existing?.scope.agentId ?? request.scope?.agentId ?? this.agentId,\n workspaceId: existing?.scope.workspaceId ?? request.scope?.workspaceId ?? this.workspaceDir,\n sessionKey: existing?.scope.sessionKey ?? request.scope?.sessionKey,\n content: request.content,\n source: existing?.source ?? { provider: this.id, path: sourcePathForTarget(target) },\n tags: existing?.tags,\n });\n } else if (request.matchText) {\n for (const existing of listMemoryRecords({\n providerId: this.id,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n kind: target === 'user' ? 'user_profile' : 'agent_note',\n limit: 200,\n })) {\n if (!existing.content.includes(request.matchText)) continue;\n upsertMemoryRecord({\n id: existing.id,\n providerId: this.id,\n kind: existing.kind,\n agentId: existing.scope.agentId,\n workspaceId: existing.scope.workspaceId,\n sessionKey: existing.scope.sessionKey,\n content: request.content,\n source: existing.source,\n tags: existing.tags,\n });\n }\n }\n return { success: true, message: result.message };\n }\n\n async delete(request: MemoryDeleteRequest): Promise<MemoryWriteResult> {\n const target = request.target ?? 'memory';\n const result = await this.store.remove(target, request.matchText ?? request.id ?? '');\n if (!result.success) return { success: false, error: result.error };\n if (request.id) {\n deleteMemoryRecord(request.id);\n } else if (request.matchText) {\n for (const existing of listMemoryRecords({\n providerId: this.id,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n kind: target === 'user' ? 'user_profile' : 'agent_note',\n limit: 200,\n })) {\n if (existing.content.includes(request.matchText)) {\n deleteMemoryRecord(existing.id);\n }\n }\n }\n return { success: true, message: result.message };\n }\n\n sync(event: MemorySyncEvent): void {\n if (event.type !== 'signal') return;\n appendMemorySignal({\n signal: event.signal,\n providerId: this.id,\n agentId: this.agentId,\n workspaceId: this.workspaceDir,\n sessionKey:\n typeof event.signal.metadata?.sessionKey === 'string'\n ? event.signal.metadata.sessionKey\n : undefined,\n });\n }\n\n async shutdown(): Promise<void> {}\n}\n\nfunction inferKindFromPath(path: string): MemoryRecord['kind'] {\n const normalized = path.replace(/\\\\/g, '/');\n if (normalized === 'user/MEMORY.md' || normalized.endsWith('/user/MEMORY.md')) return 'user_profile';\n if (/^memory\\/\\d{4}-\\d{2}-\\d{2}\\.md$/.test(normalized)) return 'daily_note';\n if (normalized.endsWith('MEMORY.md')) return 'agent_note';\n return 'workspace_fact';\n}\n\nfunction targetForKind(kind: MemoryRecord['kind']): 'memory' | 'user' {\n return kind === 'user_profile' || kind === 'preference' || kind === 'relationship' ||\n kind === 'routine' || kind === 'personal_logistics'\n ? 'user'\n : 'memory';\n}\n\nfunction sourcePathForTarget(target: 'memory' | 'user'): string {\n return target === 'user' ? 'user/MEMORY.md' : 'MEMORY.md';\n}\n\nfunction parseLineAddress(id: string): { path: string; lineStart?: number; lineEnd?: number } {\n const match = /^(.*)#L(\\d+)(?:-L(\\d+))?$/.exec(id);\n if (!match) return { path: id };\n const lineStart = Number.parseInt(match[2] ?? '1', 10);\n const lineEnd = Number.parseInt(match[3] ?? match[2] ?? '1', 10);\n return {\n path: match[1] ?? id,\n lineStart: Number.isFinite(lineStart) ? lineStart : undefined,\n lineEnd: Number.isFinite(lineEnd) ? lineEnd : undefined,\n };\n}\n"],"mappings":";;;;;;;;AA6BA,IAAa,wBAAb,MAA6D;CAC3D,KAAc;CACd,cAAuB;CACvB,eAAwB;EACtB,QAAQ;EACR,MAAM;EACN,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,eAAe;EACf,gBAAgB;EAChB,cAAc;EACd,WAAW;EACX,MAAM;EACN,OAAO;EACR;CAED,eAAuB;CACvB,UAAkB;CAElB,YAAY,OAA4C;AAA3B,OAAA,QAAA;;CAE7B,cAAuB;AACrB,SAAO;;CAGT,MAAM,WAAW,YAAoB,SAAoD;AACvF,OAAK,eAAe,SAAS,aAAa,SAAS,kBAAkB,KAAK,MAAM;AAChF,OAAK,UAAU,OAAO,SAAS,WAAW,KAAK,QAAQ;;CAGzD,oBAA4B;AAC1B,SAAO;;CAGT,gBAAsB;CAEtB,iBAAiB;AACf,SAAO,EAAE;;CAGX,MAAM,OAAO,SAA6D;EACxE,MAAM,UAAU,QAAQ,OAAO,WAAW,KAAK;EAC/C,MAAM,cAAc,QAAQ,OAAO,eAAe,KAAK;EACvD,MAAM,aAAa,oBAAoB;GACrC,OAAO,QAAQ;GACf;GACA;GACA,YAAY,KAAK;GACjB,OAAO,QAAQ;GACf,YAAY,QAAQ;GACpB,UAAU,QAAQ;GACnB,CAAC;AACF,MAAI,WAAW,SAAS,EACtB,QAAO;AAUT,UAAO,MAPe,aAAa,KAAK,cAAc,QAAQ,OAAO;GACnE,YAAY,QAAQ;GACpB,UAAU,QAAQ;GAClB,aAAa,KAAK,MAAM;GACxB,gBAAgB,KAAK,MAAM;GAC3B;GACD,CAAC,EACa,KAAK,UAAU;GAC5B,MAAM,QAAQ,MAAM,YAAY,MAAM;GACtC,MAAM,MAAM,MAAM,YAAY,MAAM,YAAY,SAAS,MAAM;GAC/D,MAAM,KAAK,GAAG,MAAM,KAAK,IAAI,MAAM,IAAI;GACvC,MAAM,OAAO,kBAAkB,MAAM,KAAK;AAgB1C,UAAO;IACL,QAhBa,mBAAmB;KAChC;KACA,YAAY,KAAK;KACjB;KACA;KACA;KACA,SAAS,MAAM;KACf,QAAQ;MACN,UAAU,KAAK;MACf,MAAM,MAAM;MACZ,WAAW;MACX,SAAS;MACV;KACD,YAAY,MAAM;KACnB,CAEO;IACN,OAAO,MAAM;IACb,SAAS,MAAM;IACf,UAAU;KACR,YAAY,KAAK;KACjB,UAAU;KACV,MAAM,MAAM;KACZ,WAAW;KACX,SAAS;KACV;IACF;IACD;;CAGJ,MAAM,KAAK,SAA8D;AACvE,MAAI,QAAQ,MAAM,CAAC,QAAQ,MAAM;GAC/B,MAAM,WAAW,gBAAgB,QAAQ,GAAG;AAC5C,OAAI,SACF,QAAO,EAAE,QAAQ,UAAU;;EAG/B,MAAM,SAAS,UACb,KAAK,cACL,QAAQ,QAAQ,QAAQ,MAAM,IAC9B,QAAQ,MACR,QAAQ,OACR,KAAK,MAAM,aACX,KAAK,MAAM,eACZ;AACD,MAAI,CAAC,OAAQ,QAAO;EACpB,MAAM,OAAO,QAAQ,QAAQ,QAAQ,MAAM;AAe3C,SAAO;GACL,QAfa,mBAAmB;IAChC,IAAI,GAAG,KAAK,IAAI,OAAO,YAAY,MAAM,IAAI,OAAO,YAAY;IAChE,YAAY,KAAK;IACjB,MAAM,kBAAkB,KAAK;IAC7B,SAAS,QAAQ,OAAO,WAAW,KAAK;IACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;IAChD,SAAS,OAAO;IAChB,QAAQ;KACN,UAAU,KAAK;KACf;KACA,WAAW,OAAO,YAAY;KAC9B,SAAS,OAAO,YAAY;KAC7B;IACF,CAEO;GACN,aAAa,OAAO;GACrB;;CAGH,MAAM,IAAI,IAA0C;EAClD,MAAM,SAAS,iBAAiB,GAAG;AAMnC,UAAO,MALc,KAAK,KAAK;GAC7B,MAAM,OAAO;GACb,MAAM,OAAO;GACb,OAAO,OAAO,WAAW,OAAO,OAAO,UAAU,OAAO,YAAY,IAAI,KAAA;GACzE,CAAC,GACa,UAAU;;CAG3B,MAAM,KAAK,SAAqD;EAC9D,MAAM,UAAU,kBAAkB;GAChC,YAAY,KAAK;GACjB,SAAS,QAAQ,OAAO,WAAW,KAAK;GACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;GAChD,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,cAAc,QAAQ;GACtB,OAAO;GACR,CAAC;AACF,MAAI,QAAQ,SAAS,KAAK,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,aAClE,QAAO,QAAQ,SACX,QAAQ,QAAQ,WAAW,cAAc,OAAO,KAAK,KAAK,QAAQ,OAAO,GACzE;EAGN,MAAM,SAAS,QAAQ,WAAW,QAAQ,SAAS,iBAAiB,SAAS;AAC7E,SAAO,KAAK,MAAM,eAAe,OAAO,CAAC,KAAK,SAAS,UACrD,mBAAmB;GACjB,IAAI,WAAW,OAAO,GAAG,QAAQ;GACjC,YAAY,KAAK;GACjB,MAAM,WAAW,SAAS,iBAAiB;GAC3C,SAAS,QAAQ,OAAO,WAAW,KAAK;GACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;GAChD;GACA,QAAQ;IACN,UAAU,KAAK;IACf,MAAM,oBAAoB,OAAO;IAClC;GACF,CAAC,CACH;;CAGH,MAAM,MAAM,SAAyD;EACnE,MAAM,SAAS,QAAQ,WAAW,QAAQ,SAAS,iBAAiB,SAAS;AAC7E,MAAI,QAAQ,WAAW,YA6BrB,QAAO;GACL,SAAS;GACT,SAAS;GACT,QA/Ba,mBAAmB;IAChC,YAAY,KAAK;IACjB,MAAM,QAAQ;IACd,SAAS,QAAQ,OAAO,WAAW,KAAK;IACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;IAChD,YAAY,QAAQ,OAAO;IAC3B,SAAS,QAAQ;IACjB,QAAQ;KACN,GAAI,QAAQ,UAAU,EAAE;KACxB,UAAU,KAAK;KAChB;IACD,YAAY,QAAQ;IACpB,MAAM,QAAQ;IACd,QAAQ;IACR,aAAa,QAAQ;IACrB,cAAc,QAAQ;IACtB,cAAc,QAAQ;IACtB,YAAY,QAAQ;IACpB,YAAY,QAAQ;IACpB,kBAAkB,QAAQ;IAC1B,UAAU,QAAQ;IAClB,WAAW,QAAQ;IACnB,SAAS,QAAQ;IACjB,aAAa,QAAQ;IACrB,WAAW,QAAQ;IACnB,oBAAoB,QAAQ;IAC5B,iBAAiB,QAAQ;IAC1B,CAIO;GACP;EAEH,MAAM,SAAS,MAAM,KAAK,MAAM,IAAI,QAAQ,QAAQ,QAAQ;AAC5D,MAAI,CAAC,OAAO,QAAS,QAAO;GAAE,SAAS;GAAO,OAAO,OAAO;GAAO;AACnE,SAAO;GACL,SAAS;GACT,SAAS,OAAO;GAChB,QAAQ,mBAAmB;IACzB,IAAI,WAAW,OAAO,GAAG,KAAK,KAAK;IACnC,YAAY,KAAK;IACjB,MAAM,QAAQ;IACd,SAAS,QAAQ,OAAO,WAAW,KAAK;IACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;IAChD,YAAY,QAAQ,OAAO;IAC3B,SAAS,QAAQ;IACjB,QAAQ;KACN,GAAI,QAAQ,UAAU,EAAE;KACxB,UAAU,KAAK;KACf,MAAM,oBAAoB,OAAO;KAClC;IACD,MAAM,QAAQ;IACd,cAAc,QAAQ;IACtB,cAAc,QAAQ;IACtB,YAAY,QAAQ;IACpB,YAAY,QAAQ;IACpB,kBAAkB,QAAQ;IAC1B,UAAU,QAAQ;IAClB,WAAW,QAAQ;IACnB,SAAS,QAAQ;IACjB,aAAa,QAAQ;IACrB,WAAW,QAAQ;IACnB,oBAAoB,QAAQ;IAC5B,iBAAiB,QAAQ;IAC1B,CAAC;GACH;;CAGH,MAAM,OAAO,SAA0D;EACrE,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,SAAS,MAAM,KAAK,MAAM,QAAQ,QAAQ,QAAQ,aAAa,QAAQ,MAAM,IAAI,QAAQ,QAAQ;AACvG,MAAI,CAAC,OAAO,QAAS,QAAO;GAAE,SAAS;GAAO,OAAO,OAAO;GAAO;AACnE,MAAI,QAAQ,IAAI;GACd,MAAM,WAAW,gBAAgB,QAAQ,GAAG;AAC5C,sBAAmB;IACjB,IAAI,QAAQ;IACZ,YAAY,KAAK;IACjB,MAAM,UAAU,SAAS,WAAW,SAAS,iBAAiB;IAC9D,SAAS,UAAU,MAAM,WAAW,QAAQ,OAAO,WAAW,KAAK;IACnE,aAAa,UAAU,MAAM,eAAe,QAAQ,OAAO,eAAe,KAAK;IAC/E,YAAY,UAAU,MAAM,cAAc,QAAQ,OAAO;IACzD,SAAS,QAAQ;IACjB,QAAQ,UAAU,UAAU;KAAE,UAAU,KAAK;KAAI,MAAM,oBAAoB,OAAO;KAAE;IACpF,MAAM,UAAU;IACjB,CAAC;aACO,QAAQ,UACjB,MAAK,MAAM,YAAY,kBAAkB;GACvC,YAAY,KAAK;GACjB,SAAS,QAAQ,OAAO,WAAW,KAAK;GACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;GAChD,MAAM,WAAW,SAAS,iBAAiB;GAC3C,OAAO;GACR,CAAC,EAAE;AACF,OAAI,CAAC,SAAS,QAAQ,SAAS,QAAQ,UAAU,CAAE;AACnD,sBAAmB;IACjB,IAAI,SAAS;IACb,YAAY,KAAK;IACjB,MAAM,SAAS;IACf,SAAS,SAAS,MAAM;IACxB,aAAa,SAAS,MAAM;IAC5B,YAAY,SAAS,MAAM;IAC3B,SAAS,QAAQ;IACjB,QAAQ,SAAS;IACjB,MAAM,SAAS;IAChB,CAAC;;AAGN,SAAO;GAAE,SAAS;GAAM,SAAS,OAAO;GAAS;;CAGnD,MAAM,OAAO,SAA0D;EACrE,MAAM,SAAS,QAAQ,UAAU;EACjC,MAAM,SAAS,MAAM,KAAK,MAAM,OAAO,QAAQ,QAAQ,aAAa,QAAQ,MAAM,GAAG;AACrF,MAAI,CAAC,OAAO,QAAS,QAAO;GAAE,SAAS;GAAO,OAAO,OAAO;GAAO;AACnE,MAAI,QAAQ,GACV,oBAAmB,QAAQ,GAAG;WACrB,QAAQ;QACZ,MAAM,YAAY,kBAAkB;IACvC,YAAY,KAAK;IACjB,SAAS,QAAQ,OAAO,WAAW,KAAK;IACxC,aAAa,QAAQ,OAAO,eAAe,KAAK;IAChD,MAAM,WAAW,SAAS,iBAAiB;IAC3C,OAAO;IACR,CAAC,CACA,KAAI,SAAS,QAAQ,SAAS,QAAQ,UAAU,CAC9C,oBAAmB,SAAS,GAAG;;AAIrC,SAAO;GAAE,SAAS;GAAM,SAAS,OAAO;GAAS;;CAGnD,KAAK,OAA8B;AACjC,MAAI,MAAM,SAAS,SAAU;AAC7B,qBAAmB;GACjB,QAAQ,MAAM;GACd,YAAY,KAAK;GACjB,SAAS,KAAK;GACd,aAAa,KAAK;GAClB,YACE,OAAO,MAAM,OAAO,UAAU,eAAe,WACzC,MAAM,OAAO,SAAS,aACtB,KAAA;GACP,CAAC;;CAGJ,MAAM,WAA0B;;AAGlC,SAAS,kBAAkB,MAAoC;CAC7D,MAAM,aAAa,KAAK,QAAQ,OAAO,IAAI;AAC3C,KAAI,eAAe,oBAAoB,WAAW,SAAS,kBAAkB,CAAE,QAAO;AACtF,KAAI,kCAAkC,KAAK,WAAW,CAAE,QAAO;AAC/D,KAAI,WAAW,SAAS,YAAY,CAAE,QAAO;AAC7C,QAAO;;AAGT,SAAS,cAAc,MAA+C;AACpE,QAAO,SAAS,kBAAkB,SAAS,gBAAgB,SAAS,kBAClE,SAAS,aAAa,SAAS,uBAC7B,SACA;;AAGN,SAAS,oBAAoB,QAAmC;AAC9D,QAAO,WAAW,SAAS,mBAAmB;;AAGhD,SAAS,iBAAiB,IAAoE;CAC5F,MAAM,QAAQ,4BAA4B,KAAK,GAAG;AAClD,KAAI,CAAC,MAAO,QAAO,EAAE,MAAM,IAAI;CAC/B,MAAM,YAAY,OAAO,SAAS,MAAM,MAAM,KAAK,GAAG;CACtD,MAAM,UAAU,OAAO,SAAS,MAAM,MAAM,MAAM,MAAM,KAAK,GAAG;AAChE,QAAO;EACL,MAAM,MAAM,MAAM;EAClB,WAAW,OAAO,SAAS,UAAU,GAAG,YAAY,KAAA;EACpD,SAAS,OAAO,SAAS,QAAQ,GAAG,UAAU,KAAA;EAC/C"}
1
+ {"version":3,"file":"builtin-provider.js","names":[],"sources":["../../../../src/agent/memory/builtin-provider.ts"],"sourcesContent":["import type { BuiltinMemoryStore } from './builtin-memory-store.js';\nimport type { MemoryAccessPolicy } from './access-policy.js';\nimport { normalizeAgentId } from '../../routing/agent-session-key.js';\nimport type { MemoryProvider, MemoryProviderInitOptions } from './provider.js';\nimport { memoryGet, memorySearch } from '../prompt/memory/index.js';\nimport {\n appendMemorySignal,\n deleteMemoryRecord,\n getMemoryRecord,\n listMemoryRecords,\n searchMemoryRecords,\n upsertMemoryRecord,\n} from '../../storage/sqlite/index.js';\nimport type {\n MemoryDeleteRequest,\n MemoryListRequest,\n MemoryReadRequest,\n MemoryReadResult,\n MemoryRecord,\n MemorySearchRequest,\n MemorySearchResult,\n MemoryUpdateRequest,\n MemoryWriteRequest,\n MemoryWriteResult,\n MemorySyncEvent,\n} from './types.js';\n\n/**\n * Builtin local memory provider backed by profile memory, agent-home curated files,\n * and the local SQLite FTS index.\n */\nexport class BuiltinMemoryProvider implements MemoryProvider {\n readonly id = 'local';\n readonly displayName = 'Local Knowledge Store';\n readonly capabilities = {\n search: true,\n read: true,\n write: true,\n update: true,\n delete: true,\n keywordSearch: true,\n semanticSearch: false,\n hybridSearch: false,\n citations: true,\n sync: false,\n local: true,\n };\n\n private workspaceDir = '';\n private agentId = 'main';\n\n constructor(\n private readonly store: BuiltinMemoryStore,\n private readonly accessPolicy?: MemoryAccessPolicy,\n ) {}\n\n isAvailable(): boolean {\n return true;\n }\n\n async initialize(_sessionId: string, options?: MemoryProviderInitOptions): Promise<void> {\n this.workspaceDir = options?.workspace ?? options?.agentWorkspace ?? this.store.workspaceDir;\n this.agentId = normalizeAgentId(String(options?.agentId ?? this.agentId));\n }\n\n systemPromptBlock(): string {\n return '';\n }\n\n queuePrefetch(): void {}\n\n getToolSchemas() {\n return [];\n }\n\n async search(request: MemorySearchRequest): Promise<MemorySearchResult[]> {\n const workspaceId = request.scope?.workspaceId ?? this.workspaceDir;\n const readableAgentIds = this.accessPolicy?.readableAgentIds ?? [this.agentId];\n const recordHits = readableAgentIds\n .flatMap((ownerAgentId) => searchMemoryRecords({\n query: request.query,\n agentId: ownerAgentId,\n workspaceId: ownerAgentId === this.agentId ? workspaceId : undefined,\n visibleToSessionKey: request.scope?.sessionKey,\n unscopedSessionOnly: request.scope?.sessionKey == null,\n visibleToProjectId: request.scope?.projectId,\n unscopedProjectOnly: request.scope?.projectId == null,\n providerId: this.id,\n kinds: request.kinds,\n maxResults: request.maxResults,\n minScore: request.minScore,\n }))\n .filter((result) => this.canReadRecord(result.record, request.scope))\n .sort((left, right) => right.score - left.score)\n .slice(0, request.maxResults ?? 5);\n if (recordHits.length > 0) {\n return recordHits;\n }\n\n const results = await memorySearch(this.workspaceDir, request.query, {\n maxResults: request.maxResults,\n minScore: request.minScore,\n memoriesDir: this.store.memoriesDir,\n userMemoryPath: this.store.userMemoryPath,\n agentId: this.agentId,\n });\n return results.map((entry) => {\n const start = entry.lineNumbers[0] ?? 1;\n const end = entry.lineNumbers[entry.lineNumbers.length - 1] ?? start;\n const id = `${entry.file}#L${start}-L${end}`;\n const kind = inferKindFromPath(entry.file);\n const record = upsertMemoryRecord({\n id,\n providerId: this.id,\n kind,\n agentId: this.agentId,\n workspaceId,\n content: entry.lines,\n source: {\n provider: this.id,\n path: entry.file,\n lineStart: start,\n lineEnd: end,\n },\n confidence: entry.score,\n });\n return {\n record,\n score: entry.score,\n snippet: entry.lines,\n citation: {\n providerId: this.id,\n recordId: id,\n path: entry.file,\n lineStart: start,\n lineEnd: end,\n },\n };\n });\n }\n\n async read(request: MemoryReadRequest): Promise<MemoryReadResult | null> {\n if (request.id && !request.path) {\n const existing = getMemoryRecord(request.id);\n if (existing && this.canReadRecord(existing, request.scope)) {\n return { record: existing };\n }\n if (existing) return null;\n }\n const result = memoryGet(\n this.workspaceDir,\n request.path ?? request.id ?? '',\n request.from,\n request.lines,\n this.store.memoriesDir,\n this.store.userMemoryPath,\n );\n if (!result) return null;\n const path = request.path ?? request.id ?? '';\n const record = upsertMemoryRecord({\n id: `${path}#L${result.lineNumbers.start}-L${result.lineNumbers.end}`,\n providerId: this.id,\n kind: inferKindFromPath(path),\n agentId: this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n content: result.content,\n source: {\n provider: this.id,\n path,\n lineStart: result.lineNumbers.start,\n lineEnd: result.lineNumbers.end,\n },\n });\n return {\n record,\n lineNumbers: result.lineNumbers,\n };\n }\n\n async get(id: string): Promise<MemoryRecord | null> {\n const parsed = parseLineAddress(id);\n const result = await this.read({\n path: parsed.path,\n from: parsed.lineStart,\n lines: parsed.lineEnd != null ? parsed.lineEnd - parsed.lineStart + 1 : undefined,\n });\n return result?.record ?? null;\n }\n\n async list(request: MemoryListRequest): Promise<MemoryRecord[]> {\n const records = listMemoryRecords({\n providerId: this.id,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n visibleToSessionKey: request.scope?.sessionKey,\n visibleToProjectId: request.scope?.projectId,\n kind: request.kind,\n status: request.status,\n canonicalKey: request.canonicalKey,\n limit: 200,\n });\n if (records.length > 0 || request.kind || request.status || request.canonicalKey) {\n return request.target\n ? records.filter((record) => targetForKind(record.kind) === request.target)\n : records;\n }\n\n const target = request.target ?? (request.kind === 'user_profile' ? 'user' : 'memory');\n return this.store.getLiveEntries(target).map((content, index) =>\n upsertMemoryRecord({\n id: `curated:${target}:${index + 1}`,\n providerId: this.id,\n kind: target === 'user' ? 'user_profile' : 'agent_note',\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n content,\n source: {\n provider: this.id,\n path: sourcePathForTarget(target),\n },\n }),\n );\n }\n\n async write(request: MemoryWriteRequest): Promise<MemoryWriteResult> {\n const target = request.target ?? (request.kind === 'user_profile' ? 'user' : 'memory');\n const ownerAgentId = normalizeAgentId(request.scope?.agentId ?? this.agentId);\n const isCrossAgentWrite = ownerAgentId !== this.agentId;\n if (isCrossAgentWrite && request.status !== 'candidate') {\n return { success: false, error: 'Cross-agent writes must be submitted as candidates' };\n }\n if (isCrossAgentWrite && !this.accessPolicy?.canSubmitCandidate(ownerAgentId)) {\n return { success: false, error: 'Cross-agent candidate submission is not allowed' };\n }\n if (request.status === 'candidate') {\n const record = upsertMemoryRecord({\n providerId: this.id,\n kind: request.kind,\n agentId: ownerAgentId,\n workspaceId: isCrossAgentWrite ? request.scope?.workspaceId : request.scope?.workspaceId ?? this.workspaceDir,\n sessionKey: isCrossAgentWrite ? undefined : request.scope?.sessionKey,\n projectId: isCrossAgentWrite ? undefined : request.scope?.projectId,\n content: request.content,\n source: {\n ...(request.source ?? {}),\n provider: this.id,\n },\n confidence: request.confidence,\n tags: isCrossAgentWrite\n ? [...(request.tags ?? []), `shared-from:${this.agentId}`]\n : request.tags,\n status: 'candidate',\n sensitivity: request.sensitivity,\n canonicalKey: request.canonicalKey,\n explicitness: request.explicitness,\n durability: request.durability,\n importance: request.importance,\n disclosurePolicy: request.disclosurePolicy,\n evidence: request.evidence,\n validFrom: request.validFrom,\n validTo: request.validTo,\n reviewAfter: request.reviewAfter,\n expiresAt: request.expiresAt,\n supersedesRecordId: request.supersedesRecordId,\n conflictGroupId: request.conflictGroupId,\n });\n return {\n success: true,\n message: 'Memory candidate added to inbox',\n record,\n };\n }\n const result = await this.store.add(target, request.content);\n if (!result.success) return { success: false, error: result.error };\n return {\n success: true,\n message: result.message,\n record: upsertMemoryRecord({\n id: `curated:${target}:${Date.now()}`,\n providerId: this.id,\n kind: request.kind,\n agentId: this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n sessionKey: request.scope?.sessionKey,\n content: request.content,\n source: {\n ...(request.source ?? {}),\n provider: this.id,\n path: sourcePathForTarget(target),\n },\n tags: request.tags,\n canonicalKey: request.canonicalKey,\n explicitness: request.explicitness,\n durability: request.durability,\n importance: request.importance,\n disclosurePolicy: request.disclosurePolicy,\n evidence: request.evidence,\n validFrom: request.validFrom,\n validTo: request.validTo,\n reviewAfter: request.reviewAfter,\n expiresAt: request.expiresAt,\n supersedesRecordId: request.supersedesRecordId,\n conflictGroupId: request.conflictGroupId,\n }),\n };\n }\n\n async update(request: MemoryUpdateRequest): Promise<MemoryWriteResult> {\n const target = request.target ?? 'memory';\n const existingRecord = request.id ? getMemoryRecord(request.id) : null;\n const requestedOwnerAgentId = existingRecord?.scope.agentId ?? request.scope?.agentId ?? this.agentId;\n if (requestedOwnerAgentId !== this.agentId) {\n return { success: false, error: 'Cross-agent memory updates are not allowed' };\n }\n const result = await this.store.replace(target, request.matchText ?? request.id ?? '', request.content);\n if (!result.success) return { success: false, error: result.error };\n if (request.id) {\n const existing = getMemoryRecord(request.id);\n upsertMemoryRecord({\n id: request.id,\n providerId: this.id,\n kind: existing?.kind ?? (target === 'user' ? 'user_profile' : 'agent_note'),\n agentId: existing?.scope.agentId ?? request.scope?.agentId ?? this.agentId,\n workspaceId: existing?.scope.workspaceId ?? request.scope?.workspaceId ?? this.workspaceDir,\n sessionKey: existing?.scope.sessionKey ?? request.scope?.sessionKey,\n content: request.content,\n source: existing?.source ?? { provider: this.id, path: sourcePathForTarget(target) },\n tags: existing?.tags,\n });\n } else if (request.matchText) {\n for (const existing of listMemoryRecords({\n providerId: this.id,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n kind: target === 'user' ? 'user_profile' : 'agent_note',\n limit: 200,\n })) {\n if (!existing.content.includes(request.matchText)) continue;\n upsertMemoryRecord({\n id: existing.id,\n providerId: this.id,\n kind: existing.kind,\n agentId: existing.scope.agentId,\n workspaceId: existing.scope.workspaceId,\n sessionKey: existing.scope.sessionKey,\n content: request.content,\n source: existing.source,\n tags: existing.tags,\n });\n }\n }\n return { success: true, message: result.message };\n }\n\n async delete(request: MemoryDeleteRequest): Promise<MemoryWriteResult> {\n const target = request.target ?? 'memory';\n const existingRecord = request.id ? getMemoryRecord(request.id) : null;\n const requestedOwnerAgentId = existingRecord?.scope.agentId ?? request.scope?.agentId ?? this.agentId;\n if (requestedOwnerAgentId !== this.agentId) {\n return { success: false, error: 'Cross-agent memory deletion is not allowed' };\n }\n const result = await this.store.remove(target, request.matchText ?? request.id ?? '');\n if (!result.success) return { success: false, error: result.error };\n if (request.id) {\n deleteMemoryRecord(request.id);\n } else if (request.matchText) {\n for (const existing of listMemoryRecords({\n providerId: this.id,\n agentId: request.scope?.agentId ?? this.agentId,\n workspaceId: request.scope?.workspaceId ?? this.workspaceDir,\n kind: target === 'user' ? 'user_profile' : 'agent_note',\n limit: 200,\n })) {\n if (existing.content.includes(request.matchText)) {\n deleteMemoryRecord(existing.id);\n }\n }\n }\n return { success: true, message: result.message };\n }\n\n sync(event: MemorySyncEvent): void {\n if (event.type !== 'signal') return;\n appendMemorySignal({\n signal: event.signal,\n providerId: this.id,\n agentId: this.agentId,\n workspaceId: this.workspaceDir,\n sessionKey:\n typeof event.signal.metadata?.sessionKey === 'string'\n ? event.signal.metadata.sessionKey\n : undefined,\n });\n }\n\n async shutdown(): Promise<void> {}\n\n private canReadRecord(record: MemoryRecord, scope: MemoryReadRequest['scope']): boolean {\n if (this.accessPolicy) return this.accessPolicy.canReadRecord(record, scope);\n if (record.scope.agentId !== this.agentId) return false;\n if (record.scope.sessionKey && record.scope.sessionKey !== scope?.sessionKey) return false;\n if (record.scope.projectId && record.scope.projectId !== scope?.projectId) return false;\n return true;\n }\n}\n\nfunction inferKindFromPath(path: string): MemoryRecord['kind'] {\n const normalized = path.replace(/\\\\/g, '/');\n if (normalized === 'user/MEMORY.md' || normalized.endsWith('/user/MEMORY.md')) return 'user_profile';\n if (/^memory\\/\\d{4}-\\d{2}-\\d{2}\\.md$/.test(normalized)) return 'daily_note';\n if (normalized.endsWith('MEMORY.md')) return 'agent_note';\n return 'workspace_fact';\n}\n\nfunction targetForKind(kind: MemoryRecord['kind']): 'memory' | 'user' {\n return kind === 'user_profile' || kind === 'preference' || kind === 'relationship' ||\n kind === 'routine' || kind === 'personal_logistics'\n ? 'user'\n : 'memory';\n}\n\nfunction sourcePathForTarget(target: 'memory' | 'user'): string {\n return target === 'user' ? 'user/MEMORY.md' : 'MEMORY.md';\n}\n\nfunction parseLineAddress(id: string): { path: string; lineStart?: number; lineEnd?: number } {\n const match = /^(.*)#L(\\d+)(?:-L(\\d+))?$/.exec(id);\n if (!match) return { path: id };\n const lineStart = Number.parseInt(match[2] ?? '1', 10);\n const lineEnd = Number.parseInt(match[3] ?? match[2] ?? '1', 10);\n return {\n path: match[1] ?? id,\n lineStart: Number.isFinite(lineStart) ? lineStart : undefined,\n lineEnd: Number.isFinite(lineEnd) ? lineEnd : undefined,\n };\n}\n"],"mappings":"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"}
@@ -4,6 +4,7 @@ import type { UserContextPlan } from './types.js';
4
4
  export declare class UserContextPlanner {
5
5
  plan(params: {
6
6
  memoryManager: MemoryManager;
7
+ agentId: string;
7
8
  sessionKey: string;
8
9
  query: string;
9
10
  userMessage: AgentMessage;
@@ -28,11 +28,12 @@ function scoreResult(result, now) {
28
28
  const freshness = Math.exp(-ageDays / 180);
29
29
  return Math.max(0, Math.min(1, result.score * .5 + confidence * .15 + result.record.importance * .2 + explicitness * .1 + freshness * .05));
30
30
  }
31
- function citationFor(result) {
31
+ function citationFor(result, requesterAgentId) {
32
32
  const base = result.citation.path ?? `${result.citation.providerId}:${result.citation.recordId}`;
33
- if (result.citation.lineStart == null) return base;
33
+ const ownerPrefix = result.record.scope.agentId !== requesterAgentId ? `shared-from-agent:${result.record.scope.agentId} ` : "";
34
+ if (result.citation.lineStart == null) return `${ownerPrefix}${base}`;
34
35
  const end = result.citation.lineEnd && result.citation.lineEnd !== result.citation.lineStart ? `-L${result.citation.lineEnd}` : "";
35
- return `${base}#L${result.citation.lineStart}${end}`;
36
+ return `${ownerPrefix}${base}#L${result.citation.lineStart}${end}`;
36
37
  }
37
38
  function prependContext(message, block) {
38
39
  if (!block) return message;
@@ -79,7 +80,10 @@ var UserContextPlanner = class {
79
80
  const started = Date.now();
80
81
  const results = await params.memoryManager.search({
81
82
  query,
82
- scope: { sessionKey: params.sessionKey },
83
+ scope: {
84
+ agentId: params.agentId,
85
+ sessionKey: params.sessionKey
86
+ },
83
87
  maxResults: MAX_RESULTS,
84
88
  minScore: .15
85
89
  }).catch(() => []);
@@ -114,7 +118,7 @@ var UserContextPlanner = class {
114
118
  content,
115
119
  score,
116
120
  section: sectionFor(result.record),
117
- citation: citationFor(result)
121
+ citation: citationFor(result, params.agentId)
118
122
  });
119
123
  }
120
124
  const sections = [];
@@ -1 +1 @@
1
- {"version":3,"file":"planner.js","names":[],"sources":["../../../../../src/agent/memory/context/planner.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport { appendMemoryTraceEvent } from '../../../storage/sqlite/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport { readAgentMessageContent } from '../agent-message-access.js';\nimport { buildUserContextBlock } from '../context-fence.js';\nimport type { MemoryManager } from '../manager.js';\nimport type { MemoryRecord, MemorySearchResult } from '../types.js';\nimport type {\n PlannedUserContextItem,\n UserContextPlan,\n UserContextRejectionReason,\n} from './types.js';\n\nconst MAX_CONTEXT_CHARS = 6_000;\nconst MAX_RESULTS = 8;\nconst log = createLogger('UserContextPlanner');\n\nfunction sectionFor(record: MemoryRecord): PlannedUserContextItem['section'] {\n if (record.kind === 'boundary') return 'safety';\n if (\n record.kind === 'preference' ||\n record.kind === 'user_profile' ||\n record.kind === 'relationship' ||\n record.kind === 'routine' ||\n record.kind === 'personal_logistics' ||\n record.kind === 'tool_preference'\n ) return 'interaction';\n return 'task';\n}\n\nfunction rejectReason(record: MemoryRecord, now: number): UserContextRejectionReason | undefined {\n if (record.validFrom && Date.parse(record.validFrom) > now) return 'not_yet_valid';\n if (\n (record.validTo && Date.parse(record.validTo) < now) ||\n (record.expiresAt && Date.parse(record.expiresAt) < now)\n ) return 'expired';\n if (record.sensitivity === 'secret' || record.sensitivity === 'regulated') return 'sensitive';\n if (record.disclosurePolicy === 'ask_before_reference') return 'requires_consent';\n return undefined;\n}\n\nfunction scoreResult(result: MemorySearchResult, now: number): number {\n const confidence = result.record.confidence ?? 0.5;\n const explicitness = result.record.explicitness === 'explicit'\n ? 1\n : result.record.explicitness === 'observed' ? 0.65 : 0.4;\n const ageDays = Math.max(0, (now - Date.parse(result.record.updatedAt)) / 86_400_000);\n const freshness = Math.exp(-ageDays / 180);\n return Math.max(0, Math.min(1,\n result.score * 0.5 + confidence * 0.15 + result.record.importance * 0.2 + explicitness * 0.1 + freshness * 0.05,\n ));\n}\n\nfunction citationFor(result: MemorySearchResult): string {\n const base = result.citation.path ?? `${result.citation.providerId}:${result.citation.recordId}`;\n if (result.citation.lineStart == null) return base;\n const end = result.citation.lineEnd && result.citation.lineEnd !== result.citation.lineStart\n ? `-L${result.citation.lineEnd}`\n : '';\n return `${base}#L${result.citation.lineStart}${end}`;\n}\n\nfunction prependContext(message: AgentMessage, block: string): AgentMessage {\n if (!block) return message;\n const prefix = `${block}\\n\\n`;\n const content = readAgentMessageContent(message);\n if (typeof content === 'string') return { ...message, content: prefix + content } as AgentMessage;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0] as { type?: string; text?: string };\n if (first.type === 'text' && typeof first.text === 'string') {\n const copy = [...content];\n copy[0] = { type: 'text', text: prefix + first.text };\n return { ...message, content: copy } as AgentMessage;\n }\n return { ...message, content: [{ type: 'text' as const, text: prefix }, ...content] } as AgentMessage;\n }\n return message;\n}\n\nexport class UserContextPlanner {\n async plan(params: {\n memoryManager: MemoryManager;\n sessionKey: string;\n query: string;\n userMessage: AgentMessage;\n }): Promise<UserContextPlan> {\n const traceId = randomUUID();\n const query = params.query.trim();\n if (!query) {\n return { traceId, modelMessage: params.userMessage, items: [], rejected: [], estimatedTokens: 0 };\n }\n const started = Date.now();\n const results = await params.memoryManager.search({\n query,\n scope: { sessionKey: params.sessionKey },\n maxResults: MAX_RESULTS,\n minScore: 0.15,\n }).catch(() => []);\n const now = Date.now();\n const rejected: UserContextPlan['rejected'] = [];\n const ranked = results\n .map((result) => ({ result, score: scoreResult(result, now) }))\n .sort((a, b) => b.score - a.score);\n const items: PlannedUserContextItem[] = [];\n let usedChars = 0;\n for (const { result, score } of ranked) {\n const reason = rejectReason(result.record, now) ?? (score < 0.25 ? 'low_score' : undefined);\n if (reason) {\n rejected.push({ recordId: result.record.id, reason });\n continue;\n }\n const content = result.snippet.trim();\n if (usedChars + content.length > MAX_CONTEXT_CHARS) {\n rejected.push({ recordId: result.record.id, reason: 'budget' });\n continue;\n }\n usedChars += content.length;\n items.push({\n recordId: result.record.id,\n content,\n score,\n section: sectionFor(result.record),\n citation: citationFor(result),\n });\n }\n const sections: string[] = [];\n for (const [section, title] of [['safety', 'Boundaries'], ['task', 'Relevant facts'], ['interaction', 'Interaction preferences']] as const) {\n const sectionItems = items.filter((item) => item.section === section);\n if (sectionItems.length > 0) {\n sections.push(`${title}:\\n${sectionItems.map((item) => `- ${item.content}\\n Source: ${item.citation}`).join('\\n')}`);\n }\n }\n const block = buildUserContextBlock(sections.join('\\n\\n'));\n try {\n appendMemoryTraceEvent({\n traceId,\n phase: 'inject',\n providerId: 'user-understanding',\n sessionKey: params.sessionKey,\n request: { query, rejected },\n resultCount: items.length,\n selectedRecordIds: items.map((item) => item.recordId),\n durationMs: Date.now() - started,\n });\n } catch (err) {\n log.debug({ err, traceId, sessionKey: params.sessionKey }, 'Context plan trace was not persisted');\n }\n return {\n traceId,\n modelMessage: prependContext(params.userMessage, block),\n items,\n rejected,\n estimatedTokens: Math.ceil(block.length / 4),\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"planner.js","names":[],"sources":["../../../../../src/agent/memory/context/planner.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport { appendMemoryTraceEvent } from '../../../storage/sqlite/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport { readAgentMessageContent } from '../agent-message-access.js';\nimport { buildUserContextBlock } from '../context-fence.js';\nimport type { MemoryManager } from '../manager.js';\nimport type { MemoryRecord, MemorySearchResult } from '../types.js';\nimport type {\n PlannedUserContextItem,\n UserContextPlan,\n UserContextRejectionReason,\n} from './types.js';\n\nconst MAX_CONTEXT_CHARS = 6_000;\nconst MAX_RESULTS = 8;\nconst log = createLogger('UserContextPlanner');\n\nfunction sectionFor(record: MemoryRecord): PlannedUserContextItem['section'] {\n if (record.kind === 'boundary') return 'safety';\n if (\n record.kind === 'preference' ||\n record.kind === 'user_profile' ||\n record.kind === 'relationship' ||\n record.kind === 'routine' ||\n record.kind === 'personal_logistics' ||\n record.kind === 'tool_preference'\n ) return 'interaction';\n return 'task';\n}\n\nfunction rejectReason(record: MemoryRecord, now: number): UserContextRejectionReason | undefined {\n if (record.validFrom && Date.parse(record.validFrom) > now) return 'not_yet_valid';\n if (\n (record.validTo && Date.parse(record.validTo) < now) ||\n (record.expiresAt && Date.parse(record.expiresAt) < now)\n ) return 'expired';\n if (record.sensitivity === 'secret' || record.sensitivity === 'regulated') return 'sensitive';\n if (record.disclosurePolicy === 'ask_before_reference') return 'requires_consent';\n return undefined;\n}\n\nfunction scoreResult(result: MemorySearchResult, now: number): number {\n const confidence = result.record.confidence ?? 0.5;\n const explicitness = result.record.explicitness === 'explicit'\n ? 1\n : result.record.explicitness === 'observed' ? 0.65 : 0.4;\n const ageDays = Math.max(0, (now - Date.parse(result.record.updatedAt)) / 86_400_000);\n const freshness = Math.exp(-ageDays / 180);\n return Math.max(0, Math.min(1,\n result.score * 0.5 + confidence * 0.15 + result.record.importance * 0.2 + explicitness * 0.1 + freshness * 0.05,\n ));\n}\n\nfunction citationFor(result: MemorySearchResult, requesterAgentId: string): string {\n const base = result.citation.path ?? `${result.citation.providerId}:${result.citation.recordId}`;\n const ownerPrefix = result.record.scope.agentId !== requesterAgentId\n ? `shared-from-agent:${result.record.scope.agentId} `\n : '';\n if (result.citation.lineStart == null) return `${ownerPrefix}${base}`;\n const end = result.citation.lineEnd && result.citation.lineEnd !== result.citation.lineStart\n ? `-L${result.citation.lineEnd}`\n : '';\n return `${ownerPrefix}${base}#L${result.citation.lineStart}${end}`;\n}\n\nfunction prependContext(message: AgentMessage, block: string): AgentMessage {\n if (!block) return message;\n const prefix = `${block}\\n\\n`;\n const content = readAgentMessageContent(message);\n if (typeof content === 'string') return { ...message, content: prefix + content } as AgentMessage;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0] as { type?: string; text?: string };\n if (first.type === 'text' && typeof first.text === 'string') {\n const copy = [...content];\n copy[0] = { type: 'text', text: prefix + first.text };\n return { ...message, content: copy } as AgentMessage;\n }\n return { ...message, content: [{ type: 'text' as const, text: prefix }, ...content] } as AgentMessage;\n }\n return message;\n}\n\nexport class UserContextPlanner {\n async plan(params: {\n memoryManager: MemoryManager;\n agentId: string;\n sessionKey: string;\n query: string;\n userMessage: AgentMessage;\n }): Promise<UserContextPlan> {\n const traceId = randomUUID();\n const query = params.query.trim();\n if (!query) {\n return { traceId, modelMessage: params.userMessage, items: [], rejected: [], estimatedTokens: 0 };\n }\n const started = Date.now();\n const results = await params.memoryManager.search({\n query,\n scope: { agentId: params.agentId, sessionKey: params.sessionKey },\n maxResults: MAX_RESULTS,\n minScore: 0.15,\n }).catch(() => []);\n const now = Date.now();\n const rejected: UserContextPlan['rejected'] = [];\n const ranked = results\n .map((result) => ({ result, score: scoreResult(result, now) }))\n .sort((a, b) => b.score - a.score);\n const items: PlannedUserContextItem[] = [];\n let usedChars = 0;\n for (const { result, score } of ranked) {\n const reason = rejectReason(result.record, now) ?? (score < 0.25 ? 'low_score' : undefined);\n if (reason) {\n rejected.push({ recordId: result.record.id, reason });\n continue;\n }\n const content = result.snippet.trim();\n if (usedChars + content.length > MAX_CONTEXT_CHARS) {\n rejected.push({ recordId: result.record.id, reason: 'budget' });\n continue;\n }\n usedChars += content.length;\n items.push({\n recordId: result.record.id,\n content,\n score,\n section: sectionFor(result.record),\n citation: citationFor(result, params.agentId),\n });\n }\n const sections: string[] = [];\n for (const [section, title] of [['safety', 'Boundaries'], ['task', 'Relevant facts'], ['interaction', 'Interaction preferences']] as const) {\n const sectionItems = items.filter((item) => item.section === section);\n if (sectionItems.length > 0) {\n sections.push(`${title}:\\n${sectionItems.map((item) => `- ${item.content}\\n Source: ${item.citation}`).join('\\n')}`);\n }\n }\n const block = buildUserContextBlock(sections.join('\\n\\n'));\n try {\n appendMemoryTraceEvent({\n traceId,\n phase: 'inject',\n providerId: 'user-understanding',\n sessionKey: params.sessionKey,\n request: { query, rejected },\n resultCount: items.length,\n selectedRecordIds: items.map((item) => item.recordId),\n durationMs: Date.now() - started,\n });\n } catch (err) {\n log.debug({ err, traceId, sessionKey: params.sessionKey }, 'Context plan trace was not persisted');\n }\n return {\n traceId,\n modelMessage: prependContext(params.userMessage, block),\n items,\n rejected,\n estimatedTokens: Math.ceil(block.length / 4),\n };\n }\n}\n"],"mappings":"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"}
@@ -2,4 +2,4 @@ import type { Config } from '../../config/schema.js';
2
2
  import { BuiltinMemoryStore } from './builtin-memory-store.js';
3
3
  import { MemoryManager } from './manager.js';
4
4
  export type MemoryProviderId = 'none' | 'stub';
5
- export declare function createMemoryManagerFromConfig(_workspaceDir: string, store: BuiltinMemoryStore, config: Config | undefined): MemoryManager;
5
+ export declare function createMemoryManagerFromConfig(workspaceDir: string, store: BuiltinMemoryStore, config: Config | undefined, agentId?: string): MemoryManager;
@@ -1,25 +1,28 @@
1
1
  import { init_agent_scope, resolveAgentIdForWorkspacePath } from "../agent-scope.js";
2
2
  import { resolveEffectiveAgentManifestForAgent } from "../../config/agent-profile.js";
3
3
  import { isMemorySubsystemEnabled } from "./memory-config.js";
4
+ import { resolveMemoryAccessPolicy } from "./access-policy.js";
4
5
  import { BuiltinMemoryProvider } from "./builtin-provider.js";
5
6
  import { MemoryManager } from "./manager.js";
6
7
  import { loadMemoryPluginProviders } from "./plugin-discovery.js";
7
8
  //#region src/agent/memory/create-memory-manager.ts
8
9
  init_agent_scope();
9
- function createMemoryManagerFromConfig(_workspaceDir, store, config) {
10
- const routing = resolveMemoryManagerOptions(_workspaceDir, config);
10
+ function createMemoryManagerFromConfig(workspaceDir, store, config, agentId) {
11
+ const routing = resolveMemoryManagerOptions(workspaceDir, config, agentId);
12
+ const accessPolicy = config && agentId ? resolveMemoryAccessPolicy(config, agentId) : void 0;
11
13
  const enabled = isMemorySubsystemEnabled(config);
12
14
  const mgr = new MemoryManager({
13
15
  ...routing,
16
+ accessPolicy,
14
17
  ...enabled ? { loadProviders: () => loadMemoryPluginProviders({ config }) } : {}
15
18
  });
16
- mgr.addProvider(new BuiltinMemoryProvider(store));
19
+ mgr.addProvider(new BuiltinMemoryProvider(store, accessPolicy));
17
20
  if (!enabled) return mgr;
18
21
  return mgr;
19
22
  }
20
- function resolveMemoryManagerOptions(workspaceDir, config) {
23
+ function resolveMemoryManagerOptions(workspaceDir, config, requestedAgentId) {
21
24
  if (!config) return {};
22
- const providerRouting = resolveEffectiveAgentManifestForAgent(config, resolveAgentIdForWorkspacePath(config, workspaceDir)).memory.providerRouting;
25
+ const providerRouting = resolveEffectiveAgentManifestForAgent(config, requestedAgentId?.trim() || resolveAgentIdForWorkspacePath(config, workspaceDir)).memory.providerRouting;
23
26
  if (!providerRouting) return {};
24
27
  return {
25
28
  searchStrategy: providerRouting.searchStrategy,
@@ -1 +1 @@
1
- {"version":3,"file":"create-memory-manager.js","names":[],"sources":["../../../../src/agent/memory/create-memory-manager.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { resolveEffectiveAgentManifestForAgent } from '../../config/agent-profile.js';\nimport { resolveAgentIdForWorkspacePath } from '../agent-scope.js';\nimport { BuiltinMemoryStore } from './builtin-memory-store.js';\nimport { BuiltinMemoryProvider } from './builtin-provider.js';\nimport { isMemorySubsystemEnabled } from './memory-config.js';\nimport { MemoryManager, type MemoryManagerOptions } from './manager.js';\nimport { loadMemoryPluginProviders } from './plugin-discovery.js';\n\nexport type MemoryProviderId = 'none' | 'stub';\n\nexport function createMemoryManagerFromConfig(\n _workspaceDir: string,\n store: BuiltinMemoryStore,\n config: Config | undefined,\n): MemoryManager {\n const routing = resolveMemoryManagerOptions(_workspaceDir, config);\n const enabled = isMemorySubsystemEnabled(config);\n const mgr = new MemoryManager({\n ...routing,\n ...(enabled ? { loadProviders: () => loadMemoryPluginProviders({ config }) } : {}),\n });\n mgr.addProvider(new BuiltinMemoryProvider(store));\n\n if (!enabled) {\n return mgr;\n }\n\n return mgr;\n}\n\nfunction resolveMemoryManagerOptions(\n workspaceDir: string,\n config: Config | undefined,\n): Omit<MemoryManagerOptions, 'loadProviders'> {\n if (!config) return {};\n const agentId = resolveAgentIdForWorkspacePath(config, workspaceDir);\n const manifest = resolveEffectiveAgentManifestForAgent(config, agentId);\n const providerRouting = manifest.memory.providerRouting;\n if (!providerRouting) return {};\n return {\n searchStrategy: providerRouting.searchStrategy,\n writeStrategy: providerRouting.writeStrategy,\n writePolicy: {\n allowExternalWrites: providerRouting.allowExternalWrites,\n allowedProviderIds: providerRouting.allowedProviderIds,\n autoWriteKinds: providerRouting.autoWriteKinds,\n },\n };\n}\n"],"mappings":";;;;;;;kBAEmE;AASnE,SAAgB,8BACd,eACA,OACA,QACe;CACf,MAAM,UAAU,4BAA4B,eAAe,OAAO;CAClE,MAAM,UAAU,yBAAyB,OAAO;CAChD,MAAM,MAAM,IAAI,cAAc;EAC5B,GAAG;EACH,GAAI,UAAU,EAAE,qBAAqB,0BAA0B,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE;EAClF,CAAC;AACF,KAAI,YAAY,IAAI,sBAAsB,MAAM,CAAC;AAEjD,KAAI,CAAC,QACH,QAAO;AAGT,QAAO;;AAGT,SAAS,4BACP,cACA,QAC6C;AAC7C,KAAI,CAAC,OAAQ,QAAO,EAAE;CAGtB,MAAM,kBADW,sCAAsC,QADvC,+BAA+B,QAAQ,aACe,CACtC,CAAC,OAAO;AACxC,KAAI,CAAC,gBAAiB,QAAO,EAAE;AAC/B,QAAO;EACL,gBAAgB,gBAAgB;EAChC,eAAe,gBAAgB;EAC/B,aAAa;GACX,qBAAqB,gBAAgB;GACrC,oBAAoB,gBAAgB;GACpC,gBAAgB,gBAAgB;GACjC;EACF"}
1
+ {"version":3,"file":"create-memory-manager.js","names":[],"sources":["../../../../src/agent/memory/create-memory-manager.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { resolveEffectiveAgentManifestForAgent } from '../../config/agent-profile.js';\nimport { resolveAgentIdForWorkspacePath } from '../agent-scope.js';\nimport { resolveMemoryAccessPolicy } from './access-policy.js';\nimport { BuiltinMemoryStore } from './builtin-memory-store.js';\nimport { BuiltinMemoryProvider } from './builtin-provider.js';\nimport { isMemorySubsystemEnabled } from './memory-config.js';\nimport { MemoryManager, type MemoryManagerOptions } from './manager.js';\nimport { loadMemoryPluginProviders } from './plugin-discovery.js';\n\nexport type MemoryProviderId = 'none' | 'stub';\n\nexport function createMemoryManagerFromConfig(\n workspaceDir: string,\n store: BuiltinMemoryStore,\n config: Config | undefined,\n agentId?: string,\n): MemoryManager {\n const routing = resolveMemoryManagerOptions(workspaceDir, config, agentId);\n const accessPolicy = config && agentId ? resolveMemoryAccessPolicy(config, agentId) : undefined;\n const enabled = isMemorySubsystemEnabled(config);\n const mgr = new MemoryManager({\n ...routing,\n accessPolicy,\n ...(enabled ? { loadProviders: () => loadMemoryPluginProviders({ config }) } : {}),\n });\n mgr.addProvider(new BuiltinMemoryProvider(\n store,\n accessPolicy,\n ));\n\n if (!enabled) {\n return mgr;\n }\n\n return mgr;\n}\n\nfunction resolveMemoryManagerOptions(\n workspaceDir: string,\n config: Config | undefined,\n requestedAgentId?: string,\n): Omit<MemoryManagerOptions, 'loadProviders'> {\n if (!config) return {};\n const agentId = requestedAgentId?.trim() || resolveAgentIdForWorkspacePath(config, workspaceDir);\n const manifest = resolveEffectiveAgentManifestForAgent(config, agentId);\n const providerRouting = manifest.memory.providerRouting;\n if (!providerRouting) return {};\n return {\n searchStrategy: providerRouting.searchStrategy,\n writeStrategy: providerRouting.writeStrategy,\n writePolicy: {\n allowExternalWrites: providerRouting.allowExternalWrites,\n allowedProviderIds: providerRouting.allowedProviderIds,\n autoWriteKinds: providerRouting.autoWriteKinds,\n },\n };\n}\n"],"mappings":";;;;;;;;kBAEmE;AAUnE,SAAgB,8BACd,cACA,OACA,QACA,SACe;CACf,MAAM,UAAU,4BAA4B,cAAc,QAAQ,QAAQ;CAC1E,MAAM,eAAe,UAAU,UAAU,0BAA0B,QAAQ,QAAQ,GAAG,KAAA;CACtF,MAAM,UAAU,yBAAyB,OAAO;CAChD,MAAM,MAAM,IAAI,cAAc;EAC5B,GAAG;EACH;EACA,GAAI,UAAU,EAAE,qBAAqB,0BAA0B,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE;EAClF,CAAC;AACF,KAAI,YAAY,IAAI,sBAClB,OACA,aACD,CAAC;AAEF,KAAI,CAAC,QACH,QAAO;AAGT,QAAO;;AAGT,SAAS,4BACP,cACA,QACA,kBAC6C;AAC7C,KAAI,CAAC,OAAQ,QAAO,EAAE;CAGtB,MAAM,kBADW,sCAAsC,QADvC,kBAAkB,MAAM,IAAI,+BAA+B,QAAQ,aAAa,CAEhE,CAAC,OAAO;AACxC,KAAI,CAAC,gBAAiB,QAAO,EAAE;AAC/B,QAAO;EACL,gBAAgB,gBAAgB;EAChC,eAAe,gBAAgB;EAC/B,aAAa;GACX,qBAAqB,gBAAgB;GACrC,oBAAoB,gBAAgB;GACpC,gBAAgB,gBAAgB;GACjC;EACF"}
@@ -1,4 +1,5 @@
1
1
  import type { Config } from '../../../config/schema.js';
2
+ import { type MemoryWriteCheckResult } from '../../../agent-runtime/memory-runtime.js';
2
3
  import { type DreamingPhaseId } from './constants.js';
3
4
  export type DreamingLightConfig = {
4
5
  enabled: boolean;
@@ -26,6 +27,7 @@ export type DreamingRemConfig = {
26
27
  };
27
28
  export type DreamingResolvedConfig = {
28
29
  enabled: boolean;
30
+ promotionWritePolicy: MemoryWriteCheckResult;
29
31
  frequency: string;
30
32
  timezone?: string;
31
33
  phases: {
@@ -1,6 +1,7 @@
1
1
  import { init_agent_scope, resolveDefaultAgentId } from "../../agent-scope.js";
2
2
  import { resolveEffectiveAgentManifestForAgent } from "../../../config/agent-profile.js";
3
3
  import { DEFAULT_DEEP_CRON, DEFAULT_LIGHT_CRON, DEFAULT_REM_CRON } from "./constants.js";
4
+ import { buildMemoryRuntime } from "../../../agent-runtime/memory-runtime.js";
4
5
  //#region src/agent/memory/dreaming/config.ts
5
6
  init_agent_scope();
6
7
  function clampScore(value, fallback) {
@@ -31,6 +32,16 @@ function resolveDreamingConfig(cfg, requestedAgentId) {
31
32
  const manifest = cfg && agentId ? resolveEffectiveAgentManifestForAgent(cfg, agentId) : void 0;
32
33
  const dreaming = manifest?.memory.dreaming;
33
34
  const enabled = dreaming?.enabled === true && manifest?.memory.mode !== "off";
35
+ const promotionWritePolicy = manifest ? buildMemoryRuntime(manifest).checkWrite({
36
+ target: "curated",
37
+ content: "Dreaming automatic memory promotion",
38
+ source: "dreaming",
39
+ confidence: 1,
40
+ sensitive: false
41
+ }) : {
42
+ decision: "deny",
43
+ reason: "agent memory manifest is unavailable"
44
+ };
34
45
  const frequency = trimmedStringOr(dreaming?.frequency, DEFAULT_DEEP_CRON);
35
46
  const timezone = optionalTrimmedString(dreaming?.timezone);
36
47
  const lightRaw = dreaming?.phases?.light ?? {};
@@ -43,7 +54,7 @@ function resolveDreamingConfig(cfg, requestedAgentId) {
43
54
  };
44
55
  const deepRaw = dreaming?.phases?.deep ?? {};
45
56
  const deep = {
46
- enabled: enabled && deepRaw?.enabled !== false,
57
+ enabled: enabled && deepRaw?.enabled !== false && promotionWritePolicy.decision === "allow",
47
58
  cron: trimmedStringOr(deepRaw?.cron, frequency),
48
59
  minScore: clampScore(Number(deepRaw?.minScore), .8),
49
60
  minRecallCount: toPositiveInt(deepRaw?.minRecallCount, 3),
@@ -62,6 +73,7 @@ function resolveDreamingConfig(cfg, requestedAgentId) {
62
73
  };
63
74
  return {
64
75
  enabled,
76
+ promotionWritePolicy,
65
77
  frequency,
66
78
  ...timezone ? { timezone } : {},
67
79
  phases: {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/config.ts"],"sourcesContent":["import type { Config } from '../../../config/schema.js';\nimport { resolveDefaultAgentId } from '../../agent-scope.js';\nimport { resolveEffectiveAgentManifestForAgent } from '../../../config/agent-profile.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/** Resolve the full three-phase dreaming config from an agent manifest. */\nexport function resolveDreamingConfig(cfg: Config | undefined, requestedAgentId?: string | null): DreamingResolvedConfig {\n const agentId = cfg ? (requestedAgentId?.trim() || resolveDefaultAgentId(cfg)) : undefined;\n const manifest = cfg && agentId ? resolveEffectiveAgentManifestForAgent(cfg, agentId) : undefined;\n const dreaming = manifest?.memory.dreaming;\n const enabled = dreaming?.enabled === true && manifest?.memory.mode !== 'off';\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"],"mappings":";;;;kBAC6D;AAsD7D,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;;;AAMpE,SAAgB,sBAAsB,KAAyB,kBAA0D;CACvH,MAAM,UAAU,MAAO,kBAAkB,MAAM,IAAI,sBAAsB,IAAI,GAAI,KAAA;CACjF,MAAM,WAAW,OAAO,UAAU,sCAAsC,KAAK,QAAQ,GAAG,KAAA;CACxF,MAAM,WAAW,UAAU,OAAO;CAClC,MAAM,UAAU,UAAU,YAAY,QAAQ,UAAU,OAAO,SAAS;CAExE,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
+ {"version":3,"file":"config.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/config.ts"],"sourcesContent":["import type { Config } from '../../../config/schema.js';\nimport { buildMemoryRuntime, type MemoryWriteCheckResult } from '../../../agent-runtime/memory-runtime.js';\nimport { resolveDefaultAgentId } from '../../agent-scope.js';\nimport { resolveEffectiveAgentManifestForAgent } from '../../../config/agent-profile.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 promotionWritePolicy: MemoryWriteCheckResult;\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/** Resolve the full three-phase dreaming config from an agent manifest. */\nexport function resolveDreamingConfig(cfg: Config | undefined, requestedAgentId?: string | null): DreamingResolvedConfig {\n const agentId = cfg ? (requestedAgentId?.trim() || resolveDefaultAgentId(cfg)) : undefined;\n const manifest = cfg && agentId ? resolveEffectiveAgentManifestForAgent(cfg, agentId) : undefined;\n const dreaming = manifest?.memory.dreaming;\n const enabled = dreaming?.enabled === true && manifest?.memory.mode !== 'off';\n const promotionWritePolicy = manifest\n ? buildMemoryRuntime(manifest).checkWrite({\n target: 'curated',\n content: 'Dreaming automatic memory promotion',\n source: 'dreaming',\n confidence: 1,\n sensitive: false,\n })\n : { decision: 'deny' as const, reason: 'agent memory manifest is unavailable' };\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 && promotionWritePolicy.decision === 'allow',\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 promotionWritePolicy,\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"],"mappings":"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"}
@@ -10,9 +10,11 @@ export type DreamingPromotionCandidate = DreamingStoreEntry & {
10
10
  recencyDecay: number;
11
11
  };
12
12
  export declare function runDreamingDeepPromotion(params: {
13
+ agentId: string;
13
14
  workspaceDir: string;
14
15
  dreamingRoot: string;
15
16
  config?: Partial<DreamingDeepConfig>;
17
+ sensitiveWritePolicy?: 'deny' | 'confirm' | 'allow';
16
18
  memoryManager?: MemoryManager;
17
19
  now?: Date;
18
20
  }): Promise<{
@@ -2,8 +2,10 @@ import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
3
  import { MEMORY_MD_FILENAME } from "./constants.js";
4
4
  import { clamp01, compareCandidatesByScore, computeCandidateScore, extractPromotionMarkers, isContaminatedSnippet, isExpiredEntry, isoDay, readFileLines, resolveDeepDefaults, sliceRange, snippetHash } from "./utils.js";
5
- import { loadDreamingStore, saveDreamingStore, withDreamingPromotionLock } from "./short-term-store.js";
5
+ import { loadDreamingStore, saveDreamingStore, withDreamingStoreLock } from "./short-term-store.js";
6
+ import { inferMemorySensitivity } from "../sensitivity.js";
6
7
  import { emptyDeepPhaseSkipped, writeDreamingDeepLastRun } from "./last-run.js";
8
+ import { activateDreamingPromotion } from "./promotion-lifecycle.js";
7
9
  import path from "node:path";
8
10
  import fs from "node:fs/promises";
9
11
  //#region src/agent/memory/dreaming/deep-promotion.ts
@@ -80,7 +82,7 @@ async function runDreamingDeepPromotion(params) {
80
82
  };
81
83
  }
82
84
  try {
83
- const result = await withDreamingPromotionLock(params.dreamingRoot, async () => {
85
+ const result = await withDreamingStoreLock(params.dreamingRoot, async () => {
84
86
  const { store } = await loadDreamingStore({ dreamingRoot: params.dreamingRoot });
85
87
  const nowMs = now.getTime();
86
88
  const ranked = Object.values(store.entries ?? {}).filter((e) => {
@@ -134,6 +136,11 @@ async function runDreamingDeepPromotion(params) {
134
136
  skipped.contaminated += 1;
135
137
  continue;
136
138
  }
139
+ const sensitivity = inferMemorySensitivity(rehydrated.snippet);
140
+ if (sensitivity !== "normal" && params.sensitiveWritePolicy !== "allow") {
141
+ skipped.contaminated += 1;
142
+ continue;
143
+ }
137
144
  const hash = snippetHash(rehydrated.snippet);
138
145
  if (existingMarkers.hashes.has(hash)) {
139
146
  skipped.hashDuplicate += 1;
@@ -150,7 +157,8 @@ async function runDreamingDeepPromotion(params) {
150
157
  endLine: rehydrated.endLine,
151
158
  score: candidate.score,
152
159
  recallCount: candidate.recallCount,
153
- avgScore: candidate.avgScore
160
+ avgScore: candidate.avgScore,
161
+ sensitivity
154
162
  });
155
163
  }
156
164
  if (appliedCandidates.length === 0) {
@@ -181,6 +189,19 @@ async function runDreamingDeepPromotion(params) {
181
189
  }
182
190
  sectionLines.push("");
183
191
  const next = `${header}${existing.endsWith("\n") || existing.length === 0 ? existing : `${existing}\n`}${sectionLines.join("\n")}`;
192
+ for (const c of appliedCandidates) activateDreamingPromotion({
193
+ agentId: params.agentId,
194
+ workspaceId: params.workspaceDir,
195
+ candidateKey: c.key,
196
+ content: c.snippet,
197
+ sourcePath: c.path,
198
+ lineStart: c.startLine,
199
+ lineEnd: c.endLine,
200
+ score: c.score,
201
+ recallCount: c.recallCount,
202
+ observedAt: now.toISOString(),
203
+ sensitivity: c.sensitivity
204
+ });
184
205
  await fs.mkdir(path.dirname(memoryPath), { recursive: true });
185
206
  await fs.writeFile(memoryPath, next, "utf-8");
186
207
  const nowIso = now.toISOString();