Survey of master for surface area whose consumers are tests/docs only, classified per candidate (production vs non-production corpus, rg + call-site reads). New proposed/simplification RFCs: - prune-producerless-vocabulary-variants: CacheHint/cache? fields, MessageSource 'agent', TurnTrigger 'continuation' (the TurnEndReasonMap omitted-until-emitted policy, applied) - drop-inert-request-knobs: GenerateOptions.prefill (both adapters throw UNSUPPORTED), ToolSchema.strict (zero setters; beta-URL-only feature) - drop-web-providers-change-event: the llm/adapter-change precedent replayed - drop-image-content-block: no producer; every consumer silently drops it - prune-write-only-fs-surface: fs-local STREAM_MIN_SIZE/streamMinSize, FsTarget.inputPath, FsEditOutcome.replacements/replaceAll, FileReadOutcome.limit/version - prune-unimplemented-subagent-vocabulary: outputSchema/structured, toolFilter, sendMessage/resume (depthLimit stays) - trim-acp-bridge-unreachable-surface: agentName/agentVersion knobs (resolves TODO(double-default)), toolKindFor name-sniffing - prune-dead-core-spine-surface: SurfaceManager.invalidate(), runLoop/Inbox exports, ToolExecutionResult.callId - share-app-bin-boot-glue: the twin coverage-exempt bin helpers Also supplements three existing proposed RFCs with survey evidence: the bash seam consumption census (generic-long-running-tool-runtime), three more static inventories (discover-package-inventory), and the bridge's already-1:1 id usage (unify-agent-and-session-id).
3.9 KiB
RFC: Drop GenerateOptions.prefill and ToolSchema.strict — request knobs with no working end-to-end path
Status: proposed
Problem
Two request-contract knobs ride the whole request pipeline, yet neither can do anything today:
prefill(packages/llm/llm/src/types.ts) has no production setter — the loop assemblesmodel/system/tools/messagesplussessionId/signal, and the compaction backend adds onlymaxTokens— and BOTH adapters reject it:packages/llm/llm-deepseek/src/serialize.tsandpackages/llm/llm-pi-ai/src/adapter.tseach throwLlmError('UNSUPPORTED')on a non-undefinedprefill. The field's entire observable behavior is two throws, each pinned by one adapter test. DeepSeek's chat-prefix completion is a Beta feature on a base URL neither adapter targets.strict(ToolSchema, same file) is threaded throughDefineToolOptions/defineTool(packages/core/tools/src/schema.ts), the registry'sschemas()allowlist (packages/core/tools/src/index.ts), the deepseek wire mapping (packages/llm/llm-deepseek/src/serialize.ts, whose wire-type note records that strict mode requires the/betabase URL the adapter does not use), and a per-tool payload-patching pass inpackages/llm/llm-pi-ai/src/adapter.ts. No shipped tool sets it —rgacross everytool-*package src andexamples/finds zerostrict:producers; the only setters are dsh-tools unit tests.
Both knobs are adapter-symmetric, so removal sheds them from both twins together — the twin-adapter design is untouched.
Proposal
- Remove
prefillfromGenerateOptions, both adapters' UNSUPPORTED guards, the tests pinning the throws, the paste lines in core.md, and the adapter README rows documenting the rejection. - Remove
strictfromToolSchema,DefineToolOptions,defineTool, and theschemas()allowlist; drop the deepseek serializer branch; simplify the pi-ai payload fixup to the unconditional scrub of pi-ai's own strict default (that half exists for wire parity with the hand-rolled twin and survives); drop the setter tests and the core.md paste line.
This RFC deliberately does NOT touch temperature, stop, or maxTokens: those are honored end-to-end by both adapters and are the natural first targets of a request-mutating hook plugin on agent/request.
Why not keep them?
"An explicit UNSUPPORTED throw is honest contract behavior" — but a knob whose only implementation across both twins is rejection promises nothing, and deleting it upgrades the failure mode: an accidental setter becomes a compile error instead of a runtime throw. "Strict schema adherence is an officially documented provider feature with complete plumbing" — but a knob is not product surface until a shipped tool sets it AND an endpoint honors it; today neither is true. Each returns with its first real producer: prefill together with an adapter that implements chat-prefix completion (and a stated policy for adapters that do not), strict together with a tool that wants it and a beta-endpoint story.
Acceptance criteria
rg prefilland a tool-schema-scopedrg strictreturn only this RFC (and unrelated prose such asstrictEqual).- Both adapters compile and their contract tests pass without the guards; the pi-ai fixup still scrubs the library's strict default (wire parity pinned by its serializer tests).
- Doc pastes and the type-equiv manifest in sync;
pnpm run doc-syncgreen.
Risks
A hooks/config plugin arriving via the interception seams may want to set request fields — it will reach for temperature/stop (kept, working), not a field adapters reject. If chat-prefix completion or strict mode become product features, the re-add lands with the adapter/endpoint work, where the contract can say what actually happens rather than "everyone throws".