@botbotgo/agent-harness 0.0.142 → 0.0.145
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/config/runtime/runtime-memory.yaml +5 -3
- package/dist/contracts/runtime.d.ts +14 -0
- package/dist/init-project.js +5 -3
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/adapter/flow/invocation-flow.d.ts +2 -0
- package/dist/runtime/adapter/flow/stream-runtime.d.ts +2 -0
- package/dist/runtime/adapter/flow/stream-runtime.js +1 -1
- package/dist/runtime/adapter/invocation-result.d.ts +2 -1
- package/dist/runtime/adapter/invocation-result.js +2 -0
- package/dist/runtime/adapter/local-tool-invocation.js +12 -0
- package/dist/runtime/adapter/model/invocation-request.d.ts +1 -0
- package/dist/runtime/adapter/model/invocation-request.js +13 -3
- package/dist/runtime/adapter/model/message-assembly.d.ts +1 -1
- package/dist/runtime/adapter/model/message-assembly.js +12 -1
- package/dist/runtime/agent-runtime-adapter.d.ts +2 -0
- package/dist/runtime/harness/run/stream-run.d.ts +2 -0
- package/dist/runtime/harness/run/stream-run.js +1 -0
- package/dist/runtime/harness/system/runtime-memory-candidates.d.ts +3 -0
- package/dist/runtime/harness/system/runtime-memory-candidates.js +110 -0
- package/dist/runtime/harness/system/runtime-memory-policy.d.ts +18 -0
- package/dist/runtime/harness/system/runtime-memory-policy.js +73 -0
- package/dist/runtime/harness.d.ts +5 -0
- package/dist/runtime/harness.js +124 -2
- package/dist/tool-modules.d.ts +7 -0
- package/dist/tool-modules.js +1 -0
- package/dist/tools.d.ts +14 -0
- package/dist/workspace/object-loader.js +1 -0
- package/package.json +1 -1
|
@@ -28,9 +28,11 @@ spec:
|
|
|
28
28
|
|
|
29
29
|
# agent-harness feature: stable namespace roots used by the runtime memory policy layer.
|
|
30
30
|
namespaces:
|
|
31
|
-
users: memories/users
|
|
32
|
-
projects: memories/projects
|
|
33
|
-
threads: memories/threads
|
|
31
|
+
users: memories/users/{userId}
|
|
32
|
+
projects: memories/projects/{projectId}
|
|
33
|
+
threads: memories/threads/{threadId}
|
|
34
|
+
agents: memories/agents/{agentId}
|
|
35
|
+
workspaces: memories/workspaces/{workspaceId}
|
|
34
36
|
|
|
35
37
|
# agent-harness feature: retrieval defaults for selecting a bounded number of relevant memories per turn.
|
|
36
38
|
retrieval:
|
|
@@ -97,6 +97,20 @@ export type RuntimeSnapshot = {
|
|
|
97
97
|
skills: RuntimeSnapshotSkill[];
|
|
98
98
|
memory: string[];
|
|
99
99
|
};
|
|
100
|
+
export type MemoryCandidate = {
|
|
101
|
+
content: string;
|
|
102
|
+
summary?: string;
|
|
103
|
+
kind?: string;
|
|
104
|
+
scope?: string;
|
|
105
|
+
confidence?: number;
|
|
106
|
+
tags?: string[];
|
|
107
|
+
sourceType?: string;
|
|
108
|
+
sourceRef?: string;
|
|
109
|
+
observedAt?: string;
|
|
110
|
+
sensitivity?: string;
|
|
111
|
+
noStore?: boolean;
|
|
112
|
+
provenance?: Record<string, unknown>;
|
|
113
|
+
};
|
|
100
114
|
/**
|
|
101
115
|
* Operator-facing projection of tool execution policy already compiled into a binding.
|
|
102
116
|
* This summarizes existing timeout, retry, validation, and retry-safety hints without
|
package/dist/init-project.js
CHANGED
|
@@ -139,9 +139,11 @@ metadata:
|
|
|
139
139
|
spec:
|
|
140
140
|
enabled: true
|
|
141
141
|
namespaces:
|
|
142
|
-
users: memories/users
|
|
143
|
-
projects: memories/projects
|
|
144
|
-
threads: memories/threads
|
|
142
|
+
users: memories/users/{userId}
|
|
143
|
+
projects: memories/projects/{projectId}
|
|
144
|
+
threads: memories/threads/{threadId}
|
|
145
|
+
agents: memories/agents/{agentId}
|
|
146
|
+
workspaces: memories/workspaces/{workspaceId}
|
|
145
147
|
retrieval:
|
|
146
148
|
defaultTopK: 5
|
|
147
149
|
maxPromptMemories: 8
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.144";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.144";
|
|
@@ -12,6 +12,7 @@ export declare function executeRuntimeInvocation(options: {
|
|
|
12
12
|
context?: Record<string, unknown>;
|
|
13
13
|
state?: Record<string, unknown>;
|
|
14
14
|
files?: Record<string, unknown>;
|
|
15
|
+
memoryContext?: string;
|
|
15
16
|
};
|
|
16
17
|
resolveTools: (tools: CompiledTool[], binding?: CompiledAgentBinding) => unknown[];
|
|
17
18
|
getToolNameMapping: (binding: CompiledAgentBinding) => ToolNameMapping;
|
|
@@ -19,6 +20,7 @@ export declare function executeRuntimeInvocation(options: {
|
|
|
19
20
|
context?: Record<string, unknown>;
|
|
20
21
|
state?: Record<string, unknown>;
|
|
21
22
|
files?: Record<string, unknown>;
|
|
23
|
+
memoryContext?: string;
|
|
22
24
|
}) => Promise<Map<string, ExecutableTool>>;
|
|
23
25
|
callRuntimeWithToolParseRecovery: (request: unknown) => Promise<Record<string, unknown>>;
|
|
24
26
|
}): Promise<RunResult>;
|
|
@@ -15,6 +15,7 @@ export declare function streamRuntimeExecution(options: {
|
|
|
15
15
|
state?: Record<string, unknown>;
|
|
16
16
|
files?: Record<string, unknown>;
|
|
17
17
|
runId?: string;
|
|
18
|
+
memoryContext?: string;
|
|
18
19
|
};
|
|
19
20
|
primaryTools: CompiledTool[];
|
|
20
21
|
toolNameMapping: ToolNameMapping;
|
|
@@ -33,6 +34,7 @@ export declare function streamRuntimeExecution(options: {
|
|
|
33
34
|
context?: Record<string, unknown>;
|
|
34
35
|
state?: Record<string, unknown>;
|
|
35
36
|
files?: Record<string, unknown>;
|
|
37
|
+
memoryContext?: string;
|
|
36
38
|
}) => Promise<{
|
|
37
39
|
output: string;
|
|
38
40
|
metadata?: Record<string, unknown>;
|
|
@@ -8,7 +8,7 @@ export async function* streamRuntimeExecution(options) {
|
|
|
8
8
|
const request = buildInvocationRequest(options.binding, options.history, options.input, options.runtimeOptions);
|
|
9
9
|
try {
|
|
10
10
|
if (options.isLangChainBinding(options.binding) && options.canUseDirectModelStream && options.langChainStreamModel?.stream) {
|
|
11
|
-
const stream = await options.withTimeout(() => options.langChainStreamModel.stream(buildRawModelMessages(options.binding, options.getSystemPrompt(options.binding), options.history, options.input)), computeRemainingTimeoutMs(options.streamDeadlineAt, options.invokeTimeoutMs), "model stream start", "stream");
|
|
11
|
+
const stream = await options.withTimeout(() => options.langChainStreamModel.stream(buildRawModelMessages(options.binding, options.getSystemPrompt(options.binding), options.history, options.input, options.runtimeOptions.memoryContext)), computeRemainingTimeoutMs(options.streamDeadlineAt, options.invokeTimeoutMs), "model stream start", "stream");
|
|
12
12
|
let emitted = false;
|
|
13
13
|
const projected = projectTextStreamChunks(options.iterateWithTimeout(stream, options.streamIdleTimeoutMs, "model stream", options.streamDeadlineAt, options.invokeTimeoutMs));
|
|
14
14
|
let nextChunk = await projected.next();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { RunResult } from "../../contracts/types.js";
|
|
1
|
+
import type { MemoryCandidate, RunResult } from "../../contracts/types.js";
|
|
2
2
|
export type ExecutedToolResult = {
|
|
3
3
|
toolName: string;
|
|
4
4
|
output: unknown;
|
|
5
5
|
isError?: boolean;
|
|
6
|
+
memoryCandidates?: MemoryCandidate[];
|
|
6
7
|
};
|
|
7
8
|
export declare function finalizeInvocationResult(params: {
|
|
8
9
|
bindingAgentId: string;
|
|
@@ -18,6 +18,7 @@ export function finalizeInvocationResult(params) {
|
|
|
18
18
|
const structuredResponse = result.structuredResponse;
|
|
19
19
|
const files = asRecord(result.files);
|
|
20
20
|
const stateSnapshot = buildStateSnapshot(result);
|
|
21
|
+
const memoryCandidates = executedToolResults.flatMap((toolResult) => toolResult.memoryCandidates ?? []);
|
|
21
22
|
return {
|
|
22
23
|
threadId,
|
|
23
24
|
runId,
|
|
@@ -31,6 +32,7 @@ export function finalizeInvocationResult(params) {
|
|
|
31
32
|
...(structuredResponse !== undefined ? { structuredResponse } : {}),
|
|
32
33
|
metadata: {
|
|
33
34
|
...(executedToolResults.length > 0 ? { executedToolResults } : {}),
|
|
35
|
+
...(memoryCandidates.length > 0 ? { memoryCandidates } : {}),
|
|
34
36
|
...(structuredResponse !== undefined ? { structuredResponse } : {}),
|
|
35
37
|
...(outputContent !== undefined ? { outputContent } : {}),
|
|
36
38
|
...(contentBlocks.length > 0 ? { contentBlocks } : {}),
|
|
@@ -2,6 +2,7 @@ import { ToolMessage } from "@langchain/core/messages";
|
|
|
2
2
|
import { createModelFacingToolNameLookupCandidates, resolveModelFacingToolName } from "./tool/tool-name-mapping.js";
|
|
3
3
|
import { canReplayToolCallsLocally } from "./tool/tool-replay.js";
|
|
4
4
|
import { extractToolCallsFromResult, normalizeToolArgsForSchema, stringifyToolOutput } from "./tool/tool-arguments.js";
|
|
5
|
+
import { extractMemoryCandidatesFromToolOutput } from "../harness/system/runtime-memory-candidates.js";
|
|
5
6
|
export async function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, }) {
|
|
6
7
|
const executedToolResults = [];
|
|
7
8
|
let activeRequest = request;
|
|
@@ -9,6 +10,14 @@ export async function runLocalToolInvocationLoop({ binding, request, primaryTool
|
|
|
9
10
|
const maxToolIterations = 8;
|
|
10
11
|
let pendingResult;
|
|
11
12
|
let result;
|
|
13
|
+
const toolCatalog = new Map();
|
|
14
|
+
for (const tool of primaryTools) {
|
|
15
|
+
toolCatalog.set(tool.name, tool);
|
|
16
|
+
const modelFacingName = toolNameMapping.originalToModelFacing.get(tool.name);
|
|
17
|
+
if (modelFacingName) {
|
|
18
|
+
toolCatalog.set(modelFacingName, tool);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
12
21
|
for (let iteration = 0; iteration < maxToolIterations; iteration += 1) {
|
|
13
22
|
result = pendingResult ?? await callRuntimeWithToolParseRecovery(activeRequest);
|
|
14
23
|
pendingResult = undefined;
|
|
@@ -39,11 +48,14 @@ export async function runLocalToolInvocationLoop({ binding, request, primaryTool
|
|
|
39
48
|
if (!activeExecutable) {
|
|
40
49
|
throw new Error(`Tool ${toolCall.name} is not configured for this agent.`);
|
|
41
50
|
}
|
|
51
|
+
const compiledTool = toolCatalog.get(toolCall.name) ?? toolCatalog.get(resolvedToolName);
|
|
42
52
|
const normalizedArgs = normalizeToolArgsForSchema(toolCall.args, activeExecutable.schema);
|
|
43
53
|
const toolResult = await activeExecutable.invoke(normalizedArgs);
|
|
54
|
+
const memoryCandidates = compiledTool ? extractMemoryCandidatesFromToolOutput(compiledTool, toolResult) : [];
|
|
44
55
|
executedToolResults.push({
|
|
45
56
|
toolName: activeExecutable.name,
|
|
46
57
|
output: toolResult,
|
|
58
|
+
...(memoryCandidates.length > 0 ? { memoryCandidates } : {}),
|
|
47
59
|
});
|
|
48
60
|
nextMessages.push(new ToolMessage({
|
|
49
61
|
name: activeExecutable.name,
|
|
@@ -7,4 +7,5 @@ export declare function buildSlashCommandSkillInstruction(binding: CompiledAgent
|
|
|
7
7
|
export declare function buildInvocationRequest(binding: CompiledAgentBinding, history: TranscriptMessage[], input: MessageContent, options?: {
|
|
8
8
|
state?: Record<string, unknown>;
|
|
9
9
|
files?: Record<string, unknown>;
|
|
10
|
+
memoryContext?: string;
|
|
10
11
|
}): Record<string, unknown>;
|
|
@@ -37,11 +37,21 @@ export function buildSlashCommandSkillInstruction(binding, input) {
|
|
|
37
37
|
export function buildInvocationRequest(binding, history, input, options = {}) {
|
|
38
38
|
const userInvocableInstruction = buildSlashCommandSkillInstruction(binding, input);
|
|
39
39
|
const messages = buildAgentMessages(history, input);
|
|
40
|
+
const memoryInstruction = typeof options.memoryContext === "string" && options.memoryContext.trim().length > 0
|
|
41
|
+
? [
|
|
42
|
+
"Relevant durable memory was retrieved for this run.",
|
|
43
|
+
"Use it when it is still applicable, but prefer fresher direct evidence if there is any conflict.",
|
|
44
|
+
"",
|
|
45
|
+
options.memoryContext.trim(),
|
|
46
|
+
].join("\n")
|
|
47
|
+
: undefined;
|
|
40
48
|
return {
|
|
41
49
|
...(options.state ?? {}),
|
|
42
50
|
...(options.files ? { files: options.files } : {}),
|
|
43
|
-
messages:
|
|
44
|
-
? [{ role: "system", content:
|
|
45
|
-
:
|
|
51
|
+
messages: [
|
|
52
|
+
...(memoryInstruction ? [{ role: "system", content: memoryInstruction }] : []),
|
|
53
|
+
...(userInvocableInstruction ? [{ role: "system", content: userInvocableInstruction }] : []),
|
|
54
|
+
...messages,
|
|
55
|
+
],
|
|
46
56
|
};
|
|
47
57
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CompiledAgentBinding, MessageContent, TranscriptMessage } from "../../../contracts/types.js";
|
|
2
2
|
export declare function buildStateSnapshot(result: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
3
|
-
export declare function buildRawModelMessages(binding: CompiledAgentBinding, systemPrompt: string | undefined, history: TranscriptMessage[], input: MessageContent): Array<{
|
|
3
|
+
export declare function buildRawModelMessages(binding: CompiledAgentBinding, systemPrompt: string | undefined, history: TranscriptMessage[], input: MessageContent, memoryContext?: string): Array<{
|
|
4
4
|
role: string;
|
|
5
5
|
content: MessageContent;
|
|
6
6
|
}>;
|
|
@@ -7,11 +7,22 @@ export function buildStateSnapshot(result) {
|
|
|
7
7
|
delete snapshot.files;
|
|
8
8
|
return Object.keys(snapshot).length > 0 ? snapshot : undefined;
|
|
9
9
|
}
|
|
10
|
-
export function buildRawModelMessages(binding, systemPrompt, history, input) {
|
|
10
|
+
export function buildRawModelMessages(binding, systemPrompt, history, input, memoryContext) {
|
|
11
11
|
const messages = [];
|
|
12
12
|
if (systemPrompt) {
|
|
13
13
|
messages.push({ role: "system", content: systemPrompt });
|
|
14
14
|
}
|
|
15
|
+
if (memoryContext?.trim()) {
|
|
16
|
+
messages.push({
|
|
17
|
+
role: "system",
|
|
18
|
+
content: [
|
|
19
|
+
"Relevant durable memory was retrieved for this run.",
|
|
20
|
+
"Use it when it still applies, but prefer fresher direct evidence if there is any conflict.",
|
|
21
|
+
"",
|
|
22
|
+
memoryContext.trim(),
|
|
23
|
+
].join("\n"),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
15
26
|
const userInvocableInstruction = buildSlashCommandSkillInstruction(binding, input);
|
|
16
27
|
if (userInvocableInstruction) {
|
|
17
28
|
messages.push({ role: "system", content: userInvocableInstruction });
|
|
@@ -80,12 +80,14 @@ export declare class AgentRuntimeAdapter {
|
|
|
80
80
|
context?: Record<string, unknown>;
|
|
81
81
|
state?: Record<string, unknown>;
|
|
82
82
|
files?: Record<string, unknown>;
|
|
83
|
+
memoryContext?: string;
|
|
83
84
|
}): Promise<RunResult>;
|
|
84
85
|
stream(binding: CompiledAgentBinding, input: MessageContent, threadId: string, history?: TranscriptMessage[], options?: {
|
|
85
86
|
context?: Record<string, unknown>;
|
|
86
87
|
state?: Record<string, unknown>;
|
|
87
88
|
files?: Record<string, unknown>;
|
|
88
89
|
runId?: string;
|
|
90
|
+
memoryContext?: string;
|
|
89
91
|
}): AsyncGenerator<RuntimeStreamChunk | string>;
|
|
90
92
|
}
|
|
91
93
|
export { AgentRuntimeAdapter as RuntimeAdapter, AGENT_INTERRUPT_SENTINEL_PREFIX, AGENT_INTERRUPT_SENTINEL_PREFIX as INTERRUPT_SENTINEL_PREFIX, RuntimeOperationTimeoutError, };
|
|
@@ -15,6 +15,7 @@ type StreamRunOptions = {
|
|
|
15
15
|
context?: Record<string, unknown>;
|
|
16
16
|
state?: Record<string, unknown>;
|
|
17
17
|
files?: Record<string, unknown>;
|
|
18
|
+
memoryContext?: string;
|
|
18
19
|
};
|
|
19
20
|
threadId: string;
|
|
20
21
|
runId: string;
|
|
@@ -28,6 +29,7 @@ type StreamRunOptions = {
|
|
|
28
29
|
state?: Record<string, unknown>;
|
|
29
30
|
files?: Record<string, unknown>;
|
|
30
31
|
runId: string;
|
|
32
|
+
memoryContext?: string;
|
|
31
33
|
}) => AsyncIterable<RuntimeStreamChunk>;
|
|
32
34
|
invokeWithHistory: (binding: CompiledAgentBinding, input: MessageContent, threadId: string, runId: string) => Promise<RunResult>;
|
|
33
35
|
emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<HarnessEvent>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CompiledTool, MemoryCandidate } from "../../../contracts/types.js";
|
|
2
|
+
export declare function extractMemoryCandidatesFromToolOutput(tool: CompiledTool, output: unknown): MemoryCandidate[];
|
|
3
|
+
export declare function renderMemoryCandidatesMarkdown(title: string, candidates: MemoryCandidate[]): string;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
function asRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
3
|
+
}
|
|
4
|
+
function asString(value) {
|
|
5
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
6
|
+
}
|
|
7
|
+
function asNumber(value) {
|
|
8
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
9
|
+
}
|
|
10
|
+
function asStringArray(value) {
|
|
11
|
+
if (!Array.isArray(value)) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const items = value
|
|
15
|
+
.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
16
|
+
.map((item) => item.trim());
|
|
17
|
+
return items.length > 0 ? items : undefined;
|
|
18
|
+
}
|
|
19
|
+
function stringifyCandidateContent(output) {
|
|
20
|
+
if (typeof output === "string") {
|
|
21
|
+
return output.trim();
|
|
22
|
+
}
|
|
23
|
+
if (typeof output === "number" || typeof output === "boolean") {
|
|
24
|
+
return String(output);
|
|
25
|
+
}
|
|
26
|
+
if (typeof output === "object" && output !== null) {
|
|
27
|
+
try {
|
|
28
|
+
return JSON.stringify(output, null, 2);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
function normalizeCandidate(value, fallback) {
|
|
37
|
+
const record = asRecord(value);
|
|
38
|
+
if (!record) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const content = asString(record.content);
|
|
42
|
+
if (!content) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
content,
|
|
47
|
+
...(asString(record.summary) ? { summary: asString(record.summary) } : {}),
|
|
48
|
+
...(asString(record.kind) ?? fallback.kind ? { kind: asString(record.kind) ?? fallback.kind } : {}),
|
|
49
|
+
...(asString(record.scope) ?? fallback.scope ? { scope: asString(record.scope) ?? fallback.scope } : {}),
|
|
50
|
+
...(asNumber(record.confidence) !== undefined ? { confidence: asNumber(record.confidence) } : {}),
|
|
51
|
+
...(asStringArray(record.tags) ?? fallback.tags ? { tags: asStringArray(record.tags) ?? fallback.tags } : {}),
|
|
52
|
+
...(asString(record.sourceType) ?? fallback.sourceType ? { sourceType: asString(record.sourceType) ?? fallback.sourceType } : {}),
|
|
53
|
+
...(asString(record.sourceRef) ? { sourceRef: asString(record.sourceRef) } : {}),
|
|
54
|
+
...(asString(record.observedAt) ? { observedAt: asString(record.observedAt) } : {}),
|
|
55
|
+
...(asString(record.sensitivity) ? { sensitivity: asString(record.sensitivity) } : {}),
|
|
56
|
+
...(typeof record.noStore === "boolean" ? { noStore: record.noStore } : {}),
|
|
57
|
+
...(asRecord(record.provenance) ? { provenance: asRecord(record.provenance) } : {}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function extractMemoryCandidatesFromToolOutput(tool, output) {
|
|
61
|
+
const memoryConfig = asRecord(tool.config?.memory);
|
|
62
|
+
if (memoryConfig?.enabled !== true) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
const fallback = {
|
|
66
|
+
sourceType: "tool-output",
|
|
67
|
+
kind: asString(memoryConfig.kind),
|
|
68
|
+
scope: asString(memoryConfig.scope) ?? "thread",
|
|
69
|
+
tags: asStringArray(memoryConfig.tags),
|
|
70
|
+
};
|
|
71
|
+
const explicitCandidates = asRecord(output)?.memoryCandidates;
|
|
72
|
+
if (Array.isArray(explicitCandidates)) {
|
|
73
|
+
const maxCandidates = asNumber(memoryConfig.maxCandidates) ?? explicitCandidates.length;
|
|
74
|
+
return explicitCandidates
|
|
75
|
+
.map((candidate) => normalizeCandidate(candidate, fallback))
|
|
76
|
+
.filter((candidate) => Boolean(candidate))
|
|
77
|
+
.slice(0, maxCandidates);
|
|
78
|
+
}
|
|
79
|
+
const content = stringifyCandidateContent(output);
|
|
80
|
+
if (!content) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
return [{
|
|
84
|
+
content,
|
|
85
|
+
...(fallback.kind ? { kind: fallback.kind } : {}),
|
|
86
|
+
...(fallback.scope ? { scope: fallback.scope } : {}),
|
|
87
|
+
...(fallback.tags ? { tags: fallback.tags } : {}),
|
|
88
|
+
sourceType: fallback.sourceType,
|
|
89
|
+
}];
|
|
90
|
+
}
|
|
91
|
+
export function renderMemoryCandidatesMarkdown(title, candidates) {
|
|
92
|
+
const lines = [`# ${title}`, ""];
|
|
93
|
+
if (candidates.length === 0) {
|
|
94
|
+
lines.push("(none)", "");
|
|
95
|
+
return lines.join("\n");
|
|
96
|
+
}
|
|
97
|
+
for (const candidate of candidates) {
|
|
98
|
+
lines.push(`## ${(candidate.summary ?? candidate.content).split("\n")[0].slice(0, 120)}`);
|
|
99
|
+
lines.push(`- kind: ${candidate.kind ?? "summary"}`);
|
|
100
|
+
lines.push(`- scope: ${candidate.scope ?? "thread"}`);
|
|
101
|
+
lines.push(`- source_type: ${candidate.sourceType ?? "tool-output"}`);
|
|
102
|
+
if (candidate.tags && candidate.tags.length > 0) {
|
|
103
|
+
lines.push(`- tags: ${candidate.tags.join(", ")}`);
|
|
104
|
+
}
|
|
105
|
+
lines.push("");
|
|
106
|
+
lines.push(candidate.summary ?? candidate.content);
|
|
107
|
+
lines.push("");
|
|
108
|
+
}
|
|
109
|
+
return lines.join("\n");
|
|
110
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type ResolvedRuntimeMemoryPolicyConfig = {
|
|
2
|
+
enabled: true;
|
|
3
|
+
retrieval: {
|
|
4
|
+
defaultTopK: number;
|
|
5
|
+
maxPromptMemories: number;
|
|
6
|
+
};
|
|
7
|
+
namespaces: {
|
|
8
|
+
thread: string;
|
|
9
|
+
workspace: string;
|
|
10
|
+
agent: string;
|
|
11
|
+
user: string;
|
|
12
|
+
project: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare function normalizeLangMemMemoryKind(kind: string | undefined): "semantic" | "episodic" | "procedural";
|
|
16
|
+
export declare function readRuntimeMemoryPolicyConfig(runtimeMemory: Record<string, unknown> | undefined, workspaceRoot: string): ResolvedRuntimeMemoryPolicyConfig | undefined;
|
|
17
|
+
export declare function resolveMemoryNamespace(template: string, values: Record<string, string | undefined>): string[];
|
|
18
|
+
export declare function scoreMemoryText(query: string, content: string, scopeBoost?: number): number;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
function asRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
4
|
+
}
|
|
5
|
+
function asString(value) {
|
|
6
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
7
|
+
}
|
|
8
|
+
function asPositiveInteger(value) {
|
|
9
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
|
|
10
|
+
}
|
|
11
|
+
export function normalizeLangMemMemoryKind(kind) {
|
|
12
|
+
const normalized = kind?.trim().toLowerCase();
|
|
13
|
+
if (!normalized) {
|
|
14
|
+
return "semantic";
|
|
15
|
+
}
|
|
16
|
+
if (["episode", "episodic", "summary", "experience", "reflection"].includes(normalized)) {
|
|
17
|
+
return "episodic";
|
|
18
|
+
}
|
|
19
|
+
if (["procedural", "workflow", "procedure", "runbook", "playbook"].includes(normalized)) {
|
|
20
|
+
return "procedural";
|
|
21
|
+
}
|
|
22
|
+
return "semantic";
|
|
23
|
+
}
|
|
24
|
+
export function readRuntimeMemoryPolicyConfig(runtimeMemory, workspaceRoot) {
|
|
25
|
+
if (runtimeMemory?.enabled !== true) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const retrieval = asRecord(runtimeMemory.retrieval);
|
|
29
|
+
const namespaces = asRecord(runtimeMemory.namespaces);
|
|
30
|
+
const workspaceId = path.basename(workspaceRoot) || "default";
|
|
31
|
+
return {
|
|
32
|
+
enabled: true,
|
|
33
|
+
retrieval: {
|
|
34
|
+
defaultTopK: asPositiveInteger(retrieval?.defaultTopK) ?? 5,
|
|
35
|
+
maxPromptMemories: asPositiveInteger(retrieval?.maxPromptMemories) ?? 8,
|
|
36
|
+
},
|
|
37
|
+
namespaces: {
|
|
38
|
+
thread: asString(namespaces?.threads) ?? "memories/threads/{threadId}",
|
|
39
|
+
workspace: asString(namespaces?.workspaces) ?? `memories/workspaces/${workspaceId}`,
|
|
40
|
+
agent: asString(namespaces?.agents) ?? "memories/agents/{agentId}",
|
|
41
|
+
user: asString(namespaces?.users) ?? "memories/users/{userId}",
|
|
42
|
+
project: asString(namespaces?.projects) ?? "memories/projects/{projectId}",
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function resolveMemoryNamespace(template, values) {
|
|
47
|
+
const rendered = template.replace(/\{([a-zA-Z0-9_]+)\}/g, (_match, key) => values[key] ?? key);
|
|
48
|
+
return rendered
|
|
49
|
+
.split("/")
|
|
50
|
+
.map((part) => part.trim())
|
|
51
|
+
.filter((part) => part.length > 0);
|
|
52
|
+
}
|
|
53
|
+
function tokenize(text) {
|
|
54
|
+
return text
|
|
55
|
+
.toLowerCase()
|
|
56
|
+
.split(/[^a-z0-9_]+/i)
|
|
57
|
+
.map((token) => token.trim())
|
|
58
|
+
.filter((token) => token.length > 2);
|
|
59
|
+
}
|
|
60
|
+
export function scoreMemoryText(query, content, scopeBoost = 0) {
|
|
61
|
+
const queryTokens = new Set(tokenize(query));
|
|
62
|
+
if (queryTokens.size === 0) {
|
|
63
|
+
return scopeBoost;
|
|
64
|
+
}
|
|
65
|
+
const contentTokens = tokenize(content);
|
|
66
|
+
let overlap = 0;
|
|
67
|
+
for (const token of contentTokens) {
|
|
68
|
+
if (queryTokens.has(token)) {
|
|
69
|
+
overlap += 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return overlap + scopeBoost;
|
|
73
|
+
}
|
|
@@ -19,6 +19,7 @@ export declare class AgentHarnessRuntime {
|
|
|
19
19
|
private readonly defaultRunRootValue;
|
|
20
20
|
private readonly defaultStore;
|
|
21
21
|
private readonly runtimeMemoryStore;
|
|
22
|
+
private readonly runtimeMemoryPolicy;
|
|
22
23
|
private readonly routingRules;
|
|
23
24
|
private readonly routingDefaultAgentId?;
|
|
24
25
|
private readonly threadMemorySync;
|
|
@@ -90,6 +91,10 @@ export declare class AgentHarnessRuntime {
|
|
|
90
91
|
private getRunCancellation;
|
|
91
92
|
private finalizeCancelledRun;
|
|
92
93
|
private invokeWithHistory;
|
|
94
|
+
private resolveMemoryNamespace;
|
|
95
|
+
private buildRuntimeMemoryContext;
|
|
96
|
+
private persistRuntimeMemoryCandidates;
|
|
97
|
+
private appendMemoryDigest;
|
|
93
98
|
private resolvePersistedRunPriority;
|
|
94
99
|
private enqueuePendingRunSlot;
|
|
95
100
|
private executeQueuedRun;
|
package/dist/runtime/harness.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import { SqlitePersistence } from "../persistence/sqlite-store.js";
|
|
2
3
|
import { createPersistentId } from "../utils/id.js";
|
|
3
4
|
import { AgentRuntimeAdapter } from "./agent-runtime-adapter.js";
|
|
@@ -28,6 +29,8 @@ import { bindingSupportsRunningReplay, getWorkspaceBinding, resolveWorkspaceAgen
|
|
|
28
29
|
import { describeWorkspaceInventory, getAgentInventoryRecord, listAgentSkills as listWorkspaceAgentSkills, } from "./harness/system/inventory.js";
|
|
29
30
|
import { createDefaultHealthSnapshot, isInventoryEnabled, isThreadMemorySyncEnabled, } from "./harness/runtime-defaults.js";
|
|
30
31
|
import { Mem0IngestionSync, readMem0RuntimeConfig } from "./harness/system/mem0-ingestion-sync.js";
|
|
32
|
+
import { renderMemoryCandidatesMarkdown } from "./harness/system/runtime-memory-candidates.js";
|
|
33
|
+
import { normalizeLangMemMemoryKind, readRuntimeMemoryPolicyConfig, resolveMemoryNamespace, scoreMemoryText, } from "./harness/system/runtime-memory-policy.js";
|
|
31
34
|
import { resolveRuntimeAdapterOptions } from "./support/runtime-adapter-options.js";
|
|
32
35
|
import { initializeHarnessRuntime, reclaimExpiredClaimedRuns as reclaimHarnessExpiredClaimedRuns, recoverStartupRuns as recoverHarnessStartupRuns, isStaleRunningRun as isHarnessStaleRunningRun, } from "./harness/run/startup-runtime.js";
|
|
33
36
|
import { streamHarnessRun } from "./harness/run/stream-run.js";
|
|
@@ -55,6 +58,7 @@ export class AgentHarnessRuntime {
|
|
|
55
58
|
defaultRunRootValue;
|
|
56
59
|
defaultStore;
|
|
57
60
|
runtimeMemoryStore;
|
|
61
|
+
runtimeMemoryPolicy;
|
|
58
62
|
routingRules;
|
|
59
63
|
routingDefaultAgentId;
|
|
60
64
|
threadMemorySync;
|
|
@@ -118,6 +122,7 @@ export class AgentHarnessRuntime {
|
|
|
118
122
|
? this.defaultRuntimeEntryBinding.harnessRuntime.runtimeMemory.store
|
|
119
123
|
: undefined;
|
|
120
124
|
this.runtimeMemoryStore = resolveStoreFromConfig(this.stores, runtimeMemoryStoreConfig, runRoot) ?? this.defaultStore;
|
|
125
|
+
this.runtimeMemoryPolicy = readRuntimeMemoryPolicyConfig(this.defaultRuntimeEntryBinding?.harnessRuntime.runtimeMemory, this.workspace.workspaceRoot) ?? null;
|
|
121
126
|
this.resolvedRuntimeAdapterOptions = resolveRuntimeAdapterOptions({
|
|
122
127
|
workspace,
|
|
123
128
|
runtimeAdapterOptions,
|
|
@@ -349,9 +354,14 @@ export class AgentHarnessRuntime {
|
|
|
349
354
|
}
|
|
350
355
|
async invokeWithHistory(binding, input, threadId, runId, resumePayload, priorHistory, options = {}) {
|
|
351
356
|
const history = priorHistory ?? await this.loadPriorHistory(threadId, runId);
|
|
357
|
+
const memoryContext = options.memoryContext ?? await this.buildRuntimeMemoryContext(binding, threadId, input);
|
|
352
358
|
const startedAt = Date.now();
|
|
353
359
|
try {
|
|
354
|
-
const result = await this.runtimeAdapter.invoke(binding, input, threadId, runId, resumePayload, history,
|
|
360
|
+
const result = await this.runtimeAdapter.invoke(binding, input, threadId, runId, resumePayload, history, {
|
|
361
|
+
...options,
|
|
362
|
+
...(memoryContext ? { memoryContext } : {}),
|
|
363
|
+
});
|
|
364
|
+
await this.persistRuntimeMemoryCandidates(binding, threadId, runId, result.metadata?.memoryCandidates);
|
|
355
365
|
this.recordLlmSuccess(startedAt);
|
|
356
366
|
return result;
|
|
357
367
|
}
|
|
@@ -360,6 +370,115 @@ export class AgentHarnessRuntime {
|
|
|
360
370
|
throw error;
|
|
361
371
|
}
|
|
362
372
|
}
|
|
373
|
+
resolveMemoryNamespace(scope, binding, options = {}) {
|
|
374
|
+
const workspaceRoot = binding.harnessRuntime.workspaceRoot ?? this.workspace.workspaceRoot;
|
|
375
|
+
const workspaceId = path.basename(workspaceRoot) || "default";
|
|
376
|
+
const template = this.runtimeMemoryPolicy?.namespaces[scope] ?? `memories/${scope}s/{${scope}Id}`;
|
|
377
|
+
return resolveMemoryNamespace(template, {
|
|
378
|
+
threadId: options.threadId,
|
|
379
|
+
agentId: binding.agent.id,
|
|
380
|
+
workspaceId,
|
|
381
|
+
userId: options.userId ?? "default",
|
|
382
|
+
projectId: options.projectId ?? workspaceId,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
async buildRuntimeMemoryContext(binding, threadId, input) {
|
|
386
|
+
const threadNamespace = this.resolveMemoryNamespace("thread", binding, { threadId });
|
|
387
|
+
const agentNamespace = this.resolveMemoryNamespace("agent", binding);
|
|
388
|
+
const workspaceNamespace = this.resolveMemoryNamespace("workspace", binding);
|
|
389
|
+
const docs = await Promise.all([
|
|
390
|
+
this.runtimeMemoryStore.get(threadNamespace, "durable-summary.md"),
|
|
391
|
+
this.runtimeMemoryStore.get(threadNamespace, "tool-memory.md"),
|
|
392
|
+
this.runtimeMemoryStore.get(threadNamespace, "semantic.md"),
|
|
393
|
+
this.runtimeMemoryStore.get(threadNamespace, "episodic.md"),
|
|
394
|
+
this.runtimeMemoryStore.get(threadNamespace, "procedural.md"),
|
|
395
|
+
this.runtimeMemoryStore.get(agentNamespace, "procedural.md"),
|
|
396
|
+
this.runtimeMemoryStore.get(workspaceNamespace, "semantic.md"),
|
|
397
|
+
this.runtimeMemoryStore.get(workspaceNamespace, "procedural.md"),
|
|
398
|
+
]);
|
|
399
|
+
const query = typeof input === "string" ? input : JSON.stringify(input ?? "");
|
|
400
|
+
const ranked = docs
|
|
401
|
+
.map((doc, index) => {
|
|
402
|
+
const content = doc?.value?.content;
|
|
403
|
+
if (typeof content !== "string" || content.trim().length === 0) {
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
const scopeBoost = index < 5 ? 4 : index === 5 ? 2 : 1;
|
|
407
|
+
return {
|
|
408
|
+
content: content.trim(),
|
|
409
|
+
score: scoreMemoryText(query, content, scopeBoost),
|
|
410
|
+
};
|
|
411
|
+
})
|
|
412
|
+
.filter((value) => Boolean(value))
|
|
413
|
+
.sort((left, right) => right.score - left.score)
|
|
414
|
+
.slice(0, this.runtimeMemoryPolicy?.retrieval.maxPromptMemories ?? 8);
|
|
415
|
+
if (ranked.length === 0) {
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
418
|
+
return ranked.map((entry) => entry.content).join("\n\n");
|
|
419
|
+
}
|
|
420
|
+
async persistRuntimeMemoryCandidates(binding, threadId, runId, value) {
|
|
421
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const candidates = value
|
|
425
|
+
.filter((candidate) => typeof candidate === "object" && candidate !== null)
|
|
426
|
+
.filter((candidate) => candidate.noStore !== true && typeof candidate.content === "string" && candidate.content.trim().length > 0);
|
|
427
|
+
if (candidates.length === 0) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
const threadCandidates = candidates.filter((candidate) => (candidate.scope ?? "thread") === "thread");
|
|
431
|
+
const workspaceCandidates = candidates.filter((candidate) => (candidate.scope ?? "thread") === "workspace");
|
|
432
|
+
const agentCandidates = candidates.filter((candidate) => (candidate.scope ?? "thread") === "agent");
|
|
433
|
+
await this.runtimeMemoryStore.put(["memories", "candidates", threadId], `${runId}.json`, {
|
|
434
|
+
runId,
|
|
435
|
+
threadId,
|
|
436
|
+
storedAt: new Date().toISOString(),
|
|
437
|
+
candidates,
|
|
438
|
+
});
|
|
439
|
+
const writes = [];
|
|
440
|
+
if (threadCandidates.length > 0) {
|
|
441
|
+
writes.push(this.appendMemoryDigest(this.resolveMemoryNamespace("thread", binding, { threadId }), "tool-memory.md", threadCandidates, 12, "Thread Tool Memory"));
|
|
442
|
+
}
|
|
443
|
+
if (workspaceCandidates.length > 0) {
|
|
444
|
+
writes.push(this.appendMemoryDigest(this.resolveMemoryNamespace("workspace", binding), "tool-memory.md", workspaceCandidates, 20, "Workspace Tool Memory"));
|
|
445
|
+
}
|
|
446
|
+
if (agentCandidates.length > 0) {
|
|
447
|
+
writes.push(this.appendMemoryDigest(this.resolveMemoryNamespace("agent", binding), "tool-memory.md", agentCandidates, 20, "Agent Tool Memory"));
|
|
448
|
+
}
|
|
449
|
+
await Promise.all(writes);
|
|
450
|
+
}
|
|
451
|
+
async appendMemoryDigest(namespace, key, candidates, maxEntries, title) {
|
|
452
|
+
const existing = await this.runtimeMemoryStore.get(namespace, key);
|
|
453
|
+
const existingItems = Array.isArray(existing?.value?.items)
|
|
454
|
+
? ((existing?.value).items ?? [])
|
|
455
|
+
: [];
|
|
456
|
+
const merged = [...existingItems];
|
|
457
|
+
for (const candidate of candidates) {
|
|
458
|
+
if (merged.some((entry) => entry.content === candidate.content && (entry.scope ?? "thread") === (candidate.scope ?? "thread"))) {
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
merged.push(candidate);
|
|
462
|
+
}
|
|
463
|
+
const recent = merged.slice(-maxEntries);
|
|
464
|
+
const taxonomyGroups = new Map();
|
|
465
|
+
for (const candidate of recent) {
|
|
466
|
+
const kind = normalizeLangMemMemoryKind(candidate.kind);
|
|
467
|
+
const existing = taxonomyGroups.get(kind) ?? [];
|
|
468
|
+
existing.push({ ...candidate, kind });
|
|
469
|
+
taxonomyGroups.set(kind, existing);
|
|
470
|
+
}
|
|
471
|
+
await this.runtimeMemoryStore.put(namespace, key, {
|
|
472
|
+
content: `${renderMemoryCandidatesMarkdown(title, recent)}\n`,
|
|
473
|
+
items: recent,
|
|
474
|
+
});
|
|
475
|
+
await Promise.all(Array.from(taxonomyGroups.entries()).map(async ([kind, items]) => {
|
|
476
|
+
await this.runtimeMemoryStore.put(namespace, `${kind}.md`, {
|
|
477
|
+
content: `${renderMemoryCandidatesMarkdown(`${title} (${kind})`, items)}\n`,
|
|
478
|
+
items,
|
|
479
|
+
});
|
|
480
|
+
}));
|
|
481
|
+
}
|
|
363
482
|
async resolvePersistedRunPriority(threadId, runId) {
|
|
364
483
|
const persisted = await this.persistence.getRunRequest(threadId, runId);
|
|
365
484
|
return normalizeRunPriority(persisted?.priority);
|
|
@@ -514,7 +633,10 @@ export class AgentHarnessRuntime {
|
|
|
514
633
|
const stream = streamHarnessRun({
|
|
515
634
|
binding,
|
|
516
635
|
input: options.input,
|
|
517
|
-
invocation
|
|
636
|
+
invocation: {
|
|
637
|
+
...invocation,
|
|
638
|
+
memoryContext: await this.buildRuntimeMemoryContext(binding, threadId, options.input),
|
|
639
|
+
},
|
|
518
640
|
threadId,
|
|
519
641
|
runId,
|
|
520
642
|
selectedAgentId,
|
package/dist/tool-modules.d.ts
CHANGED
|
@@ -6,6 +6,13 @@ export type LoadedToolModule = {
|
|
|
6
6
|
schema: ReturnType<typeof normalizeToolSchema>;
|
|
7
7
|
description: string;
|
|
8
8
|
retryable?: boolean;
|
|
9
|
+
memory?: {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
kind?: string;
|
|
12
|
+
scope?: string;
|
|
13
|
+
maxCandidates?: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
};
|
|
9
16
|
};
|
|
10
17
|
export type LoadedSkillModule = {
|
|
11
18
|
name: string;
|
package/dist/tool-modules.js
CHANGED
|
@@ -22,6 +22,7 @@ function loadToolObjectDefinition(imported, exportName) {
|
|
|
22
22
|
schema: normalizeToolSchema(definition.schema),
|
|
23
23
|
description: definition.description.trim(),
|
|
24
24
|
retryable: definition.retryable === true,
|
|
25
|
+
...(definition.memory ? { memory: { ...definition.memory } } : {}),
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
export function isSupportedToolModulePath(filePath) {
|
package/dist/tools.d.ts
CHANGED
|
@@ -6,6 +6,13 @@ export type ToolDefinitionObject = {
|
|
|
6
6
|
description: string;
|
|
7
7
|
schema: SchemaInput;
|
|
8
8
|
retryable?: boolean;
|
|
9
|
+
memory?: {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
kind?: string;
|
|
12
|
+
scope?: string;
|
|
13
|
+
maxCandidates?: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
};
|
|
9
16
|
invoke: (input: unknown, context?: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
10
17
|
[TOOL_DEFINITION_MARKER]: true;
|
|
11
18
|
};
|
|
@@ -17,6 +24,13 @@ export declare function tool(definition: {
|
|
|
17
24
|
description: string;
|
|
18
25
|
schema: SchemaInput;
|
|
19
26
|
retryable?: boolean;
|
|
27
|
+
memory?: {
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
kind?: string;
|
|
30
|
+
scope?: string;
|
|
31
|
+
maxCandidates?: number;
|
|
32
|
+
tags?: string[];
|
|
33
|
+
};
|
|
20
34
|
invoke: (input: unknown, context?: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
21
35
|
}): ToolDefinitionObject;
|
|
22
36
|
export {};
|
|
@@ -762,6 +762,7 @@ export async function readToolModuleItems(root) {
|
|
|
762
762
|
description: definition.description,
|
|
763
763
|
implementationName: definition.implementationName,
|
|
764
764
|
...(definition.retryable !== undefined ? { retryable: definition.retryable } : {}),
|
|
765
|
+
...(definition.memory ? { config: { memory: definition.memory } } : {}),
|
|
765
766
|
},
|
|
766
767
|
sourcePath: filePath,
|
|
767
768
|
});
|