@querypanel/node-sdk 1.0.51 → 1.0.53

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/index.d.cts CHANGED
@@ -180,6 +180,7 @@ declare const QueryErrorCode: {
180
180
  readonly SQL_GENERATION_FAILED: "SQL_GENERATION_FAILED";
181
181
  readonly SQL_VALIDATION_FAILED: "SQL_VALIDATION_FAILED";
182
182
  readonly CONTEXT_RETRIEVAL_FAILED: "CONTEXT_RETRIEVAL_FAILED";
183
+ readonly CLARIFICATION_NEEDED: "CLARIFICATION_NEEDED";
183
184
  readonly INTERNAL_ERROR: "INTERNAL_ERROR";
184
185
  readonly AUTHENTICATION_REQUIRED: "AUTHENTICATION_REQUIRED";
185
186
  readonly VALIDATION_ERROR: "VALIDATION_ERROR";
@@ -208,6 +209,10 @@ declare class QueryPipelineError extends Error {
208
209
  * Check if this is any guardrail error (relevance or security)
209
210
  */
210
211
  isGuardrailError(): boolean;
212
+ /**
213
+ * Check if this is a clarification needed error (v2 pipeline)
214
+ */
215
+ isClarificationNeeded(): boolean;
211
216
  }
212
217
 
213
218
  type ParamValue = string | number | boolean | string[] | number[];
@@ -514,6 +519,40 @@ interface AskOptions {
514
519
  * Use this to reuse a previously returned session for follow-up prompts.
515
520
  */
516
521
  querypanelSessionId?: string;
522
+ /**
523
+ * Pipeline version to use for query generation.
524
+ * - "v1" (default): Original query pipeline
525
+ * - "v2": Improved pipeline with intent planning, hybrid retrieval, schema linking, and SQL reflection
526
+ */
527
+ pipeline?: "v1" | "v2";
528
+ }
529
+ /**
530
+ * Intent analysis result from the v2 pipeline.
531
+ */
532
+ interface IntentResult {
533
+ intent: string;
534
+ confidence: number;
535
+ plan: {
536
+ tables: string[];
537
+ operations: string[];
538
+ filters: string[];
539
+ orderBy?: string;
540
+ limit?: number;
541
+ };
542
+ ambiguities: Array<{
543
+ issue: string;
544
+ suggestion: string;
545
+ }>;
546
+ }
547
+ /**
548
+ * Pipeline execution trace with step-level timing.
549
+ */
550
+ interface PipelineTrace {
551
+ totalDurationMs: number;
552
+ steps: Array<{
553
+ step: string;
554
+ durationMs: number;
555
+ }>;
517
556
  }
518
557
  /**
519
558
  * Response returned after executing a query.
@@ -545,6 +584,10 @@ interface AskResponse {
545
584
  target_db?: string;
546
585
  /** QueryPanel session ID for follow-up queries. */
547
586
  querypanelSessionId?: string;
587
+ /** Intent analysis from v2 pipeline. */
588
+ intent?: IntentResult;
589
+ /** Pipeline execution trace from v2 pipeline. */
590
+ trace?: PipelineTrace;
548
591
  }
549
592
  declare function anonymizeResults(rows: Array<Record<string, unknown>>): Array<Record<string, string>>;
550
593
 
@@ -688,6 +731,12 @@ interface ChartModifyOptions {
688
731
  chartMaxRetries?: number;
689
732
  /** Chart generation method: 'vega-lite' or 'vizspec' */
690
733
  chartType?: "vega-lite" | "vizspec";
734
+ /**
735
+ * Pipeline version to use for SQL regeneration.
736
+ * - "v1" (default): Original query pipeline
737
+ * - "v2": Improved pipeline with intent planning, hybrid retrieval, schema linking, and SQL reflection
738
+ */
739
+ pipeline?: "v1" | "v2";
691
740
  }
692
741
  /**
693
742
  * Response from modifyChart(), extending AskResponse with modification metadata.
@@ -1283,4 +1332,4 @@ declare class QueryPanelSdkAPI {
1283
1332
  }, signal?: AbortSignal): Promise<void>;
1284
1333
  }
1285
1334
 
1286
- export { type ActiveChartCreateInput, type ActiveChartListOptions, type ActiveChartUpdateInput, type AggregateOp, type AskOptions, type AskResponse, type AxisField, type AxisFieldInput, type ChartCreateInput, type ChartEncoding, type ChartEnvelope, type ChartListOptions, type ChartModifyInput, type ChartModifyOptions, type ChartModifyResponse, type ChartSpec, type ChartType, type ChartUpdateInput, ClickHouseAdapter, type ClickHouseAdapterOptions, type ClickHouseClientFn, type ContextDocument, type DatabaseAdapter, type DatabaseDialect, type DateRangeInput, type EncodingHints, type FieldRef, type FieldRefInput, type FieldType, type IngestResponse, type MetricEncoding, type MetricField, type MetricSpec, type PaginatedResponse$1 as PaginatedResponse, type PaginationInfo$1 as PaginationInfo, type PaginationQuery$1 as PaginationQuery, type ParamRecord, type ParamValue, PostgresAdapter, type PostgresAdapterOptions, type PostgresClientFn, QueryErrorCode, QueryErrorCode as QueryErrorCodeType, QueryPanelSdkAPI, QueryPipelineError, type SchemaIntrospection, type SchemaSyncOptions, type SdkActiveChart, type SdkChart, type SdkSession, type SdkSessionTurn, type SessionGetOptions, type SessionListOptions, type SessionUpdateInput, type SqlModifications, type StackingMode, type TableColumn, type TableEncoding, type TableSpec, type TimeUnit, type ValueFormat, type VizModifications, type VizSpec, type VizSpecGenerateInput, type VizSpecGenerateOptions, type VizSpecGeneratorInput, type VizSpecKind, type VizSpecResponse, type VizSpecResult, anonymizeResults };
1335
+ export { type ActiveChartCreateInput, type ActiveChartListOptions, type ActiveChartUpdateInput, type AggregateOp, type AskOptions, type AskResponse, type AxisField, type AxisFieldInput, type ChartCreateInput, type ChartEncoding, type ChartEnvelope, type ChartListOptions, type ChartModifyInput, type ChartModifyOptions, type ChartModifyResponse, type ChartSpec, type ChartType, type ChartUpdateInput, ClickHouseAdapter, type ClickHouseAdapterOptions, type ClickHouseClientFn, type ContextDocument, type DatabaseAdapter, type DatabaseDialect, type DateRangeInput, type EncodingHints, type FieldRef, type FieldRefInput, type FieldType, type IngestResponse, type IntentResult, type MetricEncoding, type MetricField, type MetricSpec, type PaginatedResponse$1 as PaginatedResponse, type PaginationInfo$1 as PaginationInfo, type PaginationQuery$1 as PaginationQuery, type ParamRecord, type ParamValue, type PipelineTrace, PostgresAdapter, type PostgresAdapterOptions, type PostgresClientFn, QueryErrorCode, QueryErrorCode as QueryErrorCodeType, QueryPanelSdkAPI, QueryPipelineError, type SchemaIntrospection, type SchemaSyncOptions, type SdkActiveChart, type SdkChart, type SdkSession, type SdkSessionTurn, type SessionGetOptions, type SessionListOptions, type SessionUpdateInput, type SqlModifications, type StackingMode, type TableColumn, type TableEncoding, type TableSpec, type TimeUnit, type ValueFormat, type VizModifications, type VizSpec, type VizSpecGenerateInput, type VizSpecGenerateOptions, type VizSpecGeneratorInput, type VizSpecKind, type VizSpecResponse, type VizSpecResult, anonymizeResults };
package/dist/index.d.ts CHANGED
@@ -180,6 +180,7 @@ declare const QueryErrorCode: {
180
180
  readonly SQL_GENERATION_FAILED: "SQL_GENERATION_FAILED";
181
181
  readonly SQL_VALIDATION_FAILED: "SQL_VALIDATION_FAILED";
182
182
  readonly CONTEXT_RETRIEVAL_FAILED: "CONTEXT_RETRIEVAL_FAILED";
183
+ readonly CLARIFICATION_NEEDED: "CLARIFICATION_NEEDED";
183
184
  readonly INTERNAL_ERROR: "INTERNAL_ERROR";
184
185
  readonly AUTHENTICATION_REQUIRED: "AUTHENTICATION_REQUIRED";
185
186
  readonly VALIDATION_ERROR: "VALIDATION_ERROR";
@@ -208,6 +209,10 @@ declare class QueryPipelineError extends Error {
208
209
  * Check if this is any guardrail error (relevance or security)
209
210
  */
210
211
  isGuardrailError(): boolean;
212
+ /**
213
+ * Check if this is a clarification needed error (v2 pipeline)
214
+ */
215
+ isClarificationNeeded(): boolean;
211
216
  }
212
217
 
213
218
  type ParamValue = string | number | boolean | string[] | number[];
@@ -514,6 +519,40 @@ interface AskOptions {
514
519
  * Use this to reuse a previously returned session for follow-up prompts.
515
520
  */
516
521
  querypanelSessionId?: string;
522
+ /**
523
+ * Pipeline version to use for query generation.
524
+ * - "v1" (default): Original query pipeline
525
+ * - "v2": Improved pipeline with intent planning, hybrid retrieval, schema linking, and SQL reflection
526
+ */
527
+ pipeline?: "v1" | "v2";
528
+ }
529
+ /**
530
+ * Intent analysis result from the v2 pipeline.
531
+ */
532
+ interface IntentResult {
533
+ intent: string;
534
+ confidence: number;
535
+ plan: {
536
+ tables: string[];
537
+ operations: string[];
538
+ filters: string[];
539
+ orderBy?: string;
540
+ limit?: number;
541
+ };
542
+ ambiguities: Array<{
543
+ issue: string;
544
+ suggestion: string;
545
+ }>;
546
+ }
547
+ /**
548
+ * Pipeline execution trace with step-level timing.
549
+ */
550
+ interface PipelineTrace {
551
+ totalDurationMs: number;
552
+ steps: Array<{
553
+ step: string;
554
+ durationMs: number;
555
+ }>;
517
556
  }
518
557
  /**
519
558
  * Response returned after executing a query.
@@ -545,6 +584,10 @@ interface AskResponse {
545
584
  target_db?: string;
546
585
  /** QueryPanel session ID for follow-up queries. */
547
586
  querypanelSessionId?: string;
587
+ /** Intent analysis from v2 pipeline. */
588
+ intent?: IntentResult;
589
+ /** Pipeline execution trace from v2 pipeline. */
590
+ trace?: PipelineTrace;
548
591
  }
549
592
  declare function anonymizeResults(rows: Array<Record<string, unknown>>): Array<Record<string, string>>;
550
593
 
@@ -688,6 +731,12 @@ interface ChartModifyOptions {
688
731
  chartMaxRetries?: number;
689
732
  /** Chart generation method: 'vega-lite' or 'vizspec' */
690
733
  chartType?: "vega-lite" | "vizspec";
734
+ /**
735
+ * Pipeline version to use for SQL regeneration.
736
+ * - "v1" (default): Original query pipeline
737
+ * - "v2": Improved pipeline with intent planning, hybrid retrieval, schema linking, and SQL reflection
738
+ */
739
+ pipeline?: "v1" | "v2";
691
740
  }
692
741
  /**
693
742
  * Response from modifyChart(), extending AskResponse with modification metadata.
@@ -1283,4 +1332,4 @@ declare class QueryPanelSdkAPI {
1283
1332
  }, signal?: AbortSignal): Promise<void>;
1284
1333
  }
1285
1334
 
1286
- export { type ActiveChartCreateInput, type ActiveChartListOptions, type ActiveChartUpdateInput, type AggregateOp, type AskOptions, type AskResponse, type AxisField, type AxisFieldInput, type ChartCreateInput, type ChartEncoding, type ChartEnvelope, type ChartListOptions, type ChartModifyInput, type ChartModifyOptions, type ChartModifyResponse, type ChartSpec, type ChartType, type ChartUpdateInput, ClickHouseAdapter, type ClickHouseAdapterOptions, type ClickHouseClientFn, type ContextDocument, type DatabaseAdapter, type DatabaseDialect, type DateRangeInput, type EncodingHints, type FieldRef, type FieldRefInput, type FieldType, type IngestResponse, type MetricEncoding, type MetricField, type MetricSpec, type PaginatedResponse$1 as PaginatedResponse, type PaginationInfo$1 as PaginationInfo, type PaginationQuery$1 as PaginationQuery, type ParamRecord, type ParamValue, PostgresAdapter, type PostgresAdapterOptions, type PostgresClientFn, QueryErrorCode, QueryErrorCode as QueryErrorCodeType, QueryPanelSdkAPI, QueryPipelineError, type SchemaIntrospection, type SchemaSyncOptions, type SdkActiveChart, type SdkChart, type SdkSession, type SdkSessionTurn, type SessionGetOptions, type SessionListOptions, type SessionUpdateInput, type SqlModifications, type StackingMode, type TableColumn, type TableEncoding, type TableSpec, type TimeUnit, type ValueFormat, type VizModifications, type VizSpec, type VizSpecGenerateInput, type VizSpecGenerateOptions, type VizSpecGeneratorInput, type VizSpecKind, type VizSpecResponse, type VizSpecResult, anonymizeResults };
1335
+ export { type ActiveChartCreateInput, type ActiveChartListOptions, type ActiveChartUpdateInput, type AggregateOp, type AskOptions, type AskResponse, type AxisField, type AxisFieldInput, type ChartCreateInput, type ChartEncoding, type ChartEnvelope, type ChartListOptions, type ChartModifyInput, type ChartModifyOptions, type ChartModifyResponse, type ChartSpec, type ChartType, type ChartUpdateInput, ClickHouseAdapter, type ClickHouseAdapterOptions, type ClickHouseClientFn, type ContextDocument, type DatabaseAdapter, type DatabaseDialect, type DateRangeInput, type EncodingHints, type FieldRef, type FieldRefInput, type FieldType, type IngestResponse, type IntentResult, type MetricEncoding, type MetricField, type MetricSpec, type PaginatedResponse$1 as PaginatedResponse, type PaginationInfo$1 as PaginationInfo, type PaginationQuery$1 as PaginationQuery, type ParamRecord, type ParamValue, type PipelineTrace, PostgresAdapter, type PostgresAdapterOptions, type PostgresClientFn, QueryErrorCode, QueryErrorCode as QueryErrorCodeType, QueryPanelSdkAPI, QueryPipelineError, type SchemaIntrospection, type SchemaSyncOptions, type SdkActiveChart, type SdkChart, type SdkSession, type SdkSessionTurn, type SessionGetOptions, type SessionListOptions, type SessionUpdateInput, type SqlModifications, type StackingMode, type TableColumn, type TableEncoding, type TableSpec, type TimeUnit, type ValueFormat, type VizModifications, type VizSpec, type VizSpecGenerateInput, type VizSpecGenerateOptions, type VizSpecGeneratorInput, type VizSpecKind, type VizSpecResponse, type VizSpecResult, anonymizeResults };
package/dist/index.js CHANGED
@@ -888,6 +888,8 @@ var QueryErrorCode = {
888
888
  SQL_VALIDATION_FAILED: "SQL_VALIDATION_FAILED",
889
889
  // Context retrieval errors
890
890
  CONTEXT_RETRIEVAL_FAILED: "CONTEXT_RETRIEVAL_FAILED",
891
+ // Clarification errors (v2)
892
+ CLARIFICATION_NEEDED: "CLARIFICATION_NEEDED",
891
893
  // General errors
892
894
  INTERNAL_ERROR: "INTERNAL_ERROR",
893
895
  AUTHENTICATION_REQUIRED: "AUTHENTICATION_REQUIRED",
@@ -924,6 +926,12 @@ var QueryPipelineError = class extends Error {
924
926
  isGuardrailError() {
925
927
  return this.isRelevanceError() || this.isSecurityError();
926
928
  }
929
+ /**
930
+ * Check if this is a clarification needed error (v2 pipeline)
931
+ */
932
+ isClarificationNeeded() {
933
+ return this.code === QueryErrorCode.CLARIFICATION_NEEDED;
934
+ }
927
935
  };
928
936
 
929
937
  // src/routes/charts.ts
@@ -1235,6 +1243,7 @@ async function ask(client, queryEngine, question, options, signal) {
1235
1243
  let attempt = 0;
1236
1244
  let lastError = options.lastError;
1237
1245
  let previousSql = options.previousSql;
1246
+ const queryEndpoint = options.pipeline === "v2" ? "/v2/query" : "/query";
1238
1247
  while (attempt <= maxRetry) {
1239
1248
  console.log({ lastError, previousSql });
1240
1249
  const databaseName = options.database ?? queryEngine.getDefaultDatabase();
@@ -1248,7 +1257,7 @@ async function ask(client, queryEngine, question, options, signal) {
1248
1257
  };
1249
1258
  }
1250
1259
  const queryResponse = await client.postWithHeaders(
1251
- "/query",
1260
+ queryEndpoint,
1252
1261
  {
1253
1262
  question,
1254
1263
  ...querypanelSessionId ? { session_id: querypanelSessionId } : {},
@@ -1364,7 +1373,9 @@ async function ask(client, queryEngine, question, options, signal) {
1364
1373
  context: queryResponse.data.context,
1365
1374
  attempts: attempt + 1,
1366
1375
  target_db: dbName,
1367
- querypanelSessionId: responseSessionId ?? void 0
1376
+ querypanelSessionId: responseSessionId ?? void 0,
1377
+ intent: queryResponse.data.intent,
1378
+ trace: queryResponse.data.trace
1368
1379
  };
1369
1380
  } catch (error) {
1370
1381
  attempt++;
@@ -1403,21 +1414,39 @@ function anonymizeResults(rows) {
1403
1414
  }
1404
1415
 
1405
1416
  // src/routes/modify.ts
1406
- function buildModifiedQuestion(originalQuestion, modifications) {
1417
+ function buildModifiedQuestion(originalQuestion, modifications, pipeline) {
1407
1418
  const hints = [];
1408
1419
  if (modifications.timeGranularity) {
1409
1420
  hints.push(`group results by ${modifications.timeGranularity}`);
1410
1421
  }
1411
1422
  if (modifications.dateRange) {
1412
- const parts = [];
1413
- if (modifications.dateRange.from) {
1414
- parts.push(`from ${modifications.dateRange.from}`);
1415
- }
1416
- if (modifications.dateRange.to) {
1417
- parts.push(`to ${modifications.dateRange.to}`);
1418
- }
1419
- if (parts.length > 0) {
1420
- hints.push(`filter date range ${parts.join(" ")}`);
1423
+ if (pipeline === "v2") {
1424
+ const from = normalizeDateInput(modifications.dateRange.from);
1425
+ const to = normalizeDateInput(modifications.dateRange.to);
1426
+ if (from && to) {
1427
+ hints.push(
1428
+ `replace any existing date filters with exact date range from ${from} to ${to} (inclusive, do not add extra days)`
1429
+ );
1430
+ } else if (from) {
1431
+ hints.push(
1432
+ `replace any existing date filters with exact start date ${from} (do not shift this date)`
1433
+ );
1434
+ } else if (to) {
1435
+ hints.push(
1436
+ `replace any existing date filters with exact end date ${to} (inclusive, do not add extra days)`
1437
+ );
1438
+ }
1439
+ } else {
1440
+ const parts = [];
1441
+ if (modifications.dateRange.from) {
1442
+ parts.push(`from ${modifications.dateRange.from}`);
1443
+ }
1444
+ if (modifications.dateRange.to) {
1445
+ parts.push(`to ${modifications.dateRange.to}`);
1446
+ }
1447
+ if (parts.length > 0) {
1448
+ hints.push(`filter date range ${parts.join(" ")}`);
1449
+ }
1421
1450
  }
1422
1451
  }
1423
1452
  if (modifications.additionalInstructions) {
@@ -1428,6 +1457,67 @@ function buildModifiedQuestion(originalQuestion, modifications) {
1428
1457
  }
1429
1458
  return `${originalQuestion} (${hints.join(", ")})`;
1430
1459
  }
1460
+ var START_PARAM_KEY_REGEX = /(^|_)(start|from)(_|$)/i;
1461
+ var END_PARAM_KEY_REGEX = /(^|_)(end|to)(_|$)/i;
1462
+ var ISO_DATETIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z?$/;
1463
+ var SQL_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
1464
+ var SQL_DATETIME_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
1465
+ function normalizeDateInput(value) {
1466
+ if (!value) return void 0;
1467
+ const trimmed = value.trim();
1468
+ if (!trimmed) return void 0;
1469
+ if (ISO_DATETIME_RE.test(trimmed)) {
1470
+ return trimmed.replace("T", " ").replace(/\.\d+Z?$/, "").replace(/Z$/, "");
1471
+ }
1472
+ return trimmed;
1473
+ }
1474
+ function keyLooksLikeDateBoundary(key, boundary) {
1475
+ return boundary === "start" ? START_PARAM_KEY_REGEX.test(key) : END_PARAM_KEY_REGEX.test(key);
1476
+ }
1477
+ function hasTimeComponent(value) {
1478
+ return typeof value === "string" && /\d{2}:\d{2}:\d{2}/.test(value);
1479
+ }
1480
+ function formatDateOverride(dateValue, boundary, existingValue) {
1481
+ if (SQL_DATE_RE.test(dateValue) && !hasTimeComponent(existingValue)) {
1482
+ return dateValue;
1483
+ }
1484
+ if (SQL_DATE_RE.test(dateValue)) {
1485
+ return `${dateValue} ${boundary === "start" ? "00:00:00" : "23:59:59"}`;
1486
+ }
1487
+ if (SQL_DATETIME_RE.test(dateValue)) {
1488
+ return dateValue;
1489
+ }
1490
+ return dateValue;
1491
+ }
1492
+ function normalizeGeneratedParamKey(param, index) {
1493
+ const nameCandidate = typeof param.name === "string" && param.name.trim() || typeof param.placeholder === "string" && param.placeholder.trim() || typeof param.position === "number" && String(param.position) || String(index + 1);
1494
+ return nameCandidate.replace(/[{}]/g, "").replace(/(.+):.*$/, "$1").replace(/^[:$]/, "").trim();
1495
+ }
1496
+ function applyDateRangeOverrides(dateRange, params, paramMetadata) {
1497
+ if (!dateRange) return;
1498
+ const from = normalizeDateInput(dateRange.from);
1499
+ const to = normalizeDateInput(dateRange.to);
1500
+ if (!from && !to) return;
1501
+ for (const [key, value] of Object.entries(params)) {
1502
+ if (from && keyLooksLikeDateBoundary(key, "start")) {
1503
+ params[key] = formatDateOverride(from, "start", value);
1504
+ }
1505
+ if (to && keyLooksLikeDateBoundary(key, "end")) {
1506
+ params[key] = formatDateOverride(to, "end", value);
1507
+ }
1508
+ }
1509
+ for (let i = 0; i < paramMetadata.length; i++) {
1510
+ const param = paramMetadata[i];
1511
+ if (!param) continue;
1512
+ const key = normalizeGeneratedParamKey(param, i);
1513
+ if (from && keyLooksLikeDateBoundary(key, "start")) {
1514
+ param.value = formatDateOverride(from, "start", param.value);
1515
+ }
1516
+ if (to && keyLooksLikeDateBoundary(key, "end")) {
1517
+ param.value = formatDateOverride(to, "end", param.value);
1518
+ }
1519
+ }
1520
+ }
1431
1521
  function buildVizHints(modifications) {
1432
1522
  const hints = {};
1433
1523
  if (modifications.kind) {
@@ -1460,6 +1550,9 @@ function stripVizSpecOnlyHints(hints) {
1460
1550
  const { kind: _kind, ...rest } = hints;
1461
1551
  return rest;
1462
1552
  }
1553
+ function isDateRangeOnly(mods) {
1554
+ return !!mods.dateRange && !mods.timeGranularity && !mods.additionalInstructions && !mods.customSql;
1555
+ }
1463
1556
  function resolveTenantId5(client, tenantId) {
1464
1557
  const resolved = tenantId ?? client.getDefaultTenantId();
1465
1558
  if (!resolved) {
@@ -1476,12 +1569,14 @@ async function modifyChart(client, queryEngine, input, options, signal) {
1476
1569
  const hasSqlMods = !!input.sqlModifications;
1477
1570
  const hasVizMods = !!input.vizModifications;
1478
1571
  const hasCustomSql = !!input.sqlModifications?.customSql;
1572
+ const queryEndpoint = options?.pipeline === "v2" ? "/v2/query" : "/query";
1479
1573
  let finalSql = input.sql;
1480
1574
  let finalParams = input.params ?? {};
1481
1575
  let paramMetadata = [];
1482
1576
  let rationale;
1483
1577
  let queryId;
1484
1578
  let sqlChanged = false;
1579
+ let finalQuestion = input.question;
1485
1580
  const databaseName = input.database ?? queryEngine.getDefaultDatabase();
1486
1581
  if (!databaseName) {
1487
1582
  throw new Error(
@@ -1502,13 +1597,89 @@ async function modifyChart(client, queryEngine, input, options, signal) {
1502
1597
  finalParams = {};
1503
1598
  paramMetadata = [];
1504
1599
  sqlChanged = true;
1600
+ } else if (hasSqlMods && options?.pipeline === "v2" && isDateRangeOnly(input.sqlModifications)) {
1601
+ let usedFastPath = false;
1602
+ try {
1603
+ const rewriteResponse = await client.post(
1604
+ "/v2/rewrite-datefilter",
1605
+ {
1606
+ previous_sql: input.sql,
1607
+ previous_params: input.params ? Object.entries(input.params).map(([name, value]) => ({
1608
+ name,
1609
+ value
1610
+ })) : [],
1611
+ date_range: input.sqlModifications.dateRange,
1612
+ question: input.question,
1613
+ ...tenantSettings ? { tenant_settings: tenantSettings } : {},
1614
+ ...databaseName ? { database: databaseName } : {},
1615
+ ...metadata?.dialect ? { dialect: metadata.dialect } : {}
1616
+ },
1617
+ tenantId,
1618
+ options?.userId,
1619
+ options?.scopes,
1620
+ signal,
1621
+ sessionId
1622
+ );
1623
+ finalSql = rewriteResponse.sql;
1624
+ paramMetadata = Array.isArray(rewriteResponse.params) ? rewriteResponse.params : [];
1625
+ finalParams = queryEngine.mapGeneratedParams(paramMetadata);
1626
+ applyDateRangeOverrides(
1627
+ input.sqlModifications?.dateRange,
1628
+ finalParams,
1629
+ paramMetadata
1630
+ );
1631
+ rationale = rewriteResponse.rationale;
1632
+ queryId = rewriteResponse.queryId;
1633
+ sqlChanged = finalSql !== input.sql;
1634
+ usedFastPath = true;
1635
+ } catch {
1636
+ }
1637
+ if (!usedFastPath) {
1638
+ const modifiedQuestion = buildModifiedQuestion(
1639
+ input.question,
1640
+ input.sqlModifications,
1641
+ "v2"
1642
+ );
1643
+ finalQuestion = modifiedQuestion;
1644
+ const queryResponse = await client.post(
1645
+ queryEndpoint,
1646
+ {
1647
+ question: modifiedQuestion,
1648
+ previous_sql: input.sql,
1649
+ ...options?.maxRetry ? { max_retry: options.maxRetry } : {},
1650
+ ...tenantSettings ? { tenant_settings: tenantSettings } : {},
1651
+ ...databaseName ? { database: databaseName } : {},
1652
+ ...metadata?.dialect ? { dialect: metadata.dialect } : {}
1653
+ },
1654
+ tenantId,
1655
+ options?.userId,
1656
+ options?.scopes,
1657
+ signal,
1658
+ sessionId
1659
+ );
1660
+ finalSql = queryResponse.sql;
1661
+ paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
1662
+ finalParams = queryEngine.mapGeneratedParams(paramMetadata);
1663
+ applyDateRangeOverrides(
1664
+ input.sqlModifications?.dateRange,
1665
+ finalParams,
1666
+ paramMetadata
1667
+ );
1668
+ rationale = queryResponse.rationale;
1669
+ queryId = queryResponse.queryId;
1670
+ sqlChanged = finalSql !== input.sql;
1671
+ }
1505
1672
  } else if (hasSqlMods && !hasCustomSql) {
1506
1673
  const modifiedQuestion = buildModifiedQuestion(
1507
1674
  input.question,
1508
- input.sqlModifications
1675
+ input.sqlModifications,
1676
+ options?.pipeline
1509
1677
  );
1678
+ if (options?.pipeline === "v2") {
1679
+ finalQuestion = modifiedQuestion;
1680
+ }
1510
1681
  const queryResponse = await client.post(
1511
- "/query",
1682
+ queryEndpoint,
1512
1683
  {
1513
1684
  question: modifiedQuestion,
1514
1685
  previous_sql: input.sql,
@@ -1526,6 +1697,13 @@ async function modifyChart(client, queryEngine, input, options, signal) {
1526
1697
  finalSql = queryResponse.sql;
1527
1698
  paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
1528
1699
  finalParams = queryEngine.mapGeneratedParams(paramMetadata);
1700
+ if (options?.pipeline === "v2") {
1701
+ applyDateRangeOverrides(
1702
+ input.sqlModifications?.dateRange,
1703
+ finalParams,
1704
+ paramMetadata
1705
+ );
1706
+ }
1529
1707
  rationale = queryResponse.rationale;
1530
1708
  queryId = queryResponse.queryId;
1531
1709
  sqlChanged = finalSql !== input.sql;
@@ -1548,7 +1726,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
1548
1726
  const vizspecResponse = await client.post(
1549
1727
  "/vizspec",
1550
1728
  {
1551
- question: input.question,
1729
+ question: finalQuestion,
1552
1730
  sql: finalSql,
1553
1731
  rationale,
1554
1732
  fields: execution.fields,
@@ -1573,7 +1751,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
1573
1751
  const chartResponse = await client.post(
1574
1752
  "/chart",
1575
1753
  {
1576
- question: input.question,
1754
+ question: finalQuestion,
1577
1755
  sql: finalSql,
1578
1756
  rationale,
1579
1757
  fields: execution.fields,