#16129

agent-usage-codex: Codex usage from opencode v2 is never counted (collector still reads only the legacy `message` table)

Openvaldelinopened 22h ago

System details

Intel Core i5-10210U, Intel CometLake-U GT2 (UHD Graphics), Omarchy 4.0.6-1, opencode v2.1.1, codex-cli 0.163.0

What's wrong?

omarchy-agent-usage-codex never counts Codex usage that runs through opencode v2, so the Agents panel shows a permanently empty "today" and an empty week while the rate-limit meters show the plan is being consumed (weekly meter at 16%).

Cause

scan_opencode_sessions() only reads the legacy v1 table and the v1 row shape:

conn.execute(
  "SELECT session_id, data FROM message"
  " WHERE data LIKE '%\"role\"%:%\"assistant\"%'"
  " AND ... json_extract(data, '$.providerID') END = 'openai'"
)

opencode v2 writes to session_message instead, and the shape differs:

  • the role is the type column ('assistant'), not data.role;
  • provider and model are nested: data.model.providerID and data.model.id (plus variant);
  • the session id is a real session_id column;
  • data.tokens keeps the old shape (input, output, reasoning, cache.read, cache.write) and data.time.created is still ms.

Example session_message.data (content removed):

{
  "agent": "build",
  "model": { "id": "gpt-5.6-terra", "providerID": "openai", "variant": "medium" },
  "tokens": { "input": 1180, "output": 206, "reasoning": 40, "cache": { "read": 506368, "write": 0 } },
  "time": { "created": 1792512097746, "completed": 1792512103374 }
}

The Claude collector got exactly this treatment in #14049; the Codex collector was left on the legacy table only (still true on quattro at bin/omarchy-agent-usage-codex:396).

Evidence from ~/.local/share/opencode/opencode.db on this machine

  • message (legacy): last assistant row 2026-10-12 09:52:38; zero openai rows after that date.
  • session_message (v2): openai / gpt-5.6-terra assistant rows every day through 2026-10-20.
dayv2 assistant rowstokens
2026-10-1314726,639,774
2026-10-1421132,154,122
2026-10-1517128,911,255
2026-10-1610316,916,765
2026-10-195315,298,488
2026-10-203716,598,650

Result in ~/.local/state/omarchy/agents/usage/codex.json before any fix:

{"todayPrompts":0,"todayTotalTokens":0,"activeDays":11,
 "activeDates":["...","2026-10-10","2026-10-12"],
 "totalPrompts":1453,"limits":[{"label":"5h window"},{"label":"Weekly (7-day)","percent":0.16}]}

totalPrompts is frozen at the pre-migration value and activeDates stops at 2026-10-12, while the meters still prove the subscription is in use. Adding the v2 scan against the same database gives totalPrompts: 2169, activeDays: 17, and the per-day token totals above.

Deduplication caveat

opencode dual-writes during/after the migration: 16,771 of 19,647 session_message ids also exist in message. Any scan that reads both tables and sums per row counts those messages twice — summing message + session_message naively on this DB yields 3,613 prompts instead of 2,169. The safe shape is to treat session_message as authoritative and add only legacy rows whose id is absent from it:

SELECT id, session_id, data FROM message
WHERE json_extract(data, '$.providerID') = 'openai'
  AND id NOT IN (SELECT id FROM session_message)

That union is 2,185 assistant rows here (2,169 of them carry non-zero tokens, which is what the collector counts). Worth checking the same assumption in the Claude collector's current message + session_message pair (bin/omarchy-agent-usage-claude:682-684), since it keys the two sources separately (opencode: vs opencode-v2:) without deduplicating ids — I could not confirm its output locally because that collector returns early while Claude is unauthenticated.

Steps to reproduce

  1. Use opencode v2 with the openai provider (ChatGPT/Codex subscription login) for a few prompts on a day after the v2 migration.
  2. omarchy agent usage update --force
  3. Open the Agents panel, or read ~/.local/state/omarchy/agents/usage/codex.json: today's prompts/tokens are 0 and the week stays empty, even though the 5h/weekly meters move.

Expected

opencode v2 openai messages are counted like the legacy v1 rows: todayPrompts, todayTotalTokens, recentDays, activeDates and modelUsage reflect them.

(The separate transient account/read timeout that blanks the meters is already reported in #14298; this report is only about the missing local usage.)

Activity

0

No activity yet.