import type { ApplicationService } from '@adonisjs/core/types';
import type { MediaAttachmentsOptions } from '../media/media-attachment-staging.js';
import type { HybridRetrieverOptions } from '../rag/hybrid-retriever.js';
import type { IngestDocument } from '../rag/ingest.js';
import type { PgFullTextOptions, PgVectorColumns, PgVectorMetric, PgVectorStoreOptions } from '../rag/pg-vector-store.js';
import type { QdrantClientLike, QdrantMetric } from '../rag/qdrant-store.js';
import type { RedisStreamClient } from '../redis-stream-client.js';
import type { ActorDirectory } from '../spi/actor-directory.js';
import type { AgentStore } from '../spi/agent-store.js';
import type { AttachmentStagingDescription, AttachmentStagingStore } from '../spi/attachment-staging.js';
import type { EmbeddingProvider } from '../spi/embedding-provider.js';
import type { AgentGovernanceQueries } from '../spi/governance-queries.js';
import type { AgentPricingStore } from '../spi/pricing-store.js';
import type { Retriever } from '../spi/retriever.js';
import type { TokenStreamSink } from '../spi/token-stream-sink.js';
import type { LucidDatabaseLike } from './lucid.js';
/**
 * Runtime context a {@link StoreFactory} thunk receives when the agent provider builds the configured
 * store at boot. Carries the booted application so a driver can resolve a peer's service if it needs to.
 */
export interface StoreContext {
    app: ApplicationService;
}
/**
 * A configured agent store: a thunk the agent provider calls at boot to build the {@link AgentStore}.
 * Each factory lazily imports its peer dependency (`@adonisjs/lucid`) inside the thunk, so the driver
 * is only loaded when it is actually selected — keeping that package optional.
 */
export type StoreFactory = (ctx: StoreContext) => Promise<AgentStore>;
/**
 * If `factory` is a `stores.lucid()` store factory, returns its connection (`null` = the app's default
 * connection); otherwise `undefined`. The provider uses this to mirror the main store's Lucid
 * connection when `pricingStore`/`governanceQueries` are left at their defaults.
 */
export declare function lucidStoreConnection(factory: unknown): string | null | undefined;
/** Options for the Lucid-backed persistent store. */
export interface LucidStoreConfig {
    /** Lucid connection name to use. Defaults to the `Database` default connection. */
    connection?: string;
    /**
     * Provision the agent tables on first use — the lib manages its own schema (the ecosystem
     * convention, mirroring durable/authz). Default `true`. Set `false` to run the published migration
     * instead. Governs the pricing store and governance read-model too, which share these tables.
     */
    autoCreateTables?: boolean;
}
/** Options for the in-memory store (single-process, non-durable). */
export type MemoryStoreConfig = Record<string, never>;
/**
 * The store factory namespace used in `config/agent.ts`:
 *
 * ```ts
 * import { defineConfig, stores } from '@adonis-agora/agent'
 *
 * export default defineConfig({
 *   store: 'lucid',
 *   stores: {
 *     memory: stores.memory(),
 *     lucid: stores.lucid({ connection: 'pg' }),
 *   },
 * })
 * ```
 *
 * Each factory returns a {@link StoreFactory} — a lazy thunk. Calling it in the config file costs
 * nothing; the peer dependency is only imported when the provider builds the selected store at boot.
 */
export declare const stores: {
    /** In-memory store — single-process, non-durable. Handy for tests and scratch/dev apps. */
    memory(_config?: MemoryStoreConfig): StoreFactory;
    /** Persist threads/messages/tool-calls/usage in SQL via `@adonisjs/lucid`. */
    lucid(config?: LucidStoreConfig): StoreFactory;
};
/** Runtime context a {@link PricingFactory} thunk receives — the booted application. */
export type PricingContext = StoreContext;
/** A configured pricing store: a lazy thunk the agent provider calls at boot. */
export type PricingFactory = (ctx: PricingContext) => AgentPricingStore | Promise<AgentPricingStore>;
/** Options for the Lucid-backed pricing store. */
export interface LucidPricingConfig {
    /** Lucid connection name to use. Defaults to the `Database` default connection. */
    connection?: string;
    /**
     * Provision the shared agent tables on first use. Default `true` (the ecosystem convention) — this
     * is what lets a pricing seed run before the first agent run. Set `false` to run the migration.
     */
    autoCreateTables?: boolean;
}
/**
 * The pricing factory namespace used in `config/agent.ts`, mirroring {@link stores}:
 *
 * ```ts
 * export default defineConfig({
 *   pricingStore: pricingStores.lucid(),
 * })
 * ```
 *
 * Seed model prices once (e.g. in a command) with `seedModelPrices(store, [...])`.
 */
export declare const pricingStores: {
    /** In-memory pricing table — for tests and the offline demo. */
    memory(): PricingFactory;
    /** Persist per-model prices in SQL (the `agent_model_pricing` table) via `@adonisjs/lucid`. */
    lucid(config?: LucidPricingConfig): PricingFactory;
};
/**
 * Runtime context a {@link GovernanceQueriesFactory} thunk receives — the {@link StoreContext} plus the
 * already-resolved {@link AgentPricingStore} (when the app configured one), so the read-model prices its
 * cost rollups against the SAME live prices the loop's cost fold uses. The provider resolves pricing
 * first, then the governance queries, then passes it here (the way a store-reading factory is handed the
 * built store). `pricingStore` is absent when the app configured none → the read-model reports 0 cost.
 */
export interface GovernanceQueriesContext extends StoreContext {
    pricingStore?: AgentPricingStore;
}
/**
 * A configured governance read-model: a lazy thunk the agent provider calls at boot to build the
 * {@link AgentGovernanceQueries} the optional `/agent/governance/*` read routes serve from. Each factory
 * lazily imports its peer inside the thunk (like {@link stores}), so nothing loads until governance is
 * actually selected.
 */
export type GovernanceQueriesFactory = (ctx: GovernanceQueriesContext) => AgentGovernanceQueries | Promise<AgentGovernanceQueries>;
/** Options for the Lucid-backed governance read-model. */
export interface LucidGovernanceConfig {
    /** Lucid connection name to use. Defaults to the `Database` default connection. */
    connection?: string;
    /**
     * Provision the shared agent tables on first use. Default `true` (the ecosystem convention) — lets
     * the governance routes / dashboard answer on a fresh deploy before the first agent run. Set
     * `false` to run the migration.
     */
    autoCreateTables?: boolean;
}
/**
 * The governance-queries factory namespace used in `config/agent.ts`, mirroring {@link pricingStores}:
 *
 * ```ts
 * export default defineConfig({
 *   pricingStore: pricingStores.lucid(),
 *   governanceQueries: governanceQueries.lucid(),
 * })
 * ```
 *
 * The Lucid read-model aggregates the same five agent tables the store writes and prices cost against
 * the configured `pricingStore`; wiring it mounts the `/agent/governance/*` read routes.
 */
export declare const governanceQueries: {
    /** Aggregate the five agent tables in SQL via `@adonisjs/lucid`, priced against the pricing store. */
    lucid(config?: LucidGovernanceConfig): GovernanceQueriesFactory;
};
/** Runtime context a {@link RetrieverFactory} thunk receives — the booted application. */
export type RetrieverContext = StoreContext;
/**
 * A configured retriever: a lazy thunk the agent provider calls at boot to build the {@link Retriever}
 * wired into inject-mode retrieval. Each factory imports the RAG stack inside the thunk, so nothing is
 * loaded until a retriever is actually selected — mirroring {@link stores}.
 */
export type RetrieverFactory = (ctx: RetrieverContext) => Retriever | Promise<Retriever>;
/** A lazy {@link EmbeddingProvider} factory, so an embedding SDK peer imports only when the config loads. */
export type EmbeddingFactory = () => EmbeddingProvider | Promise<EmbeddingProvider>;
/** Options for the in-memory embedding retriever (cosine over a Map, no infra). */
export interface MemoryRetrieverConfig {
    /** The embedding provider (query + ingestion), or a lazy factory so its SDK peer loads lazily. */
    embedder: EmbeddingProvider | EmbeddingFactory;
    /** Documents to ingest at boot (chunk → embed → index). Omit to ingest separately at runtime. */
    documents?: IngestDocument[];
    /** Target max characters per chunk. Default 800. */
    chunkSize?: number;
    /** Characters of overlap between chunks. Default 100. */
    overlap?: number;
}
/** Options for the pgvector-backed retriever (production RAG over `@adonisjs/lucid` + pgvector). */
export interface PgVectorRetrieverConfig {
    /** The embedding provider (query + ingestion), or a lazy factory so its SDK peer loads lazily. */
    embedder: EmbeddingProvider | EmbeddingFactory;
    /**
     * A structural Lucid DB handle (bring-your-own). Omit to resolve `@adonisjs/lucid`'s default `db`
     * service lazily inside the thunk (optionally on `connection`), keeping the peer optional.
     */
    db?: LucidDatabaseLike;
    /** Lucid connection name (used only when `db` is omitted). Defaults to the `Database` default. */
    connection?: string;
    /** Chunk table name. Default `agent_rag_chunks`. Validated against a strict identifier regex. */
    table?: string;
    /**
     * Embedding width — must match the model (e.g. 1536 for text-embedding-3-small). Default 1536. A list
     * makes a mixed-dimension table (one partial HNSW index per width); see `PgVectorStoreOptions`.
     */
    dimension?: number | readonly number[];
    /** Similarity metric / distance operator (`cosine` default, `l2`, `inner`). */
    metric?: PgVectorMetric;
    /** Override the physical column names (each validated). */
    columns?: PgVectorColumns;
    /** Allow chunks without an embedding (`embedding: []` → `NULL`). Default `false`. */
    nullableEmbeddings?: boolean;
    /** pgvector ≥ 0.8 iterative index scan for filtered searches. Default off. */
    iterativeScan?: PgVectorStoreOptions['iterativeScan'];
    /** `hnsw.ef_search` for searches. */
    efSearch?: number;
    /** Rows per multi-row upsert statement. Default 100. */
    upsertBatchSize?: number;
    /**
     * Add a Postgres full-text leg: the store becomes a `PgLexicalVectorStore` and the retriever a
     * `HybridRetriever` fusing vector + full-text search with reciprocal rank fusion (`{}` for the
     * defaults: `simple` config over `to_tsvector(text)`). Needs the GIN index — `ensureSchema` or the
     * migration creates it. Default off (vector search only). `minScore` then applies to neither leg: a
     * fused rank is not a similarity.
     */
    fullText?: PgFullTextOptions & {
        hybrid?: HybridRetrieverOptions;
    };
    /**
     * Provision the `vector` extension, table, and index at boot (idempotent DDL). Handy for tests/scripts;
     * production should run the bundled migration instead. Default `false`.
     */
    ensureSchema?: boolean;
    /** Documents to ingest at boot (chunk → embed → upsert). Omit to ingest separately at runtime. */
    documents?: IngestDocument[];
    /** Target max characters per chunk. Default 800. */
    chunkSize?: number;
    /** Characters of overlap between chunks. Default 100. */
    overlap?: number;
}
/** Options for the Qdrant-backed retriever (production RAG over a managed vector DB, e.g. GuaraCloud). */
export interface QdrantRetrieverConfig {
    /** Embedder (or a lazy factory) — the same shape as `pgvector`/`memory`. */
    embedder: EmbeddingProvider | (() => Promise<EmbeddingProvider>);
    /** Qdrant URL, used when no `client` is passed. Default `http://localhost:6333`. */
    url?: string;
    /** Qdrant API key (optional). */
    apiKey?: string;
    /** A ready structural client — for programmatic use and tests; absent → built from `url`/`apiKey`. */
    client?: QdrantClientLike;
    /** Collection name. Default `agent_rag_chunks`. */
    collection?: string;
    /** Embedding width — must match the model. Default 1536. */
    dimension?: number;
    /** Similarity metric. Default `cosine`. */
    metric?: QdrantMetric;
    /** Provision the collection (dimension + metric) at boot — handy for tests and ingestion. */
    ensureCollection?: boolean;
    /** Documents to ingest at boot (optional, same shape as `pgvector`). */
    documents?: IngestDocument[];
    /** Target max characters per chunk. Default 800. */
    chunkSize?: number;
    /** Characters of overlap between chunks. Default 100. */
    overlap?: number;
}
/**
 * The retriever factory namespace used in `config/agent.ts`, mirroring {@link stores}:
 *
 * ```ts
 * export default defineConfig({
 *   model: () => aiSdkModel(openai('gpt-4o-mini')),
 *   retriever: retrievers.memory({ embedder: myEmbedder, documents: [...] }),
 *   retrievalTopK: 5,
 * })
 * ```
 *
 * Use `retrievers.pgvector({...})` for the production pgvector/Lucid store or `retrievers.qdrant({...})`
 * for a managed Qdrant collection; `retrievers.memory` covers tests and small/embedded corpora.
 */
export declare const retrievers: {
    /** In-memory embedding retriever — cosine over a Map, single-process. Handy for tests and dev apps. */
    memory(config: MemoryRetrieverConfig): RetrieverFactory;
    /**
     * Production pgvector retriever — cosine/L2/inner similarity over a `vector(N)` column via
     * `@adonisjs/lucid` (raw SQL for the pgvector operators; the embedding is a `?::vector` binding). The
     * Lucid peer is imported lazily inside the thunk (unless a structural `db` is passed), so it stays
     * optional. Pass `ensureSchema: true` to provision the extension/table/index at boot for tests.
     */
    pgvector(config: PgVectorRetrieverConfig): RetrieverFactory;
    /**
     * Production Qdrant retriever — cosine/dot/euclid via `@qdrant/js-client-rest`. The client is
     * imported LAZILY inside the thunk (unless a structural `client` is passed), so the package stays an
     * OPTIONAL peer. Pass `ensureCollection: true` to provision the collection at boot.
     */
    qdrant(config: QdrantRetrieverConfig): RetrieverFactory;
};
/**
 * Runtime context an {@link AttachmentStagingFactory} thunk receives — the booted application, and
 * the agent store the provider built (what `attachmentStores.media()` asks which media a live
 * message of the actor carries).
 */
export interface AttachmentStagingContext extends StoreContext {
    agentStore?: AgentStore;
}
/**
 * A configured attachment-staging store: a lazy thunk the agent provider calls at boot to build the
 * {@link AttachmentStagingStore} the optional `POST /agent/attachments` upload route stages through.
 * Each factory imports its impl inside the thunk (like {@link stores}), so nothing is loaded until a
 * staging store is actually selected.
 */
export type AttachmentStagingFactory = (ctx: AttachmentStagingContext) => AttachmentStagingStore | Promise<AttachmentStagingStore>;
/**
 * The attachment-store factory namespace used in `config/agent.ts`:
 *
 * ```ts
 * export default defineConfig({
 *   model,
 *   attachments: attachmentStores.media(), // uploads on @adonis-agora/media, any Drive disk
 * })
 * ```
 *
 * Bring your own storage by passing an {@link AttachmentStagingStore} instance instead.
 */
export declare const attachmentStores: {
    /**
     * Uploads stored through `@adonis-agora/media` (register `@adonis-agora/media/media_provider`
     * and configure `config/media.ts`): media rows in their own collection, one owner per actor, on
     * any Drive disk. The url the model fetches is minted per request — signed and short-lived by
     * default — so it is never taken from the client. See `MediaAttachmentsOptions`.
     */
    media(options?: MediaAttachmentsOptions): AttachmentStagingFactory;
    /**
     * In memory — the uploaded bytes become a `data:` url the model reads inline. Single-process and
     * lost on restart: tests and demos. `limits` sets the size cap / content types it declares.
     */
    memory(limits?: AttachmentStagingDescription): AttachmentStagingFactory;
};
/**
 * A configured {@link TokenStreamSink}: a lazy thunk the agent provider calls at boot to build the live
 * token transport (the "data plane"). Each factory imports its impl — and, for Redis, its optional
 * driver — inside the thunk, so nothing loads until the sink is actually selected. Assignable to the
 * `sink` field's `SinkFactory`.
 */
export type TokenSinkFactory = (ctx: StoreContext) => TokenStreamSink | Promise<TokenStreamSink>;
/** Options for the Redis multi-replica token-stream sink. */
export interface RedisTokenSinkConfig {
    /** `@adonisjs/redis` connection name. Omit for the default connection. */
    connection?: string;
    /** Key/channel namespace. Defaults to `agent:stream`. */
    keyPrefix?: string;
    /**
     * TTL (seconds) for a run's replay keys so they self-expire — the framework never calls the sink's
     * `close()`, so without a TTL the buffer would accumulate in Redis forever. Sliding window refreshed
     * on every write. Defaults to 3600 (1h). Set `0` to disable (retain until manual cleanup).
     */
    ttlSeconds?: number;
    /**
     * Bring-your-own {@link RedisStreamClient} adapter (over `ioredis`, `node-redis`, ...). When set, the
     * `@adonisjs/redis` peer is NOT imported — the factory uses this client directly. Handy for tests and
     * non-Adonis Redis drivers.
     */
    client?: RedisStreamClient;
}
/** Options for the Lucid (SQL) multi-replica token-stream sink — several replicas, no Redis. */
export interface LucidTokenSinkConfig {
    /** Lucid connection name to use. Defaults to the `Database` default connection. */
    connection?: string;
    /** The frame table. Defaults to `agent_stream_frame`. */
    tableName?: string;
    /**
     * Gap (ms) between two reads of a run a subscriber is following — the most a frame waits before a
     * browser sees it. Defaults to 250.
     */
    pollIntervalMs?: number;
    /**
     * Gap (ms) between two reads once the run has been quiet for five seconds (parked on a human, a
     * slow tool). Defaults to 1000.
     */
    idlePollIntervalMs?: number;
    /**
     * Window (ms) consecutive `text` frames are gathered over and written as one row, so a streamed
     * answer is a handful of inserts rather than one per token. Defaults to 50; `0` writes every frame.
     */
    flushMs?: number;
    /**
     * TTL (seconds) of a run's rows, counted from its last write; `purgeExpired()` deletes what has
     * lapsed. Defaults to 3600 (1h). Set `0` to retain until manual cleanup.
     */
    ttlSeconds?: number;
    /**
     * Purge lapsed runs as a side effect of ending a run, at most once a minute per replica. Default
     * `true`. Set `false` to purge only from your own schedule (`sink.purgeExpired()`).
     */
    autoPurge?: boolean;
    /**
     * Create the frame table when the app starts. Default `true`. Set `false` to run the published
     * migration (`createAgentTables`, which creates it too) instead.
     */
    autoCreateTables?: boolean;
    /**
     * Bring-your-own Lucid database (or any {@link LucidDatabaseLike}). When set, `'lucid.db'` is NOT
     * resolved from the container and `connection` is ignored. Handy for tests and scripts.
     */
    db?: LucidDatabaseLike;
}
/**
 * The token-sink factory namespace used in `config/agent.ts`, mirroring {@link stores}. Also exported as
 * `streamTransports` (an alias — pick whichever name reads better):
 *
 * ```ts
 * import { defineConfig, tokenSinks } from '@adonis-agora/agent'
 *
 * export default defineConfig({
 *   model: () => aiSdkModel(openai('gpt-4o-mini')),
 *   sink: tokenSinks.redis({ connection: 'main' }), // multi-replica; any pod serves any run's SSE
 * })
 * ```
 *
 * Omitting `sink` entirely keeps the in-process sink (single replica); `tokenSinks.memory()` selects it
 * explicitly. `tokenSinks.redis()` fans a run's tokens across replicas over Redis pub/sub + a replayable
 * list, keeping the SSE envelope byte-identical. The `@adonisjs/redis` peer is imported ONLY inside the
 * `redis` thunk, so it stays fully optional. `tokenSinks.lucid()` is the multi-replica sink for a
 * deployment WITHOUT Redis: frames are rows in the app's SQL database, read by polling.
 */
export declare const tokenSinks: {
    /** The in-process sink — per-run in-memory buffers, single replica. The default when `sink` is omitted. */
    memory(): TokenSinkFactory;
    /**
     * The Redis multi-replica sink: any pod can serve any run's SSE stream. Builds a
     * {@link RedisStreamClient} over `@adonisjs/redis` (imported lazily here), or uses `config.client` when
     * provided. Requires `@adonisjs/redis` installed + configured (`config/redis.ts`) unless a `client` is
     * passed.
     */
    redis(config?: RedisTokenSinkConfig): TokenSinkFactory;
    /**
     * The Lucid (SQL) multi-replica sink: any pod can serve any run's SSE stream, with no Redis — a
     * run's frames are rows of `agent_stream_frame` on the app's database, which subscribers poll.
     * Slower to deliver than Redis (up to `pollIntervalMs`) and it writes to your database on every
     * streamed answer; pick {@link tokenSinks.redis} when Redis is already there. Requires
     * `@adonisjs/lucid` installed + configured unless a `db` is passed.
     */
    lucid(config?: LucidTokenSinkConfig): TokenSinkFactory;
};
/** Alias of {@link tokenSinks}. */
export declare const streamTransports: {
    /** The in-process sink — per-run in-memory buffers, single replica. The default when `sink` is omitted. */
    memory(): TokenSinkFactory;
    /**
     * The Redis multi-replica sink: any pod can serve any run's SSE stream. Builds a
     * {@link RedisStreamClient} over `@adonisjs/redis` (imported lazily here), or uses `config.client` when
     * provided. Requires `@adonisjs/redis` installed + configured (`config/redis.ts`) unless a `client` is
     * passed.
     */
    redis(config?: RedisTokenSinkConfig): TokenSinkFactory;
    /**
     * The Lucid (SQL) multi-replica sink: any pod can serve any run's SSE stream, with no Redis — a
     * run's frames are rows of `agent_stream_frame` on the app's database, which subscribers poll.
     * Slower to deliver than Redis (up to `pollIntervalMs`) and it writes to your database on every
     * streamed answer; pick {@link tokenSinks.redis} when Redis is already there. Requires
     * `@adonisjs/lucid` installed + configured unless a `db` is passed.
     */
    lucid(config?: LucidTokenSinkConfig): TokenSinkFactory;
};
/**
 * A configured {@link ActorDirectory}: a lazy thunk the agent provider calls at boot to build the
 * read-side `actorRef → label` lookup governance/dashboard surfaces resolve display names through. Each
 * factory imports its impl inside the thunk (like {@link stores}).
 */
export type ActorDirectoryFactory = (ctx: StoreContext) => ActorDirectory | Promise<ActorDirectory>;
/** Options for the in-memory actor directory. */
export interface MemoryActorDirectoryConfig {
    /** Seed `actorRef → display label` mappings. */
    labels?: Record<string, string>;
}
/**
 * The actor-directory factory namespace used in `config/agent.ts`, mirroring {@link stores}:
 *
 * ```ts
 * export default defineConfig({
 *   actorDirectory: actorDirectories.memory({ labels: { u_1: 'Ada Lovelace' } }),
 * })
 * ```
 *
 * Omit `actorDirectory` → governance surfaces render raw opaque refs. A real deployment binds its own
 * directory over the host's user table by passing an instance; `actorDirectories.memory` covers tests,
 * the offline demo, and small fixed label tables.
 */
export declare const actorDirectories: {
    /** In-memory `actorRef → label` map — single-process. Handy for tests and dev apps. */
    memory(config?: MemoryActorDirectoryConfig): ActorDirectoryFactory;
};
//# sourceMappingURL=factory.d.ts.map