@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.
Files changed (127) hide show
  1. package/README.md +18 -0
  2. package/dist/renderer/assets/AutomationList-DR-micIT.js +16 -0
  3. package/dist/renderer/assets/{Badge-BLI4LHse.js → Badge-COE1Zm2i.js} +1 -1
  4. package/dist/renderer/assets/{Card-DJeLDdL3.js → Card-F6UNFxnQ.js} +1 -1
  5. package/dist/renderer/assets/{Config-D1awc81A.js → Config-BKqxfhZi.js} +2 -2
  6. package/dist/renderer/assets/Dashboard-Bvp7-_2z.js +36 -0
  7. package/dist/renderer/assets/{EmptyState-CkI1RwPX.js → EmptyState-BwV_J0Og.js} +1 -1
  8. package/dist/renderer/assets/{HighlightedMarkdown-BUhDlhgW.js → HighlightedMarkdown-CBIBaWyM.js} +1 -1
  9. package/dist/renderer/assets/{Input-DHYrn-Ne.js → Input-C8LZd4Bi.js} +1 -1
  10. package/dist/renderer/assets/{KnowledgeDetail-Bij-Xo90.js → KnowledgeDetail-DjXYNMIs.js} +2 -2
  11. package/dist/renderer/assets/{KnowledgeHome-DmPZ2IlI.js → KnowledgeHome-Cqk5_nJh.js} +2 -2
  12. package/dist/renderer/assets/{Logs-ISY99heA.js → Logs-B6cXFvW4.js} +2 -2
  13. package/dist/renderer/assets/{Modal-DAQfz0ot.js → Modal-CAj7soll.js} +3 -3
  14. package/dist/renderer/assets/{Page-Dw43UYDT.js → Page-DlnMnu4F.js} +1 -1
  15. package/dist/renderer/assets/{Select-DzmN5OGQ.js → Select-CVay_LUX.js} +1 -1
  16. package/dist/renderer/assets/{ThreadChat-B5CWqqMK.js → ThreadChat-BxXRpYa1.js} +3 -3
  17. package/dist/renderer/assets/{Workspace-C5g9LBj9.js → Workspace-YC0pC7cM.js} +1 -1
  18. package/dist/renderer/assets/{arrow-left-BLXh56Ip.js → arrow-left-Cwm09dxx.js} +1 -1
  19. package/dist/renderer/assets/{book-open-DhPGbc-7.js → book-open-BwcGC_im.js} +1 -1
  20. package/dist/renderer/assets/{channels-DfQrmuYO.js → channels-BPytmVCd.js} +2 -2
  21. package/dist/renderer/assets/{chevron-down-CEFtpPDc.js → chevron-down-2LP9oGHG.js} +1 -1
  22. package/dist/renderer/assets/en-Bnr4nMzg.js +1 -0
  23. package/dist/renderer/assets/es-B1GIFh3i.js +1 -0
  24. package/dist/renderer/assets/{index-BIKL3fTP.css → index-B6WcpkJF.css} +1 -1
  25. package/dist/renderer/assets/index-eoVERL5K.js +162 -0
  26. package/dist/renderer/assets/{index-CYhDUAR_.js → index-llCPCiYk.js} +1 -1
  27. package/dist/renderer/assets/ja-CDWPWqEW.js +1 -0
  28. package/dist/renderer/assets/{knowledge-uHRQ80sR.js → knowledge-QujAv-Zh.js} +1 -1
  29. package/dist/renderer/assets/{pencil-BD2Y31YC.js → pencil-0P2INETc.js} +1 -1
  30. package/dist/renderer/assets/{plus-DDcldp_c.js → plus-tiGRgE2v.js} +1 -1
  31. package/dist/renderer/assets/{save-CMW_cZI9.js → save-D8U93DNa.js} +1 -1
  32. package/dist/renderer/assets/{search-BM-0CvJr.js → search-C-9J9J3f.js} +1 -1
  33. package/dist/renderer/assets/{shield-check-DaMB0FKG.js → shield-check-BCKkPPTJ.js} +1 -1
  34. package/dist/renderer/assets/{threads-DZgt9tWj.js → threads-Bsrwwnpm.js} +1 -1
  35. package/dist/renderer/assets/{trash-2-DTXVbC5y.js → trash-2-CP4sn15n.js} +1 -1
  36. package/dist/renderer/assets/zh-MSddxMDX.js +1 -0
  37. package/dist/renderer/assets/zh-TW-C_LNWX0o.js +1 -0
  38. package/dist/renderer/index.html +2 -2
  39. package/dist-electron/electron/managed-skills/agent-browser/SKILL.md +41 -0
  40. package/dist-electron/electron/managed-skills/agent-browser/references/authentication.md +83 -0
  41. package/dist-electron/electron/managed-skills/agent-browser/references/commands.md +50 -0
  42. package/dist-electron/electron/managed-skills/agent-browser/references/profiling.md +20 -0
  43. package/dist-electron/electron/managed-skills/agent-browser/references/proxy-support.md +18 -0
  44. package/dist-electron/electron/managed-skills/agent-browser/references/session-management.md +17 -0
  45. package/dist-electron/electron/managed-skills/agent-browser/references/snapshot-refs.md +17 -0
  46. package/dist-electron/electron/managed-skills/agent-browser/references/video-recording.md +21 -0
  47. package/dist-electron/electron/managed-skills/agent-browser/templates/authenticated-session.sh +11 -0
  48. package/dist-electron/electron/managed-skills/agent-browser/templates/capture-workflow.sh +12 -0
  49. package/dist-electron/electron/managed-skills/agent-browser/templates/form-automation.sh +10 -0
  50. package/dist-electron/electron/managed-skills/condition-trigger/SKILL.md +21 -0
  51. package/dist-electron/electron/managed-skills/condition-trigger/scripts/register-condition-trigger.sh +106 -0
  52. package/dist-electron/electron/managed-skills/knowledge-base/SKILL.md +13 -0
  53. package/dist-electron/electron/managed-skills/knowledge-base/scripts/search-knowledge.sh +80 -0
  54. package/dist-electron/packages/contracts/src/automations.js +211 -0
  55. package/dist-electron/packages/contracts/src/index.js +1 -0
  56. package/dist-electron/packages/core-sdk/src/automations.js +87 -0
  57. package/dist-electron/packages/core-sdk/src/client.js +101 -0
  58. package/dist-electron/packages/core-sdk/src/index.js +2 -1
  59. package/dist-electron/services/local-ai-core/src/acp/store/automation-script-store.js +415 -0
  60. package/dist-electron/services/local-ai-core/src/acp/store/automation-store.js +829 -0
  61. package/dist-electron/services/local-ai-core/src/acp/store/local-core-acp-store.js +158 -0
  62. package/dist-electron/services/local-ai-core/src/acp/store/schema.js +81 -0
  63. package/dist-electron/services/local-ai-core/src/automation/automation-action-executor.js +144 -0
  64. package/dist-electron/services/local-ai-core/src/automation/automation-condition-engine.js +79 -0
  65. package/dist-electron/services/local-ai-core/src/automation/automation-conversation-executor.js +39 -73
  66. package/dist-electron/services/local-ai-core/src/automation/automation-monitor-service.js +695 -260
  67. package/dist-electron/services/local-ai-core/src/automation/automation-script-service.js +507 -0
  68. package/dist-electron/services/local-ai-core/src/automation/automation-service.js +1019 -0
  69. package/dist-electron/services/local-ai-core/src/automation/automation-trigger-engine.js +141 -0
  70. package/dist-electron/services/local-ai-core/src/automation/condition-evaluator.js +60 -17
  71. package/dist-electron/services/local-ai-core/src/automation/legacy-automation-mappers.js +286 -0
  72. package/dist-electron/services/local-ai-core/src/automation/scripts/anthropic-sandbox-runner.js +792 -0
  73. package/dist-electron/services/local-ai-core/src/automation/scripts/sandbox-runner.js +2 -0
  74. package/dist-electron/services/local-ai-core/src/automation/scripts/script-package.js +475 -0
  75. package/dist-electron/services/local-ai-core/src/automation/scripts/script-protocol-runner.js +266 -0
  76. package/dist-electron/services/local-ai-core/src/automation/scripts/secret-resolver.js +37 -0
  77. package/dist-electron/services/local-ai-core/src/channel/weixin/inbound-poller.js +1 -2
  78. package/dist-electron/services/local-ai-core/src/channel/weixin/transport.js +9 -8
  79. package/dist-electron/services/local-ai-core/src/cli/lac.js +229 -0
  80. package/dist-electron/services/local-ai-core/src/kernel/bootstrap.js +21 -0
  81. package/dist-electron/services/local-ai-core/src/runtime/deployment-diagnostics.js +76 -0
  82. package/dist-electron/services/local-ai-core/src/runtime/handlers/automations-handler.js +322 -0
  83. package/dist-electron/services/local-ai-core/src/runtime/local-core-controller.js +20 -0
  84. package/dist-electron/services/local-ai-core/src/runtime/managed-skill-catalog.js +37 -0
  85. package/dist-electron/services/local-ai-core/src/runtime/server-helpers.js +14 -4
  86. package/dist-electron/services/local-ai-core/src/runtime/server-routes.js +75 -0
  87. package/dist-electron/services/local-ai-core/src/runtime/server.js +21 -0
  88. package/dist-electron/services/local-ai-core/src/runtime/standalone.js +1 -0
  89. package/dist-electron/services/local-ai-core/src/scheduler/cron.js +151 -39
  90. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-conversation-executor.js +2 -4
  91. package/dist-electron/services/local-ai-core/src/scheduler/scheduled-job-application-service.js +64 -12
  92. package/dist-electron/services/local-ai-core/src/scheduler/scheduler-service.js +71 -4
  93. package/dist-electron/services/local-ai-core/src/scheduler/thread-resolution.js +10 -0
  94. package/dist-electron/services/local-ai-core/src/thread/agent-message-policy.js +16 -1
  95. package/dist-electron/src/pages/Automation/automation-page-model.js +76 -0
  96. package/dist-electron/tests/contracts/agent-message-policy.test.js +32 -0
  97. package/dist-electron/tests/contracts/architecture-docs.test.js +30 -0
  98. package/dist-electron/tests/contracts/automation-contracts.test.js +154 -0
  99. package/dist-electron/tests/contracts/automation-renderer-model.test.js +47 -0
  100. package/dist-electron/tests/electron/automation-action-executor.test.js +75 -0
  101. package/dist-electron/tests/electron/automation-compatibility.test.js +463 -0
  102. package/dist-electron/tests/electron/automation-deployment.test.js +66 -0
  103. package/dist-electron/tests/electron/automation-engine.test.js +264 -0
  104. package/dist-electron/tests/electron/automation-monitor.test.js +1333 -0
  105. package/dist-electron/tests/electron/automation-sandbox-runner.test.js +344 -0
  106. package/dist-electron/tests/electron/automation-script-approval.test.js +553 -0
  107. package/dist-electron/tests/electron/automation-script-package.test.js +499 -0
  108. package/dist-electron/tests/electron/automation-script-runner.test.js +120 -0
  109. package/dist-electron/tests/electron/automation-service.test.js +1078 -0
  110. package/dist-electron/tests/electron/automation-store.test.js +593 -0
  111. package/dist-electron/tests/electron/condition-trigger-skill.test.js +93 -0
  112. package/dist-electron/tests/electron/core-client.test.js +99 -0
  113. package/dist-electron/tests/electron/lac-cli.test.js +110 -0
  114. package/dist-electron/tests/electron/workspace-task-store.test.js +25 -0
  115. package/dist-electron/tests/integration/automation-routes.test.js +186 -0
  116. package/dist-electron/tests/integration/automation-sandbox-runtime.test.js +92 -0
  117. package/package.json +4 -3
  118. package/dist/renderer/assets/CronList-CupZoNwW.js +0 -1
  119. package/dist/renderer/assets/Dashboard-nLZnOtcs.js +0 -41
  120. package/dist/renderer/assets/MonitorList-BlX82rXF.js +0 -1
  121. package/dist/renderer/assets/en-CmAr_0e6.js +0 -1
  122. package/dist/renderer/assets/es-Cs9x52ca.js +0 -1
  123. package/dist/renderer/assets/index-Dd00oqgY.js +0 -167
  124. package/dist/renderer/assets/ja-DtvtBRTW.js +0 -1
  125. package/dist/renderer/assets/play-DBJ8wsSy.js +0 -6
  126. package/dist/renderer/assets/zh-CcJ9vBZj.js +0 -1
  127. package/dist/renderer/assets/zh-TW-elI72AC1.js +0 -1
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nextActivationAt = nextActivationAt;
4
+ exports.isActivationDue = isActivationDue;
5
+ exports.missedActivationAt = missedActivationAt;
6
+ const cron_js_1 = require("../scheduler/cron.js");
7
+ const MINUTE_MS = 60_000;
8
+ function nextActivationAt(activation, after) {
9
+ const afterMs = validDateMs(after, 'after');
10
+ const compiledCron = validateActivation(activation);
11
+ switch (activation.kind) {
12
+ case 'provider-event':
13
+ return null;
14
+ case 'once': {
15
+ const runAt = parseIsoTimestamp(activation.runAt, 'once runAt');
16
+ return runAt.getTime() > afterMs ? runAt : null;
17
+ }
18
+ case 'interval': {
19
+ const nextMs = (Math.floor(afterMs / activation.intervalMs) + 1) * activation.intervalMs;
20
+ return validResultDate(nextMs);
21
+ }
22
+ case 'cron': {
23
+ const result = (0, cron_js_1.findNextCronMatchUtc)(requireCompiledCron(compiledCron), after);
24
+ if (result.date)
25
+ return result.date;
26
+ throw new Error(`No UTC cron activation exists for expression: ${activation.expression}`);
27
+ }
28
+ }
29
+ }
30
+ function isActivationDue(activation, now, nextCheckAt) {
31
+ const nowMs = validDateMs(now, 'now');
32
+ const compiledCron = validateActivation(activation);
33
+ if (activation.kind === 'provider-event')
34
+ return false;
35
+ if (nextCheckAt !== undefined) {
36
+ return parseIsoTimestamp(nextCheckAt, 'nextCheckAt').getTime() <= nowMs;
37
+ }
38
+ switch (activation.kind) {
39
+ case 'once':
40
+ return parseIsoTimestamp(activation.runAt, 'once runAt').getTime() <= nowMs;
41
+ case 'interval':
42
+ return nowMs % activation.intervalMs === 0;
43
+ case 'cron':
44
+ return nowMs === floorUtcMinute(nowMs) && (0, cron_js_1.cronMatchesFields)(requireCompiledCron(compiledCron), {
45
+ minute: now.getUTCMinutes(),
46
+ hour: now.getUTCHours(),
47
+ dayOfMonth: now.getUTCDate(),
48
+ month: now.getUTCMonth() + 1,
49
+ dayOfWeek: now.getUTCDay(),
50
+ });
51
+ }
52
+ }
53
+ function missedActivationAt(activation, lastCheckedAt, now) {
54
+ const nowMs = validDateMs(now, 'now');
55
+ const compiledCron = validateActivation(activation);
56
+ if (activation.kind === 'provider-event' || lastCheckedAt === undefined)
57
+ return null;
58
+ const lastCheckedMs = parseIsoTimestamp(lastCheckedAt, 'lastCheckedAt').getTime();
59
+ if (lastCheckedMs >= nowMs)
60
+ return null;
61
+ switch (activation.kind) {
62
+ case 'once': {
63
+ const runAt = parseIsoTimestamp(activation.runAt, 'once runAt');
64
+ return runAt.getTime() > lastCheckedMs && runAt.getTime() <= nowMs ? runAt : null;
65
+ }
66
+ case 'interval': {
67
+ const latestMs = Math.floor(nowMs / activation.intervalMs) * activation.intervalMs;
68
+ return latestMs > lastCheckedMs ? validResultDate(latestMs) : null;
69
+ }
70
+ case 'cron': {
71
+ return (0, cron_js_1.findPreviousCronMatchUtc)(requireCompiledCron(compiledCron), now, new Date(lastCheckedMs)).date;
72
+ }
73
+ }
74
+ }
75
+ function validateActivation(activation) {
76
+ switch (activation.kind) {
77
+ case 'provider-event':
78
+ return undefined;
79
+ case 'once':
80
+ parseIsoTimestamp(activation.runAt, 'once runAt');
81
+ return undefined;
82
+ case 'interval':
83
+ assertInterval(activation.intervalMs);
84
+ return undefined;
85
+ case 'cron':
86
+ assertUtcTimezone(activation.timezone);
87
+ return (0, cron_js_1.compileCronExpression)(activation.expression);
88
+ }
89
+ }
90
+ function assertUtcTimezone(timezone) {
91
+ if (timezone !== 'UTC' && timezone !== 'Etc/UTC') {
92
+ throw new Error(`Automation scheduling currently supports only UTC cron timezones; received: ${timezone}`);
93
+ }
94
+ }
95
+ function assertInterval(intervalMs) {
96
+ if (!Number.isSafeInteger(intervalMs) || intervalMs <= 0) {
97
+ throw new Error('Automation intervalMs must be a positive safe integer.');
98
+ }
99
+ }
100
+ function parseIsoTimestamp(value, label) {
101
+ const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/.exec(value);
102
+ if (!match)
103
+ throw new Error(`Automation ${label} must be a valid ISO timestamp.`);
104
+ const date = new Date(value);
105
+ validDateMs(date, label);
106
+ const [, yearText, monthText, dayText, hourText, minuteText, secondText] = match;
107
+ const year = Number(yearText);
108
+ const month = Number(monthText);
109
+ const day = Number(dayText);
110
+ const calendarDate = new Date(0);
111
+ calendarDate.setUTCFullYear(year, month - 1, day);
112
+ calendarDate.setUTCHours(0, 0, 0, 0);
113
+ if (calendarDate.getUTCFullYear() !== year
114
+ || calendarDate.getUTCMonth() !== month - 1
115
+ || calendarDate.getUTCDate() !== day
116
+ || Number(hourText) > 23
117
+ || Number(minuteText) > 59
118
+ || Number(secondText) > 59) {
119
+ throw new Error(`Automation ${label} must be a valid ISO timestamp.`);
120
+ }
121
+ return date;
122
+ }
123
+ function requireCompiledCron(compiled) {
124
+ if (!compiled)
125
+ throw new Error('Automation cron expression was not compiled.');
126
+ return compiled;
127
+ }
128
+ function validDateMs(date, label) {
129
+ const value = date.getTime();
130
+ if (!Number.isFinite(value))
131
+ throw new Error(`Automation ${label} must be a valid date.`);
132
+ return value;
133
+ }
134
+ function validResultDate(value) {
135
+ const result = new Date(value);
136
+ validDateMs(result, 'activation result');
137
+ return result;
138
+ }
139
+ function floorUtcMinute(value) {
140
+ return Math.floor(value / MINUTE_MS) * MINUTE_MS;
141
+ }
@@ -2,6 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.evaluateMonitorCondition = evaluateMonitorCondition;
4
4
  exports.evaluateExpression = evaluateExpression;
5
+ exports.evaluateRestrictedExpression = evaluateRestrictedExpression;
6
+ exports.validateRestrictedExpression = validateRestrictedExpression;
7
+ exports.compileRestrictedExpression = compileRestrictedExpression;
5
8
  exports.readMetric = readMetric;
6
9
  function evaluateMonitorCondition(condition, event) {
7
10
  if (condition.expression) {
@@ -27,27 +30,52 @@ function evaluateMonitorCondition(condition, event) {
27
30
  }
28
31
  }
29
32
  function evaluateExpression(expression, event) {
30
- const orParts = splitExpression(expression, '||');
31
- return orParts.some((orPart) => splitExpression(orPart, '&&').every((andPart) => evaluateComparison(andPart.trim(), event)));
33
+ return evaluateRestrictedExpression(expression, (metric) => readMetric(event, metric));
32
34
  }
33
- function evaluateComparison(expression, event) {
34
- const match = expression.match(/^([a-zA-Z0-9_.-]+)\s*(>=|<=|==|!=|>|<)\s*(.+)$/);
35
- if (!match) {
35
+ function evaluateRestrictedExpression(expression, contextOrResolver) {
36
+ const compiled = compileRestrictedExpression(expression);
37
+ const resolveMetric = typeof contextOrResolver === 'function'
38
+ ? contextOrResolver
39
+ : (metric) => readContextMetric(contextOrResolver, metric);
40
+ return compiled.some((orPart) => orPart.every((comparison) => evaluateRestrictedComparison(comparison, resolveMetric)));
41
+ }
42
+ function validateRestrictedExpression(expression) {
43
+ compileRestrictedExpression(expression);
44
+ }
45
+ function compileRestrictedExpression(expression) {
46
+ const source = String(expression || '').trim();
47
+ if (!source)
36
48
  throw new Error(`Unsupported monitor condition expression: ${expression}`);
37
- }
38
- const rawValue = String(match[3] || '').trim().replace(/^["']|["']$/g, '');
39
- const numeric = Number(rawValue);
40
- return evaluateMonitorCondition({
41
- metric: String(match[1] || '').trim(),
49
+ return source.split('||').map((orPart) => {
50
+ if (!orPart.trim())
51
+ throw new Error(`Unsupported monitor condition expression: ${expression}`);
52
+ return orPart.split('&&').map((andPart) => compileRestrictedComparison(andPart.trim(), expression));
53
+ });
54
+ }
55
+ function compileRestrictedComparison(expression, original) {
56
+ const match = expression.match(/^([a-zA-Z0-9_.-]+)\s*(>=|<=|==|!=|>|<)\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\s&|<>=!]+)$/);
57
+ if (!match)
58
+ throw new Error(`Unsupported monitor condition expression: ${original}`);
59
+ return {
60
+ metric: String(match[1]),
42
61
  operator: match[2],
43
- value: Number.isFinite(numeric) && rawValue !== '' ? numeric : rawValue,
44
- }, event);
62
+ rawValue: String(match[3]),
63
+ };
45
64
  }
46
- function splitExpression(expression, operator) {
47
- return expression
48
- .split(operator)
49
- .map((part) => part.trim())
50
- .filter(Boolean);
65
+ function evaluateRestrictedComparison(comparison, resolveMetric) {
66
+ const rawValue = comparison.rawValue.replace(/^["']|["']$/g, '');
67
+ const numeric = Number(rawValue);
68
+ const actual = resolveMetric(comparison.metric);
69
+ const expected = Number.isFinite(numeric) && rawValue !== '' ? numeric : rawValue;
70
+ switch (comparison.operator) {
71
+ case '>': return Number(actual) > Number(expected);
72
+ case '>=': return Number(actual) >= Number(expected);
73
+ case '<': return Number(actual) < Number(expected);
74
+ case '<=': return Number(actual) <= Number(expected);
75
+ case '==': return String(actual) === String(expected);
76
+ case '!=': return String(actual) !== String(expected);
77
+ default: return false;
78
+ }
51
79
  }
52
80
  function readMetric(event, metric) {
53
81
  const key = String(metric || '').trim();
@@ -75,3 +103,18 @@ function readMetric(event, metric) {
75
103
  return current[part];
76
104
  }, payload);
77
105
  }
106
+ function readContextMetric(context, metric) {
107
+ if (metric === 'abs_change_percent') {
108
+ return Math.abs(Number(context.change_percent ?? context.changePercent ?? 0));
109
+ }
110
+ const normalizedKey = metric.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
111
+ if (Object.prototype.hasOwnProperty.call(context, metric))
112
+ return context[metric];
113
+ if (Object.prototype.hasOwnProperty.call(context, normalizedKey))
114
+ return context[normalizedKey];
115
+ return metric.split('.').reduce((current, part) => {
116
+ if (!current || typeof current !== 'object')
117
+ return undefined;
118
+ return current[part];
119
+ }, context);
120
+ }
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scheduledJobToAutomationInput = scheduledJobToAutomationInput;
4
+ exports.automationToScheduledJob = automationToScheduledJob;
5
+ exports.monitorToAutomationInput = monitorToAutomationInput;
6
+ exports.automationToMonitor = automationToMonitor;
7
+ exports.automationToScheduledJobRun = automationToScheduledJobRun;
8
+ exports.automationToMonitorRun = automationToMonitorRun;
9
+ exports.latestFinishedEvaluation = latestFinishedEvaluation;
10
+ exports.latestAutomationRun = latestAutomationRun;
11
+ const superai_contracts_1 = require("../../../../packages/contracts/src/index.js");
12
+ const condition_evaluator_js_1 = require("./condition-evaluator.js");
13
+ function scheduledJobToAutomationInput(input) {
14
+ const triggerType = (0, superai_contracts_1.normalizeScheduledJobTriggerType)(input.triggerType);
15
+ const activation = triggerType === 'once'
16
+ ? { kind: 'once', runAt: requireText(input.runAt, 'Scheduled job runAt') }
17
+ : triggerType === 'cron'
18
+ ? { kind: 'cron', expression: requireText(input.cronExpr, 'Scheduled job cronExpr'), timezone: 'UTC' }
19
+ : fail(`Unsupported scheduled job trigger type: ${triggerType}`);
20
+ return {
21
+ workspaceId: requireText(input.workspaceId, 'Scheduled job workspaceId'),
22
+ title: String(input.description || '').trim() || requireText(input.promptTemplate, 'Scheduled job promptTemplate'),
23
+ enabled: input.enabled !== false,
24
+ activation,
25
+ condition: { kind: 'always' },
26
+ action: {
27
+ kind: 'agent-prompt',
28
+ promptTemplate: requireText(input.promptTemplate, 'Scheduled job promptTemplate'),
29
+ executionMode: legacyExecutionMode(input.executionMode, 'same-thread'),
30
+ },
31
+ delivery: { platform: requireText(input.platform, 'Scheduled job platform'), route: input.route },
32
+ policies: { concurrency: 'skip-if-running', cooldownMs: 0 },
33
+ originKind: 'scheduled-job',
34
+ legacyMetadata: { scheduledDescription: input.description ?? '' },
35
+ };
36
+ }
37
+ function automationToScheduledJob(automation, latestRun) {
38
+ assertOrigin(automation, 'scheduled-job');
39
+ if (automation.condition.kind !== 'always')
40
+ throw new Error('Scheduled-job automation condition must be always.');
41
+ if (automation.activation.kind !== 'cron' && automation.activation.kind !== 'once') {
42
+ throw new Error('Scheduled-job automation activation must be cron or once.');
43
+ }
44
+ return {
45
+ id: automation.id,
46
+ workspaceId: automation.workspaceId,
47
+ platform: automation.delivery.platform,
48
+ route: automation.delivery.route,
49
+ executionMode: automation.action.executionMode,
50
+ triggerType: automation.activation.kind,
51
+ ...(automation.activation.kind === 'cron' ? { cronExpr: automation.activation.expression } : { runAt: automation.activation.runAt }),
52
+ promptTemplate: automation.action.promptTemplate,
53
+ description: automation.legacyMetadata?.scheduledDescription ?? automation.title,
54
+ enabled: automation.enabled,
55
+ concurrencyPolicy: 'skip_if_running',
56
+ createdAt: automation.createdAt,
57
+ updatedAt: automation.updatedAt,
58
+ ...(latestRun?.finishedAt || latestRun?.startedAt || automation.lastEvaluationAt
59
+ ? { lastRunAt: latestRun?.finishedAt || latestRun?.startedAt || automation.lastEvaluationAt }
60
+ : {}),
61
+ ...(latestRun ? { lastStatus: latestRun.status } : {}),
62
+ ...(latestRun?.error ? { lastError: latestRun.error } : {}),
63
+ };
64
+ }
65
+ function monitorToAutomationInput(input) {
66
+ return {
67
+ workspaceId: requireText(input.workspaceId, 'Automation monitor workspaceId'),
68
+ title: requireText(input.title, 'Automation monitor title'),
69
+ enabled: input.enabled !== false,
70
+ activation: {
71
+ kind: 'provider-event',
72
+ sourceType: requireText(input.sourceType, 'Automation monitor sourceType'),
73
+ sourceConfig: input.sourceConfig || {},
74
+ },
75
+ condition: { kind: 'expression', expression: monitorConditionExpression(input.condition) },
76
+ action: {
77
+ kind: 'agent-prompt',
78
+ promptTemplate: requireText(input.promptTemplate, 'Automation monitor promptTemplate'),
79
+ executionMode: legacyExecutionMode(input.executionMode, 'side-thread'),
80
+ },
81
+ delivery: { platform: requireText(input.platform, 'Automation monitor platform'), route: input.route },
82
+ policies: { concurrency: 'skip-if-running', cooldownMs: input.cooldownMs ?? 15 * 60 * 1_000 },
83
+ originKind: 'automation-monitor',
84
+ };
85
+ }
86
+ function automationToMonitor(automation, latestEvaluation, latestRun, latestStateEvaluation) {
87
+ assertOrigin(automation, 'automation-monitor');
88
+ if (automation.activation.kind !== 'provider-event') {
89
+ throw new Error('Automation-monitor automation activation must be provider-event.');
90
+ }
91
+ if (automation.condition.kind !== 'expression') {
92
+ throw new Error('Automation-monitor automation condition must be expression.');
93
+ }
94
+ const stateEvaluation = latestStateEvaluation || latestEvaluation;
95
+ const lastState = stateEvaluation?.status === 'finished' ? stateEvaluation.nextState : undefined;
96
+ const latestEvaluationStatus = latestEvaluation && latestRun?.evaluationId !== latestEvaluation.id
97
+ ? evaluationStatus(latestEvaluation)
98
+ : undefined;
99
+ return {
100
+ id: automation.id,
101
+ workspaceId: automation.workspaceId,
102
+ title: automation.title,
103
+ sourceType: automation.activation.sourceType,
104
+ sourceConfig: automation.activation.sourceConfig,
105
+ condition: expressionToMonitorCondition(automation.condition.expression),
106
+ promptTemplate: automation.action.promptTemplate,
107
+ platform: automation.delivery.platform,
108
+ route: automation.delivery.route,
109
+ executionMode: automation.action.executionMode,
110
+ enabled: automation.enabled,
111
+ cooldownMs: automation.policies.cooldownMs,
112
+ concurrencyPolicy: 'skip_if_running',
113
+ ...(lastState ? { lastState } : {}),
114
+ createdAt: automation.createdAt,
115
+ updatedAt: automation.updatedAt,
116
+ ...(automation.lastTriggeredAt ? { lastTriggeredAt: automation.lastTriggeredAt } : {}),
117
+ ...(latestEvaluationStatus ? { lastStatus: latestEvaluationStatus } : latestRun ? { lastStatus: latestRun.status } : {}),
118
+ ...(latestEvaluation?.status === 'finished' && latestEvaluation.conditionOutcome === 'error' && latestEvaluation.resultSummary
119
+ ? { lastError: latestEvaluation.resultSummary }
120
+ : latestRun?.error
121
+ ? { lastError: latestRun.error }
122
+ : automation.consecutiveEvaluationFailures > 0 && latestEvaluation?.status === 'finished' && latestEvaluation.resultSummary
123
+ ? { lastError: latestEvaluation.resultSummary }
124
+ : {}),
125
+ };
126
+ }
127
+ function automationToScheduledJobRun(evaluation, run) {
128
+ const status = run?.status || evaluationStatus(evaluation);
129
+ const evaluationError = !run && evaluation.status === 'finished'
130
+ && (evaluation.conditionOutcome === 'skipped' || evaluation.conditionOutcome === 'error')
131
+ ? evaluation.resultSummary
132
+ : undefined;
133
+ return {
134
+ id: run?.id || evaluation.id,
135
+ jobId: evaluation.automationId,
136
+ status,
137
+ triggeredAt: evaluation.status === 'finished' ? evaluation.triggeredAt || evaluation.startedAt : evaluation.startedAt,
138
+ ...(run?.startedAt ? { startedAt: run.startedAt } : {}),
139
+ ...(run?.finishedAt ? { finishedAt: run.finishedAt } : {}),
140
+ ...(run?.error || evaluationError
141
+ ? { error: run?.error || evaluationError, deliveryError: run?.error || evaluationError }
142
+ : {}),
143
+ ...(run?.threadId ? { threadId: run.threadId } : {}),
144
+ ...(run?.acpRunId ? { runId: run.acpRunId } : {}),
145
+ ...(legacyDeliveryMode(run?.bridgeActivity?.deliveryMode) ? { deliveryMode: legacyDeliveryMode(run?.bridgeActivity?.deliveryMode) } : {}),
146
+ ...(run?.deliveryStatus
147
+ ? { deliveryStatus: legacyDeliveryStatus(run.deliveryStatus) }
148
+ : evaluationError ? { deliveryStatus: status === 'failed' ? 'failed' : 'skipped' } : {}),
149
+ ...(typeof run?.bridgeActivity?.lastBridgeEventAt === 'string'
150
+ ? { lastBridgeEventAt: run.bridgeActivity.lastBridgeEventAt }
151
+ : {}),
152
+ };
153
+ }
154
+ function automationToMonitorRun(evaluation, run) {
155
+ const payload = evaluation.status === 'finished' ? evaluation.payload : undefined;
156
+ const eventSnapshot = payload?.eventSnapshot ? parseEventSnapshot(payload.eventSnapshot) : undefined;
157
+ const evaluationError = !run && evaluation.status === 'finished'
158
+ && (evaluation.conditionOutcome === 'skipped' || evaluation.conditionOutcome === 'error')
159
+ ? evaluation.resultSummary
160
+ : undefined;
161
+ return {
162
+ id: run?.id || evaluation.id,
163
+ monitorId: evaluation.automationId,
164
+ status: run?.status || evaluationStatus(evaluation),
165
+ triggeredAt: eventSnapshot?.occurredAt || (evaluation.status === 'finished' ? evaluation.triggeredAt : undefined) || evaluation.startedAt,
166
+ ...(run?.startedAt ? { startedAt: run.startedAt } : {}),
167
+ ...(run?.finishedAt ? { finishedAt: run.finishedAt } : {}),
168
+ ...(run?.error || evaluationError
169
+ ? { error: run?.error || evaluationError, deliveryError: run?.error || evaluationError }
170
+ : {}),
171
+ ...(eventSnapshot ? { eventSnapshot } : {}),
172
+ ...(run?.threadId ? { threadId: run.threadId } : {}),
173
+ ...(run?.acpRunId ? { runId: run.acpRunId } : {}),
174
+ ...(legacyDeliveryMode(run?.bridgeActivity?.deliveryMode) ? { deliveryMode: legacyDeliveryMode(run?.bridgeActivity?.deliveryMode) } : {}),
175
+ ...(run?.deliveryStatus
176
+ ? { deliveryStatus: legacyDeliveryStatus(run.deliveryStatus) }
177
+ : evaluationError ? { deliveryStatus: (run?.status || evaluationStatus(evaluation)) === 'failed' ? 'failed' : 'skipped' } : {}),
178
+ ...(typeof run?.bridgeActivity?.lastBridgeEventAt === 'string'
179
+ ? { lastBridgeEventAt: run.bridgeActivity.lastBridgeEventAt }
180
+ : {}),
181
+ };
182
+ }
183
+ function latestFinishedEvaluation(evaluations) {
184
+ return evaluations.find((evaluation) => evaluation.status === 'finished');
185
+ }
186
+ function latestAutomationRun(runs) {
187
+ return runs[0];
188
+ }
189
+ function monitorConditionExpression(condition) {
190
+ const operator = (0, superai_contracts_1.normalizeAutomationMonitorConditionOperator)(condition.operator);
191
+ if (typeof condition.value !== 'number' && typeof condition.value !== 'string' && typeof condition.value !== 'boolean') {
192
+ throw new Error('Automation monitor condition value must be a number, string, or boolean.');
193
+ }
194
+ if (condition.expression?.trim()) {
195
+ const expression = condition.expression.trim();
196
+ (0, condition_evaluator_js_1.validateRestrictedExpression)(expression);
197
+ return expression;
198
+ }
199
+ const metric = requireText(condition.metric, 'Automation monitor condition metric');
200
+ const expression = `${metric} ${operator} ${JSON.stringify(condition.value)}`;
201
+ (0, condition_evaluator_js_1.validateRestrictedExpression)(expression);
202
+ return expression;
203
+ }
204
+ function expressionToMonitorCondition(expression) {
205
+ if (expression.includes('&&') || expression.includes('||')) {
206
+ return { metric: 'expression', operator: '==', value: true, expression };
207
+ }
208
+ const match = expression.trim().match(/^([a-zA-Z0-9_.-]+)\s*(>=|<=|==|!=|>|<)\s*(.+)$/);
209
+ if (!match)
210
+ return { metric: 'expression', operator: '==', value: true, expression };
211
+ const raw = match[3].trim();
212
+ let value = raw.replace(/^["']|["']$/g, '');
213
+ if (raw === 'true' || raw === 'false')
214
+ value = raw === 'true';
215
+ else if (raw !== '' && Number.isFinite(Number(raw)))
216
+ value = Number(raw);
217
+ return {
218
+ metric: match[1],
219
+ operator: parseMonitorOperator(match[2]),
220
+ value,
221
+ };
222
+ }
223
+ function evaluationStatus(evaluation) {
224
+ if (evaluation.status === 'running')
225
+ return 'running';
226
+ if (evaluation.conditionOutcome === 'error')
227
+ return 'failed';
228
+ if (evaluation.triggerDecision !== 'triggered')
229
+ return 'skipped';
230
+ return 'queued';
231
+ }
232
+ function legacyDeliveryStatus(status) {
233
+ if (status === 'delivered')
234
+ return 'succeeded';
235
+ if (status === 'delivering')
236
+ return 'streaming';
237
+ return status;
238
+ }
239
+ function legacyDeliveryMode(value) {
240
+ return value === 'thread-only' || value === 'bridge-stream' || value === 'final-message' ? value : undefined;
241
+ }
242
+ function parseEventSnapshot(value) {
243
+ if (!isRecord(value))
244
+ throw new Error('Automation eventSnapshot must be an object.');
245
+ const candidate = value;
246
+ if (!isRecord(candidate.payload)) {
247
+ throw new Error('Automation eventSnapshot payload must be an object.');
248
+ }
249
+ return {
250
+ id: requireText(candidate.id, 'Automation eventSnapshot id'),
251
+ sourceType: requireText(candidate.sourceType, 'Automation eventSnapshot sourceType'),
252
+ occurredAt: requireText(candidate.occurredAt, 'Automation eventSnapshot occurredAt'),
253
+ subject: requireText(candidate.subject, 'Automation eventSnapshot subject'),
254
+ ...(typeof candidate.summary === 'string' ? { summary: candidate.summary } : {}),
255
+ payload: candidate.payload,
256
+ };
257
+ }
258
+ function parseMonitorOperator(value) {
259
+ if (value === '>' || value === '>=' || value === '<' || value === '<=' || value === '==' || value === '!=')
260
+ return value;
261
+ throw new Error(`Automation monitor operator is invalid: ${String(value)}`);
262
+ }
263
+ function isRecord(value) {
264
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
265
+ }
266
+ function assertOrigin(automation, expected) {
267
+ if (automation.originKind !== expected)
268
+ throw new Error(`Automation must have ${expected} origin.`);
269
+ }
270
+ function requireText(value, label) {
271
+ const text = String(value || '').trim();
272
+ if (!text)
273
+ throw new Error(`${label} is required.`);
274
+ return text;
275
+ }
276
+ function legacyExecutionMode(value, fallback) {
277
+ const normalized = (0, superai_contracts_1.normalizeScheduledJobExecutionMode)(value, fallback);
278
+ if (normalized === 'same-thread')
279
+ return 'same-thread';
280
+ if (normalized === 'side-thread')
281
+ return 'side-thread';
282
+ throw new Error('Scheduled job execution mode must be same-thread or side-thread.');
283
+ }
284
+ function fail(message) {
285
+ throw new Error(message);
286
+ }