@superatomai/sdk-node 0.0.11-mds → 0.0.12-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/dist/index.mjs CHANGED
@@ -336,6 +336,10 @@ var ToolSchema = z3.object({
336
336
  id: z3.string(),
337
337
  name: z3.string(),
338
338
  description: z3.string(),
339
+ /** Tool type: "source" = routed through SourceAgent, "direct" = called directly by MainAgent */
340
+ toolType: z3.enum(["source", "direct"]).optional(),
341
+ /** Full untruncated schema for source agent (all columns visible) */
342
+ fullSchema: z3.string().optional(),
339
343
  params: z3.record(z3.string()),
340
344
  fn: z3.function().args(z3.any()).returns(z3.any()),
341
345
  outputSchema: OutputSchema.optional()
@@ -7121,28 +7125,35 @@ var MainAgent = class {
7121
7125
  * Handle a user question using the multi-agent system.
7122
7126
  *
7123
7127
  * This is ONE LLM.streamWithTools() call. The LLM:
7124
- * 1. Sees source summaries in system prompt (~100 tokens each)
7125
- * 2. Decides which source(s) to query (routing)
7126
- * 3. Calls source tools → SourceAgent runs independently → returns data
7127
- * 4. Sees data, decides if it needs more calls tools again if needed
7128
+ * 1. Sees source summaries + direct tool descriptions in system prompt
7129
+ * 2. Decides which tool(s) to call (routing)
7130
+ * 3. Source tools → SourceAgent runs independently → returns data
7131
+ * 4. Direct tools fn() called directly with LLM params returns data
7128
7132
  * 5. Generates final analysis text
7129
7133
  */
7130
7134
  async handleQuestion(userPrompt, apiKey, conversationHistory, streamCallback) {
7131
7135
  const startTime = Date.now();
7132
7136
  logger.info(`[MainAgent] Starting | prompt: "${userPrompt.substring(0, 50)}..."`);
7133
- const summaries = buildSourceSummaries(this.externalTools);
7134
- logger.info(`[MainAgent] ${summaries.length} source(s) available`);
7135
- const systemPrompt = await this.buildSystemPrompt(summaries, conversationHistory);
7137
+ const sourceTools = this.externalTools.filter((t) => t.toolType !== "direct");
7138
+ const directTools = this.externalTools.filter((t) => t.toolType === "direct");
7139
+ logger.info(`[MainAgent] ${sourceTools.length} source tool(s), ${directTools.length} direct tool(s)`);
7140
+ const summaries = buildSourceSummaries(sourceTools);
7141
+ const systemPrompt = await this.buildSystemPrompt(summaries, directTools, conversationHistory);
7136
7142
  logger.logLLMPrompt("mainAgent", "system", extractPromptText(systemPrompt));
7137
7143
  logger.logLLMPrompt("mainAgent", "user", userPrompt);
7138
- const tools = this.buildSourceToolDefinitions(summaries);
7144
+ const sourceToolDefs = this.buildSourceToolDefinitions(summaries);
7145
+ const directToolDefs = this.buildDirectToolDefinitions(directTools);
7146
+ const tools = [...sourceToolDefs, ...directToolDefs];
7139
7147
  const sourceResults = [];
7140
7148
  const executedTools = [];
7141
7149
  const toolHandler = async (toolName, toolInput) => {
7142
7150
  const externalTool = this.externalTools.find((t) => t.id === toolName);
7143
7151
  if (!externalTool) {
7144
7152
  logger.error(`[MainAgent] Unknown tool called: ${toolName}`);
7145
- return `Error: Unknown data source "${toolName}"`;
7153
+ return `Error: Unknown tool "${toolName}"`;
7154
+ }
7155
+ if (externalTool.toolType === "direct") {
7156
+ return this.handleDirectTool(externalTool, toolInput, executedTools);
7146
7157
  }
7147
7158
  const sourceInput = {
7148
7159
  intent: toolInput.intent || toolInput.query || JSON.stringify(toolInput),
@@ -7182,17 +7193,93 @@ var MainAgent = class {
7182
7193
  };
7183
7194
  }
7184
7195
  // ============================================
7196
+ // Direct Tool Execution
7197
+ // ============================================
7198
+ /**
7199
+ * Execute a direct tool — call fn() with LLM-provided params, no SourceAgent.
7200
+ */
7201
+ async handleDirectTool(tool, toolInput, executedTools) {
7202
+ const startTime = Date.now();
7203
+ logger.info(`[MainAgent] Executing direct tool "${tool.name}" | params: ${JSON.stringify(toolInput).substring(0, 200)}`);
7204
+ if (this.streamBuffer.hasCallback()) {
7205
+ this.streamBuffer.write(`
7206
+
7207
+ \u{1F527} **Running ${tool.name}...**
7208
+
7209
+ `);
7210
+ await streamDelay();
7211
+ }
7212
+ try {
7213
+ const result = await tool.fn(toolInput);
7214
+ const executionTimeMs = Date.now() - startTime;
7215
+ if (result && result.error) {
7216
+ const errorMsg = typeof result.error === "string" ? result.error : JSON.stringify(result.error);
7217
+ logger.warn(`[MainAgent] Direct tool "${tool.name}" returned error: ${errorMsg}`);
7218
+ return `\u274C Tool "${tool.name}" error: ${errorMsg}`;
7219
+ }
7220
+ const resultData = result.data || result;
7221
+ const rowCount = Array.isArray(resultData) ? resultData.length : 1;
7222
+ if (this.streamBuffer.hasCallback()) {
7223
+ this.streamBuffer.write(`\u2705 **${tool.name}** completed (${rowCount} results, ${executionTimeMs}ms)
7224
+
7225
+ `);
7226
+ }
7227
+ const formattedResult = formatToolResultForLLM(result, {
7228
+ toolName: tool.name,
7229
+ maxRows: 5,
7230
+ maxCharsPerField: 200
7231
+ });
7232
+ executedTools.push({
7233
+ id: tool.id,
7234
+ name: tool.name,
7235
+ params: toolInput,
7236
+ result: {
7237
+ _totalRecords: result.totalItems || result.count || rowCount,
7238
+ _recordsShown: rowCount,
7239
+ _metadata: result.metadata,
7240
+ _sampleData: Array.isArray(resultData) ? resultData.slice(0, 3) : [resultData]
7241
+ },
7242
+ outputSchema: tool.outputSchema
7243
+ });
7244
+ const formatted = typeof formattedResult === "string" ? formattedResult : JSON.stringify(formattedResult);
7245
+ return `\u2705 Tool "${tool.name}" executed successfully. ${rowCount} results returned.
7246
+
7247
+ ${formatted}`;
7248
+ } catch (error) {
7249
+ const executionTimeMs = Date.now() - startTime;
7250
+ const errorMsg = error instanceof Error ? error.message : String(error);
7251
+ logger.error(`[MainAgent] Direct tool "${tool.name}" failed in ${executionTimeMs}ms: ${errorMsg}`);
7252
+ if (this.streamBuffer.hasCallback()) {
7253
+ this.streamBuffer.write(`
7254
+
7255
+ \u274C **${tool.name} failed:** ${errorMsg}
7256
+
7257
+ `);
7258
+ }
7259
+ return `\u274C Tool "${tool.name}" failed: ${errorMsg}`;
7260
+ }
7261
+ }
7262
+ // ============================================
7185
7263
  // System Prompt
7186
7264
  // ============================================
7187
7265
  /**
7188
- * Build the main agent's system prompt with source summaries.
7189
- * Loads from prompt loader (file system → hardcoded fallback in prompts.ts).
7266
+ * Build the main agent's system prompt with source summaries and direct tool descriptions.
7190
7267
  */
7191
- async buildSystemPrompt(summaries, conversationHistory) {
7268
+ async buildSystemPrompt(summaries, directTools, conversationHistory) {
7192
7269
  const summariesText = formatSummariesForPrompt(summaries);
7193
7270
  const maxSourceCalls = Math.max(2, this.config.maxIterations - 2);
7271
+ let directToolsText = "";
7272
+ if (directTools.length > 0) {
7273
+ directToolsText = directTools.map((t, idx) => {
7274
+ const params = t.params || {};
7275
+ const paramList = Object.entries(params).map(([k, v]) => ` - ${k}: ${v}`).join("\n");
7276
+ return `${idx + 1}. **${t.name}** (tool: ${t.id})
7277
+ ${t.description || "No description"}${paramList ? "\n Parameters:\n" + paramList : ""}`;
7278
+ }).join("\n\n");
7279
+ }
7194
7280
  const prompts = await promptLoader.loadPrompts("agent-main", {
7195
7281
  SOURCE_SUMMARIES: summariesText,
7282
+ DIRECT_TOOLS: directToolsText,
7196
7283
  MAX_ROWS: String(this.config.maxRowsPerSource),
7197
7284
  MAX_SOURCE_CALLS: String(maxSourceCalls),
7198
7285
  GLOBAL_KNOWLEDGE_BASE: this.config.globalKnowledgeBase || "No global knowledge base available.",
@@ -7203,11 +7290,10 @@ var MainAgent = class {
7203
7290
  return prompts.system;
7204
7291
  }
7205
7292
  // ============================================
7206
- // Tool Definitions (summary-only, no full schema)
7293
+ // Tool Definitions
7207
7294
  // ============================================
7208
7295
  /**
7209
- * Build tool definitions for the main agent one per source.
7210
- * Descriptions include entity names with column names for routing.
7296
+ * Build tool definitions for source toolssummary-only descriptions.
7211
7297
  * The full schema is inside the SourceAgent which runs independently.
7212
7298
  */
7213
7299
  buildSourceToolDefinitions(summaries) {
@@ -7239,14 +7325,51 @@ var MainAgent = class {
7239
7325
  };
7240
7326
  });
7241
7327
  }
7328
+ /**
7329
+ * Build tool definitions for direct tools — expose their actual params.
7330
+ * These are called directly by the main agent LLM, no SourceAgent.
7331
+ */
7332
+ buildDirectToolDefinitions(directTools) {
7333
+ return directTools.map((tool) => {
7334
+ const properties = {};
7335
+ const required = [];
7336
+ const toolParams = tool.params || {};
7337
+ Object.entries(toolParams).forEach(([key, typeOrValue]) => {
7338
+ const valueStr = String(typeOrValue).toLowerCase();
7339
+ let schemaType = "string";
7340
+ const typeMatch = valueStr.match(/^(string|number|integer|boolean|array|object)\b/);
7341
+ if (typeMatch) {
7342
+ schemaType = typeMatch[1];
7343
+ }
7344
+ const isOptional = valueStr.includes("(optional)") || valueStr.includes("optional");
7345
+ const description = typeof typeOrValue === "string" ? typeOrValue : `Parameter: ${key}`;
7346
+ if (schemaType === "array") {
7347
+ properties[key] = { type: "array", items: { type: "string" }, description };
7348
+ } else if (schemaType === "object") {
7349
+ properties[key] = { type: "object", description };
7350
+ } else {
7351
+ properties[key] = { type: schemaType, description };
7352
+ }
7353
+ if (!isOptional) {
7354
+ required.push(key);
7355
+ }
7356
+ });
7357
+ return {
7358
+ name: tool.id,
7359
+ description: tool.description || `Call ${tool.name}`,
7360
+ input_schema: {
7361
+ type: "object",
7362
+ properties,
7363
+ required: required.length > 0 ? required : void 0
7364
+ }
7365
+ };
7366
+ });
7367
+ }
7242
7368
  // ============================================
7243
7369
  // Format Result for Main Agent
7244
7370
  // ============================================
7245
7371
  /**
7246
7372
  * Format a source agent's result as a clean string for the main agent LLM.
7247
- * Passes through the data as-is — no server-side aggregation.
7248
- * If the main agent needs aggregates, it should request aggregation: "pre-aggregate"
7249
- * from the source agent, which handles it at the query level (SQL GROUP BY, etc.).
7250
7373
  */
7251
7374
  formatResultForMainAgent(result) {
7252
7375
  if (!result.success) {
@@ -9912,6 +10035,7 @@ var get_agent_user_response = async (prompt, components, anthropicApiKey, groqAp
9912
10035
  id: t.id,
9913
10036
  name: t.name,
9914
10037
  description: t.description,
10038
+ toolType: t.toolType,
9915
10039
  fullSchema: t.fullSchema,
9916
10040
  fn: t.fn,
9917
10041
  limit: t.limit,