@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/app-core",
3
- "version": "2.0.0-alpha.337",
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.337",
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.337",
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.337",
485
- "@elizaos/ui": "^2.0.0-alpha.337",
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",
@@ -14,6 +14,7 @@ interface TriggerDraftInput {
14
14
  intervalMs?: number;
15
15
  scheduledAtIso?: string;
16
16
  cronExpression?: string;
17
+ eventKind?: string;
17
18
  maxRuns?: number;
18
19
  kind?: TriggerKind;
19
20
  workflowId?: string;
@@ -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;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;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;AAoID,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CAsMjC;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,CAoCtE;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAsChC"}
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 instructionText = `[Heartbeat: ${trigger.displayName}]\n${trigger.instructions}`;
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":"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"}
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;AA2yBhE,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,OAAO,CAAC,CAiClB"}
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 = workflow?.active ?? fallback.trigger?.enabled ?? false;
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
- : "Workflow automation.");
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: false,
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;AAi8JH,wBAAgB,eAAe,4CAO9B;AAED,wBAAgB,uBAAuB,4CAmBtC"}
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 draftCount = visibleItems.filter((item) => item.isDraft).length;
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: "Scheduled", value: _jsx("span", { className: "tabular-nums", children: activeScheduleCount }), detail: activeScheduleCount > 0
1197
- ? "Time-based runs live"
1198
- : "No live schedule", tone: activeScheduleCount > 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(OverviewMetricCard, { label: "Drafts", value: _jsx("span", { className: "tabular-nums", children: draftCount }), detail: draftCount > 0 ? "Still being shaped" : "Nothing in progress", tone: draftCount > 0 ? "warning" : "default" })] })] }), _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, {
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
- ? formatRelativeFuture(trigger.nextRunAtMs, t)
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: formatDateTime(trigger.nextRunAtMs, {
1304
- fallback: "No time-based run queued",
1305
- locale: uiLanguage,
1306
- }), tone: trigger.nextRunAtMs ? "ok" : "default" }), _jsx(OverviewMetricCard, { label: "Last run", value: formatRelativePast(trigger.lastRunAtIso, t), detail: formatDateTime(trigger.lastRunAtIso, {
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,EAQL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAI3B,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,2CA6SpB"}
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":"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"}
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;AACvD,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,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,CAAC;CAC/B"}
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"}