@plune-ai/cli 0.10.0 → 0.11.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/README.md +8 -0
- package/dist/cli.cjs +54 -41
- package/dist/index.cjs +6 -6
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -6
- package/dist/reporter-core.cjs +18 -7
- package/dist/reporter-core.js +18 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -158,6 +158,14 @@ job closes the run instead of the explicit `finish`.
|
|
|
158
158
|
`plune run exec` sets it for you — anything reporting inside it, this command included, joins
|
|
159
159
|
without closing.
|
|
160
160
|
|
|
161
|
+
### What the run is called
|
|
162
|
+
|
|
163
|
+
A run nobody named is called after the directory, the minute it started and where it ran —
|
|
164
|
+
`plune · 2026-09-15 15:26 · ci` — so a row in the list reads without being opened. The clock is the
|
|
165
|
+
reporting machine's own; `ci` comes from the `CI` variable every hosted runner sets. To call it
|
|
166
|
+
something else, set `PLUNE_RUN_TITLE`; `PLUNE_ENV` and `PLUNE_LABELS` mark where it ran and how, and
|
|
167
|
+
those stay marks rather than becoming part of the name.
|
|
168
|
+
|
|
161
169
|
## Optional: keep a history
|
|
162
170
|
|
|
163
171
|
Everything above works with no account, no network, and no token — that does not change. `run`,
|
package/dist/cli.cjs
CHANGED
|
@@ -597,7 +597,7 @@ function makeAnthropicProvider(config, env, pricing) {
|
|
|
597
597
|
() => client.messages.create({
|
|
598
598
|
model: req.model,
|
|
599
599
|
max_tokens: req.max_tokens,
|
|
600
|
-
temperature: req.temperature,
|
|
600
|
+
...req.temperature !== void 0 ? { temperature: req.temperature } : {},
|
|
601
601
|
messages: [{ role: "user", content: req.prompt_resolved }]
|
|
602
602
|
}),
|
|
603
603
|
{ max_retries: maxRetries }
|
|
@@ -657,7 +657,7 @@ function makeOpenAiCompatibleProvider(opts) {
|
|
|
657
657
|
const res = await withRetry(
|
|
658
658
|
() => client.chat.completions.create({
|
|
659
659
|
model: req.model,
|
|
660
|
-
temperature: req.temperature,
|
|
660
|
+
...req.temperature !== void 0 ? { temperature: req.temperature } : {},
|
|
661
661
|
max_tokens: req.max_tokens,
|
|
662
662
|
messages: [{ role: "user", content: req.prompt_resolved }],
|
|
663
663
|
// OpenRouter extension: ask it to include the call's actual cost in `usage` (ADR-PRC02).
|
|
@@ -1547,7 +1547,7 @@ function buildJudge(provider, cfg, onUsage) {
|
|
|
1547
1547
|
const res = await provider.complete({
|
|
1548
1548
|
provider: cfg.type,
|
|
1549
1549
|
model: cfg.model,
|
|
1550
|
-
temperature:
|
|
1550
|
+
...cfg.temperature !== void 0 ? { temperature: cfg.temperature } : {},
|
|
1551
1551
|
max_tokens: cfg.max_tokens ?? DEFAULT_MAX_TOKENS,
|
|
1552
1552
|
prompt_resolved: prompt5
|
|
1553
1553
|
});
|
|
@@ -1609,7 +1609,7 @@ function estimateUsage(prompt5, maxTokens) {
|
|
|
1609
1609
|
async function runRow(p) {
|
|
1610
1610
|
const t0 = p.now();
|
|
1611
1611
|
const prompt5 = resolvePrompt(p.template, p.row.vars);
|
|
1612
|
-
const temperature = p.providerConfig.temperature
|
|
1612
|
+
const temperature = p.providerConfig.temperature;
|
|
1613
1613
|
const maxTokens = p.providerConfig.max_tokens ?? DEFAULT_MAX_TOKENS2;
|
|
1614
1614
|
if (p.dryRun) {
|
|
1615
1615
|
const est = estimateUsage(prompt5, maxTokens);
|
|
@@ -1619,7 +1619,7 @@ async function runRow(p) {
|
|
|
1619
1619
|
const key = cacheKey({
|
|
1620
1620
|
provider: p.providerConfig.type,
|
|
1621
1621
|
model: p.providerConfig.model,
|
|
1622
|
-
temperature,
|
|
1622
|
+
temperature: temperature ?? 0,
|
|
1623
1623
|
max_tokens: maxTokens,
|
|
1624
1624
|
prompt_resolved: prompt5
|
|
1625
1625
|
});
|
|
@@ -1640,7 +1640,7 @@ async function runRow(p) {
|
|
|
1640
1640
|
const res = await p.provider.complete({
|
|
1641
1641
|
provider: p.providerConfig.type,
|
|
1642
1642
|
model: p.providerConfig.model,
|
|
1643
|
-
temperature,
|
|
1643
|
+
...temperature !== void 0 ? { temperature } : {},
|
|
1644
1644
|
max_tokens: maxTokens,
|
|
1645
1645
|
prompt_resolved: prompt5
|
|
1646
1646
|
});
|
|
@@ -2210,7 +2210,7 @@ function createClient(opts) {
|
|
|
2210
2210
|
const wait = opts.wait ?? sleep;
|
|
2211
2211
|
const base = opts.apiUrl.replace(/\/+$/, "");
|
|
2212
2212
|
const scrub = (text2) => opts.token === "" ? text2 : text2.split(opts.token).join("***");
|
|
2213
|
-
async function send(method,
|
|
2213
|
+
async function send(method, path13, body) {
|
|
2214
2214
|
let last = {
|
|
2215
2215
|
kind: "unavailable",
|
|
2216
2216
|
status: null,
|
|
@@ -2219,7 +2219,7 @@ function createClient(opts) {
|
|
|
2219
2219
|
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt += 1) {
|
|
2220
2220
|
let res;
|
|
2221
2221
|
try {
|
|
2222
|
-
res = await doFetch(`${base}${
|
|
2222
|
+
res = await doFetch(`${base}${path13}`, {
|
|
2223
2223
|
method,
|
|
2224
2224
|
headers: { "content-type": "application/json", authorization: `Bearer ${opts.token}` },
|
|
2225
2225
|
// A DELETE carries none. Sending `"undefined"` as a body is what a naive
|
|
@@ -2247,8 +2247,8 @@ function createClient(opts) {
|
|
|
2247
2247
|
return { ok: false, ...last };
|
|
2248
2248
|
}
|
|
2249
2249
|
return {
|
|
2250
|
-
post: (
|
|
2251
|
-
del: (
|
|
2250
|
+
post: (path13, body) => send("POST", path13, body),
|
|
2251
|
+
del: (path13) => send("DELETE", path13)
|
|
2252
2252
|
};
|
|
2253
2253
|
}
|
|
2254
2254
|
var RETRY_DELAYS_MS, sleep;
|
|
@@ -2313,18 +2313,25 @@ function readEnv(env = process.env) {
|
|
|
2313
2313
|
ignored: UNSUPPORTED_VARS.filter((name) => value(env, name) !== void 0)
|
|
2314
2314
|
};
|
|
2315
2315
|
}
|
|
2316
|
-
|
|
2316
|
+
function defaultRunTitle(env = process.env, now = /* @__PURE__ */ new Date(), cwd = process.cwd()) {
|
|
2317
|
+
const two = (n) => String(n).padStart(2, "0");
|
|
2318
|
+
const stamp = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())} ${two(now.getHours())}:${two(now.getMinutes())}`;
|
|
2319
|
+
const where = flag(env, "CI") || flag(env, "GITHUB_ACTIONS") ? "ci" : "local";
|
|
2320
|
+
return `${path6.basename(cwd)} \xB7 ${stamp} \xB7 ${where}`;
|
|
2321
|
+
}
|
|
2322
|
+
var path6, UNSUPPORTED_VARS;
|
|
2317
2323
|
var init_env2 = __esm({
|
|
2318
2324
|
"src/reporter-core/env.ts"() {
|
|
2319
2325
|
"use strict";
|
|
2320
2326
|
init_cjs_shims();
|
|
2327
|
+
path6 = __toESM(require("path"), 1);
|
|
2321
2328
|
UNSUPPORTED_VARS = ["PLUNE_GROUP"];
|
|
2322
2329
|
}
|
|
2323
2330
|
});
|
|
2324
2331
|
|
|
2325
2332
|
// src/reporter-core/fallback.ts
|
|
2326
2333
|
function appendBatch(file, batch) {
|
|
2327
|
-
fs6.mkdirSync(
|
|
2334
|
+
fs6.mkdirSync(path7.dirname(file), { recursive: true });
|
|
2328
2335
|
const line = {
|
|
2329
2336
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2330
2337
|
runId: batch.runId,
|
|
@@ -2334,14 +2341,14 @@ function appendBatch(file, batch) {
|
|
|
2334
2341
|
fs6.appendFileSync(file, `${JSON.stringify(line)}
|
|
2335
2342
|
`, "utf8");
|
|
2336
2343
|
}
|
|
2337
|
-
var fs6,
|
|
2344
|
+
var fs6, path7, DEFAULT_FALLBACK_PATH;
|
|
2338
2345
|
var init_fallback = __esm({
|
|
2339
2346
|
"src/reporter-core/fallback.ts"() {
|
|
2340
2347
|
"use strict";
|
|
2341
2348
|
init_cjs_shims();
|
|
2342
2349
|
fs6 = __toESM(require("fs"), 1);
|
|
2343
|
-
|
|
2344
|
-
DEFAULT_FALLBACK_PATH =
|
|
2350
|
+
path7 = __toESM(require("path"), 1);
|
|
2351
|
+
DEFAULT_FALLBACK_PATH = path7.join(".plune", "pending-results.jsonl");
|
|
2345
2352
|
}
|
|
2346
2353
|
});
|
|
2347
2354
|
|
|
@@ -2468,6 +2475,10 @@ async function startRun(passed, declared) {
|
|
|
2468
2475
|
...externalKey !== null ? { externalKey } : {},
|
|
2469
2476
|
...cfg.meta !== void 0 ? { meta: cfg.meta } : {},
|
|
2470
2477
|
...configuration !== void 0 ? { configuration } : {},
|
|
2478
|
+
// Named even when nobody named it — the list has to read without opening a row. Only what
|
|
2479
|
+
// the caller DESCRIBED goes to `warnIfDropped` below: a title this side invented is not one
|
|
2480
|
+
// a person will miss, and a deployment older than the field must not be nagged on every run.
|
|
2481
|
+
title: defaultRunTitle(),
|
|
2471
2482
|
...described
|
|
2472
2483
|
});
|
|
2473
2484
|
if (start.ok) {
|
|
@@ -2689,7 +2700,9 @@ async function handleRunStart(options = {}) {
|
|
|
2689
2700
|
const out = await client.post("/v1/runs", {
|
|
2690
2701
|
schemaVersion: 2,
|
|
2691
2702
|
kind: options.kind ?? "automated",
|
|
2692
|
-
externalKey
|
|
2703
|
+
externalKey,
|
|
2704
|
+
// The same name the reporter would give it; `PLUNE_RUN_TITLE` replaces it, as everywhere.
|
|
2705
|
+
title: env.config.title ?? defaultRunTitle()
|
|
2693
2706
|
});
|
|
2694
2707
|
if (!out.ok) throw new RunCommandError(`Could not start the run \u2014 ${out.detail || out.kind}.`);
|
|
2695
2708
|
const result = {
|
|
@@ -3351,7 +3364,7 @@ function isRunResult(v) {
|
|
|
3351
3364
|
}
|
|
3352
3365
|
function handleReport(opts = {}) {
|
|
3353
3366
|
const cwd = opts.cwd ?? process.cwd();
|
|
3354
|
-
const file =
|
|
3367
|
+
const file = path8.join(cwd, ".plune", "last-run.json");
|
|
3355
3368
|
let raw;
|
|
3356
3369
|
try {
|
|
3357
3370
|
raw = fs9.readFileSync(file, "utf8");
|
|
@@ -3369,13 +3382,13 @@ function handleReport(opts = {}) {
|
|
|
3369
3382
|
}
|
|
3370
3383
|
return parsed;
|
|
3371
3384
|
}
|
|
3372
|
-
var fs9,
|
|
3385
|
+
var fs9, path8, ReportNotFoundError;
|
|
3373
3386
|
var init_report = __esm({
|
|
3374
3387
|
"src/cli/commands/report.ts"() {
|
|
3375
3388
|
"use strict";
|
|
3376
3389
|
init_cjs_shims();
|
|
3377
3390
|
fs9 = __toESM(require("fs"), 1);
|
|
3378
|
-
|
|
3391
|
+
path8 = __toESM(require("path"), 1);
|
|
3379
3392
|
ReportNotFoundError = class extends Error {
|
|
3380
3393
|
code = "NO_SAVED_RUN";
|
|
3381
3394
|
constructor(message) {
|
|
@@ -3599,7 +3612,7 @@ async function runInitWizard(cwd) {
|
|
|
3599
3612
|
process.exit(1);
|
|
3600
3613
|
return;
|
|
3601
3614
|
}
|
|
3602
|
-
const outputPath =
|
|
3615
|
+
const outputPath = path9.join(cwd, "plune.yaml");
|
|
3603
3616
|
if (fs11.existsSync(outputPath)) {
|
|
3604
3617
|
const overwrite = await clack.confirm({
|
|
3605
3618
|
message: "plune.yaml already exists. Overwrite?"
|
|
@@ -3643,14 +3656,14 @@ async function runInitWizard(cwd) {
|
|
|
3643
3656
|
spin.stop("plune.yaml created!");
|
|
3644
3657
|
clack.outro("plune.yaml is ready.");
|
|
3645
3658
|
}
|
|
3646
|
-
var clack, fs11,
|
|
3659
|
+
var clack, fs11, path9, import_yaml2;
|
|
3647
3660
|
var init_wizard = __esm({
|
|
3648
3661
|
"src/config/init/wizard.ts"() {
|
|
3649
3662
|
"use strict";
|
|
3650
3663
|
init_cjs_shims();
|
|
3651
3664
|
clack = __toESM(require("@clack/prompts"), 1);
|
|
3652
3665
|
fs11 = __toESM(require("fs"), 1);
|
|
3653
|
-
|
|
3666
|
+
path9 = __toESM(require("path"), 1);
|
|
3654
3667
|
import_yaml2 = require("yaml");
|
|
3655
3668
|
init_errors();
|
|
3656
3669
|
}
|
|
@@ -3658,21 +3671,21 @@ var init_wizard = __esm({
|
|
|
3658
3671
|
|
|
3659
3672
|
// src/cli/templates/index.ts
|
|
3660
3673
|
function writeTemplateFile(cwd, rel, content, force) {
|
|
3661
|
-
const target =
|
|
3674
|
+
const target = path10.join(cwd, rel);
|
|
3662
3675
|
if (!force && fs12.existsSync(target)) {
|
|
3663
3676
|
return "skipped";
|
|
3664
3677
|
}
|
|
3665
|
-
fs12.mkdirSync(
|
|
3678
|
+
fs12.mkdirSync(path10.dirname(target), { recursive: true });
|
|
3666
3679
|
fs12.writeFileSync(target, content, "utf8");
|
|
3667
3680
|
return "written";
|
|
3668
3681
|
}
|
|
3669
|
-
var fs12,
|
|
3682
|
+
var fs12, path10, ENV_EXAMPLE_TPL, EXAMPLE_JSONL_TPL, PLUNE_YAML_TPL;
|
|
3670
3683
|
var init_templates = __esm({
|
|
3671
3684
|
"src/cli/templates/index.ts"() {
|
|
3672
3685
|
"use strict";
|
|
3673
3686
|
init_cjs_shims();
|
|
3674
3687
|
fs12 = __toESM(require("fs"), 1);
|
|
3675
|
-
|
|
3688
|
+
path10 = __toESM(require("path"), 1);
|
|
3676
3689
|
ENV_EXAMPLE_TPL = `# Copy this file to .env and replace the placeholders with your real keys.
|
|
3677
3690
|
# .env is gitignored; .env.example is safe to commit.
|
|
3678
3691
|
# Plune reads whichever key matches your configured provider.
|
|
@@ -3928,7 +3941,7 @@ __export(sync_exports, {
|
|
|
3928
3941
|
reportSyncFailure: () => reportSyncFailure
|
|
3929
3942
|
});
|
|
3930
3943
|
function readRun(cwd, file) {
|
|
3931
|
-
const target = file !== void 0 ?
|
|
3944
|
+
const target = file !== void 0 ? path11.resolve(cwd, file) : path11.join(cwd, ".plune", "last-run.json");
|
|
3932
3945
|
let raw;
|
|
3933
3946
|
try {
|
|
3934
3947
|
raw = fs13.readFileSync(target, "utf8");
|
|
@@ -3995,13 +4008,13 @@ function reportSyncFailure(err, write) {
|
|
|
3995
4008
|
}
|
|
3996
4009
|
return null;
|
|
3997
4010
|
}
|
|
3998
|
-
var fs13,
|
|
4011
|
+
var fs13, path11, NotLoggedInError, TokenRejectedError2, SyncFileError, SyncNetworkError, SyncHttpError;
|
|
3999
4012
|
var init_sync = __esm({
|
|
4000
4013
|
"src/cli/commands/sync.ts"() {
|
|
4001
4014
|
"use strict";
|
|
4002
4015
|
init_cjs_shims();
|
|
4003
4016
|
fs13 = __toESM(require("fs"), 1);
|
|
4004
|
-
|
|
4017
|
+
path11 = __toESM(require("path"), 1);
|
|
4005
4018
|
init_run_result_schema();
|
|
4006
4019
|
init_api_url();
|
|
4007
4020
|
init_credentials();
|
|
@@ -4051,9 +4064,9 @@ async function findLatestCairnRun(runsDir = "runs") {
|
|
|
4051
4064
|
let newest;
|
|
4052
4065
|
for (const entry of entries) {
|
|
4053
4066
|
if (!entry.isDirectory()) continue;
|
|
4054
|
-
const dir =
|
|
4067
|
+
const dir = path12.join(runsDir, entry.name);
|
|
4055
4068
|
try {
|
|
4056
|
-
const report = await fs14.lstat(
|
|
4069
|
+
const report = await fs14.lstat(path12.join(dir, "report.json"));
|
|
4057
4070
|
if (!report.isFile()) continue;
|
|
4058
4071
|
if (newest === void 0 || report.mtimeMs > newest.at) {
|
|
4059
4072
|
newest = { dir, at: report.mtimeMs };
|
|
@@ -4072,7 +4085,7 @@ async function readJson(file) {
|
|
|
4072
4085
|
}
|
|
4073
4086
|
}
|
|
4074
4087
|
async function defaultReadEvidence(dir) {
|
|
4075
|
-
const raw = await readJson(
|
|
4088
|
+
const raw = await readJson(path12.join(dir, "api-evidence.json"));
|
|
4076
4089
|
if (!Array.isArray(raw)) return void 0;
|
|
4077
4090
|
return raw.map((r) => {
|
|
4078
4091
|
const rec = asRecord(r);
|
|
@@ -4114,7 +4127,7 @@ function casesFromApi(report, verdicts) {
|
|
|
4114
4127
|
});
|
|
4115
4128
|
}
|
|
4116
4129
|
async function readCairnRun(dir, deps = {}) {
|
|
4117
|
-
const raw = await readJson(
|
|
4130
|
+
const raw = await readJson(path12.join(dir, "report.json"));
|
|
4118
4131
|
if (raw === void 0) throw new CairnRunNotFoundError(dir);
|
|
4119
4132
|
const report = asRecord(raw);
|
|
4120
4133
|
if (report["schemaVersion"] !== SUPPORTED_ARTIFACT_VERSION) {
|
|
@@ -4144,20 +4157,20 @@ async function readCairnRun(dir, deps = {}) {
|
|
|
4144
4157
|
return {
|
|
4145
4158
|
schemaVersion: INGEST_SCHEMA_VERSION,
|
|
4146
4159
|
run: {
|
|
4147
|
-
runId: str(report["runId"],
|
|
4160
|
+
runId: str(report["runId"], path12.basename(dir)),
|
|
4148
4161
|
mode,
|
|
4149
4162
|
target: str(report["url"], "unknown")
|
|
4150
4163
|
},
|
|
4151
4164
|
cases
|
|
4152
4165
|
};
|
|
4153
4166
|
}
|
|
4154
|
-
var fs14,
|
|
4167
|
+
var fs14, path12, SUPPORTED_ARTIFACT_VERSION, INGEST_SCHEMA_VERSION, NoCairnRunsError, CairnRunNotFoundError, CairnRunVersionError, CairnRunPartialError, CairnEvidenceAmbiguousError, asRecord, str;
|
|
4155
4168
|
var init_cairn_artifact = __esm({
|
|
4156
4169
|
"src/cli/commands/cairn-artifact.ts"() {
|
|
4157
4170
|
"use strict";
|
|
4158
4171
|
init_cjs_shims();
|
|
4159
4172
|
fs14 = __toESM(require("fs/promises"), 1);
|
|
4160
|
-
|
|
4173
|
+
path12 = __toESM(require("path"), 1);
|
|
4161
4174
|
SUPPORTED_ARTIFACT_VERSION = 1;
|
|
4162
4175
|
INGEST_SCHEMA_VERSION = 1;
|
|
4163
4176
|
NoCairnRunsError = class extends Error {
|
|
@@ -4613,10 +4626,10 @@ function createProgram() {
|
|
|
4613
4626
|
const { handleLogin: handleLogin2, reportLoginFailure: reportLoginFailure2 } = await Promise.resolve().then(() => (init_login(), login_exports));
|
|
4614
4627
|
try {
|
|
4615
4628
|
const token = options.token ?? await readTokenFromStdin();
|
|
4616
|
-
const { path:
|
|
4629
|
+
const { path: path13, verified } = await handleLogin2({ token, skipVerify: options.skipVerify });
|
|
4617
4630
|
process.stdout.write(
|
|
4618
|
-
verified ? `Logged in. Token checked against the API and saved to ${
|
|
4619
|
-
` : `Token saved to ${
|
|
4631
|
+
verified ? `Logged in. Token checked against the API and saved to ${path13}
|
|
4632
|
+
` : `Token saved to ${path13} WITHOUT being checked (--skip-verify).
|
|
4620
4633
|
`
|
|
4621
4634
|
);
|
|
4622
4635
|
} catch (err) {
|
|
@@ -4633,9 +4646,9 @@ function createProgram() {
|
|
|
4633
4646
|
const verbose = command.optsWithGlobals().verbose === true;
|
|
4634
4647
|
const { handleLogout: handleLogout2 } = await Promise.resolve().then(() => (init_logout(), logout_exports));
|
|
4635
4648
|
try {
|
|
4636
|
-
const { removed, path:
|
|
4649
|
+
const { removed, path: path13 } = handleLogout2();
|
|
4637
4650
|
process.stdout.write(
|
|
4638
|
-
removed ? `Logged out. Removed ${
|
|
4651
|
+
removed ? `Logged out. Removed ${path13}
|
|
4639
4652
|
` : "Not logged in \u2014 nothing to remove.\n"
|
|
4640
4653
|
);
|
|
4641
4654
|
} catch (err) {
|
package/dist/index.cjs
CHANGED
|
@@ -480,7 +480,7 @@ function makeAnthropicProvider(config, env, pricing) {
|
|
|
480
480
|
() => client.messages.create({
|
|
481
481
|
model: req.model,
|
|
482
482
|
max_tokens: req.max_tokens,
|
|
483
|
-
temperature: req.temperature,
|
|
483
|
+
...req.temperature !== void 0 ? { temperature: req.temperature } : {},
|
|
484
484
|
messages: [{ role: "user", content: req.prompt_resolved }]
|
|
485
485
|
}),
|
|
486
486
|
{ max_retries: maxRetries }
|
|
@@ -529,7 +529,7 @@ function makeOpenAiCompatibleProvider(opts) {
|
|
|
529
529
|
const res = await withRetry(
|
|
530
530
|
() => client.chat.completions.create({
|
|
531
531
|
model: req.model,
|
|
532
|
-
temperature: req.temperature,
|
|
532
|
+
...req.temperature !== void 0 ? { temperature: req.temperature } : {},
|
|
533
533
|
max_tokens: req.max_tokens,
|
|
534
534
|
messages: [{ role: "user", content: req.prompt_resolved }],
|
|
535
535
|
// OpenRouter extension: ask it to include the call's actual cost in `usage` (ADR-PRC02).
|
|
@@ -1216,7 +1216,7 @@ function buildJudge(provider, cfg, onUsage) {
|
|
|
1216
1216
|
const res = await provider.complete({
|
|
1217
1217
|
provider: cfg.type,
|
|
1218
1218
|
model: cfg.model,
|
|
1219
|
-
temperature:
|
|
1219
|
+
...cfg.temperature !== void 0 ? { temperature: cfg.temperature } : {},
|
|
1220
1220
|
max_tokens: cfg.max_tokens ?? DEFAULT_MAX_TOKENS,
|
|
1221
1221
|
prompt_resolved: prompt5
|
|
1222
1222
|
});
|
|
@@ -1273,7 +1273,7 @@ function estimateUsage(prompt5, maxTokens) {
|
|
|
1273
1273
|
async function runRow(p) {
|
|
1274
1274
|
const t0 = p.now();
|
|
1275
1275
|
const prompt5 = resolvePrompt(p.template, p.row.vars);
|
|
1276
|
-
const temperature = p.providerConfig.temperature
|
|
1276
|
+
const temperature = p.providerConfig.temperature;
|
|
1277
1277
|
const maxTokens = p.providerConfig.max_tokens ?? DEFAULT_MAX_TOKENS2;
|
|
1278
1278
|
if (p.dryRun) {
|
|
1279
1279
|
const est = estimateUsage(prompt5, maxTokens);
|
|
@@ -1283,7 +1283,7 @@ async function runRow(p) {
|
|
|
1283
1283
|
const key = cacheKey({
|
|
1284
1284
|
provider: p.providerConfig.type,
|
|
1285
1285
|
model: p.providerConfig.model,
|
|
1286
|
-
temperature,
|
|
1286
|
+
temperature: temperature ?? 0,
|
|
1287
1287
|
max_tokens: maxTokens,
|
|
1288
1288
|
prompt_resolved: prompt5
|
|
1289
1289
|
});
|
|
@@ -1304,7 +1304,7 @@ async function runRow(p) {
|
|
|
1304
1304
|
const res = await p.provider.complete({
|
|
1305
1305
|
provider: p.providerConfig.type,
|
|
1306
1306
|
model: p.providerConfig.model,
|
|
1307
|
-
temperature,
|
|
1307
|
+
...temperature !== void 0 ? { temperature } : {},
|
|
1308
1308
|
max_tokens: maxTokens,
|
|
1309
1309
|
prompt_resolved: prompt5
|
|
1310
1310
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -146,7 +146,12 @@ interface Config {
|
|
|
146
146
|
interface CompletionRequest {
|
|
147
147
|
provider: string;
|
|
148
148
|
model: string;
|
|
149
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Only when the config asked for one. Models released after Claude Opus 4.6 do not take a
|
|
151
|
+
* temperature at all — any value but 1.0 is a 400 — so a default here would be a default that
|
|
152
|
+
* breaks every eval on a current model. Absent means "the model's own".
|
|
153
|
+
*/
|
|
154
|
+
temperature?: number;
|
|
150
155
|
max_tokens: number;
|
|
151
156
|
prompt_resolved: string;
|
|
152
157
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -146,7 +146,12 @@ interface Config {
|
|
|
146
146
|
interface CompletionRequest {
|
|
147
147
|
provider: string;
|
|
148
148
|
model: string;
|
|
149
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Only when the config asked for one. Models released after Claude Opus 4.6 do not take a
|
|
151
|
+
* temperature at all — any value but 1.0 is a 400 — so a default here would be a default that
|
|
152
|
+
* breaks every eval on a current model. Absent means "the model's own".
|
|
153
|
+
*/
|
|
154
|
+
temperature?: number;
|
|
150
155
|
max_tokens: number;
|
|
151
156
|
prompt_resolved: string;
|
|
152
157
|
}
|
package/dist/index.js
CHANGED
|
@@ -427,7 +427,7 @@ function makeAnthropicProvider(config, env, pricing) {
|
|
|
427
427
|
() => client.messages.create({
|
|
428
428
|
model: req.model,
|
|
429
429
|
max_tokens: req.max_tokens,
|
|
430
|
-
temperature: req.temperature,
|
|
430
|
+
...req.temperature !== void 0 ? { temperature: req.temperature } : {},
|
|
431
431
|
messages: [{ role: "user", content: req.prompt_resolved }]
|
|
432
432
|
}),
|
|
433
433
|
{ max_retries: maxRetries }
|
|
@@ -476,7 +476,7 @@ function makeOpenAiCompatibleProvider(opts) {
|
|
|
476
476
|
const res = await withRetry(
|
|
477
477
|
() => client.chat.completions.create({
|
|
478
478
|
model: req.model,
|
|
479
|
-
temperature: req.temperature,
|
|
479
|
+
...req.temperature !== void 0 ? { temperature: req.temperature } : {},
|
|
480
480
|
max_tokens: req.max_tokens,
|
|
481
481
|
messages: [{ role: "user", content: req.prompt_resolved }],
|
|
482
482
|
// OpenRouter extension: ask it to include the call's actual cost in `usage` (ADR-PRC02).
|
|
@@ -1163,7 +1163,7 @@ function buildJudge(provider, cfg, onUsage) {
|
|
|
1163
1163
|
const res = await provider.complete({
|
|
1164
1164
|
provider: cfg.type,
|
|
1165
1165
|
model: cfg.model,
|
|
1166
|
-
temperature:
|
|
1166
|
+
...cfg.temperature !== void 0 ? { temperature: cfg.temperature } : {},
|
|
1167
1167
|
max_tokens: cfg.max_tokens ?? DEFAULT_MAX_TOKENS,
|
|
1168
1168
|
prompt_resolved: prompt5
|
|
1169
1169
|
});
|
|
@@ -1220,7 +1220,7 @@ function estimateUsage(prompt5, maxTokens) {
|
|
|
1220
1220
|
async function runRow(p) {
|
|
1221
1221
|
const t0 = p.now();
|
|
1222
1222
|
const prompt5 = resolvePrompt(p.template, p.row.vars);
|
|
1223
|
-
const temperature = p.providerConfig.temperature
|
|
1223
|
+
const temperature = p.providerConfig.temperature;
|
|
1224
1224
|
const maxTokens = p.providerConfig.max_tokens ?? DEFAULT_MAX_TOKENS2;
|
|
1225
1225
|
if (p.dryRun) {
|
|
1226
1226
|
const est = estimateUsage(prompt5, maxTokens);
|
|
@@ -1230,7 +1230,7 @@ async function runRow(p) {
|
|
|
1230
1230
|
const key = cacheKey({
|
|
1231
1231
|
provider: p.providerConfig.type,
|
|
1232
1232
|
model: p.providerConfig.model,
|
|
1233
|
-
temperature,
|
|
1233
|
+
temperature: temperature ?? 0,
|
|
1234
1234
|
max_tokens: maxTokens,
|
|
1235
1235
|
prompt_resolved: prompt5
|
|
1236
1236
|
});
|
|
@@ -1251,7 +1251,7 @@ async function runRow(p) {
|
|
|
1251
1251
|
const res = await p.provider.complete({
|
|
1252
1252
|
provider: p.providerConfig.type,
|
|
1253
1253
|
model: p.providerConfig.model,
|
|
1254
|
-
temperature,
|
|
1254
|
+
...temperature !== void 0 ? { temperature } : {},
|
|
1255
1255
|
max_tokens: maxTokens,
|
|
1256
1256
|
prompt_resolved: prompt5
|
|
1257
1257
|
});
|
package/dist/reporter-core.cjs
CHANGED
|
@@ -97,7 +97,7 @@ function createClient(opts) {
|
|
|
97
97
|
const wait = opts.wait ?? sleep;
|
|
98
98
|
const base = opts.apiUrl.replace(/\/+$/, "");
|
|
99
99
|
const scrub = (text) => opts.token === "" ? text : text.split(opts.token).join("***");
|
|
100
|
-
async function send(method,
|
|
100
|
+
async function send(method, path3, body) {
|
|
101
101
|
let last = {
|
|
102
102
|
kind: "unavailable",
|
|
103
103
|
status: null,
|
|
@@ -106,7 +106,7 @@ function createClient(opts) {
|
|
|
106
106
|
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt += 1) {
|
|
107
107
|
let res;
|
|
108
108
|
try {
|
|
109
|
-
res = await doFetch(`${base}${
|
|
109
|
+
res = await doFetch(`${base}${path3}`, {
|
|
110
110
|
method,
|
|
111
111
|
headers: { "content-type": "application/json", authorization: `Bearer ${opts.token}` },
|
|
112
112
|
// A DELETE carries none. Sending `"undefined"` as a body is what a naive
|
|
@@ -134,12 +134,13 @@ function createClient(opts) {
|
|
|
134
134
|
return { ok: false, ...last };
|
|
135
135
|
}
|
|
136
136
|
return {
|
|
137
|
-
post: (
|
|
138
|
-
del: (
|
|
137
|
+
post: (path3, body) => send("POST", path3, body),
|
|
138
|
+
del: (path3) => send("DELETE", path3)
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// src/reporter-core/env.ts
|
|
143
|
+
var path = __toESM(require("path"), 1);
|
|
143
144
|
var UNSUPPORTED_VARS = ["PLUNE_GROUP"];
|
|
144
145
|
function value(env, name) {
|
|
145
146
|
const raw = env[name]?.trim();
|
|
@@ -192,13 +193,19 @@ function readEnv(env = process.env) {
|
|
|
192
193
|
ignored: UNSUPPORTED_VARS.filter((name) => value(env, name) !== void 0)
|
|
193
194
|
};
|
|
194
195
|
}
|
|
196
|
+
function defaultRunTitle(env = process.env, now = /* @__PURE__ */ new Date(), cwd = process.cwd()) {
|
|
197
|
+
const two = (n) => String(n).padStart(2, "0");
|
|
198
|
+
const stamp = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())} ${two(now.getHours())}:${two(now.getMinutes())}`;
|
|
199
|
+
const where = flag(env, "CI") || flag(env, "GITHUB_ACTIONS") ? "ci" : "local";
|
|
200
|
+
return `${path.basename(cwd)} \xB7 ${stamp} \xB7 ${where}`;
|
|
201
|
+
}
|
|
195
202
|
|
|
196
203
|
// src/reporter-core/fallback.ts
|
|
197
204
|
var fs = __toESM(require("fs"), 1);
|
|
198
|
-
var
|
|
199
|
-
var DEFAULT_FALLBACK_PATH =
|
|
205
|
+
var path2 = __toESM(require("path"), 1);
|
|
206
|
+
var DEFAULT_FALLBACK_PATH = path2.join(".plune", "pending-results.jsonl");
|
|
200
207
|
function appendBatch(file, batch) {
|
|
201
|
-
fs.mkdirSync(
|
|
208
|
+
fs.mkdirSync(path2.dirname(file), { recursive: true });
|
|
202
209
|
const line = {
|
|
203
210
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
204
211
|
runId: batch.runId,
|
|
@@ -339,6 +346,10 @@ async function startRun(passed, declared) {
|
|
|
339
346
|
...externalKey !== null ? { externalKey } : {},
|
|
340
347
|
...cfg.meta !== void 0 ? { meta: cfg.meta } : {},
|
|
341
348
|
...configuration !== void 0 ? { configuration } : {},
|
|
349
|
+
// Named even when nobody named it — the list has to read without opening a row. Only what
|
|
350
|
+
// the caller DESCRIBED goes to `warnIfDropped` below: a title this side invented is not one
|
|
351
|
+
// a person will miss, and a deployment older than the field must not be nagged on every run.
|
|
352
|
+
title: defaultRunTitle(),
|
|
342
353
|
...described
|
|
343
354
|
});
|
|
344
355
|
if (start.ok) {
|
package/dist/reporter-core.js
CHANGED
|
@@ -54,7 +54,7 @@ function createClient(opts) {
|
|
|
54
54
|
const wait = opts.wait ?? sleep;
|
|
55
55
|
const base = opts.apiUrl.replace(/\/+$/, "");
|
|
56
56
|
const scrub = (text) => opts.token === "" ? text : text.split(opts.token).join("***");
|
|
57
|
-
async function send(method,
|
|
57
|
+
async function send(method, path3, body) {
|
|
58
58
|
let last = {
|
|
59
59
|
kind: "unavailable",
|
|
60
60
|
status: null,
|
|
@@ -63,7 +63,7 @@ function createClient(opts) {
|
|
|
63
63
|
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt += 1) {
|
|
64
64
|
let res;
|
|
65
65
|
try {
|
|
66
|
-
res = await doFetch(`${base}${
|
|
66
|
+
res = await doFetch(`${base}${path3}`, {
|
|
67
67
|
method,
|
|
68
68
|
headers: { "content-type": "application/json", authorization: `Bearer ${opts.token}` },
|
|
69
69
|
// A DELETE carries none. Sending `"undefined"` as a body is what a naive
|
|
@@ -91,12 +91,13 @@ function createClient(opts) {
|
|
|
91
91
|
return { ok: false, ...last };
|
|
92
92
|
}
|
|
93
93
|
return {
|
|
94
|
-
post: (
|
|
95
|
-
del: (
|
|
94
|
+
post: (path3, body) => send("POST", path3, body),
|
|
95
|
+
del: (path3) => send("DELETE", path3)
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// src/reporter-core/env.ts
|
|
100
|
+
import * as path from "path";
|
|
100
101
|
var UNSUPPORTED_VARS = ["PLUNE_GROUP"];
|
|
101
102
|
function value(env, name) {
|
|
102
103
|
const raw = env[name]?.trim();
|
|
@@ -149,13 +150,19 @@ function readEnv(env = process.env) {
|
|
|
149
150
|
ignored: UNSUPPORTED_VARS.filter((name) => value(env, name) !== void 0)
|
|
150
151
|
};
|
|
151
152
|
}
|
|
153
|
+
function defaultRunTitle(env = process.env, now = /* @__PURE__ */ new Date(), cwd = process.cwd()) {
|
|
154
|
+
const two = (n) => String(n).padStart(2, "0");
|
|
155
|
+
const stamp = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())} ${two(now.getHours())}:${two(now.getMinutes())}`;
|
|
156
|
+
const where = flag(env, "CI") || flag(env, "GITHUB_ACTIONS") ? "ci" : "local";
|
|
157
|
+
return `${path.basename(cwd)} \xB7 ${stamp} \xB7 ${where}`;
|
|
158
|
+
}
|
|
152
159
|
|
|
153
160
|
// src/reporter-core/fallback.ts
|
|
154
161
|
import * as fs from "fs";
|
|
155
|
-
import * as
|
|
156
|
-
var DEFAULT_FALLBACK_PATH =
|
|
162
|
+
import * as path2 from "path";
|
|
163
|
+
var DEFAULT_FALLBACK_PATH = path2.join(".plune", "pending-results.jsonl");
|
|
157
164
|
function appendBatch(file, batch) {
|
|
158
|
-
fs.mkdirSync(
|
|
165
|
+
fs.mkdirSync(path2.dirname(file), { recursive: true });
|
|
159
166
|
const line = {
|
|
160
167
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
161
168
|
runId: batch.runId,
|
|
@@ -296,6 +303,10 @@ async function startRun(passed, declared) {
|
|
|
296
303
|
...externalKey !== null ? { externalKey } : {},
|
|
297
304
|
...cfg.meta !== void 0 ? { meta: cfg.meta } : {},
|
|
298
305
|
...configuration !== void 0 ? { configuration } : {},
|
|
306
|
+
// Named even when nobody named it — the list has to read without opening a row. Only what
|
|
307
|
+
// the caller DESCRIBED goes to `warnIfDropped` below: a title this side invented is not one
|
|
308
|
+
// a person will miss, and a deployment older than the field must not be nagged on every run.
|
|
309
|
+
title: defaultRunTitle(),
|
|
299
310
|
...described
|
|
300
311
|
});
|
|
301
312
|
if (start.ok) {
|
package/package.json
CHANGED