fix(config): Improve config-manager.js for MCP server integration
- Fixed MCP server initialization warnings by refactoring config-manager.js to handle missing project roots silently during startup - Added project root tracking (loadedConfigRoot) to improve config caching and prevent unnecessary reloads - Modified _loadAndValidateConfig to return defaults without warnings when no explicitRoot provided - Improved getConfig to only update cache when loading config with a specific project root - Ensured warning messages still appear when explicitly specified roots have missing/invalid configs - Prevented console output during MCP startup that was causing JSON parsing errors - Verified parse_prd and other MCP tools still work correctly with the new config loading approach. - Replaces test perplexity api key in mcp.json and rolls it. It's invalid now.
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
"args": ["./mcp-server/server.js"],
|
"args": ["./mcp-server/server.js"],
|
||||||
"env": {
|
"env": {
|
||||||
"ANTHROPIC_API_KEY": "sk-ant-apikeyhere",
|
"ANTHROPIC_API_KEY": "sk-ant-apikeyhere",
|
||||||
"PERPLEXITY_API_KEY": "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",
|
"PERPLEXITY_API_KEY": "pplx-apikeyhere",
|
||||||
"OPENAI_API_KEY": "sk-proj-1234567890",
|
"OPENAI_API_KEY": "sk-proj-1234567890",
|
||||||
"GOOGLE_API_KEY": "AIzaSyB1234567890",
|
"GOOGLE_API_KEY": "AIzaSyB1234567890",
|
||||||
"GROK_API_KEY": "gsk_1234567890",
|
"GROK_API_KEY": "gsk_1234567890",
|
||||||
|
|||||||
@@ -12,41 +12,21 @@ import {
|
|||||||
enableSilentMode,
|
enableSilentMode,
|
||||||
disableSilentMode
|
disableSilentMode
|
||||||
} from '../../../../scripts/modules/utils.js';
|
} from '../../../../scripts/modules/utils.js';
|
||||||
import {
|
|
||||||
getAnthropicClientForMCP,
|
|
||||||
getModelConfig
|
|
||||||
} from '../utils/ai-client-utils.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Direct function wrapper for parsing PRD documents and generating tasks.
|
* Direct function wrapper for parsing PRD documents and generating tasks.
|
||||||
*
|
*
|
||||||
* @param {Object} args - Command arguments containing input, numTasks or tasks, and output options.
|
* @param {Object} args - Command arguments containing projectRoot, input, output, numTasks options.
|
||||||
* @param {Object} log - Logger object.
|
* @param {Object} log - Logger object.
|
||||||
* @param {Object} context - Context object containing session data.
|
* @param {Object} context - Context object containing session data.
|
||||||
* @returns {Promise<Object>} - Result object with success status and data/error information.
|
* @returns {Promise<Object>} - Result object with success status and data/error information.
|
||||||
*/
|
*/
|
||||||
export async function parsePRDDirect(args, log, context = {}) {
|
export async function parsePRDDirect(args, log, context = {}) {
|
||||||
const { session } = context; // Only extract session, not reportProgress
|
const { session } = context; // Only extract session
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log.info(`Parsing PRD document with args: ${JSON.stringify(args)}`);
|
log.info(`Parsing PRD document with args: ${JSON.stringify(args)}`);
|
||||||
|
|
||||||
// Initialize AI client for PRD parsing
|
|
||||||
let aiClient;
|
|
||||||
try {
|
|
||||||
aiClient = getAnthropicClientForMCP(session, log);
|
|
||||||
} catch (error) {
|
|
||||||
log.error(`Failed to initialize AI client: ${error.message}`);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: {
|
|
||||||
code: 'AI_CLIENT_ERROR',
|
|
||||||
message: `Cannot initialize AI client: ${error.message}`
|
|
||||||
},
|
|
||||||
fromCache: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate required parameters
|
// Validate required parameters
|
||||||
if (!args.projectRoot) {
|
if (!args.projectRoot) {
|
||||||
const errorMessage = 'Project root is required for parsePRDDirect';
|
const errorMessage = 'Project root is required for parsePRDDirect';
|
||||||
@@ -57,7 +37,6 @@ export async function parsePRDDirect(args, log, context = {}) {
|
|||||||
fromCache: false
|
fromCache: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.input) {
|
if (!args.input) {
|
||||||
const errorMessage = 'Input file path is required for parsePRDDirect';
|
const errorMessage = 'Input file path is required for parsePRDDirect';
|
||||||
log.error(errorMessage);
|
log.error(errorMessage);
|
||||||
@@ -67,7 +46,6 @@ export async function parsePRDDirect(args, log, context = {}) {
|
|||||||
fromCache: false
|
fromCache: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!args.output) {
|
if (!args.output) {
|
||||||
const errorMessage = 'Output file path is required for parsePRDDirect';
|
const errorMessage = 'Output file path is required for parsePRDDirect';
|
||||||
log.error(errorMessage);
|
log.error(errorMessage);
|
||||||
@@ -137,58 +115,35 @@ export async function parsePRDDirect(args, log, context = {}) {
|
|||||||
success: (message, ...args) => log.info(message, ...args) // Map success to info
|
success: (message, ...args) => log.info(message, ...args) // Map success to info
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get model config from session
|
|
||||||
const modelConfig = getModelConfig(session);
|
|
||||||
|
|
||||||
// Enable silent mode to prevent console logs from interfering with JSON response
|
// Enable silent mode to prevent console logs from interfering with JSON response
|
||||||
enableSilentMode();
|
enableSilentMode();
|
||||||
try {
|
try {
|
||||||
// Make sure the output directory exists
|
// Execute core parsePRD function - It now handles AI internally
|
||||||
const outputDir = path.dirname(outputPath);
|
const tasksDataResult = await parsePRD(inputPath, outputPath, numTasks, {
|
||||||
if (!fs.existsSync(outputDir)) {
|
mcpLog: logWrapper,
|
||||||
log.info(`Creating output directory: ${outputDir}`);
|
session
|
||||||
fs.mkdirSync(outputDir, { recursive: true });
|
});
|
||||||
|
|
||||||
|
// Check the result from the core function (assuming it might return data or null/undefined)
|
||||||
|
if (!tasksDataResult || !tasksDataResult.tasks) {
|
||||||
|
throw new Error(
|
||||||
|
'Core parsePRD function did not return valid task data.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute core parsePRD function with AI client
|
log.info(
|
||||||
await parsePRD(
|
`Successfully parsed PRD and generated ${tasksDataResult.tasks?.length || 0} tasks`
|
||||||
inputPath,
|
|
||||||
outputPath,
|
|
||||||
numTasks,
|
|
||||||
{
|
|
||||||
mcpLog: logWrapper,
|
|
||||||
session
|
|
||||||
},
|
|
||||||
aiClient,
|
|
||||||
modelConfig
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Since parsePRD doesn't return a value but writes to a file, we'll read the result
|
return {
|
||||||
// to return it to the caller
|
success: true,
|
||||||
if (fs.existsSync(outputPath)) {
|
data: {
|
||||||
const tasksData = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
message: `Successfully generated ${tasksDataResult.tasks?.length || 0} tasks from PRD`,
|
||||||
log.info(
|
taskCount: tasksDataResult.tasks?.length || 0,
|
||||||
`Successfully parsed PRD and generated ${tasksData.tasks?.length || 0} tasks`
|
outputPath
|
||||||
);
|
},
|
||||||
|
fromCache: false // This operation always modifies state
|
||||||
return {
|
};
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
message: `Successfully generated ${tasksData.tasks?.length || 0} tasks from PRD`,
|
|
||||||
taskCount: tasksData.tasks?.length || 0,
|
|
||||||
outputPath
|
|
||||||
},
|
|
||||||
fromCache: false // This operation always modifies state and should never be cached
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const errorMessage = `Tasks file was not created at ${outputPath}`;
|
|
||||||
log.error(errorMessage);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
error: { code: 'OUTPUT_FILE_NOT_CREATED', message: errorMessage },
|
|
||||||
fromCache: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
// Always restore normal logging
|
// Always restore normal logging
|
||||||
disableSilentMode();
|
disableSilentMode();
|
||||||
@@ -201,7 +156,7 @@ export async function parsePRDDirect(args, log, context = {}) {
|
|||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: {
|
error: {
|
||||||
code: 'PARSE_PRD_ERROR',
|
code: error.code || 'PARSE_PRD_ERROR', // Use error code if available
|
||||||
message: error.message || 'Unknown error parsing PRD'
|
message: error.message || 'Unknown error parsing PRD'
|
||||||
},
|
},
|
||||||
fromCache: false
|
fromCache: false
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ async function _unifiedServiceRunner(serviceType, params) {
|
|||||||
let providerName, modelId, apiKey, roleParams, providerFnSet, providerApiFn;
|
let providerName, modelId, apiKey, roleParams, providerFnSet, providerApiFn;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log('info', `Attempting service call with role: ${currentRole}`);
|
log('info', `New AI service call with role: ${currentRole}`);
|
||||||
|
|
||||||
// --- Corrected Config Fetching ---
|
// --- Corrected Config Fetching ---
|
||||||
// 1. Get Config: Provider, Model, Parameters for the current role
|
// 1. Get Config: Provider, Model, Parameters for the current role
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ const DEFAULTS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- Internal Config Loading ---
|
// --- Internal Config Loading ---
|
||||||
let loadedConfig = null; // Cache for loaded config
|
let loadedConfig = null;
|
||||||
|
let loadedConfigRoot = null; // Track which root loaded the config
|
||||||
|
|
||||||
// Custom Error for configuration issues
|
// Custom Error for configuration issues
|
||||||
class ConfigurationError extends Error {
|
class ConfigurationError extends Error {
|
||||||
@@ -84,25 +85,20 @@ class ConfigurationError extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _loadAndValidateConfig(explicitRoot = null) {
|
function _loadAndValidateConfig(explicitRoot = null) {
|
||||||
// Determine the root path to use
|
|
||||||
const rootToUse = explicitRoot || findProjectRoot();
|
|
||||||
const defaults = DEFAULTS; // Use the defined defaults
|
const defaults = DEFAULTS; // Use the defined defaults
|
||||||
|
|
||||||
|
// If no explicit root is provided (e.g., during initial server load),
|
||||||
|
// return defaults immediately and silently.
|
||||||
|
if (!explicitRoot) {
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Proceed with loading from the provided explicitRoot ---
|
||||||
|
const configPath = path.join(explicitRoot, CONFIG_FILE_NAME);
|
||||||
|
let config = { ...defaults }; // Start with a deep copy of defaults
|
||||||
let configExists = false;
|
let configExists = false;
|
||||||
|
|
||||||
if (!rootToUse) {
|
if (fs.existsSync(configPath)) {
|
||||||
console.warn(
|
|
||||||
chalk.yellow(
|
|
||||||
'Warning: Could not determine project root. Using default configuration.'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
// Allow proceeding with defaults if root finding fails, but validation later might trigger error
|
|
||||||
// Or perhaps throw here? Let's throw later based on file existence check.
|
|
||||||
}
|
|
||||||
const configPath = rootToUse ? path.join(rootToUse, CONFIG_FILE_NAME) : null;
|
|
||||||
|
|
||||||
let config = defaults; // Start with defaults
|
|
||||||
|
|
||||||
if (configPath && fs.existsSync(configPath)) {
|
|
||||||
configExists = true;
|
configExists = true;
|
||||||
try {
|
try {
|
||||||
const rawData = fs.readFileSync(configPath, 'utf-8');
|
const rawData = fs.readFileSync(configPath, 'utf-8');
|
||||||
@@ -125,59 +121,55 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
|||||||
global: { ...defaults.global, ...parsedConfig?.global }
|
global: { ...defaults.global, ...parsedConfig?.global }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Validation (Only warn if file exists but content is invalid) ---
|
// --- Validation (Warn if file content is invalid) ---
|
||||||
// Validate main provider/model
|
// Only use console.warn here, as this part runs only when an explicitRoot *is* provided
|
||||||
if (!validateProvider(config.models.main.provider)) {
|
if (!validateProvider(config.models.main.provider)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`Warning: Invalid main provider "${config.models.main.provider}" in ${CONFIG_FILE_NAME}. Falling back to default.`
|
`Warning: Invalid main provider "${config.models.main.provider}" in ${configPath}. Falling back to default.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
config.models.main = { ...defaults.models.main };
|
config.models.main = { ...defaults.models.main };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate research provider/model
|
|
||||||
if (!validateProvider(config.models.research.provider)) {
|
if (!validateProvider(config.models.research.provider)) {
|
||||||
console.warn(
|
console.warn(
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`Warning: Invalid research provider "${config.models.research.provider}" in ${CONFIG_FILE_NAME}. Falling back to default.`
|
`Warning: Invalid research provider "${config.models.research.provider}" in ${configPath}. Falling back to default.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
config.models.research = { ...defaults.models.research };
|
config.models.research = { ...defaults.models.research };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate fallback provider if it exists
|
|
||||||
if (
|
if (
|
||||||
config.models.fallback?.provider &&
|
config.models.fallback?.provider &&
|
||||||
!validateProvider(config.models.fallback.provider)
|
!validateProvider(config.models.fallback.provider)
|
||||||
) {
|
) {
|
||||||
console.warn(
|
console.warn(
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`Warning: Invalid fallback provider "${config.models.fallback.provider}" in ${CONFIG_FILE_NAME}. Fallback model configuration will be ignored.`
|
`Warning: Invalid fallback provider "${config.models.fallback.provider}" in ${configPath}. Fallback model configuration will be ignored.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
config.models.fallback.provider = undefined;
|
config.models.fallback.provider = undefined;
|
||||||
config.models.fallback.modelId = undefined;
|
config.models.fallback.modelId = undefined;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Use console.error for actual errors during parsing
|
||||||
console.error(
|
console.error(
|
||||||
chalk.red(
|
chalk.red(
|
||||||
`Error reading or parsing ${configPath}: ${error.message}. Using default configuration.`
|
`Error reading or parsing ${configPath}: ${error.message}. Using default configuration.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
config = defaults; // Reset to defaults on parse error
|
config = { ...defaults }; // Reset to defaults on parse error
|
||||||
// Do not throw ConfigurationError here, allow fallback to defaults if file is corrupt
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Config file doesn't exist
|
// Config file doesn't exist at the provided explicitRoot.
|
||||||
// **Changed: Log warning instead of throwing error**
|
// Use console.warn because an explicit root *was* given.
|
||||||
console.warn(
|
console.warn(
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`Warning: ${CONFIG_FILE_NAME} not found at project root (${rootToUse || 'unknown'}). Using default configuration. Run 'task-master models --setup' to configure.`
|
`Warning: ${CONFIG_FILE_NAME} not found at provided project root (${explicitRoot}). Using default configuration. Run 'task-master models --setup' to configure.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
// Return defaults instead of throwing error
|
// Keep config as defaults
|
||||||
return defaults;
|
config = { ...defaults };
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@@ -185,18 +177,32 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current configuration, loading it if necessary.
|
* Gets the current configuration, loading it if necessary.
|
||||||
|
* Handles MCP initialization context gracefully.
|
||||||
* @param {string|null} explicitRoot - Optional explicit path to the project root.
|
* @param {string|null} explicitRoot - Optional explicit path to the project root.
|
||||||
* @param {boolean} forceReload - Force reloading the config file.
|
* @param {boolean} forceReload - Force reloading the config file.
|
||||||
* @returns {object} The loaded configuration object.
|
* @returns {object} The loaded configuration object.
|
||||||
*/
|
*/
|
||||||
function getConfig(explicitRoot = null, forceReload = false) {
|
function getConfig(explicitRoot = null, forceReload = false) {
|
||||||
if (!loadedConfig || forceReload) {
|
// Determine if a reload is necessary
|
||||||
loadedConfig = _loadAndValidateConfig(explicitRoot);
|
const needsLoad =
|
||||||
}
|
!loadedConfig ||
|
||||||
// If an explicitRoot was provided for a one-off check, don't cache it permanently
|
forceReload ||
|
||||||
if (explicitRoot && !forceReload) {
|
(explicitRoot && explicitRoot !== loadedConfigRoot);
|
||||||
return _loadAndValidateConfig(explicitRoot);
|
|
||||||
|
if (needsLoad) {
|
||||||
|
const newConfig = _loadAndValidateConfig(explicitRoot); // _load handles null explicitRoot
|
||||||
|
|
||||||
|
// Only update the global cache if loading was forced or if an explicit root
|
||||||
|
// was provided (meaning we attempted to load a specific project's config).
|
||||||
|
// We avoid caching the initial default load triggered without an explicitRoot.
|
||||||
|
if (forceReload || explicitRoot) {
|
||||||
|
loadedConfig = newConfig;
|
||||||
|
loadedConfigRoot = explicitRoot; // Store the root used for this loaded config
|
||||||
|
}
|
||||||
|
return newConfig; // Return the newly loaded/default config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no load was needed, return the cached config
|
||||||
return loadedConfig;
|
return loadedConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,14 +79,14 @@ async function getModelConfiguration(options = {}) {
|
|||||||
|
|
||||||
// Check API keys
|
// Check API keys
|
||||||
const mainCliKeyOk = isApiKeySet(mainProvider);
|
const mainCliKeyOk = isApiKeySet(mainProvider);
|
||||||
const mainMcpKeyOk = getMcpApiKeyStatus(mainProvider);
|
const mainMcpKeyOk = getMcpApiKeyStatus(mainProvider, projectRoot);
|
||||||
const researchCliKeyOk = isApiKeySet(researchProvider);
|
const researchCliKeyOk = isApiKeySet(researchProvider);
|
||||||
const researchMcpKeyOk = getMcpApiKeyStatus(researchProvider);
|
const researchMcpKeyOk = getMcpApiKeyStatus(researchProvider, projectRoot);
|
||||||
const fallbackCliKeyOk = fallbackProvider
|
const fallbackCliKeyOk = fallbackProvider
|
||||||
? isApiKeySet(fallbackProvider)
|
? isApiKeySet(fallbackProvider)
|
||||||
: true;
|
: true;
|
||||||
const fallbackMcpKeyOk = fallbackProvider
|
const fallbackMcpKeyOk = fallbackProvider
|
||||||
? getMcpApiKeyStatus(fallbackProvider)
|
? getMcpApiKeyStatus(fallbackProvider, projectRoot)
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
// Get available models to find detailed info
|
// Get available models to find detailed info
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ describe('Unified AI Services', () => {
|
|||||||
expect(mockLog).toHaveBeenNthCalledWith(
|
expect(mockLog).toHaveBeenNthCalledWith(
|
||||||
2,
|
2,
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: main'
|
'New AI service call with role: main'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenNthCalledWith(
|
expect(mockLog).toHaveBeenNthCalledWith(
|
||||||
3,
|
3,
|
||||||
@@ -229,7 +229,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: main'
|
'New AI service call with role: main'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith('info', 'Retrieved AI client', {
|
expect(mockLog).toHaveBeenCalledWith('info', 'Retrieved AI client', {
|
||||||
provider: mockClient.provider,
|
provider: mockClient.provider,
|
||||||
@@ -277,7 +277,7 @@ describe('Unified AI Services', () => {
|
|||||||
// Check subsequent fallback attempts (which also fail)
|
// Check subsequent fallback attempts (which also fail)
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: fallback'
|
'New AI service call with role: fallback'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'error',
|
'error',
|
||||||
@@ -285,7 +285,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: research'
|
'New AI service call with role: research'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'error',
|
'error',
|
||||||
@@ -349,7 +349,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: fallback'
|
'New AI service call with role: fallback'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
@@ -431,7 +431,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: research'
|
'New AI service call with role: research'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
@@ -509,7 +509,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: research'
|
'New AI service call with role: research'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
@@ -554,7 +554,7 @@ describe('Unified AI Services', () => {
|
|||||||
// Check logs for sequence
|
// Check logs for sequence
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: fallback'
|
'New AI service call with role: fallback'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'error',
|
'error',
|
||||||
@@ -568,7 +568,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: research'
|
'New AI service call with role: research'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
@@ -613,7 +613,7 @@ describe('Unified AI Services', () => {
|
|||||||
// Check logs for sequence
|
// Check logs for sequence
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: research'
|
'New AI service call with role: research'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'error',
|
'error',
|
||||||
@@ -627,7 +627,7 @@ describe('Unified AI Services', () => {
|
|||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
'Attempting service call with role: fallback'
|
'New AI service call with role: fallback'
|
||||||
);
|
);
|
||||||
expect(mockLog).toHaveBeenCalledWith(
|
expect(mockLog).toHaveBeenCalledWith(
|
||||||
'info',
|
'info',
|
||||||
|
|||||||
Reference in New Issue
Block a user