@prmichaelsen/task-mcp 0.2.0
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/.env.example +19 -0
- package/AGENT.md +1165 -0
- package/CHANGELOG.md +72 -0
- package/agent/commands/acp.commit.md +511 -0
- package/agent/commands/acp.init.md +376 -0
- package/agent/commands/acp.package-install.md +347 -0
- package/agent/commands/acp.proceed.md +311 -0
- package/agent/commands/acp.report.md +392 -0
- package/agent/commands/acp.status.md +280 -0
- package/agent/commands/acp.sync.md +323 -0
- package/agent/commands/acp.update.md +301 -0
- package/agent/commands/acp.validate.md +385 -0
- package/agent/commands/acp.version-check-for-updates.md +275 -0
- package/agent/commands/acp.version-check.md +190 -0
- package/agent/commands/acp.version-update.md +288 -0
- package/agent/commands/command.template.md +273 -0
- package/agent/commands/git.commit.md +511 -0
- package/agent/commands/git.init.md +513 -0
- package/agent/design/.gitkeep +0 -0
- package/agent/design/acp-task-execution-requirements.md +555 -0
- package/agent/design/api-dto-design.md +394 -0
- package/agent/design/code-extraction-guide.md +827 -0
- package/agent/design/design.template.md +136 -0
- package/agent/design/requirements.template.md +387 -0
- package/agent/design/rest-api-integration.md +489 -0
- package/agent/design/sdk-export-requirements.md +549 -0
- package/agent/milestones/.gitkeep +0 -0
- package/agent/milestones/milestone-1-{title}.template.md +206 -0
- package/agent/milestones/milestone-2-task-infrastructure.md +232 -0
- package/agent/milestones/milestone-4-autonomous-execution.md +235 -0
- package/agent/patterns/.gitkeep +0 -0
- package/agent/patterns/bootstrap.md +1271 -0
- package/agent/patterns/bootstrap.template.md +1237 -0
- package/agent/patterns/pattern.template.md +364 -0
- package/agent/progress.template.yaml +158 -0
- package/agent/progress.yaml +375 -0
- package/agent/scripts/check-for-updates.sh +88 -0
- package/agent/scripts/install.sh +157 -0
- package/agent/scripts/uninstall.sh +75 -0
- package/agent/scripts/update.sh +139 -0
- package/agent/scripts/version.sh +35 -0
- package/agent/tasks/.gitkeep +0 -0
- package/agent/tasks/task-1-{title}.template.md +225 -0
- package/agent/tasks/task-86-task-data-model-schemas.md +143 -0
- package/agent/tasks/task-87-task-database-service.md +220 -0
- package/agent/tasks/task-88-firebase-client-wrapper.md +139 -0
- package/agent/tasks/task-88-task-execution-engine.md +277 -0
- package/agent/tasks/task-89-mcp-server-implementation.md +197 -0
- package/agent/tasks/task-90-build-configuration.md +146 -0
- package/agent/tasks/task-91-deployment-configuration.md +128 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +191 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +191 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/src/client.ts.html +1030 -0
- package/coverage/lcov-report/src/constant/collections.ts.html +469 -0
- package/coverage/lcov-report/src/constant/index.html +116 -0
- package/coverage/lcov-report/src/dto/index.html +116 -0
- package/coverage/lcov-report/src/dto/transformers.ts.html +568 -0
- package/coverage/lcov-report/src/index.html +146 -0
- package/coverage/lcov-report/src/schemas/index.html +116 -0
- package/coverage/lcov-report/src/schemas/task.ts.html +547 -0
- package/coverage/lcov-report/src/server-factory.ts.html +418 -0
- package/coverage/lcov-report/src/server.ts.html +289 -0
- package/coverage/lcov-report/src/services/index.html +116 -0
- package/coverage/lcov-report/src/services/task-database.service.ts.html +1495 -0
- package/coverage/lcov-report/src/tools/index.html +236 -0
- package/coverage/lcov-report/src/tools/index.ts.html +292 -0
- package/coverage/lcov-report/src/tools/task-add-message.ts.html +277 -0
- package/coverage/lcov-report/src/tools/task-complete-task-item.ts.html +343 -0
- package/coverage/lcov-report/src/tools/task-create-milestone.ts.html +286 -0
- package/coverage/lcov-report/src/tools/task-create-task-item.ts.html +358 -0
- package/coverage/lcov-report/src/tools/task-get-next-step.ts.html +460 -0
- package/coverage/lcov-report/src/tools/task-get-status.ts.html +316 -0
- package/coverage/lcov-report/src/tools/task-report-completion.ts.html +343 -0
- package/coverage/lcov-report/src/tools/task-update-progress.ts.html +232 -0
- package/coverage/lcov.info +974 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/src/client.ts.html +1030 -0
- package/coverage/src/constant/collections.ts.html +469 -0
- package/coverage/src/constant/index.html +116 -0
- package/coverage/src/dto/index.html +116 -0
- package/coverage/src/dto/transformers.ts.html +568 -0
- package/coverage/src/index.html +146 -0
- package/coverage/src/schemas/index.html +116 -0
- package/coverage/src/schemas/task.ts.html +547 -0
- package/coverage/src/server-factory.ts.html +418 -0
- package/coverage/src/server.ts.html +289 -0
- package/coverage/src/services/index.html +116 -0
- package/coverage/src/services/task-database.service.ts.html +1495 -0
- package/coverage/src/tools/index.html +236 -0
- package/coverage/src/tools/index.ts.html +292 -0
- package/coverage/src/tools/task-add-message.ts.html +277 -0
- package/coverage/src/tools/task-complete-task-item.ts.html +343 -0
- package/coverage/src/tools/task-create-milestone.ts.html +286 -0
- package/coverage/src/tools/task-create-task-item.ts.html +358 -0
- package/coverage/src/tools/task-get-next-step.ts.html +460 -0
- package/coverage/src/tools/task-get-status.ts.html +316 -0
- package/coverage/src/tools/task-report-completion.ts.html +343 -0
- package/coverage/src/tools/task-update-progress.ts.html +232 -0
- package/firestore.rules +95 -0
- package/jest.config.js +31 -0
- package/package.json +67 -0
- package/src/client.spec.ts +199 -0
- package/src/client.ts +315 -0
- package/src/constant/collections.ts +128 -0
- package/src/dto/index.ts +47 -0
- package/src/dto/task-api.dto.ts +219 -0
- package/src/dto/transformers.spec.ts +462 -0
- package/src/dto/transformers.ts +161 -0
- package/src/schemas/task.ts +154 -0
- package/src/server-factory.spec.ts +70 -0
- package/src/server-factory.ts +111 -0
- package/src/server.ts +68 -0
- package/src/services/task-database.service.e2e.ts +116 -0
- package/src/services/task-database.service.spec.ts +479 -0
- package/src/services/task-database.service.ts +470 -0
- package/src/test-schemas.ts +161 -0
- package/src/tools/index.ts +69 -0
- package/src/tools/task-add-message.ts +64 -0
- package/src/tools/task-complete-task-item.ts +86 -0
- package/src/tools/task-create-milestone.ts +67 -0
- package/src/tools/task-create-task-item.ts +91 -0
- package/src/tools/task-get-next-step.spec.ts +136 -0
- package/src/tools/task-get-next-step.ts +125 -0
- package/src/tools/task-get-status.spec.ts +213 -0
- package/src/tools/task-get-status.ts +77 -0
- package/src/tools/task-report-completion.ts +86 -0
- package/src/tools/task-update-progress.ts +49 -0
- package/src/tools/tools.spec.ts +194 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Task 87: Task Database Service
|
|
2
|
+
|
|
3
|
+
**Milestone**: Milestone 1 - Task Infrastructure
|
|
4
|
+
**Estimated Time**: 12 hours
|
|
5
|
+
**Dependencies**: Task 86 (Task Data Model and Schemas)
|
|
6
|
+
**Status**: Not Started
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Objective
|
|
11
|
+
|
|
12
|
+
Create a database service for task CRUD operations, task message operations, and progress tracking. This service will handle all Firestore interactions for tasks.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
### 1. Create TaskDatabaseService Class
|
|
17
|
+
|
|
18
|
+
Create `src/services/task-database.service.ts` with methods for:
|
|
19
|
+
- Creating tasks
|
|
20
|
+
- Reading tasks
|
|
21
|
+
- Updating tasks
|
|
22
|
+
- Deleting tasks
|
|
23
|
+
- Listing user tasks
|
|
24
|
+
|
|
25
|
+
### 2. Implement Task Message Operations
|
|
26
|
+
|
|
27
|
+
Add methods for:
|
|
28
|
+
- Adding messages to task
|
|
29
|
+
- Getting task messages
|
|
30
|
+
- Updating message
|
|
31
|
+
- Deleting message
|
|
32
|
+
|
|
33
|
+
### 3. Implement Progress Operations
|
|
34
|
+
|
|
35
|
+
Add methods for:
|
|
36
|
+
- Updating overall progress
|
|
37
|
+
- Creating milestone
|
|
38
|
+
- Updating milestone
|
|
39
|
+
- Completing milestone
|
|
40
|
+
- Creating task item
|
|
41
|
+
- Updating task item
|
|
42
|
+
- Completing task item
|
|
43
|
+
|
|
44
|
+
### 4. Add Query Methods
|
|
45
|
+
|
|
46
|
+
Add methods for:
|
|
47
|
+
- Get tasks by status
|
|
48
|
+
- Get active tasks
|
|
49
|
+
- Get completed tasks
|
|
50
|
+
- Search tasks by title
|
|
51
|
+
|
|
52
|
+
### 5. Write Unit Tests
|
|
53
|
+
|
|
54
|
+
Create `src/services/__tests__/task-database.service.spec.ts`:
|
|
55
|
+
- Test CRUD operations with mocked Firestore
|
|
56
|
+
- Test progress operations
|
|
57
|
+
- Test query methods
|
|
58
|
+
- Test error handling
|
|
59
|
+
|
|
60
|
+
### 6. Write E2E Tests
|
|
61
|
+
|
|
62
|
+
Create `src/services/__tests__/task-database.service.e2e.ts`:
|
|
63
|
+
- Test with real Firestore emulator
|
|
64
|
+
- Test concurrent operations
|
|
65
|
+
- Test transaction handling
|
|
66
|
+
|
|
67
|
+
## Verification
|
|
68
|
+
|
|
69
|
+
- [ ] All CRUD operations work
|
|
70
|
+
- [ ] Task messages can be added/retrieved
|
|
71
|
+
- [ ] Progress can be updated
|
|
72
|
+
- [ ] Milestones can be managed
|
|
73
|
+
- [ ] Task items can be managed
|
|
74
|
+
- [ ] Query methods return correct results
|
|
75
|
+
- [ ] User isolation is enforced
|
|
76
|
+
- [ ] Unit tests pass
|
|
77
|
+
- [ ] E2E tests pass
|
|
78
|
+
- [ ] Error handling works correctly
|
|
79
|
+
|
|
80
|
+
## Example Service Structure
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// src/services/task-database.service.ts
|
|
84
|
+
import { getDocument, setDocument, addDocument, queryDocuments } from '@prmichaelsen/firebase-admin-sdk-v8'
|
|
85
|
+
import { getUserTasks, getUserTaskMessages } from '@/constant/collections'
|
|
86
|
+
import { TaskSchema, type Task, type Milestone, type TaskItem } from '@/schemas/task'
|
|
87
|
+
|
|
88
|
+
export class TaskDatabaseService {
|
|
89
|
+
/**
|
|
90
|
+
* Create a new task
|
|
91
|
+
*/
|
|
92
|
+
static async createTask(
|
|
93
|
+
userId: string,
|
|
94
|
+
title: string,
|
|
95
|
+
description: string,
|
|
96
|
+
config?: Partial<Task['config']>
|
|
97
|
+
): Promise<Task> {
|
|
98
|
+
const now = new Date().toISOString()
|
|
99
|
+
|
|
100
|
+
const task: Omit<Task, 'id'> = {
|
|
101
|
+
user_id: userId,
|
|
102
|
+
title,
|
|
103
|
+
description,
|
|
104
|
+
status: 'not_started',
|
|
105
|
+
created_at: now,
|
|
106
|
+
updated_at: now,
|
|
107
|
+
progress: {
|
|
108
|
+
current_milestone: '',
|
|
109
|
+
current_task: '',
|
|
110
|
+
overall_percentage: 0,
|
|
111
|
+
milestones: [],
|
|
112
|
+
tasks: {}
|
|
113
|
+
},
|
|
114
|
+
execution: {
|
|
115
|
+
api_messages: [],
|
|
116
|
+
task_messages: [],
|
|
117
|
+
tool_results: []
|
|
118
|
+
},
|
|
119
|
+
config: {
|
|
120
|
+
model: config?.model || 'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
121
|
+
system_prompt: config?.system_prompt || '',
|
|
122
|
+
auto_approve: config?.auto_approve ?? true,
|
|
123
|
+
max_iterations: config?.max_iterations || 100,
|
|
124
|
+
timeout_minutes: config?.timeout_minutes || 120
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const tasksPath = getUserTasks(userId)
|
|
129
|
+
const docRef = await addDocument(tasksPath, task)
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
id: docRef.id,
|
|
133
|
+
...task
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get a task by ID
|
|
139
|
+
*/
|
|
140
|
+
static async getTask(userId: string, taskId: string): Promise<Task | null> {
|
|
141
|
+
const tasksPath = getUserTasks(userId)
|
|
142
|
+
const doc = await getDocument(tasksPath, taskId)
|
|
143
|
+
|
|
144
|
+
if (!doc) return null
|
|
145
|
+
|
|
146
|
+
const result = TaskSchema.safeParse({ id: taskId, ...doc })
|
|
147
|
+
return result.success ? result.data : null
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Update task status
|
|
152
|
+
*/
|
|
153
|
+
static async updateTaskStatus(
|
|
154
|
+
userId: string,
|
|
155
|
+
taskId: string,
|
|
156
|
+
status: Task['status']
|
|
157
|
+
): Promise<void> {
|
|
158
|
+
const tasksPath = getUserTasks(userId)
|
|
159
|
+
await setDocument(tasksPath, taskId, {
|
|
160
|
+
status,
|
|
161
|
+
updated_at: new Date().toISOString()
|
|
162
|
+
}, { merge: true })
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create a milestone
|
|
167
|
+
*/
|
|
168
|
+
static async createMilestone(
|
|
169
|
+
userId: string,
|
|
170
|
+
taskId: string,
|
|
171
|
+
milestone: Milestone
|
|
172
|
+
): Promise<void> {
|
|
173
|
+
const task = await this.getTask(userId, taskId)
|
|
174
|
+
if (!task) throw new Error('Task not found')
|
|
175
|
+
|
|
176
|
+
task.progress.milestones.push(milestone)
|
|
177
|
+
|
|
178
|
+
const tasksPath = getUserTasks(userId)
|
|
179
|
+
await setDocument(tasksPath, taskId, {
|
|
180
|
+
progress: task.progress,
|
|
181
|
+
updated_at: new Date().toISOString()
|
|
182
|
+
}, { merge: true })
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Add message to task
|
|
187
|
+
*/
|
|
188
|
+
static async addMessage(
|
|
189
|
+
userId: string,
|
|
190
|
+
taskId: string,
|
|
191
|
+
role: 'user' | 'assistant' | 'system',
|
|
192
|
+
content: string,
|
|
193
|
+
metadata?: any
|
|
194
|
+
): Promise<string> {
|
|
195
|
+
const messagesPath = getUserTaskMessages(userId, taskId)
|
|
196
|
+
const message = {
|
|
197
|
+
task_id: taskId,
|
|
198
|
+
role,
|
|
199
|
+
content,
|
|
200
|
+
timestamp: new Date().toISOString(),
|
|
201
|
+
metadata
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const docRef = await addDocument(messagesPath, message)
|
|
205
|
+
return docRef.id
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ... more methods
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Files to Create
|
|
213
|
+
|
|
214
|
+
- `src/services/task-database.service.ts`
|
|
215
|
+
- `src/services/__tests__/task-database.service.spec.ts`
|
|
216
|
+
- `src/services/__tests__/task-database.service.e2e.ts`
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
**Next Task**: [Task 88: Task Execution Engine](task-88-task-execution-engine.md)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Task 88: Firebase Client Wrapper & MCP Tools Foundation
|
|
2
|
+
|
|
3
|
+
**Milestone**: Milestone 2 - MCP Server Foundation
|
|
4
|
+
**Estimated Time**: 16 hours (revised from original scope)
|
|
5
|
+
**Dependencies**: Task 87 (Task Database Service)
|
|
6
|
+
**Status**: Not Started
|
|
7
|
+
**Last Updated**: 2026-02-16
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Objective
|
|
12
|
+
|
|
13
|
+
**REVISED**: Create Firebase Admin SDK client wrapper and foundational MCP tools for task-mcp server. This task was originally scoped for agentbase.me TaskExecutor but has been revised to match task-mcp's role as an MCP tool server that provides instructions to tenant platforms.
|
|
14
|
+
|
|
15
|
+
**Original Scope** (archived): TaskExecutor with Bedrock integration for agentbase.me
|
|
16
|
+
**Revised Scope**: Firebase client + core MCP tools for task-mcp server
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
### 1. Create Firebase Client Wrapper
|
|
23
|
+
|
|
24
|
+
Create `src/client.ts`:
|
|
25
|
+
- Wrapper around TaskDatabaseService
|
|
26
|
+
- Service account authentication
|
|
27
|
+
- User-scoped operations
|
|
28
|
+
- Connection management
|
|
29
|
+
- Error handling
|
|
30
|
+
|
|
31
|
+
### 2. Create Core MCP Tool: task_get_status
|
|
32
|
+
|
|
33
|
+
Create `src/tools/task-get-status.ts`:
|
|
34
|
+
- Get current task status and progress
|
|
35
|
+
- Return milestone and task information
|
|
36
|
+
- Show overall progress percentage
|
|
37
|
+
|
|
38
|
+
### 3. Create Core MCP Tool: task_get_next_step
|
|
39
|
+
|
|
40
|
+
Create `src/tools/task-get-next-step.ts`:
|
|
41
|
+
- Find current task item from progress
|
|
42
|
+
- Return instructions for what to do next
|
|
43
|
+
- Include steps and verification criteria
|
|
44
|
+
|
|
45
|
+
### 4. Create Core MCP Tool: task_update_progress
|
|
46
|
+
|
|
47
|
+
Create `src/tools/task-update-progress.ts`:
|
|
48
|
+
- Update overall progress percentage
|
|
49
|
+
- Update milestone progress
|
|
50
|
+
- Recalculate completion metrics
|
|
51
|
+
|
|
52
|
+
### 5. Create Core MCP Tool: task_complete_task_item
|
|
53
|
+
|
|
54
|
+
Create `src/tools/task-complete-task-item.ts`:
|
|
55
|
+
- Mark a task item as complete
|
|
56
|
+
- Update milestone progress
|
|
57
|
+
- Move to next task if available
|
|
58
|
+
|
|
59
|
+
### 6. Create Core MCP Tool: task_create_milestone
|
|
60
|
+
|
|
61
|
+
Create `src/tools/task-create-milestone.ts`:
|
|
62
|
+
- Add a new milestone to task
|
|
63
|
+
- Initialize milestone with tasks
|
|
64
|
+
- Update progress tracking
|
|
65
|
+
|
|
66
|
+
### 7. Create Core MCP Tool: task_create_task_item
|
|
67
|
+
|
|
68
|
+
Create `src/tools/task-create-task-item.ts`:
|
|
69
|
+
- Add a task item to a milestone
|
|
70
|
+
- Update milestone task count
|
|
71
|
+
- Return confirmation
|
|
72
|
+
|
|
73
|
+
### 8. Create Core MCP Tool: task_report_completion
|
|
74
|
+
|
|
75
|
+
Create `src/tools/task-report-completion.ts`:
|
|
76
|
+
- Agent reports task item completion
|
|
77
|
+
- Update progress
|
|
78
|
+
- Get next instructions
|
|
79
|
+
|
|
80
|
+
### 9. Create Core MCP Tool: task_add_message
|
|
81
|
+
|
|
82
|
+
Create `src/tools/task-add-message.ts`:
|
|
83
|
+
- Add message to task thread
|
|
84
|
+
- Support user, assistant, system roles
|
|
85
|
+
- Return message ID
|
|
86
|
+
|
|
87
|
+
### 10. Create Tools Index
|
|
88
|
+
|
|
89
|
+
Create `src/tools/index.ts`:
|
|
90
|
+
- Export all tool definitions
|
|
91
|
+
- Export all tool handlers
|
|
92
|
+
- Create tool registry
|
|
93
|
+
|
|
94
|
+
### 11. Write Unit Tests
|
|
95
|
+
|
|
96
|
+
Create colocated test for each tool:
|
|
97
|
+
- Test tool definitions
|
|
98
|
+
- Test handlers with mocked client
|
|
99
|
+
- Test error handling
|
|
100
|
+
- Verify JSON responses
|
|
101
|
+
|
|
102
|
+
## Verification
|
|
103
|
+
|
|
104
|
+
- [ ] FirebaseClient wrapper created
|
|
105
|
+
- [ ] All 8 core tools implemented
|
|
106
|
+
- [ ] Each tool has definition and handler
|
|
107
|
+
- [ ] Tools return JSON strings
|
|
108
|
+
- [ ] Error handling works correctly
|
|
109
|
+
- [ ] Unit tests pass for all tools
|
|
110
|
+
- [ ] Tools follow MCP Bootstrap Pattern
|
|
111
|
+
- [ ] TypeScript compiles without errors
|
|
112
|
+
|
|
113
|
+
## Notes on Revision
|
|
114
|
+
|
|
115
|
+
**Why Revised**: Original task described TaskExecutor for agentbase.me with Bedrock integration. However, task-mcp is an MCP server that exposes tools, not an execution engine. The execution happens in the tenant platform (agentbase.me).
|
|
116
|
+
|
|
117
|
+
**Architecture Clarification**:
|
|
118
|
+
- task-mcp provides **instructions** via MCP tools
|
|
119
|
+
- Tenant platform's agent **executes** those instructions
|
|
120
|
+
- Agent reports back to task-mcp via tools
|
|
121
|
+
- task-mcp tracks progress in Firestore
|
|
122
|
+
|
|
123
|
+
## Files to Create
|
|
124
|
+
|
|
125
|
+
- `src/client.ts` + `.spec.ts`
|
|
126
|
+
- `src/tools/task-get-status.ts` + `.spec.ts`
|
|
127
|
+
- `src/tools/task-get-next-step.ts` + `.spec.ts`
|
|
128
|
+
- `src/tools/task-update-progress.ts` + `.spec.ts`
|
|
129
|
+
- `src/tools/task-complete-task-item.ts` + `.spec.ts`
|
|
130
|
+
- `src/tools/task-create-milestone.ts` + `.spec.ts`
|
|
131
|
+
- `src/tools/task-create-task-item.ts` + `.spec.ts`
|
|
132
|
+
- `src/tools/task-report-completion.ts` + `.spec.ts`
|
|
133
|
+
- `src/tools/task-add-message.ts` + `.spec.ts`
|
|
134
|
+
- `src/tools/index.ts`
|
|
135
|
+
- `.env.example`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
**Next Task**: [Task 89: MCP Server Implementation](task-89-mcp-server-implementation.md)
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Task 88: Task Execution Engine
|
|
2
|
+
|
|
3
|
+
**Milestone**: Milestone 1 - Task Infrastructure
|
|
4
|
+
**Estimated Time**: 16 hours
|
|
5
|
+
**Dependencies**: Task 87 (Task Database Service)
|
|
6
|
+
**Status**: Not Started
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Objective
|
|
11
|
+
|
|
12
|
+
Create a simplified task execution engine adapted from Roo Code's Task class. This engine manages task lifecycle (start, pause, resume, stop), streams API responses, coordinates tool execution, and persists state to Firestore.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
|
|
16
|
+
### 1. Create TaskExecutor Class
|
|
17
|
+
|
|
18
|
+
Create `src/lib/task-execution/TaskExecutor.ts`:
|
|
19
|
+
- Initialize with task ID and user ID
|
|
20
|
+
- Load task state from Firestore
|
|
21
|
+
- Manage execution lifecycle
|
|
22
|
+
- Stream API responses from Bedrock
|
|
23
|
+
- Coordinate tool execution
|
|
24
|
+
- Emit events for UI updates
|
|
25
|
+
|
|
26
|
+
### 2. Create TaskLifecycle Manager
|
|
27
|
+
|
|
28
|
+
Create `src/lib/task-execution/TaskLifecycle.ts`:
|
|
29
|
+
- Handle start/pause/resume/stop transitions
|
|
30
|
+
- Validate state transitions
|
|
31
|
+
- Update task status in Firestore
|
|
32
|
+
- Emit lifecycle events
|
|
33
|
+
|
|
34
|
+
### 3. Create TaskPersistence Layer
|
|
35
|
+
|
|
36
|
+
Create `src/lib/task-execution/TaskPersistence.ts`:
|
|
37
|
+
- Save API messages to Firestore
|
|
38
|
+
- Save task messages to Firestore
|
|
39
|
+
- Save tool results to Firestore
|
|
40
|
+
- Load execution state from Firestore
|
|
41
|
+
- Implement checkpoint/resume logic
|
|
42
|
+
|
|
43
|
+
### 4. Integrate with Bedrock Chat
|
|
44
|
+
|
|
45
|
+
Adapt existing Bedrock chat integration:
|
|
46
|
+
- Use `streamChatResponse` from `src/lib/chat/bedrock.ts`
|
|
47
|
+
- Pass task-specific tools
|
|
48
|
+
- Handle tool execution results
|
|
49
|
+
- Stream responses to task thread
|
|
50
|
+
|
|
51
|
+
### 5. Implement Event System
|
|
52
|
+
|
|
53
|
+
Create event emitter for:
|
|
54
|
+
- `task:started`
|
|
55
|
+
- `task:paused`
|
|
56
|
+
- `task:resumed`
|
|
57
|
+
- `task:stopped`
|
|
58
|
+
- `task:completed`
|
|
59
|
+
- `task:error`
|
|
60
|
+
- `task:progress_update`
|
|
61
|
+
- `task:message`
|
|
62
|
+
|
|
63
|
+
### 6. Write Tests
|
|
64
|
+
|
|
65
|
+
Create tests for:
|
|
66
|
+
- Task lifecycle transitions
|
|
67
|
+
- API streaming
|
|
68
|
+
- Tool execution
|
|
69
|
+
- State persistence
|
|
70
|
+
- Error handling
|
|
71
|
+
- Event emission
|
|
72
|
+
|
|
73
|
+
## Verification
|
|
74
|
+
|
|
75
|
+
- [ ] Can start task execution
|
|
76
|
+
- [ ] Can pause task execution
|
|
77
|
+
- [ ] Can resume task execution
|
|
78
|
+
- [ ] Can stop task execution
|
|
79
|
+
- [ ] API responses stream correctly
|
|
80
|
+
- [ ] Tools execute correctly
|
|
81
|
+
- [ ] State persists to Firestore
|
|
82
|
+
- [ ] Events emit correctly
|
|
83
|
+
- [ ] Errors handled gracefully
|
|
84
|
+
- [ ] Tests pass
|
|
85
|
+
|
|
86
|
+
## Example TaskExecutor Structure
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// src/lib/task-execution/TaskExecutor.ts
|
|
90
|
+
import { EventEmitter } from 'events'
|
|
91
|
+
import { TaskDatabaseService } from '@/services/task-database.service'
|
|
92
|
+
import { streamChatResponse } from '@/lib/chat/bedrock'
|
|
93
|
+
import { createBedrockClient } from '@/lib/chat/bedrock'
|
|
94
|
+
import type { Task } from '@/schemas/task'
|
|
95
|
+
|
|
96
|
+
export class TaskExecutor extends EventEmitter {
|
|
97
|
+
private taskId: string
|
|
98
|
+
private userId: string
|
|
99
|
+
private task: Task | null = null
|
|
100
|
+
private isRunning = false
|
|
101
|
+
private isPaused = false
|
|
102
|
+
private abortController: AbortController | null = null
|
|
103
|
+
|
|
104
|
+
constructor(taskId: string, userId: string) {
|
|
105
|
+
super()
|
|
106
|
+
this.taskId = taskId
|
|
107
|
+
this.userId = userId
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Start task execution
|
|
112
|
+
*/
|
|
113
|
+
async start(): Promise<void> {
|
|
114
|
+
// Load task from Firestore
|
|
115
|
+
this.task = await TaskDatabaseService.getTask(this.userId, this.taskId)
|
|
116
|
+
if (!this.task) {
|
|
117
|
+
throw new Error('Task not found')
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Update status
|
|
121
|
+
await TaskDatabaseService.updateTaskStatus(this.userId, this.taskId, 'in_progress')
|
|
122
|
+
this.task.status = 'in_progress'
|
|
123
|
+
|
|
124
|
+
// Emit event
|
|
125
|
+
this.emit('task:started', { taskId: this.taskId })
|
|
126
|
+
|
|
127
|
+
// Start execution loop
|
|
128
|
+
this.isRunning = true
|
|
129
|
+
await this.executionLoop()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Pause task execution
|
|
134
|
+
*/
|
|
135
|
+
async pause(): Promise<void> {
|
|
136
|
+
this.isPaused = true
|
|
137
|
+
this.abortController?.abort()
|
|
138
|
+
|
|
139
|
+
await TaskDatabaseService.updateTaskStatus(this.userId, this.taskId, 'paused')
|
|
140
|
+
this.emit('task:paused', { taskId: this.taskId })
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Resume task execution
|
|
145
|
+
*/
|
|
146
|
+
async resume(): Promise<void> {
|
|
147
|
+
this.isPaused = false
|
|
148
|
+
await TaskDatabaseService.updateTaskStatus(this.userId, this.taskId, 'in_progress')
|
|
149
|
+
this.emit('task:resumed', { taskId: this.taskId })
|
|
150
|
+
|
|
151
|
+
await this.executionLoop()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Stop task execution
|
|
156
|
+
*/
|
|
157
|
+
async stop(): Promise<void> {
|
|
158
|
+
this.isRunning = false
|
|
159
|
+
this.abortController?.abort()
|
|
160
|
+
|
|
161
|
+
await TaskDatabaseService.updateTaskStatus(this.userId, this.taskId, 'paused')
|
|
162
|
+
this.emit('task:stopped', { taskId: this.taskId })
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Main execution loop
|
|
167
|
+
*/
|
|
168
|
+
private async executionLoop(): Promise<void> {
|
|
169
|
+
while (this.isRunning && !this.isPaused) {
|
|
170
|
+
try {
|
|
171
|
+
// Get current milestone and task
|
|
172
|
+
const currentMilestone = this.getCurrentMilestone()
|
|
173
|
+
const currentTask = this.getCurrentTask()
|
|
174
|
+
|
|
175
|
+
if (!currentTask) {
|
|
176
|
+
// All tasks complete
|
|
177
|
+
await this.complete()
|
|
178
|
+
break
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Execute task
|
|
182
|
+
await this.executeTask(currentTask)
|
|
183
|
+
|
|
184
|
+
// Update progress
|
|
185
|
+
await this.updateProgress()
|
|
186
|
+
|
|
187
|
+
} catch (error) {
|
|
188
|
+
await this.handleError(error)
|
|
189
|
+
break
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Execute a single task
|
|
196
|
+
*/
|
|
197
|
+
private async executeTask(taskItem: any): Promise<void> {
|
|
198
|
+
// Create Bedrock client
|
|
199
|
+
const bedrock = createBedrockClient()
|
|
200
|
+
|
|
201
|
+
// Prepare messages
|
|
202
|
+
const messages = this.prepareMessages()
|
|
203
|
+
|
|
204
|
+
// Prepare tools
|
|
205
|
+
const tools = this.prepareTools()
|
|
206
|
+
|
|
207
|
+
// Stream response
|
|
208
|
+
this.abortController = new AbortController()
|
|
209
|
+
|
|
210
|
+
const result = await streamChatResponse(
|
|
211
|
+
bedrock,
|
|
212
|
+
messages,
|
|
213
|
+
tools,
|
|
214
|
+
{
|
|
215
|
+
maxTokens: 4096,
|
|
216
|
+
temperature: 0.7,
|
|
217
|
+
systemPrompt: this.task!.config.system_prompt
|
|
218
|
+
},
|
|
219
|
+
(chunk) => {
|
|
220
|
+
// Emit chunk event
|
|
221
|
+
this.emit('task:message', {
|
|
222
|
+
taskId: this.taskId,
|
|
223
|
+
role: 'assistant',
|
|
224
|
+
content: chunk,
|
|
225
|
+
streaming: true
|
|
226
|
+
})
|
|
227
|
+
},
|
|
228
|
+
(toolCall) => {
|
|
229
|
+
// Handle tool call
|
|
230
|
+
this.emit('task:tool_call', {
|
|
231
|
+
taskId: this.taskId,
|
|
232
|
+
toolCall
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
// Save result
|
|
238
|
+
await this.saveResult(result)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Complete task
|
|
243
|
+
*/
|
|
244
|
+
private async complete(): Promise<void> {
|
|
245
|
+
await TaskDatabaseService.updateTaskStatus(this.userId, this.taskId, 'completed')
|
|
246
|
+
this.isRunning = false
|
|
247
|
+
this.emit('task:completed', { taskId: this.taskId })
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Handle error
|
|
252
|
+
*/
|
|
253
|
+
private async handleError(error: any): Promise<void> {
|
|
254
|
+
await TaskDatabaseService.updateTaskStatus(this.userId, this.taskId, 'failed')
|
|
255
|
+
this.isRunning = false
|
|
256
|
+
this.emit('task:error', {
|
|
257
|
+
taskId: this.taskId,
|
|
258
|
+
error: error instanceof Error ? error.message : String(error)
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ... more methods
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Files to Create
|
|
267
|
+
|
|
268
|
+
- `src/lib/task-execution/TaskExecutor.ts`
|
|
269
|
+
- `src/lib/task-execution/TaskLifecycle.ts`
|
|
270
|
+
- `src/lib/task-execution/TaskPersistence.ts`
|
|
271
|
+
- `src/lib/task-execution/__tests__/TaskExecutor.spec.ts`
|
|
272
|
+
- `src/lib/task-execution/__tests__/TaskLifecycle.spec.ts`
|
|
273
|
+
- `src/lib/task-execution/__tests__/TaskPersistence.spec.ts`
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
**Next Task**: [Task 89: Task API Endpoints](task-89-task-api-endpoints.md)
|