feat(ui-models)!: single-key hand-written provider editors with derived credential references

The Models page drops the generic schema renderer and the visible
environment-variable field: each editor is a curated per-family card whose
primary input is one write-only API key stored under a derived
<ROUTE>_API_KEY reference (recorded as apiKeyEnv in the pi-ai profile), an
unkeyed whole-section provider opens as its setup card, and the collapsed
customized-settings fold carries baseURL/reasoningEffort (deepseek) or
reasoning (pi-ai). dsh-client-schema-form reduces to the schema/draft model
layer (no React).
This commit is contained in:
Yichen Jiang
2026-07-30 12:17:56 +08:00
parent 65bd54f8b4
commit d1bfdbff84
24 changed files with 779 additions and 1156 deletions
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest'
import Schema from 'schemastery'
import {
deletePath, getPath, hasPath, nodeAtPath, nodeKind, rehydrateSchema, setPath, unionChoices, validateDraft,
deletePath, getPath, hasPath, nodeAtPath, rehydrateSchema, setPath, validateDraft,
} from '../src/model.ts'
const Wire = (schema: Schema): unknown => JSON.parse(JSON.stringify(schema.toJSON()))
@@ -21,33 +21,6 @@ describe('rehydration and validation', () => {
})
})
describe('nodeKind', () => {
it.each([
[Schema.object({}), 'object'],
[Schema.dict(Schema.string()), 'dict'],
[Schema.array(Schema.string()), 'array'],
[Schema.string(), 'string'],
[Schema.number(), 'number'],
[Schema.natural(), 'number'],
[Schema.boolean(), 'boolean'],
[Schema.union(['a', 'b']), 'union-const'],
[Schema.union([Schema.string(), Schema.number()]), 'unsupported'],
[Schema.transform(Schema.string(), value => value), 'unsupported'],
])('classifies %#', (schema, expected) => {
expect(nodeKind(rehydrateSchema(Wire(schema as Schema)))).toBe(expected)
})
it('lists union choices in declaration order', () => {
const node = rehydrateSchema(Wire(Schema.union(['off', 'high', 'max'])))
expect(unionChoices(node)).toEqual(['off', 'high', 'max'])
})
it('tolerates structural union nodes missing their branch list', () => {
expect(nodeKind({ type: 'union', meta: {} } as never)).toBe('union-const')
expect(unionChoices({ type: 'union', meta: {} } as never)).toEqual([])
})
})
describe('path helpers', () => {
const root = { providers: { openai: { baseURL: 'https://x' } }, models: [{ id: 'a' }] }