@duckcodeailabs/dql-agent 1.10.2 → 1.10.4

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.
@@ -50,6 +50,74 @@ import { buildAnalyticalResultFacts, renderDeterministicAnalyticalNarrative, val
50
50
  import { resolveAnalyticalPeriods, } from './analytical-period-resolution.js';
51
51
  import { classifyAnalyticalFailure, createAnalyticalFailure, } from './analytical-failure-repair.js';
52
52
  import { QUICK_PROMPT_CONTEXT_BUDGET, canUseLaneRepair, cascadeBudgetTrace, createCascadeBudgetState, deepAlternativeCountForQuestion, promptContextBudgetForQuestion, proposalToolBudgetForQuestion, recordLaneRepair, } from './cascade/budgets.js';
53
+ function semanticCompilerFailure(error) {
54
+ const record = error && typeof error === 'object' ? error : undefined;
55
+ const message = error instanceof Error ? error.message : String(error);
56
+ const details = record?.details && typeof record.details === 'object'
57
+ ? record.details
58
+ : undefined;
59
+ const trace = record?.semanticTrace && typeof record.semanticTrace === 'object'
60
+ ? record.semanticTrace
61
+ : details?.semanticTrace && typeof details.semanticTrace === 'object'
62
+ ? details.semanticTrace
63
+ : undefined;
64
+ const rawCandidates = Array.isArray(details?.candidates)
65
+ ? details.candidates
66
+ : Array.isArray(trace?.failure?.candidates)
67
+ ? trace.failure.candidates
68
+ : [];
69
+ const candidates = rawCandidates.flatMap((candidate) => {
70
+ if (!candidate || typeof candidate !== 'object')
71
+ return [];
72
+ const value = candidate;
73
+ if (typeof value.id !== 'string' || typeof value.label !== 'string')
74
+ return [];
75
+ return [{
76
+ id: value.id,
77
+ label: value.label,
78
+ ...(typeof value.description === 'string' ? { description: value.description } : {}),
79
+ kind: 'semantic_entity_path',
80
+ }];
81
+ });
82
+ return {
83
+ message,
84
+ ...(typeof record?.code === 'string' ? { code: record.code } : {}),
85
+ ...(trace ? { trace } : {}),
86
+ ...(candidates.length > 0 ? { candidates } : {}),
87
+ };
88
+ }
89
+ function semanticTraceAfterExecution(trace, input) {
90
+ if (!trace)
91
+ return undefined;
92
+ const executionStatus = input.error ? 'failed' : input.executed ? 'completed' : 'not_started';
93
+ const executionDetail = input.error
94
+ ? `Warehouse execution failed: ${input.error}`
95
+ : input.executed
96
+ ? 'The authorized warehouse query executed and returned a result.'
97
+ : 'The compiler produced SQL, but execution was not requested.';
98
+ return {
99
+ ...trace,
100
+ ...(input.result?.semanticTargetBinding
101
+ ? { targetBinding: input.result.semanticTargetBinding }
102
+ : {}),
103
+ ...(input.result?.semanticExecutionReceipt
104
+ ? { executionReceipt: input.result.semanticExecutionReceipt }
105
+ : {}),
106
+ status: input.error ? 'failed' : trace.status,
107
+ steps: trace.steps.map((step) => step.id === 'execute_query'
108
+ ? { ...step, status: executionStatus, detail: executionDetail }
109
+ : step),
110
+ ...(input.error
111
+ ? {
112
+ failure: {
113
+ code: 'EXECUTION_FAILED',
114
+ phase: 'execution',
115
+ message: input.error,
116
+ },
117
+ }
118
+ : {}),
119
+ };
120
+ }
53
121
  /**
54
122
  * Physical column names whose sampled runtime values include `value`. Used by the
55
123
  * semantic bridge to bind a filter literal to the dimension that actually carries
@@ -1623,6 +1691,7 @@ async function runAnswerLoop(input) {
1623
1691
  const semanticBridgeToolCalls = [];
1624
1692
  let semanticBridgeAnswer;
1625
1693
  let semanticRuntimeFailure;
1694
+ let semanticExecutionTrace;
1626
1695
  let semanticRuntimeCompiledAnswer = false;
1627
1696
  if (authoritativeSemanticBinding && input.semanticLayer) {
1628
1697
  const selection = authoritativeSemanticBinding.selection;
@@ -1636,6 +1705,7 @@ async function runAnswerLoop(input) {
1636
1705
  if (!semanticBridgeAnswer && input.semanticQueryCompiler) {
1637
1706
  try {
1638
1707
  const compiled = await input.semanticQueryCompiler(selection);
1708
+ semanticExecutionTrace = compiled.trace;
1639
1709
  semanticBridgeAnswer = composeSemanticQueryFromCompiledMembers({
1640
1710
  semanticLayer: input.semanticLayer,
1641
1711
  question,
@@ -1645,7 +1715,8 @@ async function runAnswerLoop(input) {
1645
1715
  semanticRuntimeCompiledAnswer = Boolean(semanticBridgeAnswer && compiled.engine !== 'native');
1646
1716
  }
1647
1717
  catch (error) {
1648
- semanticRuntimeFailure = error instanceof Error ? error.message : String(error);
1718
+ semanticRuntimeFailure = semanticCompilerFailure(error);
1719
+ semanticExecutionTrace = semanticRuntimeFailure.trace;
1649
1720
  }
1650
1721
  }
1651
1722
  if (semanticBridgeAnswer) {
@@ -1658,7 +1729,9 @@ async function runAnswerLoop(input) {
1658
1729
  });
1659
1730
  }
1660
1731
  else if (!semanticRuntimeFailure) {
1661
- semanticRuntimeFailure = `The exact plan ${authoritativeSemanticBinding.planId} is not composable by the pinned semantic runtime.`;
1732
+ semanticRuntimeFailure = {
1733
+ message: `The exact plan ${authoritativeSemanticBinding.planId} is not composable by the pinned semantic runtime.`,
1734
+ };
1662
1735
  }
1663
1736
  }
1664
1737
  if (!authoritativeSemanticBinding && input.semanticLayer && semanticMetricMatch) {
@@ -1688,6 +1761,7 @@ async function runAnswerLoop(input) {
1688
1761
  const selection = { metrics: [matchedName], dimensions: [] };
1689
1762
  try {
1690
1763
  const compiled = await input.semanticQueryCompiler(selection);
1764
+ semanticExecutionTrace = compiled.trace;
1691
1765
  semanticBridgeAnswer = composeSemanticQueryFromCompiledMembers({
1692
1766
  semanticLayer: input.semanticLayer,
1693
1767
  question,
@@ -1706,7 +1780,8 @@ async function runAnswerLoop(input) {
1706
1780
  }
1707
1781
  }
1708
1782
  catch (error) {
1709
- semanticRuntimeFailure = error instanceof Error ? error.message : String(error);
1783
+ semanticRuntimeFailure = semanticCompilerFailure(error);
1784
+ semanticExecutionTrace = semanticRuntimeFailure.trace;
1710
1785
  }
1711
1786
  }
1712
1787
  }
@@ -1740,6 +1815,7 @@ async function runAnswerLoop(input) {
1740
1815
  if (!composed && input.semanticQueryCompiler) {
1741
1816
  try {
1742
1817
  const compiled = await input.semanticQueryCompiler(selection);
1818
+ semanticExecutionTrace = compiled.trace;
1743
1819
  composed = composeSemanticQueryFromCompiledMembers({
1744
1820
  semanticLayer: bridgeLayer,
1745
1821
  question,
@@ -1758,7 +1834,8 @@ async function runAnswerLoop(input) {
1758
1834
  }
1759
1835
  }
1760
1836
  catch (error) {
1761
- semanticRuntimeFailure = error instanceof Error ? error.message : String(error);
1837
+ semanticRuntimeFailure = semanticCompilerFailure(error);
1838
+ semanticExecutionTrace = semanticRuntimeFailure.trace;
1762
1839
  }
1763
1840
  }
1764
1841
  return composed;
@@ -1812,7 +1889,11 @@ async function runAnswerLoop(input) {
1812
1889
  }
1813
1890
  }
1814
1891
  if (!semanticBridgeAnswer && semanticRuntimeFailure) {
1815
- const text = `The governed semantic metric was found, but its semantic runtime could not compile the request: ${compactSemanticRuntimeFailure(semanticRuntimeFailure)}`;
1892
+ const isPathAmbiguity = semanticRuntimeFailure.code === 'SEMANTIC_PATH_AMBIGUOUS'
1893
+ || semanticRuntimeFailure.trace?.failure?.code === 'SEMANTIC_PATH_AMBIGUOUS';
1894
+ const text = isPathAmbiguity
1895
+ ? semanticRuntimeFailure.message
1896
+ : `The governed semantic metric was found, but its semantic runtime could not compile the request: ${compactSemanticRuntimeFailure(semanticRuntimeFailure.message)}`;
1816
1897
  return {
1817
1898
  kind: 'no_answer',
1818
1899
  sourceTier: 'no_answer',
@@ -1821,10 +1902,17 @@ async function runAnswerLoop(input) {
1821
1902
  confidence: 0,
1822
1903
  text,
1823
1904
  answer: text,
1824
- refusalCode: 'modeling_gap',
1905
+ refusalCode: isPathAmbiguity ? 'ambiguous' : 'modeling_gap',
1825
1906
  // The answer shows the compact business-readable failure; the FULL compiler
1826
1907
  // output stays here for Inspect/debugging.
1827
- refusalDetails: { code: 'semantic_runtime_required', message: semanticRuntimeFailure },
1908
+ refusalDetails: {
1909
+ code: isPathAmbiguity ? 'semantic_path_ambiguous' : 'semantic_runtime_required',
1910
+ message: semanticRuntimeFailure.message,
1911
+ },
1912
+ ...(semanticExecutionTrace ? { semanticExecutionTrace } : {}),
1913
+ ...(semanticRuntimeFailure.candidates?.length
1914
+ ? { clarificationOptions: semanticRuntimeFailure.candidates.map((candidate) => ({ ...candidate, question })) }
1915
+ : {}),
1828
1916
  citations: [],
1829
1917
  memoryContext: input.memoryContext,
1830
1918
  evidence: buildNoAnswerEvidence({
@@ -2935,6 +3023,11 @@ async function runAnswerLoop(input) {
2935
3023
  : undefined;
2936
3024
  const certifiedMetricAnswer = semanticMetricCertification === 'certified' || semanticMetricCertification === 'reviewed';
2937
3025
  const governedMetricExecutionFailure = governedMetricAnswer && Boolean(executionError);
3026
+ const finalSemanticExecutionTrace = semanticTraceAfterExecution(semanticExecutionTrace, {
3027
+ executed: Boolean(result),
3028
+ ...(executionError ? { error: executionError } : {}),
3029
+ ...(result ? { result } : {}),
3030
+ });
2938
3031
  return {
2939
3032
  kind: governedMetricExecutionFailure ? 'no_answer' : 'uncertified',
2940
3033
  sourceTier: governedMetricExecutionFailure ? 'no_answer' : governedMetricAnswer ? 'semantic_layer' : activeTier,
@@ -2948,6 +3041,7 @@ async function runAnswerLoop(input) {
2948
3041
  sql: parsed.sql,
2949
3042
  result,
2950
3043
  executionError,
3044
+ ...(finalSemanticExecutionTrace ? { semanticExecutionTrace: finalSemanticExecutionTrace } : {}),
2951
3045
  ...(governedMetricExecutionFailure ? { refusalCode: 'grounding_gap' } : {}),
2952
3046
  suggestedViz: parsed.viz ?? 'table',
2953
3047
  dqlArtifact: answerDqlArtifact,
@@ -3138,6 +3232,7 @@ async function executeSemanticAnalyticalGraph(input) {
3138
3232
  const sourceResults = {};
3139
3233
  const compiledSql = [];
3140
3234
  const artifacts = [];
3235
+ let semanticExecutionTrace;
3141
3236
  for (const invocation of input.binding.invocations) {
3142
3237
  let composed = composeSemanticQueryFromMembers({
3143
3238
  semanticLayer: layer,
@@ -3149,6 +3244,7 @@ async function executeSemanticAnalyticalGraph(input) {
3149
3244
  if (!composed && input.input.semanticQueryCompiler) {
3150
3245
  try {
3151
3246
  const compiled = await input.input.semanticQueryCompiler(invocation.selection);
3247
+ semanticExecutionTrace = compiled.trace;
3152
3248
  composed = composeSemanticQueryFromCompiledMembers({
3153
3249
  semanticLayer: layer,
3154
3250
  question: input.input.question,
@@ -3157,9 +3253,34 @@ async function executeSemanticAnalyticalGraph(input) {
3157
3253
  });
3158
3254
  }
3159
3255
  catch (error) {
3256
+ const failure = semanticCompilerFailure(error);
3257
+ if (failure.candidates?.length) {
3258
+ return {
3259
+ kind: 'no_answer',
3260
+ sourceTier: 'no_answer',
3261
+ certification: 'analyst_review_required',
3262
+ reviewStatus: 'none',
3263
+ confidence: 0,
3264
+ text: failure.message,
3265
+ answer: failure.message,
3266
+ refusalCode: 'ambiguous',
3267
+ refusalDetails: { code: 'semantic_path_ambiguous', message: failure.message },
3268
+ ...(failure.trace ? { semanticExecutionTrace: failure.trace } : {}),
3269
+ clarificationOptions: failure.candidates.map((candidate) => ({
3270
+ ...candidate,
3271
+ question: input.input.question,
3272
+ })),
3273
+ analyticalExecutionGraph: input.graph,
3274
+ citations: contextPackCitations(input.input.contextPack, 8),
3275
+ considered: input.considered,
3276
+ contextPack: input.input.contextPack,
3277
+ providerUsed: input.providerName,
3278
+ };
3279
+ }
3160
3280
  return analyticalGraphFailureAnswer(input, 'COMPILATION_FAILED', error instanceof Error ? error.message : String(error), {
3161
3281
  phase: 'compilation',
3162
3282
  ...(compiledSql.length ? { compiledSql: renderAnalyticalStatements(compiledSql) } : {}),
3283
+ ...(failure.trace ? { semanticExecutionTrace: failure.trace } : {}),
3163
3284
  });
3164
3285
  }
3165
3286
  }
@@ -3182,9 +3303,19 @@ async function executeSemanticAnalyticalGraph(input) {
3182
3303
  let result;
3183
3304
  try {
3184
3305
  result = await executor();
3306
+ semanticExecutionTrace = semanticTraceAfterExecution(semanticExecutionTrace, {
3307
+ executed: true,
3308
+ result,
3309
+ });
3185
3310
  }
3186
3311
  catch (error) {
3187
- return analyticalGraphFailureAnswer(input, 'EXECUTION_FAILED', error instanceof Error ? error.message : String(error), { phase: 'execution', dqlArtifact: composed.dqlArtifact, compiledSql: composed.sql });
3312
+ const message = error instanceof Error ? error.message : String(error);
3313
+ return analyticalGraphFailureAnswer(input, 'EXECUTION_FAILED', message, {
3314
+ phase: 'execution',
3315
+ dqlArtifact: composed.dqlArtifact,
3316
+ compiledSql: composed.sql,
3317
+ semanticExecutionTrace: semanticTraceAfterExecution(semanticExecutionTrace, { executed: false, error: message }),
3318
+ });
3188
3319
  }
3189
3320
  const normalized = normalizeAnalyticalSourceResult({
3190
3321
  result,
@@ -3219,6 +3350,9 @@ async function executeSemanticAnalyticalGraph(input) {
3219
3350
  sql,
3220
3351
  ...(artifacts.length === 1 ? { dqlArtifact: artifacts[0] } : {}),
3221
3352
  analyticalExecutionGraph: input.graph,
3353
+ ...(semanticExecutionTrace
3354
+ ? { semanticExecutionTrace: semanticTraceAfterExecution(semanticExecutionTrace, { executed: false }) }
3355
+ : {}),
3222
3356
  citations: contextPackCitations(input.input.contextPack, 8),
3223
3357
  considered: input.considered,
3224
3358
  contextPack: input.input.contextPack,
@@ -3263,6 +3397,9 @@ async function executeSemanticAnalyticalGraph(input) {
3263
3397
  analyticalExecutionReceipt: executed.receipt,
3264
3398
  analyticalFacts: story.factSet,
3265
3399
  analyticalNarrative: story.narrative,
3400
+ ...(semanticExecutionTrace
3401
+ ? { semanticExecutionTrace: semanticTraceAfterExecution(semanticExecutionTrace, { executed: true }) }
3402
+ : {}),
3266
3403
  citations: contextPackCitations(input.input.contextPack, 8),
3267
3404
  considered: input.considered,
3268
3405
  contextPack: input.input.contextPack,
@@ -3472,6 +3609,7 @@ function analyticalGraphFailureAnswer(input, code, reason, artifacts = {}) {
3472
3609
  analyticalExecutionGraph: input.graph,
3473
3610
  ...(artifacts.compiledSql ? { proposedSql: artifacts.compiledSql, sql: artifacts.compiledSql } : {}),
3474
3611
  ...(artifacts.dqlArtifact ? { dqlArtifact: artifacts.dqlArtifact } : {}),
3612
+ ...(artifacts.semanticExecutionTrace ? { semanticExecutionTrace: artifacts.semanticExecutionTrace } : {}),
3475
3613
  citations: contextPackCitations(input.input.contextPack, 8),
3476
3614
  considered: input.considered,
3477
3615
  contextPack: input.input.contextPack,