@querypanel/node-sdk 1.3.0 → 1.3.1

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/README.md CHANGED
@@ -544,7 +544,7 @@ Every request is signed with `RS256` using the private key you pass to the const
544
544
 
545
545
  - HTTP errors propagate as thrown `Error` instances that include `status` (and `details` when available).
546
546
  - `syncSchema` automatically skips embedding if the schema hasn't changed (drift detection). Use `syncSchema(..., { forceReindex: true })` to force updates.
547
- - `ask()` raises immediately for guardrail/moderation errors because `/query` responds with 4xx/5xx.
547
+ - `ask()` raises immediately for guardrail/moderation errors because `/v2/query` responds with 4xx/5xx. `pipeline: "v1"` is not accepted.
548
548
 
549
549
  ### Automatic SQL repair and retry
550
550
 
package/dist/index.cjs CHANGED
@@ -61,6 +61,13 @@ var BigQueryAdapter = class {
61
61
  );
62
62
  }
63
63
  }
64
+ clientFn;
65
+ projectId;
66
+ datasetProjectId;
67
+ defaultDataset;
68
+ databaseName;
69
+ kind;
70
+ allowedTables;
64
71
  async execute(sql, params) {
65
72
  if (this.allowedTables) {
66
73
  this.validateQueryTables(sql);
@@ -291,6 +298,11 @@ var ClickHouseAdapter = class {
291
298
  this.allowedTables = normalizeTableFilter2(options.allowedTables);
292
299
  }
293
300
  }
301
+ clientFn;
302
+ databaseName;
303
+ defaultFormat;
304
+ kind;
305
+ allowedTables;
294
306
  async execute(sql, params) {
295
307
  if (this.allowedTables) {
296
308
  this.validateQueryTables(sql);
@@ -544,6 +556,11 @@ var PostgresAdapter = class {
544
556
  );
545
557
  }
546
558
  }
559
+ clientFn;
560
+ databaseName;
561
+ defaultSchema;
562
+ kind;
563
+ allowedTables;
547
564
  async execute(sql, params) {
548
565
  if (this.allowedTables) {
549
566
  this.validateQueryTables(sql);
@@ -852,6 +869,9 @@ var QueryPipelineError = class extends Error {
852
869
  this.status = status;
853
870
  this.name = "QueryPipelineError";
854
871
  }
872
+ code;
873
+ details;
874
+ status;
855
875
  /**
856
876
  * Check if this is a moderation error
857
877
  */
@@ -904,8 +924,14 @@ var QueryPipelineError = class extends Error {
904
924
 
905
925
  // src/core/client.ts
906
926
  var ApiClient = class {
927
+ baseUrl;
928
+ privateKey;
929
+ organizationId;
930
+ defaultTenantId;
931
+ additionalHeaders;
932
+ fetchImpl;
933
+ cryptoKey = null;
907
934
  constructor(baseUrl, privateKey, organizationId, options) {
908
- this.cryptoKey = null;
909
935
  if (!baseUrl) {
910
936
  throw new Error("Base URL is required");
911
937
  }
@@ -1159,6 +1185,8 @@ var ApiClient = class {
1159
1185
 
1160
1186
  // src/core/callback-client.ts
1161
1187
  var CallbackApiClient = class {
1188
+ requestHandler;
1189
+ defaultTenantId;
1162
1190
  constructor(requestHandler, options) {
1163
1191
  this.requestHandler = requestHandler;
1164
1192
  this.defaultTenantId = options?.defaultTenantId;
@@ -1301,10 +1329,9 @@ function normalizeSqlParamsInput(params) {
1301
1329
 
1302
1330
  // src/core/query-engine.ts
1303
1331
  var QueryEngine = class {
1304
- constructor() {
1305
- this.databases = /* @__PURE__ */ new Map();
1306
- this.databaseMetadata = /* @__PURE__ */ new Map();
1307
- }
1332
+ databases = /* @__PURE__ */ new Map();
1333
+ databaseMetadata = /* @__PURE__ */ new Map();
1334
+ defaultDatabase;
1308
1335
  attachDatabase(name, adapter, metadata) {
1309
1336
  this.databases.set(name, adapter);
1310
1337
  this.databaseMetadata.set(name, metadata);
@@ -1990,7 +2017,13 @@ var import_node_crypto4 = __toESM(require("crypto"), 1);
1990
2017
  // src/routes/query.ts
1991
2018
  var import_node_crypto3 = __toESM(require("crypto"), 1);
1992
2019
  function resolveQueryPipeline(pipeline) {
1993
- return pipeline ?? "v2";
2020
+ const requested = pipeline;
2021
+ if (requested != null && requested !== "v2") {
2022
+ throw new Error(
2023
+ `Query pipeline "${requested}" was removed. ask() and modifyChart() always use POST /v2/query.`
2024
+ );
2025
+ }
2026
+ return "v2";
1994
2027
  }
1995
2028
  async function ask(client, queryEngine, question, options, signal) {
1996
2029
  const tenantId = resolveTenantId5(client, options.tenantId);
@@ -2000,8 +2033,9 @@ async function ask(client, queryEngine, question, options, signal) {
2000
2033
  let attempt = 0;
2001
2034
  let lastError = options.lastError;
2002
2035
  let previousSql = options.previousSql;
2003
- const pipeline = resolveQueryPipeline(options.pipeline);
2004
- const queryEndpoint = pipeline === "v2" ? "/v2/query" : "/query";
2036
+ let parentQueryId;
2037
+ resolveQueryPipeline(options.pipeline);
2038
+ const queryEndpoint = "/v2/query";
2005
2039
  while (attempt <= maxRetry) {
2006
2040
  const databaseName = options.database ?? queryEngine.getDefaultDatabase();
2007
2041
  const metadata = databaseName ? queryEngine.getDatabaseMetadata(databaseName) : void 0;
@@ -2031,7 +2065,8 @@ async function ask(client, queryEngine, question, options, signal) {
2031
2065
  ...databaseName ? { database: databaseName } : {},
2032
2066
  ...metadata?.dialect ? { dialect: metadata.dialect } : {},
2033
2067
  ...options.model?.trim() ? { model: options.model.trim() } : {},
2034
- ...pipeline === "v2" && options.systemPrompt?.trim() ? { system_prompt: options.systemPrompt.trim() } : {},
2068
+ ...options.systemPrompt?.trim() ? { system_prompt: options.systemPrompt.trim() } : {},
2069
+ ...parentQueryId ? { parent_query_id: parentQueryId } : {},
2035
2070
  debug: options.debug ?? false
2036
2071
  },
2037
2072
  tenantId,
@@ -2053,6 +2088,9 @@ async function ask(client, queryEngine, question, options, signal) {
2053
2088
  if (!sql || !dialect) {
2054
2089
  throw new Error("Query response missing required SQL or dialect");
2055
2090
  }
2091
+ if (queryResponse.data.queryId) {
2092
+ parentQueryId = queryResponse.data.queryId;
2093
+ }
2056
2094
  const dbName = queryResponse.data.database ?? options.database ?? queryEngine.getDefaultDatabase();
2057
2095
  if (!dbName) {
2058
2096
  throw new Error(
@@ -2212,35 +2250,35 @@ async function resolveQuery(client, queryEngine, queryId, options, signal) {
2212
2250
  dialect: response.dialect
2213
2251
  };
2214
2252
  }
2253
+ async function markQueryExecuted(client, queryId, options, signal) {
2254
+ try {
2255
+ await client.post(
2256
+ `/v2/queries/${encodeURIComponent(queryId)}/executed`,
2257
+ {},
2258
+ options.tenantId,
2259
+ options.userId,
2260
+ options.scopes,
2261
+ signal
2262
+ );
2263
+ } catch {
2264
+ }
2265
+ }
2215
2266
 
2216
2267
  // src/routes/modify.ts
2217
- function buildModifiedQuestion(originalQuestion, modifications, pipeline, hasSessionContext = false) {
2268
+ function buildModifiedQuestion(originalQuestion, modifications, hasSessionContext = false) {
2218
2269
  const hints = [];
2219
2270
  if (modifications.timeGranularity) {
2220
2271
  hints.push(`group results by ${modifications.timeGranularity}`);
2221
2272
  }
2222
2273
  if (modifications.dateRange) {
2223
- if (pipeline === "v2") {
2224
- const from = normalizeDateInput(modifications.dateRange.from);
2225
- const to = normalizeDateInput(modifications.dateRange.to);
2226
- if (from && to) {
2227
- hints.push(`change date range to ${from} through ${to}`);
2228
- } else if (from) {
2229
- hints.push(`change start date to ${from}`);
2230
- } else if (to) {
2231
- hints.push(`change end date to ${to}`);
2232
- }
2233
- } else {
2234
- const parts = [];
2235
- if (modifications.dateRange.from) {
2236
- parts.push(`from ${modifications.dateRange.from}`);
2237
- }
2238
- if (modifications.dateRange.to) {
2239
- parts.push(`to ${modifications.dateRange.to}`);
2240
- }
2241
- if (parts.length > 0) {
2242
- hints.push(`filter date range ${parts.join(" ")}`);
2243
- }
2274
+ const from = normalizeDateInput(modifications.dateRange.from);
2275
+ const to = normalizeDateInput(modifications.dateRange.to);
2276
+ if (from && to) {
2277
+ hints.push(`change date range to ${from} through ${to}`);
2278
+ } else if (from) {
2279
+ hints.push(`change start date to ${from}`);
2280
+ } else if (to) {
2281
+ hints.push(`change end date to ${to}`);
2244
2282
  }
2245
2283
  }
2246
2284
  if (modifications.additionalInstructions) {
@@ -2249,7 +2287,7 @@ function buildModifiedQuestion(originalQuestion, modifications, pipeline, hasSes
2249
2287
  if (hints.length === 0) {
2250
2288
  return originalQuestion;
2251
2289
  }
2252
- if (pipeline === "v2" && hasSessionContext) {
2290
+ if (hasSessionContext) {
2253
2291
  return hints.join(", ");
2254
2292
  }
2255
2293
  return `${originalQuestion} (${hints.join(", ")})`;
@@ -2365,8 +2403,8 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2365
2403
  const hasSqlMods = !!input.sqlModifications;
2366
2404
  const hasVizMods = !!input.vizModifications;
2367
2405
  const hasCustomSql = !!input.sqlModifications?.customSql;
2368
- const pipeline = resolveQueryPipeline(options?.pipeline);
2369
- const queryEndpoint = pipeline === "v2" ? "/v2/query" : "/query";
2406
+ resolveQueryPipeline(options?.pipeline);
2407
+ const queryEndpoint = "/v2/query";
2370
2408
  let currentSql = input.sql;
2371
2409
  let finalParams = input.params ?? {};
2372
2410
  let paramMetadata = [];
@@ -2422,12 +2460,9 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2422
2460
  const modifiedQuestion = buildModifiedQuestion(
2423
2461
  input.question,
2424
2462
  input.sqlModifications,
2425
- pipeline,
2426
2463
  hasQuerypanelSessionContext
2427
2464
  );
2428
- if (pipeline === "v2") {
2429
- finalQuestion = modifiedQuestion;
2430
- }
2465
+ finalQuestion = modifiedQuestion;
2431
2466
  const queryResponse = await client.post(
2432
2467
  queryEndpoint,
2433
2468
  {
@@ -2449,13 +2484,11 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2449
2484
  finalSql = queryResponse.sql;
2450
2485
  paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
2451
2486
  finalParams = queryEngine.mapGeneratedParams(paramMetadata);
2452
- if (pipeline === "v2") {
2453
- applyDateRangeOverrides(
2454
- input.sqlModifications?.dateRange,
2455
- finalParams,
2456
- paramMetadata
2457
- );
2458
- }
2487
+ applyDateRangeOverrides(
2488
+ input.sqlModifications?.dateRange,
2489
+ finalParams,
2490
+ paramMetadata
2491
+ );
2459
2492
  rationale = queryResponse.rationale;
2460
2493
  queryId = queryResponse.queryId;
2461
2494
  sqlChanged = finalSql !== currentSql;
@@ -2673,6 +2706,9 @@ function resolveAttachEnforceTenantIsolation(tenantFieldName, enforceTenantIsola
2673
2706
  return tenantFieldName ? true : void 0;
2674
2707
  }
2675
2708
  var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2709
+ client;
2710
+ queryEngine;
2711
+ supportedChartTypes;
2676
2712
  /**
2677
2713
  * @param workspaceId - Workspace UUID (same value as your org in the dashboard). Passed to the API as JWT claim `organizationId`.
2678
2714
  */
@@ -2924,6 +2960,11 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2924
2960
  databaseName,
2925
2961
  tenantId
2926
2962
  );
2963
+ if (input.queryId) {
2964
+ await markQueryExecuted(this.client, input.queryId, {
2965
+ tenantId
2966
+ });
2967
+ }
2927
2968
  return { rows: result.rows, fields: result.fields };
2928
2969
  }
2929
2970
  // VizSpec generation