import type { ConnectorDefinition, EntityMetrics } from "@lobu/connector-sdk";
import type { AgentSettings } from "@lobu/core";
import type { Project } from "../../../config/index.js";
import { type EntityBacking, type RelationshipRule, type WatcherSource } from "./shared.js";
export interface DesiredAgentMetadata {
    agentId: string;
    name: string;
    description?: string;
}
export interface DesiredPlatform {
    /** Stable, content-addressed ID derived from `(agentId, type, name?)`. */
    stableId: string;
    type: string;
    name?: string;
    /** Platform config — values may still contain `$VAR` references. */
    config: Record<string, string>;
    /** Declarative channel bindings (`"<teamId>/<channelId>"`); Slack only. */
    channels?: string[];
}
export interface DesiredEntityType {
    slug: string;
    name?: string;
    description?: string;
    required?: string[];
    properties?: Record<string, unknown>;
    /**
     * Event kinds (semantic types) for events linked to this type, keyed by
     * semantic_type — `{ description?, metadataSchema?, jsonTemplate? }`. Present
     * only when the type declares them; absent ⇒ never churns the diff. Persisted
     * to `entity_types.event_kinds` via manage_entity_schema.
     */
    eventKinds?: Record<string, unknown>;
    /**
     * Default view template (render-DSL root node) for this type's detail page.
     * Present only when declared. Applied via manage_view_templates set/clear and
     * diffed against the remote current default (which apply-cmd fetches per
     * relevant type — NOT streamed in the entity-type list). Prune-aware: under
     * prune an absent template clears the remote one; otherwise it is left alone.
     */
    viewTemplate?: Record<string, unknown>;
    metadata?: Record<string, unknown>;
    /**
     * Present only for derived (SQL-view-backed) entity types; absent ⇒ stored
     * (the default). Normalized so a stored type compares equal on both sides
     * (desired + remote both omit it) and never churns the diff — see
     * {@link EntityBacking}.
     */
    backing?: EntityBacking;
    /**
     * Declared metric contract (eventSets/measures/dimensions/segments). Present
     * only when the type declares metrics; absent ⇒ not in the metric catalog.
     * Normalized so a type with no metrics compares equal on both sides and never
     * churns the diff (mirrors `backing`).
     */
    metrics?: EntityMetrics;
}
export interface DesiredRelationshipType {
    slug: string;
    name?: string;
    description?: string;
    rules?: RelationshipRule[];
    metadata?: Record<string, unknown>;
}
export interface DesiredWatcher {
    slug: string;
    /** Owning agent id. Every watcher belongs to exactly one agent. */
    agent: string;
    name?: string;
    description?: string;
    schedule?: string;
    prompt: string;
    /** Optional SQL data sources; server applies a default when omitted. */
    sources?: WatcherSource[];
    /**
     * Reaction script — TypeScript source compiled + executed in an isolate at
     * watcher-firing time. Authored as a sibling `.ts` file referenced by
     * `defineWatcher({ reaction: reactionFromFile("./reactions/foo.reaction.ts") })`;
     * the CLI reads it and pushes raw source via `set_reaction_script`.
     */
    reactionScript?: {
        sourcePath: string;
        sourceCode: string;
    };
    /** LLM guidance for the watcher's downstream reaction agent. */
    reactionsGuidance?: string;
    /** UUID of a device worker to pin this watcher's runs to (see `device_workers.id`). */
    deviceWorkerId?: string;
    /** MCP client id that should auto-run this watcher. */
    schedulerClientId?: string;
    /** Where firings surface — defaults to canvas server-side. */
    notificationChannel?: "canvas" | "notification" | "both";
    /** Priority class used by the dispatcher interrupt budget. */
    notificationPriority?: "low" | "normal" | "high";
    /** Minimum seconds between two firings of this watcher (0 = no cooldown). */
    minCooldownSeconds?: number;
    /** Free-form tags for filtering. */
    tags?: string[];
    /** Optional agent-kind override (e.g. "background", "notifier"). */
    agentKind?: string;
    /** Stable key generation across windows. */
    keyingConfig?: Record<string, unknown>;
    /** Classifier definitions for extraction (server-side feature). */
    classifiers?: unknown[];
}
export interface DesiredFeed {
    /** Feed key from the connector definition (`FeedDefinition.key`). */
    feedKey: string;
    name?: string;
    schedule?: string;
    config?: Record<string, unknown>;
}
export interface DesiredConnection {
    /** Stable public identifier — diff key. */
    slug: string;
    /** Connector key (e.g. `github`, `hackernews`). */
    connector: string;
    name?: string;
    /** Slug of the runtime/account auth profile (`auth:` in the manifest). */
    authProfileSlug?: string;
    /** Slug of the OAuth-app auth profile (`app_auth:` in the manifest). */
    appAuthProfileSlug?: string;
    config?: Record<string, unknown>;
    /**
     * Optional UUID pinning the connection's syncs/actions to a specific device
     * worker (`device_workers.id`). Required for connectors that declare a
     * `required_capability`; omit it for serverless-on-Lobu runs.
     */
    deviceWorkerId?: string;
    feeds: DesiredFeed[];
    /** Source label for error messages (the config the connection came from). */
    sourceFile: string;
}
export type DesiredAuthProfileKind = "env" | "oauth_app" | "oauth_account" | "browser_session";
export interface DesiredAuthProfile {
    /** Stable slug — diff key. */
    slug: string;
    connector: string;
    kind: DesiredAuthProfileKind;
    name?: string;
    /**
     * key→value credentials. Values may be `$ENV` references (collected into
     * `requiredSecrets`). Only meaningful for `kind: env | oauth_app`; must be
     * absent/empty for `oauth_account | browser_session`.
     */
    credentials?: Record<string, string>;
    sourceFile: string;
}
export interface DesiredConnectorDefinition {
    /** Connector key — diff key (`null` until the server compiles a `.ts`). */
    key: string | null;
    /** Local `.ts` path (absolute) — mutually exclusive with `sourceUrl`. */
    sourcePath?: string;
    /** Remote URL — mutually exclusive with `sourcePath`. */
    sourceUrl?: string;
    /**
     * Raw TypeScript source read from `sourcePath`, pushed verbatim to the
     * server (which compiles, extracts metadata, and returns the real `key`).
     * Absent when `sourceUrl` is used.
     */
    sourceCode?: string;
    /** For error messages — the `.connector.ts` file or `type: connector` doc. */
    sourceFile: string;
}
export interface DesiredAgent {
    metadata: DesiredAgentMetadata;
    /**
     * Settings payload destined for `PATCH /:agentId/config`. Built by the mapper
     * + agent-dir loader: networkConfig, skillsConfig,
     * preApprovedTools, guardrails, toolsConfig, nixConfig,
     * modelSelection, providerModelPreferences, installedProviders,
     * identityMd/soulMd/userMd.
     */
    settings: Partial<AgentSettings>;
    platforms: DesiredPlatform[];
    /**
     * Provider API keys resolved from `secret()` / `$VAR` provider keys, pushed
     * into `agent_secrets` after the settings PATCH. Empty when no provider
     * declared a `key` (or all are unset). The value lives only in process
     * memory; never serialized.
     */
    providerKeys: {
        providerId: string;
        value: string;
    }[];
}
export interface DesiredState {
    agents: DesiredAgent[];
    /**
     * When true (`defineConfig({ prune: true })`), `lobu apply` deletes org-owned
     * definitions (entity/relationship types, watchers, connector definitions)
     * absent from this config — including ones created in the UI. Data,
     * connections, auth profiles, and agents are never pruned. Default false.
     */
    prune: boolean;
    /**
     * Org metadata from `defineConfig` — the org slug `lobu apply` defaults to,
     * the `organizationId` it matches against, and the name/description shown
     * when telling the operator to create the org.
     */
    memory?: {
        org?: string;
        organizationId?: string;
        name?: string;
        description?: string;
    };
    memorySchema: {
        entityTypes: DesiredEntityType[];
        relationshipTypes: DesiredRelationshipType[];
    };
    /** Watchers declared via `defineWatcher`. */
    watchers: DesiredWatcher[];
    /**
     * Connectors: local `*.connector.ts` definitions (declared via
     * `connectorFromFile`), `defineConnection`s, and `defineAuthProfile`s.
     */
    connectors: {
        definitions: DesiredConnectorDefinition[];
        authProfiles: DesiredAuthProfile[];
        connections: DesiredConnection[];
    };
    /**
     * Names of env vars referenced via `secret()` / `$VAR` (provider keys,
     * auth-profile + mcp credentials). The CLI surfaces these before mutating
     * remote state so missing secrets fail loud instead of expanding to empty.
     */
    requiredSecrets: string[];
}
export interface ResolvedConnectorSchemas {
    /** Connector key → `optionsSchema` (JSON Schema), if declared. */
    optionsSchema?: Record<string, unknown>;
    /** Every feed key declared by the connector (`connector.feeds` keys). */
    feedKeys: Set<string>;
    /** Feed key → `configSchema` (JSON Schema), for keys that declare one. */
    feedConfigSchemas: Map<string, Record<string, unknown>>;
    /** Allowed auth-profile kinds for the connector (from `authSchema.methods`). */
    authKinds: Set<string>;
}
/**
 * Build per-connector validation schemas from a connector definition. Accepts
 * either a typed `ConnectorDefinition` (from `@lobu/connector-sdk`) or the
 * snake_cased shape from `manage_catalog` connector entries
 * (`options_schema`, `feeds_schema`, `auth_schema`).
 */
export declare function resolveConnectorSchemas(def: ConnectorDefinition | {
    options_schema?: Record<string, unknown> | null;
    feeds_schema?: Record<string, unknown> | null;
    auth_schema?: Record<string, unknown> | null;
}): ResolvedConnectorSchemas;
/**
 * Validate a single connection (+ its feeds) and its referenced auth-profile
 * kinds against a resolved connector schema. Pass `null` to skip schema
 * checks (e.g. a connector that only exists as a local `.ts` not yet
 * compiled by the server) — structural checks have already run at load time.
 */
export declare function validateConnectionAgainstConnector(connection: DesiredConnection, authProfiles: ReadonlyMap<string, DesiredAuthProfile>, schemas: ResolvedConnectorSchemas | null): void;
/** Keys the connector treats as feed-scoped (declared in any feed's `configSchema`). */
export declare function feedScopedKeys(schemas: ResolvedConnectorSchemas): Set<string>;
/**
 * The server stores feed-scoped settings on feeds, not the connection, and
 * REJECTS a connection whose config carries any feed-scoped key (see
 * `splitConfigByFeedScope` in packages/server). `lobu apply` mirrors that split
 * here: any feed-scoped key found in a connection's `config` is demoted to a
 * per-feed default (an explicit feed value wins) and removed from the
 * connection config. `managedBy` is Lobu metadata, never a connector option, so
 * it stays on the connection. Returns the demoted key names so the caller can
 * warn. Mutates `connection` in place so the normalized shape flows into the
 * diff + create/update payloads.
 */
export declare function normalizeConnectionConfigScope(connection: DesiredConnection, schemas: ResolvedConnectorSchemas | null): string[];
export declare function validateAuthProfileAgainstConnector(profile: DesiredAuthProfile, schemas: ResolvedConnectorSchemas | null): void;
interface LoadDesiredStateOptions {
    /** Project root (directory containing `lobu.config.ts`). */
    cwd: string;
    /** Env to resolve `$VAR` refs against; defaults to `process.env`. */
    env?: NodeJS.ProcessEnv;
    /**
     * When set, only the named resource family is loaded — `"agents"` and
     * `"memory"` both skip the `connectors/` dir (and its `$VAR` credential
     * expansion), so `--only agents` doesn't require connector secrets.
     */
    only?: "agents" | "memory";
}
/**
 * Import a `lobu.config.ts` and return its `defineConfig` default export (the
 * SDK {@link Project}). Shared by {@link loadDesiredStateFromConfig} (apply) and
 * the commands that read the authored config directly (`lobu run` preview
 * registration, `lobu doctor`, `lobu chat`, `lobu validate`, `lobu memory seed`).
 *
 * Uses jiti — the same runtime TypeScript loader Next.js/Nuxt use for their
 * `*.config.ts` — which transpiles on import and resolves the config's imports
 * (`@lobu/cli/config`, `@lobu/connector-sdk`, relative reaction/connector files)
 * from the project. No bundling, no temp file. The dynamic `import("jiti")` is
 * lazy + allow-listed (AGENTS.md).
 */
export declare function loadProjectConfig(cwd: string): Promise<{
    project: Project;
    configPath: string;
}>;
/**
 * Load desired state from a TypeScript entrypoint (`lobu.config.ts`): import the
 * `defineConfig()` project, map it to `DesiredState`, then attach the
 * file-based artifacts (agent-dir markdown + skills, watcher reaction scripts,
 * local connector source).
 */
export declare function loadDesiredStateFromConfig(opts: LoadDesiredStateOptions): Promise<{
    state: DesiredState;
    configPath: string;
    warnings: string[];
}>;
export {};
//# sourceMappingURL=desired-state.d.ts.map