@duckcodeailabs/dql-cli 1.14.0 → 1.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/args.d.ts +15 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +25 -0
- package/dist/args.js.map +1 -1
- package/dist/assets/dql-notebook/assets/{AgentLogPage-Ch7VK20X.js → AgentLogPage-DKbGpRQS.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AiBuildDialog-DBr5TmyM.js → AiBuildDialog-DPSu0Mly.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AiBuildResult-jLPzQO7O.js → AiBuildResult-1uaGnpi1.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AiSidePanel-CdlGsiVC.js → AiSidePanel-BwMREwa7.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AnalyticsHome-C0DXbOwY.js → AnalyticsHome-BGfey_ve.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AppsView-CcpwjApv.js → AppsView-CM1tPywy.js} +4 -4
- package/dist/assets/dql-notebook/assets/{BlockStudio-CFYxafw-.js → BlockStudio--S6WFVO4.js} +1 -1
- package/dist/assets/dql-notebook/assets/{BusinessArtifactView-C0kLYg2p.js → BusinessArtifactView-BEAJ-yNW.js} +1 -1
- package/dist/assets/dql-notebook/assets/{DbtFirstModelingPage-CMwElXD_.js → DbtFirstModelingPage-CNyU5MBX.js} +1 -1
- package/dist/assets/dql-notebook/assets/{GitPage-JjhRDeWY.js → GitPage-IcydAai3.js} +1 -1
- package/dist/assets/dql-notebook/assets/{GlobalAiRail-DakE4NdR.js → GlobalAiRail-CSKW-5eD.js} +1 -1
- package/dist/assets/dql-notebook/assets/{GovernedContextPage-BokDqG6a.js → GovernedContextPage-CFen0eFT.js} +1 -1
- package/dist/assets/dql-notebook/assets/{HelpDocsPage-CjOv6_gz.js → HelpDocsPage-D0D9UCIz.js} +1 -1
- package/dist/assets/dql-notebook/assets/{HomePage-nGaNcwdw.js → HomePage-CmSxapR3.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineageDAG-CO6CFJRg.js → LineageDAG-BGUcIt1B.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineageDetailView-BnGb7OF7.js → LineageDetailView-Dx48Zfzb.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineageDrawer-C5Y0Ht0b.js → LineageDrawer-zaBfSLZO.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineagePathBreadcrumb-Cgh3GR3F.js → LineagePathBreadcrumb-CTZJp4_r.js} +1 -1
- package/dist/assets/dql-notebook/assets/{MiniLineageGraph-Kla9PYuj.js → MiniLineageGraph-CdivNR1S.js} +1 -1
- package/dist/assets/dql-notebook/assets/{NewBlockModal-BR2SnmPT.js → NewBlockModal-DMBFB7nE.js} +1 -1
- package/dist/assets/dql-notebook/assets/{NewNotebookModal-BaCHMYeB.js → NewNotebookModal-DsC9CWlW.js} +1 -1
- package/dist/assets/dql-notebook/assets/{NotebookEditor-CBLqY8cE.js → NotebookEditor-hs-kw8v9.js} +1 -1
- package/dist/assets/dql-notebook/assets/{ReadinessPage-CiN0IWSS.js → ReadinessPage-DJ83cMik.js} +1 -1
- package/dist/assets/dql-notebook/assets/{SetupOnboarding-BhiCsYF-.js → SetupOnboarding-B1Pu_Bvv.js} +1 -1
- package/dist/assets/dql-notebook/assets/{SkillsPage-CCSf8VMm.js → SkillsPage-BHKDay8n.js} +1 -1
- package/dist/assets/dql-notebook/assets/{TrustBadge-BgQmFe_x.js → TrustBadge-BkyGgob2.js} +1 -1
- package/dist/assets/dql-notebook/assets/UnifiedAgentRunPanel-BYdrTaEW.js +89 -0
- package/dist/assets/dql-notebook/assets/{answer-to-notebook-AeDYUDla.js → answer-to-notebook-DmNiuLQA.js} +1 -1
- package/dist/assets/dql-notebook/assets/{arrow-left-C55x2hq_.js → arrow-left--1rsrxm8.js} +1 -1
- package/dist/assets/dql-notebook/assets/{arrow-right-C1cJrhOm.js → arrow-right-D5TdqY1G.js} +1 -1
- package/dist/assets/dql-notebook/assets/{book-open-text-CQf_sdv2.js → book-open-text-Bw7nHbzg.js} +1 -1
- package/dist/assets/dql-notebook/assets/{circle-x-X8-Z2yLY.js → circle-x-DLe6NNM4.js} +1 -1
- package/dist/assets/dql-notebook/assets/{dagre.esm-BjjNYKyY.js → dagre.esm-CW5QZdBt.js} +1 -1
- package/dist/assets/dql-notebook/assets/{external-link-C2zrz5DH.js → external-link-C9Q97sA3.js} +1 -1
- package/dist/assets/dql-notebook/assets/{grip-vertical-qGV_PYGU.js → grip-vertical-CztvkIgo.js} +1 -1
- package/dist/assets/dql-notebook/assets/{index-ByTDPDaH.js → index-zHHzDn6l.js} +127 -127
- package/dist/assets/dql-notebook/assets/{link-2-VpyOxQXG.js → link-2-CiKAvumL.js} +1 -1
- package/dist/assets/dql-notebook/assets/{list-tree-CH2Jhwms.js → list-tree-BtnP2nQ5.js} +1 -1
- package/dist/assets/dql-notebook/assets/{minimize-2-B2TZJ8BT.js → minimize-2-TSFGxcCP.js} +1 -1
- package/dist/assets/dql-notebook/assets/{panel-right-open-BunF88lt.js → panel-right-open-BfXIUWy0.js} +1 -1
- package/dist/assets/dql-notebook/assets/{play-DAFVF4_G.js → play-DVbSFJHD.js} +1 -1
- package/dist/assets/dql-notebook/assets/{rotate-ccw-DGCrrqtY.js → rotate-ccw-D_cesDcX.js} +1 -1
- package/dist/assets/dql-notebook/assets/{semantic-fields-Ci-9QL9F.js → semantic-fields-CoVStdYB.js} +1 -1
- package/dist/assets/dql-notebook/assets/{sliders-horizontal-BOAlXXbn.js → sliders-horizontal-l7xV9K5A.js} +1 -1
- package/dist/assets/dql-notebook/assets/{star-CkksZXHt.js → star-CSBS0H3b.js} +1 -1
- package/dist/assets/dql-notebook/assets/{triangle-alert-D3mjyJZE.js → triangle-alert-BTrnyY4q.js} +1 -1
- package/dist/assets/dql-notebook/assets/{upload-CTNOAVEO.js → upload-sySLq9zb.js} +1 -1
- package/dist/assets/dql-notebook/assets/{usePersistedAgentThreadId-DiQjc7x-.js → usePersistedAgentThreadId-CzwgGdus.js} +1 -1
- package/dist/assets/dql-notebook/assets/{user-round-BWd5tQRg.js → user-round-ChlgXi9j.js} +1 -1
- package/dist/assets/dql-notebook/assets/{wand-sparkles-CqsAv8P-.js → wand-sparkles-CGw0ytyT.js} +1 -1
- package/dist/assets/dql-notebook/assets/{workflow-CSqsj-sC.js → workflow-C_RltiK5.js} +1 -1
- package/dist/assets/dql-notebook/assets/{wrench-DWqzqlX8.js → wrench-D-wLfeu0.js} +1 -1
- package/dist/assets/dql-notebook/assets/{x-65M5rLCE.js → x-B28hIJIC.js} +1 -1
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/commands/agent-eval-cassette.d.ts +164 -0
- package/dist/commands/agent-eval-cassette.d.ts.map +1 -0
- package/dist/commands/agent-eval-cassette.js +313 -0
- package/dist/commands/agent-eval-cassette.js.map +1 -0
- package/dist/commands/agent-eval-runtime.d.ts +109 -0
- package/dist/commands/agent-eval-runtime.d.ts.map +1 -0
- package/dist/commands/agent-eval-runtime.js +165 -0
- package/dist/commands/agent-eval-runtime.js.map +1 -0
- package/dist/commands/agent.d.ts +124 -4
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +410 -106
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/compile.d.ts +13 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +36 -4
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +11 -3
- package/dist/commands/sync.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/analyst-loop-tools.d.ts +19 -0
- package/dist/llm/analyst-loop-tools.d.ts.map +1 -0
- package/dist/llm/analyst-loop-tools.js +56 -0
- package/dist/llm/analyst-loop-tools.js.map +1 -0
- package/dist/llm/providers/dql-agent-provider.d.ts +51 -1
- package/dist/llm/providers/dql-agent-provider.d.ts.map +1 -1
- package/dist/llm/providers/dql-agent-provider.js +563 -14
- package/dist/llm/providers/dql-agent-provider.js.map +1 -1
- package/dist/llm/types.d.ts +47 -1
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/local-runtime.d.ts +123 -1
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +1437 -163
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +10 -10
- package/package.json +10 -10
- package/dist/assets/dql-notebook/assets/UnifiedAgentRunPanel-Bw5AXNDB.js +0 -88
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider cassettes — record a suite once against a real model, replay it
|
|
3
|
+
* offline forever. A deliberately-labelled deterministic migration can keep a
|
|
4
|
+
* legacy response usable for orchestration replay, but it is never evidence of
|
|
5
|
+
* current provider quality.
|
|
6
|
+
*
|
|
7
|
+
* A provider-backed eval is the only kind that measures the product users get:
|
|
8
|
+
* without one, `mayAssumeInterpretation` is false and every ambiguous question
|
|
9
|
+
* clarifies by design (AGT-017), which makes a clarification rate an artifact.
|
|
10
|
+
* But calling a real model on every PR is slow, costly, and non-deterministic —
|
|
11
|
+
* so the suite could never gate anything.
|
|
12
|
+
*
|
|
13
|
+
* Recording once and replaying fixes all three. Model drift then shows up as a
|
|
14
|
+
* reviewable diff when cassettes are re-recorded, instead of as a mystery
|
|
15
|
+
* regression on an unrelated pull request.
|
|
16
|
+
*/
|
|
17
|
+
import { createHash } from 'node:crypto';
|
|
18
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
19
|
+
import { dirname, join } from 'node:path';
|
|
20
|
+
const EVAL_ORCHESTRATION_TRANSIENT_LABELS = [
|
|
21
|
+
'context_pack_id',
|
|
22
|
+
'run_id',
|
|
23
|
+
'snapshot_id',
|
|
24
|
+
'plan_id',
|
|
25
|
+
'reference_instant',
|
|
26
|
+
'generated_at',
|
|
27
|
+
'retrieved_at',
|
|
28
|
+
];
|
|
29
|
+
const EVAL_ORCHESTRATION_TRANSIENT_LABEL_PATTERN = EVAL_ORCHESTRATION_TRANSIENT_LABELS.join('|');
|
|
30
|
+
/**
|
|
31
|
+
* This is intentionally not a general UUID/date/path scrubber. The provider
|
|
32
|
+
* still sees and the fingerprint still binds every business date, user term,
|
|
33
|
+
* relation, column, qualified ID, join, lineage edge, SQL fragment, role, and
|
|
34
|
+
* option. Only producer-labelled orchestration values and the explicitly
|
|
35
|
+
* supplied eval project root are non-semantic enough to normalize.
|
|
36
|
+
*/
|
|
37
|
+
function canonicalizeEvalMessageContentV2(content, projectRoot) {
|
|
38
|
+
const applied = new Set();
|
|
39
|
+
const replacePlainLabel = (_whole, prefix, label) => {
|
|
40
|
+
applied.add(`producer_label:${label.toLowerCase()}`);
|
|
41
|
+
return `${prefix}<ORCHESTRATION_TRANSIENT>`;
|
|
42
|
+
};
|
|
43
|
+
const replaceJsonLabel = (_whole, prefix, label, suffix) => {
|
|
44
|
+
applied.add(`producer_label:${label.toLowerCase()}`);
|
|
45
|
+
return `${prefix}"<ORCHESTRATION_TRANSIENT>"${suffix}`;
|
|
46
|
+
};
|
|
47
|
+
let normalized = content
|
|
48
|
+
.replace(new RegExp(`^(\\s*)((?:${EVAL_ORCHESTRATION_TRANSIENT_LABEL_PATTERN}))\\s*:\\s*[^\\r\\n]*$`, 'gim'), (_whole, indent, label) => replacePlainLabel(_whole, `${indent}${label}: `, label))
|
|
49
|
+
.replace(new RegExp(`^(\\s*"((?:${EVAL_ORCHESTRATION_TRANSIENT_LABEL_PATTERN}))"\\s*:\\s*)"[^"\\r\\n]*"(\\s*,?\\s*)$`, 'gim'), (_whole, prefix, label, suffix) => replaceJsonLabel(_whole, prefix, label, suffix));
|
|
50
|
+
if (projectRoot && normalized.includes(projectRoot)) {
|
|
51
|
+
normalized = normalized.split(projectRoot).join('<PROJECT_ROOT>');
|
|
52
|
+
applied.add('project_root');
|
|
53
|
+
}
|
|
54
|
+
return { content: normalized, appliedRuleClasses: Array.from(applied).sort() };
|
|
55
|
+
}
|
|
56
|
+
export function evalCassetteCanonicalizationV2(projectRoot) {
|
|
57
|
+
return { version: 2, projectRoot };
|
|
58
|
+
}
|
|
59
|
+
function hashDispatch(value) {
|
|
60
|
+
return createHash('sha256').update(JSON.stringify(value)).digest('hex');
|
|
61
|
+
}
|
|
62
|
+
function canonicalDispatch(input, messages, version) {
|
|
63
|
+
return {
|
|
64
|
+
...(version ? { v: version } : {}),
|
|
65
|
+
p: input.providerName,
|
|
66
|
+
o: input.operation,
|
|
67
|
+
m: messages.map((message) => ({ r: message.role, c: message.content })),
|
|
68
|
+
// V1 intentionally treated a tool-set reorder as equivalent. V2 is
|
|
69
|
+
// narrower: canonicalization must not rewrite provider/tool dispatch
|
|
70
|
+
// semantics, including tool order.
|
|
71
|
+
t: version ? [...(input.toolNames ?? [])] : [...(input.toolNames ?? [])].sort(),
|
|
72
|
+
e: input.options?.reasoningEffort ?? null,
|
|
73
|
+
x: input.options?.maxTokens ?? null,
|
|
74
|
+
z: input.options?.temperature ?? null,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Stable key for one provider dispatch.
|
|
79
|
+
*
|
|
80
|
+
* Deliberately includes the full message list: the prompt IS the input, and two
|
|
81
|
+
* turns that differ only in retrieved context are genuinely different calls.
|
|
82
|
+
* Tool NAMES are included but not their schemas — a description edit should not
|
|
83
|
+
* invalidate every cassette in the suite.
|
|
84
|
+
*/
|
|
85
|
+
export function cassetteFingerprint(input) {
|
|
86
|
+
const legacyHash = hashDispatch(canonicalDispatch(input, input.messages));
|
|
87
|
+
if (!input.canonicalization)
|
|
88
|
+
return { key: legacyHash.slice(0, 32) };
|
|
89
|
+
const applied = new Set();
|
|
90
|
+
const messages = input.messages.map((message) => {
|
|
91
|
+
// A user may literally ask about an ID, date, or local path. Only
|
|
92
|
+
// producer-owned messages can contain the labelled orchestration fields
|
|
93
|
+
// that this eval-only canonicalizer is permitted to normalize.
|
|
94
|
+
if (message.role === 'user')
|
|
95
|
+
return message;
|
|
96
|
+
const normalized = canonicalizeEvalMessageContentV2(message.content, input.canonicalization.projectRoot);
|
|
97
|
+
for (const rule of normalized.appliedRuleClasses)
|
|
98
|
+
applied.add(rule);
|
|
99
|
+
return { ...message, content: normalized.content };
|
|
100
|
+
});
|
|
101
|
+
const postHash = hashDispatch(canonicalDispatch(input, messages, 2));
|
|
102
|
+
return {
|
|
103
|
+
key: postHash.slice(0, 32),
|
|
104
|
+
legacyKey: legacyHash.slice(0, 32),
|
|
105
|
+
diagnostics: {
|
|
106
|
+
version: 2,
|
|
107
|
+
messageCount: input.messages.length,
|
|
108
|
+
messageRoles: input.messages.map((message) => message.role),
|
|
109
|
+
preCanonicalHash: hashDispatch(canonicalDispatch(input, input.messages, 2)),
|
|
110
|
+
postCanonicalHash: postHash,
|
|
111
|
+
appliedRuleClasses: Array.from(applied).sort(),
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export function cassetteKey(input) {
|
|
116
|
+
return cassetteFingerprint(input).key;
|
|
117
|
+
}
|
|
118
|
+
export class CassetteStore {
|
|
119
|
+
dir;
|
|
120
|
+
loaded = new Map();
|
|
121
|
+
constructor(dir) {
|
|
122
|
+
this.dir = dir;
|
|
123
|
+
if (!existsSync(dir))
|
|
124
|
+
return;
|
|
125
|
+
for (const file of readdirSync(dir)) {
|
|
126
|
+
if (!file.endsWith('.json'))
|
|
127
|
+
continue;
|
|
128
|
+
try {
|
|
129
|
+
const entry = JSON.parse(readFileSync(join(dir, file), 'utf-8'));
|
|
130
|
+
if (entry?.key)
|
|
131
|
+
this.loaded.set(entry.key, entry);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// A corrupt cassette is skipped, not fatal: it re-records on the next
|
|
135
|
+
// --record run, and a replay miss reports the key that is missing.
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
get(key) {
|
|
140
|
+
return this.loaded.get(key);
|
|
141
|
+
}
|
|
142
|
+
put(entry) {
|
|
143
|
+
this.loaded.set(entry.key, entry);
|
|
144
|
+
mkdirSync(this.dir, { recursive: true });
|
|
145
|
+
writeFileSync(join(this.dir, `${entry.key}.json`), `${JSON.stringify(entry, null, 2)}\n`, 'utf-8');
|
|
146
|
+
}
|
|
147
|
+
size() {
|
|
148
|
+
return this.loaded.size;
|
|
149
|
+
}
|
|
150
|
+
entries() {
|
|
151
|
+
return Array.from(this.loaded.values()).sort((left, right) => left.key.localeCompare(right.key));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* A replay-only runtime with no configured provider still needs the identity
|
|
155
|
+
* that was used to derive cassette keys. Keep that identity in the cassette
|
|
156
|
+
* store rather than guessing a provider from user settings.
|
|
157
|
+
*/
|
|
158
|
+
providerNames() {
|
|
159
|
+
return Array.from(new Set(Array.from(this.loaded.values())
|
|
160
|
+
.map((entry) => entry.providerName.trim())
|
|
161
|
+
.filter(Boolean))).sort();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export function cassetteEvidenceSummary(store) {
|
|
165
|
+
const entries = store.entries();
|
|
166
|
+
const recordedProviderEntries = entries.filter((entry) => entry.provenance?.kind === 'recorded_provider').length;
|
|
167
|
+
const migratedLegacyDeterministicFixtureEntries = entries.filter((entry) => entry.provenance?.kind === 'migrated_legacy_deterministic_fixture').length;
|
|
168
|
+
const syntheticDeterministicOrchestrationFixtureEntries = entries.filter((entry) => entry.provenance?.kind === 'synthetic_deterministic_orchestration_fixture').length;
|
|
169
|
+
const unknownProvenanceEntries = entries.length
|
|
170
|
+
- recordedProviderEntries
|
|
171
|
+
- migratedLegacyDeterministicFixtureEntries
|
|
172
|
+
- syntheticDeterministicOrchestrationFixtureEntries;
|
|
173
|
+
const realProviderQualityExclusionReasons = [
|
|
174
|
+
...(migratedLegacyDeterministicFixtureEntries > 0 ? ['migrated_legacy_deterministic_fixture'] : []),
|
|
175
|
+
...(syntheticDeterministicOrchestrationFixtureEntries > 0 ? ['synthetic_deterministic_orchestration_fixture'] : []),
|
|
176
|
+
...(unknownProvenanceEntries > 0 ? ['unknown_cassette_provenance'] : []),
|
|
177
|
+
...(entries.length === 0 ? ['no_cassette_entries'] : []),
|
|
178
|
+
];
|
|
179
|
+
return {
|
|
180
|
+
totalEntries: entries.length,
|
|
181
|
+
recordedProviderEntries,
|
|
182
|
+
migratedLegacyDeterministicFixtureEntries,
|
|
183
|
+
syntheticDeterministicOrchestrationFixtureEntries,
|
|
184
|
+
unknownProvenanceEntries,
|
|
185
|
+
orchestrationReplayEligible: entries.length > 0,
|
|
186
|
+
realProviderQualityEligible: realProviderQualityExclusionReasons.length === 0,
|
|
187
|
+
realProviderQualityExclusionReasons,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
export class CassetteMissError extends Error {
|
|
191
|
+
key;
|
|
192
|
+
fingerprintDiagnostics;
|
|
193
|
+
constructor(key, operation, fingerprintDiagnostics) {
|
|
194
|
+
const safeDiagnostics = fingerprintDiagnostics
|
|
195
|
+
? ` Safe V2 dispatch facts: messages=${fingerprintDiagnostics.messageCount}; roles=${fingerprintDiagnostics.messageRoles.join(',')}; pre=${fingerprintDiagnostics.preCanonicalHash}; post=${fingerprintDiagnostics.postCanonicalHash}; rules=${fingerprintDiagnostics.appliedRuleClasses.join(',') || 'none'}.`
|
|
196
|
+
: '';
|
|
197
|
+
super(`No cassette for ${operation} (${key}). CI replays recorded provider responses and never calls a live model; `
|
|
198
|
+
+ 're-record with --record against a real provider and commit the new cassettes.'
|
|
199
|
+
+ safeDiagnostics);
|
|
200
|
+
this.name = 'CassetteMissError';
|
|
201
|
+
this.key = key;
|
|
202
|
+
this.fingerprintDiagnostics = fingerprintDiagnostics;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Wrap a provider so its dispatches are recorded or replayed.
|
|
207
|
+
*
|
|
208
|
+
* On replay of a tool loop the recorded tool calls are RE-INVOKED against the
|
|
209
|
+
* live tools rather than stubbed. The model's choices stay frozen (that is the
|
|
210
|
+
* point), but compilation, validation, and execution still really happen — so
|
|
211
|
+
* the suite keeps catching a broken compiler or a wrong number, which a fully
|
|
212
|
+
* stubbed replay would sail straight past.
|
|
213
|
+
*/
|
|
214
|
+
export function withCassette(provider, store, mode, canonicalization) {
|
|
215
|
+
if (mode === 'live')
|
|
216
|
+
return provider;
|
|
217
|
+
const wrapped = {
|
|
218
|
+
name: provider.name,
|
|
219
|
+
available: () => (mode === 'replay' ? Promise.resolve(true) : provider.available()),
|
|
220
|
+
async generate(messages, options) {
|
|
221
|
+
const fingerprint = cassetteFingerprint({ providerName: provider.name, operation: 'generate', messages, options, canonicalization });
|
|
222
|
+
// V2 dispatch identity is deliberately exact. A V1 key can describe a
|
|
223
|
+
// different full runtime envelope (for example, direct runner versus
|
|
224
|
+
// runtime runner); silently falling back would replay a response for the
|
|
225
|
+
// wrong prompt. Migrations must create an explicitly labelled V2 entry.
|
|
226
|
+
const hit = store.get(fingerprint.key);
|
|
227
|
+
if (hit)
|
|
228
|
+
return hit.text;
|
|
229
|
+
if (mode === 'replay')
|
|
230
|
+
throw new CassetteMissError(fingerprint.key, 'generate', fingerprint.diagnostics);
|
|
231
|
+
const text = await provider.generate(messages, options);
|
|
232
|
+
store.put({
|
|
233
|
+
key: fingerprint.key, operation: 'generate', text,
|
|
234
|
+
providerName: provider.name, recordedAt: new Date().toISOString(),
|
|
235
|
+
provenance: {
|
|
236
|
+
kind: 'recorded_provider',
|
|
237
|
+
replayClassification: 'recorded_provider',
|
|
238
|
+
providerQuality: 'eligible',
|
|
239
|
+
},
|
|
240
|
+
...(fingerprint.diagnostics ? { fingerprintDiagnostics: fingerprint.diagnostics } : {}),
|
|
241
|
+
});
|
|
242
|
+
return text;
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
if (provider.generateWithTools) {
|
|
246
|
+
wrapped.generateWithTools = async (messages, tools, options) => {
|
|
247
|
+
const fingerprint = cassetteFingerprint({
|
|
248
|
+
providerName: provider.name,
|
|
249
|
+
operation: 'generate_with_tools',
|
|
250
|
+
messages,
|
|
251
|
+
toolNames: tools.map((tool) => tool.name),
|
|
252
|
+
options: options,
|
|
253
|
+
canonicalization,
|
|
254
|
+
});
|
|
255
|
+
// See `generate`: never alias a V2 tool-loop dispatch to a legacy key.
|
|
256
|
+
const hit = store.get(fingerprint.key);
|
|
257
|
+
if (hit) {
|
|
258
|
+
const byName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
259
|
+
for (const call of hit.toolCalls ?? []) {
|
|
260
|
+
const tool = byName.get(call.name);
|
|
261
|
+
// A cassette recorded against a tool set that no longer has this tool
|
|
262
|
+
// is stale in a way the run should surface, not paper over.
|
|
263
|
+
if (!tool)
|
|
264
|
+
continue;
|
|
265
|
+
await tool.run(call.args).catch(() => undefined);
|
|
266
|
+
}
|
|
267
|
+
return hit.text;
|
|
268
|
+
}
|
|
269
|
+
if (mode === 'replay')
|
|
270
|
+
throw new CassetteMissError(fingerprint.key, 'generate_with_tools', fingerprint.diagnostics);
|
|
271
|
+
const observed = [];
|
|
272
|
+
const recordingTools = tools.map((tool) => ({
|
|
273
|
+
...tool,
|
|
274
|
+
run: async (args) => {
|
|
275
|
+
observed.push({ name: tool.name, args });
|
|
276
|
+
return tool.run(args);
|
|
277
|
+
},
|
|
278
|
+
}));
|
|
279
|
+
const text = await provider.generateWithTools(messages, recordingTools, options);
|
|
280
|
+
store.put({
|
|
281
|
+
key: fingerprint.key, operation: 'generate_with_tools', text, toolCalls: observed,
|
|
282
|
+
providerName: provider.name, recordedAt: new Date().toISOString(),
|
|
283
|
+
provenance: {
|
|
284
|
+
kind: 'recorded_provider',
|
|
285
|
+
replayClassification: 'recorded_provider',
|
|
286
|
+
providerQuality: 'eligible',
|
|
287
|
+
},
|
|
288
|
+
...(fingerprint.diagnostics ? { fingerprintDiagnostics: fingerprint.diagnostics } : {}),
|
|
289
|
+
});
|
|
290
|
+
return text;
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return wrapped;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Pick the cassette mode from the environment.
|
|
297
|
+
*
|
|
298
|
+
* Defaults to `replay` for ANY value that is not explicitly `record` or `live`,
|
|
299
|
+
* including a missing or misspelled one. If someone sets the cassette directory
|
|
300
|
+
* in CI and forgets the mode, the safe outcome is "never call a live model",
|
|
301
|
+
* not a surprise bill and a non-deterministic suite.
|
|
302
|
+
*/
|
|
303
|
+
export function resolveCassetteModeFromEnv(env) {
|
|
304
|
+
const raw = env.DQL_EVAL_CASSETTE_MODE;
|
|
305
|
+
return raw === 'record' || raw === 'live' ? raw : 'replay';
|
|
306
|
+
}
|
|
307
|
+
/** Where a project's eval cassettes live. */
|
|
308
|
+
export function cassetteDirFor(projectRoot, suiteName) {
|
|
309
|
+
const safe = suiteName.replace(/[^a-z0-9._-]+/gi, '-').replace(/\.(ya?ml)$/i, '');
|
|
310
|
+
return join(projectRoot, 'test-cassettes', safe);
|
|
311
|
+
}
|
|
312
|
+
export { dirname as _dirname };
|
|
313
|
+
//# sourceMappingURL=agent-eval-cassette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-eval-cassette.js","sourceRoot":"","sources":["../../src/commands/agent-eval-cassette.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime driver for `dql agent eval`.
|
|
3
|
+
*
|
|
4
|
+
* The in-process driver calls `answer()` directly, which skips
|
|
5
|
+
* `createHybridRouter`, `AgentRunEngine`, `enforceOrdinaryAnalyticalPlanBoundary`
|
|
6
|
+
* and `defaultAgentRunGates`. Every dead-end this harness exists to measure lives
|
|
7
|
+
* in that skipped half — the router can block before the cascade runs, the engine
|
|
8
|
+
* synthesizes its own modeling-gap block, and the gates declare refusal codes
|
|
9
|
+
* terminal. Measuring the answer loop alone reports a cleaner picture than users
|
|
10
|
+
* experience.
|
|
11
|
+
*
|
|
12
|
+
* This driver posts the same body the Ask panel posts and scores the persisted
|
|
13
|
+
* `AgentRun`, so the suite exercises routing, gates, and the transport projection
|
|
14
|
+
* as a real end-to-end contract.
|
|
15
|
+
*/
|
|
16
|
+
import type { AgentAnswer, AgentRun, AgentRunRoute, AgentRunStatus, AgentRunTrustState } from '@duckcodeailabs/dql-agent';
|
|
17
|
+
/** Eval-facing view of a run, shaped like the fields the scorer already reads. */
|
|
18
|
+
export interface RuntimeDrivenRun {
|
|
19
|
+
kind: 'certified' | 'uncertified' | 'no_answer';
|
|
20
|
+
route?: 'certified' | 'generated_sql' | 'research' | 'clarify' | 'blocked';
|
|
21
|
+
runRoute: AgentRunRoute;
|
|
22
|
+
status: AgentRunStatus;
|
|
23
|
+
trustState: AgentRunTrustState;
|
|
24
|
+
answer?: string;
|
|
25
|
+
proposedSql?: string;
|
|
26
|
+
rows?: unknown[];
|
|
27
|
+
clarificationOptionCount: number;
|
|
28
|
+
refusalCode?: string;
|
|
29
|
+
runId: string;
|
|
30
|
+
/**
|
|
31
|
+
* A conversational reply (greeting, capability, polite redirect). It asserts
|
|
32
|
+
* nothing about the data, so it is neither an answer nor a refusal — scoring it
|
|
33
|
+
* as either misreads the correct outcome for an out-of-scope question.
|
|
34
|
+
*/
|
|
35
|
+
conversational: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Did the meaning resolver actually run for this turn?
|
|
38
|
+
*
|
|
39
|
+
* With no provider configured it cannot, and `mayAssumeInterpretation` goes
|
|
40
|
+
* false (AGT-017) — DQL deliberately refuses to settle `booked_revenue` vs
|
|
41
|
+
* `billed_revenue` by lexical rank with semantic judgment switched off. Every
|
|
42
|
+
* ambiguous question then clarifies. That is correct behaviour, but it makes a
|
|
43
|
+
* clarification rate measured without a provider meaningless, so the harness
|
|
44
|
+
* has to be able to say so.
|
|
45
|
+
*/
|
|
46
|
+
meaningResolved: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Count captured by the persisted router retrieval receipt. This is not a
|
|
49
|
+
* synthetic context-pack size: runtime runs do not return an AgentAnswer
|
|
50
|
+
* context pack through the transport projection.
|
|
51
|
+
*/
|
|
52
|
+
retrievalCandidateCount?: number;
|
|
53
|
+
/** Source-lane coverage retained by the router-owned cascade receipt. */
|
|
54
|
+
sourceCoverage?: NonNullable<AgentRun['diagnosticReceiptV3']>['sourceCoverage'];
|
|
55
|
+
/** Typed terminal authority, distinct from a user-facing clarification. */
|
|
56
|
+
terminalOutcome?: NonNullable<AgentRun['routeDecision']>['terminalOutcome'];
|
|
57
|
+
/** Provider/tool count recorded by persisted runtime telemetry. */
|
|
58
|
+
toolCallCount: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Did this run decline to produce a usable answer?
|
|
62
|
+
*
|
|
63
|
+
* `needs_review` is deliberately NOT a refusal: a review-required generated
|
|
64
|
+
* answer is the intended outcome when no governed plan froze, and counting it as
|
|
65
|
+
* a refusal would make the false-refusal metric punish the very behaviour the
|
|
66
|
+
* cascade is supposed to produce.
|
|
67
|
+
*/
|
|
68
|
+
export declare function runtimeRunRefused(run: Pick<AgentRun, 'route' | 'status'>): boolean;
|
|
69
|
+
/** Map an engine route onto the vocabulary the eval cases already use. */
|
|
70
|
+
export declare function evalRouteForRun(route: AgentRunRoute): RuntimeDrivenRun['route'];
|
|
71
|
+
/**
|
|
72
|
+
* Collapse a run into the coarse `kind` the existing expectations assert.
|
|
73
|
+
* Certification follows TRUST, not route: a certified route that degraded to a
|
|
74
|
+
* review-required answer must not be scored as certified.
|
|
75
|
+
*/
|
|
76
|
+
export declare function evalKindForRun(run: Pick<AgentRun, 'route' | 'status' | 'trustState'>): RuntimeDrivenRun['kind'];
|
|
77
|
+
/** Pull SQL and result rows out of the run's artifacts, when it produced any. */
|
|
78
|
+
export declare function runtimeRunOutputs(run: AgentRun): {
|
|
79
|
+
proposedSql?: string;
|
|
80
|
+
rows?: unknown[];
|
|
81
|
+
};
|
|
82
|
+
export declare function projectRuntimeRun(run: AgentRun): RuntimeDrivenRun;
|
|
83
|
+
export interface RuntimeDriverOptions {
|
|
84
|
+
runtimeBase: string;
|
|
85
|
+
question: string;
|
|
86
|
+
requestedMode?: 'ask' | 'auto' | 'research';
|
|
87
|
+
threadId?: string;
|
|
88
|
+
timeoutMs?: number;
|
|
89
|
+
fetchImpl?: typeof fetch;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Post one question to a running `dql serve` and return the persisted run.
|
|
93
|
+
*
|
|
94
|
+
* Failures are surfaced rather than swallowed: a harness that silently scores a
|
|
95
|
+
* transport error as a refusal would report a false-refusal spike that no code
|
|
96
|
+
* change caused.
|
|
97
|
+
*/
|
|
98
|
+
export declare function driveViaRuntime(options: RuntimeDriverOptions): Promise<AgentRun>;
|
|
99
|
+
/**
|
|
100
|
+
* Adapt a persisted run into the `AgentAnswer` shape the existing scorer reads,
|
|
101
|
+
* so both drivers share one set of assertions.
|
|
102
|
+
*
|
|
103
|
+
* Fields the run genuinely does not carry are left UNDEFINED rather than
|
|
104
|
+
* defaulted. An expectation that references one then fails loudly instead of
|
|
105
|
+
* passing against a fabricated value — a harness that quietly invents
|
|
106
|
+
* `sourceTier` would report agreement it never observed.
|
|
107
|
+
*/
|
|
108
|
+
export declare function answerFromRuntimeRun(run: AgentRun): AgentAnswer;
|
|
109
|
+
//# sourceMappingURL=agent-eval-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-eval-runtime.d.ts","sourceRoot":"","sources":["../../src/commands/agent-eval-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE1H,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,KAAK,CAAC,EAAE,WAAW,GAAG,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3E,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,wBAAwB,EAAE,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;;;;;MASE;IACF,eAAe,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,yEAAyE;IACzE,cAAc,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAChF,2EAA2E;IAC3E,eAAe,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC5E,mEAAmE;IACnE,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,OAAO,CAKlF;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAa/E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAI/G;AAYD,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CAe3F;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,gBAAgB,CAuBjE;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8BtF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAuB/D"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Did this run decline to produce a usable answer?
|
|
3
|
+
*
|
|
4
|
+
* `needs_review` is deliberately NOT a refusal: a review-required generated
|
|
5
|
+
* answer is the intended outcome when no governed plan froze, and counting it as
|
|
6
|
+
* a refusal would make the false-refusal metric punish the very behaviour the
|
|
7
|
+
* cascade is supposed to produce.
|
|
8
|
+
*/
|
|
9
|
+
export function runtimeRunRefused(run) {
|
|
10
|
+
return run.route === 'blocked'
|
|
11
|
+
|| run.route === 'clarify'
|
|
12
|
+
|| run.status === 'blocked'
|
|
13
|
+
|| run.status === 'needs_clarification';
|
|
14
|
+
}
|
|
15
|
+
/** Map an engine route onto the vocabulary the eval cases already use. */
|
|
16
|
+
export function evalRouteForRun(route) {
|
|
17
|
+
switch (route) {
|
|
18
|
+
case 'certified_answer': return 'certified';
|
|
19
|
+
case 'semantic_answer': return 'certified';
|
|
20
|
+
case 'generated_answer': return 'generated_sql';
|
|
21
|
+
case 'research': return 'research';
|
|
22
|
+
case 'clarify': return 'clarify';
|
|
23
|
+
// A typed terminal modeling/policy gap is not a clarification. Collapsing
|
|
24
|
+
// it to `clarify` made eval reports claim the user had a choice when the
|
|
25
|
+
// persisted run explicitly recorded a blocked no-answer.
|
|
26
|
+
case 'blocked': return 'blocked';
|
|
27
|
+
default: return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Collapse a run into the coarse `kind` the existing expectations assert.
|
|
32
|
+
* Certification follows TRUST, not route: a certified route that degraded to a
|
|
33
|
+
* review-required answer must not be scored as certified.
|
|
34
|
+
*/
|
|
35
|
+
export function evalKindForRun(run) {
|
|
36
|
+
if (runtimeRunRefused(run))
|
|
37
|
+
return 'no_answer';
|
|
38
|
+
if (run.trustState === 'certified')
|
|
39
|
+
return 'certified';
|
|
40
|
+
return 'uncertified';
|
|
41
|
+
}
|
|
42
|
+
function firstArtifactPayload(run, kinds) {
|
|
43
|
+
for (const artifact of run.artifacts ?? []) {
|
|
44
|
+
if (!kinds.includes(String(artifact.kind)))
|
|
45
|
+
continue;
|
|
46
|
+
if (artifact.payload && typeof artifact.payload === 'object') {
|
|
47
|
+
return artifact.payload;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
/** Pull SQL and result rows out of the run's artifacts, when it produced any. */
|
|
53
|
+
export function runtimeRunOutputs(run) {
|
|
54
|
+
const payload = firstArtifactPayload(run, ['sql_cell', 'dql_block', 'generated_answer', 'answer', 'result']);
|
|
55
|
+
const sql = typeof payload?.sql === 'string'
|
|
56
|
+
? payload.sql
|
|
57
|
+
: typeof payload?.compiledSql === 'string' ? payload.compiledSql : undefined;
|
|
58
|
+
const resultRecord = payload?.result && typeof payload.result === 'object'
|
|
59
|
+
? payload.result
|
|
60
|
+
: undefined;
|
|
61
|
+
const rows = Array.isArray(resultRecord?.rows)
|
|
62
|
+
? resultRecord.rows
|
|
63
|
+
: Array.isArray(payload?.rows) ? payload.rows : undefined;
|
|
64
|
+
return {
|
|
65
|
+
...(sql ? { proposedSql: sql } : {}),
|
|
66
|
+
...(rows ? { rows } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function projectRuntimeRun(run) {
|
|
70
|
+
const refusalEvaluation = (run.evaluations ?? []).find((evaluation) => !evaluation.passed);
|
|
71
|
+
const sourceCoverage = run.diagnosticReceiptV3?.sourceCoverage
|
|
72
|
+
?? run.routeDecision?.analyticalCascadeDecision?.sourceCoverage;
|
|
73
|
+
const retrievalCandidateCount = run.routeDecision?.retrievalEvidence?.candidateCount;
|
|
74
|
+
return {
|
|
75
|
+
kind: evalKindForRun(run),
|
|
76
|
+
route: evalRouteForRun(run.route),
|
|
77
|
+
runRoute: run.route,
|
|
78
|
+
status: run.status,
|
|
79
|
+
trustState: run.trustState,
|
|
80
|
+
clarificationOptionCount: run.clarificationOptions?.length ?? 0,
|
|
81
|
+
runId: run.id,
|
|
82
|
+
conversational: run.route === 'conversation' || run.answerKind === 'conversational',
|
|
83
|
+
meaningResolved: Boolean(run.routeDecision?.meaningResolution),
|
|
84
|
+
toolCallCount: run.telemetry?.toolCalls ?? 0,
|
|
85
|
+
...(typeof retrievalCandidateCount === 'number' ? { retrievalCandidateCount } : {}),
|
|
86
|
+
...(sourceCoverage ? { sourceCoverage } : {}),
|
|
87
|
+
...(run.routeDecision?.terminalOutcome ? { terminalOutcome: run.routeDecision.terminalOutcome } : {}),
|
|
88
|
+
...(run.answer ? { answer: run.answer } : {}),
|
|
89
|
+
...(refusalEvaluation?.id ? { refusalCode: refusalEvaluation.id } : {}),
|
|
90
|
+
...runtimeRunOutputs(run),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Post one question to a running `dql serve` and return the persisted run.
|
|
95
|
+
*
|
|
96
|
+
* Failures are surfaced rather than swallowed: a harness that silently scores a
|
|
97
|
+
* transport error as a refusal would report a false-refusal spike that no code
|
|
98
|
+
* change caused.
|
|
99
|
+
*/
|
|
100
|
+
export async function driveViaRuntime(options) {
|
|
101
|
+
const base = options.runtimeBase.replace(/\/$/, '');
|
|
102
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
103
|
+
const controller = new AbortController();
|
|
104
|
+
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 120_000);
|
|
105
|
+
try {
|
|
106
|
+
const response = await fetchImpl(`${base}/api/agent-runs`, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { 'Content-Type': 'application/json' },
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
question: options.question,
|
|
111
|
+
requestedMode: options.requestedMode ?? 'ask',
|
|
112
|
+
...(options.threadId ? { threadId: options.threadId } : {}),
|
|
113
|
+
}),
|
|
114
|
+
signal: controller.signal,
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
throw new Error(`Runtime returned ${response.status}: ${(await response.text()).slice(0, 400)}`);
|
|
118
|
+
}
|
|
119
|
+
// The endpoint wraps the record (`{ run }`); older/streamed paths return it
|
|
120
|
+
// bare. Accept both rather than guessing one and failing the whole suite.
|
|
121
|
+
const body = await response.json();
|
|
122
|
+
const run = body.run ?? body;
|
|
123
|
+
if (!run || typeof run.id !== 'string') {
|
|
124
|
+
throw new Error(`Runtime response was not an agent run: ${JSON.stringify(body).slice(0, 200)}`);
|
|
125
|
+
}
|
|
126
|
+
return run;
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
clearTimeout(timer);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Adapt a persisted run into the `AgentAnswer` shape the existing scorer reads,
|
|
134
|
+
* so both drivers share one set of assertions.
|
|
135
|
+
*
|
|
136
|
+
* Fields the run genuinely does not carry are left UNDEFINED rather than
|
|
137
|
+
* defaulted. An expectation that references one then fails loudly instead of
|
|
138
|
+
* passing against a fabricated value — a harness that quietly invents
|
|
139
|
+
* `sourceTier` would report agreement it never observed.
|
|
140
|
+
*/
|
|
141
|
+
export function answerFromRuntimeRun(run) {
|
|
142
|
+
const projected = projectRuntimeRun(run);
|
|
143
|
+
const certification = projected.kind === 'no_answer'
|
|
144
|
+
? 'analyst_review_required'
|
|
145
|
+
: run.trustState === 'certified'
|
|
146
|
+
? 'certified'
|
|
147
|
+
: run.trustState === 'review_required'
|
|
148
|
+
? 'analyst_review_required'
|
|
149
|
+
: 'ai_generated';
|
|
150
|
+
return {
|
|
151
|
+
kind: projected.kind,
|
|
152
|
+
certification,
|
|
153
|
+
reviewStatus: run.trustState === 'review_required' ? 'analyst_review_required' : 'none',
|
|
154
|
+
text: run.answer ?? run.summary,
|
|
155
|
+
citations: [],
|
|
156
|
+
considered: [],
|
|
157
|
+
...(projected.proposedSql ? { proposedSql: projected.proposedSql } : {}),
|
|
158
|
+
...(projected.rows ? { result: { columns: [], rows: projected.rows, rowCount: projected.rows.length } } : {}),
|
|
159
|
+
...(projected.refusalCode ? { refusalCode: projected.refusalCode } : {}),
|
|
160
|
+
// Carried so the scorer can tell an answerable clarification from a dead end.
|
|
161
|
+
...(run.clarificationOptions?.length ? { clarificationOptions: run.clarificationOptions } : {}),
|
|
162
|
+
...(projected.conversational ? { answerKind: 'conversational' } : {}),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=agent-eval-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-eval-runtime.js","sourceRoot":"","sources":["../../src/commands/agent-eval-runtime.ts"],"names":[],"mappings":"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"}
|