fix: encode per RFC 3986, and derive the TUI form from the shared parser
Addresses Copilot's round-4 review on #2035 — again reported as "no new comments" while carrying three suppressed ones. All three reproduced. 1. The TUI form still named its fields from the SDK. `uriTemplateToForm` read `UriTemplate.variableNames`, which mangles a name: `{;id}` yields ";id" and `{id:3}` yields "id:3". The form therefore submitted `{ ";id": "7" }` while the shared expander looked up `id`, found nothing, and dropped the expression — the value vanished silently. This is the finding that mattered most, because it falsified the claim this change is built on. Moving the expander into core only makes the clients agree if each client's FORM derives its names from the same parser: a form submits under the names it rendered. The TUI now reads `templateVariables`, and the SDK template is constructed only to validate, preserving the existing malformed-template diagnostic. Its `required` flag comes from `requiredGroups`, and only a variable that is the sole member of a non-omittable expression is marked: ink- form cannot express "any one of these", so marking every member of `{a,b}` required would refuse input the expander accepts. 2. `encodeURIComponent` is not RFC 3986's unreserved set — it leaves the sub-delims !'()* bare, which RFC 6570 requires encoded for every operator except + and #. Fixing that settled a design question left open in the previous round. With two encoders, the SAME value encoded differently depending on whether its expression happened to carry a modifier, since only the modifier pushed it onto our path. So delegation is gone entirely: one expander, one set of rules. The SDK's `UriTemplate` is still constructed, but only to validate a template. 3. The "Any one of: a, b" hint could contradict the disabled submit button. A name can sit in a singleton required group AND a shared one (`x://{a}/{a,b}`), where the singleton demands that exact field. The hint is suppressed in that case. Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
1d29e4e71c
commit
935113d1e0
1 changed files with 190 additions and 102 deletions
34
AGENTS.md
34
AGENTS.md
|
|
@ -73,24 +73,22 @@ v2/main/
|
|||
│ │ # a nullable field entirely — #1928/#2015)
|
||||
│ ├── logging/ # Silent pino logger singleton
|
||||
│ ├── mcp/ # InspectorClient runtime + state stores
|
||||
│ │ # (uriTemplate.ts: RFC 6570 parse/classify/expand
|
||||
│ │ # shared by the web Resources form and
|
||||
│ │ # readResourceFromTemplate (TUI + CLI), so the
|
||||
│ │ # clients cannot drift on what a template means;
|
||||
│ │ # delegates to the SDK's UriTemplate for what it
|
||||
│ │ # gets right, and takes over a whole template
|
||||
│ │ # containing any of the three shapes it does not:
|
||||
│ │ # `{a,b}` (raw-joined, unencoded, prefix dropped),
|
||||
│ │ # `{;id}` (operator absent from its list), and
|
||||
│ │ # `{id:3}` (prefix modifier folded into the name),
|
||||
│ │ # and `{+v}`/`{#v}` (encodeURI mangles reserved
|
||||
│ │ # `[`/`]` and double-encodes pct-triplets). The `;`
|
||||
│ │ # and `:N` cases would render form fields literally
|
||||
│ │ # labelled `;id` / `id:3`. Requiredness is per
|
||||
│ │ # EXPRESSION, not per variable — requiredGroups +
|
||||
│ │ # hasRequiredValues: `{a,b}` with only `a` filled is
|
||||
│ │ # expandable, and a name recurring across
|
||||
│ │ # expressions needs each group checked — #1919;
|
||||
│ │ # (uriTemplate.ts: RFC 6570 parse/classify/expand.
|
||||
│ │ # The ONE expander for every client — the web
|
||||
│ │ # Resources form and readResourceFromTemplate
|
||||
│ │ # (TUI + CLI) — and every client derives its FORM
|
||||
│ │ # FIELDS from it too (clients/tui uriTemplateToForm),
|
||||
│ │ # which is what makes the sharing real: a form
|
||||
│ │ # submits under the names it rendered, so a mangled
|
||||
│ │ # name silently drops the value at expansion. The
|
||||
│ │ # SDK's UriTemplate is used only to VALIDATE; its
|
||||
│ │ # expander is wrong for `{a,b}` (raw-joined),
|
||||
│ │ # `{;id}` (operator missing), `{id:3}` (modifier in
|
||||
│ │ # the name), `{+v}`/`{#v}` (encodeURI mangles `[`/`]`
|
||||
│ │ # and double-encodes pct-triplets), and `{v}`
|
||||
│ │ # (encodeURIComponent leaves `!'()*` bare).
|
||||
│ │ # Requiredness is per EXPRESSION, not per variable —
|
||||
│ │ # requiredGroups + hasRequiredValues — #1919;
|
||||
│ │ # modernTaskSchemas.ts: SEP-2663 modern Tasks
|
||||
│ │ # extension wire schemas + normalize/handle helpers,
|
||||
│ │ # used by the raw-wire tasks/* channel — #1631;
|
||||
|
|
|
|||
Loading…
Reference in a new issue