@superatomai/sdk-node 0.0.45-mds → 0.0.46-mds
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 +942 -942
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +117 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +117 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1678,6 +1678,21 @@ var QueryCache = class {
|
|
|
1678
1678
|
};
|
|
1679
1679
|
var queryCache = new QueryCache();
|
|
1680
1680
|
|
|
1681
|
+
// src/utils/surrogate.ts
|
|
1682
|
+
var LONE_SURROGATE_RE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
1683
|
+
function stripLoneSurrogates(value) {
|
|
1684
|
+
if (typeof value !== "string") return value;
|
|
1685
|
+
if (!/[\uD800-\uDFFF]/.test(value)) return value;
|
|
1686
|
+
return value.replace(LONE_SURROGATE_RE, "\uFFFD");
|
|
1687
|
+
}
|
|
1688
|
+
function safeTruncate(text, maxUnits) {
|
|
1689
|
+
if (typeof text !== "string" || text.length <= maxUnits || maxUnits < 0) return text;
|
|
1690
|
+
let end = maxUnits;
|
|
1691
|
+
const lastCode = text.charCodeAt(end - 1);
|
|
1692
|
+
if (lastCode >= 55296 && lastCode <= 56319) end -= 1;
|
|
1693
|
+
return text.slice(0, end);
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1681
1696
|
// src/userResponse/llm-result-truncator.ts
|
|
1682
1697
|
var DEFAULT_MAX_ROWS = 10;
|
|
1683
1698
|
var DEFAULT_MAX_CHARS_PER_FIELD = 500;
|
|
@@ -1720,12 +1735,12 @@ function isDateString(value) {
|
|
|
1720
1735
|
}
|
|
1721
1736
|
function truncateTextField(value, maxLength) {
|
|
1722
1737
|
if (value.length <= maxLength) {
|
|
1723
|
-
return { text: value, wasTruncated: false };
|
|
1738
|
+
return { text: stripLoneSurrogates(value), wasTruncated: false };
|
|
1724
1739
|
}
|
|
1725
|
-
const truncated = value
|
|
1726
|
-
const remaining = value.length -
|
|
1740
|
+
const truncated = safeTruncate(value, maxLength);
|
|
1741
|
+
const remaining = value.length - truncated.length;
|
|
1727
1742
|
return {
|
|
1728
|
-
text: `${truncated}... (${remaining} more chars)`,
|
|
1743
|
+
text: `${stripLoneSurrogates(truncated)}... (${remaining} more chars)`,
|
|
1729
1744
|
wasTruncated: true
|
|
1730
1745
|
};
|
|
1731
1746
|
}
|
|
@@ -5582,6 +5597,7 @@ var LLM = class {
|
|
|
5582
5597
|
/* Get a complete text response from an LLM (Anthropic or Groq) */
|
|
5583
5598
|
static async text(messages, options = {}) {
|
|
5584
5599
|
const [provider, modelName] = this._parseModel(options.model);
|
|
5600
|
+
messages = this._sanitizeMessages(messages);
|
|
5585
5601
|
if (provider === "anthropic") {
|
|
5586
5602
|
return this._anthropicText(messages, modelName, options);
|
|
5587
5603
|
} else if (provider === "groq") {
|
|
@@ -5597,6 +5613,7 @@ var LLM = class {
|
|
|
5597
5613
|
/* Stream response from an LLM (Anthropic or Groq) */
|
|
5598
5614
|
static async stream(messages, options = {}, json) {
|
|
5599
5615
|
const [provider, modelName] = this._parseModel(options.model);
|
|
5616
|
+
messages = this._sanitizeMessages(messages);
|
|
5600
5617
|
if (provider === "anthropic") {
|
|
5601
5618
|
return this._anthropicStream(messages, modelName, options, json);
|
|
5602
5619
|
} else if (provider === "groq") {
|
|
@@ -5612,6 +5629,7 @@ var LLM = class {
|
|
|
5612
5629
|
/* Stream response with tool calling support (Anthropic and Gemini) */
|
|
5613
5630
|
static async streamWithTools(messages, tools, toolHandler, options = {}, maxIterations = 3) {
|
|
5614
5631
|
const [provider, modelName] = this._parseModel(options.model);
|
|
5632
|
+
messages = this._sanitizeMessages(messages);
|
|
5615
5633
|
if (provider === "anthropic") {
|
|
5616
5634
|
return this._anthropicStreamWithTools(messages, tools, toolHandler, modelName, options, maxIterations);
|
|
5617
5635
|
} else if (provider === "gemini") {
|
|
@@ -5637,6 +5655,26 @@ var LLM = class {
|
|
|
5637
5655
|
}
|
|
5638
5656
|
return sys;
|
|
5639
5657
|
}
|
|
5658
|
+
/**
|
|
5659
|
+
* Strip unpaired UTF-16 surrogates from every text field of a message set.
|
|
5660
|
+
*
|
|
5661
|
+
* A lone surrogate (from mid-pair string slicing or corrupt source data)
|
|
5662
|
+
* serializes to a bare `\udXXX` escape that strict JSON parsers — including
|
|
5663
|
+
* the one on Anthropic's API — reject with "no low surrogate in string",
|
|
5664
|
+
* failing the whole request. Sanitizing here, at the single boundary every
|
|
5665
|
+
* provider call flows through, guarantees no request can carry one.
|
|
5666
|
+
*/
|
|
5667
|
+
static _sanitizeMessages(messages) {
|
|
5668
|
+
const sys = typeof messages.sys === "string" ? stripLoneSurrogates(messages.sys) : messages.sys.map(
|
|
5669
|
+
(block) => block?.type === "text" && typeof block.text === "string" ? { ...block, text: stripLoneSurrogates(block.text) } : block
|
|
5670
|
+
);
|
|
5671
|
+
return {
|
|
5672
|
+
...messages,
|
|
5673
|
+
sys,
|
|
5674
|
+
user: stripLoneSurrogates(messages.user),
|
|
5675
|
+
...messages.prefill !== void 0 && { prefill: stripLoneSurrogates(messages.prefill) }
|
|
5676
|
+
};
|
|
5677
|
+
}
|
|
5640
5678
|
/**
|
|
5641
5679
|
* Log cache usage metrics from Anthropic API response
|
|
5642
5680
|
* Shows cache hits, costs, and savings
|
|
@@ -6016,12 +6054,14 @@ var LLM = class {
|
|
|
6016
6054
|
let resultContent = typeof result === "string" ? result : JSON.stringify(result);
|
|
6017
6055
|
const MAX_RESULT_LENGTH = 5e4;
|
|
6018
6056
|
if (resultContent.length > MAX_RESULT_LENGTH) {
|
|
6019
|
-
resultContent = resultContent
|
|
6057
|
+
resultContent = safeTruncate(resultContent, MAX_RESULT_LENGTH) + "\n\n... [Result truncated - showing first 50000 characters of " + resultContent.length + " total]";
|
|
6020
6058
|
}
|
|
6021
6059
|
return {
|
|
6022
6060
|
type: "tool_result",
|
|
6023
6061
|
tool_use_id: toolUse.id,
|
|
6024
|
-
|
|
6062
|
+
// Final safety net: tool results carry source data and are built
|
|
6063
|
+
// mid-loop (after entry-point sanitize), so strip lone surrogates here.
|
|
6064
|
+
content: stripLoneSurrogates(resultContent)
|
|
6025
6065
|
};
|
|
6026
6066
|
} catch (error) {
|
|
6027
6067
|
return {
|
|
@@ -6536,11 +6576,12 @@ var LLM = class {
|
|
|
6536
6576
|
let resultContent = typeof result2 === "string" ? result2 : JSON.stringify(result2);
|
|
6537
6577
|
const MAX_RESULT_LENGTH = 5e4;
|
|
6538
6578
|
if (resultContent.length > MAX_RESULT_LENGTH) {
|
|
6539
|
-
resultContent = resultContent
|
|
6579
|
+
resultContent = safeTruncate(resultContent, MAX_RESULT_LENGTH) + "\n\n... [Result truncated - showing first 50000 characters of " + resultContent.length + " total]";
|
|
6540
6580
|
}
|
|
6541
6581
|
return {
|
|
6542
6582
|
name: fc.name,
|
|
6543
|
-
|
|
6583
|
+
// Final safety net: strip lone surrogates from source-data results.
|
|
6584
|
+
response: { result: stripLoneSurrogates(resultContent) }
|
|
6544
6585
|
};
|
|
6545
6586
|
} catch (error) {
|
|
6546
6587
|
return {
|
|
@@ -6813,12 +6854,12 @@ var LLM = class {
|
|
|
6813
6854
|
result = typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult);
|
|
6814
6855
|
const MAX_RESULT_LENGTH = 5e4;
|
|
6815
6856
|
if (result.length > MAX_RESULT_LENGTH) {
|
|
6816
|
-
result = result
|
|
6857
|
+
result = safeTruncate(result, MAX_RESULT_LENGTH) + "\n\n... [Result truncated - showing first 50000 characters of " + result.length + " total]";
|
|
6817
6858
|
}
|
|
6818
6859
|
} catch (error) {
|
|
6819
6860
|
result = JSON.stringify({ error: error instanceof Error ? error.message : String(error) });
|
|
6820
6861
|
}
|
|
6821
|
-
return { role: "tool", tool_call_id: tc.id, content: result };
|
|
6862
|
+
return { role: "tool", tool_call_id: tc.id, content: stripLoneSurrogates(result) };
|
|
6822
6863
|
}));
|
|
6823
6864
|
toolCallResults.forEach((r) => conversationMessages.push(r));
|
|
6824
6865
|
}
|
|
@@ -7922,7 +7963,7 @@ Execution time: ${metadata.executionTimeMs}ms
|
|
|
7922
7963
|
const truncatedRow = {};
|
|
7923
7964
|
for (const [key, value] of Object.entries(row)) {
|
|
7924
7965
|
if (typeof value === "string" && value.length > 200) {
|
|
7925
|
-
truncatedRow[key] = value
|
|
7966
|
+
truncatedRow[key] = safeTruncate(value, 200) + "...";
|
|
7926
7967
|
} else {
|
|
7927
7968
|
truncatedRow[key] = value;
|
|
7928
7969
|
}
|
|
@@ -15059,7 +15100,7 @@ Fixed SQL query:`;
|
|
|
15059
15100
|
}
|
|
15060
15101
|
|
|
15061
15102
|
// src/dashComp/create-filter.ts
|
|
15062
|
-
async function createFilterWithLLM(prompt, components, existingComponents, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, tools, dashCompModels, collections) {
|
|
15103
|
+
async function createFilterWithLLM(prompt, components, existingComponents, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, tools, dashCompModels, collections, userId) {
|
|
15063
15104
|
const errors = [];
|
|
15064
15105
|
try {
|
|
15065
15106
|
const filterComponents = components.filter((c) => c.type.startsWith("Filter"));
|
|
@@ -15079,6 +15120,25 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
15079
15120
|
schemaDoc = schema.generateSchemaDocumentation();
|
|
15080
15121
|
}
|
|
15081
15122
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
15123
|
+
let globalKnowledgeBase = "No global knowledge base available.";
|
|
15124
|
+
let knowledgeBaseContext = "No additional knowledge base context available.";
|
|
15125
|
+
if (collections) {
|
|
15126
|
+
const kbResult = await knowledge_base_default.getAllKnowledgeBase({
|
|
15127
|
+
prompt,
|
|
15128
|
+
collections,
|
|
15129
|
+
userId,
|
|
15130
|
+
topK: KNOWLEDGE_BASE_TOP_K
|
|
15131
|
+
});
|
|
15132
|
+
globalKnowledgeBase = kbResult.globalContext || globalKnowledgeBase;
|
|
15133
|
+
const dynamicParts = [];
|
|
15134
|
+
if (kbResult.userContext) {
|
|
15135
|
+
dynamicParts.push("## User-Specific Knowledge Base\n" + kbResult.userContext);
|
|
15136
|
+
}
|
|
15137
|
+
if (kbResult.queryContext) {
|
|
15138
|
+
dynamicParts.push("## Relevant Knowledge Base (Query-Matched)\n" + kbResult.queryContext);
|
|
15139
|
+
}
|
|
15140
|
+
knowledgeBaseContext = dynamicParts.join("\n\n") || knowledgeBaseContext;
|
|
15141
|
+
}
|
|
15082
15142
|
const prompts = await promptLoader.loadPrompts("dash-filter-picker", {
|
|
15083
15143
|
USER_PROMPT: prompt,
|
|
15084
15144
|
AVAILABLE_COMPONENTS: formatComponentsForPrompt(filterComponents),
|
|
@@ -15086,8 +15146,12 @@ async function createFilterWithLLM(prompt, components, existingComponents, anthr
|
|
|
15086
15146
|
SCHEMA_DOC: schemaDoc || "No database schema available",
|
|
15087
15147
|
DATABASE_RULES: databaseRules,
|
|
15088
15148
|
AVAILABLE_TOOLS: formatToolsForPrompt(tools),
|
|
15089
|
-
CURRENT_DATETIME: getCurrentDateTimeForPrompt()
|
|
15149
|
+
CURRENT_DATETIME: getCurrentDateTimeForPrompt(),
|
|
15150
|
+
GLOBAL_KNOWLEDGE_BASE: globalKnowledgeBase,
|
|
15151
|
+
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext
|
|
15090
15152
|
});
|
|
15153
|
+
logger.logLLMPrompt("dashFilterPicker", "system", extractPromptText(prompts.system));
|
|
15154
|
+
logger.logLLMPrompt("dashFilterPicker", "user", prompts.user);
|
|
15091
15155
|
logger.debug("[DASH_COMP_REQ:FILTER] Loaded dash-filter-picker prompts");
|
|
15092
15156
|
const { apiKey, model } = getApiKeyAndModel(
|
|
15093
15157
|
anthropicApiKey,
|
|
@@ -15461,7 +15525,8 @@ var processDashCompRequest = async (data, components, _sendMessage, anthropicApi
|
|
|
15461
15525
|
llmProviders,
|
|
15462
15526
|
tools,
|
|
15463
15527
|
dashCompModels,
|
|
15464
|
-
collections
|
|
15528
|
+
collections,
|
|
15529
|
+
userId
|
|
15465
15530
|
);
|
|
15466
15531
|
} else {
|
|
15467
15532
|
llmResponse = await pickComponentWithLLM(
|
|
@@ -15615,7 +15680,7 @@ function sendReportCompResponse(id, res, sendMessage, clientId) {
|
|
|
15615
15680
|
}
|
|
15616
15681
|
|
|
15617
15682
|
// src/reportComp/generate-report.ts
|
|
15618
|
-
async function generateReportComponents(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, modelConfig, conversationHistory) {
|
|
15683
|
+
async function generateReportComponents(prompt, components, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, collections, tools, modelConfig, conversationHistory, userId) {
|
|
15619
15684
|
const errors = [];
|
|
15620
15685
|
const availableComponentsText = formatComponentsForPrompt2(components);
|
|
15621
15686
|
const availableToolsText = formatToolsForPrompt2(tools);
|
|
@@ -15631,6 +15696,25 @@ async function generateReportComponents(prompt, components, anthropicApiKey, gro
|
|
|
15631
15696
|
schemaDoc = schema.generateSchemaDocumentation();
|
|
15632
15697
|
}
|
|
15633
15698
|
const databaseRules = await promptLoader.loadDatabaseRules();
|
|
15699
|
+
let globalKnowledgeBase = "No global knowledge base available.";
|
|
15700
|
+
let knowledgeBaseContext = "No additional knowledge base context available.";
|
|
15701
|
+
if (collections) {
|
|
15702
|
+
const kbResult = await knowledge_base_default.getAllKnowledgeBase({
|
|
15703
|
+
prompt,
|
|
15704
|
+
collections,
|
|
15705
|
+
userId,
|
|
15706
|
+
topK: KNOWLEDGE_BASE_TOP_K
|
|
15707
|
+
});
|
|
15708
|
+
globalKnowledgeBase = kbResult.globalContext || globalKnowledgeBase;
|
|
15709
|
+
const dynamicParts = [];
|
|
15710
|
+
if (kbResult.userContext) {
|
|
15711
|
+
dynamicParts.push("## User-Specific Knowledge Base\n" + kbResult.userContext);
|
|
15712
|
+
}
|
|
15713
|
+
if (kbResult.queryContext) {
|
|
15714
|
+
dynamicParts.push("## Relevant Knowledge Base (Query-Matched)\n" + kbResult.queryContext);
|
|
15715
|
+
}
|
|
15716
|
+
knowledgeBaseContext = dynamicParts.join("\n\n") || knowledgeBaseContext;
|
|
15717
|
+
}
|
|
15634
15718
|
const prompts = await promptLoader.loadPrompts("report-comp-picker", {
|
|
15635
15719
|
USER_PROMPT: prompt,
|
|
15636
15720
|
AVAILABLE_COMPONENTS: availableComponentsText,
|
|
@@ -15638,8 +15722,12 @@ async function generateReportComponents(prompt, components, anthropicApiKey, gro
|
|
|
15638
15722
|
DATABASE_RULES: databaseRules,
|
|
15639
15723
|
AVAILABLE_TOOLS: availableToolsText,
|
|
15640
15724
|
CURRENT_DATETIME: getCurrentDateTimeForPrompt(),
|
|
15641
|
-
CONVERSATION_HISTORY: conversationHistory || "No previous conversation"
|
|
15725
|
+
CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
|
|
15726
|
+
GLOBAL_KNOWLEDGE_BASE: globalKnowledgeBase,
|
|
15727
|
+
KNOWLEDGE_BASE_CONTEXT: knowledgeBaseContext
|
|
15642
15728
|
});
|
|
15729
|
+
logger.logLLMPrompt("reportCompPicker", "system", extractPromptText(prompts.system));
|
|
15730
|
+
logger.logLLMPrompt("reportCompPicker", "user", prompts.user);
|
|
15643
15731
|
logger.debug("[REPORT_COMP_REQ] Loaded report-comp-picker prompts with schema and tools");
|
|
15644
15732
|
const { apiKey, model } = getApiKeyAndModel2(
|
|
15645
15733
|
anthropicApiKey,
|
|
@@ -15864,13 +15952,21 @@ async function validateAllExternalToolQueries(components, collections, tools, mo
|
|
|
15864
15952
|
data: {}
|
|
15865
15953
|
});
|
|
15866
15954
|
if (result?.success !== false && !result?.error) {
|
|
15867
|
-
const
|
|
15868
|
-
const
|
|
15955
|
+
const toolResult = result?.data ?? result;
|
|
15956
|
+
const valueKey = comp.props?.config?.valueKey;
|
|
15957
|
+
const isKpi = comp.type === "KPICard" || comp.name === "DynamicKPICard";
|
|
15958
|
+
let dataArray;
|
|
15959
|
+
if (isKpi && valueKey && toolResult && typeof toolResult === "object" && !Array.isArray(toolResult) && toolResult[valueKey] !== void 0) {
|
|
15960
|
+
dataArray = [toolResult];
|
|
15961
|
+
} else {
|
|
15962
|
+
const resultData = toolResult?.data ?? toolResult ?? [];
|
|
15963
|
+
dataArray = Array.isArray(resultData) ? resultData : [resultData];
|
|
15964
|
+
}
|
|
15869
15965
|
if (!comp.props.config) {
|
|
15870
15966
|
comp.props.config = {};
|
|
15871
15967
|
}
|
|
15872
15968
|
comp.props.config.data = dataArray;
|
|
15873
|
-
logger.info(`[REPORT_COMP_REQ] \u2713 ${comp.name} prefetched ${dataArray.length} rows (non-SQL tool)`);
|
|
15969
|
+
logger.info(`[REPORT_COMP_REQ] \u2713 ${comp.name} prefetched ${dataArray.length} ${dataArray.length === 1 && isKpi ? "aggregate" : "rows"} (non-SQL tool)`);
|
|
15874
15970
|
}
|
|
15875
15971
|
} catch (err) {
|
|
15876
15972
|
logger.warn(`[REPORT_COMP_REQ] \u26A0 ${comp.name} non-SQL prefetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -16010,7 +16106,8 @@ var processReportCompRequest = async (data, components, _sendMessage, anthropicA
|
|
|
16010
16106
|
collections,
|
|
16011
16107
|
tools,
|
|
16012
16108
|
modelConfig,
|
|
16013
|
-
conversationHistory
|
|
16109
|
+
conversationHistory,
|
|
16110
|
+
userId
|
|
16014
16111
|
);
|
|
16015
16112
|
if (llmResponse.success && reportId && prompt) {
|
|
16016
16113
|
const comps = llmResponse.data?.components;
|