@kafca/agentdock 0.1.46 → 0.1.47

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 (87) hide show
  1. package/README.md +6 -0
  2. package/dist/renderer/assets/{Badge-BIesaDYG.js → Badge-BYREM3t3.js} +1 -1
  3. package/dist/renderer/assets/{Chat-CpataoDh.js → Chat-Dtb5X7sB.js} +1 -1
  4. package/dist/renderer/assets/{ChatMarkdown-_Mdmltgv.js → ChatMarkdown-_slLloCh.js} +1 -1
  5. package/dist/renderer/assets/{Config-Pe5-zKZk.js → Config-pHichs7H.js} +1 -1
  6. package/dist/renderer/assets/{CronList-BnaOSPT8.js → CronList-CJQMeCjz.js} +1 -1
  7. package/dist/renderer/assets/{Dashboard-D05l8GKE.js → Dashboard-CY77Imde.js} +2 -2
  8. package/dist/renderer/assets/{EmptyState-BDBavDll.js → EmptyState-DCqmct2y.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeDetail-DvR798l_.js → KnowledgeDetail-DFrxa-pv.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeHome-r2ZuvU8-.js → KnowledgeHome-DL-vAfrH.js} +1 -1
  11. package/dist/renderer/assets/{Logs-BaljtmAV.js → Logs-jw9Uv590.js} +1 -1
  12. package/dist/renderer/assets/{Modal-CXhD_OWR.js → Modal-ChSm7tk6.js} +1 -1
  13. package/dist/renderer/assets/{MonitorList-D7tyipbx.js → MonitorList-DrEwyS71.js} +1 -1
  14. package/dist/renderer/assets/{Page-KUuFYgjg.js → Page-DhD-zgMU.js} +1 -1
  15. package/dist/renderer/assets/ProjectDetail-BVSjpfpL.js +11 -0
  16. package/dist/renderer/assets/{ProjectList-CbdHd5Ev.js → ProjectList-CHGbTJjk.js} +1 -1
  17. package/dist/renderer/assets/{Select-Djc8BXMC.js → Select-rHs9CSam.js} +1 -1
  18. package/dist/renderer/assets/{SessionChat-DOy0iKQR.js → SessionChat-CDc2FNMA.js} +1 -1
  19. package/dist/renderer/assets/{SessionList-DHgl1s1D.js → SessionList-Mr1uAnRW.js} +1 -1
  20. package/dist/renderer/assets/ThreadChat-Detu5UfN.js +23 -0
  21. package/dist/renderer/assets/{Workspace-DTocqY-F.js → Workspace-MRRg8ndJ.js} +1 -1
  22. package/dist/renderer/assets/{arrow-left-CXyya3hP.js → arrow-left-BU2NB2LA.js} +1 -1
  23. package/dist/renderer/assets/{book-open-9n4Kxc7E.js → book-open-D-TGvWwa.js} +1 -1
  24. package/dist/renderer/assets/{bot-C9HBk5XH.js → bot-IYNh8tH5.js} +1 -1
  25. package/dist/renderer/assets/{check-CutSg9a5.js → check-CCZ0JO_S.js} +1 -1
  26. package/dist/renderer/assets/{chevron-down-DrydR4i3.js → chevron-down-00bRZi15.js} +1 -1
  27. package/dist/renderer/assets/{circle-BEjtahw6.js → circle-CpQ8x4k_.js} +1 -1
  28. package/dist/renderer/assets/{desktop-DATgk_ka.js → desktop-D0k2aGSj.js} +1 -1
  29. package/dist/renderer/assets/{funnel-BhqZpS4f.js → funnel-UbcrCBCp.js} +1 -1
  30. package/dist/renderer/assets/{heart-Dp8Vs-7_.js → heart-DvLsV7tL.js} +1 -1
  31. package/dist/renderer/assets/{index-BKpv0P0s.js → index-B2L4G-b_.js} +1 -1
  32. package/dist/renderer/assets/{index-cI3pWBnN.js → index-dy-g2Bh4.js} +2 -2
  33. package/dist/renderer/assets/{pencil-ywcJzeOo.js → pencil-qBYOgW5M.js} +1 -1
  34. package/dist/renderer/assets/{play-AtN492Cx.js → play-Dn6b4AGj.js} +1 -1
  35. package/dist/renderer/assets/{plus-BEj14BBV.js → plus-CaApUwEm.js} +1 -1
  36. package/dist/renderer/assets/projects-BwF5RlNV.js +1 -0
  37. package/dist/renderer/assets/{save-D6ov4CNv.js → save-CN6yvTfD.js} +1 -1
  38. package/dist/renderer/assets/{search-C3bvw7AR.js → search-Dn2MxYiO.js} +1 -1
  39. package/dist/renderer/assets/{server-C1Uyedyx.js → server-DpcVLHeh.js} +1 -1
  40. package/dist/renderer/assets/{session-utils-DpRwJ6Nh.js → session-utils-DnD2Q_y1.js} +1 -1
  41. package/dist/renderer/assets/{sessions-BWmAppwK.js → sessions-eK5D4FLt.js} +1 -1
  42. package/dist/renderer/assets/{shield-check-CVx1mEs2.js → shield-check-DSSJkacw.js} +1 -1
  43. package/dist/renderer/assets/{trash-2-o-heXOgs.js → trash-2-DmYJlEvO.js} +1 -1
  44. package/dist/renderer/assets/{user-dPOzUqIc.js → user-Cvf_uiyQ.js} +1 -1
  45. package/dist/renderer/assets/{wifi-off-Fz5c3_x_.js → wifi-off-CCTloj-V.js} +1 -1
  46. package/dist/renderer/index.html +1 -1
  47. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +2 -1
  48. package/dist-electron/services/local-ai-core/src/agents/pi/launch.js +1 -1
  49. package/dist-electron/services/local-ai-core/src/agents/shared/launch-utils.js +22 -0
  50. package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +132 -348
  51. package/dist-electron/services/local-ai-core/src/channel/shared/base-channel-gateway.js +303 -0
  52. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +131 -382
  53. package/dist-electron/services/local-ai-core/src/runtime/agent-runtime-detector.js +2 -1
  54. package/dist-electron/services/local-ai-core/src/runtime/channel-service.js +150 -0
  55. package/dist-electron/services/local-ai-core/src/runtime/env-utils.js +12 -0
  56. package/dist-electron/services/local-ai-core/src/runtime/external-service.js +234 -0
  57. package/dist-electron/services/local-ai-core/src/runtime/handlers/automation-handler.js +34 -0
  58. package/dist-electron/services/local-ai-core/src/runtime/handlers/capabilities-handler.js +12 -0
  59. package/dist-electron/services/local-ai-core/src/runtime/handlers/channel-handler.js +65 -0
  60. package/dist-electron/services/local-ai-core/src/runtime/handlers/external-handler.js +17 -0
  61. package/dist-electron/services/local-ai-core/src/runtime/handlers/knowledge-handler.js +65 -0
  62. package/dist-electron/services/local-ai-core/src/runtime/handlers/openai-handler.js +496 -0
  63. package/dist-electron/services/local-ai-core/src/runtime/handlers/provider-handler.js +24 -0
  64. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtime-handler.js +68 -0
  65. package/dist-electron/services/local-ai-core/src/runtime/handlers/runtimes-handler.js +37 -0
  66. package/dist-electron/services/local-ai-core/src/runtime/handlers/scheduler-handler.js +34 -0
  67. package/dist-electron/services/local-ai-core/src/runtime/handlers/security-handler.js +49 -0
  68. package/dist-electron/services/local-ai-core/src/runtime/handlers/task-handler.js +27 -0
  69. package/dist-electron/services/local-ai-core/src/runtime/handlers/thread-handler.js +42 -0
  70. package/dist-electron/services/local-ai-core/src/runtime/handlers/workspace-handler.js +29 -0
  71. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +40 -592
  72. package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +96 -0
  73. package/dist-electron/services/local-ai-core/src/runtime/server.js +107 -1084
  74. package/dist-electron/services/local-ai-core/src/runtime/standalone.js +13 -1
  75. package/dist-electron/src/pages/Projects/project-provider-config.js +75 -0
  76. package/dist-electron/tests/contracts/architecture-docs.test.js +1 -0
  77. package/dist-electron/tests/electron/agent-runtime-detector.test.js +18 -0
  78. package/dist-electron/tests/electron/knowledge-skill-script.test.js +15 -5
  79. package/dist-electron/tests/electron/lac-cli.test.js +591 -688
  80. package/dist-electron/tests/electron/plugin-kernel.test.js +47 -31
  81. package/dist-electron/tests/electron/project-provider-config.test.js +71 -0
  82. package/dist-electron/tests/electron/workspace-task-store.test.js +19 -9
  83. package/dist-electron/tests/integration/local-core-cors.test.js +22 -0
  84. package/package.json +1 -1
  85. package/dist/renderer/assets/ProjectDetail-Ddq94-yu.js +0 -11
  86. package/dist/renderer/assets/ThreadChat-I7dYibDc.js +0 -23
  87. package/dist/renderer/assets/projects-Clar8lgb.js +0 -1
@@ -2,28 +2,28 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LocalCoreController = void 0;
4
4
  const node_events_1 = require("node:events");
5
- const node_crypto_1 = require("node:crypto");
6
- const node_fs_1 = require("node:fs");
7
- const node_path_1 = require("node:path");
8
5
  const desktop_js_1 = require("../../../../shared/desktop.js");
9
6
  const bootstrap_js_1 = require("../kernel/bootstrap.js");
10
7
  const local_core_errors_js_1 = require("../kernel/local-core-errors.js");
11
8
  const runtime_detection_service_js_1 = require("./runtime-detection-service.js");
12
9
  const provider_config_migration_js_1 = require("./provider-config-migration.js");
10
+ const channel_service_js_1 = require("./channel-service.js");
11
+ const external_service_js_1 = require("./external-service.js");
13
12
  const deployment_diagnostics_js_1 = require("./deployment-diagnostics.js");
14
13
  class LocalCoreController extends node_events_1.EventEmitter {
15
14
  userDataPath;
16
- state;
15
+ store;
17
16
  workspaceRouter;
18
17
  knowledgeProvider;
19
- channelRuntimes;
18
+ channelService;
19
+ externalService;
20
20
  scheduledJobs;
21
21
  automationMonitors;
22
- store;
23
- kernel;
24
- runtime;
25
22
  runtimeDetection;
23
+ kernel;
26
24
  errorReporter;
25
+ state;
26
+ runtime;
27
27
  busUnsubscribers = [];
28
28
  pendingLogs = [];
29
29
  handlingLog = false;
@@ -41,7 +41,12 @@ class LocalCoreController extends node_events_1.EventEmitter {
41
41
  this.knowledgeProvider = this.runtime.knowledgeProvider;
42
42
  this.workspaceRouter = this.runtime.workspaceRouter;
43
43
  const runtimeChannels = this.runtime.channelRuntimes || [this.runtime.channelRuntime, this.runtime.weixinChannelRuntime];
44
- this.channelRuntimes = new Map(runtimeChannels.filter(Boolean).map((runtime) => [runtime.platform, runtime]));
44
+ const channelRuntimes = new Map(runtimeChannels.filter(Boolean).map((ch) => [ch.platform, ch]));
45
+ this.channelService = new channel_service_js_1.ChannelService(channelRuntimes);
46
+ this.externalService = new external_service_js_1.ExternalService(this.store, this.workspaceRouter, {
47
+ readConfigState: () => this.readConfigFile(),
48
+ saveStructuredConfig: (config) => this.saveStructuredConfigFile(config),
49
+ }, userDataPath);
45
50
  this.scheduledJobs = this.runtime.scheduledJobs;
46
51
  this.automationMonitors = this.runtime.automationMonitors || {
47
52
  listMonitors: () => [],
@@ -132,7 +137,7 @@ class LocalCoreController extends node_events_1.EventEmitter {
132
137
  return { status: 'running' };
133
138
  }
134
139
  async restartService() {
135
- await this.refreshChannelBindings();
140
+ await this.channelService.refreshBindings();
136
141
  await this.emitRuntime();
137
142
  return { status: 'running' };
138
143
  }
@@ -147,437 +152,30 @@ class LocalCoreController extends node_events_1.EventEmitter {
147
152
  }
148
153
  async saveRawConfigFile(raw) {
149
154
  const next = await this.state.saveRawConfigFile(raw);
150
- await this.refreshChannelBindings();
155
+ await this.channelService.refreshBindings();
151
156
  await this.emitRuntime();
152
157
  return next;
153
158
  }
154
159
  async saveStructuredConfigFile(config) {
155
160
  const migrated = (0, provider_config_migration_js_1.migrateLegacyProjectProvidersToStore)(config, this.store);
156
161
  const next = await this.state.saveStructuredConfigFile(migrated.config);
157
- await this.refreshChannelBindings();
162
+ await this.channelService.refreshBindings();
158
163
  await this.emitRuntime();
159
164
  return next;
160
165
  }
161
- async listModelProviders() {
162
- return { providers: this.store.listModelProviders() };
163
- }
164
- async createModelProvider(input) {
165
- return this.store.upsertModelProvider(input);
166
- }
167
- async updateModelProvider(providerId, input) {
168
- const existing = this.store.getModelProvider(providerId);
169
- if (!existing) {
170
- throw new Error(`Provider not found: ${providerId}`);
171
- }
172
- return this.store.upsertModelProvider({ ...input, id: providerId });
173
- }
174
- async deleteModelProvider(providerId) {
175
- const config = await this.readAndMigrateConfigFile();
176
- const referencingProjects = (config.parsed?.projects || [])
177
- .filter((project) => project.agent?.options?.provider_id === providerId)
178
- .map((project) => project.name);
179
- if (referencingProjects.length > 0) {
180
- throw new Error(`Provider "${providerId}" is still used by projects: ${referencingProjects.join(', ')}`);
181
- }
182
- return this.store.deleteModelProvider(providerId);
183
- }
184
166
  async saveSettings(input) {
185
167
  const settings = await this.state.saveSettings(input);
186
- await this.refreshChannelBindings();
168
+ await this.channelService.refreshBindings();
187
169
  await this.emitRuntime();
188
170
  return settings;
189
171
  }
190
- async ensureExternalProject(input) {
191
- const userId = normalizeExternalId(input.user_id, 'user_id');
192
- const externalProjectId = normalizeExternalId(input.external_project_id, 'external_project_id');
193
- const agentType = normalizeExternalSegment(input.agent_type || 'pi', 'pi');
194
- const existing = this.store.getExternalProject(userId, externalProjectId);
195
- const provider = this.resolveExternalProvider(input.provider_id || existing?.providerId);
196
- const workspaceId = externalWorkspaceId(userId, externalProjectId);
197
- const workspacePath = this.externalProjectBasePath(userId, externalProjectId);
198
- const displayName = String(input.display_name || externalProjectId).trim() || externalProjectId;
199
- (0, node_fs_1.mkdirSync)(workspacePath, { recursive: true, mode: 0o700 });
200
- const now = new Date().toISOString();
201
- const project = this.store.upsertExternalProject({
202
- userId,
203
- externalProjectId,
204
- workspaceId,
205
- workspacePath,
206
- displayName,
207
- agentType,
208
- providerId: provider.id,
209
- metadata: input.metadata || existing?.metadata || {},
210
- createdAt: existing?.createdAt || now,
211
- updatedAt: now,
212
- });
213
- await this.ensureExternalWorkspaceConfig(project, input.model);
214
- this.store.upsertWorkspaceRegistryEntry({
215
- workspaceId: project.workspaceId,
216
- displayName: project.displayName,
217
- path: project.workspacePath,
218
- deviceId: 'external',
219
- defaultRuntimeId: project.agentType,
220
- health: { status: 'healthy', summary: 'External workspace is available.', issues: [], checkedAt: now },
221
- metadata: {
222
- external: true,
223
- userId: project.userId,
224
- externalProjectId: project.externalProjectId,
225
- },
226
- });
227
- return project;
228
- }
229
- async createExternalRun(input) {
230
- if (!String(input.prompt || '').trim()) {
231
- throw new Error('prompt is required.');
232
- }
233
- const project = await this.ensureExternalProject(input);
234
- const thread = await this.ensureExternalThread(project, input);
235
- const sent = await this.workspaceRouter.sendThreadMessage(thread.threadId, input.prompt, {
236
- permissionMode: input.permission_mode,
237
- runtimeEnv: input.runtime_env,
238
- });
239
- const task = this.store.getAgentTaskByRunId(sent.runId);
240
- return {
241
- project,
242
- thread,
243
- workspace_id: project.workspaceId,
244
- thread_id: thread.threadId,
245
- run_id: sent.runId,
246
- task_id: task?.taskId,
247
- events_url: `/api/local/v1/external/runs/${encodeURIComponent(sent.runId)}/events`,
248
- };
249
- }
250
- async getExternalRunSnapshot(runId) {
251
- const task = this.store.getAgentTaskByRunId(runId);
252
- const run = this.store.getRun(runId);
253
- const threadId = task?.threadId || run?.thread_id || '';
254
- const thread = threadId
255
- ? await this.workspaceRouter.getThread(threadId).catch(() => undefined)
256
- : undefined;
257
- return {
258
- runId,
259
- task,
260
- thread,
261
- };
262
- }
263
- async readAndMigrateConfigFile() {
264
- const current = await this.state.readConfigFile();
265
- if (!current.parsed) {
266
- return current;
267
- }
268
- const migrated = (0, provider_config_migration_js_1.migrateLegacyProjectProvidersToStore)(current.parsed, this.store);
269
- if (!migrated.changed) {
270
- return current;
271
- }
272
- const saved = await this.state.saveStructuredConfigFile(migrated.config);
273
- return {
274
- ...saved,
275
- warnings: [
276
- ...(current.warnings || []),
277
- ...(saved.warnings || []),
278
- ...migrated.warnings,
279
- ],
280
- };
281
- }
282
- resolveExternalProvider(providerId) {
283
- const requested = String(providerId || '').trim();
284
- if (requested) {
285
- const provider = this.store.getModelProvider(requested);
286
- if (!provider) {
287
- throw new Error(`Provider not found: ${requested}`);
288
- }
289
- return provider;
290
- }
291
- const provider = this.store.listModelProviders()[0];
292
- if (!provider) {
293
- throw new Error('No model provider is configured. Create a provider before starting an external run.');
294
- }
295
- return provider;
296
- }
297
- async ensureExternalWorkspaceConfig(project, model) {
298
- const current = await this.readAndMigrateConfigFile();
299
- const config = {
300
- ...(current.parsed || {}),
301
- projects: Array.isArray(current.parsed?.projects) ? [...current.parsed.projects] : [],
302
- };
303
- const existingIndex = config.projects.findIndex((item) => item?.name === project.workspaceId);
304
- const existing = existingIndex >= 0 ? config.projects[existingIndex] : undefined;
305
- const defaultRuntimeImageId = Array.isArray(config.sandbox_runtime_images)
306
- ? config.sandbox_runtime_images.find((image) => image?.agent_type === project.agentType)?.id
307
- : undefined;
308
- const options = {
309
- ...(existing?.agent?.options || {}),
310
- work_dir: project.workspacePath,
311
- user_id: project.userId,
312
- provider_id: project.providerId,
313
- ...(model ? { model } : {}),
314
- sandbox: {
315
- ...(existing?.agent?.options?.sandbox || {}),
316
- enabled: true,
317
- ...(defaultRuntimeImageId ? { runtime_image_id: defaultRuntimeImageId } : {}),
318
- state_scope: 'project',
319
- sandbox_lifecycle: 'per_thread',
320
- },
321
- };
322
- const nextProject = {
323
- name: project.workspaceId,
324
- agent: {
325
- ...(existing?.agent || {}),
326
- type: project.agentType,
327
- options,
328
- },
329
- platforms: Array.isArray(existing?.platforms) ? existing.platforms : [],
330
- admin_from: existing?.admin_from,
331
- disabled_commands: existing?.disabled_commands,
332
- };
333
- if (existingIndex >= 0) {
334
- config.projects[existingIndex] = nextProject;
335
- }
336
- else {
337
- config.projects.push(nextProject);
338
- }
339
- await this.saveStructuredConfigFile(config);
340
- }
341
- async ensureExternalThread(project, input) {
342
- const externalThreadId = normalizeExternalId(input.external_thread_id || `thread-${(0, node_crypto_1.randomUUID)()}`, 'external_thread_id');
343
- const existing = this.store.getExternalThread(project.userId, project.externalProjectId, externalThreadId);
344
- if (existing) {
345
- const thread = await this.workspaceRouter.getThread(existing.threadId).catch(() => undefined);
346
- if (thread) {
347
- return existing;
348
- }
349
- }
350
- const workspacePath = this.externalThreadWorkspacePath(project.userId, project.externalProjectId, externalThreadId);
351
- (0, node_fs_1.mkdirSync)(workspacePath, { recursive: true, mode: 0o700 });
352
- const title = String(input.title || externalThreadId).trim() || externalThreadId;
353
- const thread = await this.workspaceRouter.createThread(project.workspaceId, title);
354
- const now = new Date().toISOString();
355
- return this.store.upsertExternalThread({
356
- userId: project.userId,
357
- externalProjectId: project.externalProjectId,
358
- externalThreadId,
359
- workspaceId: project.workspaceId,
360
- threadId: thread.id,
361
- workspacePath,
362
- metadata: input.metadata || {},
363
- createdAt: now,
364
- updatedAt: now,
365
- });
366
- }
367
- externalProjectBasePath(userId, externalProjectId) {
368
- return (0, node_path_1.join)(this.externalWorkspaceRoot(), 'users', normalizeExternalSegment(userId, 'user'), 'projects', normalizeExternalSegment(externalProjectId, 'project'));
369
- }
370
- externalThreadWorkspacePath(userId, externalProjectId, externalThreadId) {
371
- return (0, node_path_1.join)(this.externalProjectBasePath(userId, externalProjectId), 'threads', normalizeExternalSegment(externalThreadId, 'thread'), 'workspace');
372
- }
373
- externalWorkspaceRoot() {
374
- return String(process.env.AGENTDOCK_EXTERNAL_WORKSPACE_ROOT || '').trim()
375
- || (0, node_path_1.join)(this.userDataPath, 'external-workspaces');
376
- }
377
- async listWorkspaces() {
378
- return this.workspaceRouter.listWorkspaces();
379
- }
380
- async listWorkspaceRegistry() {
381
- return this.workspaceRouter.listWorkspaceRegistry();
382
- }
383
- async getWorkspaceRegistryEntry(workspaceId) {
384
- return this.workspaceRouter.getWorkspaceRegistryEntry(workspaceId);
385
- }
386
- async createWorkspaceRegistryEntry(input) {
387
- return this.workspaceRouter.createWorkspaceRegistryEntry(input);
388
- }
389
- async updateWorkspaceRegistryEntry(workspaceId, input) {
390
- return this.workspaceRouter.updateWorkspaceRegistryEntry(workspaceId, input);
391
- }
392
- async deleteWorkspaceRegistryEntry(workspaceId) {
393
- return this.workspaceRouter.deleteWorkspaceRegistryEntry(workspaceId);
394
- }
395
- async listAgentTasks(query = {}) {
396
- return this.workspaceRouter.listAgentTasks(query);
397
- }
398
- async getAgentTask(taskId) {
399
- return this.workspaceRouter.getAgentTask(taskId);
400
- }
401
- async createAgentTask(input) {
402
- return this.workspaceRouter.createAgentTask(input);
403
- }
404
- async updateAgentTask(taskId, input) {
405
- return this.workspaceRouter.updateAgentTask(taskId, input);
406
- }
407
- async getWorkspaceSecuritySettings(workspaceId) {
408
- return this.workspaceRouter.getWorkspaceSecuritySettings(workspaceId);
409
- }
410
- async updateWorkspaceSecuritySettings(workspaceId, input) {
411
- return this.workspaceRouter.updateWorkspaceSecuritySettings(workspaceId, input);
412
- }
413
- async classifyCommand(command, workspaceId) {
414
- return this.workspaceRouter.classifyCommand(command, workspaceId);
415
- }
416
- async listApprovalRequests(query = {}) {
417
- return this.workspaceRouter.listApprovalRequests(query);
418
- }
419
- async getApprovalRequest(approvalId) {
420
- return this.workspaceRouter.getApprovalRequest(approvalId);
421
- }
422
- async createApprovalRequest(input) {
423
- return this.workspaceRouter.createApprovalRequest(input);
424
- }
425
- async resolveApprovalRequest(approvalId, input) {
426
- return this.workspaceRouter.resolveApprovalRequest(approvalId, input);
427
- }
428
- async listAuditEvents(query = {}) {
429
- return this.workspaceRouter.listAuditEvents(query);
430
- }
431
- async listScheduledJobs(workspaceId) {
432
- return this.scheduledJobs.listJobs(workspaceId);
433
- }
434
- async getScheduledJob(jobId) {
435
- const job = this.scheduledJobs.getJob(jobId);
436
- if (!job) {
437
- throw new Error(`Scheduled job not found: ${jobId}`);
438
- }
439
- return job;
440
- }
441
- async createScheduledJob(input) {
442
- return this.scheduledJobs.createJob(input);
443
- }
444
- async updateScheduledJob(jobId, input) {
445
- return this.scheduledJobs.updateJob(jobId, input);
446
- }
447
- async deleteScheduledJob(jobId) {
448
- return this.scheduledJobs.deleteJob(jobId);
449
- }
450
- async runScheduledJob(jobId) {
451
- return this.scheduledJobs.runJobNow(jobId);
452
- }
453
- async listScheduledJobRuns(jobId) {
454
- return this.scheduledJobs.listJobRuns(jobId);
455
- }
456
- async listAutomationMonitors(workspaceId) {
457
- return this.automationMonitors.listMonitors(workspaceId);
458
- }
459
- async getAutomationMonitor(monitorId) {
460
- const monitor = this.automationMonitors.getMonitor(monitorId);
461
- if (!monitor) {
462
- throw new Error(`Automation monitor not found: ${monitorId}`);
463
- }
464
- return monitor;
465
- }
466
- async createAutomationMonitor(input) {
467
- return this.automationMonitors.createMonitor(input);
468
- }
469
- async updateAutomationMonitor(monitorId, input) {
470
- return this.automationMonitors.updateMonitor(monitorId, input);
471
- }
472
- async deleteAutomationMonitor(monitorId) {
473
- return this.automationMonitors.deleteMonitor(monitorId);
474
- }
475
- async runAutomationMonitor(monitorId) {
476
- return this.automationMonitors.runMonitorNow(monitorId);
477
- }
478
- async listAutomationMonitorRuns(monitorId) {
479
- return this.automationMonitors.listRuns(monitorId);
480
- }
481
- async listThreads(workspaceId) {
482
- return this.workspaceRouter.listThreads(workspaceId);
483
- }
484
- async createThread(workspaceId, title) {
485
- return this.workspaceRouter.createThread(workspaceId, title);
486
- }
487
- async getThread(threadId) {
488
- return this.workspaceRouter.getThread(threadId);
489
- }
490
- async renameThread(threadId, title) {
491
- return this.workspaceRouter.renameThread(threadId, title);
492
- }
493
- async updateThreadKnowledgeBases(threadId, knowledgeBaseIds) {
494
- return this.workspaceRouter.updateThreadKnowledgeBases(threadId, knowledgeBaseIds);
495
- }
496
- async deleteThread(threadId) {
497
- return this.workspaceRouter.deleteThread(threadId);
498
- }
499
- async sendThreadMessage(threadId, content) {
500
- return this.workspaceRouter.sendThreadMessage(threadId, content);
501
- }
502
- async sendThreadAction(threadId, content) {
503
- return this.workspaceRouter.sendThreadAction(threadId, content);
504
- }
505
- async interruptRun(runId) {
506
- return this.workspaceRouter.interruptRun(runId);
507
- }
508
- async listKnowledgeSources() {
509
- return this.knowledgeProvider.listSources();
510
- }
511
- async getKnowledgeConfig() {
512
- return this.knowledgeProvider.getConfig();
513
- }
514
- async updateKnowledgeConfig(input) {
515
- return this.knowledgeProvider.updateConfig(input);
516
- }
517
- async listKnowledgeFolders() {
518
- return this.knowledgeProvider.listFolders();
519
- }
520
- async createKnowledgeFolder(input) {
521
- return this.knowledgeProvider.createFolder(input);
522
- }
523
- async updateKnowledgeFolder(id, input) {
524
- return this.knowledgeProvider.updateFolder(id, input);
525
- }
526
- async deleteKnowledgeFolder(id) {
527
- return this.knowledgeProvider.deleteFolder(id);
528
- }
529
- async listKnowledgeBases() {
530
- return this.knowledgeProvider.listKnowledgeBases();
531
- }
532
- async getKnowledgeBase(id) {
533
- return this.knowledgeProvider.getKnowledgeBase(id);
534
- }
535
- async createKnowledgeBase(input) {
536
- return this.knowledgeProvider.createKnowledgeBase(input);
537
- }
538
- async updateKnowledgeBase(id, input) {
539
- return this.knowledgeProvider.updateKnowledgeBase(id, input);
540
- }
541
- async deleteKnowledgeBase(id) {
542
- return this.knowledgeProvider.deleteKnowledgeBase(id);
543
- }
544
- async listKnowledgeBaseFiles(knowledgeBaseId) {
545
- return this.knowledgeProvider.listKnowledgeBaseFiles(knowledgeBaseId);
546
- }
547
- async uploadKnowledgeBaseFiles(knowledgeBaseId, request) {
548
- return this.knowledgeProvider.uploadKnowledgeBaseFiles(knowledgeBaseId, request);
549
- }
550
- async deleteKnowledgeBaseFile(knowledgeBaseId, fileId) {
551
- return this.knowledgeProvider.deleteKnowledgeBaseFile(knowledgeBaseId, fileId);
552
- }
553
- async searchKnowledgeBase(knowledgeBaseId, input) {
554
- return this.knowledgeProvider.searchKnowledgeBase(knowledgeBaseId, input);
555
- }
556
- async getCapabilities() {
557
- return this.kernel.getCapabilitySnapshot();
558
- }
559
- async getCapabilitySnapshot() {
560
- return this.kernel.getCapabilitySnapshot().snapshot;
561
- }
562
- async listInstalledAgentRuntimes() {
563
- return this.runtimeDetection.list();
564
- }
565
- async refreshInstalledAgentRuntimes(runtimeId) {
566
- return this.runtimeDetection.refresh(runtimeId);
567
- }
568
- isRuntimeDetectionRunning(runtimeId) {
569
- return this.runtimeDetection.isChecking(runtimeId);
570
- }
571
172
  async getPluginDiagnostics() {
572
173
  return this.kernel.diagnostics.snapshot();
573
174
  }
574
- async listDiagnosticErrors() {
575
- return this.errorReporter.list();
576
- }
577
175
  async runDiagnosticsDoctor() {
578
176
  const checkedAt = new Date().toISOString();
579
177
  const configFile = await this.readConfigFile();
580
- const runtimeChecks = await this.refreshInstalledAgentRuntimes().catch((error) => {
178
+ const runtimeChecks = await this.runtimeDetection.refresh().catch((error) => {
581
179
  const errorInfo = (0, local_core_errors_js_1.toLocalCoreErrorInfo)(error, 'internal_error');
582
180
  return [{
583
181
  agentType: 'runtime',
@@ -595,7 +193,7 @@ class LocalCoreController extends node_events_1.EventEmitter {
595
193
  lastLaunchError: errorInfo,
596
194
  }];
597
195
  });
598
- const channelStatuses = await this.listChannelGatewayStatuses().catch(() => []);
196
+ const channelStatuses = await this.channelService.listStatuses().catch(() => []);
599
197
  const checks = [
600
198
  configFile.error
601
199
  ? {
@@ -642,144 +240,15 @@ class LocalCoreController extends node_events_1.EventEmitter {
642
240
  const configFile = await this.readConfigFile();
643
241
  return (0, deployment_diagnostics_js_1.runDeploymentDiagnostics)({ config: configFile.parsed });
644
242
  }
645
- async probeWorkspaceStreaming(workspaceId) {
646
- return this.workspaceRouter.probeWorkspaceStreaming(workspaceId);
647
- }
648
- handleRuntimeDetectionEvent(event) {
649
- this.emit('runtime-detection', event);
650
- }
651
- async listChannelGatewayStatuses(platform) {
652
- if (!platform) {
653
- const statuses = await Promise.all([...this.channelRuntimes.values()].map((runtime) => runtime.listStatuses()));
654
- return statuses.flat();
655
- }
656
- return this.resolveChannelRuntime(platform).listStatuses();
657
- }
658
- async getChannelGatewayStatus(platform, workspaceId, instanceId) {
659
- return this.resolveChannelRuntime(platform).getStatus(workspaceId, instanceId);
660
- }
661
- async testChannelConnection(platform, workspaceId, instanceId) {
662
- return this.resolveChannelRuntime(platform).testConnection(workspaceId, instanceId);
663
- }
664
- async enableChannelGateway(platform, workspaceId, instanceId) {
665
- return this.resolveChannelRuntime(platform).enable(workspaceId, instanceId);
666
- }
667
- async disableChannelGateway(platform, workspaceId, instanceId) {
668
- return this.resolveChannelRuntime(platform).disable(workspaceId, instanceId);
669
- }
670
- async listChannelPendingPairings(platform, workspaceId) {
671
- return this.resolveChannelRuntime(platform).listPendingPairings(workspaceId);
672
- }
673
- async approveChannelPairing(platform, code) {
674
- return this.resolveChannelRuntime(platform).approvePairing(code);
675
- }
676
- async rejectChannelPairing(platform, code) {
677
- return this.resolveChannelRuntime(platform).rejectPairing(code);
678
- }
679
- async listChannelAuthorizedUsers(platform, workspaceId) {
680
- return this.resolveChannelRuntime(platform).listAuthorizedUsers(workspaceId);
681
- }
682
- async sendChannelFile(platform, workspaceId, input) {
683
- const runtime = this.resolveChannelRuntime(platform);
684
- if (runtime.sendOutboundMessage) {
685
- const result = await runtime.sendOutboundMessage(workspaceId, {
686
- route: {
687
- type: 'channel.chat',
688
- channelId: input.channelId,
689
- participantId: input.participantId,
690
- },
691
- parts: [{
692
- type: 'file',
693
- path: input.path,
694
- fileName: input.fileName,
695
- metadata: input.workspacePath ? { workspacePath: input.workspacePath } : undefined,
696
- }],
697
- });
698
- const attachment = result.attachments?.[0];
699
- return {
700
- platform: result.platform,
701
- workspaceId: result.workspaceId,
702
- channelId: result.channelId,
703
- messageId: result.messageIds[0] || '',
704
- messageIds: result.messageIds,
705
- fileKey: String(attachment?.metadata?.fileKey || attachment?.attachmentId || ''),
706
- attachmentId: attachment?.attachmentId,
707
- fileName: attachment?.fileName || input.fileName || '',
708
- fileSize: attachment?.fileSize || 0,
709
- metadata: result.metadata,
710
- };
711
- }
712
- if (!runtime.sendFile) {
713
- throw new Error(`Channel platform does not support sending files: ${platform}`);
714
- }
715
- return runtime.sendFile(workspaceId, input);
716
- }
717
- async sendChannelMessage(platform, workspaceId, input) {
718
- const runtime = this.resolveChannelRuntime(platform);
719
- if (!runtime.sendOutboundMessage) {
720
- throw new Error(`Channel platform does not support outbound messages: ${platform}`);
721
- }
722
- return runtime.sendOutboundMessage(workspaceId, input);
723
- }
724
- async getWeixinQrCode(workspaceId, instanceId) {
725
- return this.getChannelQrCode('weixin', workspaceId, instanceId);
726
- }
727
- async checkWeixinQrCodeStatus(workspaceId, ticket, instanceId) {
728
- return this.checkChannelQrCodeStatus('weixin', workspaceId, ticket, instanceId);
729
- }
730
- async getLarkQrCode(workspaceId, instanceId) {
731
- return this.getChannelQrCode('lark', workspaceId, instanceId);
732
- }
733
- async checkLarkQrCodeStatus(workspaceId, ticket, instanceId) {
734
- return this.checkChannelQrCodeStatus('lark', workspaceId, ticket, instanceId);
735
- }
736
- async getChannelQrCode(platform, workspaceId, instanceId) {
737
- const runtime = this.resolveChannelRuntime(platform);
738
- if (!runtime.getQrCode) {
739
- throw new Error(`Channel platform does not support QR setup: ${platform}`);
740
- }
741
- return runtime.getQrCode(workspaceId, instanceId);
742
- }
743
- async checkChannelQrCodeStatus(platform, workspaceId, ticket, instanceId) {
744
- const runtime = this.resolveChannelRuntime(platform);
745
- if (!runtime.checkQrCodeStatus) {
746
- throw new Error(`Channel platform does not support QR setup: ${platform}`);
747
- }
748
- return runtime.checkQrCodeStatus(workspaceId, ticket, instanceId);
749
- }
750
- async listLarkGatewayStatuses() {
751
- return this.listChannelGatewayStatuses('lark');
752
- }
753
- async getLarkGatewayStatus(workspaceId, instanceId) {
754
- return this.getChannelGatewayStatus('lark', workspaceId, instanceId);
755
- }
756
- async testLarkConnection(workspaceId, instanceId) {
757
- return this.testChannelConnection('lark', workspaceId, instanceId);
758
- }
759
- async enableLarkGateway(workspaceId, instanceId) {
760
- return this.enableChannelGateway('lark', workspaceId, instanceId);
761
- }
762
- async disableLarkGateway(workspaceId, instanceId) {
763
- return this.disableChannelGateway('lark', workspaceId, instanceId);
764
- }
765
- async listLarkPendingPairings(workspaceId) {
766
- return this.listChannelPendingPairings('lark', workspaceId);
767
- }
768
- async approveLarkPairing(code) {
769
- return this.approveChannelPairing('lark', code);
770
- }
771
- async rejectLarkPairing(code) {
772
- return this.rejectChannelPairing('lark', code);
773
- }
774
- async listLarkAuthorizedUsers(workspaceId) {
775
- return this.listChannelAuthorizedUsers('lark', workspaceId);
776
- }
777
243
  emitBridge(event) {
778
244
  this.emit('bridge', event);
779
245
  }
780
246
  async emitRuntime() {
781
247
  this.emit('runtime', await this.getRuntimeStatus());
782
248
  }
249
+ handleRuntimeDetectionEvent(event) {
250
+ this.emit('runtime-detection', event);
251
+ }
783
252
  handleLog(message) {
784
253
  if (this.handlingLog) {
785
254
  return;
@@ -814,45 +283,24 @@ class LocalCoreController extends node_events_1.EventEmitter {
814
283
  this.handlingLog = false;
815
284
  }
816
285
  }
817
- async refreshChannelBindings() {
818
- await Promise.all([...this.channelRuntimes.values()].map((runtime) => runtime.refreshBindings?.()));
819
- }
820
- resolveChannelRuntime(platform) {
821
- const runtime = this.channelRuntimes.get(platform);
822
- if (runtime) {
823
- return runtime;
286
+ async readAndMigrateConfigFile() {
287
+ const current = await this.state.readConfigFile();
288
+ if (!current.parsed) {
289
+ return current;
824
290
  }
825
- throw new Error(`Unsupported channel platform: ${platform}`);
826
- }
827
- assertPlatform(platform) {
828
- this.resolveChannelRuntime(platform);
291
+ const migrated = (0, provider_config_migration_js_1.migrateLegacyProjectProvidersToStore)(current.parsed, this.store);
292
+ if (!migrated.changed) {
293
+ return current;
294
+ }
295
+ const saved = await this.state.saveStructuredConfigFile(migrated.config);
296
+ return {
297
+ ...saved,
298
+ warnings: [
299
+ ...(current.warnings || []),
300
+ ...(saved.warnings || []),
301
+ ...migrated.warnings,
302
+ ],
303
+ };
829
304
  }
830
305
  }
831
306
  exports.LocalCoreController = LocalCoreController;
832
- function normalizeExternalId(value, label) {
833
- const normalized = String(value || '').trim();
834
- if (!normalized) {
835
- throw new Error(`${label} is required.`);
836
- }
837
- return normalized;
838
- }
839
- function normalizeExternalSegment(value, fallback) {
840
- return String(value || '')
841
- .trim()
842
- .toLowerCase()
843
- .replace(/[^a-z0-9._-]+/g, '-')
844
- .replace(/^-+|-+$/g, '')
845
- || fallback;
846
- }
847
- function externalWorkspaceId(userId, externalProjectId) {
848
- const base = [
849
- 'external',
850
- normalizeExternalSegment(userId, 'user'),
851
- normalizeExternalSegment(externalProjectId, 'project'),
852
- ].join('-');
853
- const digest = (0, node_crypto_1.createHash)('sha256')
854
- .update(`${userId}\0${externalProjectId}`)
855
- .digest('hex')
856
- .slice(0, 8);
857
- return `${base}-${digest}`;
858
- }