dsh-zotero 0.5.2 → 0.6.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 (58) hide show
  1. package/lib/ask.d.ts +2 -1
  2. package/lib/ask.d.ts.map +1 -1
  3. package/lib/attachments.d.ts +5 -15
  4. package/lib/attachments.d.ts.map +1 -1
  5. package/lib/attachments.js +7 -18
  6. package/lib/attachments.js.map +1 -1
  7. package/lib/client.js +81 -45
  8. package/lib/client.js.map +4 -4
  9. package/lib/export-items.d.ts +7 -0
  10. package/lib/export-items.d.ts.map +1 -1
  11. package/lib/export-items.js +8 -1
  12. package/lib/export-items.js.map +1 -1
  13. package/lib/json.d.ts.map +1 -1
  14. package/lib/json.js +2 -1
  15. package/lib/json.js.map +1 -1
  16. package/lib/normalize.d.ts +1 -1
  17. package/lib/normalize.d.ts.map +1 -1
  18. package/lib/presentation-meta.d.ts +1 -1
  19. package/lib/presentation-meta.d.ts.map +1 -1
  20. package/lib/prompt.d.ts +12 -7
  21. package/lib/prompt.d.ts.map +1 -1
  22. package/lib/prompt.js +13 -9
  23. package/lib/prompt.js.map +1 -1
  24. package/lib/ref-grammar.d.ts +34 -0
  25. package/lib/ref-grammar.d.ts.map +1 -0
  26. package/lib/ref-grammar.js +37 -0
  27. package/lib/ref-grammar.js.map +1 -0
  28. package/lib/refs.d.ts.map +1 -1
  29. package/lib/refs.js +6 -6
  30. package/lib/refs.js.map +1 -1
  31. package/lib/service.d.ts.map +1 -1
  32. package/lib/service.js +21 -28
  33. package/lib/service.js.map +1 -1
  34. package/lib/tools/browse.d.ts.map +1 -1
  35. package/lib/tools/browse.js +14 -15
  36. package/lib/tools/browse.js.map +1 -1
  37. package/lib/tools/export.d.ts.map +1 -1
  38. package/lib/tools/export.js +5 -4
  39. package/lib/tools/export.js.map +1 -1
  40. package/lib/tools/get.d.ts.map +1 -1
  41. package/lib/tools/get.js +2 -2
  42. package/lib/tools/get.js.map +1 -1
  43. package/lib/tools/retrieve.d.ts.map +1 -1
  44. package/lib/tools/retrieve.js +2 -2
  45. package/lib/tools/retrieve.js.map +1 -1
  46. package/lib/tools/search.d.ts.map +1 -1
  47. package/lib/tools/search.js.map +1 -1
  48. package/lib/tools/validate.d.ts +2 -0
  49. package/lib/tools/validate.d.ts.map +1 -1
  50. package/lib/tools/validate.js +6 -4
  51. package/lib/tools/validate.js.map +1 -1
  52. package/lib/typert.d.ts +8 -7
  53. package/lib/typert.d.ts.map +1 -1
  54. package/lib/typert.js +8 -7
  55. package/lib/typert.js.map +1 -1
  56. package/lib/types.d.ts +7 -5
  57. package/lib/types.d.ts.map +1 -1
  58. package/package.json +113 -110
package/lib/ask.d.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  import type { Context } from '@deepseek-ai/cordis';
17
17
  import { type ToolRunContext } from '@deepseek-ai/dsh-tools';
18
18
  /** The parts of a tool execution `withConnectivityAsk` needs. */
19
- export type ConnectivityAskExec = Pick<ToolRunContext, 'signal' | 'agent'>;
19
+ type ConnectivityAskExec = Pick<ToolRunContext, 'signal' | 'agent'>;
20
20
  /**
21
21
  * Run one Zotero request; on a connectivity failure, ask the user how to
22
22
  * proceed and retry at most once when they choose the recommended action.
@@ -31,4 +31,5 @@ export type ConnectivityAskExec = Pick<ToolRunContext, 'signal' | 'agent'>;
31
31
  * fails again.
32
32
  */
33
33
  export declare function withConnectivityAsk<T>(ctx: Context, exec: ConnectivityAskExec, run: () => Promise<T>): Promise<T>;
34
+ export {};
34
35
  //# sourceMappingURL=ask.d.ts.map
package/lib/ask.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../src/ask.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAyB1E,iEAAiE;AACjE,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAA;AA2E1E;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,CAAC,CA4BZ"}
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../src/ask.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAyB1E,iEAAiE;AACjE,KAAK,mBAAmB,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAA;AA2EnE;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,CAAC,CA4BZ"}
@@ -2,10 +2,11 @@
2
2
  * Attachment records and deterministic attachment selection.
3
3
  *
4
4
  * Zotero's own best-attachment choice (`links.attachment` on item
5
- * responses) is preferred wherever it exists; `selectAttachment` is the
5
+ * responses) is preferred wherever it exists; `selectAttachments` is the
6
6
  * documented fallback that ranks child rows the same way Zotero's
7
7
  * `getBestAttachment` does — PDF over other kinds, imported files first,
8
- * then earliest addition date, then key order.
8
+ * then earliest addition date, then key order. Single selection is the
9
+ * ranking's first entry.
9
10
  * @module dsh-zotero/attachments
10
11
  */
11
12
  /**
@@ -36,21 +37,10 @@ export declare function bestAttachmentFromLinks(json: unknown): {
36
37
  * @throws {ZoteroError} `ZOTERO_UNEXPECTED` when the object has no valid Zotero key.
37
38
  */
38
39
  export declare function normalizeAttachmentRecord(json: unknown): ZoteroAttachmentCandidate;
39
- /**
40
- * Select one attachment of the requested kind from raw child rows, ranked
41
- * deterministically: imported files first, then earliest `dateAdded`, then
42
- * key order. Rows without an attachment content type are skipped; a
43
- * malformed attachment row fails loud like every other broken invariant.
44
- * @param rows - raw child item JSON objects (notes and annotations are skipped).
45
- * @param kind - `pdf` selects `application/pdf`; anything else is matched as a literal content type.
46
- * @returns the winning record, or undefined when no row matches the kind.
47
- * @throws {ZoteroError} `ZOTERO_UNEXPECTED` on an attachment row without a valid key.
48
- */
49
- export declare function selectAttachment(rows: readonly unknown[], kind: string): ZoteroAttachmentCandidate | undefined;
50
40
  /**
51
41
  * Select every attachment of the requested kind from raw child rows, ordered
52
- * by the same deterministic ranking {@link selectAttachment} uses — so the
53
- * first entry always equals the single-selection answer, and a work with
42
+ * by the same deterministic ranking Zotero's `getBestAttachment` uses — so
43
+ * the first entry always equals the single-selection answer, and a work with
54
44
  * several PDFs (publisher copy, manuscript, supplement) can enter evidence
55
45
  * ranking as several first-class sources.
56
46
  */
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,GACZ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAKlD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,yBAAyB,CAmBlF;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,yBAAyB,GAAG,SAAS,CAEvC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,SAAS,yBAAyB,EAAE,CAoBtC"}
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,GACZ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAKlD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,yBAAyB,CAmBlF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,SAAS,yBAAyB,EAAE,CAoBtC"}
@@ -2,19 +2,21 @@
2
2
  * Attachment records and deterministic attachment selection.
3
3
  *
4
4
  * Zotero's own best-attachment choice (`links.attachment` on item
5
- * responses) is preferred wherever it exists; `selectAttachment` is the
5
+ * responses) is preferred wherever it exists; `selectAttachments` is the
6
6
  * documented fallback that ranks child rows the same way Zotero's
7
7
  * `getBestAttachment` does — PDF over other kinds, imported files first,
8
- * then earliest addition date, then key order.
8
+ * then earliest addition date, then key order. Single selection is the
9
+ * ranking's first entry.
9
10
  * @module dsh-zotero/attachments
10
11
  */
11
12
  import { ZOTERO_UNEXPECTED, ZoteroError } from './errors.js';
12
13
  import { asRecord, asString, isObjectKey } from './json.js';
14
+ import { ATTACHMENT_HREF_PATTERN } from './ref-grammar.js';
13
15
  /** Extract a Zotero object key from an API `links.attachment.href`. */
14
16
  export function extractAttachmentKey(href) {
15
17
  if (href === undefined)
16
18
  return undefined;
17
- return /\/items\/([A-Z0-9]{8})(?:[/?#]|$)/.exec(href)?.[1];
19
+ return ATTACHMENT_HREF_PATTERN.exec(href)?.[1];
18
20
  }
19
21
  /**
20
22
  * Read Zotero's own best-attachment link from an item response.
@@ -49,23 +51,10 @@ export function normalizeAttachmentRecord(json) {
49
51
  ...(url !== undefined ? { url } : {}),
50
52
  };
51
53
  }
52
- /**
53
- * Select one attachment of the requested kind from raw child rows, ranked
54
- * deterministically: imported files first, then earliest `dateAdded`, then
55
- * key order. Rows without an attachment content type are skipped; a
56
- * malformed attachment row fails loud like every other broken invariant.
57
- * @param rows - raw child item JSON objects (notes and annotations are skipped).
58
- * @param kind - `pdf` selects `application/pdf`; anything else is matched as a literal content type.
59
- * @returns the winning record, or undefined when no row matches the kind.
60
- * @throws {ZoteroError} `ZOTERO_UNEXPECTED` on an attachment row without a valid key.
61
- */
62
- export function selectAttachment(rows, kind) {
63
- return selectAttachments(rows, kind)[0];
64
- }
65
54
  /**
66
55
  * Select every attachment of the requested kind from raw child rows, ordered
67
- * by the same deterministic ranking {@link selectAttachment} uses — so the
68
- * first entry always equals the single-selection answer, and a work with
56
+ * by the same deterministic ranking Zotero's `getBestAttachment` uses — so
57
+ * the first entry always equals the single-selection answer, and a work with
69
58
  * several PDFs (publisher copy, manuscript, supplement) can enter evidence
70
59
  * ranking as several first-class sources.
71
60
  */
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"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"}
package/lib/client.js CHANGED
@@ -1012,7 +1012,7 @@ function devFreeze(value) {
1012
1012
  }
1013
1013
 
1014
1014
  // src/client/card-form.ts
1015
- function numberField(field2) {
1015
+ function numberFieldSpec(field2) {
1016
1016
  return {
1017
1017
  field: field2,
1018
1018
  // A section that carries no number for this field renders empty rather
@@ -1026,7 +1026,7 @@ function numberField(field2) {
1026
1026
  }
1027
1027
  };
1028
1028
  }
1029
- function booleanField(field2) {
1029
+ function booleanFieldSpec(field2) {
1030
1030
  return {
1031
1031
  field: field2,
1032
1032
  format: (value) => typeof value === "boolean" ? String(value) : "",
@@ -1039,7 +1039,7 @@ function booleanField(field2) {
1039
1039
  }
1040
1040
  };
1041
1041
  }
1042
- function textField(field2) {
1042
+ function textFieldSpec(field2) {
1043
1043
  return {
1044
1044
  field: field2,
1045
1045
  format: (value) => typeof value === "string" ? value : "",
@@ -1246,9 +1246,9 @@ var FIELD_SPECS = [
1246
1246
  { key: "defaultLocale", kind: "text", group: "groupDefaults" }
1247
1247
  ];
1248
1248
  var FIELDS = FIELD_SPECS.map((spec) => {
1249
- if (spec.kind === "number") return numberField(spec.key);
1250
- if (spec.kind === "boolean") return booleanField(spec.key);
1251
- return textField(spec.key);
1249
+ if (spec.kind === "number") return numberFieldSpec(spec.key);
1250
+ if (spec.kind === "boolean") return booleanFieldSpec(spec.key);
1251
+ return textFieldSpec(spec.key);
1252
1252
  });
1253
1253
  var FIELD_GROUPS = groupFields(FIELD_SPECS);
1254
1254
  var NUMERIC_FIELD_KEYS = new Set(
@@ -1510,9 +1510,37 @@ function ZoteroPluginCard(props) {
1510
1510
  // src/client/components/SourcesTab.tsx
1511
1511
  var import_react11 = require("react");
1512
1512
 
1513
+ // src/ref-grammar.ts
1514
+ var REF_KEY_SOURCE = "[A-Z0-9]{8}";
1515
+ var ATTACHMENT_HREF_PATTERN = new RegExp(`/items/(${REF_KEY_SOURCE})(?:[/?#]|$)`);
1516
+ var ZOTERO_USER_ITEM_PATH_PATTERN = new RegExp(
1517
+ `^/users/(\\d+)/items/(${REF_KEY_SOURCE})(?:[/?#].*)?$`
1518
+ );
1519
+ var ZOTERO_GROUP_ITEM_PATH_PATTERN = new RegExp(
1520
+ `^/groups/(\\d+)/items/(${REF_KEY_SOURCE})(?:[/?#].*)?$`
1521
+ );
1522
+ var LIBRARY = "(?<libraryType>user|group)/(?<libraryId>\\d+)";
1523
+ var KINDS = "(?<kind>item|attachment|annotation|collection|search)";
1524
+ var SERVER_QUALIFIER = "\\?server=(?<serverId>[A-Za-z0-9_-]{1,64})";
1525
+ var REF_PATTERN = new RegExp(
1526
+ `^zotero://${LIBRARY}/${KINDS}/(?<key>${REF_KEY_SOURCE})(?:${SERVER_QUALIFIER})?$`
1527
+ );
1528
+ var REF_IN_TEXT_PATTERN = new RegExp(
1529
+ `zotero://${LIBRARY}/${KINDS}/(?<key>${REF_KEY_SOURCE})`
1530
+ );
1531
+
1532
+ // src/json.ts
1533
+ var OBJECT_KEY_PATTERN = new RegExp(`^${REF_KEY_SOURCE}$`);
1534
+ function asRecord(value) {
1535
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
1536
+ }
1537
+ function asString(value) {
1538
+ return typeof value === "string" ? value : void 0;
1539
+ }
1540
+
1513
1541
  // src/client/presenters.ts
1514
1542
  function isRecord(value) {
1515
- return typeof value === "object" && value !== null && !Array.isArray(value);
1543
+ return asRecord(value) !== void 0;
1516
1544
  }
1517
1545
  function callNameOf(block) {
1518
1546
  return "kind" in block ? block.call?.name ?? null : block.name;
@@ -1521,10 +1549,9 @@ function orderKeyOf(block) {
1521
1549
  return "kind" in block ? block.seq : 1e9 + block.time;
1522
1550
  }
1523
1551
  function stringField(record2, key) {
1524
- const value = record2[key];
1525
- return typeof value === "string" ? value : void 0;
1552
+ return asString(record2[key]);
1526
1553
  }
1527
- function numberField2(record2, key) {
1554
+ function numberField(record2, key) {
1528
1555
  const value = record2[key];
1529
1556
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1530
1557
  }
@@ -1565,10 +1592,7 @@ function argsOf(block) {
1565
1592
  }
1566
1593
  }
1567
1594
  function shortKeyOf(value) {
1568
- const match = /zotero:\/\/user\/0\/(?:item|attachment|annotation|collection|search)\/([A-Z0-9]{8})/.exec(
1569
- value
1570
- );
1571
- return match?.[1] ?? null;
1595
+ return REF_IN_TEXT_PATTERN.exec(value)?.groups?.key ?? null;
1572
1596
  }
1573
1597
  function evidenceItemsOf(meta3) {
1574
1598
  const items = meta3["items"];
@@ -1618,9 +1642,9 @@ function exportItemsOf(value) {
1618
1642
  if (ref === void 0) continue;
1619
1643
  const key = stringField(entry, "key");
1620
1644
  const title = stringField(entry, "title");
1621
- const entryIndex = numberField2(entry, "entryIndex");
1622
- const start = numberField2(entry, "start");
1623
- const end = numberField2(entry, "end");
1645
+ const entryIndex = numberField(entry, "entryIndex");
1646
+ const start = numberField(entry, "start");
1647
+ const end = numberField(entry, "end");
1624
1648
  items.push({
1625
1649
  ref,
1626
1650
  ...key === void 0 ? {} : { key },
@@ -1641,7 +1665,7 @@ function decodeSearchRows(value) {
1641
1665
  const title = stringField(item, "title");
1642
1666
  const creatorSummary = stringField(item, "creatorSummary");
1643
1667
  if (ref === void 0 || title === void 0 || creatorSummary === void 0) return null;
1644
- const year = numberField2(item, "year");
1668
+ const year = numberField(item, "year");
1645
1669
  const bestAttachmentRef = stringField(item, "bestAttachmentRef");
1646
1670
  const bestAttachmentType = stringField(item, "bestAttachmentType");
1647
1671
  rows.push({
@@ -1658,7 +1682,7 @@ function decodeSearchRows(value) {
1658
1682
  function decodeSupportedLibrary(value) {
1659
1683
  if (!isRecord(value)) return null;
1660
1684
  const type = stringField(value, "type");
1661
- const id = numberField2(value, "id");
1685
+ const id = numberField(value, "id");
1662
1686
  if (type !== "user" && type !== "group" || id === void 0 || !Number.isInteger(id))
1663
1687
  return null;
1664
1688
  if (type === "user" && id !== 0) return null;
@@ -1687,7 +1711,7 @@ function decodeResolvedScope(value) {
1687
1711
  function searchMetaOf(meta3) {
1688
1712
  return {
1689
1713
  rows: decodeSearchRows(meta3["items"]),
1690
- omitted: numberField2(meta3, "omitted") ?? null,
1714
+ omitted: numberField(meta3, "omitted") ?? null,
1691
1715
  scope: decodeResolvedScope(meta3["scope"]),
1692
1716
  library: decodeSupportedLibrary(meta3["library"])
1693
1717
  };
@@ -1705,7 +1729,7 @@ function getMetaOf(meta3) {
1705
1729
  return {
1706
1730
  title: stringField(meta3, "title") ?? null,
1707
1731
  creators: stringField(meta3, "creators") ?? null,
1708
- year: numberField2(meta3, "year") ?? null,
1732
+ year: numberField(meta3, "year") ?? null,
1709
1733
  venue: stringField(meta3, "venue") ?? null,
1710
1734
  bestAttachment
1711
1735
  };
@@ -1717,7 +1741,7 @@ function decodeSourceAvailability(value) {
1717
1741
  if (!isRecord(entry)) continue;
1718
1742
  const requested = boolField(entry, "requested");
1719
1743
  const unavailable = boolField(entry, "unavailable");
1720
- const returnedPassages = numberField2(entry, "returnedPassages");
1744
+ const returnedPassages = numberField(entry, "returnedPassages");
1721
1745
  if (requested === void 0 || unavailable === void 0 || returnedPassages === void 0)
1722
1746
  continue;
1723
1747
  result[source] = { requested, returnedPassages, unavailable };
@@ -1728,10 +1752,10 @@ function decodeCoverage(value) {
1728
1752
  if (!isRecord(value)) return null;
1729
1753
  const complete = boolField(value, "complete");
1730
1754
  if (complete === void 0) return null;
1731
- const indexedPages = numberField2(value, "indexedPages");
1732
- const totalPages = numberField2(value, "totalPages");
1733
- const indexedChars = numberField2(value, "indexedChars");
1734
- const totalChars = numberField2(value, "totalChars");
1755
+ const indexedPages = numberField(value, "indexedPages");
1756
+ const totalPages = numberField(value, "totalPages");
1757
+ const indexedChars = numberField(value, "indexedChars");
1758
+ const totalChars = numberField(value, "totalChars");
1735
1759
  return {
1736
1760
  complete,
1737
1761
  ...indexedPages === void 0 ? {} : { indexedPages },
@@ -1744,7 +1768,7 @@ function retrieveMetaOf(meta3) {
1744
1768
  const truncated = boolField(meta3, "truncated");
1745
1769
  return {
1746
1770
  items: evidenceItemsOf(meta3),
1747
- count: numberField2(meta3, "count") ?? null,
1771
+ count: numberField(meta3, "count") ?? null,
1748
1772
  truncated: truncated === void 0 ? null : truncated,
1749
1773
  attachmentRef: stringField(meta3, "attachmentRef") ?? null,
1750
1774
  attachmentContentType: stringField(meta3, "attachmentContentType") ?? null,
@@ -1769,7 +1793,7 @@ function exportMetaOf(meta3) {
1769
1793
  style: stringField(meta3, "style") ?? null,
1770
1794
  locale: stringField(meta3, "locale") ?? null,
1771
1795
  refs: stringArrayOf(meta3["refs"]),
1772
- refsOmitted: numberField2(meta3, "refsOmitted") ?? 0,
1796
+ refsOmitted: numberField(meta3, "refsOmitted") ?? 0,
1773
1797
  items: exportItemsOf(meta3["items"])
1774
1798
  };
1775
1799
  }
@@ -2409,10 +2433,10 @@ var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primi
2409
2433
 
2410
2434
  // src/client/build-info.ts
2411
2435
  function buildVersion() {
2412
- return true ? "0.5.2" : "unknown";
2436
+ return true ? "0.6.0" : "unknown";
2413
2437
  }
2414
2438
  function buildCommit() {
2415
- return true ? "ae33e5b" : "unknown";
2439
+ return true ? "00b1b30" : "unknown";
2416
2440
  }
2417
2441
  function buildInfoOf() {
2418
2442
  return `${buildVersion()} \xB7 ${buildCommit()}`;
@@ -2436,7 +2460,7 @@ if (typeof document !== "undefined" && !document.querySelector('style[data-plugi
2436
2460
  tag.textContent = style2;
2437
2461
  document.head.appendChild(tag);
2438
2462
  }
2439
- var workspace_default = { "view": "_o1AEW_view", "detailTabCount": "_o1AEW_detailTabCount", "action": "_o1AEW_action", "sidebar": "_o1AEW_sidebar", "filterClear": "_o1AEW_filterClear", "backAction": "_o1AEW_backAction", "listItemMeta": "_o1AEW_listItemMeta", "evidencePage": "_o1AEW_evidencePage", "listItemSelected": "_o1AEW_listItemSelected", "statusText": "_o1AEW_statusText", "emptyNote": "_o1AEW_emptyNote", "note": "_o1AEW_note", "diagnosis": "_o1AEW_diagnosis", "lensBar": "_o1AEW_lensBar", "section": "_o1AEW_section", "passages": "_o1AEW_passages", "detailToggle": "_o1AEW_detailToggle", "listItem": "_o1AEW_listItem", "summaryLine": "_o1AEW_summaryLine", "passage": "_o1AEW_passage", "sourceTag": "_o1AEW_sourceTag", "filterArrowLeft": "_o1AEW_filterArrowLeft", "sectionLabel": "_o1AEW_sectionLabel", "emptyWrap": "_o1AEW_emptyWrap", "exportStack": "_o1AEW_exportStack", "actionRow": "_o1AEW_actionRow", "panel": "_o1AEW_panel", "emptyText": "_o1AEW_emptyText", "empty": "_o1AEW_empty", "warning": "_o1AEW_warning", "inspectorTitleWrap": "_o1AEW_inspectorTitleWrap", "detailTabActive": "_o1AEW_detailTabActive", "lensTabCount": "_o1AEW_lensTabCount", "listbox": "_o1AEW_listbox", "line": "_o1AEW_line", "lensTabActive": "_o1AEW_lensTabActive", "inspectorHead": "_o1AEW_inspectorHead", "detailTab": "_o1AEW_detailTab", "inspectorBody": "_o1AEW_inspectorBody", "availability": "_o1AEW_availability", "emptyIcon": "_o1AEW_emptyIcon", "spacer": "_o1AEW_spacer", "lensTab": "_o1AEW_lensTab", "inspectorTitle": "_o1AEW_inspectorTitle", "inspectorTabs": "_o1AEW_inspectorTabs", "passageHead": "_o1AEW_passageHead", "starterRow": "_o1AEW_starterRow", "inspectorMeta": "_o1AEW_inspectorMeta", "badge": "_o1AEW_badge", "inspector": "_o1AEW_inspector", "menuButton": "_o1AEW_menuButton", "refresh": "_o1AEW_refresh", "toolbar": "_o1AEW_toolbar", "workspace": "_o1AEW_workspace", "cardStack": "_o1AEW_cardStack", "listItemTitle": "_o1AEW_listItemTitle", "badges": "_o1AEW_badges", "filterBar": "_o1AEW_filterBar", "filterArrow": "_o1AEW_filterArrow", "evidenceEntry": "_o1AEW_evidenceEntry", "exportsPage": "_o1AEW_exportsPage", "filterArrowRight": "_o1AEW_filterArrowRight" };
2463
+ var workspace_default = { "panel": "_o1AEW_panel", "inspector": "_o1AEW_inspector", "line": "_o1AEW_line", "passage": "_o1AEW_passage", "lensTabActive": "_o1AEW_lensTabActive", "inspectorMeta": "_o1AEW_inspectorMeta", "evidenceEntry": "_o1AEW_evidenceEntry", "emptyWrap": "_o1AEW_emptyWrap", "inspectorTitle": "_o1AEW_inspectorTitle", "action": "_o1AEW_action", "empty": "_o1AEW_empty", "availability": "_o1AEW_availability", "workspace": "_o1AEW_workspace", "detailTab": "_o1AEW_detailTab", "inspectorHead": "_o1AEW_inspectorHead", "cardStack": "_o1AEW_cardStack", "passages": "_o1AEW_passages", "spacer": "_o1AEW_spacer", "filterArrowLeft": "_o1AEW_filterArrowLeft", "badges": "_o1AEW_badges", "passageHead": "_o1AEW_passageHead", "emptyNote": "_o1AEW_emptyNote", "detailToggle": "_o1AEW_detailToggle", "exportStack": "_o1AEW_exportStack", "warning": "_o1AEW_warning", "detailTabCount": "_o1AEW_detailTabCount", "starterRow": "_o1AEW_starterRow", "filterArrow": "_o1AEW_filterArrow", "statusText": "_o1AEW_statusText", "sourceTag": "_o1AEW_sourceTag", "listbox": "_o1AEW_listbox", "lensTab": "_o1AEW_lensTab", "backAction": "_o1AEW_backAction", "emptyIcon": "_o1AEW_emptyIcon", "actionRow": "_o1AEW_actionRow", "evidencePage": "_o1AEW_evidencePage", "toolbar": "_o1AEW_toolbar", "diagnosis": "_o1AEW_diagnosis", "emptyText": "_o1AEW_emptyText", "listItem": "_o1AEW_listItem", "badge": "_o1AEW_badge", "inspectorTabs": "_o1AEW_inspectorTabs", "listItemMeta": "_o1AEW_listItemMeta", "note": "_o1AEW_note", "detailTabActive": "_o1AEW_detailTabActive", "summaryLine": "_o1AEW_summaryLine", "menuButton": "_o1AEW_menuButton", "sidebar": "_o1AEW_sidebar", "inspectorTitleWrap": "_o1AEW_inspectorTitleWrap", "refresh": "_o1AEW_refresh", "exportsPage": "_o1AEW_exportsPage", "listItemSelected": "_o1AEW_listItemSelected", "lensBar": "_o1AEW_lensBar", "filterBar": "_o1AEW_filterBar", "sectionLabel": "_o1AEW_sectionLabel", "lensTabCount": "_o1AEW_lensTabCount", "section": "_o1AEW_section", "filterArrowRight": "_o1AEW_filterArrowRight", "inspectorBody": "_o1AEW_inspectorBody", "filterClear": "_o1AEW_filterClear", "view": "_o1AEW_view", "listItemTitle": "_o1AEW_listItemTitle" };
2440
2464
 
2441
2465
  // src/client/components/workspace/WorkspaceToolbar.tsx
2442
2466
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -2768,7 +2792,7 @@ if (typeof document !== "undefined" && !document.querySelector('style[data-plugi
2768
2792
  tag.textContent = style3;
2769
2793
  document.head.appendChild(tag);
2770
2794
  }
2771
- var open_default = { "blocked": "_02bwZG_blocked", "srOnly": "_02bwZG_srOnly", "link": "_02bwZG_link", "note": "_02bwZG_note", "linkWrap": "_02bwZG_linkWrap", "button": "_02bwZG_button" };
2795
+ var open_default = { "blocked": "_02bwZG_blocked", "linkWrap": "_02bwZG_linkWrap", "link": "_02bwZG_link", "note": "_02bwZG_note", "button": "_02bwZG_button", "srOnly": "_02bwZG_srOnly" };
2772
2796
 
2773
2797
  // src/client/components/open/BlockedOpenAction.tsx
2774
2798
  var import_jsx_runtime7 = require("react/jsx-runtime");
@@ -2939,7 +2963,7 @@ if (typeof document !== "undefined" && !document.querySelector('style[data-plugi
2939
2963
  tag.textContent = style4;
2940
2964
  document.head.appendChild(tag);
2941
2965
  }
2942
- var cards_default = { "exportToggle": "_27yOoG_exportToggle", "sourceTag": "_27yOoG_sourceTag", "exportSection": "_27yOoG_exportSection", "line": "_27yOoG_line", "exportCodeLabel": "_27yOoG_exportCodeLabel", "exportSectionTitle": "_27yOoG_exportSectionTitle", "cardHead": "_27yOoG_cardHead", "exportCode": "_27yOoG_exportCode", "exportPre": "_27yOoG_exportPre", "exportKeys": "_27yOoG_exportKeys", "note": "_27yOoG_note", "chevron": "_27yOoG_chevron", "exportHead": "_27yOoG_exportHead", "passages": "_27yOoG_passages", "exportTitle": "_27yOoG_exportTitle", "documentTitle": "_27yOoG_documentTitle", "unresolvedItemsText": "_27yOoG_unresolvedItemsText", "exportRow": "_27yOoG_exportRow", "chevronOpen": "_27yOoG_chevronOpen", "cardTitle": "_27yOoG_cardTitle", "documentKey": "_27yOoG_documentKey", "exportCodeHead": "_27yOoG_exportCodeHead", "exportKeysText": "_27yOoG_exportKeysText", "availability": "_27yOoG_availability", "exportBody": "_27yOoG_exportBody", "lineAction": "_27yOoG_lineAction", "card": "_27yOoG_card", "lineActions": "_27yOoG_lineActions", "exportSectionHead": "_27yOoG_exportSectionHead", "unresolvedItems": "_27yOoG_unresolvedItems", "passage": "_27yOoG_passage", "exportFacts": "_27yOoG_exportFacts", "exportSectionActions": "_27yOoG_exportSectionActions", "link": "_27yOoG_link", "passageHead": "_27yOoG_passageHead", "exportSectionCount": "_27yOoG_exportSectionCount" };
2966
+ var cards_default = { "passageHead": "_27yOoG_passageHead", "exportSectionActions": "_27yOoG_exportSectionActions", "exportBody": "_27yOoG_exportBody", "passage": "_27yOoG_passage", "card": "_27yOoG_card", "cardTitle": "_27yOoG_cardTitle", "lineAction": "_27yOoG_lineAction", "sourceTag": "_27yOoG_sourceTag", "unresolvedItemsText": "_27yOoG_unresolvedItemsText", "exportSectionTitle": "_27yOoG_exportSectionTitle", "note": "_27yOoG_note", "exportPre": "_27yOoG_exportPre", "exportTitle": "_27yOoG_exportTitle", "chevronOpen": "_27yOoG_chevronOpen", "unresolvedItems": "_27yOoG_unresolvedItems", "chevron": "_27yOoG_chevron", "exportHead": "_27yOoG_exportHead", "exportToggle": "_27yOoG_exportToggle", "exportCodeLabel": "_27yOoG_exportCodeLabel", "link": "_27yOoG_link", "exportFacts": "_27yOoG_exportFacts", "documentKey": "_27yOoG_documentKey", "exportSection": "_27yOoG_exportSection", "availability": "_27yOoG_availability", "lineActions": "_27yOoG_lineActions", "exportKeysText": "_27yOoG_exportKeysText", "documentTitle": "_27yOoG_documentTitle", "cardHead": "_27yOoG_cardHead", "passages": "_27yOoG_passages", "exportCode": "_27yOoG_exportCode", "exportKeys": "_27yOoG_exportKeys", "line": "_27yOoG_line", "exportSectionCount": "_27yOoG_exportSectionCount", "exportSectionHead": "_27yOoG_exportSectionHead", "exportRow": "_27yOoG_exportRow", "exportCodeHead": "_27yOoG_exportCodeHead" };
2943
2967
 
2944
2968
  // src/client/components/CopyButton.tsx
2945
2969
  var import_jsx_runtime10 = require("react/jsx-runtime");
@@ -3132,11 +3156,16 @@ function SourceEvidence({ item, t }) {
3132
3156
  var import_react8 = require("react");
3133
3157
  var import_dsh_client_ui_primitives9 = require("@deepseek-ai/dsh-client-ui-primitives");
3134
3158
 
3159
+ // src/export-items.ts
3160
+ var BIBTEX_KEY_SOURCE = "@[A-Za-z]+\\{([^,\\s{}]+),";
3161
+ var BIBTEX_KEY = new RegExp(BIBTEX_KEY_SOURCE);
3162
+
3135
3163
  // src/client/sources/bibtex.ts
3164
+ var BIBTEX_KEY2 = new RegExp(BIBTEX_KEY_SOURCE, "g");
3136
3165
  function bibTexKeysOf(text) {
3137
3166
  const keys = [];
3138
3167
  const seen = /* @__PURE__ */ new Set();
3139
- for (const match of text.matchAll(/@[A-Za-z]+\{([^,\s{}]+),/g)) {
3168
+ for (const match of text.matchAll(BIBTEX_KEY2)) {
3140
3169
  const key = match[1];
3141
3170
  if (!seen.has(key)) {
3142
3171
  seen.add(key);
@@ -3690,11 +3719,17 @@ function currentTime() {
3690
3719
  const pad = (value) => String(value).padStart(2, "0");
3691
3720
  return `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
3692
3721
  }
3693
- function sessionSignatureOf(slice) {
3694
- if (slice === void 0) return "";
3695
- const last = slice.nodes.length === 0 ? -1 : orderKeyOf(slice.nodes[slice.nodes.length - 1]);
3696
- const running = slice.runningCalls.map((call) => call.callId).join(",");
3697
- return `${slice.nodes.length}:${last}:${slice.runningCalls.length}:${running}`;
3722
+ function sessionSignatureOf(snapshot) {
3723
+ if (snapshot === void 0) return "";
3724
+ let count = 0;
3725
+ const running = [];
3726
+ for (const raw of snapshot.nodes.values()) {
3727
+ const node = raw;
3728
+ if (node.kind !== "tool-call" || node.visibility !== "visible") continue;
3729
+ count += 1;
3730
+ if (!("kind" in node.data.root)) running.push(node.data.root.callId);
3731
+ }
3732
+ return `${count}:${running.join(",")}`;
3698
3733
  }
3699
3734
  function stateOf(result, checkedAt) {
3700
3735
  if (!result.ok) return { kind: "remote-error", message: result.error.message };
@@ -3703,8 +3738,8 @@ function stateOf(result, checkedAt) {
3703
3738
  }
3704
3739
  return { kind: "unavailable", data: result.value, checkedAt };
3705
3740
  }
3706
- function collectZoteroCalls(slice) {
3707
- if (slice === void 0) return [];
3741
+ function collectZoteroCalls(snapshot) {
3742
+ if (snapshot === void 0) return [];
3708
3743
  const out = [];
3709
3744
  const seen = /* @__PURE__ */ new Set();
3710
3745
  const visit = (block) => {
@@ -3715,16 +3750,17 @@ function collectZoteroCalls(slice) {
3715
3750
  }
3716
3751
  for (const child of block.subCalls) visit(child);
3717
3752
  };
3718
- for (const node of slice.nodes) {
3719
- if (node.kind === "tool-result") visit(node);
3753
+ for (const raw of snapshot.nodes.values()) {
3754
+ const node = raw;
3755
+ if (node.kind !== "tool-call" || node.visibility !== "visible") continue;
3756
+ visit(node.data.root);
3720
3757
  }
3721
- for (const call of slice.runningCalls) visit(call);
3722
3758
  out.sort((a, b) => orderKeyOf(a) - orderKeyOf(b));
3723
3759
  return out;
3724
3760
  }
3725
3761
  function SourcesTab({ status, t, useSession, useChat, inputActions }) {
3726
3762
  const sessionId = useSession((snapshot) => snapshot.sessionId);
3727
- const chat = useChat((snapshot) => snapshot.legacy);
3763
+ const chat = useChat((snapshot) => snapshot);
3728
3764
  const [statusState, setStatusState] = (0, import_react11.useState)({ kind: "loading" });
3729
3765
  const [requestId, setRequestId] = (0, import_react11.useState)(0);
3730
3766
  const [serverId, setServerId] = (0, import_react11.useState)(void 0);