import { SupportedCurrency } from './currency'; export type CueEnvironment = 'production' | 'emulator'; export interface CueEndpoints { /** API gateway base URL */ gatewayUrl: string; /** Token exchange endpoint for API key sign-in */ tokenUrl: string; /** Firebase Auth emulator URL */ authEmulatorUrl: string; /** Firebase Storage emulator hostname, no protocol (emulator mode only, default: 'localhost') */ storageEmulatorHost: string; /** Firebase Storage emulator port (emulator mode only, default: 9199) */ storageEmulatorPort: number; /** Firebase Firestore emulator hostname, no protocol (emulator mode only, default: 'localhost') */ firestoreEmulatorHost: string; /** Firebase Firestore emulator port (emulator mode only, default: 8080) */ firestoreEmulatorPort: number; } export interface CueSdkConfig { /** Firebase API key for this project. Defaults to the QAECY demo app if omitted. */ apiKey?: string; /** Firebase App ID. Defaults to the QAECY demo app if omitted. */ appId?: string; /** Firebase Measurement ID. Defaults to the QAECY demo app if omitted. */ measurementId?: string; /** Target environment. Defaults to 'production'. */ environment?: CueEnvironment; /** Override individual endpoint URLs. Takes precedence over environment. */ endpoints?: Partial; /** Enable verbose debug logging for all entity/document store operations. */ verbose?: boolean; } export type SsoProvider = 'google' | 'microsoft'; export interface PasswordCredentials { email: string; password: string; } export interface SearchRequest { /** Natural language query or search term */ term: string; /** Project ID to search within */ projectId: string; /** Optional category filters */ categories?: string[]; } /** Options for `CueProjectView.search()`. */ export interface SearchOptions { /** Optional content category IRI filters. */ categories?: string[]; } export interface SearchSource { item: string; parent: string; content: string; } export interface SearchResponse { id: string; question: string; questionHTML: string; response: string; sources: SearchSource[]; rankedSources: SearchSource[]; } export interface ContextItem { id: string; type: string; relevance: number; info: Record; sub_items: ContextItem[]; } export interface ContextDoc { id: string; total: number; operation: { type: string; }; input: string; items: ContextItem[]; within: string[]; meta: { time_created: string; }; } /** * The standard result every Cue Index MCP *data tool* returns * (`search`, `lookup`, `traverse`, `combine`, `select`, `schema`, `inspect`): * `id` is the persistent context the call produced, `text` is the stringified * snippet the tool renders for the calling agent. {@link CueMcp.callTool} * proxies this object through exactly as the endpoint returns it. */ export interface McpContext { id: string; text: string; } export interface ProjectSettings { views?: Array<{ id: string; pinned?: boolean; }>; chatDisabled: boolean; graph?: { type: 'qlever' | 'fuseki'; uri?: string; }; /** Processing tier determining credit costs. Defaults to "l" if not set. */ tier?: 's' | 'm' | 'l'; } export interface QleverStats { /** ISO timestamp of when this index was first created (init or clone) — null for indexes built before this field existed. */ created: string | null; builtAt: string | null; qleverVersion: string | null; numTriples: number | null; numSubjects: number | null; numPredicates: number | null; numObjects: number | null; numDocuments: number | null; /** ISO timestamp of the last build whose triple/subject/predicate counts actually differed from the build before it. */ lastChanged: string | null; indexSizeBytes: number | null; updateFractionPct: number | null; lastQueriedAt: string | null; resolvedMentions: number | null; unresolvedMentions: number | null; /** Percentage of entity mentions that are resolved: (resolved / total) * 100 */ resolutionPct: number | null; avgEntitiesPerDoc: number | null; } export interface ProjectData { id: string; name: string; organizationID: string; created: string; isPublic: boolean; members: string[]; syncers: string[]; admins: string[]; alternativeIDs: string[]; projectSettings: ProjectSettings; qleverStats?: QleverStats | null; } export interface CreateProjectOptions { /** The organization this project belongs to */ organizationID: string; /** Human-readable project name */ name: string; /** Explicit project ID. Defaults to a new UUID. */ id?: string; /** UIDs to set as project admins. Non-superadmin callers are always included automatically. */ admins?: string[]; /** UIDs to set as project syncers. Non-superadmin callers are always included automatically. */ syncers?: string[]; /** UIDs to set as project members. Non-superadmin callers are always included automatically. */ members?: string[]; /** Graph backend type. The service maps this to the configured URI. */ graphType?: 'fuseki' | 'qlever'; /** Processing tier determining credit costs. */ tier?: 's' | 'm' | 'l'; } export interface SyncProgress { percent: number; syncCount: number; totalCount: number; syncSize: number; totalSize: number; } export interface SyncOptions { /** The project/space ID to sync into */ spaceId: string; /** Provider ID identifying the file source (e.g. 'local', 's3') */ providerId: string; /** Authenticated user ID */ userId: string; /** Enable verbose logging */ verbose?: boolean; /** Called whenever upload progress changes */ onProgress?: (progress: SyncProgress) => void; /** Write RDF as BLOBs to the processed bucket instead of patching the graph directly */ legacy?: boolean; } /** * Credit cost table fetched from the public bucket (`unit-credit.json`). * Maps size tier → file extension → credits per unit. */ export type UnitCreditMap = Partial>>; /** Per-extension cost breakdown returned by {@link CueSyncApi.scanCost}. */ export interface ScanOutputRecord { /** File extension (without leading dot), e.g. `"pdf"`, `"ifc"`. */ ext: string; /** Number of files with this extension. */ count: number; /** Share of this extension among supported files (0–100). */ percentOfFiltered: number; /** Share of this extension among all files (0–100). */ percentOfAll: number; /** Billable units for this extension (e.g. pages for PDFs, rows for spreadsheets). */ units: number; /** Total size of files with this extension in megabytes. */ sizeMb: number; /** Credits to consume for this extension (units × credit-per-unit for the project tier). */ credits?: number; } export interface UnitsConsumedDto { creditsAvailable: number; creditsConsumed: number; filesProcessed: number; unitsAvailable: number; unitsConsumed: number; } export interface ShaclViolation { '@type': string; 'sh:focusNode': { '@id': string; } | { '@value': string; }; 'sh:resultPath'?: { '@id': string; }; 'sh:resultSeverity': { '@id': string; }; 'sh:sourceConstraintComponent': { '@id': string; }; 'sh:sourceShape'?: { '@id': string; }; 'sh:resultMessage': string; 'sh:value'?: string; } export interface ShaclValidationReport { '@context': Record; '@type': string; 'sh:conforms': boolean; 'sh:result'?: ShaclViolation[]; } export interface SyncPreview { /** Per-extension cost breakdown for files not yet synced */ costRecords: ScanOutputRecord[]; /** Project tier used for cost calculation */ tier: 's' | 'm' | 'l'; /** Human-readable tier name from tier-names.json */ tierName: string; /** Total units required for the new files */ unitsToConsume: number; /** Total credits to consume (derived from unit-credit.json + project tier) */ creditsToConsume: number; /** Credits currently available for this project */ creditsAvailable: number; /** Units still available for this project */ unitsAvailable: number; /** Number of new files that would be uploaded */ filesToUpload: number; /** Total local files scanned */ totalLocalFiles: number; } export interface SyncResult { /** Number of files successfully synced in this run */ syncCount: number; /** Total bytes synced in this run */ syncSize: number; /** Number of files that failed to upload */ failedUploads: number; /** Total file count (local + remote combined) */ totalCount: number; /** Total size across all files */ totalSize: number; /** Whether any RDF metadata was written */ rdfWritten: boolean; /** Updated credit balance after sync, fetched from the consumption endpoint */ creditsAvailable: number; } export interface OrgMember { uid: string; name: string; email: string; isAdmin: boolean; } export interface OrganizationData { id: string; name: string; created: string; admins: string[]; members: string[]; alternativeIDs: string[]; domain: string; } /** Org's current plan — no Stripe ids exposed to the frontend. */ export interface OrgPlanSummary { type: 'freemium' | 'custom'; status: 'active' | 'pendingPayment' | 'cancelled'; monthlySpendChf?: number; pricePerCredit?: number; creditsPerMonth?: number; discountPct?: number; } /** * Org-level credit pool. Purchased credits are shared across every project * the org owns — there is no per-project allocation. `available` is * `purchased` minus the sum of every owned project's consumption. */ export interface OrgCreditsDto { purchased: number; consumed: number; available: number; plan: OrgPlanSummary; } /** Consumption for a single calendar month (`YYYY-MM`, UTC), keyed by the file's own upload time. */ export interface MonthlyConsumptionDto { unitsConsumed: number; creditsConsumed: number; filesProcessed: number; } export interface ProjectConsumptionReportDto { projectId: string; name?: string; /** Keyed by `YYYY-MM` (UTC). */ monthly: Record; } /** Per-project, per-month consumption breakdown for an org — see {@link OrgCreditsDto} for the org-level totals. */ export interface OrgConsumptionReportDto { projects: ProjectConsumptionReportDto[]; } export interface ProfileSSOAccount { id: string; label: string; } export interface APIKeyInfo { key: string; expiration: string; } export interface APIKeyDoc { key: string; uid: string; expiration: string; } /** Alias for {@link ProjectData} — the Firestore document shape for a project. */ export type ProjectDoc = ProjectData; /** Alias for {@link OrganizationData} — the Firestore document shape for an org. */ export type OrganizationDoc = OrganizationData; export interface UserDoc { id: string; name: string; email: string; created: string; lastVisit: string; lastVisitProjects?: Record; organizations: string[]; /** @deprecated Use {@link UserSettings.language} via `cue.api.userSettings` instead. */ locale?: string; hasAcceptedTermsAndConditions: boolean; } /** * Global, per-user app preferences — a small JSON blob stored via * `cue.api.userSettings`. Replaces the old Firestore `UserDoc.locale` field. * Extend with more optional fields as new preferences are added; the backend * stores this as an opaque blob, so no schema migration is needed. */ export interface UserSettings { language?: string; /** Grants access to the beta-features toggle. Not self-service — set by an admin/operator. */ betaTester?: boolean; /** User-controlled visibility of beta features, only meaningful when `betaTester` is true. */ showBetaFeatures?: boolean; /** Preferred display currency for pricing UIs (credits page, sign-up). Billing itself stays CHF. */ currency?: SupportedCurrency; /** User-controlled visibility of super-admin-only views (e.g. project workspace advanced stats). Only meaningful for users with the `superadmin` claim. */ showSuperAdminFeatures?: boolean; } /** Metadata for a Studio app saved and shared within an organization via `cue.api.apps`. */ export interface CustomAppRecord { id: string; organizationID: string; name: string; description: string; icon: string; tone: string; authorId: string; authorName: string; createdAt: string; updatedAt: string; } /** Full custom app record including its HTML body, as returned by `cue.api.apps.get`. */ export interface CustomAppWithHtml extends CustomAppRecord { html: string; } export interface CreateCustomAppOptions { organizationID: string; name: string; description?: string; icon?: string; tone?: string; /** Denormalized display name for the "author" badge — typically `cue.auth.user()?.displayName`. */ authorName?: string; html: string; } export interface UpdateCustomAppOptions { name?: string; description?: string; icon?: string; tone?: string; html?: string; } export interface RDFWritingDoc { id: string; accumulatedSizeSinceLastIdleEvent: number; accumulatedFilesSinceLastIdleEvent: number; firstRDFWrite: string; lastRDFWrite: string; } export type ProcessingStage = 'idle' | 'writing' | 'loading' | 'enriching'; /** * Aggregated, per-project pipeline status pushed live by the `accessors-data-views` * processing-status WebSocket (see `CueProcessingApi.watchStatus`). Shape mirrors * `cue-ui`'s `ProcessingStatus` (views/project-settings/models.ts) so it can be * passed straight through to `` / ``. */ export interface ProcessingStatus { stage: ProcessingStage; accumulatedSizeSinceLastIdleEvent: number; accumulatedFilesSinceLastIdleEvent: number; firstRDFWrite: string; lastRDFWrite: string; loadingTriggeredAt?: string; resolutionTriggeredAt?: string; lastResolutionActivityAt?: string; enrichmentTotalBatches?: number; enrichmentCompletedBatches?: number; } export interface ViewDefinition { id: string; pinned?: boolean; } /** * Minimal cache interface for SPARQL query results. * * Implement this against any storage backend (Cloud Storage, localStorage, * IndexedDB, in-memory Map) and pass it to the project-view classes to enable * stale-while-revalidate query caching. * * The Angular adapter wires this to `CueCache` from `cue-repos`. */ export interface QueryCache { get(key: string): Promise; set(key: string, data: unknown): Promise; } /** * A multilingual string keyed by BCP-47 language tag. The special `default` * key always resolves to the English value (or, when no English value exists, * to the untagged/first available value). */ export type LangMap = { [lang: string]: string; }; /** A taxonomy node (content category or entity category) from the triplestore. */ export interface CategoryDef { iri: string; /** * Label resolved for the currently active language (falls back to `default` * / English). This is a computed convenience view of {@link CategoryDef.labels}. */ label: string; /** * Definition resolved for the currently active language (falls back to * `default` / English). Computed view of {@link CategoryDef.definitions}. */ definition?: string; /** Full set of labels keyed by language tag (plus a `default` key). */ labels: LangMap; /** Full set of definitions keyed by language tag (plus a `default` key). */ definitions?: LangMap; /** IRI of the parent category (skos:broader), if any. */ parent?: string; /** Whether this category is marked as deprecated in the triplestore. */ deprecated?: boolean; } /** * A relationship type discovered in the triplestore via `qcy:relatedEntity` property scan. * The IRI is the property IRI, label is its rdfs:label. */ export type RelationshipDef = CategoryDef; /** Core label + classification data for a single entity. */ export interface EntityCoreData { value: string; categories: string[]; mentionCount?: number; } /** A single directed relationship edge between two entities. */ export interface EntityRelationship { /** IRI of the property used (e.g. `qcy:hasContractor`). */ relIRI: string; /** Full IRI of the related entity. */ nodeIRI: string; /** Label of the related entity. */ nodeValue: string; /** Category IRIs of the related entity. */ nodeCategories: string[]; } /** Incoming and outgoing relationship edges for one entity. */ export interface EntityRelationships { incoming: EntityRelationship[]; outgoing: EntityRelationship[]; } /** An OSM geometry associated with an entity or related entity. */ export interface MapGeometry { osmIRI: string; wkt: string; } /** Fully resolved data for a single entity, merging all lazy-loaded slices. */ export interface EntityDetailedData extends EntityCoreData { relationshipData?: EntityRelationships; /** UUIDs of documents that reference this entity. */ documentRefs?: string[]; directMapGeometries?: MapGeometry[]; indirectMapGeometries?: Array<{ rel: string; entityUUID: string; geometries: MapGeometry[]; }>; } /** * Project-level entity category graph — nodes are category IRIs, edges * represent the `qcy:relatedEntity` connection at the category level. */ export interface ProjectEntitiesData { entities: Array<{ iri: string; size?: number; }>; relations: Array<{ sourceID: string; targetID: string; }>; } /** * Structured summary graph returned by `buildSummaryGraph('graph')`. * Nodes are deduplicated category IRIs; edges carry the predicate and * occurrence count from the summary query. */ export interface SummaryGraphData { /** `weight` is the number of entity instances in that category — undefined if the count query failed. */ entities: Array<{ iri: string; weight?: number; }>; relations: Array<{ sourceID: string; predicate: string; targetID: string; weight: number; }>; } /** Core metadata for a single document (FileContent node). */ export interface DocumentInfo { id: string; contentIRI: string; path: string; suffix: string; size: number; tags: string[]; categories: string[]; subject?: string; summary?: string; providerId?: string; /** Full storage path in the processed bucket (e.g. `{projectId}/fragments/{uuid}.fragments`). * Only present on alternative representations that carry a `qcy:remoteRelativePath`. */ remoteRelativePath?: string; } /** Count + total size for a group of documents (e.g. grouped by suffix or category). */ export interface DocumentSummary { size: number; count: number; } /** Project-level document overview — fetched once on project init. */ export interface ProjectDocumentsData { duplicateCount: number; /** File extension → `{ size, count }` */ documentsBySuffix: Record; /** Content-category IRI → `{ size, count }` */ documentsByContentCategory: Record; } /** * A single dimension of a document filter expression. * * `included` IRIs are OR-ed together (document must have at least one). * `excluded` IRIs are AND-NOT-ed (document must not have any). * Multiple `SearchFilter` objects are AND-ed across dimensions. * * Type semantics: * - `entity` — document is *about* an entity of the given category IRI(s). * - `entityInstance` — document is *about* the given specific entity IRI(s) * (e.g. the canonical entity "John Doe", not the category "Person"). */ export interface SearchFilter { type: 'content' | 'mime' | 'entity' | 'entityInstance' | 'suffix'; included: string[]; excluded: string[]; } /** A single filter option (IRI + human-readable label) returned by the document filter. */ export interface DocumentFilterOption { iri: string; label: string; } /** Available filter options grouped by dimension, returned by {@link CueDocumentFilter.availableFilters}. */ export interface AvailableDocumentFilters { mimes: DocumentFilterOption[]; contents: DocumentFilterOption[]; entityCategories: DocumentFilterOption[]; } export interface IndexSearchRequest { input: string; limit?: number; aggregate?: boolean; /** `'loose'` (default) allows partial matches; `'strict'` requires exact term presence. */ mode?: 'loose' | 'strict'; /** Pre-seed the context with these document UUIDs before running the search. */ identifiers?: string[]; } export interface IndexItem { id: string; type: string; relevance: number; sub_items?: IndexItem[]; } export interface IndexSearchResponse { id?: string; total?: number; items: IndexItem[]; } /** * A single filter option returned by {@link CueIndexApi.availableFilters}. * Contains both the IRI (for use as a filter value) and a human-readable label. */ export interface IndexFilterOption { iri: string; label: string; } /** * Applied filters passed to {@link CueIndexApi.availableFilters} to constrain * which options are returned. Each array contains IRIs of the currently active * filter values for that dimension. */ export interface IndexAppliedFilters { /** MIME category IRIs currently included (e.g. `'application/pdf'`). */ mimes?: string[]; /** Content category IRIs currently included. */ contents?: string[]; /** Entity category IRIs currently included — documents must mention at least one entity of each. */ entityCategories?: string[]; } /** * Response from {@link CueIndexApi.availableFilters}. Each array lists the * filter options that exist in the document set surviving the applied filters. * Used to drive adaptive filter UIs where subsequent dropdowns narrow to only * what is actually present after earlier selections. */ export interface AvailableFiltersResponse { mimes: IndexFilterOption[]; contents: IndexFilterOption[]; entityCategories: IndexFilterOption[]; }