mirror of
https://github.com/musistudio/claude-code-router.git
synced 2026-01-29 22:02:05 +00:00
fix statusline error
This commit is contained in:
@@ -12,7 +12,7 @@ import { activateCommand } from "./utils/activateCommand";
|
||||
import { readConfigFile } from "./utils";
|
||||
import { version } from "../package.json";
|
||||
import { spawn, exec } from "child_process";
|
||||
import {PID_FILE, readPresetFile, REFERENCE_COUNT_FILE} from "@CCR/shared";
|
||||
import {getPresetDir, loadConfigFromManifest, PID_FILE, readPresetFile, REFERENCE_COUNT_FILE} from "@CCR/shared";
|
||||
import fs, { existsSync, readFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { parseStatusLineData, StatusLineInput } from "./utils/statusline";
|
||||
@@ -81,7 +81,7 @@ async function waitForService(
|
||||
|
||||
const startTime = Date.now();
|
||||
while (Date.now() - startTime < timeout) {
|
||||
const isRunning = await isServiceRunning()
|
||||
const isRunning = isServiceRunning()
|
||||
if (isRunning) {
|
||||
// Wait for an additional short period to ensure service is fully ready
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
@@ -93,43 +93,46 @@ async function waitForService(
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const isRunning = await isServiceRunning()
|
||||
const isRunning = isServiceRunning()
|
||||
|
||||
// If command is not a known command, check if it's a preset
|
||||
if (command && !KNOWN_COMMANDS.includes(command)) {
|
||||
const presetData: any = await readPresetFile(command);
|
||||
const manifest = await readPresetFile(command);
|
||||
|
||||
if (presetData) {
|
||||
// This is a preset, execute code command
|
||||
if (manifest) {
|
||||
// This is a preset, load its configuration
|
||||
const presetDir = getPresetDir(command);
|
||||
const config = loadConfigFromManifest(manifest, presetDir);
|
||||
|
||||
// Execute code command
|
||||
const codeArgs = process.argv.slice(3); // Get remaining arguments
|
||||
|
||||
// Check noServer configuration
|
||||
const shouldStartServer = presetData.noServer !== true;
|
||||
const shouldStartServer = config.noServer !== true;
|
||||
|
||||
// Build environment variable overrides
|
||||
let envOverrides: Record<string, string> | undefined;
|
||||
let envOverrides: Record<string, string> = {};
|
||||
|
||||
// Handle provider configuration (supports both old and new formats)
|
||||
let provider: any = null;
|
||||
|
||||
// Old format: presetData.provider is the provider name
|
||||
if (presetData.provider && typeof presetData.provider === 'string') {
|
||||
const config = await readConfigFile();
|
||||
provider = config.Providers?.find((p: any) => p.name === presetData.provider);
|
||||
// Old format: config.provider is the provider name
|
||||
if (config.provider && typeof config.provider === 'string') {
|
||||
const globalConfig = await readConfigFile();
|
||||
provider = globalConfig.Providers?.find((p: any) => p.name === config.provider);
|
||||
}
|
||||
// New format: presetData.Providers is an array of providers
|
||||
else if (presetData.Providers && presetData.Providers.length > 0) {
|
||||
provider = presetData.Providers[0];
|
||||
// New format: config.Providers is an array of providers
|
||||
else if (config.Providers && config.Providers.length > 0) {
|
||||
provider = config.Providers[0];
|
||||
}
|
||||
|
||||
// If noServer is not true, use local server baseurl
|
||||
if (shouldStartServer) {
|
||||
const config = await readConfigFile();
|
||||
const port = config.PORT || 3456;
|
||||
const presetName = command;
|
||||
const globalConfig = await readConfigFile();
|
||||
const port = globalConfig.PORT || 3456;
|
||||
envOverrides = {
|
||||
...envOverrides,
|
||||
ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}/preset/${presetName}`,
|
||||
ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}/preset/${command}`,
|
||||
};
|
||||
} else if (provider) {
|
||||
// Handle api_base_url, remove /v1/messages suffix
|
||||
@@ -157,10 +160,9 @@ async function main() {
|
||||
|
||||
// Build PresetConfig
|
||||
const presetConfig: PresetConfig = {
|
||||
noServer: presetData.noServer,
|
||||
claudeCodeSettings: presetData.claudeCodeSettings,
|
||||
provider: presetData.provider,
|
||||
router: presetData.router,
|
||||
noServer: config.noServer,
|
||||
claudeCodeSettings: config.claudeCodeSettings,
|
||||
StatusLine: config.StatusLine
|
||||
};
|
||||
|
||||
if (shouldStartServer && !isRunning) {
|
||||
@@ -179,7 +181,7 @@ async function main() {
|
||||
startProcess.unref();
|
||||
|
||||
if (await waitForService()) {
|
||||
executeCodeCommand(codeArgs, presetConfig, envOverrides);
|
||||
executeCodeCommand(codeArgs, presetConfig, envOverrides, command);
|
||||
} else {
|
||||
console.error(
|
||||
"Service startup timeout, please manually run `ccr start` to start the service"
|
||||
@@ -192,7 +194,7 @@ async function main() {
|
||||
console.error("Service is not running. Please start it first with `ccr start`");
|
||||
process.exit(1);
|
||||
}
|
||||
executeCodeCommand(codeArgs, presetConfig, envOverrides);
|
||||
executeCodeCommand(codeArgs, presetConfig, envOverrides, command);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
@@ -245,7 +247,9 @@ async function main() {
|
||||
process.stdin.on("end", async () => {
|
||||
try {
|
||||
const input: StatusLineInput = JSON.parse(inputData);
|
||||
const statusLine = await parseStatusLineData(input);
|
||||
// Check if preset name is provided as argument
|
||||
const presetName = process.argv[3];
|
||||
const statusLine = await parseStatusLineData(input, presetName);
|
||||
console.log(statusLine);
|
||||
} catch (error) {
|
||||
console.error("Error parsing status line data:", error);
|
||||
|
||||
@@ -18,13 +18,15 @@ export interface PresetConfig {
|
||||
};
|
||||
provider?: string;
|
||||
router?: Record<string, any>;
|
||||
StatusLine?: any; // Preset's StatusLine configuration
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export async function executeCodeCommand(
|
||||
args: string[] = [],
|
||||
presetConfig?: PresetConfig | null,
|
||||
envOverrides?: Record<string, string>
|
||||
envOverrides?: Record<string, string>,
|
||||
presetName?: string // Preset name for statusline command
|
||||
) {
|
||||
// Set environment variables using shared function
|
||||
const config = await readConfigFile();
|
||||
@@ -40,11 +42,19 @@ export async function executeCodeCommand(
|
||||
env: env as ClaudeSettingsFlag['env']
|
||||
};
|
||||
|
||||
// Add statusLine if StatusLine is configured
|
||||
if (config?.StatusLine?.enabled) {
|
||||
// Add statusLine configuration
|
||||
// Priority: preset.StatusLine > global config.StatusLine
|
||||
const statusLineConfig = presetConfig?.StatusLine || config?.StatusLine;
|
||||
|
||||
if (statusLineConfig?.enabled) {
|
||||
// If using preset, pass preset name to statusline command
|
||||
const statuslineCommand = presetName
|
||||
? `ccr statusline ${presetName}`
|
||||
: "ccr statusline";
|
||||
|
||||
settingsFlag.statusLine = {
|
||||
type: "command",
|
||||
command: "ccr statusline",
|
||||
command: statuslineCommand,
|
||||
padding: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { execSync } from "child_process";
|
||||
import { tmpdir } from "node:os";
|
||||
import { CONFIG_FILE, HOME_DIR } from "@CCR/shared";
|
||||
import { CONFIG_FILE, HOME_DIR, readPresetFile, getPresetDir, loadConfigFromManifest } from "@CCR/shared";
|
||||
import JSON5 from "json5";
|
||||
|
||||
export interface StatusLineModuleConfig {
|
||||
@@ -11,7 +11,8 @@ export interface StatusLineModuleConfig {
|
||||
text: string;
|
||||
color?: string;
|
||||
background?: string;
|
||||
scriptPath?: string; // Path to the Node.js script file to execute for script-type modules
|
||||
scriptPath?: string;
|
||||
options?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface StatusLineThemeConfig {
|
||||
@@ -162,7 +163,7 @@ function replaceVariables(text: string, variables: Record<string, string>): stri
|
||||
}
|
||||
|
||||
// Execute script and get output
|
||||
async function executeScript(scriptPath: string, variables: Record<string, string>): Promise<string> {
|
||||
async function executeScript(scriptPath: string, variables: Record<string, string>, options?: Record<string, any>): Promise<string> {
|
||||
try {
|
||||
// Check if file exists
|
||||
await fs.access(scriptPath);
|
||||
@@ -172,7 +173,7 @@ async function executeScript(scriptPath: string, variables: Record<string, strin
|
||||
|
||||
// If export is a function, call it with variables
|
||||
if (typeof scriptModule === 'function') {
|
||||
const result = scriptModule(variables);
|
||||
const result = scriptModule(variables, options);
|
||||
// If returns a Promise, wait for it to complete
|
||||
if (result instanceof Promise) {
|
||||
return await result;
|
||||
@@ -532,6 +533,37 @@ async function getProjectThemeConfig(): Promise<{ theme: StatusLineThemeConfig |
|
||||
return { theme: null, style: 'default' };
|
||||
}
|
||||
|
||||
// Read theme configuration from preset
|
||||
async function getPresetThemeConfig(presetName: string): Promise<{ theme: StatusLineThemeConfig | null, style: string }> {
|
||||
try {
|
||||
// Read preset manifest
|
||||
const manifest = await readPresetFile(presetName);
|
||||
if (!manifest) {
|
||||
return { theme: null, style: 'default' };
|
||||
}
|
||||
|
||||
// Load preset configuration (applies userValues if present)
|
||||
const presetDir = getPresetDir(presetName);
|
||||
const config = loadConfigFromManifest(manifest, presetDir);
|
||||
|
||||
// Check if there's StatusLine configuration in preset
|
||||
if (config.StatusLine) {
|
||||
// Get current style, default to 'default'
|
||||
const currentStyle = config.StatusLine.currentStyle || 'default';
|
||||
|
||||
// Check if there's configuration for the corresponding style
|
||||
if (config.StatusLine[currentStyle] && config.StatusLine[currentStyle].modules) {
|
||||
return { theme: config.StatusLine[currentStyle], style: currentStyle };
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Return null if reading fails
|
||||
// console.error("Failed to read preset theme config:", error);
|
||||
}
|
||||
|
||||
return { theme: null, style: 'default' };
|
||||
}
|
||||
|
||||
// Check if simple theme should be used (fallback scheme)
|
||||
// When environment variable USE_SIMPLE_ICONS is set, or when a terminal that might not support Nerd Fonts is detected
|
||||
function shouldUseSimpleTheme(): boolean {
|
||||
@@ -585,36 +617,7 @@ function canDisplayNerdFonts(): boolean {
|
||||
return process.env.USE_SIMPLE_ICONS !== 'true';
|
||||
}
|
||||
|
||||
// Check if specific Unicode characters can be displayed correctly
|
||||
// This is a simple heuristic check
|
||||
function canDisplayUnicodeCharacter(char: string): boolean {
|
||||
// For Nerd Font icons, we assume UTF-8 terminals can display them
|
||||
// But accurate detection is difficult, so we rely on environment variables and terminal type detection
|
||||
try {
|
||||
// Check if terminal supports UTF-8
|
||||
const lang = process.env.LANG || process.env.LC_ALL || process.env.LC_CTYPE || '';
|
||||
if (lang.includes('UTF-8') || lang.includes('utf8') || lang.includes('UTF8')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check LC_* environment variables
|
||||
const lcVars = ['LC_ALL', 'LC_CTYPE', 'LANG'];
|
||||
for (const lcVar of lcVars) {
|
||||
const value = process.env[lcVar];
|
||||
if (value && (value.includes('UTF-8') || value.includes('utf8'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// If check fails, default to true
|
||||
return true;
|
||||
}
|
||||
|
||||
// By default, assume it can be displayed
|
||||
return true;
|
||||
}
|
||||
|
||||
export async function parseStatusLineData(input: StatusLineInput): Promise<string> {
|
||||
export async function parseStatusLineData(input: StatusLineInput, presetName?: string): Promise<string> {
|
||||
try {
|
||||
// Check if simple theme should be used
|
||||
const useSimpleTheme = shouldUseSimpleTheme();
|
||||
@@ -625,8 +628,24 @@ export async function parseStatusLineData(input: StatusLineInput): Promise<strin
|
||||
// Determine which theme to use: use simple theme if user forces it or Nerd Fonts cannot be displayed
|
||||
const effectiveTheme = useSimpleTheme || !canDisplayNerd ? SIMPLE_THEME : DEFAULT_THEME;
|
||||
|
||||
// Get theme configuration from home directory, or use the determined default configuration
|
||||
const { theme: projectTheme, style: currentStyle } = await getProjectThemeConfig();
|
||||
// Get theme configuration: preset config > home directory config > default theme
|
||||
let projectTheme: StatusLineThemeConfig | null = null;
|
||||
let currentStyle = 'default';
|
||||
|
||||
if (presetName) {
|
||||
// Try to get theme configuration from preset first
|
||||
const presetConfig = await getPresetThemeConfig(presetName);
|
||||
projectTheme = presetConfig.theme;
|
||||
currentStyle = presetConfig.style;
|
||||
}
|
||||
|
||||
// If preset theme not found or no preset specified, try home directory config
|
||||
if (!projectTheme) {
|
||||
const homeConfig = await getProjectThemeConfig();
|
||||
projectTheme = homeConfig.theme;
|
||||
currentStyle = homeConfig.style;
|
||||
}
|
||||
|
||||
const theme = projectTheme || effectiveTheme;
|
||||
|
||||
// Get current working directory and Git branch
|
||||
@@ -784,34 +803,6 @@ export async function parseStatusLineData(input: StatusLineInput): Promise<strin
|
||||
}
|
||||
}
|
||||
|
||||
// Read theme configuration from user home directory (specified style)
|
||||
async function getProjectThemeConfigForStyle(style: string): Promise<StatusLineThemeConfig | null> {
|
||||
try {
|
||||
// Only use fixed configuration file in home directory
|
||||
const configPath = CONFIG_FILE;
|
||||
|
||||
// Check if configuration file exists
|
||||
try {
|
||||
await fs.access(configPath);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const configContent = await fs.readFile(configPath, "utf-8");
|
||||
const config = JSON5.parse(configContent);
|
||||
|
||||
// Check if there's StatusLine configuration
|
||||
if (config.StatusLine && config.StatusLine[style] && config.StatusLine[style].modules) {
|
||||
return config.StatusLine[style];
|
||||
}
|
||||
} catch (error) {
|
||||
// Return null if reading fails
|
||||
// console.error("Failed to read theme config:", error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Render default style status line
|
||||
async function renderDefaultStyle(
|
||||
theme: StatusLineThemeConfig,
|
||||
@@ -831,7 +822,7 @@ async function renderDefaultStyle(
|
||||
// If script type, execute script to get text
|
||||
let text = "";
|
||||
if (module.type === "script" && module.scriptPath) {
|
||||
text = await executeScript(module.scriptPath, variables);
|
||||
text = await executeScript(module.scriptPath, variables, module.options);
|
||||
} else {
|
||||
text = replaceVariables(module.text, variables);
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ export const createServer = async (config: any): Promise<any> => {
|
||||
// Return preset info, config uses the applied userValues configuration
|
||||
return {
|
||||
...presetFile,
|
||||
config: loadConfigFromManifest(manifest),
|
||||
config: loadConfigFromManifest(manifest, presetDir),
|
||||
userValues: manifest.userValues || {},
|
||||
};
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -450,7 +450,7 @@ export async function listPresets(): Promise<PresetInfo[]> {
|
||||
version: manifest.version,
|
||||
description: manifest.description,
|
||||
author: manifest.author,
|
||||
config: loadConfigFromManifest(manifest),
|
||||
config: loadConfigFromManifest(manifest, presetDir),
|
||||
});
|
||||
} catch {
|
||||
// Ignore invalid preset directories (no manifest.json or read failed)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Responsible for parsing and validating configuration schema, handling conditional logic and variable replacement
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import {
|
||||
RequiredInput,
|
||||
InputType,
|
||||
@@ -180,8 +181,8 @@ export function getDynamicOptions(
|
||||
return [];
|
||||
}
|
||||
|
||||
// Parse provider reference (e.g. {{selectedProvider}})
|
||||
const providerId = String(providerField).replace(/^{{(.+)}}$/, '$1');
|
||||
// Parse provider reference (e.g. #{selectedProvider})
|
||||
const providerId = String(providerField).replace(/^#{(.+)}$/, '$1');
|
||||
const selectedProvider = values[providerId];
|
||||
|
||||
if (!selectedProvider || !presetConfig.Providers) {
|
||||
@@ -242,7 +243,7 @@ export function resolveOptions(
|
||||
|
||||
/**
|
||||
* Template variable replacement
|
||||
* Supports {{variable}} syntax
|
||||
* Supports #{variable} syntax (different from statusline's {{variable}} format)
|
||||
*/
|
||||
export function replaceTemplateVariables(
|
||||
template: any,
|
||||
@@ -254,7 +255,7 @@ export function replaceTemplateVariables(
|
||||
|
||||
// Handle strings
|
||||
if (typeof template === 'string') {
|
||||
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => {
|
||||
return template.replace(/#{(\w+)}/g, (_, key) => {
|
||||
return values[key] !== undefined ? String(values[key]) : '';
|
||||
});
|
||||
}
|
||||
@@ -295,9 +296,9 @@ export function applyConfigMappings(
|
||||
|
||||
// Resolve value
|
||||
let value: any;
|
||||
if (typeof mapping.value === 'string' && mapping.value.startsWith('{{')) {
|
||||
if (typeof mapping.value === 'string' && mapping.value.startsWith('#')) {
|
||||
// Variable reference
|
||||
const varName = mapping.value.replace(/^{{(.+)}}$/, '$1');
|
||||
const varName = mapping.value.replace(/^#{(.+)}$/, '$1');
|
||||
value = values[varName];
|
||||
} else {
|
||||
// Fixed value
|
||||
@@ -338,7 +339,7 @@ export function applyUserInputs(
|
||||
const schemaFields = getSchemaFields(presetFile.schema);
|
||||
|
||||
// 1. First apply template (if exists)
|
||||
// template completely defines configuration structure, using {{variable}} placeholders
|
||||
// template completely defines configuration structure, using #{variable} placeholders
|
||||
if (presetFile.template) {
|
||||
config = replaceTemplateVariables(presetFile.template, values) as any;
|
||||
} else {
|
||||
@@ -347,7 +348,7 @@ export function applyUserInputs(
|
||||
// These fields will be updated or replaced in subsequent configMappings
|
||||
config = presetFile.config ? { ...presetFile.config } : {};
|
||||
|
||||
// Replace placeholders in config (e.g. {{apiKey}} -> actual value)
|
||||
// Replace placeholders in config (e.g. #{apiKey} -> actual value)
|
||||
config = replaceTemplateVariables(config, values) as any;
|
||||
|
||||
// Finally, remove schema id fields (they should not appear in final configuration)
|
||||
@@ -557,7 +558,7 @@ export function buildDependencyGraph(
|
||||
if (field.options) {
|
||||
const options = field.options as any;
|
||||
if (options.type === 'models' && options.providerField) {
|
||||
const providerId = String(options.providerField).replace(/^{{(.+)}}$/, '$1');
|
||||
const providerId = String(options.providerField).replace(/^#{(.+)}$/, '$1');
|
||||
deps.add(providerId);
|
||||
}
|
||||
}
|
||||
@@ -588,14 +589,78 @@ export function getAffectedFields(
|
||||
return affected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process StatusLine configuration, convert relative scriptPath to absolute path
|
||||
* @param statusLineConfig StatusLine configuration
|
||||
* @param presetDir Preset directory path
|
||||
*/
|
||||
function processStatusLineConfig(statusLineConfig: any, presetDir?: string): any {
|
||||
if (!statusLineConfig || typeof statusLineConfig !== 'object') {
|
||||
return statusLineConfig;
|
||||
}
|
||||
|
||||
const result = { ...statusLineConfig };
|
||||
|
||||
// Process each theme's modules
|
||||
for (const themeKey of Object.keys(result)) {
|
||||
const theme = result[themeKey];
|
||||
if (theme && typeof theme === 'object' && theme.modules) {
|
||||
const modules = Array.isArray(theme.modules) ? theme.modules : [];
|
||||
const processedModules = modules.map((module: any) => {
|
||||
// If module has scriptPath and presetDir is provided, convert to absolute path
|
||||
if (module.scriptPath && presetDir && !module.scriptPath.startsWith('/')) {
|
||||
return {
|
||||
...module,
|
||||
scriptPath: path.join(presetDir, module.scriptPath)
|
||||
};
|
||||
}
|
||||
return module;
|
||||
});
|
||||
result[themeKey] = {
|
||||
...theme,
|
||||
modules: processedModules
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process transformers configuration, convert relative path to absolute path
|
||||
* @param transformersConfig Transformers configuration array
|
||||
* @param presetDir Preset directory path
|
||||
*/
|
||||
function processTransformersConfig(transformersConfig: any[], presetDir?: string): any[] {
|
||||
if (!transformersConfig || !Array.isArray(transformersConfig)) {
|
||||
return transformersConfig;
|
||||
}
|
||||
|
||||
if (!presetDir) {
|
||||
return transformersConfig;
|
||||
}
|
||||
|
||||
return transformersConfig.map((transformer: any) => {
|
||||
// If transformer has path and it's a relative path, convert to absolute path
|
||||
if (transformer.path && !transformer.path.startsWith('/')) {
|
||||
return {
|
||||
...transformer,
|
||||
path: path.join(presetDir, transformer.path)
|
||||
};
|
||||
}
|
||||
return transformer;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configuration from Manifest and apply userValues
|
||||
* Used when reading installed presets, applying user configuration values at runtime
|
||||
*
|
||||
* @param manifest Manifest object (contains original configuration and userValues)
|
||||
* @param presetDir Optional preset directory path (for resolving relative paths like scriptPath)
|
||||
* @returns Applied configuration object
|
||||
*/
|
||||
export function loadConfigFromManifest(manifest: ManifestFile): PresetConfigSection {
|
||||
export function loadConfigFromManifest(manifest: ManifestFile, presetDir?: string): PresetConfigSection {
|
||||
// Convert manifest to PresetFile format
|
||||
const presetFile: PresetFile = {
|
||||
metadata: {
|
||||
@@ -631,11 +696,25 @@ export function loadConfigFromManifest(manifest: ManifestFile): PresetConfigSect
|
||||
}
|
||||
}
|
||||
|
||||
let config: PresetConfigSection;
|
||||
|
||||
// If userValues exist, apply them
|
||||
if (manifest.userValues && Object.keys(manifest.userValues).length > 0) {
|
||||
return applyUserInputs(presetFile, manifest.userValues);
|
||||
config = applyUserInputs(presetFile, manifest.userValues);
|
||||
} else {
|
||||
// If no userValues, use original configuration directly
|
||||
config = presetFile.config;
|
||||
}
|
||||
|
||||
// If no userValues, return original configuration directly
|
||||
return presetFile.config;
|
||||
// Process StatusLine configuration (convert relative scriptPath to absolute path)
|
||||
if (config.StatusLine) {
|
||||
config.StatusLine = processStatusLineConfig(config.StatusLine, presetDir);
|
||||
}
|
||||
|
||||
// Process transformers configuration (convert relative path to absolute path)
|
||||
if (config.transformers) {
|
||||
config.transformers = processTransformersConfig(config.transformers, presetDir);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ export interface DynamicOptions {
|
||||
// Automatically extract name and related configuration from preset's Providers
|
||||
|
||||
// Used when type is 'models'
|
||||
providerField?: string; // Point to provider selector field path (e.g. "{{selectedProvider}}")
|
||||
providerField?: string; // Point to provider selector field path (e.g. "#{selectedProvider}")
|
||||
|
||||
// Used when type is 'custom' (reserved)
|
||||
source?: string; // Custom data source
|
||||
@@ -152,8 +152,8 @@ export interface PresetConfigSection {
|
||||
|
||||
// Template configuration (for dynamically generating configuration based on user input)
|
||||
export interface TemplateConfig {
|
||||
// Template configuration using {{variable}} syntax
|
||||
// Example: { "Providers": [{ "name": "{{providerName}}", "api_key": "{{apiKey}}" }] }
|
||||
// Template configuration using #{variable} syntax (different from statusline's {{variable}} format)
|
||||
// Example: { "Providers": [{ "name": "#{providerName}", "api_key": "#{apiKey}" }] }
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ export interface ConfigMapping {
|
||||
target: string;
|
||||
|
||||
// Value source (references user input id, or uses fixed value)
|
||||
value: string | any; // If string and starts with {{, treated as variable reference
|
||||
value: string | any; // If string and starts with #, treated as variable reference (e.g. #{fieldId})
|
||||
|
||||
// Condition (optional, apply this mapping only when condition is met)
|
||||
when?: Condition | Condition[];
|
||||
|
||||
Reference in New Issue
Block a user