dsh-llm-fallbacks 0.4.3 → 0.5.0

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Time-slot rows for `fallbacks` (plan fallbacks-timeslots Task 1, pins
3
- * P4–P6): frozen preset windows, the official-V4 all-day conformance
3
+ * P4–P6): frozen preset windows, the official all-day conformance
4
4
  * guard, and the pure `resolveEffectiveChain` / `resolveSlotState`
5
5
  * resolver.
6
6
  *
@@ -15,9 +15,17 @@
15
15
  * @module dsh-llm-fallbacks/time-slots
16
16
  */
17
17
  import type { FallbacksConfig } from './config.ts';
18
- /** Official V4 models — the ONLY legal all-day selectors (length 1, XOR). */
19
- export declare const OFFICIAL_V4_FLASH = "deepseek-official/deepseek-v4-flash";
20
- export declare const OFFICIAL_V4_PRO = "deepseek-official/deepseek-v4-pro";
18
+ /** Official all-day selectors — the ONLY legal tails (length 1, XOR):
19
+ * Flash (the current official default, selectable) and Pro (displayed but
20
+ * disabled — its model is not yet served by the 0.1.5-rc.1 catalog). The
21
+ * retired V4 ids (`deepseek-v4-flash` / `deepseek-v4-pro`) are no longer
22
+ * legal tails. */
23
+ export declare const OFFICIAL_FLASH = "deepseek-official/deepseek-flash";
24
+ export declare const OFFICIAL_PRO = "deepseek-official/deepseek-pro";
25
+ /** The two official all-day tail ids (XOR — exactly one legal tail). */
26
+ export declare const OFFICIAL_ALL_DAY_IDS: readonly ["deepseek-official/deepseek-flash", "deepseek-official/deepseek-pro"];
27
+ /** Whether `id` is one of the two official all-day tail ids. */
28
+ export declare function isOfficialAllDayId(id: string): boolean;
21
29
  /** The four frozen preset ids (exact strings, spec lock). */
22
30
  export declare const PRESET_IDS: readonly ["liang-peak", "liang-valley", "glm-peak", "glm-valley"];
23
31
  export type PresetId = (typeof PRESET_IDS)[number];
@@ -65,12 +73,13 @@ export interface PresetDefinition {
65
73
  export declare const PRESETS: Record<PresetId, PresetDefinition>;
66
74
  /**
67
75
  * All-day conformance (P6): the all-day chain is conforming when its LAST
68
- * entry (the tail — the card's 默认模型 panel) is exactly one official V4
69
- * model — Flash XOR Pro. Leading entries (the card's 默认降级链 block) are
70
- * the ordered walk before that last-resort fallback. An empty chain or a
71
- * chain whose tail is not an official V4 model keeps slot rows inert and
72
- * refuses the virtual-row override/delegate; the v0.2.2 failure walk over
73
- * the raw chain stays verbatim.
76
+ * entry (the tail — the card's 默认模型 panel) is exactly one official
77
+ * model — Flash or Pro (XOR). Leading entries (the card's 默认降级链 block)
78
+ * are the ordered walk before that last-resort fallback. An empty chain or
79
+ * a chain whose tail is not an official model (including the retired V4
80
+ * ids) keeps slot rows inert and refuses the virtual-row
81
+ * delegate; the v0.2.2 failure walk over the raw chain stays
82
+ * verbatim.
74
83
  */
75
84
  export declare function isAllDayConforming(chain: readonly string[]): boolean;
76
85
  /**
@@ -83,7 +92,8 @@ export declare function isAllDayConforming(chain: readonly string[]): boolean;
83
92
  * P6 (qc1 F-001): without a conforming all-day the slot rows are inert, so
84
93
  * this IS the raw `rootChain` — the gate lives in {@link resolveSlotState},
85
94
  * the single source every slot surface (this, the 分时切换 log, the
86
- * `/fallbacks` strip, select-is-primary, the virtual adapter delegate) reads.
95
+ * `/fallbacks` strip, the virtual adapter delegate, its served-route anchor)
96
+ * reads.
87
97
  */
88
98
  export declare function resolveEffectiveChain(config: FallbacksConfig, now: Date, tz: string): string[];
89
99
  /**
@@ -14,7 +14,7 @@
14
14
  * reconcile thunk, wired by `apply()`) plus child activation. The row is
15
15
  * visible whenever the plugin is enabled — a non-conforming all-day chain
16
16
  * does NOT hide it (PR #62 feedback); conformance still gates a
17
- * successful override/delegate (`effectiveHeadOf` below refuses a
17
+ * successful delegate (`effectiveHeadOf` below refuses a
18
18
  * non-conforming all-day). The condition deliberately ignores `timeSlots`
19
19
  * and conformance, so slot-row edits and chain edits never churn
20
20
  * registration.
@@ -26,12 +26,14 @@
26
26
  * `agent/request-error`, where the existing engine walks from there).
27
27
  * `resolveModel` proxies the current effective head's metadata when
28
28
  * resolvable (modalities/context-window/reasoning follow the head) with a
29
- * permissive default otherwise — never throws.
29
+ * permissive default otherwise — never throws. `providerRetryPolicy` and
30
+ * `imageRequestPricing` mirror the same head for the host-captured retry
31
+ * policy and the token meter — also never throwing.
30
32
  *
31
33
  * @module dsh-llm-fallbacks/virtual-adapter
32
34
  */
33
35
  import type { Context } from '@deepseek-ai/cordis';
34
- import { LlmAdapter, type GenerateOptions, type LlmImageRequestPricing, type LlmModelInfo, type LlmResolvedModelInfo, type LlmRuntime, type StreamChunk } from '@deepseek-ai/dsh-llm';
36
+ import { LlmAdapter, type GenerateOptions, type LlmImageRequestPricing, type LlmModelInfo, type LlmResolvedModelInfo, type LlmRuntime, type ResolvedRetryPolicy, type StreamChunk } from '@deepseek-ai/dsh-llm';
35
37
  import type { FallbacksConfig } from './config.ts';
36
38
  /** Provider route of the virtual adapter (exact string, spec lock). */
37
39
  export declare const FALLBACKS_PROVIDER = "FallbacksChain";
@@ -62,15 +64,33 @@ export interface EffectiveHead {
62
64
  }
63
65
  /**
64
66
  * The FIRST DISPATCHABLE exact head of a chain — the single definition of
65
- * "effective head" (F-001) shared by the root select-is-primary override
66
- * (`src/index.ts`) and the virtual adapter's delegate paths. Walks the SAME
67
- * chain `resolveEffectiveChain` produces, skipping entries that can never
67
+ * "effective head" (F-001) shared by the virtual adapter's delegate paths and
68
+ * the routing engine's served-route anchor (`anchorServedRoute` in
69
+ * `src/index.ts`). Walks the SAME chain `resolveEffectiveChain` produces,
70
+ * skipping entries that can never
68
71
  * be dispatched: malformed selectors (config-warning path), `provider/*`
69
72
  * `provider/*` wildcards (no real pair), and self-routes back to
70
73
  * `FallbacksChain/*` (the P1 recursion guard). `undefined` when the chain
71
74
  * is empty or no entry is dispatchable.
72
75
  */
73
76
  export declare function firstDispatchableExactHead(chain: readonly string[]): EffectiveHead | undefined;
77
+ /**
78
+ * The effective chain head at `now` (P1): the first DISPATCHABLE exact head
79
+ * of the SAME `resolveEffectiveChain` the routing engine uses — thin
80
+ * config+clock entry into the shared {@link firstDispatchableExactHead} (no
81
+ * divergent skip/walk rules). `undefined` when the chain is empty or no
82
+ * entry is dispatchable (wildcard, self-route to `FallbacksChain/*`,
83
+ * malformed selector).
84
+ *
85
+ * Conformance gate (PR #62 feedback): the all-day `rootChain` must be
86
+ * conforming (exactly one official model — Flash or Pro)
87
+ * for a successful delegate —
88
+ * a legacy multi-model (or empty) all-day chain earns no primary
89
+ * semantics even though the picker row is visible. `resolveModel` then
90
+ * falls back to the permissive default and `stream()` throws
91
+ * {@link UNDISPATCHABLE_HEAD_CODE}.
92
+ */
93
+ export declare function effectiveHeadOf(config: FallbacksConfig, now: Date): EffectiveHead | undefined;
74
94
  /**
75
95
  * Host picker label: `Auto: <displayName>[<slot>]`.
76
96
  * Display name first so the trigger stays readable and platforms stay
@@ -104,6 +124,22 @@ export declare class FallbacksChainAdapter extends LlmAdapter {
104
124
  * answer for the CURRENT head. Permissive default otherwise; never throws.
105
125
  */
106
126
  resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo>;
127
+ /**
128
+ * Route-accurate retry attribution: the virtual row declares no policy of
129
+ * its own — the virtual `provider` argument is intentionally ignored. The
130
+ * host captures `adapter.providerRetryPolicy(provider) ??
131
+ * resolveRetryPolicy(void 0, …)` ONCE, when a route is registered, so
132
+ * answering here with the SAME policy the concrete head route declared
133
+ * (e.g. a user's `llm-deepseek.retryPolicy`, including `mode: 'always'`)
134
+ * keeps retries behaving exactly as they do on the head `stream()`
135
+ * dispatches. Never throws: an unresolvable head, a vanished `llm`, or an
136
+ * unregistered head provider degrades to `undefined` — the host's own
137
+ * default. That last arm matters: the runtime's lookup THROWS `NO_ADAPTER`
138
+ * for an unknown provider, and this call happens inside the plugin's
139
+ * `registerAdapter`, so an escaping throw would take the whole virtual
140
+ * route down instead of just degrading its policy.
141
+ */
142
+ providerRetryPolicy(_provider: string): ResolvedRetryPolicy | undefined;
107
143
  /**
108
144
  * Route-accurate image pricing (0.1.2 adoption): the virtual row has no
109
145
  * pricing of its own — the virtual `provider`/`model` arguments are
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "dsh",
6
6
  "dsh-plugin"
7
7
  ],
8
- "version": "0.4.3",
8
+ "version": "0.5.0",
9
9
  "type": "module",
10
10
  "main": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts",
@@ -47,9 +47,10 @@
47
47
  "build-client": "tsx scripts/build-client.ts",
48
48
  "release:prepare": "tsx scripts/prepare-release.ts",
49
49
  "release:validate": "tsx scripts/validate-release-version.ts",
50
- "repair:fallbacks-switch-logs": "tsx scripts/repair-fallbacks-switch-logs.ts",
50
+ "repair:session-logs": "tsx scripts/repair-session-logs.ts",
51
51
  "test": "vitest run",
52
- "typecheck": "tsc -p tsconfig.build.json --noEmit && tsc --noEmit",
52
+ "typecheck": "tsc -p tsconfig.build.json --noEmit && tsc --noEmit && pnpm run typecheck:scripts",
53
+ "typecheck:scripts": "tsc -p tsconfig.scripts.json",
53
54
  "prepare": "pnpm run build"
54
55
  },
55
56
  "engines": {
@@ -60,45 +61,65 @@
60
61
  },
61
62
  "peerDependencies": {
62
63
  "@deepseek-ai/cordis": "^4.0.2",
63
- "@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
64
- "@deepseek-ai/dsh-api-gateway": "^0.1.2-rc.1",
65
- "@deepseek-ai/dsh-api-remotes": "^0.1.2-rc.1",
66
- "@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
67
- "@deepseek-ai/dsh-client-connection": "^0.1.2-rc.1",
68
- "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
69
- "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
70
- "@deepseek-ai/dsh-client-ui-chat": "^0.1.2-rc.1",
71
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-rc.1",
72
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
73
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1",
74
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
75
- "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-rc.1",
76
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
77
- "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
78
- "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
79
- "@deepseek-ai/dsh-llm-retry": "^0.1.2-rc.1",
80
- "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
81
- "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
82
- "@deepseek-ai/dsh-tool-subagent": "^0.1.2-rc.1",
83
- "@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1",
84
- "@deepseek-ai/dsh-typert-registry": "^0.1.2-rc.1",
64
+ "@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
65
+ "@deepseek-ai/dsh-api-gateway": "^0.1.5-rc.1",
66
+ "@deepseek-ai/dsh-api-remotes": "^0.1.5-rc.1",
67
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.5-rc.1",
68
+ "@deepseek-ai/dsh-client-connection": "^0.1.5-rc.1",
69
+ "@deepseek-ai/dsh-client-locale": "^0.1.5-rc.1",
70
+ "@deepseek-ai/dsh-client-store": "^0.1.5-rc.1",
71
+ "@deepseek-ai/dsh-client-ui-chat": "^0.1.5-rc.1",
72
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.1",
73
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.1",
74
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
75
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
76
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.5-rc.1",
77
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
78
+ "@deepseek-ai/dsh-commands": "^0.1.5-rc.1",
79
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
80
+ "@deepseek-ai/dsh-llm-retry": "^0.1.5-rc.1",
81
+ "@deepseek-ai/dsh-session": "^0.1.5-rc.1",
82
+ "@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
83
+ "@deepseek-ai/dsh-tool-subagent": "^0.1.5-rc.1",
84
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
85
+ "@deepseek-ai/dsh-typert-registry": "^0.1.5-rc.1",
85
86
  "@deepseek-ai/schemastery": "^3.18.2",
86
87
  "react": "^18.2.0"
87
88
  },
88
89
  "devDependencies": {
90
+ "@shikijs/langs": "^4.4.3",
89
91
  "@testing-library/dom": "^10.4.1",
90
92
  "@testing-library/react": "^16.3.2",
93
+ "@types/mdast": "^4.0.4",
91
94
  "@types/node": "^22.20.0",
92
95
  "@types/react": "~18.3.31",
93
96
  "@types/react-dom": "~18.3.7",
94
97
  "@types/use-sync-external-store": "^1.5.0",
98
+ "anser": "^2.3.5",
99
+ "clsx": "^2.1.1",
100
+ "immer": "^10.2.0",
95
101
  "jsdom": "29.1.1",
102
+ "katex": "^0.16.47",
103
+ "mdast-util-from-markdown": "^2.0.3",
104
+ "mdast-util-gfm": "^3.1.0",
105
+ "mdast-util-math": "^3.0.0",
106
+ "micromark-core-commonmark": "^2.0.3",
107
+ "micromark-extension-gfm": "^3.0.0",
108
+ "micromark-extension-math": "^3.1.0",
109
+ "micromark-factory-space": "^2.0.1",
110
+ "micromark-util-character": "^2.1.1",
111
+ "micromark-util-classify-character": "^2.0.1",
112
+ "micromark-util-sanitize-uri": "^2.0.1",
113
+ "micromark-util-symbol": "^2.0.1",
114
+ "micromark-util-types": "^2.0.2",
96
115
  "react": "^18.3.1",
97
116
  "react-dom": "^18.3.1",
117
+ "shiki": "^4.4.3",
98
118
  "tsdown": "^0.22.2",
99
119
  "tsx": "^4.22.4",
100
120
  "typescript": "^5.9.3",
101
- "vitest": "^4.1.8"
121
+ "vitest": "^4.1.8",
122
+ "zustand": "~4.4.7"
102
123
  },
103
124
  "repository": {
104
125
  "type": "git",
@@ -48,11 +48,15 @@ const OUT_FILE = 'index.js'
48
48
 
49
49
  /**
50
50
  * Frozen loader module table (dsh mechanism-guide): the plan-documented
51
- * composition = PLATFORM_MODULES (8 entries in 0.1.2, `web/src/platform.ts:8-15`
52
- * — the old runtime `./client` exemption became the
53
- * `@deepseek-ai/dsh-client-store` platform module, so the store VALUE import
54
- * stays external and resolves from the host loader table) + the
55
- * PRELOADED_CLIENT_EXTERNALS (empty in 0.1.2, `web/src/platform.ts:16-17`).
51
+ * composition = PLATFORM_MODULES (9 entries in 0.1.5-rc.1,
52
+ * `web/src/platform.ts:8-16` — the old runtime `./client` exemption became
53
+ * the `@deepseek-ai/dsh-client-store` platform module, so the store VALUE
54
+ * import stays external and resolves from the host loader table) + the
55
+ * host's PRELOADED_CLIENT_EXTERNALS (empty in `packages/client/web/src/platform.ts`).
56
+ * The table need not list
57
+ * every platform module — it lists what this plugin's client half resolves
58
+ * from the frozen loader table; the rc.1 addition
59
+ * `@deepseek-ai/dsh-client-ui-dockkit` is not imported by this plugin.
56
60
  * rc.8 dropped `dsh-client-web-react` (deleted
57
61
  * package — the uSES bridge is vendored in `src/client/use-snapshot.ts`),
58
62
  * `dsh-client-ui-attachment` and `dsh-client-schema-form` from the platform