@plune-ai/cli 0.4.0 → 0.6.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/cli.cjs +266 -7
- package/dist/index.cjs +377 -6
- package/dist/index.d.cts +118 -1
- package/dist/index.d.ts +118 -1
- package/dist/index.js +365 -5
- package/package.json +11 -3
package/dist/index.js
CHANGED
|
@@ -315,7 +315,7 @@ function normalizeProviderError(err, secret, envVar) {
|
|
|
315
315
|
}
|
|
316
316
|
|
|
317
317
|
// src/providers/retry.ts
|
|
318
|
-
var defaultSleep = (ms) => new Promise((
|
|
318
|
+
var defaultSleep = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
319
319
|
function retryAfterMs(err) {
|
|
320
320
|
if (typeof err !== "object" || err === null || !("headers" in err)) return void 0;
|
|
321
321
|
const raw = readHeader(err.headers, "retry-after");
|
|
@@ -595,9 +595,11 @@ var XenovaEmbedder = class {
|
|
|
595
595
|
return rows.map((row) => Float32Array.from(row));
|
|
596
596
|
}
|
|
597
597
|
load() {
|
|
598
|
-
this.extractor ??= import("@huggingface/transformers").
|
|
599
|
-
|
|
600
|
-
|
|
598
|
+
this.extractor ??= import("@huggingface/transformers").catch(() => {
|
|
599
|
+
throw new Error(
|
|
600
|
+
"The `semantic-similarity` and RAG assertions need local embeddings, which ship separately: install @huggingface/transformers to enable them. Every other assertion works without it."
|
|
601
|
+
);
|
|
602
|
+
}).then(({ pipeline }) => pipeline("feature-extraction", MODEL_ID));
|
|
601
603
|
return this.extractor;
|
|
602
604
|
}
|
|
603
605
|
};
|
|
@@ -1461,6 +1463,10 @@ async function handleRun(options, depsFactory) {
|
|
|
1461
1463
|
}
|
|
1462
1464
|
}
|
|
1463
1465
|
|
|
1466
|
+
// src/cli/commands/sync.ts
|
|
1467
|
+
import * as fs6 from "fs";
|
|
1468
|
+
import * as path5 from "path";
|
|
1469
|
+
|
|
1464
1470
|
// src/types/run-result-schema.ts
|
|
1465
1471
|
import { z as z2 } from "zod";
|
|
1466
1472
|
var RUN_RESULT_SCHEMA_VERSION = 1;
|
|
@@ -1519,12 +1525,366 @@ var runResultSchema = z2.object({
|
|
|
1519
1525
|
function parseRunResult(value) {
|
|
1520
1526
|
return runResultSchema.parse(value);
|
|
1521
1527
|
}
|
|
1528
|
+
|
|
1529
|
+
// src/cli/credentials.ts
|
|
1530
|
+
import { chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1531
|
+
import { homedir } from "os";
|
|
1532
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
1533
|
+
function credentialsFile() {
|
|
1534
|
+
const base = process.env["XDG_CONFIG_HOME"]?.trim() || join3(homedir(), ".config");
|
|
1535
|
+
return join3(base, "plune", "credentials.json");
|
|
1536
|
+
}
|
|
1537
|
+
function loadToken() {
|
|
1538
|
+
try {
|
|
1539
|
+
const parsed = JSON.parse(readFileSync3(credentialsFile(), "utf-8"));
|
|
1540
|
+
return typeof parsed.token === "string" && parsed.token.length > 0 ? parsed.token : null;
|
|
1541
|
+
} catch {
|
|
1542
|
+
return null;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
// src/cli/commands/sync.ts
|
|
1547
|
+
var DEFAULT_API_URL = "https://beta-api.plune.ai";
|
|
1548
|
+
var NotLoggedInError = class extends Error {
|
|
1549
|
+
constructor() {
|
|
1550
|
+
super('Not logged in. Run "plune login" first to save your API token.');
|
|
1551
|
+
this.name = "NotLoggedInError";
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
var TokenRejectedError = class extends Error {
|
|
1555
|
+
constructor() {
|
|
1556
|
+
super(
|
|
1557
|
+
'Your API token was rejected (revoked or invalid). Run "plune login" with a fresh token.'
|
|
1558
|
+
);
|
|
1559
|
+
this.name = "TokenRejectedError";
|
|
1560
|
+
}
|
|
1561
|
+
};
|
|
1562
|
+
var SyncFileError = class extends Error {
|
|
1563
|
+
constructor(message) {
|
|
1564
|
+
super(message);
|
|
1565
|
+
this.name = "SyncFileError";
|
|
1566
|
+
}
|
|
1567
|
+
};
|
|
1568
|
+
var SyncNetworkError = class extends Error {
|
|
1569
|
+
constructor(apiUrl) {
|
|
1570
|
+
super(
|
|
1571
|
+
`Could not reach the Plune API at ${apiUrl}. Check your connection (or PLUNE_API_URL) and try again.`
|
|
1572
|
+
);
|
|
1573
|
+
this.name = "SyncNetworkError";
|
|
1574
|
+
}
|
|
1575
|
+
};
|
|
1576
|
+
var SyncHttpError = class extends Error {
|
|
1577
|
+
constructor(status, detail) {
|
|
1578
|
+
super(`Sync failed \u2014 the server returned HTTP ${status}${detail ? ` (${detail})` : ""}.`);
|
|
1579
|
+
this.status = status;
|
|
1580
|
+
this.name = "SyncHttpError";
|
|
1581
|
+
}
|
|
1582
|
+
status;
|
|
1583
|
+
};
|
|
1584
|
+
function resolveApiUrl(explicit) {
|
|
1585
|
+
const raw = explicit ?? process.env["PLUNE_API_URL"] ?? DEFAULT_API_URL;
|
|
1586
|
+
return raw.replace(/\/+$/, "");
|
|
1587
|
+
}
|
|
1588
|
+
function readRun(cwd, file) {
|
|
1589
|
+
const target = file !== void 0 ? path5.resolve(cwd, file) : path5.join(cwd, ".plune", "last-run.json");
|
|
1590
|
+
let raw;
|
|
1591
|
+
try {
|
|
1592
|
+
raw = fs6.readFileSync(target, "utf8");
|
|
1593
|
+
} catch {
|
|
1594
|
+
throw new SyncFileError(
|
|
1595
|
+
file !== void 0 ? `Run file not found: ${target}` : 'No run to sync. Run "plune run" first (or pass --file <path>).'
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
let json;
|
|
1599
|
+
try {
|
|
1600
|
+
json = JSON.parse(raw);
|
|
1601
|
+
} catch {
|
|
1602
|
+
throw new SyncFileError(`Run file is not valid JSON: ${target}`);
|
|
1603
|
+
}
|
|
1604
|
+
try {
|
|
1605
|
+
return parseRunResult(json);
|
|
1606
|
+
} catch {
|
|
1607
|
+
throw new SyncFileError(`Run file does not match the RunResult schema: ${target}`);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
async function safeErrorDetail(res) {
|
|
1611
|
+
try {
|
|
1612
|
+
const body = await res.json();
|
|
1613
|
+
return typeof body.error === "string" ? body.error : "";
|
|
1614
|
+
} catch {
|
|
1615
|
+
return "";
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
async function handleSync(deps = {}) {
|
|
1619
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
1620
|
+
const apiUrl = resolveApiUrl(deps.apiUrl);
|
|
1621
|
+
const token = (deps.loadToken ?? loadToken)();
|
|
1622
|
+
if (token === null) throw new NotLoggedInError();
|
|
1623
|
+
const run = readRun(cwd, deps.file);
|
|
1624
|
+
const doFetch = deps.fetchImpl ?? fetch;
|
|
1625
|
+
const endpoint = `${apiUrl}/v1/runs`;
|
|
1626
|
+
let res;
|
|
1627
|
+
try {
|
|
1628
|
+
res = await doFetch(endpoint, {
|
|
1629
|
+
method: "POST",
|
|
1630
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
1631
|
+
body: JSON.stringify(run)
|
|
1632
|
+
});
|
|
1633
|
+
} catch {
|
|
1634
|
+
throw new SyncNetworkError(apiUrl);
|
|
1635
|
+
}
|
|
1636
|
+
if (!res.ok) {
|
|
1637
|
+
const detail = await safeErrorDetail(res);
|
|
1638
|
+
if (res.status === 401) throw new TokenRejectedError();
|
|
1639
|
+
throw new SyncHttpError(res.status, detail);
|
|
1640
|
+
}
|
|
1641
|
+
const body = await res.json().catch(() => ({}));
|
|
1642
|
+
const id = typeof body.id === "string" ? body.id : "";
|
|
1643
|
+
return { id, url: `${endpoint}/${id}` };
|
|
1644
|
+
}
|
|
1645
|
+
function reportSyncFailure(err, write) {
|
|
1646
|
+
if (err instanceof NotLoggedInError || err instanceof TokenRejectedError || err instanceof SyncFileError) {
|
|
1647
|
+
write(err.message + "\n");
|
|
1648
|
+
return 2;
|
|
1649
|
+
}
|
|
1650
|
+
if (err instanceof SyncNetworkError || err instanceof SyncHttpError) {
|
|
1651
|
+
write(err.message + "\n");
|
|
1652
|
+
return 1;
|
|
1653
|
+
}
|
|
1654
|
+
return null;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
// src/cli/commands/cairn-artifact.ts
|
|
1658
|
+
import * as fs7 from "fs/promises";
|
|
1659
|
+
import * as path6 from "path";
|
|
1660
|
+
var SUPPORTED_ARTIFACT_VERSION = 1;
|
|
1661
|
+
var INGEST_SCHEMA_VERSION = 1;
|
|
1662
|
+
var CairnRunNotFoundError = class extends Error {
|
|
1663
|
+
constructor(dir) {
|
|
1664
|
+
super(`No Cairn run found in ${dir} \u2014 expected a report.json written by "cairn design|explore|api".`);
|
|
1665
|
+
this.name = "CairnRunNotFoundError";
|
|
1666
|
+
}
|
|
1667
|
+
};
|
|
1668
|
+
var CairnRunVersionError = class extends Error {
|
|
1669
|
+
constructor(found) {
|
|
1670
|
+
super(
|
|
1671
|
+
found === void 0 ? "This run predates versioned Cairn artifacts. Re-run it with Cairn 0.7.0 or newer, which stamps the format so it can be read safely." : `Unsupported Cairn artifact version ${String(found)} (this CLI reads version ${SUPPORTED_ARTIFACT_VERSION}). Upgrade @plune-ai/cli.`
|
|
1672
|
+
);
|
|
1673
|
+
this.name = "CairnRunVersionError";
|
|
1674
|
+
}
|
|
1675
|
+
};
|
|
1676
|
+
var CairnRunPartialError = class extends Error {
|
|
1677
|
+
constructor(reason) {
|
|
1678
|
+
super(`That Cairn run did not finish, so its cases are incomplete: ${reason}`);
|
|
1679
|
+
this.name = "CairnRunPartialError";
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
var CairnEvidenceAmbiguousError = class extends Error {
|
|
1683
|
+
constructor(name) {
|
|
1684
|
+
super(
|
|
1685
|
+
`Cannot attach results safely: the operation "${name}" appears more than once in this run's evidence, and the evidence file carries no case identity to disambiguate it. Nothing was uploaded.`
|
|
1686
|
+
);
|
|
1687
|
+
this.name = "CairnEvidenceAmbiguousError";
|
|
1688
|
+
}
|
|
1689
|
+
};
|
|
1690
|
+
var asRecord = (v) => typeof v === "object" && v !== null ? v : {};
|
|
1691
|
+
var str = (v, fallback = "") => typeof v === "string" && v !== "" ? v : fallback;
|
|
1692
|
+
async function readJson(file) {
|
|
1693
|
+
try {
|
|
1694
|
+
return JSON.parse(await fs7.readFile(file, "utf8"));
|
|
1695
|
+
} catch {
|
|
1696
|
+
return void 0;
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
async function defaultReadEvidence(dir) {
|
|
1700
|
+
const raw = await readJson(path6.join(dir, "api-evidence.json"));
|
|
1701
|
+
if (!Array.isArray(raw)) return void 0;
|
|
1702
|
+
return raw.map((r) => {
|
|
1703
|
+
const rec = asRecord(r);
|
|
1704
|
+
return { name: str(rec["name"]), passed: rec["passed"] === true };
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
function casesFromDesign(report) {
|
|
1708
|
+
const list = Array.isArray(report["testCases"]) ? report["testCases"] : [];
|
|
1709
|
+
return list.map((raw) => {
|
|
1710
|
+
const c = asRecord(raw);
|
|
1711
|
+
const steps = (Array.isArray(c["steps"]) ? c["steps"] : []).map((s) => str(s)).filter((s) => s !== "");
|
|
1712
|
+
return {
|
|
1713
|
+
stableId: str(c["stableId"]),
|
|
1714
|
+
title: str(c["title"], "untitled case"),
|
|
1715
|
+
execution: c["execution"] === "manual" ? "manual" : "auto",
|
|
1716
|
+
steps: steps.length > 0 ? steps : ["(no steps recorded)"],
|
|
1717
|
+
expected: str(c["expected"], "(no expected result recorded)"),
|
|
1718
|
+
...typeof c["technique"] === "string" ? { technique: c["technique"] } : {},
|
|
1719
|
+
...typeof c["priority"] === "string" ? { priority: c["priority"] } : {}
|
|
1720
|
+
};
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
function casesFromApi(report, verdicts) {
|
|
1724
|
+
const list = Array.isArray(report["cases"]) ? report["cases"] : [];
|
|
1725
|
+
return list.map((raw) => {
|
|
1726
|
+
const c = asRecord(raw);
|
|
1727
|
+
const name = str(c["name"], "unnamed operation");
|
|
1728
|
+
const request = `${str(c["method"], "GET")} ${str(c["path"], "/")}`;
|
|
1729
|
+
const verdict = verdicts.get(name);
|
|
1730
|
+
return {
|
|
1731
|
+
stableId: str(c["stableId"]),
|
|
1732
|
+
title: name,
|
|
1733
|
+
execution: "auto",
|
|
1734
|
+
steps: [request],
|
|
1735
|
+
expected: `HTTP ${str(c["expectedStatus"], "default")}`,
|
|
1736
|
+
...verdict !== void 0 ? { verdict } : {},
|
|
1737
|
+
...typeof c["technique"] === "string" ? { technique: c["technique"] } : {}
|
|
1738
|
+
};
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
async function readCairnRun(dir, deps = {}) {
|
|
1742
|
+
const raw = await readJson(path6.join(dir, "report.json"));
|
|
1743
|
+
if (raw === void 0) throw new CairnRunNotFoundError(dir);
|
|
1744
|
+
const report = asRecord(raw);
|
|
1745
|
+
if (report["schemaVersion"] !== SUPPORTED_ARTIFACT_VERSION) {
|
|
1746
|
+
throw new CairnRunVersionError(report["schemaVersion"]);
|
|
1747
|
+
}
|
|
1748
|
+
if (report["partial"] === true) {
|
|
1749
|
+
throw new CairnRunPartialError(str(report["error"], "no reason recorded"));
|
|
1750
|
+
}
|
|
1751
|
+
const mode = report["mode"];
|
|
1752
|
+
if (mode !== "design" && mode !== "explore" && mode !== "api") {
|
|
1753
|
+
throw new CairnRunVersionError(`${SUPPORTED_ARTIFACT_VERSION} (unknown run mode ${String(mode)})`);
|
|
1754
|
+
}
|
|
1755
|
+
let cases;
|
|
1756
|
+
if (mode === "api") {
|
|
1757
|
+
const evidence = await (deps.readEvidence ?? defaultReadEvidence)(dir);
|
|
1758
|
+
const verdicts = /* @__PURE__ */ new Map();
|
|
1759
|
+
for (const e of evidence ?? []) {
|
|
1760
|
+
if (verdicts.has(e.name)) throw new CairnEvidenceAmbiguousError(e.name);
|
|
1761
|
+
verdicts.set(e.name, e.passed ? "passed" : "failed");
|
|
1762
|
+
}
|
|
1763
|
+
cases = casesFromApi(report, verdicts);
|
|
1764
|
+
} else {
|
|
1765
|
+
cases = casesFromDesign(report);
|
|
1766
|
+
}
|
|
1767
|
+
return {
|
|
1768
|
+
schemaVersion: INGEST_SCHEMA_VERSION,
|
|
1769
|
+
run: {
|
|
1770
|
+
runId: str(report["runId"], path6.basename(dir)),
|
|
1771
|
+
mode,
|
|
1772
|
+
target: str(report["url"], "unknown")
|
|
1773
|
+
},
|
|
1774
|
+
cases
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
// src/cli/commands/ingest.ts
|
|
1779
|
+
var DEFAULT_API_URL2 = "https://beta-api.plune.ai";
|
|
1780
|
+
var IngestNotLoggedInError = class extends Error {
|
|
1781
|
+
constructor() {
|
|
1782
|
+
super('Not logged in. Run "plune login" first to save your API token.');
|
|
1783
|
+
this.name = "IngestNotLoggedInError";
|
|
1784
|
+
}
|
|
1785
|
+
};
|
|
1786
|
+
var IngestTokenRejectedError = class extends Error {
|
|
1787
|
+
constructor() {
|
|
1788
|
+
super('Your API token was rejected (401). Run "plune login" again with a fresh token.');
|
|
1789
|
+
this.name = "IngestTokenRejectedError";
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
var IngestNetworkError = class extends Error {
|
|
1793
|
+
constructor(apiUrl) {
|
|
1794
|
+
super(`Could not reach the Plune API at ${apiUrl}. Check your connection, then try again.`);
|
|
1795
|
+
this.name = "IngestNetworkError";
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
var IngestHttpError = class extends Error {
|
|
1799
|
+
constructor(status, detail) {
|
|
1800
|
+
super(`Plune API returned ${status}${detail !== "" ? ` \u2014 ${detail}` : ""}.`);
|
|
1801
|
+
this.status = status;
|
|
1802
|
+
this.name = "IngestHttpError";
|
|
1803
|
+
}
|
|
1804
|
+
status;
|
|
1805
|
+
};
|
|
1806
|
+
function resolveApiUrl2(explicit) {
|
|
1807
|
+
const raw = explicit ?? process.env["PLUNE_API_URL"] ?? DEFAULT_API_URL2;
|
|
1808
|
+
return raw.replace(/\/+$/, "");
|
|
1809
|
+
}
|
|
1810
|
+
async function safeErrorDetail2(res) {
|
|
1811
|
+
try {
|
|
1812
|
+
const body = await res.json();
|
|
1813
|
+
return typeof body.error === "string" ? body.error : "";
|
|
1814
|
+
} catch {
|
|
1815
|
+
return "";
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
async function handleIngest(deps) {
|
|
1819
|
+
const apiUrl = resolveApiUrl2(deps.apiUrl);
|
|
1820
|
+
const token = (deps.loadToken ?? loadToken)();
|
|
1821
|
+
if (token === null) throw new IngestNotLoggedInError();
|
|
1822
|
+
const payload = await readCairnRun(deps.dir);
|
|
1823
|
+
const doFetch = deps.fetchImpl ?? fetch;
|
|
1824
|
+
const endpoint = `${apiUrl}/v1/ingest/cairn`;
|
|
1825
|
+
let res;
|
|
1826
|
+
try {
|
|
1827
|
+
res = await doFetch(endpoint, {
|
|
1828
|
+
method: "POST",
|
|
1829
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
1830
|
+
body: JSON.stringify(payload)
|
|
1831
|
+
});
|
|
1832
|
+
} catch {
|
|
1833
|
+
throw new IngestNetworkError(apiUrl);
|
|
1834
|
+
}
|
|
1835
|
+
if (!res.ok) {
|
|
1836
|
+
const detail = await safeErrorDetail2(res);
|
|
1837
|
+
if (res.status === 401) throw new IngestTokenRejectedError();
|
|
1838
|
+
throw new IngestHttpError(res.status, detail);
|
|
1839
|
+
}
|
|
1840
|
+
const body = await res.json().catch(() => ({}));
|
|
1841
|
+
return {
|
|
1842
|
+
runId: typeof body.runId === "string" ? body.runId : "",
|
|
1843
|
+
linked: typeof body.linked === "number" ? body.linked : 0,
|
|
1844
|
+
proposed: typeof body.proposed === "number" ? body.proposed : 0,
|
|
1845
|
+
skipped: typeof body.skipped === "number" ? body.skipped : 0
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
function reportIngestFailure(err, write) {
|
|
1849
|
+
if (err instanceof IngestNotLoggedInError || err instanceof IngestTokenRejectedError || err instanceof CairnRunNotFoundError || err instanceof CairnRunVersionError || err instanceof CairnRunPartialError || err instanceof CairnEvidenceAmbiguousError) {
|
|
1850
|
+
write(`${err.message}
|
|
1851
|
+
`);
|
|
1852
|
+
return 2;
|
|
1853
|
+
}
|
|
1854
|
+
if (err instanceof IngestNetworkError || err instanceof IngestHttpError) {
|
|
1855
|
+
write(`${err.message}
|
|
1856
|
+
`);
|
|
1857
|
+
return 1;
|
|
1858
|
+
}
|
|
1859
|
+
return null;
|
|
1860
|
+
}
|
|
1861
|
+
function formatIngestResult(r) {
|
|
1862
|
+
const lines = [
|
|
1863
|
+
`Ingested Cairn run \u2192 ${r.runId}`,
|
|
1864
|
+
` ${r.linked} result(s) attached to existing cases`,
|
|
1865
|
+
` ${r.proposed} case(s) proposed \u2014 review them in Plune to accept`,
|
|
1866
|
+
` ${r.skipped} skipped (already queued, already rejected, repeated, or never executed)`
|
|
1867
|
+
];
|
|
1868
|
+
return `${lines.join("\n")}
|
|
1869
|
+
`;
|
|
1870
|
+
}
|
|
1522
1871
|
export {
|
|
1872
|
+
NotLoggedInError,
|
|
1523
1873
|
RUN_RESULT_SCHEMA_VERSION,
|
|
1874
|
+
SyncFileError,
|
|
1875
|
+
SyncHttpError,
|
|
1876
|
+
SyncNetworkError,
|
|
1877
|
+
TokenRejectedError,
|
|
1524
1878
|
assertionConfigSchema,
|
|
1525
1879
|
assertionResultRecordSchema,
|
|
1526
1880
|
binaryVerdictSchema,
|
|
1881
|
+
formatIngestResult,
|
|
1882
|
+
handleIngest as ingest,
|
|
1527
1883
|
parseRunResult,
|
|
1884
|
+
readCairnRun,
|
|
1885
|
+
reportIngestFailure,
|
|
1886
|
+
reportSyncFailure,
|
|
1528
1887
|
handleRun as run,
|
|
1529
|
-
runResultSchema
|
|
1888
|
+
runResultSchema,
|
|
1889
|
+
handleSync as sync
|
|
1530
1890
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plune-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "AI-powered assertion testing for LLM apps — write assertions, run them against any provider, get a pass/fail report (local, CI, or diff).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -53,8 +53,7 @@
|
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@anthropic-ai/sdk": "^0.102.0",
|
|
55
55
|
"@clack/prompts": "^1.5.1",
|
|
56
|
-
"
|
|
57
|
-
"ajv": "^8.20.0",
|
|
56
|
+
"ajv": "^8.17.1",
|
|
58
57
|
"better-sqlite3": "^12.10.0",
|
|
59
58
|
"commander": "^12.0.0",
|
|
60
59
|
"dotenv": "^16.4.0",
|
|
@@ -63,6 +62,7 @@
|
|
|
63
62
|
"zod": "^3.23.0"
|
|
64
63
|
},
|
|
65
64
|
"devDependencies": {
|
|
65
|
+
"@huggingface/transformers": "4.2.0",
|
|
66
66
|
"@types/better-sqlite3": "^7.6.13",
|
|
67
67
|
"@types/node": "^25.9.1",
|
|
68
68
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -96,5 +96,13 @@
|
|
|
96
96
|
"protobufjs",
|
|
97
97
|
"sharp"
|
|
98
98
|
]
|
|
99
|
+
},
|
|
100
|
+
"peerDependencies": {
|
|
101
|
+
"@huggingface/transformers": "4.2.0"
|
|
102
|
+
},
|
|
103
|
+
"peerDependenciesMeta": {
|
|
104
|
+
"@huggingface/transformers": {
|
|
105
|
+
"optional": true
|
|
106
|
+
}
|
|
99
107
|
}
|
|
100
108
|
}
|