Repository navigation
design pi config
Fifth and last per-target panel, the #60/#62/#63/#64 pattern applied to pi.
This closes the per-target panel family: all five AgentTargets with runtime
config now have a dedicated panel. Durable companions:
design-phase-9-harness-runtime.md (§4.3 the W16 writer this extends),
research-provider-model-params.md (§3.6 pi ground truth),
design-claude-code-config.md / -opencode- / -codex- /
-deepseek-config.md (the pattern's first four instances).
The provider row keeps ONLY the connection (provider / credential /
base URL). The pi panel owns everything model-shaped: the default model,
the switchable rows (settings enabledModels), and per-model detail. The
generic default-model grid and extra-models rows are hidden for
target === 'pi'.
in core/model-config.js, re-verified 2026-10-17)
Per model entry: id (required), name, api, baseUrl, reasoning
(BOOLEAN capability flag), thinkingLevelMap, input
(('text'|'image')[]), cost, contextWindow, maxTokens,
samplingParams (Record<string, unknown>), headers, compat.
Sampling merge order (pi-ai resolveSamplingParams):
{...model.samplingParams, ...samplingParamsByThinkingLevel[level], ...requestParams}.
The W16 writer already landed name/contextWindow/maxTokens/input from the #51 seed; the panel adds the overlay plus pi's OWN knob vocabulary:
-
reasoning: true— a simple boolean capability declaration (panel-only; the seed carries no such field). Symmetric with opencode's 推理 checkbox. -
samplingParams— free key/value pairs edited with the #56 TagCombobox + Switch/JSON idiom (opencode'soptionseditor verbatim). Effective on the openai wires, silently ignored on anthropic — the registry's documented warn-not-reject stance; the panel hint says so.serverToolsdeliberately does NOT ridesamplingParams.tools(the research §4.2 clobber risk).
OUT of v1 (same class as dsh's wire-dict gaps): thinkingLevelMap +
samplingParamsByThinkingLevel (per-level wire spellings), cost (the
registry carries no pricing), headers, compat. No behavior section —
pi's settings.json (55 fields, none sampling) is already fully managed by
the W16 writer (defaultProvider/defaultModel/enabledModels).
spec.pi — additive optional field (piConfigSchema: per-model name /
contextWindow / maxOutputTokens / vision / reasoning /
samplingParams, ≤17 entries), zod-validated both ends; old daemons strip
it. The four-spot wiring: core PiConfigData mirror, service row, toView
passthrough, sdk re-exports.
applyPiConfig's models array gains the panel overlay, per field: panel
value (spec.pi.models) > #51 modelEntries seed > omitted
(reasoning/samplingParams are panel-only — the seed carries neither).
A bare id with no detail and no seed stays { id } byte-identical
(test-pinned). settings.json and the key file are untouched by #65.
Rig-verified end to end (survey-box, 2026-10-17): volcengine-openai route
(no registry models — free-text ids, no seed interference) — panel name +
contextWindow + vision + reasoning + samplingParams {enable_thinking: true, top_p: 0.9} → exact models.json; the doubao extra stayed a bare
{id}; pi auth check --provider harness-nexus → "ready" (pi itself
loaded the written schema); reload prefill round-trip exact (tags, switch,
JSON value all restored).
pi-panel.tsx, i18n pi* keys (en/zh side by side):
- 模型 — default model (registry select when available, free-text otherwise) + the extra-models rows. Hint: the enabled list is the switchable set.
- 模型详情 — collapsible per-model groups: 显示名 / 上下文窗口 / 输出上限 / 视觉 + 推理 checkboxes / 采样参数 (TagCombobox keys; boolean keys ride a Switch, others a raw JSON input parsed at the apply boundary — the #56 idiom). The validation issue renders INLINE below the groups (the #63 lesson).
Note for eval/browser drivers: TagCombobox commits via Enter keydown on its input (aria-label contains the field label); the listbox add-option click path is flaky under synthetic events.