@open-code-review/cli 2.2.0 → 2.2.1
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/dashboard/client/assets/{_basePickBy-BBPb8BJA.js → _basePickBy-BAlGnwHG.js} +1 -1
- package/dist/dashboard/client/assets/{_baseUniq-CFHdos6T.js → _baseUniq-CoauyOeL.js} +1 -1
- package/dist/dashboard/client/assets/{arc-BKGGWA2F.js → arc-DtS0aHfP.js} +1 -1
- package/dist/dashboard/client/assets/{architectureDiagram-VXUJARFQ-B_ovNjX1.js → architectureDiagram-VXUJARFQ-CnWmtRTh.js} +1 -1
- package/dist/dashboard/client/assets/{blockDiagram-VD42YOAC-C2M-avVp.js → blockDiagram-VD42YOAC-DgPp4oGV.js} +1 -1
- package/dist/dashboard/client/assets/{c4Diagram-YG6GDRKO-BtOBpAzH.js → c4Diagram-YG6GDRKO--LV4qQaE.js} +1 -1
- package/dist/dashboard/client/assets/channel-BU2129fl.js +1 -0
- package/dist/dashboard/client/assets/{chunk-4BX2VUAB-Cz2EbHPl.js → chunk-4BX2VUAB-BRglpc7Z.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-55IACEB6-C8xpXw9G.js → chunk-55IACEB6-Bgx06_CV.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-B4BG7PRW-BSRfOovX.js → chunk-B4BG7PRW-D6HN3Yiy.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-DI55MBZ5-CEUbYQWn.js → chunk-DI55MBZ5-NH9EgN9T.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-FMBD7UC4-5xWP6GRj.js → chunk-FMBD7UC4-xriO6WNP.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-QN33PNHL-DfNCVcy8.js → chunk-QN33PNHL-CV1h6_Zl.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-QZHKN3VN--OdToKKu.js → chunk-QZHKN3VN-CV4VzxNq.js} +1 -1
- package/dist/dashboard/client/assets/{chunk-TZMSLE5B-B_0K0Qso.js → chunk-TZMSLE5B-isdklocW.js} +1 -1
- package/dist/dashboard/client/assets/classDiagram-2ON5EDUG-CVftFGiR.js +1 -0
- package/dist/dashboard/client/assets/classDiagram-v2-WZHVMYZB-CVftFGiR.js +1 -0
- package/dist/dashboard/client/assets/clone-DC6LEEC5.js +1 -0
- package/dist/dashboard/client/assets/{cose-bilkent-S5V4N54A-Cc_Dmnxz.js → cose-bilkent-S5V4N54A-CCzlFSJf.js} +1 -1
- package/dist/dashboard/client/assets/{dagre-6UL2VRFP-DaAfvUXU.js → dagre-6UL2VRFP-DVN3PkjZ.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-PSM6KHXK-7idwN0rC.js → diagram-PSM6KHXK-SzJVoSsb.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-QEK2KX5R-D9j9H13n.js → diagram-QEK2KX5R-CgGn7ts-.js} +1 -1
- package/dist/dashboard/client/assets/{diagram-S2PKOQOG-SMF5SB0K.js → diagram-S2PKOQOG-Bz1ukSx8.js} +1 -1
- package/dist/dashboard/client/assets/{erDiagram-Q2GNP2WA-EVJ4Qa2F.js → erDiagram-Q2GNP2WA-CpstUTMZ.js} +1 -1
- package/dist/dashboard/client/assets/{flowDiagram-NV44I4VS-tZ7SFE77.js → flowDiagram-NV44I4VS-aYVydGhp.js} +1 -1
- package/dist/dashboard/client/assets/{ganttDiagram-JELNMOA3-DFSqguY7.js → ganttDiagram-JELNMOA3-Cb2DUSRk.js} +1 -1
- package/dist/dashboard/client/assets/{gitGraphDiagram-V2S2FVAM-CqHdP3HE.js → gitGraphDiagram-V2S2FVAM-BUOnwA2w.js} +1 -1
- package/dist/dashboard/client/assets/{graph-C0XnkNkk.js → graph-4X5ddhLp.js} +1 -1
- package/dist/dashboard/client/assets/index-CKWqYAfu.js +581 -0
- package/dist/dashboard/client/assets/{infoDiagram-HS3SLOUP-DlXZo9U2.js → infoDiagram-HS3SLOUP-BlMqcrwm.js} +1 -1
- package/dist/dashboard/client/assets/{journeyDiagram-XKPGCS4Q-CgC8_7eN.js → journeyDiagram-XKPGCS4Q-DF2ew7ju.js} +1 -1
- package/dist/dashboard/client/assets/{kanban-definition-3W4ZIXB7-BMAw_jNp.js → kanban-definition-3W4ZIXB7-BKQMx0-n.js} +1 -1
- package/dist/dashboard/client/assets/{layout-XjM3Q-ka.js → layout-DNcn2g9w.js} +1 -1
- package/dist/dashboard/client/assets/{linear-CMUrrr1X.js → linear-Bqy9gvqb.js} +1 -1
- package/dist/dashboard/client/assets/{mermaid-renderer-D2jYNs7K.js → mermaid-renderer-dJ71wgld.js} +4 -4
- package/dist/dashboard/client/assets/{mindmap-definition-VGOIOE7T-CL4hv-vg.js → mindmap-definition-VGOIOE7T-BARc8sqJ.js} +1 -1
- package/dist/dashboard/client/assets/{pieDiagram-ADFJNKIX-DTqv-1h1.js → pieDiagram-ADFJNKIX-CULlNZTd.js} +1 -1
- package/dist/dashboard/client/assets/{quadrantDiagram-AYHSOK5B-BpFlSW9N.js → quadrantDiagram-AYHSOK5B-BJEZPVe9.js} +1 -1
- package/dist/dashboard/client/assets/{requirementDiagram-UZGBJVZJ-BqYqqXL4.js → requirementDiagram-UZGBJVZJ-BhMsmUIs.js} +1 -1
- package/dist/dashboard/client/assets/{sankeyDiagram-TZEHDZUN-kEI9kntR.js → sankeyDiagram-TZEHDZUN-BYbNgogG.js} +1 -1
- package/dist/dashboard/client/assets/{sequenceDiagram-WL72ISMW-Cnu_1j-N.js → sequenceDiagram-WL72ISMW-MoM_NwWk.js} +1 -1
- package/dist/dashboard/client/assets/{stateDiagram-FKZM4ZOC-BoC-rqoG.js → stateDiagram-FKZM4ZOC-ditrlbM3.js} +1 -1
- package/dist/dashboard/client/assets/stateDiagram-v2-4FDKWEC3-SqoG2LCn.js +1 -0
- package/dist/dashboard/client/assets/{timeline-definition-IT6M3QCI-CXMWuzDL.js → timeline-definition-IT6M3QCI-DOAJyjuz.js} +1 -1
- package/dist/dashboard/client/assets/{treemap-GDKQZRPO-o9ZFgpbJ.js → treemap-GDKQZRPO-BBJkjnJl.js} +1 -1
- package/dist/dashboard/client/assets/{xychartDiagram-PRI3JC2R-CfIuUpeA.js → xychartDiagram-PRI3JC2R-CPW4s5vm.js} +1 -1
- package/dist/dashboard/client/index.html +1 -1
- package/dist/dashboard/server.js +157 -153
- package/dist/index.js +144 -68
- package/dist/lib/models.js +125 -50
- package/package.json +2 -2
- package/dist/dashboard/client/assets/channel-rgw7C1e7.js +0 -1
- package/dist/dashboard/client/assets/classDiagram-2ON5EDUG-DTGi7d9X.js +0 -1
- package/dist/dashboard/client/assets/classDiagram-v2-WZHVMYZB-DTGi7d9X.js +0 -1
- package/dist/dashboard/client/assets/clone-Cz7hswqi.js +0 -1
- package/dist/dashboard/client/assets/index-C3NEq704.js +0 -571
- package/dist/dashboard/client/assets/stateDiagram-v2-4FDKWEC3-COR3QD3v.js +0 -1
package/dist/index.js
CHANGED
|
@@ -16034,6 +16034,12 @@ function execBinary(binary, args, opts) {
|
|
|
16034
16034
|
shell: isWindows
|
|
16035
16035
|
});
|
|
16036
16036
|
}
|
|
16037
|
+
async function execBinaryAsync(binary, args, opts) {
|
|
16038
|
+
return execFilePromise(binary, args, {
|
|
16039
|
+
...opts,
|
|
16040
|
+
shell: isWindows
|
|
16041
|
+
});
|
|
16042
|
+
}
|
|
16037
16043
|
function isProcessAlive(pid) {
|
|
16038
16044
|
try {
|
|
16039
16045
|
process.kill(pid, 0);
|
|
@@ -30086,7 +30092,7 @@ ${hint}
|
|
|
30086
30092
|
}
|
|
30087
30093
|
|
|
30088
30094
|
// src/lib/version.ts
|
|
30089
|
-
var CLI_VERSION = true ? "2.2.
|
|
30095
|
+
var CLI_VERSION = true ? "2.2.1" : createRequire(import.meta.url)("../../package.json").version;
|
|
30090
30096
|
|
|
30091
30097
|
// src/lib/deps.ts
|
|
30092
30098
|
init_src();
|
|
@@ -35520,23 +35526,62 @@ var sessionCommand = new Command("session").description("Manage agent-CLI sessio
|
|
|
35520
35526
|
|
|
35521
35527
|
// src/lib/models.ts
|
|
35522
35528
|
init_src();
|
|
35523
|
-
|
|
35524
|
-
|
|
35525
|
-
|
|
35526
|
-
|
|
35527
|
-
];
|
|
35528
|
-
|
|
35529
|
-
|
|
35530
|
-
|
|
35531
|
-
|
|
35532
|
-
|
|
35533
|
-
|
|
35534
|
-
|
|
35529
|
+
function parseOpenCodeModelList(stdout) {
|
|
35530
|
+
const models = [];
|
|
35531
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
35532
|
+
const line = rawLine.trim();
|
|
35533
|
+
if (!/^[^\s:]+\/\S+$/.test(line)) continue;
|
|
35534
|
+
const provider = line.slice(0, line.indexOf("/"));
|
|
35535
|
+
models.push({ id: line, provider });
|
|
35536
|
+
}
|
|
35537
|
+
return models.length > 0 ? models : null;
|
|
35538
|
+
}
|
|
35539
|
+
var VENDOR_MODEL_STRATEGIES = {
|
|
35540
|
+
claude: {
|
|
35541
|
+
displayName: "Claude Code",
|
|
35542
|
+
native: {
|
|
35543
|
+
// Verified against Claude Code 2.1.x: the CLI has no model-listing
|
|
35544
|
+
// subcommand (`claude models --json` → "unknown option"). Revisit if
|
|
35545
|
+
// a future release adds one.
|
|
35546
|
+
unavailableReason: "Claude Code does not provide a model-listing command; showing its documented model aliases instead"
|
|
35547
|
+
},
|
|
35548
|
+
// Vendor-documented aliases that always track the latest generation —
|
|
35549
|
+
// dated ids here would go stale by construction (the exact bug class of
|
|
35550
|
+
// issue #39). Pinned dated ids remain available via free-text entry.
|
|
35551
|
+
bundled: [
|
|
35552
|
+
{ id: "opus", displayName: "Claude Opus (latest)" },
|
|
35553
|
+
{ id: "sonnet", displayName: "Claude Sonnet (latest)" },
|
|
35554
|
+
{ id: "haiku", displayName: "Claude Haiku (latest)" }
|
|
35555
|
+
]
|
|
35556
|
+
},
|
|
35557
|
+
opencode: {
|
|
35558
|
+
displayName: "OpenCode",
|
|
35559
|
+
native: {
|
|
35560
|
+
// Plain `opencode models` — newline-delimited ids. (`--json` is not a
|
|
35561
|
+
// real flag, and `--verbose` interleaves JSON metadata blocks that
|
|
35562
|
+
// defeat line parsing.)
|
|
35563
|
+
args: ["models"],
|
|
35564
|
+
parse: parseOpenCodeModelList
|
|
35565
|
+
},
|
|
35566
|
+
bundled: [
|
|
35567
|
+
{ id: "anthropic/claude-opus-4-8", provider: "anthropic" },
|
|
35568
|
+
{ id: "anthropic/claude-sonnet-4-6", provider: "anthropic" },
|
|
35569
|
+
{ id: "anthropic/claude-haiku-4-5", provider: "anthropic" }
|
|
35570
|
+
]
|
|
35571
|
+
}
|
|
35572
|
+
};
|
|
35573
|
+
var SUPPORTED_VENDORS = Object.keys(
|
|
35574
|
+
VENDOR_MODEL_STRATEGIES
|
|
35575
|
+
);
|
|
35576
|
+
function isModelVendor(value) {
|
|
35577
|
+
return Object.hasOwn(VENDOR_MODEL_STRATEGIES, value);
|
|
35578
|
+
}
|
|
35579
|
+
async function detectActiveVendor() {
|
|
35580
|
+
for (const vendor of SUPPORTED_VENDORS) {
|
|
35535
35581
|
try {
|
|
35536
|
-
|
|
35582
|
+
await execBinaryAsync(vendor, ["--version"], {
|
|
35537
35583
|
encoding: "utf-8",
|
|
35538
|
-
timeout: 3e3
|
|
35539
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
35584
|
+
timeout: 3e3
|
|
35540
35585
|
});
|
|
35541
35586
|
return vendor;
|
|
35542
35587
|
} catch {
|
|
@@ -35544,68 +35589,97 @@ function detectActiveVendor() {
|
|
|
35544
35589
|
}
|
|
35545
35590
|
return null;
|
|
35546
35591
|
}
|
|
35547
|
-
function
|
|
35592
|
+
function describeProbeFailure(vendor, args, err) {
|
|
35593
|
+
const command = `${vendor} ${args.join(" ")}`;
|
|
35594
|
+
const e = err;
|
|
35595
|
+
if (e.code === "ENOENT") {
|
|
35596
|
+
return `\`${vendor}\` is not installed or not on PATH`;
|
|
35597
|
+
}
|
|
35598
|
+
if (e.killed) {
|
|
35599
|
+
return `\`${command}\` timed out or exceeded output limits`;
|
|
35600
|
+
}
|
|
35601
|
+
const stderr = typeof e.stderr === "string" ? e.stderr.trim() : "";
|
|
35602
|
+
const firstLine = (stderr.split(/\r?\n/)[0] ?? "").replace(/\u001b\[[0-9;]*[A-Za-z]/g, "").replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
|
|
35603
|
+
const detail = firstLine ? `: ${firstLine}` : "";
|
|
35604
|
+
const exit = typeof e.code === "number" ? ` with exit code ${e.code}` : "";
|
|
35605
|
+
return `\`${command}\` failed${exit}${detail}`;
|
|
35606
|
+
}
|
|
35607
|
+
async function tryNativeEnumeration(vendor, probe) {
|
|
35608
|
+
let stdout;
|
|
35548
35609
|
try {
|
|
35549
|
-
const
|
|
35610
|
+
const result = await execBinaryAsync(vendor, probe.args, {
|
|
35550
35611
|
encoding: "utf-8",
|
|
35551
|
-
timeout: 5e3
|
|
35552
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
35612
|
+
timeout: 5e3
|
|
35553
35613
|
});
|
|
35554
|
-
|
|
35555
|
-
|
|
35556
|
-
|
|
35557
|
-
for (const item of parsed) {
|
|
35558
|
-
if (typeof item === "string") {
|
|
35559
|
-
models.push({ id: item });
|
|
35560
|
-
} else if (typeof item === "object" && item !== null && "id" in item && typeof item.id === "string") {
|
|
35561
|
-
const obj = item;
|
|
35562
|
-
const desc = { id: obj.id };
|
|
35563
|
-
if (typeof obj.displayName === "string") desc.displayName = obj.displayName;
|
|
35564
|
-
if (typeof obj.provider === "string") desc.provider = obj.provider;
|
|
35565
|
-
if (Array.isArray(obj.tags)) {
|
|
35566
|
-
desc.tags = obj.tags.filter((t) => typeof t === "string");
|
|
35567
|
-
}
|
|
35568
|
-
models.push(desc);
|
|
35569
|
-
}
|
|
35570
|
-
}
|
|
35571
|
-
return models.length > 0 ? models : null;
|
|
35572
|
-
} catch {
|
|
35573
|
-
return null;
|
|
35614
|
+
stdout = result.stdout;
|
|
35615
|
+
} catch (err) {
|
|
35616
|
+
return { models: null, reason: describeProbeFailure(vendor, probe.args, err) };
|
|
35574
35617
|
}
|
|
35618
|
+
const models = probe.parse(stdout);
|
|
35619
|
+
if (!models) {
|
|
35620
|
+
return {
|
|
35621
|
+
models: null,
|
|
35622
|
+
reason: `\`${vendor} ${probe.args.join(" ")}\` output did not contain any model identifiers`
|
|
35623
|
+
};
|
|
35624
|
+
}
|
|
35625
|
+
return { models };
|
|
35575
35626
|
}
|
|
35576
|
-
|
|
35577
|
-
|
|
35578
|
-
|
|
35579
|
-
|
|
35580
|
-
|
|
35581
|
-
|
|
35582
|
-
|
|
35583
|
-
|
|
35627
|
+
var SUCCESS_TTL_MS = 6e4;
|
|
35628
|
+
var FAILURE_TTL_MS = 1e4;
|
|
35629
|
+
var cache = /* @__PURE__ */ new Map();
|
|
35630
|
+
async function listModelsForVendor(vendor) {
|
|
35631
|
+
const cached = cache.get(vendor);
|
|
35632
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
35633
|
+
return cached.result;
|
|
35634
|
+
}
|
|
35635
|
+
const strategy = VENDOR_MODEL_STRATEGIES[vendor];
|
|
35636
|
+
if (!strategy) {
|
|
35637
|
+
throw new Error(`Unknown vendor: ${vendor}`);
|
|
35584
35638
|
}
|
|
35585
|
-
|
|
35639
|
+
let result;
|
|
35640
|
+
if ("unavailableReason" in strategy.native) {
|
|
35641
|
+
result = {
|
|
35642
|
+
vendor,
|
|
35643
|
+
source: "bundled",
|
|
35644
|
+
models: strategy.bundled,
|
|
35645
|
+
nativeUnavailableReason: strategy.native.unavailableReason
|
|
35646
|
+
};
|
|
35647
|
+
} else {
|
|
35648
|
+
const native = await tryNativeEnumeration(vendor, strategy.native);
|
|
35649
|
+
result = native.models ? { vendor, source: "native", models: native.models } : {
|
|
35650
|
+
vendor,
|
|
35651
|
+
source: "bundled",
|
|
35652
|
+
models: strategy.bundled,
|
|
35653
|
+
nativeUnavailableReason: native.reason
|
|
35654
|
+
};
|
|
35655
|
+
}
|
|
35656
|
+
const ttl = result.source === "native" ? SUCCESS_TTL_MS : FAILURE_TTL_MS;
|
|
35657
|
+
cache.set(vendor, { result, expiresAt: Date.now() + ttl });
|
|
35658
|
+
return result;
|
|
35586
35659
|
}
|
|
35587
35660
|
|
|
35588
35661
|
// src/commands/models.ts
|
|
35589
|
-
var
|
|
35590
|
-
|
|
35591
|
-
"Override autodetection (claude | opencode)"
|
|
35592
|
-
).option("--json", "Emit JSON for programmatic consumption").action(async (options) => {
|
|
35662
|
+
var vendorList = SUPPORTED_VENDORS.join(" | ");
|
|
35663
|
+
var listSubcommand2 = new Command("list").description("List models the active AI CLI is willing to accept").option("--vendor <vendor>", `Override autodetection (${vendorList})`).option("--json", "Emit JSON for programmatic consumption").action(async (options) => {
|
|
35593
35664
|
let vendor;
|
|
35594
35665
|
if (options.vendor) {
|
|
35595
|
-
|
|
35666
|
+
const requested = options.vendor.toLowerCase();
|
|
35667
|
+
if (!isModelVendor(requested)) {
|
|
35596
35668
|
console.error(
|
|
35597
35669
|
source_default.red(
|
|
35598
|
-
`Invalid --vendor: "${options.vendor}". Must be
|
|
35670
|
+
`Invalid --vendor: "${options.vendor}". Must be one of: ${vendorList}.`
|
|
35599
35671
|
)
|
|
35600
35672
|
);
|
|
35601
35673
|
process.exit(1);
|
|
35602
35674
|
}
|
|
35603
|
-
vendor =
|
|
35675
|
+
vendor = requested;
|
|
35604
35676
|
} else {
|
|
35605
|
-
vendor = detectActiveVendor();
|
|
35677
|
+
vendor = await detectActiveVendor();
|
|
35606
35678
|
if (!vendor) {
|
|
35607
35679
|
if (options.json) {
|
|
35608
|
-
console.log(
|
|
35680
|
+
console.log(
|
|
35681
|
+
JSON.stringify({ vendor: null, source: null, models: [] }, null, 2)
|
|
35682
|
+
);
|
|
35609
35683
|
return;
|
|
35610
35684
|
}
|
|
35611
35685
|
console.error(
|
|
@@ -35616,16 +35690,18 @@ var listSubcommand2 = new Command("list").description("List models the active AI
|
|
|
35616
35690
|
process.exit(1);
|
|
35617
35691
|
}
|
|
35618
35692
|
}
|
|
35619
|
-
const
|
|
35693
|
+
const result = await listModelsForVendor(vendor);
|
|
35620
35694
|
if (options.json) {
|
|
35621
|
-
console.log(JSON.stringify(
|
|
35695
|
+
console.log(JSON.stringify(result, null, 2));
|
|
35622
35696
|
return;
|
|
35623
35697
|
}
|
|
35698
|
+
const { source, models, nativeUnavailableReason } = result;
|
|
35624
35699
|
console.log(source_default.bold(`Models for ${vendor} (${source})`));
|
|
35625
35700
|
if (source === "bundled") {
|
|
35701
|
+
const reason = nativeUnavailableReason ? ` \u2014 ${nativeUnavailableReason}` : "";
|
|
35626
35702
|
console.log(
|
|
35627
35703
|
source_default.dim(
|
|
35628
|
-
|
|
35704
|
+
` Note: bundled fallback list${reason}. Free-text input is always accepted.`
|
|
35629
35705
|
)
|
|
35630
35706
|
);
|
|
35631
35707
|
}
|
|
@@ -36844,10 +36920,10 @@ function readCache(cacheFile) {
|
|
|
36844
36920
|
return null;
|
|
36845
36921
|
}
|
|
36846
36922
|
}
|
|
36847
|
-
function writeCache(cacheFile,
|
|
36923
|
+
function writeCache(cacheFile, cache2) {
|
|
36848
36924
|
try {
|
|
36849
36925
|
mkdirSync8(join28(cacheFile, ".."), { recursive: true });
|
|
36850
|
-
writeFileSync10(cacheFile, JSON.stringify(
|
|
36926
|
+
writeFileSync10(cacheFile, JSON.stringify(cache2));
|
|
36851
36927
|
} catch {
|
|
36852
36928
|
}
|
|
36853
36929
|
}
|
|
@@ -36869,14 +36945,14 @@ async function checkForUpdate(currentVersion, options) {
|
|
|
36869
36945
|
}
|
|
36870
36946
|
const cacheFile = join28(options?.cacheDir ?? CACHE_DIR2, "update-check.json");
|
|
36871
36947
|
try {
|
|
36872
|
-
const
|
|
36873
|
-
if (
|
|
36874
|
-
if (!
|
|
36875
|
-
if (!isNewer(
|
|
36948
|
+
const cache2 = readCache(cacheFile);
|
|
36949
|
+
if (cache2 && Date.now() - cache2.lastCheck < CHECK_INTERVAL_MS) {
|
|
36950
|
+
if (!cache2.latestVersion) return null;
|
|
36951
|
+
if (!isNewer(cache2.latestVersion, currentVersion)) return null;
|
|
36876
36952
|
return {
|
|
36877
36953
|
updateAvailable: true,
|
|
36878
36954
|
currentVersion,
|
|
36879
|
-
latestVersion:
|
|
36955
|
+
latestVersion: cache2.latestVersion,
|
|
36880
36956
|
updateCommand: detectUpdateCommand()
|
|
36881
36957
|
};
|
|
36882
36958
|
}
|
package/dist/lib/models.js
CHANGED
|
@@ -7,31 +7,70 @@ import {
|
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
8
|
var execFilePromise = promisify(execFile);
|
|
9
9
|
var isWindows = process.platform === "win32";
|
|
10
|
-
function
|
|
11
|
-
return
|
|
10
|
+
async function execBinaryAsync(binary, args, opts) {
|
|
11
|
+
return execFilePromise(binary, args, {
|
|
12
12
|
...opts,
|
|
13
13
|
shell: isWindows
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// src/lib/models.ts
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
function parseOpenCodeModelList(stdout) {
|
|
19
|
+
const models = [];
|
|
20
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
21
|
+
const line = rawLine.trim();
|
|
22
|
+
if (!/^[^\s:]+\/\S+$/.test(line)) continue;
|
|
23
|
+
const provider = line.slice(0, line.indexOf("/"));
|
|
24
|
+
models.push({ id: line, provider });
|
|
25
|
+
}
|
|
26
|
+
return models.length > 0 ? models : null;
|
|
27
|
+
}
|
|
28
|
+
var VENDOR_MODEL_STRATEGIES = {
|
|
29
|
+
claude: {
|
|
30
|
+
displayName: "Claude Code",
|
|
31
|
+
native: {
|
|
32
|
+
// Verified against Claude Code 2.1.x: the CLI has no model-listing
|
|
33
|
+
// subcommand (`claude models --json` → "unknown option"). Revisit if
|
|
34
|
+
// a future release adds one.
|
|
35
|
+
unavailableReason: "Claude Code does not provide a model-listing command; showing its documented model aliases instead"
|
|
36
|
+
},
|
|
37
|
+
// Vendor-documented aliases that always track the latest generation —
|
|
38
|
+
// dated ids here would go stale by construction (the exact bug class of
|
|
39
|
+
// issue #39). Pinned dated ids remain available via free-text entry.
|
|
40
|
+
bundled: [
|
|
41
|
+
{ id: "opus", displayName: "Claude Opus (latest)" },
|
|
42
|
+
{ id: "sonnet", displayName: "Claude Sonnet (latest)" },
|
|
43
|
+
{ id: "haiku", displayName: "Claude Haiku (latest)" }
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
opencode: {
|
|
47
|
+
displayName: "OpenCode",
|
|
48
|
+
native: {
|
|
49
|
+
// Plain `opencode models` — newline-delimited ids. (`--json` is not a
|
|
50
|
+
// real flag, and `--verbose` interleaves JSON metadata blocks that
|
|
51
|
+
// defeat line parsing.)
|
|
52
|
+
args: ["models"],
|
|
53
|
+
parse: parseOpenCodeModelList
|
|
54
|
+
},
|
|
55
|
+
bundled: [
|
|
56
|
+
{ id: "anthropic/claude-opus-4-8", provider: "anthropic" },
|
|
57
|
+
{ id: "anthropic/claude-sonnet-4-6", provider: "anthropic" },
|
|
58
|
+
{ id: "anthropic/claude-haiku-4-5", provider: "anthropic" }
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var SUPPORTED_VENDORS = Object.keys(
|
|
63
|
+
VENDOR_MODEL_STRATEGIES
|
|
64
|
+
);
|
|
65
|
+
function isModelVendor(value) {
|
|
66
|
+
return Object.hasOwn(VENDOR_MODEL_STRATEGIES, value);
|
|
67
|
+
}
|
|
68
|
+
async function detectActiveVendor() {
|
|
69
|
+
for (const vendor of SUPPORTED_VENDORS) {
|
|
30
70
|
try {
|
|
31
|
-
|
|
71
|
+
await execBinaryAsync(vendor, ["--version"], {
|
|
32
72
|
encoding: "utf-8",
|
|
33
|
-
timeout: 3e3
|
|
34
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
73
|
+
timeout: 3e3
|
|
35
74
|
});
|
|
36
75
|
return vendor;
|
|
37
76
|
} catch {
|
|
@@ -39,47 +78,83 @@ function detectActiveVendor() {
|
|
|
39
78
|
}
|
|
40
79
|
return null;
|
|
41
80
|
}
|
|
42
|
-
function
|
|
81
|
+
function describeProbeFailure(vendor, args, err) {
|
|
82
|
+
const command = `${vendor} ${args.join(" ")}`;
|
|
83
|
+
const e = err;
|
|
84
|
+
if (e.code === "ENOENT") {
|
|
85
|
+
return `\`${vendor}\` is not installed or not on PATH`;
|
|
86
|
+
}
|
|
87
|
+
if (e.killed) {
|
|
88
|
+
return `\`${command}\` timed out or exceeded output limits`;
|
|
89
|
+
}
|
|
90
|
+
const stderr = typeof e.stderr === "string" ? e.stderr.trim() : "";
|
|
91
|
+
const firstLine = (stderr.split(/\r?\n/)[0] ?? "").replace(/\u001b\[[0-9;]*[A-Za-z]/g, "").replace(/[\u0000-\u001f\u007f]/g, "").slice(0, 200);
|
|
92
|
+
const detail = firstLine ? `: ${firstLine}` : "";
|
|
93
|
+
const exit = typeof e.code === "number" ? ` with exit code ${e.code}` : "";
|
|
94
|
+
return `\`${command}\` failed${exit}${detail}`;
|
|
95
|
+
}
|
|
96
|
+
async function tryNativeEnumeration(vendor, probe) {
|
|
97
|
+
let stdout;
|
|
43
98
|
try {
|
|
44
|
-
const
|
|
99
|
+
const result = await execBinaryAsync(vendor, probe.args, {
|
|
45
100
|
encoding: "utf-8",
|
|
46
|
-
timeout: 5e3
|
|
47
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
101
|
+
timeout: 5e3
|
|
48
102
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
for (const item of parsed) {
|
|
53
|
-
if (typeof item === "string") {
|
|
54
|
-
models.push({ id: item });
|
|
55
|
-
} else if (typeof item === "object" && item !== null && "id" in item && typeof item.id === "string") {
|
|
56
|
-
const obj = item;
|
|
57
|
-
const desc = { id: obj.id };
|
|
58
|
-
if (typeof obj.displayName === "string") desc.displayName = obj.displayName;
|
|
59
|
-
if (typeof obj.provider === "string") desc.provider = obj.provider;
|
|
60
|
-
if (Array.isArray(obj.tags)) {
|
|
61
|
-
desc.tags = obj.tags.filter((t) => typeof t === "string");
|
|
62
|
-
}
|
|
63
|
-
models.push(desc);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return models.length > 0 ? models : null;
|
|
67
|
-
} catch {
|
|
68
|
-
return null;
|
|
103
|
+
stdout = result.stdout;
|
|
104
|
+
} catch (err) {
|
|
105
|
+
return { models: null, reason: describeProbeFailure(vendor, probe.args, err) };
|
|
69
106
|
}
|
|
107
|
+
const models = probe.parse(stdout);
|
|
108
|
+
if (!models) {
|
|
109
|
+
return {
|
|
110
|
+
models: null,
|
|
111
|
+
reason: `\`${vendor} ${probe.args.join(" ")}\` output did not contain any model identifiers`
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return { models };
|
|
70
115
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
116
|
+
var SUCCESS_TTL_MS = 6e4;
|
|
117
|
+
var FAILURE_TTL_MS = 1e4;
|
|
118
|
+
var cache = /* @__PURE__ */ new Map();
|
|
119
|
+
function clearModelListCache() {
|
|
120
|
+
cache.clear();
|
|
74
121
|
}
|
|
75
|
-
function listModelsForVendor(vendor) {
|
|
76
|
-
const
|
|
77
|
-
if (
|
|
78
|
-
return
|
|
122
|
+
async function listModelsForVendor(vendor) {
|
|
123
|
+
const cached = cache.get(vendor);
|
|
124
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
125
|
+
return cached.result;
|
|
126
|
+
}
|
|
127
|
+
const strategy = VENDOR_MODEL_STRATEGIES[vendor];
|
|
128
|
+
if (!strategy) {
|
|
129
|
+
throw new Error(`Unknown vendor: ${vendor}`);
|
|
130
|
+
}
|
|
131
|
+
let result;
|
|
132
|
+
if ("unavailableReason" in strategy.native) {
|
|
133
|
+
result = {
|
|
134
|
+
vendor,
|
|
135
|
+
source: "bundled",
|
|
136
|
+
models: strategy.bundled,
|
|
137
|
+
nativeUnavailableReason: strategy.native.unavailableReason
|
|
138
|
+
};
|
|
139
|
+
} else {
|
|
140
|
+
const native = await tryNativeEnumeration(vendor, strategy.native);
|
|
141
|
+
result = native.models ? { vendor, source: "native", models: native.models } : {
|
|
142
|
+
vendor,
|
|
143
|
+
source: "bundled",
|
|
144
|
+
models: strategy.bundled,
|
|
145
|
+
nativeUnavailableReason: native.reason
|
|
146
|
+
};
|
|
79
147
|
}
|
|
80
|
-
|
|
148
|
+
const ttl = result.source === "native" ? SUCCESS_TTL_MS : FAILURE_TTL_MS;
|
|
149
|
+
cache.set(vendor, { result, expiresAt: Date.now() + ttl });
|
|
150
|
+
return result;
|
|
81
151
|
}
|
|
82
152
|
export {
|
|
153
|
+
SUPPORTED_VENDORS,
|
|
154
|
+
VENDOR_MODEL_STRATEGIES,
|
|
155
|
+
clearModelListCache,
|
|
83
156
|
detectActiveVendor,
|
|
84
|
-
|
|
157
|
+
isModelVendor,
|
|
158
|
+
listModelsForVendor,
|
|
159
|
+
parseOpenCodeModelList
|
|
85
160
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-code-review/cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "CLI for Open Code Review - Multi-environment setup and progress tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"ora": "^8.1.1",
|
|
81
81
|
"socket.io": "^4.8",
|
|
82
82
|
"yaml": "^2.8.3",
|
|
83
|
-
"@open-code-review/agents": "2.2.
|
|
83
|
+
"@open-code-review/agents": "2.2.1"
|
|
84
84
|
},
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{ap as o,aq as n}from"./mermaid-renderer-D2jYNs7K.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-B4BG7PRW-BSRfOovX.js";import{_ as i}from"./mermaid-renderer-D2jYNs7K.js";import"./chunk-FMBD7UC4-5xWP6GRj.js";import"./chunk-55IACEB6-C8xpXw9G.js";import"./chunk-QN33PNHL-DfNCVcy8.js";import"./index-C3NEq704.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as a,c as s,a as e,C as t}from"./chunk-B4BG7PRW-BSRfOovX.js";import{_ as i}from"./mermaid-renderer-D2jYNs7K.js";import"./chunk-FMBD7UC4-5xWP6GRj.js";import"./chunk-55IACEB6-C8xpXw9G.js";import"./chunk-QN33PNHL-DfNCVcy8.js";import"./index-C3NEq704.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as r}from"./_baseUniq-CFHdos6T.js";var e=4;function a(o){return r(o,e)}export{a as c};
|