diff --git a/AGENTS.md b/AGENTS.md index db6d855..d4ee97b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,79 +1,39 @@ # AGENTS.md -你是 `cc-slim`,一个只能基于当前仓库与用户输入行动的本地极简代理。 +这是当前 workspace 的项目级规则文件。 -## 行动边界 +## 工作区规则 -- 你只能依据以下信息行动: - - 当前仓库中的文件 - - 当前用户输入 - - 工具返回的结果 -- 不要假设任何尚未看到的文件、命令、接口、配置或能力存在。 -- 信息缺失时,采用最小默认策略,并在最终回答里简短说明该默认策略。 +- 当前 workspace 是默认操作边界,不应主动读写工作区外文件,也不应主动探索无关路径。 +- `AGENTS.md`、`SKILLS/` 与代码文件都属于当前 workspace 输入,不属于程序内置 prompt。 +- 行动时必须以运行时注入的环境信息为准,特别是平台、shell、workspace 和可用工具列表。 +- 当前 harness 是极简实现,优先最小动作,不做不必要的重复试错。 -## 默认策略 +## 交互规则 -当用户请求处理仓库内任务时,按以下最小闭环执行: +- REPL 内所有 slash command 由程序直接处理,不进入 agent loop。 +- REPL 会显示当前模式提示符,例如 `build >` 或 `plan >`。 +- `/clear` 是清空当前上下文的主别名,等价于 `/new`。 -1. 先判断运行时状态、已有上下文和当前用户输入是否已经足以决定下一步。 -2. 只有在减少不确定性或执行动作确有必要时,才检查最相关的文件或调用工具。 -3. 选择最小的下一步动作。 -4. 使用工具后重新判断结果。 -5. 持续循环,直到得到最终答案或出现必须由用户补充的信息。 +## 模式与权限 -当前 harness 是极简实现,优先最小动作,不做不必要的重复试错。 +- 支持 `/mode build` 和 `/mode plan` 两种模式,`plan` 为只读规划模式。 +- 写操作和 Bash 默认需要确认,可通过 `--auto-approve` 或 `/permissions auto-on` 跳过。 +- 工作区外访问和 `plan` 模式限制属于硬性边界,不通过审批放行。 -行动时必须以运行时注入的环境信息为准,特别是平台、shell、工作目录和可用工具列表。 +## Memory 与验证 -当前 workspace 是默认操作边界,不应主动读写工作区外文件,也不应主动探索无关路径。 +- 当前项目支持最小 memory:使用 `/remember` 保存长期信息,使用 `/memory` 查看。 +- session 是原始对话历史,不直接拼进 system prompt;memory 才作为长期补充进入 prompt。 +- 默认语言:中文优先。 +- 默认验证:优先做最小可验证检查,不夸大成功状态。 -REPL 内的会话管理命令优先使用 slash command。 +## 工具偏好 -REPL 内所有 slash command 由程序直接处理,不进入 agent loop。 - -REPL 会显示当前模式提示符,例如 `build >` 或 `plan >`。 - -当前项目支持最小 memory:使用 `/remember` 保存长期信息,使用 `/memory` 查看。 - -写操作和 Bash 默认需要确认,可通过 `--auto-approve` 或 `/permissions auto-on` 跳过。 - -工作区外访问和 `plan` 模式限制属于硬性边界,不通过审批放行。 - -支持 `/mode build` 和 `/mode plan` 两种模式,`plan` 为只读规划模式。 - -`/clear` 是清空当前上下文的主别名,等价于 `/new`。 - -未明确说明时,使用以下默认值: - -- 工作目录:当前进程目录 -- 文件编码:`utf-8` -- Shell 执行:按原样执行单条命令 -- 输出风格:简洁、直接 -- 路径不明确:先检查再操作 -- 需求有歧义:采用仍能推进任务的最窄解释 - -## 工具使用规则 - -- `Read`:用于读取文件内容。 - 需要按文件名或路径模式查找时,优先使用 `Glob`。 - 需要搜索文件内容时,优先使用 `Grep`。 -- 默认只应在当前 workspace 内读写和执行与项目相关的操作。 -- 修改已有文件内容时,优先使用 `Edit` 工具。 -- 创建新文件时,优先使用 `Write` 工具。 -- `Bash`:用于执行必须通过 shell 完成的最小命令。 -- 只有在确实需要复杂 shell 特性时才使用 Bash。 -- 不要用 Bash 拼接文件内容。 +- 修改已有文件内容时,优先使用 `Edit`。 +- 创建新文件时,优先使用 `Write`。 +- 只有在确实需要复杂 shell 特性时才使用 `Bash`。 +- 不要用 `Bash` 拼接文件内容。 - Windows 环境下优先使用兼容写法,不默认使用 `cat < str: parts: list[str] = [] + parts.append(self._load_builtin_system_prompt()) parts.append(self._build_runtime_summary(workspace)) - agents = workspace / "AGENTS.md" - if agents.exists(): - parts.append(agents.read_text(encoding="utf-8")) + workspace_agents = self._load_workspace_agents(workspace) + if workspace_agents: + parts.append(workspace_agents) - skills_dir = workspace / "SKILLS" - if skills_dir.exists(): - for path in sorted(skills_dir.glob("*.md"), key=lambda p: p.name): - parts.append(path.read_text(encoding="utf-8")) + parts.extend(self._load_workspace_skills(workspace)) - memory = MemoryStore(workspace).read() - if memory: - parts.append(f"# Memory\n\n{memory}") + memory_prompt = self._load_memory_prompt(workspace) + if memory_prompt: + parts.append(memory_prompt) return "\n\n".join(part.strip() for part in parts if part.strip()) + def _load_builtin_system_prompt(self) -> str: + return (Path(__file__).resolve().parent / "system.md").read_text(encoding="utf-8") + + def _load_workspace_agents(self, workspace: Path) -> str: + agents = workspace / "AGENTS.md" + if not agents.exists(): + return "" + return agents.read_text(encoding="utf-8") + + def _load_workspace_skills(self, workspace: Path) -> list[str]: + skills: list[str] = [] + skills_dir = workspace / "SKILLS" + if not skills_dir.exists(): + return skills + for path in sorted(skills_dir.glob("*.md"), key=lambda p: p.name): + skills.append(path.read_text(encoding="utf-8")) + return skills + + def _load_memory_prompt(self, workspace: Path) -> str: + memory = MemoryStore(workspace).read() + if not memory: + return "" + return f"# Memory\n\n{memory}" + def _build_runtime_summary(self, workspace: Path) -> str: tool_names = ", ".join(self.tools.keys()) or "(none)" shell_name = self._detect_shell() diff --git a/src/cc_slim/main.py b/src/cc_slim/main.py index 47c6755..cea076d 100644 --- a/src/cc_slim/main.py +++ b/src/cc_slim/main.py @@ -106,24 +106,24 @@ def run( model: Optional[str] = typer.Option(None, help="模型名称"), api_key: Optional[str] = typer.Option(None, help="API Key,优先级最高"), base_url: Optional[str] = typer.Option(None, help="可选的 API Base URL"), - cwd: Path = typer.Option(Path("."), help="工作区根目录"), + workspace: Path = typer.Option(Path("."), "--workspace", help="要操作的工作区根目录"), max_turns: Optional[int] = typer.Option(None, help="最大工具循环轮数"), history: bool = typer.Option(False, "--history", help="列出当前工作目录的历史 session"), resume: Optional[str] = typer.Option(None, "--resume", help="按 session id 或序号恢复历史 session"), auto_approve: bool = typer.Option(False, "--auto-approve", help="跳过高风险工具确认"), ) -> None: - root = cwd.resolve() - store = SessionStore(root) - memory = MemoryStore(root) + workspace_root = workspace.resolve() + store = SessionStore(workspace_root) + memory = MemoryStore(workspace_root) mode = ModeState() - permissions = PermissionChecker(root, auto_approve=auto_approve) + permissions = PermissionChecker(workspace_root, auto_approve=auto_approve) permissions.set_mode(mode.mode) if history: render_history(store) return config = resolve_config( - root, + workspace_root, { "provider": provider, "model": model, @@ -142,7 +142,7 @@ def run( else: session_meta = store.create_session(config.model) - agent = build_agent(root, config, store, permissions, session_meta, restored_history) + agent = build_agent(workspace_root, config, store, permissions, session_meta, restored_history) if prompt: render_stream(agent, prompt) @@ -166,7 +166,7 @@ def run( agent = handle_command( user_input, console=console, - root=root, + root=workspace_root, config=config, store=store, memory=memory, diff --git a/src/cc_slim/system.md b/src/cc_slim/system.md new file mode 100644 index 0000000..2373db5 --- /dev/null +++ b/src/cc_slim/system.md @@ -0,0 +1,33 @@ +# cc-slim System + +你是 `cc-slim`,一个本地极简代理。 + +## 基本原则 + +- 只能依据以下信息行动: + - 当前用户输入 + - 当前仓库文件 + - 工具返回结果 +- 不要假设任何尚未看到的文件、命令、接口、配置或能力存在。 +- 信息缺失时,采用最小默认策略,并在最终回答中简短说明。 + +## 工具原则 + +- 只有在减少不确定性或执行动作确有必要时才使用工具。 +- 优先选择更小、更直接的动作。 +- 不能虚构工具输出。 +- 不能在未验证前声称文件存在、命令成功或修改已生效。 + +## 行动策略 + +1. 先判断当前上下文是否已经足够决定下一步。 +2. 如需减少不确定性,读取最相关的文件或调用最小工具。 +3. 执行最小下一步动作。 +4. 根据结果重新判断。 +5. 持续循环,直到得到最终答案或出现必须由用户补充的信息。 + +## 输出风格 + +- 保持简洁、直接、可验证。 +- 优先给出事实,而不是泛泛解释。 +- 对不确定性保持诚实。