Skip to content

Add comprehensive mapper functions for wire format conversion#2

Merged
amavashev merged 7 commits into
mainfrom
claude/verify-typescript-client-spec-XOTI1
Mar 13, 2026
Merged

Add comprehensive mapper functions for wire format conversion#2
amavashev merged 7 commits into
mainfrom
claude/verify-typescript-client-spec-XOTI1

Conversation

@amavashev
Copy link
Copy Markdown
Contributor

Summary

This PR adds a complete set of typed mapper functions to convert between camelCase TypeScript interfaces and snake_case wire format for all API operations. This enables developers to use strongly-typed request/response objects while maintaining compatibility with the wire protocol.

Key Changes

New Response Mappers (snake_case → camelCase)

  • commitResponseFromWire() — parse commit responses with status, charged, released, and balances
  • releaseResponseFromWire() — parse release responses with status and released amount
  • reservationExtendResponseFromWire() — parse extend responses with new expiry time
  • decisionResponseFromWire() — parse decision responses (ALLOW/ALLOW_WITH_CAPS/DENY)
  • eventCreateResponseFromWire() — parse event creation responses with event ID
  • reservationDetailFromWire() — parse full reservation details with all metadata
  • reservationSummaryFromWire() — parse reservation summaries for list operations
  • reservationListResponseFromWire() — parse paginated reservation lists
  • balanceResponseFromWire() — parse balance queries with pagination support

New Request Mappers (camelCase → snake_case)

  • reservationCreateRequestToWire() — convert reservation creation requests
  • commitRequestToWire() — convert commit requests with metrics
  • releaseRequestToWire() — convert release requests with optional reason
  • reservationExtendRequestToWire() — convert extend requests
  • decisionRequestToWire() — convert decision/preflight check requests
  • eventCreateRequestToWire() — convert event creation requests

Helper Functions

  • subjectFromWire() and subjectToWire() — handle subject object conversion with all optional fields (tenant, workspace, app, workflow, agent, toolset, dimensions)
  • actionFromWire() and actionToWire() — handle action object conversion with optional tags

Documentation & Examples

  • Updated README with comprehensive examples showing typed mapper usage for all operations
  • Added examples for programmatic client usage with request/response mappers
  • Clarified streaming lifecycle: commit() and release() now auto-stop the heartbeat
  • Added examples for querying balances, reservations, and using release/extend operations

Testing

  • Added 527 lines of comprehensive test coverage for all new mappers
  • Tests verify full wire response conversion, optional field handling, and edge cases
  • Tests confirm request mappers properly strip undefined fields and convert camelCase to snake_case

Validation

  • Added validateExtendByMs() function to validate extend duration (1–86400000 ms)
  • Updated streaming and lifecycle modules to use new validation

Exports

  • Exported all new mapper functions from main index.ts for public API access
  • Organized exports by category (request mappers, response mappers)

Implementation Details

  • Mappers use stripUndefined() helper to remove undefined fields from wire format, keeping payloads clean
  • Subject and action objects support partial initialization (only required fields must be present)
  • Balance response mapper handles missing balances array gracefully (defaults to empty array)
  • All mappers preserve type safety through TypeScript's type system

https://claude.ai/code/session_01Sio9KybwwP6J6RYaDJUNNP

claude added 7 commits March 13, 2026 17:00
… compliance

The TypeScript client models were consistent with the protocol spec, but
mapper coverage was incomplete — only reservationCreateResponseFromWire and
metricsToWire existed. This adds all missing request-to-wire and
response-from-wire mappers so typed interfaces can be used end-to-end.
Also adds validateExtendByMs (spec range: 1–86400000) which was missing.

https://claude.ai/code/session_01Sio9KybwwP6J6RYaDJUNNP
Covers all 15 new mapper functions (9 response-from-wire, 6 request-to-wire)
and the new validateExtendByMs validation. Brings mappers.ts from 36% to 90%
statement coverage and validation.ts to 100%.

https://claude.ai/code/session_01Sio9KybwwP6J6RYaDJUNNP
- Programmatic client section now shows typed mapper usage alongside raw wire format
- Added wire-format mappers reference table for all request and response mappers
- Updated decide, events, balances, and reservations sections with mapper examples
- Added release and extend usage examples
- Added balance overdraft/debt fields to query examples

https://claude.ai/code/session_01Sio9KybwwP6J6RYaDJUNNP
The previous design required callers to use `finally { handle.dispose() }` to
stop the heartbeat. In streaming HTTP handlers, the `finally` block runs when
the handler returns the response object, not when the stream actually finishes,
causing the heartbeat to stop while the stream is still active.

Now commit() and release() automatically stop the heartbeat as terminal
operations. dispose() is retained only for stream startup failures where
neither commit nor release applies.

https://claude.ai/code/session_01Sio9KybwwP6J6RYaDJUNNP
In real streaming code, multiple terminal paths can fire concurrently
(onFinish, error handler, abort signal, client disconnect). The handle
now enforces once-only finalization:

- commit() throws CyclesError if already finalized (silent drops hide bugs)
- release() is a silent no-op if already finalized (best-effort by design)
- dispose() is a silent no-op if already finalized
- handle.finalized exposes the current state

This prevents conflicting server-side operations (commit + release on
the same reservation) when multiple error/completion paths race.

https://claude.ai/code/session_01Sio9KybwwP6J6RYaDJUNNP
@amavashev amavashev merged commit acc5c45 into main Mar 13, 2026
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