@duckcodeailabs/dql-agent 1.6.31 → 1.6.33
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/agent-run-engine.d.ts +42 -6
- package/dist/agent-run-engine.d.ts.map +1 -1
- package/dist/agent-run-engine.js +133 -79
- package/dist/agent-run-engine.js.map +1 -1
- package/dist/agent-run-gates.d.ts.map +1 -1
- package/dist/agent-run-gates.js +72 -5
- package/dist/agent-run-gates.js.map +1 -1
- package/dist/agent-run-planner.d.ts.map +1 -1
- package/dist/agent-run-planner.js +13 -0
- package/dist/agent-run-planner.js.map +1 -1
- package/dist/answer-loop.d.ts +110 -8
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +1679 -1299
- package/dist/answer-loop.js.map +1 -1
- package/dist/answer-shape.d.ts +16 -0
- package/dist/answer-shape.d.ts.map +1 -0
- package/dist/answer-shape.js +85 -0
- package/dist/answer-shape.js.map +1 -0
- package/dist/cascade/budgets.d.ts +101 -0
- package/dist/cascade/budgets.d.ts.map +1 -0
- package/dist/cascade/budgets.js +184 -0
- package/dist/cascade/budgets.js.map +1 -0
- package/dist/cascade/cascade.d.ts +86 -0
- package/dist/cascade/cascade.d.ts.map +1 -0
- package/dist/cascade/cascade.js +115 -0
- package/dist/cascade/cascade.js.map +1 -0
- package/dist/cascade/route-policy.d.ts +14 -0
- package/dist/cascade/route-policy.d.ts.map +1 -0
- package/dist/cascade/route-policy.js +48 -0
- package/dist/cascade/route-policy.js.map +1 -0
- package/dist/cascade/triage.d.ts +20 -0
- package/dist/cascade/triage.d.ts.map +1 -0
- package/dist/cascade/triage.js +25 -0
- package/dist/cascade/triage.js.map +1 -0
- package/dist/conversation/rolling-summary.d.ts +13 -0
- package/dist/conversation/rolling-summary.d.ts.map +1 -0
- package/dist/conversation/rolling-summary.js +43 -0
- package/dist/conversation/rolling-summary.js.map +1 -0
- package/dist/conversation/session-store.d.ts +110 -0
- package/dist/conversation/session-store.d.ts.map +1 -0
- package/dist/conversation/session-store.js +387 -0
- package/dist/conversation/session-store.js.map +1 -0
- package/dist/conversation/snapshot.d.ts +59 -0
- package/dist/conversation/snapshot.d.ts.map +1 -0
- package/dist/conversation/snapshot.js +153 -0
- package/dist/conversation/snapshot.js.map +1 -0
- package/dist/conversation/working-state.d.ts +49 -0
- package/dist/conversation/working-state.d.ts.map +1 -0
- package/dist/conversation/working-state.js +249 -0
- package/dist/conversation/working-state.js.map +1 -0
- package/dist/embeddings/provider.d.ts +62 -0
- package/dist/embeddings/provider.d.ts.map +1 -1
- package/dist/embeddings/provider.js +98 -0
- package/dist/embeddings/provider.js.map +1 -1
- package/dist/grounding/context-ledger.d.ts +30 -0
- package/dist/grounding/context-ledger.d.ts.map +1 -0
- package/dist/grounding/context-ledger.js +54 -0
- package/dist/grounding/context-ledger.js.map +1 -0
- package/dist/grounding/regrounding.d.ts +24 -0
- package/dist/grounding/regrounding.d.ts.map +1 -0
- package/dist/grounding/regrounding.js +219 -0
- package/dist/grounding/regrounding.js.map +1 -0
- package/dist/grounding/value-index.d.ts +32 -0
- package/dist/grounding/value-index.d.ts.map +1 -0
- package/dist/grounding/value-index.js +67 -0
- package/dist/grounding/value-index.js.map +1 -0
- package/dist/index.d.ts +45 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +102 -11
- package/dist/index.js.map +1 -1
- package/dist/intent-controller.d.ts +7 -0
- package/dist/intent-controller.d.ts.map +1 -1
- package/dist/intent-controller.js +22 -1
- package/dist/intent-controller.js.map +1 -1
- package/dist/kg/build.d.ts.map +1 -1
- package/dist/kg/build.js +44 -17
- package/dist/kg/build.js.map +1 -1
- package/dist/kg/sqlite-fts.d.ts +3 -1
- package/dist/kg/sqlite-fts.d.ts.map +1 -1
- package/dist/kg/sqlite-fts.js +16 -2
- package/dist/kg/sqlite-fts.js.map +1 -1
- package/dist/kg/types.d.ts +23 -1
- package/dist/kg/types.d.ts.map +1 -1
- package/dist/memory/fts-query.d.ts +7 -0
- package/dist/memory/fts-query.d.ts.map +1 -0
- package/dist/memory/fts-query.js +36 -0
- package/dist/memory/fts-query.js.map +1 -0
- package/dist/memory/sqlite-memory.d.ts.map +1 -1
- package/dist/memory/sqlite-memory.js +1 -30
- package/dist/memory/sqlite-memory.js.map +1 -1
- package/dist/metadata/analysis-planner.d.ts +23 -0
- package/dist/metadata/analysis-planner.d.ts.map +1 -1
- package/dist/metadata/analysis-planner.js +432 -2
- package/dist/metadata/analysis-planner.js.map +1 -1
- package/dist/metadata/block-fit.d.ts +24 -0
- package/dist/metadata/block-fit.d.ts.map +1 -0
- package/dist/metadata/block-fit.js +373 -0
- package/dist/metadata/block-fit.js.map +1 -0
- package/dist/metadata/catalog.d.ts +72 -3
- package/dist/metadata/catalog.d.ts.map +1 -1
- package/dist/metadata/catalog.js +1452 -72
- package/dist/metadata/catalog.js.map +1 -1
- package/dist/metadata/drafts.d.ts +25 -0
- package/dist/metadata/drafts.d.ts.map +1 -1
- package/dist/metadata/drafts.js +112 -2
- package/dist/metadata/drafts.js.map +1 -1
- package/dist/metadata/metric-match.d.ts +55 -6
- package/dist/metadata/metric-match.d.ts.map +1 -1
- package/dist/metadata/metric-match.js +158 -13
- package/dist/metadata/metric-match.js.map +1 -1
- package/dist/metadata/sql-context-validation.d.ts +13 -1
- package/dist/metadata/sql-context-validation.d.ts.map +1 -1
- package/dist/metadata/sql-context-validation.js +172 -19
- package/dist/metadata/sql-context-validation.js.map +1 -1
- package/dist/metadata/sql-retrieval.d.ts +3 -2
- package/dist/metadata/sql-retrieval.d.ts.map +1 -1
- package/dist/metadata/sql-retrieval.js +6 -4
- package/dist/metadata/sql-retrieval.js.map +1 -1
- package/dist/providers/claude.d.ts +2 -1
- package/dist/providers/claude.d.ts.map +1 -1
- package/dist/providers/claude.js +95 -0
- package/dist/providers/claude.js.map +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts +2 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +143 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/tool-output.d.ts +2 -0
- package/dist/providers/tool-output.d.ts.map +1 -0
- package/dist/providers/tool-output.js +22 -0
- package/dist/providers/tool-output.js.map +1 -0
- package/dist/providers/types.d.ts +23 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/semantic-bridge/compose.d.ts +89 -0
- package/dist/semantic-bridge/compose.d.ts.map +1 -0
- package/dist/semantic-bridge/compose.js +528 -0
- package/dist/semantic-bridge/compose.js.map +1 -0
- package/dist/semantic-bridge/member-select.d.ts +23 -0
- package/dist/semantic-bridge/member-select.d.ts.map +1 -0
- package/dist/semantic-bridge/member-select.js +106 -0
- package/dist/semantic-bridge/member-select.js.map +1 -0
- package/dist/skills/defaults.d.ts.map +1 -1
- package/dist/skills/defaults.js +5 -0
- package/dist/skills/defaults.js.map +1 -1
- package/dist/synthesize.d.ts +26 -0
- package/dist/synthesize.d.ts.map +1 -1
- package/dist/synthesize.js +72 -3
- package/dist/synthesize.js.map +1 -1
- package/dist/tools/registry.d.ts +15 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +692 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/trust/stamp.d.ts +26 -0
- package/dist/trust/stamp.d.ts.map +1 -0
- package/dist/trust/stamp.js +33 -0
- package/dist/trust/stamp.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type IntentDecision, type IntentSignals } from "./intent-controller.js";
|
|
2
|
+
import { type CascadeAnalysisDepth, type CascadeBudgetTrace, type PartialCascadeBudgetModel } from "./cascade/budgets.js";
|
|
2
3
|
import type { MetadataAgentIntent } from "./metadata/catalog.js";
|
|
3
4
|
import type { ReasoningEffort } from "./providers/reasoning-effort.js";
|
|
4
5
|
export type AgentRunRequestedMode = "auto" | "ask" | "research" | "sql" | "block" | "app";
|
|
@@ -78,11 +79,18 @@ export interface AgentRunRequest {
|
|
|
78
79
|
signals?: IntentSignals;
|
|
79
80
|
selectedObject?: AgentRunSelectedObject;
|
|
80
81
|
workspaceContext?: Record<string, unknown>;
|
|
82
|
+
conversationContext?: Record<string, unknown>;
|
|
81
83
|
history?: Array<{
|
|
82
84
|
role: "user" | "assistant";
|
|
83
85
|
text: string;
|
|
84
86
|
}>;
|
|
87
|
+
/** Server-side conversation thread this run belongs to (persistence + resume). */
|
|
88
|
+
threadId?: string;
|
|
85
89
|
runId?: string;
|
|
90
|
+
/** Optional run-specific model effort. Hosts should still apply provider/settings ceilings. */
|
|
91
|
+
reasoningEffort?: ReasoningEffort;
|
|
92
|
+
/** Optional run-specific context depth for governed answer retrieval and prompting. */
|
|
93
|
+
analysisDepth?: CascadeAnalysisDepth;
|
|
86
94
|
}
|
|
87
95
|
export interface AgentRunEvent {
|
|
88
96
|
id: string;
|
|
@@ -114,6 +122,7 @@ export interface AgentRunStep {
|
|
|
114
122
|
id: string;
|
|
115
123
|
index: number;
|
|
116
124
|
route: AgentRunRoute;
|
|
125
|
+
resolvedRoute?: AgentRunRoute;
|
|
117
126
|
goal: string;
|
|
118
127
|
successCriteria: string[];
|
|
119
128
|
status: AgentRunStepStatus;
|
|
@@ -144,7 +153,12 @@ export interface AgentRun {
|
|
|
144
153
|
evaluations: AgentRunEvaluation[];
|
|
145
154
|
events: AgentRunEvent[];
|
|
146
155
|
nextActions: AgentRunNextAction[];
|
|
156
|
+
/** Same-lane repair reruns. Escalations are tracked separately. */
|
|
147
157
|
repairAttempts: number;
|
|
158
|
+
/** Engine-level route escalations, separate from same-lane repairs. */
|
|
159
|
+
escalationAttempts?: number;
|
|
160
|
+
/** Visible budget model and spend for audits/traces. */
|
|
161
|
+
budgetUsage?: CascadeBudgetTrace;
|
|
148
162
|
}
|
|
149
163
|
export interface AgentRouteExecutionContext {
|
|
150
164
|
runId: string;
|
|
@@ -171,6 +185,18 @@ export interface AgentRouteExecutionContext {
|
|
|
171
185
|
export interface AgentRouteExecutorResult {
|
|
172
186
|
summary?: string;
|
|
173
187
|
answer?: string;
|
|
188
|
+
/**
|
|
189
|
+
* Route resolved by a deeper executor-owned cascade. For example, Ask mode may
|
|
190
|
+
* execute through the generated-answer route, then the answer loop can prove
|
|
191
|
+
* the result came from a certified block.
|
|
192
|
+
*/
|
|
193
|
+
resolvedRoute?: AgentRunRoute;
|
|
194
|
+
/**
|
|
195
|
+
* Cascade tier that actually produced the answer (certified_block /
|
|
196
|
+
* semantic_metric / generated_sql / business_context / no_answer). Lets the
|
|
197
|
+
* engine short-circuit on a governed tier even when the route was generated_answer.
|
|
198
|
+
*/
|
|
199
|
+
answerTier?: string;
|
|
174
200
|
/** How to read `answer` for trust; defaults to "governed". */
|
|
175
201
|
answerKind?: AgentRunAnswerKind;
|
|
176
202
|
status?: AgentRunStatus;
|
|
@@ -208,6 +234,9 @@ export interface AgentRunReplanInput {
|
|
|
208
234
|
attemptsUsed: number;
|
|
209
235
|
repairAttemptsUsed: number;
|
|
210
236
|
maxRepairAttempts: number;
|
|
237
|
+
engineEscalationsUsed?: number;
|
|
238
|
+
maxEngineEscalations?: number;
|
|
239
|
+
budgetUsage?: CascadeBudgetTrace;
|
|
211
240
|
}
|
|
212
241
|
export type AgentRunReplanDecision = {
|
|
213
242
|
decision: "accept";
|
|
@@ -250,6 +279,8 @@ export interface AgentRunEngineOptions {
|
|
|
250
279
|
idGenerator?: () => string;
|
|
251
280
|
now?: () => Date;
|
|
252
281
|
maxRepairAttempts?: number;
|
|
282
|
+
maxEngineEscalations?: number;
|
|
283
|
+
budgets?: PartialCascadeBudgetModel;
|
|
253
284
|
maxSteps?: number;
|
|
254
285
|
}
|
|
255
286
|
/**
|
|
@@ -262,12 +293,17 @@ export declare function resolveAudience(request: AgentRunRequest): AgentRunAudie
|
|
|
262
293
|
/** A stakeholder may never land on an authoring route — collapse it to a governed answer. */
|
|
263
294
|
export declare function constrainRouteForAudience(route: AgentRunRoute, audience: AgentRunAudience): AgentRunRoute;
|
|
264
295
|
/**
|
|
265
|
-
* "Answer anyway, labeled" —
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
296
|
+
* "Answer anyway, labeled" — get a best-effort governed answer rather than a
|
|
297
|
+
* dead-end clarify. The answer loop does its own grounding/retrieval and can still
|
|
298
|
+
* return a needs-clarification result if it genuinely can't proceed.
|
|
299
|
+
*
|
|
300
|
+
* - A SOFT clarify ("nothing governed matched") is answered anyway for EVERY
|
|
301
|
+
* audience — analysts included — so a real analytical question never dead-ends.
|
|
302
|
+
* - A genuine clarify (explicit missing context, explicit clarify intent, or a
|
|
303
|
+
* trust-gap review) stays a clarify for analysts; stakeholders keep the legacy
|
|
304
|
+
* answer-anyway affordance unless the catalog explicitly flagged missing context.
|
|
269
305
|
*/
|
|
270
|
-
export declare function answerAnywayRoute(route: AgentRunRoute, request: AgentRunRequest, audience: AgentRunAudience): AgentRunRoute;
|
|
306
|
+
export declare function answerAnywayRoute(route: AgentRunRoute, request: AgentRunRequest, audience: AgentRunAudience, decision?: IntentDecision): AgentRunRoute;
|
|
271
307
|
/**
|
|
272
308
|
* Task-adaptive reasoning effort per route — the DQL differentiator. Cheap,
|
|
273
309
|
* mechanical routes (chat, clarify, blocked, a pre-written certified lookup) run
|
|
@@ -307,7 +343,7 @@ export declare class AgentRunEngine {
|
|
|
307
343
|
private readonly store?;
|
|
308
344
|
private readonly idGenerator;
|
|
309
345
|
private readonly now;
|
|
310
|
-
private readonly
|
|
346
|
+
private readonly budgetModel;
|
|
311
347
|
private readonly maxSteps;
|
|
312
348
|
constructor(options?: AgentRunEngineOptions);
|
|
313
349
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-run-engine.d.ts","sourceRoot":"","sources":["../src/agent-run-engine.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-run-engine.d.ts","sourceRoot":"","sources":["../src/agent-run-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/agent-run-engine.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { classifyConversationalTurn, decideAgentAction, } from "./intent-controller.js";
|
|
5
|
+
import { selectCascadeRunRoute } from "./cascade/route-policy.js";
|
|
6
|
+
import { canUseEngineEscalation, canUseLaneRepair, cascadeBudgetTrace, createCascadeBudgetState, recordEngineEscalation, recordLaneRepair, } from "./cascade/budgets.js";
|
|
5
7
|
/** Routes a stakeholder may never land on (analyst authoring lives in the Notebook). */
|
|
6
8
|
const ANALYST_ONLY_ROUTES = new Set(["sql_cell", "dql_block_draft"]);
|
|
7
|
-
const DEFAULT_MAX_REPAIR_ATTEMPTS = 2;
|
|
8
9
|
const DEFAULT_MAX_STEPS = 4;
|
|
9
|
-
const CERTIFIED_MATCH_THRESHOLD = 0.5;
|
|
10
10
|
/**
|
|
11
11
|
* Routes whose gate failure is better answered by switching routes than by
|
|
12
12
|
* re-running the same executor (repair can't add what the route can't produce).
|
|
@@ -27,16 +27,25 @@ export function constrainRouteForAudience(route, audience) {
|
|
|
27
27
|
return route;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* "Answer anyway, labeled" —
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
30
|
+
* "Answer anyway, labeled" — get a best-effort governed answer rather than a
|
|
31
|
+
* dead-end clarify. The answer loop does its own grounding/retrieval and can still
|
|
32
|
+
* return a needs-clarification result if it genuinely can't proceed.
|
|
33
|
+
*
|
|
34
|
+
* - A SOFT clarify ("nothing governed matched") is answered anyway for EVERY
|
|
35
|
+
* audience — analysts included — so a real analytical question never dead-ends.
|
|
36
|
+
* - A genuine clarify (explicit missing context, explicit clarify intent, or a
|
|
37
|
+
* trust-gap review) stays a clarify for analysts; stakeholders keep the legacy
|
|
38
|
+
* answer-anyway affordance unless the catalog explicitly flagged missing context.
|
|
34
39
|
*/
|
|
35
|
-
export function answerAnywayRoute(route, request, audience) {
|
|
36
|
-
if (
|
|
40
|
+
export function answerAnywayRoute(route, request, audience, decision) {
|
|
41
|
+
if (route !== "clarify")
|
|
37
42
|
return route;
|
|
38
43
|
const explicitMissing = (request.signals?.missingContext?.length ?? 0) > 0;
|
|
39
|
-
|
|
44
|
+
if (decision?.clarifySoft === true && !explicitMissing)
|
|
45
|
+
return "generated_answer";
|
|
46
|
+
if (audience === "stakeholder" && !explicitMissing)
|
|
47
|
+
return "generated_answer";
|
|
48
|
+
return "clarify";
|
|
40
49
|
}
|
|
41
50
|
/**
|
|
42
51
|
* Task-adaptive reasoning effort per route — the DQL differentiator. Cheap,
|
|
@@ -171,7 +180,7 @@ export class AgentRunEngine {
|
|
|
171
180
|
store;
|
|
172
181
|
idGenerator;
|
|
173
182
|
now;
|
|
174
|
-
|
|
183
|
+
budgetModel;
|
|
175
184
|
maxSteps;
|
|
176
185
|
constructor(options = {}) {
|
|
177
186
|
this.executors = options.executors ?? {};
|
|
@@ -181,7 +190,14 @@ export class AgentRunEngine {
|
|
|
181
190
|
this.store = options.store;
|
|
182
191
|
this.idGenerator = options.idGenerator ?? randomUUID;
|
|
183
192
|
this.now = options.now ?? (() => new Date());
|
|
184
|
-
this.
|
|
193
|
+
this.budgetModel = {
|
|
194
|
+
...options.budgets,
|
|
195
|
+
lane: {
|
|
196
|
+
...options.budgets?.lane,
|
|
197
|
+
execution: options.maxRepairAttempts ?? options.budgets?.lane?.execution,
|
|
198
|
+
},
|
|
199
|
+
engineEscalations: options.maxEngineEscalations ?? options.budgets?.engineEscalations,
|
|
200
|
+
};
|
|
185
201
|
this.maxSteps = Math.max(1, options.maxSteps ?? DEFAULT_MAX_STEPS);
|
|
186
202
|
}
|
|
187
203
|
/**
|
|
@@ -228,7 +244,7 @@ export class AgentRunEngine {
|
|
|
228
244
|
});
|
|
229
245
|
const audience = resolveAudience(request);
|
|
230
246
|
const routeDecision = await this.decideRoute(request);
|
|
231
|
-
const defaultRoute = answerAnywayRoute(constrainRouteForAudience(selectRoute(request, routeDecision), audience), request, audience);
|
|
247
|
+
const defaultRoute = answerAnywayRoute(constrainRouteForAudience(selectRoute(request, routeDecision), audience), request, audience, routeDecision);
|
|
232
248
|
try {
|
|
233
249
|
const plan = await this.planner.plan({
|
|
234
250
|
request,
|
|
@@ -249,14 +265,18 @@ export class AgentRunEngine {
|
|
|
249
265
|
// without explicit missing context.
|
|
250
266
|
const queue = plan.steps.map((step) => ({
|
|
251
267
|
...step,
|
|
252
|
-
route: answerAnywayRoute(constrainRouteForAudience(step.route, audience), request, audience),
|
|
268
|
+
route: answerAnywayRoute(constrainRouteForAudience(step.route, audience), request, audience, routeDecision),
|
|
253
269
|
}));
|
|
254
|
-
|
|
270
|
+
const budgets = createCascadeBudgetState(this.budgetModel);
|
|
255
271
|
let stepCount = 0;
|
|
256
272
|
let finalStep;
|
|
257
273
|
let finalResult;
|
|
258
274
|
let finalOutcome;
|
|
259
275
|
let clarifyOutcome;
|
|
276
|
+
// The last step that actually produced a user-facing answer. A later
|
|
277
|
+
// non-answer step (e.g. a research/draft step that emits only an artifact)
|
|
278
|
+
// must not drop the data answer an earlier step already computed.
|
|
279
|
+
let bestAnswerResult;
|
|
260
280
|
while (queue.length > 0 && stepCount < this.maxSteps) {
|
|
261
281
|
const planned = queue.shift();
|
|
262
282
|
stepCount += 1;
|
|
@@ -299,7 +319,7 @@ export class AgentRunEngine {
|
|
|
299
319
|
request,
|
|
300
320
|
route,
|
|
301
321
|
routeDecision,
|
|
302
|
-
maxRepairAttempts:
|
|
322
|
+
maxRepairAttempts: budgets.limits.lane.execution,
|
|
303
323
|
attempt,
|
|
304
324
|
stepGoal: planned.goal,
|
|
305
325
|
priorEvaluations,
|
|
@@ -326,11 +346,6 @@ export class AgentRunEngine {
|
|
|
326
346
|
stepStatus = attempt > 0 ? "repaired" : "passed";
|
|
327
347
|
break;
|
|
328
348
|
}
|
|
329
|
-
// Out of modify budget — accept the best result we have.
|
|
330
|
-
if (repairAttemptsTotal >= this.maxRepairAttempts) {
|
|
331
|
-
stepStatus = "needs_review";
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
349
|
const currentStep = {
|
|
335
350
|
id: stepId,
|
|
336
351
|
index: stepCount,
|
|
@@ -349,8 +364,11 @@ export class AgentRunEngine {
|
|
|
349
364
|
currentStep,
|
|
350
365
|
remainingSteps: queue,
|
|
351
366
|
attemptsUsed: attempt,
|
|
352
|
-
repairAttemptsUsed:
|
|
353
|
-
maxRepairAttempts:
|
|
367
|
+
repairAttemptsUsed: budgets.usage.laneExecutionAttemptsUsed,
|
|
368
|
+
maxRepairAttempts: budgets.limits.lane.execution,
|
|
369
|
+
engineEscalationsUsed: budgets.usage.engineEscalationsUsed,
|
|
370
|
+
maxEngineEscalations: budgets.limits.engineEscalations,
|
|
371
|
+
budgetUsage: cascadeBudgetTrace(budgets),
|
|
354
372
|
});
|
|
355
373
|
emit({
|
|
356
374
|
type: "replan.decided",
|
|
@@ -359,27 +377,51 @@ export class AgentRunEngine {
|
|
|
359
377
|
payload: decision,
|
|
360
378
|
});
|
|
361
379
|
if (decision.decision === "repair") {
|
|
362
|
-
|
|
380
|
+
const nextRepairHint = repairHintForEvaluation(failing, decision.repairHint);
|
|
381
|
+
if (!canUseLaneRepair(budgets, "execution")) {
|
|
382
|
+
stepStatus = "needs_review";
|
|
383
|
+
emit({
|
|
384
|
+
type: "repair.attempted",
|
|
385
|
+
message: `Repair budget exhausted for ${route.replaceAll("_", " ")}.`,
|
|
386
|
+
route,
|
|
387
|
+
payload: {
|
|
388
|
+
repairHint: nextRepairHint,
|
|
389
|
+
budgetUsage: cascadeBudgetTrace(budgets),
|
|
390
|
+
},
|
|
391
|
+
});
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
recordLaneRepair(budgets, "execution");
|
|
363
395
|
attempt += 1;
|
|
364
|
-
repairHint =
|
|
396
|
+
repairHint = nextRepairHint;
|
|
365
397
|
priorEvaluations = evaluations;
|
|
366
398
|
emit({
|
|
367
399
|
type: "repair.attempted",
|
|
368
400
|
message: `Repairing ${route.replaceAll("_", " ")}: ${repairHint}`,
|
|
369
401
|
route,
|
|
370
|
-
payload: { attempt, repairHint },
|
|
402
|
+
payload: { attempt, repairHint, budgetUsage: cascadeBudgetTrace(budgets) },
|
|
371
403
|
});
|
|
372
404
|
continue;
|
|
373
405
|
}
|
|
374
406
|
if (decision.decision === "escalate") {
|
|
375
|
-
|
|
376
|
-
|
|
407
|
+
if (!canUseEngineEscalation(budgets)) {
|
|
408
|
+
stepStatus = "needs_review";
|
|
409
|
+
emit({
|
|
410
|
+
type: "escalated",
|
|
411
|
+
message: `Escalation budget exhausted for ${route.replaceAll("_", " ")}.`,
|
|
412
|
+
route,
|
|
413
|
+
payload: { decision, budgetUsage: cascadeBudgetTrace(budgets) },
|
|
414
|
+
});
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
recordEngineEscalation(budgets);
|
|
418
|
+
escalation = { route: decision.route, goal: decision.goal, hint: repairHintForEvaluation(failing, decision.repairHint) };
|
|
377
419
|
stepStatus = "escalated";
|
|
378
420
|
emit({
|
|
379
421
|
type: "escalated",
|
|
380
422
|
message: `Escalating ${route.replaceAll("_", " ")} → ${decision.route.replaceAll("_", " ")}.`,
|
|
381
423
|
route,
|
|
382
|
-
payload: decision,
|
|
424
|
+
payload: { ...decision, budgetUsage: cascadeBudgetTrace(budgets) },
|
|
383
425
|
});
|
|
384
426
|
break;
|
|
385
427
|
}
|
|
@@ -426,6 +468,7 @@ export class AgentRunEngine {
|
|
|
426
468
|
id: stepId,
|
|
427
469
|
index: stepCount,
|
|
428
470
|
route,
|
|
471
|
+
resolvedRoute: result.resolvedRoute,
|
|
429
472
|
goal: planned.goal,
|
|
430
473
|
successCriteria: planned.successCriteria,
|
|
431
474
|
status: outcome.status === "blocked" ? "blocked" : stepStatus,
|
|
@@ -462,6 +505,9 @@ export class AgentRunEngine {
|
|
|
462
505
|
finalStep = step;
|
|
463
506
|
finalResult = result;
|
|
464
507
|
finalOutcome = outcome;
|
|
508
|
+
if (outcome.status !== "blocked" && typeof result.answer === "string" && result.answer.trim().length > 0) {
|
|
509
|
+
bestAnswerResult = result;
|
|
510
|
+
}
|
|
465
511
|
if (outcome.status === "blocked")
|
|
466
512
|
break;
|
|
467
513
|
if (isTerminalSuccess(route, outcome))
|
|
@@ -480,7 +526,8 @@ export class AgentRunEngine {
|
|
|
480
526
|
finalResult,
|
|
481
527
|
finalOutcome,
|
|
482
528
|
clarifyOutcome,
|
|
483
|
-
|
|
529
|
+
bestAnswerResult,
|
|
530
|
+
budgetUsage: cascadeBudgetTrace(budgets),
|
|
484
531
|
events,
|
|
485
532
|
});
|
|
486
533
|
emit({
|
|
@@ -489,6 +536,7 @@ export class AgentRunEngine {
|
|
|
489
536
|
route: run.route,
|
|
490
537
|
status: run.status,
|
|
491
538
|
trustState: run.trustState,
|
|
539
|
+
payload: { budgetUsage: run.budgetUsage },
|
|
492
540
|
});
|
|
493
541
|
run.completedAt = this.timestamp();
|
|
494
542
|
await this.store?.save(run);
|
|
@@ -528,6 +576,8 @@ export class AgentRunEngine {
|
|
|
528
576
|
events,
|
|
529
577
|
nextActions: [],
|
|
530
578
|
repairAttempts: 0,
|
|
579
|
+
escalationAttempts: 0,
|
|
580
|
+
budgetUsage: cascadeBudgetTrace(createCascadeBudgetState(this.budgetModel)),
|
|
531
581
|
};
|
|
532
582
|
await this.store?.save(run);
|
|
533
583
|
return run;
|
|
@@ -535,6 +585,8 @@ export class AgentRunEngine {
|
|
|
535
585
|
}
|
|
536
586
|
finalizeRun(input) {
|
|
537
587
|
const { finalStep, finalResult, finalOutcome } = input;
|
|
588
|
+
const repairAttempts = input.budgetUsage.usage.laneExecutionAttemptsUsed;
|
|
589
|
+
const escalationAttempts = input.budgetUsage.usage.engineEscalationsUsed;
|
|
538
590
|
const completedAt = this.timestamp();
|
|
539
591
|
if (!finalStep || !finalResult || !finalOutcome) {
|
|
540
592
|
// No step produced a usable result (e.g. an empty plan). Treat as blocked.
|
|
@@ -563,14 +615,21 @@ export class AgentRunEngine {
|
|
|
563
615
|
}],
|
|
564
616
|
events: input.events,
|
|
565
617
|
nextActions: [],
|
|
566
|
-
repairAttempts
|
|
618
|
+
repairAttempts,
|
|
619
|
+
escalationAttempts,
|
|
620
|
+
budgetUsage: input.budgetUsage,
|
|
567
621
|
};
|
|
568
622
|
}
|
|
569
|
-
const route = finalStep.route;
|
|
623
|
+
const route = finalResult.resolvedRoute ?? finalStep.resolvedRoute ?? finalStep.route;
|
|
570
624
|
// Aggregate artifacts across every accepted step so a multi-step plan
|
|
571
625
|
// (e.g. research → block draft) surfaces all of its durable work, while the
|
|
572
626
|
// status/trust/answer reflect the final step.
|
|
573
627
|
const artifacts = input.steps.flatMap((step) => step.artifacts);
|
|
628
|
+
// If the final step produced no user-facing answer (e.g. it only drafted an
|
|
629
|
+
// artifact), fall back to the last step that DID answer so the run never
|
|
630
|
+
// drops a data answer an earlier step already computed.
|
|
631
|
+
const finalHasAnswer = typeof finalResult.answer === "string" && finalResult.answer.trim().length > 0;
|
|
632
|
+
const answerSource = finalHasAnswer ? finalResult : (input.bestAnswerResult ?? finalResult);
|
|
574
633
|
return {
|
|
575
634
|
id: input.runId,
|
|
576
635
|
question: input.request.question,
|
|
@@ -586,13 +645,15 @@ export class AgentRunEngine {
|
|
|
586
645
|
plan: input.plan,
|
|
587
646
|
steps: input.steps,
|
|
588
647
|
summary: finalOutcome.summary,
|
|
589
|
-
answer: input.clarifyOutcome?.question ??
|
|
590
|
-
answerKind:
|
|
648
|
+
answer: input.clarifyOutcome?.question ?? answerSource.answer,
|
|
649
|
+
answerKind: answerSource.answerKind ?? "governed",
|
|
591
650
|
artifacts,
|
|
592
651
|
evaluations: finalStep.evaluations,
|
|
593
652
|
events: input.events,
|
|
594
653
|
nextActions: applyAudienceToNextActions(finalResult.nextActions ?? defaultNextActions(route, finalOutcome.status), resolveAudience(input.request), finalOutcome.status),
|
|
595
|
-
repairAttempts: finalResult.repairAttempts ??
|
|
654
|
+
repairAttempts: finalResult.repairAttempts ?? repairAttempts,
|
|
655
|
+
escalationAttempts,
|
|
656
|
+
budgetUsage: input.budgetUsage,
|
|
596
657
|
};
|
|
597
658
|
}
|
|
598
659
|
evaluate(context) {
|
|
@@ -635,6 +696,7 @@ function computeStepOutcome(route, result, evaluations, request, isClarify, clar
|
|
|
635
696
|
artifacts,
|
|
636
697
|
stopReason,
|
|
637
698
|
summary: result.summary ?? fallback.summary,
|
|
699
|
+
...(result.answerTier ? { terminalTier: result.answerTier } : {}),
|
|
638
700
|
};
|
|
639
701
|
}
|
|
640
702
|
function isTerminalSuccess(route, outcome) {
|
|
@@ -644,7 +706,15 @@ function isTerminalSuccess(route, outcome) {
|
|
|
644
706
|
// run loop ends naturally when the planned queue empties or maxSteps is hit.
|
|
645
707
|
if (route === "conversation" && outcome.status === "completed")
|
|
646
708
|
return true;
|
|
647
|
-
|
|
709
|
+
if (route === "certified_answer" && outcome.status === "completed")
|
|
710
|
+
return true;
|
|
711
|
+
// A governed SEMANTIC answer (deterministically compiled from the semantic layer)
|
|
712
|
+
// is as terminal as a certified block for a metric question — no further step adds
|
|
713
|
+
// trust. Generated SQL (generated_sql / business_context) stays NON-terminal so a
|
|
714
|
+
// multi-step plan can still chain a research step.
|
|
715
|
+
if (outcome.status === "completed" && outcome.terminalTier === "semantic_metric")
|
|
716
|
+
return true;
|
|
717
|
+
return false;
|
|
648
718
|
}
|
|
649
719
|
function describeReplan(decision) {
|
|
650
720
|
switch (decision.decision) {
|
|
@@ -658,6 +728,12 @@ function describeReplan(decision) {
|
|
|
658
728
|
return "Accepting the current result.";
|
|
659
729
|
}
|
|
660
730
|
}
|
|
731
|
+
function repairHintForEvaluation(evaluation, plannerHint) {
|
|
732
|
+
return evaluation.repairAction?.hint
|
|
733
|
+
?? plannerHint
|
|
734
|
+
?? evaluation.suggestedRepair
|
|
735
|
+
?? "Revise and retry.";
|
|
736
|
+
}
|
|
661
737
|
/**
|
|
662
738
|
* The default, fully deterministic planner. Produces a single-step plan from the
|
|
663
739
|
* existing route selection and drives repair/escalation from failing evaluations.
|
|
@@ -726,6 +802,19 @@ export function defaultSuccessCriteria(route) {
|
|
|
726
802
|
}
|
|
727
803
|
}
|
|
728
804
|
function buildIntentDecision(request) {
|
|
805
|
+
const hasConversationContext = Boolean(request.conversationContext && Object.keys(request.conversationContext).length > 0);
|
|
806
|
+
const conversationalKind = classifyConversationalTurn(request.question, Boolean((request.history?.length ?? 0) > 0 || hasConversationContext));
|
|
807
|
+
if (request.requestedMode === "ask" && conversationalKind && hasConversationContext) {
|
|
808
|
+
return {
|
|
809
|
+
action: "converse",
|
|
810
|
+
confidence: 0.9,
|
|
811
|
+
reason: "This asks about the prior conversation, so I will answer from conversation context instead of querying governed data.",
|
|
812
|
+
conversationalKind,
|
|
813
|
+
category: "conversational",
|
|
814
|
+
source: "heuristic",
|
|
815
|
+
followsUp: true,
|
|
816
|
+
};
|
|
817
|
+
}
|
|
729
818
|
const forcedAction = requestedModeToAction(request.requestedMode);
|
|
730
819
|
if (forcedAction) {
|
|
731
820
|
return {
|
|
@@ -754,42 +843,7 @@ function requestedModeToAction(mode) {
|
|
|
754
843
|
return undefined;
|
|
755
844
|
}
|
|
756
845
|
export function selectRoute(request, decision) {
|
|
757
|
-
|
|
758
|
-
if (mode === "research")
|
|
759
|
-
return "research";
|
|
760
|
-
if (mode === "sql")
|
|
761
|
-
return "sql_cell";
|
|
762
|
-
if (mode === "block")
|
|
763
|
-
return "dql_block_draft";
|
|
764
|
-
if (mode === "app")
|
|
765
|
-
return "app_build";
|
|
766
|
-
// A conversational turn is decided first — before the authoring/app regexes —
|
|
767
|
-
// so a greeting never trips "create a … block" style matches.
|
|
768
|
-
if (decision.action === "converse")
|
|
769
|
-
return "conversation";
|
|
770
|
-
const question = request.question;
|
|
771
|
-
if (looksLikeDqlBlockRequest(question))
|
|
772
|
-
return "dql_block_draft";
|
|
773
|
-
if (looksLikeSqlCellRequest(question))
|
|
774
|
-
return "sql_cell";
|
|
775
|
-
if (looksLikeComposeApp(question))
|
|
776
|
-
return "app_build";
|
|
777
|
-
if (decision.action === "compose_app")
|
|
778
|
-
return "app_build";
|
|
779
|
-
if (decision.action === "investigate")
|
|
780
|
-
return "research";
|
|
781
|
-
if (decision.action === "clarify")
|
|
782
|
-
return "clarify";
|
|
783
|
-
const certifiedScore = request.signals?.certifiedScore ?? 0;
|
|
784
|
-
if (certifiedScore >= CERTIFIED_MATCH_THRESHOLD)
|
|
785
|
-
return "certified_answer";
|
|
786
|
-
return "generated_answer";
|
|
787
|
-
}
|
|
788
|
-
function looksLikeSqlCellRequest(question) {
|
|
789
|
-
return /\b(sql|query|notebook cell|cell draft|write a select|generate a query)\b/i.test(question);
|
|
790
|
-
}
|
|
791
|
-
function looksLikeDqlBlockRequest(question) {
|
|
792
|
-
return /\b(dql block|block draft|draft block|create.*block|turn .* into .*block|promote .* block)\b/i.test(question);
|
|
846
|
+
return selectCascadeRunRoute(request, decision);
|
|
793
847
|
}
|
|
794
848
|
function defaultExecutorResult(route, request, decision) {
|
|
795
849
|
const fallback = defaultOutcome(route);
|
|
@@ -834,7 +888,7 @@ function defaultOutcome(route) {
|
|
|
834
888
|
};
|
|
835
889
|
}
|
|
836
890
|
}
|
|
837
|
-
function defaultEvaluations(route,
|
|
891
|
+
function defaultEvaluations(route, _request, decision) {
|
|
838
892
|
// A conversational reply carries no governance checks — it renders as plain chat.
|
|
839
893
|
if (route === "conversation")
|
|
840
894
|
return [];
|
|
@@ -849,9 +903,9 @@ function defaultEvaluations(route, request, decision) {
|
|
|
849
903
|
base.push({
|
|
850
904
|
id: "certified-context",
|
|
851
905
|
label: "Certified context",
|
|
852
|
-
passed:
|
|
853
|
-
severity: "
|
|
854
|
-
message: "
|
|
906
|
+
passed: true,
|
|
907
|
+
severity: "info",
|
|
908
|
+
message: "Certified status must come from the route executor or resolved answer-loop tier, not token-overlap routing.",
|
|
855
909
|
});
|
|
856
910
|
}
|
|
857
911
|
if (route === "generated_answer" || route === "sql_cell") {
|
|
@@ -976,12 +1030,12 @@ function defaultNextActions(route, status) {
|
|
|
976
1030
|
}
|
|
977
1031
|
if (route === "research") {
|
|
978
1032
|
return [
|
|
979
|
-
{ id: "
|
|
980
|
-
{ id: "
|
|
1033
|
+
{ id: "create-block", label: "Review DQL draft", route: "dql_block_draft", artifactKind: "dql_block_draft" },
|
|
1034
|
+
{ id: "insert-sql", label: "Insert SQL preview", route: "sql_cell", artifactKind: "sql_cell" },
|
|
981
1035
|
];
|
|
982
1036
|
}
|
|
983
1037
|
if (route === "sql_cell") {
|
|
984
|
-
return [{ id: "create-block", label: "
|
|
1038
|
+
return [{ id: "create-block", label: "Review as DQL draft", route: "dql_block_draft", artifactKind: "dql_block_draft" }];
|
|
985
1039
|
}
|
|
986
1040
|
if (route === "dql_block_draft") {
|
|
987
1041
|
return [{ id: "open-review", label: "Open review checklist", artifactKind: "dql_block_draft" }];
|