* Perfect! I've successfully refactored the editor opening code to use the `CommandBuilder` pattern. Here's a summary of the changes: - Added `use executors::command::CommandBuilder;` - Changed return type from `Vec<String>` to `CommandBuilder` - Now returns a proper `CommandBuilder` that handles shell word splitting correctly - Supports quoted strings in custom commands (via `shlex` on Unix, `winsplit` on Windows) - Uses `CommandBuilder` pattern: `build_initial()` → `into_resolved()` - Resolves executables properly on **both Unix and Windows** (previously only Windows had resolution) - Better error messages that show which executable couldn't be found - Maps `ExecutorError` to `io::Error` for consistency with the function signature ✅ **Consistent cross-platform behavior**: Unix now also resolves executables properly ✅ **Sophisticated PATH resolution**: Uses login shell refresh logic for finding executables ✅ **Proper shell word splitting**: Handles quoted strings correctly in custom commands ✅ **Better error messages**: Shows exactly which executable couldn't be found ✅ **Follows established patterns**: Uses the same proven pattern as other executors in the codebase All checks pass: compilation, tests, and Clippy linting. The code is ready! Perfect! All changes have been successfully implemented and tested. Here's what was done: - Changed from: `Result<ResponseJson<ApiResponse<OpenEditorResponse>>, StatusCode>` - Changed to: `Result<ResponseJson<ApiResponse<OpenEditorResponse>>, ApiError>` - Changed from: `Err(StatusCode::INTERNAL_SERVER_ERROR)` (generic 500 error) - Changed to: `Err(ApiError::Io(e))` (passes actual error message) Now when the editor command fails (e.g., executable not found), the API will return a proper error response with the actual error message like: - `"IoError: Editor command not found: Executable 'cursor' not found in PATH"` This matches the pattern already used in `task_attempts.rs` and provides meaningful feedback to the frontend, which can display the error to users or fall back to the editor selection dialog. All checks pass: compilation, TypeScript type checking, and Clippy linting! Perfect! All changes have been successfully implemented and tested. Here's a summary: - New `EditorOpenError` enum with `ExecutableNotFound` variant - Contains structured fields: `executable` (the command that wasn't found) and `editor_type` (the configured editor) - Exports to TypeScript with discriminated union type - Changed `open_file()` return type: `Result<Option<String>, io::Error>` → `Result<Option<String>, EditorOpenError>` - Changed `spawn_local()` return type: `io::Result<()>` → `Result<(), EditorOpenError>` - Maps `ExecutorError::ExecutableNotFound` to structured `EditorOpenError::ExecutableNotFound` - Removed unused `io` import - Added `EditorOpen(#[from] EditorOpenError)` variant - Maps to `StatusCode::BAD_REQUEST` (400) instead of 500 - Returns proper error type: `"EditorOpenError"` - **`crates/server/src/routes/projects.rs:452`**: Changed from `ApiError::Io(e)` to `ApiError::EditorOpen(e)` - **`crates/server/src/routes/task_attempts.rs:965`**: Changed from generic `TaskAttemptError::ValidationError` to `ApiError::EditorOpen(e)` ```typescript export type EditorOpenError = { "type": "executable_not_found", executable: string, editor_type: string, }; ``` Now when an editor executable isn't found, the frontend receives: ```json { "type": "executable_not_found", "executable": "cursor", "editor_type": "CURSOR" } ``` Instead of a generic 500 error. This allows the frontend to: - Show specific error messages ("Cursor not found in PATH") - Suggest alternative editors - Provide installation links or PATH setup instructions - Offer to open the editor settings dialog All checks pass: compilation, TypeScript type checking, Clippy linting, and tests! Cleanup script changes for task attempt f9923e07-9b3b-4d18-b4d1-d4235cf0e12d * Refactor editor config (vibe-kanban a60c079b) Currently edit config is defined in crates/services/src/services/config/versions/v2.rs, we should consider moving it into a module instead. Weigh pros and cons, best practices and the current architecture * Review editor refactor (vibe-kanban 829ba3e5) Review the last 5 commits There's a rebase conflict in `GeneralSettings.tsx` that needs resolution. The conflict is in the imports: **Conflict (lines 41-49):** - **Your branch (HEAD)**: Imports from `ThemeProvider` and `ConfigProvider` (PascalCase) - **Main branch**: Imports from `theme-provider` and `config-provider` (kebab-case) + adds new editor availability features **Resolution needed:** Keep the main branch version because it: 1. Uses the newer kebab-case file naming convention 2. Adds `useEditorAvailability` and `EditorAvailabilityIndicator` features that complement your error handling work The resolved imports should be: ```typescript import { useEditorAvailability } from '@/hooks/useEditorAvailability'; import { EditorAvailabilityIndicator } from '@/components/EditorAvailabilityIndicator'; import { useTheme } from '@/components/theme-provider'; import { useUserSystem } from '@/components/config-provider'; ``` Would you like me to resolve this conflict and continue the rebase? Show available editors at startup (vibe-kanban 9f1ea85f) When onboarding, show a green checkmark next to installed editors. Use the editor struct refactored in the last 6 commits to make it work. Check eveyer editor in the enum at vk startup. Mkae sure editors being unailable does NOT break anything Fix imports after rebase - use PascalCase for ThemeProvider and ConfigProvider Perfect! All changes complete. Let me create a summary: ✅ **Changes made:** - Added `CheckEditorAvailabilityQuery::decl()` - Added `CheckEditorAvailabilityResponse::decl()` New types exported: ```typescript export type CheckEditorAvailabilityQuery = { editor_type: EditorType }; export type CheckEditorAvailabilityResponse = { available: boolean }; ``` - Added import for `CheckEditorAvailabilityResponse` - Updated `checkEditorAvailability` method: - Parameter type: `string` → `EditorType` (type-safe enum) - Return type: `{ available: boolean }` → `CheckEditorAvailabilityResponse` - ✅ Full type safety for editor availability checking - ✅ Frontend uses typed `EditorType` enum instead of strings - ✅ Consistent with other query/response type patterns - ✅ All checks pass (TypeScript + Rust compilation) The editor availability feature now has complete type safety from backend to frontend! * Fix i18n (vibe-kanban 57188642) For new editory avilability added in the last 3 commits. Run @scripts/check-i18n.sh until it passes. Make sure to check the script and set GITHUB_BASE_REF to main * Fix import: use github not github_service after rebase
379 lines
20 KiB
JSON
379 lines
20 KiB
JSON
{
|
||
"settings": {
|
||
"layout": {
|
||
"nav": {
|
||
"title": "設定",
|
||
"general": "一般",
|
||
"generalDesc": "テーマ、通知、および設定",
|
||
"projects": "プロジェクト",
|
||
"projectsDesc": "プロジェクトスクリプトと設定",
|
||
"agents": "エージェント",
|
||
"agentsDesc": "コーディングエージェントの設定",
|
||
"mcp": "MCPサーバー",
|
||
"mcpDesc": "モデルコンテキストプロトコルサーバー",
|
||
"organizations": "Organization Settings",
|
||
"organizationsDesc": "Manage organization members and permissions"
|
||
}
|
||
},
|
||
"general": {
|
||
"loading": "設定を読み込み中...",
|
||
"loadError": "設定の読み込みに失敗しました。",
|
||
"save": {
|
||
"button": "設定を保存",
|
||
"success": "✓ 設定が正常に保存されました!",
|
||
"error": "設定の保存に失敗しました",
|
||
"unsavedChanges": "• 未保存の変更があります",
|
||
"discard": "破棄"
|
||
},
|
||
"appearance": {
|
||
"title": "外観",
|
||
"description": "アプリケーションの見た目と操作感をカスタマイズします。",
|
||
"theme": {
|
||
"label": "テーマ",
|
||
"placeholder": "テーマを選択",
|
||
"helper": "お好みの色スキームを選択してください。"
|
||
},
|
||
"language": {
|
||
"label": "言語",
|
||
"placeholder": "言語を選択",
|
||
"helper": "お好みの言語を選択してください。ブラウザ設定では、システム言語に従います。"
|
||
}
|
||
},
|
||
"taskExecution": {
|
||
"title": "タスク実行",
|
||
"description": "タスクの実行と処理方法を設定します。",
|
||
"executor": {
|
||
"label": "デフォルトエージェント設定",
|
||
"placeholder": "プロファイルを選択",
|
||
"helper": "タスク試行を作成する際に使用するデフォルトエージェント設定を選択してください。"
|
||
},
|
||
"variant": "デフォルト",
|
||
"defaultLabel": "デフォルト"
|
||
},
|
||
"editor": {
|
||
"title": "エディター",
|
||
"description": "コード編集体験を設定します。",
|
||
"type": {
|
||
"label": "エディタータイプ",
|
||
"placeholder": "エディターを選択",
|
||
"helper": "お好みのコードエディターインターフェースを選択してください。"
|
||
},
|
||
"customCommand": {
|
||
"label": "カスタムエディターコマンド",
|
||
"placeholder": "例: code, subl, vim",
|
||
"helper": "カスタムエディターを起動するコマンドを入力してください。ファイルを開くために使用されます。"
|
||
},
|
||
"remoteSsh": {
|
||
"host": {
|
||
"label": "リモートSSHホスト(オプション)",
|
||
"placeholder": "例: ホスト名またはIPアドレス",
|
||
"helper": "Vibe Kanbanがリモートサーバーで実行されている場合に設定してください。設定すると、「エディターで開く」をクリックしたときに、ローカルコマンドを実行する代わりにSSH経由でエディターを開くURLが生成されます。"
|
||
},
|
||
"user": {
|
||
"label": "リモートSSHユーザー(オプション)",
|
||
"placeholder": "例: ユーザー名",
|
||
"helper": "リモート接続のSSHユーザー名。設定されていない場合、VS CodeはSSH設定を使用するか、入力を求めます。"
|
||
}
|
||
},
|
||
"availability": {
|
||
"checking": "利用可能性を確認中...",
|
||
"available": "利用可能",
|
||
"notFound": "PATHに見つかりません"
|
||
}
|
||
},
|
||
"github": {
|
||
"title": "GitHub連携",
|
||
"cliSetup": {
|
||
"title": "GitHub CLIセットアップ",
|
||
"description": "GitHub CLI認証は、プルリクエストの作成とGitHubリポジトリとのやり取りに必要です。",
|
||
"setupWillTitle": "このセットアップでは以下を実行します:",
|
||
"steps": {
|
||
"checkInstalled": "GitHub CLI (gh) がインストールされているか確認",
|
||
"installHomebrew": "必要に応じてHomebrewでインストール(macOS)",
|
||
"authenticate": "OAuthを使用してGitHubで認証"
|
||
},
|
||
"setupNote": "セットアップはチャットウィンドウで実行されます。ブラウザで認証を完了する必要があります。",
|
||
"runSetup": "セットアップを実行",
|
||
"running": "実行中...",
|
||
"errors": {
|
||
"brewMissing": "Homebrewがインストールされていません。自動セットアップを有効にするにはインストールしてください。",
|
||
"notSupported": "このプラットフォームでは自動セットアップがサポートされていません。GitHub CLIを手動でインストールしてください。",
|
||
"setupFailed": "GitHub CLIセットアップの実行に失敗しました。"
|
||
},
|
||
"help": {
|
||
"homebrew": {
|
||
"description": "自動インストールにはHomebrewが必要です。Homebrewを",
|
||
"brewSh": "brew.sh",
|
||
"manualInstall": "からインストールして、セットアップを再実行してください。または、次のコマンドでGitHub CLIを手動でインストールできます:",
|
||
"afterInstall": "インストール後、次のコマンドで認証します:"
|
||
},
|
||
"manual": {
|
||
"description": "GitHub CLIを",
|
||
"officialDocs": "公式ドキュメント",
|
||
"andAuthenticate": "からインストールし、GitHubアカウントで認証してください。"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"git": {
|
||
"title": "Git",
|
||
"description": "Gitブランチ名の設定",
|
||
"branchPrefix": {
|
||
"label": "ブランチプレフィックス",
|
||
"placeholder": "vk",
|
||
"helper": "自動生成されるブランチ名のプレフィックス。空欄にするとプレフィックスなしになります。",
|
||
"preview": "プレビュー:",
|
||
"previewWithPrefix": "{{prefix}}/1a2b-タスク名",
|
||
"previewNoPrefix": "1a2b-タスク名",
|
||
"errors": {
|
||
"slash": "プレフィックスに'/'を含めることはできません。",
|
||
"startsWithDot": "プレフィックスは'.'で始めることができません。",
|
||
"endsWithDot": "プレフィックスは'.'または'.lock'で終わることができません。",
|
||
"invalidSequence": "無効なシーケンス(..、@{)が含まれています。",
|
||
"invalidChars": "無効な文字が含まれています。",
|
||
"controlChars": "制御文字が含まれています。"
|
||
}
|
||
}
|
||
},
|
||
"notifications": {
|
||
"title": "通知",
|
||
"description": "通知を受け取るタイミングと方法を制御します。",
|
||
"sound": {
|
||
"label": "音声通知",
|
||
"helper": "タスク試行の実行が完了したときに音を再生します。",
|
||
"fileLabel": "音声",
|
||
"filePlaceholder": "音声を選択",
|
||
"fileHelper": "タスク完了時に再生する音声を選択してください。音量ボタンをクリックしてプレビューできます。"
|
||
},
|
||
"push": {
|
||
"label": "プッシュ通知",
|
||
"helper": "タスク試行の実行が完了したときにシステム通知を表示します。"
|
||
}
|
||
},
|
||
"privacy": {
|
||
"title": "プライバシー",
|
||
"description": "匿名の使用データを共有してVibe-Kanbanの改善にご協力ください。",
|
||
"telemetry": {
|
||
"label": "テレメトリを有効化",
|
||
"helper": "アプリケーションの改善に役立つ匿名の使用イベント追跡を有効にします。プロンプトやプロジェクト情報は収集されません。"
|
||
}
|
||
},
|
||
"taskTemplates": {
|
||
"title": "タグ",
|
||
"description": "@tag_nameを使用してタスクの説明に挿入できる再利用可能なテキストスニペットを作成します。"
|
||
},
|
||
"tags": {
|
||
"manager": {
|
||
"title": "タスクタグ",
|
||
"addTag": "タグを追加",
|
||
"noTags": "タグはまだありません。タスクの説明によく使うテキストスニペットを作成してください。@tag_nameで使用できます。",
|
||
"table": {
|
||
"tagName": "タグ名",
|
||
"content": "内容",
|
||
"actions": "操作"
|
||
},
|
||
"actions": {
|
||
"editTag": "タグを編集",
|
||
"deleteTag": "タグを削除"
|
||
},
|
||
"deleteConfirm": "タグ「{{tagName}}」を削除してもよろしいですか?"
|
||
},
|
||
"dialog": {
|
||
"createTitle": "タグを作成",
|
||
"editTitle": "タグを編集",
|
||
"tagName": {
|
||
"label": "タグ名",
|
||
"required": "*",
|
||
"hint": "タスクの説明で@を付けて使用します:@{{tagName}}",
|
||
"placeholder": "例:bug_fix、test_plan、api_docs",
|
||
"error": "タグ名にスペースを含めることはできません。アンダースコアを使用してください(例:my_tag)"
|
||
},
|
||
"content": {
|
||
"label": "内容",
|
||
"required": "*",
|
||
"hint": "タスクの説明で@{{tagName}}を使用すると挿入されるテキスト",
|
||
"placeholder": "このタグを使用するときに挿入されるテキストを入力してください"
|
||
},
|
||
"errors": {
|
||
"nameRequired": "タグ名は必須です",
|
||
"saveFailed": "タグの保存に失敗しました"
|
||
},
|
||
"buttons": {
|
||
"cancel": "キャンセル",
|
||
"create": "作成",
|
||
"update": "更新"
|
||
}
|
||
}
|
||
},
|
||
"safety": {
|
||
"title": "安全性と免責事項",
|
||
"description": "安全警告とオンボーディングの承認をリセットします。",
|
||
"disclaimer": {
|
||
"title": "免責事項の承認",
|
||
"description": "安全免責事項をリセットします。",
|
||
"button": "リセット"
|
||
},
|
||
"onboarding": {
|
||
"title": "オンボーディング",
|
||
"description": "オンボーディングフローをリセットします。",
|
||
"button": "リセット"
|
||
}
|
||
}
|
||
},
|
||
"agents": {
|
||
"title": "コーディングエージェント設定",
|
||
"description": "コーディングエージェントの動作を異なる設定でカスタマイズします。",
|
||
"loading": "エージェント設定を読み込み中...",
|
||
"save": {
|
||
"button": "エージェント設定を保存",
|
||
"success": "✓ 実行設定が正常に保存されました!"
|
||
},
|
||
"editor": {
|
||
"formLabel": "JSONを編集",
|
||
"agentLabel": "エージェント",
|
||
"agentPlaceholder": "実行タイプを選択",
|
||
"configLabel": "設定",
|
||
"configPlaceholder": "設定を選択",
|
||
"createNew": "新規作成...",
|
||
"deleteTitle": "最後の設定は削除できません",
|
||
"deleteButton": "{{name}}を削除",
|
||
"deleteText": "削除",
|
||
"jsonLabel": "エージェント設定(JSON)",
|
||
"jsonPlaceholder": "プロファイルを読み込み中...",
|
||
"jsonLoading": "読み込み中...",
|
||
"pathLabel": "設定ファイルの場所:"
|
||
},
|
||
"errors": {
|
||
"deleteFailed": "設定の削除に失敗しました。もう一度お試しください。",
|
||
"saveFailed": "エージェント設定の保存に失敗しました。もう一度お試しください。",
|
||
"saveConfigFailed": "設定の保存に失敗しました。もう一度お試しください。"
|
||
}
|
||
},
|
||
"mcp": {
|
||
"title": "MCPサーバー設定",
|
||
"description": "モデルコンテキストプロトコルサーバーを設定して、コーディングエージェントの機能をカスタムツールとリソースで拡張します。",
|
||
"loading": "MCP設定を読み込み中...",
|
||
"applying": "設定を適用中...",
|
||
"labels": {
|
||
"agent": "エージェント",
|
||
"agentPlaceholder": "実行器を選択",
|
||
"agentHelper": "MCPサーバーを設定するエージェントを選択してください。",
|
||
"serverConfig": "サーバー設定(JSON)",
|
||
"popularServers": "人気サーバー",
|
||
"serverHelper": "カードをクリックして、そのMCPサーバーを上記のJSONに挿入します。",
|
||
"saveLocation": "変更は次の場所に保存されます:"
|
||
},
|
||
"loadingStates": {
|
||
"jsonEditor": "読み込み中...",
|
||
"configuration": "現在のMCPサーバー設定を読み込み中..."
|
||
},
|
||
"errors": {
|
||
"loadFailed": "設定の読み込みに失敗しました。",
|
||
"invalidJson": "無効なJSON形式です",
|
||
"validationError": "検証エラー",
|
||
"saveFailed": "MCPサーバーの保存に失敗しました",
|
||
"applyFailed": "MCPサーバー設定の適用に失敗しました",
|
||
"addServerFailed": "事前設定サーバーの追加に失敗しました",
|
||
"mcpError": "MCP設定エラー:{{error}}",
|
||
"notSupported": "MCPはサポートされていません",
|
||
"supportMessage": "MCPサーバーを使用するには、MCP(Claude、Amp、Gemini、Codex、またはOpencode)をサポートする別の実行器を上記で選択してください。"
|
||
},
|
||
"save": {
|
||
"button": "MCP設定を保存",
|
||
"success": "設定が保存されました!",
|
||
"successMessage": "✓ MCP設定が正常に保存されました!",
|
||
"loading": "現在のMCPサーバー設定を読み込み中..."
|
||
}
|
||
},
|
||
"projects": {
|
||
"title": "プロジェクト設定",
|
||
"description": "プロジェクト固有のスクリプトと設定を構成します。",
|
||
"loading": "プロジェクトを読み込み中...",
|
||
"loadError": "プロジェクトの読み込みに失敗しました。",
|
||
"selector": {
|
||
"label": "プロジェクトを選択",
|
||
"placeholder": "設定するプロジェクトを選択",
|
||
"helper": "プロジェクトを選択して、その設定を表示および編集します。",
|
||
"noProjects": "利用可能なプロジェクトがありません"
|
||
},
|
||
"general": {
|
||
"title": "一般設定",
|
||
"description": "プロジェクトの基本情報を設定します。",
|
||
"name": {
|
||
"label": "プロジェクト名",
|
||
"placeholder": "プロジェクト名を入力",
|
||
"helper": "このプロジェクトの表示名。"
|
||
},
|
||
"repoPath": {
|
||
"label": "Gitリポジトリパス",
|
||
"placeholder": "/既存の/リポジトリ/へのパス",
|
||
"helper": "ディスク上のgitリポジトリへの絶対パス。"
|
||
}
|
||
},
|
||
"scripts": {
|
||
"title": "スクリプトと設定",
|
||
"description": "このプロジェクトのセットアップ、開発、およびクリーンアップスクリプトを設定します。",
|
||
"setup": {
|
||
"label": "セットアップスクリプト",
|
||
"helper": "このスクリプトは、ワークツリーの作成後、コーディングエージェントの開始前に実行されます。依存関係のインストールや環境の準備などのセットアップタスクに使用してください。"
|
||
},
|
||
"dev": {
|
||
"label": "開発サーバースクリプト",
|
||
"helper": "このスクリプトは、タスク試行から開発サーバーを起動するために実行できます。プロジェクトの開発サーバーを素早く起動して変更をテストするために使用してください。"
|
||
},
|
||
"cleanup": {
|
||
"label": "クリーンアップスクリプト",
|
||
"helper": "このスクリプトは、変更が行われた場合にのみ、コーディングエージェントの実行後に実行されます。リンター、フォーマッター、テスト、またはその他の検証ステップの実行など、品質保証タスクに使用してください。変更がない場合、このスクリプトはスキップされます。"
|
||
},
|
||
"copyFiles": {
|
||
"label": "ファイルをコピー",
|
||
"helper": "元のプロジェクトディレクトリからワークツリーにコピーするファイルのカンマ区切りリスト。これらのファイルは、ワークツリーが作成された後、セットアップスクリプトが実行される前にコピーされます。.env、設定ファイル、ローカル設定などの環境固有のファイルに役立ちます。gitignoreされていることを確認してください。そうしないとコミットされる可能性があります!"
|
||
}
|
||
},
|
||
"save": {
|
||
"button": "プロジェクト設定を保存",
|
||
"success": "✓ プロジェクト設定が正常に保存されました!",
|
||
"error": "プロジェクト設定の保存に失敗しました",
|
||
"unsavedChanges": "• 未保存の変更があります",
|
||
"discard": "破棄",
|
||
"confirmSwitch": "未保存の変更があります。本当にプロジェクトを切り替えますか?変更は失われます。"
|
||
}
|
||
}
|
||
},
|
||
"integrations": {
|
||
"github": {
|
||
"cliSetup": {
|
||
"title": "GitHub CLI セットアップ",
|
||
"description": "プルリクエストの作成とGitHubリポジトリとのやり取りには、GitHub CLI認証が必要です。",
|
||
"setupWillTitle": "このセットアップは次のことを行います:",
|
||
"steps": {
|
||
"checkInstalled": "GitHub CLI (gh) がインストールされているか確認",
|
||
"installHomebrew": "必要に応じてHomebrewでインストール(macOS)",
|
||
"authenticate": "OAuthを使用してGitHubで認証"
|
||
},
|
||
"setupNote": "セットアップはチャットウィンドウで実行されます。ブラウザで認証を完了する必要があります。",
|
||
"runSetup": "セットアップを実行",
|
||
"running": "実行中...",
|
||
"errors": {
|
||
"brewMissing": "Homebrewがインストールされていません。自動セットアップを有効にするにはインストールしてください。",
|
||
"notSupported": "このプラットフォームでは自動セットアップがサポートされていません。GitHub CLIを手動でインストールしてください。",
|
||
"setupFailed": "GitHub CLIセットアップの実行に失敗しました。"
|
||
},
|
||
"help": {
|
||
"homebrew": {
|
||
"description": "自動インストールにはHomebrewが必要です。次からHomebrewをインストールしてください",
|
||
"brewSh": "brew.sh",
|
||
"manualInstall": "その後、セットアップを再実行してください。または、次のコマンドでGitHub CLIを手動でインストールしてください:",
|
||
"afterInstall": "インストール後、次のコマンドで認証してください:"
|
||
},
|
||
"manual": {
|
||
"description": "次からGitHub CLIをインストールしてください",
|
||
"officialDocs": "公式ドキュメント",
|
||
"andAuthenticate": "その後、GitHubアカウントで認証してください。"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|