mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 08:15:17 +00:00
fix(cliproxy): include BASE_URL and AUTH_TOKEN when applying presets
Presets now always include ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN when applied to provider settings. This ensures CLIProxy routing works correctly for Gemini, Codex, and Agy providers. Also fixes settings save failing for new profiles by changing PUT /api/settings/:profile to upsert behavior (create if not exists).
This commit is contained in:
1 parent
68eab562ce
commit
598454c931
2 files changed
+36
-18
No files matched your search
+27
-18
@@ -781,6 +781,7 @@ apiRoutes.get('/settings/:profile/raw', (req: Request, res: Response): void => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* PUT /api/settings/:profile - Update settings with conflict detection and backup
|
* PUT /api/settings/:profile - Update settings with conflict detection and backup
|
||||||
|
* Creates the settings file if it doesn't exist (upsert behavior)
|
||||||
*/
|
*/
|
||||||
apiRoutes.put('/settings/:profile', (req: Request, res: Response): void => {
|
apiRoutes.put('/settings/:profile', (req: Request, res: Response): void => {
|
||||||
const { profile } = req.params;
|
const { profile } = req.params;
|
||||||
@@ -788,29 +789,36 @@ apiRoutes.put('/settings/:profile', (req: Request, res: Response): void => {
|
|||||||
const ccsDir = getCcsDir();
|
const ccsDir = getCcsDir();
|
||||||
const settingsPath = path.join(ccsDir, `${profile}.settings.json`);
|
const settingsPath = path.join(ccsDir, `${profile}.settings.json`);
|
||||||
|
|
||||||
if (!fs.existsSync(settingsPath)) {
|
const fileExists = fs.existsSync(settingsPath);
|
||||||
res.status(404).json({ error: 'Settings not found' });
|
|
||||||
return;
|
// Only check conflict if file exists and expectedMtime was provided
|
||||||
|
if (fileExists && expectedMtime) {
|
||||||
|
const stat = fs.statSync(settingsPath);
|
||||||
|
if (stat.mtime.getTime() !== expectedMtime) {
|
||||||
|
res.status(409).json({
|
||||||
|
error: 'File modified externally',
|
||||||
|
currentMtime: stat.mtime.getTime(),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conflict detection
|
// Create backup only if file exists
|
||||||
const stat = fs.statSync(settingsPath);
|
let backupPath: string | undefined;
|
||||||
if (expectedMtime && stat.mtime.getTime() !== expectedMtime) {
|
if (fileExists) {
|
||||||
res.status(409).json({
|
const backupDir = path.join(ccsDir, 'backups');
|
||||||
error: 'File modified externally',
|
if (!fs.existsSync(backupDir)) {
|
||||||
currentMtime: stat.mtime.getTime(),
|
fs.mkdirSync(backupDir, { recursive: true });
|
||||||
});
|
}
|
||||||
return;
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
backupPath = path.join(backupDir, `${profile}.${timestamp}.settings.json`);
|
||||||
|
fs.copyFileSync(settingsPath, backupPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create backup
|
// Ensure directory exists for new files
|
||||||
const backupDir = path.join(ccsDir, 'backups');
|
if (!fileExists) {
|
||||||
if (!fs.existsSync(backupDir)) {
|
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
||||||
fs.mkdirSync(backupDir, { recursive: true });
|
|
||||||
}
|
}
|
||||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
||||||
const backupPath = path.join(backupDir, `${profile}.${timestamp}.settings.json`);
|
|
||||||
fs.copyFileSync(settingsPath, backupPath);
|
|
||||||
|
|
||||||
// Write new settings atomically
|
// Write new settings atomically
|
||||||
const tempPath = settingsPath + '.tmp';
|
const tempPath = settingsPath + '.tmp';
|
||||||
@@ -822,6 +830,7 @@ apiRoutes.put('/settings/:profile', (req: Request, res: Response): void => {
|
|||||||
profile,
|
profile,
|
||||||
mtime: newStat.mtime.getTime(),
|
mtime: newStat.mtime.getTime(),
|
||||||
backupPath,
|
backupPath,
|
||||||
|
created: !fileExists,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -296,7 +296,10 @@ export function ProviderEditor({
|
|||||||
sonnet: model.id,
|
sonnet: model.id,
|
||||||
haiku: model.id,
|
haiku: model.id,
|
||||||
};
|
};
|
||||||
|
// Always include BASE_URL and AUTH_TOKEN for CLIProxy providers
|
||||||
updateEnvValues({
|
updateEnvValues({
|
||||||
|
ANTHROPIC_BASE_URL: `http://127.0.0.1:8317/api/provider/${provider}`,
|
||||||
|
ANTHROPIC_AUTH_TOKEN: 'ccs-internal-managed',
|
||||||
ANTHROPIC_MODEL: mapping.default,
|
ANTHROPIC_MODEL: mapping.default,
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: mapping.opus,
|
ANTHROPIC_DEFAULT_OPUS_MODEL: mapping.opus,
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL: mapping.sonnet,
|
ANTHROPIC_DEFAULT_SONNET_MODEL: mapping.sonnet,
|
||||||
@@ -318,7 +321,10 @@ export function ProviderEditor({
|
|||||||
size="sm"
|
size="sm"
|
||||||
className="text-xs h-7 gap-1 pr-6"
|
className="text-xs h-7 gap-1 pr-6"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
// Always include BASE_URL and AUTH_TOKEN for CLIProxy providers
|
||||||
updateEnvValues({
|
updateEnvValues({
|
||||||
|
ANTHROPIC_BASE_URL: `http://127.0.0.1:8317/api/provider/${provider}`,
|
||||||
|
ANTHROPIC_AUTH_TOKEN: 'ccs-internal-managed',
|
||||||
ANTHROPIC_MODEL: preset.default,
|
ANTHROPIC_MODEL: preset.default,
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: preset.opus,
|
ANTHROPIC_DEFAULT_OPUS_MODEL: preset.opus,
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL: preset.sonnet,
|
ANTHROPIC_DEFAULT_SONNET_MODEL: preset.sonnet,
|
||||||
@@ -655,7 +661,10 @@ export function ProviderEditor({
|
|||||||
haiku: haikuModel || '',
|
haiku: haikuModel || '',
|
||||||
}}
|
}}
|
||||||
onApply={(values, presetName) => {
|
onApply={(values, presetName) => {
|
||||||
|
// Always include BASE_URL and AUTH_TOKEN for CLIProxy providers
|
||||||
updateEnvValues({
|
updateEnvValues({
|
||||||
|
ANTHROPIC_BASE_URL: `http://127.0.0.1:8317/api/provider/${provider}`,
|
||||||
|
ANTHROPIC_AUTH_TOKEN: 'ccs-internal-managed',
|
||||||
ANTHROPIC_MODEL: values.default,
|
ANTHROPIC_MODEL: values.default,
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL: values.opus,
|
ANTHROPIC_DEFAULT_OPUS_MODEL: values.opus,
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL: values.sonnet,
|
ANTHROPIC_DEFAULT_SONNET_MODEL: values.sonnet,
|
||||||
|
|||||||
Reference in new issue
Block a user