feat: add project profiles for snapshot-based config switching

Add a profile feature that captures the current provider, MCP,
skills and prompt state for Claude Code and Codex as a named
snapshot, and re-applies it in one click from the header switcher
or the tray Projects submenu.

- New profiles table (schema v12) with current marker in settings
- ProfileService orchestrates the four existing switch primitives
  (provider first, then MCP diff, skills diff, prompt enable)
- Best-effort apply: dangling references become warnings, no rollback
- Header combobox switcher + snapshot-style manage dialog
- Tray Projects submenu shared with the UI apply/event pipeline
- i18n for zh/en/ja/zh-TW under the new profiles domain
- Integration tests covering roundtrip, dangling refs and clear
This commit is contained in:
Jason
2026-07-04 16:03:19 +08:00
parent b3e5e32c89
commit 8f018a2d45
22 changed files with 1955 additions and 3 deletions
+28
View File
@@ -1866,6 +1866,34 @@
"deleteMessage": "Are you sure you want to delete prompt \"{{name}}\"?"
}
},
"profiles": {
"switcherTooltip": "Projects: switch providers / MCP / Skills / memory files for Claude Code and Codex in one click",
"none": "No project",
"searchPlaceholder": "Search projects",
"empty": "No projects yet",
"createFromCurrent": "New project",
"createDescription": "Save the current provider, MCP, Skills and memory file configuration as a project you can switch to later.",
"manage": "Manage projects…",
"manageTitle": "Manage Projects",
"manageDescription": "Projects are configuration snapshots. To change a project, adjust your configuration first, then click \"Update from current\".",
"namePlaceholder": "e.g. Development, Drawing",
"rename": "Rename",
"updateSnapshot": "Update from current",
"updateSnapshotConfirm": "Overwrite the snapshot of project \"{{name}}\" with the current configuration?",
"delete": "Delete",
"deleteConfirmTitle": "Confirm Delete",
"deleteConfirmMessage": "Are you sure you want to delete project \"{{name}}\"? Your current configuration will not be changed.",
"createSuccess": "Project created",
"createFailed": "Failed to create project: {{detail}}",
"updateSuccess": "Project updated",
"updateFailed": "Failed to update project: {{detail}}",
"deleteSuccess": "Project deleted",
"deleteFailed": "Failed to delete project: {{detail}}",
"applySuccess": "Project applied",
"applyFailed": "Failed to apply project: {{detail}}",
"applyWarnings": "Project applied with {{warningCount}} warning(s):\n{{details}}",
"clearSuccess": "Switched to no project"
},
"workspace": {
"title": "Workspace Files",
"manage": "Workspace",
+28
View File
@@ -1866,6 +1866,34 @@
"deleteMessage": "プロンプト「{{name}}」を削除してもよろしいですか?"
}
},
"profiles": {
"switcherTooltip": "プロジェクト:Claude Code と Codex のプロバイダー / MCP / Skills / メモリファイルをワンクリックで切り替え",
"none": "プロジェクトを使用しない",
"searchPlaceholder": "プロジェクトを検索",
"empty": "プロジェクトはまだありません",
"createFromCurrent": "新規プロジェクト",
"createDescription": "現在のプロバイダー、MCP、Skills、メモリファイルの設定をプロジェクトとして保存し、後からワンクリックで切り替えられます。",
"manage": "プロジェクトを管理…",
"manageTitle": "プロジェクト管理",
"manageDescription": "プロジェクトは設定のスナップショットです。内容を変更するには、先に設定を調整してから「現在の状態で更新」をクリックしてください。",
"namePlaceholder": "例:開発、イラスト",
"rename": "名前を変更",
"updateSnapshot": "現在の状態で更新",
"updateSnapshotConfirm": "プロジェクト「{{name}}」のスナップショットを現在の設定で上書きしますか?",
"delete": "削除",
"deleteConfirmTitle": "削除の確認",
"deleteConfirmMessage": "プロジェクト「{{name}}」を削除してもよろしいですか?現在の設定は変更されません。",
"createSuccess": "プロジェクトを作成しました",
"createFailed": "プロジェクトの作成に失敗しました: {{detail}}",
"updateSuccess": "プロジェクトを更新しました",
"updateFailed": "プロジェクトの更新に失敗しました: {{detail}}",
"deleteSuccess": "プロジェクトを削除しました",
"deleteFailed": "プロジェクトの削除に失敗しました: {{detail}}",
"applySuccess": "プロジェクトを適用しました",
"applyFailed": "プロジェクトの適用に失敗しました: {{detail}}",
"applyWarnings": "プロジェクトを適用しました(警告 {{warningCount}} 件):\n{{details}}",
"clearSuccess": "プロジェクトを使用しない状態に切り替えました"
},
"workspace": {
"title": "ワークスペースファイル",
"manage": "ワークスペース",
+28
View File
@@ -1838,6 +1838,34 @@
"deleteMessage": "確定要刪除提示詞 \"{{name}}\" 嗎?"
}
},
"profiles": {
"switcherTooltip": "專案:一鍵切換 Claude Code 與 Codex 的供應商 / MCP / Skills / 記憶檔案",
"none": "不使用專案",
"searchPlaceholder": "搜尋專案",
"empty": "尚無專案",
"createFromCurrent": "新建專案",
"createDescription": "把目前的供應商、MCP、Skills 和記憶檔案設定儲存為一個專案,之後可一鍵切換。",
"manage": "管理專案…",
"manageTitle": "管理專案",
"manageDescription": "專案是設定快照。要修改專案內容,先手動調好設定,再點「以目前狀態更新」。",
"namePlaceholder": "例如:開發、繪圖",
"rename": "重新命名",
"updateSnapshot": "以目前狀態更新",
"updateSnapshotConfirm": "用目前的設定狀態覆蓋專案 \"{{name}}\" 的快照?",
"delete": "刪除",
"deleteConfirmTitle": "確認刪除",
"deleteConfirmMessage": "確定要刪除專案 \"{{name}}\" 嗎?不會改動任何現有設定。",
"createSuccess": "專案已建立",
"createFailed": "建立專案失敗: {{detail}}",
"updateSuccess": "專案已更新",
"updateFailed": "更新專案失敗: {{detail}}",
"deleteSuccess": "專案已刪除",
"deleteFailed": "刪除專案失敗: {{detail}}",
"applySuccess": "專案已套用",
"applyFailed": "套用專案失敗: {{detail}}",
"applyWarnings": "專案已套用,{{warningCount}} 條警告:\n{{details}}",
"clearSuccess": "已切換為不使用專案"
},
"workspace": {
"title": "Workspace 檔案管理",
"manage": "Workspace",
+28
View File
@@ -1866,6 +1866,34 @@
"deleteMessage": "确定要删除提示词 \"{{name}}\" 吗?"
}
},
"profiles": {
"switcherTooltip": "项目:一键切换 Claude Code 与 Codex 的供应商 / MCP / Skills / 记忆文件",
"none": "不使用项目",
"searchPlaceholder": "搜索项目",
"empty": "暂无项目",
"createFromCurrent": "新建项目",
"createDescription": "把当前的供应商、MCP、Skills 和记忆文件配置保存为一个项目,之后可一键切换。",
"manage": "管理项目…",
"manageTitle": "管理项目",
"manageDescription": "项目是配置快照。要修改项目内容,先手动调好配置,再点\"以当前状态更新\"。",
"namePlaceholder": "例如:开发、绘图",
"rename": "重命名",
"updateSnapshot": "以当前状态更新",
"updateSnapshotConfirm": "用当前的配置状态覆盖项目 \"{{name}}\" 的快照?",
"delete": "删除",
"deleteConfirmTitle": "确认删除",
"deleteConfirmMessage": "确定要删除项目 \"{{name}}\" 吗?不会改动任何现有配置。",
"createSuccess": "项目已创建",
"createFailed": "创建项目失败: {{detail}}",
"updateSuccess": "项目已更新",
"updateFailed": "更新项目失败: {{detail}}",
"deleteSuccess": "项目已删除",
"deleteFailed": "删除项目失败: {{detail}}",
"applySuccess": "项目已应用",
"applyFailed": "应用项目失败: {{detail}}",
"applyWarnings": "项目已应用,{{warningCount}} 条警告:\n{{details}}",
"clearSuccess": "已切换为不使用项目"
},
"workspace": {
"title": "Workspace 文件管理",
"manage": "Workspace",