@plune-ai/cli 0.14.1 → 0.14.2

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 CHANGED
@@ -2501,11 +2501,13 @@ async function startRun(passed, declared) {
2501
2501
  "/v1/test-cases/resolve",
2502
2502
  { keys: part }
2503
2503
  );
2504
- if (!out.ok) {
2505
- log(`plune: could not look up test cases (${out.detail || out.kind}).`);
2504
+ if (!out.ok || !Array.isArray(out.body?.results)) {
2505
+ log(`plune: could not look up test cases (${out.ok ? "the answer had no results" : out.detail || out.kind}).`);
2506
2506
  return;
2507
2507
  }
2508
- for (const row of out.body.results) resolved.set(row.key.value, row.testCaseId);
2508
+ for (const row of out.body.results) {
2509
+ if (typeof row?.key?.value === "string") resolved.set(row.key.value, row.testCaseId);
2510
+ }
2509
2511
  }
2510
2512
  }
2511
2513
  if (!offline) {
@@ -2542,12 +2544,13 @@ async function startRun(passed, declared) {
2542
2544
  title: defaultRunTitle(),
2543
2545
  ...described
2544
2546
  });
2545
- if (start.ok) {
2547
+ if (start.ok && typeof start.body?.run?.id === "string") {
2546
2548
  runId = start.body.run.id;
2547
2549
  joined = start.status === 200;
2548
2550
  warnIfDropped(described, start.body.run, log);
2549
2551
  } else {
2550
- log(`plune: could not start the run (${start.detail || start.kind}). Results will be written to ${fallbackPath}.`);
2552
+ const why = start.ok ? "the answer had no run" : start.detail || start.kind;
2553
+ log(`plune: could not start the run (${why}). Results will be written to ${fallbackPath}.`);
2551
2554
  }
2552
2555
  }
2553
2556
  function matchFor(result) {
@@ -2582,15 +2585,15 @@ async function startRun(passed, declared) {
2582
2585
  discovered: batch,
2583
2586
  runId
2584
2587
  });
2585
- if (!out.ok) {
2588
+ if (!out.ok || !Array.isArray(out.body?.results)) {
2586
2589
  stats.unoffered = batches.slice(index).reduce((n, rest) => n + rest.length, 0);
2587
2590
  log(
2588
- `plune: could not offer ${stats.unoffered} unknown test(s) for review (${out.detail || out.kind}).`
2591
+ `plune: could not offer ${stats.unoffered} unknown test(s) for review (${out.ok ? "the answer had no results" : out.detail || out.kind}).`
2589
2592
  );
2590
2593
  return;
2591
2594
  }
2592
- stats.offered += out.body.results.filter((r) => r.outcome === "queued").length;
2593
- stats.created += out.body.results.filter((r) => r.outcome === "created").length;
2595
+ stats.offered += out.body.results.filter((r) => r?.outcome === "queued").length;
2596
+ stats.created += out.body.results.filter((r) => r?.outcome === "created").length;
2594
2597
  }
2595
2598
  }
2596
2599
  async function flush() {
@@ -2630,11 +2633,9 @@ async function startRun(passed, declared) {
2630
2633
  results: part
2631
2634
  });
2632
2635
  const counts = out.ok ? out.body?.counts : void 0;
2633
- if (counts !== void 0) {
2634
- stats.accepted += counts.accepted ?? 0;
2635
- stats.duplicate += counts.duplicate ?? 0;
2636
- stats.conflict += counts.conflict ?? 0;
2637
- stats.rejected += counts.rejected ?? 0;
2636
+ const told = COUNTED.filter((k) => typeof counts?.[k] === "number");
2637
+ if (told.length > 0) {
2638
+ for (const k of told) stats[k] += counts[k];
2638
2639
  progress();
2639
2640
  continue;
2640
2641
  }
@@ -2698,7 +2699,7 @@ async function startRun(passed, declared) {
2698
2699
  ...reason !== void 0 ? { reason } : {}
2699
2700
  });
2700
2701
  if (!out.ok) log(`plune: could not close run ${runId} (${out.detail || out.kind}).`);
2701
- else if (typeof out.body.detached === "number" && out.body.detached > 0) {
2702
+ else if (typeof out.body?.detached === "number" && out.body.detached > 0) {
2702
2703
  log(`plune: ${out.body.detached} test case(s) marked detached \u2014 this full run no longer reports them.`);
2703
2704
  }
2704
2705
  }
@@ -2716,7 +2717,7 @@ async function startRun(passed, declared) {
2716
2717
  }
2717
2718
  };
2718
2719
  }
2719
- var import_node_crypto2, RESOLVE_CHUNK, BATCH_MAX, DISCOVER_MAX, BATCH_DEFAULT, EXPECTED_MAX, KEY_MAX, TITLE_MAX, BATCH_BYTES, ENVELOPE_BYTES;
2720
+ var import_node_crypto2, RESOLVE_CHUNK, BATCH_MAX, DISCOVER_MAX, BATCH_DEFAULT, EXPECTED_MAX, KEY_MAX, TITLE_MAX, COUNTED, BATCH_BYTES, ENVELOPE_BYTES;
2720
2721
  var init_session = __esm({
2721
2722
  "src/reporter-core/session.ts"() {
2722
2723
  "use strict";
@@ -2734,6 +2735,7 @@ var init_session = __esm({
2734
2735
  EXPECTED_MAX = 1e4;
2735
2736
  KEY_MAX = 1024;
2736
2737
  TITLE_MAX = 300;
2738
+ COUNTED = ["accepted", "duplicate", "conflict", "rejected"];
2737
2739
  BATCH_BYTES = 8 * 1024 * 1024;
2738
2740
  ENVELOPE_BYTES = Buffer.byteLength(JSON.stringify({ results: [] }));
2739
2741
  }
@@ -3211,8 +3213,10 @@ function pathIn(path14) {
3211
3213
  const parts = path14.split(/[\\/]+/);
3212
3214
  while (parts.length > 1 && parts.at(-1) === "") parts.pop();
3213
3215
  if (!parts.some((part) => part !== "" && !/^[A-Za-z]:$/.test(part))) return void 0;
3214
- const escaped = parts.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]+");
3215
- return new RegExp(`(?:file:\\/\\/\\/?)?${escaped}`, /^[A-Za-z]:$/.test(parts[0]) ? "gi" : "g");
3216
+ const joined = parts.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]+");
3217
+ const escaped = /^\/(?!\/)/.test(path14) ? joined.replace("[\\\\/]+", "\\\\*\\/") : joined;
3218
+ const url = "(?:(?:file|webpack|webpack-internal):(?:\\\\*\\/){2,3})?";
3219
+ return new RegExp(`${url}${escaped}`, /^[A-Za-z]:$/.test(parts[0]) ? "gi" : "g");
3216
3220
  }
3217
3221
  function cut(text2) {
3218
3222
  if (jsonBytes(text2) <= TEXT_LIMIT) return text2;
@@ -3288,7 +3292,7 @@ var init_failure_detail = __esm({
3288
3292
  TEXT_LIMIT = 524288;
3289
3293
  HEADLINE_LIMIT = 8 * 1024;
3290
3294
  jsonBytes = (text2) => Buffer.byteLength(JSON.stringify(text2)) - 2;
3291
- ANY_HOME = /(?<=^|[\s'"`(=,[])(?:file:\/\/\/?)?(?:\/home\/|\/Users\/|[A-Za-z]:[\\/]+Users[\\/]+)[^\\/\s'"`:*?<>|]+/g;
3295
+ ANY_HOME = /(?<=^|[\s'"`(=,[])(?:(?:file|webpack|webpack-internal):(?:\\*\/){2,3})?(?:\\*\/home\\*\/|\\*\/Users\\*\/|[A-Za-z]:[\\/]+Users[\\/]+)[^\\/\s'"`:*?<>|]+/g;
3292
3296
  fileNameOf = (name) => /^(?:file:\/\/|[\\/]|~[\\/]|[A-Za-z]:[\\/])/.test(name) ? name.split(/[\\/]/).pop() ?? "" : name;
3293
3297
  omitted = (lines) => `\u2026[omitted ${lines} lines]\u2026`;
3294
3298
  METADATA_TYPE = "application/plune.metadata+json";
@@ -268,6 +268,7 @@ var BATCH_DEFAULT = 100;
268
268
  var EXPECTED_MAX = 1e4;
269
269
  var KEY_MAX = 1024;
270
270
  var TITLE_MAX = 300;
271
+ var COUNTED = ["accepted", "duplicate", "conflict", "rejected"];
271
272
  function boundKey(key) {
272
273
  if (key.value.length <= KEY_MAX) return key;
273
274
  const digest = (0, import_node_crypto.createHash)("sha256").update(key.value).digest("hex").slice(0, 16);
@@ -378,11 +379,13 @@ async function startRun(passed, declared) {
378
379
  "/v1/test-cases/resolve",
379
380
  { keys: part }
380
381
  );
381
- if (!out.ok) {
382
- log(`plune: could not look up test cases (${out.detail || out.kind}).`);
382
+ if (!out.ok || !Array.isArray(out.body?.results)) {
383
+ log(`plune: could not look up test cases (${out.ok ? "the answer had no results" : out.detail || out.kind}).`);
383
384
  return;
384
385
  }
385
- for (const row of out.body.results) resolved.set(row.key.value, row.testCaseId);
386
+ for (const row of out.body.results) {
387
+ if (typeof row?.key?.value === "string") resolved.set(row.key.value, row.testCaseId);
388
+ }
386
389
  }
387
390
  }
388
391
  if (!offline) {
@@ -419,12 +422,13 @@ async function startRun(passed, declared) {
419
422
  title: defaultRunTitle(),
420
423
  ...described
421
424
  });
422
- if (start.ok) {
425
+ if (start.ok && typeof start.body?.run?.id === "string") {
423
426
  runId = start.body.run.id;
424
427
  joined = start.status === 200;
425
428
  warnIfDropped(described, start.body.run, log);
426
429
  } else {
427
- log(`plune: could not start the run (${start.detail || start.kind}). Results will be written to ${fallbackPath}.`);
430
+ const why = start.ok ? "the answer had no run" : start.detail || start.kind;
431
+ log(`plune: could not start the run (${why}). Results will be written to ${fallbackPath}.`);
428
432
  }
429
433
  }
430
434
  function matchFor(result) {
@@ -459,15 +463,15 @@ async function startRun(passed, declared) {
459
463
  discovered: batch,
460
464
  runId
461
465
  });
462
- if (!out.ok) {
466
+ if (!out.ok || !Array.isArray(out.body?.results)) {
463
467
  stats.unoffered = batches.slice(index).reduce((n, rest) => n + rest.length, 0);
464
468
  log(
465
- `plune: could not offer ${stats.unoffered} unknown test(s) for review (${out.detail || out.kind}).`
469
+ `plune: could not offer ${stats.unoffered} unknown test(s) for review (${out.ok ? "the answer had no results" : out.detail || out.kind}).`
466
470
  );
467
471
  return;
468
472
  }
469
- stats.offered += out.body.results.filter((r) => r.outcome === "queued").length;
470
- stats.created += out.body.results.filter((r) => r.outcome === "created").length;
473
+ stats.offered += out.body.results.filter((r) => r?.outcome === "queued").length;
474
+ stats.created += out.body.results.filter((r) => r?.outcome === "created").length;
471
475
  }
472
476
  }
473
477
  async function flush() {
@@ -507,11 +511,9 @@ async function startRun(passed, declared) {
507
511
  results: part
508
512
  });
509
513
  const counts = out.ok ? out.body?.counts : void 0;
510
- if (counts !== void 0) {
511
- stats.accepted += counts.accepted ?? 0;
512
- stats.duplicate += counts.duplicate ?? 0;
513
- stats.conflict += counts.conflict ?? 0;
514
- stats.rejected += counts.rejected ?? 0;
514
+ const told = COUNTED.filter((k) => typeof counts?.[k] === "number");
515
+ if (told.length > 0) {
516
+ for (const k of told) stats[k] += counts[k];
515
517
  progress();
516
518
  continue;
517
519
  }
@@ -575,7 +577,7 @@ async function startRun(passed, declared) {
575
577
  ...reason !== void 0 ? { reason } : {}
576
578
  });
577
579
  if (!out.ok) log(`plune: could not close run ${runId} (${out.detail || out.kind}).`);
578
- else if (typeof out.body.detached === "number" && out.body.detached > 0) {
580
+ else if (typeof out.body?.detached === "number" && out.body.detached > 0) {
579
581
  log(`plune: ${out.body.detached} test case(s) marked detached \u2014 this full run no longer reports them.`);
580
582
  }
581
583
  }
@@ -653,13 +655,15 @@ var PATH_START = "(?<![\\w.~%/\\\\-])";
653
655
  var TEXT_LIMIT = 524288;
654
656
  var HEADLINE_LIMIT = 8 * 1024;
655
657
  var jsonBytes = (text) => Buffer.byteLength(JSON.stringify(text)) - 2;
656
- var ANY_HOME = /(?<=^|[\s'"`(=,[])(?:file:\/\/\/?)?(?:\/home\/|\/Users\/|[A-Za-z]:[\\/]+Users[\\/]+)[^\\/\s'"`:*?<>|]+/g;
658
+ var ANY_HOME = /(?<=^|[\s'"`(=,[])(?:(?:file|webpack|webpack-internal):(?:\\*\/){2,3})?(?:\\*\/home\\*\/|\\*\/Users\\*\/|[A-Za-z]:[\\/]+Users[\\/]+)[^\\/\s'"`:*?<>|]+/g;
657
659
  function pathIn(path3) {
658
660
  const parts = path3.split(/[\\/]+/);
659
661
  while (parts.length > 1 && parts.at(-1) === "") parts.pop();
660
662
  if (!parts.some((part) => part !== "" && !/^[A-Za-z]:$/.test(part))) return void 0;
661
- const escaped = parts.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]+");
662
- return new RegExp(`(?:file:\\/\\/\\/?)?${escaped}`, /^[A-Za-z]:$/.test(parts[0]) ? "gi" : "g");
663
+ const joined = parts.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]+");
664
+ const escaped = /^\/(?!\/)/.test(path3) ? joined.replace("[\\\\/]+", "\\\\*\\/") : joined;
665
+ const url = "(?:(?:file|webpack|webpack-internal):(?:\\\\*\\/){2,3})?";
666
+ return new RegExp(`${url}${escaped}`, /^[A-Za-z]:$/.test(parts[0]) ? "gi" : "g");
663
667
  }
664
668
  var fileNameOf = (name) => /^(?:file:\/\/|[\\/]|~[\\/]|[A-Za-z]:[\\/])/.test(name) ? name.split(/[\\/]/).pop() ?? "" : name;
665
669
  function cut(text) {
@@ -221,6 +221,7 @@ var BATCH_DEFAULT = 100;
221
221
  var EXPECTED_MAX = 1e4;
222
222
  var KEY_MAX = 1024;
223
223
  var TITLE_MAX = 300;
224
+ var COUNTED = ["accepted", "duplicate", "conflict", "rejected"];
224
225
  function boundKey(key) {
225
226
  if (key.value.length <= KEY_MAX) return key;
226
227
  const digest = createHash("sha256").update(key.value).digest("hex").slice(0, 16);
@@ -331,11 +332,13 @@ async function startRun(passed, declared) {
331
332
  "/v1/test-cases/resolve",
332
333
  { keys: part }
333
334
  );
334
- if (!out.ok) {
335
- log(`plune: could not look up test cases (${out.detail || out.kind}).`);
335
+ if (!out.ok || !Array.isArray(out.body?.results)) {
336
+ log(`plune: could not look up test cases (${out.ok ? "the answer had no results" : out.detail || out.kind}).`);
336
337
  return;
337
338
  }
338
- for (const row of out.body.results) resolved.set(row.key.value, row.testCaseId);
339
+ for (const row of out.body.results) {
340
+ if (typeof row?.key?.value === "string") resolved.set(row.key.value, row.testCaseId);
341
+ }
339
342
  }
340
343
  }
341
344
  if (!offline) {
@@ -372,12 +375,13 @@ async function startRun(passed, declared) {
372
375
  title: defaultRunTitle(),
373
376
  ...described
374
377
  });
375
- if (start.ok) {
378
+ if (start.ok && typeof start.body?.run?.id === "string") {
376
379
  runId = start.body.run.id;
377
380
  joined = start.status === 200;
378
381
  warnIfDropped(described, start.body.run, log);
379
382
  } else {
380
- log(`plune: could not start the run (${start.detail || start.kind}). Results will be written to ${fallbackPath}.`);
383
+ const why = start.ok ? "the answer had no run" : start.detail || start.kind;
384
+ log(`plune: could not start the run (${why}). Results will be written to ${fallbackPath}.`);
381
385
  }
382
386
  }
383
387
  function matchFor(result) {
@@ -412,15 +416,15 @@ async function startRun(passed, declared) {
412
416
  discovered: batch,
413
417
  runId
414
418
  });
415
- if (!out.ok) {
419
+ if (!out.ok || !Array.isArray(out.body?.results)) {
416
420
  stats.unoffered = batches.slice(index).reduce((n, rest) => n + rest.length, 0);
417
421
  log(
418
- `plune: could not offer ${stats.unoffered} unknown test(s) for review (${out.detail || out.kind}).`
422
+ `plune: could not offer ${stats.unoffered} unknown test(s) for review (${out.ok ? "the answer had no results" : out.detail || out.kind}).`
419
423
  );
420
424
  return;
421
425
  }
422
- stats.offered += out.body.results.filter((r) => r.outcome === "queued").length;
423
- stats.created += out.body.results.filter((r) => r.outcome === "created").length;
426
+ stats.offered += out.body.results.filter((r) => r?.outcome === "queued").length;
427
+ stats.created += out.body.results.filter((r) => r?.outcome === "created").length;
424
428
  }
425
429
  }
426
430
  async function flush() {
@@ -460,11 +464,9 @@ async function startRun(passed, declared) {
460
464
  results: part
461
465
  });
462
466
  const counts = out.ok ? out.body?.counts : void 0;
463
- if (counts !== void 0) {
464
- stats.accepted += counts.accepted ?? 0;
465
- stats.duplicate += counts.duplicate ?? 0;
466
- stats.conflict += counts.conflict ?? 0;
467
- stats.rejected += counts.rejected ?? 0;
467
+ const told = COUNTED.filter((k) => typeof counts?.[k] === "number");
468
+ if (told.length > 0) {
469
+ for (const k of told) stats[k] += counts[k];
468
470
  progress();
469
471
  continue;
470
472
  }
@@ -528,7 +530,7 @@ async function startRun(passed, declared) {
528
530
  ...reason !== void 0 ? { reason } : {}
529
531
  });
530
532
  if (!out.ok) log(`plune: could not close run ${runId} (${out.detail || out.kind}).`);
531
- else if (typeof out.body.detached === "number" && out.body.detached > 0) {
533
+ else if (typeof out.body?.detached === "number" && out.body.detached > 0) {
532
534
  log(`plune: ${out.body.detached} test case(s) marked detached \u2014 this full run no longer reports them.`);
533
535
  }
534
536
  }
@@ -606,13 +608,15 @@ var PATH_START = "(?<![\\w.~%/\\\\-])";
606
608
  var TEXT_LIMIT = 524288;
607
609
  var HEADLINE_LIMIT = 8 * 1024;
608
610
  var jsonBytes = (text) => Buffer.byteLength(JSON.stringify(text)) - 2;
609
- var ANY_HOME = /(?<=^|[\s'"`(=,[])(?:file:\/\/\/?)?(?:\/home\/|\/Users\/|[A-Za-z]:[\\/]+Users[\\/]+)[^\\/\s'"`:*?<>|]+/g;
611
+ var ANY_HOME = /(?<=^|[\s'"`(=,[])(?:(?:file|webpack|webpack-internal):(?:\\*\/){2,3})?(?:\\*\/home\\*\/|\\*\/Users\\*\/|[A-Za-z]:[\\/]+Users[\\/]+)[^\\/\s'"`:*?<>|]+/g;
610
612
  function pathIn(path3) {
611
613
  const parts = path3.split(/[\\/]+/);
612
614
  while (parts.length > 1 && parts.at(-1) === "") parts.pop();
613
615
  if (!parts.some((part) => part !== "" && !/^[A-Za-z]:$/.test(part))) return void 0;
614
- const escaped = parts.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]+");
615
- return new RegExp(`(?:file:\\/\\/\\/?)?${escaped}`, /^[A-Za-z]:$/.test(parts[0]) ? "gi" : "g");
616
+ const joined = parts.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("[\\\\/]+");
617
+ const escaped = /^\/(?!\/)/.test(path3) ? joined.replace("[\\\\/]+", "\\\\*\\/") : joined;
618
+ const url = "(?:(?:file|webpack|webpack-internal):(?:\\\\*\\/){2,3})?";
619
+ return new RegExp(`${url}${escaped}`, /^[A-Za-z]:$/.test(parts[0]) ? "gi" : "g");
616
620
  }
617
621
  var fileNameOf = (name) => /^(?:file:\/\/|[\\/]|~[\\/]|[A-Za-z]:[\\/])/.test(name) ? name.split(/[\\/]/).pop() ?? "" : name;
618
622
  function cut(text) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plune-ai/cli",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
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",