@workweave/router 0.2.2 → 0.2.3
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/bin.js +3 -3
- package/cc-statusline.sh +47 -2
- package/commands/fm.md +1 -1
- package/commands/force-model.md +1 -1
- package/commands/rf.md +1 -1
- package/commands/router-feedback.md +1 -1
- package/commands/router-off.md +1 -1
- package/commands/router-on.md +1 -1
- package/commands/router-status.md +2 -2
- package/commands/ufm.md +1 -1
- package/commands/unforce-model.md +1 -1
- package/install.sh +193 -41
- package/opencode-weave/README.md +59 -0
- package/opencode-weave/package.json +9 -0
- package/opencode-weave/src/index.ts +438 -0
- package/package.json +2 -1
- package/pi-router/src/dispatch.ts +2 -2
- package/pi-router/src/index.ts +1 -1
- package/pi-router/src/provider.ts +1 -1
- package/pi-router/src/routed-model.ts +1 -1
- package/uninstall.sh +35 -11
package/bin.js
CHANGED
|
@@ -17,7 +17,7 @@ const script = path.join(__dirname, scriptName);
|
|
|
17
17
|
|
|
18
18
|
if (!existsSync(script)) {
|
|
19
19
|
console.error(
|
|
20
|
-
`
|
|
20
|
+
`Weave Router: ${scriptName} missing from package — report it at https://github.com/workweave/router/issues`,
|
|
21
21
|
);
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
@@ -25,7 +25,7 @@ if (!existsSync(script)) {
|
|
|
25
25
|
const bash = pickBash();
|
|
26
26
|
if (!bash) {
|
|
27
27
|
console.error(
|
|
28
|
-
"
|
|
28
|
+
"Weave Router: bash is required. On Windows install Git Bash or run inside WSL.",
|
|
29
29
|
);
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
@@ -36,7 +36,7 @@ const result = spawnSync(bash, [script, ...args], {
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
if (result.error) {
|
|
39
|
-
console.error("
|
|
39
|
+
console.error("Weave Router:", result.error.message);
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
|
42
42
|
process.exit(result.status ?? 1);
|
package/cc-statusline.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
#
|
|
3
|
-
# Claude Code statusline for the Weave
|
|
3
|
+
# Claude Code statusline for the Weave Router. CC pipes a JSON blob on stdin
|
|
4
4
|
# whose `transcript_path` points at the JSONL log of the current session and
|
|
5
5
|
# whose `model.display_name` is the user's CC-side model selection. The
|
|
6
6
|
# router rewrites each request's `model` field before forwarding, so
|
|
@@ -166,9 +166,11 @@ prices='{
|
|
|
166
166
|
"gpt-5.5-nano": 0.00015,
|
|
167
167
|
"gpt-5.5-pro": 0.03,
|
|
168
168
|
"minimax/minimax-m2.7": 0.0003,
|
|
169
|
+
"minimax/minimax-m3": 0.0003,
|
|
169
170
|
"mistralai/mistral-small-2603": 0.0002,
|
|
170
171
|
"moonshotai/kimi-k2.5": 0.0006,
|
|
171
172
|
"moonshotai/kimi-k2.6": 0.00095,
|
|
173
|
+
"moonshotai/kimi-k2.7": 0.00095,
|
|
172
174
|
"qwen/qwen3-235b-a22b-2507": 0.0002266,
|
|
173
175
|
"qwen/qwen3-30b-a3b-instruct-2507": 0.00015,
|
|
174
176
|
"qwen/qwen3-coder": 0.0009,
|
|
@@ -176,6 +178,7 @@ prices='{
|
|
|
176
178
|
"qwen/qwen3-next-80b-a3b-instruct": 0.00015,
|
|
177
179
|
"qwen/qwen3.5-flash-02-23": 0.00005,
|
|
178
180
|
"qwen/qwen3.6-35b-a3b": 0.00015,
|
|
181
|
+
"qwen/qwen3.7-plus": 0.0004,
|
|
179
182
|
"xiaomi/mimo-v2.5-pro": 0.001,
|
|
180
183
|
"z-ai/glm-5": 0.0006,
|
|
181
184
|
"z-ai/glm-5.1": 0.00105
|
|
@@ -218,9 +221,11 @@ prices='{
|
|
|
218
221
|
"gpt-5.5-nano": 0.0006,
|
|
219
222
|
"gpt-5.5-pro": 0.12,
|
|
220
223
|
"minimax/minimax-m2.7": 0.0012,
|
|
224
|
+
"minimax/minimax-m3": 0.0012,
|
|
221
225
|
"mistralai/mistral-small-2603": 0.0006,
|
|
222
226
|
"moonshotai/kimi-k2.5": 0.003,
|
|
223
227
|
"moonshotai/kimi-k2.6": 0.004,
|
|
228
|
+
"moonshotai/kimi-k2.7": 0.004,
|
|
224
229
|
"qwen/qwen3-235b-a22b-2507": 0.0009064,
|
|
225
230
|
"qwen/qwen3-30b-a3b-instruct-2507": 0.0006,
|
|
226
231
|
"qwen/qwen3-coder": 0.0027,
|
|
@@ -228,6 +233,7 @@ prices='{
|
|
|
228
233
|
"qwen/qwen3-next-80b-a3b-instruct": 0.0012,
|
|
229
234
|
"qwen/qwen3.5-flash-02-23": 0.00015,
|
|
230
235
|
"qwen/qwen3.6-35b-a3b": 0.00095,
|
|
236
|
+
"qwen/qwen3.7-plus": 0.0016,
|
|
231
237
|
"xiaomi/mimo-v2.5-pro": 0.003,
|
|
232
238
|
"z-ai/glm-5": 0.00208,
|
|
233
239
|
"z-ai/glm-5.1": 0.0035
|
|
@@ -236,6 +242,8 @@ prices='{
|
|
|
236
242
|
# END_GENERATED_PRICES
|
|
237
243
|
|
|
238
244
|
routed=""
|
|
245
|
+
forced="false"
|
|
246
|
+
forced_model=""
|
|
239
247
|
session_savings=""
|
|
240
248
|
tot_in=0
|
|
241
249
|
tot_out=0
|
|
@@ -273,6 +281,36 @@ if [[ -n "$transcript_path" && -f "$transcript_path" ]]; then
|
|
|
273
281
|
routed="$(normalize_model "$routed")"
|
|
274
282
|
fi
|
|
275
283
|
|
|
284
|
+
# Detect an active /force-model pin from the router's synthetic ack turns —
|
|
285
|
+
# the only turns stamped message.model == "weave-router". The router emits
|
|
286
|
+
# one whenever a pin changes state:
|
|
287
|
+
# * /force-model → "force-model applied: <model> (<provider>) …"
|
|
288
|
+
# * /unforce-model → "force-model cleared …"
|
|
289
|
+
# * loop / no-progress break → "… clearing the session pin …" (expires the
|
|
290
|
+
# pin, including a user-forced one)
|
|
291
|
+
# * unrecognized model → "… isn't a recognized model · keeping
|
|
292
|
+
# automatic routing" — a NO-OP: the prior
|
|
293
|
+
# pin, if any, is left untouched
|
|
294
|
+
# These persist on disk (the ingress stripper only scrubs them from upstream
|
|
295
|
+
# requests). Classify each weave-router turn newest-first, skip the no-op
|
|
296
|
+
# "rejected" acks, and let the latest real state change decide: an "applied"
|
|
297
|
+
# marker means the session is pinned (and names the model); anything else
|
|
298
|
+
# (cleared / loop-break / no-progress) means automatic routing has resumed.
|
|
299
|
+
# Restricting to weave-router turns keeps a normal reply that merely quotes
|
|
300
|
+
# these phrases from flipping the tag. (A silent server-side TTL expiry emits
|
|
301
|
+
# no turn and so can't be reflected here — the pin TTL outlives a session.)
|
|
302
|
+
force_state="$("${reverse[@]}" "$transcript_path" 2>/dev/null \
|
|
303
|
+
| jq -r 'select(.type=="assistant" and .message.model=="weave-router")
|
|
304
|
+
| ([.message.content[]? | select(.type? == "text") | .text] | join(" ") | gsub("[\n\r]"; " ")) as $t
|
|
305
|
+
| if ($t | test("force-model applied:")) then "APPLIED " + ($t | capture("force-model applied: (?<m>[^ ]+)").m)
|
|
306
|
+
elif ($t | test("isn.t a recognized model")) then "REJECTED"
|
|
307
|
+
else "CLEARED" end' 2>/dev/null \
|
|
308
|
+
| grep -m1 -v '^REJECTED$' || true)"
|
|
309
|
+
if [[ "$force_state" == APPLIED\ * ]]; then
|
|
310
|
+
forced="true"
|
|
311
|
+
forced_model="${force_state#APPLIED }"
|
|
312
|
+
fi
|
|
313
|
+
|
|
276
314
|
# Compute a session running total: savings across every assistant turn
|
|
277
315
|
# whose marker reports a requested ≠ routed swap, plus cumulative token
|
|
278
316
|
# counts across every assistant turn (rerouted or not — total work the
|
|
@@ -375,7 +413,14 @@ if [[ "$tot_in" -gt 0 || "$tot_out" -gt 0 || "$tot_cache_read" -gt 0 || "$tot_ca
|
|
|
375
413
|
fi
|
|
376
414
|
fi
|
|
377
415
|
|
|
378
|
-
if [[ "$
|
|
416
|
+
if [[ "$forced" == "true" ]]; then
|
|
417
|
+
# Session is pinned via /force-model. The "← selection · saved $X" clause
|
|
418
|
+
# describes automatic routing and would be misleading on a manual pin, so
|
|
419
|
+
# show the pinned model with a [forced] tag instead. forced_model comes from
|
|
420
|
+
# the marker; fall back to the routed/selected id if parsing came up empty.
|
|
421
|
+
forced_display="${forced_model:-${routed:-$selected_display}}"
|
|
422
|
+
printf '%s — %s [forced]%s' "$brand" "$forced_display" "$tokens_clause"
|
|
423
|
+
elif [[ "$routed" == "failure" ]]; then
|
|
379
424
|
# Latest turn was a CC-synthesized error stub — don't claim a routing
|
|
380
425
|
# swap or compute savings against a non-model.
|
|
381
426
|
printf '%s — %s%s' "$brand" "$routed" "$tokens_clause"
|
package/commands/fm.md
CHANGED
package/commands/force-model.md
CHANGED
package/commands/rf.md
CHANGED
package/commands/router-off.md
CHANGED
package/commands/router-on.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Show whether Claude Code is routing through the Weave Router or directly to Anthropic
|
|
2
|
+
description: Show whether Claude Code is routing through the Weave Router or directly to Anthropic.
|
|
3
3
|
allowed-tools: Bash(npx:*)
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Report whether Claude Code is
|
|
6
|
+
Report whether Claude Code is using the Weave Router by running:
|
|
7
7
|
|
|
8
8
|
`npx @workweave/router status --claude{{SCOPE}}`
|
|
9
9
|
|
package/commands/ufm.md
CHANGED