@a9i5k4/dsh-literature 0.3.1 → 0.3.2

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 (2) hide show
  1. package/lib/index.js +287 -82
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -2857,8 +2857,8 @@ async function startTask(key, kind) {
2857
2857
  emitTask(task);
2858
2858
  return task;
2859
2859
  }
2860
- async function finishTask(task, state2, message) {
2861
- const next = await putTask({ id: task.id, state: state2, progress: 100, message });
2860
+ async function finishTask(task, state3, message) {
2861
+ const next = await putTask({ id: task.id, state: state3, progress: 100, message });
2862
2862
  emitTask(next);
2863
2863
  return next;
2864
2864
  }
@@ -3111,8 +3111,8 @@ async function saveItem(key, { mode, tags } = {}) {
3111
3111
  if (wantMode === "dir") {
3112
3112
  let buffer = null;
3113
3113
  if (current.pdf?.path) {
3114
- const { readFile: readFile7 } = await import("node:fs/promises");
3115
- buffer = await readFile7(current.pdf.path).catch(() => null);
3114
+ const { readFile: readFile8 } = await import("node:fs/promises");
3115
+ buffer = await readFile8(current.pdf.path).catch(() => null);
3116
3116
  }
3117
3117
  result = await exportToDirectory(current.record, buffer);
3118
3118
  const updated2 = await patchItem(key, { state: "saved", saveMode: "dir", export: result, error: null, updatedAt: Date.now() });
@@ -3122,14 +3122,14 @@ async function saveItem(key, { mode, tags } = {}) {
3122
3122
  }
3123
3123
  let pdfBuffer = null;
3124
3124
  if (current.pdf?.path) {
3125
- const { readFile: readFile7 } = await import("node:fs/promises");
3126
- pdfBuffer = await readFile7(current.pdf.path).catch(() => null);
3125
+ const { readFile: readFile8 } = await import("node:fs/promises");
3126
+ pdfBuffer = await readFile8(current.pdf.path).catch(() => null);
3127
3127
  }
3128
3128
  if (!pdfBuffer) {
3129
3129
  const fetched = await fetchItemPdf(key);
3130
3130
  if (fetched?.pdf?.path) {
3131
- const { readFile: readFile7 } = await import("node:fs/promises");
3132
- pdfBuffer = await readFile7(fetched.pdf.path).catch(() => null);
3131
+ const { readFile: readFile8 } = await import("node:fs/promises");
3132
+ pdfBuffer = await readFile8(fetched.pdf.path).catch(() => null);
3133
3133
  } else {
3134
3134
  const err = fetched?.error ?? failure("fetch_failed", "\u65E0\u6CD5\u83B7\u53D6\u5168\u6587 PDF\uFF0C\u65E0\u6CD5\u4FDD\u5B58\u5230\u6587\u732E\u5E93");
3135
3135
  throw Object.assign(new Error(err.message), { code: err.code ?? "fetch_failed", detail: err.detail });
@@ -5396,8 +5396,8 @@ var init_pdf2 = __esm({
5396
5396
  var getTypedArrayConstructor = function(it) {
5397
5397
  var proto = getPrototypeOf(it);
5398
5398
  if (!isObject(proto)) return;
5399
- var state2 = getInternalState(proto);
5400
- return state2 && hasOwn(state2, TYPED_ARRAY_CONSTRUCTOR) ? state2[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto);
5399
+ var state3 = getInternalState(proto);
5400
+ return state3 && hasOwn(state3, TYPED_ARRAY_CONSTRUCTOR) ? state3[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto);
5401
5401
  };
5402
5402
  var isTypedArray = function(it) {
5403
5403
  if (!isObject(it)) return false;
@@ -6234,11 +6234,11 @@ var init_pdf2 = __esm({
6234
6234
  };
6235
6235
  var getterFor = function(TYPE) {
6236
6236
  return function(it) {
6237
- var state2;
6238
- if (!isObject(it) || (state2 = get(it)).type !== TYPE) {
6237
+ var state3;
6238
+ if (!isObject(it) || (state3 = get(it)).type !== TYPE) {
6239
6239
  throw new TypeError2("Incompatible receiver, " + TYPE + " required");
6240
6240
  }
6241
- return state2;
6241
+ return state3;
6242
6242
  };
6243
6243
  };
6244
6244
  if (NATIVE_WEAK_MAP || shared.state) {
@@ -6363,8 +6363,8 @@ var init_pdf2 = __esm({
6363
6363
  var getInternalState = __webpack_require__2(1181).get;
6364
6364
  module.exports = function isRawJSON(O) {
6365
6365
  if (!isObject(O)) return false;
6366
- var state2 = getInternalState(O);
6367
- return !!state2 && state2.type === "RawJSON";
6366
+ var state3 = getInternalState(O);
6367
+ return !!state3 && state3.type === "RawJSON";
6368
6368
  };
6369
6369
  },
6370
6370
  /***/
@@ -6465,8 +6465,8 @@ var init_pdf2 = __esm({
6465
6465
  },
6466
6466
  /***/
6467
6467
  6859(module) {
6468
- module.exports = function(state2) {
6469
- state2.iterator = state2.next = state2.nextHandler = state2.mapper = state2.predicate = state2.inner = state2.iterables = state2.iters = state2.openIters = state2.padding = state2.finishResults = state2.buffer = null;
6468
+ module.exports = function(state3) {
6469
+ state3.iterator = state3.next = state3.nextHandler = state3.mapper = state3.predicate = state3.inner = state3.iterables = state3.iters = state3.openIters = state3.padding = state3.finishResults = state3.buffer = null;
6470
6470
  };
6471
6471
  },
6472
6472
  /***/
@@ -6535,31 +6535,31 @@ var init_pdf2 = __esm({
6535
6535
  var getInternalState = InternalStateModule.getterFor(IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER);
6536
6536
  return defineBuiltIns(create(IteratorPrototype), {
6537
6537
  next: function next() {
6538
- var state2 = getInternalState(this);
6539
- if (IS_ITERATOR) return state2.nextHandler();
6540
- if (state2.done) return createIterResultObject(void 0, true);
6538
+ var state3 = getInternalState(this);
6539
+ if (IS_ITERATOR) return state3.nextHandler();
6540
+ if (state3.done) return createIterResultObject(void 0, true);
6541
6541
  try {
6542
- var result = state2.nextHandler();
6543
- if (state2.done) cleanupState(state2);
6544
- return state2.returnHandlerResult ? result : createIterResultObject(result, state2.done);
6542
+ var result = state3.nextHandler();
6543
+ if (state3.done) cleanupState(state3);
6544
+ return state3.returnHandlerResult ? result : createIterResultObject(result, state3.done);
6545
6545
  } catch (error2) {
6546
- state2.done = true;
6547
- cleanupState(state2);
6546
+ state3.done = true;
6547
+ cleanupState(state3);
6548
6548
  throw error2;
6549
6549
  }
6550
6550
  },
6551
6551
  "return": function() {
6552
- var state2 = getInternalState(this);
6553
- var iterator = state2.iterator;
6554
- var inner = state2.inner;
6555
- var openIters = state2.openIters;
6556
- var done = state2.done;
6557
- state2.done = true;
6552
+ var state3 = getInternalState(this);
6553
+ var iterator = state3.iterator;
6554
+ var inner = state3.inner;
6555
+ var openIters = state3.openIters;
6556
+ var done = state3.done;
6557
+ state3.done = true;
6558
6558
  if (IS_ITERATOR) {
6559
6559
  var returnMethod = getMethod(iterator, "return");
6560
6560
  return returnMethod ? call2(returnMethod, iterator) : createIterResultObject(void 0, true);
6561
6561
  }
6562
- cleanupState(state2);
6562
+ cleanupState(state3);
6563
6563
  if (done) return createIterResultObject(void 0, true);
6564
6564
  if (inner) try {
6565
6565
  iteratorClose(inner.iterator, NORMAL);
@@ -6581,17 +6581,17 @@ var init_pdf2 = __esm({
6581
6581
  var IteratorHelperPrototype = createIteratorProxyPrototype(false);
6582
6582
  createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, "Iterator Helper");
6583
6583
  module.exports = function(nextHandler, IS_ITERATOR, RETURN_HANDLER_RESULT) {
6584
- var IteratorProxy = function Iterator2(record, state2) {
6585
- if (state2) {
6586
- state2.iterator = record.iterator;
6587
- state2.next = record.next;
6588
- } else state2 = record;
6589
- state2.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER;
6590
- state2.returnHandlerResult = !!RETURN_HANDLER_RESULT;
6591
- state2.nextHandler = nextHandler;
6592
- state2.counter = 0;
6593
- state2.done = false;
6594
- setInternalState(this, state2);
6584
+ var IteratorProxy = function Iterator2(record, state3) {
6585
+ if (state3) {
6586
+ state3.iterator = record.iterator;
6587
+ state3.next = record.next;
6588
+ } else state3 = record;
6589
+ state3.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER;
6590
+ state3.returnHandlerResult = !!RETURN_HANDLER_RESULT;
6591
+ state3.nextHandler = nextHandler;
6592
+ state3.counter = 0;
6593
+ state3.done = false;
6594
+ setInternalState(this, state3);
6595
6595
  };
6596
6596
  IteratorProxy.prototype = IS_ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype;
6597
6597
  return IteratorProxy;
@@ -6695,7 +6695,7 @@ var init_pdf2 = __esm({
6695
6695
  var defineProperty = Object.defineProperty;
6696
6696
  var stringSlice = uncurryThis("".slice);
6697
6697
  var replace = uncurryThis("".replace);
6698
- var join9 = uncurryThis([].join);
6698
+ var join10 = uncurryThis([].join);
6699
6699
  var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() {
6700
6700
  return defineProperty(function() {
6701
6701
  }, "length", { value: 8 }).length !== 8;
@@ -6720,9 +6720,9 @@ var init_pdf2 = __esm({
6720
6720
  } else if (value.prototype) value.prototype = void 0;
6721
6721
  } catch (error2) {
6722
6722
  }
6723
- var state2 = enforceInternalState(value);
6724
- if (!hasOwn(state2, "source")) {
6725
- state2.source = join9(TEMPLATE, typeof name2 == "string" ? name2 : "");
6723
+ var state3 = enforceInternalState(value);
6724
+ if (!hasOwn(state3, "source")) {
6725
+ state3.source = join10(TEMPLATE, typeof name2 == "string" ? name2 : "");
6726
6726
  }
6727
6727
  return value;
6728
6728
  };
@@ -8864,21 +8864,21 @@ var init_pdf2 = __esm({
8864
8864
  sumPrecise: function sumPrecise(items) {
8865
8865
  var numbers = [];
8866
8866
  var count = 0;
8867
- var state2 = MINUS_ZERO;
8867
+ var state3 = MINUS_ZERO;
8868
8868
  iterate(items, function(n2) {
8869
8869
  if (++count > MAX_SAFE_INTEGER) throw new $RangeError("Maximum allowed index exceeded");
8870
8870
  if (typeof n2 != "number") throw new $TypeError("Value is not a number");
8871
- if (state2 !== NOT_A_NUMBER) {
8872
- if (n2 !== n2) state2 = NOT_A_NUMBER;
8873
- else if (n2 === $Infinity) state2 = state2 === MINUS_INFINITY ? NOT_A_NUMBER : PLUS_INFINITY;
8874
- else if (n2 === -$Infinity) state2 = state2 === PLUS_INFINITY ? NOT_A_NUMBER : MINUS_INFINITY;
8875
- else if ((n2 !== 0 || 1 / n2 === $Infinity) && (state2 === MINUS_ZERO || state2 === FINITE)) {
8876
- state2 = FINITE;
8871
+ if (state3 !== NOT_A_NUMBER) {
8872
+ if (n2 !== n2) state3 = NOT_A_NUMBER;
8873
+ else if (n2 === $Infinity) state3 = state3 === MINUS_INFINITY ? NOT_A_NUMBER : PLUS_INFINITY;
8874
+ else if (n2 === -$Infinity) state3 = state3 === PLUS_INFINITY ? NOT_A_NUMBER : MINUS_INFINITY;
8875
+ else if ((n2 !== 0 || 1 / n2 === $Infinity) && (state3 === MINUS_ZERO || state3 === FINITE)) {
8876
+ state3 = FINITE;
8877
8877
  push2(numbers, n2);
8878
8878
  }
8879
8879
  }
8880
8880
  });
8881
- switch (state2) {
8881
+ switch (state3) {
8882
8882
  case NOT_A_NUMBER:
8883
8883
  return $NaN;
8884
8884
  case MINUS_INFINITY:
@@ -9245,7 +9245,7 @@ var init_pdf2 = __esm({
9245
9245
  var charAt = uncurryThis("".charAt);
9246
9246
  var Uint8Array2 = globalThis2.Uint8Array;
9247
9247
  var $Array = globalThis2.Array;
9248
- var join9 = uncurryThis([].join);
9248
+ var join10 = uncurryThis([].join);
9249
9249
  var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() {
9250
9250
  try {
9251
9251
  var target = new Uint8Array2();
@@ -9291,7 +9291,7 @@ var init_pdf2 = __esm({
9291
9291
  result[written++] = "=";
9292
9292
  }
9293
9293
  }
9294
- return join9(result, "");
9294
+ return join10(result, "");
9295
9295
  }
9296
9296
  });
9297
9297
  },
@@ -9303,7 +9303,7 @@ var init_pdf2 = __esm({
9303
9303
  var anUint8Array = __webpack_require__2(4154);
9304
9304
  var notDetached = __webpack_require__2(5169);
9305
9305
  var numberToString = uncurryThis(1.1.toString);
9306
- var join9 = uncurryThis([].join);
9306
+ var join10 = uncurryThis([].join);
9307
9307
  var $Array = Array;
9308
9308
  var Uint8Array2 = globalThis2.Uint8Array;
9309
9309
  var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() {
@@ -9323,7 +9323,7 @@ var init_pdf2 = __esm({
9323
9323
  var hex = numberToString(this[i], 16);
9324
9324
  result[i] = hex.length === 1 ? "0" + hex : hex;
9325
9325
  }
9326
- return join9(result, "");
9326
+ return join10(result, "");
9327
9327
  }
9328
9328
  });
9329
9329
  },
@@ -12515,8 +12515,8 @@ var init_pdf2 = __esm({
12515
12515
  editor.show(visible);
12516
12516
  }
12517
12517
  }
12518
- const state2 = this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true;
12519
- if (state2 !== visible) {
12518
+ const state3 = this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true;
12519
+ if (state3 !== visible) {
12520
12520
  this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]);
12521
12521
  }
12522
12522
  }
@@ -22362,28 +22362,28 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
22362
22362
  const operator = array[0];
22363
22363
  for (let i = 1; i < length; i++) {
22364
22364
  const element = array[i];
22365
- let state2;
22365
+ let state3;
22366
22366
  if (Array.isArray(element)) {
22367
- state2 = this.#evaluateVisibilityExpression(element);
22367
+ state3 = this.#evaluateVisibilityExpression(element);
22368
22368
  } else if (this.#groups.has(element)) {
22369
- state2 = this.#groups.get(element).visible;
22369
+ state3 = this.#groups.get(element).visible;
22370
22370
  } else {
22371
22371
  warn2(`Optional content group not found: ${element}`);
22372
22372
  return true;
22373
22373
  }
22374
22374
  switch (operator) {
22375
22375
  case "And":
22376
- if (!state2) {
22376
+ if (!state3) {
22377
22377
  return false;
22378
22378
  }
22379
22379
  break;
22380
22380
  case "Or":
22381
- if (state2) {
22381
+ if (state3) {
22382
22382
  return true;
22383
22383
  }
22384
22384
  break;
22385
22385
  case "Not":
22386
- return !state2;
22386
+ return !state3;
22387
22387
  default:
22388
22388
  return true;
22389
22389
  }
@@ -22478,11 +22478,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
22478
22478
  this.#cachedGetHash = null;
22479
22479
  }
22480
22480
  setOCGState({
22481
- state: state2,
22481
+ state: state3,
22482
22482
  preserveRB
22483
22483
  }) {
22484
22484
  let operator;
22485
- for (const elem of state2) {
22485
+ for (const elem of state3) {
22486
22486
  switch (elem) {
22487
22487
  case "ON":
22488
22488
  case "OFF":
@@ -35902,6 +35902,152 @@ var init_ai = __esm({
35902
35902
  }
35903
35903
  });
35904
35904
 
35905
+ // src/node/profile.js
35906
+ var profile_exports = {};
35907
+ __export(profile_exports, {
35908
+ distillMaterial: () => distillMaterial,
35909
+ profileMarkdown: () => profileMarkdown,
35910
+ recordCite: () => recordCite,
35911
+ recordMethod: () => recordMethod,
35912
+ recordNote: () => recordNote,
35913
+ recordQuery: () => recordQuery,
35914
+ recordTopic: () => recordTopic,
35915
+ saveProfileMarkdown: () => saveProfileMarkdown,
35916
+ setSelfDeclared: () => setSelfDeclared
35917
+ });
35918
+ import { readFile as readFile6, writeFile as writeFile5, mkdir as mkdir5 } from "node:fs/promises";
35919
+ import { join as join7, dirname as dirname4 } from "node:path";
35920
+ async function load2() {
35921
+ if (state2) return state2;
35922
+ try {
35923
+ state2 = { ...structuredClone(EMPTY2), ...JSON.parse(await readFile6(PROFILE_PATH, "utf8")) };
35924
+ } catch {
35925
+ state2 = structuredClone(EMPTY2);
35926
+ }
35927
+ return state2;
35928
+ }
35929
+ async function persist2() {
35930
+ await mkdir5(dirname4(PROFILE_PATH), { recursive: true });
35931
+ await writeFile5(PROFILE_PATH, JSON.stringify(state2, null, 2), "utf8");
35932
+ }
35933
+ function schedulePersist() {
35934
+ if (saveTimer) return;
35935
+ saveTimer = setTimeout(() => {
35936
+ saveTimer = null;
35937
+ persist2().catch(() => {
35938
+ });
35939
+ }, 800);
35940
+ saveTimer.unref?.();
35941
+ }
35942
+ function bump(map, key, by = 1) {
35943
+ if (!key) return;
35944
+ map[key] = (map[key] ?? 0) + by;
35945
+ }
35946
+ async function recordCite(style) {
35947
+ const s = await load2();
35948
+ bump(s.citationStyles, String(style ?? "apa").toLowerCase());
35949
+ s.updatedAt = Date.now();
35950
+ schedulePersist();
35951
+ }
35952
+ async function recordQuery(query) {
35953
+ const s = await load2();
35954
+ s.queries.unshift({ q: String(query ?? "").slice(0, 120), at: Date.now() });
35955
+ if (s.queries.length > 100) s.queries.length = 100;
35956
+ s.updatedAt = Date.now();
35957
+ schedulePersist();
35958
+ }
35959
+ async function recordNote(key, note) {
35960
+ const s = await load2();
35961
+ const text = String(note ?? "");
35962
+ s.pragmatics.noteCount += 1;
35963
+ s.pragmatics.avgNoteLen = Math.round((s.pragmatics.avgNoteLen * (s.pragmatics.noteCount - 1) + text.length) / s.pragmatics.noteCount);
35964
+ s.pragmatics.language = hasCjk(text) ? /[a-zA-Z]{4,}/.test(text) ? "zh-en-mixed" : "zh" : "en";
35965
+ schedulePersist();
35966
+ }
35967
+ async function recordTopic(topic, itemKey) {
35968
+ const s = await load2();
35969
+ const t = String(topic ?? "").trim().slice(0, 60);
35970
+ if (!t) return;
35971
+ const entry = s.topics[t] = s.topics[t] ?? { weight: 0, evidence: [] };
35972
+ entry.weight += 1;
35973
+ if (itemKey && !entry.evidence.includes(itemKey)) entry.evidence.unshift(itemKey);
35974
+ if (entry.evidence.length > 10) entry.evidence.length = 10;
35975
+ s.updatedAt = Date.now();
35976
+ schedulePersist();
35977
+ }
35978
+ async function recordMethod(kind) {
35979
+ const s = await load2();
35980
+ bump(s.methods, String(kind ?? "").toLowerCase());
35981
+ schedulePersist();
35982
+ }
35983
+ async function setSelfDeclared(text) {
35984
+ const s = await load2();
35985
+ s.selfDeclared = String(text ?? "").slice(0, 2e3);
35986
+ s.updatedAt = Date.now();
35987
+ await persist2();
35988
+ }
35989
+ async function distillMaterial() {
35990
+ const s = await load2();
35991
+ const top = Object.entries(s.topics).sort((a, b) => b[1].weight - a[1].weight).slice(0, 12).map(([topic, v]) => `${topic}\uFF08${v.weight} \u6B21 \xB7 \u8BC1\u636E\uFF1A${v.evidence.slice(0, 3).join(", ") || "\u2014"}\uFF09`);
35992
+ const methods = Object.entries(s.methods).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}=${v}`);
35993
+ const styles = Object.entries(s.citationStyles).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}=${v}`);
35994
+ const queries = s.queries.slice(0, 20).map((q) => `- ${q.q}`);
35995
+ return [
35996
+ `\u3010\u753B\u50CF\u84B8\u998F\u7D20\u6750\u3011\uFF08\u622A\u81F3 ${new Date(s.updatedAt ?? Date.now()).toISOString().slice(0, 10)}\uFF09`,
35997
+ top.length ? `\u7814\u7A76\u4E3B\u9898\uFF08\u6309\u51FA\u73B0\u9891\u6B21\uFF09\uFF1A
35998
+ ${top.map((t) => "- " + t).join("\n")}` : "\u7814\u7A76\u4E3B\u9898\uFF1A\u6682\u65E0\u8DB3\u591F\u6570\u636E",
35999
+ methods.length ? `\u65B9\u6CD5\u8BBA\u503E\u5411\uFF1A${methods.join(", ")}` : "\u65B9\u6CD5\u8BBA\u503E\u5411\uFF1A\u6682\u65E0\u6570\u636E",
36000
+ styles.length ? `\u5F15\u7528\u683C\u5F0F\u4F7F\u7528\uFF1A${styles.join(", ")}` : "\u5F15\u7528\u683C\u5F0F\u4F7F\u7528\uFF1A\u6682\u65E0\u6570\u636E",
36001
+ `\u8BED\u7528\u89C2\u5BDF\uFF1A\u8BED\u8A00=${s.pragmatics.language || "\u672A\u77E5"}\uFF0C\u7B14\u8BB0\u5747\u957F=${s.pragmatics.avgNoteLen} \u5B57\uFF0C\u7B14\u8BB0\u6570=${s.pragmatics.noteCount}`,
36002
+ queries.length ? `\u8FD1\u671F\u68C0\u7D22\uFF08\u53CD\u6620\u771F\u5B9E\u5173\u6CE8\u70B9\uFF09\uFF1A
36003
+ ${queries.join("\n")}` : "\u8FD1\u671F\u68C0\u7D22\uFF1A\u6682\u65E0",
36004
+ s.selfDeclared ? `\u7528\u6237\u81EA\u8FF0\uFF1A${s.selfDeclared}` : ""
36005
+ ].filter(Boolean).join("\n\n");
36006
+ }
36007
+ async function profileMarkdown() {
36008
+ try {
36009
+ return await readFile6(PROFILE_MD_PATH, "utf8");
36010
+ } catch {
36011
+ return "";
36012
+ }
36013
+ }
36014
+ async function saveProfileMarkdown(md) {
36015
+ await mkdir5(dirname4(PROFILE_MD_PATH), { recursive: true });
36016
+ await writeFile5(PROFILE_MD_PATH, String(md ?? "").slice(0, 8e3), "utf8");
36017
+ }
36018
+ function hasCjk(s) {
36019
+ return /[\u4e00-\u9fff]/.test(String(s ?? ""));
36020
+ }
36021
+ var PROFILE_PATH, PROFILE_MD_PATH, EMPTY2, state2, saveTimer;
36022
+ var init_profile = __esm({
36023
+ "src/node/profile.js"() {
36024
+ init_config();
36025
+ PROFILE_PATH = join7(STORE_DIR, "scholar-profile.json");
36026
+ PROFILE_MD_PATH = join7(STORE_DIR, "scholar-profile.md");
36027
+ EMPTY2 = {
36028
+ version: 1,
36029
+ updatedAt: 0,
36030
+ // topic -> { weight, evidence: [itemKey] } — raised by deepread cards,
36031
+ // saves, notes. Weight is a simple counter; ranking normalises it.
36032
+ topics: {},
36033
+ // methodology affinity: experiment / theory / engineering / review
36034
+ methods: {},
36035
+ // citation format usage counters: apa / gb / mla / chicago / bibtex
36036
+ citationStyles: {},
36037
+ // search query log (capped): what the user asks for, verbatim
36038
+ queries: [],
36039
+ // canonical term -> accepted variants (from notes/deepread language)
36040
+ terminology: {},
36041
+ // pragmatics observed from query & note text
36042
+ pragmatics: { language: "", avgNoteLen: 0, noteCount: 0 },
36043
+ // free-form notes the user explicitly adds about themselves
36044
+ selfDeclared: ""
36045
+ };
36046
+ state2 = null;
36047
+ saveTimer = null;
36048
+ }
36049
+ });
36050
+
35905
36051
  // src/node/courseware/reading-modes.js
35906
36052
  var reading_modes_exports = {};
35907
36053
  __export(reading_modes_exports, {
@@ -36021,12 +36167,12 @@ __export(doctor_selfheal_exports, {
36021
36167
  });
36022
36168
  import { createHash } from "node:crypto";
36023
36169
  import { existsSync as existsSync2, readdirSync as readdirSync2 } from "node:fs";
36024
- import { join as join8 } from "node:path";
36170
+ import { join as join9 } from "node:path";
36025
36171
  import { homedir as homedir4 } from "node:os";
36026
36172
  import { spawn } from "node:child_process";
36027
36173
  import net from "node:net";
36028
36174
  function doctorRoot() {
36029
- return process.env.DSH_DOCTOR_HOME?.trim() || join8(homedir4(), ".dsh-doctor");
36175
+ return process.env.DSH_DOCTOR_HOME?.trim() || join9(homedir4(), ".dsh-doctor");
36030
36176
  }
36031
36177
  function doctorPipeName(root = doctorRoot()) {
36032
36178
  const hash = createHash("sha256").update(root).digest("hex").slice(0, 16);
@@ -36051,7 +36197,7 @@ function pipeAvailable(pipe, timeoutMs = 1500) {
36051
36197
  });
36052
36198
  }
36053
36199
  function findDoctorCli() {
36054
- const profilesDir = join8(homedir4(), ".dsh", "profiles");
36200
+ const profilesDir = join9(homedir4(), ".dsh", "profiles");
36055
36201
  let entries = [];
36056
36202
  try {
36057
36203
  entries = readdirSync2(profilesDir);
@@ -36059,7 +36205,7 @@ function findDoctorCli() {
36059
36205
  return "";
36060
36206
  }
36061
36207
  for (const name2 of entries) {
36062
- const candidate = join8(profilesDir, name2, "node_modules", "@linxin666", "dsh-doctor", "lib", "cli.mjs");
36208
+ const candidate = join9(profilesDir, name2, "node_modules", "@linxin666", "dsh-doctor", "lib", "cli.mjs");
36063
36209
  if (existsSync2(candidate)) return candidate;
36064
36210
  }
36065
36211
  return "";
@@ -36641,9 +36787,10 @@ function snippetFor(item, terms) {
36641
36787
  // src/node/tools.js
36642
36788
  init_normalize();
36643
36789
  init_log();
36644
- import { writeFile as writeFile5, mkdtemp, readFile as readFile6, rm } from "node:fs/promises";
36790
+ init_profile();
36791
+ import { writeFile as writeFile6, mkdtemp, readFile as readFile7, rm } from "node:fs/promises";
36645
36792
  import { tmpdir } from "node:os";
36646
- import { join as join7 } from "node:path";
36793
+ import { join as join8 } from "node:path";
36647
36794
  function textResult(value) {
36648
36795
  return {
36649
36796
  schema: { type: "string" },
@@ -36651,7 +36798,7 @@ function textResult(value) {
36651
36798
  };
36652
36799
  }
36653
36800
  function toolDefs() {
36654
- return [lookupTool(), searchTool(), getTool(), citeTool(), noteTool(), statusTool(), saveTool(), figureTool(), deepreadTool()];
36801
+ return [lookupTool(), searchTool(), getTool(), citeTool(), noteTool(), statusTool(), saveTool(), figureTool(), deepreadTool(), profileTool()];
36655
36802
  }
36656
36803
  function registerTools(ctx2) {
36657
36804
  let mounted = [];
@@ -36743,6 +36890,8 @@ function searchTool() {
36743
36890
  async execute(args) {
36744
36891
  const query = String(args?.query ?? "").trim();
36745
36892
  if (!query) return "\u7F3A\u5C11\u68C0\u7D22\u8BCD\u3002";
36893
+ recordQuery(query).catch(() => {
36894
+ });
36746
36895
  const limit = Math.max(1, Math.min(Number(args?.limit) || 8, 20));
36747
36896
  const items = await listItems();
36748
36897
  const hits = searchItems2(items, query, { limit });
@@ -36815,6 +36964,8 @@ function citeTool() {
36815
36964
  const item = await getItem(key);
36816
36965
  if (!item?.record) return `\u6761\u76EE ${key} \u7F3A\u5C11\u5143\u6570\u636E\uFF0C\u65E0\u6CD5\u751F\u6210\u5F15\u7528\u3002\u8BF7\u5148\u7528 literature_lookup \u89E3\u6790\u5143\u6570\u636E\u3002`;
36817
36966
  const { citeDetailed: citeDetailed2 } = await Promise.resolve().then(() => (init_cite(), cite_exports));
36967
+ recordCite(args?.style ?? "apa").catch(() => {
36968
+ });
36818
36969
  const d = citeDetailed2(item.record, {
36819
36970
  style: args?.style ?? "apa",
36820
36971
  mode: args?.mode ?? "reference",
@@ -36851,6 +37002,8 @@ function noteTool() {
36851
37002
  if (notes.some((n) => (typeof n === "string" ? n : n.text) === note)) return "\u8BE5\u7B14\u8BB0\u5DF2\u5B58\u5728\uFF0C\u672A\u91CD\u590D\u5199\u5165\u3002";
36852
37003
  const entry = { text: note, at: (/* @__PURE__ */ new Date()).toISOString() };
36853
37004
  await patchItem(key, { notes: [...notes, entry] });
37005
+ recordNote(key, note).catch(() => {
37006
+ });
36854
37007
  return `\u5DF2\u8BB0\u5F55\u5230\u6761\u76EE ${key}\uFF08\u5171 ${notes.length + 1} \u6761\u7B14\u8BB0\uFF09\u3002`;
36855
37008
  }
36856
37009
  };
@@ -36922,10 +37075,10 @@ function figureTool() {
36922
37075
  if (!fig || !fig.hasMatplotlib) {
36923
37076
  return "\u793A\u610F\u56FE\u5F15\u64CE\u5C1A\u672A\u5C31\u7EEA\uFF1A\u672C\u673A\u7F3A\u5C11 Python + matplotlib\u3002\u8BF7\u5728\u4FA7\u7A97\u8BBE\u7F6E\u9875\u300C\u793A\u610F\u56FE\u5F15\u64CE\u300D\u4E2D\u70B9\u51FB\u300C\u5B89\u88C5\u4F9D\u8D56\u300D\u540E\u91CD\u8BD5\uFF1B\u671F\u95F4\u53EF\u4EE5\u8BA9\u6211\u8F93\u51FA\u6570\u636E\u8868\u683C\u4EE3\u66FF\u56FE\u8868\u3002";
36924
37077
  }
36925
- const { mkdtemp: _mk, writeFile: _w, readFile: _r, rm: _rm } = { mkdtemp, writeFile: writeFile5, readFile: readFile6, rm };
36926
- const dir = await mkdtemp(join7(tmpdir(), "lit-fig-"));
36927
- const pyFile = join7(dir, "fig.py");
36928
- const pngFile = join7(dir, "fig.png");
37078
+ const { mkdtemp: _mk, writeFile: _w, readFile: _r, rm: _rm } = { mkdtemp, writeFile: writeFile6, readFile: readFile7, rm };
37079
+ const dir = await mkdtemp(join8(tmpdir(), "lit-fig-"));
37080
+ const pyFile = join8(dir, "fig.py");
37081
+ const pngFile = join8(dir, "fig.png");
36929
37082
  const script = [
36930
37083
  "import matplotlib",
36931
37084
  "matplotlib.use('Agg')",
@@ -36962,13 +37115,13 @@ function figureTool() {
36962
37115
  "plt.tight_layout()",
36963
37116
  `plt.savefig(${JSON.stringify(pngFile)})`
36964
37117
  ].join("\n");
36965
- await writeFile5(pyFile, script, "utf8");
37118
+ await writeFile6(pyFile, script, "utf8");
36966
37119
  const { execFile: execFile2 } = await import("node:child_process");
36967
37120
  const run2 = () => new Promise((resolve6) => execFile2(fig.exe, [pyFile], { timeout: 6e4, windowsHide: true }, (err, stdout, stderr) => resolve6({ err, stdout, stderr })));
36968
37121
  const r = await run2();
36969
37122
  let png = null;
36970
37123
  try {
36971
- png = await readFile6(pngFile);
37124
+ png = await readFile7(pngFile);
36972
37125
  } catch {
36973
37126
  }
36974
37127
  await rm(dir, { recursive: true, force: true }).catch(() => {
@@ -37021,6 +37174,8 @@ function deepreadTool() {
37021
37174
  for (const m of text.matchAll(/(?:Fig(?:ure)?|表|Table)\s*\d+[.::][^\n]{5,90}/g)) {
37022
37175
  if (figures.length < 12) figures.push(m[0].trim());
37023
37176
  }
37177
+ recordTopic(title, key).catch(() => {
37178
+ });
37024
37179
  const { buildReadPackage: buildReadPackage2 } = await Promise.resolve().then(() => (init_reading_modes(), reading_modes_exports));
37025
37180
  const pack = buildReadPackage2(mode, { title, text, figures });
37026
37181
  return pack + `
@@ -37029,6 +37184,56 @@ function deepreadTool() {
37029
37184
  }
37030
37185
  };
37031
37186
  }
37187
+ function profileTool() {
37188
+ return {
37189
+ name: "literature_profile",
37190
+ description: "\u5B66\u8005\u753B\u50CF\uFF1A\u67E5\u770B/\u84B8\u998F/\u4FDD\u5B58\u6839\u636E\u7528\u6237\u6587\u732E\u884C\u4E3A\u63A8\u65AD\u7684\u5B66\u672F\u80CC\u666F\u3001\u8BED\u7528\u4E60\u60EF\u4E0E\u504F\u597D\u3002\u7528\u6237\u95EE\u300C\u6211\u7684\u7814\u7A76\u753B\u50CF/\u6211\u5728\u5173\u6CE8\u4EC0\u4E48/\u6839\u636E\u6211\u7684\u4E60\u60EF\u6765\u300D\u65F6\u8C03\u7528\uFF1B\u84B8\u998F\u540E\u628A\u753B\u50CF\u5199\u56DE\uFF08action=save\uFF09\uFF0C\u5E76\u53EF\u5EFA\u8BAE\u7528\u6237\u540C\u6B65\u5230 auto-memory\u3002",
37191
+ parameters: {
37192
+ type: "object",
37193
+ properties: {
37194
+ action: { type: "string", description: "view\uFF08\u9ED8\u8BA4\uFF0C\u770B\u5F53\u524D\u753B\u50CF\uFF09| distill\uFF08\u53D6\u7D20\u6750\u5E76\u84B8\u998F\uFF09| save\uFF08\u4FDD\u5B58\u84B8\u998F\u7ED3\u679C\uFF09| self\uFF08\u767B\u8BB0\u7528\u6237\u81EA\u8FF0\uFF09" },
37195
+ content: { type: "string", description: "action=save \u65F6\u7684\u753B\u50CF Markdown\uFF1Baction=self \u65F6\u7684\u7528\u6237\u81EA\u8FF0" }
37196
+ },
37197
+ required: []
37198
+ },
37199
+ output: textResult(),
37200
+ timeoutMs: 15e3,
37201
+ async execute(args) {
37202
+ const { distillMaterial: distillMaterial2, profileMarkdown: profileMarkdown2, saveProfileMarkdown: saveProfileMarkdown2, setSelfDeclared: setSelfDeclared2 } = await Promise.resolve().then(() => (init_profile(), profile_exports));
37203
+ const action = String(args?.action ?? "view");
37204
+ if (action === "save") {
37205
+ const md = String(args?.content ?? "").trim();
37206
+ if (!md) return "\u7F3A\u5C11\u753B\u50CF\u5185\u5BB9\uFF08content\uFF09\u3002";
37207
+ await saveProfileMarkdown2(md);
37208
+ return "\u5B66\u8005\u753B\u50CF\u5DF2\u4FDD\u5B58\u3002\n[\u4E0B\u4E00\u6B65] \u7528\u6237\u5982\u9700\u8DE8\u4F1A\u8BDD\u751F\u6548\uFF0C\u5EFA\u8BAE\u628A\u753B\u50CF\u540C\u6B65\u5230 auto-memory \u7684\u7528\u6237\u7EA7\u8BB0\u5FC6\uFF08memory_user_pre\uFF09\uFF0C\u6216\u7531\u7528\u6237\u5728\u8BB0\u5FC6\u9762\u677F\u786E\u8BA4\u3002";
37209
+ }
37210
+ if (action === "self") {
37211
+ await setSelfDeclared2(args?.content);
37212
+ return "\u5DF2\u767B\u8BB0\u7528\u6237\u81EA\u8FF0\uFF0C\u4E0B\u6B21\u84B8\u998F\u4F1A\u7EB3\u5165\u3002";
37213
+ }
37214
+ if (action === "distill") {
37215
+ const material = await distillMaterial2();
37216
+ const existing = await profileMarkdown2();
37217
+ return [
37218
+ material,
37219
+ "",
37220
+ existing ? "\u3010\u73B0\u6709\u753B\u50CF\u3011\n" + existing : "",
37221
+ "",
37222
+ "\u4EFB\u52A1\uFF1A\u4F9D\u636E\u7D20\u6750\u5199\u4E00\u4EFD\u300C\u5B66\u8005\u753B\u50CF\u300D\uFF08Markdown\uFF0C\u2264600 \u5B57\uFF09\uFF0C\u7ED3\u6784\u56FA\u5B9A\u4E3A\uFF1A",
37223
+ "## \u7814\u7A76\u9886\u57DF\uFF08\u6309\u719F\u6089\u5EA6\u6392\u5E8F\uFF09",
37224
+ "## \u65B9\u6CD5\u8BBA\u504F\u597D\uFF08\u5B9E\u9A8C/\u7406\u8BBA/\u5DE5\u7A0B\uFF09",
37225
+ "## \u672F\u8BED\u4E0E\u8868\u8FBE\u4E60\u60EF\uFF08\u7528\u6237\u5982\u4F55\u79F0\u547C\u6982\u5FF5\u3001\u4E2D\u82F1\u6DF7\u7528\u60C5\u51B5\uFF09",
37226
+ "## \u5F15\u7528\u4E60\u60EF\uFF08\u5E38\u7528\u683C\u5F0F\u3001\u8BED\u6C14\uFF09",
37227
+ "## \u5F53\u524D\u5173\u6CE8\u4E0E\u76EE\u6807",
37228
+ "\u53EA\u4F9D\u636E\u7D20\u6750\uFF0C\u4E0D\u63A8\u65AD\u7D20\u6750\u4E4B\u5916\u7684\u5185\u5BB9\uFF1B\u8BC1\u636E\u4E0D\u8DB3\u7684\u7EF4\u5EA6\u5199\u300C\u6682\u65E0\u8DB3\u591F\u6570\u636E\u300D\u3002",
37229
+ "\u5199\u5B8C\u540E\u8C03\u7528 literature_profile(action=save, content=\u753B\u50CF) \u4FDD\u5B58\u3002"
37230
+ ].join("\n");
37231
+ }
37232
+ const current = await profileMarkdown2();
37233
+ return current ? "\u3010\u5F53\u524D\u5B66\u8005\u753B\u50CF\u3011\n" + current : "\u5C1A\u65E0\u753B\u50CF\u3002\u8C03\u7528 literature_profile(action=distill) \u4F9D\u636E\u884C\u4E3A\u7D20\u6750\u84B8\u998F\u4E00\u4EFD\u3002";
37234
+ }
37235
+ };
37236
+ }
37032
37237
  function saveTool() {
37033
37238
  return {
37034
37239
  name: "literature_save",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a9i5k4/dsh-literature",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "DSH Literature 文献侧窗:在 DeepSeek Harness 侧边栏识别 DOI/arXiv/标题、抓取元数据与全文、写入本地文献库或导出目录,并提供内置 PDF 阅读器(缩放/翻页/目录/搜索/高亮/笔记)。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",