@ncukondo/reference-manager 0.24.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +44 -1
  2. package/dist/chunks/{SearchableMultiSelect-CKRfbnka.js → SearchableMultiSelect-B7qEWPDT.js} +2 -2
  3. package/dist/chunks/{SearchableMultiSelect-CKRfbnka.js.map → SearchableMultiSelect-B7qEWPDT.js.map} +1 -1
  4. package/dist/chunks/{action-menu-BCgv1m3v.js → action-menu-DD0RtNVD.js} +3 -3
  5. package/dist/chunks/{action-menu-BCgv1m3v.js.map → action-menu-DD0RtNVD.js.map} +1 -1
  6. package/dist/chunks/checker-7pzK2XSC.js +92 -0
  7. package/dist/chunks/checker-7pzK2XSC.js.map +1 -0
  8. package/dist/chunks/crossref-client-DGNz4PNW.js +52 -0
  9. package/dist/chunks/crossref-client-DGNz4PNW.js.map +1 -0
  10. package/dist/chunks/fix-interaction-BpfMLRNY.js +203 -0
  11. package/dist/chunks/fix-interaction-BpfMLRNY.js.map +1 -0
  12. package/dist/chunks/{index-C36Us_zC.js → index-CYEise6v.js} +4 -4
  13. package/dist/chunks/{index-C36Us_zC.js.map → index-CYEise6v.js.map} +1 -1
  14. package/dist/chunks/{index-DWAtvFtp.js → index-D2HsxXnK.js} +203 -21
  15. package/dist/chunks/index-D2HsxXnK.js.map +1 -0
  16. package/dist/chunks/{index-zafRwZEZ.js → index-PQkbePWV.js} +3 -3
  17. package/dist/chunks/index-PQkbePWV.js.map +1 -0
  18. package/dist/chunks/{index-JA964gjc.js → index-QTYx5RaF.js} +285 -27
  19. package/dist/chunks/index-QTYx5RaF.js.map +1 -0
  20. package/dist/chunks/{loader-CV71qNY2.js → loader-B-fte1uv.js} +19 -8
  21. package/dist/chunks/loader-B-fte1uv.js.map +1 -0
  22. package/dist/chunks/pubmed-client-J18fg3fG.js +51 -0
  23. package/dist/chunks/pubmed-client-J18fg3fG.js.map +1 -0
  24. package/dist/chunks/{reference-select-Bbl-roAS.js → reference-select-Qpgt9cbN.js} +3 -3
  25. package/dist/chunks/{reference-select-Bbl-roAS.js.map → reference-select-Qpgt9cbN.js.map} +1 -1
  26. package/dist/chunks/{style-select-BeAktUts.js → style-select-mEMoWbM2.js} +3 -3
  27. package/dist/chunks/{style-select-BeAktUts.js.map → style-select-mEMoWbM2.js.map} +1 -1
  28. package/dist/cli/commands/check.d.ts +42 -0
  29. package/dist/cli/commands/check.d.ts.map +1 -0
  30. package/dist/cli/commands/index.d.ts +2 -0
  31. package/dist/cli/commands/index.d.ts.map +1 -1
  32. package/dist/cli/index.d.ts.map +1 -1
  33. package/dist/cli/server-client.d.ts +2 -1
  34. package/dist/cli/server-client.d.ts.map +1 -1
  35. package/dist/cli.js +1 -1
  36. package/dist/config/defaults.d.ts.map +1 -1
  37. package/dist/config/env-override.d.ts.map +1 -1
  38. package/dist/config/key-parser.d.ts.map +1 -1
  39. package/dist/config/loader.d.ts.map +1 -1
  40. package/dist/config/schema.d.ts +3 -0
  41. package/dist/config/schema.d.ts.map +1 -1
  42. package/dist/features/check/checker.d.ts +18 -0
  43. package/dist/features/check/checker.d.ts.map +1 -0
  44. package/dist/features/check/crossref-client.d.ts +24 -0
  45. package/dist/features/check/crossref-client.d.ts.map +1 -0
  46. package/dist/features/check/fix-actions.d.ts +16 -0
  47. package/dist/features/check/fix-actions.d.ts.map +1 -0
  48. package/dist/features/check/fix-interaction.d.ts +11 -0
  49. package/dist/features/check/fix-interaction.d.ts.map +1 -0
  50. package/dist/features/check/pubmed-client.d.ts +20 -0
  51. package/dist/features/check/pubmed-client.d.ts.map +1 -0
  52. package/dist/features/check/types.d.ts +23 -0
  53. package/dist/features/check/types.d.ts.map +1 -0
  54. package/dist/features/operations/check.d.ts +28 -0
  55. package/dist/features/operations/check.d.ts.map +1 -0
  56. package/dist/features/operations/index.d.ts +1 -0
  57. package/dist/features/operations/index.d.ts.map +1 -1
  58. package/dist/features/operations/library-operations.d.ts +8 -0
  59. package/dist/features/operations/library-operations.d.ts.map +1 -1
  60. package/dist/features/operations/operations-library.d.ts +2 -0
  61. package/dist/features/operations/operations-library.d.ts.map +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/mcp/tools/check.d.ts +10 -0
  64. package/dist/mcp/tools/check.d.ts.map +1 -0
  65. package/dist/mcp/tools/index.d.ts.map +1 -1
  66. package/dist/server/index.d.ts.map +1 -1
  67. package/dist/server/routes/check.d.ts +4 -0
  68. package/dist/server/routes/check.d.ts.map +1 -0
  69. package/dist/server.js +3 -3
  70. package/package.json +1 -1
  71. package/dist/chunks/index-DWAtvFtp.js.map +0 -1
  72. package/dist/chunks/index-JA964gjc.js.map +0 -1
  73. package/dist/chunks/index-zafRwZEZ.js.map +0 -1
  74. package/dist/chunks/loader-CV71qNY2.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { a } from "./index-DWAtvFtp.js";
2
- import { d, g, l, o, s } from "./index-JA964gjc.js";
1
+ import { a } from "./index-D2HsxXnK.js";
2
+ import { d, g, l, o, s } from "./index-QTYx5RaF.js";
3
3
  export {
4
4
  a as addAttachment,
5
5
  d as detachAttachment,
@@ -8,4 +8,4 @@ export {
8
8
  o as openAttachment,
9
9
  s as syncAttachments
10
10
  };
11
- //# sourceMappingURL=index-zafRwZEZ.js.map
11
+ //# sourceMappingURL=index-PQkbePWV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-PQkbePWV.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -5,9 +5,9 @@ import { promises, readFileSync, existsSync, mkdirSync, writeFileSync } from "no
5
5
  import * as os from "node:os";
6
6
  import * as path from "node:path";
7
7
  import path__default, { join, basename, dirname } from "node:path";
8
- import { n as normalizePathForOutput, d as deleteDirectoryIfEmpty, p as parseFilename, i as isReservedRole, e as ensureDirectory, a as addAttachment, R as RESERVED_ROLES, g as generateFilename, b as findFulltextFiles, c as findFulltextFile, h as extensionToFormat, j as fulltextAttach, k as fulltextGet, l as fulltextDiscover, m as fulltextFetch, o as fulltextConvert, q as getExtension, r as getDefaultExportFromCjs, B as BUILTIN_STYLES, s as getFulltextAttachmentTypes, t as startServerWithFileWatcher } from "./index-DWAtvFtp.js";
8
+ import { n as normalizePathForOutput, d as deleteDirectoryIfEmpty, p as parseFilename, i as isReservedRole, e as ensureDirectory, a as addAttachment, R as RESERVED_ROLES, b as generateFilename, c as findFulltextFiles, h as findFulltextFile, j as extensionToFormat, k as fulltextAttach, l as fulltextGet, m as fulltextDiscover, o as fulltextFetch, q as fulltextConvert, r as getExtension, s as getDefaultExportFromCjs, B as BUILTIN_STYLES, t as getFulltextAttachmentTypes, u as startServerWithFileWatcher } from "./index-D2HsxXnK.js";
9
9
  import { readFile, unlink, stat, readdir, rename } from "node:fs/promises";
10
- import { o as openWithSystemApp, l as loadConfig, e as getDefaultCurrentDirConfigFilename, h as getDefaultUserConfigPath } from "./loader-CV71qNY2.js";
10
+ import { o as openWithSystemApp, l as loadConfig, e as getDefaultCurrentDirConfigFilename, h as getDefaultUserConfigPath } from "./loader-B-fte1uv.js";
11
11
  import { spawn, spawnSync } from "node:child_process";
12
12
  import process$1, { stdin, stdout } from "node:process";
13
13
  import * as readline from "node:readline";
@@ -19,7 +19,7 @@ import "@citation-js/plugin-csl";
19
19
  import { ZodOptional as ZodOptional$2, z } from "zod";
20
20
  import { serve } from "@hono/node-server";
21
21
  const name = "@ncukondo/reference-manager";
22
- const version$1 = "0.24.1";
22
+ const version$1 = "0.25.0";
23
23
  const description$1 = "A local reference management tool using CSL-JSON as the single source of truth";
24
24
  const packageJson = {
25
25
  name,
@@ -902,15 +902,15 @@ class OperationsLibrary {
902
902
  }
903
903
  // High-level operations
904
904
  async search(options) {
905
- const { searchReferences } = await import("./index-DWAtvFtp.js").then((n) => n.A);
905
+ const { searchReferences } = await import("./index-D2HsxXnK.js").then((n) => n.E);
906
906
  return searchReferences(this.library, options);
907
907
  }
908
908
  async list(options) {
909
- const { listReferences } = await import("./index-DWAtvFtp.js").then((n) => n.z);
909
+ const { listReferences } = await import("./index-D2HsxXnK.js").then((n) => n.D);
910
910
  return listReferences(this.library, options ?? {});
911
911
  }
912
912
  async cite(options) {
913
- const { citeReferences } = await import("./index-DWAtvFtp.js").then((n) => n.y);
913
+ const { citeReferences } = await import("./index-D2HsxXnK.js").then((n) => n.C);
914
914
  const defaultStyle = options.defaultStyle ?? this.citationConfig?.defaultStyle;
915
915
  const cslDirectory = options.cslDirectory ?? this.citationConfig?.cslDirectory;
916
916
  const mergedOptions = {
@@ -921,32 +921,36 @@ class OperationsLibrary {
921
921
  return citeReferences(this.library, mergedOptions);
922
922
  }
923
923
  async import(inputs, options) {
924
- const { addReferences } = await import("./index-DWAtvFtp.js").then((n) => n.x);
924
+ const { addReferences } = await import("./index-D2HsxXnK.js").then((n) => n.z);
925
925
  return addReferences(inputs, this.library, options ?? {});
926
926
  }
927
+ async check(options) {
928
+ const { checkReferences } = await import("./index-D2HsxXnK.js").then((n) => n.A);
929
+ return checkReferences(this.library, options);
930
+ }
927
931
  // Attachment operations
928
932
  async attachAdd(options) {
929
- const { addAttachment: addAttachment2 } = await import("./index-zafRwZEZ.js");
933
+ const { addAttachment: addAttachment2 } = await import("./index-PQkbePWV.js");
930
934
  return addAttachment2(this.library, options);
931
935
  }
932
936
  async attachList(options) {
933
- const { listAttachments: listAttachments2 } = await import("./index-zafRwZEZ.js");
937
+ const { listAttachments: listAttachments2 } = await import("./index-PQkbePWV.js");
934
938
  return listAttachments2(this.library, options);
935
939
  }
936
940
  async attachGet(options) {
937
- const { getAttachment: getAttachment2 } = await import("./index-zafRwZEZ.js");
941
+ const { getAttachment: getAttachment2 } = await import("./index-PQkbePWV.js");
938
942
  return getAttachment2(this.library, options);
939
943
  }
940
944
  async attachDetach(options) {
941
- const { detachAttachment: detachAttachment2 } = await import("./index-zafRwZEZ.js");
945
+ const { detachAttachment: detachAttachment2 } = await import("./index-PQkbePWV.js");
942
946
  return detachAttachment2(this.library, options);
943
947
  }
944
948
  async attachSync(options) {
945
- const { syncAttachments: syncAttachments2 } = await import("./index-zafRwZEZ.js");
949
+ const { syncAttachments: syncAttachments2 } = await import("./index-PQkbePWV.js");
946
950
  return syncAttachments2(this.library, options);
947
951
  }
948
952
  async attachOpen(options) {
949
- const { openAttachment: openAttachment2 } = await import("./index-zafRwZEZ.js");
953
+ const { openAttachment: openAttachment2 } = await import("./index-PQkbePWV.js");
950
954
  return openAttachment2(this.library, options);
951
955
  }
952
956
  }
@@ -1084,6 +1088,18 @@ class ServerClient {
1084
1088
  }
1085
1089
  return await response.json();
1086
1090
  }
1091
+ async check(options) {
1092
+ const url2 = `${this.baseUrl}/api/check`;
1093
+ const response = await fetch(url2, {
1094
+ method: "POST",
1095
+ headers: { "Content-Type": "application/json" },
1096
+ body: JSON.stringify(options)
1097
+ });
1098
+ if (!response.ok) {
1099
+ throw new Error(await response.text());
1100
+ }
1101
+ return await response.json();
1102
+ }
1087
1103
  /**
1088
1104
  * Generate citations for references.
1089
1105
  * @param options - Cite options including identifiers and formatting
@@ -1790,7 +1806,7 @@ function getAttachExitCode(result) {
1790
1806
  }
1791
1807
  async function executeInteractiveSelect$2(context, config2) {
1792
1808
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
1793
- const { selectReferencesOrExit } = await import("./reference-select-Bbl-roAS.js");
1809
+ const { selectReferencesOrExit } = await import("./reference-select-Qpgt9cbN.js");
1794
1810
  const allReferences = await context.library.getAll();
1795
1811
  const identifiers = await withAlternateScreen2(
1796
1812
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -2281,6 +2297,192 @@ const attach = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
2281
2297
  runInteractiveMode,
2282
2298
  syncNewFilesWithRolePrompt
2283
2299
  }, Symbol.toStringTag, { value: "Module" }));
2300
+ function buildCheckOptions(options, appConfig) {
2301
+ const opOptions = {};
2302
+ if (options.all) {
2303
+ opOptions.all = true;
2304
+ } else if (options.search) {
2305
+ opOptions.searchQuery = options.search;
2306
+ } else if (options.identifiers.length > 0) {
2307
+ opOptions.identifiers = options.identifiers;
2308
+ }
2309
+ if (options.uuid) {
2310
+ opOptions.idType = "uuid";
2311
+ }
2312
+ if (options.days !== void 0) {
2313
+ opOptions.skipDays = options.days;
2314
+ }
2315
+ if (options.noSave) {
2316
+ opOptions.save = false;
2317
+ }
2318
+ if (appConfig) {
2319
+ const pubmed = {};
2320
+ if (appConfig.pubmed.email) pubmed.email = appConfig.pubmed.email;
2321
+ if (appConfig.pubmed.apiKey) pubmed.apiKey = appConfig.pubmed.apiKey;
2322
+ opOptions.config = {
2323
+ ...appConfig.email ? { email: appConfig.email } : {},
2324
+ pubmed
2325
+ };
2326
+ }
2327
+ return opOptions;
2328
+ }
2329
+ async function executeCheck(options, context, appConfig) {
2330
+ return context.library.check(buildCheckOptions(options, appConfig));
2331
+ }
2332
+ function getStatusLabel(result) {
2333
+ if (result.status === "skipped") return "[SKIPPED]";
2334
+ if (result.status === "ok") return "[OK]";
2335
+ const finding = result.findings[0];
2336
+ if (!finding) return "[WARNING]";
2337
+ switch (finding.type) {
2338
+ case "retracted":
2339
+ return "[RETRACTED]";
2340
+ case "concern":
2341
+ return "[CONCERN]";
2342
+ case "version_changed":
2343
+ return "[VERSION]";
2344
+ case "metadata_changed":
2345
+ return "[METADATA]";
2346
+ default:
2347
+ return "[WARNING]";
2348
+ }
2349
+ }
2350
+ function formatFindingDetails(finding) {
2351
+ const lines = [];
2352
+ lines.push(` ${finding.message}`);
2353
+ if (finding.details?.retractionDoi) {
2354
+ lines.push(` Retraction notice: https://doi.org/${finding.details.retractionDoi}`);
2355
+ }
2356
+ if (finding.details?.newDoi) {
2357
+ lines.push(` New DOI: https://doi.org/${finding.details.newDoi}`);
2358
+ }
2359
+ return lines;
2360
+ }
2361
+ function formatCheckTextOutput(result) {
2362
+ const lines = [];
2363
+ for (const r of result.results) {
2364
+ const label = getStatusLabel(r);
2365
+ lines.push(`${label} ${r.id}`);
2366
+ for (const finding of r.findings) {
2367
+ lines.push(...formatFindingDetails(finding));
2368
+ }
2369
+ lines.push("");
2370
+ }
2371
+ const { summary } = result;
2372
+ const parts = [`${summary.total} checked`];
2373
+ if (summary.warnings > 0) parts.push(`${summary.warnings} warning(s)`);
2374
+ if (summary.ok > 0) parts.push(`${summary.ok} ok`);
2375
+ if (summary.skipped > 0) parts.push(`${summary.skipped} skipped`);
2376
+ lines.push(`Summary: ${parts.join(", ")}`);
2377
+ return lines.join("\n");
2378
+ }
2379
+ function formatCheckJsonOutput(result, options) {
2380
+ if (!options?.full || !options.items) {
2381
+ return result;
2382
+ }
2383
+ const results = result.results.map((r) => {
2384
+ const item = options.items?.get(r.id);
2385
+ return item ? { ...r, item } : r;
2386
+ });
2387
+ return { ...result, results };
2388
+ }
2389
+ async function handleCheckAction(identifiers, options, globalOpts) {
2390
+ const outputFormat = options.output ?? "text";
2391
+ if (options.fix && !isTTY()) {
2392
+ outputCheckError(new Error("--fix requires an interactive terminal (TTY)"), outputFormat);
2393
+ setExitCode(ExitCode.ERROR);
2394
+ return;
2395
+ }
2396
+ try {
2397
+ const config2 = await loadConfigWithOverrides({ ...globalOpts, ...options });
2398
+ const context = await createExecutionContext(config2, Library.load);
2399
+ const ids = await resolveIdentifiers$1(identifiers, options, context, config2);
2400
+ if (ids === null) return;
2401
+ const result = await executeCheck({ ...options, identifiers: ids }, context, config2);
2402
+ const needAllRefs = options.full && outputFormat === "json" || options.fix;
2403
+ const allRefs = needAllRefs ? await context.library.getAll() : void 0;
2404
+ const jsonOptions = buildJsonOptionsFromRefs(options, outputFormat, result, allRefs);
2405
+ outputCheckResult(result, outputFormat, jsonOptions);
2406
+ if (options.fix && result.summary.warnings > 0 && allRefs) {
2407
+ const { runFixInteraction } = await import("./fix-interaction-BpfMLRNY.js");
2408
+ const findItem = (id2) => allRefs.find((item) => item.id === id2);
2409
+ const fixResult = await runFixInteraction(result.results, context.library, findItem);
2410
+ const removedSuffix = fixResult.removed.length > 0 ? `, ${fixResult.removed.length} removed` : "";
2411
+ process.stderr.write(
2412
+ `
2413
+ Fix summary: ${fixResult.applied} applied, ${fixResult.skipped} skipped${removedSuffix}
2414
+ `
2415
+ );
2416
+ }
2417
+ setExitCode(ExitCode.SUCCESS);
2418
+ } catch (error) {
2419
+ outputCheckError(error, outputFormat);
2420
+ setExitCode(ExitCode.ERROR);
2421
+ }
2422
+ }
2423
+ function buildJsonOptionsFromRefs(options, outputFormat, result, allRefs) {
2424
+ if (!options.full || outputFormat !== "json" || !allRefs) return void 0;
2425
+ const items2 = /* @__PURE__ */ new Map();
2426
+ for (const r of result.results) {
2427
+ const item = allRefs.find((ref2) => ref2.id === r.id);
2428
+ if (item) items2.set(r.id, item);
2429
+ }
2430
+ return { full: true, items: items2 };
2431
+ }
2432
+ async function resolveIdentifiers$1(identifiers, options, context, config2) {
2433
+ if (identifiers.length > 0 || options.all || options.search) {
2434
+ return identifiers;
2435
+ }
2436
+ if (isTTY()) {
2437
+ const ids = await selectReferencesInteractively(context, config2);
2438
+ if (ids.length === 0) {
2439
+ setExitCode(ExitCode.SUCCESS);
2440
+ return null;
2441
+ }
2442
+ return ids;
2443
+ }
2444
+ const stdinIds = await readIdentifiersFromStdin();
2445
+ if (stdinIds.length === 0) {
2446
+ process.stderr.write(
2447
+ "Error: No identifiers provided. Provide IDs, use --all, --search, or run interactively.\n"
2448
+ );
2449
+ setExitCode(ExitCode.ERROR);
2450
+ return null;
2451
+ }
2452
+ return stdinIds;
2453
+ }
2454
+ function outputCheckResult(result, format2, jsonOptions) {
2455
+ if (format2 === "json") {
2456
+ process.stdout.write(`${JSON.stringify(formatCheckJsonOutput(result, jsonOptions))}
2457
+ `);
2458
+ } else {
2459
+ process.stderr.write(`${formatCheckTextOutput(result)}
2460
+ `);
2461
+ }
2462
+ }
2463
+ function outputCheckError(error, format2) {
2464
+ const message = error instanceof Error ? error.message : String(error);
2465
+ if (format2 === "json") {
2466
+ process.stdout.write(`${JSON.stringify({ error: message })}
2467
+ `);
2468
+ } else {
2469
+ process.stderr.write(`Error: ${message}
2470
+ `);
2471
+ }
2472
+ }
2473
+ async function selectReferencesInteractively(context, config2) {
2474
+ const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
2475
+ const { selectReferenceItemsOrExit } = await import("./reference-select-Qpgt9cbN.js");
2476
+ const allReferences = await context.library.getAll();
2477
+ if (allReferences.length === 0) {
2478
+ process.stderr.write("No references in library.\n");
2479
+ return [];
2480
+ }
2481
+ const selectedItems = await withAlternateScreen2(
2482
+ () => selectReferenceItemsOrExit(allReferences, { multiSelect: true }, config2.cli.tui)
2483
+ );
2484
+ return selectedItems.map((item) => item.id);
2485
+ }
2284
2486
  async function validateOptions$2(options) {
2285
2487
  if (options.output && !["text", "html", "rtf"].includes(options.output)) {
2286
2488
  throw new Error(`Invalid output format '${options.output}'. Must be one of: text, html, rtf`);
@@ -2338,8 +2540,8 @@ function getCiteExitCode(result) {
2338
2540
  }
2339
2541
  async function executeInteractiveCite(options, context, config2) {
2340
2542
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
2341
- const { runCiteFlow } = await import("./index-C36Us_zC.js");
2342
- const { buildStyleChoices, listCustomStyles } = await import("./style-select-BeAktUts.js");
2543
+ const { runCiteFlow } = await import("./index-CYEise6v.js");
2544
+ const { buildStyleChoices, listCustomStyles } = await import("./style-select-mEMoWbM2.js");
2343
2545
  const { search } = await import("./file-watcher-Dlx0PolG.js").then((n) => n.B);
2344
2546
  const { tokenize } = await import("./file-watcher-Dlx0PolG.js").then((n) => n.A);
2345
2547
  const { checkTTY } = await import("./tty-BMyaEOhX.js");
@@ -2419,6 +2621,7 @@ async function handleCiteAction(identifiers, options, globalOpts) {
2419
2621
  }
2420
2622
  const ENV_OVERRIDE_MAP = {
2421
2623
  REFERENCE_MANAGER_LIBRARY: "library",
2624
+ EMAIL: "email",
2422
2625
  REFERENCE_MANAGER_ATTACHMENTS_DIR: "attachments.directory",
2423
2626
  REFERENCE_MANAGER_CLI_DEFAULT_LIMIT: "cli.default_limit",
2424
2627
  REFERENCE_MANAGER_MCP_DEFAULT_LIMIT: "mcp.default_limit",
@@ -2454,6 +2657,7 @@ const CONFIG_KEY_REGISTRY = [
2454
2657
  description: "Log level",
2455
2658
  enumValues: ["silent", "info", "debug"]
2456
2659
  },
2660
+ { key: "email", type: "string", description: "Fallback email for API services", optional: true },
2457
2661
  // backup section
2458
2662
  { key: "backup.max_generations", type: "integer", description: "Maximum backup generations" },
2459
2663
  { key: "backup.max_age_days", type: "integer", description: "Maximum backup age in days" },
@@ -6938,7 +7142,7 @@ function formatEditOutput(result) {
6938
7142
  }
6939
7143
  async function executeInteractiveEdit(options, context, config2) {
6940
7144
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
6941
- const { selectReferencesOrExit } = await import("./reference-select-Bbl-roAS.js");
7145
+ const { selectReferencesOrExit } = await import("./reference-select-Qpgt9cbN.js");
6942
7146
  const allReferences = await context.library.getAll();
6943
7147
  const identifiers = await withAlternateScreen2(
6944
7148
  () => selectReferencesOrExit(allReferences, { multiSelect: true }, config2.cli.tui)
@@ -10479,7 +10683,7 @@ function getFulltextExitCode(result) {
10479
10683
  }
10480
10684
  async function executeInteractiveSelect$1(context, config2) {
10481
10685
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
10482
- const { selectReferencesOrExit } = await import("./reference-select-Bbl-roAS.js");
10686
+ const { selectReferencesOrExit } = await import("./reference-select-Qpgt9cbN.js");
10483
10687
  const allReferences = await context.library.getAll();
10484
10688
  const identifiers = await withAlternateScreen2(
10485
10689
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -31328,6 +31532,53 @@ function registerAddTool(server, getLibraryOperations) {
31328
31532
  }
31329
31533
  );
31330
31534
  }
31535
+ function formatCheckResult(result) {
31536
+ const lines = [];
31537
+ for (const r of result.results) {
31538
+ if (r.status === "ok") {
31539
+ lines.push(`[OK] ${r.id}`);
31540
+ } else if (r.status === "skipped") {
31541
+ lines.push(`[SKIPPED] ${r.id}`);
31542
+ } else {
31543
+ for (const f of r.findings) {
31544
+ lines.push(`[${f.type.toUpperCase()}] ${r.id}: ${f.message}`);
31545
+ }
31546
+ }
31547
+ }
31548
+ const { summary } = result;
31549
+ lines.push(
31550
+ `
31551
+ Summary: ${summary.total} checked, ${summary.ok} ok, ${summary.warnings} warnings, ${summary.skipped} skipped`
31552
+ );
31553
+ return lines.join("\n");
31554
+ }
31555
+ function registerCheckTool(server, getLibraryOperations) {
31556
+ server.registerTool(
31557
+ "check",
31558
+ {
31559
+ description: "Check references for retractions, expressions of concern, and version changes by querying Crossref and PubMed APIs.",
31560
+ inputSchema: {
31561
+ ids: z.array(z.string()).optional().describe("Array of reference IDs to check. Omit if using 'all'."),
31562
+ all: z.boolean().optional().describe("Check all references in library"),
31563
+ skipDays: z.number().optional().describe("Skip references checked within n days (default: 7)"),
31564
+ save: z.boolean().optional().describe("Whether to save results to library (default: true)")
31565
+ }
31566
+ },
31567
+ async (args) => {
31568
+ const libraryOps = getLibraryOperations();
31569
+ const options = {};
31570
+ if (args.ids?.length) options.identifiers = args.ids;
31571
+ if (args.all) options.all = true;
31572
+ if (args.skipDays !== void 0) options.skipDays = args.skipDays;
31573
+ if (args.save !== void 0) options.save = args.save;
31574
+ const result = await libraryOps.check(options);
31575
+ const text = formatCheckResult(result);
31576
+ return {
31577
+ content: [{ type: "text", text }]
31578
+ };
31579
+ }
31580
+ );
31581
+ }
31331
31582
  function registerCiteTool(server, getLibraryOperations) {
31332
31583
  server.registerTool(
31333
31584
  "cite",
@@ -31718,6 +31969,7 @@ function registerAllTools(server, getLibraryOperations, getConfig) {
31718
31969
  registerSearchTool(server, getLibraryOperations, getConfig);
31719
31970
  registerListTool(server, getLibraryOperations, getConfig);
31720
31971
  registerCiteTool(server, getLibraryOperations);
31972
+ registerCheckTool(server, getLibraryOperations);
31721
31973
  registerAddTool(server, getLibraryOperations);
31722
31974
  registerRemoveTool(server, getLibraryOperations);
31723
31975
  registerFulltextAttachTool(server, getLibraryOperations, getConfig);
@@ -31779,7 +32031,7 @@ async function mcpStart(options) {
31779
32031
  async function executeRemove(options, context) {
31780
32032
  const { identifier, idType = "id", fulltextDirectory, deleteFulltext = false } = options;
31781
32033
  if (context.mode === "local" && deleteFulltext && fulltextDirectory) {
31782
- const { removeReference } = await import("./index-DWAtvFtp.js").then((n) => n.w);
32034
+ const { removeReference } = await import("./index-D2HsxXnK.js").then((n) => n.x);
31783
32035
  return removeReference(context.library, {
31784
32036
  identifier,
31785
32037
  idType,
@@ -31834,7 +32086,7 @@ Continue?`;
31834
32086
  }
31835
32087
  async function executeInteractiveRemove(context, config2) {
31836
32088
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
31837
- const { selectReferenceItemsOrExit } = await import("./reference-select-Bbl-roAS.js");
32089
+ const { selectReferenceItemsOrExit } = await import("./reference-select-Qpgt9cbN.js");
31838
32090
  const allReferences = await context.library.getAll();
31839
32091
  const selectedItems = await withAlternateScreen2(
31840
32092
  () => selectReferenceItemsOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -32059,7 +32311,7 @@ async function executeInteractiveSearch(options, context, config2) {
32059
32311
  validateInteractiveOptions(options);
32060
32312
  const { checkTTY } = await import("./tty-BMyaEOhX.js");
32061
32313
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
32062
- const { runSearchFlow } = await import("./index-C36Us_zC.js");
32314
+ const { runSearchFlow } = await import("./index-CYEise6v.js");
32063
32315
  const { search } = await import("./file-watcher-Dlx0PolG.js").then((n) => n.B);
32064
32316
  const { tokenize } = await import("./file-watcher-Dlx0PolG.js").then((n) => n.A);
32065
32317
  checkTTY();
@@ -32078,7 +32330,7 @@ async function executeInteractiveSearch(options, context, config2) {
32078
32330
  })
32079
32331
  );
32080
32332
  if (result.selectedItems && !result.cancelled) {
32081
- const { isSideEffectAction } = await import("./action-menu-BCgv1m3v.js");
32333
+ const { isSideEffectAction } = await import("./action-menu-DD0RtNVD.js");
32082
32334
  if (isSideEffectAction(result.action)) {
32083
32335
  await executeSideEffectAction(result.action, result.selectedItems, context, config2);
32084
32336
  return { output: "", cancelled: false, action: result.action };
@@ -32094,7 +32346,7 @@ async function executeSideEffectAction(action, items2, context, config2) {
32094
32346
  switch (action) {
32095
32347
  case "open-url": {
32096
32348
  const { resolveDefaultUrl: resolveDefaultUrl2 } = await Promise.resolve().then(() => url);
32097
- const { openWithSystemApp: openWithSystemApp2 } = await import("./loader-CV71qNY2.js").then((n) => n.j);
32349
+ const { openWithSystemApp: openWithSystemApp2 } = await import("./loader-B-fte1uv.js").then((n) => n.j);
32098
32350
  const item = items2[0];
32099
32351
  if (!item) return;
32100
32352
  const url$1 = resolveDefaultUrl2(item);
@@ -32481,7 +32733,7 @@ function formatUpdateOutput(result, identifier) {
32481
32733
  }
32482
32734
  async function executeInteractiveUpdate(context, config2) {
32483
32735
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
32484
- const { selectReferencesOrExit } = await import("./reference-select-Bbl-roAS.js");
32736
+ const { selectReferencesOrExit } = await import("./reference-select-Qpgt9cbN.js");
32485
32737
  const allReferences = await context.library.getAll();
32486
32738
  const identifiers = await withAlternateScreen2(
32487
32739
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -32776,7 +33028,7 @@ function getUrlExitCode(result) {
32776
33028
  }
32777
33029
  async function executeInteractiveSelect(context, config2) {
32778
33030
  const { withAlternateScreen: withAlternateScreen2 } = await Promise.resolve().then(() => alternateScreen);
32779
- const { selectReferencesOrExit } = await import("./reference-select-Bbl-roAS.js");
33031
+ const { selectReferencesOrExit } = await import("./reference-select-Qpgt9cbN.js");
32780
33032
  const allReferences = await context.library.getAll();
32781
33033
  const identifiers = await withAlternateScreen2(
32782
33034
  () => selectReferencesOrExit(allReferences, { multiSelect: false }, config2.cli.tui)
@@ -33147,6 +33399,7 @@ function createProgram() {
33147
33399
  registerRemoveCommand(program);
33148
33400
  registerUpdateCommand(program);
33149
33401
  registerEditCommand(program);
33402
+ registerCheckCommand(program);
33150
33403
  registerCiteCommand(program);
33151
33404
  registerServerCommand(program);
33152
33405
  registerFulltextCommand(program);
@@ -33308,7 +33561,7 @@ function shouldAutoFetch(cliFlag, configEnabled) {
33308
33561
  return configEnabled;
33309
33562
  }
33310
33563
  async function performAutoFetch(addedItems, context, config2) {
33311
- const { fulltextFetch: fulltextFetch2 } = await import("./index-DWAtvFtp.js").then((n) => n.v);
33564
+ const { fulltextFetch: fulltextFetch2 } = await import("./index-D2HsxXnK.js").then((n) => n.w);
33312
33565
  const fetchResults = await autoFetchFulltext(addedItems, context, {
33313
33566
  fulltextConfig: config2.fulltext,
33314
33567
  fulltextDirectory: config2.attachments.directory,
@@ -33388,6 +33641,11 @@ function registerEditCommand(program) {
33388
33641
  await handleEditAction(identifiers, options, program.opts());
33389
33642
  });
33390
33643
  }
33644
+ function registerCheckCommand(program) {
33645
+ program.command("check").description("Check references for retractions, expressions of concern, and version changes").argument("[ids...]", "Citation keys or UUIDs to check (interactive selection if omitted)").option("--all", "Check all references in library").option("--search <query>", "Check references matching search query").option("--uuid", "Interpret identifiers as UUIDs").option("-o, --output <format>", "Output format: text|json", "text").option("--full", "Include full details in JSON output").option("--no-save", "Report only, do not save results to library").option("--days <n>", "Skip references checked within n days (default: 7)", Number.parseInt).option("--fix", "Interactive repair for findings (TTY only)").action(async (ids, options) => {
33646
+ await handleCheckAction(ids, options, program.opts());
33647
+ });
33648
+ }
33391
33649
  function registerCiteCommand(program) {
33392
33650
  program.command("cite").description("Generate formatted citations for references").argument(
33393
33651
  "[id-or-uuid...]",
@@ -33587,4 +33845,4 @@ export {
33587
33845
  restoreStdinAfterInk as r,
33588
33846
  syncAttachments as s
33589
33847
  };
33590
- //# sourceMappingURL=index-JA964gjc.js.map
33848
+ //# sourceMappingURL=index-QTYx5RaF.js.map