dsh-llm-fallbacks 0.4.2 → 0.4.4

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.
@@ -102,6 +102,7 @@ export declare const zh: {
102
102
  'allDay.hint': string;
103
103
  'allDay.flash': string;
104
104
  'allDay.pro': string;
105
+ 'allDay.proCaveat': string;
105
106
  'allDay.nonconforming': string;
106
107
  'roles.list.label': string;
107
108
  'roles.list.hint': string;
@@ -111,9 +112,11 @@ export declare const zh: {
111
112
  'roles.idPlaceholder': string;
112
113
  'roles.persona': string;
113
114
  'roles.personaPlaceholder': string;
114
- 'roles.seedDefault': string;
115
- 'roles.seedOverride': string;
116
- 'roles.revertPersona': string;
115
+ 'roles.persona.expand': string;
116
+ 'roles.persona.collapse': string;
117
+ 'roles.persona.empty': string;
118
+ 'roles.seedSource.bundled': string;
119
+ 'roles.seedSource.user': string;
117
120
  'roles.seedChainOptional': string;
118
121
  'roles.fallback': string;
119
122
  'roles.fallback.inherit-root': string;
@@ -182,6 +185,7 @@ export declare const zh: {
182
185
  'chat.switch.summary': string;
183
186
  'chat.switch.summary.roleInject': string;
184
187
  'chat.switch.roleMap': string;
188
+ 'subagentRole.hover': string;
185
189
  'defaults.prefix': string;
186
190
  save: string;
187
191
  'save.saving': string;
@@ -296,6 +300,7 @@ export declare const en: {
296
300
  'allDay.hint': string;
297
301
  'allDay.flash': string;
298
302
  'allDay.pro': string;
303
+ 'allDay.proCaveat': string;
299
304
  'allDay.nonconforming': string;
300
305
  'roles.list.label': string;
301
306
  'roles.list.hint': string;
@@ -305,9 +310,11 @@ export declare const en: {
305
310
  'roles.idPlaceholder': string;
306
311
  'roles.persona': string;
307
312
  'roles.personaPlaceholder': string;
308
- 'roles.seedDefault': string;
309
- 'roles.seedOverride': string;
310
- 'roles.revertPersona': string;
313
+ 'roles.persona.expand': string;
314
+ 'roles.persona.collapse': string;
315
+ 'roles.persona.empty': string;
316
+ 'roles.seedSource.bundled': string;
317
+ 'roles.seedSource.user': string;
311
318
  'roles.seedChainOptional': string;
312
319
  'roles.fallback': string;
313
320
  'roles.fallback.inherit-root': string;
@@ -376,6 +383,7 @@ export declare const en: {
376
383
  'chat.switch.summary': string;
377
384
  'chat.switch.summary.roleInject': string;
378
385
  'chat.switch.roleMap': string;
386
+ 'subagentRole.hover': string;
379
387
  'defaults.prefix': string;
380
388
  save: string;
381
389
  'save.saving': string;
package/dist/config.d.ts CHANGED
@@ -91,7 +91,7 @@ export interface FallbacksConfig {
91
91
  maxSwitchesPerStep: number;
92
92
  alwaysModeRetryCap: number;
93
93
  /**
94
- * Preset-role injection switch: `'bundled'` declares the 7 preset roles
94
+ * Preset-role injection switch: `'bundled'` declares the 5 preset roles
95
95
  * (spec §9.2) as seed rows on apply; `'none'` disables declaration.
96
96
  * Optional on purpose — a required field would break library consumers
97
97
  * that construct `FallbacksConfig` literals with the existing 8 keys
package/dist/events.d.ts CHANGED
@@ -4,9 +4,11 @@
4
4
  * Writing is stopped (issue #52): the plugin no longer appends this event —
5
5
  * the apply()-time event-type registration was proven ineffective (module
6
6
  * instance mismatch), and a session containing the event refused to load
7
- * after a dsh restart. The event now exists only in history: old logs are
8
- * repaired by `scripts/repair-fallbacks-switch-logs.ts`, which marks legacy
9
- * events ignorable so affected sessions load again.
7
+ * after a dsh restart. The event now exists only in history: old logs that
8
+ * contain it cannot be repaired by an `ignorable` flag (the released
9
+ * session-format chain refuses unknown event types even when marked
10
+ * ignorable), so `scripts/repair-fallbacks-switch-logs.ts` is a detector
11
+ * that reports such logs and never writes.
10
12
  * The module is type-only — the augmentation is erased at runtime; the
11
13
  * plugin's runtime behavior lives in `src/index.ts`.
12
14
  *
package/dist/gateway.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * T1 (plan llm-fallbacks-settings-gateway) + T3 (plan fallbacks-role-seeds) —
3
3
  * host-side `fallbacks` config gateway: the `/api/fallbacks/get` +
4
4
  * `/api/fallbacks/set` + `/api/fallbacks/reset` + `/api/fallbacks/revert-seed`
5
- * endpoints.
5
+ * + `/api/fallbacks/subagent-roles` endpoints.
6
6
  *
7
7
  * Transport: the typertGateway `/api` interceptor is the single host-wide RPC
8
8
  * slot (a plugin must NOT `connection.rpc.intercept('/api')` again — it would
@@ -43,6 +43,11 @@
43
43
  * `revert-seed` exposes revert-to-current-seed-default for one id — both
44
44
  * delegate to the per-apply `FallbacksSeedManager` passed into the
45
45
  * constructor (single point of truth, no copied manager logic).
46
+ * `subagent-roles` (plan subagent-role-badge T2) is the read-only badge
47
+ * readback: it projects the per-apply dispatch-resolved role-record map
48
+ * (same T1 map the inject block writes, via the optional snapshot fn) for a
49
+ * batch of session ids — unknown ids are omitted, an unwired or throwing
50
+ * snapshot degrades to `{}`, never an error.
46
51
  *
47
52
  * The settings service is OPTIONAL (no settings service → the bridge source
48
53
  * stays the entry, `get` still works; `set`/`reset` fail with a clear
@@ -126,6 +131,29 @@ export type SubagentPolicySnapshotFn = () => {
126
131
  reason: string;
127
132
  };
128
133
  };
134
+ /**
135
+ * One dispatch-resolved subagent role record on the wire (plan
136
+ * subagent-role-badge T2): the role the subagent's dispatch resolved and the
137
+ * route it actually runs after the inject decision. `model` is optional on
138
+ * the WIRE type only — the writer (T1) always sets it, but a record without
139
+ * one still reads back as `{ role, at }` instead of failing the readback.
140
+ */
141
+ export type SubagentRoleRecord = {
142
+ role: string;
143
+ model?: {
144
+ provider: string;
145
+ model: string;
146
+ };
147
+ at: number;
148
+ };
149
+ /**
150
+ * Live role-record snapshot the gateway reads through (plan
151
+ * subagent-role-badge T2) — the `SubagentPolicySnapshotFn` pattern: built in
152
+ * `apply()` over the SAME T1 map the dispatch inject block writes, no second
153
+ * record source. Optional: constructors that omit it make the
154
+ * `/api/fallbacks/subagent-roles` endpoint return `{}`.
155
+ */
156
+ export type SubagentRolesSnapshotFn = () => ReadonlyMap<string, SubagentRoleRecord>;
129
157
  /**
130
158
  * The live configuration source for the gateway (guide §7 — the same bridge
131
159
  * shape the runtime reads through). `source()` returns the live composed
@@ -184,6 +212,12 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
184
212
  * used by gateway unit tests stays byte-identical to the pre-T5 payload.
185
213
  */
186
214
  private readonly subagentPolicy;
215
+ /**
216
+ * Optional role-record snapshot (plan subagent-role-badge T2). When omitted
217
+ * the `subagentRoles` endpoint returns `{}` — every existing constructor
218
+ * call site keeps its payload byte-identical.
219
+ */
220
+ private readonly subagentRolesSnapshot;
187
221
  /**
188
222
  * @param ctx - owning context (the plugin fiber's ctx inside `apply`).
189
223
  * @param bridge - the same `FallbacksSettingsBridge` the runtime reads, so
@@ -193,8 +227,11 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
193
227
  * copied manager logic), through the io seam built over this bridge.
194
228
  * @param subagentPolicy - live host-policy snapshot from `apply()`; omit
195
229
  * to leave the additive field off the wire.
230
+ * @param subagentRoles - live dispatch-resolved role-record snapshot from
231
+ * `apply()` (plan subagent-role-badge T2); omit to make the
232
+ * `subagent-roles` endpoint return `{}`.
196
233
  */
197
- constructor(ctx: Context, bridge: FallbacksSettingsBridge, seeds: FallbacksSeedManager, subagentPolicy?: SubagentPolicySnapshotFn);
234
+ constructor(ctx: Context, bridge: FallbacksSettingsBridge, seeds: FallbacksSeedManager, subagentPolicy?: SubagentPolicySnapshotFn, subagentRoles?: SubagentRolesSnapshotFn);
198
235
  /**
199
236
  * Read the current composed config (schema defaults → entry base → settings
200
237
  * user layer). No hard-gate resolver (ADR-2): the raw composed config is
@@ -253,6 +290,22 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
253
290
  * write channel is unavailable (KD-G5).
254
291
  */
255
292
  revertSeed(id: string): Promise<FallbacksRevertResult>;
293
+ /**
294
+ * Batch readback of dispatch-resolved subagent role records (plan
295
+ * subagent-role-badge T2) — the read side of the session-header role badge.
296
+ * Ids are agent ids (≡ session ids: the same id space the dispatch inject
297
+ * block records under). Unknown/absent ids are OMITTED from the result,
298
+ * never an error — the badge renders nothing for them. No snapshot wired
299
+ * (pre-T2 constructors) or a throwing snapshot ⇒ `{}` — degrade-never-crash,
300
+ * the same fail-closed shape as `projectSubagentPolicy`.
301
+ * @param ids - the session ids to read (at most
302
+ * {@link SUBAGENT_ROLES_MAX_IDS} entries).
303
+ * @returns a plain JSON object keyed by KNOWN id only, each carrying the
304
+ * wire record (`role`, `at`, `model` when the record has one).
305
+ * @throws TypeError when `ids` is not an array of strings or the batch
306
+ * exceeds {@link SUBAGENT_ROLES_MAX_IDS} entries.
307
+ */
308
+ subagentRoles(ids: string[]): Record<string, SubagentRoleRecord>;
256
309
  /**
257
310
  * Read the live composed config and normalize it to the typertGateway JSON
258
311
  * wire boundary. Containment (guide §10): a malformed stored user layer
package/dist/index.d.ts CHANGED
@@ -38,7 +38,7 @@ import { Config } from './schema.ts';
38
38
  import { resolveChain } from './chains.ts';
39
39
  import { resolveRole } from './roles.ts';
40
40
  import { FallbackStateStore, type BlockedSwitchAttempt, type EffectiveChainHead } from './state.ts';
41
- import { type EffectiveRolesReadback, type SeedDeclaration, type SeedDeclareOutcome, type SeedRevertOutcome } from './seeds.ts';
41
+ import { type EffectiveRolesReadback, type SeedDeclaration, type SeedDeclareOutcome, type SeedRevertOutcome, type SeedsDeclareOptions } from './seeds.ts';
42
42
  /** The plugin row id mounted by the profile bundle patch. */
43
43
  export declare const name = "llm-fallbacks";
44
44
  /**
@@ -66,8 +66,14 @@ export interface FallbacksService {
66
66
  resolveChain: typeof resolveChain;
67
67
  validateFallbacksConfig: typeof validateFallbacksConfig;
68
68
  detectLegacyKeys: typeof detectLegacyKeys;
69
- /** (a) Declare the companion's FULL current seed set (replacement semantics, spec §9.1). */
70
- declareSeeds(seeds: readonly SeedDeclaration[]): Promise<SeedDeclareOutcome>;
69
+ /**
70
+ * (a) Declare the companion's FULL current seed set (replacement semantics,
71
+ * spec §9.1). The optional `options.set` records the batch's registered
72
+ * provenance set name (read back as the rows' `source`); there is
73
+ * deliberately no way to label a declare `bundled` — reserved for the
74
+ * plugin's own preset self-declare.
75
+ */
76
+ declareSeeds(seeds: readonly SeedDeclaration[], options?: SeedsDeclareOptions): Promise<SeedDeclareOutcome>;
71
77
  /** (b) Sync readback — effective taxonomy with seed annotations. */
72
78
  getEffectiveRoles(): EffectiveRolesReadback;
73
79
  /** (c) Revert one id to the CURRENT declared seed default. */
@@ -83,14 +89,14 @@ export { Config };
83
89
  /** The plugin's composition config — the `fallbacks` settings schema (spec §4). */
84
90
  export type Config = FallbacksConfig;
85
91
  export type { FallbackSwitchReason, FallbacksSwitchEventData } from './events.ts';
86
- export type { AgentFallbackState, BlockedSwitchAttempt, FallbackStateStore, PendingSwitch, StepFailures } from './state.ts';
92
+ export type { AgentFallbackState, BlockedSwitchAttempt, FallbackStateStore, PendingSwitch, StepFailures, SwitchScope } from './state.ts';
87
93
  /** @internal T5 test-seam types (mirrors `BlockedSwitchAttempt`; not public API). */
88
94
  export type { ChainHeadSource, EffectiveChainHead } from './state.ts';
89
95
  export { resolveRole, type AgentLike, type Origin, } from './roles.ts';
90
96
  export { annotateCandidates, createCandidateFilter, hasWildcardEntry, resolveCandidate, resolveChain, resolveChainViews, selectCandidates, type AnnotatedCandidate, type CandidateFilterOptions, type CandidateSkipReason, type FailingModel, } from './chains.ts';
91
97
  export { defaultFallbacksConfig, detectLegacyKeys, INHERIT_ROLE_ID, ROLE_ID_PATTERN, validateFallbacksConfig, type FallbacksConfig, type FallbacksConfigLogger, type FallbacksRole, type FallbacksRoles, type FallbacksRoleRule, type FallbackStrategy, type RevertPolicy, type RecoveryPolicy, } from './config.ts';
92
98
  export { parseSelector, SelectorError, type Selector, } from './selectors.ts';
93
- export { FallbacksSeedManager, type EffectiveRole, type EffectiveRolesReadback, type SeedConflict, type SeedDeclaration, type SeedDeclareOutcome, type SeedRevertFailReason, type SeedRevertOutcome, type SeedSkipReason, type SeedsIo, type SeedsWireStatus, } from './seeds.ts';
99
+ export { FallbacksSeedManager, type EffectiveRole, type EffectiveRolesReadback, type SeedConflict, type SeedDeclaration, type SeedDeclareOutcome, type SeedRevertFailReason, type SeedRevertOutcome, type SeedSkipReason, type SeedSource, type SeedsDeclareOptions, type SeedsIo, type SeedsWireStatus, } from './seeds.ts';
94
100
  export { presetRoles } from './presets.ts';
95
101
  /**
96
102
  * @internal Test seam (T3 review Minor 3): the per-agent fallback state store
@@ -116,6 +122,29 @@ export declare function blockedAttempts(ctx: Context): ReadonlyMap<string, Block
116
122
  * plugin is applied.
117
123
  */
118
124
  export declare function chainHeads(ctx: Context): ReadonlyMap<string, EffectiveChainHead> | undefined;
125
+ /**
126
+ * One dispatch-resolved subagent role record (plan subagent-role-badge T1):
127
+ * the role `resolveRoleAtDispatch` resolved at the subagent's first request
128
+ * and the route the subagent will actually run after the inject decision
129
+ * (the override target when it applies, else the host seed).
130
+ */
131
+ type SubagentRoleRecord = {
132
+ role: string;
133
+ model: {
134
+ provider: string;
135
+ model: string;
136
+ };
137
+ at: number;
138
+ };
139
+ /**
140
+ * @internal Test seam (mirrors `chainHeads`): the per-agent dispatch-resolved
141
+ * role records written by the role-inject block (plan subagent-role-badge T1)
142
+ * for the plugin applied to `ctx`. Not part of the plugin's public surface;
143
+ * lets tests read the badge record without reaching into the closure (the
144
+ * gateway readback closes over the per-apply map directly). `undefined` when
145
+ * no plugin is applied.
146
+ */
147
+ export declare function subagentRoleRecords(ctx: Context): ReadonlyMap<string, SubagentRoleRecord> | undefined;
119
148
  /**
120
149
  * Count durable `llm/retry` events for the current (turn, step, provider) in
121
150
  * **always mode** (ADR-2; spec §2 clause 5). Normal-mode retries belong to