cortico-bot-zcor 0.1.0 → 0.1.1
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/README.md +3 -1
- package/package.json +21 -6
- package/persona/memory.ts +26 -3
- package/persona/persona.ts +7 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ AI 自行调用工具保存和检索记忆:
|
|
|
14
14
|
- `zcor_memory_important(id, important)`:标记或取消重要记忆。
|
|
15
15
|
- `zcor_memory_query(keywords?, from?, to?, limit?, offset?)`:本地查询当前记忆。
|
|
16
16
|
- `zcor_memory_history(keywords?, from?, to?, limit?, offset?)`:本地查询操作历史。
|
|
17
|
+
- `zcor_memory_backup()` / `zcor_memory_restore(backupFile)`:备份或恢复 Memory 状态。
|
|
17
18
|
- `zcor_synonyms_add(terms)`:添加同义词组。
|
|
18
19
|
- `zcor_memory_search(keywords)`:关键词数组检索。
|
|
19
20
|
|
|
@@ -41,13 +42,14 @@ AI 自行调用工具保存和检索记忆:
|
|
|
41
42
|
`nextOffset`;同一时刻按记录顺序倒序。`limit` 默认 20、最多 100,`offset` 默认 0。
|
|
42
43
|
查询期间新增记录可能改变分页位置。
|
|
43
44
|
|
|
44
|
-
`memory-state.json`
|
|
45
|
+
`memory-state.json` 原子保存当前记忆、重要标记和操作历史,包含状态格式版本。首次工具操作自动载入旧
|
|
45
46
|
`memories.json` 的全部记录,保留原文件作迁移快照,此后以 `memory-state.json` 为准。
|
|
46
47
|
没有旧文件时从空记忆开始。操作历史从迁移后开始;修改保留前后全文,删除保留删除前全文,
|
|
47
48
|
重要标记保留替换回执。所有记忆工具调用记录参数及成功或错误状态,包括读取、查询和同义词修改;
|
|
48
49
|
自动召回、系统前缀读取不记操作历史。历史查询本身在结果产生后留痕。
|
|
49
50
|
历史随操作累积、没有自动清理;整份状态文件在写入时重写,适合单进程的小型 Memory。
|
|
50
51
|
同义词文件与操作日志分别保存,日志写入失败会返回“操作可能已生效”的错误。
|
|
52
|
+
`zcor_memory_backup` 生成带时间戳的状态副本;恢复前应先备份当前状态,恢复只接受当前版本的副本。
|
|
51
53
|
|
|
52
54
|
`synonyms.json` 保存词组,首次创建时复制包内的中文及少量英文词组。
|
|
53
55
|
可以通过工具补充,或直接编辑部署侧同义词文件。
|
package/package.json
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-bot-zcor",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.ts",
|
|
6
6
|
"description": "Cortico bot with synonym title retrieval and LLM memory selection",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"keywords": [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
8
|
+
"keywords": [
|
|
9
|
+
"cortico-bot",
|
|
10
|
+
"cortico"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=22"
|
|
14
|
+
},
|
|
15
|
+
"cortico": {
|
|
16
|
+
"kind": "bot",
|
|
17
|
+
"api": 6,
|
|
18
|
+
"displayName": "zcor"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"index.ts",
|
|
22
|
+
"persona",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"cortico": "^0.1.16"
|
|
27
|
+
}
|
|
13
28
|
}
|
package/persona/memory.ts
CHANGED
|
@@ -7,6 +7,7 @@ export const MAX_CANDIDATES = 20;
|
|
|
7
7
|
export const MAX_RESULTS = 5;
|
|
8
8
|
export const MAX_AUTO_RECALL = 10;
|
|
9
9
|
export const MAX_IMPORTANT = 5;
|
|
10
|
+
export const MEMORY_STATE_VERSION = 1;
|
|
10
11
|
|
|
11
12
|
export interface MemoryOperation {
|
|
12
13
|
id: string;
|
|
@@ -15,6 +16,7 @@ export interface MemoryOperation {
|
|
|
15
16
|
details: unknown;
|
|
16
17
|
}
|
|
17
18
|
interface MemoryState {
|
|
19
|
+
version: number;
|
|
18
20
|
records: MemoryRecord[];
|
|
19
21
|
importantIds: string[];
|
|
20
22
|
history: MemoryOperation[];
|
|
@@ -102,6 +104,10 @@ export class MemoryStore {
|
|
|
102
104
|
renameSync(temporary, file);
|
|
103
105
|
}
|
|
104
106
|
|
|
107
|
+
private freshState(records: MemoryRecord[] = []): MemoryState {
|
|
108
|
+
return { version: MEMORY_STATE_VERSION, records, importantIds: [], history: [] };
|
|
109
|
+
}
|
|
110
|
+
|
|
105
111
|
private legacyRecords(): MemoryRecord[] {
|
|
106
112
|
const data: unknown = JSON.parse(readFileSync(this.file, 'utf8'));
|
|
107
113
|
if (!Array.isArray(data) || !data.every((v) => v && typeof v === 'object'
|
|
@@ -112,9 +118,9 @@ export class MemoryStore {
|
|
|
112
118
|
}
|
|
113
119
|
|
|
114
120
|
private state(): MemoryState {
|
|
115
|
-
if (!existsSync(this.stateFile)) return
|
|
121
|
+
if (!existsSync(this.stateFile)) return this.freshState(this.legacyRecords());
|
|
116
122
|
const state = JSON.parse(readFileSync(this.stateFile, 'utf8')) as MemoryState;
|
|
117
|
-
if (!state || !Array.isArray(state.records) || !state.records.every((record) => record
|
|
123
|
+
if (!state || state.version !== MEMORY_STATE_VERSION || !Array.isArray(state.records) || !state.records.every((record) => record
|
|
118
124
|
&& ['id', 'title', 'content', 'createdAt', 'updatedAt'].every((key) =>
|
|
119
125
|
typeof (record as unknown as Record<string, unknown>)[key] === 'string'))
|
|
120
126
|
|| !Array.isArray(state.importantIds) || state.importantIds.length > MAX_IMPORTANT
|
|
@@ -122,7 +128,7 @@ export class MemoryStore {
|
|
|
122
128
|
|| !state.importantIds.every((id) => typeof id === 'string' && state.records.some((r) => r.id === id))
|
|
123
129
|
|| !Array.isArray(state.history) || !state.history.every((entry) => entry
|
|
124
130
|
&& typeof entry.id === 'string' && typeof entry.recordedAt === 'string' && typeof entry.kind === 'string')) {
|
|
125
|
-
throw new Error(
|
|
131
|
+
throw new Error(`memory-state.json 格式错误或版本不支持(需要 ${MEMORY_STATE_VERSION})`);
|
|
126
132
|
}
|
|
127
133
|
return state;
|
|
128
134
|
}
|
|
@@ -130,6 +136,7 @@ export class MemoryStore {
|
|
|
130
136
|
private records(): MemoryRecord[] { return this.state().records; }
|
|
131
137
|
|
|
132
138
|
private commit(state: MemoryState, kind: string, details: unknown): void {
|
|
139
|
+
state.version = MEMORY_STATE_VERSION;
|
|
133
140
|
state.history.push({ id: randomUUID(), recordedAt: this.now(), kind, details });
|
|
134
141
|
this.save(this.stateFile, state);
|
|
135
142
|
}
|
|
@@ -138,6 +145,22 @@ export class MemoryStore {
|
|
|
138
145
|
this.commit(this.state(), kind, details);
|
|
139
146
|
}
|
|
140
147
|
|
|
148
|
+
backup(): string {
|
|
149
|
+
const backupFile = `${this.stateFile}.bak-${this.now().replace(/[:.]/g, '-')}`;
|
|
150
|
+
writeFileSync(backupFile, readFileSync(this.stateFile, 'utf8'), 'utf8');
|
|
151
|
+
return backupFile;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
restore(backupFile: unknown): void {
|
|
155
|
+
const file = requiredText(backupFile, 'backupFile');
|
|
156
|
+
const restored = JSON.parse(readFileSync(file, 'utf8')) as MemoryState;
|
|
157
|
+
if (restored.version !== MEMORY_STATE_VERSION || !Array.isArray(restored.records)
|
|
158
|
+
|| !Array.isArray(restored.importantIds) || !Array.isArray(restored.history)) {
|
|
159
|
+
throw new Error(`备份格式错误或版本不支持(需要 ${MEMORY_STATE_VERSION})`);
|
|
160
|
+
}
|
|
161
|
+
this.save(this.stateFile, restored);
|
|
162
|
+
}
|
|
163
|
+
|
|
141
164
|
important(): MemoryRecord[] {
|
|
142
165
|
const state = this.state();
|
|
143
166
|
return state.importantIds.map((id) => state.records.find((record) => record.id === id)!);
|
package/persona/persona.ts
CHANGED
|
@@ -128,6 +128,13 @@ export class ZcorPersona implements Persona {
|
|
|
128
128
|
query, [], ['read'], (args) => this.memory.query(args)),
|
|
129
129
|
tool('zcor_memory_history', '本地查询操作记录:按操作时间范围(含端点)及记录全文关键词全部命中筛选。包含修改前后内容、删除快照、重要标记和工具调用结果状态;按时间倒序分页,不调用 LLM。',
|
|
130
130
|
query, [], ['read'], (args) => this.memory.history(args)),
|
|
131
|
+
tool('zcor_memory_backup', '将当前 Memory 状态复制为带时间戳的备份文件。', {}, [], ['write'],
|
|
132
|
+
() => ({ file: this.memory.backup() })),
|
|
133
|
+
tool('zcor_memory_restore', '从指定备份文件恢复 Memory 状态;恢复前应先备份当前状态。',
|
|
134
|
+
{ backupFile: string }, ['backupFile'], ['write'], (args) => {
|
|
135
|
+
this.memory.restore(args.backupFile);
|
|
136
|
+
return { restored: true };
|
|
137
|
+
}),
|
|
131
138
|
tool('zcor_memory_delete', '按 id 删除当前记忆;操作历史保留删除前内容。', { id: string }, ['id'], ['write'],
|
|
132
139
|
(args) => ({ deleted: this.memory.delete(args.id) })),
|
|
133
140
|
tool('zcor_synonyms_add', '保存一组同义词,查询时双向扩展,重叠词组连通。',
|