Compare commits
2 Commits
task-maste
...
feat/impro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4107f83324 | ||
|
|
184bb5e68e |
8
.changeset/fuzzy-words-count.md
Normal file
8
.changeset/fuzzy-words-count.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix scope-up/down prompts to include all required fields for better AI model compatibility
|
||||||
|
|
||||||
|
- Added missing `priority` field to scope adjustment prompts to prevent validation errors with Claude-code and other models
|
||||||
|
- Ensures generated JSON includes all fields required by the schema
|
||||||
8
.changeset/tender-trams-refuse.md
Normal file
8
.changeset/tender-trams-refuse.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix MCP scope-up/down tools not finding tasks
|
||||||
|
|
||||||
|
- Fixed task ID parsing in MCP layer - now correctly converts string IDs to numbers
|
||||||
|
- scope_up_task and scope_down_task MCP tools now work properly
|
||||||
11
.changeset/vast-sites-leave.md
Normal file
11
.changeset/vast-sites-leave.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve AI provider compatibility for JSON generation
|
||||||
|
|
||||||
|
- Fixed schema compatibility issues between Perplexity and OpenAI o3 models
|
||||||
|
- Removed nullable/default modifiers from Zod schemas for broader compatibility
|
||||||
|
- Added automatic JSON repair for malformed AI responses (handles cases like missing array values)
|
||||||
|
- Perplexity now uses JSON mode for more reliable structured output
|
||||||
|
- Post-processing handles default values separately from schema validation
|
||||||
12
.github/scripts/tag-extension.mjs
vendored
12
.github/scripts/tag-extension.mjs
vendored
@@ -86,19 +86,23 @@ if (gitResult.status !== 0) {
|
|||||||
console.error('Error:', gitResult.error);
|
console.error('Error:', gitResult.error);
|
||||||
console.error('Stderr:', gitResult.stderr);
|
console.error('Stderr:', gitResult.stderr);
|
||||||
console.error('Command:', `git ls-remote ${repoUrl} ${tag}`);
|
console.error('Command:', `git ls-remote ${repoUrl} ${tag}`);
|
||||||
|
|
||||||
// For CI environments, try using origin instead of the full URL
|
// For CI environments, try using origin instead of the full URL
|
||||||
if (process.env.CI) {
|
if (process.env.CI) {
|
||||||
console.log('Retrying with origin remote...');
|
console.log('Retrying with origin remote...');
|
||||||
gitResult = spawnSync('git', ['ls-remote', 'origin', tag], {
|
gitResult = spawnSync('git', ['ls-remote', 'origin', tag], {
|
||||||
encoding: 'utf8'
|
encoding: 'utf8'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (gitResult.status !== 0) {
|
if (gitResult.status !== 0) {
|
||||||
throw new Error(`Failed to check remote for tag ${tag}. Exit code: ${gitResult.status}`);
|
throw new Error(
|
||||||
|
`Failed to check remote for tag ${tag}. Exit code: ${gitResult.status}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Failed to check remote for tag ${tag}. Exit code: ${gitResult.status}`);
|
throw new Error(
|
||||||
|
`Failed to check remote for tag ${tag}. Exit code: ${gitResult.status}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ export async function scopeDownDirect(args, log, context = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse task IDs
|
// Parse task IDs - convert to numbers as expected by scopeDownTask
|
||||||
const taskIds = id.split(',').map((taskId) => taskId.trim());
|
const taskIds = id.split(',').map((taskId) => parseInt(taskId.trim(), 10));
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
`Scoping down tasks: ${taskIds.join(', ')}, strength: ${strength}, research: ${research}`
|
`Scoping down tasks: ${taskIds.join(', ')}, strength: ${strength}, research: ${research}`
|
||||||
@@ -90,10 +90,10 @@ export async function scopeDownDirect(args, log, context = {}) {
|
|||||||
projectRoot,
|
projectRoot,
|
||||||
commandName: 'scope-down',
|
commandName: 'scope-down',
|
||||||
outputType: 'mcp',
|
outputType: 'mcp',
|
||||||
tag
|
tag,
|
||||||
|
research
|
||||||
},
|
},
|
||||||
'json', // outputFormat
|
'json' // outputFormat
|
||||||
research
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore normal logging
|
// Restore normal logging
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ export async function scopeUpDirect(args, log, context = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse task IDs
|
// Parse task IDs - convert to numbers as expected by scopeUpTask
|
||||||
const taskIds = id.split(',').map((taskId) => taskId.trim());
|
const taskIds = id.split(',').map((taskId) => parseInt(taskId.trim(), 10));
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
`Scoping up tasks: ${taskIds.join(', ')}, strength: ${strength}, research: ${research}`
|
`Scoping up tasks: ${taskIds.join(', ')}, strength: ${strength}, research: ${research}`
|
||||||
@@ -90,10 +90,10 @@ export async function scopeUpDirect(args, log, context = {}) {
|
|||||||
projectRoot,
|
projectRoot,
|
||||||
commandName: 'scope-up',
|
commandName: 'scope-up',
|
||||||
outputType: 'mcp',
|
outputType: 'mcp',
|
||||||
tag
|
tag,
|
||||||
|
research
|
||||||
},
|
},
|
||||||
'json', // outputFormat
|
'json' // outputFormat
|
||||||
research
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore normal logging
|
// Restore normal logging
|
||||||
|
|||||||
16
package-lock.json
generated
16
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "task-master-ai",
|
"name": "task-master-ai",
|
||||||
"version": "0.22.1-rc.0",
|
"version": "0.23.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "task-master-ai",
|
"name": "task-master-ai",
|
||||||
"version": "0.22.1-rc.0",
|
"version": "0.23.0",
|
||||||
"license": "MIT WITH Commons-Clause",
|
"license": "MIT WITH Commons-Clause",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
"helmet": "^8.1.0",
|
"helmet": "^8.1.0",
|
||||||
"inquirer": "^12.5.0",
|
"inquirer": "^12.5.0",
|
||||||
"jsonc-parser": "^3.3.1",
|
"jsonc-parser": "^3.3.1",
|
||||||
|
"jsonrepair": "^3.13.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lru-cache": "^10.2.0",
|
"lru-cache": "^10.2.0",
|
||||||
"ollama-ai-provider": "^1.2.0",
|
"ollama-ai-provider": "^1.2.0",
|
||||||
@@ -84,7 +85,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"apps/extension": {
|
"apps/extension": {
|
||||||
"version": "0.22.3",
|
"version": "0.23.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/modifiers": "^9.0.0",
|
"@dnd-kit/modifiers": "^9.0.0",
|
||||||
@@ -14942,6 +14943,15 @@
|
|||||||
"graceful-fs": "^4.1.6"
|
"graceful-fs": "^4.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsonrepair": {
|
||||||
|
"version": "3.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.13.0.tgz",
|
||||||
|
"integrity": "sha512-5YRzlAQ7tuzV1nAJu3LvDlrKtBFIALHN2+a+I1MGJCt3ldRDBF/bZuvIPzae8Epot6KBXd0awRZZcuoeAsZ/mw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"jsonrepair": "bin/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsonwebtoken": {
|
"node_modules/jsonwebtoken": {
|
||||||
"version": "9.0.2",
|
"version": "9.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
"helmet": "^8.1.0",
|
"helmet": "^8.1.0",
|
||||||
"inquirer": "^12.5.0",
|
"inquirer": "^12.5.0",
|
||||||
"jsonc-parser": "^3.3.1",
|
"jsonc-parser": "^3.3.1",
|
||||||
|
"jsonrepair": "^3.13.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lru-cache": "^10.2.0",
|
"lru-cache": "^10.2.0",
|
||||||
"ollama-ai-provider": "^1.2.0",
|
"ollama-ai-provider": "^1.2.0",
|
||||||
|
|||||||
@@ -1479,7 +1479,8 @@ function registerCommands(programInstance) {
|
|||||||
projectRoot: taskMaster.getProjectRoot(),
|
projectRoot: taskMaster.getProjectRoot(),
|
||||||
tag,
|
tag,
|
||||||
commandName: 'scope-up',
|
commandName: 'scope-up',
|
||||||
outputType: 'cli'
|
outputType: 'cli',
|
||||||
|
research: options.research || false
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await scopeUpTask(
|
const result = await scopeUpTask(
|
||||||
@@ -1605,7 +1606,8 @@ function registerCommands(programInstance) {
|
|||||||
projectRoot: taskMaster.getProjectRoot(),
|
projectRoot: taskMaster.getProjectRoot(),
|
||||||
tag,
|
tag,
|
||||||
commandName: 'scope-down',
|
commandName: 'scope-down',
|
||||||
outputType: 'cli'
|
outputType: 'cli',
|
||||||
|
research: options.research || false
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await scopeDownTask(
|
const result = await scopeDownTask(
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ import { displayAiUsageSummary } from '../ui.js';
|
|||||||
|
|
||||||
// Define the Zod schema for a SINGLE task object
|
// Define the Zod schema for a SINGLE task object
|
||||||
const prdSingleTaskSchema = z.object({
|
const prdSingleTaskSchema = z.object({
|
||||||
id: z.number().int().positive(),
|
id: z.number(),
|
||||||
title: z.string().min(1),
|
title: z.string().min(1),
|
||||||
description: z.string().min(1),
|
description: z.string().min(1),
|
||||||
details: z.string().nullable(),
|
details: z.string(),
|
||||||
testStrategy: z.string().nullable(),
|
testStrategy: z.string(),
|
||||||
priority: z.enum(['high', 'medium', 'low']).nullable(),
|
priority: z.enum(['high', 'medium', 'low']),
|
||||||
dependencies: z.array(z.number().int().positive()).nullable(),
|
dependencies: z.array(z.number()),
|
||||||
status: z.string().nullable()
|
status: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Define the Zod schema for the ENTIRE expected AI response object
|
// Define the Zod schema for the ENTIRE expected AI response object
|
||||||
@@ -257,10 +257,15 @@ async function parsePRD(prdPath, tasksPath, numTasks, options = {}) {
|
|||||||
return {
|
return {
|
||||||
...task,
|
...task,
|
||||||
id: newId,
|
id: newId,
|
||||||
status: 'pending',
|
status: task.status || 'pending',
|
||||||
priority: task.priority || 'medium',
|
priority: task.priority || 'medium',
|
||||||
dependencies: Array.isArray(task.dependencies) ? task.dependencies : [],
|
dependencies: Array.isArray(task.dependencies) ? task.dependencies : [],
|
||||||
subtasks: []
|
subtasks: [],
|
||||||
|
// Ensure all required fields have values (even if empty strings)
|
||||||
|
title: task.title || '',
|
||||||
|
description: task.description || '',
|
||||||
|
details: task.details || '',
|
||||||
|
testStrategy: task.testStrategy || ''
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ ${
|
|||||||
}
|
}
|
||||||
|
|
||||||
Return a JSON object with a "subtasks" array. Each subtask should have:
|
Return a JSON object with a "subtasks" array. Each subtask should have:
|
||||||
- id: Sequential number starting from 1
|
- id: Sequential NUMBER starting from 1 (e.g., 1, 2, 3 - NOT "1", "2", "3")
|
||||||
- title: Clear, specific title
|
- title: Clear, specific title
|
||||||
- description: Detailed description
|
- description: Detailed description
|
||||||
- dependencies: Array of dependency IDs as STRINGS (use format ["${task.id}.1", "${task.id}.2"] for siblings, or empty array [] for no dependencies)
|
- dependencies: Array of dependency IDs as STRINGS (use format ["${task.id}.1", "${task.id}.2"] for siblings, or empty array [] for no dependencies)
|
||||||
@@ -345,7 +345,9 @@ Return a JSON object with a "subtasks" array. Each subtask should have:
|
|||||||
- status: "pending"
|
- status: "pending"
|
||||||
- testStrategy: Testing approach
|
- testStrategy: Testing approach
|
||||||
|
|
||||||
IMPORTANT: Dependencies must be strings, not numbers!
|
IMPORTANT:
|
||||||
|
- The 'id' field must be a NUMBER, not a string!
|
||||||
|
- Dependencies must be strings, not numbers!
|
||||||
|
|
||||||
Ensure the JSON is valid and properly formatted.`;
|
Ensure the JSON is valid and properly formatted.`;
|
||||||
|
|
||||||
@@ -358,14 +360,14 @@ Ensure the JSON is valid and properly formatted.`;
|
|||||||
description: z.string().min(10),
|
description: z.string().min(10),
|
||||||
dependencies: z.array(z.string()),
|
dependencies: z.array(z.string()),
|
||||||
details: z.string().min(20),
|
details: z.string().min(20),
|
||||||
status: z.string().default('pending'),
|
status: z.string(),
|
||||||
testStrategy: z.string().nullable().default('')
|
testStrategy: z.string()
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
const aiResult = await generateObjectService({
|
const aiResult = await generateObjectService({
|
||||||
role: 'main',
|
role: context.research ? 'research' : 'main',
|
||||||
session: context.session,
|
session: context.session,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
prompt,
|
prompt,
|
||||||
@@ -377,14 +379,21 @@ Ensure the JSON is valid and properly formatted.`;
|
|||||||
|
|
||||||
const generatedSubtasks = aiResult.mainResult.subtasks || [];
|
const generatedSubtasks = aiResult.mainResult.subtasks || [];
|
||||||
|
|
||||||
|
// Post-process generated subtasks to ensure defaults
|
||||||
|
const processedGeneratedSubtasks = generatedSubtasks.map((subtask) => ({
|
||||||
|
...subtask,
|
||||||
|
status: subtask.status || 'pending',
|
||||||
|
testStrategy: subtask.testStrategy || ''
|
||||||
|
}));
|
||||||
|
|
||||||
// Update task with preserved subtasks + newly generated ones
|
// Update task with preserved subtasks + newly generated ones
|
||||||
task.subtasks = [...preservedSubtasks, ...generatedSubtasks];
|
task.subtasks = [...preservedSubtasks, ...processedGeneratedSubtasks];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
updatedTask: task,
|
updatedTask: task,
|
||||||
regenerated: true,
|
regenerated: true,
|
||||||
preserved: preservedSubtasks.length,
|
preserved: preservedSubtasks.length,
|
||||||
generated: generatedSubtasks.length
|
generated: processedGeneratedSubtasks.length
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log(
|
log(
|
||||||
@@ -457,6 +466,7 @@ ADJUSTMENT REQUIREMENTS:
|
|||||||
- description: Updated task description
|
- description: Updated task description
|
||||||
- details: Updated implementation details
|
- details: Updated implementation details
|
||||||
- testStrategy: Updated test strategy
|
- testStrategy: Updated test strategy
|
||||||
|
- priority: Task priority ('low', 'medium', or 'high')
|
||||||
|
|
||||||
Ensure the JSON is valid and properly formatted.`;
|
Ensure the JSON is valid and properly formatted.`;
|
||||||
|
|
||||||
@@ -501,14 +511,11 @@ async function adjustTaskComplexity(
|
|||||||
.string()
|
.string()
|
||||||
.min(1)
|
.min(1)
|
||||||
.describe('Updated testing approach for the adjusted scope'),
|
.describe('Updated testing approach for the adjusted scope'),
|
||||||
priority: z
|
priority: z.enum(['low', 'medium', 'high']).describe('Task priority level')
|
||||||
.enum(['low', 'medium', 'high'])
|
|
||||||
.optional()
|
|
||||||
.describe('Task priority level')
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const aiResult = await generateObjectService({
|
const aiResult = await generateObjectService({
|
||||||
role: 'main',
|
role: context.research ? 'research' : 'main',
|
||||||
session: context.session,
|
session: context.session,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
prompt,
|
prompt,
|
||||||
@@ -520,10 +527,16 @@ async function adjustTaskComplexity(
|
|||||||
|
|
||||||
const updatedTaskData = aiResult.mainResult;
|
const updatedTaskData = aiResult.mainResult;
|
||||||
|
|
||||||
|
// Ensure priority has a value (in case AI didn't provide one)
|
||||||
|
const processedTaskData = {
|
||||||
|
...updatedTaskData,
|
||||||
|
priority: updatedTaskData.priority || task.priority || 'medium'
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
updatedTask: {
|
updatedTask: {
|
||||||
...task,
|
...task,
|
||||||
...updatedTaskData
|
...processedTaskData
|
||||||
},
|
},
|
||||||
telemetryData: aiResult.telemetryData
|
telemetryData: aiResult.telemetryData
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
import { generateObject, generateText, streamText } from 'ai';
|
import {
|
||||||
|
generateObject,
|
||||||
|
generateText,
|
||||||
|
streamText,
|
||||||
|
zodSchema,
|
||||||
|
JSONParseError,
|
||||||
|
NoObjectGeneratedError
|
||||||
|
} from 'ai';
|
||||||
|
import { jsonrepair } from 'jsonrepair';
|
||||||
import { log } from '../../scripts/modules/utils.js';
|
import { log } from '../../scripts/modules/utils.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,8 +214,8 @@ export class BaseAIProvider {
|
|||||||
const result = await generateObject({
|
const result = await generateObject({
|
||||||
model: client(params.modelId),
|
model: client(params.modelId),
|
||||||
messages: params.messages,
|
messages: params.messages,
|
||||||
schema: params.schema,
|
schema: zodSchema(params.schema),
|
||||||
mode: 'auto',
|
mode: params.mode || 'auto',
|
||||||
maxTokens: params.maxTokens,
|
maxTokens: params.maxTokens,
|
||||||
temperature: params.temperature
|
temperature: params.temperature
|
||||||
});
|
});
|
||||||
@@ -226,6 +234,43 @@ export class BaseAIProvider {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Check if this is a JSON parsing error that we can potentially fix
|
||||||
|
if (
|
||||||
|
NoObjectGeneratedError.isInstance(error) &&
|
||||||
|
JSONParseError.isInstance(error.cause) &&
|
||||||
|
error.cause.text
|
||||||
|
) {
|
||||||
|
log(
|
||||||
|
'warn',
|
||||||
|
`${this.name} generated malformed JSON, attempting to repair...`
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use jsonrepair to fix the malformed JSON
|
||||||
|
const repairedJson = jsonrepair(error.cause.text);
|
||||||
|
const parsed = JSON.parse(repairedJson);
|
||||||
|
|
||||||
|
log('info', `Successfully repaired ${this.name} JSON output`);
|
||||||
|
|
||||||
|
// Return in the expected format
|
||||||
|
return {
|
||||||
|
object: parsed,
|
||||||
|
usage: {
|
||||||
|
// Extract usage information from the error if available
|
||||||
|
inputTokens: error.usage?.promptTokens || 0,
|
||||||
|
outputTokens: error.usage?.completionTokens || 0,
|
||||||
|
totalTokens: error.usage?.totalTokens || 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (repairError) {
|
||||||
|
log(
|
||||||
|
'error',
|
||||||
|
`Failed to repair ${this.name} JSON: ${repairError.message}`
|
||||||
|
);
|
||||||
|
// Fall through to handleError with original error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.handleError('object generation', error);
|
this.handleError('object generation', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,21 @@ export class PerplexityAIProvider extends BaseAIProvider {
|
|||||||
this.handleError('client initialization', error);
|
this.handleError('client initialization', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override generateObject to use JSON mode for Perplexity
|
||||||
|
*
|
||||||
|
* NOTE: Perplexity models (especially sonar models) have known issues
|
||||||
|
* generating valid JSON, particularly with array fields. They often
|
||||||
|
* generate malformed JSON like "dependencies": , instead of "dependencies": []
|
||||||
|
*
|
||||||
|
* The base provider now handles JSON repair automatically for all providers.
|
||||||
|
*/
|
||||||
|
async generateObject(params) {
|
||||||
|
// Force JSON mode for Perplexity as it may help with reliability
|
||||||
|
return super.generateObject({
|
||||||
|
...params,
|
||||||
|
mode: 'json'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user