import { createElement, type ComponentType, type ReactNode } from "react";
import type { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
import { HttpClientRequest } from "effect/unstable/http";
import * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi";
export { Schema } from "effect";
export { HttpApi, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
export * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
export * as Atom from "effect/unstable/reactivity/Atom";
export * as AtomHttpApi from "effect/unstable/reactivity/AtomHttpApi";
export { useAtomValue, useAtomSet, useAtomMount, useAtomRefresh } from "@effect/atom-react";
export interface PageDecl {
    /** Path relative to the plugin's mount point, e.g. `/`, `/edit/$id`. */
    readonly path: string;
    readonly component: ComponentType;
    /** Optional sidebar nav metadata — the host renders these alongside its
     *  own nav links. Omit to register a page without a nav entry. */
    readonly nav?: {
        readonly label: string;
        readonly section?: string;
    };
}
export interface WidgetProps {
    readonly scopeId?: string;
}
export interface WidgetDecl {
    readonly id: string;
    readonly component: ComponentType<WidgetProps>;
    readonly size?: "half" | "full";
}
/**
 * Open record of host-defined slot components a plugin can fill. Slot
 * names are part of the host UI contract — plugins opt in by registering
 * a component for the slot they care about. Adding a slot is a host-side
 * change; plugin authors don't define new slots.
 */
export type SlotComponent = ComponentType<Record<string, unknown>>;
export interface IntegrationPreset {
    /** Unique id (e.g. "stripe", "github-graphql"). */
    readonly id: string;
    readonly name: string;
    readonly summary: string;
    /** URL passed as `initialUrl` to the add form. Omit for presets that
     *  don't use a URL (e.g. stdio MCP presets). */
    readonly url?: string;
    /** Endpoint passed to agent-facing probe/add tools when their schema
     *  uses `endpoint` instead of `url`. */
    readonly endpoint?: string;
    /** Optional icon URL (favicon, logo). */
    readonly icon?: string;
    /** Shown in the top-level grid on the integrations page when true. */
    readonly featured?: boolean;
}
export interface IntegrationAccountHandoff {
    /** Changes on each handoff URL, so the accounts UI can open once per link. */
    readonly key: string;
    readonly owner?: "org" | "user";
    /** Auth template/method to preselect when present. */
    readonly template?: string;
    /** Non-secret connection label to prefill. */
    readonly label?: string;
}
/** Outcome of applying an edit-sheet section's staged change. `summary` is
 *  toasted on success; `ok: false` keeps the sheet open (the section renders
 *  its own error inline). */
export type EditSheetApplyResult = {
    readonly ok: true;
    readonly summary: string | null;
} | {
    readonly ok: false;
};
export interface EditSheetSectionProps {
    readonly sourceId: string;
    readonly onPendingChange?: (apply: (() => Promise<EditSheetApplyResult>) | null) => void;
}
export interface IntegrationPlugin {
    /** Unique key matching the SDK plugin id (e.g. "openapi"). */
    readonly key: string;
    readonly label: string;
    readonly add: ComponentType<{
        /** Called when the integration has been registered. Receives the slug of
         *  the just-registered integration, so the host can route to its detail
         *  hub (`/integrations/<slug>`). Optional so existing no-arg calls still
         *  typecheck while plugins are threading the slug through. */
        readonly onComplete: (slug?: string) => void;
        readonly onCancel: () => void;
        readonly initialUrl?: string;
        readonly initialPreset?: string;
        readonly initialNamespace?: string;
    }>;
    /** Legacy full-page edit surface. No host renders this anymore — plugin
     *  configuration lives in the integration Edit sheet via `editSheet`. */
    readonly edit?: ComponentType<{
        readonly sourceId: string;
        readonly onSave: () => void;
    }>;
    /** Plugin-owned configuration rendered inside the integration's Edit sheet,
     *  below the shared metadata fields (e.g. the OpenAPI spec-update controls).
     *  The sheet has ONE Save: the section stages its pending change locally and
     *  reports it through `onPendingChange` — a thunk that applies the staged
     *  change. Save runs the metadata update, then the staged apply; a failed
     *  apply keeps the sheet open with the section showing its own error. */
    readonly editSheet?: ComponentType<EditSheetSectionProps>;
    readonly summary?: ComponentType<{
        readonly sourceId: string;
        readonly variant?: "badge" | "panel";
        readonly onAction?: () => void;
    }>;
    /** Renders the integration's Accounts hub (auth methods + connections) inside
     *  the detail page's Accounts tab. Plugins that declare auth methods implement
     *  this; the page falls back to a generic accounts list when absent. */
    readonly accounts?: ComponentType<{
        readonly sourceId: string;
        readonly integrationName: string;
        readonly accountHandoff?: IntegrationAccountHandoff | null;
    }>;
    readonly presets?: readonly IntegrationPreset[];
    /** Trigger early download of the plugin's lazy component chunks (add/edit/etc.).
     *  Call from the host on intent (hover/focus) so the chunks land before the
     *  user navigates into the add page. Idempotent. */
    readonly preload?: () => void;
}
export interface SecretProviderPlugin {
    /** Unique key matching the SDK plugin id (e.g. "onepassword"). */
    readonly key: string;
    readonly label: string;
    readonly settings: ComponentType<Record<string, never>>;
}
export interface ClientPluginSpec<TId extends string = string> {
    readonly id: TId;
    readonly pages?: readonly PageDecl[];
    readonly widgets?: readonly WidgetDecl[];
    readonly slots?: Record<string, SlotComponent>;
    /** Integration plugin contribution — populated by plugins that expose
     *  `kind` rows in the core `source` table (openapi, mcp, graphql).
     *  The host's integrations page derives its provider
     *  list from the union of every loaded plugin's `integrationPlugin`. */
    readonly integrationPlugin?: IntegrationPlugin;
    /** Secret provider plugin contribution — populated by plugins that
     *  also ship a `secretProviders` (or related) server-side capability
     *  AND want to expose a settings card on the host's secrets page. */
    readonly secretProviderPlugin?: SecretProviderPlugin;
}
/**
 * Identity factory — returns the spec unchanged but pins the inferred
 * literal type of `id` so the host can index plugin records by id with
 * full autocomplete. Plugins export this as their package's default
 * (or named) export from `./client`.
 */
export declare const defineClientPlugin: <const TId extends string>(spec: ClientPluginSpec<TId>) => ClientPluginSpec<TId>;
export interface CreatePluginAtomClientOptions {
    /** Override the base URL. Defaults to `/api` (host strips this prefix
     *  when forwarding to the Effect handler) — same convention as the
     *  core `ExecutorApiClient`. */
    readonly baseUrl?: string | (() => string);
    /** Optional dynamic Authorization header for hosts whose active
     *  Executor Server Connection requires Basic or Bearer auth. */
    readonly authorizationHeader?: string | null | (() => string | null);
    /** Optional dynamic request headers supplied by the host shell. */
    readonly headers?: Readonly<Record<string, string | null | undefined>> | (() => Readonly<Record<string, string | null | undefined>>);
}
export interface PluginAtomClientRequestTransformOptions {
    readonly baseUrl?: () => string;
    readonly authorizationHeader?: string | null | (() => string | null);
    readonly headers?: Readonly<Record<string, string | null | undefined>> | (() => Readonly<Record<string, string | null | undefined>>);
}
/** @internal */
export declare const applyPluginAtomClientRequestTransform: (request: HttpClientRequest.HttpClientRequest, options: PluginAtomClientRequestTransformOptions) => HttpClientRequest.HttpClientRequest;
/**
 * Build a typed reactive client for a plugin's HttpApiGroup.
 *
 *   const FooClient = createPluginAtomClient(FooApi)
 *   export const fooThings = FooClient.query("foo", "listThings", { ... })
 *   export const fooSync   = FooClient.mutation("foo", "syncThing")
 *
 * Each plugin gets a private service Tag (`Plugin_<id>Client`) keyed by
 * the group's `identifier`, so multiple plugins coexist in the same
 * React tree without colliding.
 */
export declare const createPluginAtomClient: <G extends HttpApiGroup.HttpApiGroup<string, HttpApiEndpoint.Any, boolean>>(group: G, options?: CreatePluginAtomClientOptions) => AtomHttpApi.AtomHttpApiClient<`Plugin_${G["identifier"]}Client`, `Plugin_${string}Client`, G>;
export interface ExecutorPluginsProviderProps {
    readonly plugins: readonly ClientPluginSpec[];
    readonly children: ReactNode;
}
export declare function ExecutorPluginsProvider(props: ExecutorPluginsProviderProps): ReturnType<typeof createElement>;
/** Full list of loaded `ClientPluginSpec` values. */
export declare const useClientPlugins: () => readonly ClientPluginSpec[];
/** Integration plugins extracted from `clientPlugins[].integrationPlugin`. */
export declare const useIntegrationPlugins: () => readonly IntegrationPlugin[];
/** Secret-provider plugins extracted from `clientPlugins[].secretProviderPlugin`. */
export declare const useSecretProviderPlugins: () => readonly SecretProviderPlugin[];
//# sourceMappingURL=client.d.ts.map