pi-fabric 0.88.2 → 0.89.0
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/chunks/chunk-5SU3YXBS.js +15 -0
- package/dist/chunks/chunk-5SU3YXBS.js.map +7 -0
- package/dist/chunks/{chunk-73YWS2PJ.js → chunk-7X72JCGN.js} +4 -4
- package/dist/chunks/{chunk-ZV5AXJYG.js → chunk-BOCWQOTG.js} +2 -2
- package/dist/chunks/{chunk-WJW47JBN.js → chunk-G23OLG5P.js} +7 -7
- package/dist/chunks/{chunk-AIN5KTE6.js → chunk-GUQT67PQ.js} +600 -70
- package/dist/chunks/chunk-GUQT67PQ.js.map +7 -0
- package/dist/chunks/{chunk-CXUYJNP7.js → chunk-HDPGQRHV.js} +3 -3
- package/dist/chunks/{chunk-ZKJ62VD3.js → chunk-J7BQS5XH.js} +4 -1
- package/dist/chunks/{chunk-ZKJ62VD3.js.map → chunk-J7BQS5XH.js.map} +2 -2
- package/dist/chunks/{chunk-NFHAYIIQ.js → chunk-JQJBQA2C.js} +3 -5
- package/dist/chunks/{chunk-NFHAYIIQ.js.map → chunk-JQJBQA2C.js.map} +1 -1
- package/dist/chunks/{chunk-4RCPQIN2.js → chunk-M3R56VXZ.js} +4 -4
- package/dist/chunks/{chunk-KWBZBSMX.js → chunk-MYCDJTSM.js} +34 -20
- package/dist/chunks/{chunk-KWBZBSMX.js.map → chunk-MYCDJTSM.js.map} +2 -2
- package/dist/chunks/{chunk-XMLNV3QH.js → chunk-TDCMU5L4.js} +2 -2
- package/dist/chunks/{chunk-B7INQVFM.js → chunk-TQR7IE6H.js} +6 -6
- package/dist/chunks/{chunk-HOKY6UCZ.js → chunk-UTR3I23Z.js} +5 -3
- package/dist/chunks/chunk-UTR3I23Z.js.map +7 -0
- package/dist/chunks/chunk-XB3RJVT4.js +17 -0
- package/dist/chunks/chunk-XB3RJVT4.js.map +7 -0
- package/dist/chunks/{chunk-L6R3Y7XI.js → chunk-Y7V2ZTMF.js} +1470 -913
- package/dist/chunks/chunk-Y7V2ZTMF.js.map +7 -0
- package/dist/chunks/{chunk-LUADHXOA.js → chunk-YIDC2IVN.js} +28 -15
- package/dist/chunks/chunk-YIDC2IVN.js.map +7 -0
- package/dist/chunks/{chunk-LBSO3BIH.js → chunk-Z43ZKIZT.js} +76 -5
- package/dist/chunks/chunk-Z43ZKIZT.js.map +7 -0
- package/dist/core/action-registry.js +3 -3
- package/dist/entropy/index.js +5 -5
- package/dist/fabric-runtime-state.js +42 -44
- package/dist/fabric-runtime-state.js.map +1 -1
- package/dist/index.js +542 -50
- package/dist/index.js.map +4 -4
- package/dist/memory/client.d.ts +31 -0
- package/dist/memory/client.d.ts.map +1 -0
- package/dist/memory/context.d.ts +2 -0
- package/dist/memory/context.d.ts.map +1 -1
- package/dist/memory/discovery.js +2 -2
- package/dist/memory/expand-service.d.ts +1 -1
- package/dist/memory/expand-service.d.ts.map +1 -1
- package/dist/memory/host-source.d.ts +59 -0
- package/dist/memory/host-source.d.ts.map +1 -0
- package/dist/memory/index.d.ts +7 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/lineage.d.ts +5 -0
- package/dist/memory/lineage.d.ts.map +1 -1
- package/dist/memory/normalize.d.ts +21 -3
- package/dist/memory/normalize.d.ts.map +1 -1
- package/dist/memory/normalize.js +3 -1
- package/dist/memory/portable.d.ts +64 -0
- package/dist/memory/portable.d.ts.map +1 -0
- package/dist/memory/recall-service.d.ts +1 -1
- package/dist/memory/recall-service.d.ts.map +1 -1
- package/dist/memory/request-cache.d.ts +2 -2
- package/dist/memory/request-cache.d.ts.map +1 -1
- package/dist/memory/request-context.d.ts +3 -0
- package/dist/memory/request-context.d.ts.map +1 -1
- package/dist/memory/search.js +2 -2
- package/dist/memory/sessions-service.d.ts +1 -1
- package/dist/memory/sessions-service.d.ts.map +1 -1
- package/dist/memory/source-observation.d.ts +6 -0
- package/dist/memory/source-observation.d.ts.map +1 -1
- package/dist/memory.d.ts +6 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +79 -0
- package/dist/memory.js.map +7 -0
- package/dist/providers/memory-provider.d.ts +15 -0
- package/dist/providers/memory-provider.d.ts.map +1 -1
- package/dist/providers/memory-provider.js +6 -4
- package/dist/residency/host.js +8 -8
- package/dist/residency/pi-entry.js +8 -8
- package/dist/runtime/core-override-guest-types.js +2 -2
- package/dist/runtime/guest-types.d.ts +1 -1
- package/dist/runtime/guest-types.d.ts.map +1 -1
- package/dist/runtime/guest-types.js +1 -1
- package/dist/runtime/monty-runtime.js +2 -2
- package/dist/runtime/typescript-kernel.js +2 -2
- package/dist/ui/controller.d.ts.map +1 -1
- package/dist/ui/conversation-chrome.d.ts +1 -1
- package/dist/ui/conversation-chrome.d.ts.map +1 -1
- package/dist/ui/conversation-chrome.js +2 -1
- package/dist/ui/conversation-host.d.ts +7 -0
- package/dist/ui/conversation-host.d.ts.map +1 -0
- package/dist/ui/conversation-host.js +9 -0
- package/dist/ui/conversation-host.js.map +7 -0
- package/dist/ui/conversation-native-reader.d.ts +1 -1
- package/dist/ui/conversation-native-reader.d.ts.map +1 -1
- package/dist/ui/conversation-native-reader.js +6 -6
- package/dist/ui/conversation-native-reader.js.map +2 -2
- package/dist/ui/conversation-render.d.ts +1 -1
- package/dist/ui/conversation-render.d.ts.map +1 -1
- package/dist/ui/conversation.js +19 -28
- package/dist/ui/conversation.js.map +2 -2
- package/dist/ui/dashboard.js +6 -7
- package/dist/ui/dashboard.js.map +1 -1
- package/dist/ui/settings-component.d.ts +2 -2
- package/dist/ui/settings-component.d.ts.map +1 -1
- package/dist/ui/settings-rpc.d.ts +2 -2
- package/dist/ui/settings-rpc.d.ts.map +1 -1
- package/dist/ui/settings-sections.d.ts +2 -2
- package/dist/ui/settings-sections.d.ts.map +1 -1
- package/dist/ui/settings-submenus.d.ts +1 -1
- package/dist/ui/settings-submenus.d.ts.map +1 -1
- package/dist/ui/settings.d.ts +3 -3
- package/dist/ui/settings.d.ts.map +1 -1
- package/dist/ui/settings.js +3 -19
- package/dist/ui/settings.js.map +3 -3
- package/docs/memory-recall.md +52 -2
- package/package.json +5 -1
- package/dist/chunks/chunk-AIN5KTE6.js.map +0 -7
- package/dist/chunks/chunk-HOKY6UCZ.js.map +0 -7
- package/dist/chunks/chunk-K344VGRR.js +0 -506
- package/dist/chunks/chunk-K344VGRR.js.map +0 -7
- package/dist/chunks/chunk-L6R3Y7XI.js.map +0 -7
- package/dist/chunks/chunk-LBSO3BIH.js.map +0 -7
- package/dist/chunks/chunk-LUADHXOA.js.map +0 -7
- package/dist/chunks/chunk-VE5LH2Z7.js +0 -74
- package/dist/chunks/chunk-VE5LH2Z7.js.map +0 -7
- package/dist/chunks/chunk-Z3AEX7SQ.js +0 -574
- package/dist/chunks/chunk-Z3AEX7SQ.js.map +0 -7
- /package/dist/chunks/{chunk-73YWS2PJ.js.map → chunk-7X72JCGN.js.map} +0 -0
- /package/dist/chunks/{chunk-ZV5AXJYG.js.map → chunk-BOCWQOTG.js.map} +0 -0
- /package/dist/chunks/{chunk-WJW47JBN.js.map → chunk-G23OLG5P.js.map} +0 -0
- /package/dist/chunks/{chunk-CXUYJNP7.js.map → chunk-HDPGQRHV.js.map} +0 -0
- /package/dist/chunks/{chunk-4RCPQIN2.js.map → chunk-M3R56VXZ.js.map} +0 -0
- /package/dist/chunks/{chunk-XMLNV3QH.js.map → chunk-TDCMU5L4.js.map} +0 -0
- /package/dist/chunks/{chunk-B7INQVFM.js.map → chunk-TQR7IE6H.js.map} +0 -0
|
@@ -4,13 +4,20 @@ import {
|
|
|
4
4
|
DEFAULT_REGEX_MAX_HAYSTACK_TERMS,
|
|
5
5
|
DEFAULT_REGEX_MAX_PATTERN_BYTES,
|
|
6
6
|
DEFAULT_REGEX_TIMEOUT_MS,
|
|
7
|
+
MEMORY_CACHE_VERSION,
|
|
8
|
+
classifySessionTiers,
|
|
9
|
+
digestPolicy,
|
|
7
10
|
fingerprintSource,
|
|
11
|
+
fitDigestCache,
|
|
8
12
|
loadTieredIndex,
|
|
13
|
+
reconstructRecordsLineage,
|
|
9
14
|
reconstructSessionLineage,
|
|
10
|
-
searchMemoryIndex
|
|
11
|
-
|
|
15
|
+
searchMemoryIndex,
|
|
16
|
+
shardPolicy
|
|
17
|
+
} from "./chunk-YIDC2IVN.js";
|
|
12
18
|
import {
|
|
13
19
|
compareLexical,
|
|
20
|
+
foldSessionDigest,
|
|
14
21
|
normalizeMemoryPhrase,
|
|
15
22
|
tokenizeLexical
|
|
16
23
|
} from "./chunk-U5FYOMG5.js";
|
|
@@ -19,11 +26,12 @@ import {
|
|
|
19
26
|
enumerateAllSessions,
|
|
20
27
|
resolveScope,
|
|
21
28
|
resolveSessionTarget
|
|
22
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-TDCMU5L4.js";
|
|
23
30
|
import {
|
|
24
31
|
expandSessionEntriesChecked,
|
|
32
|
+
normalizeRecords,
|
|
25
33
|
normalizeSession
|
|
26
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-MYCDJTSM.js";
|
|
27
35
|
|
|
28
36
|
// src/memory/context.ts
|
|
29
37
|
var RECALL_DEFAULT_PAGE_SIZE = 10;
|
|
@@ -75,17 +83,19 @@ var makeSnippet = (text, query, queryMode, maxChars) => {
|
|
|
75
83
|
truncated: true
|
|
76
84
|
};
|
|
77
85
|
};
|
|
78
|
-
var sourceFromSegment = (segment) => ({
|
|
86
|
+
var sourceFromSegment = (segment, sourceId) => ({
|
|
79
87
|
sessionId: boundedMetadata(segment.sessionId) ?? "",
|
|
80
88
|
sessionFile: segment.sessionFile,
|
|
89
|
+
...sourceId ? { source: sourceId } : {},
|
|
81
90
|
sourceHash: segment.sourceHash,
|
|
82
91
|
branches: segment.branches,
|
|
83
92
|
lineageFingerprint: segment.lineageFingerprint,
|
|
84
93
|
tier: segment.tier
|
|
85
94
|
});
|
|
86
|
-
var sourceFromDigest = (digest) => ({
|
|
95
|
+
var sourceFromDigest = (digest, sourceId) => ({
|
|
87
96
|
sessionId: boundedMetadata(digest.sessionId) ?? "",
|
|
88
97
|
sessionFile: digest.sessionFile,
|
|
98
|
+
...sourceId ? { source: sourceId } : {},
|
|
89
99
|
sourceHash: digest.sourceHash,
|
|
90
100
|
branches: digest.branches,
|
|
91
101
|
lineageFingerprint: digest.lineageFingerprint,
|
|
@@ -93,14 +103,15 @@ var sourceFromDigest = (digest) => ({
|
|
|
93
103
|
});
|
|
94
104
|
var expandArgs = (source, entry) => ({
|
|
95
105
|
session: source.sessionFile,
|
|
106
|
+
...source.source ? { source: source.source } : {},
|
|
96
107
|
expectedSourceHash: source.sourceHash,
|
|
97
108
|
expectedLineageFingerprint: source.lineageFingerprint,
|
|
98
109
|
branches: source.branches,
|
|
99
110
|
indices: [entry.index]
|
|
100
111
|
});
|
|
101
|
-
var entryHit = (segment, item, query, queryMode, snippetChars) => {
|
|
112
|
+
var entryHit = (segment, item, query, queryMode, snippetChars, sourceId) => {
|
|
102
113
|
const entry = item.entry;
|
|
103
|
-
const source = sourceFromSegment(segment);
|
|
114
|
+
const source = sourceFromSegment(segment, sourceId);
|
|
104
115
|
const snippet = makeSnippet(entry.text, query, queryMode, snippetChars);
|
|
105
116
|
return {
|
|
106
117
|
kind: "entry",
|
|
@@ -135,8 +146,8 @@ var hydrationArgs = (digest, request) => {
|
|
|
135
146
|
expectedLineageFingerprint: digest.lineageFingerprint
|
|
136
147
|
};
|
|
137
148
|
};
|
|
138
|
-
var sessionHit = (digest, request) => {
|
|
139
|
-
const source = sourceFromDigest(digest);
|
|
149
|
+
var sessionHit = (digest, request, sourceId) => {
|
|
150
|
+
const source = sourceFromDigest(digest, sourceId);
|
|
140
151
|
return {
|
|
141
152
|
kind: "session",
|
|
142
153
|
sessionId: source.sessionId,
|
|
@@ -185,7 +196,7 @@ var flattenCandidates = (result) => {
|
|
|
185
196
|
recallCandidateCache.set(result, candidates);
|
|
186
197
|
return candidates;
|
|
187
198
|
};
|
|
188
|
-
var materializeCandidate = (candidate, query, queryMode, snippetChars, request) => candidate.kind === "session" ? sessionHit(candidate.digest, request) : entryHit(candidate.segment, candidate.item, query, queryMode, snippetChars);
|
|
199
|
+
var materializeCandidate = (candidate, query, queryMode, snippetChars, request, sourceId) => candidate.kind === "session" ? sessionHit(candidate.digest, request, sourceId) : entryHit(candidate.segment, candidate.item, query, queryMode, snippetChars, sourceId);
|
|
189
200
|
var canonicalNextArgs = (request, offset) => {
|
|
190
201
|
const { offset: _offset, ...base } = request;
|
|
191
202
|
return { ...base, offset };
|
|
@@ -201,7 +212,8 @@ var presentRecall = (input) => {
|
|
|
201
212
|
input.query,
|
|
202
213
|
input.queryMode,
|
|
203
214
|
input.snippetChars,
|
|
204
|
-
input.requestArgs
|
|
215
|
+
input.requestArgs,
|
|
216
|
+
input.requestArgs.source
|
|
205
217
|
)
|
|
206
218
|
);
|
|
207
219
|
return {
|
|
@@ -308,6 +320,7 @@ var recallFailure = (error) => ({
|
|
|
308
320
|
import path3 from "node:path";
|
|
309
321
|
|
|
310
322
|
// src/memory/source-observation.ts
|
|
323
|
+
import crypto from "node:crypto";
|
|
311
324
|
import fs from "node:fs";
|
|
312
325
|
import path2 from "node:path";
|
|
313
326
|
var sourceIdentity = (file) => {
|
|
@@ -336,6 +349,21 @@ var observeSource = (file, branches, liveBranch) => {
|
|
|
336
349
|
liveBranchSignature: branches === "active" ? liveBranchSignature(liveBranch) : null
|
|
337
350
|
};
|
|
338
351
|
};
|
|
352
|
+
var hostIdentity = (revision, sourceHash) => {
|
|
353
|
+
const digest = crypto.createHash("sha256").update(`${revision}\0${sourceHash}`).digest("hex");
|
|
354
|
+
return {
|
|
355
|
+
device: BigInt(parseInt(digest.slice(0, 8), 16)),
|
|
356
|
+
inode: BigInt(parseInt(digest.slice(8, 16), 16)),
|
|
357
|
+
size: BigInt(parseInt(digest.slice(16, 24), 16)),
|
|
358
|
+
modifiedAt: BigInt(parseInt(digest.slice(24, 32), 16)),
|
|
359
|
+
changedAt: BigInt(parseInt(digest.slice(32, 40), 16))
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
var observeHostSource = (displayKey, revision, sourceHash) => ({
|
|
363
|
+
file: displayKey,
|
|
364
|
+
identity: hostIdentity(revision, sourceHash),
|
|
365
|
+
liveBranchSignature: null
|
|
366
|
+
});
|
|
339
367
|
var observeSources = (refs, branches, liveResolver) => {
|
|
340
368
|
const observations = [];
|
|
341
369
|
for (const ref of refs) {
|
|
@@ -443,6 +471,419 @@ var MemoryRequestCache = class {
|
|
|
443
471
|
}
|
|
444
472
|
};
|
|
445
473
|
|
|
474
|
+
// src/memory/host-source.ts
|
|
475
|
+
import crypto2 from "node:crypto";
|
|
476
|
+
|
|
477
|
+
// src/memory/portable.ts
|
|
478
|
+
var MEMORY_SOURCE_INTERFACE_VERSION = 1;
|
|
479
|
+
var MemorySourceError = class extends Error {
|
|
480
|
+
constructor(code, message) {
|
|
481
|
+
super(message);
|
|
482
|
+
this.code = code;
|
|
483
|
+
this.name = "MemorySourceError";
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
var SOURCE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
487
|
+
var isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
488
|
+
var assertValidSource = (source) => {
|
|
489
|
+
if (!isRecord(source) || typeof source !== "object") {
|
|
490
|
+
throw new TypeError("A portable memory source must be an object");
|
|
491
|
+
}
|
|
492
|
+
if (source.interfaceVersion !== MEMORY_SOURCE_INTERFACE_VERSION) {
|
|
493
|
+
throw new TypeError(
|
|
494
|
+
`Portable memory source interface version must be ${MEMORY_SOURCE_INTERFACE_VERSION}`
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
if (typeof source.id !== "string" || !SOURCE_ID_PATTERN.test(source.id)) {
|
|
498
|
+
throw new TypeError(
|
|
499
|
+
"Portable memory source id must be 1-128 chars of letters, digits, dot, underscore, or dash"
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
if (typeof source.listSessions !== "function" || typeof source.loadSession !== "function") {
|
|
503
|
+
throw new TypeError("A portable memory source requires listSessions and loadSession");
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
var defineMemorySource = (source) => {
|
|
507
|
+
assertValidSource(source);
|
|
508
|
+
return source;
|
|
509
|
+
};
|
|
510
|
+
var createMemorySourceRegistry = () => {
|
|
511
|
+
const sources = /* @__PURE__ */ new Map();
|
|
512
|
+
return {
|
|
513
|
+
register(source) {
|
|
514
|
+
assertValidSource(source);
|
|
515
|
+
sources.set(source.id, source);
|
|
516
|
+
},
|
|
517
|
+
get(id) {
|
|
518
|
+
return sources.get(id);
|
|
519
|
+
},
|
|
520
|
+
ids() {
|
|
521
|
+
return [...sources.keys()].sort();
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
// src/memory/host-source.ts
|
|
527
|
+
var HOST_KEY_PREFIX = "memory-source:";
|
|
528
|
+
var REASON_PATTERN = /^[a-z0-9_.:-]{1,64}$/;
|
|
529
|
+
var hostDisplayKey = (sourceId, sessionKey) => `${HOST_KEY_PREFIX}${sourceId}/${sessionKey}`;
|
|
530
|
+
var hostSessionKey = (sourceId, session) => {
|
|
531
|
+
const prefix = `${HOST_KEY_PREFIX}${sourceId}/`;
|
|
532
|
+
return session.startsWith(prefix) ? session.slice(prefix.length) : session;
|
|
533
|
+
};
|
|
534
|
+
var resolveRegisteredSource = (registry, sourceId) => {
|
|
535
|
+
const source = registry?.get(sourceId);
|
|
536
|
+
if (!source) throw new MemorySourceError("source_not_found", `Memory source not registered: ${sourceId}`);
|
|
537
|
+
return source;
|
|
538
|
+
};
|
|
539
|
+
var memorySourceFailure = (error) => error instanceof MemorySourceError ? { code: error.code, message: error.message } : null;
|
|
540
|
+
var checkAbort = (signal) => {
|
|
541
|
+
if (signal?.aborted) throw new MemorySourceError("aborted", "Memory source call was aborted.");
|
|
542
|
+
};
|
|
543
|
+
var assertAuthorized = async (source, action, sessionKey) => {
|
|
544
|
+
if (!source.authorize) return;
|
|
545
|
+
let allowed;
|
|
546
|
+
try {
|
|
547
|
+
allowed = await source.authorize(action, sessionKey);
|
|
548
|
+
} catch {
|
|
549
|
+
throw new MemorySourceError("source_unauthorized", "Memory source authorization failed.");
|
|
550
|
+
}
|
|
551
|
+
if (allowed !== true) {
|
|
552
|
+
throw new MemorySourceError("source_unauthorized", "Memory source denied access.");
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
var coverageReasons = (coverage) => {
|
|
556
|
+
if (!coverage || coverage.complete !== false) return [];
|
|
557
|
+
const reason = typeof coverage.reason === "string" && REASON_PATTERN.test(coverage.reason) ? `source_coverage:${coverage.reason}` : "source_coverage_incomplete";
|
|
558
|
+
return [reason];
|
|
559
|
+
};
|
|
560
|
+
var asSessionKey = (value) => typeof value === "string" && value.length > 0 ? value : "";
|
|
561
|
+
var normalizeListResponse = (response) => Array.isArray(response) ? { sessions: response, coverageReasons: [] } : { sessions: response.sessions, coverageReasons: coverageReasons(response.coverage) };
|
|
562
|
+
var loadHostSnapshot = async (source, sessionKey, action, signal) => {
|
|
563
|
+
checkAbort(signal);
|
|
564
|
+
await assertAuthorized(source, action, sessionKey);
|
|
565
|
+
const response = await source.loadSession(sessionKey, signal === void 0 ? {} : { signal });
|
|
566
|
+
checkAbort(signal);
|
|
567
|
+
await assertAuthorized(source, action, sessionKey);
|
|
568
|
+
if (response === null || response === void 0) return null;
|
|
569
|
+
const key = asSessionKey(response.sessionKey);
|
|
570
|
+
const revision = asSessionKey(response.revision);
|
|
571
|
+
if (!revision || !Array.isArray(response.records) || key !== sessionKey) {
|
|
572
|
+
throw new MemorySourceError("invalid_source_response", "Memory source returned an invalid snapshot.");
|
|
573
|
+
}
|
|
574
|
+
if (!response.records.every((record) => record !== null && typeof record === "object" && !Array.isArray(record))) {
|
|
575
|
+
throw new MemorySourceError("invalid_source_response", "Memory source snapshot has non-object records.");
|
|
576
|
+
}
|
|
577
|
+
let records;
|
|
578
|
+
try {
|
|
579
|
+
records = JSON.parse(JSON.stringify(response.records));
|
|
580
|
+
} catch {
|
|
581
|
+
throw new MemorySourceError(
|
|
582
|
+
"invalid_source_response",
|
|
583
|
+
"Memory source snapshot records are not JSON-serializable."
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
sourceId: source.id,
|
|
588
|
+
sessionKey,
|
|
589
|
+
displayKey: hostDisplayKey(source.id, sessionKey),
|
|
590
|
+
sessionId: response.sessionId ?? sessionKey,
|
|
591
|
+
revision,
|
|
592
|
+
metadata: { ...response.metadata ?? {} },
|
|
593
|
+
records,
|
|
594
|
+
coverageReasons: coverageReasons(response.coverage)
|
|
595
|
+
};
|
|
596
|
+
};
|
|
597
|
+
var listHostSnapshots = async (source, limit, action, signal) => {
|
|
598
|
+
checkAbort(signal);
|
|
599
|
+
await assertAuthorized(source, action, null);
|
|
600
|
+
const boundedLimit = Math.max(0, Math.floor(limit));
|
|
601
|
+
const listed = normalizeListResponse(
|
|
602
|
+
await source.listSessions(signal === void 0 ? { limit: boundedLimit } : { limit: boundedLimit, signal })
|
|
603
|
+
);
|
|
604
|
+
checkAbort(signal);
|
|
605
|
+
const snapshots = [];
|
|
606
|
+
const coverageReasons2 = new Set(listed.coverageReasons);
|
|
607
|
+
if (listed.sessions.length > boundedLimit) {
|
|
608
|
+
coverageReasons2.add("source_limit_exceeded");
|
|
609
|
+
}
|
|
610
|
+
for (const descriptor of listed.sessions.slice(0, boundedLimit)) {
|
|
611
|
+
checkAbort(signal);
|
|
612
|
+
const key = asSessionKey(descriptor.sessionKey);
|
|
613
|
+
if (!key) {
|
|
614
|
+
coverageReasons2.add("invalid_source_response");
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
const snapshot = await loadHostSnapshot(source, key, action, signal);
|
|
618
|
+
if (!snapshot) {
|
|
619
|
+
coverageReasons2.add("source_unavailable");
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
for (const reason of snapshot.coverageReasons) coverageReasons2.add(reason);
|
|
623
|
+
snapshots.push(snapshot);
|
|
624
|
+
}
|
|
625
|
+
if (snapshots.length === 0) {
|
|
626
|
+
await assertAuthorized(source, action, null);
|
|
627
|
+
}
|
|
628
|
+
return { snapshots, coverageReasons: [...coverageReasons2] };
|
|
629
|
+
};
|
|
630
|
+
var hostSourceState = (snapshot) => {
|
|
631
|
+
const canonical = JSON.stringify(snapshot.records);
|
|
632
|
+
const sourceHash = crypto2.createHash("sha256").update(`${snapshot.revision}\0${canonical}`).digest("hex");
|
|
633
|
+
return {
|
|
634
|
+
mtime: snapshot.metadata.updatedAt ?? 0,
|
|
635
|
+
size: Buffer.byteLength(canonical, "utf8"),
|
|
636
|
+
sourceHash
|
|
637
|
+
};
|
|
638
|
+
};
|
|
639
|
+
var hostRef = (snapshot) => ({
|
|
640
|
+
id: snapshot.sessionId,
|
|
641
|
+
file: snapshot.displayKey,
|
|
642
|
+
cwd: snapshot.metadata.cwd ?? "",
|
|
643
|
+
mtime: snapshot.metadata.updatedAt ?? 0
|
|
644
|
+
});
|
|
645
|
+
var hostLineage = (snapshot, branches) => reconstructRecordsLineage(snapshot.records, branches);
|
|
646
|
+
var hostIdentity2 = (sessionFile, sessionId, cwd) => ({
|
|
647
|
+
sessionFile,
|
|
648
|
+
...sessionId !== void 0 ? { sessionId } : {},
|
|
649
|
+
...cwd !== void 0 ? { cwd } : {}
|
|
650
|
+
});
|
|
651
|
+
var mergedCoverage = (base, extra) => {
|
|
652
|
+
if (extra.length === 0) return base;
|
|
653
|
+
const reasons = [.../* @__PURE__ */ new Set([...base.reasons, ...extra])].sort();
|
|
654
|
+
return { complete: false, reasons };
|
|
655
|
+
};
|
|
656
|
+
var buildHostShard = (snapshot, options, tier, entryRange) => {
|
|
657
|
+
const state = hostSourceState(snapshot);
|
|
658
|
+
const lineage = hostLineage(snapshot, options.branches ?? "active");
|
|
659
|
+
const { entries, header, indexCoverage } = normalizeRecords(
|
|
660
|
+
snapshot.records,
|
|
661
|
+
hostIdentity2(snapshot.displayKey, snapshot.sessionId, snapshot.metadata.cwd),
|
|
662
|
+
options.maxEntryChars,
|
|
663
|
+
{
|
|
664
|
+
lineage,
|
|
665
|
+
indexThinking: options.indexThinking ?? false,
|
|
666
|
+
indexToolOutput: options.indexToolOutput ?? true
|
|
667
|
+
}
|
|
668
|
+
);
|
|
669
|
+
const selected = entryRange ? entries.filter((entry) => entry.index >= entryRange.first && entry.index <= entryRange.last) : entries;
|
|
670
|
+
return {
|
|
671
|
+
cacheVersion: MEMORY_CACHE_VERSION,
|
|
672
|
+
kind: "shard",
|
|
673
|
+
sessionFile: snapshot.displayKey,
|
|
674
|
+
sessionId: header?.sessionId ?? snapshot.sessionId,
|
|
675
|
+
mtime: state.mtime,
|
|
676
|
+
size: state.size,
|
|
677
|
+
sourceHash: state.sourceHash,
|
|
678
|
+
branches: lineage.branches,
|
|
679
|
+
lineageFingerprint: lineage.fingerprint,
|
|
680
|
+
policy: shardPolicy(options, lineage),
|
|
681
|
+
cacheBytes: 0,
|
|
682
|
+
cacheSourceRatio: 0,
|
|
683
|
+
entries: selected,
|
|
684
|
+
totalEntryCount: entries.length,
|
|
685
|
+
indexCoverage: mergedCoverage(indexCoverage, snapshot.coverageReasons),
|
|
686
|
+
tier
|
|
687
|
+
};
|
|
688
|
+
};
|
|
689
|
+
var buildHostDigest = (snapshot, options) => {
|
|
690
|
+
const state = hostSourceState(snapshot);
|
|
691
|
+
const lineage = hostLineage(snapshot, options.branches ?? "active");
|
|
692
|
+
const { entries, header, indexCoverage } = normalizeRecords(
|
|
693
|
+
snapshot.records,
|
|
694
|
+
hostIdentity2(snapshot.displayKey, snapshot.sessionId, snapshot.metadata.cwd),
|
|
695
|
+
Number.MAX_SAFE_INTEGER,
|
|
696
|
+
{
|
|
697
|
+
lineage,
|
|
698
|
+
indexThinking: options.indexThinking ?? false,
|
|
699
|
+
indexToolOutput: options.indexToolOutput ?? true
|
|
700
|
+
}
|
|
701
|
+
);
|
|
702
|
+
const digest = foldSessionDigest({
|
|
703
|
+
sessionId: header?.sessionId ?? snapshot.sessionId,
|
|
704
|
+
file: snapshot.displayKey,
|
|
705
|
+
cwd: header?.cwd ?? snapshot.metadata.cwd ?? "",
|
|
706
|
+
entries,
|
|
707
|
+
maxVocabularyBytes: options.maxColdVocabularyBytes ?? 512 * 1024,
|
|
708
|
+
normalizationCoverage: mergedCoverage(indexCoverage, snapshot.coverageReasons)
|
|
709
|
+
});
|
|
710
|
+
return fitDigestCache({
|
|
711
|
+
cacheVersion: MEMORY_CACHE_VERSION,
|
|
712
|
+
kind: "digest",
|
|
713
|
+
...digest,
|
|
714
|
+
mtime: state.mtime,
|
|
715
|
+
size: state.size,
|
|
716
|
+
sourceHash: state.sourceHash,
|
|
717
|
+
branches: lineage.branches,
|
|
718
|
+
lineageFingerprint: lineage.fingerprint,
|
|
719
|
+
policy: digestPolicy(options, lineage),
|
|
720
|
+
cacheBytes: 0,
|
|
721
|
+
cacheSourceRatio: 0
|
|
722
|
+
}, options.maxColdCacheBytes ?? 1024 * 1024);
|
|
723
|
+
};
|
|
724
|
+
var loadHostTieredIndex = (snapshots, options, hydrate = false, entryRange, extraReasons = []) => {
|
|
725
|
+
const refs = snapshots.map(hostRef);
|
|
726
|
+
const tiers = classifySessionTiers(refs, options.hotSessions ?? 50);
|
|
727
|
+
const maxSessions = options.maxSyncSessions ?? 1e4;
|
|
728
|
+
const maxSourceBytes = options.maxSyncSourceBytes ?? 512 * 1024 * 1024;
|
|
729
|
+
const shards = [];
|
|
730
|
+
const digests = [];
|
|
731
|
+
const reasons = new Set(extraReasons);
|
|
732
|
+
let indexedSessions = 0;
|
|
733
|
+
let incompleteSessions = 0;
|
|
734
|
+
let processedSessions = 0;
|
|
735
|
+
let processedSourceBytes = 0;
|
|
736
|
+
const byKey = new Map(snapshots.map((snapshot) => [snapshot.displayKey, snapshot]));
|
|
737
|
+
for (const ref of refs) {
|
|
738
|
+
const snapshot = byKey.get(ref.file);
|
|
739
|
+
if (!snapshot) {
|
|
740
|
+
reasons.add("source_unavailable");
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const size = hostSourceState(snapshot).size;
|
|
744
|
+
if (processedSessions >= maxSessions) {
|
|
745
|
+
reasons.add("max_sync_sessions");
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
const tier = tiers.get(ref.file) ?? "cold";
|
|
749
|
+
const sourceWorkBytes = size * (hydrate && tier === "cold" ? 6 : 3);
|
|
750
|
+
if (processedSourceBytes + sourceWorkBytes > maxSourceBytes) {
|
|
751
|
+
reasons.add("max_sync_source_bytes");
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
processedSessions += 1;
|
|
755
|
+
processedSourceBytes += sourceWorkBytes;
|
|
756
|
+
if (hydrate) {
|
|
757
|
+
if (tier === "cold") digests.push(buildHostDigest(snapshot, options));
|
|
758
|
+
const shard = buildHostShard(snapshot, options, "cold", entryRange);
|
|
759
|
+
shards.push(shard);
|
|
760
|
+
if (shard.sourceHash) indexedSessions += 1;
|
|
761
|
+
if (shard.sourceHash && !shard.indexCoverage.complete) {
|
|
762
|
+
incompleteSessions += 1;
|
|
763
|
+
for (const reason of shard.indexCoverage.reasons) reasons.add(reason);
|
|
764
|
+
}
|
|
765
|
+
} else if (tier === "hot") {
|
|
766
|
+
const shard = buildHostShard(snapshot, options, "hot");
|
|
767
|
+
shards.push(shard);
|
|
768
|
+
if (shard.sourceHash) indexedSessions += 1;
|
|
769
|
+
if (shard.sourceHash && !shard.indexCoverage.complete) {
|
|
770
|
+
incompleteSessions += 1;
|
|
771
|
+
for (const reason of shard.indexCoverage.reasons) reasons.add(reason);
|
|
772
|
+
}
|
|
773
|
+
} else {
|
|
774
|
+
const digest = buildHostDigest(snapshot, options);
|
|
775
|
+
digests.push(digest);
|
|
776
|
+
if (digest.sourceHash) indexedSessions += 1;
|
|
777
|
+
if (!digest.indexCoverage.complete) {
|
|
778
|
+
incompleteSessions += 1;
|
|
779
|
+
for (const reason of digest.indexCoverage.reasons) reasons.add(reason);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
const eligibleSessions = refs.length;
|
|
784
|
+
const staleSessions = eligibleSessions - indexedSessions;
|
|
785
|
+
const coverage = {
|
|
786
|
+
complete: reasons.size === 0 && staleSessions === 0 && incompleteSessions === 0,
|
|
787
|
+
indexedSessions,
|
|
788
|
+
eligibleSessions,
|
|
789
|
+
staleSessions,
|
|
790
|
+
incompleteSessions,
|
|
791
|
+
reasons: [...reasons].sort()
|
|
792
|
+
};
|
|
793
|
+
return { shards, digests, refs, tiers, coverage };
|
|
794
|
+
};
|
|
795
|
+
var fileRecallPlan = (refs, context) => {
|
|
796
|
+
const liveResolver = liveBranchResolver(context);
|
|
797
|
+
return {
|
|
798
|
+
refs,
|
|
799
|
+
sessionKey: null,
|
|
800
|
+
observeAll: (branches) => observeSources(refs, branches, liveResolver),
|
|
801
|
+
stateFor: (ref) => fingerprintSource(ref.file),
|
|
802
|
+
lineageFor: (ref, branches) => reconstructSessionLineage(ref.file, branches, liveResolver?.(ref.file)),
|
|
803
|
+
loadIndex: (options, hydrate, entryRange) => loadTieredIndex(refs, resolveTierRefs(refs, context), options, hydrate, entryRange)
|
|
804
|
+
};
|
|
805
|
+
};
|
|
806
|
+
var hostRecallPlan = async (source, sourceId, sessionKey, context, signal) => {
|
|
807
|
+
const loaded = sessionKey !== null ? await (async () => {
|
|
808
|
+
const snapshot = await loadHostSnapshot(source, sessionKey, "recall", signal);
|
|
809
|
+
return snapshot ? { snapshots: [snapshot], coverageReasons: [] } : null;
|
|
810
|
+
})() : await listHostSnapshots(source, context.config.maxSessions, "recall", signal);
|
|
811
|
+
if (!loaded) throw new MemorySourceError("session_not_found", `Session not found in source ${sourceId}: ${sessionKey}`);
|
|
812
|
+
const snapshots = loaded.snapshots;
|
|
813
|
+
const refs = snapshots.map(hostRef);
|
|
814
|
+
const byKey = new Map(snapshots.map((snapshot) => [snapshot.displayKey, snapshot]));
|
|
815
|
+
const stateByKey = /* @__PURE__ */ new Map();
|
|
816
|
+
const stateOf = (snapshot) => {
|
|
817
|
+
let state = stateByKey.get(snapshot.displayKey);
|
|
818
|
+
if (!state) {
|
|
819
|
+
state = hostSourceState(snapshot);
|
|
820
|
+
stateByKey.set(snapshot.displayKey, state);
|
|
821
|
+
}
|
|
822
|
+
return state;
|
|
823
|
+
};
|
|
824
|
+
return {
|
|
825
|
+
refs,
|
|
826
|
+
sessionKey,
|
|
827
|
+
observeAll: (branches) => snapshots.map((snapshot) => observeHostSource(snapshot.displayKey, snapshot.revision, stateOf(snapshot).sourceHash)),
|
|
828
|
+
stateFor: (ref) => {
|
|
829
|
+
const snapshot = byKey.get(ref.file);
|
|
830
|
+
return snapshot ? stateOf(snapshot) : null;
|
|
831
|
+
},
|
|
832
|
+
lineageFor: (ref, branches) => {
|
|
833
|
+
const snapshot = byKey.get(ref.file);
|
|
834
|
+
return snapshot ? hostLineage(snapshot, branches) : reconstructSessionLineage(ref.file, branches);
|
|
835
|
+
},
|
|
836
|
+
loadIndex: (options, hydrate, entryRange) => loadHostTieredIndex(snapshots, options, hydrate, entryRange, loaded.coverageReasons)
|
|
837
|
+
};
|
|
838
|
+
};
|
|
839
|
+
var fileExpansionAccess = (session, context) => {
|
|
840
|
+
const ref = resolveSessionTarget(context.agentDir, session);
|
|
841
|
+
if (!ref) return null;
|
|
842
|
+
const liveResolver = liveBranchResolver(context);
|
|
843
|
+
return {
|
|
844
|
+
ref,
|
|
845
|
+
state: () => fingerprintSource(ref.file),
|
|
846
|
+
lineage: (branches) => reconstructSessionLineage(ref.file, branches, liveResolver?.(ref.file)),
|
|
847
|
+
observe: (branches) => observeSource(ref.file, branches, branches === "active" ? liveResolver?.(ref.file) : void 0),
|
|
848
|
+
normalizeFull: (branches, policy, lineage) => {
|
|
849
|
+
const resolvedLineage = lineage ?? reconstructSessionLineage(ref.file, branches, liveResolver?.(ref.file));
|
|
850
|
+
const normalized = normalizeSession(ref.file, Number.MAX_SAFE_INTEGER, {
|
|
851
|
+
lineage: resolvedLineage,
|
|
852
|
+
...policy
|
|
853
|
+
});
|
|
854
|
+
return normalized.header === null && normalized.entries.length === 0 && normalized.indexCoverage.reasons.includes("source_unavailable") ? null : { entries: normalized.entries, indexCoverage: normalized.indexCoverage };
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
};
|
|
858
|
+
var hostExpansionAccess = async (sourceId, session, context, signal) => {
|
|
859
|
+
const source = resolveRegisteredSource(context.sources, sourceId);
|
|
860
|
+
const sessionKey = hostSessionKey(sourceId, session);
|
|
861
|
+
const snapshot = await loadHostSnapshot(source, sessionKey, "expand", signal);
|
|
862
|
+
if (!snapshot) {
|
|
863
|
+
throw new MemorySourceError("session_not_found", `Session not found in source ${sourceId}: ${sessionKey}`);
|
|
864
|
+
}
|
|
865
|
+
const state = hostSourceState(snapshot);
|
|
866
|
+
const ref = hostRef(snapshot);
|
|
867
|
+
return {
|
|
868
|
+
ref,
|
|
869
|
+
state: () => state,
|
|
870
|
+
lineage: (branches) => hostLineage(snapshot, branches),
|
|
871
|
+
observe: () => observeHostSource(snapshot.displayKey, snapshot.revision, state.sourceHash),
|
|
872
|
+
normalizeFull: (branches, policy) => {
|
|
873
|
+
const normalized = normalizeRecords(
|
|
874
|
+
snapshot.records,
|
|
875
|
+
hostIdentity2(snapshot.displayKey, snapshot.sessionId, snapshot.metadata.cwd),
|
|
876
|
+
Number.MAX_SAFE_INTEGER,
|
|
877
|
+
{ lineage: hostLineage(snapshot, branches), ...policy }
|
|
878
|
+
);
|
|
879
|
+
return {
|
|
880
|
+
entries: normalized.entries,
|
|
881
|
+
indexCoverage: mergedCoverage(normalized.indexCoverage, snapshot.coverageReasons)
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
};
|
|
886
|
+
|
|
446
887
|
// src/memory/recall-service.ts
|
|
447
888
|
async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
448
889
|
const query = typeof args.query === "string" ? args.query : void 0;
|
|
@@ -478,15 +919,38 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
478
919
|
const offset = typeof args.offset === "number" && args.offset >= 0 ? Math.floor(args.offset) : void 0;
|
|
479
920
|
const pageSize = typeof args.pageSize === "number" && args.pageSize >= 1 ? Math.min(Math.floor(args.pageSize), RECALL_MAX_PAGE_SIZE) : RECALL_DEFAULT_PAGE_SIZE;
|
|
480
921
|
const snippetChars = typeof args.snippetChars === "number" && args.snippetChars >= 80 ? Math.min(Math.floor(args.snippetChars), RECALL_MAX_SNIPPET_CHARS) : RECALL_DEFAULT_SNIPPET_CHARS;
|
|
481
|
-
const
|
|
482
|
-
|
|
922
|
+
const sourceId = typeof args.source === "string" && args.source.length > 0 ? args.source : void 0;
|
|
923
|
+
let plan;
|
|
924
|
+
if (sourceId !== void 0) {
|
|
925
|
+
if (scope !== void 0 && scope !== `source:${sourceId}` && !scope.startsWith("session:")) {
|
|
926
|
+
throw new Error(
|
|
927
|
+
"memory.recall scope must name the selected source, one of its sessions, or be omitted"
|
|
928
|
+
);
|
|
929
|
+
}
|
|
930
|
+
try {
|
|
931
|
+
plan = await hostRecallPlan(
|
|
932
|
+
resolveRegisteredSource(context.sources, sourceId),
|
|
933
|
+
sourceId,
|
|
934
|
+
scope?.startsWith("session:") ? scope.slice("session:".length).trim() : null,
|
|
935
|
+
context,
|
|
936
|
+
invocationContext.signal
|
|
937
|
+
);
|
|
938
|
+
} catch (error) {
|
|
939
|
+
const failure = memorySourceFailure(error);
|
|
940
|
+
if (!failure) throw error;
|
|
941
|
+
return recallFailure(failure);
|
|
942
|
+
}
|
|
943
|
+
} else {
|
|
944
|
+
plan = fileRecallPlan(resolveRefs(scope, context, false), context);
|
|
945
|
+
}
|
|
946
|
+
const refs = plan.refs;
|
|
483
947
|
const options = resolveIndexOptions(
|
|
484
948
|
context.config,
|
|
485
949
|
context.agentDir,
|
|
486
950
|
branches,
|
|
487
|
-
|
|
951
|
+
sourceId === void 0 ? liveBranchResolver(context) : void 0
|
|
488
952
|
);
|
|
489
|
-
const hydrate = scope?.trim().startsWith("session:") ?? false;
|
|
953
|
+
const hydrate = sourceId !== void 0 ? plan.sessionKey !== null : scope?.trim().startsWith("session:") ?? false;
|
|
490
954
|
if ((expectedSourceHash !== void 0 || expectedLineageFingerprint !== void 0) && !hydrate) {
|
|
491
955
|
throw new Error("memory.recall integrity expectations require scope session:<id-or-path>");
|
|
492
956
|
}
|
|
@@ -514,13 +978,14 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
514
978
|
if (since !== void 0) filters.since = since;
|
|
515
979
|
if (until !== void 0) filters.until = until;
|
|
516
980
|
const baseRequestArgs = {
|
|
981
|
+
...sourceId ? { source: sourceId } : {},
|
|
517
982
|
...query === void 0 ? {} : { query },
|
|
518
983
|
queryMode,
|
|
519
984
|
...queryMode === "literal" ? { queryMatch } : {},
|
|
520
985
|
...expectedSourceHash ? { expectedSourceHash } : {},
|
|
521
986
|
...expectedLineageFingerprint ? { expectedLineageFingerprint } : {},
|
|
522
987
|
branches,
|
|
523
|
-
scope: scope ?? "session",
|
|
988
|
+
scope: sourceId ? plan.sessionKey !== null ? `session:${plan.refs[0]?.file ?? plan.sessionKey}` : `source:${sourceId}` : scope ?? "session",
|
|
524
989
|
...offset === void 0 ? {} : { offset },
|
|
525
990
|
pageSize,
|
|
526
991
|
snippetChars,
|
|
@@ -539,7 +1004,7 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
539
1004
|
searchResult.matchMode === "structural" ? `memory.recall: ${searchResult.matchedCount} structural matches` : searchResult.matchMode === "combined" ? `memory.recall: ${searchResult.matchedCount} filtered matches` : query ? `memory.recall: ${searchResult.matchedCount} matches` : `memory.recall: ${searchResult.matchedCount} recent entries`
|
|
540
1005
|
);
|
|
541
1006
|
};
|
|
542
|
-
const observationsBefore =
|
|
1007
|
+
const observationsBefore = await plan.observeAll(branches);
|
|
543
1008
|
const cached = offset === void 0 ? void 0 : cache.cachedRecallContinuation(
|
|
544
1009
|
recallContinuationKey(baseRequestArgs),
|
|
545
1010
|
observationsBefore
|
|
@@ -555,7 +1020,7 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
555
1020
|
snippetChars,
|
|
556
1021
|
requestArgs: cached.requestArgs
|
|
557
1022
|
});
|
|
558
|
-
const observationsAfterCachedPage =
|
|
1023
|
+
const observationsAfterCachedPage = await plan.observeAll(branches);
|
|
559
1024
|
if (observationsBefore && observationsAfterCachedPage && sameSourceObservations(observationsBefore, observationsAfterCachedPage)) {
|
|
560
1025
|
if (response2.next === null) cache.forgetRecallContinuation(cached);
|
|
561
1026
|
updateProgress(cached.result);
|
|
@@ -564,12 +1029,8 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
564
1029
|
cache.forgetRecallContinuation(cached);
|
|
565
1030
|
}
|
|
566
1031
|
if (hydrate && refs[0]) {
|
|
567
|
-
const state =
|
|
568
|
-
const lineage =
|
|
569
|
-
refs[0].file,
|
|
570
|
-
branches,
|
|
571
|
-
liveResolver?.(refs[0].file)
|
|
572
|
-
);
|
|
1032
|
+
const state = plan.stateFor(refs[0]);
|
|
1033
|
+
const lineage = plan.lineageFor(refs[0], branches);
|
|
573
1034
|
const sourceChanged = expectedSourceHash !== void 0 && state?.sourceHash !== expectedSourceHash;
|
|
574
1035
|
const lineageChanged = expectedLineageFingerprint !== void 0 && lineage.fingerprint !== expectedLineageFingerprint;
|
|
575
1036
|
if (state && (sourceChanged || lineageChanged)) {
|
|
@@ -582,13 +1043,7 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
582
1043
|
));
|
|
583
1044
|
}
|
|
584
1045
|
}
|
|
585
|
-
const index =
|
|
586
|
-
refs,
|
|
587
|
-
resolveTierRefs(refs, context),
|
|
588
|
-
options,
|
|
589
|
-
hydrate,
|
|
590
|
-
selectedRange
|
|
591
|
-
);
|
|
1046
|
+
const index = plan.loadIndex(options, hydrate, selectedRange);
|
|
592
1047
|
const hydratedShard = index.shards[0];
|
|
593
1048
|
const hydratedSourceChanged = expectedSourceHash !== void 0 && hydratedShard?.sourceHash !== expectedSourceHash;
|
|
594
1049
|
const hydratedLineageChanged = expectedLineageFingerprint !== void 0 && hydratedShard?.lineageFingerprint !== expectedLineageFingerprint;
|
|
@@ -652,7 +1107,7 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
652
1107
|
snippetChars,
|
|
653
1108
|
requestArgs
|
|
654
1109
|
});
|
|
655
|
-
const observationsAfter =
|
|
1110
|
+
const observationsAfter = await plan.observeAll(branches);
|
|
656
1111
|
if (response.next !== null && observationsBefore && observationsAfter && sameSourceObservations(observationsBefore, observationsAfter)) {
|
|
657
1112
|
cache.rememberRecallContinuation({
|
|
658
1113
|
key: recallContinuationKey(requestArgs),
|
|
@@ -668,8 +1123,9 @@ async function processMemoryRecall(args, invocationContext, context, cache) {
|
|
|
668
1123
|
}
|
|
669
1124
|
|
|
670
1125
|
// src/memory/expand-service.ts
|
|
671
|
-
async function processMemoryExpand(args, context, cache) {
|
|
1126
|
+
async function processMemoryExpand(args, context, cache, signal) {
|
|
672
1127
|
const session = typeof args.session === "string" ? args.session : "";
|
|
1128
|
+
const sourceId = typeof args.source === "string" && args.source.length > 0 ? args.source : void 0;
|
|
673
1129
|
const expectedSourceHash = typeof args.expectedSourceHash === "string" ? args.expectedSourceHash : void 0;
|
|
674
1130
|
const expectedLineageFingerprint = typeof args.expectedLineageFingerprint === "string" ? args.expectedLineageFingerprint : void 0;
|
|
675
1131
|
const branches = parseBranches(args.branches, "memory.expand");
|
|
@@ -708,17 +1164,27 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
708
1164
|
const textOffset = numeric(args.textOffset, 0, Number.MAX_SAFE_INTEGER);
|
|
709
1165
|
const maxChars = Math.max(256, numeric(args.maxChars, EXPAND_DEFAULT_MAX_CHARS, EXPAND_MAX_CHARS));
|
|
710
1166
|
const maxEntries = Math.max(1, numeric(args.maxEntries, EXPAND_DEFAULT_MAX_ENTRIES, EXPAND_MAX_ENTRIES));
|
|
711
|
-
|
|
712
|
-
if (
|
|
1167
|
+
let access;
|
|
1168
|
+
if (sourceId !== void 0) {
|
|
1169
|
+
try {
|
|
1170
|
+
access = await hostExpansionAccess(sourceId, session, context, signal);
|
|
1171
|
+
} catch (error) {
|
|
1172
|
+
const failure = memorySourceFailure(error);
|
|
1173
|
+
if (!failure) throw error;
|
|
1174
|
+
return { session, error: failure, entries: [] };
|
|
1175
|
+
}
|
|
1176
|
+
} else {
|
|
1177
|
+
access = fileExpansionAccess(session, context);
|
|
1178
|
+
}
|
|
1179
|
+
if (!access) {
|
|
713
1180
|
return {
|
|
714
1181
|
session,
|
|
715
1182
|
error: { code: "session_not_found", message: `Session not found: ${session}` },
|
|
716
1183
|
entries: []
|
|
717
1184
|
};
|
|
718
1185
|
}
|
|
719
|
-
const
|
|
720
|
-
const
|
|
721
|
-
const observedSource = observeSource(ref.file, branches, observedLiveBranch);
|
|
1186
|
+
const ref = access.ref;
|
|
1187
|
+
const observedSource = access.observe(branches);
|
|
722
1188
|
let snapshot = cache.cachedExpansionSnapshot(ref.file, branches, observedSource);
|
|
723
1189
|
if (snapshot) {
|
|
724
1190
|
const sourceChanged = expectedSourceHash !== void 0 && snapshot.sourceHash !== expectedSourceHash;
|
|
@@ -739,7 +1205,7 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
739
1205
|
}
|
|
740
1206
|
}
|
|
741
1207
|
if (!snapshot) {
|
|
742
|
-
const initialState =
|
|
1208
|
+
const initialState = access.state();
|
|
743
1209
|
if (!initialState) {
|
|
744
1210
|
return {
|
|
745
1211
|
session: ref.file,
|
|
@@ -747,12 +1213,7 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
747
1213
|
entries: []
|
|
748
1214
|
};
|
|
749
1215
|
}
|
|
750
|
-
const
|
|
751
|
-
const initialLineage = reconstructSessionLineage(
|
|
752
|
-
ref.file,
|
|
753
|
-
branches,
|
|
754
|
-
initialLiveBranch
|
|
755
|
-
);
|
|
1216
|
+
const initialLineage = access.lineage(branches);
|
|
756
1217
|
const sourceChanged = expectedSourceHash !== void 0 && initialState.sourceHash !== expectedSourceHash;
|
|
757
1218
|
const lineageChanged = expectedLineageFingerprint !== void 0 && initialLineage.fingerprint !== expectedLineageFingerprint;
|
|
758
1219
|
if (sourceChanged || lineageChanged) {
|
|
@@ -769,23 +1230,28 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
769
1230
|
entries: []
|
|
770
1231
|
};
|
|
771
1232
|
}
|
|
772
|
-
const
|
|
773
|
-
ref.file,
|
|
774
|
-
Number.MAX_SAFE_INTEGER,
|
|
775
|
-
{
|
|
776
|
-
lineage: initialLineage,
|
|
777
|
-
indexThinking: true,
|
|
778
|
-
indexToolOutput: true
|
|
779
|
-
}
|
|
780
|
-
).entries;
|
|
781
|
-
const finalState2 = fingerprintSource(ref.file);
|
|
782
|
-
const finalLiveBranch = branches === "active" ? liveResolver?.(ref.file) : void 0;
|
|
783
|
-
const finalLineage2 = reconstructSessionLineage(
|
|
784
|
-
ref.file,
|
|
1233
|
+
const normalizedFull = access.normalizeFull(
|
|
785
1234
|
branches,
|
|
786
|
-
|
|
1235
|
+
{ indexThinking: true, indexToolOutput: true },
|
|
1236
|
+
initialLineage
|
|
787
1237
|
);
|
|
788
|
-
|
|
1238
|
+
if (!normalizedFull) {
|
|
1239
|
+
return {
|
|
1240
|
+
session: ref.file,
|
|
1241
|
+
error: stalePointerError(
|
|
1242
|
+
ref.file,
|
|
1243
|
+
expectedSourceHash ?? initialState.sourceHash,
|
|
1244
|
+
initialState.sourceHash,
|
|
1245
|
+
expectedLineageFingerprint ?? initialLineage.fingerprint,
|
|
1246
|
+
initialLineage.fingerprint
|
|
1247
|
+
),
|
|
1248
|
+
entries: []
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
const normalized = normalizedFull.entries;
|
|
1252
|
+
const finalState2 = access.state();
|
|
1253
|
+
const finalLineage2 = access.lineage(branches);
|
|
1254
|
+
const finalObservation = access.observe(branches);
|
|
789
1255
|
if (!finalState2 || !finalObservation || finalState2.sourceHash !== initialState.sourceHash || finalLineage2.fingerprint !== initialLineage.fingerprint) {
|
|
790
1256
|
return {
|
|
791
1257
|
session: ref.file,
|
|
@@ -994,6 +1460,7 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
994
1460
|
const responseAt = (records, cursor2) => {
|
|
995
1461
|
const hasNext = cursor2.position < selected.length;
|
|
996
1462
|
const nextArgs = hasNext ? {
|
|
1463
|
+
...sourceId ? { source: sourceId } : {},
|
|
997
1464
|
session: ref.file,
|
|
998
1465
|
expectedSourceHash: finalState.sourceHash,
|
|
999
1466
|
expectedLineageFingerprint: finalLineage.fingerprint,
|
|
@@ -1071,12 +1538,11 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
1071
1538
|
response = responseAt(output, cursor);
|
|
1072
1539
|
}
|
|
1073
1540
|
}
|
|
1074
|
-
const
|
|
1075
|
-
const endingObservation = observeSource(ref.file, branches, endingLiveBranch);
|
|
1541
|
+
const endingObservation = access.observe(branches);
|
|
1076
1542
|
if (!endingObservation || !sameSourceObservation(snapshot.observation, endingObservation)) {
|
|
1077
1543
|
cache.forgetExpansionSnapshot(snapshot);
|
|
1078
|
-
const actualState =
|
|
1079
|
-
const actualLineage =
|
|
1544
|
+
const actualState = access.state();
|
|
1545
|
+
const actualLineage = access.lineage(branches);
|
|
1080
1546
|
if (!actualState || !endingObservation || actualState.sourceHash !== snapshot.sourceHash || actualLineage.fingerprint !== snapshot.lineageFingerprint) {
|
|
1081
1547
|
return {
|
|
1082
1548
|
session: ref.file,
|
|
@@ -1102,10 +1568,51 @@ async function processMemoryExpand(args, context, cache) {
|
|
|
1102
1568
|
}
|
|
1103
1569
|
|
|
1104
1570
|
// src/memory/sessions-service.ts
|
|
1105
|
-
async function processMemorySessions(args, context) {
|
|
1571
|
+
async function processMemorySessions(args, context, signal) {
|
|
1572
|
+
const sourceId = typeof args.source === "string" && args.source.length > 0 ? args.source : void 0;
|
|
1106
1573
|
const scope = typeof args.scope === "string" ? args.scope : void 0;
|
|
1107
1574
|
const branches = parseBranches(args.branches, "memory.sessions");
|
|
1108
1575
|
const limit = typeof args.limit === "number" && Number.isSafeInteger(args.limit) && args.limit >= 1 ? Math.min(args.limit, SESSIONS_MAX) : SESSIONS_MAX;
|
|
1576
|
+
if (sourceId !== void 0) {
|
|
1577
|
+
try {
|
|
1578
|
+
const source = resolveRegisteredSource(context.sources, sourceId);
|
|
1579
|
+
const { snapshots, coverageReasons: coverageReasons2 } = await listHostSnapshots(source, limit, "list", signal);
|
|
1580
|
+
const options2 = resolveIndexOptions(context.config, context.agentDir, branches);
|
|
1581
|
+
const index2 = loadHostTieredIndex(snapshots, options2, false, void 0, coverageReasons2);
|
|
1582
|
+
const shards2 = new Map(index2.shards.map((shard) => [shard.sessionFile, shard]));
|
|
1583
|
+
const digests2 = new Map(index2.digests.map((digest) => [digest.file, digest]));
|
|
1584
|
+
const sessions2 = snapshots.map((snapshot) => {
|
|
1585
|
+
const tier = index2.tiers.get(snapshot.displayKey) ?? "cold";
|
|
1586
|
+
const shard = shards2.get(snapshot.displayKey);
|
|
1587
|
+
const digest = digests2.get(snapshot.displayKey);
|
|
1588
|
+
return {
|
|
1589
|
+
id: shard?.sessionId ?? digest?.sessionId ?? snapshot.sessionId,
|
|
1590
|
+
file: snapshot.displayKey,
|
|
1591
|
+
cwd: digest?.cwd ?? snapshot.metadata.cwd ?? "",
|
|
1592
|
+
mtime: snapshot.metadata.updatedAt ?? 0,
|
|
1593
|
+
entryCount: shard?.entries.length ?? digest?.entryCount ?? 0,
|
|
1594
|
+
tier,
|
|
1595
|
+
branches,
|
|
1596
|
+
lineageFingerprint: shard?.lineageFingerprint ?? digest?.lineageFingerprint ?? null
|
|
1597
|
+
};
|
|
1598
|
+
});
|
|
1599
|
+
return {
|
|
1600
|
+
scope: `source:${sourceId}`,
|
|
1601
|
+
branches,
|
|
1602
|
+
sessions: sessions2,
|
|
1603
|
+
...index2.coverage.complete ? {} : { coverage: index2.coverage }
|
|
1604
|
+
};
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
const failure = memorySourceFailure(error);
|
|
1607
|
+
if (!failure) throw error;
|
|
1608
|
+
return {
|
|
1609
|
+
scope: `source:${sourceId}`,
|
|
1610
|
+
branches,
|
|
1611
|
+
sessions: [],
|
|
1612
|
+
error: failure
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1109
1616
|
const refs = resolveRefs(scope, context, true).slice(0, limit);
|
|
1110
1617
|
const options = resolveIndexOptions(
|
|
1111
1618
|
context.config,
|
|
@@ -1569,6 +2076,11 @@ var sessionsOutputSchema = {
|
|
|
1569
2076
|
error: errorOutputSchema
|
|
1570
2077
|
}
|
|
1571
2078
|
};
|
|
2079
|
+
var SOURCE_ARG_SCHEMA = {
|
|
2080
|
+
type: "string",
|
|
2081
|
+
minLength: 1,
|
|
2082
|
+
description: "Registered portable memory source id. When set, the call resolves against that source only \u2014 filesystem scopes are never consulted and there is no filesystem fallback."
|
|
2083
|
+
};
|
|
1572
2084
|
var descriptors = [
|
|
1573
2085
|
{
|
|
1574
2086
|
name: "recall",
|
|
@@ -1576,6 +2088,7 @@ var descriptors = [
|
|
|
1576
2088
|
inputSchema: {
|
|
1577
2089
|
type: "object",
|
|
1578
2090
|
properties: {
|
|
2091
|
+
source: SOURCE_ARG_SCHEMA,
|
|
1579
2092
|
query: { type: "string", maxLength: 4096 },
|
|
1580
2093
|
queryMode: {
|
|
1581
2094
|
type: "string",
|
|
@@ -1684,7 +2197,8 @@ var descriptors = [
|
|
|
1684
2197
|
inputSchema: {
|
|
1685
2198
|
type: "object",
|
|
1686
2199
|
properties: {
|
|
1687
|
-
|
|
2200
|
+
source: SOURCE_ARG_SCHEMA,
|
|
2201
|
+
session: { type: "string", description: "Exact session file path, unambiguous id, or source session key." },
|
|
1688
2202
|
expectedSourceHash: {
|
|
1689
2203
|
type: "string",
|
|
1690
2204
|
description: "SHA-256 from a prior pointer; stale sources are refused."
|
|
@@ -1762,6 +2276,7 @@ var descriptors = [
|
|
|
1762
2276
|
inputSchema: {
|
|
1763
2277
|
type: "object",
|
|
1764
2278
|
properties: {
|
|
2279
|
+
source: SOURCE_ARG_SCHEMA,
|
|
1765
2280
|
scope: { type: "string" },
|
|
1766
2281
|
branches: {
|
|
1767
2282
|
type: "string",
|
|
@@ -1797,6 +2312,12 @@ var normalizeMemoryArgs = actionArgNormalizer(
|
|
|
1797
2312
|
() => descriptors,
|
|
1798
2313
|
MEMORY_ARG_NORMALIZATION
|
|
1799
2314
|
);
|
|
2315
|
+
var memoryActionSchemas = Object.fromEntries(
|
|
2316
|
+
descriptors.map((descriptor) => [
|
|
2317
|
+
descriptor.name,
|
|
2318
|
+
{ inputSchema: descriptor.inputSchema, outputSchema: descriptor.outputSchema }
|
|
2319
|
+
])
|
|
2320
|
+
);
|
|
1800
2321
|
var MemoryProvider = class {
|
|
1801
2322
|
constructor(context) {
|
|
1802
2323
|
this.context = context;
|
|
@@ -1822,9 +2343,9 @@ var MemoryProvider = class {
|
|
|
1822
2343
|
case "recall":
|
|
1823
2344
|
return await processMemoryRecall(args, invocationContext, this.context, this.cache);
|
|
1824
2345
|
case "expand":
|
|
1825
|
-
return await processMemoryExpand(args, this.context, this.cache);
|
|
2346
|
+
return await processMemoryExpand(args, this.context, this.cache, invocationContext.signal);
|
|
1826
2347
|
case "sessions":
|
|
1827
|
-
return await processMemorySessions(args, this.context);
|
|
2348
|
+
return await processMemorySessions(args, this.context, invocationContext.signal);
|
|
1828
2349
|
default:
|
|
1829
2350
|
throw new Error(`Unknown memory action: ${actionName}`);
|
|
1830
2351
|
}
|
|
@@ -1848,7 +2369,16 @@ var MemoryProvider = class {
|
|
|
1848
2369
|
export {
|
|
1849
2370
|
uniqueDeclaredKeyForSpelling,
|
|
1850
2371
|
actionArgNormalizer,
|
|
2372
|
+
MemoryRequestCache,
|
|
2373
|
+
MEMORY_SOURCE_INTERFACE_VERSION,
|
|
2374
|
+
MemorySourceError,
|
|
2375
|
+
defineMemorySource,
|
|
2376
|
+
createMemorySourceRegistry,
|
|
2377
|
+
processMemoryRecall,
|
|
2378
|
+
processMemoryExpand,
|
|
2379
|
+
processMemorySessions,
|
|
1851
2380
|
normalizeMemoryArgs,
|
|
2381
|
+
memoryActionSchemas,
|
|
1852
2382
|
MemoryProvider
|
|
1853
2383
|
};
|
|
1854
|
-
//# sourceMappingURL=chunk-
|
|
2384
|
+
//# sourceMappingURL=chunk-GUQT67PQ.js.map
|