@duckcodeailabs/dql-agent 1.14.0 → 1.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/agent-run-engine.d.ts +68 -2
  2. package/dist/agent-run-engine.d.ts.map +1 -1
  3. package/dist/agent-run-engine.js +520 -26
  4. package/dist/agent-run-engine.js.map +1 -1
  5. package/dist/agent-run-gates.d.ts.map +1 -1
  6. package/dist/agent-run-gates.js +25 -0
  7. package/dist/agent-run-gates.js.map +1 -1
  8. package/dist/agentic/analyst-loop.d.ts +91 -0
  9. package/dist/agentic/analyst-loop.d.ts.map +1 -0
  10. package/dist/agentic/analyst-loop.js +331 -0
  11. package/dist/agentic/analyst-loop.js.map +1 -0
  12. package/dist/agentic/assumptions.d.ts +62 -0
  13. package/dist/agentic/assumptions.d.ts.map +1 -0
  14. package/dist/agentic/assumptions.js +73 -0
  15. package/dist/agentic/assumptions.js.map +1 -0
  16. package/dist/agentic/business-explanation.d.ts +56 -0
  17. package/dist/agentic/business-explanation.d.ts.map +1 -0
  18. package/dist/agentic/business-explanation.js +130 -0
  19. package/dist/agentic/business-explanation.js.map +1 -0
  20. package/dist/agentic/identifier-ledger.d.ts +74 -0
  21. package/dist/agentic/identifier-ledger.d.ts.map +1 -0
  22. package/dist/agentic/identifier-ledger.js +151 -0
  23. package/dist/agentic/identifier-ledger.js.map +1 -0
  24. package/dist/agentic/ledger-tools.d.ts +68 -0
  25. package/dist/agentic/ledger-tools.d.ts.map +1 -0
  26. package/dist/agentic/ledger-tools.js +198 -0
  27. package/dist/agentic/ledger-tools.js.map +1 -0
  28. package/dist/agentic/orchestrator-policy.d.ts +60 -0
  29. package/dist/agentic/orchestrator-policy.d.ts.map +1 -0
  30. package/dist/agentic/orchestrator-policy.js +73 -0
  31. package/dist/agentic/orchestrator-policy.js.map +1 -0
  32. package/dist/agentic/orchestrator.d.ts +54 -0
  33. package/dist/agentic/orchestrator.d.ts.map +1 -0
  34. package/dist/agentic/orchestrator.js +67 -0
  35. package/dist/agentic/orchestrator.js.map +1 -0
  36. package/dist/agentic/preview-tool.d.ts +36 -0
  37. package/dist/agentic/preview-tool.d.ts.map +1 -0
  38. package/dist/agentic/preview-tool.js +71 -0
  39. package/dist/agentic/preview-tool.js.map +1 -0
  40. package/dist/agentic/rerank.d.ts +50 -0
  41. package/dist/agentic/rerank.d.ts.map +1 -0
  42. package/dist/agentic/rerank.js +140 -0
  43. package/dist/agentic/rerank.js.map +1 -0
  44. package/dist/agentic/research/hypothesis.d.ts +110 -0
  45. package/dist/agentic/research/hypothesis.d.ts.map +1 -0
  46. package/dist/agentic/research/hypothesis.js +125 -0
  47. package/dist/agentic/research/hypothesis.js.map +1 -0
  48. package/dist/agentic/research/synthesis.d.ts +36 -0
  49. package/dist/agentic/research/synthesis.d.ts.map +1 -0
  50. package/dist/agentic/research/synthesis.js +109 -0
  51. package/dist/agentic/research/synthesis.js.map +1 -0
  52. package/dist/agentic/research-agent.d.ts +54 -0
  53. package/dist/agentic/research-agent.d.ts.map +1 -0
  54. package/dist/agentic/research-agent.js +177 -0
  55. package/dist/agentic/research-agent.js.map +1 -0
  56. package/dist/agentic/sql-authorization.d.ts +131 -0
  57. package/dist/agentic/sql-authorization.d.ts.map +1 -0
  58. package/dist/agentic/sql-authorization.js +460 -0
  59. package/dist/agentic/sql-authorization.js.map +1 -0
  60. package/dist/agentic/tool-loop.d.ts +29 -0
  61. package/dist/agentic/tool-loop.d.ts.map +1 -1
  62. package/dist/agentic/tool-loop.js +129 -52
  63. package/dist/agentic/tool-loop.js.map +1 -1
  64. package/dist/agentic/toolset.d.ts.map +1 -1
  65. package/dist/agentic/toolset.js +155 -0
  66. package/dist/agentic/toolset.js.map +1 -1
  67. package/dist/agentic/turn-plan.d.ts +35 -0
  68. package/dist/agentic/turn-plan.d.ts.map +1 -0
  69. package/dist/agentic/turn-plan.js +108 -0
  70. package/dist/agentic/turn-plan.js.map +1 -0
  71. package/dist/agentic/value-probe.d.ts +89 -0
  72. package/dist/agentic/value-probe.d.ts.map +1 -0
  73. package/dist/agentic/value-probe.js +304 -0
  74. package/dist/agentic/value-probe.js.map +1 -0
  75. package/dist/analytical-frame.d.ts.map +1 -1
  76. package/dist/analytical-frame.js +10 -1
  77. package/dist/analytical-frame.js.map +1 -1
  78. package/dist/analytical-orchestration.d.ts +382 -0
  79. package/dist/analytical-orchestration.d.ts.map +1 -1
  80. package/dist/analytical-orchestration.js +782 -6
  81. package/dist/analytical-orchestration.js.map +1 -1
  82. package/dist/analytical-request-policy.d.ts +26 -0
  83. package/dist/analytical-request-policy.d.ts.map +1 -0
  84. package/dist/analytical-request-policy.js +82 -0
  85. package/dist/analytical-request-policy.js.map +1 -0
  86. package/dist/analytical-result-facts.d.ts +13 -0
  87. package/dist/analytical-result-facts.d.ts.map +1 -1
  88. package/dist/analytical-result-facts.js +37 -1
  89. package/dist/analytical-result-facts.js.map +1 -1
  90. package/dist/answer-loop.d.ts +105 -16
  91. package/dist/answer-loop.d.ts.map +1 -1
  92. package/dist/answer-loop.js +833 -108
  93. package/dist/answer-loop.js.map +1 -1
  94. package/dist/answer-shape.d.ts +32 -1
  95. package/dist/answer-shape.d.ts.map +1 -1
  96. package/dist/answer-shape.js +49 -3
  97. package/dist/answer-shape.js.map +1 -1
  98. package/dist/cascade/budgets.d.ts.map +1 -1
  99. package/dist/cascade/budgets.js +8 -1
  100. package/dist/cascade/budgets.js.map +1 -1
  101. package/dist/cascade/packer.d.ts +88 -0
  102. package/dist/cascade/packer.d.ts.map +1 -0
  103. package/dist/cascade/packer.js +106 -0
  104. package/dist/cascade/packer.js.map +1 -0
  105. package/dist/conversation/result-ops.d.ts +18 -3
  106. package/dist/conversation/result-ops.d.ts.map +1 -1
  107. package/dist/conversation/result-ops.js +77 -5
  108. package/dist/conversation/result-ops.js.map +1 -1
  109. package/dist/conversation/rolling-summary.d.ts.map +1 -1
  110. package/dist/conversation/rolling-summary.js +7 -2
  111. package/dist/conversation/rolling-summary.js.map +1 -1
  112. package/dist/conversation/session-store.d.ts +3 -0
  113. package/dist/conversation/session-store.d.ts.map +1 -1
  114. package/dist/conversation/session-store.js +8 -4
  115. package/dist/conversation/session-store.js.map +1 -1
  116. package/dist/conversation/snapshot.d.ts +20 -0
  117. package/dist/conversation/snapshot.d.ts.map +1 -1
  118. package/dist/conversation/snapshot.js +40 -2
  119. package/dist/conversation/snapshot.js.map +1 -1
  120. package/dist/fixtures/ask-ai-office-shaped.d.ts +153 -0
  121. package/dist/fixtures/ask-ai-office-shaped.d.ts.map +1 -0
  122. package/dist/fixtures/ask-ai-office-shaped.js +94 -0
  123. package/dist/fixtures/ask-ai-office-shaped.js.map +1 -0
  124. package/dist/hints/store.d.ts.map +1 -1
  125. package/dist/hints/store.js +15 -5
  126. package/dist/hints/store.js.map +1 -1
  127. package/dist/index.d.ts +29 -9
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +29 -6
  130. package/dist/index.js.map +1 -1
  131. package/dist/intent-controller.d.ts +36 -0
  132. package/dist/intent-controller.d.ts.map +1 -1
  133. package/dist/intent-controller.js +95 -0
  134. package/dist/intent-controller.js.map +1 -1
  135. package/dist/meaning-resolution.d.ts +69 -2
  136. package/dist/meaning-resolution.d.ts.map +1 -1
  137. package/dist/meaning-resolution.js +128 -7
  138. package/dist/meaning-resolution.js.map +1 -1
  139. package/dist/metadata/analysis-planner.d.ts.map +1 -1
  140. package/dist/metadata/analysis-planner.js +124 -7
  141. package/dist/metadata/analysis-planner.js.map +1 -1
  142. package/dist/metadata/block-fit.d.ts +36 -0
  143. package/dist/metadata/block-fit.d.ts.map +1 -1
  144. package/dist/metadata/block-fit.js +290 -38
  145. package/dist/metadata/block-fit.js.map +1 -1
  146. package/dist/metadata/catalog.d.ts +20 -23
  147. package/dist/metadata/catalog.d.ts.map +1 -1
  148. package/dist/metadata/catalog.js +193 -22
  149. package/dist/metadata/catalog.js.map +1 -1
  150. package/dist/metadata/meaning-evidence.d.ts +10 -1
  151. package/dist/metadata/meaning-evidence.d.ts.map +1 -1
  152. package/dist/metadata/meaning-evidence.js +275 -53
  153. package/dist/metadata/meaning-evidence.js.map +1 -1
  154. package/dist/metadata/metric-match.d.ts +32 -0
  155. package/dist/metadata/metric-match.d.ts.map +1 -1
  156. package/dist/metadata/metric-match.js +120 -9
  157. package/dist/metadata/metric-match.js.map +1 -1
  158. package/dist/research-loop.d.ts +33 -2
  159. package/dist/research-loop.d.ts.map +1 -1
  160. package/dist/research-loop.js +66 -4
  161. package/dist/research-loop.js.map +1 -1
  162. package/dist/resolved-analytical-plan.d.ts +7 -0
  163. package/dist/resolved-analytical-plan.d.ts.map +1 -1
  164. package/dist/resolved-analytical-plan.js +11 -4
  165. package/dist/resolved-analytical-plan.js.map +1 -1
  166. package/dist/router.d.ts +32 -19
  167. package/dist/router.d.ts.map +1 -1
  168. package/dist/router.js +1977 -73
  169. package/dist/router.js.map +1 -1
  170. package/dist/semantic-bridge/member-select.d.ts.map +1 -1
  171. package/dist/semantic-bridge/member-select.js +39 -21
  172. package/dist/semantic-bridge/member-select.js.map +1 -1
  173. package/package.json +5 -5
@@ -0,0 +1,108 @@
1
+ /**
2
+ * One structured planning call, made before the analyst loop starts acting.
3
+ *
4
+ * The loop can already sequence its own tools, so this is not what makes it
5
+ * work — it is what makes it legible. Without a plan the trace can only emit a
6
+ * hardcoded "working on it" string, and the user waits in silence exactly as
7
+ * they do today. With one, the trace names what the agent intends to establish
8
+ * before it establishes it, which is the difference between a progress bar and
9
+ * an analyst thinking out loud.
10
+ *
11
+ * It is therefore strictly optional: any failure, timeout, or malformed reply
12
+ * returns `undefined` and the loop proceeds exactly as it would have. A
13
+ * planning call that blocked an answer would be a bad trade.
14
+ */
15
+ const PLAN_PROMPT = `You are planning one analytical turn. Do not answer the question.
16
+ Reply with ONLY a JSON object:
17
+ {"restatement": "<the question in your own words, one sentence>",
18
+ "mustEstablish": ["<fact to verify before writing SQL>", "..."],
19
+ "openingTool": "<the tool you will call first>"}
20
+ List at most four things under mustEstablish. Each must be something a tool can
21
+ check — a metric exists, a column exists, a value appears in a column, two
22
+ members are compatible. Never list something you would assume.`;
23
+ /** Pull the first JSON object out of a reply that may be fenced or prefaced. */
24
+ function extractJsonObject(raw) {
25
+ const trimmed = raw.trim();
26
+ const start = trimmed.indexOf('{');
27
+ if (start < 0)
28
+ return undefined;
29
+ let depth = 0;
30
+ let inString = false;
31
+ let escaped = false;
32
+ for (let i = start; i < trimmed.length; i += 1) {
33
+ const char = trimmed[i];
34
+ if (escaped) {
35
+ escaped = false;
36
+ continue;
37
+ }
38
+ if (char === '\\') {
39
+ escaped = true;
40
+ continue;
41
+ }
42
+ if (char === '"') {
43
+ inString = !inString;
44
+ continue;
45
+ }
46
+ if (inString)
47
+ continue;
48
+ if (char === '{')
49
+ depth += 1;
50
+ else if (char === '}') {
51
+ depth -= 1;
52
+ if (depth === 0) {
53
+ try {
54
+ return JSON.parse(trimmed.slice(start, i + 1));
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ }
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ export function parseAnalystTurnPlan(raw, toolNames = []) {
65
+ const parsed = extractJsonObject(raw);
66
+ if (!parsed || typeof parsed !== 'object')
67
+ return undefined;
68
+ const record = parsed;
69
+ const restatement = typeof record.restatement === 'string' ? record.restatement.trim() : '';
70
+ if (!restatement)
71
+ return undefined;
72
+ const mustEstablish = Array.isArray(record.mustEstablish)
73
+ ? record.mustEstablish
74
+ .filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
75
+ .map((entry) => entry.trim())
76
+ .slice(0, 4)
77
+ : [];
78
+ // Only echo a tool the model can actually call. A hallucinated name in the
79
+ // trace would promise the user a step that never happens.
80
+ const openingTool = typeof record.openingTool === 'string'
81
+ && toolNames.includes(record.openingTool.trim())
82
+ ? record.openingTool.trim()
83
+ : undefined;
84
+ return { restatement, mustEstablish, ...(openingTool ? { openingTool } : {}) };
85
+ }
86
+ export async function planAnalystTurn(provider, question, toolNames, options = {}) {
87
+ const timeoutMs = options.timeoutMs ?? 2_500;
88
+ const controller = new AbortController();
89
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
90
+ const onAbort = () => controller.abort();
91
+ options.signal?.addEventListener('abort', onAbort, { once: true });
92
+ try {
93
+ const raw = await provider.generate([
94
+ { role: 'system', content: `${PLAN_PROMPT}\n\nTools available: ${toolNames.join(', ')}` },
95
+ { role: 'user', content: question },
96
+ ], { signal: controller.signal });
97
+ return parseAnalystTurnPlan(raw, toolNames);
98
+ }
99
+ catch {
100
+ // Planning is decoration on a working loop. Never let it fail the turn.
101
+ return undefined;
102
+ }
103
+ finally {
104
+ clearTimeout(timer);
105
+ options.signal?.removeEventListener('abort', onAbort);
106
+ }
107
+ }
108
+ //# sourceMappingURL=turn-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-plan.js","sourceRoot":"","sources":["../../src/agentic/turn-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAkBH,MAAM,WAAW,GAAG;;;;;;;+DAO2C,CAAC;AAEhE,gFAAgF;AAChF,SAAS,iBAAiB,CAAC,GAAW;IACpC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,OAAO,EAAE,CAAC;YAAC,OAAO,GAAG,KAAK,CAAC;YAAC,SAAS;QAAC,CAAC;QAC3C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAAC,OAAO,GAAG,IAAI,CAAC;YAAC,SAAS;QAAC,CAAC;QAChD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAAC,QAAQ,GAAG,CAAC,QAAQ,CAAC;YAAC,SAAS;QAAC,CAAC;QACrD,IAAI,QAAQ;YAAE,SAAS;QACvB,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,IAAI,CAAC,CAAC;aACxB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACtB,KAAK,IAAI,CAAC,CAAC;YACX,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,IAAI,CAAC;oBACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACjD,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,SAAS,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,YAA+B,EAAE;IACjF,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAiC,CAAC;IACjD,MAAM,WAAW,GAAG,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAC;IACnC,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;QACvD,CAAC,CAAC,MAAM,CAAC,aAAa;aACjB,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aACxF,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;aAC5B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,CAAC,EAAE,CAAC;IACP,2EAA2E;IAC3E,0DAA0D;IAC1D,MAAM,WAAW,GAAG,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ;WACrD,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAChD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE;QAC3B,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAsB,EACtB,QAAgB,EAChB,SAA4B,EAC5B,UAAwD,EAAE;IAE1D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IACzC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CACjC;YACE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,WAAW,wBAAwB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE;YACzF,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;SACpC,EACD,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAC9B,CAAC;QACF,OAAO,oBAAoB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,wEAAwE;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * `search_values` — bind a literal the user named to a real column value.
3
+ *
4
+ * The recorded highest-severity defect in this program: asking about a specific
5
+ * member returned every row instead of that member's, and the narration then
6
+ * described the truncated result as if the member were absent. The chain was
7
+ * `runtime_value_index` empty -> no member grounding -> empty filters -> plan
8
+ * froze filterless -> 200 of 500 rows -> "no such customer".
9
+ *
10
+ * The persisted index was deleted for a good reason (SEC-003: warehouse cell
11
+ * values must not sit in a rebuildable metadata database). The fix is not to
12
+ * bring it back but to look the value up ON DEMAND, bounded, and only in columns
13
+ * a project has agreed may be searched.
14
+ *
15
+ * Two independent gates, and BOTH must pass:
16
+ * 1. a hard deny-list that no configuration can override — secrets and
17
+ * free-text payloads are never probed, however a project is set up
18
+ * 2. an allow-list of column-name shapes that plausibly hold an identifier
19
+ *
20
+ * The deny-list is first and unconditional on purpose. An allow-list alone
21
+ * eventually admits something it should not, because it grows by exception.
22
+ */
23
+ import type { AgentToolDefinition } from '../providers/types.js';
24
+ export interface ProbeColumn {
25
+ name: string;
26
+ type?: string;
27
+ }
28
+ export interface ProbeRelation {
29
+ relation: string;
30
+ columns: ProbeColumn[];
31
+ }
32
+ /**
33
+ * May this column be probed for a literal?
34
+ *
35
+ * Canonical implementation — the host's `isAgentValueProbeColumn` delegates here
36
+ * so the deny-list has exactly one definition. Two copies of a security rule
37
+ * drift, and the one that drifts is the one nobody is looking at.
38
+ */
39
+ export declare function isProbeSafeColumn(column: ProbeColumn): boolean;
40
+ /**
41
+ * Build a bounded DISTINCT lookup for one column.
42
+ *
43
+ * Exact match first, then a prefix match on the longer tokens. Prefix rather
44
+ * than `%term%`: a leading wildcard cannot use an index, and on a large
45
+ * dimension table that is the difference between a probe and an outage.
46
+ */
47
+ export declare function buildValueProbeSql(relation: string, column: string, terms: readonly string[], limit?: number): string | undefined;
48
+ export interface SearchValuesOptions {
49
+ execute: (sql: string) => Promise<{
50
+ rows: unknown[];
51
+ }>;
52
+ relations: readonly ProbeRelation[];
53
+ /** Probing is opt-in per project; disabled means the tool reports why. */
54
+ enabled: boolean;
55
+ /** Max relations probed per call, so one question cannot scan the warehouse. */
56
+ maxRelations?: number;
57
+ /** Hard ceiling across columns, not per relation. Never expose more than this many queries. */
58
+ maxColumnQueries?: number;
59
+ }
60
+ export type ValueProbeCoverageStatus = 'complete' | 'partial' | 'disabled' | 'budget_exhausted' | 'unknown_relation';
61
+ /**
62
+ * Redacted coverage is the evidence contract for a value lookup. It says what
63
+ * was attempted without leaking query text, warehouse errors, or values that
64
+ * were not already supplied by the caller.
65
+ */
66
+ export interface ValueProbeCoverageV1 {
67
+ version: 1;
68
+ status: ValueProbeCoverageStatus;
69
+ queryLimit: number;
70
+ queriesAttempted: number;
71
+ relationsRequested: string[];
72
+ relationsSearched: string[];
73
+ relationsWithNoSearchableColumn: string[];
74
+ /** Approved relation/column identifiers that could not form ANSI probe SQL. */
75
+ relationsWithUnbuildableIdentifier: string[];
76
+ failedRelations: string[];
77
+ unknownRelations: string[];
78
+ }
79
+ /** The total maximum value-probe queries a single tool call may issue. */
80
+ export declare const MAX_VALUE_PROBE_COLUMN_QUERIES = 12;
81
+ /**
82
+ * A tool that answers "does this literal exist, and in which column?".
83
+ *
84
+ * Returns the matched VALUES — which is the point, since the loop needs the
85
+ * exact stored spelling to build a filter — but only from columns that passed
86
+ * both gates, and only values the caller already named.
87
+ */
88
+ export declare function buildSearchValuesTool(options: SearchValuesOptions): AgentToolDefinition;
89
+ //# sourceMappingURL=value-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-probe.d.ts","sourceRoot":"","sources":["../../src/agentic/value-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAkFD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAY9D;AAoBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,SAAK,GAAG,MAAM,GAAG,SAAS,CAqB7H;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;IACvD,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IACpC,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,wBAAwB,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAErH;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,wBAAwB,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,+BAA+B,EAAE,MAAM,EAAE,CAAC;IAC1C,+EAA+E;IAC/E,kCAAkC,EAAE,MAAM,EAAE,CAAC;IAC7C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,0EAA0E;AAC1E,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CA2IvF"}
@@ -0,0 +1,304 @@
1
+ /** Values that must never be probed, whatever the configuration says. */
2
+ /**
3
+ * Hard deny. No configuration overrides this.
4
+ *
5
+ * Three groups, and the reason each is here:
6
+ * SECRETS — a probe returns literal values, so one match leaks the secret.
7
+ * FREE TEXT — a note or description can contain anything, including all of
8
+ * the above, so its shape gives no safety.
9
+ * DIRECT AND REGULATED IDENTIFIERS — payment, government, contact, health,
10
+ * and compensation fields. A probe over these is a data-protection
11
+ * incident even when the query is otherwise correct, and "the model asked
12
+ * for it" is not a defence. Added after a live run answered a request for
13
+ * credit-card numbers and home addresses from the nearest certified block.
14
+ *
15
+ * Deliberately broad. A false deny costs one value lookup; a false allow
16
+ * cannot be undone once the values have left the warehouse.
17
+ */
18
+ const DENY_RE = /\b(password|passwd|secret|token|credential|apikey|api key|private key|hash|salt|signature|session|cookie|auth|otp|pin)\b|\b(notes?|comments?|description|message|body|payload|content|remarks?|feedback|reason)\b|\b(ssn|social security|social insurance|sin\b|dob|date of birth|birth date|birthdate|national id|government id|government identifier|tax id|taxpayer id|taxpayer identification|tin\b|itin\b|ein\b|medicare|medicaid|passport|license|licence|driver license|visa|nric|aadhaar)\b|\b(card|cardnumber|card number|credit card|debit card|cvv|cvc|iban|swift|bic|routing|account number|acct|sort code|bank)\b|\b(address|street|postal|postcode|zip|zipcode|latitude|longitude|geo|coordinates?)\b|\b(phone|mobile|telephone|fax|contact number)\b|\b(salary|compensation|wage|payroll|bonus|income|net pay|gross pay)\b|\b(medical|diagnosis|patient|health|insurance|prescription|disability|biometric|fingerprint|race|ethnicity|religion|gender|sexual)\b/;
19
+ /** Email is denied separately: it is an identifier, but also direct PII. */
20
+ const EMAIL_RE = /\bemail\b/;
21
+ /** Name shapes that plausibly identify an entity rather than describe one. */
22
+ const IDENTIFIER_TOKENS = new Set([
23
+ 'account', 'category', 'channel', 'city', 'code', 'country', 'customer',
24
+ 'full', 'id', 'key', 'member', 'name', 'number', 'product', 'region',
25
+ 'segment', 'sku', 'state', 'status', 'subscriber', 'tier', 'type', 'user',
26
+ ]);
27
+ /**
28
+ * Token-level aliases that must remain denied even when a connector exposes
29
+ * them with underscores, dashes, or camel case rather than the prose phrases
30
+ * above. The phrase regex is intentionally broad, but `tax_number` and
31
+ * `customerBirthDt` never contain the literal phrase "tax id" or "birth
32
+ * date". Normalise the identifier into tokens before the allow-list gets a
33
+ * chance to treat its `number` / `customer` part as a business key.
34
+ */
35
+ const SENSITIVE_IDENTIFIER_PREFIXES = new Set([
36
+ 'government', 'govt', 'national', 'tax', 'taxpayer',
37
+ ]);
38
+ const SENSITIVE_IDENTIFIER_SUFFIXES = new Set([
39
+ 'id', 'identifier', 'number', 'no', 'num',
40
+ ]);
41
+ // Connector metadata often elides separators inside an otherwise ordinary
42
+ // entity identifier (for example `customer_taxnumber`). Match only a
43
+ // sensitive alias at the end of the compact identifier: this catches the
44
+ // sensitive suffix without turning `customer_id` or `product_number` into a
45
+ // false positive.
46
+ const COMPACT_SENSITIVE_IDENTIFIER_ALIAS_RE = /(?:taxpayer|tax|government|govt|national)(?:id|identifier|number|no|num)$/;
47
+ const COMPACT_BIRTH_DATE_ALIAS_RE = /(?:birth(?:date|dt|day|dob|on)|dateofbirth|birthday)$/;
48
+ /** Types that can hold a searchable literal. */
49
+ const TEXTUAL_TYPE_RE = /\b(char|character|clob|string|text|uuid|varchar|nvarchar)\b/;
50
+ function tokenize(name) {
51
+ return new Set(name
52
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
53
+ .replace(/[_\-.]+/g, ' ')
54
+ .toLowerCase()
55
+ .split(/\s+/)
56
+ .filter(Boolean));
57
+ }
58
+ function isSensitiveIdentifierAlias(tokens) {
59
+ const has = (...values) => values.some((value) => tokens.has(value));
60
+ const compact = [...tokens].join('');
61
+ if (COMPACT_SENSITIVE_IDENTIFIER_ALIAS_RE.test(compact) || COMPACT_BIRTH_DATE_ALIAS_RE.test(compact)) {
62
+ return true;
63
+ }
64
+ // `date_of_birth`, `customer_birth_dt`, and `customerDOB` are all direct
65
+ // personal identifiers despite their otherwise identifier-shaped names.
66
+ if (has('dob') || (has('birth') && has('date', 'dt', 'day', 'on')))
67
+ return true;
68
+ // Treat a government/tax qualifier plus an identifier suffix as sensitive.
69
+ // This intentionally does not deny ordinary business identifiers such as
70
+ // `customer_id`, `product_number`, or `order_code`.
71
+ return has(...SENSITIVE_IDENTIFIER_PREFIXES)
72
+ && has(...SENSITIVE_IDENTIFIER_SUFFIXES);
73
+ }
74
+ /**
75
+ * May this column be probed for a literal?
76
+ *
77
+ * Canonical implementation — the host's `isAgentValueProbeColumn` delegates here
78
+ * so the deny-list has exactly one definition. Two copies of a security rule
79
+ * drift, and the one that drifts is the one nobody is looking at.
80
+ */
81
+ export function isProbeSafeColumn(column) {
82
+ const normalized = column.name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_\-.]+/g, ' ').toLowerCase();
83
+ if (DENY_RE.test(normalized))
84
+ return false;
85
+ if (EMAIL_RE.test(normalized))
86
+ return false;
87
+ const tokens = tokenize(column.name);
88
+ if (isSensitiveIdentifierAlias(tokens))
89
+ return false;
90
+ if (![...tokens].some((token) => IDENTIFIER_TOKENS.has(token)))
91
+ return false;
92
+ const type = column.type?.toLowerCase() ?? '';
93
+ // An unknown type is allowed: many drivers omit it, and the name gates already
94
+ // passed. A KNOWN non-textual type is not — a literal cannot live in a float.
95
+ if (!type)
96
+ return true;
97
+ return TEXTUAL_TYPE_RE.test(type);
98
+ }
99
+ /** Escape a single-quoted SQL literal. */
100
+ function sqlLiteral(value) {
101
+ return `'${value.replace(/'/g, "''")}'`;
102
+ }
103
+ /** Quote an identifier ANSI-style, rejecting anything that is not a plain name. */
104
+ function quoteIdentifier(value) {
105
+ // Identifiers come from the SCHEMA, never from the user, so anything exotic
106
+ // here means a caller is passing something it should not.
107
+ if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(value))
108
+ return undefined;
109
+ return `"${value}"`;
110
+ }
111
+ function quoteRelation(relation) {
112
+ const parts = relation.split('.').map(quoteIdentifier);
113
+ return parts.every(Boolean) ? parts.join('.') : undefined;
114
+ }
115
+ /**
116
+ * Build a bounded DISTINCT lookup for one column.
117
+ *
118
+ * Exact match first, then a prefix match on the longer tokens. Prefix rather
119
+ * than `%term%`: a leading wildcard cannot use an index, and on a large
120
+ * dimension table that is the difference between a probe and an outage.
121
+ */
122
+ export function buildValueProbeSql(relation, column, terms, limit = 25) {
123
+ const quotedRelation = quoteRelation(relation);
124
+ const quotedColumn = quoteIdentifier(column);
125
+ if (!quotedRelation || !quotedColumn)
126
+ return undefined;
127
+ const cast = `LOWER(CAST(${quotedColumn} AS VARCHAR))`;
128
+ const predicates = [];
129
+ for (const term of terms) {
130
+ const normalized = term.toLowerCase().replace(/\s+/g, ' ').trim();
131
+ if (!normalized)
132
+ continue;
133
+ predicates.push(`${cast} = ${sqlLiteral(normalized)}`);
134
+ for (const token of normalized.split(' ').filter((part) => part.length >= 4).slice(0, 2)) {
135
+ predicates.push(`${cast} LIKE ${sqlLiteral(`${token.replace(/[%_\\]/g, '\\$&')}%`)} ESCAPE '\\'`);
136
+ }
137
+ }
138
+ if (predicates.length === 0)
139
+ return undefined;
140
+ return [
141
+ `SELECT DISTINCT CAST(${quotedColumn} AS VARCHAR) AS value`,
142
+ `FROM ${quotedRelation}`,
143
+ `WHERE ${quotedColumn} IS NOT NULL AND (${[...new Set(predicates)].slice(0, 8).join(' OR ')})`,
144
+ `LIMIT ${Math.max(1, Math.min(limit, 50))}`,
145
+ ].join('\n');
146
+ }
147
+ /** The total maximum value-probe queries a single tool call may issue. */
148
+ export const MAX_VALUE_PROBE_COLUMN_QUERIES = 12;
149
+ /**
150
+ * A tool that answers "does this literal exist, and in which column?".
151
+ *
152
+ * Returns the matched VALUES — which is the point, since the loop needs the
153
+ * exact stored spelling to build a filter — but only from columns that passed
154
+ * both gates, and only values the caller already named.
155
+ */
156
+ export function buildSearchValuesTool(options) {
157
+ const maxRelations = options.maxRelations ?? 6;
158
+ const maxColumnQueries = Math.max(1, Math.min(options.maxColumnQueries ?? MAX_VALUE_PROBE_COLUMN_QUERIES, MAX_VALUE_PROBE_COLUMN_QUERIES));
159
+ return {
160
+ name: 'search_values',
161
+ description: 'Check whether a literal the question names (a customer, product, region, status) exists as a value in the data, and get its exact stored spelling. Use it BEFORE filtering on a name, so a filter is built from a real value rather than a guess. Only searches columns approved for value lookup.',
162
+ inputSchema: {
163
+ type: 'object',
164
+ additionalProperties: false,
165
+ required: ['terms'],
166
+ properties: {
167
+ terms: { type: 'array', items: { type: 'string' }, description: 'Literals named in the question, e.g. ["Wesley Jenkins"].' },
168
+ relations: { type: 'array', items: { type: 'string' }, description: 'Optional relations to restrict the search to.' },
169
+ },
170
+ },
171
+ run: async (args) => {
172
+ const input = (args && typeof args === 'object' ? args : {});
173
+ const terms = Array.isArray(input.terms)
174
+ ? input.terms.filter((term) => typeof term === 'string' && term.trim().length > 0)
175
+ : [];
176
+ if (terms.length === 0)
177
+ return { error: 'Pass the literal(s) to look up, e.g. ["Wesley Jenkins"].' };
178
+ if (!options.enabled) {
179
+ // Say WHY, and name the setting. A silent empty result here is what
180
+ // produced the false-absence defect: the loop concluded the value did
181
+ // not exist when it had simply never been allowed to look.
182
+ return {
183
+ searched: false,
184
+ reason: 'Value lookup is disabled for this project. Enable agent.runtimeValueGrounding in dql.config.json to let DQL confirm a named value before filtering on it.',
185
+ matches: [],
186
+ coverage: {
187
+ version: 1,
188
+ status: 'disabled',
189
+ queryLimit: maxColumnQueries,
190
+ queriesAttempted: 0,
191
+ relationsRequested: [],
192
+ relationsSearched: [],
193
+ relationsWithNoSearchableColumn: [],
194
+ relationsWithUnbuildableIdentifier: [],
195
+ failedRelations: [],
196
+ unknownRelations: [],
197
+ },
198
+ };
199
+ }
200
+ const requestedRelations = Array.isArray(input.relations)
201
+ ? [...new Set(input.relations.filter((r) => typeof r === 'string' && r.trim().length > 0).map((r) => r.trim()))]
202
+ : [];
203
+ const wanted = requestedRelations.length > 0
204
+ ? new Set(requestedRelations.map((relation) => relation.toLowerCase()))
205
+ : undefined;
206
+ const knownRelations = new Set(options.relations.map((relation) => relation.relation.toLowerCase()));
207
+ const unknownRelations = requestedRelations.filter((relation) => !knownRelations.has(relation.toLowerCase()));
208
+ const matches = [];
209
+ const searched = [];
210
+ const skipped = [];
211
+ const unbuildableRelations = new Set();
212
+ const failedRelations = new Set();
213
+ let queriesAttempted = 0;
214
+ let relationBudgetExceeded = false;
215
+ let queryBudgetExceeded = false;
216
+ let relationsConsidered = 0;
217
+ for (const relation of options.relations) {
218
+ if (wanted && !wanted.has(relation.relation.toLowerCase()))
219
+ continue;
220
+ if (relationsConsidered >= maxRelations) {
221
+ relationBudgetExceeded = true;
222
+ break;
223
+ }
224
+ relationsConsidered += 1;
225
+ const safe = relation.columns.filter(isProbeSafeColumn);
226
+ if (safe.length === 0) {
227
+ skipped.push(relation.relation);
228
+ continue;
229
+ }
230
+ for (const column of safe) {
231
+ if (queriesAttempted >= maxColumnQueries) {
232
+ queryBudgetExceeded = true;
233
+ break;
234
+ }
235
+ const sql = buildValueProbeSql(relation.relation, column.name, terms);
236
+ if (!sql) {
237
+ // Metadata identifiers are not automatically executable SQL
238
+ // identifiers. Never turn an unquotable schema name into a
239
+ // zero-query "not found" claim.
240
+ unbuildableRelations.add(relation.relation);
241
+ continue;
242
+ }
243
+ if (!searched.includes(relation.relation))
244
+ searched.push(relation.relation);
245
+ queriesAttempted += 1;
246
+ try {
247
+ const result = await options.execute(sql);
248
+ const values = (result.rows ?? [])
249
+ .map((row) => (Array.isArray(row) ? row[0] : row?.value))
250
+ .filter((value) => typeof value === 'string');
251
+ if (values.length > 0)
252
+ matches.push({ relation: relation.relation, column: column.name, values });
253
+ }
254
+ catch {
255
+ // One unreadable relation must not fail the whole probe; a permission
256
+ // error on a single table is normal in a governed warehouse.
257
+ failedRelations.add(relation.relation);
258
+ }
259
+ }
260
+ if (queryBudgetExceeded)
261
+ break;
262
+ }
263
+ const complete = unknownRelations.length === 0
264
+ && failedRelations.size === 0
265
+ && skipped.length === 0
266
+ && unbuildableRelations.size === 0
267
+ && !relationBudgetExceeded
268
+ && !queryBudgetExceeded;
269
+ const status = unknownRelations.length > 0
270
+ ? 'unknown_relation'
271
+ : queryBudgetExceeded || relationBudgetExceeded
272
+ ? 'budget_exhausted'
273
+ : complete
274
+ ? 'complete'
275
+ : 'partial';
276
+ const coverage = {
277
+ version: 1,
278
+ status,
279
+ queryLimit: maxColumnQueries,
280
+ queriesAttempted,
281
+ relationsRequested: requestedRelations,
282
+ relationsSearched: searched,
283
+ relationsWithNoSearchableColumn: skipped,
284
+ relationsWithUnbuildableIdentifier: [...unbuildableRelations],
285
+ failedRelations: [...failedRelations],
286
+ unknownRelations,
287
+ };
288
+ return {
289
+ searched: searched.length > 0,
290
+ terms,
291
+ matches,
292
+ relationsSearched: searched,
293
+ ...(skipped.length > 0 ? { relationsWithNoSearchableColumn: skipped } : {}),
294
+ coverage,
295
+ // Absence is a claim, not a default for an empty array. Only an
296
+ // exhaustive, error-free scan of the approved scope may support it.
297
+ ...(matches.length === 0 && complete
298
+ ? { absence: 'not_found', note: 'Searched the approved columns and found no match for these literals.' }
299
+ : {}),
300
+ };
301
+ },
302
+ };
303
+ }
304
+ //# sourceMappingURL=value-probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-probe.js","sourceRoot":"","sources":["../../src/agentic/value-probe.ts"],"names":[],"mappings":"AAkCA,yEAAyE;AACzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,GAAG,g7BAAg7B,CAAC;AACj8B,4EAA4E;AAC5E,MAAM,QAAQ,GAAG,WAAW,CAAC;AAE7B,8EAA8E;AAC9E,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU;IACvE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ;IACpE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAC1E,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,6BAA6B,GAAG,IAAI,GAAG,CAAC;IAC5C,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;CACpD,CAAC,CAAC;AACH,MAAM,6BAA6B,GAAG,IAAI,GAAG,CAAC;IAC5C,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK;CAC1C,CAAC,CAAC;AACH,0EAA0E;AAC1E,qEAAqE;AACrE,yEAAyE;AACzE,4EAA4E;AAC5E,kBAAkB;AAClB,MAAM,qCAAqC,GAAG,2EAA2E,CAAC;AAC1H,MAAM,2BAA2B,GAAG,uDAAuD,CAAC;AAE5F,gDAAgD;AAChD,MAAM,eAAe,GAAG,6DAA6D,CAAC;AAEtF,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,GAAG,CACZ,IAAI;SACD,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,WAAW,EAAE;SACb,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC,CACnB,CAAC;AACJ,CAAC;AAED,SAAS,0BAA0B,CAAC,MAA2B;IAC7D,MAAM,GAAG,GAAG,CAAC,GAAG,MAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,qCAAqC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACrG,OAAO,IAAI,CAAC;IACd,CAAC;IACD,yEAAyE;IACzE,wEAAwE;IACxE,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChF,2EAA2E;IAC3E,yEAAyE;IACzE,oDAAoD;IACpD,OAAO,GAAG,CAAC,GAAG,6BAA6B,CAAC;WACvC,GAAG,CAAC,GAAG,6BAA6B,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7G,IAAI,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,0BAA0B,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC9C,+EAA+E;IAC/E,8EAA8E;IAC9E,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,0CAA0C;AAC1C,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAC1C,CAAC;AAED,mFAAmF;AACnF,SAAS,eAAe,CAAC,KAAa;IACpC,4EAA4E;IAC5E,0DAA0D;IAC1D,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,IAAI,KAAK,GAAG,CAAC;AACtB,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACvD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,MAAc,EAAE,KAAwB,EAAE,KAAK,GAAG,EAAE;IACvG,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,cAAc,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IACvD,MAAM,IAAI,GAAG,cAAc,YAAY,eAAe,CAAC;IACvD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACvD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACzF,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,SAAS,UAAU,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACpG,CAAC;IACH,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO;QACL,wBAAwB,YAAY,uBAAuB;QAC3D,QAAQ,cAAc,EAAE;QACxB,SAAS,YAAY,qBAAqB,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG;QAC9F,SAAS,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE;KAC5C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAkCD,0EAA0E;AAC1E,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAAE,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA4B;IAChE,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC;IAC/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,8BAA8B,EAAE,8BAA8B,CAAC,CAAC,CAAC;IAC3I,OAAO;QACL,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,oSAAoS;QACtS,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,KAAK;YAC3B,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,0DAA0D,EAAE;gBAC5H,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,+CAA+C,EAAE;aACtH;SACF;QACD,GAAG,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;YAC3B,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAA6C,CAAC;YACzG,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;gBACtC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;gBAClG,CAAC,CAAC,EAAE,CAAC;YACP,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,0DAA0D,EAAE,CAAC;YACrG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACrB,oEAAoE;gBACpE,sEAAsE;gBACtE,2DAA2D;gBAC3D,OAAO;oBACL,QAAQ,EAAE,KAAK;oBACf,MAAM,EAAE,2JAA2J;oBACnK,OAAO,EAAE,EAAE;oBACX,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;wBACV,MAAM,EAAE,UAAU;wBAClB,UAAU,EAAE,gBAAgB;wBAC5B,gBAAgB,EAAE,CAAC;wBACnB,kBAAkB,EAAE,EAAE;wBACtB,iBAAiB,EAAE,EAAE;wBACrB,+BAA+B,EAAE,EAAE;wBACnC,kCAAkC,EAAE,EAAE;wBACtC,eAAe,EAAE,EAAE;wBACnB,gBAAgB,EAAE,EAAE;qBACU;iBACjC,CAAC;YACJ,CAAC;YACD,MAAM,kBAAkB,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;gBACvD,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC7H,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,GAAG,CAAC;gBAC1C,CAAC,CAAC,IAAI,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;gBACvE,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YACrG,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YAC9G,MAAM,OAAO,GAAkE,EAAE,CAAC;YAClF,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;YAC/C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;YAC1C,IAAI,gBAAgB,GAAG,CAAC,CAAC;YACzB,IAAI,sBAAsB,GAAG,KAAK,CAAC;YACnC,IAAI,mBAAmB,GAAG,KAAK,CAAC;YAChC,IAAI,mBAAmB,GAAG,CAAC,CAAC;YAC5B,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACzC,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;oBAAE,SAAS;gBACrE,IAAI,mBAAmB,IAAI,YAAY,EAAE,CAAC;oBACxC,sBAAsB,GAAG,IAAI,CAAC;oBAC9B,MAAM;gBACR,CAAC;gBACD,mBAAmB,IAAI,CAAC,CAAC;gBACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;gBACxD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAAC,SAAS;gBAAC,CAAC;gBACrE,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;oBAC1B,IAAI,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;wBACzC,mBAAmB,GAAG,IAAI,CAAC;wBAC3B,MAAM;oBACR,CAAC;oBACD,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;oBACtE,IAAI,CAAC,GAAG,EAAE,CAAC;wBACT,4DAA4D;wBAC5D,4DAA4D;wBAC5D,gCAAgC;wBAChC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBAC5C,SAAS;oBACX,CAAC;oBACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAC5E,gBAAgB,IAAI,CAAC,CAAC;oBACtB,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;wBAC1C,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;6BAC/B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,GAA+B,EAAE,KAAK,CAAC,CAAC;6BACrF,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;wBACjE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;4BAAE,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;oBACpG,CAAC;oBAAC,MAAM,CAAC;wBACP,sEAAsE;wBACtE,6DAA6D;wBAC7D,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACzC,CAAC;gBACH,CAAC;gBACD,IAAI,mBAAmB;oBAAE,MAAM;YACjC,CAAC;YACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,KAAK,CAAC;mBACzC,eAAe,CAAC,IAAI,KAAK,CAAC;mBAC1B,OAAO,CAAC,MAAM,KAAK,CAAC;mBACpB,oBAAoB,CAAC,IAAI,KAAK,CAAC;mBAC/B,CAAC,sBAAsB;mBACvB,CAAC,mBAAmB,CAAC;YAC1B,MAAM,MAAM,GAA6B,gBAAgB,CAAC,MAAM,GAAG,CAAC;gBAClE,CAAC,CAAC,kBAAkB;gBACpB,CAAC,CAAC,mBAAmB,IAAI,sBAAsB;oBAC7C,CAAC,CAAC,kBAAkB;oBACpB,CAAC,CAAC,QAAQ;wBACR,CAAC,CAAC,UAAU;wBACZ,CAAC,CAAC,SAAS,CAAC;YAClB,MAAM,QAAQ,GAAyB;gBACrC,OAAO,EAAE,CAAC;gBACV,MAAM;gBACN,UAAU,EAAE,gBAAgB;gBAC5B,gBAAgB;gBAChB,kBAAkB,EAAE,kBAAkB;gBACtC,iBAAiB,EAAE,QAAQ;gBAC3B,+BAA+B,EAAE,OAAO;gBACxC,kCAAkC,EAAE,CAAC,GAAG,oBAAoB,CAAC;gBAC7D,eAAe,EAAE,CAAC,GAAG,eAAe,CAAC;gBACrC,gBAAgB;aACjB,CAAC;YACF,OAAO;gBACL,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAC7B,KAAK;gBACL,OAAO;gBACP,iBAAiB,EAAE,QAAQ;gBAC3B,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,+BAA+B,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,QAAQ;gBACR,iEAAiE;gBACjE,oEAAoE;gBACpE,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ;oBAClC,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,sEAAsE,EAAE;oBACxG,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"analytical-frame.d.ts","sourceRoot":"","sources":["../src/analytical-frame.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAwE,KAAK,yBAAyB,EAAiC,MAAM,0BAA0B,CAAC;AAC/K,OAAO,EAAwB,KAAK,sBAAsB,EAAE,KAAK,sBAAsB,EAA2B,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC5K,OAAO,KAAK,EAAE,sBAAsB,EAA6B,MAAM,+BAA+B,CAAC;AAEvG;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,WAAW,EAAE,yBAAyB,CAAC;CACxC,GAAG,yBAAyB,CAoF5B;AA0BD,wBAAgB,iCAAiC,CAAC,KAAK,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,QAAQ,EAAE,sBAAsB,CAAC;IACjC,eAAe,EAAE,sBAAsB,CAAC;IACxC,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC5C,UAAU,EAAE,sBAAsB,EAAE,CAAC;CACtC,GAAG,yBAAyB,GAAG,SAAS,CAsOxC"}
1
+ {"version":3,"file":"analytical-frame.d.ts","sourceRoot":"","sources":["../src/analytical-frame.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAwE,KAAK,yBAAyB,EAAiC,MAAM,0BAA0B,CAAC;AAC/K,OAAO,EAAwB,KAAK,sBAAsB,EAAE,KAAK,sBAAsB,EAA2B,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC5K,OAAO,KAAK,EAAE,sBAAsB,EAA6B,MAAM,+BAA+B,CAAC;AAEvG;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,sBAAsB,CAAC;IAC7B,WAAW,EAAE,yBAAyB,CAAC;CACxC,GAAG,yBAAyB,CA8F5B;AA0BD,wBAAgB,iCAAiC,CAAC,KAAK,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,QAAQ,EAAE,sBAAsB,CAAC;IACjC,eAAe,EAAE,sBAAsB,CAAC;IACxC,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,sBAAsB,EAAE,CAAC;IAC5C,UAAU,EAAE,sBAAsB,EAAE,CAAC;CACtC,GAAG,yBAAyB,GAAG,SAAS,CAsOxC"}
@@ -24,7 +24,16 @@ export function projectResolvedAnalyticalFrame(input) {
24
24
  ...sourceFrame.metricConceptIds.filter((metricId) => metricId !== sourceFrame.metricConceptIds[0]),
25
25
  ])
26
26
  : unique(resolvedMeasureIds);
27
- const groupedDimensionIds = unique(plan.query.dimensions.flatMap((binding) => binding.status === 'resolved' && binding.qualifiedId ? [binding.qualifiedId] : []));
27
+ const sourceTimeDimensionId = sourceFrame.timeContext?.timeDimensionId;
28
+ const sourceTimeIsGrouped = Boolean(sourceTimeDimensionId && sourceFrame.dimensions.some((binding) => binding.dimensionId === sourceTimeDimensionId && binding.role === 'group_by'));
29
+ const groupedDimensionIds = unique(plan.query.dimensions.flatMap((binding) => binding.status === 'resolved' && binding.qualifiedId
30
+ // The ordinary RAP query list intentionally carries the time phrase for
31
+ // binding/audit. It must not silently turn a V2 time_axis into a
32
+ // group_by role when the source frame did not request a time-series
33
+ // output; that changes a current-vs-prior ranking into per-day rows.
34
+ && (binding.qualifiedId !== sourceTimeDimensionId || sourceTimeIsGrouped)
35
+ ? [binding.qualifiedId]
36
+ : []));
28
37
  const rankingRequested = Boolean(sourceFrame.ranking || plan.query.order || plan.query.limit !== undefined);
29
38
  const dimensions = groupedDimensionIds.flatMap((dimensionId, index) => [
30
39
  { dimensionId, role: 'group_by' },