@a9i5k4/dsh-literature 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/README_EN.md +4 -2
- package/lib/client.js +27 -13
- package/lib/index.js +70 -20
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -757,7 +757,7 @@ var UA, FetchFailure;
|
|
|
757
757
|
var init_net = __esm({
|
|
758
758
|
"src/node/net.js"() {
|
|
759
759
|
init_log();
|
|
760
|
-
UA = "dsh-literature/0.3.
|
|
760
|
+
UA = "dsh-literature/0.3.6 (+https://github.com/deepseek-ai/deepseek-harness)";
|
|
761
761
|
FetchFailure = class extends Error {
|
|
762
762
|
constructor(message, { code = "network", status = 0, retryable = true, cause } = {}) {
|
|
763
763
|
super(message, { cause });
|
|
@@ -2421,6 +2421,8 @@ function titleFromFilename(name2) {
|
|
|
2421
2421
|
if (doi) return { kind: "doi", value: doi[1].replace(/_/g, "/") };
|
|
2422
2422
|
const arxiv = /\b(\d{4}\.\d{4,5})(v\d+)?\b/.exec(t);
|
|
2423
2423
|
if (arxiv) return { kind: "arxiv", value: arxiv[1] + (arxiv[2] ?? "") };
|
|
2424
|
+
const springer = /^([a-z]\d{4,6}-\d{2,4}-\d{2,6}(?:-[a-z0-9]{1,10})?)(?:\s*\(\d+\))?\s*$/i.exec(t.trim());
|
|
2425
|
+
if (springer) return { kind: "doi", value: `10.1007/${springer[1].toLowerCase()}` };
|
|
2424
2426
|
t = t.replace(/^\[\d+\]\s*/, "").replace(/\s*\(?\d{4}[a-z]?\)?\s*$/i, "").replace(/[_\-]+/g, " ").replace(/^\d+[\s.]+/, "").trim();
|
|
2425
2427
|
if (!t) return null;
|
|
2426
2428
|
return { kind: "title", value: t };
|
|
@@ -2825,6 +2827,7 @@ __export(pipeline_exports, {
|
|
|
2825
2827
|
log: () => log,
|
|
2826
2828
|
normalizeDoi: () => normalizeDoi,
|
|
2827
2829
|
previewConflict: () => previewConflict,
|
|
2830
|
+
reidentifyItem: () => reidentifyItem,
|
|
2828
2831
|
resolveItem: () => resolveItem,
|
|
2829
2832
|
retryItem: () => retryItem,
|
|
2830
2833
|
saveItem: () => saveItem,
|
|
@@ -3275,6 +3278,33 @@ async function importDroppedPdf(buffer, { filename = "dropped.pdf" } = {}) {
|
|
|
3275
3278
|
emitItem(saved);
|
|
3276
3279
|
return saved;
|
|
3277
3280
|
}
|
|
3281
|
+
async function reidentifyItem(key) {
|
|
3282
|
+
const item = await getItem(key);
|
|
3283
|
+
if (!item) throw failure("not_found", "\u6761\u76EE\u4E0D\u5B58\u5728");
|
|
3284
|
+
const name2 = item.pdf?.filename ?? item.sourceFile ?? (item.rawValue ? `${item.rawValue}.pdf` : "");
|
|
3285
|
+
const { titleFromFilename: titleFromFilename2 } = await Promise.resolve().then(() => (init_importer(), importer_exports));
|
|
3286
|
+
const hit = titleFromFilename2(name2);
|
|
3287
|
+
if (!hit || hit.kind === "title") {
|
|
3288
|
+
throw failure("network", "\u65E0\u6CD5\u4ECE\u6587\u4EF6\u540D\u8BC6\u522B\u51FA DOI / arXiv \u6807\u8BC6\u7B26\uFF0C\u8BF7\u624B\u52A8\u7C98\u8D34\u6807\u8BC6\u7B26\u540E\u91CD\u8BD5");
|
|
3289
|
+
}
|
|
3290
|
+
let next = await patchItem(key, {
|
|
3291
|
+
kind: hit.kind,
|
|
3292
|
+
rawValue: hit.value,
|
|
3293
|
+
display: hit.value,
|
|
3294
|
+
doi: hit.kind === "doi" ? hit.value : "",
|
|
3295
|
+
arxiv: hit.kind === "arxiv" ? hit.value : "",
|
|
3296
|
+
isbn: "",
|
|
3297
|
+
record: null,
|
|
3298
|
+
error: null
|
|
3299
|
+
});
|
|
3300
|
+
emitItem(next);
|
|
3301
|
+
try {
|
|
3302
|
+
next = await resolveItem(key);
|
|
3303
|
+
} catch {
|
|
3304
|
+
}
|
|
3305
|
+
emitItem(next);
|
|
3306
|
+
return next;
|
|
3307
|
+
}
|
|
3278
3308
|
async function importDroppedCourseware(buffer, { filename = "deck.pptx" } = {}) {
|
|
3279
3309
|
if (!buffer || buffer.length < 4 || buffer.subarray(0, 2).toString("latin1") !== "PK") {
|
|
3280
3310
|
throw failure("network", "\u62D6\u5165\u7684\u6587\u4EF6\u4E0D\u662F\u6709\u6548\u7684 .pptx\uFF08\u65E7\u7248 .ppt \u8BF7\u5148\u53E6\u5B58\u4E3A .pptx \u6216\u5BFC\u51FA PDF\uFF09");
|
|
@@ -36262,7 +36292,7 @@ init_health();
|
|
|
36262
36292
|
init_local_api();
|
|
36263
36293
|
init_connector();
|
|
36264
36294
|
init_log();
|
|
36265
|
-
import { readFile as readFile5 } from "node:fs/promises";
|
|
36295
|
+
import { readFile as readFile5, open as openFile, stat as statFile } from "node:fs/promises";
|
|
36266
36296
|
import { resolve as resolve5 } from "node:path";
|
|
36267
36297
|
var PREFIX2 = "/api/dsh-literature";
|
|
36268
36298
|
function pathOf(req) {
|
|
@@ -36311,30 +36341,44 @@ async function servePdf(req, res, key) {
|
|
|
36311
36341
|
writeJson(res, 400, { error: "invalid key", code: "invalidKey" });
|
|
36312
36342
|
return;
|
|
36313
36343
|
}
|
|
36314
|
-
let
|
|
36344
|
+
let size = 0;
|
|
36315
36345
|
try {
|
|
36316
|
-
|
|
36346
|
+
size = (await statFile(path)).size;
|
|
36317
36347
|
} catch {
|
|
36318
36348
|
writeJson(res, 404, { error: "pdf not downloaded yet", code: "pdfNotDownloaded" });
|
|
36319
36349
|
return;
|
|
36320
36350
|
}
|
|
36321
|
-
const range = parseRange(req.headers.range,
|
|
36351
|
+
const range = parseRange(req.headers.range, size);
|
|
36322
36352
|
if (range?.invalid) {
|
|
36323
|
-
res.writeHead(416, { "content-range": `bytes */${
|
|
36353
|
+
res.writeHead(416, { "content-range": `bytes */${size}`, "content-length": 0 });
|
|
36324
36354
|
res.end();
|
|
36325
36355
|
return;
|
|
36326
36356
|
}
|
|
36327
36357
|
if (range) {
|
|
36328
|
-
const
|
|
36358
|
+
const len = range.end - range.start + 1;
|
|
36359
|
+
const slice = Buffer.alloc(len);
|
|
36360
|
+
const fh = await openFile(path, "r");
|
|
36361
|
+
try {
|
|
36362
|
+
await fh.read(slice, 0, len, range.start);
|
|
36363
|
+
} finally {
|
|
36364
|
+
await fh.close();
|
|
36365
|
+
}
|
|
36329
36366
|
res.writeHead(206, {
|
|
36330
36367
|
"content-type": "application/pdf",
|
|
36331
36368
|
"content-length": slice.length,
|
|
36332
|
-
"content-range": `bytes ${range.start}-${range.end}/${
|
|
36369
|
+
"content-range": `bytes ${range.start}-${range.end}/${size}`,
|
|
36333
36370
|
"accept-ranges": "bytes"
|
|
36334
36371
|
});
|
|
36335
36372
|
res.end(req.method === "HEAD" ? void 0 : slice);
|
|
36336
36373
|
return;
|
|
36337
36374
|
}
|
|
36375
|
+
let buffer;
|
|
36376
|
+
try {
|
|
36377
|
+
buffer = await readFile5(path);
|
|
36378
|
+
} catch {
|
|
36379
|
+
writeJson(res, 404, { error: "pdf not downloaded yet", code: "pdfNotDownloaded" });
|
|
36380
|
+
return;
|
|
36381
|
+
}
|
|
36338
36382
|
res.writeHead(200, {
|
|
36339
36383
|
"content-type": "application/pdf",
|
|
36340
36384
|
"content-length": buffer.length,
|
|
@@ -36406,7 +36450,7 @@ async function readJsonBody2(req) {
|
|
|
36406
36450
|
const { readJsonBody: read } = await Promise.resolve().then(() => (init_http(), http_exports));
|
|
36407
36451
|
return read(req);
|
|
36408
36452
|
}
|
|
36409
|
-
async function handler(req, res, ctx2) {
|
|
36453
|
+
async function handler(req, res, ctx2, { activation } = {}) {
|
|
36410
36454
|
if (!isLoopbackRequest(req)) {
|
|
36411
36455
|
writeJson(res, 403, { error: "forbidden: loopback-only", code: "forbidden" });
|
|
36412
36456
|
return;
|
|
@@ -36485,6 +36529,12 @@ async function handler(req, res, ctx2) {
|
|
|
36485
36529
|
writeJson(res, 200, { item });
|
|
36486
36530
|
return;
|
|
36487
36531
|
}
|
|
36532
|
+
if (head === "reidentify" && methodOk(req, "POST")) {
|
|
36533
|
+
const body = await readJsonBody2(req);
|
|
36534
|
+
const item = await reidentifyItem(String(body?.key ?? ""));
|
|
36535
|
+
writeJson(res, 200, { item });
|
|
36536
|
+
return;
|
|
36537
|
+
}
|
|
36488
36538
|
if (head === "save" && methodOk(req, "POST")) {
|
|
36489
36539
|
const body = await readJsonBody2(req);
|
|
36490
36540
|
const item = await saveItem(String(body?.key ?? ""), { mode: body?.mode, tags: body?.tags });
|
|
@@ -36687,8 +36737,8 @@ async function handler(req, res, ctx2) {
|
|
|
36687
36737
|
else res.end();
|
|
36688
36738
|
}
|
|
36689
36739
|
}
|
|
36690
|
-
function registerRoutes(ctx2, { activation
|
|
36691
|
-
const disposers = [ctx2.webServer.register({ kind: "prefix", path: PREFIX2, handler: (req, res) => handler(req, res, ctx2) })];
|
|
36740
|
+
function registerRoutes(ctx2, { activation } = {}) {
|
|
36741
|
+
const disposers = [ctx2.webServer.register({ kind: "prefix", path: PREFIX2, handler: (req, res) => handler(req, res, ctx2, { activation }) })];
|
|
36692
36742
|
if (typeof ctx2.on === "function") {
|
|
36693
36743
|
disposers.push(
|
|
36694
36744
|
ctx2.on("session/event", (session) => {
|
|
@@ -37307,14 +37357,14 @@ function textFromSessionEvent(event) {
|
|
|
37307
37357
|
}
|
|
37308
37358
|
return "";
|
|
37309
37359
|
}
|
|
37310
|
-
function registerSessionHook(ctx2, { activation
|
|
37360
|
+
function registerSessionHook(ctx2, { activation, detectIntent: detectIntent2 } = {}) {
|
|
37311
37361
|
const disposers = [];
|
|
37312
37362
|
disposers.push(
|
|
37313
37363
|
ctx2.on("session/event", (session, event) => {
|
|
37314
37364
|
const text = textFromSessionEvent(event);
|
|
37315
|
-
if (
|
|
37365
|
+
if (activation && detectIntent2 && event?.type === "user/message") {
|
|
37316
37366
|
const verdict = detectIntent2(textFromSessionEvent(event));
|
|
37317
|
-
if (verdict.active)
|
|
37367
|
+
if (verdict.active) activation.activate(verdict.reason);
|
|
37318
37368
|
}
|
|
37319
37369
|
if (!text || text.length < 20) return;
|
|
37320
37370
|
if (!extractIdentifiers(text).length) return;
|
|
@@ -37508,12 +37558,12 @@ function apply(ctx2, config) {
|
|
|
37508
37558
|
const ready = (async () => {
|
|
37509
37559
|
await ensureDirs();
|
|
37510
37560
|
await init();
|
|
37511
|
-
const
|
|
37512
|
-
|
|
37561
|
+
const activation = createActivation();
|
|
37562
|
+
activation.activate("always-on");
|
|
37513
37563
|
const toolsCtl = registerTools(ctx2);
|
|
37514
37564
|
toolsCtl.mount();
|
|
37515
|
-
disposers.push(
|
|
37516
|
-
disposers.push(() =>
|
|
37565
|
+
disposers.push(activation.onTransition(({ active }) => active ? toolsCtl.mount() : toolsCtl.unmount()));
|
|
37566
|
+
disposers.push(() => activation.dispose());
|
|
37517
37567
|
try {
|
|
37518
37568
|
disposers.push(
|
|
37519
37569
|
ctx2.systemPrompt.section({
|
|
@@ -37533,9 +37583,9 @@ function apply(ctx2, config) {
|
|
|
37533
37583
|
} catch (e) {
|
|
37534
37584
|
error("systemPrompt unavailable:", e.message);
|
|
37535
37585
|
}
|
|
37536
|
-
disposers.push(...registerRoutes(ctx2, { activation
|
|
37586
|
+
disposers.push(...registerRoutes(ctx2, { activation }));
|
|
37537
37587
|
try {
|
|
37538
|
-
disposers.push(...registerSessionHook(ctx2, { activation
|
|
37588
|
+
disposers.push(...registerSessionHook(ctx2, { activation, detectIntent }));
|
|
37539
37589
|
} catch (e) {
|
|
37540
37590
|
error("session hook unavailable:", e.message);
|
|
37541
37591
|
}
|
package/package.json
CHANGED