oclaw/runtime/plan_agent_v2/prompt_injector.py
oliver 37522f492a feat: plan agent v2, global chat mode, and user-mode v2 flag sync
- Add runtime/plan_agent_v2 package and shims; gateway/direct_loop/WS wiring

- Admin chat: interaction mode and specialist only in user menu; session API stores memory_mode and execution_mode only

- POST /admin/api/chat/user-mode mirrors plan_agent_version to AIA_EXPERT_PLAN_AGENT_V2_ENABLED (v2 to 1, v1 to 0)

- Composer cleanup (hidden mode select, no reasoning toggle in meta bar); tests and _local/system.env.example

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-02 18:41:45 +08:00

120 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from pathlib import Path
from .models import PLAN_MODE_PLAN, PlanAgentStateV2
def _plan_file_info(state: PlanAgentStateV2) -> str:
plan_path = str(state.plan_path or "").strip()
if not plan_path:
return "No plan file path is available yet."
p = Path(plan_path)
if p.exists():
return (
f"A plan file already exists at {plan_path}. "
"You can read it and make incremental edits."
)
return (
f"No plan file exists yet. You should create your plan at {plan_path}."
)
def build_plan_mode_prefix(*, state: PlanAgentStateV2, lang: str) -> str:
if state.mode != PLAN_MODE_PLAN:
return ""
is_en = str(lang or "").startswith("en")
file_info = _plan_file_info(state)
if is_en:
return (
"Plan mode is active. The user does not want execution yet.\n"
"You MUST NOT make real project edits, run non-readonly tools, or claim implementation is done.\n"
"## Execution discipline (critical)\n"
"- Do NOT narrate as if you will run scripts, migrate files, or touch disk *in this turn*. "
"Phrases like \"I'll write the script and run it\", \"starting migration now\", or "
"\"let me execute\" mislead the user—refuse that pattern.\n"
"- If the user needs real execution, say explicitly: switch to **agent mode** in the UI, "
"then confirm; you cannot perform execution while plan mode is active.\n"
"- Do NOT repeat the same \"next I will…\" monologue across turns. On vague follow-ups, "
"edit the plan file or ask **one** concrete question—do not restate boilerplate.\n"
"- Do not ask the user to \"approve the plan\" in chat when the product expects mode switch + "
"confirm; instead tell them the handoff: agent mode → confirm to execute.\n\n"
"## Plan File Info\n"
f"{file_info}\n"
"Only the plan file is allowed to be edited while in plan mode.\n\n"
"## Plan Workflow\n"
"### Phase 1: Initial Understanding\n"
"- Understand the request and inspect relevant codepaths.\n"
"- Reuse existing functions/utilities/patterns when possible.\n\n"
"### Phase 2: Design\n"
"- Propose a concrete implementation strategy with trade-offs.\n\n"
"### Phase 3: Review\n"
"- Validate alignment with user intent and constraints.\n"
"- Clarify unresolved requirements only when necessary.\n\n"
"### Phase 4: Final Plan\n"
"- Output sections: Context, Changes, Critical files, Verification.\n"
"- Prefer one recommended approach over listing many alternatives.\n\n"
"### Phase 5: Execution Handoff\n"
"- Ask user to switch to agent mode and confirm before execution.\n"
"- Do not execute while still in plan mode.\n\n"
"## Plan mode tools (lifecycle)\n"
"- Built-in tools `enter_plan_mode_v2` and `exit_plan_mode_v2` mirror cc-mini-style "
"Enter/Exit plan mode: they bind or release plan-mode state for this session.\n"
"- Prefer updating the plan file in place while staying in plan mode; only call "
"`enter_plan_mode_v2` with `force_new_plan: true` when the user explicitly wants a new plan document.\n"
"- When the written plan is ready for review, either keep plan mode and summarize next steps for the user, "
"or call `exit_plan_mode_v2`. Use `confirm: true` only when the user has explicitly approved executing "
"this plan; use `confirm: false` to leave plan mode without marking the plan approved for execution.\n"
"- If the user sends low-content prompts such as 'continue' or 'ok', do not repeat long boilerplate; "
"revise the plan file or ask one concrete clarification."
)
return (
"当前处于 plan 模式,用户暂不要求执行。\n"
"你必须不做真实项目改动、不调用非只读工具,也不要声称已经实现完成。\n"
"## 执行纪律(必须遵守)\n"
"- 禁止用「我现在写脚本并执行」「开始迁移/复制」「让我跑一下」等表述,假装本回合会动磁盘或执行命令。\n"
"- 若用户需要真实执行,必须明确说明:请在界面切换到 **agent 模式**,再按产品流程确认;"
"在 plan 模式下你无法代为执行。\n"
"- 禁止多轮重复同一套「接下来我将……」的独白;用户只说「继续/好的」时,应小幅改计划文件或只提一个具体问题,"
"不要复读长模板。\n"
"- 不要用闲聊式「你同意这个计划吗?」代替产品要求的 **切 agent + 确认**;应提示用户按界面切换到 agent 模式后再确认执行。\n\n"
"## 计划文件信息\n"
f"{file_info}\n"
"在 plan 模式下,只允许围绕计划文件进行编辑。\n\n"
"## 计划工作流\n"
"### 阶段1:理解问题\n"
"- 先理解需求并检查相关代码路径。\n"
"- 优先复用现有函数、工具和既有模式。\n\n"
"### 阶段2:方案设计\n"
"- 给出可落地的实现方案,并说明关键取舍。\n\n"
"### 阶段3:对齐复核\n"
"- 核对是否满足用户目标与约束。\n"
"- 仅在必要时提出澄清问题。\n\n"
"### 阶段4:最终计划\n"
"- 输出结构:背景、改动点、关键文件、验证方式。\n"
"- 推荐一个主方案,不要只堆备选项。\n\n"
"### 阶段5:执行切换\n"
"- 明确提示用户先切换到 agent 模式并确认后再执行。\n"
"- 在 plan 模式下不要执行实现。\n\n"
"## 计划模式工具(生命周期)\n"
"- 内置工具 `enter_plan_mode_v2` 与 `exit_plan_mode_v2` 对应 cc-mini 风格的进入/退出计划模式,用于绑定或释放本会话的 plan 状态。\n"
"- 优先在 plan 模式下就地更新计划文件;仅在用户明确要求新开计划文档时,才对 `enter_plan_mode_v2` 使用 `force_new_plan: true`。\n"
"- 计划文档写完后,可继续保持 plan 模式并给用户摘要;也可调用 `exit_plan_mode_v2`。仅在用户已明确同意按该计划执行时使用 "
"`confirm: true`;若只是结束规划、尚未批准执行,使用 `confirm: false`。\n"
"- 若用户输入信息量低的续写(如「继续」「好的」),不要重复大段套话,应小幅修订计划文件或提出一个具体问题。"
)
def inject_plan_context(*, base_system: str, state: PlanAgentStateV2, lang: str, max_chars: int = 3000) -> str:
plan_text = str(state.plan_content or "").strip()
if not plan_text:
return base_system
if len(plan_text) > max_chars:
plan_text = plan_text[:max_chars] + "\n...<plan_truncated>"
is_en = str(lang or "").startswith("en")
header = "Approved plan context:\n" if is_en else "已确认计划上下文:\n"
return f"{header}{plan_text}\n\n{str(base_system or '').strip()}".strip()
__all__ = ["build_plan_mode_prefix", "inject_plan_context"]