@duckedup/nidus 0.89.0 → 0.91.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -455,13 +455,23 @@ var NidusClient = class {
455
455
  /**
456
456
  * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by
457
457
  * document frequency (commonest first), which is the opposite of how a prefix clause
458
- * ranks documents. Completions are stems: the prefix is folded, not stemmed.
458
+ * ranks documents. Completions are real spellings: the prefix is folded, not stemmed.
459
+ *
460
+ * The `df` counts only documents passing `filter` and carrying every word already typed
461
+ * before the final token, so a permission-scoped dropdown is expressible and "quick br"
462
+ * completes against the documents that also say "quick".
459
463
  */
460
464
  suggest(opts) {
461
465
  return this.request(
462
466
  "POST",
463
- `/collections/${enc(opts.collection)}/suggest`,
464
- prune({ field: opts.field, prefix: opts.prefix, limit: opts.limit })
467
+ "/suggest",
468
+ prune({
469
+ scope: opts.scope ?? [],
470
+ field: opts.field,
471
+ prefix: opts.prefix,
472
+ limit: opts.limit,
473
+ filter: opts.filter ?? []
474
+ })
465
475
  );
466
476
  }
467
477
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/annotations.ts","../src/errors.ts","../src/values.ts","../src/client.ts","../src/filter.ts"],"sourcesContent":["//! `@duckedup/nidus` — the JavaScript/TypeScript client for nidus.\n//\n// A zero-dependency, cross-runtime remote client over the `nidus serve` HTTP API.\n// Point a {@link NidusClient} at a local or remote server, then upsert and search.\n\nexport { NidusClient } from \"./client.js\";\nexport type { FetchLike, NidusClientOptions } from \"./client.js\";\nexport { NidusError } from \"./errors.js\";\nexport { f } from \"./filter.js\";\nexport { decodeAttrs, decodeValue, encodeAttrs, encodeValue, v } from \"./values.js\";\nexport type {\n AggregateOptions,\n Aggregation,\n AnnInfo,\n AnnotationOptions,\n Annotations,\n AttrInput,\n ClauseScore,\n Expansion,\n ClusterStatus,\n Decay,\n DecodedRecord,\n DecodedValue,\n Expand,\n Filter,\n FilterIndexField,\n Footprint,\n Fragment,\n FtsCombine,\n FtsField,\n Highlight,\n HighlightOptions,\n Hit,\n HybridQuerySpelling,\n HybridSearchBase,\n HybridSearchOptions,\n LegScore,\n LimitPer,\n ListOptions,\n NidusRecord,\n OrderBy,\n PlanCandidates,\n PlanNarrowing,\n PlanTimings,\n Predicate,\n ProjectionOptions,\n QueryPath,\n QueryPlan,\n RankBy,\n RankingOptions,\n Readiness,\n RecallOptions,\n RecordInput,\n RememberOptions,\n RememberResult,\n RerankOptions,\n Rollup,\n SearchOptions,\n SimilarSearchOptions,\n Stats,\n StoreVersions,\n Suggestion,\n Suggestions,\n SuggestOptions,\n TextClause,\n TextQuerySpelling,\n TextSearchBase,\n TextSearchOptions,\n Value,\n} from \"./types.js\";\n","//! Decoding a hit's optional annotations — the opt-in \"why did this match\".\n//\n// One rule here is JS's alone. The server reports a highlight span as a **UTF-8 byte**\n// range into the fragment text, but a JS string is indexed in UTF-16 code units, so\n// `text.slice(...span)` on a raw span is wrong for any non-ASCII excerpt. Converted here,\n// once, so a caller's obvious slice is the right one.\n\nimport type { Annotations, Fragment, Highlight } from \"./types.js\";\n\n/** A fragment as it arrives: `spans` are UTF-8 byte offsets into `text`. */\ninterface WireFragment {\n text: string;\n spans: [number, number][];\n}\n\ninterface WireHighlight {\n field: string;\n fragments: WireFragment[];\n}\n\n/** A hit's annotations as they arrive, before the span offsets are converted. */\nexport interface WireAnnotations {\n vector?: { rank: number; score: number };\n text?: { rank: number; score: number };\n clauses?: {\n field: string;\n score: number;\n expansion?: { matched: number; scored: number };\n }[];\n highlights?: WireHighlight[];\n}\n\n/**\n * Decode a hit's annotations, converting every highlight span to JS string indices. The\n * parts the server omitted stay omitted rather than becoming empty arrays.\n */\nexport function decodeAnnotations(a: WireAnnotations): Annotations {\n const out: Annotations = {};\n if (a.vector) out.vector = a.vector;\n if (a.text) out.text = a.text;\n if (a.clauses) out.clauses = a.clauses;\n if (a.highlights) out.highlights = a.highlights.map(decodeHighlight);\n return out;\n}\n\nfunction decodeHighlight(h: WireHighlight): Highlight {\n return { field: h.field, fragments: h.fragments.map(decodeFragment) };\n}\n\nfunction decodeFragment(fr: WireFragment): Fragment {\n return { text: fr.text, spans: toStringIndices(fr.text, fr.spans) };\n}\n\n/**\n * Convert UTF-8 byte ranges into `text` to JS string indices (UTF-16 code units), so\n * `text.slice(...span)` yields the matched term. An all-ASCII excerpt needs no conversion\n * and is the common case, so it is detected before any table is built.\n */\nexport function toStringIndices(\n text: string,\n spans: [number, number][],\n): [number, number][] {\n if (spans.length === 0 || isAscii(text)) return spans;\n const index = byteToUnit(text);\n const at = (b: number): number =>\n index[Math.min(Math.max(b, 0), index.length - 1)]!;\n return spans.map(([start, end]): [number, number] => [at(start), at(end)]);\n}\n\n/** One entry per byte of `text` (plus its end), holding that byte's UTF-16 index. */\nfunction byteToUnit(text: string): number[] {\n const index: number[] = [];\n let unit = 0;\n // A byte *inside* a codepoint maps to that codepoint's start. Spans land on token\n // boundaries, so this only keeps a malformed offset from landing mid-surrogate.\n for (const ch of text) {\n for (let n = utf8Len(ch.codePointAt(0)!); n > 0; n--) index.push(unit);\n unit += ch.length;\n }\n index.push(unit);\n return index;\n}\n\nfunction utf8Len(codePoint: number): number {\n if (codePoint < 0x80) return 1;\n if (codePoint < 0x800) return 2;\n return codePoint < 0x10000 ? 3 : 4;\n}\n\n/** True when every code unit is ASCII, i.e. byte offsets already *are* string indices. */\nfunction isAscii(text: string): boolean {\n for (let i = 0; i < text.length; i++) {\n if (text.charCodeAt(i) > 0x7f) return false;\n }\n return true;\n}\n","//! Error type carrying the HTTP status the server reported.\n//\n// The server replies to a failed request with `{ \"error\": <message> }` and a\n// meaningful status (`src/server/mod.rs#classify`): 400 dimension mismatch,\n// 403 read-only store, 409 writer-lock conflict, 507 capacity/OOM, 500 otherwise.\n// Callers branch on `.status` to tell a client fault from a server fault.\n\n/** An error returned by a `nidus` server, or a transport failure reaching it. */\nexport class NidusError extends Error {\n /** The HTTP status code, or `0` for a transport/timeout failure (no response). */\n readonly status: number;\n\n constructor(message: string, status: number) {\n super(message);\n this.name = \"NidusError\";\n this.status = status;\n }\n\n /** A malformed request the server rejected (HTTP 400). */\n get isBadRequest(): boolean {\n return this.status === 400;\n }\n /** The store is read-only (HTTP 403). */\n get isReadOnly(): boolean {\n return this.status === 403;\n }\n /** The writer lock is held by another process (HTTP 409). */\n get isLocked(): boolean {\n return this.status === 409;\n }\n /** Out of capacity: `max_vector_bytes` exceeded or OOM (HTTP 507). */\n get isOutOfCapacity(): boolean {\n return this.status === 507;\n }\n}\n","//! Ergonomic constructors and decoders for the externally-tagged `Value` wire type.\n//\n// Callers should never hand-write `{ Str: \"x\" }`. Use `v.str(\"x\")`, `v.int(5)`,\n// etc., or just pass plain JS values into `attrs` — `encodeValue` normalizes them.\n//\n// One rule is JS's alone. The store's `Int` and `Float` are separate types compared\n// same-type only, but JS has one `number` and `1.0 === 1`, so `Number.isInteger` has to\n// decide. A whole-numbered measurement therefore lands as an `Int` in whichever records\n// it came out round, and a `Float` range filter then skips exactly those: write such a\n// field with `v.float`. Go and Python have the types JS lacks and decide from them.\n\nimport type { AttrInput, DecodedValue, Value } from \"./types.js\";\n\n/** Every tag this SDK version knows, in the order `decodeValue` tries them. */\nconst TAGS = [\"Str\", \"Int\", \"Bool\", \"List\", \"Float\", \"DateTime\"] as const;\n\n/**\n * Value constructors mirroring the `Value` variants. `v.int` requires a safe\n * integer and `v.float` a finite number — `NaN`/`Infinity` have no JSON spelling,\n * and `JSON.stringify` would quietly write `null`.\n */\nexport const v = {\n str: (s: string): Value => ({ Str: s }),\n int: (n: number): Value => {\n if (!Number.isInteger(n)) {\n throw new TypeError(`v.int expects an integer, got ${n}`);\n }\n return { Int: n };\n },\n float: (n: number): Value => {\n if (typeof n !== \"number\" || !Number.isFinite(n)) {\n throw new TypeError(`v.float expects a finite number, got ${n}`);\n }\n return { Float: n };\n },\n bool: (b: boolean): Value => ({ Bool: b }),\n list: (items: string[]): Value => ({ List: items }),\n /**\n * A UTC instant, from a `Date` or a raw epoch-millisecond count. Milliseconds is\n * the wire type, so there is no sub-millisecond precision and no timezone.\n */\n datetime: (when: Date | number): Value => {\n const ms = when instanceof Date ? when.getTime() : when;\n if (!Number.isSafeInteger(ms)) {\n throw new TypeError(\n `v.datetime expects a valid Date or epoch ms, got ${when}`,\n );\n }\n return { DateTime: ms };\n },\n /** The explicit `Null` value — set-but-empty, distinct from an absent key. */\n nil: (): Value => \"Null\",\n} as const;\n\n/** True if `x` is already a wire-tagged {@link Value}. */\nfunction isValue(x: unknown): x is Value {\n if (x === \"Null\") return true;\n if (typeof x !== \"object\" || x === null) return false;\n return TAGS.some((tag) => tag in x);\n}\n\n/**\n * Normalize a caller-supplied {@link AttrInput} into the wire {@link Value} shape.\n * Plain scalars map by type; an already-tagged `Value` passes through unchanged.\n * Throws on a non-finite number, an invalid `Date`, or a non-string list element.\n */\nexport function encodeValue(input: AttrInput): Value {\n if (isValue(input)) return input;\n if (input === null) return \"Null\";\n switch (typeof input) {\n case \"string\":\n return { Str: input };\n case \"boolean\":\n return { Bool: input };\n case \"number\":\n return Number.isInteger(input) ? v.int(input) : v.float(input);\n case \"object\":\n // Date before the array check: both are objects, only one is a list.\n if (input instanceof Date) return v.datetime(input);\n if (Array.isArray(input)) {\n if (!input.every((e) => typeof e === \"string\")) {\n throw new TypeError(\"a List attribute must contain only strings\");\n }\n return { List: input };\n }\n // falls through\n default:\n throw new TypeError(`cannot encode attribute value: ${String(input)}`);\n }\n}\n\n/** Normalize a whole `attrs` map of {@link AttrInput} into wire {@link Value}s. */\nexport function encodeAttrs(\n attrs: Record<string, AttrInput>,\n): Record<string, Value> {\n const out: Record<string, Value> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = encodeValue(val);\n }\n return out;\n}\n\n/** Decode a wire {@link Value} back to a plain JS value. */\nexport function decodeValue(value: Value): DecodedValue {\n if (value === \"Null\") return null;\n if (\"Str\" in value) return value.Str;\n if (\"Int\" in value) return value.Int;\n if (\"Bool\" in value) return value.Bool;\n if (\"List\" in value) return value.List;\n if (\"Float\" in value) return value.Float;\n // A Date, not the raw number: a number would demote every instant to an Int\n // when a decoded attrs map is written back.\n if (\"DateTime\" in value) return new Date(value.DateTime);\n // Unknown tag (forward-compat): hand it back untouched.\n return value as unknown as DecodedValue;\n}\n\n/** Decode a whole wire `attrs` map back to plain JS values. */\nexport function decodeAttrs(\n attrs: Record<string, Value>,\n): Record<string, DecodedValue> {\n const out: Record<string, DecodedValue> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = decodeValue(val);\n }\n return out;\n}\n","//! `NidusClient` — a remote client over the `nidus serve` HTTP API.\n//\n// One method per endpoint (`src/server/mod.rs`). \"Local vs remote\" is just the\n// base URL: point at a local `nidus serve` or any reachable host. Built on the\n// platform-global `fetch`, so it runs unchanged on Node 18+, Deno, Bun, Cloudflare\n// Workers, and browsers — with no runtime dependencies.\n\nimport { decodeAnnotations, type WireAnnotations } from \"./annotations.js\";\nimport { NidusError } from \"./errors.js\";\nimport type {\n AggregateOptions,\n Aggregation,\n BatchSearchOptions,\n ClusterStatus,\n DecodedRecord,\n Expand,\n Filter,\n FilterIndexField,\n FtsField,\n HighlightOptions,\n Hit,\n HybridSearchOptions,\n ListOptions,\n NidusRecord,\n PlanCandidates,\n PlanNarrowing,\n PlanTimings,\n QueryPlan,\n RankBy,\n Readiness,\n RecallOptions,\n RecordInput,\n RememberOptions,\n RememberResult,\n RerankOptions,\n Rollup,\n SearchOptions,\n SimilarSearchOptions,\n Stats,\n StoreVersions,\n Suggestions,\n SuggestOptions,\n TextSearchOptions,\n Value,\n} from \"./types.js\";\nimport { decodeAttrs, decodeValue, encodeAttrs } from \"./values.js\";\n\n/** Minimal `fetch` signature the client needs — satisfied by the platform global. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Construction options for {@link NidusClient}. */\nexport interface NidusClientOptions {\n /** Base URL of the server, e.g. `http://127.0.0.1:7700`. Trailing slash optional. */\n baseUrl: string;\n /** Bearer token, when the server was started with `--token`. */\n token?: string;\n /** Override the `fetch` implementation (defaults to `globalThis.fetch`). */\n fetch?: FetchLike;\n /** Per-request timeout in milliseconds. Omit (or `0`) to disable. */\n timeoutMs?: number;\n /** Extra headers sent on every request. */\n headers?: Record<string, string>;\n}\n\nexport class NidusClient {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly doFetch: FetchLike;\n private readonly timeoutMs: number;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: NidusClientOptions) {\n if (!options.baseUrl) {\n throw new TypeError(\"NidusClient requires a baseUrl\");\n }\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.token = options.token;\n this.timeoutMs = options.timeoutMs ?? 0;\n this.extraHeaders = options.headers ?? {};\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\n \"no fetch available; pass options.fetch (Node < 18, or a custom runtime)\",\n );\n }\n // Bind so a passed `globalThis.fetch` keeps its `this`.\n this.doFetch = f === globalThis.fetch ? f.bind(globalThis) : f;\n }\n\n // ── Admin / introspection ─────────────────────────────────────────────────\n\n /** Liveness check. Returns `true` when the server answers `/health`. */\n async health(): Promise<boolean> {\n try {\n const res = await this.raw(\"GET\", \"/health\");\n return res.ok;\n } catch {\n return false;\n }\n }\n\n /** Store-wide introspection: dimension, distance, ANN config, collections, footprint. */\n stats(): Promise<Stats> {\n return this.request<Stats>(\"GET\", \"/stats\");\n }\n\n /**\n * Readiness: whether this instance can serve. A `503` is the negative answer, not an\n * error, so a poll loop branches on `ready` instead of catching. Other failures throw.\n */\n async ready(): Promise<Readiness> {\n const res = await this.raw(\"GET\", \"/ready\");\n const text = await res.text();\n if (res.status === 503) return { ready: false, reason: extractError(text, 503) };\n if (!res.ok) throw new NidusError(extractError(text, res.status), res.status);\n return JSON.parse(text) as Readiness;\n }\n\n /** Cluster role, writer-handle state, fencing token, commit counter, staleness. */\n cluster(): Promise<ClusterStatus> {\n return this.request<ClusterStatus>(\"GET\", \"/cluster\");\n }\n\n /** The readable commit points and this instance's pin, if any. */\n versions(): Promise<StoreVersions> {\n return this.request<StoreVersions>(\"GET\", \"/versions\");\n }\n\n /** List every collection name. */\n collections(): Promise<string[]> {\n return this.request<string[]>(\"GET\", \"/collections\");\n }\n\n /** Create a collection. Idempotent on the server side. */\n async createCollection(name: string): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}`, {});\n }\n\n /** Drop a collection and all its records. */\n async dropCollection(name: string): Promise<void> {\n await this.request(\"DELETE\", `/collections/${enc(name)}`);\n }\n\n /** Every alias and the concrete collection it resolves to. */\n aliases(): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\"GET\", \"/aliases\");\n }\n\n /** Create or repoint an alias. The target must already exist; aliases never chain. */\n async setAlias(name: string, target: string): Promise<void> {\n await this.request(\"PUT\", `/aliases/${enc(name)}`, { target });\n }\n\n /** Remove an alias. Deletes no records. */\n async dropAlias(name: string): Promise<void> {\n await this.request(\"DELETE\", `/aliases/${enc(name)}`);\n }\n\n /** Read a collection's free-form string metadata. */\n getMeta(name: string): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\n \"GET\",\n `/collections/${enc(name)}/meta`,\n );\n }\n\n /** Replace a collection's free-form string metadata. */\n async setMeta(name: string, meta: Record<string, string>): Promise<void> {\n await this.request(\"PUT\", `/collections/${enc(name)}/meta`, meta);\n }\n\n // ── Data ──────────────────────────────────────────────────────────────────\n\n /**\n * Insert or replace records (idempotent on `id` within the collection).\n * `attrs` accept plain JS values or `v.*` helpers; they are normalized for you.\n * Returns the number of records upserted.\n */\n async upsert(name: string, records: RecordInput[]): Promise<number> {\n const wire: NidusRecord[] = records.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: encodeAttrs(r.attrs),\n }));\n const res = await this.request<{ upserted: number }>(\n \"POST\",\n `/collections/${enc(name)}/upsert`,\n { records: wire },\n );\n return res.upserted;\n }\n\n /** Delete records by id. Returns the number deleted. */\n async delete(name: string, opts: { ids: string[] }): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { ids: opts.ids },\n );\n return res.deleted;\n }\n\n /** Delete every record matching `filter`. Returns the number deleted. */\n async deleteWhere(name: string, filter: Filter): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { filter },\n );\n return res.deleted;\n }\n\n /** Fetch every record in a collection (attrs decoded to plain JS values). */\n async records(name: string): Promise<DecodedRecord[]> {\n const recs = await this.request<NidusRecord[]>(\n \"GET\",\n `/collections/${enc(name)}/records`,\n );\n return recs.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: decodeAttrs(r.attrs),\n }));\n }\n\n /**\n * Declare the full-text-indexed attribute fields for a collection. A bare string\n * takes the server's BM25/analyzer defaults; an {@link FtsField} object tunes `k1`,\n * `b`, and the analyzer for that field alone.\n */\n async setFtsSchema(\n name: string,\n fields: (string | FtsField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/fts-schema`, {\n fields: fields.map(encodeFtsField),\n });\n }\n\n /**\n * Declare which attribute fields are indexed for the text predicates (`Fuzzy`,\n * `ContainsAllTokens`, `ContainsAnyToken`, `ContainsTokenSequence`, `Regex`). Fields\n * already written are indexed as part of applying the declaration.\n *\n * This changes how fast those predicates run, never what they return: the index\n * proposes candidate documents and the predicate itself still decides. The cost is\n * paid at write time and in memory. Pass an empty array to drop the declaration.\n */\n async setFilterIndex(\n name: string,\n fields: (string | FilterIndexField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/filter-index`, {\n fields: fields.map(encodeFilterIndexField),\n });\n }\n\n // ── Search ──────────────────────────────────────────────────────────────\n\n /** Vector (cosine) nearest-neighbour search. Empty `scope` searches all collections. */\n search(opts: SearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.search}, but also reports the scan strategy the server took. */\n searchWithPlan(\n opts: SearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Records most like an existing one. The source record itself is never returned. */\n searchSimilar(opts: SimilarSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /** Like {@link NidusClient.searchSimilar}, but also reports the scan strategy taken. */\n searchSimilarWithPlan(\n opts: SimilarSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /**\n * BM25 full-text search over one indexed field, or over a `clauses` list folded by\n * `combine` (`\"Sum\"` unless said otherwise). Naming the fields both ways is a `400`.\n */\n textSearch(opts: TextSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/text-search\", {\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, query: opts.query, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /**\n * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by\n * document frequency (commonest first), which is the opposite of how a prefix clause\n * ranks documents. Completions are stems: the prefix is folded, not stemmed.\n */\n suggest(opts: SuggestOptions): Promise<Suggestions> {\n return this.request<Suggestions>(\n \"POST\",\n `/collections/${enc(opts.collection)}/suggest`,\n prune({ field: opts.field, prefix: opts.prefix, limit: opts.limit }),\n );\n }\n\n /**\n * Hybrid search: fuse a vector query and a BM25 text query via RRF. The text leg takes\n * the same single-field / `clauses` choice as {@link NidusClient.textSearch}.\n */\n hybridSearch(opts: HybridSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.hybridSearch}, but also reports the scan strategy taken. */\n hybridSearchWithPlan(\n opts: HybridSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Metadata-only listing (no vector), paginated by `offset`/`limit`. */\n list(opts: ListOptions = {}): Promise<Hit[]> {\n return this.searchRequest(\"/list\", {\n scope: opts.scope ?? [],\n offset: opts.offset,\n limit: opts.limit,\n filter: opts.filter ?? [],\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n order_by: opts.orderBy,\n });\n }\n\n /**\n * Count the records matching a filter and sum the named attributes. Answered from the\n * in-RAM index alone — no record is built and no vector is read.\n */\n async aggregate(opts: AggregateOptions = {}): Promise<Aggregation> {\n const res = await this.request<RawAggregation>(\n \"POST\",\n \"/aggregate\",\n prune({\n scope: opts.scope ?? [],\n filter: opts.filter ?? [],\n sum: opts.sum ?? [],\n group_by: opts.groupBy,\n }),\n );\n // Every sum is an `Int` or a `Float`, both of which decode to a JS number.\n return {\n count: res.count,\n sums: decodeAttrs(res.sums) as Record<string, number>,\n // Kept absent, not `undefined`, so an ungrouped answer is the shape it always was.\n ...(res.groups\n ? {\n groups: res.groups.map((g) => ({\n value: g.value === null ? null : decodeValue(g.value),\n count: g.count,\n sums: decodeAttrs(g.sums) as Record<string, number>,\n })),\n }\n : {}),\n ...(res.groups_truncated ? { groupsTruncated: true } : {}),\n };\n }\n\n /**\n * Answer several vector queries in one round-trip (16 max). Returns one ranking per\n * query in request order, or — with `opts.fuse` — a single array holding the one fused\n * ranking, so the return shape is uniform either way.\n *\n * The server validates the whole batch before running any leg, so a malformed query\n * fails the call rather than returning a partial answer that cannot be told apart.\n */\n async batchSearch(opts: BatchSearchOptions): Promise<Hit[][]> {\n const body = prune({\n queries: opts.queries.map((q) => ({\n query: q.query,\n scope: q.scope ?? [],\n top_k: q.topK,\n offset: q.offset,\n min_score: q.minScore,\n filter: q.filter ?? [],\n exact: q.exact,\n include_attributes: q.includeAttributes,\n exclude_attributes: q.excludeAttributes,\n rank_by: encodeRankBy(q.rankBy),\n limit_per: q.limitPer,\n diversity: q.diversity,\n expand: encodeExpand(q.expand),\n })),\n fuse: opts.fuse\n ? prune({\n rrf_k: opts.fuse.rrfK,\n weights: opts.fuse.weights,\n top_k: opts.fuse.topK,\n })\n : undefined,\n });\n const res = await this.request<RawBatchSearch>(\n \"POST\",\n \"/search/batch\",\n body,\n );\n return (res.fused ? [res.fused] : (res.results ?? [])).map((hits) =>\n hits.map((h) => this.decodeHit(h)),\n );\n }\n\n // ── Memory (text-native) ──────────────────────────────────────────────────\n //\n // Available only when `nidus serve` was started with an embedder\n // (`--embed-provider …`); otherwise these answer `400`. The server embeds the\n // text/query — the client only sends strings.\n\n /**\n * Embed `text` and upsert it under `id` in `collection` (idempotent on `id`).\n * With `opts.mode === \"summarize\"` the server summarizes first, embeds the\n * summary, and stamps a `nidus.summary` attr (requires the server to have a\n * summarizer). The raw text is always stored under `nidus.text`. `opts.attrs` accept plain JS values or `v.*`\n * helpers; they are normalized for you.\n *\n * Read `id` off the result rather than assuming the one you passed:\n * `opts.dedupeThreshold` can redirect the write onto a near-duplicate.\n */\n async remember(\n collection: string,\n id: string,\n text: string,\n opts: RememberOptions = {},\n ): Promise<RememberResult> {\n const res = await this.request<Partial<RememberResult> | undefined>(\n \"POST\",\n `/collections/${enc(collection)}/remember`,\n prune({\n id,\n text,\n mode: opts.mode,\n attrs: opts.attrs ? encodeAttrs(opts.attrs) : undefined,\n ttl_seconds: opts.ttlSeconds,\n dedupe_threshold: opts.dedupeThreshold,\n }),\n );\n // A server predating the echoed fields answers `{ok, upserted}`; falling back to the\n // requested id keeps that case honest instead of reporting `undefined` as the target.\n return {\n id: res?.id ?? id,\n upserted: res?.upserted ?? 0,\n deduped: res?.deduped ?? false,\n };\n }\n\n /**\n * Embed `query` and vector-search `collection`, best-first (attrs decoded to\n * plain JS values). Refused with a cross-model guard if the collection was\n * written with a different embedder than the server's.\n */\n recall(\n collection: string,\n query: string,\n opts: RecallOptions = {},\n ): Promise<Hit[]> {\n return this.searchRequest(`/collections/${enc(collection)}/recall`, {\n query,\n top_k: opts.topK,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n diversity: opts.diversity,\n rollup: encodeRollup(opts.rollup),\n rerank: encodeRerank(opts.rerank),\n reinforce: opts.reinforce,\n extend_ttl_seconds: opts.extendTtlSeconds,\n rank_by: encodeRankBy(opts.rankBy),\n });\n }\n\n // ── Maintenance ───────────────────────────────────────────────────────────\n\n /** Force a durability flush. */\n async flush(): Promise<void> {\n await this.request(\"POST\", \"/flush\", {});\n }\n\n /** Compact the store (reclaim space from deleted/overwritten rows). */\n async compact(): Promise<void> {\n await this.request(\"POST\", \"/compact\", {});\n }\n\n /** Adopt a writer's newer committed state. Returns whether anything was adopted. */\n async refresh(): Promise<boolean> {\n const res = await this.request<{ adopted: boolean }>(\"POST\", \"/refresh\", {});\n return res.adopted;\n }\n\n // ── Internals ─────────────────────────────────────────────────────────────\n\n /** Run a search-family request and decode the resulting hits' attrs. */\n private async searchRequest(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Hit[]> {\n const hits = await this.request<RawHit[]>(\"POST\", path, prune(body));\n return hits.map((h) => this.decodeHit(h));\n }\n\n /** Like {@link NidusClient.searchRequest}, asking for `plan: true` and decoding it too. */\n private async searchRequestWithPlan(\n path: string,\n body: Record<string, unknown>,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n const res = await this.request<{ hits: RawHit[]; plan: RawQueryPlan }>(\n \"POST\",\n path,\n prune({ ...body, plan: true }),\n );\n return {\n hits: res.hits.map((h) => this.decodeHit(h)),\n plan: decodeQueryPlan(res.plan),\n };\n }\n\n /** One wire hit into a {@link Hit}. Shared so every search surface decodes identically. */\n private decodeHit(h: RawHit): Hit {\n return {\n collection: h.collection,\n id: h.id,\n score: h.score,\n attrs: decodeAttrs(h.attrs),\n // Kept absent, not `undefined`, so an unannotated hit is the shape it always was.\n ...(h.annotations\n ? { annotations: decodeAnnotations(h.annotations) }\n : {}),\n ...(h.context !== undefined ? { context: h.context } : {}),\n };\n }\n\n /** Issue a request and parse a JSON body, mapping a non-2xx to {@link NidusError}. */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const res = await this.raw(method, path, body);\n const text = await res.text();\n if (!res.ok) {\n throw new NidusError(extractError(text, res.status), res.status);\n }\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** The bare transport: headers, auth, timeout, and transport-error mapping. */\n private async raw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const headers: Record<string, string> = { ...this.extraHeaders };\n if (this.token) headers.authorization = `Bearer ${this.token}`;\n let payload: string | undefined;\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n payload = JSON.stringify(body);\n }\n\n const controller = this.timeoutMs > 0 ? new AbortController() : undefined;\n const timer =\n controller && this.timeoutMs > 0\n ? setTimeout(() => controller.abort(), this.timeoutMs)\n : undefined;\n try {\n return await this.doFetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: payload,\n signal: controller?.signal,\n });\n } catch (err) {\n const reason =\n (controller?.signal.aborted ?? false)\n ? `request to ${path} timed out after ${this.timeoutMs}ms`\n : `request to ${path} failed: ${(err as Error).message}`;\n throw new NidusError(reason, 0);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\n/** A hit as it arrives on the wire, before attrs are decoded. */\ninterface RawHit {\n collection: string;\n id: string;\n score: number;\n attrs: Record<string, Value>;\n annotations?: WireAnnotations;\n context?: string;\n}\n\n/** A `QueryPlan` as it arrives on the wire (snake_case), before camelCasing. */\ninterface RawQueryPlan {\n path: string;\n rows_scanned?: number;\n candidates?: {\n surfaced: number;\n survived: number;\n dropped_out_of_scope: number;\n dropped_stale: number;\n dropped_filtered: number;\n dropped_min_score: number;\n };\n narrowing: { state: PlanNarrowing[\"state\"]; candidates?: number };\n timings: {\n narrow_us?: number;\n gather_us?: number;\n walk_us?: number;\n resolve_us?: number;\n first_pass_us?: number;\n rescore_us?: number;\n score_us?: number;\n total_us: number;\n };\n}\n\n/** Wire `QueryPlan` into its camelCase {@link QueryPlan} shape. */\nfunction decodeQueryPlan(p: RawQueryPlan): QueryPlan {\n const candidates: PlanCandidates | undefined = p.candidates\n ? {\n surfaced: p.candidates.surfaced,\n survived: p.candidates.survived,\n droppedOutOfScope: p.candidates.dropped_out_of_scope,\n droppedStale: p.candidates.dropped_stale,\n droppedFiltered: p.candidates.dropped_filtered,\n droppedMinScore: p.candidates.dropped_min_score,\n }\n : undefined;\n const t = p.timings;\n const timings: PlanTimings = {\n ...(t.narrow_us !== undefined ? { narrowUs: t.narrow_us } : {}),\n ...(t.gather_us !== undefined ? { gatherUs: t.gather_us } : {}),\n ...(t.walk_us !== undefined ? { walkUs: t.walk_us } : {}),\n ...(t.resolve_us !== undefined ? { resolveUs: t.resolve_us } : {}),\n ...(t.first_pass_us !== undefined ? { firstPassUs: t.first_pass_us } : {}),\n ...(t.rescore_us !== undefined ? { rescoreUs: t.rescore_us } : {}),\n ...(t.score_us !== undefined ? { scoreUs: t.score_us } : {}),\n totalUs: t.total_us,\n };\n return {\n path: p.path,\n ...(p.rows_scanned !== undefined ? { rowsScanned: p.rows_scanned } : {}),\n ...(candidates ? { candidates } : {}),\n narrowing: {\n state: p.narrowing.state,\n ...(p.narrowing.candidates !== undefined\n ? { candidates: p.narrowing.candidates }\n : {}),\n },\n timings,\n };\n}\n\n/** An `/aggregate` response, whose sums arrive as tagged {@link Value}s. */\ninterface RawAggregation {\n count: number;\n sums: Record<string, Value>;\n groups?: {\n value: Value | null;\n count: number;\n sums: Record<string, Value>;\n }[];\n groups_truncated?: boolean;\n}\n\n/** A `/search/batch` response: exactly one of the two fields is present. */\ninterface RawBatchSearch {\n results?: RawHit[][];\n fused?: RawHit[];\n}\n\n/** Encode `rankBy` to its externally-tagged wire form, dropping the knobs left unset. */\n/** camelCase → the wire's snake_case, omitting the object entirely when unset. */\nfunction encodeExpand(e: Expand | undefined): unknown {\n if (!e) return undefined;\n return prune({\n radius: e.radius,\n parent_field: e.parentField,\n index_field: e.indexField,\n text_field: e.textField,\n });\n}\n\nfunction encodeRollup(r: Rollup | undefined): unknown {\n if (!r) return undefined;\n return prune({ per_parent: r.perParent, neighbours: r.neighbours });\n}\n\nfunction encodeRankBy(rank: RankBy | undefined): unknown {\n if (!rank) return undefined;\n const d = rank.decay;\n return {\n Decay: prune({\n field: d.field,\n origin: d.origin instanceof Date ? d.origin.getTime() : d.origin,\n scale: d.scale,\n decay: d.decay,\n lambda: d.lambda,\n missing: d.missing,\n count_field: d.countField,\n count_scale: d.countScale,\n count_lambda: d.countLambda,\n }),\n };\n}\n\n/** Encode `highlight`: `true` is the empty object the server reads as \"all defaults\". */\nfunction encodeHighlight(h: boolean | HighlightOptions | undefined): unknown {\n if (h === undefined || h === false) return undefined;\n if (h === true) return {};\n return prune({\n max_fragments: h.maxFragments,\n fragment_chars: h.fragmentChars,\n });\n}\n\n/** Encode `rerank`. Undefined sub-fields drop out at `JSON.stringify`, not here. */\nfunction encodeRerank(r: RerankOptions | undefined): unknown {\n if (r === undefined) return undefined;\n return { query: r.query, overscan: r.overscan, text_attr: r.textAttr };\n}\n\n/** Path-segment encode a collection name (allows slashes/spaces in names). */\nfunction enc(name: string): string {\n return encodeURIComponent(name);\n}\n\n/**\n * Encode one `setFtsSchema` field. A string passes through as the server's bare-name\n * form; an object becomes the snake_case body, pruned so an unset knob keeps the\n * server's default rather than being sent as `undefined`.\n */\nfunction encodeFtsField(f: string | FtsField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n k1: f.k1,\n b: f.b,\n language: f.language,\n ascii_folding: f.asciiFolding,\n max_token_len: f.maxTokenLen,\n });\n}\n\n/**\n * Encode one `setFilterIndex` field, on the same bare-name-or-object rule as\n * {@link encodeFtsField}. Pruning matters here: the server defaults both structures to\n * `true`, so sending an explicit `undefined` would be indistinguishable from `false`.\n */\nfunction encodeFilterIndexField(f: string | FilterIndexField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n tokens: f.tokens,\n trigrams: f.trigrams,\n });\n}\n\n/** Drop `undefined` fields so server `#[serde(default)]`s apply instead. */\nfunction prune(body: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(body)) {\n if (val !== undefined) out[k] = val;\n }\n return out;\n}\n\n/** Pull the `{ \"error\": … }` message out of a failed response, or fall back. */\nfunction extractError(text: string, status: number): string {\n try {\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed.error === \"string\") return parsed.error;\n } catch {\n // not JSON — fall through\n }\n return text || `HTTP ${status}`;\n}\n","//! Filter builder producing the bare predicate-array wire shape.\n//\n// A `Filter` is AND-combined predicates; on the wire it is a plain array. Each\n// predicate is a *positive assertion about a present attribute* — an absent key\n// matches nothing, including the negative predicates (`ne`/`notIn`) and ranges.\n// Comparisons are same-type only (Int↔Int numeric, Float↔Float by IEEE, Str↔Str\n// lexical, Bool↔Bool, DateTime↔DateTime as instants), so an operand's encoded type\n// has to match the attribute's: `ge(\"score\", v.float(2))`, not `ge(\"score\", 2)`.\n\nimport type { AttrInput, Filter, Predicate, Value } from \"./types.js\";\nimport { encodeValue } from \"./values.js\";\n\n/**\n * Predicate constructors. Each accepts a plain JS value (auto-normalized) or an\n * explicit `v.*` {@link Value}. Combine results into a {@link Filter} array, or\n * use {@link f.and} for readability.\n */\nexport const f = {\n /** `attrs[key] === value`. */\n eq: (key: string, value: AttrInput): Predicate => ({\n Eq: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is present and `!== value`. */\n ne: (key: string, value: AttrInput): Predicate => ({\n Ne: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `Str` matching the glob pattern (`*`, `?`, `[..]`). */\n glob: (key: string, pattern: string): Predicate => ({ Glob: [key, pattern] }),\n /**\n * {@link f.glob}, ignoring **ASCII** case on both sides — `\"Src/*\"` matches\n * `\"src/main.rs\"`. Non-ASCII is not folded (`É` does not match `é`).\n */\n iglob: (key: string, pattern: string): Predicate => ({\n IGlob: [key, pattern],\n }),\n /** `attrs[key]` equals one of `values`. */\n in: (key: string, values: AttrInput[]): Predicate => ({\n In: [key, values.map(encodeValue)],\n }),\n /** `attrs[key]` is present and equals none of `values`. */\n notIn: (key: string, values: AttrInput[]): Predicate => ({\n NotIn: [key, values.map(encodeValue)],\n }),\n /** `attrs[key] < value` (same-type, orderable). */\n lt: (key: string, value: AttrInput): Predicate => ({\n Lt: [key, encodeValue(value)],\n }),\n /** `attrs[key] <= value` (same-type, orderable). */\n le: (key: string, value: AttrInput): Predicate => ({\n Le: [key, encodeValue(value)],\n }),\n /** `attrs[key] > value` (same-type, orderable). */\n gt: (key: string, value: AttrInput): Predicate => ({\n Gt: [key, encodeValue(value)],\n }),\n /** `attrs[key] >= value` (same-type, orderable). */\n ge: (key: string, value: AttrInput): Predicate => ({\n Ge: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` containing `value` (whole-element, not substring). */\n contains: (key: string, value: AttrInput): Predicate => ({\n Contains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a present `List` not containing `value`. */\n notContains: (key: string, value: AttrInput): Predicate => ({\n NotContains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` sharing at least one element with `values`. */\n containsAny: (key: string, values: AttrInput[]): Predicate => ({\n ContainsAny: [key, values.map(encodeValue)],\n }),\n /** Every sub-predicate holds. `all()` is `true`. */\n all: (...preds: Predicate[]): Predicate => ({ All: preds }),\n /** At least one sub-predicate holds. `any()` is `false`. */\n any: (...preds: Predicate[]): Predicate => ({ Any: preds }),\n /**\n * The sub-predicate does not hold. Differs from {@link f.ne} on an absent key:\n * `not(eq(k, v))` matches a record with no `k`, `ne(k, v)` does not.\n */\n not: (pred: Predicate): Predicate => ({ Not: pred }),\n /**\n * `attrs[key]` is within `maxEdits` Levenshtein edits of `text`, ASCII-case-folded on\n * both sides; a `List` matches if any element does. The only three-element predicate.\n * A `maxEdits` above 8 is refused by the server, not clamped.\n */\n fuzzy: (key: string, text: string, maxEdits: number): Predicate => ({\n Fuzzy: [key, text, maxEdits],\n }),\n /**\n * Every token of `text` appears among `attrs[key]`'s tokens, in any order. Tokens are\n * ASCII-case-folded runs of alphanumerics; a `List` matches if any single element does.\n */\n containsAllTokens: (key: string, text: string): Predicate => ({\n ContainsAllTokens: [key, text],\n }),\n /** At least one token of `text` appears among `attrs[key]`'s tokens. Empty never matches. */\n containsAnyToken: (key: string, text: string): Predicate => ({\n ContainsAnyToken: [key, text],\n }),\n /** `text`'s tokens appear consecutively and in order — a phrase match. */\n containsTokenSequence: (key: string, text: string): Predicate => ({\n ContainsTokenSequence: [key, text],\n }),\n /**\n * `attrs[key]` matches the regular expression, **anchored at both ends** like\n * {@link f.glob} — `.*` opts back into a substring search, and `(?i)` into case folding.\n * The syntax is Rust's `regex`, not JS's: no backreferences and no lookaround.\n */\n regex: (key: string, pattern: string): Predicate => ({ Regex: [key, pattern] }),\n /** Collect predicates into a {@link Filter} (purely sugar — they already AND). */\n and: (...preds: Predicate[]): Filter => preds,\n} as const;\n\n// Aliases for the comparison operators, for callers who prefer them.\nexport type { Filter, Predicate, Value };\n"],"mappings":"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","names":["f"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/annotations.ts","../src/errors.ts","../src/values.ts","../src/client.ts","../src/filter.ts"],"sourcesContent":["//! `@duckedup/nidus` — the JavaScript/TypeScript client for nidus.\n//\n// A zero-dependency, cross-runtime remote client over the `nidus serve` HTTP API.\n// Point a {@link NidusClient} at a local or remote server, then upsert and search.\n\nexport { NidusClient } from \"./client.js\";\nexport type { FetchLike, NidusClientOptions } from \"./client.js\";\nexport { NidusError } from \"./errors.js\";\nexport { f } from \"./filter.js\";\nexport { decodeAttrs, decodeValue, encodeAttrs, encodeValue, v } from \"./values.js\";\nexport type {\n AggregateOptions,\n Aggregation,\n AnnInfo,\n AnnotationOptions,\n Annotations,\n AttrInput,\n ClauseScore,\n Expansion,\n ClusterStatus,\n Decay,\n DecodedRecord,\n DecodedValue,\n Expand,\n Filter,\n FilterIndexField,\n Footprint,\n Fragment,\n FtsCombine,\n FtsField,\n Highlight,\n HighlightOptions,\n Hit,\n HybridQuerySpelling,\n HybridSearchBase,\n HybridSearchOptions,\n LegScore,\n LimitPer,\n ListOptions,\n NidusRecord,\n OrderBy,\n PlanCandidates,\n PlanNarrowing,\n PlanTimings,\n Predicate,\n ProjectionOptions,\n QueryPath,\n QueryPlan,\n RankBy,\n RankingOptions,\n Readiness,\n RecallOptions,\n RecordInput,\n RememberOptions,\n RememberResult,\n RerankOptions,\n Rollup,\n SearchOptions,\n SimilarSearchOptions,\n Stats,\n StoreVersions,\n Suggestion,\n Suggestions,\n SuggestOptions,\n TextClause,\n TextQuerySpelling,\n TextSearchBase,\n TextSearchOptions,\n Value,\n} from \"./types.js\";\n","//! Decoding a hit's optional annotations — the opt-in \"why did this match\".\n//\n// One rule here is JS's alone. The server reports a highlight span as a **UTF-8 byte**\n// range into the fragment text, but a JS string is indexed in UTF-16 code units, so\n// `text.slice(...span)` on a raw span is wrong for any non-ASCII excerpt. Converted here,\n// once, so a caller's obvious slice is the right one.\n\nimport type { Annotations, Fragment, Highlight } from \"./types.js\";\n\n/** A fragment as it arrives: `spans` are UTF-8 byte offsets into `text`. */\ninterface WireFragment {\n text: string;\n spans: [number, number][];\n}\n\ninterface WireHighlight {\n field: string;\n fragments: WireFragment[];\n}\n\n/** A hit's annotations as they arrive, before the span offsets are converted. */\nexport interface WireAnnotations {\n vector?: { rank: number; score: number };\n text?: { rank: number; score: number };\n clauses?: {\n field: string;\n score: number;\n expansion?: { matched: number; scored: number };\n }[];\n highlights?: WireHighlight[];\n}\n\n/**\n * Decode a hit's annotations, converting every highlight span to JS string indices. The\n * parts the server omitted stay omitted rather than becoming empty arrays.\n */\nexport function decodeAnnotations(a: WireAnnotations): Annotations {\n const out: Annotations = {};\n if (a.vector) out.vector = a.vector;\n if (a.text) out.text = a.text;\n if (a.clauses) out.clauses = a.clauses;\n if (a.highlights) out.highlights = a.highlights.map(decodeHighlight);\n return out;\n}\n\nfunction decodeHighlight(h: WireHighlight): Highlight {\n return { field: h.field, fragments: h.fragments.map(decodeFragment) };\n}\n\nfunction decodeFragment(fr: WireFragment): Fragment {\n return { text: fr.text, spans: toStringIndices(fr.text, fr.spans) };\n}\n\n/**\n * Convert UTF-8 byte ranges into `text` to JS string indices (UTF-16 code units), so\n * `text.slice(...span)` yields the matched term. An all-ASCII excerpt needs no conversion\n * and is the common case, so it is detected before any table is built.\n */\nexport function toStringIndices(\n text: string,\n spans: [number, number][],\n): [number, number][] {\n if (spans.length === 0 || isAscii(text)) return spans;\n const index = byteToUnit(text);\n const at = (b: number): number =>\n index[Math.min(Math.max(b, 0), index.length - 1)]!;\n return spans.map(([start, end]): [number, number] => [at(start), at(end)]);\n}\n\n/** One entry per byte of `text` (plus its end), holding that byte's UTF-16 index. */\nfunction byteToUnit(text: string): number[] {\n const index: number[] = [];\n let unit = 0;\n // A byte *inside* a codepoint maps to that codepoint's start. Spans land on token\n // boundaries, so this only keeps a malformed offset from landing mid-surrogate.\n for (const ch of text) {\n for (let n = utf8Len(ch.codePointAt(0)!); n > 0; n--) index.push(unit);\n unit += ch.length;\n }\n index.push(unit);\n return index;\n}\n\nfunction utf8Len(codePoint: number): number {\n if (codePoint < 0x80) return 1;\n if (codePoint < 0x800) return 2;\n return codePoint < 0x10000 ? 3 : 4;\n}\n\n/** True when every code unit is ASCII, i.e. byte offsets already *are* string indices. */\nfunction isAscii(text: string): boolean {\n for (let i = 0; i < text.length; i++) {\n if (text.charCodeAt(i) > 0x7f) return false;\n }\n return true;\n}\n","//! Error type carrying the HTTP status the server reported.\n//\n// The server replies to a failed request with `{ \"error\": <message> }` and a\n// meaningful status (`src/server/mod.rs#classify`): 400 dimension mismatch,\n// 403 read-only store, 409 writer-lock conflict, 507 capacity/OOM, 500 otherwise.\n// Callers branch on `.status` to tell a client fault from a server fault.\n\n/** An error returned by a `nidus` server, or a transport failure reaching it. */\nexport class NidusError extends Error {\n /** The HTTP status code, or `0` for a transport/timeout failure (no response). */\n readonly status: number;\n\n constructor(message: string, status: number) {\n super(message);\n this.name = \"NidusError\";\n this.status = status;\n }\n\n /** A malformed request the server rejected (HTTP 400). */\n get isBadRequest(): boolean {\n return this.status === 400;\n }\n /** The store is read-only (HTTP 403). */\n get isReadOnly(): boolean {\n return this.status === 403;\n }\n /** The writer lock is held by another process (HTTP 409). */\n get isLocked(): boolean {\n return this.status === 409;\n }\n /** Out of capacity: `max_vector_bytes` exceeded or OOM (HTTP 507). */\n get isOutOfCapacity(): boolean {\n return this.status === 507;\n }\n}\n","//! Ergonomic constructors and decoders for the externally-tagged `Value` wire type.\n//\n// Callers should never hand-write `{ Str: \"x\" }`. Use `v.str(\"x\")`, `v.int(5)`,\n// etc., or just pass plain JS values into `attrs` — `encodeValue` normalizes them.\n//\n// One rule is JS's alone. The store's `Int` and `Float` are separate types compared\n// same-type only, but JS has one `number` and `1.0 === 1`, so `Number.isInteger` has to\n// decide. A whole-numbered measurement therefore lands as an `Int` in whichever records\n// it came out round, and a `Float` range filter then skips exactly those: write such a\n// field with `v.float`. Go and Python have the types JS lacks and decide from them.\n\nimport type { AttrInput, DecodedValue, Value } from \"./types.js\";\n\n/** Every tag this SDK version knows, in the order `decodeValue` tries them. */\nconst TAGS = [\"Str\", \"Int\", \"Bool\", \"List\", \"Float\", \"DateTime\"] as const;\n\n/**\n * Value constructors mirroring the `Value` variants. `v.int` requires a safe\n * integer and `v.float` a finite number — `NaN`/`Infinity` have no JSON spelling,\n * and `JSON.stringify` would quietly write `null`.\n */\nexport const v = {\n str: (s: string): Value => ({ Str: s }),\n int: (n: number): Value => {\n if (!Number.isInteger(n)) {\n throw new TypeError(`v.int expects an integer, got ${n}`);\n }\n return { Int: n };\n },\n float: (n: number): Value => {\n if (typeof n !== \"number\" || !Number.isFinite(n)) {\n throw new TypeError(`v.float expects a finite number, got ${n}`);\n }\n return { Float: n };\n },\n bool: (b: boolean): Value => ({ Bool: b }),\n list: (items: string[]): Value => ({ List: items }),\n /**\n * A UTC instant, from a `Date` or a raw epoch-millisecond count. Milliseconds is\n * the wire type, so there is no sub-millisecond precision and no timezone.\n */\n datetime: (when: Date | number): Value => {\n const ms = when instanceof Date ? when.getTime() : when;\n if (!Number.isSafeInteger(ms)) {\n throw new TypeError(\n `v.datetime expects a valid Date or epoch ms, got ${when}`,\n );\n }\n return { DateTime: ms };\n },\n /** The explicit `Null` value — set-but-empty, distinct from an absent key. */\n nil: (): Value => \"Null\",\n} as const;\n\n/** True if `x` is already a wire-tagged {@link Value}. */\nfunction isValue(x: unknown): x is Value {\n if (x === \"Null\") return true;\n if (typeof x !== \"object\" || x === null) return false;\n return TAGS.some((tag) => tag in x);\n}\n\n/**\n * Normalize a caller-supplied {@link AttrInput} into the wire {@link Value} shape.\n * Plain scalars map by type; an already-tagged `Value` passes through unchanged.\n * Throws on a non-finite number, an invalid `Date`, or a non-string list element.\n */\nexport function encodeValue(input: AttrInput): Value {\n if (isValue(input)) return input;\n if (input === null) return \"Null\";\n switch (typeof input) {\n case \"string\":\n return { Str: input };\n case \"boolean\":\n return { Bool: input };\n case \"number\":\n return Number.isInteger(input) ? v.int(input) : v.float(input);\n case \"object\":\n // Date before the array check: both are objects, only one is a list.\n if (input instanceof Date) return v.datetime(input);\n if (Array.isArray(input)) {\n if (!input.every((e) => typeof e === \"string\")) {\n throw new TypeError(\"a List attribute must contain only strings\");\n }\n return { List: input };\n }\n // falls through\n default:\n throw new TypeError(`cannot encode attribute value: ${String(input)}`);\n }\n}\n\n/** Normalize a whole `attrs` map of {@link AttrInput} into wire {@link Value}s. */\nexport function encodeAttrs(\n attrs: Record<string, AttrInput>,\n): Record<string, Value> {\n const out: Record<string, Value> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = encodeValue(val);\n }\n return out;\n}\n\n/** Decode a wire {@link Value} back to a plain JS value. */\nexport function decodeValue(value: Value): DecodedValue {\n if (value === \"Null\") return null;\n if (\"Str\" in value) return value.Str;\n if (\"Int\" in value) return value.Int;\n if (\"Bool\" in value) return value.Bool;\n if (\"List\" in value) return value.List;\n if (\"Float\" in value) return value.Float;\n // A Date, not the raw number: a number would demote every instant to an Int\n // when a decoded attrs map is written back.\n if (\"DateTime\" in value) return new Date(value.DateTime);\n // Unknown tag (forward-compat): hand it back untouched.\n return value as unknown as DecodedValue;\n}\n\n/** Decode a whole wire `attrs` map back to plain JS values. */\nexport function decodeAttrs(\n attrs: Record<string, Value>,\n): Record<string, DecodedValue> {\n const out: Record<string, DecodedValue> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = decodeValue(val);\n }\n return out;\n}\n","//! `NidusClient` — a remote client over the `nidus serve` HTTP API.\n//\n// One method per endpoint (`src/server/mod.rs`). \"Local vs remote\" is just the\n// base URL: point at a local `nidus serve` or any reachable host. Built on the\n// platform-global `fetch`, so it runs unchanged on Node 18+, Deno, Bun, Cloudflare\n// Workers, and browsers — with no runtime dependencies.\n\nimport { decodeAnnotations, type WireAnnotations } from \"./annotations.js\";\nimport { NidusError } from \"./errors.js\";\nimport type {\n AggregateOptions,\n Aggregation,\n BatchSearchOptions,\n ClusterStatus,\n DecodedRecord,\n Expand,\n Filter,\n FilterIndexField,\n FtsField,\n HighlightOptions,\n Hit,\n HybridSearchOptions,\n ListOptions,\n NidusRecord,\n PlanCandidates,\n PlanNarrowing,\n PlanTimings,\n QueryPlan,\n RankBy,\n Readiness,\n RecallOptions,\n RecordInput,\n RememberOptions,\n RememberResult,\n RerankOptions,\n Rollup,\n SearchOptions,\n SimilarSearchOptions,\n Stats,\n StoreVersions,\n Suggestions,\n SuggestOptions,\n TextSearchOptions,\n Value,\n} from \"./types.js\";\nimport { decodeAttrs, decodeValue, encodeAttrs } from \"./values.js\";\n\n/** Minimal `fetch` signature the client needs — satisfied by the platform global. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Construction options for {@link NidusClient}. */\nexport interface NidusClientOptions {\n /** Base URL of the server, e.g. `http://127.0.0.1:7700`. Trailing slash optional. */\n baseUrl: string;\n /** Bearer token, when the server was started with `--token`. */\n token?: string;\n /** Override the `fetch` implementation (defaults to `globalThis.fetch`). */\n fetch?: FetchLike;\n /** Per-request timeout in milliseconds. Omit (or `0`) to disable. */\n timeoutMs?: number;\n /** Extra headers sent on every request. */\n headers?: Record<string, string>;\n}\n\nexport class NidusClient {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly doFetch: FetchLike;\n private readonly timeoutMs: number;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: NidusClientOptions) {\n if (!options.baseUrl) {\n throw new TypeError(\"NidusClient requires a baseUrl\");\n }\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.token = options.token;\n this.timeoutMs = options.timeoutMs ?? 0;\n this.extraHeaders = options.headers ?? {};\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\n \"no fetch available; pass options.fetch (Node < 18, or a custom runtime)\",\n );\n }\n // Bind so a passed `globalThis.fetch` keeps its `this`.\n this.doFetch = f === globalThis.fetch ? f.bind(globalThis) : f;\n }\n\n // ── Admin / introspection ─────────────────────────────────────────────────\n\n /** Liveness check. Returns `true` when the server answers `/health`. */\n async health(): Promise<boolean> {\n try {\n const res = await this.raw(\"GET\", \"/health\");\n return res.ok;\n } catch {\n return false;\n }\n }\n\n /** Store-wide introspection: dimension, distance, ANN config, collections, footprint. */\n stats(): Promise<Stats> {\n return this.request<Stats>(\"GET\", \"/stats\");\n }\n\n /**\n * Readiness: whether this instance can serve. A `503` is the negative answer, not an\n * error, so a poll loop branches on `ready` instead of catching. Other failures throw.\n */\n async ready(): Promise<Readiness> {\n const res = await this.raw(\"GET\", \"/ready\");\n const text = await res.text();\n if (res.status === 503) return { ready: false, reason: extractError(text, 503) };\n if (!res.ok) throw new NidusError(extractError(text, res.status), res.status);\n return JSON.parse(text) as Readiness;\n }\n\n /** Cluster role, writer-handle state, fencing token, commit counter, staleness. */\n cluster(): Promise<ClusterStatus> {\n return this.request<ClusterStatus>(\"GET\", \"/cluster\");\n }\n\n /** The readable commit points and this instance's pin, if any. */\n versions(): Promise<StoreVersions> {\n return this.request<StoreVersions>(\"GET\", \"/versions\");\n }\n\n /** List every collection name. */\n collections(): Promise<string[]> {\n return this.request<string[]>(\"GET\", \"/collections\");\n }\n\n /** Create a collection. Idempotent on the server side. */\n async createCollection(name: string): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}`, {});\n }\n\n /** Drop a collection and all its records. */\n async dropCollection(name: string): Promise<void> {\n await this.request(\"DELETE\", `/collections/${enc(name)}`);\n }\n\n /** Every alias and the concrete collection it resolves to. */\n aliases(): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\"GET\", \"/aliases\");\n }\n\n /** Create or repoint an alias. The target must already exist; aliases never chain. */\n async setAlias(name: string, target: string): Promise<void> {\n await this.request(\"PUT\", `/aliases/${enc(name)}`, { target });\n }\n\n /** Remove an alias. Deletes no records. */\n async dropAlias(name: string): Promise<void> {\n await this.request(\"DELETE\", `/aliases/${enc(name)}`);\n }\n\n /** Read a collection's free-form string metadata. */\n getMeta(name: string): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\n \"GET\",\n `/collections/${enc(name)}/meta`,\n );\n }\n\n /** Replace a collection's free-form string metadata. */\n async setMeta(name: string, meta: Record<string, string>): Promise<void> {\n await this.request(\"PUT\", `/collections/${enc(name)}/meta`, meta);\n }\n\n // ── Data ──────────────────────────────────────────────────────────────────\n\n /**\n * Insert or replace records (idempotent on `id` within the collection).\n * `attrs` accept plain JS values or `v.*` helpers; they are normalized for you.\n * Returns the number of records upserted.\n */\n async upsert(name: string, records: RecordInput[]): Promise<number> {\n const wire: NidusRecord[] = records.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: encodeAttrs(r.attrs),\n }));\n const res = await this.request<{ upserted: number }>(\n \"POST\",\n `/collections/${enc(name)}/upsert`,\n { records: wire },\n );\n return res.upserted;\n }\n\n /** Delete records by id. Returns the number deleted. */\n async delete(name: string, opts: { ids: string[] }): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { ids: opts.ids },\n );\n return res.deleted;\n }\n\n /** Delete every record matching `filter`. Returns the number deleted. */\n async deleteWhere(name: string, filter: Filter): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { filter },\n );\n return res.deleted;\n }\n\n /** Fetch every record in a collection (attrs decoded to plain JS values). */\n async records(name: string): Promise<DecodedRecord[]> {\n const recs = await this.request<NidusRecord[]>(\n \"GET\",\n `/collections/${enc(name)}/records`,\n );\n return recs.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: decodeAttrs(r.attrs),\n }));\n }\n\n /**\n * Declare the full-text-indexed attribute fields for a collection. A bare string\n * takes the server's BM25/analyzer defaults; an {@link FtsField} object tunes `k1`,\n * `b`, and the analyzer for that field alone.\n */\n async setFtsSchema(\n name: string,\n fields: (string | FtsField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/fts-schema`, {\n fields: fields.map(encodeFtsField),\n });\n }\n\n /**\n * Declare which attribute fields are indexed for the text predicates (`Fuzzy`,\n * `ContainsAllTokens`, `ContainsAnyToken`, `ContainsTokenSequence`, `Regex`). Fields\n * already written are indexed as part of applying the declaration.\n *\n * This changes how fast those predicates run, never what they return: the index\n * proposes candidate documents and the predicate itself still decides. The cost is\n * paid at write time and in memory. Pass an empty array to drop the declaration.\n */\n async setFilterIndex(\n name: string,\n fields: (string | FilterIndexField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/filter-index`, {\n fields: fields.map(encodeFilterIndexField),\n });\n }\n\n // ── Search ──────────────────────────────────────────────────────────────\n\n /** Vector (cosine) nearest-neighbour search. Empty `scope` searches all collections. */\n search(opts: SearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.search}, but also reports the scan strategy the server took. */\n searchWithPlan(\n opts: SearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Records most like an existing one. The source record itself is never returned. */\n searchSimilar(opts: SimilarSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /** Like {@link NidusClient.searchSimilar}, but also reports the scan strategy taken. */\n searchSimilarWithPlan(\n opts: SimilarSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /**\n * BM25 full-text search over one indexed field, or over a `clauses` list folded by\n * `combine` (`\"Sum\"` unless said otherwise). Naming the fields both ways is a `400`.\n */\n textSearch(opts: TextSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/text-search\", {\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, query: opts.query, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /**\n * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by\n * document frequency (commonest first), which is the opposite of how a prefix clause\n * ranks documents. Completions are real spellings: the prefix is folded, not stemmed.\n *\n * The `df` counts only documents passing `filter` and carrying every word already typed\n * before the final token, so a permission-scoped dropdown is expressible and \"quick br\"\n * completes against the documents that also say \"quick\".\n */\n suggest(opts: SuggestOptions): Promise<Suggestions> {\n return this.request<Suggestions>(\n \"POST\",\n \"/suggest\",\n prune({\n scope: opts.scope ?? [],\n field: opts.field,\n prefix: opts.prefix,\n limit: opts.limit,\n filter: opts.filter ?? [],\n }),\n );\n }\n\n /**\n * Hybrid search: fuse a vector query and a BM25 text query via RRF. The text leg takes\n * the same single-field / `clauses` choice as {@link NidusClient.textSearch}.\n */\n hybridSearch(opts: HybridSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.hybridSearch}, but also reports the scan strategy taken. */\n hybridSearchWithPlan(\n opts: HybridSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Metadata-only listing (no vector), paginated by `offset`/`limit`. */\n list(opts: ListOptions = {}): Promise<Hit[]> {\n return this.searchRequest(\"/list\", {\n scope: opts.scope ?? [],\n offset: opts.offset,\n limit: opts.limit,\n filter: opts.filter ?? [],\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n order_by: opts.orderBy,\n });\n }\n\n /**\n * Count the records matching a filter and sum the named attributes. Answered from the\n * in-RAM index alone — no record is built and no vector is read.\n */\n async aggregate(opts: AggregateOptions = {}): Promise<Aggregation> {\n const res = await this.request<RawAggregation>(\n \"POST\",\n \"/aggregate\",\n prune({\n scope: opts.scope ?? [],\n filter: opts.filter ?? [],\n sum: opts.sum ?? [],\n group_by: opts.groupBy,\n }),\n );\n // Every sum is an `Int` or a `Float`, both of which decode to a JS number.\n return {\n count: res.count,\n sums: decodeAttrs(res.sums) as Record<string, number>,\n // Kept absent, not `undefined`, so an ungrouped answer is the shape it always was.\n ...(res.groups\n ? {\n groups: res.groups.map((g) => ({\n value: g.value === null ? null : decodeValue(g.value),\n count: g.count,\n sums: decodeAttrs(g.sums) as Record<string, number>,\n })),\n }\n : {}),\n ...(res.groups_truncated ? { groupsTruncated: true } : {}),\n };\n }\n\n /**\n * Answer several vector queries in one round-trip (16 max). Returns one ranking per\n * query in request order, or — with `opts.fuse` — a single array holding the one fused\n * ranking, so the return shape is uniform either way.\n *\n * The server validates the whole batch before running any leg, so a malformed query\n * fails the call rather than returning a partial answer that cannot be told apart.\n */\n async batchSearch(opts: BatchSearchOptions): Promise<Hit[][]> {\n const body = prune({\n queries: opts.queries.map((q) => ({\n query: q.query,\n scope: q.scope ?? [],\n top_k: q.topK,\n offset: q.offset,\n min_score: q.minScore,\n filter: q.filter ?? [],\n exact: q.exact,\n include_attributes: q.includeAttributes,\n exclude_attributes: q.excludeAttributes,\n rank_by: encodeRankBy(q.rankBy),\n limit_per: q.limitPer,\n diversity: q.diversity,\n expand: encodeExpand(q.expand),\n })),\n fuse: opts.fuse\n ? prune({\n rrf_k: opts.fuse.rrfK,\n weights: opts.fuse.weights,\n top_k: opts.fuse.topK,\n })\n : undefined,\n });\n const res = await this.request<RawBatchSearch>(\n \"POST\",\n \"/search/batch\",\n body,\n );\n return (res.fused ? [res.fused] : (res.results ?? [])).map((hits) =>\n hits.map((h) => this.decodeHit(h)),\n );\n }\n\n // ── Memory (text-native) ──────────────────────────────────────────────────\n //\n // Available only when `nidus serve` was started with an embedder\n // (`--embed-provider …`); otherwise these answer `400`. The server embeds the\n // text/query — the client only sends strings.\n\n /**\n * Embed `text` and upsert it under `id` in `collection` (idempotent on `id`).\n * With `opts.mode === \"summarize\"` the server summarizes first, embeds the\n * summary, and stamps a `nidus.summary` attr (requires the server to have a\n * summarizer). The raw text is always stored under `nidus.text`. `opts.attrs` accept plain JS values or `v.*`\n * helpers; they are normalized for you.\n *\n * Read `id` off the result rather than assuming the one you passed:\n * `opts.dedupeThreshold` can redirect the write onto a near-duplicate.\n */\n async remember(\n collection: string,\n id: string,\n text: string,\n opts: RememberOptions = {},\n ): Promise<RememberResult> {\n const res = await this.request<Partial<RememberResult> | undefined>(\n \"POST\",\n `/collections/${enc(collection)}/remember`,\n prune({\n id,\n text,\n mode: opts.mode,\n attrs: opts.attrs ? encodeAttrs(opts.attrs) : undefined,\n ttl_seconds: opts.ttlSeconds,\n dedupe_threshold: opts.dedupeThreshold,\n }),\n );\n // A server predating the echoed fields answers `{ok, upserted}`; falling back to the\n // requested id keeps that case honest instead of reporting `undefined` as the target.\n return {\n id: res?.id ?? id,\n upserted: res?.upserted ?? 0,\n deduped: res?.deduped ?? false,\n };\n }\n\n /**\n * Embed `query` and vector-search `collection`, best-first (attrs decoded to\n * plain JS values). Refused with a cross-model guard if the collection was\n * written with a different embedder than the server's.\n */\n recall(\n collection: string,\n query: string,\n opts: RecallOptions = {},\n ): Promise<Hit[]> {\n return this.searchRequest(`/collections/${enc(collection)}/recall`, {\n query,\n top_k: opts.topK,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n diversity: opts.diversity,\n rollup: encodeRollup(opts.rollup),\n rerank: encodeRerank(opts.rerank),\n reinforce: opts.reinforce,\n extend_ttl_seconds: opts.extendTtlSeconds,\n rank_by: encodeRankBy(opts.rankBy),\n });\n }\n\n // ── Maintenance ───────────────────────────────────────────────────────────\n\n /** Force a durability flush. */\n async flush(): Promise<void> {\n await this.request(\"POST\", \"/flush\", {});\n }\n\n /** Compact the store (reclaim space from deleted/overwritten rows). */\n async compact(): Promise<void> {\n await this.request(\"POST\", \"/compact\", {});\n }\n\n /** Adopt a writer's newer committed state. Returns whether anything was adopted. */\n async refresh(): Promise<boolean> {\n const res = await this.request<{ adopted: boolean }>(\"POST\", \"/refresh\", {});\n return res.adopted;\n }\n\n // ── Internals ─────────────────────────────────────────────────────────────\n\n /** Run a search-family request and decode the resulting hits' attrs. */\n private async searchRequest(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Hit[]> {\n const hits = await this.request<RawHit[]>(\"POST\", path, prune(body));\n return hits.map((h) => this.decodeHit(h));\n }\n\n /** Like {@link NidusClient.searchRequest}, asking for `plan: true` and decoding it too. */\n private async searchRequestWithPlan(\n path: string,\n body: Record<string, unknown>,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n const res = await this.request<{ hits: RawHit[]; plan: RawQueryPlan }>(\n \"POST\",\n path,\n prune({ ...body, plan: true }),\n );\n return {\n hits: res.hits.map((h) => this.decodeHit(h)),\n plan: decodeQueryPlan(res.plan),\n };\n }\n\n /** One wire hit into a {@link Hit}. Shared so every search surface decodes identically. */\n private decodeHit(h: RawHit): Hit {\n return {\n collection: h.collection,\n id: h.id,\n score: h.score,\n attrs: decodeAttrs(h.attrs),\n // Kept absent, not `undefined`, so an unannotated hit is the shape it always was.\n ...(h.annotations\n ? { annotations: decodeAnnotations(h.annotations) }\n : {}),\n ...(h.context !== undefined ? { context: h.context } : {}),\n };\n }\n\n /** Issue a request and parse a JSON body, mapping a non-2xx to {@link NidusError}. */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const res = await this.raw(method, path, body);\n const text = await res.text();\n if (!res.ok) {\n throw new NidusError(extractError(text, res.status), res.status);\n }\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** The bare transport: headers, auth, timeout, and transport-error mapping. */\n private async raw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const headers: Record<string, string> = { ...this.extraHeaders };\n if (this.token) headers.authorization = `Bearer ${this.token}`;\n let payload: string | undefined;\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n payload = JSON.stringify(body);\n }\n\n const controller = this.timeoutMs > 0 ? new AbortController() : undefined;\n const timer =\n controller && this.timeoutMs > 0\n ? setTimeout(() => controller.abort(), this.timeoutMs)\n : undefined;\n try {\n return await this.doFetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: payload,\n signal: controller?.signal,\n });\n } catch (err) {\n const reason =\n (controller?.signal.aborted ?? false)\n ? `request to ${path} timed out after ${this.timeoutMs}ms`\n : `request to ${path} failed: ${(err as Error).message}`;\n throw new NidusError(reason, 0);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\n/** A hit as it arrives on the wire, before attrs are decoded. */\ninterface RawHit {\n collection: string;\n id: string;\n score: number;\n attrs: Record<string, Value>;\n annotations?: WireAnnotations;\n context?: string;\n}\n\n/** A `QueryPlan` as it arrives on the wire (snake_case), before camelCasing. */\ninterface RawQueryPlan {\n path: string;\n rows_scanned?: number;\n candidates?: {\n surfaced: number;\n survived: number;\n dropped_out_of_scope: number;\n dropped_stale: number;\n dropped_filtered: number;\n dropped_min_score: number;\n };\n narrowing: { state: PlanNarrowing[\"state\"]; candidates?: number };\n timings: {\n narrow_us?: number;\n gather_us?: number;\n walk_us?: number;\n resolve_us?: number;\n first_pass_us?: number;\n rescore_us?: number;\n score_us?: number;\n total_us: number;\n };\n}\n\n/** Wire `QueryPlan` into its camelCase {@link QueryPlan} shape. */\nfunction decodeQueryPlan(p: RawQueryPlan): QueryPlan {\n const candidates: PlanCandidates | undefined = p.candidates\n ? {\n surfaced: p.candidates.surfaced,\n survived: p.candidates.survived,\n droppedOutOfScope: p.candidates.dropped_out_of_scope,\n droppedStale: p.candidates.dropped_stale,\n droppedFiltered: p.candidates.dropped_filtered,\n droppedMinScore: p.candidates.dropped_min_score,\n }\n : undefined;\n const t = p.timings;\n const timings: PlanTimings = {\n ...(t.narrow_us !== undefined ? { narrowUs: t.narrow_us } : {}),\n ...(t.gather_us !== undefined ? { gatherUs: t.gather_us } : {}),\n ...(t.walk_us !== undefined ? { walkUs: t.walk_us } : {}),\n ...(t.resolve_us !== undefined ? { resolveUs: t.resolve_us } : {}),\n ...(t.first_pass_us !== undefined ? { firstPassUs: t.first_pass_us } : {}),\n ...(t.rescore_us !== undefined ? { rescoreUs: t.rescore_us } : {}),\n ...(t.score_us !== undefined ? { scoreUs: t.score_us } : {}),\n totalUs: t.total_us,\n };\n return {\n path: p.path,\n ...(p.rows_scanned !== undefined ? { rowsScanned: p.rows_scanned } : {}),\n ...(candidates ? { candidates } : {}),\n narrowing: {\n state: p.narrowing.state,\n ...(p.narrowing.candidates !== undefined\n ? { candidates: p.narrowing.candidates }\n : {}),\n },\n timings,\n };\n}\n\n/** An `/aggregate` response, whose sums arrive as tagged {@link Value}s. */\ninterface RawAggregation {\n count: number;\n sums: Record<string, Value>;\n groups?: {\n value: Value | null;\n count: number;\n sums: Record<string, Value>;\n }[];\n groups_truncated?: boolean;\n}\n\n/** A `/search/batch` response: exactly one of the two fields is present. */\ninterface RawBatchSearch {\n results?: RawHit[][];\n fused?: RawHit[];\n}\n\n/** Encode `rankBy` to its externally-tagged wire form, dropping the knobs left unset. */\n/** camelCase → the wire's snake_case, omitting the object entirely when unset. */\nfunction encodeExpand(e: Expand | undefined): unknown {\n if (!e) return undefined;\n return prune({\n radius: e.radius,\n parent_field: e.parentField,\n index_field: e.indexField,\n text_field: e.textField,\n });\n}\n\nfunction encodeRollup(r: Rollup | undefined): unknown {\n if (!r) return undefined;\n return prune({ per_parent: r.perParent, neighbours: r.neighbours });\n}\n\nfunction encodeRankBy(rank: RankBy | undefined): unknown {\n if (!rank) return undefined;\n const d = rank.decay;\n return {\n Decay: prune({\n field: d.field,\n origin: d.origin instanceof Date ? d.origin.getTime() : d.origin,\n scale: d.scale,\n decay: d.decay,\n lambda: d.lambda,\n missing: d.missing,\n count_field: d.countField,\n count_scale: d.countScale,\n count_lambda: d.countLambda,\n }),\n };\n}\n\n/** Encode `highlight`: `true` is the empty object the server reads as \"all defaults\". */\nfunction encodeHighlight(h: boolean | HighlightOptions | undefined): unknown {\n if (h === undefined || h === false) return undefined;\n if (h === true) return {};\n return prune({\n max_fragments: h.maxFragments,\n fragment_chars: h.fragmentChars,\n });\n}\n\n/** Encode `rerank`. Undefined sub-fields drop out at `JSON.stringify`, not here. */\nfunction encodeRerank(r: RerankOptions | undefined): unknown {\n if (r === undefined) return undefined;\n return { query: r.query, overscan: r.overscan, text_attr: r.textAttr };\n}\n\n/** Path-segment encode a collection name (allows slashes/spaces in names). */\nfunction enc(name: string): string {\n return encodeURIComponent(name);\n}\n\n/**\n * Encode one `setFtsSchema` field. A string passes through as the server's bare-name\n * form; an object becomes the snake_case body, pruned so an unset knob keeps the\n * server's default rather than being sent as `undefined`.\n */\nfunction encodeFtsField(f: string | FtsField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n k1: f.k1,\n b: f.b,\n language: f.language,\n ascii_folding: f.asciiFolding,\n max_token_len: f.maxTokenLen,\n });\n}\n\n/**\n * Encode one `setFilterIndex` field, on the same bare-name-or-object rule as\n * {@link encodeFtsField}. Pruning matters here: the server defaults both structures to\n * `true`, so sending an explicit `undefined` would be indistinguishable from `false`.\n */\nfunction encodeFilterIndexField(f: string | FilterIndexField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n tokens: f.tokens,\n trigrams: f.trigrams,\n });\n}\n\n/** Drop `undefined` fields so server `#[serde(default)]`s apply instead. */\nfunction prune(body: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(body)) {\n if (val !== undefined) out[k] = val;\n }\n return out;\n}\n\n/** Pull the `{ \"error\": … }` message out of a failed response, or fall back. */\nfunction extractError(text: string, status: number): string {\n try {\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed.error === \"string\") return parsed.error;\n } catch {\n // not JSON — fall through\n }\n return text || `HTTP ${status}`;\n}\n","//! Filter builder producing the bare predicate-array wire shape.\n//\n// A `Filter` is AND-combined predicates; on the wire it is a plain array. Each\n// predicate is a *positive assertion about a present attribute* — an absent key\n// matches nothing, including the negative predicates (`ne`/`notIn`) and ranges.\n// Comparisons are same-type only (Int↔Int numeric, Float↔Float by IEEE, Str↔Str\n// lexical, Bool↔Bool, DateTime↔DateTime as instants), so an operand's encoded type\n// has to match the attribute's: `ge(\"score\", v.float(2))`, not `ge(\"score\", 2)`.\n\nimport type { AttrInput, Filter, Predicate, Value } from \"./types.js\";\nimport { encodeValue } from \"./values.js\";\n\n/**\n * Predicate constructors. Each accepts a plain JS value (auto-normalized) or an\n * explicit `v.*` {@link Value}. Combine results into a {@link Filter} array, or\n * use {@link f.and} for readability.\n */\nexport const f = {\n /** `attrs[key] === value`. */\n eq: (key: string, value: AttrInput): Predicate => ({\n Eq: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is present and `!== value`. */\n ne: (key: string, value: AttrInput): Predicate => ({\n Ne: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `Str` matching the glob pattern (`*`, `?`, `[..]`). */\n glob: (key: string, pattern: string): Predicate => ({ Glob: [key, pattern] }),\n /**\n * {@link f.glob}, ignoring **ASCII** case on both sides — `\"Src/*\"` matches\n * `\"src/main.rs\"`. Non-ASCII is not folded (`É` does not match `é`).\n */\n iglob: (key: string, pattern: string): Predicate => ({\n IGlob: [key, pattern],\n }),\n /** `attrs[key]` equals one of `values`. */\n in: (key: string, values: AttrInput[]): Predicate => ({\n In: [key, values.map(encodeValue)],\n }),\n /** `attrs[key]` is present and equals none of `values`. */\n notIn: (key: string, values: AttrInput[]): Predicate => ({\n NotIn: [key, values.map(encodeValue)],\n }),\n /** `attrs[key] < value` (same-type, orderable). */\n lt: (key: string, value: AttrInput): Predicate => ({\n Lt: [key, encodeValue(value)],\n }),\n /** `attrs[key] <= value` (same-type, orderable). */\n le: (key: string, value: AttrInput): Predicate => ({\n Le: [key, encodeValue(value)],\n }),\n /** `attrs[key] > value` (same-type, orderable). */\n gt: (key: string, value: AttrInput): Predicate => ({\n Gt: [key, encodeValue(value)],\n }),\n /** `attrs[key] >= value` (same-type, orderable). */\n ge: (key: string, value: AttrInput): Predicate => ({\n Ge: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` containing `value` (whole-element, not substring). */\n contains: (key: string, value: AttrInput): Predicate => ({\n Contains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a present `List` not containing `value`. */\n notContains: (key: string, value: AttrInput): Predicate => ({\n NotContains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` sharing at least one element with `values`. */\n containsAny: (key: string, values: AttrInput[]): Predicate => ({\n ContainsAny: [key, values.map(encodeValue)],\n }),\n /** Every sub-predicate holds. `all()` is `true`. */\n all: (...preds: Predicate[]): Predicate => ({ All: preds }),\n /** At least one sub-predicate holds. `any()` is `false`. */\n any: (...preds: Predicate[]): Predicate => ({ Any: preds }),\n /**\n * The sub-predicate does not hold. Differs from {@link f.ne} on an absent key:\n * `not(eq(k, v))` matches a record with no `k`, `ne(k, v)` does not.\n */\n not: (pred: Predicate): Predicate => ({ Not: pred }),\n /**\n * `attrs[key]` is within `maxEdits` Levenshtein edits of `text`, ASCII-case-folded on\n * both sides; a `List` matches if any element does. The only three-element predicate.\n * A `maxEdits` above 8 is refused by the server, not clamped.\n */\n fuzzy: (key: string, text: string, maxEdits: number): Predicate => ({\n Fuzzy: [key, text, maxEdits],\n }),\n /**\n * Every token of `text` appears among `attrs[key]`'s tokens, in any order. Tokens are\n * ASCII-case-folded runs of alphanumerics; a `List` matches if any single element does.\n */\n containsAllTokens: (key: string, text: string): Predicate => ({\n ContainsAllTokens: [key, text],\n }),\n /** At least one token of `text` appears among `attrs[key]`'s tokens. Empty never matches. */\n containsAnyToken: (key: string, text: string): Predicate => ({\n ContainsAnyToken: [key, text],\n }),\n /** `text`'s tokens appear consecutively and in order — a phrase match. */\n containsTokenSequence: (key: string, text: string): Predicate => ({\n ContainsTokenSequence: [key, text],\n }),\n /**\n * `attrs[key]` matches the regular expression, **anchored at both ends** like\n * {@link f.glob} — `.*` opts back into a substring search, and `(?i)` into case folding.\n * The syntax is Rust's `regex`, not JS's: no backreferences and no lookaround.\n */\n regex: (key: string, pattern: string): Predicate => ({ Regex: [key, pattern] }),\n /** Collect predicates into a {@link Filter} (purely sugar — they already AND). */\n and: (...preds: Predicate[]): Filter => preds,\n} as const;\n\n// Aliases for the comparison operators, for callers who prefer them.\nexport type { Filter, Predicate, Value };\n"],"mappings":"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","names":["f"]}
package/dist/index.d.cts CHANGED
@@ -486,13 +486,22 @@ interface TextSearchBase extends ProjectionOptions, RankingOptions, AnnotationOp
486
486
  type TextSearchOptions = TextSearchBase & TextQuerySpelling;
487
487
  /** Options for {@link NidusClient.suggest}. */
488
488
  interface SuggestOptions {
489
- collection: string;
489
+ /** Collections whose vocabulary to complete from. Omit or leave empty for all of them. */
490
+ scope?: string[];
490
491
  /** The full-text-indexed field whose vocabulary to complete from. */
491
492
  field: string;
492
- /** The partial word being typed. Only its final token is completed. */
493
+ /**
494
+ * The phrase typed so far. Its final token is completed; the words before it narrow the
495
+ * completions to documents that also contain them, so send the whole phrase.
496
+ */
493
497
  prefix: string;
494
498
  /** How many completions to return. The server defaults to 10. */
495
499
  limit?: number;
500
+ /**
501
+ * Each completion's `df` counts only documents matching this filter, so a completion no
502
+ * matching document carries is not offered at all.
503
+ */
504
+ filter?: Filter;
496
505
  }
497
506
  /** One completion: an indexed term and how many live documents contain it. */
498
507
  interface Suggestion {
@@ -809,7 +818,11 @@ declare class NidusClient {
809
818
  /**
810
819
  * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by
811
820
  * document frequency (commonest first), which is the opposite of how a prefix clause
812
- * ranks documents. Completions are stems: the prefix is folded, not stemmed.
821
+ * ranks documents. Completions are real spellings: the prefix is folded, not stemmed.
822
+ *
823
+ * The `df` counts only documents passing `filter` and carrying every word already typed
824
+ * before the final token, so a permission-scoped dropdown is expressible and "quick br"
825
+ * completes against the documents that also say "quick".
813
826
  */
814
827
  suggest(opts: SuggestOptions): Promise<Suggestions>;
815
828
  /**
package/dist/index.d.ts CHANGED
@@ -486,13 +486,22 @@ interface TextSearchBase extends ProjectionOptions, RankingOptions, AnnotationOp
486
486
  type TextSearchOptions = TextSearchBase & TextQuerySpelling;
487
487
  /** Options for {@link NidusClient.suggest}. */
488
488
  interface SuggestOptions {
489
- collection: string;
489
+ /** Collections whose vocabulary to complete from. Omit or leave empty for all of them. */
490
+ scope?: string[];
490
491
  /** The full-text-indexed field whose vocabulary to complete from. */
491
492
  field: string;
492
- /** The partial word being typed. Only its final token is completed. */
493
+ /**
494
+ * The phrase typed so far. Its final token is completed; the words before it narrow the
495
+ * completions to documents that also contain them, so send the whole phrase.
496
+ */
493
497
  prefix: string;
494
498
  /** How many completions to return. The server defaults to 10. */
495
499
  limit?: number;
500
+ /**
501
+ * Each completion's `df` counts only documents matching this filter, so a completion no
502
+ * matching document carries is not offered at all.
503
+ */
504
+ filter?: Filter;
496
505
  }
497
506
  /** One completion: an indexed term and how many live documents contain it. */
498
507
  interface Suggestion {
@@ -809,7 +818,11 @@ declare class NidusClient {
809
818
  /**
810
819
  * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by
811
820
  * document frequency (commonest first), which is the opposite of how a prefix clause
812
- * ranks documents. Completions are stems: the prefix is folded, not stemmed.
821
+ * ranks documents. Completions are real spellings: the prefix is folded, not stemmed.
822
+ *
823
+ * The `df` counts only documents passing `filter` and carrying every word already typed
824
+ * before the final token, so a permission-scoped dropdown is expressible and "quick br"
825
+ * completes against the documents that also say "quick".
813
826
  */
814
827
  suggest(opts: SuggestOptions): Promise<Suggestions>;
815
828
  /**
package/dist/index.js CHANGED
@@ -422,13 +422,23 @@ var NidusClient = class {
422
422
  /**
423
423
  * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by
424
424
  * document frequency (commonest first), which is the opposite of how a prefix clause
425
- * ranks documents. Completions are stems: the prefix is folded, not stemmed.
425
+ * ranks documents. Completions are real spellings: the prefix is folded, not stemmed.
426
+ *
427
+ * The `df` counts only documents passing `filter` and carrying every word already typed
428
+ * before the final token, so a permission-scoped dropdown is expressible and "quick br"
429
+ * completes against the documents that also say "quick".
426
430
  */
427
431
  suggest(opts) {
428
432
  return this.request(
429
433
  "POST",
430
- `/collections/${enc(opts.collection)}/suggest`,
431
- prune({ field: opts.field, prefix: opts.prefix, limit: opts.limit })
434
+ "/suggest",
435
+ prune({
436
+ scope: opts.scope ?? [],
437
+ field: opts.field,
438
+ prefix: opts.prefix,
439
+ limit: opts.limit,
440
+ filter: opts.filter ?? []
441
+ })
432
442
  );
433
443
  }
434
444
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/annotations.ts","../src/errors.ts","../src/values.ts","../src/client.ts","../src/filter.ts"],"sourcesContent":["//! Decoding a hit's optional annotations — the opt-in \"why did this match\".\n//\n// One rule here is JS's alone. The server reports a highlight span as a **UTF-8 byte**\n// range into the fragment text, but a JS string is indexed in UTF-16 code units, so\n// `text.slice(...span)` on a raw span is wrong for any non-ASCII excerpt. Converted here,\n// once, so a caller's obvious slice is the right one.\n\nimport type { Annotations, Fragment, Highlight } from \"./types.js\";\n\n/** A fragment as it arrives: `spans` are UTF-8 byte offsets into `text`. */\ninterface WireFragment {\n text: string;\n spans: [number, number][];\n}\n\ninterface WireHighlight {\n field: string;\n fragments: WireFragment[];\n}\n\n/** A hit's annotations as they arrive, before the span offsets are converted. */\nexport interface WireAnnotations {\n vector?: { rank: number; score: number };\n text?: { rank: number; score: number };\n clauses?: {\n field: string;\n score: number;\n expansion?: { matched: number; scored: number };\n }[];\n highlights?: WireHighlight[];\n}\n\n/**\n * Decode a hit's annotations, converting every highlight span to JS string indices. The\n * parts the server omitted stay omitted rather than becoming empty arrays.\n */\nexport function decodeAnnotations(a: WireAnnotations): Annotations {\n const out: Annotations = {};\n if (a.vector) out.vector = a.vector;\n if (a.text) out.text = a.text;\n if (a.clauses) out.clauses = a.clauses;\n if (a.highlights) out.highlights = a.highlights.map(decodeHighlight);\n return out;\n}\n\nfunction decodeHighlight(h: WireHighlight): Highlight {\n return { field: h.field, fragments: h.fragments.map(decodeFragment) };\n}\n\nfunction decodeFragment(fr: WireFragment): Fragment {\n return { text: fr.text, spans: toStringIndices(fr.text, fr.spans) };\n}\n\n/**\n * Convert UTF-8 byte ranges into `text` to JS string indices (UTF-16 code units), so\n * `text.slice(...span)` yields the matched term. An all-ASCII excerpt needs no conversion\n * and is the common case, so it is detected before any table is built.\n */\nexport function toStringIndices(\n text: string,\n spans: [number, number][],\n): [number, number][] {\n if (spans.length === 0 || isAscii(text)) return spans;\n const index = byteToUnit(text);\n const at = (b: number): number =>\n index[Math.min(Math.max(b, 0), index.length - 1)]!;\n return spans.map(([start, end]): [number, number] => [at(start), at(end)]);\n}\n\n/** One entry per byte of `text` (plus its end), holding that byte's UTF-16 index. */\nfunction byteToUnit(text: string): number[] {\n const index: number[] = [];\n let unit = 0;\n // A byte *inside* a codepoint maps to that codepoint's start. Spans land on token\n // boundaries, so this only keeps a malformed offset from landing mid-surrogate.\n for (const ch of text) {\n for (let n = utf8Len(ch.codePointAt(0)!); n > 0; n--) index.push(unit);\n unit += ch.length;\n }\n index.push(unit);\n return index;\n}\n\nfunction utf8Len(codePoint: number): number {\n if (codePoint < 0x80) return 1;\n if (codePoint < 0x800) return 2;\n return codePoint < 0x10000 ? 3 : 4;\n}\n\n/** True when every code unit is ASCII, i.e. byte offsets already *are* string indices. */\nfunction isAscii(text: string): boolean {\n for (let i = 0; i < text.length; i++) {\n if (text.charCodeAt(i) > 0x7f) return false;\n }\n return true;\n}\n","//! Error type carrying the HTTP status the server reported.\n//\n// The server replies to a failed request with `{ \"error\": <message> }` and a\n// meaningful status (`src/server/mod.rs#classify`): 400 dimension mismatch,\n// 403 read-only store, 409 writer-lock conflict, 507 capacity/OOM, 500 otherwise.\n// Callers branch on `.status` to tell a client fault from a server fault.\n\n/** An error returned by a `nidus` server, or a transport failure reaching it. */\nexport class NidusError extends Error {\n /** The HTTP status code, or `0` for a transport/timeout failure (no response). */\n readonly status: number;\n\n constructor(message: string, status: number) {\n super(message);\n this.name = \"NidusError\";\n this.status = status;\n }\n\n /** A malformed request the server rejected (HTTP 400). */\n get isBadRequest(): boolean {\n return this.status === 400;\n }\n /** The store is read-only (HTTP 403). */\n get isReadOnly(): boolean {\n return this.status === 403;\n }\n /** The writer lock is held by another process (HTTP 409). */\n get isLocked(): boolean {\n return this.status === 409;\n }\n /** Out of capacity: `max_vector_bytes` exceeded or OOM (HTTP 507). */\n get isOutOfCapacity(): boolean {\n return this.status === 507;\n }\n}\n","//! Ergonomic constructors and decoders for the externally-tagged `Value` wire type.\n//\n// Callers should never hand-write `{ Str: \"x\" }`. Use `v.str(\"x\")`, `v.int(5)`,\n// etc., or just pass plain JS values into `attrs` — `encodeValue` normalizes them.\n//\n// One rule is JS's alone. The store's `Int` and `Float` are separate types compared\n// same-type only, but JS has one `number` and `1.0 === 1`, so `Number.isInteger` has to\n// decide. A whole-numbered measurement therefore lands as an `Int` in whichever records\n// it came out round, and a `Float` range filter then skips exactly those: write such a\n// field with `v.float`. Go and Python have the types JS lacks and decide from them.\n\nimport type { AttrInput, DecodedValue, Value } from \"./types.js\";\n\n/** Every tag this SDK version knows, in the order `decodeValue` tries them. */\nconst TAGS = [\"Str\", \"Int\", \"Bool\", \"List\", \"Float\", \"DateTime\"] as const;\n\n/**\n * Value constructors mirroring the `Value` variants. `v.int` requires a safe\n * integer and `v.float` a finite number — `NaN`/`Infinity` have no JSON spelling,\n * and `JSON.stringify` would quietly write `null`.\n */\nexport const v = {\n str: (s: string): Value => ({ Str: s }),\n int: (n: number): Value => {\n if (!Number.isInteger(n)) {\n throw new TypeError(`v.int expects an integer, got ${n}`);\n }\n return { Int: n };\n },\n float: (n: number): Value => {\n if (typeof n !== \"number\" || !Number.isFinite(n)) {\n throw new TypeError(`v.float expects a finite number, got ${n}`);\n }\n return { Float: n };\n },\n bool: (b: boolean): Value => ({ Bool: b }),\n list: (items: string[]): Value => ({ List: items }),\n /**\n * A UTC instant, from a `Date` or a raw epoch-millisecond count. Milliseconds is\n * the wire type, so there is no sub-millisecond precision and no timezone.\n */\n datetime: (when: Date | number): Value => {\n const ms = when instanceof Date ? when.getTime() : when;\n if (!Number.isSafeInteger(ms)) {\n throw new TypeError(\n `v.datetime expects a valid Date or epoch ms, got ${when}`,\n );\n }\n return { DateTime: ms };\n },\n /** The explicit `Null` value — set-but-empty, distinct from an absent key. */\n nil: (): Value => \"Null\",\n} as const;\n\n/** True if `x` is already a wire-tagged {@link Value}. */\nfunction isValue(x: unknown): x is Value {\n if (x === \"Null\") return true;\n if (typeof x !== \"object\" || x === null) return false;\n return TAGS.some((tag) => tag in x);\n}\n\n/**\n * Normalize a caller-supplied {@link AttrInput} into the wire {@link Value} shape.\n * Plain scalars map by type; an already-tagged `Value` passes through unchanged.\n * Throws on a non-finite number, an invalid `Date`, or a non-string list element.\n */\nexport function encodeValue(input: AttrInput): Value {\n if (isValue(input)) return input;\n if (input === null) return \"Null\";\n switch (typeof input) {\n case \"string\":\n return { Str: input };\n case \"boolean\":\n return { Bool: input };\n case \"number\":\n return Number.isInteger(input) ? v.int(input) : v.float(input);\n case \"object\":\n // Date before the array check: both are objects, only one is a list.\n if (input instanceof Date) return v.datetime(input);\n if (Array.isArray(input)) {\n if (!input.every((e) => typeof e === \"string\")) {\n throw new TypeError(\"a List attribute must contain only strings\");\n }\n return { List: input };\n }\n // falls through\n default:\n throw new TypeError(`cannot encode attribute value: ${String(input)}`);\n }\n}\n\n/** Normalize a whole `attrs` map of {@link AttrInput} into wire {@link Value}s. */\nexport function encodeAttrs(\n attrs: Record<string, AttrInput>,\n): Record<string, Value> {\n const out: Record<string, Value> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = encodeValue(val);\n }\n return out;\n}\n\n/** Decode a wire {@link Value} back to a plain JS value. */\nexport function decodeValue(value: Value): DecodedValue {\n if (value === \"Null\") return null;\n if (\"Str\" in value) return value.Str;\n if (\"Int\" in value) return value.Int;\n if (\"Bool\" in value) return value.Bool;\n if (\"List\" in value) return value.List;\n if (\"Float\" in value) return value.Float;\n // A Date, not the raw number: a number would demote every instant to an Int\n // when a decoded attrs map is written back.\n if (\"DateTime\" in value) return new Date(value.DateTime);\n // Unknown tag (forward-compat): hand it back untouched.\n return value as unknown as DecodedValue;\n}\n\n/** Decode a whole wire `attrs` map back to plain JS values. */\nexport function decodeAttrs(\n attrs: Record<string, Value>,\n): Record<string, DecodedValue> {\n const out: Record<string, DecodedValue> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = decodeValue(val);\n }\n return out;\n}\n","//! `NidusClient` — a remote client over the `nidus serve` HTTP API.\n//\n// One method per endpoint (`src/server/mod.rs`). \"Local vs remote\" is just the\n// base URL: point at a local `nidus serve` or any reachable host. Built on the\n// platform-global `fetch`, so it runs unchanged on Node 18+, Deno, Bun, Cloudflare\n// Workers, and browsers — with no runtime dependencies.\n\nimport { decodeAnnotations, type WireAnnotations } from \"./annotations.js\";\nimport { NidusError } from \"./errors.js\";\nimport type {\n AggregateOptions,\n Aggregation,\n BatchSearchOptions,\n ClusterStatus,\n DecodedRecord,\n Expand,\n Filter,\n FilterIndexField,\n FtsField,\n HighlightOptions,\n Hit,\n HybridSearchOptions,\n ListOptions,\n NidusRecord,\n PlanCandidates,\n PlanNarrowing,\n PlanTimings,\n QueryPlan,\n RankBy,\n Readiness,\n RecallOptions,\n RecordInput,\n RememberOptions,\n RememberResult,\n RerankOptions,\n Rollup,\n SearchOptions,\n SimilarSearchOptions,\n Stats,\n StoreVersions,\n Suggestions,\n SuggestOptions,\n TextSearchOptions,\n Value,\n} from \"./types.js\";\nimport { decodeAttrs, decodeValue, encodeAttrs } from \"./values.js\";\n\n/** Minimal `fetch` signature the client needs — satisfied by the platform global. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Construction options for {@link NidusClient}. */\nexport interface NidusClientOptions {\n /** Base URL of the server, e.g. `http://127.0.0.1:7700`. Trailing slash optional. */\n baseUrl: string;\n /** Bearer token, when the server was started with `--token`. */\n token?: string;\n /** Override the `fetch` implementation (defaults to `globalThis.fetch`). */\n fetch?: FetchLike;\n /** Per-request timeout in milliseconds. Omit (or `0`) to disable. */\n timeoutMs?: number;\n /** Extra headers sent on every request. */\n headers?: Record<string, string>;\n}\n\nexport class NidusClient {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly doFetch: FetchLike;\n private readonly timeoutMs: number;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: NidusClientOptions) {\n if (!options.baseUrl) {\n throw new TypeError(\"NidusClient requires a baseUrl\");\n }\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.token = options.token;\n this.timeoutMs = options.timeoutMs ?? 0;\n this.extraHeaders = options.headers ?? {};\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\n \"no fetch available; pass options.fetch (Node < 18, or a custom runtime)\",\n );\n }\n // Bind so a passed `globalThis.fetch` keeps its `this`.\n this.doFetch = f === globalThis.fetch ? f.bind(globalThis) : f;\n }\n\n // ── Admin / introspection ─────────────────────────────────────────────────\n\n /** Liveness check. Returns `true` when the server answers `/health`. */\n async health(): Promise<boolean> {\n try {\n const res = await this.raw(\"GET\", \"/health\");\n return res.ok;\n } catch {\n return false;\n }\n }\n\n /** Store-wide introspection: dimension, distance, ANN config, collections, footprint. */\n stats(): Promise<Stats> {\n return this.request<Stats>(\"GET\", \"/stats\");\n }\n\n /**\n * Readiness: whether this instance can serve. A `503` is the negative answer, not an\n * error, so a poll loop branches on `ready` instead of catching. Other failures throw.\n */\n async ready(): Promise<Readiness> {\n const res = await this.raw(\"GET\", \"/ready\");\n const text = await res.text();\n if (res.status === 503) return { ready: false, reason: extractError(text, 503) };\n if (!res.ok) throw new NidusError(extractError(text, res.status), res.status);\n return JSON.parse(text) as Readiness;\n }\n\n /** Cluster role, writer-handle state, fencing token, commit counter, staleness. */\n cluster(): Promise<ClusterStatus> {\n return this.request<ClusterStatus>(\"GET\", \"/cluster\");\n }\n\n /** The readable commit points and this instance's pin, if any. */\n versions(): Promise<StoreVersions> {\n return this.request<StoreVersions>(\"GET\", \"/versions\");\n }\n\n /** List every collection name. */\n collections(): Promise<string[]> {\n return this.request<string[]>(\"GET\", \"/collections\");\n }\n\n /** Create a collection. Idempotent on the server side. */\n async createCollection(name: string): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}`, {});\n }\n\n /** Drop a collection and all its records. */\n async dropCollection(name: string): Promise<void> {\n await this.request(\"DELETE\", `/collections/${enc(name)}`);\n }\n\n /** Every alias and the concrete collection it resolves to. */\n aliases(): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\"GET\", \"/aliases\");\n }\n\n /** Create or repoint an alias. The target must already exist; aliases never chain. */\n async setAlias(name: string, target: string): Promise<void> {\n await this.request(\"PUT\", `/aliases/${enc(name)}`, { target });\n }\n\n /** Remove an alias. Deletes no records. */\n async dropAlias(name: string): Promise<void> {\n await this.request(\"DELETE\", `/aliases/${enc(name)}`);\n }\n\n /** Read a collection's free-form string metadata. */\n getMeta(name: string): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\n \"GET\",\n `/collections/${enc(name)}/meta`,\n );\n }\n\n /** Replace a collection's free-form string metadata. */\n async setMeta(name: string, meta: Record<string, string>): Promise<void> {\n await this.request(\"PUT\", `/collections/${enc(name)}/meta`, meta);\n }\n\n // ── Data ──────────────────────────────────────────────────────────────────\n\n /**\n * Insert or replace records (idempotent on `id` within the collection).\n * `attrs` accept plain JS values or `v.*` helpers; they are normalized for you.\n * Returns the number of records upserted.\n */\n async upsert(name: string, records: RecordInput[]): Promise<number> {\n const wire: NidusRecord[] = records.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: encodeAttrs(r.attrs),\n }));\n const res = await this.request<{ upserted: number }>(\n \"POST\",\n `/collections/${enc(name)}/upsert`,\n { records: wire },\n );\n return res.upserted;\n }\n\n /** Delete records by id. Returns the number deleted. */\n async delete(name: string, opts: { ids: string[] }): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { ids: opts.ids },\n );\n return res.deleted;\n }\n\n /** Delete every record matching `filter`. Returns the number deleted. */\n async deleteWhere(name: string, filter: Filter): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { filter },\n );\n return res.deleted;\n }\n\n /** Fetch every record in a collection (attrs decoded to plain JS values). */\n async records(name: string): Promise<DecodedRecord[]> {\n const recs = await this.request<NidusRecord[]>(\n \"GET\",\n `/collections/${enc(name)}/records`,\n );\n return recs.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: decodeAttrs(r.attrs),\n }));\n }\n\n /**\n * Declare the full-text-indexed attribute fields for a collection. A bare string\n * takes the server's BM25/analyzer defaults; an {@link FtsField} object tunes `k1`,\n * `b`, and the analyzer for that field alone.\n */\n async setFtsSchema(\n name: string,\n fields: (string | FtsField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/fts-schema`, {\n fields: fields.map(encodeFtsField),\n });\n }\n\n /**\n * Declare which attribute fields are indexed for the text predicates (`Fuzzy`,\n * `ContainsAllTokens`, `ContainsAnyToken`, `ContainsTokenSequence`, `Regex`). Fields\n * already written are indexed as part of applying the declaration.\n *\n * This changes how fast those predicates run, never what they return: the index\n * proposes candidate documents and the predicate itself still decides. The cost is\n * paid at write time and in memory. Pass an empty array to drop the declaration.\n */\n async setFilterIndex(\n name: string,\n fields: (string | FilterIndexField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/filter-index`, {\n fields: fields.map(encodeFilterIndexField),\n });\n }\n\n // ── Search ──────────────────────────────────────────────────────────────\n\n /** Vector (cosine) nearest-neighbour search. Empty `scope` searches all collections. */\n search(opts: SearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.search}, but also reports the scan strategy the server took. */\n searchWithPlan(\n opts: SearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Records most like an existing one. The source record itself is never returned. */\n searchSimilar(opts: SimilarSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /** Like {@link NidusClient.searchSimilar}, but also reports the scan strategy taken. */\n searchSimilarWithPlan(\n opts: SimilarSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /**\n * BM25 full-text search over one indexed field, or over a `clauses` list folded by\n * `combine` (`\"Sum\"` unless said otherwise). Naming the fields both ways is a `400`.\n */\n textSearch(opts: TextSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/text-search\", {\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, query: opts.query, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /**\n * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by\n * document frequency (commonest first), which is the opposite of how a prefix clause\n * ranks documents. Completions are stems: the prefix is folded, not stemmed.\n */\n suggest(opts: SuggestOptions): Promise<Suggestions> {\n return this.request<Suggestions>(\n \"POST\",\n `/collections/${enc(opts.collection)}/suggest`,\n prune({ field: opts.field, prefix: opts.prefix, limit: opts.limit }),\n );\n }\n\n /**\n * Hybrid search: fuse a vector query and a BM25 text query via RRF. The text leg takes\n * the same single-field / `clauses` choice as {@link NidusClient.textSearch}.\n */\n hybridSearch(opts: HybridSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.hybridSearch}, but also reports the scan strategy taken. */\n hybridSearchWithPlan(\n opts: HybridSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Metadata-only listing (no vector), paginated by `offset`/`limit`. */\n list(opts: ListOptions = {}): Promise<Hit[]> {\n return this.searchRequest(\"/list\", {\n scope: opts.scope ?? [],\n offset: opts.offset,\n limit: opts.limit,\n filter: opts.filter ?? [],\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n order_by: opts.orderBy,\n });\n }\n\n /**\n * Count the records matching a filter and sum the named attributes. Answered from the\n * in-RAM index alone — no record is built and no vector is read.\n */\n async aggregate(opts: AggregateOptions = {}): Promise<Aggregation> {\n const res = await this.request<RawAggregation>(\n \"POST\",\n \"/aggregate\",\n prune({\n scope: opts.scope ?? [],\n filter: opts.filter ?? [],\n sum: opts.sum ?? [],\n group_by: opts.groupBy,\n }),\n );\n // Every sum is an `Int` or a `Float`, both of which decode to a JS number.\n return {\n count: res.count,\n sums: decodeAttrs(res.sums) as Record<string, number>,\n // Kept absent, not `undefined`, so an ungrouped answer is the shape it always was.\n ...(res.groups\n ? {\n groups: res.groups.map((g) => ({\n value: g.value === null ? null : decodeValue(g.value),\n count: g.count,\n sums: decodeAttrs(g.sums) as Record<string, number>,\n })),\n }\n : {}),\n ...(res.groups_truncated ? { groupsTruncated: true } : {}),\n };\n }\n\n /**\n * Answer several vector queries in one round-trip (16 max). Returns one ranking per\n * query in request order, or — with `opts.fuse` — a single array holding the one fused\n * ranking, so the return shape is uniform either way.\n *\n * The server validates the whole batch before running any leg, so a malformed query\n * fails the call rather than returning a partial answer that cannot be told apart.\n */\n async batchSearch(opts: BatchSearchOptions): Promise<Hit[][]> {\n const body = prune({\n queries: opts.queries.map((q) => ({\n query: q.query,\n scope: q.scope ?? [],\n top_k: q.topK,\n offset: q.offset,\n min_score: q.minScore,\n filter: q.filter ?? [],\n exact: q.exact,\n include_attributes: q.includeAttributes,\n exclude_attributes: q.excludeAttributes,\n rank_by: encodeRankBy(q.rankBy),\n limit_per: q.limitPer,\n diversity: q.diversity,\n expand: encodeExpand(q.expand),\n })),\n fuse: opts.fuse\n ? prune({\n rrf_k: opts.fuse.rrfK,\n weights: opts.fuse.weights,\n top_k: opts.fuse.topK,\n })\n : undefined,\n });\n const res = await this.request<RawBatchSearch>(\n \"POST\",\n \"/search/batch\",\n body,\n );\n return (res.fused ? [res.fused] : (res.results ?? [])).map((hits) =>\n hits.map((h) => this.decodeHit(h)),\n );\n }\n\n // ── Memory (text-native) ──────────────────────────────────────────────────\n //\n // Available only when `nidus serve` was started with an embedder\n // (`--embed-provider …`); otherwise these answer `400`. The server embeds the\n // text/query — the client only sends strings.\n\n /**\n * Embed `text` and upsert it under `id` in `collection` (idempotent on `id`).\n * With `opts.mode === \"summarize\"` the server summarizes first, embeds the\n * summary, and stamps a `nidus.summary` attr (requires the server to have a\n * summarizer). The raw text is always stored under `nidus.text`. `opts.attrs` accept plain JS values or `v.*`\n * helpers; they are normalized for you.\n *\n * Read `id` off the result rather than assuming the one you passed:\n * `opts.dedupeThreshold` can redirect the write onto a near-duplicate.\n */\n async remember(\n collection: string,\n id: string,\n text: string,\n opts: RememberOptions = {},\n ): Promise<RememberResult> {\n const res = await this.request<Partial<RememberResult> | undefined>(\n \"POST\",\n `/collections/${enc(collection)}/remember`,\n prune({\n id,\n text,\n mode: opts.mode,\n attrs: opts.attrs ? encodeAttrs(opts.attrs) : undefined,\n ttl_seconds: opts.ttlSeconds,\n dedupe_threshold: opts.dedupeThreshold,\n }),\n );\n // A server predating the echoed fields answers `{ok, upserted}`; falling back to the\n // requested id keeps that case honest instead of reporting `undefined` as the target.\n return {\n id: res?.id ?? id,\n upserted: res?.upserted ?? 0,\n deduped: res?.deduped ?? false,\n };\n }\n\n /**\n * Embed `query` and vector-search `collection`, best-first (attrs decoded to\n * plain JS values). Refused with a cross-model guard if the collection was\n * written with a different embedder than the server's.\n */\n recall(\n collection: string,\n query: string,\n opts: RecallOptions = {},\n ): Promise<Hit[]> {\n return this.searchRequest(`/collections/${enc(collection)}/recall`, {\n query,\n top_k: opts.topK,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n diversity: opts.diversity,\n rollup: encodeRollup(opts.rollup),\n rerank: encodeRerank(opts.rerank),\n reinforce: opts.reinforce,\n extend_ttl_seconds: opts.extendTtlSeconds,\n rank_by: encodeRankBy(opts.rankBy),\n });\n }\n\n // ── Maintenance ───────────────────────────────────────────────────────────\n\n /** Force a durability flush. */\n async flush(): Promise<void> {\n await this.request(\"POST\", \"/flush\", {});\n }\n\n /** Compact the store (reclaim space from deleted/overwritten rows). */\n async compact(): Promise<void> {\n await this.request(\"POST\", \"/compact\", {});\n }\n\n /** Adopt a writer's newer committed state. Returns whether anything was adopted. */\n async refresh(): Promise<boolean> {\n const res = await this.request<{ adopted: boolean }>(\"POST\", \"/refresh\", {});\n return res.adopted;\n }\n\n // ── Internals ─────────────────────────────────────────────────────────────\n\n /** Run a search-family request and decode the resulting hits' attrs. */\n private async searchRequest(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Hit[]> {\n const hits = await this.request<RawHit[]>(\"POST\", path, prune(body));\n return hits.map((h) => this.decodeHit(h));\n }\n\n /** Like {@link NidusClient.searchRequest}, asking for `plan: true` and decoding it too. */\n private async searchRequestWithPlan(\n path: string,\n body: Record<string, unknown>,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n const res = await this.request<{ hits: RawHit[]; plan: RawQueryPlan }>(\n \"POST\",\n path,\n prune({ ...body, plan: true }),\n );\n return {\n hits: res.hits.map((h) => this.decodeHit(h)),\n plan: decodeQueryPlan(res.plan),\n };\n }\n\n /** One wire hit into a {@link Hit}. Shared so every search surface decodes identically. */\n private decodeHit(h: RawHit): Hit {\n return {\n collection: h.collection,\n id: h.id,\n score: h.score,\n attrs: decodeAttrs(h.attrs),\n // Kept absent, not `undefined`, so an unannotated hit is the shape it always was.\n ...(h.annotations\n ? { annotations: decodeAnnotations(h.annotations) }\n : {}),\n ...(h.context !== undefined ? { context: h.context } : {}),\n };\n }\n\n /** Issue a request and parse a JSON body, mapping a non-2xx to {@link NidusError}. */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const res = await this.raw(method, path, body);\n const text = await res.text();\n if (!res.ok) {\n throw new NidusError(extractError(text, res.status), res.status);\n }\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** The bare transport: headers, auth, timeout, and transport-error mapping. */\n private async raw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const headers: Record<string, string> = { ...this.extraHeaders };\n if (this.token) headers.authorization = `Bearer ${this.token}`;\n let payload: string | undefined;\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n payload = JSON.stringify(body);\n }\n\n const controller = this.timeoutMs > 0 ? new AbortController() : undefined;\n const timer =\n controller && this.timeoutMs > 0\n ? setTimeout(() => controller.abort(), this.timeoutMs)\n : undefined;\n try {\n return await this.doFetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: payload,\n signal: controller?.signal,\n });\n } catch (err) {\n const reason =\n (controller?.signal.aborted ?? false)\n ? `request to ${path} timed out after ${this.timeoutMs}ms`\n : `request to ${path} failed: ${(err as Error).message}`;\n throw new NidusError(reason, 0);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\n/** A hit as it arrives on the wire, before attrs are decoded. */\ninterface RawHit {\n collection: string;\n id: string;\n score: number;\n attrs: Record<string, Value>;\n annotations?: WireAnnotations;\n context?: string;\n}\n\n/** A `QueryPlan` as it arrives on the wire (snake_case), before camelCasing. */\ninterface RawQueryPlan {\n path: string;\n rows_scanned?: number;\n candidates?: {\n surfaced: number;\n survived: number;\n dropped_out_of_scope: number;\n dropped_stale: number;\n dropped_filtered: number;\n dropped_min_score: number;\n };\n narrowing: { state: PlanNarrowing[\"state\"]; candidates?: number };\n timings: {\n narrow_us?: number;\n gather_us?: number;\n walk_us?: number;\n resolve_us?: number;\n first_pass_us?: number;\n rescore_us?: number;\n score_us?: number;\n total_us: number;\n };\n}\n\n/** Wire `QueryPlan` into its camelCase {@link QueryPlan} shape. */\nfunction decodeQueryPlan(p: RawQueryPlan): QueryPlan {\n const candidates: PlanCandidates | undefined = p.candidates\n ? {\n surfaced: p.candidates.surfaced,\n survived: p.candidates.survived,\n droppedOutOfScope: p.candidates.dropped_out_of_scope,\n droppedStale: p.candidates.dropped_stale,\n droppedFiltered: p.candidates.dropped_filtered,\n droppedMinScore: p.candidates.dropped_min_score,\n }\n : undefined;\n const t = p.timings;\n const timings: PlanTimings = {\n ...(t.narrow_us !== undefined ? { narrowUs: t.narrow_us } : {}),\n ...(t.gather_us !== undefined ? { gatherUs: t.gather_us } : {}),\n ...(t.walk_us !== undefined ? { walkUs: t.walk_us } : {}),\n ...(t.resolve_us !== undefined ? { resolveUs: t.resolve_us } : {}),\n ...(t.first_pass_us !== undefined ? { firstPassUs: t.first_pass_us } : {}),\n ...(t.rescore_us !== undefined ? { rescoreUs: t.rescore_us } : {}),\n ...(t.score_us !== undefined ? { scoreUs: t.score_us } : {}),\n totalUs: t.total_us,\n };\n return {\n path: p.path,\n ...(p.rows_scanned !== undefined ? { rowsScanned: p.rows_scanned } : {}),\n ...(candidates ? { candidates } : {}),\n narrowing: {\n state: p.narrowing.state,\n ...(p.narrowing.candidates !== undefined\n ? { candidates: p.narrowing.candidates }\n : {}),\n },\n timings,\n };\n}\n\n/** An `/aggregate` response, whose sums arrive as tagged {@link Value}s. */\ninterface RawAggregation {\n count: number;\n sums: Record<string, Value>;\n groups?: {\n value: Value | null;\n count: number;\n sums: Record<string, Value>;\n }[];\n groups_truncated?: boolean;\n}\n\n/** A `/search/batch` response: exactly one of the two fields is present. */\ninterface RawBatchSearch {\n results?: RawHit[][];\n fused?: RawHit[];\n}\n\n/** Encode `rankBy` to its externally-tagged wire form, dropping the knobs left unset. */\n/** camelCase → the wire's snake_case, omitting the object entirely when unset. */\nfunction encodeExpand(e: Expand | undefined): unknown {\n if (!e) return undefined;\n return prune({\n radius: e.radius,\n parent_field: e.parentField,\n index_field: e.indexField,\n text_field: e.textField,\n });\n}\n\nfunction encodeRollup(r: Rollup | undefined): unknown {\n if (!r) return undefined;\n return prune({ per_parent: r.perParent, neighbours: r.neighbours });\n}\n\nfunction encodeRankBy(rank: RankBy | undefined): unknown {\n if (!rank) return undefined;\n const d = rank.decay;\n return {\n Decay: prune({\n field: d.field,\n origin: d.origin instanceof Date ? d.origin.getTime() : d.origin,\n scale: d.scale,\n decay: d.decay,\n lambda: d.lambda,\n missing: d.missing,\n count_field: d.countField,\n count_scale: d.countScale,\n count_lambda: d.countLambda,\n }),\n };\n}\n\n/** Encode `highlight`: `true` is the empty object the server reads as \"all defaults\". */\nfunction encodeHighlight(h: boolean | HighlightOptions | undefined): unknown {\n if (h === undefined || h === false) return undefined;\n if (h === true) return {};\n return prune({\n max_fragments: h.maxFragments,\n fragment_chars: h.fragmentChars,\n });\n}\n\n/** Encode `rerank`. Undefined sub-fields drop out at `JSON.stringify`, not here. */\nfunction encodeRerank(r: RerankOptions | undefined): unknown {\n if (r === undefined) return undefined;\n return { query: r.query, overscan: r.overscan, text_attr: r.textAttr };\n}\n\n/** Path-segment encode a collection name (allows slashes/spaces in names). */\nfunction enc(name: string): string {\n return encodeURIComponent(name);\n}\n\n/**\n * Encode one `setFtsSchema` field. A string passes through as the server's bare-name\n * form; an object becomes the snake_case body, pruned so an unset knob keeps the\n * server's default rather than being sent as `undefined`.\n */\nfunction encodeFtsField(f: string | FtsField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n k1: f.k1,\n b: f.b,\n language: f.language,\n ascii_folding: f.asciiFolding,\n max_token_len: f.maxTokenLen,\n });\n}\n\n/**\n * Encode one `setFilterIndex` field, on the same bare-name-or-object rule as\n * {@link encodeFtsField}. Pruning matters here: the server defaults both structures to\n * `true`, so sending an explicit `undefined` would be indistinguishable from `false`.\n */\nfunction encodeFilterIndexField(f: string | FilterIndexField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n tokens: f.tokens,\n trigrams: f.trigrams,\n });\n}\n\n/** Drop `undefined` fields so server `#[serde(default)]`s apply instead. */\nfunction prune(body: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(body)) {\n if (val !== undefined) out[k] = val;\n }\n return out;\n}\n\n/** Pull the `{ \"error\": … }` message out of a failed response, or fall back. */\nfunction extractError(text: string, status: number): string {\n try {\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed.error === \"string\") return parsed.error;\n } catch {\n // not JSON — fall through\n }\n return text || `HTTP ${status}`;\n}\n","//! Filter builder producing the bare predicate-array wire shape.\n//\n// A `Filter` is AND-combined predicates; on the wire it is a plain array. Each\n// predicate is a *positive assertion about a present attribute* — an absent key\n// matches nothing, including the negative predicates (`ne`/`notIn`) and ranges.\n// Comparisons are same-type only (Int↔Int numeric, Float↔Float by IEEE, Str↔Str\n// lexical, Bool↔Bool, DateTime↔DateTime as instants), so an operand's encoded type\n// has to match the attribute's: `ge(\"score\", v.float(2))`, not `ge(\"score\", 2)`.\n\nimport type { AttrInput, Filter, Predicate, Value } from \"./types.js\";\nimport { encodeValue } from \"./values.js\";\n\n/**\n * Predicate constructors. Each accepts a plain JS value (auto-normalized) or an\n * explicit `v.*` {@link Value}. Combine results into a {@link Filter} array, or\n * use {@link f.and} for readability.\n */\nexport const f = {\n /** `attrs[key] === value`. */\n eq: (key: string, value: AttrInput): Predicate => ({\n Eq: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is present and `!== value`. */\n ne: (key: string, value: AttrInput): Predicate => ({\n Ne: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `Str` matching the glob pattern (`*`, `?`, `[..]`). */\n glob: (key: string, pattern: string): Predicate => ({ Glob: [key, pattern] }),\n /**\n * {@link f.glob}, ignoring **ASCII** case on both sides — `\"Src/*\"` matches\n * `\"src/main.rs\"`. Non-ASCII is not folded (`É` does not match `é`).\n */\n iglob: (key: string, pattern: string): Predicate => ({\n IGlob: [key, pattern],\n }),\n /** `attrs[key]` equals one of `values`. */\n in: (key: string, values: AttrInput[]): Predicate => ({\n In: [key, values.map(encodeValue)],\n }),\n /** `attrs[key]` is present and equals none of `values`. */\n notIn: (key: string, values: AttrInput[]): Predicate => ({\n NotIn: [key, values.map(encodeValue)],\n }),\n /** `attrs[key] < value` (same-type, orderable). */\n lt: (key: string, value: AttrInput): Predicate => ({\n Lt: [key, encodeValue(value)],\n }),\n /** `attrs[key] <= value` (same-type, orderable). */\n le: (key: string, value: AttrInput): Predicate => ({\n Le: [key, encodeValue(value)],\n }),\n /** `attrs[key] > value` (same-type, orderable). */\n gt: (key: string, value: AttrInput): Predicate => ({\n Gt: [key, encodeValue(value)],\n }),\n /** `attrs[key] >= value` (same-type, orderable). */\n ge: (key: string, value: AttrInput): Predicate => ({\n Ge: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` containing `value` (whole-element, not substring). */\n contains: (key: string, value: AttrInput): Predicate => ({\n Contains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a present `List` not containing `value`. */\n notContains: (key: string, value: AttrInput): Predicate => ({\n NotContains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` sharing at least one element with `values`. */\n containsAny: (key: string, values: AttrInput[]): Predicate => ({\n ContainsAny: [key, values.map(encodeValue)],\n }),\n /** Every sub-predicate holds. `all()` is `true`. */\n all: (...preds: Predicate[]): Predicate => ({ All: preds }),\n /** At least one sub-predicate holds. `any()` is `false`. */\n any: (...preds: Predicate[]): Predicate => ({ Any: preds }),\n /**\n * The sub-predicate does not hold. Differs from {@link f.ne} on an absent key:\n * `not(eq(k, v))` matches a record with no `k`, `ne(k, v)` does not.\n */\n not: (pred: Predicate): Predicate => ({ Not: pred }),\n /**\n * `attrs[key]` is within `maxEdits` Levenshtein edits of `text`, ASCII-case-folded on\n * both sides; a `List` matches if any element does. The only three-element predicate.\n * A `maxEdits` above 8 is refused by the server, not clamped.\n */\n fuzzy: (key: string, text: string, maxEdits: number): Predicate => ({\n Fuzzy: [key, text, maxEdits],\n }),\n /**\n * Every token of `text` appears among `attrs[key]`'s tokens, in any order. Tokens are\n * ASCII-case-folded runs of alphanumerics; a `List` matches if any single element does.\n */\n containsAllTokens: (key: string, text: string): Predicate => ({\n ContainsAllTokens: [key, text],\n }),\n /** At least one token of `text` appears among `attrs[key]`'s tokens. Empty never matches. */\n containsAnyToken: (key: string, text: string): Predicate => ({\n ContainsAnyToken: [key, text],\n }),\n /** `text`'s tokens appear consecutively and in order — a phrase match. */\n containsTokenSequence: (key: string, text: string): Predicate => ({\n ContainsTokenSequence: [key, text],\n }),\n /**\n * `attrs[key]` matches the regular expression, **anchored at both ends** like\n * {@link f.glob} — `.*` opts back into a substring search, and `(?i)` into case folding.\n * The syntax is Rust's `regex`, not JS's: no backreferences and no lookaround.\n */\n regex: (key: string, pattern: string): Predicate => ({ Regex: [key, pattern] }),\n /** Collect predicates into a {@link Filter} (purely sugar — they already AND). */\n and: (...preds: Predicate[]): Filter => preds,\n} as const;\n\n// Aliases for the comparison operators, for callers who prefer them.\nexport type { Filter, Predicate, Value };\n"],"mappings":";AAoCO,SAAS,kBAAkB,GAAiC;AACjE,QAAM,MAAmB,CAAC;AAC1B,MAAI,EAAE,OAAQ,KAAI,SAAS,EAAE;AAC7B,MAAI,EAAE,KAAM,KAAI,OAAO,EAAE;AACzB,MAAI,EAAE,QAAS,KAAI,UAAU,EAAE;AAC/B,MAAI,EAAE,WAAY,KAAI,aAAa,EAAE,WAAW,IAAI,eAAe;AACnE,SAAO;AACT;AAEA,SAAS,gBAAgB,GAA6B;AACpD,SAAO,EAAE,OAAO,EAAE,OAAO,WAAW,EAAE,UAAU,IAAI,cAAc,EAAE;AACtE;AAEA,SAAS,eAAe,IAA4B;AAClD,SAAO,EAAE,MAAM,GAAG,MAAM,OAAO,gBAAgB,GAAG,MAAM,GAAG,KAAK,EAAE;AACpE;AAOO,SAAS,gBACd,MACA,OACoB;AACpB,MAAI,MAAM,WAAW,KAAK,QAAQ,IAAI,EAAG,QAAO;AAChD,QAAM,QAAQ,WAAW,IAAI;AAC7B,QAAM,KAAK,CAAC,MACV,MAAM,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC;AAClD,SAAO,MAAM,IAAI,CAAC,CAAC,OAAO,GAAG,MAAwB,CAAC,GAAG,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC;AAC3E;AAGA,SAAS,WAAW,MAAwB;AAC1C,QAAM,QAAkB,CAAC;AACzB,MAAI,OAAO;AAGX,aAAW,MAAM,MAAM;AACrB,aAAS,IAAI,QAAQ,GAAG,YAAY,CAAC,CAAE,GAAG,IAAI,GAAG,IAAK,OAAM,KAAK,IAAI;AACrE,YAAQ,GAAG;AAAA,EACb;AACA,QAAM,KAAK,IAAI;AACf,SAAO;AACT;AAEA,SAAS,QAAQ,WAA2B;AAC1C,MAAI,YAAY,IAAM,QAAO;AAC7B,MAAI,YAAY,KAAO,QAAO;AAC9B,SAAO,YAAY,QAAU,IAAI;AACnC;AAGA,SAAS,QAAQ,MAAuB;AACtC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,WAAW,CAAC,IAAI,IAAM,QAAO;AAAA,EACxC;AACA,SAAO;AACT;;;ACvFO,IAAM,aAAN,cAAyB,MAAM;AAAA;AAAA,EAE3B;AAAA,EAET,YAAY,SAAiB,QAAgB;AAC3C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGA,IAAI,eAAwB;AAC1B,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA,EAEA,IAAI,kBAA2B;AAC7B,WAAO,KAAK,WAAW;AAAA,EACzB;AACF;;;ACpBA,IAAM,OAAO,CAAC,OAAO,OAAO,QAAQ,QAAQ,SAAS,UAAU;AAOxD,IAAM,IAAI;AAAA,EACf,KAAK,CAAC,OAAsB,EAAE,KAAK,EAAE;AAAA,EACrC,KAAK,CAAC,MAAqB;AACzB,QAAI,CAAC,OAAO,UAAU,CAAC,GAAG;AACxB,YAAM,IAAI,UAAU,iCAAiC,CAAC,EAAE;AAAA,IAC1D;AACA,WAAO,EAAE,KAAK,EAAE;AAAA,EAClB;AAAA,EACA,OAAO,CAAC,MAAqB;AAC3B,QAAI,OAAO,MAAM,YAAY,CAAC,OAAO,SAAS,CAAC,GAAG;AAChD,YAAM,IAAI,UAAU,wCAAwC,CAAC,EAAE;AAAA,IACjE;AACA,WAAO,EAAE,OAAO,EAAE;AAAA,EACpB;AAAA,EACA,MAAM,CAAC,OAAuB,EAAE,MAAM,EAAE;AAAA,EACxC,MAAM,CAAC,WAA4B,EAAE,MAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,EAKjD,UAAU,CAAC,SAA+B;AACxC,UAAM,KAAK,gBAAgB,OAAO,KAAK,QAAQ,IAAI;AACnD,QAAI,CAAC,OAAO,cAAc,EAAE,GAAG;AAC7B,YAAM,IAAI;AAAA,QACR,oDAAoD,IAAI;AAAA,MAC1D;AAAA,IACF;AACA,WAAO,EAAE,UAAU,GAAG;AAAA,EACxB;AAAA;AAAA,EAEA,KAAK,MAAa;AACpB;AAGA,SAAS,QAAQ,GAAwB;AACvC,MAAI,MAAM,OAAQ,QAAO;AACzB,MAAI,OAAO,MAAM,YAAY,MAAM,KAAM,QAAO;AAChD,SAAO,KAAK,KAAK,CAAC,QAAQ,OAAO,CAAC;AACpC;AAOO,SAAS,YAAY,OAAyB;AACnD,MAAI,QAAQ,KAAK,EAAG,QAAO;AAC3B,MAAI,UAAU,KAAM,QAAO;AAC3B,UAAQ,OAAO,OAAO;AAAA,IACpB,KAAK;AACH,aAAO,EAAE,KAAK,MAAM;AAAA,IACtB,KAAK;AACH,aAAO,EAAE,MAAM,MAAM;AAAA,IACvB,KAAK;AACH,aAAO,OAAO,UAAU,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,MAAM,KAAK;AAAA,IAC/D,KAAK;AAEH,UAAI,iBAAiB,KAAM,QAAO,EAAE,SAAS,KAAK;AAClD,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAI,CAAC,MAAM,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG;AAC9C,gBAAM,IAAI,UAAU,4CAA4C;AAAA,QAClE;AACA,eAAO,EAAE,MAAM,MAAM;AAAA,MACvB;AAAA;AAAA,IAEF;AACE,YAAM,IAAI,UAAU,kCAAkC,OAAO,KAAK,CAAC,EAAE;AAAA,EACzE;AACF;AAGO,SAAS,YACd,OACuB;AACvB,QAAM,MAA6B,CAAC;AACpC,aAAW,CAAC,GAAG,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC5C,QAAI,CAAC,IAAI,YAAY,GAAG;AAAA,EAC1B;AACA,SAAO;AACT;AAGO,SAAS,YAAY,OAA4B;AACtD,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,SAAS,MAAO,QAAO,MAAM;AACjC,MAAI,SAAS,MAAO,QAAO,MAAM;AACjC,MAAI,UAAU,MAAO,QAAO,MAAM;AAClC,MAAI,UAAU,MAAO,QAAO,MAAM;AAClC,MAAI,WAAW,MAAO,QAAO,MAAM;AAGnC,MAAI,cAAc,MAAO,QAAO,IAAI,KAAK,MAAM,QAAQ;AAEvD,SAAO;AACT;AAGO,SAAS,YACd,OAC8B;AAC9B,QAAM,MAAoC,CAAC;AAC3C,aAAW,CAAC,GAAG,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC5C,QAAI,CAAC,IAAI,YAAY,GAAG;AAAA,EAC1B;AACA,SAAO;AACT;;;AC3DO,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA6B;AACvC,QAAI,CAAC,QAAQ,SAAS;AACpB,YAAM,IAAI,UAAU,gCAAgC;AAAA,IACtD;AACA,SAAK,UAAU,QAAQ,QAAQ,QAAQ,QAAQ,EAAE;AACjD,SAAK,QAAQ,QAAQ;AACrB,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,eAAe,QAAQ,WAAW,CAAC;AACxC,UAAMA,KAAI,QAAQ,SAAS,WAAW;AACtC,QAAI,OAAOA,OAAM,YAAY;AAC3B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,SAAK,UAAUA,OAAM,WAAW,QAAQA,GAAE,KAAK,UAAU,IAAIA;AAAA,EAC/D;AAAA;AAAA;AAAA,EAKA,MAAM,SAA2B;AAC/B,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,IAAI,OAAO,SAAS;AAC3C,aAAO,IAAI;AAAA,IACb,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,QAAwB;AACtB,WAAO,KAAK,QAAe,OAAO,QAAQ;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAA4B;AAChC,UAAM,MAAM,MAAM,KAAK,IAAI,OAAO,QAAQ;AAC1C,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,IAAI,WAAW,IAAK,QAAO,EAAE,OAAO,OAAO,QAAQ,aAAa,MAAM,GAAG,EAAE;AAC/E,QAAI,CAAC,IAAI,GAAI,OAAM,IAAI,WAAW,aAAa,MAAM,IAAI,MAAM,GAAG,IAAI,MAAM;AAC5E,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AAAA;AAAA,EAGA,UAAkC;AAChC,WAAO,KAAK,QAAuB,OAAO,UAAU;AAAA,EACtD;AAAA;AAAA,EAGA,WAAmC;AACjC,WAAO,KAAK,QAAuB,OAAO,WAAW;AAAA,EACvD;AAAA;AAAA,EAGA,cAAiC;AAC/B,WAAO,KAAK,QAAkB,OAAO,cAAc;AAAA,EACrD;AAAA;AAAA,EAGA,MAAM,iBAAiB,MAA6B;AAClD,UAAM,KAAK,QAAQ,QAAQ,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,EAC5D;AAAA;AAAA,EAGA,MAAM,eAAe,MAA6B;AAChD,UAAM,KAAK,QAAQ,UAAU,gBAAgB,IAAI,IAAI,CAAC,EAAE;AAAA,EAC1D;AAAA;AAAA,EAGA,UAA2C;AACzC,WAAO,KAAK,QAAgC,OAAO,UAAU;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,SAAS,MAAc,QAA+B;AAC1D,UAAM,KAAK,QAAQ,OAAO,YAAY,IAAI,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,UAAU,MAA6B;AAC3C,UAAM,KAAK,QAAQ,UAAU,YAAY,IAAI,IAAI,CAAC,EAAE;AAAA,EACtD;AAAA;AAAA,EAGA,QAAQ,MAA+C;AACrD,WAAO,KAAK;AAAA,MACV;AAAA,MACA,gBAAgB,IAAI,IAAI,CAAC;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,QAAQ,MAAc,MAA6C;AACvE,UAAM,KAAK,QAAQ,OAAO,gBAAgB,IAAI,IAAI,CAAC,SAAS,IAAI;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAO,MAAc,SAAyC;AAClE,UAAM,OAAsB,QAAQ,IAAI,CAAC,OAAO;AAAA,MAC9C,IAAI,EAAE;AAAA,MACN,GAAI,EAAE,WAAW,SAAY,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,MACrD,OAAO,YAAY,EAAE,KAAK;AAAA,IAC5B,EAAE;AACF,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA,gBAAgB,IAAI,IAAI,CAAC;AAAA,MACzB,EAAE,SAAS,KAAK;AAAA,IAClB;AACA,WAAO,IAAI;AAAA,EACb;AAAA;AAAA,EAGA,MAAM,OAAO,MAAc,MAA0C;AACnE,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA,gBAAgB,IAAI,IAAI,CAAC;AAAA,MACzB,EAAE,KAAK,KAAK,IAAI;AAAA,IAClB;AACA,WAAO,IAAI;AAAA,EACb;AAAA;AAAA,EAGA,MAAM,YAAY,MAAc,QAAiC;AAC/D,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA,gBAAgB,IAAI,IAAI,CAAC;AAAA,MACzB,EAAE,OAAO;AAAA,IACX;AACA,WAAO,IAAI;AAAA,EACb;AAAA;AAAA,EAGA,MAAM,QAAQ,MAAwC;AACpD,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA,gBAAgB,IAAI,IAAI,CAAC;AAAA,IAC3B;AACA,WAAO,KAAK,IAAI,CAAC,OAAO;AAAA,MACtB,IAAI,EAAE;AAAA,MACN,GAAI,EAAE,WAAW,SAAY,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,MACrD,OAAO,YAAY,EAAE,KAAK;AAAA,IAC5B,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aACJ,MACA,QACe;AACf,UAAM,KAAK,QAAQ,QAAQ,gBAAgB,IAAI,IAAI,CAAC,eAAe;AAAA,MACjE,QAAQ,OAAO,IAAI,cAAc;AAAA,IACnC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,eACJ,MACA,QACe;AACf,UAAM,KAAK,QAAQ,QAAQ,gBAAgB,IAAI,IAAI,CAAC,iBAAiB;AAAA,MACnE,QAAQ,OAAO,IAAI,sBAAsB;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAKA,OAAO,MAAqC;AAC1C,WAAO,KAAK,cAAc,WAAW;AAAA,MACnC,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,oBAAoB,KAAK;AAAA,MACzB,oBAAoB,KAAK;AAAA,MACzB,SAAS,aAAa,KAAK,MAAM;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,eACE,MAC2C;AAC3C,WAAO,KAAK,sBAAsB,WAAW;AAAA,MAC3C,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,oBAAoB,KAAK;AAAA,MACzB,oBAAoB,KAAK;AAAA,MACzB,SAAS,aAAa,KAAK,MAAM;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,cAAc,MAA4C;AACxD,WAAO,KAAK,cAAc,mBAAmB;AAAA,MAC3C,YAAY,KAAK;AAAA,MACjB,IAAI,KAAK;AAAA,MACT,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,oBAAoB,KAAK;AAAA,MACzB,oBAAoB,KAAK;AAAA,MACzB,SAAS,aAAa,KAAK,MAAM;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,sBACE,MAC2C;AAC3C,WAAO,KAAK,sBAAsB,mBAAmB;AAAA,MACnD,YAAY,KAAK;AAAA,MACjB,IAAI,KAAK;AAAA,MACT,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,oBAAoB,KAAK;AAAA,MACzB,oBAAoB,KAAK;AAAA,MACzB,SAAS,aAAa,KAAK,MAAM;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,MAAyC;AAClD,WAAO,KAAK,cAAc,gBAAgB;AAAA,MACxC,GAAI,KAAK,UACL,EAAE,SAAS,KAAK,SAAS,SAAS,KAAK,QAAQ,IAC/C,EAAE,OAAO,KAAK,OAAO,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,MAChE,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,SAAS,KAAK;AAAA,MACd,WAAW,gBAAgB,KAAK,SAAS;AAAA,MACzC,oBAAoB,KAAK;AAAA,MACzB,oBAAoB,KAAK;AAAA,MACzB,SAAS,aAAa,KAAK,MAAM;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,MAA4C;AAClD,WAAO,KAAK;AAAA,MACV;AAAA,MACA,gBAAgB,IAAI,KAAK,UAAU,CAAC;AAAA,MACpC,MAAM,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,OAAO,KAAK,MAAM,CAAC;AAAA,IACrE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,MAA2C;AACtD,WAAO,KAAK,cAAc,kBAAkB;AAAA,MAC1C,QAAQ,KAAK;AAAA,MACb,GAAI,KAAK,UACL,EAAE,SAAS,KAAK,SAAS,SAAS,KAAK,QAAQ,IAC/C,EAAE,OAAO,KAAK,OAAO,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO;AAAA,MAC9D,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,WAAW,gBAAgB,KAAK,SAAS;AAAA,MACzC,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK;AAAA,MAClB,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,qBACE,MAC2C;AAC3C,WAAO,KAAK,sBAAsB,kBAAkB;AAAA,MAClD,QAAQ,KAAK;AAAA,MACb,GAAI,KAAK,UACL,EAAE,SAAS,KAAK,SAAS,SAAS,KAAK,QAAQ,IAC/C,EAAE,OAAO,KAAK,OAAO,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO;AAAA,MAC9D,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,WAAW,gBAAgB,KAAK,SAAS;AAAA,MACzC,eAAe,KAAK;AAAA,MACpB,aAAa,KAAK;AAAA,MAClB,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,QAAQ,aAAa,KAAK,MAAM;AAAA,IAClC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,KAAK,OAAoB,CAAC,GAAmB;AAC3C,WAAO,KAAK,cAAc,SAAS;AAAA,MACjC,OAAO,KAAK,SAAS,CAAC;AAAA,MACtB,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,oBAAoB,KAAK;AAAA,MACzB,oBAAoB,KAAK;AAAA,MACzB,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,OAAyB,CAAC,GAAyB;AACjE,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ,OAAO,KAAK,SAAS,CAAC;AAAA,QACtB,QAAQ,KAAK,UAAU,CAAC;AAAA,QACxB,KAAK,KAAK,OAAO,CAAC;AAAA,QAClB,UAAU,KAAK;AAAA,MACjB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,OAAO,IAAI;AAAA,MACX,MAAM,YAAY,IAAI,IAAI;AAAA;AAAA,MAE1B,GAAI,IAAI,SACJ;AAAA,QACE,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO;AAAA,UAC7B,OAAO,EAAE,UAAU,OAAO,OAAO,YAAY,EAAE,KAAK;AAAA,UACpD,OAAO,EAAE;AAAA,UACT,MAAM,YAAY,EAAE,IAAI;AAAA,QAC1B,EAAE;AAAA,MACJ,IACA,CAAC;AAAA,MACL,GAAI,IAAI,mBAAmB,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YAAY,MAA4C;AAC5D,UAAM,OAAO,MAAM;AAAA,MACjB,SAAS,KAAK,QAAQ,IAAI,CAAC,OAAO;AAAA,QAChC,OAAO,EAAE;AAAA,QACT,OAAO,EAAE,SAAS,CAAC;AAAA,QACnB,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE,UAAU,CAAC;AAAA,QACrB,OAAO,EAAE;AAAA,QACT,oBAAoB,EAAE;AAAA,QACtB,oBAAoB,EAAE;AAAA,QACtB,SAAS,aAAa,EAAE,MAAM;AAAA,QAC9B,WAAW,EAAE;AAAA,QACb,WAAW,EAAE;AAAA,QACb,QAAQ,aAAa,EAAE,MAAM;AAAA,MAC/B,EAAE;AAAA,MACF,MAAM,KAAK,OACP,MAAM;AAAA,QACJ,OAAO,KAAK,KAAK;AAAA,QACjB,SAAS,KAAK,KAAK;AAAA,QACnB,OAAO,KAAK,KAAK;AAAA,MACnB,CAAC,IACD;AAAA,IACN,CAAC;AACD,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,YAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAK,IAAI,WAAW,CAAC,GAAI;AAAA,MAAI,CAAC,SAC1D,KAAK,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,SACJ,YACA,IACA,MACA,OAAwB,CAAC,GACA;AACzB,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA,gBAAgB,IAAI,UAAU,CAAC;AAAA,MAC/B,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,QAAQ,YAAY,KAAK,KAAK,IAAI;AAAA,QAC9C,aAAa,KAAK;AAAA,QAClB,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAGA,WAAO;AAAA,MACL,IAAI,KAAK,MAAM;AAAA,MACf,UAAU,KAAK,YAAY;AAAA,MAC3B,SAAS,KAAK,WAAW;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OACE,YACA,OACA,OAAsB,CAAC,GACP;AAChB,WAAO,KAAK,cAAc,gBAAgB,IAAI,UAAU,CAAC,WAAW;AAAA,MAClE;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK,UAAU,CAAC;AAAA,MACxB,WAAW,KAAK;AAAA,MAChB,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,QAAQ,aAAa,KAAK,MAAM;AAAA,MAChC,WAAW,KAAK;AAAA,MAChB,oBAAoB,KAAK;AAAA,MACzB,SAAS,aAAa,KAAK,MAAM;AAAA,IACnC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,UAAM,KAAK,QAAQ,QAAQ,UAAU,CAAC,CAAC;AAAA,EACzC;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,UAAM,KAAK,QAAQ,QAAQ,YAAY,CAAC,CAAC;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,UAA4B;AAChC,UAAM,MAAM,MAAM,KAAK,QAA8B,QAAQ,YAAY,CAAC,CAAC;AAC3E,WAAO,IAAI;AAAA,EACb;AAAA;AAAA;AAAA,EAKA,MAAc,cACZ,MACA,MACgB;AAChB,UAAM,OAAO,MAAM,KAAK,QAAkB,QAAQ,MAAM,MAAM,IAAI,CAAC;AACnE,WAAO,KAAK,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;AAAA,EAC1C;AAAA;AAAA,EAGA,MAAc,sBACZ,MACA,MAC2C;AAC3C,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA,MAAM,EAAE,GAAG,MAAM,MAAM,KAAK,CAAC;AAAA,IAC/B;AACA,WAAO;AAAA,MACL,MAAM,IAAI,KAAK,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;AAAA,MAC3C,MAAM,gBAAgB,IAAI,IAAI;AAAA,IAChC;AAAA,EACF;AAAA;AAAA,EAGQ,UAAU,GAAgB;AAChC,WAAO;AAAA,MACL,YAAY,EAAE;AAAA,MACd,IAAI,EAAE;AAAA,MACN,OAAO,EAAE;AAAA,MACT,OAAO,YAAY,EAAE,KAAK;AAAA;AAAA,MAE1B,GAAI,EAAE,cACF,EAAE,aAAa,kBAAkB,EAAE,WAAW,EAAE,IAChD,CAAC;AAAA,MACL,GAAI,EAAE,YAAY,SAAY,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,QACZ,QACA,MACA,MACY;AACZ,UAAM,MAAM,MAAM,KAAK,IAAI,QAAQ,MAAM,IAAI;AAC7C,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,WAAW,aAAa,MAAM,IAAI,MAAM,GAAG,IAAI,MAAM;AAAA,IACjE;AACA,WAAQ,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EACpC;AAAA;AAAA,EAGA,MAAc,IACZ,QACA,MACA,MACmB;AACnB,UAAM,UAAkC,EAAE,GAAG,KAAK,aAAa;AAC/D,QAAI,KAAK,MAAO,SAAQ,gBAAgB,UAAU,KAAK,KAAK;AAC5D,QAAI;AACJ,QAAI,SAAS,QAAW;AACtB,cAAQ,cAAc,IAAI;AAC1B,gBAAU,KAAK,UAAU,IAAI;AAAA,IAC/B;AAEA,UAAM,aAAa,KAAK,YAAY,IAAI,IAAI,gBAAgB,IAAI;AAChE,UAAM,QACJ,cAAc,KAAK,YAAY,IAC3B,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS,IACnD;AACN,QAAI;AACF,aAAO,MAAM,KAAK,QAAQ,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,QAClD;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,QAAQ,YAAY;AAAA,MACtB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,SACH,YAAY,OAAO,WAAW,QAC3B,cAAc,IAAI,oBAAoB,KAAK,SAAS,OACpD,cAAc,IAAI,YAAa,IAAc,OAAO;AAC1D,YAAM,IAAI,WAAW,QAAQ,CAAC;AAAA,IAChC,UAAE;AACA,UAAI,MAAO,cAAa,KAAK;AAAA,IAC/B;AAAA,EACF;AACF;AAsCA,SAAS,gBAAgB,GAA4B;AACnD,QAAM,aAAyC,EAAE,aAC7C;AAAA,IACE,UAAU,EAAE,WAAW;AAAA,IACvB,UAAU,EAAE,WAAW;AAAA,IACvB,mBAAmB,EAAE,WAAW;AAAA,IAChC,cAAc,EAAE,WAAW;AAAA,IAC3B,iBAAiB,EAAE,WAAW;AAAA,IAC9B,iBAAiB,EAAE,WAAW;AAAA,EAChC,IACA;AACJ,QAAM,IAAI,EAAE;AACZ,QAAM,UAAuB;AAAA,IAC3B,GAAI,EAAE,cAAc,SAAY,EAAE,UAAU,EAAE,UAAU,IAAI,CAAC;AAAA,IAC7D,GAAI,EAAE,cAAc,SAAY,EAAE,UAAU,EAAE,UAAU,IAAI,CAAC;AAAA,IAC7D,GAAI,EAAE,YAAY,SAAY,EAAE,QAAQ,EAAE,QAAQ,IAAI,CAAC;AAAA,IACvD,GAAI,EAAE,eAAe,SAAY,EAAE,WAAW,EAAE,WAAW,IAAI,CAAC;AAAA,IAChE,GAAI,EAAE,kBAAkB,SAAY,EAAE,aAAa,EAAE,cAAc,IAAI,CAAC;AAAA,IACxE,GAAI,EAAE,eAAe,SAAY,EAAE,WAAW,EAAE,WAAW,IAAI,CAAC;AAAA,IAChE,GAAI,EAAE,aAAa,SAAY,EAAE,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,IAC1D,SAAS,EAAE;AAAA,EACb;AACA,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IACR,GAAI,EAAE,iBAAiB,SAAY,EAAE,aAAa,EAAE,aAAa,IAAI,CAAC;AAAA,IACtE,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,IACnC,WAAW;AAAA,MACT,OAAO,EAAE,UAAU;AAAA,MACnB,GAAI,EAAE,UAAU,eAAe,SAC3B,EAAE,YAAY,EAAE,UAAU,WAAW,IACrC,CAAC;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF;AAsBA,SAAS,aAAa,GAAgC;AACpD,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,MAAM;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,cAAc,EAAE;AAAA,IAChB,aAAa,EAAE;AAAA,IACf,YAAY,EAAE;AAAA,EAChB,CAAC;AACH;AAEA,SAAS,aAAa,GAAgC;AACpD,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,MAAM,EAAE,YAAY,EAAE,WAAW,YAAY,EAAE,WAAW,CAAC;AACpE;AAEA,SAAS,aAAa,MAAmC;AACvD,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,IAAI,KAAK;AACf,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,MACX,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE,kBAAkB,OAAO,EAAE,OAAO,QAAQ,IAAI,EAAE;AAAA,MAC1D,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE;AAAA,MACV,SAAS,EAAE;AAAA,MACX,aAAa,EAAE;AAAA,MACf,aAAa,EAAE;AAAA,MACf,cAAc,EAAE;AAAA,IAClB,CAAC;AAAA,EACH;AACF;AAGA,SAAS,gBAAgB,GAAoD;AAC3E,MAAI,MAAM,UAAa,MAAM,MAAO,QAAO;AAC3C,MAAI,MAAM,KAAM,QAAO,CAAC;AACxB,SAAO,MAAM;AAAA,IACX,eAAe,EAAE;AAAA,IACjB,gBAAgB,EAAE;AAAA,EACpB,CAAC;AACH;AAGA,SAAS,aAAa,GAAuC;AAC3D,MAAI,MAAM,OAAW,QAAO;AAC5B,SAAO,EAAE,OAAO,EAAE,OAAO,UAAU,EAAE,UAAU,WAAW,EAAE,SAAS;AACvE;AAGA,SAAS,IAAI,MAAsB;AACjC,SAAO,mBAAmB,IAAI;AAChC;AAOA,SAAS,eAAeA,IAA+B;AACrD,MAAI,OAAOA,OAAM,SAAU,QAAOA;AAClC,SAAO,MAAM;AAAA,IACX,OAAOA,GAAE;AAAA,IACT,IAAIA,GAAE;AAAA,IACN,GAAGA,GAAE;AAAA,IACL,UAAUA,GAAE;AAAA,IACZ,eAAeA,GAAE;AAAA,IACjB,eAAeA,GAAE;AAAA,EACnB,CAAC;AACH;AAOA,SAAS,uBAAuBA,IAAuC;AACrE,MAAI,OAAOA,OAAM,SAAU,QAAOA;AAClC,SAAO,MAAM;AAAA,IACX,OAAOA,GAAE;AAAA,IACT,QAAQA,GAAE;AAAA,IACV,UAAUA,GAAE;AAAA,EACd,CAAC;AACH;AAGA,SAAS,MAAM,MAAwD;AACrE,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,GAAG,GAAG,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC3C,QAAI,QAAQ,OAAW,KAAI,CAAC,IAAI;AAAA,EAClC;AACA,SAAO;AACT;AAGA,SAAS,aAAa,MAAc,QAAwB;AAC1D,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,UAAU,OAAO,OAAO,UAAU,SAAU,QAAO,OAAO;AAAA,EAChE,QAAQ;AAAA,EAER;AACA,SAAO,QAAQ,QAAQ,MAAM;AAC/B;;;ACh3BO,IAAM,IAAI;AAAA;AAAA,EAEf,IAAI,CAAC,KAAa,WAAiC;AAAA,IACjD,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA,EAEA,IAAI,CAAC,KAAa,WAAiC;AAAA,IACjD,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA,EAEA,MAAM,CAAC,KAAa,aAAgC,EAAE,MAAM,CAAC,KAAK,OAAO,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3E,OAAO,CAAC,KAAa,aAAgC;AAAA,IACnD,OAAO,CAAC,KAAK,OAAO;AAAA,EACtB;AAAA;AAAA,EAEA,IAAI,CAAC,KAAa,YAAoC;AAAA,IACpD,IAAI,CAAC,KAAK,OAAO,IAAI,WAAW,CAAC;AAAA,EACnC;AAAA;AAAA,EAEA,OAAO,CAAC,KAAa,YAAoC;AAAA,IACvD,OAAO,CAAC,KAAK,OAAO,IAAI,WAAW,CAAC;AAAA,EACtC;AAAA;AAAA,EAEA,IAAI,CAAC,KAAa,WAAiC;AAAA,IACjD,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA,EAEA,IAAI,CAAC,KAAa,WAAiC;AAAA,IACjD,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA,EAEA,IAAI,CAAC,KAAa,WAAiC;AAAA,IACjD,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA,EAEA,IAAI,CAAC,KAAa,WAAiC;AAAA,IACjD,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA,EAEA,UAAU,CAAC,KAAa,WAAiC;AAAA,IACvD,UAAU,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EACpC;AAAA;AAAA,EAEA,aAAa,CAAC,KAAa,WAAiC;AAAA,IAC1D,aAAa,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,EACvC;AAAA;AAAA,EAEA,aAAa,CAAC,KAAa,YAAoC;AAAA,IAC7D,aAAa,CAAC,KAAK,OAAO,IAAI,WAAW,CAAC;AAAA,EAC5C;AAAA;AAAA,EAEA,KAAK,IAAI,WAAmC,EAAE,KAAK,MAAM;AAAA;AAAA,EAEzD,KAAK,IAAI,WAAmC,EAAE,KAAK,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,EAKzD,KAAK,CAAC,UAAgC,EAAE,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlD,OAAO,CAAC,KAAa,MAAc,cAAiC;AAAA,IAClE,OAAO,CAAC,KAAK,MAAM,QAAQ;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,CAAC,KAAa,UAA6B;AAAA,IAC5D,mBAAmB,CAAC,KAAK,IAAI;AAAA,EAC/B;AAAA;AAAA,EAEA,kBAAkB,CAAC,KAAa,UAA6B;AAAA,IAC3D,kBAAkB,CAAC,KAAK,IAAI;AAAA,EAC9B;AAAA;AAAA,EAEA,uBAAuB,CAAC,KAAa,UAA6B;AAAA,IAChE,uBAAuB,CAAC,KAAK,IAAI;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,CAAC,KAAa,aAAgC,EAAE,OAAO,CAAC,KAAK,OAAO,EAAE;AAAA;AAAA,EAE7E,KAAK,IAAI,UAA+B;AAC1C;","names":["f"]}
1
+ {"version":3,"sources":["../src/annotations.ts","../src/errors.ts","../src/values.ts","../src/client.ts","../src/filter.ts"],"sourcesContent":["//! Decoding a hit's optional annotations — the opt-in \"why did this match\".\n//\n// One rule here is JS's alone. The server reports a highlight span as a **UTF-8 byte**\n// range into the fragment text, but a JS string is indexed in UTF-16 code units, so\n// `text.slice(...span)` on a raw span is wrong for any non-ASCII excerpt. Converted here,\n// once, so a caller's obvious slice is the right one.\n\nimport type { Annotations, Fragment, Highlight } from \"./types.js\";\n\n/** A fragment as it arrives: `spans` are UTF-8 byte offsets into `text`. */\ninterface WireFragment {\n text: string;\n spans: [number, number][];\n}\n\ninterface WireHighlight {\n field: string;\n fragments: WireFragment[];\n}\n\n/** A hit's annotations as they arrive, before the span offsets are converted. */\nexport interface WireAnnotations {\n vector?: { rank: number; score: number };\n text?: { rank: number; score: number };\n clauses?: {\n field: string;\n score: number;\n expansion?: { matched: number; scored: number };\n }[];\n highlights?: WireHighlight[];\n}\n\n/**\n * Decode a hit's annotations, converting every highlight span to JS string indices. The\n * parts the server omitted stay omitted rather than becoming empty arrays.\n */\nexport function decodeAnnotations(a: WireAnnotations): Annotations {\n const out: Annotations = {};\n if (a.vector) out.vector = a.vector;\n if (a.text) out.text = a.text;\n if (a.clauses) out.clauses = a.clauses;\n if (a.highlights) out.highlights = a.highlights.map(decodeHighlight);\n return out;\n}\n\nfunction decodeHighlight(h: WireHighlight): Highlight {\n return { field: h.field, fragments: h.fragments.map(decodeFragment) };\n}\n\nfunction decodeFragment(fr: WireFragment): Fragment {\n return { text: fr.text, spans: toStringIndices(fr.text, fr.spans) };\n}\n\n/**\n * Convert UTF-8 byte ranges into `text` to JS string indices (UTF-16 code units), so\n * `text.slice(...span)` yields the matched term. An all-ASCII excerpt needs no conversion\n * and is the common case, so it is detected before any table is built.\n */\nexport function toStringIndices(\n text: string,\n spans: [number, number][],\n): [number, number][] {\n if (spans.length === 0 || isAscii(text)) return spans;\n const index = byteToUnit(text);\n const at = (b: number): number =>\n index[Math.min(Math.max(b, 0), index.length - 1)]!;\n return spans.map(([start, end]): [number, number] => [at(start), at(end)]);\n}\n\n/** One entry per byte of `text` (plus its end), holding that byte's UTF-16 index. */\nfunction byteToUnit(text: string): number[] {\n const index: number[] = [];\n let unit = 0;\n // A byte *inside* a codepoint maps to that codepoint's start. Spans land on token\n // boundaries, so this only keeps a malformed offset from landing mid-surrogate.\n for (const ch of text) {\n for (let n = utf8Len(ch.codePointAt(0)!); n > 0; n--) index.push(unit);\n unit += ch.length;\n }\n index.push(unit);\n return index;\n}\n\nfunction utf8Len(codePoint: number): number {\n if (codePoint < 0x80) return 1;\n if (codePoint < 0x800) return 2;\n return codePoint < 0x10000 ? 3 : 4;\n}\n\n/** True when every code unit is ASCII, i.e. byte offsets already *are* string indices. */\nfunction isAscii(text: string): boolean {\n for (let i = 0; i < text.length; i++) {\n if (text.charCodeAt(i) > 0x7f) return false;\n }\n return true;\n}\n","//! Error type carrying the HTTP status the server reported.\n//\n// The server replies to a failed request with `{ \"error\": <message> }` and a\n// meaningful status (`src/server/mod.rs#classify`): 400 dimension mismatch,\n// 403 read-only store, 409 writer-lock conflict, 507 capacity/OOM, 500 otherwise.\n// Callers branch on `.status` to tell a client fault from a server fault.\n\n/** An error returned by a `nidus` server, or a transport failure reaching it. */\nexport class NidusError extends Error {\n /** The HTTP status code, or `0` for a transport/timeout failure (no response). */\n readonly status: number;\n\n constructor(message: string, status: number) {\n super(message);\n this.name = \"NidusError\";\n this.status = status;\n }\n\n /** A malformed request the server rejected (HTTP 400). */\n get isBadRequest(): boolean {\n return this.status === 400;\n }\n /** The store is read-only (HTTP 403). */\n get isReadOnly(): boolean {\n return this.status === 403;\n }\n /** The writer lock is held by another process (HTTP 409). */\n get isLocked(): boolean {\n return this.status === 409;\n }\n /** Out of capacity: `max_vector_bytes` exceeded or OOM (HTTP 507). */\n get isOutOfCapacity(): boolean {\n return this.status === 507;\n }\n}\n","//! Ergonomic constructors and decoders for the externally-tagged `Value` wire type.\n//\n// Callers should never hand-write `{ Str: \"x\" }`. Use `v.str(\"x\")`, `v.int(5)`,\n// etc., or just pass plain JS values into `attrs` — `encodeValue` normalizes them.\n//\n// One rule is JS's alone. The store's `Int` and `Float` are separate types compared\n// same-type only, but JS has one `number` and `1.0 === 1`, so `Number.isInteger` has to\n// decide. A whole-numbered measurement therefore lands as an `Int` in whichever records\n// it came out round, and a `Float` range filter then skips exactly those: write such a\n// field with `v.float`. Go and Python have the types JS lacks and decide from them.\n\nimport type { AttrInput, DecodedValue, Value } from \"./types.js\";\n\n/** Every tag this SDK version knows, in the order `decodeValue` tries them. */\nconst TAGS = [\"Str\", \"Int\", \"Bool\", \"List\", \"Float\", \"DateTime\"] as const;\n\n/**\n * Value constructors mirroring the `Value` variants. `v.int` requires a safe\n * integer and `v.float` a finite number — `NaN`/`Infinity` have no JSON spelling,\n * and `JSON.stringify` would quietly write `null`.\n */\nexport const v = {\n str: (s: string): Value => ({ Str: s }),\n int: (n: number): Value => {\n if (!Number.isInteger(n)) {\n throw new TypeError(`v.int expects an integer, got ${n}`);\n }\n return { Int: n };\n },\n float: (n: number): Value => {\n if (typeof n !== \"number\" || !Number.isFinite(n)) {\n throw new TypeError(`v.float expects a finite number, got ${n}`);\n }\n return { Float: n };\n },\n bool: (b: boolean): Value => ({ Bool: b }),\n list: (items: string[]): Value => ({ List: items }),\n /**\n * A UTC instant, from a `Date` or a raw epoch-millisecond count. Milliseconds is\n * the wire type, so there is no sub-millisecond precision and no timezone.\n */\n datetime: (when: Date | number): Value => {\n const ms = when instanceof Date ? when.getTime() : when;\n if (!Number.isSafeInteger(ms)) {\n throw new TypeError(\n `v.datetime expects a valid Date or epoch ms, got ${when}`,\n );\n }\n return { DateTime: ms };\n },\n /** The explicit `Null` value — set-but-empty, distinct from an absent key. */\n nil: (): Value => \"Null\",\n} as const;\n\n/** True if `x` is already a wire-tagged {@link Value}. */\nfunction isValue(x: unknown): x is Value {\n if (x === \"Null\") return true;\n if (typeof x !== \"object\" || x === null) return false;\n return TAGS.some((tag) => tag in x);\n}\n\n/**\n * Normalize a caller-supplied {@link AttrInput} into the wire {@link Value} shape.\n * Plain scalars map by type; an already-tagged `Value` passes through unchanged.\n * Throws on a non-finite number, an invalid `Date`, or a non-string list element.\n */\nexport function encodeValue(input: AttrInput): Value {\n if (isValue(input)) return input;\n if (input === null) return \"Null\";\n switch (typeof input) {\n case \"string\":\n return { Str: input };\n case \"boolean\":\n return { Bool: input };\n case \"number\":\n return Number.isInteger(input) ? v.int(input) : v.float(input);\n case \"object\":\n // Date before the array check: both are objects, only one is a list.\n if (input instanceof Date) return v.datetime(input);\n if (Array.isArray(input)) {\n if (!input.every((e) => typeof e === \"string\")) {\n throw new TypeError(\"a List attribute must contain only strings\");\n }\n return { List: input };\n }\n // falls through\n default:\n throw new TypeError(`cannot encode attribute value: ${String(input)}`);\n }\n}\n\n/** Normalize a whole `attrs` map of {@link AttrInput} into wire {@link Value}s. */\nexport function encodeAttrs(\n attrs: Record<string, AttrInput>,\n): Record<string, Value> {\n const out: Record<string, Value> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = encodeValue(val);\n }\n return out;\n}\n\n/** Decode a wire {@link Value} back to a plain JS value. */\nexport function decodeValue(value: Value): DecodedValue {\n if (value === \"Null\") return null;\n if (\"Str\" in value) return value.Str;\n if (\"Int\" in value) return value.Int;\n if (\"Bool\" in value) return value.Bool;\n if (\"List\" in value) return value.List;\n if (\"Float\" in value) return value.Float;\n // A Date, not the raw number: a number would demote every instant to an Int\n // when a decoded attrs map is written back.\n if (\"DateTime\" in value) return new Date(value.DateTime);\n // Unknown tag (forward-compat): hand it back untouched.\n return value as unknown as DecodedValue;\n}\n\n/** Decode a whole wire `attrs` map back to plain JS values. */\nexport function decodeAttrs(\n attrs: Record<string, Value>,\n): Record<string, DecodedValue> {\n const out: Record<string, DecodedValue> = {};\n for (const [k, val] of Object.entries(attrs)) {\n out[k] = decodeValue(val);\n }\n return out;\n}\n","//! `NidusClient` — a remote client over the `nidus serve` HTTP API.\n//\n// One method per endpoint (`src/server/mod.rs`). \"Local vs remote\" is just the\n// base URL: point at a local `nidus serve` or any reachable host. Built on the\n// platform-global `fetch`, so it runs unchanged on Node 18+, Deno, Bun, Cloudflare\n// Workers, and browsers — with no runtime dependencies.\n\nimport { decodeAnnotations, type WireAnnotations } from \"./annotations.js\";\nimport { NidusError } from \"./errors.js\";\nimport type {\n AggregateOptions,\n Aggregation,\n BatchSearchOptions,\n ClusterStatus,\n DecodedRecord,\n Expand,\n Filter,\n FilterIndexField,\n FtsField,\n HighlightOptions,\n Hit,\n HybridSearchOptions,\n ListOptions,\n NidusRecord,\n PlanCandidates,\n PlanNarrowing,\n PlanTimings,\n QueryPlan,\n RankBy,\n Readiness,\n RecallOptions,\n RecordInput,\n RememberOptions,\n RememberResult,\n RerankOptions,\n Rollup,\n SearchOptions,\n SimilarSearchOptions,\n Stats,\n StoreVersions,\n Suggestions,\n SuggestOptions,\n TextSearchOptions,\n Value,\n} from \"./types.js\";\nimport { decodeAttrs, decodeValue, encodeAttrs } from \"./values.js\";\n\n/** Minimal `fetch` signature the client needs — satisfied by the platform global. */\nexport type FetchLike = (\n input: string,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Construction options for {@link NidusClient}. */\nexport interface NidusClientOptions {\n /** Base URL of the server, e.g. `http://127.0.0.1:7700`. Trailing slash optional. */\n baseUrl: string;\n /** Bearer token, when the server was started with `--token`. */\n token?: string;\n /** Override the `fetch` implementation (defaults to `globalThis.fetch`). */\n fetch?: FetchLike;\n /** Per-request timeout in milliseconds. Omit (or `0`) to disable. */\n timeoutMs?: number;\n /** Extra headers sent on every request. */\n headers?: Record<string, string>;\n}\n\nexport class NidusClient {\n private readonly baseUrl: string;\n private readonly token?: string;\n private readonly doFetch: FetchLike;\n private readonly timeoutMs: number;\n private readonly extraHeaders: Record<string, string>;\n\n constructor(options: NidusClientOptions) {\n if (!options.baseUrl) {\n throw new TypeError(\"NidusClient requires a baseUrl\");\n }\n this.baseUrl = options.baseUrl.replace(/\\/+$/, \"\");\n this.token = options.token;\n this.timeoutMs = options.timeoutMs ?? 0;\n this.extraHeaders = options.headers ?? {};\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\n \"no fetch available; pass options.fetch (Node < 18, or a custom runtime)\",\n );\n }\n // Bind so a passed `globalThis.fetch` keeps its `this`.\n this.doFetch = f === globalThis.fetch ? f.bind(globalThis) : f;\n }\n\n // ── Admin / introspection ─────────────────────────────────────────────────\n\n /** Liveness check. Returns `true` when the server answers `/health`. */\n async health(): Promise<boolean> {\n try {\n const res = await this.raw(\"GET\", \"/health\");\n return res.ok;\n } catch {\n return false;\n }\n }\n\n /** Store-wide introspection: dimension, distance, ANN config, collections, footprint. */\n stats(): Promise<Stats> {\n return this.request<Stats>(\"GET\", \"/stats\");\n }\n\n /**\n * Readiness: whether this instance can serve. A `503` is the negative answer, not an\n * error, so a poll loop branches on `ready` instead of catching. Other failures throw.\n */\n async ready(): Promise<Readiness> {\n const res = await this.raw(\"GET\", \"/ready\");\n const text = await res.text();\n if (res.status === 503) return { ready: false, reason: extractError(text, 503) };\n if (!res.ok) throw new NidusError(extractError(text, res.status), res.status);\n return JSON.parse(text) as Readiness;\n }\n\n /** Cluster role, writer-handle state, fencing token, commit counter, staleness. */\n cluster(): Promise<ClusterStatus> {\n return this.request<ClusterStatus>(\"GET\", \"/cluster\");\n }\n\n /** The readable commit points and this instance's pin, if any. */\n versions(): Promise<StoreVersions> {\n return this.request<StoreVersions>(\"GET\", \"/versions\");\n }\n\n /** List every collection name. */\n collections(): Promise<string[]> {\n return this.request<string[]>(\"GET\", \"/collections\");\n }\n\n /** Create a collection. Idempotent on the server side. */\n async createCollection(name: string): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}`, {});\n }\n\n /** Drop a collection and all its records. */\n async dropCollection(name: string): Promise<void> {\n await this.request(\"DELETE\", `/collections/${enc(name)}`);\n }\n\n /** Every alias and the concrete collection it resolves to. */\n aliases(): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\"GET\", \"/aliases\");\n }\n\n /** Create or repoint an alias. The target must already exist; aliases never chain. */\n async setAlias(name: string, target: string): Promise<void> {\n await this.request(\"PUT\", `/aliases/${enc(name)}`, { target });\n }\n\n /** Remove an alias. Deletes no records. */\n async dropAlias(name: string): Promise<void> {\n await this.request(\"DELETE\", `/aliases/${enc(name)}`);\n }\n\n /** Read a collection's free-form string metadata. */\n getMeta(name: string): Promise<Record<string, string>> {\n return this.request<Record<string, string>>(\n \"GET\",\n `/collections/${enc(name)}/meta`,\n );\n }\n\n /** Replace a collection's free-form string metadata. */\n async setMeta(name: string, meta: Record<string, string>): Promise<void> {\n await this.request(\"PUT\", `/collections/${enc(name)}/meta`, meta);\n }\n\n // ── Data ──────────────────────────────────────────────────────────────────\n\n /**\n * Insert or replace records (idempotent on `id` within the collection).\n * `attrs` accept plain JS values or `v.*` helpers; they are normalized for you.\n * Returns the number of records upserted.\n */\n async upsert(name: string, records: RecordInput[]): Promise<number> {\n const wire: NidusRecord[] = records.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: encodeAttrs(r.attrs),\n }));\n const res = await this.request<{ upserted: number }>(\n \"POST\",\n `/collections/${enc(name)}/upsert`,\n { records: wire },\n );\n return res.upserted;\n }\n\n /** Delete records by id. Returns the number deleted. */\n async delete(name: string, opts: { ids: string[] }): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { ids: opts.ids },\n );\n return res.deleted;\n }\n\n /** Delete every record matching `filter`. Returns the number deleted. */\n async deleteWhere(name: string, filter: Filter): Promise<number> {\n const res = await this.request<{ deleted: number }>(\n \"POST\",\n `/collections/${enc(name)}/delete`,\n { filter },\n );\n return res.deleted;\n }\n\n /** Fetch every record in a collection (attrs decoded to plain JS values). */\n async records(name: string): Promise<DecodedRecord[]> {\n const recs = await this.request<NidusRecord[]>(\n \"GET\",\n `/collections/${enc(name)}/records`,\n );\n return recs.map((r) => ({\n id: r.id,\n ...(r.vector !== undefined ? { vector: r.vector } : {}),\n attrs: decodeAttrs(r.attrs),\n }));\n }\n\n /**\n * Declare the full-text-indexed attribute fields for a collection. A bare string\n * takes the server's BM25/analyzer defaults; an {@link FtsField} object tunes `k1`,\n * `b`, and the analyzer for that field alone.\n */\n async setFtsSchema(\n name: string,\n fields: (string | FtsField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/fts-schema`, {\n fields: fields.map(encodeFtsField),\n });\n }\n\n /**\n * Declare which attribute fields are indexed for the text predicates (`Fuzzy`,\n * `ContainsAllTokens`, `ContainsAnyToken`, `ContainsTokenSequence`, `Regex`). Fields\n * already written are indexed as part of applying the declaration.\n *\n * This changes how fast those predicates run, never what they return: the index\n * proposes candidate documents and the predicate itself still decides. The cost is\n * paid at write time and in memory. Pass an empty array to drop the declaration.\n */\n async setFilterIndex(\n name: string,\n fields: (string | FilterIndexField)[],\n ): Promise<void> {\n await this.request(\"POST\", `/collections/${enc(name)}/filter-index`, {\n fields: fields.map(encodeFilterIndexField),\n });\n }\n\n // ── Search ──────────────────────────────────────────────────────────────\n\n /** Vector (cosine) nearest-neighbour search. Empty `scope` searches all collections. */\n search(opts: SearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.search}, but also reports the scan strategy the server took. */\n searchWithPlan(\n opts: SearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search\", {\n query: opts.query,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Records most like an existing one. The source record itself is never returned. */\n searchSimilar(opts: SimilarSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /** Like {@link NidusClient.searchSimilar}, but also reports the scan strategy taken. */\n searchSimilarWithPlan(\n opts: SimilarSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/search/similar\", {\n collection: opts.collection,\n id: opts.id,\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n exact: opts.exact,\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n });\n }\n\n /**\n * BM25 full-text search over one indexed field, or over a `clauses` list folded by\n * `combine` (`\"Sum\"` unless said otherwise). Naming the fields both ways is a `400`.\n */\n textSearch(opts: TextSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/text-search\", {\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, query: opts.query, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n rank_by: encodeRankBy(opts.rankBy),\n limit_per: opts.limitPer,\n diversity: opts.diversity,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /**\n * Ranked term completions for a partial word, for an autocomplete dropdown. Ranked by\n * document frequency (commonest first), which is the opposite of how a prefix clause\n * ranks documents. Completions are real spellings: the prefix is folded, not stemmed.\n *\n * The `df` counts only documents passing `filter` and carrying every word already typed\n * before the final token, so a permission-scoped dropdown is expressible and \"quick br\"\n * completes against the documents that also say \"quick\".\n */\n suggest(opts: SuggestOptions): Promise<Suggestions> {\n return this.request<Suggestions>(\n \"POST\",\n \"/suggest\",\n prune({\n scope: opts.scope ?? [],\n field: opts.field,\n prefix: opts.prefix,\n limit: opts.limit,\n filter: opts.filter ?? [],\n }),\n );\n }\n\n /**\n * Hybrid search: fuse a vector query and a BM25 text query via RRF. The text leg takes\n * the same single-field / `clauses` choice as {@link NidusClient.textSearch}.\n */\n hybridSearch(opts: HybridSearchOptions): Promise<Hit[]> {\n return this.searchRequest(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Like {@link NidusClient.hybridSearch}, but also reports the scan strategy taken. */\n hybridSearchWithPlan(\n opts: HybridSearchOptions,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n return this.searchRequestWithPlan(\"/hybrid-search\", {\n vector: opts.vector,\n ...(opts.clauses\n ? { clauses: opts.clauses, combine: opts.combine }\n : { field: opts.field, text: opts.text, prefix: opts.prefix }),\n scope: opts.scope ?? [],\n top_k: opts.topK,\n offset: opts.offset,\n filter: opts.filter ?? [],\n rrf_k: opts.rrfK,\n candidates: opts.candidates,\n explain: opts.explain,\n highlight: encodeHighlight(opts.highlight),\n vector_weight: opts.vectorWeight,\n text_weight: opts.textWeight,\n expand: encodeExpand(opts.expand),\n rerank: encodeRerank(opts.rerank),\n });\n }\n\n /** Metadata-only listing (no vector), paginated by `offset`/`limit`. */\n list(opts: ListOptions = {}): Promise<Hit[]> {\n return this.searchRequest(\"/list\", {\n scope: opts.scope ?? [],\n offset: opts.offset,\n limit: opts.limit,\n filter: opts.filter ?? [],\n include_attributes: opts.includeAttributes,\n exclude_attributes: opts.excludeAttributes,\n order_by: opts.orderBy,\n });\n }\n\n /**\n * Count the records matching a filter and sum the named attributes. Answered from the\n * in-RAM index alone — no record is built and no vector is read.\n */\n async aggregate(opts: AggregateOptions = {}): Promise<Aggregation> {\n const res = await this.request<RawAggregation>(\n \"POST\",\n \"/aggregate\",\n prune({\n scope: opts.scope ?? [],\n filter: opts.filter ?? [],\n sum: opts.sum ?? [],\n group_by: opts.groupBy,\n }),\n );\n // Every sum is an `Int` or a `Float`, both of which decode to a JS number.\n return {\n count: res.count,\n sums: decodeAttrs(res.sums) as Record<string, number>,\n // Kept absent, not `undefined`, so an ungrouped answer is the shape it always was.\n ...(res.groups\n ? {\n groups: res.groups.map((g) => ({\n value: g.value === null ? null : decodeValue(g.value),\n count: g.count,\n sums: decodeAttrs(g.sums) as Record<string, number>,\n })),\n }\n : {}),\n ...(res.groups_truncated ? { groupsTruncated: true } : {}),\n };\n }\n\n /**\n * Answer several vector queries in one round-trip (16 max). Returns one ranking per\n * query in request order, or — with `opts.fuse` — a single array holding the one fused\n * ranking, so the return shape is uniform either way.\n *\n * The server validates the whole batch before running any leg, so a malformed query\n * fails the call rather than returning a partial answer that cannot be told apart.\n */\n async batchSearch(opts: BatchSearchOptions): Promise<Hit[][]> {\n const body = prune({\n queries: opts.queries.map((q) => ({\n query: q.query,\n scope: q.scope ?? [],\n top_k: q.topK,\n offset: q.offset,\n min_score: q.minScore,\n filter: q.filter ?? [],\n exact: q.exact,\n include_attributes: q.includeAttributes,\n exclude_attributes: q.excludeAttributes,\n rank_by: encodeRankBy(q.rankBy),\n limit_per: q.limitPer,\n diversity: q.diversity,\n expand: encodeExpand(q.expand),\n })),\n fuse: opts.fuse\n ? prune({\n rrf_k: opts.fuse.rrfK,\n weights: opts.fuse.weights,\n top_k: opts.fuse.topK,\n })\n : undefined,\n });\n const res = await this.request<RawBatchSearch>(\n \"POST\",\n \"/search/batch\",\n body,\n );\n return (res.fused ? [res.fused] : (res.results ?? [])).map((hits) =>\n hits.map((h) => this.decodeHit(h)),\n );\n }\n\n // ── Memory (text-native) ──────────────────────────────────────────────────\n //\n // Available only when `nidus serve` was started with an embedder\n // (`--embed-provider …`); otherwise these answer `400`. The server embeds the\n // text/query — the client only sends strings.\n\n /**\n * Embed `text` and upsert it under `id` in `collection` (idempotent on `id`).\n * With `opts.mode === \"summarize\"` the server summarizes first, embeds the\n * summary, and stamps a `nidus.summary` attr (requires the server to have a\n * summarizer). The raw text is always stored under `nidus.text`. `opts.attrs` accept plain JS values or `v.*`\n * helpers; they are normalized for you.\n *\n * Read `id` off the result rather than assuming the one you passed:\n * `opts.dedupeThreshold` can redirect the write onto a near-duplicate.\n */\n async remember(\n collection: string,\n id: string,\n text: string,\n opts: RememberOptions = {},\n ): Promise<RememberResult> {\n const res = await this.request<Partial<RememberResult> | undefined>(\n \"POST\",\n `/collections/${enc(collection)}/remember`,\n prune({\n id,\n text,\n mode: opts.mode,\n attrs: opts.attrs ? encodeAttrs(opts.attrs) : undefined,\n ttl_seconds: opts.ttlSeconds,\n dedupe_threshold: opts.dedupeThreshold,\n }),\n );\n // A server predating the echoed fields answers `{ok, upserted}`; falling back to the\n // requested id keeps that case honest instead of reporting `undefined` as the target.\n return {\n id: res?.id ?? id,\n upserted: res?.upserted ?? 0,\n deduped: res?.deduped ?? false,\n };\n }\n\n /**\n * Embed `query` and vector-search `collection`, best-first (attrs decoded to\n * plain JS values). Refused with a cross-model guard if the collection was\n * written with a different embedder than the server's.\n */\n recall(\n collection: string,\n query: string,\n opts: RecallOptions = {},\n ): Promise<Hit[]> {\n return this.searchRequest(`/collections/${enc(collection)}/recall`, {\n query,\n top_k: opts.topK,\n min_score: opts.minScore,\n filter: opts.filter ?? [],\n diversity: opts.diversity,\n rollup: encodeRollup(opts.rollup),\n rerank: encodeRerank(opts.rerank),\n reinforce: opts.reinforce,\n extend_ttl_seconds: opts.extendTtlSeconds,\n rank_by: encodeRankBy(opts.rankBy),\n });\n }\n\n // ── Maintenance ───────────────────────────────────────────────────────────\n\n /** Force a durability flush. */\n async flush(): Promise<void> {\n await this.request(\"POST\", \"/flush\", {});\n }\n\n /** Compact the store (reclaim space from deleted/overwritten rows). */\n async compact(): Promise<void> {\n await this.request(\"POST\", \"/compact\", {});\n }\n\n /** Adopt a writer's newer committed state. Returns whether anything was adopted. */\n async refresh(): Promise<boolean> {\n const res = await this.request<{ adopted: boolean }>(\"POST\", \"/refresh\", {});\n return res.adopted;\n }\n\n // ── Internals ─────────────────────────────────────────────────────────────\n\n /** Run a search-family request and decode the resulting hits' attrs. */\n private async searchRequest(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Hit[]> {\n const hits = await this.request<RawHit[]>(\"POST\", path, prune(body));\n return hits.map((h) => this.decodeHit(h));\n }\n\n /** Like {@link NidusClient.searchRequest}, asking for `plan: true` and decoding it too. */\n private async searchRequestWithPlan(\n path: string,\n body: Record<string, unknown>,\n ): Promise<{ hits: Hit[]; plan: QueryPlan }> {\n const res = await this.request<{ hits: RawHit[]; plan: RawQueryPlan }>(\n \"POST\",\n path,\n prune({ ...body, plan: true }),\n );\n return {\n hits: res.hits.map((h) => this.decodeHit(h)),\n plan: decodeQueryPlan(res.plan),\n };\n }\n\n /** One wire hit into a {@link Hit}. Shared so every search surface decodes identically. */\n private decodeHit(h: RawHit): Hit {\n return {\n collection: h.collection,\n id: h.id,\n score: h.score,\n attrs: decodeAttrs(h.attrs),\n // Kept absent, not `undefined`, so an unannotated hit is the shape it always was.\n ...(h.annotations\n ? { annotations: decodeAnnotations(h.annotations) }\n : {}),\n ...(h.context !== undefined ? { context: h.context } : {}),\n };\n }\n\n /** Issue a request and parse a JSON body, mapping a non-2xx to {@link NidusError}. */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const res = await this.raw(method, path, body);\n const text = await res.text();\n if (!res.ok) {\n throw new NidusError(extractError(text, res.status), res.status);\n }\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** The bare transport: headers, auth, timeout, and transport-error mapping. */\n private async raw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const headers: Record<string, string> = { ...this.extraHeaders };\n if (this.token) headers.authorization = `Bearer ${this.token}`;\n let payload: string | undefined;\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n payload = JSON.stringify(body);\n }\n\n const controller = this.timeoutMs > 0 ? new AbortController() : undefined;\n const timer =\n controller && this.timeoutMs > 0\n ? setTimeout(() => controller.abort(), this.timeoutMs)\n : undefined;\n try {\n return await this.doFetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: payload,\n signal: controller?.signal,\n });\n } catch (err) {\n const reason =\n (controller?.signal.aborted ?? false)\n ? `request to ${path} timed out after ${this.timeoutMs}ms`\n : `request to ${path} failed: ${(err as Error).message}`;\n throw new NidusError(reason, 0);\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\n/** A hit as it arrives on the wire, before attrs are decoded. */\ninterface RawHit {\n collection: string;\n id: string;\n score: number;\n attrs: Record<string, Value>;\n annotations?: WireAnnotations;\n context?: string;\n}\n\n/** A `QueryPlan` as it arrives on the wire (snake_case), before camelCasing. */\ninterface RawQueryPlan {\n path: string;\n rows_scanned?: number;\n candidates?: {\n surfaced: number;\n survived: number;\n dropped_out_of_scope: number;\n dropped_stale: number;\n dropped_filtered: number;\n dropped_min_score: number;\n };\n narrowing: { state: PlanNarrowing[\"state\"]; candidates?: number };\n timings: {\n narrow_us?: number;\n gather_us?: number;\n walk_us?: number;\n resolve_us?: number;\n first_pass_us?: number;\n rescore_us?: number;\n score_us?: number;\n total_us: number;\n };\n}\n\n/** Wire `QueryPlan` into its camelCase {@link QueryPlan} shape. */\nfunction decodeQueryPlan(p: RawQueryPlan): QueryPlan {\n const candidates: PlanCandidates | undefined = p.candidates\n ? {\n surfaced: p.candidates.surfaced,\n survived: p.candidates.survived,\n droppedOutOfScope: p.candidates.dropped_out_of_scope,\n droppedStale: p.candidates.dropped_stale,\n droppedFiltered: p.candidates.dropped_filtered,\n droppedMinScore: p.candidates.dropped_min_score,\n }\n : undefined;\n const t = p.timings;\n const timings: PlanTimings = {\n ...(t.narrow_us !== undefined ? { narrowUs: t.narrow_us } : {}),\n ...(t.gather_us !== undefined ? { gatherUs: t.gather_us } : {}),\n ...(t.walk_us !== undefined ? { walkUs: t.walk_us } : {}),\n ...(t.resolve_us !== undefined ? { resolveUs: t.resolve_us } : {}),\n ...(t.first_pass_us !== undefined ? { firstPassUs: t.first_pass_us } : {}),\n ...(t.rescore_us !== undefined ? { rescoreUs: t.rescore_us } : {}),\n ...(t.score_us !== undefined ? { scoreUs: t.score_us } : {}),\n totalUs: t.total_us,\n };\n return {\n path: p.path,\n ...(p.rows_scanned !== undefined ? { rowsScanned: p.rows_scanned } : {}),\n ...(candidates ? { candidates } : {}),\n narrowing: {\n state: p.narrowing.state,\n ...(p.narrowing.candidates !== undefined\n ? { candidates: p.narrowing.candidates }\n : {}),\n },\n timings,\n };\n}\n\n/** An `/aggregate` response, whose sums arrive as tagged {@link Value}s. */\ninterface RawAggregation {\n count: number;\n sums: Record<string, Value>;\n groups?: {\n value: Value | null;\n count: number;\n sums: Record<string, Value>;\n }[];\n groups_truncated?: boolean;\n}\n\n/** A `/search/batch` response: exactly one of the two fields is present. */\ninterface RawBatchSearch {\n results?: RawHit[][];\n fused?: RawHit[];\n}\n\n/** Encode `rankBy` to its externally-tagged wire form, dropping the knobs left unset. */\n/** camelCase → the wire's snake_case, omitting the object entirely when unset. */\nfunction encodeExpand(e: Expand | undefined): unknown {\n if (!e) return undefined;\n return prune({\n radius: e.radius,\n parent_field: e.parentField,\n index_field: e.indexField,\n text_field: e.textField,\n });\n}\n\nfunction encodeRollup(r: Rollup | undefined): unknown {\n if (!r) return undefined;\n return prune({ per_parent: r.perParent, neighbours: r.neighbours });\n}\n\nfunction encodeRankBy(rank: RankBy | undefined): unknown {\n if (!rank) return undefined;\n const d = rank.decay;\n return {\n Decay: prune({\n field: d.field,\n origin: d.origin instanceof Date ? d.origin.getTime() : d.origin,\n scale: d.scale,\n decay: d.decay,\n lambda: d.lambda,\n missing: d.missing,\n count_field: d.countField,\n count_scale: d.countScale,\n count_lambda: d.countLambda,\n }),\n };\n}\n\n/** Encode `highlight`: `true` is the empty object the server reads as \"all defaults\". */\nfunction encodeHighlight(h: boolean | HighlightOptions | undefined): unknown {\n if (h === undefined || h === false) return undefined;\n if (h === true) return {};\n return prune({\n max_fragments: h.maxFragments,\n fragment_chars: h.fragmentChars,\n });\n}\n\n/** Encode `rerank`. Undefined sub-fields drop out at `JSON.stringify`, not here. */\nfunction encodeRerank(r: RerankOptions | undefined): unknown {\n if (r === undefined) return undefined;\n return { query: r.query, overscan: r.overscan, text_attr: r.textAttr };\n}\n\n/** Path-segment encode a collection name (allows slashes/spaces in names). */\nfunction enc(name: string): string {\n return encodeURIComponent(name);\n}\n\n/**\n * Encode one `setFtsSchema` field. A string passes through as the server's bare-name\n * form; an object becomes the snake_case body, pruned so an unset knob keeps the\n * server's default rather than being sent as `undefined`.\n */\nfunction encodeFtsField(f: string | FtsField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n k1: f.k1,\n b: f.b,\n language: f.language,\n ascii_folding: f.asciiFolding,\n max_token_len: f.maxTokenLen,\n });\n}\n\n/**\n * Encode one `setFilterIndex` field, on the same bare-name-or-object rule as\n * {@link encodeFtsField}. Pruning matters here: the server defaults both structures to\n * `true`, so sending an explicit `undefined` would be indistinguishable from `false`.\n */\nfunction encodeFilterIndexField(f: string | FilterIndexField): unknown {\n if (typeof f === \"string\") return f;\n return prune({\n field: f.field,\n tokens: f.tokens,\n trigrams: f.trigrams,\n });\n}\n\n/** Drop `undefined` fields so server `#[serde(default)]`s apply instead. */\nfunction prune(body: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(body)) {\n if (val !== undefined) out[k] = val;\n }\n return out;\n}\n\n/** Pull the `{ \"error\": … }` message out of a failed response, or fall back. */\nfunction extractError(text: string, status: number): string {\n try {\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed.error === \"string\") return parsed.error;\n } catch {\n // not JSON — fall through\n }\n return text || `HTTP ${status}`;\n}\n","//! Filter builder producing the bare predicate-array wire shape.\n//\n// A `Filter` is AND-combined predicates; on the wire it is a plain array. Each\n// predicate is a *positive assertion about a present attribute* — an absent key\n// matches nothing, including the negative predicates (`ne`/`notIn`) and ranges.\n// Comparisons are same-type only (Int↔Int numeric, Float↔Float by IEEE, Str↔Str\n// lexical, Bool↔Bool, DateTime↔DateTime as instants), so an operand's encoded type\n// has to match the attribute's: `ge(\"score\", v.float(2))`, not `ge(\"score\", 2)`.\n\nimport type { AttrInput, Filter, Predicate, Value } from \"./types.js\";\nimport { encodeValue } from \"./values.js\";\n\n/**\n * Predicate constructors. Each accepts a plain JS value (auto-normalized) or an\n * explicit `v.*` {@link Value}. Combine results into a {@link Filter} array, or\n * use {@link f.and} for readability.\n */\nexport const f = {\n /** `attrs[key] === value`. */\n eq: (key: string, value: AttrInput): Predicate => ({\n Eq: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is present and `!== value`. */\n ne: (key: string, value: AttrInput): Predicate => ({\n Ne: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `Str` matching the glob pattern (`*`, `?`, `[..]`). */\n glob: (key: string, pattern: string): Predicate => ({ Glob: [key, pattern] }),\n /**\n * {@link f.glob}, ignoring **ASCII** case on both sides — `\"Src/*\"` matches\n * `\"src/main.rs\"`. Non-ASCII is not folded (`É` does not match `é`).\n */\n iglob: (key: string, pattern: string): Predicate => ({\n IGlob: [key, pattern],\n }),\n /** `attrs[key]` equals one of `values`. */\n in: (key: string, values: AttrInput[]): Predicate => ({\n In: [key, values.map(encodeValue)],\n }),\n /** `attrs[key]` is present and equals none of `values`. */\n notIn: (key: string, values: AttrInput[]): Predicate => ({\n NotIn: [key, values.map(encodeValue)],\n }),\n /** `attrs[key] < value` (same-type, orderable). */\n lt: (key: string, value: AttrInput): Predicate => ({\n Lt: [key, encodeValue(value)],\n }),\n /** `attrs[key] <= value` (same-type, orderable). */\n le: (key: string, value: AttrInput): Predicate => ({\n Le: [key, encodeValue(value)],\n }),\n /** `attrs[key] > value` (same-type, orderable). */\n gt: (key: string, value: AttrInput): Predicate => ({\n Gt: [key, encodeValue(value)],\n }),\n /** `attrs[key] >= value` (same-type, orderable). */\n ge: (key: string, value: AttrInput): Predicate => ({\n Ge: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` containing `value` (whole-element, not substring). */\n contains: (key: string, value: AttrInput): Predicate => ({\n Contains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a present `List` not containing `value`. */\n notContains: (key: string, value: AttrInput): Predicate => ({\n NotContains: [key, encodeValue(value)],\n }),\n /** `attrs[key]` is a `List` sharing at least one element with `values`. */\n containsAny: (key: string, values: AttrInput[]): Predicate => ({\n ContainsAny: [key, values.map(encodeValue)],\n }),\n /** Every sub-predicate holds. `all()` is `true`. */\n all: (...preds: Predicate[]): Predicate => ({ All: preds }),\n /** At least one sub-predicate holds. `any()` is `false`. */\n any: (...preds: Predicate[]): Predicate => ({ Any: preds }),\n /**\n * The sub-predicate does not hold. Differs from {@link f.ne} on an absent key:\n * `not(eq(k, v))` matches a record with no `k`, `ne(k, v)` does not.\n */\n not: (pred: Predicate): Predicate => ({ Not: pred }),\n /**\n * `attrs[key]` is within `maxEdits` Levenshtein edits of `text`, ASCII-case-folded on\n * both sides; a `List` matches if any element does. The only three-element predicate.\n * A `maxEdits` above 8 is refused by the server, not clamped.\n */\n fuzzy: (key: string, text: string, maxEdits: number): Predicate => ({\n Fuzzy: [key, text, maxEdits],\n }),\n /**\n * Every token of `text` appears among `attrs[key]`'s tokens, in any order. Tokens are\n * ASCII-case-folded runs of alphanumerics; a `List` matches if any single element does.\n */\n containsAllTokens: (key: string, text: string): Predicate => ({\n ContainsAllTokens: [key, text],\n }),\n /** At least one token of `text` appears among `attrs[key]`'s tokens. Empty never matches. */\n containsAnyToken: (key: string, text: string): Predicate => ({\n ContainsAnyToken: [key, text],\n }),\n /** `text`'s tokens appear consecutively and in order — a phrase match. */\n containsTokenSequence: (key: string, text: string): Predicate => ({\n ContainsTokenSequence: [key, text],\n }),\n /**\n * `attrs[key]` matches the regular expression, **anchored at both ends** like\n * {@link f.glob} — `.*` opts back into a substring search, and `(?i)` into case folding.\n * The syntax is Rust's `regex`, not JS's: no backreferences and no lookaround.\n */\n regex: (key: string, pattern: string): Predicate => ({ Regex: [key, pattern] }),\n /** Collect predicates into a {@link Filter} (purely sugar — they already AND). */\n and: (...preds: Predicate[]): Filter => preds,\n} as const;\n\n// Aliases for the comparison operators, for callers who prefer them.\nexport type { Filter, Predicate, Value };\n"],"mappings":"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","names":["f"]}
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duckedup/nidus",
3
- "version": "0.89.0",
3
+ "version": "0.91.0",
4
4
  "description": "JavaScript/TypeScript client for nidus — a small, fast vector store. Connects to a local or remote `nidus serve` over HTTP.",
5
5
  "type": "module",
6
6
  "license": "MIT",