@biffo/cli 0.266.1 → 0.267.0
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/index.js +651 -38
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -2863,6 +2863,24 @@ function assertTargetFidelity(options) {
|
|
|
2863
2863
|
findings.push({ path: entry.path, reason: "content-differs", source });
|
|
2864
2864
|
}
|
|
2865
2865
|
}
|
|
2866
|
+
for (const migration of options.migrations ?? []) {
|
|
2867
|
+
const path = `${MIGRATIONS_VERSIONS_DIR}/${migration.file}`;
|
|
2868
|
+
checked++;
|
|
2869
|
+
if (!blobs.has(path)) {
|
|
2870
|
+
findings.push({ path, reason: "absent-from-tag", source: "migration" });
|
|
2871
|
+
continue;
|
|
2872
|
+
}
|
|
2873
|
+
let tagText;
|
|
2874
|
+
try {
|
|
2875
|
+
tagText = git(["-C", options.templateRepo, "show", `${tag}:${path}`]);
|
|
2876
|
+
} catch {
|
|
2877
|
+
findings.push({ path, reason: "content-differs", source: "migration" });
|
|
2878
|
+
continue;
|
|
2879
|
+
}
|
|
2880
|
+
if (migrationBodyHash(tagText) !== migrationBodyHash(migration.content)) {
|
|
2881
|
+
findings.push({ path, reason: "content-differs", source: "migration" });
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2866
2884
|
return { checked, findings, unverifiable: null };
|
|
2867
2885
|
}
|
|
2868
2886
|
function fidelityFailure(report, toVersion) {
|
|
@@ -3456,8 +3474,14 @@ async function runCoreUpgradeResolved(options, deps, cleanups) {
|
|
|
3456
3474
|
});
|
|
3457
3475
|
const orphanRatchet = checkOrphanRatchet(plan.orphaned.length, readOrphanBaseline(options.cwd));
|
|
3458
3476
|
const newSeams = findNewUndeclaredSeams(baseDir, theirsDir, options.cwd);
|
|
3477
|
+
const migrations = planMigrationCarry({
|
|
3478
|
+
templateDir: theirsDir,
|
|
3479
|
+
instanceDir: options.cwd,
|
|
3480
|
+
declined: readDeclinedMigrations(options.cwd)
|
|
3481
|
+
});
|
|
3459
3482
|
const fidelity = assertTargetFidelity({
|
|
3460
3483
|
entries: plan.entries,
|
|
3484
|
+
migrations: migrations.entries,
|
|
3461
3485
|
templateRepo,
|
|
3462
3486
|
toVersion,
|
|
3463
3487
|
theirsDir,
|
|
@@ -3482,11 +3506,6 @@ async function runCoreUpgradeResolved(options, deps, cleanups) {
|
|
|
3482
3506
|
`${String(plan.orphaned.length)} unsanctioned instance file(s) under a template-owned path (baseline ${String(orphanRatchet.baseline)}) \u2014 see the list above (#1026). Move new instance-written files under a sanctioned carve-out (services/api/tests/instance/, modules/**/instance/) or otherwise reduce the count, then re-run.`
|
|
3483
3507
|
);
|
|
3484
3508
|
}
|
|
3485
|
-
const migrations = planMigrationCarry({
|
|
3486
|
-
templateDir: theirsDir,
|
|
3487
|
-
instanceDir: options.cwd,
|
|
3488
|
-
declined: readDeclinedMigrations(options.cwd)
|
|
3489
|
-
});
|
|
3490
3509
|
const coreVersionCleanup = planCoreVersionCleanup(options.cwd);
|
|
3491
3510
|
if (plan.changes.length === 0 && migrations.entries.length === 0) {
|
|
3492
3511
|
log.success("Nothing to upgrade \u2014 the instance already matches the target for all core files.");
|
|
@@ -10218,8 +10237,8 @@ async function runOwnershipCheck(argv) {
|
|
|
10218
10237
|
const { stdout } = await execa8("git", ["diff", "--cached", "--name-status"], { cwd: root });
|
|
10219
10238
|
({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
|
|
10220
10239
|
if (messageFile) {
|
|
10221
|
-
const { readFileSync: readFileSync32, existsSync:
|
|
10222
|
-
if (
|
|
10240
|
+
const { readFileSync: readFileSync32, existsSync: existsSync43 } = await import("fs");
|
|
10241
|
+
if (existsSync43(messageFile)) commitMessage = readFileSync32(messageFile, "utf8");
|
|
10223
10242
|
}
|
|
10224
10243
|
} else {
|
|
10225
10244
|
const base = process.env["GITHUB_BASE_REF"] ?? args[0];
|
|
@@ -10709,13 +10728,420 @@ async function runPluginTerraformCheck() {
|
|
|
10709
10728
|
}
|
|
10710
10729
|
|
|
10711
10730
|
// src/scripts/check-plugin-tool-supply.ts
|
|
10712
|
-
import { existsSync as
|
|
10731
|
+
import { existsSync as existsSync40 } from "fs";
|
|
10713
10732
|
import { join as join43 } from "path";
|
|
10714
10733
|
import { execa as execa12 } from "execa";
|
|
10715
10734
|
|
|
10716
10735
|
// src/lib/plugin-tool-supply-audit.ts
|
|
10717
|
-
import { readFileSync as readFileSync30, readdirSync as readdirSync18, statSync as statSync10 } from "fs";
|
|
10736
|
+
import { existsSync as existsSync39, readFileSync as readFileSync30, readdirSync as readdirSync18, statSync as statSync10 } from "fs";
|
|
10718
10737
|
import { join as join42 } from "path";
|
|
10738
|
+
|
|
10739
|
+
// src/lib/openrouter-model-snapshot.ts
|
|
10740
|
+
var OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT = "2026-08-10T06:39:01Z";
|
|
10741
|
+
var OPENROUTER_MODEL_IDS = [
|
|
10742
|
+
"ai21/jamba-large-1.7",
|
|
10743
|
+
"aion-labs/aion-2.0",
|
|
10744
|
+
"aion-labs/aion-3.0",
|
|
10745
|
+
"aion-labs/aion-3.0-mini",
|
|
10746
|
+
"aion-labs/aion-rp-llama-3.1-8b",
|
|
10747
|
+
"allenai/olmo-3-32b-think",
|
|
10748
|
+
"amazon/nova-2-lite-v1",
|
|
10749
|
+
"amazon/nova-lite-v1",
|
|
10750
|
+
"amazon/nova-micro-v1",
|
|
10751
|
+
"amazon/nova-premier-v1",
|
|
10752
|
+
"amazon/nova-pro-v1",
|
|
10753
|
+
"anthracite-org/magnum-v4-72b",
|
|
10754
|
+
"anthropic/claude-3-haiku",
|
|
10755
|
+
"anthropic/claude-fable-5",
|
|
10756
|
+
"anthropic/claude-fable-5:batch",
|
|
10757
|
+
"anthropic/claude-haiku-4.5",
|
|
10758
|
+
"anthropic/claude-haiku-4.5:batch",
|
|
10759
|
+
"anthropic/claude-opus-4",
|
|
10760
|
+
"anthropic/claude-opus-4.1",
|
|
10761
|
+
"anthropic/claude-opus-4.1:batch",
|
|
10762
|
+
"anthropic/claude-opus-4.5",
|
|
10763
|
+
"anthropic/claude-opus-4.5:batch",
|
|
10764
|
+
"anthropic/claude-opus-4.6",
|
|
10765
|
+
"anthropic/claude-opus-4.6:batch",
|
|
10766
|
+
"anthropic/claude-opus-4.7",
|
|
10767
|
+
"anthropic/claude-opus-4.7-fast",
|
|
10768
|
+
"anthropic/claude-opus-4.7:batch",
|
|
10769
|
+
"anthropic/claude-opus-4.8",
|
|
10770
|
+
"anthropic/claude-opus-4.8-fast",
|
|
10771
|
+
"anthropic/claude-opus-4.8:batch",
|
|
10772
|
+
"anthropic/claude-opus-5",
|
|
10773
|
+
"anthropic/claude-opus-5-fast",
|
|
10774
|
+
"anthropic/claude-opus-5:batch",
|
|
10775
|
+
"anthropic/claude-sonnet-4",
|
|
10776
|
+
"anthropic/claude-sonnet-4.5",
|
|
10777
|
+
"anthropic/claude-sonnet-4.5:batch",
|
|
10778
|
+
"anthropic/claude-sonnet-4.6",
|
|
10779
|
+
"anthropic/claude-sonnet-4.6:batch",
|
|
10780
|
+
"anthropic/claude-sonnet-5",
|
|
10781
|
+
"anthropic/claude-sonnet-5:batch",
|
|
10782
|
+
"arcee-ai/trinity-large-thinking",
|
|
10783
|
+
"arcee-ai/virtuoso-large",
|
|
10784
|
+
"baidu/ernie-4.5-vl-424b-a47b",
|
|
10785
|
+
"bytedance-seed/seed-1.6",
|
|
10786
|
+
"bytedance-seed/seed-1.6-flash",
|
|
10787
|
+
"bytedance-seed/seed-2.0-lite",
|
|
10788
|
+
"bytedance-seed/seed-2.0-mini",
|
|
10789
|
+
"bytedance/ui-tars-1.5-7b",
|
|
10790
|
+
"cognitivecomputations/dolphin-mistral-24b-venice-edition",
|
|
10791
|
+
"cohere/command-a",
|
|
10792
|
+
"cohere/command-r-08-2024",
|
|
10793
|
+
"cohere/command-r-plus-08-2024",
|
|
10794
|
+
"cohere/command-r7b-12-2024",
|
|
10795
|
+
"cohere/north-mini-code:free",
|
|
10796
|
+
"deepcogito/cogito-v2.1-671b",
|
|
10797
|
+
"deepseek/deepseek-chat",
|
|
10798
|
+
"deepseek/deepseek-chat-v3-0324",
|
|
10799
|
+
"deepseek/deepseek-chat-v3.1",
|
|
10800
|
+
"deepseek/deepseek-r1",
|
|
10801
|
+
"deepseek/deepseek-r1-0528",
|
|
10802
|
+
"deepseek/deepseek-r1-distill-llama-70b",
|
|
10803
|
+
"deepseek/deepseek-v3.1-terminus",
|
|
10804
|
+
"deepseek/deepseek-v3.2",
|
|
10805
|
+
"deepseek/deepseek-v3.2-exp",
|
|
10806
|
+
"deepseek/deepseek-v4-flash",
|
|
10807
|
+
"deepseek/deepseek-v4-flash-0731",
|
|
10808
|
+
"deepseek/deepseek-v4-pro",
|
|
10809
|
+
"google/gemini-2.5-flash",
|
|
10810
|
+
"google/gemini-2.5-flash-image",
|
|
10811
|
+
"google/gemini-2.5-flash-lite",
|
|
10812
|
+
"google/gemini-2.5-flash-lite:batch",
|
|
10813
|
+
"google/gemini-2.5-flash:batch",
|
|
10814
|
+
"google/gemini-2.5-pro",
|
|
10815
|
+
"google/gemini-2.5-pro-preview",
|
|
10816
|
+
"google/gemini-2.5-pro-preview-05-06",
|
|
10817
|
+
"google/gemini-2.5-pro:batch",
|
|
10818
|
+
"google/gemini-3-flash-preview",
|
|
10819
|
+
"google/gemini-3-flash-preview:batch",
|
|
10820
|
+
"google/gemini-3-pro-image",
|
|
10821
|
+
"google/gemini-3-pro-image-preview",
|
|
10822
|
+
"google/gemini-3.1-flash-image",
|
|
10823
|
+
"google/gemini-3.1-flash-image-preview",
|
|
10824
|
+
"google/gemini-3.1-flash-lite",
|
|
10825
|
+
"google/gemini-3.1-flash-lite-image",
|
|
10826
|
+
"google/gemini-3.1-flash-lite-preview",
|
|
10827
|
+
"google/gemini-3.1-flash-lite:batch",
|
|
10828
|
+
"google/gemini-3.1-pro-preview",
|
|
10829
|
+
"google/gemini-3.1-pro-preview-customtools",
|
|
10830
|
+
"google/gemini-3.1-pro-preview:batch",
|
|
10831
|
+
"google/gemini-3.5-flash",
|
|
10832
|
+
"google/gemini-3.5-flash-lite",
|
|
10833
|
+
"google/gemini-3.5-flash-lite:batch",
|
|
10834
|
+
"google/gemini-3.5-flash:batch",
|
|
10835
|
+
"google/gemini-3.6-flash",
|
|
10836
|
+
"google/gemini-3.6-flash:batch",
|
|
10837
|
+
"google/gemma-2-27b-it",
|
|
10838
|
+
"google/gemma-3-12b-it",
|
|
10839
|
+
"google/gemma-3-27b-it",
|
|
10840
|
+
"google/gemma-3-4b-it",
|
|
10841
|
+
"google/gemma-3n-e4b-it",
|
|
10842
|
+
"google/gemma-4-26b-a4b-it",
|
|
10843
|
+
"google/gemma-4-26b-a4b-it:free",
|
|
10844
|
+
"google/gemma-4-31b-it",
|
|
10845
|
+
"google/gemma-4-31b-it:free",
|
|
10846
|
+
"google/lyria-3-clip-preview",
|
|
10847
|
+
"google/lyria-3-pro-preview",
|
|
10848
|
+
"gryphe/mythomax-l2-13b",
|
|
10849
|
+
"ibm-granite/granite-4.0-h-micro",
|
|
10850
|
+
"ibm-granite/granite-4.1-8b",
|
|
10851
|
+
"inception/mercury-2",
|
|
10852
|
+
"inclusionai/ling-2.6-1t",
|
|
10853
|
+
"inclusionai/ling-2.6-flash",
|
|
10854
|
+
"inclusionai/ling-3.0-flash",
|
|
10855
|
+
"inclusionai/ling-3.0-tiny:free",
|
|
10856
|
+
"inclusionai/ring-2.6-1t",
|
|
10857
|
+
"kwaipilot/kat-coder-air-v2.5",
|
|
10858
|
+
"kwaipilot/kat-coder-pro-v2",
|
|
10859
|
+
"kwaipilot/kat-coder-pro-v2.5",
|
|
10860
|
+
"mancer/weaver",
|
|
10861
|
+
"meituan/longcat-2.0",
|
|
10862
|
+
"meta-llama/llama-3.1-70b-instruct",
|
|
10863
|
+
"meta-llama/llama-3.1-8b-instruct",
|
|
10864
|
+
"meta-llama/llama-3.2-1b-instruct",
|
|
10865
|
+
"meta-llama/llama-3.2-3b-instruct",
|
|
10866
|
+
"meta-llama/llama-3.3-70b-instruct",
|
|
10867
|
+
"meta-llama/llama-4-maverick",
|
|
10868
|
+
"meta-llama/llama-4-scout",
|
|
10869
|
+
"meta-llama/llama-guard-4-12b",
|
|
10870
|
+
"meta/muse-spark-1.1",
|
|
10871
|
+
"meta/muse-spark-1.2",
|
|
10872
|
+
"microsoft/phi-4",
|
|
10873
|
+
"microsoft/wizardlm-2-8x22b",
|
|
10874
|
+
"minimax/minimax-01",
|
|
10875
|
+
"minimax/minimax-m1",
|
|
10876
|
+
"minimax/minimax-m2",
|
|
10877
|
+
"minimax/minimax-m2-her",
|
|
10878
|
+
"minimax/minimax-m2.1",
|
|
10879
|
+
"minimax/minimax-m2.5",
|
|
10880
|
+
"minimax/minimax-m2.7",
|
|
10881
|
+
"minimax/minimax-m3",
|
|
10882
|
+
"minimax/minimax-m3:batch",
|
|
10883
|
+
"mistralai/codestral-2508",
|
|
10884
|
+
"mistralai/ministral-14b-2512",
|
|
10885
|
+
"mistralai/ministral-3b-2512",
|
|
10886
|
+
"mistralai/ministral-8b-2512",
|
|
10887
|
+
"mistralai/mistral-large",
|
|
10888
|
+
"mistralai/mistral-large-2407",
|
|
10889
|
+
"mistralai/mistral-large-2512",
|
|
10890
|
+
"mistralai/mistral-medium-3",
|
|
10891
|
+
"mistralai/mistral-medium-3-5",
|
|
10892
|
+
"mistralai/mistral-medium-3.1",
|
|
10893
|
+
"mistralai/mistral-nemo",
|
|
10894
|
+
"mistralai/mistral-saba",
|
|
10895
|
+
"mistralai/mistral-small-24b-instruct-2501",
|
|
10896
|
+
"mistralai/mistral-small-2603",
|
|
10897
|
+
"mistralai/mistral-small-3.1-24b-instruct",
|
|
10898
|
+
"mistralai/mistral-small-3.2-24b-instruct",
|
|
10899
|
+
"mistralai/mixtral-8x22b-instruct",
|
|
10900
|
+
"mistralai/voxtral-small-24b-2507",
|
|
10901
|
+
"moonshotai/kimi-k2",
|
|
10902
|
+
"moonshotai/kimi-k2-0905",
|
|
10903
|
+
"moonshotai/kimi-k2-thinking",
|
|
10904
|
+
"moonshotai/kimi-k2.5",
|
|
10905
|
+
"moonshotai/kimi-k2.6",
|
|
10906
|
+
"moonshotai/kimi-k2.7-code",
|
|
10907
|
+
"moonshotai/kimi-k2.7-code:batch",
|
|
10908
|
+
"moonshotai/kimi-k3",
|
|
10909
|
+
"morph/morph-v3-fast",
|
|
10910
|
+
"morph/morph-v3-large",
|
|
10911
|
+
"nex-agi/nex-n2-mini",
|
|
10912
|
+
"nex-agi/nex-n2-pro",
|
|
10913
|
+
"nousresearch/hermes-3-llama-3.1-405b",
|
|
10914
|
+
"nousresearch/hermes-3-llama-3.1-70b",
|
|
10915
|
+
"nousresearch/hermes-4-405b",
|
|
10916
|
+
"nousresearch/hermes-4-70b",
|
|
10917
|
+
"nvidia/nemotron-3-nano-30b-a3b",
|
|
10918
|
+
"nvidia/nemotron-3-nano-30b-a3b:free",
|
|
10919
|
+
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free",
|
|
10920
|
+
"nvidia/nemotron-3-super-120b-a12b",
|
|
10921
|
+
"nvidia/nemotron-3-super-120b-a12b:free",
|
|
10922
|
+
"nvidia/nemotron-3-ultra-550b-a55b",
|
|
10923
|
+
"nvidia/nemotron-3-ultra-550b-a55b:batch",
|
|
10924
|
+
"nvidia/nemotron-3-ultra-550b-a55b:free",
|
|
10925
|
+
"nvidia/nemotron-3.5-content-safety:free",
|
|
10926
|
+
"nvidia/nemotron-nano-12b-v2-vl:free",
|
|
10927
|
+
"nvidia/nemotron-nano-9b-v2:free",
|
|
10928
|
+
"openai/gpt-3.5-turbo",
|
|
10929
|
+
"openai/gpt-3.5-turbo-0613",
|
|
10930
|
+
"openai/gpt-3.5-turbo-16k",
|
|
10931
|
+
"openai/gpt-3.5-turbo-instruct",
|
|
10932
|
+
"openai/gpt-3.5-turbo:batch",
|
|
10933
|
+
"openai/gpt-4",
|
|
10934
|
+
"openai/gpt-4-turbo",
|
|
10935
|
+
"openai/gpt-4-turbo-preview",
|
|
10936
|
+
"openai/gpt-4-turbo:batch",
|
|
10937
|
+
"openai/gpt-4.1",
|
|
10938
|
+
"openai/gpt-4.1-mini",
|
|
10939
|
+
"openai/gpt-4.1-mini:batch",
|
|
10940
|
+
"openai/gpt-4.1-nano",
|
|
10941
|
+
"openai/gpt-4.1-nano:batch",
|
|
10942
|
+
"openai/gpt-4.1:batch",
|
|
10943
|
+
"openai/gpt-4o",
|
|
10944
|
+
"openai/gpt-4o-2024-05-13",
|
|
10945
|
+
"openai/gpt-4o-2024-08-06",
|
|
10946
|
+
"openai/gpt-4o-2024-11-20",
|
|
10947
|
+
"openai/gpt-4o-mini",
|
|
10948
|
+
"openai/gpt-4o-mini-2024-07-18",
|
|
10949
|
+
"openai/gpt-4o-mini:batch",
|
|
10950
|
+
"openai/gpt-4o:batch",
|
|
10951
|
+
"openai/gpt-5",
|
|
10952
|
+
"openai/gpt-5-codex:batch",
|
|
10953
|
+
"openai/gpt-5-image",
|
|
10954
|
+
"openai/gpt-5-image-mini",
|
|
10955
|
+
"openai/gpt-5-mini",
|
|
10956
|
+
"openai/gpt-5-mini:batch",
|
|
10957
|
+
"openai/gpt-5-nano",
|
|
10958
|
+
"openai/gpt-5-nano:batch",
|
|
10959
|
+
"openai/gpt-5-pro",
|
|
10960
|
+
"openai/gpt-5-pro:batch",
|
|
10961
|
+
"openai/gpt-5.1",
|
|
10962
|
+
"openai/gpt-5.1-codex",
|
|
10963
|
+
"openai/gpt-5.1-codex-max",
|
|
10964
|
+
"openai/gpt-5.1-codex-mini",
|
|
10965
|
+
"openai/gpt-5.1:batch",
|
|
10966
|
+
"openai/gpt-5.2",
|
|
10967
|
+
"openai/gpt-5.2-chat",
|
|
10968
|
+
"openai/gpt-5.2-codex",
|
|
10969
|
+
"openai/gpt-5.2-pro",
|
|
10970
|
+
"openai/gpt-5.2-pro:batch",
|
|
10971
|
+
"openai/gpt-5.2:batch",
|
|
10972
|
+
"openai/gpt-5.3-chat",
|
|
10973
|
+
"openai/gpt-5.3-codex",
|
|
10974
|
+
"openai/gpt-5.4",
|
|
10975
|
+
"openai/gpt-5.4-image-2",
|
|
10976
|
+
"openai/gpt-5.4-mini",
|
|
10977
|
+
"openai/gpt-5.4-mini:batch",
|
|
10978
|
+
"openai/gpt-5.4-nano",
|
|
10979
|
+
"openai/gpt-5.4-nano:batch",
|
|
10980
|
+
"openai/gpt-5.4-pro",
|
|
10981
|
+
"openai/gpt-5.4-pro:batch",
|
|
10982
|
+
"openai/gpt-5.4:batch",
|
|
10983
|
+
"openai/gpt-5.5",
|
|
10984
|
+
"openai/gpt-5.5-pro",
|
|
10985
|
+
"openai/gpt-5.5-pro:batch",
|
|
10986
|
+
"openai/gpt-5.5:batch",
|
|
10987
|
+
"openai/gpt-5.6-luna",
|
|
10988
|
+
"openai/gpt-5.6-luna-pro",
|
|
10989
|
+
"openai/gpt-5.6-luna-pro:batch",
|
|
10990
|
+
"openai/gpt-5.6-luna:batch",
|
|
10991
|
+
"openai/gpt-5.6-sol",
|
|
10992
|
+
"openai/gpt-5.6-sol-pro",
|
|
10993
|
+
"openai/gpt-5.6-sol-pro:batch",
|
|
10994
|
+
"openai/gpt-5.6-sol:batch",
|
|
10995
|
+
"openai/gpt-5.6-terra",
|
|
10996
|
+
"openai/gpt-5.6-terra-pro",
|
|
10997
|
+
"openai/gpt-5.6-terra-pro:batch",
|
|
10998
|
+
"openai/gpt-5.6-terra:batch",
|
|
10999
|
+
"openai/gpt-5:batch",
|
|
11000
|
+
"openai/gpt-audio",
|
|
11001
|
+
"openai/gpt-audio-mini",
|
|
11002
|
+
"openai/gpt-chat-latest",
|
|
11003
|
+
"openai/gpt-oss-120b",
|
|
11004
|
+
"openai/gpt-oss-20b",
|
|
11005
|
+
"openai/gpt-oss-20b:free",
|
|
11006
|
+
"openai/gpt-oss-safeguard-20b",
|
|
11007
|
+
"openai/o1",
|
|
11008
|
+
"openai/o1-pro",
|
|
11009
|
+
"openai/o1-pro:batch",
|
|
11010
|
+
"openai/o1:batch",
|
|
11011
|
+
"openai/o3",
|
|
11012
|
+
"openai/o3-mini",
|
|
11013
|
+
"openai/o3-mini-high",
|
|
11014
|
+
"openai/o3-mini-high:batch",
|
|
11015
|
+
"openai/o3-mini:batch",
|
|
11016
|
+
"openai/o3-pro",
|
|
11017
|
+
"openai/o3-pro:batch",
|
|
11018
|
+
"openai/o3:batch",
|
|
11019
|
+
"openai/o4-mini",
|
|
11020
|
+
"openai/o4-mini-high",
|
|
11021
|
+
"openai/o4-mini-high:batch",
|
|
11022
|
+
"openai/o4-mini:batch",
|
|
11023
|
+
"openrouter/auto",
|
|
11024
|
+
"openrouter/auto-beta",
|
|
11025
|
+
"openrouter/bodybuilder",
|
|
11026
|
+
"openrouter/free",
|
|
11027
|
+
"openrouter/fusion",
|
|
11028
|
+
"openrouter/pareto-code",
|
|
11029
|
+
"perceptron/perceptron-mk1",
|
|
11030
|
+
"perplexity/sonar",
|
|
11031
|
+
"perplexity/sonar-deep-research",
|
|
11032
|
+
"perplexity/sonar-pro",
|
|
11033
|
+
"perplexity/sonar-pro-search",
|
|
11034
|
+
"perplexity/sonar-reasoning-pro",
|
|
11035
|
+
"poolside/laguna-s-2.1",
|
|
11036
|
+
"poolside/laguna-s-2.1:free",
|
|
11037
|
+
"poolside/laguna-xs-2.1",
|
|
11038
|
+
"poolside/laguna-xs-2.1:free",
|
|
11039
|
+
"qwen/qwen-2.5-72b-instruct",
|
|
11040
|
+
"qwen/qwen-2.5-7b-instruct",
|
|
11041
|
+
"qwen/qwen-2.5-coder-32b-instruct",
|
|
11042
|
+
"qwen/qwen-plus",
|
|
11043
|
+
"qwen/qwen-plus-2025-07-28",
|
|
11044
|
+
"qwen/qwen-plus-2025-07-28:thinking",
|
|
11045
|
+
"qwen/qwen2.5-vl-72b-instruct",
|
|
11046
|
+
"qwen/qwen3-14b",
|
|
11047
|
+
"qwen/qwen3-235b-a22b",
|
|
11048
|
+
"qwen/qwen3-235b-a22b-2507",
|
|
11049
|
+
"qwen/qwen3-235b-a22b-thinking-2507",
|
|
11050
|
+
"qwen/qwen3-30b-a3b",
|
|
11051
|
+
"qwen/qwen3-30b-a3b-instruct-2507",
|
|
11052
|
+
"qwen/qwen3-30b-a3b-thinking-2507",
|
|
11053
|
+
"qwen/qwen3-32b",
|
|
11054
|
+
"qwen/qwen3-8b",
|
|
11055
|
+
"qwen/qwen3-coder",
|
|
11056
|
+
"qwen/qwen3-coder-30b-a3b-instruct",
|
|
11057
|
+
"qwen/qwen3-coder-flash",
|
|
11058
|
+
"qwen/qwen3-coder-next",
|
|
11059
|
+
"qwen/qwen3-coder-plus",
|
|
11060
|
+
"qwen/qwen3-max",
|
|
11061
|
+
"qwen/qwen3-max-thinking",
|
|
11062
|
+
"qwen/qwen3-next-80b-a3b-instruct",
|
|
11063
|
+
"qwen/qwen3-next-80b-a3b-thinking",
|
|
11064
|
+
"qwen/qwen3-vl-235b-a22b-instruct",
|
|
11065
|
+
"qwen/qwen3-vl-235b-a22b-thinking",
|
|
11066
|
+
"qwen/qwen3-vl-30b-a3b-instruct",
|
|
11067
|
+
"qwen/qwen3-vl-30b-a3b-thinking",
|
|
11068
|
+
"qwen/qwen3-vl-32b-instruct",
|
|
11069
|
+
"qwen/qwen3-vl-8b-instruct",
|
|
11070
|
+
"qwen/qwen3-vl-8b-thinking",
|
|
11071
|
+
"qwen/qwen3.5-122b-a10b",
|
|
11072
|
+
"qwen/qwen3.5-27b",
|
|
11073
|
+
"qwen/qwen3.5-35b-a3b",
|
|
11074
|
+
"qwen/qwen3.5-397b-a17b",
|
|
11075
|
+
"qwen/qwen3.5-9b",
|
|
11076
|
+
"qwen/qwen3.5-flash-02-23",
|
|
11077
|
+
"qwen/qwen3.5-plus-02-15",
|
|
11078
|
+
"qwen/qwen3.5-plus-20260420",
|
|
11079
|
+
"qwen/qwen3.6-27b",
|
|
11080
|
+
"qwen/qwen3.6-35b-a3b",
|
|
11081
|
+
"qwen/qwen3.6-flash",
|
|
11082
|
+
"qwen/qwen3.6-max-preview",
|
|
11083
|
+
"qwen/qwen3.6-plus",
|
|
11084
|
+
"qwen/qwen3.7-flash",
|
|
11085
|
+
"qwen/qwen3.7-max",
|
|
11086
|
+
"qwen/qwen3.7-plus",
|
|
11087
|
+
"qwen/qwen3.8-max",
|
|
11088
|
+
"rekaai/reka-edge",
|
|
11089
|
+
"rekaai/reka-flash-3",
|
|
11090
|
+
"relace/relace-apply-3",
|
|
11091
|
+
"relace/relace-search",
|
|
11092
|
+
"sakana/fugu-ultra",
|
|
11093
|
+
"sao10k/l3-lunaris-8b",
|
|
11094
|
+
"sao10k/l3.1-euryale-70b",
|
|
11095
|
+
"sao10k/l3.3-euryale-70b",
|
|
11096
|
+
"stepfun/step-3.5-flash",
|
|
11097
|
+
"stepfun/step-3.7-flash",
|
|
11098
|
+
"tencent/hunyuan-a13b-instruct",
|
|
11099
|
+
"tencent/hy3",
|
|
11100
|
+
"tencent/hy3-preview",
|
|
11101
|
+
"thedrummer/cydonia-24b-v4.1",
|
|
11102
|
+
"thedrummer/rocinante-12b",
|
|
11103
|
+
"thedrummer/skyfall-36b-v2",
|
|
11104
|
+
"thedrummer/unslopnemo-12b",
|
|
11105
|
+
"thinkingmachines/inkling",
|
|
11106
|
+
"thinkingmachines/inkling-small",
|
|
11107
|
+
"thinkingmachines/inkling:batch",
|
|
11108
|
+
"undi95/remm-slerp-l2-13b",
|
|
11109
|
+
"upstage/solar-pro-3",
|
|
11110
|
+
"writer/palmyra-x5",
|
|
11111
|
+
"x-ai/grok-4.20",
|
|
11112
|
+
"x-ai/grok-4.20-multi-agent",
|
|
11113
|
+
"x-ai/grok-4.3",
|
|
11114
|
+
"x-ai/grok-4.5",
|
|
11115
|
+
"x-ai/grok-build-0.1",
|
|
11116
|
+
"xiaomi/mimo-v2.5",
|
|
11117
|
+
"xiaomi/mimo-v2.5-pro",
|
|
11118
|
+
"z-ai/glm-4.5",
|
|
11119
|
+
"z-ai/glm-4.5-air",
|
|
11120
|
+
"z-ai/glm-4.5v",
|
|
11121
|
+
"z-ai/glm-4.6",
|
|
11122
|
+
"z-ai/glm-4.6v",
|
|
11123
|
+
"z-ai/glm-4.7",
|
|
11124
|
+
"z-ai/glm-4.7-flash",
|
|
11125
|
+
"z-ai/glm-5",
|
|
11126
|
+
"z-ai/glm-5-turbo",
|
|
11127
|
+
"z-ai/glm-5.1",
|
|
11128
|
+
"z-ai/glm-5.2",
|
|
11129
|
+
"z-ai/glm-5.2:batch",
|
|
11130
|
+
"z-ai/glm-5v-turbo",
|
|
11131
|
+
"~anthropic/claude-fable-latest",
|
|
11132
|
+
"~anthropic/claude-haiku-latest",
|
|
11133
|
+
"~anthropic/claude-opus-latest",
|
|
11134
|
+
"~anthropic/claude-sonnet-latest",
|
|
11135
|
+
"~deepseek/deepseek-v4-flash-latest",
|
|
11136
|
+
"~google/gemini-flash-latest",
|
|
11137
|
+
"~google/gemini-pro-latest",
|
|
11138
|
+
"~moonshotai/kimi-latest",
|
|
11139
|
+
"~openai/gpt-latest",
|
|
11140
|
+
"~openai/gpt-mini-latest",
|
|
11141
|
+
"~x-ai/grok-latest"
|
|
11142
|
+
];
|
|
11143
|
+
|
|
11144
|
+
// src/lib/plugin-tool-supply-audit.ts
|
|
10719
11145
|
function listDirs(root) {
|
|
10720
11146
|
let entries;
|
|
10721
11147
|
try {
|
|
@@ -10968,6 +11394,148 @@ function extractTerraformEnvKeys(tfText) {
|
|
|
10968
11394
|
}
|
|
10969
11395
|
return { keys: [...keys].sort(), rawMarkerCount, resolvedBlockCount };
|
|
10970
11396
|
}
|
|
11397
|
+
var SETTINGS_STR_FIELD = /^[ \t]*([A-Za-z_][A-Za-z0-9_]*)\s*:\s*str\s*=\s*"([^"]*)"/gm;
|
|
11398
|
+
function extractSettingsModelFields(text) {
|
|
11399
|
+
const out = [];
|
|
11400
|
+
SETTINGS_STR_FIELD.lastIndex = 0;
|
|
11401
|
+
let m;
|
|
11402
|
+
while ((m = SETTINGS_STR_FIELD.exec(text)) !== null) {
|
|
11403
|
+
const [field, value] = [m[1], m[2]];
|
|
11404
|
+
if (field.toLowerCase().includes("model") && value.includes("/")) {
|
|
11405
|
+
out.push({ field, value });
|
|
11406
|
+
}
|
|
11407
|
+
}
|
|
11408
|
+
return out;
|
|
11409
|
+
}
|
|
11410
|
+
var MODEL_FIELD_NAME_MARKER = /"name"\s*:\s*"model"/g;
|
|
11411
|
+
var FIELD_DEFAULT = /"default"\s*:\s*"([^"]*)"/;
|
|
11412
|
+
var FIELD_OPTIONS_START = /"options"\s*:\s*\[/;
|
|
11413
|
+
var OPTION_VALUE = /"value"\s*:\s*"([^"]*)"/g;
|
|
11414
|
+
function extractCuratedModelFields(text) {
|
|
11415
|
+
const fields = [];
|
|
11416
|
+
let rawFieldCount = 0;
|
|
11417
|
+
MODEL_FIELD_NAME_MARKER.lastIndex = 0;
|
|
11418
|
+
let m;
|
|
11419
|
+
while ((m = MODEL_FIELD_NAME_MARKER.exec(text)) !== null) {
|
|
11420
|
+
rawFieldCount += 1;
|
|
11421
|
+
const start = m.index + m[0].length;
|
|
11422
|
+
const nextNameIdx = text.indexOf('"name"', start);
|
|
11423
|
+
const windowEnd = nextNameIdx === -1 ? text.length : nextNameIdx;
|
|
11424
|
+
const window = text.slice(start, windowEnd);
|
|
11425
|
+
const defaultMatch = FIELD_DEFAULT.exec(window);
|
|
11426
|
+
const defaultValue = defaultMatch ? defaultMatch[1] : null;
|
|
11427
|
+
const optionsMatch = FIELD_OPTIONS_START.exec(window);
|
|
11428
|
+
const optionValues = [];
|
|
11429
|
+
if (optionsMatch) {
|
|
11430
|
+
const openIdx = start + optionsMatch.index + optionsMatch[0].length - 1;
|
|
11431
|
+
const closeIdx = balancedSpanFrom(text, openIdx, "[", "]");
|
|
11432
|
+
if (closeIdx !== null) {
|
|
11433
|
+
const inner = text.slice(openIdx, closeIdx + 1);
|
|
11434
|
+
OPTION_VALUE.lastIndex = 0;
|
|
11435
|
+
let om;
|
|
11436
|
+
while ((om = OPTION_VALUE.exec(inner)) !== null) {
|
|
11437
|
+
optionValues.push(om[1]);
|
|
11438
|
+
}
|
|
11439
|
+
}
|
|
11440
|
+
}
|
|
11441
|
+
fields.push({ defaultValue, optionValues });
|
|
11442
|
+
}
|
|
11443
|
+
return { rawFieldCount, fields };
|
|
11444
|
+
}
|
|
11445
|
+
var MODEL_SNAPSHOT_MAX_AGE_DAYS = 45;
|
|
11446
|
+
function isSnapshotStale(fetchedAt, now) {
|
|
11447
|
+
const fetchedMs = new Date(fetchedAt).getTime();
|
|
11448
|
+
if (Number.isNaN(fetchedMs)) return true;
|
|
11449
|
+
const ageMs = now.getTime() - fetchedMs;
|
|
11450
|
+
return ageMs > MODEL_SNAPSHOT_MAX_AGE_DAYS * 24 * 60 * 60 * 1e3;
|
|
11451
|
+
}
|
|
11452
|
+
function normalizeModelId(id) {
|
|
11453
|
+
return id.endsWith(":online") ? id.slice(0, -":online".length) : id;
|
|
11454
|
+
}
|
|
11455
|
+
var CONFIG_PY_PATH = join42("services", "api", "src", "api", "config.py");
|
|
11456
|
+
var ORCHESTRATION_SCHEMA_PATH = join42(
|
|
11457
|
+
"services",
|
|
11458
|
+
"api",
|
|
11459
|
+
"src",
|
|
11460
|
+
"api",
|
|
11461
|
+
"schemas",
|
|
11462
|
+
"orchestration.py"
|
|
11463
|
+
);
|
|
11464
|
+
function auditDeclaredModelIds(repoRoot, options = {}) {
|
|
11465
|
+
const knownModelIds = options.knownModelIds ?? OPENROUTER_MODEL_IDS;
|
|
11466
|
+
const snapshotFetchedAt = options.snapshotFetchedAt ?? OPENROUTER_MODEL_SNAPSHOT_FETCHED_AT;
|
|
11467
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
11468
|
+
const configPath = join42(repoRoot, CONFIG_PY_PATH);
|
|
11469
|
+
const orchestrationPath = join42(repoRoot, ORCHESTRATION_SCHEMA_PATH);
|
|
11470
|
+
const configMissing = !existsSync39(configPath);
|
|
11471
|
+
const orchestrationSchemaMissing = !existsSync39(orchestrationPath);
|
|
11472
|
+
const knownSet = new Set(knownModelIds);
|
|
11473
|
+
const snapshotEmpty = knownModelIds.length === 0;
|
|
11474
|
+
const snapshotStale = isSnapshotStale(snapshotFetchedAt, now);
|
|
11475
|
+
const findings = [];
|
|
11476
|
+
const record = (source, rawValue) => {
|
|
11477
|
+
const normalized = normalizeModelId(rawValue);
|
|
11478
|
+
const ok2 = knownSet.has(normalized);
|
|
11479
|
+
findings.push({
|
|
11480
|
+
source,
|
|
11481
|
+
modelId: rawValue,
|
|
11482
|
+
normalizedModelId: normalized,
|
|
11483
|
+
status: ok2 ? "ok" : "unknown-model",
|
|
11484
|
+
detail: ok2 ? `"${rawValue}" is in the OpenRouter snapshot (${knownModelIds.length} id(s), fetched ${snapshotFetchedAt})` : `"${rawValue}" (normalized "${normalized}") is NOT in the OpenRouter snapshot (${knownModelIds.length} id(s), fetched ${snapshotFetchedAt}) \u2014 either the slug is wrong or the snapshot needs a refresh`
|
|
11485
|
+
});
|
|
11486
|
+
};
|
|
11487
|
+
let settingsBlind = false;
|
|
11488
|
+
if (!configMissing) {
|
|
11489
|
+
const settingsFields = extractSettingsModelFields(readFileSync30(configPath, "utf8"));
|
|
11490
|
+
if (settingsFields.length === 0) settingsBlind = true;
|
|
11491
|
+
for (const { field, value } of settingsFields) record(`${CONFIG_PY_PATH}#${field}`, value);
|
|
11492
|
+
}
|
|
11493
|
+
let curatedFieldsBlind = false;
|
|
11494
|
+
if (!orchestrationSchemaMissing) {
|
|
11495
|
+
const curated = extractCuratedModelFields(readFileSync30(orchestrationPath, "utf8"));
|
|
11496
|
+
if (curated.rawFieldCount > 0 && curated.fields.every((f) => f.defaultValue === null && f.optionValues.length === 0)) {
|
|
11497
|
+
curatedFieldsBlind = true;
|
|
11498
|
+
}
|
|
11499
|
+
curated.fields.forEach((field, i) => {
|
|
11500
|
+
if (field.defaultValue !== null) {
|
|
11501
|
+
record(`${ORCHESTRATION_SCHEMA_PATH}#model[${i}].default`, field.defaultValue);
|
|
11502
|
+
}
|
|
11503
|
+
field.optionValues.forEach((v, j) => {
|
|
11504
|
+
record(`${ORCHESTRATION_SCHEMA_PATH}#model[${i}].options[${j}]`, v);
|
|
11505
|
+
});
|
|
11506
|
+
});
|
|
11507
|
+
}
|
|
11508
|
+
const badFindings = findings.filter((f) => f.status !== "ok");
|
|
11509
|
+
const ok = !configMissing && !orchestrationSchemaMissing && !settingsBlind && !curatedFieldsBlind && !snapshotEmpty && !snapshotStale && badFindings.length === 0;
|
|
11510
|
+
const summaryParts = [
|
|
11511
|
+
`${findings.length} declared model id(s) checked against ${knownModelIds.length} known OpenRouter id(s) (snapshot fetched ${snapshotFetchedAt})`,
|
|
11512
|
+
`${badFindings.length} not ok`
|
|
11513
|
+
];
|
|
11514
|
+
if (configMissing) summaryParts.push(`MISSING ${CONFIG_PY_PATH}`);
|
|
11515
|
+
if (orchestrationSchemaMissing) summaryParts.push(`MISSING ${ORCHESTRATION_SCHEMA_PATH}`);
|
|
11516
|
+
if (settingsBlind) summaryParts.push("SETTINGS EXTRACTOR BLIND");
|
|
11517
|
+
if (curatedFieldsBlind) summaryParts.push("CURATED-OPTIONS EXTRACTOR BLIND");
|
|
11518
|
+
if (snapshotEmpty) summaryParts.push("SNAPSHOT EMPTY");
|
|
11519
|
+
if (snapshotStale)
|
|
11520
|
+
summaryParts.push(
|
|
11521
|
+
`SNAPSHOT STALE (older than ${MODEL_SNAPSHOT_MAX_AGE_DAYS}d \u2014 run refresh-openrouter-model-snapshot.ts)`
|
|
11522
|
+
);
|
|
11523
|
+
return {
|
|
11524
|
+
configPath: CONFIG_PY_PATH,
|
|
11525
|
+
orchestrationSchemaPath: ORCHESTRATION_SCHEMA_PATH,
|
|
11526
|
+
configMissing,
|
|
11527
|
+
orchestrationSchemaMissing,
|
|
11528
|
+
settingsBlind,
|
|
11529
|
+
curatedFieldsBlind,
|
|
11530
|
+
snapshotFetchedAt,
|
|
11531
|
+
snapshotModelCount: knownModelIds.length,
|
|
11532
|
+
snapshotEmpty,
|
|
11533
|
+
snapshotStale,
|
|
11534
|
+
findings,
|
|
11535
|
+
ok,
|
|
11536
|
+
summary: summaryParts.join("; ")
|
|
11537
|
+
};
|
|
11538
|
+
}
|
|
10971
11539
|
function discoverPluginDirs(pluginsRoot) {
|
|
10972
11540
|
return listDirs(pluginsRoot).filter((name) => {
|
|
10973
11541
|
try {
|
|
@@ -11115,37 +11683,82 @@ function auditPluginToolSupply(pluginsRoot) {
|
|
|
11115
11683
|
// src/scripts/check-plugin-tool-supply.ts
|
|
11116
11684
|
async function runPluginToolSupplyCheck() {
|
|
11117
11685
|
const root = (await execa12("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
11686
|
+
let allOk = true;
|
|
11118
11687
|
const pluginsRoot = join43(root, "services", "_plugins");
|
|
11119
|
-
if (!
|
|
11688
|
+
if (!existsSync40(pluginsRoot)) {
|
|
11120
11689
|
console.log("\u2713 plugin tool-supply guard: no services/_plugins/ \u2014 nothing to audit");
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11690
|
+
} else {
|
|
11691
|
+
const report = auditPluginToolSupply(pluginsRoot);
|
|
11692
|
+
console.log(
|
|
11693
|
+
`audited ${report.plugins.length} plugin dir(s), ${report.findings.length} declared tool(s) cross-checked, under ${pluginsRoot}`
|
|
11694
|
+
);
|
|
11695
|
+
if (!report.ok) {
|
|
11696
|
+
allOk = false;
|
|
11697
|
+
console.error("\u2717 plugin tool-supply guard: an unsatisfiable tool grant found\n");
|
|
11698
|
+
if (report.noPluginsFound) {
|
|
11699
|
+
console.error(` NO PLUGINS FOUND under ${pluginsRoot} \u2014 cannot evaluate an empty world.`);
|
|
11700
|
+
}
|
|
11701
|
+
if (report.registryBlind) {
|
|
11702
|
+
console.error(
|
|
11703
|
+
" REGISTRY BLIND: raw source contains ToolDefinition( call site(s) but the extractor resolved none \u2014 the extractor broke, this is not evidence a plugin registers nothing."
|
|
11704
|
+
);
|
|
11705
|
+
}
|
|
11706
|
+
if (report.terraformBlind) {
|
|
11707
|
+
console.error(
|
|
11708
|
+
" TERRAFORM BLIND: raw source contains environment_variables but the extractor resolved no keys \u2014 the extractor broke, this is not evidence of an empty Lambda."
|
|
11709
|
+
);
|
|
11710
|
+
}
|
|
11711
|
+
for (const f of report.findings.filter((f2) => f2.status !== "ok")) {
|
|
11712
|
+
console.error(` ${f.status.toUpperCase()} ${f.plugin}/${f.tool} ${f.detail}`);
|
|
11713
|
+
}
|
|
11714
|
+
} else {
|
|
11715
|
+
console.log(`\u2713 plugin tool-supply guard: ${report.summary}`);
|
|
11141
11716
|
}
|
|
11142
|
-
|
|
11143
|
-
|
|
11717
|
+
}
|
|
11718
|
+
const servicesApiRoot = join43(root, "services", "api");
|
|
11719
|
+
if (!existsSync40(servicesApiRoot)) {
|
|
11720
|
+
console.log("\u2713 plugin model-id guard: no services/api/ \u2014 nothing to audit");
|
|
11721
|
+
} else {
|
|
11722
|
+
const modelReport = auditDeclaredModelIds(root);
|
|
11723
|
+
console.log(`audited ${modelReport.findings.length} declared model id(s)`);
|
|
11724
|
+
if (!modelReport.ok) {
|
|
11725
|
+
allOk = false;
|
|
11726
|
+
console.error("\u2717 plugin model-id guard: a declared model id does not match the provider\n");
|
|
11727
|
+
if (modelReport.configMissing) {
|
|
11728
|
+
console.error(` MISSING ${modelReport.configPath}`);
|
|
11729
|
+
}
|
|
11730
|
+
if (modelReport.orchestrationSchemaMissing) {
|
|
11731
|
+
console.error(` MISSING ${modelReport.orchestrationSchemaPath}`);
|
|
11732
|
+
}
|
|
11733
|
+
if (modelReport.settingsBlind) {
|
|
11734
|
+
console.error(
|
|
11735
|
+
` SETTINGS EXTRACTOR BLIND: ${modelReport.configPath} exists but no model-named string field resolved \u2014 the extractor broke, this is not evidence there is no default.`
|
|
11736
|
+
);
|
|
11737
|
+
}
|
|
11738
|
+
if (modelReport.curatedFieldsBlind) {
|
|
11739
|
+
console.error(
|
|
11740
|
+
` CURATED-OPTIONS EXTRACTOR BLIND: ${modelReport.orchestrationSchemaPath} has a "name": "model" field but no default/options resolved from it.`
|
|
11741
|
+
);
|
|
11742
|
+
}
|
|
11743
|
+
if (modelReport.snapshotEmpty) {
|
|
11744
|
+
console.error(" SNAPSHOT EMPTY: the committed OpenRouter snapshot has zero ids.");
|
|
11745
|
+
}
|
|
11746
|
+
if (modelReport.snapshotStale) {
|
|
11747
|
+
console.error(
|
|
11748
|
+
` SNAPSHOT STALE: fetched ${modelReport.snapshotFetchedAt}, older than the refresh window \u2014 run refresh-openrouter-model-snapshot.ts and commit the result.`
|
|
11749
|
+
);
|
|
11750
|
+
}
|
|
11751
|
+
for (const f of modelReport.findings.filter((f2) => f2.status !== "ok")) {
|
|
11752
|
+
console.error(` ${f.status.toUpperCase()} ${f.source} ${f.detail}`);
|
|
11753
|
+
}
|
|
11754
|
+
} else {
|
|
11755
|
+
console.log(`\u2713 plugin model-id guard: ${modelReport.summary}`);
|
|
11144
11756
|
}
|
|
11757
|
+
}
|
|
11758
|
+
if (!allOk) {
|
|
11145
11759
|
console.error("\nSee biffo-template#822.");
|
|
11146
11760
|
process.exit(1);
|
|
11147
11761
|
}
|
|
11148
|
-
console.log(`\u2713 plugin tool-supply guard: ${report.summary}`);
|
|
11149
11762
|
}
|
|
11150
11763
|
|
|
11151
11764
|
// src/scripts/check-release-subject.ts
|
|
@@ -11329,7 +11942,7 @@ function rawArgsAfter(subcommand) {
|
|
|
11329
11942
|
}
|
|
11330
11943
|
|
|
11331
11944
|
// src/commands/doctor.ts
|
|
11332
|
-
import { existsSync as
|
|
11945
|
+
import { existsSync as existsSync41, readFileSync as readFileSync31 } from "fs";
|
|
11333
11946
|
import { join as join44, resolve as resolve18 } from "path";
|
|
11334
11947
|
import chalk21 from "chalk";
|
|
11335
11948
|
import { Command as Command24 } from "commander";
|
|
@@ -11506,7 +12119,7 @@ async function runDoctor(options, deps = { git: new GitAdapter() }) {
|
|
|
11506
12119
|
}
|
|
11507
12120
|
function readLocalCoreVersion(cwd) {
|
|
11508
12121
|
const path = join44(cwd, INSTANCE_CORE_FILE);
|
|
11509
|
-
if (!
|
|
12122
|
+
if (!existsSync41(path)) return null;
|
|
11510
12123
|
try {
|
|
11511
12124
|
return parseCoreRecord(readFileSync31(path, "utf8"));
|
|
11512
12125
|
} catch {
|
|
@@ -11524,7 +12137,7 @@ function parseCoreRecord(contents) {
|
|
|
11524
12137
|
}
|
|
11525
12138
|
function readFossil(cwd) {
|
|
11526
12139
|
const path = join44(cwd, CORE_VERSION_FILE);
|
|
11527
|
-
if (!
|
|
12140
|
+
if (!existsSync41(path)) return null;
|
|
11528
12141
|
try {
|
|
11529
12142
|
const value = readFileSync31(path, "utf8").trim();
|
|
11530
12143
|
return value === "" ? null : value;
|
|
@@ -11975,13 +12588,13 @@ import { fileURLToPath as fileURLToPath6 } from "url";
|
|
|
11975
12588
|
import { Command as Command26 } from "commander";
|
|
11976
12589
|
|
|
11977
12590
|
// src/lib/packaged-scripts.ts
|
|
11978
|
-
import { existsSync as
|
|
12591
|
+
import { existsSync as existsSync42 } from "fs";
|
|
11979
12592
|
import { dirname as dirname10, join as join45 } from "path";
|
|
11980
12593
|
function findPackagedScript(startDir, relativePath) {
|
|
11981
12594
|
let dir = startDir;
|
|
11982
12595
|
for (; ; ) {
|
|
11983
12596
|
const candidate = join45(dir, relativePath);
|
|
11984
|
-
if (
|
|
12597
|
+
if (existsSync42(candidate)) return candidate;
|
|
11985
12598
|
const parent = dirname10(dir);
|
|
11986
12599
|
if (parent === dir) return null;
|
|
11987
12600
|
dir = parent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@biffo/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.267.0",
|
|
4
4
|
"description": "Biffo project scaffolding CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -50,7 +50,8 @@
|
|
|
50
50
|
"check:core-ownership": "tsx src/index.ts check ownership",
|
|
51
51
|
"check:plugin-terraform": "tsx src/index.ts check plugin-terraform",
|
|
52
52
|
"sync:core-tag": "tsx src/scripts/sync-core-tag.ts",
|
|
53
|
-
"report:publish-failure": "tsx src/scripts/report-publish-failure.ts"
|
|
53
|
+
"report:publish-failure": "tsx src/scripts/report-publish-failure.ts",
|
|
54
|
+
"refresh:openrouter-models": "tsx src/scripts/refresh-openrouter-model-snapshot.ts"
|
|
54
55
|
},
|
|
55
56
|
"dependencies": {
|
|
56
57
|
"@aws-sdk/client-cloudformation": "^3.726.1",
|