Skip to content

feat: add --context-variables-json for typed preview context variables - #483

Open
nico-pappagianis wants to merge 4 commits into
mainfrom
feat/preview-ctx-var-agents-alignment
Open

feat: add --context-variables-json for typed preview context variables#483
nico-pappagianis wants to merge 4 commits into
mainfrom
feat/preview-ctx-var-agents-alignment

Conversation

@nico-pappagianis

Copy link
Copy Markdown
Collaborator

What

Adds a new --context-variables-json flag to sf agent preview and sf agent preview start so callers can send typed context variables (Boolean, Number, Object, List, Json) to the preview API, not just Text.

Why

--context-variables (the existing Name=Value flag) hard-codes every value as type Text. A boolean-gated route (for example available when @variables.probeGate == True) never opens, because the runtime compares the string "True" against the boolean True. See W-24014400.

The new flag matches the preview API's own Variable schema (a discriminated union keyed on type), so a value is sent with the correct JSON type on the wire.

How

  • New contextVariablesJsonFlag in src/flags.ts, plus parseContextVariablesJson (validates JSON shape and that each value matches its declared type) and mergeContextVariables (merges the text-form and JSON-form variables; on a duplicate name the JSON entry wins, keeping the text entry's position).
  • Both agent:preview and agent:preview:start accept both flags together.
  • Deliberately no delimiter on the JSON flag, so commas inside a List/Object/JSON value are safe (unlike --context-variables, which splits on ,).
  • Help text and command snapshot updated.

Notes

Tests

yarn test green (30 flags tests, including parseContextVariablesJson and mergeContextVariables coverage).

--context-variables can only send Text, so a boolean-gated route
(available when @variables.x == True) never opens: the runtime compares
the string "True" against boolean True. Add --context-variables-json,
which takes a JSON array of typed variables ({ name, type, value })
matching the preview API's Variable schema, so Boolean/Number/Object/
List/Json values reach the wire with the correct type.

The JSON flag has no comma delimiter, so List/Object values (and any
comma-bearing value) are safe, unlike --context-variables. Both flags can
be combined; on a duplicate name the JSON entry wins. Each entry is
validated at parse time: name required, type in the enum, and value shape
checked against type.

Requires @salesforce/agents with the typed ContextVariable union.

@W-24014400
Add test/nuts/z3.agent.preview.context-variables.nut.ts covering the
--context-variables-json flag end-to-end via trace inspection: all wire
types (Text/Number/Boolean/Json/List) round-trip in one session, the JSON
flag wins over --context-variables on a duplicate name, a comma-bearing
value survives the JSON flag (with the old flag as a mangling control),
the server rejects an Internal variable, and a type-mismatched value is
rejected client-side.

Augment the Willie_Resort_Manager fixture with five typed External probe
variables (NutProbeText/Bool/Num/Obj/List) so the injected values can be
observed in the session trace.
Reuse the Bot User pre-provisioned in shared setup by writing agentUser into
the spec, instead of letting core auto-create one in the same transaction as
the BotDefinition save. That auto-create intermittently races the pre-save
validation trigger and fails with "User doesn't have access to agent".
Mirrors #484.
Comment thread messages/shared.md

Typed session variables for the agent preview session, as a JSON array.

# flags.context-variables-json.description

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I went with context-variables-json instead of context-variables-object because object already means something in context variable land (a type of variable) so the name was a bit confusing. Plus, it is JSON.

const contextVariables = mergeContextVariables(
parseContextVariables(flags['context-variables']),
parseContextVariablesJson(flags['context-variables-json'])
);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

When merging context-variables and context-variables-json, context-variables-json wins out if there are duplicated variables.

Comment thread src/flags.ts
}

function toContextVariable(entry: unknown, index: number): ContextVariable {
if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Array.isArray is just checking the format is not an array since it must be a json object.
e.g. reject [["x"]] or [[{"name":"a"}]]

@nico-pappagianis
nico-pappagianis marked this pull request as ready for review August 28, 2026 22:23
@nico-pappagianis
nico-pappagianis requested a review from a team as a code owner August 28, 2026 22:23
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