@kafca/agentdock 0.1.41 → 0.1.43
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 +10 -0
- package/dist/renderer/assets/{Badge-BX3RC8l6.js → Badge-CbG6yRSm.js} +1 -1
- package/dist/renderer/assets/{Chat-DJwIciel.js → Chat-BvNNWGGX.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-DfGbRR0S.js → ChatMarkdown-Ct-PvJB8.js} +1 -1
- package/dist/renderer/assets/{Config-2x2RDL3j.js → Config-lQX2qVVV.js} +2 -2
- package/dist/renderer/assets/CronList-Dj_3muVG.js +1 -0
- package/dist/renderer/assets/{Dashboard-2Wcx_bvJ.js → Dashboard-eh_RhGYb.js} +2 -2
- package/dist/renderer/assets/{EmptyState-DoCpF2tn.js → EmptyState-Bn2Qh14U.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-CBRu2bXX.js → KnowledgeDetail-Bsz6Ou41.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-CItdlDVR.js → KnowledgeHome-Cgj4XFXn.js} +2 -2
- package/dist/renderer/assets/{Logs-Cd_7ZOXc.js → Logs-Dp-NF6GN.js} +1 -1
- package/dist/renderer/assets/{Modal-B4eOiBsB.js → Modal-B6YPPBN6.js} +1 -1
- package/dist/renderer/assets/MonitorList-xEZWg460.js +1 -0
- package/dist/renderer/assets/{Page-C5VH4D9U.js → Page-Bn7RjGOS.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-D_DA--IP.js → ProjectDetail-Cv_jIE61.js} +2 -2
- package/dist/renderer/assets/{ProjectList-CtCXJ50u.js → ProjectList-BDk5_gqY.js} +1 -1
- package/dist/renderer/assets/{Select-B6E68LcN.js → Select-xshfMIEQ.js} +1 -1
- package/dist/renderer/assets/SessionChat-BkHy90z3.js +1 -0
- package/dist/renderer/assets/{SessionList-Do-5-Xx6.js → SessionList-BZyXT92L.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-B1tEtE3V.js → ThreadChat-DUOIyXrS.js} +7 -7
- package/dist/renderer/assets/{Workspace-BlhS2RFw.js → Workspace-Dl80fNEC.js} +1 -1
- package/dist/renderer/assets/{arrow-left-DF1_F9Pk.js → arrow-left-C54ZI-AS.js} +1 -1
- package/dist/renderer/assets/{book-open-DxRTGpWO.js → book-open-Dl7GO0zn.js} +1 -1
- package/dist/renderer/assets/{check-BAqPPYkf.js → check-CiqgtrOL.js} +1 -1
- package/dist/renderer/assets/{chevron-down-DIZZgSb3.js → chevron-down-DTL2OuVh.js} +1 -1
- package/dist/renderer/assets/{circle-B5raL_XK.js → circle-DaVKfa3P.js} +1 -1
- package/dist/renderer/assets/desktop-C6q6wBae.js +5 -0
- package/dist/renderer/assets/desktop-jaAiayNB.js +1 -0
- package/dist/renderer/assets/en-D2SkCrhG.js +1 -0
- package/dist/renderer/assets/{funnel-BPjLpVSB.js → funnel-CrmnLMJI.js} +1 -1
- package/dist/renderer/assets/{heart-D2M1xN1N.js → heart-BMfQI7y_.js} +1 -1
- package/dist/renderer/assets/{index-Cx71F_Lz.js → index-HPNb1zfx.js} +39 -34
- package/dist/renderer/assets/{index-BijJAYmo.js → index-nreiKY1f.js} +3 -3
- package/dist/renderer/assets/{pencil-DlDr8Mmp.js → pencil-wTQ4l465.js} +1 -1
- package/dist/renderer/assets/{play-BOEG_mY8.js → play-BK--MXmw.js} +1 -1
- package/dist/renderer/assets/{plug-BI27elC-.js → plug-BIx9fjip.js} +1 -1
- package/dist/renderer/assets/{plus-BhURuFIQ.js → plus-Dn7JFWQ8.js} +1 -1
- package/dist/renderer/assets/projects-brJZgwEJ.js +1 -0
- package/dist/renderer/assets/{save-RwkHNm9e.js → save-CC3zOSWb.js} +1 -1
- package/dist/renderer/assets/{search-DMNtm2WP.js → search-CDTy9Czu.js} +1 -1
- package/dist/renderer/assets/{server-CNaxKyAq.js → server-DtQk3t2a.js} +1 -1
- package/dist/renderer/assets/{session-utils-vsALZkZN.js → session-utils-4ep5D66T.js} +1 -1
- package/dist/renderer/assets/{sessions-BY-R1IL_.js → sessions-Dor1LteH.js} +1 -1
- package/dist/renderer/assets/{shield-check-BF-4oJbj.js → shield-check-Cz2LpU6r.js} +1 -1
- package/dist/renderer/assets/{trash-2-DduflM4q.js → trash-2-C2EmWFZV.js} +1 -1
- package/dist/renderer/assets/{user-DBcvnuW4.js → user-I8B-cs5A.js} +1 -1
- package/dist/renderer/assets/{wifi-off-X1nXESYu.js → wifi-off-CPevTQJn.js} +1 -1
- package/dist/renderer/assets/zh-DIcdHycM.js +1 -0
- package/dist/renderer/index.html +1 -1
- package/dist-electron/packages/contracts/src/local-core.js +28 -0
- package/dist-electron/packages/core-sdk/src/index.js +32 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +76 -39
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +13 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +4 -1357
- package/dist-electron/services/local-ai-core/src/acp/local-core-slash-commands.js +28 -0
- package/dist-electron/services/local-ai-core/src/acp/store/agent-task-store.js +166 -0
- package/dist-electron/services/local-ai-core/src/acp/store/automation-monitor-store.js +231 -0
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +263 -0
- package/dist-electron/services/local-ai-core/src/acp/store/platform-store.js +186 -0
- package/dist-electron/services/local-ai-core/src/acp/store/scheduler-store.js +201 -0
- package/dist-electron/services/local-ai-core/src/acp/store/schema.js +275 -0
- package/dist-electron/services/local-ai-core/src/acp/store/security-store.js +266 -0
- package/dist-electron/services/local-ai-core/src/acp/store/thread-store.js +232 -0
- package/dist-electron/services/local-ai-core/src/acp/store/utils.js +47 -0
- package/dist-electron/services/local-ai-core/src/acp/store/workspace-registry-store.js +109 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +136 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-repository.js +56 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +359 -0
- package/dist-electron/services/local-ai-core/src/automation/condition-evaluator.js +77 -0
- package/dist-electron/services/local-ai-core/src/automation/mock-stock-provider.js +40 -0
- package/dist-electron/services/local-ai-core/src/automation/monitor-id.js +10 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/cards.js +55 -0
- package/dist-electron/services/local-ai-core/src/channel/lark/local-core-lark-gateway.js +101 -29
- package/dist-electron/services/local-ai-core/src/channel/shared/session-command-runtime.js +53 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +51 -33
- package/dist-electron/services/local-ai-core/src/cli/lac.js +196 -0
- package/dist-electron/services/local-ai-core/src/cli/monitor-cli-parsers.js +37 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +43 -0
- package/dist-electron/services/local-ai-core/src/kernel/capability-registry.js +12 -0
- package/dist-electron/services/local-ai-core/src/plugins/builtin/monitor-stock-plugin.js +30 -0
- package/dist-electron/services/local-ai-core/src/router/workspace-router.js +40 -4
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +41 -0
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +31 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +36 -0
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-bridge-session.js +25 -11
- package/dist-electron/services/local-ai-core/src/thread/session-command-service.js +275 -0
- package/dist-electron/services/local-ai-core/src/thread/slash-command-registry.js +27 -0
- package/dist-electron/services/local-ai-core/src/thread/thread-command-service.js +134 -0
- package/dist-electron/shared/desktop.js +21 -1
- package/dist-electron/tests/contracts/local-core-contracts.test.js +9 -0
- package/dist-electron/tests/electron/automation-monitor.test.js +38 -0
- package/dist-electron/tests/electron/lac-cli.test.js +146 -0
- package/dist-electron/tests/electron/plugin-kernel.test.js +26 -0
- package/dist-electron/tests/integration/local-core-refactor.test.js +359 -0
- package/package.json +1 -1
- package/dist/renderer/assets/CronList-C6nPAmEo.js +0 -1
- package/dist/renderer/assets/SessionChat-D1HtMdQS.js +0 -1
- package/dist/renderer/assets/desktop-CFcnzwcY.js +0 -1
- package/dist/renderer/assets/desktop-O8_6ZCVZ.js +0 -4
- package/dist/renderer/assets/en-CKhCF6St.js +0 -1
- package/dist/renderer/assets/projects-DpR972HM.js +0 -1
- package/dist/renderer/assets/zh-Dz5FLTBV.js +0 -1
|
@@ -17,10 +17,12 @@ const scheduler_cron_plugin_js_1 = require("../plugins/builtin/scheduler-cron-pl
|
|
|
17
17
|
const scheduler_lark_plugin_js_1 = require("../plugins/builtin/scheduler-lark-plugin.js");
|
|
18
18
|
const scheduler_local_plugin_js_1 = require("../plugins/builtin/scheduler-local-plugin.js");
|
|
19
19
|
const scheduler_weixin_plugin_js_1 = require("../plugins/builtin/scheduler-weixin-plugin.js");
|
|
20
|
+
const monitor_stock_plugin_js_1 = require("../plugins/builtin/monitor-stock-plugin.js");
|
|
20
21
|
const workspace_router_js_1 = require("../router/workspace-router.js");
|
|
21
22
|
const local_core_runtime_state_js_1 = require("../runtime/local-core-runtime-state.js");
|
|
22
23
|
const scheduled_job_application_service_js_1 = require("../scheduler/scheduled-job-application-service.js");
|
|
23
24
|
const scheduler_service_js_1 = require("../scheduler/scheduler-service.js");
|
|
25
|
+
const automation_monitor_service_js_1 = require("../automation/automation-monitor-service.js");
|
|
24
26
|
function bootstrapLocalCoreKernel(options) {
|
|
25
27
|
const capabilities = new capability_registry_js_1.LocalCoreCapabilityRegistry();
|
|
26
28
|
const plugins = new plugin_registry_js_1.LocalCorePluginRegistry(options?.disabledPluginIds);
|
|
@@ -59,6 +61,7 @@ function bootstrapLocalCoreKernel(options) {
|
|
|
59
61
|
diagnostics,
|
|
60
62
|
getCapabilitySnapshot() {
|
|
61
63
|
const snapshot = capabilities.snapshot();
|
|
64
|
+
const monitorCapabilities = snapshot.monitors || [];
|
|
62
65
|
return {
|
|
63
66
|
adapters: {
|
|
64
67
|
channels: snapshot.channels.map((capability) => capability.platform),
|
|
@@ -74,6 +77,14 @@ function bootstrapLocalCoreKernel(options) {
|
|
|
74
77
|
deliveryTargets: [...new Set(snapshot.schedulers.flatMap((capability) => capability.deliveryTargets || capability.deliveryPlatforms || []))],
|
|
75
78
|
platforms: [...new Set(snapshot.schedulers.flatMap((capability) => capability.deliveryTargets || capability.deliveryPlatforms || []))],
|
|
76
79
|
},
|
|
80
|
+
...(monitorCapabilities.length > 0
|
|
81
|
+
? {
|
|
82
|
+
monitors: {
|
|
83
|
+
enabled: monitorCapabilities.some((capability) => capability.enabled !== false),
|
|
84
|
+
sourceTypes: [...new Set(monitorCapabilities.flatMap((capability) => capability.sourceTypes))],
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
: {}),
|
|
77
88
|
snapshot,
|
|
78
89
|
};
|
|
79
90
|
},
|
|
@@ -99,6 +110,7 @@ function logCapabilityContributions(plugin, log) {
|
|
|
99
110
|
...(plugin.capabilities.channels || []).map((capability) => capability.id),
|
|
100
111
|
...(plugin.capabilities.knowledge || []).map((capability) => capability.id),
|
|
101
112
|
...(plugin.capabilities.schedulers || []).map((capability) => capability.id),
|
|
113
|
+
...(plugin.capabilities.monitors || []).map((capability) => capability.id),
|
|
102
114
|
...(plugin.capabilities.ui || []).map((capability) => capability.id),
|
|
103
115
|
];
|
|
104
116
|
for (const capabilityId of capabilityIds) {
|
|
@@ -145,6 +157,16 @@ function resolveSchedulerRuntime(plugin, context) {
|
|
|
145
157
|
}
|
|
146
158
|
return runtime;
|
|
147
159
|
}
|
|
160
|
+
function resolveMonitorRuntime(plugin, context) {
|
|
161
|
+
if (!plugin.createRuntime) {
|
|
162
|
+
throw new Error(`Monitor plugin ${plugin.manifest.id} does not provide a runtime factory.`);
|
|
163
|
+
}
|
|
164
|
+
const runtime = plugin.createRuntime(context);
|
|
165
|
+
if (runtime instanceof Promise) {
|
|
166
|
+
throw new Error(`Monitor plugin ${plugin.manifest.id} returned an async runtime factory during synchronous bootstrap.`);
|
|
167
|
+
}
|
|
168
|
+
return runtime;
|
|
169
|
+
}
|
|
148
170
|
function bootstrapLocalCoreRuntime(options) {
|
|
149
171
|
const state = (0, local_core_runtime_state_js_1.createLocalCoreRuntimeState)({
|
|
150
172
|
userDataPath: options.userDataPath,
|
|
@@ -209,6 +231,9 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
209
231
|
log: options.log,
|
|
210
232
|
}),
|
|
211
233
|
];
|
|
234
|
+
const monitorPlugins = [
|
|
235
|
+
(0, monitor_stock_plugin_js_1.createBuiltinStockMonitorPlugin)(),
|
|
236
|
+
];
|
|
212
237
|
for (const plugin of agentPlugins.filter((plugin) => plugin !== localCoreAgentPlugin)) {
|
|
213
238
|
registerPlugin(kernel, plugin);
|
|
214
239
|
}
|
|
@@ -218,6 +243,9 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
218
243
|
for (const plugin of schedulerPlugins) {
|
|
219
244
|
registerPlugin(kernel, plugin);
|
|
220
245
|
}
|
|
246
|
+
for (const plugin of monitorPlugins) {
|
|
247
|
+
registerPlugin(kernel, plugin);
|
|
248
|
+
}
|
|
221
249
|
const agentRuntimes = agentPlugins
|
|
222
250
|
.filter((plugin) => kernel.plugins.isEnabled(plugin.manifest.id))
|
|
223
251
|
.map((plugin) => resolveAgentRuntime(plugin, kernel.context).runtime);
|
|
@@ -241,6 +269,10 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
241
269
|
];
|
|
242
270
|
const schedulerTriggers = schedulerRuntimes.flatMap((runtime) => runtime.triggers || []);
|
|
243
271
|
const schedulerExecutors = schedulerRuntimes.flatMap((runtime) => runtime.executors || []);
|
|
272
|
+
const monitorRuntimes = monitorPlugins
|
|
273
|
+
.filter((plugin) => kernel.plugins.isEnabled(plugin.manifest.id))
|
|
274
|
+
.map((plugin) => resolveMonitorRuntime(plugin, kernel.context));
|
|
275
|
+
const monitorProviders = monitorRuntimes.flatMap((runtime) => runtime.providers || []);
|
|
244
276
|
const knowledgeProvider = knowledgeRuntime.provider;
|
|
245
277
|
const knowledgeAttachments = knowledgeRuntime.attachments;
|
|
246
278
|
workspaceRouter = (0, workspace_router_js_1.createWorkspaceRouter)({
|
|
@@ -266,6 +298,14 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
266
298
|
store,
|
|
267
299
|
scheduler,
|
|
268
300
|
});
|
|
301
|
+
const automationMonitors = new automation_monitor_service_js_1.AutomationMonitorService({
|
|
302
|
+
store,
|
|
303
|
+
providers: monitorProviders,
|
|
304
|
+
getWorkspaceRouter: () => workspaceRouter,
|
|
305
|
+
getChannelRuntime: (platform) => channelRuntimes.find((runtime) => runtime.platform === platform || platform.startsWith(`${runtime.platform}:`)),
|
|
306
|
+
eventBus: kernel.context.bus,
|
|
307
|
+
log: options.log,
|
|
308
|
+
});
|
|
269
309
|
workspaceRouter.setSchedulerBridge({
|
|
270
310
|
createJob: async ({ workspaceId, platform, route, name, schedule, scheduleDescription, message }) => scheduledJobs.createCronJob({ workspaceId, platform, route, name, schedule, scheduleDescription, message }),
|
|
271
311
|
listJobsForThread: async (threadId) => scheduledJobs.listJobsForThread(threadId),
|
|
@@ -286,11 +326,14 @@ function bootstrapLocalCoreRuntime(options) {
|
|
|
286
326
|
workspaceRouter,
|
|
287
327
|
scheduler,
|
|
288
328
|
scheduledJobs,
|
|
329
|
+
automationMonitors,
|
|
289
330
|
async start() {
|
|
290
331
|
await kernel.lifecycle.startAll();
|
|
291
332
|
await scheduler.start();
|
|
333
|
+
await automationMonitors.start();
|
|
292
334
|
},
|
|
293
335
|
async stop() {
|
|
336
|
+
await automationMonitors.stop();
|
|
294
337
|
await scheduler.stop();
|
|
295
338
|
await kernel.lifecycle.stopAll();
|
|
296
339
|
workspaceRouter.close();
|
|
@@ -6,6 +6,7 @@ class LocalCoreCapabilityRegistry {
|
|
|
6
6
|
channels = new Map();
|
|
7
7
|
knowledge = new Map();
|
|
8
8
|
schedulers = new Map();
|
|
9
|
+
monitors = new Map();
|
|
9
10
|
ui = new Map();
|
|
10
11
|
registerAgent(capability) {
|
|
11
12
|
this.agents.set(capability.id, capability);
|
|
@@ -19,6 +20,9 @@ class LocalCoreCapabilityRegistry {
|
|
|
19
20
|
registerScheduler(capability) {
|
|
20
21
|
this.schedulers.set(capability.id, capability);
|
|
21
22
|
}
|
|
23
|
+
registerMonitor(capability) {
|
|
24
|
+
this.monitors.set(capability.id, capability);
|
|
25
|
+
}
|
|
22
26
|
registerUi(capability) {
|
|
23
27
|
this.ui.set(capability.id, capability);
|
|
24
28
|
}
|
|
@@ -35,6 +39,9 @@ class LocalCoreCapabilityRegistry {
|
|
|
35
39
|
for (const capability of contributions.schedulers || []) {
|
|
36
40
|
this.registerScheduler(capability);
|
|
37
41
|
}
|
|
42
|
+
for (const capability of contributions.monitors || []) {
|
|
43
|
+
this.registerMonitor(capability);
|
|
44
|
+
}
|
|
38
45
|
for (const capability of contributions.ui || []) {
|
|
39
46
|
this.registerUi(capability);
|
|
40
47
|
}
|
|
@@ -51,15 +58,20 @@ class LocalCoreCapabilityRegistry {
|
|
|
51
58
|
listSchedulers() {
|
|
52
59
|
return [...this.schedulers.values()];
|
|
53
60
|
}
|
|
61
|
+
listMonitors() {
|
|
62
|
+
return [...this.monitors.values()];
|
|
63
|
+
}
|
|
54
64
|
listUi() {
|
|
55
65
|
return [...this.ui.values()];
|
|
56
66
|
}
|
|
57
67
|
snapshot() {
|
|
68
|
+
const monitors = this.listMonitors();
|
|
58
69
|
return {
|
|
59
70
|
agents: this.listAgents(),
|
|
60
71
|
channels: this.listChannels(),
|
|
61
72
|
knowledge: this.listKnowledge(),
|
|
62
73
|
schedulers: this.listSchedulers(),
|
|
74
|
+
...(monitors.length > 0 ? { monitors } : {}),
|
|
63
75
|
ui: this.listUi(),
|
|
64
76
|
};
|
|
65
77
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBuiltinStockMonitorPlugin = createBuiltinStockMonitorPlugin;
|
|
4
|
+
const mock_stock_provider_js_1 = require("../../automation/mock-stock-provider.js");
|
|
5
|
+
function createBuiltinStockMonitorPlugin() {
|
|
6
|
+
return {
|
|
7
|
+
manifest: {
|
|
8
|
+
id: 'builtin.monitor-stock',
|
|
9
|
+
kind: 'monitor',
|
|
10
|
+
version: '0.1.0',
|
|
11
|
+
provides: ['monitor.source.stock.quote'],
|
|
12
|
+
},
|
|
13
|
+
capabilities: {
|
|
14
|
+
monitors: [
|
|
15
|
+
{
|
|
16
|
+
id: 'monitor.source.stock.quote',
|
|
17
|
+
sourceTypes: ['stock.quote'],
|
|
18
|
+
modes: ['poll'],
|
|
19
|
+
enabled: true,
|
|
20
|
+
displayName: 'Stock Quote Monitor',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
createRuntime() {
|
|
25
|
+
return {
|
|
26
|
+
providers: [new mock_stock_provider_js_1.MockStockQuoteProvider()],
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -48,6 +48,7 @@ class WorkspaceRouter {
|
|
|
48
48
|
return this.schedulerBridge.deleteJob(jobId);
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
|
+
getAgentTypes: () => this.options.getCapabilities().snapshot.agents.map((agent) => agent.agentType),
|
|
51
52
|
log: options.log,
|
|
52
53
|
});
|
|
53
54
|
}
|
|
@@ -203,12 +204,14 @@ class WorkspaceRouter {
|
|
|
203
204
|
}
|
|
204
205
|
async sendThreadMessage(threadId, content, options) {
|
|
205
206
|
const { workspaceId } = (0, workspace_thread_id_js_1.decodeThreadId)(threadId);
|
|
206
|
-
const route =
|
|
207
|
+
const route = isLocalSlashCommand(content)
|
|
208
|
+
? await this.getWorkspaceRoute(workspaceId)
|
|
209
|
+
: await this.getThreadWorkspaceRoute(threadId, workspaceId);
|
|
207
210
|
return this.localCoreAcp.sendThreadMessage(threadId, content, route.config, options);
|
|
208
211
|
}
|
|
209
212
|
async sendThreadAction(threadId, content) {
|
|
210
213
|
const { workspaceId } = (0, workspace_thread_id_js_1.decodeThreadId)(threadId);
|
|
211
|
-
const route = await this.
|
|
214
|
+
const route = await this.getThreadWorkspaceRoute(threadId, workspaceId);
|
|
212
215
|
return this.localCoreAcp.sendThreadAction(threadId, content, route.config);
|
|
213
216
|
}
|
|
214
217
|
async interruptRun(runId) {
|
|
@@ -425,11 +428,21 @@ class WorkspaceRouter {
|
|
|
425
428
|
await this.localCoreAcp.deleteThread(thread.id).catch(() => ({ deleted: false }));
|
|
426
429
|
}
|
|
427
430
|
}
|
|
428
|
-
async
|
|
431
|
+
async getThreadWorkspaceRoute(threadId, workspaceId) {
|
|
432
|
+
const defaultRoute = await this.getWorkspaceRoute(workspaceId);
|
|
433
|
+
const row = this.store.getThreadRow(threadId);
|
|
434
|
+
const threadAgentType = String(row?.agent_type || '').trim().toLowerCase();
|
|
435
|
+
if (!threadAgentType || threadAgentType === defaultRoute.agentType) {
|
|
436
|
+
return defaultRoute;
|
|
437
|
+
}
|
|
438
|
+
return this.getWorkspaceRoute(workspaceId, threadAgentType);
|
|
439
|
+
}
|
|
440
|
+
async getWorkspaceRoute(workspaceId, agentTypeOverride = '') {
|
|
429
441
|
const configState = await this.options.readConfigState();
|
|
430
442
|
const projects = Array.isArray(configState.parsed?.projects) ? configState.parsed.projects : [];
|
|
431
443
|
const matched = projects.find((project) => String(project?.name || '').trim() === workspaceId);
|
|
432
|
-
const
|
|
444
|
+
const project = matched && agentTypeOverride ? withAgentTypeOverride(matched, agentTypeOverride) : matched;
|
|
445
|
+
const route = project ? this.resolveProjectRoute(configState, project) : null;
|
|
433
446
|
if (!matched || !route) {
|
|
434
447
|
throw new Error(`Workspace "${workspaceId}" is not configured as a Local AI Core ACP workspace.`);
|
|
435
448
|
}
|
|
@@ -512,6 +525,29 @@ function inferWorkspacePath(project) {
|
|
|
512
525
|
}
|
|
513
526
|
return '';
|
|
514
527
|
}
|
|
528
|
+
function withAgentTypeOverride(project, agentType) {
|
|
529
|
+
const options = project.agent?.options && typeof project.agent.options === 'object'
|
|
530
|
+
? { ...project.agent.options }
|
|
531
|
+
: {};
|
|
532
|
+
delete options.command;
|
|
533
|
+
delete options.args;
|
|
534
|
+
return {
|
|
535
|
+
...project,
|
|
536
|
+
agent: {
|
|
537
|
+
...(project.agent || {}),
|
|
538
|
+
type: agentType,
|
|
539
|
+
options,
|
|
540
|
+
},
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function isLocalSlashCommand(content) {
|
|
544
|
+
const text = typeof content === 'string' ? content : String(content.displayText || '');
|
|
545
|
+
const normalized = text.trim().toLowerCase();
|
|
546
|
+
return normalized === '/agent'
|
|
547
|
+
|| normalized.startsWith('/agent ')
|
|
548
|
+
|| normalized === '/mode'
|
|
549
|
+
|| normalized.startsWith('/mode ');
|
|
550
|
+
}
|
|
515
551
|
function workspaceHealth(path) {
|
|
516
552
|
if (!path) {
|
|
517
553
|
return {
|
|
@@ -12,6 +12,7 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
12
12
|
knowledgeProvider;
|
|
13
13
|
channelRuntimes;
|
|
14
14
|
scheduledJobs;
|
|
15
|
+
automationMonitors;
|
|
15
16
|
kernel;
|
|
16
17
|
runtime;
|
|
17
18
|
runtimeDetection;
|
|
@@ -33,6 +34,15 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
33
34
|
const runtimeChannels = this.runtime.channelRuntimes || [this.runtime.channelRuntime, this.runtime.weixinChannelRuntime];
|
|
34
35
|
this.channelRuntimes = new Map(runtimeChannels.filter(Boolean).map((runtime) => [runtime.platform, runtime]));
|
|
35
36
|
this.scheduledJobs = this.runtime.scheduledJobs;
|
|
37
|
+
this.automationMonitors = this.runtime.automationMonitors || {
|
|
38
|
+
listMonitors: () => [],
|
|
39
|
+
getMonitor: () => undefined,
|
|
40
|
+
createMonitor: () => { throw new Error('Automation monitor service is not available.'); },
|
|
41
|
+
updateMonitor: () => { throw new Error('Automation monitor service is not available.'); },
|
|
42
|
+
deleteMonitor: () => ({ deleted: false }),
|
|
43
|
+
runMonitorNow: async () => { throw new Error('Automation monitor service is not available.'); },
|
|
44
|
+
listRuns: () => [],
|
|
45
|
+
};
|
|
36
46
|
this.runtimeDetection = new runtime_detection_service_js_1.RuntimeDetectionService({
|
|
37
47
|
userDataPath,
|
|
38
48
|
readConfig: async () => (await this.readConfigFile()).parsed,
|
|
@@ -42,10 +52,16 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
42
52
|
this.flushPendingLogs();
|
|
43
53
|
this.busUnsubscribers.push(this.kernel.context.bus.on('platform.bridge.updated', (event) => {
|
|
44
54
|
this.emit('bridge', event);
|
|
55
|
+
}), this.kernel.context.bus.on('thread.session.activated', (event) => {
|
|
56
|
+
this.emit('thread-session-activated', event);
|
|
45
57
|
}), this.kernel.context.bus.on('scheduler.job.updated', (job) => {
|
|
46
58
|
this.emit('scheduler-job', job);
|
|
47
59
|
}), this.kernel.context.bus.on('scheduler.run.updated', (run) => {
|
|
48
60
|
this.emit('scheduler-run', run);
|
|
61
|
+
}), this.kernel.context.bus.on('automation.monitor.updated', (monitor) => {
|
|
62
|
+
this.emit('automation-monitor', monitor);
|
|
63
|
+
}), this.kernel.context.bus.on('automation.monitor.run.updated', (run) => {
|
|
64
|
+
this.emit('automation-monitor-run', run);
|
|
49
65
|
}), this.kernel.context.bus.on('runtime.state.changed', () => {
|
|
50
66
|
void this.emitRuntime();
|
|
51
67
|
}));
|
|
@@ -208,6 +224,31 @@ class LocalCoreController extends node_events_1.EventEmitter {
|
|
|
208
224
|
async listScheduledJobRuns(jobId) {
|
|
209
225
|
return this.scheduledJobs.listJobRuns(jobId);
|
|
210
226
|
}
|
|
227
|
+
async listAutomationMonitors(workspaceId) {
|
|
228
|
+
return this.automationMonitors.listMonitors(workspaceId);
|
|
229
|
+
}
|
|
230
|
+
async getAutomationMonitor(monitorId) {
|
|
231
|
+
const monitor = this.automationMonitors.getMonitor(monitorId);
|
|
232
|
+
if (!monitor) {
|
|
233
|
+
throw new Error(`Automation monitor not found: ${monitorId}`);
|
|
234
|
+
}
|
|
235
|
+
return monitor;
|
|
236
|
+
}
|
|
237
|
+
async createAutomationMonitor(input) {
|
|
238
|
+
return this.automationMonitors.createMonitor(input);
|
|
239
|
+
}
|
|
240
|
+
async updateAutomationMonitor(monitorId, input) {
|
|
241
|
+
return this.automationMonitors.updateMonitor(monitorId, input);
|
|
242
|
+
}
|
|
243
|
+
async deleteAutomationMonitor(monitorId) {
|
|
244
|
+
return this.automationMonitors.deleteMonitor(monitorId);
|
|
245
|
+
}
|
|
246
|
+
async runAutomationMonitor(monitorId) {
|
|
247
|
+
return this.automationMonitors.runMonitorNow(monitorId);
|
|
248
|
+
}
|
|
249
|
+
async listAutomationMonitorRuns(monitorId) {
|
|
250
|
+
return this.automationMonitors.listRuns(monitorId);
|
|
251
|
+
}
|
|
211
252
|
async listThreads(workspaceId) {
|
|
212
253
|
return this.workspaceRouter.listThreads(workspaceId);
|
|
213
254
|
}
|
|
@@ -48,6 +48,9 @@ function parseLocalAiCoreRoute(method, path) {
|
|
|
48
48
|
if (segments[0] === 'scheduler' && segments[1] === 'jobs') {
|
|
49
49
|
return parseSchedulerJobsRoute(normalizedMethod, segments);
|
|
50
50
|
}
|
|
51
|
+
if (segments[0] === 'automation' && segments[1] === 'monitors') {
|
|
52
|
+
return parseAutomationMonitorsRoute(normalizedMethod, segments);
|
|
53
|
+
}
|
|
51
54
|
if (segments[0] === 'threads') {
|
|
52
55
|
return parseThreadsRoute(normalizedMethod, segments);
|
|
53
56
|
}
|
|
@@ -92,6 +95,34 @@ function parseLocalAiCoreRoute(method, path) {
|
|
|
92
95
|
}
|
|
93
96
|
return null;
|
|
94
97
|
}
|
|
98
|
+
function parseAutomationMonitorsRoute(method, segments) {
|
|
99
|
+
if (method === 'GET' && segments.length === 2) {
|
|
100
|
+
return { name: 'automation.monitors.list' };
|
|
101
|
+
}
|
|
102
|
+
if (method === 'POST' && segments.length === 2) {
|
|
103
|
+
return { name: 'automation.monitors.create' };
|
|
104
|
+
}
|
|
105
|
+
const monitorId = segments.length >= 3 ? decodeURIComponent(segments[2] || '') : '';
|
|
106
|
+
if (!monitorId) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
if (method === 'GET' && segments.length === 3) {
|
|
110
|
+
return { name: 'automation.monitor.get', monitorId };
|
|
111
|
+
}
|
|
112
|
+
if (method === 'GET' && segments.length === 4 && segments[3] === 'runs') {
|
|
113
|
+
return { name: 'automation.monitor.runs', monitorId };
|
|
114
|
+
}
|
|
115
|
+
if (method === 'POST' && segments.length === 4 && segments[3] === 'run') {
|
|
116
|
+
return { name: 'automation.monitor.run', monitorId };
|
|
117
|
+
}
|
|
118
|
+
if (method === 'PATCH' && segments.length === 3) {
|
|
119
|
+
return { name: 'automation.monitor.update', monitorId };
|
|
120
|
+
}
|
|
121
|
+
if (method === 'DELETE' && segments.length === 3) {
|
|
122
|
+
return { name: 'automation.monitor.delete', monitorId };
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
95
126
|
function parseRuntimesRoute(method, segments) {
|
|
96
127
|
if (method === 'GET' && segments.length === 1) {
|
|
97
128
|
return { name: 'runtimes.list' };
|
|
@@ -62,12 +62,21 @@ class LocalAiCoreServer {
|
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
|
+
this.bindings.on('thread-session-activated', (event) => {
|
|
66
|
+
this.broadcast({ type: 'thread.session.activated', ...event });
|
|
67
|
+
});
|
|
65
68
|
this.bindings.on('scheduler-job', (job) => {
|
|
66
69
|
this.broadcast({ type: 'scheduler.job.updated', job });
|
|
67
70
|
});
|
|
68
71
|
this.bindings.on('scheduler-run', (run) => {
|
|
69
72
|
this.broadcast({ type: 'scheduler.run.updated', run });
|
|
70
73
|
});
|
|
74
|
+
this.bindings.on('automation-monitor', (monitor) => {
|
|
75
|
+
this.broadcast({ type: 'automation.monitor.updated', monitor });
|
|
76
|
+
});
|
|
77
|
+
this.bindings.on('automation-monitor-run', (run) => {
|
|
78
|
+
this.broadcast({ type: 'automation.monitor.run.updated', run });
|
|
79
|
+
});
|
|
71
80
|
this.bindings.on('runtime-detection', (event) => {
|
|
72
81
|
this.broadcast(event);
|
|
73
82
|
});
|
|
@@ -226,6 +235,33 @@ class LocalAiCoreServer {
|
|
|
226
235
|
case 'scheduler.job.delete':
|
|
227
236
|
json(res, 200, await this.bindings.deleteScheduledJob(route.jobId));
|
|
228
237
|
return;
|
|
238
|
+
case 'automation.monitors.list': {
|
|
239
|
+
const workspaceId = String(url.searchParams.get('workspace_id') || '');
|
|
240
|
+
json(res, 200, { monitors: await this.bindings.listAutomationMonitors(workspaceId || undefined) });
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
case 'automation.monitors.create': {
|
|
244
|
+
const body = await readJsonBody(req);
|
|
245
|
+
json(res, 200, await this.bindings.createAutomationMonitor(body));
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
case 'automation.monitor.get':
|
|
249
|
+
json(res, 200, await this.bindings.getAutomationMonitor(route.monitorId));
|
|
250
|
+
return;
|
|
251
|
+
case 'automation.monitor.runs':
|
|
252
|
+
json(res, 200, { runs: await this.bindings.listAutomationMonitorRuns(route.monitorId) });
|
|
253
|
+
return;
|
|
254
|
+
case 'automation.monitor.run':
|
|
255
|
+
json(res, 200, await this.bindings.runAutomationMonitor(route.monitorId));
|
|
256
|
+
return;
|
|
257
|
+
case 'automation.monitor.update': {
|
|
258
|
+
const body = await readJsonBody(req);
|
|
259
|
+
json(res, 200, await this.bindings.updateAutomationMonitor(route.monitorId, body));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
case 'automation.monitor.delete':
|
|
263
|
+
json(res, 200, await this.bindings.deleteAutomationMonitor(route.monitorId));
|
|
264
|
+
return;
|
|
229
265
|
case 'threads.list': {
|
|
230
266
|
const workspaceId = String(url.searchParams.get('workspace_id') || '');
|
|
231
267
|
json(res, 200, { threads: workspaceId ? await this.bindings.listThreads(workspaceId) : [] });
|
|
@@ -5,19 +5,20 @@ class ScheduledBridgeSession {
|
|
|
5
5
|
static async open(input) {
|
|
6
6
|
const sessionKey = input.workspaceRouter.getThreadSessionKey(input.threadId);
|
|
7
7
|
const channelRuntime = input.getChannelRuntime();
|
|
8
|
+
const target = input.target || targetFromScheduledJob(input.job);
|
|
8
9
|
const unregister = await channelRuntime.registerScheduledThreadBridge?.({
|
|
9
|
-
workspaceId:
|
|
10
|
-
platform:
|
|
11
|
-
route:
|
|
10
|
+
workspaceId: target.workspaceId,
|
|
11
|
+
platform: target.platform,
|
|
12
|
+
route: target.route,
|
|
12
13
|
threadId: input.threadId,
|
|
13
14
|
sessionKey,
|
|
14
15
|
});
|
|
15
|
-
await sendScheduledStartNotice(channelRuntime, input.
|
|
16
|
+
await sendScheduledStartNotice(channelRuntime, target, sessionKey, input.noticeIcon, input.noticeTitle);
|
|
16
17
|
return {
|
|
17
18
|
mode: 'bridge-stream',
|
|
18
|
-
workspaceId:
|
|
19
|
-
platform:
|
|
20
|
-
route:
|
|
19
|
+
workspaceId: target.workspaceId,
|
|
20
|
+
platform: target.platform,
|
|
21
|
+
route: target.route,
|
|
21
22
|
threadId: input.threadId,
|
|
22
23
|
sessionKey,
|
|
23
24
|
close: async () => {
|
|
@@ -27,7 +28,20 @@ class ScheduledBridgeSession {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
exports.ScheduledBridgeSession = ScheduledBridgeSession;
|
|
30
|
-
|
|
31
|
+
function targetFromScheduledJob(job) {
|
|
32
|
+
if (!job) {
|
|
33
|
+
throw new Error('Scheduled bridge session requires a job or automation target.');
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
id: job.id,
|
|
37
|
+
workspaceId: job.workspaceId,
|
|
38
|
+
platform: job.platform,
|
|
39
|
+
route: job.route,
|
|
40
|
+
title: job.description || job.promptTemplate || job.id,
|
|
41
|
+
promptTemplate: job.promptTemplate,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function sendScheduledStartNotice(channelRuntime, target, sessionKey, noticeIcon, noticeTitle) {
|
|
31
45
|
if (!channelRuntime.onBridgeEvent) {
|
|
32
46
|
return;
|
|
33
47
|
}
|
|
@@ -36,15 +50,15 @@ async function sendScheduledStartNotice(channelRuntime, job, sessionKey) {
|
|
|
36
50
|
type: 'status',
|
|
37
51
|
sessionKey,
|
|
38
52
|
bridgeKind: 'status',
|
|
39
|
-
content:
|
|
53
|
+
content: `${noticeIcon || '⏰'} ${noticeTitle || automationNoticeTitle(target)}`,
|
|
40
54
|
});
|
|
41
55
|
}
|
|
42
56
|
catch {
|
|
43
57
|
// The scheduled run should continue even if the proactive start notice fails.
|
|
44
58
|
}
|
|
45
59
|
}
|
|
46
|
-
function
|
|
47
|
-
const title = normalizeNoticeTitle(
|
|
60
|
+
function automationNoticeTitle(target) {
|
|
61
|
+
const title = normalizeNoticeTitle(target.title) || normalizeNoticeTitle(target.promptTemplate) || target.id;
|
|
48
62
|
return truncateNoticeTitle(title, 80);
|
|
49
63
|
}
|
|
50
64
|
function normalizeNoticeTitle(value) {
|