@triflux/core 10.89.2 → 10.90.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.
@@ -397,12 +397,19 @@ export async function queryJevBatch(input = {}, options = {}) {
397
397
  const { state = "", questions = {} } = sanitizeJevInput(input);
398
398
  const entries = Object.entries(questions || {});
399
399
  const startedAt = Date.now();
400
+ let transport = null;
400
401
  const fallback = (reason) => {
401
402
  recordJevStat(
402
403
  {
403
404
  hook: "jev_batch",
404
405
  kind: "batch",
406
+ accepted: false,
405
407
  intervened: false,
408
+ batchAccepted: false,
409
+ batchReason: reason,
410
+ transport,
411
+ transportFallback: transport === "cli",
412
+ appliedTo: null,
406
413
  reason,
407
414
  durationMs: Date.now() - startedAt,
408
415
  },
@@ -411,19 +418,68 @@ export async function queryJevBatch(input = {}, options = {}) {
411
418
  return null;
412
419
  };
413
420
  if (entries.length === 0) return fallback("batch_empty_questions");
421
+ const finish = (out, transport) => {
422
+ for (const [key, req] of entries) {
423
+ if (
424
+ req.kind === "choice" &&
425
+ Array.isArray(req.options) &&
426
+ !req.options.includes(out[key]?.choice)
427
+ )
428
+ out[key] = null;
429
+ }
430
+ const valid = entries.every(([key]) => out[key]);
431
+ const confident =
432
+ valid &&
433
+ entries.every(([key]) => out[key].confidence >= minConfidence(options));
434
+ const batchReason = !valid
435
+ ? entries.some(([key]) => out[key])
436
+ ? "batch_partial_response"
437
+ : "batch_invalid_response"
438
+ : !confident
439
+ ? "batch_low_confidence"
440
+ : "batch_accepted";
441
+ for (const [key, req] of entries) {
442
+ const result = out[key];
443
+ const accepted = Boolean(
444
+ result && result.confidence >= minConfidence(options),
445
+ );
446
+ recordJevStat(
447
+ {
448
+ hook: req.hook || "jev_batch",
449
+ kind: req.kind,
450
+ transport,
451
+ transportFallback: transport === "cli",
452
+ accepted,
453
+ intervened: accepted,
454
+ reason: !result
455
+ ? "invalid_response"
456
+ : accepted
457
+ ? "accepted"
458
+ : "low_confidence",
459
+ batchAccepted: confident,
460
+ batchReason,
461
+ confidence: result?.confidence ?? null,
462
+ outcome: result?.choice ?? result?.value ?? result?.score ?? null,
463
+ appliedTo: null,
464
+ durationMs: Date.now() - startedAt,
465
+ },
466
+ options,
467
+ );
468
+ }
469
+ return out;
470
+ };
414
471
 
415
472
  try {
416
473
  const clientFn = options.batchClient || options.client;
417
474
  if (typeof clientFn === "function") {
475
+ transport = "custom";
418
476
  const custom = await clientFn({ state, questions }, options);
419
477
  const answers = custom?.answers || custom || {};
420
478
  const out = {};
421
479
  for (const [key, req] of entries) {
422
480
  out[key] = normalizeResponse(answers[key], req.kind);
423
481
  }
424
- if (Object.values(out).some((answer) => !answer))
425
- fallback("batch_invalid_response");
426
- return out;
482
+ return finish(out, "custom");
427
483
  }
428
484
 
429
485
  const env = resolveEnv(options);
@@ -431,6 +487,7 @@ export async function queryJevBatch(input = {}, options = {}) {
431
487
  if (!apiKey) {
432
488
  if (!resolveJevCliBin(env))
433
489
  return fallback("batch_transport_unavailable");
490
+ transport = "cli";
434
491
  const out = {};
435
492
  for (const [key, req] of entries) {
436
493
  out[key] = await callJevCli(
@@ -440,11 +497,15 @@ export async function queryJevBatch(input = {}, options = {}) {
440
497
  },
441
498
  options,
442
499
  );
443
- if (!out[key]) return fallback("batch_invalid_response");
500
+ if (!out[key]) {
501
+ finish(out, "cli");
502
+ return null;
503
+ }
444
504
  }
445
- return out;
505
+ return finish(out, "cli");
446
506
  }
447
507
 
508
+ transport = "http";
448
509
  const url = options.apiUrl || env.JEV_API_URL || DEFAULT_JEV_API_URL;
449
510
  const model = options.model || env.JEV_MODEL || DEFAULT_JEV_MODEL;
450
511
  const timeoutMs = Number(
@@ -479,9 +540,7 @@ export async function queryJevBatch(input = {}, options = {}) {
479
540
  for (const [key, req] of entries) {
480
541
  out[key] = normalizeResponse(answers[key], req.kind);
481
542
  }
482
- if (Object.values(out).some((answer) => !answer))
483
- fallback("batch_invalid_response");
484
- return out;
543
+ return finish(out, "http");
485
544
  } catch {
486
545
  return fallback("batch_call_failed");
487
546
  }
@@ -496,7 +555,12 @@ export function recordJevStat(entry = {}, options = {}) {
496
555
  if (flag === "0" || flag === "false" || flag === "off") return;
497
556
 
498
557
  const explicitFile = options.statsFile || env.TFX_JEV_STATS_FILE || "";
499
- if (!explicitFile && typeof options.client === "function") return;
558
+ if (
559
+ !explicitFile &&
560
+ (typeof options.client === "function" ||
561
+ typeof options.batchClient === "function")
562
+ )
563
+ return;
500
564
 
501
565
  const filePath = explicitFile || DEFAULT_JEV_STATS_PATH;
502
566
  mkdirSync(dirname(filePath), { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@triflux/core",
3
- "version": "10.89.2",
3
+ "version": "10.90.0",
4
4
  "description": "triflux core — CLI routing, adapters. Zero native dependencies.",
5
5
  "type": "module",
6
6
  "main": "hub/index.mjs",