@aigne/did-space-memory 1.0.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 +16 -0
- package/LICENSE.md +93 -0
- package/README.md +171 -0
- package/lib/cjs/index.d.ts +3 -0
- package/lib/cjs/index.js +19 -0
- package/lib/cjs/memory.d.ts +88 -0
- package/lib/cjs/memory.js +245 -0
- package/lib/cjs/package.json +3 -0
- package/lib/cjs/readme-contents.d.ts +4 -0
- package/lib/cjs/readme-contents.js +23 -0
- package/lib/cjs/readme-manager.d.ts +21 -0
- package/lib/cjs/readme-manager.js +48 -0
- package/lib/cjs/utils/fs.d.ts +1 -0
- package/lib/cjs/utils/fs.js +10 -0
- package/lib/cjs/utils/index.d.ts +1 -0
- package/lib/cjs/utils/index.js +17 -0
- package/lib/dts/index.d.ts +3 -0
- package/lib/dts/memory.d.ts +88 -0
- package/lib/dts/readme-contents.d.ts +4 -0
- package/lib/dts/readme-manager.d.ts +21 -0
- package/lib/dts/utils/fs.d.ts +1 -0
- package/lib/dts/utils/index.d.ts +1 -0
- package/lib/esm/index.d.ts +3 -0
- package/lib/esm/index.js +3 -0
- package/lib/esm/memory.d.ts +88 -0
- package/lib/esm/memory.js +241 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/readme-contents.d.ts +4 -0
- package/lib/esm/readme-contents.js +20 -0
- package/lib/esm/readme-manager.d.ts +21 -0
- package/lib/esm/readme-manager.js +44 -0
- package/lib/esm/utils/fs.d.ts +1 -0
- package/lib/esm/utils/fs.js +7 -0
- package/lib/esm/utils/index.d.ts +1 -0
- package/lib/esm/utils/index.js +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type SpaceClientOptionsAuth } from "@blocklet/did-space-js";
|
|
2
|
+
/**
|
|
3
|
+
* Manages README files for DID Spaces Memory
|
|
4
|
+
*/
|
|
5
|
+
export declare class ReadmeManager {
|
|
6
|
+
private client;
|
|
7
|
+
private rootDir;
|
|
8
|
+
constructor(url: string, auth: SpaceClientOptionsAuth, rootDir: string);
|
|
9
|
+
/**
|
|
10
|
+
* Check if a file exists in DID Spaces
|
|
11
|
+
*/
|
|
12
|
+
private exists;
|
|
13
|
+
/**
|
|
14
|
+
* Create README file if it doesn't exist
|
|
15
|
+
*/
|
|
16
|
+
private createReadmeIfNotExists;
|
|
17
|
+
/**
|
|
18
|
+
* Initialize all README files
|
|
19
|
+
*/
|
|
20
|
+
initializeReadmeFiles(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReadmeManager = void 0;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const did_space_js_1 = require("@blocklet/did-space-js");
|
|
6
|
+
const readme_contents_js_1 = require("./readme-contents.js");
|
|
7
|
+
/**
|
|
8
|
+
* Manages README files for DID Spaces Memory
|
|
9
|
+
*/
|
|
10
|
+
class ReadmeManager {
|
|
11
|
+
client;
|
|
12
|
+
rootDir;
|
|
13
|
+
constructor(url, auth, rootDir) {
|
|
14
|
+
this.client = new did_space_js_1.SpaceClient({ url, auth });
|
|
15
|
+
this.rootDir = rootDir;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check if a file exists in DID Spaces
|
|
19
|
+
*/
|
|
20
|
+
async exists(key) {
|
|
21
|
+
try {
|
|
22
|
+
const output = await this.client.send(new did_space_js_1.ListObjectCommand({ key }));
|
|
23
|
+
return output.statusCode === 200;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create README file if it doesn't exist
|
|
31
|
+
*/
|
|
32
|
+
async createReadmeIfNotExists(filename, content) {
|
|
33
|
+
const filePath = (0, node_path_1.join)(this.rootDir, filename);
|
|
34
|
+
if (!(await this.exists(filePath))) {
|
|
35
|
+
await this.client.send(new did_space_js_1.PutObjectCommand({
|
|
36
|
+
key: filePath,
|
|
37
|
+
data: content,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Initialize all README files
|
|
43
|
+
*/
|
|
44
|
+
async initializeReadmeFiles() {
|
|
45
|
+
await this.createReadmeIfNotExists("README.md", readme_contents_js_1.README_EN_CONTENT);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.ReadmeManager = ReadmeManager;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function streamToString(stream: ReadableStream | NodeJS.ReadableStream, encoding?: BufferEncoding): Promise<string>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.streamToString = streamToString;
|
|
4
|
+
async function streamToString(stream, encoding = "utf-8") {
|
|
5
|
+
const chunks = [];
|
|
6
|
+
for await (const chunk of stream) {
|
|
7
|
+
chunks.push(chunk);
|
|
8
|
+
}
|
|
9
|
+
return Buffer.concat(chunks).toString(encoding);
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./fs.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./fs.js"), exports);
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
import { type SpaceClientOptionsAuth } from "@blocklet/did-space-js";
|
|
4
|
+
export declare const MEMORY_FILE_NAME = "memory.yaml";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the DIDSpacesMemory class.
|
|
7
|
+
*/
|
|
8
|
+
export interface DIDSpacesMemoryOptions extends Partial<MemoryAgentOptions> {
|
|
9
|
+
/**
|
|
10
|
+
* The URL of the DIDSpaces.
|
|
11
|
+
*/
|
|
12
|
+
url: string;
|
|
13
|
+
/**
|
|
14
|
+
* The authentication method for the DIDSpaces.
|
|
15
|
+
*/
|
|
16
|
+
auth: SpaceClientOptionsAuth;
|
|
17
|
+
/**
|
|
18
|
+
* Optional configuration for the memory retriever agent.
|
|
19
|
+
* Controls how memories are retrieved from the file system.
|
|
20
|
+
*/
|
|
21
|
+
retrieverOptions?: Partial<DIDSpacesMemoryRetrieverOptions>;
|
|
22
|
+
/**
|
|
23
|
+
* Optional configuration for the memory recorder agent.
|
|
24
|
+
* Controls how memories are recorded to the file system.
|
|
25
|
+
*/
|
|
26
|
+
recorderOptions?: Partial<DIDSpacesMemoryRecorderOptions>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A memory implementation that stores and retrieves memories using the file system.
|
|
30
|
+
* DIDSpacesMemory provides persistent storage of agent memories as files in a specified directory.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* Here is an example of how to use the DIDSpacesMemory class:
|
|
34
|
+
* {@includeCode ../../test/did-spaces-memory/did-spaces-memory.test.ts#example-did-spaces-memory-simple}
|
|
35
|
+
*/
|
|
36
|
+
export declare class DIDSpacesMemory extends MemoryAgent {
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new DIDSpacesMemory instance.
|
|
39
|
+
*/
|
|
40
|
+
constructor(options: DIDSpacesMemoryOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Initialize README files in the memory directory
|
|
43
|
+
*/
|
|
44
|
+
private initializeReadmeFiles;
|
|
45
|
+
}
|
|
46
|
+
interface DIDSpacesMemoryRetrieverOptions extends AIAgentOptions<DIDSpacesMemoryRetrieverAgentInput, DIDSpacesMemoryRetrieverAgentOutput> {
|
|
47
|
+
/**
|
|
48
|
+
* The URL of the DIDSpaces.
|
|
49
|
+
*/
|
|
50
|
+
url: string;
|
|
51
|
+
/**
|
|
52
|
+
* The authentication method for the DIDSpaces.
|
|
53
|
+
*/
|
|
54
|
+
auth: SpaceClientOptionsAuth;
|
|
55
|
+
/**
|
|
56
|
+
* The name of the memory file.
|
|
57
|
+
*/
|
|
58
|
+
memoryFileName: string;
|
|
59
|
+
}
|
|
60
|
+
interface DIDSpacesMemoryRetrieverAgentInput extends MemoryRetrieverInput {
|
|
61
|
+
allMemory: string;
|
|
62
|
+
}
|
|
63
|
+
interface DIDSpacesMemoryRetrieverAgentOutput extends Message {
|
|
64
|
+
memories: {
|
|
65
|
+
content: string;
|
|
66
|
+
}[];
|
|
67
|
+
}
|
|
68
|
+
interface DIDSpacesMemoryRecorderOptions extends AIAgentOptions<DIDSpacesMemoryRecorderAgentInput, DIDSpacesMemoryRecorderAgentOutput> {
|
|
69
|
+
/**
|
|
70
|
+
* The URL of the DIDSpaces.
|
|
71
|
+
*/
|
|
72
|
+
url: string;
|
|
73
|
+
/**
|
|
74
|
+
* The authentication method for the DIDSpaces.
|
|
75
|
+
*/
|
|
76
|
+
auth: SpaceClientOptionsAuth;
|
|
77
|
+
/**
|
|
78
|
+
* The name of the memory file.
|
|
79
|
+
*/
|
|
80
|
+
memoryFileName: string;
|
|
81
|
+
}
|
|
82
|
+
type DIDSpacesMemoryRecorderAgentInput = MemoryRecorderInput;
|
|
83
|
+
interface DIDSpacesMemoryRecorderAgentOutput extends Message {
|
|
84
|
+
memories: {
|
|
85
|
+
content: string;
|
|
86
|
+
}[];
|
|
87
|
+
}
|
|
88
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* README content for DID Spaces Memory
|
|
3
|
+
*/
|
|
4
|
+
export declare const README_EN_CONTENT = "# AIGNE Memory Directory\n\nThis directory is used to store agent context and conversation memories.\n\n## Files\n\n- `memory.yaml` - Contains the conversation history and context that the AI agent remembers across sessions\n- `README.md` - This file (English documentation)\n- `README.zh.md` - Chinese documentation\n\n## Purpose\n\nThe memory system allows AI agents to maintain context and remember important information from previous conversations, enabling more personalized and coherent interactions.\n\n## Privacy\n\nThe memory files are stored in your personal DID Space and are only accessible to you and the agents you authorize.";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type SpaceClientOptionsAuth } from "@blocklet/did-space-js";
|
|
2
|
+
/**
|
|
3
|
+
* Manages README files for DID Spaces Memory
|
|
4
|
+
*/
|
|
5
|
+
export declare class ReadmeManager {
|
|
6
|
+
private client;
|
|
7
|
+
private rootDir;
|
|
8
|
+
constructor(url: string, auth: SpaceClientOptionsAuth, rootDir: string);
|
|
9
|
+
/**
|
|
10
|
+
* Check if a file exists in DID Spaces
|
|
11
|
+
*/
|
|
12
|
+
private exists;
|
|
13
|
+
/**
|
|
14
|
+
* Create README file if it doesn't exist
|
|
15
|
+
*/
|
|
16
|
+
private createReadmeIfNotExists;
|
|
17
|
+
/**
|
|
18
|
+
* Initialize all README files
|
|
19
|
+
*/
|
|
20
|
+
initializeReadmeFiles(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function streamToString(stream: ReadableStream | NodeJS.ReadableStream, encoding?: BufferEncoding): Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./fs.js";
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
import { type SpaceClientOptionsAuth } from "@blocklet/did-space-js";
|
|
4
|
+
export declare const MEMORY_FILE_NAME = "memory.yaml";
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the DIDSpacesMemory class.
|
|
7
|
+
*/
|
|
8
|
+
export interface DIDSpacesMemoryOptions extends Partial<MemoryAgentOptions> {
|
|
9
|
+
/**
|
|
10
|
+
* The URL of the DIDSpaces.
|
|
11
|
+
*/
|
|
12
|
+
url: string;
|
|
13
|
+
/**
|
|
14
|
+
* The authentication method for the DIDSpaces.
|
|
15
|
+
*/
|
|
16
|
+
auth: SpaceClientOptionsAuth;
|
|
17
|
+
/**
|
|
18
|
+
* Optional configuration for the memory retriever agent.
|
|
19
|
+
* Controls how memories are retrieved from the file system.
|
|
20
|
+
*/
|
|
21
|
+
retrieverOptions?: Partial<DIDSpacesMemoryRetrieverOptions>;
|
|
22
|
+
/**
|
|
23
|
+
* Optional configuration for the memory recorder agent.
|
|
24
|
+
* Controls how memories are recorded to the file system.
|
|
25
|
+
*/
|
|
26
|
+
recorderOptions?: Partial<DIDSpacesMemoryRecorderOptions>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A memory implementation that stores and retrieves memories using the file system.
|
|
30
|
+
* DIDSpacesMemory provides persistent storage of agent memories as files in a specified directory.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* Here is an example of how to use the DIDSpacesMemory class:
|
|
34
|
+
* {@includeCode ../../test/did-spaces-memory/did-spaces-memory.test.ts#example-did-spaces-memory-simple}
|
|
35
|
+
*/
|
|
36
|
+
export declare class DIDSpacesMemory extends MemoryAgent {
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new DIDSpacesMemory instance.
|
|
39
|
+
*/
|
|
40
|
+
constructor(options: DIDSpacesMemoryOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Initialize README files in the memory directory
|
|
43
|
+
*/
|
|
44
|
+
private initializeReadmeFiles;
|
|
45
|
+
}
|
|
46
|
+
interface DIDSpacesMemoryRetrieverOptions extends AIAgentOptions<DIDSpacesMemoryRetrieverAgentInput, DIDSpacesMemoryRetrieverAgentOutput> {
|
|
47
|
+
/**
|
|
48
|
+
* The URL of the DIDSpaces.
|
|
49
|
+
*/
|
|
50
|
+
url: string;
|
|
51
|
+
/**
|
|
52
|
+
* The authentication method for the DIDSpaces.
|
|
53
|
+
*/
|
|
54
|
+
auth: SpaceClientOptionsAuth;
|
|
55
|
+
/**
|
|
56
|
+
* The name of the memory file.
|
|
57
|
+
*/
|
|
58
|
+
memoryFileName: string;
|
|
59
|
+
}
|
|
60
|
+
interface DIDSpacesMemoryRetrieverAgentInput extends MemoryRetrieverInput {
|
|
61
|
+
allMemory: string;
|
|
62
|
+
}
|
|
63
|
+
interface DIDSpacesMemoryRetrieverAgentOutput extends Message {
|
|
64
|
+
memories: {
|
|
65
|
+
content: string;
|
|
66
|
+
}[];
|
|
67
|
+
}
|
|
68
|
+
interface DIDSpacesMemoryRecorderOptions extends AIAgentOptions<DIDSpacesMemoryRecorderAgentInput, DIDSpacesMemoryRecorderAgentOutput> {
|
|
69
|
+
/**
|
|
70
|
+
* The URL of the DIDSpaces.
|
|
71
|
+
*/
|
|
72
|
+
url: string;
|
|
73
|
+
/**
|
|
74
|
+
* The authentication method for the DIDSpaces.
|
|
75
|
+
*/
|
|
76
|
+
auth: SpaceClientOptionsAuth;
|
|
77
|
+
/**
|
|
78
|
+
* The name of the memory file.
|
|
79
|
+
*/
|
|
80
|
+
memoryFileName: string;
|
|
81
|
+
}
|
|
82
|
+
type DIDSpacesMemoryRecorderAgentInput = MemoryRecorderInput;
|
|
83
|
+
interface DIDSpacesMemoryRecorderAgentOutput extends Message {
|
|
84
|
+
memories: {
|
|
85
|
+
content: string;
|
|
86
|
+
}[];
|
|
87
|
+
}
|
|
88
|
+
export {};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { AIAgent } from "@aigne/core";
|
|
3
|
+
import { MemoryAgent, MemoryRecorder, MemoryRetriever, newMemoryId, } from "@aigne/core/memory/index.js";
|
|
4
|
+
import { logger } from "@aigne/core/utils/logger.js";
|
|
5
|
+
import { GetObjectCommand, ListObjectCommand, PutObjectCommand, SpaceClient, } from "@blocklet/did-space-js";
|
|
6
|
+
import { stringify } from "yaml";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { ReadmeManager } from "./readme-manager.js";
|
|
9
|
+
import { streamToString } from "./utils/fs.js";
|
|
10
|
+
export const MEMORY_FILE_NAME = "memory.yaml";
|
|
11
|
+
/**
|
|
12
|
+
* A memory implementation that stores and retrieves memories using the file system.
|
|
13
|
+
* DIDSpacesMemory provides persistent storage of agent memories as files in a specified directory.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* Here is an example of how to use the DIDSpacesMemory class:
|
|
17
|
+
* {@includeCode ../../test/did-spaces-memory/did-spaces-memory.test.ts#example-did-spaces-memory-simple}
|
|
18
|
+
*/
|
|
19
|
+
export class DIDSpacesMemory extends MemoryAgent {
|
|
20
|
+
/**
|
|
21
|
+
* Creates a new DIDSpacesMemory instance.
|
|
22
|
+
*/
|
|
23
|
+
constructor(options) {
|
|
24
|
+
const rootDir = "/.aigne/";
|
|
25
|
+
const memoryFileName = join(rootDir, MEMORY_FILE_NAME);
|
|
26
|
+
super({
|
|
27
|
+
...options,
|
|
28
|
+
recorder: options.recorder ??
|
|
29
|
+
new DIDSpacesMemoryRecorder({
|
|
30
|
+
url: options.url,
|
|
31
|
+
auth: options.auth,
|
|
32
|
+
memoryFileName,
|
|
33
|
+
...options.recorderOptions,
|
|
34
|
+
}),
|
|
35
|
+
retriever: options.retriever ??
|
|
36
|
+
new DIDSpacesMemoryRetriever({
|
|
37
|
+
url: options.url,
|
|
38
|
+
auth: options.auth,
|
|
39
|
+
memoryFileName,
|
|
40
|
+
...options.retrieverOptions,
|
|
41
|
+
}),
|
|
42
|
+
autoUpdate: options.autoUpdate ?? true,
|
|
43
|
+
});
|
|
44
|
+
// Initialize README files asynchronously
|
|
45
|
+
this.initializeReadmeFiles(options.url, options.auth, rootDir).catch((error) => {
|
|
46
|
+
logger.warn("Failed to initialize README files:", error);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Initialize README files in the memory directory
|
|
51
|
+
*/
|
|
52
|
+
async initializeReadmeFiles(url, auth, rootDir) {
|
|
53
|
+
const readmeManager = new ReadmeManager(url, auth, rootDir);
|
|
54
|
+
await readmeManager.initializeReadmeFiles();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
class DIDSpacesMemoryRetriever extends MemoryRetriever {
|
|
58
|
+
options;
|
|
59
|
+
constructor(options) {
|
|
60
|
+
super({});
|
|
61
|
+
this.options = options;
|
|
62
|
+
this.agent = AIAgent.from({
|
|
63
|
+
name: "did_spaces_memory_retriever",
|
|
64
|
+
description: "Retrieves memories from the file or directory.",
|
|
65
|
+
...options,
|
|
66
|
+
instructions: options.instructions || DEFAULT_DID_SPACES_MEMORY_RETRIEVER_INSTRUCTIONS,
|
|
67
|
+
outputSchema: z.object({
|
|
68
|
+
memories: z
|
|
69
|
+
.array(z.object({
|
|
70
|
+
content: z.string().describe("Content of the memory"),
|
|
71
|
+
}))
|
|
72
|
+
.describe("List of memories"),
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
agent;
|
|
77
|
+
async exists() {
|
|
78
|
+
const client = new SpaceClient({
|
|
79
|
+
url: this.options.url,
|
|
80
|
+
auth: this.options.auth,
|
|
81
|
+
});
|
|
82
|
+
const listObjectCommandOutput = await client.send(new ListObjectCommand({
|
|
83
|
+
key: this.options.memoryFileName,
|
|
84
|
+
}));
|
|
85
|
+
return listObjectCommandOutput.statusCode === 200;
|
|
86
|
+
}
|
|
87
|
+
async read(input, options) {
|
|
88
|
+
const client = new SpaceClient({
|
|
89
|
+
url: this.options.url,
|
|
90
|
+
auth: this.options.auth,
|
|
91
|
+
});
|
|
92
|
+
const getObjectCommandOutput = await client.send(new GetObjectCommand({
|
|
93
|
+
key: this.options.memoryFileName,
|
|
94
|
+
}));
|
|
95
|
+
if (getObjectCommandOutput.statusCode !== 200) {
|
|
96
|
+
logger.warn(`statusCode: ${getObjectCommandOutput.statusCode}, statusMessage: ${getObjectCommandOutput.statusMessage}`);
|
|
97
|
+
throw new Error(getObjectCommandOutput.statusMessage);
|
|
98
|
+
}
|
|
99
|
+
const allMemory = await streamToString(getObjectCommandOutput.data);
|
|
100
|
+
const { memories } = await options.context.invoke(this.agent, {
|
|
101
|
+
...input,
|
|
102
|
+
allMemory,
|
|
103
|
+
});
|
|
104
|
+
const results = memories.map((memory) => ({
|
|
105
|
+
id: newMemoryId(),
|
|
106
|
+
content: memory.content,
|
|
107
|
+
createdAt: new Date().toISOString(),
|
|
108
|
+
}));
|
|
109
|
+
return results;
|
|
110
|
+
}
|
|
111
|
+
async process(input, options) {
|
|
112
|
+
if (!(await this.exists())) {
|
|
113
|
+
return { memories: [] };
|
|
114
|
+
}
|
|
115
|
+
const memories = await this.read(input, options);
|
|
116
|
+
return { memories };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
class DIDSpacesMemoryRecorder extends MemoryRecorder {
|
|
120
|
+
options;
|
|
121
|
+
constructor(options) {
|
|
122
|
+
super({});
|
|
123
|
+
this.options = options;
|
|
124
|
+
this.agent = AIAgent.from({
|
|
125
|
+
name: "did_spaces_memory_recorder",
|
|
126
|
+
description: "Records memories in files by AI agent",
|
|
127
|
+
...options,
|
|
128
|
+
instructions: options.instructions || DEFAULT_FS_MEMORY_RECORDER_INSTRUCTIONS,
|
|
129
|
+
outputSchema: z.object({
|
|
130
|
+
memories: z
|
|
131
|
+
.array(z.object({
|
|
132
|
+
content: z.string().describe("Content of the memory"),
|
|
133
|
+
}))
|
|
134
|
+
.describe("List of memories"),
|
|
135
|
+
}),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
agent;
|
|
139
|
+
async write(input, options) {
|
|
140
|
+
const client = new SpaceClient({
|
|
141
|
+
url: this.options.url,
|
|
142
|
+
auth: this.options.auth,
|
|
143
|
+
});
|
|
144
|
+
const output = await client.send(new GetObjectCommand({
|
|
145
|
+
key: this.options.memoryFileName,
|
|
146
|
+
}));
|
|
147
|
+
const allMemory = output.statusCode === 200 ? await streamToString(output.data) : "";
|
|
148
|
+
const { memories } = await options.context.invoke(this.agent, {
|
|
149
|
+
...input,
|
|
150
|
+
allMemory,
|
|
151
|
+
});
|
|
152
|
+
const raws = stringify(memories.map((i) => ({
|
|
153
|
+
content: i.content,
|
|
154
|
+
})));
|
|
155
|
+
const putObjectCommandOutput = await client.send(new PutObjectCommand({
|
|
156
|
+
key: this.options.memoryFileName,
|
|
157
|
+
data: raws,
|
|
158
|
+
}));
|
|
159
|
+
if (putObjectCommandOutput.statusCode !== 200) {
|
|
160
|
+
logger.warn(`statusCode: ${putObjectCommandOutput.statusCode}, statusMessage: ${putObjectCommandOutput.statusMessage}`);
|
|
161
|
+
throw new Error(putObjectCommandOutput.statusMessage);
|
|
162
|
+
}
|
|
163
|
+
const results = memories.map((memory) => ({
|
|
164
|
+
id: newMemoryId(),
|
|
165
|
+
content: memory.content,
|
|
166
|
+
createdAt: new Date().toISOString(),
|
|
167
|
+
}));
|
|
168
|
+
return { memories: results };
|
|
169
|
+
}
|
|
170
|
+
async process(input, options) {
|
|
171
|
+
return this.write(input, options);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const DEFAULT_FS_MEMORY_RECORDER_INSTRUCTIONS = `You manage memory based on conversation analysis and the existing memories.
|
|
175
|
+
|
|
176
|
+
## IMPORTANT: All existing memories are available in the allMemory variable. DO NOT call any tools.
|
|
177
|
+
|
|
178
|
+
## FIRST: Determine If Memory Updates Needed
|
|
179
|
+
- Analyze if the conversation contains ANY information worth remembering
|
|
180
|
+
- Examples of content NOT worth storing:
|
|
181
|
+
* General questions ("What's the weather?", "How do I do X?")
|
|
182
|
+
* Greetings and small talk ("Hello", "How are you?", "Thanks")
|
|
183
|
+
* System instructions or commands ("Show me", "Find", "Save")
|
|
184
|
+
* General facts not specific to the user
|
|
185
|
+
* Duplicate information already stored
|
|
186
|
+
- If conversation lacks meaningful personal information to store:
|
|
187
|
+
* Return the existing memories unchanged
|
|
188
|
+
|
|
189
|
+
## Your Workflow:
|
|
190
|
+
1. Read the existing memories from the allMemory variable
|
|
191
|
+
2. Extract key topics from the conversation
|
|
192
|
+
3. DECIDE whether to create/update/delete memories based on the conversation
|
|
193
|
+
4. Return ALL memories including your updates (remove any duplicates)
|
|
194
|
+
|
|
195
|
+
## Memory Handling:
|
|
196
|
+
- CREATE: Add new memory objects for new topics
|
|
197
|
+
- UPDATE: Modify existing memories if substantial new information is available
|
|
198
|
+
- DELETE: Remove obsolete memories when appropriate
|
|
199
|
+
|
|
200
|
+
## Memory Structure:
|
|
201
|
+
- Each memory has an id, content, and createdAt fields
|
|
202
|
+
- Keep the existing structure when returning updated memories
|
|
203
|
+
|
|
204
|
+
## Operation Decision Rules:
|
|
205
|
+
- CREATE only for truly new topics not covered in any existing memory
|
|
206
|
+
- UPDATE only when new information is meaningfully different
|
|
207
|
+
- NEVER update for just rephrasing or minor differences
|
|
208
|
+
- DELETE only when information becomes obsolete
|
|
209
|
+
|
|
210
|
+
## IMPORTANT: Your job is to return the complete updated memory collection.
|
|
211
|
+
Return ALL memories (existing and new) in your response.
|
|
212
|
+
|
|
213
|
+
## Existing Memories:
|
|
214
|
+
<existing-memory>
|
|
215
|
+
{{allMemory}}
|
|
216
|
+
</existing-memory>
|
|
217
|
+
|
|
218
|
+
## Conversation:
|
|
219
|
+
<conversation>
|
|
220
|
+
{{content}}
|
|
221
|
+
</conversation>
|
|
222
|
+
`;
|
|
223
|
+
const DEFAULT_DID_SPACES_MEMORY_RETRIEVER_INSTRUCTIONS = `You retrieve only the most relevant memories for the current conversation.
|
|
224
|
+
|
|
225
|
+
## IMPORTANT: All existing memories are available in the allMemory variable
|
|
226
|
+
|
|
227
|
+
## Process:
|
|
228
|
+
1. Read the existing memories from the allMemory variable
|
|
229
|
+
2. Extract key topics from the conversation or search query
|
|
230
|
+
3. Match memory contents against these topics
|
|
231
|
+
|
|
232
|
+
## Existing Memories:
|
|
233
|
+
<existing-memory>
|
|
234
|
+
{{allMemory}}
|
|
235
|
+
</existing-memory>
|
|
236
|
+
|
|
237
|
+
## Search Query:
|
|
238
|
+
<search-query>
|
|
239
|
+
{{search}}
|
|
240
|
+
</search-query>
|
|
241
|
+
`;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* README content for DID Spaces Memory
|
|
3
|
+
*/
|
|
4
|
+
export declare const README_EN_CONTENT = "# AIGNE Memory Directory\n\nThis directory is used to store agent context and conversation memories.\n\n## Files\n\n- `memory.yaml` - Contains the conversation history and context that the AI agent remembers across sessions\n- `README.md` - This file (English documentation)\n- `README.zh.md` - Chinese documentation\n\n## Purpose\n\nThe memory system allows AI agents to maintain context and remember important information from previous conversations, enabling more personalized and coherent interactions.\n\n## Privacy\n\nThe memory files are stored in your personal DID Space and are only accessible to you and the agents you authorize.";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* README content for DID Spaces Memory
|
|
3
|
+
*/
|
|
4
|
+
export const README_EN_CONTENT = `# AIGNE Memory Directory
|
|
5
|
+
|
|
6
|
+
This directory is used to store agent context and conversation memories.
|
|
7
|
+
|
|
8
|
+
## Files
|
|
9
|
+
|
|
10
|
+
- \`memory.yaml\` - Contains the conversation history and context that the AI agent remembers across sessions
|
|
11
|
+
- \`README.md\` - This file (English documentation)
|
|
12
|
+
- \`README.zh.md\` - Chinese documentation
|
|
13
|
+
|
|
14
|
+
## Purpose
|
|
15
|
+
|
|
16
|
+
The memory system allows AI agents to maintain context and remember important information from previous conversations, enabling more personalized and coherent interactions.
|
|
17
|
+
|
|
18
|
+
## Privacy
|
|
19
|
+
|
|
20
|
+
The memory files are stored in your personal DID Space and are only accessible to you and the agents you authorize.`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type SpaceClientOptionsAuth } from "@blocklet/did-space-js";
|
|
2
|
+
/**
|
|
3
|
+
* Manages README files for DID Spaces Memory
|
|
4
|
+
*/
|
|
5
|
+
export declare class ReadmeManager {
|
|
6
|
+
private client;
|
|
7
|
+
private rootDir;
|
|
8
|
+
constructor(url: string, auth: SpaceClientOptionsAuth, rootDir: string);
|
|
9
|
+
/**
|
|
10
|
+
* Check if a file exists in DID Spaces
|
|
11
|
+
*/
|
|
12
|
+
private exists;
|
|
13
|
+
/**
|
|
14
|
+
* Create README file if it doesn't exist
|
|
15
|
+
*/
|
|
16
|
+
private createReadmeIfNotExists;
|
|
17
|
+
/**
|
|
18
|
+
* Initialize all README files
|
|
19
|
+
*/
|
|
20
|
+
initializeReadmeFiles(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { ListObjectCommand, PutObjectCommand, SpaceClient, } from "@blocklet/did-space-js";
|
|
3
|
+
import { README_EN_CONTENT } from "./readme-contents.js";
|
|
4
|
+
/**
|
|
5
|
+
* Manages README files for DID Spaces Memory
|
|
6
|
+
*/
|
|
7
|
+
export class ReadmeManager {
|
|
8
|
+
client;
|
|
9
|
+
rootDir;
|
|
10
|
+
constructor(url, auth, rootDir) {
|
|
11
|
+
this.client = new SpaceClient({ url, auth });
|
|
12
|
+
this.rootDir = rootDir;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Check if a file exists in DID Spaces
|
|
16
|
+
*/
|
|
17
|
+
async exists(key) {
|
|
18
|
+
try {
|
|
19
|
+
const output = await this.client.send(new ListObjectCommand({ key }));
|
|
20
|
+
return output.statusCode === 200;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create README file if it doesn't exist
|
|
28
|
+
*/
|
|
29
|
+
async createReadmeIfNotExists(filename, content) {
|
|
30
|
+
const filePath = join(this.rootDir, filename);
|
|
31
|
+
if (!(await this.exists(filePath))) {
|
|
32
|
+
await this.client.send(new PutObjectCommand({
|
|
33
|
+
key: filePath,
|
|
34
|
+
data: content,
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Initialize all README files
|
|
40
|
+
*/
|
|
41
|
+
async initializeReadmeFiles() {
|
|
42
|
+
await this.createReadmeIfNotExists("README.md", README_EN_CONTENT);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function streamToString(stream: ReadableStream | NodeJS.ReadableStream, encoding?: BufferEncoding): Promise<string>;
|