@elizaos/plugin-todos 2.0.3-beta.6 → 2.0.3-beta.7
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/dist/actions/todo.d.ts +17 -0
- package/dist/actions/todo.d.ts.map +1 -0
- package/dist/actions/todo.js +582 -0
- package/dist/actions/todo.js.map +1 -0
- package/dist/components/todos/TodosSpatialView.d.ts +46 -0
- package/dist/components/todos/TodosSpatialView.d.ts.map +1 -0
- package/dist/components/todos/TodosSpatialView.js +72 -0
- package/dist/components/todos/TodosSpatialView.js.map +1 -0
- package/dist/components/todos/TodosView.d.ts +41 -0
- package/dist/components/todos/TodosView.d.ts.map +1 -0
- package/dist/components/todos/TodosView.js +163 -0
- package/dist/components/todos/TodosView.js.map +1 -0
- package/dist/components/todos/todos-view-bundle.d.ts +2 -0
- package/dist/components/todos/todos-view-bundle.d.ts.map +1 -0
- package/dist/components/todos/todos-view-bundle.js +5 -0
- package/dist/components/todos/todos-view-bundle.js.map +1 -0
- package/dist/db/index.d.ts +2 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +2 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +249 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +45 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/current-todos.d.ts +11 -0
- package/dist/providers/current-todos.d.ts.map +1 -0
- package/dist/providers/current-todos.js +45 -0
- package/dist/providers/current-todos.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +26 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +9 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +5 -0
- package/dist/register.js.map +1 -0
- package/dist/service.d.ts +70 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +189 -0
- package/dist/service.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +31 -0
- package/dist/types.js.map +1 -0
- package/dist/views/bundle.js +266 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TODO umbrella action.
|
|
3
|
+
*
|
|
4
|
+
* ABSORPTION NOTE — OWNER_TODOS from plugin-lifeops is collapsed into this
|
|
5
|
+
* existing action. The umbrella already covers list/create/update/complete/
|
|
6
|
+
* cancel/delete/write/clear, which is a superset of what the owner-facing
|
|
7
|
+
* surface needed; no new op is required.
|
|
8
|
+
*
|
|
9
|
+
* TODO(migrate: plugins/plugin-lifeops/src/actions/owner-surfaces.ts
|
|
10
|
+
* ownerTodosAction): port any owner-only formatting (e.g. lane-based
|
|
11
|
+
* grouping by Today/Upcoming/Someday, due-date defaults, recap rendering)
|
|
12
|
+
* into the `list` op here. After migration, the OWNER_TODOS action and
|
|
13
|
+
* its source can be deleted from plugin-lifeops.
|
|
14
|
+
*/
|
|
15
|
+
import type { Action } from "@elizaos/core";
|
|
16
|
+
export declare const todoAction: Action;
|
|
17
|
+
//# sourceMappingURL=todo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"todo.d.ts","sourceRoot":"","sources":["../../src/actions/todo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,MAAM,EAOP,MAAM,eAAe,CAAC;AA+bvB,eAAO,MAAM,UAAU,EAAE,MAsOxB,CAAC"}
|
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getTodosService
|
|
3
|
+
} from "../service.js";
|
|
4
|
+
import {
|
|
5
|
+
TODO_ACTIONS,
|
|
6
|
+
TODO_FAILURE_TEXT_PREFIX,
|
|
7
|
+
TODO_STATUSES,
|
|
8
|
+
TODOS_CONTEXTS
|
|
9
|
+
} from "../types.js";
|
|
10
|
+
const PARENT_TRAJECTORY_STEP_ENV_KEY = "ELIZA_PARENT_TRAJECTORY_STEP_ID";
|
|
11
|
+
function checkboxFor(status) {
|
|
12
|
+
switch (status) {
|
|
13
|
+
case "completed":
|
|
14
|
+
return "[x]";
|
|
15
|
+
case "in_progress":
|
|
16
|
+
return "[\u2192]";
|
|
17
|
+
case "cancelled":
|
|
18
|
+
return "[-]";
|
|
19
|
+
default:
|
|
20
|
+
return "[ ]";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function renderMarkdown(todos) {
|
|
24
|
+
if (todos.length === 0) return "(no todos)";
|
|
25
|
+
return todos.map((t) => `- ${checkboxFor(t.status)} ${t.content}`).join("\n");
|
|
26
|
+
}
|
|
27
|
+
function failure(reason, message) {
|
|
28
|
+
const text = `${TODO_FAILURE_TEXT_PREFIX} ${reason}: ${message}`;
|
|
29
|
+
return { success: false, text, error: new Error(text) };
|
|
30
|
+
}
|
|
31
|
+
function readString(value) {
|
|
32
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
33
|
+
}
|
|
34
|
+
function readBoolean(value) {
|
|
35
|
+
if (typeof value === "boolean") return value;
|
|
36
|
+
if (typeof value === "string") {
|
|
37
|
+
const v = value.trim().toLowerCase();
|
|
38
|
+
if (v === "true" || v === "1" || v === "yes") return true;
|
|
39
|
+
if (v === "false" || v === "0" || v === "no") return false;
|
|
40
|
+
}
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
function readNumber(value) {
|
|
44
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
45
|
+
if (typeof value === "string" && value.trim()) {
|
|
46
|
+
const n = Number(value);
|
|
47
|
+
if (Number.isFinite(n)) return n;
|
|
48
|
+
}
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
function readStatus(value) {
|
|
52
|
+
const s = readString(value)?.toLowerCase();
|
|
53
|
+
if (!s) return void 0;
|
|
54
|
+
if (TODO_STATUSES.includes(s)) {
|
|
55
|
+
return s;
|
|
56
|
+
}
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
function readAction(value) {
|
|
60
|
+
const s = readString(value)?.toLowerCase();
|
|
61
|
+
if (!s) return void 0;
|
|
62
|
+
if (TODO_ACTIONS.includes(s)) {
|
|
63
|
+
return s;
|
|
64
|
+
}
|
|
65
|
+
return void 0;
|
|
66
|
+
}
|
|
67
|
+
function isOwnedByScope(todo, scope) {
|
|
68
|
+
return todo.entityId === scope.entityId && todo.agentId === scope.agentId;
|
|
69
|
+
}
|
|
70
|
+
function parseTodoList(raw) {
|
|
71
|
+
if (!Array.isArray(raw)) {
|
|
72
|
+
return { ok: false, message: "todos must be an array" };
|
|
73
|
+
}
|
|
74
|
+
const items = [];
|
|
75
|
+
for (let i = 0; i < raw.length; i++) {
|
|
76
|
+
const entry = raw[i];
|
|
77
|
+
if (!entry || typeof entry !== "object") {
|
|
78
|
+
return { ok: false, message: `todos[${i}] is not an object` };
|
|
79
|
+
}
|
|
80
|
+
const e = entry;
|
|
81
|
+
const content = readString(e.content);
|
|
82
|
+
if (!content) {
|
|
83
|
+
return {
|
|
84
|
+
ok: false,
|
|
85
|
+
message: `todos[${i}].content must be a non-empty string`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const status = readStatus(e.status);
|
|
89
|
+
if (!status) {
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
message: `todos[${i}].status must be one of ${TODO_STATUSES.join(", ")}`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const item = { content, status };
|
|
96
|
+
const id = readString(e.id);
|
|
97
|
+
if (id) item.id = id;
|
|
98
|
+
const activeForm = readString(e.activeForm);
|
|
99
|
+
if (activeForm) item.activeForm = activeForm;
|
|
100
|
+
items.push(item);
|
|
101
|
+
}
|
|
102
|
+
return { ok: true, items };
|
|
103
|
+
}
|
|
104
|
+
function readScope(runtime, message) {
|
|
105
|
+
const entityId = readString(message.entityId);
|
|
106
|
+
if (!entityId) {
|
|
107
|
+
return { error: "message has no entityId" };
|
|
108
|
+
}
|
|
109
|
+
const agentId = readString(runtime.agentId);
|
|
110
|
+
if (!agentId) {
|
|
111
|
+
return { error: "runtime has no agentId" };
|
|
112
|
+
}
|
|
113
|
+
const parentStepFromEnv = readString(
|
|
114
|
+
process.env[PARENT_TRAJECTORY_STEP_ENV_KEY]
|
|
115
|
+
);
|
|
116
|
+
return {
|
|
117
|
+
entityId,
|
|
118
|
+
agentId,
|
|
119
|
+
roomId: readString(message.roomId) ?? null,
|
|
120
|
+
worldId: readString(message.worldId) ?? null,
|
|
121
|
+
parentTrajectoryStepId: parentStepFromEnv ?? null
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async function emit(callback, text) {
|
|
125
|
+
if (callback) {
|
|
126
|
+
await callback({ text, source: "todos" });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function actionWrite({
|
|
130
|
+
service,
|
|
131
|
+
scope,
|
|
132
|
+
params,
|
|
133
|
+
callback
|
|
134
|
+
}) {
|
|
135
|
+
const parsed = parseTodoList(params.todos);
|
|
136
|
+
if (!parsed.ok) {
|
|
137
|
+
return failure("invalid_param", parsed.message);
|
|
138
|
+
}
|
|
139
|
+
const result = await service.writeList({
|
|
140
|
+
entityId: scope.entityId,
|
|
141
|
+
agentId: scope.agentId,
|
|
142
|
+
roomId: scope.roomId,
|
|
143
|
+
worldId: scope.worldId,
|
|
144
|
+
parentTrajectoryStepId: scope.parentTrajectoryStepId,
|
|
145
|
+
todos: parsed.items
|
|
146
|
+
});
|
|
147
|
+
let pending = 0;
|
|
148
|
+
let inProgress = 0;
|
|
149
|
+
let completed = 0;
|
|
150
|
+
let cancelled = 0;
|
|
151
|
+
for (const t of result.after) {
|
|
152
|
+
if (t.status === "completed") completed++;
|
|
153
|
+
else if (t.status === "in_progress") inProgress++;
|
|
154
|
+
else if (t.status === "cancelled") cancelled++;
|
|
155
|
+
else pending++;
|
|
156
|
+
}
|
|
157
|
+
const text = renderMarkdown(result.after);
|
|
158
|
+
await emit(callback, text);
|
|
159
|
+
return {
|
|
160
|
+
success: true,
|
|
161
|
+
text,
|
|
162
|
+
data: {
|
|
163
|
+
action: "write",
|
|
164
|
+
op: "write",
|
|
165
|
+
entityId: scope.entityId,
|
|
166
|
+
todos: result.after,
|
|
167
|
+
oldTodos: result.before,
|
|
168
|
+
pendingCount: pending,
|
|
169
|
+
inProgressCount: inProgress,
|
|
170
|
+
completedCount: completed,
|
|
171
|
+
cancelledCount: cancelled
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async function actionCreate({
|
|
176
|
+
service,
|
|
177
|
+
scope,
|
|
178
|
+
params,
|
|
179
|
+
callback
|
|
180
|
+
}) {
|
|
181
|
+
const content = readString(params.content);
|
|
182
|
+
if (!content) {
|
|
183
|
+
return failure("missing_param", "content is required for action=create");
|
|
184
|
+
}
|
|
185
|
+
const status = readStatus(params.status) ?? "pending";
|
|
186
|
+
const activeForm = readString(params.activeForm);
|
|
187
|
+
const parentTodoId = readString(params.parentTodoId);
|
|
188
|
+
const input = {
|
|
189
|
+
entityId: scope.entityId,
|
|
190
|
+
agentId: scope.agentId,
|
|
191
|
+
roomId: scope.roomId,
|
|
192
|
+
worldId: scope.worldId,
|
|
193
|
+
content,
|
|
194
|
+
status,
|
|
195
|
+
parentTrajectoryStepId: scope.parentTrajectoryStepId
|
|
196
|
+
};
|
|
197
|
+
if (activeForm !== void 0) input.activeForm = activeForm;
|
|
198
|
+
if (parentTodoId !== void 0) input.parentTodoId = parentTodoId;
|
|
199
|
+
const todo = await service.create(input);
|
|
200
|
+
const text = `Created: ${checkboxFor(todo.status)} ${todo.content}`;
|
|
201
|
+
await emit(callback, text);
|
|
202
|
+
return {
|
|
203
|
+
success: true,
|
|
204
|
+
text,
|
|
205
|
+
data: {
|
|
206
|
+
action: "create",
|
|
207
|
+
op: "create",
|
|
208
|
+
entityId: scope.entityId,
|
|
209
|
+
todo
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async function actionUpdate({
|
|
214
|
+
service,
|
|
215
|
+
scope,
|
|
216
|
+
params,
|
|
217
|
+
callback
|
|
218
|
+
}) {
|
|
219
|
+
const id = readString(params.id);
|
|
220
|
+
if (!id) {
|
|
221
|
+
return failure("missing_param", "id is required for action=update");
|
|
222
|
+
}
|
|
223
|
+
const existing = await service.get(id);
|
|
224
|
+
if (!existing || !isOwnedByScope(existing, scope)) {
|
|
225
|
+
return failure("not_found", `todo ${id} not found for this user`);
|
|
226
|
+
}
|
|
227
|
+
const patch = {};
|
|
228
|
+
const content = readString(params.content);
|
|
229
|
+
if (content !== void 0) patch.content = content;
|
|
230
|
+
const activeForm = readString(params.activeForm);
|
|
231
|
+
if (activeForm !== void 0) patch.activeForm = activeForm;
|
|
232
|
+
const status = readStatus(params.status);
|
|
233
|
+
if (status !== void 0) patch.status = status;
|
|
234
|
+
const parentTodoId = readString(params.parentTodoId);
|
|
235
|
+
if (parentTodoId !== void 0) patch.parentTodoId = parentTodoId;
|
|
236
|
+
if (Object.keys(patch).length === 0) {
|
|
237
|
+
return failure(
|
|
238
|
+
"missing_param",
|
|
239
|
+
"at least one field is required for action=update"
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
const todo = await service.update(id, patch);
|
|
243
|
+
if (!todo) {
|
|
244
|
+
return failure("not_found", `todo ${id} not found`);
|
|
245
|
+
}
|
|
246
|
+
const text = `Updated: ${checkboxFor(todo.status)} ${todo.content}`;
|
|
247
|
+
await emit(callback, text);
|
|
248
|
+
return {
|
|
249
|
+
success: true,
|
|
250
|
+
text,
|
|
251
|
+
data: {
|
|
252
|
+
action: "update",
|
|
253
|
+
op: "update",
|
|
254
|
+
entityId: scope.entityId,
|
|
255
|
+
todo
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
async function actionSetStatus(args, status, verb) {
|
|
260
|
+
const { service, scope, params, callback } = args;
|
|
261
|
+
const id = readString(params.id);
|
|
262
|
+
if (!id) {
|
|
263
|
+
return failure("missing_param", `id is required for action=${verb}`);
|
|
264
|
+
}
|
|
265
|
+
const existing = await service.get(id);
|
|
266
|
+
if (!existing || !isOwnedByScope(existing, scope)) {
|
|
267
|
+
return failure("not_found", `todo ${id} not found for this user`);
|
|
268
|
+
}
|
|
269
|
+
const todo = await service.update(id, { status });
|
|
270
|
+
if (!todo) {
|
|
271
|
+
return failure("not_found", `todo ${id} not found`);
|
|
272
|
+
}
|
|
273
|
+
const text = `${verb}: ${checkboxFor(todo.status)} ${todo.content}`;
|
|
274
|
+
await emit(callback, text);
|
|
275
|
+
return {
|
|
276
|
+
success: true,
|
|
277
|
+
text,
|
|
278
|
+
data: { action: verb, op: verb, entityId: scope.entityId, todo }
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
async function actionDelete({
|
|
282
|
+
service,
|
|
283
|
+
scope,
|
|
284
|
+
params,
|
|
285
|
+
callback
|
|
286
|
+
}) {
|
|
287
|
+
const id = readString(params.id);
|
|
288
|
+
if (!id) {
|
|
289
|
+
return failure("missing_param", "id is required for action=delete");
|
|
290
|
+
}
|
|
291
|
+
const existing = await service.get(id);
|
|
292
|
+
if (!existing || !isOwnedByScope(existing, scope)) {
|
|
293
|
+
return failure("not_found", `todo ${id} not found for this user`);
|
|
294
|
+
}
|
|
295
|
+
const ok = await service.delete(id);
|
|
296
|
+
if (!ok) {
|
|
297
|
+
return failure("not_found", `todo ${id} not found`);
|
|
298
|
+
}
|
|
299
|
+
const text = `Deleted: ${existing.content}`;
|
|
300
|
+
await emit(callback, text);
|
|
301
|
+
return {
|
|
302
|
+
success: true,
|
|
303
|
+
text,
|
|
304
|
+
data: {
|
|
305
|
+
action: "delete",
|
|
306
|
+
op: "delete",
|
|
307
|
+
entityId: scope.entityId,
|
|
308
|
+
id
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
async function actionList({
|
|
313
|
+
service,
|
|
314
|
+
scope,
|
|
315
|
+
params,
|
|
316
|
+
callback
|
|
317
|
+
}) {
|
|
318
|
+
const includeCompleted = readBoolean(params.includeCompleted) ?? false;
|
|
319
|
+
const limit = readNumber(params.limit);
|
|
320
|
+
const filter = {
|
|
321
|
+
entityId: scope.entityId,
|
|
322
|
+
agentId: scope.agentId,
|
|
323
|
+
includeCompleted
|
|
324
|
+
};
|
|
325
|
+
if (limit !== void 0) filter.limit = limit;
|
|
326
|
+
const todos = await service.list(filter);
|
|
327
|
+
const text = renderMarkdown(todos);
|
|
328
|
+
await emit(callback, text);
|
|
329
|
+
return {
|
|
330
|
+
success: true,
|
|
331
|
+
text,
|
|
332
|
+
data: {
|
|
333
|
+
action: "list",
|
|
334
|
+
op: "list",
|
|
335
|
+
entityId: scope.entityId,
|
|
336
|
+
todos
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
async function actionClear({
|
|
341
|
+
service,
|
|
342
|
+
scope,
|
|
343
|
+
callback
|
|
344
|
+
}) {
|
|
345
|
+
const filter = {
|
|
346
|
+
entityId: scope.entityId,
|
|
347
|
+
agentId: scope.agentId
|
|
348
|
+
};
|
|
349
|
+
if (scope.roomId) filter.roomId = scope.roomId;
|
|
350
|
+
const count = await service.clear(filter);
|
|
351
|
+
const text = `Cleared ${count} todo${count === 1 ? "" : "s"}.`;
|
|
352
|
+
await emit(callback, text);
|
|
353
|
+
return {
|
|
354
|
+
success: true,
|
|
355
|
+
text,
|
|
356
|
+
data: {
|
|
357
|
+
action: "clear",
|
|
358
|
+
op: "clear",
|
|
359
|
+
entityId: scope.entityId,
|
|
360
|
+
count
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
const todoAction = {
|
|
365
|
+
name: "TODO",
|
|
366
|
+
contexts: [...TODOS_CONTEXTS],
|
|
367
|
+
roleGate: { minRole: "ADMIN" },
|
|
368
|
+
contextGate: { anyOf: [...TODOS_CONTEXTS] },
|
|
369
|
+
tags: [
|
|
370
|
+
"domain:reminders",
|
|
371
|
+
"capability:read",
|
|
372
|
+
"capability:write",
|
|
373
|
+
"capability:update",
|
|
374
|
+
"capability:delete",
|
|
375
|
+
"surface:internal"
|
|
376
|
+
],
|
|
377
|
+
similes: [
|
|
378
|
+
"TODO_WRITE",
|
|
379
|
+
"WRITE_TODOS",
|
|
380
|
+
"SET_TODOS",
|
|
381
|
+
"UPDATE_TODOS",
|
|
382
|
+
"TODO_CREATE",
|
|
383
|
+
"CREATE_TODO",
|
|
384
|
+
"TODO_UPDATE",
|
|
385
|
+
"UPDATE_TODO",
|
|
386
|
+
"TODO_COMPLETE",
|
|
387
|
+
"COMPLETE_TODO",
|
|
388
|
+
"FINISH_TODO",
|
|
389
|
+
"TODO_CANCEL",
|
|
390
|
+
"CANCEL_TODO",
|
|
391
|
+
"TODO_DELETE",
|
|
392
|
+
"DELETE_TODO",
|
|
393
|
+
"REMOVE_TODO",
|
|
394
|
+
"TODO_LIST",
|
|
395
|
+
"LIST_TODOS",
|
|
396
|
+
"GET_TODOS",
|
|
397
|
+
"SHOW_TODOS",
|
|
398
|
+
"TODO_CLEAR",
|
|
399
|
+
"CLEAR_TODOS"
|
|
400
|
+
],
|
|
401
|
+
description: "Manage the user's todo list. Actions: write (replace the list with `todos:[{id?, content, status, activeForm?}]`), create (add one), update (change by id), complete, cancel, delete, list, clear. Todos are user-scoped (entityId), persistent, and shared across rooms for the same user.",
|
|
402
|
+
descriptionCompressed: "todos: write|create|update|complete|cancel|delete|list|clear; user-scoped (entityId)",
|
|
403
|
+
parameters: [
|
|
404
|
+
{
|
|
405
|
+
name: "action",
|
|
406
|
+
description: "Action: write, create, update, complete, cancel, delete, list, clear.",
|
|
407
|
+
required: true,
|
|
408
|
+
schema: { type: "string", enum: [...TODO_ACTIONS] }
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
name: "id",
|
|
412
|
+
description: "Todo id (update/complete/cancel/delete).",
|
|
413
|
+
required: false,
|
|
414
|
+
schema: { type: "string" }
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
name: "content",
|
|
418
|
+
description: "Imperative form, e.g. 'Add tests' (create/update).",
|
|
419
|
+
required: false,
|
|
420
|
+
schema: { type: "string" }
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: "activeForm",
|
|
424
|
+
description: "Present-continuous form, e.g. 'Adding tests' (create/update).",
|
|
425
|
+
required: false,
|
|
426
|
+
schema: { type: "string" }
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: "status",
|
|
430
|
+
description: "pending | in_progress | completed | cancelled.",
|
|
431
|
+
required: false,
|
|
432
|
+
schema: { type: "string", enum: [...TODO_STATUSES] }
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: "parentTodoId",
|
|
436
|
+
description: "Parent todo id for sub-tasks (create/update).",
|
|
437
|
+
required: false,
|
|
438
|
+
schema: { type: "string" }
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: "todos",
|
|
442
|
+
description: "Array of {id?, content, status, activeForm?} for action=write. Replaces the user's list for this conversation.",
|
|
443
|
+
required: false,
|
|
444
|
+
schema: {
|
|
445
|
+
type: "array",
|
|
446
|
+
items: {
|
|
447
|
+
type: "object",
|
|
448
|
+
properties: {
|
|
449
|
+
id: { type: "string" },
|
|
450
|
+
content: { type: "string" },
|
|
451
|
+
status: { type: "string", enum: [...TODO_STATUSES] },
|
|
452
|
+
activeForm: { type: "string" }
|
|
453
|
+
},
|
|
454
|
+
required: ["content", "status"]
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
name: "includeCompleted",
|
|
460
|
+
description: "Include completed/cancelled todos in action=list output.",
|
|
461
|
+
required: false,
|
|
462
|
+
schema: { type: "boolean" }
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: "limit",
|
|
466
|
+
description: "Max rows to return for action=list.",
|
|
467
|
+
required: false,
|
|
468
|
+
schema: { type: "number" }
|
|
469
|
+
}
|
|
470
|
+
],
|
|
471
|
+
validate: async (runtime) => Boolean(getTodosService(runtime)),
|
|
472
|
+
handler: async (runtime, message, _state, options, callback) => {
|
|
473
|
+
const params = options?.parameters ?? {};
|
|
474
|
+
const action = readAction(params.action ?? params.subaction ?? params.op);
|
|
475
|
+
if (!action) {
|
|
476
|
+
return failure(
|
|
477
|
+
"missing_param",
|
|
478
|
+
`action is required (one of: ${TODO_ACTIONS.join(", ")})`
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
const scope = readScope(runtime, message);
|
|
482
|
+
if ("error" in scope) {
|
|
483
|
+
return failure("missing_param", scope.error);
|
|
484
|
+
}
|
|
485
|
+
try {
|
|
486
|
+
const service = getTodosService(runtime);
|
|
487
|
+
const args = { service, scope, params, callback };
|
|
488
|
+
switch (action) {
|
|
489
|
+
case "write":
|
|
490
|
+
return await actionWrite(args);
|
|
491
|
+
case "create":
|
|
492
|
+
return await actionCreate(args);
|
|
493
|
+
case "update":
|
|
494
|
+
return await actionUpdate(args);
|
|
495
|
+
case "complete":
|
|
496
|
+
return await actionSetStatus(args, "completed", "complete");
|
|
497
|
+
case "cancel":
|
|
498
|
+
return await actionSetStatus(args, "cancelled", "cancel");
|
|
499
|
+
case "delete":
|
|
500
|
+
return await actionDelete(args);
|
|
501
|
+
case "list":
|
|
502
|
+
return await actionList(args);
|
|
503
|
+
case "clear":
|
|
504
|
+
return await actionClear(args);
|
|
505
|
+
}
|
|
506
|
+
} catch (error) {
|
|
507
|
+
const message2 = error instanceof Error ? error.message : "todo persistence failed";
|
|
508
|
+
return failure("persistence_error", message2);
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
examples: [
|
|
512
|
+
[
|
|
513
|
+
{
|
|
514
|
+
name: "{{name1}}",
|
|
515
|
+
content: {
|
|
516
|
+
text: "Add 'review PR feedback' to my todo list.",
|
|
517
|
+
source: "chat"
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
name: "{{agentName}}",
|
|
522
|
+
content: {
|
|
523
|
+
text: "Adding the todo.",
|
|
524
|
+
actions: ["TODO"],
|
|
525
|
+
thought: "Single-todo creation maps to TODO action=create with content set."
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
],
|
|
529
|
+
[
|
|
530
|
+
{
|
|
531
|
+
name: "{{name1}}",
|
|
532
|
+
content: {
|
|
533
|
+
text: "Show my todos that are still pending.",
|
|
534
|
+
source: "chat"
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: "{{agentName}}",
|
|
539
|
+
content: {
|
|
540
|
+
text: "Listing your pending todos.",
|
|
541
|
+
actions: ["TODO"],
|
|
542
|
+
thought: "List query maps to TODO action=list with includeCompleted=false."
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
],
|
|
546
|
+
[
|
|
547
|
+
{
|
|
548
|
+
name: "{{name1}}",
|
|
549
|
+
content: { text: "Cancel todo abc-123.", source: "chat" }
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
name: "{{agentName}}",
|
|
553
|
+
content: {
|
|
554
|
+
text: "Cancelling that todo.",
|
|
555
|
+
actions: ["TODO"],
|
|
556
|
+
thought: "Cancel intent on a specific id maps to TODO action=cancel with id=abc-123."
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
],
|
|
560
|
+
[
|
|
561
|
+
{
|
|
562
|
+
name: "{{name1}}",
|
|
563
|
+
content: {
|
|
564
|
+
text: "rappelle-moi de relire l'audit demain",
|
|
565
|
+
source: "chat"
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
name: "{{agentName}}",
|
|
570
|
+
content: {
|
|
571
|
+
text: "Saved. I'll remind you tomorrow about the audit re-read.",
|
|
572
|
+
actions: ["TODO"],
|
|
573
|
+
thought: "Casual French reminder phrasing maps to TODO action=create. Plugin examples must cover non-English idiom so the few-shot extends past the literal 'Add X to my todo list' pattern."
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
]
|
|
577
|
+
]
|
|
578
|
+
};
|
|
579
|
+
export {
|
|
580
|
+
todoAction
|
|
581
|
+
};
|
|
582
|
+
//# sourceMappingURL=todo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/actions/todo.ts"],"sourcesContent":["/**\n * TODO umbrella action.\n *\n * ABSORPTION NOTE — OWNER_TODOS from plugin-lifeops is collapsed into this\n * existing action. The umbrella already covers list/create/update/complete/\n * cancel/delete/write/clear, which is a superset of what the owner-facing\n * surface needed; no new op is required.\n *\n * TODO(migrate: plugins/plugin-lifeops/src/actions/owner-surfaces.ts\n * ownerTodosAction): port any owner-only formatting (e.g. lane-based\n * grouping by Today/Upcoming/Someday, due-date defaults, recap rendering)\n * into the `list` op here. After migration, the OWNER_TODOS action and\n * its source can be deleted from plugin-lifeops.\n */\n\nimport type {\n Action,\n ActionResult,\n HandlerCallback,\n HandlerOptions,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\n\nimport {\n type CreateTodoInput,\n getTodosService,\n type TodosService,\n type UpdateTodoInput,\n} from \"../service.js\";\nimport {\n TODO_ACTIONS,\n TODO_FAILURE_TEXT_PREFIX,\n TODO_STATUSES,\n TODOS_CONTEXTS,\n type Todo,\n type TodoActionName,\n type TodoStatus,\n} from \"../types.js\";\n\nconst PARENT_TRAJECTORY_STEP_ENV_KEY = \"ELIZA_PARENT_TRAJECTORY_STEP_ID\";\n\ninterface TodoActionParameters {\n action?: unknown;\n subaction?: unknown;\n op?: unknown;\n id?: unknown;\n content?: unknown;\n activeForm?: unknown;\n status?: unknown;\n parentTodoId?: unknown;\n todos?: unknown;\n includeCompleted?: unknown;\n limit?: unknown;\n}\n\nfunction checkboxFor(status: TodoStatus): string {\n switch (status) {\n case \"completed\":\n return \"[x]\";\n case \"in_progress\":\n return \"[→]\";\n case \"cancelled\":\n return \"[-]\";\n default:\n return \"[ ]\";\n }\n}\n\nfunction renderMarkdown(todos: Todo[]): string {\n if (todos.length === 0) return \"(no todos)\";\n return todos.map((t) => `- ${checkboxFor(t.status)} ${t.content}`).join(\"\\n\");\n}\n\nfunction failure(reason: string, message: string): ActionResult {\n const text = `${TODO_FAILURE_TEXT_PREFIX} ${reason}: ${message}`;\n return { success: false, text, error: new Error(text) };\n}\n\nfunction readString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0\n ? value.trim()\n : undefined;\n}\n\nfunction readBoolean(value: unknown): boolean | undefined {\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"string\") {\n const v = value.trim().toLowerCase();\n if (v === \"true\" || v === \"1\" || v === \"yes\") return true;\n if (v === \"false\" || v === \"0\" || v === \"no\") return false;\n }\n return undefined;\n}\n\nfunction readNumber(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\" && value.trim()) {\n const n = Number(value);\n if (Number.isFinite(n)) return n;\n }\n return undefined;\n}\n\nfunction readStatus(value: unknown): TodoStatus | undefined {\n const s = readString(value)?.toLowerCase();\n if (!s) return undefined;\n if ((TODO_STATUSES as readonly string[]).includes(s)) {\n return s as TodoStatus;\n }\n return undefined;\n}\n\nfunction readAction(value: unknown): TodoActionName | undefined {\n const s = readString(value)?.toLowerCase();\n if (!s) return undefined;\n if ((TODO_ACTIONS as readonly string[]).includes(s)) {\n return s as TodoActionName;\n }\n return undefined;\n}\n\nfunction isOwnedByScope(todo: Todo, scope: ScopeContext): boolean {\n return todo.entityId === scope.entityId && todo.agentId === scope.agentId;\n}\n\ninterface ParsedListItem {\n id?: string;\n content: string;\n status: TodoStatus;\n activeForm?: string;\n}\n\nfunction parseTodoList(\n raw: unknown,\n): { ok: true; items: ParsedListItem[] } | { ok: false; message: string } {\n if (!Array.isArray(raw)) {\n return { ok: false, message: \"todos must be an array\" };\n }\n const items: ParsedListItem[] = [];\n for (let i = 0; i < raw.length; i++) {\n const entry = raw[i];\n if (!entry || typeof entry !== \"object\") {\n return { ok: false, message: `todos[${i}] is not an object` };\n }\n const e = entry as Record<string, unknown>;\n const content = readString(e.content);\n if (!content) {\n return {\n ok: false,\n message: `todos[${i}].content must be a non-empty string`,\n };\n }\n const status = readStatus(e.status);\n if (!status) {\n return {\n ok: false,\n message: `todos[${i}].status must be one of ${TODO_STATUSES.join(\", \")}`,\n };\n }\n const item: ParsedListItem = { content, status };\n const id = readString(e.id);\n if (id) item.id = id;\n const activeForm = readString(e.activeForm);\n if (activeForm) item.activeForm = activeForm;\n items.push(item);\n }\n return { ok: true, items };\n}\n\ninterface ScopeContext {\n entityId: string;\n agentId: string;\n roomId: string | null;\n worldId: string | null;\n parentTrajectoryStepId: string | null;\n}\n\nfunction readScope(\n runtime: IAgentRuntime,\n message: Memory,\n): ScopeContext | { error: string } {\n const entityId = readString(message.entityId);\n if (!entityId) {\n return { error: \"message has no entityId\" };\n }\n const agentId = readString(runtime.agentId);\n if (!agentId) {\n return { error: \"runtime has no agentId\" };\n }\n const parentStepFromEnv = readString(\n process.env[PARENT_TRAJECTORY_STEP_ENV_KEY],\n );\n return {\n entityId,\n agentId,\n roomId: readString(message.roomId) ?? null,\n worldId: readString(message.worldId) ?? null,\n parentTrajectoryStepId: parentStepFromEnv ?? null,\n };\n}\n\nasync function emit(\n callback: HandlerCallback | undefined,\n text: string,\n): Promise<void> {\n if (callback) {\n await callback({ text, source: \"todos\" });\n }\n}\n\ninterface ActionHandlerArgs {\n service: TodosService;\n scope: ScopeContext;\n params: TodoActionParameters;\n callback: HandlerCallback | undefined;\n}\n\nasync function actionWrite({\n service,\n scope,\n params,\n callback,\n}: ActionHandlerArgs): Promise<ActionResult> {\n const parsed = parseTodoList(params.todos);\n if (!parsed.ok) {\n return failure(\"invalid_param\", parsed.message);\n }\n const result = await service.writeList({\n entityId: scope.entityId,\n agentId: scope.agentId,\n roomId: scope.roomId,\n worldId: scope.worldId,\n parentTrajectoryStepId: scope.parentTrajectoryStepId,\n todos: parsed.items,\n });\n let pending = 0;\n let inProgress = 0;\n let completed = 0;\n let cancelled = 0;\n for (const t of result.after) {\n if (t.status === \"completed\") completed++;\n else if (t.status === \"in_progress\") inProgress++;\n else if (t.status === \"cancelled\") cancelled++;\n else pending++;\n }\n const text = renderMarkdown(result.after);\n await emit(callback, text);\n return {\n success: true,\n text,\n data: {\n action: \"write\" as const,\n op: \"write\" as const,\n entityId: scope.entityId,\n todos: result.after,\n oldTodos: result.before,\n pendingCount: pending,\n inProgressCount: inProgress,\n completedCount: completed,\n cancelledCount: cancelled,\n },\n };\n}\n\nasync function actionCreate({\n service,\n scope,\n params,\n callback,\n}: ActionHandlerArgs): Promise<ActionResult> {\n const content = readString(params.content);\n if (!content) {\n return failure(\"missing_param\", \"content is required for action=create\");\n }\n const status = readStatus(params.status) ?? \"pending\";\n const activeForm = readString(params.activeForm);\n const parentTodoId = readString(params.parentTodoId);\n const input: CreateTodoInput = {\n entityId: scope.entityId,\n agentId: scope.agentId,\n roomId: scope.roomId,\n worldId: scope.worldId,\n content,\n status,\n parentTrajectoryStepId: scope.parentTrajectoryStepId,\n };\n if (activeForm !== undefined) input.activeForm = activeForm;\n if (parentTodoId !== undefined) input.parentTodoId = parentTodoId;\n const todo = await service.create(input);\n const text = `Created: ${checkboxFor(todo.status)} ${todo.content}`;\n await emit(callback, text);\n return {\n success: true,\n text,\n data: {\n action: \"create\" as const,\n op: \"create\" as const,\n entityId: scope.entityId,\n todo,\n },\n };\n}\n\nasync function actionUpdate({\n service,\n scope,\n params,\n callback,\n}: ActionHandlerArgs): Promise<ActionResult> {\n const id = readString(params.id);\n if (!id) {\n return failure(\"missing_param\", \"id is required for action=update\");\n }\n const existing = await service.get(id);\n if (!existing || !isOwnedByScope(existing, scope)) {\n return failure(\"not_found\", `todo ${id} not found for this user`);\n }\n const patch: UpdateTodoInput = {};\n const content = readString(params.content);\n if (content !== undefined) patch.content = content;\n const activeForm = readString(params.activeForm);\n if (activeForm !== undefined) patch.activeForm = activeForm;\n const status = readStatus(params.status);\n if (status !== undefined) patch.status = status;\n const parentTodoId = readString(params.parentTodoId);\n if (parentTodoId !== undefined) patch.parentTodoId = parentTodoId;\n if (Object.keys(patch).length === 0) {\n return failure(\n \"missing_param\",\n \"at least one field is required for action=update\",\n );\n }\n const todo = await service.update(id, patch);\n if (!todo) {\n return failure(\"not_found\", `todo ${id} not found`);\n }\n const text = `Updated: ${checkboxFor(todo.status)} ${todo.content}`;\n await emit(callback, text);\n return {\n success: true,\n text,\n data: {\n action: \"update\" as const,\n op: \"update\" as const,\n entityId: scope.entityId,\n todo,\n },\n };\n}\n\nasync function actionSetStatus(\n args: ActionHandlerArgs,\n status: TodoStatus,\n verb: string,\n): Promise<ActionResult> {\n const { service, scope, params, callback } = args;\n const id = readString(params.id);\n if (!id) {\n return failure(\"missing_param\", `id is required for action=${verb}`);\n }\n const existing = await service.get(id);\n if (!existing || !isOwnedByScope(existing, scope)) {\n return failure(\"not_found\", `todo ${id} not found for this user`);\n }\n const todo = await service.update(id, { status });\n if (!todo) {\n return failure(\"not_found\", `todo ${id} not found`);\n }\n const text = `${verb}: ${checkboxFor(todo.status)} ${todo.content}`;\n await emit(callback, text);\n return {\n success: true,\n text,\n data: { action: verb, op: verb, entityId: scope.entityId, todo },\n };\n}\n\nasync function actionDelete({\n service,\n scope,\n params,\n callback,\n}: ActionHandlerArgs): Promise<ActionResult> {\n const id = readString(params.id);\n if (!id) {\n return failure(\"missing_param\", \"id is required for action=delete\");\n }\n const existing = await service.get(id);\n if (!existing || !isOwnedByScope(existing, scope)) {\n return failure(\"not_found\", `todo ${id} not found for this user`);\n }\n const ok = await service.delete(id);\n if (!ok) {\n return failure(\"not_found\", `todo ${id} not found`);\n }\n const text = `Deleted: ${existing.content}`;\n await emit(callback, text);\n return {\n success: true,\n text,\n data: {\n action: \"delete\" as const,\n op: \"delete\" as const,\n entityId: scope.entityId,\n id,\n },\n };\n}\n\nasync function actionList({\n service,\n scope,\n params,\n callback,\n}: ActionHandlerArgs): Promise<ActionResult> {\n const includeCompleted = readBoolean(params.includeCompleted) ?? false;\n const limit = readNumber(params.limit);\n const filter: Parameters<TodosService[\"list\"]>[0] = {\n entityId: scope.entityId,\n agentId: scope.agentId,\n includeCompleted,\n };\n if (limit !== undefined) filter.limit = limit;\n const todos = await service.list(filter);\n const text = renderMarkdown(todos);\n await emit(callback, text);\n return {\n success: true,\n text,\n data: {\n action: \"list\" as const,\n op: \"list\" as const,\n entityId: scope.entityId,\n todos,\n },\n };\n}\n\nasync function actionClear({\n service,\n scope,\n callback,\n}: ActionHandlerArgs): Promise<ActionResult> {\n const filter: { entityId: string; agentId: string; roomId?: string } = {\n entityId: scope.entityId,\n agentId: scope.agentId,\n };\n if (scope.roomId) filter.roomId = scope.roomId;\n const count = await service.clear(filter);\n const text = `Cleared ${count} todo${count === 1 ? \"\" : \"s\"}.`;\n await emit(callback, text);\n return {\n success: true,\n text,\n data: {\n action: \"clear\" as const,\n op: \"clear\" as const,\n entityId: scope.entityId,\n count,\n },\n };\n}\n\n// Canonical planner-facing todo surface. Backed by the per-user @elizaos/core\n// TodosService store (filesystem under TODOS_BASE_PATH). The owner-store\n// equivalent — backed by app-lifeops definitions — is OWNER_TODOS in\n// plugins/plugin-personal-assistant/src/actions/owner-surfaces.ts. The two surfaces target\n// different stores and must not be merged.\nexport const todoAction: Action = {\n name: \"TODO\",\n contexts: [...TODOS_CONTEXTS],\n roleGate: { minRole: \"ADMIN\" },\n contextGate: { anyOf: [...TODOS_CONTEXTS] },\n tags: [\n \"domain:reminders\",\n \"capability:read\",\n \"capability:write\",\n \"capability:update\",\n \"capability:delete\",\n \"surface:internal\",\n ],\n similes: [\n \"TODO_WRITE\",\n \"WRITE_TODOS\",\n \"SET_TODOS\",\n \"UPDATE_TODOS\",\n \"TODO_CREATE\",\n \"CREATE_TODO\",\n \"TODO_UPDATE\",\n \"UPDATE_TODO\",\n \"TODO_COMPLETE\",\n \"COMPLETE_TODO\",\n \"FINISH_TODO\",\n \"TODO_CANCEL\",\n \"CANCEL_TODO\",\n \"TODO_DELETE\",\n \"DELETE_TODO\",\n \"REMOVE_TODO\",\n \"TODO_LIST\",\n \"LIST_TODOS\",\n \"GET_TODOS\",\n \"SHOW_TODOS\",\n \"TODO_CLEAR\",\n \"CLEAR_TODOS\",\n ],\n description:\n \"Manage the user's todo list. Actions: write (replace the list with `todos:[{id?, content, status, activeForm?}]`), create (add one), update (change by id), complete, cancel, delete, list, clear. Todos are user-scoped (entityId), persistent, and shared across rooms for the same user.\",\n descriptionCompressed:\n \"todos: write|create|update|complete|cancel|delete|list|clear; user-scoped (entityId)\",\n parameters: [\n {\n name: \"action\",\n description:\n \"Action: write, create, update, complete, cancel, delete, list, clear.\",\n required: true,\n schema: { type: \"string\" as const, enum: [...TODO_ACTIONS] },\n },\n {\n name: \"id\",\n description: \"Todo id (update/complete/cancel/delete).\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"content\",\n description: \"Imperative form, e.g. 'Add tests' (create/update).\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"activeForm\",\n description:\n \"Present-continuous form, e.g. 'Adding tests' (create/update).\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"status\",\n description: \"pending | in_progress | completed | cancelled.\",\n required: false,\n schema: { type: \"string\" as const, enum: [...TODO_STATUSES] },\n },\n {\n name: \"parentTodoId\",\n description: \"Parent todo id for sub-tasks (create/update).\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"todos\",\n description:\n \"Array of {id?, content, status, activeForm?} for action=write. Replaces the user's list for this conversation.\",\n required: false,\n schema: {\n type: \"array\" as const,\n items: {\n type: \"object\" as const,\n properties: {\n id: { type: \"string\" as const },\n content: { type: \"string\" as const },\n status: { type: \"string\" as const, enum: [...TODO_STATUSES] },\n activeForm: { type: \"string\" as const },\n },\n required: [\"content\", \"status\"],\n },\n },\n },\n {\n name: \"includeCompleted\",\n description: \"Include completed/cancelled todos in action=list output.\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"limit\",\n description: \"Max rows to return for action=list.\",\n required: false,\n schema: { type: \"number\" as const },\n },\n ],\n validate: async (runtime: IAgentRuntime) => Boolean(getTodosService(runtime)),\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: HandlerOptions,\n callback?: HandlerCallback,\n ): Promise<ActionResult> => {\n const params = (options?.parameters ?? {}) as TodoActionParameters;\n const action = readAction(params.action ?? params.subaction ?? params.op);\n if (!action) {\n return failure(\n \"missing_param\",\n `action is required (one of: ${TODO_ACTIONS.join(\", \")})`,\n );\n }\n const scope = readScope(runtime, message);\n if (\"error\" in scope) {\n return failure(\"missing_param\", scope.error);\n }\n try {\n const service = getTodosService(runtime);\n const args: ActionHandlerArgs = { service, scope, params, callback };\n switch (action) {\n case \"write\":\n return await actionWrite(args);\n case \"create\":\n return await actionCreate(args);\n case \"update\":\n return await actionUpdate(args);\n case \"complete\":\n return await actionSetStatus(args, \"completed\", \"complete\");\n case \"cancel\":\n return await actionSetStatus(args, \"cancelled\", \"cancel\");\n case \"delete\":\n return await actionDelete(args);\n case \"list\":\n return await actionList(args);\n case \"clear\":\n return await actionClear(args);\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"todo persistence failed\";\n return failure(\"persistence_error\", message);\n }\n },\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Add 'review PR feedback' to my todo list.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Adding the todo.\",\n actions: [\"TODO\"],\n thought:\n \"Single-todo creation maps to TODO action=create with content set.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Show my todos that are still pending.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Listing your pending todos.\",\n actions: [\"TODO\"],\n thought:\n \"List query maps to TODO action=list with includeCompleted=false.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Cancel todo abc-123.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Cancelling that todo.\",\n actions: [\"TODO\"],\n thought:\n \"Cancel intent on a specific id maps to TODO action=cancel with id=abc-123.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"rappelle-moi de relire l'audit demain\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Saved. I'll remind you tomorrow about the audit re-read.\",\n actions: [\"TODO\"],\n thought:\n \"Casual French reminder phrasing maps to TODO action=create. Plugin examples must cover non-English idiom so the few-shot extends past the literal 'Add X to my todo list' pattern.\",\n },\n },\n ],\n ],\n};\n"],"mappings":"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","names":["message"]}
|