@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.
- package/apps/app-lifeops/src/actions/intent-sync.d.ts.map +1 -1
- package/apps/app-lifeops/src/actions/intent-sync.js +4 -41
- package/apps/app-lifeops/src/actions/password-manager.d.ts.map +1 -1
- package/apps/app-lifeops/src/actions/password-manager.js +1 -32
- package/apps/app-lifeops/src/actions/remote-desktop.d.ts.map +1 -1
- package/apps/app-lifeops/src/actions/remote-desktop.js +1 -40
- package/apps/app-lifeops/src/actions/screen-time.d.ts.map +1 -1
- package/apps/app-lifeops/src/actions/screen-time.js +1 -20
- package/apps/app-lifeops/src/actions/subscriptions.d.ts.map +1 -1
- package/apps/app-lifeops/src/actions/subscriptions.js +23 -84
- package/apps/app-lifeops/src/lifeops/repository.d.ts +14 -0
- package/apps/app-lifeops/src/lifeops/repository.d.ts.map +1 -1
- package/apps/app-lifeops/src/lifeops/repository.js +25 -0
- package/apps/app-lifeops/src/lifeops/service-helpers-browser.d.ts.map +1 -1
- package/apps/app-lifeops/src/lifeops/service-helpers-browser.js +8 -0
- package/apps/app-lifeops/src/lifeops/service-mixin-reminders.js +5 -1
- package/apps/app-lifeops/src/lifeops/service-mixin-workflows.d.ts +2 -1
- package/apps/app-lifeops/src/lifeops/service-mixin-workflows.d.ts.map +1 -1
- package/apps/app-lifeops/src/lifeops/service-mixin-workflows.js +187 -13
- package/apps/app-lifeops/src/lifeops/service-normalize-connector.d.ts.map +1 -1
- package/apps/app-lifeops/src/lifeops/service-normalize-connector.js +52 -1
- package/apps/app-lifeops/src/lifeops/service-types.d.ts +8 -0
- package/apps/app-lifeops/src/lifeops/service-types.d.ts.map +1 -1
- package/apps/app-lifeops/src/lifeops/service.d.ts +5 -0
- package/apps/app-lifeops/src/lifeops/service.d.ts.map +1 -1
- package/package.json +4 -4
- package/packages/agent/src/runtime/eliza.js +2 -2
- package/packages/shared/src/contracts/lifeops.d.ts +29 -1
- package/packages/shared/src/contracts/lifeops.d.ts.map +1 -1
- 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 =
|
|
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;
|
|
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;
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
472
|
-
"@elizaos/skills": "^2.0.0-alpha.
|
|
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
|
-
: "
|
|
358
|
+
: "openai/gpt-oss-20b");
|
|
359
359
|
setEnvIfMissing("GROQ_LARGE_MODEL", currentSharedLargeModel && !isLikelyOpenAiTextModel(currentSharedLargeModel)
|
|
360
360
|
? currentSharedLargeModel
|
|
361
|
-
: "
|
|
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;
|