@kontextmind/kxm 0.7.185 → 0.7.187
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/.claude-plugin/marketplace.json +1 -1
- package/.kxm/README.md +1 -1
- package/.kxm/roles/writer.yaml +1 -1
- package/CHANGELOG.md +18 -0
- package/docs/contributing/assignment-runner.md +2 -2
- package/docs/contributing/ci-and-release.md +2 -1
- package/docs/contributing/development.md +22 -0
- package/docs/contributing/harness-routing-internals.md +12 -12
- package/docs/glossary.md +1 -1
- package/docs/guides/governed-skills.md +1 -1
- package/docs/guides/pi-workers.md +2 -2
- package/docs/guides/provenance-gates.md +1 -1
- package/docs/operations/troubleshooting.md +1 -1
- package/docs/reference/cli-reference.md +11 -11
- package/docs/reference/config-reference.md +44 -10
- package/docs/reference/configuration.md +2 -2
- package/docs/reference/harness-routing.md +27 -12
- package/package.json +1 -1
- package/packages/core/tui/dist/index.js +1 -1
- package/packages/core/tui/src/tui/optimizer.ts +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +47 -28
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +6 -2
- package/plugins/kxm/dist/runtime.js +7 -3
- package/plugins/kxm/dist/server.js +0 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/src/cli/system.ts +1 -1
- package/plugins/kxm/src/init-guide-setup.ts +9 -9
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/model-catalog-refresh.ts +572 -0
- package/plugins/kxm/src/model-inventory.ts +42 -15
- package/plugins/kxm/src/oneshot-producer.ts +2 -2
- package/plugins/kxm/src/pi-producer.ts +1 -1
- package/plugins/kxm/src/subagent-control.ts +1 -1
- package/plugins/kxm/src/workforce-names.mjs +12 -4
- package/scripts/harness-run.d.mts +1 -1
- package/scripts/harness-run.mjs +2 -2
- package/scripts/refresh-model-catalog.mjs +67 -0
|
@@ -12,11 +12,11 @@ These are KXM's routing rules. The code enforces them in layers: the Pi native-v
|
|
|
12
12
|
- **Same model, prefer the subscription.** Prefer an authenticated native subscription for the same model.
|
|
13
13
|
- **Quota exhaustion is not a license to cross-bill.** Take the **next best** authenticated option by quality, then cost, from the report, not a silent Pi API key for the same vendor.
|
|
14
14
|
- **A harness is not a model, and it is not a worker.** A harness runs only the models it hosts. Only Pi is a long-lived worker. `grok` and `agy` are one-shot CLIs.
|
|
15
|
-
- **Admission is a decision, not a config tweak.** A route that is not admitted is refused. Admit one precise selector, such as `openrouter/qwen/qwen3-
|
|
15
|
+
- **Admission is a decision, not a config tweak.** A route that is not admitted is refused. Admit one precise selector, such as `openrouter/qwen/qwen3.7-plus`, never a whole provider.
|
|
16
16
|
|
|
17
17
|
## 1. Decision procedure: "I want model X"
|
|
18
18
|
|
|
19
|
-
1. **Name the vendor of X.** The vendor is the lab that trained the model, not whoever bills you for it. `x-ai/grok-4.6` is xAI. `qwen/qwen3-
|
|
19
|
+
1. **Name the vendor of X.** The vendor is the lab that trained the model, not whoever bills you for it. `x-ai/grok-4.6` is xAI. `qwen/qwen3.7-plus` is Alibaba. `z-ai/glm-5.3` is Z.ai.
|
|
20
20
|
2. **Check whether the vendor has a native harness.** KXM maps `anthropic→claude`, `openai→codex`, `xai→grok`, `google→agy`, `moonshot→kimi` and `deepseek→deepseek`. Google is an exception (section 4). If the vendor is not in this list, go to step 6.
|
|
21
21
|
3. **Check that the native harness is installed and logged in.** In `kxm harness list`, the row must show `detected yes`, `auth yes` and `dispatch yes`. `no` and `unknown` are never eligible.
|
|
22
22
|
4. **Check that the harness hosts X.** `claude` runs only Anthropic models. `grok` runs only `grok-*`. `agy` runs only `gemini-*`. `kimi` runs only `kimi-*` or `moonshot-*`. `deepseek` runs only `deepseek-*`. `codex` refuses other vendors' model prefixes. To see the exact ids, use the harness's own catalog: `grok models`, `agy models` or `kimi provider list`.
|
|
@@ -92,14 +92,14 @@ codex login status
|
|
|
92
92
|
grok models
|
|
93
93
|
agy models
|
|
94
94
|
kimi provider list
|
|
95
|
-
pi auth check --model openrouter/qwen/qwen3-
|
|
95
|
+
pi auth check --model openrouter/qwen/qwen3.7-plus --json --no-refresh
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
## 2. Which route will a config line use?
|
|
99
99
|
|
|
100
100
|
### How KXM builds a route
|
|
101
101
|
|
|
102
|
-
- **Selector.** The selector is `<vendor>/<model>` from the selected `.kxm/models/<route>.yaml`. The agent names a `role`, `.kxm/roles/<role>.yaml` lists route ids, and the chosen roster entry names that model file. The model id may contain `/`, for example `openrouter/qwen/qwen3-
|
|
102
|
+
- **Selector.** The selector is `<vendor>/<model>` from the selected `.kxm/models/<route>.yaml`. The agent names a `role`, `.kxm/roles/<role>.yaml` lists route ids, and the chosen roster entry names that model file. The model id may contain `/`, for example `openrouter/qwen/qwen3.7-plus`.
|
|
103
103
|
- **Harness.** The harness is the `harness` field on that model file. An agent file does not select it.
|
|
104
104
|
- **Admission.** The selector must be admitted. The engine uses the first roster entry whose model file is readable and whose route is admitted.
|
|
105
105
|
- **Dispatch probe.** Before spawning anything, the producer probes the exact harness, provider and model triple. It refuses unhosted pairs and the Pi brake.
|
|
@@ -135,7 +135,7 @@ model: openrouter/x-ai/grok-4.7
|
|
|
135
135
|
vendor: xai
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
The selector is `openrouter/x-ai/grok-4.7` and the harness is `pi`. The Pi brake refuses it before Pi starts, because the vendor segment `x-ai` is xAI, which has a native harness. A vendor with no native harness runs in the same shape: with `model: openrouter/qwen/qwen3-
|
|
138
|
+
The selector is `openrouter/x-ai/grok-4.7` and the harness is `pi`. The Pi brake refuses it before Pi starts, because the vendor segment `x-ai` is xAI, which has a native harness. A vendor with no native harness runs in the same shape: with `model: openrouter/qwen/qwen3.7-plus`, Pi is spawned with `--model openrouter/qwen/qwen3.7-plus`, its read-only flags (section 3) and `-p --mode json`. Write `model` exactly as the provider names it. For OpenRouter that is the vendor slug, so `x-ai`, not `xai`.
|
|
139
139
|
|
|
140
140
|
The harness and the selector have to agree. Pi refuses `provider: xai` and `openrouter/x-ai/…`. `grok` refuses `provider: openrouter`. [What the brake refuses](#what-the-brake-refuses) has the exact messages.
|
|
141
141
|
|
|
@@ -153,7 +153,7 @@ description: Primary implementation agent.
|
|
|
153
153
|
roster:
|
|
154
154
|
- route: grok-grok-4-7
|
|
155
155
|
effort: medium
|
|
156
|
-
- route: pi-qwen3-
|
|
156
|
+
- route: pi-qwen3-7-plus-openrouter
|
|
157
157
|
effort: medium
|
|
158
158
|
- route: agy-gemini-4-argon-high
|
|
159
159
|
effort: medium
|
|
@@ -165,7 +165,7 @@ roster:
|
|
|
165
165
|
effort: medium
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
`grok-grok-4-7` resolves to `.kxm/models/grok-grok-4-7.yaml`: harness `grok`, model `grok-4.7`, vendor `xai`, status `admitted`, permission `edit`. `pi-qwen3-
|
|
168
|
+
`grok-grok-4-7` resolves to `.kxm/models/grok-grok-4-7.yaml`: harness `grok`, model `grok-4.7`, vendor `xai`, status `admitted`, permission `edit`. `pi-qwen3-7-plus-openrouter` is harness `pi`, model `openrouter/qwen/qwen3.7-plus`, vendor `alibaba`, and it is writer #2. `agy-gemini-4-argon-high` is harness `agy`, model `gemini-4-argon-high`, vendor `google`. `kxm role list` prints the first route id as the primary, for example `(grok-grok-4-7)`. The previous ids `grok-native` and `gemini-agy` are aliases. `gemini-agy` resolves to `agy-gemini-4-argon-high`. `qwen-openrouter-pi` is not an alias: it belonged to retired `pi-qwen3-coder-plus-openrouter` (`openrouter/qwen/qwen3-coder-plus`, catalog 404) and does not resolve to `pi-qwen3-7-plus-openrouter`.
|
|
169
169
|
|
|
170
170
|
Dispatch resolves a step from the agent `role`, then `.kxm/roles/<role>.yaml`, then the selected `.kxm/models/<route>.yaml`. That model file carries `harness`, `model`, `vendor`, `status`, and `permissions`. The engine walks the roster in order and uses the first admitted route whose model file is readable. A missing or unreadable model file is a refusal (`roster_model_unreadable` at load, `producer_route_unsupported` at dispatch), not a skip to the next entry. A route file that names a harness the model cannot run on still fails closed with `harness_unhosted_model`.
|
|
171
171
|
|
|
@@ -176,7 +176,7 @@ Role files are what `kxm role` and the Runtime membership check use.
|
|
|
176
176
|
`kxm routes list` prints one line per decision, for example:
|
|
177
177
|
|
|
178
178
|
```text
|
|
179
|
-
admitted openrouter/qwen/qwen3-
|
|
179
|
+
admitted openrouter/qwen/qwen3.7-plus
|
|
180
180
|
admitted xai/grok-4.7
|
|
181
181
|
disabled openrouter/x-ai/grok-4.7
|
|
182
182
|
```
|
|
@@ -201,7 +201,7 @@ The first segment of an id is the provider, and the rest is the model id. A rout
|
|
|
201
201
|
`kxm routes admit --model <id>` only takes an id that exists in `.kxm/models/inventory.yaml`. The inventory is a different namespace from these selectors (next section), and it never carries an `openrouter/…` selector, so a dry run refuses one:
|
|
202
202
|
|
|
203
203
|
```bash
|
|
204
|
-
kxm routes admit --model openrouter/qwen/qwen3-
|
|
204
|
+
kxm routes admit --model openrouter/qwen/qwen3.7-plus --dry-run
|
|
205
205
|
```
|
|
206
206
|
|
|
207
207
|
```text
|
|
@@ -252,7 +252,7 @@ The brake runs wherever KXM starts Pi on a model: in the dispatch probe that eac
|
|
|
252
252
|
| A Pi provider that belongs to the vendor | `openai-codex/…`, `moonshotai/…`, `moonshotai-cn/…`, `kimi-coding/…`, `google-vertex/…`, `claude-bridge/…`, and `antigravity/…` except Gemini ids | `pi provider openai-codex bills native vendor openai for gpt-6.1-sol; use the native harness` |
|
|
253
253
|
| The vendor segment of an aggregator id, including the aliases `x-ai`, `moonshotai` and `google-ai` | `openrouter/x-ai/grok-4.6`, `openrouter/anthropic/claude-fable-5.1`, `nous-portal/google/…` | `pi must not bill native vendor xai through openrouter; use the native harness` |
|
|
254
254
|
|
|
255
|
-
The brake accepts `antigravity/gemini-…` and any id whose vendor has no native harness, such as `openrouter/qwen/qwen3-
|
|
255
|
+
The brake accepts `antigravity/gemini-…` and any id whose vendor has no native harness, such as `openrouter/qwen/qwen3.7-plus`, `zai-coding-cn/glm-5.3` or `qwen-token-plan/qwen3.8-flash`. Passing the brake is not admission: the route must still be admitted. The hosting refusal at dispatch reads `grok_not_authenticated: grok harness not detected (harness_unhosted_model)`.
|
|
256
256
|
|
|
257
257
|
To run the load-time check, which covers only agents that declare a harness and select a profile or tag, run the read-only validation:
|
|
258
258
|
|
|
@@ -452,7 +452,7 @@ Admit an `antigravity/…` route only through a reviewed admission decision. The
|
|
|
452
452
|
Pi is the right harness when the vendor has no native harness in KXM, for example Qwen (Alibaba) and GLM (Z.ai). The choice is then between the vendor's own plan provider in Pi and an aggregator:
|
|
453
453
|
|
|
454
454
|
- Prefer the vendor-plan provider when `pi auth check` reports it `ready`, for example `qwen-token-plan/qwen3.8-flash` or `zai-coding-cn/glm-5.3`.
|
|
455
|
-
- Otherwise use an aggregator selector, such as `openrouter/qwen/qwen3-
|
|
455
|
+
- Otherwise use an aggregator selector, such as `openrouter/qwen/qwen3.7-plus`.
|
|
456
456
|
- Admit the exact selector, with the permission it needs, never a whole provider.
|
|
457
457
|
|
|
458
458
|
DeepSeek has a native harness entry, but it is never eligible: its auth is always `unknown`, and it has no audited read-only profile. A DeepSeek model billed through another vendor's plan, such as `qwen-token-plan/deepseek-…`, passes the brake because its id names no vendor segment. It is an admission question, not a precedent.
|
|
@@ -497,7 +497,7 @@ Each of those is a fail-closed stop, or a new admission decision.
|
|
|
497
497
|
| `pi auth check --provider nous-portal` or `--provider antigravity` returns `provider_not_found`. | The provider comes from a Pi package or the KXM Pi extension, and `pi auth check` never loads extensions, not even one passed with `-e`. | Confirm with `pi list` and `pi --list-models <id>`. The Runtime's Pi one-shot runs with `--no-extensions` and checks readiness with `pi auth check`, so it cannot reach extension providers. |
|
|
498
498
|
| `producer_route_unsupported: model '<selector>' is not admitted`, or `producer_route_not_admitted`. | The selector is missing from `admitted` in `.kxm/routes.yaml`, or it is under `disabled`. | Check with `kxm routes list`. After a reviewed decision, run `kxm routes admit --model <id>`, or edit the file when the inventory lacks the id. |
|
|
499
499
|
| `producer_route_unsupported: model '<selector>' not in role '<role>' roster` | The role file exists and does not list the selector. | Add it to `.kxm/roles/<role>.yaml` by Git review, and check with `kxm role get <role>`. |
|
|
500
|
-
| `pi_native_impersonation_blocked`, at dispatch or when a worker starts. | A Pi agent or worker names a native vendor's model: directly, through that vendor's Pi provider, or behind an aggregator. | Use the native harness (`harness: grok` for `provider: xai`), or an admitted Pi route whose vendor has no native harness, such as `openrouter/qwen/qwen3-
|
|
500
|
+
| `pi_native_impersonation_blocked`, at dispatch or when a worker starts. | A Pi agent or worker names a native vendor's model: directly, through that vendor's Pi provider, or behind an aggregator. | Use the native harness (`harness: grok` for `provider: xai`), or an admitted Pi route whose vendor has no native harness, such as `openrouter/qwen/qwen3.7-plus`. |
|
|
501
501
|
| `grok_not_authenticated: grok harness not detected (harness_unhosted_model)`, or `harness grok does not host provider openrouter`. | A native-harness agent was given an aggregator or another vendor's selector, often from a mixed role roster. | Give that selector its own agent with `harness:` omitted. |
|
|
502
502
|
| `routing report` shows every attempt under `Unk*`, and records carry `costBasis: unknown`. | Grok and every Pi route are recorded as `unknown` today. That is the design, not a missing price. | Nothing to fix per run. Compare quality and latency, and use list estimates for cost. |
|
|
503
503
|
| `providerMetadata.priceCatalogStale: true`, and there is no `listCostUsd`. | `.kxm/prices.yaml` is not dated today, or no row matches the route's provider. | Edit `.kxm/prices.yaml` by Git review: add a row for the provider, then update `date` and `sha256`. The loader refuses a hash mismatch. |
|
|
@@ -520,6 +520,21 @@ kxm models refresh
|
|
|
520
520
|
kxm routing report --equivalent-list-cost
|
|
521
521
|
```
|
|
522
522
|
|
|
523
|
+
## Weekly price and inventory refresh
|
|
524
|
+
|
|
525
|
+
OpenRouter list prices in `.kxm/prices.yaml` and `.kxm/models/inventory.yaml`
|
|
526
|
+
go stale as models are added, removed, and repriced. A Monday 13:00 UTC
|
|
527
|
+
workflow, `.github/workflows/refresh-models.yml`, fetches the public OpenRouter
|
|
528
|
+
models API and opens one pull request on `automation/model-refresh` when the
|
|
529
|
+
catalog changed. The pull request body lists models added, removed, and
|
|
530
|
+
repriced. A route or roster model that disappeared, or whose input or output
|
|
531
|
+
rate moved by more than 20 percent, is listed first. A disappeared referenced
|
|
532
|
+
model stays in the inventory with `missingUpstream: true`, and the
|
|
533
|
+
`model-catalog-guard` check fails until someone removes the reference or
|
|
534
|
+
restores the model.
|
|
535
|
+
|
|
536
|
+
Manual run, and the file fields, are in [Weekly OpenRouter refresh](config-reference.md#weekly-openrouter-refresh). `kxm models inventory-refresh` remains the local command that also queries Pi, Grok, agy, and Nous.
|
|
537
|
+
|
|
523
538
|
## Where the code is looser than the rules
|
|
524
539
|
|
|
525
540
|
These are places where the code decides less than the [routing rules](#routing-rules) say. Each one is an open operator policy question, not a defect with an obvious fix. Until it is decided, follow the rule.
|
package/package.json
CHANGED
|
@@ -1167,7 +1167,7 @@ function evaluatePlanOptimizations(tasks) {
|
|
|
1167
1167
|
projectedTimeSavingsSeconds: 5,
|
|
1168
1168
|
projectedCostSavingsPercent: 65,
|
|
1169
1169
|
suggestedHarness: "pi",
|
|
1170
|
-
suggestedModel: "qwen/qwen3-
|
|
1170
|
+
suggestedModel: "qwen/qwen3.7-plus",
|
|
1171
1171
|
selected: true
|
|
1172
1172
|
});
|
|
1173
1173
|
} else if (isFrontier && (task.category === "lint" || /lint|format|style/i.test(task.title))) {
|
|
@@ -84,7 +84,7 @@ export function evaluatePlanOptimizations(tasks: readonly OptimizerTaskInput[]):
|
|
|
84
84
|
projectedTimeSavingsSeconds: 5,
|
|
85
85
|
projectedCostSavingsPercent: 65,
|
|
86
86
|
suggestedHarness: "pi",
|
|
87
|
-
suggestedModel: "qwen/qwen3-
|
|
87
|
+
suggestedModel: "qwen/qwen3.7-plus",
|
|
88
88
|
selected: true,
|
|
89
89
|
});
|
|
90
90
|
} else if (isFrontier && (task.category === "lint" || /lint|format|style/i.test(task.title))) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "kxm",
|
|
4
4
|
"displayName": "KXM",
|
|
5
|
-
"version": "0.7.
|
|
5
|
+
"version": "0.7.187",
|
|
6
6
|
"description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "KontextMind",
|
package/plugins/kxm/dist/cli.js
CHANGED
|
@@ -18541,9 +18541,14 @@ function lintWorkforce(root) {
|
|
|
18541
18541
|
if (!expected || model.id !== expected) {
|
|
18542
18542
|
push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
|
|
18543
18543
|
}
|
|
18544
|
-
|
|
18544
|
+
const retired = doc.status === "retired";
|
|
18545
|
+
if (retired && used.has(model.id)) {
|
|
18546
|
+
push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
|
|
18547
|
+
}
|
|
18548
|
+
if (!retired && !used.has(model.id)) {
|
|
18545
18549
|
push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
|
|
18546
18550
|
}
|
|
18551
|
+
if (retired) continue;
|
|
18547
18552
|
const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
|
|
18548
18553
|
if (!selectorHit) {
|
|
18549
18554
|
push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
|
|
@@ -18614,7 +18619,6 @@ var init_workforce_names = __esm({
|
|
|
18614
18619
|
]);
|
|
18615
18620
|
ROUTE_RENAMES = Object.freeze([
|
|
18616
18621
|
["grok-native", "grok-grok-4-7"],
|
|
18617
|
-
["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
|
|
18618
18622
|
["gemini-agy", "agy-gemini-4-argon-high"],
|
|
18619
18623
|
["fable-claude", "claude-fable"],
|
|
18620
18624
|
// sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
|
|
@@ -28789,6 +28793,32 @@ function rates(raw) {
|
|
|
28789
28793
|
function modelId(id) {
|
|
28790
28794
|
return id.trim().toLowerCase();
|
|
28791
28795
|
}
|
|
28796
|
+
function blankModel(id, item) {
|
|
28797
|
+
return {
|
|
28798
|
+
id,
|
|
28799
|
+
...typeof item?.name === "string" ? { name: item.name } : {},
|
|
28800
|
+
...typeof item?.context_length === "number" ? { contextLength: item.context_length } : {},
|
|
28801
|
+
capabilities: { thinking: { supported: null, source: "unknown" }, speed: { fast: null, source: "unknown" } },
|
|
28802
|
+
sources: []
|
|
28803
|
+
};
|
|
28804
|
+
}
|
|
28805
|
+
function applyAggregatorItem(current, item, source, kind) {
|
|
28806
|
+
if (!current.sources.includes(source)) current.sources.push(source);
|
|
28807
|
+
const parsed = rates(item.pricing);
|
|
28808
|
+
if (parsed) {
|
|
28809
|
+
if (kind === "standard") current.standard = parsed;
|
|
28810
|
+
else current.discount = parsed;
|
|
28811
|
+
}
|
|
28812
|
+
if (!current.name && typeof item.name === "string") current.name = item.name;
|
|
28813
|
+
if (!current.contextLength && typeof item.context_length === "number") current.contextLength = item.context_length;
|
|
28814
|
+
const parameters = Array.isArray(item.supported_parameters) ? item.supported_parameters.filter((value) => typeof value === "string") : [];
|
|
28815
|
+
if (parameters.some((value) => /reasoning|thinking/i.test(value))) current.capabilities.thinking = { supported: true, source };
|
|
28816
|
+
if (parameters.some((value) => /speed|service.?tier|fast/i.test(value))) current.capabilities.speed = { fast: true, tiers: ["fast"], source };
|
|
28817
|
+
if (Array.isArray(item.thinkingLevels) && item.thinkingLevels.length > 0) {
|
|
28818
|
+
current.capabilities.thinking = { supported: true, levels: item.thinkingLevels, ...item.defaultThinking ? { default: item.defaultThinking } : {}, source };
|
|
28819
|
+
}
|
|
28820
|
+
if (item.fast === true) current.capabilities.speed = { fast: true, tiers: ["fast"], source };
|
|
28821
|
+
}
|
|
28792
28822
|
async function fetchModels(url, authorization) {
|
|
28793
28823
|
try {
|
|
28794
28824
|
const headers = { Accept: "application/json" };
|
|
@@ -28810,20 +28840,8 @@ async function refreshModelInventory(options) {
|
|
|
28810
28840
|
const add = (item, source, kind) => {
|
|
28811
28841
|
if (!item || typeof item.id !== "string" || !item.id.trim()) return;
|
|
28812
28842
|
const key = modelId(item.id);
|
|
28813
|
-
const current = byId.get(key) ??
|
|
28814
|
-
|
|
28815
|
-
const parsed = rates(item.pricing);
|
|
28816
|
-
if (parsed) {
|
|
28817
|
-
if (kind === "standard") current.standard = parsed;
|
|
28818
|
-
else current.discount = parsed;
|
|
28819
|
-
}
|
|
28820
|
-
if (!current.name && typeof item.name === "string") current.name = item.name;
|
|
28821
|
-
if (!current.contextLength && typeof item.context_length === "number") current.contextLength = item.context_length;
|
|
28822
|
-
const parameters = Array.isArray(item.supported_parameters) ? item.supported_parameters.filter((value) => typeof value === "string") : [];
|
|
28823
|
-
if (parameters.some((value) => /reasoning|thinking/i.test(value))) current.capabilities.thinking = { supported: true, source };
|
|
28824
|
-
if (parameters.some((value) => /speed|service.?tier|fast/i.test(value))) current.capabilities.speed = { fast: true, tiers: ["fast"], source };
|
|
28825
|
-
if (Array.isArray(item.thinkingLevels) && item.thinkingLevels.length > 0) current.capabilities.thinking = { supported: true, levels: item.thinkingLevels, ...item.defaultThinking ? { default: item.defaultThinking } : {}, source };
|
|
28826
|
-
if (item.fast === true) current.capabilities.speed = { fast: true, tiers: ["fast"], source };
|
|
28843
|
+
const current = byId.get(key) ?? blankModel(item.id, item);
|
|
28844
|
+
applyAggregatorItem(current, item, source, kind);
|
|
28827
28845
|
byId.set(key, current);
|
|
28828
28846
|
};
|
|
28829
28847
|
const native2 = async (command, args, source) => {
|
|
@@ -28856,13 +28874,14 @@ async function refreshModelInventory(options) {
|
|
|
28856
28874
|
writeFileSync18(join28(options.outputRoot, ".kxm", "models", "inventory.yaml"), (0, import_yaml17.stringify)(inventory), "utf8");
|
|
28857
28875
|
return inventory;
|
|
28858
28876
|
}
|
|
28859
|
-
var import_yaml17, OR_URL, NOUS_URL;
|
|
28877
|
+
var import_yaml17, OPENROUTER_MODELS_URL, OR_URL, NOUS_URL;
|
|
28860
28878
|
var init_model_inventory = __esm({
|
|
28861
28879
|
"plugins/kxm/src/model-inventory.ts"() {
|
|
28862
28880
|
"use strict";
|
|
28863
28881
|
import_yaml17 = __toESM(require_dist(), 1);
|
|
28864
28882
|
init_oneshot_process();
|
|
28865
|
-
|
|
28883
|
+
OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models";
|
|
28884
|
+
OR_URL = OPENROUTER_MODELS_URL;
|
|
28866
28885
|
NOUS_URL = "https://inference-api.nousresearch.com/v1/models";
|
|
28867
28886
|
}
|
|
28868
28887
|
});
|
|
@@ -56721,7 +56740,7 @@ var ADMITTED_GUIDE_BINDINGS = Object.freeze({
|
|
|
56721
56740
|
"openai/gpt-5.6-sol": { harness: "codex", provider: "openai", model: "gpt-5.6-sol" },
|
|
56722
56741
|
"x-ai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
|
|
56723
56742
|
"xai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
|
|
56724
|
-
"qwen/qwen3-
|
|
56743
|
+
"qwen/qwen3.7-plus": { harness: "pi", provider: "openrouter", model: "qwen/qwen3.7-plus" }
|
|
56725
56744
|
});
|
|
56726
56745
|
var GUIDE_WORKFLOWS = [
|
|
56727
56746
|
{
|
|
@@ -56752,7 +56771,7 @@ var GUIDE_WORKFLOWS = [
|
|
|
56752
56771
|
{ vendor: "openai", model: "gpt-5.6-sol" },
|
|
56753
56772
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
56754
56773
|
{ vendor: "google", model: "gemini-3.8-flash" },
|
|
56755
|
-
{ vendor: "qwen", model: "qwen3-
|
|
56774
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
56756
56775
|
{ vendor: "anthropic", model: "claude-fable-5.1" }
|
|
56757
56776
|
]
|
|
56758
56777
|
},
|
|
@@ -56764,7 +56783,7 @@ var GUIDE_WORKFLOWS = [
|
|
|
56764
56783
|
candidates: [
|
|
56765
56784
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
56766
56785
|
{ vendor: "mistralai", model: "devstral-2512" },
|
|
56767
|
-
{ vendor: "qwen", model: "qwen3-
|
|
56786
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
56768
56787
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
56769
56788
|
{ vendor: "kwaipilot", model: "kat-coder-pro-v2.5" }
|
|
56770
56789
|
]
|
|
@@ -56776,7 +56795,7 @@ var GUIDE_WORKFLOWS = [
|
|
|
56776
56795
|
domain: "Implements domain entities, SQL queries/migrations, ORM persistence, concurrency primitives, and transactional boundaries.",
|
|
56777
56796
|
candidates: [
|
|
56778
56797
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
56779
|
-
{ vendor: "qwen", model: "qwen3-
|
|
56798
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
56780
56799
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
56781
56800
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
56782
56801
|
{ vendor: "kwaipilot", model: "kat-coder-pro-v2.5" }
|
|
@@ -56803,7 +56822,7 @@ var GUIDE_WORKFLOWS = [
|
|
|
56803
56822
|
candidates: [
|
|
56804
56823
|
{ vendor: "openai", model: "gpt-5.6-sol" },
|
|
56805
56824
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
56806
|
-
{ vendor: "qwen", model: "qwen3-
|
|
56825
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
56807
56826
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
56808
56827
|
{ vendor: "google", model: "gemini-3.8-flash" }
|
|
56809
56828
|
]
|
|
@@ -56930,7 +56949,7 @@ var GUIDE_WORKFLOWS = [
|
|
|
56930
56949
|
domain: "Generates declarative Terraform/OpenTofu, Pulumi, Kubernetes CRDs, and VPC networking definitions.",
|
|
56931
56950
|
candidates: [
|
|
56932
56951
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
56933
|
-
{ vendor: "qwen", model: "qwen3-
|
|
56952
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
56934
56953
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
56935
56954
|
{ vendor: "google", model: "gemini-3.8-flash" },
|
|
56936
56955
|
{ vendor: "mistralai", model: "devstral-2512" }
|
|
@@ -56990,7 +57009,7 @@ var GUIDE_WORKFLOWS = [
|
|
|
56990
57009
|
domain: "Authors concise, accurate developer and operator documentation with clear terminology, correct command flags, and consistent formatting without marketing drift.",
|
|
56991
57010
|
candidates: [
|
|
56992
57011
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
56993
|
-
{ vendor: "qwen", model: "qwen3-
|
|
57012
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
56994
57013
|
{ vendor: "anthropic", model: "claude-sonnet-5" },
|
|
56995
57014
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
56996
57015
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" }
|
|
@@ -57095,11 +57114,11 @@ function workflowDocument(workflow) {
|
|
|
57095
57114
|
};
|
|
57096
57115
|
}
|
|
57097
57116
|
var GUIDE_PI_EVIDENCE_SOURCE = "plans/evidence/route-guide-qwen-pi.md";
|
|
57098
|
-
var GUIDE_PI_EVIDENCE_SHA256 = "
|
|
57117
|
+
var GUIDE_PI_EVIDENCE_SHA256 = "8a24a7dc6db416df2153cfec7bccf1a4462f838e35c4e6707dc421ca84cf069b";
|
|
57099
57118
|
var GUIDE_PI_NOTE = {
|
|
57100
57119
|
harness: "pi",
|
|
57101
57120
|
vendor: "openrouter",
|
|
57102
|
-
model: "qwen/qwen3-
|
|
57121
|
+
model: "qwen/qwen3.7-plus",
|
|
57103
57122
|
reason: "Qwen has no supported native harness on this runner, and the operator admitted that exact model for guided setup.",
|
|
57104
57123
|
provingCommand: "pi auth check --provider openrouter"
|
|
57105
57124
|
};
|
|
@@ -58101,7 +58120,7 @@ async function cmdRoutingReport(runtime, options) {
|
|
|
58101
58120
|
}
|
|
58102
58121
|
async function cmdRoutingBenchmark(runtime, options) {
|
|
58103
58122
|
const task = options.task || "Deterministic benchmark task";
|
|
58104
|
-
const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3-
|
|
58123
|
+
const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3.7-plus";
|
|
58105
58124
|
const armsList = armsStr.split(",").map((s) => s.trim()).filter(Boolean);
|
|
58106
58125
|
const runsCount = Math.max(1, parseInt(options.runs || "1", 10) || 1);
|
|
58107
58126
|
const arms = armsList.map((arm) => {
|
|
@@ -25462,7 +25462,7 @@ function sessionTokenFixHint(policy) {
|
|
|
25462
25462
|
}
|
|
25463
25463
|
|
|
25464
25464
|
// plugins/kxm/src/mcp-server.ts
|
|
25465
|
-
var VERSION = "0.7.
|
|
25465
|
+
var VERSION = "0.7.187";
|
|
25466
25466
|
var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
|
|
25467
25467
|
var inbox = /* @__PURE__ */ new Map();
|
|
25468
25468
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
|
@@ -15543,7 +15543,6 @@ var ROLE_IDS = Object.freeze([
|
|
|
15543
15543
|
]);
|
|
15544
15544
|
var ROUTE_RENAMES = Object.freeze([
|
|
15545
15545
|
["grok-native", "grok-grok-4-7"],
|
|
15546
|
-
["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
|
|
15547
15546
|
["gemini-agy", "agy-gemini-4-argon-high"],
|
|
15548
15547
|
["fable-claude", "claude-fable"],
|
|
15549
15548
|
// sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
|
|
@@ -15735,9 +15734,14 @@ function lintWorkforce(root) {
|
|
|
15735
15734
|
if (!expected || model.id !== expected) {
|
|
15736
15735
|
push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
|
|
15737
15736
|
}
|
|
15738
|
-
|
|
15737
|
+
const retired = doc.status === "retired";
|
|
15738
|
+
if (retired && used.has(model.id)) {
|
|
15739
|
+
push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
|
|
15740
|
+
}
|
|
15741
|
+
if (!retired && !used.has(model.id)) {
|
|
15739
15742
|
push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
|
|
15740
15743
|
}
|
|
15744
|
+
if (retired) continue;
|
|
15741
15745
|
const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
|
|
15742
15746
|
if (!selectorHit) {
|
|
15743
15747
|
push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
|
|
@@ -15516,7 +15516,6 @@ var ROLE_IDS = Object.freeze([
|
|
|
15516
15516
|
]);
|
|
15517
15517
|
var ROUTE_RENAMES = Object.freeze([
|
|
15518
15518
|
["grok-native", "grok-grok-4-7"],
|
|
15519
|
-
["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
|
|
15520
15519
|
["gemini-agy", "agy-gemini-4-argon-high"],
|
|
15521
15520
|
["fable-claude", "claude-fable"],
|
|
15522
15521
|
// sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
|
|
@@ -15708,9 +15707,14 @@ function lintWorkforce(root) {
|
|
|
15708
15707
|
if (!expected || model.id !== expected) {
|
|
15709
15708
|
push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
|
|
15710
15709
|
}
|
|
15711
|
-
|
|
15710
|
+
const retired = doc.status === "retired";
|
|
15711
|
+
if (retired && used.has(model.id)) {
|
|
15712
|
+
push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
|
|
15713
|
+
}
|
|
15714
|
+
if (!retired && !used.has(model.id)) {
|
|
15712
15715
|
push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
|
|
15713
15716
|
}
|
|
15717
|
+
if (retired) continue;
|
|
15714
15718
|
const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
|
|
15715
15719
|
if (!selectorHit) {
|
|
15716
15720
|
push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
|
|
@@ -36447,7 +36451,7 @@ var SUBAGENT_TYPES = Object.freeze([
|
|
|
36447
36451
|
]);
|
|
36448
36452
|
var DEFAULT_SUBAGENT_MODELS = Object.freeze({
|
|
36449
36453
|
general: "grok/grok-4.6",
|
|
36450
|
-
Explore: "openrouter/qwen/qwen3-
|
|
36454
|
+
Explore: "openrouter/qwen/qwen3.7-plus",
|
|
36451
36455
|
Plan: "claude/fable",
|
|
36452
36456
|
Reviewer: "openai/gpt-5.6-sol",
|
|
36453
36457
|
Auditor: "claude/fable"
|
|
@@ -15008,7 +15008,6 @@ var ROLE_IDS = Object.freeze([
|
|
|
15008
15008
|
]);
|
|
15009
15009
|
var ROUTE_RENAMES = Object.freeze([
|
|
15010
15010
|
["grok-native", "grok-grok-4-7"],
|
|
15011
|
-
["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
|
|
15012
15011
|
["gemini-agy", "agy-gemini-4-argon-high"],
|
|
15013
15012
|
["fable-claude", "claude-fable"],
|
|
15014
15013
|
// sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
|
package/plugins/kxm/package.json
CHANGED
|
@@ -1071,7 +1071,7 @@ export async function cmdRoutingBenchmark(
|
|
|
1071
1071
|
options: { task?: string | undefined; arms?: string | undefined; runs?: string | undefined },
|
|
1072
1072
|
): Promise<number> {
|
|
1073
1073
|
const task = options.task || "Deterministic benchmark task";
|
|
1074
|
-
const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3-
|
|
1074
|
+
const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3.7-plus";
|
|
1075
1075
|
const armsList = armsStr.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1076
1076
|
const runsCount = Math.max(1, parseInt(options.runs || "1", 10) || 1);
|
|
1077
1077
|
|
|
@@ -64,7 +64,7 @@ const ADMITTED_GUIDE_BINDINGS: Readonly<Record<string, AgentBinding>> = Object.f
|
|
|
64
64
|
"openai/gpt-5.6-sol": { harness: "codex", provider: "openai", model: "gpt-5.6-sol" },
|
|
65
65
|
"x-ai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
|
|
66
66
|
"xai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
|
|
67
|
-
"qwen/qwen3-
|
|
67
|
+
"qwen/qwen3.7-plus": { harness: "pi", provider: "openrouter", model: "qwen/qwen3.7-plus" },
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
/** Guide candidates are ordered by preference; the first eligible wins. */
|
|
@@ -97,7 +97,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
|
|
|
97
97
|
{ vendor: "openai", model: "gpt-5.6-sol" },
|
|
98
98
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
99
99
|
{ vendor: "google", model: "gemini-3.8-flash" },
|
|
100
|
-
{ vendor: "qwen", model: "qwen3-
|
|
100
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
101
101
|
{ vendor: "anthropic", model: "claude-fable-5.1" },
|
|
102
102
|
],
|
|
103
103
|
},
|
|
@@ -109,7 +109,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
|
|
|
109
109
|
candidates: [
|
|
110
110
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
111
111
|
{ vendor: "mistralai", model: "devstral-2512" },
|
|
112
|
-
{ vendor: "qwen", model: "qwen3-
|
|
112
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
113
113
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
114
114
|
{ vendor: "kwaipilot", model: "kat-coder-pro-v2.5" },
|
|
115
115
|
],
|
|
@@ -121,7 +121,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
|
|
|
121
121
|
domain: "Implements domain entities, SQL queries/migrations, ORM persistence, concurrency primitives, and transactional boundaries.",
|
|
122
122
|
candidates: [
|
|
123
123
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
124
|
-
{ vendor: "qwen", model: "qwen3-
|
|
124
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
125
125
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
126
126
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
127
127
|
{ vendor: "kwaipilot", model: "kat-coder-pro-v2.5" },
|
|
@@ -148,7 +148,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
|
|
|
148
148
|
candidates: [
|
|
149
149
|
{ vendor: "openai", model: "gpt-5.6-sol" },
|
|
150
150
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
151
|
-
{ vendor: "qwen", model: "qwen3-
|
|
151
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
152
152
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
153
153
|
{ vendor: "google", model: "gemini-3.8-flash" },
|
|
154
154
|
],
|
|
@@ -275,7 +275,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
|
|
|
275
275
|
domain: "Generates declarative Terraform/OpenTofu, Pulumi, Kubernetes CRDs, and VPC networking definitions.",
|
|
276
276
|
candidates: [
|
|
277
277
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
278
|
-
{ vendor: "qwen", model: "qwen3-
|
|
278
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
279
279
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
280
280
|
{ vendor: "google", model: "gemini-3.8-flash" },
|
|
281
281
|
{ vendor: "mistralai", model: "devstral-2512" },
|
|
@@ -335,7 +335,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
|
|
|
335
335
|
domain: "Authors concise, accurate developer and operator documentation with clear terminology, correct command flags, and consistent formatting without marketing drift.",
|
|
336
336
|
candidates: [
|
|
337
337
|
{ vendor: "x-ai", model: "grok-4.6" },
|
|
338
|
-
{ vendor: "qwen", model: "qwen3-
|
|
338
|
+
{ vendor: "qwen", model: "qwen3.7-plus" },
|
|
339
339
|
{ vendor: "anthropic", model: "claude-sonnet-5" },
|
|
340
340
|
{ vendor: "openai", model: "gpt-5.3-codex" },
|
|
341
341
|
{ vendor: "deepseek", model: "deepseek-v4-pro-0813" },
|
|
@@ -490,11 +490,11 @@ function workflowDocument(workflow: GuideWorkflow): Record<string, unknown> {
|
|
|
490
490
|
* id, and harness gets no model file and no origin.
|
|
491
491
|
*/
|
|
492
492
|
const GUIDE_PI_EVIDENCE_SOURCE = "plans/evidence/route-guide-qwen-pi.md";
|
|
493
|
-
const GUIDE_PI_EVIDENCE_SHA256 = "
|
|
493
|
+
const GUIDE_PI_EVIDENCE_SHA256 = "8a24a7dc6db416df2153cfec7bccf1a4462f838e35c4e6707dc421ca84cf069b";
|
|
494
494
|
const GUIDE_PI_NOTE = {
|
|
495
495
|
harness: "pi",
|
|
496
496
|
vendor: "openrouter",
|
|
497
|
-
model: "qwen/qwen3-
|
|
497
|
+
model: "qwen/qwen3.7-plus",
|
|
498
498
|
reason: "Qwen has no supported native harness on this runner, and the operator admitted that exact model for guided setup.",
|
|
499
499
|
provingCommand: "pi auth check --provider openrouter",
|
|
500
500
|
} as const;
|
|
@@ -11,7 +11,7 @@ import { deliverInboxNotification } from "./inbox.ts";
|
|
|
11
11
|
import type { HubEvent, MessageRecord } from "./protocol.ts";
|
|
12
12
|
import { sessionTokenFixHint } from "./session-token-hint.ts";
|
|
13
13
|
|
|
14
|
-
const VERSION = "0.7.
|
|
14
|
+
const VERSION = "0.7.187";
|
|
15
15
|
const CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
|
|
16
16
|
const inbox = new Map<string, MessageRecord>();
|
|
17
17
|
const notifiedInbox = new Set<string>();
|