/**
 * Fetch OpenAI org costs + usage for the window. Iterates pagination
 * (page_token) until exhausted.
 *
 * Reference: GET /v1/organization/costs
 *   query: start_time (unix sec), end_time (unix sec), bucket_width=1d,
 *          group_by[]=project_id&group_by[]=line_item, page
 *   response shape:
 *     {
 *       object: 'page',
 *       data: [
 *         { object: 'bucket', start_time, end_time,
 *           results: [{ amount: { value, currency }, project_id, line_item, ... }] }
 *       ],
 *       has_more: boolean,
 *       next_page: '...'
 *     }
 *
 * We normalize each result row into a NormalizedSpendRecord.
 *
 * @param {{ startMs: number, endMs: number, groupBy?: string[] }} opts
 * @returns {Promise<{ ok: true, items: NormalizedSpendRecord[], rawBuckets: number }>}
 */
export function fetchOpenAICosts({ startMs, endMs, groupBy }: {
    startMs: number;
    endMs: number;
    groupBy?: string[];
}): Promise<{
    ok: true;
    items: NormalizedSpendRecord[];
    rawBuckets: number;
}>;
/**
 * Fetch the OpenAI project catalog (id → name). Useful for the digest
 * to display "acme-prod" instead of "proj_abc123". Cheap — usually
 * <50 projects. Returns Map<projectId, projectName>.
 */
export function fetchOpenAIProjects(): Promise<Map<any, any>>;
/**
 * Fetch Anthropic cost report.
 *
 * Reference: GET /v1/organizations/cost_report
 *   query: starting_at (ISO), ending_at (ISO), bucket=1d,
 *          group_by[]=workspace_id&group_by[]=model
 *   headers: x-api-key, anthropic-version: 2023-06-01
 *   response shape (beta):
 *     {
 *       data: [
 *         { starting_at, ending_at, currency: 'USD',
 *           results: [{ amount: '0.42', workspace_id, model, ... }] }
 *       ],
 *       has_more, next_page
 *     }
 *
 * Anthropic returns cost amounts as decimal strings (cents-precision).
 * Multiply-by-100 then parse-int → exact-cents arithmetic OK; for the
 * digest we just parseFloat (drift over 28 days is negligible).
 */
export function fetchAnthropicCosts({ startMs, endMs, groupBy }: {
    startMs: any;
    endMs: any;
    groupBy?: string[];
}): Promise<{
    ok: boolean;
    items: {
        provider: string;
        day: any;
        costUsd: number;
        workspaceId: any;
        apiKeyId: any;
        model: any;
        tokensIn: number;
        tokensOut: number;
        cachedTokens: number;
    }[];
    rawBuckets: number;
}>;
/**
 * Fetch Anthropic workspace catalog (id → name).
 */
export function fetchAnthropicWorkspaces(): Promise<Map<any, any>>;
/**
 * Fetch Cursor team daily-usage data. The endpoint returns per-day,
 * per-user, per-model rolls — we flatten to NormalizedSpendRecord.
 *
 * Reference: GET /teams/daily-usage-data
 *   query: startDate (YYYY-MM-DD), endDate (YYYY-MM-DD)
 *   header: Authorization: Bearer <admin-key>
 *   response shape (Cursor Admin API, 2026):
 *     {
 *       data: [
 *         { date, totalCents, userMetrics: [
 *             { email, totalCents, modelUsage: [
 *                 { model, requestCount, acceptedLines, suggestedLines } ] } ]
 *         }
 *       ]
 *     }
 *
 * acceptanceRate = acceptedLines / suggestedLines (per model per user
 * per day). The digest aggregates across users for the team-level rate.
 */
export function fetchCursorSpend({ startMs, endMs }: {
    startMs: any;
    endMs: any;
}): Promise<{
    ok: boolean;
    items: ({
        provider: string;
        day: any;
        costUsd: number;
        userEmail: any;
        model: any;
        requestCount: number;
        acceptanceRate: number;
    } | {
        provider: string;
        day: any;
        costUsd: number;
        userEmail: any;
        model?: undefined;
        requestCount?: undefined;
        acceptanceRate?: undefined;
    })[];
    rawBuckets: number;
}>;
/**
 * Pull all three providers in parallel. Returns a per-provider result
 * map so the analyze node can degrade gracefully when one provider
 * fails (not connected, key revoked, upstream 500, etc.).
 *
 * @param {{ startMs: number, endMs: number }} opts
 * @returns {Promise<{
 *   openai:    { ok: true, items: NormalizedSpendRecord[] } | { ok: false, error: string },
 *   anthropic: { ok: true, items: NormalizedSpendRecord[] } | { ok: false, error: string },
 *   cursor:    { ok: true, items: NormalizedSpendRecord[] } | { ok: false, error: string },
 *   totals:    { provider: string, totalUsd: number }[],
 * }>}
 */
export function fetchAllProviders({ startMs, endMs }: {
    startMs: number;
    endMs: number;
}): Promise<{
    openai: {
        ok: true;
        items: NormalizedSpendRecord[];
    } | {
        ok: false;
        error: string;
    };
    anthropic: {
        ok: true;
        items: NormalizedSpendRecord[];
    } | {
        ok: false;
        error: string;
    };
    cursor: {
        ok: true;
        items: NormalizedSpendRecord[];
    } | {
        ok: false;
        error: string;
    };
    totals: {
        provider: string;
        totalUsd: number;
    }[];
}>;
/**
 * Group an array of normalized records by a key + sum costUsd.
 * Convenience for analyze nodes — saves writing the same reduce 5x.
 *
 * @param {NormalizedSpendRecord[]} items
 * @param {(item: NormalizedSpendRecord) => string} keyFn
 * @returns {{ key: string, totalUsd: number, count: number }[]}  sorted desc by totalUsd
 */
export function groupByKey(items: NormalizedSpendRecord[], keyFn: (item: NormalizedSpendRecord) => string): {
    key: string;
    totalUsd: number;
    count: number;
}[];
/**
 * Compute mean + stddev over a numeric window. Used by analyze nodes
 * to flag this-week-vs-baseline anomalies (>2σ).
 *
 * @param {number[]} xs
 * @returns {{ mean: number, stddev: number }}
 */
export function meanStddev(xs: number[]): {
    mean: number;
    stddev: number;
};
/**
 * Normalized record shape — one entry per (provider × day × dimension)
 * after each provider's response is unpacked. Optional fields are
 * provider-specific and may be undefined.
 *
 * @typedef {Object} NormalizedSpendRecord
 * @property {'openai'|'anthropic'|'cursor'} provider
 * @property {string} day                 ISO date (YYYY-MM-DD)
 * @property {number} costUsd             USD, positive
 * @property {string} [projectId]         OpenAI project_id
 * @property {string} [projectName]       OpenAI project metadata (joined on lookup)
 * @property {string} [workspaceId]       Anthropic workspace_id
 * @property {string} [workspaceName]     Anthropic workspace metadata
 * @property {string} [apiKeyId]          OpenAI / Anthropic api_key_id
 * @property {string} [userEmail]         Cursor team-member email
 * @property {string} [model]             Model id (when grouped by model)
 * @property {number} [tokensIn]
 * @property {number} [tokensOut]
 * @property {number} [cachedTokens]
 * @property {number} [requestCount]      Cursor
 * @property {number} [acceptanceRate]    Cursor: 0..1
 */
/**
 * Marketplace-gating skill declarations. The id matches the
 * REQUIRED_INTEGRATION_MAP entry on the backend; the template's node
 * just declares `skills: [SKILLS.OPENAI_BILLING, ...]` and the bundler
 * derives required integrations automatically.
 *
 * These are intentionally minimal — no MCP tools, no resolve(), no
 * prompt fragments. The skill object exists ONLY to register the
 * integration dependency. Runtime behavior lives in the fetch fns below.
 */
export const openaiBillingSkill: Readonly<{
    id: "openai_billing";
    requiresIntegration: "openai_billing";
    description: "OpenAI organization billing/usage admin API (paste sk-admin-... key)";
}>;
export const anthropicBillingSkill: Readonly<{
    id: "anthropic_billing";
    requiresIntegration: "anthropic_billing";
    description: "Anthropic organization cost/usage admin API (paste sk-ant-admin-... key)";
}>;
export const cursorAdminSkill: Readonly<{
    id: "cursor_admin";
    requiresIntegration: "cursor_admin";
    description: "Cursor Team/Enterprise admin API (paste admin key)";
}>;
/**
 * Normalized record shape — one entry per (provider × day × dimension)
 * after each provider's response is unpacked. Optional fields are
 * provider-specific and may be undefined.
 */
export type NormalizedSpendRecord = {
    provider: "openai" | "anthropic" | "cursor";
    /**
     * ISO date (YYYY-MM-DD)
     */
    day: string;
    /**
     * USD, positive
     */
    costUsd: number;
    /**
     * OpenAI project_id
     */
    projectId?: string;
    /**
     * OpenAI project metadata (joined on lookup)
     */
    projectName?: string;
    /**
     * Anthropic workspace_id
     */
    workspaceId?: string;
    /**
     * Anthropic workspace metadata
     */
    workspaceName?: string;
    /**
     * OpenAI / Anthropic api_key_id
     */
    apiKeyId?: string;
    /**
     * Cursor team-member email
     */
    userEmail?: string;
    /**
     * Model id (when grouped by model)
     */
    model?: string;
    tokensIn?: number;
    tokensOut?: number;
    cachedTokens?: number;
    /**
     * Cursor
     */
    requestCount?: number;
    /**
     * Cursor: 0..1
     */
    acceptanceRate?: number;
};
