@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.
- package/LICENSE +21 -661
- package/dist/{chunk-MYZ2CWY6.js → chunk-E2DHUFZK.js} +464 -542
- package/dist/{chunk-LAXNNWHM.js → chunk-EEEL53X4.js} +191 -12
- package/dist/{chunk-TBFAARM5.js → chunk-JSVQILB3.js} +12 -1
- package/dist/{chunk-ELR2HSVC.js → chunk-NNO2V4GH.js} +243 -0
- package/dist/{chunk-P5SB75FK.js → chunk-NOIZQRQV.js} +2 -2
- package/dist/{chunk-575MUIW5.js → chunk-V5CDMHRN.js} +14 -179
- package/dist/index.js +192 -164
- package/openclaw.plugin.json +2 -2
- package/package.json +2 -2
|
@@ -1,26 +1,43 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ENTRY_TYPE_DESCRIPTION,
|
|
3
|
+
EXPIRY_DESCRIPTION,
|
|
4
|
+
RECALL_MODES,
|
|
5
|
+
UPDATE_EXPIRY_DESCRIPTION,
|
|
6
|
+
asRecord,
|
|
7
|
+
buildEntryMemoryResolverPorts,
|
|
2
8
|
createMemoryRepository,
|
|
9
|
+
formatErrorMessage,
|
|
3
10
|
ingestEpisodeTranscript,
|
|
11
|
+
normalizeStringArray,
|
|
12
|
+
parseEntryType,
|
|
13
|
+
parseEntryTypes,
|
|
14
|
+
parseExpiry,
|
|
15
|
+
parseRecallMode,
|
|
16
|
+
resolveTargetEntry,
|
|
4
17
|
storeEntriesDetailed
|
|
5
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-EEEL53X4.js";
|
|
6
19
|
import {
|
|
7
20
|
containsAgenrMemoryContext,
|
|
8
21
|
formatInjectionEntryBodyLines,
|
|
9
22
|
formatInjectionEntryHeader,
|
|
10
23
|
stripAgenrMemoryContext,
|
|
11
24
|
wrapAgenrMemoryContext
|
|
12
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-V5CDMHRN.js";
|
|
13
26
|
import {
|
|
27
|
+
ENTRY_PREVIEW_MAX_CHARS,
|
|
14
28
|
ENTRY_SELECT_COLUMNS,
|
|
15
29
|
ENTRY_TYPES,
|
|
16
|
-
|
|
30
|
+
assertEntryFetchableContentLength,
|
|
17
31
|
attachCrossEncoderPort,
|
|
18
32
|
buildActiveEntryClause,
|
|
33
|
+
buildEntryRecallPreview,
|
|
34
|
+
buildFetchToolDetails,
|
|
19
35
|
createDatabase,
|
|
20
36
|
createEmbeddingClient,
|
|
21
37
|
createLlmClient,
|
|
22
38
|
createOpenAICrossEncoder,
|
|
23
39
|
createRecallAdapter,
|
|
40
|
+
formatFetchedEntryText,
|
|
24
41
|
mapEntryRow,
|
|
25
42
|
normalizeManualClaimKeyUpdate,
|
|
26
43
|
projectClaimCentricRecallEntry,
|
|
@@ -28,6 +45,7 @@ import {
|
|
|
28
45
|
readNumber,
|
|
29
46
|
readOptionalString,
|
|
30
47
|
readRequiredString,
|
|
48
|
+
recallResultHasTruncatedEntryPreviews,
|
|
31
49
|
resolveClaimExtractionConfig,
|
|
32
50
|
resolveConfigPath,
|
|
33
51
|
resolveCrossEncoderApiKey,
|
|
@@ -37,17 +55,13 @@ import {
|
|
|
37
55
|
resolveLlmApiKey,
|
|
38
56
|
resolveModel,
|
|
39
57
|
runUnifiedRecall,
|
|
58
|
+
truncate,
|
|
40
59
|
validateTemporalValidityRange
|
|
41
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-NNO2V4GH.js";
|
|
42
61
|
import {
|
|
43
62
|
recall
|
|
44
63
|
} from "./chunk-5LADPJ4C.js";
|
|
45
64
|
|
|
46
|
-
// src/adapters/shared/errors.ts
|
|
47
|
-
function formatErrorMessage(error) {
|
|
48
|
-
return error instanceof Error ? error.message : String(error);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
65
|
// src/app/plugin-runtime/session-tracking.ts
|
|
52
66
|
function resolveSessionIdentityKey(sessionId, sessionKey) {
|
|
53
67
|
const normalizedSessionId = sessionId?.trim();
|
|
@@ -459,7 +473,7 @@ function buildArtifactRecallQuery(sections, maxChars) {
|
|
|
459
473
|
continue;
|
|
460
474
|
}
|
|
461
475
|
const labeled = `${section.title}: ${normalizedContent}`;
|
|
462
|
-
const truncated =
|
|
476
|
+
const truncated = truncate2(labeled, remaining);
|
|
463
477
|
if (truncated.length === 0) {
|
|
464
478
|
continue;
|
|
465
479
|
}
|
|
@@ -570,7 +584,7 @@ function normalizeOptionalString2(value) {
|
|
|
570
584
|
function normalizeWhitespace(value) {
|
|
571
585
|
return value.replace(/\s+/g, " ").trim();
|
|
572
586
|
}
|
|
573
|
-
function
|
|
587
|
+
function truncate2(value, maxChars) {
|
|
574
588
|
if (maxChars <= 0) {
|
|
575
589
|
return "";
|
|
576
590
|
}
|
|
@@ -1814,536 +1828,213 @@ async function composeHostPluginServices(input) {
|
|
|
1814
1828
|
});
|
|
1815
1829
|
}
|
|
1816
1830
|
|
|
1817
|
-
// src/adapters/shared/
|
|
1818
|
-
function
|
|
1819
|
-
const
|
|
1820
|
-
|
|
1821
|
-
`requested=${result.routing.requested} detected=${result.routing.detectedIntent} queried=${result.routing.queried.join(", ") || "none"}`,
|
|
1822
|
-
result.routing.reason,
|
|
1823
|
-
""
|
|
1824
|
-
];
|
|
1825
|
-
if (result.timeWindow) {
|
|
1826
|
-
lines.push("Resolved Time Window");
|
|
1827
|
-
lines.push(`${result.timeWindow.start} -> ${result.timeWindow.end} (${result.timeWindow.timezone}) from ${JSON.stringify(result.timeWindow.resolvedFrom)}`);
|
|
1828
|
-
lines.push("");
|
|
1829
|
-
}
|
|
1830
|
-
if (result.asOf) {
|
|
1831
|
-
lines.push("As Of");
|
|
1832
|
-
lines.push(result.asOf);
|
|
1833
|
-
lines.push("");
|
|
1834
|
-
}
|
|
1835
|
-
if (result.routing.queried.includes("procedures") || result.procedure || result.procedureCandidates.length > 0 || result.procedureNotices.length > 0) {
|
|
1836
|
-
appendProcedureMatches(lines, result);
|
|
1837
|
-
lines.push("");
|
|
1838
|
-
}
|
|
1839
|
-
const renderEntriesFirst = result.routing.detectedIntent === "historical_state";
|
|
1840
|
-
if (renderEntriesFirst) {
|
|
1841
|
-
appendEntryMatches(lines, result);
|
|
1842
|
-
lines.push("");
|
|
1843
|
-
appendClaimTransitions(lines, result);
|
|
1844
|
-
lines.push("");
|
|
1845
|
-
appendEpisodeMatches(lines, result);
|
|
1846
|
-
} else {
|
|
1847
|
-
appendEpisodeMatches(lines, result);
|
|
1848
|
-
lines.push("");
|
|
1849
|
-
appendEntryMatches(lines, result);
|
|
1850
|
-
lines.push("");
|
|
1851
|
-
appendClaimTransitions(lines, result);
|
|
1852
|
-
}
|
|
1853
|
-
if (result.notices.length > 0) {
|
|
1854
|
-
lines.push("");
|
|
1855
|
-
lines.push("Notices");
|
|
1856
|
-
for (const notice of result.notices) {
|
|
1857
|
-
lines.push(`- ${notice}`);
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
return lines.join("\n");
|
|
1831
|
+
// src/adapters/shared/claim-support.ts
|
|
1832
|
+
function buildSessionSourceFile(session, prefix) {
|
|
1833
|
+
const target = session.sessionKey ?? session.sessionId ?? session.agentId ?? "unknown";
|
|
1834
|
+
return `${prefix}:${target}`;
|
|
1861
1835
|
}
|
|
1862
|
-
function
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1836
|
+
function buildToolCallClaimSupport(session, prefix, toolName, observedAt) {
|
|
1837
|
+
return {
|
|
1838
|
+
claim_support_source_kind: "tool_call",
|
|
1839
|
+
claim_support_locator: `${buildSessionSourceFile(session, prefix)}#${toolName}`,
|
|
1840
|
+
claim_support_observed_at: observedAt,
|
|
1841
|
+
claim_support_mode: "explicit"
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
// src/adapters/shared/memory-tools.ts
|
|
1846
|
+
function buildRecallToolServices(services) {
|
|
1847
|
+
return {
|
|
1848
|
+
episodes: services.episodes,
|
|
1849
|
+
procedures: services.procedures,
|
|
1850
|
+
recall: services.recall,
|
|
1851
|
+
embeddingStatus: services.embeddingStatus,
|
|
1852
|
+
embedQuery: services.beforeTurn.embedQuery
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
var STORE_TOOL_PARAMETERS = {
|
|
1856
|
+
type: "object",
|
|
1857
|
+
additionalProperties: false,
|
|
1858
|
+
properties: {
|
|
1859
|
+
type: {
|
|
1860
|
+
type: "string",
|
|
1861
|
+
enum: [...ENTRY_TYPES],
|
|
1862
|
+
description: ENTRY_TYPE_DESCRIPTION
|
|
1863
|
+
},
|
|
1864
|
+
subject: {
|
|
1865
|
+
type: "string",
|
|
1866
|
+
description: "Short subject line future recall can match. Name the durable takeaway, person, system, rule, relationship, or milestone directly."
|
|
1867
|
+
},
|
|
1868
|
+
content: {
|
|
1869
|
+
type: "string",
|
|
1870
|
+
description: "What a fresh session should remember. Store the durable takeaway, not the activity log, canonical record, or transient progress snapshot."
|
|
1871
|
+
},
|
|
1872
|
+
importance: {
|
|
1873
|
+
type: "integer",
|
|
1874
|
+
minimum: 1,
|
|
1875
|
+
maximum: 10,
|
|
1876
|
+
description: "Importance from 1 to 10. Use 7 for normal durable memory, 9 for critical constraints, and 10 only rarely."
|
|
1877
|
+
},
|
|
1878
|
+
expiry: {
|
|
1879
|
+
type: "string",
|
|
1880
|
+
enum: ["core", "permanent", "temporary"],
|
|
1881
|
+
description: EXPIRY_DESCRIPTION
|
|
1882
|
+
},
|
|
1883
|
+
tags: {
|
|
1884
|
+
type: "array",
|
|
1885
|
+
items: { type: "string" },
|
|
1886
|
+
description: "Optional tags for entities, systems, teams, or themes that should improve later recall."
|
|
1887
|
+
},
|
|
1888
|
+
sourceContext: {
|
|
1889
|
+
type: "string",
|
|
1890
|
+
description: "Optional provenance note explaining why this memory was stored or what situation produced it."
|
|
1891
|
+
},
|
|
1892
|
+
supersedes: {
|
|
1893
|
+
type: "string",
|
|
1894
|
+
description: "ID of an entry this replaces. The old entry will be marked as superseded."
|
|
1895
|
+
},
|
|
1896
|
+
claimKey: {
|
|
1897
|
+
type: "string",
|
|
1898
|
+
description: 'Slot key identifying the specific knowledge slot (entity/attribute format, e.g., "project_name/deploy_strategy" or "postgres/max_connections"). Entries with the same claim key are candidates for supersession.'
|
|
1899
|
+
},
|
|
1900
|
+
validFrom: {
|
|
1901
|
+
type: "string",
|
|
1902
|
+
description: "ISO 8601 timestamp for when this fact became true in the world."
|
|
1903
|
+
},
|
|
1904
|
+
validTo: {
|
|
1905
|
+
type: "string",
|
|
1906
|
+
description: "ISO 8601 timestamp for when this fact stopped being true."
|
|
1871
1907
|
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1908
|
+
},
|
|
1909
|
+
required: ["type", "subject", "content"]
|
|
1910
|
+
};
|
|
1911
|
+
var RECALL_TOOL_PARAMETERS = {
|
|
1912
|
+
type: "object",
|
|
1913
|
+
additionalProperties: false,
|
|
1914
|
+
properties: {
|
|
1915
|
+
query: {
|
|
1916
|
+
type: "string",
|
|
1917
|
+
description: "What you need to remember. Use a focused natural-language query rather than a broad 'everything' search. Phrase prior-state asks directly, for example 'what was the previous approach' or 'what changed from X to Y'. Phrase procedural asks directly, for example 'how do I rotate credentials' or 'what steps should I follow'."
|
|
1918
|
+
},
|
|
1919
|
+
mode: {
|
|
1920
|
+
type: "string",
|
|
1921
|
+
enum: [...RECALL_MODES],
|
|
1922
|
+
description: "Recall mode: auto routes between exact entry recall, historical-state recall, procedural recall, and episodes; entries forces semantic recall; episodes forces temporal or semantic session recall; procedures forces procedural recall."
|
|
1923
|
+
},
|
|
1924
|
+
limit: {
|
|
1925
|
+
type: "integer",
|
|
1926
|
+
minimum: 1,
|
|
1927
|
+
maximum: 10,
|
|
1928
|
+
description: "Maximum results to return. Lower this when you want a tighter shortlist."
|
|
1929
|
+
},
|
|
1930
|
+
threshold: {
|
|
1931
|
+
type: "number",
|
|
1932
|
+
minimum: 0,
|
|
1933
|
+
maximum: 1,
|
|
1934
|
+
description: "Minimum final score from 0 to 1. Raise this when you want fewer, higher-confidence matches."
|
|
1935
|
+
},
|
|
1936
|
+
budget: {
|
|
1937
|
+
type: "integer",
|
|
1938
|
+
minimum: 1,
|
|
1939
|
+
description: "Approximate token budget applied after entry scoring. Omit when you do not want a budget cap."
|
|
1940
|
+
},
|
|
1941
|
+
types: {
|
|
1942
|
+
type: "array",
|
|
1943
|
+
items: {
|
|
1944
|
+
type: "string",
|
|
1945
|
+
enum: [...ENTRY_TYPES]
|
|
1946
|
+
},
|
|
1947
|
+
description: "Optional knowledge types to filter by, such as decision, preference, lesson, fact, milestone, or relationship."
|
|
1948
|
+
},
|
|
1949
|
+
tags: {
|
|
1950
|
+
type: "array",
|
|
1951
|
+
items: { type: "string" },
|
|
1952
|
+
description: "Optional tags to filter by once you already know the relevant entity, system, or theme."
|
|
1953
|
+
},
|
|
1954
|
+
asOf: {
|
|
1955
|
+
type: "string",
|
|
1956
|
+
description: "Optional reference time for current-vs-prior resolution. Supports ISO timestamps and natural-language date phrases."
|
|
1957
|
+
}
|
|
1958
|
+
},
|
|
1959
|
+
required: ["query"]
|
|
1960
|
+
};
|
|
1961
|
+
var UPDATE_TOOL_PARAMETERS = {
|
|
1962
|
+
type: "object",
|
|
1963
|
+
additionalProperties: false,
|
|
1964
|
+
properties: {
|
|
1965
|
+
id: {
|
|
1966
|
+
type: "string",
|
|
1967
|
+
description: "Entry id to update. Provide exactly one of id or subject."
|
|
1968
|
+
},
|
|
1969
|
+
subject: {
|
|
1970
|
+
type: "string",
|
|
1971
|
+
description: "Subject text to resolve when the id is unknown. The most recent exact or substring match wins. Provide exactly one of id or subject."
|
|
1972
|
+
},
|
|
1973
|
+
importance: {
|
|
1974
|
+
type: "integer",
|
|
1975
|
+
description: "New importance from 1 to 10. Use 7 for normal durable memory and reserve 9 to 10 for rare critical entries."
|
|
1976
|
+
},
|
|
1977
|
+
expiry: {
|
|
1978
|
+
type: "string",
|
|
1979
|
+
description: UPDATE_EXPIRY_DESCRIPTION
|
|
1980
|
+
},
|
|
1981
|
+
claimKey: {
|
|
1982
|
+
type: "string",
|
|
1983
|
+
description: 'Slot key identifying the specific knowledge slot (entity/attribute format, e.g., "project_name/deploy_strategy" or "postgres/max_connections"). Entries with the same claim key are candidates for supersession.'
|
|
1984
|
+
},
|
|
1985
|
+
validFrom: {
|
|
1986
|
+
type: "string",
|
|
1987
|
+
description: "ISO 8601 timestamp for when this fact became true."
|
|
1988
|
+
},
|
|
1989
|
+
validTo: {
|
|
1990
|
+
type: "string",
|
|
1991
|
+
description: "ISO 8601 timestamp for when this fact stopped being true."
|
|
1880
1992
|
}
|
|
1881
1993
|
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1994
|
+
};
|
|
1995
|
+
var FETCH_TOOL_PARAMETERS = {
|
|
1996
|
+
type: "object",
|
|
1997
|
+
additionalProperties: false,
|
|
1998
|
+
properties: {
|
|
1999
|
+
id: {
|
|
2000
|
+
type: "string",
|
|
2001
|
+
description: "Entry id to fetch. Provide exactly one of id or subject."
|
|
2002
|
+
},
|
|
2003
|
+
subject: {
|
|
2004
|
+
type: "string",
|
|
2005
|
+
description: "Subject text to resolve when the id is unknown. The most recent exact or substring match wins. Provide exactly one of id or subject."
|
|
1886
2006
|
}
|
|
1887
2007
|
}
|
|
1888
|
-
}
|
|
1889
|
-
function
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
)
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
const provenance = formatProjectedEntryProvenance(entry);
|
|
1906
|
-
if (provenance) {
|
|
1907
|
-
lines.push(` provenance=${provenance}`);
|
|
1908
|
-
}
|
|
1909
|
-
lines.push(` why_surfaced=${entry.whySurfaced.summary}`);
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
function appendEpisodeMatches(lines, result) {
|
|
1914
|
-
lines.push("Episode Matches");
|
|
1915
|
-
if (result.episodes.length === 0) {
|
|
1916
|
-
lines.push("None.");
|
|
1917
|
-
return;
|
|
1918
|
-
}
|
|
1919
|
-
for (const [index, episode] of result.episodes.entries()) {
|
|
1920
|
-
lines.push(
|
|
1921
|
-
`${index + 1}. ${episode.episode.id} | ${episode.episode.source} | ${episode.episode.startedAt} -> ${episode.episode.endedAt ?? episode.episode.startedAt} | score ${episode.score.toFixed(2)}`
|
|
1922
|
-
);
|
|
1923
|
-
lines.push(` ${index < 3 ? episode.episode.summary.trim() : truncate2(episode.episode.summary.trim(), 220)}`);
|
|
1924
|
-
lines.push(` why_matched=${describeEpisodeMatch(episode)}`);
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
function appendCanonicalProcedure(lines, procedure, candidates) {
|
|
1928
|
-
const leadCandidate = candidates.find((candidate) => candidate.procedure.id === procedure.id);
|
|
1929
|
-
lines.push(
|
|
1930
|
-
leadCandidate ? `Canonical Procedure. ${procedure.procedure_key} | ${procedure.title} | score ${leadCandidate.score.toFixed(2)}` : `Canonical Procedure. ${procedure.procedure_key} | ${procedure.title}`
|
|
1931
|
-
);
|
|
1932
|
-
lines.push(` goal=${procedure.goal}`);
|
|
1933
|
-
appendLabeledList(lines, "when_to_use", procedure.when_to_use);
|
|
1934
|
-
appendLabeledList(lines, "when_not_to_use", procedure.when_not_to_use);
|
|
1935
|
-
appendLabeledList(lines, "prerequisites", procedure.prerequisites);
|
|
1936
|
-
lines.push(" steps");
|
|
1937
|
-
for (const [index, step] of procedure.steps.entries()) {
|
|
1938
|
-
lines.push(` ${index + 1}. [${step.kind}] ${step.instruction}`);
|
|
1939
|
-
const stepDetails = formatProcedureStepDetails(step);
|
|
1940
|
-
if (stepDetails.length > 0) {
|
|
1941
|
-
for (const detail of stepDetails) {
|
|
1942
|
-
lines.push(` ${detail}`);
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
appendLabeledList(lines, "verification", procedure.verification);
|
|
1947
|
-
appendLabeledList(lines, "failure_modes", procedure.failure_modes);
|
|
1948
|
-
lines.push(" sources");
|
|
1949
|
-
for (const source of procedure.sources) {
|
|
1950
|
-
lines.push(` - ${formatProcedureSource(source)}`);
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
function appendClaimTransitions(lines, result) {
|
|
1954
|
-
lines.push("Claim Transitions");
|
|
1955
|
-
if (result.claimTransitions.length === 0) {
|
|
1956
|
-
lines.push("None.");
|
|
1957
|
-
return;
|
|
1958
|
-
}
|
|
1959
|
-
for (const [index, transition] of result.claimTransitions.entries()) {
|
|
1960
|
-
lines.push(
|
|
1961
|
-
`${index + 1}. family=${transition.claimKey ?? transition.familyKey} | slot_policy=${transition.slotPolicy}${transition.currentEntryId ? ` | current=${transition.currentEntryId}` : ""}${transition.priorEntryId ? ` | prior=${transition.priorEntryId}` : ""}`
|
|
1962
|
-
);
|
|
1963
|
-
lines.push(` ${transition.summary}`);
|
|
1964
|
-
if (transition.episodeContext) {
|
|
1965
|
-
lines.push(
|
|
1966
|
-
` episode=${transition.episodeContext.episodeId} | ${transition.episodeContext.startedAt} -> ${transition.episodeContext.endedAt ?? transition.episodeContext.startedAt}`
|
|
1967
|
-
);
|
|
1968
|
-
lines.push(` ${truncate2(transition.episodeContext.summary.trim(), 220)}`);
|
|
1969
|
-
}
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
function appendLabeledList(lines, label, values) {
|
|
1973
|
-
lines.push(` ${label}`);
|
|
1974
|
-
if (values.length === 0) {
|
|
1975
|
-
lines.push(" - none");
|
|
1976
|
-
return;
|
|
1977
|
-
}
|
|
1978
|
-
for (const value of values) {
|
|
1979
|
-
lines.push(` - ${value}`);
|
|
1980
|
-
}
|
|
1981
|
-
}
|
|
1982
|
-
function formatProcedureStepDetails(step) {
|
|
1983
|
-
switch (step.kind) {
|
|
1984
|
-
case "run_command":
|
|
1985
|
-
return [`command=${step.command}`];
|
|
1986
|
-
case "read_reference":
|
|
1987
|
-
return [`ref=${formatProcedureSource(step.ref)}`];
|
|
1988
|
-
case "inspect_state":
|
|
1989
|
-
return [step.target ? `target=${step.target}` : void 0, step.query ? `query=${step.query}` : void 0].filter(
|
|
1990
|
-
(value) => value !== void 0
|
|
1991
|
-
);
|
|
1992
|
-
case "edit_file":
|
|
1993
|
-
return [`path=${step.path}`, `edit=${step.edit}`];
|
|
1994
|
-
case "ask_user":
|
|
1995
|
-
return [`prompt=${step.prompt}`];
|
|
1996
|
-
case "invoke_tool":
|
|
1997
|
-
return [step.tool ? `tool=${step.tool}` : void 0, step.arguments ? `arguments=${JSON.stringify(step.arguments)}` : void 0].filter(
|
|
1998
|
-
(value) => value !== void 0
|
|
1999
|
-
);
|
|
2000
|
-
case "verify":
|
|
2001
|
-
return step.checks.map((check) => `check=${check}`);
|
|
2002
|
-
default:
|
|
2003
|
-
return [];
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
function formatProcedureSource(source) {
|
|
2007
|
-
const parts = [source.kind, source.label, source.path, source.locator].filter((value) => Boolean(value && value.length > 0));
|
|
2008
|
-
return parts.join(" | ");
|
|
2009
|
-
}
|
|
2010
|
-
function describeEpisodeMatch(result) {
|
|
2011
|
-
if (result.scores.semantic > 0 && result.scores.temporal > 0) {
|
|
2012
|
-
return "Semantic match within the resolved time window.";
|
|
2013
|
-
}
|
|
2014
|
-
if (result.scores.semantic > 0) {
|
|
2015
|
-
return "Semantic match to the episode summary.";
|
|
2016
|
-
}
|
|
2017
|
-
if (result.scores.temporal > 0) {
|
|
2018
|
-
return "Session overlaps the resolved time window.";
|
|
2019
|
-
}
|
|
2020
|
-
return "Matched episodic recall ranking.";
|
|
2021
|
-
}
|
|
2022
|
-
function formatClaimStatus(status) {
|
|
2023
|
-
return status === "no_key" ? "no-key" : status;
|
|
2024
|
-
}
|
|
2025
|
-
function formatProjectedEntryProvenance(entry) {
|
|
2026
|
-
const parts = [
|
|
2027
|
-
entry.provenance.supersededById ? `superseded_by=${entry.provenance.supersededById}` : void 0,
|
|
2028
|
-
entry.provenance.supersessionKind ? `kind=${entry.provenance.supersessionKind}` : void 0,
|
|
2029
|
-
entry.provenance.supersessionReason ? `reason=${truncate2(entry.provenance.supersessionReason, 120)}` : void 0,
|
|
2030
|
-
entry.provenance.supportSourceKind ? `support=${entry.provenance.supportSourceKind}` : void 0,
|
|
2031
|
-
entry.provenance.supportMode ? `support_mode=${entry.provenance.supportMode}` : void 0,
|
|
2032
|
-
entry.provenance.supportObservedAt ? `observed=${entry.provenance.supportObservedAt}` : void 0,
|
|
2033
|
-
entry.provenance.supportLocator ? `locator=${truncate2(entry.provenance.supportLocator, 120)}` : void 0
|
|
2034
|
-
].filter((value) => value !== void 0);
|
|
2035
|
-
return parts.join(" | ");
|
|
2036
|
-
}
|
|
2037
|
-
function truncate2(value, maxChars) {
|
|
2038
|
-
if (value.length <= maxChars) {
|
|
2039
|
-
return value;
|
|
2040
|
-
}
|
|
2041
|
-
return `${value.slice(0, maxChars - 3).trimEnd()}...`;
|
|
2042
|
-
}
|
|
2043
|
-
|
|
2044
|
-
// src/adapters/shared/entry-tools.ts
|
|
2045
|
-
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.";
|
|
2046
|
-
var EXPIRY_DESCRIPTION = "Lifetime bucket: core (always injected at session start, use sparingly), permanent (durable and recalled on demand), or temporary (short-horizon).";
|
|
2047
|
-
var UPDATE_EXPIRY_DESCRIPTION = `${EXPIRY_DESCRIPTION} Accepted values: ${EXPIRY_LEVELS.join(", ")}.`;
|
|
2048
|
-
var RECALL_MODES = ["auto", "entries", "episodes", "procedures"];
|
|
2049
|
-
function asRecord(value) {
|
|
2050
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
2051
|
-
return value;
|
|
2052
|
-
}
|
|
2053
|
-
throw new Error("Tool parameters must be an object.");
|
|
2054
|
-
}
|
|
2055
|
-
function parseExpiry(value) {
|
|
2056
|
-
if (value === void 0) {
|
|
2057
|
-
return void 0;
|
|
2058
|
-
}
|
|
2059
|
-
if (EXPIRY_LEVELS.includes(value)) {
|
|
2060
|
-
return value;
|
|
2061
|
-
}
|
|
2062
|
-
throw new Error(`Unsupported expiry "${value}".`);
|
|
2063
|
-
}
|
|
2064
|
-
function parseEntryTypes(values) {
|
|
2065
|
-
return normalizeStringArray(values).map((value) => parseEntryType(value));
|
|
2066
|
-
}
|
|
2067
|
-
function parseEntryType(value) {
|
|
2068
|
-
if (ENTRY_TYPES.includes(value)) {
|
|
2069
|
-
return value;
|
|
2070
|
-
}
|
|
2071
|
-
throw new Error(`Unsupported entry type "${value}".`);
|
|
2072
|
-
}
|
|
2073
|
-
function parseRecallMode(value) {
|
|
2074
|
-
if (value === void 0) {
|
|
2075
|
-
return void 0;
|
|
2076
|
-
}
|
|
2077
|
-
if (RECALL_MODES.includes(value)) {
|
|
2078
|
-
return value;
|
|
2079
|
-
}
|
|
2080
|
-
throw new Error(`Unsupported recall mode "${value}".`);
|
|
2081
|
-
}
|
|
2082
|
-
function normalizeStringArray(values) {
|
|
2083
|
-
if (!values) {
|
|
2084
|
-
return [];
|
|
2085
|
-
}
|
|
2086
|
-
return Array.from(new Set(values.map((value) => value.trim()).filter((value) => value.length > 0)));
|
|
2087
|
-
}
|
|
2088
|
-
function formatTargetSelector(id, subject, last) {
|
|
2089
|
-
if (last === true) {
|
|
2090
|
-
return "last";
|
|
2091
|
-
}
|
|
2092
|
-
if (id) {
|
|
2093
|
-
return `id:${JSON.stringify(id)}`;
|
|
2094
|
-
}
|
|
2095
|
-
if (subject) {
|
|
2096
|
-
return `subject:${JSON.stringify(subject)}`;
|
|
2097
|
-
}
|
|
2098
|
-
return "unknown";
|
|
2099
|
-
}
|
|
2100
|
-
function sanitizeUpdateToolParams(params) {
|
|
2101
|
-
return {
|
|
2102
|
-
...params.id ? { id: params.id } : {},
|
|
2103
|
-
...params.subject ? { subject: params.subject } : {},
|
|
2104
|
-
...params.importance !== void 0 ? { importance: params.importance } : {},
|
|
2105
|
-
...params.expiry !== void 0 ? { expiry: params.expiry } : {},
|
|
2106
|
-
...params.claimKey !== void 0 ? { hasClaimKey: true } : {},
|
|
2107
|
-
...params.validFrom !== void 0 ? { hasValidFrom: true } : {},
|
|
2108
|
-
...params.validTo !== void 0 ? { hasValidTo: true } : {}
|
|
2109
|
-
};
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
|
-
// src/adapters/shared/resolve-target.ts
|
|
2113
|
-
async function resolveTargetEntry(ports, params, options = {}) {
|
|
2114
|
-
const id = readOptionalStringParam(params, "id");
|
|
2115
|
-
const subject = readOptionalStringParam(params, "subject");
|
|
2116
|
-
const last = options.allowLast ? readBooleanParam(params, "last") : void 0;
|
|
2117
|
-
const selectorCount = (id ? 1 : 0) + (subject ? 1 : 0) + (last === true ? 1 : 0);
|
|
2118
|
-
const selectorDescription = options.allowLast ? "id, subject, or last" : "id or subject";
|
|
2119
|
-
if (selectorCount !== 1) {
|
|
2120
|
-
throw new Error(`Provide exactly one target selector: ${selectorDescription}.`);
|
|
2121
|
-
}
|
|
2122
|
-
if (last) {
|
|
2123
|
-
const entry2 = await ports.findMostRecentEntry();
|
|
2124
|
-
if (!entry2) {
|
|
2125
|
-
throw new Error("No agenr entries exist yet.");
|
|
2126
|
-
}
|
|
2127
|
-
return entry2;
|
|
2128
|
-
}
|
|
2129
|
-
if (id) {
|
|
2130
|
-
const entry2 = await ports.getEntryById(id);
|
|
2131
|
-
if (!entry2) {
|
|
2132
|
-
throw new Error(`No agenr entry found for id ${id}.`);
|
|
2133
|
-
}
|
|
2134
|
-
return entry2;
|
|
2135
|
-
}
|
|
2136
|
-
const entry = await ports.findEntryBySubject(subject ?? "");
|
|
2137
|
-
if (!entry) {
|
|
2138
|
-
throw new Error(`No agenr entry found for subject "${subject}".`);
|
|
2139
|
-
}
|
|
2140
|
-
return entry;
|
|
2141
|
-
}
|
|
2142
|
-
function readBooleanParam(params, key) {
|
|
2143
|
-
const value = params[key];
|
|
2144
|
-
if (value === void 0) {
|
|
2145
|
-
return void 0;
|
|
2146
|
-
}
|
|
2147
|
-
if (typeof value === "boolean") {
|
|
2148
|
-
return value;
|
|
2149
|
-
}
|
|
2150
|
-
throw new Error(`${key} must be a boolean.`);
|
|
2151
|
-
}
|
|
2152
|
-
function readOptionalStringParam(params, key) {
|
|
2153
|
-
const value = params[key];
|
|
2154
|
-
if (value === void 0 || value === null) {
|
|
2155
|
-
return void 0;
|
|
2156
|
-
}
|
|
2157
|
-
if (typeof value !== "string") {
|
|
2158
|
-
throw new Error(`${key} must be a string.`);
|
|
2159
|
-
}
|
|
2160
|
-
const normalized = value.trim();
|
|
2161
|
-
return normalized.length > 0 ? normalized : void 0;
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
|
-
// src/adapters/shared/claim-support.ts
|
|
2165
|
-
function buildSessionSourceFile(session, prefix) {
|
|
2166
|
-
const target = session.sessionKey ?? session.sessionId ?? session.agentId ?? "unknown";
|
|
2167
|
-
return `${prefix}:${target}`;
|
|
2168
|
-
}
|
|
2169
|
-
function buildToolCallClaimSupport(session, prefix, toolName, observedAt) {
|
|
2170
|
-
return {
|
|
2171
|
-
claim_support_source_kind: "tool_call",
|
|
2172
|
-
claim_support_locator: `${buildSessionSourceFile(session, prefix)}#${toolName}`,
|
|
2173
|
-
claim_support_observed_at: observedAt,
|
|
2174
|
-
claim_support_mode: "explicit"
|
|
2175
|
-
};
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
// src/adapters/shared/memory-tools.ts
|
|
2179
|
-
function buildRecallToolServices(services) {
|
|
2180
|
-
return {
|
|
2181
|
-
episodes: services.episodes,
|
|
2182
|
-
procedures: services.procedures,
|
|
2183
|
-
recall: services.recall,
|
|
2184
|
-
embeddingStatus: services.embeddingStatus,
|
|
2185
|
-
embedQuery: services.beforeTurn.embedQuery
|
|
2186
|
-
};
|
|
2187
|
-
}
|
|
2188
|
-
var STORE_TOOL_PARAMETERS = {
|
|
2189
|
-
type: "object",
|
|
2190
|
-
additionalProperties: false,
|
|
2191
|
-
properties: {
|
|
2192
|
-
type: {
|
|
2193
|
-
type: "string",
|
|
2194
|
-
enum: [...ENTRY_TYPES],
|
|
2195
|
-
description: ENTRY_TYPE_DESCRIPTION
|
|
2196
|
-
},
|
|
2197
|
-
subject: {
|
|
2198
|
-
type: "string",
|
|
2199
|
-
description: "Short subject line future recall can match. Name the durable takeaway, person, system, rule, relationship, or milestone directly."
|
|
2200
|
-
},
|
|
2201
|
-
content: {
|
|
2202
|
-
type: "string",
|
|
2203
|
-
description: "What a fresh session should remember. Store the durable takeaway, not the activity log, canonical record, or transient progress snapshot."
|
|
2204
|
-
},
|
|
2205
|
-
importance: {
|
|
2206
|
-
type: "integer",
|
|
2207
|
-
minimum: 1,
|
|
2208
|
-
maximum: 10,
|
|
2209
|
-
description: "Importance from 1 to 10. Use 7 for normal durable memory, 9 for critical constraints, and 10 only rarely."
|
|
2210
|
-
},
|
|
2211
|
-
expiry: {
|
|
2212
|
-
type: "string",
|
|
2213
|
-
enum: ["core", "permanent", "temporary"],
|
|
2214
|
-
description: EXPIRY_DESCRIPTION
|
|
2215
|
-
},
|
|
2216
|
-
tags: {
|
|
2217
|
-
type: "array",
|
|
2218
|
-
items: { type: "string" },
|
|
2219
|
-
description: "Optional tags for entities, systems, teams, or themes that should improve later recall."
|
|
2220
|
-
},
|
|
2221
|
-
sourceContext: {
|
|
2222
|
-
type: "string",
|
|
2223
|
-
description: "Optional provenance note explaining why this memory was stored or what situation produced it."
|
|
2224
|
-
},
|
|
2225
|
-
supersedes: {
|
|
2226
|
-
type: "string",
|
|
2227
|
-
description: "ID of an entry this replaces. The old entry will be marked as superseded."
|
|
2228
|
-
},
|
|
2229
|
-
claimKey: {
|
|
2230
|
-
type: "string",
|
|
2231
|
-
description: 'Slot key identifying the specific knowledge slot (entity/attribute format, e.g., "project_name/deploy_strategy" or "postgres/max_connections"). Entries with the same claim key are candidates for supersession.'
|
|
2232
|
-
},
|
|
2233
|
-
validFrom: {
|
|
2234
|
-
type: "string",
|
|
2235
|
-
description: "ISO 8601 timestamp for when this fact became true in the world."
|
|
2236
|
-
},
|
|
2237
|
-
validTo: {
|
|
2238
|
-
type: "string",
|
|
2239
|
-
description: "ISO 8601 timestamp for when this fact stopped being true."
|
|
2240
|
-
}
|
|
2241
|
-
},
|
|
2242
|
-
required: ["type", "subject", "content"]
|
|
2243
|
-
};
|
|
2244
|
-
var RECALL_TOOL_PARAMETERS = {
|
|
2245
|
-
type: "object",
|
|
2246
|
-
additionalProperties: false,
|
|
2247
|
-
properties: {
|
|
2248
|
-
query: {
|
|
2249
|
-
type: "string",
|
|
2250
|
-
description: "What you need to remember. Use a focused natural-language query rather than a broad 'everything' search. Phrase prior-state asks directly, for example 'what was the previous approach' or 'what changed from X to Y'. Phrase procedural asks directly, for example 'how do I rotate credentials' or 'what steps should I follow'."
|
|
2251
|
-
},
|
|
2252
|
-
mode: {
|
|
2253
|
-
type: "string",
|
|
2254
|
-
enum: [...RECALL_MODES],
|
|
2255
|
-
description: "Recall mode: auto routes between exact entry recall, historical-state recall, procedural recall, and episodes; entries forces semantic recall; episodes forces temporal or semantic session recall; procedures forces procedural recall."
|
|
2256
|
-
},
|
|
2257
|
-
limit: {
|
|
2258
|
-
type: "integer",
|
|
2259
|
-
minimum: 1,
|
|
2260
|
-
maximum: 10,
|
|
2261
|
-
description: "Maximum results to return. Lower this when you want a tighter shortlist."
|
|
2262
|
-
},
|
|
2263
|
-
threshold: {
|
|
2264
|
-
type: "number",
|
|
2265
|
-
minimum: 0,
|
|
2266
|
-
maximum: 1,
|
|
2267
|
-
description: "Minimum final score from 0 to 1. Raise this when you want fewer, higher-confidence matches."
|
|
2268
|
-
},
|
|
2269
|
-
types: {
|
|
2270
|
-
type: "array",
|
|
2271
|
-
items: {
|
|
2272
|
-
type: "string",
|
|
2273
|
-
enum: [...ENTRY_TYPES]
|
|
2274
|
-
},
|
|
2275
|
-
description: "Optional knowledge types to filter by, such as decision, preference, lesson, fact, milestone, or relationship."
|
|
2276
|
-
},
|
|
2277
|
-
tags: {
|
|
2278
|
-
type: "array",
|
|
2279
|
-
items: { type: "string" },
|
|
2280
|
-
description: "Optional tags to filter by once you already know the relevant entity, system, or theme."
|
|
2281
|
-
},
|
|
2282
|
-
asOf: {
|
|
2283
|
-
type: "string",
|
|
2284
|
-
description: "Optional reference time for current-vs-prior resolution. Supports ISO timestamps and natural-language date phrases."
|
|
2285
|
-
}
|
|
2286
|
-
},
|
|
2287
|
-
required: ["query"]
|
|
2288
|
-
};
|
|
2289
|
-
var UPDATE_TOOL_PARAMETERS = {
|
|
2290
|
-
type: "object",
|
|
2291
|
-
additionalProperties: false,
|
|
2292
|
-
properties: {
|
|
2293
|
-
id: {
|
|
2294
|
-
type: "string",
|
|
2295
|
-
description: "Entry id to update. Provide exactly one of id or subject."
|
|
2296
|
-
},
|
|
2297
|
-
subject: {
|
|
2298
|
-
type: "string",
|
|
2299
|
-
description: "Subject text to resolve when the id is unknown. The most recent exact or substring match wins. Provide exactly one of id or subject."
|
|
2300
|
-
},
|
|
2301
|
-
importance: {
|
|
2302
|
-
type: "integer",
|
|
2303
|
-
description: "New importance from 1 to 10. Use 7 for normal durable memory and reserve 9 to 10 for rare critical entries."
|
|
2304
|
-
},
|
|
2305
|
-
expiry: {
|
|
2306
|
-
type: "string",
|
|
2307
|
-
description: UPDATE_EXPIRY_DESCRIPTION
|
|
2308
|
-
},
|
|
2309
|
-
claimKey: {
|
|
2310
|
-
type: "string",
|
|
2311
|
-
description: 'Slot key identifying the specific knowledge slot (entity/attribute format, e.g., "project_name/deploy_strategy" or "postgres/max_connections"). Entries with the same claim key are candidates for supersession.'
|
|
2312
|
-
},
|
|
2313
|
-
validFrom: {
|
|
2314
|
-
type: "string",
|
|
2315
|
-
description: "ISO 8601 timestamp for when this fact became true."
|
|
2316
|
-
},
|
|
2317
|
-
validTo: {
|
|
2318
|
-
type: "string",
|
|
2319
|
-
description: "ISO 8601 timestamp for when this fact stopped being true."
|
|
2320
|
-
}
|
|
2321
|
-
}
|
|
2322
|
-
};
|
|
2323
|
-
function parseStoreToolParams(rawParams, reader) {
|
|
2324
|
-
const params = asRecord(rawParams);
|
|
2325
|
-
const type = parseEntryType(reader.readString(params, "type", { required: true, label: "type" }) ?? "");
|
|
2326
|
-
return {
|
|
2327
|
-
type,
|
|
2328
|
-
subject: reader.readString(params, "subject", { required: true, label: "subject" }) ?? "",
|
|
2329
|
-
content: reader.readString(params, "content", { required: true, label: "content" }) ?? "",
|
|
2330
|
-
importance: reader.readNumber(params, "importance", { integer: true, strict: true }),
|
|
2331
|
-
expiry: parseExpiry(reader.readString(params, "expiry")),
|
|
2332
|
-
tags: normalizeStringArray(reader.readStringArray(params, "tags")),
|
|
2333
|
-
sourceContext: reader.readString(params, "sourceContext"),
|
|
2334
|
-
supersedes: reader.readString(params, "supersedes"),
|
|
2335
|
-
claimKey: reader.readString(params, "claimKey", { trim: false }),
|
|
2336
|
-
validFrom: reader.readString(params, "validFrom"),
|
|
2337
|
-
validTo: reader.readString(params, "validTo")
|
|
2338
|
-
};
|
|
2008
|
+
};
|
|
2009
|
+
function parseStoreToolParams(rawParams, reader) {
|
|
2010
|
+
const params = asRecord(rawParams);
|
|
2011
|
+
const type = parseEntryType(reader.readString(params, "type", { required: true, label: "type" }) ?? "");
|
|
2012
|
+
return {
|
|
2013
|
+
type,
|
|
2014
|
+
subject: reader.readString(params, "subject", { required: true, label: "subject" }) ?? "",
|
|
2015
|
+
content: reader.readString(params, "content", { required: true, label: "content" }) ?? "",
|
|
2016
|
+
importance: reader.readNumber(params, "importance", { integer: true, strict: true }),
|
|
2017
|
+
expiry: parseExpiry(reader.readString(params, "expiry")),
|
|
2018
|
+
tags: normalizeStringArray(reader.readStringArray(params, "tags")),
|
|
2019
|
+
sourceContext: reader.readString(params, "sourceContext"),
|
|
2020
|
+
supersedes: reader.readString(params, "supersedes"),
|
|
2021
|
+
claimKey: reader.readString(params, "claimKey", { trim: false }),
|
|
2022
|
+
validFrom: reader.readString(params, "validFrom"),
|
|
2023
|
+
validTo: reader.readString(params, "validTo")
|
|
2024
|
+
};
|
|
2339
2025
|
}
|
|
2340
2026
|
function parseRecallToolParams(rawParams, reader) {
|
|
2341
2027
|
const params = asRecord(rawParams);
|
|
2028
|
+
const budget = reader.readNumber(params, "budget", { integer: true, strict: true });
|
|
2029
|
+
if (budget !== void 0 && budget <= 0) {
|
|
2030
|
+
throw new Error("budget must be a positive integer.");
|
|
2031
|
+
}
|
|
2342
2032
|
return {
|
|
2343
2033
|
query: reader.readString(params, "query", { required: true, label: "query" }) ?? "",
|
|
2344
2034
|
mode: parseRecallMode(reader.readString(params, "mode")),
|
|
2345
2035
|
limit: reader.readNumber(params, "limit", { integer: true, strict: true }),
|
|
2346
2036
|
threshold: reader.readNumber(params, "threshold", { strict: true }),
|
|
2037
|
+
budget,
|
|
2347
2038
|
types: parseEntryTypes(reader.readStringArray(params, "types")),
|
|
2348
2039
|
tags: normalizeStringArray(reader.readStringArray(params, "tags")),
|
|
2349
2040
|
asOf: reader.readString(params, "asOf")
|
|
@@ -2361,6 +2052,13 @@ function parseUpdateToolParams(rawParams, reader) {
|
|
|
2361
2052
|
validTo: reader.readString(params, "validTo")
|
|
2362
2053
|
};
|
|
2363
2054
|
}
|
|
2055
|
+
function parseFetchToolParams(rawParams, reader) {
|
|
2056
|
+
const params = asRecord(rawParams);
|
|
2057
|
+
return {
|
|
2058
|
+
id: reader.readString(params, "id"),
|
|
2059
|
+
subject: reader.readString(params, "subject")
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2364
2062
|
async function runStoreMemoryTool(params, services, options) {
|
|
2365
2063
|
const result = await storeEntriesDetailed(
|
|
2366
2064
|
[
|
|
@@ -2430,6 +2128,7 @@ async function runRecallMemoryTool(params, services, options = {}) {
|
|
|
2430
2128
|
...params.mode ? { mode: params.mode } : {},
|
|
2431
2129
|
...params.limit !== void 0 ? { limit: params.limit } : {},
|
|
2432
2130
|
...params.threshold !== void 0 ? { threshold: params.threshold } : {},
|
|
2131
|
+
...params.budget !== void 0 ? { budget: params.budget } : {},
|
|
2433
2132
|
...params.types.length > 0 ? { types: params.types } : {},
|
|
2434
2133
|
...params.tags.length > 0 ? { tags: params.tags } : {},
|
|
2435
2134
|
...params.asOf ? { asOf: params.asOf } : {},
|
|
@@ -2450,6 +2149,11 @@ async function runRecallMemoryTool(params, services, options = {}) {
|
|
|
2450
2149
|
}
|
|
2451
2150
|
);
|
|
2452
2151
|
}
|
|
2152
|
+
async function runFetchMemoryTool(params, services, options = {}) {
|
|
2153
|
+
const entry = await resolveTargetEntry(buildEntryMemoryResolverPorts(services), { id: params.id, subject: params.subject });
|
|
2154
|
+
assertEntryFetchableContentLength(entry.content);
|
|
2155
|
+
return okOutcome(formatFetchedEntryText(entry), buildFetchToolDetails(entry, options.extraDetails));
|
|
2156
|
+
}
|
|
2453
2157
|
async function runUpdateMemoryTool(params, services, options) {
|
|
2454
2158
|
const claimSupport = params.claimKeyInput === void 0 ? void 0 : buildToolCallClaimSupport(options.session, options.sourcePrefix, "agenr_update", (/* @__PURE__ */ new Date()).toISOString());
|
|
2455
2159
|
const normalizedClaimKeyUpdate = params.claimKeyInput === void 0 ? void 0 : (() => {
|
|
@@ -2466,14 +2170,7 @@ async function runUpdateMemoryTool(params, services, options) {
|
|
|
2466
2170
|
throw new Error("claimKey must use canonical entity/attribute format.");
|
|
2467
2171
|
}
|
|
2468
2172
|
})();
|
|
2469
|
-
const entry = await resolveTargetEntry(
|
|
2470
|
-
{
|
|
2471
|
-
getEntryById: async (entryId) => await services.entries.getEntry(entryId) ?? (await services.memory.getEntryTrace(entryId))?.entry ?? null,
|
|
2472
|
-
findEntryBySubject: async (entrySubject) => services.memory.findEntryBySubject(entrySubject),
|
|
2473
|
-
findMostRecentEntry: async () => services.memory.findMostRecentEntry()
|
|
2474
|
-
},
|
|
2475
|
-
{ id: params.id, subject: params.subject }
|
|
2476
|
-
);
|
|
2173
|
+
const entry = await resolveTargetEntry(buildEntryMemoryResolverPorts(services), { id: params.id, subject: params.subject });
|
|
2477
2174
|
if (params.importance === void 0 && params.expiry === void 0 && normalizedClaimKeyUpdate === void 0 && params.validFrom === void 0 && params.validTo === void 0) {
|
|
2478
2175
|
throw new Error("Provide at least one update field: importance, expiry, claimKey, validFrom, or validTo.");
|
|
2479
2176
|
}
|
|
@@ -2516,6 +2213,234 @@ function failedOutcome(text, details) {
|
|
|
2516
2213
|
return { text, details, failed: true };
|
|
2517
2214
|
}
|
|
2518
2215
|
|
|
2216
|
+
// src/adapters/shared/recall-format.ts
|
|
2217
|
+
function formatUnifiedRecallResults(result) {
|
|
2218
|
+
const lines = [
|
|
2219
|
+
"Recall Route",
|
|
2220
|
+
`requested=${result.routing.requested} detected=${result.routing.detectedIntent} queried=${result.routing.queried.join(", ") || "none"}`,
|
|
2221
|
+
result.routing.reason,
|
|
2222
|
+
""
|
|
2223
|
+
];
|
|
2224
|
+
if (result.timeWindow) {
|
|
2225
|
+
lines.push("Resolved Time Window");
|
|
2226
|
+
lines.push(`${result.timeWindow.start} -> ${result.timeWindow.end} (${result.timeWindow.timezone}) from ${JSON.stringify(result.timeWindow.resolvedFrom)}`);
|
|
2227
|
+
lines.push("");
|
|
2228
|
+
}
|
|
2229
|
+
if (result.asOf) {
|
|
2230
|
+
lines.push("As Of");
|
|
2231
|
+
lines.push(result.asOf);
|
|
2232
|
+
lines.push("");
|
|
2233
|
+
}
|
|
2234
|
+
if (result.routing.queried.includes("procedures") || result.procedure || result.procedureCandidates.length > 0 || result.procedureNotices.length > 0) {
|
|
2235
|
+
appendProcedureMatches(lines, result);
|
|
2236
|
+
lines.push("");
|
|
2237
|
+
}
|
|
2238
|
+
const renderEntriesFirst = result.routing.detectedIntent === "historical_state";
|
|
2239
|
+
if (renderEntriesFirst) {
|
|
2240
|
+
appendEntryMatches(lines, result);
|
|
2241
|
+
lines.push("");
|
|
2242
|
+
appendClaimTransitions(lines, result);
|
|
2243
|
+
lines.push("");
|
|
2244
|
+
appendEpisodeMatches(lines, result);
|
|
2245
|
+
} else {
|
|
2246
|
+
appendEpisodeMatches(lines, result);
|
|
2247
|
+
lines.push("");
|
|
2248
|
+
appendEntryMatches(lines, result);
|
|
2249
|
+
lines.push("");
|
|
2250
|
+
appendClaimTransitions(lines, result);
|
|
2251
|
+
}
|
|
2252
|
+
if (recallResultHasTruncatedEntryPreviews(result)) {
|
|
2253
|
+
lines.push("");
|
|
2254
|
+
lines.push("Fetch Guidance");
|
|
2255
|
+
lines.push("One or more entry previews were truncated. Call agenr_fetch with id when exact stored wording is required.");
|
|
2256
|
+
}
|
|
2257
|
+
if (result.notices.length > 0) {
|
|
2258
|
+
lines.push("");
|
|
2259
|
+
lines.push("Notices");
|
|
2260
|
+
for (const notice of result.notices) {
|
|
2261
|
+
lines.push(`- ${notice}`);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
return lines.join("\n");
|
|
2265
|
+
}
|
|
2266
|
+
function appendProcedureMatches(lines, result) {
|
|
2267
|
+
lines.push("Procedure Matches");
|
|
2268
|
+
if (!result.procedure && result.procedureCandidates.length === 0) {
|
|
2269
|
+
lines.push("None.");
|
|
2270
|
+
} else {
|
|
2271
|
+
if (result.procedure) {
|
|
2272
|
+
appendCanonicalProcedure(lines, result.procedure, result.procedureCandidates);
|
|
2273
|
+
} else {
|
|
2274
|
+
lines.push("Canonical procedure: none.");
|
|
2275
|
+
}
|
|
2276
|
+
const additionalCandidates = result.procedureCandidates.filter((candidate) => candidate.procedure.id !== result.procedure?.id);
|
|
2277
|
+
if (additionalCandidates.length > 0) {
|
|
2278
|
+
lines.push("Other Candidates");
|
|
2279
|
+
for (const [index, candidate] of additionalCandidates.entries()) {
|
|
2280
|
+
lines.push(
|
|
2281
|
+
`${index + 1}. ${candidate.procedure.procedure_key} | ${candidate.procedure.title} | score ${candidate.score.toFixed(2)} | lexical=${candidate.scores.lexical.toFixed(2)} | vector=${candidate.scores.vector.toFixed(2)}`
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
if (result.procedureNotices.length > 0) {
|
|
2287
|
+
lines.push("Procedure Notices");
|
|
2288
|
+
for (const notice of result.procedureNotices) {
|
|
2289
|
+
lines.push(`- ${notice}`);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
function appendEntryMatches(lines, result) {
|
|
2294
|
+
lines.push("Entry Matches");
|
|
2295
|
+
if (result.projectedEntries.length === 0) {
|
|
2296
|
+
lines.push("None.");
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
for (const [familyIndex, family] of result.entryFamilies.entries()) {
|
|
2300
|
+
lines.push(
|
|
2301
|
+
family.claimKey ? `Family ${familyIndex + 1}. claim_key=${family.claimKey} | slot_policy=${family.slotPolicy} | primary=${family.primary.entryId} | subject=${family.subject}` : `Standalone ${familyIndex + 1}. ${family.primary.entryId} | subject=${family.subject}`
|
|
2302
|
+
);
|
|
2303
|
+
for (const [entryIndex, entry] of family.entries.entries()) {
|
|
2304
|
+
const preview = buildEntryRecallPreview(entry.recall.entry.content);
|
|
2305
|
+
lines.push(
|
|
2306
|
+
` ${entryIndex + 1}. ${entry.entryId} | ${entry.recall.entry.type} | ${entry.recall.entry.subject} | score ${entry.recall.score.toFixed(2)} | state=${entry.memoryState} | claim_status=${formatClaimStatus(entry.claimStatus)}`
|
|
2307
|
+
);
|
|
2308
|
+
lines.push(` ${preview.contentPreview}`);
|
|
2309
|
+
lines.push(` content_chars=${preview.contentChars} preview_truncated=${preview.previewTruncated ? "true" : "false"}`);
|
|
2310
|
+
lines.push(` freshness=${entry.freshness.label}`);
|
|
2311
|
+
const provenance = formatProjectedEntryProvenance(entry);
|
|
2312
|
+
if (provenance) {
|
|
2313
|
+
lines.push(` provenance=${provenance}`);
|
|
2314
|
+
}
|
|
2315
|
+
lines.push(` why_surfaced=${entry.whySurfaced.summary}`);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
function appendEpisodeMatches(lines, result) {
|
|
2320
|
+
lines.push("Episode Matches");
|
|
2321
|
+
if (result.episodes.length === 0) {
|
|
2322
|
+
lines.push("None.");
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
for (const [index, episode] of result.episodes.entries()) {
|
|
2326
|
+
lines.push(
|
|
2327
|
+
`${index + 1}. ${episode.episode.id} | ${episode.episode.source} | ${episode.episode.startedAt} -> ${episode.episode.endedAt ?? episode.episode.startedAt} | score ${episode.score.toFixed(2)}`
|
|
2328
|
+
);
|
|
2329
|
+
lines.push(` ${index < 3 ? episode.episode.summary.trim() : truncate(episode.episode.summary.trim(), ENTRY_PREVIEW_MAX_CHARS)}`);
|
|
2330
|
+
lines.push(` why_matched=${describeEpisodeMatch(episode)}`);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
function appendCanonicalProcedure(lines, procedure, candidates) {
|
|
2334
|
+
const leadCandidate = candidates.find((candidate) => candidate.procedure.id === procedure.id);
|
|
2335
|
+
lines.push(
|
|
2336
|
+
leadCandidate ? `Canonical Procedure. ${procedure.procedure_key} | ${procedure.title} | score ${leadCandidate.score.toFixed(2)}` : `Canonical Procedure. ${procedure.procedure_key} | ${procedure.title}`
|
|
2337
|
+
);
|
|
2338
|
+
lines.push(` goal=${procedure.goal}`);
|
|
2339
|
+
appendLabeledList(lines, "when_to_use", procedure.when_to_use);
|
|
2340
|
+
appendLabeledList(lines, "when_not_to_use", procedure.when_not_to_use);
|
|
2341
|
+
appendLabeledList(lines, "prerequisites", procedure.prerequisites);
|
|
2342
|
+
lines.push(" steps");
|
|
2343
|
+
for (const [index, step] of procedure.steps.entries()) {
|
|
2344
|
+
lines.push(` ${index + 1}. [${step.kind}] ${step.instruction}`);
|
|
2345
|
+
const stepDetails = formatProcedureStepDetails(step);
|
|
2346
|
+
if (stepDetails.length > 0) {
|
|
2347
|
+
for (const detail of stepDetails) {
|
|
2348
|
+
lines.push(` ${detail}`);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
appendLabeledList(lines, "verification", procedure.verification);
|
|
2353
|
+
appendLabeledList(lines, "failure_modes", procedure.failure_modes);
|
|
2354
|
+
lines.push(" sources");
|
|
2355
|
+
for (const source of procedure.sources) {
|
|
2356
|
+
lines.push(` - ${formatProcedureSource(source)}`);
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
function appendClaimTransitions(lines, result) {
|
|
2360
|
+
lines.push("Claim Transitions");
|
|
2361
|
+
if (result.claimTransitions.length === 0) {
|
|
2362
|
+
lines.push("None.");
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
for (const [index, transition] of result.claimTransitions.entries()) {
|
|
2366
|
+
lines.push(
|
|
2367
|
+
`${index + 1}. family=${transition.claimKey ?? transition.familyKey} | slot_policy=${transition.slotPolicy}${transition.currentEntryId ? ` | current=${transition.currentEntryId}` : ""}${transition.priorEntryId ? ` | prior=${transition.priorEntryId}` : ""}`
|
|
2368
|
+
);
|
|
2369
|
+
lines.push(` ${transition.summary}`);
|
|
2370
|
+
if (transition.episodeContext) {
|
|
2371
|
+
lines.push(
|
|
2372
|
+
` episode=${transition.episodeContext.episodeId} | ${transition.episodeContext.startedAt} -> ${transition.episodeContext.endedAt ?? transition.episodeContext.startedAt}`
|
|
2373
|
+
);
|
|
2374
|
+
lines.push(` ${truncate(transition.episodeContext.summary.trim(), ENTRY_PREVIEW_MAX_CHARS)}`);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
function appendLabeledList(lines, label, values) {
|
|
2379
|
+
lines.push(` ${label}`);
|
|
2380
|
+
if (values.length === 0) {
|
|
2381
|
+
lines.push(" - none");
|
|
2382
|
+
return;
|
|
2383
|
+
}
|
|
2384
|
+
for (const value of values) {
|
|
2385
|
+
lines.push(` - ${value}`);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
function formatProcedureStepDetails(step) {
|
|
2389
|
+
switch (step.kind) {
|
|
2390
|
+
case "run_command":
|
|
2391
|
+
return [`command=${step.command}`];
|
|
2392
|
+
case "read_reference":
|
|
2393
|
+
return [`ref=${formatProcedureSource(step.ref)}`];
|
|
2394
|
+
case "inspect_state":
|
|
2395
|
+
return [step.target ? `target=${step.target}` : void 0, step.query ? `query=${step.query}` : void 0].filter(
|
|
2396
|
+
(value) => value !== void 0
|
|
2397
|
+
);
|
|
2398
|
+
case "edit_file":
|
|
2399
|
+
return [`path=${step.path}`, `edit=${step.edit}`];
|
|
2400
|
+
case "ask_user":
|
|
2401
|
+
return [`prompt=${step.prompt}`];
|
|
2402
|
+
case "invoke_tool":
|
|
2403
|
+
return [step.tool ? `tool=${step.tool}` : void 0, step.arguments ? `arguments=${JSON.stringify(step.arguments)}` : void 0].filter(
|
|
2404
|
+
(value) => value !== void 0
|
|
2405
|
+
);
|
|
2406
|
+
case "verify":
|
|
2407
|
+
return step.checks.map((check) => `check=${check}`);
|
|
2408
|
+
default:
|
|
2409
|
+
return [];
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
function formatProcedureSource(source) {
|
|
2413
|
+
const parts = [source.kind, source.label, source.path, source.locator].filter((value) => Boolean(value && value.length > 0));
|
|
2414
|
+
return parts.join(" | ");
|
|
2415
|
+
}
|
|
2416
|
+
function describeEpisodeMatch(result) {
|
|
2417
|
+
if (result.scores.semantic > 0 && result.scores.temporal > 0) {
|
|
2418
|
+
return "Semantic match within the resolved time window.";
|
|
2419
|
+
}
|
|
2420
|
+
if (result.scores.semantic > 0) {
|
|
2421
|
+
return "Semantic match to the episode summary.";
|
|
2422
|
+
}
|
|
2423
|
+
if (result.scores.temporal > 0) {
|
|
2424
|
+
return "Session overlaps the resolved time window.";
|
|
2425
|
+
}
|
|
2426
|
+
return "Matched episodic recall ranking.";
|
|
2427
|
+
}
|
|
2428
|
+
function formatClaimStatus(status) {
|
|
2429
|
+
return status === "no_key" ? "no-key" : status;
|
|
2430
|
+
}
|
|
2431
|
+
function formatProjectedEntryProvenance(entry) {
|
|
2432
|
+
const parts = [
|
|
2433
|
+
entry.provenance.supersededById ? `superseded_by=${entry.provenance.supersededById}` : void 0,
|
|
2434
|
+
entry.provenance.supersessionKind ? `kind=${entry.provenance.supersessionKind}` : void 0,
|
|
2435
|
+
entry.provenance.supersessionReason ? `reason=${truncate(entry.provenance.supersessionReason, 120)}` : void 0,
|
|
2436
|
+
entry.provenance.supportSourceKind ? `support=${entry.provenance.supportSourceKind}` : void 0,
|
|
2437
|
+
entry.provenance.supportMode ? `support_mode=${entry.provenance.supportMode}` : void 0,
|
|
2438
|
+
entry.provenance.supportObservedAt ? `observed=${entry.provenance.supportObservedAt}` : void 0,
|
|
2439
|
+
entry.provenance.supportLocator ? `locator=${truncate(entry.provenance.supportLocator, 120)}` : void 0
|
|
2440
|
+
].filter((value) => value !== void 0);
|
|
2441
|
+
return parts.join(" | ");
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2519
2444
|
// src/adapters/shared/bounded-episode-summary.ts
|
|
2520
2445
|
var EPISODE_SUMMARY_TIMEOUT_MS = 45e3;
|
|
2521
2446
|
var EPISODE_SUMMARY_TIMEOUT_MESSAGE = "Episode summary generation timed out.";
|
|
@@ -2688,23 +2613,20 @@ async function writeBoundedSingleTranscriptEpisode(params) {
|
|
|
2688
2613
|
}
|
|
2689
2614
|
|
|
2690
2615
|
export {
|
|
2691
|
-
formatUnifiedRecallResults,
|
|
2692
|
-
formatErrorMessage,
|
|
2693
|
-
asRecord,
|
|
2694
|
-
formatTargetSelector,
|
|
2695
|
-
sanitizeUpdateToolParams,
|
|
2696
|
-
resolveTargetEntry,
|
|
2697
|
-
readBooleanParam,
|
|
2698
2616
|
buildRecallToolServices,
|
|
2699
2617
|
STORE_TOOL_PARAMETERS,
|
|
2700
2618
|
RECALL_TOOL_PARAMETERS,
|
|
2701
2619
|
UPDATE_TOOL_PARAMETERS,
|
|
2620
|
+
FETCH_TOOL_PARAMETERS,
|
|
2702
2621
|
parseStoreToolParams,
|
|
2703
2622
|
parseRecallToolParams,
|
|
2704
2623
|
parseUpdateToolParams,
|
|
2624
|
+
parseFetchToolParams,
|
|
2705
2625
|
runStoreMemoryTool,
|
|
2706
2626
|
runRecallMemoryTool,
|
|
2627
|
+
runFetchMemoryTool,
|
|
2707
2628
|
runUpdateMemoryTool,
|
|
2629
|
+
formatUnifiedRecallResults,
|
|
2708
2630
|
normalizeOptionalBoolean,
|
|
2709
2631
|
normalizeOptionalPositiveInteger,
|
|
2710
2632
|
normalizePluginInjectionMemoryPolicyConfig,
|