mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
Enhance skill generator documentation and templates
- Updated Phase 1 and Phase 2 documentation to include next phase links and data flow details. - Expanded Phase 5 documentation to include comprehensive validation and README generation steps, along with validation report structure. - Added purpose and usage context sections to various action and script templates (e.g., autonomous-action, llm-action, script-bash). - Improved commands management by simplifying the command scanning logic and enabling/disabling commands through renaming files. - Enhanced dashboard command manager to format group names and display nested groups with appropriate icons and colors. - Updated LiteLLM executor to allow model overrides during execution. - Added action reference guide and template reference sections to the skill-tuning SKILL.md for better navigation and understanding.
This commit is contained in:
@@ -281,7 +281,8 @@ export function addEndpoint(
|
||||
addClaudeApiEndpoint(homedir(), {
|
||||
id: endpoint.id,
|
||||
name: endpoint.id, // Use endpoint ID as tool name for CLI access
|
||||
enabled: endpoint.enabled !== false
|
||||
enabled: endpoint.enabled !== false,
|
||||
model: endpoint.model // Sync model as primaryModel/secondaryModel
|
||||
});
|
||||
console.log(`[LiteLLM Config] Synced endpoint ${endpoint.id} to cli-tools.json (api-endpoint)`);
|
||||
} catch (syncError) {
|
||||
@@ -320,13 +321,14 @@ export function updateEndpoint(
|
||||
|
||||
saveConfig(baseDir, config);
|
||||
|
||||
// Sync enabled status to cli-tools.json
|
||||
// Sync enabled status and model to cli-tools.json
|
||||
const updatedEndpoint = config.endpoints[endpointIndex];
|
||||
try {
|
||||
addClaudeApiEndpoint(homedir(), {
|
||||
id: updatedEndpoint.id,
|
||||
name: updatedEndpoint.id,
|
||||
enabled: updatedEndpoint.enabled !== false
|
||||
enabled: updatedEndpoint.enabled !== false,
|
||||
model: updatedEndpoint.model // Sync model as primaryModel/secondaryModel
|
||||
});
|
||||
console.log(`[LiteLLM Config] Synced endpoint ${updatedEndpoint.id} update to cli-tools.json`);
|
||||
} catch (syncError) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* - POST /api/commands/:name/toggle - Enable/disable single command
|
||||
* - POST /api/commands/group/:groupName/toggle - Batch toggle commands by group
|
||||
*/
|
||||
import { existsSync, readdirSync, readFileSync, mkdirSync, cpSync, rmSync, renameSync, statSync } from 'fs';
|
||||
import { existsSync, readdirSync, readFileSync, mkdirSync, renameSync } from 'fs';
|
||||
import { join, relative, dirname, basename } from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { validatePath as validateAllowedPath } from '../../utils/path-validator.js';
|
||||
@@ -78,15 +78,6 @@ function getCommandsDir(location: CommandLocation, projectPath: string): string
|
||||
return join(homedir(), '.claude', 'commands');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disabled commands directory path
|
||||
*/
|
||||
function getDisabledCommandsDir(location: CommandLocation, projectPath: string): string {
|
||||
if (location === 'project') {
|
||||
return join(projectPath, '.claude', 'commands', '_disabled');
|
||||
}
|
||||
return join(homedir(), '.claude', 'commands', '_disabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse YAML frontmatter from command file
|
||||
@@ -221,7 +212,6 @@ function scanCommandsRecursive(
|
||||
baseDir: string,
|
||||
currentDir: string,
|
||||
location: CommandLocation,
|
||||
enabled: boolean,
|
||||
projectPath: string
|
||||
): CommandInfo[] {
|
||||
const results: CommandInfo[] = [];
|
||||
@@ -235,37 +225,46 @@ function scanCommandsRecursive(
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = join(currentDir, entry.name);
|
||||
const relativePath = relative(baseDir, fullPath);
|
||||
let relativePath = relative(baseDir, fullPath);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// Skip _disabled directory when scanning enabled commands
|
||||
if (entry.name === '_disabled') continue;
|
||||
|
||||
// Recursively scan subdirectories
|
||||
results.push(...scanCommandsRecursive(baseDir, fullPath, location, enabled, projectPath));
|
||||
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
||||
try {
|
||||
const content = readFileSync(fullPath, 'utf8');
|
||||
const metadata = parseCommandFrontmatter(content);
|
||||
const commandName = metadata.name || basename(entry.name, '.md');
|
||||
results.push(...scanCommandsRecursive(baseDir, fullPath, location, projectPath));
|
||||
} else if (entry.isFile()) {
|
||||
// Check for .md or .md.disabled files
|
||||
const isEnabled = entry.name.endsWith('.md') && !entry.name.endsWith('.md.disabled');
|
||||
const isDisabled = entry.name.endsWith('.md.disabled');
|
||||
|
||||
// Get group from external config (not from frontmatter)
|
||||
const group = getCommandGroup(commandName, relativePath, location, projectPath);
|
||||
if (isEnabled || isDisabled) {
|
||||
try {
|
||||
const content = readFileSync(fullPath, 'utf8');
|
||||
const metadata = parseCommandFrontmatter(content);
|
||||
|
||||
results.push({
|
||||
name: commandName,
|
||||
description: metadata.description,
|
||||
group,
|
||||
enabled,
|
||||
location,
|
||||
path: fullPath,
|
||||
relativePath,
|
||||
argumentHint: metadata.argumentHint,
|
||||
allowedTools: metadata.allowedTools
|
||||
});
|
||||
} catch (err) {
|
||||
// Skip files that fail to read
|
||||
console.error(`[Commands] Failed to read ${fullPath}:`, err);
|
||||
// For disabled files, remove .disabled from relativePath for consistency
|
||||
if (isDisabled) {
|
||||
relativePath = relativePath.replace(/\.disabled$/, '');
|
||||
}
|
||||
|
||||
const commandName = metadata.name || basename(relativePath, '.md');
|
||||
|
||||
// Get group from external config (not from frontmatter)
|
||||
const group = getCommandGroup(commandName, relativePath, location, projectPath);
|
||||
|
||||
results.push({
|
||||
name: commandName,
|
||||
description: metadata.description,
|
||||
group,
|
||||
enabled: isEnabled,
|
||||
location,
|
||||
path: fullPath,
|
||||
relativePath,
|
||||
argumentHint: metadata.argumentHint,
|
||||
allowedTools: metadata.allowedTools
|
||||
});
|
||||
} catch (err) {
|
||||
// Skip files that fail to read
|
||||
console.error(`[Commands] Failed to read ${fullPath}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,33 +288,13 @@ function getCommandsConfig(projectPath: string): CommandsConfig {
|
||||
const groupSet = new Set<string>();
|
||||
|
||||
try {
|
||||
// Scan project commands
|
||||
// Scan project commands (includes both .md and .md.disabled)
|
||||
const projectDir = getCommandsDir('project', projectPath);
|
||||
const projectDisabledDir = getDisabledCommandsDir('project', projectPath);
|
||||
result.projectCommands = scanCommandsRecursive(projectDir, projectDir, 'project', projectPath);
|
||||
|
||||
// Enabled project commands
|
||||
const enabledProject = scanCommandsRecursive(projectDir, projectDir, 'project', true, projectPath);
|
||||
result.projectCommands.push(...enabledProject);
|
||||
|
||||
// Disabled project commands
|
||||
if (existsSync(projectDisabledDir)) {
|
||||
const disabledProject = scanCommandsRecursive(projectDisabledDir, projectDisabledDir, 'project', false, projectPath);
|
||||
result.projectCommands.push(...disabledProject);
|
||||
}
|
||||
|
||||
// Scan user commands
|
||||
// Scan user commands (includes both .md and .md.disabled)
|
||||
const userDir = getCommandsDir('user', projectPath);
|
||||
const userDisabledDir = getDisabledCommandsDir('user', projectPath);
|
||||
|
||||
// Enabled user commands
|
||||
const enabledUser = scanCommandsRecursive(userDir, userDir, 'user', true, projectPath);
|
||||
result.userCommands.push(...enabledUser);
|
||||
|
||||
// Disabled user commands
|
||||
if (existsSync(userDisabledDir)) {
|
||||
const disabledUser = scanCommandsRecursive(userDisabledDir, userDisabledDir, 'user', false, projectPath);
|
||||
result.userCommands.push(...disabledUser);
|
||||
}
|
||||
result.userCommands = scanCommandsRecursive(userDir, userDir, 'user', projectPath);
|
||||
|
||||
// Collect all groups
|
||||
for (const cmd of [...result.projectCommands, ...result.userCommands]) {
|
||||
@@ -330,40 +309,6 @@ function getCommandsConfig(projectPath: string): CommandsConfig {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move directory with fallback to copy-delete and rollback on failure
|
||||
*/
|
||||
function moveDirectory(source: string, target: string): void {
|
||||
try {
|
||||
// Ensure target parent directory exists
|
||||
const targetParent = dirname(target);
|
||||
if (!existsSync(targetParent)) {
|
||||
mkdirSync(targetParent, { recursive: true });
|
||||
}
|
||||
|
||||
// Try atomic rename first
|
||||
renameSync(source, target);
|
||||
} catch (error: unknown) {
|
||||
const err = error as NodeJS.ErrnoException;
|
||||
// If rename fails (cross-filesystem, permission issues), fallback to copy-delete
|
||||
if (err.code === 'EXDEV' || err.code === 'EPERM' || err.code === 'EBUSY') {
|
||||
cpSync(source, target, { recursive: true, force: true });
|
||||
try {
|
||||
rmSync(source, { recursive: true, force: true });
|
||||
} catch (rmError) {
|
||||
// Rollback: remove the copied target to avoid duplicates
|
||||
try {
|
||||
rmSync(target, { recursive: true, force: true });
|
||||
} catch {
|
||||
// Ignore rollback errors
|
||||
}
|
||||
throw new Error(`Failed to remove source after copy: ${(rmError as Error).message}`);
|
||||
}
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find command by name in commands list
|
||||
@@ -416,47 +361,48 @@ async function toggleCommand(
|
||||
}
|
||||
|
||||
const commandsDir = getCommandsDir(location, projectPath);
|
||||
const disabledDir = getDisabledCommandsDir(location, projectPath);
|
||||
// relativePath already includes .md extension (e.g., 'workflow/plan.md')
|
||||
const commandPath = join(commandsDir, command.relativePath);
|
||||
const disabledPath = commandPath + '.disabled';
|
||||
|
||||
if (command.enabled) {
|
||||
// Disable: move from commands to _disabled
|
||||
const targetPath = join(disabledDir, command.relativePath);
|
||||
|
||||
// Check if target already exists
|
||||
if (existsSync(targetPath)) {
|
||||
return { success: false, message: 'Command already exists in disabled directory', status: 409 };
|
||||
// Disable: rename .md to .md.disabled
|
||||
if (!existsSync(commandPath)) {
|
||||
return { success: false, message: 'Command file not found', status: 404 };
|
||||
}
|
||||
if (existsSync(disabledPath)) {
|
||||
return { success: false, message: 'Command already disabled', status: 409 };
|
||||
}
|
||||
|
||||
moveDirectory(command.path, targetPath);
|
||||
return {
|
||||
success: true,
|
||||
message: 'Command disabled',
|
||||
commandName: command.name,
|
||||
location
|
||||
renameSync(commandPath, disabledPath);
|
||||
return {
|
||||
success: true,
|
||||
message: 'Command disabled',
|
||||
commandName: command.name,
|
||||
location
|
||||
};
|
||||
} else {
|
||||
// Enable: move from _disabled back to commands
|
||||
// Calculate target path in enabled directory
|
||||
const targetPath = join(commandsDir, command.relativePath);
|
||||
|
||||
// Check if target already exists
|
||||
if (existsSync(targetPath)) {
|
||||
return { success: false, message: 'Command already exists in commands directory', status: 409 };
|
||||
// Enable: rename .md.disabled back to .md
|
||||
if (!existsSync(disabledPath)) {
|
||||
return { success: false, message: 'Disabled command not found', status: 404 };
|
||||
}
|
||||
if (existsSync(commandPath)) {
|
||||
return { success: false, message: 'Command already enabled', status: 409 };
|
||||
}
|
||||
|
||||
moveDirectory(command.path, targetPath);
|
||||
return {
|
||||
success: true,
|
||||
message: 'Command enabled',
|
||||
commandName: command.name,
|
||||
location
|
||||
renameSync(disabledPath, commandPath);
|
||||
return {
|
||||
success: true,
|
||||
message: 'Command enabled',
|
||||
commandName: command.name,
|
||||
location
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message,
|
||||
status: 500
|
||||
return {
|
||||
success: false,
|
||||
message: (error as Error).message,
|
||||
status: 500
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1631,6 +1631,12 @@ const i18n = {
|
||||
'commands.group.task': 'Task',
|
||||
'commands.group.issue': 'Issue',
|
||||
'commands.group.other': 'Other',
|
||||
'commands.group.review': 'Review',
|
||||
'commands.group.execute': 'Execute',
|
||||
'commands.group.plan': 'Plan',
|
||||
'commands.group.test': 'Test',
|
||||
'commands.group.debug': 'Debug',
|
||||
'commands.group.tools': 'Tools',
|
||||
'commands.enableAll': 'Enable All',
|
||||
'commands.disableAll': 'Disable All',
|
||||
'commands.enableGroupConfirm': 'Enable all commands in "{group}" group?',
|
||||
@@ -4307,6 +4313,12 @@ const i18n = {
|
||||
'commands.group.task': '任务',
|
||||
'commands.group.issue': '问题',
|
||||
'commands.group.other': '其他',
|
||||
'commands.group.review': '审查',
|
||||
'commands.group.execute': '执行',
|
||||
'commands.group.plan': '规划',
|
||||
'commands.group.test': '测试',
|
||||
'commands.group.debug': '调试',
|
||||
'commands.group.tools': '工具',
|
||||
'commands.enableAll': '全部启用',
|
||||
'commands.disableAll': '全部禁用',
|
||||
'commands.enableGroupConfirm': '启用 "{group}" 分组中的所有命令?',
|
||||
|
||||
@@ -205,6 +205,50 @@ function renderCommandsView() {
|
||||
if (typeof lucide !== 'undefined') lucide.createIcons();
|
||||
}
|
||||
|
||||
// Format group name for display (e.g., 'workflow/review' -> 'Workflow > Review')
|
||||
function formatGroupName(groupName) {
|
||||
if (!groupName.includes('/')) {
|
||||
return t('commands.group.' + groupName) || groupName;
|
||||
}
|
||||
|
||||
// Split path and translate each part
|
||||
const parts = groupName.split('/');
|
||||
const translatedParts = parts.map(part => t('commands.group.' + part) || part);
|
||||
return translatedParts.join(' › ');
|
||||
}
|
||||
|
||||
// Get icon for a group (use top-level parent's icon for nested groups)
|
||||
function getGroupIcon(groupName) {
|
||||
const groupIcons = {
|
||||
cli: 'terminal',
|
||||
workflow: 'git-branch',
|
||||
memory: 'brain',
|
||||
task: 'clipboard-list',
|
||||
issue: 'alert-circle',
|
||||
other: 'folder'
|
||||
};
|
||||
|
||||
// For nested groups, use the top-level parent's icon
|
||||
const topLevel = groupName.split('/')[0];
|
||||
return groupIcons[topLevel] || 'folder';
|
||||
}
|
||||
|
||||
// Get color for a group (use top-level parent's color for nested groups)
|
||||
function getGroupColor(groupName) {
|
||||
const groupColors = {
|
||||
cli: 'text-primary bg-primary/10',
|
||||
workflow: 'text-success bg-success/10',
|
||||
memory: 'text-indigo bg-indigo/10',
|
||||
task: 'text-warning bg-warning/10',
|
||||
issue: 'text-destructive bg-destructive/10',
|
||||
other: 'text-muted-foreground bg-muted'
|
||||
};
|
||||
|
||||
// For nested groups, use the top-level parent's color
|
||||
const topLevel = groupName.split('/')[0];
|
||||
return groupColors[topLevel] || 'text-muted-foreground bg-muted';
|
||||
}
|
||||
|
||||
function renderAccordionGroup(groupName, commands) {
|
||||
// Default to expanded for new/custom groups
|
||||
if (expandedGroups[groupName] === undefined) expandedGroups[groupName] = true;
|
||||
@@ -217,31 +261,14 @@ function renderAccordionGroup(groupName, commands) {
|
||||
? commands
|
||||
: enabledCommands;
|
||||
|
||||
// Group icons
|
||||
const groupIcons = {
|
||||
cli: 'terminal',
|
||||
workflow: 'workflow',
|
||||
memory: 'brain',
|
||||
task: 'clipboard-list',
|
||||
issue: 'alert-circle',
|
||||
other: 'folder'
|
||||
};
|
||||
|
||||
// Group colors
|
||||
const groupColors = {
|
||||
cli: 'text-primary bg-primary/10',
|
||||
workflow: 'text-success bg-success/10',
|
||||
memory: 'text-indigo bg-indigo/10',
|
||||
task: 'text-warning bg-warning/10',
|
||||
issue: 'text-destructive bg-destructive/10',
|
||||
other: 'text-muted-foreground bg-muted'
|
||||
};
|
||||
|
||||
const icon = groupIcons[groupName] || 'folder';
|
||||
const colorClass = groupColors[groupName] || 'text-muted-foreground bg-muted';
|
||||
const icon = getGroupIcon(groupName);
|
||||
const colorClass = getGroupColor(groupName);
|
||||
const displayName = formatGroupName(groupName);
|
||||
const indentLevel = (groupName.match(/\//g) || []).length;
|
||||
const indentStyle = indentLevel > 0 ? `style="margin-left: ${indentLevel * 20}px;"` : '';
|
||||
|
||||
return `
|
||||
<div class="accordion-group mb-4">
|
||||
<div class="accordion-group mb-4" ${indentStyle}>
|
||||
<!-- Group Header -->
|
||||
<div class="accordion-header flex items-center justify-between px-4 py-3 bg-card border border-border rounded-lg hover:bg-hover transition-colors">
|
||||
<div class="flex items-center gap-3 flex-1 cursor-pointer" onclick="toggleAccordionGroup('${groupName}')">
|
||||
@@ -250,7 +277,7 @@ function renderAccordionGroup(groupName, commands) {
|
||||
<i data-lucide="${icon}" class="w-4 h-4"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-base font-semibold text-foreground capitalize">${t('commands.group.' + groupName) || groupName}</h3>
|
||||
<h3 class="text-base font-semibold text-foreground">${displayName}</h3>
|
||||
<p class="text-xs text-muted-foreground">${enabledCommands.length}/${commands.length} ${t('commands.enabled') || 'enabled'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -802,13 +802,15 @@ export function getNativeResume(projectDir: string): boolean {
|
||||
*/
|
||||
export function addClaudeApiEndpoint(
|
||||
projectDir: string,
|
||||
endpoint: { id: string; name: string; enabled: boolean }
|
||||
endpoint: { id: string; name: string; enabled: boolean; model?: string }
|
||||
): ClaudeCliToolsConfig {
|
||||
const config = loadClaudeCliTools(projectDir);
|
||||
|
||||
// Add as a tool with type: 'api-endpoint'
|
||||
config.tools[endpoint.name] = {
|
||||
enabled: endpoint.enabled,
|
||||
primaryModel: endpoint.model, // Use endpoint.model as primaryModel (can be overridden via --model)
|
||||
secondaryModel: endpoint.model, // Same as primary for fallback
|
||||
tags: [],
|
||||
type: 'api-endpoint',
|
||||
id: endpoint.id // Store endpoint ID for settings lookup
|
||||
|
||||
@@ -557,6 +557,11 @@ async function executeCliTool(
|
||||
// id field is the LiteLLM endpoint ID (e.g., "g25")
|
||||
const litellmEndpointId = toolConfig.id || toolName;
|
||||
|
||||
// Use configured primary model if no explicit model provided
|
||||
// This allows --model parameter to override the tool's primaryModel
|
||||
// Use undefined if primaryModel is empty string (endpoint.model will be used as fallback)
|
||||
const apiEndpointEffectiveModel = model || (toolConfig.primaryModel || undefined);
|
||||
|
||||
// Find LiteLLM endpoint configuration
|
||||
const litellmEndpoint = findEndpointById(workingDir, litellmEndpointId);
|
||||
if (litellmEndpoint) {
|
||||
@@ -568,13 +573,14 @@ async function executeCliTool(
|
||||
});
|
||||
}
|
||||
|
||||
// Execute via LiteLLM
|
||||
// Execute via LiteLLM with model override
|
||||
const result = await executeLiteLLMEndpoint({
|
||||
prompt,
|
||||
endpointId: litellmEndpointId,
|
||||
baseDir: workingDir,
|
||||
cwd: cd || workingDir,
|
||||
includeDirs: includeDirs ? includeDirs.split(',').map(d => d.trim()) : undefined,
|
||||
model: apiEndpointEffectiveModel, // Pass effective model (--model or primaryModel)
|
||||
onOutput: onOutput || undefined,
|
||||
});
|
||||
|
||||
@@ -587,7 +593,7 @@ async function executeCliTool(
|
||||
id: customId || `${Date.now()}-litellm`,
|
||||
timestamp: new Date(startTime).toISOString(),
|
||||
tool: toolName,
|
||||
model: litellmEndpoint.model,
|
||||
model: result.model, // Use effective model from result (reflects any override)
|
||||
mode,
|
||||
prompt,
|
||||
status: result.success ? 'success' : 'error',
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface LiteLLMExecutionOptions {
|
||||
cwd?: string; // Working directory for file resolution
|
||||
includeDirs?: string[]; // Additional directories for @patterns
|
||||
enableCache?: boolean; // Override endpoint cache setting
|
||||
model?: string; // Override model for this execution (if not specified, uses endpoint.model)
|
||||
onOutput?: (unit: CliOutputUnit) => void;
|
||||
/** Number of retries after the initial attempt (default: 0) */
|
||||
maxRetries?: number;
|
||||
@@ -56,7 +57,7 @@ export function extractPatterns(prompt: string): string[] {
|
||||
export async function executeLiteLLMEndpoint(
|
||||
options: LiteLLMExecutionOptions
|
||||
): Promise<LiteLLMExecutionResult> {
|
||||
const { prompt, endpointId, baseDir, cwd, includeDirs, enableCache, onOutput } = options;
|
||||
const { prompt, endpointId, baseDir, cwd, includeDirs, enableCache, model: modelOverride, onOutput } = options;
|
||||
|
||||
// 1. Find endpoint configuration
|
||||
const endpoint = findEndpointById(baseDir, endpointId);
|
||||
@@ -96,7 +97,10 @@ export async function executeLiteLLMEndpoint(
|
||||
};
|
||||
}
|
||||
|
||||
// 3. Process context cache if enabled
|
||||
// 3. Determine effective model: use override if provided, otherwise use endpoint.model
|
||||
const effectiveModel = modelOverride || endpoint.model;
|
||||
|
||||
// 4. Process context cache if enabled
|
||||
let finalPrompt = prompt;
|
||||
let cacheUsed = false;
|
||||
let cachedFiles: string[] = [];
|
||||
@@ -168,12 +172,12 @@ export async function executeLiteLLMEndpoint(
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Call LiteLLM
|
||||
// 5. Call LiteLLM
|
||||
try {
|
||||
if (onOutput) {
|
||||
onOutput({
|
||||
type: 'stderr',
|
||||
content: `[LiteLLM: Calling ${provider.type}/${endpoint.model}]\n`,
|
||||
content: `[LiteLLM: Calling ${provider.type}/${effectiveModel}]\n`,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
@@ -206,14 +210,14 @@ export async function executeLiteLLMEndpoint(
|
||||
delete process.env['CCW_LITELLM_EXTRA_HEADERS'];
|
||||
}
|
||||
|
||||
// Use litellm-client to call chat
|
||||
// Use litellm-client to call chat with effective model
|
||||
const response = await callWithRetries(
|
||||
() => client.chat(finalPrompt, endpoint.model),
|
||||
() => client.chat(finalPrompt, effectiveModel),
|
||||
{
|
||||
maxRetries: options.maxRetries ?? 0,
|
||||
baseDelayMs: options.retryBaseDelayMs ?? 1000,
|
||||
onOutput,
|
||||
rateLimitKey: `${provider.type}:${endpoint.model}`,
|
||||
rateLimitKey: `${provider.type}:${effectiveModel}`,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -228,7 +232,7 @@ export async function executeLiteLLMEndpoint(
|
||||
return {
|
||||
success: true,
|
||||
output: response,
|
||||
model: endpoint.model,
|
||||
model: effectiveModel,
|
||||
provider: provider.type,
|
||||
cacheUsed,
|
||||
cachedFiles,
|
||||
@@ -246,7 +250,7 @@ export async function executeLiteLLMEndpoint(
|
||||
return {
|
||||
success: false,
|
||||
output: '',
|
||||
model: endpoint.model,
|
||||
model: effectiveModel,
|
||||
provider: provider.type,
|
||||
cacheUsed,
|
||||
error: errorMsg,
|
||||
|
||||
Reference in New Issue
Block a user