/**
 * API prompt sections for YAML and SDK experiences.
 *
 * These functions generate the appropriate API documentation sections
 * based on whether the SDK API feature flag is enabled.
 */
/**
 * YAML-based API prompt section (legacy experience).
 *
 * Uses:
 * - useApi / useApiData / executeApi from @superblocksteam/library
 * - APIs in apis/ApiName/api.yaml
 * - getApiDocs tool is mandatory before API work
 */
export function buildYamlApiSection() {
    return `<apis>
## Using APIs - The ONLY Superblocks-Specific Feature

**🚨 MANDATORY: Call \`getApiDocs\` before explaining API syntax, bindings, or showing example code.** Superblocks syntax differs from public documentation - do NOT rely on general knowledge.

<integrations_and_data_sources>
**CRITICAL: Always prefer integrations and data sources already in use in the current application.**

Before creating APIs with new integrations:
- Check which integrations are already used in existing APIs
- Prefer the most frequently used integration. If multiple integrations are equally common, use the askMultiChoice tool to let the user choose rather than guessing.
- Only introduce new integrations if existing ones cannot fulfill the requirement
</integrations_and_data_sources>

<creating_and_editing_apis>
**CRITICAL: Only modify APIs when explicitly requested by the user.**

Rules for API modification:
- If the user tags/mentions an API but says "don't change the API" or "without modifying the API", don't change it
- If the user tags an API for context/reference only, do not modify it
- Only delegate to the API tool when the user explicitly requests API creation or modification
- When the user does request changes to multiple APIs, parallelize the tool calls to optimize the process

Examples of when NOT to modify APIs:
- "The getUsersApi returns this data [tagged API] but don't change it"
- "Using the existing searchApi [tagged], update the UI to show results"
- "The API is working fine, just fix the display"

Examples of when TO modify APIs:
- "Update the getUsersApi to include email addresses"
- "Create a new API to fetch products"
- "Change the searchApi to filter by category"
</creating_and_editing_apis>

<api_failure_handling>
**CRITICAL: When APIs fail, timeout, or error - stop everything and ask the user first.**

If an API you created or are testing encounters issues (connection failure, timeout, error response, wrong data, connection refused):

**Do not:**
- Create any UI pages, components, or anything else
- Switch to a different integration than the one the user requested

Instead, you must explain what failed and why and use askMultiChoice to present options.
A working API is a prerequisite for building UI. The user specified the integration for a reason.
</api_failure_handling>

<permissions>
If the user requests checking user data, like email, ID, this information cannot be passed from the frontend because it is UNSAFE and can result in security vulnerabilities.

You must NEVER attempt to rely on frontend data for security-critical operations, rely on the injected \`Global\` object in APIs instead.
</permissions>

APIs MUST be loaded using hooks and utilities from \`@superblocksteam/library\` with the exact API name based on its folder name under apis/. Having apis/<ApiName>/api.yaml, the first argument should be \`<ApiName>\`.

**Three primitives for three use cases:**
- **\`useApiData\`** — React hook for data loading (reads). Auto-fetches on mount and when inputs change. Has shared cache, stale-while-revalidate, retry, and auto-refetch.
- **\`useApi\`** — React hook for mutations/actions (writes). Call \`run()\` manually on button click, form submit, etc. No auto-fetch, no cache.
- **\`executeApi\`** — Plain function for calling APIs outside React (utility functions, event handlers, initialization logic). Returns a Promise.

**CRITICAL: Use \`useApiData\` for data loading, \`useApi\` for mutations, and \`executeApi\` outside React components. Do NOT use \`useApi\` with a second argument for data loading — that pattern is deprecated.**

**CRITICAL: Do NOT create custom wrapper hooks around these hooks. Do NOT manage loading or data state with separate useState — the hooks handle this for you.**

**CRITICAL: When a user says that an API is not working or has an error, ALWAYS check the API call sites in the application and ensure the inputs are correct! DO NOT assume the API itself is broken, it is important to verify the frontend code first!**

\`\`\`typescript
// Data loading — auto-fetches when inputs change (preferred for reads)
import { useApiData } from "@superblocksteam/library";

const { data, loading, isError, error, fetching } = useApiData("GetUsers", { email: email ?? null, name: name ?? null });
// \`data\` updates automatically, \`loading\` is true on first fetch with no cached data
// \`fetching\` is true during any fetch (including background refetch)
// \`error\` is populated if the fetch fails — no try/catch needed
// Re-fetches when email or name changes — no useEffect needed
// IMPORTANT: Always use \`fetching\` to show a loading indicator during refetches

if (loading) return <Skeleton />;
if (isError) return <ErrorBanner error={error} />;
return <UserList users={data.users} />;
\`\`\`

\`\`\`typescript
// Mutations — for event-driven actions (button clicks, form submissions)
import { useApi } from "@superblocksteam/library";
import { toast } from "sonner";

const { run: createOrder, loading, error } = useApi("CreateOrder");

const handleSubmit = useCallback(async () => {
  try {
    await createOrder({ item, qty });
  } catch (error) {
    const message =
      error && typeof error === "object" && "message" in error
        ? String((error as { message: unknown }).message)
        : String(error);
    toast.error("Error creating order: " + message);
  }
}, [item, qty, createOrder]);
\`\`\`

\`\`\`typescript
// Refetch after a mutation — combine useApiData + useApi
import { useApiData, useApi } from "@superblocksteam/library";

const { data: todos, refetch } = useApiData("GetTodos", {});
const { run: createTodo } = useApi("CreateTodo");

const handleCreate = async (title: string) => {
  await createTodo({ title });
  await refetch(); // Refresh the list after mutation
};
\`\`\`

\`\`\`typescript
// Outside React — utility functions, event handlers, initialization logic
import { executeApi } from "@superblocksteam/library";

// Simple call — returns a Promise
const users = await executeApi("GetUsers", { email: "a@b.com" });

// With cancellation
const controller = new AbortController();
const data = await executeApi("GetUser", { id: userId }, { signal: controller.signal });

// In a utility function (no React hooks needed)
async function syncUserData(userId: string) {
  const user = await executeApi("GetUser", { id: userId });
  const orders = await executeApi("GetOrders", { userId: user.id });
  return { user, orders };
}
\`\`\`

**\`useApiData\` returns \`{ data, error, status, fetchStatus, loading, fetching, isError, isSuccess, isStale, refetch, cancel }\`:**
- \`data\` — cached/fetched response (persists across background refetches)
- \`error\` — error from the last failed fetch (cleared on success)
- \`loading\` — true when fetching for the first time with no cached data
- \`fetching\` — true when any fetch is in progress (including background refetch)
- \`isError\` / \`isSuccess\` — boolean status helpers
- \`refetch()\` — manually trigger a fresh fetch
- \`cancel()\` — abort the current in-flight fetch

**\`useApi\` returns \`{ run, cancel, loading, data, error, status, variables, reset }\`:**
- \`run(inputs)\` — execute the API imperatively
- \`cancel()\` — cancel in-flight requests
- \`loading\` — boolean, true while the most recent call is in flight
- \`data\` — last successful response (persists across re-runs)
- \`error\` — error from the last failed run (cleared on next success)
- \`status\` — \`"idle" | "pending" | "success" | "error"\`
- \`reset()\` — reset state back to idle

**\`executeApi(apiName, inputs?, options?)\` returns \`Promise<TOutput>\`:**
- Plain async function — no React hooks, no caching, no reactive state
- Use for utility functions, event handlers, initialization logic, and non-component code
- Supports \`{ signal: AbortSignal }\` option for cancellation
- Errors are thrown as exceptions — use try/catch or .catch()

### Critical Rules

1. **MUST call API by the exact name**: Format is \`<ApiName>\` in folder apis/<ApiName>/api.yaml
2. **Always pass parameters to the function**: \`await run({ param1: value1, param2: value2 })\` for useApi, or as the second argument for useApiData / executeApi
3. **Use \`useApiData\` for data loading, \`useApi\` for mutations, \`executeApi\` outside React**: Do NOT create separate useState for loading, response data, or error state
4. **Do NOT create wrapper hooks**: Use the hooks directly in components — no \`useGetUsers\` pattern needed
5. **ALWAYS check API input/output interfaces**: NEVER guess the response structure - use the actual interface defined by the API
6. **ALWAYS include all parameters in the function call**: NEVER omit parameters the API expects, even if they are optional, they should be included and passed as null
7. **ALWAYS include error handling**: In useApi, wrap \`run()\` in try/catch. In useApiData, check the \`error\` or \`isError\` fields. For executeApi, use try/catch or .catch().

### File Handling

**CRITICAL: Files must be wrapped in \`{ files: [...] }\` format.**

\`\`\`tsx
// ✅ CORRECT - Frontend: wrap files in { files: [...] }
const response = await runUploadApi({ userFile: { files: selectedFiles } });

// ❌ WRONG - backend cannot process unwrapped files
const response = await runUploadApi({ userFile: selectedFiles });
\`\`\`

\`\`\`typescript
// ✅ Backend API: access via .files property
const file = inputs.userFile.files[0];
// Available: file.name, file.size, file.type, file.extension
\`\`\`

### Efficient-Friendly Patterns

Efficiency is key when building applications for production. You should always be thinking about patterns that will help you build efficient applications
when it comes to loading data from APIs.

Here are some examples (not exhaustive) that you should consider when building applications:
1. **Always show loading indicators on refetch**: When inputs change (e.g. filters, search), show a visual loading indicator while new data loads. Use \`fetching\` from useApiData.
2. **Loading State Hierarchy**:
  - No data yet (\`loading\`) → Full skeleton placeholder
  - Has data, refetching (\`fetching\` && !\`loading\`) → Keep showing current data with a subtle visual indicator: apply light opacity (e.g. \`opacity-70\`) to signal a refresh is in progress, plus a non-blocking label (e.g. "Updating…" text, small spinner, or thin progress bar). Do not use \`pointer-events-none\` — the content must remain fully interactive during refetch.
  - Error state (\`isError\`) → Show error with retry option, optionally keep stale data visible
3. **Debounce Rapid Requests**: Prevent multiple API calls in short succession
4. **Use useApiData for automatic refetching**: \`useApiData\` auto-refetches when inputs change and supports \`staleTime\`, \`refetchOnWindowFocus\`, and \`refetchOnReconnect\` options.

\`\`\`tsx
// ✅ CORRECT — subtle opacity + indicator, table stays interactive
const { data, loading, fetching, isError, error } = useApiData("GetOrders", { status: statusFilter, search });

if (loading) return <Skeleton />;                // First load: full skeleton
if (isError) return <ErrorBanner error={error} />;
return (
  <div>
    {fetching && <div className="text-xs text-muted-foreground">Updating…</div>}
    <div className={fetching ? "opacity-70" : ""}>
      <OrderTable orders={data.orders} />          {/* Dimmed but still interactive */}
    </div>
  </div>
);
\`\`\`

\`\`\`tsx
// ❌ WRONG — pointer-events-none disables the table, making it feel broken
return (
  <div className={fetching ? "opacity-50 pointer-events-none" : ""}>
    <OrderTable orders={data.orders} />
  </div>
);

// ❌ WRONG — no loading indicator when filters change. User sees stale data with no feedback.
const { data, loading } = useApiData("GetOrders", { status: statusFilter, search });

if (loading) return <Skeleton />;
return <OrderTable orders={data.orders} />;
\`\`\`

### Interpreting testApi Results

**CRITICAL**: \`success: false\` or missing = FAILURE. Never show success toast. Even when \`success: true\`, verify the output data is valid before confirming success to the user.
</apis>`;
}
/**
 * SDK-based API prompt section (new experience).
 *
 * Uses:
 * - useApi from @/hooks/useApi.js, useApiData from @/hooks/useApiData.js, executeApi from @/lib/executeApi.js
 * - API modules under server/apis/ (group by domain or feature, e.g. server/apis/users/get-users.ts; paths are flexible)
 * - SDK READMEs for documentation
 * - Zod schemas and integration IDs
 */
export function buildSdkApiSection() {
    return `<apis>
## Using APIs - The ONLY Superblocks-Specific Feature
<sdk>
The API SDK is available via the installed \`@superblocksteam/sdk-api\` package. It re-exports everything you need including \`z\` (zod), \`api\`, and integration clients. **Do NOT install zod or any other SDK dependency separately** — import everything from \`@superblocksteam/sdk-api\`.

**MANDATORY: Call \`getSdkApiDocs\` before writing SDK APIs**

Before writing ANY API, you MUST:
1. **Call \`getSdkApiDocs\` first**
   - Pass integration IDs whenever available so docs are tailored to the app's actual integrations
   - \`getSdkApiDocs\` returns version-aware integration documentation for the app's plugin versions
   - This is REQUIRED before creating or modifying any SDK API

2. **Use \`getSdkApiDocs\` output as the source of truth for integration methods and SDK API patterns**
   - Do NOT guess or hallucinate integration methods based on vendor APIs
   - Do NOT read SDK documentation directly from filesystem files; fetch documentation through \`getSdkApiDocs\` only

**Trace Metadata:**
All integration client methods accept an optional \`metadata\` parameter as the last argument: \`{ label?: string, description?: string }\`. When \`includeDiagnostics\` is enabled, this metadata appears in the trace view. Always include a \`label\` on each integration call to make traces readable. Example: \`ctx.integrations.db.query(sql, Schema, params, { label: "Fetch active users" })\`.

**CRITICAL - Method Validation:**
Before calling ANY integration client method, you MUST:
1. Call \`getSdkApiDocs\` (with integration IDs when possible) and use its integration documentation output
2. Check the client's TypeScript type definition in \`node_modules/@superblocksteam/sdk-api/src/integrations/<client>/types.ts\` if needed
3. Verify the method exists and review its exact signature
4. Do NOT hallucinate methods based on the real service's API (e.g., \`openai.createChatCompletion()\` doesn't exist - check \`getSdkApiDocs\` output for actual methods)
</sdk>

<integrations_and_data_sources>
**CRITICAL: Always prefer integrations and data sources already in use in the current application.**

Before creating APIs with new integrations:
- Check which integrations are already used in existing APIs
- Prefer the most frequently used integration. If multiple integrations are equally common, use the askMultiChoice tool to let the user choose rather than guessing.
- Only introduce new integrations if existing ones cannot fulfill the requirement
</integrations_and_data_sources>

<integration_ids>
**CRITICAL: Integration IDs**

When using integrations in SDK APIs:
1. **Use integration IDs** (UUIDs), not display names - IDs are stable identifiers that won't break if integrations are renamed
2. **Get the ID from the integrations panel** - each integration has a unique ID visible in its settings
3. **Store IDs in constants** with descriptive names at the top of the API file for clarity

Example:
\`\`\`typescript
// Store integration IDs in constants with descriptive names
const PROD_POSTGRES = "a1b2c3d4-5678-90ab-cdef-ghijklmnopqr";
const OPS_SLACK = "e5f6g7h8-1234-56ab-cdef-ghijklmnopqr";

export default api({
  integrations: {
    db: postgres(PROD_POSTGRES),
    notifier: slack(OPS_SLACK),
  },
  // ...
});
\`\`\`

**NEVER use integration display names** like \`postgres("Production Postgres")\` - always use the UUID.

**Access in run(): use \`ctx.integrations.<name>\` pattern.** In your API \`run\` function, access each integration by the **key name** you declared in \`integrations\`, not by integration ID. Example: \`integrations: { db: postgres(PROD_POSTGRES), notifier: slack(OPS_SLACK) }\` → use \`ctx.integrations.db\` and \`ctx.integrations.notifier\`. The integration ID (UUID) is only for the declaration (e.g. \`postgres(UUID)\`); access is always \`ctx.integrations.<key>\`.
</integration_ids>

<creating_and_editing_apis>
**CRITICAL: Only modify APIs when explicitly requested by the user.**

Rules for API modification:
- If the user tags/mentions an API but says "don't change the API" or "without modifying the API", don't change it
- If the user tags an API for context/reference only, do not modify it
- Only delegate to the API tool when the user explicitly requests API creation or modification
- When the user does request changes to multiple APIs, parallelize the tool calls to optimize the process

**MANDATORY: Always include a \`description\` field when creating or editing SDK APIs.**
The \`description\` must be a short phrase (under 10 words) summarizing the API's core logic, e.g. "Fetches active orders from Postgres" or "Sends a Slack notification". Place it right after \`name\` in the \`api()\` call. When editing an existing API, update the description if the API logic changed.

Examples of when NOT to modify APIs:
- "The getUsersApi returns this data [tagged API] but don't change it"
- "Using the existing searchApi [tagged], update the UI to show results"
- "The API is working fine, just fix the display"

Examples of when TO modify APIs:
- "Update the getUsersApi to include email addresses"
- "Create a new API to fetch products"
- "Change the searchApi to filter by category"
</creating_and_editing_apis>

<api_failure_handling>
**CRITICAL: When APIs fail, timeout, or error - stop everything and ask the user first.**

If an API you created or are testing encounters issues (connection failure, timeout, error response, wrong data, connection refused):

**Do not:**
- Create any UI pages, components, or anything else
- Switch to a different integration than the one the user requested

Instead, you must explain what failed and why and use askMultiChoice to present options.
A working API is a prerequisite for building UI. The user specified the integration for a reason.
</api_failure_handling>

<permissions>
If the user requests checking user data, like email, ID, groups, or custom claims, this information cannot be passed from the frontend because it is UNSAFE and can result in security vulnerabilities.

You must NEVER attempt to rely on frontend data for security-critical operations. Instead, use \`ctx.user\`, which is securely populated server-side from the Superblocks JWT. Call \`getSdkApiDocs\` for the full \`ctx.user\` interface, properties, and usage examples including groups and custom claims.
</permissions>

**First argument to \`useApi\` / \`useApiData\` / \`executeApi\`:** each key on the default export in \`server/apis/index.ts\` — not the \`name\` field inside \`api({ … })\` when those differ. Use \`index.ts\` and existing call sites;

**CRITICAL: When debugging data issues:**
- If the UI is showing no data, ALWAYS test the relevant APIs first to verify they are actually returning data
- DO NOT assume the API itself is correct or broken without testing it - verify both the API response AND the frontend code

**File layout:** Group APIs under \`server/apis/\` by domain or feature (e.g. \`users/\`, \`orders/\`, \`billing/\`). Use descriptive file names (\`get-users.ts\`, \`create-order.ts\`) instead of repeating \`api.ts\` inside a folder named after the registry key. The path is independent of the string passed to \`useApi("...")\`—only \`server/apis/index.ts\` maps names to files.

\`\`\`typescript
// API definition in server/apis/users/get-users.ts
import { api, z, postgres } from "@superblocksteam/sdk-api";

// Integration IDs from the integrations panel - store in constants with descriptive names
const PROD_POSTGRES = "a1b2c3d4-5678-90ab-cdef-ghijklmnopqr";

const UserSchema = z.object({
  id: z.string(),
  email: z.string(),
  name: z.string(),
});

type User = z.infer<typeof UserSchema>;

export default api({
  // REQUIRED: name is used for identification in logs and debugging
  name: "GetUsers",

  // REQUIRED: plain-language summary for non-technical readers
  description: "Looks up users from the production database, with optional filtering by email or name. Returns a list of matching users.",

  // Declare integrations upfront using their IDs for type safety
  integrations: {
    db: postgres(PROD_POSTGRES),
  },

  input: z.object({
    email: z.string().nullable(),
    name: z.string().nullable(),
  }),

  output: z.object({
    users: z.array(UserSchema),
  }),

  async run(ctx, { email, name }) {
    // ctx.integrations.db is fully typed as PostgresClient
    // All integration methods accept an optional metadata arg as the last parameter
    // for trace labeling: { label?: string, description?: string }
    const users = await ctx.integrations.db.query(
      "SELECT id, email, name FROM users WHERE ($1::text IS NULL OR email = $1) AND ($2::text IS NULL OR name = $2)",
      UserSchema,
      [email, name],
      { label: "Find users by email/name" }
    );
    return { users };
  },
});
\`\`\`

**Custom Type Casts (Enums, Composite Types):**
When casting SQL parameters, always use the actual column type — not \`text\` or other generic types. If \`grepMetadata\` reports a custom type (e.g., \`billing_plan_enum\`, \`order_status_enum\`), use that exact type in casts. Casting to \`text\` will fail with \`operator does not exist\`.

\`\`\`sql
-- Column type is "billing_plan_enum" (from grepMetadata)
WHERE plan = ANY($1::billing_plan_enum[])  -- ✅ CORRECT
WHERE plan = ANY($1::text[])               -- ❌ WRONG: "operator does not exist: billing_plan_enum = text"
\`\`\`

Rule: Before writing \`::type\` casts, check the actual column type via \`grepMetadata\`. Use \`::text\` only for built-in text columns.

\`\`\`typescript
// Data loading — auto-fetches when inputs change (preferred for reads)
import { useApiData } from "@/hooks/useApiData.js";

const { data, loading, isError, error, fetching } = useApiData("GetUsers", { email, name });
// \`data\` updates automatically, \`loading\` is true on first fetch with no cached data
// \`fetching\` is true during any fetch (including background refetch)
// \`error\` is populated if the fetch fails — no try/catch needed
// Re-fetches when email or name changes — no useEffect needed
// IMPORTANT: Always use \`fetching\` to show a loading indicator during refetches

if (loading) return <Skeleton />;
if (isError) return <ErrorBanner error={error} />;
return <UserList users={data.users} />;
\`\`\`

\`\`\`typescript
// Mutations — for event-driven actions (button clicks, form submissions)
import { useApi } from "@/hooks/useApi.js";
import { toast } from "sonner";

const { run: createOrder, loading, error } = useApi("CreateOrder");

const handleSubmit = useCallback(async () => {
  try {
    await createOrder({ item, qty });
  } catch (error) {
    const message =
      error && typeof error === "object" && "message" in error
        ? String((error as { message: unknown }).message)
        : String(error);
    toast.error("Error creating order: " + message);
  }
}, [item, qty, createOrder]);
\`\`\`

\`\`\`typescript
// Refetch after a mutation — combine useApiData + useApi
import { useApiData } from "@/hooks/useApiData.js";
import { useApi } from "@/hooks/useApi.js";

const { data: todos, refetch } = useApiData("GetTodos", {});
const { run: createTodo } = useApi("CreateTodo");

const handleCreate = async (title: string) => {
  await createTodo({ title });
  await refetch(); // Refresh the list after mutation
};
\`\`\`

\`\`\`typescript
// Conditional fetching and stale-while-revalidate
import { useApiData } from "@/hooks/useApiData.js";

// Only fetch when userId is available
const { data } = useApiData("GetUser", { id: userId }, { enabled: !!userId });

// Show cached data while refreshing in background
const { data, fetching } = useApiData("GetMetrics", {}, { staleTime: 30_000 });
\`\`\`

\`\`\`typescript
// Outside React — utility functions, event handlers, initialization logic
import { executeApi } from "@/lib/executeApi.js";

// Simple call — returns a Promise
const users = await executeApi("GetUsers", { email: "a@b.com" });

// With cancellation
const controller = new AbortController();
const data = await executeApi("GetUser", { id: userId }, { signal: controller.signal });

// In a utility function (no React hooks needed)
async function syncUserData(userId: string) {
  const user = await executeApi("GetUser", { id: userId });
  const orders = await executeApi("GetOrders", { userId: user.id });
  return { user, orders };
}
\`\`\`

**Three primitives for three use cases:**
- **\`useApiData\`** — React hook for data loading (reads). Auto-fetches on mount and when inputs change.
- **\`useApi\`** — React hook for mutations/actions (writes). Call \`run()\` manually.
- **\`executeApi\`** — Plain function for calling APIs outside React (utility functions, event handlers, initialization logic).

**\`useApiData\` returns \`{ data, error, status, fetchStatus, loading, fetching, isError, isSuccess, isStale, refetch, cancel }\`:**
- \`data\` — cached/fetched response (persists across background refetches)
- \`error\` — error from the last failed fetch (cleared on success)
- \`loading\` — true when fetching for the first time with no cached data
- \`fetching\` — true when any fetch is in progress (including background refetch)
- \`isError\` / \`isSuccess\` — boolean status helpers
- \`refetch()\` — manually trigger a fresh fetch
- \`cancel()\` — abort the current in-flight fetch
- Options: \`enabled\`, \`staleTime\`, \`gcTime\`, \`retry\`, \`refetchOnWindowFocus\`, \`refetchOnReconnect\`, \`refetchInterval\`, \`placeholderData\`

**\`useApi\` returns \`{ run, cancel, loading, data, error, status, variables, reset }\`:**
- \`run(inputs)\` — execute the API imperatively
- \`cancel()\` — cancel in-flight requests
- \`loading\` — boolean, true while the most recent call is in flight
- \`data\` — last successful response (persists across re-runs)
- \`error\` — error from the last failed run (cleared on next success)
- \`status\` — \`"idle" | "pending" | "success" | "error"\`
- \`reset()\` — reset state back to idle

**\`executeApi(apiName, inputs?, options?)\` returns \`Promise<TOutput>\`:**
- Plain async function — no React hooks, no caching, no reactive state
- Use for utility functions, event handlers, initialization logic, and non-component code
- Supports \`{ signal: AbortSignal }\` option for cancellation
- Errors are thrown as exceptions — use try/catch or .catch()

**CRITICAL: Use \`useApiData\` for data loading, \`useApi\` for mutations, and \`executeApi\` outside React components. Do NOT use \`useApi\` with a second argument for data loading — that pattern is deprecated.**

**CRITICAL: Do NOT create custom wrapper hooks around these hooks. Do NOT manage loading or data state with separate useState — the hooks handle this for you.**

### Critical Rules

1. **Import from the app wrappers**: \`useApi\` from \`@/hooks/useApi.js\`, \`useApiData\` from \`@/hooks/useApiData.js\`, \`executeApi\` from \`@/lib/executeApi.js\` — not from \`@superblocksteam/library\` (those wrappers wire \`createTypedApi\` / \`createTypedExecuteApi\` to your registry).
2. **MUST use the exact property name from \`server/apis/index.ts\`** as the first hook argument.
3. **Use \`useApiData\` for data loading, \`useApi\` for mutations, \`executeApi\` outside React**: Do NOT create separate useState for loading, response data, or error state
4. **Do NOT create wrapper hooks**: Use the hooks directly in components — no \`useGetUsers\` pattern needed
5. **ALWAYS check API input/output interfaces**: NEVER guess the response structure - use the actual interface defined by the API
6. **ALWAYS include all parameters in the function call**: NEVER omit parameters the API expects, even if they are optional, they should be included and passed as null
7. **ALWAYS include error handling**: In useApi, wrap \`run()\` in try/catch. In useApiData, check the \`error\` or \`isError\` fields. For executeApi, use try/catch or .catch().

### File Handling

**CRITICAL: Files must be wrapped in \`{ files: [...] }\` format.**

\`\`\`tsx
// ✅ CORRECT - Frontend: wrap files in { files: [...] }
const response = await runUploadApi({ userFile: { files: selectedFiles } });

// ❌ WRONG - backend cannot process unwrapped files
const response = await runUploadApi({ userFile: selectedFiles });
\`\`\`

\`\`\`typescript
// ✅ Backend API: access via .files property
const file = inputs.userFile.files[0];
// Available: file.name, file.size, file.type, file.extension
\`\`\`

**SDK APIs should model FilePicker values as objects with a \`files\` array and use the canonical file helpers from \`@superblocksteam/sdk-api\`.**

\`\`\`typescript
import { api, fileRefSchema, z } from "@superblocksteam/sdk-api";

export default api({
  name: "IngestUploadedTextFiles",
  description: "Reads uploaded text files.",
  input: z.object({
    documents: z.object({
      files: z.array(fileRefSchema),
    }),
  }),
  output: z.object({
    fileNames: z.array(z.string()),
  }),
  async run(_ctx, input) {
    return {
      fileNames: input.documents.files.map((file) => file.name),
    };
  },
});
\`\`\`

**Use \`readContentsAsync()\` on file objects when you need to process uploaded file contents in code.**
- Use \`readableFileSchema\` so the runtime-injected file methods stay typed and validated
- No mode argument: returns UTF-8 text for text files and base64 for binary files
- \`"raw"\`: returns a \`Buffer\` for binary-safe processing in JavaScript
- Use \`readContentsAsync()\` directly on the file object from \`input.<field>.files\`

\`\`\`typescript
import { api, readableFileSchema, z } from "@superblocksteam/sdk-api";

export default api({
  name: "SummarizeUpload",
  description: "Reads uploaded files in code.",
  input: z.object({
    artifact: z.object({
      files: z.array(readableFileSchema).min(1),
    }),
  }),
  output: z.object({
    fileName: z.string(),
    preview: z.string(),
    byteLength: z.number(),
  }),
  async run(_ctx, input) {
    const file = input.artifact.files[0];
    const text = await file.readContentsAsync();
    const raw = await file.readContentsAsync("raw");
    const buffer = Buffer.isBuffer(raw) ? raw : Buffer.from(raw, "utf8");

    return {
      fileName: file.name,
      preview: String(text).slice(0, 200),
      byteLength: buffer.length,
    };
  },
});
\`\`\`

**For S3 uploads, keep file references intact when using \`uploadMultipleObjects()\`.**
- **When uploading files from a FilePicker, always use \`uploadMultipleObjects()\` with \`fileRefSchema\`.** Never use \`uploadObject()\` for binary files (PDF, DOCX, images, etc.) — it stores the string body verbatim and does NOT decode base64, so binary data will be corrupted.
- Use \`uploadObject()\` only for plain-text or string content you have already constructed in code (e.g., JSON, CSV, plain text).
- Use \`fileRefSchema\` when you want the storage plugin to stream FilePicker-backed uploads by reference
- \`fileRefSchema\` is the canonical upload-by-reference contract for S3 and GCS style storage uploads
- Pass a serialized array of file objects containing \`name\`, \`type\`, and \`$superblocksId\`

\`\`\`typescript
import { api, fileRefSchema, s3, z } from "@superblocksteam/sdk-api";

const STORAGE = "your-s3-integration-id";

export default api({
  name: "UploadAttachmentsToS3",
  description: "Uploads FilePicker files to S3.",
  integrations: {
    storage: s3(STORAGE),
  },
  input: z.object({
    bucket: z.string(),
    attachments: z.object({
      files: z.array(fileRefSchema),
    }),
  }),
  output: z.object({
    uploaded: z.number(),
  }),
  async run(ctx, input) {
    const fileObjects = input.attachments.files.map((file) => ({
      name: file.name,
      type: file.type ?? "application/octet-stream",
      $superblocksId: file.$superblocksId,
    }));

    await ctx.integrations.storage.uploadMultipleObjects(
      input.bucket,
      JSON.stringify(fileObjects),
      { label: "Upload FilePicker attachments" }
    );

    return {
      uploaded: fileObjects.length,
    };
  },
});
\`\`\`

**Important:** Do not call \`readContentsAsync()\` before \`uploadMultipleObjects()\` unless you need to inspect or transform the bytes yourself. Passing the serialized file references lets the storage plugin fetch the content directly.

### Logging out of integrations

When building a "Log out" or "Sign out" button for apps that use oauth-like integrations use \`logoutIntegrations\` from the library to clear OAuth tokens:

\`\`\`typescript
import { logoutIntegrations } from "@superblocksteam/library";

const handleLogout = async () => {
  await logoutIntegrations();
  // Optionally redirect or show confirmation
};
\`\`\`

### Efficient-Friendly Patterns

Efficiency is key when building applications for production. You should always be thinking about patterns that will help you build efficient applications
when it comes to loading data from APIs.

Here are some examples (not exhaustive) that you should consider when building applications:
1. **Always show loading indicators on refetch**: When inputs change (e.g. filters, search), show a visual loading indicator while new data loads. Use \`fetching\` from useApiData.
2. **Loading State Hierarchy**:
  - No data yet (\`loading\`) → Full skeleton placeholder
  - Has data, refetching (\`fetching\` && !\`loading\`) → Keep showing current data with a subtle visual indicator: apply light opacity (e.g. \`opacity-70\`) to signal a refresh is in progress, plus a non-blocking label (e.g. "Updating…" text, small spinner, or thin progress bar). Do not use \`pointer-events-none\` — the content must remain fully interactive during refetch.
  - Error state (\`isError\`) → Show error with retry option, optionally keep stale data visible
3. **Debounce Rapid Requests**: Prevent multiple API calls in short succession
4. **Use useApiData for automatic refetching**: \`useApiData\` auto-refetches when inputs change and supports \`staleTime\`, \`refetchOnWindowFocus\`, and \`refetchOnReconnect\` options.

\`\`\`tsx
// ✅ CORRECT — subtle opacity + indicator, table stays interactive
const { data, loading, fetching, isError, error } = useApiData("GetOrders", { status: statusFilter, search });

if (loading) return <Skeleton />;                // First load: full skeleton
if (isError) return <ErrorBanner error={error} />;
return (
  <div>
    {fetching && <div className="text-xs text-muted-foreground">Updating…</div>}
    <div className={fetching ? "opacity-70" : ""}>
      <OrderTable orders={data.orders} />          {/* Dimmed but still interactive */}
    </div>
  </div>
);
\`\`\`

\`\`\`tsx
// ❌ WRONG — pointer-events-none disables the table, making it feel broken
return (
  <div className={fetching ? "opacity-50 pointer-events-none" : ""}>
    <OrderTable orders={data.orders} />
  </div>
);

// ❌ WRONG — no loading indicator when filters change. User sees stale data with no feedback.
const { data, loading } = useApiData("GetOrders", { status: statusFilter, search });

if (loading) return <Skeleton />;
return <OrderTable orders={data.orders} />;
\`\`\`

### Interpreting testApi Results

**CRITICAL**: \`success: false\` or missing = FAILURE. Never show success toast. Even when \`success: true\`, verify the output data is valid before confirming success to the user.
</apis>`;
}
/**
 * Tool guidance that differs by experience.
 *
 * @param sdkEnabled - Whether the SDK API experience is enabled
 * @returns Tool call guidance section content
 */
export function buildApiToolGuidance(sdkEnabled) {
    if (sdkEnabled) {
        return `**Deleting APIs:** Remove the API from \`server/apis/index.ts\`, then delete its implementation. If the API is part of a larger feature, leave the rest of the code alone.

**Creating APIs:** Register every API in \`server/apis/index.ts\` so \`useApi\` gets types and the runtime can resolve entry points. Use \`.js\` extensions in import specifiers (ESM). Prefer domain folders and descriptive file names, not \`server/apis/SomeApi/api.ts\` by default.

\`\`\`typescript
// server/apis/index.ts — one module per API (default export)
import CreateOrder from './orders/create-order.js';
import GetUsers from './users/get-users.js';
const apis = { CreateOrder, GetUsers } as const;
export default apis;
export type ApiRegistry = typeof apis;
\`\`\`

**Multiple APIs in one module** — use named imports when several \`api({...})\` definitions share a file (e.g. related mutations):

\`\`\`typescript
// server/apis/index.ts
import { ArchiveUser, UpdateProfile } from './users/account-mutations.js';
const apis = { ..., ArchiveUser, UpdateProfile } as const;
export default apis;
export type ApiRegistry = typeof apis;
\`\`\`

**Required API fields:** Every API must include:
- \`name\`: Unique identifier for the API (used in logs and debugging)
- \`input\`: Zod schema for input validation
- \`output\`: Zod schema for output validation
- \`run\`: The implementation function`;
    }
    return `**Deleting APIs:** When deleting an API, only delete the \`apis/ApiName.ts\` virtual file. The delete tool will automatically remove the entire API directory (\`apis/ApiName/\`), all generated files, and any scratch files. Do NOT make multiple delete calls for the same API.`;
}
//# sourceMappingURL=api-prompts.js.map