switchback-core 2026.10.14 → 2026.10.16
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/package.json +2 -1
- package/src/availability.ts +5 -4
- package/src/classify.ts +14 -11
- package/src/config-editor.ts +101 -107
- package/src/config.ts +202 -183
- package/src/context-fit.ts +3 -3
- package/src/dispatch.ts +1 -1
- package/src/failure.ts +6 -6
- package/src/idle.ts +3 -3
- package/src/index.ts +28 -5
- package/src/routing.ts +56 -18
- package/src/simulate.ts +10 -2
- package/src/state.ts +63 -1
- package/src/systemone.ts +52 -46
- package/src/thinking.ts +2 -2
- package/src/types.ts +56 -31
package/src/types.ts
CHANGED
|
@@ -5,46 +5,57 @@
|
|
|
5
5
|
/** A physical-model preference as "provider/id" (e.g. "zai/glm-4.7"). */
|
|
6
6
|
export type ModelId = string;
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
/**
|
|
9
|
+
* A decision-model address as "provider/model-id" - the same shape as a
|
|
10
|
+
* fallback entry, e.g. "typesafe/jev-latest" or "ollama/tev1:0.8b".
|
|
11
|
+
*/
|
|
12
|
+
export type DecisionModelId = string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A decision model after address resolution.
|
|
16
|
+
*
|
|
17
|
+
* With a `baseUrl` the host drives the SystemOne endpoint directly (both pi and
|
|
18
|
+
* OpenCode can do this). Without one the host resolves the address from its own
|
|
19
|
+
* classifier catalog - pi has one, OpenCode does not, so a catalog-only address
|
|
20
|
+
* stays an explicit "no classifier" cycle there.
|
|
21
|
+
*/
|
|
22
|
+
export interface DecisionModelConfig {
|
|
23
|
+
/** Provider id (e.g. "typesafe", "ollama", "openrouter"). */
|
|
11
24
|
provider: string;
|
|
12
|
-
/**
|
|
25
|
+
/** Model id within that provider (e.g. "jev-latest", "tev1:0.8b"). */
|
|
13
26
|
id: string;
|
|
14
|
-
/**
|
|
15
|
-
* Optional direct endpoint. When set, switchback registers this classifier
|
|
16
|
-
* itself instead of looking it up in pi's catalog - for a local System One
|
|
17
|
-
* server such as Ollama v0.35+ (`http://localhost:11434/v1`). This is
|
|
18
|
-
* deliberately outside pi's normal provider/model configuration: exactly one
|
|
19
|
-
* decision model, configured here, used only by this extension.
|
|
20
|
-
*/
|
|
27
|
+
/** Direct SystemOne endpoint. When set, no catalog lookup happens. */
|
|
21
28
|
baseUrl?: string;
|
|
22
|
-
/**
|
|
23
|
-
api?: string;
|
|
24
|
-
/** Bearer token for the direct endpoint, or `secret:<name>` referencing the encrypted store. */
|
|
29
|
+
/** Bearer token for the direct endpoint, or `secret:<name>` referencing a secret store. */
|
|
25
30
|
apiKey?: string;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Connection details for one decision-model address - a `decisionModels:` map
|
|
35
|
+
* value. `baseUrl` and `apiKey` come as a pair: a direct endpoint needs a bearer
|
|
36
|
+
* token even when the endpoint ignores it (`apiKey: local`).
|
|
37
|
+
*/
|
|
38
|
+
export interface DecisionModelEntry {
|
|
39
|
+
/** Direct SystemOne endpoint (http/https). */
|
|
40
|
+
baseUrl?: string;
|
|
41
|
+
/** Bearer token, or `secret:<name>`. Required with `baseUrl`. */
|
|
42
|
+
apiKey?: string;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
|
-
/** A model's classifier: inline config, or a `decisionModel:` reference by name. */
|
|
35
|
-
export type JevRef = JevConfig | { decisionModel: string };
|
|
36
|
-
|
|
37
45
|
/**
|
|
38
|
-
* A config entry after
|
|
39
|
-
* This is what the router and the extension consume; the
|
|
40
|
-
* only in the YAML file and the config editor.
|
|
46
|
+
* A config entry after address resolution: `decisionModel` is always the
|
|
47
|
+
* provider/id descriptor. This is what the router and the extension consume; the
|
|
48
|
+
* address form exists only in the YAML file and the config editor.
|
|
41
49
|
*/
|
|
42
|
-
export type ResolvedSwitchbackConfig = Omit<SwitchbackConfig, "
|
|
50
|
+
export type ResolvedSwitchbackConfig = Omit<SwitchbackConfig, "decisionModel"> & {
|
|
51
|
+
decisionModel?: DecisionModelConfig;
|
|
52
|
+
};
|
|
43
53
|
|
|
44
|
-
/** A config file after aggregation and
|
|
54
|
+
/** A config file after aggregation and address resolution. */
|
|
45
55
|
export interface ResolvedSwitchbackFileConfig {
|
|
46
56
|
models: ResolvedSwitchbackConfig[];
|
|
47
|
-
decisionModels
|
|
57
|
+
/** Resolved `decisionModels:` entries, keyed by their address. */
|
|
58
|
+
decisionModels?: Record<DecisionModelId, DecisionModelConfig>;
|
|
48
59
|
debug?: boolean;
|
|
49
60
|
}
|
|
50
61
|
|
|
@@ -63,8 +74,12 @@ export interface SwitchbackConfig {
|
|
|
63
74
|
name: string;
|
|
64
75
|
/** Ordered preference of physical models ("provider/id"). First entry is the preferred model. */
|
|
65
76
|
fallbacks: ModelId[];
|
|
66
|
-
/**
|
|
67
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Decision model as "provider/model-id". Connection details for direct
|
|
79
|
+
* endpoints live in the top-level `decisionModels:` map under the same
|
|
80
|
+
* address. Absent: report and blind-cycle.
|
|
81
|
+
*/
|
|
82
|
+
decisionModel?: DecisionModelId;
|
|
68
83
|
/** Return to the head of the list after this much idle time (default `never`). */
|
|
69
84
|
idleReset?: IdleResetConfig;
|
|
70
85
|
}
|
|
@@ -72,8 +87,12 @@ export interface SwitchbackConfig {
|
|
|
72
87
|
/** Top-level switchback configuration. */
|
|
73
88
|
export interface SwitchbackFileConfig {
|
|
74
89
|
models: SwitchbackConfig[];
|
|
75
|
-
/**
|
|
76
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Connection details for decision-model addresses that need a direct
|
|
92
|
+
* SystemOne endpoint, keyed by the same "provider/model-id" address a chain
|
|
93
|
+
* names in `decisionModel:`.
|
|
94
|
+
*/
|
|
95
|
+
decisionModels?: Record<DecisionModelId, DecisionModelEntry>;
|
|
77
96
|
/**
|
|
78
97
|
* Emit one diagnostics notification per model switch (the classifier's verdict
|
|
79
98
|
* and how the requested reasoning category resolved against the activated
|
|
@@ -149,5 +168,11 @@ export interface SwitchbackState {
|
|
|
149
168
|
/** Cross-session blocked-until map. Keyed by "provider/id", value is epoch ms. */
|
|
150
169
|
export type BlockedMap = Record<ModelId, number>;
|
|
151
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Manually disabled models. Keyed by "provider/id", value is the epoch ms of the
|
|
173
|
+
* disable. Never expires; only an explicit enable removes an entry.
|
|
174
|
+
*/
|
|
175
|
+
export type DisabledMap = Record<ModelId, number>;
|
|
176
|
+
|
|
152
177
|
/** Reason for a route() decision. */
|
|
153
178
|
export type RouteReason = "user" | "continuation" | "retry" | "direct";
|