acp-ts 1.0.6 → 1.0.9
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/agentcp.d.ts +9 -17
- package/dist/agentcp.js +37 -77
- package/dist/agentmanager.d.ts +3 -25
- package/dist/agentmanager.js +4 -50
- package/dist/cli.js +12 -1
- package/dist/datamanager.d.ts +3 -0
- package/dist/datamanager.js +63 -22
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/interfaces.d.ts +5 -0
- package/dist/messagestore.d.ts +65 -0
- package/dist/messagestore.js +308 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +815 -497
- package/package.json +1 -1
package/dist/agentcp.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { IAgentCP, IAgentIdentity } from "./interfaces";
|
|
2
|
+
import { MessageStore } from "./messagestore";
|
|
2
3
|
declare class AgentCP implements IAgentCP {
|
|
3
4
|
private seedPassword;
|
|
4
5
|
private apUrl;
|
|
5
6
|
private msgUrl;
|
|
6
7
|
private activeAid;
|
|
8
|
+
private _messageStore;
|
|
7
9
|
private agentMdPath;
|
|
8
|
-
|
|
10
|
+
private agentMdUploaded;
|
|
11
|
+
get messageStore(): MessageStore;
|
|
12
|
+
constructor(apiUrl: string, seedPassword?: string, basePath?: string, options?: {
|
|
13
|
+
persistMessages?: boolean;
|
|
14
|
+
});
|
|
9
15
|
/**
|
|
10
16
|
* 初始化并预热加密模块
|
|
11
17
|
*/
|
|
@@ -21,28 +27,14 @@ declare class AgentCP implements IAgentCP {
|
|
|
21
27
|
messageServer: string;
|
|
22
28
|
heartbeatServer: string;
|
|
23
29
|
}>;
|
|
24
|
-
/**
|
|
25
|
-
* 设置 agent.md 文件路径,登录成功后会自动上传(仅首次)
|
|
26
|
-
* @param filePath agent.md 文件的本地路径
|
|
27
|
-
*/
|
|
28
|
-
setAgentMdPath(filePath: string): void;
|
|
29
|
-
/**
|
|
30
|
-
* 重置 agent.md 上传状态,下次登录时会重新上传
|
|
31
|
-
* 当 agent.md 内容更新后调用此方法
|
|
32
|
-
*/
|
|
33
|
-
resetAgentMdUploadStatus(): Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* 上传 agent.md 文件
|
|
36
|
-
* @param signature 签名(从 signIn 获取)
|
|
37
|
-
* @returns 上传结果
|
|
38
|
-
*/
|
|
39
|
-
private uploadAgentMd;
|
|
40
30
|
getCertInfo(aid: string): Promise<{
|
|
41
31
|
privateKey: string;
|
|
42
32
|
publicKey: string;
|
|
43
33
|
csr: string;
|
|
44
34
|
cert: string;
|
|
45
35
|
} | null>;
|
|
36
|
+
setAgentMdPath(filePath: string): void;
|
|
37
|
+
resetAgentMdUploadStatus(): Promise<void>;
|
|
46
38
|
private handleError;
|
|
47
39
|
}
|
|
48
40
|
export { AgentCP };
|
package/dist/agentcp.js
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.AgentCP = void 0;
|
|
7
4
|
const cert_1 = require("./cert");
|
|
8
5
|
const datamanager_1 = require("./datamanager");
|
|
9
6
|
const api_1 = require("./api");
|
|
10
7
|
const utils_1 = require("./utils");
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const isNodeEnvironment = typeof process !== 'undefined' &&
|
|
14
|
-
process.versions != null &&
|
|
15
|
-
process.versions.node != null;
|
|
8
|
+
const messagestore_1 = require("./messagestore");
|
|
9
|
+
const filesync_1 = require("./filesync");
|
|
16
10
|
class AgentCP {
|
|
17
|
-
|
|
11
|
+
get messageStore() {
|
|
12
|
+
return this._messageStore;
|
|
13
|
+
}
|
|
14
|
+
constructor(apiUrl, seedPassword = "", basePath, options) {
|
|
15
|
+
var _a;
|
|
18
16
|
this.activeAid = '';
|
|
19
|
-
this.agentMdPath =
|
|
17
|
+
this.agentMdPath = null;
|
|
18
|
+
this.agentMdUploaded = false;
|
|
20
19
|
if (!apiUrl) {
|
|
21
20
|
this.handleError("参数缺失:apiUrl不应为空");
|
|
22
21
|
}
|
|
23
22
|
if (apiUrl.startsWith('http://')) {
|
|
24
23
|
this.handleError("apiUrl不需要http://开头");
|
|
25
24
|
}
|
|
25
|
+
if (basePath) {
|
|
26
|
+
datamanager_1.CertAndKeyStore.setBasePath(basePath);
|
|
27
|
+
}
|
|
26
28
|
const baseUrl = `https://acp3.${apiUrl}`;
|
|
27
29
|
this.seedPassword = seedPassword;
|
|
28
30
|
this.apUrl = `${baseUrl}/api/accesspoint`;
|
|
29
31
|
this.msgUrl = `${baseUrl}/api/message`;
|
|
32
|
+
this._messageStore = new messagestore_1.MessageStore({
|
|
33
|
+
persistMessages: (_a = options === null || options === void 0 ? void 0 : options.persistMessages) !== null && _a !== void 0 ? _a : false,
|
|
34
|
+
basePath: basePath || process.cwd(),
|
|
35
|
+
});
|
|
30
36
|
// 预热加密模块
|
|
31
37
|
this.initializeCrypto();
|
|
32
38
|
}
|
|
@@ -155,20 +161,25 @@ class AgentCP {
|
|
|
155
161
|
else {
|
|
156
162
|
messageSignature = (_a = msgData.signature) !== null && _a !== void 0 ? _a : '';
|
|
157
163
|
}
|
|
158
|
-
// 登录成功后自动上传 agent.md
|
|
159
|
-
if (this.agentMdPath &&
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
// 登录成功后自动上传 agent.md(仅首次)
|
|
165
|
+
if (this.agentMdPath && !this.agentMdUploaded) {
|
|
166
|
+
try {
|
|
167
|
+
const fileSync = new filesync_1.FileSync({
|
|
168
|
+
apiUrl: this.msgUrl,
|
|
169
|
+
aid: this.activeAid,
|
|
170
|
+
signature: messageSignature,
|
|
171
|
+
});
|
|
172
|
+
const result = await fileSync.uploadAgentMdFromFile(this.agentMdPath);
|
|
173
|
+
if (result.success) {
|
|
174
|
+
this.agentMdUploaded = true;
|
|
167
175
|
}
|
|
168
176
|
else {
|
|
169
|
-
console.warn(
|
|
177
|
+
console.warn('agent.md 上传失败:', result.error);
|
|
170
178
|
}
|
|
171
179
|
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
console.warn('agent.md 上传异常:', err);
|
|
182
|
+
}
|
|
172
183
|
}
|
|
173
184
|
return {
|
|
174
185
|
messageSignature,
|
|
@@ -176,63 +187,6 @@ class AgentCP {
|
|
|
176
187
|
heartbeatServer
|
|
177
188
|
};
|
|
178
189
|
}
|
|
179
|
-
/**
|
|
180
|
-
* 设置 agent.md 文件路径,登录成功后会自动上传(仅首次)
|
|
181
|
-
* @param filePath agent.md 文件的本地路径
|
|
182
|
-
*/
|
|
183
|
-
setAgentMdPath(filePath) {
|
|
184
|
-
this.agentMdPath = filePath;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* 重置 agent.md 上传状态,下次登录时会重新上传
|
|
188
|
-
* 当 agent.md 内容更新后调用此方法
|
|
189
|
-
*/
|
|
190
|
-
async resetAgentMdUploadStatus() {
|
|
191
|
-
if (this.activeAid) {
|
|
192
|
-
await datamanager_1.CertAndKeyStore.storeData(`agent_md_uploaded_${this.activeAid}`, false);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* 上传 agent.md 文件
|
|
197
|
-
* @param signature 签名(从 signIn 获取)
|
|
198
|
-
* @returns 上传结果
|
|
199
|
-
*/
|
|
200
|
-
async uploadAgentMd(signature) {
|
|
201
|
-
var _a, _b, _c;
|
|
202
|
-
if (!this.agentMdPath) {
|
|
203
|
-
return { success: false, error: '未设置 agent.md 路径' };
|
|
204
|
-
}
|
|
205
|
-
if (!isNodeEnvironment) {
|
|
206
|
-
return { success: false, error: '自动上传 agent.md 仅支持 Node.js 环境' };
|
|
207
|
-
}
|
|
208
|
-
const fs = require('fs');
|
|
209
|
-
try {
|
|
210
|
-
if (!fs.existsSync(this.agentMdPath)) {
|
|
211
|
-
return { success: false, error: `文件不存在: ${this.agentMdPath}` };
|
|
212
|
-
}
|
|
213
|
-
const content = fs.readFileSync(this.agentMdPath, 'utf8');
|
|
214
|
-
// 检查文件大小限制(4KB)
|
|
215
|
-
const contentSize = Buffer.byteLength(content, 'utf8');
|
|
216
|
-
if (contentSize > 4 * 1024) {
|
|
217
|
-
return { success: false, error: `文件大小超过限制: ${contentSize} bytes > 4KB` };
|
|
218
|
-
}
|
|
219
|
-
const url = `https://${this.activeAid}/agent.md`;
|
|
220
|
-
const response = await axios_1.default.post(url, content, {
|
|
221
|
-
headers: {
|
|
222
|
-
'Content-Type': 'text/markdown',
|
|
223
|
-
'Authorization': `Bearer ${signature}`
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
if (response.status === 200) {
|
|
227
|
-
return { success: true, url: response.data.url || url };
|
|
228
|
-
}
|
|
229
|
-
return { success: false, error: ((_a = response.data) === null || _a === void 0 ? void 0 : _a.message) || `上传失败: ${response.status}` };
|
|
230
|
-
}
|
|
231
|
-
catch (error) {
|
|
232
|
-
const errorMsg = ((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || error.message || '上传 agent.md 失败';
|
|
233
|
-
return { success: false, error: errorMsg };
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
190
|
async getCertInfo(aid) {
|
|
237
191
|
const csr = await datamanager_1.CertAndKeyStore.getCsr(aid);
|
|
238
192
|
const privateKey = await datamanager_1.CertAndKeyStore.getPrivateKey(aid);
|
|
@@ -247,6 +201,12 @@ class AgentCP {
|
|
|
247
201
|
cert: certPem
|
|
248
202
|
};
|
|
249
203
|
}
|
|
204
|
+
setAgentMdPath(filePath) {
|
|
205
|
+
this.agentMdPath = filePath;
|
|
206
|
+
}
|
|
207
|
+
async resetAgentMdUploadStatus() {
|
|
208
|
+
this.agentMdUploaded = false;
|
|
209
|
+
}
|
|
250
210
|
handleError(error, customMessage) {
|
|
251
211
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
252
212
|
throw new Error(`${customMessage || '操作失败'}: ${errorMessage}`);
|
package/dist/agentmanager.d.ts
CHANGED
|
@@ -1,37 +1,15 @@
|
|
|
1
1
|
import { IAgentCP, IAgentWS, IConnectionConfig } from './interfaces';
|
|
2
|
-
import { FileSync, SyncResult } from './filesync';
|
|
3
2
|
declare class AgentManager {
|
|
4
3
|
private static instance;
|
|
5
4
|
private agentCP;
|
|
6
5
|
private agentWS;
|
|
7
|
-
private fileSync;
|
|
8
|
-
private apiUrl;
|
|
9
6
|
private constructor();
|
|
10
7
|
static getInstance(): AgentManager;
|
|
11
|
-
initACP(apiUrl: string, seedPassword?: string
|
|
8
|
+
initACP(apiUrl: string, seedPassword?: string, basePath?: string, options?: {
|
|
9
|
+
persistMessages?: boolean;
|
|
10
|
+
}): IAgentCP;
|
|
12
11
|
initAWS(aid: string, config: IConnectionConfig): IAgentWS;
|
|
13
12
|
acp(): IAgentCP;
|
|
14
13
|
aws(): IAgentWS;
|
|
15
|
-
/**
|
|
16
|
-
* 初始化文件同步模块
|
|
17
|
-
* @param aid 智能体ID
|
|
18
|
-
* @param signature 签名
|
|
19
|
-
* @param localDir 本地公共文件目录
|
|
20
|
-
* @returns FileSync实例
|
|
21
|
-
*/
|
|
22
|
-
initFileSync(aid: string, signature: string, localDir: string): FileSync;
|
|
23
|
-
/**
|
|
24
|
-
* 获取文件同步实例
|
|
25
|
-
* @returns FileSync实例
|
|
26
|
-
*/
|
|
27
|
-
fs(): FileSync;
|
|
28
|
-
/**
|
|
29
|
-
* 快捷方法:同步公共文件
|
|
30
|
-
* @param aid 智能体ID
|
|
31
|
-
* @param signature 签名
|
|
32
|
-
* @param localDir 本地公共文件目录
|
|
33
|
-
* @returns 同步结果
|
|
34
|
-
*/
|
|
35
|
-
syncPublicFiles(aid: string, signature: string, localDir: string): Promise<SyncResult>;
|
|
36
14
|
}
|
|
37
15
|
export { AgentManager };
|
package/dist/agentmanager.js
CHANGED
|
@@ -3,13 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AgentManager = void 0;
|
|
4
4
|
const agentcp_1 = require("./agentcp");
|
|
5
5
|
const agentws_1 = require("./agentws");
|
|
6
|
-
const filesync_1 = require("./filesync");
|
|
7
6
|
class AgentManager {
|
|
8
7
|
constructor() {
|
|
9
8
|
this.agentCP = null;
|
|
10
9
|
this.agentWS = null;
|
|
11
|
-
this.fileSync = null;
|
|
12
|
-
this.apiUrl = '';
|
|
13
10
|
}
|
|
14
11
|
static getInstance() {
|
|
15
12
|
if (!AgentManager.instance) {
|
|
@@ -17,10 +14,10 @@ class AgentManager {
|
|
|
17
14
|
}
|
|
18
15
|
return AgentManager.instance;
|
|
19
16
|
}
|
|
20
|
-
initACP(apiUrl, seedPassword = "") {
|
|
21
|
-
|
|
22
|
-
this.agentCP =
|
|
23
|
-
return
|
|
17
|
+
initACP(apiUrl, seedPassword = "", basePath, options) {
|
|
18
|
+
const acp = new agentcp_1.AgentCP(apiUrl, seedPassword, basePath, options);
|
|
19
|
+
this.agentCP = acp;
|
|
20
|
+
return acp;
|
|
24
21
|
}
|
|
25
22
|
initAWS(aid, config) {
|
|
26
23
|
const { messageServer, messageSignature } = config;
|
|
@@ -39,48 +36,5 @@ class AgentManager {
|
|
|
39
36
|
}
|
|
40
37
|
return this.agentWS;
|
|
41
38
|
}
|
|
42
|
-
/**
|
|
43
|
-
* 初始化文件同步模块
|
|
44
|
-
* @param aid 智能体ID
|
|
45
|
-
* @param signature 签名
|
|
46
|
-
* @param localDir 本地公共文件目录
|
|
47
|
-
* @returns FileSync实例
|
|
48
|
-
*/
|
|
49
|
-
initFileSync(aid, signature, localDir) {
|
|
50
|
-
if (!this.apiUrl) {
|
|
51
|
-
throw new Error("请先调用initACP初始化API地址");
|
|
52
|
-
}
|
|
53
|
-
// 构建完整的 API URL(与 AgentCP 保持一致)
|
|
54
|
-
const baseUrl = `https://acp3.${this.apiUrl}`;
|
|
55
|
-
const config = {
|
|
56
|
-
apiUrl: `${baseUrl}/api/accesspoint`,
|
|
57
|
-
aid: aid,
|
|
58
|
-
signature: signature,
|
|
59
|
-
localDir: localDir
|
|
60
|
-
};
|
|
61
|
-
this.fileSync = new filesync_1.FileSync(config);
|
|
62
|
-
return this.fileSync;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* 获取文件同步实例
|
|
66
|
-
* @returns FileSync实例
|
|
67
|
-
*/
|
|
68
|
-
fs() {
|
|
69
|
-
if (!this.fileSync) {
|
|
70
|
-
throw new Error("FileSync未初始化,请先调用initFileSync");
|
|
71
|
-
}
|
|
72
|
-
return this.fileSync;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* 快捷方法:同步公共文件
|
|
76
|
-
* @param aid 智能体ID
|
|
77
|
-
* @param signature 签名
|
|
78
|
-
* @param localDir 本地公共文件目录
|
|
79
|
-
* @returns 同步结果
|
|
80
|
-
*/
|
|
81
|
-
async syncPublicFiles(aid, signature, localDir) {
|
|
82
|
-
const fileSync = this.initFileSync(aid, signature, localDir);
|
|
83
|
-
return fileSync.syncPublicFiles();
|
|
84
|
-
}
|
|
85
39
|
}
|
|
86
40
|
exports.AgentManager = AgentManager;
|
package/dist/cli.js
CHANGED
|
@@ -107,6 +107,7 @@ function update() {
|
|
|
107
107
|
const args = process.argv.slice(2);
|
|
108
108
|
let port = 9527; // 使用非常用端口
|
|
109
109
|
let apiUrl = 'aid.pub'; // 默认服务地址
|
|
110
|
+
let dataDir = ''; // 数据目录
|
|
110
111
|
// 解析命令行参数
|
|
111
112
|
for (let i = 0; i < args.length; i++) {
|
|
112
113
|
if (args[i] === 'update') {
|
|
@@ -140,6 +141,15 @@ for (let i = 0; i < args.length; i++) {
|
|
|
140
141
|
apiUrl = urlArg;
|
|
141
142
|
i++;
|
|
142
143
|
}
|
|
144
|
+
else if (args[i] === '-d' || args[i] === '--data-dir') {
|
|
145
|
+
const dirArg = args[i + 1];
|
|
146
|
+
if (!dirArg || dirArg.startsWith('-')) {
|
|
147
|
+
console.error('错误: -d 参数需要指定数据目录路径');
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
dataDir = dirArg;
|
|
151
|
+
i++;
|
|
152
|
+
}
|
|
143
153
|
else if (args[i] === '-h' || args[i] === '--help') {
|
|
144
154
|
console.log(`
|
|
145
155
|
acp-ts - 智能体通信调试工具 v${getVersion()}
|
|
@@ -152,6 +162,7 @@ acp-ts - 智能体通信调试工具 v${getVersion()}
|
|
|
152
162
|
-v, --version 显示版本号
|
|
153
163
|
-p, --port <端口> 指定服务端口 (默认: 9527)
|
|
154
164
|
-u, --url <地址> 指定 API 服务器地址 (默认: aid.pub)
|
|
165
|
+
-d, --data-dir <路径> 指定数据目录 (默认: 当前目录)
|
|
155
166
|
-h, --help 显示帮助信息
|
|
156
167
|
|
|
157
168
|
安装:
|
|
@@ -165,4 +176,4 @@ acp-ts - 智能体通信调试工具 v${getVersion()}
|
|
|
165
176
|
process.exit(0);
|
|
166
177
|
}
|
|
167
178
|
}
|
|
168
|
-
(0, server_1.startServer)(port, apiUrl);
|
|
179
|
+
(0, server_1.startServer)(port, apiUrl, dataDir);
|
package/dist/datamanager.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export declare class CertAndKeyStore {
|
|
2
2
|
static aidKey: string;
|
|
3
|
+
private static basePath;
|
|
4
|
+
static setBasePath(p: string): void;
|
|
5
|
+
static getAIDsDir(): string;
|
|
3
6
|
static storeData(key: string, value: any): Promise<void>;
|
|
4
7
|
static getData(key: string): Promise<any>;
|
|
5
8
|
static getGuestAid(): Promise<string | null>;
|
package/dist/datamanager.js
CHANGED
|
@@ -105,7 +105,13 @@ else {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
class CertAndKeyStore {
|
|
108
|
-
|
|
108
|
+
static setBasePath(p) {
|
|
109
|
+
this.basePath = p;
|
|
110
|
+
}
|
|
111
|
+
static getAIDsDir() {
|
|
112
|
+
return path.join(this.basePath, 'AIDs');
|
|
113
|
+
}
|
|
114
|
+
// 存储数据(仍用 storage.json,用于会话/消息)
|
|
109
115
|
static async storeData(key, value) {
|
|
110
116
|
try {
|
|
111
117
|
await AsyncStorage.setItem(key, JSON.stringify(value));
|
|
@@ -114,7 +120,7 @@ class CertAndKeyStore {
|
|
|
114
120
|
console.error(e);
|
|
115
121
|
}
|
|
116
122
|
}
|
|
117
|
-
//
|
|
123
|
+
// 获取数据(仍用 storage.json,用于会话/消息)
|
|
118
124
|
static async getData(key) {
|
|
119
125
|
try {
|
|
120
126
|
const value = await AsyncStorage.getItem(key);
|
|
@@ -151,48 +157,82 @@ class CertAndKeyStore {
|
|
|
151
157
|
}
|
|
152
158
|
}
|
|
153
159
|
static async getAids() {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
160
|
+
try {
|
|
161
|
+
const aidsDir = this.getAIDsDir();
|
|
162
|
+
if (!fs.existsSync(aidsDir)) {
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
const entries = fs.readdirSync(aidsDir, { withFileTypes: true });
|
|
166
|
+
return entries.filter(e => e.isDirectory()).map(e => e.name);
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
console.error('扫描 AIDs 目录失败:', e);
|
|
170
|
+
return [];
|
|
157
171
|
}
|
|
158
|
-
return [];
|
|
159
172
|
}
|
|
160
173
|
static async saveAid(aid) {
|
|
161
174
|
try {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
await this.storeData(this.aidKey, mergedAids);
|
|
167
|
-
}
|
|
175
|
+
const privateDir = path.join(this.getAIDsDir(), aid, 'private');
|
|
176
|
+
const publicDir = path.join(this.getAIDsDir(), aid, 'public');
|
|
177
|
+
if (!fs.existsSync(privateDir)) {
|
|
178
|
+
fs.mkdirSync(privateDir, { recursive: true });
|
|
168
179
|
}
|
|
169
|
-
|
|
170
|
-
|
|
180
|
+
if (!fs.existsSync(publicDir)) {
|
|
181
|
+
fs.mkdirSync(publicDir, { recursive: true });
|
|
171
182
|
}
|
|
172
183
|
}
|
|
173
184
|
catch (e) {
|
|
174
|
-
console.error('
|
|
185
|
+
console.error('创建 AID 目录失败:', e);
|
|
175
186
|
}
|
|
176
187
|
}
|
|
177
188
|
static async getCertificate(aid) {
|
|
178
|
-
|
|
189
|
+
try {
|
|
190
|
+
const certPath = path.join(this.getAIDsDir(), aid, 'public', `${aid}.crt`);
|
|
191
|
+
if (fs.existsSync(certPath)) {
|
|
192
|
+
return fs.readFileSync(certPath, 'utf-8');
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
console.error('读取证书失败:', e);
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
179
200
|
}
|
|
180
201
|
static async saveCertificate(aid, cert) {
|
|
181
|
-
await this.
|
|
202
|
+
await this.saveAid(aid);
|
|
203
|
+
const certPath = path.join(this.getAIDsDir(), aid, 'public', `${aid}.crt`);
|
|
204
|
+
fs.writeFileSync(certPath, cert, 'utf-8');
|
|
182
205
|
}
|
|
183
206
|
static async getCsr(aid) {
|
|
184
|
-
|
|
207
|
+
try {
|
|
208
|
+
const csrPath = path.join(this.getAIDsDir(), aid, 'private', `${aid}.csr`);
|
|
209
|
+
if (fs.existsSync(csrPath)) {
|
|
210
|
+
return fs.readFileSync(csrPath, 'utf-8');
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
console.error('读取 CSR 失败:', e);
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
185
218
|
}
|
|
186
219
|
static async saveCsr(aid, csr) {
|
|
187
|
-
await this.
|
|
220
|
+
await this.saveAid(aid);
|
|
221
|
+
const csrPath = path.join(this.getAIDsDir(), aid, 'private', `${aid}.csr`);
|
|
222
|
+
fs.writeFileSync(csrPath, csr, 'utf-8');
|
|
188
223
|
}
|
|
189
224
|
static async savePrivateKey(aid, key) {
|
|
190
|
-
await this.
|
|
225
|
+
await this.saveAid(aid);
|
|
226
|
+
const keyPath = path.join(this.getAIDsDir(), aid, 'private', `${aid}.key`);
|
|
227
|
+
fs.writeFileSync(keyPath, key, 'utf-8');
|
|
191
228
|
}
|
|
192
229
|
static async getPrivateKey(aid) {
|
|
193
230
|
try {
|
|
194
|
-
const
|
|
195
|
-
|
|
231
|
+
const keyPath = path.join(this.getAIDsDir(), aid, 'private', `${aid}.key`);
|
|
232
|
+
if (fs.existsSync(keyPath)) {
|
|
233
|
+
return fs.readFileSync(keyPath, 'utf-8');
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
196
236
|
}
|
|
197
237
|
catch (error) {
|
|
198
238
|
console.error('获取私钥失败:', error);
|
|
@@ -202,3 +242,4 @@ class CertAndKeyStore {
|
|
|
202
242
|
}
|
|
203
243
|
exports.CertAndKeyStore = CertAndKeyStore;
|
|
204
244
|
CertAndKeyStore.aidKey = 'currentAidKey';
|
|
245
|
+
CertAndKeyStore.basePath = process.cwd();
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ import { ConnectionStatus } from "./websocket";
|
|
|
2
2
|
import { AgentManager } from './agentmanager';
|
|
3
3
|
import { IAgentIdentity } from './interfaces';
|
|
4
4
|
import { HeartbeatClient, HeartbeatStatus, InviteInfo } from './heartbeat';
|
|
5
|
-
import {
|
|
6
|
-
export { AgentManager, IAgentIdentity, HeartbeatClient,
|
|
7
|
-
export type { ConnectionStatus, HeartbeatStatus, InviteInfo,
|
|
5
|
+
import { MessageStore, MessageItem, SessionRecord, Session, SessionSummary } from './messagestore';
|
|
6
|
+
export { AgentManager, IAgentIdentity, HeartbeatClient, MessageStore };
|
|
7
|
+
export type { ConnectionStatus, HeartbeatStatus, InviteInfo, MessageItem, SessionRecord, Session, SessionSummary, };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.MessageStore = exports.HeartbeatClient = exports.AgentManager = void 0;
|
|
4
4
|
const agentmanager_1 = require("./agentmanager");
|
|
5
5
|
Object.defineProperty(exports, "AgentManager", { enumerable: true, get: function () { return agentmanager_1.AgentManager; } });
|
|
6
6
|
const heartbeat_1 = require("./heartbeat");
|
|
7
7
|
Object.defineProperty(exports, "HeartbeatClient", { enumerable: true, get: function () { return heartbeat_1.HeartbeatClient; } });
|
|
8
|
-
const
|
|
9
|
-
Object.defineProperty(exports, "
|
|
8
|
+
const messagestore_1 = require("./messagestore");
|
|
9
|
+
Object.defineProperty(exports, "MessageStore", { enumerable: true, get: function () { return messagestore_1.MessageStore; } });
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ACPMessageSessionResponse, ConnectionStatus, InviteStatus } from "./websocket";
|
|
2
|
+
import { MessageStore } from "./messagestore";
|
|
2
3
|
/**
|
|
3
4
|
* 代理身份信息接口
|
|
4
5
|
* @interface IAgentIdentity
|
|
@@ -28,6 +29,10 @@ interface IConnectionConfig {
|
|
|
28
29
|
* @interface IAgentCP
|
|
29
30
|
*/
|
|
30
31
|
interface IAgentCP {
|
|
32
|
+
/**
|
|
33
|
+
* 消息存储模块
|
|
34
|
+
*/
|
|
35
|
+
readonly messageStore: MessageStore;
|
|
31
36
|
/**
|
|
32
37
|
* 导入代理身份
|
|
33
38
|
* @param {IAgentIdentity} identity - 代理身份信息
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export type MessageItem = {
|
|
2
|
+
type: 'sent' | 'received';
|
|
3
|
+
content: string;
|
|
4
|
+
from?: string;
|
|
5
|
+
to?: string;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
};
|
|
8
|
+
export interface SessionRecord {
|
|
9
|
+
sessionId: string;
|
|
10
|
+
identifyingCode: string;
|
|
11
|
+
peerAid: string;
|
|
12
|
+
ownerAid: string;
|
|
13
|
+
type: 'outgoing' | 'incoming';
|
|
14
|
+
createdAt: number;
|
|
15
|
+
lastMessageAt: number;
|
|
16
|
+
messageCount: number;
|
|
17
|
+
closed: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface Session extends SessionRecord {
|
|
20
|
+
messages: MessageItem[];
|
|
21
|
+
}
|
|
22
|
+
export interface SessionSummary {
|
|
23
|
+
sessionId: string;
|
|
24
|
+
peerAid: string;
|
|
25
|
+
ownerAid: string;
|
|
26
|
+
type: 'outgoing' | 'incoming';
|
|
27
|
+
lastMessageAt: number;
|
|
28
|
+
messageCount: number;
|
|
29
|
+
createdAt: number;
|
|
30
|
+
lastMessage: string;
|
|
31
|
+
closed: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare class MessageStore {
|
|
34
|
+
private persistMessages;
|
|
35
|
+
private basePath;
|
|
36
|
+
private maxMessagesPerSession;
|
|
37
|
+
private sessions;
|
|
38
|
+
constructor(options: {
|
|
39
|
+
persistMessages: boolean;
|
|
40
|
+
basePath: string;
|
|
41
|
+
maxMessagesPerSession?: number;
|
|
42
|
+
});
|
|
43
|
+
private getSessionsDir;
|
|
44
|
+
private getIndexPath;
|
|
45
|
+
private getSessionFilePath;
|
|
46
|
+
private ensureDir;
|
|
47
|
+
loadSessionsForAid(ownerAid: string): Promise<void>;
|
|
48
|
+
/** 从 JSONL 文件读取消息列表 */
|
|
49
|
+
private readMessagesFromFile;
|
|
50
|
+
private migrateFromLegacy;
|
|
51
|
+
getOrCreateSession(sessionId: string, identifyingCode: string, peerAid: string, type: 'outgoing' | 'incoming', ownerAid: string): Session;
|
|
52
|
+
addMessageToSession(sessionId: string, msg: MessageItem): void;
|
|
53
|
+
getSessionList(ownerAid: string): SessionSummary[];
|
|
54
|
+
hasSession(sessionId: string): boolean;
|
|
55
|
+
getSession(sessionId: string): Session | null;
|
|
56
|
+
/** 只写索引文件 */
|
|
57
|
+
flushIndex(ownerAid: string): Promise<void>;
|
|
58
|
+
/** 全量重写单个会话的消息文件(JSONL 格式) */
|
|
59
|
+
flushSession(ownerAid: string, sessionId: string): Promise<void>;
|
|
60
|
+
/** 追加单条消息到 JSONL 文件 */
|
|
61
|
+
private appendMessage;
|
|
62
|
+
/** 全量写入指定 AID 的索引 + 所有会话消息文件 */
|
|
63
|
+
flush(ownerAid: string): Promise<void>;
|
|
64
|
+
flushAll(): Promise<void>;
|
|
65
|
+
}
|