@duckcodeailabs/dql-agent 1.6.30 → 1.6.32
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 +52 -6
- package/dist/agent-run-engine.d.ts.map +1 -1
- package/dist/agent-run-engine.js +159 -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 +117 -8
- package/dist/answer-loop.d.ts.map +1 -1
- package/dist/answer-loop.js +1690 -1302
- 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 +47 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +104 -13
- 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 +151 -28
- package/dist/providers/claude.js.map +1 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +20 -0
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts +3 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -0
- 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 +156 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/reasoning-effort.d.ts +46 -0
- package/dist/providers/reasoning-effort.d.ts.map +1 -0
- package/dist/providers/reasoning-effort.js +81 -0
- package/dist/providers/reasoning-effort.js.map +1 -0
- 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 +29 -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,5 +1,7 @@
|
|
|
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";
|
|
4
|
+
import type { ReasoningEffort } from "./providers/reasoning-effort.js";
|
|
3
5
|
export type AgentRunRequestedMode = "auto" | "ask" | "research" | "sql" | "block" | "app";
|
|
4
6
|
/**
|
|
5
7
|
* Who the run serves. `analyst` (the Notebook) keeps every route, including
|
|
@@ -77,11 +79,18 @@ export interface AgentRunRequest {
|
|
|
77
79
|
signals?: IntentSignals;
|
|
78
80
|
selectedObject?: AgentRunSelectedObject;
|
|
79
81
|
workspaceContext?: Record<string, unknown>;
|
|
82
|
+
conversationContext?: Record<string, unknown>;
|
|
80
83
|
history?: Array<{
|
|
81
84
|
role: "user" | "assistant";
|
|
82
85
|
text: string;
|
|
83
86
|
}>;
|
|
87
|
+
/** Server-side conversation thread this run belongs to (persistence + resume). */
|
|
88
|
+
threadId?: string;
|
|
84
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;
|
|
85
94
|
}
|
|
86
95
|
export interface AgentRunEvent {
|
|
87
96
|
id: string;
|
|
@@ -113,6 +122,7 @@ export interface AgentRunStep {
|
|
|
113
122
|
id: string;
|
|
114
123
|
index: number;
|
|
115
124
|
route: AgentRunRoute;
|
|
125
|
+
resolvedRoute?: AgentRunRoute;
|
|
116
126
|
goal: string;
|
|
117
127
|
successCriteria: string[];
|
|
118
128
|
status: AgentRunStepStatus;
|
|
@@ -143,7 +153,12 @@ export interface AgentRun {
|
|
|
143
153
|
evaluations: AgentRunEvaluation[];
|
|
144
154
|
events: AgentRunEvent[];
|
|
145
155
|
nextActions: AgentRunNextAction[];
|
|
156
|
+
/** Same-lane repair reruns. Escalations are tracked separately. */
|
|
146
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;
|
|
147
162
|
}
|
|
148
163
|
export interface AgentRouteExecutionContext {
|
|
149
164
|
runId: string;
|
|
@@ -170,6 +185,18 @@ export interface AgentRouteExecutionContext {
|
|
|
170
185
|
export interface AgentRouteExecutorResult {
|
|
171
186
|
summary?: string;
|
|
172
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;
|
|
173
200
|
/** How to read `answer` for trust; defaults to "governed". */
|
|
174
201
|
answerKind?: AgentRunAnswerKind;
|
|
175
202
|
status?: AgentRunStatus;
|
|
@@ -207,6 +234,9 @@ export interface AgentRunReplanInput {
|
|
|
207
234
|
attemptsUsed: number;
|
|
208
235
|
repairAttemptsUsed: number;
|
|
209
236
|
maxRepairAttempts: number;
|
|
237
|
+
engineEscalationsUsed?: number;
|
|
238
|
+
maxEngineEscalations?: number;
|
|
239
|
+
budgetUsage?: CascadeBudgetTrace;
|
|
210
240
|
}
|
|
211
241
|
export type AgentRunReplanDecision = {
|
|
212
242
|
decision: "accept";
|
|
@@ -249,6 +279,8 @@ export interface AgentRunEngineOptions {
|
|
|
249
279
|
idGenerator?: () => string;
|
|
250
280
|
now?: () => Date;
|
|
251
281
|
maxRepairAttempts?: number;
|
|
282
|
+
maxEngineEscalations?: number;
|
|
283
|
+
budgets?: PartialCascadeBudgetModel;
|
|
252
284
|
maxSteps?: number;
|
|
253
285
|
}
|
|
254
286
|
/**
|
|
@@ -261,12 +293,26 @@ export declare function resolveAudience(request: AgentRunRequest): AgentRunAudie
|
|
|
261
293
|
/** A stakeholder may never land on an authoring route — collapse it to a governed answer. */
|
|
262
294
|
export declare function constrainRouteForAudience(route: AgentRunRoute, audience: AgentRunAudience): AgentRunRoute;
|
|
263
295
|
/**
|
|
264
|
-
* "Answer anyway, labeled" —
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
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.
|
|
305
|
+
*/
|
|
306
|
+
export declare function answerAnywayRoute(route: AgentRunRoute, request: AgentRunRequest, audience: AgentRunAudience, decision?: IntentDecision): AgentRunRoute;
|
|
307
|
+
/**
|
|
308
|
+
* Task-adaptive reasoning effort per route — the DQL differentiator. Cheap,
|
|
309
|
+
* mechanical routes (chat, clarify, blocked, a pre-written certified lookup) run
|
|
310
|
+
* `low`; correctness-critical routes that generate/validate SQL or investigate
|
|
311
|
+
* run `high`; app assembly sits at `medium` (its gap-fill sub-answers route
|
|
312
|
+
* through `generated_answer` and pick up `high` on their own). The host clamps
|
|
313
|
+
* this by the provider's Settings ceiling before sending it to the model.
|
|
268
314
|
*/
|
|
269
|
-
export declare function
|
|
315
|
+
export declare function routeReasoningEffort(route: AgentRunRoute): ReasoningEffort;
|
|
270
316
|
/** Audience-aware escalation target: stakeholders never escalate into authoring. */
|
|
271
317
|
export declare function escalationRouteFor(route: AgentRunRoute, audience: AgentRunAudience): AgentRunRoute | undefined;
|
|
272
318
|
export declare class InMemoryAgentRunStore implements AgentRunStore {
|
|
@@ -297,7 +343,7 @@ export declare class AgentRunEngine {
|
|
|
297
343
|
private readonly store?;
|
|
298
344
|
private readonly idGenerator;
|
|
299
345
|
private readonly now;
|
|
300
|
-
private readonly
|
|
346
|
+
private readonly budgetModel;
|
|
301
347
|
private readonly maxSteps;
|
|
302
348
|
constructor(options?: AgentRunEngineOptions);
|
|
303
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,51 @@ 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";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Task-adaptive reasoning effort per route — the DQL differentiator. Cheap,
|
|
52
|
+
* mechanical routes (chat, clarify, blocked, a pre-written certified lookup) run
|
|
53
|
+
* `low`; correctness-critical routes that generate/validate SQL or investigate
|
|
54
|
+
* run `high`; app assembly sits at `medium` (its gap-fill sub-answers route
|
|
55
|
+
* through `generated_answer` and pick up `high` on their own). The host clamps
|
|
56
|
+
* this by the provider's Settings ceiling before sending it to the model.
|
|
57
|
+
*/
|
|
58
|
+
export function routeReasoningEffort(route) {
|
|
59
|
+
switch (route) {
|
|
60
|
+
case "conversation":
|
|
61
|
+
case "clarify":
|
|
62
|
+
case "certified_answer":
|
|
63
|
+
case "blocked":
|
|
64
|
+
return "low";
|
|
65
|
+
case "app_build":
|
|
66
|
+
return "medium";
|
|
67
|
+
case "generated_answer":
|
|
68
|
+
case "research":
|
|
69
|
+
case "sql_cell":
|
|
70
|
+
case "dql_block_draft":
|
|
71
|
+
return "high";
|
|
72
|
+
default:
|
|
73
|
+
return "medium";
|
|
74
|
+
}
|
|
40
75
|
}
|
|
41
76
|
/** Audience-aware escalation target: stakeholders never escalate into authoring. */
|
|
42
77
|
export function escalationRouteFor(route, audience) {
|
|
@@ -145,7 +180,7 @@ export class AgentRunEngine {
|
|
|
145
180
|
store;
|
|
146
181
|
idGenerator;
|
|
147
182
|
now;
|
|
148
|
-
|
|
183
|
+
budgetModel;
|
|
149
184
|
maxSteps;
|
|
150
185
|
constructor(options = {}) {
|
|
151
186
|
this.executors = options.executors ?? {};
|
|
@@ -155,7 +190,14 @@ export class AgentRunEngine {
|
|
|
155
190
|
this.store = options.store;
|
|
156
191
|
this.idGenerator = options.idGenerator ?? randomUUID;
|
|
157
192
|
this.now = options.now ?? (() => new Date());
|
|
158
|
-
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
|
+
};
|
|
159
201
|
this.maxSteps = Math.max(1, options.maxSteps ?? DEFAULT_MAX_STEPS);
|
|
160
202
|
}
|
|
161
203
|
/**
|
|
@@ -202,7 +244,7 @@ export class AgentRunEngine {
|
|
|
202
244
|
});
|
|
203
245
|
const audience = resolveAudience(request);
|
|
204
246
|
const routeDecision = await this.decideRoute(request);
|
|
205
|
-
const defaultRoute = answerAnywayRoute(constrainRouteForAudience(selectRoute(request, routeDecision), audience), request, audience);
|
|
247
|
+
const defaultRoute = answerAnywayRoute(constrainRouteForAudience(selectRoute(request, routeDecision), audience), request, audience, routeDecision);
|
|
206
248
|
try {
|
|
207
249
|
const plan = await this.planner.plan({
|
|
208
250
|
request,
|
|
@@ -223,14 +265,18 @@ export class AgentRunEngine {
|
|
|
223
265
|
// without explicit missing context.
|
|
224
266
|
const queue = plan.steps.map((step) => ({
|
|
225
267
|
...step,
|
|
226
|
-
route: answerAnywayRoute(constrainRouteForAudience(step.route, audience), request, audience),
|
|
268
|
+
route: answerAnywayRoute(constrainRouteForAudience(step.route, audience), request, audience, routeDecision),
|
|
227
269
|
}));
|
|
228
|
-
|
|
270
|
+
const budgets = createCascadeBudgetState(this.budgetModel);
|
|
229
271
|
let stepCount = 0;
|
|
230
272
|
let finalStep;
|
|
231
273
|
let finalResult;
|
|
232
274
|
let finalOutcome;
|
|
233
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;
|
|
234
280
|
while (queue.length > 0 && stepCount < this.maxSteps) {
|
|
235
281
|
const planned = queue.shift();
|
|
236
282
|
stepCount += 1;
|
|
@@ -273,7 +319,7 @@ export class AgentRunEngine {
|
|
|
273
319
|
request,
|
|
274
320
|
route,
|
|
275
321
|
routeDecision,
|
|
276
|
-
maxRepairAttempts:
|
|
322
|
+
maxRepairAttempts: budgets.limits.lane.execution,
|
|
277
323
|
attempt,
|
|
278
324
|
stepGoal: planned.goal,
|
|
279
325
|
priorEvaluations,
|
|
@@ -300,11 +346,6 @@ export class AgentRunEngine {
|
|
|
300
346
|
stepStatus = attempt > 0 ? "repaired" : "passed";
|
|
301
347
|
break;
|
|
302
348
|
}
|
|
303
|
-
// Out of modify budget — accept the best result we have.
|
|
304
|
-
if (repairAttemptsTotal >= this.maxRepairAttempts) {
|
|
305
|
-
stepStatus = "needs_review";
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
349
|
const currentStep = {
|
|
309
350
|
id: stepId,
|
|
310
351
|
index: stepCount,
|
|
@@ -323,8 +364,11 @@ export class AgentRunEngine {
|
|
|
323
364
|
currentStep,
|
|
324
365
|
remainingSteps: queue,
|
|
325
366
|
attemptsUsed: attempt,
|
|
326
|
-
repairAttemptsUsed:
|
|
327
|
-
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),
|
|
328
372
|
});
|
|
329
373
|
emit({
|
|
330
374
|
type: "replan.decided",
|
|
@@ -333,27 +377,51 @@ export class AgentRunEngine {
|
|
|
333
377
|
payload: decision,
|
|
334
378
|
});
|
|
335
379
|
if (decision.decision === "repair") {
|
|
336
|
-
|
|
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");
|
|
337
395
|
attempt += 1;
|
|
338
|
-
repairHint =
|
|
396
|
+
repairHint = nextRepairHint;
|
|
339
397
|
priorEvaluations = evaluations;
|
|
340
398
|
emit({
|
|
341
399
|
type: "repair.attempted",
|
|
342
400
|
message: `Repairing ${route.replaceAll("_", " ")}: ${repairHint}`,
|
|
343
401
|
route,
|
|
344
|
-
payload: { attempt, repairHint },
|
|
402
|
+
payload: { attempt, repairHint, budgetUsage: cascadeBudgetTrace(budgets) },
|
|
345
403
|
});
|
|
346
404
|
continue;
|
|
347
405
|
}
|
|
348
406
|
if (decision.decision === "escalate") {
|
|
349
|
-
|
|
350
|
-
|
|
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) };
|
|
351
419
|
stepStatus = "escalated";
|
|
352
420
|
emit({
|
|
353
421
|
type: "escalated",
|
|
354
422
|
message: `Escalating ${route.replaceAll("_", " ")} → ${decision.route.replaceAll("_", " ")}.`,
|
|
355
423
|
route,
|
|
356
|
-
payload: decision,
|
|
424
|
+
payload: { ...decision, budgetUsage: cascadeBudgetTrace(budgets) },
|
|
357
425
|
});
|
|
358
426
|
break;
|
|
359
427
|
}
|
|
@@ -400,6 +468,7 @@ export class AgentRunEngine {
|
|
|
400
468
|
id: stepId,
|
|
401
469
|
index: stepCount,
|
|
402
470
|
route,
|
|
471
|
+
resolvedRoute: result.resolvedRoute,
|
|
403
472
|
goal: planned.goal,
|
|
404
473
|
successCriteria: planned.successCriteria,
|
|
405
474
|
status: outcome.status === "blocked" ? "blocked" : stepStatus,
|
|
@@ -436,6 +505,9 @@ export class AgentRunEngine {
|
|
|
436
505
|
finalStep = step;
|
|
437
506
|
finalResult = result;
|
|
438
507
|
finalOutcome = outcome;
|
|
508
|
+
if (outcome.status !== "blocked" && typeof result.answer === "string" && result.answer.trim().length > 0) {
|
|
509
|
+
bestAnswerResult = result;
|
|
510
|
+
}
|
|
439
511
|
if (outcome.status === "blocked")
|
|
440
512
|
break;
|
|
441
513
|
if (isTerminalSuccess(route, outcome))
|
|
@@ -454,7 +526,8 @@ export class AgentRunEngine {
|
|
|
454
526
|
finalResult,
|
|
455
527
|
finalOutcome,
|
|
456
528
|
clarifyOutcome,
|
|
457
|
-
|
|
529
|
+
bestAnswerResult,
|
|
530
|
+
budgetUsage: cascadeBudgetTrace(budgets),
|
|
458
531
|
events,
|
|
459
532
|
});
|
|
460
533
|
emit({
|
|
@@ -463,6 +536,7 @@ export class AgentRunEngine {
|
|
|
463
536
|
route: run.route,
|
|
464
537
|
status: run.status,
|
|
465
538
|
trustState: run.trustState,
|
|
539
|
+
payload: { budgetUsage: run.budgetUsage },
|
|
466
540
|
});
|
|
467
541
|
run.completedAt = this.timestamp();
|
|
468
542
|
await this.store?.save(run);
|
|
@@ -502,6 +576,8 @@ export class AgentRunEngine {
|
|
|
502
576
|
events,
|
|
503
577
|
nextActions: [],
|
|
504
578
|
repairAttempts: 0,
|
|
579
|
+
escalationAttempts: 0,
|
|
580
|
+
budgetUsage: cascadeBudgetTrace(createCascadeBudgetState(this.budgetModel)),
|
|
505
581
|
};
|
|
506
582
|
await this.store?.save(run);
|
|
507
583
|
return run;
|
|
@@ -509,6 +585,8 @@ export class AgentRunEngine {
|
|
|
509
585
|
}
|
|
510
586
|
finalizeRun(input) {
|
|
511
587
|
const { finalStep, finalResult, finalOutcome } = input;
|
|
588
|
+
const repairAttempts = input.budgetUsage.usage.laneExecutionAttemptsUsed;
|
|
589
|
+
const escalationAttempts = input.budgetUsage.usage.engineEscalationsUsed;
|
|
512
590
|
const completedAt = this.timestamp();
|
|
513
591
|
if (!finalStep || !finalResult || !finalOutcome) {
|
|
514
592
|
// No step produced a usable result (e.g. an empty plan). Treat as blocked.
|
|
@@ -537,14 +615,21 @@ export class AgentRunEngine {
|
|
|
537
615
|
}],
|
|
538
616
|
events: input.events,
|
|
539
617
|
nextActions: [],
|
|
540
|
-
repairAttempts
|
|
618
|
+
repairAttempts,
|
|
619
|
+
escalationAttempts,
|
|
620
|
+
budgetUsage: input.budgetUsage,
|
|
541
621
|
};
|
|
542
622
|
}
|
|
543
|
-
const route = finalStep.route;
|
|
623
|
+
const route = finalResult.resolvedRoute ?? finalStep.resolvedRoute ?? finalStep.route;
|
|
544
624
|
// Aggregate artifacts across every accepted step so a multi-step plan
|
|
545
625
|
// (e.g. research → block draft) surfaces all of its durable work, while the
|
|
546
626
|
// status/trust/answer reflect the final step.
|
|
547
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);
|
|
548
633
|
return {
|
|
549
634
|
id: input.runId,
|
|
550
635
|
question: input.request.question,
|
|
@@ -560,13 +645,15 @@ export class AgentRunEngine {
|
|
|
560
645
|
plan: input.plan,
|
|
561
646
|
steps: input.steps,
|
|
562
647
|
summary: finalOutcome.summary,
|
|
563
|
-
answer: input.clarifyOutcome?.question ??
|
|
564
|
-
answerKind:
|
|
648
|
+
answer: input.clarifyOutcome?.question ?? answerSource.answer,
|
|
649
|
+
answerKind: answerSource.answerKind ?? "governed",
|
|
565
650
|
artifacts,
|
|
566
651
|
evaluations: finalStep.evaluations,
|
|
567
652
|
events: input.events,
|
|
568
653
|
nextActions: applyAudienceToNextActions(finalResult.nextActions ?? defaultNextActions(route, finalOutcome.status), resolveAudience(input.request), finalOutcome.status),
|
|
569
|
-
repairAttempts: finalResult.repairAttempts ??
|
|
654
|
+
repairAttempts: finalResult.repairAttempts ?? repairAttempts,
|
|
655
|
+
escalationAttempts,
|
|
656
|
+
budgetUsage: input.budgetUsage,
|
|
570
657
|
};
|
|
571
658
|
}
|
|
572
659
|
evaluate(context) {
|
|
@@ -609,6 +696,7 @@ function computeStepOutcome(route, result, evaluations, request, isClarify, clar
|
|
|
609
696
|
artifacts,
|
|
610
697
|
stopReason,
|
|
611
698
|
summary: result.summary ?? fallback.summary,
|
|
699
|
+
...(result.answerTier ? { terminalTier: result.answerTier } : {}),
|
|
612
700
|
};
|
|
613
701
|
}
|
|
614
702
|
function isTerminalSuccess(route, outcome) {
|
|
@@ -618,7 +706,15 @@ function isTerminalSuccess(route, outcome) {
|
|
|
618
706
|
// run loop ends naturally when the planned queue empties or maxSteps is hit.
|
|
619
707
|
if (route === "conversation" && outcome.status === "completed")
|
|
620
708
|
return true;
|
|
621
|
-
|
|
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;
|
|
622
718
|
}
|
|
623
719
|
function describeReplan(decision) {
|
|
624
720
|
switch (decision.decision) {
|
|
@@ -632,6 +728,12 @@ function describeReplan(decision) {
|
|
|
632
728
|
return "Accepting the current result.";
|
|
633
729
|
}
|
|
634
730
|
}
|
|
731
|
+
function repairHintForEvaluation(evaluation, plannerHint) {
|
|
732
|
+
return evaluation.repairAction?.hint
|
|
733
|
+
?? plannerHint
|
|
734
|
+
?? evaluation.suggestedRepair
|
|
735
|
+
?? "Revise and retry.";
|
|
736
|
+
}
|
|
635
737
|
/**
|
|
636
738
|
* The default, fully deterministic planner. Produces a single-step plan from the
|
|
637
739
|
* existing route selection and drives repair/escalation from failing evaluations.
|
|
@@ -700,6 +802,19 @@ export function defaultSuccessCriteria(route) {
|
|
|
700
802
|
}
|
|
701
803
|
}
|
|
702
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
|
+
}
|
|
703
818
|
const forcedAction = requestedModeToAction(request.requestedMode);
|
|
704
819
|
if (forcedAction) {
|
|
705
820
|
return {
|
|
@@ -728,42 +843,7 @@ function requestedModeToAction(mode) {
|
|
|
728
843
|
return undefined;
|
|
729
844
|
}
|
|
730
845
|
export function selectRoute(request, decision) {
|
|
731
|
-
|
|
732
|
-
if (mode === "research")
|
|
733
|
-
return "research";
|
|
734
|
-
if (mode === "sql")
|
|
735
|
-
return "sql_cell";
|
|
736
|
-
if (mode === "block")
|
|
737
|
-
return "dql_block_draft";
|
|
738
|
-
if (mode === "app")
|
|
739
|
-
return "app_build";
|
|
740
|
-
// A conversational turn is decided first — before the authoring/app regexes —
|
|
741
|
-
// so a greeting never trips "create a … block" style matches.
|
|
742
|
-
if (decision.action === "converse")
|
|
743
|
-
return "conversation";
|
|
744
|
-
const question = request.question;
|
|
745
|
-
if (looksLikeDqlBlockRequest(question))
|
|
746
|
-
return "dql_block_draft";
|
|
747
|
-
if (looksLikeSqlCellRequest(question))
|
|
748
|
-
return "sql_cell";
|
|
749
|
-
if (looksLikeComposeApp(question))
|
|
750
|
-
return "app_build";
|
|
751
|
-
if (decision.action === "compose_app")
|
|
752
|
-
return "app_build";
|
|
753
|
-
if (decision.action === "investigate")
|
|
754
|
-
return "research";
|
|
755
|
-
if (decision.action === "clarify")
|
|
756
|
-
return "clarify";
|
|
757
|
-
const certifiedScore = request.signals?.certifiedScore ?? 0;
|
|
758
|
-
if (certifiedScore >= CERTIFIED_MATCH_THRESHOLD)
|
|
759
|
-
return "certified_answer";
|
|
760
|
-
return "generated_answer";
|
|
761
|
-
}
|
|
762
|
-
function looksLikeSqlCellRequest(question) {
|
|
763
|
-
return /\b(sql|query|notebook cell|cell draft|write a select|generate a query)\b/i.test(question);
|
|
764
|
-
}
|
|
765
|
-
function looksLikeDqlBlockRequest(question) {
|
|
766
|
-
return /\b(dql block|block draft|draft block|create.*block|turn .* into .*block|promote .* block)\b/i.test(question);
|
|
846
|
+
return selectCascadeRunRoute(request, decision);
|
|
767
847
|
}
|
|
768
848
|
function defaultExecutorResult(route, request, decision) {
|
|
769
849
|
const fallback = defaultOutcome(route);
|
|
@@ -808,7 +888,7 @@ function defaultOutcome(route) {
|
|
|
808
888
|
};
|
|
809
889
|
}
|
|
810
890
|
}
|
|
811
|
-
function defaultEvaluations(route,
|
|
891
|
+
function defaultEvaluations(route, _request, decision) {
|
|
812
892
|
// A conversational reply carries no governance checks — it renders as plain chat.
|
|
813
893
|
if (route === "conversation")
|
|
814
894
|
return [];
|
|
@@ -823,9 +903,9 @@ function defaultEvaluations(route, request, decision) {
|
|
|
823
903
|
base.push({
|
|
824
904
|
id: "certified-context",
|
|
825
905
|
label: "Certified context",
|
|
826
|
-
passed:
|
|
827
|
-
severity: "
|
|
828
|
-
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.",
|
|
829
909
|
});
|
|
830
910
|
}
|
|
831
911
|
if (route === "generated_answer" || route === "sql_cell") {
|
|
@@ -950,12 +1030,12 @@ function defaultNextActions(route, status) {
|
|
|
950
1030
|
}
|
|
951
1031
|
if (route === "research") {
|
|
952
1032
|
return [
|
|
953
|
-
{ id: "
|
|
954
|
-
{ 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" },
|
|
955
1035
|
];
|
|
956
1036
|
}
|
|
957
1037
|
if (route === "sql_cell") {
|
|
958
|
-
return [{ id: "create-block", label: "
|
|
1038
|
+
return [{ id: "create-block", label: "Review as DQL draft", route: "dql_block_draft", artifactKind: "dql_block_draft" }];
|
|
959
1039
|
}
|
|
960
1040
|
if (route === "dql_block_draft") {
|
|
961
1041
|
return [{ id: "open-review", label: "Open review checklist", artifactKind: "dql_block_draft" }];
|