@kafca/agentdock 0.1.42 → 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 +4 -0
- package/dist/renderer/assets/{Badge-D-WU4kUV.js → Badge-CbG6yRSm.js} +1 -1
- package/dist/renderer/assets/{Chat-BGkC5tAe.js → Chat-BvNNWGGX.js} +1 -1
- package/dist/renderer/assets/{ChatMarkdown-CfbC1jRd.js → ChatMarkdown-Ct-PvJB8.js} +1 -1
- package/dist/renderer/assets/{Config-qQb4bX5D.js → Config-lQX2qVVV.js} +2 -2
- package/dist/renderer/assets/CronList-Dj_3muVG.js +1 -0
- package/dist/renderer/assets/{Dashboard-xn6cUy_n.js → Dashboard-eh_RhGYb.js} +2 -2
- package/dist/renderer/assets/{EmptyState-BdKBBUpr.js → EmptyState-Bn2Qh14U.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-Duk8IQP3.js → KnowledgeDetail-Bsz6Ou41.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-BfjX_4Sv.js → KnowledgeHome-Cgj4XFXn.js} +2 -2
- package/dist/renderer/assets/{Logs-Bfq61QMn.js → Logs-Dp-NF6GN.js} +1 -1
- package/dist/renderer/assets/{Modal-B3vlBmBr.js → Modal-B6YPPBN6.js} +1 -1
- package/dist/renderer/assets/MonitorList-xEZWg460.js +1 -0
- package/dist/renderer/assets/{Page-CPsLOP3z.js → Page-Bn7RjGOS.js} +1 -1
- package/dist/renderer/assets/{ProjectDetail-D-g46wyF.js → ProjectDetail-Cv_jIE61.js} +2 -2
- package/dist/renderer/assets/{ProjectList-BrQEKDQ8.js → ProjectList-BDk5_gqY.js} +1 -1
- package/dist/renderer/assets/{Select-C4CFMQmF.js → Select-xshfMIEQ.js} +1 -1
- package/dist/renderer/assets/SessionChat-BkHy90z3.js +1 -0
- package/dist/renderer/assets/{SessionList-DPWIUbOg.js → SessionList-BZyXT92L.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-BjtU-j9q.js → ThreadChat-DUOIyXrS.js} +7 -7
- package/dist/renderer/assets/{Workspace-BcNmHuJx.js → Workspace-Dl80fNEC.js} +1 -1
- package/dist/renderer/assets/{arrow-left-DPzSmidS.js → arrow-left-C54ZI-AS.js} +1 -1
- package/dist/renderer/assets/{book-open-B0xhoRqZ.js → book-open-Dl7GO0zn.js} +1 -1
- package/dist/renderer/assets/{check-BTJTyd0C.js → check-CiqgtrOL.js} +1 -1
- package/dist/renderer/assets/{chevron-down-B6jJXlhi.js → chevron-down-DTL2OuVh.js} +1 -1
- package/dist/renderer/assets/{circle-qRhJR9qR.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-CbYKGTn8.js → funnel-CrmnLMJI.js} +1 -1
- package/dist/renderer/assets/{heart-DjwWJfkz.js → heart-BMfQI7y_.js} +1 -1
- package/dist/renderer/assets/{index-BWmHJRhe.js → index-HPNb1zfx.js} +39 -34
- package/dist/renderer/assets/{index-CyZs_2NJ.js → index-nreiKY1f.js} +3 -3
- package/dist/renderer/assets/{pencil-1dfAivmj.js → pencil-wTQ4l465.js} +1 -1
- package/dist/renderer/assets/{play-CB3w1G6S.js → play-BK--MXmw.js} +1 -1
- package/dist/renderer/assets/{plug-Bvep5o3r.js → plug-BIx9fjip.js} +1 -1
- package/dist/renderer/assets/{plus-DJVg9m09.js → plus-Dn7JFWQ8.js} +1 -1
- package/dist/renderer/assets/projects-brJZgwEJ.js +1 -0
- package/dist/renderer/assets/{save-xjJn3qf2.js → save-CC3zOSWb.js} +1 -1
- package/dist/renderer/assets/{search-BK3UrQxM.js → search-CDTy9Czu.js} +1 -1
- package/dist/renderer/assets/{server-Dyd2eXJu.js → server-DtQk3t2a.js} +1 -1
- package/dist/renderer/assets/{session-utils-eXC0020s.js → session-utils-4ep5D66T.js} +1 -1
- package/dist/renderer/assets/{sessions-WLYpkyUt.js → sessions-Dor1LteH.js} +1 -1
- package/dist/renderer/assets/{shield-check-C0N6aWzF.js → shield-check-Cz2LpU6r.js} +1 -1
- package/dist/renderer/assets/{trash-2-BGMTNJA6.js → trash-2-C2EmWFZV.js} +1 -1
- package/dist/renderer/assets/{user-BcGMLyhu.js → user-I8B-cs5A.js} +1 -1
- package/dist/renderer/assets/{wifi-off-FhcQx0HK.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 +51 -0
- package/dist-electron/services/local-ai-core/src/acp/local-core-acp-store.js +4 -1364
- 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/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 +15 -15
- 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/integration/local-core-refactor.test.js +194 -0
- package/package.json +1 -1
- package/dist/renderer/assets/CronList-CKhggzYk.js +0 -1
- package/dist/renderer/assets/SessionChat-06Jny5_G.js +0 -1
- package/dist/renderer/assets/desktop-DXmXjjUR.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-xnW0fTtq.js +0 -1
- package/dist/renderer/assets/zh-Dz5FLTBV.js +0 -1
|
@@ -8,6 +8,8 @@ const node_process_1 = __importDefault(require("node:process"));
|
|
|
8
8
|
const index_js_1 = require("../../../../packages/contracts/src/index.js");
|
|
9
9
|
const job_id_js_1 = require("../scheduler/job-id.js");
|
|
10
10
|
const scheduled_job_route_js_1 = require("../scheduler/scheduled-job-route.js");
|
|
11
|
+
const monitor_id_js_1 = require("../automation/monitor-id.js");
|
|
12
|
+
const monitor_cli_parsers_js_1 = require("./monitor-cli-parsers.js");
|
|
11
13
|
const DEFAULT_BASE_URL = 'http://127.0.0.1:9831/api/local/v1';
|
|
12
14
|
async function runCli(argv, env = node_process_1.default.env, io = node_process_1.default) {
|
|
13
15
|
try {
|
|
@@ -23,6 +25,26 @@ async function runCli(argv, env = node_process_1.default.env, io = node_process_
|
|
|
23
25
|
return 2;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
28
|
+
if (domain === 'monitor') {
|
|
29
|
+
switch (action) {
|
|
30
|
+
case 'add':
|
|
31
|
+
return await handleMonitorAdd(flags, env, io, json);
|
|
32
|
+
case 'list':
|
|
33
|
+
return await handleMonitorList(flags, env, io, json);
|
|
34
|
+
case 'info':
|
|
35
|
+
return await handleMonitorInfo(maybeId, flags, env, io, json);
|
|
36
|
+
case 'edit':
|
|
37
|
+
return await handleMonitorEdit(maybeId, flags, env, io, json);
|
|
38
|
+
case 'del':
|
|
39
|
+
case 'delete':
|
|
40
|
+
return await handleMonitorDelete(maybeId, flags, env, io, json);
|
|
41
|
+
case 'run':
|
|
42
|
+
return await handleMonitorRun(maybeId, flags, env, io, json);
|
|
43
|
+
default:
|
|
44
|
+
printUsage(io.stderr);
|
|
45
|
+
return 2;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
26
48
|
if (domain !== 'scheduler') {
|
|
27
49
|
printUsage(io.stderr);
|
|
28
50
|
return 2;
|
|
@@ -51,6 +73,110 @@ async function runCli(argv, env = node_process_1.default.env, io = node_process_
|
|
|
51
73
|
return 1;
|
|
52
74
|
}
|
|
53
75
|
}
|
|
76
|
+
async function handleMonitorAdd(flags, env, io, json) {
|
|
77
|
+
const context = resolveContext(flags, env);
|
|
78
|
+
if (!context.workspaceId) {
|
|
79
|
+
throw new Error('monitor add requires a workspace context. Set LOCAL_AI_WORKSPACE_ID or pass --workspace.');
|
|
80
|
+
}
|
|
81
|
+
const title = getRequiredFlag(flags, 'title');
|
|
82
|
+
const sourceType = getRequiredFlag(flags, 'source');
|
|
83
|
+
const promptTemplate = getRequiredFlag(flags, 'message');
|
|
84
|
+
const condition = (0, monitor_cli_parsers_js_1.parseMonitorCondition)(getRequiredFlag(flags, 'condition'));
|
|
85
|
+
const sourceConfig = buildSourceConfig(sourceType, flags);
|
|
86
|
+
const monitor = await request(context.baseUrl, 'POST', '/automation/monitors', {
|
|
87
|
+
workspaceId: context.workspaceId,
|
|
88
|
+
...(context.threadId ? { threadId: context.threadId } : {}),
|
|
89
|
+
title,
|
|
90
|
+
sourceType,
|
|
91
|
+
sourceConfig,
|
|
92
|
+
condition,
|
|
93
|
+
promptTemplate,
|
|
94
|
+
executionMode: getMonitorExecutionMode(flags),
|
|
95
|
+
cooldownMs: (0, monitor_cli_parsers_js_1.parseDurationMs)(getFlag(flags, 'cooldown') || '15m'),
|
|
96
|
+
enabled: true,
|
|
97
|
+
});
|
|
98
|
+
print(json, io.stdout, presentMonitor(monitor), [
|
|
99
|
+
`Created monitor ${(0, monitor_id_js_1.toPublicAutomationMonitorId)(monitor.id)}`,
|
|
100
|
+
`Title: ${monitor.title}`,
|
|
101
|
+
`Source: ${monitor.sourceType}`,
|
|
102
|
+
`Condition: ${formatCondition(monitor.condition)}`,
|
|
103
|
+
`Execution mode: ${monitor.executionMode}`,
|
|
104
|
+
].join('\n'));
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
async function handleMonitorList(flags, env, io, json) {
|
|
108
|
+
const context = resolveContext(flags, env);
|
|
109
|
+
const workspaceId = getFlag(flags, 'workspace') || context.workspaceId;
|
|
110
|
+
const threadId = flags.has('thread')
|
|
111
|
+
? normalizeMaybeBooleanFlag(getFlag(flags, 'thread')) || context.threadId
|
|
112
|
+
: '';
|
|
113
|
+
const suffix = workspaceId ? `?workspace_id=${encodeURIComponent(workspaceId)}` : '';
|
|
114
|
+
const response = await request(context.baseUrl, 'GET', `/automation/monitors${suffix}`);
|
|
115
|
+
const monitors = threadId
|
|
116
|
+
? response.monitors.filter((monitor) => monitor.route.threadId === threadId || monitorMatchesCliContext(monitor, context))
|
|
117
|
+
: response.monitors;
|
|
118
|
+
print(json, io.stdout, { monitors: monitors.map(presentMonitor) }, monitors.length === 0 ? 'No monitors.' : monitors.map(formatMonitorLine).join('\n'));
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
async function handleMonitorInfo(monitorId, flags, env, io, json) {
|
|
122
|
+
if (!monitorId) {
|
|
123
|
+
throw new Error('monitor info requires a monitor id.');
|
|
124
|
+
}
|
|
125
|
+
const context = resolveContext(flags, env);
|
|
126
|
+
const monitor = await request(context.baseUrl, 'GET', `/automation/monitors/${encodeURIComponent(monitorId)}`);
|
|
127
|
+
const runs = await request(context.baseUrl, 'GET', `/automation/monitors/${encodeURIComponent(monitorId)}/runs`);
|
|
128
|
+
print(json, io.stdout, { monitor: presentMonitor(monitor), runs: runs.runs }, formatMonitorDetails(monitor, runs.runs[0]));
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
async function handleMonitorEdit(monitorId, flags, env, io, json) {
|
|
132
|
+
if (!monitorId) {
|
|
133
|
+
throw new Error('monitor edit requires a monitor id.');
|
|
134
|
+
}
|
|
135
|
+
const input = {};
|
|
136
|
+
const title = getFlag(flags, 'title');
|
|
137
|
+
const promptTemplate = getFlag(flags, 'message');
|
|
138
|
+
const condition = getFlag(flags, 'condition');
|
|
139
|
+
const enabled = getOptionalBooleanFlag(flags, 'enabled');
|
|
140
|
+
const executionMode = getFlag(flags, 'execution-mode');
|
|
141
|
+
const cooldown = getFlag(flags, 'cooldown');
|
|
142
|
+
if (title)
|
|
143
|
+
input.title = title;
|
|
144
|
+
if (typeof promptTemplate === 'string' && promptTemplate)
|
|
145
|
+
input.promptTemplate = promptTemplate;
|
|
146
|
+
if (condition)
|
|
147
|
+
input.condition = (0, monitor_cli_parsers_js_1.parseMonitorCondition)(condition);
|
|
148
|
+
if (typeof enabled === 'boolean')
|
|
149
|
+
input.enabled = enabled;
|
|
150
|
+
if (executionMode)
|
|
151
|
+
input.executionMode = (0, index_js_1.normalizeScheduledJobExecutionMode)(executionMode);
|
|
152
|
+
if (cooldown)
|
|
153
|
+
input.cooldownMs = (0, monitor_cli_parsers_js_1.parseDurationMs)(cooldown);
|
|
154
|
+
if (Object.keys(input).length === 0) {
|
|
155
|
+
throw new Error('monitor edit requires at least one editable field.');
|
|
156
|
+
}
|
|
157
|
+
const context = resolveContext(flags, env);
|
|
158
|
+
const monitor = await request(context.baseUrl, 'PATCH', `/automation/monitors/${encodeURIComponent(monitorId)}`, input);
|
|
159
|
+
print(json, io.stdout, presentMonitor(monitor), `Updated monitor ${(0, monitor_id_js_1.toPublicAutomationMonitorId)(monitor.id)}`);
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
162
|
+
async function handleMonitorDelete(monitorId, flags, env, io, json) {
|
|
163
|
+
if (!monitorId) {
|
|
164
|
+
throw new Error('monitor del requires a monitor id.');
|
|
165
|
+
}
|
|
166
|
+
const context = resolveContext(flags, env);
|
|
167
|
+
const result = await request(context.baseUrl, 'DELETE', `/automation/monitors/${encodeURIComponent(monitorId)}`);
|
|
168
|
+
print(json, io.stdout, result, `Deleted monitor ${monitorId}`);
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
async function handleMonitorRun(monitorId, flags, env, io, json) {
|
|
172
|
+
if (!monitorId) {
|
|
173
|
+
throw new Error('monitor run requires a monitor id.');
|
|
174
|
+
}
|
|
175
|
+
const context = resolveContext(flags, env);
|
|
176
|
+
const run = await request(context.baseUrl, 'POST', `/automation/monitors/${encodeURIComponent(monitorId)}/run`);
|
|
177
|
+
print(json, io.stdout, run, `Triggered monitor ${monitorId}: ${run.status}`);
|
|
178
|
+
return 0;
|
|
179
|
+
}
|
|
54
180
|
async function handleChannelSendFile(flags, env, io, json) {
|
|
55
181
|
const context = resolveContext(flags, env);
|
|
56
182
|
const filePath = getRequiredFlag(flags, 'path');
|
|
@@ -282,6 +408,23 @@ function normalizeMaybeBooleanFlag(value) {
|
|
|
282
408
|
function getExecutionMode(flags) {
|
|
283
409
|
return (0, index_js_1.normalizeScheduledJobExecutionMode)(getFlag(flags, 'execution-mode'));
|
|
284
410
|
}
|
|
411
|
+
function getMonitorExecutionMode(flags) {
|
|
412
|
+
return (0, index_js_1.normalizeScheduledJobExecutionMode)(getFlag(flags, 'execution-mode') || 'side-thread');
|
|
413
|
+
}
|
|
414
|
+
function buildSourceConfig(sourceType, flags) {
|
|
415
|
+
const config = {};
|
|
416
|
+
if (sourceType === 'stock.quote') {
|
|
417
|
+
config.symbol = getRequiredFlag(flags, 'symbol').toUpperCase();
|
|
418
|
+
const price = getFlag(flags, 'price');
|
|
419
|
+
if (price)
|
|
420
|
+
config.price = Number(price);
|
|
421
|
+
}
|
|
422
|
+
const rawConfig = getFlag(flags, 'source-config');
|
|
423
|
+
if (rawConfig) {
|
|
424
|
+
return { ...config, ...JSON.parse(rawConfig) };
|
|
425
|
+
}
|
|
426
|
+
return config;
|
|
427
|
+
}
|
|
285
428
|
function print(asJson, output, payload, text) {
|
|
286
429
|
output.write(asJson ? `${JSON.stringify(payload, null, 2)}\n` : `${text}\n`);
|
|
287
430
|
}
|
|
@@ -294,6 +437,12 @@ function printUsage(output) {
|
|
|
294
437
|
' lac scheduler edit <job-id> [--cron "<expr>"] [--message "<text>"] [--desc "<label>"] [--enabled true|false] [--execution-mode same-thread|side-thread] [--json]',
|
|
295
438
|
' lac scheduler del <job-id> [--json]',
|
|
296
439
|
' lac scheduler run <job-id> [--json]',
|
|
440
|
+
' lac monitor add --title "<title>" --source stock.quote --symbol <symbol> --condition "change_percent >= 3" --message "<text>" [--cooldown 15m] [--execution-mode same-thread|side-thread] [--json]',
|
|
441
|
+
' lac monitor list [--workspace <id>] [--thread [<id>]] [--json]',
|
|
442
|
+
' lac monitor info <monitor-id> [--json]',
|
|
443
|
+
' lac monitor edit <monitor-id> [--title "<title>"] [--condition "<expr>"] [--message "<text>"] [--enabled true|false] [--cooldown 15m] [--execution-mode same-thread|side-thread] [--json]',
|
|
444
|
+
' lac monitor del <monitor-id> [--json]',
|
|
445
|
+
' lac monitor run <monitor-id> [--json]',
|
|
297
446
|
' lac channel send-file --path "<file>" [--target <chat-or-user-id>] [--workspace <id>] [--workspace-path <path>] [--platform lark] [--name <filename>] [--json]',
|
|
298
447
|
].join('\n') + '\n');
|
|
299
448
|
}
|
|
@@ -321,6 +470,53 @@ function presentJob(job) {
|
|
|
321
470
|
id: (0, job_id_js_1.toPublicScheduledJobId)(job.id),
|
|
322
471
|
};
|
|
323
472
|
}
|
|
473
|
+
function formatMonitorLine(monitor) {
|
|
474
|
+
return `${(0, monitor_id_js_1.toPublicAutomationMonitorId)(monitor.id)} | ${monitor.enabled ? 'enabled' : 'disabled'} | ${monitor.executionMode} | ${monitor.sourceType} | ${formatCondition(monitor.condition)} | ${monitor.title}`;
|
|
475
|
+
}
|
|
476
|
+
function formatMonitorDetails(monitor, latestRun) {
|
|
477
|
+
return [
|
|
478
|
+
`Monitor: ${(0, monitor_id_js_1.toPublicAutomationMonitorId)(monitor.id)}`,
|
|
479
|
+
`Title: ${monitor.title}`,
|
|
480
|
+
`Workspace: ${monitor.workspaceId}`,
|
|
481
|
+
`Platform: ${monitor.platform}`,
|
|
482
|
+
`Thread: ${monitor.route.threadId || ''}`,
|
|
483
|
+
`Execution mode: ${monitor.executionMode}`,
|
|
484
|
+
`Source: ${monitor.sourceType}`,
|
|
485
|
+
`Condition: ${formatCondition(monitor.condition)}`,
|
|
486
|
+
`Cooldown: ${monitor.cooldownMs}ms`,
|
|
487
|
+
`Enabled: ${monitor.enabled ? 'true' : 'false'}`,
|
|
488
|
+
`Message: ${monitor.promptTemplate}`,
|
|
489
|
+
latestRun ? `Latest run: ${latestRun.status} @ ${latestRun.triggeredAt}` : 'Latest run: none',
|
|
490
|
+
].join('\n');
|
|
491
|
+
}
|
|
492
|
+
function formatCondition(condition) {
|
|
493
|
+
if (condition.expression) {
|
|
494
|
+
return condition.expression;
|
|
495
|
+
}
|
|
496
|
+
return `${condition.metric} ${condition.operator} ${condition.value}`;
|
|
497
|
+
}
|
|
498
|
+
function presentMonitor(monitor) {
|
|
499
|
+
return {
|
|
500
|
+
...monitor,
|
|
501
|
+
id: (0, monitor_id_js_1.toPublicAutomationMonitorId)(monitor.id),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
function monitorMatchesCliContext(monitor, context) {
|
|
505
|
+
return (0, scheduled_job_route_js_1.scheduledJobMatchesCliContext)({
|
|
506
|
+
id: monitor.id,
|
|
507
|
+
workspaceId: monitor.workspaceId,
|
|
508
|
+
platform: monitor.platform,
|
|
509
|
+
route: monitor.route,
|
|
510
|
+
executionMode: monitor.executionMode,
|
|
511
|
+
triggerType: 'once',
|
|
512
|
+
promptTemplate: monitor.promptTemplate,
|
|
513
|
+
description: monitor.title,
|
|
514
|
+
enabled: monitor.enabled,
|
|
515
|
+
concurrencyPolicy: monitor.concurrencyPolicy,
|
|
516
|
+
createdAt: monitor.createdAt,
|
|
517
|
+
updatedAt: monitor.updatedAt,
|
|
518
|
+
}, context);
|
|
519
|
+
}
|
|
324
520
|
function formatError(error) {
|
|
325
521
|
return error instanceof Error ? error.message : String(error);
|
|
326
522
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMonitorCondition = parseMonitorCondition;
|
|
4
|
+
exports.parseDurationMs = parseDurationMs;
|
|
5
|
+
const index_js_1 = require("../../../../packages/contracts/src/index.js");
|
|
6
|
+
function parseMonitorCondition(value) {
|
|
7
|
+
const expression = String(value || '').trim();
|
|
8
|
+
if (expression.includes('&&') || expression.includes('||')) {
|
|
9
|
+
return {
|
|
10
|
+
metric: 'expression',
|
|
11
|
+
operator: '==',
|
|
12
|
+
value: true,
|
|
13
|
+
expression,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const match = expression.match(/^([a-zA-Z0-9_.-]+)\s*(>=|<=|==|!=|>|<)\s*(.+)$/);
|
|
17
|
+
if (!match) {
|
|
18
|
+
throw new Error('Monitor condition must look like "change_percent >= 3".');
|
|
19
|
+
}
|
|
20
|
+
const rawValue = String(match[3] || '').trim();
|
|
21
|
+
const numeric = Number(rawValue);
|
|
22
|
+
return {
|
|
23
|
+
metric: String(match[1] || '').trim(),
|
|
24
|
+
operator: (0, index_js_1.normalizeAutomationMonitorConditionOperator)(match[2]),
|
|
25
|
+
value: Number.isFinite(numeric) && rawValue !== '' ? numeric : rawValue,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function parseDurationMs(value) {
|
|
29
|
+
const match = String(value || '').trim().match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/i);
|
|
30
|
+
if (!match) {
|
|
31
|
+
throw new Error('Duration must be a number with optional ms, s, m, or h suffix.');
|
|
32
|
+
}
|
|
33
|
+
const amount = Number(match[1]);
|
|
34
|
+
const unit = String(match[2] || 'ms').toLowerCase();
|
|
35
|
+
const multiplier = unit === 'h' ? 60 * 60 * 1000 : unit === 'm' ? 60 * 1000 : unit === 's' ? 1000 : 1;
|
|
36
|
+
return Math.round(amount * multiplier);
|
|
37
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -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) : [] });
|