mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 15:37:55 +08:00
cli/config: --auto-continue flag and [agent] auto_continue_limits
This commit is contained in:
+20
-4
@@ -124,9 +124,14 @@ def _read_prompt_text(prompt: str | None, *, stdin_isatty: bool) -> str | None:
|
||||
return text or None
|
||||
|
||||
|
||||
def _setup_hooks(*, interactive: bool) -> None:
|
||||
"""Install interactive limit hooks (workspace policy is set on ReplState)."""
|
||||
if interactive:
|
||||
def _setup_hooks(*, interactive: bool, auto_continue: bool) -> None:
|
||||
"""Install limit hooks (workspace policy is set on ReplState).
|
||||
|
||||
``auto_continue`` keeps the PTY/limit hook installed for one-shot runs so
|
||||
``--auto-continue`` / ``[agent] auto_continue_limits`` can raise limits
|
||||
without a prompt; otherwise non-interactive runs keep today's deny.
|
||||
"""
|
||||
if interactive or auto_continue:
|
||||
install_cli_limit_hooks()
|
||||
else:
|
||||
from plyngent.tools.process.pty_session import PtyManager
|
||||
@@ -221,6 +226,7 @@ async def _run_chat( # noqa: C901, PLR0912, PLR0915 — chat orchestration
|
||||
prompt_text: str | None,
|
||||
stream: bool,
|
||||
yes: bool,
|
||||
auto_continue: bool,
|
||||
quiet: bool,
|
||||
) -> int:
|
||||
oneshot = prompt_text is not None
|
||||
@@ -236,7 +242,8 @@ async def _run_chat( # noqa: C901, PLR0912, PLR0915 — chat orchestration
|
||||
if store.recoverable_providers:
|
||||
_warn_recoverable_providers(store.recoverable_providers)
|
||||
|
||||
_setup_hooks(interactive=interactive)
|
||||
auto_effective = auto_continue or store.agent_config.auto_continue_limits
|
||||
_setup_hooks(interactive=interactive, auto_continue=auto_effective)
|
||||
# --yes forces sticky YOLO; else derive from config.confirm_destructive.
|
||||
from plyngent.cli.state import YoloMode
|
||||
|
||||
@@ -315,6 +322,7 @@ async def _run_chat( # noqa: C901, PLR0912, PLR0915 — chat orchestration
|
||||
max_rounds=max_rounds,
|
||||
stream_enabled=stream,
|
||||
interactive_limits=interactive,
|
||||
auto_continue_limits=auto_effective,
|
||||
yolo=yolo,
|
||||
mcp_manager=mcp_manager,
|
||||
)
|
||||
@@ -480,6 +488,12 @@ def main(ctx: click.Context, log_level: str) -> None:
|
||||
default=False,
|
||||
help="Enable YOLO: skip destructive-tool confirms (sticky for this process).",
|
||||
)
|
||||
@click.option(
|
||||
"--auto-continue",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Auto-raise tool/PTY limits without prompting (like answering yyy).",
|
||||
)
|
||||
@click.option(
|
||||
"--quiet",
|
||||
is_flag=True,
|
||||
@@ -498,6 +512,7 @@ def chat_cmd(
|
||||
prompt: str | None,
|
||||
stream: bool, # noqa: FBT001
|
||||
yes: bool, # noqa: FBT001
|
||||
auto_continue: bool, # noqa: FBT001
|
||||
quiet: bool, # noqa: FBT001
|
||||
) -> None:
|
||||
"""Interactive chat REPL, or one-shot with ``-p`` / stdin.
|
||||
@@ -538,6 +553,7 @@ def chat_cmd(
|
||||
prompt_text=prompt_text,
|
||||
stream=stream,
|
||||
yes=yes,
|
||||
auto_continue=auto_continue,
|
||||
quiet=quiet,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -36,14 +36,17 @@ def _echo_interrupted() -> None:
|
||||
async def run_repl(state: ReplState) -> None:
|
||||
"""Interactive chat loop with readline editing, history, and Tab completion."""
|
||||
setup_readline(state)
|
||||
from plyngent.cli.limits import auto_continue_enabled
|
||||
|
||||
yolo = state.effective_yolo()
|
||||
yolo_part = f" yolo={yolo}" if yolo != "off" else ""
|
||||
auto_part = " limit_auto=on" if auto_continue_enabled() else ""
|
||||
click.echo(
|
||||
f"plyngent chat provider={state.provider_name} model={state.model} "
|
||||
f"session={state.session_id} tools={'on' if state.tools_enabled else 'off'} "
|
||||
f"rounds={state.max_rounds} messages={len(state.agent.messages)} "
|
||||
f"stream={'on' if state.agent.stream else 'off'} "
|
||||
f"verbose={'on' if state.verbose else 'off'}{yolo_part}"
|
||||
f"verbose={'on' if state.verbose else 'off'}{yolo_part}{auto_part}"
|
||||
)
|
||||
click.echo('Type /help for commands. Multiline: """ … """. Empty line is ignored.')
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ class ReplState:
|
||||
markdown_enabled: bool = True
|
||||
# One-shot / scripts: never prompt to raise tool-loop limits.
|
||||
interactive_limits: bool = True
|
||||
# Auto-raise tool/PTY limits without prompting (--auto-continue / config).
|
||||
auto_continue_limits: bool = False
|
||||
# Soft destructive-tool confirms: None → derive from config.confirm_destructive.
|
||||
# off = confirm; on = skip (sticky); once = skip next user turn then off.
|
||||
yolo: YoloMode | None = None
|
||||
@@ -97,6 +99,9 @@ class ReplState:
|
||||
self.instance_state.workspace_root = self.workspace
|
||||
self.instance_state.workspace.root = self.workspace
|
||||
self._install_config_access()
|
||||
from plyngent.cli.limits import set_auto_continue_default
|
||||
|
||||
set_auto_continue_default(enabled=self.auto_continue_limits)
|
||||
self.session_state = self._session_data_for_todo()
|
||||
self.agent = self._make_agent()
|
||||
self.sync_display_flags()
|
||||
@@ -340,7 +345,7 @@ class ReplState:
|
||||
return "\n\n".join(parts)
|
||||
|
||||
def _make_agent(self) -> ChatAgent:
|
||||
from plyngent.cli.limits import prompt_continue_limit_async
|
||||
from plyngent.cli.limits import auto_continue_enabled, prompt_continue_limit_async
|
||||
from plyngent.config import compose_agent_system_content
|
||||
|
||||
agent_cfg = self.config.agent_config
|
||||
@@ -350,7 +355,7 @@ class ReplState:
|
||||
agent_cfg.tool_directives,
|
||||
mcp_text,
|
||||
)
|
||||
on_limit = prompt_continue_limit_async if self.interactive_limits else None
|
||||
on_limit = prompt_continue_limit_async if (self.interactive_limits or auto_continue_enabled()) else None
|
||||
peak = 0
|
||||
band = 0
|
||||
last_req = None
|
||||
|
||||
@@ -117,6 +117,9 @@ class AgentConfig(Struct, omit_defaults=True):
|
||||
# Static directory pre-allow (resolved path → mode); never prompts.
|
||||
# Denylist still applies, and the path must exist when chat starts.
|
||||
allow_paths: dict[str, AllowPathMode] = field(default_factory=dict)
|
||||
# Auto-raise tool/PTY limits without prompting (same as answering ``yyy``);
|
||||
# process-wide, so every turn skips the limit confirm.
|
||||
auto_continue_limits: bool = False
|
||||
max_context_tokens: int = 200_000
|
||||
|
||||
# How to inject todo stack nags into model context (see agent/todo_nag.py).
|
||||
|
||||
Reference in New Issue
Block a user