mirror of
https://github.com/NCBM/plyngent.git
synced 2026-07-23 05:55:16 +08:00
ci/lint: ruff format pass and fix compact seed test typing
Apply pending ruff format; narrow AssistantChatMessage.content before membership checks so basedpyright accepts Unset|None unions.
This commit is contained in:
@@ -52,9 +52,7 @@ def format_transcript(messages: Sequence[AnyChatMessage]) -> str:
|
||||
if tool_calls is not UNSET and tool_calls:
|
||||
for call in tool_calls:
|
||||
if isinstance(call, AssistantFunctionToolCall):
|
||||
lines.append(
|
||||
f"[assistant tool_call] {call.function.name}({call.function.arguments})"
|
||||
)
|
||||
lines.append(f"[assistant tool_call] {call.function.name}({call.function.arguments})")
|
||||
else:
|
||||
lines.append(f"[assistant tool_call] custom id={call.id}")
|
||||
elif isinstance(msg, ToolChatMessage):
|
||||
|
||||
@@ -104,9 +104,7 @@ async def _execute_tool_calls(
|
||||
*[_run_one_tool(tools, call, max_result_chars=max_result_chars) for call in tool_calls]
|
||||
)
|
||||
else:
|
||||
results = [
|
||||
await _run_one_tool(tools, call, max_result_chars=max_result_chars) for call in tool_calls
|
||||
]
|
||||
results = [await _run_one_tool(tools, call, max_result_chars=max_result_chars) for call in tool_calls]
|
||||
|
||||
for tool_msg, err in results:
|
||||
if err is not None:
|
||||
|
||||
@@ -90,8 +90,7 @@ async def _run_chat(
|
||||
except ValueError as exc:
|
||||
raise click.ClickException(str(exc)) from exc
|
||||
click.echo(
|
||||
f"resumed session {session_id} ({len(state.agent.messages)} messages) "
|
||||
f"workspace={state.workspace}"
|
||||
f"resumed session {session_id} ({len(state.agent.messages)} messages) workspace={state.workspace}"
|
||||
)
|
||||
elif new_session:
|
||||
await state.new_session()
|
||||
|
||||
@@ -92,4 +92,3 @@ async def render_events(events: AsyncIterator[AgentEvent]) -> None: # noqa: C90
|
||||
if printed_text:
|
||||
click.echo()
|
||||
click.echo()
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ def pause_task_cancel_for_prompt() -> Generator[None]:
|
||||
loop = asyncio.get_running_loop()
|
||||
_ = loop.remove_signal_handler(signal.SIGINT)
|
||||
loop_handler_removed = True
|
||||
except (RuntimeError, NotImplementedError, ValueError):
|
||||
except RuntimeError, NotImplementedError, ValueError:
|
||||
loop_handler_removed = False
|
||||
|
||||
try:
|
||||
|
||||
@@ -18,7 +18,7 @@ def _prompt_continue_limit_sync(reason: str) -> bool:
|
||||
click.secho(f"[limit] {reason}", fg="yellow")
|
||||
try:
|
||||
return bool(click.confirm("Raise limit and continue?", default=True))
|
||||
except (click.Abort, KeyboardInterrupt):
|
||||
except click.Abort, KeyboardInterrupt:
|
||||
return False
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ def _prompt_confirm_tool_sync(name: str, args: Mapping[str, object], reason: str
|
||||
click.secho(f"[confirm] tool {name!r}: {reason}", fg="yellow")
|
||||
try:
|
||||
return bool(click.confirm("Allow this tool call?", default=False))
|
||||
except (click.Abort, KeyboardInterrupt):
|
||||
except click.Abort, KeyboardInterrupt:
|
||||
return False
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ def _prompt_workspace_mismatch_sync(
|
||||
default="k",
|
||||
show_choices=True,
|
||||
)
|
||||
except (click.Abort, KeyboardInterrupt):
|
||||
except click.Abort, KeyboardInterrupt:
|
||||
return "abort"
|
||||
key = str(raw).strip().lower()
|
||||
if key == "u":
|
||||
|
||||
@@ -94,9 +94,7 @@ async def _cmd_sessions(state: ReplState) -> None:
|
||||
for session in sessions:
|
||||
marker = "*" if session.sid == state.session_id else " "
|
||||
ws = session.workspace or "(unbound)"
|
||||
click.echo(
|
||||
f"{marker} {session.sid}\t{session.name}\tworkspace={ws}\tupdated={session.updated_at}"
|
||||
)
|
||||
click.echo(f"{marker} {session.sid}\t{session.name}\tworkspace={ws}\tupdated={session.updated_at}")
|
||||
|
||||
|
||||
async def _cmd_new(state: ReplState, arg: str) -> None:
|
||||
@@ -126,10 +124,7 @@ async def _cmd_resume(state: ReplState, arg: str) -> None:
|
||||
except ValueError as exc:
|
||||
click.echo(f"error: {exc}")
|
||||
return
|
||||
click.echo(
|
||||
f"resumed session {session_id} ({len(state.agent.messages)} messages) "
|
||||
f"workspace={state.workspace}"
|
||||
)
|
||||
click.echo(f"resumed session {session_id} ({len(state.agent.messages)} messages) workspace={state.workspace}")
|
||||
|
||||
|
||||
async def _cmd_compact(state: ReplState, arg: str) -> None:
|
||||
|
||||
@@ -57,14 +57,14 @@ async def run_cancellable[T](coro: Coroutine[object, object, T]) -> T:
|
||||
def _reinstall() -> None:
|
||||
try:
|
||||
loop.add_signal_handler(signal.SIGINT, _on_sigint)
|
||||
except (NotImplementedError, RuntimeError, ValueError):
|
||||
except NotImplementedError, RuntimeError, ValueError:
|
||||
return
|
||||
|
||||
try:
|
||||
loop.add_signal_handler(signal.SIGINT, _on_sigint)
|
||||
installed = True
|
||||
set_sigint_reinstall(_reinstall)
|
||||
except (NotImplementedError, RuntimeError, ValueError):
|
||||
except NotImplementedError, RuntimeError, ValueError:
|
||||
installed = False
|
||||
|
||||
try:
|
||||
@@ -115,8 +115,7 @@ def _echo_turn_usage(agent: ChatAgent) -> None:
|
||||
|
||||
async def _wait_for_retry(attempt: int, max_retries: int, wait: float) -> bool:
|
||||
click.secho(
|
||||
f"auto-retry {attempt}/{max_retries} in {wait:g}s "
|
||||
f"(Ctrl+C to cancel; then /retry later)",
|
||||
f"auto-retry {attempt}/{max_retries} in {wait:g}s (Ctrl+C to cancel; then /retry later)",
|
||||
fg="yellow",
|
||||
)
|
||||
try:
|
||||
|
||||
@@ -90,9 +90,7 @@ def copy_path(src: str, dst: str, *, overwrite: bool = False) -> str:
|
||||
source, dest, root = pair
|
||||
if not source.exists() and not source.is_symlink():
|
||||
return f"error: source does not exist: {src}"
|
||||
return _copy_or_move_validated(
|
||||
source, dest, root, src=src, dst=dst, overwrite=overwrite, action="copy"
|
||||
)
|
||||
return _copy_or_move_validated(source, dest, root, src=src, dst=dst, overwrite=overwrite, action="copy")
|
||||
|
||||
|
||||
@tool
|
||||
@@ -106,9 +104,7 @@ def move_path(src: str, dst: str, *, overwrite: bool = False) -> str:
|
||||
return f"error: source does not exist: {src}"
|
||||
if source == root:
|
||||
return "error: cannot move the workspace root"
|
||||
return _copy_or_move_validated(
|
||||
source, dest, root, src=src, dst=dst, overwrite=overwrite, action="move"
|
||||
)
|
||||
return _copy_or_move_validated(source, dest, root, src=src, dst=dst, overwrite=overwrite, action="move")
|
||||
|
||||
|
||||
def _delete_directory(target: Path, path: str, *, recursive: bool) -> str:
|
||||
|
||||
@@ -41,7 +41,7 @@ def _collect_glob(
|
||||
try:
|
||||
resolved = candidate.resolve()
|
||||
rel = resolved.relative_to(root)
|
||||
except (OSError, ValueError):
|
||||
except OSError, ValueError:
|
||||
continue
|
||||
# Skip anything under (or itself) VCS / hidden path components.
|
||||
if skip_hidden_dirs and _hidden_or_vcs(rel.parts):
|
||||
@@ -87,9 +87,7 @@ def glob_paths(
|
||||
return resolved
|
||||
root, base = resolved
|
||||
|
||||
result = _collect_glob(
|
||||
base, root, pattern, max_matches=max_matches, skip_hidden_dirs=skip_hidden_dirs
|
||||
)
|
||||
result = _collect_glob(base, root, pattern, max_matches=max_matches, skip_hidden_dirs=skip_hidden_dirs)
|
||||
if isinstance(result, str):
|
||||
return result
|
||||
matches, truncated = result
|
||||
|
||||
@@ -210,7 +210,7 @@ class PtyManager:
|
||||
ready, _, _ = select.select([session.master_fd], [], [], timeout)
|
||||
if ready:
|
||||
data = os.read(session.master_fd, to_read)
|
||||
except (OSError, ValueError):
|
||||
except OSError, ValueError:
|
||||
data = b""
|
||||
cls._poll_exit(session)
|
||||
if not data:
|
||||
@@ -305,9 +305,7 @@ class PtyManager:
|
||||
budget_exhausted=True,
|
||||
)
|
||||
|
||||
chunks, matched = cls._collect_chunks(
|
||||
session, max_bytes=max_bytes, timeout=timeout, until=until
|
||||
)
|
||||
chunks, matched = cls._collect_chunks(session, max_bytes=max_bytes, timeout=timeout, until=until)
|
||||
data = b"".join(chunks).decode(errors="replace")
|
||||
truncated = len(data) > max_bytes
|
||||
if truncated:
|
||||
|
||||
@@ -18,10 +18,7 @@ def _backend_or_error() -> VcsBackend | str:
|
||||
return f"error: {exc}"
|
||||
backend = detect_vcs(root)
|
||||
if backend is None:
|
||||
return (
|
||||
"error: no supported VCS detected under workspace "
|
||||
"(currently: git; other systems can register detectors)"
|
||||
)
|
||||
return "error: no supported VCS detected under workspace (currently: git; other systems can register detectors)"
|
||||
return backend
|
||||
|
||||
|
||||
|
||||
@@ -96,9 +96,7 @@ def test_compact_disabled_when_max_tokens_zero() -> None:
|
||||
ToolChatMessage(content="x" * 500, tool_call_id="1"),
|
||||
]
|
||||
out = compact_messages_for_request(messages, max_tokens=0)
|
||||
assert out[0] is messages[0] or (
|
||||
isinstance(out[0], ToolChatMessage) and out[0].content == "x" * 500
|
||||
)
|
||||
assert out[0] is messages[0] or (isinstance(out[0], ToolChatMessage) and out[0].content == "x" * 500)
|
||||
|
||||
|
||||
def test_measure_messages_tokens_calibrates_to_api_hint() -> None:
|
||||
|
||||
@@ -53,8 +53,10 @@ def test_build_compacted_seed_messages() -> None:
|
||||
assert isinstance(seed[0], SystemChatMessage)
|
||||
assert seed[0].content == "sys"
|
||||
assert isinstance(seed[1], AssistantChatMessage)
|
||||
assert "summary text" in seed[1].content
|
||||
assert "session 3" in seed[1].content
|
||||
content = seed[1].content
|
||||
assert isinstance(content, str)
|
||||
assert "summary text" in content
|
||||
assert "session 3" in content
|
||||
|
||||
|
||||
class SummaryClient:
|
||||
|
||||
@@ -617,7 +617,6 @@ async def test_retry_after_resume_orphan_user() -> None:
|
||||
await store.close()
|
||||
|
||||
|
||||
|
||||
async def test_chat_agent_system_prompt_prepended() -> None:
|
||||
from plyngent.lmproto.openai_compatible.model import SystemChatMessage
|
||||
|
||||
|
||||
@@ -142,9 +142,7 @@ async def test_rounds(state: ReplState) -> None:
|
||||
assert state.agent.max_rounds == 40
|
||||
|
||||
|
||||
async def test_status_shows_context_tokens(
|
||||
state: ReplState, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
async def test_status_shows_context_tokens(state: ReplState, capsys: pytest.CaptureFixture[str]) -> None:
|
||||
from plyngent.agent.usage import TokenUsage
|
||||
from plyngent.lmproto.openai_compatible.model import UserChatMessage
|
||||
|
||||
|
||||
@@ -41,4 +41,3 @@ max_context_tokens = 5000
|
||||
assert store.agent_config.confirm_destructive is False
|
||||
assert store.agent_config.path_denylist == ["/secrets/", ".ssh/"]
|
||||
assert store.agent_config.max_context_tokens == 5000
|
||||
|
||||
|
||||
@@ -13,9 +13,7 @@ def test_classify_delete_and_move() -> None:
|
||||
|
||||
def test_classify_copy_overwrite_only() -> None:
|
||||
assert classify_danger("copy_path", {"src": "a", "dst": "b"}) is None
|
||||
assert "overwrite" in (
|
||||
classify_danger("copy_path", {"src": "a", "dst": "b", "overwrite": True}) or ""
|
||||
)
|
||||
assert "overwrite" in (classify_danger("copy_path", {"src": "a", "dst": "b", "overwrite": True}) or "")
|
||||
|
||||
|
||||
def test_classify_write_file_overwrite(workspace: object) -> None:
|
||||
|
||||
Reference in New Issue
Block a user