diff --git a/scripts/wine_env.py b/scripts/wine_env.py index 10b4d68..5a1e419 100644 --- a/scripts/wine_env.py +++ b/scripts/wine_env.py @@ -187,10 +187,7 @@ def ensure_windows_uv(layout: WineLayout) -> None: return print(f"Fetching Windows uv {layout.win_uv_version} ...", file=sys.stderr) layout.bin_dir.mkdir(parents=True, exist_ok=True) - url = ( - f"https://github.com/astral-sh/uv/releases/download/" - f"{layout.win_uv_version}/uv-x86_64-pc-windows-msvc.zip" - ) + url = f"https://github.com/astral-sh/uv/releases/download/{layout.win_uv_version}/uv-x86_64-pc-windows-msvc.zip" zip_path = layout.bin_dir / "uv.zip" _ = urlretrieve(url, zip_path) with zipfile.ZipFile(zip_path) as zf: @@ -283,9 +280,7 @@ def find_project_venv_scripts(layout: WineLayout) -> Path | None: users = layout.prefix / "drive_c" / "users" if not users.is_dir(): return None - matches = sorted( - p for p in users.glob("**/pdm/pdm/venvs/project-view-*/Scripts") if p.is_dir() - ) + matches = sorted(p for p in users.glob("**/pdm/pdm/venvs/project-view-*/Scripts") if p.is_dir()) return matches[-1] if matches else None diff --git a/src/plyngent/agent/__init__.py b/src/plyngent/agent/__init__.py index 21db963..58eebe6 100644 --- a/src/plyngent/agent/__init__.py +++ b/src/plyngent/agent/__init__.py @@ -2,8 +2,6 @@ from .chat import ChatAgent as ChatAgent from .client import ChatClient as ChatClient from .compact import build_compacted_seed_messages as build_compacted_seed_messages from .compact import summarize_messages as summarize_messages -from .responses_client import ResponsesChatClient as ResponsesChatClient -from .responses_client import wrap_openai_for_agent as wrap_openai_for_agent from .events import AgentEvent as AgentEvent from .events import AssistantMessageEvent as AssistantMessageEvent from .events import CancelledEvent as CancelledEvent @@ -16,6 +14,8 @@ from .events import ToolResultEvent as ToolResultEvent from .events import UsageEvent as UsageEvent from .loop import DEFAULT_MAX_ROUNDS as DEFAULT_MAX_ROUNDS from .loop import run_chat_loop as run_chat_loop +from .responses_client import ResponsesChatClient as ResponsesChatClient +from .responses_client import wrap_openai_for_agent as wrap_openai_for_agent from .tools import DangerClassifier as DangerClassifier from .tools import ToolConfirmHook as ToolConfirmHook from .tools import ToolDefinition as ToolDefinition diff --git a/src/plyngent/agent/responses_client.py b/src/plyngent/agent/responses_client.py index 20e3dfe..4d7b08a 100644 --- a/src/plyngent/agent/responses_client.py +++ b/src/plyngent/agent/responses_client.py @@ -87,10 +87,15 @@ class ResponsesChatClient: if etype == "response.output_text.delta" and isinstance(event.delta, str) and event.delta: yield text_delta_chunk(model=model, content=event.delta) continue - if etype in { - "response.reasoning_summary_text.delta", - "response.reasoning_text.delta", - } and isinstance(event.delta, str) and event.delta: + if ( + etype + in { + "response.reasoning_summary_text.delta", + "response.reasoning_text.delta", + } + and isinstance(event.delta, str) + and event.delta + ): yield reasoning_delta_chunk(model=model, content=event.delta) continue if etype == "response.completed" and event.response is not UNSET: @@ -101,7 +106,7 @@ class ResponsesChatClient: try: final = msgspec.convert(event.response, ResponseModel) - except (TypeError, ValueError, msgspec.ValidationError): + except TypeError, ValueError, msgspec.ValidationError: final = None if final is not None: diff --git a/src/plyngent/cli/app.py b/src/plyngent/cli/app.py index e3e318b..fe9831c 100644 --- a/src/plyngent/cli/app.py +++ b/src/plyngent/cli/app.py @@ -74,8 +74,7 @@ def _warn_recoverable_providers(recoverable: Mapping[str, object]) -> None: return names = ", ".join(sorted(recoverable.keys())) click.secho( - f"warning: providers with empty models ({len(recoverable)}): {names} " - f"(will try GET /models or --model on use)", + f"warning: providers with empty models ({len(recoverable)}): {names} (will try GET /models or --model on use)", fg="yellow", err=True, ) diff --git a/src/plyngent/cli/provider_recovery.py b/src/plyngent/cli/provider_recovery.py index fac47a8..c968f4c 100644 --- a/src/plyngent/cli/provider_recovery.py +++ b/src/plyngent/cli/provider_recovery.py @@ -22,7 +22,7 @@ async def discover_model_ids(provider: Provider) -> list[str]: return [] try: return await fetch_remote_model_ids(client) - except (RuntimeError, TypeError, OSError, ValueError): + except RuntimeError, TypeError, OSError, ValueError: return [] @@ -79,8 +79,7 @@ async def ensure_provider_ready( promoted = await try_promote_provider(store, name, seed_model_ids=seeds or None) if promoted is not None: click.secho( - f"recovered provider {name!r} with {len(promoted.models)} model(s) " - f"(was empty models in config)", + f"recovered provider {name!r} with {len(promoted.models)} model(s) (was empty models in config)", fg="yellow", err=True, ) @@ -110,8 +109,5 @@ async def ensure_provider_ready( ) return promoted - msg = ( - f"provider {name!r} has empty models and could not be recovered " - f"(pass --model or fix GET /models)" - ) + msg = f"provider {name!r} has empty models and could not be recovered (pass --model or fix GET /models)" raise click.ClickException(msg) diff --git a/src/plyngent/cli/slash.py b/src/plyngent/cli/slash.py index 3c345e5..1bb48dc 100644 --- a/src/plyngent/cli/slash.py +++ b/src/plyngent/cli/slash.py @@ -655,8 +655,7 @@ def models_cmd(state: ReplState, *, refresh: bool) -> None: click.secho(f"remote list unavailable: {remote_err}", fg="yellow", err=True) elif remote is not None: click.echo( - f"({len(remote)} remote, {len(config_ids)} config; " - f"cache TTL {int(DEFAULT_MODELS_CACHE_TTL)}s)", + f"({len(remote)} remote, {len(config_ids)} config; cache TTL {int(DEFAULT_MODELS_CACHE_TTL)}s)", err=True, ) diff --git a/src/plyngent/cli/state.py b/src/plyngent/cli/state.py index 9d7dd38..44765c3 100644 --- a/src/plyngent/cli/state.py +++ b/src/plyngent/cli/state.py @@ -185,7 +185,7 @@ class ReplState: remote: list[str] | None try: remote = await self.ensure_remote_models(refresh=refresh) - except (RuntimeError, TypeError, OSError, ValueError): + except RuntimeError, TypeError, OSError, ValueError: remote = self.cached_remote_models() return model_choices_for_provider(self.provider, remote_ids=remote) @@ -269,13 +269,13 @@ class ReplState: preferred=pname, interactive=False, ) - except (click.ClickException, ProviderNotSupportedError): + except click.ClickException, ProviderNotSupportedError: return False # Session resume: seed empty recoverable with remembered model if any. if not provider.models and self.model: try: provider = self.config.promote_provider(name, [self.model]) - except (KeyError, ValueError): + except KeyError, ValueError: return False if name != self.provider_name or provider is not self.provider: self.provider_name = name diff --git a/src/plyngent/lmproto/openai/client.py b/src/plyngent/lmproto/openai/client.py index 03b6430..9b80296 100644 --- a/src/plyngent/lmproto/openai/client.py +++ b/src/plyngent/lmproto/openai/client.py @@ -66,9 +66,7 @@ class OpenAIClient(BaseOpenAIClient): return self.decoder.decode(body) @overload - async def responses( - self, param: ResponsesCreateParam, *, stream: Literal[False] = False - ) -> Response: ... + async def responses(self, param: ResponsesCreateParam, *, stream: Literal[False] = False) -> Response: ... @overload async def responses( diff --git a/src/plyngent/lmproto/openai/model.py b/src/plyngent/lmproto/openai/model.py index b24637a..661c47f 100644 --- a/src/plyngent/lmproto/openai/model.py +++ b/src/plyngent/lmproto/openai/model.py @@ -316,7 +316,7 @@ def response_function_calls(response: Response) -> list[ResponseFunctionToolCall continue try: result.append(msgspec_convert_function_call(raw)) - except (TypeError, ValueError, KeyError, msgspec.ValidationError): + except TypeError, ValueError, KeyError, msgspec.ValidationError: continue return result diff --git a/src/plyngent/runtime/client_factory.py b/src/plyngent/runtime/client_factory.py index 90ed1fe..677b0e3 100644 --- a/src/plyngent/runtime/client_factory.py +++ b/src/plyngent/runtime/client_factory.py @@ -20,9 +20,7 @@ if TYPE_CHECKING: DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1" DEFAULT_DEEPSEEK_BASE_URL = "https://api.deepseek.com" -type ProtocolClient = ( - OpenAIClient | OpenAICompatibleClient | DeepseekOpenAIClient | ResponsesChatClient -) +type ProtocolClient = OpenAIClient | OpenAICompatibleClient | DeepseekOpenAIClient | ResponsesChatClient # Backward-compatible name used by older imports/tests. type OpenAICompatibleClientUnion = ProtocolClient diff --git a/src/plyngent/tools/process/pty_backend.py b/src/plyngent/tools/process/pty_backend.py index 7eb0a81..f3941fe 100644 --- a/src/plyngent/tools/process/pty_backend.py +++ b/src/plyngent/tools/process/pty_backend.py @@ -97,7 +97,7 @@ class PosixPtyHandle: ready, _, _ = select.select([self.master_fd], [], [], timeout) if ready: data = os.read(self.master_fd, max_bytes) - except (OSError, ValueError): + except OSError, ValueError: data = b"" _ = self.poll_exit() return data diff --git a/tests/test_lmproto/test_models.py b/tests/test_lmproto/test_models.py index 01a53d8..26a0223 100644 --- a/tests/test_lmproto/test_models.py +++ b/tests/test_lmproto/test_models.py @@ -24,11 +24,7 @@ async def test_client_models_sorted_unique(monkeypatch: pytest.MonkeyPatch) -> N @property def content(self) -> bytes: - return ( - b'{"object":"list","data":[' - b'{"id":"m2"},{"id":"m1"},{"id":"m2"},{"id":""}' - b"]}" - ) + return b'{"object":"list","data":[{"id":"m2"},{"id":"m1"},{"id":"m2"},{"id":""}]}' async def fake_get(path: str, **kwargs: object) -> _Resp: assert path == "/models" diff --git a/tests/test_lmproto/test_responses.py b/tests/test_lmproto/test_responses.py index a3c4d38..8fe4e16 100644 --- a/tests/test_lmproto/test_responses.py +++ b/tests/test_lmproto/test_responses.py @@ -59,10 +59,7 @@ def test_create_param_encode_omits_defaults() -> None: def test_stream_event_decode() -> None: - raw = ( - b'{"type":"response.output_text.delta","item_id":"msg_1",' - b'"output_index":0,"content_index":0,"delta":"hel"}' - ) + raw = b'{"type":"response.output_text.delta","item_id":"msg_1","output_index":0,"content_index":0,"delta":"hel"}' event = msgspec.json.decode(raw, type=ResponseStreamEvent) assert event.type == "response.output_text.delta" assert event.delta == "hel"