/** * Plugin configuration. Every deployment-varying choice is a validated * `Config` field; the schema fills defaults and `resolveConfig` enforces the * constraints Schemastery cannot express (loopback-only `baseUrl`, positive * finite limits) at load time, failing loud on misconfiguration. * * Fields are `volatile`: the settings page edits the live entry without * remounting. `Config` is what the loader hands the constructor (references); * `Options` is what humans write (plain values); `resolveConfig` accepts * either, unwraps, and validates. * @module dsh-zotero/config */ import type { Volatile } from '@deepseek-ai/cordis'; import Schema from '@deepseek-ai/schemastery'; export interface Config { /** Zotero Local API base URL. Must be plain loopback HTTP. */ baseUrl?: Volatile; /** Provider id to select; the built-in local provider registers as `local`. */ provider?: Volatile; /** Per-request provider deadline in milliseconds. */ timeoutMs?: Volatile; /** * Upper bound for concurrent in-flight requests to the Local API. Each * domain pool bounds one call's fan-out; this is the process-wide slot * count, the real bound on what Zotero is asked to serve at once. Two calls * run at full width, and a burst queues instead of stacking. */ maxInFlightRequests?: Volatile; /** Upper bound for `zotero_search` `limit`. */ maxSearchResults?: Volatile; /** Upper bound for note records `zotero_search` scans for body matches. */ maxNoteScanRecords?: Volatile; /** * Parallel parent-attribution queries `zotero_search` may keep in flight * (`ZOTERO_ITEMKEY_BATCH` itemKeys each). */ searchConcurrency?: Volatile; /** Total character budget for retrieved evidence passages. */ maxEvidenceChars?: Volatile; /** Upper bound for the number of evidence passages. */ maxEvidencePassages?: Volatile; /** Character budget for the `zotero_get` abstract preview. */ maxDetailChars?: Volatile; /** Character budget for a note item's own body returned by `zotero_get`. */ maxNoteBodyChars?: Volatile; /** Per-note character budget for `zotero_get` note previews. */ maxNoteChars?: Volatile; /** Upper bound for note records returned by `zotero_get`. */ maxNoteRecords?: Volatile; /** Upper bound for annotation records returned by `zotero_get`. */ maxAnnotationRecords?: Volatile; /** Upper bound for attachment records returned by `zotero_get` and `zotero_children`. */ maxAttachmentRecords?: Volatile; /** Word count of each full-text passage entering evidence ranking. */ fulltextChunkWords?: Volatile; /** Character bound for full text accepted into `zotero_retrieve` ranking. */ maxFulltextChars?: Volatile; /** * Upper bound for attachments one `zotero_retrieve` call ranks full text * from: each member costs a metadata read and a full-text read and all of * their text enters one ranking. `specified` rejects a longer list; * `allIndexed` reads the first entries in selection order and reports the * rest as unread. */ retrieveAttachmentCap?: Volatile; /** Parallel attachment reads `zotero_retrieve` may keep in flight; annotation children ride the single `?itemType=annotation` listing instead. */ graphConcurrency?: Volatile; /** Streaming byte bound for every API response body. */ maxResponseBytes?: Volatile; /** Provider hard limit for export output; the model-facing inline budget is deployment spill policy. */ maxExportChars?: Volatile; /** Upper bound for refs in one `zotero_export` call; citation batches up to this value, the other formats refuse to exceed the API's 50-key request cap. */ maxExportRefs?: Volatile; /** Upper bound for items a browse call may return */ maxBrowseResults?: Volatile; /** Display cap for `zotero_changes` listings; the diff itself always reads the whole range. */ maxChangesResults?: Volatile; /** How long a collections/searches scope listing is trusted before a re-read (ms); the provider reads it live, so an edit applies to the next lookup without rebuilding the transport. */ scopeListingTtlMs?: Volatile; /** CSL style for citation/bibliography formats; must be bundled with Zotero (e.g. `apa`). */ defaultStyle?: Volatile; /** CSL locale for citation/bibliography formats. */ defaultLocale?: Volatile; /** * Whether the write tools register and the `local` provider serves writes * (research notes, tags, collection membership). Off by default: writing * is an explicit opt-in, and the capability stays absent until it is. */ writeEnabled?: Volatile; /** * Whether an Always-Allow grant from Zotero's authorization dialog is * persisted into the host credentials store (bound to the Zotero instance * that issued it). One-time keys are never persisted regardless. */ writePersistKey?: Volatile; /** Character budget for one research note body write; the converted HTML rides the batch's successful bucket (bounded by `maxResponseBytes`), and this bound keeps one pathological note from dominating a batch. */ writeNoteMaxChars?: Volatile; /** Upper bound for items in one tags/collection-membership write's list arguments, the same scale as the write batch cap, so one call cannot fan out into many protocol batches. */ writeListMaxItems?: Volatile; /** Deadline for the Zotero authorization dialog during a write (ms). That request waits for a person to read the dialog, so it is independent of `timeoutMs` and deliberately far above it. */ writeAuthorizeDeadlineMs?: Volatile; /** * Whether the dedicated Zotero web view (tool cards in a conversation tab) is enabled. * Client-only: the host half never reads this (it shares the `zotero` * settings namespace so the card and the tab stay on one document); only * `src/client/` gates on it. Do not branch host behavior on it. */ webEnabled?: Volatile; /** * Allow the explicit `run_in_background` parameter on heavy tools. Timeout * promotion is controlled separately by `promoteOnTimeout`. */ enableRunInBackground?: Volatile; /** Keep a tool call running as a background job when foreground wait times out. */ promoteOnTimeout?: Volatile; /** How long a tool call waits in the foreground before promoting to a background job (ms). */ foregroundWaitMs?: Volatile; /** * Whether the local diagnostics ring also retains `debug` entries (HTTP * request lines, tool argument digests, cache hits). The ring itself is * in-process memory served only over the loopback remote face; nothing is * written to a file or sent anywhere at either setting. */ debug?: Volatile; } /** * Every field is `volatile`: the settings page edits the live entry, and the * loader commits volatile edits into the running fiber without remounting * (non-volatile edits would remount instead, and the settings write path * refuses them). The service re-reads the references per request and reacts * to `loader/volatile-update` for structural flips (transport, write tools). */ export declare const Config: Schema; provider: Schema; timeoutMs: Schema; maxInFlightRequests: Schema; maxSearchResults: Schema; maxNoteScanRecords: Schema; searchConcurrency: Schema; maxEvidenceChars: Schema; maxEvidencePassages: Schema; maxDetailChars: Schema; maxNoteBodyChars: Schema; maxNoteChars: Schema; maxNoteRecords: Schema; maxAnnotationRecords: Schema; maxAttachmentRecords: Schema; fulltextChunkWords: Schema; maxFulltextChars: Schema; retrieveAttachmentCap: Schema; graphConcurrency: Schema; maxResponseBytes: Schema; maxExportChars: Schema; maxExportRefs: Schema; maxBrowseResults: Schema; maxChangesResults: Schema; scopeListingTtlMs: Schema; defaultStyle: Schema; defaultLocale: Schema; writeEnabled: Schema; writePersistKey: Schema; writeNoteMaxChars: Schema; writeListMaxItems: Schema; writeAuthorizeDeadlineMs: Schema; webEnabled: Schema; enableRunInBackground: Schema; promoteOnTimeout: Schema; foregroundWaitMs: Schema; debug: Schema; }>>, Schemastery.ObjectT; provider: Schema; timeoutMs: Schema; maxInFlightRequests: Schema; maxSearchResults: Schema; maxNoteScanRecords: Schema; searchConcurrency: Schema; maxEvidenceChars: Schema; maxEvidencePassages: Schema; maxDetailChars: Schema; maxNoteBodyChars: Schema; maxNoteChars: Schema; maxNoteRecords: Schema; maxAnnotationRecords: Schema; maxAttachmentRecords: Schema; fulltextChunkWords: Schema; maxFulltextChars: Schema; retrieveAttachmentCap: Schema; graphConcurrency: Schema; maxResponseBytes: Schema; maxExportChars: Schema; maxExportRefs: Schema; maxBrowseResults: Schema; maxChangesResults: Schema; scopeListingTtlMs: Schema; defaultStyle: Schema; defaultLocale: Schema; writeEnabled: Schema; writePersistKey: Schema; writeNoteMaxChars: Schema; writeListMaxItems: Schema; writeAuthorizeDeadlineMs: Schema; webEnabled: Schema; enableRunInBackground: Schema; promoteOnTimeout: Schema; foregroundWaitMs: Schema; debug: Schema; }>>, "plain">; export interface ResolvedConfig { readonly baseUrl: string; readonly provider: string; readonly timeoutMs: number; readonly maxInFlightRequests: number; readonly maxSearchResults: number; readonly maxNoteScanRecords: number; readonly searchConcurrency: number; readonly maxEvidenceChars: number; readonly maxEvidencePassages: number; readonly maxDetailChars: number; readonly maxNoteBodyChars: number; readonly maxNoteChars: number; readonly maxNoteRecords: number; readonly maxAnnotationRecords: number; readonly maxAttachmentRecords: number; readonly fulltextChunkWords: number; readonly maxFulltextChars: number; readonly retrieveAttachmentCap: number; readonly graphConcurrency: number; readonly maxResponseBytes: number; readonly maxExportChars: number; readonly maxExportRefs: number; readonly maxBrowseResults: number; readonly maxChangesResults: number; readonly scopeListingTtlMs: number; readonly defaultStyle: string; readonly defaultLocale: string; readonly writeEnabled: boolean; readonly writePersistKey: boolean; readonly writeNoteMaxChars: number; readonly writeListMaxItems: number; readonly writeAuthorizeDeadlineMs: number; readonly webEnabled: boolean; readonly enableRunInBackground: boolean; readonly promoteOnTimeout: boolean; readonly foregroundWaitMs: number; readonly debug: boolean; } /** * Hostnames that are loopback by definition. `localhost` is pinned to the * IPv4 literal before any request leaves the plugin; the set is the single * spelling authority for validation and for the shell-write detector's * host anchors, so the two can never drift. */ export declare const LOOPBACK_HOSTNAMES: ReadonlySet; /** Plain options as humans write them: every `Config` reference unwrapped. */ export type Options = { [K in keyof Config]?: NonNullable extends Volatile ? T : never; }; /** * Normalize an entry for the service's live read. Schema-complete input is * kept as-is (Loader hands stable volatile references; live commits write * those same refs). Partial `Options` cannot observe volatile commits, so the * resolved snapshot is stored instead of re-applying Schemastery per request. * @param config - the constructor's entry, already accepted by {@link resolveConfig}. * @returns the entry the live getter reads. */ export declare function toLiveEntry(config: Config | Options): Config | Options; /** * Live read of a schema-complete entry (the Loader/fiber contract: every * field is present as a stable volatile reference or a plain value that * already passed {@link resolveConfig}). Unwrap and constraint checks only: * Schemastery is not re-applied on this path. * @throws {Error} on loopback/URL/limit violations, or when a field is missing. */ export declare function readResolvedConfig(entry: Config | Options): ResolvedConfig; /** * Validate a raw config and fill schema defaults. * * The single schema+constraint authority: runs at load (a violating entry * fails loud) and as the `internal/config` veto (a violating settings commit * is refused before it lands). The service's per-request live read goes * through {@link readResolvedConfig} on an entry that already passed this * function (or arrived Loader schema-complete), so it never observes a value * this function would reject. * @throws {Error} on loopback/URL/limit violations; misconfiguration fails the plugin load. */ export declare function resolveConfig(config: Config | Options): ResolvedConfig; //# sourceMappingURL=config.d.ts.map