paper-manager 0.1.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/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/ai/embed.d.ts +3 -0
- package/dist/ai/embed.js +13 -0
- package/dist/ai/embed.js.map +1 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/provider.d.ts +3 -0
- package/dist/ai/provider.js +9 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +57 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/knowledge-base.d.ts +2 -0
- package/dist/commands/knowledge-base.js +152 -0
- package/dist/commands/knowledge-base.js.map +1 -0
- package/dist/commands/literature.d.ts +2 -0
- package/dist/commands/literature.js +302 -0
- package/dist/commands/literature.js.map +1 -0
- package/dist/config/index.d.ts +38 -0
- package/dist/config/index.js +107 -0
- package/dist/config/index.js.map +1 -0
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.js +76 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/operations/knowledge-bases.d.ts +10 -0
- package/dist/db/operations/knowledge-bases.js +25 -0
- package/dist/db/operations/knowledge-bases.js.map +1 -0
- package/dist/db/operations/literatures.d.ts +9 -0
- package/dist/db/operations/literatures.js +87 -0
- package/dist/db/operations/literatures.js.map +1 -0
- package/dist/db/project/knowledge-bases.d.ts +9 -0
- package/dist/db/project/knowledge-bases.js +15 -0
- package/dist/db/project/knowledge-bases.js.map +1 -0
- package/dist/db/project/literatures.d.ts +8 -0
- package/dist/db/project/literatures.js +24 -0
- package/dist/db/project/literatures.js.map +1 -0
- package/dist/db/schema.d.ts +2 -0
- package/dist/db/schema.js +26 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/user/knowledge-bases.d.ts +9 -0
- package/dist/db/user/knowledge-bases.js +15 -0
- package/dist/db/user/knowledge-bases.js.map +1 -0
- package/dist/db/user/literatures.d.ts +8 -0
- package/dist/db/user/literatures.js +24 -0
- package/dist/db/user/literatures.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/pdf/extractor.d.ts +2 -0
- package/dist/pdf/extractor.js +6 -0
- package/dist/pdf/extractor.js.map +1 -0
- package/dist/types/index.d.ts +74 -0
- package/dist/types/index.js +45 -0
- package/dist/types/index.js.map +1 -0
- package/dist/vector-store/embeddings.d.ts +8 -0
- package/dist/vector-store/embeddings.js +16 -0
- package/dist/vector-store/embeddings.js.map +1 -0
- package/dist/vector-store/index.d.ts +6 -0
- package/dist/vector-store/index.js +17 -0
- package/dist/vector-store/index.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Phantom
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# my-ts-starter
|
|
2
|
+
|
|
3
|
+
A minimal TypeScript project template with modern tooling powered by the [oxc](https://oxc.rs/) ecosystem.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **TypeScript** — Type-safe development with `tsc`
|
|
8
|
+
- **oxlint** — Fast linter with type-aware rules (via `oxlint-tsgolint`)
|
|
9
|
+
- **oxfmt** — Fast formatter
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install dependencies
|
|
15
|
+
pnpm install
|
|
16
|
+
|
|
17
|
+
# Type check
|
|
18
|
+
pnpm typecheck
|
|
19
|
+
|
|
20
|
+
# Lint
|
|
21
|
+
pnpm lint
|
|
22
|
+
|
|
23
|
+
# Format
|
|
24
|
+
pnpm fmt
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Available Scripts
|
|
28
|
+
|
|
29
|
+
| Script | Description |
|
|
30
|
+
| ---------------- | -------------------------------- |
|
|
31
|
+
| `pnpm typecheck` | Run TypeScript type checking |
|
|
32
|
+
| `pnpm lint` | Lint with oxlint (type-aware) |
|
|
33
|
+
| `pnpm lint:fix` | Lint and auto-fix |
|
|
34
|
+
| `pnpm fmt` | Format with oxfmt |
|
|
35
|
+
| `pnpm fmt:check` | Check formatting without writing |
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
[MIT](LICENSE)
|
package/dist/ai/embed.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { embed as aiEmbed, embedMany as aiEmbedMany } from "ai";
|
|
2
|
+
import { createEmbeddingModel } from "./provider.js";
|
|
3
|
+
export async function embed(config, text) {
|
|
4
|
+
const model = createEmbeddingModel(config);
|
|
5
|
+
const result = await aiEmbed({ model, value: text });
|
|
6
|
+
return result.embedding;
|
|
7
|
+
}
|
|
8
|
+
export async function embedMany(config, texts) {
|
|
9
|
+
const model = createEmbeddingModel(config);
|
|
10
|
+
const result = await aiEmbedMany({ model, values: texts });
|
|
11
|
+
return result.embeddings;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=embed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed.js","sourceRoot":"","sources":["../../src/ai/embed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,IAAI,CAAC;AAGhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,MAA4B,EAAE,IAAY;IACpE,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC,SAAS,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAA4B,EAC5B,KAAe;IAEf,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,OAAO,MAAM,CAAC,UAAU,CAAC;AAC3B,CAAC"}
|
package/dist/ai/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
2
|
+
export function createEmbeddingModel(config) {
|
|
3
|
+
const openai = createOpenAI({
|
|
4
|
+
apiKey: config.apiKey,
|
|
5
|
+
baseURL: config.baseUrl,
|
|
6
|
+
});
|
|
7
|
+
return openai.embedding(config.model);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAK9C,MAAM,UAAU,oBAAoB,CAAC,MAA4B;IAC/D,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { listConfig, loadMergedConfig, removeConfig, setConfig } from "../config/index.js";
|
|
3
|
+
export function createConfigCommand() {
|
|
4
|
+
const config = new Command("config").description("Manage configuration");
|
|
5
|
+
config
|
|
6
|
+
.command("get <key>")
|
|
7
|
+
.description("Get a config value")
|
|
8
|
+
.option("--user", "Read from user config")
|
|
9
|
+
.action((key, options) => {
|
|
10
|
+
const source = options.user ? listConfig({ user: true }) : loadMergedConfig();
|
|
11
|
+
const value = source[key];
|
|
12
|
+
if (value === undefined) {
|
|
13
|
+
console.log(`Config "${key}" is not set.`);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
console.log(JSON.stringify(value, null, 2));
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
config
|
|
20
|
+
.command("set <key> <value>")
|
|
21
|
+
.description("Set a config value")
|
|
22
|
+
.option("--user", "Write to user config")
|
|
23
|
+
.action((key, rawValue, options) => {
|
|
24
|
+
let value;
|
|
25
|
+
try {
|
|
26
|
+
value = JSON.parse(rawValue);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
value = rawValue;
|
|
30
|
+
}
|
|
31
|
+
setConfig(key, value, { user: options.user });
|
|
32
|
+
console.log(`Config "${key}" has been set.`);
|
|
33
|
+
});
|
|
34
|
+
config
|
|
35
|
+
.command("remove <key>")
|
|
36
|
+
.description("Remove a config key")
|
|
37
|
+
.option("--user", "Remove from user config")
|
|
38
|
+
.action((key, options) => {
|
|
39
|
+
removeConfig(key, { user: options.user });
|
|
40
|
+
console.log(`Config "${key}" has been removed.`);
|
|
41
|
+
});
|
|
42
|
+
config
|
|
43
|
+
.command("list")
|
|
44
|
+
.description("List all config")
|
|
45
|
+
.option("--user", "List user config only")
|
|
46
|
+
.action((options) => {
|
|
47
|
+
const result = options.user ? listConfig({ user: true }) : loadMergedConfig();
|
|
48
|
+
if (Object.keys(result).length === 0) {
|
|
49
|
+
console.log("No config set.");
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.log(JSON.stringify(result, null, 2));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return config;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { getConfig, getModelConfig, getPdfDir, getProjectDataDir, getUserDataDir, getVectorStoreDir, } from "../config/index.js";
|
|
5
|
+
import * as projectKb from "../db/project/knowledge-bases.js";
|
|
6
|
+
import * as projectLit from "../db/project/literatures.js";
|
|
7
|
+
import * as userKb from "../db/user/knowledge-bases.js";
|
|
8
|
+
import * as userLit from "../db/user/literatures.js";
|
|
9
|
+
import { queryVectorStore } from "../vector-store/index.js";
|
|
10
|
+
function resolveKnowledgeBase(id) {
|
|
11
|
+
const pkb = projectKb.getKnowledgeBase(id);
|
|
12
|
+
if (pkb)
|
|
13
|
+
return { kb: pkb, scope: "project" };
|
|
14
|
+
const ukb = userKb.getKnowledgeBase(id);
|
|
15
|
+
if (ukb)
|
|
16
|
+
return { kb: ukb, scope: "user" };
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
function getBaseDir(scope) {
|
|
20
|
+
return scope === "project" ? getProjectDataDir() : getUserDataDir();
|
|
21
|
+
}
|
|
22
|
+
export function createKnowledgeBaseCommand() {
|
|
23
|
+
const kb = new Command("kb").description("Manage knowledge bases");
|
|
24
|
+
kb.command("create <name>")
|
|
25
|
+
.description("Create a knowledge base")
|
|
26
|
+
.requiredOption("-d, --description <desc>", "Knowledge base description")
|
|
27
|
+
.option("-e, --embedding-model <id>", "Embedding model config ID")
|
|
28
|
+
.option("--user", "Create in user scope")
|
|
29
|
+
.action((name, options) => {
|
|
30
|
+
let embeddingModelId = options.embeddingModel;
|
|
31
|
+
if (!embeddingModelId) {
|
|
32
|
+
const defaultId = getConfig("defaultEmbeddingModelId");
|
|
33
|
+
if (!defaultId) {
|
|
34
|
+
console.error("Error: No embedding model specified and no default configured.");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
embeddingModelId = defaultId;
|
|
38
|
+
}
|
|
39
|
+
// Validate model config exists
|
|
40
|
+
const models = getConfig("embeddingModels");
|
|
41
|
+
if (!models?.[embeddingModelId]) {
|
|
42
|
+
console.error(`Error: Embedding model "${embeddingModelId}" not found in config.`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const create = options.user ? userKb.createKnowledgeBase : projectKb.createKnowledgeBase;
|
|
46
|
+
const result = create({
|
|
47
|
+
name,
|
|
48
|
+
description: options.description,
|
|
49
|
+
embeddingModelId,
|
|
50
|
+
});
|
|
51
|
+
console.log(`Knowledge base created: ${result.id}`);
|
|
52
|
+
console.log(` Name: ${result.name}`);
|
|
53
|
+
console.log(` Scope: ${options.user ? "user" : "project"}`);
|
|
54
|
+
});
|
|
55
|
+
kb.command("list")
|
|
56
|
+
.description("List knowledge bases")
|
|
57
|
+
.option("--user", "List user knowledge bases only")
|
|
58
|
+
.option("--all", "List all knowledge bases (default)")
|
|
59
|
+
.action((options) => {
|
|
60
|
+
let results = [];
|
|
61
|
+
if (options.user) {
|
|
62
|
+
results = userKb.listKnowledgeBases().map((k) => ({ ...k, scope: "user" }));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const projectKbs = projectKb.listKnowledgeBases().map((k) => ({ ...k, scope: "project" }));
|
|
66
|
+
const userKbs = userKb.listKnowledgeBases().map((k) => ({ ...k, scope: "user" }));
|
|
67
|
+
results = [...projectKbs, ...userKbs];
|
|
68
|
+
}
|
|
69
|
+
if (results.length === 0) {
|
|
70
|
+
console.log("No knowledge bases found.");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
for (const kb of results) {
|
|
74
|
+
console.log(`[${kb.scope}] ${kb.id}`);
|
|
75
|
+
console.log(` Name: ${kb.name}`);
|
|
76
|
+
console.log(` Description: ${kb.description}`);
|
|
77
|
+
console.log(` Model: ${kb.embeddingModelId}`);
|
|
78
|
+
console.log(` Created: ${kb.createdAt.toISOString()}`);
|
|
79
|
+
console.log();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
kb.command("remove <id>")
|
|
83
|
+
.description("Remove a knowledge base and all its data")
|
|
84
|
+
.action((id) => {
|
|
85
|
+
const resolved = resolveKnowledgeBase(id);
|
|
86
|
+
if (!resolved) {
|
|
87
|
+
console.error(`Knowledge base not found: ${id}`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
const { scope } = resolved;
|
|
91
|
+
const baseDir = getBaseDir(scope);
|
|
92
|
+
const litOps = scope === "project" ? projectLit : userLit;
|
|
93
|
+
const kbOps = scope === "project" ? projectKb : userKb;
|
|
94
|
+
// 1. Get all literatures in this KB
|
|
95
|
+
const literatures = litOps.getLiteraturesByKnowledgeBaseId(id);
|
|
96
|
+
// 2. Delete PDF files
|
|
97
|
+
const pdfDir = getPdfDir(baseDir);
|
|
98
|
+
for (const lit of literatures) {
|
|
99
|
+
const pdfPath = path.join(pdfDir, `${lit.id}.pdf`);
|
|
100
|
+
if (fs.existsSync(pdfPath)) {
|
|
101
|
+
fs.unlinkSync(pdfPath);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// 3. Delete literatures from DB
|
|
105
|
+
litOps.deleteLiteraturesByKnowledgeBaseId(id);
|
|
106
|
+
// 4. Delete vector store directory
|
|
107
|
+
const vectorDir = path.join(getVectorStoreDir(baseDir), id);
|
|
108
|
+
if (fs.existsSync(vectorDir)) {
|
|
109
|
+
fs.rmSync(vectorDir, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
// 5. Delete knowledge base
|
|
112
|
+
kbOps.deleteKnowledgeBase(id);
|
|
113
|
+
console.log(`Knowledge base "${id}" and all associated data removed.`);
|
|
114
|
+
});
|
|
115
|
+
kb.command("query <id> <query-text>")
|
|
116
|
+
.description("Query a knowledge base")
|
|
117
|
+
.option("-k, --top-k <number>", "Number of results", "5")
|
|
118
|
+
.action(async (id, queryText, options) => {
|
|
119
|
+
const resolved = resolveKnowledgeBase(id);
|
|
120
|
+
if (!resolved) {
|
|
121
|
+
console.error(`Knowledge base not found: ${id}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
const { kb: kbMeta, scope } = resolved;
|
|
125
|
+
const baseDir = getBaseDir(scope);
|
|
126
|
+
const vectorDir = path.join(getVectorStoreDir(baseDir), id);
|
|
127
|
+
if (!fs.existsSync(vectorDir)) {
|
|
128
|
+
console.error("No vector store found for this knowledge base.");
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
const modelConfig = getModelConfig(kbMeta.embeddingModelId);
|
|
132
|
+
const k = parseInt(options.topK, 10);
|
|
133
|
+
const results = await queryVectorStore(modelConfig, vectorDir, queryText, k);
|
|
134
|
+
if (results.length === 0) {
|
|
135
|
+
console.log("No results found.");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
for (let i = 0; i < results.length; i++) {
|
|
139
|
+
const doc = results[i];
|
|
140
|
+
if (!doc)
|
|
141
|
+
continue;
|
|
142
|
+
console.log(`--- Result ${String(i + 1)} ---`);
|
|
143
|
+
console.log(doc.pageContent);
|
|
144
|
+
if (doc.metadata && Object.keys(doc.metadata).length > 0) {
|
|
145
|
+
console.log(` Metadata: ${JSON.stringify(doc.metadata)}`);
|
|
146
|
+
}
|
|
147
|
+
console.log();
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return kb;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=knowledge-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge-base.js","sourceRoot":"","sources":["../../src/commands/knowledge-base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { RecursiveCharacterTextSplitter } from "@langchain/textsplitters";
|
|
4
|
+
import cliProgress from "cli-progress";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { getModelConfig, getPdfDir, getProjectDataDir, getUserDataDir, getVectorStoreDir, } from "../config/index.js";
|
|
7
|
+
import * as projectKb from "../db/project/knowledge-bases.js";
|
|
8
|
+
import * as projectLit from "../db/project/literatures.js";
|
|
9
|
+
import * as userKb from "../db/user/knowledge-bases.js";
|
|
10
|
+
import * as userLit from "../db/user/literatures.js";
|
|
11
|
+
import { extractPdfContent } from "../pdf/extractor.js";
|
|
12
|
+
import { createVectorStore, loadVectorStore } from "../vector-store/index.js";
|
|
13
|
+
function resolveKnowledgeBase(id) {
|
|
14
|
+
const pkb = projectKb.getKnowledgeBase(id);
|
|
15
|
+
if (pkb)
|
|
16
|
+
return { kb: pkb, scope: "project" };
|
|
17
|
+
const ukb = userKb.getKnowledgeBase(id);
|
|
18
|
+
if (ukb)
|
|
19
|
+
return { kb: ukb, scope: "user" };
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function getBaseDir(scope) {
|
|
23
|
+
return scope === "project" ? getProjectDataDir() : getUserDataDir();
|
|
24
|
+
}
|
|
25
|
+
function getLitOps(scope) {
|
|
26
|
+
return scope === "project" ? projectLit : userLit;
|
|
27
|
+
}
|
|
28
|
+
export function createLiteratureCommand() {
|
|
29
|
+
const lit = new Command("lit").description("Manage literatures");
|
|
30
|
+
// ─── lit add ───────────────────────────────────────────────
|
|
31
|
+
lit
|
|
32
|
+
.command("add <knowledge-base-id> <pdf-path>")
|
|
33
|
+
.description("Add a literature from a PDF file")
|
|
34
|
+
.option("-t, --title <title>", "Literature title")
|
|
35
|
+
.action(async (kbId, pdfPath, options) => {
|
|
36
|
+
const resolved = resolveKnowledgeBase(kbId);
|
|
37
|
+
if (!resolved) {
|
|
38
|
+
console.error(`Knowledge base not found: ${kbId}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
const { kb, scope } = resolved;
|
|
42
|
+
const baseDir = getBaseDir(scope);
|
|
43
|
+
const litOps = getLitOps(scope);
|
|
44
|
+
// Resolve PDF path
|
|
45
|
+
const absolutePdfPath = path.resolve(pdfPath);
|
|
46
|
+
if (!fs.existsSync(absolutePdfPath)) {
|
|
47
|
+
console.error(`PDF file not found: ${absolutePdfPath}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
const title = options.title ?? path.basename(pdfPath, path.extname(pdfPath));
|
|
51
|
+
console.log(`Extracting PDF content...`);
|
|
52
|
+
const docs = await extractPdfContent(absolutePdfPath);
|
|
53
|
+
console.log(` Extracted ${String(docs.length)} pages.`);
|
|
54
|
+
// Create literature record
|
|
55
|
+
const literature = litOps.createLiterature({
|
|
56
|
+
title,
|
|
57
|
+
titleTranslation: null,
|
|
58
|
+
author: null,
|
|
59
|
+
abstract: null,
|
|
60
|
+
summary: null,
|
|
61
|
+
keywords: [],
|
|
62
|
+
url: null,
|
|
63
|
+
notes: {},
|
|
64
|
+
knowledgeBaseId: kbId,
|
|
65
|
+
});
|
|
66
|
+
// Copy PDF to storage
|
|
67
|
+
const pdfDir = getPdfDir(baseDir);
|
|
68
|
+
fs.mkdirSync(pdfDir, { recursive: true });
|
|
69
|
+
fs.copyFileSync(absolutePdfPath, path.join(pdfDir, `${literature.id}.pdf`));
|
|
70
|
+
// Split text and add to vector store
|
|
71
|
+
console.log(`Splitting text...`);
|
|
72
|
+
const splitter = new RecursiveCharacterTextSplitter({
|
|
73
|
+
chunkSize: 1000,
|
|
74
|
+
chunkOverlap: 200,
|
|
75
|
+
});
|
|
76
|
+
const splitDocs = await splitter.splitDocuments(docs);
|
|
77
|
+
console.log(` Created ${String(splitDocs.length)} chunks.`);
|
|
78
|
+
// Add literature ID metadata to each chunk
|
|
79
|
+
for (const doc of splitDocs) {
|
|
80
|
+
doc.metadata = { ...doc.metadata, literatureId: literature.id };
|
|
81
|
+
}
|
|
82
|
+
const vectorDir = path.join(getVectorStoreDir(baseDir), kbId);
|
|
83
|
+
const modelConfig = getModelConfig(kb.embeddingModelId);
|
|
84
|
+
console.log(`Embedding and storing vectors...`);
|
|
85
|
+
const bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
|
|
86
|
+
bar.start(splitDocs.length, 0);
|
|
87
|
+
// Check if vector store already exists
|
|
88
|
+
if (fs.existsSync(vectorDir)) {
|
|
89
|
+
const store = await loadVectorStore(modelConfig, vectorDir);
|
|
90
|
+
await store.addDocuments(splitDocs);
|
|
91
|
+
await store.save(vectorDir);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
fs.mkdirSync(vectorDir, { recursive: true });
|
|
95
|
+
await createVectorStore(splitDocs, modelConfig, vectorDir);
|
|
96
|
+
}
|
|
97
|
+
bar.update(splitDocs.length);
|
|
98
|
+
bar.stop();
|
|
99
|
+
console.log(`Literature added: ${literature.id}`);
|
|
100
|
+
console.log(` Title: ${literature.title}`);
|
|
101
|
+
});
|
|
102
|
+
// ─── lit remove ────────────────────────────────────────────
|
|
103
|
+
lit
|
|
104
|
+
.command("remove <knowledge-base-id> <id>")
|
|
105
|
+
.description("Remove a literature")
|
|
106
|
+
.action((kbId, id) => {
|
|
107
|
+
const resolved = resolveKnowledgeBase(kbId);
|
|
108
|
+
if (!resolved) {
|
|
109
|
+
console.error(`Knowledge base not found: ${kbId}`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
const { scope } = resolved;
|
|
113
|
+
const baseDir = getBaseDir(scope);
|
|
114
|
+
const litOps = getLitOps(scope);
|
|
115
|
+
const literature = litOps.getLiterature(id);
|
|
116
|
+
if (!literature) {
|
|
117
|
+
console.error(`Literature not found: ${id}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
// Delete PDF
|
|
121
|
+
const pdfPath = path.join(getPdfDir(baseDir), `${id}.pdf`);
|
|
122
|
+
if (fs.existsSync(pdfPath)) {
|
|
123
|
+
fs.unlinkSync(pdfPath);
|
|
124
|
+
}
|
|
125
|
+
// Delete literature record
|
|
126
|
+
litOps.deleteLiterature(id);
|
|
127
|
+
console.log(`Literature "${id}" removed.`);
|
|
128
|
+
});
|
|
129
|
+
// ─── lit update ────────────────────────────────────────────
|
|
130
|
+
lit
|
|
131
|
+
.command("update <knowledge-base-id> <id>")
|
|
132
|
+
.description("Update a literature")
|
|
133
|
+
.option("-t, --title <title>", "Title")
|
|
134
|
+
.option("--title-translation <translation>", "Title translation")
|
|
135
|
+
.option("-a, --author <author>", "Author")
|
|
136
|
+
.option("--abstract <abstract>", "Abstract")
|
|
137
|
+
.option("--summary <summary>", "Summary")
|
|
138
|
+
.option("--url <url>", "URL")
|
|
139
|
+
.option("--keywords <keywords>", "Keywords (comma-separated)")
|
|
140
|
+
.action((kbId, id, options) => {
|
|
141
|
+
const resolved = resolveKnowledgeBase(kbId);
|
|
142
|
+
if (!resolved) {
|
|
143
|
+
console.error(`Knowledge base not found: ${kbId}`);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
const litOps = getLitOps(resolved.scope);
|
|
147
|
+
const input = {};
|
|
148
|
+
if (options.title !== undefined)
|
|
149
|
+
input["title"] = options.title;
|
|
150
|
+
if (options.titleTranslation !== undefined)
|
|
151
|
+
input["titleTranslation"] = options.titleTranslation;
|
|
152
|
+
if (options.author !== undefined)
|
|
153
|
+
input["author"] = options.author;
|
|
154
|
+
if (options.abstract !== undefined)
|
|
155
|
+
input["abstract"] = options.abstract;
|
|
156
|
+
if (options.summary !== undefined)
|
|
157
|
+
input["summary"] = options.summary;
|
|
158
|
+
if (options.url !== undefined)
|
|
159
|
+
input["url"] = options.url;
|
|
160
|
+
if (options.keywords !== undefined)
|
|
161
|
+
input["keywords"] = options.keywords.split(",").map((k) => k.trim());
|
|
162
|
+
const updated = litOps.updateLiterature(id, input);
|
|
163
|
+
if (!updated) {
|
|
164
|
+
console.error(`Literature not found: ${id}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
console.log(`Literature "${id}" updated.`);
|
|
168
|
+
});
|
|
169
|
+
// ─── lit list ──────────────────────────────────────────────
|
|
170
|
+
lit
|
|
171
|
+
.command("list <knowledge-base-id>")
|
|
172
|
+
.description("List literatures in a knowledge base")
|
|
173
|
+
.action((kbId) => {
|
|
174
|
+
const resolved = resolveKnowledgeBase(kbId);
|
|
175
|
+
if (!resolved) {
|
|
176
|
+
console.error(`Knowledge base not found: ${kbId}`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
const litOps = getLitOps(resolved.scope);
|
|
180
|
+
const literatures = litOps.listLiteratures(kbId);
|
|
181
|
+
if (literatures.length === 0) {
|
|
182
|
+
console.log("No literatures found.");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
for (const l of literatures) {
|
|
186
|
+
console.log(`${l.id}`);
|
|
187
|
+
console.log(` Title: ${l.title}`);
|
|
188
|
+
if (l.author)
|
|
189
|
+
console.log(` Author: ${l.author}`);
|
|
190
|
+
console.log(` Created: ${l.createdAt.toISOString()}`);
|
|
191
|
+
console.log();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
// ─── lit show ──────────────────────────────────────────────
|
|
195
|
+
lit
|
|
196
|
+
.command("show <knowledge-base-id> <id>")
|
|
197
|
+
.description("Show literature details")
|
|
198
|
+
.action((kbId, id) => {
|
|
199
|
+
const resolved = resolveKnowledgeBase(kbId);
|
|
200
|
+
if (!resolved) {
|
|
201
|
+
console.error(`Knowledge base not found: ${kbId}`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const litOps = getLitOps(resolved.scope);
|
|
205
|
+
const literature = litOps.getLiterature(id);
|
|
206
|
+
if (!literature) {
|
|
207
|
+
console.error(`Literature not found: ${id}`);
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
printLiterature(literature);
|
|
211
|
+
});
|
|
212
|
+
// ─── lit note ──────────────────────────────────────────────
|
|
213
|
+
const note = lit.command("note").description("Manage literature notes");
|
|
214
|
+
note
|
|
215
|
+
.command("list <literature-id>")
|
|
216
|
+
.description("List all notes for a literature")
|
|
217
|
+
.action((litId) => {
|
|
218
|
+
const literature = findLiterature(litId);
|
|
219
|
+
if (!literature) {
|
|
220
|
+
console.error(`Literature not found: ${litId}`);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
const entries = Object.entries(literature.notes);
|
|
224
|
+
if (entries.length === 0) {
|
|
225
|
+
console.log("No notes found.");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
for (const [key, value] of entries) {
|
|
229
|
+
console.log(`${key}: ${value}`);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
note
|
|
233
|
+
.command("set <literature-id> <key> <value>")
|
|
234
|
+
.description("Set a note on a literature")
|
|
235
|
+
.action((litId, key, value) => {
|
|
236
|
+
const found = findLiteratureWithScope(litId);
|
|
237
|
+
if (!found) {
|
|
238
|
+
console.error(`Literature not found: ${litId}`);
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
const litOps = getLitOps(found.scope);
|
|
242
|
+
const newNotes = { ...found.literature.notes, [key]: value };
|
|
243
|
+
litOps.updateLiterature(litId, { notes: newNotes });
|
|
244
|
+
console.log(`Note "${key}" set on literature "${litId}".`);
|
|
245
|
+
});
|
|
246
|
+
note
|
|
247
|
+
.command("remove <literature-id> <key>")
|
|
248
|
+
.description("Remove a note from a literature")
|
|
249
|
+
.action((litId, key) => {
|
|
250
|
+
const found = findLiteratureWithScope(litId);
|
|
251
|
+
if (!found) {
|
|
252
|
+
console.error(`Literature not found: ${litId}`);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
const litOps = getLitOps(found.scope);
|
|
256
|
+
const newNotes = { ...found.literature.notes };
|
|
257
|
+
delete newNotes[key];
|
|
258
|
+
litOps.updateLiterature(litId, { notes: newNotes });
|
|
259
|
+
console.log(`Note "${key}" removed from literature "${litId}".`);
|
|
260
|
+
});
|
|
261
|
+
return lit;
|
|
262
|
+
}
|
|
263
|
+
// ─── Helpers ────────────────────────────────────────────────
|
|
264
|
+
function findLiterature(id) {
|
|
265
|
+
return projectLit.getLiterature(id) ?? userLit.getLiterature(id);
|
|
266
|
+
}
|
|
267
|
+
function findLiteratureWithScope(id) {
|
|
268
|
+
const pLit = projectLit.getLiterature(id);
|
|
269
|
+
if (pLit)
|
|
270
|
+
return { literature: pLit, scope: "project" };
|
|
271
|
+
const uLit = userLit.getLiterature(id);
|
|
272
|
+
if (uLit)
|
|
273
|
+
return { literature: uLit, scope: "user" };
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
function printLiterature(lit) {
|
|
277
|
+
console.log(`ID: ${lit.id}`);
|
|
278
|
+
console.log(`Title: ${lit.title}`);
|
|
279
|
+
if (lit.titleTranslation)
|
|
280
|
+
console.log(`Title (translated): ${lit.titleTranslation}`);
|
|
281
|
+
if (lit.author)
|
|
282
|
+
console.log(`Author: ${lit.author}`);
|
|
283
|
+
if (lit.abstract)
|
|
284
|
+
console.log(`Abstract: ${lit.abstract}`);
|
|
285
|
+
if (lit.summary)
|
|
286
|
+
console.log(`Summary: ${lit.summary}`);
|
|
287
|
+
if (lit.keywords.length > 0)
|
|
288
|
+
console.log(`Keywords: ${lit.keywords.join(", ")}`);
|
|
289
|
+
if (lit.url)
|
|
290
|
+
console.log(`URL: ${lit.url}`);
|
|
291
|
+
console.log(`Knowledge Base: ${lit.knowledgeBaseId}`);
|
|
292
|
+
console.log(`Created: ${lit.createdAt.toISOString()}`);
|
|
293
|
+
console.log(`Updated: ${lit.updatedAt.toISOString()}`);
|
|
294
|
+
const noteEntries = Object.entries(lit.notes);
|
|
295
|
+
if (noteEntries.length > 0) {
|
|
296
|
+
console.log(`Notes:`);
|
|
297
|
+
for (const [key, value] of noteEntries) {
|
|
298
|
+
console.log(` ${key}: ${value}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=literature.js.map
|