@superatomai/sdk-node 0.0.54-dsp → 0.0.55-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.js CHANGED
@@ -3656,7 +3656,8 @@ var getGlobalKnowledgeBase = async ({
3656
3656
  var getUserKnowledgeBase = async ({
3657
3657
  collections,
3658
3658
  userId,
3659
- limit = 100
3659
+ limit = 100,
3660
+ trace
3660
3661
  }) => {
3661
3662
  try {
3662
3663
  if (!userId) {
@@ -3676,6 +3677,13 @@ var getUserKnowledgeBase = async ({
3676
3677
  return "";
3677
3678
  }
3678
3679
  logger.info(`[KnowledgeBase] Retrieved ${result.count || 0} user knowledge base nodes for userId: ${userId}`);
3680
+ if (trace) {
3681
+ try {
3682
+ trace.userKbContext = result.content;
3683
+ } catch (traceErr) {
3684
+ logger.warn(`[KnowledgeBase] Trace capture failed for user KB context (non-blocking): ${traceErr}`);
3685
+ }
3686
+ }
3679
3687
  return result.content;
3680
3688
  } catch (error) {
3681
3689
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -3692,7 +3700,7 @@ var getAllKnowledgeBase = async ({
3692
3700
  }) => {
3693
3701
  const [globalContext, userContext, queryContext] = await Promise.all([
3694
3702
  getGlobalKnowledgeBase({ collections, trace }),
3695
- getUserKnowledgeBase({ collections, userId }),
3703
+ getUserKnowledgeBase({ collections, userId, trace }),
3696
3704
  getKnowledgeBase({ prompt, collections, topK, trace })
3697
3705
  ]);
3698
3706
  let combinedContext = "";
@@ -9986,6 +9994,11 @@ var SourceAgent = class {
9986
9994
  logger.logLLMPrompt(`sourceAgent:${this.tool.name}`, "system", extractPromptText(prompts.system));
9987
9995
  logger.logLLMPrompt(`sourceAgent:${this.tool.name}`, "user", prompts.user);
9988
9996
  const tools = this.buildToolDefinitions();
9997
+ try {
9998
+ if (this.traceSchemaEntry) this.traceSchemaEntry.toolsSent = tools;
9999
+ } catch (traceErr) {
10000
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for toolsSent (non-blocking): ${traceErr}`);
10001
+ }
9989
10002
  let executedTool = null;
9990
10003
  let allExecutedTools = [];
9991
10004
  let resultData = [];
@@ -10177,6 +10190,18 @@ Analyze the error and try again with a corrected query.`;
10177
10190
  const extraSearches = hasSchemaSearch ? 2 : 0;
10178
10191
  const responseIterations = 1;
10179
10192
  const maxIterations = totalQueryAttempts * perQueryCost + extraSearches + responseIterations;
10193
+ try {
10194
+ if (this.traceSchemaEntry) {
10195
+ this.traceSchemaEntry.callConfig = {
10196
+ model: this.config.sourceAgentModel || void 0,
10197
+ maxTokens: 2048,
10198
+ temperature: 0,
10199
+ maxIterations
10200
+ };
10201
+ }
10202
+ } catch (traceErr) {
10203
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for callConfig (non-blocking): ${traceErr}`);
10204
+ }
10180
10205
  await LLM.streamWithTools(
10181
10206
  { sys: prompts.system, user: prompts.user },
10182
10207
  tools,
@@ -10294,6 +10319,11 @@ Analyze the error and try again with a corrected query.`;
10294
10319
  logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for schema prompt (non-blocking): ${traceErr}`);
10295
10320
  }
10296
10321
  const databaseRules = await promptLoader.loadDatabaseRulesForType(sourceType);
10322
+ try {
10323
+ if (this.traceSchemaEntry) this.traceSchemaEntry.databaseRulesText = databaseRules;
10324
+ } catch (traceErr) {
10325
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for databaseRulesText (non-blocking): ${traceErr}`);
10326
+ }
10297
10327
  const rowLimitSyntax = {
10298
10328
  "mssql": `Use SELECT TOP ${this.config.maxRowsFetched} in every SELECT statement`,
10299
10329
  "postgres": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
@@ -10305,6 +10335,11 @@ Analyze the error and try again with a corrected query.`;
10305
10335
  "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)`
10306
10336
  };
10307
10337
  const rowLimitInstruction = rowLimitSyntax[sourceType] || `Limit results to ${this.config.maxRowsFetched} rows`;
10338
+ try {
10339
+ if (this.traceSchemaEntry) this.traceSchemaEntry.rowLimitSyntaxText = rowLimitInstruction;
10340
+ } catch (traceErr) {
10341
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for rowLimitSyntaxText (non-blocking): ${traceErr}`);
10342
+ }
10308
10343
  const hasSchemaSearch = !this.options.skipSchemaSearch && !!this.tool.schemaSearchFn;
10309
10344
  const schemaTier = this.tool.schemaTier || "";
10310
10345
  let schemaSearchInstructions = "";
@@ -10338,7 +10373,18 @@ This source has a large schema. The top tables are shown in detail above, but no
10338
10373
  Even if a table appears in the detailed schema above, search_schema returns sample values that help you write correct WHERE filters.
10339
10374
  **Never skip the search step \u2014 it prevents failed queries and retries.**`;
10340
10375
  }
10376
+ try {
10377
+ if (this.traceSchemaEntry) this.traceSchemaEntry.schemaSearchInstructionsText = schemaSearchInstructions;
10378
+ } catch (traceErr) {
10379
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for schemaSearchInstructionsText (non-blocking): ${traceErr}`);
10380
+ }
10341
10381
  const displaySourceType = sourceType === "excel" || sourceType === "csv" ? `${sourceType} \u2014 uses DuckDB SQL engine` : sourceType;
10382
+ const userAccessContextText = this.config.userAccessContext || "No user-specific access restrictions.";
10383
+ try {
10384
+ if (this.traceSchemaEntry) this.traceSchemaEntry.userAccessContextText = userAccessContextText;
10385
+ } catch (traceErr) {
10386
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for userAccessContextText (non-blocking): ${traceErr}`);
10387
+ }
10342
10388
  const prompts = await promptLoader.loadPrompts("agent-source-query", {
10343
10389
  SOURCE_NAME: sourceName,
10344
10390
  SOURCE_TYPE: displaySourceType,
@@ -10356,7 +10402,7 @@ Even if a table appears in the detailed schema above, search_schema returns samp
10356
10402
  GLOBAL_KNOWLEDGE_BASE: this.config.globalKnowledgeBase || "No global knowledge base available.",
10357
10403
  CURRENT_DATETIME: getCurrentDateTimeForPrompt(),
10358
10404
  KNOWLEDGE_BASE_CONTEXT: this.config.knowledgeBaseContext || "No additional knowledge base context available.",
10359
- USER_ACCESS_CONTEXT: this.config.userAccessContext || "No user-specific access restrictions.",
10405
+ USER_ACCESS_CONTEXT: userAccessContextText,
10360
10406
  INTENT: intent
10361
10407
  });
10362
10408
  return { system: prompts.system, user: prompts.user };
@@ -11554,7 +11600,7 @@ var WRITE_ANALYSIS_TOOL_DEF = {
11554
11600
  required: ["analysisBody"]
11555
11601
  }
11556
11602
  };
11557
- var MAX_SCRIPT_ATTEMPTS = 3;
11603
+ var MAX_SCRIPT_ATTEMPTS = 8;
11558
11604
  var MAX_ANALYSIS_ATTEMPTS = 3;
11559
11605
  var MainAgent = class {
11560
11606
  constructor(externalTools, config2, scriptStore, turnId, streamBuffer, workflows = [], forkMode = false, editContext, componentCatalog = [], displayPreference) {
@@ -11670,6 +11716,16 @@ var MainAgent = class {
11670
11716
  } catch (traceErr) {
11671
11717
  logger.warn(`[MainAgent] Trace capture failed for entity catalog (non-blocking): ${traceErr}`);
11672
11718
  }
11719
+ try {
11720
+ if (this.config.trace) this.config.trace.concepts.catalogText = conceptCatalog.text ?? "";
11721
+ } catch (traceErr) {
11722
+ logger.warn(`[MainAgent] Trace capture failed for concept catalog (non-blocking): ${traceErr}`);
11723
+ }
11724
+ try {
11725
+ if (this.config.trace) this.config.trace.concepts.invariantsText = conceptInvariants.text ?? "";
11726
+ } catch (traceErr) {
11727
+ logger.warn(`[MainAgent] Trace capture failed for concept invariants (non-blocking): ${traceErr}`);
11728
+ }
11673
11729
  const systemPrompt = await this.buildSystemPrompt(
11674
11730
  summaries,
11675
11731
  directTools,
@@ -11695,9 +11751,15 @@ var MainAgent = class {
11695
11751
  // flow falls back to generateScriptComponents exactly as before.
11696
11752
  ...this.scriptingEnabled && this.componentCatalog.length > 0 ? [this.buildWriteComponentsToolDef()] : []
11697
11753
  ];
11754
+ try {
11755
+ if (this.config.trace) this.config.trace.toolsSent = tools;
11756
+ } catch (traceErr) {
11757
+ logger.warn(`[MainAgent] Trace capture failed for tools sent (non-blocking): ${traceErr}`);
11758
+ }
11698
11759
  const sourceResults = [];
11699
11760
  const executedTools = [];
11700
11761
  let sourceCallCounter = 0;
11762
+ const toolIdCallCounts = {};
11701
11763
  let selectedWorkflow;
11702
11764
  const toolHandler = async (toolName, toolInput) => {
11703
11765
  const workflow = this.workflows.find((w) => w.id === toolName);
@@ -11775,6 +11837,17 @@ var MainAgent = class {
11775
11837
  ...sourceInput,
11776
11838
  intent: sourceInput.intent + entityBlock + conceptBlock
11777
11839
  });
11840
+ const callNumber = toolIdCallCounts[externalTool.id] = (toolIdCallCounts[externalTool.id] ?? 0) + 1;
11841
+ if (callNumber > 1) {
11842
+ const suffix = `#${callNumber}`;
11843
+ result.sourceId = `${result.sourceId}${suffix}`;
11844
+ if (result.executedTool) {
11845
+ result.executedTool = { ...result.executedTool, id: `${result.executedTool.id}${suffix}` };
11846
+ }
11847
+ if (result.allExecutedTools && result.allExecutedTools.length > 0) {
11848
+ result.allExecutedTools = result.allExecutedTools.map((t) => ({ ...t, id: `${t.id}${suffix}` }));
11849
+ }
11850
+ }
11778
11851
  sourceResults.push(result);
11779
11852
  if (result.success) {
11780
11853
  if (result.allExecutedTools && result.allExecutedTools.length > 0) {
@@ -11789,6 +11862,7 @@ var MainAgent = class {
11789
11862
  if (entry) {
11790
11863
  entry.result = formatted;
11791
11864
  if (this.resolvedConcepts.length) entry.resolvedConcepts = [...this.resolvedConcepts];
11865
+ entry.aggregation = sourceInput.aggregation;
11792
11866
  }
11793
11867
  } catch (traceErr) {
11794
11868
  logger.warn(`[MainAgent] Trace capture failed for source result (non-blocking): ${traceErr}`);
@@ -11796,6 +11870,7 @@ var MainAgent = class {
11796
11870
  return formatted;
11797
11871
  };
11798
11872
  let text = "";
11873
+ const firstIterationToolChoice = entitySearchActive ? { type: "tool", name: "resolve_entities" } : (this.forkMode || this.editMode) && this.scriptingEnabled ? { type: "any" } : void 0;
11799
11874
  try {
11800
11875
  text = await LLM.streamWithTools(
11801
11876
  {
@@ -11814,14 +11889,7 @@ var MainAgent = class {
11814
11889
  apiKey: apiKey || this.config.apiKey,
11815
11890
  partial: streamCallback,
11816
11891
  signal,
11817
- // PIN resolve_entities to iteration 1 in EVERY mode — edit and fork
11818
- // included. An optional tool reproduces the bug it exists to fix (the
11819
- // agent skipped resolution and hand-wrote `LIKE '%FDC%'`), and an edit
11820
- // like "same thing for Premier Energies" needs resolution just as much
11821
- // as a fresh ask does. It also satisfies what fork/edit used `any` for —
11822
- // a tool call on iteration 1 so the model cannot stop at a bare "I'll
11823
- // adapt…" preamble; iterations 2+ revert to auto so write_script follows.
11824
- ...entitySearchActive ? { firstIterationToolChoice: { type: "tool", name: "resolve_entities" } } : (this.forkMode || this.editMode) && this.scriptingEnabled ? { firstIterationToolChoice: { type: "any" } } : {}
11892
+ ...firstIterationToolChoice ? { firstIterationToolChoice } : {}
11825
11893
  },
11826
11894
  this.config.maxIterations
11827
11895
  );
@@ -11975,6 +12043,11 @@ ${catalog}`,
11975
12043
  async handleWriteComponents(input) {
11976
12044
  const body = String(input?.componentsBody || "").trim();
11977
12045
  if (!body) return "write_components needs `componentsBody`.";
12046
+ try {
12047
+ if (this.config.trace) this.config.trace.writeComponentsBody = body;
12048
+ } catch (traceErr) {
12049
+ logger.warn(`[MainAgent] Trace capture failed for write_components body (non-blocking): ${traceErr}`);
12050
+ }
11978
12051
  const result = this.scriptState.lastSuccessfulResult;
11979
12052
  if (!result) {
11980
12053
  return "write_components requires data: run write_script then execute_script successfully first.";
@@ -12061,6 +12134,11 @@ Now write your answer for the user. Do not restate the component list.`;
12061
12134
  async handleWriteAnalysis(input) {
12062
12135
  const body = String(input?.analysisBody || "").trim();
12063
12136
  if (!body) return "write_analysis needs `analysisBody`.";
12137
+ try {
12138
+ if (this.config.trace) this.config.trace.writeAnalysisBody = body;
12139
+ } catch (traceErr) {
12140
+ logger.warn(`[MainAgent] Trace capture failed for write_analysis body (non-blocking): ${traceErr}`);
12141
+ }
12064
12142
  const verified = this.scriptState.lastSuccessfulResult;
12065
12143
  if (!verified) {
12066
12144
  return "No verified script result yet \u2014 call write_script then execute_script first, so the analysis is written against real data.";
@@ -12565,7 +12643,6 @@ ${r.body}`).join("\n\n");
12565
12643
  * whole answer down.
12566
12644
  */
12567
12645
  async handleResolveConcepts(toolInput) {
12568
- var _a;
12569
12646
  const fn = this.config.collections?.["concepts"]?.["resolve"];
12570
12647
  const names = Array.isArray(toolInput?.names) ? toolInput.names.filter(Boolean) : [];
12571
12648
  if (!fn) {
@@ -12604,8 +12681,16 @@ ${r.body}`).join("\n\n");
12604
12681
  };
12605
12682
  try {
12606
12683
  if (this.config.trace) {
12607
- (_a = this.config.trace).conceptResolution ?? (_a.conceptResolution = { calls: [] });
12608
- this.config.trace.conceptResolution.calls.push({ via: "resolve_concepts", asked: names, implied: res?.implied || [], ...seenByLLM });
12684
+ this.config.trace.concepts.calls.push({
12685
+ via: "resolve_concepts",
12686
+ asked: names,
12687
+ implied: res?.implied || [],
12688
+ returned: seenByLLM.concepts,
12689
+ ...corrected.length ? { corrected } : {},
12690
+ ...suggestions.length ? { suggestions } : {},
12691
+ unmatched: res?.unmatched || [],
12692
+ note: notes.join(" ")
12693
+ });
12609
12694
  }
12610
12695
  } catch (traceErr) {
12611
12696
  logger.warn(`[MainAgent] Trace capture failed for resolve_concepts (non-blocking): ${traceErr}`);
@@ -12648,7 +12733,6 @@ ${r.body}`).join("\n\n");
12648
12733
  * leave the agent exactly as it was, not take the whole answer down.
12649
12734
  */
12650
12735
  async handleResolveEntities(toolInput, userPrompt) {
12651
- var _a;
12652
12736
  const fn = this.config.collections?.["entity-search"]?.["resolveEntities"];
12653
12737
  const mentions = Array.isArray(toolInput?.mentions) ? toolInput.mentions.filter((m) => m?.text) : [];
12654
12738
  const entityTypes = Array.isArray(toolInput?.entityTypes) ? toolInput.entityTypes.filter(Boolean) : [];
@@ -12657,8 +12741,7 @@ ${r.body}`).join("\n\n");
12657
12741
  if (conceptTrace) {
12658
12742
  try {
12659
12743
  if (this.config.trace) {
12660
- (_a = this.config.trace).conceptResolution ?? (_a.conceptResolution = { calls: [] });
12661
- this.config.trace.conceptResolution.calls.push({ via: "resolve_entities", ...conceptTrace });
12744
+ this.config.trace.concepts.calls.push({ via: "resolve_entities", ...conceptTrace });
12662
12745
  }
12663
12746
  } catch (traceErr) {
12664
12747
  logger.warn(`[MainAgent] Trace capture failed for concepts-in-resolve_entities (non-blocking): ${traceErr}`);
@@ -12925,6 +13008,11 @@ ${formatted}`;
12925
13008
  ${t.description || "No description"}${paramList ? "\n Parameters:\n" + paramList : ""}`;
12926
13009
  }).join("\n\n");
12927
13010
  }
13011
+ try {
13012
+ if (this.config.trace) this.config.trace.directToolsText = directToolsText;
13013
+ } catch (traceErr) {
13014
+ logger.warn(`[MainAgent] Trace capture failed for direct tools text (non-blocking): ${traceErr}`);
13015
+ }
12928
13016
  let workflowsText = "";
12929
13017
  if (workflows.length > 0) {
12930
13018
  workflowsText = workflows.map((w, idx) => {
@@ -12940,10 +13028,20 @@ ${propLines}` : ""
12940
13028
  } else {
12941
13029
  workflowsText = "No workflow components registered for this project.";
12942
13030
  }
13031
+ try {
13032
+ if (this.config.trace) this.config.trace.workflowsText = workflowsText;
13033
+ } catch (traceErr) {
13034
+ logger.warn(`[MainAgent] Trace capture failed for workflows text (non-blocking): ${traceErr}`);
13035
+ }
12943
13036
  const scriptBodyContract = await promptLoader.loadScriptBodyContract({
12944
13037
  MAX_ROWS_RENDERED: String(MAX_ROWS_RENDERED),
12945
13038
  MAX_ROWS_FETCHED: String(MAX_ROWS_FETCHED)
12946
13039
  });
13040
+ try {
13041
+ if (this.config.trace) this.config.trace.scriptBodyContractText = scriptBodyContract;
13042
+ } catch (traceErr) {
13043
+ logger.warn(`[MainAgent] Trace capture failed for script body contract text (non-blocking): ${traceErr}`);
13044
+ }
12947
13045
  const commonVars = {
12948
13046
  SOURCE_SUMMARIES: summariesText,
12949
13047
  DIRECT_TOOLS: directToolsText,
@@ -12967,6 +13065,20 @@ ${propLines}` : ""
12967
13065
  };
12968
13066
  if (this.editContext) {
12969
13067
  const ec = this.editContext;
13068
+ try {
13069
+ if (this.config.trace) {
13070
+ this.config.trace.editContext = {
13071
+ recipeId: ec.recipeId,
13072
+ parentName: ec.parentName,
13073
+ parentBody: ec.parentBody,
13074
+ instruction: ec.instruction,
13075
+ lastResultColumns: ec.lastResultColumns,
13076
+ parentParams: ec.parentParams
13077
+ };
13078
+ }
13079
+ } catch (traceErr) {
13080
+ logger.warn(`[MainAgent] Trace capture failed for edit context (non-blocking): ${traceErr}`);
13081
+ }
12970
13082
  const prompts2 = await promptLoader.loadPrompts("agent-main-edit", {
12971
13083
  ...commonVars,
12972
13084
  PARENT_SCRIPT_NAME: ec.parentName,
@@ -13241,7 +13353,9 @@ function createRunTrace() {
13241
13353
  schemaNodes: { routing: [], preResolve: [], sourceAgentSchemas: [] },
13242
13354
  script: null,
13243
13355
  scriptMatcher: null,
13244
- entityResolution: { calls: [] }
13356
+ entityResolution: { calls: [] },
13357
+ concepts: { calls: [] },
13358
+ componentGen: []
13245
13359
  };
13246
13360
  }
13247
13361
  var DEFAULT_AGENT_CONFIG = {
@@ -13253,7 +13367,7 @@ var DEFAULT_AGENT_CONFIG = {
13253
13367
  // will use the provider's default model
13254
13368
  maxRetries: 2,
13255
13369
  // 2 retries = 3 total query attempts (1 initial + 2 retries for SQL errors)
13256
- maxIterations: 20
13370
+ maxIterations: 30
13257
13371
  // schema search (2-3) + query attempts (2) + write_script/execute_script (2-3) + write_analysis (up to 3) + LLM responses + final
13258
13372
  };
13259
13373
 
@@ -14154,6 +14268,9 @@ var ScriptMatcher = class {
14154
14268
  );
14155
14269
  logger.logLLMPrompt("scriptMatcher", "system", extractPromptText(prompts.system));
14156
14270
  logger.logLLMPrompt("scriptMatcher", "user", extractPromptText(prompts.user));
14271
+ traceEntry.sent.model = model || void 0;
14272
+ traceEntry.sent.maxTokens = 500;
14273
+ traceEntry.sent.temperature = 0;
14157
14274
  const response = await LLM.stream(
14158
14275
  { sys: prompts.system, user: prompts.user },
14159
14276
  {
@@ -14723,10 +14840,20 @@ async function buildScriptComponent(comp, ctx) {
14723
14840
  return { component, spec };
14724
14841
  }
14725
14842
  async function generateScriptComponents(params) {
14726
- const { userPrompt, scriptResult, queryIds, availableComponents, apiKey, model, componentStreamCallback, analysisText, analysisSummary, signal } = params;
14843
+ const { userPrompt, scriptResult, queryIds, availableComponents, apiKey, model, componentStreamCallback, analysisText, analysisSummary, signal, trace } = params;
14844
+ const traceEntry = { via: "generateScriptComponents" };
14845
+ const pushTrace = () => {
14846
+ if (!trace) return;
14847
+ try {
14848
+ trace.componentGen.push(traceEntry);
14849
+ } catch (traceErr) {
14850
+ logger.warn(`[ScriptComponentGen] Trace capture failed for generateScriptComponents (non-blocking): ${traceErr}`);
14851
+ }
14852
+ };
14727
14853
  const queries = scriptResult.executedQueries;
14728
14854
  if (!queries || queries.length === 0) {
14729
14855
  logger.warn(`[ScriptComponentGen] No query data available \u2014 returning empty`);
14856
+ pushTrace();
14730
14857
  return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14731
14858
  }
14732
14859
  logger.info(`[ScriptComponentGen] Starting | ${queries.length} queries | ${availableComponents.length} available components`);
@@ -14744,6 +14871,7 @@ async function generateScriptComponents(params) {
14744
14871
  Keywords: ${keywords}
14745
14872
  Props Structure: ${propsPreview}`;
14746
14873
  }).join("\n\n");
14874
+ traceEntry.componentCatalog = availableCompsText;
14747
14875
  const sourceDescriptions = queries.map((q, idx) => {
14748
14876
  if (!q.data || q.data.length === 0) return null;
14749
14877
  const cols = columnsByIndex[idx];
@@ -14760,15 +14888,22 @@ async function generateScriptComponents(params) {
14760
14888
  ${sampleData}
14761
14889
  \`\`\``;
14762
14890
  }).filter(Boolean).join("\n\n");
14891
+ traceEntry.columnDescriptions = sourceDescriptions;
14763
14892
  try {
14893
+ const sourceNameValue = queries.map((q) => q.sourceName).join(", ");
14894
+ const rowCountValue = queries.map((q) => `${q.sourceName}: ${Math.min(q.count, MAX_ROWS_RENDERED)}${q.count > MAX_ROWS_RENDERED ? ` of ${q.count}` : ""}`).join(", ");
14895
+ const analysisTextValue = analysisText && analysisText.trim() ? analysisText.trim() : "No analysis text provided \u2014 infer intent from the user question and the returned data.";
14896
+ traceEntry.sourceName = sourceNameValue;
14897
+ traceEntry.rowCount = rowCountValue;
14898
+ traceEntry.analysisText = analysisTextValue;
14764
14899
  const prompts = await promptLoader.loadPrompts("script-components", {
14765
14900
  USER_PROMPT: userPrompt,
14766
14901
  AVAILABLE_COMPONENTS: availableCompsText,
14767
- SOURCE_NAME: queries.map((q) => q.sourceName).join(", "),
14768
- ROW_COUNT: queries.map((q) => `${q.sourceName}: ${Math.min(q.count, MAX_ROWS_RENDERED)}${q.count > MAX_ROWS_RENDERED ? ` of ${q.count}` : ""}`).join(", "),
14902
+ SOURCE_NAME: sourceNameValue,
14903
+ ROW_COUNT: rowCountValue,
14769
14904
  COLUMN_DESCRIPTIONS: sourceDescriptions,
14770
14905
  SAMPLE_DATA: "",
14771
- ANALYSIS_TEXT: analysisText && analysisText.trim() ? analysisText.trim() : "No analysis text provided \u2014 infer intent from the user question and the returned data."
14906
+ ANALYSIS_TEXT: analysisTextValue
14772
14907
  });
14773
14908
  const ctx = {
14774
14909
  queries,
@@ -14799,19 +14934,21 @@ ${sampleData}
14799
14934
  } : void 0;
14800
14935
  logger.logLLMPrompt("scriptComponentGen", "system", prompts.system);
14801
14936
  logger.logLLMPrompt("scriptComponentGen", "user", prompts.user);
14937
+ const callConfig = { model: model || void 0, maxTokens: 5e3, temperature: 0 };
14938
+ traceEntry.callConfig = callConfig;
14802
14939
  const response = await LLM.stream(
14803
14940
  { sys: prompts.system, user: prompts.user },
14804
14941
  {
14805
- model: model || void 0,
14806
- maxTokens: 5e3,
14807
- temperature: 0,
14942
+ ...callConfig,
14808
14943
  apiKey,
14809
14944
  partial,
14810
14945
  signal
14811
14946
  },
14812
14947
  true
14813
14948
  );
14814
- logger.logLLMPrompt("scriptComponentGen:response", "user", JSON.stringify(response, null, 2));
14949
+ const responseText = JSON.stringify(response, null, 2);
14950
+ logger.logLLMPrompt("scriptComponentGen:response", "user", responseText);
14951
+ traceEntry.rawResponse = responseText;
14815
14952
  if (!response || !response.components || !Array.isArray(response.components)) {
14816
14953
  logger.warn(`[ScriptComponentGen] LLM returned invalid response`);
14817
14954
  return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
@@ -14879,26 +15016,45 @@ ${sampleData}
14879
15016
  const msg = error instanceof Error ? error.message : String(error);
14880
15017
  logger.error(`[ScriptComponentGen] Failed: ${msg}`);
14881
15018
  return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
15019
+ } finally {
15020
+ pushTrace();
14882
15021
  }
14883
15022
  }
14884
- async function summarizeToMarkdown(analysis, apiKey, model) {
14885
- if (!analysis || !analysis.trim()) return "";
15023
+ async function summarizeToMarkdown(analysis, apiKey, model, trace) {
15024
+ const traceEntry = { via: "summarizeToMarkdown", analysisText: analysis };
15025
+ const pushTrace = () => {
15026
+ if (!trace) return;
15027
+ try {
15028
+ trace.componentGen.push(traceEntry);
15029
+ } catch (traceErr) {
15030
+ logger.warn(`[ScriptComponentGen] Trace capture failed for summarizeToMarkdown (non-blocking): ${traceErr}`);
15031
+ }
15032
+ };
15033
+ if (!analysis || !analysis.trim()) {
15034
+ pushTrace();
15035
+ return "";
15036
+ }
14886
15037
  try {
14887
15038
  const prompts = await promptLoader.loadPrompts("script-component-summary", { ANALYSIS_TEXT: analysis });
14888
- const text = await LLM.text({ sys: prompts.system, user: prompts.user }, { model: model || void 0, maxTokens: 400, temperature: 0, apiKey });
15039
+ const callConfig = { model: model || void 0, maxTokens: 400, temperature: 0 };
15040
+ traceEntry.callConfig = callConfig;
15041
+ const text = await LLM.text({ sys: prompts.system, user: prompts.user }, { ...callConfig, apiKey });
15042
+ traceEntry.rawResponse = text;
14889
15043
  return (text || "").trim();
14890
15044
  } catch (err) {
14891
15045
  logger.warn(`[ScriptComponentGen] summarizeToMarkdown failed, falling back: ${err instanceof Error ? err.message : String(err)}`);
14892
15046
  return "";
15047
+ } finally {
15048
+ pushTrace();
14893
15049
  }
14894
15050
  }
14895
- async function markdownContent(analysisSummary, analysisText, apiKey, model) {
15051
+ async function markdownContent(analysisSummary, analysisText, apiKey, model, trace) {
14896
15052
  const bullets = (analysisSummary || []).map((b) => String(b).trim()).filter(Boolean);
14897
15053
  if (bullets.length) return bullets.map((b) => `- ${b}`).join("\n");
14898
- return await summarizeToMarkdown(analysisText || "", apiKey, model) || analysisText || "";
15054
+ return await summarizeToMarkdown(analysisText || "", apiKey, model, trace) || analysisText || "";
14899
15055
  }
14900
15056
  async function assembleComponentsFromSpecs(params) {
14901
- const { specs, scriptResult, queryIds, availableComponents, componentStreamCallback, analysisText, analysisSummary, apiKey, model } = params;
15057
+ const { specs, scriptResult, queryIds, availableComponents, componentStreamCallback, analysisText, analysisSummary, apiKey, model, trace } = params;
14902
15058
  if (!specs || specs.length === 0) return null;
14903
15059
  const queries = scriptResult.executedQueries || [];
14904
15060
  const byId = new Map(queries.map((q) => [q.sourceId, q]));
@@ -14924,7 +15080,7 @@ async function assembleComponentsFromSpecs(params) {
14924
15080
  return null;
14925
15081
  }
14926
15082
  if (spec.sourceRef === "markdown") {
14927
- const summary = await markdownContent(analysisSummary, analysisText, apiKey, model) || spec.content || "";
15083
+ const summary = await markdownContent(analysisSummary, analysisText, apiKey, model, trace) || spec.content || "";
14928
15084
  const md = buildMarkdown(summary, spec.title, spec.description);
14929
15085
  if (md) {
14930
15086
  out.push(md);
@@ -14980,7 +15136,7 @@ async function assembleComponentsFromSpecs(params) {
14980
15136
  }
14981
15137
  }
14982
15138
  if (out.length > 0 && !out.some((c) => c.type === "MarkdownBlock")) {
14983
- const summary = await markdownContent(analysisSummary, analysisText, apiKey, model);
15139
+ const summary = await markdownContent(analysisSummary, analysisText, apiKey, model, trace);
14984
15140
  const md = buildMarkdown(summary);
14985
15141
  if (md) {
14986
15142
  out.push(md);
@@ -15001,31 +15157,47 @@ async function authorComponentsProgram(params) {
15001
15157
  externalTools,
15002
15158
  apiKey,
15003
15159
  model,
15004
- signal
15160
+ signal,
15161
+ trace
15005
15162
  } = params;
15006
15163
  const maxAttempts = params.maxAttempts ?? 2;
15007
- const queries = scriptResult.executedQueries || [];
15008
- if (!queries.length) return null;
15009
- const datasets = {};
15010
- for (const q of queries) {
15011
- if (q.virtual && q.sourceId?.startsWith("computed:")) {
15012
- datasets[q.sourceId.slice("computed:".length)] = q.data;
15164
+ const traceEntry = { via: "authorComponentsProgram", instruction, attempts: [] };
15165
+ const pushTrace = () => {
15166
+ if (!trace) return;
15167
+ try {
15168
+ trace.componentGen.push(traceEntry);
15169
+ } catch (traceErr) {
15170
+ logger.warn(`[ComponentsEdit] Trace capture failed for authorComponentsProgram (non-blocking): ${traceErr}`);
15013
15171
  }
15014
- }
15015
- const catalog = availableComponents.map((c) => {
15016
- const cfg = c.props?.config;
15017
- return `- ${c.name} (${c.type})${c.description ? ` \u2014 ${c.description}` : ""}` + (cfg ? `
15172
+ };
15173
+ try {
15174
+ const queries = scriptResult.executedQueries || [];
15175
+ if (!queries.length) return null;
15176
+ const datasets = {};
15177
+ for (const q of queries) {
15178
+ if (q.virtual && q.sourceId?.startsWith("computed:")) {
15179
+ datasets[q.sourceId.slice("computed:".length)] = q.data;
15180
+ }
15181
+ }
15182
+ const catalog = availableComponents.map((c) => {
15183
+ const cfg = c.props?.config;
15184
+ return `- ${c.name} (${c.type})${c.description ? ` \u2014 ${c.description}` : ""}` + (cfg ? `
15018
15185
  config: ${JSON.stringify(cfg)}` : "");
15019
- }).join("\n");
15020
- const shapes = queries.map((q) => {
15021
- const cols = inferColumns(q.data);
15022
- const desc = [...cols.values()].map((c) => `${c.name}:${c.type}`).join(", ");
15023
- return `- ${q.sourceId} \u2014 ${q.count ?? q.data.length} rows [${desc}]`;
15024
- }).join("\n");
15025
- const current = stripToComponentsExport(recipe.scriptBody || "");
15026
- let feedback = "";
15027
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
15028
- const sys = `You re-author ONE function: \`getComponents(data, params, fmt, datasets)\`, which RETURNS an array of component specs { componentType, sourceRef, title, description, config }.
15186
+ }).join("\n");
15187
+ traceEntry.componentCatalog = catalog;
15188
+ const shapes = queries.map((q) => {
15189
+ const cols = inferColumns(q.data);
15190
+ const desc = [...cols.values()].map((c) => `${c.name}:${c.type}`).join(", ");
15191
+ return `- ${q.sourceId} \u2014 ${q.count ?? q.data.length} rows [${desc}]`;
15192
+ }).join("\n");
15193
+ traceEntry.datasetShapes = shapes;
15194
+ const current = stripToComponentsExport(recipe.scriptBody || "");
15195
+ traceEntry.currentBody = current;
15196
+ const callConfig = { model: model || void 0, maxTokens: 2e3, temperature: 0 };
15197
+ traceEntry.callConfig = callConfig;
15198
+ let feedback = "";
15199
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
15200
+ const sys = `You re-author ONE function: \`getComponents(data, params, fmt, datasets)\`, which RETURNS an array of component specs { componentType, sourceRef, title, description, config }.
15029
15201
 
15030
15202
  It re-runs on every replay, so build any figure in a title from \`datasets\`/\`fmt\` \u2014 never type one in. Bind each component to ONE \`sourceRef\` from the datasets below and select columns from it; never group, sum, or reshape, and never set an aggregation config.
15031
15203
 
@@ -15034,7 +15206,7 @@ ${shapes}
15034
15206
 
15035
15207
  ## Available components
15036
15208
  ${catalog}`;
15037
- const user = `Apply this rendering change: ${instruction}
15209
+ const user = `Apply this rendering change: ${instruction}
15038
15210
 
15039
15211
  ` + (current ? `Current getComponents:
15040
15212
  \`\`\`js
@@ -15042,57 +15214,64 @@ ${current}
15042
15214
  \`\`\`
15043
15215
 
15044
15216
  Change ONLY what the instruction asks for; keep every other component and its text as-is.` : "There is no existing getComponents \u2014 author one that displays this result under the instruction above.") + feedback + "\n\nReply with the complete `export function getComponents(...) { ... }` and nothing else.";
15045
- let body;
15046
- try {
15047
- body = await LLM.stream({ sys, user }, { model, maxTokens: 2e3, temperature: 0, apiKey, signal });
15048
- } catch (err) {
15049
- logger.warn(`[ComponentsEdit] LLM call failed: ${err instanceof Error ? err.message : err}`);
15050
- return null;
15051
- }
15052
- body = body.replace(/^[\s\S]*?```(?:js|javascript|ts|typescript)?\n/, "").replace(/```[\s\S]*$/, "").trim();
15053
- if (!/export\s+(?:async\s+)?function\s+getComponents\b/.test(body)) {
15054
- feedback = `
15217
+ const feedbackThisAttempt = feedback;
15218
+ let body;
15219
+ try {
15220
+ body = await LLM.stream({ sys, user }, { ...callConfig, apiKey, signal });
15221
+ } catch (err) {
15222
+ logger.warn(`[ComponentsEdit] LLM call failed: ${err instanceof Error ? err.message : err}`);
15223
+ traceEntry.attempts.push({ feedback: feedbackThisAttempt });
15224
+ return null;
15225
+ }
15226
+ traceEntry.attempts.push({ feedback: feedbackThisAttempt, rawResponse: body });
15227
+ traceEntry.rawResponse = body;
15228
+ body = body.replace(/^[\s\S]*?```(?:js|javascript|ts|typescript)?\n/, "").replace(/```[\s\S]*$/, "").trim();
15229
+ if (!/export\s+(?:async\s+)?function\s+getComponents\b/.test(body)) {
15230
+ feedback = `
15055
15231
 
15056
15232
  Your previous reply did not contain \`export function getComponents\`.`;
15057
- continue;
15058
- }
15059
- if (!await scriptStore.attachComponents(recipe.id, body)) return null;
15060
- const { components, componentsError } = await runComponentsOnly(
15061
- recipe,
15062
- scriptStore.getScriptPath(recipe),
15063
- {},
15064
- scriptResult.data,
15065
- { externalTools, signal },
15066
- datasets
15067
- );
15068
- if (componentsError || !components?.length) {
15069
- feedback = `
15233
+ continue;
15234
+ }
15235
+ if (!await scriptStore.attachComponents(recipe.id, body)) return null;
15236
+ const { components, componentsError } = await runComponentsOnly(
15237
+ recipe,
15238
+ scriptStore.getScriptPath(recipe),
15239
+ {},
15240
+ scriptResult.data,
15241
+ { externalTools, signal },
15242
+ datasets
15243
+ );
15244
+ if (componentsError || !components?.length) {
15245
+ feedback = `
15070
15246
 
15071
15247
  Your previous getComponents failed: ${componentsError || "it returned no components"}`;
15072
- continue;
15073
- }
15074
- const availableSourceRefs = queries.map((q) => q.sourceId);
15075
- const findings = [];
15076
- for (const spec of components) {
15077
- const q = queries.find((x) => x.sourceId === spec.sourceRef);
15078
- const rows = q?.data || [];
15079
- findings.push(...validateComponentSpec(
15080
- { ...spec, config: spec.config || {} },
15081
- { cols: inferColumns(rows), rowCount: rows.length, rows, availableSourceRefs }
15082
- ).filter((f) => f.severity === "error"));
15083
- }
15084
- if (findings.length) {
15085
- logger.warn(`[ComponentsEdit] attempt ${attempt} rejected: ${findings.length} finding(s)`);
15086
- feedback = `
15248
+ continue;
15249
+ }
15250
+ const availableSourceRefs = queries.map((q) => q.sourceId);
15251
+ const findings = [];
15252
+ for (const spec of components) {
15253
+ const q = queries.find((x) => x.sourceId === spec.sourceRef);
15254
+ const rows = q?.data || [];
15255
+ findings.push(...validateComponentSpec(
15256
+ { ...spec, config: spec.config || {} },
15257
+ { cols: inferColumns(rows), rowCount: rows.length, rows, availableSourceRefs }
15258
+ ).filter((f) => f.severity === "error"));
15259
+ }
15260
+ if (findings.length) {
15261
+ logger.warn(`[ComponentsEdit] attempt ${attempt} rejected: ${findings.length} finding(s)`);
15262
+ feedback = `
15087
15263
 
15088
15264
  ${formatFindingsForAgent(findings)}`;
15089
- continue;
15265
+ continue;
15266
+ }
15267
+ logger.info(`[ComponentsEdit] Re-authored getComponents for "${recipe.name}" (${components.length} component(s), attempt ${attempt})`);
15268
+ return components;
15090
15269
  }
15091
- logger.info(`[ComponentsEdit] Re-authored getComponents for "${recipe.name}" (${components.length} component(s), attempt ${attempt})`);
15092
- return components;
15270
+ logger.warn(`[ComponentsEdit] Gave up after ${maxAttempts} attempts \u2014 falling back to spec generation`);
15271
+ return null;
15272
+ } finally {
15273
+ pushTrace();
15093
15274
  }
15094
- logger.warn(`[ComponentsEdit] Gave up after ${maxAttempts} attempts \u2014 falling back to spec generation`);
15095
- return null;
15096
15275
  }
15097
15276
  function stripToComponentsExport(body) {
15098
15277
  const m = body.search(/export\s+(?:async\s+)?function\s+getComponents\b/);
@@ -17559,7 +17738,8 @@ ${JSON.stringify(preview, null, 2)}
17559
17738
  analysisText: scriptTextResponse,
17560
17739
  analysisSummary: scriptResult?.analysis?.summary,
17561
17740
  apiKey,
17562
- model: sourceAgentModel
17741
+ model: sourceAgentModel,
17742
+ trace: runTrace
17563
17743
  });
17564
17744
  if (assembled && assembled.length > 0) {
17565
17745
  matchedComponents2 = assembled;
@@ -17577,7 +17757,8 @@ ${JSON.stringify(preview, null, 2)}
17577
17757
  externalTools: agentTools,
17578
17758
  apiKey,
17579
17759
  model: sourceAgentModel,
17580
- signal
17760
+ signal,
17761
+ trace: runTrace
17581
17762
  });
17582
17763
  if (reauthored?.length) {
17583
17764
  const assembled = await assembleComponentsFromSpecs({
@@ -17589,7 +17770,8 @@ ${JSON.stringify(preview, null, 2)}
17589
17770
  analysisText: scriptTextResponse,
17590
17771
  analysisSummary: scriptResult?.analysis?.summary,
17591
17772
  apiKey,
17592
- model: sourceAgentModel
17773
+ model: sourceAgentModel,
17774
+ trace: runTrace
17593
17775
  });
17594
17776
  if (assembled?.length) {
17595
17777
  matchedComponents2 = assembled;
@@ -17630,7 +17812,8 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17630
17812
  collections,
17631
17813
  analysisText: scriptTextResponse,
17632
17814
  analysisSummary: scriptResult?.analysis?.summary,
17633
- signal
17815
+ signal,
17816
+ trace: runTrace
17634
17817
  });
17635
17818
  if (compResult.components.length > 0) {
17636
17819
  matchedComponents2 = compResult.components;
@@ -17770,6 +17953,18 @@ User question: ${prompt}
17770
17953
  ---
17771
17954
 
17772
17955
  BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containing the adapted getData() body, immediately followed by \`execute_script\`. Do NOT reply with prose, a plan, or "I'll adapt\u2026" first \u2014 that ends your turn with no script and produces a broken answer. Call \`write_script\` now.`;
17956
+ if (runTrace) {
17957
+ try {
17958
+ runTrace.forkContext = {
17959
+ ...runTrace.forkContext || {},
17960
+ parentBody: forkContext.parentBody,
17961
+ gaps: gapsBlock,
17962
+ modificationHint: hintBlock
17963
+ };
17964
+ } catch (traceErr) {
17965
+ logger.warn(`[AgentFlow] Trace capture failed for fork-mode preamble (non-blocking): ${traceErr}`);
17966
+ }
17967
+ }
17773
17968
  }
17774
17969
  let filteredTools = agentTools;
17775
17970
  const sqlToolCount = agentTools.filter((t) => t.toolType !== "direct").length;
@@ -17995,7 +18190,8 @@ BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containin
17995
18190
  analysisText: agentResponse.text,
17996
18191
  analysisSummary: agentResponse.analysis?.summary,
17997
18192
  apiKey,
17998
- model: sourceAgentModel
18193
+ model: sourceAgentModel,
18194
+ trace: runTrace
17999
18195
  });
18000
18196
  if (assembled && assembled.length > 0) {
18001
18197
  matchedComponents = assembled;
@@ -18022,7 +18218,8 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18022
18218
  collections,
18023
18219
  analysisText: agentResponse.text,
18024
18220
  analysisSummary: agentResponse.analysis?.summary,
18025
- signal
18221
+ signal,
18222
+ trace: runTrace
18026
18223
  };
18027
18224
  const MAX_COMP_ATTEMPTS = 3;
18028
18225
  let compResult;
@@ -18178,6 +18375,18 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18178
18375
  forkDepth: Math.min(FORK_DEPTH_CAP, forkContext.parentDepth + 1),
18179
18376
  forkReason: forkContext.modificationHint
18180
18377
  } : void 0;
18378
+ if (runTrace && forkContext && lineage) {
18379
+ try {
18380
+ runTrace.forkContext = {
18381
+ ...runTrace.forkContext || {},
18382
+ parentRecipeId: lineage.parentId,
18383
+ forkDepth: lineage.forkDepth,
18384
+ forkReason: lineage.forkReason
18385
+ };
18386
+ } catch (traceErr) {
18387
+ logger.warn(`[AgentFlow] Trace capture failed for fork lineage (non-blocking): ${traceErr}`);
18388
+ }
18389
+ }
18181
18390
  const promoted = await scriptStore.promoteToVerified(authored.recipeId, {
18182
18391
  sourceIds: authored.sourceIds,
18183
18392
  tables: authored.tables,
@@ -18370,7 +18579,7 @@ function transformUIBlockForDB(uiblock, userPrompt, uiBlockId) {
18370
18579
  };
18371
18580
  }
18372
18581
  function hasTraceContent(trace) {
18373
- return trace.kbNodes.global.length > 0 || trace.kbNodes.query.length > 0 || trace.schemaNodes.routing.length > 0 || trace.schemaNodes.preResolve.length > 0 || !!trace.schemaNodes.mainAgentCatalog || trace.schemaNodes.sourceAgentSchemas.length > 0 || trace.script != null || trace.scriptMatcher != null || !!trace.entityResolution.catalogText || trace.entityResolution.calls.length > 0 || !!trace.conversationHistory;
18582
+ return trace.kbNodes.global.length > 0 || trace.kbNodes.query.length > 0 || trace.schemaNodes.routing.length > 0 || trace.schemaNodes.preResolve.length > 0 || !!trace.schemaNodes.mainAgentCatalog || trace.schemaNodes.sourceAgentSchemas.length > 0 || trace.script != null || trace.scriptMatcher != null || !!trace.entityResolution.catalogText || trace.entityResolution.calls.length > 0 || !!trace.conversationHistory || !!trace.userAccessContext || !!trace.userKbContext || !!trace.concepts?.catalogText || !!trace.concepts?.invariantsText || (trace.concepts?.calls?.length ?? 0) > 0 || (trace.componentGen?.length ?? 0) > 0;
18374
18583
  }
18375
18584
  async function saveConversation(params) {
18376
18585
  const { userId, userPrompt, uiblock, uiBlockId, threadId, collections, status = "success", error: turnError, trace } = params;
@@ -26458,8 +26667,7 @@ function buildResolveEntitiesTool(sdk, trace) {
26458
26667
  if (trace) {
26459
26668
  if (entityResult) trace.entityResolution.calls.push({ mentions, ...entityResult });
26460
26669
  if (conceptResult) {
26461
- trace.conceptResolution ?? (trace.conceptResolution = { calls: [] });
26462
- trace.conceptResolution.calls.push({ via: "dashboard-agent", asked: conceptNames, ...conceptResult });
26670
+ trace.concepts.calls.push({ via: "dashboard-agent", asked: conceptNames, ...conceptResult });
26463
26671
  }
26464
26672
  }
26465
26673
  } catch (traceErr) {
@@ -26796,7 +27004,7 @@ ${fullPrompt}
26796
27004
  return { success: false, error: `No configured model found (tried ${tried}). Configure at least one of OPENROUTER_API_KEY, ANTHROPIC_API_KEY, or OPENAI_API_KEY.` };
26797
27005
  }
26798
27006
  }
26799
- model = { ...model, maxTokens: 8e3 };
27007
+ model = { ...model, maxTokens: 2e4 };
26800
27008
  const toolsList = sdk.getTools().map((t) => `- ${t.id}: ${t.name}`).join("\n");
26801
27009
  if (signal?.aborted) {
26802
27010
  console.log(`[DashboardAgent] Aborted during setup \u2014 skipping schema pre-resolution for dashboard ${dashboardId}`);