paper-manager 0.10.4 → 0.11.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.
- package/README.md +9 -9
- package/dist/commands/knowledge-base.js +11 -8
- package/dist/commands/literature.js +17 -12
- package/dist/commands/output.js +25 -0
- package/dist/commands/util.js +4 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -55,10 +55,10 @@ paper config list [--user] # List all config
|
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
paper kb create <name> -d <desc> [-e <model-id>] [--user] # Create a knowledge base
|
|
58
|
-
paper kb list [--all | --user]
|
|
59
|
-
paper kb update <id> [-n <name>] [-d <desc>]
|
|
60
|
-
paper kb remove <id>
|
|
61
|
-
paper kb query <id> <query-text>
|
|
58
|
+
paper kb list [--all | --user] [--json] [--jq <expr>] # List knowledge bases
|
|
59
|
+
paper kb update <id> [-n <name>] [-d <desc>] # Update knowledge base metadata
|
|
60
|
+
paper kb remove <id> # Remove a knowledge base
|
|
61
|
+
paper kb query <id> <query-text> [--json] [--jq <expr>] # Query a knowledge base
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
### Literature (`paper lit`)
|
|
@@ -67,10 +67,10 @@ paper kb query <id> <query-text> # Query a knowledge base
|
|
|
67
67
|
paper lit add <kb-id> <file-path> # Add a literature (auto-extracts PDF metadata)
|
|
68
68
|
paper lit remove <kb-id> <id> # Remove a literature
|
|
69
69
|
paper lit update <kb-id> <id> [opts] # Update literature metadata
|
|
70
|
-
paper lit list <kb-id>
|
|
71
|
-
paper lit search <kb-id> [opts]
|
|
72
|
-
paper lit show <kb-id> <id>
|
|
73
|
-
paper lit note list <lit-id>
|
|
70
|
+
paper lit list <kb-id> [--json] [--jq <expr>] # List literatures
|
|
71
|
+
paper lit search <kb-id> [opts] [--json] [--jq <expr>] # Search literatures by metadata
|
|
72
|
+
paper lit show <kb-id> <id> [--json] [--jq <expr>] # Show literature details
|
|
73
|
+
paper lit note list <lit-id> [--json] [--jq <expr>] # List notes
|
|
74
74
|
paper lit note set <lit-id> <k> <v> # Set a note
|
|
75
75
|
paper lit note remove <lit-id> <key> # Remove a note
|
|
76
76
|
```
|
|
@@ -79,7 +79,7 @@ paper lit note remove <lit-id> <key> # Remove a note
|
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
81
|
paper util doi2bib <doi> # Convert a DOI to BibTeX citation
|
|
82
|
-
paper util pdf-meta <file> [--json] # Extract metadata from a PDF file
|
|
82
|
+
paper util pdf-meta <file> [--json] [--jq <expr>] # Extract metadata from a PDF file
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
## Configuration
|
|
@@ -9,6 +9,7 @@ import * as userLit from "../db/user/literatures.js";
|
|
|
9
9
|
import { removeImageDir } from "../extractor/markdown.js";
|
|
10
10
|
import { log } from "../logger.js";
|
|
11
11
|
import { queryVectorStore } from "../vector-store/index.js";
|
|
12
|
+
import { outputJson } from "./output.js";
|
|
12
13
|
function resolveKnowledgeBase(id) {
|
|
13
14
|
const pkb = projectKb.getKnowledgeBase(id);
|
|
14
15
|
if (pkb)
|
|
@@ -59,6 +60,7 @@ export function createKnowledgeBaseCommand() {
|
|
|
59
60
|
.option("--user", "List user knowledge bases only")
|
|
60
61
|
.option("--all", "List all knowledge bases (default)")
|
|
61
62
|
.option("--json", "Output as JSON")
|
|
63
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
62
64
|
.action((options) => {
|
|
63
65
|
let results = [];
|
|
64
66
|
if (options.user) {
|
|
@@ -70,16 +72,16 @@ export function createKnowledgeBaseCommand() {
|
|
|
70
72
|
results = [...projectKbs, ...userKbs];
|
|
71
73
|
}
|
|
72
74
|
if (results.length === 0) {
|
|
73
|
-
if (options.json) {
|
|
74
|
-
|
|
75
|
+
if (options.json || options.jq) {
|
|
76
|
+
outputJson([], options.jq);
|
|
75
77
|
}
|
|
76
78
|
else {
|
|
77
79
|
log.info("No knowledge bases found.");
|
|
78
80
|
}
|
|
79
81
|
return;
|
|
80
82
|
}
|
|
81
|
-
if (options.json) {
|
|
82
|
-
|
|
83
|
+
if (options.json || options.jq) {
|
|
84
|
+
outputJson(results, options.jq);
|
|
83
85
|
return;
|
|
84
86
|
}
|
|
85
87
|
for (const kb of results) {
|
|
@@ -164,6 +166,7 @@ export function createKnowledgeBaseCommand() {
|
|
|
164
166
|
.description("Query a knowledge base")
|
|
165
167
|
.option("-k, --top-k <number>", "Number of results", "5")
|
|
166
168
|
.option("--json", "Output as JSON")
|
|
169
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
167
170
|
.action(async (id, queryText, options) => {
|
|
168
171
|
const resolved = resolveKnowledgeBase(id);
|
|
169
172
|
if (!resolved) {
|
|
@@ -181,19 +184,19 @@ export function createKnowledgeBaseCommand() {
|
|
|
181
184
|
const k = parseInt(options.topK, 10);
|
|
182
185
|
const results = await queryVectorStore(modelConfig, vectorDir, queryText, k);
|
|
183
186
|
if (results.length === 0) {
|
|
184
|
-
if (options.json) {
|
|
185
|
-
|
|
187
|
+
if (options.json || options.jq) {
|
|
188
|
+
outputJson([], options.jq);
|
|
186
189
|
}
|
|
187
190
|
else {
|
|
188
191
|
log.info("No results found.");
|
|
189
192
|
}
|
|
190
193
|
return;
|
|
191
194
|
}
|
|
192
|
-
if (options.json) {
|
|
195
|
+
if (options.json || options.jq) {
|
|
193
196
|
const output = results
|
|
194
197
|
.filter((doc) => doc != null)
|
|
195
198
|
.map((doc) => ({ pageContent: doc.pageContent, metadata: doc.metadata }));
|
|
196
|
-
|
|
199
|
+
outputJson(output, options.jq);
|
|
197
200
|
return;
|
|
198
201
|
}
|
|
199
202
|
for (let i = 0; i < results.length; i++) {
|
|
@@ -13,6 +13,7 @@ import { convertPdfToMarkdown, isOpendataLoaderAvailable, removeImageDir, saveCo
|
|
|
13
13
|
import { log } from "../logger.js";
|
|
14
14
|
import { splitDocuments } from "../text-splitter.js";
|
|
15
15
|
import { addDocuments, createVectorStore } from "../vector-store/index.js";
|
|
16
|
+
import { outputJson } from "./output.js";
|
|
16
17
|
function resolveKnowledgeBase(id) {
|
|
17
18
|
const pkb = projectKb.getKnowledgeBase(id);
|
|
18
19
|
if (pkb)
|
|
@@ -249,6 +250,7 @@ export function createLiteratureCommand() {
|
|
|
249
250
|
.command("list <knowledge-base-id>")
|
|
250
251
|
.description("List literatures in a knowledge base")
|
|
251
252
|
.option("--json", "Output as JSON")
|
|
253
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
252
254
|
.action((kbId, options) => {
|
|
253
255
|
const resolved = resolveKnowledgeBase(kbId);
|
|
254
256
|
if (!resolved) {
|
|
@@ -258,16 +260,16 @@ export function createLiteratureCommand() {
|
|
|
258
260
|
const litOps = getLitOps(resolved.scope);
|
|
259
261
|
const literatures = litOps.listLiteratures(kbId);
|
|
260
262
|
if (literatures.length === 0) {
|
|
261
|
-
if (options.json) {
|
|
262
|
-
|
|
263
|
+
if (options.json || options.jq) {
|
|
264
|
+
outputJson([], options.jq);
|
|
263
265
|
}
|
|
264
266
|
else {
|
|
265
267
|
log.info("No literatures found.");
|
|
266
268
|
}
|
|
267
269
|
return;
|
|
268
270
|
}
|
|
269
|
-
if (options.json) {
|
|
270
|
-
|
|
271
|
+
if (options.json || options.jq) {
|
|
272
|
+
outputJson(literatures, options.jq);
|
|
271
273
|
return;
|
|
272
274
|
}
|
|
273
275
|
const filesDir = getFilesDir(getBaseDir(resolved.scope));
|
|
@@ -292,6 +294,7 @@ export function createLiteratureCommand() {
|
|
|
292
294
|
.option("-k, --keyword <keyword>", "Keyword substring")
|
|
293
295
|
.option("--doi <doi>", "DOI substring")
|
|
294
296
|
.option("--json", "Output as JSON")
|
|
297
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
295
298
|
.action((kbId, options) => {
|
|
296
299
|
const resolved = resolveKnowledgeBase(kbId);
|
|
297
300
|
if (!resolved) {
|
|
@@ -313,16 +316,16 @@ export function createLiteratureCommand() {
|
|
|
313
316
|
doi: options.doi,
|
|
314
317
|
});
|
|
315
318
|
if (results.length === 0) {
|
|
316
|
-
if (options.json) {
|
|
317
|
-
|
|
319
|
+
if (options.json || options.jq) {
|
|
320
|
+
outputJson([], options.jq);
|
|
318
321
|
}
|
|
319
322
|
else {
|
|
320
323
|
log.info("No literatures found.");
|
|
321
324
|
}
|
|
322
325
|
return;
|
|
323
326
|
}
|
|
324
|
-
if (options.json) {
|
|
325
|
-
|
|
327
|
+
if (options.json || options.jq) {
|
|
328
|
+
outputJson(results, options.jq);
|
|
326
329
|
return;
|
|
327
330
|
}
|
|
328
331
|
for (const l of results) {
|
|
@@ -344,6 +347,7 @@ export function createLiteratureCommand() {
|
|
|
344
347
|
.command("show <knowledge-base-id> <id>")
|
|
345
348
|
.description("Show literature details")
|
|
346
349
|
.option("--json", "Output as JSON")
|
|
350
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
347
351
|
.action((kbId, id, options) => {
|
|
348
352
|
const resolved = resolveKnowledgeBase(kbId);
|
|
349
353
|
if (!resolved) {
|
|
@@ -356,8 +360,8 @@ export function createLiteratureCommand() {
|
|
|
356
360
|
log.error(`Literature not found: ${id}`);
|
|
357
361
|
process.exit(1);
|
|
358
362
|
}
|
|
359
|
-
if (options.json) {
|
|
360
|
-
|
|
363
|
+
if (options.json || options.jq) {
|
|
364
|
+
outputJson(literature, options.jq);
|
|
361
365
|
return;
|
|
362
366
|
}
|
|
363
367
|
const filesDir = getFilesDir(getBaseDir(resolved.scope));
|
|
@@ -369,14 +373,15 @@ export function createLiteratureCommand() {
|
|
|
369
373
|
.command("list <literature-id>")
|
|
370
374
|
.description("List all notes for a literature")
|
|
371
375
|
.option("--json", "Output as JSON")
|
|
376
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
372
377
|
.action((litId, options) => {
|
|
373
378
|
const literature = findLiterature(litId);
|
|
374
379
|
if (!literature) {
|
|
375
380
|
log.error(`Literature not found: ${litId}`);
|
|
376
381
|
process.exit(1);
|
|
377
382
|
}
|
|
378
|
-
if (options.json) {
|
|
379
|
-
|
|
383
|
+
if (options.json || options.jq) {
|
|
384
|
+
outputJson(literature.notes, options.jq);
|
|
380
385
|
return;
|
|
381
386
|
}
|
|
382
387
|
const entries = Object.entries(literature.notes);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jq } from "@eurfelux/jq-js";
|
|
2
|
+
import { log } from "../logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Output data as JSON, optionally filtered by a jq expression.
|
|
5
|
+
* When `jqExpr` is provided, applies the jq filter and prints each result value.
|
|
6
|
+
* Otherwise prints pretty-printed JSON.
|
|
7
|
+
*/
|
|
8
|
+
export function outputJson(data, jqExpr) {
|
|
9
|
+
const jsonStr = JSON.stringify(data, null, 2);
|
|
10
|
+
if (jqExpr) {
|
|
11
|
+
const normalized = JSON.parse(jsonStr);
|
|
12
|
+
const results = jq(jqExpr, normalized);
|
|
13
|
+
for (const result of results) {
|
|
14
|
+
if (typeof result === "string") {
|
|
15
|
+
log.plain(result);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
log.plain(JSON.stringify(result, null, 2));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
log.plain(jsonStr);
|
|
24
|
+
}
|
|
25
|
+
}
|
package/dist/commands/util.js
CHANGED
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import { extractPdfMetadata } from "../extractor/pdf.js";
|
|
5
5
|
import { log } from "../logger.js";
|
|
6
|
+
import { outputJson } from "./output.js";
|
|
6
7
|
export function createUtilCommand() {
|
|
7
8
|
const util = new Command("util").description("Utility commands");
|
|
8
9
|
util
|
|
@@ -26,6 +27,7 @@ export function createUtilCommand() {
|
|
|
26
27
|
.command("pdf-meta <file>")
|
|
27
28
|
.description("Extract metadata from a PDF file")
|
|
28
29
|
.option("--json", "Output as JSON")
|
|
30
|
+
.option("--jq <expression>", "Filter JSON output with a jq expression (implies --json)")
|
|
29
31
|
.action(async (file, options) => {
|
|
30
32
|
const absolutePath = path.resolve(file);
|
|
31
33
|
if (!existsSync(absolutePath)) {
|
|
@@ -44,8 +46,8 @@ export function createUtilCommand() {
|
|
|
44
46
|
log.error(`Failed to parse PDF: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
47
|
process.exit(1);
|
|
46
48
|
}
|
|
47
|
-
if (options.json) {
|
|
48
|
-
|
|
49
|
+
if (options.json || options.jq) {
|
|
50
|
+
outputJson(meta, options.jq);
|
|
49
51
|
return;
|
|
50
52
|
}
|
|
51
53
|
log.header("PDF Metadata");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paper-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "A paper management system.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/EurFelux/paper-manager",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@ai-sdk/openai": "^3.0.37",
|
|
23
23
|
"@ai-sdk/provider": "^3.0.8",
|
|
24
|
+
"@eurfelux/jq-js": "^0.3.0",
|
|
24
25
|
"ai": "^6.0.105",
|
|
25
26
|
"better-sqlite3": "^12.6.2",
|
|
26
27
|
"chalk": "^5.6.2",
|