@aigne/agent-library 1.20.4 → 1.21.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/CHANGELOG.md +26 -0
- package/lib/cjs/package.json +3 -1
- package/lib/esm/package.json +3 -1
- package/package.json +5 -5
- package/lib/cjs/agentic-memory/index.d.ts +0 -38
- package/lib/cjs/agentic-memory/index.js +0 -73
- package/lib/cjs/agentic-memory/prompt.d.ts +0 -1
- package/lib/cjs/agentic-memory/prompt.js +0 -44
- package/lib/cjs/default-memory/default-memory-storage/index.d.ts +0 -29
- package/lib/cjs/default-memory/default-memory-storage/index.js +0 -95
- package/lib/cjs/default-memory/default-memory-storage/migrate.d.ts +0 -3
- package/lib/cjs/default-memory/default-memory-storage/migrate.js +0 -32
- package/lib/cjs/default-memory/default-memory-storage/migrations/001-init.d.ts +0 -5
- package/lib/cjs/default-memory/default-memory-storage/migrations/001-init.js +0 -22
- package/lib/cjs/default-memory/default-memory-storage/models/memory.d.ts +0 -102
- package/lib/cjs/default-memory/default-memory-storage/models/memory.js +0 -21
- package/lib/cjs/default-memory/index.d.ts +0 -44
- package/lib/cjs/default-memory/index.js +0 -132
- package/lib/cjs/default-memory/storage.d.ts +0 -13
- package/lib/cjs/default-memory/storage.js +0 -6
- package/lib/cjs/fs-memory/index.d.ts +0 -59
- package/lib/cjs/fs-memory/index.js +0 -184
- package/lib/dts/agentic-memory/index.d.ts +0 -38
- package/lib/dts/agentic-memory/prompt.d.ts +0 -1
- package/lib/dts/default-memory/default-memory-storage/index.d.ts +0 -29
- package/lib/dts/default-memory/default-memory-storage/migrate.d.ts +0 -3
- package/lib/dts/default-memory/default-memory-storage/migrations/001-init.d.ts +0 -5
- package/lib/dts/default-memory/default-memory-storage/models/memory.d.ts +0 -102
- package/lib/dts/default-memory/index.d.ts +0 -44
- package/lib/dts/default-memory/storage.d.ts +0 -13
- package/lib/dts/fs-memory/index.d.ts +0 -59
- package/lib/esm/agentic-memory/index.d.ts +0 -38
- package/lib/esm/agentic-memory/index.js +0 -67
- package/lib/esm/agentic-memory/prompt.d.ts +0 -1
- package/lib/esm/agentic-memory/prompt.js +0 -41
- package/lib/esm/default-memory/default-memory-storage/index.d.ts +0 -29
- package/lib/esm/default-memory/default-memory-storage/index.js +0 -91
- package/lib/esm/default-memory/default-memory-storage/migrate.d.ts +0 -3
- package/lib/esm/default-memory/default-memory-storage/migrate.js +0 -26
- package/lib/esm/default-memory/default-memory-storage/migrations/001-init.d.ts +0 -5
- package/lib/esm/default-memory/default-memory-storage/migrations/001-init.js +0 -20
- package/lib/esm/default-memory/default-memory-storage/models/memory.d.ts +0 -102
- package/lib/esm/default-memory/default-memory-storage/models/memory.js +0 -18
- package/lib/esm/default-memory/index.d.ts +0 -44
- package/lib/esm/default-memory/index.js +0 -126
- package/lib/esm/default-memory/storage.d.ts +0 -13
- package/lib/esm/default-memory/storage.js +0 -2
- package/lib/esm/fs-memory/index.d.ts +0 -59
- package/lib/esm/fs-memory/index.js +0 -180
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { MemoryAgent, MemoryRecorder, MemoryRetriever, } from "@aigne/core";
|
|
2
|
-
import { flat, isRecord, pick } from "@aigne/core/utils/type-utils.js";
|
|
3
|
-
import { DefaultMemoryStorage, } from "./default-memory-storage/index.js";
|
|
4
|
-
import { MemoryStorage } from "./storage.js";
|
|
5
|
-
const DEFAULT_RETRIEVE_MEMORY_COUNT = 10;
|
|
6
|
-
export class DefaultMemory extends MemoryAgent {
|
|
7
|
-
constructor(options = {}) {
|
|
8
|
-
const storage = options.storage instanceof MemoryStorage
|
|
9
|
-
? options.storage
|
|
10
|
-
: new DefaultMemoryStorage(options.storage);
|
|
11
|
-
super({
|
|
12
|
-
...options,
|
|
13
|
-
recorder: options.recorder ?? new DefaultMemoryRecorder({ ...options, storage }),
|
|
14
|
-
retriever: options.retriever ??
|
|
15
|
-
new DefaultMemoryRetriever({
|
|
16
|
-
...options,
|
|
17
|
-
retrieveRecentMemoryCount: options.retrieveRecentMemoryCount ??
|
|
18
|
-
Math.ceil(options.retrieveMemoryCount ?? DEFAULT_RETRIEVE_MEMORY_COUNT) / 2,
|
|
19
|
-
storage,
|
|
20
|
-
}),
|
|
21
|
-
autoUpdate: options.autoUpdate ?? true,
|
|
22
|
-
});
|
|
23
|
-
this.storage = storage;
|
|
24
|
-
}
|
|
25
|
-
storage;
|
|
26
|
-
}
|
|
27
|
-
export class DefaultMemoryRetriever extends MemoryRetriever {
|
|
28
|
-
constructor(options) {
|
|
29
|
-
super(options);
|
|
30
|
-
this.storage = options.storage;
|
|
31
|
-
this.retrieveMemoryCount = options.retrieveMemoryCount;
|
|
32
|
-
this.retrieveRecentMemoryCount = options.retrieveRecentMemoryCount;
|
|
33
|
-
this.inputKey = flat(options.inputKey);
|
|
34
|
-
this.outputKey = flat(options.outputKey);
|
|
35
|
-
if (options.getSearchPattern)
|
|
36
|
-
this.getSearchPattern = options.getSearchPattern;
|
|
37
|
-
if (options.formatMessage)
|
|
38
|
-
this.formatMessage = options.formatMessage;
|
|
39
|
-
if (options.formatMemory)
|
|
40
|
-
this.formatMemory = options.formatMemory;
|
|
41
|
-
}
|
|
42
|
-
storage;
|
|
43
|
-
retrieveMemoryCount;
|
|
44
|
-
retrieveRecentMemoryCount;
|
|
45
|
-
inputKey;
|
|
46
|
-
outputKey;
|
|
47
|
-
getSearchPattern = (search) => {
|
|
48
|
-
if (!search || typeof search === "string")
|
|
49
|
-
return search;
|
|
50
|
-
const obj = search && this.inputKey ? pick(search, this.inputKey) : search;
|
|
51
|
-
return Object.values(obj)
|
|
52
|
-
.map((v) => (typeof v === "string" ? v : undefined))
|
|
53
|
-
.join("\n");
|
|
54
|
-
};
|
|
55
|
-
formatMessage = (content, key) => {
|
|
56
|
-
if (!isRecord(content))
|
|
57
|
-
return content;
|
|
58
|
-
const obj = !key?.length ? content : pick(content, key);
|
|
59
|
-
return Object.values(obj)
|
|
60
|
-
.map((v) => (typeof v === "string" ? v : undefined))
|
|
61
|
-
.join("\n");
|
|
62
|
-
};
|
|
63
|
-
formatMemory = (content) => {
|
|
64
|
-
if (isRecord(content) && "input" in content && "output" in content) {
|
|
65
|
-
return {
|
|
66
|
-
input: this.formatMessage(content.input, this.inputKey),
|
|
67
|
-
output: this.formatMessage(content.output, this.outputKey),
|
|
68
|
-
source: content.source,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return content;
|
|
72
|
-
};
|
|
73
|
-
async process(input, options) {
|
|
74
|
-
const limit = input.limit ?? this.retrieveMemoryCount ?? DEFAULT_RETRIEVE_MEMORY_COUNT;
|
|
75
|
-
const search = this.getSearchPattern(input.search);
|
|
76
|
-
const recentLimit = this.retrieveRecentMemoryCount;
|
|
77
|
-
const [recent, related] = await Promise.all([
|
|
78
|
-
// Query latest messages
|
|
79
|
-
!recentLimit
|
|
80
|
-
? []
|
|
81
|
-
: this.storage
|
|
82
|
-
.search({ limit: recentLimit, orderBy: ["createdAt", "desc"] }, options)
|
|
83
|
-
.then(({ result }) => result.reverse()),
|
|
84
|
-
// Query related messages
|
|
85
|
-
!input.search
|
|
86
|
-
? []
|
|
87
|
-
: this.storage.search({ ...input, search, limit }, options).then(({ result }) => result),
|
|
88
|
-
]);
|
|
89
|
-
const recentSet = new Set(recent.map((i) => i.id));
|
|
90
|
-
const memories = related
|
|
91
|
-
// Filter out recent memories from related results
|
|
92
|
-
.filter((i) => !recentSet.has(i.id))
|
|
93
|
-
.concat(recent)
|
|
94
|
-
.slice(-limit);
|
|
95
|
-
return { memories: memories.map((i) => ({ ...i, content: this.formatMemory(i.content) })) };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
export class DefaultMemoryRecorder extends MemoryRecorder {
|
|
99
|
-
constructor(options) {
|
|
100
|
-
super(options);
|
|
101
|
-
this.storage = options.storage;
|
|
102
|
-
this.inputKey = flat(options.inputKey);
|
|
103
|
-
this.outputKey = flat(options.outputKey);
|
|
104
|
-
}
|
|
105
|
-
storage;
|
|
106
|
-
inputKey;
|
|
107
|
-
outputKey;
|
|
108
|
-
async process(input, options) {
|
|
109
|
-
const newMemories = [];
|
|
110
|
-
for (const item of input.content) {
|
|
111
|
-
const { result } = await this.storage.create({
|
|
112
|
-
content: {
|
|
113
|
-
input: item.input && this.inputKey?.length ? pick(item.input, this.inputKey) : item.input,
|
|
114
|
-
output: item.output && this.outputKey?.length
|
|
115
|
-
? pick(item.output, this.outputKey)
|
|
116
|
-
: item.output,
|
|
117
|
-
source: item.source,
|
|
118
|
-
},
|
|
119
|
-
}, options);
|
|
120
|
-
newMemories.push(result);
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
memories: newMemories,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { AgentInvokeOptions, Memory } from "@aigne/core";
|
|
2
|
-
export declare abstract class MemoryStorage {
|
|
3
|
-
abstract create(memory: Pick<Memory, "content">, options: AgentInvokeOptions): Promise<{
|
|
4
|
-
result: Memory;
|
|
5
|
-
}>;
|
|
6
|
-
abstract search(query: {
|
|
7
|
-
search?: string;
|
|
8
|
-
limit?: number;
|
|
9
|
-
orderBy?: [string, "asc" | "desc"];
|
|
10
|
-
}, options: AgentInvokeOptions): Promise<{
|
|
11
|
-
result: Memory[];
|
|
12
|
-
}>;
|
|
13
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { type AIAgentOptions, type Message } from "@aigne/core";
|
|
2
|
-
import { MemoryAgent, type MemoryAgentOptions, type MemoryRecorderInput, type MemoryRetrieverInput } from "@aigne/core/memory/index.js";
|
|
3
|
-
export declare const MEMORY_FILE_NAME = "memory.yaml";
|
|
4
|
-
/**
|
|
5
|
-
* Configuration options for the FSMemory class.
|
|
6
|
-
*/
|
|
7
|
-
export interface FSMemoryOptions extends Partial<MemoryAgentOptions> {
|
|
8
|
-
/**
|
|
9
|
-
* The root directory where memory files will be stored.
|
|
10
|
-
* Can be absolute or relative path. Relative paths are resolved from the current working directory.
|
|
11
|
-
* Home directory prefix (~) will be expanded appropriately.
|
|
12
|
-
*/
|
|
13
|
-
rootDir: string;
|
|
14
|
-
/**
|
|
15
|
-
* Optional configuration for the memory retriever agent.
|
|
16
|
-
* Controls how memories are retrieved from the file system.
|
|
17
|
-
*/
|
|
18
|
-
retrieverOptions?: Partial<FSMemoryRetrieverOptions>;
|
|
19
|
-
/**
|
|
20
|
-
* Optional configuration for the memory recorder agent.
|
|
21
|
-
* Controls how memories are recorded to the file system.
|
|
22
|
-
*/
|
|
23
|
-
recorderOptions?: Partial<FSMemoryRecorderOptions>;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* A memory implementation that stores and retrieves memories using the file system.
|
|
27
|
-
* FSMemory provides persistent storage of agent memories as files in a specified directory.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* Here is an example of how to use the FSMemory class:
|
|
31
|
-
* {@includeCode ../../test/fs-memory/fs-memory.test.ts#example-fs-memory-simple}
|
|
32
|
-
*/
|
|
33
|
-
export declare class FSMemory extends MemoryAgent {
|
|
34
|
-
/**
|
|
35
|
-
* Creates a new FSMemory instance.
|
|
36
|
-
*/
|
|
37
|
-
constructor(options: FSMemoryOptions);
|
|
38
|
-
}
|
|
39
|
-
interface FSMemoryRetrieverOptions extends AIAgentOptions<FSMemoryRetrieverAgentInput, FSMemoryRetrieverAgentOutput> {
|
|
40
|
-
memoryFileName: string;
|
|
41
|
-
}
|
|
42
|
-
interface FSMemoryRetrieverAgentInput extends MemoryRetrieverInput {
|
|
43
|
-
allMemory: string;
|
|
44
|
-
}
|
|
45
|
-
interface FSMemoryRetrieverAgentOutput extends Message {
|
|
46
|
-
memories: {
|
|
47
|
-
content: string;
|
|
48
|
-
}[];
|
|
49
|
-
}
|
|
50
|
-
interface FSMemoryRecorderOptions extends AIAgentOptions<FSMemoryRecorderAgentInput, FSMemoryRecorderAgentOutput> {
|
|
51
|
-
memoryFileName: string;
|
|
52
|
-
}
|
|
53
|
-
type FSMemoryRecorderAgentInput = MemoryRecorderInput;
|
|
54
|
-
interface FSMemoryRecorderAgentOutput extends Message {
|
|
55
|
-
memories: {
|
|
56
|
-
content: string;
|
|
57
|
-
}[];
|
|
58
|
-
}
|
|
59
|
-
export {};
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { dirname, isAbsolute, join, normalize, resolve } from "node:path";
|
|
3
|
-
import { AIAgent } from "@aigne/core";
|
|
4
|
-
import { MemoryAgent, MemoryRecorder, MemoryRetriever, newMemoryId, } from "@aigne/core/memory/index.js";
|
|
5
|
-
import { stringify } from "yaml";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
import { exists, expandHome } from "../utils/fs.js";
|
|
8
|
-
export const MEMORY_FILE_NAME = "memory.yaml";
|
|
9
|
-
/**
|
|
10
|
-
* A memory implementation that stores and retrieves memories using the file system.
|
|
11
|
-
* FSMemory provides persistent storage of agent memories as files in a specified directory.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* Here is an example of how to use the FSMemory class:
|
|
15
|
-
* {@includeCode ../../test/fs-memory/fs-memory.test.ts#example-fs-memory-simple}
|
|
16
|
-
*/
|
|
17
|
-
export class FSMemory extends MemoryAgent {
|
|
18
|
-
/**
|
|
19
|
-
* Creates a new FSMemory instance.
|
|
20
|
-
*/
|
|
21
|
-
constructor(options) {
|
|
22
|
-
let rootDir = normalize(expandHome(options.rootDir));
|
|
23
|
-
rootDir = isAbsolute(rootDir) ? rootDir : resolve(process.cwd(), rootDir);
|
|
24
|
-
const memoryFileName = join(rootDir, MEMORY_FILE_NAME);
|
|
25
|
-
super({
|
|
26
|
-
...options,
|
|
27
|
-
recorder: options.recorder ??
|
|
28
|
-
new FSMemoryRecorder({
|
|
29
|
-
memoryFileName,
|
|
30
|
-
...options.recorderOptions,
|
|
31
|
-
}),
|
|
32
|
-
retriever: options.retriever ??
|
|
33
|
-
new FSMemoryRetriever({
|
|
34
|
-
memoryFileName,
|
|
35
|
-
...options.retrieverOptions,
|
|
36
|
-
}),
|
|
37
|
-
autoUpdate: options.autoUpdate ?? true,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
class FSMemoryRetriever extends MemoryRetriever {
|
|
42
|
-
options;
|
|
43
|
-
constructor(options) {
|
|
44
|
-
super({});
|
|
45
|
-
this.options = options;
|
|
46
|
-
this.agent = AIAgent.from({
|
|
47
|
-
name: "fs_memory_retriever",
|
|
48
|
-
description: "Retrieves memories from the file or directory.",
|
|
49
|
-
...options,
|
|
50
|
-
instructions: options.instructions || DEFAULT_FS_MEMORY_RETRIEVER_INSTRUCTIONS,
|
|
51
|
-
outputSchema: z.object({
|
|
52
|
-
memories: z
|
|
53
|
-
.array(z.object({
|
|
54
|
-
content: z.string().describe("Content of the memory"),
|
|
55
|
-
}))
|
|
56
|
-
.describe("List of memories"),
|
|
57
|
-
}),
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
agent;
|
|
61
|
-
async process(input, options) {
|
|
62
|
-
if (!(await exists(this.options.memoryFileName)))
|
|
63
|
-
return { memories: [] };
|
|
64
|
-
const allMemory = await readFile(this.options.memoryFileName, "utf-8");
|
|
65
|
-
const { memories } = await options.context.invoke(this.agent, { ...input, allMemory });
|
|
66
|
-
const result = memories.map((memory) => ({
|
|
67
|
-
id: newMemoryId(),
|
|
68
|
-
content: memory.content,
|
|
69
|
-
createdAt: new Date().toISOString(),
|
|
70
|
-
}));
|
|
71
|
-
return { memories: result };
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
class FSMemoryRecorder extends MemoryRecorder {
|
|
75
|
-
options;
|
|
76
|
-
constructor(options) {
|
|
77
|
-
super({});
|
|
78
|
-
this.options = options;
|
|
79
|
-
this.agent = AIAgent.from({
|
|
80
|
-
name: "fs_memory_recorder",
|
|
81
|
-
description: "Records memories in files by AI agent",
|
|
82
|
-
...options,
|
|
83
|
-
instructions: options.instructions || DEFAULT_FS_MEMORY_RECORDER_INSTRUCTIONS,
|
|
84
|
-
outputSchema: z.object({
|
|
85
|
-
memories: z
|
|
86
|
-
.array(z.object({
|
|
87
|
-
content: z.string().describe("Content of the memory"),
|
|
88
|
-
}))
|
|
89
|
-
.describe("List of memories"),
|
|
90
|
-
}),
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
agent;
|
|
94
|
-
async process(input, options) {
|
|
95
|
-
const allMemory = (await exists(this.options.memoryFileName))
|
|
96
|
-
? await readFile(this.options.memoryFileName, "utf-8")
|
|
97
|
-
: "";
|
|
98
|
-
const { memories } = await options.context.invoke(this.agent, { ...input, allMemory });
|
|
99
|
-
const raw = stringify(memories.map((i) => ({
|
|
100
|
-
content: i.content,
|
|
101
|
-
})));
|
|
102
|
-
await mkdir(dirname(this.options.memoryFileName), { recursive: true });
|
|
103
|
-
await writeFile(this.options.memoryFileName, raw, "utf-8");
|
|
104
|
-
return {
|
|
105
|
-
memories: memories.map((i) => ({
|
|
106
|
-
id: newMemoryId(),
|
|
107
|
-
content: i.content,
|
|
108
|
-
createdAt: new Date().toISOString(),
|
|
109
|
-
})),
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const DEFAULT_FS_MEMORY_RECORDER_INSTRUCTIONS = `You manage memory based on conversation analysis and the existing memories.
|
|
114
|
-
|
|
115
|
-
## IMPORTANT: All existing memories are available in the allMemory variable. DO NOT call any tools.
|
|
116
|
-
|
|
117
|
-
## FIRST: Determine If Memory Updates Needed
|
|
118
|
-
- Analyze if the conversation contains ANY information worth remembering
|
|
119
|
-
- Examples of content NOT worth storing:
|
|
120
|
-
* General questions ("What's the weather?", "How do I do X?")
|
|
121
|
-
* Greetings and small talk ("Hello", "How are you?", "Thanks")
|
|
122
|
-
* System instructions or commands ("Show me", "Find", "Save")
|
|
123
|
-
* General facts not specific to the user
|
|
124
|
-
* Duplicate information already stored
|
|
125
|
-
- If conversation lacks meaningful personal information to store:
|
|
126
|
-
* Return the existing memories unchanged
|
|
127
|
-
|
|
128
|
-
## Your Workflow:
|
|
129
|
-
1. Read the existing memories from the allMemory variable
|
|
130
|
-
2. Extract key topics from the conversation
|
|
131
|
-
3. DECIDE whether to create/update/delete memories based on the conversation
|
|
132
|
-
4. Return ALL memories including your updates (remove any duplicates)
|
|
133
|
-
|
|
134
|
-
## Memory Handling:
|
|
135
|
-
- CREATE: Add new memory objects for new topics
|
|
136
|
-
- UPDATE: Modify existing memories if substantial new information is available
|
|
137
|
-
- DELETE: Remove obsolete memories when appropriate
|
|
138
|
-
|
|
139
|
-
## Memory Structure:
|
|
140
|
-
- Each memory has an id, content, and createdAt fields
|
|
141
|
-
- Keep the existing structure when returning updated memories
|
|
142
|
-
|
|
143
|
-
## Operation Decision Rules:
|
|
144
|
-
- CREATE only for truly new topics not covered in any existing memory
|
|
145
|
-
- UPDATE only when new information is meaningfully different
|
|
146
|
-
- NEVER update for just rephrasing or minor differences
|
|
147
|
-
- DELETE only when information becomes obsolete
|
|
148
|
-
|
|
149
|
-
## IMPORTANT: Your job is to return the complete updated memory collection.
|
|
150
|
-
Return ALL memories (existing and new) in your response.
|
|
151
|
-
|
|
152
|
-
## Existing Memories:
|
|
153
|
-
<existing-memory>
|
|
154
|
-
{{allMemory}}
|
|
155
|
-
</existing-memory>
|
|
156
|
-
|
|
157
|
-
## Conversation:
|
|
158
|
-
<conversation>
|
|
159
|
-
{{content}}
|
|
160
|
-
</conversation>
|
|
161
|
-
`;
|
|
162
|
-
const DEFAULT_FS_MEMORY_RETRIEVER_INSTRUCTIONS = `You retrieve only the most relevant memories for the current conversation.
|
|
163
|
-
|
|
164
|
-
## IMPORTANT: All existing memories are available in the allMemory variable
|
|
165
|
-
|
|
166
|
-
## Process:
|
|
167
|
-
1. Read the existing memories from the allMemory variable
|
|
168
|
-
2. Extract key topics from the conversation or search query
|
|
169
|
-
3. Match memory contents against these topics
|
|
170
|
-
|
|
171
|
-
## Existing Memories:
|
|
172
|
-
<existing-memory>
|
|
173
|
-
{{allMemory}}
|
|
174
|
-
</existing-memory>
|
|
175
|
-
|
|
176
|
-
## Search Query:
|
|
177
|
-
<search-query>
|
|
178
|
-
{{search}}
|
|
179
|
-
</search-query>
|
|
180
|
-
`;
|