@duckcodeailabs/dql-agent 1.6.3 → 1.6.5

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.
@@ -26,7 +26,7 @@ export type AnswerReviewStatus = 'none' | 'draft_ready' | 'analyst_review_requir
26
26
  export type AgentIntent = 'exact_certified_lookup' | 'ad_hoc_analysis' | 'drillthrough' | 'clarify';
27
27
  export interface AgentCitation {
28
28
  nodeId: string;
29
- kind: KGNode['kind'] | 'memory';
29
+ kind: KGNode['kind'] | 'memory' | 'runtime_schema';
30
30
  name: string;
31
31
  /** Frozen-in-time SHA at the moment of indexing. */
32
32
  gitSha?: string;
@@ -43,7 +43,7 @@ export interface AgentEvidenceRouteStep {
43
43
  }
44
44
  export interface AgentEvidenceAsset {
45
45
  nodeId: string;
46
- kind: KGNode['kind'] | 'memory' | 'question';
46
+ kind: KGNode['kind'] | 'memory' | 'question' | 'runtime_schema';
47
47
  name: string;
48
48
  description?: string;
49
49
  sourceTier?: AnswerSourceTier | 'memory' | 'project';
@@ -73,6 +73,8 @@ export interface AgentSchemaColumn {
73
73
  name: string;
74
74
  type?: string;
75
75
  description?: string;
76
+ /** Bounded runtime values that matched the user's question, used only as SQL-generation hints. */
77
+ sampleValues?: string[];
76
78
  }
77
79
  export interface AgentSchemaTable {
78
80
  relation: string;
@@ -1 +1 @@
1
- {"version":3,"file":"answer-loop.d.ts","sourceRoot":"","sources":["../src/answer-loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"answer-loop.d.ts","sourceRoot":"","sources":["../src/answer-loop.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@
14
14
  * step. Tests can mock the provider with a canned response and exercise the
15
15
  * full pipeline.
16
16
  */
17
- import { buildSkillsPrompt } from './skills/loader.js';
17
+ import { buildSkillBlockHints, buildSkillsPrompt } from './skills/loader.js';
18
18
  const CERTIFIED_HIT_THRESHOLD = 0.18;
19
19
  const HARD_NEGATIVE_RATIO = 0.5;
20
20
  const EXECUTABLE_ARTIFACT_KINDS = ['block', 'dashboard', 'app', 'notebook'];
@@ -24,6 +24,10 @@ const SEMANTIC_KINDS = ['metric', 'dimension', 'measure', 'entity', 'semantic_mo
24
24
  const MANIFEST_KINDS = ['dbt_model', 'dbt_source'];
25
25
  export async function answer(input) {
26
26
  const { question, userId, domain, provider, kg, skills = [], blockHints = [] } = input;
27
+ const effectiveBlockHints = Array.from(new Set([
28
+ ...blockHints,
29
+ ...buildSkillBlockHints(skills, userId ?? null),
30
+ ]));
27
31
  const followUpSourceBlock = input.followUp?.sourceBlockName
28
32
  ? kg.getNode(`block:${input.followUp.sourceBlockName}`)
29
33
  : null;
@@ -52,7 +56,7 @@ export async function answer(input) {
52
56
  executableArtifactHits,
53
57
  businessHits,
54
58
  question,
55
- blockHints: input.followUp?.kind === 'drilldown' ? [] : blockHints,
59
+ blockHints: input.followUp?.kind === 'drilldown' ? [] : effectiveBlockHints,
56
60
  excludedArtifactIds,
57
61
  kg,
58
62
  })
@@ -170,7 +174,7 @@ export async function answer(input) {
170
174
  const reviewRequiredArtifactHits = artifactHits
171
175
  .filter((hit) => hit.score >= CERTIFIED_HIT_THRESHOLD && !isCertifiedHit(hit, kg))
172
176
  .slice(0, 4);
173
- const trustedArtifactContext = executableArtifactHits
177
+ const trustedArtifactContext = rankGeneratedContextHits(executableArtifactHits.filter((hit) => !excludedArtifactIds?.has(hit.node.nodeId)), input.schemaContext ?? [], question)
174
178
  .filter((hit) => !excludedArtifactIds?.has(hit.node.nodeId))
175
179
  .slice(0, 5);
176
180
  const contextHits = activeTier === 'semantic_layer'
@@ -275,6 +279,7 @@ export async function answer(input) {
275
279
  sourceTier: 'memory',
276
280
  provenance: m.source,
277
281
  })),
282
+ ...schemaCitations(input.schemaContext ?? [], Math.max(0, 4 - contextNodes.length)),
278
283
  ];
279
284
  let result;
280
285
  let executionError;
@@ -364,6 +369,7 @@ export async function answer(input) {
364
369
  activeTier,
365
370
  intent,
366
371
  contextNodes,
372
+ schemaContext: input.schemaContext ?? [],
367
373
  followUp: input.followUp,
368
374
  businessHits,
369
375
  semanticHits,
@@ -383,18 +389,27 @@ export async function answer(input) {
383
389
  const SYSTEM_PROMPT = `You are the DQL Analytics Agent.
384
390
 
385
391
  Rules:
386
- 1. Use certified DQL blocks only when the user's question exactly asks for that
387
- saved block, direct KPI, or definition. For ad hoc rankings, breakdowns,
388
- comparisons, drill-throughs, or custom grains, generate review-required SQL
389
- from the supplied metadata and cite certified context as evidence.
390
- 2. If you must generate SQL, return it inside a single \`\`\`sql code block.
391
- 3. Provide a one-paragraph natural-language summary BEFORE the SQL block.
392
- 4. Suggest a visualization type from this list, on a line starting with "Viz:":
392
+ 1. First classify the question: exact saved artifact/direct KPI, entity-specific
393
+ lookup, ad hoc ranking/breakdown/comparison/custom grain, drill-through
394
+ follow-up, or insufficient context.
395
+ 2. Use certified DQL blocks only when the user's question exactly asks for that
396
+ saved block, direct KPI, or definition. For single-user/customer/account,
397
+ custom filters, rankings, breakdowns, comparisons, drill-throughs, or custom
398
+ grains, generate review-required SQL from supplied metadata and cite
399
+ certified context as evidence.
400
+ 3. If you must generate SQL, return it inside a single \`\`\`sql code block.
401
+ 4. Provide a one-paragraph natural-language summary BEFORE the SQL block.
402
+ 5. Suggest a visualization type from this list, on a line starting with "Viz:":
393
403
  line, bar, area, pie, single_value, table, pivot, kpi.
394
- 5. NEVER fabricate column names that are not present in the supplied schema context.
395
- 6. Return runnable SQL for the local warehouse/runtime. Do NOT use dbt/Jinja
396
- macros such as {{ ref(...) }} or {{ source(...) }} in proposed SQL.
397
- 7. If the schema is insufficient to answer, say so explicitly and ask a clarifying question.`;
404
+ 6. NEVER fabricate column names that are not present in the supplied schema context.
405
+ If a requested filter value is supplied as a matched value, prefer the table
406
+ and column that matched that value.
407
+ 7. Return one read-only SELECT or WITH query for the local warehouse/runtime.
408
+ Do NOT use dbt/Jinja macros such as {{ ref(...) }} or {{ source(...) }} in
409
+ proposed SQL. Do not emit INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, COPY,
410
+ PRAGMA, SET, or multiple statements.
411
+ 8. If the schema is insufficient to answer, say so explicitly and ask a
412
+ clarifying question instead of guessing.`;
398
413
  function renderContextPrompt(blocks, businessContext, others, activeTier, memoryContext, extraContext, followUp, schemaContext = [], intent = 'ad_hoc_analysis') {
399
414
  const intentSection = `## Routing intent\n\nintent: ${intent}\n${intent === 'exact_certified_lookup'
400
415
  ? 'Use a certified artifact only if it exactly answers the question.'
@@ -420,7 +435,12 @@ function renderContextPrompt(blocks, businessContext, others, activeTier, memory
420
435
  .map((table) => {
421
436
  const cols = table.columns
422
437
  .slice(0, 50)
423
- .map((col) => `${col.name}${col.type ? ` ${col.type}` : ''}${col.description ? ` (${col.description})` : ''}`)
438
+ .map((col) => {
439
+ const sampleValues = col.sampleValues?.length
440
+ ? `; matched values: ${col.sampleValues.slice(0, 4).map(formatPromptValue).join(', ')}`
441
+ : '';
442
+ return `${col.name}${col.type ? ` ${col.type}` : ''}${col.description ? ` (${col.description})` : ''}${sampleValues}`;
443
+ })
424
444
  .join(', ');
425
445
  return `- ${table.relation}${table.description ? ` — ${table.description}` : ''}\n columns: ${cols}`;
426
446
  })
@@ -473,6 +493,8 @@ export function parseProposal(raw) {
473
493
  function buildSchemaAwareProposal(input) {
474
494
  if (input.intent !== 'ad_hoc_analysis' && input.intent !== 'drillthrough')
475
495
  return undefined;
496
+ if (isFilteredEntityQuestion(input.question))
497
+ return undefined;
476
498
  const lower = input.question.toLowerCase();
477
499
  const asksForCustomerPerformance = /\bcustomers?\b/.test(lower)
478
500
  && /\border|orders|spend|revenue|perform|performed|better|top|best|rank|ranking\b/.test(lower)
@@ -570,12 +592,15 @@ function pickCertifiedArtifact(input) {
570
592
  return { node, score: 1, snippet: undefined };
571
593
  }
572
594
  }
595
+ const executableHit = pickFirstCertifiedHit(input.executableArtifactHits, input.kg, input.excludedArtifactIds, input.question);
573
596
  if (isBusinessDefinitionQuestion(input.question)) {
597
+ if (executableHit && hasExactExecutableArtifactSignal(input.question, executableHit.node)) {
598
+ return executableHit;
599
+ }
574
600
  const businessHit = pickFirstCertifiedHit(input.businessHits, input.kg);
575
601
  if (businessHit)
576
602
  return businessHit;
577
603
  }
578
- const executableHit = pickFirstCertifiedHit(input.executableArtifactHits, input.kg, input.excludedArtifactIds, input.question);
579
604
  if (executableHit && shouldDeferCertifiedArtifactForReviewPath({
580
605
  hits: input.executableArtifactHits,
581
606
  selected: executableHit,
@@ -686,6 +711,97 @@ function hasMeaningfulCertifiedBlockSignal(question, node) {
686
711
  }
687
712
  return false;
688
713
  }
714
+ function hasExactExecutableArtifactSignal(question, node) {
715
+ if (!EXECUTABLE_ARTIFACT_KINDS.includes(node.kind))
716
+ return false;
717
+ const questionTokens = exactMatchTokens(question);
718
+ const nameTokens = exactMatchTokens(node.name);
719
+ if (nameTokens.size === 0)
720
+ return false;
721
+ for (const token of nameTokens) {
722
+ if (!questionTokens.has(token))
723
+ return false;
724
+ }
725
+ return true;
726
+ }
727
+ function rankGeneratedContextHits(hits, schemaContext, question) {
728
+ const schemaTokens = schemaEntityTokens(schemaContext, question);
729
+ if (schemaTokens.size === 0)
730
+ return hits;
731
+ const filteredEntityQuestion = isFilteredEntityQuestion(question);
732
+ return [...hits].sort((a, b) => {
733
+ const aScore = generatedContextScore(a, schemaTokens, filteredEntityQuestion);
734
+ const bScore = generatedContextScore(b, schemaTokens, filteredEntityQuestion);
735
+ return bScore - aScore;
736
+ });
737
+ }
738
+ function generatedContextScore(hit, schemaTokens, filteredEntityQuestion) {
739
+ const identityTokens = exactMatchTokens([
740
+ hit.node.name,
741
+ hit.node.domain ?? '',
742
+ ...(hit.node.tags ?? []),
743
+ ].join(' '));
744
+ const bodyTokens = exactMatchTokens([
745
+ hit.node.description ?? '',
746
+ hit.node.llmContext ?? '',
747
+ ].join(' '));
748
+ let score = hit.score;
749
+ for (const token of schemaTokens) {
750
+ if (identityTokens.has(token)) {
751
+ score += filteredEntityQuestion ? 0.6 : 0.25;
752
+ }
753
+ else if (bodyTokens.has(token)) {
754
+ score += filteredEntityQuestion ? 0.15 : 0.05;
755
+ }
756
+ }
757
+ if (hit.node.kind === 'block')
758
+ score += 0.2;
759
+ return score;
760
+ }
761
+ function schemaEntityTokens(schemaContext, question) {
762
+ const tokens = new Set();
763
+ for (const table of schemaContext) {
764
+ const hasMatchedValues = table.columns.some((column) => column.sampleValues?.length);
765
+ if (!hasMatchedValues)
766
+ continue;
767
+ for (const token of exactMatchTokens([table.relation, table.name, table.description ?? ''].join(' '))) {
768
+ tokens.add(token);
769
+ }
770
+ for (const column of table.columns) {
771
+ if (!column.sampleValues?.length)
772
+ continue;
773
+ for (const token of exactMatchTokens(column.name))
774
+ tokens.add(token);
775
+ }
776
+ }
777
+ if (tokens.size > 0 || !isFilteredEntityQuestion(question))
778
+ return tokens;
779
+ for (const table of schemaContext) {
780
+ for (const token of exactMatchTokens([table.relation, table.name, table.description ?? ''].join(' '))) {
781
+ if (ENTITY_CONTEXT_TOKENS.has(token))
782
+ tokens.add(token);
783
+ }
784
+ for (const column of table.columns) {
785
+ for (const token of exactMatchTokens(column.name)) {
786
+ if (ENTITY_CONTEXT_TOKENS.has(token))
787
+ tokens.add(token);
788
+ }
789
+ }
790
+ }
791
+ return tokens;
792
+ }
793
+ const ENTITY_CONTEXT_TOKENS = new Set([
794
+ 'account',
795
+ 'customer',
796
+ 'location',
797
+ 'member',
798
+ 'order',
799
+ 'product',
800
+ 'region',
801
+ 'segment',
802
+ 'subscriber',
803
+ 'user',
804
+ ]);
689
805
  function meaningfulTokens(value) {
690
806
  const tokens = new Set();
691
807
  for (const raw of value.toLowerCase().match(/[a-z0-9_]+/g) ?? []) {
@@ -698,6 +814,18 @@ function meaningfulTokens(value) {
698
814
  }
699
815
  return tokens;
700
816
  }
817
+ function exactMatchTokens(value) {
818
+ const tokens = new Set();
819
+ for (const raw of value.toLowerCase().match(/[a-z0-9_]+/g) ?? []) {
820
+ for (const part of raw.split('_')) {
821
+ const normalized = normalizeToken(part);
822
+ if (!normalized || normalized.length < 3)
823
+ continue;
824
+ tokens.add(normalized);
825
+ }
826
+ }
827
+ return tokens;
828
+ }
701
829
  function normalizeToken(token) {
702
830
  if (token === 'skus')
703
831
  return 'sku';
@@ -716,14 +844,16 @@ function normalizeToken(token) {
716
844
  function classifyAgentIntent(input) {
717
845
  if (input.followUp?.kind === 'drilldown')
718
846
  return 'drillthrough';
719
- if (isBusinessDefinitionQuestion(input.question))
720
- return 'exact_certified_lookup';
721
847
  if (isExplicitSavedArtifactQuestion(input.question, input.artifactHits))
722
848
  return 'exact_certified_lookup';
723
849
  const hasContext = input.artifactHits.some((hit) => hit.score >= CERTIFIED_HIT_THRESHOLD) ||
724
850
  input.semanticHits.some((hit) => hit.score >= CERTIFIED_HIT_THRESHOLD) ||
725
851
  input.manifestHits.some((hit) => hit.score >= CERTIFIED_HIT_THRESHOLD) ||
726
852
  input.schemaContext.length > 0;
853
+ if (isFilteredEntityQuestion(input.question))
854
+ return hasContext ? 'ad_hoc_analysis' : 'clarify';
855
+ if (isBusinessDefinitionQuestion(input.question))
856
+ return 'exact_certified_lookup';
727
857
  if (isAdHocAnalysisQuestion(input.question))
728
858
  return hasContext ? 'ad_hoc_analysis' : 'clarify';
729
859
  if (looksLikeDataQuestion(input.question) && !hasContext)
@@ -746,11 +876,27 @@ function isAdHocAnalysisQuestion(question) {
746
876
  const lower = question.toLowerCase();
747
877
  if (isBusinessDefinitionQuestion(question))
748
878
  return false;
749
- return /\b(break\s*down|breakdown|drill\s*(?:down|into)|slice|segment|split|compare|versus|vs\.?|trend|over time|top|bottom|best|worst|highest|lowest|rank|ranking|performed better|better performing|by\s+[a-z][\w\s-]{1,40})\b/i.test(lower)
750
- || /\b(show|list|find|give)\b.+\b(customer|customers|product|products|order|orders|region|location|month|week|day)\b/i.test(lower);
879
+ return /\b(break\s*down|breakdown|drill\s*(?:down|into)|slice|segment|split|compare|versus|vs\.?|trend|over time|top|bottom|best|worst|highest|lowest|rank|ranking|performed better|better performing|why|what drove|driver|drivers|top movers?|changed?|change|dropped?|drop|decreased?|decrease|declined?|decline|increased?|increase|anomal(?:y|ies)|exceptions?|root cause|contribut(?:e|ed|ion)|variance|delta|by\s+[a-z][\w\s-]{1,40})\b/i.test(lower)
880
+ || /\b(show|list|find|give)\b.+\b(account|accounts|customer|customers|product|products|order|orders|region|location|month|week|day|user|users)\b/i.test(lower);
881
+ }
882
+ function isFilteredEntityQuestion(question) {
883
+ const lower = question.toLowerCase();
884
+ if (!looksLikeDataQuestion(question))
885
+ return false;
886
+ if (/\b(for|where|only|specific|single|individual|named|called)\b.+\b(account|accounts|customer|customers|product|products|sku|user|users)\b/i.test(lower)) {
887
+ return true;
888
+ }
889
+ if (/\b(account|customer|product|sku|user)\s+(?:id|name|email)\b/i.test(lower))
890
+ return true;
891
+ if (/[A-Z][a-z]+(?:\s+[A-Z][a-z]+){1,3}/.test(question) && /\b(revenue|sales|order|orders|spend|value|churn|usage|activity|performance|performed|metric|kpi)\b/i.test(lower)) {
892
+ return true;
893
+ }
894
+ if (/\b[\w.%+-]+@[\w.-]+\.[A-Za-z]{2,}\b/.test(question))
895
+ return true;
896
+ return false;
751
897
  }
752
898
  function looksLikeDataQuestion(question) {
753
- return /\b(show|list|find|what|which|how many|how much|compare|trend|revenue|customer|customers|order|orders|product|products|sales|metric|kpi|dashboard|performance|performed)\b/i.test(question);
899
+ return /\b(show|list|find|what|which|how many|how much|compare|trend|revenue|account|accounts|customer|customers|order|orders|product|products|sales|metric|kpi|dashboard|performance|performed|user|users)\b/i.test(question);
754
900
  }
755
901
  function citationSourceTier(node, fallback) {
756
902
  if (node.sourceTier === 'certified_artifact')
@@ -871,6 +1017,11 @@ function chartNameFromConfig(config) {
871
1017
  }
872
1018
  return undefined;
873
1019
  }
1020
+ function formatPromptValue(value) {
1021
+ const compact = value.replace(/\s+/g, ' ').trim();
1022
+ const shown = compact.length > 80 ? `${compact.slice(0, 77)}...` : compact;
1023
+ return JSON.stringify(shown);
1024
+ }
874
1025
  function composeClarificationText(question, considered, schemaContext) {
875
1026
  const context = considered.slice(0, 3).map((hit) => hit.node.name).join(', ');
876
1027
  const tables = schemaContext.slice(0, 3).map((table) => table.relation).join(', ');
@@ -1082,9 +1233,12 @@ function buildGeneratedEvidence(input) {
1082
1233
  const semanticObjects = uniqueAssets([...input.contextNodes, ...input.semanticHits.map((hit) => hit.node)]
1083
1234
  .filter((node) => SEMANTIC_KINDS.includes(node.kind))
1084
1235
  .map(assetFromNode)).slice(0, 6);
1085
- const sourceTables = uniqueAssets([...input.contextNodes, ...input.manifestHits.map((hit) => hit.node)]
1086
- .filter((node) => MANIFEST_KINDS.includes(node.kind))
1087
- .map(assetFromNode)).slice(0, 6);
1236
+ const sourceTables = uniqueAssets([
1237
+ ...[...input.contextNodes, ...input.manifestHits.map((hit) => hit.node)]
1238
+ .filter((node) => MANIFEST_KINDS.includes(node.kind))
1239
+ .map(assetFromNode),
1240
+ ...schemaContextAssets(input.schemaContext),
1241
+ ]).slice(0, 6);
1088
1242
  const selectedAssets = uniqueAssets(selectedNodes.map(assetFromNode)).slice(0, 4);
1089
1243
  const selectedSemantic = input.activeTier === 'semantic_layer' && semanticObjects.length > 0;
1090
1244
  return {
@@ -1122,7 +1276,17 @@ function buildGeneratedEvidence(input) {
1122
1276
  {
1123
1277
  tool: input.activeTier === 'semantic_layer' ? 'compose_semantic_query' : 'search_dbt_manifest',
1124
1278
  status: 'selected',
1125
- label: input.activeTier === 'semantic_layer' ? 'Composed SQL from semantic context' : 'Composed SQL from dbt manifest context',
1279
+ label: input.activeTier === 'semantic_layer'
1280
+ ? 'Composed SQL from semantic context'
1281
+ : input.schemaContext.length > 0
1282
+ ? 'Composed SQL from runtime schema and project metadata'
1283
+ : 'Composed SQL from dbt manifest context',
1284
+ },
1285
+ {
1286
+ tool: 'inspect_runtime_schema',
1287
+ status: input.schemaContext.length > 0 ? 'checked' : 'skipped',
1288
+ label: input.schemaContext.length > 0 ? 'Runtime tables and columns attached' : 'No runtime schema context available',
1289
+ detail: input.schemaContext.slice(0, 3).map((table) => table.relation).join(', ') || undefined,
1126
1290
  },
1127
1291
  {
1128
1292
  tool: 'validate_sql',
@@ -1284,6 +1448,29 @@ function assetFromNode(node) {
1284
1448
  status: node.status,
1285
1449
  };
1286
1450
  }
1451
+ function schemaContextAssets(schemaContext) {
1452
+ return schemaContext.slice(0, 6).map((table) => ({
1453
+ nodeId: `runtime_schema:${table.relation}`,
1454
+ kind: 'runtime_schema',
1455
+ name: table.relation,
1456
+ description: table.description ?? `${table.columns.length} runtime column${table.columns.length === 1 ? '' : 's'} available for generated SQL.`,
1457
+ sourceTier: 'project',
1458
+ certification: 'ai_generated',
1459
+ provenance: table.source ?? 'runtime information_schema',
1460
+ sourcePath: table.relation,
1461
+ }));
1462
+ }
1463
+ function schemaCitations(schemaContext, limit) {
1464
+ if (limit <= 0)
1465
+ return [];
1466
+ return schemaContext.slice(0, limit).map((table) => ({
1467
+ nodeId: `runtime_schema:${table.relation}`,
1468
+ kind: 'runtime_schema',
1469
+ name: table.relation,
1470
+ sourceTier: 'dbt_manifest',
1471
+ provenance: table.source ?? 'runtime information_schema',
1472
+ }));
1473
+ }
1287
1474
  function certificationForNode(node) {
1288
1475
  if (node.status === 'certified' || node.certification === 'certified')
1289
1476
  return 'certified';