@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.
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DtONoxBN.js → agent-avatar-dicebear-BRTCpm3t.js} +1 -1
- package/dist/gateway/static/root/assets/agents-Bd863Akz.js +2 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-BRBxLECY.js → app-management-settings-panel-DaMMZBAT.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-ChvyuSEt.js → appearance-settings-BXHThPyM.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-DgHWTnjs.js → apps-page-B4omjLxa.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-CdIoagem.js → archive-plugin-izB-4N4L.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-Ch411Kht.js → attachment-load-CJihXa5y.js} +1 -1
- package/dist/gateway/static/root/assets/{automation-suggestion-card-SVq27yw2.js → automation-suggestion-card-fgtj5Gek.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-CFt5Ik4q.js → automations-page-Dz2mgjIR.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-D8cV-emn.js → binary-plugins-D3VUeG8s.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-CXDkby6y.js → block-editor-KnA0sLI3.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-settings-page-ColJPwer.js → browser-settings-page-DZZz5v_i.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-api-DLxI--Ge.js → capability-presets-api-D8rRNhc6.js} +1 -1
- package/dist/gateway/static/root/assets/{capability-presets-settings-panel-DKyRbnlH.js → capability-presets-settings-panel-sCHojZr4.js} +1 -1
- package/dist/gateway/static/root/assets/{channel-recipient-api-DllrPmp-.js → channel-recipient-api-BWgqwC5h.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-BDLHV3Jx.js → channels-settings-UyVSnf9s.js} +1 -1
- package/dist/gateway/static/root/assets/channels-status-swr-CB5FzcLf.js +1 -0
- package/dist/gateway/static/root/assets/{connectors-page-CA752gY8.js → connectors-page-BzhHiUO4.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Bz9ommjr.js → desktop-pet-CzdqX001.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BnLgxgoR.js → desktop-pet-settings-DqqUPC7G.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-DLsCwFaf.js → directory-picker-path-field-PzlO5tSM.js} +1 -1
- package/dist/gateway/static/root/assets/{dreaming-settings-BzkF1-XT.js → dreaming-settings-BmL54kQq.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CdERvf3L.js → extension-debug-page-DcW8Ie3r.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-D1fz474Z.js → extension-page-DT5cpace.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DoQMkNOK.js → extension-settings-page-CbMk4GhQ.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-BID89uCH.js → fetch-06q5eCMA.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-Rygo8UAs.js → gateway-config-api-4VXUJtLz.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-kb8KIeQL.js → gateway-settings-CdghmKHJ.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BkrLLlpE.js → gateway-startup-retry-2f7_vsv7.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-create-dialog-DVAHnifk.js → goal-create-dialog-CAlsM9MP.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-detail-page-BuOEQZn_.js → goal-detail-page-CLPa4F2y.js} +1 -1
- package/dist/gateway/static/root/assets/{goals-config-api-BuY6-l0a.js → goals-config-api-BpuQTufF.js} +1 -1
- package/dist/gateway/static/root/assets/{goals-page-WV4cHvD-.js → goals-page-B2VpdzfH.js} +1 -1
- package/dist/gateway/static/root/assets/{goals-settings-DoH5fZWo.js → goals-settings-CW1NwxvV.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-BqDs48B-.js → heartbeat-settings-C86k5tff.js} +1 -1
- package/dist/gateway/static/root/assets/{index-CrPRlGMg.js → index-ehajXmqL.js} +31 -31
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-D51yogNZ.js → keyboard-shortcuts-settings-8xwKEhui.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CL22jleU.js → logs-page-C_BMONOO.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-CSt32FWE.js → markdown-split-zS4KLNAf.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-ByItHxBj.js → media-plugins-_BgNJ9_7.js} +1 -1
- package/dist/gateway/static/root/assets/{messages-DbNQuFdA.js → messages-B-8CqAeX.js} +2 -2
- package/dist/gateway/static/root/assets/{models-hub-panel-BkV9hDc-.js → models-hub-panel-Do_cwNjF.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-BK9yydrL.js → notes-page-5IdlPHaX.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-workbench-Dd0v-hK2.js → notes-workbench-0KsRZJIZ.js} +2 -2
- package/dist/gateway/static/root/assets/{page-tabs-DOfMaq_L.js → page-tabs-B7sGQkgU.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-BArxASu7.js → preview-open-alternatives-D1ri4s_O.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-DSPhB3do.js → project-detail-page-Dk2zB1gy.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-C-fZk1f7.js → projects-page-CJQntm2G.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-BGaVc3t7.js → remote-access-hub-CHeZZg7O.js} +1 -1
- package/dist/gateway/static/root/assets/{save-bar-controls-BRxlkhG8.js → save-bar-controls-BClrOinh.js} +1 -1
- package/dist/gateway/static/root/assets/{schedule-field-BzM1iyOc.js → schedule-field-CL7YTwLV.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-ChVcm0DX.js → schema-form-ww4PiIje.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-DbnzgQOP.js → sessions-page-9Hb_r0AG.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-PmzVFvAv.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-BcD9xrvY.js → settings-collapsible-section-D9gEEVm2.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-Cu30CXVl.js → settings-form-section-DGeEoBkb.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-loading-skeleton-Cfd37IYb.js → settings-loading-skeleton-BXUeMR37.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-EINHyzLo.js → settings-page-C5G2klUB.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-C15zixct.js → settings-page-layout-CEepfbCa.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-Bu7SdpD4.js → setup-status-panel-oQ8OLnw3.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-CjjAFV-v.js → share-preview-page-CXtDHMSi.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-06IYvwDt.js → shares-settings-BlNoairj.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BYV5x1KO.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-3W2-wDyO.js → skills-page-ClBcKQZP.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-DlQMtzPf.js → system-settings-panel-W6MBJXrr.js} +1 -1
- package/dist/gateway/static/root/assets/{typed-models-lib-BS1BwExE.js → typed-models-lib-BkODXN7T.js} +1 -1
- package/dist/gateway/static/root/assets/{use-channel-catalog-EA4hfbsP.js → use-channel-catalog-CTbwLZXc.js} +1 -1
- package/dist/gateway/static/root/assets/{user-profile-settings-panel-B7RCdmSp.js → user-profile-settings-panel-CeC308-E.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-BrhEgVaa.js → utils-ZxrKHxyb.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-BPn1ZEga.js → voice-api-key-field-BE57S-nS.js} +1 -1
- package/dist/gateway/static/root/assets/{work-item-detail-page-BQGTTsz1.js → work-item-detail-page-Di1ww5Aa.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-na-N4jZ6.js → workflow-run-setup-panel-CzK84i-B.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-start-dialog-BZCY7N42.js → workflow-start-dialog-CtLTtNUB.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-CjeVDs4h.js → workflows-page-CZFZdua9.js} +1 -1
- package/dist/gateway/static/root/index.html +4 -4
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +13 -21
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/background-review/run-background-review.js +1 -0
- package/dist/src/agent/background-review/run-background-review.js.map +1 -1
- package/dist/src/agent/memory/access-policy.d.ts +12 -0
- package/dist/src/agent/memory/access-policy.js +44 -0
- package/dist/src/agent/memory/access-policy.js.map +1 -0
- package/dist/src/agent/memory/builtin-provider.d.ts +4 -1
- package/dist/src/agent/memory/builtin-provider.js +51 -16
- package/dist/src/agent/memory/builtin-provider.js.map +1 -1
- package/dist/src/agent/memory/context/planner.d.ts +1 -0
- package/dist/src/agent/memory/context/planner.js +9 -5
- package/dist/src/agent/memory/context/planner.js.map +1 -1
- package/dist/src/agent/memory/create-memory-manager.d.ts +1 -1
- package/dist/src/agent/memory/create-memory-manager.js +8 -5
- package/dist/src/agent/memory/create-memory-manager.js.map +1 -1
- package/dist/src/agent/memory/dreaming/config.d.ts +2 -0
- package/dist/src/agent/memory/dreaming/config.js +13 -1
- package/dist/src/agent/memory/dreaming/config.js.map +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +2 -0
- package/dist/src/agent/memory/dreaming/deep-promotion.js +24 -3
- package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -0
- package/dist/src/agent/memory/dreaming/light-sweep.js +184 -16
- package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
- package/dist/src/agent/memory/dreaming/promotion-lifecycle.d.ts +30 -0
- package/dist/src/agent/memory/dreaming/promotion-lifecycle.js +85 -0
- package/dist/src/agent/memory/dreaming/promotion-lifecycle.js.map +1 -0
- package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +4 -0
- package/dist/src/agent/memory/dreaming/rem-patterns.js +76 -53
- package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.d.ts +10 -0
- package/dist/src/agent/memory/dreaming/short-term-store.js +157 -79
- package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
- package/dist/src/agent/memory/manager.d.ts +7 -0
- package/dist/src/agent/memory/manager.js +31 -6
- package/dist/src/agent/memory/manager.js.map +1 -1
- package/dist/src/agent/memory/memory-config.d.ts +1 -1
- package/dist/src/agent/memory/memory-config.js +3 -3
- package/dist/src/agent/memory/memory-config.js.map +1 -1
- package/dist/src/agent/memory/sensitivity.d.ts +3 -0
- package/dist/src/agent/memory/sensitivity.js +13 -0
- package/dist/src/agent/memory/sensitivity.js.map +1 -0
- package/dist/src/agent/memory/understanding/service.js +10 -14
- package/dist/src/agent/memory/understanding/service.js.map +1 -1
- package/dist/src/agent/memory/user-context-coordinator.d.ts +1 -0
- package/dist/src/agent/memory/user-context-coordinator.js +2 -0
- package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +8 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +3 -12
- package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.js +14 -2
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/memory-tool.d.ts +3 -0
- package/dist/src/agent/tools/memory-tool.js +6 -3
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/agent/workspace-runtime/registry.d.ts +6 -6
- package/dist/src/agent/workspace-runtime/registry.js +19 -12
- package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
- package/dist/src/agent-manifest/schema.d.ts +4 -0
- package/dist/src/agent-manifest/schema.js +2 -1
- package/dist/src/agent-manifest/schema.js.map +1 -1
- package/dist/src/agent-runtime/index.js +1 -1
- package/dist/src/agent-runtime/runtime-profile.js +1 -1
- package/dist/src/config/schema.d.ts +4 -0
- package/dist/src/gateway/hono/lib/config-payload.d.ts +2 -0
- package/dist/src/gateway/hono/routes/dreaming.js +28 -21
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
- package/dist/src/gateway/hono/routes/memory.js +16 -4
- package/dist/src/gateway/hono/routes/memory.js.map +1 -1
- package/dist/src/storage/sqlite/fts.d.ts +6 -0
- package/dist/src/storage/sqlite/fts.js +70 -1
- package/dist/src/storage/sqlite/fts.js.map +1 -1
- package/dist/src/storage/sqlite/memory-index-repository.js +16 -7
- package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
- package/dist/src/storage/sqlite/memory-records-repository.d.ts +18 -0
- package/dist/src/storage/sqlite/memory-records-repository.js +55 -8
- package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-Dl9EWnUh.js +0 -2
- package/dist/gateway/static/root/assets/channels-status-swr-EUwWYx8l.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CuDBoz5k.js +0 -1
- 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:
|
|
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:
|
|
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:
|
|
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":"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"}
|
|
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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"}
|
|
@@ -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
|
-
|
|
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: {
|
|
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(
|
|
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(
|
|
10
|
-
const routing = resolveMemoryManagerOptions(
|
|
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
|
|
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":"
|
|
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,
|
|
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
|
|
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();
|