@workweave/router 0.2.10 → 0.2.12
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 +40 -14
- package/cc-statusline.sh +274 -23
- package/codex-skills/fm/SKILL.md +15 -0
- package/codex-skills/fm/scripts/emit.sh +8 -0
- package/codex-skills/force-model/SKILL.md +15 -0
- package/codex-skills/force-model/scripts/emit.sh +9 -0
- package/codex-skills/rf/SKILL.md +15 -0
- package/codex-skills/rf/scripts/emit.sh +7 -0
- package/codex-skills/router-feedback/SKILL.md +15 -0
- package/codex-skills/router-feedback/scripts/emit.sh +9 -0
- package/codex-skills/router-models/SKILL.md +51 -0
- package/codex-skills/router-off/SKILL.md +22 -0
- package/codex-skills/router-on/SKILL.md +22 -0
- package/codex-skills/router-status/SKILL.md +19 -0
- package/codex-skills/ufm/SKILL.md +14 -0
- package/codex-skills/ufm/scripts/emit.sh +3 -0
- package/codex-skills/unforce-model/SKILL.md +14 -0
- package/codex-skills/unforce-model/scripts/emit.sh +4 -0
- package/codex-status.sh +312 -0
- package/commands/beta.md +5 -0
- package/commands/models.md +46 -0
- package/commands/router-models.md +46 -0
- package/directives.tsv +13 -0
- package/install.sh +1849 -263
- package/package.json +7 -1
- package/pi-router/README.md +39 -7
- package/pi-router/skills/install-lsps/SKILL.md +75 -0
- package/pi-router/skills/lsp-guide/SKILL.md +63 -0
- package/pi-router/src/beta.ts +21 -0
- package/pi-router/src/compaction.ts +46 -8
- package/pi-router/src/config.ts +34 -5
- package/pi-router/src/context-window.ts +12 -0
- package/pi-router/src/dispatch.ts +35 -2
- package/pi-router/src/index.ts +12 -1
- package/pi-router/src/lsp-broker.ts +255 -0
- package/pi-router/src/lsp-client.ts +435 -0
- package/pi-router/src/lsp-format.ts +230 -0
- package/pi-router/src/lsp-install.ts +215 -0
- package/pi-router/src/lsp-protocol.ts +128 -0
- package/pi-router/src/lsp-servers.ts +361 -0
- package/pi-router/src/lsp.ts +529 -0
- package/pi-router/src/pricing.generated.ts +77 -70
- package/pi-router/src/provider.ts +15 -2
- package/pi-router/src/routed-model.ts +17 -0
- package/pi-router/src/savings.ts +1 -1
- package/registry.sh +102 -0
- package/uninstall.sh +210 -31
|
@@ -4,78 +4,85 @@
|
|
|
4
4
|
export interface ModelPricing {
|
|
5
5
|
inputUsdPerMillion: number;
|
|
6
6
|
outputUsdPerMillion: number;
|
|
7
|
+
cacheReadMultiplier: number;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
export const PRICING_VERSION = "catalog-sha256:
|
|
10
|
+
export const PRICING_VERSION = "catalog-sha256:f2403470b0f8838c";
|
|
10
11
|
|
|
11
12
|
export const MODEL_PRICING: Readonly<Record<string, ModelPricing>> = Object.freeze({
|
|
12
|
-
"claude-fable-5": { inputUsdPerMillion: 10, outputUsdPerMillion: 50 },
|
|
13
|
-
"claude-haiku-4-5": { inputUsdPerMillion: 1, outputUsdPerMillion: 5 },
|
|
14
|
-
"claude-opus-4-0": { inputUsdPerMillion: 15, outputUsdPerMillion: 75 },
|
|
15
|
-
"claude-opus-4-1": { inputUsdPerMillion: 15, outputUsdPerMillion: 75 },
|
|
16
|
-
"claude-opus-4-5": { inputUsdPerMillion: 5, outputUsdPerMillion: 25 },
|
|
17
|
-
"claude-opus-4-6": { inputUsdPerMillion: 5, outputUsdPerMillion: 25 },
|
|
18
|
-
"claude-opus-4-7": { inputUsdPerMillion: 5, outputUsdPerMillion: 25 },
|
|
19
|
-
"claude-opus-4-8": { inputUsdPerMillion: 5, outputUsdPerMillion: 25 },
|
|
20
|
-
"claude-opus-5": { inputUsdPerMillion: 5, outputUsdPerMillion: 25 },
|
|
21
|
-
"claude-sonnet-4-5": { inputUsdPerMillion: 3, outputUsdPerMillion: 15 },
|
|
22
|
-
"claude-sonnet-4-6": { inputUsdPerMillion: 3, outputUsdPerMillion: 15 },
|
|
23
|
-
"claude-sonnet-5": { inputUsdPerMillion: 3, outputUsdPerMillion: 15 },
|
|
24
|
-
"deepseek/deepseek-v4-flash": { inputUsdPerMillion: 0.1134, outputUsdPerMillion: 0.2791 },
|
|
25
|
-
"deepseek/deepseek-v4-pro": { inputUsdPerMillion: 1.74, outputUsdPerMillion: 3.48 },
|
|
26
|
-
"
|
|
27
|
-
"gemini-2.0-flash
|
|
28
|
-
"gemini-2.
|
|
29
|
-
"gemini-2.5-flash
|
|
30
|
-
"gemini-2.5-
|
|
31
|
-
"gemini-
|
|
32
|
-
"gemini-3-
|
|
33
|
-
"gemini-3
|
|
34
|
-
"gemini-3.1-
|
|
35
|
-
"gemini-3.
|
|
36
|
-
"gemini-3.5-flash
|
|
37
|
-
"gemini-3.
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"gpt-4.1
|
|
42
|
-
"gpt-
|
|
43
|
-
"gpt-
|
|
44
|
-
"gpt-
|
|
45
|
-
"gpt-
|
|
46
|
-
"gpt-5
|
|
47
|
-
"gpt-5-
|
|
48
|
-
"gpt-5
|
|
49
|
-
"gpt-5
|
|
50
|
-
"gpt-5.4
|
|
51
|
-
"gpt-5.4-
|
|
52
|
-
"gpt-5.
|
|
53
|
-
"gpt-5.
|
|
54
|
-
"gpt-5.5
|
|
55
|
-
"gpt-5.5-
|
|
56
|
-
"gpt-5.
|
|
57
|
-
"gpt-5.
|
|
58
|
-
"gpt-5.6-
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"qwen/qwen3-
|
|
73
|
-
"qwen/qwen3
|
|
74
|
-
"qwen/qwen3
|
|
75
|
-
"qwen/qwen3
|
|
76
|
-
"qwen/qwen3
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
13
|
+
"claude-fable-5": { inputUsdPerMillion: 10, outputUsdPerMillion: 50, cacheReadMultiplier: 0.1 },
|
|
14
|
+
"claude-haiku-4-5": { inputUsdPerMillion: 1, outputUsdPerMillion: 5, cacheReadMultiplier: 0.1 },
|
|
15
|
+
"claude-opus-4-0": { inputUsdPerMillion: 15, outputUsdPerMillion: 75, cacheReadMultiplier: 0.1 },
|
|
16
|
+
"claude-opus-4-1": { inputUsdPerMillion: 15, outputUsdPerMillion: 75, cacheReadMultiplier: 0.1 },
|
|
17
|
+
"claude-opus-4-5": { inputUsdPerMillion: 5, outputUsdPerMillion: 25, cacheReadMultiplier: 0.1 },
|
|
18
|
+
"claude-opus-4-6": { inputUsdPerMillion: 5, outputUsdPerMillion: 25, cacheReadMultiplier: 0.1 },
|
|
19
|
+
"claude-opus-4-7": { inputUsdPerMillion: 5, outputUsdPerMillion: 25, cacheReadMultiplier: 0.1 },
|
|
20
|
+
"claude-opus-4-8": { inputUsdPerMillion: 5, outputUsdPerMillion: 25, cacheReadMultiplier: 0.1 },
|
|
21
|
+
"claude-opus-5": { inputUsdPerMillion: 5, outputUsdPerMillion: 25, cacheReadMultiplier: 0.1 },
|
|
22
|
+
"claude-sonnet-4-5": { inputUsdPerMillion: 3, outputUsdPerMillion: 15, cacheReadMultiplier: 0.1 },
|
|
23
|
+
"claude-sonnet-4-6": { inputUsdPerMillion: 3, outputUsdPerMillion: 15, cacheReadMultiplier: 0.1 },
|
|
24
|
+
"claude-sonnet-5": { inputUsdPerMillion: 3, outputUsdPerMillion: 15, cacheReadMultiplier: 0.1 },
|
|
25
|
+
"deepseek/deepseek-v4-flash": { inputUsdPerMillion: 0.1134, outputUsdPerMillion: 0.2791, cacheReadMultiplier: 0.2 },
|
|
26
|
+
"deepseek/deepseek-v4-pro": { inputUsdPerMillion: 1.74, outputUsdPerMillion: 3.48, cacheReadMultiplier: 0.11494252873563218 },
|
|
27
|
+
"deepseek/deepseek-v4-pro-0813": { inputUsdPerMillion: 1.74, outputUsdPerMillion: 3.48, cacheReadMultiplier: 0.11494252873563218 },
|
|
28
|
+
"gemini-2.0-flash": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4, cacheReadMultiplier: 0.25 },
|
|
29
|
+
"gemini-2.0-flash-lite": { inputUsdPerMillion: 0.075, outputUsdPerMillion: 0.3, cacheReadMultiplier: 0.25 },
|
|
30
|
+
"gemini-2.5-flash": { inputUsdPerMillion: 0.3, outputUsdPerMillion: 1.2, cacheReadMultiplier: 0.1 },
|
|
31
|
+
"gemini-2.5-flash-lite": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4, cacheReadMultiplier: 0.1 },
|
|
32
|
+
"gemini-2.5-pro": { inputUsdPerMillion: 1.25, outputUsdPerMillion: 5, cacheReadMultiplier: 0.1 },
|
|
33
|
+
"gemini-3-flash-preview": { inputUsdPerMillion: 0.5, outputUsdPerMillion: 2, cacheReadMultiplier: 0.1 },
|
|
34
|
+
"gemini-3-pro-preview": { inputUsdPerMillion: 2, outputUsdPerMillion: 8, cacheReadMultiplier: 0.1 },
|
|
35
|
+
"gemini-3.1-flash-lite-preview": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4, cacheReadMultiplier: 0.1 },
|
|
36
|
+
"gemini-3.1-pro-preview": { inputUsdPerMillion: 2, outputUsdPerMillion: 8, cacheReadMultiplier: 0.1 },
|
|
37
|
+
"gemini-3.5-flash": { inputUsdPerMillion: 1.5, outputUsdPerMillion: 9, cacheReadMultiplier: 0.1 },
|
|
38
|
+
"gemini-3.5-flash-lite": { inputUsdPerMillion: 0.3, outputUsdPerMillion: 2.5, cacheReadMultiplier: 0.1 },
|
|
39
|
+
"gemini-3.6-flash": { inputUsdPerMillion: 1.5, outputUsdPerMillion: 7.5, cacheReadMultiplier: 0.1 },
|
|
40
|
+
"gemini-3.7-flash": { inputUsdPerMillion: 1.5, outputUsdPerMillion: 7.5, cacheReadMultiplier: 0.1 },
|
|
41
|
+
"google/gemma-4-26b-a4b-it": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 0.6, cacheReadMultiplier: 0.1 },
|
|
42
|
+
"gpt-4.1": { inputUsdPerMillion: 2, outputUsdPerMillion: 8, cacheReadMultiplier: 0.25 },
|
|
43
|
+
"gpt-4.1-mini": { inputUsdPerMillion: 0.4, outputUsdPerMillion: 1.6, cacheReadMultiplier: 0.25 },
|
|
44
|
+
"gpt-4.1-nano": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4, cacheReadMultiplier: 0.25 },
|
|
45
|
+
"gpt-4o": { inputUsdPerMillion: 2.5, outputUsdPerMillion: 10, cacheReadMultiplier: 0.5 },
|
|
46
|
+
"gpt-4o-mini": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 0.6, cacheReadMultiplier: 0.5 },
|
|
47
|
+
"gpt-5": { inputUsdPerMillion: 2.5, outputUsdPerMillion: 10, cacheReadMultiplier: 0.1 },
|
|
48
|
+
"gpt-5-chat": { inputUsdPerMillion: 2.5, outputUsdPerMillion: 10, cacheReadMultiplier: 0.1 },
|
|
49
|
+
"gpt-5-mini": { inputUsdPerMillion: 0.5, outputUsdPerMillion: 2, cacheReadMultiplier: 0.1 },
|
|
50
|
+
"gpt-5-nano": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4, cacheReadMultiplier: 0.1 },
|
|
51
|
+
"gpt-5.4": { inputUsdPerMillion: 2.5, outputUsdPerMillion: 15, cacheReadMultiplier: 0.1 },
|
|
52
|
+
"gpt-5.4-mini": { inputUsdPerMillion: 0.75, outputUsdPerMillion: 4.5, cacheReadMultiplier: 0.1 },
|
|
53
|
+
"gpt-5.4-nano": { inputUsdPerMillion: 0.2, outputUsdPerMillion: 1.25, cacheReadMultiplier: 0.1 },
|
|
54
|
+
"gpt-5.4-pro": { inputUsdPerMillion: 30, outputUsdPerMillion: 180, cacheReadMultiplier: 1 },
|
|
55
|
+
"gpt-5.5": { inputUsdPerMillion: 5, outputUsdPerMillion: 30, cacheReadMultiplier: 0.1 },
|
|
56
|
+
"gpt-5.5-mini": { inputUsdPerMillion: 0.5, outputUsdPerMillion: 2.5, cacheReadMultiplier: 0.1 },
|
|
57
|
+
"gpt-5.5-nano": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 0.6, cacheReadMultiplier: 0.1 },
|
|
58
|
+
"gpt-5.5-pro": { inputUsdPerMillion: 30, outputUsdPerMillion: 180, cacheReadMultiplier: 1 },
|
|
59
|
+
"gpt-5.6-luna": { inputUsdPerMillion: 1, outputUsdPerMillion: 6, cacheReadMultiplier: 0.1 },
|
|
60
|
+
"gpt-5.6-luna-pro": { inputUsdPerMillion: 1, outputUsdPerMillion: 6, cacheReadMultiplier: 0.1 },
|
|
61
|
+
"gpt-5.6-sol": { inputUsdPerMillion: 5, outputUsdPerMillion: 30, cacheReadMultiplier: 0.1 },
|
|
62
|
+
"gpt-5.6-sol-pro": { inputUsdPerMillion: 5, outputUsdPerMillion: 30, cacheReadMultiplier: 0.1 },
|
|
63
|
+
"gpt-5.6-terra": { inputUsdPerMillion: 2.5, outputUsdPerMillion: 15, cacheReadMultiplier: 0.1 },
|
|
64
|
+
"grok-4.5": { inputUsdPerMillion: 2, outputUsdPerMillion: 6, cacheReadMultiplier: 0.25 },
|
|
65
|
+
"grok-4.6": { inputUsdPerMillion: 2, outputUsdPerMillion: 6, cacheReadMultiplier: 0.25 },
|
|
66
|
+
"minimax/minimax-m2.7": { inputUsdPerMillion: 0.3, outputUsdPerMillion: 1.2, cacheReadMultiplier: 0.2 },
|
|
67
|
+
"minimax/minimax-m3": { inputUsdPerMillion: 0.3, outputUsdPerMillion: 1.2, cacheReadMultiplier: 0.2 },
|
|
68
|
+
"mistralai/mistral-small-2603": { inputUsdPerMillion: 0.2, outputUsdPerMillion: 0.6, cacheReadMultiplier: 0.1 },
|
|
69
|
+
"moonshotai/kimi-k2.5": { inputUsdPerMillion: 0.6, outputUsdPerMillion: 3, cacheReadMultiplier: 0.5 },
|
|
70
|
+
"moonshotai/kimi-k2.6": { inputUsdPerMillion: 0.95, outputUsdPerMillion: 4, cacheReadMultiplier: 0.1684 },
|
|
71
|
+
"moonshotai/kimi-k2.7": { inputUsdPerMillion: 0.95, outputUsdPerMillion: 4, cacheReadMultiplier: 0.2 },
|
|
72
|
+
"moonshotai/kimi-k3": { inputUsdPerMillion: 3, outputUsdPerMillion: 15, cacheReadMultiplier: 0.1 },
|
|
73
|
+
"qwen/qwen3-235b-a22b-2507": { inputUsdPerMillion: 0.2266, outputUsdPerMillion: 0.9064, cacheReadMultiplier: 0.5 },
|
|
74
|
+
"qwen/qwen3-30b-a3b-instruct-2507": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 0.6, cacheReadMultiplier: 0.1684 },
|
|
75
|
+
"qwen/qwen3-coder": { inputUsdPerMillion: 0.9, outputUsdPerMillion: 2.7, cacheReadMultiplier: 0.1684 },
|
|
76
|
+
"qwen/qwen3-coder-next": { inputUsdPerMillion: 0.5, outputUsdPerMillion: 1.2, cacheReadMultiplier: 0.5 },
|
|
77
|
+
"qwen/qwen3-next-80b-a3b-instruct": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 1.2, cacheReadMultiplier: 0.5 },
|
|
78
|
+
"qwen/qwen3.5-flash-02-23": { inputUsdPerMillion: 0.05, outputUsdPerMillion: 0.15, cacheReadMultiplier: 0.1 },
|
|
79
|
+
"qwen/qwen3.6-35b-a3b": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 1, cacheReadMultiplier: 0.1 },
|
|
80
|
+
"qwen/qwen3.7-plus": { inputUsdPerMillion: 0.4, outputUsdPerMillion: 1.6, cacheReadMultiplier: 0.2 },
|
|
81
|
+
"qwen/qwen3.8-max": { inputUsdPerMillion: 2, outputUsdPerMillion: 6, cacheReadMultiplier: 0.125 },
|
|
82
|
+
"xiaomi/mimo-v2.5-pro": { inputUsdPerMillion: 1, outputUsdPerMillion: 3, cacheReadMultiplier: 0.1 },
|
|
83
|
+
"z-ai/glm-5": { inputUsdPerMillion: 1, outputUsdPerMillion: 3.2, cacheReadMultiplier: 0.2 },
|
|
84
|
+
"z-ai/glm-5.1": { inputUsdPerMillion: 1.4, outputUsdPerMillion: 4.4, cacheReadMultiplier: 0.18571428571428572 },
|
|
85
|
+
"z-ai/glm-5.2": { inputUsdPerMillion: 1.4, outputUsdPerMillion: 4.4, cacheReadMultiplier: 0.18571428571428572 },
|
|
86
|
+
"z-ai/glm-5.3": { inputUsdPerMillion: 1.4, outputUsdPerMillion: 4.4, cacheReadMultiplier: 0.18571428571428572 },
|
|
87
|
+
"z-ai/glm-5.3-flash": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 0.5, cacheReadMultiplier: 0.2 },
|
|
81
88
|
});
|
|
@@ -18,7 +18,20 @@ import {
|
|
|
18
18
|
WEAVE_MODELS,
|
|
19
19
|
} from "./config.js";
|
|
20
20
|
|
|
21
|
-
export
|
|
21
|
+
export interface ContextWindowOverride {
|
|
22
|
+
modelId: string;
|
|
23
|
+
contextWindow: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function modelsForContextWindow(override?: ContextWindowOverride): typeof WEAVE_MODELS {
|
|
27
|
+
if (!override) return WEAVE_MODELS;
|
|
28
|
+
return WEAVE_MODELS.map((model) =>
|
|
29
|
+
model.id === override.modelId ? { ...model, contextWindow: override.contextWindow } : model,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Register the Weave provider, optionally using the router-confirmed active context window. */
|
|
34
|
+
export function registerWeave(pi: ExtensionAPI, contextWindowOverride?: ContextWindowOverride): void {
|
|
22
35
|
const key = resolveRouterKey();
|
|
23
36
|
const role = getRole();
|
|
24
37
|
|
|
@@ -46,6 +59,6 @@ export function registerWeave(pi: ExtensionAPI): void {
|
|
|
46
59
|
api: "anthropic-messages",
|
|
47
60
|
authHeader: false,
|
|
48
61
|
headers: providerHeaders(role, key),
|
|
49
|
-
models:
|
|
62
|
+
models: modelsForContextWindow(contextWindowOverride),
|
|
50
63
|
});
|
|
51
64
|
}
|
|
@@ -13,10 +13,14 @@ import {
|
|
|
13
13
|
isSubagent,
|
|
14
14
|
ROUTED_MODEL_HEADER,
|
|
15
15
|
ROUTED_MODEL_STDERR_PREFIX,
|
|
16
|
+
ROUTED_CONTEXT_WINDOW_HEADER,
|
|
16
17
|
ROUTED_PROVIDER_HEADER,
|
|
17
18
|
ROUTER_DECISION_HEADER,
|
|
19
|
+
PROVIDER_NAME,
|
|
18
20
|
} from "./config.js";
|
|
21
|
+
import { parseRoutedContextWindow } from "./context-window.js";
|
|
19
22
|
import { forcedModelFromBranch } from "./force-model.js";
|
|
23
|
+
import { registerWeave } from "./provider.js";
|
|
20
24
|
import {
|
|
21
25
|
aggregateSavings,
|
|
22
26
|
createSavingsEntry,
|
|
@@ -90,6 +94,9 @@ export function registerRoutedModel(pi: ExtensionAPI): void {
|
|
|
90
94
|
});
|
|
91
95
|
|
|
92
96
|
pi.on("model_select", (event, ctx: ExtensionContext) => {
|
|
97
|
+
// A new requested model has not yet received a router-confirmed window.
|
|
98
|
+
// Restore the conservative virtual-model default until its first response.
|
|
99
|
+
registerWeave(pi);
|
|
93
100
|
if (isSubagent()) return;
|
|
94
101
|
requestedModel = event.model.id;
|
|
95
102
|
routedModel = undefined;
|
|
@@ -100,6 +107,10 @@ export function registerRoutedModel(pi: ExtensionAPI): void {
|
|
|
100
107
|
if (event.status < 200 || event.status >= 300) return;
|
|
101
108
|
const model = event.headers?.[ROUTED_MODEL_HEADER];
|
|
102
109
|
if (!model) return;
|
|
110
|
+
const contextWindow = parseRoutedContextWindow(event.headers?.[ROUTED_CONTEXT_WINDOW_HEADER]);
|
|
111
|
+
if (contextWindow && ctx.model?.provider === PROVIDER_NAME) {
|
|
112
|
+
registerWeave(pi, { modelId: ctx.model.id, contextWindow });
|
|
113
|
+
}
|
|
103
114
|
const route: PendingRoute = {
|
|
104
115
|
...(ctx.model?.id ? { requestedModel: ctx.model.id } : {}),
|
|
105
116
|
routedModel: normalizeModelId(model),
|
|
@@ -130,6 +141,9 @@ export function registerRoutedModel(pi: ExtensionAPI): void {
|
|
|
130
141
|
const restoredForcedModel = forcedModelFromBranch(ctx.sessionManager.getBranch());
|
|
131
142
|
if (restoredForcedModel !== forcedModel) {
|
|
132
143
|
forcedModel = restoredForcedModel;
|
|
144
|
+
// Force-model directives take effect between responses, before the next
|
|
145
|
+
// served-window header can arrive. Fall back to the conservative value.
|
|
146
|
+
registerWeave(pi);
|
|
133
147
|
refresh(ctx);
|
|
134
148
|
}
|
|
135
149
|
const pending = pendingRoutes.shift();
|
|
@@ -153,6 +167,9 @@ export function registerRoutedModel(pi: ExtensionAPI): void {
|
|
|
153
167
|
});
|
|
154
168
|
|
|
155
169
|
pi.on("session_tree", (_event, ctx: ExtensionContext) => {
|
|
170
|
+
// A branch can have been served by another pinned model. Do not carry that
|
|
171
|
+
// window into the first request on the newly selected branch.
|
|
172
|
+
registerWeave(pi);
|
|
156
173
|
if (isSubagent()) return;
|
|
157
174
|
restore(ctx);
|
|
158
175
|
refresh(ctx);
|
package/pi-router/src/savings.ts
CHANGED
|
@@ -60,7 +60,7 @@ function normalizedUsage(usage: TokenUsage): TokenUsage | undefined {
|
|
|
60
60
|
function modelCostUsd(model: string, usage: TokenUsage): number | undefined {
|
|
61
61
|
const price = MODEL_PRICING[normalizeModelId(model)];
|
|
62
62
|
if (!price) return undefined;
|
|
63
|
-
const inputTokens = usage.input + 1.25 * usage.cacheWrite +
|
|
63
|
+
const inputTokens = usage.input + 1.25 * usage.cacheWrite + price.cacheReadMultiplier * usage.cacheRead;
|
|
64
64
|
return (inputTokens * price.inputUsdPerMillion + usage.output * price.outputUsdPerMillion) / 1_000_000;
|
|
65
65
|
}
|
|
66
66
|
|
package/registry.sh
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Shared, shell-portable directive registry helpers. Columns are documented in
|
|
4
|
+
# directives.tsv, which is the canonical declaration.
|
|
5
|
+
#
|
|
6
|
+
# install.sh is served standalone (WorkWeave serves it for `curl | sh`, and it
|
|
7
|
+
# has no sibling files there), so it carries an embedded copy of both this
|
|
8
|
+
# helper block and the registry data. The region between the markers below is
|
|
9
|
+
# copied verbatim into install.sh; install/tests/registry_test.sh asserts the
|
|
10
|
+
# two never drift. Callers that DO have the files alongside them (uninstall.sh,
|
|
11
|
+
# the packaged installer) source this file instead.
|
|
12
|
+
#
|
|
13
|
+
# Rows come from $WEAVE_REGISTRY_DATA when set (install.sh's embedded copy),
|
|
14
|
+
# otherwise from directives.tsv next to this script.
|
|
15
|
+
|
|
16
|
+
# >>> weave-router registry lib >>>
|
|
17
|
+
weave_registry_rows() {
|
|
18
|
+
if [ -n "${WEAVE_REGISTRY_DATA:-}" ]; then
|
|
19
|
+
printf '%s\n' "$WEAVE_REGISTRY_DATA" | awk -F '|' '!/^([[:space:]]*#|[[:space:]]*$)/ { print }'
|
|
20
|
+
return 0
|
|
21
|
+
fi
|
|
22
|
+
local registry="${WEAVE_REGISTRY_FILE:-}"
|
|
23
|
+
if [ -z "$registry" ]; then
|
|
24
|
+
local dir
|
|
25
|
+
dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd -P)" || return 1
|
|
26
|
+
registry="$dir/directives.tsv"
|
|
27
|
+
fi
|
|
28
|
+
[ -f "$registry" ] || return 1
|
|
29
|
+
awk -F '|' '!/^([[:space:]]*#|[[:space:]]*$)/ { print }' "$registry"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# weave_registry_names lists every canonical name and alias a client installs.
|
|
33
|
+
weave_registry_names() {
|
|
34
|
+
local target="$1" canonical aliases capability claude codex opencode pi cursor adapter
|
|
35
|
+
while IFS='|' read -r canonical aliases capability claude codex opencode pi cursor adapter; do
|
|
36
|
+
case "$target" in
|
|
37
|
+
claude) [ "$claude" = yes ] || continue ;; codex) [ "$codex" = yes ] || continue ;;
|
|
38
|
+
opencode) [ "$opencode" = yes ] || continue ;; pi) [ "$pi" = yes ] || continue ;;
|
|
39
|
+
cursor) [ "$cursor" = yes ] || continue ;;
|
|
40
|
+
esac
|
|
41
|
+
printf '%s\n' "$canonical"
|
|
42
|
+
[ -n "$aliases" ] && printf '%s\n' "$aliases" | tr ',' '\n'
|
|
43
|
+
done <<EOF
|
|
44
|
+
$(weave_registry_rows)
|
|
45
|
+
EOF
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# weave_registry_skill_names lists the prompt directives a client exposes as a
|
|
49
|
+
# native skill. Local-config toggles are excluded: they mutate config this
|
|
50
|
+
# installer owns and are handled per target, not as a generic prompt.
|
|
51
|
+
weave_registry_skill_names() {
|
|
52
|
+
local target="$1" canonical aliases capability claude codex opencode pi cursor adapter
|
|
53
|
+
while IFS='|' read -r canonical aliases capability claude codex opencode pi cursor adapter; do
|
|
54
|
+
[ "$capability" = prompt ] || continue
|
|
55
|
+
case "$target" in
|
|
56
|
+
claude) [ "$claude" = yes ] || continue ;; codex) [ "$codex" = yes ] || continue ;;
|
|
57
|
+
opencode) [ "$opencode" = yes ] || continue ;; pi) [ "$pi" = yes ] || continue ;;
|
|
58
|
+
cursor) [ "$cursor" = yes ] || continue ;;
|
|
59
|
+
esac
|
|
60
|
+
printf '%s\n' "$canonical"
|
|
61
|
+
[ -n "$aliases" ] && printf '%s\n' "$aliases" | tr ',' '\n'
|
|
62
|
+
done <<EOF
|
|
63
|
+
$(weave_registry_rows)
|
|
64
|
+
EOF
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# weave_registry_skill_assets lists every directive a client ships as a skill
|
|
68
|
+
# file, including local-config toggles such as Codex's disable-routing. Install
|
|
69
|
+
# and uninstall use this for file management; weave_registry_skill_names is the
|
|
70
|
+
# narrower prompt-only set used when generating prompt adapters.
|
|
71
|
+
weave_registry_skill_assets() {
|
|
72
|
+
local target="$1" canonical aliases capability claude codex opencode pi cursor adapter
|
|
73
|
+
while IFS='|' read -r canonical aliases capability claude codex opencode pi cursor adapter; do
|
|
74
|
+
case ",$adapter," in *,skill,*) ;; *) continue ;; esac
|
|
75
|
+
case "$target" in
|
|
76
|
+
claude) [ "$claude" = yes ] || continue ;; codex) [ "$codex" = yes ] || continue ;;
|
|
77
|
+
opencode) [ "$opencode" = yes ] || continue ;; pi) [ "$pi" = yes ] || continue ;;
|
|
78
|
+
cursor) [ "$cursor" = yes ] || continue ;;
|
|
79
|
+
esac
|
|
80
|
+
printf '%s\n' "$canonical"
|
|
81
|
+
[ -n "$aliases" ] && printf '%s\n' "$aliases" | tr ',' '\n'
|
|
82
|
+
done <<EOF
|
|
83
|
+
$(weave_registry_rows)
|
|
84
|
+
EOF
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# weave_registry_canonical_for resolves a name or alias to its canonical
|
|
88
|
+
# directive, and fails when the name is not in the registry at all.
|
|
89
|
+
weave_registry_canonical_for() {
|
|
90
|
+
local wanted="$1" canonical aliases capability claude codex opencode pi cursor adapter alias
|
|
91
|
+
while IFS='|' read -r canonical aliases capability claude codex opencode pi cursor adapter; do
|
|
92
|
+
[ "$wanted" = "$canonical" ] && { printf '%s' "$canonical"; return 0; }
|
|
93
|
+
IFS=',' read -ra _aliases <<< "$aliases"
|
|
94
|
+
for alias in ${_aliases[@]+"${_aliases[@]}"}; do
|
|
95
|
+
[ "$wanted" = "$alias" ] && { printf '%s' "$canonical"; return 0; }
|
|
96
|
+
done
|
|
97
|
+
done <<EOF
|
|
98
|
+
$(weave_registry_rows)
|
|
99
|
+
EOF
|
|
100
|
+
return 1
|
|
101
|
+
}
|
|
102
|
+
# <<< weave-router registry lib <<<
|