feat(workbench): schema-driven route input editors over a static manifest inputSchema (#105 stage 2) - #224
Conversation
Project bounded route schemas into the manifest so Routes can validate inputs, hand tool calls to existing MCP sessions, and render CLI argv without executing route modules.
Mirror the flagship tool's real operation schema and retain the canonical generated-CLI usage format after rebasing the editor slice.
🦋 Changeset detectedLatest commit: f36462e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f36462e3bc
ℹ️ 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".
| } | ||
| return typeof schema.default === 'boolean' ? schema.default : String(schema.default); | ||
| } | ||
| if (schema.type === 'boolean') return false; |
There was a problem hiding this comment.
Preserve the unset state for optional booleans
For an optional boolean such as the new strict: z.boolean().optional(), initializing the draft to false makes validateRouteInput treat the field as present and hand off { strict: false } even when the user never touched the checkbox. This changes the route input from an omitted property to an explicit false value, which is observable by handlers and defeats optional/default semantics; the draft needs an unset state distinct from false.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in #226 (6901324): an optional boolean without a schema default now stays out of the draft and renders as a three-state (omitted)/true/false select, so an untouched field is omitted from the validated arguments and the MCP prefill while an explicit false still travels as false. Required and defaulted booleans keep the checkbox. The flagship e2e asserts strict is absent from the prefill unless explicitly set.
| const [toolName, setToolName] = useState(initialToolPrefill?.toolName ?? ''); | ||
| const [toolArguments, setToolArguments] = useState<ImmutableJsonRecord>(initialToolPrefill?.arguments ?? {}); |
There was a problem hiding this comment.
Do not fall back to another tool for stale prefills
When a prefill names a tool that the opened server no longer advertises—for example, when handing off from the explicitly supported stale route catalog—this nonempty toolName fails the lookup at selectedTool, which then silently falls back to tools[0] while retaining the prefilled arguments. The resulting call control can therefore invoke an unrelated first tool with arguments intended for the missing tool; reject or clear a mismatched prefill instead of allowing that fallback.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in #226 (6901324): a non-empty tool selection the live session does not advertise no longer falls back to tools[0] — the prefill aside states the server no longer advertises that tool and no call control renders, so the prepared arguments can never attach to a different tool; manual selection of an advertised tool starts with empty arguments. The plain manual flow (empty selection defaults to the first tool) is unchanged.
First #105 stage-2 slice, per the stage-1 handoff: the compiled route
inputSchemagoes on the wire as a NEW optional field onRouteManifestRoute, with therouteSchemastrict decoder inroute-manifest-client.tsextended in the same PR (no other status/artifact DTO widened), and the Routes page renders generated input editors with validation before invoke.Static projection — modules are still never executed
routes/input-schema.ts;cli-argv.tsconsumes it with byte-identical AB4814 diagnostics and argv output (existing tests unchanged).extractInputSchemaprojects any conventional route module'sexport const inputSchemainto a deterministic, deep-frozen JSON-Schema draft-2020-12 subset (type/properties/required/additionalProperties:false; scalarstring|number|boolean,enum, array-of-scalaritems,default,description). Validation-only refinements stay uninterpreted by design — the module's real zod schema still validates at execution.CompiledAgentRoute.inputSchemajoins the graph identity/digest deterministically;routeManifestForpasses it through.Workbench editors
cliCommandUsage) matching the generated CLI help conventions landed in fix(workbench): route catalog review fixes from #211 (usage arity, empty server surfaces, stale-repair e2e) #222.inventory_sourcestool now declares its schema as an in-grammar literal mirroring the operation contract exactly (source/report?/strict?+ describes), so the catalog demonstrates a projectable tool schema.Verification
pnpm typecheck+ all example typechecks: clean.pnpm lint: 859 files, 0 issues.examples-real.e2e.test.ts5/5 — the flagship journey now covers generated editor fields, a validation error, the enabled MCP handoff with prefilled server/tool/arguments, the CLI argv line, then the stale→repair legs from fix(workbench): route catalog review fixes from #211 (usage arity, empty server surfaces, stale-repair e2e) #222.Stage-2's Agent Document stage (render-event stream for route runs) follows in the next PR; stages 3–4 (lifecycle replay, host inventory) remain per #107.