@agenr/agenr-plugin 3.0.0 → 3.1.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.
@@ -21,8 +21,9 @@ import {
21
21
  readNumber,
22
22
  readOptionalString,
23
23
  readRequiredString,
24
+ truncate,
24
25
  validateTemporalValidityRange
25
- } from "./chunk-ELR2HSVC.js";
26
+ } from "./chunk-NNO2V4GH.js";
26
27
  import {
27
28
  compactClaimKey,
28
29
  describeClaimKeyNormalizationFailure,
@@ -36,6 +37,166 @@ import {
36
37
  validateExtractedClaimKey
37
38
  } from "./chunk-5LADPJ4C.js";
38
39
 
40
+ // src/adapters/shared/errors.ts
41
+ function formatErrorMessage(error) {
42
+ return error instanceof Error ? error.message : String(error);
43
+ }
44
+
45
+ // src/adapters/shared/resolve-target.ts
46
+ function buildEntryMemoryResolverPorts(services) {
47
+ return {
48
+ getEntryById: async (entryId) => await services.entries.getEntry(entryId) ?? (await services.memory.getEntryTrace(entryId))?.entry ?? null,
49
+ findEntryBySubject: async (subject) => services.memory.findEntryBySubject(subject),
50
+ findMostRecentEntry: async () => services.memory.findMostRecentEntry()
51
+ };
52
+ }
53
+ async function resolveTargetEntry(ports, params, options = {}) {
54
+ const id = readOptionalStringParam(params, "id");
55
+ const subject = readOptionalStringParam(params, "subject");
56
+ const last = options.allowLast ? readBooleanParam(params, "last") : void 0;
57
+ const selectorCount = (id ? 1 : 0) + (subject ? 1 : 0) + (last === true ? 1 : 0);
58
+ const selectorDescription = options.allowLast ? "id, subject, or last" : "id or subject";
59
+ if (selectorCount !== 1) {
60
+ throw new Error(`Provide exactly one target selector: ${selectorDescription}.`);
61
+ }
62
+ if (last) {
63
+ const entry2 = await ports.findMostRecentEntry();
64
+ if (!entry2) {
65
+ throw new Error("No agenr entries exist yet.");
66
+ }
67
+ return entry2;
68
+ }
69
+ if (id) {
70
+ const entry2 = await ports.getEntryById(id);
71
+ if (!entry2) {
72
+ throw new Error(`No agenr entry found for id ${id}.`);
73
+ }
74
+ return entry2;
75
+ }
76
+ const entry = await ports.findEntryBySubject(subject ?? "");
77
+ if (!entry) {
78
+ throw new Error(`No agenr entry found for subject "${subject}".`);
79
+ }
80
+ return entry;
81
+ }
82
+ function readBooleanParam(params, key) {
83
+ const value = params[key];
84
+ if (value === void 0) {
85
+ return void 0;
86
+ }
87
+ if (typeof value === "boolean") {
88
+ return value;
89
+ }
90
+ throw new Error(`${key} must be a boolean.`);
91
+ }
92
+ function readOptionalStringParam(params, key) {
93
+ const value = params[key];
94
+ if (value === void 0 || value === null) {
95
+ return void 0;
96
+ }
97
+ if (typeof value !== "string") {
98
+ throw new Error(`${key} must be a string.`);
99
+ }
100
+ const normalized = value.trim();
101
+ return normalized.length > 0 ? normalized : void 0;
102
+ }
103
+
104
+ // src/adapters/shared/entry-tools.ts
105
+ var ENTRY_TYPE_DESCRIPTION = "Knowledge type to store. Use fact for durable truth about a person, system, place, or how something works. Use decision for a standing rule, constraint, policy, or chosen approach future sessions should follow - not a progress update or completed action. Use preference for what someone likes, wants, values, or wants avoided. Use lesson for a non-obvious takeaway learned from experience that should change future behavior. Use milestone for a rare one-time event with durable future significance - not ordinary execution progress. Use relationship for a meaningful durable connection between people, groups, or systems.";
106
+ var EXPIRY_DESCRIPTION = "Lifetime bucket: core (always injected at session start, use sparingly), permanent (durable and recalled on demand), or temporary (short-horizon).";
107
+ var UPDATE_EXPIRY_DESCRIPTION = `${EXPIRY_DESCRIPTION} Accepted values: ${EXPIRY_LEVELS.join(", ")}.`;
108
+ var RECALL_MODES = ["auto", "entries", "episodes", "procedures"];
109
+ function asRecord(value) {
110
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
111
+ return value;
112
+ }
113
+ throw new Error("Tool parameters must be an object.");
114
+ }
115
+ function parseExpiry(value) {
116
+ if (value === void 0) {
117
+ return void 0;
118
+ }
119
+ if (EXPIRY_LEVELS.includes(value)) {
120
+ return value;
121
+ }
122
+ throw new Error(`Unsupported expiry "${value}".`);
123
+ }
124
+ function parseEntryTypes(values) {
125
+ return normalizeStringArray(values).map((value) => parseEntryType(value));
126
+ }
127
+ function parseEntryType(value) {
128
+ if (ENTRY_TYPES.includes(value)) {
129
+ return value;
130
+ }
131
+ throw new Error(`Unsupported entry type "${value}".`);
132
+ }
133
+ function parseRecallMode(value) {
134
+ if (value === void 0) {
135
+ return void 0;
136
+ }
137
+ if (RECALL_MODES.includes(value)) {
138
+ return value;
139
+ }
140
+ throw new Error(`Unsupported recall mode "${value}".`);
141
+ }
142
+ function normalizeStringArray(values) {
143
+ if (!values) {
144
+ return [];
145
+ }
146
+ return Array.from(new Set(values.map((value) => value.trim()).filter((value) => value.length > 0)));
147
+ }
148
+ function formatTargetSelector(id, subject, last) {
149
+ if (last === true) {
150
+ return "last";
151
+ }
152
+ if (id) {
153
+ return `id:${JSON.stringify(id)}`;
154
+ }
155
+ if (subject) {
156
+ return `subject:${JSON.stringify(subject)}`;
157
+ }
158
+ return "unknown";
159
+ }
160
+ function formatTargetSelectorFromParams(params, options = {}) {
161
+ const id = readTrimmedOptionalStringParam(params, "id");
162
+ const subject = readTrimmedOptionalStringParam(params, "subject");
163
+ const last = options.allowLast ? readBooleanParam(params, "last") : void 0;
164
+ const maxValueChars = options.maxValueChars;
165
+ return formatTargetSelector(
166
+ id && maxValueChars !== void 0 ? truncate(id, maxValueChars) : id,
167
+ subject && maxValueChars !== void 0 ? truncate(subject, maxValueChars) : subject,
168
+ last
169
+ );
170
+ }
171
+ function readTrimmedOptionalStringParam(params, key) {
172
+ const value = params[key];
173
+ if (value === void 0 || value === null) {
174
+ return void 0;
175
+ }
176
+ if (typeof value !== "string") {
177
+ throw new Error(`${key} must be a string.`);
178
+ }
179
+ const normalized = value.trim();
180
+ return normalized.length > 0 ? normalized : void 0;
181
+ }
182
+ function sanitizeUpdateToolParams(params) {
183
+ return {
184
+ ...params.id ? { id: params.id } : {},
185
+ ...params.subject ? { subject: params.subject } : {},
186
+ ...params.importance !== void 0 ? { importance: params.importance } : {},
187
+ ...params.expiry !== void 0 ? { expiry: params.expiry } : {},
188
+ ...params.claimKey !== void 0 ? { hasClaimKey: true } : {},
189
+ ...params.validFrom !== void 0 ? { hasValidFrom: true } : {},
190
+ ...params.validTo !== void 0 ? { hasValidTo: true } : {}
191
+ };
192
+ }
193
+ function sanitizeFetchToolParams(params) {
194
+ return {
195
+ ...params.id ? { id: params.id } : {},
196
+ ...params.subject ? { subject: params.subject } : {}
197
+ };
198
+ }
199
+
39
200
  // src/app/episode-ingest/activity-threshold.ts
40
201
  function resolveEpisodeActivityEligibility(materialTurns, startedAt, endedAt, threshold) {
41
202
  const durationMs = resolveTranscriptDurationMs(startedAt, endedAt);
@@ -1172,8 +1333,8 @@ function detectClaimKeyEntityFamilyCandidates(entries) {
1172
1333
  return support?.autoSafe === true;
1173
1334
  });
1174
1335
  const componentProfiles = component.map((entity) => profiles.get(entity)).filter((profile) => Boolean(profile));
1175
- const entryIds = normalizeStringArray(componentProfiles.flatMap((profile) => [...profile.entryIds]));
1176
- const claimKeys = normalizeStringArray(componentProfiles.flatMap((profile) => [...profile.claimKeys]));
1336
+ const entryIds = normalizeStringArray2(componentProfiles.flatMap((profile) => [...profile.entryIds]));
1337
+ const claimKeys = normalizeStringArray2(componentProfiles.flatMap((profile) => [...profile.claimKeys]));
1177
1338
  const confidence = componentSupport.length > 0 ? Math.max(...componentSupport.map((support) => support.confidence)) : 0.75;
1178
1339
  families.push({
1179
1340
  entityPrefixes: [...component].sort((left, right) => left.localeCompare(right)),
@@ -1372,7 +1533,7 @@ function buildPairSupport(profiles) {
1372
1533
  }
1373
1534
  }
1374
1535
  for (const entities of attributeBuckets.values()) {
1375
- const normalizedEntities = normalizeStringArray(entities);
1536
+ const normalizedEntities = normalizeStringArray2(entities);
1376
1537
  if (normalizedEntities.length < 2 || normalizedEntities.length > MAX_ATTRIBUTE_BUCKET_SIZE) {
1377
1538
  continue;
1378
1539
  }
@@ -1463,7 +1624,7 @@ function evaluateEntityFamilyPairSupport(leftProfile, rightProfile) {
1463
1624
  );
1464
1625
  return {
1465
1626
  entityPrefixes: [leftProfile.entityPrefix, rightProfile.entityPrefix],
1466
- supportingEntryIds: normalizeStringArray([...leftProfile.entryIds, ...rightProfile.entryIds]),
1627
+ supportingEntryIds: normalizeStringArray2([...leftProfile.entryIds, ...rightProfile.entryIds]),
1467
1628
  sharedAttributes,
1468
1629
  confidence,
1469
1630
  autoSafe: lexicalRelation.autoSafe && (sharedAttributes.length >= 2 || sharedAttributes.length === 1 && groundingAnchorCount >= 1 && groundingScore >= 2),
@@ -1569,7 +1730,7 @@ function selectCanonicalEntityPrefix(entityPrefixes, pairSupport, profiles) {
1569
1730
  reasons.push(`lexical alias evidence prefers "${entityPrefix}"`);
1570
1731
  }
1571
1732
  scoreByEntity.set(entityPrefix, score);
1572
- reasonsByEntity.set(entityPrefix, normalizeStringArray(reasons));
1733
+ reasonsByEntity.set(entityPrefix, normalizeStringArray2(reasons));
1573
1734
  }
1574
1735
  const ranked = [...scoreByEntity.entries()].sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0]));
1575
1736
  const [bestCandidate, secondCandidate] = ranked;
@@ -1813,7 +1974,7 @@ function intersectSets(left, right) {
1813
1974
  }
1814
1975
  return intersection.sort((first, second) => first.localeCompare(second));
1815
1976
  }
1816
- function normalizeStringArray(values) {
1977
+ function normalizeStringArray2(values) {
1817
1978
  return Array.from(new Set(values.map((value) => value.trim()).filter((value) => value.length > 0)));
1818
1979
  }
1819
1980
  function buildPairKey(leftEntityPrefix, rightEntityPrefix) {
@@ -2078,7 +2239,7 @@ function evaluateClaimKeySupport(entry, targetClaimKey, trustedHints) {
2078
2239
  familyReuseCount: familyReuseEntries.length,
2079
2240
  groundedFamilyReuseCount: groundedFamilyReuseEntries.length,
2080
2241
  relaxedStableSlotFamilyGate: promotionSupport.relaxedStableSlotFamilyGate,
2081
- supportingEntryIds: normalizeStringArray2([
2242
+ supportingEntryIds: normalizeStringArray3([
2082
2243
  ...groundedExactReuseEntries.map((candidate) => candidate.id),
2083
2244
  ...groundedFamilyReuseEntries.map((candidate) => candidate.id),
2084
2245
  ...familyReuseEntries.filter((candidate) => candidate.id.startsWith("example:")).map((candidate) => candidate.id)
@@ -2134,18 +2295,18 @@ function evaluateClaimKeyCompactness(claimKey, prior) {
2134
2295
  };
2135
2296
  }
2136
2297
  function normalizeGroundingTags(tags) {
2137
- return normalizeStringArray2((tags ?? []).map((tag) => normalizeClaimKeySegment(tag)).filter((tag) => tag.length > 0));
2298
+ return normalizeStringArray3((tags ?? []).map((tag) => normalizeClaimKeySegment(tag)).filter((tag) => tag.length > 0));
2138
2299
  }
2139
2300
  function tokenizeGroundingText(value) {
2140
2301
  if (!value) {
2141
2302
  return [];
2142
2303
  }
2143
- return normalizeStringArray2(
2304
+ return normalizeStringArray3(
2144
2305
  value.split(/[^a-zA-Z0-9]+/u).map((token) => normalizeClaimKeySegment(token)).filter((token) => token.length > 2 && !GROUNDING_STOP_TOKENS.has(token))
2145
2306
  );
2146
2307
  }
2147
2308
  function buildEntryLocalLexicalTokens(entry) {
2148
- return normalizeStringArray2([
2309
+ return normalizeStringArray3([
2149
2310
  ...tokenizeGroundingText(entry.subject),
2150
2311
  ...tokenizeGroundingText(entry.content),
2151
2312
  ...tokenizeGroundingText(entry.source_context),
@@ -2253,7 +2414,7 @@ function intersects(left, right) {
2253
2414
  }
2254
2415
  return false;
2255
2416
  }
2256
- function normalizeStringArray2(values) {
2417
+ function normalizeStringArray3(values) {
2257
2418
  const seen = /* @__PURE__ */ new Set();
2258
2419
  const normalized = [];
2259
2420
  for (const value of values) {
@@ -3891,6 +4052,24 @@ export {
3891
4052
  computeNormContentHash,
3892
4053
  validateEntriesWithIndexes,
3893
4054
  storeEntriesDetailed,
4055
+ formatErrorMessage,
4056
+ buildEntryMemoryResolverPorts,
4057
+ resolveTargetEntry,
4058
+ readBooleanParam,
4059
+ ENTRY_TYPE_DESCRIPTION,
4060
+ EXPIRY_DESCRIPTION,
4061
+ UPDATE_EXPIRY_DESCRIPTION,
4062
+ RECALL_MODES,
4063
+ asRecord,
4064
+ parseExpiry,
4065
+ parseEntryTypes,
4066
+ parseEntryType,
4067
+ parseRecallMode,
4068
+ normalizeStringArray,
4069
+ formatTargetSelector,
4070
+ formatTargetSelectorFromParams,
4071
+ sanitizeUpdateToolParams,
4072
+ sanitizeFetchToolParams,
3894
4073
  backfillEpisodeEmbeddings,
3895
4074
  prepareEpisodeIngest,
3896
4075
  ingestEpisodeTranscript,
@@ -1,3 +1,7 @@
1
+ import {
2
+ formatTargetSelectorFromParams
3
+ } from "./chunk-EEEL53X4.js";
4
+
1
5
  // src/adapters/openclaw/transcript/parser.ts
2
6
  import { createHash } from "crypto";
3
7
  import * as fs2 from "fs/promises";
@@ -75,6 +79,7 @@ function parseJsonlLines(raw, onRecord) {
75
79
  }
76
80
 
77
81
  // src/adapters/openclaw/transcript/tool-summarization.ts
82
+ var AGENR_FETCH_TARGET_MAX_CHARS = 80;
78
83
  var DEFAULT_TOOL_RESULT_DROP_NAMES = ["read", "web_fetch", "browser", "screenshot", "snapshot", "canvas", "tts"];
79
84
  var DEFAULT_TOOL_RESULT_KEEP_NAMES = ["web_search", "memory_search", "memory_get", "image"];
80
85
  var DEFAULT_TOOL_RESULT_DROP_NAME_SET = new Set(DEFAULT_TOOL_RESULT_DROP_NAMES);
@@ -147,6 +152,9 @@ function toolIdentifier(toolName, args) {
147
152
  const query = getString(args.query) ?? "(no query)";
148
153
  return `"${truncateInline(query, 80)}"`;
149
154
  }
155
+ if (normalizedToolName === "agenr_fetch") {
156
+ return formatTargetSelectorFromParams(args, { maxValueChars: AGENR_FETCH_TARGET_MAX_CHARS });
157
+ }
150
158
  if (normalizedToolName === "message") {
151
159
  const action = getString(args.action) ?? "(unknown action)";
152
160
  const target = getString(args.target) ?? getString(args.to) ?? "(unknown target)";
@@ -247,6 +255,9 @@ function summarizeToolCall(call, options) {
247
255
  const query = getString(args.query) ?? "(no query)";
248
256
  return `[recalled from brain: "${truncateInline(query, 100)}"]`;
249
257
  }
258
+ if (normalizedToolName === "agenr_fetch") {
259
+ return `[fetched from brain: ${formatTargetSelectorFromParams(args, { maxValueChars: AGENR_FETCH_TARGET_MAX_CHARS })}]`;
260
+ }
250
261
  if (normalizedToolName === "sessions_spawn") {
251
262
  const label = getString(args.label);
252
263
  const mode = getString(args.mode) ?? "run";
@@ -550,7 +561,7 @@ async function applyMessageTimestampFallbacks(filePath, messages, options) {
550
561
  // src/adapters/openclaw/transcript/parser.ts
551
562
  var SKIPPED_RECORD_TYPES = /* @__PURE__ */ new Set(["compaction", "custom", "thinking_level_change"]);
552
563
  var TOOL_RESULT_POLICY = {
553
- dropToolNames: /* @__PURE__ */ new Set([...DEFAULT_TOOL_RESULT_DROP_NAMES, "agenr_recall", "image"]),
564
+ dropToolNames: /* @__PURE__ */ new Set([...DEFAULT_TOOL_RESULT_DROP_NAMES, "agenr_recall", "agenr_fetch", "image"]),
554
565
  keepToolNames: new Set(DEFAULT_TOOL_RESULT_KEEP_NAMES.filter((name) => name !== "image"))
555
566
  };
556
567
  var RAW_TEXT_BLOCK_TYPES = /* @__PURE__ */ new Set(["input_text", "output_text", "text"]);
@@ -5399,6 +5399,236 @@ async function rollbackTransaction(transaction) {
5399
5399
  await transaction.rollback();
5400
5400
  }
5401
5401
 
5402
+ // src/adapters/shared/memory-tool-format.ts
5403
+ var DEFAULT_RECALL_LIMIT = 10;
5404
+ var RESULT_SUBJECT_LOG_LIMIT = 5;
5405
+ var ENTRY_PREVIEW_MAX_CHARS = 220;
5406
+ var ENTRY_FETCH_MAX_CONTENT_CHARS = 32768;
5407
+ function buildEntryRecallPreview(content) {
5408
+ const trimmed = content.trim();
5409
+ const previewTruncated = trimmed.length > ENTRY_PREVIEW_MAX_CHARS;
5410
+ return {
5411
+ contentPreview: previewTruncated ? truncate(trimmed, ENTRY_PREVIEW_MAX_CHARS) : trimmed,
5412
+ contentChars: trimmed.length,
5413
+ previewTruncated
5414
+ };
5415
+ }
5416
+ function recallResultHasTruncatedEntryPreviews(result) {
5417
+ if (result.entries.some((entry) => buildEntryRecallPreview(entry.entry.content).previewTruncated)) {
5418
+ return true;
5419
+ }
5420
+ return result.entryFamilies.some((family) => family.entries.some((entry) => buildEntryRecallPreview(entry.recall.entry.content).previewTruncated));
5421
+ }
5422
+ function assertEntryFetchableContentLength(content) {
5423
+ const contentChars = content.trim().length;
5424
+ if (contentChars > ENTRY_FETCH_MAX_CONTENT_CHARS) {
5425
+ throw new Error(
5426
+ `Entry content is ${contentChars} characters, which exceeds the agenr_fetch limit of ${ENTRY_FETCH_MAX_CONTENT_CHARS}. Use agenr_trace or the CLI for full inspection.`
5427
+ );
5428
+ }
5429
+ }
5430
+ function truncate(value, maxChars) {
5431
+ if (value.length <= maxChars) {
5432
+ return value;
5433
+ }
5434
+ return `${value.slice(0, maxChars - 3).trimEnd()}...`;
5435
+ }
5436
+ function sanitizeStoreToolParams(params) {
5437
+ return {
5438
+ type: params.type,
5439
+ subject: params.subject,
5440
+ ...params.importance !== void 0 ? { importance: params.importance } : {},
5441
+ ...params.expiry !== void 0 ? { expiry: params.expiry } : {},
5442
+ ...params.tags.length > 0 ? { tags: params.tags } : {},
5443
+ contentLength: params.content.length,
5444
+ ...params.sourceContext !== void 0 ? { sourceContextLength: params.sourceContext.length } : {},
5445
+ ...params.supersedes !== void 0 ? { hasSupersedes: true } : {},
5446
+ ...params.claimKey !== void 0 ? { hasClaimKey: true } : {},
5447
+ ...params.validFrom !== void 0 ? { hasValidFrom: true } : {},
5448
+ ...params.validTo !== void 0 ? { hasValidTo: true } : {}
5449
+ };
5450
+ }
5451
+ function formatRecallToolSummary(params) {
5452
+ const parts = [`query=${JSON.stringify(truncate(params.query, 80))}`];
5453
+ if (params.mode) {
5454
+ parts.push(`mode=${params.mode}`);
5455
+ }
5456
+ if (params.limit !== void 0 && params.limit !== DEFAULT_RECALL_LIMIT) {
5457
+ parts.push(`limit=${params.limit}`);
5458
+ }
5459
+ if (params.types.length > 0) {
5460
+ parts.push(`types=${JSON.stringify(params.types)}`);
5461
+ }
5462
+ if (params.tags.length > 0) {
5463
+ parts.push(`tags=${JSON.stringify(params.tags)}`);
5464
+ }
5465
+ if (params.asOf) {
5466
+ parts.push(`as_of=${JSON.stringify(params.asOf)}`);
5467
+ }
5468
+ if (params.budget !== void 0) {
5469
+ parts.push(`budget=${params.budget}`);
5470
+ }
5471
+ return parts.join(" ");
5472
+ }
5473
+ function sanitizeRecallToolParams(params) {
5474
+ return {
5475
+ query: params.query,
5476
+ ...params.mode ? { mode: params.mode } : {},
5477
+ ...params.limit !== void 0 ? { limit: params.limit } : {},
5478
+ ...params.threshold !== void 0 ? { threshold: params.threshold } : {},
5479
+ ...params.types.length > 0 ? { types: params.types } : {},
5480
+ ...params.tags.length > 0 ? { tags: params.tags } : {},
5481
+ ...params.asOf ? { asOf: params.asOf } : {},
5482
+ ...params.budget !== void 0 ? { budget: params.budget } : {}
5483
+ };
5484
+ }
5485
+ function formatUnifiedRecallLogSummary(result) {
5486
+ const procedureCount = result.procedureCandidates.length;
5487
+ const procedureSummary = result.procedure ? ` [procedure: ${JSON.stringify(truncate(result.procedure.title, 80))}]` : "";
5488
+ const entrySubjects = result.entries.map((entry) => entry.entry.subject.trim()).filter((subject) => subject.length > 0);
5489
+ const displayed = entrySubjects.slice(0, RESULT_SUBJECT_LOG_LIMIT).map((subject) => JSON.stringify(truncate(subject, 80)));
5490
+ const remaining = entrySubjects.length - RESULT_SUBJECT_LOG_LIMIT;
5491
+ const suffix = displayed.length === 0 ? "" : ` [entry subjects: ${displayed.join(", ")}${remaining > 0 ? `, ... and ${remaining} more` : ""}]`;
5492
+ const entryEpisodeSummary = `${result.episodes.length} episode${result.episodes.length === 1 ? "" : "s"}, ${result.entries.length} entr${result.entries.length === 1 ? "y" : "ies"}`;
5493
+ if (procedureCount === 0 && !result.procedure) {
5494
+ return `${entryEpisodeSummary}${suffix}`;
5495
+ }
5496
+ return `${procedureCount} procedure candidate${procedureCount === 1 ? "" : "s"}, ${entryEpisodeSummary}${procedureSummary}${suffix}`;
5497
+ }
5498
+ function buildRecallToolDetails(result, extraDetails = {}) {
5499
+ return {
5500
+ status: "ok",
5501
+ count: result.count,
5502
+ ...extraDetails,
5503
+ routing: {
5504
+ requested: result.routing.requested,
5505
+ detectedIntent: result.routing.detectedIntent,
5506
+ queried: result.routing.queried,
5507
+ reason: result.routing.reason
5508
+ },
5509
+ ...result.asOf ? { asOf: result.asOf } : {},
5510
+ ...result.timeWindow ? { timeWindow: result.timeWindow } : {},
5511
+ ...result.procedure ? {
5512
+ procedure: {
5513
+ id: result.procedure.id,
5514
+ procedureKey: result.procedure.procedure_key,
5515
+ title: result.procedure.title,
5516
+ goal: result.procedure.goal
5517
+ }
5518
+ } : {},
5519
+ procedures: result.procedureCandidates.map((candidate) => ({
5520
+ id: candidate.procedure.id,
5521
+ procedureKey: candidate.procedure.procedure_key,
5522
+ title: candidate.procedure.title,
5523
+ goal: candidate.procedure.goal,
5524
+ score: candidate.score,
5525
+ lexicalScore: candidate.scores.lexical,
5526
+ vectorScore: candidate.scores.vector
5527
+ })),
5528
+ procedureNotices: result.procedureNotices,
5529
+ episodes: result.episodes.map((episode) => ({
5530
+ id: episode.episode.id,
5531
+ source: episode.episode.source,
5532
+ sourceId: episode.episode.sourceId,
5533
+ startedAt: episode.episode.startedAt,
5534
+ endedAt: episode.episode.endedAt,
5535
+ tags: episode.episode.tags,
5536
+ score: episode.score,
5537
+ activityLevel: episode.episode.activityLevel,
5538
+ summary: episode.episode.summary,
5539
+ whyMatched: describeEpisodeWhyMatched(episode.scores.semantic, episode.scores.temporal)
5540
+ })),
5541
+ entries: result.entries.map((entry) => {
5542
+ const preview = buildEntryRecallPreview(entry.entry.content);
5543
+ return {
5544
+ id: entry.entry.id,
5545
+ subject: entry.entry.subject,
5546
+ type: entry.entry.type,
5547
+ expiry: entry.entry.expiry,
5548
+ importance: entry.entry.importance,
5549
+ score: entry.score,
5550
+ tags: entry.entry.tags,
5551
+ contentPreview: preview.contentPreview,
5552
+ contentChars: preview.contentChars,
5553
+ previewTruncated: preview.previewTruncated
5554
+ };
5555
+ }),
5556
+ projectedEntries: result.projectedEntries.map((entry) => {
5557
+ const preview = buildEntryRecallPreview(entry.recall.entry.content);
5558
+ return {
5559
+ id: entry.entryId,
5560
+ familyKey: entry.familyKey,
5561
+ claimKey: entry.claimKey,
5562
+ slotPolicy: entry.slotPolicy,
5563
+ memoryState: entry.memoryState,
5564
+ claimStatus: entry.claimStatus,
5565
+ freshness: entry.freshness,
5566
+ provenance: entry.provenance,
5567
+ whySurfaced: entry.whySurfaced,
5568
+ contentPreview: preview.contentPreview,
5569
+ contentChars: preview.contentChars,
5570
+ previewTruncated: preview.previewTruncated
5571
+ };
5572
+ }),
5573
+ entryFamilies: result.entryFamilies.map((family) => ({
5574
+ familyKey: family.familyKey,
5575
+ claimKey: family.claimKey,
5576
+ slotPolicy: family.slotPolicy,
5577
+ subject: family.subject,
5578
+ primaryEntryId: family.primary.entryId,
5579
+ entries: family.entries.map((entry) => ({
5580
+ id: entry.entryId,
5581
+ memoryState: entry.memoryState,
5582
+ claimStatus: entry.claimStatus
5583
+ }))
5584
+ })),
5585
+ claimTransitions: result.claimTransitions,
5586
+ notices: result.notices
5587
+ };
5588
+ }
5589
+ function formatFetchedEntryText(entry) {
5590
+ const metadata = [
5591
+ `Entry ${entry.id}`,
5592
+ `subject=${entry.subject}`,
5593
+ `type=${entry.type} importance=${entry.importance} expiry=${entry.expiry} created=${entry.created_at}`,
5594
+ entry.claim_key ? `claim_key=${entry.claim_key}` : void 0,
5595
+ entry.tags.length > 0 ? `tags=${entry.tags.join(", ")}` : void 0,
5596
+ entry.valid_from ? `valid_from=${entry.valid_from}` : void 0,
5597
+ entry.valid_to ? `valid_to=${entry.valid_to}` : void 0,
5598
+ entry.source_context ? `source_context=${entry.source_context}` : void 0
5599
+ ].filter((value) => value !== void 0);
5600
+ return [...metadata, "", entry.content.trim()].join("\n");
5601
+ }
5602
+ function buildFetchToolDetails(entry, extraDetails = {}) {
5603
+ return {
5604
+ status: "ok",
5605
+ entryId: entry.id,
5606
+ subject: entry.subject,
5607
+ type: entry.type,
5608
+ importance: entry.importance,
5609
+ expiry: entry.expiry,
5610
+ tags: entry.tags,
5611
+ ...entry.claim_key ? { claimKey: entry.claim_key } : {},
5612
+ ...entry.valid_from ? { validFrom: entry.valid_from } : {},
5613
+ ...entry.valid_to ? { validTo: entry.valid_to } : {},
5614
+ ...entry.source_context ? { sourceContext: entry.source_context } : {},
5615
+ content: entry.content,
5616
+ ...extraDetails
5617
+ };
5618
+ }
5619
+ function describeEpisodeWhyMatched(semanticScore, temporalScore) {
5620
+ if (semanticScore > 0 && temporalScore > 0) {
5621
+ return "Semantic match within the resolved time window.";
5622
+ }
5623
+ if (semanticScore > 0) {
5624
+ return "Semantic match to the episode summary.";
5625
+ }
5626
+ if (temporalScore > 0) {
5627
+ return "Session overlaps the resolved time window.";
5628
+ }
5629
+ return "Matched episodic recall ranking.";
5630
+ }
5631
+
5402
5632
  // src/adapters/db/recall-adapter.ts
5403
5633
  var RECALL_CANDIDATE_SELECT_COLUMNS = `
5404
5634
  e.id,
@@ -7515,6 +7745,7 @@ function buildEntryRecallInput(input, parsedTimeWindow, routing) {
7515
7745
  text: input.text,
7516
7746
  ...input.limit !== void 0 ? { limit: input.limit } : {},
7517
7747
  ...input.threshold !== void 0 ? { threshold: input.threshold } : {},
7748
+ ...input.budget !== void 0 ? { budget: input.budget } : {},
7518
7749
  ...input.types && input.types.length > 0 ? { types: input.types } : {},
7519
7750
  ...input.tags && input.tags.length > 0 ? { tags: input.tags } : {},
7520
7751
  ...input.sessionKey ? { sessionKey: input.sessionKey } : {},
@@ -7764,6 +7995,18 @@ export {
7764
7995
  resolveModel,
7765
7996
  resolveLlmCredentials,
7766
7997
  resolveLlmApiKey,
7998
+ ENTRY_PREVIEW_MAX_CHARS,
7999
+ buildEntryRecallPreview,
8000
+ recallResultHasTruncatedEntryPreviews,
8001
+ assertEntryFetchableContentLength,
8002
+ truncate,
8003
+ sanitizeStoreToolParams,
8004
+ formatRecallToolSummary,
8005
+ sanitizeRecallToolParams,
8006
+ formatUnifiedRecallLogSummary,
8007
+ buildRecallToolDetails,
8008
+ formatFetchedEntryText,
8009
+ buildFetchToolDetails,
7767
8010
  createOpenAICrossEncoder,
7768
8011
  resolveCrossEncoderApiKey,
7769
8012
  createRecallAdapter,
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  formatAgenrBeforeTurnRecall,
14
14
  runBeforeTurn
15
- } from "./chunk-575MUIW5.js";
15
+ } from "./chunk-V5CDMHRN.js";
16
16
  import {
17
17
  CLAIM_KEY_SOURCES,
18
18
  CLAIM_KEY_STATUSES,
@@ -41,7 +41,7 @@ import {
41
41
  resolveEmbeddingModel,
42
42
  resolveModel,
43
43
  runUnifiedRecall
44
- } from "./chunk-ELR2HSVC.js";
44
+ } from "./chunk-NNO2V4GH.js";
45
45
  import {
46
46
  recall
47
47
  } from "./chunk-5LADPJ4C.js";