Skip to content

feat(providers): capture user prompts from Pi and Codex#117

Open
ya-nsh wants to merge 1 commit into
mainfrom
feat/prompt-capture-pi-codex
Open

feat(providers): capture user prompts from Pi and Codex#117
ya-nsh wants to merge 1 commit into
mainfrom
feat/prompt-capture-pi-codex

Conversation

@ya-nsh

@ya-nsh ya-nsh commented Apr 19, 2026

Copy link
Copy Markdown
Owner

What

Extends prompt capture beyond Claude Code to Pi and Codex, so the Receipts feature surfaces real prompt text for those users instead of empty line items.

Why

Before this change, `tokenleak receipts` on a machine that only uses Pi or Codex logs yields zero captured prompts — every cost rolls into Service Fees. The underlying log formats already carry the user turn data; the parsers just weren't reading it.

How

Shared — hoist `MAX_PROMPT_CHARS = 2_000` to `packages/core/src/constants.ts` and re-export from `@tokenleak/core`. Claude Code now imports the shared constant.

Pi (easy)

  • New `extractPiUserPrompt` handles both `role: 'user'` string `content` and the `[{type: 'text', text: …}]` array form (same shape as Claude).
  • `PiProvider.load` tracks `lastUserPrompt` per session file and attaches it to the next assistant usage record before clearing.

Codex (medium — stateful linking)

  • Codex writes user turns twice: noisy `response_item` blocks and clean `event_msg` with `payload.type === 'user_message'`. Use the cleaner `event_msg` source.
  • `CodexProvider.load` adds `lastUserPrompt` tracking parallel to Pi's pattern. The prompt attaches to the next token_count or response event and clears.
  • Updated fixture `codex-current/.../session-current.jsonl` now has a `user_message` record preceding the first token_count.

Test Coverage

  • `pi.test.ts` — new case: first event's `prompt === 'Hello'` (from fixture line 2).
  • `codex.test.ts` — two new cases: first event's `prompt` matches the fixture user_message; second event has no prompt (no preceding user_message).

Registry package: 162 tests (was 159), 0 failures. Full repo: 785 pass.

End-to-end: `tokenleak receipts --codex --format json | jq '.lines[0].samplePrompts'` now returns real user prompts on my dev machine with live Codex data.

Out of scope

  • OpenCode — storage schema (SQLite + JSON) has no content column. Requires upstream change.
  • Cursor — CSV usage logs have no prompt column. Blocked on Cursor's own data export.

Checklist

  • All new code has unit tests
  • Edge cases are covered (no preceding user turn, multiple turns in a session)
  • Error paths are tested (malformed records skipped without affecting neighbours)
  • Types are strict (no `any`)
  • No dead code or console.log left in
  • README or JSDoc updated if public API changed (new `MAX_PROMPT_CHARS` export documented via JSDoc)

Before this change only Claude Code surfaced captured prompts to the
Receipts feature, so non-Claude users saw an empty receipt no matter
how much they spent. Extend prompt capture to two more providers.

Shared
- Hoist the 2_000-char cap to `MAX_PROMPT_CHARS` in
  packages/core/src/constants.ts and re-export it from @tokenleak/core
  so provider parsers share a single truth about prompt length.
- Claude Code now imports the shared constant instead of defining its
  own local copy.

Pi (easy — data was already there)
- New `extractPiUserPrompt` parses JSONL records with `role: 'user'`
  and handles both string `content` and `[{type: 'text', text: ...}]`
  array form, matching the Claude shape.
- `PiProvider.load` tracks `lastUserPrompt` through each session file
  and attaches it to the next assistant usage record before clearing.
- Test covers the fixture's user/assistant pair: first event's
  `prompt` now equals the preceding user message.

Codex (medium — needed stateful linking)
- Codex JSONL writes user turns twice: a `response_item` with mixed
  boilerplate and a cleaner `event_msg` with `payload.type ===
  'user_message'` whose `payload.message` is the raw typed input.
  New `extractCodexUserPrompt` reads the cleaner event_msg source.
- `CodexProvider.load` adds `lastUserPrompt` tracking parallel to Pi's
  pattern; the prompt attaches to the next token_count or response
  event and then clears.
- Fixture `codex-current/.../session-current.jsonl` gains a
  user_message record to exercise the linkage; tests assert the first
  event has the expected prompt and the second has none.
@coderabbitai

coderabbitai Bot commented Apr 19, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@ya-nsh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 23 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 25 minutes and 23 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f525c49b-cfac-4233-bb41-81ff986f8f12

📥 Commits

Reviewing files that changed from the base of the PR and between c3bb5d1 and 97ec63a.

📒 Files selected for processing (8)
  • packages/core/src/constants.ts
  • packages/core/src/index.ts
  • packages/registry/src/__fixtures__/codex-current/sessions/2026/03/12/session-current.jsonl
  • packages/registry/src/providers/claude-code.ts
  • packages/registry/src/providers/codex.test.ts
  • packages/registry/src/providers/codex.ts
  • packages/registry/src/providers/pi.test.ts
  • packages/registry/src/providers/pi.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/prompt-capture-pi-codex

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

1 participant