dsh-llm-fallbacks 0.4.0-alpha.1 → 0.4.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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ![node](https://img.shields.io/badge/node-%3E%3D22-339933.svg)
8
8
  ![pnpm](https://img.shields.io/badge/pnpm-%3E%3D10-f69220.svg)
9
9
  ![dsh tui](https://img.shields.io/badge/dsh%20tui-compatible-4B32C3.svg)
10
- ![dsh](https://img.shields.io/badge/DSH-0.1.2--alpha.2-4B32C3.svg)
10
+ ![dsh](https://img.shields.io/badge/DSH-0.1.2--rc.1-4B32C3.svg)
11
11
  [![dshfind](https://dshfind.com/api/badge/omdsh-dev/dsh-llm-fallbacks?lang=en)](https://dshfind.com/zh/plugins/omdsh-dev/dsh-llm-fallbacks?ref=badge)
12
12
 
13
13
  Automatic provider/model fallback chains for dsh (DeepSeek Harness): when an agent's LLM requests keep failing — retries exhausted, auth errors, quota exceeded, rate limiting (429) — the plugin switches provider/model along the fallback chain for the current role, and the current step/turn continues on the target model: tasks are not interrupted by model problems.
package/README.zh-CN.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ![node](https://img.shields.io/badge/node-%3E%3D22-339933.svg)
8
8
  ![pnpm](https://img.shields.io/badge/pnpm-%3E%3D10-f69220.svg)
9
9
  ![dsh tui](https://img.shields.io/badge/dsh%20tui-compatible-4B32C3.svg)
10
- ![dsh](https://img.shields.io/badge/DSH-0.1.2--alpha.2-4B32C3.svg)
10
+ ![dsh](https://img.shields.io/badge/DSH-0.1.2--rc.1-4B32C3.svg)
11
11
  [![dshfind](https://dshfind.com/api/badge/omdsh-dev/dsh-llm-fallbacks?lang=zh)](https://dshfind.com/zh/plugins/omdsh-dev/dsh-llm-fallbacks?ref=badge)
12
12
 
13
13
  dsh(DeepSeek Harness)的自动模型降级插件:当 root agent 或 subagent 的模型请求持续失败(重试耗尽、权限、配额超限、限流 429)时,按角色/模型 fallback 链自动切换 provider/model,当前 step/turn 在目标模型上继续完成——任务不因模型问题中断。
@@ -51,6 +51,13 @@ export { FallbacksSettingsController, FALLBACKS_SETTINGS_NS } from './fallbacks-
51
51
  * it reflectively and degrades to the switches empty state when absent
52
52
  * (`setCurrentSession` never called, `loadSwitches` ready with an empty
53
53
  * array, which the store already supports).
54
+ *
55
+ * rc.1 dotted-namespace contract: each client Remote namespace is a
56
+ * child-fiber service named `remote.<ns>` (upstream `remoteServiceKey`), and
57
+ * the traceable proxy forwards `ctx.remote.llm` / `.settings` / `.session`
58
+ * to those context properties — consumers MUST declare the dotted names
59
+ * here or the fiber walk throws `cannot get property "remote.llm" without
60
+ * inject`. `remote` stays for the `$on` invalidation face.
54
61
  */
55
62
  export declare const inject: string[];
56
63
  /**
@@ -4489,13 +4489,23 @@ window.__ModuleLoader__.load({
4489
4489
  * it reflectively and degrades to the switches empty state when absent
4490
4490
  * (`setCurrentSession` never called, `loadSwitches` ready with an empty
4491
4491
  * array, which the store already supports).
4492
+ *
4493
+ * rc.1 dotted-namespace contract: each client Remote namespace is a
4494
+ * child-fiber service named `remote.<ns>` (upstream `remoteServiceKey`), and
4495
+ * the traceable proxy forwards `ctx.remote.llm` / `.settings` / `.session`
4496
+ * to those context properties — consumers MUST declare the dotted names
4497
+ * here or the fiber walk throws `cannot get property "remote.llm" without
4498
+ * inject`. `remote` stays for the `$on` invalidation face.
4492
4499
  */
4493
4500
  const inject = [
4494
4501
  "slots",
4495
4502
  "locale",
4496
4503
  "connection",
4497
4504
  "remote",
4498
- "uiConversation"
4505
+ "uiConversation",
4506
+ "remote.llm",
4507
+ "remote.settings",
4508
+ "remote.session"
4499
4509
  ];
4500
4510
  /**
4501
4511
  * Register the `fallbacks` dictionaries and the plugin-config card once the
@@ -48,7 +48,7 @@ export interface FallbacksCommandAgent {
48
48
  readonly header?: {
49
49
  readonly origin?: Origin;
50
50
  };
51
- readonly events: readonly unknown[];
51
+ readonly snapshotEvents: () => readonly unknown[];
52
52
  };
53
53
  }
54
54
  /** One active cooldown entry displayed by `/fallbacks`. */
package/dist/index.js CHANGED
@@ -2291,7 +2291,7 @@ async function makeModelExists(ctx, providers) {
2291
2291
  }
2292
2292
  function countRetryEvents(session, turn, step, provider) {
2293
2293
  let count = 0;
2294
- const events = session.events;
2294
+ const events = session.snapshotEvents();
2295
2295
  for (let index = events.length - 1; index >= 0; index -= 1) {
2296
2296
  const event = events[index];
2297
2297
  const data = event.data;
@@ -2348,7 +2348,7 @@ function authorizedRouteView(ctx, agent) {
2348
2348
  const parentOptions = parent?.options;
2349
2349
  return {
2350
2350
  requestHeader: agent.session?.requestHeader()?.config,
2351
- events: agent.session?.events,
2351
+ events: agent.session?.snapshotEvents(),
2352
2352
  options: agent.options,
2353
2353
  inherited: parentHeader ?? (typeof parentOptions?.provider === "string" && typeof parentOptions?.model === "string" ? {
2354
2354
  provider: parentOptions.provider,
@@ -2480,7 +2480,7 @@ function apply(ctx, config = defaultFallbacksConfig) {
2480
2480
  };
2481
2481
  if (agent.session?.header?.origin === "subagent" && target !== void 0) {
2482
2482
  const settingsRead = readGuardedPolicySettings(ctx, agent.id, lastKnownPolicySettings, logger.warn);
2483
- const policy = settingsRead.ok ? effectivePolicy(readSessionPolicyEvent(agent.session.events), settingsRead.settings) : { state: "unprovable" };
2483
+ const policy = settingsRead.ok ? effectivePolicy(readSessionPolicyEvent(agent.session.snapshotEvents()), settingsRead.settings) : { state: "unprovable" };
2484
2484
  if (policy.state === "unprovable") {
2485
2485
  logger.warn("llm-fallbacks: agent \"%s\" subagent model-selection policy is on but unreadable — skipping fallback switch", agent.id);
2486
2486
  return null;
@@ -2593,7 +2593,7 @@ function apply(ctx, config = defaultFallbacksConfig) {
2593
2593
  dispatchInjected.add(agent.id);
2594
2594
  try {
2595
2595
  const settingsRead = readGuardedPolicySettings(ctx, agent.id, lastKnownPolicySettings, logger.warn);
2596
- const policy = settingsRead.ok ? effectivePolicy(readSessionPolicyEvent(agent.session.events), settingsRead.settings) : { state: "unprovable" };
2596
+ const policy = settingsRead.ok ? effectivePolicy(readSessionPolicyEvent(agent.session.snapshotEvents()), settingsRead.settings) : { state: "unprovable" };
2597
2597
  if (policy.state === "unprovable") logger.warn("llm-fallbacks: agent \"%s\" subagent model-selection policy is on but unreadable — skipping role-inject", agent.id);
2598
2598
  else {
2599
2599
  const authorized = policy.state === "enabled" ? detectAuthorizedRoute(authorizedRouteView(ctx, agent)) : void 0;
@@ -2707,7 +2707,7 @@ function apply(ctx, config = defaultFallbacksConfig) {
2707
2707
  role,
2708
2708
  ...resolveChainForDiagnostic(config.roles.list, config.rootChain, role, logger.warn),
2709
2709
  slot: resolveSlotState(config, new Date(), config.tz ?? "Asia/Shanghai"),
2710
- switches: recentFallbacksSwitches(agent.session.events, 5),
2710
+ switches: recentFallbacksSwitches(agent.session.snapshotEvents(), 5),
2711
2711
  cooldown: state === void 0 ? [] : recovery === "half-open" ? [...state.cooldown.snapshot(), ...state.recovery.halfOpenEntries().map((entry) => ({
2712
2712
  key: entry.key,
2713
2713
  untilEpochMs: entry.untilEpochMs,
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "dsh",
6
6
  "dsh-plugin"
7
7
  ],
8
- "version": "0.4.0-alpha.1",
8
+ "version": "0.4.1",
9
9
  "type": "module",
10
10
  "main": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts",
@@ -60,28 +60,28 @@
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@deepseek-ai/cordis": "^4.0.2",
63
- "@deepseek-ai/dsh-agent": "^0.1.2-alpha.2",
64
- "@deepseek-ai/dsh-api-gateway": "^0.1.2-alpha.2",
65
- "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.2",
66
- "@deepseek-ai/dsh-api-session-controller": "^0.1.2-alpha.2",
67
- "@deepseek-ai/dsh-client-connection": "^0.1.2-alpha.2",
68
- "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.2",
69
- "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.2",
70
- "@deepseek-ai/dsh-client-ui-chat": "^0.1.2-alpha.2",
71
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-alpha.2",
72
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-alpha.2",
73
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2",
74
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.2",
75
- "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-alpha.2",
76
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.2",
77
- "@deepseek-ai/dsh-commands": "^0.1.2-alpha.2",
78
- "@deepseek-ai/dsh-llm": "^0.1.2-alpha.2",
79
- "@deepseek-ai/dsh-llm-retry": "^0.1.2-alpha.2",
80
- "@deepseek-ai/dsh-session": "^0.1.2-alpha.2",
81
- "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2",
82
- "@deepseek-ai/dsh-tool-subagent": "^0.1.2-alpha.2",
83
- "@deepseek-ai/dsh-typert-protocol": "^0.1.2-alpha.2",
84
- "@deepseek-ai/dsh-typert-registry": "^0.1.2-alpha.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",
85
85
  "@deepseek-ai/schemastery": "^3.18.2",
86
86
  "react": "^18.2.0"
87
87
  },