dsh-llm-fallbacks 0.6.13 → 0.7.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.
package/dist/config.d.ts CHANGED
@@ -94,7 +94,6 @@ export interface FallbacksConfig {
94
94
  cooldownMs: number;
95
95
  revertPolicy: RevertPolicy;
96
96
  maxSwitchesPerStep: number;
97
- alwaysModeRetryCap: number;
98
97
  /**
99
98
  * Preset-role injection switch: `'bundled'` declares the 5 preset roles
100
99
  * (spec §9.2) as seed rows on apply; `'none'` disables declaration.
@@ -105,19 +104,6 @@ export interface FallbacksConfig {
105
104
  * every resolved config carries a value via the schema default.
106
105
  */
107
106
  presets?: 'bundled' | 'none';
108
- /**
109
- * Dispatch-time LLM role auto-match switch (plan fallbacks-role-automatch
110
- * Task 1): when `true` (default), a subagent-origin request with no
111
- * explicit/rules-resolved role may have the best-fit declared role picked
112
- * by the LLM; `false` reproduces today's behavior exactly. Optional on
113
- * purpose, mirroring `presets` — a required field would break library
114
- * consumers that construct `FallbacksConfig` literals with the existing
115
- * keys (additive, non-breaking). The value domain is guarded by the
116
- * schema (`z.boolean().default(true)` in `src/schema.ts`), and the
117
- * runtime reads it defensively as `config.roleAutoMatch ?? true` (safe
118
- * for direct constructors that omit it).
119
- */
120
- roleAutoMatch?: boolean;
121
107
  /**
122
108
  * Extra time-slot rows (plan fallbacks-timeslots Task 1, P5): the FIRST
123
109
  * matching row's chain becomes the effective root chain at request time;
@@ -196,8 +182,10 @@ export declare function validateFallbacksConfig(config: FallbacksConfig, logger:
196
182
  /**
197
183
  * Detect legacy (two-block-era) leftovers in a config SOURCE — the composed
198
184
  * object `source()` returns, or a raw settings document. Recognizes the
199
- * removed `chains` key, the removed `roles.default` field, the removed
200
- * role-entity fields `roles.list[].label` / `roles.list[].description`
185
+ * removed `chains` key, the removed always-mode retry cap and dispatch
186
+ * role-auto-match keys (`alwaysModeRetryCap` / `roleAutoMatch` — direction
187
+ * C, virtual-chain-only fallback), the removed `roles.default` field, the
188
+ * removed role-entity fields `roles.list[].label` / `roles.list[].description`
201
189
  * (renamed to `persona`), and `roles.rules[].role` values that reference no
202
190
  * declared `roles.list` id and are not the built-in `'inherit'`. Returns
203
191
  * descriptive key/role names; the gateway attaches them as `get().legacyKeys`
@@ -1,15 +1,11 @@
1
1
  /**
2
- * Cooldown store + per-step failure set (spec §5.1; plan Task 2).
2
+ * Cooldown store (spec §5.1; plan Task 2).
3
3
  *
4
4
  * `CooldownStore` maps `provider/model` keys to an expiry epoch ms with lazy
5
5
  * evaluation: expired entries are dropped on read. `revertPolicy: 'never'`
6
6
  * is expressed by suppressing with `Infinity` — the entry never expires
7
7
  * within the session.
8
8
  *
9
- * `StepFailureSet` is the step's failed-model set (spec §5.1 `failed`).
10
- * `switchCount` / `maxSwitchesPerStep` judgement belongs to the caller
11
- * (Task 3) — this task only provides the data structure.
12
- *
13
9
  * @module dsh-llm-fallbacks/cooldown
14
10
  */
15
11
  /**
@@ -45,13 +41,3 @@ export declare class CooldownStore {
45
41
  untilEpochMs: number;
46
42
  }>;
47
43
  }
48
- /**
49
- * The current step's failed-model set (`${provider}/${model}` keys).
50
- */
51
- export declare class StepFailureSet {
52
- private keys;
53
- get size(): number;
54
- add(key: string): void;
55
- has(key: string): boolean;
56
- reset(): void;
57
- }
package/dist/events.d.ts CHANGED
@@ -15,15 +15,15 @@
15
15
  * @module dsh-llm-fallbacks/events
16
16
  */
17
17
  /**
18
- * Why a switch was decided (spec §5.1 `PendingSwitch.reason`).
18
+ * Why a switch was decided — a **history and bookkeeping vocabulary** since
19
+ * direction C, not a set of live decision paths.
19
20
  *
20
- * `role-inject` is the dispatch-time reason (plan fallbacks-role-automatch
21
- * Task 4): a subagent-origin agent's first request was re-routed to its
22
- * resolved role's chain head. It is ADDITIVE to the failure-time reasons —
23
- * the event shape stays a superset of the pre-feature payload, and existing
24
- * renderers show unknown reasons raw (AC-5). Unlike `trigger-code` /
25
- * `always-cap`, a `role-inject` event is NOT a failure decision: it carries
26
- * no pending switch / cooldown / failure bookkeeping (no `commit()`).
21
+ * `trigger-code` is the only reason the current code produces (the walk's
22
+ * swallowed trigger failure, and the blocked-attempt record that mirrors it).
23
+ * `always-cap` (retired always-mode cap) and `role-inject` (retired
24
+ * dispatch-time request override) survive only so legacy `fallbacks/switch`
25
+ * events and their renderers keep a label; nothing writes them any more, and
26
+ * an unknown reason still renders raw (AC-5).
27
27
  */
28
28
  export type FallbackSwitchReason = 'trigger-code' | 'always-cap' | 'role-inject';
29
29
  /** Durable payload of one provider/model switch (spec §5 table). */
package/dist/gateway.d.ts CHANGED
@@ -26,9 +26,9 @@
26
26
  * Data: `get` reads the `FallbacksSettingsBridge` source — the same live
27
27
  * composed config the runtime reads (schema defaults → plugin-row base →
28
28
  * profile patch). There is NO hard-gate resolver (unlike advisor's
29
- * `resolveAdvisorConfig`): the fallbacks decision path runs at
30
- * `agent/request` time in `src/index.ts`, so the gateway returns the raw
31
- * composed config. There is NO config-level `enabled` key on the contract
29
+ * `resolveAdvisorConfig`): the fallbacks decision path runs inside the
30
+ * virtual route's chain walk (`src/chain-walk.ts`), so the gateway returns
31
+ * the raw composed config. There is NO config-level `enabled` key on the contract
32
32
  * (plan fallbacks-web-ux-alignment T2): the Plugins-page row toggle is the
33
33
  * master switch, the runtime gates read content presence
34
34
  * (`isFallbackActive` in `src/config.ts`), and a stored `enabled:` line is
@@ -96,6 +96,8 @@ export type SubagentPolicyRoute = {
96
96
  provider: string;
97
97
  model: string;
98
98
  };
99
+ /** Settings namespace of the host's subagent-model-selection policy. */
100
+ export declare const SUBAGENT_POLICY_SETTINGS_NS = "subagent-model-selection-settings";
99
101
  /**
100
102
  * Additive `/api/fallbacks/get` host-policy snapshot (spec D4 / T5).
101
103
  * Omitted only when the snapshot is unwired (3-arg constructor) so older
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
- * dsh-llm-fallbacks host half (plan Task 3: settings + waterfall + state
3
- * machine + events).
2
+ * dsh-llm-fallbacks host half: settings, the virtual chain row, the dispatch
3
+ * seam, role seeds and the diagnostics surfaces (direction C, plan
4
+ * dsh-022-rc1-upgrade).
4
5
  *
5
6
  * Cordis function plugin mounted by the profile bundle patch row
6
7
  * `llm-fallbacks` (see `bundle/cordis.patch.yml`), composed AFTER llm-retry.
@@ -11,33 +12,25 @@
11
12
  * `apply` reads the Loader's live config reference, and the
12
13
  * `settings/document-updated` listener re-derives the runtime caches —
13
14
  * the old `installSection` setSource/onChange contract, spec §4).
14
- * - `agent/request-error` waterfall: inactive config (`isFallbackActive`) /
15
- * code ∉ `triggerCodes`
16
- * (**always mode included**) → `next()`; otherwise resolve role + chain,
17
- * and when a candidate survives the filter (current / cooldown /
18
- * step-failed / `provider/*`-missing-id) write the pending switch +
19
- * cooldown + failure bookkeeping, then return
20
- * `{ kind: 'retry' }` (own recovery, no `next()`).
21
- * - `agent/request` waterfall: apply a pending switch after `await next()`
22
- * (provider/model override; the inherited `reasoningEffort` follows the
23
- * upstream routeChanged rule — dropped on a route change unless explicitly
24
- * named, preserved on a same-route override; spec D3); a
25
- * root-origin `FallbacksChain/Auto` seed is served UNCHANGED (plan
26
- * model-change-notice-loop Task 1 — the route the loop serves and records
27
- * must equal the session selection, otherwise the host `model-selection`
28
- * notice is re-armed on every step; the virtual adapter's `stream()`
29
- * delegate is what reaches the chain head); then the always-mode cap check
30
- * (count `llm/retry` events for the current turn/step/provider; ≥
31
- * `alwaysModeRetryCap` → same decision path, reason `always-cap` —
32
- * ADR-2).
33
- * - Per-agent state (`FallbackStateStore`): `agent/disposed` removes it,
34
- * `agent/status` idle prunes per-step state defensively, plugin dispose
35
- * clears everything (spec §6 — no residual state).
15
+ * - The virtual `FallbacksChain/Auto` adapter is the ONLY fallback path: its
16
+ * `stream()` WALKS the session's chain (`src/chain-walk.ts`). No
17
+ * `agent/request` / `agent/request-error` listener is registered — rc.1
18
+ * rejects a request that changes the captured selection, and a
19
+ * request-error retry `continue`s with that captured selection, so the old
20
+ * waterfall could not route a retried attempt at all. Real-model sessions
21
+ * therefore have no plugin fallback; `llm-retry` owns their recovery.
22
+ * - Subagents: the dispatch seam (`src/subagents-seam.ts`) mounts an
23
+ * inheriting child on the virtual row by stamping its creation options
24
+ * (design §1.3) — creation-time only, so a resumed child's own durable
25
+ * selection always wins.
26
+ * - Per-agent state (`FallbackStateStore`): `agent/disposed` removes it, plugin
27
+ * dispose clears everything (spec §6 — no residual state). The cooldown /
28
+ * recovery circuit is the cross-call memory the walk reads; per-request
29
+ * bookkeeping lives inside one walk.
36
30
  *
37
31
  * @module dsh-llm-fallbacks
38
32
  */
39
33
  import type { Context } from '@deepseek-ai/cordis';
40
- import type { Session } from '@deepseek-ai/dsh-session';
41
34
  import { detectLegacyKeys, validateFallbacksConfig, type FallbacksConfig } from './config.ts';
42
35
  import { Config } from './schema.ts';
43
36
  import { resolveChain } from './chains.ts';
@@ -113,7 +106,7 @@ export { Config };
113
106
  /** The plugin's composition config — the `fallbacks` settings schema (spec §4). */
114
107
  export type Config = FallbacksConfig;
115
108
  export type { FallbackSwitchReason, FallbacksSwitchEventData } from './events.ts';
116
- export type { AgentFallbackState, BlockedSwitchAttempt, FallbackStateStore, PendingSwitch, StepFailures, SwitchScope } from './state.ts';
109
+ export type { AgentFallbackState, BlockedSwitchAttempt, FallbackStateStore } from './state.ts';
117
110
  /** @internal T5 test-seam types (mirrors `BlockedSwitchAttempt`; not public API). */
118
111
  export type { ChainHeadSource, EffectiveChainHead } from './state.ts';
119
112
  export { resolveRole, type AgentLike, type Origin, } from './roles.ts';
@@ -147,20 +140,6 @@ export declare function blockedAttempts(ctx: Context): ReadonlyMap<string, Block
147
140
  * plugin is applied.
148
141
  */
149
142
  export declare function chainHeads(ctx: Context): ReadonlyMap<string, EffectiveChainHead> | undefined;
150
- /**
151
- * Count durable `llm/retry` events for the current (turn, step, provider) in
152
- * **always mode** (ADR-2; spec §2 clause 5). Normal-mode retries belong to
153
- * llm-retry's bounded budget and must not preempt the fallback, so only
154
- * `mode: 'always'` events count toward `alwaysModeRetryCap` (T3 review
155
- * Minor 2 — the real event carries the discriminator, llm-retry types.ts).
156
- *
157
- * Fast path (T3 review Minor 4): the session log is append-ordered, so the
158
- * scan runs backwards and stops at the first event older than the target
159
- * (turn, step) — a long session's earlier turns are never scanned.
160
- *
161
- * Exported for direct unit testing of the counting + fast path.
162
- */
163
- export declare function countRetryEvents(session: Session, turn: number, step: number, provider: string): number;
164
143
  /**
165
144
  * The live config reference the Loader hands `apply` for a
166
145
  * volatile Config schema: an identity-stable `{ get }` view (cosmokit's