gnosys 4.4.6 → 5.0.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 +12 -7
- package/dist/cli.js +140 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/attachments.d.ts +43 -0
- package/dist/lib/attachments.d.ts.map +1 -0
- package/dist/lib/attachments.js +154 -0
- package/dist/lib/attachments.js.map +1 -0
- package/dist/lib/audioExtract.d.ts +39 -0
- package/dist/lib/audioExtract.d.ts.map +1 -0
- package/dist/lib/audioExtract.js +220 -0
- package/dist/lib/audioExtract.js.map +1 -0
- package/dist/lib/chunkSplitter.d.ts +46 -0
- package/dist/lib/chunkSplitter.d.ts.map +1 -0
- package/dist/lib/chunkSplitter.js +233 -0
- package/dist/lib/chunkSplitter.js.map +1 -0
- package/dist/lib/config.d.ts +70 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +62 -6
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/db.d.ts +7 -1
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +31 -4
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/dbWrite.d.ts.map +1 -1
- package/dist/lib/dbWrite.js +11 -0
- package/dist/lib/dbWrite.js.map +1 -1
- package/dist/lib/docxExtract.d.ts +27 -0
- package/dist/lib/docxExtract.d.ts.map +1 -0
- package/dist/lib/docxExtract.js +80 -0
- package/dist/lib/docxExtract.js.map +1 -0
- package/dist/lib/fileDetect.d.ts +20 -0
- package/dist/lib/fileDetect.d.ts.map +1 -0
- package/dist/lib/fileDetect.js +124 -0
- package/dist/lib/fileDetect.js.map +1 -0
- package/dist/lib/imageExtract.d.ts +26 -0
- package/dist/lib/imageExtract.d.ts.map +1 -0
- package/dist/lib/imageExtract.js +113 -0
- package/dist/lib/imageExtract.js.map +1 -0
- package/dist/lib/llm.d.ts +9 -0
- package/dist/lib/llm.d.ts.map +1 -1
- package/dist/lib/llm.js +102 -0
- package/dist/lib/llm.js.map +1 -1
- package/dist/lib/multimodalIngest.d.ts +68 -0
- package/dist/lib/multimodalIngest.d.ts.map +1 -0
- package/dist/lib/multimodalIngest.js +463 -0
- package/dist/lib/multimodalIngest.js.map +1 -0
- package/dist/lib/pdfExtract.d.ts +29 -0
- package/dist/lib/pdfExtract.d.ts.map +1 -0
- package/dist/lib/pdfExtract.js +163 -0
- package/dist/lib/pdfExtract.js.map +1 -0
- package/dist/lib/setup.d.ts +9 -0
- package/dist/lib/setup.d.ts.map +1 -1
- package/dist/lib/setup.js +241 -16
- package/dist/lib/setup.js.map +1 -1
- package/dist/lib/store.d.ts +3 -0
- package/dist/lib/store.d.ts.map +1 -1
- package/dist/lib/store.js.map +1 -1
- package/dist/lib/videoExtract.d.ts +30 -0
- package/dist/lib/videoExtract.d.ts.map +1 -0
- package/dist/lib/videoExtract.js +92 -0
- package/dist/lib/videoExtract.js.map +1 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -274,7 +274,7 @@ type = "local"
|
|
|
274
274
|
command = ["gnosys", "serve"]
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
-
> **Note:** API keys are configured
|
|
277
|
+
> **Note:** API keys are configured via `gnosys setup` (macOS Keychain, environment variable, or `~/.config/gnosys/.env`). See [LLM Provider Setup](https://gnosys.ai/guide.html#guide-llm-provider-setup) in the User Guide.
|
|
278
278
|
|
|
279
279
|
---
|
|
280
280
|
|
|
@@ -345,14 +345,18 @@ Eight providers behind a single interface — switch between cloud and local wit
|
|
|
345
345
|
|
|
346
346
|
| Provider | Type | Default Model | API Key Env Var |
|
|
347
347
|
|----------|------|---------------|-----------------|
|
|
348
|
-
| **Anthropic** | Cloud | claude-sonnet-4-6 | `
|
|
348
|
+
| **Anthropic** | Cloud | claude-sonnet-4-6 | `GNOSYS_ANTHROPIC_KEY` |
|
|
349
349
|
| **Ollama** | Local | llama3.2 | — (runs locally) |
|
|
350
|
-
| **Groq** | Cloud | llama-3.3-70b-versatile | `
|
|
351
|
-
| **OpenAI** | Cloud | gpt-5.4-mini | `
|
|
350
|
+
| **Groq** | Cloud | llama-3.3-70b-versatile | `GNOSYS_GROQ_KEY` |
|
|
351
|
+
| **OpenAI** | Cloud | gpt-5.4-mini | `GNOSYS_OPENAI_KEY` |
|
|
352
352
|
| **LM Studio** | Local | default | — (runs locally) |
|
|
353
|
-
| **xAI** | Cloud | grok-4.20 | `
|
|
354
|
-
| **Mistral** | Cloud | mistral-small-4 | `
|
|
355
|
-
| **Custom** | Any | (user-defined) | `
|
|
353
|
+
| **xAI** | Cloud | grok-4.20 | `GNOSYS_XAI_KEY` |
|
|
354
|
+
| **Mistral** | Cloud | mistral-small-4 | `GNOSYS_MISTRAL_KEY` |
|
|
355
|
+
| **Custom** | Any | (user-defined) | `GNOSYS_CUSTOM_KEY` |
|
|
356
|
+
|
|
357
|
+
> Model lists and pricing are fetched dynamically from [OpenRouter](https://openrouter.ai) during `gnosys setup` and cached for 24 hours. Bundled defaults are used when offline.
|
|
358
|
+
|
|
359
|
+
> **API Key Security:** `gnosys setup` offers three storage options: macOS Keychain (recommended — encrypted, no plaintext), environment variable (shell profile), or `~/.config/gnosys/.env` (least secure). Legacy env var names (`ANTHROPIC_API_KEY`, `GROQ_API_KEY`, `OPENAI_API_KEY`, etc.) are still supported for backward compatibility.
|
|
356
360
|
|
|
357
361
|
Route tasks to different providers — a cheap model for structuring, a powerful model for synthesis:
|
|
358
362
|
|
|
@@ -561,6 +565,7 @@ Gnosys is open source (MIT) and actively developed. Here's how to get involved:
|
|
|
561
565
|
- Graph visualization in the dashboard
|
|
562
566
|
- Obsidian community plugin for native vault integration
|
|
563
567
|
- Docker Hub published image for one-line deployment
|
|
568
|
+
- Multimodal memory ingestion (PDFs, images, audio/video transcription)
|
|
564
569
|
|
|
565
570
|
---
|
|
566
571
|
|
package/dist/cli.js
CHANGED
|
@@ -350,6 +350,36 @@ program
|
|
|
350
350
|
console.error("No writable store found. Create a .gnosys/ directory or set GNOSYS_PERSONAL.");
|
|
351
351
|
process.exit(1);
|
|
352
352
|
}
|
|
353
|
+
// Check if input is a file path — if so, route through multimodal ingestion
|
|
354
|
+
if (existsSync(input)) {
|
|
355
|
+
const { ingestFile } = await import("./lib/multimodalIngest.js");
|
|
356
|
+
const storePath = writeTarget.store.getStorePath();
|
|
357
|
+
console.log(`Detected file: ${input}`);
|
|
358
|
+
console.log("Ingesting via multimodal pipeline...");
|
|
359
|
+
const result = await ingestFile({
|
|
360
|
+
filePath: path.resolve(input),
|
|
361
|
+
storePath,
|
|
362
|
+
mode: "llm",
|
|
363
|
+
author: opts.author,
|
|
364
|
+
authority: opts.authority,
|
|
365
|
+
onProgress: (p) => {
|
|
366
|
+
console.log(` [${p.current}/${p.total}] ${p.title || "Processing..."}`);
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
console.log(`\nFile type: ${result.fileType}`);
|
|
370
|
+
console.log(`Memories created: ${result.memories.length}`);
|
|
371
|
+
console.log(`Duration: ${(result.duration / 1000).toFixed(1)}s`);
|
|
372
|
+
for (const mem of result.memories) {
|
|
373
|
+
console.log(` ${mem.id}: ${mem.title}`);
|
|
374
|
+
}
|
|
375
|
+
if (result.errors.length > 0) {
|
|
376
|
+
console.error(`\nErrors (${result.errors.length}):`);
|
|
377
|
+
for (const err of result.errors) {
|
|
378
|
+
console.error(` Chunk ${err.chunk}: ${err.error}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
353
383
|
const tagRegistry = new GnosysTagRegistry(writeTarget.store.getStorePath());
|
|
354
384
|
await tagRegistry.load();
|
|
355
385
|
const ingestion = new GnosysIngestion(writeTarget.store, tagRegistry);
|
|
@@ -439,6 +469,12 @@ program
|
|
|
439
469
|
await fs.writeFile(path.join(storePath, ".config", "tags.json"), JSON.stringify(defaultRegistry, null, 2), "utf-8");
|
|
440
470
|
// Write default gnosys.json config (LLM settings)
|
|
441
471
|
await fs.writeFile(path.join(storePath, ".config", "gnosys-config.json"), generateConfigTemplate() + "\n", "utf-8");
|
|
472
|
+
// v5.0: Create attachments directory and empty manifest
|
|
473
|
+
await fs.mkdir(path.join(storePath, "attachments"), { recursive: true });
|
|
474
|
+
await fs.writeFile(path.join(storePath, "attachments", "attachments.json"), JSON.stringify({ attachments: [] }, null, 2) + "\n", "utf-8");
|
|
475
|
+
// Create .gitignore inside .gnosys to exclude large binary attachments
|
|
476
|
+
const storeGitignore = "# Large binary attachments (tracked via manifest, not git)\nattachments/\n";
|
|
477
|
+
await fs.writeFile(path.join(storePath, ".gitignore"), storeGitignore, "utf-8");
|
|
442
478
|
const changelog = `# Gnosys Changelog\n\n## ${new Date().toISOString().split("T")[0]}\n\n- Store initialized\n`;
|
|
443
479
|
await fs.writeFile(path.join(storePath, "CHANGELOG.md"), changelog, "utf-8");
|
|
444
480
|
try {
|
|
@@ -793,6 +829,110 @@ program
|
|
|
793
829
|
console.log(`Memory added to [${writeTarget.label}]: ${opts.title}`);
|
|
794
830
|
console.log(`Path: ${writeTarget.label}:${relPath}`);
|
|
795
831
|
});
|
|
832
|
+
// ─── gnosys ingest <file> ─────────────────────────────────────────────────
|
|
833
|
+
program
|
|
834
|
+
.command("ingest <fileOrGlob>")
|
|
835
|
+
.description("Ingest a file (PDF, DOCX, TXT, MD) into Gnosys memory. Extracts text, splits into chunks, and creates atomic memories.")
|
|
836
|
+
.option("--mode <mode>", "Ingestion mode: llm or structured", "llm")
|
|
837
|
+
.option("-s, --store <store>", "Target store: project, personal, global")
|
|
838
|
+
.option("-a, --author <author>", "Author", "human")
|
|
839
|
+
.option("--authority <authority>", "Authority level", "imported")
|
|
840
|
+
.option("--dry-run", "Preview what would be created without writing")
|
|
841
|
+
.option("--list-attachments", "List all stored attachments")
|
|
842
|
+
.option("-d, --directory <dir>", "Project directory")
|
|
843
|
+
.action(async (fileOrGlob, opts) => {
|
|
844
|
+
// List attachments mode
|
|
845
|
+
if (opts.listAttachments) {
|
|
846
|
+
const { listAttachments } = await import("./lib/attachments.js");
|
|
847
|
+
const resolver = await getResolver();
|
|
848
|
+
const writeTarget = resolver.getWriteTarget(opts.store || undefined);
|
|
849
|
+
if (!writeTarget) {
|
|
850
|
+
console.error("No writable store found.");
|
|
851
|
+
process.exit(1);
|
|
852
|
+
}
|
|
853
|
+
const attachments = await listAttachments(writeTarget.store.getStorePath());
|
|
854
|
+
if (attachments.length === 0) {
|
|
855
|
+
console.log("No attachments found.");
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
console.log(`Found ${attachments.length} attachment(s):\n`);
|
|
859
|
+
for (const a of attachments) {
|
|
860
|
+
const sizeMb = (a.sizeBytes / (1024 * 1024)).toFixed(2);
|
|
861
|
+
console.log(` ${a.originalName} (${sizeMb}MB, ${a.extension})`);
|
|
862
|
+
console.log(` UUID: ${a.uuid}`);
|
|
863
|
+
console.log(` Hash: ${a.contentHash.slice(0, 16)}...`);
|
|
864
|
+
console.log(` Memories: ${a.memoryIds.length > 0 ? a.memoryIds.join(", ") : "none"}`);
|
|
865
|
+
console.log(` Created: ${a.createdAt}\n`);
|
|
866
|
+
}
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
// Resolve the file path
|
|
870
|
+
const resolvedPath = path.resolve(opts.directory || process.cwd(), fileOrGlob);
|
|
871
|
+
// Check the file exists
|
|
872
|
+
try {
|
|
873
|
+
await fs.access(resolvedPath);
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
console.error(`File not found: ${resolvedPath}`);
|
|
877
|
+
process.exit(1);
|
|
878
|
+
}
|
|
879
|
+
// Resolve the store
|
|
880
|
+
const resolver = await getResolver();
|
|
881
|
+
const writeTarget = resolver.getWriteTarget(opts.store || undefined);
|
|
882
|
+
if (!writeTarget) {
|
|
883
|
+
console.error("No writable store found. Create a .gnosys/ directory or set GNOSYS_PERSONAL.");
|
|
884
|
+
process.exit(1);
|
|
885
|
+
}
|
|
886
|
+
const storePath = writeTarget.store.getStorePath();
|
|
887
|
+
// Run ingestion
|
|
888
|
+
const { ingestFile } = await import("./lib/multimodalIngest.js");
|
|
889
|
+
console.log(`Ingesting: ${path.basename(resolvedPath)}`);
|
|
890
|
+
if (opts.dryRun) {
|
|
891
|
+
console.log("(dry run — no files will be written)\n");
|
|
892
|
+
}
|
|
893
|
+
try {
|
|
894
|
+
const result = await ingestFile({
|
|
895
|
+
filePath: resolvedPath,
|
|
896
|
+
storePath,
|
|
897
|
+
mode: opts.mode,
|
|
898
|
+
store: opts.store || undefined,
|
|
899
|
+
author: opts.author,
|
|
900
|
+
authority: opts.authority,
|
|
901
|
+
dryRun: opts.dryRun,
|
|
902
|
+
projectRoot: opts.directory,
|
|
903
|
+
onProgress: (p) => {
|
|
904
|
+
process.stdout.write(`\r Processing chunk ${p.current}/${p.total}...`);
|
|
905
|
+
},
|
|
906
|
+
});
|
|
907
|
+
// Clear the progress line
|
|
908
|
+
if (result.memories.length > 0) {
|
|
909
|
+
process.stdout.write("\r" + " ".repeat(60) + "\r");
|
|
910
|
+
}
|
|
911
|
+
// Print results
|
|
912
|
+
console.log(`\nFile type: ${result.fileType}`);
|
|
913
|
+
console.log(`Attachment: ${result.attachment.originalName} (${result.attachment.uuid.slice(0, 8)}...)`);
|
|
914
|
+
console.log(`Duration: ${(result.duration / 1000).toFixed(1)}s`);
|
|
915
|
+
console.log(`Memories created: ${result.memories.length}`);
|
|
916
|
+
if (result.memories.length > 0) {
|
|
917
|
+
console.log("\nMemories:");
|
|
918
|
+
for (const m of result.memories) {
|
|
919
|
+
const extra = m.page ? ` [page ${m.page}]` : "";
|
|
920
|
+
console.log(` ${m.id}: ${m.title}${extra}`);
|
|
921
|
+
console.log(` Path: ${m.path}`);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
if (result.errors.length > 0) {
|
|
925
|
+
console.log(`\nErrors (${result.errors.length}):`);
|
|
926
|
+
for (const e of result.errors) {
|
|
927
|
+
console.log(` Chunk ${e.chunk}: ${e.error}`);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
catch (err) {
|
|
932
|
+
console.error(`\nIngestion failed: ${err instanceof Error ? err.message : err}`);
|
|
933
|
+
process.exit(1);
|
|
934
|
+
}
|
|
935
|
+
});
|
|
796
936
|
// ─── gnosys tags-add ────────────────────────────────────────────────────
|
|
797
937
|
program
|
|
798
938
|
.command("tags-add")
|