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,99 +0,0 @@
.fields {
display: flex;
flex-direction: column;
gap: 14px;
}
.field {
display: flex;
flex-direction: column;
gap: 4px;
}
.field.group {
border: 1px solid var(--border, #e2e2e2);
border-radius: 10px;
padding: 12px;
}
.labelRow {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.label {
font-size: 13px;
font-weight: 500;
color: var(--text-secondary, #555);
}
.description {
margin: 0;
font-size: 12px;
color: var(--text-tertiary, #888);
}
.control {
width: 100%;
box-sizing: border-box;
padding: 8px 10px;
border: 1px solid var(--border, #d9d9d9);
border-radius: 8px;
font: inherit;
background: var(--surface, #fff);
color: inherit;
}
.control:focus {
outline: 2px solid var(--accent, #3964fe);
outline-offset: -1px;
}
.resetButton {
border: none;
background: none;
color: var(--accent, #3964fe);
font-size: 12px;
cursor: pointer;
padding: 0;
}
.stack {
display: flex;
flex-direction: column;
gap: 8px;
}
.row {
display: flex;
align-items: center;
gap: 8px;
}
.row > :first-child {
flex: 1;
}
.dictKey {
min-width: 96px;
font-size: 13px;
font-weight: 500;
}
.unsupported {
display: flex;
flex-direction: column;
gap: 4px;
font-size: 12px;
color: var(--text-tertiary, #888);
}
.unsupported pre {
margin: 0;
padding: 8px;
border-radius: 8px;
background: var(--surface-sunken, #f5f5f5);
overflow-x: auto;
}
Binary file not shown.
-6
View File
@@ -1,6 +0,0 @@
declare module '*.module.css' {
const classes: Record<string, string>
export default classes
}
declare module '*.css'
+6 -10
View File
@@ -1,16 +1,12 @@
/**
* Schema-driven React form renderer for settings sections. `SchemaForm`
* rehydrates the wire's serialized schemastery envelope and edits a draft
* user section against it; the model helpers expose the same introspection
* and immutable path editing for page-level composition.
* Schema/draft model layer for settings editors: rehydrate the wire's
* serialized schemastery envelope, resolve nodes by settings path, validate
* drafts, and edit them immutably by path. Editors render their own controls
* (the Models page hand-writes its layout) on top of these helpers.
* @module @deepseek-ai/dsh-client-schema-form
*/
export { SchemaForm } from './SchemaForm.tsx'
export type {
SchemaFieldContext, SchemaFormLabels, SchemaFormProps, SchemaFormSecret,
} from './SchemaForm.tsx'
export {
deletePath, getPath, hasPath, nodeAtPath, nodeKind, rehydrateSchema, setPath, unionChoices, validateDraft,
deletePath, getPath, hasPath, nodeAtPath, rehydrateSchema, setPath, validateDraft,
} from './model.ts'
export type { NodeKind, SchemaNode } from './model.ts'
export type { SchemaNode } from './model.ts'
+4 -4
View File
@@ -15,10 +15,10 @@ export const name = 'client-schema-form-invariant'
export const inject = ['invariants']
/**
* No runtime invariant: a pure React rendering library — it emits no cordis
* events and owns no cross-plugin mutable relation; draft immutability,
* schema rehydration, and control/edit round trips are asserted directly by
* this package's component and model specs.
* No runtime invariant: a pure schema/draft helper library — it emits no
* cordis events and owns no cross-plugin mutable relation; draft
* immutability, schema rehydration, and path-edit round trips are asserted
* directly by this package's model specs.
*/
const install: InvariantInstaller = () => {}
+3 -46
View File
@@ -1,8 +1,8 @@
/**
* Schema introspection and draft-editing helpers behind the form renderer.
* Schema introspection and draft-editing helpers behind settings editors.
* The serialized schemastery envelope (`schema.toJSON()`) rehydrates into a
* live validator whose node relations (`dict`/`inner`/`list`) the renderer
* walks; drafts are edited immutably by path.
* live validator whose node relations (`dict`/`inner`) editors probe for
* field presence and roles; drafts are edited immutably by path.
* @module @deepseek-ai/dsh-client-schema-form/model
*/
@@ -35,49 +35,6 @@ export function validateDraft(schema: SchemaNode, draft: unknown): string | unde
}
}
/** The renderable classification of one schema node. */
export type NodeKind =
| 'object'
| 'dict'
| 'array'
| 'string'
| 'number'
| 'boolean'
| 'union-const'
| 'unsupported'
/**
* Classify one node into the renderer's vocabulary. A union renders as a
* select only when every branch is a literal; everything else the renderer
* cannot faithfully edit is `unsupported` and falls back to a read-only view
* (never silently dropped).
* @param node - live schema node.
* @returns the control family for this node.
*/
export function nodeKind(node: SchemaNode): NodeKind {
switch (node.type) {
case 'object': return 'object'
case 'dict': return 'dict'
case 'array': return 'array'
case 'string': return 'string'
case 'number': return 'number'
case 'boolean': return 'boolean'
case 'union':
return (node.list ?? []).every(branch => branch.type === 'const') ? 'union-const' : 'unsupported'
default:
return 'unsupported'
}
}
/**
* Literal choices of a `union-const` node, in declaration order.
* @param node - a node classified `union-const`.
* @returns each branch's literal value.
*/
export function unionChoices(node: SchemaNode): unknown[] {
return (node.list ?? []).map(branch => (branch as { value?: unknown }).value)
}
/**
* Resolve the schema node at a settings path (the configurable-provider
* directory's `settingsPath` vocabulary): object properties by name, dict