tools/chat: rename tools to ask_user_line, ask_user_choice, ask_user_form

Model-facing names via @tool(name=…); Python symbols unchanged.
This commit is contained in:
2026-07-17 15:36:29 +08:00
parent b8ed9e0ee9
commit 39acd5967e
6 changed files with 15 additions and 15 deletions
+2 -2
View File
@@ -77,7 +77,7 @@ Module-level `@tool` handlers. Call `set_workspace_root()` before use.
- CLI limit hooks: interactive confirm to raise tool-loop rounds, PTY session cap, or PTY output budget.
- Destructive confirms: `classify_danger` + `ToolRegistry(on_confirm=…)`; CLI default deny; config `confirm_destructive` / `path_denylist`. Session YOLO: `/yolo on|off|once` and `--yes` (skip soft confirms; hard denylists unchanged; `once` expires after the next user turn).
- **`vcs`**: read-only VCS tools (`vcs_kind` / `vcs_status` / `vcs_diff` / `vcs_log` / `vcs_branch`) via `VcsBackend` protocol; **git** implemented; detectors are pluggable for other systems.
- **`chat`**: human prompts as tools — `ask_user`, `choose_user`, `form_user` (shared `prompting` core).
- **`chat`**: human prompts as tools — `ask_user_line` / `ask_user_choice` / `ask_user_form` (shared `prompting` core).
- **`DEFAULT_TOOLS`**: file + process + vcs + chat tool list for a `ToolRegistry`.
### Prompting (`prompting.py`)
@@ -112,7 +112,7 @@ Basedpyright `recommended`. Ruff includes `ANN` (private return types `ANN202` i
- **Phase G (CLI polish + hardening)** — single-user only; multi-tenant stays Phase H.
**Done**
- G0: `prompting` (`ask`/`choose`/`form`/`confirm`) + chat tools (`ask_user`/`choose_user`/`form_user`)
- G0: `prompting` (`ask`/`choose`/`form`/`confirm`) + chat tools (`ask_user_line`/`ask_user_choice`/`ask_user_form`)
- G1: `ReasoningDeltaEvent`, `/stream`, `/verbose`
- G2: `/rename`, `/delete` (confirm), `/export md|json`
- G2.5: Click slash registry (`cli/slash.py`) + `awaitlet` for sync Click / async memory; auto `/help`; completer from `slash.list_commands`
+1 -1
View File
@@ -210,7 +210,7 @@ User messages are saved immediately. On API error or Ctrl+C, partial assistant/t
## Tools (when enabled)
Default registry: file ops, `run_command` / PTY (POSIX openpty; Windows ConPTY via pywinpty), read-only VCS (git), and human prompts (`ask_user` / `choose_user` / `form_user`).
Default registry: file ops, `run_command` / PTY (POSIX openpty; Windows ConPTY via pywinpty), read-only VCS (git), and human prompts (`ask_user_line` / `ask_user_choice` / `ask_user_form`).
Safety defaults:
+2 -2
View File
@@ -4,9 +4,9 @@ from plyngent.agent import tool
from plyngent.prompting import NonInteractiveError, ask_async
@tool
@tool(name="ask_user_line")
async def ask_user(question: str, default: str = "") -> str:
"""Ask the human a free-form question and return their answer.
"""Ask the human a free-form one-line question and return their answer.
Always allows arbitrary text. Use for clarifying requirements, preferences,
or any input that is not a fixed menu. Optional ``default`` is used if the
+2 -2
View File
@@ -46,7 +46,7 @@ def parse_options(raw: str) -> list[ChoiceOption]:
return out
@tool
@tool(name="ask_user_choice")
async def choose_user(
question: str,
options: str,
@@ -54,7 +54,7 @@ async def choose_user(
*,
allow_custom: bool = True,
) -> str:
"""Ask the human to pick from options (or type a custom answer).
"""Ask the human to pick from a list of options (or type a custom answer).
``options`` is a JSON array of strings, or objects with
``label``, optional ``description``, optional ``value``.
+2 -2
View File
@@ -54,13 +54,13 @@ def parse_fields(raw: str) -> list[FormField]:
return out
@tool
@tool(name="ask_user_form")
async def form_user(title: str, fields: str, *, confirm_submit: bool = True) -> str:
"""Run a multi-step form with the human; returns JSON object of answers.
``fields`` is a JSON array of objects:
``name``, ``prompt``, optional ``default``, optional ``options`` (same shape
as choose_user), optional ``allow_custom`` (default true).
as ask_user_choice), optional ``allow_custom`` (default true).
When ``confirm_submit`` is true, the human reviews a summary before submit.
"""
try:
+6 -6
View File
@@ -12,7 +12,7 @@ async def test_ask_user_tool() -> None:
backend = ScriptedBackend(["42"])
with temporary_backend(backend):
registry = ToolRegistry([ask_user])
out = await registry.execute("ask_user", '{"question": "Answer?"}')
out = await registry.execute("ask_user_line", '{"question": "Answer?"}')
assert out == "42"
@@ -21,7 +21,7 @@ async def test_choose_user_tool_index() -> None:
with temporary_backend(backend):
registry = ToolRegistry([choose_user])
out = await registry.execute(
"choose_user",
"ask_user_choice",
json.dumps(
{
"question": "Pick",
@@ -36,7 +36,7 @@ async def test_choose_user_tool_index() -> None:
async def test_choose_user_bad_options() -> None:
registry = ToolRegistry([choose_user])
out = await registry.execute(
"choose_user",
"ask_user_choice",
json.dumps({"question": "Pick", "options": "not-json"}),
)
assert out.startswith("error:")
@@ -48,7 +48,7 @@ async def test_form_user_tool() -> None:
with temporary_backend(backend):
registry = ToolRegistry([form_user])
out = await registry.execute(
"form_user",
"ask_user_form",
json.dumps({"title": "Setup", "fields": fields, "confirm_submit": True}),
)
assert json.loads(out) == {"user": "ncbm"}
@@ -56,11 +56,11 @@ async def test_form_user_tool() -> None:
async def test_chat_tools_in_default_list() -> None:
names = {t.name for t in CHAT_TOOLS}
assert names == {"ask_user", "choose_user", "form_user"}
assert names == {"ask_user_line", "ask_user_choice", "ask_user_form"}
async def test_ask_user_non_interactive_error() -> None:
with temporary_backend(NonInteractiveBackend()):
registry = ToolRegistry([ask_user])
out = await registry.execute("ask_user", '{"question": "hi"}')
out = await registry.execute("ask_user_line", '{"question": "hi"}')
assert out.startswith("error:")