Skip to content

fix: preserve user-defined keys nested below preserved tiers#95

Merged
PennyroyalTea merged 2 commits into
elevenlabs:mainfrom
aicayzer:fix/preserve-nested-user-keys
Jun 15, 2026
Merged

fix: preserve user-defined keys nested below preserved tiers#95
PennyroyalTea merged 2 commits into
elevenlabs:mainfrom
aicayzer:fix/preserve-nested-user-keys

Conversation

@aicayzer

Copy link
Copy Markdown
Contributor

Fixes #93, fixes #94.

Problem

The PRESERVE_CHILD_KEYS preservation in toCamelCaseKeys()/toSnakeCaseKeys() is exactly one level deep. Two real bug families live one level lower:

Before this change:

{"dynamicVariables":{"dynamic_variable_placeholders":{"transactionId":"txn_1"}}}   // wrapper stripped by the SDK, names mangled
{"queryParamsSchema":{"properties":{"userId":{...}},"required":["user_id"]}}       // schema inconsistent

After:

{"dynamicVariables":{"dynamicVariablePlaceholders":{"transaction_id":"txn_1"}}}
{"queryParamsSchema":{"properties":{"user_id":{...}},"required":["user_id"]}}

Fix

  • The 'names-only' mode now consults PRESERVE_CHILD_KEYS: a preserved-tier key nested directly inside another preserved tier (e.g. dynamic_variable_placeholders under dynamic_variables) is converted itself while its children are preserved. Mirrored in toSnakeCaseKeys, which fixes the pull direction too
  • Added dynamic_variable_placeholders/dynamicVariablePlaceholders and properties to the set. properties children are user-defined JSON-schema property names everywhere in this API (checked every properties field in the SDK's types; all are user-keyed Records), and because normal-mode recursion re-applies the set at every level, nested request_body_schema objects are covered at any depth

Behaviour is unchanged for flat dynamic_variables maps (test configs), request_headers, language_presets, data_collection, model_usage and nodes/edges; the existing suite covers these and still passes.

Known limitation: a user-defined key that exactly matches a preserved-tier name (e.g. a data_collection item literally named properties, or a workflow node named dynamic_variables) is now treated as a nested tier inside preserved contexts. That's inherent to any name-based preservation heuristic; flagging it here for the record.

Tests

13 new tests: 7 transform-level (utils.test.ts) and 6 through the real API functions with mock clients (casing.test.ts), covering push, pull and round-trip for both families. All 6 seam tests fail on main without the fix. Full suite 215/215, lint and build clean.

Note: built on main independently of #92 (which adds path_params_schema to the same set); happy to rebase whichever lands second.

- names-only preservation now handles a preserved-tier key nested inside
  another preserved tier: the key itself is converted while its children
  are preserved
- add dynamic_variable_placeholders and properties to PRESERVE_CHILD_KEYS
- fixes agents/tools push silently dropping all dynamic_variable_placeholders
  changes (the snake_case wrapper key was stripped by the SDK request
  serializer before reaching the API)
- fixes query_params_schema and request_body_schema property names being
  camelCased on push with required[] left referencing the old names, and
  the mirrored conversion on pull
# Conflicts:
#	src/__tests__/casing.test.ts
#	src/shared/utils.ts
@PennyroyalTea PennyroyalTea merged commit fccab96 into elevenlabs:main Jun 15, 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

2 participants