Repository navigation
@relaycast/sdk: registerOrRotate no longer rotates (409 on existing name); relay CLI still calls it - #512
@relaycast/sdk: registerOrRotate no longer rotates (409 on existing name); relay CLI still calls it#512agent-relay-code[bot] wants to merge 1 commit into
Conversation
…ag mixed-case field collisions registerOrRotate's fail-closed behavior on a name conflict is intentional (strict-identity hardening against silent takeover) and stays as-is, but the thrown error now names agents.recover() as the replacement instead of just repeating the server's generic "already exists" message, so callers upgrading from the old rotating behavior have a clear migration path. decamelizeKeys() now throws when a request object mixes both casings of the same field (e.g. autoJoinGeneral and auto_join_general) instead of letting whichever key enumerates last silently win. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
|
Relayflow: the adversarial review did not pass. This branch is not approved: the flow stopped here and did not mark it ready to merge. Review: PR #512 —
|
@relaycast/sdk: makeregisterOrRotate's fail-closed conflict actionable, and stop silent dual-casing collisionsContext
The ticket reported that
registerOrRotate"no longer rotates" in 9.1.1 and that acaller built against SDK 8.0.7 breaks on upgrade, plus that
registerseemed to"ignore"
auto_join_generalwhile onlyautoJoinGeneralworked.Investigation on this branch found:
registerOrRotate's fail-closed behavior (409name_conflicton an existingname, no silent token rotation) is already the intended, tested contract
in this repo —
src/__tests__/strict-identity.test.tslocks it in explicitly("is a fail-closed compatibility alias on name conflict", "fails closed
without a suffixed-name retry on conflict"). Silently rotating/taking over an
existing agent name on conflict is exactly the identity-spoofing hole the
strict-identity model (
register,recover,takeOver,revokeToken) wasbuilt to close. Reverting to silent rotation would reintroduce that hole and
contradict the committed test suite, so that part of the ticket is not
actionable as "restore rotation" — the other option the ticket offered,
"migrate callers," is the right direction.
auto_join_general/autoJoinGeneralclaim doesn't reproduce as asimple "snake_case is ignored" bug —
decamelizeKeys()already convertseither casing to the correct wire key (
auto_join_general) on its own,verified with a throwaway probe test against the real request path. What
does reproduce is a silent collision: if a caller's options object ends up
with both
autoJoinGeneralandauto_join_general(e.g. from merging alegacy snake_case config with the typed camelCase field), whichever key
enumerates last in the object silently wins — so depending on construction
order, it looks like "only autoJoinGeneral works" or the opposite. Per
CLAUDE.md's "do not introduce mixed-case field fallbacks," the fix is toflag this loudly rather than add precedence/alias rules.
Changes
src/casing.ts:decamelizeKeys()now throws a clear error(
Ambiguous request fields "..." and "..." both map to "...") when twodifferently-cased keys in the same object would collide into one wire field,
instead of letting object key order decide silently.
src/relay.ts:registerOrRotate()still fails closed exactly as before(same
code/retryable/statusCode), but on aname_conflictit nowraises a message that names
agents.recover()as the real replacement,instead of just repeating the server's generic "already exists" message.
This is the actionable form of "migrate callers" available from inside this
repo — the actual external caller (
AgentWorkforce/relay'sagent-relay-mcp.ts) isn't part of this repository.CHANGELOG.md(sdk-typescript): documented both fixes under[Unreleased].Tests
src/__tests__/casing.test.ts: new regression tests for the dual-casingcollision (both key orders) and confirmation that either casing alone still
works.
src/__tests__/strict-identity.test.ts: extended the existingregisterOrRotateconflict test to assertcode/retryable/statusCodeare unchanged and the message now mentions
agents.recover(); thenon-conflict rethrow test now also pins the message is passed through
verbatim.
Ran the full
sdk-typescript,mcp,openclaw, andreactpackage testsuites (all depend on this SDK) plus
tsc --noEmitforsdk-typescriptandmcp— all green.Checks
The checks failed, and there was no time left in the run to check the base commit (base not checked), so it is not known whether this change caused them. This pull request is a draft until someone looks.
What ran (.relayflow/check.sh)
Output on this branch (last 80 lines)
Fixes #493
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.