@kafca/agentdock 0.1.7
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 +70 -0
- package/bin/agentdock.mjs +275 -0
- package/build/icon.png +0 -0
- package/dist/renderer/assets/index-BaNpzC6d.js +482 -0
- package/dist/renderer/assets/index-CLWJyO0E.css +11 -0
- package/dist/renderer/favicon.svg +19 -0
- package/dist/renderer/index.html +14 -0
- package/dist/renderer/logo-options.svg +153 -0
- package/dist-electron/electron/knowledge-skill-script.test.js +125 -0
- package/dist-electron/electron/lac-cli.test.js +221 -0
- package/dist-electron/electron/local-core-refactor.test.js +1075 -0
- package/dist-electron/electron/main.js +163 -0
- package/dist-electron/electron/plugin-kernel.test.js +534 -0
- package/dist-electron/electron/preload.js +2 -0
- package/dist-electron/package.json +3 -0
- package/dist-electron/packages/contracts/src/index.js +18 -0
- package/dist-electron/packages/contracts/src/local-core.js +2 -0
- package/dist-electron/packages/core-sdk/src/index.js +406 -0
- package/dist-electron/packages/knowledge-api/src/ai-vector-provider.js +388 -0
- package/dist-electron/packages/knowledge-api/src/index.js +146 -0
- package/dist-electron/packages/knowledge-api/src/sqlite-store.js +467 -0
- package/dist-electron/packages/knowledge-api/src/thread-knowledge-store.js +21 -0
- package/dist-electron/packages/knowledge-api/test/ai-vector-provider.test.js +412 -0
- package/dist-electron/packages/plugin-sdk/src/index.js +2 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +369 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +110 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +171 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +635 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +190 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +244 -0
- package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +52 -0
- package/dist-electron/services/local-ai-core/src/cli/lac.js +290 -0
- package/dist-electron/services/local-ai-core/src/gateway/local-core-lark-gateway.js +976 -0
- package/dist-electron/services/local-ai-core/src/gateway/local-core-weixin-gateway.js +1143 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +291 -0
- package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +67 -0
- package/dist-electron/services/local-ai-core/src/kernel/diagnostics.js +27 -0
- package/dist-electron/services/local-ai-core/src/kernel/event-bus.js +27 -0
- package/dist-electron/services/local-ai-core/src/kernel/lifecycle-manager.js +85 -0
- package/dist-electron/services/local-ai-core/src/kernel/plugin-registry.js +60 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/agent-localcore-acp-plugin.js +114 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +59 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +56 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +7 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +7 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/runtime-capabilities-plugin.js +62 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-cron-plugin.js +49 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-lark-plugin.js +38 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-weixin-plugin.js +38 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +230 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-router-types.js +2 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +389 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +315 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +282 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +465 -0
- package/dist-electron/services/local-ai-core/src/runtime/standalone.js +38 -0
- package/dist-electron/services/local-ai-core/src/scheduler/adapters.js +2 -0
- package/dist-electron/services/local-ai-core/src/scheduler/cron-command-detector.js +70 -0
- package/dist-electron/services/local-ai-core/src/scheduler/cron.js +53 -0
- package/dist-electron/services/local-ai-core/src/scheduler/execution-policy.js +2 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +66 -0
- package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +77 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +46 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js +64 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +133 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +66 -0
- package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +78 -0
- package/dist-electron/services/local-ai-core/src/thread/workspace-thread-id.js +17 -0
- package/dist-electron/services/local-ai-core/src/thread/workspace-thread-mappers.js +43 -0
- package/dist-electron/shared/desktop.js +195 -0
- package/dist-electron/src/api/client.js +73 -0
- package/dist-electron/src/api/sessions.js +21 -0
- package/dist-electron/src/lib/session-utils.js +51 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.js +246 -0
- package/dist-electron/src/pages/Threads/thread-chat-model.test.js +76 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.js +26 -0
- package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +102 -0
- package/dist-electron/src/pages/Threads/thread-chat-task-state.js +65 -0
- package/package.json +146 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = __importDefault(require("node:test"));
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_fs_2 = require("node:fs");
|
|
10
|
+
const node_os_1 = require("node:os");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const index_js_1 = require("../src/index.js");
|
|
13
|
+
const sqlite_store_js_1 = require("../src/sqlite-store.js");
|
|
14
|
+
function withTempDir() {
|
|
15
|
+
const dir = (0, node_fs_2.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kb-'));
|
|
16
|
+
return {
|
|
17
|
+
dir,
|
|
18
|
+
cleanup() {
|
|
19
|
+
(0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
(0, node_test_1.default)('migrates legacy knowledge-store.json into sqlite and keeps a backup', () => {
|
|
24
|
+
const temp = withTempDir();
|
|
25
|
+
try {
|
|
26
|
+
const runtimeDir = (0, node_path_1.join)(temp.dir, 'runtime');
|
|
27
|
+
(0, node_fs_1.mkdirSync)(runtimeDir, { recursive: true });
|
|
28
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(runtimeDir, 'knowledge-store.json'), JSON.stringify({
|
|
29
|
+
folders: [
|
|
30
|
+
{
|
|
31
|
+
id: 'folder-1',
|
|
32
|
+
name: '运营',
|
|
33
|
+
parentId: null,
|
|
34
|
+
path: '运营',
|
|
35
|
+
sortOrder: 0,
|
|
36
|
+
createdAt: '2026-01-01T00:00:00.000Z',
|
|
37
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
knowledgeBases: [
|
|
41
|
+
{
|
|
42
|
+
id: 'kb-1',
|
|
43
|
+
name: '运营知识库',
|
|
44
|
+
description: 'desc',
|
|
45
|
+
folderId: 'folder-1',
|
|
46
|
+
creatorName: '系统管理员',
|
|
47
|
+
icon: 'book',
|
|
48
|
+
fileCount: 0,
|
|
49
|
+
wordCount: 0,
|
|
50
|
+
createdAt: '2026-01-01T00:00:00.000Z',
|
|
51
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
}), 'utf8');
|
|
55
|
+
const store = new sqlite_store_js_1.KnowledgeSqliteStore({ userDataPath: temp.dir });
|
|
56
|
+
try {
|
|
57
|
+
strict_1.default.equal(store.listFolders().length, 1);
|
|
58
|
+
strict_1.default.equal(store.listKnowledgeBases().length, 1);
|
|
59
|
+
strict_1.default.equal(store.getKnowledgeBase('kb-1')?.name, '运营知识库');
|
|
60
|
+
strict_1.default.equal((0, node_fs_1.existsSync)((0, node_path_1.join)(runtimeDir, 'knowledge-store.json')), false);
|
|
61
|
+
strict_1.default.equal((0, node_fs_1.existsSync)((0, node_path_1.join)(runtimeDir, 'knowledge-store.json.bak')), true);
|
|
62
|
+
strict_1.default.equal((0, node_fs_1.existsSync)((0, node_path_1.join)(runtimeDir, 'knowledge.db')), true);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
store.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
temp.cleanup();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
(0, node_test_1.default)('uses uploaded file cache when remote list is empty', async () => {
|
|
73
|
+
const temp = withTempDir();
|
|
74
|
+
const config = {
|
|
75
|
+
...(0, index_js_1.defaultKnowledgeConfig)(),
|
|
76
|
+
baseUrl: 'http://vector.example.com',
|
|
77
|
+
};
|
|
78
|
+
let knowledgeBaseId = '';
|
|
79
|
+
const provider = new index_js_1.AiVectorKnowledgeProvider({
|
|
80
|
+
userDataPath: temp.dir,
|
|
81
|
+
getConfig: () => config,
|
|
82
|
+
setConfig: (input) => ({ ...config, ...input }),
|
|
83
|
+
});
|
|
84
|
+
const originalFetch = globalThis.fetch;
|
|
85
|
+
globalThis.fetch = (async (input) => {
|
|
86
|
+
const url = String(input);
|
|
87
|
+
if (url.endsWith('/qdrant/file')) {
|
|
88
|
+
return new Response(JSON.stringify({
|
|
89
|
+
resultCode: 0,
|
|
90
|
+
resultMsg: 'success',
|
|
91
|
+
data: [
|
|
92
|
+
{
|
|
93
|
+
knowledgebase_id: knowledgeBaseId,
|
|
94
|
+
file_id: 'file-1',
|
|
95
|
+
file_name: 'doc.md',
|
|
96
|
+
file_type: 'md',
|
|
97
|
+
file_size: 12,
|
|
98
|
+
folder: null,
|
|
99
|
+
create_time: '2026-01-02T00:00:00.000Z',
|
|
100
|
+
word_count: 5,
|
|
101
|
+
metadata: { source: 'upload' },
|
|
102
|
+
abstract: 'summary',
|
|
103
|
+
full_content: 'hello world',
|
|
104
|
+
success: true,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Unexpected fetch URL: ${url}`);
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
const base = await provider.createKnowledgeBase({
|
|
113
|
+
name: '运营知识库',
|
|
114
|
+
description: 'desc',
|
|
115
|
+
});
|
|
116
|
+
knowledgeBaseId = base.id;
|
|
117
|
+
const upload = await provider.uploadKnowledgeBaseFiles(knowledgeBaseId, {
|
|
118
|
+
contentType: 'multipart/form-data; boundary=test',
|
|
119
|
+
body: new Uint8Array([1, 2, 3]),
|
|
120
|
+
});
|
|
121
|
+
const files = await provider.listKnowledgeBaseFiles(knowledgeBaseId);
|
|
122
|
+
const nextBase = await provider.getKnowledgeBase(knowledgeBaseId);
|
|
123
|
+
strict_1.default.equal(upload.length, 1);
|
|
124
|
+
strict_1.default.equal(files.length, 1);
|
|
125
|
+
strict_1.default.equal(files[0]?.fileId, 'file-1');
|
|
126
|
+
strict_1.default.equal(files[0]?.wordCount, 5);
|
|
127
|
+
strict_1.default.equal(nextBase.fileCount, 1);
|
|
128
|
+
strict_1.default.equal(nextBase.wordCount, 5);
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
globalThis.fetch = originalFetch;
|
|
132
|
+
temp.cleanup();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
(0, node_test_1.default)('reads file lists and stats from sqlite without calling remote list', async () => {
|
|
136
|
+
const temp = withTempDir();
|
|
137
|
+
const config = {
|
|
138
|
+
...(0, index_js_1.defaultKnowledgeConfig)(),
|
|
139
|
+
baseUrl: 'http://vector.example.com',
|
|
140
|
+
};
|
|
141
|
+
let knowledgeBaseId = '';
|
|
142
|
+
const provider = new index_js_1.AiVectorKnowledgeProvider({
|
|
143
|
+
userDataPath: temp.dir,
|
|
144
|
+
getConfig: () => config,
|
|
145
|
+
setConfig: (input) => ({ ...config, ...input }),
|
|
146
|
+
});
|
|
147
|
+
const originalFetch = globalThis.fetch;
|
|
148
|
+
globalThis.fetch = (async (input) => {
|
|
149
|
+
const url = String(input);
|
|
150
|
+
if (url.endsWith('/qdrant/file')) {
|
|
151
|
+
return new Response(JSON.stringify({
|
|
152
|
+
resultCode: 0,
|
|
153
|
+
resultMsg: 'success',
|
|
154
|
+
data: [
|
|
155
|
+
{
|
|
156
|
+
knowledgebase_id: knowledgeBaseId,
|
|
157
|
+
file_id: 'file-1',
|
|
158
|
+
file_name: 'doc.md',
|
|
159
|
+
file_type: 'md',
|
|
160
|
+
file_size: 12,
|
|
161
|
+
folder: null,
|
|
162
|
+
create_time: '2026-01-02T00:00:00.000Z',
|
|
163
|
+
word_count: 5,
|
|
164
|
+
metadata: null,
|
|
165
|
+
abstract: null,
|
|
166
|
+
full_content: 'hello world',
|
|
167
|
+
success: true,
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
throw new Error(`Unexpected fetch URL: ${url}`);
|
|
173
|
+
});
|
|
174
|
+
try {
|
|
175
|
+
const base = await provider.createKnowledgeBase({
|
|
176
|
+
name: '运营知识库',
|
|
177
|
+
description: 'desc',
|
|
178
|
+
});
|
|
179
|
+
knowledgeBaseId = base.id;
|
|
180
|
+
await provider.uploadKnowledgeBaseFiles(knowledgeBaseId, {
|
|
181
|
+
contentType: 'multipart/form-data; boundary=test',
|
|
182
|
+
body: new Uint8Array([1, 2, 3]),
|
|
183
|
+
});
|
|
184
|
+
globalThis.fetch = (async (input) => {
|
|
185
|
+
throw new Error(`No remote read expected: ${String(input)}`);
|
|
186
|
+
});
|
|
187
|
+
const files = await provider.listKnowledgeBaseFiles(knowledgeBaseId);
|
|
188
|
+
const nextBase = await provider.getKnowledgeBase(knowledgeBaseId);
|
|
189
|
+
const bases = await provider.listKnowledgeBases();
|
|
190
|
+
strict_1.default.equal(files.length, 1);
|
|
191
|
+
strict_1.default.equal(files[0]?.fileId, 'file-1');
|
|
192
|
+
strict_1.default.equal(nextBase.fileCount, 1);
|
|
193
|
+
strict_1.default.equal(nextBase.wordCount, 5);
|
|
194
|
+
strict_1.default.equal(bases[0]?.fileCount, 1);
|
|
195
|
+
strict_1.default.equal(bases[0]?.wordCount, 5);
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
globalThis.fetch = originalFetch;
|
|
199
|
+
temp.cleanup();
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
(0, node_test_1.default)('supports raw ai_vector search responses without envelope', async () => {
|
|
203
|
+
const temp = withTempDir();
|
|
204
|
+
const config = {
|
|
205
|
+
...(0, index_js_1.defaultKnowledgeConfig)(),
|
|
206
|
+
baseUrl: 'http://vector.example.com',
|
|
207
|
+
};
|
|
208
|
+
const provider = new index_js_1.AiVectorKnowledgeProvider({
|
|
209
|
+
userDataPath: temp.dir,
|
|
210
|
+
getConfig: () => config,
|
|
211
|
+
setConfig: (input) => ({ ...config, ...input }),
|
|
212
|
+
});
|
|
213
|
+
const originalFetch = globalThis.fetch;
|
|
214
|
+
globalThis.fetch = (async (input) => {
|
|
215
|
+
const url = String(input);
|
|
216
|
+
if (url.endsWith('/qdrant/query')) {
|
|
217
|
+
return new Response(JSON.stringify({
|
|
218
|
+
intent: 'CHAT',
|
|
219
|
+
documents: [
|
|
220
|
+
{
|
|
221
|
+
id: 'result-1',
|
|
222
|
+
score: 0.9,
|
|
223
|
+
metadata: {
|
|
224
|
+
file_id: 'file-1',
|
|
225
|
+
file_name: 'doc.md',
|
|
226
|
+
document: 'hello knowledge',
|
|
227
|
+
chunk_offset: 2,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
throw new Error(`Unexpected fetch URL: ${url}`);
|
|
234
|
+
});
|
|
235
|
+
try {
|
|
236
|
+
const base = await provider.createKnowledgeBase({
|
|
237
|
+
name: '运营知识库',
|
|
238
|
+
description: 'desc',
|
|
239
|
+
});
|
|
240
|
+
const results = await provider.searchKnowledgeBase(base.id, { query: 'hello', limit: 3 });
|
|
241
|
+
strict_1.default.equal(results.length, 1);
|
|
242
|
+
strict_1.default.equal(results[0]?.fileId, 'file-1');
|
|
243
|
+
strict_1.default.equal(results[0]?.chunkOffset, 2);
|
|
244
|
+
strict_1.default.equal(results[0]?.title, '运营知识库 · doc.md');
|
|
245
|
+
strict_1.default.match(results[0]?.snippet || '', /hello knowledge/);
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
globalThis.fetch = originalFetch;
|
|
249
|
+
temp.cleanup();
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
(0, node_test_1.default)('stores selected knowledge-base bindings per thread in sqlite', async () => {
|
|
253
|
+
const temp = withTempDir();
|
|
254
|
+
const provider = new index_js_1.AiVectorKnowledgeProvider({
|
|
255
|
+
userDataPath: temp.dir,
|
|
256
|
+
getConfig: () => (0, index_js_1.defaultKnowledgeConfig)(),
|
|
257
|
+
setConfig: (input) => ({ ...(0, index_js_1.defaultKnowledgeConfig)(), ...input }),
|
|
258
|
+
});
|
|
259
|
+
const attachments = new index_js_1.SqliteThreadKnowledgeAttachmentStore({
|
|
260
|
+
userDataPath: temp.dir,
|
|
261
|
+
});
|
|
262
|
+
try {
|
|
263
|
+
const firstBase = await provider.createKnowledgeBase({ name: '知识库 A' });
|
|
264
|
+
const secondBase = await provider.createKnowledgeBase({ name: '知识库 B' });
|
|
265
|
+
const storedIds = await attachments.updateThreadKnowledgeBaseIds('thread-1', [
|
|
266
|
+
firstBase.id,
|
|
267
|
+
secondBase.id,
|
|
268
|
+
firstBase.id,
|
|
269
|
+
]);
|
|
270
|
+
strict_1.default.deepEqual(storedIds, [firstBase.id, secondBase.id]);
|
|
271
|
+
strict_1.default.deepEqual(await attachments.listThreadKnowledgeBaseIds('thread-1'), [firstBase.id, secondBase.id]);
|
|
272
|
+
await attachments.deleteThreadKnowledgeBaseLinks('thread-1');
|
|
273
|
+
strict_1.default.deepEqual(await attachments.listThreadKnowledgeBaseIds('thread-1'), []);
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
temp.cleanup();
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
(0, node_test_1.default)('ai-vector knowledge plugin creates provider runtime and registers enabled capability', async () => {
|
|
280
|
+
const temp = withTempDir();
|
|
281
|
+
try {
|
|
282
|
+
const plugin = (0, index_js_1.createAiVectorKnowledgePlugin)({
|
|
283
|
+
userDataPath: temp.dir,
|
|
284
|
+
getConfig: () => (0, index_js_1.defaultKnowledgeConfig)(),
|
|
285
|
+
setConfig: (input) => ({ ...(0, index_js_1.defaultKnowledgeConfig)(), ...input }),
|
|
286
|
+
});
|
|
287
|
+
strict_1.default.equal(plugin.manifest.id, 'knowledge.ai-vector');
|
|
288
|
+
strict_1.default.equal(plugin.capabilities?.knowledge?.[0]?.enabled, true);
|
|
289
|
+
const runtime = await plugin.createRuntime?.({
|
|
290
|
+
bus: { emit() { }, on() { return () => { }; } },
|
|
291
|
+
capabilities: {
|
|
292
|
+
registerAgent() { },
|
|
293
|
+
registerChannel() { },
|
|
294
|
+
registerKnowledge() { },
|
|
295
|
+
registerScheduler() { },
|
|
296
|
+
registerUi() { },
|
|
297
|
+
registerContributions() { },
|
|
298
|
+
listAgents() { return []; },
|
|
299
|
+
listChannels() { return []; },
|
|
300
|
+
listKnowledge() { return []; },
|
|
301
|
+
listSchedulers() { return []; },
|
|
302
|
+
listUi() { return []; },
|
|
303
|
+
snapshot() { return { agents: [], channels: [], knowledge: [], schedulers: [], ui: [] }; },
|
|
304
|
+
},
|
|
305
|
+
logger: { log() { } },
|
|
306
|
+
});
|
|
307
|
+
strict_1.default.ok(runtime);
|
|
308
|
+
strict_1.default.deepEqual(await runtime?.attachments.listThreadKnowledgeBaseIds('thread-1'), []);
|
|
309
|
+
strict_1.default.deepEqual(await runtime?.provider.listKnowledgeBases(), []);
|
|
310
|
+
}
|
|
311
|
+
finally {
|
|
312
|
+
temp.cleanup();
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
(0, node_test_1.default)('noop knowledge plugin exposes a disabled capability and inert runtime', async () => {
|
|
316
|
+
const plugin = (0, index_js_1.createNoopKnowledgePlugin)();
|
|
317
|
+
const runtime = await plugin.createRuntime?.({
|
|
318
|
+
bus: { emit() { }, on() { return () => { }; } },
|
|
319
|
+
capabilities: {
|
|
320
|
+
registerAgent() { },
|
|
321
|
+
registerChannel() { },
|
|
322
|
+
registerKnowledge() { },
|
|
323
|
+
registerScheduler() { },
|
|
324
|
+
registerUi() { },
|
|
325
|
+
registerContributions() { },
|
|
326
|
+
listAgents() { return []; },
|
|
327
|
+
listChannels() { return []; },
|
|
328
|
+
listKnowledge() { return []; },
|
|
329
|
+
listSchedulers() { return []; },
|
|
330
|
+
listUi() { return []; },
|
|
331
|
+
snapshot() { return { agents: [], channels: [], knowledge: [], schedulers: [], ui: [] }; },
|
|
332
|
+
},
|
|
333
|
+
logger: { log() { } },
|
|
334
|
+
});
|
|
335
|
+
strict_1.default.equal(plugin.capabilities?.knowledge?.[0]?.enabled, false);
|
|
336
|
+
strict_1.default.deepEqual(await runtime?.provider.listKnowledgeBases(), []);
|
|
337
|
+
strict_1.default.deepEqual(await runtime?.attachments.listThreadKnowledgeBaseIds('thread-1'), []);
|
|
338
|
+
});
|
|
339
|
+
(0, node_test_1.default)('deletes remote vector data for cached-miss knowledge bases before removing local base', async () => {
|
|
340
|
+
const temp = withTempDir();
|
|
341
|
+
const config = {
|
|
342
|
+
...(0, index_js_1.defaultKnowledgeConfig)(),
|
|
343
|
+
baseUrl: 'http://vector.example.com',
|
|
344
|
+
};
|
|
345
|
+
let knowledgeBaseId = '';
|
|
346
|
+
let batchDeletePayload = null;
|
|
347
|
+
const provider = new index_js_1.AiVectorKnowledgeProvider({
|
|
348
|
+
userDataPath: temp.dir,
|
|
349
|
+
getConfig: () => config,
|
|
350
|
+
setConfig: (input) => ({ ...config, ...input }),
|
|
351
|
+
});
|
|
352
|
+
const originalFetch = globalThis.fetch;
|
|
353
|
+
globalThis.fetch = (async (input, init) => {
|
|
354
|
+
const url = String(input);
|
|
355
|
+
if (url.endsWith('/qdrant/query')) {
|
|
356
|
+
return new Response(JSON.stringify({
|
|
357
|
+
intent: 'CHAT',
|
|
358
|
+
documents: [
|
|
359
|
+
{
|
|
360
|
+
id: 'result-1',
|
|
361
|
+
metadata: {
|
|
362
|
+
file_id: 'file-a',
|
|
363
|
+
file_name: 'doc-a.md',
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
id: 'result-2',
|
|
368
|
+
metadata: {
|
|
369
|
+
file_id: 'file-b',
|
|
370
|
+
file_name: 'doc-b.md',
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
id: 'result-3',
|
|
375
|
+
metadata: {
|
|
376
|
+
file_id: 'file-a',
|
|
377
|
+
file_name: 'doc-a.md',
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
}));
|
|
382
|
+
}
|
|
383
|
+
if (url.endsWith('/qdrant/batchDelete')) {
|
|
384
|
+
batchDeletePayload = init?.body ? JSON.parse(String(init.body)) : null;
|
|
385
|
+
return new Response(JSON.stringify({
|
|
386
|
+
resultCode: 0,
|
|
387
|
+
resultMsg: 'success',
|
|
388
|
+
data: { success: true },
|
|
389
|
+
}));
|
|
390
|
+
}
|
|
391
|
+
throw new Error(`Unexpected fetch URL: ${url}`);
|
|
392
|
+
});
|
|
393
|
+
try {
|
|
394
|
+
const base = await provider.createKnowledgeBase({
|
|
395
|
+
name: '运营知识库',
|
|
396
|
+
description: 'desc',
|
|
397
|
+
});
|
|
398
|
+
knowledgeBaseId = base.id;
|
|
399
|
+
const result = await provider.deleteKnowledgeBase(knowledgeBaseId);
|
|
400
|
+
strict_1.default.equal(result.deleted, true);
|
|
401
|
+
strict_1.default.deepEqual(batchDeletePayload, {
|
|
402
|
+
collection: 'personal_knowledge',
|
|
403
|
+
knowledgebase_id: knowledgeBaseId,
|
|
404
|
+
file_ids: ['file-a', 'file-b'],
|
|
405
|
+
});
|
|
406
|
+
await strict_1.default.rejects(() => provider.getKnowledgeBase(knowledgeBaseId), /Knowledge base does not exist/);
|
|
407
|
+
}
|
|
408
|
+
finally {
|
|
409
|
+
globalThis.fetch = originalFetch;
|
|
410
|
+
temp.cleanup();
|
|
411
|
+
}
|
|
412
|
+
});
|