@agenr/skeln-plugin 3.3.0 → 2026.6.2
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/build-before-turn-artifact-NPUHVWFE.js +71 -0
- package/dist/build-recall-artifact-F3LS3PZX.js +62 -0
- package/dist/chunk-5AXMFBHR.js +14 -0
- package/dist/chunk-5AYIXQRF.js +4452 -0
- package/dist/{chunk-Z5X7T4QZ.js → chunk-5TIP2EPP.js} +1519 -2565
- package/dist/{chunk-5LADPJ4C.js → chunk-GAERET5Q.js} +138 -504
- package/dist/chunk-GF3PX3VM.js +41 -0
- package/dist/chunk-GKZQ5AG5.js +44 -0
- package/dist/chunk-LDJN7CVU.js +3231 -0
- package/dist/{chunk-ZYADFKX3.js → chunk-MC3C2XM5.js} +34 -1
- package/dist/chunk-NBS62ES5.js +3012 -0
- package/dist/chunk-NSLTJBUC.js +270 -0
- package/dist/chunk-OJSIZDZD.js +9 -0
- package/dist/chunk-OWGQWQUP.js +45 -0
- package/dist/chunk-Q5UTJXHZ.js +1069 -0
- package/dist/{chunk-M5M65AYP.js → chunk-SOQW7356.js} +271 -1934
- package/dist/chunk-VBPYU7GO.js +597 -0
- package/dist/chunk-VTHBPXDQ.js +1750 -0
- package/dist/{chunk-KH52KJSJ.js → chunk-XFJ4S4G2.js} +844 -39
- package/dist/chunk-Y5NB3FTH.js +106 -0
- package/dist/{chunk-RYMSM3OS.js → chunk-ZX55JBV2.js} +1710 -322
- package/dist/claim-slot-policy-CdrW_1l4.d.ts +13 -0
- package/dist/index.d.ts +630 -51
- package/dist/index.js +881 -4682
- package/dist/lifecycle-checkpoint-IAC5FCQU.js +154 -0
- package/dist/{claim-slot-policy-CQ-h0GaV.d.ts → ports-C4QkwDBS.d.ts} +168 -78
- package/dist/scan-6JKPOQHD.js +6 -0
- package/dist/service-EKFACEN6.js +15 -0
- package/dist/service-RHNB5AEQ.js +861 -0
- package/dist/sink-AUAAWC5O.js +8 -0
- package/package.json +1 -1
- package/dist/cli.d.ts +0 -1
- package/dist/internal-eval-server.d.ts +0 -1
- package/dist/internal-recall-eval-server.d.ts +0 -1
|
@@ -1,11 +1,344 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DURABLE_SELECT_COLUMNS,
|
|
3
|
+
buildActiveDurableClause,
|
|
4
|
+
buildValidAsOfClause,
|
|
5
|
+
getDurables,
|
|
6
|
+
mapDurableRow,
|
|
7
|
+
parseJsonStringArray,
|
|
2
8
|
projectClaimCentricRecallEntry,
|
|
9
|
+
readOptionalString,
|
|
10
|
+
readRequiredString,
|
|
3
11
|
runProcedureRecall,
|
|
4
12
|
truncate
|
|
5
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-5TIP2EPP.js";
|
|
6
14
|
import {
|
|
7
15
|
recall
|
|
8
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-GAERET5Q.js";
|
|
17
|
+
import {
|
|
18
|
+
MEMORY_DIRECTIVE_CLAIM_KEY_PREFIX,
|
|
19
|
+
isDirectiveDurable,
|
|
20
|
+
isProactiveDirectiveDurable,
|
|
21
|
+
parseDirectiveMetadata
|
|
22
|
+
} from "./chunk-VTHBPXDQ.js";
|
|
23
|
+
import {
|
|
24
|
+
isCurrentlyValidMemory,
|
|
25
|
+
isWithinValidityWindow,
|
|
26
|
+
resolveKeyedDurableLifecycleStatus
|
|
27
|
+
} from "./chunk-VBPYU7GO.js";
|
|
28
|
+
|
|
29
|
+
// src/core/directives/abstain.ts
|
|
30
|
+
var ABSTAIN_VERB_PATTERN = "(?:mention|mentioning|bring up|bringing up|discuss|discussing|talk about|talking about|reference|referencing|raise|raising|recommend|recommending|suggest|suggesting|surface|surfacing|remind me about|remind me of)";
|
|
31
|
+
var ABSTAIN_LEAD_PATTERN = "(?:do not|don't|do n't|never|please do not|please don't|stop|avoid|no longer)";
|
|
32
|
+
var ABSTAIN_PHRASE_PATTERN = new RegExp(`\\b${ABSTAIN_LEAD_PATTERN}\\s+${ABSTAIN_VERB_PATTERN}\\s+(.+?)(?:[.!?;]|$)`, "giu");
|
|
33
|
+
var TRAILING_QUALIFIER_PATTERN = /\b(?:again|anymore|any more|ever again|ever|at all|please|with me|to me)\s*$/giu;
|
|
34
|
+
var LEADING_DETERMINER_PATTERN = /^(?:the|a|an|any|my|our|that|this|these|those)\s+/iu;
|
|
35
|
+
var MIN_BLOCKED_TERM_LENGTH = 2;
|
|
36
|
+
function parseAbstainDirective(entry) {
|
|
37
|
+
const metadata = parseDirectiveMetadata(entry);
|
|
38
|
+
if (!metadata || metadata.polarity !== "abstain") {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const claimKey = entry.claim_key?.trim() ?? `${MEMORY_DIRECTIVE_CLAIM_KEY_PREFIX}${entry.id}`;
|
|
42
|
+
const blockedTerms = extractBlockedTerms(entry, claimKey);
|
|
43
|
+
if (blockedTerms.length === 0) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
id: entry.id,
|
|
48
|
+
claimKey,
|
|
49
|
+
blockedTerms
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function collectAbstainDirectives(entries) {
|
|
53
|
+
const directives = [];
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
const directive = parseAbstainDirective(entry);
|
|
56
|
+
if (directive) {
|
|
57
|
+
directives.push(directive);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return directives;
|
|
61
|
+
}
|
|
62
|
+
function findAbstainViolation(entry, directives) {
|
|
63
|
+
if (directives.length === 0) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const haystack = normalizeForMatch(`${entry.subject} ${entry.content}`);
|
|
67
|
+
if (haystack.length === 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
for (const directive of directives) {
|
|
71
|
+
if (directive.id === entry.id) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
for (const blockedTerm of directive.blockedTerms) {
|
|
75
|
+
if (mentionsBlockedTerm(haystack, blockedTerm)) {
|
|
76
|
+
return {
|
|
77
|
+
directiveId: directive.id,
|
|
78
|
+
blockedTerm
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
function normalizeTextForPhraseMatch(value) {
|
|
86
|
+
return normalizeForMatch(value);
|
|
87
|
+
}
|
|
88
|
+
function textMentionsPhrase(normalizedHaystack, normalizedPhrase) {
|
|
89
|
+
return mentionsBlockedTerm(normalizedHaystack, normalizedPhrase);
|
|
90
|
+
}
|
|
91
|
+
function textMatchesTopicTrigger(normalizedHaystack, trigger) {
|
|
92
|
+
if (!trigger.startsWith("topic:")) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
const topic = trigger.slice("topic:".length);
|
|
96
|
+
return textMentionsPhrase(normalizedHaystack, topic);
|
|
97
|
+
}
|
|
98
|
+
function extractBlockedTerms(entry, claimKey) {
|
|
99
|
+
const terms = /* @__PURE__ */ new Set();
|
|
100
|
+
for (const source of [entry.content, entry.subject]) {
|
|
101
|
+
for (const phrase of matchAbstainPhrases(source)) {
|
|
102
|
+
const cleaned = cleanBlockedTerm(phrase);
|
|
103
|
+
if (cleaned.length >= MIN_BLOCKED_TERM_LENGTH) {
|
|
104
|
+
terms.add(cleaned);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (terms.size === 0) {
|
|
109
|
+
const fallback = cleanBlockedTerm(deriveTermFromClaimKey(claimKey));
|
|
110
|
+
if (fallback.length >= MIN_BLOCKED_TERM_LENGTH) {
|
|
111
|
+
terms.add(fallback);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return Array.from(terms);
|
|
115
|
+
}
|
|
116
|
+
function matchAbstainPhrases(source) {
|
|
117
|
+
const phrases = [];
|
|
118
|
+
const pattern = new RegExp(ABSTAIN_PHRASE_PATTERN.source, ABSTAIN_PHRASE_PATTERN.flags);
|
|
119
|
+
let match = pattern.exec(source);
|
|
120
|
+
while (match !== null) {
|
|
121
|
+
const captured = match[1];
|
|
122
|
+
if (captured) {
|
|
123
|
+
phrases.push(captured);
|
|
124
|
+
}
|
|
125
|
+
match = pattern.exec(source);
|
|
126
|
+
}
|
|
127
|
+
return phrases;
|
|
128
|
+
}
|
|
129
|
+
function deriveTermFromClaimKey(claimKey) {
|
|
130
|
+
const suffix = claimKey.slice(MEMORY_DIRECTIVE_CLAIM_KEY_PREFIX.length);
|
|
131
|
+
return suffix.replace(/^(?:do[_-]?not[_-]?mention[_-]?|avoid[_-]?|no[_-]?)/iu, "").replace(/[_-]+/gu, " ").trim();
|
|
132
|
+
}
|
|
133
|
+
function cleanBlockedTerm(phrase) {
|
|
134
|
+
const collapsed = phrase.replace(/\s+/gu, " ").trim();
|
|
135
|
+
const withoutLead = collapsed.replace(LEADING_DETERMINER_PATTERN, "");
|
|
136
|
+
const withoutTrailing = withoutLead.replace(TRAILING_QUALIFIER_PATTERN, "").trim();
|
|
137
|
+
return normalizeForMatch(withoutTrailing);
|
|
138
|
+
}
|
|
139
|
+
function mentionsBlockedTerm(haystack, blockedTerm) {
|
|
140
|
+
if (blockedTerm.length < MIN_BLOCKED_TERM_LENGTH) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const escaped = escapeRegExp(blockedTerm).replace(/\\?\s+/gu, "\\s+");
|
|
144
|
+
const pattern = new RegExp(`(?:^|[^\\p{L}\\p{N}])${escaped}(?:[^\\p{L}\\p{N}]|$)`, "iu");
|
|
145
|
+
return pattern.test(haystack);
|
|
146
|
+
}
|
|
147
|
+
function normalizeForMatch(value) {
|
|
148
|
+
return value.replace(/\s+/gu, " ").trim().normalize("NFKC").toLocaleLowerCase();
|
|
149
|
+
}
|
|
150
|
+
function escapeRegExp(value) {
|
|
151
|
+
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/app/directives/abstain-filter.ts
|
|
155
|
+
var ABSTAIN_DIRECTIVE_LOOKUP_FAILED_NOTICE = "Memory-directive lookup failed; blocked-topic suppression was skipped this pass and only directive rows were withheld.";
|
|
156
|
+
async function applyAbstainDirectives(items, listActiveAbstainDirectives2) {
|
|
157
|
+
if (items.length === 0) {
|
|
158
|
+
return { kept: [...items], suppressed: [], lookupFailed: false };
|
|
159
|
+
}
|
|
160
|
+
const suppressed = [];
|
|
161
|
+
const nonDirectiveItems = [];
|
|
162
|
+
for (const item of items) {
|
|
163
|
+
if (isDirectiveDurable(item.entry) && !isAllowedDirectiveInjectionItem(item)) {
|
|
164
|
+
suppressed.push({ entryId: item.entry.id, reason: "directive_self" });
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
nonDirectiveItems.push(item);
|
|
168
|
+
}
|
|
169
|
+
if (!listActiveAbstainDirectives2 || nonDirectiveItems.length === 0) {
|
|
170
|
+
return { kept: nonDirectiveItems, suppressed, lookupFailed: false };
|
|
171
|
+
}
|
|
172
|
+
let directiveRows;
|
|
173
|
+
try {
|
|
174
|
+
directiveRows = await listActiveAbstainDirectives2();
|
|
175
|
+
} catch {
|
|
176
|
+
return { kept: nonDirectiveItems, suppressed, lookupFailed: true };
|
|
177
|
+
}
|
|
178
|
+
const directives = collectAbstainDirectives(directiveRows);
|
|
179
|
+
if (directives.length === 0) {
|
|
180
|
+
return { kept: nonDirectiveItems, suppressed, lookupFailed: false };
|
|
181
|
+
}
|
|
182
|
+
const kept = [];
|
|
183
|
+
for (const item of nonDirectiveItems) {
|
|
184
|
+
const violation = findAbstainViolation(item.entry, directives);
|
|
185
|
+
if (violation) {
|
|
186
|
+
suppressed.push({
|
|
187
|
+
entryId: item.entry.id,
|
|
188
|
+
reason: "directive_topic",
|
|
189
|
+
directiveId: violation.directiveId,
|
|
190
|
+
blockedTerm: violation.blockedTerm
|
|
191
|
+
});
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
kept.push(item);
|
|
195
|
+
}
|
|
196
|
+
return { kept, suppressed, lookupFailed: false };
|
|
197
|
+
}
|
|
198
|
+
function buildAbstentionNotice(suppression) {
|
|
199
|
+
if (suppression.reason === "directive_self") {
|
|
200
|
+
return `Skipped injecting memory directive ${suppression.entryId}; directives are not surfaced as memory.`;
|
|
201
|
+
}
|
|
202
|
+
const directive = suppression.directiveId ?? "unknown";
|
|
203
|
+
const term = suppression.blockedTerm ?? "a blocked topic";
|
|
204
|
+
return `Suppressed durable ${suppression.entryId} because memory directive ${directive} blocks "${term}".`;
|
|
205
|
+
}
|
|
206
|
+
async function applyAbstainDirectivesForInjection(items, listActiveAbstainDirectives2, diagnostics) {
|
|
207
|
+
const result = await applyAbstainDirectives(items, listActiveAbstainDirectives2);
|
|
208
|
+
if (result.lookupFailed) {
|
|
209
|
+
diagnostics.notices.push(ABSTAIN_DIRECTIVE_LOOKUP_FAILED_NOTICE);
|
|
210
|
+
}
|
|
211
|
+
if (result.suppressed.length > 0) {
|
|
212
|
+
diagnostics.directiveAbstentions = result.suppressed;
|
|
213
|
+
for (const suppression of result.suppressed) {
|
|
214
|
+
diagnostics.notices.push(buildAbstentionNotice(suppression));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return result.kept;
|
|
218
|
+
}
|
|
219
|
+
function isAllowedDirectiveInjectionItem(item) {
|
|
220
|
+
return item.sourceKind === "directive" && isProactiveDirectiveDurable(item.entry);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/app/before-turn/format-provenance.ts
|
|
224
|
+
function formatProjectedProvenance(provenance) {
|
|
225
|
+
const parts = [
|
|
226
|
+
provenance.supersededById ? `superseded_by=${provenance.supersededById}` : void 0,
|
|
227
|
+
provenance.supersessionKind ? `kind=${provenance.supersessionKind}` : void 0,
|
|
228
|
+
provenance.supersessionReason ? `reason=${provenance.supersessionReason}` : void 0,
|
|
229
|
+
provenance.supportSourceKind ? `support=${provenance.supportSourceKind}` : void 0,
|
|
230
|
+
provenance.supportMode ? `support_mode=${provenance.supportMode}` : void 0,
|
|
231
|
+
provenance.supportObservedAt ? `observed=${provenance.supportObservedAt}` : void 0,
|
|
232
|
+
provenance.supportLocator ? `locator=${provenance.supportLocator}` : void 0
|
|
233
|
+
].filter((value) => value !== void 0);
|
|
234
|
+
return parts.length > 0 ? parts.join(" | ") : void 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/app/before-turn/select-patch-items.ts
|
|
238
|
+
function selectDurablePatchItems(items, policy, diagnostics) {
|
|
239
|
+
if (policy.maxDurableEntries <= 0 || items.length === 0) {
|
|
240
|
+
return [];
|
|
241
|
+
}
|
|
242
|
+
const boundedItems = items.slice(0, policy.maxDurableEntries);
|
|
243
|
+
const expandedLimit = Math.max(policy.maxDurableEntries, policy.maxHighConfidenceDurableEntries);
|
|
244
|
+
if (expandedLimit <= policy.maxDurableEntries || items.length <= policy.maxDurableEntries) {
|
|
245
|
+
return boundedItems;
|
|
246
|
+
}
|
|
247
|
+
const expansionCandidates = items.slice(0, expandedLimit);
|
|
248
|
+
const canExpand = expansionCandidates.length > policy.maxDurableEntries && expansionCandidates.every((item) => item.score >= policy.highConfidenceRecallThreshold);
|
|
249
|
+
if (canExpand) {
|
|
250
|
+
diagnostics.notices.push(`Before-turn durable recall expanded to ${expansionCandidates.length} high-confidence items.`);
|
|
251
|
+
return expansionCandidates;
|
|
252
|
+
}
|
|
253
|
+
diagnostics.notices.push(
|
|
254
|
+
`Before-turn durable recall kept the top ${boundedItems.length} item${boundedItems.length === 1 ? "" : "s"} because additional candidates were not high confidence.`
|
|
255
|
+
);
|
|
256
|
+
return boundedItems;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/app/before-turn/topic-directives.ts
|
|
260
|
+
var TOPIC_PROACTIVE_DIRECTIVE_LOOKUP_FAILED_NOTICE = "Topic proactive directive lookup failed; topic directive surfacing was skipped this pass.";
|
|
261
|
+
async function injectTopicProactiveDirectives(currentTurnText, recalledItems, policy, deps, diagnostics) {
|
|
262
|
+
if (!deps.listActiveTopicProactiveDirectives) {
|
|
263
|
+
return recalledItems;
|
|
264
|
+
}
|
|
265
|
+
let directiveRows;
|
|
266
|
+
try {
|
|
267
|
+
directiveRows = await deps.listActiveTopicProactiveDirectives();
|
|
268
|
+
} catch {
|
|
269
|
+
diagnostics.notices.push(TOPIC_PROACTIVE_DIRECTIVE_LOOKUP_FAILED_NOTICE);
|
|
270
|
+
return recalledItems;
|
|
271
|
+
}
|
|
272
|
+
const now = deps.now ?? /* @__PURE__ */ new Date();
|
|
273
|
+
const nowMs = now.getTime();
|
|
274
|
+
const activeDirectives = filterCurrentEntries(directiveRows, nowMs);
|
|
275
|
+
diagnostics.topicProactiveDirectiveCandidateCount = activeDirectives.length;
|
|
276
|
+
const normalizedTurn = normalizeTextForPhraseMatch(currentTurnText);
|
|
277
|
+
const matchedDirectives = activeDirectives.filter((entry) => {
|
|
278
|
+
const metadata = parseDirectiveMetadata(entry);
|
|
279
|
+
return metadata?.polarity === "proactive" && metadata.trigger.startsWith("topic:") && textMatchesTopicTrigger(normalizedTurn, metadata.trigger);
|
|
280
|
+
});
|
|
281
|
+
diagnostics.topicProactiveDirectiveMatchedCount = matchedDirectives.length;
|
|
282
|
+
if (matchedDirectives.length === 0) {
|
|
283
|
+
return recalledItems;
|
|
284
|
+
}
|
|
285
|
+
const directiveItems = matchedDirectives.map((entry) => buildTopicDirectivePatchItem(entry, deps, policy.highConfidenceRecallThreshold));
|
|
286
|
+
return mergeTopicDirectivePatchItems(directiveItems, recalledItems, policy, diagnostics);
|
|
287
|
+
}
|
|
288
|
+
function filterCurrentEntries(entries, nowMs) {
|
|
289
|
+
return entries.filter((entry) => isWithinValidityWindow(entry.valid_from, entry.valid_to, nowMs));
|
|
290
|
+
}
|
|
291
|
+
function buildTopicDirectivePatchItem(entry, deps, score) {
|
|
292
|
+
const metadata = parseDirectiveMetadata(entry);
|
|
293
|
+
const projected = projectClaimCentricRecallEntry(buildSyntheticRecallOutput(entry, score), {
|
|
294
|
+
slotPolicyConfig: deps.slotPolicyConfig
|
|
295
|
+
});
|
|
296
|
+
const provenanceSummary = formatProjectedProvenance(projected.provenance);
|
|
297
|
+
return {
|
|
298
|
+
rank: 0,
|
|
299
|
+
entry,
|
|
300
|
+
sourceKind: "directive",
|
|
301
|
+
score,
|
|
302
|
+
whySurfaced: {
|
|
303
|
+
summary: `proactive memory directive; trigger ${metadata?.trigger ?? "topic"}`,
|
|
304
|
+
reasons: ["proactive memory directive", `trigger ${metadata?.trigger ?? "topic"}`, `importance ${entry.importance}`]
|
|
305
|
+
},
|
|
306
|
+
memoryState: projected.memoryState,
|
|
307
|
+
claimStatus: projected.claimStatus,
|
|
308
|
+
freshnessLabel: projected.freshness.label,
|
|
309
|
+
...provenanceSummary ? { provenanceSummary } : {}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function buildSyntheticRecallOutput(entry, score) {
|
|
313
|
+
return {
|
|
314
|
+
entry,
|
|
315
|
+
score,
|
|
316
|
+
scores: {
|
|
317
|
+
relevance: score,
|
|
318
|
+
rrf: score,
|
|
319
|
+
vector: 0,
|
|
320
|
+
lexical: 0,
|
|
321
|
+
recency: 1,
|
|
322
|
+
importance: entry.importance / 10,
|
|
323
|
+
historicalLineage: 0,
|
|
324
|
+
neighborhoodBoost: 0,
|
|
325
|
+
claimKeyTrustPenalty: 0,
|
|
326
|
+
claimKeyRedundancyPenalty: 0
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function mergeTopicDirectivePatchItems(directiveItems, recalledItems, policy, diagnostics) {
|
|
331
|
+
const seenEntryIds = /* @__PURE__ */ new Set();
|
|
332
|
+
const merged = [];
|
|
333
|
+
for (const item of [...directiveItems, ...recalledItems]) {
|
|
334
|
+
if (seenEntryIds.has(item.entry.id)) {
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
seenEntryIds.add(item.entry.id);
|
|
338
|
+
merged.push(item);
|
|
339
|
+
}
|
|
340
|
+
return selectDurablePatchItems(merged, policy, diagnostics);
|
|
341
|
+
}
|
|
9
342
|
|
|
10
343
|
// src/app/before-turn/service.ts
|
|
11
344
|
var DEFAULT_MAX_DURABLE_ENTRIES = 1;
|
|
@@ -114,10 +447,12 @@ async function runBeforeTurn(input, deps) {
|
|
|
114
447
|
diagnostics
|
|
115
448
|
};
|
|
116
449
|
}
|
|
117
|
-
const [
|
|
450
|
+
const [recalledDurableMemory, procedure] = await Promise.all([
|
|
118
451
|
policy.enableDurableRecall ? runDurableRecallSelection(currentTurnText, durableQueryPlan, input.sessionKey, policy, deps, diagnostics) : Promise.resolve([]),
|
|
119
452
|
policy.enableProcedureSuggestion && procedureQuery ? runProcedureSelection(procedureQuery, policy, deps, diagnostics) : Promise.resolve(void 0)
|
|
120
453
|
]);
|
|
454
|
+
const durableMemoryWithTopicDirectives = await injectTopicProactiveDirectives(currentTurnText, recalledDurableMemory, policy, deps, diagnostics);
|
|
455
|
+
const durableMemory = await applyAbstainDirectivesForInjection(durableMemoryWithTopicDirectives, deps.listActiveAbstainDirectives, diagnostics);
|
|
121
456
|
if (!policy.enableDurableRecall) {
|
|
122
457
|
diagnostics.abstentionReasons.push("Durable recall disabled by before-turn policy.");
|
|
123
458
|
} else if (durableMemory.length === 0) {
|
|
@@ -217,7 +552,8 @@ async function runDurableRecallAttempt(currentTurnText, query, sessionKey, polic
|
|
|
217
552
|
durableRecallTrace = summary;
|
|
218
553
|
}
|
|
219
554
|
},
|
|
220
|
-
slotPolicyConfig: deps.slotPolicyConfig
|
|
555
|
+
slotPolicyConfig: deps.slotPolicyConfig,
|
|
556
|
+
...deps.now ? { now: deps.now } : {}
|
|
221
557
|
}
|
|
222
558
|
);
|
|
223
559
|
const notices = durableRecallTrace?.degraded.notices.length ? [...durableRecallTrace.degraded.notices] : [];
|
|
@@ -537,7 +873,7 @@ function isIdentityWrapperSubject(subject, entity) {
|
|
|
537
873
|
return false;
|
|
538
874
|
}
|
|
539
875
|
function hasDefinitionalContent(content, entity) {
|
|
540
|
-
const escapedEntity =
|
|
876
|
+
const escapedEntity = escapeRegExp2(entity);
|
|
541
877
|
if (startsWithBareRelationshipPredicate(content, escapedEntity)) {
|
|
542
878
|
return false;
|
|
543
879
|
}
|
|
@@ -602,32 +938,12 @@ function containsKeyword(text, keywords) {
|
|
|
602
938
|
}
|
|
603
939
|
return false;
|
|
604
940
|
}
|
|
605
|
-
function
|
|
941
|
+
function escapeRegExp2(value) {
|
|
606
942
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
607
943
|
}
|
|
608
944
|
function roundToThreeDecimals(value) {
|
|
609
945
|
return Math.round(value * 1e3) / 1e3;
|
|
610
946
|
}
|
|
611
|
-
function selectDurablePatchItems(items, policy, diagnostics) {
|
|
612
|
-
if (policy.maxDurableEntries <= 0 || items.length === 0) {
|
|
613
|
-
return [];
|
|
614
|
-
}
|
|
615
|
-
const boundedItems = items.slice(0, policy.maxDurableEntries);
|
|
616
|
-
const expandedLimit = Math.max(policy.maxDurableEntries, policy.maxHighConfidenceDurableEntries);
|
|
617
|
-
if (expandedLimit <= policy.maxDurableEntries || items.length <= policy.maxDurableEntries) {
|
|
618
|
-
return boundedItems;
|
|
619
|
-
}
|
|
620
|
-
const expansionCandidates = items.slice(0, expandedLimit);
|
|
621
|
-
const canExpand = expansionCandidates.length > policy.maxDurableEntries && expansionCandidates.every((item) => item.score >= policy.highConfidenceRecallThreshold);
|
|
622
|
-
if (canExpand) {
|
|
623
|
-
diagnostics.notices.push(`Before-turn durable recall expanded to ${expansionCandidates.length} high-confidence items.`);
|
|
624
|
-
return expansionCandidates;
|
|
625
|
-
}
|
|
626
|
-
diagnostics.notices.push(
|
|
627
|
-
`Before-turn durable recall kept the top ${boundedItems.length} item${boundedItems.length === 1 ? "" : "s"} because additional candidates were not high confidence.`
|
|
628
|
-
);
|
|
629
|
-
return boundedItems;
|
|
630
|
-
}
|
|
631
947
|
function inspectTurnSignal(currentTurnText) {
|
|
632
948
|
const normalizedTurn = normalizeWhitespace(currentTurnText);
|
|
633
949
|
const lowerTurn = normalizedTurn.toLowerCase();
|
|
@@ -730,18 +1046,6 @@ function normalizeRecentTurns(recentTurns, maxRecentTurns, currentTurnText) {
|
|
|
730
1046
|
}
|
|
731
1047
|
return deduped.slice(-maxRecentTurns);
|
|
732
1048
|
}
|
|
733
|
-
function formatProjectedProvenance(provenance) {
|
|
734
|
-
const parts = [
|
|
735
|
-
provenance.supersededById ? `superseded_by=${provenance.supersededById}` : void 0,
|
|
736
|
-
provenance.supersessionKind ? `kind=${provenance.supersessionKind}` : void 0,
|
|
737
|
-
provenance.supersessionReason ? `reason=${provenance.supersessionReason}` : void 0,
|
|
738
|
-
provenance.supportSourceKind ? `support=${provenance.supportSourceKind}` : void 0,
|
|
739
|
-
provenance.supportMode ? `support_mode=${provenance.supportMode}` : void 0,
|
|
740
|
-
provenance.supportObservedAt ? `observed=${provenance.supportObservedAt}` : void 0,
|
|
741
|
-
provenance.supportLocator ? `locator=${provenance.supportLocator}` : void 0
|
|
742
|
-
].filter((value) => value !== void 0);
|
|
743
|
-
return parts.length > 0 ? parts.join(" | ") : void 0;
|
|
744
|
-
}
|
|
745
1049
|
function normalizeOptionalString(value) {
|
|
746
1050
|
const normalized = value?.trim();
|
|
747
1051
|
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
@@ -863,12 +1167,513 @@ function formatProcedureBodyLines(suggestion) {
|
|
|
863
1167
|
return lines;
|
|
864
1168
|
}
|
|
865
1169
|
|
|
1170
|
+
// src/app/session-memory/predecessor-artifacts.ts
|
|
1171
|
+
var SESSION_START_ARTIFACT_KINDS = [
|
|
1172
|
+
"compaction_checkpoint",
|
|
1173
|
+
"branch_abandonment",
|
|
1174
|
+
"session_episode"
|
|
1175
|
+
];
|
|
1176
|
+
async function resolvePredecessorSessionArtifacts(input, repository) {
|
|
1177
|
+
const sessionKey = input.sessionKey.trim();
|
|
1178
|
+
if (!sessionKey) {
|
|
1179
|
+
return {
|
|
1180
|
+
artifacts: []
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
const lineageEdge = await repository.getLatestLineageEdgeForChild(sessionKey);
|
|
1184
|
+
const predecessorSessionKey = lineageEdge?.parentSessionKey?.trim();
|
|
1185
|
+
const parentSourceRef = lineageEdge?.parentSourceRef?.trim();
|
|
1186
|
+
if (!predecessorSessionKey && !parentSourceRef) {
|
|
1187
|
+
return {
|
|
1188
|
+
...lineageEdge ? { lineageEdge } : {},
|
|
1189
|
+
artifacts: []
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
const artifacts = predecessorSessionKey ? await repository.listSessionArtifacts({
|
|
1193
|
+
sessionKey: predecessorSessionKey,
|
|
1194
|
+
kinds: [...SESSION_START_ARTIFACT_KINDS],
|
|
1195
|
+
limit: 10
|
|
1196
|
+
}) : await repository.listSessionArtifactsBySourceRef({
|
|
1197
|
+
sourceRef: parentSourceRef,
|
|
1198
|
+
kinds: [...SESSION_START_ARTIFACT_KINDS],
|
|
1199
|
+
limit: 10
|
|
1200
|
+
});
|
|
1201
|
+
return {
|
|
1202
|
+
...lineageEdge ? { lineageEdge } : {},
|
|
1203
|
+
artifacts
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
// src/app/session-start/artifact-recall-query.ts
|
|
1208
|
+
var ARTIFACT_QUERY_TITLES = {
|
|
1209
|
+
compaction_checkpoint: "Compaction checkpoint",
|
|
1210
|
+
branch_abandonment: "Branch abandonment",
|
|
1211
|
+
session_episode: "Session episode"
|
|
1212
|
+
};
|
|
1213
|
+
var SESSION_START_QUERY_ARTIFACT_ORDER = new Map(SESSION_START_ARTIFACT_KINDS.map((kind, index) => [kind, index]));
|
|
1214
|
+
function buildSessionStartArtifactRecallQuery(artifacts, maxChars) {
|
|
1215
|
+
if (artifacts.length === 0 || maxChars <= 0) {
|
|
1216
|
+
return void 0;
|
|
1217
|
+
}
|
|
1218
|
+
const orderedArtifacts = [...artifacts].sort(compareSessionStartArtifacts);
|
|
1219
|
+
let remaining = maxChars;
|
|
1220
|
+
const parts = [];
|
|
1221
|
+
for (const artifact of orderedArtifacts) {
|
|
1222
|
+
if (remaining <= 0) {
|
|
1223
|
+
break;
|
|
1224
|
+
}
|
|
1225
|
+
const title = ARTIFACT_QUERY_TITLES[artifact.kind];
|
|
1226
|
+
if (!title) {
|
|
1227
|
+
continue;
|
|
1228
|
+
}
|
|
1229
|
+
const normalizedContent = normalizeWhitespace2(artifact.summary);
|
|
1230
|
+
if (normalizedContent.length === 0) {
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
const labeled = `${title}: ${normalizedContent}`;
|
|
1234
|
+
const truncated = truncate3(labeled, remaining);
|
|
1235
|
+
if (truncated.length === 0) {
|
|
1236
|
+
continue;
|
|
1237
|
+
}
|
|
1238
|
+
parts.push(truncated);
|
|
1239
|
+
remaining -= truncated.length;
|
|
1240
|
+
}
|
|
1241
|
+
const query = normalizeWhitespace2(parts.join("\n"));
|
|
1242
|
+
return query.length > 0 ? query : void 0;
|
|
1243
|
+
}
|
|
1244
|
+
function compareSessionStartArtifacts(left, right) {
|
|
1245
|
+
const leftOrder = SESSION_START_QUERY_ARTIFACT_ORDER.get(left.kind) ?? Number.MAX_SAFE_INTEGER;
|
|
1246
|
+
const rightOrder = SESSION_START_QUERY_ARTIFACT_ORDER.get(right.kind) ?? Number.MAX_SAFE_INTEGER;
|
|
1247
|
+
if (leftOrder !== rightOrder) {
|
|
1248
|
+
return leftOrder - rightOrder;
|
|
1249
|
+
}
|
|
1250
|
+
return right.createdAt.localeCompare(left.createdAt);
|
|
1251
|
+
}
|
|
1252
|
+
function normalizeWhitespace2(value) {
|
|
1253
|
+
return value.replace(/\s+/g, " ").trim();
|
|
1254
|
+
}
|
|
1255
|
+
function truncate3(value, maxChars) {
|
|
1256
|
+
if (maxChars <= 0) {
|
|
1257
|
+
return "";
|
|
1258
|
+
}
|
|
1259
|
+
if (value.length <= maxChars) {
|
|
1260
|
+
return value;
|
|
1261
|
+
}
|
|
1262
|
+
return `${value.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
// src/app/session-start/service.ts
|
|
1266
|
+
var DEFAULT_MAX_CORE_ENTRIES = 4;
|
|
1267
|
+
var DEFAULT_MAX_ARTIFACT_RECALL_ENTRIES = 3;
|
|
1268
|
+
var DEFAULT_MAX_DURABLE_ENTRIES2 = 5;
|
|
1269
|
+
var DEFAULT_MAX_ARTIFACT_CHARS = 1200;
|
|
1270
|
+
var DEFAULT_MAX_PROFILE_SNAPSHOT_AGE_HOURS = 48;
|
|
1271
|
+
async function runSessionStart(input, deps) {
|
|
1272
|
+
const policy = normalizePolicy2(input.policy);
|
|
1273
|
+
const now = deps.now ?? /* @__PURE__ */ new Date();
|
|
1274
|
+
const nowMs = now.getTime();
|
|
1275
|
+
const profileSnapshot = await deps.repository.getActiveProfileSnapshot(policy.maxProfileSnapshotAgeHours * 60 * 60 * 1e3, now);
|
|
1276
|
+
const profileEntries = profileSnapshot ? filterCurrentEntries2(await deps.repository.listEntriesByIds(profileSnapshot.durableIds), nowMs) : [];
|
|
1277
|
+
const profileItems = profileEntries.map((entry) => buildProfilePatchItem(entry, profileSnapshot?.id ?? "unknown", nowMs));
|
|
1278
|
+
const proactiveDirectiveEntries = filterCurrentEntries2(await deps.listActiveProactiveDirectives?.() ?? [], nowMs);
|
|
1279
|
+
const proactiveDirectiveItems = proactiveDirectiveEntries.map((entry) => buildDirectivePatchItem(entry, nowMs));
|
|
1280
|
+
const coreEntries = await deps.repository.listCoreEntries(policy.maxCoreEntries, now);
|
|
1281
|
+
const coreItems = coreEntries.map((entry) => buildCorePatchItem(entry, nowMs));
|
|
1282
|
+
const diagnostics = {
|
|
1283
|
+
coreCandidateCount: coreEntries.length,
|
|
1284
|
+
profileCandidateCount: profileEntries.length,
|
|
1285
|
+
...profileSnapshot ? { activeProfileSnapshotId: profileSnapshot.id } : {},
|
|
1286
|
+
proactiveDirectiveCandidateCount: proactiveDirectiveEntries.length,
|
|
1287
|
+
artifactRecallCandidateCount: 0,
|
|
1288
|
+
artifactRecallUsed: false,
|
|
1289
|
+
notices: []
|
|
1290
|
+
};
|
|
1291
|
+
const artifactRecallQuery = await resolveSessionStartArtifactRecallQuery(input.sessionKey, policy, deps);
|
|
1292
|
+
if (!policy.enableArtifactRecall) {
|
|
1293
|
+
diagnostics.notices.push("Artifact-grounded durable recall disabled by session-start policy.");
|
|
1294
|
+
}
|
|
1295
|
+
const artifactRecallItems = artifactRecallQuery ? await runArtifactRecallSelection(artifactRecallQuery, input.sessionKey, policy, deps, diagnostics) : [];
|
|
1296
|
+
const mergedDurableMemory = mergeDurableMemory(profileItems, proactiveDirectiveItems, coreItems, artifactRecallItems, policy.maxDurableEntries);
|
|
1297
|
+
const visibleDurableMemory = await applyAbstainDirectivesForInjection(mergedDurableMemory, deps.listActiveAbstainDirectives, diagnostics);
|
|
1298
|
+
const durableMemory = assignRanks2(visibleDurableMemory);
|
|
1299
|
+
return {
|
|
1300
|
+
durableMemory,
|
|
1301
|
+
diagnostics
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
async function resolveSessionStartArtifactRecallQuery(sessionKey, policy, deps) {
|
|
1305
|
+
if (!policy.enableArtifactRecall) {
|
|
1306
|
+
return void 0;
|
|
1307
|
+
}
|
|
1308
|
+
const normalizedSessionKey = sessionKey?.trim();
|
|
1309
|
+
if (!normalizedSessionKey || !deps.sessionMemoryRepository) {
|
|
1310
|
+
return void 0;
|
|
1311
|
+
}
|
|
1312
|
+
const predecessor = await resolvePredecessorSessionArtifacts({ sessionKey: normalizedSessionKey }, deps.sessionMemoryRepository);
|
|
1313
|
+
return buildSessionStartArtifactRecallQuery(predecessor.artifacts, policy.maxArtifactChars);
|
|
1314
|
+
}
|
|
1315
|
+
function buildProfilePatchItem(entry, snapshotId, nowMs) {
|
|
1316
|
+
return {
|
|
1317
|
+
rank: 0,
|
|
1318
|
+
entry,
|
|
1319
|
+
sourceKind: "profile",
|
|
1320
|
+
whySurfaced: {
|
|
1321
|
+
summary: `active profile snapshot ${snapshotId}`,
|
|
1322
|
+
reasons: ["active profile snapshot", `snapshot ${snapshotId}`, `importance ${entry.importance}`]
|
|
1323
|
+
},
|
|
1324
|
+
memoryState: resolveMemoryState(entry, nowMs),
|
|
1325
|
+
claimStatus: resolveClaimStatus(entry),
|
|
1326
|
+
freshnessLabel: buildFreshnessLabel(entry),
|
|
1327
|
+
...buildProvenanceSummary(entry) ? { provenanceSummary: buildProvenanceSummary(entry) } : {}
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
function buildDirectivePatchItem(entry, nowMs) {
|
|
1331
|
+
const metadata = parseDirectiveMetadata(entry);
|
|
1332
|
+
return {
|
|
1333
|
+
rank: 0,
|
|
1334
|
+
entry,
|
|
1335
|
+
sourceKind: "directive",
|
|
1336
|
+
whySurfaced: {
|
|
1337
|
+
summary: `proactive memory directive; trigger ${metadata?.trigger ?? "session_start"}`,
|
|
1338
|
+
reasons: ["proactive memory directive", `trigger ${metadata?.trigger ?? "session_start"}`, `importance ${entry.importance}`]
|
|
1339
|
+
},
|
|
1340
|
+
memoryState: resolveMemoryState(entry, nowMs),
|
|
1341
|
+
claimStatus: resolveClaimStatus(entry),
|
|
1342
|
+
freshnessLabel: buildFreshnessLabel(entry),
|
|
1343
|
+
...buildProvenanceSummary(entry) ? { provenanceSummary: buildProvenanceSummary(entry) } : {}
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
async function runArtifactRecallSelection(query, sessionKey, policy, deps, diagnostics) {
|
|
1347
|
+
diagnostics.artifactRecallUsed = true;
|
|
1348
|
+
diagnostics.artifactRecallQuery = query;
|
|
1349
|
+
let artifactRecallTrace;
|
|
1350
|
+
try {
|
|
1351
|
+
const recalled = await recall(
|
|
1352
|
+
{
|
|
1353
|
+
text: query,
|
|
1354
|
+
limit: policy.maxArtifactRecallEntries,
|
|
1355
|
+
threshold: policy.recallThreshold,
|
|
1356
|
+
sessionKey
|
|
1357
|
+
},
|
|
1358
|
+
deps.recall,
|
|
1359
|
+
{
|
|
1360
|
+
trace: {
|
|
1361
|
+
reportSummary(summary) {
|
|
1362
|
+
artifactRecallTrace = summary;
|
|
1363
|
+
}
|
|
1364
|
+
},
|
|
1365
|
+
slotPolicyConfig: deps.slotPolicyConfig,
|
|
1366
|
+
...deps.now ? { now: deps.now } : {}
|
|
1367
|
+
}
|
|
1368
|
+
);
|
|
1369
|
+
diagnostics.artifactRecallTrace = artifactRecallTrace;
|
|
1370
|
+
diagnostics.artifactRecallCandidateCount = recalled.length;
|
|
1371
|
+
if (artifactRecallTrace?.degraded.notices.length) {
|
|
1372
|
+
diagnostics.notices.push(...artifactRecallTrace.degraded.notices);
|
|
1373
|
+
}
|
|
1374
|
+
return recalled.map((item) => buildArtifactRecallPatchItem(item, deps));
|
|
1375
|
+
} catch (error) {
|
|
1376
|
+
diagnostics.artifactRecallTrace = artifactRecallTrace;
|
|
1377
|
+
diagnostics.notices.push(`Artifact-grounded durable recall failed: ${formatErrorMessage2(error)}`);
|
|
1378
|
+
return [];
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
function buildCorePatchItem(entry, nowMs) {
|
|
1382
|
+
return {
|
|
1383
|
+
rank: 0,
|
|
1384
|
+
entry,
|
|
1385
|
+
sourceKind: "core",
|
|
1386
|
+
whySurfaced: {
|
|
1387
|
+
summary: `always-on core memory; importance ${entry.importance}`,
|
|
1388
|
+
reasons: ["always-on core memory", `importance ${entry.importance}`, `expiry ${entry.expiry}`]
|
|
1389
|
+
},
|
|
1390
|
+
memoryState: resolveMemoryState(entry, nowMs),
|
|
1391
|
+
claimStatus: resolveClaimStatus(entry),
|
|
1392
|
+
freshnessLabel: buildFreshnessLabel(entry),
|
|
1393
|
+
...buildProvenanceSummary(entry) ? { provenanceSummary: buildProvenanceSummary(entry) } : {}
|
|
1394
|
+
};
|
|
1395
|
+
}
|
|
1396
|
+
function buildArtifactRecallPatchItem(recalled, deps) {
|
|
1397
|
+
const projected = projectClaimCentricRecallEntry(recalled, {
|
|
1398
|
+
slotPolicyConfig: deps.slotPolicyConfig
|
|
1399
|
+
});
|
|
1400
|
+
return {
|
|
1401
|
+
rank: 0,
|
|
1402
|
+
entry: recalled.entry,
|
|
1403
|
+
sourceKind: "artifact_recall",
|
|
1404
|
+
score: recalled.score,
|
|
1405
|
+
whySurfaced: projected.whySurfaced,
|
|
1406
|
+
memoryState: projected.memoryState,
|
|
1407
|
+
claimStatus: projected.claimStatus,
|
|
1408
|
+
freshnessLabel: projected.freshness.label,
|
|
1409
|
+
...formatProjectedProvenance2(projected.provenance) ? { provenanceSummary: formatProjectedProvenance2(projected.provenance) } : {}
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
function mergeDurableMemory(profileItems, directiveItems, coreItems, artifactRecallItems, maxDurableEntries) {
|
|
1413
|
+
const merged = [];
|
|
1414
|
+
const seenEntryIds = /* @__PURE__ */ new Set();
|
|
1415
|
+
const tryAdd = (item) => {
|
|
1416
|
+
if (merged.length >= maxDurableEntries || seenEntryIds.has(item.entry.id)) {
|
|
1417
|
+
return false;
|
|
1418
|
+
}
|
|
1419
|
+
seenEntryIds.add(item.entry.id);
|
|
1420
|
+
merged.push(item);
|
|
1421
|
+
return true;
|
|
1422
|
+
};
|
|
1423
|
+
const addFrom = (items, maxAdd = Number.POSITIVE_INFINITY) => {
|
|
1424
|
+
let added = 0;
|
|
1425
|
+
for (const item of items) {
|
|
1426
|
+
if (merged.length >= maxDurableEntries || added >= maxAdd) {
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
if (tryAdd(item)) {
|
|
1430
|
+
added += 1;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
};
|
|
1434
|
+
addFrom(profileItems);
|
|
1435
|
+
addFrom(directiveItems);
|
|
1436
|
+
if (merged.length >= maxDurableEntries) {
|
|
1437
|
+
return merged;
|
|
1438
|
+
}
|
|
1439
|
+
const uniqueArtifact = artifactRecallItems.find((item) => !seenEntryIds.has(item.entry.id));
|
|
1440
|
+
const remainingSlots = maxDurableEntries - merged.length;
|
|
1441
|
+
const coreLimit = uniqueArtifact ? Math.max(0, remainingSlots - 1) : remainingSlots;
|
|
1442
|
+
addFrom(coreItems, coreLimit);
|
|
1443
|
+
if (uniqueArtifact) {
|
|
1444
|
+
tryAdd(uniqueArtifact);
|
|
1445
|
+
}
|
|
1446
|
+
addFrom(coreItems);
|
|
1447
|
+
addFrom(artifactRecallItems);
|
|
1448
|
+
return merged;
|
|
1449
|
+
}
|
|
1450
|
+
function assignRanks2(items) {
|
|
1451
|
+
return items.map((item, index) => ({
|
|
1452
|
+
...item,
|
|
1453
|
+
rank: index + 1
|
|
1454
|
+
}));
|
|
1455
|
+
}
|
|
1456
|
+
function normalizePolicy2(policy) {
|
|
1457
|
+
const maxCoreEntries = normalizeCount2(policy?.maxCoreEntries, DEFAULT_MAX_CORE_ENTRIES);
|
|
1458
|
+
const maxArtifactRecallEntries = normalizeCount2(policy?.maxArtifactRecallEntries, DEFAULT_MAX_ARTIFACT_RECALL_ENTRIES);
|
|
1459
|
+
const maxDurableEntries = Math.max(maxCoreEntries, normalizeCount2(policy?.maxDurableEntries, DEFAULT_MAX_DURABLE_ENTRIES2));
|
|
1460
|
+
return {
|
|
1461
|
+
maxCoreEntries,
|
|
1462
|
+
enableArtifactRecall: policy?.enableArtifactRecall !== false,
|
|
1463
|
+
maxArtifactRecallEntries,
|
|
1464
|
+
maxDurableEntries,
|
|
1465
|
+
maxArtifactChars: normalizeCount2(policy?.maxArtifactChars, DEFAULT_MAX_ARTIFACT_CHARS),
|
|
1466
|
+
recallThreshold: normalizeThreshold2(policy?.recallThreshold),
|
|
1467
|
+
maxProfileSnapshotAgeHours: normalizeCount2(policy?.maxProfileSnapshotAgeHours, DEFAULT_MAX_PROFILE_SNAPSHOT_AGE_HOURS)
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
function filterCurrentEntries2(entries, nowMs) {
|
|
1471
|
+
return entries.filter((entry) => isWithinValidityWindow(entry.valid_from, entry.valid_to, nowMs));
|
|
1472
|
+
}
|
|
1473
|
+
function normalizeCount2(value, fallback) {
|
|
1474
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1475
|
+
return fallback;
|
|
1476
|
+
}
|
|
1477
|
+
return Math.max(0, Math.trunc(value));
|
|
1478
|
+
}
|
|
1479
|
+
function normalizeThreshold2(value) {
|
|
1480
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
1481
|
+
return 0;
|
|
1482
|
+
}
|
|
1483
|
+
return Math.min(1, Math.max(0, value));
|
|
1484
|
+
}
|
|
1485
|
+
function resolveMemoryState(entry, nowMs) {
|
|
1486
|
+
if (entry.superseded_by) {
|
|
1487
|
+
return "superseded";
|
|
1488
|
+
}
|
|
1489
|
+
if (!isCurrentlyValidMemory(entry, nowMs)) {
|
|
1490
|
+
return "historical";
|
|
1491
|
+
}
|
|
1492
|
+
return "current";
|
|
1493
|
+
}
|
|
1494
|
+
function resolveClaimStatus(entry) {
|
|
1495
|
+
return resolveKeyedDurableLifecycleStatus(entry);
|
|
1496
|
+
}
|
|
1497
|
+
function buildFreshnessLabel(entry) {
|
|
1498
|
+
const parts = [`created ${entry.created_at}`];
|
|
1499
|
+
const validFrom = normalizeOptionalString2(entry.valid_from);
|
|
1500
|
+
const validTo = normalizeOptionalString2(entry.valid_to);
|
|
1501
|
+
if (validFrom || validTo) {
|
|
1502
|
+
parts.push(`valid ${validFrom ?? "?"} -> ${validTo ?? "ongoing"}`);
|
|
1503
|
+
}
|
|
1504
|
+
return parts.join(" | ");
|
|
1505
|
+
}
|
|
1506
|
+
function buildProvenanceSummary(entry) {
|
|
1507
|
+
const parts = [
|
|
1508
|
+
entry.superseded_by ? `superseded_by=${entry.superseded_by}` : void 0,
|
|
1509
|
+
entry.supersession_kind ? `kind=${entry.supersession_kind}` : void 0,
|
|
1510
|
+
entry.supersession_reason ? `reason=${entry.supersession_reason}` : void 0,
|
|
1511
|
+
entry.claim_support_source_kind ? `support=${entry.claim_support_source_kind}` : void 0,
|
|
1512
|
+
entry.claim_support_mode ? `support_mode=${entry.claim_support_mode}` : void 0,
|
|
1513
|
+
entry.claim_support_observed_at ? `observed=${entry.claim_support_observed_at}` : void 0,
|
|
1514
|
+
entry.claim_support_locator ? `locator=${entry.claim_support_locator}` : void 0
|
|
1515
|
+
].filter((value) => value !== void 0);
|
|
1516
|
+
return parts.length > 0 ? parts.join(" | ") : void 0;
|
|
1517
|
+
}
|
|
1518
|
+
function formatProjectedProvenance2(provenance) {
|
|
1519
|
+
const parts = [
|
|
1520
|
+
provenance.supersededById ? `superseded_by=${provenance.supersededById}` : void 0,
|
|
1521
|
+
provenance.supersessionKind ? `kind=${provenance.supersessionKind}` : void 0,
|
|
1522
|
+
provenance.supersessionReason ? `reason=${provenance.supersessionReason}` : void 0,
|
|
1523
|
+
provenance.supportSourceKind ? `support=${provenance.supportSourceKind}` : void 0,
|
|
1524
|
+
provenance.supportMode ? `support_mode=${provenance.supportMode}` : void 0,
|
|
1525
|
+
provenance.supportObservedAt ? `observed=${provenance.supportObservedAt}` : void 0,
|
|
1526
|
+
provenance.supportLocator ? `locator=${provenance.supportLocator}` : void 0
|
|
1527
|
+
].filter((value) => value !== void 0);
|
|
1528
|
+
return parts.length > 0 ? parts.join(" | ") : void 0;
|
|
1529
|
+
}
|
|
1530
|
+
function normalizeOptionalString2(value) {
|
|
1531
|
+
const normalized = value?.trim();
|
|
1532
|
+
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
1533
|
+
}
|
|
1534
|
+
function formatErrorMessage2(error) {
|
|
1535
|
+
if (error instanceof Error) {
|
|
1536
|
+
return error.message;
|
|
1537
|
+
}
|
|
1538
|
+
return String(error);
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
// src/adapters/db/directives-repository.ts
|
|
1542
|
+
var MAX_DIRECTIVES = 50;
|
|
1543
|
+
async function listActiveAbstainDirectives(executor, now = /* @__PURE__ */ new Date()) {
|
|
1544
|
+
const nowIso = now.toISOString();
|
|
1545
|
+
const result = await executor.execute({
|
|
1546
|
+
sql: `
|
|
1547
|
+
SELECT
|
|
1548
|
+
${DURABLE_SELECT_COLUMNS}
|
|
1549
|
+
FROM durables
|
|
1550
|
+
WHERE ${buildActiveDurableClause()}
|
|
1551
|
+
AND (
|
|
1552
|
+
(type = 'directive' AND directive_polarity = 'abstain')
|
|
1553
|
+
OR (claim_key LIKE ? AND (directive_polarity IS NULL OR directive_polarity = 'abstain'))
|
|
1554
|
+
)
|
|
1555
|
+
AND ${buildValidAsOfClause()}
|
|
1556
|
+
ORDER BY created_at DESC
|
|
1557
|
+
LIMIT ?
|
|
1558
|
+
`,
|
|
1559
|
+
args: [`${MEMORY_DIRECTIVE_CLAIM_KEY_PREFIX}%`, nowIso, nowIso, MAX_DIRECTIVES]
|
|
1560
|
+
});
|
|
1561
|
+
return result.rows.map((row) => mapDurableRow(row));
|
|
1562
|
+
}
|
|
1563
|
+
async function listActiveSessionStartProactiveDirectives(executor, now = /* @__PURE__ */ new Date()) {
|
|
1564
|
+
const nowIso = now.toISOString();
|
|
1565
|
+
const result = await executor.execute({
|
|
1566
|
+
sql: `
|
|
1567
|
+
SELECT
|
|
1568
|
+
${DURABLE_SELECT_COLUMNS}
|
|
1569
|
+
FROM durables
|
|
1570
|
+
WHERE ${buildActiveDurableClause()}
|
|
1571
|
+
AND type = 'directive'
|
|
1572
|
+
AND directive_polarity = 'proactive'
|
|
1573
|
+
AND directive_trigger IN ('session_start', 'always')
|
|
1574
|
+
AND ${buildValidAsOfClause()}
|
|
1575
|
+
ORDER BY importance DESC, created_at DESC
|
|
1576
|
+
LIMIT ?
|
|
1577
|
+
`,
|
|
1578
|
+
args: [nowIso, nowIso, MAX_DIRECTIVES]
|
|
1579
|
+
});
|
|
1580
|
+
return result.rows.map((row) => mapDurableRow(row));
|
|
1581
|
+
}
|
|
1582
|
+
async function listActiveTopicProactiveDirectives(executor, now = /* @__PURE__ */ new Date()) {
|
|
1583
|
+
const nowIso = now.toISOString();
|
|
1584
|
+
const result = await executor.execute({
|
|
1585
|
+
sql: `
|
|
1586
|
+
SELECT
|
|
1587
|
+
${DURABLE_SELECT_COLUMNS}
|
|
1588
|
+
FROM durables
|
|
1589
|
+
WHERE ${buildActiveDurableClause()}
|
|
1590
|
+
AND type = 'directive'
|
|
1591
|
+
AND directive_polarity = 'proactive'
|
|
1592
|
+
AND directive_trigger LIKE 'topic:%'
|
|
1593
|
+
AND ${buildValidAsOfClause()}
|
|
1594
|
+
ORDER BY importance DESC, created_at DESC
|
|
1595
|
+
LIMIT ?
|
|
1596
|
+
`,
|
|
1597
|
+
args: [nowIso, nowIso, MAX_DIRECTIVES]
|
|
1598
|
+
});
|
|
1599
|
+
return result.rows.map((row) => mapDurableRow(row));
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
// src/adapters/db/session-start-repository.ts
|
|
1603
|
+
function createSessionStartRepository(executor) {
|
|
1604
|
+
return {
|
|
1605
|
+
listCoreEntries: async (limit, now) => listCoreEntries(executor, limit, now),
|
|
1606
|
+
getActiveProfileSnapshot: async (maxAgeMs, now) => getActiveProfileSnapshot(executor, maxAgeMs, now),
|
|
1607
|
+
listEntriesByIds: async (ids) => getDurables(executor, ids)
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
async function getActiveProfileSnapshot(executor, maxAgeMs, now = /* @__PURE__ */ new Date()) {
|
|
1611
|
+
if (!Number.isFinite(maxAgeMs) || maxAgeMs <= 0) {
|
|
1612
|
+
return null;
|
|
1613
|
+
}
|
|
1614
|
+
const minCreatedAt = new Date(now.getTime() - maxAgeMs).toISOString();
|
|
1615
|
+
const result = await executor.execute({
|
|
1616
|
+
sql: `
|
|
1617
|
+
SELECT
|
|
1618
|
+
p.id,
|
|
1619
|
+
p.durable_ids,
|
|
1620
|
+
p.directive_ids,
|
|
1621
|
+
p.as_of,
|
|
1622
|
+
p.run_id,
|
|
1623
|
+
p.created_at
|
|
1624
|
+
FROM dream_state AS s
|
|
1625
|
+
JOIN profile_snapshots AS p ON p.id = s.active_profile_snapshot_id
|
|
1626
|
+
WHERE s.id = 'default'
|
|
1627
|
+
AND datetime(p.created_at) >= datetime(?)
|
|
1628
|
+
LIMIT 1
|
|
1629
|
+
`,
|
|
1630
|
+
args: [minCreatedAt]
|
|
1631
|
+
});
|
|
1632
|
+
const row = result.rows[0];
|
|
1633
|
+
if (!row) {
|
|
1634
|
+
return null;
|
|
1635
|
+
}
|
|
1636
|
+
return {
|
|
1637
|
+
id: readRequiredString(row, "id"),
|
|
1638
|
+
durableIds: parseJsonStringArray(readOptionalString(row, "durable_ids")),
|
|
1639
|
+
directiveIds: parseJsonStringArray(readOptionalString(row, "directive_ids")),
|
|
1640
|
+
asOf: readRequiredString(row, "as_of"),
|
|
1641
|
+
runId: readOptionalString(row, "run_id") ?? null,
|
|
1642
|
+
createdAt: readRequiredString(row, "created_at")
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
async function listCoreEntries(executor, limit, now = /* @__PURE__ */ new Date()) {
|
|
1646
|
+
if (limit <= 0) {
|
|
1647
|
+
return [];
|
|
1648
|
+
}
|
|
1649
|
+
const nowIso = now.toISOString();
|
|
1650
|
+
const result = await executor.execute({
|
|
1651
|
+
sql: `
|
|
1652
|
+
SELECT
|
|
1653
|
+
${DURABLE_SELECT_COLUMNS}
|
|
1654
|
+
FROM durables
|
|
1655
|
+
WHERE ${buildActiveDurableClause()}
|
|
1656
|
+
AND expiry = 'core'
|
|
1657
|
+
AND ${buildValidAsOfClause()}
|
|
1658
|
+
ORDER BY importance DESC, created_at DESC
|
|
1659
|
+
LIMIT ?
|
|
1660
|
+
`,
|
|
1661
|
+
args: [nowIso, nowIso, limit]
|
|
1662
|
+
});
|
|
1663
|
+
return result.rows.map((row) => mapDurableRow(row));
|
|
1664
|
+
}
|
|
1665
|
+
|
|
866
1666
|
export {
|
|
867
1667
|
runBeforeTurn,
|
|
1668
|
+
listActiveAbstainDirectives,
|
|
1669
|
+
listActiveSessionStartProactiveDirectives,
|
|
1670
|
+
listActiveTopicProactiveDirectives,
|
|
1671
|
+
createSessionStartRepository,
|
|
868
1672
|
formatInjectionEntryHeader,
|
|
869
1673
|
formatInjectionEntryBodyLines,
|
|
870
1674
|
wrapAgenrMemoryContext,
|
|
871
1675
|
containsAgenrMemoryContext,
|
|
872
1676
|
stripAgenrMemoryContext,
|
|
873
|
-
formatAgenrBeforeTurnRecall
|
|
1677
|
+
formatAgenrBeforeTurnRecall,
|
|
1678
|
+
runSessionStart
|
|
874
1679
|
};
|