mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-08 22:39:36 +08:00
Merge branch 'feat/agents-new' of github.com:CherryHQ/cherry-studio into feat/agents-new
This commit is contained in:
commit
87f3628b49
@ -80,33 +80,102 @@
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Define how many request/response cycles the agent may complete automatically.",
|
||||
"helper": "Higher values enable longer autonomous runs; lower values keep sessions short.",
|
||||
"label": "Conversation turn limit"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Control how the agent handles actions that require approval.",
|
||||
"label": "Permission mode",
|
||||
"options": {
|
||||
"acceptEdits": "Accept edits automatically",
|
||||
"bypassPermissions": "Bypass permission checks",
|
||||
"default": "Default (ask before continuing)",
|
||||
"plan": "Planning mode (requires plan approval)"
|
||||
},
|
||||
"placeholder": "Choose a permission behavior"
|
||||
},
|
||||
"title": "Advanced Settings"
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Define how many request/response cycles the agent may complete automatically.",
|
||||
"helper": "Higher values enable longer autonomous runs; lower values keep sessions short.",
|
||||
"label": "Conversation turn limit"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Control how the agent handles actions that require approval.",
|
||||
"label": "Permission mode",
|
||||
"options": {
|
||||
"acceptEdits": "Accept edits automatically",
|
||||
"bypassPermissions": "Bypass permission checks",
|
||||
"default": "Default (ask before continuing)",
|
||||
"plan": "Planning mode (requires plan approval)"
|
||||
},
|
||||
"essential": "Essential Settings",
|
||||
"mcps": "MCP Servers",
|
||||
"prompt": "Prompt Settings",
|
||||
"tools": {
|
||||
"approved": "approved",
|
||||
"caution": "Pre-approved tools bypass human review. Enable only trusted tools.",
|
||||
"description": "Choose which tools can run without manual approval.",
|
||||
"requiresPermission": "Requires permission when not pre-approved.",
|
||||
"placeholder": "Choose a permission behavior"
|
||||
},
|
||||
"title": "Advanced Settings"
|
||||
},
|
||||
"essential": "Essential Settings",
|
||||
"prompt": "Prompt Settings",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "File edits and filesystem operations are automatically approved.",
|
||||
"title": "Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "Every tool is pre-approved automatically.",
|
||||
"description": "All permission prompts are skipped — use with caution.",
|
||||
"title": "Bypass permission checks",
|
||||
"warning": "Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "Switching modes updates the automatically approved tools.",
|
||||
"title": "Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "Read-only tools are pre-approved automatically.",
|
||||
"description": "Read-only tools are pre-approved; everything else still needs permission.",
|
||||
"title": "Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "Read-only defaults are pre-approved while execution remains disabled.",
|
||||
"description": "Shares the default read-only tool set but presents a plan before execution.",
|
||||
"title": "Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "Added by mode",
|
||||
"autoDescription": "This tool is auto-approved by the current permission mode.",
|
||||
"empty": "No tools match your filters.",
|
||||
"mcpBadge": "MCP tool",
|
||||
"requiresApproval": "Requires approval when disabled",
|
||||
"search": "Search tools",
|
||||
"toggle": "Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "Auto: {{count}}",
|
||||
"customTools": "Custom: {{count}}",
|
||||
"helper": "Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "MCP: {{count}}",
|
||||
"mode": "Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "approved",
|
||||
"caution": "Pre-approved tools bypass human review. Enable only trusted tools.",
|
||||
"description": "Choose which tools can run without manual approval.",
|
||||
"requiresPermission": "Requires permission when not pre-approved.",
|
||||
"tab": "Pre-approved tools",
|
||||
"title": "Pre-approved tools",
|
||||
"toggle": "{{defaultValue}}"
|
||||
|
||||
@ -99,12 +99,81 @@
|
||||
},
|
||||
"title": "高级设置"
|
||||
},
|
||||
"essential": "基础设置",
|
||||
"mcps": "MCP 服务器",
|
||||
"prompt": "提示词设置",
|
||||
"tools": {
|
||||
"approved": "已授权",
|
||||
"caution": "预先授权的工具会跳过人工审核,请仅启用可信的工具。",
|
||||
"essential": "基础设置",
|
||||
"prompt": "提示词设置",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "连接 MCP 服务器即可解锁更多可在上方预先授权的工具。",
|
||||
"empty": "未检测到 MCP 服务器,请前往 MCP 设置页添加。",
|
||||
"manageHint": "需要更多配置?前往 设置 → MCP 服务器。",
|
||||
"toggle": "切换 {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "预先授权受信任的文件系统工具,允许即时执行。",
|
||||
"description": "文件编辑和文件系统操作将自动通过审批。",
|
||||
"title": "自动接受文件编辑"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "所有工具都会被自动预先授权。",
|
||||
"description": "所有权限提示都会被跳过,请谨慎使用。",
|
||||
"title": "跳过所有权限检查",
|
||||
"warning": "危险:所有工具都会在无审批情况下执行。"
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "切换模式会更新自动预先授权的工具。",
|
||||
"title": "确认切换权限模式?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "只读工具会自动预先授权。",
|
||||
"description": "只读工具会自动预先授权,其它操作仍需权限。",
|
||||
"title": "默认(继续前询问)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "默认的只读工具会自动预先授权,但执行仍被禁用。",
|
||||
"description": "继承默认的只读工具集,并会在执行前先呈现计划。",
|
||||
"title": "规划模式(即将支持)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "模式自动添加",
|
||||
"autoDescription": "该工具由当前权限模式自动预先授权。",
|
||||
"empty": "没有符合筛选条件的工具。",
|
||||
"mcpBadge": "MCP 工具",
|
||||
"requiresApproval": "禁用时需要人工审批",
|
||||
"search": "搜索工具",
|
||||
"toggle": "切换 {{name}}",
|
||||
"warning": {
|
||||
"description": "仅启用你信任的工具。模式默认值会自动标注。",
|
||||
"title": "预先授权的工具将在无人工审核时运行。"
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "自动:{{count}}",
|
||||
"customTools": "自定义:{{count}}",
|
||||
"helper": "设置会自动保存,可随时返回上方步骤进行调整。",
|
||||
"mcp": "MCP:{{count}}",
|
||||
"mode": "模式:{{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "MCP 服务器"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "步骤 1 · 权限模式"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "步骤 2 · 预先授权工具"
|
||||
},
|
||||
"review": {
|
||||
"title": "步骤 3 · 总览"
|
||||
}
|
||||
},
|
||||
"tab": "工具与权限"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "已授权",
|
||||
"caution": "预先授权的工具会跳过人工审核,请仅启用可信的工具。",
|
||||
"description": "选择哪些工具可以在无需人工审批的情况下执行。",
|
||||
"requiresPermission": "未预先授权时需要人工审批。",
|
||||
"tab": "预先授权工具",
|
||||
|
||||
@ -99,12 +99,81 @@
|
||||
},
|
||||
"title": "進階設定"
|
||||
},
|
||||
"essential": "必要設定",
|
||||
"mcps": "MCP 伺服器",
|
||||
"prompt": "提示設定",
|
||||
"tools": {
|
||||
"approved": "已授權",
|
||||
"caution": "預先授權的工具會略過人工審查,請僅啟用可信任的工具。",
|
||||
"essential": "必要設定",
|
||||
"prompt": "提示設定",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "連線 MCP 伺服器即可解鎖更多可在上方預先授權的工具。",
|
||||
"empty": "尚未偵測到 MCP 伺服器,請前往 MCP 設定頁新增。",
|
||||
"manageHint": "需要進階設定?前往 設定 → MCP 伺服器。",
|
||||
"toggle": "切換 {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "預先授權受信任的檔案系統工具,允許即時執行。",
|
||||
"description": "檔案編輯與檔案系統操作會自動通過核准。",
|
||||
"title": "自動接受檔案編輯"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "所有工具都會被自動預先授權。",
|
||||
"description": "所有權限提示都會被略過,請務必謹慎使用。",
|
||||
"title": "略過所有權限檢查",
|
||||
"warning": "警告:所有工具都會在無核准情況下執行。"
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "切換模式會更新自動預先授權的工具。",
|
||||
"title": "確認切換權限模式?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "唯讀工具會自動預先授權。",
|
||||
"description": "唯讀工具會自動預先授權,其它操作仍需核准。",
|
||||
"title": "預設(繼續前先詢問)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "預設的唯讀工具會自動預先授權,但執行仍被停用。",
|
||||
"description": "沿用預設的唯讀工具集,並會在執行前先呈現計畫。",
|
||||
"title": "規劃模式(即將支援)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "模式自動添加",
|
||||
"autoDescription": "此工具由目前的權限模式自動預先授權。",
|
||||
"empty": "沒有符合篩選條件的工具。",
|
||||
"mcpBadge": "MCP 工具",
|
||||
"requiresApproval": "停用時需要人工核准",
|
||||
"search": "搜尋工具",
|
||||
"toggle": "切換 {{name}}",
|
||||
"warning": {
|
||||
"description": "僅啟用你信任的工具。模式預設值會自動標示。",
|
||||
"title": "預先授權的工具將在無人工審查下執行。"
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "自動:{{count}}",
|
||||
"customTools": "自訂:{{count}}",
|
||||
"helper": "設定會自動儲存,可隨時回到上方步驟調整。",
|
||||
"mcp": "MCP:{{count}}",
|
||||
"mode": "模式:{{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "MCP 伺服器"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "步驟 1 · 權限模式"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "步驟 2 · 預先授權工具"
|
||||
},
|
||||
"review": {
|
||||
"title": "步驟 3 · 檢視"
|
||||
}
|
||||
},
|
||||
"tab": "工具與權限"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "已授權",
|
||||
"caution": "預先授權的工具會略過人工審查,請僅啟用可信任的工具。",
|
||||
"description": "選擇哪些工具可在無需人工核准的情況下執行。",
|
||||
"requiresPermission": "未預先授權時需要人工核准。",
|
||||
"tab": "預先授權工具",
|
||||
|
||||
@ -47,8 +47,8 @@
|
||||
"allowed_tools": {
|
||||
"empty": "Δεν υπάρχουν διαθέσιμα εργαλεία για αυτόν τον agent.",
|
||||
"helper": "Επιλέξτε ποια εργαλεία είναι προεγκεκριμένα. Τα μη επιλεγμένα θα χρειαστούν έγκριση πριν από τη χρήση.",
|
||||
"label": "Προεγκεκριμένα εργαλεία",
|
||||
"placeholder": "Επιλέξτε προεγκεκριμένα εργαλεία"
|
||||
"label": "[to be translated]:Pre-approved tools",
|
||||
"placeholder": "[to be translated]:Select pre-approved tools"
|
||||
},
|
||||
"create": {
|
||||
"error": {
|
||||
@ -82,26 +82,96 @@
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Ορίστε τον αριθμό γύρων αιτήματος/απάντησης που θα εκτελούνται αυτόματα από τον διαμεσολαβητ.",
|
||||
"helper": "Όσο υψηλότερη είναι η τιμή, τόσο περισσότερο μπορεί να λειτουργεί αυτόνομα· όσο χαμηλότερη είναι, τόσο πιο εύκολα ελέγχεται.",
|
||||
"label": "Όριο αριθμού γύρων συνεδρίας"
|
||||
"description": "[to be translated]:设定代理自动执行的请求/回复轮次数。",
|
||||
"helper": "[to be translated]:数值越高可自主运行越久;数值越低更易控制。",
|
||||
"label": "[to be translated]:会话轮次数上限"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Ο τρόπος με τον οποίο ο πληρεξούσιος χειρίζεται την κατάσταση όταν απαιτείται εξουσιοδότηση.",
|
||||
"label": "Λειτουργία δικαιωμάτων",
|
||||
"description": "[to be translated]:控制代理在需要授权时的处理方式。",
|
||||
"label": "[to be translated]:权限模式",
|
||||
"options": {
|
||||
"acceptEdits": "Αυτόματη αποδοχή επεξεργασίας",
|
||||
"bypassPermissions": "παράλειψη ελέγχου δικαιωμάτων",
|
||||
"default": "Προεπιλογή (να ερωτηθεί πριν από τη συνέχεια)",
|
||||
"plan": "Λειτουργία σχεδιασμού (απαιτείται έγκριση σχεδίου)"
|
||||
"acceptEdits": "[to be translated]:自动接受编辑",
|
||||
"bypassPermissions": "[to be translated]:跳过权限检查",
|
||||
"default": "[to be translated]:默认(继续前询问)",
|
||||
"plan": "[to be translated]:规划模式(需审批计划)"
|
||||
},
|
||||
"placeholder": "Επιλέξτε λειτουργία δικαιωμάτων"
|
||||
"placeholder": "[to be translated]:选择权限模式"
|
||||
},
|
||||
"title": "Ρυθμίσεις για προχωρημένους"
|
||||
"title": "[to be translated]:高级设置"
|
||||
},
|
||||
"essential": "Βασικές Ρυθμίσεις",
|
||||
"mcps": "Διακομιστής MCP",
|
||||
"prompt": "Ρυθμίσεις Προτροπής",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "[to be translated]:Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "[to be translated]:No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "[to be translated]:Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "[to be translated]:Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "[to be translated]:Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "[to be translated]:File edits and filesystem operations are automatically approved.",
|
||||
"title": "[to be translated]:Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "[to be translated]:Every tool is pre-approved automatically.",
|
||||
"description": "[to be translated]:All permission prompts are skipped — use with caution.",
|
||||
"title": "[to be translated]:Bypass permission checks",
|
||||
"warning": "[to be translated]:Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "[to be translated]:Switching modes updates the automatically approved tools.",
|
||||
"title": "[to be translated]:Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "[to be translated]:No tools are pre-approved automatically.",
|
||||
"description": "[to be translated]:Normal permission checks apply.",
|
||||
"title": "[to be translated]:Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "[to be translated]:Read-only tools only. Execution is disabled.",
|
||||
"description": "[to be translated]:Claude can only use read-only tools and presents a plan before execution.",
|
||||
"title": "[to be translated]:Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "[to be translated]:Added by mode",
|
||||
"autoDescription": "[to be translated]:This tool is auto-approved by the current permission mode.",
|
||||
"empty": "[to be translated]:No tools match your filters.",
|
||||
"mcpBadge": "[to be translated]:MCP tool",
|
||||
"requiresApproval": "[to be translated]:Requires approval when disabled",
|
||||
"search": "[to be translated]:Search tools",
|
||||
"toggle": "[to be translated]:Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "[to be translated]:Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "[to be translated]:Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "[to be translated]:Auto: {{count}}",
|
||||
"customTools": "[to be translated]:Custom: {{count}}",
|
||||
"helper": "[to be translated]:Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "[to be translated]:MCP: {{count}}",
|
||||
"mode": "[to be translated]:Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "[to be translated]:MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "[to be translated]:Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "[to be translated]:Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "[to be translated]:Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "[to be translated]:Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "εγκεκριμένο",
|
||||
"caution": "Εργαλεία προεγκεκριμένα παρακάμπτουν την ανθρώπινη αξιολόγηση. Ενεργοποιήστε μόνο έμπιστα εργαλεία.",
|
||||
|
||||
@ -47,8 +47,8 @@
|
||||
"allowed_tools": {
|
||||
"empty": "No hay herramientas disponibles para este agente.",
|
||||
"helper": "Elige qué herramientas quedan preaprobadas. Las no seleccionadas requerirán aprobación manual antes de usarse.",
|
||||
"label": "Herramientas preaprobadas",
|
||||
"placeholder": "Seleccionar herramientas preaprobadas"
|
||||
"label": "[to be translated]:Pre-approved tools",
|
||||
"placeholder": "[to be translated]:Select pre-approved tools"
|
||||
},
|
||||
"create": {
|
||||
"error": {
|
||||
@ -82,26 +82,96 @@
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Establece el número de rondas de solicitud/respuesta que el agente ejecutará automáticamente.",
|
||||
"helper": "Cuanto mayor es el valor, más tiempo puede funcionar de forma autónoma; cuanto menor es el valor, más fácil es de controlar.",
|
||||
"label": "Límite máximo de turnos de conversación"
|
||||
"description": "[to be translated]:设定代理自动执行的请求/回复轮次数。",
|
||||
"helper": "[to be translated]:数值越高可自主运行越久;数值越低更易控制。",
|
||||
"label": "[to be translated]:会话轮次数上限"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Cómo el agente de control maneja las situaciones que requieren autorización.",
|
||||
"label": "modo de permisos",
|
||||
"description": "[to be translated]:控制代理在需要授权时的处理方式。",
|
||||
"label": "[to be translated]:权限模式",
|
||||
"options": {
|
||||
"acceptEdits": "Aceptar ediciones automáticamente",
|
||||
"bypassPermissions": "Omitir verificación de permisos",
|
||||
"default": "Predeterminado (preguntar antes de continuar)",
|
||||
"plan": "Modo de planificación (requiere aprobación del plan)"
|
||||
"acceptEdits": "[to be translated]:自动接受编辑",
|
||||
"bypassPermissions": "[to be translated]:跳过权限检查",
|
||||
"default": "[to be translated]:默认(继续前询问)",
|
||||
"plan": "[to be translated]:规划模式(需审批计划)"
|
||||
},
|
||||
"placeholder": "Seleccionar modo de permisos"
|
||||
"placeholder": "[to be translated]:选择权限模式"
|
||||
},
|
||||
"title": "Configuración avanzada"
|
||||
"title": "[to be translated]:高级设置"
|
||||
},
|
||||
"essential": "Configuraciones esenciales",
|
||||
"mcps": "Servidor MCP",
|
||||
"prompt": "Configuración de indicaciones",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "[to be translated]:Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "[to be translated]:No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "[to be translated]:Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "[to be translated]:Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "[to be translated]:Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "[to be translated]:File edits and filesystem operations are automatically approved.",
|
||||
"title": "[to be translated]:Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "[to be translated]:Every tool is pre-approved automatically.",
|
||||
"description": "[to be translated]:All permission prompts are skipped — use with caution.",
|
||||
"title": "[to be translated]:Bypass permission checks",
|
||||
"warning": "[to be translated]:Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "[to be translated]:Switching modes updates the automatically approved tools.",
|
||||
"title": "[to be translated]:Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "[to be translated]:No tools are pre-approved automatically.",
|
||||
"description": "[to be translated]:Normal permission checks apply.",
|
||||
"title": "[to be translated]:Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "[to be translated]:Read-only tools only. Execution is disabled.",
|
||||
"description": "[to be translated]:Claude can only use read-only tools and presents a plan before execution.",
|
||||
"title": "[to be translated]:Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "[to be translated]:Added by mode",
|
||||
"autoDescription": "[to be translated]:This tool is auto-approved by the current permission mode.",
|
||||
"empty": "[to be translated]:No tools match your filters.",
|
||||
"mcpBadge": "[to be translated]:MCP tool",
|
||||
"requiresApproval": "[to be translated]:Requires approval when disabled",
|
||||
"search": "[to be translated]:Search tools",
|
||||
"toggle": "[to be translated]:Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "[to be translated]:Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "[to be translated]:Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "[to be translated]:Auto: {{count}}",
|
||||
"customTools": "[to be translated]:Custom: {{count}}",
|
||||
"helper": "[to be translated]:Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "[to be translated]:MCP: {{count}}",
|
||||
"mode": "[to be translated]:Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "[to be translated]:MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "[to be translated]:Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "[to be translated]:Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "[to be translated]:Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "[to be translated]:Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "aprobado",
|
||||
"caution": "Herramientas preaprobadas omiten la revisión humana. Habilita solo herramientas de confianza.",
|
||||
|
||||
@ -47,8 +47,8 @@
|
||||
"allowed_tools": {
|
||||
"empty": "Aucun outil disponible pour cet agent.",
|
||||
"helper": "Choisissez les outils préapprouvés. Les outils non sélectionnés nécessiteront une approbation avant utilisation.",
|
||||
"label": "Outils pré-approuvés",
|
||||
"placeholder": "Sélectionner des outils pré-approuvés"
|
||||
"label": "[to be translated]:Pre-approved tools",
|
||||
"placeholder": "[to be translated]:Select pre-approved tools"
|
||||
},
|
||||
"create": {
|
||||
"error": {
|
||||
@ -82,26 +82,96 @@
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Définir le nombre de cycles de requête/réponse exécutés automatiquement par l'agent.",
|
||||
"helper": "Une valeur plus élevée permet une autonomie prolongée ; une valeur plus faible facilite le contrôle.",
|
||||
"label": "Limite maximale de tours de conversation"
|
||||
"description": "[to be translated]:设定代理自动执行的请求/回复轮次数。",
|
||||
"helper": "[to be translated]:数值越高可自主运行越久;数值越低更易控制。",
|
||||
"label": "[to be translated]:会话轮次数上限"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Contrôle la manière dont l'agent gère les demandes d'autorisation.",
|
||||
"label": "mode d'autorisation",
|
||||
"description": "[to be translated]:控制代理在需要授权时的处理方式。",
|
||||
"label": "[to be translated]:权限模式",
|
||||
"options": {
|
||||
"acceptEdits": "Accepter automatiquement les modifications",
|
||||
"bypassPermissions": "sauter la vérification des autorisations",
|
||||
"default": "Par défaut (demander avant de continuer)",
|
||||
"plan": "Mode de planification (plan soumis à approbation)"
|
||||
"acceptEdits": "[to be translated]:自动接受编辑",
|
||||
"bypassPermissions": "[to be translated]:跳过权限检查",
|
||||
"default": "[to be translated]:默认(继续前询问)",
|
||||
"plan": "[to be translated]:规划模式(需审批计划)"
|
||||
},
|
||||
"placeholder": "Choisir le mode d'autorisation"
|
||||
"placeholder": "[to be translated]:选择权限模式"
|
||||
},
|
||||
"title": "Paramètres avancés"
|
||||
"title": "[to be translated]:高级设置"
|
||||
},
|
||||
"essential": "Paramètres essentiels",
|
||||
"mcps": "Serveur MCP",
|
||||
"prompt": "Paramètres de l'invite",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "[to be translated]:Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "[to be translated]:No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "[to be translated]:Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "[to be translated]:Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "[to be translated]:Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "[to be translated]:File edits and filesystem operations are automatically approved.",
|
||||
"title": "[to be translated]:Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "[to be translated]:Every tool is pre-approved automatically.",
|
||||
"description": "[to be translated]:All permission prompts are skipped — use with caution.",
|
||||
"title": "[to be translated]:Bypass permission checks",
|
||||
"warning": "[to be translated]:Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "[to be translated]:Switching modes updates the automatically approved tools.",
|
||||
"title": "[to be translated]:Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "[to be translated]:No tools are pre-approved automatically.",
|
||||
"description": "[to be translated]:Normal permission checks apply.",
|
||||
"title": "[to be translated]:Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "[to be translated]:Read-only tools only. Execution is disabled.",
|
||||
"description": "[to be translated]:Claude can only use read-only tools and presents a plan before execution.",
|
||||
"title": "[to be translated]:Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "[to be translated]:Added by mode",
|
||||
"autoDescription": "[to be translated]:This tool is auto-approved by the current permission mode.",
|
||||
"empty": "[to be translated]:No tools match your filters.",
|
||||
"mcpBadge": "[to be translated]:MCP tool",
|
||||
"requiresApproval": "[to be translated]:Requires approval when disabled",
|
||||
"search": "[to be translated]:Search tools",
|
||||
"toggle": "[to be translated]:Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "[to be translated]:Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "[to be translated]:Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "[to be translated]:Auto: {{count}}",
|
||||
"customTools": "[to be translated]:Custom: {{count}}",
|
||||
"helper": "[to be translated]:Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "[to be translated]:MCP: {{count}}",
|
||||
"mode": "[to be translated]:Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "[to be translated]:MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "[to be translated]:Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "[to be translated]:Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "[to be translated]:Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "[to be translated]:Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "approuvé",
|
||||
"caution": "Outils pré-approuvés contournent la révision humaine. Activez uniquement les outils de confiance.",
|
||||
|
||||
@ -82,26 +82,96 @@
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "プロキシが自動的に実行するリクエスト/レスポンスのラウンド数を設定します。",
|
||||
"helper": "数値が高いほど自律動作の時間が長くなり、数値が低いほど制御しやすくなります。",
|
||||
"label": "会話ラウンド数の上限"
|
||||
"description": "[to be translated]:设定代理自动执行的请求/回复轮次数。",
|
||||
"helper": "[to be translated]:数值越高可自主运行越久;数值越低更易控制。",
|
||||
"label": "[to be translated]:会话轮次数上限"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "制御エージェントが認可を必要とする場合の処理方法。",
|
||||
"label": "権限モード",
|
||||
"description": "[to be translated]:控制代理在需要授权时的处理方式。",
|
||||
"label": "[to be translated]:权限模式",
|
||||
"options": {
|
||||
"acceptEdits": "自動的に編集を受け入れる",
|
||||
"bypassPermissions": "権限チェックをスキップ",
|
||||
"default": "デフォルト(続行する前に確認)",
|
||||
"plan": "計画モード(承認が必要な計画)"
|
||||
"acceptEdits": "[to be translated]:自动接受编辑",
|
||||
"bypassPermissions": "[to be translated]:跳过权限检查",
|
||||
"default": "[to be translated]:默认(继续前询问)",
|
||||
"plan": "[to be translated]:规划模式(需审批计划)"
|
||||
},
|
||||
"placeholder": "権限モードを選択"
|
||||
"placeholder": "[to be translated]:选择权限模式"
|
||||
},
|
||||
"title": "高級設定"
|
||||
"title": "[to be translated]:高级设置"
|
||||
},
|
||||
"essential": "必須設定",
|
||||
"mcps": "MCPサーバー",
|
||||
"prompt": "プロンプト設定",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "[to be translated]:Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "[to be translated]:No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "[to be translated]:Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "[to be translated]:Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "[to be translated]:Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "[to be translated]:File edits and filesystem operations are automatically approved.",
|
||||
"title": "[to be translated]:Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "[to be translated]:Every tool is pre-approved automatically.",
|
||||
"description": "[to be translated]:All permission prompts are skipped — use with caution.",
|
||||
"title": "[to be translated]:Bypass permission checks",
|
||||
"warning": "[to be translated]:Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "[to be translated]:Switching modes updates the automatically approved tools.",
|
||||
"title": "[to be translated]:Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "[to be translated]:No tools are pre-approved automatically.",
|
||||
"description": "[to be translated]:Normal permission checks apply.",
|
||||
"title": "[to be translated]:Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "[to be translated]:Read-only tools only. Execution is disabled.",
|
||||
"description": "[to be translated]:Claude can only use read-only tools and presents a plan before execution.",
|
||||
"title": "[to be translated]:Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "[to be translated]:Added by mode",
|
||||
"autoDescription": "[to be translated]:This tool is auto-approved by the current permission mode.",
|
||||
"empty": "[to be translated]:No tools match your filters.",
|
||||
"mcpBadge": "[to be translated]:MCP tool",
|
||||
"requiresApproval": "[to be translated]:Requires approval when disabled",
|
||||
"search": "[to be translated]:Search tools",
|
||||
"toggle": "[to be translated]:Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "[to be translated]:Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "[to be translated]:Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "[to be translated]:Auto: {{count}}",
|
||||
"customTools": "[to be translated]:Custom: {{count}}",
|
||||
"helper": "[to be translated]:Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "[to be translated]:MCP: {{count}}",
|
||||
"mode": "[to be translated]:Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "[to be translated]:MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "[to be translated]:Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "[to be translated]:Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "[to be translated]:Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "[to be translated]:Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "承認済み",
|
||||
"caution": "事前承認したツールは人によるレビューをスキップします。信頼できるツールのみ有効にしてください。",
|
||||
|
||||
@ -47,8 +47,8 @@
|
||||
"allowed_tools": {
|
||||
"empty": "Não há ferramentas disponíveis para este agente.",
|
||||
"helper": "Escolha quais ferramentas ficam pré-autorizadas. As não selecionadas exigirão aprovação antes do uso.",
|
||||
"label": "Ferramentas pré-aprovadas",
|
||||
"placeholder": "Selecionar ferramentas pré-aprovadas"
|
||||
"label": "[to be translated]:Pre-approved tools",
|
||||
"placeholder": "[to be translated]:Select pre-approved tools"
|
||||
},
|
||||
"create": {
|
||||
"error": {
|
||||
@ -82,26 +82,96 @@
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Define o número de ciclos de solicitação/resposta executados automaticamente pelo agente.",
|
||||
"helper": "Quanto maior o valor, mais tempo pode funcionar de forma autônoma; quanto menor o valor, mais fácil de controlar.",
|
||||
"label": "Limite máximo de turnos de conversa"
|
||||
"description": "[to be translated]:设定代理自动执行的请求/回复轮次数。",
|
||||
"helper": "[to be translated]:数值越高可自主运行越久;数值越低更易控制。",
|
||||
"label": "[to be translated]:会话轮次数上限"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Controla como o agente lida com situações que exigem autorização.",
|
||||
"label": "Modo de permissão",
|
||||
"description": "[to be translated]:控制代理在需要授权时的处理方式。",
|
||||
"label": "[to be translated]:权限模式",
|
||||
"options": {
|
||||
"acceptEdits": "Aceitar edições automaticamente",
|
||||
"bypassPermissions": "忽略检查 de permissão",
|
||||
"default": "Padrão (perguntar antes de continuar)",
|
||||
"plan": "Modo de planejamento (plano sujeito a aprovação)"
|
||||
"acceptEdits": "[to be translated]:自动接受编辑",
|
||||
"bypassPermissions": "[to be translated]:跳过权限检查",
|
||||
"default": "[to be translated]:默认(继续前询问)",
|
||||
"plan": "[to be translated]:规划模式(需审批计划)"
|
||||
},
|
||||
"placeholder": "Selecione o modo de permissão"
|
||||
"placeholder": "[to be translated]:选择权限模式"
|
||||
},
|
||||
"title": "Configurações avançadas"
|
||||
"title": "[to be translated]:高级设置"
|
||||
},
|
||||
"essential": "Configurações Essenciais",
|
||||
"mcps": "Servidor MCP",
|
||||
"prompt": "Configurações de Prompt",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "[to be translated]:Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "[to be translated]:No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "[to be translated]:Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "[to be translated]:Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "[to be translated]:Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "[to be translated]:File edits and filesystem operations are automatically approved.",
|
||||
"title": "[to be translated]:Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "[to be translated]:Every tool is pre-approved automatically.",
|
||||
"description": "[to be translated]:All permission prompts are skipped — use with caution.",
|
||||
"title": "[to be translated]:Bypass permission checks",
|
||||
"warning": "[to be translated]:Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "[to be translated]:Switching modes updates the automatically approved tools.",
|
||||
"title": "[to be translated]:Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "[to be translated]:No tools are pre-approved automatically.",
|
||||
"description": "[to be translated]:Normal permission checks apply.",
|
||||
"title": "[to be translated]:Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "[to be translated]:Read-only tools only. Execution is disabled.",
|
||||
"description": "[to be translated]:Claude can only use read-only tools and presents a plan before execution.",
|
||||
"title": "[to be translated]:Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "[to be translated]:Added by mode",
|
||||
"autoDescription": "[to be translated]:This tool is auto-approved by the current permission mode.",
|
||||
"empty": "[to be translated]:No tools match your filters.",
|
||||
"mcpBadge": "[to be translated]:MCP tool",
|
||||
"requiresApproval": "[to be translated]:Requires approval when disabled",
|
||||
"search": "[to be translated]:Search tools",
|
||||
"toggle": "[to be translated]:Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "[to be translated]:Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "[to be translated]:Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "[to be translated]:Auto: {{count}}",
|
||||
"customTools": "[to be translated]:Custom: {{count}}",
|
||||
"helper": "[to be translated]:Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "[to be translated]:MCP: {{count}}",
|
||||
"mode": "[to be translated]:Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "[to be translated]:MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "[to be translated]:Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "[to be translated]:Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "[to be translated]:Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "[to be translated]:Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "aprovado",
|
||||
"caution": "Ferramentas pré-aprovadas ignoram a revisão humana. Ative apenas ferramentas confiáveis.",
|
||||
|
||||
@ -47,8 +47,8 @@
|
||||
"allowed_tools": {
|
||||
"empty": "Для этого агента нет доступных инструментов.",
|
||||
"helper": "Выберите инструменты с предварительным допуском. Неотмеченные инструменты потребуют подтверждения перед использованием.",
|
||||
"label": "Предварительно одобренные инструменты",
|
||||
"placeholder": "Выберите предварительно одобренные инструменты"
|
||||
"label": "[to be translated]:Pre-approved tools",
|
||||
"placeholder": "[to be translated]:Select pre-approved tools"
|
||||
},
|
||||
"create": {
|
||||
"error": {
|
||||
@ -82,26 +82,96 @@
|
||||
"settings": {
|
||||
"advance": {
|
||||
"maxTurns": {
|
||||
"description": "Установить количество циклов запрос/ответ, выполняемых автоматически через прокси.",
|
||||
"helper": "Чем выше значение, тем дольше может работать автономно; чем ниже значение, тем легче контролировать.",
|
||||
"label": "Максимальное количество раундов в сеансе"
|
||||
"description": "[to be translated]:设定代理自动执行的请求/回复轮次数。",
|
||||
"helper": "[to be translated]:数值越高可自主运行越久;数值越低更易控制。",
|
||||
"label": "[to be translated]:会话轮次数上限"
|
||||
},
|
||||
"permissionMode": {
|
||||
"description": "Как агент управления обрабатывает ситуации, требующие авторизации.",
|
||||
"label": "Режим разрешений",
|
||||
"description": "[to be translated]:控制代理在需要授权时的处理方式。",
|
||||
"label": "[to be translated]:权限模式",
|
||||
"options": {
|
||||
"acceptEdits": "Автоматически принимать правки",
|
||||
"bypassPermissions": "Пропустить проверку разрешений",
|
||||
"default": "По умолчанию (спросить перед продолжением)",
|
||||
"plan": "Режим планирования (требуется утверждение плана)"
|
||||
"acceptEdits": "[to be translated]:自动接受编辑",
|
||||
"bypassPermissions": "[to be translated]:跳过权限检查",
|
||||
"default": "[to be translated]:默认(继续前询问)",
|
||||
"plan": "[to be translated]:规划模式(需审批计划)"
|
||||
},
|
||||
"placeholder": "Выбрать режим разрешений"
|
||||
"placeholder": "[to be translated]:选择权限模式"
|
||||
},
|
||||
"title": "Расширенные настройки"
|
||||
"title": "[to be translated]:高级设置"
|
||||
},
|
||||
"essential": "Основные настройки",
|
||||
"mcps": "MCP сервер",
|
||||
"prompt": "Настройки подсказки",
|
||||
"tooling": {
|
||||
"mcp": {
|
||||
"description": "[to be translated]:Connect MCP servers to unlock additional tools you can approve above.",
|
||||
"empty": "[to be translated]:No MCP servers detected. Add one from the MCP settings page.",
|
||||
"manageHint": "[to be translated]:Need advanced configuration? Visit Settings → MCP Servers.",
|
||||
"toggle": "[to be translated]:Toggle {{name}}"
|
||||
},
|
||||
"permissionMode": {
|
||||
"acceptEdits": {
|
||||
"behavior": "[to be translated]:Pre-approves trusted filesystem tools so edits run immediately.",
|
||||
"description": "[to be translated]:File edits and filesystem operations are automatically approved.",
|
||||
"title": "[to be translated]:Auto-accept file edits"
|
||||
},
|
||||
"bypassPermissions": {
|
||||
"behavior": "[to be translated]:Every tool is pre-approved automatically.",
|
||||
"description": "[to be translated]:All permission prompts are skipped — use with caution.",
|
||||
"title": "[to be translated]:Bypass permission checks",
|
||||
"warning": "[to be translated]:Use with caution — all tools will run without asking for approval."
|
||||
},
|
||||
"confirmChange": {
|
||||
"description": "[to be translated]:Switching modes updates the automatically approved tools.",
|
||||
"title": "[to be translated]:Change permission mode?"
|
||||
},
|
||||
"default": {
|
||||
"behavior": "[to be translated]:No tools are pre-approved automatically.",
|
||||
"description": "[to be translated]:Normal permission checks apply.",
|
||||
"title": "[to be translated]:Default (ask before continuing)"
|
||||
},
|
||||
"plan": {
|
||||
"behavior": "[to be translated]:Read-only tools only. Execution is disabled.",
|
||||
"description": "[to be translated]:Claude can only use read-only tools and presents a plan before execution.",
|
||||
"title": "[to be translated]:Planning mode (coming soon)"
|
||||
}
|
||||
},
|
||||
"preapproved": {
|
||||
"autoBadge": "[to be translated]:Added by mode",
|
||||
"autoDescription": "[to be translated]:This tool is auto-approved by the current permission mode.",
|
||||
"empty": "[to be translated]:No tools match your filters.",
|
||||
"mcpBadge": "[to be translated]:MCP tool",
|
||||
"requiresApproval": "[to be translated]:Requires approval when disabled",
|
||||
"search": "[to be translated]:Search tools",
|
||||
"toggle": "[to be translated]:Toggle {{name}}",
|
||||
"warning": {
|
||||
"description": "[to be translated]:Enable only tools you trust. Mode defaults are highlighted automatically.",
|
||||
"title": "[to be translated]:Pre-approved tools run without manual review."
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"autoTools": "[to be translated]:Auto: {{count}}",
|
||||
"customTools": "[to be translated]:Custom: {{count}}",
|
||||
"helper": "[to be translated]:Changes save automatically. Adjust the steps above any time to fine-tune permissions.",
|
||||
"mcp": "[to be translated]:MCP: {{count}}",
|
||||
"mode": "[to be translated]:Mode: {{mode}}"
|
||||
},
|
||||
"steps": {
|
||||
"mcp": {
|
||||
"title": "[to be translated]:MCP servers"
|
||||
},
|
||||
"permissionMode": {
|
||||
"title": "[to be translated]:Step 1 · Permission mode"
|
||||
},
|
||||
"preapproved": {
|
||||
"title": "[to be translated]:Step 2 · Pre-approved tools"
|
||||
},
|
||||
"review": {
|
||||
"title": "[to be translated]:Step 3 · Review"
|
||||
}
|
||||
},
|
||||
"tab": "[to be translated]:Tooling & permissions"
|
||||
},
|
||||
"tools": {
|
||||
"approved": "одобрено",
|
||||
"caution": "Предварительно одобренные инструменты обходят проверку человеком. Включайте только доверенные инструменты.",
|
||||
|
||||
@ -1,33 +1,16 @@
|
||||
import { Input, Select, SelectItem, Tooltip } from '@heroui/react'
|
||||
import type { Selection } from '@react-types/shared'
|
||||
import { Input, Tooltip } from '@heroui/react'
|
||||
import {
|
||||
AgentConfiguration,
|
||||
AgentConfigurationSchema,
|
||||
GetAgentResponse,
|
||||
PermissionMode,
|
||||
PermissionModeSchema,
|
||||
UpdateAgentForm
|
||||
} from '@renderer/types'
|
||||
import { Info } from 'lucide-react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
||||
|
||||
const permissionModeKeyMap: Record<PermissionMode, string> = {
|
||||
default: 'agent.settings.advance.permissionMode.options.default',
|
||||
acceptEdits: 'agent.settings.advance.permissionMode.options.acceptEdits',
|
||||
bypassPermissions: 'agent.settings.advance.permissionMode.options.bypassPermissions',
|
||||
plan: 'agent.settings.advance.permissionMode.options.plan'
|
||||
}
|
||||
|
||||
const permissionModeFallback: Record<PermissionMode, string> = {
|
||||
default: 'Default (ask before continuing)',
|
||||
acceptEdits: 'Accept edits automatically',
|
||||
bypassPermissions: 'Bypass permission checks',
|
||||
plan: 'Planning mode (requires plan approval)'
|
||||
}
|
||||
|
||||
type AgentConfigurationState = AgentConfiguration & Record<string, unknown>
|
||||
|
||||
interface AgentAdvanceSettingsProps {
|
||||
@ -53,33 +36,6 @@ export const AgentAdvanceSettings: React.FC<AgentAdvanceSettingsProps> = ({ agen
|
||||
setMaxTurnsInput(String(parsed.max_turns))
|
||||
}, [agent])
|
||||
|
||||
const permissionOptions = useMemo(
|
||||
() =>
|
||||
PermissionModeSchema.options.map((mode) => ({
|
||||
key: mode,
|
||||
label: t(permissionModeKeyMap[mode], permissionModeFallback[mode])
|
||||
})) satisfies { key: PermissionMode; label: string }[],
|
||||
[t]
|
||||
)
|
||||
|
||||
const handlePermissionChange = useCallback(
|
||||
(keys: Selection) => {
|
||||
if (!agent || keys === 'all') return
|
||||
const [first] = Array.from(keys)
|
||||
if (!first) return
|
||||
const nextMode = first as PermissionMode
|
||||
setConfiguration((prev) => {
|
||||
if (prev.permission_mode === nextMode) {
|
||||
return prev
|
||||
}
|
||||
const next = { ...prev, permission_mode: nextMode } as AgentConfigurationState
|
||||
updateAgent({ id: agent.id, configuration: next } satisfies UpdateAgentForm)
|
||||
return next
|
||||
})
|
||||
},
|
||||
[agent, updateAgent]
|
||||
)
|
||||
|
||||
const commitMaxTurns = useCallback(() => {
|
||||
if (!agent) return
|
||||
const parsedValue = Number.parseInt(maxTurnsInput, 10)
|
||||
@ -104,29 +60,6 @@ export const AgentAdvanceSettings: React.FC<AgentAdvanceSettingsProps> = ({ agen
|
||||
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsItem>
|
||||
<SettingsTitle
|
||||
actions={
|
||||
<Tooltip content={t('agent.settings.advance.permissionMode.description')} placement="right">
|
||||
<Info size={16} className="text-foreground-400" />
|
||||
</Tooltip>
|
||||
}>
|
||||
{t('agent.settings.advance.permissionMode.label')}
|
||||
</SettingsTitle>
|
||||
<Select
|
||||
aria-label={t('agent.settings.advance.permissionMode.label')}
|
||||
selectionMode="single"
|
||||
selectedKeys={[configuration.permission_mode]}
|
||||
onSelectionChange={handlePermissionChange}
|
||||
className="max-w-md"
|
||||
placeholder={t('agent.settings.advance.permissionMode.placeholder')}>
|
||||
{permissionOptions.map((option) => (
|
||||
<SelectItem key={option.key} textValue={option.label}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</SettingsItem>
|
||||
<SettingsItem divider={false}>
|
||||
<SettingsTitle
|
||||
actions={
|
||||
|
||||
@ -1,130 +0,0 @@
|
||||
import { Card, CardBody, CardHeader, Switch, Tooltip } from '@heroui/react'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import { GetAgentResponse, UpdateAgentForm } from '@renderer/types'
|
||||
import { Info } from 'lucide-react'
|
||||
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
||||
|
||||
interface AgentMCPSettingsProps {
|
||||
agent: GetAgentResponse | undefined | null
|
||||
updateAgent: (form: UpdateAgentForm) => Promise<void> | void
|
||||
}
|
||||
|
||||
export const AgentMCPSettings: React.FC<AgentMCPSettingsProps> = ({ agent, updateAgent }) => {
|
||||
const { t } = useTranslation()
|
||||
const { mcpServers: allMcpServers } = useMCPServers()
|
||||
const [selectedIds, setSelectedIds] = useState<string[]>([])
|
||||
|
||||
const availableServers = useMemo(() => allMcpServers ?? [], [allMcpServers])
|
||||
|
||||
useEffect(() => {
|
||||
if (!agent) {
|
||||
setSelectedIds([])
|
||||
return
|
||||
}
|
||||
const mcps = agent.mcps ?? []
|
||||
const validIds = mcps.filter((id) => availableServers.some((server) => server.id === id))
|
||||
setSelectedIds((prev) => {
|
||||
if (prev.length === validIds.length && prev.every((id) => validIds.includes(id))) {
|
||||
return prev
|
||||
}
|
||||
return validIds
|
||||
})
|
||||
}, [agent, availableServers])
|
||||
|
||||
const handleToggle = useCallback(
|
||||
(serverId: string, isEnabled: boolean) => {
|
||||
if (!agent) return
|
||||
|
||||
setSelectedIds((prev) => {
|
||||
const exists = prev.includes(serverId)
|
||||
if (isEnabled === exists) {
|
||||
return prev
|
||||
}
|
||||
const next = isEnabled ? [...prev, serverId] : prev.filter((id) => id !== serverId)
|
||||
updateAgent({ id: agent.id, mcps: next })
|
||||
return next
|
||||
})
|
||||
},
|
||||
[agent, updateAgent]
|
||||
)
|
||||
|
||||
const enabledCount = useMemo(() => {
|
||||
const validSelected = selectedIds.filter((id) => availableServers.some((server) => server.id === id))
|
||||
return validSelected.length
|
||||
}, [selectedIds, availableServers])
|
||||
|
||||
const renderServerMeta = useCallback((meta?: ReactNode) => {
|
||||
if (!meta) return null
|
||||
return <span className="text-foreground-400 text-xs">{meta}</span>
|
||||
}, [])
|
||||
|
||||
if (!agent) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsItem divider={false} className="flex-1">
|
||||
<div className="flex h-full flex-col gap-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<SettingsTitle>
|
||||
{t('assistants.settings.mcp.title')}
|
||||
<Tooltip
|
||||
placement="right"
|
||||
content={t('assistants.settings.mcp.description', 'Select MCP servers to use with this agent')}>
|
||||
<Info size={16} className="text-foreground-400" />
|
||||
</Tooltip>
|
||||
</SettingsTitle>
|
||||
{availableServers.length > 0 ? (
|
||||
<span className="text-foreground-500 text-xs">
|
||||
{enabledCount} / {availableServers.length} {t('settings.mcp.active')}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{availableServers.length > 0 ? (
|
||||
<div className="flex flex-1 flex-col gap-3 overflow-auto pr-1">
|
||||
{availableServers.map((server) => {
|
||||
const isSelected = selectedIds.includes(server.id)
|
||||
return (
|
||||
<Card key={server.id} shadow="none" className="border border-default-200">
|
||||
<CardHeader className="flex items-start justify-between gap-3">
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-1">
|
||||
<span className="truncate font-medium text-sm">{server.name}</span>
|
||||
{server.description ? (
|
||||
<span className="line-clamp-2 text-foreground-500 text-xs">{server.description}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<Switch
|
||||
aria-label={t('assistants.settings.mcp.toggle', {
|
||||
defaultValue: `Toggle ${server.name}`
|
||||
})}
|
||||
isSelected={isSelected}
|
||||
isDisabled={!server.isActive}
|
||||
size="sm"
|
||||
onValueChange={(value) => handleToggle(server.id, value)}
|
||||
/>
|
||||
</CardHeader>
|
||||
<CardBody className="gap-1 py-0 pb-3">
|
||||
{renderServerMeta(server.baseUrl)}
|
||||
{renderServerMeta(server.provider)}
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-1 items-center justify-center rounded-medium border border-default-200 border-dashed px-4 py-10 text-foreground-500 text-sm">
|
||||
{t('assistants.settings.mcp.noServersAvailable', 'No MCP servers available')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</SettingsItem>
|
||||
</SettingsContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default AgentMCPSettings
|
||||
@ -1,145 +0,0 @@
|
||||
import { Alert, Card, CardBody, CardHeader, Switch, Tooltip } from '@heroui/react'
|
||||
import { GetAgentResponse, Tool, UpdateAgentForm } from '@renderer/types'
|
||||
import { Info } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
||||
|
||||
interface AgentToolSettingsProps {
|
||||
agent: GetAgentResponse | undefined | null
|
||||
updateAgent: (form: UpdateAgentForm) => Promise<void> | void
|
||||
}
|
||||
|
||||
const isSameSelection = (next: string[], previous: string[]) => {
|
||||
if (next.length !== previous.length) {
|
||||
return false
|
||||
}
|
||||
const previousSet = new Set(previous)
|
||||
return next.every((id) => previousSet.has(id))
|
||||
}
|
||||
|
||||
export const AgentToolSettings: FC<AgentToolSettingsProps> = ({ agent, updateAgent }) => {
|
||||
const { t } = useTranslation()
|
||||
const [approvedIds, setApprovedIds] = useState<string[]>([])
|
||||
|
||||
const availableTools = useMemo<Tool[]>(() => agent?.tools ?? [], [agent?.tools])
|
||||
|
||||
useEffect(() => {
|
||||
if (!agent) {
|
||||
setApprovedIds((prev) => (prev.length === 0 ? prev : []))
|
||||
return
|
||||
}
|
||||
const allowed = agent.allowed_tools ?? []
|
||||
const validIds = allowed.filter((id) => availableTools.some((tool) => tool.id === id))
|
||||
setApprovedIds((prev) => {
|
||||
if (isSameSelection(prev, validIds)) {
|
||||
return prev
|
||||
}
|
||||
return validIds
|
||||
})
|
||||
}, [agent, availableTools])
|
||||
|
||||
const handleToggle = useCallback(
|
||||
(toolId: string, isApproved: boolean) => {
|
||||
if (!agent) return
|
||||
|
||||
setApprovedIds((prev) => {
|
||||
const exists = prev.includes(toolId)
|
||||
if (isApproved === exists) {
|
||||
return prev
|
||||
}
|
||||
const next = isApproved ? [...prev, toolId] : prev.filter((id) => id !== toolId)
|
||||
const previous = agent.allowed_tools ?? []
|
||||
if (!isSameSelection(next, previous)) {
|
||||
updateAgent({ id: agent.id, allowed_tools: next })
|
||||
}
|
||||
return next
|
||||
})
|
||||
},
|
||||
[agent, updateAgent]
|
||||
)
|
||||
|
||||
const approvedCount = useMemo(() => {
|
||||
return approvedIds.filter((id) => availableTools.some((tool) => tool.id === id)).length
|
||||
}, [approvedIds, availableTools])
|
||||
|
||||
if (!agent) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsItem divider={false} className="flex-1">
|
||||
<div className="flex h-full flex-col gap-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<SettingsTitle>
|
||||
{t('agent.settings.tools.title', 'Pre-approved tools')}
|
||||
<Tooltip
|
||||
placement="right"
|
||||
content={t('agent.settings.tools.description', 'Choose which tools can run without manual approval.')}>
|
||||
<Info size={16} className="text-foreground-400" />
|
||||
</Tooltip>
|
||||
</SettingsTitle>
|
||||
{availableTools.length > 0 ? (
|
||||
<span className="text-foreground-500 text-xs">
|
||||
{approvedCount} / {availableTools.length} {t('agent.settings.tools.approved', 'approved')}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Alert
|
||||
color="warning"
|
||||
title={t(
|
||||
'agent.settings.tools.caution',
|
||||
'Pre-approved tools bypass human review. Enable only trusted tools.'
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{availableTools.length > 0 ? (
|
||||
<div className="flex flex-1 flex-col gap-3 overflow-auto pr-1">
|
||||
{availableTools.map((tool) => {
|
||||
const isApproved = approvedIds.includes(tool.id)
|
||||
return (
|
||||
<Card key={tool.id} shadow="none" className="border border-default-200">
|
||||
<CardHeader className="flex items-start justify-between gap-3">
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-1">
|
||||
<span className="truncate font-medium text-sm">{tool.name}</span>
|
||||
{tool.description ? (
|
||||
<span className="line-clamp-2 text-foreground-500 text-xs">{tool.description}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<Switch
|
||||
aria-label={t('agent.settings.tools.toggle', {
|
||||
defaultValue: `Toggle ${tool.name}`
|
||||
})}
|
||||
isSelected={isApproved}
|
||||
size="sm"
|
||||
onValueChange={(value) => handleToggle(tool.id, value)}
|
||||
/>
|
||||
</CardHeader>
|
||||
{tool.requirePermissions ? (
|
||||
<CardBody className="py-0 pb-3">
|
||||
<span className="text-foreground-400 text-xs">
|
||||
{t('agent.settings.tools.requiresPermission', 'Requires permission when not pre-approved.')}
|
||||
</span>
|
||||
</CardBody>
|
||||
) : null}
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-1 items-center justify-center rounded-medium border border-default-200 border-dashed px-4 py-10 text-foreground-500 text-sm">
|
||||
{t('agent.session.allowed_tools.empty')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</SettingsItem>
|
||||
</SettingsContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default AgentToolSettings
|
||||
@ -0,0 +1,541 @@
|
||||
import { Alert, Card, CardBody, CardHeader, Chip, Input, Switch } from '@heroui/react'
|
||||
import { useAgentClient } from '@renderer/hooks/agents/useAgentClient'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import {
|
||||
AgentConfiguration,
|
||||
AgentConfigurationSchema,
|
||||
GetAgentResponse,
|
||||
PermissionMode,
|
||||
Tool,
|
||||
UpdateAgentForm
|
||||
} from '@renderer/types'
|
||||
import { Modal } from 'antd'
|
||||
import { ShieldAlert, ShieldCheck, Wrench } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { mutate } from 'swr'
|
||||
|
||||
import { SettingsContainer, SettingsItem, SettingsTitle } from './shared'
|
||||
|
||||
interface AgentToolingSettingsProps {
|
||||
agent: GetAgentResponse | undefined | null
|
||||
updateAgent: (form: UpdateAgentForm) => Promise<void> | void
|
||||
}
|
||||
|
||||
type AgentConfigurationState = AgentConfiguration & Record<string, unknown>
|
||||
|
||||
type PermissionModeCard = {
|
||||
mode: PermissionMode
|
||||
titleKey: string
|
||||
titleFallback: string
|
||||
descriptionKey: string
|
||||
descriptionFallback: string
|
||||
behaviorKey: string
|
||||
behaviorFallback: string
|
||||
caution?: boolean
|
||||
unsupported?: boolean
|
||||
}
|
||||
|
||||
const defaultConfiguration = AgentConfigurationSchema.parse({}) as AgentConfigurationState
|
||||
|
||||
const permissionModeCards: PermissionModeCard[] = [
|
||||
{
|
||||
mode: 'default',
|
||||
titleKey: 'agent.settings.tooling.permissionMode.default.title',
|
||||
titleFallback: 'Default (ask before continuing)',
|
||||
descriptionKey: 'agent.settings.tooling.permissionMode.default.description',
|
||||
descriptionFallback: 'Read-only tools are pre-approved; everything else still needs permission.',
|
||||
behaviorKey: 'agent.settings.tooling.permissionMode.default.behavior',
|
||||
behaviorFallback: 'Read-only tools are pre-approved automatically.'
|
||||
},
|
||||
{
|
||||
mode: 'plan',
|
||||
titleKey: 'agent.settings.tooling.permissionMode.plan.title',
|
||||
titleFallback: 'Planning mode',
|
||||
descriptionKey: 'agent.settings.tooling.permissionMode.plan.description',
|
||||
descriptionFallback: 'Shares the default read-only tool set but presents a plan before execution.',
|
||||
behaviorKey: 'agent.settings.tooling.permissionMode.plan.behavior',
|
||||
behaviorFallback: 'Read-only defaults are pre-approved while execution remains disabled.'
|
||||
},
|
||||
{
|
||||
mode: 'acceptEdits',
|
||||
titleKey: 'agent.settings.tooling.permissionMode.acceptEdits.title',
|
||||
titleFallback: 'Auto-accept file edits',
|
||||
descriptionKey: 'agent.settings.tooling.permissionMode.acceptEdits.description',
|
||||
descriptionFallback: 'File edits and filesystem operations are automatically approved.',
|
||||
behaviorKey: 'agent.settings.tooling.permissionMode.acceptEdits.behavior',
|
||||
behaviorFallback: 'Pre-approves trusted filesystem tools so edits run immediately.'
|
||||
},
|
||||
{
|
||||
mode: 'bypassPermissions',
|
||||
titleKey: 'agent.settings.tooling.permissionMode.bypassPermissions.title',
|
||||
titleFallback: 'Bypass permission checks',
|
||||
descriptionKey: 'agent.settings.tooling.permissionMode.bypassPermissions.description',
|
||||
descriptionFallback: 'All permission prompts are skipped — use with caution.',
|
||||
behaviorKey: 'agent.settings.tooling.permissionMode.bypassPermissions.behavior',
|
||||
behaviorFallback: 'Every tool is pre-approved automatically.',
|
||||
caution: true
|
||||
}
|
||||
]
|
||||
|
||||
const computeModeDefaults = (mode: PermissionMode, tools: Tool[]): string[] => {
|
||||
const defaultToolIds = tools.filter((tool) => !tool.requirePermissions).map((tool) => tool.id)
|
||||
switch (mode) {
|
||||
case 'acceptEdits':
|
||||
return [
|
||||
...defaultToolIds,
|
||||
'Edit',
|
||||
'MultiEdit',
|
||||
'NotebookEdit',
|
||||
'Write',
|
||||
'Bash(mkdir:*)',
|
||||
'Bash(touch:*)',
|
||||
'Bash(rm:*)',
|
||||
'Bash(mv:*)',
|
||||
'Bash(cp:*)'
|
||||
]
|
||||
case 'bypassPermissions':
|
||||
return tools.map((tool) => tool.id)
|
||||
case 'default':
|
||||
case 'plan':
|
||||
return defaultToolIds
|
||||
}
|
||||
}
|
||||
|
||||
const unique = (values: string[]) => Array.from(new Set(values))
|
||||
|
||||
export const AgentToolingSettings: FC<AgentToolingSettingsProps> = ({ agent, updateAgent }) => {
|
||||
const { t } = useTranslation()
|
||||
const client = useAgentClient()
|
||||
const { mcpServers: allServers } = useMCPServers()
|
||||
|
||||
const [configuration, setConfiguration] = useState<AgentConfigurationState>(defaultConfiguration)
|
||||
const [selectedMode, setSelectedMode] = useState<PermissionMode>(defaultConfiguration.permission_mode)
|
||||
const [autoToolIds, setAutoToolIds] = useState<string[]>([])
|
||||
const [approvedToolIds, setApprovedToolIds] = useState<string[]>([])
|
||||
const [searchTerm, setSearchTerm] = useState('')
|
||||
const [isUpdatingMode, setIsUpdatingMode] = useState(false)
|
||||
const [isUpdatingTools, setIsUpdatingTools] = useState(false)
|
||||
const [selectedMcpIds, setSelectedMcpIds] = useState<string[]>([])
|
||||
const [isUpdatingMcp, setIsUpdatingMcp] = useState(false)
|
||||
|
||||
const availableTools = useMemo(() => agent?.tools ?? [], [agent?.tools])
|
||||
const availableServers = useMemo(() => allServers ?? [], [allServers])
|
||||
|
||||
useEffect(() => {
|
||||
if (!agent) {
|
||||
setConfiguration(defaultConfiguration)
|
||||
setSelectedMode(defaultConfiguration.permission_mode)
|
||||
setApprovedToolIds([])
|
||||
setAutoToolIds([])
|
||||
setSelectedMcpIds([])
|
||||
return
|
||||
}
|
||||
const parsed = AgentConfigurationSchema.parse(agent.configuration ?? {}) as AgentConfigurationState
|
||||
setConfiguration(parsed)
|
||||
setSelectedMode(parsed.permission_mode)
|
||||
|
||||
const defaults = computeModeDefaults(parsed.permission_mode, availableTools)
|
||||
setAutoToolIds(defaults)
|
||||
const allowed = agent.allowed_tools ?? []
|
||||
setApprovedToolIds((prev) => {
|
||||
const sanitized = allowed.filter((id) => availableTools.some((tool) => tool.id === id))
|
||||
const isSame = sanitized.length === prev.length && sanitized.every((id) => prev.includes(id))
|
||||
if (isSame) {
|
||||
return prev
|
||||
}
|
||||
// Ensure defaults are included even if backend omitted them
|
||||
const merged = unique([...sanitized, ...defaults])
|
||||
return merged
|
||||
})
|
||||
setSelectedMcpIds(agent.mcps ?? [])
|
||||
}, [agent, availableTools])
|
||||
|
||||
const filteredTools = useMemo(() => {
|
||||
if (!searchTerm.trim()) {
|
||||
return availableTools
|
||||
}
|
||||
const term = searchTerm.trim().toLowerCase()
|
||||
return availableTools.filter((tool) => {
|
||||
return (
|
||||
tool.name.toLowerCase().includes(term) ||
|
||||
(tool.description ? tool.description.toLowerCase().includes(term) : false)
|
||||
)
|
||||
})
|
||||
}, [availableTools, searchTerm])
|
||||
|
||||
const userAddedIds = useMemo(() => {
|
||||
return approvedToolIds.filter((id) => !autoToolIds.includes(id))
|
||||
}, [approvedToolIds, autoToolIds])
|
||||
|
||||
const handleSelectPermissionMode = useCallback(
|
||||
(nextMode: PermissionMode) => {
|
||||
if (!agent || nextMode === selectedMode || isUpdatingMode) {
|
||||
return
|
||||
}
|
||||
const defaults = computeModeDefaults(nextMode, availableTools)
|
||||
const merged = unique([...defaults, ...userAddedIds])
|
||||
const removedDefaults = autoToolIds.filter((id) => !defaults.includes(id))
|
||||
|
||||
const applyChange = async () => {
|
||||
setIsUpdatingMode(true)
|
||||
try {
|
||||
const nextConfiguration = { ...configuration, permission_mode: nextMode } satisfies AgentConfigurationState
|
||||
await updateAgent({ id: agent.id, configuration: nextConfiguration, allowed_tools: merged })
|
||||
setConfiguration(nextConfiguration)
|
||||
setSelectedMode(nextMode)
|
||||
setAutoToolIds(defaults)
|
||||
setApprovedToolIds(merged)
|
||||
} finally {
|
||||
setIsUpdatingMode(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (removedDefaults.length > 0) {
|
||||
Modal.confirm({
|
||||
title: t('agent.settings.tooling.permissionMode.confirmChange.title', 'Change permission mode?'),
|
||||
content: (
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-foreground-500 text-sm">
|
||||
{t(
|
||||
'agent.settings.tooling.permissionMode.confirmChange.description',
|
||||
'Switching modes updates the automatically approved tools.'
|
||||
)}
|
||||
</p>
|
||||
<div className="rounded-medium border border-default-200 bg-default-50 px-3 py-2 text-sm">
|
||||
<span className="font-medium text-foreground">{t('common.removed', 'Removed')}:</span>
|
||||
<ul className="mt-1 list-disc pl-4">
|
||||
{removedDefaults.map((id) => {
|
||||
const tool = availableTools.find((item) => item.id === id)
|
||||
return <li key={id}>{tool?.name ?? id}</li>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
okText: t('common.confirm'),
|
||||
cancelText: t('common.cancel'),
|
||||
onOk: applyChange
|
||||
})
|
||||
} else {
|
||||
void applyChange()
|
||||
}
|
||||
},
|
||||
[agent, selectedMode, isUpdatingMode, availableTools, userAddedIds, autoToolIds, configuration, updateAgent, t]
|
||||
)
|
||||
|
||||
const handleToggleTool = useCallback(
|
||||
(toolId: string, isApproved: boolean) => {
|
||||
if (!agent || isUpdatingTools) {
|
||||
return
|
||||
}
|
||||
setApprovedToolIds((prev) => {
|
||||
const exists = prev.includes(toolId)
|
||||
if (isApproved === exists) {
|
||||
return prev
|
||||
}
|
||||
const next = isApproved ? [...prev, toolId] : prev.filter((id) => id !== toolId)
|
||||
const sanitized = unique(next.filter((id) => availableTools.some((tool) => tool.id === id)).concat(autoToolIds))
|
||||
setIsUpdatingTools(true)
|
||||
void (async () => {
|
||||
try {
|
||||
await updateAgent({ id: agent.id, allowed_tools: sanitized })
|
||||
} finally {
|
||||
setIsUpdatingTools(false)
|
||||
}
|
||||
})()
|
||||
return sanitized
|
||||
})
|
||||
},
|
||||
[agent, isUpdatingTools, availableTools, autoToolIds, updateAgent]
|
||||
)
|
||||
|
||||
const { agentSummary, autoCount, customCount } = useMemo(() => {
|
||||
const autoCountValue = autoToolIds.length
|
||||
const customCountValue = userAddedIds.length
|
||||
return {
|
||||
agentSummary: {
|
||||
mode: selectedMode,
|
||||
auto: autoCountValue,
|
||||
custom: customCountValue,
|
||||
totalTools: availableTools.length,
|
||||
mcps: selectedMcpIds.length
|
||||
},
|
||||
autoCount: autoCountValue,
|
||||
customCount: customCountValue
|
||||
}
|
||||
}, [selectedMode, autoToolIds, userAddedIds, availableTools.length, selectedMcpIds.length])
|
||||
|
||||
const handleToggleMcp = useCallback(
|
||||
(serverId: string, enabled: boolean) => {
|
||||
if (!agent || isUpdatingMcp) {
|
||||
return
|
||||
}
|
||||
setSelectedMcpIds((prev) => {
|
||||
const exists = prev.includes(serverId)
|
||||
if (enabled === exists) {
|
||||
return prev
|
||||
}
|
||||
const next = enabled ? [...prev, serverId] : prev.filter((id) => id !== serverId)
|
||||
setIsUpdatingMcp(true)
|
||||
void (async () => {
|
||||
try {
|
||||
await updateAgent({ id: agent.id, mcps: next })
|
||||
const refreshed = await client.getAgent(agent.id)
|
||||
const key = client.agentPaths.withId(agent.id)
|
||||
mutate(key, refreshed, false)
|
||||
} finally {
|
||||
setIsUpdatingMcp(false)
|
||||
}
|
||||
})()
|
||||
return next
|
||||
})
|
||||
},
|
||||
[agent, isUpdatingMcp, client, updateAgent]
|
||||
)
|
||||
|
||||
if (!agent) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsItem>
|
||||
<SettingsTitle>
|
||||
{t('agent.settings.tooling.steps.permissionMode.title', 'Step 1 · Permission mode')}
|
||||
</SettingsTitle>
|
||||
<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
|
||||
{permissionModeCards.map((card) => {
|
||||
const isSelected = card.mode === selectedMode
|
||||
const disabled = card.unsupported
|
||||
const showCaution = card.caution
|
||||
return (
|
||||
<Card
|
||||
key={card.mode}
|
||||
isPressable={!disabled}
|
||||
isDisabled={disabled || isUpdatingMode}
|
||||
onPress={() => handleSelectPermissionMode(card.mode)}
|
||||
className={`border ${
|
||||
isSelected ? 'border-primary shadow-lg' : 'border-default-200'
|
||||
} ${disabled ? 'opacity-60' : ''}`}>
|
||||
<CardHeader className="flex items-start justify-between gap-2">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-left font-semibold text-sm">{t(card.titleKey, card.titleFallback)}</span>
|
||||
<span className="text-left text-foreground-500 text-xs">
|
||||
{t(card.descriptionKey, card.descriptionFallback)}
|
||||
</span>
|
||||
</div>
|
||||
{disabled ? (
|
||||
<Chip color="warning" size="sm" variant="flat">
|
||||
{t('common.coming_soon', 'Coming soon')}
|
||||
</Chip>
|
||||
) : isSelected ? (
|
||||
<Chip color="primary" size="sm" variant="flat" startContent={<ShieldCheck size={14} />}>
|
||||
{t('common.selected', 'Selected')}
|
||||
</Chip>
|
||||
) : null}
|
||||
</CardHeader>
|
||||
<CardBody className="gap-2 text-left text-xs">
|
||||
<span className="text-foreground-600">{t(card.behaviorKey, card.behaviorFallback)}</span>
|
||||
{showCaution ? (
|
||||
<span className="flex items-center gap-1 text-danger-600">
|
||||
<ShieldAlert size={14} />
|
||||
{t(
|
||||
'agent.settings.tooling.permissionMode.bypassPermissions.warning',
|
||||
'Use with caution — all tools will run without asking for approval.'
|
||||
)}
|
||||
</span>
|
||||
) : null}
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem>
|
||||
<SettingsTitle>
|
||||
{t('agent.settings.tooling.steps.preapproved.title', 'Step 2 · Pre-approved tools')}
|
||||
</SettingsTitle>
|
||||
<div className="flex flex-col gap-4">
|
||||
<Alert
|
||||
color="warning"
|
||||
title={t(
|
||||
'agent.settings.tooling.preapproved.warning.title',
|
||||
'Pre-approved tools run without manual review.'
|
||||
)}
|
||||
description={t(
|
||||
'agent.settings.tooling.preapproved.warning.description',
|
||||
'Enable only tools you trust. Mode defaults are highlighted automatically.'
|
||||
)}
|
||||
/>
|
||||
<Input
|
||||
isClearable
|
||||
value={searchTerm}
|
||||
onValueChange={setSearchTerm}
|
||||
placeholder={t('agent.settings.tooling.preapproved.search', 'Search tools')}
|
||||
aria-label={t('agent.settings.tooling.preapproved.search', 'Search tools')}
|
||||
className="max-w-md"
|
||||
/>
|
||||
<div className="flex flex-col gap-3">
|
||||
{filteredTools.length === 0 ? (
|
||||
<div className="rounded-medium border border-default-200 border-dashed px-4 py-10 text-center text-foreground-500 text-sm">
|
||||
{t('agent.settings.tooling.preapproved.empty', 'No tools match your filters.')}
|
||||
</div>
|
||||
) : (
|
||||
filteredTools.map((tool) => {
|
||||
const isAuto = autoToolIds.includes(tool.id)
|
||||
const isApproved = approvedToolIds.includes(tool.id)
|
||||
return (
|
||||
<Card key={tool.id} shadow="none" className="border border-default-200">
|
||||
<CardHeader className="flex items-start justify-between gap-3">
|
||||
<div className="flex min-w-0 flex-col gap-1">
|
||||
<span className="truncate font-medium text-sm">{tool.name}</span>
|
||||
{tool.description ? (
|
||||
<span className="line-clamp-2 text-foreground-500 text-xs">{tool.description}</span>
|
||||
) : null}
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{isAuto ? (
|
||||
<Chip size="sm" color="primary" variant="flat">
|
||||
{t('agent.settings.tooling.preapproved.autoBadge', 'Added by mode')}
|
||||
</Chip>
|
||||
) : null}
|
||||
{tool.type === 'mcp' ? (
|
||||
<Chip size="sm" color="secondary" variant="flat">
|
||||
{t('agent.settings.tooling.preapproved.mcpBadge', 'MCP tool')}
|
||||
</Chip>
|
||||
) : null}
|
||||
{tool.requirePermissions ? (
|
||||
<Chip size="sm" color="warning" variant="flat">
|
||||
{t(
|
||||
'agent.settings.tooling.preapproved.requiresApproval',
|
||||
'Requires approval when disabled'
|
||||
)}
|
||||
</Chip>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
aria-label={t('agent.settings.tooling.preapproved.toggle', {
|
||||
defaultValue: `Toggle ${tool.name}`,
|
||||
name: tool.name
|
||||
})}
|
||||
isSelected={isApproved}
|
||||
isDisabled={isAuto || isUpdatingTools}
|
||||
size="sm"
|
||||
onValueChange={(value) => handleToggleTool(tool.id, value)}
|
||||
/>
|
||||
</CardHeader>
|
||||
{isAuto ? (
|
||||
<CardBody className="py-0 pb-3">
|
||||
<span className="text-foreground-400 text-xs">
|
||||
{t(
|
||||
'agent.settings.tooling.preapproved.autoDescription',
|
||||
'This tool is auto-approved by the current permission mode.'
|
||||
)}
|
||||
</span>
|
||||
</CardBody>
|
||||
) : null}
|
||||
</Card>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem>
|
||||
<SettingsTitle>{t('agent.settings.tooling.steps.mcp.title', 'MCP servers')}</SettingsTitle>
|
||||
<div className="flex flex-col gap-3">
|
||||
<span className="text-foreground-500 text-sm">
|
||||
{t(
|
||||
'agent.settings.tooling.mcp.description',
|
||||
'Connect MCP servers to unlock additional tools you can approve above.'
|
||||
)}
|
||||
</span>
|
||||
{availableServers.length === 0 ? (
|
||||
<div className="rounded-medium border border-default-200 border-dashed px-4 py-6 text-center text-foreground-500 text-sm">
|
||||
{t('agent.settings.tooling.mcp.empty', 'No MCP servers detected. Add one from the MCP settings page.')}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-2">
|
||||
{availableServers.map((server) => {
|
||||
const isSelected = selectedMcpIds.includes(server.id)
|
||||
return (
|
||||
<Card key={server.id} shadow="none" className="border border-default-200">
|
||||
<CardHeader className="flex items-center justify-between gap-2">
|
||||
<div className="flex min-w-0 flex-col">
|
||||
<span className="truncate font-medium text-sm">{server.name}</span>
|
||||
{server.description ? (
|
||||
<span className="line-clamp-2 text-foreground-500 text-xs">{server.description}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<Switch
|
||||
aria-label={t('agent.settings.tooling.mcp.toggle', {
|
||||
defaultValue: `Toggle ${server.name}`,
|
||||
name: server.name
|
||||
})}
|
||||
isSelected={isSelected}
|
||||
size="sm"
|
||||
isDisabled={!server.isActive || isUpdatingMcp}
|
||||
onValueChange={(value) => handleToggleMcp(server.id, value)}
|
||||
/>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-2 text-foreground-500 text-xs">
|
||||
<Wrench size={14} />
|
||||
<span>
|
||||
{t('agent.settings.tooling.mcp.manageHint', 'Need advanced configuration? Visit Settings → MCP Servers.')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem divider={false}>
|
||||
<SettingsTitle>{t('agent.settings.tooling.steps.review.title', 'Step 3 · Review')}</SettingsTitle>
|
||||
<Card shadow="none" className="border border-default-200">
|
||||
<CardBody className="flex flex-col gap-2 text-sm">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Chip variant="flat" color="primary">
|
||||
{t('agent.settings.tooling.review.mode', {
|
||||
defaultValue: `Mode: ${selectedMode}`,
|
||||
mode: selectedMode
|
||||
})}
|
||||
</Chip>
|
||||
<Chip variant="flat" color="secondary">
|
||||
{t('agent.settings.tooling.review.autoTools', {
|
||||
defaultValue: `Auto: ${autoCount}`,
|
||||
count: autoCount
|
||||
})}
|
||||
</Chip>
|
||||
<Chip variant="flat" color="success">
|
||||
{t('agent.settings.tooling.review.customTools', {
|
||||
defaultValue: `Custom: ${customCount}`,
|
||||
count: customCount
|
||||
})}
|
||||
</Chip>
|
||||
<Chip variant="flat" color="warning">
|
||||
{t('agent.settings.tooling.review.mcp', {
|
||||
defaultValue: `MCP: ${agentSummary.mcps}`,
|
||||
count: agentSummary.mcps
|
||||
})}
|
||||
</Chip>
|
||||
</div>
|
||||
<span className="text-foreground-500 text-xs">
|
||||
{t(
|
||||
'agent.settings.tooling.review.helper',
|
||||
'Changes save automatically. Adjust the steps above any time to fine-tune permissions.'
|
||||
)}
|
||||
</span>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</SettingsItem>
|
||||
</SettingsContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default AgentToolingSettings
|
||||
@ -9,9 +9,8 @@ import styled from 'styled-components'
|
||||
|
||||
import AgentAdvanceSettings from './AgentAdvanceSettings'
|
||||
import AgentEssentialSettings from './AgentEssentialSettings'
|
||||
import AgentMCPSettings from './AgentMCPSettings'
|
||||
import AgentPromptSettings from './AgentPromptSettings'
|
||||
import AgentToolSettings from './AgentToolSettings'
|
||||
import AgentToolingSettings from './AgentToolingSettings'
|
||||
import { AgentLabel } from './shared'
|
||||
|
||||
interface AgentSettingPopupShowParams {
|
||||
@ -23,7 +22,7 @@ interface AgentSettingPopupParams extends AgentSettingPopupShowParams {
|
||||
resolve: () => void
|
||||
}
|
||||
|
||||
type AgentSettingPopupTab = 'essential' | 'prompt' | 'tools' | 'mcps' | 'advance' | 'session-mcps'
|
||||
type AgentSettingPopupTab = 'essential' | 'prompt' | 'tooling' | 'advance' | 'session-mcps'
|
||||
|
||||
const AgentSettingPopupContainer: React.FC<AgentSettingPopupParams> = ({ tab, agentId, resolve }) => {
|
||||
const [open, setOpen] = useState(true)
|
||||
@ -56,12 +55,8 @@ const AgentSettingPopupContainer: React.FC<AgentSettingPopupParams> = ({ tab, ag
|
||||
label: t('agent.settings.prompt')
|
||||
},
|
||||
{
|
||||
key: 'tools',
|
||||
label: t('agent.settings.tools.tab', 'Pre-approved tools')
|
||||
},
|
||||
{
|
||||
key: 'mcps',
|
||||
label: t('agent.settings.mcps', 'MCP Servers')
|
||||
key: 'tooling',
|
||||
label: t('agent.settings.tooling.tab', 'Tooling & permissions')
|
||||
},
|
||||
{
|
||||
key: 'advance',
|
||||
@ -96,8 +91,7 @@ const AgentSettingPopupContainer: React.FC<AgentSettingPopupParams> = ({ tab, ag
|
||||
<Settings>
|
||||
{menu === 'essential' && <AgentEssentialSettings agent={agent} update={updateAgent} />}
|
||||
{menu === 'prompt' && <AgentPromptSettings agent={agent} update={updateAgent} />}
|
||||
{menu === 'tools' && <AgentToolSettings agent={agent} updateAgent={updateAgent} />}
|
||||
{menu === 'mcps' && <AgentMCPSettings agent={agent} updateAgent={updateAgent} />}
|
||||
{menu === 'tooling' && <AgentToolingSettings agent={agent} updateAgent={updateAgent} />}
|
||||
{menu === 'advance' && <AgentAdvanceSettings agent={agent} updateAgent={updateAgent} />}
|
||||
</Settings>
|
||||
</div>
|
||||
|
||||
@ -45,6 +45,7 @@ export type Tool = z.infer<typeof ToolSchema>
|
||||
// ------------------ Agent configuration & base schema ------------------
|
||||
export const AgentConfigurationSchema = z
|
||||
.object({
|
||||
// https://docs.claude.com/en/docs/claude-code/sdk/sdk-permissions#mode-specific-behaviors
|
||||
permission_mode: PermissionModeSchema.default('default'), // Permission mode, default to 'default'
|
||||
max_turns: z.number().default(10) // Maximum number of interaction turns, default to 10
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user