@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.
Files changed (79) hide show
  1. package/README.md +70 -0
  2. package/bin/agentdock.mjs +275 -0
  3. package/build/icon.png +0 -0
  4. package/dist/renderer/assets/index-BaNpzC6d.js +482 -0
  5. package/dist/renderer/assets/index-CLWJyO0E.css +11 -0
  6. package/dist/renderer/favicon.svg +19 -0
  7. package/dist/renderer/index.html +14 -0
  8. package/dist/renderer/logo-options.svg +153 -0
  9. package/dist-electron/electron/knowledge-skill-script.test.js +125 -0
  10. package/dist-electron/electron/lac-cli.test.js +221 -0
  11. package/dist-electron/electron/local-core-refactor.test.js +1075 -0
  12. package/dist-electron/electron/main.js +163 -0
  13. package/dist-electron/electron/plugin-kernel.test.js +534 -0
  14. package/dist-electron/electron/preload.js +2 -0
  15. package/dist-electron/package.json +3 -0
  16. package/dist-electron/packages/contracts/src/index.js +18 -0
  17. package/dist-electron/packages/contracts/src/local-core.js +2 -0
  18. package/dist-electron/packages/core-sdk/src/index.js +406 -0
  19. package/dist-electron/packages/knowledge-api/src/ai-vector-provider.js +388 -0
  20. package/dist-electron/packages/knowledge-api/src/index.js +146 -0
  21. package/dist-electron/packages/knowledge-api/src/sqlite-store.js +467 -0
  22. package/dist-electron/packages/knowledge-api/src/thread-knowledge-store.js +21 -0
  23. package/dist-electron/packages/knowledge-api/test/ai-vector-provider.test.js +412 -0
  24. package/dist-electron/packages/plugin-sdk/src/index.js +2 -0
  25. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +369 -0
  26. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-response-processor.js +110 -0
  27. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +171 -0
  28. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +635 -0
  29. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +190 -0
  30. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +244 -0
  31. package/dist-electron/services/local-ai-core/src/acp/workspace-acp-permissions.js +52 -0
  32. package/dist-electron/services/local-ai-core/src/cli/lac.js +290 -0
  33. package/dist-electron/services/local-ai-core/src/gateway/local-core-lark-gateway.js +976 -0
  34. package/dist-electron/services/local-ai-core/src/gateway/local-core-weixin-gateway.js +1143 -0
  35. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +291 -0
  36. package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +67 -0
  37. package/dist-electron/services/local-ai-core/src/kernel/diagnostics.js +27 -0
  38. package/dist-electron/services/local-ai-core/src/kernel/event-bus.js +27 -0
  39. package/dist-electron/services/local-ai-core/src/kernel/lifecycle-manager.js +85 -0
  40. package/dist-electron/services/local-ai-core/src/kernel/plugin-registry.js +60 -0
  41. package/dist-electron/services/local-ai-core/src/plugins/builtin/agent-localcore-acp-plugin.js +114 -0
  42. package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-lark-plugin.js +59 -0
  43. package/dist-electron/services/local-ai-core/src/plugins/builtin/channel-weixin-plugin.js +56 -0
  44. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-ai-vector-plugin.js +7 -0
  45. package/dist-electron/services/local-ai-core/src/plugins/builtin/knowledge-noop-plugin.js +7 -0
  46. package/dist-electron/services/local-ai-core/src/plugins/builtin/runtime-capabilities-plugin.js +62 -0
  47. package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-cron-plugin.js +49 -0
  48. package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-lark-plugin.js +38 -0
  49. package/dist-electron/services/local-ai-core/src/plugins/builtin/scheduler-weixin-plugin.js +38 -0
  50. package/dist-electron/services/local-ai-core/src/router/workspace-route-config.js +230 -0
  51. package/dist-electron/services/local-ai-core/src/router/workspace-router-types.js +2 -0
  52. package/dist-electron/services/local-ai-core/src/router/workspace-router.js +389 -0
  53. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +315 -0
  54. package/dist-electron/services/local-ai-core/src/runtime/local-core-runtime-state.js +282 -0
  55. package/dist-electron/services/local-ai-core/src/runtime/server.js +465 -0
  56. package/dist-electron/services/local-ai-core/src/runtime/standalone.js +38 -0
  57. package/dist-electron/services/local-ai-core/src/scheduler/adapters.js +2 -0
  58. package/dist-electron/services/local-ai-core/src/scheduler/cron-command-detector.js +70 -0
  59. package/dist-electron/services/local-ai-core/src/scheduler/cron.js +53 -0
  60. package/dist-electron/services/local-ai-core/src/scheduler/execution-policy.js +2 -0
  61. package/dist-electron/services/local-ai-core/src/scheduler/lark-execution-policies.js +66 -0
  62. package/dist-electron/services/local-ai-core/src/scheduler/lark-schedule-adapter.js +77 -0
  63. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +46 -0
  64. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-run-lifecycle.js +64 -0
  65. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +133 -0
  66. package/dist-electron/services/local-ai-core/src/scheduler/weixin-execution-policies.js +66 -0
  67. package/dist-electron/services/local-ai-core/src/scheduler/weixin-schedule-adapter.js +78 -0
  68. package/dist-electron/services/local-ai-core/src/thread/workspace-thread-id.js +17 -0
  69. package/dist-electron/services/local-ai-core/src/thread/workspace-thread-mappers.js +43 -0
  70. package/dist-electron/shared/desktop.js +195 -0
  71. package/dist-electron/src/api/client.js +73 -0
  72. package/dist-electron/src/api/sessions.js +21 -0
  73. package/dist-electron/src/lib/session-utils.js +51 -0
  74. package/dist-electron/src/pages/Threads/thread-chat-model.js +246 -0
  75. package/dist-electron/src/pages/Threads/thread-chat-model.test.js +76 -0
  76. package/dist-electron/src/pages/Threads/thread-chat-permission.js +26 -0
  77. package/dist-electron/src/pages/Threads/thread-chat-permission.test.js +102 -0
  78. package/dist-electron/src/pages/Threads/thread-chat-task-state.js +65 -0
  79. package/package.json +146 -0
@@ -0,0 +1,534 @@
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_os_1 = require("node:os");
10
+ const node_path_1 = require("node:path");
11
+ const bootstrap_js_1 = require("../services/local-ai-core/src/kernel/bootstrap.js");
12
+ const bootstrap_js_2 = require("../services/local-ai-core/src/kernel/bootstrap.js");
13
+ const capability_registry_js_1 = require("../services/local-ai-core/src/kernel/capability-registry.js");
14
+ const event_bus_js_1 = require("../services/local-ai-core/src/kernel/event-bus.js");
15
+ const lifecycle_manager_js_1 = require("../services/local-ai-core/src/kernel/lifecycle-manager.js");
16
+ const plugin_registry_js_1 = require("../services/local-ai-core/src/kernel/plugin-registry.js");
17
+ const local_core_controller_js_1 = require("../services/local-ai-core/src/runtime/local-core-controller.js");
18
+ function plugin(id, dependsOn = []) {
19
+ return {
20
+ manifest: {
21
+ id,
22
+ kind: 'composite',
23
+ version: '0.1.0',
24
+ dependsOn,
25
+ provides: [],
26
+ },
27
+ };
28
+ }
29
+ (0, node_test_1.default)('bootstrapLocalCoreKernel exposes the static built-in capability snapshot', () => {
30
+ const kernel = (0, bootstrap_js_1.bootstrapLocalCoreKernel)();
31
+ strict_1.default.deepEqual(kernel.getCapabilitySnapshot(), {
32
+ adapters: {
33
+ channels: ['localcore-acp'],
34
+ agents: ['codex', 'cursor', 'gemini', 'qoder', 'iflow', 'localcore-acp'],
35
+ knowledge: false,
36
+ knowledgeProviders: [],
37
+ },
38
+ scheduler: {
39
+ enabled: true,
40
+ triggerTypes: ['cron', 'once'],
41
+ deliveryTargets: [],
42
+ platforms: [],
43
+ },
44
+ snapshot: {
45
+ agents: [
46
+ { id: 'agent.codex', agentType: 'codex', displayName: 'codex' },
47
+ { id: 'agent.cursor', agentType: 'cursor', displayName: 'cursor' },
48
+ { id: 'agent.gemini', agentType: 'gemini', displayName: 'gemini' },
49
+ { id: 'agent.qoder', agentType: 'qoder', displayName: 'qoder' },
50
+ { id: 'agent.iflow', agentType: 'iflow', displayName: 'iflow' },
51
+ { id: 'agent.localcore-acp', agentType: 'localcore-acp', displayName: 'LocalCore ACP' },
52
+ ],
53
+ channels: [
54
+ { id: 'channel.localcore-acp', platform: 'localcore-acp', displayName: 'LocalCore ACP' },
55
+ ],
56
+ knowledge: [],
57
+ schedulers: [
58
+ {
59
+ id: 'scheduler.trigger.cron',
60
+ triggerTypes: ['cron', 'once'],
61
+ deliveryTargets: [],
62
+ enabled: true,
63
+ displayName: 'Cron Trigger',
64
+ },
65
+ ],
66
+ ui: [],
67
+ },
68
+ });
69
+ });
70
+ (0, node_test_1.default)('plugin registry preserves registration order for unrelated plugins', () => {
71
+ const registry = new plugin_registry_js_1.LocalCorePluginRegistry();
72
+ registry.register(plugin('plugin.first'));
73
+ registry.register(plugin('plugin.second'));
74
+ registry.register(plugin('plugin.third'));
75
+ strict_1.default.deepEqual(registry.list().map((entry) => entry.manifest.id), [
76
+ 'plugin.first',
77
+ 'plugin.second',
78
+ 'plugin.third',
79
+ ]);
80
+ });
81
+ (0, node_test_1.default)('plugin registry resolves dependencies before dependents', () => {
82
+ const registry = new plugin_registry_js_1.LocalCorePluginRegistry();
83
+ registry.register(plugin('plugin.scheduler', ['plugin.channel']));
84
+ registry.register(plugin('plugin.channel'));
85
+ registry.register(plugin('plugin.unrelated'));
86
+ strict_1.default.deepEqual(registry.list().map((entry) => entry.manifest.id), [
87
+ 'plugin.channel',
88
+ 'plugin.scheduler',
89
+ 'plugin.unrelated',
90
+ ]);
91
+ });
92
+ (0, node_test_1.default)('plugin registry rejects duplicate plugin ids', () => {
93
+ const registry = new plugin_registry_js_1.LocalCorePluginRegistry();
94
+ registry.register(plugin('plugin.duplicate'));
95
+ strict_1.default.throws(() => registry.register(plugin('plugin.duplicate')), /Plugin already registered: plugin\.duplicate/);
96
+ });
97
+ (0, node_test_1.default)('capability registry snapshots contributions by capability type', () => {
98
+ const capabilities = new capability_registry_js_1.LocalCoreCapabilityRegistry();
99
+ capabilities.registerContributions({
100
+ agents: [{ id: 'agent.test', agentType: 'test-agent' }],
101
+ channels: [{ id: 'channel.test', platform: 'test-platform' }],
102
+ knowledge: [{ id: 'knowledge.test', sourceType: 'test-source', enabled: true }],
103
+ schedulers: [{ id: 'scheduler.test', triggerTypes: ['cron'], deliveryTargets: ['test-platform'] }],
104
+ ui: [{ id: 'ui.test' }],
105
+ });
106
+ strict_1.default.deepEqual(capabilities.snapshot(), {
107
+ agents: [{ id: 'agent.test', agentType: 'test-agent' }],
108
+ channels: [{ id: 'channel.test', platform: 'test-platform' }],
109
+ knowledge: [{ id: 'knowledge.test', sourceType: 'test-source', enabled: true }],
110
+ schedulers: [{ id: 'scheduler.test', triggerTypes: ['cron'], deliveryTargets: ['test-platform'] }],
111
+ ui: [{ id: 'ui.test' }],
112
+ });
113
+ });
114
+ (0, node_test_1.default)('kernel lifecycle initializes plugins and diagnostics report health', async () => {
115
+ const kernel = (0, bootstrap_js_1.bootstrapLocalCoreKernel)();
116
+ await kernel.lifecycle.initAll();
117
+ const diagnostics = await kernel.diagnostics.snapshot();
118
+ strict_1.default.equal(diagnostics.pluginCount, 7);
119
+ strict_1.default.equal(diagnostics.enabledPluginCount, 7);
120
+ strict_1.default.deepEqual(diagnostics.plugins.map((plugin) => plugin.pluginId).sort(), [
121
+ 'builtin.agent-codex',
122
+ 'builtin.agent-cursor',
123
+ 'builtin.agent-gemini',
124
+ 'builtin.agent-iflow',
125
+ 'builtin.agent-localcore-acp',
126
+ 'builtin.agent-qoder',
127
+ 'builtin.scheduler-cron',
128
+ ]);
129
+ strict_1.default.deepEqual(diagnostics.plugins.map((plugin) => ({
130
+ pluginId: plugin.pluginId,
131
+ enabled: plugin.enabled,
132
+ health: plugin.health,
133
+ })), [
134
+ 'builtin.agent-codex',
135
+ 'builtin.agent-cursor',
136
+ 'builtin.agent-gemini',
137
+ 'builtin.agent-qoder',
138
+ 'builtin.agent-iflow',
139
+ 'builtin.agent-localcore-acp',
140
+ 'builtin.scheduler-cron',
141
+ ].map((pluginId) => ({
142
+ pluginId,
143
+ enabled: true,
144
+ health: { status: 'healthy' },
145
+ })));
146
+ });
147
+ (0, node_test_1.default)('runtime bootstrap registers the active knowledge provider in capability snapshot', async () => {
148
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kernel-'));
149
+ try {
150
+ const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
151
+ userDataPath,
152
+ });
153
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().adapters.agents, [
154
+ 'codex',
155
+ 'cursor',
156
+ 'gemini',
157
+ 'qoder',
158
+ 'iflow',
159
+ 'localcore-acp',
160
+ 'opencode',
161
+ 'claudecode',
162
+ ]);
163
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().adapters.channels, ['localcore-acp', 'lark', 'weixin']);
164
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().adapters.knowledgeProviders, ['ai-vector']);
165
+ strict_1.default.equal(runtime.kernel.getCapabilitySnapshot().adapters.knowledge, true);
166
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().scheduler, {
167
+ enabled: true,
168
+ triggerTypes: ['cron', 'once'],
169
+ deliveryTargets: ['lark', 'weixin'],
170
+ platforms: ['lark', 'weixin'],
171
+ });
172
+ await runtime.start();
173
+ await runtime.stop();
174
+ }
175
+ finally {
176
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
177
+ }
178
+ });
179
+ (0, node_test_1.default)('runtime bootstrap supports a disabled knowledge plugin path', () => {
180
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kernel-'));
181
+ try {
182
+ const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
183
+ userDataPath,
184
+ enableKnowledge: false,
185
+ });
186
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().adapters.agents, [
187
+ 'codex',
188
+ 'cursor',
189
+ 'gemini',
190
+ 'qoder',
191
+ 'iflow',
192
+ 'localcore-acp',
193
+ 'opencode',
194
+ 'claudecode',
195
+ ]);
196
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().adapters.channels, ['localcore-acp', 'lark', 'weixin']);
197
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().adapters.knowledgeProviders, []);
198
+ strict_1.default.equal(runtime.kernel.getCapabilitySnapshot().adapters.knowledge, false);
199
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().scheduler, {
200
+ enabled: true,
201
+ triggerTypes: ['cron', 'once'],
202
+ deliveryTargets: ['lark', 'weixin'],
203
+ platforms: ['lark', 'weixin'],
204
+ });
205
+ }
206
+ finally {
207
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
208
+ }
209
+ });
210
+ (0, node_test_1.default)('runtime bootstrap knowledge capabilities come from the selected provider plugin', () => {
211
+ const enabledUserDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kernel-'));
212
+ const disabledUserDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kernel-'));
213
+ try {
214
+ const enabledRuntime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
215
+ userDataPath: enabledUserDataPath,
216
+ });
217
+ const disabledRuntime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
218
+ userDataPath: disabledUserDataPath,
219
+ enableKnowledge: false,
220
+ });
221
+ strict_1.default.deepEqual(enabledRuntime.kernel.getCapabilitySnapshot().snapshot.knowledge.map((capability) => capability.sourceType), ['ai-vector']);
222
+ strict_1.default.deepEqual(disabledRuntime.kernel.getCapabilitySnapshot().snapshot.knowledge, [
223
+ {
224
+ id: 'knowledge.noop',
225
+ sourceType: 'noop',
226
+ enabled: false,
227
+ displayName: 'Disabled Knowledge',
228
+ },
229
+ ]);
230
+ strict_1.default.equal(disabledRuntime.kernel.getCapabilitySnapshot().adapters.knowledge, false);
231
+ }
232
+ finally {
233
+ (0, node_fs_1.rmSync)(enabledUserDataPath, { recursive: true, force: true });
234
+ (0, node_fs_1.rmSync)(disabledUserDataPath, { recursive: true, force: true });
235
+ }
236
+ });
237
+ (0, node_test_1.default)('runtime bootstrap keeps disabled plugins diagnosable without contributing capabilities', async () => {
238
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kernel-'));
239
+ try {
240
+ const runtimeDir = (0, node_path_1.join)(userDataPath, 'runtime');
241
+ (0, node_fs_1.mkdirSync)(runtimeDir, { recursive: true });
242
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(runtimeDir, 'local-core-settings.json'), JSON.stringify({
243
+ configPath: (0, node_path_1.join)(runtimeDir, 'config.toml'),
244
+ defaultProject: 'default',
245
+ autoStartService: true,
246
+ knowledge: {
247
+ baseUrl: '',
248
+ authMode: 'none',
249
+ token: '',
250
+ headerName: 'X-API-Key',
251
+ defaultCollection: 'personal_knowledge',
252
+ },
253
+ plugins: {
254
+ 'builtin.scheduler-lark': { enabled: false },
255
+ },
256
+ }), 'utf8');
257
+ const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
258
+ userDataPath,
259
+ });
260
+ const diagnostics = await runtime.kernel.diagnostics.snapshot();
261
+ const disabledPlugin = diagnostics.plugins.find((plugin) => plugin.pluginId === 'builtin.scheduler-lark');
262
+ strict_1.default.ok(disabledPlugin);
263
+ strict_1.default.equal(disabledPlugin.enabled, false);
264
+ strict_1.default.equal(disabledPlugin.health.status, 'degraded');
265
+ strict_1.default.deepEqual(runtime.kernel.getCapabilitySnapshot().scheduler, {
266
+ enabled: true,
267
+ triggerTypes: ['cron', 'once'],
268
+ deliveryTargets: ['weixin'],
269
+ platforms: ['weixin'],
270
+ });
271
+ }
272
+ finally {
273
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
274
+ }
275
+ });
276
+ (0, node_test_1.default)('LocalCoreController accepts injected bootstrap dependencies', async () => {
277
+ const bus = new event_bus_js_1.LocalCoreEventBus();
278
+ const capabilitySnapshot = {
279
+ adapters: {
280
+ channels: ['test-channel'],
281
+ agents: ['test-agent'],
282
+ knowledge: false,
283
+ knowledgeProviders: [],
284
+ },
285
+ scheduler: {
286
+ enabled: false,
287
+ triggerTypes: [],
288
+ deliveryTargets: [],
289
+ platforms: [],
290
+ },
291
+ snapshot: {
292
+ agents: [{ id: 'agent.test', agentType: 'test-agent' }],
293
+ channels: [{ id: 'channel.test', platform: 'test-channel' }],
294
+ knowledge: [],
295
+ schedulers: [],
296
+ ui: [],
297
+ },
298
+ };
299
+ let started = false;
300
+ let stopped = false;
301
+ let channelRefreshes = 0;
302
+ let weixinRefreshes = 0;
303
+ const controller = new local_core_controller_js_1.LocalCoreController('/tmp/local-core-controller-injected', {
304
+ kernel: {
305
+ context: {
306
+ bus,
307
+ capabilities: new capability_registry_js_1.LocalCoreCapabilityRegistry(),
308
+ logger: { log: () => { } },
309
+ },
310
+ plugins: new plugin_registry_js_1.LocalCorePluginRegistry(),
311
+ capabilities: new capability_registry_js_1.LocalCoreCapabilityRegistry(),
312
+ lifecycle: {},
313
+ diagnostics: {
314
+ snapshot: async () => ({
315
+ pluginCount: 0,
316
+ enabledPluginCount: 0,
317
+ plugins: [],
318
+ }),
319
+ },
320
+ getCapabilitySnapshot: () => capabilitySnapshot,
321
+ },
322
+ state: {
323
+ getSettings: () => ({
324
+ binaryPath: '',
325
+ configPath: '',
326
+ autoStartService: true,
327
+ defaultProject: 'default',
328
+ managementPort: 0,
329
+ managementToken: '',
330
+ bridgePort: 0,
331
+ bridgeToken: '',
332
+ bridgePath: '',
333
+ knowledge: {
334
+ baseUrl: '',
335
+ authMode: 'none',
336
+ token: '',
337
+ headerName: 'X-API-Key',
338
+ defaultCollection: 'personal_knowledge',
339
+ },
340
+ plugins: {},
341
+ }),
342
+ getLogs: () => [],
343
+ readConfigFile: async () => ({
344
+ path: '',
345
+ exists: false,
346
+ raw: '',
347
+ parsed: null,
348
+ }),
349
+ saveStructuredConfigFile: async (config) => ({
350
+ path: '',
351
+ exists: true,
352
+ raw: JSON.stringify(config),
353
+ parsed: config,
354
+ }),
355
+ },
356
+ store: {},
357
+ agentRuntimes: [],
358
+ channelRuntime: {
359
+ platform: 'test-channel',
360
+ routeType: 'channel.test',
361
+ refreshBindings: async () => {
362
+ channelRefreshes++;
363
+ },
364
+ },
365
+ weixinChannelRuntime: {
366
+ platform: 'weixin',
367
+ routeType: 'channel.chat',
368
+ refreshBindings: async () => {
369
+ weixinRefreshes++;
370
+ },
371
+ },
372
+ knowledgeProvider: {},
373
+ knowledgeAttachments: {},
374
+ workspaceRouter: {},
375
+ scheduler: {},
376
+ start: async () => {
377
+ started = true;
378
+ },
379
+ stop: async () => {
380
+ stopped = true;
381
+ },
382
+ });
383
+ await controller.init();
384
+ strict_1.default.equal(started, true);
385
+ strict_1.default.deepEqual(await controller.getCapabilities(), capabilitySnapshot);
386
+ await controller.saveStructuredConfigFile({ projects: [] });
387
+ strict_1.default.equal(channelRefreshes, 1);
388
+ strict_1.default.equal(weixinRefreshes, 1);
389
+ await controller.close();
390
+ strict_1.default.equal(stopped, true);
391
+ });
392
+ (0, node_test_1.default)('runtime logs are persisted to local-core.log', () => {
393
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-logs-'));
394
+ try {
395
+ const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
396
+ userDataPath,
397
+ enableKnowledge: false,
398
+ log: () => { },
399
+ });
400
+ runtime.state.pushLog('localcore-weixin send failed for sessionKey=test');
401
+ runtime.state.pushLog('second line');
402
+ const logPath = (0, node_path_1.join)(userDataPath, 'runtime', 'local-core.log');
403
+ const raw = (0, node_fs_1.readFileSync)(logPath, 'utf-8');
404
+ strict_1.default.match(raw, /^\d{4}-\d{2}-\d{2}T.* localcore-weixin send failed for sessionKey=test/m);
405
+ strict_1.default.match(raw, /^\d{4}-\d{2}-\d{2}T.* second line/m);
406
+ }
407
+ finally {
408
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
409
+ }
410
+ });
411
+ (0, node_test_1.default)('channel plugin lifecycle start and stop are driven by the kernel lifecycle', async () => {
412
+ const calls = [];
413
+ const registry = new plugin_registry_js_1.LocalCorePluginRegistry();
414
+ registry.register({
415
+ manifest: {
416
+ id: 'plugin.channel-test',
417
+ kind: 'channel',
418
+ version: '0.1.0',
419
+ provides: ['channel:test'],
420
+ },
421
+ init: () => {
422
+ calls.push('init');
423
+ },
424
+ start: () => {
425
+ calls.push('start');
426
+ },
427
+ stop: () => {
428
+ calls.push('stop');
429
+ },
430
+ });
431
+ const lifecycle = new lifecycle_manager_js_1.LocalCoreLifecycleManager(registry, {
432
+ bus: new event_bus_js_1.LocalCoreEventBus(),
433
+ capabilities: new capability_registry_js_1.LocalCoreCapabilityRegistry(),
434
+ logger: { log: () => { } },
435
+ });
436
+ await lifecycle.startAll();
437
+ await lifecycle.stopAll();
438
+ strict_1.default.deepEqual(calls, ['init', 'start', 'stop']);
439
+ });
440
+ (0, node_test_1.default)('channel and scheduler capabilities use registry targets instead of Lark-specific routing', () => {
441
+ const registry = new plugin_registry_js_1.LocalCorePluginRegistry();
442
+ const capabilities = new capability_registry_js_1.LocalCoreCapabilityRegistry();
443
+ const plugins = [
444
+ {
445
+ manifest: {
446
+ id: 'plugin.channel-slack',
447
+ kind: 'channel',
448
+ version: '0.1.0',
449
+ provides: ['channel:slack'],
450
+ },
451
+ capabilities: {
452
+ channels: [{ id: 'channel.slack', platform: 'slack', routeType: 'channel.chat' }],
453
+ },
454
+ },
455
+ {
456
+ manifest: {
457
+ id: 'plugin.scheduler-slack',
458
+ kind: 'scheduler',
459
+ version: '0.1.0',
460
+ dependsOn: ['plugin.channel-slack'],
461
+ provides: ['scheduler.delivery.slack'],
462
+ },
463
+ capabilities: {
464
+ schedulers: [{ id: 'scheduler.delivery.slack', triggerTypes: [], deliveryTargets: ['slack'] }],
465
+ },
466
+ },
467
+ ];
468
+ for (const entry of plugins) {
469
+ registry.register(entry);
470
+ }
471
+ for (const entry of registry.list()) {
472
+ capabilities.registerContributions(entry.capabilities || {});
473
+ }
474
+ strict_1.default.deepEqual(capabilities.snapshot().channels.map((capability) => capability.platform), ['slack']);
475
+ strict_1.default.deepEqual(capabilities.snapshot().schedulers.flatMap((capability) => capability.deliveryTargets), ['slack']);
476
+ });
477
+ (0, node_test_1.default)('agent runtime selection is registry-based and disabled runtimes do not route workspaces', async () => {
478
+ const userDataPath = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'agentdock-kernel-'));
479
+ try {
480
+ const runtimeDir = (0, node_path_1.join)(userDataPath, 'runtime');
481
+ (0, node_fs_1.mkdirSync)(runtimeDir, { recursive: true });
482
+ (0, node_fs_1.writeFileSync)((0, node_path_1.join)(runtimeDir, 'local-core-settings.json'), JSON.stringify({
483
+ configPath: (0, node_path_1.join)(runtimeDir, 'config.toml'),
484
+ defaultProject: 'default',
485
+ autoStartService: true,
486
+ knowledge: {
487
+ baseUrl: '',
488
+ authMode: 'none',
489
+ token: '',
490
+ headerName: 'X-API-Key',
491
+ defaultCollection: 'personal_knowledge',
492
+ },
493
+ plugins: {
494
+ 'builtin.agent-claudecode': { enabled: false },
495
+ },
496
+ }), 'utf8');
497
+ const runtime = (0, bootstrap_js_2.bootstrapLocalCoreRuntime)({
498
+ userDataPath,
499
+ });
500
+ await runtime.state.saveRawConfigFile(`
501
+ [[projects]]
502
+ name = "claude-workspace"
503
+
504
+ [projects.agent]
505
+ type = "claudecode"
506
+ `);
507
+ strict_1.default.deepEqual(runtime.agentRuntimes.map((entry) => entry.agentType), ['localcore-acp', 'opencode']);
508
+ strict_1.default.equal(runtime.kernel.getCapabilitySnapshot().snapshot.agents.some((capability) => capability.agentType === 'claudecode'), false);
509
+ strict_1.default.deepEqual(await runtime.workspaceRouter.listWorkspaces(), []);
510
+ await strict_1.default.rejects(() => runtime.workspaceRouter.listThreads('claude-workspace'), /Workspace "claude-workspace" is not configured as a Local AI Core ACP workspace/);
511
+ await runtime.stop();
512
+ }
513
+ finally {
514
+ (0, node_fs_1.rmSync)(userDataPath, { recursive: true, force: true });
515
+ }
516
+ });
517
+ (0, node_test_1.default)('renderer route and nav rendering are sourced from the contribution registry', () => {
518
+ const appSource = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'src', 'App.tsx'), 'utf8');
519
+ const sidebarSource = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'src', 'components', 'Layout', 'Sidebar.tsx'), 'utf8');
520
+ const headerSource = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'src', 'components', 'Layout', 'Header.tsx'), 'utf8');
521
+ strict_1.default.match(appSource, /rendererUiContributions\.listRoutes\(\)\.map/);
522
+ strict_1.default.match(sidebarSource, /rendererUiContributions\s*\.\s*listNavItems\(\)/);
523
+ strict_1.default.match(headerSource, /resolveRouteTitleKey/);
524
+ });
525
+ (0, node_test_1.default)('renderer feature visibility is capability-driven', () => {
526
+ const runtimeSource = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'src', 'app', 'runtime.ts'), 'utf8');
527
+ const sidebarSource = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'src', 'components', 'Layout', 'Sidebar.tsx'), 'utf8');
528
+ const dashboardSource = (0, node_fs_1.readFileSync)((0, node_path_1.join)(process.cwd(), 'src', 'pages', 'Dashboard.tsx'), 'utf8');
529
+ strict_1.default.match(runtimeSource, /snapshot\?\.knowledge\.some/);
530
+ strict_1.default.match(runtimeSource, /snapshot\?\.schedulers\.some/);
531
+ strict_1.default.match(runtimeSource, /snapshot\?\.agents\.some/);
532
+ strict_1.default.match(sidebarSource, /useRuntimeFeatureSupport/);
533
+ strict_1.default.match(dashboardSource, /useRuntimeFeatureSupport/);
534
+ });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,18 @@
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("../../../shared/desktop"), exports);
18
+ __exportStar(require("./local-core"), exports);
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });