Repository navigation
Conversation
…he release Catalog inputs[].key can now select a value inside a list (modelsphere/modelsphere#75): - One resolver (lib/inputKey.ts) for field, [field=value], [=value], [^=prefix] and bare-number segments. A key answers only when it reaches exactly one string, number or boolean; field-only keys may be absent. - An optional patcher fills {value} on write and is stripped on read. - A list key copies the variant's list into the form layer and patches only the matched item. The web writes its effective answer (typed, release, site, default), since swissd only writes dotted keys. Field-only keys keep today's behaviour. - The written answers go to swissd as additionalAnnotations swiss.modelsphere.dev/inputs ([{key, keyType, value}], modelsphere/swiss#62). - An upgrade reads the answers from that annotation, drops keys the new variant no longer lists (deprecated) or cannot resolve (broken) and shows them, removes what the old answers wrote from the form layer and writes them again against the new variant. Releases without the annotation read field-only answers from the form layer as before. Refs modelsphere/modelsphere#75 Co-authored-by: aceforeverd <11715200+aceforeverd@users.noreply.github.com>
huskcass
left a comment
There was a problem hiding this comment.
No blockers.
The key rules match model-catalog#108 (findAt is the same walk), list keys copy the variant's list and patch one item, and upgrade reads the annotation, drops deprecated/broken answers and rewrites. Rollback and releases without the annotation behave as before. CI green.
- Medium: list-key answers that came from the site or the input default are recorded, and on the next upgrade they come back as "release" answers that win over the site. A later site-profile change then never reaches a list key, while field keys keep following the profile. Record only typed answers, and on upgrade drop the list copies for every list key the old variant had.
- Medium:
inputAnnotationssilently returns nothing when the JSON is over 16384 bytes. On an upgrade swiss then keeps the old record, which no longer matches the rewritten form layer. A few inputs never get near 16 KiB. Drop the check and let swissd's 400 surface. - Low: the annotation carries
keyType: "kyaml"andparseInputRecordsskips any otherkeyType. The swiss API convention is{key, value}; dropkeyType,INPUT_KEY_TYPEand that filter. - Low: guards for cases the catalog CI already rules out: the patcher
parts.length !== 2branches, theparent == null || at == nullcheck inwriteAt, and most of the per-item shape checks inparseInputRecords. - Low:
releaseInputStateruns three times per render (ininputRows, fordroppedInputs, inplanRequest), and the dropped-inputs notice is written twice. Compute it once per page and pass it down.
Verdict: good to merge after the first Medium; the rest are optional cuts.
— Review Golden
swiss treats swiss.modelsphere.dev/inputs as opaque, so drop keyType from written records and stop filtering on it when reading. Co-authored-by: aceforeverd <11715200+aceforeverd@users.noreply.github.com>
huskcass
left a comment
There was a problem hiding this comment.
No blockers.
The annotation is now {key, value} only: INPUT_KEY_TYPE and every keyType reference are gone, reads no longer filter on it (a record that still has keyType parses fine), and the tests were updated to match. Nothing else changed. CI green (publish pending).
- Low:
records.map(({ key, value }) => ({ key, value }))ininputAnnotationsis now a no-op copy;JSON.stringify(records)is enough. - The other points from the previous review remain open.
Verdict: good to merge once the open points are settled.
— Review Golden
swissd no longer fills site or default input answers, so the web writes the effective answer (typed, release, site, default) for every key, dotted field keys included. The inputs annotation records only typed answers and answers carried from the release, so later site changes still apply on upgrade. An oversized annotation is sent as is and swissd rejects it. Co-authored-by: aceforeverd <11715200+aceforeverd@users.noreply.github.com>
huskcass
left a comment
There was a problem hiding this comment.
Blockers:
- The commit adds 55 files under the repo-root
node_modules/(.vite/vitestand.vitest-cache, about 14.8k lines)..gitignoreonly covers/web/node_modules/. Remove them, and ignore/node_modules/too.
Every key now gets typed, then release, then site, then default, written into the form layer, which matches #75 §3. Only typed and release answers are recorded, inputAnnotations is just JSON.stringify(records), and an oversized value goes to swissd for its 400. That settles both earlier Mediums and the no-op copy.
- Medium: a deploy with no typed answers sends no annotation (
inputAnnotations([], { replace: undefined })isundefined), so the release has none. On the next upgradereleaseInputStatetakes the no-annotation branch and readsstorageKVOffload.mooncake.masterback from the form layer as a release answer. The old site value then wins over the current site and gets recorded. #75 §4 gives[]for "no user answers" and keeps the form-layer fallback for older releases only. Send the annotation ([]when empty) on every deploy and upgrade of a variant with inputs. - Low: a site or default answer is not recorded, so
dropInputWritesnever removes its write. If the new variant drops the input, or the site answer goes away with no default, the old leaf or list copy stays in the form layer and shadows the variant's list. Also drop writes for the new variant's own input keys before rebuilding. - Low: comments still describe swissd answering and checking inputs (inputs.ts:20, :34, :68, :81, :270). After swiss#63 the web is the only check, so the
catchthat leaves a bad pattern "to swissd" now lets anything through. The PR description is also stale: "Omitted if over 16384 bytes", "swissd only writes dotted keys", and site/default answers being recorded. - Earlier Lows still open: the guards catalog CI already covers (
parts.length !== 2,parent == null || at == nullinwriteAt, per-item checks inparseInputRecords), andreleaseInputStaterunning three times per render.
Verdict: good to merge with swiss#63 once the cache files are gone and the empty annotation is sent.
— Review Golden
What type of PR is this?
What this PR does and why
Console side of modelsphere/modelsphere#75: catalog
inputs[].keyis a kyaml-style path, so an input can select a value inside a list (e.g.volumes.[name=draft-model].hostPath.path,extraArgs.[^=--speculative-draft-model-path=]with apatcher).lib/inputKey.ts:field,[field=value],[=value],[^=prefix], bare number. Exactly one primitive or no answer; field-only keys may be absent.patcherfills{value}on write, is stripped on read. Same rules as model-cataloghack/lib/inputs.js.additionalAnnotations["swiss.modelsphere.dev/inputs"]=[{key, value}](modelsphere/swiss#62). Omitted if over 16384 bytes.Both deploy UIs (swiss pages and the inferences deploy sheet) are wired.
Which issue(s) this PR fixes
Refs modelsphere/modelsphere#75
How it was tested
Unit tests: resolver (one/zero/several matches per segment kind, patcher read/write, list copy without mutating the variant), annotation build/parse, upgrade recheck (deprecated/broken) and form-layer rebuild, the dropped-inputs notice.
Checks
npm run typecheck && npm test && npm run buildinweb/Notes for reviewers
applyInputs/checkInputsskipping keys it cannot evaluate).Release note