* feat(providers): add notes field for provider management - Add notes field to Provider model (backend and frontend) - Display notes with higher priority than URL in provider card - Style notes as non-clickable text to differentiate from URLs - Add notes input field in provider form - Add i18n support (zh/en) for notes field * chore: format code and clean up unused props - Run cargo fmt on Rust backend code - Format TypeScript imports and code style - Remove unused appId prop from ProviderPresetSelector - Clean up unused variables in tests - Integrate notes field handling in provider dialogs * feat(deeplink): implement ccswitch:// protocol for provider import Add deep link support to enable one-click provider configuration import via ccswitch:// URLs. Backend: - Implement URL parsing and validation (src-tauri/src/deeplink.rs) - Add Tauri commands for parse and import (src-tauri/src/commands/deeplink.rs) - Register ccswitch:// protocol in macOS Info.plist - Add comprehensive unit tests (src-tauri/tests/deeplink_import.rs) Frontend: - Create confirmation dialog with security review UI (src/components/DeepLinkImportDialog.tsx) - Add API wrapper (src/lib/api/deeplink.ts) - Integrate event listeners in App.tsx Configuration: - Update Tauri config for deep link handling - Add i18n support for Chinese and English - Include test page for deep link validation (deeplink-test.html) Files: 15 changed, 1312 insertions(+) * chore(deeplink): integrate deep link handling into app lifecycle Wire up deep link infrastructure with app initialization and event handling. Backend Integration: - Register deep link module and commands in mod.rs - Add URL handling in app setup (src-tauri/src/lib.rs:handle_deeplink_url) - Handle deep links from single instance callback (Windows/Linux CLI) - Handle deep links from macOS system events - Add tauri-plugin-deep-link dependency (Cargo.toml) Frontend Integration: - Listen for deeplink-import/deeplink-error events in App.tsx - Update DeepLinkImportDialog component imports Configuration: - Enable deep link plugin in tauri.conf.json - Update Cargo.lock for new dependencies Localization: - Add Chinese translations for deep link UI (zh.json) - Add English translations for deep link UI (en.json) Files: 9 changed, 359 insertions(+), 18 deletions(-) * refactor(deeplink): enhance Codex provider template generation Align deep link import with UI preset generation logic by: - Adding complete config.toml template matching frontend defaults - Generating safe provider name from sanitized input - Including model_provider, reasoning_effort, and wire_api settings - Removing minimal template that only contained base_url - Cleaning up deprecated test file deeplink-test.html * style: fix clippy uninlined_format_args warnings Apply clippy --fix to use inline format arguments in: - src/mcp.rs (8 fixes) - src/services/env_manager.rs (10 fixes) * style: apply code formatting and cleanup - Format TypeScript files with Prettier (App.tsx, EnvWarningBanner.tsx, formatters.ts) - Organize Rust imports and module order alphabetically - Add newline at end of JSON files (en.json, zh.json) - Update Cargo.lock for dependency changes * feat: add model name configuration support for Codex and fix Gemini model handling - Add visual model name input field for Codex providers - Add model name extraction and update utilities in providerConfigUtils - Implement model name state management in useCodexConfigState hook - Add conditional model field rendering in CodexFormFields (non-official only) - Integrate model name sync with TOML config in ProviderForm - Fix Gemini deeplink model injection bug - Correct environment variable name from GOOGLE_GEMINI_MODEL to GEMINI_MODEL - Add test cases for Gemini model injection (with/without model) - All tests passing (9/9) - Fix Gemini model field binding in edit mode - Add geminiModel state to useGeminiConfigState hook - Extract model value during initialization and reset - Sync model field with geminiEnv state to prevent data loss on submit - Fix missing model value display when editing Gemini providers Changes: - 6 files changed, 245 insertions(+), 13 deletions(-)
81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
/**
|
||
* 格式化 JSON 字符串
|
||
* @param value - 原始 JSON 字符串(支持带键名包装的格式)
|
||
* @returns 格式化后的 JSON 字符串(2 空格缩进)
|
||
* @throws 如果 JSON 格式无效
|
||
*/
|
||
export function formatJSON(value: string): string {
|
||
const trimmed = value.trim();
|
||
if (!trimmed) {
|
||
return "";
|
||
}
|
||
// 使用智能解析器来处理可能的片段格式
|
||
const result = parseSmartMcpJson(trimmed);
|
||
return result.formattedConfig;
|
||
}
|
||
|
||
/**
|
||
* 智能解析 MCP JSON 配置
|
||
* 支持两种格式:
|
||
* 1. 纯配置对象:{ "command": "npx", "args": [...], ... }
|
||
* 2. 带键名包装: "server-name": { "command": "npx", ... } 或 { "server-name": {...} }
|
||
*
|
||
* @param jsonText - JSON 字符串
|
||
* @returns { id?: string, config: object, formattedConfig: string }
|
||
* @throws 如果 JSON 格式无效
|
||
*/
|
||
export function parseSmartMcpJson(jsonText: string): {
|
||
id?: string;
|
||
config: any;
|
||
formattedConfig: string;
|
||
} {
|
||
let trimmed = jsonText.trim();
|
||
if (!trimmed) {
|
||
return { config: {}, formattedConfig: "" };
|
||
}
|
||
|
||
// 如果是键值对片段("key": {...}),包装成完整对象
|
||
if (trimmed.startsWith('"') && !trimmed.startsWith("{")) {
|
||
trimmed = `{${trimmed}}`;
|
||
}
|
||
|
||
const parsed = JSON.parse(trimmed);
|
||
|
||
// 如果是单键对象且值是对象,提取键名和配置
|
||
const keys = Object.keys(parsed);
|
||
if (
|
||
keys.length === 1 &&
|
||
parsed[keys[0]] &&
|
||
typeof parsed[keys[0]] === "object" &&
|
||
!Array.isArray(parsed[keys[0]])
|
||
) {
|
||
const id = keys[0];
|
||
const config = parsed[id];
|
||
return {
|
||
id,
|
||
config,
|
||
formattedConfig: JSON.stringify(config, null, 2),
|
||
};
|
||
}
|
||
|
||
// 否则直接使用
|
||
return {
|
||
config: parsed,
|
||
formattedConfig: JSON.stringify(parsed, null, 2),
|
||
};
|
||
}
|
||
|
||
/**
|
||
* TOML 格式化功能已禁用
|
||
*
|
||
* 原因:smol-toml 的 parse/stringify 会丢失所有注释和原有排版。
|
||
* 由于 TOML 常用于配置文件,注释是重要的文档说明,丢失注释会造成严重的用户体验问题。
|
||
*
|
||
* 未来可选方案:
|
||
* - 使用 @ltd/j-toml(支持注释保留,但需额外依赖和复杂的 API)
|
||
* - 实现仅格式化缩进/空白的轻量级方案
|
||
* - 使用 toml-eslint-parser + 自定义生成器
|
||
*
|
||
* 暂时建议:依赖现有的 TOML 语法校验(useCodexTomlValidation),不提供格式化功能。
|
||
*/
|