feat: make more compatible with "o" family models

This commit is contained in:
Ralph Khreish
2025-06-21 22:16:51 +03:00
parent 122a0465d8
commit 54f50a4dc8
9 changed files with 36 additions and 23 deletions

View File

@@ -0,0 +1,10 @@
---
"task-master-ai": minor
---
Make task-master more compatible with the "o" family models of OpenAI
Now works well with:
- o3
- o3-mini
- etc.

View File

@@ -6,7 +6,8 @@
".changeset", ".changeset",
"tasks", "tasks",
"package-lock.json", "package-lock.json",
"tests/fixture/*.json" "tests/fixture/*.json",
"dist"
] ]
}, },
"formatter": { "formatter": {

View File

@@ -54,7 +54,7 @@ const DEFAULTS = {
// No default fallback provider/model initially // No default fallback provider/model initially
provider: 'anthropic', provider: 'anthropic',
modelId: 'claude-3-5-sonnet', modelId: 'claude-3-5-sonnet',
maxTokens: 64000, // Default parameters if fallback IS configured maxTokens: 8192, // Default parameters if fallback IS configured
temperature: 0.2 temperature: 0.2
} }
}, },

View File

@@ -54,7 +54,7 @@
"output": 15.0 "output": 15.0
}, },
"allowed_roles": ["main", "fallback"], "allowed_roles": ["main", "fallback"],
"max_tokens": 64000 "max_tokens": 8192
} }
], ],
"openai": [ "openai": [
@@ -84,7 +84,8 @@
"input": 2.0, "input": 2.0,
"output": 8.0 "output": 8.0
}, },
"allowed_roles": ["main", "fallback"] "allowed_roles": ["main", "fallback"],
"max_tokens": 100000
}, },
{ {
"id": "o3-mini", "id": "o3-mini",

View File

@@ -27,7 +27,6 @@ import {
} from '../utils.js'; } from '../utils.js';
import { generateObjectService } from '../ai-services-unified.js'; import { generateObjectService } from '../ai-services-unified.js';
import { getDefaultPriority } from '../config-manager.js'; import { getDefaultPriority } from '../config-manager.js';
import generateTaskFiles from './generate-task-files.js';
import ContextGatherer from '../utils/contextGatherer.js'; import ContextGatherer from '../utils/contextGatherer.js';
// Define Zod schema for the expected AI output object // Define Zod schema for the expected AI output object
@@ -44,7 +43,7 @@ const AiTaskDataSchema = z.object({
.describe('Detailed approach for verifying task completion'), .describe('Detailed approach for verifying task completion'),
dependencies: z dependencies: z
.array(z.number()) .array(z.number())
.optional() .nullable()
.describe( .describe(
'Array of task IDs that this task depends on (must be completed before this task can start)' 'Array of task IDs that this task depends on (must be completed before this task can start)'
) )

View File

@@ -43,8 +43,9 @@ const subtaskSchema = z
), ),
testStrategy: z testStrategy: z
.string() .string()
.optional() .nullable()
.describe('Approach for testing this subtask') .describe('Approach for testing this subtask')
.default('')
}) })
.strict(); .strict();
const subtaskArraySchema = z.array(subtaskSchema); const subtaskArraySchema = z.array(subtaskSchema);

View File

@@ -26,11 +26,11 @@ const prdSingleTaskSchema = z.object({
id: z.number().int().positive(), id: z.number().int().positive(),
title: z.string().min(1), title: z.string().min(1),
description: z.string().min(1), description: z.string().min(1),
details: z.string().optional().default(''), details: z.string().nullable(),
testStrategy: z.string().optional().default(''), testStrategy: z.string().nullable(),
priority: z.enum(['high', 'medium', 'low']).default('medium'), priority: z.enum(['high', 'medium', 'low']).nullable(),
dependencies: z.array(z.number().int().positive()).optional().default([]), dependencies: z.array(z.number().int().positive()).nullable(),
status: z.string().optional().default('pending') status: z.string().nullable()
}); });
// Define the Zod schema for the ENTIRE expected AI response object // Define the Zod schema for the ENTIRE expected AI response object

View File

@@ -36,9 +36,9 @@ const updatedTaskSchema = z
description: z.string(), description: z.string(),
status: z.string(), status: z.string(),
dependencies: z.array(z.union([z.number().int(), z.string()])), dependencies: z.array(z.union([z.number().int(), z.string()])),
priority: z.string().optional(), priority: z.string().nullable().default('medium'),
details: z.string().optional(), details: z.string().nullable().default(''),
testStrategy: z.string().optional(), testStrategy: z.string().nullable().default(''),
subtasks: z subtasks: z
.array( .array(
z.object({ z.object({
@@ -50,12 +50,13 @@ const updatedTaskSchema = z
title: z.string(), title: z.string(),
description: z.string(), description: z.string(),
status: z.string(), status: z.string(),
dependencies: z.array(z.number().int()).optional(), dependencies: z.array(z.number().int()).nullable().default([]),
details: z.string().optional(), details: z.string().nullable().default(''),
testStrategy: z.string().optional() testStrategy: z.string().nullable().default('')
}) })
) )
.optional() .nullable()
.default([])
}) })
.strip(); // Allows parsing even if AI adds extra fields, but validation focuses on schema .strip(); // Allows parsing even if AI adds extra fields, but validation focuses on schema

View File

@@ -35,10 +35,10 @@ const updatedTaskSchema = z
description: z.string(), description: z.string(),
status: z.string(), status: z.string(),
dependencies: z.array(z.union([z.number().int(), z.string()])), dependencies: z.array(z.union([z.number().int(), z.string()])),
priority: z.string().optional(), priority: z.string().nullable(),
details: z.string().optional(), details: z.string().nullable(),
testStrategy: z.string().optional(), testStrategy: z.string().nullable(),
subtasks: z.array(z.any()).optional() // Keep subtasks flexible for now subtasks: z.array(z.any()).nullable() // Keep subtasks flexible for now
}) })
.strip(); // Allow potential extra fields during parsing if needed, then validate structure .strip(); // Allow potential extra fields during parsing if needed, then validate structure
const updatedTaskArraySchema = z.array(updatedTaskSchema); const updatedTaskArraySchema = z.array(updatedTaskSchema);