@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.mjs CHANGED
@@ -3582,7 +3582,8 @@ var getGlobalKnowledgeBase = async ({
3582
3582
  var getUserKnowledgeBase = async ({
3583
3583
  collections,
3584
3584
  userId,
3585
- limit = 100
3585
+ limit = 100,
3586
+ trace
3586
3587
  }) => {
3587
3588
  try {
3588
3589
  if (!userId) {
@@ -3602,6 +3603,13 @@ var getUserKnowledgeBase = async ({
3602
3603
  return "";
3603
3604
  }
3604
3605
  logger.info(`[KnowledgeBase] Retrieved ${result.count || 0} user knowledge base nodes for userId: ${userId}`);
3606
+ if (trace) {
3607
+ try {
3608
+ trace.userKbContext = result.content;
3609
+ } catch (traceErr) {
3610
+ logger.warn(`[KnowledgeBase] Trace capture failed for user KB context (non-blocking): ${traceErr}`);
3611
+ }
3612
+ }
3605
3613
  return result.content;
3606
3614
  } catch (error) {
3607
3615
  const errorMsg = error instanceof Error ? error.message : String(error);
@@ -3618,7 +3626,7 @@ var getAllKnowledgeBase = async ({
3618
3626
  }) => {
3619
3627
  const [globalContext, userContext, queryContext] = await Promise.all([
3620
3628
  getGlobalKnowledgeBase({ collections, trace }),
3621
- getUserKnowledgeBase({ collections, userId }),
3629
+ getUserKnowledgeBase({ collections, userId, trace }),
3622
3630
  getKnowledgeBase({ prompt, collections, topK, trace })
3623
3631
  ]);
3624
3632
  let combinedContext = "";
@@ -9912,6 +9920,11 @@ var SourceAgent = class {
9912
9920
  logger.logLLMPrompt(`sourceAgent:${this.tool.name}`, "system", extractPromptText(prompts.system));
9913
9921
  logger.logLLMPrompt(`sourceAgent:${this.tool.name}`, "user", prompts.user);
9914
9922
  const tools = this.buildToolDefinitions();
9923
+ try {
9924
+ if (this.traceSchemaEntry) this.traceSchemaEntry.toolsSent = tools;
9925
+ } catch (traceErr) {
9926
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for toolsSent (non-blocking): ${traceErr}`);
9927
+ }
9915
9928
  let executedTool = null;
9916
9929
  let allExecutedTools = [];
9917
9930
  let resultData = [];
@@ -10103,6 +10116,18 @@ Analyze the error and try again with a corrected query.`;
10103
10116
  const extraSearches = hasSchemaSearch ? 2 : 0;
10104
10117
  const responseIterations = 1;
10105
10118
  const maxIterations = totalQueryAttempts * perQueryCost + extraSearches + responseIterations;
10119
+ try {
10120
+ if (this.traceSchemaEntry) {
10121
+ this.traceSchemaEntry.callConfig = {
10122
+ model: this.config.sourceAgentModel || void 0,
10123
+ maxTokens: 2048,
10124
+ temperature: 0,
10125
+ maxIterations
10126
+ };
10127
+ }
10128
+ } catch (traceErr) {
10129
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for callConfig (non-blocking): ${traceErr}`);
10130
+ }
10106
10131
  await LLM.streamWithTools(
10107
10132
  { sys: prompts.system, user: prompts.user },
10108
10133
  tools,
@@ -10220,6 +10245,11 @@ Analyze the error and try again with a corrected query.`;
10220
10245
  logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for schema prompt (non-blocking): ${traceErr}`);
10221
10246
  }
10222
10247
  const databaseRules = await promptLoader.loadDatabaseRulesForType(sourceType);
10248
+ try {
10249
+ if (this.traceSchemaEntry) this.traceSchemaEntry.databaseRulesText = databaseRules;
10250
+ } catch (traceErr) {
10251
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for databaseRulesText (non-blocking): ${traceErr}`);
10252
+ }
10223
10253
  const rowLimitSyntax = {
10224
10254
  "mssql": `Use SELECT TOP ${this.config.maxRowsFetched} in every SELECT statement`,
10225
10255
  "postgres": `Add LIMIT ${this.config.maxRowsFetched} at the end of every query`,
@@ -10231,6 +10261,11 @@ Analyze the error and try again with a corrected query.`;
10231
10261
  "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)`
10232
10262
  };
10233
10263
  const rowLimitInstruction = rowLimitSyntax[sourceType] || `Limit results to ${this.config.maxRowsFetched} rows`;
10264
+ try {
10265
+ if (this.traceSchemaEntry) this.traceSchemaEntry.rowLimitSyntaxText = rowLimitInstruction;
10266
+ } catch (traceErr) {
10267
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for rowLimitSyntaxText (non-blocking): ${traceErr}`);
10268
+ }
10234
10269
  const hasSchemaSearch = !this.options.skipSchemaSearch && !!this.tool.schemaSearchFn;
10235
10270
  const schemaTier = this.tool.schemaTier || "";
10236
10271
  let schemaSearchInstructions = "";
@@ -10264,7 +10299,18 @@ This source has a large schema. The top tables are shown in detail above, but no
10264
10299
  Even if a table appears in the detailed schema above, search_schema returns sample values that help you write correct WHERE filters.
10265
10300
  **Never skip the search step \u2014 it prevents failed queries and retries.**`;
10266
10301
  }
10302
+ try {
10303
+ if (this.traceSchemaEntry) this.traceSchemaEntry.schemaSearchInstructionsText = schemaSearchInstructions;
10304
+ } catch (traceErr) {
10305
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for schemaSearchInstructionsText (non-blocking): ${traceErr}`);
10306
+ }
10267
10307
  const displaySourceType = sourceType === "excel" || sourceType === "csv" ? `${sourceType} \u2014 uses DuckDB SQL engine` : sourceType;
10308
+ const userAccessContextText = this.config.userAccessContext || "No user-specific access restrictions.";
10309
+ try {
10310
+ if (this.traceSchemaEntry) this.traceSchemaEntry.userAccessContextText = userAccessContextText;
10311
+ } catch (traceErr) {
10312
+ logger.warn(`[SourceAgent:${this.tool.name}] Trace capture failed for userAccessContextText (non-blocking): ${traceErr}`);
10313
+ }
10268
10314
  const prompts = await promptLoader.loadPrompts("agent-source-query", {
10269
10315
  SOURCE_NAME: sourceName,
10270
10316
  SOURCE_TYPE: displaySourceType,
@@ -10282,7 +10328,7 @@ Even if a table appears in the detailed schema above, search_schema returns samp
10282
10328
  GLOBAL_KNOWLEDGE_BASE: this.config.globalKnowledgeBase || "No global knowledge base available.",
10283
10329
  CURRENT_DATETIME: getCurrentDateTimeForPrompt(),
10284
10330
  KNOWLEDGE_BASE_CONTEXT: this.config.knowledgeBaseContext || "No additional knowledge base context available.",
10285
- USER_ACCESS_CONTEXT: this.config.userAccessContext || "No user-specific access restrictions.",
10331
+ USER_ACCESS_CONTEXT: userAccessContextText,
10286
10332
  INTENT: intent
10287
10333
  });
10288
10334
  return { system: prompts.system, user: prompts.user };
@@ -11480,7 +11526,7 @@ var WRITE_ANALYSIS_TOOL_DEF = {
11480
11526
  required: ["analysisBody"]
11481
11527
  }
11482
11528
  };
11483
- var MAX_SCRIPT_ATTEMPTS = 3;
11529
+ var MAX_SCRIPT_ATTEMPTS = 8;
11484
11530
  var MAX_ANALYSIS_ATTEMPTS = 3;
11485
11531
  var MainAgent = class {
11486
11532
  constructor(externalTools, config2, scriptStore, turnId, streamBuffer, workflows = [], forkMode = false, editContext, componentCatalog = [], displayPreference) {
@@ -11596,6 +11642,16 @@ var MainAgent = class {
11596
11642
  } catch (traceErr) {
11597
11643
  logger.warn(`[MainAgent] Trace capture failed for entity catalog (non-blocking): ${traceErr}`);
11598
11644
  }
11645
+ try {
11646
+ if (this.config.trace) this.config.trace.concepts.catalogText = conceptCatalog.text ?? "";
11647
+ } catch (traceErr) {
11648
+ logger.warn(`[MainAgent] Trace capture failed for concept catalog (non-blocking): ${traceErr}`);
11649
+ }
11650
+ try {
11651
+ if (this.config.trace) this.config.trace.concepts.invariantsText = conceptInvariants.text ?? "";
11652
+ } catch (traceErr) {
11653
+ logger.warn(`[MainAgent] Trace capture failed for concept invariants (non-blocking): ${traceErr}`);
11654
+ }
11599
11655
  const systemPrompt = await this.buildSystemPrompt(
11600
11656
  summaries,
11601
11657
  directTools,
@@ -11621,9 +11677,15 @@ var MainAgent = class {
11621
11677
  // flow falls back to generateScriptComponents exactly as before.
11622
11678
  ...this.scriptingEnabled && this.componentCatalog.length > 0 ? [this.buildWriteComponentsToolDef()] : []
11623
11679
  ];
11680
+ try {
11681
+ if (this.config.trace) this.config.trace.toolsSent = tools;
11682
+ } catch (traceErr) {
11683
+ logger.warn(`[MainAgent] Trace capture failed for tools sent (non-blocking): ${traceErr}`);
11684
+ }
11624
11685
  const sourceResults = [];
11625
11686
  const executedTools = [];
11626
11687
  let sourceCallCounter = 0;
11688
+ const toolIdCallCounts = {};
11627
11689
  let selectedWorkflow;
11628
11690
  const toolHandler = async (toolName, toolInput) => {
11629
11691
  const workflow = this.workflows.find((w) => w.id === toolName);
@@ -11701,6 +11763,17 @@ var MainAgent = class {
11701
11763
  ...sourceInput,
11702
11764
  intent: sourceInput.intent + entityBlock + conceptBlock
11703
11765
  });
11766
+ const callNumber = toolIdCallCounts[externalTool.id] = (toolIdCallCounts[externalTool.id] ?? 0) + 1;
11767
+ if (callNumber > 1) {
11768
+ const suffix = `#${callNumber}`;
11769
+ result.sourceId = `${result.sourceId}${suffix}`;
11770
+ if (result.executedTool) {
11771
+ result.executedTool = { ...result.executedTool, id: `${result.executedTool.id}${suffix}` };
11772
+ }
11773
+ if (result.allExecutedTools && result.allExecutedTools.length > 0) {
11774
+ result.allExecutedTools = result.allExecutedTools.map((t) => ({ ...t, id: `${t.id}${suffix}` }));
11775
+ }
11776
+ }
11704
11777
  sourceResults.push(result);
11705
11778
  if (result.success) {
11706
11779
  if (result.allExecutedTools && result.allExecutedTools.length > 0) {
@@ -11715,6 +11788,7 @@ var MainAgent = class {
11715
11788
  if (entry) {
11716
11789
  entry.result = formatted;
11717
11790
  if (this.resolvedConcepts.length) entry.resolvedConcepts = [...this.resolvedConcepts];
11791
+ entry.aggregation = sourceInput.aggregation;
11718
11792
  }
11719
11793
  } catch (traceErr) {
11720
11794
  logger.warn(`[MainAgent] Trace capture failed for source result (non-blocking): ${traceErr}`);
@@ -11722,6 +11796,7 @@ var MainAgent = class {
11722
11796
  return formatted;
11723
11797
  };
11724
11798
  let text = "";
11799
+ const firstIterationToolChoice = entitySearchActive ? { type: "tool", name: "resolve_entities" } : (this.forkMode || this.editMode) && this.scriptingEnabled ? { type: "any" } : void 0;
11725
11800
  try {
11726
11801
  text = await LLM.streamWithTools(
11727
11802
  {
@@ -11740,14 +11815,7 @@ var MainAgent = class {
11740
11815
  apiKey: apiKey || this.config.apiKey,
11741
11816
  partial: streamCallback,
11742
11817
  signal,
11743
- // PIN resolve_entities to iteration 1 in EVERY mode — edit and fork
11744
- // included. An optional tool reproduces the bug it exists to fix (the
11745
- // agent skipped resolution and hand-wrote `LIKE '%FDC%'`), and an edit
11746
- // like "same thing for Premier Energies" needs resolution just as much
11747
- // as a fresh ask does. It also satisfies what fork/edit used `any` for —
11748
- // a tool call on iteration 1 so the model cannot stop at a bare "I'll
11749
- // adapt…" preamble; iterations 2+ revert to auto so write_script follows.
11750
- ...entitySearchActive ? { firstIterationToolChoice: { type: "tool", name: "resolve_entities" } } : (this.forkMode || this.editMode) && this.scriptingEnabled ? { firstIterationToolChoice: { type: "any" } } : {}
11818
+ ...firstIterationToolChoice ? { firstIterationToolChoice } : {}
11751
11819
  },
11752
11820
  this.config.maxIterations
11753
11821
  );
@@ -11901,6 +11969,11 @@ ${catalog}`,
11901
11969
  async handleWriteComponents(input) {
11902
11970
  const body = String(input?.componentsBody || "").trim();
11903
11971
  if (!body) return "write_components needs `componentsBody`.";
11972
+ try {
11973
+ if (this.config.trace) this.config.trace.writeComponentsBody = body;
11974
+ } catch (traceErr) {
11975
+ logger.warn(`[MainAgent] Trace capture failed for write_components body (non-blocking): ${traceErr}`);
11976
+ }
11904
11977
  const result = this.scriptState.lastSuccessfulResult;
11905
11978
  if (!result) {
11906
11979
  return "write_components requires data: run write_script then execute_script successfully first.";
@@ -11987,6 +12060,11 @@ Now write your answer for the user. Do not restate the component list.`;
11987
12060
  async handleWriteAnalysis(input) {
11988
12061
  const body = String(input?.analysisBody || "").trim();
11989
12062
  if (!body) return "write_analysis needs `analysisBody`.";
12063
+ try {
12064
+ if (this.config.trace) this.config.trace.writeAnalysisBody = body;
12065
+ } catch (traceErr) {
12066
+ logger.warn(`[MainAgent] Trace capture failed for write_analysis body (non-blocking): ${traceErr}`);
12067
+ }
11990
12068
  const verified = this.scriptState.lastSuccessfulResult;
11991
12069
  if (!verified) {
11992
12070
  return "No verified script result yet \u2014 call write_script then execute_script first, so the analysis is written against real data.";
@@ -12491,7 +12569,6 @@ ${r.body}`).join("\n\n");
12491
12569
  * whole answer down.
12492
12570
  */
12493
12571
  async handleResolveConcepts(toolInput) {
12494
- var _a;
12495
12572
  const fn = this.config.collections?.["concepts"]?.["resolve"];
12496
12573
  const names = Array.isArray(toolInput?.names) ? toolInput.names.filter(Boolean) : [];
12497
12574
  if (!fn) {
@@ -12530,8 +12607,16 @@ ${r.body}`).join("\n\n");
12530
12607
  };
12531
12608
  try {
12532
12609
  if (this.config.trace) {
12533
- (_a = this.config.trace).conceptResolution ?? (_a.conceptResolution = { calls: [] });
12534
- this.config.trace.conceptResolution.calls.push({ via: "resolve_concepts", asked: names, implied: res?.implied || [], ...seenByLLM });
12610
+ this.config.trace.concepts.calls.push({
12611
+ via: "resolve_concepts",
12612
+ asked: names,
12613
+ implied: res?.implied || [],
12614
+ returned: seenByLLM.concepts,
12615
+ ...corrected.length ? { corrected } : {},
12616
+ ...suggestions.length ? { suggestions } : {},
12617
+ unmatched: res?.unmatched || [],
12618
+ note: notes.join(" ")
12619
+ });
12535
12620
  }
12536
12621
  } catch (traceErr) {
12537
12622
  logger.warn(`[MainAgent] Trace capture failed for resolve_concepts (non-blocking): ${traceErr}`);
@@ -12574,7 +12659,6 @@ ${r.body}`).join("\n\n");
12574
12659
  * leave the agent exactly as it was, not take the whole answer down.
12575
12660
  */
12576
12661
  async handleResolveEntities(toolInput, userPrompt) {
12577
- var _a;
12578
12662
  const fn = this.config.collections?.["entity-search"]?.["resolveEntities"];
12579
12663
  const mentions = Array.isArray(toolInput?.mentions) ? toolInput.mentions.filter((m) => m?.text) : [];
12580
12664
  const entityTypes = Array.isArray(toolInput?.entityTypes) ? toolInput.entityTypes.filter(Boolean) : [];
@@ -12583,8 +12667,7 @@ ${r.body}`).join("\n\n");
12583
12667
  if (conceptTrace) {
12584
12668
  try {
12585
12669
  if (this.config.trace) {
12586
- (_a = this.config.trace).conceptResolution ?? (_a.conceptResolution = { calls: [] });
12587
- this.config.trace.conceptResolution.calls.push({ via: "resolve_entities", ...conceptTrace });
12670
+ this.config.trace.concepts.calls.push({ via: "resolve_entities", ...conceptTrace });
12588
12671
  }
12589
12672
  } catch (traceErr) {
12590
12673
  logger.warn(`[MainAgent] Trace capture failed for concepts-in-resolve_entities (non-blocking): ${traceErr}`);
@@ -12851,6 +12934,11 @@ ${formatted}`;
12851
12934
  ${t.description || "No description"}${paramList ? "\n Parameters:\n" + paramList : ""}`;
12852
12935
  }).join("\n\n");
12853
12936
  }
12937
+ try {
12938
+ if (this.config.trace) this.config.trace.directToolsText = directToolsText;
12939
+ } catch (traceErr) {
12940
+ logger.warn(`[MainAgent] Trace capture failed for direct tools text (non-blocking): ${traceErr}`);
12941
+ }
12854
12942
  let workflowsText = "";
12855
12943
  if (workflows.length > 0) {
12856
12944
  workflowsText = workflows.map((w, idx) => {
@@ -12866,10 +12954,20 @@ ${propLines}` : ""
12866
12954
  } else {
12867
12955
  workflowsText = "No workflow components registered for this project.";
12868
12956
  }
12957
+ try {
12958
+ if (this.config.trace) this.config.trace.workflowsText = workflowsText;
12959
+ } catch (traceErr) {
12960
+ logger.warn(`[MainAgent] Trace capture failed for workflows text (non-blocking): ${traceErr}`);
12961
+ }
12869
12962
  const scriptBodyContract = await promptLoader.loadScriptBodyContract({
12870
12963
  MAX_ROWS_RENDERED: String(MAX_ROWS_RENDERED),
12871
12964
  MAX_ROWS_FETCHED: String(MAX_ROWS_FETCHED)
12872
12965
  });
12966
+ try {
12967
+ if (this.config.trace) this.config.trace.scriptBodyContractText = scriptBodyContract;
12968
+ } catch (traceErr) {
12969
+ logger.warn(`[MainAgent] Trace capture failed for script body contract text (non-blocking): ${traceErr}`);
12970
+ }
12873
12971
  const commonVars = {
12874
12972
  SOURCE_SUMMARIES: summariesText,
12875
12973
  DIRECT_TOOLS: directToolsText,
@@ -12893,6 +12991,20 @@ ${propLines}` : ""
12893
12991
  };
12894
12992
  if (this.editContext) {
12895
12993
  const ec = this.editContext;
12994
+ try {
12995
+ if (this.config.trace) {
12996
+ this.config.trace.editContext = {
12997
+ recipeId: ec.recipeId,
12998
+ parentName: ec.parentName,
12999
+ parentBody: ec.parentBody,
13000
+ instruction: ec.instruction,
13001
+ lastResultColumns: ec.lastResultColumns,
13002
+ parentParams: ec.parentParams
13003
+ };
13004
+ }
13005
+ } catch (traceErr) {
13006
+ logger.warn(`[MainAgent] Trace capture failed for edit context (non-blocking): ${traceErr}`);
13007
+ }
12896
13008
  const prompts2 = await promptLoader.loadPrompts("agent-main-edit", {
12897
13009
  ...commonVars,
12898
13010
  PARENT_SCRIPT_NAME: ec.parentName,
@@ -13167,7 +13279,9 @@ function createRunTrace() {
13167
13279
  schemaNodes: { routing: [], preResolve: [], sourceAgentSchemas: [] },
13168
13280
  script: null,
13169
13281
  scriptMatcher: null,
13170
- entityResolution: { calls: [] }
13282
+ entityResolution: { calls: [] },
13283
+ concepts: { calls: [] },
13284
+ componentGen: []
13171
13285
  };
13172
13286
  }
13173
13287
  var DEFAULT_AGENT_CONFIG = {
@@ -13179,7 +13293,7 @@ var DEFAULT_AGENT_CONFIG = {
13179
13293
  // will use the provider's default model
13180
13294
  maxRetries: 2,
13181
13295
  // 2 retries = 3 total query attempts (1 initial + 2 retries for SQL errors)
13182
- maxIterations: 20
13296
+ maxIterations: 30
13183
13297
  // schema search (2-3) + query attempts (2) + write_script/execute_script (2-3) + write_analysis (up to 3) + LLM responses + final
13184
13298
  };
13185
13299
 
@@ -14080,6 +14194,9 @@ var ScriptMatcher = class {
14080
14194
  );
14081
14195
  logger.logLLMPrompt("scriptMatcher", "system", extractPromptText(prompts.system));
14082
14196
  logger.logLLMPrompt("scriptMatcher", "user", extractPromptText(prompts.user));
14197
+ traceEntry.sent.model = model || void 0;
14198
+ traceEntry.sent.maxTokens = 500;
14199
+ traceEntry.sent.temperature = 0;
14083
14200
  const response = await LLM.stream(
14084
14201
  { sys: prompts.system, user: prompts.user },
14085
14202
  {
@@ -14649,10 +14766,20 @@ async function buildScriptComponent(comp, ctx) {
14649
14766
  return { component, spec };
14650
14767
  }
14651
14768
  async function generateScriptComponents(params) {
14652
- const { userPrompt, scriptResult, queryIds, availableComponents, apiKey, model, componentStreamCallback, analysisText, analysisSummary, signal } = params;
14769
+ const { userPrompt, scriptResult, queryIds, availableComponents, apiKey, model, componentStreamCallback, analysisText, analysisSummary, signal, trace } = params;
14770
+ const traceEntry = { via: "generateScriptComponents" };
14771
+ const pushTrace = () => {
14772
+ if (!trace) return;
14773
+ try {
14774
+ trace.componentGen.push(traceEntry);
14775
+ } catch (traceErr) {
14776
+ logger.warn(`[ScriptComponentGen] Trace capture failed for generateScriptComponents (non-blocking): ${traceErr}`);
14777
+ }
14778
+ };
14653
14779
  const queries = scriptResult.executedQueries;
14654
14780
  if (!queries || queries.length === 0) {
14655
14781
  logger.warn(`[ScriptComponentGen] No query data available \u2014 returning empty`);
14782
+ pushTrace();
14656
14783
  return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14657
14784
  }
14658
14785
  logger.info(`[ScriptComponentGen] Starting | ${queries.length} queries | ${availableComponents.length} available components`);
@@ -14670,6 +14797,7 @@ async function generateScriptComponents(params) {
14670
14797
  Keywords: ${keywords}
14671
14798
  Props Structure: ${propsPreview}`;
14672
14799
  }).join("\n\n");
14800
+ traceEntry.componentCatalog = availableCompsText;
14673
14801
  const sourceDescriptions = queries.map((q, idx) => {
14674
14802
  if (!q.data || q.data.length === 0) return null;
14675
14803
  const cols = columnsByIndex[idx];
@@ -14686,15 +14814,22 @@ async function generateScriptComponents(params) {
14686
14814
  ${sampleData}
14687
14815
  \`\`\``;
14688
14816
  }).filter(Boolean).join("\n\n");
14817
+ traceEntry.columnDescriptions = sourceDescriptions;
14689
14818
  try {
14819
+ const sourceNameValue = queries.map((q) => q.sourceName).join(", ");
14820
+ const rowCountValue = queries.map((q) => `${q.sourceName}: ${Math.min(q.count, MAX_ROWS_RENDERED)}${q.count > MAX_ROWS_RENDERED ? ` of ${q.count}` : ""}`).join(", ");
14821
+ const analysisTextValue = analysisText && analysisText.trim() ? analysisText.trim() : "No analysis text provided \u2014 infer intent from the user question and the returned data.";
14822
+ traceEntry.sourceName = sourceNameValue;
14823
+ traceEntry.rowCount = rowCountValue;
14824
+ traceEntry.analysisText = analysisTextValue;
14690
14825
  const prompts = await promptLoader.loadPrompts("script-components", {
14691
14826
  USER_PROMPT: userPrompt,
14692
14827
  AVAILABLE_COMPONENTS: availableCompsText,
14693
- SOURCE_NAME: queries.map((q) => q.sourceName).join(", "),
14694
- ROW_COUNT: queries.map((q) => `${q.sourceName}: ${Math.min(q.count, MAX_ROWS_RENDERED)}${q.count > MAX_ROWS_RENDERED ? ` of ${q.count}` : ""}`).join(", "),
14828
+ SOURCE_NAME: sourceNameValue,
14829
+ ROW_COUNT: rowCountValue,
14695
14830
  COLUMN_DESCRIPTIONS: sourceDescriptions,
14696
14831
  SAMPLE_DATA: "",
14697
- ANALYSIS_TEXT: analysisText && analysisText.trim() ? analysisText.trim() : "No analysis text provided \u2014 infer intent from the user question and the returned data."
14832
+ ANALYSIS_TEXT: analysisTextValue
14698
14833
  });
14699
14834
  const ctx = {
14700
14835
  queries,
@@ -14725,19 +14860,21 @@ ${sampleData}
14725
14860
  } : void 0;
14726
14861
  logger.logLLMPrompt("scriptComponentGen", "system", prompts.system);
14727
14862
  logger.logLLMPrompt("scriptComponentGen", "user", prompts.user);
14863
+ const callConfig = { model: model || void 0, maxTokens: 5e3, temperature: 0 };
14864
+ traceEntry.callConfig = callConfig;
14728
14865
  const response = await LLM.stream(
14729
14866
  { sys: prompts.system, user: prompts.user },
14730
14867
  {
14731
- model: model || void 0,
14732
- maxTokens: 5e3,
14733
- temperature: 0,
14868
+ ...callConfig,
14734
14869
  apiKey,
14735
14870
  partial,
14736
14871
  signal
14737
14872
  },
14738
14873
  true
14739
14874
  );
14740
- logger.logLLMPrompt("scriptComponentGen:response", "user", JSON.stringify(response, null, 2));
14875
+ const responseText = JSON.stringify(response, null, 2);
14876
+ logger.logLLMPrompt("scriptComponentGen:response", "user", responseText);
14877
+ traceEntry.rawResponse = responseText;
14741
14878
  if (!response || !response.components || !Array.isArray(response.components)) {
14742
14879
  logger.warn(`[ScriptComponentGen] LLM returned invalid response`);
14743
14880
  return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
@@ -14805,26 +14942,45 @@ ${sampleData}
14805
14942
  const msg = error instanceof Error ? error.message : String(error);
14806
14943
  logger.error(`[ScriptComponentGen] Failed: ${msg}`);
14807
14944
  return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14945
+ } finally {
14946
+ pushTrace();
14808
14947
  }
14809
14948
  }
14810
- async function summarizeToMarkdown(analysis, apiKey, model) {
14811
- if (!analysis || !analysis.trim()) return "";
14949
+ async function summarizeToMarkdown(analysis, apiKey, model, trace) {
14950
+ const traceEntry = { via: "summarizeToMarkdown", analysisText: analysis };
14951
+ const pushTrace = () => {
14952
+ if (!trace) return;
14953
+ try {
14954
+ trace.componentGen.push(traceEntry);
14955
+ } catch (traceErr) {
14956
+ logger.warn(`[ScriptComponentGen] Trace capture failed for summarizeToMarkdown (non-blocking): ${traceErr}`);
14957
+ }
14958
+ };
14959
+ if (!analysis || !analysis.trim()) {
14960
+ pushTrace();
14961
+ return "";
14962
+ }
14812
14963
  try {
14813
14964
  const prompts = await promptLoader.loadPrompts("script-component-summary", { ANALYSIS_TEXT: analysis });
14814
- const text = await LLM.text({ sys: prompts.system, user: prompts.user }, { model: model || void 0, maxTokens: 400, temperature: 0, apiKey });
14965
+ const callConfig = { model: model || void 0, maxTokens: 400, temperature: 0 };
14966
+ traceEntry.callConfig = callConfig;
14967
+ const text = await LLM.text({ sys: prompts.system, user: prompts.user }, { ...callConfig, apiKey });
14968
+ traceEntry.rawResponse = text;
14815
14969
  return (text || "").trim();
14816
14970
  } catch (err) {
14817
14971
  logger.warn(`[ScriptComponentGen] summarizeToMarkdown failed, falling back: ${err instanceof Error ? err.message : String(err)}`);
14818
14972
  return "";
14973
+ } finally {
14974
+ pushTrace();
14819
14975
  }
14820
14976
  }
14821
- async function markdownContent(analysisSummary, analysisText, apiKey, model) {
14977
+ async function markdownContent(analysisSummary, analysisText, apiKey, model, trace) {
14822
14978
  const bullets = (analysisSummary || []).map((b) => String(b).trim()).filter(Boolean);
14823
14979
  if (bullets.length) return bullets.map((b) => `- ${b}`).join("\n");
14824
- return await summarizeToMarkdown(analysisText || "", apiKey, model) || analysisText || "";
14980
+ return await summarizeToMarkdown(analysisText || "", apiKey, model, trace) || analysisText || "";
14825
14981
  }
14826
14982
  async function assembleComponentsFromSpecs(params) {
14827
- const { specs, scriptResult, queryIds, availableComponents, componentStreamCallback, analysisText, analysisSummary, apiKey, model } = params;
14983
+ const { specs, scriptResult, queryIds, availableComponents, componentStreamCallback, analysisText, analysisSummary, apiKey, model, trace } = params;
14828
14984
  if (!specs || specs.length === 0) return null;
14829
14985
  const queries = scriptResult.executedQueries || [];
14830
14986
  const byId = new Map(queries.map((q) => [q.sourceId, q]));
@@ -14850,7 +15006,7 @@ async function assembleComponentsFromSpecs(params) {
14850
15006
  return null;
14851
15007
  }
14852
15008
  if (spec.sourceRef === "markdown") {
14853
- const summary = await markdownContent(analysisSummary, analysisText, apiKey, model) || spec.content || "";
15009
+ const summary = await markdownContent(analysisSummary, analysisText, apiKey, model, trace) || spec.content || "";
14854
15010
  const md = buildMarkdown(summary, spec.title, spec.description);
14855
15011
  if (md) {
14856
15012
  out.push(md);
@@ -14906,7 +15062,7 @@ async function assembleComponentsFromSpecs(params) {
14906
15062
  }
14907
15063
  }
14908
15064
  if (out.length > 0 && !out.some((c) => c.type === "MarkdownBlock")) {
14909
- const summary = await markdownContent(analysisSummary, analysisText, apiKey, model);
15065
+ const summary = await markdownContent(analysisSummary, analysisText, apiKey, model, trace);
14910
15066
  const md = buildMarkdown(summary);
14911
15067
  if (md) {
14912
15068
  out.push(md);
@@ -14927,31 +15083,47 @@ async function authorComponentsProgram(params) {
14927
15083
  externalTools,
14928
15084
  apiKey,
14929
15085
  model,
14930
- signal
15086
+ signal,
15087
+ trace
14931
15088
  } = params;
14932
15089
  const maxAttempts = params.maxAttempts ?? 2;
14933
- const queries = scriptResult.executedQueries || [];
14934
- if (!queries.length) return null;
14935
- const datasets = {};
14936
- for (const q of queries) {
14937
- if (q.virtual && q.sourceId?.startsWith("computed:")) {
14938
- datasets[q.sourceId.slice("computed:".length)] = q.data;
15090
+ const traceEntry = { via: "authorComponentsProgram", instruction, attempts: [] };
15091
+ const pushTrace = () => {
15092
+ if (!trace) return;
15093
+ try {
15094
+ trace.componentGen.push(traceEntry);
15095
+ } catch (traceErr) {
15096
+ logger.warn(`[ComponentsEdit] Trace capture failed for authorComponentsProgram (non-blocking): ${traceErr}`);
14939
15097
  }
14940
- }
14941
- const catalog = availableComponents.map((c) => {
14942
- const cfg = c.props?.config;
14943
- return `- ${c.name} (${c.type})${c.description ? ` \u2014 ${c.description}` : ""}` + (cfg ? `
15098
+ };
15099
+ try {
15100
+ const queries = scriptResult.executedQueries || [];
15101
+ if (!queries.length) return null;
15102
+ const datasets = {};
15103
+ for (const q of queries) {
15104
+ if (q.virtual && q.sourceId?.startsWith("computed:")) {
15105
+ datasets[q.sourceId.slice("computed:".length)] = q.data;
15106
+ }
15107
+ }
15108
+ const catalog = availableComponents.map((c) => {
15109
+ const cfg = c.props?.config;
15110
+ return `- ${c.name} (${c.type})${c.description ? ` \u2014 ${c.description}` : ""}` + (cfg ? `
14944
15111
  config: ${JSON.stringify(cfg)}` : "");
14945
- }).join("\n");
14946
- const shapes = queries.map((q) => {
14947
- const cols = inferColumns(q.data);
14948
- const desc = [...cols.values()].map((c) => `${c.name}:${c.type}`).join(", ");
14949
- return `- ${q.sourceId} \u2014 ${q.count ?? q.data.length} rows [${desc}]`;
14950
- }).join("\n");
14951
- const current = stripToComponentsExport(recipe.scriptBody || "");
14952
- let feedback = "";
14953
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
14954
- const sys = `You re-author ONE function: \`getComponents(data, params, fmt, datasets)\`, which RETURNS an array of component specs { componentType, sourceRef, title, description, config }.
15112
+ }).join("\n");
15113
+ traceEntry.componentCatalog = catalog;
15114
+ const shapes = queries.map((q) => {
15115
+ const cols = inferColumns(q.data);
15116
+ const desc = [...cols.values()].map((c) => `${c.name}:${c.type}`).join(", ");
15117
+ return `- ${q.sourceId} \u2014 ${q.count ?? q.data.length} rows [${desc}]`;
15118
+ }).join("\n");
15119
+ traceEntry.datasetShapes = shapes;
15120
+ const current = stripToComponentsExport(recipe.scriptBody || "");
15121
+ traceEntry.currentBody = current;
15122
+ const callConfig = { model: model || void 0, maxTokens: 2e3, temperature: 0 };
15123
+ traceEntry.callConfig = callConfig;
15124
+ let feedback = "";
15125
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
15126
+ const sys = `You re-author ONE function: \`getComponents(data, params, fmt, datasets)\`, which RETURNS an array of component specs { componentType, sourceRef, title, description, config }.
14955
15127
 
14956
15128
  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.
14957
15129
 
@@ -14960,7 +15132,7 @@ ${shapes}
14960
15132
 
14961
15133
  ## Available components
14962
15134
  ${catalog}`;
14963
- const user = `Apply this rendering change: ${instruction}
15135
+ const user = `Apply this rendering change: ${instruction}
14964
15136
 
14965
15137
  ` + (current ? `Current getComponents:
14966
15138
  \`\`\`js
@@ -14968,57 +15140,64 @@ ${current}
14968
15140
  \`\`\`
14969
15141
 
14970
15142
  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.";
14971
- let body;
14972
- try {
14973
- body = await LLM.stream({ sys, user }, { model, maxTokens: 2e3, temperature: 0, apiKey, signal });
14974
- } catch (err) {
14975
- logger.warn(`[ComponentsEdit] LLM call failed: ${err instanceof Error ? err.message : err}`);
14976
- return null;
14977
- }
14978
- body = body.replace(/^[\s\S]*?```(?:js|javascript|ts|typescript)?\n/, "").replace(/```[\s\S]*$/, "").trim();
14979
- if (!/export\s+(?:async\s+)?function\s+getComponents\b/.test(body)) {
14980
- feedback = `
15143
+ const feedbackThisAttempt = feedback;
15144
+ let body;
15145
+ try {
15146
+ body = await LLM.stream({ sys, user }, { ...callConfig, apiKey, signal });
15147
+ } catch (err) {
15148
+ logger.warn(`[ComponentsEdit] LLM call failed: ${err instanceof Error ? err.message : err}`);
15149
+ traceEntry.attempts.push({ feedback: feedbackThisAttempt });
15150
+ return null;
15151
+ }
15152
+ traceEntry.attempts.push({ feedback: feedbackThisAttempt, rawResponse: body });
15153
+ traceEntry.rawResponse = body;
15154
+ body = body.replace(/^[\s\S]*?```(?:js|javascript|ts|typescript)?\n/, "").replace(/```[\s\S]*$/, "").trim();
15155
+ if (!/export\s+(?:async\s+)?function\s+getComponents\b/.test(body)) {
15156
+ feedback = `
14981
15157
 
14982
15158
  Your previous reply did not contain \`export function getComponents\`.`;
14983
- continue;
14984
- }
14985
- if (!await scriptStore.attachComponents(recipe.id, body)) return null;
14986
- const { components, componentsError } = await runComponentsOnly(
14987
- recipe,
14988
- scriptStore.getScriptPath(recipe),
14989
- {},
14990
- scriptResult.data,
14991
- { externalTools, signal },
14992
- datasets
14993
- );
14994
- if (componentsError || !components?.length) {
14995
- feedback = `
15159
+ continue;
15160
+ }
15161
+ if (!await scriptStore.attachComponents(recipe.id, body)) return null;
15162
+ const { components, componentsError } = await runComponentsOnly(
15163
+ recipe,
15164
+ scriptStore.getScriptPath(recipe),
15165
+ {},
15166
+ scriptResult.data,
15167
+ { externalTools, signal },
15168
+ datasets
15169
+ );
15170
+ if (componentsError || !components?.length) {
15171
+ feedback = `
14996
15172
 
14997
15173
  Your previous getComponents failed: ${componentsError || "it returned no components"}`;
14998
- continue;
14999
- }
15000
- const availableSourceRefs = queries.map((q) => q.sourceId);
15001
- const findings = [];
15002
- for (const spec of components) {
15003
- const q = queries.find((x) => x.sourceId === spec.sourceRef);
15004
- const rows = q?.data || [];
15005
- findings.push(...validateComponentSpec(
15006
- { ...spec, config: spec.config || {} },
15007
- { cols: inferColumns(rows), rowCount: rows.length, rows, availableSourceRefs }
15008
- ).filter((f) => f.severity === "error"));
15009
- }
15010
- if (findings.length) {
15011
- logger.warn(`[ComponentsEdit] attempt ${attempt} rejected: ${findings.length} finding(s)`);
15012
- feedback = `
15174
+ continue;
15175
+ }
15176
+ const availableSourceRefs = queries.map((q) => q.sourceId);
15177
+ const findings = [];
15178
+ for (const spec of components) {
15179
+ const q = queries.find((x) => x.sourceId === spec.sourceRef);
15180
+ const rows = q?.data || [];
15181
+ findings.push(...validateComponentSpec(
15182
+ { ...spec, config: spec.config || {} },
15183
+ { cols: inferColumns(rows), rowCount: rows.length, rows, availableSourceRefs }
15184
+ ).filter((f) => f.severity === "error"));
15185
+ }
15186
+ if (findings.length) {
15187
+ logger.warn(`[ComponentsEdit] attempt ${attempt} rejected: ${findings.length} finding(s)`);
15188
+ feedback = `
15013
15189
 
15014
15190
  ${formatFindingsForAgent(findings)}`;
15015
- continue;
15191
+ continue;
15192
+ }
15193
+ logger.info(`[ComponentsEdit] Re-authored getComponents for "${recipe.name}" (${components.length} component(s), attempt ${attempt})`);
15194
+ return components;
15016
15195
  }
15017
- logger.info(`[ComponentsEdit] Re-authored getComponents for "${recipe.name}" (${components.length} component(s), attempt ${attempt})`);
15018
- return components;
15196
+ logger.warn(`[ComponentsEdit] Gave up after ${maxAttempts} attempts \u2014 falling back to spec generation`);
15197
+ return null;
15198
+ } finally {
15199
+ pushTrace();
15019
15200
  }
15020
- logger.warn(`[ComponentsEdit] Gave up after ${maxAttempts} attempts \u2014 falling back to spec generation`);
15021
- return null;
15022
15201
  }
15023
15202
  function stripToComponentsExport(body) {
15024
15203
  const m = body.search(/export\s+(?:async\s+)?function\s+getComponents\b/);
@@ -17485,7 +17664,8 @@ ${JSON.stringify(preview, null, 2)}
17485
17664
  analysisText: scriptTextResponse,
17486
17665
  analysisSummary: scriptResult?.analysis?.summary,
17487
17666
  apiKey,
17488
- model: sourceAgentModel
17667
+ model: sourceAgentModel,
17668
+ trace: runTrace
17489
17669
  });
17490
17670
  if (assembled && assembled.length > 0) {
17491
17671
  matchedComponents2 = assembled;
@@ -17503,7 +17683,8 @@ ${JSON.stringify(preview, null, 2)}
17503
17683
  externalTools: agentTools,
17504
17684
  apiKey,
17505
17685
  model: sourceAgentModel,
17506
- signal
17686
+ signal,
17687
+ trace: runTrace
17507
17688
  });
17508
17689
  if (reauthored?.length) {
17509
17690
  const assembled = await assembleComponentsFromSpecs({
@@ -17515,7 +17696,8 @@ ${JSON.stringify(preview, null, 2)}
17515
17696
  analysisText: scriptTextResponse,
17516
17697
  analysisSummary: scriptResult?.analysis?.summary,
17517
17698
  apiKey,
17518
- model: sourceAgentModel
17699
+ model: sourceAgentModel,
17700
+ trace: runTrace
17519
17701
  });
17520
17702
  if (assembled?.length) {
17521
17703
  matchedComponents2 = assembled;
@@ -17556,7 +17738,8 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17556
17738
  collections,
17557
17739
  analysisText: scriptTextResponse,
17558
17740
  analysisSummary: scriptResult?.analysis?.summary,
17559
- signal
17741
+ signal,
17742
+ trace: runTrace
17560
17743
  });
17561
17744
  if (compResult.components.length > 0) {
17562
17745
  matchedComponents2 = compResult.components;
@@ -17696,6 +17879,18 @@ User question: ${prompt}
17696
17879
  ---
17697
17880
 
17698
17881
  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.`;
17882
+ if (runTrace) {
17883
+ try {
17884
+ runTrace.forkContext = {
17885
+ ...runTrace.forkContext || {},
17886
+ parentBody: forkContext.parentBody,
17887
+ gaps: gapsBlock,
17888
+ modificationHint: hintBlock
17889
+ };
17890
+ } catch (traceErr) {
17891
+ logger.warn(`[AgentFlow] Trace capture failed for fork-mode preamble (non-blocking): ${traceErr}`);
17892
+ }
17893
+ }
17699
17894
  }
17700
17895
  let filteredTools = agentTools;
17701
17896
  const sqlToolCount = agentTools.filter((t) => t.toolType !== "direct").length;
@@ -17921,7 +18116,8 @@ BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containin
17921
18116
  analysisText: agentResponse.text,
17922
18117
  analysisSummary: agentResponse.analysis?.summary,
17923
18118
  apiKey,
17924
- model: sourceAgentModel
18119
+ model: sourceAgentModel,
18120
+ trace: runTrace
17925
18121
  });
17926
18122
  if (assembled && assembled.length > 0) {
17927
18123
  matchedComponents = assembled;
@@ -17948,7 +18144,8 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
17948
18144
  collections,
17949
18145
  analysisText: agentResponse.text,
17950
18146
  analysisSummary: agentResponse.analysis?.summary,
17951
- signal
18147
+ signal,
18148
+ trace: runTrace
17952
18149
  };
17953
18150
  const MAX_COMP_ATTEMPTS = 3;
17954
18151
  let compResult;
@@ -18104,6 +18301,18 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18104
18301
  forkDepth: Math.min(FORK_DEPTH_CAP, forkContext.parentDepth + 1),
18105
18302
  forkReason: forkContext.modificationHint
18106
18303
  } : void 0;
18304
+ if (runTrace && forkContext && lineage) {
18305
+ try {
18306
+ runTrace.forkContext = {
18307
+ ...runTrace.forkContext || {},
18308
+ parentRecipeId: lineage.parentId,
18309
+ forkDepth: lineage.forkDepth,
18310
+ forkReason: lineage.forkReason
18311
+ };
18312
+ } catch (traceErr) {
18313
+ logger.warn(`[AgentFlow] Trace capture failed for fork lineage (non-blocking): ${traceErr}`);
18314
+ }
18315
+ }
18107
18316
  const promoted = await scriptStore.promoteToVerified(authored.recipeId, {
18108
18317
  sourceIds: authored.sourceIds,
18109
18318
  tables: authored.tables,
@@ -18296,7 +18505,7 @@ function transformUIBlockForDB(uiblock, userPrompt, uiBlockId) {
18296
18505
  };
18297
18506
  }
18298
18507
  function hasTraceContent(trace) {
18299
- 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;
18508
+ 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;
18300
18509
  }
18301
18510
  async function saveConversation(params) {
18302
18511
  const { userId, userPrompt, uiblock, uiBlockId, threadId, collections, status = "success", error: turnError, trace } = params;
@@ -26384,8 +26593,7 @@ function buildResolveEntitiesTool(sdk, trace) {
26384
26593
  if (trace) {
26385
26594
  if (entityResult) trace.entityResolution.calls.push({ mentions, ...entityResult });
26386
26595
  if (conceptResult) {
26387
- trace.conceptResolution ?? (trace.conceptResolution = { calls: [] });
26388
- trace.conceptResolution.calls.push({ via: "dashboard-agent", asked: conceptNames, ...conceptResult });
26596
+ trace.concepts.calls.push({ via: "dashboard-agent", asked: conceptNames, ...conceptResult });
26389
26597
  }
26390
26598
  }
26391
26599
  } catch (traceErr) {
@@ -26722,7 +26930,7 @@ ${fullPrompt}
26722
26930
  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.` };
26723
26931
  }
26724
26932
  }
26725
- model = { ...model, maxTokens: 8e3 };
26933
+ model = { ...model, maxTokens: 2e4 };
26726
26934
  const toolsList = sdk.getTools().map((t) => `- ${t.id}: ${t.name}`).join("\n");
26727
26935
  if (signal?.aborted) {
26728
26936
  console.log(`[DashboardAgent] Aborted during setup \u2014 skipping schema pre-resolution for dashboard ${dashboardId}`);