import { z } from "zod";
import { compareSemVer, } from "@superblocksteam/shared";
import { selectExamplesByTags, formatSelectedExamples, } from "../../subagents/apis/example-selector.js";
import { POSITIVE_EXAMPLES, } from "../../subagents/apis/examples.js";
import { createToolFactory, ToolCategory } from "../../tools2/types.js";
import { getIntegrationTypeDefinition, getSdkDeclarationName, } from "./integration-types.js";
/**
 * Core type definitions - control flow and base types only
 * Integration-specific types are provided by getIntegrationTypeDefinition
 *
 * @remarks Exported for testing purposes to validate completeness
 */
export const TYPE_DEFINITIONS = `
## Core Type Definitions

These are the core type definitions for control flow blocks and base types in Superblocks APIs:

\`\`\`typescript
// @superblocksteam/library

export type JsonValue = any;

export type State = { [key: string]: JsonValue };

export type Binding<T> = T | ((state: State) => T);

export declare abstract class Block {
  protected name: string;

  constructor(name: string);
}

export declare abstract class Integration extends Block {
  constructor(name: string, integration: string);
}

// Control Flow Blocks

export type Condition = {
  when: Binding<boolean>;
  then: Block[];
};

export type Conditions = {
  if: Condition;
  elif?: Condition[];
  else?: Block[];
};

export declare class Conditional extends Block {
  public conditions: Conditions;

  constructor(name: string, config: Conditions);
}

export declare class Loop extends Block {
  constructor(
    name: string,
    config:
      | {
          type?: "TYPE_FOREACH"; // Optional - defaults to TYPE_FOREACH
          over: Binding<JsonValue[]>;
          variables: { item: string; index: string };
          blocks: Block[];
        }
      | {
          type: "TYPE_WHILE"; // Required for TYPE_WHILE
          condition: Binding<boolean>;
          blocks: Block[];
        }
  );
  public static fromJSON(json: any, entities: string[]): Loop;
}

export declare class Parallel extends Block {
  constructor(
    name: string,
    config:
      | {
          mode: "dynamic";
          over: Binding<JsonValue[]>;
          // variables defaults to { item: "item" } - only specify if you need a different name
          blocks: Block[];
        }
      | {
          mode: "static";
          paths: Record<string, Block[]>;
        }
  );
  public static fromJSON(json: any, entities: string[]): Parallel;
}

export declare class Variables extends Block {
  constructor(
    name: string,
    variables: { key: string; value: Binding<JsonValue> }[],
  );
  public static fromJSON(json: any, entities: string[]): Variables;
}

export declare class TryCatch extends Block {
  constructor(
    name: string,
    config: {
      try: Block[];
      catch: Block[];
      finally?: Block[];
      variables: { error: string };
    },
  );
}

export declare class Throw extends Block {
  constructor(
    name: string,
    config: {
      error: Binding<JsonValue>;
    },
  );
}

export declare class Return extends Block {
  constructor(
    name: string,
    config: {
      data: Binding<JsonValue>;
    },
  );
}

export declare class Break extends Block {
  constructor(
    name: string,
    config: {
      condition: Binding<JsonValue>;
    },
  );
}

// API and Authorization

export type Authorization =
  | {
      type: "AUTHORIZATION_TYPE_APP_USERS";
    }
  | {
      type: "AUTHORIZATION_TYPE_JS_EXPRESSION";
      expression: Binding<boolean>;
    };

export declare class Api {
  constructor(name: string, blocks?: Block[], authorization?: Authorization);
}
\`\`\`

**Note:** Integration-specific type definitions (PostgreSQL, Snowflake, OpenApi, etc.) are provided when you specify \`integrationIds\` in the tool call. JavaScript and Python block definitions are included in the "Built-in Blocks" section.
`;
/**
 * Integration exploration workflow - critical for understanding integrations
 */
const INTEGRATION_EXPLORATION_WORKFLOW = `
## 🔍 Integration Exploration Workflow (CRITICAL)

When exploring integrations and data sources:

### 1. Start with metadata exploration

Use \`grepMetadata\` to understand:
- What tables/endpoints exist
- Schema structure and organization
- Available fields and data types

Query actual data (\`executeRequestToIntegration\`) only when you need:
- Specific data values for analysis
- Sample records to understand data patterns
- Actual data for application functionality

**💡 KEY PRINCIPLE:** For "tell me about the data" type questions, metadata exploration is usually sufficient and more efficient

### 2. NEVER use SQL/API queries for metadata exploration

❌ **WRONG**: \`SHOW COLUMNS FROM users\`, \`DESCRIBE table\`, \`SELECT * FROM INFORMATION_SCHEMA\`
❌ **WRONG**: API calls just to see what endpoints exist
✅ **CORRECT**: \`grepMetadata({ grepPattern: "\\\\.columns\\\\[\\\\d+\\\\]\\\\.name" })\` to find all columns (database)
✅ **CORRECT**: \`grepMetadata({ grepPattern: "\\\\.paths\\\\[\\".*repo.*\\"\\\\]" })\` for API paths with "repo" (OpenAPI)

### 3. Progressive Exploration for Large Integrations (100+ tables/endpoints)

**⚠️ Use this workflow ONLY for exploratory prompts** ("tell me about @databricks", "what data is available").
**When user mentions specific topics** ("weather app", "user orders"), search for those or similar keywords directly instead.

#### Step 1: Discover Top-Level Organization
- **Database Pattern**: \`"\\\\.dbSchema\\\\.schemas\\\\[\\\\d+\\\\]\\\\.name"\` (returns all unique schemas)
- **OpenAPI Pattern**: \`"\\\\.paths\\\\[.*\\\\]"\` (returns all API paths)
- **GraphQL Pattern**: \`"\\\\.types\\\\[\\\\d+\\\\]\\\\.name"\` (returns all GraphQL types)

#### Step 2: Explore Specific Area (User-Directed)
- **Database Pattern**:
  - \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\".*\\""\` (get all table names)
  - \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name"\` (shorter - just find table name fields)
  - **⚠️ NOT** \`"\\\\.schema\\\\.tables"\` - the field is \`dbSchema\` not \`schema\`!
- **OpenAPI Pattern**: \`"\\\\.paths\\\\[\\".*category.*\\"\\\\]"\` (paths matching category)
- **GraphQL Pattern**: \`"\\\\.types\\\\[\\\\d+\\\\]\\\\.name = \\".*User.*\\""\` (types matching pattern)

#### Step 3: Dive Into Specifics
- **Database Pattern**: \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\"exact_table\\""\` (returns full table with all columns!)
- **OpenAPI Pattern**: \`"\\\\.paths\\\\[\\"/exact/path\\"\\\\]\\\\..*"\` (all details for that endpoint)
- **GraphQL Pattern**: \`"\\\\.types\\\\[\\\\d+\\\\]\\\\.name = \\"User\\"|" + "\\\\.fields\\\\[\\\\d+\\\\]\\\\.name"\` (get fields for a type)

### 4. Critical: Different integration types use different key formats

#### DATABASE integrations (Postgres, MySQL, Snowflake, Databricks, etc.)
- **Structure**: All databases use \`json.dbSchema.schemas[]\` and \`json.dbSchema.tables[]\`
- **⚠️ CRITICAL**: It's \`dbSchema\` (NOT \`schema\`!) - the field name is \`dbSchema\`
- Use **numeric array indices**: \`[0]\`, \`[1]\`, \`[2]\`, etc.
- Pattern: Use \`\\\\d+\` to match any number
- Examples:
  - ✅ \`"\\\\.dbSchema\\\\.schemas\\\\[\\\\d+\\\\]\\\\.name"\` - Find schema names
  - ✅ \`"\\\\.tables\\\\[\\\\d+\\\\]\\\\.name = \\".*user.*\\""\` - Find tables
  - ❌ \`"\\\\.schema\\\\.tables"\` - WRONG! It's \`dbSchema\` not \`schema\`

#### OPENAPI integrations (REST APIs with OpenAPI specs)
- Use **string object keys**: \`["/users"]\`, \`["/repos"]\`
- Pattern: Use \`.*\` to match any key (NOT \`\\\\d+\`!)
- **Structure**: Path string IS the key (not a field!)
  - Format: \`json.openApiSpec.paths["/users"].get.operationId\`
- Examples:
  - ✅ \`"\\\\.paths\\\\[\\".*repos.*\\"\\\\]"\` - Find paths with "repos"
  - ✅ \`"\\\\.paths\\\\[\\"/exact/path\\"\\\\]"\` - Exact path match
  - ❌ \`"\\\\.paths\\\\[\\\\d+\\\\]"\` - WRONG! OpenAPI doesn't use numeric indices

#### GRAPHQL integrations
- **Structure**: GraphQL uses standard introspection response format at \`json.graphql.data.__schema\`
- Use **numeric array indices**: \`[0]\`, \`[1]\`, \`[2]\`, etc.
- **Two-step workflow** (recommended for large schemas):
  1. **Exploration**: Use \`includeDetails: false\` to get type with field names
  2. **Detailed lookup**: Search for 1-3 specific fields at a time

### 5. Pagination and Truncation

**Understanding \`truncated: true\`**:
- Truncation is **NORMAL and EXPECTED** for large schemas
- It means: "Here's what I found so far"

**When to paginate:**
1. User explicitly wants ALL results: "Give me ALL tables"
2. Specific search truncated AND you need more
3. User requests continuation: "Show me more"

**When NOT to paginate:**
1. Sample is sufficient for the question
2. Can refine search instead

### 6. REST API vs OpenAPI Selection

**🚨 CRITICAL: When working with REST API integrations:**
1. **ALWAYS call \`grepMetadata\` first** to determine if the REST API is OpenAPI-backed
2. **If metadata shows it's an OpenAPI-backed API, you MUST:**
   - Use the \`OpenApi\` class, NOT \`RestApi\`
   - Supply the required \`openapi.path\` property
   - Example: \`new OpenApi("api_call", "integration-id", {...}, { path: "/endpoint" })\`
3. **Only use \`RestApi\` class for non-OpenAPI REST integrations**
`;
/**
 * Block output scoping rules - critical for understanding variable access
 */
const BLOCK_OUTPUT_SCOPING_RULES = `
## Block Output Scoping Rules

**CRITICAL: Blocks can only access outputs from specific scopes based on their position in the hierarchy.**

### Scoping Hierarchy
Control flow blocks (Loop, Conditional, TryCatch) create new scopes for their children. Regular blocks (JavaScript, PostgreSQL, etc.) do not create scopes.

### What blocks CAN access:
1. **Previous sibling blocks** at the same level (executed before them)
2. **ALL ancestor block outputs** (parent, grandparent, etc. up the chain)
3. **Parent control flow variables** (e.g., \`item\` and \`index\` in Loop, \`error\` in TryCatch)
4. **Control flow block outputs** (equals the output of their last child block)

### What blocks CANNOT access:
- ❌ Outputs from blocks nested inside other control flow blocks
- ❌ Outputs from blocks in other Conditional branches
- ❌ Outputs from blocks that come after them at the same level

### Example Hierarchy:

\`\`\`typescript
// Structure: A → B(Loop) → [B1, B2, B3] → C → D

new JavaScript("A_fetch_data", { fn: () => [...] }),        // Block A

new Loop("B_process_items", {                               // Block B (control flow)
  over: ({ A_fetch_data }) => A_fetch_data.output,
  variables: { item: "current", index: "i" },
  blocks: [
    new JavaScript("B1_validate", {                         // Block B1
      fn: ({ current, i, A_fetch_data }) => {
        // ✅ Can access: current, i (loop vars), A_fetch_data
        return { valid: true };
      }
    }),
    new JavaScript("B2_transform", {                        // Block B2
      fn: ({ B1_validate, current }) => {
        // ✅ Can access: B1_validate, current, A_fetch_data
        return { transformed: current.value };
      }
    }),
    new JavaScript("B3_save", {                             // Block B3
      fn: ({ B2_transform, B1_validate }) => {
        // ✅ Can access: B2_transform, B1_validate, loop vars, A_fetch_data
        return { saved: true };
      }
    })
  ]
}),

new JavaScript("C_aggregate", {                             // Block C
  fn: ({ B_process_items, A_fetch_data }) => {
    // ✅ Can access: B_process_items.output (= B3's output), A_fetch_data
    // ❌ CANNOT access: B1_validate, B2_transform, B3_save (inside B's scope)
    return { total: B_process_items.output.length };
  }
}),

new JavaScript("D_finalize", {                              // Block D
  fn: ({ C_aggregate, B_process_items, A_fetch_data }) => {
    // ✅ Can access: C_aggregate, B_process_items, A_fetch_data
    // ❌ CANNOT access: B1_validate, B2_transform, B3_save (inside B's scope)
    return { complete: true };
  }
})
\`\`\`

### Conditional Branch Scoping:

\`\`\`typescript
new Conditional("check_user_type", {
  if: {
    when: ({ userRole }) => userRole === "admin",
    then: [
      new JavaScript("admin_process", {
        fn: () => ({ adminData: "..." })
      })
    ]
  },
  elif: [{
    when: ({ userRole }) => userRole === "user",
    then: [
      new JavaScript("user_process", {
        fn: () => ({ userData: "..." })
      })
    ]
  }]
}),

new JavaScript("next_step", {
  fn: ({ check_user_type }) => {
    // ✅ Can access: check_user_type.output (from whichever branch executed)
    // ❌ CANNOT access: admin_process or user_process directly
    return check_user_type.output;
  }
})
\`\`\`

### Variable Access Patterns

**Use destructured parameters to access Variables and block outputs:**
\`\`\`typescript
// ✅ CORRECT: Destructure the variables/blocks you need
when: ({ hasMore }) => !hasMore.value
over: ({ items }) => items.output
condition: ({ counter }) => counter.value < 10

// ✅ Multiple variables in one function
fn: ({ results, page, hasMore }) => {
  results.set([...results.value, ...newItems]);
  page.set(page.value + 1);
  hasMore.set(newItems.length > 0);
}

// ❌ WRONG: Single param pattern - 'p' is never passed, causes runtime error!
when: (p) => !p.hasMore.value  // TypeError: Cannot read properties of null
\`\`\`

**Control Block Variables:**
\`\`\`typescript
// Always use .value for Loop, TryCatch variables
new Loop("process_items", {
  type: "TYPE_FOREACH",
  over: ({ items }) => items.output,
  variables: { item: "order", index: "i" },
  blocks: [
    new JavaScript("process", {
      fn: ({ order, i }) => ({
        id: order.value.id,        // ✅ .value for loop variables
        position: i.value          // ✅ .value for index
      })
    })
  ]
})
\`\`\`

**Previous Block Outputs:**
\`\`\`typescript
// Use .output for previous block results
new JavaScript("get_data", {
  fn: () => [{ id: 1, name: "John" }, { id: 2, name: "Jane" }]
}),
new JavaScript("process_data", {
  fn: ({ get_data }) => get_data.output.length // ✅ .output
})
\`\`\`

**Inputs:**
\`\`\`typescript
// Direct access inputs - no .value needed!
new PostgreSQL("insert_user", "valid-postgres-id", {
  statement: ({ FirstName, LastName }) =>
    \`INSERT INTO users VALUES ('\${FirstName}', '\${LastName}')\`
    // ✅ FirstName and LastName are API inputs - accessed directly, no .value
})

// Compare with step outputs which DO need .output:
new JavaScript("process", {
  fn: ({ FirstName, insert_user }) => {
    // FirstName is an API input - no .value needed
    if (FirstName) { ... }  // ✅ CORRECT

    // insert_user is a step output - needs .output
    if (insert_user.output) { ... }  // ✅ CORRECT
  }
})
\`\`\`
`;
/**
 * Input discovery rules - how variables become API inputs
 */
const INPUT_DISCOVERY_RULES = `
## 🎯 API Input Discovery Rules (CRITICAL)

**IMPORTANT: You do NOT need to explicitly declare API inputs. They are automatically discovered through code analysis.**

### How Variables Become API Inputs

Variables are **implicitly discovered** as API inputs when they are:
1. **Destructured in block functions** but not defined elsewhere
2. **Referenced but not produced** by any previous block
3. **External to the API scope** (not step outputs or control flow variables)

### 🚨 CRITICAL: Always Type Your Input Parameters

**EVERY input parameter MUST have a TypeScript type annotation.**

When you reference input variables in your API code, you MUST add type annotations to the destructured parameters:

#### ✅ CORRECT - Typed parameters:
\`\`\`typescript
// Single typed parameter
new JavaScript("validate_email", {
  fn: ({ email }: { email: string }) => {
    return email.includes("@");
  }
})

// Multiple typed parameters
new PostgreSQL("search_users", "postgres-id", {
  statement: ({ searchTerm, limit }: { searchTerm: string; limit: number }) =>
    \`SELECT * FROM users WHERE name ILIKE '%\${searchTerm}%' LIMIT \${limit}\`
})

// Optional parameters with union types
new JavaScript("process_filters", {
  fn: ({ status, category }: { status?: string; category?: string | null }) => {
    const filters = [];
    if (status) filters.push(\`status = '\${status}'\`);
    if (category) filters.push(\`category = '\${category}'\`);
    return filters.join(" AND ");
  }
})
\`\`\`

#### ❌ WRONG - Untyped parameters:
\`\`\`typescript
// Missing type annotations
new JavaScript("validate_email", {
  fn: ({ email }) => {  // ❌ No type annotation!
    return email.includes("@");
  }
})

new PostgreSQL("search_users", "postgres-id", {
  statement: ({ searchTerm, limit }) =>  // ❌ No types!
    \`SELECT * FROM users WHERE name ILIKE '%\${searchTerm}%' LIMIT \${limit}\`
})
\`\`\`

#### Type Inference from Context

Use appropriate types based on the parameter's usage:
- **String fields**: \`name: string\`, \`email: string\`, \`description: string\`
- **Numeric values**: \`age: number\`, \`price: number\`, \`quantity: number\`
- **Booleans**: \`isActive: boolean\`, \`hasPermission: boolean\`
- **Optional values**: \`category?: string\`, \`userId?: number\`
- **Nullable values**: \`middleName: string | null\`, \`avatar: string | null | undefined\`
- **Arrays**: \`tags: string[]\`, \`ids: number[]\`
- **Objects**: \`user: { id: number; name: string }\`
- **Union types**: \`status: "active" | "pending" | "inactive"\`

#### Why This Matters

Typed parameters enable:
1. **Automatic type extraction** - The buildApi tool extracts these types to generate accurate input interfaces
2. **Better IDE support** - Type checking catches errors before runtime
3. **Self-documenting code** - Types show what inputs are expected
4. **Frontend integration** - Generated type definition files provide accurate TypeScript types for the frontend

**REMEMBER**: Every input parameter MUST have a type annotation. The system will automatically extract these to generate the API's input interface.

### ⚠️ CRITICAL: When to Use .value vs Direct Access

**API Inputs** - Access DIRECTLY (no .value):
\`\`\`typescript
fn: ({ statusFilter, emailFilter }) => {
  if (statusFilter) { ... }       // ✅ CORRECT - direct access
  if (statusFilter.value) { ... } // ❌ WRONG - don't use .value
}
\`\`\`

**Step Outputs** - Use .output:
\`\`\`typescript
fn: ({ previous_step }) => {
  return previous_step.output;    // ✅ CORRECT - use .output
  return previous_step;           // ❌ WRONG - missing .output
}
\`\`\`

**Loop Variables** - Use .value:
\`\`\`typescript
fn: ({ item, index }) => {        // Loop variables from Loop block
  return item.value.id;          // ✅ CORRECT - use .value
  return item.id;                // ❌ WRONG - missing .value
}
\`\`\`

**TryCatch Error Variables** - Use .value:
\`\`\`typescript
fn: ({ error }) => {              // Error variable from TryCatch
  return error.value.message;    // ✅ CORRECT - use .value
  return error.message;          // ❌ WRONG - missing .value
}
\`\`\`

### Automatic Input Detection

\`\`\`typescript
// Example: startDate and endDate automatically become API inputs
export default new Api("GetOrders", [
  new JavaScript("build_query", {
    fn: ({ startDate, endDate }) => {  // ✅ These become inputs automatically
      let query = "SELECT * FROM orders";

      if (startDate) {
        query += \` WHERE date >= '\${startDate}'\`;
      }
      if (endDate) {
        query += \` AND date <= '\${endDate}'\`;
      }

      return query;
    }
  }),

  new PostgreSQL("fetch_orders", "postgres-id", {
    statement: ({ build_query }) => build_query.output  // ❌ NOT an input (it's a block output)
  })
]);
\`\`\`

### What Does NOT Become an Input

1. **Previous block outputs** (accessed via \`.output\`):
\`\`\`typescript
new JavaScript("process", {
  fn: ({ fetch_data }) => fetch_data.output  // ❌ NOT an input - it's a block reference
})
\`\`\`

2. **Control flow variables** (accessed via \`.value\`):
\`\`\`typescript
new Loop("process_items", {
  variables: { item: "order", index: "i" },
  blocks: [
    new JavaScript("transform", {
      fn: ({ order, i }) => ({  // ❌ NOT inputs - they're loop variables
        id: order.value.id,
        position: i.value
      })
    })
  ]
})
\`\`\`

3. **Error variables in TryCatch**:
\`\`\`typescript
new TryCatch("safe_operation", {
  catch: [
    new JavaScript("handle_error", {
      fn: ({ err }) => err.value  // ❌ NOT an input - it's a catch variable
    })
  ],
  variables: { error: "err" }
})
\`\`\`

### Type Generation

When you build an API, the system automatically:
1. **Analyzes your code** to find all undefined external variables
2. **Generates TypeScript interfaces** for the inputs
3. **Creates a types.d.ts file** with the proper types

Example generated types for the GetOrders API above:
\`\`\`typescript
// Auto-generated by Superblocks
interface GetOrdersInput {
  startDate?: any;
  endDate?: any;
}

type GetOrdersResponse = any;
\`\`\`

### How APIs Are Called

Once built, APIs can be called from the frontend with the discovered inputs:

\`\`\`typescript
// In React component
const { run: runGetOrders } = useApi("GetOrders");

const response = await runGetOrders({
  startDate: "2024-01-01",
  endDate: "2024-12-31"
});

// The API returns the output of the last block directly
const orders = response || [];
\`\`\`

### Best Practices

1. **Use descriptive parameter names** that clearly indicate their purpose
2. **Don't worry about declaring inputs** - the system handles it automatically
3. **Focus on using the variables** where you need them - inputs are inferred
4. **Check the build output** to see which inputs were detected

### Common Patterns

**Filter parameters automatically become inputs:**
\`\`\`typescript
new JavaScript("build_filter", {
  fn: ({ statusFilter, userIdFilter, dateRangeFilter }) => {
    // All three filters automatically become API inputs
    const conditions = [];
    if (statusFilter) conditions.push(\`status = '\${statusFilter}'\`);
    if (userIdFilter) conditions.push(\`user_id = \${userIdFilter}\`);
    if (dateRangeFilter) conditions.push(\`date BETWEEN ...\`);
    return conditions;
  }
})
\`\`\`

**Pagination parameters:**
\`\`\`typescript
new JavaScript("paginate", {
  fn: ({ page = 1, pageSize = 20 }) => {
    // page and pageSize become optional inputs with defaults
    const offset = (page - 1) * pageSize;
    return { offset, limit: pageSize };
  }
})
\`\`\`
`;
/**
 * Common API patterns including the critical two-block dynamic SQL pattern
 */
const COMMON_API_PATTERNS = `
## 🔄 Common API Patterns

### Groups check
\`\`\`typescript
new JavaScript("check_groups", {
  fn: ({ Global }) => {
    const isFieldEngUser = Global.groups.some(group => group.name === "FieldEngineer");
    if (isFieldEngUser) {
      // Perform actions for FieldEngineer
    } else {
      // Perform actions for non-FieldEngineer
    }
  }
})
\`\`\`

### Simple Data Retrieval
\`\`\`typescript
export default new Api("getUsersApi", [
  new JavaScript("fetch_users", {
    fn: () => [
      { id: 1, name: "John Doe", email: "john@example.com" },
      { id: 2, name: "Jane Smith", email: "jane@example.com" }
    ]
  })
]);
\`\`\`

### Input Validation + Processing
\`\`\`typescript
export default new Api("createUserApi", [
  new Conditional("validate_inputs", {
    if: {
      when: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }): boolean =>
        !FirstNameInput || !EmailInput,
      then: [
        new Throw("validation_error", {
          error: "First name and email are required"
        })
      ]
    }
  }),
  new JavaScript("create_user", {
    fn: ({ FirstNameInput, EmailInput }: { FirstNameInput: string; EmailInput: string }) => ({
      id: Math.floor(Math.random() * 1000),
      name: FirstNameInput,
      email: EmailInput,
      created_at: new Date().toISOString()
    })
  })
]);
\`\`\`

### Data Processing with Loops
\`\`\`typescript
export default new Api("processOrdersApi", [
  new JavaScript("get_orders", {
    fn: () => [
      { id: 1, status: "pending", amount: 100 },
      { id: 2, status: "pending", amount: 200 }
    ]
  }),
  new Loop("process_each_order", {
    over: ({ get_orders }) => get_orders.output,
    variables: { item: "order", index: "i" },
    blocks: [
      new JavaScript("calculate_tax", {
        fn: ({ order, i }) => ({
          ...order.value,
          tax: order.value.amount * 0.1,
          total: order.value.amount * 1.1,
          position: i.value
        })
      })
    ]
  })
]);
\`\`\`

### Variables Block - Stateful Variables for APIs
Variables blocks create named variables that persist throughout API execution. Use them for:
- Tracking pagination state (cursors, page numbers, hasMore flags)
- Accumulating results across loop iterations
- Storing intermediate computation results

\`\`\`typescript
export default new Api("paginatedFetchApi", [
  // Initialize variables for pagination
  new Variables("pagination_state", [
    { key: "allResults", value: () => [] },
    { key: "cursor", value: () => null },
    { key: "hasMore", value: () => true },
  ]),

  // Fetch first page
  new RestApi("fetch_page", "rest-api-id", {
    method: "GET",
    url: ({ cursor }: { cursor: string | null }) =>
      \`https://api.example.com/items\${cursor ? \`?cursor=\${cursor}\` : ""}\`,
  }),

  // Update variables with results
  new JavaScript("update_state", {
    fn: ({ fetch_page, allResults }) => {
      const response = fetch_page.output;
      // Accumulate results
      allResults.set([...allResults.value, ...response.items]);
      // Update cursor for next page
      cursor.set(response.nextCursor);
      // Check if more pages exist
      hasMore.set(response.hasMore);
      return allResults.value;
    }
  })
]);
\`\`\`

**Variable Access Patterns:**
- \`variableName.value\` - Read the current value
- \`variableName.set(newValue)\` - Update the variable's value

**Pagination with Loop + Variables + Break:**
\`\`\`typescript
export default new Api("fetchAllPagesApi", [
  new Variables("state", [
    { key: "results", value: () => [] },
    { key: "page", value: () => 1 },
    { key: "hasMore", value: () => true },
  ]),

  // Loop until no more pages (TYPE_FOREACH with Break)
  new Loop("fetch_all_pages", {
    type: "TYPE_FOREACH",
    over: () => [...Array(100).keys()],  // Creates [0,1,2,...,99] - max iterations safety limit
    variables: { item: "_", index: "i" },
    blocks: [
      // Break if no more pages
      new Conditional("check_done", {
        if: {
          when: ({ hasMore }) => !hasMore.value,
          then: [new Break("exit_loop", { condition: () => true })]
        }
      }),

      // Fetch current page
      new RestApi("fetch_page", "rest-api-id", {
        method: "GET",
        url: ({ page }) => \`https://api.example.com/items?page=\${page.value}\`,
      }),

      // Update state
      new JavaScript("accumulate", {
        fn: ({ fetch_page, results, page, hasMore }) => {
          const response = fetch_page.output;
          results.set([...results.value, ...response.items]);
          page.set(page.value + 1);
          hasMore.set(response.items.length > 0);
          return results.value;
        }
      })
    ]
  }),

  // Return accumulated results
  new JavaScript("return_results", {
    fn: ({ results }) => results.value
  })
]);

// Alternative: TYPE_WHILE (same pattern, uses condition instead of over)
new Loop("fetch_while_more", {
  type: "TYPE_WHILE",
  condition: ({ hasMore }) => hasMore.value,  // Loop while condition is true
  blocks: [/* same fetch and accumulate blocks */]
});
\`\`\`

### Dynamic SQL with Optional Filters

Use the \`parameters\` array with the "OR NULL" pattern for optional filters:
- \`WHERE (column = $1 OR $1::type IS NULL)\` makes the condition a no-op when parameter is null
- Cast parameters to their type when checking for NULL (PostgreSQL can't infer types from NULL values)
- Always pass all parameters, using null for unused filters
- NEVER interpolate user values directly into SQL strings

### Uploading Files to S3/GCS

**Frontend wraps files in \`{ files: [...] }\` format:**
\`\`\`typescript
const response = await runUploadApi({ userFiles: { files: selectedFiles } });
\`\`\`

**Backend API - pass files directly:**
\`\`\`typescript
export default new Api("uploadFilesApi", [
  new S3("upload_files", "your-s3-integration-id", {
    action: "UPLOAD_MULTIPLE_OBJECTS",
    resource: ({ bucketName }) => bucketName,
    fileObjects: ({ userFiles }) => userFiles.files  // Direct pass-through
  })
]);
\`\`\`

The S3 plugin internally handles reading file content and conversion.

### Processing File Content in JavaScript/Python

When you need to read and process file content (parse CSV, extract text, validate, etc.):

FilePicker files are stored on the orchestrator's file server.

**Methods:**
- \`readContents(mode?)\` - Synchronous
- \`readContentsAsync(mode?)\` - Asynchronous

**Mode parameter:**
- (none) - auto-detects: returns base64 string for binary files, UTF-8 string for text
- \`'raw'\` - returns Buffer in JavaScript, bytes in Python (for direct byte access)
- \`'text'\` - returns UTF-8 string
- \`'binary'\` - returns base64 string

**JavaScript - use await directly:**
\`\`\`typescript
new JavaScript("parse_csv", {
  fn: async ({ csvFile }) => {
    const file = csvFile.files[0];
    const content = await file.readContentsAsync();
    const headers = content.split("\\n")[0].split(",").map(h => h.trim());
    return { fileName: file.name, headers };
  }
})

// Binary file - use 'raw' mode for byte access
new JavaScript("check_jpeg", {
  fn: async ({ imageFile }) => {
    const buf = await imageFile.files[0].readContentsAsync('raw'); // Buffer
    const isJPEG = buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF;
    return { isJPEG };
  }
})
\`\`\`

**Python - use sync for single file, async for parallel:**
\`\`\`python
# Single file - use sync (simpler)
content = file.readContents()
rows = content.split('\\n')

# Check file type by magic bytes
raw = file.readContents('raw')
is_pdf = raw[:4] == b'%PDF'

# Multiple files in parallel - use async
import asyncio
async def fetch_all(files):
    return await asyncio.gather(*[f.readContentsAsync() for f in files])
contents = asyncio.run(fetch_all(files))
\`\`\`
`;
/**
 * Error handling guidelines - when to use TryCatch
 */
const ERROR_HANDLING_GUIDELINES = `
## ⚠️ Error Handling: When to Use TryCatch

**IMPORTANT: Do NOT use TryCatch blocks by default. Only use them when truly necessary.**

Wrapping everything in try/catch adds unnecessary complexity that makes workflows harder to understand and debug.

### ❌ DO NOT use TryCatch for:

1. **Standard operations that should fail fast:**
\`\`\`typescript
// ❌ WRONG - Unnecessary try/catch for normal database query
new TryCatch("wrapped_query", {
  try: [
    new PostgreSQL("fetch_users", "postgres-id", {
      statement: "SELECT * FROM users LIMIT 100"
    })
  ],
  catch: [
    new JavaScript("handle_error", {
      fn: ({ err }) => ({ error: err.value })
    })
  ],
  variables: { error: "err" }
})

// ✅ CORRECT - Let the query fail naturally if there's an issue
new PostgreSQL("fetch_users", "postgres-id", {
  statement: "SELECT * FROM users LIMIT 100"
})
\`\`\`

2. **Simple data transformations:**
\`\`\`typescript
// ❌ WRONG - Wrapping basic JavaScript logic
new TryCatch("safe_transform", {
  try: [
    new JavaScript("transform_data", {
      fn: ({ userData }) => userData.output.map(u => u.name)
    })
  ],
  catch: [
    new Return("empty_array", { data: () => [] })
  ],
  variables: { error: "err" }
})

// ✅ CORRECT - Direct transformation
new JavaScript("transform_data", {
  fn: ({ userData }) => userData.output.map(u => u.name)
})
\`\`\`

### ✅ DO use TryCatch when:

1. **User explicitly requests error handling**

2. **Continuing execution after failure is business-critical:**
\`\`\`typescript
// ✅ Process must continue even if notification fails
new TryCatch("attempt_notification", {
  try: [
    new Email("send_notification", {
      from: "noreply@example.com",
      to: ({ userEmail }) => userEmail,
      subject: "Order Confirmed",
      body: "Your order has been confirmed"
    })
  ],
  catch: [
    new JavaScript("log_notification_failure", {
      fn: ({ err }) => ({
        emailFailed: true,
        error: err.value.message
      })
    })
  ],
  variables: { error: "err" }
}),
// Continue processing regardless of email success
new JavaScript("finalize_order", {
  fn: ({ orderData }) => ({ status: "complete" })
})
\`\`\`

3. **Partial failure recovery in loops:**
\`\`\`typescript
// ✅ Process all items even if some fail
new Loop("process_all_orders", {
  over: ({ orders }) => orders.output,
  variables: { item: "order", index: "i" },
  blocks: [
    new TryCatch("safe_process", {
      try: [
        new RestApi("external_validation", "rest-id", {
          method: "POST",
          url: "https://validator.example.com/check",
          body: ({ order }) => JSON.stringify(order.value)
        })
      ],
      catch: [
        new JavaScript("mark_failed", {
          fn: ({ order, err }) => ({
            orderId: order.value.id,
            failed: true,
            error: err.value
          })
        })
      ],
      variables: { error: "err" }
    })
  ]
})
\`\`\`

4. **Graceful degradation with fallback data:**
\`\`\`typescript
// ✅ Use cached data if live fetch fails
new TryCatch("fetch_with_fallback", {
  try: [
    new RestApi("fetch_live_prices", "rest-id", {
      method: "GET",
      url: "https://api.example.com/prices"
    })
  ],
  catch: [
    new PostgreSQL("fetch_cached_prices", "postgres-id", {
      statement: "SELECT * FROM cached_prices WHERE updated_at > NOW() - INTERVAL '1 hour'"
    })
  ],
  variables: { error: "err" }
})
\`\`\`

### General Rule:

**If you can't clearly articulate why the try/catch is necessary for business logic, don't use it.** Error messages are more helpful to users when they surface naturally rather than being caught and hidden.
`;
/**
 * Minimum plugin versions required for parameterized query support.
 * These versions align with VERSION_SPECIFIC_TYPE_DEFINITIONS in integration-types.ts.
 *
 * @remarks Exported for testing purposes to validate consistency with VERSION_SPECIFIC_TYPE_DEFINITIONS
 */
export const SQL_PLUGIN_MIN_VERSIONS_FOR_PARAMETERS = {
    postgres: "0.0.12",
    mysql: "0.0.12",
    mariadb: "0.0.12",
    mssql: "0.0.11",
    snowflake: "0.0.11",
    redshift: "0.0.8",
    bigquery: "0.0.8",
    athena: "0.0.2",
    databricks: "0.0.5",
    cockroachdb: "0.0.3",
    oracledb: "0.0.3",
    lakebase: "0.0.1",
    snowflakepostgres: "0.0.1",
};
/**
 * Compare two semantic version strings.
 * Returns true if version >= minVersion.
 */
function semverGte(version, minVersion) {
    return compareSemVer(version, minVersion) >= 0;
}
/**
 * Check if any SQL plugin in the organization supports parameterized queries
 * based on its execution version.
 *
 * @param pluginVersions - Map of plugin IDs to their execution versions
 * @returns true if at least one SQL plugin has a version that supports parameters
 *
 * @remarks Exported for testing purposes
 */
export function anySqlPluginSupportsParameters(pluginVersions) {
    if (!pluginVersions) {
        return false;
    }
    for (const [pluginId, minVersion] of Object.entries(SQL_PLUGIN_MIN_VERSIONS_FOR_PARAMETERS)) {
        const currentVersion = pluginVersions[pluginId];
        if (currentVersion && semverGte(currentVersion, minVersion)) {
            return true;
        }
    }
    return false;
}
/**
 * SQL best practices section - parameterized queries documentation (shown only when feature is enabled)
 */
const SQL_PARAMETERIZED_QUERIES_SECTION = `
### 🔒 SQL Security Priority
**ALWAYS prefer parameterized queries over string interpolation for user input values.**

Use \`parameters: "[var1, var2]"\` with the database-specific SQL placeholders:

| Database | Placeholder Syntax | Example |
|----------|-------------------|---------|
| PostgreSQL, Redshift, CockroachDB | \`$1\`, \`$2\`, \`$3\` | \`WHERE id = $1 AND status = $2\` |
| MySQL, MariaDB, Snowflake, BigQuery, Athena | \`?\`, \`?\`, \`?\` | \`WHERE id = ? AND status = ?\` |
| MSSQL | \`@PARAM_1\`, \`@PARAM_2\` | \`WHERE id = @PARAM_1 AND status = @PARAM_2\` |
| Databricks | \`:PARAM_1\`, \`:PARAM_2\` | \`WHERE id = :PARAM_1 AND status = :PARAM_2\` |
| OracleDB | \`:1\`, \`:2\`, \`:3\` | \`WHERE id = :1 AND status = :2\` |

Only use binding functions for truly dynamic SQL elements like table/column names.

#### Parameters syntax is different from statement syntax
**Important:** \`parameters\` is a JavaScript expression string that gets evaluated directly. Do NOT use \`\${}\` interpolation or binding functions.

\`\`\`typescript
// ❌ WRONG - Don't use \${} interpolation in parameters
parameters: "[\${build_query.output.userId}, \${searchTerm}]"

// ❌ WRONG - Don't use binding functions for parameters  
parameters: ({ build_query }) => JSON.stringify(build_query.output.params)

// ✅ CORRECT - Write expressions directly (they get evaluated as JS)
parameters: "[build_query.output.userId, searchTerm, limit]"

// ✅ CORRECT - Reference block output array directly
parameters: "build_query.output.params"
\`\`\`

This is different from \`statement\`, where binding functions with \`\${}\` ARE used to interpolate values into SQL.

`;
/**
 * Get SQL best practices section with conditional parameterized queries documentation.
 * Only includes parameterized queries guidance when:
 * 1. The feature flag is enabled, AND
 * 2. At least one SQL plugin has a version that supports parameters
 *
 * @param options - Configuration options including feature flags and plugin versions
 * @returns SQL best practices documentation string
 *
 * @remarks Exported for testing purposes
 */
export function getSqlBestPractices(options) {
    const sections = ["## 📝 SQL Best Practices\n"];
    // Only include parameterized queries section if:
    // 1. Feature flag is enabled AND
    // 2. At least one SQL plugin has a version that supports parameters
    const shouldIncludeParameters = options?.parameterizedApisEnabled === true &&
        anySqlPluginSupportsParameters(options?.pluginExecutionVersions);
    if (shouldIncludeParameters) {
        sections.push(SQL_PARAMETERIZED_QUERIES_SECTION);
    }
    sections.push(`### 1. ONE Query Per Block Rule
Each SQL block (PostgreSQL, Snowflake, MySQL, MicrosoftSql, Databricks) can execute **ONLY ONE SQL query**.

❌ **WRONG - Multiple queries in one block:**
\`\`\`sql
UPDATE users SET status = 'active';
DELETE FROM logs WHERE created < '2023-01-01';
INSERT INTO audit VALUES ('done');
\`\`\`

✅ **CORRECT - One query per block:**
\`\`\`typescript
new PostgreSQL("update_status", "postgres-id", {
  statement: "UPDATE users SET status = 'active'"
}),
new PostgreSQL("clean_logs", "postgres-id", {
  statement: "DELETE FROM logs WHERE created < '2023-01-01'"
})
\`\`\`

### 2. Sort, Don't Filter by Date (Default)
Do NOT add automatic date filters (e.g., "last 90 days") unless the user explicitly requests them. This is a common cause of unexpected empty SQL results.

✅ **Default approach:**
\`\`\`sql
SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
\`\`\`

❌ **Avoid automatic filtering:**
\`\`\`sql
SELECT * FROM orders WHERE created_at >= CURRENT_DATE - INTERVAL '90 days';  -- Can return empty results
\`\`\`

Only add date WHERE clauses when users explicitly ask for time-based filtering.

### 3. Always Add Defensive Row Limits
Always include a row limit clause to prevent runaway queries. Use 100 as the default unless user specifies otherwise.

Different SQL dialects have different syntax:
- **MySQL/PostgreSQL/SQLite**: \`LIMIT N\`
- **SQL Server**: \`SELECT TOP N\`
- **ANSI SQL (SQL Server, Oracle, DB2)**: \`OFFSET 0 ROWS FETCH NEXT N ROWS ONLY\`

✅ **Default approach (PostgreSQL/MySQL):**
\`\`\`sql
SELECT * FROM orders ORDER BY created_at DESC LIMIT 100;
\`\`\`

✅ **SQL Server:**
\`\`\`sql
SELECT TOP 100 * FROM orders ORDER BY created_at DESC;
\`\`\`

✅ **ANSI SQL (SQL Server with ORDER BY):**
\`\`\`sql
SELECT * FROM orders ORDER BY created_at DESC OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY;
\`\`\`

❌ **Avoid unlimited queries:**
\`\`\`sql
SELECT * FROM orders ORDER BY created_at DESC;  -- Can timeout or crash
\`\`\`
`);
    return sections.join("\n");
}
/**
 * Database naming conventions
 */
const DATABASE_NAMING_CONVENTIONS = `
## 📊 Database Schema Naming Conventions

### Databricks Three-Part Naming
Databricks uses a **three-part naming convention**: \`catalog.schema.table\`

When you see Databricks metadata like:
- \`uber.default.orders\` - Use the FULL path: \`uber.default.orders\`
- \`production.analytics.users\` - Use: \`production.analytics.users\`

**❌ WRONG for Databricks:**
\`\`\`sql
-- Metadata shows: uber.default.orders
SELECT * FROM uber.orders  -- ❌ Missing schema part
SELECT * FROM orders       -- ❌ Missing catalog and schema
\`\`\`

**✅ CORRECT for Databricks:**
\`\`\`sql
-- Always use the full three-part name
SELECT * FROM uber.default.orders     -- ✅ Full path
SELECT * FROM catalog.schema.table    -- ✅ Pattern
\`\`\`

**Note:** The word "default" in Databricks paths is NOT optional - it's the actual schema name. Always include all three parts exactly as shown in the metadata.

### Snowflake Two-Part Naming
Snowflake uses **schema-qualified table names**: \`schema.table\`

When you see Snowflake metadata where tables have a \`schema\` property, **you MUST qualify table names**:

**Metadata structure:**
\`\`\`json
{
  "schema": {
    "tables": [
      {
        "name": "PRODUCTLINE",
        "schema": "MASTERDATA",
        "columns": [...]
      }
    ]
  }
}
\`\`\`

**❌ WRONG for Snowflake:**
\`\`\`sql
-- Missing schema qualification
SELECT * FROM PRODUCTLINE  -- ❌ Will fail if no default schema
\`\`\`

**✅ CORRECT for Snowflake:**
\`\`\`sql
-- Always use schema.table format when schema property exists
SELECT * FROM MASTERDATA.PRODUCTLINE  -- ✅ Fully qualified
\`\`\`

**Rule**: If a table object has a non-empty \`schema\` property, use \`{schema}.{name}\` format in your SQL queries.

### Traditional SQL Databases (PostgreSQL, MySQL, etc.)
Traditional databases use **two-part naming**: \`schema.table\`
- PostgreSQL: \`public.orders\` or just \`orders\`
- MySQL: \`database.orders\` or just \`orders\`
`;
/**
 * Response interface guidelines
 */
const RESPONSE_INTERFACE_GUIDELINES = `
## 📝 Response Interface for finalizeApi

The \`responseInterface\` describes what external code gets from \`apiName.response\`. Internal blocks/steps are NOT visible externally.

### Direct Response Types

✅ **CORRECT**: Direct array response
\`\`\`typescript
interface GetUsersApiResponse {
  id: number;
  name: string;
  email: string;
}[]
\`\`\`

✅ **CORRECT**: Direct data structure
\`\`\`typescript
interface GetOrdersApiResponse {
  orders: Order[];
  totalCount: number;
}
\`\`\`

❌ **WRONG**: Exposing internal steps
\`\`\`typescript
interface GetOrdersApiResponse {
  fetchStep: { output: Order[] };  // ❌ Steps are internal
  countStep: { output: number };   // ❌ Not visible outside
}
\`\`\`

### Type Safety for API Response Interfaces

**CRITICAL: When defining response interfaces, consider runtime reality, not just happy-path data.**

#### Making Fields Optional

When uncertain if an API field will always be present, mark it optional:

✅ **CORRECT** - Accounts for real-world API behavior:
\`\`\`typescript
interface GitHubPRResponse {
  id: number;
  title: string;
  user?: {  // ← Optional, can be null for deleted users
    login: string;
    avatar_url: string;
  } | null;
  labels?: Label[];  // ← Optional, might be omitted in response
}
\`\`\`

❌ **WRONG** - False confidence:
\`\`\`typescript
interface GitHubPRResponse {
  user: {  // ← Marked required, but API can return null
    login: string;
    avatar_url: string;
  };
}
\`\`\`

#### When to Make Fields Optional

Mark fields optional when:
1. **User/account references** - Can be null for deleted/deactivated accounts
2. **Nested objects** - May be omitted in partial responses
3. **Third-party APIs** - GitHub, Stripe, etc. often have nullable fields
4. **Loading states** - Data may not be available during initial render
5. **Uncertain API behavior** - When in doubt, mark optional

This prevents downstream runtime errors when frontend code accesses these fields.
`;
/**
 * Runtime safety and defensive coding
 */
const RUNTIME_SAFETY = `
## Runtime Safety and Defensive Coding (CRITICAL)

- Prefer safe access patterns that tolerate partial/missing data. When reading nested fields, assume null/undefined is possible unless guaranteed otherwise.
- Use optional chaining and nullish coalescing when producing outputs that the frontend will consume; avoid throwing on missing optional fields.
- For REST/OpenAPI/GraphQL responses, treat non-required fields as optional in interfaces. If unsure, mark as optional and document assumptions in finalize summary.
- Avoid catching and suppressing unexpected errors with TryCatch unless explicitly asked; surface meaningful errors. Use validation (Conditional + Throw) for expected preconditions.
- When transforming arrays or objects from external sources, default to empty arrays/objects when inputs are absent.

Examples:
\`\`\`typescript
// Optional fields
type User = { id: number; name?: string | null };

// Defensive transformation
new JavaScript("normalize_users", {
  fn: ({ fetch_users }) => (Array.isArray(fetch_users.output) ? fetch_users.output : []).map(u => ({
    id: u.id,
    name: (u.name ?? "Unknown").toString()
  }))
})

// Guarded access
new Conditional("validate_email", {
  if: {
    when: ({ EmailInput }) => !EmailInput,
    then: [new Throw("missing_email", { error: "Email is required" })]
  }
})
\`\`\`
`;
/**
 * Error recovery strategies
 */
const ERROR_RECOVERY_STRATEGIES = `
## 🚨 Error Handling and Recovery

When you encounter errors while building APIs, follow these guidelines:

### Read Error Messages Carefully

Error messages contain specific guidance on how to fix the problem. Pay close attention to:
- What operation failed (compilation, validation, execution)
- Suggestions for how to resolve the issue
- Whether metadata is missing

### When to Check Integration Metadata

If you encounter errors mentioning:
- "unknown column", "table not found", "invalid field"
- "check integration metadata"
- Integration type mismatches

You MUST call \`readIntegrationMetadata\` to get the correct schema/table structure before retrying.
`;
/**
 * Loop control patterns
 */
const LOOP_CONTROL = `
## 🔄 Loop Control

### Loop Types

- **TYPE_FOREACH** (default): Iterates over an array using \`over\`. Provides \`item\` and \`index\` variables.
- **TYPE_WHILE**: Repeats while \`condition\` is true. Provides only \`index\` variable.

**Breaking out of loops:**
\`\`\`typescript
new Loop("process_until_complete", {
  over: ({ items }) => items.output,
  variables: { item: "current", index: "i" },
  blocks: [
    new Conditional("check_stop_condition", {
      if: {
        when: ({ current }) => current.value.status === "complete",
        then: [
          new Break("exit_loop", { condition: () => true }) // ✅ Only way to exit
        ]
      }
    }),
    new JavaScript("process_item", {
      fn: ({ current, i }) => ({
        processed: current.value,
        position: i.value
      })
    })
  ]
})
\`\`\`
`;
/**
 * API structure requirements
 *
 * @remarks Exported for testing purposes to validate completeness
 */
export const API_STRUCTURE = `
## 🏗️ API Structure Requirements

### File Structure
\`\`\`typescript
// Path: /apis/apiName.ts

// ✅ ALWAYS import the required types from the library
import {
  Api,
  JavaScript,
  Python,
  Databricks,
  Snowflake,
  PostgreSQL,
  GraphQL,
  RestApi,
  S3,
  Email,
  Conditional,
  TryCatch,
  Loop,
  Parallel,
  Throw,
  Return,
  Break,
} from "@superblocksteam/library";

// ❌ NEVER define constants here - they won't be serialized!

// ✅ ALL logic must be inside new Api()
export default new Api("apiName", [
  // Workflow blocks here
]);
\`\`\`

**🚨 CRITICAL:** Only code inside \`new Api()\` is serialized. Constants/helpers defined outside cause \`ReferenceError\` at runtime.

### Basic Workflow Structure
\`\`\`typescript
// 1. Input validation
// 2. Data fetching (integrations)
// 3. Data processing (JavaScript/Python)
// 4. Error handling (Try/Catch)
// 5. Return formatted output
\`\`\`
`;
/**
 * Critical mistakes to avoid
 */
const CRITICAL_MISTAKES = `
## 🚨 Critical Mistakes to Avoid

### 1. DEFINING CONSTANTS OR VARIABLES OUTSIDE THE API

**NEVER define constants, variables, or helper functions outside \`new Api()\`. They are NOT serialized and cause \`ReferenceError\` at runtime.**

❌ **WRONG:**
\`\`\`typescript
const MAX_BATCHES = 100;  // ❌ Not serialized!
export default new Api("MyApi", [
  new Loop("loop", {
    condition: ({ count }) => count.value < MAX_BATCHES,  // ReferenceError!
    blocks: [...]
  })
]);
\`\`\`

✅ **CORRECT - Use Variables block or inline values:**
\`\`\`typescript
export default new Api("MyApi", [
  new Variables("state", [
    { key: "count", value: () => 0 },
    { key: "maxBatches", value: () => 100 },  // ✅ Config inside Api
  ]),
  new Loop("loop", {
    condition: ({ count, maxBatches }) => count.value < maxBatches.value,  // ✅ Works
    blocks: [...]
  })
]);
\`\`\`

### 2. OVERUSING TRYCATCH BLOCKS
See the Error Handling section - only use TryCatch when truly necessary, not by default.

### 2. WRONG LANGUAGE FOR INTEGRATION TYPE

❌ **NEVER put JavaScript in PostgreSQL statement:**
\`\`\`typescript
new PostgreSQL("bad_query", "valid-postgres-id", {
  statement: ({ userId }) => \`SELECT * FROM users WHERE id = \${userId}\` // ❌ This is JavaScript!
})
\`\`\`

❌ **NEVER put SQL in JavaScript fn:**
\`\`\`typescript
new JavaScript("bad_js", {
  fn: "SELECT * FROM users" // ❌ This is SQL, not JavaScript!
})
\`\`\`

❌ **NEVER put multiple queries in one SQL block:**
\`\`\`typescript
new PostgreSQL("bad_multiple_queries", "postgres-id", {
  statement: \`
    UPDATE users SET status = 'active';
    DELETE FROM logs WHERE created < '2023-01-01';
    INSERT INTO audit VALUES ('done');
  \` // ❌ Multiple queries in one block will fail!
})
\`\`\`

✅ **CORRECT Language Matching:**
\`\`\`typescript
// ✅ PostgreSQL gets SQL in statement with typed parameters
new PostgreSQL("good_query", "your-postgresql-integration-id", {
  statement: ({ userId }: { userId: string }) => \`SELECT * FROM users WHERE id = '\${userId}'\`
})

// ✅ JavaScript gets JavaScript function in fn with typed parameters
new JavaScript("good_js", {
  fn: ({ userData }: { userData: Array<{ id: number; name: string; email: string }> }) =>
    userData.map(user => ({ id: user.id, name: user.name }))
})

// ✅ Python gets Python string in fn
new Python("good_python", {
  fn: \`return f"Processing user {userId}"\`
})
\`\`\`

### 3. Wrong Variable Access
\`\`\`typescript
// WRONG - accessing non-existent variables
new JavaScript("bad_example", {
  fn: ({ SomeVariable }) => SomeVariable
  // ❌ SomeVariable must be provided as an input when the API is called!
})
\`\`\`

### 4. Fake Integration IDs
\`\`\`typescript
// WRONG - making up integration IDs
new PostgreSQL("query", "fake-postgres-id", { // ❌ Never do this!
  statement: "SELECT * FROM users"
})
\`\`\`

### 5. APIs Cannot Set Frontend State
APIs are backend workflows that can only READ state, never SET it. State mutations MUST happen on the frontend.

❌ **NEVER attempt to set state inside API blocks:**
\`\`\`typescript
new JavaScript("update_data", {
  fn: ({ userData }) => {
    userNameVar.value = userData.name;        // ❌ CANNOT set state here!
    selectedUserVar.value = userData;         // ❌ CANNOT set state here!
    UserInput.value = userData.email;         // ❌ CANNOT set component values here!
    return userData;
  }
})
\`\`\`

✅ **CORRECT: APIs return data, frontend handles state updates:**
\`\`\`typescript
new JavaScript("update_data", {
  fn: ({ userData }) => {
    // Process data, perform calculations, transformations
    const processedUser = {
      ...userData,
      fullName: \`\${userData.firstName} \${userData.lastName}\`,
      lastUpdated: new Date().toISOString()
    };
    return processedUser;  // Frontend will handle state updates in onSuccess
  }
})
\`\`\`

### 6. Return blocks cannot contain statements, must return data directly
✅ **CORRECT: Return blocks returns data immediately
\`\`\`typescript
new Return("test_return", {
  data: (({ records }) => ({ records, totalCount: records.length, pageSize: pageSize || 10, pageNumber: pageNumber || 1 }))()
})

new Return("test_return", {
  data: (({ records }) => records.map(record => ({ id: record.id, name: record.name })))()
})
\`\`\`

❌ **WRONG: Return blocks cannot contain statements
\`\`\`typescript
new Return("test_return", {
  data: (({ records }) => {
    const totalCount = records.length;
    const pageSize = pageSize || 10;
    const pageNumber = pageNumber || 1;
    return { records, totalCount, pageSize, pageNumber };
  })()
})
\`\`\`
`;
/**
 * API checklist
 */
const API_CHECKLIST = `
## 📝 API Checklist

When creating APIs, you MUST follow this mental checklist:

1. **CORRECT LANGUAGE FOR EACH INTEGRATION** - SQL for PostgreSQL/Redshift/Snowflake, JavaScript for JavaScript blocks, Python strings for Python blocks
2. **CORRECT CLASS FOR REST APIs** - Use \`OpenApi\` class with \`openapi.path\` when \`grepMetadata\` shows OpenAPI spec exists, otherwise use \`RestApi\`
3. All imports included
4. Correct variable access patterns (.value, .output, and .output.data for GraphQL)
5. No fake or placeholder integration IDs
6. No placeholder logic
7. Descriptive block names
8. Error handling where appropriate - **avoid TryCatch blocks unless truly necessary**
9. Consistent naming across the API
10. NEVER change the API name when editing an existing API. Even if the prompt suggests another name, you must leave it as-is, or the API will break.
11. **ALWAYS**  test the API after building to ensure it works as expected before moving on to other work.
12. Response interface describes ONLY what's available as \`apiName.response\` - no internal steps

Remember: Superblocks APIs are reactive workflow builders that transform inputs into backend operations. Keep them declarative and focused.
`;
/**
 * Core documentation that applies to all APIs - now much more comprehensive
 */
const CORE_DOCUMENTATION = `# Superblocks API Documentation

## Mental Model

APIs in Superblocks are backend logic blocks that run in a secure server environment. They:
- Execute integrations (database queries, API calls, etc.)
- Process data with JavaScript or Python
- Return data to the frontend
- Cannot directly modify UI state

**Superblocks APIs are NOT traditional backend services.** They are frontend-coupled workflow builders that:
- **Build declarative workflows** - using a chain of blocks to provide I/O and control flow
- **Access inputs the user provides when they call the API from the frontend** - APIs receive input parameters passed from the application
- **Are visualized in the Superblocks editor** - APIs are represented in the Superblocks UI in a way that any user can understand

## 🚨 Critical Rules

### 1. Language Must Match Integration Type

**NEVER mix languages between integration types. This is the #1 cause of API failures.**

- **SQL integrations** (PostgreSQL, MySQL, Snowflake, etc.): Use SQL syntax
- **JavaScript blocks**: Use JavaScript/TypeScript syntax
- **Python blocks**: Use Python syntax
- **REST/GraphQL**: Use appropriate query languages

**The API will completely fail if you provide the wrong language to an integration.**

### 2. Variable Scoping

Variables referenced in API blocks can ONLY come from these sources:
- **Outputs of previous blocks** in the same API (accessed via block name)
- **Inputs from the user calling the API in their app** (passed as destructured parameters)

Important: Input variables from the frontend are GLOBAL for all API blocks. Do not shadow user input variables with local variables in your code.

### 4. Block Execution Order
- Blocks execute sequentially from top to bottom
- Each block can access outputs from previous blocks
- Use control flow blocks (Loop, Conditional, Try/Catch) for complex logic

### 5. GraphQL Output Structure
GraphQL steps return \`{ data: {...}, errors?: [...] }\`. Access query results via \`stepName.output.data\`, not \`stepName.output\` directly.

## ✅ Best Practices

1. **Single Responsibility**: Each API should do one thing well
2. **Clear Naming**: Use descriptive names for blocks and APIs
3. **Input Validation**: Validate inputs early in the API
4. **Error Boundaries**: Use Try/Catch for external operations (but only when truly necessary)
5. **Documentation**: Comment complex logic
6. **Performance**: Minimize database round trips
7. **Security**: Never expose sensitive data in responses
8. **Reasonable Guardrails**: Use LIMIT clauses in SQL queries, validate input ranges
9. **Plan the workflow**: Think through the sequence of operations before coding
10. **No placeholder logic**: Always implement real functionality

## Parallel Generation

Whenever you have multiple APIs to create, parallelize the tool calls as much as possible to minimize latency.

## Permissions

If the user request's checking user data, like email, ID, or group membership, you MUST use \`Global\` in your API code. This is injected by the backend API execution engine.

\`\`\`
type Global = {
  user: {
    email: string;
    username: string;
    id: string;
    name: string;
    groups: Group[]
  };
};
\`\`\`

\`Global\` is always available to use inside your API code, include it as a parameter when you need to access user data.
`;
/**
 * Get documentation for built-in blocks (JavaScript and Python)
 */
function getBuiltInBlockDocumentation() {
    return `## Built-in Blocks

### JavaScript Blocks

JavaScript blocks execute code directly in the API runtime environment. They're used for data transformation, validation, and business logic.

#### TypeScript Definition
\`\`\`typescript
export class JavaScript extends Integration {
  constructor(
    name: string,
    config: {
      fn: (state: State) => any;  // Function that receives state with all previous blocks
    }
  );
}
\`\`\`

#### Usage Pattern
\`\`\`typescript
new JavaScript("TransformData", {
  fn: ({ GetUsers, statusFilter }) => {
    // Access previous block outputs directly
    const users = GetUsers.output;

    // Access frontend variables
    const status = statusFilter.value;

    // Transform and return data
    return users
      .filter(user => user.status === status)
      .map(user => ({
        ...user,
        fullName: \`\${user.firstName} \${user.lastName}\`
      }));
  }
})
\`\`\`

#### Key Points
- Use \`fn\` property with a JavaScript function
- Access previous blocks via destructured parameters
- Can access frontend variables in the same way
- Return value becomes the block's output
- Supports async/await for asynchronous operations

### Python Blocks

Python blocks execute Python code strings. They're ideal for data science operations, complex calculations, and when Python libraries are needed.

Always return a value from the function string.

#### TypeScript Definition
\`\`\`typescript
export class Python extends Integration {
  constructor(
    name: string,
    config: {
      fn: string;  // Python code as a string
    }
  );
}
\`\`\`

#### Usage Pattern
\`\`\`typescript
new Python("AnalyzeData", {
  fn: \`import pandas as pd
  # Access previous block outputs directly
  users = GetUsers['output']

  # Access input parameters directly
  status = statusFilter

  # Convert to DataFrame
  df = pd.DataFrame(users)

  # Filter by status
  df_filtered = df[df['status'] == status]

  # Perform analysis
  summary = {
      'total_count': len(df_filtered),
      'avg_age': df_filtered['age'].mean(),
      'status_distribution': df_filtered['status'].value_counts().to_dict()
  }

  # Return as JSON-serializable object
  return summary\`
})
\`\`\`

#### Key Points
- Use \`fn\` property with a Python code string that always returns JSON-serializable data
- Access previous blocks and inputs as function parameters
- Previous block outputs accessed as \`blockName['output']\`
- Input parameters accessed directly
- Must return JSON-serializable data
- Common libraries available: pandas, numpy, scipy, etc.
- DON'T FORGET to return the result using the \`return\` statement

### 🚨 Critical: Never Mix Languages

**CORRECT:**
- JavaScript block: \`fn: ({ data }) => data.map(...)\`
- Python block: \`fn: "import pandas as pd\\ndf = pd.DataFrame(data)"\`
- SQL block: \`statement: "SELECT * FROM users"\`

**INCORRECT:**
- JavaScript block with Python: \`fn: "import pandas"\` ❌
- Python block with JavaScript: \`fn: ({ data }) => ...\` ❌
- SQL block with JavaScript: \`statement: "users.map(u => u.id)"\` ❌`;
}
/**
 * Get integration-specific documentation based on plugin type
 */
export function getIntegrationSpecificDocs(pluginId) {
    const specialDocs = {
        snowflake: `### Snowflake Specific Patterns
- Use two-part naming: \`schema.table\` or \`"SCHEMA"."TABLE"\`
- Case sensitivity: Unquoted identifiers are uppercase
- Use \`FLATTEN\` for JSON data
- Leverage warehouse-specific settings when needed`,
        databricks: `### Databricks Specific Patterns
- Use three-part naming: \`catalog.schema.table\`
- Default catalog is 'main' if not specified
- Supports both SQL and Python notebooks
- Use Unity Catalog for governance`,
        postgres: `### PostgreSQL Specific Patterns
- Use schema-qualified names: \`schema.table\` or \`"schema"."table"\`
- Case sensitivity: Unquoted identifiers are lowercase
- Use \`::type\` for type casting
- Leverage JSONB operators for JSON data`,
        mongodb: `### MongoDB Specific Patterns
- Use proper operation names: find, insertOne, updateMany, etc.
- Structure queries as JSON objects
- Use aggregation pipelines for complex queries
- Remember to specify the collection name`,
        snowflakecortex: `### Snowflake Cortex Specific Patterns
- The \`/api/v2/cortex/inference:complete\` endpoint defaults to \`stream: true\`, returning SSE (Server-Sent Events) chunks instead of clean JSON.
- **Always set \`"stream": false\` in the request body** unless the user explicitly asks for streaming. This returns a single JSON response instead of SSE chunks.
- Non-streaming response shape: \`{ "choices": [{ "message": { "content": "..." } }], "usage": { "prompt_tokens": N, "completion_tokens": N } }\`
- The \`model\` and \`messages\` fields are required in the request body for the complete endpoint.
- Use \`GET /api/v2/cortex/models\` to discover available models.`,
    };
    return specialDocs[pluginId] || "";
}
/**
 * Build documentation for specific integrations including TypeScript types
 */
export function buildIntegrationDocumentation(integrationIds, services) {
    const sections = [];
    const processedPluginIds = new Set();
    for (const integrationId of integrationIds) {
        // Get integration header from store
        const header = services.integrationStore.getHeader(integrationId);
        if (!header) {
            continue;
        }
        const plugin = header.plugin;
        // Avoid duplicating docs for same plugin type
        if (processedPluginIds.has(plugin.id)) {
            continue;
        }
        processedPluginIds.add(plugin.id);
        // Get the plugin execution version to provide version-specific documentation
        const pluginVersion = services.integrationStore.getPluginExecutionVersion(plugin.id);
        // Get TypeScript type definition (version-aware, feature-flag-aware)
        const typeDef = getIntegrationTypeDefinition(plugin, pluginVersion, {
            parameterizedApisEnabled: services.features.parameterizedApisEnabled,
        });
        if (!typeDef) {
            continue;
        }
        // Build section for this integration
        const sdkName = getSdkDeclarationName(plugin.id);
        const integrationSection = [
            `## ${typeDef.className} Integration`,
            "",
            `**Integration ID**: \`${integrationId}\` (use this ID in the declaration, e.g. \`${sdkName}("${integrationId}")\`)`,
            `**Plugin Type**: ${plugin.id}`,
            `**Description**: ${typeDef.description}`,
            "",
            // Only emit corrective import guidance when the SDK name differs from the plugin ID
            ...(sdkName !== plugin.id
                ? [
                    `**IMPORTANT — Correct import name**: \`import { ${sdkName} } from "@superblocksteam/sdk-api"\`. Do NOT use \`${plugin.id}\` as the import — the correct SDK export is \`${sdkName}\`.`,
                    "",
                ]
                : []),
            "**SDK access**: In your API `run` function, use the **key name** you declared: `ctx.integrations.<name>` (e.g. `ctx.integrations.db`). Do not use the integration ID when accessing—only when declaring the integration.",
            "",
            "### TypeScript Type Definition",
            "```typescript",
            typeDef.typeDefinition,
            "```",
            "",
        ];
        // Add example if available
        if (typeDef.example) {
            integrationSection.push("### Example Usage", "```typescript", typeDef.example, "```", "");
        }
        // Add integration-specific patterns/rules
        const specificDocs = getIntegrationSpecificDocs(plugin.id);
        if (specificDocs) {
            integrationSection.push(specificDocs, "");
        }
        sections.push(integrationSection.join("\n"));
    }
    return sections.join("\n\n");
}
/**
 * Get relevant examples based on integration types
 */
export function getRelevantExamples(integrationIds, services) {
    const tags = [];
    const pluginTypes = new Set();
    // Collect plugin types from integration IDs
    for (const integrationId of integrationIds) {
        const header = services.integrationStore.getHeader(integrationId);
        if (header) {
            pluginTypes.add(header.plugin.id);
        }
    }
    // Map plugin types to relevant tags
    if (pluginTypes.has("snowflake"))
        tags.push("snowflake");
    if (pluginTypes.has("databricks"))
        tags.push("databricks");
    if (pluginTypes.has("postgres") ||
        pluginTypes.has("mysql") ||
        pluginTypes.has("mssql")) {
        tags.push("sql-query");
    }
    if (pluginTypes.size > 1)
        tags.push("multi-integration");
    // If no integrations provided, default to data transformation examples
    if (integrationIds.length === 0) {
        tags.push("data-transformation", "variable-access");
    }
    // Always include some common patterns
    tags.push("error-handling", "variable-access");
    // Select and format examples
    const selectedExamples = selectExamplesByTags(tags, {
        maxExamples: 3,
        includeNegative: true,
        maxTokenBudget: 3000,
    });
    // If no examples were selected, use a fallback example
    if (selectedExamples.length === 0) {
        // Find a basic data transformation example as fallback
        const fallbackExample = POSITIVE_EXAMPLES.find((ex) => ex.metadata.tags.includes("data-transformation") &&
            ex.metadata.tags.includes("variable-access")) || POSITIVE_EXAMPLES[0]; // Ultimate fallback to first example
        if (fallbackExample) {
            // Create metadata object with id for formatting
            const fallbackMetadata = {
                id: fallbackExample.id,
                ...fallbackExample.metadata,
            };
            const formattedFallback = formatSelectedExamples([fallbackMetadata]);
            return `## Relevant Examples

${formattedFallback}`;
        }
    }
    const formattedExamples = formatSelectedExamples(selectedExamples);
    return `## Relevant Examples

${formattedExamples}`;
}
export const getApiDocsToolFactory = createToolFactory("getApiDocs", (services) => ({
    category: ToolCategory.API,
    readOnly: true,
    description: `
Retrieve comprehensive API development documentation with TypeScript type definitions and examples.

This tool provides:
- Core API development rules and best practices
- Complete TypeScript type definitions for all blocks and integrations
- Integration exploration workflow (grepMetadata patterns)
- Block output scoping rules
- Common API patterns including dynamic SQL two-block pattern
- Error handling and TryCatch usage guidelines
- SQL best practices (parameterized queries, LIMIT, no auto date filtering, one query per block)
- Database naming conventions (Databricks, Snowflake, PostgreSQL)
- Response interface guidelines
- Runtime safety and defensive coding patterns
- Integration-specific patterns and syntax rules
- Relevant code examples based on integration types

ALWAYS call this tool:
- Before building or modifying APIs
- When explaining API syntax, patterns, or examples to users
`,
    inputSchema: z.object({
        integrationIds: z
            .array(z.string())
            .describe("Integration IDs to include type definitions and specific documentation for. Pass the actual integration IDs from your page context.")
            .optional(),
        sections: z
            .array(z.enum([
            "core",
            "types",
            "integration-workflow",
            "scoping",
            "patterns",
            "error-handling",
            "sql-best-practices",
            "database-naming",
            "response-interface",
            "runtime-safety",
            "error-recovery",
            "loop-control",
            "api-structure",
            "critical-mistakes",
            "checklist",
            "built-in-blocks",
            "examples",
        ]))
            .optional()
            .describe("Specific sections to include. If not specified, all sections are included."),
        verbosity: z
            .enum(["minimal", "standard", "comprehensive"])
            .optional()
            .describe("Level of detail to include. Defaults to comprehensive."),
    }),
    execute: async ({ integrationIds = [], sections, verbosity = "comprehensive", }) => {
        const documentationSections = {
            core: CORE_DOCUMENTATION,
            types: TYPE_DEFINITIONS,
            "integration-workflow": INTEGRATION_EXPLORATION_WORKFLOW,
            scoping: BLOCK_OUTPUT_SCOPING_RULES,
            "input-discovery": INPUT_DISCOVERY_RULES,
            patterns: COMMON_API_PATTERNS,
            "error-handling": ERROR_HANDLING_GUIDELINES,
            "sql-best-practices": getSqlBestPractices({
                parameterizedApisEnabled: services.features.parameterizedApisEnabled,
                pluginExecutionVersions: services.integrationStore.pluginExecutionVersions,
            }),
            "database-naming": DATABASE_NAMING_CONVENTIONS,
            "response-interface": RESPONSE_INTERFACE_GUIDELINES,
            "runtime-safety": RUNTIME_SAFETY,
            "error-recovery": ERROR_RECOVERY_STRATEGIES,
            "loop-control": LOOP_CONTROL,
            "api-structure": API_STRUCTURE,
            "critical-mistakes": CRITICAL_MISTAKES,
            checklist: API_CHECKLIST,
            "built-in-blocks": getBuiltInBlockDocumentation(),
        };
        // Determine which sections to include
        let sectionsToInclude = [];
        if (sections && sections.length > 0) {
            // Use only specified sections
            sectionsToInclude = sections;
        }
        else {
            // Include sections based on verbosity
            switch (verbosity) {
                case "minimal":
                    sectionsToInclude = ["core", "critical-mistakes", "checklist"];
                    break;
                case "standard":
                    sectionsToInclude = [
                        "core",
                        "integration-workflow",
                        "scoping",
                        "input-discovery",
                        "patterns",
                        "error-handling",
                        "sql-best-practices",
                        "database-naming",
                        "critical-mistakes",
                        "checklist",
                    ];
                    break;
                case "comprehensive":
                default:
                    sectionsToInclude = Object.keys(documentationSections);
                    break;
            }
        }
        // Build documentation sections
        const outputSections = [];
        // Add requested sections, but handle built-in-blocks specially
        for (const section of sectionsToInclude) {
            // Skip built-in-blocks if integrations are provided, unless explicitly requested
            if (section === "built-in-blocks" &&
                integrationIds.length > 0 &&
                (!sections || !sections.includes("built-in-blocks"))) {
                continue;
            }
            if (documentationSections[section]) {
                outputSections.push(documentationSections[section]);
            }
        }
        // Add integration-specific documentation if integrationIds provided
        if (integrationIds.length > 0) {
            const integrationDocs = buildIntegrationDocumentation(integrationIds, services);
            if (integrationDocs) {
                outputSections.push(integrationDocs);
            }
        }
        // Always add relevant examples if requested or in comprehensive mode
        if (sectionsToInclude.includes("examples") ||
            verbosity === "comprehensive") {
            const examples = getRelevantExamples(integrationIds, services);
            if (examples) {
                outputSections.push(examples);
            }
        }
        return {
            documentation: outputSections.filter(Boolean).join("\n\n---\n\n"),
            integrationCount: integrationIds.length,
            sectionsIncluded: sectionsToInclude,
            verbosity,
        };
    },
    getSummary: (_input, output) => {
        const sectionCount = output.sectionsIncluded?.length ?? 0;
        return {
            input: `verbosity: ${output.verbosity ?? "comprehensive"}`,
            output: `${sectionCount} section${sectionCount === 1 ? "" : "s"}`,
        };
    },
}));
//# sourceMappingURL=get-api-docs.js.map