dsh-llm-verifier 0.6.0 → 0.6.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/README.md +3 -0
- package/lib/{auto-DAMeKRkK.js → auto-caXDU2pw.js} +19 -1
- package/lib/{auto-DAMeKRkK.js.map → auto-caXDU2pw.js.map} +1 -1
- package/lib/client.js +493 -331
- package/lib/client.js.map +1 -1
- package/lib/index.js +201 -52
- package/lib/index.js.map +1 -1
- package/lib/replay.js +1 -1
- package/lib/types/client-i18n.d.ts +36 -11
- package/lib/types/client-i18n.d.ts.map +1 -1
- package/lib/types/client-i18n.js +50 -9
- package/lib/types/client-i18n.js.map +1 -1
- package/lib/types/client.d.ts +17 -7
- package/lib/types/client.d.ts.map +1 -1
- package/lib/types/client.js +165 -44
- package/lib/types/client.js.map +1 -1
- package/lib/types/decisions.d.ts +8 -0
- package/lib/types/decisions.d.ts.map +1 -1
- package/lib/types/decisions.js +13 -1
- package/lib/types/decisions.js.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +47 -31
- package/lib/types/index.js.map +1 -1
- package/lib/types/process-selection.d.ts +27 -5
- package/lib/types/process-selection.d.ts.map +1 -1
- package/lib/types/process-selection.js +17 -8
- package/lib/types/process-selection.js.map +1 -1
- package/lib/types/router.d.ts +22 -0
- package/lib/types/router.d.ts.map +1 -1
- package/lib/types/router.js +20 -0
- package/lib/types/router.js.map +1 -1
- package/lib/types/statistics.d.ts +8 -0
- package/lib/types/statistics.d.ts.map +1 -1
- package/lib/types/statistics.js +1 -1
- package/lib/types/statistics.js.map +1 -1
- package/lib/types/verifier-activity.d.ts +189 -0
- package/lib/types/verifier-activity.d.ts.map +1 -0
- package/lib/types/verifier-activity.js +223 -0
- package/lib/types/verifier-activity.js.map +1 -0
- package/package.json +1 -1
- package/src/client-i18n.ts +55 -16
- package/src/client.test.ts +101 -16
- package/src/client.tsx +238 -103
- package/src/decisions.test.ts +16 -0
- package/src/decisions.ts +22 -1
- package/src/index.test.ts +32 -0
- package/src/index.ts +48 -33
- package/src/process-selection.test.ts +13 -0
- package/src/process-selection.ts +39 -14
- package/src/router.test.ts +46 -0
- package/src/router.ts +31 -0
- package/src/statistics.test.ts +16 -0
- package/src/statistics.ts +9 -1
- package/src/verifier-activity.test.ts +164 -0
- package/src/verifier-activity.ts +321 -0
- package/lib/types/process-activity.d.ts +0 -109
- package/lib/types/process-activity.d.ts.map +0 -1
- package/lib/types/process-activity.js +0 -135
- package/lib/types/process-activity.js.map +0 -1
- package/src/process-activity.test.ts +0 -91
- package/src/process-activity.ts +0 -177
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CRITERIA_PRESETS, CRITERIA_PRESET_IDS, DEFAULT_CRITERIA, DEFAULT_GROUND_TRUTH_NOTE, EMPTY_WORK_BASELINE, GRANULARITY, LETTERS, MAX_DIAGNOSTICS, MAX_DIAGNOSTIC_ACTION_CHARS, MAX_DIAGNOSTIC_CHARS, PROCESS_CRITERIA, PROPOSAL_CRITERIA, SCALE_DESCRIPTION, UNTRUSTED_EVIDENCE_NOTE, accumulatePairs, bradleyTerry, buildFindingContract, buildGenerationPrompt, buildPairwisePrompt, buildProgressPrompt, dedupeCriterionId, diagnosticKey, evidenceNonce, extractProgressScore, extractScore, normalizeScoreLetter, parseCriteriaMarkdown, parseDiagnostics, pivotRoundPairs, rankScores, renderDelimitedBlock, renderDiagnostics, renderReferenceContext, ringCycle, seededRandom, slugCriterionId, swapDiagnosticEvidence, topPivots } from "./core.js";
|
|
2
2
|
import { a as attachUsage, c as emptyUsage, f as partialUsage, g as resolveCapabilityFile, h as TopLogprobCapabilityCache, i as addUsage, m as requestAttempts, o as callVerifier, p as predictScoringChannel, r as RequestLimiter, s as callVerifierText, u as generateCandidate } from "./caller-BUK7OgUs.js";
|
|
3
|
-
import { A as verificationFailed, C as latestDirectUserSeq, D as semanticDecision, E as routedRepeats, F as ScoreCache, I as SingleFlight, L as resolveCacheFile, M as extractSession, N as sanitizeVerifierText, O as semanticReferencesVisible, P as sessionEvents, R as stableHash, S as itemBudget, T as parseSemanticRoute, _ as buildSemanticRoutePrompt, a as compareRouteFeedbackDetail, b as inspectDeliveryPhase, c as selectRouteFeedbackDetail, d as AutoVerifierRouter, f as MAX_ROUTED_CHECKPOINTS, g as buildEvidenceIndex, h as boundDecision, i as automaticFeedback, j as verificationVerdict, k as semanticRouteHint, l as sessionAccepted, m as analyzeStructuredRoute, n as PROPOSAL_FEEDBACK_NOTE, o as failedAcceptanceCriteria, p as RECOVERY_FAILURE_CONTEXT_CHARS, r as analyzeAutoTask, s as isSubagentSession, t as MAX_ROUTE_FEEDBACK_CHARS, u as topScoreIndices, v as buildSemanticRouteView, w as nextDiagnosticCycleId, x as inspectRecoverySignal, y as estimateRoutedCalls } from "./auto-
|
|
3
|
+
import { A as verificationFailed, C as latestDirectUserSeq, D as semanticDecision, E as routedRepeats, F as ScoreCache, I as SingleFlight, L as resolveCacheFile, M as extractSession, N as sanitizeVerifierText, O as semanticReferencesVisible, P as sessionEvents, R as stableHash, S as itemBudget, T as parseSemanticRoute, _ as buildSemanticRoutePrompt, a as compareRouteFeedbackDetail, b as inspectDeliveryPhase, c as selectRouteFeedbackDetail, d as AutoVerifierRouter, f as MAX_ROUTED_CHECKPOINTS, g as buildEvidenceIndex, h as boundDecision, i as automaticFeedback, j as verificationVerdict, k as semanticRouteHint, l as sessionAccepted, m as analyzeStructuredRoute, n as PROPOSAL_FEEDBACK_NOTE, o as failedAcceptanceCriteria, p as RECOVERY_FAILURE_CONTEXT_CHARS, r as analyzeAutoTask, s as isSubagentSession, t as MAX_ROUTE_FEEDBACK_CHARS, u as topScoreIndices, v as buildSemanticRouteView, w as nextDiagnosticCycleId, x as inspectRecoverySignal, y as estimateRoutedCalls } from "./auto-caXDU2pw.js";
|
|
4
4
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
5
5
|
import { createUserMessage, isAgentLoopRequest } from "@deepseek-ai/dsh-llm";
|
|
6
6
|
import z from "schemastery";
|
|
@@ -1381,7 +1381,7 @@ var CriteriaResolver = class {
|
|
|
1381
1381
|
}
|
|
1382
1382
|
};
|
|
1383
1383
|
/**
|
|
1384
|
-
* Map one finished cycle onto the outcome the chip distinguishes.
|
|
1384
|
+
* Map one finished P06 cycle onto the outcome the chip distinguishes.
|
|
1385
1385
|
*
|
|
1386
1386
|
* `replayed` is the host-facing fact ("which stream did the host actually receive") and wins over
|
|
1387
1387
|
* the outcome label: a cycle recorded as `candidate-selected` whose winner was withheld before the
|
|
@@ -1398,17 +1398,120 @@ function classifyProcessOutcome(outcome, replayed) {
|
|
|
1398
1398
|
return "failed";
|
|
1399
1399
|
}
|
|
1400
1400
|
/**
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
1403
|
-
*
|
|
1401
|
+
* Map one granted reservation onto the chip's active record.
|
|
1402
|
+
*
|
|
1403
|
+
* `process` is deliberately NOT mapped: P06 publishes its own richer record (candidate count,
|
|
1404
|
+
* generation vs comparison), and two writers for one cycle id would race. `plan_review` and
|
|
1405
|
+
* `team_task` are not announced either — the plan gate already shows a pending tool row in the
|
|
1406
|
+
* chat, so a chip line would only repeat it.
|
|
1407
|
+
* @param reservation - the reservation the router just granted.
|
|
1408
|
+
* @param startedAt - wall clock the cycle began at.
|
|
1409
|
+
* @returns The active record, or undefined for a phase the chip stays silent about.
|
|
1410
|
+
*/
|
|
1411
|
+
function reservationActivity(reservation, startedAt) {
|
|
1412
|
+
switch (reservation.phase) {
|
|
1413
|
+
case "semantic": return {
|
|
1414
|
+
cycleId: reservation.id,
|
|
1415
|
+
stage: "route",
|
|
1416
|
+
phase: "classifying",
|
|
1417
|
+
expectedCalls: reservation.expectedCalls,
|
|
1418
|
+
startedAt
|
|
1419
|
+
};
|
|
1420
|
+
case "compare":
|
|
1421
|
+
case "select":
|
|
1422
|
+
case "track": return {
|
|
1423
|
+
cycleId: reservation.id,
|
|
1424
|
+
stage: "route",
|
|
1425
|
+
phase: "reviewing",
|
|
1426
|
+
destination: reservation.phase,
|
|
1427
|
+
expectedCalls: reservation.expectedCalls,
|
|
1428
|
+
startedAt
|
|
1429
|
+
};
|
|
1430
|
+
case "final": return {
|
|
1431
|
+
cycleId: reservation.id,
|
|
1432
|
+
stage: "final",
|
|
1433
|
+
phase: "accepting",
|
|
1434
|
+
expectedCalls: reservation.expectedCalls,
|
|
1435
|
+
startedAt
|
|
1436
|
+
};
|
|
1437
|
+
default: return;
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Map a promotion onto the update the chip needs.
|
|
1442
|
+
*
|
|
1443
|
+
* A classification cycle that resolved to a decision stays the SAME reservation (that is what
|
|
1444
|
+
* promotion is for), so the chip must be moved from "classifying" to "reviewing" instead of leaving
|
|
1445
|
+
* a second cycle behind.
|
|
1446
|
+
* @param reservation - the promoted reservation, already carrying its execution phase.
|
|
1447
|
+
* @returns The patch, or undefined when the phase is not one the chip announces.
|
|
1448
|
+
*/
|
|
1449
|
+
function reservationPromotion(reservation) {
|
|
1450
|
+
switch (reservation.phase) {
|
|
1451
|
+
case "compare":
|
|
1452
|
+
case "select":
|
|
1453
|
+
case "track": return {
|
|
1454
|
+
phase: "reviewing",
|
|
1455
|
+
destination: reservation.phase,
|
|
1456
|
+
expectedCalls: reservation.expectedCalls
|
|
1457
|
+
};
|
|
1458
|
+
default: return;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Map a router settlement onto the chip's settled row.
|
|
1463
|
+
*
|
|
1464
|
+
* A routed verdict is steered into the chat by the caller right after the cycle settles, so a second
|
|
1465
|
+
* transient line would only repeat it; the final gate is the opposite (a PASSING acceptance steers
|
|
1466
|
+
* nothing), and that is exactly the case worth showing. `undefined` means "clear the active row and
|
|
1467
|
+
* leave nothing behind".
|
|
1468
|
+
* @param reservation - the reservation being settled.
|
|
1469
|
+
* @param outcome - whether the router committed or failed it.
|
|
1470
|
+
* @returns The stage and outcome to keep, or undefined to clear silently.
|
|
1471
|
+
*/
|
|
1472
|
+
function reservationSettled(reservation, outcome) {
|
|
1473
|
+
return reservation.phase === "final" ? {
|
|
1474
|
+
stage: "final",
|
|
1475
|
+
outcome: outcome === "committed" ? "accepted" : "rejected"
|
|
1476
|
+
} : void 0;
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Build the router's advisory observer over one activity table.
|
|
1480
|
+
*
|
|
1481
|
+
* The router supplies the reservation (it is the only component that knows a cycle was granted and
|
|
1482
|
+
* when it settled); this module owns what the chip says about it.
|
|
1483
|
+
* @param activities - the table the plugin's RPC reads.
|
|
1484
|
+
* @param now - wall clock used for the records and their TTLs.
|
|
1485
|
+
* @returns The observer to hand to `new AutoVerifierRouter(...)`.
|
|
1404
1486
|
*/
|
|
1405
|
-
|
|
1487
|
+
function createActivityObserver(activities, now = Date.now) {
|
|
1488
|
+
const key = (agent) => String(agent.id);
|
|
1489
|
+
return {
|
|
1490
|
+
begin: (agent, reservation) => {
|
|
1491
|
+
const activity = reservationActivity(reservation, now());
|
|
1492
|
+
if (activity !== void 0) activities.begin(key(agent), activity);
|
|
1493
|
+
},
|
|
1494
|
+
promoted: (agent, reservation) => {
|
|
1495
|
+
const patch = reservationPromotion(reservation);
|
|
1496
|
+
if (patch !== void 0) activities.update(key(agent), reservation.id, patch);
|
|
1497
|
+
},
|
|
1498
|
+
settled: (agent, reservation, outcome) => {
|
|
1499
|
+
const settled = reservationSettled(reservation, outcome);
|
|
1500
|
+
activities.finish(key(agent), reservation.id, settled?.outcome, now());
|
|
1501
|
+
}
|
|
1502
|
+
};
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Per-session activity table.
|
|
1506
|
+
*
|
|
1507
|
+
* One active cycle per session, because the router owns one in-flight reservation per agent at a
|
|
1508
|
+
* time; a settled cycle replaces the previous settled one (the chip is a status line, not a history
|
|
1509
|
+
* — the statistics sidecar is the history).
|
|
1510
|
+
*/
|
|
1511
|
+
var VerifierActivities = class {
|
|
1406
1512
|
active = /* @__PURE__ */ new Map();
|
|
1407
1513
|
settled = /* @__PURE__ */ new Map();
|
|
1408
|
-
/**
|
|
1409
|
-
* Publish one cycle as in flight. Called once per bought cycle, after the reservation and the
|
|
1410
|
-
* cycle log are in place and immediately before the alternative is dispatched.
|
|
1411
|
-
*/
|
|
1514
|
+
/** Publish one cycle as in flight. */
|
|
1412
1515
|
begin(sessionId, activity) {
|
|
1413
1516
|
this.active.set(sessionId, activity);
|
|
1414
1517
|
}
|
|
@@ -1419,50 +1522,62 @@ var ProcessActivities = class {
|
|
|
1419
1522
|
* moved back into "in flight" by a late async step.
|
|
1420
1523
|
* @returns whether the exact cycle was the active one.
|
|
1421
1524
|
*/
|
|
1422
|
-
|
|
1525
|
+
update(sessionId, cycleId, patch) {
|
|
1423
1526
|
const current = this.active.get(sessionId);
|
|
1424
1527
|
if (current === void 0 || current.cycleId !== cycleId) return false;
|
|
1425
1528
|
this.active.set(sessionId, {
|
|
1426
1529
|
...current,
|
|
1427
|
-
|
|
1530
|
+
...patch
|
|
1428
1531
|
});
|
|
1429
1532
|
return true;
|
|
1430
1533
|
}
|
|
1431
1534
|
/**
|
|
1432
|
-
* Retire one cycle
|
|
1535
|
+
* Retire one cycle.
|
|
1433
1536
|
*
|
|
1434
1537
|
* A cycle nobody observed (the purchase itself failed, so `begin` never ran) leaves nothing
|
|
1435
1538
|
* behind: the chip must not claim a cycle that never started. A cycle that WAS observed stays
|
|
1436
|
-
* correctable while its own settled record is the current one, which is what
|
|
1437
|
-
*
|
|
1438
|
-
* @
|
|
1539
|
+
* correctable while its own settled record is the current one, which is what P06's late
|
|
1540
|
+
* "the winner was not delivered" correction needs.
|
|
1541
|
+
* @param sessionId - the session the cycle belongs to.
|
|
1542
|
+
* @param cycleId - the cycle to retire.
|
|
1543
|
+
* @param outcome - the settled row to keep, or undefined to clear without leaving one.
|
|
1544
|
+
* @param now - wall clock used for the settled record.
|
|
1545
|
+
* @returns whether the cycle was known and retired.
|
|
1439
1546
|
*/
|
|
1440
|
-
finish(sessionId, cycleId, outcome,
|
|
1441
|
-
const
|
|
1442
|
-
const
|
|
1547
|
+
finish(sessionId, cycleId, outcome, now) {
|
|
1548
|
+
const active = this.active.get(sessionId);
|
|
1549
|
+
const settled = this.settled.get(sessionId);
|
|
1550
|
+
const known = active?.cycleId === cycleId ? active : settled?.cycleId === cycleId ? settled : void 0;
|
|
1443
1551
|
if (known === void 0) return false;
|
|
1444
|
-
if (
|
|
1552
|
+
if (active?.cycleId === cycleId) this.active.delete(sessionId);
|
|
1553
|
+
if (outcome === void 0) {
|
|
1554
|
+
if (settled?.cycleId === cycleId) this.settled.delete(sessionId);
|
|
1555
|
+
return true;
|
|
1556
|
+
}
|
|
1445
1557
|
this.settled.set(sessionId, {
|
|
1446
1558
|
cycleId,
|
|
1447
|
-
|
|
1448
|
-
|
|
1559
|
+
stage: known.stage,
|
|
1560
|
+
outcome,
|
|
1561
|
+
...known.candidates === void 0 ? {} : { candidates: known.candidates },
|
|
1449
1562
|
at: now
|
|
1450
1563
|
});
|
|
1451
1564
|
return true;
|
|
1452
1565
|
}
|
|
1453
1566
|
/**
|
|
1454
|
-
* What one session has to show right now, with expired
|
|
1567
|
+
* What one session has to show right now, with expired records pruned in place.
|
|
1455
1568
|
* @param sessionId - the session to read.
|
|
1456
|
-
* @param now - wall clock used for
|
|
1569
|
+
* @param now - wall clock used for both TTLs.
|
|
1457
1570
|
*/
|
|
1458
1571
|
read(sessionId, now) {
|
|
1572
|
+
const active = this.active.get(sessionId);
|
|
1573
|
+
if (active !== void 0 && now - active.startedAt >= 6e5) this.active.delete(sessionId);
|
|
1459
1574
|
const settled = this.settled.get(sessionId);
|
|
1460
1575
|
if (settled !== void 0 && now - settled.at >= 2e4) this.settled.delete(sessionId);
|
|
1461
|
-
const
|
|
1462
|
-
const
|
|
1576
|
+
const currentActive = this.active.get(sessionId);
|
|
1577
|
+
const currentSettled = this.settled.get(sessionId);
|
|
1463
1578
|
return {
|
|
1464
|
-
...
|
|
1465
|
-
...
|
|
1579
|
+
...currentActive === void 0 ? {} : { active: currentActive },
|
|
1580
|
+
...currentSettled === void 0 ? {} : { settled: currentSettled }
|
|
1466
1581
|
};
|
|
1467
1582
|
}
|
|
1468
1583
|
/** Forget one session entirely (settings changed, task replaced, agent disposed). */
|
|
@@ -1996,14 +2111,18 @@ var ProcessSelector = class {
|
|
|
1996
2111
|
*
|
|
1997
2112
|
* Host-only and in memory: a session event would carry the same information, but the persistence
|
|
1998
2113
|
* read path refuses unknown event types for an out-of-repo plugin, and `Session.append` cannot
|
|
1999
|
-
* set the `ignorable` marker that would make one loadable (see `
|
|
2114
|
+
* set the `ignorable` marker that would make one loadable (see `verifier-activity.ts`).
|
|
2000
2115
|
*/
|
|
2001
|
-
activities
|
|
2116
|
+
activities;
|
|
2002
2117
|
constructor(deps) {
|
|
2003
2118
|
this.deps = deps;
|
|
2119
|
+
this.activities = deps.activities ?? new VerifierActivities();
|
|
2004
2120
|
}
|
|
2005
2121
|
/**
|
|
2006
2122
|
* The cycle one session has to show right now, for the UI chip (in flight, or just settled).
|
|
2123
|
+
*
|
|
2124
|
+
* Reads the SAME table the router publishes into, so a routed review and a process cycle are never
|
|
2125
|
+
* two different answers to "what is this session doing".
|
|
2007
2126
|
* @param sessionId - the session to read.
|
|
2008
2127
|
*/
|
|
2009
2128
|
activity(sessionId) {
|
|
@@ -2169,6 +2288,7 @@ var ProcessSelector = class {
|
|
|
2169
2288
|
this.cycles.set(intent.sessionId, phase);
|
|
2170
2289
|
this.activities.begin(intent.sessionId, {
|
|
2171
2290
|
cycleId: reservation.id,
|
|
2291
|
+
stage: "process",
|
|
2172
2292
|
phase: "generating",
|
|
2173
2293
|
candidates: count,
|
|
2174
2294
|
...observation.alternativeModel === void 0 ? {} : { alternativeModel: observation.alternativeModel },
|
|
@@ -2511,7 +2631,7 @@ var ProcessSelector = class {
|
|
|
2511
2631
|
});
|
|
2512
2632
|
return;
|
|
2513
2633
|
}
|
|
2514
|
-
this.activities.
|
|
2634
|
+
this.activities.update(intent.sessionId, reservation.id, { phase: "comparing" });
|
|
2515
2635
|
let judged;
|
|
2516
2636
|
try {
|
|
2517
2637
|
if ("candidateA" in view) {
|
|
@@ -2530,7 +2650,8 @@ var ProcessSelector = class {
|
|
|
2530
2650
|
winner: compared.winner === "B" ? alternatives[0] : void 0,
|
|
2531
2651
|
tie: compared.winner === "tie",
|
|
2532
2652
|
stats: compared.stats,
|
|
2533
|
-
compare: compared
|
|
2653
|
+
compare: compared,
|
|
2654
|
+
...compared.decisionId === void 0 ? {} : { decisionId: compared.decisionId }
|
|
2534
2655
|
};
|
|
2535
2656
|
} else {
|
|
2536
2657
|
const selected = await this.deps.select({
|
|
@@ -2547,7 +2668,8 @@ var ProcessSelector = class {
|
|
|
2547
2668
|
winner: selected.index > 0 ? alternatives[selected.index - 1] : void 0,
|
|
2548
2669
|
tie: false,
|
|
2549
2670
|
stats: selected.stats,
|
|
2550
|
-
select: selected
|
|
2671
|
+
select: selected,
|
|
2672
|
+
...selected.decisionId === void 0 ? {} : { decisionId: selected.decisionId }
|
|
2551
2673
|
};
|
|
2552
2674
|
}
|
|
2553
2675
|
} catch (error) {
|
|
@@ -2622,7 +2744,7 @@ var ProcessSelector = class {
|
|
|
2622
2744
|
const outcome = "candidate-not-delivered (" + staleBeforeReplay + ")";
|
|
2623
2745
|
observation.replayed = "original";
|
|
2624
2746
|
await this.deps.store(intent.agent).finish(reservation.id, outcome, "original");
|
|
2625
|
-
this.activities.finish(intent.sessionId, reservation.id, outcome, "original", this.deps.now());
|
|
2747
|
+
this.activities.finish(intent.sessionId, reservation.id, classifyProcessOutcome(outcome, "original"), this.deps.now());
|
|
2626
2748
|
try {
|
|
2627
2749
|
await this.deps.correctDelivery({
|
|
2628
2750
|
agent: intent.agent,
|
|
@@ -2690,13 +2812,15 @@ var ProcessSelector = class {
|
|
|
2690
2812
|
}
|
|
2691
2813
|
/** Record a purchased cycle and stamp its durable outcome. */
|
|
2692
2814
|
async report(input) {
|
|
2693
|
-
this.activities.finish(input.intent.sessionId, input.reservation.id, input.outcome, input.replayed, this.deps.now());
|
|
2815
|
+
this.activities.finish(input.intent.sessionId, input.reservation.id, classifyProcessOutcome(input.outcome, input.replayed), this.deps.now());
|
|
2694
2816
|
await this.deps.store(input.intent.agent).finish(input.reservation.id, input.outcome, input.replayed);
|
|
2817
|
+
const decisionId = input.compare?.decisionId ?? input.select?.decisionId;
|
|
2695
2818
|
await this.deps.record({
|
|
2696
2819
|
agent: input.intent.agent,
|
|
2697
2820
|
cycleId: input.reservation.id,
|
|
2698
2821
|
purchased: true,
|
|
2699
2822
|
startedAt: input.startedAt,
|
|
2823
|
+
...decisionId === void 0 ? {} : { decisionId },
|
|
2700
2824
|
outcome: input.outcome,
|
|
2701
2825
|
replayed: input.replayed,
|
|
2702
2826
|
generatedCalls: input.generatedCalls,
|
|
@@ -3302,7 +3426,7 @@ var StatisticsStore = class {
|
|
|
3302
3426
|
const verdict = cleanVerdict(input.verdict);
|
|
3303
3427
|
const route = cleanRoute(input.route);
|
|
3304
3428
|
const record = {
|
|
3305
|
-
id: randomUUID(),
|
|
3429
|
+
id: typeof input.id === "string" && input.id.length > 0 ? input.id : randomUUID(),
|
|
3306
3430
|
toolName: input.toolName,
|
|
3307
3431
|
...input.sessionId ? { sessionId: input.sessionId } : {},
|
|
3308
3432
|
startedAt: input.startedAt,
|
|
@@ -3638,7 +3762,7 @@ var DecisionStore = class {
|
|
|
3638
3762
|
const calls = boundDecisionCalls(input.calls);
|
|
3639
3763
|
if (calls.length === 0) return void 0;
|
|
3640
3764
|
const record = {
|
|
3641
|
-
id:
|
|
3765
|
+
id: idOf(input.id),
|
|
3642
3766
|
toolName: input.toolName,
|
|
3643
3767
|
phase: input.phase,
|
|
3644
3768
|
startedAt: input.startedAt,
|
|
@@ -3698,6 +3822,18 @@ var DecisionStore = class {
|
|
|
3698
3822
|
}
|
|
3699
3823
|
};
|
|
3700
3824
|
/**
|
|
3825
|
+
* The id a snapshot is filed under.
|
|
3826
|
+
*
|
|
3827
|
+
* A caller-supplied id is the statistics row's own id ({@link DecisionInput.id}), which is what
|
|
3828
|
+
* makes the dashboard's "one snapshot per row" lookup resolve; anything unusable falls back to a
|
|
3829
|
+
* fresh uuid so a malformed argument can never merge two invocations into one record.
|
|
3830
|
+
* @param candidate - id supplied by the caller, if any.
|
|
3831
|
+
* @returns The id to store the record under.
|
|
3832
|
+
*/
|
|
3833
|
+
function idOf(candidate) {
|
|
3834
|
+
return typeof candidate === "string" && candidate.length > 0 ? candidate : randomUUID();
|
|
3835
|
+
}
|
|
3836
|
+
/**
|
|
3701
3837
|
* Loose validation, so a record written by a newer/older plugin still loads.
|
|
3702
3838
|
* @param value - parsed JSON entry.
|
|
3703
3839
|
* @returns True when the entry carries the fields the dashboard needs.
|
|
@@ -4095,7 +4231,8 @@ function apply(ctx, config = {}) {
|
|
|
4095
4231
|
limiter = new RequestLimiter(current().maxConcurrency);
|
|
4096
4232
|
clearProcessIntents();
|
|
4097
4233
|
});
|
|
4098
|
-
const
|
|
4234
|
+
const activities = new VerifierActivities();
|
|
4235
|
+
const autoRouter = new AutoVerifierRouter(createActivityObserver(activities));
|
|
4099
4236
|
const topics = /* @__PURE__ */ new Map();
|
|
4100
4237
|
const topic = (header) => {
|
|
4101
4238
|
const selected = current();
|
|
@@ -4258,7 +4395,7 @@ function apply(ctx, config = {}) {
|
|
|
4258
4395
|
...completed.result,
|
|
4259
4396
|
...route(selected)
|
|
4260
4397
|
};
|
|
4261
|
-
await statistics.record({
|
|
4398
|
+
const invocation = await statistics.record({
|
|
4262
4399
|
toolName,
|
|
4263
4400
|
sessionId: String(agent.id),
|
|
4264
4401
|
startedAt,
|
|
@@ -4268,8 +4405,9 @@ function apply(ctx, config = {}) {
|
|
|
4268
4405
|
stats: statsFrom(value),
|
|
4269
4406
|
verdict: verdictFrom(toolName, value, phase),
|
|
4270
4407
|
...observation ? { route: observation } : {}
|
|
4271
|
-
}).catch(() =>
|
|
4408
|
+
}).catch(() => void 0);
|
|
4272
4409
|
if (calls.length > 0) await topicEntry.decisions.record({
|
|
4410
|
+
...invocation === void 0 ? {} : { id: invocation.id },
|
|
4273
4411
|
toolName,
|
|
4274
4412
|
phase,
|
|
4275
4413
|
startedAt,
|
|
@@ -4877,6 +5015,7 @@ function apply(ctx, config = {}) {
|
|
|
4877
5015
|
sanitize: (text, maxChars) => sanitizeVerifierText(text, maxChars),
|
|
4878
5016
|
policy: processPolicy,
|
|
4879
5017
|
router: () => autoRouter,
|
|
5018
|
+
activities,
|
|
4880
5019
|
store: (agent) => topic(agent.session.header).process,
|
|
4881
5020
|
taskStatement: async (agent, fromSeq, signal) => {
|
|
4882
5021
|
const target = agent;
|
|
@@ -4908,15 +5047,18 @@ function apply(ctx, config = {}) {
|
|
|
4908
5047
|
reviewStage: "proposal",
|
|
4909
5048
|
...trace ? { trace } : {}
|
|
4910
5049
|
}, request.signal);
|
|
4911
|
-
|
|
5050
|
+
const snapshot = calls.length === 0 ? void 0 : await topic(agent.session.header).decisions.record({
|
|
4912
5051
|
toolName: "verifier_compare",
|
|
4913
5052
|
phase: "process",
|
|
4914
5053
|
startedAt,
|
|
4915
5054
|
provider: selected.provider,
|
|
4916
5055
|
model: selected.model,
|
|
4917
5056
|
calls: boundDecisionCalls([...calls].sort((a, b) => a.label < b.label ? -1 : a.label > b.label ? 1 : 0))
|
|
4918
|
-
}).catch(() =>
|
|
4919
|
-
return result
|
|
5057
|
+
}).catch(() => void 0);
|
|
5058
|
+
return snapshot === void 0 ? result : {
|
|
5059
|
+
...result,
|
|
5060
|
+
decisionId: snapshot.id
|
|
5061
|
+
};
|
|
4920
5062
|
},
|
|
4921
5063
|
select: async (request) => {
|
|
4922
5064
|
const agent = request.agent;
|
|
@@ -4935,15 +5077,18 @@ function apply(ctx, config = {}) {
|
|
|
4935
5077
|
reviewStage: "proposal",
|
|
4936
5078
|
...trace ? { trace } : {}
|
|
4937
5079
|
}, request.signal);
|
|
4938
|
-
|
|
5080
|
+
const snapshot = calls.length === 0 ? void 0 : await topic(agent.session.header).decisions.record({
|
|
4939
5081
|
toolName: "verifier_select",
|
|
4940
5082
|
phase: "process",
|
|
4941
5083
|
startedAt,
|
|
4942
5084
|
provider: selected.provider,
|
|
4943
5085
|
model: selected.model,
|
|
4944
5086
|
calls: boundDecisionCalls([...calls].sort((a, b) => a.label < b.label ? -1 : a.label > b.label ? 1 : 0))
|
|
4945
|
-
}).catch(() =>
|
|
4946
|
-
return result
|
|
5087
|
+
}).catch(() => void 0);
|
|
5088
|
+
return snapshot === void 0 ? result : {
|
|
5089
|
+
...result,
|
|
5090
|
+
decisionId: snapshot.id
|
|
5091
|
+
};
|
|
4947
5092
|
},
|
|
4948
5093
|
record: async (report) => {
|
|
4949
5094
|
const agent = report.agent;
|
|
@@ -4970,6 +5115,7 @@ function apply(ctx, config = {}) {
|
|
|
4970
5115
|
};
|
|
4971
5116
|
const failedCall = report.outcome === "generation-failed" || report.outcome === "comparison-failed";
|
|
4972
5117
|
await topic(agent.session.header).statistics.record({
|
|
5118
|
+
...report.decisionId === void 0 ? {} : { id: report.decisionId },
|
|
4973
5119
|
toolName: report.select === void 0 ? "verifier_compare" : "verifier_select",
|
|
4974
5120
|
sessionId: String(agent.id),
|
|
4975
5121
|
startedAt: report.startedAt,
|
|
@@ -5080,15 +5226,18 @@ function apply(ctx, config = {}) {
|
|
|
5080
5226
|
/** Whether a payload asks for a decision snapshot instead of a statistics overview. */
|
|
5081
5227
|
const isDecisionQuery = (payload) => typeof payload === "object" && payload !== null && payload.kind === "decision";
|
|
5082
5228
|
/**
|
|
5083
|
-
* Whether a payload asks what
|
|
5229
|
+
* Whether a payload asks what this plugin is doing for one session.
|
|
5084
5230
|
*
|
|
5085
|
-
* This is what the chat chip polls while a turn runs
|
|
5086
|
-
*
|
|
5087
|
-
*
|
|
5231
|
+
* This is what the chat chip polls while a turn runs: a P06 cycle (which buffers the reply), a
|
|
5232
|
+
* routed review, or the final acceptance. The wire name is historical — it covers every stage now,
|
|
5233
|
+
* and keeping it means a page holding the older client bundle keeps working.
|
|
5088
5234
|
*/
|
|
5089
5235
|
const isProcessQuery = (payload) => typeof payload === "object" && payload !== null && payload.kind === "process";
|
|
5090
5236
|
/**
|
|
5091
|
-
* Read the in-flight / just-settled
|
|
5237
|
+
* Read the in-flight / just-settled cycle of one session.
|
|
5238
|
+
*
|
|
5239
|
+
* In-memory state only: no sidecar read, no model call, nothing durable, so polling it cannot cost
|
|
5240
|
+
* anything or change a verdict. A session with nothing to show answers with an empty object.
|
|
5092
5241
|
* @param payload - the RPC payload; `sessionId` is required.
|
|
5093
5242
|
* @returns The activity view, or a bad-request failure.
|
|
5094
5243
|
*/
|
|
@@ -5097,7 +5246,7 @@ function apply(ctx, config = {}) {
|
|
|
5097
5246
|
if (typeof sessionId !== "string" || sessionId === "") return rpcFailure("a sessionId is required");
|
|
5098
5247
|
return rpcSuccess({
|
|
5099
5248
|
sessionId,
|
|
5100
|
-
...
|
|
5249
|
+
...activities.read(sessionId, Date.now())
|
|
5101
5250
|
});
|
|
5102
5251
|
};
|
|
5103
5252
|
/**
|