Repository navigation
fix(cave): read the familiar roster in Cave's contract spelling - #342
Merged
Merged
Conversation
The discovered and managed transports parsed GET /api/client/v1/familiars
with the earlier snake_case field names (`display_name`, `last_seen`,
`active_sessions`). A real Cave has served the documented camelCase roster
(`displayName`, `lastSeenAt`, `activeSessions`) since its canonical read
projections landed, so `credentialStatus()` and `familiars()` refused
every non-empty roster with `invalid_response` ("display_name must be a
non-empty string"). A freshly exchanged credential therefore read as
broken the moment the Cave had one familiar. The unit tests fed the
parser an empty roster, which is how this escaped.
Read the contract spelling first and keep the snake_case spelling as a
fallback for an older Cave. The record still leaves the parser in the
wire type's spelling, so the public types and `toFamiliar` are unchanged.
`listFamiliars()` and the other canonical reads were already correct.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Observable behaviour
Against a real Cave with at least one familiar,
credentialStatus()on a discovered client fails withinvalid_response("familiar.display_name must be a non-empty string") right after a successful exchange, andfamiliars()fails the same way. The managed native transport'sfamiliarsread shares the parser.listFamiliars()and the other canonical reads were already correct.The discovered and managed transports parse
GET /api/client/v1/familiarswith the earlier snake_case field names (display_name,last_seen,active_sessions), while Cave has served the documented camelCase roster (displayName,lastSeenAt,activeSessions;docs/api/client-v1.md) since its canonical read projections landed. The unit tests fed this parser an empty roster, which is how the mismatch escaped.Change
parseFamiliarreads the contract spelling first and keeps the snake_case spelling as a fallback for an older Cave. The record still leaves the parser in the wire type's spelling, soCaveFamiliarWire,CaveFamiliar,toFamiliarand every public type are unchanged.Compatibility
Patch for
@opencoven/cave-client(changeset included). No API change. A custom transport returning the snake_case roster keeps working.Validation
tests/cave-discovery-pairing.spec.ts: after a discovered exchange, the documented camelCase roster (one entry with every optional field, one with only the guaranteed three) makescredentialStatus()reportvalid/chat:readandfamiliars()return the mapped records with neither spelling leaking; a roster entry with no name under either spelling is stillinvalid_response. The test fails onmain.corepack pnpm@10.34.0 verify: typecheck, build, 92 test files (3155 tests) passed; the remaining stages were running at the time of opening and CI runs the same gate.credentialStatus(),listFamiliars()andlistConversations()all succeed; without this changecredentialStatus()fails as described.Release implications
Pairs with #341: an app on the discovered client needs both to work against a current Cave. OpenCoven/mamase (which vendors the SDK) is blocked on both; see OpenCoven/mamase#126.
🤖 Generated with Claude Code