Skip to content

Keep playground form args marker-free - #4257

Closed
sxlijin wants to merge 3 commits into
canaryfrom
agent/b-814-cast-json-type
Closed

sxlijin wants to merge 3 commits into
canaryfrom
agent/b-814-cast-json-type

Conversation

@sxlijin

@sxlijin sxlijin commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Keep schema-driven form and raw editor state as ordinary JSON.
  • Cast uniquely matched class and enum values only in transient execution payloads.
  • Preserve unannotated runtime fallback for ambiguous, invalid, and unsupported values.

Why

The dynamic args form currently writes $baml transport markers into user-visible JSON. The parameter and type schemas already identify most values, so marker generation belongs at the execution boundary rather than editor state.

Validation

  • pnpm --filter @b/pkg-playground test (132 tests)
  • pnpm --filter @b/pkg-playground typecheck
  • pnpm --filter app-vscode-webview typecheck
  • pnpm --filter app-vscode-webview test:unit:run (21 tests)
  • pnpm run build:wasm
  • pnpm --filter app-vscode-webview build

Linear: B-814

Before / after

Before — $baml markers in editor state

At the exact PR base (2960e7a), the TypeScript2 playground's raw editor persists class and enum transport markers.

Before: raw playground arguments include class and enum $baml markers

After — marker-free editor with execution-boundary casting

At the exact PR head (c4ec9b2), the same fixture and viewport keep ordinary JSON in the raw editor; the successful graph input renders user.Person, demonstrating that the known type is applied only at the execution boundary.

After: raw playground arguments are plain JSON while the successful graph input is typed as user.Person

@linear

linear Bot commented Jul 28, 2026

Copy link
Copy Markdown

B-814

@vercel

vercel Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jul 28, 2026 9:54pm
promptfiddle Ready Ready Preview, Comment Jul 28, 2026 9:54pm
promptfiddle2 Ready Ready Preview, Comment Jul 28, 2026 9:54pm

Request Review

@sxlijin
sxlijin marked this pull request as ready for review July 28, 2026 21:18
@coderabbitai

coderabbitai Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Schema-directed argument casting

Layer / File(s) Summary
Defaults, casting, and reconciliation semantics
typescript2/pkg-playground/src/args-form-model.ts, typescript2/pkg-playground/src/args-form-model.test.ts, typescript2/pkg-playground/src/worker-protocol.ts
Defaults and reconciled values remain marker-free; castArgsToKnownTypes adds transient markers for uniquely matched schemas, with coverage for enums, classes, unions, containers, legacy markers, and invalid values.
Form editing and execution wiring
typescript2/pkg-playground/src/ArgsForm.tsx, typescript2/pkg-playground/src/ExecutionPanel.tsx
Enum and class editors update plain JSON, while preview and function execution cast arguments before encodeRunArgs.
Raw-state and hydration expectations
typescript2/app-vscode-webview/src/ExecutionPanel.strict-mode.test.tsx
Raw argument assertions now expect marker-free enum, nested class, recursive class, seeded, and hydrated values.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ArgsForm
  participant ExecutionPanel
  participant castArgsToKnownTypes
  participant encodeRunArgs
  User->>ArgsForm: Edit enum or class argument
  ArgsForm-->>ExecutionPanel: Marker-free JSON state
  ExecutionPanel->>castArgsToKnownTypes: Parse and schema-cast arguments
  castArgsToKnownTypes-->>ExecutionPanel: Transiently annotated arguments
  ExecutionPanel->>encodeRunArgs: Encode cast arguments
Loading

Suggested reviewers: rossirpaulo

Poem

I’m a bunny with JSON, plain and bright,
No wire markers hiding from sight.
At run time they bloom, then swiftly encode,
While enums and classes stay light in the form.
Hop, hop—typed arguments take flight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: keeping playground form and raw args marker-free.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/b-814-cast-json-type

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@vercel
vercel Bot temporarily deployed to Preview – beps July 28, 2026 21:19 Inactive
@sxlijin

sxlijin commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95df3940fd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

new Set(),
strictObject,
);
if (fieldCast === CAST_FAILED) return CAST_FAILED;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the known class cast when a raw child cannot be cast

When a known class contains a media/unsupported field, or a valid deep schema whose extraction tail was cut to unsupported, that child's cast always returns CAST_FAILED and this line discards the cast for the entire class. The encoder consequently serializes the marker-free object as a map rather than a classValue, so otherwise valid playground calls using classes with raw-editor fields fail with an "expected instance, got map" error. Outside strict union disambiguation, preserve the original child value while retaining the known parent class annotation.

Useful? React with 👍 / 👎.

strictObject,
);
if (entryCast === CAST_FAILED) return CAST_FAILED;
cast[key] = entryCast;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve __proto__ entries when rebuilding maps

When a map<string, T> argument contains the valid JSON key __proto__, assigning it into the ordinary {} accumulator invokes the inherited prototype setter instead of creating an own property. Since encodeRunArgs later enumerates own entries, that map entry silently disappears from the execution payload. Build the result with Object.fromEntries, a null-prototype object, or an explicit own-property definition.

Useful? React with 👍 / 👎.

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 July 28, 2026 21:27 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
typescript2/pkg-playground/src/ExecutionPanel.tsx (1)

2237-2241: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The adjacent comment now understates what raw mode does.

Line 2229 still claims raw mode is "an exact escape hatch"; with this change raw-mode args are also schema-cast before encoding (only reconciliation is skipped). Worth clarifying so the next reader doesn't assume raw bytes are byte-for-byte what the user typed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@typescript2/pkg-playground/src/ExecutionPanel.tsx` around lines 2237 - 2241,
The comment near the argument encoding flow should no longer describe raw mode
as an “exact escape hatch.” Update it to state that raw mode skips
reconciliation but still casts arguments through castArgsToKnownTypes before
encodeRunArgs, so it does not guarantee byte-for-byte preservation of user
input.
typescript2/pkg-playground/src/args-form-model.test.ts (1)

319-434: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the strict-union and required-field-omission paths.

The suite exercises unique/ambiguous/invalid cases well, but two behaviors that decide whether a payload gets annotated are untested: strictObject union matching (surplus class keys must make a union variant fail) and the class branch that fails the cast when a missing field is not omittable (schemaAllowsOmission). Both are the difference between an annotated payload and a silent fallback, so a regression there would be invisible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@typescript2/pkg-playground/src/args-form-model.test.ts` around lines 319 -
434, Extend the castArgsToKnownTypes tests to cover strictObject union matching,
verifying that surplus class keys reject that union variant and leave the
payload unannotated, and cover the required-field omission path where
schemaAllowsOmission is false, verifying the class cast fails and falls back
without annotation. Add focused cases alongside the existing union and
class-casting tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@typescript2/pkg-playground/src/args-form-model.test.ts`:
- Around line 319-434: Extend the castArgsToKnownTypes tests to cover
strictObject union matching, verifying that surplus class keys reject that union
variant and leave the payload unannotated, and cover the required-field omission
path where schemaAllowsOmission is false, verifying the class cast fails and
falls back without annotation. Add focused cases alongside the existing union
and class-casting tests.

In `@typescript2/pkg-playground/src/ExecutionPanel.tsx`:
- Around line 2237-2241: The comment near the argument encoding flow should no
longer describe raw mode as an “exact escape hatch.” Update it to state that raw
mode skips reconciliation but still casts arguments through castArgsToKnownTypes
before encodeRunArgs, so it does not guarantee byte-for-byte preservation of
user input.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d0dc3607-403b-4f0a-892c-6116c773bf46

📥 Commits

Reviewing files that changed from the base of the PR and between 2960e7a and 95df394.

📒 Files selected for processing (6)
  • typescript2/app-vscode-webview/src/ExecutionPanel.strict-mode.test.tsx
  • typescript2/pkg-playground/src/ArgsForm.tsx
  • typescript2/pkg-playground/src/ExecutionPanel.tsx
  • typescript2/pkg-playground/src/args-form-model.test.ts
  • typescript2/pkg-playground/src/args-form-model.ts
  • typescript2/pkg-playground/src/worker-protocol.ts

@vercel
vercel Bot temporarily deployed to Preview – beps July 28, 2026 21:29 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps July 28, 2026 21:33 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 July 28, 2026 21:41 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle July 28, 2026 21:54 Inactive
@sxlijin sxlijin closed this Jul 29, 2026
@sxlijin
sxlijin deleted the agent/b-814-cast-json-type branch July 29, 2026 04:41

This branch was previously deployed

3 inactive deployments
Preview – promptfiddle — c4ec9b29 Deployed Jul 28, 2026 by vercel[bot]
Preview – promptfiddle2 — c4ec9b29 Deployed Jul 28, 2026 by vercel[bot]
Preview – beps — c4ec9b29 Deployed Jul 28, 2026 by vercel[bot]
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