visionclaw 0.1.216-beta.1 → 0.1.216-beta.2
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/agent/engine-fallback.d.ts +175 -0
- package/dist/agent/engine-fallback.d.ts.map +1 -0
- package/dist/agent/engine-fallback.js +454 -0
- package/dist/agent/engine-fallback.js.map +1 -0
- package/dist/agent/engine-probe.d.ts +47 -0
- package/dist/agent/engine-probe.d.ts.map +1 -0
- package/dist/agent/engine-probe.js +99 -0
- package/dist/agent/engine-probe.js.map +1 -0
- package/dist/agent/engine-switch-target.d.ts.map +1 -1
- package/dist/agent/engine-switch-target.js +23 -5
- package/dist/agent/engine-switch-target.js.map +1 -1
- package/dist/agent/engine-switch.d.ts +21 -4
- package/dist/agent/engine-switch.d.ts.map +1 -1
- package/dist/agent/engine-switch.js +71 -22
- package/dist/agent/engine-switch.js.map +1 -1
- package/dist/agent/engines/pi/tools.js +2 -2
- package/dist/agent/engines/pi/tools.js.map +1 -1
- package/dist/agent/heartbeat-manager.d.ts +10 -6
- package/dist/agent/heartbeat-manager.d.ts.map +1 -1
- package/dist/agent/heartbeat-manager.js +30 -24
- package/dist/agent/heartbeat-manager.js.map +1 -1
- package/dist/agent/interrupt-handler.d.ts.map +1 -1
- package/dist/agent/interrupt-handler.js +2 -1
- package/dist/agent/interrupt-handler.js.map +1 -1
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +80 -15
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/model-provider.d.ts +63 -12
- package/dist/agent/model-provider.d.ts.map +1 -1
- package/dist/agent/model-provider.js +97 -34
- package/dist/agent/model-provider.js.map +1 -1
- package/dist/agent/nightly-maintenance/memory-dreaming.js +4 -4
- package/dist/agent/nightly-maintenance/memory-dreaming.js.map +1 -1
- package/dist/agent/nightly-maintenance/vocabulary-processor.d.ts +2 -11
- package/dist/agent/nightly-maintenance/vocabulary-processor.d.ts.map +1 -1
- package/dist/agent/nightly-maintenance/vocabulary-processor.js +36 -70
- package/dist/agent/nightly-maintenance/vocabulary-processor.js.map +1 -1
- package/dist/agent/onboarding-gate.d.ts.map +1 -1
- package/dist/agent/onboarding-gate.js +2 -0
- package/dist/agent/onboarding-gate.js.map +1 -1
- package/dist/agent/status.d.ts.map +1 -1
- package/dist/agent/status.js +27 -22
- package/dist/agent/status.js.map +1 -1
- package/dist/agent/transcript-summarizer.d.ts +2 -0
- package/dist/agent/transcript-summarizer.d.ts.map +1 -1
- package/dist/agent/transcript-summarizer.js +60 -7
- package/dist/agent/transcript-summarizer.js.map +1 -1
- package/dist/agent/vocabulary-evidence.d.ts +11 -0
- package/dist/agent/vocabulary-evidence.d.ts.map +1 -0
- package/dist/agent/vocabulary-evidence.js +17 -0
- package/dist/agent/vocabulary-evidence.js.map +1 -0
- package/dist/agent/vocabulary-glossary.d.ts +12 -3
- package/dist/agent/vocabulary-glossary.d.ts.map +1 -1
- package/dist/agent/vocabulary-glossary.js +69 -22
- package/dist/agent/vocabulary-glossary.js.map +1 -1
- package/dist/agent/vocabulary-injection.d.ts +8 -5
- package/dist/agent/vocabulary-injection.d.ts.map +1 -1
- package/dist/agent/vocabulary-injection.js +10 -12
- package/dist/agent/vocabulary-injection.js.map +1 -1
- package/dist/agent/wake-cycle-runner.d.ts +61 -3
- package/dist/agent/wake-cycle-runner.d.ts.map +1 -1
- package/dist/agent/wake-cycle-runner.js +304 -64
- package/dist/agent/wake-cycle-runner.js.map +1 -1
- package/dist/channels/finapp.d.ts.map +1 -1
- package/dist/channels/finapp.js +3 -1
- package/dist/channels/finapp.js.map +1 -1
- package/dist/channels/telegram.d.ts.map +1 -1
- package/dist/channels/telegram.js +3 -1
- package/dist/channels/telegram.js.map +1 -1
- package/dist/config/types.d.ts +3 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -1
- package/dist/onboarding/onboarding-service-client.d.ts +15 -6
- package/dist/onboarding/onboarding-service-client.d.ts.map +1 -1
- package/dist/onboarding/onboarding-service-client.js.map +1 -1
- package/dist/onboarding/prepare-linux.d.ts.map +1 -1
- package/dist/onboarding/prepare-linux.js +23 -3
- package/dist/onboarding/prepare-linux.js.map +1 -1
- package/dist/stt-client.d.ts.map +1 -1
- package/dist/stt-client.js +20 -14
- package/dist/stt-client.js.map +1 -1
- package/dist/tools/index.js +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/transcribe-audio.d.ts +4 -9
- package/dist/tools/transcribe-audio.d.ts.map +1 -1
- package/dist/tools/transcribe-audio.js +22 -33
- package/dist/tools/transcribe-audio.js.map +1 -1
- package/dist/transcription-context.d.ts +9 -0
- package/dist/transcription-context.d.ts.map +1 -0
- package/dist/transcription-context.js +12 -0
- package/dist/transcription-context.js.map +1 -0
- package/dist/utils/transcribe.d.ts +3 -2
- package/dist/utils/transcribe.d.ts.map +1 -1
- package/dist/utils/transcribe.js +5 -4
- package/dist/utils/transcribe.js.map +1 -1
- package/dist-agent/bundle.cjs +2 -2
- package/package.json +1 -1
- package/dist/agent/provider-fallback.d.ts +0 -69
- package/dist/agent/provider-fallback.d.ts.map +0 -1
- package/dist/agent/provider-fallback.js +0 -169
- package/dist/agent/provider-fallback.js.map +0 -1
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EngineFallbackManager — health, cooldowns and failover across engines.
|
|
3
|
+
*
|
|
4
|
+
* Failover happens between **engines** (`grok` / `gpt` / `claude`), all served
|
|
5
|
+
* through the single runtime provider, LLM Gateway. The provider only chooses
|
|
6
|
+
* the route, credentials and protocol; it takes no part in health tracking.
|
|
7
|
+
* Failures that belong to the shared gateway — 401/402/403, the managed key's
|
|
8
|
+
* token budget — are handled by the caller and never cool an engine down,
|
|
9
|
+
* because every engine would fail them identically. See issue #2519.
|
|
10
|
+
*
|
|
11
|
+
* ## What is and is not persisted
|
|
12
|
+
*
|
|
13
|
+
* The selected failover engine lives in `model-provider`'s module state, not
|
|
14
|
+
* in `config.json`: `engineOverride` is the *user's* preference and must
|
|
15
|
+
* survive a failover untouched. But degrading to Claude changes the agent
|
|
16
|
+
* runtime and therefore requires a process restart — so the cooldown table is
|
|
17
|
+
* mirrored to `<configDir>/engine-health.json`. Without that, the replacement
|
|
18
|
+
* process would come up with an empty table, re-select the dead engine, and
|
|
19
|
+
* restart again in a loop.
|
|
20
|
+
*
|
|
21
|
+
* ## Priority
|
|
22
|
+
*
|
|
23
|
+
* The candidate order is the user's preference first, then the remaining
|
|
24
|
+
* engines in priority order. Putting the preference first is what makes
|
|
25
|
+
* recovery automatic: as soon as its cooldown lapses it is picked again, with
|
|
26
|
+
* no separate "switch back" code path.
|
|
27
|
+
*
|
|
28
|
+
* The priority comes from the heartbeat's `llmEnginePriority` when the server
|
|
29
|
+
* sends it, and from {@link ENGINE_PRIORITY} otherwise — so an older server, or
|
|
30
|
+
* one that never sets the field, leaves failover fully working.
|
|
31
|
+
*
|
|
32
|
+
* Cooldowns:
|
|
33
|
+
* - 5 min, doubling per consecutive failure, capped at 30 min
|
|
34
|
+
* - reset to the base on the first success
|
|
35
|
+
*/
|
|
36
|
+
import { type Engine, type VisionClawConfig } from "../config/types.js";
|
|
37
|
+
/** Engine failover order used when the server does not send one. */
|
|
38
|
+
export declare const ENGINE_PRIORITY: readonly Engine[];
|
|
39
|
+
/**
|
|
40
|
+
* Why an engine was taken out of rotation. There is deliberately no auth
|
|
41
|
+
* reason: a gateway auth or key-budget failure is shared by every engine and
|
|
42
|
+
* never cools one down.
|
|
43
|
+
*/
|
|
44
|
+
export type EngineFailReason = "network" | "silence_exhausted"
|
|
45
|
+
/** The engine's model is gone or out of quota — deterministic, not transient. */
|
|
46
|
+
| "model_unavailable";
|
|
47
|
+
/** An engine currently out of rotation, as reported on the heartbeat. */
|
|
48
|
+
export interface DisabledEngineInfo {
|
|
49
|
+
engine: Engine;
|
|
50
|
+
reason: EngineFailReason;
|
|
51
|
+
disabledUntil: string;
|
|
52
|
+
}
|
|
53
|
+
/** Outcome of an attempted failover, for logging and caller branching. */
|
|
54
|
+
export type EngineSwitchOutcome = {
|
|
55
|
+
kind: "hot";
|
|
56
|
+
from: Engine;
|
|
57
|
+
to: Engine;
|
|
58
|
+
} | {
|
|
59
|
+
kind: "restart";
|
|
60
|
+
from: Engine;
|
|
61
|
+
to: Engine;
|
|
62
|
+
} | {
|
|
63
|
+
kind: "none";
|
|
64
|
+
why: "no-candidate" | "probe-failed" | "persist-failed" | "worker-cross-runtime";
|
|
65
|
+
};
|
|
66
|
+
export declare function setActiveEngineFallback(manager: EngineFallbackManager | null): void;
|
|
67
|
+
export declare function getActiveEngineFallback(): EngineFallbackManager | null;
|
|
68
|
+
export declare class EngineFallbackManager {
|
|
69
|
+
private readonly config;
|
|
70
|
+
private priorityList;
|
|
71
|
+
private states;
|
|
72
|
+
/**
|
|
73
|
+
* Cross-runtime failover is blocked while a restart is already pending, so
|
|
74
|
+
* a second failure inside the shutdown window cannot schedule a second one.
|
|
75
|
+
*/
|
|
76
|
+
private restartScheduled;
|
|
77
|
+
constructor(config: VisionClawConfig);
|
|
78
|
+
/**
|
|
79
|
+
* Adopt the server's `llmEnginePriority`. Unknown and duplicate entries are
|
|
80
|
+
* dropped; a missing or unusable list falls back to {@link ENGINE_PRIORITY}.
|
|
81
|
+
* Never let a bad list disable failover — that is exactly the silent no-op
|
|
82
|
+
* this class used to have.
|
|
83
|
+
*/
|
|
84
|
+
setPriorityList(serverPriority: string[] | null | undefined): void;
|
|
85
|
+
/** Engine priority currently in force. */
|
|
86
|
+
get enginePriority(): Engine[];
|
|
87
|
+
private healthFilePath;
|
|
88
|
+
/**
|
|
89
|
+
* Load the persisted cooldown table and re-apply a still-valid failover
|
|
90
|
+
* selection. Must run before `prepareEngineSwitchBoundary()` so the session
|
|
91
|
+
* boundary is evaluated against the engine we will actually start on.
|
|
92
|
+
*
|
|
93
|
+
* A missing, corrupt or version-mismatched file is treated as "no state":
|
|
94
|
+
* startup must never be blocked by it.
|
|
95
|
+
*/
|
|
96
|
+
initEngineHealth(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Atomically write the cooldown table. Returns false when it did not land.
|
|
99
|
+
*
|
|
100
|
+
* `activeFallback` is passed explicitly rather than read from module state:
|
|
101
|
+
* a cross-runtime switch records the engine the *next* process should start
|
|
102
|
+
* on while this process deliberately keeps serving the old one until the
|
|
103
|
+
* restart lands.
|
|
104
|
+
*/
|
|
105
|
+
private persistEngineHealth;
|
|
106
|
+
/** The engine the user/server selected, ignoring any active failover. */
|
|
107
|
+
private preferredEngine;
|
|
108
|
+
/** Candidate order: preference first, then the remaining priority entries. */
|
|
109
|
+
private candidateOrder;
|
|
110
|
+
private isCooling;
|
|
111
|
+
private getOrCreateState;
|
|
112
|
+
/** The engine currently serving traffic. */
|
|
113
|
+
get activeEngine(): Engine | null;
|
|
114
|
+
/** Engines currently in cooldown, reported on the heartbeat as `disabledEngines`. */
|
|
115
|
+
get disabledEngines(): DisabledEngineInfo[];
|
|
116
|
+
/**
|
|
117
|
+
* Record a retryable network failure against the active engine.
|
|
118
|
+
* Returns true once the threshold is reached and it should be cooled down.
|
|
119
|
+
*/
|
|
120
|
+
recordNetworkFailure(): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* A turn completed on `engine`: clear its backoff so a later, unrelated
|
|
123
|
+
* failure starts from the 5 minute base again.
|
|
124
|
+
*/
|
|
125
|
+
noteEngineSuccess(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Cool down the active engine and move to the next usable candidate.
|
|
128
|
+
*
|
|
129
|
+
* `probeTarget` is injected so the manager stays free of network concerns
|
|
130
|
+
* and unit-testable; it is only consulted before a cross-runtime switch,
|
|
131
|
+
* where being wrong costs a restart plus a session collapse. A failing probe
|
|
132
|
+
* there means the target is unreachable too, i.e. a shared-cause failure
|
|
133
|
+
* rather than a per-engine one, so nothing is switched.
|
|
134
|
+
*/
|
|
135
|
+
switchAwayFromActive(reason: EngineFailReason, probeTarget?: (engine: Engine) => Promise<boolean>): Promise<EngineSwitchOutcome>;
|
|
136
|
+
private runtimeOf;
|
|
137
|
+
/**
|
|
138
|
+
* Optimistic recovery: when a better candidate (normally the user's
|
|
139
|
+
* preference) is out of cooldown again, take it.
|
|
140
|
+
*
|
|
141
|
+
* Only same-runtime moves happen here — a cross-runtime move back costs a
|
|
142
|
+
* restart, so it waits for the idle gate (see
|
|
143
|
+
* {@link pendingCrossRuntimeRecovery}). Either way the caller must rotate the
|
|
144
|
+
* session: a model change never reuses the previous history.
|
|
145
|
+
*/
|
|
146
|
+
maybeRecoverEngine(): {
|
|
147
|
+
recovered: Engine;
|
|
148
|
+
} | null;
|
|
149
|
+
/**
|
|
150
|
+
* Whether a cross-runtime move back to a recovered engine is pending.
|
|
151
|
+
* The caller restarts only while idle so a live conversation is never cut.
|
|
152
|
+
*/
|
|
153
|
+
pendingCrossRuntimeRecovery(): {
|
|
154
|
+
target: Engine;
|
|
155
|
+
} | null;
|
|
156
|
+
/**
|
|
157
|
+
* A cross-runtime failover or recovery has armed a restart of this process.
|
|
158
|
+
* Work claimed by the current wake must then stay in flight so the
|
|
159
|
+
* replacement process replays it on the new engine.
|
|
160
|
+
*/
|
|
161
|
+
isRestartPending(): boolean;
|
|
162
|
+
/** Arm a cross-runtime recovery: persist first, then let the caller restart. */
|
|
163
|
+
commitCrossRuntimeRecovery(target: Engine): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Forget every cooldown and the failover selection because the owner chose
|
|
166
|
+
* an engine by hand (`/engine`, `switch_engine`).
|
|
167
|
+
*
|
|
168
|
+
* Only valid for callers that restart immediately afterwards: dropping a
|
|
169
|
+
* cross-runtime selection (e.g. back from Claude) without a restart would
|
|
170
|
+
* flip the effective engine while the live `SessionManager` still runs the
|
|
171
|
+
* old SDK. Every manual-switch caller restarts, and nothing else resets.
|
|
172
|
+
*/
|
|
173
|
+
clearForManualSwitch(): void;
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=engine-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-fallback.d.ts","sourceRoot":"","sources":["../../src/agent/engine-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAOH,OAAO,EACL,KAAK,MAAM,EACX,KAAK,gBAAgB,EAEtB,MAAM,oBAAoB,CAAC;AAU5B,oEAAoE;AACpE,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAA8B,CAAC;AAQ5E;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,mBAAmB;AACrB,iFAAiF;GAC/E,mBAAmB,CAAC;AAaxB,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,cAAc,GAAG,cAAc,GAAG,gBAAgB,GAAG,sBAAsB,CAAA;CAAE,CAAC;AAiDvG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAEnF;AAED,wBAAgB,uBAAuB,IAAI,qBAAqB,GAAG,IAAI,CAEtE;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,MAAM,CAAkC;IAChD;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,EAAE,gBAAgB;IAMpC;;;;;OAKG;IACH,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI;IAclE,0CAA0C;IAC1C,IAAI,cAAc,IAAI,MAAM,EAAE,CAE7B;IAID,OAAO,CAAC,cAAc;IAItB;;;;;;;OAOG;IACH,gBAAgB,IAAI,IAAI;IA+CxB;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAmC3B,yEAAyE;IACzE,OAAO,CAAC,eAAe;IAMvB,8EAA8E;IAC9E,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,gBAAgB;IASxB,4CAA4C;IAC5C,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,qFAAqF;IACrF,IAAI,eAAe,IAAI,kBAAkB,EAAE,CAa1C;IAID;;;OAGG;IACH,oBAAoB,IAAI,OAAO;IAQ/B;;;OAGG;IACH,iBAAiB,IAAI,IAAI;IAazB;;;;;;;;OAQG;IACG,oBAAoB,CACxB,MAAM,EAAE,gBAAgB,EACxB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GACjD,OAAO,CAAC,mBAAmB,CAAC;IA0F/B,OAAO,CAAC,SAAS;IAIjB;;;;;;;;OAQG;IACH,kBAAkB,IAAI;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAiBlD;;;OAGG;IACH,2BAA2B,IAAI;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAWxD;;;;OAIG;IACH,gBAAgB,IAAI,OAAO;IAI3B,gFAAgF;IAChF,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAenD;;;;;;;;OAQG;IACH,oBAAoB,IAAI,IAAI;CAK7B"}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EngineFallbackManager — health, cooldowns and failover across engines.
|
|
3
|
+
*
|
|
4
|
+
* Failover happens between **engines** (`grok` / `gpt` / `claude`), all served
|
|
5
|
+
* through the single runtime provider, LLM Gateway. The provider only chooses
|
|
6
|
+
* the route, credentials and protocol; it takes no part in health tracking.
|
|
7
|
+
* Failures that belong to the shared gateway — 401/402/403, the managed key's
|
|
8
|
+
* token budget — are handled by the caller and never cool an engine down,
|
|
9
|
+
* because every engine would fail them identically. See issue #2519.
|
|
10
|
+
*
|
|
11
|
+
* ## What is and is not persisted
|
|
12
|
+
*
|
|
13
|
+
* The selected failover engine lives in `model-provider`'s module state, not
|
|
14
|
+
* in `config.json`: `engineOverride` is the *user's* preference and must
|
|
15
|
+
* survive a failover untouched. But degrading to Claude changes the agent
|
|
16
|
+
* runtime and therefore requires a process restart — so the cooldown table is
|
|
17
|
+
* mirrored to `<configDir>/engine-health.json`. Without that, the replacement
|
|
18
|
+
* process would come up with an empty table, re-select the dead engine, and
|
|
19
|
+
* restart again in a loop.
|
|
20
|
+
*
|
|
21
|
+
* ## Priority
|
|
22
|
+
*
|
|
23
|
+
* The candidate order is the user's preference first, then the remaining
|
|
24
|
+
* engines in priority order. Putting the preference first is what makes
|
|
25
|
+
* recovery automatic: as soon as its cooldown lapses it is picked again, with
|
|
26
|
+
* no separate "switch back" code path.
|
|
27
|
+
*
|
|
28
|
+
* The priority comes from the heartbeat's `llmEnginePriority` when the server
|
|
29
|
+
* sends it, and from {@link ENGINE_PRIORITY} otherwise — so an older server, or
|
|
30
|
+
* one that never sets the field, leaves failover fully working.
|
|
31
|
+
*
|
|
32
|
+
* Cooldowns:
|
|
33
|
+
* - 5 min, doubling per consecutive failure, capped at 30 min
|
|
34
|
+
* - reset to the base on the first success
|
|
35
|
+
*/
|
|
36
|
+
import fs from "node:fs";
|
|
37
|
+
import { z } from "zod";
|
|
38
|
+
import path from "node:path";
|
|
39
|
+
import { getConfigDir, isWorkerThreadContext } from "../config/index.js";
|
|
40
|
+
import { EngineSchema, } from "../config/types.js";
|
|
41
|
+
import { canUseEngine, getEffectiveEngine, getEffectiveRoute, getFallbackEngine, setFallbackEngine, } from "./model-provider.js";
|
|
42
|
+
import { logger } from "../logger.js";
|
|
43
|
+
/** Engine failover order used when the server does not send one. */
|
|
44
|
+
export const ENGINE_PRIORITY = ["grok", "gpt", "claude"];
|
|
45
|
+
const ENGINE_COOLDOWN_BASE_MS = 5 * 60_000; // 5 minutes
|
|
46
|
+
const ENGINE_COOLDOWN_MAX_MS = 30 * 60_000; // 30 minutes
|
|
47
|
+
const NETWORK_FAILURE_THRESHOLD = 3;
|
|
48
|
+
const ENGINE_HEALTH_FILE = "engine-health.json";
|
|
49
|
+
const ENGINE_HEALTH_VERSION = 1;
|
|
50
|
+
const ENGINE_FAIL_REASONS = ["network", "silence_exhausted", "model_unavailable"];
|
|
51
|
+
/**
|
|
52
|
+
* Validates `engine-health.json`. Anything that does not match — including an
|
|
53
|
+
* older `version` — is discarded rather than trusted, because this file drives
|
|
54
|
+
* a restart decision.
|
|
55
|
+
*/
|
|
56
|
+
const EngineHealthFileSchema = z.object({
|
|
57
|
+
version: z.literal(ENGINE_HEALTH_VERSION),
|
|
58
|
+
activeFallback: EngineSchema.nullish().transform((v) => v ?? null),
|
|
59
|
+
engines: z.record(z.string(), z.object({
|
|
60
|
+
until: z.number(),
|
|
61
|
+
consecutiveFailures: z.number().int().nonnegative().catch(1),
|
|
62
|
+
// An unknown reason (e.g. from a newer build) drops the reason, not the
|
|
63
|
+
// whole cooldown entry.
|
|
64
|
+
reason: z.enum(ENGINE_FAIL_REASONS).optional().catch(undefined),
|
|
65
|
+
})).default({}),
|
|
66
|
+
});
|
|
67
|
+
function emptyState() {
|
|
68
|
+
return {
|
|
69
|
+
disabledUntil: 0,
|
|
70
|
+
consecutiveFailures: 0,
|
|
71
|
+
consecutiveNetworkFailures: 0,
|
|
72
|
+
disableReason: null,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The manager owned by the running agent loop.
|
|
77
|
+
*
|
|
78
|
+
* `/engine` and the `switch_engine` remote command both land in
|
|
79
|
+
* `applyEngineSwitchTarget()`, which is a pure config mutation with no access
|
|
80
|
+
* to the loop's wiring. It needs to drop the failover state so a manual choice
|
|
81
|
+
* is not immediately overridden — hence this small registry rather than
|
|
82
|
+
* threading the manager through every command handler.
|
|
83
|
+
*/
|
|
84
|
+
let activeManager = null;
|
|
85
|
+
export function setActiveEngineFallback(manager) {
|
|
86
|
+
activeManager = manager;
|
|
87
|
+
}
|
|
88
|
+
export function getActiveEngineFallback() {
|
|
89
|
+
return activeManager;
|
|
90
|
+
}
|
|
91
|
+
export class EngineFallbackManager {
|
|
92
|
+
config;
|
|
93
|
+
priorityList = [];
|
|
94
|
+
states = new Map();
|
|
95
|
+
/**
|
|
96
|
+
* Cross-runtime failover is blocked while a restart is already pending, so
|
|
97
|
+
* a second failure inside the shutdown window cannot schedule a second one.
|
|
98
|
+
*/
|
|
99
|
+
restartScheduled = false;
|
|
100
|
+
constructor(config) {
|
|
101
|
+
this.config = config;
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------- priority
|
|
104
|
+
/**
|
|
105
|
+
* Adopt the server's `llmEnginePriority`. Unknown and duplicate entries are
|
|
106
|
+
* dropped; a missing or unusable list falls back to {@link ENGINE_PRIORITY}.
|
|
107
|
+
* Never let a bad list disable failover — that is exactly the silent no-op
|
|
108
|
+
* this class used to have.
|
|
109
|
+
*/
|
|
110
|
+
setPriorityList(serverPriority) {
|
|
111
|
+
const engines = [];
|
|
112
|
+
for (const candidate of serverPriority ?? []) {
|
|
113
|
+
const parsed = EngineSchema.safeParse(candidate);
|
|
114
|
+
if (parsed.success && !engines.includes(parsed.data))
|
|
115
|
+
engines.push(parsed.data);
|
|
116
|
+
}
|
|
117
|
+
const next = engines.length > 0 ? engines : [...ENGINE_PRIORITY];
|
|
118
|
+
const changed = next.join(",") !== this.priorityList.join(",");
|
|
119
|
+
this.priorityList = next;
|
|
120
|
+
if (changed && engines.length > 0) {
|
|
121
|
+
logger.system(`[engine-fallback] Engine priority from server: [${next.join(", ")}]`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** Engine priority currently in force. */
|
|
125
|
+
get enginePriority() {
|
|
126
|
+
return this.priorityList.length > 0 ? this.priorityList : [...ENGINE_PRIORITY];
|
|
127
|
+
}
|
|
128
|
+
// ------------------------------------------------------------- persistence
|
|
129
|
+
healthFilePath() {
|
|
130
|
+
return path.join(getConfigDir(), ENGINE_HEALTH_FILE);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Load the persisted cooldown table and re-apply a still-valid failover
|
|
134
|
+
* selection. Must run before `prepareEngineSwitchBoundary()` so the session
|
|
135
|
+
* boundary is evaluated against the engine we will actually start on.
|
|
136
|
+
*
|
|
137
|
+
* A missing, corrupt or version-mismatched file is treated as "no state":
|
|
138
|
+
* startup must never be blocked by it.
|
|
139
|
+
*/
|
|
140
|
+
initEngineHealth() {
|
|
141
|
+
const filePath = this.healthFilePath();
|
|
142
|
+
let parsed;
|
|
143
|
+
try {
|
|
144
|
+
if (!fs.existsSync(filePath))
|
|
145
|
+
return;
|
|
146
|
+
parsed = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
logger.warn(`[engine-fallback] Ignoring unreadable engine-health.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const snapshot = EngineHealthFileSchema.safeParse(parsed);
|
|
153
|
+
if (!snapshot.success) {
|
|
154
|
+
logger.warn("[engine-fallback] Ignoring malformed or version-mismatched engine-health.json");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const now = Date.now();
|
|
158
|
+
for (const [name, entry] of Object.entries(snapshot.data.engines)) {
|
|
159
|
+
const engine = EngineSchema.safeParse(name);
|
|
160
|
+
if (!engine.success)
|
|
161
|
+
continue;
|
|
162
|
+
if (entry.until <= now)
|
|
163
|
+
continue; // expired — drop it
|
|
164
|
+
const state = this.getOrCreateState(engine.data);
|
|
165
|
+
state.disabledUntil = entry.until;
|
|
166
|
+
state.consecutiveFailures = entry.consecutiveFailures;
|
|
167
|
+
state.disableReason = entry.reason ?? null;
|
|
168
|
+
}
|
|
169
|
+
const restored = snapshot.data.activeFallback;
|
|
170
|
+
if (restored) {
|
|
171
|
+
// Only honour a restored selection that is still usable; otherwise the
|
|
172
|
+
// normal selection path runs on the next failure.
|
|
173
|
+
if (!this.isCooling(restored) && canUseEngine(this.config, restored)) {
|
|
174
|
+
setFallbackEngine(restored);
|
|
175
|
+
logger.system(`[engine-fallback] Restored failover engine "${restored}" from disk`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const cooling = this.disabledEngines;
|
|
179
|
+
if (cooling.length > 0) {
|
|
180
|
+
logger.system(`[engine-fallback] Restored cooldowns: ${cooling.map((c) => `${c.engine}→${c.disabledUntil}`).join(", ")}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Atomically write the cooldown table. Returns false when it did not land.
|
|
185
|
+
*
|
|
186
|
+
* `activeFallback` is passed explicitly rather than read from module state:
|
|
187
|
+
* a cross-runtime switch records the engine the *next* process should start
|
|
188
|
+
* on while this process deliberately keeps serving the old one until the
|
|
189
|
+
* restart lands.
|
|
190
|
+
*/
|
|
191
|
+
persistEngineHealth(activeFallback = getFallbackEngine()) {
|
|
192
|
+
const filePath = this.healthFilePath();
|
|
193
|
+
const tempPath = `${filePath}.tmp-${process.pid}`;
|
|
194
|
+
const engines = {};
|
|
195
|
+
const now = Date.now();
|
|
196
|
+
for (const [engine, state] of this.states) {
|
|
197
|
+
if (state.disabledUntil <= now)
|
|
198
|
+
continue;
|
|
199
|
+
engines[engine] = {
|
|
200
|
+
until: state.disabledUntil,
|
|
201
|
+
consecutiveFailures: state.consecutiveFailures,
|
|
202
|
+
...(state.disableReason ? { reason: state.disableReason } : {}),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const payload = {
|
|
206
|
+
version: ENGINE_HEALTH_VERSION,
|
|
207
|
+
updatedAt: new Date().toISOString(),
|
|
208
|
+
activeFallback,
|
|
209
|
+
engines,
|
|
210
|
+
};
|
|
211
|
+
try {
|
|
212
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
213
|
+
fs.writeFileSync(tempPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
214
|
+
fs.renameSync(tempPath, filePath);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
try {
|
|
219
|
+
fs.unlinkSync(tempPath);
|
|
220
|
+
}
|
|
221
|
+
catch { /* best-effort */ }
|
|
222
|
+
logger.warn(`[engine-fallback] Failed to persist engine health: ${err instanceof Error ? err.message : String(err)}`);
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// ------------------------------------------------------------------ state
|
|
227
|
+
/** The engine the user/server selected, ignoring any active failover. */
|
|
228
|
+
preferredEngine() {
|
|
229
|
+
return this.config.engineOverride
|
|
230
|
+
?? getEffectiveRoute(this.config, { ignoreFallback: true })?.engine
|
|
231
|
+
?? null;
|
|
232
|
+
}
|
|
233
|
+
/** Candidate order: preference first, then the remaining priority entries. */
|
|
234
|
+
candidateOrder() {
|
|
235
|
+
const preference = this.preferredEngine();
|
|
236
|
+
const rest = this.enginePriority.filter((e) => e !== preference);
|
|
237
|
+
return preference ? [preference, ...rest] : rest;
|
|
238
|
+
}
|
|
239
|
+
isCooling(engine) {
|
|
240
|
+
const state = this.states.get(engine);
|
|
241
|
+
return !!state && state.disabledUntil > Date.now();
|
|
242
|
+
}
|
|
243
|
+
getOrCreateState(engine) {
|
|
244
|
+
let state = this.states.get(engine);
|
|
245
|
+
if (!state) {
|
|
246
|
+
state = emptyState();
|
|
247
|
+
this.states.set(engine, state);
|
|
248
|
+
}
|
|
249
|
+
return state;
|
|
250
|
+
}
|
|
251
|
+
/** The engine currently serving traffic. */
|
|
252
|
+
get activeEngine() {
|
|
253
|
+
return getEffectiveEngine(this.config);
|
|
254
|
+
}
|
|
255
|
+
/** Engines currently in cooldown, reported on the heartbeat as `disabledEngines`. */
|
|
256
|
+
get disabledEngines() {
|
|
257
|
+
const now = Date.now();
|
|
258
|
+
const result = [];
|
|
259
|
+
for (const [engine, state] of this.states) {
|
|
260
|
+
if (state.disabledUntil > now) {
|
|
261
|
+
result.push({
|
|
262
|
+
engine,
|
|
263
|
+
reason: state.disableReason ?? "network",
|
|
264
|
+
disabledUntil: new Date(state.disabledUntil).toISOString(),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
// ------------------------------------------------------------- failure I/O
|
|
271
|
+
/**
|
|
272
|
+
* Record a retryable network failure against the active engine.
|
|
273
|
+
* Returns true once the threshold is reached and it should be cooled down.
|
|
274
|
+
*/
|
|
275
|
+
recordNetworkFailure() {
|
|
276
|
+
const engine = this.activeEngine;
|
|
277
|
+
if (!engine)
|
|
278
|
+
return false;
|
|
279
|
+
const state = this.getOrCreateState(engine);
|
|
280
|
+
state.consecutiveNetworkFailures++;
|
|
281
|
+
return state.consecutiveNetworkFailures >= NETWORK_FAILURE_THRESHOLD;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* A turn completed on `engine`: clear its backoff so a later, unrelated
|
|
285
|
+
* failure starts from the 5 minute base again.
|
|
286
|
+
*/
|
|
287
|
+
noteEngineSuccess() {
|
|
288
|
+
const engine = this.activeEngine;
|
|
289
|
+
if (!engine)
|
|
290
|
+
return;
|
|
291
|
+
const state = this.states.get(engine);
|
|
292
|
+
if (!state)
|
|
293
|
+
return;
|
|
294
|
+
state.consecutiveNetworkFailures = 0;
|
|
295
|
+
state.consecutiveFailures = 0;
|
|
296
|
+
state.disabledUntil = 0;
|
|
297
|
+
state.disableReason = null;
|
|
298
|
+
}
|
|
299
|
+
// ---------------------------------------------------------------- failover
|
|
300
|
+
/**
|
|
301
|
+
* Cool down the active engine and move to the next usable candidate.
|
|
302
|
+
*
|
|
303
|
+
* `probeTarget` is injected so the manager stays free of network concerns
|
|
304
|
+
* and unit-testable; it is only consulted before a cross-runtime switch,
|
|
305
|
+
* where being wrong costs a restart plus a session collapse. A failing probe
|
|
306
|
+
* there means the target is unreachable too, i.e. a shared-cause failure
|
|
307
|
+
* rather than a per-engine one, so nothing is switched.
|
|
308
|
+
*/
|
|
309
|
+
async switchAwayFromActive(reason, probeTarget) {
|
|
310
|
+
const current = this.activeEngine;
|
|
311
|
+
if (!current)
|
|
312
|
+
return { kind: "none", why: "no-candidate" };
|
|
313
|
+
if (this.restartScheduled) {
|
|
314
|
+
// A restart is already armed and the replacement process will pick its
|
|
315
|
+
// engine from `engine-health.json`. Rerouting now would only diverge
|
|
316
|
+
// from what was persisted.
|
|
317
|
+
return { kind: "none", why: "no-candidate" };
|
|
318
|
+
}
|
|
319
|
+
const state = this.getOrCreateState(current);
|
|
320
|
+
const cooldownMs = Math.min(ENGINE_COOLDOWN_BASE_MS * 2 ** state.consecutiveFailures, ENGINE_COOLDOWN_MAX_MS);
|
|
321
|
+
const previousUntil = state.disabledUntil;
|
|
322
|
+
const previousFailures = state.consecutiveFailures;
|
|
323
|
+
state.disabledUntil = Date.now() + cooldownMs;
|
|
324
|
+
state.consecutiveFailures += 1;
|
|
325
|
+
state.consecutiveNetworkFailures = 0;
|
|
326
|
+
state.disableReason = reason;
|
|
327
|
+
const rollback = () => {
|
|
328
|
+
state.disabledUntil = previousUntil;
|
|
329
|
+
state.consecutiveFailures = previousFailures;
|
|
330
|
+
};
|
|
331
|
+
const target = this.candidateOrder().find((engine) => engine !== current && !this.isCooling(engine) && canUseEngine(this.config, engine));
|
|
332
|
+
if (!target) {
|
|
333
|
+
logger.system(`[engine-fallback] ${current} cooled for ${cooldownMs / 60_000}min (${reason}); ` +
|
|
334
|
+
"no usable alternate engine — staying put");
|
|
335
|
+
this.persistEngineHealth();
|
|
336
|
+
return { kind: "none", why: "no-candidate" };
|
|
337
|
+
}
|
|
338
|
+
const crossRuntime = this.runtimeOf(current) !== this.runtimeOf(target);
|
|
339
|
+
if (!crossRuntime) {
|
|
340
|
+
setFallbackEngine(target === this.preferredEngine() ? null : target);
|
|
341
|
+
this.persistEngineHealth();
|
|
342
|
+
logger.system(`[engine-fallback] ${current} → ${target} (${reason}, cooled ${cooldownMs / 60_000}min) — same runtime, no restart (the caller rotates the session)`);
|
|
343
|
+
return { kind: "hot", from: current, to: target };
|
|
344
|
+
}
|
|
345
|
+
// Cross-runtime: the agent SDK and transcript store both change, so this
|
|
346
|
+
// only takes effect after a restart.
|
|
347
|
+
if (isWorkerThreadContext()) {
|
|
348
|
+
// A worker is a forked child; `scheduleRestart()` would either bounce the
|
|
349
|
+
// whole app via its process manager or exit just this worker. Neither is
|
|
350
|
+
// a behaviour we want to trigger from a thread, so stay put.
|
|
351
|
+
rollback();
|
|
352
|
+
logger.system(`[engine-fallback] ${current} → ${target} needs a cross-runtime restart; skipped inside a thread worker`);
|
|
353
|
+
return { kind: "none", why: "worker-cross-runtime" };
|
|
354
|
+
}
|
|
355
|
+
if (probeTarget && !(await probeTarget(target))) {
|
|
356
|
+
rollback();
|
|
357
|
+
logger.system(`[engine-fallback] ${target} failed its probe as well — treating as a shared-cause failure, not restarting`);
|
|
358
|
+
return { kind: "none", why: "probe-failed" };
|
|
359
|
+
}
|
|
360
|
+
// Deliberately not `setFallbackEngine(target)`: this process keeps serving
|
|
361
|
+
// the old runtime until the restart lands, and flipping the effective
|
|
362
|
+
// engine now would make `SessionManager` (built for the old runtime)
|
|
363
|
+
// resolve models for the new one.
|
|
364
|
+
if (!this.persistEngineHealth(target === this.preferredEngine() ? null : target)) {
|
|
365
|
+
// Restarting without a durable cooldown table would re-select the dead
|
|
366
|
+
// engine and restart again. Abort the switch instead.
|
|
367
|
+
rollback();
|
|
368
|
+
logger.err(`[engine-fallback] Refusing cross-runtime switch to ${target}: engine health could not be persisted`);
|
|
369
|
+
return { kind: "none", why: "persist-failed" };
|
|
370
|
+
}
|
|
371
|
+
this.restartScheduled = true;
|
|
372
|
+
logger.system(`[engine-fallback] ${current} → ${target} (${reason}) — cross-runtime, restarting`);
|
|
373
|
+
return { kind: "restart", from: current, to: target };
|
|
374
|
+
}
|
|
375
|
+
runtimeOf(engine) {
|
|
376
|
+
return getEffectiveRoute(this.config, { engine })?.runtime ?? null;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Optimistic recovery: when a better candidate (normally the user's
|
|
380
|
+
* preference) is out of cooldown again, take it.
|
|
381
|
+
*
|
|
382
|
+
* Only same-runtime moves happen here — a cross-runtime move back costs a
|
|
383
|
+
* restart, so it waits for the idle gate (see
|
|
384
|
+
* {@link pendingCrossRuntimeRecovery}). Either way the caller must rotate the
|
|
385
|
+
* session: a model change never reuses the previous history.
|
|
386
|
+
*/
|
|
387
|
+
maybeRecoverEngine() {
|
|
388
|
+
const current = this.activeEngine;
|
|
389
|
+
// A restart is already armed and the next process will pick its own engine
|
|
390
|
+
// from disk; swapping now would only diverge from what was persisted.
|
|
391
|
+
if (!current || this.restartScheduled)
|
|
392
|
+
return null;
|
|
393
|
+
const target = this.candidateOrder().find((engine) => !this.isCooling(engine) && canUseEngine(this.config, engine));
|
|
394
|
+
if (!target || target === current)
|
|
395
|
+
return null;
|
|
396
|
+
if (this.runtimeOf(target) !== this.runtimeOf(current))
|
|
397
|
+
return null;
|
|
398
|
+
setFallbackEngine(target === this.preferredEngine() ? null : target);
|
|
399
|
+
this.persistEngineHealth();
|
|
400
|
+
logger.system(`[engine-fallback] ${current} → ${target} — recovered, same runtime`);
|
|
401
|
+
return { recovered: target };
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Whether a cross-runtime move back to a recovered engine is pending.
|
|
405
|
+
* The caller restarts only while idle so a live conversation is never cut.
|
|
406
|
+
*/
|
|
407
|
+
pendingCrossRuntimeRecovery() {
|
|
408
|
+
const current = this.activeEngine;
|
|
409
|
+
if (!current || this.restartScheduled || isWorkerThreadContext())
|
|
410
|
+
return null;
|
|
411
|
+
const target = this.candidateOrder().find((engine) => !this.isCooling(engine) && canUseEngine(this.config, engine));
|
|
412
|
+
if (!target || target === current)
|
|
413
|
+
return null;
|
|
414
|
+
if (this.runtimeOf(target) === this.runtimeOf(current))
|
|
415
|
+
return null;
|
|
416
|
+
return { target };
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* A cross-runtime failover or recovery has armed a restart of this process.
|
|
420
|
+
* Work claimed by the current wake must then stay in flight so the
|
|
421
|
+
* replacement process replays it on the new engine.
|
|
422
|
+
*/
|
|
423
|
+
isRestartPending() {
|
|
424
|
+
return this.restartScheduled;
|
|
425
|
+
}
|
|
426
|
+
/** Arm a cross-runtime recovery: persist first, then let the caller restart. */
|
|
427
|
+
commitCrossRuntimeRecovery(target) {
|
|
428
|
+
if (this.restartScheduled)
|
|
429
|
+
return false;
|
|
430
|
+
// As above: persist the next process's selection without activating it here.
|
|
431
|
+
if (!this.persistEngineHealth(target === this.preferredEngine() ? null : target)) {
|
|
432
|
+
logger.err(`[engine-fallback] Refusing cross-runtime recovery to ${target}: engine health could not be persisted`);
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
this.restartScheduled = true;
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
// --------------------------------------------------------------- lifecycle
|
|
439
|
+
/**
|
|
440
|
+
* Forget every cooldown and the failover selection because the owner chose
|
|
441
|
+
* an engine by hand (`/engine`, `switch_engine`).
|
|
442
|
+
*
|
|
443
|
+
* Only valid for callers that restart immediately afterwards: dropping a
|
|
444
|
+
* cross-runtime selection (e.g. back from Claude) without a restart would
|
|
445
|
+
* flip the effective engine while the live `SessionManager` still runs the
|
|
446
|
+
* old SDK. Every manual-switch caller restarts, and nothing else resets.
|
|
447
|
+
*/
|
|
448
|
+
clearForManualSwitch() {
|
|
449
|
+
this.states.clear();
|
|
450
|
+
setFallbackEngine(null);
|
|
451
|
+
this.persistEngineHealth(null);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
//# sourceMappingURL=engine-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-fallback.js","sourceRoot":"","sources":["../../src/agent/engine-fallback.ts"],"names":[],"mappings":"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"}
|