mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 00:22:34 +00:00
fix(delegation): dynamic model display from settings
- Read ANTHROPIC_MODEL from profile settings instead of hardcoding - Display model name in full uppercase (GLM-4.7, not Glm-4.7) - Add null/undefined guard to getModelDisplayName - Remove hardcoded GLM-4.6/GLM-4.6 (Thinking) display names Closes #431
This commit is contained in:
@@ -14,7 +14,7 @@ import { ui, warn, info } from '../utils/ui';
|
||||
import { type ExecutionOptions, type ExecutionResult, type StreamMessage } from './executor/types';
|
||||
import { StreamBuffer, formatToolVerbose } from './executor/stream-parser';
|
||||
import { buildExecutionResult } from './executor/result-aggregator';
|
||||
import { getCcsDir } from '../utils/config-manager';
|
||||
import { getCcsDir, getModelDisplayName } from '../utils/config-manager';
|
||||
|
||||
// Re-export types for consumers
|
||||
export type { ExecutionOptions, ExecutionResult, StreamMessage } from './executor/types';
|
||||
@@ -196,8 +196,7 @@ export class HeadlessExecutor {
|
||||
const streamBuffer = new StreamBuffer();
|
||||
|
||||
if (showProgress) {
|
||||
const modelName =
|
||||
profile === 'glm' ? 'GLM-4.6' : profile === 'kimi' ? 'Kimi' : profile.toUpperCase();
|
||||
const modelName = getModelDisplayName(profile);
|
||||
console.error(ui.info(`Delegating to ${modelName}...`));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import * as path from 'path';
|
||||
import { execSync } from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import { ui } from '../utils/ui';
|
||||
import { getModelDisplayName } from '../utils/config-manager';
|
||||
import type { ExecutionResult, ExecutionError, PermissionDenial } from './executor/types';
|
||||
|
||||
// Alias for backward compatibility
|
||||
@@ -58,7 +59,7 @@ class ResultFormatter {
|
||||
let output = '';
|
||||
|
||||
// Header box
|
||||
const modelName = this.getModelDisplayName(profile);
|
||||
const modelName = getModelDisplayName(profile);
|
||||
const headerIcon = success ? '[i]' : '[X]';
|
||||
output += ui.box(`${headerIcon} Delegated to ${modelName} (ccs:${profile})`, {
|
||||
borderStyle: 'round',
|
||||
@@ -225,7 +226,7 @@ class ResultFormatter {
|
||||
*/
|
||||
private static formatInfoTable(result: ExecutionResult): string {
|
||||
const { cwd, profile, duration, exitCode, sessionId, totalCost, numTurns } = result;
|
||||
const modelName = this.getModelDisplayName(profile);
|
||||
const modelName = getModelDisplayName(profile);
|
||||
const durationSec = (duration / 1000).toFixed(1);
|
||||
|
||||
const rows: string[][] = [
|
||||
@@ -253,20 +254,6 @@ class ResultFormatter {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display name for model profile
|
||||
*/
|
||||
private static getModelDisplayName(profile: string): string {
|
||||
const displayNames: Record<string, string> = {
|
||||
glm: 'GLM-4.6',
|
||||
glmt: 'GLM-4.6 (Thinking)',
|
||||
kimi: 'Kimi',
|
||||
default: 'Claude',
|
||||
};
|
||||
|
||||
return displayNames[profile] || profile.toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate string to max length
|
||||
*/
|
||||
@@ -283,7 +270,7 @@ class ResultFormatter {
|
||||
static async formatMinimal(result: ExecutionResult): Promise<string> {
|
||||
await ui.init();
|
||||
const { profile, success, duration } = result;
|
||||
const modelName = this.getModelDisplayName(profile);
|
||||
const modelName = getModelDisplayName(profile);
|
||||
const icon = success ? ui.ok('') : ui.fail('');
|
||||
const durationSec = (duration / 1000).toFixed(1);
|
||||
|
||||
@@ -326,7 +313,7 @@ class ResultFormatter {
|
||||
await ui.init();
|
||||
|
||||
const { profile, duration, sessionId, totalCost, permissionDenials } = result;
|
||||
const modelName = this.getModelDisplayName(profile);
|
||||
const modelName = getModelDisplayName(profile);
|
||||
const timeoutMin = (duration / 60000).toFixed(1);
|
||||
|
||||
let output = '';
|
||||
|
||||
@@ -246,3 +246,37 @@ export function getSettingsPath(profile: string): string {
|
||||
|
||||
return expandedPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display name for a profile by reading ANTHROPIC_MODEL from settings
|
||||
* @param profile - Profile name (glm, glmt, kimi, custom, etc.)
|
||||
* @returns Formatted display name (e.g., 'GLM-4.7', 'Kimi', 'Custom-Model')
|
||||
*/
|
||||
export function getModelDisplayName(profile: string): string {
|
||||
if (!profile) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const settingsPath = path.join(getCcsDir(), `${profile}.settings.json`);
|
||||
|
||||
try {
|
||||
if (fs.existsSync(settingsPath)) {
|
||||
const content = fs.readFileSync(settingsPath, 'utf8');
|
||||
const settings = JSON.parse(content) as { env?: { ANTHROPIC_MODEL?: string } };
|
||||
const model = settings.env?.ANTHROPIC_MODEL;
|
||||
|
||||
if (model) {
|
||||
// Format: 'glm-4.7' -> 'GLM-4.7' (uppercase letters, preserve numbers)
|
||||
return model
|
||||
.split('-')
|
||||
.map((part) => part.toUpperCase())
|
||||
.join('-');
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Fall through to default
|
||||
}
|
||||
|
||||
// Fallback: profile name uppercase
|
||||
return profile.toUpperCase();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('ResultFormatter', () => {
|
||||
|
||||
const formatted = await ResultFormatter.format(result);
|
||||
|
||||
assert.ok(formatted.includes('Delegated to GLM-4.6'));
|
||||
assert.ok(formatted.toLowerCase().includes('delegated to glm'));
|
||||
assert.ok(formatted.includes('ccs:glm'));
|
||||
assert.ok(formatted.includes('/home/user/project'));
|
||||
assert.ok(formatted.includes('2.3s'));
|
||||
@@ -179,11 +179,13 @@ describe('ResultFormatter', () => {
|
||||
};
|
||||
|
||||
const glmFormatted = await ResultFormatter.format(glmResult);
|
||||
assert.ok(glmFormatted.includes('GLM-4.6'));
|
||||
// Model display reads from settings or falls back to profile uppercase
|
||||
// Use case-insensitive check since format may vary (GLM, Glm-4.7, etc.)
|
||||
assert.ok(glmFormatted.toLowerCase().includes('glm'));
|
||||
|
||||
const kimiResult = { ...glmResult, profile: 'kimi' };
|
||||
const kimiFormatted = await ResultFormatter.format(kimiResult);
|
||||
assert.ok(kimiFormatted.includes('Kimi'));
|
||||
assert.ok(kimiFormatted.toLowerCase().includes('kimi'));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -220,7 +222,8 @@ describe('ResultFormatter', () => {
|
||||
const minimal = await ResultFormatter.formatMinimal(result);
|
||||
|
||||
assert.ok(minimal.includes('[OK]'));
|
||||
assert.ok(minimal.includes('GLM-4.6'));
|
||||
// Model display reads from settings or falls back to profile uppercase
|
||||
assert.ok(minimal.toLowerCase().includes('glm'));
|
||||
assert.ok(minimal.includes('1.5s'));
|
||||
assert.ok(minimal.split('\n').length <= 3);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user