@superatomai/sdk-node 0.0.84-dsp → 0.0.86-dsp

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.mts CHANGED
@@ -1624,6 +1624,8 @@ interface PromptContext {
1624
1624
  dashboardId?: string;
1625
1625
  /** The filter values set on that dashboard, keyed by parameter name. */
1626
1626
  filters?: Record<string, unknown>;
1627
+ /** Follow the question already running in this thread (a reloaded page); never starts a new one. */
1628
+ follow?: boolean;
1627
1629
  }
1628
1630
  /**
1629
1631
  * Everything a replacement answer flow is handed for one question. Deliberately
@@ -4449,6 +4451,8 @@ interface PolicyExceptionTable {
4449
4451
  link?: string;
4450
4452
  columns?: string[];
4451
4453
  own?: string;
4454
+ /** A predicate (`{t}` is the table) that makes more rows visible, with only `columns` readable; no key list. */
4455
+ visibleWhere?: string;
4452
4456
  }
4453
4457
  /**
4454
4458
  * A named grant: extra rows a restricted user may see outside their branch. `visibleKeys` is
package/dist/index.d.ts CHANGED
@@ -1624,6 +1624,8 @@ interface PromptContext {
1624
1624
  dashboardId?: string;
1625
1625
  /** The filter values set on that dashboard, keyed by parameter name. */
1626
1626
  filters?: Record<string, unknown>;
1627
+ /** Follow the question already running in this thread (a reloaded page); never starts a new one. */
1628
+ follow?: boolean;
1627
1629
  }
1628
1630
  /**
1629
1631
  * Everything a replacement answer flow is handed for one question. Deliberately
@@ -4449,6 +4451,8 @@ interface PolicyExceptionTable {
4449
4451
  link?: string;
4450
4452
  columns?: string[];
4451
4453
  own?: string;
4454
+ /** A predicate (`{t}` is the table) that makes more rows visible, with only `columns` readable; no key list. */
4455
+ visibleWhere?: string;
4452
4456
  }
4453
4457
  /**
4454
4458
  * A named grant: extra rows a restricted user may see outside their branch. `visibleKeys` is
package/dist/index.js CHANGED
@@ -2694,16 +2694,18 @@ function exceptionsFromConfig(raw) {
2694
2694
  const s = spec;
2695
2695
  const link = str(s.link);
2696
2696
  const own = str(s.own);
2697
+ const visibleWhere = str(s.visibleWhere);
2697
2698
  const columns = Array.isArray(s.columns) ? s.columns.filter((c) => typeof c === "string" && !!c) : [];
2698
2699
  let bad = null;
2699
2700
  if (!own && !link) bad = 'it has neither "link" nor "own"';
2700
2701
  else if (!own && columns.length === 0) bad = 'it lists no "columns"';
2701
- else if (!own && !visibleKeys) bad = 'the exception has no "visibleKeys"';
2702
+ else if (own && visibleWhere && columns.length === 0) bad = 'it has "visibleWhere" with "own" but lists no "columns"';
2703
+ else if (!own && !visibleKeys && !visibleWhere) bad = 'the exception has no "visibleKeys" and the table no "visibleWhere"';
2702
2704
  if (bad) {
2703
2705
  logger.warn(`[RequestIdentity] Exception "${name ?? "?"}": table "${table}" dropped because ${bad}.`);
2704
2706
  continue;
2705
2707
  }
2706
- tables[table] = own ? { own } : { link, columns };
2708
+ tables[table] = own ? visibleWhere ? { own, columns, visibleWhere } : { own } : { link, columns, ...visibleWhere ? { visibleWhere } : {} };
2707
2709
  }
2708
2710
  if (Object.keys(tables).length === 0) continue;
2709
2711
  out.push({ name, visibleKeys, tables });
@@ -9839,6 +9841,8 @@ var PromptLoader = class {
9839
9841
  // Excel sources use DuckDB engine
9840
9842
  "csv": "duckdb",
9841
9843
  // CSV sources use DuckDB engine
9844
+ "s3": "duckdb",
9845
+ // S3 Parquet sources use DuckDB engine
9842
9846
  "dynamodb": "dynamodb",
9843
9847
  // DynamoDB uses its own PartiQL rules (no JOIN/GROUP BY/aggregates)
9844
9848
  "redis": "redis",
@@ -11007,6 +11011,7 @@ Analyze the error and try again with a corrected query.`;
11007
11011
  "mysql": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
11008
11012
  "excel": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
11009
11013
  "csv": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
11014
+ "s3": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
11010
11015
  "dynamodb": `Add LIMIT ${this.config.maxRowsFetched} at the end (this tool applies it \u2014 DynamoDB has no LIMIT clause) and always filter by the partition key`,
11011
11016
  "redis": `Provide ONE Redis read command in the query field (e.g. HGETALL key, or SCAN 0 MATCH pattern:* COUNT ${this.config.maxRowsFetched}). Look up by exact key when known; never use KEYS`,
11012
11017
  "netsuite": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query (this tool converts it internally \u2014 SuiteQL itself has no LIMIT keyword, so never write FETCH FIRST/OFFSET/TOP yourself)`
@@ -11055,7 +11060,7 @@ Even if a table appears in the detailed schema above, search_schema returns samp
11055
11060
  } catch (traceErr) {
11056
11061
  logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for schemaSearchInstructionsText (non-blocking): ${traceErr}`);
11057
11062
  }
11058
- const displaySourceType = sourceType === "excel" || sourceType === "csv" ? `${sourceType} \u2014 uses DuckDB SQL engine` : sourceType;
11063
+ const displaySourceType = sourceType === "excel" || sourceType === "csv" || sourceType === "s3" ? `${sourceType} \u2014 uses DuckDB SQL engine` : sourceType;
11059
11064
  const userAccessContextText = buildAccessSection(this.config.userAccessContext ?? "", "source");
11060
11065
  try {
11061
11066
  if (this.traceSchemaEntry) this.traceSchemaEntry.userAccessContextText = userAccessContextText;
@@ -19725,6 +19730,7 @@ function promptContextFrom(raw) {
19725
19730
  if (source.filters && typeof source.filters === "object" && !Array.isArray(source.filters)) {
19726
19731
  context.filters = source.filters;
19727
19732
  }
19733
+ if (source.follow === true) context.follow = true;
19728
19734
  return Object.keys(context).length ? context : void 0;
19729
19735
  }
19730
19736
  var inFlightAborts = /* @__PURE__ */ new Map();
@@ -19907,7 +19913,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19907
19913
  };
19908
19914
  let userResponse;
19909
19915
  try {
19910
- const replayed = answerProvider && !attachments ? (await replayExactMatch({ prompt, collections, userId, threadId, streamCallback, method: "custom-exact-match", startTime: Date.now() }))?.response : void 0;
19916
+ const replayed = answerProvider && !attachments && !payload.context?.follow ? (await replayExactMatch({ prompt, collections, userId, threadId, streamCallback, method: "custom-exact-match", startTime: Date.now() }))?.response : void 0;
19911
19917
  userResponse = replayed ? replayed : answerProvider ? await answerProvider({
19912
19918
  prompt,
19913
19919
  components,
@@ -19952,6 +19958,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19952
19958
  if (Array.isArray(narration) && narration.length) uiBlock.setNarration(narration);
19953
19959
  uiBlock.setDurationMs(Date.now() - requestStartTime);
19954
19960
  const uiBlockId = existingUiBlockId;
19961
+ const recordable = !!userId && !userResponse?.data?.followed;
19955
19962
  const wasAborted = abortController.signal.aborted || !userResponse.success && Array.isArray(userResponse.errors) && userResponse.errors.includes("aborted");
19956
19963
  if (wasAborted) {
19957
19964
  thread.removeUIBlock(uiBlockId);
@@ -19961,7 +19968,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19961
19968
  }
19962
19969
  let savedConversationId2;
19963
19970
  let savedResponse2;
19964
- if (userId) {
19971
+ if (recordable) {
19965
19972
  const saveResult = await saveConversation({
19966
19973
  userId,
19967
19974
  userPrompt: prompt,
@@ -19980,7 +19987,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19980
19987
  savedResponse2 = saveResult.response;
19981
19988
  }
19982
19989
  }
19983
- if (userId) {
19990
+ if (recordable) {
19984
19991
  const latencyMs = Date.now() - requestStartTime;
19985
19992
  const turn = reported(userResponse);
19986
19993
  const model = turn.model || mainAgentModel || "unknown";
@@ -20030,7 +20037,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
20030
20037
  }
20031
20038
  let savedConversationId2;
20032
20039
  let savedResponse2;
20033
- if (userId) {
20040
+ if (recordable) {
20034
20041
  const saveResult = await saveConversation({
20035
20042
  userId,
20036
20043
  userPrompt: prompt,
@@ -20052,7 +20059,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
20052
20059
  savedResponse2 = saveResult.response;
20053
20060
  }
20054
20061
  }
20055
- if (userId) {
20062
+ if (recordable) {
20056
20063
  const latencyMs = Date.now() - requestStartTime;
20057
20064
  const turn = reported(userResponse);
20058
20065
  const model = turn.model || mainAgentModel || "unknown";
@@ -20117,7 +20124,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
20117
20124
  logger.info(`Completed UIBlock: ${uiBlockId} in Thread: ${threadId}`);
20118
20125
  let savedConversationId;
20119
20126
  let savedResponse;
20120
- if (userId) {
20127
+ if (recordable) {
20121
20128
  const responseMethod = userResponse.data?.method || "";
20122
20129
  const semanticSimilarity = userResponse.data?.semanticSimilarity || 0;
20123
20130
  const isExactMatch = responseMethod.includes("semantic-match") && semanticSimilarity >= 0.99;
@@ -20156,7 +20163,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
20156
20163
  }
20157
20164
  }
20158
20165
  llmUsageLogger.logSessionSummary(prompt?.substring(0, 50));
20159
- if (userId) {
20166
+ if (recordable) {
20160
20167
  const latencyMs = Date.now() - requestStartTime;
20161
20168
  const turn = reported(userResponse);
20162
20169
  const model = turn.model || mainAgentModel || "unknown";
package/dist/index.mjs CHANGED
@@ -2582,16 +2582,18 @@ function exceptionsFromConfig(raw) {
2582
2582
  const s = spec;
2583
2583
  const link = str(s.link);
2584
2584
  const own = str(s.own);
2585
+ const visibleWhere = str(s.visibleWhere);
2585
2586
  const columns = Array.isArray(s.columns) ? s.columns.filter((c) => typeof c === "string" && !!c) : [];
2586
2587
  let bad = null;
2587
2588
  if (!own && !link) bad = 'it has neither "link" nor "own"';
2588
2589
  else if (!own && columns.length === 0) bad = 'it lists no "columns"';
2589
- else if (!own && !visibleKeys) bad = 'the exception has no "visibleKeys"';
2590
+ else if (own && visibleWhere && columns.length === 0) bad = 'it has "visibleWhere" with "own" but lists no "columns"';
2591
+ else if (!own && !visibleKeys && !visibleWhere) bad = 'the exception has no "visibleKeys" and the table no "visibleWhere"';
2590
2592
  if (bad) {
2591
2593
  logger.warn(`[RequestIdentity] Exception "${name ?? "?"}": table "${table}" dropped because ${bad}.`);
2592
2594
  continue;
2593
2595
  }
2594
- tables[table] = own ? { own } : { link, columns };
2596
+ tables[table] = own ? visibleWhere ? { own, columns, visibleWhere } : { own } : { link, columns, ...visibleWhere ? { visibleWhere } : {} };
2595
2597
  }
2596
2598
  if (Object.keys(tables).length === 0) continue;
2597
2599
  out.push({ name, visibleKeys, tables });
@@ -9727,6 +9729,8 @@ var PromptLoader = class {
9727
9729
  // Excel sources use DuckDB engine
9728
9730
  "csv": "duckdb",
9729
9731
  // CSV sources use DuckDB engine
9732
+ "s3": "duckdb",
9733
+ // S3 Parquet sources use DuckDB engine
9730
9734
  "dynamodb": "dynamodb",
9731
9735
  // DynamoDB uses its own PartiQL rules (no JOIN/GROUP BY/aggregates)
9732
9736
  "redis": "redis",
@@ -10895,6 +10899,7 @@ Analyze the error and try again with a corrected query.`;
10895
10899
  "mysql": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
10896
10900
  "excel": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
10897
10901
  "csv": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
10902
+ "s3": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
10898
10903
  "dynamodb": `Add LIMIT ${this.config.maxRowsFetched} at the end (this tool applies it \u2014 DynamoDB has no LIMIT clause) and always filter by the partition key`,
10899
10904
  "redis": `Provide ONE Redis read command in the query field (e.g. HGETALL key, or SCAN 0 MATCH pattern:* COUNT ${this.config.maxRowsFetched}). Look up by exact key when known; never use KEYS`,
10900
10905
  "netsuite": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query (this tool converts it internally \u2014 SuiteQL itself has no LIMIT keyword, so never write FETCH FIRST/OFFSET/TOP yourself)`
@@ -10943,7 +10948,7 @@ Even if a table appears in the detailed schema above, search_schema returns samp
10943
10948
  } catch (traceErr) {
10944
10949
  logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for schemaSearchInstructionsText (non-blocking): ${traceErr}`);
10945
10950
  }
10946
- const displaySourceType = sourceType === "excel" || sourceType === "csv" ? `${sourceType} \u2014 uses DuckDB SQL engine` : sourceType;
10951
+ const displaySourceType = sourceType === "excel" || sourceType === "csv" || sourceType === "s3" ? `${sourceType} \u2014 uses DuckDB SQL engine` : sourceType;
10947
10952
  const userAccessContextText = buildAccessSection(this.config.userAccessContext ?? "", "source");
10948
10953
  try {
10949
10954
  if (this.traceSchemaEntry) this.traceSchemaEntry.userAccessContextText = userAccessContextText;
@@ -19613,6 +19618,7 @@ function promptContextFrom(raw) {
19613
19618
  if (source.filters && typeof source.filters === "object" && !Array.isArray(source.filters)) {
19614
19619
  context.filters = source.filters;
19615
19620
  }
19621
+ if (source.follow === true) context.follow = true;
19616
19622
  return Object.keys(context).length ? context : void 0;
19617
19623
  }
19618
19624
  var inFlightAborts = /* @__PURE__ */ new Map();
@@ -19795,7 +19801,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19795
19801
  };
19796
19802
  let userResponse;
19797
19803
  try {
19798
- const replayed = answerProvider && !attachments ? (await replayExactMatch({ prompt, collections, userId, threadId, streamCallback, method: "custom-exact-match", startTime: Date.now() }))?.response : void 0;
19804
+ const replayed = answerProvider && !attachments && !payload.context?.follow ? (await replayExactMatch({ prompt, collections, userId, threadId, streamCallback, method: "custom-exact-match", startTime: Date.now() }))?.response : void 0;
19799
19805
  userResponse = replayed ? replayed : answerProvider ? await answerProvider({
19800
19806
  prompt,
19801
19807
  components,
@@ -19840,6 +19846,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19840
19846
  if (Array.isArray(narration) && narration.length) uiBlock.setNarration(narration);
19841
19847
  uiBlock.setDurationMs(Date.now() - requestStartTime);
19842
19848
  const uiBlockId = existingUiBlockId;
19849
+ const recordable = !!userId && !userResponse?.data?.followed;
19843
19850
  const wasAborted = abortController.signal.aborted || !userResponse.success && Array.isArray(userResponse.errors) && userResponse.errors.includes("aborted");
19844
19851
  if (wasAborted) {
19845
19852
  thread.removeUIBlock(uiBlockId);
@@ -19849,7 +19856,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19849
19856
  }
19850
19857
  let savedConversationId2;
19851
19858
  let savedResponse2;
19852
- if (userId) {
19859
+ if (recordable) {
19853
19860
  const saveResult = await saveConversation({
19854
19861
  userId,
19855
19862
  userPrompt: prompt,
@@ -19868,7 +19875,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19868
19875
  savedResponse2 = saveResult.response;
19869
19876
  }
19870
19877
  }
19871
- if (userId) {
19878
+ if (recordable) {
19872
19879
  const latencyMs = Date.now() - requestStartTime;
19873
19880
  const turn = reported(userResponse);
19874
19881
  const model = turn.model || mainAgentModel || "unknown";
@@ -19918,7 +19925,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19918
19925
  }
19919
19926
  let savedConversationId2;
19920
19927
  let savedResponse2;
19921
- if (userId) {
19928
+ if (recordable) {
19922
19929
  const saveResult = await saveConversation({
19923
19930
  userId,
19924
19931
  userPrompt: prompt,
@@ -19940,7 +19947,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19940
19947
  savedResponse2 = saveResult.response;
19941
19948
  }
19942
19949
  }
19943
- if (userId) {
19950
+ if (recordable) {
19944
19951
  const latencyMs = Date.now() - requestStartTime;
19945
19952
  const turn = reported(userResponse);
19946
19953
  const model = turn.model || mainAgentModel || "unknown";
@@ -20005,7 +20012,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
20005
20012
  logger.info(`Completed UIBlock: ${uiBlockId} in Thread: ${threadId}`);
20006
20013
  let savedConversationId;
20007
20014
  let savedResponse;
20008
- if (userId) {
20015
+ if (recordable) {
20009
20016
  const responseMethod = userResponse.data?.method || "";
20010
20017
  const semanticSimilarity = userResponse.data?.semanticSimilarity || 0;
20011
20018
  const isExactMatch = responseMethod.includes("semantic-match") && semanticSimilarity >= 0.99;
@@ -20044,7 +20051,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
20044
20051
  }
20045
20052
  }
20046
20053
  llmUsageLogger.logSessionSummary(prompt?.substring(0, 50));
20047
- if (userId) {
20054
+ if (recordable) {
20048
20055
  const latencyMs = Date.now() - requestStartTime;
20049
20056
  const turn = reported(userResponse);
20050
20057
  const model = turn.model || mainAgentModel || "unknown";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superatomai/sdk-node",
3
- "version": "0.0.84-dsp",
3
+ "version": "0.0.86-dsp",
4
4
  "description": "Node.js TypeScript SDK for Superatom",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",