@kafca/agentdock 0.1.61 → 0.1.63
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 +18 -0
- package/dist/renderer/assets/AutomationList-DR-micIT.js +16 -0
- package/dist/renderer/assets/{Badge-BLI4LHse.js → Badge-COE1Zm2i.js} +1 -1
- package/dist/renderer/assets/{Card-DJeLDdL3.js → Card-F6UNFxnQ.js} +1 -1
- package/dist/renderer/assets/{Config-D1awc81A.js → Config-BKqxfhZi.js} +2 -2
- package/dist/renderer/assets/Dashboard-Bvp7-_2z.js +36 -0
- package/dist/renderer/assets/{EmptyState-CkI1RwPX.js → EmptyState-BwV_J0Og.js} +1 -1
- package/dist/renderer/assets/{HighlightedMarkdown-BUhDlhgW.js → HighlightedMarkdown-CBIBaWyM.js} +1 -1
- package/dist/renderer/assets/{Input-DHYrn-Ne.js → Input-C8LZd4Bi.js} +1 -1
- package/dist/renderer/assets/{KnowledgeDetail-Bij-Xo90.js → KnowledgeDetail-DjXYNMIs.js} +2 -2
- package/dist/renderer/assets/{KnowledgeHome-DmPZ2IlI.js → KnowledgeHome-Cqk5_nJh.js} +2 -2
- package/dist/renderer/assets/{Logs-ISY99heA.js → Logs-B6cXFvW4.js} +2 -2
- package/dist/renderer/assets/{Modal-DAQfz0ot.js → Modal-CAj7soll.js} +3 -3
- package/dist/renderer/assets/{Page-Dw43UYDT.js → Page-DlnMnu4F.js} +1 -1
- package/dist/renderer/assets/{Select-DzmN5OGQ.js → Select-CVay_LUX.js} +1 -1
- package/dist/renderer/assets/{ThreadChat-B5CWqqMK.js → ThreadChat-BxXRpYa1.js} +3 -3
- package/dist/renderer/assets/{Workspace-C5g9LBj9.js → Workspace-YC0pC7cM.js} +1 -1
- package/dist/renderer/assets/{arrow-left-BLXh56Ip.js → arrow-left-Cwm09dxx.js} +1 -1
- package/dist/renderer/assets/{book-open-DhPGbc-7.js → book-open-BwcGC_im.js} +1 -1
- package/dist/renderer/assets/{channels-DfQrmuYO.js → channels-BPytmVCd.js} +2 -2
- package/dist/renderer/assets/{chevron-down-CEFtpPDc.js → chevron-down-2LP9oGHG.js} +1 -1
- package/dist/renderer/assets/en-Bnr4nMzg.js +1 -0
- package/dist/renderer/assets/es-B1GIFh3i.js +1 -0
- package/dist/renderer/assets/{index-BIKL3fTP.css → index-B6WcpkJF.css} +1 -1
- package/dist/renderer/assets/index-eoVERL5K.js +162 -0
- package/dist/renderer/assets/{index-CYhDUAR_.js → index-llCPCiYk.js} +1 -1
- package/dist/renderer/assets/ja-CDWPWqEW.js +1 -0
- package/dist/renderer/assets/{knowledge-uHRQ80sR.js → knowledge-QujAv-Zh.js} +1 -1
- package/dist/renderer/assets/{pencil-BD2Y31YC.js → pencil-0P2INETc.js} +1 -1
- package/dist/renderer/assets/{plus-DDcldp_c.js → plus-tiGRgE2v.js} +1 -1
- package/dist/renderer/assets/{save-CMW_cZI9.js → save-D8U93DNa.js} +1 -1
- package/dist/renderer/assets/{search-BM-0CvJr.js → search-C-9J9J3f.js} +1 -1
- package/dist/renderer/assets/{shield-check-DaMB0FKG.js → shield-check-BCKkPPTJ.js} +1 -1
- package/dist/renderer/assets/{threads-DZgt9tWj.js → threads-Bsrwwnpm.js} +1 -1
- package/dist/renderer/assets/{trash-2-DTXVbC5y.js → trash-2-CP4sn15n.js} +1 -1
- package/dist/renderer/assets/zh-MSddxMDX.js +1 -0
- package/dist/renderer/assets/zh-TW-C_LNWX0o.js +1 -0
- package/dist/renderer/index.html +2 -2
- package/dist-electron/electron/managed-skills/agent-browser/SKILL.md +41 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/authentication.md +83 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/commands.md +50 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/profiling.md +20 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/proxy-support.md +18 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/session-management.md +17 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/snapshot-refs.md +17 -0
- package/dist-electron/electron/managed-skills/agent-browser/references/video-recording.md +21 -0
- package/dist-electron/electron/managed-skills/agent-browser/templates/authenticated-session.sh +11 -0
- package/dist-electron/electron/managed-skills/agent-browser/templates/capture-workflow.sh +12 -0
- package/dist-electron/electron/managed-skills/agent-browser/templates/form-automation.sh +10 -0
- package/dist-electron/electron/managed-skills/condition-trigger/SKILL.md +21 -0
- package/dist-electron/electron/managed-skills/condition-trigger/scripts/register-condition-trigger.sh +106 -0
- package/dist-electron/electron/managed-skills/knowledge-base/SKILL.md +13 -0
- package/dist-electron/electron/managed-skills/knowledge-base/scripts/search-knowledge.sh +80 -0
- package/dist-electron/packages/contracts/src/automations.js +211 -0
- package/dist-electron/packages/contracts/src/index.js +1 -0
- package/dist-electron/packages/core-sdk/src/automations.js +87 -0
- package/dist-electron/packages/core-sdk/src/client.js +101 -0
- package/dist-electron/packages/core-sdk/src/index.js +2 -1
- package/dist-electron/services/local-ai-core/src/acp/store/automation-script-store.js +415 -0
- package/dist-electron/services/local-ai-core/src/acp/store/automation-store.js +829 -0
- package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +158 -0
- package/dist-electron/services/local-ai-core/src/acp/store/schema.js +81 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-action-executor.js +144 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-condition-engine.js +79 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +39 -73
- package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +695 -260
- package/dist-electron/services/local-ai-core/src/automation/automation-script-service.js +507 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-service.js +1019 -0
- package/dist-electron/services/local-ai-core/src/automation/automation-trigger-engine.js +141 -0
- package/dist-electron/services/local-ai-core/src/automation/condition-evaluator.js +60 -17
- package/dist-electron/services/local-ai-core/src/automation/legacy-automation-mappers.js +286 -0
- package/dist-electron/services/local-ai-core/src/automation/scripts/anthropic-sandbox-runner.js +792 -0
- package/dist-electron/services/local-ai-core/src/automation/scripts/sandbox-runner.js +2 -0
- package/dist-electron/services/local-ai-core/src/automation/scripts/script-package.js +475 -0
- package/dist-electron/services/local-ai-core/src/automation/scripts/script-protocol-runner.js +266 -0
- package/dist-electron/services/local-ai-core/src/automation/scripts/secret-resolver.js +37 -0
- package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +1 -2
- package/dist-electron/services/local-ai-core/src/channel/weixin/transport.js +9 -8
- package/dist-electron/services/local-ai-core/src/cli/lac.js +229 -0
- package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +21 -0
- package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +76 -0
- package/dist-electron/services/local-ai-core/src/runtime/handlers/automations-handler.js +322 -0
- package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +20 -0
- package/dist-electron/services/local-ai-core/src/runtime/managed-skill-catalog.js +37 -0
- package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +14 -4
- package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +75 -0
- package/dist-electron/services/local-ai-core/src/runtime/server.js +21 -0
- package/dist-electron/services/local-ai-core/src/runtime/standalone.js +1 -0
- package/dist-electron/services/local-ai-core/src/scheduler/cron.js +151 -39
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +2 -4
- package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-application-service.js +64 -12
- package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +71 -4
- package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +10 -0
- package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +16 -1
- package/dist-electron/src/pages/Automation/automation-page-model.js +76 -0
- package/dist-electron/tests/contracts/agent-message-policy.test.js +32 -0
- package/dist-electron/tests/contracts/architecture-docs.test.js +30 -0
- package/dist-electron/tests/contracts/automation-contracts.test.js +154 -0
- package/dist-electron/tests/contracts/automation-renderer-model.test.js +47 -0
- package/dist-electron/tests/electron/automation-action-executor.test.js +75 -0
- package/dist-electron/tests/electron/automation-compatibility.test.js +463 -0
- package/dist-electron/tests/electron/automation-deployment.test.js +66 -0
- package/dist-electron/tests/electron/automation-engine.test.js +264 -0
- package/dist-electron/tests/electron/automation-monitor.test.js +1333 -0
- package/dist-electron/tests/electron/automation-sandbox-runner.test.js +344 -0
- package/dist-electron/tests/electron/automation-script-approval.test.js +553 -0
- package/dist-electron/tests/electron/automation-script-package.test.js +499 -0
- package/dist-electron/tests/electron/automation-script-runner.test.js +120 -0
- package/dist-electron/tests/electron/automation-service.test.js +1078 -0
- package/dist-electron/tests/electron/automation-store.test.js +593 -0
- package/dist-electron/tests/electron/condition-trigger-skill.test.js +93 -0
- package/dist-electron/tests/electron/core-client.test.js +99 -0
- package/dist-electron/tests/electron/lac-cli.test.js +110 -0
- package/dist-electron/tests/electron/workspace-task-store.test.js +25 -0
- package/dist-electron/tests/integration/automation-routes.test.js +186 -0
- package/dist-electron/tests/integration/automation-sandbox-runtime.test.js +92 -0
- package/package.json +4 -3
- package/dist/renderer/assets/CronList-CupZoNwW.js +0 -1
- package/dist/renderer/assets/Dashboard-nLZnOtcs.js +0 -41
- package/dist/renderer/assets/MonitorList-BlX82rXF.js +0 -1
- package/dist/renderer/assets/en-CmAr_0e6.js +0 -1
- package/dist/renderer/assets/es-Cs9x52ca.js +0 -1
- package/dist/renderer/assets/index-Dd00oqgY.js +0 -167
- package/dist/renderer/assets/ja-DtvtBRTW.js +0 -1
- package/dist/renderer/assets/play-DBJ8wsSy.js +0 -6
- package/dist/renderer/assets/zh-CcJ9vBZj.js +0 -1
- package/dist/renderer/assets/zh-TW-elI72AC1.js +0 -1
|
@@ -48,6 +48,12 @@ function parseLocalAiCoreRoute(method, path) {
|
|
|
48
48
|
if (segments[0] === 'automation' && segments[1] === 'monitors') {
|
|
49
49
|
return parseAutomationMonitorsRoute(normalizedMethod, segments);
|
|
50
50
|
}
|
|
51
|
+
if (segments[0] === 'automations') {
|
|
52
|
+
return parseAutomationsRoute(normalizedMethod, segments);
|
|
53
|
+
}
|
|
54
|
+
if (segments[0] === 'automation-scripts') {
|
|
55
|
+
return parseAutomationScriptsRoute(normalizedMethod, segments);
|
|
56
|
+
}
|
|
51
57
|
if (segments[0] === 'threads') {
|
|
52
58
|
return parseThreadsRoute(normalizedMethod, segments);
|
|
53
59
|
}
|
|
@@ -104,6 +110,75 @@ function parseLocalAiCoreRoute(method, path) {
|
|
|
104
110
|
}
|
|
105
111
|
return null;
|
|
106
112
|
}
|
|
113
|
+
function parseAutomationsRoute(method, segments) {
|
|
114
|
+
if (segments.length === 1) {
|
|
115
|
+
if (method === 'GET')
|
|
116
|
+
return { name: 'automations.list' };
|
|
117
|
+
if (method === 'POST')
|
|
118
|
+
return { name: 'automations.create' };
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const automationId = decodeURIComponent(segments[1] || '').trim();
|
|
122
|
+
if (!automationId)
|
|
123
|
+
return null;
|
|
124
|
+
if (segments.length === 2) {
|
|
125
|
+
if (method === 'GET')
|
|
126
|
+
return { name: 'automation.get', automationId };
|
|
127
|
+
if (method === 'PATCH')
|
|
128
|
+
return { name: 'automation.update', automationId };
|
|
129
|
+
if (method === 'DELETE')
|
|
130
|
+
return { name: 'automation.delete', automationId };
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
if (segments.length !== 3)
|
|
134
|
+
return null;
|
|
135
|
+
if (method === 'POST' && segments[2] === 'check')
|
|
136
|
+
return { name: 'automation.check', automationId };
|
|
137
|
+
if (method === 'GET' && segments[2] === 'evaluations')
|
|
138
|
+
return { name: 'automation.evaluations', automationId };
|
|
139
|
+
if (method === 'GET' && segments[2] === 'runs')
|
|
140
|
+
return { name: 'automation.runs', automationId };
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
function parseAutomationScriptsRoute(method, segments) {
|
|
144
|
+
if (segments.length === 1) {
|
|
145
|
+
if (method === 'GET')
|
|
146
|
+
return { name: 'automation-scripts.list' };
|
|
147
|
+
if (method === 'POST')
|
|
148
|
+
return { name: 'automation-scripts.create' };
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
if (segments[1] === 'versions') {
|
|
152
|
+
const versionId = decodeURIComponent(segments[2] || '').trim();
|
|
153
|
+
if (!versionId || segments.length !== 4 || method !== 'POST')
|
|
154
|
+
return null;
|
|
155
|
+
switch (segments[3]) {
|
|
156
|
+
case 'test-approval': return { name: 'automation-script-version.test-approval', versionId };
|
|
157
|
+
case 'test': return { name: 'automation-script-version.test', versionId };
|
|
158
|
+
case 'enable-approval': return { name: 'automation-script-version.enable-approval', versionId };
|
|
159
|
+
case 'approve': return { name: 'automation-script-version.approve', versionId };
|
|
160
|
+
case 'reject': return { name: 'automation-script-version.reject', versionId };
|
|
161
|
+
case 'revoke': return { name: 'automation-script-version.revoke', versionId };
|
|
162
|
+
default: return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const scriptId = decodeURIComponent(segments[1] || '').trim();
|
|
166
|
+
if (!scriptId)
|
|
167
|
+
return null;
|
|
168
|
+
if (segments.length === 2) {
|
|
169
|
+
if (method === 'GET')
|
|
170
|
+
return { name: 'automation-script.get', scriptId };
|
|
171
|
+
if (method === 'PATCH')
|
|
172
|
+
return { name: 'automation-script.update', scriptId };
|
|
173
|
+
}
|
|
174
|
+
if (segments.length === 3 && segments[2] === 'versions') {
|
|
175
|
+
if (method === 'GET')
|
|
176
|
+
return { name: 'automation-script.versions', scriptId };
|
|
177
|
+
if (method === 'POST')
|
|
178
|
+
return { name: 'automation-script.version.submit', scriptId };
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
107
182
|
function parseOpenAiRoute(method, segments) {
|
|
108
183
|
if (method === 'POST' && segments.length === 3 && segments[1] === 'chat' && segments[2] === 'completions') {
|
|
109
184
|
return { name: 'openai.chat.completions' };
|
|
@@ -12,6 +12,7 @@ const security_handler_js_1 = require("./handlers/security-handler.js");
|
|
|
12
12
|
const task_handler_js_1 = require("./handlers/task-handler.js");
|
|
13
13
|
const scheduler_handler_js_1 = require("./handlers/scheduler-handler.js");
|
|
14
14
|
const automation_handler_js_1 = require("./handlers/automation-handler.js");
|
|
15
|
+
const automations_handler_js_1 = require("./handlers/automations-handler.js");
|
|
15
16
|
const knowledge_handler_js_1 = require("./handlers/knowledge-handler.js");
|
|
16
17
|
const capabilities_handler_js_1 = require("./handlers/capabilities-handler.js");
|
|
17
18
|
const provider_handler_js_1 = require("./handlers/provider-handler.js");
|
|
@@ -93,6 +94,14 @@ class LocalAiCoreServer {
|
|
|
93
94
|
(0, task_handler_js_1.registerTaskHandlers)(this.handlers, b.workspaceRouter);
|
|
94
95
|
(0, scheduler_handler_js_1.registerSchedulerHandlers)(this.handlers, b.scheduledJobs);
|
|
95
96
|
(0, automation_handler_js_1.registerAutomationHandlers)(this.handlers, b.automationMonitors);
|
|
97
|
+
if (b.automations) {
|
|
98
|
+
(0, automations_handler_js_1.registerUnifiedAutomationHandlers)(this.handlers, {
|
|
99
|
+
automations: b.automations,
|
|
100
|
+
store: b.store,
|
|
101
|
+
executeScriptTest: (versionId) => b.automations.executeAuthorizedScriptTest(versionId),
|
|
102
|
+
emitScriptVersion: (version) => b.controller.emit('automation-script-version', version),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
96
105
|
(0, knowledge_handler_js_1.registerKnowledgeHandlers)(this.handlers, b.knowledgeProvider);
|
|
97
106
|
(0, capabilities_handler_js_1.registerCapabilitiesHandlers)(this.handlers, b.kernel);
|
|
98
107
|
(0, provider_handler_js_1.registerProviderHandlers)(this.handlers, b.store);
|
|
@@ -153,6 +162,18 @@ class LocalAiCoreServer {
|
|
|
153
162
|
b.controller.on('automation-monitor-run', (run) => {
|
|
154
163
|
this.broadcast({ type: 'automation.monitor.run.updated', run });
|
|
155
164
|
});
|
|
165
|
+
b.controller.on('automation-definition', (automation) => {
|
|
166
|
+
this.broadcast({ type: 'automation.definition.updated', automation });
|
|
167
|
+
});
|
|
168
|
+
b.controller.on('automation-evaluation', (evaluation) => {
|
|
169
|
+
this.broadcast({ type: 'automation.evaluation.updated', evaluation });
|
|
170
|
+
});
|
|
171
|
+
b.controller.on('automation-run', (run) => {
|
|
172
|
+
this.broadcast({ type: 'automation.run.updated', run });
|
|
173
|
+
});
|
|
174
|
+
b.controller.on('automation-script-version', (version) => {
|
|
175
|
+
this.broadcast({ type: 'automation.script-version.updated', version });
|
|
176
|
+
});
|
|
156
177
|
b.controller.on('runtime-detection', (event) => {
|
|
157
178
|
this.broadcast(event);
|
|
158
179
|
});
|
|
@@ -21,6 +21,7 @@ async function main() {
|
|
|
21
21
|
knowledgeProvider: controller.knowledgeProvider,
|
|
22
22
|
scheduledJobs: controller.scheduledJobs,
|
|
23
23
|
automationMonitors: controller.automationMonitors,
|
|
24
|
+
automations: controller.automations,
|
|
24
25
|
store: controller.store,
|
|
25
26
|
runtimeDetection: controller.runtimeDetection,
|
|
26
27
|
kernel: controller.kernel,
|
|
@@ -1,53 +1,165 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compileCronExpression = compileCronExpression;
|
|
4
|
+
exports.cronMatchesFields = cronMatchesFields;
|
|
3
5
|
exports.cronMatchesDate = cronMatchesDate;
|
|
6
|
+
exports.findNextCronMatchUtc = findNextCronMatchUtc;
|
|
7
|
+
exports.findPreviousCronMatchUtc = findPreviousCronMatchUtc;
|
|
4
8
|
exports.floorToMinute = floorToMinute;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
10
|
+
const GREGORIAN_CYCLE_DAYS = 146_097;
|
|
11
|
+
const MIN_DATE_MS = -8_640_000_000_000_000;
|
|
12
|
+
const MAX_DATE_MS = 8_640_000_000_000_000;
|
|
13
|
+
function compileCronExpression(expression) {
|
|
14
|
+
const normalized = String(expression ?? '').trim();
|
|
15
|
+
const fields = normalized ? normalized.split(/\s+/) : [];
|
|
16
|
+
if (fields.length !== 5) {
|
|
17
|
+
throw invalidCron(normalized, 'expected exactly 5 fields');
|
|
13
18
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
expression: normalized,
|
|
21
|
+
minutes: compileField(normalized, 'minute', fields[0], 0, 59),
|
|
22
|
+
hours: compileField(normalized, 'hour', fields[1], 0, 23),
|
|
23
|
+
daysOfMonth: compileField(normalized, 'day-of-month', fields[2], 1, 31),
|
|
24
|
+
months: compileField(normalized, 'month', fields[3], 1, 12),
|
|
25
|
+
daysOfWeek: compileField(normalized, 'day-of-week', fields[4], 0, 6),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function cronMatchesFields(compiled, fields) {
|
|
29
|
+
// Preserve the legacy scheduler's DOM+DOW AND behavior.
|
|
30
|
+
return compiled.minutes.includes(fields.minute)
|
|
31
|
+
&& compiled.hours.includes(fields.hour)
|
|
32
|
+
&& compiled.daysOfMonth.includes(fields.dayOfMonth)
|
|
33
|
+
&& compiled.months.includes(fields.month)
|
|
34
|
+
&& compiled.daysOfWeek.includes(fields.dayOfWeek);
|
|
35
|
+
}
|
|
36
|
+
function cronMatchesDate(cronExpr, date) {
|
|
37
|
+
let compiled;
|
|
38
|
+
try {
|
|
39
|
+
compiled = compileCronExpression(cronExpr);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return cronMatchesFields(compiled, {
|
|
45
|
+
minute: date.getMinutes(),
|
|
46
|
+
hour: date.getHours(),
|
|
47
|
+
dayOfMonth: date.getDate(),
|
|
48
|
+
month: date.getMonth() + 1,
|
|
49
|
+
dayOfWeek: date.getDay(),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function findNextCronMatchUtc(compiled, after) {
|
|
53
|
+
const afterMs = validDateMs(after, 'cron search date');
|
|
54
|
+
let dayMs = startOfUtcDay(afterMs);
|
|
55
|
+
for (let inspectedDays = 1; inspectedDays <= GREGORIAN_CYCLE_DAYS + 1; inspectedDays += 1) {
|
|
56
|
+
if (dayMs > MAX_DATE_MS)
|
|
57
|
+
return { date: null, inspectedDays };
|
|
58
|
+
const day = new Date(dayMs);
|
|
59
|
+
if (cronMatchesUtcDay(compiled, day)) {
|
|
60
|
+
for (const hour of compiled.hours) {
|
|
61
|
+
for (const minute of compiled.minutes) {
|
|
62
|
+
const candidateMs = dayMs + hour * 60 * 60 * 1000 + minute * 60 * 1000;
|
|
63
|
+
if (candidateMs > afterMs && candidateMs <= MAX_DATE_MS) {
|
|
64
|
+
return { date: new Date(candidateMs), inspectedDays };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
31
67
|
}
|
|
32
68
|
}
|
|
69
|
+
dayMs += DAY_MS;
|
|
33
70
|
}
|
|
34
|
-
return
|
|
71
|
+
return { date: null, inspectedDays: GREGORIAN_CYCLE_DAYS + 1 };
|
|
35
72
|
}
|
|
36
|
-
function
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
73
|
+
function findPreviousCronMatchUtc(compiled, atOrBefore, afterExclusive) {
|
|
74
|
+
const atOrBeforeMs = validDateMs(atOrBefore, 'cron search date');
|
|
75
|
+
const afterExclusiveMs = afterExclusive
|
|
76
|
+
? validDateMs(afterExclusive, 'cron search lower bound')
|
|
77
|
+
: undefined;
|
|
78
|
+
if (afterExclusiveMs !== undefined && afterExclusiveMs >= atOrBeforeMs) {
|
|
79
|
+
return { date: null, inspectedDays: 0 };
|
|
40
80
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
81
|
+
const lowerBoundDayMs = afterExclusiveMs === undefined ? undefined : startOfUtcDay(afterExclusiveMs);
|
|
82
|
+
let dayMs = startOfUtcDay(atOrBeforeMs);
|
|
83
|
+
for (let inspectedDays = 1; inspectedDays <= GREGORIAN_CYCLE_DAYS + 1; inspectedDays += 1) {
|
|
84
|
+
if (dayMs < MIN_DATE_MS)
|
|
85
|
+
return { date: null, inspectedDays };
|
|
86
|
+
if (lowerBoundDayMs !== undefined && dayMs < lowerBoundDayMs) {
|
|
87
|
+
return { date: null, inspectedDays: inspectedDays - 1 };
|
|
88
|
+
}
|
|
89
|
+
const day = new Date(dayMs);
|
|
90
|
+
if (cronMatchesUtcDay(compiled, day)) {
|
|
91
|
+
for (let hourIndex = compiled.hours.length - 1; hourIndex >= 0; hourIndex -= 1) {
|
|
92
|
+
for (let minuteIndex = compiled.minutes.length - 1; minuteIndex >= 0; minuteIndex -= 1) {
|
|
93
|
+
const candidateMs = dayMs
|
|
94
|
+
+ compiled.hours[hourIndex] * 60 * 60 * 1000
|
|
95
|
+
+ compiled.minutes[minuteIndex] * 60 * 1000;
|
|
96
|
+
if (candidateMs <= atOrBeforeMs
|
|
97
|
+
&& candidateMs >= MIN_DATE_MS
|
|
98
|
+
&& (afterExclusiveMs === undefined || candidateMs > afterExclusiveMs)) {
|
|
99
|
+
return { date: new Date(candidateMs), inspectedDays };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (dayMs === lowerBoundDayMs)
|
|
105
|
+
return { date: null, inspectedDays };
|
|
106
|
+
dayMs -= DAY_MS;
|
|
107
|
+
}
|
|
108
|
+
return { date: null, inspectedDays: GREGORIAN_CYCLE_DAYS + 1 };
|
|
50
109
|
}
|
|
51
110
|
function floorToMinute(date) {
|
|
52
111
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), 0, 0);
|
|
53
112
|
}
|
|
113
|
+
function compileField(expression, fieldName, field, min, max) {
|
|
114
|
+
if (!field)
|
|
115
|
+
throw invalidCron(expression, `${fieldName} field is empty`);
|
|
116
|
+
const values = new Set();
|
|
117
|
+
const tokens = field.split(',');
|
|
118
|
+
if (tokens.some((token) => token === '')) {
|
|
119
|
+
throw invalidCron(expression, `${fieldName} contains an empty list item`);
|
|
120
|
+
}
|
|
121
|
+
for (const token of tokens) {
|
|
122
|
+
const match = /^(\*|\d+|\d+-\d+)(?:\/(\d+))?$/.exec(token);
|
|
123
|
+
if (!match)
|
|
124
|
+
throw invalidCron(expression, `${fieldName} contains invalid token "${token}"`);
|
|
125
|
+
const step = match[2] === undefined ? 1 : Number(match[2]);
|
|
126
|
+
if (!Number.isSafeInteger(step) || step <= 0) {
|
|
127
|
+
throw invalidCron(expression, `${fieldName} step must be a positive integer`);
|
|
128
|
+
}
|
|
129
|
+
const range = match[1];
|
|
130
|
+
let start = min;
|
|
131
|
+
let end = max;
|
|
132
|
+
if (range !== '*') {
|
|
133
|
+
const rangeParts = range.split('-');
|
|
134
|
+
start = Number(rangeParts[0]);
|
|
135
|
+
end = Number(rangeParts[1] ?? rangeParts[0]);
|
|
136
|
+
if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < min || end > max) {
|
|
137
|
+
throw invalidCron(expression, `${fieldName} values must be between ${min} and ${max}`);
|
|
138
|
+
}
|
|
139
|
+
if (start > end)
|
|
140
|
+
throw invalidCron(expression, `${fieldName} range start must not exceed its end`);
|
|
141
|
+
}
|
|
142
|
+
for (let value = start; value <= end; value += step)
|
|
143
|
+
values.add(value);
|
|
144
|
+
}
|
|
145
|
+
return Object.freeze([...values].sort((left, right) => left - right));
|
|
146
|
+
}
|
|
147
|
+
function cronMatchesUtcDay(compiled, day) {
|
|
148
|
+
return compiled.daysOfMonth.includes(day.getUTCDate())
|
|
149
|
+
&& compiled.months.includes(day.getUTCMonth() + 1)
|
|
150
|
+
&& compiled.daysOfWeek.includes(day.getUTCDay());
|
|
151
|
+
}
|
|
152
|
+
function startOfUtcDay(value) {
|
|
153
|
+
const date = new Date(value);
|
|
154
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
155
|
+
return date.getTime();
|
|
156
|
+
}
|
|
157
|
+
function validDateMs(date, label) {
|
|
158
|
+
const value = date.getTime();
|
|
159
|
+
if (!Number.isFinite(value))
|
|
160
|
+
throw new Error(`Invalid ${label}.`);
|
|
161
|
+
return value;
|
|
162
|
+
}
|
|
163
|
+
function invalidCron(expression, reason) {
|
|
164
|
+
return new Error(`Invalid cron expression "${expression}": ${reason}.`);
|
|
165
|
+
}
|
package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ScheduledConversationExecutor = void 0;
|
|
4
4
|
const scheduled_job_route_js_1 = require("./scheduled-job-route.js");
|
|
5
5
|
const run_polling_js_1 = require("./run-polling.js");
|
|
6
|
+
const thread_resolution_js_1 = require("./thread-resolution.js");
|
|
6
7
|
const SCHEDULED_RUN_PERMISSION_MODE = 'bypassPermissions';
|
|
7
8
|
class ScheduledConversationExecutor {
|
|
8
9
|
options;
|
|
@@ -20,10 +21,7 @@ class ScheduledConversationExecutor {
|
|
|
20
21
|
});
|
|
21
22
|
await (0, run_polling_js_1.waitForRunCompletion)(this.options.store, sendResult.runId, timeoutMs, 'Scheduled');
|
|
22
23
|
const thread = await workspaceRouter.getThread(target.threadId);
|
|
23
|
-
const replyText =
|
|
24
|
-
.reverse()
|
|
25
|
-
.find((message) => message.role === 'assistant' && message.kind === 'final')
|
|
26
|
-
?.content;
|
|
24
|
+
const replyText = (0, thread_resolution_js_1.getLatestAssistantFinalContent)(thread);
|
|
27
25
|
return {
|
|
28
26
|
threadId: target.threadId,
|
|
29
27
|
runId: sendResult.runId,
|
package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-application-service.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ScheduledJobApplicationService = void 0;
|
|
4
|
+
const legacy_automation_mappers_js_1 = require("../automation/legacy-automation-mappers.js");
|
|
5
|
+
const job_id_js_1 = require("./job-id.js");
|
|
4
6
|
const scheduled_job_route_js_1 = require("./scheduled-job-route.js");
|
|
5
7
|
class ScheduledJobApplicationService {
|
|
6
8
|
options;
|
|
@@ -8,16 +10,22 @@ class ScheduledJobApplicationService {
|
|
|
8
10
|
this.options = options;
|
|
9
11
|
}
|
|
10
12
|
listJobs(workspaceId) {
|
|
11
|
-
return this.options.
|
|
13
|
+
return this.options.automations.list(workspaceId)
|
|
14
|
+
.filter((automation) => automation.originKind === 'scheduled-job')
|
|
15
|
+
.map((automation) => (0, legacy_automation_mappers_js_1.automationToScheduledJob)(automation, (0, legacy_automation_mappers_js_1.latestAutomationRun)(this.options.automations.listRuns(automation.id))));
|
|
12
16
|
}
|
|
13
17
|
getJob(jobId) {
|
|
14
|
-
|
|
18
|
+
const resolved = this.resolveJobId(jobId);
|
|
19
|
+
const automation = resolved ? this.options.automations.get(resolved) : undefined;
|
|
20
|
+
return automation?.originKind === 'scheduled-job'
|
|
21
|
+
? (0, legacy_automation_mappers_js_1.automationToScheduledJob)(automation, (0, legacy_automation_mappers_js_1.latestAutomationRun)(this.options.automations.listRuns(automation.id)))
|
|
22
|
+
: undefined;
|
|
15
23
|
}
|
|
16
24
|
createJob(input) {
|
|
17
|
-
return this.options.
|
|
25
|
+
return (0, legacy_automation_mappers_js_1.automationToScheduledJob)(this.options.automations.createFromLegacy((0, legacy_automation_mappers_js_1.scheduledJobToAutomationInput)(this.resolveCreateInput(input))));
|
|
18
26
|
}
|
|
19
27
|
createCronJob(input) {
|
|
20
|
-
return this.
|
|
28
|
+
return this.createJob({
|
|
21
29
|
workspaceId: input.workspaceId,
|
|
22
30
|
platform: input.platform,
|
|
23
31
|
route: this.resolveExplicitRoute(input.platform, input.route),
|
|
@@ -29,23 +37,45 @@ class ScheduledJobApplicationService {
|
|
|
29
37
|
});
|
|
30
38
|
}
|
|
31
39
|
updateJob(jobId, input) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
this.options.automations.assertLegacyFacadesAvailable();
|
|
41
|
+
const existing = this.getRequiredJob(jobId);
|
|
42
|
+
const resolved = this.resolveRequiredJobId(jobId);
|
|
43
|
+
const merged = this.resolveCreateInput({
|
|
44
|
+
workspaceId: existing.workspaceId,
|
|
45
|
+
platform: existing.platform,
|
|
46
|
+
route: input.route ? (0, scheduled_job_route_js_1.withoutThreadRoute)(input.route) : existing.route,
|
|
47
|
+
executionMode: input.executionMode ?? existing.executionMode,
|
|
48
|
+
triggerType: input.triggerType ?? existing.triggerType,
|
|
49
|
+
cronExpr: input.cronExpr ?? existing.cronExpr,
|
|
50
|
+
runAt: input.runAt ?? existing.runAt,
|
|
51
|
+
promptTemplate: input.promptTemplate ?? existing.promptTemplate,
|
|
52
|
+
description: input.description ?? existing.description,
|
|
53
|
+
enabled: input.enabled ?? existing.enabled,
|
|
35
54
|
});
|
|
55
|
+
const mapped = (0, legacy_automation_mappers_js_1.scheduledJobToAutomationInput)(merged);
|
|
56
|
+
const { workspaceId: _workspaceId, originKind: _originKind, ...update } = mapped;
|
|
57
|
+
return (0, legacy_automation_mappers_js_1.automationToScheduledJob)(this.options.automations.updateFromLegacy(resolved, update));
|
|
36
58
|
}
|
|
37
59
|
deleteJob(jobId) {
|
|
38
|
-
|
|
60
|
+
this.options.automations.assertLegacyFacadesAvailable();
|
|
61
|
+
return this.options.automations.delete(this.resolveRequiredJobId(jobId));
|
|
39
62
|
}
|
|
40
|
-
runJobNow(jobId) {
|
|
41
|
-
|
|
63
|
+
async runJobNow(jobId) {
|
|
64
|
+
this.options.automations.assertLegacyFacadesAvailable();
|
|
65
|
+
const resolved = this.resolveRequiredJobId(jobId);
|
|
66
|
+
const evaluation = await this.options.automations.checkNow(resolved);
|
|
67
|
+
const run = this.options.automations.listRuns(resolved).find((candidate) => candidate.evaluationId === evaluation.id);
|
|
68
|
+
return (0, legacy_automation_mappers_js_1.automationToScheduledJobRun)(evaluation, run);
|
|
42
69
|
}
|
|
43
70
|
listJobRuns(jobId) {
|
|
44
|
-
|
|
71
|
+
const resolved = this.resolveRequiredJobId(jobId);
|
|
72
|
+
const runs = this.options.automations.listRuns(resolved);
|
|
73
|
+
const runsByEvaluationId = new Map(runs.map((run) => [run.evaluationId, run]));
|
|
74
|
+
return this.options.automations.listEvaluations(resolved).map((evaluation) => (0, legacy_automation_mappers_js_1.automationToScheduledJobRun)(evaluation, runsByEvaluationId.get(evaluation.id)));
|
|
45
75
|
}
|
|
46
76
|
listJobsForThread(threadId) {
|
|
47
77
|
const binding = this.options.store.getPlatformThreadBindingByThreadId(threadId);
|
|
48
|
-
return this
|
|
78
|
+
return this
|
|
49
79
|
.listJobs()
|
|
50
80
|
.filter((job) => job.route.threadId === threadId ||
|
|
51
81
|
(binding ? (0, scheduled_job_route_js_1.scheduledJobMatchesPlatformBinding)(job, binding) : false));
|
|
@@ -80,5 +110,27 @@ class ScheduledJobApplicationService {
|
|
|
80
110
|
resolveExplicitRoute(platform, route) {
|
|
81
111
|
return (0, scheduled_job_route_js_1.routeWithPlatformInstance)((0, scheduled_job_route_js_1.withoutThreadRoute)(route), platform);
|
|
82
112
|
}
|
|
113
|
+
resolveJobId(jobId) {
|
|
114
|
+
const direct = this.options.automations.get(jobId);
|
|
115
|
+
if (direct?.originKind === 'scheduled-job')
|
|
116
|
+
return direct.id;
|
|
117
|
+
const matches = this.options.automations.list()
|
|
118
|
+
.filter((automation) => automation.originKind === 'scheduled-job' && (0, job_id_js_1.toPublicScheduledJobId)(automation.id) === jobId);
|
|
119
|
+
if (matches.length > 1)
|
|
120
|
+
throw new Error(`Scheduled job id is ambiguous: ${jobId}`);
|
|
121
|
+
return matches[0]?.id || '';
|
|
122
|
+
}
|
|
123
|
+
resolveRequiredJobId(jobId) {
|
|
124
|
+
const resolved = this.resolveJobId(jobId);
|
|
125
|
+
if (!resolved)
|
|
126
|
+
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
127
|
+
return resolved;
|
|
128
|
+
}
|
|
129
|
+
getRequiredJob(jobId) {
|
|
130
|
+
const job = this.getJob(jobId);
|
|
131
|
+
if (!job)
|
|
132
|
+
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
133
|
+
return job;
|
|
134
|
+
}
|
|
83
135
|
}
|
|
84
136
|
exports.ScheduledJobApplicationService = ScheduledJobApplicationService;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SchedulerService = void 0;
|
|
4
4
|
const node_events_1 = require("node:events");
|
|
5
|
+
const legacy_automation_mappers_js_1 = require("../automation/legacy-automation-mappers.js");
|
|
5
6
|
const job_id_js_1 = require("./job-id.js");
|
|
6
7
|
const scheduler_run_lifecycle_js_1 = require("./scheduler-run-lifecycle.js");
|
|
7
8
|
const SCHEDULER_AUTO_DISABLE_THRESHOLD = 5;
|
|
@@ -29,10 +30,7 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
29
30
|
this.options.eventBus.emit({ type: 'scheduler.run.updated', payload: run });
|
|
30
31
|
}
|
|
31
32
|
async start() {
|
|
32
|
-
|
|
33
|
-
this.timer = setInterval(() => {
|
|
34
|
-
void this.tick();
|
|
35
|
-
}, 1000);
|
|
33
|
+
// Unified AutomationService owns scheduled-job execution after migration.
|
|
36
34
|
}
|
|
37
35
|
async stop() {
|
|
38
36
|
if (this.timer) {
|
|
@@ -41,29 +39,88 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
41
39
|
}
|
|
42
40
|
}
|
|
43
41
|
listJobs(workspaceId) {
|
|
42
|
+
const automations = this.options.automations;
|
|
43
|
+
if (automations) {
|
|
44
|
+
return automations.list(workspaceId)
|
|
45
|
+
.filter((automation) => automation.originKind === 'scheduled-job')
|
|
46
|
+
.map((automation) => (0, legacy_automation_mappers_js_1.automationToScheduledJob)(automation, (0, legacy_automation_mappers_js_1.latestAutomationRun)(automations.listRuns(automation.id))));
|
|
47
|
+
}
|
|
44
48
|
return this.options.store.listScheduledJobs(workspaceId);
|
|
45
49
|
}
|
|
46
50
|
getJob(jobId) {
|
|
51
|
+
if (this.options.automations) {
|
|
52
|
+
const resolved = this.resolveJobId(jobId);
|
|
53
|
+
const automation = resolved ? this.options.automations.get(resolved) : undefined;
|
|
54
|
+
return automation?.originKind === 'scheduled-job'
|
|
55
|
+
? (0, legacy_automation_mappers_js_1.automationToScheduledJob)(automation, (0, legacy_automation_mappers_js_1.latestAutomationRun)(this.options.automations.listRuns(automation.id)))
|
|
56
|
+
: undefined;
|
|
57
|
+
}
|
|
47
58
|
const resolvedJobId = this.resolveJobId(jobId);
|
|
48
59
|
return resolvedJobId ? this.options.store.getScheduledJob(resolvedJobId) : undefined;
|
|
49
60
|
}
|
|
50
61
|
createJob(input) {
|
|
62
|
+
if (this.options.automations) {
|
|
63
|
+
if (!input.platform || !input.route)
|
|
64
|
+
throw new Error('Scheduled job creation requires a resolved platform and route.');
|
|
65
|
+
return (0, legacy_automation_mappers_js_1.automationToScheduledJob)(this.options.automations.createFromLegacy((0, legacy_automation_mappers_js_1.scheduledJobToAutomationInput)({
|
|
66
|
+
...input,
|
|
67
|
+
platform: input.platform,
|
|
68
|
+
route: input.route,
|
|
69
|
+
})));
|
|
70
|
+
}
|
|
51
71
|
const job = this.options.store.createScheduledJob(input);
|
|
52
72
|
this.emitJob(job);
|
|
53
73
|
return job;
|
|
54
74
|
}
|
|
55
75
|
updateJob(jobId, input) {
|
|
76
|
+
if (this.options.automations) {
|
|
77
|
+
this.options.automations.assertLegacyFacadesAvailable();
|
|
78
|
+
const existing = this.getJob(jobId);
|
|
79
|
+
if (!existing)
|
|
80
|
+
throw new Error(`Scheduled job not found: ${jobId}`);
|
|
81
|
+
const mapped = (0, legacy_automation_mappers_js_1.scheduledJobToAutomationInput)({
|
|
82
|
+
workspaceId: existing.workspaceId,
|
|
83
|
+
platform: existing.platform,
|
|
84
|
+
route: input.route ?? existing.route,
|
|
85
|
+
executionMode: input.executionMode ?? existing.executionMode,
|
|
86
|
+
triggerType: input.triggerType ?? existing.triggerType,
|
|
87
|
+
cronExpr: input.cronExpr ?? existing.cronExpr,
|
|
88
|
+
runAt: input.runAt ?? existing.runAt,
|
|
89
|
+
promptTemplate: input.promptTemplate ?? existing.promptTemplate,
|
|
90
|
+
description: input.description ?? existing.description,
|
|
91
|
+
enabled: input.enabled ?? existing.enabled,
|
|
92
|
+
});
|
|
93
|
+
const { workspaceId: _workspaceId, originKind: _originKind, ...update } = mapped;
|
|
94
|
+
return (0, legacy_automation_mappers_js_1.automationToScheduledJob)(this.options.automations.updateFromLegacy(this.resolveRequiredJobId(jobId), update));
|
|
95
|
+
}
|
|
56
96
|
const job = this.options.store.updateScheduledJob(this.resolveRequiredJobId(jobId), input);
|
|
57
97
|
this.emitJob(job);
|
|
58
98
|
return job;
|
|
59
99
|
}
|
|
60
100
|
deleteJob(jobId) {
|
|
101
|
+
if (this.options.automations) {
|
|
102
|
+
this.options.automations.assertLegacyFacadesAvailable();
|
|
103
|
+
return this.options.automations.delete(this.resolveRequiredJobId(jobId));
|
|
104
|
+
}
|
|
61
105
|
return this.options.store.deleteScheduledJob(this.resolveRequiredJobId(jobId));
|
|
62
106
|
}
|
|
63
107
|
listJobRuns(jobId) {
|
|
108
|
+
if (this.options.automations) {
|
|
109
|
+
const resolved = this.resolveRequiredJobId(jobId);
|
|
110
|
+
const runs = this.options.automations.listRuns(resolved);
|
|
111
|
+
const runsByEvaluationId = new Map(runs.map((run) => [run.evaluationId, run]));
|
|
112
|
+
return this.options.automations.listEvaluations(resolved).map((evaluation) => (0, legacy_automation_mappers_js_1.automationToScheduledJobRun)(evaluation, runsByEvaluationId.get(evaluation.id)));
|
|
113
|
+
}
|
|
64
114
|
return this.options.store.listScheduledJobRuns(this.resolveRequiredJobId(jobId));
|
|
65
115
|
}
|
|
66
116
|
async runJobNow(jobId) {
|
|
117
|
+
if (this.options.automations) {
|
|
118
|
+
this.options.automations.assertLegacyFacadesAvailable();
|
|
119
|
+
const resolved = this.resolveRequiredJobId(jobId);
|
|
120
|
+
const evaluation = await this.options.automations.checkNow(resolved);
|
|
121
|
+
const run = this.options.automations.listRuns(resolved).find((candidate) => candidate.evaluationId === evaluation.id);
|
|
122
|
+
return (0, legacy_automation_mappers_js_1.automationToScheduledJobRun)(evaluation, run);
|
|
123
|
+
}
|
|
67
124
|
const resolvedJobId = this.resolveRequiredJobId(jobId);
|
|
68
125
|
const job = this.options.store.getScheduledJob(resolvedJobId);
|
|
69
126
|
if (!job) {
|
|
@@ -72,6 +129,16 @@ class SchedulerService extends node_events_1.EventEmitter {
|
|
|
72
129
|
return this.executeJob(job, new Date().toISOString(), true);
|
|
73
130
|
}
|
|
74
131
|
resolveJobId(jobId) {
|
|
132
|
+
if (this.options.automations) {
|
|
133
|
+
const direct = this.options.automations.get(jobId);
|
|
134
|
+
if (direct?.originKind === 'scheduled-job')
|
|
135
|
+
return direct.id;
|
|
136
|
+
const matches = this.options.automations.list()
|
|
137
|
+
.filter((automation) => automation.originKind === 'scheduled-job' && (0, job_id_js_1.toPublicScheduledJobId)(automation.id) === jobId);
|
|
138
|
+
if (matches.length > 1)
|
|
139
|
+
throw new Error(`Scheduled job id is ambiguous: ${jobId}`);
|
|
140
|
+
return matches[0]?.id || '';
|
|
141
|
+
}
|
|
75
142
|
if (this.options.store.getScheduledJob(jobId)) {
|
|
76
143
|
return jobId;
|
|
77
144
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.threadExists = threadExists;
|
|
4
|
+
exports.getLatestAssistantFinalContent = getLatestAssistantFinalContent;
|
|
4
5
|
async function threadExists(router, threadId) {
|
|
5
6
|
try {
|
|
6
7
|
await router.getThread(threadId);
|
|
@@ -10,3 +11,12 @@ async function threadExists(router, threadId) {
|
|
|
10
11
|
return false;
|
|
11
12
|
}
|
|
12
13
|
}
|
|
14
|
+
function getLatestAssistantFinalContent(thread) {
|
|
15
|
+
for (let i = thread.messages.length - 1; i >= 0; i -= 1) {
|
|
16
|
+
const message = thread.messages[i];
|
|
17
|
+
if (message && message.role === 'assistant' && message.kind === 'final') {
|
|
18
|
+
return message.content;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|