feat: add default permission mode + rename accept→edit
- Add "default" permission mode: no flags passed to CC, uses its own built-in default (asks about everything). Now the system default. - Rename "accept" alias to "edit" (acceptEdits) for clarity - Remove "skip" alias (duplicate of "bypass") - Update all help text, error messages, tests, and LLM prompts Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9c04d47c8e
commit
b707fa84f9
@ -18,12 +18,13 @@ def strip_ansi(text: str) -> str:
|
||||
|
||||
|
||||
PERMISSION_MODE_FLAGS: dict[str, list[str]] = {
|
||||
"bypassPermissions": ["--dangerously-skip-permissions"],
|
||||
"default": [], # CC's own default: asks about everything
|
||||
"acceptEdits": ["--permission-mode", "acceptEdits"],
|
||||
"plan": ["--permission-mode", "plan"],
|
||||
"bypassPermissions": ["--dangerously-skip-permissions"],
|
||||
}
|
||||
VALID_PERMISSION_MODES = list(PERMISSION_MODE_FLAGS)
|
||||
DEFAULT_PERMISSION_MODE = "bypassPermissions"
|
||||
DEFAULT_PERMISSION_MODE = "default"
|
||||
|
||||
|
||||
async def run_claude(
|
||||
|
||||
@ -20,14 +20,15 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# Permission mode aliases (user-facing shorthand → internal CC mode)
|
||||
_PERM_ALIASES: dict[str, str] = {
|
||||
"bypass": "bypassPermissions",
|
||||
"skip": "bypassPermissions",
|
||||
"accept": "acceptEdits",
|
||||
"plan": "plan",
|
||||
"bypass": "bypassPermissions",
|
||||
"default": "default",
|
||||
"edit": "acceptEdits",
|
||||
"plan": "plan",
|
||||
}
|
||||
_PERM_LABELS: dict[str, str] = {
|
||||
"default": "default",
|
||||
"bypassPermissions": "bypass",
|
||||
"acceptEdits": "accept",
|
||||
"acceptEdits": "edit",
|
||||
"plan": "plan",
|
||||
}
|
||||
|
||||
@ -113,14 +114,14 @@ async def handle_command(user_id: str, text: str) -> Optional[str]:
|
||||
async def _cmd_new(user_id: str, args: str) -> str:
|
||||
"""Create a new session."""
|
||||
if not args:
|
||||
return "Usage: /new <project_dir> [initial_message] [--timeout N] [--perm MODE]\nModes: bypass (default), accept, plan"
|
||||
return "Usage: /new <project_dir> [initial_message] [--timeout N] [--perm MODE]\nModes: default, edit, plan, bypass"
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("working_dir", nargs="?", help="Project directory")
|
||||
parser.add_argument("rest", nargs="*", help="Initial message")
|
||||
parser.add_argument("--timeout", type=int, default=None, help="CC timeout in seconds")
|
||||
parser.add_argument("--idle", type=int, default=None, help="Idle timeout in seconds")
|
||||
parser.add_argument("--perm", default=None, help="Permission mode: bypass, accept, plan")
|
||||
parser.add_argument("--perm", default=None, help="Permission mode: default, edit, plan, bypass")
|
||||
|
||||
try:
|
||||
parsed = parser.parse_args(args.split())
|
||||
@ -132,7 +133,7 @@ async def _cmd_new(user_id: str, args: str) -> str:
|
||||
|
||||
permission_mode = _resolve_perm(parsed.perm) if parsed.perm else DEFAULT_PERMISSION_MODE
|
||||
if permission_mode is None:
|
||||
return f"Invalid --perm. Valid modes: bypass, accept, plan"
|
||||
return f"Invalid --perm. Valid modes: default, edit, plan, bypass"
|
||||
|
||||
working_dir = parsed.working_dir
|
||||
initial_msg = " ".join(parsed.rest) if parsed.rest else None
|
||||
@ -288,10 +289,11 @@ async def _cmd_perm(user_id: str, args: str) -> str:
|
||||
if not parts:
|
||||
return (
|
||||
"Usage: /perm <mode> [conv_id]\n"
|
||||
"Modes: bypass (default), accept, plan\n"
|
||||
" bypass — skip all permission checks\n"
|
||||
" accept — auto-accept file edits, confirm shell commands\n"
|
||||
" plan — plan only, no writes"
|
||||
"Modes: default, edit, plan, bypass\n"
|
||||
" default — default mode\n"
|
||||
" edit — auto-accept file edits, confirm shell commands\n"
|
||||
" plan — plan only, no writes\n"
|
||||
" bypass — skip all permission checks"
|
||||
)
|
||||
|
||||
alias = parts[0]
|
||||
@ -299,7 +301,7 @@ async def _cmd_perm(user_id: str, args: str) -> str:
|
||||
|
||||
permission_mode = _resolve_perm(alias)
|
||||
if permission_mode is None:
|
||||
return f"Unknown mode '{alias}'. Valid: bypass, accept, plan"
|
||||
return f"Unknown mode '{alias}'. Valid: default, edit, plan, bypass"
|
||||
|
||||
if not conv_id:
|
||||
return "No active session. Use `//perm <mode> <conv_id>` or activate a session first."
|
||||
@ -442,7 +444,7 @@ def _cmd_help() -> str:
|
||||
{P}status - Show sessions and current mode
|
||||
{P}close [n] - Close session (active or by number)
|
||||
{P}switch <n> - Switch to session by number
|
||||
{P}perm <mode> [conv_id] - Set permission mode (bypass/accept/plan)
|
||||
{P}perm <mode> [conv_id] - Set permission mode (default/edit/plan/bypass)
|
||||
{P}direct - Direct mode: messages → Claude Code (no LLM overhead)
|
||||
{P}smart - Smart mode: messages → LLM routing (default)
|
||||
{P}shell <cmd> - Run shell command (bypasses LLM)
|
||||
@ -454,9 +456,10 @@ def _cmd_help() -> str:
|
||||
{P}help - Show this help
|
||||
|
||||
**Permission modes** (used by {P}perm and {P}new --perm):
|
||||
bypass — 跳过所有权限确认,CC 自动执行一切操作(默认)
|
||||
适合:受信任的沙盒环境、自动化任务
|
||||
accept — 自动接受文件编辑,但 shell 命令仍需手动确认
|
||||
default — 默认模式,遇到文件编辑操作时手动确认
|
||||
edit — 自动接受文件编辑,但 shell 命令仍需手动确认
|
||||
适合:日常开发,需要对命令执行保持控制
|
||||
plan — 只规划、不执行任何写操作
|
||||
适合:先预览 CC 的操作计划再决定是否执行"""
|
||||
适合:先预览 CC 的操作计划再决定是否执行
|
||||
bypass — 跳过所有权限确认,CC 自动执行一切操作
|
||||
适合:受信任的沙盒环境、自动化任务"""
|
||||
@ -53,10 +53,10 @@ Bot command prefix: {prefix}
|
||||
- Any other command the user would type manually
|
||||
|
||||
Available bot commands (pass verbatim to run_command):
|
||||
{prefix}new <dir> [msg] [--perm bypass|accept|plan] — create session
|
||||
{prefix}new <dir> [msg] [--perm default|edit|plan|bypass] — create session
|
||||
{prefix}close [n|conv_id] — close session
|
||||
{prefix}switch <n> — switch active session
|
||||
{prefix}perm <mode> [conv_id] — permission mode: bypass (default), accept, plan
|
||||
{prefix}perm <mode> [conv_id] — permission mode: default, edit, plan, bypass
|
||||
{prefix}direct — direct mode (bypass LLM for CC messages)
|
||||
{prefix}smart — smart mode (LLM routing, default)
|
||||
{prefix}status — list sessions
|
||||
|
||||
@ -720,7 +720,7 @@ class RunCommandInput(BaseModel):
|
||||
command: str = Field(
|
||||
...,
|
||||
description=(
|
||||
"A bot slash command to execute (e.g. '/perm accept', '/close 1', '/switch 2'). "
|
||||
"A bot slash command to execute (e.g. '//perm edit', '//close 1', '//switch 2'). "
|
||||
"This runs bot control commands — NOT shell commands on the host machine. "
|
||||
"Use run_shell for host shell commands (git, ls, etc.)."
|
||||
),
|
||||
@ -732,7 +732,7 @@ class RunCommandTool(BaseTool):
|
||||
description: str = (
|
||||
"Execute a PhoneWork bot slash command on behalf of the user. "
|
||||
"Use this to control sessions, switch modes, change permissions, etc. "
|
||||
"Examples: '/perm accept', '/close 1', '/switch 2', '/direct', '/smart', '/status'. "
|
||||
"Examples: '/perm edit', '/close 1', '/switch 2', '/direct', '/smart', '/status'. "
|
||||
"Do NOT use this for shell commands — use run_shell for those."
|
||||
)
|
||||
args_schema: Type[BaseModel] = RunCommandInput
|
||||
|
||||
@ -7,14 +7,14 @@ Feature: /perm command — change session permission mode
|
||||
When user sends "/perm"
|
||||
Then reply contains "Usage"
|
||||
And reply contains "bypass"
|
||||
And reply contains "accept"
|
||||
And reply contains "edit"
|
||||
And reply contains "plan"
|
||||
|
||||
Scenario: Set active session to accept mode
|
||||
Scenario: Set active session to edit mode
|
||||
Given user has session "sess01" in "/tmp/proj1"
|
||||
And active session is "sess01"
|
||||
When user sends "/perm accept"
|
||||
Then reply contains "accept"
|
||||
When user sends "/perm edit"
|
||||
Then reply contains "edit"
|
||||
And reply contains "sess01"
|
||||
And session "sess01" has permission mode "acceptEdits"
|
||||
|
||||
@ -40,7 +40,7 @@ Feature: /perm command — change session permission mode
|
||||
|
||||
Scenario: No active session returns error
|
||||
Given no active session for user "user_abc123"
|
||||
When user sends "/perm accept"
|
||||
When user sends "/perm edit"
|
||||
Then reply contains "No active session"
|
||||
|
||||
Scenario: Set permission on specific conv_id
|
||||
@ -53,12 +53,12 @@ Feature: /perm command — change session permission mode
|
||||
|
||||
Scenario: Cannot change permission of another user's session
|
||||
Given session "sess01" in "/tmp/proj1" belongs to user "other_user"
|
||||
When user sends "/perm accept sess01"
|
||||
When user sends "/perm edit sess01"
|
||||
Then reply contains "another user"
|
||||
|
||||
Scenario: New session with --perm accept
|
||||
When user sends "/new myproject --perm accept"
|
||||
Then reply contains "accept"
|
||||
Scenario: New session with --perm edit
|
||||
When user sends "/new myproject --perm edit"
|
||||
Then reply contains "edit"
|
||||
And session manager has 1 session for user "user_abc123"
|
||||
|
||||
Scenario: New session with --perm plan
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user