@prettier-ai/dsh-client-ui-settings-models 0.1.2-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js ADDED
@@ -0,0 +1,6 @@
1
+ //#region lib/types/index.js
2
+ /** Host loader entry for the browser implementation exported from `./client`. */
3
+ /** Host plugin body — no host-side behavior for the models settings plugin. */
4
+ function apply() {}
5
+ //#endregion
6
+ export { apply };
@@ -0,0 +1,24 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@prettier-ai/dsh-client-ui-settings-models`.
4
+ * @module @prettier-ai/dsh-client-ui-settings-models/invariant
5
+ */
6
+ const PACKAGE_NAME = "@prettier-ai/dsh-client-ui-settings-models";
7
+ /** Cordis companion plugin name. */
8
+ const name = "client-ui-settings-models-invariant";
9
+ /** Service required before the companion can reserve package ownership. */
10
+ const inject = ["invariants"];
11
+ /**
12
+ * No runtime invariant: a nav-entry-only section plugin rendering a fixed
13
+ * empty content column — it emits no cordis events and owns no cross-plugin
14
+ * mutable relation.
15
+ */
16
+ const install = () => {};
17
+ /**
18
+ * Register this package's invariant companion.
19
+ * @param ctx - Cordis context carrying the invariant service.
20
+ * @returns the installed registration's disposer after setup succeeds.
21
+ */
22
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
23
+ //#endregion
24
+ export { apply, inject, name };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The card that declares a provider pi-ai does not ship — an OpenAI-compatible
3
+ * gateway, a self-hosted server, or a provider newer than the installed
4
+ * catalog.
5
+ *
6
+ * This is a create, not an edit, which is why it is its own card rather than
7
+ * the provider editor with extra fields: the route id is being *chosen* here,
8
+ * and the settings address does not exist until it is. One `settings.mutate`
9
+ * sets the whole profile at `providers.<route>`; the key travels separately
10
+ * through `credentials/set` under the reference the profile records, exactly as
11
+ * an existing provider's key does.
12
+ *
13
+ * The three fields a hand-declared route cannot default — endpoint, protocol,
14
+ * and at least one model — are required here rather than at load, so the
15
+ * failure names the field while the user is still looking at it.
16
+ *
17
+ * There is deliberately no reasoning-effort control, here or on the editor
18
+ * card: effort is a per-MODEL capability, and the models under one provider
19
+ * disagree about it, so a provider-scoped control can only be set to a value
20
+ * some of them reject. The composer's model picker offers each model its own
21
+ * levels instead.
22
+ */
23
+ import type { ReactNode } from 'react';
24
+ import type { ModelsWire } from './store.ts';
25
+ import type { en } from './locales.ts';
26
+ /** Props of {@link CustomProviderCard}. */
27
+ export interface CustomProviderCardProps {
28
+ /** Route ids already declared, so the card refuses to shadow one. */
29
+ taken: readonly string[];
30
+ /** Wire protocols the adapter can serve, in the order it reports them. */
31
+ protocols: readonly string[];
32
+ /**
33
+ * Revision of the `llm-pi-ai` user section this card opened at, sent with
34
+ * the create so a route another tab declared meanwhile is a refusal rather
35
+ * than a silent overwrite of its whole profile.
36
+ */
37
+ revision: number;
38
+ /** Wire faces for the write and for interrogating the endpoint. */
39
+ api: ModelsWire;
40
+ /** Section copy. */
41
+ t: (key: keyof typeof en) => string;
42
+ /** Disable writes (read-only settings provider). */
43
+ readOnly: boolean;
44
+ /** Close the card; `changed` reports whether a provider was created. */
45
+ onClose: (changed: boolean) => void;
46
+ }
47
+ /**
48
+ * Render the custom-provider creation card.
49
+ * @param props - existing routes, protocol choices, wire faces, and copy.
50
+ * @returns the creation card.
51
+ */
52
+ export declare function CustomProviderCard(props: CustomProviderCardProps): ReactNode;
53
+ //# sourceMappingURL=CustomProviderCard.d.ts.map
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Curated editor for the direct DeepSeek adapter's advisory model catalog.
3
+ * The settings layer replaces `models` as one array, so the parent supplies
4
+ * the effective inherited rows until the first edit materializes a user
5
+ * override; reset removes that override instead of copying defaults into it.
6
+ */
7
+ import type { ReactNode } from 'react';
8
+ import type { en } from './locales.ts';
9
+ /** One catalog entry kept structurally open so hidden or future fields survive an edit. */
10
+ export type DeepSeekModelDraft = Record<string, unknown>;
11
+ /**
12
+ * Read a typed capacity, so a user can write `256K` or `1M` instead of counting
13
+ * zeroes. The stored value stays a plain token count.
14
+ * @param text - raw field text.
15
+ * @returns the count; `undefined` when blank (inherit), `NaN` when unreadable
16
+ * (rejected by {@link validateDeepSeekModels} before any write).
17
+ */
18
+ export declare function parseCapacity(text: string): number | undefined;
19
+ /**
20
+ * Spell a stored count back in the shortest form that survives a round trip
21
+ * through {@link parseCapacity}; a count that is not a whole number of
22
+ * thousands stays written out.
23
+ * @param value - stored capacity.
24
+ * @returns the field text.
25
+ */
26
+ export declare function formatCapacity(value: number): string;
27
+ /** A localized validation failure for one user-owned model array. */
28
+ export interface DeepSeekModelsValidationFailure {
29
+ /** Zero-based model position. */
30
+ index: number;
31
+ /** Message key owned by the Models settings section. */
32
+ key: 'modelIdRequired' | 'modelIdDuplicate' | 'modelNameInvalid' | 'modelContextInvalid' | 'modelMaxTokensInvalid';
33
+ }
34
+ /** Convert a schema-validated catalog value into records without dropping hidden fields. */
35
+ export declare function modelDrafts(value: unknown): DeepSeekModelDraft[];
36
+ /**
37
+ * Validate adapter constraints that the serialized schema cannot express.
38
+ * @param value - user-owned `models` value, or undefined while inherited.
39
+ * @returns the first invalid row, or undefined when the adapter will accept it.
40
+ */
41
+ export declare function validateDeepSeekModels(value: unknown): DeepSeekModelsValidationFailure | undefined;
42
+ /** Props of {@link DeepSeekModelsEditor}. */
43
+ export interface DeepSeekModelsEditorProps {
44
+ /** Effective rows: inherited until the parent materializes an override. */
45
+ models: readonly DeepSeekModelDraft[];
46
+ /** Whether the user layer currently owns the whole array. */
47
+ overridden: boolean;
48
+ /** Fallback context capacity used when a row omits its exact value. */
49
+ defaultContextWindow: number | undefined;
50
+ /** Fallback output cap used when a row omits its exact value. */
51
+ defaultMaxTokens: number | undefined;
52
+ /** Section copy. */
53
+ t: (key: keyof typeof en) => string;
54
+ /** Disable every mutation. */
55
+ disabled: boolean;
56
+ /** Replace the user-owned array after one visible edit. */
57
+ onChange: (models: DeepSeekModelDraft[]) => void;
58
+ /** Remove the user-owned array and return to inheritance. */
59
+ onReset: () => void;
60
+ }
61
+ /**
62
+ * Render the direct DeepSeek adapter's model catalog: id and display name on
63
+ * each row, capacities behind the row's own disclosure.
64
+ * @param props - effective rows plus the array-level override actions.
65
+ * @returns the catalog editor.
66
+ */
67
+ export declare function DeepSeekModelsEditor(props: DeepSeekModelsEditorProps): ReactNode;
68
+ //# sourceMappingURL=DeepSeekModelsEditor.d.ts.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Official-DeepSeek first-run step. Readiness comes from the same
3
+ * provider/settings/credential join as the Models page: any provider the user
4
+ * can already talk to ends the step, and only a user with none is offered the
5
+ * official DeepSeek route. The step reuses that page's credential editor in
6
+ * the onboarding plugin's shared modal, so the key is entered once.
7
+ */
8
+ import type { ReactNode } from 'react';
9
+ import type { SnapshotStore } from '@prettier-ai/dsh-client-store';
10
+ import type { InjectFace, PropsRuntime } from '@prettier-ai/dsh-client-ui-slots';
11
+ import type { ModelsSettingsState, ModelsSettingsStore, ModelsWire } from './store.ts';
12
+ import type { SettingsSchemaOperations } from './schema-operations.ts';
13
+ import type { en } from './locales.ts';
14
+ /** Registration-side dependencies of {@link DeepSeekOnboardingDialog}. */
15
+ export interface DeepSeekOnboardingInjected {
16
+ hooks: {
17
+ /** Shared Models-page join state, bound by the slot renderer. */
18
+ models: SnapshotStore<ModelsSettingsState>;
19
+ };
20
+ /** Shared Models-page join controller. */
21
+ controller: ModelsSettingsStore;
22
+ /** Existing wire face reused by the Models credential editor. */
23
+ api: ModelsWire;
24
+ /** Settings schema and immutable path callbacks. */
25
+ schema: SettingsSchemaOperations;
26
+ /** Feature copy. */
27
+ t: (key: keyof typeof en) => string;
28
+ }
29
+ /** Slot owner props plus the feature's injected dependencies. */
30
+ export type DeepSeekOnboardingDialogProps = PropsRuntime<'settings.onboarding'> & InjectFace<DeepSeekOnboardingInjected>;
31
+ /**
32
+ * Prompt a first-run user for the official DeepSeek credential while no
33
+ * provider can serve requests and that credential is writable.
34
+ * @param props - settings-shell owner state and Models feature dependencies.
35
+ * @returns the onboarding modal or null when onboarding needs no intervention.
36
+ */
37
+ export declare function DeepSeekOnboardingDialog(props: DeepSeekOnboardingDialogProps): ReactNode;
38
+ //# sourceMappingURL=DeepSeekOnboardingDialog.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The action row every provider card ends with: dismiss on the left, commit on
3
+ * the right.
4
+ *
5
+ * The two cards commit different things — one creates a route, one edits an
6
+ * existing profile — but the row itself carries no such knowledge. It renders
7
+ * what it is handed, so the cards keep sole ownership of when a commit is
8
+ * allowed and what the in-flight wording is.
9
+ *
10
+ * Cancel refuses input only while a commit is in flight, never because the card
11
+ * is disabled: a card the deployment cannot write to must still be dismissable.
12
+ *
13
+ * @module dsh-client-ui-settings-models/client/EditorFooter
14
+ */
15
+ import type { ReactNode } from 'react';
16
+ import type { en } from './locales.ts';
17
+ /** Props of {@link EditorFooter}. */
18
+ export interface EditorFooterProps {
19
+ /** Localizer for the row's own labels. */
20
+ t: (key: keyof typeof en) => string;
21
+ /** Whether a commit is in flight; holds Cancel and swaps the commit label. */
22
+ busy: boolean;
23
+ /** Whether the commit is refused, as judged by the owning card. */
24
+ submitDisabled: boolean;
25
+ /** Commit label while idle. */
26
+ submitLabelKey: keyof typeof en;
27
+ /** Commit label while a commit is in flight. */
28
+ submitBusyLabelKey: keyof typeof en;
29
+ /** Dismiss label; defaults to the settings editor copy. */
30
+ cancelLabelKey?: keyof typeof en;
31
+ /** Dismiss the card without committing. */
32
+ onCancel: () => void;
33
+ /** Run the card's commit. */
34
+ onSubmit: () => void;
35
+ }
36
+ /**
37
+ * Render one provider card's action row.
38
+ * @param props - the labels, commit gating, and handlers the owning card supplies.
39
+ * @returns the cancel/commit row.
40
+ */
41
+ export declare function EditorFooter(props: EditorFooterProps): ReactNode;
42
+ //# sourceMappingURL=EditorFooter.d.ts.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The model list of one pi-ai provider profile, plus the action that asks the
3
+ * provider what it serves.
4
+ *
5
+ * The list is the profile's `models` array as the card holds it: an empty list
6
+ * means "serve this route's built-in catalog", and any entry replaces that
7
+ * catalog, so a row is only ever added deliberately. Fetching asks the endpoint
8
+ * **the form currently shows** — including a key typed but not yet saved — so
9
+ * adding a provider is one pass instead of save-then-return; the reply is
10
+ * candidates the user picks from, never configuration written behind them.
11
+ *
12
+ * A provider that cannot be interrogated (an unreachable endpoint, a protocol
13
+ * with no readable listing) is not a dead end: the failure is shown next to the
14
+ * rows the user can still fill in by hand.
15
+ */
16
+ import type { ReactNode } from 'react';
17
+ import type { DeepSeekModelDraft } from './DeepSeekModelsEditor.tsx';
18
+ import { type ModelsWire } from './store.ts';
19
+ import type { en } from './locales.ts';
20
+ /**
21
+ * One configured model row. Fields this card does not edit must survive an
22
+ * edit rather than being dropped by a rebuild.
23
+ */
24
+ export type ModelDraft = DeepSeekModelDraft;
25
+ /** What an interrogation needs, taken from the live form. */
26
+ export interface ProbeTarget {
27
+ /** Settings namespace whose adapter family answers. */
28
+ settingsNs: string;
29
+ /**
30
+ * Route being edited, when the card edits one. An adapter that already
31
+ * describes it answers from its own registry, so such a card can ask without
32
+ * an endpoint at all.
33
+ */
34
+ provider?: string;
35
+ /** Endpoint as the form currently shows it. */
36
+ baseURL?: string;
37
+ /** Wire protocol the form names, when it names one. */
38
+ api?: string;
39
+ /** Key typed into the form and not yet stored, when there is one. */
40
+ apiKey?: string;
41
+ }
42
+ /** Props of {@link ModelListEditor}. */
43
+ export interface ModelListEditorProps {
44
+ /** The rows as currently drafted. */
45
+ models: readonly ModelDraft[];
46
+ /** Whether the user layer currently owns the whole array; absent on a create. */
47
+ overridden?: boolean;
48
+ /** Replace the drafted rows. */
49
+ onChange: (models: ModelDraft[]) => void;
50
+ /** Remove the user-owned array and return to inheritance; absent on a create. */
51
+ onReset?: () => void;
52
+ /** Endpoint facts for the fetch action. */
53
+ probe: ProbeTarget;
54
+ /**
55
+ * Copy key naming why the fetch action is unavailable, or `undefined` when
56
+ * it is. The card owns this because the key it would send is judged there:
57
+ * asking with a key the form has already refused spends a round trip to be
58
+ * told what the field already says.
59
+ */
60
+ probeBlocked?: keyof typeof en | undefined;
61
+ /** Wire face the fetch action calls. */
62
+ api: Pick<ModelsWire, 'llm'>;
63
+ /** Section copy. */
64
+ t: (key: keyof typeof en) => string;
65
+ /** Disable every control (read-only deployment or a pending write). */
66
+ disabled: boolean;
67
+ }
68
+ /**
69
+ * Render the model list with its fetch action.
70
+ * @param props - the drafted rows, probe target, wire face, and copy.
71
+ * @returns the model-list editor.
72
+ */
73
+ export declare function ModelListEditor(props: ModelListEditorProps): ReactNode;
74
+ //# sourceMappingURL=ModelListEditor.d.ts.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Models settings section: the provider rows joined from the configurable
3
+ * directory, settings namespaces, and credential states, with one editor
4
+ * card at a time. Rows expose only confirmed API-key state through accessible
5
+ * solid configured or missing dots. A whole-section provider without a
6
+ * configured key renders as its open setup card instead of a row, but only in
7
+ * the first-run posture — no provider on the page can serve requests yet — and
8
+ * only until the user closes that card; the add flow is a card carrying the
9
+ * dormant-provider select. Each card kind owns its own open state, so closing
10
+ * one never discards a draft in another. Every mutation writes through the
11
+ * wire, while a provider removal first requires confirmation; the page
12
+ * re-renders from pushed invalidations or the post-apply reload.
13
+ */
14
+ import type { ReactNode } from 'react';
15
+ import type { InjectFace, PropsRenderSlots } from '@prettier-ai/dsh-client-ui-slots';
16
+ import type { ModelsSettingsStore, ModelsWire, ProviderRow } from './store.ts';
17
+ import type { SettingsSchemaOperations } from './schema-operations.ts';
18
+ import type { en } from './locales.ts';
19
+ /** Injected dependencies of {@link ModelsSection} (slot `inject`). */
20
+ export interface ModelsSectionInjected {
21
+ /** The page store (loaded on mount, refreshed on pushed invalidations). */
22
+ controller: ModelsSettingsStore;
23
+ hooks: {
24
+ /** Page snapshot bound by the UI renderer as useSnapshot. */
25
+ snapshot: ModelsSettingsStore['store'];
26
+ };
27
+ /** Wire faces the editor writes through. */
28
+ api: ModelsWire;
29
+ /** Settings schema and immutable path callbacks. */
30
+ schema: SettingsSchemaOperations;
31
+ /** Section copy. */
32
+ t: (key: keyof typeof en) => string;
33
+ }
34
+ /** The child slots this section declares and dispatches (see ./slot-contract.ts). */
35
+ type ModelsChildSlots = 'settings.models.provider-card' | 'settings.models.footer';
36
+ /**
37
+ * Props delivered by the slot outlet: the inject face spread flat (the
38
+ * renderer erases the share boundary at the render call) plus the child-slot
39
+ * dispatch seat. The seat is required: the renderer binds it at the render
40
+ * call itself — unlike the inject face it is never absent at runtime — and a
41
+ * direct render that forgets it fails to compile instead of mounting nothing.
42
+ */
43
+ export type ModelsSectionProps = Partial<InjectFace<ModelsSectionInjected>> & PropsRenderSlots<ModelsChildSlots>;
44
+ /** Provider identity shared by row actions and confirmation copy. */
45
+ export interface ProviderIdentity {
46
+ /** Stable provider route id. */
47
+ provider: string;
48
+ /** Human-facing provider name. */
49
+ displayName: string;
50
+ }
51
+ /**
52
+ * Remove one user-added provider and its page-managed credential. Credential
53
+ * removal comes first so a second-step failure leaves the provider row visible
54
+ * and the whole operation safely retryable; both unsets are idempotent.
55
+ * The settings removal names the profile rather than rebuilding its whole
56
+ * namespace from a partial view.
57
+ * @param api - settings and credential wire faces.
58
+ * @param controller - the page store to refresh.
59
+ * @param target - the provider's settings address and optional managed credential.
60
+ * @returns the failure message, or undefined once the write and reload landed.
61
+ */
62
+ export declare function removeProviderProfile(api: Pick<ModelsWire, 'settings' | 'credentials'>, controller: ModelsSettingsStore, target: {
63
+ settingsNs: string;
64
+ settingsPath: readonly string[];
65
+ credentialRef?: string;
66
+ }): Promise<string | undefined>;
67
+ /**
68
+ * Whether a whole-section provider still needs its first key: an unconfigured
69
+ * credential opens the setup card instead of showing a row. This is the
70
+ * first-run posture alone — a user who can already reach some provider gets an
71
+ * ordinary row with the missing-key dot, since nothing here is blocking them.
72
+ * @param row - the joined provider row.
73
+ * @param anyUsable - whether any joined row can already serve requests.
74
+ * @returns whether to render the setup card.
75
+ */
76
+ export declare function needsSetup(row: ProviderRow, anyUsable: boolean): boolean;
77
+ /** Stable visible and accessible identity for one provider target. */
78
+ export declare function providerTargetLabel(target: ProviderIdentity): string;
79
+ /** Replace the one provider placeholder in localized destructive-action copy. */
80
+ export declare function providerCopy(template: string, target: ProviderIdentity): string;
81
+ /**
82
+ * Render the Models section content column.
83
+ * @param props - slot-delivered injected dependencies.
84
+ * @returns the section, or null while the shell has not injected yet.
85
+ */
86
+ export declare function ModelsSection(props: ModelsSectionProps): ReactNode;
87
+ export {};
88
+ //# sourceMappingURL=ModelsSection.d.ts.map
@@ -0,0 +1,15 @@
1
+ /** Shared modal chrome for every step registered by this onboarding plugin. */
2
+ import type { ReactNode } from 'react';
3
+ /**
4
+ * Render a blocking onboarding dialog and keep the application root inert.
5
+ * @param props.title - accessible and visible dialog title.
6
+ * @param props.focusTitle - focus the title when the step has no form control.
7
+ * @param props.children - step-owned body and actions.
8
+ * @returns the body-portaled modal.
9
+ */
10
+ export declare function OnboardingModal({ title, focusTitle, children, }: {
11
+ title: string;
12
+ focusTitle?: boolean;
13
+ children: ReactNode;
14
+ }): ReactNode;
15
+ //# sourceMappingURL=OnboardingModal.d.ts.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * One provider's editor card, hand-written per adapter family: the primary
3
+ * field is a single write-only **API key** input (the page never asks for an
4
+ * environment-variable name — a typed key stores through `credentials/set`
5
+ * under the profile's reference, deriving `<ROUTE>_API_KEY` when the profile
6
+ * has none. The pi-ai profile records that derivation as `apiKeyEnv` only when
7
+ * a key is entered; a blank key materializes a reference-free profile for
8
+ * provider-native authentication);
9
+ * the collapsed 自定义设置 area carries the per-family extras (`baseURL` for
10
+ * both families, DeepSeek's id/name/context-window model catalog, and the
11
+ * display name and wire protocol of a pi-ai route the adapter does not ship —
12
+ * the two fields the create card asked that route for, editable here for the
13
+ * same reason).
14
+ * Reasoning effort is deliberately absent: it is a per-MODEL capability, and
15
+ * the models under one provider disagree about it, so a provider-scoped
16
+ * control can only be set to a value some of them reject. The composer's
17
+ * model picker offers each model its own levels; `settings.yaml` keeps the
18
+ * profile field for a deployment that knows its route. Everything else stays
19
+ * owned by `settings.yaml`. Profile edits land as minimal `settings.mutate`
20
+ * path ops against the stored section — the card names only the fields it can
21
+ * see instead of rebuilding the whole subtree from a partial descriptor.
22
+ */
23
+ import type { ReactNode } from 'react';
24
+ import type { SettingsNamespaceView, SettingsPathOpView } from '@prettier-ai/dsh-api-remotes/client';
25
+ import type { ModelsWire } from './store.ts';
26
+ import type { SettingsSchemaOperations } from './schema-operations.ts';
27
+ import type { en } from './locales.ts';
28
+ /** Props of {@link ProviderEditor}. */
29
+ export interface ProviderEditorProps {
30
+ /** Provider route id. */
31
+ provider: string;
32
+ /** Display name for the card title. */
33
+ displayName: string;
34
+ /** Hide the title row (the add card renders its own provider select). */
35
+ hideTitle?: boolean;
36
+ /**
37
+ * Whether the adapter reports this route as hand-declared — absent from its
38
+ * installed catalog. Such a route carries its own wire protocol, chosen when
39
+ * it was created and editable here for the same reason; a catalog route's
40
+ * models each carry theirs, so a route-level protocol there could only
41
+ * override every one of them and the card does not offer it.
42
+ */
43
+ declared?: boolean;
44
+ /** The owning namespace view (schema, layers, secrets). */
45
+ namespace: SettingsNamespaceView;
46
+ /** Settings-owned synchronous schema and immutable path operations. */
47
+ schema: SettingsSchemaOperations;
48
+ /** Path from the section root to this provider's profile. */
49
+ settingsPath: readonly string[];
50
+ /** Wire faces for writes and for interrogating a provider endpoint. */
51
+ api: ModelsWire;
52
+ /** Section copy. */
53
+ t: (key: keyof typeof en) => string;
54
+ /** Disable writes (read-only settings provider). */
55
+ readOnly: boolean;
56
+ /** Render only the credential field and actions, without provider settings. */
57
+ credentialOnly?: boolean;
58
+ /** Require a newly entered credential before this editor can submit. */
59
+ credentialRequired?: boolean;
60
+ /** Give the credential field initial focus when this editor mounts. */
61
+ autoFocusCredential?: boolean;
62
+ /** Override the dismiss action copy. */
63
+ cancelLabelKey?: keyof typeof en;
64
+ /** Override the idle commit action copy. */
65
+ submitLabelKey?: keyof typeof en;
66
+ /** Override the in-flight commit action copy. */
67
+ submitBusyLabelKey?: keyof typeof en;
68
+ /** Close the editor; `changed` reports whether an Apply committed. */
69
+ onClose: (changed: boolean) => void;
70
+ }
71
+ /**
72
+ * The minimal path ops carrying `after` over `before`, both as the card sees
73
+ * them. Only keys the card observed are named; fields absent from both sides
74
+ * produce no op, which is why edits are path-addressed rather than a rebuilt
75
+ * section.
76
+ * @param base - path of the edited subtree inside the user section.
77
+ * @param before - the subtree as loaded, or undefined when it is new.
78
+ * @param after - the subtree as edited.
79
+ * @returns ordered set/unset ops; empty when nothing changed.
80
+ */
81
+ export declare function pathOps(base: readonly string[], before: unknown, after: Record<string, unknown>): SettingsPathOpView[];
82
+ /**
83
+ * Render one provider's editing card.
84
+ * @param props - the addressed profile plus wire faces and copy.
85
+ * @returns the editor card.
86
+ */
87
+ export declare function ProviderEditor(props: ProviderEditorProps): ReactNode;
88
+ //# sourceMappingURL=ProviderEditor.d.ts.map
@@ -0,0 +1,26 @@
1
+ /** Product-wide, versioned internal-testing notice. */
2
+ import type { ReactNode } from 'react';
3
+ import type { SnapshotStore } from '@prettier-ai/dsh-client-store';
4
+ import type { InjectFace, PropsRuntime } from '@prettier-ai/dsh-client-ui-slots';
5
+ import type { WelcomeNoticeState, WelcomeNoticeStore } from './welcome-store.ts';
6
+ import type { en } from './locales.ts';
7
+ /** Registration-side dependencies of {@link WelcomeNotice}. */
8
+ export interface WelcomeNoticeInjected {
9
+ hooks: {
10
+ /** Durable or process-local acknowledgement state. */
11
+ welcome: SnapshotStore<WelcomeNoticeState>;
12
+ };
13
+ /** Welcome acknowledgement controller. */
14
+ controller: WelcomeNoticeStore;
15
+ /** Onboarding copy. */
16
+ t: (key: keyof typeof en) => string;
17
+ }
18
+ /** Coordinator owner props plus this step's injected face. */
19
+ export type WelcomeNoticeProps = PropsRuntime<'settings.onboarding'> & InjectFace<WelcomeNoticeInjected>;
20
+ /**
21
+ * Render the current notice until its exact copy version is acknowledged.
22
+ * @param props - settings-shell owner state and welcome dependencies.
23
+ * @returns the welcome modal or null while the step decides not to show.
24
+ */
25
+ export declare function WelcomeNotice(props: WelcomeNoticeProps): ReactNode;
26
+ //# sourceMappingURL=WelcomeNotice.d.ts.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Browser-side judgement of a typed API key.
3
+ * @module @prettier-ai/dsh-client-ui-settings-models/apiKey
4
+ */
5
+ /**
6
+ * Copy key naming why a typed key cannot be saved. A wrapped paste reports the
7
+ * same format failure as an illegal character: the reader's next move is the
8
+ * same either way — look at the key and paste it again — so naming the two
9
+ * causes apart would spend the field's one line on a distinction that changes
10
+ * nothing about what to do.
11
+ */
12
+ export type ApiKeyFailureKey = 'keyBlank' | 'keyIllegalCharacters';
13
+ /**
14
+ * Judge the key input's current value.
15
+ *
16
+ * An empty field is not a failure: every card opens with it empty even when a
17
+ * key is already stored, where it means keep that one. A field holding only
18
+ * whitespace is a failure rather than an empty field, so typed input is never
19
+ * silently discarded.
20
+ * @param draft - the key input's current value, untrimmed.
21
+ * @returns the copy key for a field-level failure, or `undefined` to allow submit.
22
+ */
23
+ export declare function apiKeyFailure(draft: string): ApiKeyFailureKey | undefined;
24
+ //# sourceMappingURL=apiKey.d.ts.map
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Models settings and product-onboarding plugin, browser half. It registers
3
+ * the Models page plus the ordered internal-testing and official-DeepSeek
4
+ * onboarding dialogs, whose UI shares this package's modal wrapper. The Host
5
+ * settings and credential contracts stay behind their existing wire APIs.
6
+ * Export discipline:
7
+ * packages/client/AGENTS.md.
8
+ */
9
+ import type { Context as ClientContext } from '@prettier-ai/cordis';
10
+ import { ModelsSettingsStore } from './store.ts';
11
+ import { type ModelsKey } from './locales.ts';
12
+ export type { ModelsSectionInjected, ModelsSectionProps } from './ModelsSection.tsx';
13
+ export type { ModelsFooterOwnerProps, ProviderCardExtrasOwnerProps } from './slot-contract.ts';
14
+ export type { ModelsKey } from './locales.ts';
15
+ declare module '@prettier-ai/dsh-client-ui-slots' {
16
+ interface LocaleNamespaceMap {
17
+ /** The Models page + product-onboarding copy. */
18
+ 'settings.models': ModelsKey;
19
+ }
20
+ }
21
+ export type { ModelsCredentials, ModelsLlm, ModelsSettingsState, ModelsWire, ProviderDirectoryEntry, ProviderRow, } from './store.ts';
22
+ /**
23
+ * Refetch the page snapshot only after its first load: an unopened Models
24
+ * page must not fetch on background invalidations.
25
+ * @param controller - the page store.
26
+ */
27
+ export declare function refreshIfLoaded(controller: ModelsSettingsStore): void;
28
+ /**
29
+ * Required services (cordis fiber inject). The target slot is declared by
30
+ * ui-settings' apply, whose activation order relative to this one is NOT
31
+ * constrained; registration depends on each slot through `slots.inject()`.
32
+ */
33
+ export declare const inject: string[];
34
+ /**
35
+ * Register the Models section once the `settings.section` declaration is on
36
+ * the ledger, wire its store to the connection, and keep it fresh on every
37
+ * pushed invalidation (settings, credentials, or provider topology).
38
+ * @param ctx - client root context.
39
+ */
40
+ export declare function apply(ctx: ClientContext): void;
41
+ //# sourceMappingURL=index.d.ts.map