@dexto/tools-todo 0.1.1
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/LICENSE +44 -0
- package/dist/error-codes.cjs +34 -0
- package/dist/error-codes.d.cts +11 -0
- package/dist/error-codes.d.ts +11 -0
- package/dist/error-codes.js +10 -0
- package/dist/errors.cjs +84 -0
- package/dist/errors.d.cts +32 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.js +60 -0
- package/dist/index.cjs +43 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +14 -0
- package/dist/todo-service.cjs +187 -0
- package/dist/todo-service.d.cts +53 -0
- package/dist/todo-service.d.ts +53 -0
- package/dist/todo-service.js +163 -0
- package/dist/todo-write-tool.cjs +75 -0
- package/dist/todo-write-tool.d.cts +16 -0
- package/dist/todo-write-tool.d.ts +16 -0
- package/dist/todo-write-tool.js +51 -0
- package/dist/tool-provider.cjs +68 -0
- package/dist/tool-provider.d.cts +39 -0
- package/dist/tool-provider.d.ts +39 -0
- package/dist/tool-provider.js +44 -0
- package/dist/types.cjs +28 -0
- package/dist/types.d.cts +56 -0
- package/dist/types.d.ts +56 -0
- package/dist/types.js +4 -0
- package/package.json +39 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Database, AgentEventBus, IDextoLogger } from '@dexto/core';
|
|
2
|
+
import { TodoConfig, TodoInput, TodoUpdateResult, Todo } from './types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Todo Service
|
|
6
|
+
*
|
|
7
|
+
* Manages todo lists for tracking agent workflow and task progress.
|
|
8
|
+
* Emits events through the AgentEventBus using the service:event pattern.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* TodoService - Manages todo lists for agent workflow tracking
|
|
13
|
+
*/
|
|
14
|
+
declare class TodoService {
|
|
15
|
+
private database;
|
|
16
|
+
private eventBus;
|
|
17
|
+
private logger;
|
|
18
|
+
private config;
|
|
19
|
+
private initialized;
|
|
20
|
+
constructor(database: Database, eventBus: AgentEventBus, logger: IDextoLogger, config?: TodoConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Initialize the service
|
|
23
|
+
*/
|
|
24
|
+
initialize(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Update todos for a session (replaces entire list)
|
|
27
|
+
*/
|
|
28
|
+
updateTodos(sessionId: string, todoInputs: TodoInput[]): Promise<TodoUpdateResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Get todos for a session
|
|
31
|
+
*/
|
|
32
|
+
getTodos(sessionId: string): Promise<Todo[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Generate database key for session todos
|
|
35
|
+
*/
|
|
36
|
+
private getTodosDatabaseKey;
|
|
37
|
+
/**
|
|
38
|
+
* Generate consistent key for todo matching (content + activeForm)
|
|
39
|
+
* Uses JSON encoding to prevent collisions when fields contain delimiters
|
|
40
|
+
*/
|
|
41
|
+
private getTodoKey;
|
|
42
|
+
/**
|
|
43
|
+
* Generate key from TodoInput
|
|
44
|
+
* Uses JSON encoding to prevent collisions when fields contain delimiters
|
|
45
|
+
*/
|
|
46
|
+
private getTodoKeyFromInput;
|
|
47
|
+
/**
|
|
48
|
+
* Validate todo status
|
|
49
|
+
*/
|
|
50
|
+
private validateTodoStatus;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { TodoService };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { nanoid } from "nanoid";
|
|
2
|
+
import { DextoRuntimeError } from "@dexto/core";
|
|
3
|
+
import { TodoError } from "./errors.js";
|
|
4
|
+
import { TODO_STATUS_VALUES } from "./types.js";
|
|
5
|
+
const DEFAULT_MAX_TODOS = 100;
|
|
6
|
+
const TODOS_KEY_PREFIX = "todos:";
|
|
7
|
+
class TodoService {
|
|
8
|
+
database;
|
|
9
|
+
eventBus;
|
|
10
|
+
logger;
|
|
11
|
+
config;
|
|
12
|
+
initialized = false;
|
|
13
|
+
constructor(database, eventBus, logger, config = {}) {
|
|
14
|
+
this.database = database;
|
|
15
|
+
this.eventBus = eventBus;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
this.config = {
|
|
18
|
+
maxTodosPerSession: config.maxTodosPerSession ?? DEFAULT_MAX_TODOS,
|
|
19
|
+
enableEvents: config.enableEvents ?? true
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the service
|
|
24
|
+
*/
|
|
25
|
+
async initialize() {
|
|
26
|
+
if (this.initialized) {
|
|
27
|
+
this.logger.debug("TodoService already initialized");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.initialized = true;
|
|
31
|
+
this.logger.info("TodoService initialized successfully");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Update todos for a session (replaces entire list)
|
|
35
|
+
*/
|
|
36
|
+
async updateTodos(sessionId, todoInputs) {
|
|
37
|
+
if (!this.initialized) {
|
|
38
|
+
throw TodoError.notInitialized();
|
|
39
|
+
}
|
|
40
|
+
if (todoInputs.length > this.config.maxTodosPerSession) {
|
|
41
|
+
throw TodoError.todoLimitExceeded(todoInputs.length, this.config.maxTodosPerSession);
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const existing = await this.getTodos(sessionId);
|
|
45
|
+
const existingMap = new Map(existing.map((t) => [this.getTodoKey(t), t]));
|
|
46
|
+
const now = /* @__PURE__ */ new Date();
|
|
47
|
+
const newTodos = [];
|
|
48
|
+
const stats = { created: 0, updated: 0, deleted: 0 };
|
|
49
|
+
for (let i = 0; i < todoInputs.length; i++) {
|
|
50
|
+
const input = todoInputs[i];
|
|
51
|
+
this.validateTodoStatus(input.status);
|
|
52
|
+
const todoKey = this.getTodoKeyFromInput(input);
|
|
53
|
+
const existingTodo = existingMap.get(todoKey);
|
|
54
|
+
if (existingTodo) {
|
|
55
|
+
const updated = {
|
|
56
|
+
...existingTodo,
|
|
57
|
+
status: input.status,
|
|
58
|
+
updatedAt: now,
|
|
59
|
+
position: i
|
|
60
|
+
};
|
|
61
|
+
newTodos.push(updated);
|
|
62
|
+
stats.updated++;
|
|
63
|
+
existingMap.delete(todoKey);
|
|
64
|
+
} else {
|
|
65
|
+
const created = {
|
|
66
|
+
id: nanoid(),
|
|
67
|
+
sessionId,
|
|
68
|
+
content: input.content,
|
|
69
|
+
activeForm: input.activeForm,
|
|
70
|
+
status: input.status,
|
|
71
|
+
position: i,
|
|
72
|
+
createdAt: now,
|
|
73
|
+
updatedAt: now
|
|
74
|
+
};
|
|
75
|
+
newTodos.push(created);
|
|
76
|
+
stats.created++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
stats.deleted = existingMap.size;
|
|
80
|
+
const key = this.getTodosDatabaseKey(sessionId);
|
|
81
|
+
await this.database.set(key, newTodos);
|
|
82
|
+
if (this.config.enableEvents) {
|
|
83
|
+
this.eventBus.emit("service:event", {
|
|
84
|
+
service: "todo",
|
|
85
|
+
event: "updated",
|
|
86
|
+
sessionId,
|
|
87
|
+
data: {
|
|
88
|
+
todos: newTodos,
|
|
89
|
+
stats
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
this.logger.debug(
|
|
94
|
+
`Updated todos for session ${sessionId}: ${stats.created} created, ${stats.updated} updated, ${stats.deleted} deleted`
|
|
95
|
+
);
|
|
96
|
+
return {
|
|
97
|
+
todos: newTodos,
|
|
98
|
+
sessionId,
|
|
99
|
+
...stats
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error instanceof DextoRuntimeError) {
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
throw TodoError.databaseError(
|
|
106
|
+
"updateTodos",
|
|
107
|
+
error instanceof Error ? error.message : String(error)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get todos for a session
|
|
113
|
+
*/
|
|
114
|
+
async getTodos(sessionId) {
|
|
115
|
+
if (!this.initialized) {
|
|
116
|
+
throw TodoError.notInitialized();
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const key = this.getTodosDatabaseKey(sessionId);
|
|
120
|
+
const todos = await this.database.get(key);
|
|
121
|
+
return todos || [];
|
|
122
|
+
} catch (error) {
|
|
123
|
+
if (error instanceof DextoRuntimeError) {
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
throw TodoError.databaseError(
|
|
127
|
+
"getTodos",
|
|
128
|
+
error instanceof Error ? error.message : String(error)
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate database key for session todos
|
|
134
|
+
*/
|
|
135
|
+
getTodosDatabaseKey(sessionId) {
|
|
136
|
+
return `${TODOS_KEY_PREFIX}${sessionId}`;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Generate consistent key for todo matching (content + activeForm)
|
|
140
|
+
* Uses JSON encoding to prevent collisions when fields contain delimiters
|
|
141
|
+
*/
|
|
142
|
+
getTodoKey(todo) {
|
|
143
|
+
return JSON.stringify([todo.content, todo.activeForm]);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Generate key from TodoInput
|
|
147
|
+
* Uses JSON encoding to prevent collisions when fields contain delimiters
|
|
148
|
+
*/
|
|
149
|
+
getTodoKeyFromInput(input) {
|
|
150
|
+
return JSON.stringify([input.content, input.activeForm]);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate todo status
|
|
154
|
+
*/
|
|
155
|
+
validateTodoStatus(status) {
|
|
156
|
+
if (!TODO_STATUS_VALUES.includes(status)) {
|
|
157
|
+
throw TodoError.invalidStatus(status);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export {
|
|
162
|
+
TodoService
|
|
163
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var todo_write_tool_exports = {};
|
|
20
|
+
__export(todo_write_tool_exports, {
|
|
21
|
+
createTodoWriteTool: () => createTodoWriteTool
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(todo_write_tool_exports);
|
|
24
|
+
var import_zod = require("zod");
|
|
25
|
+
var import_types = require("./types.js");
|
|
26
|
+
const TodoItemSchema = import_zod.z.object({
|
|
27
|
+
content: import_zod.z.string().min(1).describe('Task description in imperative form (e.g., "Fix authentication bug")'),
|
|
28
|
+
activeForm: import_zod.z.string().min(1).describe(
|
|
29
|
+
'Present continuous form shown during execution (e.g., "Fixing authentication bug")'
|
|
30
|
+
),
|
|
31
|
+
status: import_zod.z.enum(import_types.TODO_STATUS_VALUES).describe(
|
|
32
|
+
"Task status: pending (not started), in_progress (currently working), completed (finished)"
|
|
33
|
+
)
|
|
34
|
+
}).strict();
|
|
35
|
+
const TodoWriteInputSchema = import_zod.z.object({
|
|
36
|
+
todos: import_zod.z.array(TodoItemSchema).min(1).describe("Array of todo items representing the complete task list for the session")
|
|
37
|
+
}).strict().superRefine((value, ctx) => {
|
|
38
|
+
const inProgressCount = value.todos.filter((todo) => todo.status === "in_progress").length;
|
|
39
|
+
if (inProgressCount > 1) {
|
|
40
|
+
ctx.addIssue({
|
|
41
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
42
|
+
message: "Only one todo may be in_progress at a time.",
|
|
43
|
+
path: ["todos"]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}).describe(
|
|
47
|
+
"Manage task list for current session. Replaces the entire todo list with the provided tasks."
|
|
48
|
+
);
|
|
49
|
+
function createTodoWriteTool(todoService) {
|
|
50
|
+
return {
|
|
51
|
+
id: "todo_write",
|
|
52
|
+
description: `Track progress on multi-step tasks. Use for:
|
|
53
|
+
- Implementation tasks with 3+ steps (features, refactors, bug fixes)
|
|
54
|
+
- Tasks where the user asks for a plan or breakdown
|
|
55
|
+
- Complex workflows where progress visibility helps
|
|
56
|
+
|
|
57
|
+
Do NOT use for simple single-file edits, quick questions, or explanations.
|
|
58
|
+
|
|
59
|
+
IMPORTANT: This replaces the entire todo list. Always include ALL tasks (pending, in_progress, completed). Only ONE task should be in_progress at a time. Update status as you work: pending \u2192 in_progress \u2192 completed.`,
|
|
60
|
+
inputSchema: TodoWriteInputSchema,
|
|
61
|
+
execute: async (input, context) => {
|
|
62
|
+
const validatedInput = TodoWriteInputSchema.parse(input);
|
|
63
|
+
const sessionId = context?.sessionId ?? "default";
|
|
64
|
+
const result = await todoService.updateTodos(sessionId, validatedInput.todos);
|
|
65
|
+
const completed = result.todos.filter((t) => t.status === "completed").length;
|
|
66
|
+
const inProgress = result.todos.filter((t) => t.status === "in_progress").length;
|
|
67
|
+
const pending = result.todos.filter((t) => t.status === "pending").length;
|
|
68
|
+
return `Updated tasks: ${completed}/${result.todos.length} completed${inProgress > 0 ? `, 1 in progress` : ""}${pending > 0 ? `, ${pending} pending` : ""}`;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
73
|
+
0 && (module.exports = {
|
|
74
|
+
createTodoWriteTool
|
|
75
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InternalTool } from '@dexto/core';
|
|
2
|
+
import { TodoService } from './todo-service.cjs';
|
|
3
|
+
import './types.cjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Todo Write Tool
|
|
7
|
+
*
|
|
8
|
+
* Manages task lists for tracking agent progress and workflow organization
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create todo_write internal tool
|
|
13
|
+
*/
|
|
14
|
+
declare function createTodoWriteTool(todoService: TodoService): InternalTool;
|
|
15
|
+
|
|
16
|
+
export { createTodoWriteTool };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InternalTool } from '@dexto/core';
|
|
2
|
+
import { TodoService } from './todo-service.js';
|
|
3
|
+
import './types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Todo Write Tool
|
|
7
|
+
*
|
|
8
|
+
* Manages task lists for tracking agent progress and workflow organization
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create todo_write internal tool
|
|
13
|
+
*/
|
|
14
|
+
declare function createTodoWriteTool(todoService: TodoService): InternalTool;
|
|
15
|
+
|
|
16
|
+
export { createTodoWriteTool };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { TODO_STATUS_VALUES } from "./types.js";
|
|
3
|
+
const TodoItemSchema = z.object({
|
|
4
|
+
content: z.string().min(1).describe('Task description in imperative form (e.g., "Fix authentication bug")'),
|
|
5
|
+
activeForm: z.string().min(1).describe(
|
|
6
|
+
'Present continuous form shown during execution (e.g., "Fixing authentication bug")'
|
|
7
|
+
),
|
|
8
|
+
status: z.enum(TODO_STATUS_VALUES).describe(
|
|
9
|
+
"Task status: pending (not started), in_progress (currently working), completed (finished)"
|
|
10
|
+
)
|
|
11
|
+
}).strict();
|
|
12
|
+
const TodoWriteInputSchema = z.object({
|
|
13
|
+
todos: z.array(TodoItemSchema).min(1).describe("Array of todo items representing the complete task list for the session")
|
|
14
|
+
}).strict().superRefine((value, ctx) => {
|
|
15
|
+
const inProgressCount = value.todos.filter((todo) => todo.status === "in_progress").length;
|
|
16
|
+
if (inProgressCount > 1) {
|
|
17
|
+
ctx.addIssue({
|
|
18
|
+
code: z.ZodIssueCode.custom,
|
|
19
|
+
message: "Only one todo may be in_progress at a time.",
|
|
20
|
+
path: ["todos"]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}).describe(
|
|
24
|
+
"Manage task list for current session. Replaces the entire todo list with the provided tasks."
|
|
25
|
+
);
|
|
26
|
+
function createTodoWriteTool(todoService) {
|
|
27
|
+
return {
|
|
28
|
+
id: "todo_write",
|
|
29
|
+
description: `Track progress on multi-step tasks. Use for:
|
|
30
|
+
- Implementation tasks with 3+ steps (features, refactors, bug fixes)
|
|
31
|
+
- Tasks where the user asks for a plan or breakdown
|
|
32
|
+
- Complex workflows where progress visibility helps
|
|
33
|
+
|
|
34
|
+
Do NOT use for simple single-file edits, quick questions, or explanations.
|
|
35
|
+
|
|
36
|
+
IMPORTANT: This replaces the entire todo list. Always include ALL tasks (pending, in_progress, completed). Only ONE task should be in_progress at a time. Update status as you work: pending \u2192 in_progress \u2192 completed.`,
|
|
37
|
+
inputSchema: TodoWriteInputSchema,
|
|
38
|
+
execute: async (input, context) => {
|
|
39
|
+
const validatedInput = TodoWriteInputSchema.parse(input);
|
|
40
|
+
const sessionId = context?.sessionId ?? "default";
|
|
41
|
+
const result = await todoService.updateTodos(sessionId, validatedInput.todos);
|
|
42
|
+
const completed = result.todos.filter((t) => t.status === "completed").length;
|
|
43
|
+
const inProgress = result.todos.filter((t) => t.status === "in_progress").length;
|
|
44
|
+
const pending = result.todos.filter((t) => t.status === "pending").length;
|
|
45
|
+
return `Updated tasks: ${completed}/${result.todos.length} completed${inProgress > 0 ? `, 1 in progress` : ""}${pending > 0 ? `, ${pending} pending` : ""}`;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
createTodoWriteTool
|
|
51
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var tool_provider_exports = {};
|
|
20
|
+
__export(tool_provider_exports, {
|
|
21
|
+
todoToolsProvider: () => todoToolsProvider
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(tool_provider_exports);
|
|
24
|
+
var import_zod = require("zod");
|
|
25
|
+
var import_todo_service = require("./todo-service.js");
|
|
26
|
+
var import_todo_write_tool = require("./todo-write-tool.js");
|
|
27
|
+
const DEFAULT_MAX_TODOS_PER_SESSION = 100;
|
|
28
|
+
const DEFAULT_ENABLE_EVENTS = true;
|
|
29
|
+
const TodoToolsConfigSchema = import_zod.z.object({
|
|
30
|
+
type: import_zod.z.literal("todo-tools"),
|
|
31
|
+
maxTodosPerSession: import_zod.z.number().int().positive().default(DEFAULT_MAX_TODOS_PER_SESSION).describe(`Maximum todos per session (default: ${DEFAULT_MAX_TODOS_PER_SESSION})`),
|
|
32
|
+
enableEvents: import_zod.z.boolean().default(DEFAULT_ENABLE_EVENTS).describe("Enable real-time events for todo updates")
|
|
33
|
+
}).strict();
|
|
34
|
+
const todoToolsProvider = {
|
|
35
|
+
type: "todo-tools",
|
|
36
|
+
configSchema: TodoToolsConfigSchema,
|
|
37
|
+
create: (config, context) => {
|
|
38
|
+
const { logger, agent, services } = context;
|
|
39
|
+
logger.debug("Creating TodoService for todo tools");
|
|
40
|
+
const storageManager = services?.storageManager;
|
|
41
|
+
if (!storageManager) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
"TodoService requires storageManager service. Ensure it is available in ToolCreationContext."
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const database = storageManager.getDatabase();
|
|
47
|
+
const eventBus = agent.agentEventBus;
|
|
48
|
+
const todoService = new import_todo_service.TodoService(database, eventBus, logger, {
|
|
49
|
+
maxTodosPerSession: config.maxTodosPerSession,
|
|
50
|
+
enableEvents: config.enableEvents
|
|
51
|
+
});
|
|
52
|
+
todoService.initialize().catch((error) => {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
logger.error(`TodoToolsProvider.create: Failed to initialize TodoService: ${message}`);
|
|
55
|
+
});
|
|
56
|
+
logger.debug("TodoService created - initialization will complete on first tool use");
|
|
57
|
+
return [(0, import_todo_write_tool.createTodoWriteTool)(todoService)];
|
|
58
|
+
},
|
|
59
|
+
metadata: {
|
|
60
|
+
displayName: "Todo Tools",
|
|
61
|
+
description: "Task tracking and workflow management (todo_write)",
|
|
62
|
+
category: "workflow"
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
66
|
+
0 && (module.exports = {
|
|
67
|
+
todoToolsProvider
|
|
68
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CustomToolProvider } from '@dexto/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Todo Tools Provider
|
|
6
|
+
*
|
|
7
|
+
* Provides task tracking tools by wrapping TodoService.
|
|
8
|
+
* When registered, the provider initializes TodoService and creates the
|
|
9
|
+
* todo_write tool for managing task lists.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Configuration schema for Todo tools provider.
|
|
14
|
+
*/
|
|
15
|
+
declare const TodoToolsConfigSchema: z.ZodObject<{
|
|
16
|
+
type: z.ZodLiteral<"todo-tools">;
|
|
17
|
+
maxTodosPerSession: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
enableEvents: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
}, "strict", z.ZodTypeAny, {
|
|
20
|
+
maxTodosPerSession: number;
|
|
21
|
+
enableEvents: boolean;
|
|
22
|
+
type: "todo-tools";
|
|
23
|
+
}, {
|
|
24
|
+
type: "todo-tools";
|
|
25
|
+
maxTodosPerSession?: number | undefined;
|
|
26
|
+
enableEvents?: boolean | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
type TodoToolsConfig = z.output<typeof TodoToolsConfigSchema>;
|
|
29
|
+
/**
|
|
30
|
+
* Todo tools provider.
|
|
31
|
+
*
|
|
32
|
+
* Wraps TodoService and provides the todo_write tool for managing task lists.
|
|
33
|
+
*
|
|
34
|
+
* When registered via customToolRegistry, TodoService is automatically
|
|
35
|
+
* initialized and the todo_write tool becomes available to the agent.
|
|
36
|
+
*/
|
|
37
|
+
declare const todoToolsProvider: CustomToolProvider<'todo-tools', TodoToolsConfig>;
|
|
38
|
+
|
|
39
|
+
export { todoToolsProvider };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CustomToolProvider } from '@dexto/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Todo Tools Provider
|
|
6
|
+
*
|
|
7
|
+
* Provides task tracking tools by wrapping TodoService.
|
|
8
|
+
* When registered, the provider initializes TodoService and creates the
|
|
9
|
+
* todo_write tool for managing task lists.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Configuration schema for Todo tools provider.
|
|
14
|
+
*/
|
|
15
|
+
declare const TodoToolsConfigSchema: z.ZodObject<{
|
|
16
|
+
type: z.ZodLiteral<"todo-tools">;
|
|
17
|
+
maxTodosPerSession: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
enableEvents: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
}, "strict", z.ZodTypeAny, {
|
|
20
|
+
maxTodosPerSession: number;
|
|
21
|
+
enableEvents: boolean;
|
|
22
|
+
type: "todo-tools";
|
|
23
|
+
}, {
|
|
24
|
+
type: "todo-tools";
|
|
25
|
+
maxTodosPerSession?: number | undefined;
|
|
26
|
+
enableEvents?: boolean | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
type TodoToolsConfig = z.output<typeof TodoToolsConfigSchema>;
|
|
29
|
+
/**
|
|
30
|
+
* Todo tools provider.
|
|
31
|
+
*
|
|
32
|
+
* Wraps TodoService and provides the todo_write tool for managing task lists.
|
|
33
|
+
*
|
|
34
|
+
* When registered via customToolRegistry, TodoService is automatically
|
|
35
|
+
* initialized and the todo_write tool becomes available to the agent.
|
|
36
|
+
*/
|
|
37
|
+
declare const todoToolsProvider: CustomToolProvider<'todo-tools', TodoToolsConfig>;
|
|
38
|
+
|
|
39
|
+
export { todoToolsProvider };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { TodoService } from "./todo-service.js";
|
|
3
|
+
import { createTodoWriteTool } from "./todo-write-tool.js";
|
|
4
|
+
const DEFAULT_MAX_TODOS_PER_SESSION = 100;
|
|
5
|
+
const DEFAULT_ENABLE_EVENTS = true;
|
|
6
|
+
const TodoToolsConfigSchema = z.object({
|
|
7
|
+
type: z.literal("todo-tools"),
|
|
8
|
+
maxTodosPerSession: z.number().int().positive().default(DEFAULT_MAX_TODOS_PER_SESSION).describe(`Maximum todos per session (default: ${DEFAULT_MAX_TODOS_PER_SESSION})`),
|
|
9
|
+
enableEvents: z.boolean().default(DEFAULT_ENABLE_EVENTS).describe("Enable real-time events for todo updates")
|
|
10
|
+
}).strict();
|
|
11
|
+
const todoToolsProvider = {
|
|
12
|
+
type: "todo-tools",
|
|
13
|
+
configSchema: TodoToolsConfigSchema,
|
|
14
|
+
create: (config, context) => {
|
|
15
|
+
const { logger, agent, services } = context;
|
|
16
|
+
logger.debug("Creating TodoService for todo tools");
|
|
17
|
+
const storageManager = services?.storageManager;
|
|
18
|
+
if (!storageManager) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
"TodoService requires storageManager service. Ensure it is available in ToolCreationContext."
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
const database = storageManager.getDatabase();
|
|
24
|
+
const eventBus = agent.agentEventBus;
|
|
25
|
+
const todoService = new TodoService(database, eventBus, logger, {
|
|
26
|
+
maxTodosPerSession: config.maxTodosPerSession,
|
|
27
|
+
enableEvents: config.enableEvents
|
|
28
|
+
});
|
|
29
|
+
todoService.initialize().catch((error) => {
|
|
30
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
31
|
+
logger.error(`TodoToolsProvider.create: Failed to initialize TodoService: ${message}`);
|
|
32
|
+
});
|
|
33
|
+
logger.debug("TodoService created - initialization will complete on first tool use");
|
|
34
|
+
return [createTodoWriteTool(todoService)];
|
|
35
|
+
},
|
|
36
|
+
metadata: {
|
|
37
|
+
displayName: "Todo Tools",
|
|
38
|
+
description: "Task tracking and workflow management (todo_write)",
|
|
39
|
+
category: "workflow"
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
todoToolsProvider
|
|
44
|
+
};
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var types_exports = {};
|
|
20
|
+
__export(types_exports, {
|
|
21
|
+
TODO_STATUS_VALUES: () => TODO_STATUS_VALUES
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(types_exports);
|
|
24
|
+
const TODO_STATUS_VALUES = ["pending", "in_progress", "completed"];
|
|
25
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
26
|
+
0 && (module.exports = {
|
|
27
|
+
TODO_STATUS_VALUES
|
|
28
|
+
});
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Todo Service Types
|
|
3
|
+
*
|
|
4
|
+
* Types for todo list management and workflow tracking
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Valid todo status values
|
|
8
|
+
* Centralized constant to prevent duplication across domains
|
|
9
|
+
*/
|
|
10
|
+
declare const TODO_STATUS_VALUES: readonly ["pending", "in_progress", "completed"];
|
|
11
|
+
/**
|
|
12
|
+
* Todo item status
|
|
13
|
+
*/
|
|
14
|
+
type TodoStatus = (typeof TODO_STATUS_VALUES)[number];
|
|
15
|
+
/**
|
|
16
|
+
* Todo item with system metadata
|
|
17
|
+
*/
|
|
18
|
+
interface Todo {
|
|
19
|
+
id: string;
|
|
20
|
+
sessionId: string;
|
|
21
|
+
content: string;
|
|
22
|
+
activeForm: string;
|
|
23
|
+
status: TodoStatus;
|
|
24
|
+
position: number;
|
|
25
|
+
createdAt: Date;
|
|
26
|
+
updatedAt: Date;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Todo input from tool (without system metadata)
|
|
30
|
+
*/
|
|
31
|
+
interface TodoInput {
|
|
32
|
+
content: string;
|
|
33
|
+
activeForm: string;
|
|
34
|
+
status: TodoStatus;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Todo list update result
|
|
38
|
+
*/
|
|
39
|
+
interface TodoUpdateResult {
|
|
40
|
+
todos: Todo[];
|
|
41
|
+
sessionId: string;
|
|
42
|
+
created: number;
|
|
43
|
+
updated: number;
|
|
44
|
+
deleted: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Configuration for TodoService
|
|
48
|
+
*/
|
|
49
|
+
interface TodoConfig {
|
|
50
|
+
/** Maximum todos per session */
|
|
51
|
+
maxTodosPerSession?: number;
|
|
52
|
+
/** Enable real-time events */
|
|
53
|
+
enableEvents?: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { TODO_STATUS_VALUES, type Todo, type TodoConfig, type TodoInput, type TodoStatus, type TodoUpdateResult };
|