refactor(tools): type the py-types render frame and tighten the note

Follow-ups from the bot's review of the trusted-after-validation revert:
- renderType's Frame now carries JsonSchemaNode (the root schema is asserted
  before any frame is built), dropping the `as Record<string, unknown>` casts,
  the `node.oneOf as unknown[]` cast, and the runtime `required` filter — the
  same typed-frame shape as the sibling ts-types renderer, so the "symmetric
  with ts-types" claim holds structurally, not just behaviorally.
- The language-dispatch note broadens the trusted-input argument to cover all
  real sources (first-party defineTool/raw registration and wire-derived plain
  JSON), and the zh side uses full-width punctuation per translation-rules.md.
py-types.ts stays at 100% per-file coverage.
This commit is contained in:
Chinesezjc
2026-08-02 16:42:32 +08:00
parent f61b138e08
commit cabeaed1eb
4 changed files with 28 additions and 24 deletions

View File

@@ -25,7 +25,7 @@ Both tables are read with `Object.hasOwn` before use so a language named `toStri
`py-types.ts` renders the same unified tool-schema vocabulary `jsonSchemaToTs` covers, targeting Python: `jsonSchemaToPy` emits a type expression per JSON-schema node, and `renderToolsSdkPy` assembles named `TypedDict`s for each visible tool's arguments and canonical output plus a `tools` object with usage instructions equivalent to the TypeScript flavor. Unsupported raw constructs degrade rather than throwing during assembly, matching the TypeScript renderer's contract. The output is deterministic — lexicographic tool order, byte-identical text for an unchanged tool set — so the prompt stays prefix-cache-friendly.
`renderType` validates the whole schema once (`assertSupportedJsonSchema`) and then trusts it, wrapping the walk in one `try/catch` that degrades to `Any` — the same trusted-after-validation stance the sibling `ts-types` renderer takes at this typed same-process seam ([Trust TypeScript at typed same-process seams](../../../../AGENTS.md)). It deliberately carries NO defenses against a schema whose accessors mutate between reads (post-validation cycles, TOCTOU on `const`/`enum`, self-referential functions): the input is a first-party `defineTool` object literal that already passed validation, so such inputs are unreachable, and adding per-shape guards here would break symmetry with `ts-types` (which has none) for values the static interface forbids. `jsonSchemaToPy(schema: unknown)` accepts `unknown` and returns `Any` on a malformed schema — the Python counterpart of the TS flavor's `unknown` — but its contract is "degrade an unsupported schema", not "survive an adversarial mutating one".
`renderType` validates the whole schema once (`assertSupportedJsonSchema`) and then trusts it, wrapping the walk in one `try/catch` that degrades to `Any` — the same trusted-after-validation stance the sibling `ts-types` renderer takes at this typed same-process seam ([Trust TypeScript at typed same-process seams](../../../../AGENTS.md)). It deliberately carries NO defenses against a schema whose accessors mutate between reads (post-validation cycles, TOCTOU on `const`/`enum`, self-referential functions): the input is a first-party registration (a `defineTool` literal or a raw registration) or a wire-derived plain JSON schema — the former is trusted per AGENTS.md, the latter is a `JSON.parse` product that physically cannot carry accessors, and `renderType` re-validates the whole tree on every call regardless — so such inputs are unreachable, and adding per-shape guards here would break symmetry with `ts-types` (which has none) for values the static interface forbids. `jsonSchemaToPy(schema: unknown)` accepts `unknown` and returns `Any` on a malformed schema — the Python counterpart of the TS flavor's `unknown` — but its contract is "degrade an unsupported schema", not "survive an adversarial mutating one".
## Alternatives considered