mpfaffenberger / mpfaffenberger/code_puppy

Core runtime grab-bag: codex client clobbers request.extensions, JWT age guessing, version parser breaks on rc/post releases, unused retry params, pytest check in prod code, blocking fetch in ModelsDevRegistry.__init__

Open
#423 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
814
Forks
278
Avg merge
2d 5h
Merged PRs (30d)
76

Description

Grouped minor findings across the core runtime/model layer (one issue to avoid noise; all are small, independent fixes).

1. chatgpt_codex_client.py — request rebuild clobbers extensions; stream conversion buffers entire response
  • Line ~76: request.extensions = rebuilt.extensions replaces caller extensions instead of merging. claude_cache_client.py got this right ({**rebuilt.extensions, **request.extensions} with a comment explaining why losing flags is dangerous). Codex client should do the same.
  • _convert_stream_to_response() buffers the full SSE stream in memory and returns a fake httpx.Response whose headers still claim content-type: text/event-stream / possibly content-encoding from the original — copying response.headers verbatim onto a JSON body is fragile; strip transfer-related headers and set content-type: application/json.
2. claude_cache_client.py — _get_jwt_age_seconds 'exp' fallback guesses

Lines ~150-160: when only exp is present, age is computed as TOKEN_MAX_AGE_SECONDS - time_until_exp, i.e. assumes all tokens live exactly 3600s. For longer-lived tokens this causes premature refresh storms; for shorter ones it misses expiry. Prefer comparing exp - now < REFRESH_BUFFER directly instead of synthesizing an "age".

3. version_checker.py — _version_tuple cannot parse pre/post-release versions

tuple(int(x) for x in version_str.split('.')) returns None for 1.2.3rc1 or 1.2.3.post1, silently disabling update notification. Use packaging.version.Version (already a transitive dependency).

4. http_utils.py — create_client() ignores its retry_status_codes parameter

Lines ~207-228: parameter accepted, documented by a TODO, never used — misleading API surface. Either implement RetryingClient(httpx.Client) or drop the parameter.

5. config.py — normalize_command_history() checks if \"pytest\" in sys.modules: return

Production code special-casing the test runner is an anti-pattern; tests should patch/inject instead. Same file: import datetime, import os, import configparser re-imported inside multiple function bodies despite top-level imports.

6. reopenable_async_client.py — is_closed race & build_request churn

is_closed reads _is_closed without the asyncio lock (benign but inconsistent with the rest of the class), and build_request() constructs and tears down a full httpx.Client (TLS context and all) per call when closed — expensive; a plain httpx.Request(...) construction would do.

7. models_dev_parser.py — blocking network call in constructor

ModelsDevRegistry.__init__ performs a synchronous 10s-timeout HTTP fetch. Any caller on the event loop (TUI pickers) freezes the UI for up to 10s. Provide an async factory or fetch lazily/cached.

8. callbacks.py — _trigger_callbacks_sync returns None for async callbacks in async contexts

Lines ~243-258: when a sync trigger meets a coroutine while a loop is running, it logs a warning and appends None — the callback silently never runs. Hooks documented as "accept sync or async functions" (CONTRIBUTING table includes sync-triggered hooks like load_models_config) will mysteriously no-op if a plugin makes them async. Consider asyncio.run_coroutine_threadsafe when on a worker thread, or document loudly which hooks must be sync.

Filed by Zen Reviewer A (code-puppy-60635a)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Separate the eight findings into focused changes and inspect the referenced functions in chatgpt_codex_client.py, claude_cache_client.py, version_checker.py, http_utils.py, config.py, reopenable_async_client.py, models_dev_parser.py, and callbacks.py. Compare the Codex request handling with claude_cache_client.py and locate existing pytest coverage before changing behavior. Done means each reported issue has a focused fix or documented decision, with relevant tests passing.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend, networking, performance, testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.