New:Socket for Asana Is Now Available.Learn more
Sign In

@oscardvs/zoteus

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@oscardvs/zoteus - npm Package Compare versions

Comparing version
1.1.0
to
1.2.0
+76
dist/api/connector-writes.d.ts
import { RateLimitedFetcher } from './http.js';
import type { Logger } from '../lib/logger.js';
export interface ConnectorWriteClientOptions {
port?: number;
fetcher?: RateLimitedFetcher;
logger?: Logger;
}
export interface SaveTarget {
id: string;
name: string;
level?: number;
}
/**
* Write client for the Zotero desktop connector API (available on Zotero 7+ while
* the app is running, including versions whose local API is still read-only).
*
* This is the same protocol the browser connectors use:
* - `POST /connector/saveItems` saves items through Zotero's ItemSaver. Items may
* carry a client-chosen `id` ("connector key") that later calls use to reference
* them.
* - `POST /connector/saveAttachment` streams file bytes (X-Metadata header with
* sessionID/parentItemID/url/title) into a stored attachment under a session item.
* - `POST /connector/updateSession` re-targets a session: moves already-saved items
* to another collection (treeViewID), applies tags, and can attach a note.
*
* Limitations vs the cloud Web API: no updates/deletes, no response payload (created
* keys must be recovered by querying the local API afterwards), and saves land in the
* personal library only.
*/
export declare class ConnectorWriteClient {
private readonly base;
private readonly fetcher;
private readonly logger?;
constructor(opts?: ConnectorWriteClientOptions);
private jsonHeaders;
private newSessionId;
ping(): Promise<boolean>;
/**
* Save items (metadata, notes, or annotations with `parentItem`) and open a session
* for follow-up calls. Each item gets a connector `id` (returned alongside) that
* `saveAttachment` uses as `parentItemID`.
*/
saveItems(items: Record<string, unknown>[], opts?: {
uri?: string;
sessionID?: string;
}): Promise<{
sessionID: string;
connectorIds: string[];
}>;
/**
* Re-target a session: moves its saved items to `target` (a treeViewID like "L1" or
* "C20"), applies `tags`, and optionally attaches `note` to each item.
*/
updateSession(sessionID: string, opts?: {
target?: string;
tags?: string[];
note?: string;
}): Promise<void>;
/**
* Stream file bytes into a stored attachment under an item saved in this session.
* `url` is recorded as the attachment's source URL (it is NOT fetched by Zotero).
*/
saveAttachment(opts: {
sessionID: string;
parentConnectorId: string;
url: string;
title?: string;
bytes: Uint8Array;
contentType: string;
}): Promise<void>;
/** Current save target + full list of selectable targets (library and collections). */
getSelectedCollection(): Promise<{
current: string;
targets: SaveTarget[];
}>;
}
import { randomBytes } from 'node:crypto';
import { RateLimitedFetcher } from './http.js';
/**
* Write client for the Zotero desktop connector API (available on Zotero 7+ while
* the app is running, including versions whose local API is still read-only).
*
* This is the same protocol the browser connectors use:
* - `POST /connector/saveItems` saves items through Zotero's ItemSaver. Items may
* carry a client-chosen `id` ("connector key") that later calls use to reference
* them.
* - `POST /connector/saveAttachment` streams file bytes (X-Metadata header with
* sessionID/parentItemID/url/title) into a stored attachment under a session item.
* - `POST /connector/updateSession` re-targets a session: moves already-saved items
* to another collection (treeViewID), applies tags, and can attach a note.
*
* Limitations vs the cloud Web API: no updates/deletes, no response payload (created
* keys must be recovered by querying the local API afterwards), and saves land in the
* personal library only.
*/
export class ConnectorWriteClient {
base;
fetcher;
logger;
constructor(opts = {}) {
this.base = `http://127.0.0.1:${opts.port ?? 23119}`;
this.fetcher = opts.fetcher ?? new RateLimitedFetcher();
this.logger = opts.logger;
}
jsonHeaders() {
return {
'Content-Type': 'application/json',
'x-zotero-connector-api-version': '3',
'x-zotero-connector-version': '5.0.125',
};
}
newSessionId() {
return `zoteus-${Date.now().toString(36)}-${randomBytes(4).toString('hex')}`;
}
async ping() {
try {
const res = await this.fetcher.fetch(`${this.base}/connector/ping`, { method: 'GET' }, { maxRetries: 0 });
const text = await res.text().catch(() => '');
return res.ok && /zotero is running/i.test(text);
}
catch {
return false;
}
}
/**
* Save items (metadata, notes, or annotations with `parentItem`) and open a session
* for follow-up calls. Each item gets a connector `id` (returned alongside) that
* `saveAttachment` uses as `parentItemID`.
*/
async saveItems(items, opts = {}) {
const sessionID = opts.sessionID ?? this.newSessionId();
const connectorIds = items.map((_, i) => `${sessionID}-${i}`);
const payload = {
uri: opts.uri ?? 'zotero://zoteus/session/' + sessionID,
sessionID,
items: items.map((it, i) => ({ id: connectorIds[i], ...it })),
};
const res = await this.fetcher.fetch(`${this.base}/connector/saveItems`, { method: 'POST', headers: this.jsonHeaders(), body: JSON.stringify(payload) }, { maxRetries: 0, deadlineMs: 120_000 });
const text = await res.text().catch(() => '');
if (res.status === 409) {
// Session id collision — retry once with a fresh id.
if (!opts.sessionID)
return this.saveItems(items, { ...opts, sessionID: this.newSessionId() });
throw new Error(`Connector save session exists: ${text}`);
}
if (!res.ok && res.status !== 201) {
throw new Error(`Connector saveItems failed (HTTP ${res.status}): ${text.slice(0, 300)}`);
}
this.logger?.info(`Connector session ${sessionID}: saved ${items.length} item(s).`);
return { sessionID, connectorIds };
}
/**
* Re-target a session: moves its saved items to `target` (a treeViewID like "L1" or
* "C20"), applies `tags`, and optionally attaches `note` to each item.
*/
async updateSession(sessionID, opts = {}) {
const body = { sessionID };
if (opts.target)
body.target = opts.target;
if (opts.tags)
body.tags = opts.tags;
if (opts.note !== undefined)
body.note = opts.note;
const res = await this.fetcher.fetch(`${this.base}/connector/updateSession`, { method: 'POST', headers: this.jsonHeaders(), body: JSON.stringify(body) }, { maxRetries: 0, deadlineMs: 60_000 });
const text = await res.text().catch(() => '');
if (!res.ok)
throw new Error(`Connector updateSession failed (HTTP ${res.status}): ${text.slice(0, 300)}`);
if (/COLLECTION_NOT_FOUND|SESSION_NOT_FOUND/.test(text)) {
throw new Error(`Connector updateSession rejected: ${text}`);
}
}
/**
* Stream file bytes into a stored attachment under an item saved in this session.
* `url` is recorded as the attachment's source URL (it is NOT fetched by Zotero).
*/
async saveAttachment(opts) {
const metadata = {
sessionID: opts.sessionID,
parentItemID: opts.parentConnectorId,
url: opts.url,
title: opts.title ?? 'Full Text PDF',
};
const bodyInit = opts.bytes;
const res = await this.fetcher.fetch(`${this.base}/connector/saveAttachment`, {
method: 'POST',
headers: {
...this.jsonHeaders(),
'Content-Type': opts.contentType,
'X-Metadata': JSON.stringify(metadata),
},
body: bodyInit,
}, { maxRetries: 0, deadlineMs: 300_000 });
const text = await res.text().catch(() => '');
if (!res.ok && res.status !== 201) {
throw new Error(`Connector saveAttachment failed (HTTP ${res.status}): ${text.slice(0, 300)}`);
}
if (/not editable/i.test(text))
throw new Error(`Zotero refused the file: ${text}`);
this.logger?.info(`Connector session ${opts.sessionID}: attached ${opts.bytes.length} bytes (${opts.contentType}).`);
}
/** Current save target + full list of selectable targets (library and collections). */
async getSelectedCollection() {
const res = await this.fetcher.fetch(`${this.base}/connector/getSelectedCollection`, { method: 'POST', headers: this.jsonHeaders(), body: '{}' }, { maxRetries: 0 });
const json = (await res.json().catch(() => ({})));
return {
current: typeof json.id === 'string' ? json.id : String(json.id ?? ''),
targets: Array.isArray(json.targets) ? json.targets : [],
};
}
}
//# sourceMappingURL=connector-writes.js.map
{"version":3,"file":"connector-writes.js","sourceRoot":"","sources":["../../src/api/connector-writes.ts"],"names":[],"mappings":"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"}
import { RateLimitedFetcher } from './http.js';
import type { WriteResult } from './web-client.js';
import type { Logger } from '../lib/logger.js';
export interface LocalWriteClientOptions {
/** Zotero desktop local-API port (default 23119). */
port?: number;
fetcher?: RateLimitedFetcher;
logger?: Logger;
/** Where the granted local-API key is cached (default: <dataDir>/local-api-key.json). */
keyStorePath?: string;
/** Pre-provisioned local API key (ZOTEUS_LOCAL_API_KEY); skips the authorize prompt. */
key?: string;
/** App name shown in Zotero's grant dialog. */
appName?: string;
}
/**
* Write client for the Zotero 9+ desktop local API.
*
* Zotero >= 9 accepts writes (POST/PATCH/DELETE) on the same local API the reads use
* (http://127.0.0.1:23119/api/users/0/...), gated by a *local* API key that the user
* grants through a one-time in-Zotero dialog:
*
* 1. Every response carries a `Zotero-Server-ID` header; writes must echo it back
* (428 when missing, 412 when it no longer matches the running instance).
* 2. `POST /api/local/authorize` with `{"appName": "..."}` shows a dialog in Zotero
* ("Allow" / "Always Allow" / "Deny") and returns `{key, remember}`.
* 3. Writes then carry `Zotero-API-Key: <key>`. A single-use key is consumed by the
* first successful write, so a 401 means: re-authorize.
*
* Keys are unrelated to zotero.org cloud keys. Grants are cached on disk so the user
* is prompted once ("Always Allow"); single-use "Allow" grants degrade gracefully by
* re-prompting on the next write.
*/
export declare class LocalWriteClient {
private readonly base;
private readonly fetcher;
private readonly logger?;
private readonly keyStorePath?;
private readonly appName;
private key?;
private serverId?;
constructor(opts?: LocalWriteClientOptions);
/**
* True when a local-API key is already available (env-provided or cached from a
* previous "Always Allow" grant) — i.e. writes can proceed without prompting.
*/
hasStoredKey(): boolean;
/** Stable ID of the running Zotero instance (required on every write). */
getServerId(): Promise<string>;
/**
* Ask Zotero to grant this app a local API key. Blocks until the user answers the
* dialog in Zotero ("Always Allow" recommended). Returns the key, or throws with a
* human-readable reason on denial/error.
*/
authorize(): Promise<string>;
private readHeaders;
private writeHeaders;
private loadGrant;
private storeGrant;
private ensureKey;
/**
* Run a write request against the local API, transparently handling the two
* re-auth/re-probe cases: 401 (key consumed/unknown -> authorize again) and
* 412/428 (server-id stale/missing -> refresh it).
*/
private request;
/** Multi-write (create/update) up to 50 items, mirroring the Web API semantics. */
writeItems(items: Record<string, unknown>[]): Promise<WriteResult>;
/** Partial single-item update. */
patchItem(key: string, patch: Record<string, unknown>): Promise<number>;
/** Trash items by key (permanent=false, the default) or delete permanently. */
deleteItems(keys: string[], permanent?: boolean): Promise<void>;
/**
* Store a file on a (child) attachment item using the Web-API 3-phase upload flow,
* which the local API re-implements: authorize -> POST bytes to the returned URL ->
* register the uploadKey.
*/
uploadFile(attachmentKey: string, file: {
bytes: Uint8Array;
filename: string;
contentType: string;
mtimeMs?: number;
}): Promise<void>;
private parseWriteResult;
private throwApi;
}
import { createHash } from 'node:crypto';
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
import { dirname } from 'node:path';
import { RateLimitedFetcher } from './http.js';
import { ZoteroApiError } from './errors.js';
/**
* Write client for the Zotero 9+ desktop local API.
*
* Zotero >= 9 accepts writes (POST/PATCH/DELETE) on the same local API the reads use
* (http://127.0.0.1:23119/api/users/0/...), gated by a *local* API key that the user
* grants through a one-time in-Zotero dialog:
*
* 1. Every response carries a `Zotero-Server-ID` header; writes must echo it back
* (428 when missing, 412 when it no longer matches the running instance).
* 2. `POST /api/local/authorize` with `{"appName": "..."}` shows a dialog in Zotero
* ("Allow" / "Always Allow" / "Deny") and returns `{key, remember}`.
* 3. Writes then carry `Zotero-API-Key: <key>`. A single-use key is consumed by the
* first successful write, so a 401 means: re-authorize.
*
* Keys are unrelated to zotero.org cloud keys. Grants are cached on disk so the user
* is prompted once ("Always Allow"); single-use "Allow" grants degrade gracefully by
* re-prompting on the next write.
*/
export class LocalWriteClient {
base;
fetcher;
logger;
keyStorePath;
appName;
key;
serverId;
constructor(opts = {}) {
this.base = `http://127.0.0.1:${opts.port ?? 23119}/api`;
this.fetcher = opts.fetcher ?? new RateLimitedFetcher();
this.logger = opts.logger;
this.keyStorePath = opts.keyStorePath;
this.appName = opts.appName ?? 'Zoteus MCP';
this.key = opts.key;
}
/**
* True when a local-API key is already available (env-provided or cached from a
* previous "Always Allow" grant) — i.e. writes can proceed without prompting.
*/
hasStoredKey() {
if (this.key)
return true;
return Boolean(this.loadGrant()?.key);
}
/** Stable ID of the running Zotero instance (required on every write). */
async getServerId() {
if (this.serverId)
return this.serverId;
const res = await this.fetcher.fetch(`${this.base}/users/0/items?limit=1`, { method: 'GET', headers: this.readHeaders() }, { maxRetries: 0 });
if (!res.ok)
throw new Error(`Local API unreachable (HTTP ${res.status}) — is Zotero running?`);
const id = res.headers.get('zotero-server-id');
await res.body?.cancel().catch(() => { });
if (!id)
throw new Error('Local API did not return a Zotero-Server-ID header (Zotero >= 9 required for writes).');
this.serverId = id;
return id;
}
/**
* Ask Zotero to grant this app a local API key. Blocks until the user answers the
* dialog in Zotero ("Always Allow" recommended). Returns the key, or throws with a
* human-readable reason on denial/error.
*/
async authorize() {
this.logger?.info(`Requesting local API write access from Zotero (appName="${this.appName}")…`);
const res = await this.fetcher.fetch(`${this.base}/local/authorize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Zotero-API-Version': '3' },
body: JSON.stringify({ appName: this.appName }),
}, { maxRetries: 0, deadlineMs: 300_000 });
const text = await res.text().catch(() => '');
if (res.status === 403) {
throw new Error('Zotero local write access was denied. Re-run when you can accept the dialog in Zotero.');
}
if (res.status === 429) {
throw new Error('Too many local-API authorization prompts; wait a minute and try again.');
}
if (!res.ok) {
throw new Error(`Local API authorize failed (HTTP ${res.status}): ${text || res.statusText}. ` +
'Writes need Zotero 9+ with the local API enabled.');
}
const { key, remember } = JSON.parse(text);
this.key = key;
this.storeGrant({ key, appName: this.appName, serverId: this.serverId, remember, grantedAt: new Date().toISOString() });
this.logger?.info(`Local API write access granted (remember=${!!remember}).`);
return key;
}
readHeaders() {
return { 'Zotero-API-Version': '3', 'x-zotero-connector-api-version': '3' };
}
async writeHeaders() {
return {
...this.readHeaders(),
'Zotero-API-Key': this.key ?? (await this.authorize()),
'Zotero-Server-ID': await this.getServerId(),
};
}
loadGrant() {
if (!this.keyStorePath)
return null;
try {
return JSON.parse(readFileSync(this.keyStorePath, 'utf8'));
}
catch {
return null;
}
}
storeGrant(grant) {
if (!this.keyStorePath)
return;
try {
mkdirSync(dirname(this.keyStorePath), { recursive: true });
writeFileSync(this.keyStorePath, JSON.stringify(grant, null, 2));
}
catch (e) {
this.logger?.warn(`Could not persist local API grant: ${e}`);
}
}
async ensureKey() {
if (this.key)
return;
const grant = this.loadGrant();
if (grant?.key) {
this.key = grant.key;
this.serverId = this.serverId ?? grant.serverId;
}
}
/**
* Run a write request against the local API, transparently handling the two
* re-auth/re-probe cases: 401 (key consumed/unknown -> authorize again) and
* 412/428 (server-id stale/missing -> refresh it).
*/
async request(method, path, init = {}, retried = false) {
await this.ensureKey();
if (!this.key)
await this.authorize();
const headers = await this.writeHeaders();
if (init.json !== undefined) {
headers['Content-Type'] = 'application/json';
}
else if (init.form) {
headers['Content-Type'] = 'application/x-www-form-urlencoded';
}
const res = await this.fetcher.fetch(`${this.base}${path}`, {
method,
headers: { ...headers, ...init.headers },
body: init.json !== undefined ? JSON.stringify(init.json) : init.form?.toString(),
}, { maxRetries: 0, deadlineMs: 120_000 });
if (res.status === 401 && !retried) {
this.logger?.info('Local API key rejected (401); requesting a fresh grant from Zotero…');
this.key = undefined;
await this.authorize();
return this.request(method, path, init, true);
}
if ((res.status === 412 || res.status === 428) && !retried) {
this.serverId = undefined;
await res.body?.cancel().catch(() => { });
return this.request(method, path, init, true);
}
return res;
}
/** Multi-write (create/update) up to 50 items, mirroring the Web API semantics. */
async writeItems(items) {
const res = await this.request('POST', '/users/0/items', { json: items });
return this.parseWriteResult(res);
}
/** Partial single-item update. */
async patchItem(key, patch) {
const res = await this.request('PATCH', `/users/0/items/${key}`, { json: patch });
if (!res.ok)
await this.throwApi(res, `PATCH /items/${key}`);
const v = Number(res.headers.get('last-modified-version'));
await res.body?.cancel().catch(() => { });
return Number.isFinite(v) ? v : 0;
}
/** Trash items by key (permanent=false, the default) or delete permanently. */
async deleteItems(keys, permanent = false) {
const path = `/users/0/items${permanent ? '/deleted' : ''}?itemKey=${keys.join(',')}`;
const res = await this.request('DELETE', path);
if (!res.ok && res.status !== 204)
await this.throwApi(res, `DELETE ${path}`);
await res.body?.cancel().catch(() => { });
}
/**
* Store a file on a (child) attachment item using the Web-API 3-phase upload flow,
* which the local API re-implements: authorize -> POST bytes to the returned URL ->
* register the uploadKey.
*/
async uploadFile(attachmentKey, file) {
const md5 = createHash('md5').update(file.bytes).digest('hex');
const mtime = file.mtimeMs ?? Date.now();
const authorize = await this.request('POST', `/users/0/items/${attachmentKey}/file`, {
form: new URLSearchParams({
md5,
filename: file.filename,
filesize: String(file.bytes.length),
mtime: String(mtime),
contentType: file.contentType,
}),
headers: { 'If-None-Match': '*' },
});
if (!authorize.ok)
await this.throwApi(authorize, `authorize upload for ${attachmentKey}`);
const auth = (await authorize.json());
if (auth.exists)
return; // identical file already stored
if (!auth.url || !auth.uploadKey)
throw new Error('Local API did not return an upload URL.');
const bodyInit = file.bytes;
const up = await this.fetcher.fetch(auth.url, {
method: 'POST',
headers: { 'Content-Type': 'application/octet-stream' },
body: bodyInit,
}, { maxRetries: 0, deadlineMs: 300_000 });
if (!up.ok)
await this.throwApi(up, 'file-bytes upload');
await up.body?.cancel().catch(() => { });
const register = await this.request('POST', `/users/0/items/${attachmentKey}/file`, {
form: new URLSearchParams({ upload: auth.uploadKey }),
headers: { 'If-None-Match': '*' },
});
if (!register.ok && register.status !== 204)
await this.throwApi(register, 'register upload');
await register.body?.cancel().catch(() => { });
}
async parseWriteResult(res) {
if (!res.ok)
await this.throwApi(res, 'local write');
const json = (await res.json().catch(() => ({})));
const successful = [];
for (const [idx, obj] of Object.entries(json.successful ?? {})) {
successful.push({ index: Number(idx), key: obj.key, version: obj.version });
}
const failed = [];
for (const [idx, obj] of Object.entries(json.failed ?? {})) {
failed.push({ index: Number(idx), code: obj.code ?? 0, message: obj.message ?? 'write failed', key: obj.key });
}
return {
successful,
unchanged: Object.keys(json.unchanged ?? {}),
failed,
newLibraryVersion: Number(res.headers.get('last-modified-version')) || 0,
};
}
async throwApi(res, what) {
const body = await res.text().catch(() => '');
throw new ZoteroApiError({ status: res.status, message: `Local API ${what} failed (${res.status}): ${body.slice(0, 400)}`, body });
}
}
//# sourceMappingURL=local-writes.js.map
{"version":3,"file":"local-writes.js","sourceRoot":"","sources":["../../src/api/local-writes.ts"],"names":[],"mappings":"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"}
import type { ToolContext } from '../../registry/registry.js';
import type { LibraryRef } from '../../api/web-client.js';
import type { IndexBuildStatus } from './index-manager.js';
/** Hard cap on items per build — keeps very large libraries bounded. */
export declare const MAX_ITEMS = 5000;
/** The Zotero Web API pages items 100-at-a-time. */
export declare const PAGE_SIZE = 100;
/** One-line progress summary used in tool messages and status output. */
export declare function progressLine(s: IndexBuildStatus): string;
/** Human summary of a build/status snapshot. */
export declare function statusSummary(s: IndexBuildStatus): string;
/**
* Kick off the incremental background index build used by zotero_index and by
* zotero_semantic_search's auto-build. Fire-and-forget: the build runs on the
* server event loop; callers poll `ctx.search.buildStatus()` for progress.
* Throws if a build is already running.
*/
export declare function startIndexBuild(ctx: ToolContext, lib?: LibraryRef, maxItems?: number): IndexBuildStatus;
import { saveIndex } from './persistence.js';
/** Hard cap on items per build — keeps very large libraries bounded. */
export const MAX_ITEMS = 5000;
/** The Zotero Web API pages items 100-at-a-time. */
export const PAGE_SIZE = 100;
/** One-line progress summary used in tool messages and status output. */
export function progressLine(s) {
const total = s.itemsTotal > 0 ? String(s.itemsTotal) : '?';
return `${s.itemsFetched}/${total} items, ${s.passages} passages, ${s.vectors} vectors (embedder=${s.embedder})`;
}
/** Human summary of a build/status snapshot. */
export function statusSummary(s) {
switch (s.state) {
case 'building':
return `Index build in progress — ${progressLine(s)}. Poll zotero_index action:"status" again shortly.`;
case 'error':
return `Index build failed: ${s.lastError ?? 'unknown error'}. Partial data kept — ${progressLine(s)}.`;
case 'done':
return `Index ready — ${s.documents} passages over ${s.items} items (embedder=${s.embedder}). Run zotero_semantic_search to search by meaning.`;
default:
return `Index: ${s.documents} passages over ${s.items} items; embedder=${s.embedder}.`;
}
}
/**
* Kick off the incremental background index build used by zotero_index and by
* zotero_semantic_search's auto-build. Fire-and-forget: the build runs on the
* server event loop; callers poll `ctx.search.buildStatus()` for progress.
* Throws if a build is already running.
*/
export function startIndexBuild(ctx, lib, maxItems = MAX_ITEMS) {
const library = lib ?? ctx.router.defaultLibrary();
const cap = Math.min(maxItems, MAX_ITEMS);
const fetchPage = async (start) => {
const page = await ctx.web.listItems(library, { limit: PAGE_SIZE, start, top: true });
return { items: page.data, totalResults: page.totalResults };
};
const persist = ctx.searchIndexPath
? () => saveIndex(ctx.search, ctx.searchIndexPath).catch((e) => ctx.logger.warn(`Could not persist index: ${e instanceof Error ? e.message : String(e)}`))
: undefined;
const job = ctx.search.buildIncremental(fetchPage, { maxItems: cap, persist });
job.catch((e) => ctx.logger.error(`Index build crashed: ${e instanceof Error ? e.message : String(e)}`));
return ctx.search.buildStatus();
}
//# sourceMappingURL=build.js.map
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/features/search/build.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,wEAAwE;AACxE,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC;AAC9B,oDAAoD;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAE7B,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,CAAmB;IAC9C,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5D,OAAO,GAAG,CAAC,CAAC,YAAY,IAAI,KAAK,WAAW,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,OAAO,sBAAsB,CAAC,CAAC,QAAQ,GAAG,CAAC;AACnH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,aAAa,CAAC,CAAmB;IAC/C,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAChB,KAAK,UAAU;YACb,OAAO,6BAA6B,YAAY,CAAC,CAAC,CAAC,oDAAoD,CAAC;QAC1G,KAAK,OAAO;YACV,OAAO,uBAAuB,CAAC,CAAC,SAAS,IAAI,eAAe,yBAAyB,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1G,KAAK,MAAM;YACT,OAAO,iBAAiB,CAAC,CAAC,SAAS,kBAAkB,CAAC,CAAC,KAAK,oBAAoB,CAAC,CAAC,QAAQ,qDAAqD,CAAC;QAClJ;YACE,OAAO,UAAU,CAAC,CAAC,SAAS,kBAAkB,CAAC,CAAC,KAAK,oBAAoB,CAAC,CAAC,QAAQ,GAAG,CAAC;IAC3F,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAgB,EAAE,GAAgB,EAAE,QAAQ,GAAG,SAAS;IACtF,MAAM,OAAO,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,KAAK,EAAE,KAAa,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QACtF,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;IAC/D,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe;QACjC,CAAC,CAAC,GAAG,EAAE,CACH,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CACrD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1F;QACL,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/E,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzG,OAAO,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC"}
import type { ToolDefinition } from '../registry/registry.js';
/**
* Normalize a caller-supplied position into Zotero's stored form:
* {"pageIndex": <0-based page>, "rects": [[x1, y1, x2, y2], ...]}
* Points, origin at the BOTTOM-LEFT of the page (native PDF coordinate space, y
* increasing upward). Accepts
* either that object directly (or its JSON string) or the shorthand
* [pageIndex, [x1, y1, x2, y2]].
*/
export declare function normalizePosition(position: unknown, page?: number): {
pageIndex: number;
rects: number[][];
} | null;
/**
* Replicates the PDF reader's sort-index scheme so annotations order correctly in
* the sidebar: `PPPPP|OOOOOO|TTTTT` (5-digit page | 6-digit char offset | 5-digit
* distance of the topmost rect from the page bottom). Callers that extracted the
* highlight from the PDF itself can pass the exact offset; otherwise offset 0 with
* the rect-derived `top` still keeps same-page highlights in reading order.
*/
export declare function buildSortIndex(pageIndex: number, rects: number[][], opts?: {
offset?: number;
pageHeight?: number;
}): string;
declare const annotateTool: ToolDefinition;
export default annotateTool;
import { z } from 'zod';
import { ok, requireCloudLibrary, isLocalWritesUnavailable, ensureLocalApi } from '../registry/registry.js';
/**
* Normalize a caller-supplied position into Zotero's stored form:
* {"pageIndex": <0-based page>, "rects": [[x1, y1, x2, y2], ...]}
* Points, origin at the BOTTOM-LEFT of the page (native PDF coordinate space, y
* increasing upward). Accepts
* either that object directly (or its JSON string) or the shorthand
* [pageIndex, [x1, y1, x2, y2]].
*/
export function normalizePosition(position, page) {
if (position == null) {
return page != null ? { pageIndex: page, rects: [] } : null;
}
if (typeof position === 'string') {
try {
return normalizePosition(JSON.parse(position), page);
}
catch {
return null;
}
}
if (Array.isArray(position) && position.length === 2 && typeof position[0] === 'number') {
const rect = position[1];
if (Array.isArray(rect) && rect.length === 4 && rect.every((n) => typeof n === 'number')) {
return { pageIndex: position[0], rects: [rect] };
}
return null;
}
const p = position;
if (typeof p.pageIndex === 'number' && Array.isArray(p.rects)) {
const rects = p.rects.filter((r) => Array.isArray(r) && r.length === 4 && r.every((n) => typeof n === 'number'));
return { pageIndex: p.pageIndex, rects };
}
return null;
}
/**
* Replicates the PDF reader's sort-index scheme so annotations order correctly in
* the sidebar: `PPPPP|OOOOOO|TTTTT` (5-digit page | 6-digit char offset | 5-digit
* distance of the topmost rect from the page bottom). Callers that extracted the
* highlight from the PDF itself can pass the exact offset; otherwise offset 0 with
* the rect-derived `top` still keeps same-page highlights in reading order.
*/
export function buildSortIndex(pageIndex, rects, opts = {}) {
const pad = (n, w) => String(Math.max(0, Math.floor(n))).slice(0, w).padStart(w, '0');
let top = 0;
if (rects.length && opts.pageHeight) {
// Topmost rect: the reader sorts rects by their third coordinate descending
// and takes the first; mirror that exactly.
const topRect = rects.slice().sort((a, b) => (b[2] ?? 0) - (a[2] ?? 0))[0] ?? [0, 0, 0, 0];
top = Math.max(0, opts.pageHeight - (topRect[3] ?? 0));
}
return `${pad(pageIndex, 5)}|${pad(opts.offset ?? 0, 6)}|${pad(Math.floor(top), 5)}`;
}
const annotationSchema = z.object({
type: z.enum(['highlight', 'note', 'underline', 'image']).optional()
.describe('Annotation type; default "highlight".'),
text: z.string().optional()
.describe('The highlighted/underlined passage itself (required for highlight/underline). For notes, goes in annotationText of an extracted-text style note or leave to `comment`.'),
comment: z.string().optional().describe('Comment attached to the annotation (markdown-ish plain text).'),
color: z.string().optional().describe('Hex color, e.g. "#ffd400" (highlight default) or "#26a69a".'),
page: z.number().int().optional().describe('0-based PDF page index (annotationPageLabel uses page+1 when unset).'),
page_label: z.string().optional().describe('Explicit page label (overrides page+1).'),
position: z.union([z.string(), z.any()]).optional()
.describe('Zotero position: {"pageIndex": N, "rects": [[x1,y1,x2,y2],...]} (points, bottom-left origin), its JSON string, or shorthand [N, [x1,y1,x2,y2]]. Required for highlights/underlines to render in place.'),
sort_index: z.string().optional().describe('Explicit annotationSortIndex; computed from position when omitted.'),
char_offset: z.number().int().optional().describe('Reading-order character offset of the passage start on the page (refines sort_index).'),
page_height: z.number().optional().describe('Page height in points (refines sort_index, e.g. 841.89 for A4).'),
tags: z.array(z.string()).optional().describe('Tags to attach to the annotation.'),
});
const annotateTool = {
name: 'zotero_annotate',
title: 'Annotate a PDF (highlights, notes)',
description: 'Add or delete Zotero PDF annotations (highlights, underlines, notes) — the same objects you create in the Zotero PDF reader. `action:"add"` needs `parent` (a regular item key OR a PDF attachment key) and `annotations`: each with `type` (highlight|note|underline, default highlight), `text` (the exact highlighted passage), optional `comment`, `color`, `page` (0-based page index), and `position` ({"pageIndex":N,"rects":[[x1,y1,x2,y2],...]} in PDF points with bottom-left origin — without a position a highlight cannot render in place). `action:"delete"` trashes the annotations in `annotation_keys`. Writes go to the running Zotero desktop app for your personal library (via its connector protocol, or its local-API writes where available), otherwise to the cloud Web API.',
inputSchema: {
action: z.enum(['add', 'delete']).optional().describe('Default "add".'),
parent: z.string().optional().describe('Item key or PDF attachment key to annotate.'),
annotations: z.array(annotationSchema).optional().describe('Annotations to add.'),
annotation_keys: z.array(z.string()).optional().describe('Annotation keys to trash (action:"delete").'),
library_type: z.enum(['user', 'group']).optional(),
library_id: z.number().int().optional(),
},
annotations: { readOnlyHint: false, openWorldHint: true },
handler: async (args, ctx) => {
const action = args.action ?? 'add';
if (action === 'delete') {
const keys = args.annotation_keys ?? [];
if (!keys.length) {
return { content: [{ type: 'text', text: '`annotation_keys` is required for action:"delete".' }], isError: true };
}
if (!args.library_id && (await ensureLocalApi(ctx)) && ctx.localWrites) {
try {
await ctx.localWrites.deleteItems(keys, false);
return ok({ trashed: keys, target: 'local' }, `Trashed ${keys.length} annotation(s) via the Zotero desktop app.`);
}
catch (e) {
if (!isLocalWritesUnavailable(e))
throw e;
// Running Zotero has no local-API writes; fall through to cloud/guidance.
}
}
if (ctx.capabilities.cloud) {
const lib = requireCloudLibrary(ctx, args);
const objects = [];
for (const key of keys) {
const item = await ctx.web.getItem(lib, key);
objects.push({ key, version: item?.version ?? item?.data?.version, deleted: 1 });
}
const result = await ctx.web.writeItems(lib, objects);
return ok({ trashed: result.successful.map((s) => s.key), failed: result.failed, target: 'cloud' }, `Trashed ${result.successful.length} annotation(s) via the cloud Web API.`);
}
return {
content: [{
type: 'text',
text: 'Deleting annotations needs write access this Zotero cannot grant yet: the running app\u2019s local API is read-only (Zotero < 9.1) and the connector protocol cannot delete. Set ZOTERO_API_KEY for cloud writes, upgrade Zotero when local writes ship, or delete the annotations manually in Zotero\u2019s PDF reader.',
}],
isError: true,
};
}
// --- add ---
if (!args.parent) {
return { content: [{ type: 'text', text: '`parent` (item key or PDF attachment key) is required for action:"add".' }], isError: true };
}
const parentKey = args.parent;
const anns = args.annotations ?? [];
if (!anns.length) {
return { content: [{ type: 'text', text: '`annotations` must contain at least one entry.' }], isError: true };
}
// Resolve the PDF attachment: the parent may be the attachment itself or any
// regular item whose children include a stored/linked PDF.
const parentItem = await ctx.router.getItem(parentKey);
const parentData = parentItem?.data ?? parentItem;
let attachmentKey;
if (parentData?.itemType === 'attachment') {
attachmentKey = parentData.key ?? parentKey;
}
else {
const children = await ctx.router.getItemChildren(parentKey);
const pdf = children.data
.map((c) => c?.data ?? c)
.filter((c) => c?.itemType === 'attachment')
.sort((a, b) => scorePdf(b) - scorePdf(a))[0];
attachmentKey = pdf?.key;
if (!attachmentKey) {
return {
content: [{ type: 'text', text: `No PDF attachment found under item ${parentKey}. Add the PDF first (or pass the attachment key directly).` }],
isError: true,
};
}
}
if (!attachmentKey) {
return { content: [{ type: 'text', text: 'Could not resolve a PDF attachment.' }], isError: true };
}
const targetAttachment = attachmentKey;
// Build annotation items in Zotero's data model.
const items = [];
const problems = [];
anns.forEach((a, i) => {
const type = a.type ?? 'highlight';
if ((type === 'highlight' || type === 'underline') && !a.text) {
problems.push(`annotations[${i}]: ${type} requires \`text\` (the exact passage).`);
return;
}
const pos = normalizePosition(a.position, a.page);
if ((type === 'highlight' || type === 'underline') && !pos?.rects?.length) {
problems.push(`annotations[${i}]: ${type} needs \`position\` ({"pageIndex":N,"rects":[[x1,y1,x2,y2],...]}) to render in place.`);
return;
}
const pageIndex = pos?.pageIndex ?? a.page ?? 0;
const item = {
itemType: 'annotation',
parentItem: targetAttachment,
annotationType: type,
annotationColor: a.color ?? (type === 'note' ? '#26a69a' : '#ffd400'),
annotationSortIndex: a.sort_index ?? buildSortIndex(pageIndex, pos?.rects ?? [], { offset: a.char_offset, pageHeight: a.page_height }),
annotationPosition: JSON.stringify(pos ?? { pageIndex, rects: [] }),
tags: (a.tags ?? []).map((t) => ({ tag: t })),
};
if (a.text)
item.annotationText = a.text;
if (a.comment)
item.annotationComment = a.comment;
const label = a.page_label ?? String(pageIndex + 1);
if (label)
item.annotationPageLabel = label;
items.push(item);
});
if (problems.length) {
return { content: [{ type: 'text', text: `Nothing was written:\n- ${problems.join('\n- ')}` }], isError: true };
}
// Prefer the desktop app for the personal library; fall back to the cloud.
// (a) Zotero with local-API write support (upcoming; needs a stored/provided key —
// we never trigger the grant dialog unexpectedly), or (b) the connector protocol
// that every recent Zotero exposes while running.
if (!args.library_id && (await ensureLocalApi(ctx)) && ctx.localWrites) {
try {
const result = await ctx.localWrites.writeItems(items);
if (result.failed.length) {
return { content: [{ type: 'text', text: `Local write failed: ${JSON.stringify(result.failed)}` }], isError: true };
}
return ok({
target: 'local',
attachment: targetAttachment,
created: result.successful.map((s, i) => ({ key: s.key, type: items[i]?.annotationType, text: items[i]?.annotationText ?? '', comment: items[i]?.annotationComment ?? '' })),
}, `Added ${result.successful.length} annotation(s) to PDF ${targetAttachment} via the Zotero desktop app.`);
}
catch (e) {
if (!isLocalWritesUnavailable(e))
throw e;
ctx.logger.info(`Local-API writes unavailable (${e instanceof Error ? e.message : e}); using the connector protocol.`);
}
}
if (!args.library_id && ctx.connectorWrites && (await ensureLocalApi(ctx))) {
const { sessionID } = await ctx.connectorWrites.saveItems(items, { uri: 'zotero://zoteus/annotate' });
// The connector returns no keys; recover them by querying the local API.
const created = await pollCreatedAnnotations(ctx, targetAttachment, items);
return ok({
target: 'desktop',
sessionID,
attachment: targetAttachment,
created,
note: created.length < items.length
? 'Some annotations could not be matched back yet; they may still appear in Zotero (check the PDF sidebar).'
: undefined,
}, `Added ${created.length}/${items.length} annotation(s) to PDF ${targetAttachment} via the running Zotero desktop app.`);
}
const lib = requireCloudLibrary(ctx, args);
const result = await ctx.web.writeItems(lib, items);
return ok({
target: 'cloud',
attachment: targetAttachment,
created: result.successful.map((s, i) => ({ key: s.key, type: items[i]?.annotationType })),
failed: result.failed,
}, `Added ${result.successful.length} annotation(s) to PDF ${targetAttachment} via the cloud Web API.`);
},
};
/** Rank attachment children: stored PDFs first, then linked PDFs, then anything else. */
function scorePdf(att) {
if (att?.contentType !== 'application/pdf')
return 0;
const lm = att?.linkMode;
if (lm === 'imported_file')
return 3;
if (lm === 'imported_url')
return 2;
if (lm === 'linked_file' || lm === 'linked_url')
return 1;
return 1;
}
export default annotateTool;
/**
* Recover the item keys of annotations just created through the connector protocol
* (which returns no payload) by querying the desktop local API for the attachment's
* annotation children and matching them against what we sent.
*/
async function pollCreatedAnnotations(ctx, attachmentKey, sent) {
const wanted = new Map();
for (const it of sent) {
const fingerprint = `${it.annotationType ?? ''}::${(it.annotationText ?? '')}`;
wanted.set(fingerprint, it);
}
const found = [];
const deadline = Date.now() + 15_000;
while (wanted.size && Date.now() < deadline) {
try {
// Must be the /children endpoint: the local API ignores a `parentItem` filter
// on /items and would hand back the entire library instead.
const res = await ctx.local.getItemChildren(attachmentKey, { itemType: 'annotation', limit: 100 });
for (const child of res.data) {
const d = child?.data ?? child;
if (d?.itemType && d.itemType !== 'annotation')
continue;
const fingerprint = `${d?.annotationType ?? ''}::${d?.annotationText ?? ''}`;
if (wanted.has(fingerprint)) {
wanted.delete(fingerprint);
found.push({
key: d.key,
type: d.annotationType,
text: d.annotationText ?? '',
comment: d.annotationComment ?? '',
});
}
}
}
catch {
// Local API hiccup; keep polling until the deadline.
}
if (wanted.size)
await new Promise((r) => setTimeout(r, 750));
}
return found;
}
//# sourceMappingURL=annotate.js.map
{"version":3,"file":"annotate.js","sourceRoot":"","sources":["../../src/tools/annotate.ts"],"names":[],"mappings":"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"}
import type { ToolDefinition } from '../registry/registry.js';
/**
* Attach a file (local path or URL) to an item as a stored (imported_file)
* attachment. Requires the Zotero desktop app (Zotero 9+ local API writes), since
* the cloud client here does not implement the storage upload flow.
*/
declare const attachFile: ToolDefinition;
export default attachFile;
import { z } from 'zod';
import { readFile } from 'node:fs/promises';
import { ok, ensureLocalApi } from '../registry/registry.js';
/**
* Attach a file (local path or URL) to an item as a stored (imported_file)
* attachment. Requires the Zotero desktop app (Zotero 9+ local API writes), since
* the cloud client here does not implement the storage upload flow.
*/
const attachFile = {
name: 'zotero_attach_file',
title: 'Attach a file (PDF, snapshot) to an item',
description: 'Add a stored file attachment (e.g. a PDF full text) under an existing item. Give `parent` (the item key) and either `path` (a local file the Zoteus process can read) or `url` (downloaded first). `filename` and `content_type` are inferred when omitted. Runs against the Zotero desktop app\u2019s local API (Zotero 9+; you may be asked once to allow Zoteus write access — choose "Always Allow"). Returns the new attachment key.',
inputSchema: {
parent: z.string().describe('Key of the parent item to attach the file to.'),
path: z.string().optional().describe('Local filesystem path to the file.'),
url: z.string().url().optional().describe('URL to download the file from.'),
filename: z.string().optional().describe('File name to store; inferred from path/url if omitted.'),
content_type: z.string().optional().describe('MIME type; inferred from the extension if omitted (pdf -> application/pdf).'),
title: z.string().optional().describe('Attachment title, e.g. "Full Text PDF".'),
},
annotations: { readOnlyHint: false, openWorldHint: true },
handler: async (args, ctx) => {
if (!ctx.localWrites || !(await ensureLocalApi(ctx))) {
return {
content: [{ type: 'text', text: 'Storing files needs Zotero desktop write access. If your Zotero has the upcoming local-API writes, provide a key via ZOTEUS_LOCAL_API_KEY (or grant it once); on current Zotero versions, attach files DURING import instead — zotero_import supports `attach_url`, which streams the file into the same save session. Otherwise set ZOTERO_API_KEY and use the cloud flow.' }],
isError: true,
};
}
if (!args.path && !args.url) {
return { content: [{ type: 'text', text: 'Provide `path` or `url`.' }], isError: true };
}
let bytes;
let inferredName;
if (args.path) {
bytes = new Uint8Array(await readFile(args.path));
inferredName = args.path.split(/[\\/]/).pop() ?? 'attachment';
}
else {
const res = await ctx.fetcher.fetch(args.url, { method: 'GET' }, { maxRetries: 2, deadlineMs: 300_000 });
if (!res.ok) {
return { content: [{ type: 'text', text: `Download failed (${res.status}) for ${args.url}` }], isError: true };
}
bytes = new Uint8Array(await res.arrayBuffer());
const noQuery = args.url.split('?')[0] ?? args.url;
inferredName = decodeURIComponent(noQuery.split('/').pop() ?? 'attachment');
}
const filename = args.filename ?? inferredName;
const ext = filename.split('.').pop()?.toLowerCase() ?? '';
const contentType = args.content_type ??
(ext === 'pdf' ? 'application/pdf' : ext === 'html' || ext === 'htm' ? 'text/html' : 'application/octet-stream');
// 1) Create the attachment item, 2) upload + register the file bytes.
const result = await ctx.localWrites.writeItems([
{
itemType: 'attachment',
parentItem: args.parent,
linkMode: 'imported_file',
title: args.title ?? filename,
contentType,
tags: [],
},
]);
if (result.failed.length || !result.successful.length) {
return { content: [{ type: 'text', text: `Could not create attachment item: ${JSON.stringify(result.failed)}` }], isError: true };
}
const attachmentKey = result.successful[0]?.key;
if (!attachmentKey) {
return { content: [{ type: 'text', text: 'Local write returned no attachment key.' }], isError: true };
}
await ctx.localWrites.uploadFile(attachmentKey, { bytes, filename, contentType });
return ok({ attachment: attachmentKey, parent: args.parent, filename, bytes: bytes.length, contentType, target: 'local' }, `Attached ${filename} (${bytes.length} bytes) to item ${args.parent} as ${attachmentKey}.`);
},
};
export default attachFile;
//# sourceMappingURL=attach-file.js.map
{"version":3,"file":"attach-file.js","sourceRoot":"","sources":["../../src/tools/attach-file.ts"],"names":[],"mappings":"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"}
+6
-0

@@ -27,2 +27,8 @@ import { RateLimitedFetcher } from './http.js';

}): Promise<any>;
/**
* Children (attachments, notes, annotations) of an item. The desktop local API
* silently ignores a `parentItem` query param on /items and answers with the whole
* library, so the dedicated /children endpoint is the only correct way to ask.
*/
getItemChildren(key: string, query?: ItemQuery): Promise<ListResult>;
listCollections(query?: {

@@ -29,0 +35,0 @@ top?: boolean;

@@ -66,2 +66,12 @@ import { RateLimitedFetcher } from './http.js';

}
/**
* Children (attachments, notes, annotations) of an item. The desktop local API
* silently ignores a `parentItem` query param on /items and answers with the whole
* library, so the dedicated /children endpoint is the only correct way to ask.
*/
async getItemChildren(key, query = {}) {
const { top: _t, collectionKey: _c, ...rest } = query;
const { json, headers } = await this.getJson(`/users/0/items/${key}/children`, this.buildQuery(rest));
return this.toListResult(json, headers);
}
async listCollections(query = {}) {

@@ -68,0 +78,0 @@ const segment = query.top ? '/collections/top' : '/collections';

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"local-client.js","sourceRoot":"","sources":["../../src/api/local-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAQ/C;;;;GAIG;AACH,MAAM,OAAO,cAAc;IACzB,MAAM,CAAU,aAAa,GAAG,CAAC,CAAC;IACjB,IAAI,CAAS;IACb,OAAO,CAAqB;IAE7C,YAAY,OAA8B,EAAE;QAC1C,IAAI,CAAC,IAAI,GAAG,oBAAoB,IAAI,CAAC,IAAI,IAAI,KAAK,MAAM,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,kBAAkB,EAAE,CAAC;IAC1D,CAAC;IAEO,OAAO;QACb,OAAO,EAAE,oBAAoB,EAAE,GAAG,EAAE,gCAAgC,EAAE,GAAG,EAAE,CAAC;IAC9E,CAAC;IAEO,UAAU,CAChB,MAAwE;QAExE,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,SAAS;gBAAE,SAAS;YAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;;gBAC3D,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,KAAK,GAAG,EAAE;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAClC,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE,EAC7B,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,EAC1C,EAAE,UAAU,EAAE,CAAC,EAAE,CAClB,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,QAAQ,IAAI,EAAE,CAAC,CAAC;QACpE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC;IAEO,YAAY,CAAI,IAAS,EAAE,OAAgB;QACjD,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACvD,OAAO;YACL,IAAI,EAAE,IAAI;YACV,YAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;YACpD,mBAAmB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAChD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACpE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,QAAmB,EAAE;QACnC,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QAClD,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,gBAAgB,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC;QAClE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,OAAO,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,IAAW,CAAC,CAAC,CAAC;QACjG,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,QAA+C,EAAE;QAC1E,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,kBAAkB,GAAG,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,QAA2D,EAAE;QAE7D,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,cAAc,CAAC;QAChE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;QACnC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,OAAO,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,IAAW,CAAC,CAAC,CAAC;QACjG,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC"}
{"version":3,"file":"local-client.js","sourceRoot":"","sources":["../../src/api/local-client.ts"],"names":[],"mappings":"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"}
export interface ZoteusConfig {
apiKey?: string;
/** Pre-provisioned Zotero 9+ desktop local-API key (skips the grant dialog). */
localApiKey?: string;
libraryId?: number;

@@ -4,0 +6,0 @@ libraryType: 'user' | 'group';

@@ -20,2 +20,3 @@ import { z } from 'zod';

ZOTERO_API_KEY: optionalNonEmpty(),
ZOTEUS_LOCAL_API_KEY: optionalNonEmpty(),
ZOTERO_LIBRARY_ID: z.coerce.number().int().positive().optional(),

@@ -88,2 +89,3 @@ ZOTERO_LIBRARY_TYPE: z.enum(['user', 'group']).default('user'),

apiKey: parsed.ZOTERO_API_KEY,
localApiKey: parsed.ZOTEUS_LOCAL_API_KEY,
libraryId: parsed.ZOTERO_LIBRARY_ID,

@@ -90,0 +92,0 @@ libraryType: parsed.ZOTERO_LIBRARY_TYPE,

@@ -1,1 +0,1 @@

{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}

@@ -16,3 +16,5 @@ /**

}): Promise<string[] | null>;
/** Join extracted page texts into one document text (pages separated by a blank line). */
export declare function pdfPagesToText(pages: string[]): string;
/** 1-based page whose text contains the passage's leading window, or undefined. */
export declare function locatePage(pages: string[], passage: string, headChars?: number): number | undefined;

@@ -27,3 +27,6 @@ /**

try {
const loadingTask = pdfjs.getDocument({ data: bytes, useSystemFonts: true, isEvalSupported: false });
// pdfjs transfers (detaches) the buffer it is given; hand it a copy so the
// caller's bytes stay intact (matters when the same buffer is re-extracted).
const data = bytes.slice();
const loadingTask = pdfjs.getDocument({ data, useSystemFonts: true, isEvalSupported: false });
const doc = await loadingTask.promise;

@@ -42,2 +45,6 @@ const pages = [];

}
/** Join extracted page texts into one document text (pages separated by a blank line). */
export function pdfPagesToText(pages) {
return pages.join('\n\n');
}
function normalize(s) {

@@ -44,0 +51,0 @@ return s.toLowerCase().replace(/\s+/g, ' ').trim();

@@ -1,1 +0,1 @@

{"version":3,"file":"pdf-pages.js","sourceRoot":"","sources":["../../../src/features/fulltext/pdf-pages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEnE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAiB,EACjB,OAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,yBAAyB,CAAC;IAC5D,gFAAgF;IAChF,IAAI,KAAK,CAAC,UAAU,GAAG,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,KAAU,CAAC;IACf,IAAI,CAAC;QACH,8CAA8C;QAC9C,KAAK,GAAG,MAAM,MAAM,CAAC,iCAAwC,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,qCAAqC;IACpD,CAAC;IACD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;QACrG,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC;QACtC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAE,OAAO,CAAC,KAAe,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,wCAAwC;IACvD,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,KAAe,EAAE,OAAe,EAAE,SAAS,GAAG,EAAE;IACzE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
{"version":3,"file":"pdf-pages.js","sourceRoot":"","sources":["../../../src/features/fulltext/pdf-pages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,QAAQ;AAEnE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAiB,EACjB,OAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,yBAAyB,CAAC;IAC5D,gFAAgF;IAChF,IAAI,KAAK,CAAC,UAAU,GAAG,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,KAAU,CAAC;IACf,IAAI,CAAC;QACH,8CAA8C;QAC9C,KAAK,GAAG,MAAM,MAAM,CAAC,iCAAwC,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,qCAAqC;IACpD,CAAC;IACD,IAAI,CAAC;QACH,2EAA2E;QAC3E,6EAA6E;QAC7E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9F,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC;QACtC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAE,OAAO,CAAC,KAAe,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,wCAAwC;IACvD,CAAC;AACH,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,cAAc,CAAC,KAAe;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,KAAe,EAAE,OAAe,EAAE,SAAS,GAAG,EAAE;IACzE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}

@@ -15,6 +15,17 @@ import type { ZoteusConfig } from '../../config.js';

private readonly model;
/** Injectable extractor factory (tests); defaults to the transformers.js pipeline. */
private readonly loadExtractor?;
readonly name = "local";
/** Texts handed to the transformers pipeline in a single call. */
static readonly BATCH_SIZE = 32;
private extractor;
constructor(model?: string);
constructor(model?: string,
/** Injectable extractor factory (tests); defaults to the transformers.js pipeline. */
loadExtractor?: (() => Promise<any>) | undefined);
private ensure;
/**
* Embed texts in batches through the pipeline (one call per batch instead of one
* per text), yielding to the event loop between batches so long builds stay
* responsive and interruptible. Returns exactly one vector per input text.
*/
embed(texts: string[]): Promise<number[][]>;

@@ -21,0 +32,0 @@ }

@@ -23,6 +23,12 @@ const DIM = 64;

model;
loadExtractor;
name = 'local';
/** Texts handed to the transformers pipeline in a single call. */
static BATCH_SIZE = 32;
extractor;
constructor(model = 'Xenova/all-MiniLM-L6-v2') {
constructor(model = 'Xenova/all-MiniLM-L6-v2',
/** Injectable extractor factory (tests); defaults to the transformers.js pipeline. */
loadExtractor) {
this.model = model;
this.loadExtractor = loadExtractor;
}

@@ -32,2 +38,6 @@ async ensure() {

return this.extractor;
if (this.loadExtractor) {
this.extractor = await this.loadExtractor();
return this.extractor;
}
let transformers;

@@ -43,8 +53,24 @@ try {

}
/**
* Embed texts in batches through the pipeline (one call per batch instead of one
* per text), yielding to the event loop between batches so long builds stay
* responsive and interruptible. Returns exactly one vector per input text.
*/
async embed(texts) {
if (texts.length === 0)
return [];
const extractor = await this.ensure();
const out = [];
for (const t of texts) {
const tensor = await extractor(t, { pooling: 'mean', normalize: true });
out.push(Array.from(tensor.data));
for (let i = 0; i < texts.length; i += LocalEmbeddingProvider.BATCH_SIZE) {
const batch = texts.slice(i, i + LocalEmbeddingProvider.BATCH_SIZE);
const tensor = await extractor(batch, { pooling: 'mean', normalize: true });
const data = tensor.data;
const dims = tensor.dims;
const dim = dims && dims.length > 1 ? dims[dims.length - 1] : data.length / batch.length;
for (let b = 0; b < batch.length; b++) {
out.push(Array.from(data.slice(b * dim, (b + 1) * dim)));
}
if (i + LocalEmbeddingProvider.BATCH_SIZE < texts.length) {
await new Promise((resolve) => setImmediate(resolve));
}
}

@@ -51,0 +77,0 @@ return out;

@@ -1,1 +0,1 @@

{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../../src/features/search/embeddings.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../../src/features/search/embeddings.ts"],"names":[],"mappings":"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"}

@@ -17,2 +17,44 @@ import { VectorStore } from './vector-store.js';

}
/** Lifecycle of the asynchronous background index build. */
export type BuildState = 'idle' | 'building' | 'done' | 'error';
/**
* Live build/status snapshot. Backward compatible with SearchIndexStatus (it keeps
* documents/vectors/items/embedder/builtFromVersion) and adds build progress.
*/
export interface IndexBuildStatus extends SearchIndexStatus {
state: BuildState;
/** Items pulled from the Zotero API so far. */
itemsFetched: number;
/** Total items expected (0 = not yet known). Capped by the build limit. */
itemsTotal: number;
/** Passages indexed so far (alias of documents). */
passages: number;
/** Set when state === 'error'. */
lastError?: string;
}
/** One page of library items plus the library-wide total (for progress). */
export interface PageResult {
items: any[];
totalResults: number;
}
/** Fetch a page of items starting at offset `start` (the Web API pages 100-at-a-time). */
export type PageFetcher = (start: number) => Promise<PageResult>;
export interface IncrementalBuildOptions {
/** Hard cap on items to index (defaults to no cap beyond the fetcher). */
maxItems?: number;
/** Embedding batch size (texts handed to the provider per call). */
embedBatchSize?: number;
/** Persist partial progress every N items. */
persistEveryItems?: number;
/** Persist partial progress at least every N ms. */
persistEveryMs?: number;
/** Log/report progress every N items. */
progressEveryItems?: number;
/** Log/report progress at least every N ms. */
progressEveryMs?: number;
/** Atomically persist the current (partial) index; called periodically and at the end. */
persist?: () => Promise<void>;
/** Optional progress hook (e.g. MCP notifications) fired alongside the logger. */
onProgress?: (status: IndexBuildStatus) => void;
}
interface ChunkRecord {

@@ -42,5 +84,19 @@ id: string;

private builtFromVersion;
private buildState;
private itemsFetched;
private itemsTotal;
private lastBuildError;
private cancelToken;
constructor(opts: SearchIndexOptions);
get embedderName(): string;
get hasEmbedder(): boolean;
/** True while a background build is running. */
get isBuilding(): boolean;
/** Full live status: index size + build progress. Backward compatible with status(). */
buildStatus(): IndexBuildStatus;
/**
* Cooperatively cancel the running build. Returns false if nothing is building.
* The build halts between pages/batches and keeps whatever was already indexed.
*/
requestStop(): boolean;
/** Embed arbitrary texts with the configured provider (empty array if none). */

@@ -52,2 +108,14 @@ embed(texts: string[]): Promise<number[][]>;

build(libraryItems: any[], opts?: BuildOptions): Promise<SearchIndexStatus>;
/**
* Asynchronous, incremental, resumable index build.
*
* Pages items via `fetchPage`, chunks/keyword-indexes them as they arrive, embeds in
* small batches, and atomically persists partial progress along the way — so a
* timeout, crash, or `requestStop()` never leaves a corrupt index and whatever was
* saved stays queryable. Returns the final build status; the caller should kick this
* off without awaiting (fire-and-forget) and poll `buildStatus()`.
*/
buildIncremental(fetchPage: PageFetcher, opts?: IncrementalBuildOptions): Promise<IndexBuildStatus>;
/** Chunk a single library item into the keyword index and queue passages for embedding. */
private addOneItem;
query(q: string, opts?: {

@@ -54,0 +122,0 @@ limit?: number;

@@ -58,2 +58,8 @@ import { BM25Index } from './bm25.js';

builtFromVersion = 0;
// Asynchronous build lifecycle (see buildIncremental / requestStop / buildStatus).
buildState = 'idle';
itemsFetched = 0;
itemsTotal = 0;
lastBuildError = undefined;
cancelToken = null;
constructor(opts) {

@@ -68,2 +74,30 @@ this.opts = opts;

}
/** True while a background build is running. */
get isBuilding() {
return this.buildState === 'building';
}
/** Full live status: index size + build progress. Backward compatible with status(). */
buildStatus() {
const base = this.status();
const s = {
...base,
passages: base.documents,
state: this.buildState,
itemsFetched: this.itemsFetched,
itemsTotal: this.itemsTotal,
};
if (this.buildState === 'error' && this.lastBuildError)
s.lastError = this.lastBuildError;
return s;
}
/**
* Cooperatively cancel the running build. Returns false if nothing is building.
* The build halts between pages/batches and keeps whatever was already indexed.
*/
requestStop() {
if (!this.isBuilding || !this.cancelToken)
return false;
this.cancelToken.cancelled = true;
return true;
}
/** Embed arbitrary texts with the configured provider (empty array if none). */

@@ -127,2 +161,159 @@ async embed(texts) {

}
/**
* Asynchronous, incremental, resumable index build.
*
* Pages items via `fetchPage`, chunks/keyword-indexes them as they arrive, embeds in
* small batches, and atomically persists partial progress along the way — so a
* timeout, crash, or `requestStop()` never leaves a corrupt index and whatever was
* saved stays queryable. Returns the final build status; the caller should kick this
* off without awaiting (fire-and-forget) and poll `buildStatus()`.
*/
async buildIncremental(fetchPage, opts = {}) {
if (this.isBuilding)
throw new Error('Index build already in progress; poll action:"status".');
this.buildState = 'building';
this.lastBuildError = undefined;
this.itemsFetched = 0;
this.itemsTotal = 0;
const token = { cancelled: false };
this.cancelToken = token;
this.reset();
const embedBatchSize = opts.embedBatchSize ?? 32;
const persistEveryItems = opts.persistEveryItems ?? 200;
const persistEveryMs = opts.persistEveryMs ?? 10_000;
const progressEveryItems = opts.progressEveryItems ?? 500;
const progressEveryMs = opts.progressEveryMs ?? 10_000;
const maxItems = opts.maxItems;
const pending = []; // passages awaiting embedding
let start = 0;
let itemsSincePersist = 0;
let lastPersistAt = Date.now();
let itemsSinceLog = 0;
let lastLogAt = Date.now();
let embeddingDisabled = false;
let warnedEmbed = false;
const persistNow = async () => {
itemsSincePersist = 0;
lastPersistAt = Date.now();
if (!opts.persist)
return;
try {
await opts.persist();
}
catch (e) {
this.opts.logger?.warn(`Could not persist index: ${e instanceof Error ? e.message : String(e)}`);
}
};
const maybePersist = async () => {
if (itemsSincePersist >= persistEveryItems || Date.now() - lastPersistAt >= persistEveryMs)
await persistNow();
};
const maybeLog = () => {
if (itemsSinceLog < progressEveryItems && Date.now() - lastLogAt < progressEveryMs)
return;
itemsSinceLog = 0;
lastLogAt = Date.now();
const s = this.buildStatus();
const total = s.itemsTotal > 0 ? String(s.itemsTotal) : '?';
this.opts.logger?.info(`index build: ${s.itemsFetched}/${total} items, ${s.passages} passages, ${s.vectors} vectors (embedder=${s.embedder})`);
opts.onProgress?.(s);
};
const embedPending = async (force) => {
if (!this.hasEmbedder || embeddingDisabled) {
pending.length = 0;
return;
}
while (pending.length >= (force ? 1 : embedBatchSize)) {
if (token.cancelled)
return;
const batch = pending.splice(0, Math.min(embedBatchSize, pending.length));
try {
const vecs = await this.opts.embedder.embed(batch.map((r) => r.text));
batch.forEach((r, i) => {
if (vecs[i])
this.vectors.add(r.id, vecs[i]);
});
}
catch (e) {
embeddingDisabled = true;
pending.length = 0;
if (!warnedEmbed) {
warnedEmbed = true;
this.opts.logger?.warn(`Embedding failed; falling back to keyword-only. ${e instanceof Error ? e.message : String(e)}`);
}
}
// Yield so long embedding runs stay interruptible and the event loop breathes.
await new Promise((resolve) => setImmediate(resolve));
}
};
try {
for (;;) {
if (token.cancelled)
break;
if (maxItems !== undefined && this.itemsFetched >= maxItems)
break;
const page = await fetchPage(start);
const pageItems = page.items ?? [];
if (pageItems.length === 0)
break;
if (!this.itemsTotal && page.totalResults) {
this.itemsTotal = maxItems !== undefined ? Math.min(page.totalResults, maxItems) : page.totalResults;
}
for (const item of pageItems) {
if (token.cancelled)
break;
if (maxItems !== undefined && this.itemsFetched >= maxItems)
break;
this.addOneItem(item, pending);
this.itemsFetched++;
itemsSincePersist++;
itemsSinceLog++;
}
start += pageItems.length;
await embedPending(false);
maybeLog();
await maybePersist();
if (start >= page.totalResults)
break;
}
if (!token.cancelled)
await embedPending(true);
this.builtFromVersion = this.itemsFetched;
await persistNow();
this.buildState = 'done';
const final = this.buildStatus();
const total = final.itemsTotal > 0 ? String(final.itemsTotal) : '?';
this.opts.logger?.info(`index build ${token.cancelled ? 'stopped' : 'complete'}: ` +
`${final.itemsFetched}/${total} items, ${final.passages} passages, ${final.vectors} vectors (embedder=${final.embedder})`);
opts.onProgress?.(final);
return final;
}
catch (e) {
this.buildState = 'error';
this.lastBuildError = e instanceof Error ? e.message : String(e);
this.opts.logger?.error(`index build failed: ${this.lastBuildError}`);
// Keep whatever partial data we already indexed, and persist it best-effort.
await persistNow().catch(() => { });
opts.onProgress?.(this.buildStatus());
return this.buildStatus();
}
finally {
this.cancelToken = null;
}
}
/** Chunk a single library item into the keyword index and queue passages for embedding. */
addOneItem(item, pending) {
const d = item.data ?? item;
const key = item.key ?? d.key;
if (!key)
return;
this.items.add(key);
for (const ch of chunkText(itemText(d))) {
const rec = { id: `${key}#${ch.index}`, itemKey: key, title: d.title ?? '(untitled)', text: ch.text };
this.chunks.set(rec.id, rec);
this.bm25.addDoc(rec.id, rec.text);
if (this.hasEmbedder)
pending.push(rec);
}
}
async query(q, opts = {}) {

@@ -129,0 +320,0 @@ const limit = opts.limit ?? 10;

@@ -1,1 +0,1 @@

{"version":3,"file":"index-manager.js","sourceRoot":"","sources":["../../../src/features/search/index-manager.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index-manager.js","sourceRoot":"","sources":["../../../src/features/search/index-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgB,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,WAAW,EAAkB,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAmFzC,SAAS,QAAQ,CAAC,CAAM;IACtB,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpG,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7E,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC;SAC9F,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,uDAAuD;AACvD,SAAS,GAAG,CAAC,KAAmC,EAAE,CAAC,GAAG,EAAE;IACtD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvG,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa,EAAE,GAAG,GAAG,GAAG;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;YAAE,GAAG,GAAG,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,KAAK,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnC,CAAC;IACD,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACvC,IAAI,EAAE,GAAG,KAAK;YAAE,GAAG,GAAG,EAAE,CAAC;IAC3B,CAAC;IACD,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,KAAK,GAAG,CAAC;QAAE,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;IAClC,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM;QAAE,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iFAAiF;AACjF,MAAM,OAAO,WAAW;IAcO;IAbrB,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;IACvB,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAC5B,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IACxC,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAC1B,gBAAgB,GAAG,CAAC,CAAC;IAE7B,mFAAmF;IAC3E,UAAU,GAAe,MAAM,CAAC;IAChC,YAAY,GAAG,CAAC,CAAC;IACjB,UAAU,GAAG,CAAC,CAAC;IACf,cAAc,GAAuB,SAAS,CAAC;IAC/C,WAAW,GAAkC,IAAI,CAAC;IAE1D,YAA6B,IAAwB;QAAxB,SAAI,GAAJ,IAAI,CAAoB;IAAG,CAAC;IAEzD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,qBAAqB,CAAC;IAC3D,CAAC;IAED,IAAI,WAAW;QACb,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,gDAAgD;IAChD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC;IACxC,CAAC;IAED,wFAAwF;IACxF,WAAW;QACT,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAqB;YAC1B,GAAG,IAAI;YACP,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;QACF,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,IAAI,IAAI,CAAC,cAAc;YAAE,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC;QAC1F,OAAO,CAAC,CAAC;IACX,CAAC;IAED;;;OAGG;IACH,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QACxD,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,KAAK,CAAC,KAAe;QACzB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,MAAM;QACJ,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;YAC1B,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;YACtB,QAAQ,EAAE,IAAI,CAAC,YAAY;YAC3B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;SACxC,CAAC;IACJ,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;IAC9B,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,YAAmB,EAAE,OAAqB,EAAE;QACtD,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,OAAO,GAAkB,EAAE,CAAC;QAClC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;YAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;YAC9B,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;YAChD,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAgB,EAAE,EAAE,EAAE,GAAG,GAAG,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;gBACnH,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAClB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBACxE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACvB,IAAI,IAAI,CAAC,CAAC,CAAC;wBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;gBAChD,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,mDAAmD,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1H,CAAC;QACH,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,gBAAgB,CAAC,SAAsB,EAAE,OAAgC,EAAE;QAC/E,IAAI,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC/F,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,MAAM,KAAK,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC;QACjD,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,GAAG,CAAC;QACxD,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC;QACrD,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,IAAI,GAAG,CAAC;QAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,IAAI,MAAM,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAE/B,MAAM,OAAO,GAAkB,EAAE,CAAC,CAAC,8BAA8B;QACjE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,IAAI,iBAAiB,GAAG,KAAK,CAAC;QAC9B,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,MAAM,UAAU,GAAG,KAAK,IAAmB,EAAE;YAC3C,iBAAiB,GAAG,CAAC,CAAC;YACtB,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,OAAO;YAC1B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,4BAA4B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnG,CAAC;QACH,CAAC,CAAC;QACF,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE;YAC7C,IAAI,iBAAiB,IAAI,iBAAiB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,IAAI,cAAc;gBAAE,MAAM,UAAU,EAAE,CAAC;QACjH,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,IAAI,aAAa,GAAG,kBAAkB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,eAAe;gBAAE,OAAO;YAC3F,aAAa,GAAG,CAAC,CAAC;YAClB,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC5D,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CACpB,gBAAgB,CAAC,CAAC,YAAY,IAAI,KAAK,WAAW,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,OAAO,sBAAsB,CAAC,CAAC,QAAQ,GAAG,CACvH,CAAC;YACF,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC;QACF,MAAM,YAAY,GAAG,KAAK,EAAE,KAAc,EAAiB,EAAE;YAC3D,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,iBAAiB,EAAE,CAAC;gBAC3C,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC;gBACtD,IAAI,KAAK,CAAC,SAAS;oBAAE,OAAO;gBAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC1E,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;oBACvE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;wBACrB,IAAI,IAAI,CAAC,CAAC,CAAC;4BAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;oBAChD,CAAC,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,iBAAiB,GAAG,IAAI,CAAC;oBACzB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;oBACnB,IAAI,CAAC,WAAW,EAAE,CAAC;wBACjB,WAAW,GAAG,IAAI,CAAC;wBACnB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CACpB,mDAAmD,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAChG,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,+EAA+E;gBAC/E,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,SAAS,CAAC;gBACR,IAAI,KAAK,CAAC,SAAS;oBAAE,MAAM;gBAC3B,IAAI,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,IAAI,QAAQ;oBAAE,MAAM;gBACnE,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC;gBACpC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBACnC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM;gBAClC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC1C,IAAI,CAAC,UAAU,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC;gBACvG,CAAC;gBACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;oBAC7B,IAAI,KAAK,CAAC,SAAS;wBAAE,MAAM;oBAC3B,IAAI,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,IAAI,QAAQ;wBAAE,MAAM;oBACnE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBAC/B,IAAI,CAAC,YAAY,EAAE,CAAC;oBACpB,iBAAiB,EAAE,CAAC;oBACpB,aAAa,EAAE,CAAC;gBAClB,CAAC;gBACD,KAAK,IAAI,SAAS,CAAC,MAAM,CAAC;gBAC1B,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;gBAC1B,QAAQ,EAAE,CAAC;gBACX,MAAM,YAAY,EAAE,CAAC;gBACrB,IAAI,KAAK,IAAI,IAAI,CAAC,YAAY;oBAAE,MAAM;YACxC,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,SAAS;gBAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,YAAY,CAAC;YAC1C,MAAM,UAAU,EAAE,CAAC;YACnB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YACpE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CACpB,eAAe,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,IAAI;gBACzD,GAAG,KAAK,CAAC,YAAY,IAAI,KAAK,WAAW,KAAK,CAAC,QAAQ,cAAc,KAAK,CAAC,OAAO,sBAAsB,KAAK,CAAC,QAAQ,GAAG,CAC5H,CAAC;YACF,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC;YAC1B,IAAI,CAAC,cAAc,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACjE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,uBAAuB,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;YACtE,6EAA6E;YAC7E,MAAM,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACnC,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,2FAA2F;IACnF,UAAU,CAAC,IAAS,EAAE,OAAsB;QAClD,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;QAC9B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxC,MAAM,GAAG,GAAgB,EAAE,EAAE,EAAE,GAAG,GAAG,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YACnH,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,WAAW;gBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,CAAS,EAAE,OAAmE,EAAE;QAC1F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;QAEvB,MAAM,OAAO,GAAc,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAChF,IAAI,MAAM,GAAgB,EAAE,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClE,IAAI,CAAC;gBACH,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjD,IAAI,EAAE;oBAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,yCAAyC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChH,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,IAAI,GAAgB,EAAE,CAAC;QAC7B,KAAK,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC5C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAChG,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK;gBAAE,MAAM;QAClC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM;QACJ,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACxH,CAAC;IAED,YAAY,CAAC,IAAyE;QACpF,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC;IACrD,CAAC;CACF"}
import type { SearchIndex } from './index-manager.js';
/**
* Atomically persist the index: write to a temp file in the same directory, then
* rename over the target. A crash mid-write can therefore never leave a corrupt or
* half-written search-index.json — readers see either the previous complete snapshot
* or the new one.
*/
export declare function saveIndex(index: SearchIndex, path: string): Promise<void>;
export declare function loadIndex(index: SearchIndex, path: string): Promise<boolean>;

@@ -1,6 +0,20 @@

import { readFile, writeFile, mkdir } from 'node:fs/promises';
import { readFile, writeFile, mkdir, rename, unlink } from 'node:fs/promises';
import { dirname } from 'node:path';
/**
* Atomically persist the index: write to a temp file in the same directory, then
* rename over the target. A crash mid-write can therefore never leave a corrupt or
* half-written search-index.json — readers see either the previous complete snapshot
* or the new one.
*/
export async function saveIndex(index, path) {
await mkdir(dirname(path), { recursive: true });
await writeFile(path, JSON.stringify(index.toJSON()));
const tmp = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
try {
await writeFile(tmp, JSON.stringify(index.toJSON()));
await rename(tmp, path);
}
catch (e) {
await unlink(tmp).catch(() => { });
throw e;
}
}

@@ -7,0 +21,0 @@ export async function loadIndex(index, path) {

@@ -1,1 +0,1 @@

{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../../src/features/search/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAkB,EAAE,IAAY;IAC9D,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAkB,EAAE,IAAY;IAC9D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../../src/features/search/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAkB,EAAE,IAAY;IAC9D,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,IAAI,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9F,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAkB,EAAE,IAAY;IAC9D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}

@@ -9,2 +9,4 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

import type { LocalApiClient } from '../api/local-client.js';
import type { LocalWriteClient } from '../api/local-writes.js';
import type { ConnectorWriteClient } from '../api/connector-writes.js';
import type { Logger } from '../lib/logger.js';

@@ -23,2 +25,6 @@ import type { StyleResolver } from '../features/citation/styles.js';

local?: LocalApiClient;
/** Zotero 9+ desktop local-API writes (user-granted key); undefined when unavailable. */
localWrites?: LocalWriteClient;
/** Desktop connector-API writes (Zotero 7+): saveItems/saveAttachment/updateSession. */
connectorWrites?: ConnectorWriteClient;
styles: StyleResolver;

@@ -85,1 +91,15 @@ translation: TranslationServerClient;

export declare function registerAllTools(server: McpServer, defs: ToolDefinition[], ctx: ToolContext): void;
/**
* True when a local-API write failure means the running Zotero simply does not have
* (or accept) local writes yet — e.g. Zotero <= 9.0 whose local API is read-only
* ("No endpoint found", 501 "Endpoint does not support method") — as opposed to a
* real write failure (denied grant, validation error, stale version). Callers use
* this to fall back to the connector protocol or the cloud Web API.
*/
export declare function isLocalWritesUnavailable(err: unknown): boolean;
/**
* The local-API capability is probed at startup, but Zotero may be restarted (or
* briefly unresponsive) during a long-lived server process. This re-pings once and
* refreshes the flag so desktop write paths recover without a restart.
*/
export declare function ensureLocalApi(ctx: ToolContext): Promise<boolean>;

@@ -29,3 +29,4 @@ import { ZoteroApiError } from '../api/errors.js';

if (!cloud) {
throw new Error('This operation writes to Zotero and requires a cloud API key (set ZOTERO_API_KEY). The desktop local API is read-only.');
throw new Error('This operation writes to a cloud/group library and requires a cloud API key (set ZOTERO_API_KEY). ' +
'For the personal library, writes can instead go through the running Zotero 9+ desktop app (local API).');
}

@@ -58,2 +59,28 @@ return { type: 'user', id: cloud.userID };

}
/**
* True when a local-API write failure means the running Zotero simply does not have
* (or accept) local writes yet — e.g. Zotero <= 9.0 whose local API is read-only
* ("No endpoint found", 501 "Endpoint does not support method") — as opposed to a
* real write failure (denied grant, validation error, stale version). Callers use
* this to fall back to the connector protocol or the cloud Web API.
*/
export function isLocalWritesUnavailable(err) {
const msg = err instanceof Error ? err.message : String(err);
return /local api/i.test(msg) && /404|no endpoint|not implemented|not supported|unreachable/i.test(msg);
}
/**
* The local-API capability is probed at startup, but Zotero may be restarted (or
* briefly unresponsive) during a long-lived server process. This re-pings once and
* refreshes the flag so desktop write paths recover without a restart.
*/
export async function ensureLocalApi(ctx) {
if (ctx.capabilities.localApi)
return true;
if (!ctx.local || ctx.config.local === 'off')
return false;
const up = await ctx.local.ping().catch(() => false);
if (up)
ctx.capabilities.localApi = true;
return up;
}
//# sourceMappingURL=registry.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry/registry.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiDlD;;;;;;;GAOG;AACH,MAAM,UAAU,EAAE,CAAC,UAAmC,EAAE,OAAe;IACrE,OAAO;QACL,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;YAC/B,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;SAC5D;QACD,iBAAiB,EAAE,UAAU;KAC9B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAgB,EAChB,IAA+D;IAE/D,IAAI,IAAI,EAAE,UAAU;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,IAAI,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACzF,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC;IACrC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAAiB,EACjB,IAAsB,EACtB,GAAgB;IAEhB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,YAAY,CACjB,GAAG,CAAC,IAAI,EACR;YACE,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,WAAW,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE;SAC3E,EACD,KAAK,EAAE,IAAa,EAAE,EAAE;YACtB,IAAI,CAAC;gBACH,OAAO,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACtC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GACX,GAAG,YAAY,cAAc;oBAC3B,CAAC,CAAC,GAAG,CAAC,OAAO;oBACb,CAAC,CAAC,GAAG,YAAY,KAAK;wBACpB,CAAC,CAAC,GAAG,CAAC,OAAO;wBACb,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACpB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,IAAI,UAAU,EAAE,OAAO,CAAC,CAAC;gBACtD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAChF,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/registry/registry.ts"],"names":[],"mappings":"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"}

@@ -11,3 +11,14 @@ export async function probeCapabilities(config, deps) {

: Promise.resolve(null);
const localPromise = config.local !== 'off' && deps.local ? deps.local.ping().catch(() => false) : Promise.resolve(false);
// The desktop app may be mid-startup when zoteus boots; a single instant ping can
// race it and wrongly disable every desktop write path for the process lifetime.
const localPromise = config.local !== 'off' && deps.local
? (async () => {
for (let attempt = 0; attempt < 3; attempt++) {
if (await deps.local.ping().catch(() => false))
return true;
await new Promise((r) => setTimeout(r, 600));
}
return false;
})()
: Promise.resolve(false);
const [cloud, localApi] = await Promise.all([cloudPromise, localPromise]);

@@ -14,0 +25,0 @@ deps.logger.info(`Capabilities: cloud=${cloud ? `user ${cloud.userID}` : 'none'}, localApi=${localApi}`);

@@ -1,1 +0,1 @@

{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/router/capabilities.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,IAAe;IAEf,MAAM,YAAY,GAA4B,IAAI,CAAC,GAAG,CAAC,MAAM;QAC3D,CAAC,CAAC,IAAI,CAAC,GAAG;aACL,WAAW,EAAE;aACb,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;aACpB,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACN,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,MAAM,YAAY,GAChB,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAEvG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,uBAAuB,KAAK,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,cAAc,QAAQ,EAAE,CACvF,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC"}
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/router/capabilities.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAoB,EACpB,IAAe;IAEf,MAAM,YAAY,GAA4B,IAAI,CAAC,GAAG,CAAC,MAAM;QAC3D,CAAC,CAAC,IAAI,CAAC,GAAG;aACL,WAAW,EAAE;aACb,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;aACpB,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACN,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,kFAAkF;IAClF,iFAAiF;IACjF,MAAM,YAAY,GAChB,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK;QAClC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE;YACV,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;gBAC7C,IAAI,MAAM,IAAI,CAAC,KAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC7D,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,EAAE;QACN,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE7B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,uBAAuB,KAAK,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,cAAc,QAAQ,EAAE,CACvF,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC7B,CAAC"}

@@ -52,3 +52,6 @@ /**

const lib = library ?? this.defaultLibrary();
// Children are always available via the cloud; local may not implement /children uniformly.
// Prefer the desktop app for the personal library (local-only mode has no cloud
// fallback — hitting api.zotero.org with user id 0 yields "Invalid user ID").
if (this.useLocal(lib))
return this.local.getItemChildren(key, rest);
return this.web.getItemChildren(lib, key, rest);

@@ -55,0 +58,0 @@ }

@@ -1,1 +0,1 @@

{"version":3,"file":"library-router.js","sourceRoot":"","sources":["../../src/router/library-router.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"library-router.js","sourceRoot":"","sources":["../../src/router/library-router.ts"],"names":[],"mappings":"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"}

@@ -6,2 +6,4 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';

import { LocalApiClient } from './api/local-client.js';
import { LocalWriteClient } from './api/local-writes.js';
import { ConnectorWriteClient } from './api/connector-writes.js';
import { probeCapabilities } from './router/capabilities.js';

@@ -49,2 +51,19 @@ import { LibraryRouter } from './router/library-router.js';

const router = new LibraryRouter({ config, capabilities, web, local });
// Zotero 9+ accepts local-API writes behind a user-granted key. Only the operator
// context (never per-user tenants) talks to the desktop app. The client is created
// eagerly but authorizes lazily, on first write.
const localWrites = !perUser && capabilities.localApi
? new LocalWriteClient({
port: config.localPort,
fetcher,
logger,
key: config.localApiKey,
keyStorePath: join(config.dataDir, 'local-api-key.json'),
})
: undefined;
// The connector protocol works on all recent Zotero versions while the app runs,
// including ones whose local API is still read-only (no grant dialog involved).
const connectorWrites = !perUser && capabilities.localApi
? new ConnectorWriteClient({ port: config.localPort, fetcher, logger })
: undefined;
const schema = new SchemaService({ web });

@@ -64,2 +83,4 @@ const styles = new StyleResolver();

local,
localWrites,
connectorWrites,
styles,

@@ -66,0 +87,0 @@ translation,

@@ -1,1 +0,1 @@

{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
import { z } from 'zod';
import { ok } from '../registry/registry.js';
import { rankPassages, approxPage } from '../features/fulltext/passages.js';
import { extractPdfPages, locatePage, DEFAULT_PRECISE_MAX_BYTES } from '../features/fulltext/pdf-pages.js';
import { extractPdfPages, locatePage, pdfPagesToText, DEFAULT_PRECISE_MAX_BYTES } from '../features/fulltext/pdf-pages.js';
function err(text) {

@@ -39,3 +39,3 @@ return { content: [{ type: 'text', text }], isError: true };

title: 'Get attachment full text / passages (read-only)',
description: "Retrieve an item's PDF text for grounding. Pass a parent `item_key` (its best PDF attachment is resolved automatically) or an attachment key. With `query`, returns the top relevant passages with locators (char offsets, nearest section, and a page); with `page_range` (e.g. \"3-7\"), returns that span; with neither, returns a truncated head. Page numbers are an estimate (pageApprox) unless `precise_pages:true`, which re-extracts the PDF for exact pages when possible (otherwise it degrades to approximate with a notice). Read-only; cloud full text. Use this to cite a claim with a page after finding an item via zotero_search_items / zotero_semantic_search.",
description: "Retrieve an item's PDF text for grounding. Pass a parent `item_key` (its best PDF attachment is resolved automatically) or an attachment key. With `query`, returns the top relevant passages with locators (char offsets, nearest section, and a page); with `page_range` (e.g. \"3-7\"), returns that span; with neither, returns a truncated head. Text comes from Zotero's full-text index when available; when the attachment is NOT indexed yet, the PDF itself is downloaded and parsed on the fly (`fallback`, on by default — set `fallback:false` to disable), so unindexed PDFs still return text (marked fulltextSource:\"pdf\"). Page numbers are exact in that case, and otherwise an estimate (pageApprox) unless `precise_pages:true`, which re-extracts the PDF for exact pages when possible (otherwise it degrades to approximate with a notice). Read-only; cloud full text. Use this to cite a claim with a page after finding an item via zotero_search_items / zotero_semantic_search.",
inputSchema: {

@@ -54,2 +54,6 @@ item_key: z.string().describe('Parent item key or attachment key.'),

precise_pages: z.boolean().optional().describe('Re-extract the PDF for exact page numbers.'),
fallback: z
.boolean()
.optional()
.describe('When Zotero has no indexed full text for the attachment, download the PDF and extract it directly (default true).'),
library_type: z.enum(['user', 'group']).optional(),

@@ -67,9 +71,50 @@ library_id: z.number().int().optional(),

return err(resolved.error);
const maxMb = Math.round(DEFAULT_PRECISE_MAX_BYTES / (1024 * 1024));
const ft = await ctx.web.getFullText(lib, resolved.attachmentKey);
if (!ft || typeof ft.content !== 'string' || !ft.content.length) {
return err(`No extracted full text for attachment ${resolved.attachmentKey}. Zotero may not have indexed it yet (open it once in Zotero, or check it is a text PDF).`);
const indexed = Boolean(ft && typeof ft.content === 'string' && ft.content.length);
// Where the text comes from: Zotero's index when available, otherwise (fallback,
// on by default) the attachment PDF itself, parsed on the fly with pdfjs.
let content;
let totalChars;
let totalPages;
let pages = null;
let fulltextSource = 'zotero';
let sourceNotice = '';
if (indexed) {
content = ft.content;
totalChars = typeof ft.totalChars === 'number' && ft.totalChars > 0 ? ft.totalChars : content.length;
totalPages = typeof ft.totalPages === 'number' ? ft.totalPages : undefined;
}
const content = ft.content;
const totalChars = typeof ft.totalChars === 'number' && ft.totalChars > 0 ? ft.totalChars : content.length;
const totalPages = typeof ft.totalPages === 'number' ? ft.totalPages : undefined;
else if (args.fallback === false) {
return err(`No extracted full text for attachment ${resolved.attachmentKey}. Zotero has not indexed it yet ` +
`(open it once in Zotero to index it, or retry with fallback enabled to parse the PDF directly).`);
}
else {
// --- PDF fallback: download the attachment and extract text directly ---
const noText = `No extracted full text for attachment ${resolved.attachmentKey} (Zotero has not indexed it)`;
if (resolved.size && resolved.size > DEFAULT_PRECISE_MAX_BYTES) {
return err(`${noText}, and direct PDF extraction is skipped: the file is larger than the ${maxMb} MB limit for on-the-fly parsing. ` +
`Open the PDF once in Zotero to have it indexed, then retry.`);
}
let bytes;
try {
const dl = await ctx.web.downloadFileBytes(lib, resolved.attachmentKey);
bytes = dl.bytes;
}
catch (e) {
return err(`${noText}, and the attachment file could not be downloaded either (${e instanceof Error ? e.message : String(e)}). ` +
`It may be a linked file with no stored copy.`);
}
const extracted = await extractPdfPages(bytes);
if (!extracted || !extracted.some((p) => p.trim())) {
return err(`${noText}, and direct PDF extraction yielded nothing (corrupt/scanned PDF, oversized file, or the optional pdfjs-dist parser is missing). ` +
`Open the PDF once in Zotero to have it indexed, then retry.`);
}
pages = extracted;
content = pdfPagesToText(extracted);
totalChars = content.length;
totalPages = extracted.length;
fulltextSource = 'pdf';
sourceNotice = ` Zotero had no indexed full text for this attachment; the text was extracted directly from the PDF (fallback).`;
}
const maxChars = args.max_chars ?? 12000;

@@ -82,11 +127,12 @@ const base = {

title: resolved.title,
fulltextSource,
totalChars,
totalPages,
indexedChars: ft.indexedChars,
indexedPages: ft.indexedPages,
indexedChars: indexed ? ft.indexedChars : undefined,
indexedPages: indexed ? ft.indexedPages : undefined,
};
// Optionally pull exact pages once (shared by passages / page_range).
let pages = null;
// Optionally pull exact pages once (shared by passages / page_range). When the text
// came from the PDF fallback we already hold the exact pages.
let tooLarge = false;
if (args.precise_pages) {
if (!pages && args.precise_pages) {
// Pre-download guard: skip the (potentially large) file transfer + pdfjs extraction

@@ -112,5 +158,4 @@ // when the attachment is already known to exceed the safe size for this host. pdfjs can

const exact = Boolean(pages && pages.length);
const pageSource = args.precise_pages ? (exact ? 'exact' : 'approximate') : 'approximate';
const maxMb = Math.round(DEFAULT_PRECISE_MAX_BYTES / (1024 * 1024));
const degradeNotice = args.precise_pages && !exact
const pageSource = exact ? 'exact' : 'approximate';
const degradeNotice = indexed && args.precise_pages && !exact
? tooLarge

@@ -152,4 +197,5 @@ ? ` Exact pages skipped: this PDF exceeds the ${maxMb} MB re-extraction limit on this instance; pageApprox is an estimate.`

(truncated ? ' Some lower-ranked passages omitted (max_chars).' : '') +
sourceNotice +
degradeNotice;
return ok({ ...base, mode: 'passages', pageSource, passages, truncated, notice: degradeNotice.trim() || undefined }, summary);
return ok({ ...base, mode: 'passages', pageSource, passages, truncated, notice: (sourceNotice + degradeNotice).trim() || undefined }, summary);
}

@@ -184,5 +230,6 @@ // --- page_range mode ---

omittedChars: truncated ? slice.length - maxChars : 0,
notice: (degradeNotice + emptyNotice).trim() || undefined,
notice: (sourceNotice + degradeNotice + emptyNotice).trim() || undefined,
}, `Text for pages ${args.page_range} of ${args.item_key} (${pageSource}).` +
(truncated ? ' Truncated (max_chars).' : '') +
sourceNotice +
degradeNotice +

@@ -194,6 +241,8 @@ emptyNotice);

const text = truncated ? content.slice(0, maxChars) : content;
const notice = truncated
? `Truncated to ${maxChars} of ${content.length} chars — pass query (for relevant passages), page_range, or a larger max_chars.`
: undefined;
return ok({ ...base, mode: 'document', pageSource, text, truncated, omittedChars: truncated ? content.length - maxChars : 0, notice }, `Full text of ${args.item_key}: ${content.length} chars${truncated ? `, returned first ${maxChars}` : ''}.`);
const truncNotice = truncated
? ` Truncated to ${maxChars} of ${content.length} chars — pass query (for relevant passages), page_range, or a larger max_chars.`
: '';
const notice = (sourceNotice + truncNotice).trim() || undefined;
return ok({ ...base, mode: 'document', pageSource, text, truncated, omittedChars: truncated ? content.length - maxChars : 0, notice }, `Full text of ${args.item_key}: ${content.length} chars${truncated ? `, returned first ${maxChars}` : ''} ` +
`(${fulltextSource === 'pdf' ? 'extracted from the PDF directly' : 'from the Zotero full-text index'}).`);
},

@@ -200,0 +249,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"file":"get-fulltext.js","sourceRoot":"","sources":["../../src/tools/get-fulltext.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"get-fulltext.js","sourceRoot":"","sources":["../../src/tools/get-fulltext.ts"],"names":[],"mappings":"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"}
import { z } from 'zod';
import { ok, requireCloudLibrary } from '../registry/registry.js';
import { ok, requireCloudLibrary, isLocalWritesUnavailable, ensureLocalApi } from '../registry/registry.js';
import { arxivItem, fromScholarWork, parseIdentifier, bareDoi } from '../features/resolve/resolve.js';

@@ -45,3 +45,3 @@ function err(text) {

title: 'Import items by identifier or URL',
description: 'Resolve bibliographic metadata to Zotero item-data and optionally save it to your library. `action: "by_identifier"` resolves a DOI, ISBN, PMID, arXiv id, or ADS bibcode (set `identifier`); `action: "by_url"` scrapes a web page (set `url`) and may return multiple choices to pick from. Set `save_to_library:true` (and optionally `collection_key`) to persist the resolved items (requires a cloud API key); otherwise the resolved metadata is returned without saving. When a Zotero translation-server is reachable (ZOTEUS_TRANSLATION_SERVER_URL, default http://127.0.0.1:1969) it is the primary path; if none is running, DOI and arXiv ids fall back to built-in resolution (OpenAlex/Crossref and the arXiv API respectively) — the result then carries a `source` field ("scholar" or "arxiv"). ISBN/PMID/bibcode and web URLs require a translation-server.',
description: 'Resolve bibliographic metadata to Zotero item-data and optionally save it to your library. `action: "by_identifier"` resolves a DOI, ISBN, PMID, arXiv id, or ADS bibcode (set `identifier`); `action: "by_url"` scrapes a web page (set `url`) and may return multiple choices to pick from. Set `save_to_library:true` (and optionally `collection_key`) to persist the resolved items — saved into the running Zotero desktop app when available, otherwise via the cloud Web API (requires ZOTERO_API_KEY); otherwise the resolved metadata is returned without saving. When a Zotero translation-server is reachable (ZOTEUS_TRANSLATION_SERVER_URL, default http://127.0.0.1:1969) it is the primary path; if none is running, DOI and arXiv ids fall back to built-in resolution (OpenAlex/Crossref and the arXiv API respectively) — the result then carries a `source` field ("scholar" or "arxiv"). ISBN/PMID/bibcode and web URLs require a translation-server.',
inputSchema: {

@@ -51,4 +51,6 @@ action: z.enum(['by_identifier', 'by_url']),

url: z.string().optional().describe('Web page URL to scrape (needs a translation-server).'),
save_to_library: z.boolean().optional().describe('Persist the resolved items (needs a cloud key).'),
collection_key: z.string().optional().describe('Collection to add saved items to.'),
save_to_library: z.boolean().optional().describe('Persist the resolved items — into the running Zotero desktop app when available, otherwise the cloud Web API (needs a cloud key).'),
collection_key: z.string().optional().describe('Collection to add saved items to: an 8-char collection key or a Zotero treeViewID like "C20".'),
attach_url: z.string().url().optional().describe('File URL (e.g. an arXiv PDF) to download and attach as a stored attachment to the (single) imported item when saving to the desktop app.'),
attach_title: z.string().optional().describe('Title for the attached file, e.g. "Full Text PDF".'),
library_type: z.enum(['user', 'group']).optional(),

@@ -73,3 +75,3 @@ library_id: z.number().int().optional(),

if (items.length)
return maybeSave(ctx, args, items, 'translation-server');
return await maybeSave(ctx, args, items, 'translation-server');
}

@@ -79,3 +81,3 @@ // translation-server down (or the identifier failed): try the built-in path.

const { items, source } = await resolveBuiltin(ctx, args.identifier);
return maybeSave(ctx, args, items, source);
return await maybeSave(ctx, args, items, source);
}

@@ -96,3 +98,3 @@ catch (e) {

return err(`No items found at ${args.url}.`);
return maybeSave(ctx, args, items, 'translation-server');
return await maybeSave(ctx, args, items, 'translation-server');
},

@@ -110,3 +112,73 @@ };

}
const lib = requireCloudLibrary(ctx, args);
// Prefer the desktop app for the personal library (no cloud key needed);
// fall back to the cloud Web API otherwise.
if (!args.library_id && (await ensureLocalApi(ctx)) && ctx.localWrites) {
try {
if (args.collection_key) {
for (const it of payload)
it.collections = [...(it.collections ?? []), args.collection_key];
}
const result = await ctx.localWrites.writeItems(payload);
return ok({ created: result.successful.map((s) => s.key), failed: result.failed, resolved: payload.length, source, target: 'local' }, `Imported ${result.successful.length} of ${payload.length} resolved item(s) via ${source} into the library (Zotero desktop).`);
}
catch (e) {
if (!isLocalWritesUnavailable(e))
throw e;
ctx.logger.info(`Local-API writes unavailable (${e instanceof Error ? e.message : e}); using the connector protocol.`);
}
}
if (!args.library_id && ctx.connectorWrites && (await ensureLocalApi(ctx))) {
// Connector protocol: collections are targeted by treeViewID via updateSession,
// not by the collections array, so strip it from the payload.
const stripped = payload.map(({ collections: _c, ...rest }) => rest);
const { sessionID, connectorIds } = await ctx.connectorWrites.saveItems(stripped, {
uri: 'zotero://zoteus/import',
});
let placedIn;
if (args.collection_key) {
try {
const target = await resolveTreeViewId(ctx, args.collection_key);
if (target) {
await ctx.connectorWrites.updateSession(sessionID, { target });
placedIn = target;
}
}
catch (e) {
return ok({ sessionID, resolved: stripped.length, source, target: 'desktop', warning: String(e) }, `Saved ${stripped.length} item(s) via ${source}, but could not place them in "${args.collection_key}": ${e}`);
}
}
let attached;
if (args.attach_url && connectorIds[0]) {
const res = await ctx.fetcher.fetch(args.attach_url, { method: 'GET' }, { maxRetries: 2, deadlineMs: 300_000 });
if (!res.ok) {
return ok({ sessionID, resolved: stripped.length, source, target: 'desktop', warning: `File download failed (${res.status}) for ${args.attach_url}` }, `Saved ${stripped.length} item(s) via ${source}; attachment download failed (${res.status}).`);
}
const contentType = res.headers.get('content-type')?.split(';')[0] ?? 'application/pdf';
const bytes = new Uint8Array(await res.arrayBuffer());
await ctx.connectorWrites.saveAttachment({
sessionID,
parentConnectorId: connectorIds[0],
url: args.attach_url,
title: args.attach_title ?? 'Full Text PDF',
bytes,
contentType,
});
attached = { bytes: bytes.length, contentType };
}
const created = await pollImportedItems(ctx, stripped);
return ok({
sessionID,
created,
resolved: stripped.length,
source,
target: 'desktop',
placedIn,
attached,
note: created.length < stripped.length
? 'Some items could not be matched back yet; they may still appear in Zotero.'
: undefined,
}, `Imported ${created.length}/${stripped.length} resolved item(s) via ${source} into the running Zotero desktop app` +
(placedIn ? ` (collection ${placedIn})` : '') +
(attached ? `, with ${attached.bytes}-byte PDF attached` : '') + '.');
}
if (args.collection_key) {

@@ -116,6 +188,74 @@ for (const it of payload)

}
let lib;
try {
lib = requireCloudLibrary(ctx, args);
}
catch (e) {
return {
content: [{
type: 'text',
text: `${e instanceof Error ? e.message : e} Tip: with the Zotero desktop app running, saving needs no cloud key — start the app (or set ZOTEUS_LOCAL=on) and retry.`,
}],
isError: true,
};
}
const result = await ctx.web.writeItems(lib, payload);
return ok({ created: result.successful.map((s) => s.key), failed: result.failed, resolved: payload.length, source }, `Imported ${result.successful.length} of ${payload.length} resolved item(s) via ${source} into the library.`);
return ok({
created: result.successful.map((s) => s.key),
failed: result.failed,
resolved: payload.length,
source,
target: 'cloud',
warning: args.attach_url ? 'attach_url is only supported for desktop-app saves; the file was not attached.' : undefined,
}, `Imported ${result.successful.length} of ${payload.length} resolved item(s) via ${source} into the library.`);
}
export default importTool;
/**
* Resolve a caller-supplied collection to the connector protocol's treeViewID
* ("L1" for My Library, "C<id>" for collections). Accepts a treeViewID directly,
* or an 8-char collection key that is matched by name against the app's target list.
*/
async function resolveTreeViewId(ctx, collectionKey) {
if (/^[CL]\d+$/.test(collectionKey))
return collectionKey;
const collections = await ctx.router.listCollections({ limit: 1000 });
const match = collections.data
.map((c) => c?.data ?? c)
.find((c) => c?.key === collectionKey);
if (!match)
throw new Error(`Collection key ${collectionKey} not found in the library.`);
const { targets } = await ctx.connectorWrites.getSelectedCollection();
const byName = targets.filter((t) => t.name === match.name);
if (!byName.length)
return undefined;
if (byName.length > 1) {
throw new Error(`Multiple collections named "${match.name}" exist (${byName.map((t) => t.id).join(', ')}); pass an explicit treeViewID instead.`);
}
return byName[0]?.id;
}
/** Recover the keys of items just saved through the connector protocol (no payload). */
async function pollImportedItems(ctx, sent) {
const found = [];
const deadline = Date.now() + 15_000;
const wanted = new Set(sent.map((it) => String(it.title ?? '')));
while (wanted.size && Date.now() < deadline) {
try {
const res = await ctx.local.listItems({ sort: 'dateAdded', direction: 'desc', limit: 25 });
for (const item of res.data) {
const d = item?.data ?? item;
const title = String(d?.title ?? '');
if (wanted.has(title)) {
wanted.delete(title);
found.push(d.key);
}
}
}
catch {
// Keep polling until the deadline.
}
if (wanted.size)
await new Promise((r) => setTimeout(r, 750));
}
return found;
}
//# sourceMappingURL=import.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/tools/import.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/tools/import.ts"],"names":[],"mappings":"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"}
import { z } from 'zod';
import { ok } from '../registry/registry.js';
import { saveIndex } from '../features/search/persistence.js';
const MAX_ITEMS = 5000;
async function fetchAllItems(ctx, lib) {
const all = [];
let start = 0;
for (;;) {
const page = await ctx.web.listItems(lib, { limit: 100, start, top: true });
all.push(...page.data);
start += page.data.length;
if (page.data.length === 0 || all.length >= page.totalResults || all.length >= MAX_ITEMS)
break;
}
return all;
}
import { MAX_ITEMS, progressLine, startIndexBuild, statusSummary } from '../features/search/build.js';
const indexTool = {
name: 'zotero_index',
title: 'Build the semantic search index',
description: "Build, refresh, or report the status of the local hybrid-search index used by zotero_semantic_search. `action: \"build\"` (or \"refresh\") fetches the library's top-level items and indexes their text (title, abstract, creators, tags) for BM25 keyword search and — if an embedding provider is configured — vector search; the index is persisted under the Zoteus data dir. `action: \"status\"` reports the index size and which embedder is active (it falls back to keyword-only when no local model or embedding API is available). Run a build before semantic searching, and refresh after large library changes.",
description: "Manage the local hybrid-search index used by zotero_semantic_search. The build runs as a background job on the server, so this tool returns immediately — never blocks on large libraries. `action: \"build\"` (or \"refresh\") starts a background build: it pages the library's top-level items (100-at-a-time, capped at 5000 items unless a smaller `limit` is given), indexes their text (title, abstract, creators, tags) for BM25 keyword search and — if an embedding provider is configured — vector search, persisting partial progress atomically as it goes. Start a build, then POLL `action: \"status\"` every few seconds until `state` is \"done\" (or \"error\"); calling build again while one is running just returns current progress. `action: \"status\"` reports the build state (idle|building|done|error), fetch/embed progress, index size and the active embedder. `action: \"stop\"` cancels a running build (partial data is kept and stays searchable). A partially built index is always usable for keyword search. Local embeddings are CPU-bound (see ZOTEUS_EMBEDDINGS), so large builds take a while — poll status rather than retrying build.",
inputSchema: {
action: z.enum(['build', 'refresh', 'status']),
action: z.enum(['build', 'refresh', 'status', 'stop']),
library_type: z.enum(['user', 'group']).optional(),
library_id: z.number().int().optional(),
limit: z
.number()
.int()
.min(1)
.max(MAX_ITEMS)
.optional()
.describe(`Max items to index (default ${MAX_ITEMS}, which is also the hard cap).`),
},

@@ -29,13 +23,24 @@ annotations: { readOnlyHint: false, openWorldHint: true },

if (args.action === 'status') {
const s = ctx.search.status();
return ok({ ...s }, `Index: ${s.documents} passages over ${s.items} items; embedder=${s.embedder}.`);
const s = ctx.search.buildStatus();
return ok({ ...s }, statusSummary(s));
}
if (args.action === 'stop') {
const stopped = ctx.search.requestStop();
if (stopped) {
return ok({ ...ctx.search.buildStatus() }, 'Stop requested — the build halts after the current page/batch and keeps the partial index. Poll action:"status".');
}
return ok({ ...ctx.search.buildStatus() }, 'No build is currently running.');
}
// build / refresh: kick off a background job and return immediately.
if (ctx.search.isBuilding) {
const s = ctx.search.buildStatus();
return ok({ ...s }, `A build is already in progress — ${progressLine(s)}. Poll action:"status" instead of starting another build.`);
}
const lib = args.library_id
? { type: (args.library_type ?? 'group'), id: args.library_id }
: ctx.router.defaultLibrary();
const items = await fetchAllItems(ctx, lib);
const status = await ctx.search.build(items, { version: items.length });
await saveIndex(ctx.search, ctx.searchIndexPath).catch((e) => ctx.logger.warn(`Could not persist index: ${e instanceof Error ? e.message : String(e)}`));
return ok({ ...status }, `Indexed ${status.documents} passages over ${status.items} items (embedder=${status.embedder}). ` +
'The index is ready — run zotero_semantic_search now to search the library by meaning.');
: undefined;
const maxItems = Math.min(args.limit ?? MAX_ITEMS, MAX_ITEMS);
const s = startIndexBuild(ctx, lib, maxItems);
return ok({ ...s }, `Index build started in the background (up to ${maxItems} items). ` +
'Poll zotero_index action:"status" every few seconds until state is "done"; use action:"stop" to cancel.');
},

@@ -42,0 +47,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"file":"index-tool.js","sourceRoot":"","sources":["../../src/tools/index-tool.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index-tool.js","sourceRoot":"","sources":["../../src/tools/index-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,EAAE,EAAE,MAAM,yBAAyB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGtG,MAAM,SAAS,GAAmB;IAChC,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,iCAAiC;IACxC,WAAW,EACT,mnCAAmnC;IACrnC,WAAW,EAAE;QACX,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtD,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;QAClD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACvC,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,SAAS,CAAC;aACd,QAAQ,EAAE;aACV,QAAQ,CAAC,+BAA+B,SAAS,gCAAgC,CAAC;KACtF;IACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;IACzD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC3B,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACnC,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACzC,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,EAAE,CACP,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,EAC/B,kHAAkH,CACnH,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE,gCAAgC,CAAC,CAAC;QAC/E,CAAC;QAED,qEAAqE;QACrE,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACnC,OAAO,EAAE,CACP,EAAE,GAAG,CAAC,EAAE,EACR,oCAAoC,YAAY,CAAC,CAAC,CAAC,2DAA2D,CAC/G,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAA2B,IAAI,CAAC,UAAU;YACjD,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,YAAY,IAAI,OAAO,CAAqB,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE;YACnF,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,EAAE,SAAS,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC9C,OAAO,EAAE,CACP,EAAE,GAAG,CAAC,EAAE,EACR,gDAAgD,QAAQ,WAAW;YACjE,yGAAyG,CAC5G,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,SAAS,CAAC"}

@@ -18,2 +18,4 @@ import whoami from './whoami.js';

import attachment from './attachment.js';
import annotate from './annotate.js';
import attachFile from './attach-file.js';
import importTool from './import.js';

@@ -51,2 +53,4 @@ import styles from './styles.js';

attachment,
annotate,
attachFile,
// Citation pipeline (M5)

@@ -53,0 +57,0 @@ importTool,

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,OAAO,MAAM,eAAe,CAAC;AACpC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,iBAAiB,MAAM,yBAAyB,CAAC;AACxD,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,SAAS,MAAM,iBAAiB,CAAC;AACxC,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAClD,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,eAAe,MAAM,uBAAuB,CAAC;AACpD,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,MAAM,CAAC,MAAM,KAAK,GAAqB;IACrC,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,UAAU;IACV,aAAa;IACb,WAAW;IACX,UAAU;IACV,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,UAAU;IACV,aAAa;IACb,sCAAsC;IACtC,MAAM;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,IAAI;IACJ,UAAU;IACV,yBAAyB;IACzB,UAAU;IACV,MAAM;IACN,kBAAkB;IAClB,YAAY;IACZ,8BAA8B;IAC9B,SAAS;IACT,cAAc;IACd,+BAA+B;IAC/B,OAAO;IACP,kCAAkC;IAClC,WAAW;IACX,uDAAuD;IACvD,QAAQ;IACR,eAAe;IACf,QAAQ;CACT,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,OAAO,MAAM,eAAe,CAAC;AACpC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,iBAAiB,MAAM,yBAAyB,CAAC;AACxD,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,SAAS,MAAM,iBAAiB,CAAC;AACxC,OAAO,cAAc,MAAM,sBAAsB,CAAC;AAClD,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,eAAe,MAAM,uBAAuB,CAAC;AACpD,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,MAAM,CAAC,MAAM,KAAK,GAAqB;IACrC,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,UAAU;IACV,aAAa;IACb,WAAW;IACX,UAAU;IACV,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,UAAU;IACV,aAAa;IACb,sCAAsC;IACtC,MAAM;IACN,UAAU;IACV,QAAQ;IACR,WAAW;IACX,IAAI;IACJ,UAAU;IACV,QAAQ;IACR,UAAU;IACV,yBAAyB;IACzB,UAAU;IACV,MAAM;IACN,kBAAkB;IAClB,YAAY;IACZ,8BAA8B;IAC9B,SAAS;IACT,cAAc;IACd,+BAA+B;IAC/B,OAAO;IACP,kCAAkC;IAClC,WAAW;IACX,uDAAuD;IACvD,QAAQ;IACR,eAAe;IACf,QAAQ;CACT,CAAC"}
import { z } from 'zod';
import { ok } from '../registry/registry.js';
import { progressLine, startIndexBuild } from '../features/search/build.js';
const semanticSearch = {
name: 'zotero_semantic_search',
title: 'Semantic / hybrid library search',
description: 'Search the library by meaning, not just keywords. Combines BM25 keyword scoring with vector similarity (when an embedding provider is configured) via reciprocal-rank fusion, and returns the best-matching items with a snippet and score. `mode`: "auto" (hybrid, default), "keyword" (BM25 only), or "semantic" (vector only). Requires the index to be built first with zotero_index (action:"build"); if it is empty, this returns guidance to build it. For exact field/tag/itemType filtering use zotero_search_items instead; use this for conceptual/"papers about X" queries. To read the actual passages of a found item (with page locators) use zotero_get_fulltext.',
description: 'Search the library by meaning, not just keywords. Combines BM25 keyword scoring with vector similarity (when an embedding provider is configured) via reciprocal-rank fusion, and returns the best-matching items with a snippet and score. `mode`: "auto" (hybrid, default), "keyword" (BM25 only), or "semantic" (vector only). The index must be built once before first use: when it is empty this tool starts a background build automatically (`auto_build`, on by default) and tells you to poll zotero_index action:"status" and retry — pass `auto_build:false` to opt out. For exact field/tag/itemType filtering use zotero_search_items instead; use this for conceptual/"papers about X" queries. To read the actual passages of a found item (with page locators) use zotero_get_fulltext.',
inputSchema: {

@@ -11,2 +12,6 @@ q: z.string().min(1).describe('Natural-language query.'),

mode: z.enum(['auto', 'keyword', 'semantic']).optional(),
auto_build: z
.boolean()
.optional()
.describe('Start building the index automatically in the background when it is empty (default true).'),
},

@@ -16,2 +21,33 @@ annotations: { readOnlyHint: true, openWorldHint: true },

if (ctx.search.isEmpty) {
// A build is already on its way (started here or via zotero_index): report progress.
if (ctx.search.isBuilding) {
const s = ctx.search.buildStatus();
return {
content: [
{
type: 'text',
text: `The semantic-search index is being built right now — ${progressLine(s)}. ` +
'Poll zotero_index with action:"status" until state is "done", then retry this search.',
},
],
structuredContent: { ...s, autoBuild: true },
isError: true,
};
}
if (args.auto_build !== false) {
// First use: populate the index on the fly instead of leaving the user stranded.
const s = startIndexBuild(ctx);
return {
content: [
{
type: 'text',
text: 'The semantic-search index is empty, so a background build was started automatically ' +
`(first-time setup; ${progressLine(s)}). Poll zotero_index with action:"status" every few seconds ` +
'until state is "done", then retry this search. Pass auto_build:false to opt out.',
},
],
structuredContent: { ...s, autoBuild: true },
isError: true,
};
}
return {

@@ -18,0 +54,0 @@ content: [

@@ -1,1 +0,1 @@

{"version":3,"file":"semantic-search.js","sourceRoot":"","sources":["../../src/tools/semantic-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,EAAE,EAAE,MAAM,yBAAyB,CAAC;AAE7C,MAAM,cAAc,GAAmB;IACrC,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,kCAAkC;IACzC,WAAW,EACT,mpBAAmpB;IACrpB,WAAW,EAAE;QACX,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACxD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACvF,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;KACzD;IACD,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACxD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC3B,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,oFAAoF;qBAC3F;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1F,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM;YACzB,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,mBAAmB,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI;YAC9E,CAAC,CAAC,mBAAmB,IAAI,CAAC,CAAC,IAAI,CAAC;QAClC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;CACF,CAAC;AAEF,eAAe,cAAc,CAAC"}
{"version":3,"file":"semantic-search.js","sourceRoot":"","sources":["../../src/tools/semantic-search.ts"],"names":[],"mappings":"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"}
import { z } from 'zod';
import { ok, requireCloudLibrary } from '../registry/registry.js';
import { ok, requireCloudLibrary, isLocalWritesUnavailable, ensureLocalApi } from '../registry/registry.js';
function versionOf(item) {

@@ -9,3 +9,3 @@ return item?.version ?? item?.data?.version;

title: 'Trash or restore Zotero items',
description: 'Move items to the trash (the safe, REVERSIBLE default) or restore them. This sets the `deleted` flag (1=trash, 0=restore) — it is NOT a permanent delete, so trashed items can be recovered here or in the Zotero app. Use this instead of zotero_delete_items unless you truly need irreversible removal. Provide `item_keys` and optional `action` (default "trash"). Writes go to the cloud Web API.',
description: 'Move items to the trash (the safe, REVERSIBLE default) or restore them. This sets the `deleted` flag (1=trash, 0=restore) — it is NOT a permanent delete, so trashed items can be recovered here or in the Zotero app. Use this instead of zotero_delete_items unless you truly need irreversible removal. Provide `item_keys` and optional `action` (default "trash"). Writes go to the running Zotero desktop app for your personal library (via its local-API writes where available), otherwise to the cloud Web API.',
inputSchema: {

@@ -19,4 +19,23 @@ item_keys: z.array(z.string()).min(1).describe('Item keys to trash or restore.'),

handler: async (args, ctx) => {
const deleted = args.action === 'restore' ? 0 : 1;
// Local-first for the personal library when the desktop app supports writes.
if (ctx.localWrites && !args.library_id && (await ensureLocalApi(ctx))) {
try {
if (deleted === 1) {
await ctx.localWrites.deleteItems(args.item_keys, false);
return ok({ updated: args.item_keys, target: 'local' }, `Trashed ${args.item_keys.length} item(s) via the Zotero desktop app.`);
}
const objects = [];
for (const key of args.item_keys)
objects.push({ key, deleted: 0 });
const result = await ctx.localWrites.writeItems(objects);
return ok({ updated: result.successful.map((s) => s.key), failed: result.failed, target: 'local' }, `Restored ${result.successful.length} item(s) via the Zotero desktop app.`);
}
catch (e) {
if (!isLocalWritesUnavailable(e))
throw e;
ctx.logger.info(`Local-API writes unavailable (${e instanceof Error ? e.message : e}); falling back to the cloud Web API.`);
}
}
const lib = requireCloudLibrary(ctx, args);
const deleted = args.action === 'restore' ? 0 : 1;
const objects = [];

@@ -23,0 +42,0 @@ for (const key of args.item_keys) {

@@ -1,1 +0,1 @@

{"version":3,"file":"trash-items.js","sourceRoot":"","sources":["../../src/tools/trash-items.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,EAAE,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAElE,SAAS,SAAS,CAAC,IAAS;IAC1B,OAAO,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,GAAmB;IACjC,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,+BAA+B;IACtC,WAAW,EACT,yYAAyY;IAC3Y,WAAW,EAAE;QACX,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QAChF,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC5E,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;QAClD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;KACxC;IACD,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;IACjF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,OAAO,GAAU,EAAE,CAAC;QAC1B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;QAC9C,MAAM,OAAO,GACX,GAAG,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,UAAU;YAC7C,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACrE,OAAO,EAAE,CACP,EAAE,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,iBAAiB,EAAE,EACjH,OAAO,CACR,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,UAAU,CAAC"}
{"version":3,"file":"trash-items.js","sourceRoot":"","sources":["../../src/tools/trash-items.ts"],"names":[],"mappings":"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"}
{
"name": "@oscardvs/zoteus",
"version": "1.1.0",
"version": "1.2.0",
"description": "The everything Zotero MCP server — complete Zotero Web API v3 + desktop local API for Claude and any MCP client.",

@@ -5,0 +5,0 @@ "keywords": [

+20
-13

@@ -7,3 +7,3 @@ <div align="center">

The **everything Zotero MCP server**. Give Claude, Cursor, and any [MCP](https://modelcontextprotocol.io) client complete, **safe** access to your [Zotero](https://www.zotero.org) library — search papers, add by DOI, format bibliographies in ~2,800 styles, run semantic search over your own PDFs, and ground every answer in a source you actually own. **Local-first. Private. One command.**
The **everything Zotero MCP server**. Give Claude, Cursor, and any [MCP](https://modelcontextprotocol.io) client complete, **safe** access to your [Zotero](https://www.zotero.org) library — search papers, add by DOI, format bibliographies in ~2,800 styles, run semantic search over your library's metadata and abstracts, pull exact passages from your PDFs, and ground every answer in a source you actually own. **Local-first. Private. One command.**

@@ -29,10 +29,12 @@ [![npm](https://img.shields.io/npm/v/@oscardvs/zoteus.svg?color=2ea44f)](https://www.npmjs.com/package/@oscardvs/zoteus)

For normal use there is **nothing to download or unzip from GitHub** — your AI app fetches Zoteus automatically when it first runs. New to this? Follow the no-code getting-started guide → [`docs/getting-started.md`](./docs/getting-started.md)
| Client | Command |
|---|---|
| **Claude Desktop (one-click)** | download `zoteus.mcpb` from the [latest release](https://github.com/oscardvs/zoteus/releases/latest) → double-click |
| **Claude Code** | `claude mcp add --transport stdio zoteus -- npx -y @oscardvs/zoteus` |
| **Cursor / VS Code / Claude Desktop / Codex / Zed…** | `npx add-mcp @oscardvs/zoteus` |
| **Claude Desktop (one-click)** | download `zoteus.mcpb` from the [latest release](https://github.com/oscardvs/zoteus/releases/latest) → double-click |
| **claude.ai (web)** | Add custom connector → your hosted URL (OAuth) |
Add your cloud key for writes/sync/groups (optional — reads work key-free against the desktop app):
Add your cloud key for sync, group libraries, and writes without the desktop app (optional — reads *and* personal-library writes work key-free against a running Zotero):

@@ -43,3 +45,3 @@ ```bash

> Get a key at [zotero.org/settings/keys](https://www.zotero.org/settings/keys). For key-free local reads, enable **Settings → Advanced → "Allow other applications on this computer to communicate with Zotero"** in the desktop app.
> Get a key at [zotero.org/settings/keys](https://www.zotero.org/settings/keys). For key-free local reads and writes, enable **Settings → Advanced → "Allow other applications on this computer to communicate with Zotero"** in the desktop app.

@@ -58,3 +60,3 @@ ---

| CSL bibliographies (~2,800 styles) | ✅ | rare | ❌ |
| Local hybrid semantic search over PDFs | ✅ | some (cloud) | varies |
| Local hybrid semantic search + full-text PDF retrieval | ✅ | some (cloud) | varies |
| No Python — TypeScript, one `npx` | ✅ | varies | n/a |

@@ -66,9 +68,11 @@ | MCP Resources + Prompts + code-execution | ✅ | ❌ | n/a |

- **Find anything in your own work.** *"Find papers in my library that argue against X"* — hybrid keyword + semantic search across metadata, full text, and annotations, returned **with the page number**.
- **Find anything in your own work.** *"Find papers in my library that argue against X"* — hybrid keyword + semantic search over your library's titles, abstracts, creators, and tags, plus full-text keyword search inside your PDFs and notes, with the matching passage returned **with the page number**.
- **Cite without hallucinating.** Zoteus surfaces *your* Zotero citation data and formats it with [citeproc-js](https://citeproc-js.readthedocs.io) in any [CSL](https://citationstyles.org) style — it never invents a reference.
- **Add a paper by identifier.** Drop in a DOI or arXiv id and Zoteus fetches the metadata and files it — works out of the box via built-in resolvers, no extra services needed (a Zotero translation-server extends this to ISBN/PMID/URLs; see [`docs/resolver.md`](./docs/resolver.md)).
- **Write back, safely.** Create items, edit, tag, organize — versioned with optimistic-locking retries, reversible trash by default, permanent delete opt-in and confirmation-gated.
- **Ground claims in the PDF.** `zotero_get_fulltext` returns the relevant passage with character offsets, nearest heading, and a page locator.
- **Write straight to the desktop app.** Personal-library writes go to your running Zotero — **no cloud API key needed**. On Zotero 9+ that's the local API behind a key you grant once ("Always Allow"); on older builds it's the same connector protocol the browser extensions use. The cloud Web API is the fallback for group libraries and for when the app isn't running.
- **Annotate PDFs and attach files.** `zotero_annotate` adds real highlights, underlines, and notes — the same objects the Zotero PDF reader creates, positioned on the page — and `zotero_attach_file` stores a local file or a URL as an attachment under any item.
- **Ground claims in the PDF.** `zotero_get_fulltext` returns the relevant passage with character offsets, nearest heading, and a page locator — extracting the text on the fly when Zotero hasn't indexed the PDF.
- **Follow the scholarship.** A scholarly-context graph over OpenAlex / Crossref / Semantic Scholar.
- **Built for agents.** ~28 consolidated, well-described tools (not 70 thin endpoint mirrors), `zotero_*`-namespaced, structured outputs, and a generated tool tree for the [code-execution-with-MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) pattern.
- **Built for agents.** 30 consolidated, well-described tools (not 70 thin endpoint mirrors), `zotero_*`-namespaced, structured outputs, and a generated tool tree for the [code-execution-with-MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) pattern.

@@ -78,7 +82,9 @@ ## How it works

1. **Install** — one `npx` command (or the one-click `.mcpb`).
2. **Connect** — paste your Zotero API key (or just run the desktop app for key-free local reads).
2. **Connect** — just run the desktop app for key-free local access, or paste your Zotero API key.
3. **Ask** — your AI can now search, cite, add, and organize your library.
Zoteus auto-detects your running Zotero desktop app and uses its fast, key-free **local API** for reads (full PDFs, real saved-search results), falling back to the cloud **Web API v3** for writes, sync, and group libraries.
Zoteus auto-detects your running Zotero desktop app and talks to it directly: its fast, key-free **local API** for reads (full PDFs, real saved-search results), and the desktop app itself for personal-library writes (imports, annotations, attachments, trash). The cloud **Web API v3** is the fallback — and stays required for sync, group libraries, and writes when the app isn't running. Details: [`docs/writing.md`](./docs/writing.md).
> **Semantic search — one-time setup.** The first `zotero_semantic_search` builds the library index automatically in the background (auto-build). On very large libraries you can also run `zotero_index` (action:"build") yourself, then poll action:"status" until done.
## Configuration

@@ -88,4 +94,5 @@

|---|---|---|
| `ZOTERO_API_KEY` | — | Cloud auth (writes/sync/groups; optional for local-only reads) |
| `ZOTEUS_LOCAL` | `auto` | `auto\|on\|off` — use the Zotero desktop local API |
| `ZOTERO_API_KEY` | — | Cloud auth (sync, groups, writes without the desktop app; optional otherwise) |
| `ZOTEUS_LOCAL` | `auto` | `auto\|on\|off` — use the Zotero desktop app (reads + personal-library writes) |
| `ZOTEUS_LOCAL_API_KEY` | — | Pre-provision the Zotero 9+ desktop write key (else granted once, in-app) |
| `ZOTEUS_EMBEDDINGS` | `local` | `local\|openai\|gemini\|off` for semantic search |

@@ -98,3 +105,3 @@ | `ZOTEUS_ALLOW_DELETE` | `false` | Must be `true` to expose permanent deletion |

📚 **[zoteus.com/docs](https://zoteus.com/docs)** · [Configuration](./docs/configuration.md) · [Import & resolver](./docs/resolver.md) · [Architecture](./docs/architecture.md) · [Safe writes](./docs/writing.md) · [Citations](./docs/citations.md) · [Semantic search](./docs/semantic-search.md) · [Scholarly context](./docs/scholar.md) · [Code execution](./docs/code-execution.md) · [Deployment](./docs/deployment.md)
📚 **[zoteus.com/docs](https://zoteus.com/docs)** · [Getting started](./docs/getting-started.md) · [Configuration](./docs/configuration.md) · [Import & resolver](./docs/resolver.md) · [Architecture](./docs/architecture.md) · [Safe writes](./docs/writing.md) · [Citations](./docs/citations.md) · [Semantic search](./docs/semantic-search.md) · [Scholarly context](./docs/scholar.md) · [Code execution](./docs/code-execution.md) · [Deployment](./docs/deployment.md)

@@ -101,0 +108,0 @@ ## Contributing