@elizaos/app-core 2.0.0-alpha.337 → 2.0.0-alpha.338
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/package.json +5 -5
- package/packages/agent/src/api/trigger-routes.d.ts +1 -0
- package/packages/agent/src/api/trigger-routes.d.ts.map +1 -1
- package/packages/agent/src/api/trigger-routes.js +48 -0
- package/packages/agent/src/triggers/runtime.d.ts +5 -1
- package/packages/agent/src/triggers/runtime.d.ts.map +1 -1
- package/packages/agent/src/triggers/runtime.js +24 -6
- package/packages/agent/src/triggers/scheduling.d.ts +2 -0
- package/packages/agent/src/triggers/scheduling.d.ts.map +1 -1
- package/packages/agent/src/triggers/scheduling.js +34 -0
- package/packages/agent/src/triggers/types.d.ts +4 -0
- package/packages/agent/src/triggers/types.d.ts.map +1 -1
- package/packages/app-core/src/api/automations-compat-routes.d.ts.map +1 -1
- package/packages/app-core/src/api/automations-compat-routes.js +7 -4
- package/packages/app-core/src/components/pages/AutomationsView.d.ts.map +1 -1
- package/packages/app-core/src/components/pages/AutomationsView.js +38 -11
- package/packages/app-core/src/components/pages/HeartbeatForm.d.ts.map +1 -1
- package/packages/app-core/src/components/pages/HeartbeatForm.js +42 -3
- package/packages/app-core/src/components/pages/heartbeat-utils.d.ts +2 -0
- package/packages/app-core/src/components/pages/heartbeat-utils.d.ts.map +1 -1
- package/packages/app-core/src/components/pages/heartbeat-utils.js +18 -0
- package/packages/typescript/src/types/trigger.d.ts +4 -2
- package/packages/typescript/src/types/trigger.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/app-core",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.338",
|
|
4
4
|
"description": "Shared application core for elizaOS white-label agent apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -469,7 +469,7 @@
|
|
|
469
469
|
"@capacitor/preferences": "^8.0.1",
|
|
470
470
|
"@capacitor/push-notifications": "^8.0.0",
|
|
471
471
|
"@clack/prompts": "^1.0.0",
|
|
472
|
-
"@elizaos/agent": "^2.0.0-alpha.
|
|
472
|
+
"@elizaos/agent": "^2.0.0-alpha.338",
|
|
473
473
|
"@elizaos/app-companion": "^0.0.0",
|
|
474
474
|
"@elizaos/app-elizamaker": "^0.0.0",
|
|
475
475
|
"@elizaos/app-lifeops": "^0.0.0",
|
|
@@ -478,11 +478,11 @@
|
|
|
478
478
|
"@elizaos/app-task-coordinator": "^0.0.0",
|
|
479
479
|
"@elizaos/app-training": "^0.0.1",
|
|
480
480
|
"@elizaos/app-vincent": "^0.0.0",
|
|
481
|
-
"@elizaos/core": "^2.0.0-alpha.
|
|
481
|
+
"@elizaos/core": "^2.0.0-alpha.338",
|
|
482
482
|
"@elizaos/plugin-browser-bridge": "^0.1.0",
|
|
483
483
|
"@elizaos/plugin-wechat": "^0.1.0",
|
|
484
|
-
"@elizaos/shared": "^2.0.0-alpha.
|
|
485
|
-
"@elizaos/ui": "^2.0.0-alpha.
|
|
484
|
+
"@elizaos/shared": "^2.0.0-alpha.338",
|
|
485
|
+
"@elizaos/ui": "^2.0.0-alpha.338",
|
|
486
486
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
487
487
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
488
488
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger-routes.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/api/trigger-routes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"trigger-routes.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/api/trigger-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,11 @@ function parseNonEmptyString(value) {
|
|
|
21
21
|
const trimmed = value.trim();
|
|
22
22
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
23
23
|
}
|
|
24
|
+
function parseEventPayload(value) {
|
|
25
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
26
|
+
? value
|
|
27
|
+
: {};
|
|
28
|
+
}
|
|
24
29
|
function normalizeTriggerPath(pathname) {
|
|
25
30
|
if (pathname === "/api/heartbeats") {
|
|
26
31
|
return {
|
|
@@ -122,6 +127,7 @@ export async function handleTriggerRoutes(ctx) {
|
|
|
122
127
|
cronExpression: typeof body.cronExpression === "string"
|
|
123
128
|
? body.cronExpression
|
|
124
129
|
: undefined,
|
|
130
|
+
eventKind: typeof body.eventKind === "string" ? body.eventKind : undefined,
|
|
125
131
|
maxRuns: typeof body.maxRuns === "number" ? body.maxRuns : undefined,
|
|
126
132
|
kind,
|
|
127
133
|
workflowId,
|
|
@@ -232,6 +238,47 @@ export async function handleTriggerRoutes(ctx) {
|
|
|
232
238
|
: { ok: true, result, trigger: summary });
|
|
233
239
|
return true;
|
|
234
240
|
}
|
|
241
|
+
const eventMatch = /^\/api\/triggers\/events\/([^/]+)$/.exec(normalizedPathname);
|
|
242
|
+
if (method === "POST" && eventMatch) {
|
|
243
|
+
const eventKind = decodeURIComponent(eventMatch[1] ?? "").trim();
|
|
244
|
+
if (!eventKind) {
|
|
245
|
+
error(res, "event kind is required", 400);
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
const body = await readJsonBody(req, res);
|
|
249
|
+
if (!body)
|
|
250
|
+
return true;
|
|
251
|
+
const payload = parseEventPayload(body.payload ?? body);
|
|
252
|
+
const tasks = await listTriggerTasks(runtime);
|
|
253
|
+
const matchingTasks = tasks.filter((task) => {
|
|
254
|
+
const trigger = readTriggerConfig(task);
|
|
255
|
+
return (trigger?.enabled === true &&
|
|
256
|
+
trigger.triggerType === "event" &&
|
|
257
|
+
trigger.eventKind === eventKind);
|
|
258
|
+
});
|
|
259
|
+
const results = [];
|
|
260
|
+
for (const task of matchingTasks) {
|
|
261
|
+
const result = await executeTriggerTask(runtime, task, {
|
|
262
|
+
source: "event",
|
|
263
|
+
event: { kind: eventKind, payload },
|
|
264
|
+
});
|
|
265
|
+
const refreshed = task.id ? await runtime.getTask(task.id) : null;
|
|
266
|
+
results.push({
|
|
267
|
+
taskId: task.id,
|
|
268
|
+
result,
|
|
269
|
+
trigger: refreshed
|
|
270
|
+
? taskToTriggerSummary(refreshed)
|
|
271
|
+
: (result.trigger ?? null),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
json(res, {
|
|
275
|
+
ok: true,
|
|
276
|
+
eventKind,
|
|
277
|
+
matched: matchingTasks.length,
|
|
278
|
+
results,
|
|
279
|
+
});
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
235
282
|
const itemMatch = /^\/api\/triggers\/([^/]+)$/.exec(normalizedPathname);
|
|
236
283
|
if (!itemMatch)
|
|
237
284
|
return false;
|
|
@@ -310,6 +357,7 @@ export async function handleTriggerRoutes(ctx) {
|
|
|
310
357
|
cronExpression: typeof body.cronExpression === "string"
|
|
311
358
|
? body.cronExpression
|
|
312
359
|
: current.cronExpression,
|
|
360
|
+
eventKind: typeof body.eventKind === "string" ? body.eventKind : current.eventKind,
|
|
313
361
|
maxRuns: typeof body.maxRuns === "number" ? body.maxRuns : current.maxRuns,
|
|
314
362
|
kind: nextKind,
|
|
315
363
|
workflowId: nextWorkflowId,
|
|
@@ -3,8 +3,12 @@ import type { TriggerConfig, TriggerHealthSnapshot, TriggerRunRecord, TriggerSum
|
|
|
3
3
|
export declare const TRIGGER_TASK_NAME: "TRIGGER_DISPATCH";
|
|
4
4
|
export declare const TRIGGER_TASK_TAGS: readonly ["queue", "repeat", "trigger"];
|
|
5
5
|
export interface TriggerExecutionOptions {
|
|
6
|
-
source: "scheduler" | "manual";
|
|
6
|
+
source: "scheduler" | "manual" | "event";
|
|
7
7
|
force?: boolean;
|
|
8
|
+
event?: {
|
|
9
|
+
kind: string;
|
|
10
|
+
payload?: Record<string, unknown>;
|
|
11
|
+
};
|
|
8
12
|
}
|
|
9
13
|
export interface TriggerExecutionResult {
|
|
10
14
|
status: "success" | "error" | "skipped";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/triggers/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAW,IAAI,EAAQ,MAAM,eAAe,CAAC;AAOxE,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EAEf,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,iBAAiB,EAAG,kBAA2B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AAYzE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/triggers/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAW,IAAI,EAAQ,MAAM,eAAe,CAAC;AAOxE,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EAEf,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,iBAAiB,EAAG,kBAA2B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,yCAA0C,CAAC;AAYzE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAGhC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAgDD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,aAAa,GAAG,IAAI,CAOlE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,gBAAgB,EAAE,CAG9D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAavE;AAED,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAa/D;AA6ID,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CA0NjC;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAiBtE;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,EAAE,CAAC,CAwBjB;AAkED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,cAAc,GAAG,IAAI,CAqCtE;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAsChC"}
|
|
@@ -92,7 +92,7 @@ async function isAutonomyServiceAvailable(runtime) {
|
|
|
92
92
|
* This replaces the previous approach of calling a non-existent
|
|
93
93
|
* `injectAutonomousInstruction` method on the service.
|
|
94
94
|
*/
|
|
95
|
-
async function dispatchInstruction(runtime, taskId, trigger) {
|
|
95
|
+
async function dispatchInstruction(runtime, taskId, trigger, event) {
|
|
96
96
|
// Resolve the autonomy service to find the target room.
|
|
97
97
|
// Retry up to 5 times (500ms, 1s, 1.5s, 2s backoff) because the
|
|
98
98
|
// service may still be registering after a runtime restart or SQL
|
|
@@ -127,7 +127,10 @@ async function dispatchInstruction(runtime, taskId, trigger) {
|
|
|
127
127
|
}
|
|
128
128
|
// Create a memory in the autonomy room with the trigger instruction.
|
|
129
129
|
// The AutonomyService loop picks this up as an autonomous action.
|
|
130
|
-
const
|
|
130
|
+
const eventText = event
|
|
131
|
+
? `\n\nEvent: ${event.kind}\nPayload: ${JSON.stringify(event.payload ?? {})}`
|
|
132
|
+
: "";
|
|
133
|
+
const instructionText = `[Heartbeat: ${trigger.displayName}]\n${trigger.instructions}${eventText}`;
|
|
131
134
|
await runtime.createMemory({
|
|
132
135
|
entityId: runtime.agentId,
|
|
133
136
|
roomId,
|
|
@@ -147,7 +150,7 @@ async function dispatchInstruction(runtime, taskId, trigger) {
|
|
|
147
150
|
// call processActions here to avoid double-dispatch — the loop is
|
|
148
151
|
// the single execution path for all autonomous instructions.
|
|
149
152
|
}
|
|
150
|
-
async function dispatchWorkflow(runtime, trigger) {
|
|
153
|
+
async function dispatchWorkflow(runtime, trigger, event) {
|
|
151
154
|
if (!trigger.workflowId) {
|
|
152
155
|
return { ok: false, error: "workflow trigger missing workflowId" };
|
|
153
156
|
}
|
|
@@ -160,7 +163,7 @@ async function dispatchWorkflow(runtime, trigger) {
|
|
|
160
163
|
}, "[triggers] workflow dispatch requested but N8N_DISPATCH service not registered");
|
|
161
164
|
return { ok: false, error: "N8N_DISPATCH service not registered" };
|
|
162
165
|
}
|
|
163
|
-
const result = await svc.execute(trigger.workflowId);
|
|
166
|
+
const result = await svc.execute(trigger.workflowId, event ? { eventKind: event.kind, eventPayload: event.payload ?? {} } : {});
|
|
164
167
|
return result.ok
|
|
165
168
|
? { ok: true, executionId: result.executionId }
|
|
166
169
|
: { ok: false, error: result.error ?? "workflow execution failed" };
|
|
@@ -178,6 +181,19 @@ export async function executeTriggerTask(runtime, task, options) {
|
|
|
178
181
|
recordExecutionMetric(runtime.agentId, "skipped", Date.now());
|
|
179
182
|
return { status: "skipped", taskDeleted: false };
|
|
180
183
|
}
|
|
184
|
+
if (options.source === "event" &&
|
|
185
|
+
trigger.triggerType !== "event" &&
|
|
186
|
+
!options.force) {
|
|
187
|
+
recordExecutionMetric(runtime.agentId, "skipped", Date.now());
|
|
188
|
+
return { status: "skipped", taskDeleted: false };
|
|
189
|
+
}
|
|
190
|
+
if (options.source === "event" &&
|
|
191
|
+
trigger.triggerType === "event" &&
|
|
192
|
+
trigger.eventKind !== options.event?.kind &&
|
|
193
|
+
!options.force) {
|
|
194
|
+
recordExecutionMetric(runtime.agentId, "skipped", Date.now());
|
|
195
|
+
return { status: "skipped", taskDeleted: false };
|
|
196
|
+
}
|
|
181
197
|
if (typeof trigger.maxRuns === "number" &&
|
|
182
198
|
trigger.maxRuns > 0 &&
|
|
183
199
|
trigger.runCount >= trigger.maxRuns) {
|
|
@@ -208,7 +224,7 @@ export async function executeTriggerTask(runtime, task, options) {
|
|
|
208
224
|
let errorMessage = "";
|
|
209
225
|
let workflowExecutionId;
|
|
210
226
|
if (isWorkflowKind) {
|
|
211
|
-
const result = await dispatchWorkflow(runtime, trigger);
|
|
227
|
+
const result = await dispatchWorkflow(runtime, trigger, options.event);
|
|
212
228
|
if (result.ok === true) {
|
|
213
229
|
workflowExecutionId = result.executionId;
|
|
214
230
|
}
|
|
@@ -227,7 +243,7 @@ export async function executeTriggerTask(runtime, task, options) {
|
|
|
227
243
|
}
|
|
228
244
|
else {
|
|
229
245
|
try {
|
|
230
|
-
await dispatchInstruction(runtime, task.id, trigger);
|
|
246
|
+
await dispatchInstruction(runtime, task.id, trigger, options.event);
|
|
231
247
|
}
|
|
232
248
|
catch (error) {
|
|
233
249
|
status = "error";
|
|
@@ -262,6 +278,7 @@ export async function executeTriggerTask(runtime, task, options) {
|
|
|
262
278
|
error: errorMessage || undefined,
|
|
263
279
|
latencyMs: finishedAt - startedAt,
|
|
264
280
|
source: options.source,
|
|
281
|
+
eventKind: options.event?.kind,
|
|
265
282
|
};
|
|
266
283
|
const updatedTrigger = {
|
|
267
284
|
...trigger,
|
|
@@ -449,6 +466,7 @@ export function taskToTriggerSummary(task) {
|
|
|
449
466
|
intervalMs: trigger.intervalMs,
|
|
450
467
|
scheduledAtIso: trigger.scheduledAtIso,
|
|
451
468
|
cronExpression: trigger.cronExpression,
|
|
469
|
+
eventKind: trigger.eventKind,
|
|
452
470
|
maxRuns: trigger.maxRuns,
|
|
453
471
|
runCount: trigger.runCount,
|
|
454
472
|
nextRunAtMs: trigger.nextRunAtMs,
|
|
@@ -27,6 +27,7 @@ interface DraftInput {
|
|
|
27
27
|
intervalMs?: number;
|
|
28
28
|
scheduledAtIso?: string;
|
|
29
29
|
cronExpression?: string;
|
|
30
|
+
eventKind?: string;
|
|
30
31
|
maxRuns?: number;
|
|
31
32
|
kind?: TriggerKind;
|
|
32
33
|
workflowId?: string;
|
|
@@ -49,6 +50,7 @@ export declare function buildTriggerDedupeKey(parts: {
|
|
|
49
50
|
intervalMs?: number;
|
|
50
51
|
scheduledAtIso?: string;
|
|
51
52
|
cronExpression?: string;
|
|
53
|
+
eventKind?: string;
|
|
52
54
|
wakeMode: TriggerWakeMode;
|
|
53
55
|
kind?: TriggerKind;
|
|
54
56
|
workflowId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/triggers/scheduling.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,KAAK,sBAAsB,EAE3B,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAC9C,eAAO,MAAM,uBAAuB,QAA2B,CAAC;AAChE,eAAO,MAAM,4BAA4B,QAA4B,CAAC;AACtE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAW3C,UAAU,YAAY;IACpB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AAgBD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,UAAU;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAeD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AA8CD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAmC3E;AA6DD,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAgBf;AAED,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIzE;AAED,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,GACZ,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"scheduling.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/triggers/scheduling.ts"],"names":[],"mappings":"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"}
|
|
@@ -199,6 +199,13 @@ export function resolveTriggerTiming(trigger, nowMs) {
|
|
|
199
199
|
nextRunAtMs,
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
|
+
if (trigger.triggerType === "event") {
|
|
203
|
+
return {
|
|
204
|
+
updatedAt: nowMs,
|
|
205
|
+
updateIntervalMs: DISABLED_TRIGGER_INTERVAL_MS,
|
|
206
|
+
nextRunAtMs: nowMs + DISABLED_TRIGGER_INTERVAL_MS,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
202
209
|
const nextRunAtMs = trigger.cronExpression
|
|
203
210
|
? computeNextCronRunAtMs(trigger.cronExpression, nowMs, trigger.timezone)
|
|
204
211
|
: null;
|
|
@@ -233,6 +240,7 @@ export function buildTriggerDedupeKey(parts) {
|
|
|
233
240
|
String(parts.intervalMs ?? ""),
|
|
234
241
|
parts.scheduledAtIso ?? "",
|
|
235
242
|
parts.cronExpression ?? "",
|
|
243
|
+
parts.eventKind ?? "",
|
|
236
244
|
parts.wakeMode,
|
|
237
245
|
];
|
|
238
246
|
if (effectiveKind === "workflow") {
|
|
@@ -266,6 +274,9 @@ export function buildTriggerConfig(params) {
|
|
|
266
274
|
cronExpression: params.draft.triggerType === "cron"
|
|
267
275
|
? params.draft.cronExpression
|
|
268
276
|
: undefined,
|
|
277
|
+
eventKind: params.draft.triggerType === "event"
|
|
278
|
+
? params.draft.eventKind
|
|
279
|
+
: undefined,
|
|
269
280
|
maxRuns: params.draft.maxRuns,
|
|
270
281
|
runCount: previous?.runCount ?? 0,
|
|
271
282
|
dedupeKey: buildTriggerDedupeKey({
|
|
@@ -274,6 +285,7 @@ export function buildTriggerConfig(params) {
|
|
|
274
285
|
intervalMs: params.draft.intervalMs,
|
|
275
286
|
scheduledAtIso: params.draft.scheduledAtIso,
|
|
276
287
|
cronExpression: params.draft.cronExpression,
|
|
288
|
+
eventKind: params.draft.eventKind,
|
|
277
289
|
wakeMode: params.draft.wakeMode,
|
|
278
290
|
kind: params.draft.kind,
|
|
279
291
|
workflowId: params.draft.workflowId,
|
|
@@ -327,6 +339,7 @@ export function normalizeTriggerDraft(params) {
|
|
|
327
339
|
: undefined;
|
|
328
340
|
const scheduledAtIso = params.input.scheduledAtIso?.trim();
|
|
329
341
|
const cronExpression = params.input.cronExpression?.trim();
|
|
342
|
+
const eventKind = params.input.eventKind?.trim();
|
|
330
343
|
const maxRuns = typeof params.input.maxRuns === "number"
|
|
331
344
|
? Math.floor(params.input.maxRuns)
|
|
332
345
|
: undefined;
|
|
@@ -379,6 +392,27 @@ export function normalizeTriggerDraft(params) {
|
|
|
379
392
|
},
|
|
380
393
|
};
|
|
381
394
|
}
|
|
395
|
+
if (triggerType === "event") {
|
|
396
|
+
if (!eventKind) {
|
|
397
|
+
return { error: "eventKind is required for event triggers" };
|
|
398
|
+
}
|
|
399
|
+
return {
|
|
400
|
+
draft: {
|
|
401
|
+
displayName,
|
|
402
|
+
instructions,
|
|
403
|
+
triggerType,
|
|
404
|
+
wakeMode,
|
|
405
|
+
enabled,
|
|
406
|
+
createdBy,
|
|
407
|
+
timezone,
|
|
408
|
+
eventKind,
|
|
409
|
+
maxRuns,
|
|
410
|
+
kind,
|
|
411
|
+
workflowId,
|
|
412
|
+
workflowName,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
382
416
|
if (!cronExpression || !parseCronExpression(cronExpression)) {
|
|
383
417
|
return { error: "cronExpression must be a valid 5-field cron expression" };
|
|
384
418
|
}
|
|
@@ -21,6 +21,7 @@ export interface TriggerSummary {
|
|
|
21
21
|
intervalMs?: number;
|
|
22
22
|
scheduledAtIso?: string;
|
|
23
23
|
cronExpression?: string;
|
|
24
|
+
eventKind?: string;
|
|
24
25
|
maxRuns?: number;
|
|
25
26
|
runCount: number;
|
|
26
27
|
nextRunAtMs?: number;
|
|
@@ -53,6 +54,7 @@ export interface CreateTriggerRequest {
|
|
|
53
54
|
intervalMs?: number;
|
|
54
55
|
scheduledAtIso?: string;
|
|
55
56
|
cronExpression?: string;
|
|
57
|
+
eventKind?: string;
|
|
56
58
|
maxRuns?: number;
|
|
57
59
|
kind?: TriggerKind;
|
|
58
60
|
workflowId?: string;
|
|
@@ -68,6 +70,7 @@ export interface UpdateTriggerRequest {
|
|
|
68
70
|
intervalMs?: number;
|
|
69
71
|
scheduledAtIso?: string;
|
|
70
72
|
cronExpression?: string;
|
|
73
|
+
eventKind?: string;
|
|
71
74
|
maxRuns?: number;
|
|
72
75
|
kind?: TriggerKind;
|
|
73
76
|
workflowId?: string;
|
|
@@ -84,6 +87,7 @@ export interface NormalizedTriggerDraft {
|
|
|
84
87
|
intervalMs?: number;
|
|
85
88
|
scheduledAtIso?: string;
|
|
86
89
|
cronExpression?: string;
|
|
90
|
+
eventKind?: string;
|
|
87
91
|
maxRuns?: number;
|
|
88
92
|
kind?: TriggerKind;
|
|
89
93
|
workflowId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/triggers/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../agent/src/triggers/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"automations-compat-routes.d.ts","sourceRoot":"","sources":["../../../../../src/api/automations-compat-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAwClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"automations-compat-routes.d.ts","sourceRoot":"","sources":["../../../../../src/api/automations-compat-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAwClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AA+yBhE,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,OAAO,CAAC,CAiClB"}
|
|
@@ -254,25 +254,28 @@ function buildAutomationDraftItem(room) {
|
|
|
254
254
|
};
|
|
255
255
|
}
|
|
256
256
|
function buildWorkflowItem(workflow, room, fallback) {
|
|
257
|
+
const missingBackingWorkflow = !workflow && !fallback.trigger;
|
|
257
258
|
const title = workflow?.name?.trim() ||
|
|
258
259
|
room?.metadata.workflowName?.trim() ||
|
|
259
260
|
fallback.workflowName?.trim() ||
|
|
260
261
|
fallback.workflowId;
|
|
261
|
-
const enabled =
|
|
262
|
+
const enabled = missingBackingWorkflow === true
|
|
263
|
+
? false
|
|
264
|
+
: (workflow?.active ?? fallback.trigger?.enabled ?? false);
|
|
262
265
|
const description = workflow?.description?.trim() ||
|
|
263
266
|
(fallback.trigger
|
|
264
267
|
? `Scheduled workflow automation for ${title}.`
|
|
265
|
-
: "
|
|
268
|
+
: "");
|
|
266
269
|
return {
|
|
267
270
|
id: `workflow:${fallback.workflowId}`,
|
|
268
271
|
type: "n8n_workflow",
|
|
269
272
|
source: workflow ? "n8n_workflow" : "workflow_shadow",
|
|
270
273
|
title,
|
|
271
274
|
description,
|
|
272
|
-
status: enabled ? "active" : "paused",
|
|
275
|
+
status: missingBackingWorkflow ? "draft" : enabled ? "active" : "paused",
|
|
273
276
|
enabled,
|
|
274
277
|
system: false,
|
|
275
|
-
isDraft:
|
|
278
|
+
isDraft: missingBackingWorkflow,
|
|
276
279
|
hasBackingWorkflow: Boolean(workflow),
|
|
277
280
|
updatedAt: room?.updatedAt ??
|
|
278
281
|
normalizeDateValue(fallback.trigger?.updatedAt) ??
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutomationsView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/AutomationsView.tsx"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"AutomationsView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/AutomationsView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAg+JH,wBAAgB,eAAe,4CAO9B;AAED,wBAAgB,uBAAuB,4CAmBtC"}
|
|
@@ -15,7 +15,7 @@ import { AppPageSidebar } from "../shared/AppPageSidebar";
|
|
|
15
15
|
import { AppWorkspaceChrome, useAppWorkspaceChatChrome, } from "../workspace/AppWorkspaceChrome";
|
|
16
16
|
import { buildAutomationDraftConversationMetadata, buildAutomationResponseRoutingMetadata, buildCoordinatorConversationMetadata, buildCoordinatorTriggerConversationMetadata, buildWorkflowConversationMetadata, buildWorkflowDraftConversationMetadata, getAutomationBridgeConversationId, resolveAutomationConversation, } from "./automation-conversations";
|
|
17
17
|
import { HeartbeatForm } from "./HeartbeatForm";
|
|
18
|
-
import { buildCreateRequest, buildUpdateRequest, emptyForm, formFromTrigger, loadUserTemplates, localizedExecutionStatus, railMonogram, saveUserTemplates, scheduleLabel, toneForLastStatus, validateForm, } from "./heartbeat-utils";
|
|
18
|
+
import { buildCreateRequest, buildUpdateRequest, emptyForm, formFromTrigger, humanizeEventKind, loadUserTemplates, localizedExecutionStatus, railMonogram, saveUserTemplates, scheduleLabel, toneForLastStatus, validateForm, } from "./heartbeat-utils";
|
|
19
19
|
import { PageScopedChatPane } from "./PageScopedChatPane";
|
|
20
20
|
import { WorkflowGraphViewer } from "./WorkflowGraphViewer";
|
|
21
21
|
import { VISUALIZE_WORKFLOW_EVENT, } from "./workflow-graph-events";
|
|
@@ -186,6 +186,9 @@ function collectScheduledAutomationEntries(items) {
|
|
|
186
186
|
key: `${item.id}:${schedule.id}`,
|
|
187
187
|
})));
|
|
188
188
|
}
|
|
189
|
+
function isTimeBasedTrigger(trigger) {
|
|
190
|
+
return trigger.triggerType !== "event";
|
|
191
|
+
}
|
|
189
192
|
function formatScheduleCount(count) {
|
|
190
193
|
return count === 1 ? "1 schedule" : `${count} schedules`;
|
|
191
194
|
}
|
|
@@ -246,6 +249,8 @@ function getTriggerStartModeLabel(trigger) {
|
|
|
246
249
|
return "One time";
|
|
247
250
|
if (trigger.triggerType === "cron")
|
|
248
251
|
return "Cron schedule";
|
|
252
|
+
if (trigger.triggerType === "event")
|
|
253
|
+
return "Event";
|
|
249
254
|
return "Repeating";
|
|
250
255
|
}
|
|
251
256
|
function buildTriggerSchedulePrompt(trigger) {
|
|
@@ -258,6 +263,9 @@ function buildTriggerSchedulePrompt(trigger) {
|
|
|
258
263
|
if (trigger.triggerType === "cron") {
|
|
259
264
|
return `Schedule: cron ${trigger.cronExpression ?? ""}.`;
|
|
260
265
|
}
|
|
266
|
+
if (trigger.triggerType === "event") {
|
|
267
|
+
return `Event: ${trigger.eventKind ?? "event"}.`;
|
|
268
|
+
}
|
|
261
269
|
return `Schedule type: ${trigger.triggerType}.`;
|
|
262
270
|
}
|
|
263
271
|
function buildWorkflowCompilationPrompt(item) {
|
|
@@ -1017,6 +1025,7 @@ function TaskAutomationDetailPane({ automation, onPromoteToWorkflow, }) {
|
|
|
1017
1025
|
: "Open";
|
|
1018
1026
|
const statusTone = automation.system ? "muted" : task.isCompleted ? "muted" : "success";
|
|
1019
1027
|
const nextScheduledRun = automation.schedules
|
|
1028
|
+
.filter(isTimeBasedTrigger)
|
|
1020
1029
|
.map((schedule) => schedule.nextRunAtMs ?? 0)
|
|
1021
1030
|
.filter((value) => value > 0)
|
|
1022
1031
|
.sort((left, right) => left - right)[0];
|
|
@@ -1149,10 +1158,11 @@ function AutomationsDashboard({ items, onSelectItem, onCreateTask, onCreateWorkf
|
|
|
1149
1158
|
const taskCount = visibleItems.filter((item) => item.type !== "n8n_workflow").length;
|
|
1150
1159
|
const workflowCount = visibleItems.filter((item) => item.type === "n8n_workflow").length;
|
|
1151
1160
|
const activeCount = visibleItems.filter((item) => item.enabled && !item.isDraft).length;
|
|
1152
|
-
const activeScheduleCount = scheduledEntries.filter(({ schedule }) => schedule.enabled).length;
|
|
1153
|
-
const
|
|
1161
|
+
const activeScheduleCount = scheduledEntries.filter(({ schedule }) => schedule.enabled && isTimeBasedTrigger(schedule)).length;
|
|
1162
|
+
const activeEventCount = scheduledEntries.filter(({ schedule }) => schedule.enabled && schedule.triggerType === "event").length;
|
|
1154
1163
|
const upcoming = useMemo(() => scheduledEntries
|
|
1155
1164
|
.filter(({ schedule }) => schedule.enabled &&
|
|
1165
|
+
isTimeBasedTrigger(schedule) &&
|
|
1156
1166
|
typeof schedule.nextRunAtMs === "number" &&
|
|
1157
1167
|
schedule.nextRunAtMs > now)
|
|
1158
1168
|
.sort((a, b) => (a.schedule.nextRunAtMs ?? 0) - (b.schedule.nextRunAtMs ?? 0))
|
|
@@ -1193,9 +1203,9 @@ function AutomationsDashboard({ items, onSelectItem, onCreateTask, onCreateWorkf
|
|
|
1193
1203
|
return (_jsxs("div", { className: "space-y-4 px-1 pt-4", children: [_jsx("section", { className: "overflow-hidden rounded-xl border border-border/25 bg-[radial-gradient(circle_at_top_left,rgba(34,211,238,0.14),transparent_38%),radial-gradient(circle_at_top_right,rgba(34,197,94,0.12),transparent_32%),rgba(255,255,255,0.02)]", children: _jsxs("div", { className: "space-y-3 px-4 py-4 sm:px-5", children: [_jsxs("div", { className: "inline-flex items-center gap-2 rounded-full border border-border/25 bg-bg/40 px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted/70", children: [_jsx(LayoutDashboard, { className: "h-3 w-3", "aria-hidden": true }), "Overview"] }), _jsxs("div", { className: "space-y-1", children: [_jsx("h2", { className: "text-lg font-semibold text-txt", children: "Build your first automation" }), _jsx("p", { className: "text-xs-tight text-muted/80", children: "Workflows handle multi-step pipelines; tasks are simple prompts that run on a schedule or from an event." })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: "default", size: "sm", onClick: onCreateTask, children: "New task" }), _jsx(Button, { variant: "outline", size: "sm", onClick: onCreateWorkflow, children: "New workflow" })] })] }) }), _jsxs("div", { className: "grid gap-3 xl:grid-cols-2", children: [_jsx(DetailSection, { title: "Task ideas", children: _jsx("div", { className: "p-2", children: _jsx(OverviewIdeaGrid, { ideas: taskIdeas, onSelect: (idea) => onUseIdea(idea) }) }) }), _jsx(DetailSection, { title: "Workflow ideas", children: _jsx("div", { className: "p-2", children: _jsx(OverviewIdeaGrid, { ideas: workflowIdeas, onSelect: (idea) => onUseIdea(idea) }) }) })] }), draftItems.length > 0 && (_jsx(DetailSection, { title: "Drafts in progress", children: _jsx("div", { className: "divide-y divide-border/20", children: draftItems.map((item) => (_jsx(OverviewListItem, { onClick: () => onSelectItem(item), title: getOverviewDisplayTitle(item), badge: "Draft", meta: formatRelativePast(item.updatedAt, t), detail: item.description.trim() ||
|
|
1194
1204
|
"Open it and keep shaping it in the sidebar agent.", tone: "warning" }, item.id))) }) }))] }));
|
|
1195
1205
|
}
|
|
1196
|
-
return (_jsxs("div", { className: "space-y-4 px-1 pt-4", children: [_jsxs("section", { className: "grid gap-4 xl:grid-cols-[minmax(0,1.15fr)_minmax(320px,0.85fr)]", children: [_jsxs("div", { className: "rounded-xl border border-border/25 bg-[radial-gradient(circle_at_top_left,rgba(34,197,94,0.1),transparent_34%),radial-gradient(circle_at_top_right,rgba(56,189,248,0.12),transparent_30%),rgba(255,255,255,0.02)] px-4 py-4 sm:px-5", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "inline-flex items-center gap-2 rounded-full border border-border/25 bg-bg/40 px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted/70", children: [_jsx(LayoutDashboard, { className: "h-3 w-3", "aria-hidden": true }), "Overview"] }), _jsx("h2", { className: "text-lg font-semibold text-txt", children: "Automations" })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: "default", size: "sm", onClick: onCreateTask, children: "New task" }), _jsx(Button, { variant: "outline", size: "sm", onClick: onCreateWorkflow, children: "New workflow" })] })] }), _jsxs("div", { className: "mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4", children: [_jsx(OverviewMetricCard, { label: "Live", value: _jsx("span", { className: "tabular-nums", children: activeCount }), detail: activeCount > 0 ? "Ready to run" : "Nothing enabled", tone: activeCount > 0 ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "
|
|
1197
|
-
? "
|
|
1198
|
-
: "No
|
|
1206
|
+
return (_jsxs("div", { className: "space-y-4 px-1 pt-4", children: [_jsxs("section", { className: "grid gap-4 xl:grid-cols-[minmax(0,1.15fr)_minmax(320px,0.85fr)]", children: [_jsxs("div", { className: "rounded-xl border border-border/25 bg-[radial-gradient(circle_at_top_left,rgba(34,197,94,0.1),transparent_34%),radial-gradient(circle_at_top_right,rgba(56,189,248,0.12),transparent_30%),rgba(255,255,255,0.02)] px-4 py-4 sm:px-5", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "inline-flex items-center gap-2 rounded-full border border-border/25 bg-bg/40 px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted/70", children: [_jsx(LayoutDashboard, { className: "h-3 w-3", "aria-hidden": true }), "Overview"] }), _jsx("h2", { className: "text-lg font-semibold text-txt", children: "Automations" })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { variant: "default", size: "sm", onClick: onCreateTask, children: "New task" }), _jsx(Button, { variant: "outline", size: "sm", onClick: onCreateWorkflow, children: "New workflow" })] })] }), _jsxs("div", { className: "mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4", children: [_jsx(OverviewMetricCard, { label: "Live", value: _jsx("span", { className: "tabular-nums", children: activeCount }), detail: activeCount > 0 ? "Ready to run" : "Nothing enabled", tone: activeCount > 0 ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Timed", value: _jsx("span", { className: "tabular-nums", children: activeScheduleCount }), detail: activeScheduleCount > 0
|
|
1207
|
+
? "Schedules live"
|
|
1208
|
+
: "No timed runs", tone: activeScheduleCount > 0 ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Events", value: _jsx("span", { className: "tabular-nums", children: activeEventCount }), detail: activeEventCount > 0 ? "Hooks live" : "No event hooks", tone: activeEventCount > 0 ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Attention", value: _jsx("span", { className: "tabular-nums", children: attentionEntries.length }), detail: attentionEntries.length > 0 ? "Failed runs" : "Nothing urgent", tone: attentionEntries.length > 0 ? "danger" : "ok" })] })] }), _jsx(DetailSection, { title: "Next up", className: "h-full", children: nextUpcoming?.schedule.nextRunAtMs ? (_jsxs("button", { type: "button", onClick: () => onSelectItem(nextUpcoming.item), className: "flex w-full flex-col gap-2 px-4 py-4 text-left transition-colors hover:bg-bg-muted/40", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StatusDot, { tone: "success", className: "shrink-0" }), _jsx("span", { className: "truncate text-sm font-semibold text-txt", children: getOverviewDisplayTitle(nextUpcoming.item) }), _jsx("span", { className: "rounded bg-bg/50 px-1.5 py-0.5 text-[10px] uppercase tracking-[0.12em] text-muted/70", children: getAutomationGroupLabel(nextUpcoming.item) })] }), _jsx("div", { className: "pl-4 text-[11px] text-muted/70", children: scheduleLabel(nextUpcoming.schedule, t, uiLanguage) }), _jsxs("div", { className: "pl-4", children: [_jsx("div", { className: "text-lg font-semibold text-txt", children: formatRelativeFuture(nextUpcoming.schedule.nextRunAtMs, t) }), _jsx("div", { className: "mt-1 text-[11px] text-muted/70", children: formatDateTime(nextUpcoming.schedule.nextRunAtMs, {
|
|
1199
1209
|
fallback: "—",
|
|
1200
1210
|
locale: uiLanguage,
|
|
1201
1211
|
}) })] })] })) : (_jsxs("div", { className: "flex h-full min-h-[11.75rem] flex-col justify-between gap-3 px-4 py-4", children: [_jsx("div", { className: "space-y-1", children: _jsx("div", { className: "text-sm font-medium text-txt", children: "None queued." }) }), draftItems[0] ? (_jsx(Button, { variant: "outline", size: "sm", className: "w-fit", onClick: () => onSelectItem(draftItems[0]), children: "Continue draft" })) : null] })) })] }), attentionEntries.length > 0 ? (_jsx(DetailSection, { title: "Needs attention", children: _jsx("div", { className: "divide-y divide-border/20", children: attentionEntries.map((entry) => (_jsx(OverviewListItem, { onClick: () => onSelectItem(entry.item), title: entry.title, badge: entry.groupLabel, meta: entry.meta, detail: entry.detail, trailing: entry.trailing, tone: entry.tone }, entry.key))) }) })) : null, _jsxs("div", { className: "grid gap-4 xl:grid-cols-2", children: [_jsx(DetailSection, { title: "Upcoming runs", className: "h-full", children: upcoming.length > 0 ? (_jsx("div", { className: "divide-y divide-border/20", children: upcoming.map(({ key, item, schedule }) => (_jsx(OverviewListItem, { onClick: () => onSelectItem(item), title: getOverviewDisplayTitle(item), badge: getAutomationGroupLabel(item), meta: scheduleLabel(schedule, t, uiLanguage), detail: formatDateTime(schedule.nextRunAtMs ?? null, {
|
|
@@ -1286,7 +1296,9 @@ function TriggerAutomationDetailPane({ automation, onPromoteToWorkflow, }) {
|
|
|
1286
1296
|
return counts;
|
|
1287
1297
|
}, { failureCount: 0, successCount: 0 });
|
|
1288
1298
|
const nextRunLabel = trigger.nextRunAtMs
|
|
1289
|
-
?
|
|
1299
|
+
? trigger.triggerType === "event"
|
|
1300
|
+
? `On ${humanizeEventKind(trigger.eventKind ?? "event")}`
|
|
1301
|
+
: formatRelativeFuture(trigger.nextRunAtMs, t)
|
|
1290
1302
|
: "Event or manual";
|
|
1291
1303
|
const whatRuns = trigger.kind === "workflow"
|
|
1292
1304
|
? trigger.workflowName || "Selected workflow"
|
|
@@ -1300,10 +1312,14 @@ function TriggerAutomationDetailPane({ automation, onPromoteToWorkflow, }) {
|
|
|
1300
1312
|
setEditingId(null);
|
|
1301
1313
|
setSelectedItemId(null);
|
|
1302
1314
|
setSelectedItemKind(null);
|
|
1303
|
-
}, icon: _jsx(Copy, { className: "h-3.5 w-3.5" }) }), _jsx(IconAction, { label: "Compile to Workflow", onClick: () => void onPromoteToWorkflow(automation), icon: _jsx(GitBranch, { className: "h-3.5 w-3.5" }) })] }) }), _jsxs("div", { className: "grid gap-2 sm:grid-cols-2 xl:grid-cols-5", children: [_jsx(OverviewMetricCard, { label: "Runs", value: _jsx("span", { className: "tabular-nums", children: selectedRuns.length }), detail: `${successCount} successful · ${failureCount} failed`, tone: failureCount > 0 ? "danger" : successCount > 0 ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Starts", value: getTriggerStartModeLabel(trigger), detail: scheduleLabel(trigger, t, uiLanguage) }), _jsx(OverviewMetricCard, { label: "When it fires", value: getTriggerWakeModeLabel(trigger), detail: trigger.enabled ? "Enabled" : "Paused", tone: trigger.enabled ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Next run", value: nextRunLabel, detail:
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1315
|
+
}, icon: _jsx(Copy, { className: "h-3.5 w-3.5" }) }), _jsx(IconAction, { label: "Compile to Workflow", onClick: () => void onPromoteToWorkflow(automation), icon: _jsx(GitBranch, { className: "h-3.5 w-3.5" }) })] }) }), _jsxs("div", { className: "grid gap-2 sm:grid-cols-2 xl:grid-cols-5", children: [_jsx(OverviewMetricCard, { label: "Runs", value: _jsx("span", { className: "tabular-nums", children: selectedRuns.length }), detail: `${successCount} successful · ${failureCount} failed`, tone: failureCount > 0 ? "danger" : successCount > 0 ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Starts", value: getTriggerStartModeLabel(trigger), detail: scheduleLabel(trigger, t, uiLanguage) }), _jsx(OverviewMetricCard, { label: "When it fires", value: getTriggerWakeModeLabel(trigger), detail: trigger.enabled ? "Enabled" : "Paused", tone: trigger.enabled ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Next run", value: nextRunLabel, detail: trigger.triggerType === "event"
|
|
1316
|
+
? "Waiting for event input"
|
|
1317
|
+
: formatDateTime(trigger.nextRunAtMs, {
|
|
1318
|
+
fallback: "No time-based run queued",
|
|
1319
|
+
locale: uiLanguage,
|
|
1320
|
+
}), tone: trigger.nextRunAtMs || trigger.triggerType === "event"
|
|
1321
|
+
? "ok"
|
|
1322
|
+
: "default" }), _jsx(OverviewMetricCard, { label: "Last run", value: formatRelativePast(trigger.lastRunAtIso, t), detail: formatDateTime(trigger.lastRunAtIso, {
|
|
1307
1323
|
fallback: "Not run yet",
|
|
1308
1324
|
locale: uiLanguage,
|
|
1309
1325
|
}) })] }), _jsx(DetailSection, { title: trigger.kind === "workflow" ? "Runs this workflow" : "Prompt", children: _jsx("div", { className: "min-h-[8rem] px-4 py-4 text-sm leading-relaxed text-muted/85 whitespace-pre-wrap", children: whatRuns }) }), _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,1fr)_minmax(320px,0.95fr)]", children: [_jsx(DetailSection, { title: "Run history", className: "h-full", action: _jsx(IconAction, { label: t("common.refresh"), onClick: () => void loadTriggerRuns(trigger.id), icon: _jsx(RefreshCw, { className: "h-3.5 w-3.5" }) }), children: !hasLoadedRuns ? (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 text-xs-tight text-muted/70", children: [_jsx("div", { className: "h-3 w-3 animate-spin rounded-full border-2 border-muted/30 border-t-muted/80" }), t("databaseview.Loading")] })) : selectedRuns.length === 0 ? (_jsx("div", { className: "px-3 py-3 text-xs-tight text-muted/60", children: "No runs yet." })) : (_jsx("div", { className: "divide-y divide-border/20", children: selectedRuns.map((run) => (_jsxs("div", { className: "flex flex-wrap items-center gap-2 px-3 py-2 text-xs-tight", children: [_jsx(StatusBadge, { label: localizedExecutionStatus(run.status, t), variant: toneForLastStatus(run.status) }), _jsx("span", { className: "text-muted/70 tabular-nums", children: formatDateTime(run.startedAt, { locale: uiLanguage }) }), _jsx("span", { className: "text-muted/60", children: formatDurationMs(run.latencyMs, { t }) }), _jsx("span", { className: "ml-auto rounded bg-bg/40 px-1 py-0.5 font-mono text-[10px] text-muted/60", children: run.source }), run.error ? (_jsx("div", { className: "basis-full whitespace-pre-wrap rounded border border-danger/20 bg-danger/10 px-2 py-1 font-mono text-[11px] text-danger/90", children: run.error })) : null] }, run.triggerRunId))) })) }), _jsx(DetailSection, { title: "Schedule & behavior", className: "h-full", children: _jsx(DetailFactList, { items: [
|
|
@@ -1315,6 +1331,16 @@ function TriggerAutomationDetailPane({ automation, onPromoteToWorkflow, }) {
|
|
|
1315
1331
|
label: "Trigger type",
|
|
1316
1332
|
value: getTriggerStartModeLabel(trigger),
|
|
1317
1333
|
},
|
|
1334
|
+
...(trigger.triggerType === "event"
|
|
1335
|
+
? [
|
|
1336
|
+
{
|
|
1337
|
+
label: "Event",
|
|
1338
|
+
value: trigger.eventKind
|
|
1339
|
+
? humanizeEventKind(trigger.eventKind)
|
|
1340
|
+
: "Unknown",
|
|
1341
|
+
},
|
|
1342
|
+
]
|
|
1343
|
+
: []),
|
|
1318
1344
|
{
|
|
1319
1345
|
label: "Wake mode",
|
|
1320
1346
|
value: getTriggerWakeModeLabel(trigger),
|
|
@@ -1346,6 +1372,7 @@ function WorkflowAutomationDetailPane({ automation, n8nStatus, workflowFetchErro
|
|
|
1346
1372
|
getWorkflowNodeCount(automation);
|
|
1347
1373
|
const workflowIsActive = graphWorkflow?.active ?? automation.enabled;
|
|
1348
1374
|
const nextWorkflowRun = automation.schedules
|
|
1375
|
+
.filter(isTimeBasedTrigger)
|
|
1349
1376
|
.map((schedule) => schedule.nextRunAtMs ?? 0)
|
|
1350
1377
|
.filter((value) => value > 0)
|
|
1351
1378
|
.sort((left, right) => left - right)[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeartbeatForm.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/HeartbeatForm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEpE,OAAO,
|
|
1
|
+
{"version":3,"file":"HeartbeatForm.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/HeartbeatForm.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEpE,OAAO,EASL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AA2B3B,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,IAAI,EAAE,gBAAgB,CAAC;IACvB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,wDAAwD;IACxD,aAAa,EAAE,OAAO,CAAC;IACvB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,qDAAqD;IACrD,cAAc,EAAE,OAAO,CAAC;IACxB,mCAAmC;IACnC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACxE,4BAA4B;IAC5B,CAAC,EAAE,WAAW,CAAC;IACf,qCAAqC;IACrC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qCAAqC;IACrC,QAAQ,EAAE,CAAC,CAAC,SAAS,MAAM,gBAAgB,EACzC,GAAG,EAAE,CAAC,EACN,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,KACvB,IAAI,CAAC;IACV,qCAAqC;IACrC,OAAO,EAAE,CACP,IAAI,EAAE,gBAAgB,GAAG,CAAC,CAAC,IAAI,EAAE,gBAAgB,KAAK,gBAAgB,CAAC,KACpE,IAAI,CAAC;IACV,8BAA8B;IAC9B,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,8BAA8B;IAC9B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,iCAAiC;IACjC,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,wCAAwC;IACxC,sBAAsB,EAAE,CACtB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,OAAO,KACtB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,2CAA2C;IAC3C,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,sCAAsC;IACtC,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,SAAS,EACT,aAAa,EACb,UAAU,EACV,SAAS,EACT,cAAc,EACd,cAAc,EACd,QAAQ,EACR,eAAe,EACf,CAAC,EACD,iBAAiB,EACjB,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,oBAAoB,EACpB,sBAAsB,EACtB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,GAChB,EAAE,kBAAkB,2CAkTpB"}
|
|
@@ -3,7 +3,29 @@ import { Button, FieldLabel, FieldSwitch, FormSelect, FormSelectItem, Input, Pag
|
|
|
3
3
|
import { useEffect, useMemo, useState } from "react";
|
|
4
4
|
import { client } from "../../api";
|
|
5
5
|
import { formatDateTime, formatDurationMs } from "../../utils/format";
|
|
6
|
-
import { DURATION_UNITS, durationToMs, durationUnitLabel, formFromTrigger, localizedExecutionStatus, nextRunsForCron, nextRunsForInterval, validateCronExpression, } from "./heartbeat-utils";
|
|
6
|
+
import { DURATION_UNITS, durationToMs, durationUnitLabel, formFromTrigger, humanizeEventKind, localizedExecutionStatus, nextRunsForCron, nextRunsForInterval, validateCronExpression, } from "./heartbeat-utils";
|
|
7
|
+
const EVENT_KIND_OPTIONS = [
|
|
8
|
+
{
|
|
9
|
+
value: "message.received",
|
|
10
|
+
label: "Message received",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
value: "discord.message.received",
|
|
14
|
+
label: "Discord message",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
value: "telegram.message.received",
|
|
18
|
+
label: "Telegram message",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
value: "gmail.message.received",
|
|
22
|
+
label: "Gmail message",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
value: "calendar.event.ended",
|
|
26
|
+
label: "Calendar event ended",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
7
29
|
export function HeartbeatForm({ form, editingId, editorEnabled, modalTitle, formError, triggersSaving, templateNotice, triggers, triggerRunsById, t, selectedTriggerId, setField, setForm, setFormError, closeEditor, onSubmit, onDelete, onRunSelectedTrigger, onToggleTriggerEnabled, saveFormAsTemplate, loadTriggerRuns, kickerLabelCreate, kickerLabelEdit, submitLabelCreate, submitLabelEdit, }) {
|
|
8
30
|
const cronInvalid = form.triggerType === "cron" &&
|
|
9
31
|
!validateCronExpression(form.cronExpression).ok;
|
|
@@ -15,7 +37,7 @@ export function HeartbeatForm({ form, editingId, editorEnabled, modalTitle, form
|
|
|
15
37
|
window.dispatchEvent(new CustomEvent("milady:automations:setFilter", {
|
|
16
38
|
detail: { filter: "workflows" },
|
|
17
39
|
}));
|
|
18
|
-
} })] }), _jsxs("div", { className: "grid gap-4 rounded-xl border border-border/30 bg-bg/20 p-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-[0.14em] text-muted", children: "When it starts" }), _jsxs("div", { className: "grid grid-cols-1 gap-5 lg:grid-cols-2", children: [_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Trigger type" }), _jsxs(FormSelect, { value: form.triggerType, onValueChange: (value) => setField("triggerType", value), placeholder: "Repeating interval", children: [_jsx(FormSelectItem, { value: "interval", children: "Repeating interval" }), _jsx(FormSelectItem, { value: "once", children: "One time" }), _jsx(FormSelectItem, { value: "cron", children: "Cron schedule" })] })] }), _jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "When it fires" }), _jsxs(FormSelect, { value: form.wakeMode, onValueChange: (value) => setField("wakeMode", value), placeholder: "Interrupt and run now", children: [_jsx(FormSelectItem, { value: "inject_now", children: "Interrupt and run now" }), _jsx(FormSelectItem, { value: "next_autonomy_cycle", children: "Queue for next cycle" })] })] })] }), form.triggerType === "interval" && (_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Repeat every" }), _jsxs("div", { className: "grid grid-cols-[140px_minmax(0,1fr)] gap-3", children: [_jsx(Input, { type: "number", min: "1", variant: "form", value: form.durationValue, onChange: (event) => setField("durationValue", event.target.value), placeholder: "1" }), _jsx(FormSelect, { value: form.durationUnit, onValueChange: (value) => setField("durationUnit", value), placeholder: durationUnitLabel(form.durationUnit, t), children: DURATION_UNITS.map((unit) => (_jsx(FormSelectItem, { value: unit.unit, children: durationUnitLabel(unit.unit, t) }, unit.unit))) })] })] })), form.triggerType === "once" && (_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Run at" }), _jsx(Input, { type: "datetime-local", variant: "form", value: form.scheduledAtIso, onChange: (event) => setField("scheduledAtIso", event.target.value) })] })), form.triggerType === "cron" && (_jsx(CronInputSection, { form: form, setField: setField, t: t })), _jsx(SchedulePreview, { form: form, t: t })] }), _jsxs("div", { className: "grid gap-4 rounded-xl border border-border/30 bg-bg/20 p-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-[0.14em] text-muted", children: "Run behavior" }), _jsxs("div", { className: "grid grid-cols-1 gap-5 lg:grid-cols-2", children: [_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Stop after" }), _jsx(Input, { variant: "form", value: form.maxRuns, onChange: (event) => setField("maxRuns", event.target.value), placeholder: "Unlimited" })] }), _jsx("div", { className: "flex items-end", children: _jsx(FieldSwitch, { checked: form.enabled, "aria-label": "Enabled", className: "flex-1", label: "Enabled", onCheckedChange: (checked) => setField("enabled", checked) }) })] })] })] }), _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [form.displayName.trim() && (_jsx("button", { type: "button", className: "text-xs font-medium text-muted transition-colors hover:text-accent underline-offset-2 hover:underline", onClick: saveFormAsTemplate, children: t("heartbeatsview.SaveAsTemplate", {
|
|
40
|
+
} })] }), _jsxs("div", { className: "grid gap-4 rounded-xl border border-border/30 bg-bg/20 p-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-[0.14em] text-muted", children: "When it starts" }), _jsxs("div", { className: "grid grid-cols-1 gap-5 lg:grid-cols-2", children: [_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Trigger type" }), _jsxs(FormSelect, { value: form.triggerType, onValueChange: (value) => setField("triggerType", value), placeholder: "Repeating interval", children: [_jsx(FormSelectItem, { value: "interval", children: "Repeating interval" }), _jsx(FormSelectItem, { value: "once", children: "One time" }), _jsx(FormSelectItem, { value: "cron", children: "Cron schedule" }), _jsx(FormSelectItem, { value: "event", children: "Event" })] })] }), _jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "When it fires" }), _jsxs(FormSelect, { value: form.wakeMode, onValueChange: (value) => setField("wakeMode", value), placeholder: "Interrupt and run now", children: [_jsx(FormSelectItem, { value: "inject_now", children: "Interrupt and run now" }), _jsx(FormSelectItem, { value: "next_autonomy_cycle", children: "Queue for next cycle" })] })] })] }), form.triggerType === "interval" && (_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Repeat every" }), _jsxs("div", { className: "grid grid-cols-[140px_minmax(0,1fr)] gap-3", children: [_jsx(Input, { type: "number", min: "1", variant: "form", value: form.durationValue, onChange: (event) => setField("durationValue", event.target.value), placeholder: "1" }), _jsx(FormSelect, { value: form.durationUnit, onValueChange: (value) => setField("durationUnit", value), placeholder: durationUnitLabel(form.durationUnit, t), children: DURATION_UNITS.map((unit) => (_jsx(FormSelectItem, { value: unit.unit, children: durationUnitLabel(unit.unit, t) }, unit.unit))) })] })] })), form.triggerType === "once" && (_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Run at" }), _jsx(Input, { type: "datetime-local", variant: "form", value: form.scheduledAtIso, onChange: (event) => setField("scheduledAtIso", event.target.value) })] })), form.triggerType === "cron" && (_jsx(CronInputSection, { form: form, setField: setField, t: t })), form.triggerType === "event" && (_jsx(EventInputSection, { form: form, setField: setField })), _jsx(SchedulePreview, { form: form, t: t })] }), _jsxs("div", { className: "grid gap-4 rounded-xl border border-border/30 bg-bg/20 p-4", children: [_jsx("div", { className: "text-xs font-semibold uppercase tracking-[0.14em] text-muted", children: "Run behavior" }), _jsxs("div", { className: "grid grid-cols-1 gap-5 lg:grid-cols-2", children: [_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Stop after" }), _jsx(Input, { variant: "form", value: form.maxRuns, onChange: (event) => setField("maxRuns", event.target.value), placeholder: "Unlimited" })] }), _jsx("div", { className: "flex items-end", children: _jsx(FieldSwitch, { checked: form.enabled, "aria-label": "Enabled", className: "flex-1", label: "Enabled", onCheckedChange: (checked) => setField("enabled", checked) }) })] })] })] }), _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [form.displayName.trim() && (_jsx("button", { type: "button", className: "text-xs font-medium text-muted transition-colors hover:text-accent underline-offset-2 hover:underline", onClick: saveFormAsTemplate, children: t("heartbeatsview.SaveAsTemplate", {
|
|
19
41
|
defaultValue: "Save as template",
|
|
20
42
|
}) })), _jsxs("div", { className: "flex flex-wrap items-center gap-2.5", children: [_jsx(Button, { variant: "default", size: "sm", className: "h-10 px-6 text-sm text-white shadow-sm hover:text-white dark:text-white dark:hover:text-white", disabled: triggersSaving ||
|
|
21
43
|
(form.kind === "workflow" && !form.workflowId) ||
|
|
@@ -94,6 +116,16 @@ function CronInputSection({ form, setField, t, }) {
|
|
|
94
116
|
const isInvalid = !validationResult.ok;
|
|
95
117
|
return (_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Cron schedule" }), _jsx(Input, { variant: "form", className: "font-mono", value: form.cronExpression, onChange: (event) => setField("cronExpression", event.target.value), placeholder: "*/15 * * * *", "aria-invalid": isInvalid, "aria-describedby": isInvalid ? cronErrorId : undefined }), isInvalid ? (_jsxs("p", { id: cronErrorId, className: "mt-1.5 text-xs font-medium text-danger", role: "alert", children: [t("triggers.cronError"), " ", validationResult.message] })) : (_jsx("div", { className: "mt-2 text-xs-tight text-muted", children: "minute hour day month weekday" })), _jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-1.5", children: [_jsx("span", { className: "text-xs text-muted", children: t("triggers.cronExampleHint") }), CRON_EXAMPLES.map(({ expr, labelKey }) => (_jsx(Button, { variant: "outline", size: "sm", className: "h-6 px-2 py-0 text-xs font-mono", onClick: () => setField("cronExpression", expr), children: t(labelKey) }, expr)))] })] }));
|
|
96
118
|
}
|
|
119
|
+
function EventInputSection({ form, setField, }) {
|
|
120
|
+
const isCustomEvent = !EVENT_KIND_OPTIONS.some((option) => option.value === form.eventKind);
|
|
121
|
+
return (_jsxs("div", { className: "grid gap-3", children: [_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Event" }), _jsxs(FormSelect, { value: isCustomEvent ? "__custom" : form.eventKind, onValueChange: (value) => {
|
|
122
|
+
if (value === "__custom") {
|
|
123
|
+
setField("eventKind", "");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
setField("eventKind", value);
|
|
127
|
+
}, placeholder: "Message received", children: [EVENT_KIND_OPTIONS.map((option) => (_jsx(FormSelectItem, { value: option.value, children: option.label }, option.value))), _jsx(FormSelectItem, { value: "__custom", children: "Custom event" })] })] }), isCustomEvent && (_jsxs("div", { children: [_jsx(FieldLabel, { variant: "form", children: "Event name" }), _jsx(Input, { variant: "form", className: "font-mono", value: form.eventKind, onChange: (event) => setField("eventKind", event.target.value), placeholder: "namespace.subject.verb" })] })), form.eventKind.trim() && (_jsxs("div", { className: "rounded-lg border border-border/30 bg-bg/30 px-4 py-3 text-xs text-muted", children: ["Runs when ", _jsx("span", { className: "font-medium text-txt", children: humanizeEventKind(form.eventKind) }), " arrives."] }))] }));
|
|
128
|
+
}
|
|
97
129
|
// ── Schedule preview ("Next runs: …") ────────────────────────────
|
|
98
130
|
function SchedulePreview({ form, t, }) {
|
|
99
131
|
const preview = useMemo(() => {
|
|
@@ -127,6 +159,12 @@ function SchedulePreview({ form, t, }) {
|
|
|
127
159
|
return null;
|
|
128
160
|
return { kind: "dates", dates };
|
|
129
161
|
}
|
|
162
|
+
if (form.triggerType === "event") {
|
|
163
|
+
return {
|
|
164
|
+
kind: "event",
|
|
165
|
+
label: humanizeEventKind(form.eventKind || "event"),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
130
168
|
return null;
|
|
131
169
|
}, [
|
|
132
170
|
form.triggerType,
|
|
@@ -134,13 +172,14 @@ function SchedulePreview({ form, t, }) {
|
|
|
134
172
|
form.durationUnit,
|
|
135
173
|
form.scheduledAtIso,
|
|
136
174
|
form.cronExpression,
|
|
175
|
+
form.eventKind,
|
|
137
176
|
t,
|
|
138
177
|
]);
|
|
139
178
|
if (!preview)
|
|
140
179
|
return null;
|
|
141
180
|
return (_jsx("div", { role: "status", "aria-live": "polite", className: "rounded-lg border border-border/30 bg-bg/30 px-4 py-3 text-sm", children: preview.kind === "error" ? (_jsx("p", { className: "text-xs font-medium text-danger", children: preview.message })) : preview.kind === "once" ? (_jsxs("div", { children: [preview.isPast && (_jsx("p", { className: "mb-1 text-xs font-medium text-warning", children: t("triggers.scheduleOnceInPast") })), _jsx("p", { className: "text-xs text-muted", children: t("triggers.scheduleOnceLabel", {
|
|
142
181
|
time: formatDateTime(preview.date),
|
|
143
|
-
}) })] })) : (_jsxs("div", { children: [_jsx("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted", children: "Next runs" }), _jsx("ul", { className: "space-y-0.5", children: preview.dates.map((date) => (_jsx("li", { className: "text-xs text-txt/80 before:mr-1.5 before:content-['\u2022']", children: formatDateTime(date) }, date.getTime()))) })] })) }));
|
|
182
|
+
}) })] })) : preview.kind === "event" ? (_jsxs("p", { className: "text-xs text-muted", children: ["Waiting for ", _jsx("span", { className: "font-medium text-txt", children: preview.label }), "."] })) : (_jsxs("div", { children: [_jsx("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted", children: "Next runs" }), _jsx("ul", { className: "space-y-0.5", children: preview.dates.map((date) => (_jsx("li", { className: "text-xs text-txt/80 before:mr-1.5 before:content-['\u2022']", children: formatDateTime(date) }, date.getTime()))) })] })) }));
|
|
144
183
|
}
|
|
145
184
|
// ── Run history sub-section (shown when editing) ───────────────────
|
|
146
185
|
function HeartbeatRunHistory({ editingId, triggers, triggerRunsById, loadTriggerRuns, t, }) {
|
|
@@ -39,6 +39,7 @@ export interface TriggerFormState {
|
|
|
39
39
|
workflowId: string;
|
|
40
40
|
workflowName: string;
|
|
41
41
|
triggerType: TriggerType;
|
|
42
|
+
eventKind: string;
|
|
42
43
|
wakeMode: TriggerWakeMode;
|
|
43
44
|
scheduledAtIso: string;
|
|
44
45
|
cronExpression: string;
|
|
@@ -67,6 +68,7 @@ export declare function getTemplateInstructions(template: HeartbeatTemplate, t:
|
|
|
67
68
|
export declare function railMonogram(label: string): string;
|
|
68
69
|
export declare function parsePositiveInteger(value: string): number | undefined;
|
|
69
70
|
export declare function scheduleLabel(trigger: TriggerSummary, t: TranslateFn, locale?: string): string;
|
|
71
|
+
export declare function humanizeEventKind(value: string): string;
|
|
70
72
|
export declare function formFromTrigger(trigger: TriggerSummary): TriggerFormState;
|
|
71
73
|
export declare function buildCreateRequest(form: TriggerFormState): CreateTriggerRequest;
|
|
72
74
|
export declare function buildUpdateRequest(form: TriggerFormState): UpdateTriggerRequest;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heartbeat-utils.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/heartbeat-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,eAAe,EACf,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAG9C,OAAO,KAAK,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AAKjE,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC;AAIzC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;EAqBjB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAQ7E;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAGtE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,GAAG,MAAM,CAG5E;AAID,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"heartbeat-utils.d.ts","sourceRoot":"","sources":["../../../../../../src/components/pages/heartbeat-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,6 +53,7 @@ export const emptyForm = {
|
|
|
53
53
|
workflowId: "",
|
|
54
54
|
workflowName: "",
|
|
55
55
|
triggerType: "interval",
|
|
56
|
+
eventKind: "message.received",
|
|
56
57
|
wakeMode: "inject_now",
|
|
57
58
|
scheduledAtIso: "",
|
|
58
59
|
cronExpression: "0 * * * *",
|
|
@@ -163,8 +164,20 @@ export function scheduleLabel(trigger, t, locale) {
|
|
|
163
164
|
if (trigger.triggerType === "cron") {
|
|
164
165
|
return `${t("heartbeatsview.cronPrefix")} ${trigger.cronExpression ?? "\u2014"}`;
|
|
165
166
|
}
|
|
167
|
+
if (trigger.triggerType === "event") {
|
|
168
|
+
return `On ${humanizeEventKind(trigger.eventKind ?? "event")}`;
|
|
169
|
+
}
|
|
166
170
|
return trigger.triggerType;
|
|
167
171
|
}
|
|
172
|
+
export function humanizeEventKind(value) {
|
|
173
|
+
return value
|
|
174
|
+
.trim()
|
|
175
|
+
.replace(/[_-]+/g, ".")
|
|
176
|
+
.split(".")
|
|
177
|
+
.filter(Boolean)
|
|
178
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
179
|
+
.join(" ");
|
|
180
|
+
}
|
|
168
181
|
export function formFromTrigger(trigger) {
|
|
169
182
|
const intervalMs = trigger.intervalMs ?? 3_600_000;
|
|
170
183
|
const { value, unit } = bestFitUnit(intervalMs);
|
|
@@ -175,6 +188,7 @@ export function formFromTrigger(trigger) {
|
|
|
175
188
|
workflowId: trigger.workflowId ?? "",
|
|
176
189
|
workflowName: trigger.workflowName ?? "",
|
|
177
190
|
triggerType: trigger.triggerType,
|
|
191
|
+
eventKind: trigger.eventKind ?? "message.received",
|
|
178
192
|
wakeMode: trigger.wakeMode,
|
|
179
193
|
scheduledAtIso: trigger.scheduledAtIso ?? "",
|
|
180
194
|
cronExpression: trigger.cronExpression ?? "0 * * * *",
|
|
@@ -200,6 +214,7 @@ export function buildCreateRequest(form) {
|
|
|
200
214
|
: undefined,
|
|
201
215
|
scheduledAtIso: form.triggerType === "once" ? form.scheduledAtIso.trim() : undefined,
|
|
202
216
|
cronExpression: form.triggerType === "cron" ? form.cronExpression.trim() : undefined,
|
|
217
|
+
eventKind: form.triggerType === "event" ? form.eventKind.trim() : undefined,
|
|
203
218
|
maxRuns,
|
|
204
219
|
};
|
|
205
220
|
}
|
|
@@ -310,6 +325,9 @@ export function validateForm(form, t) {
|
|
|
310
325
|
return `${t("triggers.cronError")} ${cronResult.message}`;
|
|
311
326
|
}
|
|
312
327
|
}
|
|
328
|
+
if (form.triggerType === "event" && !form.eventKind.trim()) {
|
|
329
|
+
return "Event is required.";
|
|
330
|
+
}
|
|
313
331
|
if (form.maxRuns.trim() && !parsePositiveInteger(form.maxRuns)) {
|
|
314
332
|
return t("heartbeatsview.validationMaxRunsPositive");
|
|
315
333
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UUID } from "./primitives";
|
|
2
2
|
export declare const TRIGGER_SCHEMA_VERSION: 1;
|
|
3
|
-
export type TriggerType = "interval" | "once" | "cron";
|
|
3
|
+
export type TriggerType = "interval" | "once" | "cron" | "event";
|
|
4
4
|
export type TriggerWakeMode = "inject_now" | "next_autonomy_cycle";
|
|
5
5
|
export type TriggerLastStatus = "success" | "error" | "skipped";
|
|
6
6
|
export type TriggerKind = "text" | "workflow";
|
|
@@ -17,6 +17,7 @@ export interface TriggerConfig {
|
|
|
17
17
|
intervalMs?: number;
|
|
18
18
|
scheduledAtIso?: string;
|
|
19
19
|
cronExpression?: string;
|
|
20
|
+
eventKind?: string;
|
|
20
21
|
maxRuns?: number;
|
|
21
22
|
runCount: number;
|
|
22
23
|
nextRunAtMs?: number;
|
|
@@ -37,6 +38,7 @@ export interface TriggerRunRecord {
|
|
|
37
38
|
status: TriggerLastStatus;
|
|
38
39
|
error?: string;
|
|
39
40
|
latencyMs: number;
|
|
40
|
-
source: "scheduler" | "manual";
|
|
41
|
+
source: "scheduler" | "manual" | "event";
|
|
42
|
+
eventKind?: string;
|
|
41
43
|
}
|
|
42
44
|
//# sourceMappingURL=trigger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../../../../../typescript/src/types/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../../../../../typescript/src/types/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAEjD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACjE,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,qBAAqB,CAAC;AACnE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAChC,YAAY,EAAE,IAAI,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB"}
|