@jesonliu/lark-claudecode-bridge 1.4.0 → 1.4.2
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/assets/web/js/pages/memory.js +551 -102
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/gateway/card-builder.js +3 -2
- package/dist/gateway/card-builder.js.map +1 -1
- package/dist/gateway/progress-card.d.ts +19 -2
- package/dist/gateway/progress-card.js +71 -8
- package/dist/gateway/progress-card.js.map +1 -1
- package/dist/index.js +95 -52
- package/dist/index.js.map +1 -1
- package/dist/memory-installer.d.ts +53 -2
- package/dist/memory-installer.js +294 -67
- package/dist/memory-installer.js.map +1 -1
- package/dist/memory.d.ts +22 -2
- package/dist/memory.js +123 -26
- package/dist/memory.js.map +1 -1
- package/dist/types.d.ts +17 -3
- package/dist/util/file-tracker.d.ts +2 -7
- package/dist/util/file-tracker.js +2 -24
- package/dist/util/file-tracker.js.map +1 -1
- package/dist/web/config-api.js +15 -8
- package/dist/web/config-api.js.map +1 -1
- package/dist/web/memory-api.d.ts +10 -2
- package/dist/web/memory-api.js +25 -5
- package/dist/web/memory-api.js.map +1 -1
- package/dist/web/memory-users-api.d.ts +106 -0
- package/dist/web/memory-users-api.js +534 -0
- package/dist/web/memory-users-api.js.map +1 -0
- package/dist/web/server.js +88 -5
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
// 「用户与密钥」Tab 后端(记忆系统最终方案 v1.1 §六 Tab2 / §三 决策 2·4·5):Admin API 用户
|
|
2
|
+
// 聚合 + 密钥保险库 + 审计留痕。
|
|
3
|
+
//
|
|
4
|
+
// 身份模型(OpenViking 0.5.0 源码实证,见方案附录):key = base64url(account).base64url(user).
|
|
5
|
+
// base64url(secret),一把 key 天然绑定一个固定身份;api_key 模式下声明头被服务端静默删除,
|
|
6
|
+
// 身份只认 key。Admin API(X-API-Key 携 root key):
|
|
7
|
+
// - GET /api/v1/admin/accounts/{account}/users → 列表(api_key 模式下明文回带 api_key,
|
|
8
|
+
// server/auth/__init__.py should_expose_user_key:trusted 模式才隐藏——LCB 的保险库可自愈回读)
|
|
9
|
+
// - POST /api/v1/admin/accounts/{account}/users → 创建即返回 user_key(仅此响应出现)
|
|
10
|
+
// - POST /api/v1/admin/accounts/{account}/users/{uid}/key → Regenerate(旧 key 立即失效)
|
|
11
|
+
// - DELETE /api/v1/admin/accounts/{account}/users/{uid} → 202 异步清理(LCB 先备份再删)
|
|
12
|
+
//
|
|
13
|
+
// 安全边界(方案 §六 / §七):
|
|
14
|
+
// - 密钥明文只在本进程与 Admin API 间流转;落盘一律 DPAPI 加密(Windows CurrentUser 域绑定,
|
|
15
|
+
// PowerShell stdin 传 base64,明文不上命令行——进程列表不可见);
|
|
16
|
+
// - 浏览器只见脱敏提示;reveal(打开记忆空间 / 复制 key)单次放行并留痕;
|
|
17
|
+
// - 每次查看/重置/删除/初始化行为写审计日志(JSONL 追加);
|
|
18
|
+
// - 删除动作备份前置:打包 user 目录(明文数据可直接 tar/zip)到 backups/ 再调 Admin 删除。
|
|
19
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from 'node:fs';
|
|
20
|
+
import { spawn } from 'node:child_process';
|
|
21
|
+
import { dirname, join } from 'node:path';
|
|
22
|
+
import { MANAGED_OV_CONF, MEMORY_MANAGED_DIR } from '../memory-installer.js';
|
|
23
|
+
import { DEFAULT_MEMORY_ACCOUNT, memoryAccount, memoryEndpoint, ensureRemoteAccount, probeMemoryHealth } from '../memory.js';
|
|
24
|
+
import { maskSecret } from './config-api.js';
|
|
25
|
+
/** 网页管理端用户约定 uid(方案 §四 阶段 3:{"user_id":"web"}) */
|
|
26
|
+
export const WEB_USER_ID = 'web';
|
|
27
|
+
/** 密钥保险库(uid → base64(DPAPI(plain));DPAPI CurrentUser 域绑定,换机/换账户不可解密) */
|
|
28
|
+
const VAULT_FILE = join(MEMORY_MANAGED_DIR, 'user-keys.vault.json');
|
|
29
|
+
/** 审计日志(JSONL 追加;查看/重置/删除/初始化留痕,方案 §六「管理员每次查看行为留痕」) */
|
|
30
|
+
export const MEMORY_AUDIT_LOG = join(MEMORY_MANAGED_DIR, 'audit.log');
|
|
31
|
+
/** 删除前备份目录(先备份后删除,方案 §六/§七「清理动作必须二次确认 + 先备份」) */
|
|
32
|
+
export const MEMORY_BACKUP_DIR = join(MEMORY_MANAGED_DIR, 'backups');
|
|
33
|
+
/** user_id 合法性(路径安全 + OpenViking uid 口径):字母数字下划线连字符,≤128 */
|
|
34
|
+
export function isValidUserId(uid) {
|
|
35
|
+
return /^[A-Za-z0-9_-]{1,128}$/.test(uid);
|
|
36
|
+
}
|
|
37
|
+
// ============ 审计留痕 ============
|
|
38
|
+
/** 审计写一条(JSONL;失败静默——留痕不可用不应阻断管理动作本身) */
|
|
39
|
+
export function auditMemory(action, detail = {}) {
|
|
40
|
+
try {
|
|
41
|
+
mkdirSync(MEMORY_MANAGED_DIR, { recursive: true });
|
|
42
|
+
appendFileSync(MEMORY_AUDIT_LOG, JSON.stringify({ ts: new Date().toISOString(), action, ...detail }) + '\n', 'utf8');
|
|
43
|
+
}
|
|
44
|
+
catch { /* 留痕失败不阻断 */ }
|
|
45
|
+
}
|
|
46
|
+
// ============ root key 解析 ============
|
|
47
|
+
/** 读受管 ov.conf 的 server.root_api_key(memory.api_key 未配置时的兜底——一键安装写 conf 后
|
|
48
|
+
* config.yaml 回写中断等场景,root key 仍在 conf 里可自愈) */
|
|
49
|
+
function managedRootKey() {
|
|
50
|
+
try {
|
|
51
|
+
const doc = JSON.parse(readFileSync(MANAGED_OV_CONF, 'utf8'));
|
|
52
|
+
return doc.server?.root_api_key || undefined;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Admin API 用的 root key:config.memory.api_key 优先,受管 conf 兜底 */
|
|
59
|
+
function resolveRootKey(memory) {
|
|
60
|
+
return memory?.apiKey?.trim() || managedRootKey();
|
|
61
|
+
}
|
|
62
|
+
/** Admin API 调用(X-API-Key 携 root key;10s 超时——管理面动作不拖页面)。root key 只进本进程 */
|
|
63
|
+
async function adminCall(memory, rootKey, method, path, body) {
|
|
64
|
+
const base = memoryEndpoint(memory).replace(/\/+$/, '');
|
|
65
|
+
try {
|
|
66
|
+
const res = await fetch(`${base}${path}`, {
|
|
67
|
+
method,
|
|
68
|
+
headers: { 'X-API-Key': rootKey, ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}) },
|
|
69
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
70
|
+
signal: AbortSignal.timeout(10_000),
|
|
71
|
+
});
|
|
72
|
+
const json = (await res.json().catch(() => ({})));
|
|
73
|
+
// 错误文案:OpenViking 错误体为 {error:{code,message}},顶层 message 形态只在旧版本出现——
|
|
74
|
+
// 只读顶层 message 时,所有 404 都退化成裸「HTTP 404」(账号名写错的真因就此隐身)
|
|
75
|
+
const errObj = json.error && typeof json.error === 'object' ? json.error : undefined;
|
|
76
|
+
const code = typeof errObj?.code === 'string' ? errObj.code : undefined;
|
|
77
|
+
const msg = (typeof errObj?.message === 'string' ? errObj.message : undefined)
|
|
78
|
+
?? (typeof json.error === 'string' ? json.error : undefined)
|
|
79
|
+
?? (typeof json.message === 'string' ? json.message : undefined);
|
|
80
|
+
return { ok: res.ok, status: res.status, json, ...(msg ? { message: code ? `${code}: ${msg}` : msg } : {}) };
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
return { ok: false, status: 0, json: {}, message: e instanceof Error ? e.message : String(e) };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const adminPath = (memory, suffix) => `/api/v1/admin/accounts/${encodeURIComponent(memoryAccount(memory))}${suffix}`;
|
|
87
|
+
function loadVault() {
|
|
88
|
+
try {
|
|
89
|
+
const doc = JSON.parse(readFileSync(VAULT_FILE, 'utf8'));
|
|
90
|
+
return doc && typeof doc === 'object' && !Array.isArray(doc) ? doc : {};
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** 原子写(tmp + rename;与 memory-installer writeAtomic 同款,独立内联避免反向依赖) */
|
|
97
|
+
function writeAtomic(path, text) {
|
|
98
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
99
|
+
const tmp = `${path}.tmp-${Date.now()}`;
|
|
100
|
+
writeFileSync(tmp, text, 'utf8');
|
|
101
|
+
renameSync(tmp, path);
|
|
102
|
+
}
|
|
103
|
+
function saveVault(v) {
|
|
104
|
+
writeAtomic(VAULT_FILE, JSON.stringify(v, null, 2));
|
|
105
|
+
}
|
|
106
|
+
function removeVaultEntry(uid) {
|
|
107
|
+
const v = loadVault();
|
|
108
|
+
if (!(uid in v))
|
|
109
|
+
return;
|
|
110
|
+
delete v[uid];
|
|
111
|
+
saveVault(v);
|
|
112
|
+
}
|
|
113
|
+
/** DPAPI protect/unprotect(PowerShell stdin 收发 base64——明文不上命令行,进程列表不可见;
|
|
114
|
+
* CurrentUser 域绑定 = 同机同账户可解,符合「机器绑定加密」约束)。非 Windows 返回 null(调用方降级) */
|
|
115
|
+
function dpapi(mode, b64) {
|
|
116
|
+
if (process.platform !== 'win32')
|
|
117
|
+
return Promise.resolve(null);
|
|
118
|
+
const script = mode === 'protect'
|
|
119
|
+
? `Add-Type -AssemblyName System.Security;$b=[Convert]::FromBase64String([Console]::In.ReadToEnd().Trim());$p=[System.Security.Cryptography.ProtectedData]::Protect($b,$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser);[Console]::Out.Write([Convert]::ToBase64String($p))`
|
|
120
|
+
: `Add-Type -AssemblyName System.Security;$b=[Convert]::FromBase64String([Console]::In.ReadToEnd().Trim());$u=[System.Security.Cryptography.ProtectedData]::Unprotect($b,$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser);[Console]::Out.Write([Convert]::ToBase64String($u))`;
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
try {
|
|
123
|
+
const p = spawn('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
124
|
+
let out = '', err = '';
|
|
125
|
+
const timer = setTimeout(() => { try {
|
|
126
|
+
p.kill();
|
|
127
|
+
}
|
|
128
|
+
catch { /* 已退出 */ } resolve(null); }, 15_000);
|
|
129
|
+
p.stdout.on('data', (d) => { out += String(d); });
|
|
130
|
+
p.stderr.on('data', (d) => { err += String(d); });
|
|
131
|
+
p.on('error', () => { clearTimeout(timer); resolve(null); });
|
|
132
|
+
p.on('close', (code) => {
|
|
133
|
+
clearTimeout(timer);
|
|
134
|
+
resolve(code === 0 && out.trim() ? out.trim() : null);
|
|
135
|
+
if (code !== 0)
|
|
136
|
+
console.warn(`[memory-users] DPAPI ${mode} 失败(退出码 ${code}):${err.trim().slice(0, 200)}`);
|
|
137
|
+
});
|
|
138
|
+
p.stdin.write(b64);
|
|
139
|
+
p.stdin.end();
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
resolve(null);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** 密钥入保险库:Windows DPAPI 加密;其他平台降级 base64 混淆 + 控制台明示(方案适用面为 Windows)。
|
|
147
|
+
* 明文进程内缓存:列表每次聚合都会回带 api_key——值未变时跳过 DPAPI 重加密(省一次 PowerShell 进程) */
|
|
148
|
+
const vaultSeenPlain = new Map();
|
|
149
|
+
async function vaultStore(uid, plain) {
|
|
150
|
+
if (vaultSeenPlain.get(uid) === plain && loadVault()[uid])
|
|
151
|
+
return;
|
|
152
|
+
const v = loadVault();
|
|
153
|
+
if (process.platform === 'win32') {
|
|
154
|
+
const b64 = Buffer.from(plain, 'utf8').toString('base64');
|
|
155
|
+
const sealed = await dpapi('protect', b64);
|
|
156
|
+
if (sealed) {
|
|
157
|
+
v[uid] = sealed;
|
|
158
|
+
saveVault(v);
|
|
159
|
+
vaultSeenPlain.set(uid, plain);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
console.warn('[memory-users] DPAPI 保护失败,降级 base64 混淆存储(建议检查 PowerShell 可用性)');
|
|
163
|
+
v[uid] = `plain:${b64}`;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
v[uid] = `plain:${Buffer.from(plain, 'utf8').toString('base64')}`;
|
|
167
|
+
}
|
|
168
|
+
saveVault(v);
|
|
169
|
+
vaultSeenPlain.set(uid, plain);
|
|
170
|
+
}
|
|
171
|
+
/** 取密钥明文(reveal / 打开记忆空间用;解不开返回 undefined) */
|
|
172
|
+
async function vaultRead(uid) {
|
|
173
|
+
const sealed = loadVault()[uid];
|
|
174
|
+
if (!sealed)
|
|
175
|
+
return undefined;
|
|
176
|
+
if (sealed.startsWith('plain:')) {
|
|
177
|
+
try {
|
|
178
|
+
return Buffer.from(sealed.slice(6), 'base64').toString('utf8');
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const b64 = await dpapi('unprotect', sealed);
|
|
185
|
+
if (!b64)
|
|
186
|
+
return undefined;
|
|
187
|
+
try {
|
|
188
|
+
return Buffer.from(b64, 'base64').toString('utf8');
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// ============ 磁盘元信息(体量 / 最近活跃) ============
|
|
195
|
+
/** user 目录(方案 §五-P3:data/viking/<account>/user/<uid>/ 为明文,可直接统计/打包) */
|
|
196
|
+
export function memoryUserDir(account, uid) {
|
|
197
|
+
return join(MEMORY_MANAGED_DIR, 'data', 'viking', account, 'user', uid);
|
|
198
|
+
}
|
|
199
|
+
/** 递归统计目录体量与最近修改(容错:目录不存在/单文件 stat 失败均按 0 继续) */
|
|
200
|
+
function dirStats(dir) {
|
|
201
|
+
let size = 0;
|
|
202
|
+
let last = 0;
|
|
203
|
+
const walk = (d) => {
|
|
204
|
+
let entries;
|
|
205
|
+
try {
|
|
206
|
+
entries = readdirSync(d, { withFileTypes: true });
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
for (const e of entries) {
|
|
212
|
+
const p = join(d, e.name);
|
|
213
|
+
if (e.isDirectory())
|
|
214
|
+
walk(p);
|
|
215
|
+
else {
|
|
216
|
+
try {
|
|
217
|
+
const st = statSync(p);
|
|
218
|
+
size += st.size;
|
|
219
|
+
if (st.mtimeMs > last)
|
|
220
|
+
last = st.mtimeMs;
|
|
221
|
+
}
|
|
222
|
+
catch { /* 竞态删除/权限:跳过该文件 */ }
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
if (existsSync(dir))
|
|
227
|
+
walk(dir);
|
|
228
|
+
return { sizeBytes: size, ...(last ? { lastActive: new Date(last).toISOString() } : {}) };
|
|
229
|
+
}
|
|
230
|
+
/** Root 密钥状态(供快照携带;明文一律不放行,见 MemoryUsersSnapshot.rootKey) */
|
|
231
|
+
function rootKeyStatus(memory) {
|
|
232
|
+
if (!memory)
|
|
233
|
+
return { configured: false, source: 'missing' };
|
|
234
|
+
if (memory.apiKey?.trim())
|
|
235
|
+
return { configured: true, source: 'config' };
|
|
236
|
+
if (managedRootKey())
|
|
237
|
+
return { configured: true, source: 'ov-conf' };
|
|
238
|
+
return { configured: false, source: 'missing' };
|
|
239
|
+
}
|
|
240
|
+
/** 用户列表聚合:Admin API + 本地磁盘统计。全程容错(服务不可达返回可达性标记,不抛出) */
|
|
241
|
+
export async function listMemoryUsers(config) {
|
|
242
|
+
const memory = config.memory;
|
|
243
|
+
const account = memory ? memoryAccount(memory) : DEFAULT_MEMORY_ACCOUNT;
|
|
244
|
+
const empty = { reachable: false, users: [], totalBytes: 0, authInitNeeded: false };
|
|
245
|
+
if (!memory)
|
|
246
|
+
return { ...empty, error: 'memory 段未配置', rootKey: rootKeyStatus(undefined) };
|
|
247
|
+
const health = await probeMemoryHealth(memoryEndpoint(memory));
|
|
248
|
+
if (!health.healthy)
|
|
249
|
+
return { ...empty, error: health.detail ?? '服务不可达', rootKey: rootKeyStatus(memory), ...(health.authMode ? { authMode: health.authMode } : {}) };
|
|
250
|
+
if (health.authMode !== 'api_key') {
|
|
251
|
+
// dev 模式:Admin API 被服务端禁用(403)——这是「无需用户密钥」的正常形态而非错误
|
|
252
|
+
return { reachable: true, authMode: health.authMode, users: [], totalBytes: 0, authInitNeeded: false, rootKey: rootKeyStatus(memory) };
|
|
253
|
+
}
|
|
254
|
+
const rootKey = resolveRootKey(memory);
|
|
255
|
+
if (!rootKey)
|
|
256
|
+
return { ...empty, authMode: health.authMode, rootKey: rootKeyStatus(memory), error: 'root key 未配置(memory.api_key 与受管 ov.conf 均未见)——请先「检查修复」对齐鉴权' };
|
|
257
|
+
const r = await adminCall(memory, rootKey, 'GET', adminPath(memory, '/users'));
|
|
258
|
+
if (!r.ok) {
|
|
259
|
+
return { ...empty, authMode: health.authMode, rootKey: rootKeyStatus(memory), error: `用户列表获取失败:HTTP ${r.status}${r.message ? `(${r.message})` : ''}` };
|
|
260
|
+
}
|
|
261
|
+
const rawUsers = (Array.isArray(r.json.result) ? r.json.result : []);
|
|
262
|
+
const botNames = new Map(config.apps.map((a) => [a.appId, a.name]));
|
|
263
|
+
const rows = [];
|
|
264
|
+
for (const u of rawUsers) {
|
|
265
|
+
const uid = String(u.user_id ?? '');
|
|
266
|
+
if (!uid)
|
|
267
|
+
continue;
|
|
268
|
+
// 保险库自愈:列表明文回带的 api_key 刷入保险库(DPAPI 重加密)——重装/换 Key 后无须重初始化
|
|
269
|
+
if (typeof u.api_key === 'string' && u.api_key)
|
|
270
|
+
await vaultStore(uid, u.api_key);
|
|
271
|
+
const kind = uid === WEB_USER_ID ? 'web' : botNames.has(uid) ? 'bot' : 'other';
|
|
272
|
+
// 聊天者维度(历史复合 ID:{appId}-{ou_xxx},插件旧口径创建):前缀归属到对应飞书应用,
|
|
273
|
+
// 页面显示「<应用名> · 聊天者」——OpenViking 无显示名字段(user_id 仅 ASCII),1933 右上角
|
|
274
|
+
// 只能显示技术 ID,人可读对照以本列表为准
|
|
275
|
+
const ownerBot = kind === 'other'
|
|
276
|
+
? [...botNames.entries()].find(([appId]) => uid.startsWith(`${appId}-`))
|
|
277
|
+
: undefined;
|
|
278
|
+
const stats = dirStats(memoryUserDir(account, uid));
|
|
279
|
+
rows.push({
|
|
280
|
+
userId: uid,
|
|
281
|
+
kind,
|
|
282
|
+
...(kind === 'bot' ? { appName: botNames.get(uid) } : ownerBot ? { appName: `${ownerBot[1]} · 聊天者` } : {}),
|
|
283
|
+
...(u.role ? { role: u.role } : {}),
|
|
284
|
+
keyAvailable: typeof u.api_key === 'string' && !!u.api_key,
|
|
285
|
+
...(typeof u.api_key === 'string' && u.api_key ? { keyHint: maskSecret(u.api_key).secretHint } : {}),
|
|
286
|
+
sizeBytes: stats.sizeBytes,
|
|
287
|
+
...(stats.lastActive ? { lastActive: stats.lastActive } : {}),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
reachable: true,
|
|
292
|
+
authMode: health.authMode,
|
|
293
|
+
users: rows,
|
|
294
|
+
totalBytes: rows.reduce((s, r2) => s + (r2.sizeBytes ?? 0), 0),
|
|
295
|
+
// 待初始化:api_key 模式跑着但网页端用户还没建(浏览器打开 1933 会 401 重定向的根因)
|
|
296
|
+
authInitNeeded: !rows.some((x) => x.userId === WEB_USER_ID),
|
|
297
|
+
rootKey: rootKeyStatus(memory),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/** 一键初始化(方案 §六:建 web 用户 + 各 bot 用户 → 签 key → 加密落盘)。幂等可重跑:
|
|
301
|
+
* 已存在用户由列表自愈回读 key(创建响应的 user_key 只出现一次,但 api_key 模式列表可回带)。
|
|
302
|
+
* dev 模式 / 服务不可达:直接说明,不视为失败动作。 */
|
|
303
|
+
export async function initMemoryUsers(config) {
|
|
304
|
+
const memory = config.memory;
|
|
305
|
+
const out = { ok: false, created: [], existing: [], errors: [], detail: '' };
|
|
306
|
+
if (!memory)
|
|
307
|
+
return { ...out, errors: ['memory 段未配置'], detail: '请先开启记忆增强并保存模型配置' };
|
|
308
|
+
const health = await probeMemoryHealth(memoryEndpoint(memory));
|
|
309
|
+
if (!health.healthy)
|
|
310
|
+
return { ...out, errors: [`服务不可达(${health.detail ?? '未知原因'})`], detail: '请先在「服务与配置」拉起服务,再一键初始化' };
|
|
311
|
+
if (health.authMode !== 'api_key') {
|
|
312
|
+
return {
|
|
313
|
+
...out, ok: true,
|
|
314
|
+
detail: `服务为 ${health.authMode ?? '未知'} 模式:本机回环免鉴权、身份经命名空间隔离,无须创建用户密钥(部署走向 api_key 模式后再初始化)`,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const rootKey = resolveRootKey(memory);
|
|
318
|
+
if (!rootKey)
|
|
319
|
+
return { ...out, errors: ['root key 未配置'], detail: '「检查修复」可对齐 memory.api_key 与受管 ov.conf' };
|
|
320
|
+
// 账号兜底:服务端只认已存在账号,账号不存在时下面每个用户都会 404(历史上表现为
|
|
321
|
+
// 「创建 xxx 失败:HTTP 404」全红,用户无从判断是账号问题还是服务没起)→ 缺账号先自动建
|
|
322
|
+
const account = memoryAccount(memory);
|
|
323
|
+
const accountReady = await ensureRemoteAccount(memoryEndpoint(memory).replace(/\/+$/, ''), account, rootKey);
|
|
324
|
+
if (!accountReady.ok) {
|
|
325
|
+
return {
|
|
326
|
+
...out,
|
|
327
|
+
errors: [`记忆账号「${account}」不可用:${accountReady.detail}`],
|
|
328
|
+
detail: '请核对 config.yaml 的 memory.account(缺省 default)是否与服务端账号一致',
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
// 期望用户:web + 每个 bot(appId 即 OpenViking 侧 user_id,与 ensureMemoryUserKeys 签发口径一致)
|
|
332
|
+
const desired = [WEB_USER_ID, ...config.apps.map((a) => a.appId)];
|
|
333
|
+
// 先列表自愈:已存在用户的 key 直接刷保险库(避免对已存在用户重复创建撞 409)
|
|
334
|
+
const listR = await adminCall(memory, rootKey, 'GET', adminPath(memory, '/users'));
|
|
335
|
+
const known = new Set();
|
|
336
|
+
if (listR.ok && Array.isArray(listR.json.result)) {
|
|
337
|
+
for (const u of listR.json.result) {
|
|
338
|
+
const uid = String(u.user_id ?? '');
|
|
339
|
+
if (uid)
|
|
340
|
+
known.add(uid);
|
|
341
|
+
if (uid && typeof u.api_key === 'string' && u.api_key)
|
|
342
|
+
await vaultStore(uid, u.api_key);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
for (const uid of desired) {
|
|
346
|
+
if (!isValidUserId(uid)) {
|
|
347
|
+
out.errors.push(`用户名 ${uid} 含非法字符,跳过`);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
if (known.has(uid)) {
|
|
351
|
+
out.existing.push(uid);
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
const r = await adminCall(memory, rootKey, 'POST', adminPath(memory, '/users'), { user_id: uid, role: 'user' });
|
|
355
|
+
const result = (r.json.result ?? {});
|
|
356
|
+
if (r.ok && typeof result.user_key === 'string' && result.user_key) {
|
|
357
|
+
await vaultStore(uid, result.user_key);
|
|
358
|
+
out.created.push(uid);
|
|
359
|
+
}
|
|
360
|
+
else if (r.ok) {
|
|
361
|
+
// 创建成功但响应未带 key(should_expose_user_key=false 等服务端形态)→ 列表自愈兜底
|
|
362
|
+
out.created.push(uid);
|
|
363
|
+
out.errors.push(`${uid} 已创建但响应未含密钥——已尝试从用户列表回读`);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
const why = r.message ? `(${r.message})` : '';
|
|
367
|
+
const hint = r.status === 404
|
|
368
|
+
? '——服务端不存在该账号或用户,请核对 config.yaml 的 memory.account(缺省 default)'
|
|
369
|
+
: r.status === 409 ? '(用户已存在,可直接「重置密钥」)' : '';
|
|
370
|
+
out.errors.push(`创建 ${uid} 失败:HTTP ${r.status}${why}${hint}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
out.ok = out.errors.length === 0;
|
|
374
|
+
out.detail = `初始化完成:新建 ${out.created.length ? out.created.join('、') : '无'};已存在 ${out.existing.length ? out.existing.join('、') : '无'}${out.errors.length ? `;${out.errors.length} 项异常` : ''}`;
|
|
375
|
+
auditMemory('init', { created: out.created, existing: out.existing, errors: out.errors });
|
|
376
|
+
return out;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* 取 Root 密钥明文(单次放行 + 审计留痕)——**给 OpenViking Studio 的登录框用**。
|
|
380
|
+
* 背景(用户实测卡点):Studio 首屏要填「Root 或账号管理员 API 密钥」,而 LCB 配置页此前
|
|
381
|
+
* 完全没有 root key 的入口,唯一长得像的「模型配置 → API Key」是智谱模型 key,填进去必然 401。
|
|
382
|
+
* Studio 自己的提示写的是「Root API 密钥位于服务端 ov.conf 的 server.root_api_key」,本页就按
|
|
383
|
+
* 同一口径给出处 + 复制按钮,别让用户自己在磁盘上翻配置文件。
|
|
384
|
+
* 顺带校验:带 key 打一次 /api/v1/system/status(api_key 模式下鉴权通过的证明),把「拷贝即用」
|
|
385
|
+
* 的确定性前置到本页,而不是让用户在 Studio 的报错里猜。
|
|
386
|
+
*/
|
|
387
|
+
export async function revealRootKey(config) {
|
|
388
|
+
const memory = config.memory;
|
|
389
|
+
if (!memory)
|
|
390
|
+
return { ok: false, error: 'memory 段未配置' };
|
|
391
|
+
const fromConfig = memory.apiKey?.trim();
|
|
392
|
+
const rootKey = resolveRootKey(memory);
|
|
393
|
+
if (!rootKey) {
|
|
394
|
+
return {
|
|
395
|
+
ok: false,
|
|
396
|
+
error: 'Root 密钥未配置:config.yaml 的 memory.api_key 与受管 ov.conf 的 server.root_api_key 均为空。'
|
|
397
|
+
+ '请到「服务与配置」点「检查修复」重新生成,或手工把 ov.conf 里的 server.root_api_key 回写到 memory.api_key',
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
const source = fromConfig ? 'config' : 'ov-conf';
|
|
401
|
+
auditMemory('reveal-root', { source });
|
|
402
|
+
// 校验:/system/status 在 api_key 模式下带 X-API-Key 通过即有效;dev 模式不校验直接视为有效
|
|
403
|
+
const health = await probeMemoryHealth(memoryEndpoint(memory));
|
|
404
|
+
if (health.authMode && health.authMode !== 'api_key') {
|
|
405
|
+
return { ok: true, key: rootKey, source, valid: true, validDetail: `服务为 ${health.authMode} 模式,Studio 无需密钥` };
|
|
406
|
+
}
|
|
407
|
+
if (!health.healthy) {
|
|
408
|
+
return { ok: true, key: rootKey, source, valid: false, validDetail: `服务不可达,未能校验(${health.detail ?? '未知原因'})` };
|
|
409
|
+
}
|
|
410
|
+
const r = await adminCall(memory, rootKey, 'GET', '/api/v1/system/status');
|
|
411
|
+
return {
|
|
412
|
+
ok: true,
|
|
413
|
+
key: rootKey,
|
|
414
|
+
source,
|
|
415
|
+
valid: r.ok,
|
|
416
|
+
...(r.ok ? {} : { validDetail: `校验未通过:HTTP ${r.status}${r.message ? `(${r.message})` : ''}——这把密钥与服务端不匹配` }),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
/** 取某用户密钥明文(单次放行 + 审计留痕)。保险库未命中时尝试列表自愈回读(服务端 api_key
|
|
420
|
+
* 模式列表可回带明文),再未命中提示重置。root key / 他人密钥的边界:本接口只服务本机配置页 */
|
|
421
|
+
export async function revealUserKey(config, uid) {
|
|
422
|
+
if (!isValidUserId(uid))
|
|
423
|
+
return { ok: false, error: '用户名非法' };
|
|
424
|
+
const memory = config.memory;
|
|
425
|
+
if (!memory)
|
|
426
|
+
return { ok: false, error: 'memory 段未配置' };
|
|
427
|
+
const cached = await vaultRead(uid);
|
|
428
|
+
if (cached) {
|
|
429
|
+
auditMemory('reveal', { user_id: uid, source: 'vault' });
|
|
430
|
+
return { ok: true, key: cached };
|
|
431
|
+
}
|
|
432
|
+
// 自愈:服务端列表回读 → 刷保险库
|
|
433
|
+
const rootKey = resolveRootKey(memory);
|
|
434
|
+
if (rootKey) {
|
|
435
|
+
const r = await adminCall(memory, rootKey, 'GET', adminPath(memory, '/users'));
|
|
436
|
+
if (r.ok && Array.isArray(r.json.result)) {
|
|
437
|
+
const hit = r.json.result.find((u) => String(u.user_id ?? '') === uid);
|
|
438
|
+
if (hit && typeof hit.api_key === 'string' && hit.api_key) {
|
|
439
|
+
await vaultStore(uid, hit.api_key);
|
|
440
|
+
auditMemory('reveal', { user_id: uid, source: 'admin-list' });
|
|
441
|
+
return { ok: true, key: hit.api_key };
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
auditMemory('reveal-miss', { user_id: uid });
|
|
446
|
+
return { ok: false, error: '本地保险库无此密钥且服务端未回带——请用「重置」重新签发(旧使用方需同步更新)' };
|
|
447
|
+
}
|
|
448
|
+
// ============ 重置(Regenerate) ============
|
|
449
|
+
/** 重置密钥(Admin Regenerate:旧 key 立即失效,新 key 入保险库)。方案 §六:危险操作,
|
|
450
|
+
* 前端二次确认 + 提示「所有使用方需同步更新 + 重启会话」;此处负责执行与留痕 */
|
|
451
|
+
export async function resetUserKey(config, uid) {
|
|
452
|
+
if (!isValidUserId(uid))
|
|
453
|
+
return { ok: false, error: '用户名非法' };
|
|
454
|
+
const memory = config.memory;
|
|
455
|
+
if (!memory)
|
|
456
|
+
return { ok: false, error: 'memory 段未配置' };
|
|
457
|
+
const rootKey = resolveRootKey(memory);
|
|
458
|
+
if (!rootKey)
|
|
459
|
+
return { ok: false, error: 'root key 未配置' };
|
|
460
|
+
const r = await adminCall(memory, rootKey, 'POST', adminPath(memory, `/users/${encodeURIComponent(uid)}/key`), {});
|
|
461
|
+
const result = (r.json.result ?? {});
|
|
462
|
+
if (r.ok && typeof result.user_key === 'string' && result.user_key) {
|
|
463
|
+
await vaultStore(uid, result.user_key);
|
|
464
|
+
auditMemory('reset', { user_id: uid });
|
|
465
|
+
return { ok: true, key: result.user_key };
|
|
466
|
+
}
|
|
467
|
+
auditMemory('reset-fail', { user_id: uid, status: r.status });
|
|
468
|
+
return { ok: false, error: `重置失败:HTTP ${r.status}${r.message ? `(${r.message})` : ''}` };
|
|
469
|
+
}
|
|
470
|
+
// ============ 删除(备份前置) ============
|
|
471
|
+
/** 打包目录为压缩档(Windows bsdtar -a 依扩展名产 zip;其他平台 GNU tar 产 tar.gz)。
|
|
472
|
+
* 返回备份文件路径。tar 失败抛错(调用方放弃删除——备份前置是硬约束) */
|
|
473
|
+
async function backupUserDir(account, uid) {
|
|
474
|
+
const srcDir = memoryUserDir(account, uid);
|
|
475
|
+
if (!existsSync(srcDir))
|
|
476
|
+
return ''; // 无数据目录(纯密钥用户):无须备份
|
|
477
|
+
mkdirSync(MEMORY_BACKUP_DIR, { recursive: true });
|
|
478
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
479
|
+
const isWin = process.platform === 'win32';
|
|
480
|
+
const archive = join(MEMORY_BACKUP_DIR, `${uid}-${stamp}${isWin ? '.zip' : '.tar.gz'}`);
|
|
481
|
+
const tarCmd = isWin ? join(process.env.SystemRoot ?? 'C:\\Windows', 'System32', 'tar.exe') : 'tar';
|
|
482
|
+
const args = isWin ? ['-a', '-c', '-f', archive, '-C', dirname(srcDir), uid] : ['-czf', archive, '-C', dirname(srcDir), uid];
|
|
483
|
+
await new Promise((resolve, reject) => {
|
|
484
|
+
const p = spawn(tarCmd, args, { windowsHide: true, stdio: ['ignore', 'ignore', 'pipe'] });
|
|
485
|
+
let err = '';
|
|
486
|
+
p.stderr?.on('data', (d) => { err += String(d); });
|
|
487
|
+
p.on('error', reject);
|
|
488
|
+
p.on('close', (code) => code === 0 ? resolve() : reject(new Error(`备份打包失败(退出码 ${code}):${err.trim().slice(0, 200)}`)));
|
|
489
|
+
});
|
|
490
|
+
if (!existsSync(archive))
|
|
491
|
+
throw new Error('备份打包后未找到产物');
|
|
492
|
+
return archive;
|
|
493
|
+
}
|
|
494
|
+
/** 删除用户:先备份 user 目录到 backups/,再调 Admin 删除(202 异步清理),最后清保险库条目。
|
|
495
|
+
* 方案 §六/§七:二次确认在前端;备份前置在这里是硬约束(备份失败即中止删除) */
|
|
496
|
+
export async function deleteMemoryUser(config, uid) {
|
|
497
|
+
if (!isValidUserId(uid))
|
|
498
|
+
return { ok: false, detail: '用户名非法' };
|
|
499
|
+
const memory = config.memory;
|
|
500
|
+
if (!memory)
|
|
501
|
+
return { ok: false, detail: 'memory 段未配置' };
|
|
502
|
+
const rootKey = resolveRootKey(memory);
|
|
503
|
+
if (!rootKey)
|
|
504
|
+
return { ok: false, detail: 'root key 未配置' };
|
|
505
|
+
const account = memoryAccount(memory);
|
|
506
|
+
// 备份前置:打包失败绝不删除(磁盘明文数据是唯一正本)
|
|
507
|
+
let backupPath;
|
|
508
|
+
try {
|
|
509
|
+
const p = await backupUserDir(account, uid);
|
|
510
|
+
if (p)
|
|
511
|
+
backupPath = p;
|
|
512
|
+
}
|
|
513
|
+
catch (e) {
|
|
514
|
+
auditMemory('delete-abort', { user_id: uid, reason: e instanceof Error ? e.message : String(e) });
|
|
515
|
+
return { ok: false, detail: `已中止删除——备份失败:${e instanceof Error ? e.message : String(e)}` };
|
|
516
|
+
}
|
|
517
|
+
const r = await adminCall(memory, rootKey, 'DELETE', adminPath(memory, `/users/${encodeURIComponent(uid)}`));
|
|
518
|
+
if (!r.ok && r.status !== 202) {
|
|
519
|
+
auditMemory('delete-fail', { user_id: uid, status: r.status });
|
|
520
|
+
return { ok: false, detail: `删除失败:HTTP ${r.status}${r.message ? `(${r.message})` : ''}${backupPath ? `;数据备份在 ${backupPath}` : ''}` };
|
|
521
|
+
}
|
|
522
|
+
removeVaultEntry(uid);
|
|
523
|
+
auditMemory('delete', { user_id: uid, ...(backupPath ? { backupPath } : {}) });
|
|
524
|
+
return {
|
|
525
|
+
ok: true,
|
|
526
|
+
detail: `已删除 ${uid}(服务端异步清理数据)${backupPath ? `;数据备份:${backupPath}` : '(该用户无本地记忆数据)'}`,
|
|
527
|
+
...(backupPath ? { backupPath } : {}),
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
/** 保险库脱敏概览(审计/排障用:只回 uid 与是否在库,绝不回明文) */
|
|
531
|
+
export function vaultOverview() {
|
|
532
|
+
return Object.entries(loadVault()).map(([userId, sealed]) => ({ userId, sealed: !sealed.startsWith('plain:') }));
|
|
533
|
+
}
|
|
534
|
+
//# sourceMappingURL=memory-users-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-users-api.js","sourceRoot":"","sources":["../../src/web/memory-users-api.ts"],"names":[],"mappings":"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"}
|