Skip to content

Attribute Codex sessions to their model from thread settings - #6478

Open
dalmasluca wants to merge 3 commits into
basecamp:quattrofrom
dalmasluca:codex-model-attribution
Open

Attribute Codex sessions to their model from thread settings#6478
dalmasluca wants to merge 3 commits into
basecamp:quattrofrom
dalmasluca:codex-model-attribution

Conversation

@dalmasluca

Copy link
Copy Markdown

Summary

Fixes the generic codex model bucket in codex_usage_scanner.py by attributing native Codex session tokens to their real model.

Two issues caused tokens to fall into a catch-all codex bucket:

  1. Newer sessions record the model in thread_settings_applied (not turn_context), so the model was never picked up.
  2. Token counts logged before the first model event were assigned to the default codex model, even when the session later revealed its model.

Both are fixed: the scanner now reads thread_settings_applied.model, and a pre-pass seeds current_model with the first model a session records.

Verified against real sessions: the codex bucket disappears and all tokens land on the actual models (e.g. gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.4...).

Notes

  • Authored by opencode (an AI coding assistant) on behalf of the reporter.
  • This work was done by me (the assistant).

Tests

./test/shell.d/model-usage-codex-scanner-test.sh

Copilot AI review requested due to automatic review settings August 1, 2026 09:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Attributes native Codex token usage to session models rather than the generic codex bucket.

Changes:

  • Pre-scans sessions for their first model event.
  • Handles newer thread_settings_applied events.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Suppressed comments (2)

shell/plugins/model-usage/scripts/codex_usage_scanner.py:212

  • thread_settings_applied exposes its model directly on the event payload, but this reads a nested thread_settings.model. For newer sessions that omit turn_context, the pre-pass therefore keeps current_model as codex, so the generic bucket this PR is intended to remove remains. Read payload.model first (retaining the nested lookup only as a compatibility fallback).
          if payload.get("type") == "thread_settings_applied":
            current_model = model_name((payload.get("thread_settings") or {}).get("model") or current_model)

shell/plugins/model-usage/scripts/codex_usage_scanner.py:234

  • The normal scan repeats the same incorrect nesting: native thread_settings_applied records put model directly in payload, not under payload.thread_settings. As written, later model events are ignored and token counts continue to use the seeded or generic model.
            if payload.get("type") == "thread_settings_applied":
              current_model = model_name((payload.get("thread_settings") or {}).get("model") or current_model)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +197 to +201
try:
# A session may log token counts before its first model event. Read the
# first model the file records so those early counts land on the real
# model instead of a generic "codex" bucket.
with path.open(errors="replace") as handle:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in acc7251. The new rollout-thread.jsonl fixture exercises exactly these two cases: a token_count precedes the first model event (line 49, so the pre-pass must skip token counts and keep scanning), and the only model event is an event_msgthread_settings_applied with a direct model field (line 50, no turn_context at all). The asserts then check the early token count lands on gpt-thread and that no generic codex bucket is left behind. The same fixture drives the turn_context pre-pass path from the primary rollout, and the pi-router fixture asserts provider-strict filtering (47a7f0c).

Copilot AI review requested due to automatic review settings August 1, 2026 09:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 1, 2026 10:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@dalmasluca

Copy link
Copy Markdown
Author

Addressed the review comment plus a follow-up edge case (commit 47a7f0c):

  • pi sessions are now attributed to Codex strictly by provider == "openai-codex", dropping the api.startswith("openai-codex") fallback. A third-party router connected in pi agent that serves the same gpt models — even one presenting an openai-codex-style api — no longer lands on the Codex screen.
  • This matches the existing provider-only attribution for Kimi (kimi-coding) and Grok (xai).
  • Regression test: a pi session from third-party-router with model gpt-5.6-sol and api openai-codex-responses is ignored, and leaves no gpt-5.6-sol bucket. All scanner tests pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants