/** InfonaError + env lookup used by the SDK client. */ declare class InfonaError extends Error { status?: number; body?: string; constructor(message: string, opts?: { status?: number; body?: string; }); } /** Shared Client / RawApi TypeScript types. Re-exported from ``client.ts`` so existing ``from "./client.js"`` imports keep working. No runtime behavior. */ interface ClientOptions { apiKey?: string; baseUrl?: string; tenant?: string; } interface IngestOptions { kg?: string; contentType?: "text" | "csv" | "json" | string; /** Treat `pathOrText` as a FILE PATH, not as raw text. When set, a path that * does not resolve to a readable file throws a `InfonaError` instead of * silently POSTing the path string itself as text content (ONTA-253: a * file-intent caller — e.g. the MCP `ingest_csv` tool — must never fabricate * a success by LLM-extracting entities out of a nonexistent filename). The * dual-mode default (`asFile` unset) keeps the CLI's intentional * `ingest ` path working. */ asFile?: boolean; /** Treat `pathOrText` as RAW TEXT even if the string happens to resolve to an * existing file path. Use from text-intent callers (e.g. MCP `ingest_text`) * so a note that looks like a path is never silently re-read from disk. * Mutually exclusive with `asFile` — when both are set, `asFile` wins. */ asText?: boolean; /** Rows per batch for CSV ingest. Default 200. Larger = fewer round-trips * but higher per-request memory; 200 is a good balance for typical KGs. */ batchSize?: number; /** Max number of batches in flight at once. Default 4. Higher saturates * the backend faster but risks 429s on large ingests. */ concurrency?: number; /** Called after each batch completes during CSV ingest, in batch order. * Use for progress UI. Not invoked for text/json ingest. */ onProgress?: (progress: IngestProgress) => void; /** CSV only. Join-by-exact-key ingest mode (ONTA-250): match each row to an * EXISTING entity by an exact key attribute and merge the row's attributes * ONTO that node instead of minting a duplicate. `keyAttribute` is the * snake_case attribute the key column maps to (e.g. an id column); when a * row's key matches no existing entity it mints a new node unless * `mintUnmatched` is false (then it is skipped and reported). A thin * pass-through of the `/ingest/csv/rows` route's `key_join` field — the * server does the matching. General over any (type, key). */ keyJoin?: { keyAttribute: string; mintUnmatched?: boolean; }; /** CSV only. Called once after schema inference and BEFORE any rows are * written, with the inferred mapping. Return the (possibly edited/approved) * mapping to ingest, or `null` to cancel without writing anything. When * omitted the inferred mapping is applied as-is (non-interactive). This is * the same confirm/override gate the Explorer surfaces in its review step. */ onSchemaInferred?: (mapping: Record, info: { totalRows: number; rowsProfiled: number; }) => Promise | null>; /** CSV only. Deterministic ingest: skip LLM schema inference entirely and * map columns VERBATIM under this entity type — the first column becomes * the entity name (`type_id`), every other column a literal attribute named * exactly like its header. The predictable counterpart to the inferred flow * for when column names are load-bearing (e.g. an attribute another rail * binds on, like an external series/id column an enrichment source joins * against). `onSchemaInferred` is not called in this mode — there is * nothing inferred to review. */ typeName?: string; } interface IngestProgress { rowsProcessed: number; totalRows: number; entitiesResolved: number; triplesInserted: number; } interface AskOptions { kg?: string; model?: string; } interface ResolvedChange { kind: "attribute" | "relationship"; subject_type: string; name: string; datatype_or_target: string; action: "reuse" | "extend" | "create"; confidence: number; reason: string; } interface OntologyResolveResult { applied: ResolvedChange[]; proposals: ResolvedChange[]; summary: string; } interface OntologyApplyResult { applied: ResolvedChange; operations: number; summary: string; } /** One change's outcome inside an {@link OntologyApplyBatchResult}. */ interface OntologyApplyChangeResult { change: ResolvedChange; /** false ⇒ this change raised; see `error`. The rest of the batch still ran. */ ok: boolean; operations: number; error: string; } /** Response of {@link Client.ontologyApplyBatch} — one entry per submitted change. */ interface OntologyApplyBatchResult { results: OntologyApplyChangeResult[]; applied_count: number; failed_count: number; operations: number; summary: string; } interface TypeCount { name: string; entity_count: number; /** Instances carry geometry, so the type is in the spatio-temporal index. * The backend has always returned this; the type just never declared it. */ spatially_indexed?: boolean; /** Instances carry validity (an explicit bound, or a start+end pair). */ temporally_indexed?: boolean; } interface AttributeUsage { name: string; datatype: string; count: number; } interface RelationshipUsage { name: string; target_type: string | null; count: number; } interface EntitySample { uri: string; label: string; } interface TypeUsage { name: string; description: string; parent_type: string | null; entity_count: number; attributes: AttributeUsage[]; relationships: RelationshipUsage[]; samples: EntitySample[]; } interface AttributeSummary { name: string; predicate_uri: string; datatype: string; count: number; coverage_pct: number; } interface RelationshipSummary { name: string; predicate_uri: string; target_type: string | null; count: number; coverage_pct: number; avg_degree: number; } interface TypeSummary { name: string; description: string; parent_type: string | null; entity_count: number; attributes: AttributeSummary[]; relationships: RelationshipSummary[]; /** See {@link TypeCount.spatially_indexed} (also returned here). */ spatially_indexed?: boolean; /** See {@link TypeCount.temporally_indexed} (also returned here). */ temporally_indexed?: boolean; } /** An {@link AttributeSummary} inside a {@link KgSchema}, annotated with whether * any instance in this KG actually carries it. A declared attribute with no * data is returned with `populated: false` rather than dropped: a count of 0 * is indistinguishable from a transient backend throttle, so dropping makes * slots flicker across identical calls. */ interface SchemaAttribute extends AttributeSummary { populated: boolean; } /** A {@link RelationshipSummary} inside a {@link KgSchema}. See * {@link SchemaAttribute} for the `populated` semantics. */ interface SchemaRelationship extends RelationshipSummary { populated: boolean; } /** One type inside a {@link KgSchema}: the {@link TypeSummary} shape plus the * population annotations that make declared-but-empty schema visible instead * of hidden. */ interface KgSchemaType extends TypeSummary { attributes: SchemaAttribute[]; relationships: SchemaRelationship[]; /** This KG has at least one instance of the type. */ populated: boolean; /** Declared in the ontology but with no instances in THIS KG. */ declared_only: boolean; /** How many slots the `minCoverage` floor withheld (0 when unfiltered). */ attributes_withheld: number; relationships_withheld: number; } /** Response of {@link Client.kgSchema}: the whole KG's population-aware schema. */ interface KgSchema { kg: string; /** Types sorted by `entity_count` descending, capped by `limit`. */ types: KgSchemaType[]; total_types: number; truncated: boolean; /** Names of the types the `limit` cap withheld, so a capped type is still * known to EXIST and can be fetched with `types: [...]`. */ omitted_type_names: string[]; /** Populated ONLY when a `types` filter matched nothing: every type name the * graph does have, so a typo reads as "you meant one of these" rather than * "that type does not exist". Empty otherwise. */ available_type_names: string[]; /** `"precomputed"` (materialized stats) or `"live_scan"` (legacy KG). */ stats_source: string; /** How `coverage_pct` is computed, including the multi-typed-entity caveat. */ coverage_note: string; } type EnrichmentTier = "auto" | "lite" | "base" | "core" | "pro"; type JobStatus = "queued" | "running" | "review" | "applied" | "cancelled" | "failed"; /** The job statuses that mean "stopped doing work, will not advance on its own" * — the mirror of the backend's `JobStatus.is_terminal()`. `queued`/`running` * are the only in-flight states; everything else is settled (`review` is a * finished run parked for human conflict decisions). Kept in lockstep with the * server so a `waitForJob` caller and the wait route agree on when to stop. */ declare const TERMINAL_JOB_STATUSES: readonly JobStatus[]; /** True when a job status is terminal (see {@link TERMINAL_JOB_STATUSES}). */ declare function isTerminalJobStatus(status: JobStatus): boolean; /** The kind of work a tracked job performs — the unified `/jobs` feed spans all * categories. Existing enrichment jobs default to `enrichment` server-side. * `discovery` is a web-discovery ingest (the `web_ingest` capability): it * CREATES a new record set from the web rather than filling/merging an existing * one. `ingest` is file CSV/JSON/text ingest (ONTA-386): an A1-like entry that * maps/extracts, places against the ontology, and writes via insert_facts. * `answer` is a read-only NL ask / agent Q&A turn (P7 Answer / A7 + P0/A9 * stage_trace; ONTA-389) — not every chat message, only meaningful completions. */ type JobCategory = "dedupe" | "enrichment" | "reconciliation" | "discovery" | "ingest" | "answer"; type JobTrigger = "manual" | "scheduled" | "webhook"; type ConflictPolicy = "skip" | "verify" | "overwrite" | "stage"; type RowAction = "filled" | "verified" | "conflict" | "skipped" | "no_match"; type ReviewDecision = "accept" | "reject" | "skip"; interface EnrichRequest { type_name: string; attributes: string[]; tier?: EnrichmentTier; kg_name: string; conflict_policy?: ConflictPolicy; confidence_min?: number; limit?: number; /** Chat provenance: the conversation/thread id this job is kicked off from, so * the created job is traceable back to its conversation. Omit for non-chat * (direct API / CLI / scheduled) callers. */ thread_id?: string; } interface EnrichJobCreate { /** Null when the backend needs the client to clarify the source before a job * is created (see {@link needs_clarification}). */ job_id: string | null; /** Either a real {@link JobStatus} (e.g. "queued") or the routing sentinel * "needs_clarification" when the backend wants the client to pick a tier. */ status: "queued" | "needs_clarification" | JobStatus | string; /** The concrete tier a job was actually created at — e.g. "lite" (Wikidata, * free) or "core" (live web search) — once the backend's "auto" routing * resolves. Null/absent when {@link needs_clarification}. */ resolved_tier?: EnrichmentTier | null; /** Short human reason for the routing decision, e.g. "Wikidata is thin for * these attributes — using web search". */ routing_note?: string | null; /** True when the backend could not confidently route "auto" and wants the * client to choose among {@link candidates}; no job was created. */ needs_clarification?: boolean; /** The tiers to offer the user when {@link needs_clarification}, e.g. * ["lite","core"]. */ candidates?: string[] | null; estimated_cost_usd?: number; total_entities?: number; } interface Verdict { value: string; confidence: number; source: string; source_url?: string | null; reasoning?: string | null; } interface JobProgress { total: number; processed: number; filled: number; verified: number; conflicts: number; skipped: number; no_match: number; cache_hits: number; /** Coarse WHAT-is-happening-now label for a running job (ONTA-238): discovery * sets it through the run ("searching" → "ingesting" → "done" / "failed"); * enrichment/dedupe leave it "". Optional for back-compat with older payloads * that predate the field. The MCP `get_job` tool surfaces it. */ phase?: string; } interface RowResult { entity_uri: string; attribute: string; existing_value: string | null; verdict: Verdict | null; action: RowAction; } /** One day-aligned usage line: a breakdown member or the total. `total` is the * window aggregate (sum for requests/cost; weighted average for latency). */ interface UsageSeries { label: string; values: number[]; total: number; } /** A usage metric's total line plus its per-KG / per-API-key breakdowns. */ interface UsageMetricBlock { total: UsageSeries; by_kg: UsageSeries[]; by_key: UsageSeries[]; } interface UsageTotals { requests: number; errors: number; avg_latency_ms: number; cost_usd: number; } /** `GET /graphs/{tenant}/usage` — the dashboard usage panel's one payload: * day-aligned series for requests / latency / cost, current + previous * window totals (for deltas), route-class request counts, and the * month-to-date request count (quota "used"). */ interface UsageReport { days: string[]; requests: UsageMetricBlock; latency_ms: UsageMetricBlock; cost_usd: UsageMetricBlock; totals: UsageTotals; prev_totals: UsageTotals; route_class_requests: Record; has_queried: boolean; month_requests: number; } interface JobSummary { id: string; tenant_id: string; kg_name: string; type_name: string; attributes: string[]; tier: EnrichmentTier; status: JobStatus; progress: JobProgress; created_at: string; started_at?: string | null; completed_at?: string | null; conflict_policy: ConflictPolicy; confidence_min: number; error?: string | null; category?: JobCategory; trigger?: JobTrigger; last_run?: string | null; next_run?: string | null; cost?: number | null; cost_note?: string | null; /** Discovery/web-ingest summary fields. `result_count` is the headline "how * many records were found" number; `platforms` are the web sources/providers * consulted during the run. Both null/absent for non-discovery jobs. */ result_count?: number | null; platforms?: string[] | null; /** Derived 0-100 completion percentage from progress.processed/total. */ progress_pct?: number; /** Chat provenance: the conversation/thread id this job was created from, when * it was kicked off from the Ask-AI chat (null/absent for non-chat jobs). */ thread_id?: string | null; } interface EnrichJob extends JobSummary { results?: RowResult[]; limit?: number | null; } interface ConflictReview { entity_uri: string; attribute: string; existing_value: string; proposed: Verdict; decision?: ReviewDecision | null; } /** Agent, schedule, explore, search, and grep SDK types. Re-exported from ``client.ts`` so existing imports keep working. */ /** Actions a tenant may CREATE or UPDATE through the schedules CRUD routes — * mirrors the Ask-AI action endpoints: find-merge-duplicates (dedupe), enrich * (enrichment), suggest-relationships (reconciliation), plus `notify` (ONTA-235): * a standing-alert / weekly-refresh that snapshots a watched value each fire, * diffs it against the previous fire, and delivers a change payload out through * a delivery sink ONLY when it changed. A schedule's `category` agrees with its * `action`. The backend rejects any other action on create/update with a 422 — * see {@link ScheduleAction} for the system-managed values that can still APPEAR * in list/get responses. */ type UserSchedulableAction = "find-merge-duplicates" | "enrich" | "suggest-relationships" | "notify" | "extract"; /** The action a {@link Schedule} fires — the FULL read-side vocabulary, a * superset of {@link UserSchedulableAction}. `semantic-embed-fill` / * `semantic-reconcile` (ONTA-181) are SYSTEM-MANAGED semantic-index * maintenance rows the backend creates internally; they show up in a tenant's * schedule list/get responses, but create/update accept only the * user-schedulable subset (422 otherwise) and PATCHing a system row is a 403. * `extract` (ONTA-555) is user-schedulable (gated like the extract family); * preferred write path is `PUT /extract-sources/{slug}/schedule`. * Exhaustive consumers of `Schedule.action` must handle all six arms. */ type ScheduleAction = UserSchedulableAction | "semantic-embed-fill" | "semantic-reconcile"; /** Runtime companion of {@link UserSchedulableAction} (e.g. for building a * create-schedule action picker) — mirrors the backend's * `USER_SCHEDULABLE_ACTIONS` allowlist in `scheduling/models.py`. */ declare const USER_SCHEDULABLE_ACTIONS: readonly UserSchedulableAction[]; /** * A recurring-action schedule for a tenant's KG (COG-135). Recurs on EXACTLY * one of `cron` / `interval_seconds` (the backend rejects both/neither). This * is the scheduling DATA shape — the firing loop that turns a due schedule into * a job is server-side and separate. `params` carries the action-specific job * payload (e.g. `type_name`/`attributes`/`tier`/`conflict_policy` for enrich). */ interface Schedule { id: string; tenant_id: string; kg_name: string; category: JobCategory; action: ScheduleAction; params: Record; cron?: string | null; interval_seconds?: number | null; enabled: boolean; next_run?: string | null; last_run?: string | null; created_at: string; } /** Inputs to {@link Client.agent} — mirror the `/agent` HTTP body. */ interface AgentTurnOptions { /** The user's natural-language message. Optional when `confirmPlanId` is set * (a confirm turn carries no new message). */ message?: string; /** Context graph the turn operates within. */ kgName?: string; /** Optional active type scope (needed for enrich/clean/dedup planning). */ typeName?: string; /** Optional explicit links to parse for this turn (threaded into the request * `context.urls`). The server routes a URL-bearing turn to enrich existing * entities or discover new ones, then extracts records from these pages. */ urls?: string[]; /** Optional conversation/session id for multi-turn continuity. */ sessionId?: string; /** When set, the server CONFIRMS + EXECUTES this previously-proposed plan * (the only mutating path) instead of classifying a new message. */ confirmPlanId?: string; /** Optional HARD per-run spend ceiling (USD) for any enrichment/discovery job * this turn kicks off (ONTA-282/ONTA-378). Threaded into the request body as * `spend_ceiling_usd`; the server stamps it onto the job it creates so the * executor's ceiling override bounds that single run. Omit for the deployment * default (unchanged behavior); a value of 0 means unlimited. */ spendCeilingUsd?: number; } /** * The kind-tagged result of one agent turn. The server returns exactly one of: * - `answer` — a read-only answer (questions; an ontology INSPECT) with SPARQL. * - `clarify` — the agent needs more detail; ask the user `question`. * - `plan` — a proposed (un-executed) plan with `plan_id` + `steps`; confirm * by calling `agent({ confirmPlanId: plan_id })`. * - `result` — the outcome of executing a confirmed plan, per-step. A * duplicate confirm of a finished plan returns the SAME result * with `replayed: true` (the plan is never run twice). * - `error` — e.g. an unknown/expired plan_id on confirm, or a duplicate * confirm that can't replay yet: `code:"plan_already_executing"` * (first confirm still in flight) / `"plan_already_executed"` * (finished with no replayable result). * Extra fields vary by kind (answer/sparql/rows; question; plan_id/steps; * steps), so this is intentionally open beyond the discriminant. */ interface AgentResult { kind: "answer" | "clarify" | "plan" | "result" | "error"; [key: string]: unknown; } /** One row in the Explorer Data table — an entity instance with its attribute * values. `id` is the entity URI; `name` is the display name; the remaining * keys are per-attribute values (all stringly-typed for display). */ interface TypeRecord { id: string; name: string; [attr: string]: string; } /** A page of {@link TypeRecord}s returned by {@link Client.exploreRecords}. * `next_cursor` is the last entity URI of this page; pass it back as `cursor` * to fetch the following page, or `null` when there are no more rows. */ interface TypeRecordsPage { columns: string[]; rows: TypeRecord[]; total: number; next_cursor: string | null; } /** An undirected type→type edge in the Explorer overview graph, weighted by the * number of instance relationships it summarizes. */ interface TypeEdge { source: string; target: string; weight: number; } /** A stored normalization rule (suggested / confirmed / rejected / applied / * failed). `failed` means the background apply raised — `last_error` says why * and `failed_at` when; the rule is NOT dead, POSTing apply again retries it. * Open beyond the documented fields because the rule's `params` shape varies by * `rule_type` (e.g. `strip_emoji`, `list_explode`). */ interface NormalizationRule { id: string; kg_name: string; type_name: string; predicate: string; rule_type: string; target_kind?: string; params?: Record; confidence?: number; rationale?: string; status: "suggested" | "confirmed" | "rejected" | "applied" | "failed" | string; created_at?: string; applied_at?: string | null; failed_at?: string | null; last_error?: string | null; [key: string]: unknown; } /** The list/summary shape for a registered API source. Secret-free by * construction: only `has_secret` is exposed, never a value. `editable` is true * only for `tenant_custom` entries (global entries are read-only). */ interface ApiSourceSummary { slug: string; title: string; publisher: string; description: string; layer: "global_public" | "global_enhanced" | "tenant_custom" | string; authority_level: string; entity_kinds: string[]; attributes: string[]; enabled: boolean; editable: boolean; has_secret: boolean; } /** One structured validation error from the validate route. */ interface ApiSourceValidationError { path: string; message: string; } /** Response of `POST /api-sources/validate`. */ interface ApiSourceValidateResult { valid: boolean; errors: ApiSourceValidationError[]; } /** Response of `POST /api-sources/test` — the smoke-call result. A secret is * never echoed here; `rows` carry no auth material. */ interface ApiSourceTestResult { ok: boolean; rows: Record[]; error?: string | null; } /** Create/update body. `spec` is an `ApiSourceSpec` JSON object; `secrets` is a * write-only logical-name→value map (never returned); `enabled` toggles the * row. On update, all fields are optional (e.g. flip `enabled` alone). */ interface ApiSourceWrite { spec?: Record; secrets?: Record; enabled?: boolean; } /** One entity-grouped hit from the canonical `/search` route: the entity that * matched, small denormalized display fields (`attrs.label`, `attrs.type`, …), * and the best-matching chunk's snippet + source attribute so a UI can show * WHERE the match happened without a follow-up fetch. */ interface SemanticSearchHit { entity_uri: string; attrs: Record; snippet: string; attr: string; score: number; } /** Options for {@link Client.search} (`POST /graphs/{tenant}/search`). */ interface SemanticSearchOptions { /** Restrict to one knowledge graph (`kg_name` in the body). */ kg?: string; /** Restrict to one entity type (AND with other filters). */ type?: string; /** * Strict entity-URI allowlist (`entity_uris` in the body) — structured * pre-filter before hybrid ranking. Omit = unrestricted; `[]` = zero hits; * server blanks-strip + dedupes and 400s above 500 unique URIs. */ entityUris?: string[]; /** Max entities to return (server clamps to 1..50; default 10). */ topK?: number; } /** The `/search` response envelope. `degraded: true` means the query ran * lexical-only (no query embedding was available) — reduced recall that must * be surfaced, never hidden. `top_k` echoes the server-side clamped value * (1..50) actually used. */ interface SemanticSearchResponse { hits: SemanticSearchHit[]; count: number; degraded: boolean; top_k: number; } /** ONE matching triple from the `/grep` route. The unit is a TRIPLE, not an * entity (contrast {@link SemanticSearchHit}): the same entity appears once per * matching attribute, because "which field did this match in?" is the point of * a grep. `value` is the literal (truncated), `snippet` a bounded window * centered on the match, `attr` the predicate's leaf name. `label` / `type` are * empty when the subject carries neither. */ interface GrepMatch { entity_uri: string; label: string; type: string; predicate: string; attr: string; value: string; snippet: string; } /** The `/grep` response envelope. `truncated: true` means the scan hit `limit` * and more matches exist (the server over-fetches by one row, so this is * observed, not inferred). `limit` echoes the server-side clamped value * (1..200) actually used. */ interface GrepResponse { matches: GrepMatch[]; count: number; limit: number; truncated: boolean; } /** Per-call overrides for a RawApi method — extra/override headers and a * custom timeout. A body here is ignored by methods that take an explicit * body argument (they set it themselves). */ interface RawInit { headers?: Record; timeoutMs?: number; } /** Frozen ONTA-553 Wave-1 extract contract (`POST /graphs/{tenant}/ingest/dlt`). */ type DltSourceKind = "rest_api" | "sql"; type DltAuthType = "bearer" | "basic" | "api_key" | "none"; interface DltAuthSpec { type?: DltAuthType; /** BYOK: `env:VAR` (CLI substitutes locally) or `store:/`. */ secret_ref?: string; /** Write-only inline token. Never echoed. */ token?: string; username?: string; api_key_header?: string; } interface DltSourceSpec { kind: DltSourceKind; base_url?: string; dsn?: string; auth?: DltAuthSpec; resources: string[]; headers?: Record; limit?: number; } interface DltResourceMap { type: string; id_field?: string; attributes?: string[]; } interface DltIngestRequest { source: DltSourceSpec; map: Record; kg?: string; } /** A source's recurring-read cadence (ONTA-555). An ordinary row in the shared * schedule store — see infona_client/ingestion/schedule.py. */ interface ExtractSchedule { id: string; interval_seconds?: number | null; cron?: string | null; enabled: boolean; next_run?: string | null; last_run?: string | null; } interface ExtractSourceSummary { slug: string; title: string; kind: DltSourceKind; enabled: boolean; has_secret: boolean; resources: string[]; mapped: string[]; kg?: string | null; schedule?: ExtractSchedule | null; } /** Body for `PUT .../extract-sources/{slug}/schedule`. Exactly one of * `interval_seconds` / `cron`. */ interface ExtractScheduleWrite { interval_seconds?: number; cron?: string; enabled?: boolean; } /** One connector template from `GET .../extract-sources/catalog` (ONTA-555). * Prefill for the SAME generic REST/SQL extract — never a shipped credential. */ interface ConnectorTemplate { id: string; title: string; category: string; kind: DltSourceKind; blurb: string; docs_url?: string; base_url?: string | null; placeholders: { key: string; label: string; example?: string; help?: string; }[]; headers?: Record; auth: { type: DltAuthType; label: string; help?: string; api_key_header?: string | null; username_label?: string | null; username_default?: string | null; }; resources: { path: string; label: string; suggested_type: string; id_field: string; default: boolean; }[]; custom: boolean; note?: string; } interface ExtractSourceWrite { slug?: string; title?: string; source?: DltSourceSpec; map?: Record; kg?: string; enabled?: boolean; secrets?: Record; } /** Raw / passthrough methods for the 3rd-party extract family (ONTA-553/554/555). A sibling of `clientRaw.ts` — that file sits at its size pin, and this family is a self-contained seam: the frozen `POST /ingest/dlt` execute route, the `/extract-sources` persist CRUD, the connector catalog and a source's cadence. {@link RawApi} extends this class, so callers still reach every method through `client.raw.*` and nothing about the surface changes. Each method returns the backend Response VERBATIM (no throw on non-2xx, no reshape) and builds its path from the Client path builders, exactly like the rest of the raw surface. */ declare class RawExtractApi { protected readonly client: Client; constructor(client: Client); /** `POST /graphs/{tenant}/ingest/dlt` — extract a REST/SQL source via dlt. */ ingestDlt(body: unknown, init?: RawInit): Promise; extractSourcesList(init?: RawInit): Promise; extractSourcesGet(slug: string, init?: RawInit): Promise; extractSourcesCreate(body: unknown, init?: RawInit): Promise; extractSourcesUpdate(slug: string, body: unknown, init?: RawInit): Promise; extractSourcesDelete(slug: string, init?: RawInit): Promise; extractSourcesRun(slug: string, body?: unknown, init?: RawInit): Promise; /** `GET /graphs/{tenant}/extract-sources/catalog` — connector templates. */ extractCatalog(init?: RawInit): Promise; /** `PUT /graphs/{tenant}/extract-sources/{slug}/schedule` — set the cadence. */ extractSourceScheduleSet(slug: string, body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/extract-sources/{slug}/schedule` — stop recurring reads. */ extractSourceScheduleClear(slug: string, init?: RawInit): Promise; } /** Raw / passthrough methods for skills, functions, entity detail, stats. {@link RawApi} extends this class (which extends {@link RawExtractApi}), so callers still reach every method through ``client.raw.*``. Paths come from the Client path builders; each method returns the backend Response VERBATIM. */ declare class RawSkillsApi extends RawExtractApi { /** `GET /graphs/{tenant}/skills?type_name`. */ skills(opts?: { typeName?: string; }, init?: RawInit): Promise; /** `GET /graphs/{tenant}/skills/{type}/{slug}`. */ skill(typeName: string, slug: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/skills` — create or replace a tenant skill. */ createSkill(body: unknown, init?: RawInit): Promise; /** `PATCH /graphs/{tenant}/skills/{type}/{slug}`. */ updateSkill(typeName: string, slug: string, body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/skills/{type}/{slug}`. */ deleteSkill(typeName: string, slug: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/skills/validate`. */ validateSkill(body: unknown, init?: RawInit): Promise; /** `GET /graphs/{tenant}/skills/prompt-block?type_name`. */ skillsPromptBlock(typeNames?: string[], init?: RawInit): Promise; /** `GET /graphs/{tenant}/functions?entity_type`. */ functions(opts?: { entityType?: string; }, init?: RawInit): Promise; /** `POST /graphs/{tenant}/functions`. */ registerFunction(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/functions/{name}/invoke`. */ invokeFunction(name: string, body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/functions/{name}?entity_type=` (required). */ deleteFunction(name: string, opts: { entityType: string; }, init?: RawInit): Promise; /** `GET /graphs/{tenant}/explore/kgs/{kg}/entities/{id}`. */ exploreEntity(kg: string, entityId: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/explore/kgs/{kg}/recompute-stats`. */ recomputeStats(kg: string, init?: RawInit): Promise; } /** Raw / passthrough API — one method per canonical backend operation. Each method returns the backend Response VERBATIM (no throw on non-2xx, no reshape). Paths come from Client path builders so they stay shared with the typed methods. */ /** * Raw / passthrough surface — reached via {@link Client.raw}. Each method maps * to ONE canonical backend operation, builds the path internally (callers pass * NO path string), and returns the backend {@link Response} VERBATIM: * * - it does NOT throw on a non-2xx status (a 404/500 resolves as a `Response` * whose `.status` the caller inspects — contrast the typed methods, which * throw {@link InfonaError}); and * - it does NOT parse or reshape the body (the caller gets the unread stream; * contrast e.g. {@link Client.listKgs}, which unwraps `{kgs:[]}`). * * Every method funnels through {@link Client.requestRaw}, so the base URL, * `X-API-Key`, `/graphs/{tenant}` prefix, JSON content-type and timeout are * centralized in exactly one place. The only rejection paths are a network * failure or a timeout — the cases where there is no HTTP response to return. * * @example * ```ts * const client = new Client({ apiKey, tenant }); * // Webapp proxy pattern: forward the backend response 1:1, no reshaping. * const res = await client.raw.enrichJobs(); // GET …/enrich/jobs * return new Response(res.body, { status: res.status, headers: res.headers }); * * // A non-2xx is a Response, not a throw: * const r = await client.raw.enrichJob("does-not-exist"); * if (r.status === 404) { ... } // no try/catch needed * ``` */ declare class RawApi extends RawSkillsApi { /** `POST /graphs/{tenant}/agent` — one turn of the unified Ask-AI agent. */ agent(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ask` — natural-language question. */ ask(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ingest` — ingest text/json (or csv) content. */ ingest(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ingest/csv/schema` — infer a CSV schema mapping. */ ingestCsvSchema(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ingest/csv/rows` — write a batch of mapped rows. */ ingestCsvRows(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/enrich/jobs` — plan + run an enrichment job. */ enrichCreateJob(body: unknown, init?: RawInit): Promise; /** `GET /graphs/{tenant}/enrich/jobs` — list recent enrichment jobs. */ enrichJobs(init?: RawInit): Promise; /** `GET /graphs/{tenant}/jobs?category` — unified jobs list across ALL * categories (dedupe + enrichment + reconciliation), newest first. */ jobs(opts?: { category?: string; }, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/jobs` — hard-delete every job for the tenant. */ purgeJobs(init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/jobs/{id}` — hard-delete one job. */ deleteJob(jobId: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/usage?days` — per-tenant API-usage report * (day-aligned request/latency/cost series + breakdowns + totals). */ usage(opts?: { days?: number; }, init?: RawInit): Promise; /** `POST /graphs/{tenant}/actions/find-merge-duplicates` — start a dedupe * job (second-pass entity resolution). Body `{kg_name}`. */ actionFindMergeDuplicates(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/actions/enrich` — start an enrichment job. Body * `{type_name, attributes, kg_name, tier?, …}`. */ actionEnrich(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/actions/suggest-relationships` — start a * reconciliation job. Body `{kg_name}`. Premium: degrades to a terminal * failed job when no recommender is registered. */ actionSuggestRelationships(body: unknown, init?: RawInit): Promise; /** `GET /graphs/{tenant}/enrich/jobs/{id}` — fetch a single job. */ enrichJob(jobId: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/enrich/jobs/{id}/wait?timeout_s=` — bounded * server-side long-poll until the job is terminal or the (capped) timeout. */ waitForJob(jobId: string, timeoutS?: number, init?: RawInit): Promise; /** `GET /graphs/{tenant}/enrich/jobs/{id}/conflicts` — conflict review queue. */ enrichConflicts(jobId: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/enrich/jobs/{id}/apply` — apply review decisions. */ enrichApply(jobId: string, body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/enrich/jobs/{id}` — cancel a job. */ enrichCancel(jobId: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/schedules` — list recurring schedules, oldest first. */ schedules(init?: RawInit): Promise; /** `POST /graphs/{tenant}/schedules` — create a recurring schedule. The * body's `action` must be a {@link UserSchedulableAction} (the backend * answers 422 for system-managed actions). Body * `{kg_name, category, action, params?, cron?|interval_seconds, enabled?}`. */ createSchedule(body: unknown, init?: RawInit): Promise; /** `PATCH /graphs/{tenant}/schedules/{id}` — enable/disable or update a * schedule. Only provided fields change. System-managed rows (a * non-{@link UserSchedulableAction} `action`, e.g. `semantic-reconcile`) * reject every PATCH with 403. */ updateSchedule(id: string, body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/schedules/{id}` — delete a schedule. */ deleteSchedule(id: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology` — effective layered workspace ontology * (ONTA-397/408 browser payload). */ ontology(init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology/type-counts` — workspace-wide Active * type counts (ONTA-409 KgStats union). */ ontologyTypeCounts(init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology/base-pin` — current pin + revision (ONTA-410). */ ontologyBasePin(init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology/base-pin/preview` — upgrade preview. */ ontologyBasePinPreview(query?: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ontology/base-pin/upgrade`. */ ontologyBasePinUpgrade(body?: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ontology/base-pin/rollback`. */ ontologyBasePinRollback(init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology/history` — grouped changelog (ONTA-410). */ ontologyHistory(query?: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology/diff` — structural ChangeRecords (ONTA-410). */ ontologyDiff(query?: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/ontology/types` — list ontology types. */ ontologyTypes(init?: RawInit): Promise; /** `POST /graphs/{tenant}/ontology/resolve` — resolve an NL ontology change. */ ontologyResolve(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ontology/recommend` — recommend ontology changes. * Premium route: only mounted on deployments with the proprietary layer, * 404s on bare OSS. */ ontologyRecommend(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ontology/apply` — apply one resolved change. */ ontologyApply(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/ontology/apply/batch` — apply many resolved changes * in one call. Body: `{ changes: ResolvedChange[] }`. */ ontologyApplyBatch(body: unknown, init?: RawInit): Promise; /** `GET /graphs/{tenant}/kgs` — list context graphs. */ kgs(init?: RawInit): Promise; /** `POST /graphs/{tenant}/kgs` — create a context graph. */ createKg(body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/kgs/{name}` — delete a context graph. */ deleteKg(name: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/explore/kgs/{kg}/types/{type}/summary`. */ exploreSummary(kg: string, typeName: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/explore/kgs/{kg}/types/{type}/records?limit&cursor`. */ exploreRecords(kg: string, typeName: string, opts?: { limit?: number; cursor?: string; }, init?: RawInit): Promise; /** `GET /graphs/{tenant}/explore/kgs/{kg}/type-edges`. */ exploreTypeEdges(kg: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/explore/kgs/{kg}/schema?type&min_coverage&include_empty&limit`. */ exploreSchema(kg: string, opts?: { types?: string[]; minCoverage?: number; includeEmpty?: boolean; limit?: number; }, init?: RawInit): Promise; /** `GET /graphs/{tenant}/kgs/{kg}/type-counts`. */ typeCounts(kg: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/kgs/{kg}/export?format&type&limit` (F10). */ exportKg(kg: string, opts?: { format?: "json" | "csv"; type?: string; limit?: number; }, init?: RawInit): Promise; /** `POST /graphs/{tenant}/search` — canonical semantic instance search * (ONTA-178). Body `{query, kg_name?, type?, top_k?}`. */ search(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/grep` — index-free literal scan of ONE KG * (ONTA-416). Body `{q, kg_name, type?, predicate?, case_sensitive?, limit?}`. */ grep(body: unknown, init?: RawInit): Promise; /** `GET /graphs/{tenant}/explore/search?kg&q&kind`. */ exploreSearch(kg: string, q: string, kind?: "type" | "attr", init?: RawInit): Promise; /** `POST /graphs/{tenant}/normalize/suggest?kg&type` — infer + persist rules. */ normalizeSuggest(kg: string, type: string, init?: RawInit): Promise; /** `GET /graphs/{tenant}/normalize/rules?kg&status` — list stored rules. */ normalizeRules(opts?: { kg?: string; status?: string; }, init?: RawInit): Promise; /** `POST /graphs/{tenant}/normalize/rules` — create a user-authored rule. */ normalizeCreateRule(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/normalize/rules/{id}/confirm`. */ normalizeConfirmRule(ruleId: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/normalize/rules/{id}/reject`. */ normalizeRejectRule(ruleId: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/normalize/rules/{id}/apply`. */ normalizeApplyRule(ruleId: string, init?: RawInit): Promise; /** `POST /v1/me/tenants` — create/grant a tenant for the authed user. */ createTenant(body: unknown, init?: RawInit): Promise; /** `PATCH /v1/me/tenants/{id}` — rename a tenant (label only; id is fixed). */ renameTenant(tenantId: string, body: unknown, init?: RawInit): Promise; /** `DELETE /v1/me/tenants/{id}` — remove a tenant grant. */ deleteTenant(tenantId: string, init?: RawInit): Promise; /** `GET /v1/me/tenants` — list tenants the authed user can access. */ tenants(init?: RawInit): Promise; /** `GET /graphs/{tenant}/api-sources` — list global (read-only) + tenant-custom * (editable) sources, each flagged by `layer` / `editable` / `has_secret`. */ apiSourcesList(init?: RawInit): Promise; /** `GET /graphs/{tenant}/api-sources/{slug}` — read one full spec (secrets * redacted) + `has_secret`. */ apiSourcesGet(slug: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/api-sources` — create a tenant-custom source. `body` * is `{spec, secrets?, enabled?}`; `secrets` is write-only, never returned. */ apiSourcesCreate(body: unknown, init?: RawInit): Promise; /** `PATCH /graphs/{tenant}/api-sources/{slug}` — edit a tenant-custom source * (spec / enabled / secrets). A global slug => 403. */ apiSourcesUpdate(slug: string, body: unknown, init?: RawInit): Promise; /** `DELETE /graphs/{tenant}/api-sources/{slug}` — delete a tenant-custom source * (+ its stored secrets). A global slug => 403. */ apiSourcesDelete(slug: string, init?: RawInit): Promise; /** `POST /graphs/{tenant}/api-sources/validate` — validate a spec (no write). * `body` is `{spec}`; returns `{valid, errors:[{path,message}]}`. */ apiSourcesValidate(body: unknown, init?: RawInit): Promise; /** `POST /graphs/{tenant}/api-sources/test` — run ONE smoke request (no write, * no persist). `body` is `{slug?, spec?, sample_params}`; a secret is never * echoed. Returns `{ok, rows, error?}`. */ apiSourcesTest(body: unknown, init?: RawInit): Promise; } /** Skills, functions, entity-detail, and workspace SDK types. Re-exported from ``client.ts`` so existing imports keep working. */ /** List/summary shape from `GET /graphs/{tenant}/skills`. */ interface SkillSummary { slug: string; type_name: string; title: string; summary: string; layer: string; enabled: boolean; version: number; body_chars: number; editable: boolean; } /** Full skill from get/create/update (`body` is the markdown). */ interface SkillDetail extends SkillSummary { body: string; metadata: Record; } /** Body of `POST /graphs/{tenant}/skills` (create-or-replace) and `/validate`. */ interface SkillWrite { slug?: string; type_name: string; body?: string; title?: string; summary?: string; enabled?: boolean; metadata?: Record; filename?: string; archive_b64?: string; } /** Body of `PATCH /graphs/{tenant}/skills/{type}/{slug}`. */ interface SkillPatch { body?: string | null; title?: string | null; summary?: string | null; enabled?: boolean | null; metadata?: Record | null; } interface SkillValidateResult { valid: boolean; errors: Array<{ message: string; }>; } /** Exact agent-injection text from `GET …/skills/prompt-block`. */ interface SkillsPromptBlock { text: string; skill_count: number; chars: number; } /** One registered function from `GET /graphs/{tenant}/functions`. */ interface FunctionRef { name: string; entity_type: string; description: string; endpoint_url?: string | null; tier?: string; layer?: string; } /** Body of `POST /graphs/{tenant}/functions`. `endpoint_url` is https or a Lambda ARN. */ interface FunctionRegister { name: string; entity_type: string; endpoint_url: string; description?: string; layer?: "tenant" | "enhanced" | "public"; } interface FunctionRegisterResult { registered: string; entity_type: string; layer: string; type_uri?: string; graph_uri?: string; [key: string]: unknown; } /** Body of `POST /graphs/{tenant}/functions/{name}/invoke`. */ interface FunctionInvokeRequest { entity_uri: string; kg_name: string; } interface FunctionInvokeResult { entity_uri: string; function: string; output: Record; discovered_entities?: Array>; duration_ms: number; [key: string]: unknown; } interface EntityRel { attr: string; rel_type: string; other_id: string; other_name?: string | null; other_type?: string | null; direction: string; } /** `GET /graphs/{tenant}/explore/kgs/{kg}/entities/{id}`. */ interface EntityDetail { id: string; name?: string | null; primary_type?: string | null; source?: string | null; labels?: string[]; properties?: Record; outgoing?: EntityRel[]; incoming?: EntityRel[]; [key: string]: unknown; } interface TenantInfo { id: string; label: string; role?: string; capability?: string; } interface RecomputeStatsResult { status: string; kg: string; [key: string]: unknown; } declare class ClientHttp { apiKey: string | undefined; baseUrl: string; tenant: string; /** In-flight heal for configs that still have tenant = Clerk user id. */ protected tenantHealPromise: Promise | null; constructor(opts?: ClientOptions); /** * If `this.tenant` is a Clerk user id (legacy login bug), resolve the first * real workspace via GET /v1/me/tenants and rewrite config + this.tenant. */ protected healTenantIfNeeded(): Promise; protected headers(): Record; protected base(): string; /** * Low-level passthrough request. Centralizes the absolute URL (already built * by a path-builder, so it carries the base URL + `/graphs/{tenant}` prefix), * the `X-API-Key` header, JSON content-type, body stringification, and a * timeout/abort — then returns the backend {@link Response} UNCHANGED. * * Unlike {@link request}, this does NOT inspect `res.ok` and does NOT parse or * reshape the body. A 4xx/5xx comes back as a resolved `Response` (the caller * reads `.status`/`.headers`/`.body`), NOT a thrown {@link InfonaError}. The * only rejection paths are a genuine network failure or a timeout abort — * exactly the cases where there is no HTTP response to hand back. * * `init.headers` is merged last so a caller can add/override headers; `init.body`, * when a non-string is passed, is JSON-stringified for convenience. */ requestRaw(method: string, path: string, init?: { body?: unknown; headers?: Record; timeoutMs?: number; }): Promise; /** * Probe the backend to determine reachability and whether endpoints * require an X-API-Key header. Used at shell startup to distinguish * cloud (auth required) from self-hosted open-access deployments. */ healthCheck(): Promise<{ ok: boolean; requiresAuth: boolean; url: string; neo4j?: boolean; status?: string; }>; protected request(method: string, url: string, body?: unknown, timeoutMs?: number): Promise; } declare class ClientIngest extends ClientHttp { /** * Ingest a file path or raw text into a context graph. * * If `pathOrText` points to an existing file, its contents are read and the * format is inferred from the extension (.csv, .json, .txt) unless * `contentType` is given. CSV files use the two-step schema-inference + row * mapping flow. */ ingest(pathOrText: string, opts?: IngestOptions): Promise>; /** `POST /graphs/{tenant}/ingest/dlt` — extract REST/SQL then ingest. */ ingestDlt(body: DltIngestRequest): Promise>; protected ingestCsv(content: string, opts: IngestOptions): Promise>; } declare class ClientApi extends ClientIngest { ask(question: string, opts?: AskOptions): Promise>; /** * One turn of the unified Ask-AI agent — the SINGLE conversational surface * (`POST /graphs/{tenant}/agent`, COG-118). Mirrors the HTTP contract exactly: * * - `confirmPlanId` set → the server runs `execute_plan` (the only mutating * path) and returns `{kind:"result", steps}`. Confirms are ONE-SHOT * server-side: a plan executes exactly once, so a duplicate confirm (a * retry after a gateway timeout, an auto-confirm double-fire) never * re-runs the steps — it replays the same result marked `replayed: true` * once finished, or errors with `code:"plan_already_executing"` while the * first confirm is still in flight. * - otherwise → the server runs `planner.handle(message)` and returns one of * `{kind:"answer"}` / `{kind:"clarify"}` / `{kind:"plan"}`. * * The agent classifies intent server-side and drives the underlying engines * through its capability registry — the client never talks to `/ask`, * `/enrich/*` etc. for an agent turn. ENTITLEMENT for any paid step a plan * contains is enforced server-side at execute time (the same authorization the * direct paid routes apply), so confirming a plan here cannot bypass a gate the * direct path enforces — the gate lives behind the endpoint, not in this client. */ agent(opts: AgentTurnOptions): Promise; /** List the tenants the authenticated user can access (GET /v1/me/tenants). * Keyed by the API key (X-API-Key → user), so it's independent of the active * tenant. Throws InfonaError with status 501 on deployments without a tenant * provider (e.g. OSS-only). */ listTenants(): Promise>; /** List all context graphs for the current tenant. */ listKgs(): Promise>>; /** Create a context graph. */ createKg(name: string, description?: string): Promise>; /** Delete a context graph by name. */ deleteKg(name: string): Promise>; /** * Export KG instance data (`GET /kgs/{kg}/export`). * JSON → parsed object; CSV → raw string body. */ exportKg(kg: string, opts?: { format?: "json" | "csv"; type?: string; limit?: number; }): Promise | string>; /** * Effective workspace ontology — layered C+A/B read with shadowing applied * (`GET /graphs/{tenant}/ontology`, ONTA-397/408). Returns the full browser * payload (`tenant_id`, `entitled`, `layers`, `types` with sources/skills * overlays). Empty is a normal `{ types: [] }`, never an error. */ ontology(): Promise>; /** * Workspace-wide Active type counts — union of `KgStats.type_breakdown` * across every KG in the tenant (`GET /graphs/{tenant}/ontology/type-counts`, * ONTA-409). Powers the Ontology viewer's Active / All pills. Types with * zero instances everywhere are omitted. Empty is `{ types: [] }`. */ ontologyTypeCounts(): Promise>; /** List ontology types. */ ontologyTypes(): Promise>>; /** * Resolve a natural-language ontology change against the existing ontology. * The caller does not need to know exact type/attribute/relationship names — * the server matches the plain-language `ask` to the current schema and * returns auto-applied changes plus proposals that need confirmation. */ ontologyResolve(ask: string, opts?: { knowledge_graph?: string; }): Promise; /** * Apply a single resolved ontology change — one of the `proposals` returned * by {@link ontologyResolve}. Pass the proposal object through unchanged. */ ontologyApply(proposal: ResolvedChange): Promise; /** * Apply MANY resolved changes in a single round-trip — the canonical * batch-apply route. Equivalent to calling {@link ontologyApply} once per * change (same idempotent upserts, applied in order) but one HTTP call * instead of N. Partial failure is well defined: the response reports each * change with `ok`/`error`, and a failed change does not abort the rest. * * Thin pass-through — the loop lives server-side; the client never * reimplements it (interface convergence). */ ontologyApplyBatch(changes: ResolvedChange[]): Promise; /** * Second-pass entity resolution: re-run ER over an already-ingested KG to * collapse intra-batch fragments. Synchronous on the server; returns a * per-type before/after report. Generous timeout — it rewrites triples. */ erRebuild(kg: string): Promise>; /** Per-KG type counts: every type with ≥1 instance, sorted desc. */ typeCounts(kg: string): Promise; /** Plan + run an enrichment job. Returns immediately with the job id. */ enrichRun(req: EnrichRequest): Promise; /** List recent enrichment jobs for the current tenant. */ enrichJobs(): Promise; /** * List ALL of a tenant's tracked jobs — dedupe, enrichment AND reconciliation * — newest first (`GET /graphs/{tenant}/jobs`, COG-101). This is the unified * feed the Jobs page renders; contrast {@link enrichJobs}, which lists only * enrichment jobs (`/enrich/jobs`). Pass `category` to filter to one kind. * Each item carries the unified summary fields (category, trigger, last_run, * next_run, cost(+note), status, progress_pct). */ jobs(opts?: { category?: JobCategory; }): Promise; /** Hard-delete every job for this tenant (`DELETE /graphs/{tenant}/jobs`). */ purgeJobs(): Promise<{ deleted: number; }>; /** Hard-delete one job (`DELETE /graphs/{tenant}/jobs/{id}`). */ deleteJob(jobId: string): Promise<{ deleted: boolean; job_id: string; }>; /** * Per-tenant API-usage report (`GET /graphs/{tenant}/usage?days=`): the * dashboard's usage panel data — day-aligned request / latency / cost * series with per-KG and per-API-key breakdowns, window + previous-window * totals for deltas, route-class counts and the month-to-date request * count. `days` defaults server-side to 30 (max 90). */ usage(opts?: { days?: number; }): Promise; /** Fetch a single enrichment job (with truncated results). */ enrichJob(jobId: string): Promise; /** * Wait for a job to settle, then return it (`GET …/enrich/jobs/{id}/wait`). * * The backend blocks SERVER-SIDE (async, never busy-waiting) until the job is * terminal or the bounded timeout elapses, then returns the job with its * current status. This is the efficient alternative to hammering * {@link enrichJob} in a client-side poll loop: web discovery / enrichment * jobs take minutes to settle, and one `waitForJob` call covers a whole * server-side wait window. * * @param timeoutS how long the SERVER should block, in seconds. Clamped * server-side to a hard cap (120s); omit to use the server default (60s). * @returns the job. If it is still `running`/`queued` when the server window * elapses, it comes back with that (non-terminal) status — NOT an error — * so a caller loops: `while (!isTerminalJobStatus(job.status)) job = * await client.waitForJob(job.id);`. A few iterations cover a multi-minute * job. Inspect {@link isTerminalJobStatus} to decide when to stop. */ waitForJob(jobId: string, timeoutS?: number): Promise; /** Fetch the conflict review queue for a job. */ enrichConflicts(jobId: string): Promise; /** Apply a set of conflict review decisions to a job. */ enrichApply(jobId: string, decisions: ConflictReview[]): Promise<{ applied: number; }>; /** Cancel an enrichment job. */ enrichCancel(jobId: string): Promise; /** Per-type breakdown for one type in one KG: definition + counts + samples. * * System predicates (rdfs:label, ingested_at, source) are hidden by default * — they're attached to every entity at 100% and drown out the columns the * user cares about. Pass `includeSystem: true` to see them. */ typeUsage(kg: string, typeName: string, opts?: { includeSystem?: boolean; }): Promise; } /** Explore, normalize, and API-source registry methods for the SDK client. */ declare class ClientExplore extends ClientApi { typeSummary(kg: string, typeName: string): Promise; /** * Population-aware schema for ONE context graph (`GET * /graphs/{tenant}/explore/kgs/{kg}/schema`, ONTA-418): every type with the * attributes/relationships that are actually POPULATED in that KG, with real * coverage percentages. * * Complements {@link ontologyTypes} (tenant-wide, declaration-only): this one * is KG-scoped and tells you which of the declared slots carry data, so a * caller never has to guess between similar names. * * Declared-but-empty types and attributes are returned MARKED * (`populated: false` / `declared_only: true`), never omitted. `minCoverage` * is the only filter that withholds slots, and the response reports how many * it withheld. * * A backend join by design (the interface-convergence rule): the whole-KG * stats are already materialized server-side, so this is one request rather * than a per-type fan-out. */ kgSchema(kg: string, opts?: { types?: string[]; minCoverage?: number; includeEmpty?: boolean; limit?: number; }): Promise; /** * Semantic instance search (`POST /graphs/{tenant}/search`, ONTA-178) — * "which entities talk about X?" answered by the backend's hybrid * lexical+vector index over marked free-text attributes, grouped by entity. * * This is THE canonical search operation every interface rides (the * interface-convergence rule): the MCP `search` tool, the CLI and the * webapp all call this method / route — never a bespoke endpoint. The * backend embeds the query server-side; when it can't (embedding service * down/unconfigured) it answers lexical-only and sets `degraded: true` — * surface that to users as "reduced recall", never silently. * * `topK` is clamped server-side to 1..50 (the response echoes the effective * value). An unknown `kg` yields empty hits, not an error. A deployment with * the semantic index gate (`INFONA_SEMANTIC_INDEX_ENABLED`) OFF does NOT * error: the vector leg is simply never populated, so the route degrades to * the keyword leg and answers 200 with `degraded: true`. (It historically * 503'd there; that dead-ended callers for no correctness benefit.) * * Both legs read the derived chunk index, so `search` cannot see a value that * has not been indexed yet — use {@link Client.grep} for an index-free literal * scan of a single KG when you need "is this exact string in my graph?". * * `entityUris` is a structured pre-filter (filter-then-semantic): pass entity * URIs from SPARQL / your own logic so hybrid ranking only considers that * set. Omit/`undefined` = no URI filter; `[]` = zero hits (strict empty * allowlist); server blanks-strip + dedupes and 400s above 500 unique URIs. * Combined with `kg` / `type` via AND, applied inside ranking legs before * LIMIT (not a post-hoc top_k shrink). */ search(query: string, opts?: SemanticSearchOptions): Promise; /** * Index-free literal grep over ONE knowledge graph * (`POST /graphs/{tenant}/grep`, ONTA-416) — "is this exact string anywhere in * my graph?" answered by a live SPARQL scan of the KG's triples. * * The debugging counterpart to {@link Client.search}, and a SEPARATE canonical * route because its contract inverts search's on every axis: it reads the * triple store (not the derived chunk index), so it finds values that were * never indexed; `kg` is REQUIRED (an index-free scan must be bounded); a hit * is ONE matching triple, not a ranked entity; and results are in scan order, * not ranked. * * Because the scan has no supporting index, the server guards it: the needle * must carry >= 2 non-whitespace characters (else 400), `limit` is clamped to * 1..200 and echoed, the scan runs under a short dedicated timeout, and the * route is rate-limited. `truncated: true` means the limit was hit and more * matches exist. A deployment may disable the surface entirely * (`INFONA_GREP_ENABLED=false`), which answers 503 naming the gate (thrown * here as an InfonaError). */ grep(q: string, kg: string, opts?: { type?: string; predicate?: string; caseSensitive?: boolean; limit?: number; }): Promise; /** Search types or attributes by name substring within a KG. */ exploreSearch(kg: string, q: string, kind?: "type" | "attr"): Promise>>; /** * One page of entity instances of a type for the Explorer Data table * (`GET /explore/kgs/{kg}/types/{type}/records`). Keyset-paginated by entity * URI: pass the previous page's `next_cursor` as `cursor`. `limit` is clamped * server-side to 1..200 (default 50). */ exploreRecords(kg: string, typeName: string, opts?: { limit?: number; cursor?: string; }): Promise; /** Undirected type→type edges for the Explorer overview graph * (`GET /explore/kgs/{kg}/type-edges`). Returns `[{source, target, weight}]`. */ exploreTypeEdges(kg: string): Promise; /** Infer + persist normalization rules for a type's predicates, returned ranked * by confidence desc (`POST /normalize/suggest?kg&type`). */ normalizeSuggest(kg: string, type: string): Promise; /** List stored normalization rules, optionally filtered by KG and/or status * (`GET /normalize/rules?kg&status`). */ normalizeRules(opts?: { kg?: string; status?: string; }): Promise; /** Confirm a suggested normalization rule (`POST /normalize/rules/{id}/confirm`). */ normalizeConfirmRule(ruleId: string): Promise; /** Reject a suggested normalization rule (`POST /normalize/rules/{id}/reject`). */ normalizeRejectRule(ruleId: string): Promise; /** Apply a confirmed normalization rule in the background; the server acks 202 * (`POST /normalize/rules/{id}/apply`). */ normalizeApplyRule(ruleId: string): Promise>; /** Recommend ontology relationships/changes for the active KG * (`POST /ontology/recommend`). Body shape is passed through unchanged. * * NOTE: this targets the *premium* ontology-recommender route, which is only * mounted on deployments carrying the proprietary layer. It 404s on a bare * OSS deployment. */ ontologyRecommend(body?: Record): Promise>; /** List global (read-only) + tenant-custom (editable) sources. */ apiSourcesList(): Promise; /** Read one source's full spec (secrets redacted) + `has_secret` / `editable`. */ apiSourcesGet(slug: string): Promise>; /** Create a tenant-custom source. `body` is `{spec, secrets?, enabled?}`. */ apiSourcesCreate(body: ApiSourceWrite): Promise; /** Edit a tenant-custom source (spec / enabled / secrets). Global slug => 403. */ apiSourcesUpdate(slug: string, body: ApiSourceWrite): Promise; /** Convenience: enable/disable a tenant-custom source (folds into update). */ apiSourcesSetEnabled(slug: string, enabled: boolean): Promise; /** Delete a tenant-custom source (+ its secrets). Global slug => 403. */ apiSourcesDelete(slug: string): Promise<{ ok: boolean; }>; /** Validate a spec (no write). `body` is `{spec}`. */ apiSourcesValidate(spec: Record): Promise; /** Run ONE smoke request (no write, no persist). Provide `slug` OR inline * `spec` (+ `sample_params`). A secret is never echoed. */ apiSourcesTest(body: { slug?: string; spec?: Record; sample_params?: Record; }): Promise; extractSourcesList(): Promise; extractSourcesGet(slug: string): Promise>; extractSourcesCreate(body: ExtractSourceWrite): Promise; extractSourcesUpdate(slug: string, body: ExtractSourceWrite): Promise; extractSourcesDelete(slug: string): Promise<{ ok: boolean; }>; extractSourcesRun(slug: string, body?: { kg?: string; limit?: number; }): Promise>; /** Connector templates for the connect flow (ONTA-555). Static per release — * served from the backend so every client offers the same catalog. */ extractCatalog(): Promise; /** Set how often a saved source is re-read (ONTA-555). */ extractScheduleSet(slug: string, body: ExtractScheduleWrite): Promise; /** Stop recurring reads. The source stays, runnable on demand. */ extractScheduleClear(slug: string): Promise; } /** Skills, functions, entity detail, and workspace methods for the SDK client. Path builders live here (not on ClientHttp) so that file stays under the size budget. RawApi reaches the same builders via ``this.client.pSkills`` etc. */ declare class ClientSkills extends ClientExplore { /** List resolved skills (`GET /graphs/{tenant}/skills`). */ listSkills(typeName?: string): Promise; /** Read one skill, full body (`GET …/skills/{type}/{slug}`). */ getSkill(typeName: string, slug: string): Promise; /** Create or replace a tenant skill (`POST /graphs/{tenant}/skills`). */ createSkill(body: SkillWrite): Promise; /** Partially update a tenant skill (`PATCH …/skills/{type}/{slug}`). */ updateSkill(typeName: string, slug: string, body: SkillPatch): Promise; /** Delete a tenant skill (`DELETE …/skills/{type}/{slug}`). */ deleteSkill(typeName: string, slug: string): Promise<{ ok: boolean; }>; /** Validate a skill body with no write (`POST …/skills/validate`). */ validateSkill(body: SkillWrite): Promise; /** * Exact text an agent is handed for these types * (`GET …/skills/prompt-block`). Clients must not re-render locally. */ skillsPromptBlock(typeNames?: string[]): Promise; /** List function attachments (`GET /graphs/{tenant}/functions`). */ listFunctions(entityType?: string): Promise; /** Attach an endpoint URL to a type (`POST /graphs/{tenant}/functions`). */ registerFunction(body: FunctionRegister): Promise; /** Invoke a registered function (`POST …/functions/{name}/invoke`). */ invokeFunction(name: string, body: FunctionInvokeRequest): Promise; /** * Delete a function attachment (`DELETE …/functions/{name}?entity_type=`). * `entityType` is required: attachment identity is (tenant, type, name). */ deleteFunction(name: string, opts: { entityType: string; }): Promise>; /** Alias of {@link typeSummary} — same `GET …/types/{type}/summary` route. */ exploreSummary(kg: string, typeName: string): Promise; /** Entity detail (`GET …/explore/kgs/{kg}/entities/{id}`). */ getEntity(kg: string, entityId: string): Promise; /** Create a workspace (`POST /v1/me/tenants`). Empty body mints Untitled N. */ createTenant(body?: { label?: string; id?: string; }): Promise; /** * Schedule a type-stats recompute (`POST …/explore/kgs/{kg}/recompute-stats`). * Rewrites the stats graph, not instance data. */ recomputeStats(kg: string): Promise; } /** Infona SDK client — typed + raw access to the canonical backend. Implementation lives in sibling ``client*.ts`` modules. Every previously importable name is re-exported here. Interface/endpoint convergence: clients reach the backend through these path builders, not hand-rolled URLs. */ declare class Client extends ClientSkills { /** * Raw / passthrough API — one method per canonical backend operation, with * the path encoded inside the SDK. Each method returns the backend * Response VERBATIM: it does NOT throw on non-2xx and does NOT reshape * the body. */ readonly raw: RawApi; constructor(opts?: ClientOptions); } export { type AgentResult, type AgentTurnOptions, type ApiSourceSummary, type ApiSourceTestResult, type ApiSourceValidateResult, type ApiSourceValidationError, type ApiSourceWrite, type AskOptions, Client, type ClientOptions, type ConflictPolicy, type ConflictReview, type ConnectorTemplate, type DltAuthSpec, type DltAuthType, type DltIngestRequest, type DltResourceMap, type DltSourceKind, type DltSourceSpec, type EnrichJob, type EnrichJobCreate, type EnrichRequest, type EnrichmentTier, type EntityDetail, type EntityRel, type ExtractSchedule, type ExtractScheduleWrite, type ExtractSourceSummary, type ExtractSourceWrite, type FunctionInvokeRequest, type FunctionInvokeResult, type FunctionRef, type FunctionRegister, type FunctionRegisterResult, type GrepMatch, type GrepResponse, InfonaError, type IngestOptions, type JobCategory, type JobProgress, type JobStatus, type JobSummary, type KgSchema, type KgSchemaType, type NormalizationRule, type OntologyApplyBatchResult, type OntologyApplyChangeResult, type OntologyApplyResult, type OntologyResolveResult, RawApi, RawExtractApi, type RawInit, RawSkillsApi, type RecomputeStatsResult, type ResolvedChange, type ReviewDecision, type RowAction, type RowResult, type Schedule, type ScheduleAction, type SchemaAttribute, type SchemaRelationship, type SemanticSearchHit, type SemanticSearchOptions, type SemanticSearchResponse, type SkillDetail, type SkillPatch, type SkillSummary, type SkillValidateResult, type SkillWrite, type SkillsPromptBlock, TERMINAL_JOB_STATUSES, type TenantInfo, type TypeEdge, type TypeRecord, type TypeRecordsPage, type TypeSummary, USER_SCHEDULABLE_ACTIONS, type UsageMetricBlock, type UsageReport, type UsageSeries, type UsageTotals, type UserSchedulableAction, type Verdict, isTerminalJobStatus };