@elizaos/agent 2.0.0-alpha.211 → 2.0.0-alpha.213

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/apps/app-lifeops/src/actions/intent-sync.d.ts.map +1 -1
  2. package/apps/app-lifeops/src/actions/intent-sync.js +4 -41
  3. package/apps/app-lifeops/src/actions/password-manager.d.ts.map +1 -1
  4. package/apps/app-lifeops/src/actions/password-manager.js +1 -32
  5. package/apps/app-lifeops/src/actions/remote-desktop.d.ts.map +1 -1
  6. package/apps/app-lifeops/src/actions/remote-desktop.js +1 -40
  7. package/apps/app-lifeops/src/actions/screen-time.d.ts.map +1 -1
  8. package/apps/app-lifeops/src/actions/screen-time.js +1 -20
  9. package/apps/app-lifeops/src/actions/subscriptions.d.ts.map +1 -1
  10. package/apps/app-lifeops/src/actions/subscriptions.js +23 -84
  11. package/apps/app-lifeops/src/lifeops/repository.d.ts +14 -0
  12. package/apps/app-lifeops/src/lifeops/repository.d.ts.map +1 -1
  13. package/apps/app-lifeops/src/lifeops/repository.js +25 -0
  14. package/apps/app-lifeops/src/lifeops/service-helpers-browser.d.ts.map +1 -1
  15. package/apps/app-lifeops/src/lifeops/service-helpers-browser.js +8 -0
  16. package/apps/app-lifeops/src/lifeops/service-mixin-reminders.js +5 -1
  17. package/apps/app-lifeops/src/lifeops/service-mixin-workflows.d.ts +2 -1
  18. package/apps/app-lifeops/src/lifeops/service-mixin-workflows.d.ts.map +1 -1
  19. package/apps/app-lifeops/src/lifeops/service-mixin-workflows.js +187 -13
  20. package/apps/app-lifeops/src/lifeops/service-normalize-connector.d.ts.map +1 -1
  21. package/apps/app-lifeops/src/lifeops/service-normalize-connector.js +52 -1
  22. package/apps/app-lifeops/src/lifeops/service-types.d.ts +8 -0
  23. package/apps/app-lifeops/src/lifeops/service-types.d.ts.map +1 -1
  24. package/apps/app-lifeops/src/lifeops/service.d.ts +5 -0
  25. package/apps/app-lifeops/src/lifeops/service.d.ts.map +1 -1
  26. package/package.json +4 -4
  27. package/packages/agent/src/runtime/eliza.js +2 -2
  28. package/packages/shared/src/contracts/lifeops.d.ts +29 -1
  29. package/packages/shared/src/contracts/lifeops.d.ts.map +1 -1
  30. package/packages/shared/src/contracts/lifeops.js +14 -1
@@ -19,7 +19,7 @@ export function withWorkflows(Base) {
19
19
  return null;
20
20
  }
21
21
  const schedule = workflow.schedule;
22
- if (schedule.kind === "manual") {
22
+ if (schedule.kind === "manual" || schedule.kind === "event") {
23
23
  return null;
24
24
  }
25
25
  if (schedule.kind === "once") {
@@ -50,29 +50,53 @@ export function withWorkflows(Base) {
50
50
  };
51
51
  }
52
52
  initializeWorkflowSchedulerState(workflow) {
53
- const nextDueAt = this.computeWorkflowNextDueAt(workflow);
54
53
  const currentState = this.readWorkflowSchedulerState(workflow);
55
- const targetState = workflow.triggerType !== "schedule" || workflow.schedule.kind === "manual"
56
- ? null
57
- : {
58
- managedBy: "task_worker",
59
- nextDueAt,
60
- lastDueAt: null,
61
- lastRunId: null,
62
- lastRunStatus: null,
63
- updatedAt: new Date().toISOString(),
64
- };
54
+ const targetState = this.buildInitialSchedulerState(workflow);
65
55
  if ((currentState === null && targetState === null) ||
66
56
  (currentState &&
67
57
  targetState &&
68
58
  currentState.nextDueAt === targetState.nextDueAt &&
69
59
  currentState.lastDueAt === targetState.lastDueAt &&
70
60
  currentState.lastRunId === targetState.lastRunId &&
71
- currentState.lastRunStatus === targetState.lastRunStatus)) {
61
+ currentState.lastRunStatus === targetState.lastRunStatus &&
62
+ (currentState.lastFiredEventEndAt ?? null) ===
63
+ (targetState.lastFiredEventEndAt ?? null) &&
64
+ (currentState.lastFiredEventId ?? null) ===
65
+ (targetState.lastFiredEventId ?? null))) {
72
66
  return workflow;
73
67
  }
74
68
  return this.withWorkflowSchedulerState(workflow, targetState);
75
69
  }
70
+ buildInitialSchedulerState(workflow) {
71
+ if (workflow.triggerType === "manual") {
72
+ return null;
73
+ }
74
+ if (workflow.triggerType === "event") {
75
+ // Anchor the cursor at workflow creation so we never fire for events
76
+ // that ended before the workflow existed.
77
+ return {
78
+ managedBy: "task_worker",
79
+ nextDueAt: null,
80
+ lastDueAt: null,
81
+ lastRunId: null,
82
+ lastRunStatus: null,
83
+ updatedAt: new Date().toISOString(),
84
+ lastFiredEventEndAt: workflow.createdAt,
85
+ lastFiredEventId: null,
86
+ };
87
+ }
88
+ if (workflow.schedule.kind === "manual") {
89
+ return null;
90
+ }
91
+ return {
92
+ managedBy: "task_worker",
93
+ nextDueAt: this.computeWorkflowNextDueAt(workflow),
94
+ lastDueAt: null,
95
+ lastRunId: null,
96
+ lastRunStatus: null,
97
+ updatedAt: new Date().toISOString(),
98
+ };
99
+ }
76
100
  async runDueWorkflows(args) {
77
101
  const nowMs = Date.parse(args.now);
78
102
  const workflows = await this.repository.listWorkflows(this.agentId());
@@ -135,6 +159,112 @@ export function withWorkflows(Base) {
135
159
  }
136
160
  return runs;
137
161
  }
162
+ /**
163
+ * Fires event-triggered workflows for calendar events that have ended since
164
+ * the workflow's cursor. Uses a (end_at, id) tuple cursor per workflow so
165
+ * repeated invocations never re-fire for the same event.
166
+ */
167
+ async runDueEventWorkflows(args) {
168
+ const workflows = await this.repository.listWorkflows(this.agentId());
169
+ const runs = [];
170
+ for (const workflow of workflows) {
171
+ if (runs.length >= args.limit) {
172
+ break;
173
+ }
174
+ if (workflow.status !== "active" ||
175
+ workflow.triggerType !== "event" ||
176
+ workflow.schedule.kind !== "event") {
177
+ continue;
178
+ }
179
+ if (workflow.schedule.eventKind !== "calendar.event.ended") {
180
+ continue;
181
+ }
182
+ let nextWorkflow = workflow;
183
+ const existingState = this.readWorkflowSchedulerState(nextWorkflow);
184
+ let schedulerState = existingState ?? {
185
+ managedBy: "task_worker",
186
+ nextDueAt: null,
187
+ lastDueAt: null,
188
+ lastRunId: null,
189
+ lastRunStatus: null,
190
+ updatedAt: new Date().toISOString(),
191
+ lastFiredEventEndAt: nextWorkflow.createdAt,
192
+ lastFiredEventId: null,
193
+ };
194
+ let stateChanged = existingState === null;
195
+ const remaining = args.limit - runs.length;
196
+ const candidates = await this.repository.listCalendarEventsEndedAfterCursor({
197
+ agentId: this.agentId(),
198
+ provider: "google",
199
+ side: "owner",
200
+ cursorEndAt: schedulerState.lastFiredEventEndAt ?? null,
201
+ cursorEventId: schedulerState.lastFiredEventId ?? null,
202
+ upToIso: args.now,
203
+ limit: Math.max(remaining * 4, 8),
204
+ });
205
+ const filters = workflow.schedule.filters?.kind === "calendar.event.ended"
206
+ ? workflow.schedule.filters.filters
207
+ : undefined;
208
+ for (const event of candidates) {
209
+ if (runs.length >= args.limit) {
210
+ break;
211
+ }
212
+ if (!matchesCalendarEventEndedFilters(event, filters)) {
213
+ // Even when skipped we advance the cursor so the workflow never
214
+ // re-considers this event on the next tick.
215
+ schedulerState = {
216
+ ...schedulerState,
217
+ lastFiredEventEndAt: event.endAt,
218
+ lastFiredEventId: event.id,
219
+ updatedAt: new Date().toISOString(),
220
+ };
221
+ stateChanged = true;
222
+ continue;
223
+ }
224
+ const { run, error } = await this.executeWorkflowDefinition(nextWorkflow, {
225
+ startedAt: event.endAt,
226
+ confirmBrowserActions: false,
227
+ request: {
228
+ scheduledExecution: false,
229
+ event: {
230
+ kind: "calendar.event.ended",
231
+ eventId: event.id,
232
+ calendarId: event.calendarId,
233
+ title: event.title,
234
+ startAt: event.startAt,
235
+ endAt: event.endAt,
236
+ htmlLink: event.htmlLink,
237
+ },
238
+ },
239
+ });
240
+ runs.push(run);
241
+ await this.emitWorkflowRunNudge(nextWorkflow, run);
242
+ schedulerState = {
243
+ ...schedulerState,
244
+ lastDueAt: event.endAt,
245
+ lastRunId: run.id,
246
+ lastRunStatus: run.status,
247
+ lastFiredEventEndAt: event.endAt,
248
+ lastFiredEventId: event.id,
249
+ updatedAt: new Date().toISOString(),
250
+ };
251
+ stateChanged = true;
252
+ if (error) {
253
+ this.logLifeOpsError("workflow_event_execution", error, {
254
+ workflowId: nextWorkflow.id,
255
+ workflowRunId: run.id,
256
+ eventId: event.id,
257
+ eventEndAt: event.endAt,
258
+ });
259
+ }
260
+ }
261
+ if (stateChanged) {
262
+ nextWorkflow = this.withWorkflowSchedulerState(nextWorkflow, schedulerState);
263
+ await this.repository.updateWorkflow(nextWorkflow);
264
+ }
265
+ }
266
+ return runs;
267
+ }
138
268
  async listWorkflows() {
139
269
  const workflows = await this.repository.listWorkflows(this.agentId());
140
270
  const records = [];
@@ -409,3 +539,47 @@ export function withWorkflows(Base) {
409
539
  }
410
540
  return LifeOpsWorkflowsServiceMixin;
411
541
  }
542
+ export function matchesCalendarEventEndedFilters(event, filters) {
543
+ if (!filters) {
544
+ return true;
545
+ }
546
+ if (filters.calendarIds && filters.calendarIds.length > 0) {
547
+ if (!filters.calendarIds.includes(event.calendarId)) {
548
+ return false;
549
+ }
550
+ }
551
+ if (filters.titleIncludesAny && filters.titleIncludesAny.length > 0) {
552
+ const title = (event.title ?? "").toLowerCase();
553
+ const matched = filters.titleIncludesAny.some((needle) => title.includes(needle.toLowerCase()));
554
+ if (!matched) {
555
+ return false;
556
+ }
557
+ }
558
+ if (typeof filters.minDurationMinutes === "number") {
559
+ const startMs = Date.parse(event.startAt);
560
+ const endMs = Date.parse(event.endAt);
561
+ if (Number.isFinite(startMs) && Number.isFinite(endMs)) {
562
+ const minutes = (endMs - startMs) / 60_000;
563
+ if (minutes < filters.minDurationMinutes) {
564
+ return false;
565
+ }
566
+ }
567
+ }
568
+ if (filters.attendeeEmailIncludesAny &&
569
+ filters.attendeeEmailIncludesAny.length > 0) {
570
+ const attendees = Array.isArray(event.attendees) ? event.attendees : [];
571
+ const matched = attendees.some((attendee) => {
572
+ const email = typeof attendee === "object" && attendee !== null
573
+ ? String(attendee.email ?? "").toLowerCase()
574
+ : "";
575
+ if (!email) {
576
+ return false;
577
+ }
578
+ return filters.attendeeEmailIncludesAny.some((needle) => email.includes(needle.toLowerCase()));
579
+ });
580
+ if (!matched) {
581
+ return false;
582
+ }
583
+ }
584
+ return true;
585
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"service-normalize-connector.d.ts","sourceRoot":"","sources":["../../../../../../../apps/app-lifeops/src/lifeops/service-normalize-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,6BAA6B,EAC7B,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EAGvB,mBAAmB,EACnB,+BAA+B,EAC/B,uBAAuB,EACvB,0BAA0B,EAC1B,mCAAmC,EACpC,MAAM,mCAAmC,CAAC;AA8E3C,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,oBAAoB,GAAG,SAAS,CAKlC;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,oBAAoB,GAAG,SAAS,CAKlC;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,OAAO,GACb,uBAAuB,EAAE,GAAG,SAAS,CAsBvC;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,uBAAuB,EAAE,CAE3B;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,GACb,0BAA0B,CAM5B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,0BAA0B,GACtC,uBAAuB,CA0CzB;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,+BAAoE,GAC5E,+BAA+B,CAqCjC;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,kBAAkB,GAAG,IAAI,CAM3B;AAED,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,6BAAgE,GACxE,6BAA6B,CA+B/B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYrE;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,CAgCR;AAED,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CASV;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAS3E;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,mCAAmC,EAC5C,OAAO,EAAE,sBAAsB,GAC9B,sBAAsB,CAsExB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,mBAAmB,CAgErB;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmDzB"}
1
+ {"version":3,"file":"service-normalize-connector.d.ts","sourceRoot":"","sources":["../../../../../../../apps/app-lifeops/src/lifeops/service-normalize-connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,6BAA6B,EAC7B,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EAGvB,mBAAmB,EACnB,+BAA+B,EAC/B,uBAAuB,EACvB,0BAA0B,EAC1B,mCAAmC,EACpC,MAAM,mCAAmC,CAAC;AA+E3C,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,oBAAoB,GAAG,SAAS,CAKlC;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,oBAAoB,GAAG,SAAS,CAKlC;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,OAAO,GACb,uBAAuB,EAAE,GAAG,SAAS,CAsBvC;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,uBAAuB,EAAE,CAE3B;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,GACb,0BAA0B,CAM5B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,0BAA0B,GACtC,uBAAuB,CA6CzB;AA8ED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,+BAAoE,GAC5E,+BAA+B,CAqCjC;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,kBAAkB,GAAG,IAAI,CAM3B;AAED,wBAAgB,oCAAoC,CAClD,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,6BAAgE,GACxE,6BAA6B,CA+B/B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYrE;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,CAgCR;AAED,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,EAAE,CASV;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAS3E;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,mCAAmC,EAC5C,OAAO,EAAE,sBAAsB,GAC9B,sBAAsB,CAsExB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,mBAAmB,CAgErB;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmDzB"}
@@ -1,4 +1,4 @@
1
- import { LIFEOPS_BROWSER_KINDS, LIFEOPS_BROWSER_SITE_ACCESS_MODES, LIFEOPS_BROWSER_TRACKING_MODES, LIFEOPS_CONNECTOR_MODES, LIFEOPS_CONNECTOR_SIDES, LIFEOPS_GOOGLE_CAPABILITIES, LIFEOPS_REMINDER_CHANNELS, LIFEOPS_TIME_WINDOW_NAMES, LIFEOPS_WORKFLOW_TRIGGER_TYPES, } from "@elizaos/shared/contracts/lifeops";
1
+ import { LIFEOPS_BROWSER_KINDS, LIFEOPS_BROWSER_SITE_ACCESS_MODES, LIFEOPS_BROWSER_TRACKING_MODES, LIFEOPS_CONNECTOR_MODES, LIFEOPS_CONNECTOR_SIDES, LIFEOPS_EVENT_KINDS, LIFEOPS_GOOGLE_CAPABILITIES, LIFEOPS_REMINDER_CHANNELS, LIFEOPS_TIME_WINDOW_NAMES, LIFEOPS_WORKFLOW_TRIGGER_TYPES, } from "@elizaos/shared/contracts/lifeops";
2
2
  import { parseCronExpression } from "@elizaos/agent/triggers/scheduling";
3
3
  import { LifeOpsServiceError } from "./service-types.js";
4
4
  import { fail, normalizeEnumValue, normalizeFiniteNumber, normalizeIsoString, normalizeOptionalBoolean, normalizeOptionalIsoString, normalizeOptionalString, normalizePositiveInteger, normalizeValidTimeZone, requireNonEmptyString, } from "./service-normalize.js";
@@ -80,6 +80,9 @@ export function normalizeWorkflowSchedule(value, triggerType) {
80
80
  return { kind: "manual" };
81
81
  }
82
82
  const schedule = requireRecord(value, "schedule");
83
+ if (triggerType === "event") {
84
+ return normalizeEventTrigger(schedule);
85
+ }
83
86
  const kind = normalizeEnumValue(schedule.kind, "schedule.kind", [
84
87
  "once",
85
88
  "interval",
@@ -109,6 +112,54 @@ export function normalizeWorkflowSchedule(value, triggerType) {
109
112
  timezone: normalizeValidTimeZone(schedule.timezone, "schedule.timezone"),
110
113
  };
111
114
  }
115
+ function normalizeEventTrigger(schedule) {
116
+ const kind = normalizeEnumValue(schedule.kind, "schedule.kind", [
117
+ "event",
118
+ ]);
119
+ const eventKind = normalizeEnumValue(schedule.eventKind, "schedule.eventKind", LIFEOPS_EVENT_KINDS);
120
+ const rawFilters = schedule.filters;
121
+ if (rawFilters === undefined || rawFilters === null) {
122
+ return { kind, eventKind };
123
+ }
124
+ const filtersRecord = requireRecord(rawFilters, "schedule.filters");
125
+ if (eventKind === "calendar.event.ended") {
126
+ return {
127
+ kind,
128
+ eventKind,
129
+ filters: {
130
+ kind: "calendar.event.ended",
131
+ filters: normalizeCalendarEventEndedFilters(filtersRecord),
132
+ },
133
+ };
134
+ }
135
+ return { kind, eventKind };
136
+ }
137
+ function normalizeCalendarEventEndedFilters(input) {
138
+ const filters = {};
139
+ if (input.calendarIds !== undefined) {
140
+ filters.calendarIds = normalizeStringArray(input.calendarIds, "schedule.filters.calendarIds");
141
+ }
142
+ if (input.titleIncludesAny !== undefined) {
143
+ filters.titleIncludesAny = normalizeStringArray(input.titleIncludesAny, "schedule.filters.titleIncludesAny");
144
+ }
145
+ if (input.minDurationMinutes !== undefined) {
146
+ filters.minDurationMinutes = normalizePositiveInteger(input.minDurationMinutes, "schedule.filters.minDurationMinutes");
147
+ }
148
+ if (input.attendeeEmailIncludesAny !== undefined) {
149
+ filters.attendeeEmailIncludesAny = normalizeStringArray(input.attendeeEmailIncludesAny, "schedule.filters.attendeeEmailIncludesAny");
150
+ }
151
+ return filters;
152
+ }
153
+ function normalizeStringArray(value, field) {
154
+ if (!Array.isArray(value)) {
155
+ fail(400, `${field} must be an array of strings`);
156
+ }
157
+ const out = [];
158
+ for (const entry of value) {
159
+ out.push(requireNonEmptyString(entry, `${field}[]`));
160
+ }
161
+ return out;
162
+ }
112
163
  export function normalizeWorkflowPermissionPolicy(value, current = DEFAULT_WORKFLOW_PERMISSION_POLICY) {
113
164
  if (value === undefined) {
114
165
  return { ...current };
@@ -7,6 +7,14 @@ export type LifeOpsWorkflowSchedulerState = {
7
7
  lastRunId: string | null;
8
8
  lastRunStatus: LifeOpsWorkflowRun["status"] | null;
9
9
  updatedAt: string;
10
+ /**
11
+ * Tuple cursor for event-triggered workflows. Processing is ordered by
12
+ * (end_at ASC, id ASC); after each fire we advance to the (end_at, id) of
13
+ * the last-fired event so we never re-fire for an event we already ran.
14
+ * Null for non-event workflows.
15
+ */
16
+ lastFiredEventEndAt?: string | null;
17
+ lastFiredEventId?: string | null;
10
18
  };
11
19
  export type ExecuteWorkflowResult = {
12
20
  run: LifeOpsWorkflowRun;
@@ -1 +1 @@
1
- {"version":3,"file":"service-types.d.ts","sourceRoot":"","sources":["../../../../../../../apps/app-lifeops/src/lifeops/service-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAE3E,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,aAAa,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IAClD,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,kBAAkB,CAAA;IACvB,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtF,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,YAAY,CAAA;AAC5D,MAAM,MAAM,+BAA+B,GAAG;IAC5C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,iBAAiB,EAAE,OAAO,CAAA;IAC1B,oEAAoE;IACpE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,QAAQ,GAAG,eAAe,GAAG,sBAAsB,CAAA;IAClE,6BAA6B,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5C,kBAAkB,EAAE,KAAK,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAC,CAAA;IACF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;CAKlB"}
1
+ {"version":3,"file":"service-types.d.ts","sourceRoot":"","sources":["../../../../../../../apps/app-lifeops/src/lifeops/service-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAE3E,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,aAAa,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IAClD,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,kBAAkB,CAAA;IACvB,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtF,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,YAAY,CAAA;AAC5D,MAAM,MAAM,+BAA+B,GAAG;IAC5C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,iBAAiB,EAAE,OAAO,CAAA;IAC1B,oEAAoE;IACpE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,QAAQ,GAAG,eAAe,GAAG,sBAAsB,CAAA;IAClE,6BAA6B,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5C,kBAAkB,EAAE,KAAK,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAC,CAAA;IACF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,CAAA;AAED,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM;CAKlB"}
@@ -825,10 +825,15 @@ declare const LifeOpsServiceComposedBase_base: {
825
825
  computeWorkflowNextDueAt(workflow: import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowDefinition, cursorIso?: string | null): string | null;
826
826
  withWorkflowSchedulerState(workflow: import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowDefinition, state: import("./service-types.js").LifeOpsWorkflowSchedulerState | null): import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowDefinition;
827
827
  initializeWorkflowSchedulerState(workflow: import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowDefinition): import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowDefinition;
828
+ buildInitialSchedulerState(workflow: import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowDefinition): import("./service-types.js").LifeOpsWorkflowSchedulerState | null;
828
829
  runDueWorkflows(args: {
829
830
  now: string;
830
831
  limit: number;
831
832
  }): Promise<import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowRun[]>;
833
+ runDueEventWorkflows(args: {
834
+ now: string;
835
+ limit: number;
836
+ }): Promise<import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowRun[]>;
832
837
  listWorkflows(): Promise<import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowRecord[]>;
833
838
  getWorkflow(workflowId: string): Promise<import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowRecord>;
834
839
  createWorkflow(request: import("@elizaos/shared/contracts/lifeops.js").CreateLifeOpsWorkflowRequest): Promise<import("@elizaos/shared/contracts/lifeops.js").LifeOpsWorkflowRecord>;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../../../apps/app-lifeops/src/lifeops/service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iEA6EokpC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;0BAA55iC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AArDtvG;;;;;;;GAOG;AACH,qBAAa,0BAA2B,SAAQ,+BA0C/C;CAAG;AAEJ,qBAAa,cAAe,SAAQ,0BAA0B;CAAG"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../../../apps/app-lifeops/src/lifeops/service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iEA6EokpC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;0BAA55iC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AArDtvG;;;;;;;GAOG;AACH,qBAAa,0BAA2B,SAAQ,+BA0C/C;CAAG;AAEJ,qBAAa,cAAe,SAAQ,0BAA0B;CAAG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/agent",
3
- "version": "2.0.0-alpha.211",
3
+ "version": "2.0.0-alpha.213",
4
4
  "description": "Standalone elizaOS-based agent and backend server package.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -462,14 +462,14 @@
462
462
  "@elizaos/app-steward": "^0.0.0",
463
463
  "@elizaos/app-task-coordinator": "^0.0.0",
464
464
  "@elizaos/app-training": "^0.0.1",
465
- "@elizaos/core": "^2.0.0-alpha.211",
465
+ "@elizaos/core": "^2.0.0-alpha.213",
466
466
  "@elizaos/plugin-agent-orchestrator": "^0.6.2-alpha.0",
467
467
  "@elizaos/plugin-ollama": "^2.0.0-alpha.14",
468
468
  "@elizaos/plugin-pdf": "^2.0.0-alpha.18",
469
469
  "@elizaos/plugin-solana": "1.2.6",
470
470
  "@elizaos/plugin-sql": "^2.0.0-alpha.19",
471
- "@elizaos/shared": "^2.0.0-alpha.211",
472
- "@elizaos/skills": "^2.0.0-alpha.211",
471
+ "@elizaos/shared": "^2.0.0-alpha.213",
472
+ "@elizaos/skills": "^2.0.0-alpha.213",
473
473
  "@hapi/boom": "^10.0.1",
474
474
  "@noble/curves": "^2.0.1",
475
475
  "@whiskeysockets/baileys": "7.0.0-rc.9",
@@ -355,10 +355,10 @@ export function configureLocalEmbeddingPlugin(_plugin, config) {
355
355
  const currentSharedLargeModel = process.env.OPENAI_LARGE_MODEL ?? process.env.LARGE_MODEL;
356
356
  setEnvIfMissing("GROQ_SMALL_MODEL", currentSharedSmallModel && !isLikelyOpenAiTextModel(currentSharedSmallModel)
357
357
  ? currentSharedSmallModel
358
- : "llama-3.1-8b-instant");
358
+ : "openai/gpt-oss-20b");
359
359
  setEnvIfMissing("GROQ_LARGE_MODEL", currentSharedLargeModel && !isLikelyOpenAiTextModel(currentSharedLargeModel)
360
360
  ? currentSharedLargeModel
361
- : "qwen/qwen3-32b");
361
+ : "openai/gpt-oss-120b");
362
362
  logger.info(`[eliza] Configured local embedding env: ${process.env.LOCAL_EMBEDDING_MODEL} (repo: ${process.env.LOCAL_EMBEDDING_MODEL_REPO ?? "auto"}, dims: ${process.env.LOCAL_EMBEDDING_DIMENSIONS ?? "auto"}, ctx: ${process.env.LOCAL_EMBEDDING_CONTEXT_SIZE ?? "auto"}, GPU: ${process.env.LOCAL_EMBEDDING_GPU_LAYERS}, mmap: ${process.env.LOCAL_EMBEDDING_USE_MMAP})`);
363
363
  }
364
364
  // ---------------------------------------------------------------------------
@@ -14,8 +14,32 @@ export declare const LIFEOPS_WORKFLOW_STATUSES: readonly ["active", "paused", "a
14
14
  export type LifeOpsWorkflowStatus = (typeof LIFEOPS_WORKFLOW_STATUSES)[number];
15
15
  export declare const LIFEOPS_WORKFLOW_RUN_STATUSES: readonly ["queued", "running", "success", "failed", "cancelled"];
16
16
  export type LifeOpsWorkflowRunStatus = (typeof LIFEOPS_WORKFLOW_RUN_STATUSES)[number];
17
- export declare const LIFEOPS_WORKFLOW_TRIGGER_TYPES: readonly ["manual", "schedule"];
17
+ export declare const LIFEOPS_WORKFLOW_TRIGGER_TYPES: readonly ["manual", "schedule", "event"];
18
18
  export type LifeOpsWorkflowTriggerType = (typeof LIFEOPS_WORKFLOW_TRIGGER_TYPES)[number];
19
+ /**
20
+ * Registry of event kinds that can fire a LifeOps workflow.
21
+ *
22
+ * Each entry is a stable identifier ("namespace.subject.verb") emitted by a
23
+ * detector inside the engine. Adding a new entry means adding a detector that
24
+ * publishes matching occurrences to `runDueEventWorkflows`, and — optionally —
25
+ * a filter shape under {@link LifeOpsEventFilters}.
26
+ */
27
+ export declare const LIFEOPS_EVENT_KINDS: readonly ["calendar.event.ended"];
28
+ export type LifeOpsEventKind = (typeof LIFEOPS_EVENT_KINDS)[number];
29
+ export interface LifeOpsCalendarEventEndedFilters {
30
+ /** Only fire for events on these calendar ids (e.g. "primary"). */
31
+ calendarIds?: string[];
32
+ /** Only fire when event title matches one of these case-insensitive substrings. */
33
+ titleIncludesAny?: string[];
34
+ /** Only fire when the event lasted at least this many minutes. */
35
+ minDurationMinutes?: number;
36
+ /** Only fire when one attendee email contains one of these substrings. */
37
+ attendeeEmailIncludesAny?: string[];
38
+ }
39
+ export type LifeOpsEventFilters = {
40
+ kind: "calendar.event.ended";
41
+ filters?: LifeOpsCalendarEventEndedFilters;
42
+ };
19
43
  export declare const LIFEOPS_NEGOTIATION_STATES: readonly ["initiated", "proposals_sent", "awaiting_response", "confirmed", "cancelled"];
20
44
  export type LifeOpsNegotiationState = (typeof LIFEOPS_NEGOTIATION_STATES)[number];
21
45
  export declare const LIFEOPS_PROPOSAL_STATUSES: readonly ["pending", "accepted", "declined", "expired"];
@@ -332,6 +356,10 @@ export type LifeOpsWorkflowSchedule = {
332
356
  kind: "cron";
333
357
  cronExpression: string;
334
358
  timezone: string;
359
+ } | {
360
+ kind: "event";
361
+ eventKind: LifeOpsEventKind;
362
+ filters?: LifeOpsEventFilters;
335
363
  };
336
364
  export interface LifeOpsWorkflowPermissionPolicy {
337
365
  allowBrowserActions: boolean;