Skip to content

Add provider audit envelopes and user-input audit metadata#12

Open
Savid wants to merge 6 commits intomasterfrom
refactor/provider-audit-cutover
Open

Add provider audit envelopes and user-input audit metadata#12
Savid wants to merge 6 commits intomasterfrom
refactor/provider-audit-cutover

Conversation

@Savid
Copy link
Copy Markdown
Member

@Savid Savid commented Mar 29, 2026

Summary

  • Add AuditEnvelope type to all message types, capturing provider-native event payloads at the SDK boundary for downstream audit/debugging
  • Propagate audit metadata through requestUserInput parsing and response serialization
  • Add public NewAuditEnvelope constructor matching the OpenRouter SDK signature for cross-SDK consistency
  • Add audit envelope parse-time attachment tests
  • Fix test_examples.sh to handle examples with their own go.mod (nested modules)

Test plan

  • go test ./... passes
  • make test-integration passes
  • Audit envelope tests verify attachment on AssistantMessage, SystemMessage, ResultMessage
  • Raw wire data preservation test confirms unknown fields survive in payload
  • Public constructor round-trip and marshal error tests
  • test_examples.sh correctly runs custom_logger (nested module example)

🤖 Generated with Claude Code

Savid and others added 6 commits March 29, 2026 13:06
Expose provider-native audit envelopes on surfaced message types and propagate audit metadata through requestUserInput parsing and response serialization.

This keeps provider event capture SDK-owned while preserving the existing normalized public surface for downstream consumers.
Expose NewAuditEnvelope(eventType, subtype, payload) as a public API
matching the OpenRouter SDK signature, enabling consumers to construct
audit envelopes from typed payloads. The existing private parse-time
constructor remains for raw wire data attachment.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Add WithMaxTurns option with exec CLI flag and app-server protocol
support across both backends. Add MultiSelect field to user input
Question struct with camelCase/snake_case parsing.
The audit envelope payload was previously produced by re-marshaling the
decoded map[string]any, which loses byte-level details like number
formatting (1e+06 vs 1000000), key ordering, and whitespace from the
original wire data. This is problematic for audit/provenance use cases
where exact reproduction of the provider response matters.

Changes:
- Add internal/message/raw_json.go with AnnotateRawJSON, extractRawJSON,
  and stripRawJSON helpers that thread original bytes through decoded maps
  via a hidden sentinel key.
- Widen Parse() signature from map[string]any to any, accepting []byte
  and json.RawMessage directly so callers can pass raw wire data.
- Thread raw line bytes through the JSON-RPC notification path
  (RPCNotification.Raw field, toNotification parameter) and annotate
  events in both AppServerAdapter and CLITransport before dispatch.
- Update sessions.go GetSessionMessages to pass raw line bytes to Parse.
- newAuditEnvelope now prefers the annotated original bytes, falling back
  to re-marshal only when raw bytes are unavailable.
- Add test verifying audit payloads preserve original JSON bytes verbatim.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…Message

Extend ResultMessage with session-level metadata fields returned by the
Codex turn-completed event: stop_reason (optional), duration_ms,
num_turns, and total_cost_usd (optional). Parse these fields from the
raw event map in parseCodexTurnCompleted and add tests covering full
field presence, the Parse entry point, and missing optional field
defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
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