@wy35002/dsh-model-fallback-ui 0.1.2-alpha.3

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 model-fallback settings panel. */
4
+ function apply() {}
5
+ //#endregion
6
+ export { apply };
@@ -0,0 +1,20 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@deepseek-ai/dsh-client-ui-model-fallback`.
4
+ * @module @deepseek-ai/dsh-client-ui-model-fallback/invariant
5
+ */
6
+ const PACKAGE_NAME = "@deepseek-ai/dsh-client-ui-model-fallback";
7
+ /** Cordis companion plugin name. */
8
+ const name = "client-ui-model-fallback-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 that renders a fixed
13
+ * content column and edits the `model-fallback` settings namespace through the
14
+ * standard settings transport; it emits no cordis events and owns no cross-plugin
15
+ * mutable relation beyond that namespace.
16
+ */
17
+ const install = () => {};
18
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
19
+ //#endregion
20
+ export { apply, inject, name };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Model-fallback settings section. Two modes resolved from the `model-fallback`
3
+ * settings namespace:
4
+ *
5
+ * - Auto (default): the plugin auto-discovers free models and tries them first
6
+ * before any paid model. The panel exposes free-model overrides and a
7
+ * per-provider "trust whole provider (unknown = free)" list.
8
+ * - Manual: an explicit, ordered fallback chain (shown only when the chain is
9
+ * non-empty).
10
+ *
11
+ * Edits are local until Save writes through the settings transport with
12
+ * revision fencing; Revert reloads the current namespace.
13
+ */
14
+ import { type ReactNode } from 'react';
15
+ import type { InjectFace, PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots';
16
+ import type { ModelFallbackActions, ModelFallbackStore } from './store.ts';
17
+ import type { en } from './locales.ts';
18
+ export interface ModelFallbackSectionInjected {
19
+ controller: ModelFallbackStore;
20
+ hooks: {
21
+ snapshot: ModelFallbackStore['store'];
22
+ };
23
+ actions: ModelFallbackActions;
24
+ t: (key: keyof typeof en) => string;
25
+ }
26
+ type ModelFallbackChildSlots = never;
27
+ type ModelFallbackProps = Partial<InjectFace<ModelFallbackSectionInjected>> & PropsRenderSlots<ModelFallbackChildSlots>;
28
+ export declare function ModelFallbackSection(props: ModelFallbackProps): ReactNode;
29
+ export {};
30
+ //# sourceMappingURL=ModelFallbackSection.d.ts.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Model-fallback settings panel, browser half: registers a settings section
3
+ * that edits the `model-fallback` namespace (fallback chain + switching
4
+ * policy). Discovery is limited to registered providers over the remote llm
5
+ * namespace; model ids are typed by the user.
6
+ */
7
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
8
+ import { type ModelFallbackKey } from './locales.ts';
9
+ export type { ModelFallbackSectionInjected } from './ModelFallbackSection.tsx';
10
+ export type { ModelFallbackKey } from './locales.ts';
11
+ export type { ChainEntry, FallbackPolicy, ModelFallbackActions, ModelFallbackSnapshot } from './store.ts';
12
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
13
+ interface LocaleNamespaceMap {
14
+ /** Model-fallback settings section copy. */
15
+ 'model.fallback': ModelFallbackKey;
16
+ }
17
+ }
18
+ export declare const inject: string[];
19
+ export declare function apply(ctx: ClientContext): void;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,60 @@
1
+ /** Copy dictionaries for the model-fallback settings section. */
2
+ export declare const en: {
3
+ readonly nav: "Model fallback";
4
+ readonly title: "Model fallback";
5
+ readonly intro: "When the current model is rate-limited or out of quota the plugin auto-switches: free models are tried first (discovered automatically), then any paid model only if your policy allows. Override which models count as free, or trust a whole provider.";
6
+ readonly modeLabel: "Mode";
7
+ readonly modeAuto: "Auto (discovered free pool, fail-closed)";
8
+ readonly modeManual: "Manual (explicit chain)";
9
+ readonly chainLabel: "Fallback chain";
10
+ readonly chainEmpty: "No chain configured. Add entries below to switch to explicit chain mode; otherwise the plugin runs in auto mode.";
11
+ readonly chainHelp: "Explicit, ordered chain. Only models you list here are tried, in this order.";
12
+ readonly pos: "Order";
13
+ readonly provider: "Provider";
14
+ readonly model: "Model";
15
+ readonly modelPlaceholder: "Select a model";
16
+ readonly modelHelp: "Enter a model id. Use the Models settings page or the model-fallback-discover tool to see what each provider offers.";
17
+ readonly kind: "Tier";
18
+ readonly kindPrimary: "Primary";
19
+ readonly kindFree: "Free";
20
+ readonly kindPaid: "Paid";
21
+ readonly addEntry: "Add entry";
22
+ readonly removeEntry: "Remove";
23
+ readonly moveUp: "Move up";
24
+ readonly moveDown: "Move down";
25
+ readonly freeLabel: "Free-model overrides";
26
+ readonly freeEmpty: "No overrides. The plugin uses its built-in community free-model table.";
27
+ readonly freeHelp: "Pick a provider, then load and click its configured models to mark them free beyond the built-in table.";
28
+ readonly freeProvider: "Provider";
29
+ readonly addFree: "Add";
30
+ readonly loadModels: "Load models";
31
+ readonly loadingModels: "Loading…";
32
+ readonly modelsEmpty: "This provider reports no models.";
33
+ readonly modelPickerHelp: "Click a model to add it as free.";
34
+ readonly modelAdded: "Added";
35
+ readonly unknownFreeLabel: "Trust whole provider (treat unknown models as free)";
36
+ readonly unknownFreeEmpty: "None — unknown models are treated as paid (fail-closed).";
37
+ readonly unknownFreeHelp: "Check a provider you trust entirely; its unrecognized models are counted as free.";
38
+ readonly policyLabel: "Switching policy";
39
+ readonly paidPolicy: "Switching into a paid model";
40
+ readonly paidPolicyAsk: "Ask me each time";
41
+ readonly paidPolicyAuto: "Switch automatically";
42
+ readonly paidPolicyNever: "Never switch to paid";
43
+ readonly switchCodesLabel: "Fail codes that trigger a switch";
44
+ readonly switchCodesHelp: "Space-separated. RATE_LIMIT and QUOTA are the defaults.";
45
+ readonly skipQuota: "On quota exhaustion, skip the rest of the same provider";
46
+ readonly save: "Save";
47
+ readonly saving: "Saving…";
48
+ readonly saved: "Saved";
49
+ readonly revert: "Revert";
50
+ readonly readOnly: "The settings document is read-only in this deployment.";
51
+ readonly loadFailed: "Could not load the fallback settings";
52
+ readonly conflict: "The settings changed while you were editing. Reopen to see the current values.";
53
+ readonly writeError: "Could not save the settings";
54
+ readonly providerEmpty: "No registered providers";
55
+ };
56
+ export type ModelFallbackKey = keyof typeof en;
57
+ export declare const zh: {
58
+ [Key in ModelFallbackKey]: string;
59
+ };
60
+ //# sourceMappingURL=locales.d.ts.map
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Page store for the model-fallback settings section. It mirrors the
3
+ * `model-fallback` settings namespace into an editable draft (chain, free-model
4
+ * overrides, per-provider "unknown is free" trust, and switching policy), joins
5
+ * registered providers for the dropdowns, and serializes saves through the
6
+ * settings transport with revision fencing.
7
+ */
8
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
9
+ import { type SnapshotStore } from '@deepseek-ai/dsh-client-store';
10
+ import type { LlmModelInfo, LlmProviderInfo } from '@deepseek-ai/dsh-api-remotes/client';
11
+ import type { SettingsScope } from '@deepseek-ai/dsh-client-ui-settings/client';
12
+ /** Must match the host plugin's DEFAULT_SWITCHABLE_CODES. */
13
+ export declare const DEFAULT_SWITCHABLE_CODES: readonly string[];
14
+ export interface ChainEntry {
15
+ provider: string;
16
+ model: string;
17
+ kind: 'primary' | 'free' | 'paid';
18
+ }
19
+ export interface ModelOverrideGroup {
20
+ provider: string;
21
+ ids: string[];
22
+ }
23
+ export interface FallbackPolicy {
24
+ paidSwitchPolicy: 'ask' | 'auto' | 'never';
25
+ skipProviderOnQuota: boolean;
26
+ }
27
+ /** Raw namespace value shape the client decodes before it reaches the store. */
28
+ export interface ModelFallbackNamespaceValue {
29
+ chain?: ChainEntry[];
30
+ paidSwitchPolicy?: string;
31
+ skipProviderOnQuota?: boolean;
32
+ switchableCodes?: string[];
33
+ freeModelIds?: ModelOverrideGroup[];
34
+ paidModelIds?: ModelOverrideGroup[];
35
+ unknownFreeProviders?: string[];
36
+ }
37
+ export interface ModelFallbackSnapshot {
38
+ status: 'idle' | 'loading' | 'ready' | 'error';
39
+ error: string | null;
40
+ writable: boolean;
41
+ revision: number | undefined;
42
+ chain: ChainEntry[];
43
+ policy: FallbackPolicy;
44
+ switchableCodes: string[];
45
+ freeModelIds: ModelOverrideGroup[];
46
+ paidModelIds: ModelOverrideGroup[];
47
+ unknownFreeProviders: string[];
48
+ providers: LlmProviderInfo[];
49
+ saving: boolean;
50
+ saveError: string | null;
51
+ saved: boolean | null;
52
+ }
53
+ export interface ModelFallbackActions {
54
+ load: () => Promise<void>;
55
+ setChain: (chain: ChainEntry[]) => void;
56
+ setEntry: (index: number, entry: ChainEntry) => void;
57
+ addEntry: () => void;
58
+ removeEntry: (index: number) => void;
59
+ moveEntry: (from: number, to: number) => void;
60
+ setPolicy: (policy: Partial<FallbackPolicy>) => void;
61
+ setSwitchableCodes: (codes: string[]) => void;
62
+ addFreeModel: (provider: string, modelId: string) => void;
63
+ removeFreeModel: (groupIndex: number, modelIndex: number) => void;
64
+ addPaidModel: (provider: string, modelId: string) => void;
65
+ removePaidModel: (groupIndex: number, modelIndex: number) => void;
66
+ toggleUnknownFreeProvider: (provider: string) => void;
67
+ fetchProviderModels: (provider: string) => Promise<LlmModelInfo[]>;
68
+ save: () => Promise<'ok' | 'conflict' | 'error'>;
69
+ revert: () => void;
70
+ }
71
+ export declare class ModelFallbackStore {
72
+ private readonly ctx;
73
+ private readonly scope;
74
+ readonly store: SnapshotStore<ModelFallbackSnapshot>;
75
+ private disposers;
76
+ constructor(ctx: ClientContext, scope: SettingsScope<ModelFallbackNamespaceValue>);
77
+ private refetchFromScope;
78
+ load(): Promise<void>;
79
+ private fetchProviders;
80
+ readonly actions: ModelFallbackActions;
81
+ dispose(): void;
82
+ }
83
+ export declare function createModelFallbackStore(ctx: ClientContext, scope: SettingsScope<ModelFallbackNamespaceValue>): ModelFallbackStore;
84
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,4 @@
1
+ /** Host loader entry for the browser implementation exported from `./client`. */
2
+ /** Host plugin body — no host-side behavior for the model-fallback settings panel. */
3
+ export declare function apply(): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Package-owned invariant companion for `@deepseek-ai/dsh-client-ui-model-fallback`.
3
+ * @module @deepseek-ai/dsh-client-ui-model-fallback/invariant
4
+ */
5
+ import type { Context } from '@deepseek-ai/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "client-ui-model-fallback-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ export declare const apply: (ctx: Context) => Promise<() => void>;
11
+ //# sourceMappingURL=invariant.d.ts.map
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@wy35002/dsh-model-fallback-ui",
3
+ "description": "Click-to-label settings panel for the model-fallback auto-switch chain: label registered models free/paid and build the fallback order",
4
+ "version": "0.1.2-alpha.3",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/client/ui-model-fallback"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./client": {
26
+ "types": "./lib/types/client/index.d.ts",
27
+ "default": "./lib/client.js"
28
+ },
29
+ "./cordis.patch.yml": "./cordis.patch.yml",
30
+ "./src/*": "./src/*",
31
+ "./package.json": "./package.json"
32
+ },
33
+ "dsh": {
34
+ "bundle": {
35
+ "patch": "./cordis.patch.yml"
36
+ },
37
+ "client": {
38
+ "inject": [
39
+ "@deepseek-ai/dsh-client-ui-settings",
40
+ "@deepseek-ai/dsh-client-locale",
41
+ "@deepseek-ai/dsh-client-store",
42
+ "@deepseek-ai/dsh-api-remotes"
43
+ ],
44
+ "platform": "web"
45
+ }
46
+ },
47
+ "scripts": {
48
+ "bundle": "tsdown",
49
+ "watch": "tsdown --watch"
50
+ },
51
+ "license": "MIT",
52
+ "peerDependencies": {
53
+ "@deepseek-ai/cordis": "^4.0.2"
54
+ },
55
+ "devDependencies": {
56
+ "@deepseek-ai/dsh-api-remotes": "workspace:^",
57
+ "@deepseek-ai/dsh-client-locale": "workspace:^",
58
+ "@deepseek-ai/dsh-client-store": "workspace:^",
59
+ "@deepseek-ai/dsh-client-ui-primitives": "workspace:^",
60
+ "@deepseek-ai/dsh-client-ui-renderer": "workspace:^",
61
+ "@deepseek-ai/dsh-client-ui-settings": "workspace:^",
62
+ "@deepseek-ai/dsh-client-ui-slots": "workspace:^",
63
+ "@deepseek-ai/dsh-invariants": "workspace:^",
64
+ "@deepseek-ai/dsh-util-values": "workspace:^",
65
+ "@types/react": "~18.3.1",
66
+ "@deepseek-ai/cordis": "workspace:^",
67
+ "react": "^18.2.0"
68
+ },
69
+ "files": [
70
+ "lib/index.js",
71
+ "lib/invariant.js",
72
+ "lib/client.js",
73
+ "lib/types/**/*.d.ts",
74
+ "cordis.patch.yml"
75
+ ]
76
+ }