Skip to content

Commit 8f452a1

Browse files
Passing live API tests
1 parent 23377e1 commit 8f452a1

13 files changed

+1204
-795
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ This will show the available commands and options.
4040
The task manager supports multiple LLM providers for generating project plans. You can configure one or more of the following environment variables depending on which providers you want to use:
4141

4242
- `OPENAI_API_KEY`: Required for using OpenAI models (e.g., GPT-4)
43-
- `GEMINI_API_KEY`: Required for using Google's Gemini models
43+
- `GOOGLE_GENERATIVE_AI_API_KEY`: Required for using Google's Gemini models
4444
- `DEEPSEEK_API_KEY`: Required for using Deepseek models
4545

4646
To generate project plans using the CLI, set these environment variables in your shell:
4747

4848
```bash
4949
export OPENAI_API_KEY="your-api-key"
50-
export GEMINI_API_KEY="your-api-key"
50+
export GOOGLE_GENERATIVE_AI_API_KEY="your-api-key"
5151
export DEEPSEEK_API_KEY="your-api-key"
5252
```
5353

@@ -61,7 +61,7 @@ Or you can include them in your MCP client configuration to generate project pla
6161
"args": ["-y", "taskqueue-mcp"],
6262
"env": {
6363
"OPENAI_API_KEY": "your-api-key",
64-
"GEMINI_API_KEY": "your-api-key",
64+
"GOOGLE_GENERATIVE_AI_API_KEY": "your-api-key",
6565
"DEEPSEEK_API_KEY": "your-api-key"
6666
}
6767
}

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"@types/jest": "^29.5.12",
5656
"@types/json-schema": "^7.0.15",
5757
"@types/node": "^20.11.0",
58+
"dotenv": "^16.4.7",
5859
"jest": "^29.7.0",
5960
"shx": "^0.3.4",
6061
"ts-jest": "^29.1.2",

src/client/cli.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ program
344344

345345
// Fetch tasks for this project, applying state filter
346346
const tasksResponse = await taskManager.listTasks(projectId, filterState);
347-
const tasks = tasksResponse.data?.tasks || [];
347+
// Check for success before accessing data
348+
const tasks = tasksResponse.status === 'success' ? tasksResponse.data.tasks : [];
348349

349350
console.log(chalk.cyan(`\n📋 Project ${chalk.bold(projectId)} details:`));
350351
console.log(` - ${chalk.bold('Initial Prompt:')} ${project.initialPrompt}`);
@@ -428,7 +429,8 @@ program
428429
} else {
429430
// List all projects, applying state filter
430431
const projectsResponse = await taskManager.listProjects(filterState);
431-
const projectsToList = projectsResponse.data?.projects || [];
432+
// Check for success before accessing data
433+
const projectsToList = projectsResponse.status === 'success' ? projectsResponse.data.projects : [];
432434

433435
if (projectsToList.length === 0) {
434436
console.log(chalk.yellow(`No projects found${filterState ? ` matching state '${filterState}'` : ''}.`));

src/server/TaskManager.ts

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
import * as path from "node:path";
2-
import { Task, TaskManagerFile, TaskState, StandardResponse, ErrorCode, Project } from "../types/index.js";
2+
import {
3+
Task,
4+
TaskManagerFile,
5+
TaskState,
6+
StandardResponse,
7+
ErrorCode,
8+
Project,
9+
ProjectCreationSuccessData,
10+
ApproveTaskSuccessData,
11+
ApproveProjectSuccessData,
12+
OpenTaskSuccessData,
13+
ListProjectsSuccessData,
14+
ListTasksSuccessData,
15+
AddTasksSuccessData,
16+
DeleteTaskSuccessData,
17+
ReadProjectSuccessData
18+
} from "../types/index.js";
319
import { createError, createSuccessResponse } from "../utils/errors.js";
420
import { generateObject, jsonSchema } from "ai";
521
import { formatTaskProgressTable, formatProjectsList } from "./taskFormattingUtils.js";
@@ -54,7 +70,7 @@ export class TaskManager {
5470
tasks: { title: string; description: string; toolRecommendations?: string; ruleRecommendations?: string }[],
5571
projectPlan?: string,
5672
autoApprove?: boolean
57-
) {
73+
): Promise<StandardResponse<ProjectCreationSuccessData>> {
5874
await this.ensureInitialized();
5975
// Reload before creating to ensure counters are up-to-date
6076
await this.reloadFromDisk();
@@ -113,7 +129,7 @@ export class TaskManager {
113129
provider: string;
114130
model: string;
115131
attachments: string[];
116-
}): Promise<StandardResponse> {
132+
}): Promise<StandardResponse<ProjectCreationSuccessData>> {
117133
await this.ensureInitialized();
118134

119135
// Wrap prompt and attachments in XML tags
@@ -283,7 +299,7 @@ export class TaskManager {
283299
};
284300
}
285301

286-
public async approveTaskCompletion(projectId: string, taskId: string) {
302+
public async approveTaskCompletion(projectId: string, taskId: string): Promise<StandardResponse<ApproveTaskSuccessData>> {
287303
await this.ensureInitialized();
288304
// Reload before modifying
289305
await this.reloadFromDisk();
@@ -308,7 +324,18 @@ export class TaskManager {
308324
);
309325
}
310326
if (task.approved) {
311-
return createSuccessResponse({ message: "Task already approved." });
327+
// Return the full expected data structure even if already approved
328+
return createSuccessResponse({
329+
message: "Task already approved.",
330+
projectId: proj.projectId,
331+
task: {
332+
id: task.id,
333+
title: task.title,
334+
description: task.description,
335+
completedDetails: task.completedDetails,
336+
approved: task.approved,
337+
},
338+
});
312339
}
313340

314341
task.approved = true;
@@ -325,7 +352,7 @@ export class TaskManager {
325352
});
326353
}
327354

328-
public async approveProjectCompletion(projectId: string) {
355+
public async approveProjectCompletion(projectId: string): Promise<StandardResponse<ApproveProjectSuccessData>> {
329356
await this.ensureInitialized();
330357
// Reload before modifying
331358
await this.reloadFromDisk();
@@ -369,7 +396,7 @@ export class TaskManager {
369396
});
370397
}
371398

372-
public async openTaskDetails(taskId: string) {
399+
public async openTaskDetails(taskId: string): Promise<StandardResponse<OpenTaskSuccessData>> {
373400
await this.ensureInitialized();
374401
// Reload from disk to ensure we have the latest data
375402
await this.reloadFromDisk();
@@ -399,7 +426,7 @@ export class TaskManager {
399426
);
400427
}
401428

402-
public async listProjects(state?: TaskState) {
429+
public async listProjects(state?: TaskState): Promise<StandardResponse<ListProjectsSuccessData>> {
403430
await this.ensureInitialized();
404431
// Reload from disk to ensure we have the latest data
405432
await this.reloadFromDisk();
@@ -434,7 +461,7 @@ export class TaskManager {
434461
});
435462
}
436463

437-
public async listTasks(projectId?: string, state?: TaskState) {
464+
public async listTasks(projectId?: string, state?: TaskState): Promise<StandardResponse<ListTasksSuccessData>> {
438465
await this.ensureInitialized();
439466
// Reload from disk to ensure we have the latest data
440467
await this.reloadFromDisk();
@@ -489,7 +516,7 @@ export class TaskManager {
489516
public async addTasksToProject(
490517
projectId: string,
491518
tasks: { title: string; description: string; toolRecommendations?: string; ruleRecommendations?: string }[]
492-
) {
519+
): Promise<StandardResponse<AddTasksSuccessData>> {
493520
await this.ensureInitialized();
494521
// Reload before modifying
495522
await this.reloadFromDisk();
@@ -541,7 +568,7 @@ export class TaskManager {
541568
status?: "not started" | "in progress" | "done";
542569
completedDetails?: string;
543570
}
544-
) {
571+
): Promise<StandardResponse<Task>> {
545572
await this.ensureInitialized();
546573
// Reload before modifying
547574
await this.reloadFromDisk();
@@ -573,7 +600,7 @@ export class TaskManager {
573600
return createSuccessResponse(project.tasks[taskIndex]);
574601
}
575602

576-
public async deleteTask(projectId: string, taskId: string) {
603+
public async deleteTask(projectId: string, taskId: string): Promise<StandardResponse<DeleteTaskSuccessData>> {
577604
await this.ensureInitialized();
578605
// Reload before modifying
579606
await this.reloadFromDisk();
@@ -608,13 +635,7 @@ export class TaskManager {
608635
});
609636
}
610637

611-
public async readProject(projectId: string): Promise<StandardResponse<{
612-
projectId: string;
613-
initialPrompt: string;
614-
projectPlan: string;
615-
completed: boolean;
616-
tasks: Task[];
617-
}>> {
638+
public async readProject(projectId: string): Promise<StandardResponse<ReadProjectSuccessData>> {
618639
await this.ensureInitialized();
619640
// Reload from disk to ensure we have the latest data
620641
await this.reloadFromDisk();

src/types/index.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,75 @@ export interface StandardError {
8383
details?: unknown;
8484
}
8585

86+
// Define the structure for createProject success data
87+
export interface ProjectCreationSuccessData {
88+
projectId: string;
89+
totalTasks: number;
90+
tasks: Array<{ id: string; title: string; description: string }>;
91+
message: string;
92+
}
93+
94+
// --- NEW Success Data Interfaces ---
95+
96+
export interface ApproveTaskSuccessData {
97+
projectId: string;
98+
task: {
99+
id: string;
100+
title: string;
101+
description: string;
102+
completedDetails: string;
103+
approved: boolean;
104+
};
105+
}
106+
107+
export interface ApproveProjectSuccessData {
108+
projectId: string;
109+
message: string;
110+
}
111+
112+
export interface OpenTaskSuccessData {
113+
projectId: string;
114+
initialPrompt: string;
115+
projectPlan: string;
116+
completed: boolean;
117+
task: Task; // Use the full Task type
118+
}
119+
120+
export interface ListProjectsSuccessData {
121+
message: string;
122+
projects: Array<{
123+
projectId: string;
124+
initialPrompt: string;
125+
totalTasks: number;
126+
completedTasks: number;
127+
approvedTasks: number;
128+
}>;
129+
}
130+
131+
export interface ListTasksSuccessData {
132+
message: string;
133+
tasks: Task[]; // Use the full Task type
134+
}
135+
136+
export interface AddTasksSuccessData {
137+
message: string;
138+
newTasks: Array<{ id: string; title: string; description: string }>;
139+
}
140+
141+
export interface DeleteTaskSuccessData {
142+
message: string;
143+
}
144+
145+
export interface ReadProjectSuccessData {
146+
projectId: string;
147+
initialPrompt: string;
148+
projectPlan: string;
149+
completed: boolean;
150+
tasks: Task[]; // Use the full Task type
151+
}
152+
153+
// --- End NEW Success Data Interfaces ---
154+
86155
// Generic success response
87156
export interface SuccessResponse<T = unknown> {
88157
status: "success";

0 commit comments

Comments
 (0)