gnosys 5.4.3 → 5.6.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 +52 -8
- package/dist/cli.js +246 -27
- package/dist/cli.js.map +1 -1
- package/dist/lib/audioExtract.d.ts +1 -1
- package/dist/lib/audioExtract.js +6 -6
- package/dist/lib/audioExtract.js.map +1 -1
- package/dist/lib/chat/choose.d.ts +75 -0
- package/dist/lib/chat/choose.d.ts.map +1 -0
- package/dist/lib/chat/choose.js +146 -0
- package/dist/lib/chat/choose.js.map +1 -0
- package/dist/lib/chat/commands.d.ts +96 -0
- package/dist/lib/chat/commands.d.ts.map +1 -0
- package/dist/lib/chat/commands.js +367 -0
- package/dist/lib/chat/commands.js.map +1 -0
- package/dist/lib/chat/focus.d.ts +70 -0
- package/dist/lib/chat/focus.d.ts.map +1 -0
- package/dist/lib/chat/focus.js +120 -0
- package/dist/lib/chat/focus.js.map +1 -0
- package/dist/lib/chat/index.d.ts +32 -0
- package/dist/lib/chat/index.d.ts.map +1 -0
- package/dist/lib/chat/index.js +151 -0
- package/dist/lib/chat/index.js.map +1 -0
- package/dist/lib/chat/intent.d.ts +100 -0
- package/dist/lib/chat/intent.d.ts.map +1 -0
- package/dist/lib/chat/intent.js +192 -0
- package/dist/lib/chat/intent.js.map +1 -0
- package/dist/lib/chat/llmTurn.d.ts +37 -0
- package/dist/lib/chat/llmTurn.d.ts.map +1 -0
- package/dist/lib/chat/llmTurn.js +61 -0
- package/dist/lib/chat/llmTurn.js.map +1 -0
- package/dist/lib/chat/recall.d.ts +58 -0
- package/dist/lib/chat/recall.d.ts.map +1 -0
- package/dist/lib/chat/recall.js +109 -0
- package/dist/lib/chat/recall.js.map +1 -0
- package/dist/lib/chat/render.d.ts +30 -0
- package/dist/lib/chat/render.d.ts.map +1 -0
- package/dist/lib/chat/render.js +737 -0
- package/dist/lib/chat/render.js.map +1 -0
- package/dist/lib/chat/session.d.ts +121 -0
- package/dist/lib/chat/session.d.ts.map +1 -0
- package/dist/lib/chat/session.js +148 -0
- package/dist/lib/chat/session.js.map +1 -0
- package/dist/lib/chat/types.d.ts +42 -0
- package/dist/lib/chat/types.d.ts.map +1 -0
- package/dist/lib/chat/types.js +6 -0
- package/dist/lib/chat/types.js.map +1 -0
- package/dist/lib/chat/write.d.ts +66 -0
- package/dist/lib/chat/write.d.ts.map +1 -0
- package/dist/lib/chat/write.js +203 -0
- package/dist/lib/chat/write.js.map +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +6 -2
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/db.d.ts +3 -1
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +18 -2
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/embeddings.d.ts +1 -1
- package/dist/lib/embeddings.d.ts.map +1 -1
- package/dist/lib/embeddings.js +9 -4
- package/dist/lib/embeddings.js.map +1 -1
- package/dist/lib/exportProject.d.ts +51 -0
- package/dist/lib/exportProject.d.ts.map +1 -0
- package/dist/lib/exportProject.js +72 -0
- package/dist/lib/exportProject.js.map +1 -0
- package/dist/lib/importProject.d.ts +35 -0
- package/dist/lib/importProject.d.ts.map +1 -0
- package/dist/lib/importProject.js +135 -0
- package/dist/lib/importProject.js.map +1 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Gnosys takes a different approach: the central brain is a single SQLite database
|
|
|
52
52
|
- **Reflection API** — `gnosys.reflect(outcome)` updates confidence and consolidates memories based on real-world outcomes.
|
|
53
53
|
- **Bulk import** — CSV, JSON, JSONL. Import entire datasets in seconds.
|
|
54
54
|
- **Obsidian-native** — `gnosys export` generates a full vault with YAML frontmatter, `[[wikilinks]]`, summaries, and graph data.
|
|
55
|
-
- **Multi-machine sync
|
|
55
|
+
- **Multi-machine sync** — share your `gnosys.db` across machines via NAS or shared drive. Remote NAS is the canonical source of truth; local DB is an offline-resilience cache. Built-in conflict detection with skip-and-flag resolution. Run `gnosys setup remote` to set up.
|
|
56
56
|
- **MCP-compatible** — also runs as a full MCP server that drops into Cursor, Claude Desktop (Chat / Cowork / Code), Claude Code, Codex, Gemini CLI, Antigravity, or any MCP client.
|
|
57
57
|
- **Zero infrastructure** — no external databases, no Docker (unless you want it), no cloud services. Just `npm install`.
|
|
58
58
|
|
|
@@ -96,6 +96,50 @@ The helper auto-starts the sandbox if it's not running. No MCP required.
|
|
|
96
96
|
|
|
97
97
|
---
|
|
98
98
|
|
|
99
|
+
## Interactive Chat (TUI)
|
|
100
|
+
|
|
101
|
+
`gnosys chat` opens a memory-aware terminal chat. Every prompt triggers federated recall against the central brain; the LLM sees relevant memories in context and cites them in its answers.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
gnosys chat # new session
|
|
105
|
+
gnosys chat --resume <id> # continue an earlier session
|
|
106
|
+
gnosys chat --list # see all sessions
|
|
107
|
+
gnosys chat --search <query> # full-text search across session logs
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Free-text or slash commands.** "remember that flag default is OFF" works the same as `/remember flag default is OFF`. The TUI also recognizes "what did we decide about ULIDs?" → `/recall`, "thanks, that's all" → `/quit`. Destructive intents always confirm; non-destructive ones auto-accept after 5 confirmations of the same pattern.
|
|
111
|
+
|
|
112
|
+
**24 slash commands** across reading, recall, writing, focus, and polish — type `/help` inside the TUI for the full list. Highlights:
|
|
113
|
+
|
|
114
|
+
- `/pin <id>`, `/scope`, `/threshold`, `/recall <q>` — tune what shows up in context
|
|
115
|
+
- `/remember <text>`, `/save-turn`, `/attach <file>` — promote chat content to gnosys memory (PDFs, images, audio all auto-pin to the session)
|
|
116
|
+
- `/focus <topic>`, `/branch`, `/resume-focus` — replace the "new chat" model with cheap focus boundaries; one continuous session log, instant pivot
|
|
117
|
+
- `/export <file.md>`, `/search-chats <q>`, `/dream-here` — round-trip the session, find old chats, or trigger a focused dream cycle
|
|
118
|
+
|
|
119
|
+
**Multiple choice.** When the model needs you to pick from a small set, it emits a fenced `gnosys-choose` block. The TUI parses it and shows an arrow-key selectable list — provider-agnostic, no tool-use API required.
|
|
120
|
+
|
|
121
|
+
Sessions live as append-only JSONL at `~/.gnosys/chat-sessions/`; promoted memories carry `session:<id>`, `from-chat:true`, and `source:remember|save-turn|auto|attach` provenance tags so you can find them later via federated search.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Per-Project Bundles
|
|
126
|
+
|
|
127
|
+
Move a single project's memories between machines without dragging the whole central DB.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
gnosys export project --to ./gnosys-public.json.gz # auto-detects current project
|
|
131
|
+
gnosys export project <projectId> --to <bundle> # explicit
|
|
132
|
+
gnosys import project <bundle> --strategy merge # default — skip existing
|
|
133
|
+
gnosys import project <bundle> --strategy replace # wipe target project first
|
|
134
|
+
gnosys import project <bundle> --strategy new-id # remap to a fresh project ID
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Bundles are gzipped JSON containing the project row, memories (with embeddings inline), relationships, and audit log. Lossless round-trip with the same DB schema; partially compatible across versions via the bundle manifest.
|
|
138
|
+
|
|
139
|
+
For an Obsidian-compatible markdown vault, use `gnosys export vault --to <dir>` (the v5.5.x form `gnosys export --to <dir>` keeps working).
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
99
143
|
## Web Knowledge Base
|
|
100
144
|
|
|
101
145
|
Turn any website into a searchable knowledge base for AI chatbots. No database required. Works on Vercel, Netlify, Cloudflare Pages, or any platform that can serve files.
|
|
@@ -461,19 +505,19 @@ All memories live in a single `~/.gnosys/gnosys.db` with `project_id` and `scope
|
|
|
461
505
|
|
|
462
506
|
### Multi-Machine Sync
|
|
463
507
|
|
|
464
|
-
Gnosys
|
|
508
|
+
Gnosys supports running across multiple machines with a shared database on a NAS or network share.
|
|
465
509
|
|
|
466
510
|
**How it works:**
|
|
467
|
-
- Local DB at `~/.gnosys/gnosys.db` is your fast working cache
|
|
468
511
|
- Remote DB on a network share (e.g. `/Volumes/nas/gnosys/`) is the canonical source of truth
|
|
469
|
-
-
|
|
470
|
-
-
|
|
471
|
-
-
|
|
512
|
+
- Local DB at `~/.gnosys/gnosys.db` is an offline-resilience cache, not a performance optimization
|
|
513
|
+
- Reads hit remote when reachable; fall back to local cache when remote is offline
|
|
514
|
+
- Writes go to remote first; queue locally and auto-flush when offline
|
|
515
|
+
- Per-memory `modified` timestamps detect conflicts; ULID memory IDs prevent collisions across concurrent writers
|
|
472
516
|
- Skip-and-flag is the safe default; `--newer-wins` for unattended sync
|
|
473
517
|
|
|
474
518
|
**Setup:**
|
|
475
519
|
```bash
|
|
476
|
-
gnosys remote
|
|
520
|
+
gnosys setup remote
|
|
477
521
|
# interactive: validates path, tests SQLite locking, checks latency
|
|
478
522
|
```
|
|
479
523
|
|
|
@@ -616,7 +660,7 @@ All commands support `--json` for programmatic output. See the [User Guide](http
|
|
|
616
660
|
|
|
617
661
|
**Web knowledge base:** `web init`, `web ingest`, `web build-index`, `web build`, `web add`, `web remove`, `web status`
|
|
618
662
|
|
|
619
|
-
**Multi-machine sync:** `remote
|
|
663
|
+
**Multi-machine sync:** `remote status`, `remote sync`, `remote push`, `remote pull`, `remote resolve` (configure via `gnosys setup remote`)
|
|
620
664
|
|
|
621
665
|
**Server:** `serve`, `serve --with-maintenance`
|
|
622
666
|
|
package/dist/cli.js
CHANGED
|
@@ -108,6 +108,32 @@ function maybePrintUpgradeNudge() {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
maybePrintUpgradeNudge();
|
|
111
|
+
/**
|
|
112
|
+
* v5.6.0 back-compat shim: rewrite `gnosys export --to <dir>` →
|
|
113
|
+
* `gnosys export vault --to <dir>` before commander parses argv. The v5.6.0
|
|
114
|
+
* restructure made `export` a parent command with `vault` and `project`
|
|
115
|
+
* subcommands; without this shim, the bare `--to` form prints usage instead
|
|
116
|
+
* of running the vault export.
|
|
117
|
+
*
|
|
118
|
+
* Pattern: argv[2]==="export" AND argv[3] is not a known subcommand AND any
|
|
119
|
+
* of the v5.5.x flags appear (`--to`, `--all`, `--overwrite`, etc.).
|
|
120
|
+
*/
|
|
121
|
+
function rewriteLegacyExport() {
|
|
122
|
+
if (process.argv[2] !== "export")
|
|
123
|
+
return;
|
|
124
|
+
const next = process.argv[3];
|
|
125
|
+
if (next === "vault" || next === "project" || next === "--help" || next === "-h")
|
|
126
|
+
return;
|
|
127
|
+
// Any v5.5.x-style flag → assume legacy vault invocation
|
|
128
|
+
const looksLegacy = process.argv.slice(3).some((a) => a === "--to" || a.startsWith("--to=") ||
|
|
129
|
+
a === "--all" || a === "--overwrite" ||
|
|
130
|
+
a === "--no-summaries" || a === "--no-reviews" || a === "--no-graph" ||
|
|
131
|
+
a === "--json");
|
|
132
|
+
if (looksLegacy) {
|
|
133
|
+
process.argv.splice(3, 0, "vault");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
rewriteLegacyExport();
|
|
111
137
|
async function getResolver() {
|
|
112
138
|
const resolver = new GnosysResolver();
|
|
113
139
|
await resolver.resolve();
|
|
@@ -1218,6 +1244,45 @@ program
|
|
|
1218
1244
|
centralDb?.close();
|
|
1219
1245
|
}
|
|
1220
1246
|
});
|
|
1247
|
+
// ─── gnosys chat (TUI) ───────────────────────────────────────────────────
|
|
1248
|
+
program
|
|
1249
|
+
.command("chat")
|
|
1250
|
+
.description("Interactive memory-aware terminal chat (TUI)")
|
|
1251
|
+
.option("--resume <sessionId>", "Resume an existing chat session")
|
|
1252
|
+
.option("--list", "List recent chat sessions and exit")
|
|
1253
|
+
.option("--search <query>", "Full-text search across session logs")
|
|
1254
|
+
.option("--provider <name>", "Override LLM provider (anthropic, openai, groq, ollama, …)")
|
|
1255
|
+
.option("--model <name>", "Override LLM model name")
|
|
1256
|
+
.option("--limit <n>", "Limit for --list / --search (default 20)", "20")
|
|
1257
|
+
.action(async (opts) => {
|
|
1258
|
+
const limit = parseInt(opts.limit, 10) || 20;
|
|
1259
|
+
const chat = await import("./lib/chat/index.js");
|
|
1260
|
+
if (opts.list) {
|
|
1261
|
+
chat.printSessionList(limit);
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
if (opts.search) {
|
|
1265
|
+
chat.printSearchResults(opts.search, limit);
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
// Interactive chat
|
|
1269
|
+
const resolver = await getResolver();
|
|
1270
|
+
const stores = resolver.getStores();
|
|
1271
|
+
const storePath = stores[0]?.path ?? process.cwd();
|
|
1272
|
+
let cliConfig;
|
|
1273
|
+
try {
|
|
1274
|
+
cliConfig = await loadConfig(storePath);
|
|
1275
|
+
}
|
|
1276
|
+
catch {
|
|
1277
|
+
cliConfig = (await import("./lib/config.js")).DEFAULT_CONFIG;
|
|
1278
|
+
}
|
|
1279
|
+
await chat.startChat({
|
|
1280
|
+
config: cliConfig,
|
|
1281
|
+
resume: opts.resume,
|
|
1282
|
+
providerName: opts.provider,
|
|
1283
|
+
modelName: opts.model,
|
|
1284
|
+
});
|
|
1285
|
+
});
|
|
1221
1286
|
// ─── gnosys ingest <file> ─────────────────────────────────────────────────
|
|
1222
1287
|
program
|
|
1223
1288
|
.command("ingest <fileOrGlob>")
|
|
@@ -1876,12 +1941,13 @@ program
|
|
|
1876
1941
|
}
|
|
1877
1942
|
}
|
|
1878
1943
|
});
|
|
1879
|
-
// ─── gnosys import
|
|
1880
|
-
program
|
|
1881
|
-
.command("import
|
|
1882
|
-
.
|
|
1883
|
-
.
|
|
1884
|
-
.
|
|
1944
|
+
// ─── gnosys import (parent + subcommands) ───────────────────────────────
|
|
1945
|
+
const importCmd = program
|
|
1946
|
+
.command("import [fileOrUrl]")
|
|
1947
|
+
.enablePositionalOptions()
|
|
1948
|
+
.description("Import data into Gnosys (bulk CSV/JSON/JSONL — see also: 'gnosys import project <bundle>')")
|
|
1949
|
+
.option("--format <format>", "Data format: csv, json, jsonl (required for bulk import)")
|
|
1950
|
+
.option("--mapping <json>", 'Field mapping as JSON: \'{"source_field":"gnosys_field"}\'. Valid targets: title, category, content, tags, relevance')
|
|
1885
1951
|
.option("--mode <mode>", "Processing mode: llm or structured", "structured")
|
|
1886
1952
|
.option("--limit <n>", "Max records to import", parseInt)
|
|
1887
1953
|
.option("--offset <n>", "Skip first N records", parseInt)
|
|
@@ -1892,6 +1958,17 @@ program
|
|
|
1892
1958
|
.option("--dry-run", "Preview without writing")
|
|
1893
1959
|
.option("--store <store>", "Target store: project, personal, global", "project")
|
|
1894
1960
|
.action(async (fileOrUrl, opts) => {
|
|
1961
|
+
if (!fileOrUrl) {
|
|
1962
|
+
console.error("Usage:");
|
|
1963
|
+
console.error(" gnosys import <file> --format csv|json|jsonl --mapping '{...}' (bulk)");
|
|
1964
|
+
console.error(" gnosys import project <bundle.json.gz> (project bundle)");
|
|
1965
|
+
process.exit(1);
|
|
1966
|
+
}
|
|
1967
|
+
if (!opts.format || !opts.mapping) {
|
|
1968
|
+
console.error("Error: --format and --mapping are required for bulk imports.");
|
|
1969
|
+
console.error(" For project bundles, use 'gnosys import project <bundle>'.");
|
|
1970
|
+
process.exit(1);
|
|
1971
|
+
}
|
|
1895
1972
|
// Parse mapping JSON
|
|
1896
1973
|
let mapping;
|
|
1897
1974
|
try {
|
|
@@ -1966,6 +2043,51 @@ program
|
|
|
1966
2043
|
process.exit(1);
|
|
1967
2044
|
}
|
|
1968
2045
|
});
|
|
2046
|
+
// `gnosys import project <bundle>` — restore a portable .json.gz bundle
|
|
2047
|
+
importCmd
|
|
2048
|
+
.command("project <bundlePath>")
|
|
2049
|
+
.description("Import a project bundle (.json.gz) created by 'gnosys export project'")
|
|
2050
|
+
.option("--strategy <strategy>", "Conflict handling: merge (default), replace, new-id", "merge")
|
|
2051
|
+
.option("--working-directory <dir>", "Override the bundle's working_directory (e.g. when restoring on a different machine)")
|
|
2052
|
+
.option("--json", "Output the result as JSON")
|
|
2053
|
+
.action(async (bundlePath, opts) => {
|
|
2054
|
+
const validStrategies = ["merge", "replace", "new-id"];
|
|
2055
|
+
if (!validStrategies.includes(opts.strategy)) {
|
|
2056
|
+
console.error(`Invalid strategy: ${opts.strategy}. Use one of: ${validStrategies.join(", ")}`);
|
|
2057
|
+
process.exit(1);
|
|
2058
|
+
}
|
|
2059
|
+
const { GnosysDB: DbClass } = await import("./lib/db.js");
|
|
2060
|
+
const { importProject } = await import("./lib/importProject.js");
|
|
2061
|
+
const centralDb = DbClass.openCentral();
|
|
2062
|
+
if (!centralDb.isAvailable()) {
|
|
2063
|
+
console.error("Central DB unavailable.");
|
|
2064
|
+
process.exit(1);
|
|
2065
|
+
}
|
|
2066
|
+
try {
|
|
2067
|
+
const result = importProject(centralDb, {
|
|
2068
|
+
bundlePath: path.resolve(bundlePath),
|
|
2069
|
+
strategy: opts.strategy,
|
|
2070
|
+
workingDirectoryOverride: opts.workingDirectory,
|
|
2071
|
+
});
|
|
2072
|
+
if (opts.json) {
|
|
2073
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2074
|
+
}
|
|
2075
|
+
else {
|
|
2076
|
+
console.log(`Imported project ${result.projectName} (${result.projectId})`);
|
|
2077
|
+
console.log(` Strategy: ${result.strategy}`);
|
|
2078
|
+
console.log(` Memories: ${result.memoriesInserted} inserted, ${result.memoriesSkipped} skipped, ${result.memoriesReplaced} replaced`);
|
|
2079
|
+
console.log(` Relationships: ${result.relationshipsInserted}`);
|
|
2080
|
+
console.log(` Audit entries: ${result.auditEntriesInserted}`);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
catch (err) {
|
|
2084
|
+
console.error(`Import failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2085
|
+
process.exit(1);
|
|
2086
|
+
}
|
|
2087
|
+
finally {
|
|
2088
|
+
centralDb.close();
|
|
2089
|
+
}
|
|
2090
|
+
});
|
|
1969
2091
|
// ─── gnosys reindex ──────────────────────────────────────────────────────
|
|
1970
2092
|
program
|
|
1971
2093
|
.command("reindex")
|
|
@@ -3347,14 +3469,7 @@ program
|
|
|
3347
3469
|
const dreamCmd = program
|
|
3348
3470
|
.command("dream")
|
|
3349
3471
|
.description("Dream Mode — idle-time consolidation (run a cycle, view log)");
|
|
3350
|
-
|
|
3351
|
-
dreamCmd
|
|
3352
|
-
.option("--max-runtime <minutes>", "Max runtime in minutes (default: 30)")
|
|
3353
|
-
.option("--no-critique", "Skip self-critique phase")
|
|
3354
|
-
.option("--no-summaries", "Skip summary generation")
|
|
3355
|
-
.option("--no-relationships", "Skip relationship discovery")
|
|
3356
|
-
.option("--json", "Output raw JSON report")
|
|
3357
|
-
.action(async (opts) => {
|
|
3472
|
+
async function runDreamCycle(opts) {
|
|
3358
3473
|
const resolver = new GnosysResolver();
|
|
3359
3474
|
await resolver.resolve();
|
|
3360
3475
|
const stores = resolver.getStores();
|
|
@@ -3364,6 +3479,7 @@ dreamCmd
|
|
|
3364
3479
|
}
|
|
3365
3480
|
const { GnosysDB: DbClass } = await import("./lib/db.js");
|
|
3366
3481
|
const { GnosysDreamEngine, formatDreamReport } = await import("./lib/dream.js");
|
|
3482
|
+
const { getMachineId } = await import("./lib/remote.js");
|
|
3367
3483
|
const storePath = stores[0].path;
|
|
3368
3484
|
const cfg = await loadConfig(storePath);
|
|
3369
3485
|
const db = new DbClass(storePath);
|
|
@@ -3371,6 +3487,24 @@ dreamCmd
|
|
|
3371
3487
|
console.error("Dream Mode requires gnosys.db (v2.0). Run 'gnosys migrate' first.");
|
|
3372
3488
|
process.exit(1);
|
|
3373
3489
|
}
|
|
3490
|
+
// Designation gate — warn (and exit unless --force) if this isn't the
|
|
3491
|
+
// designated dream machine. Manual runs from non-designated machines are
|
|
3492
|
+
// useful for testing but shouldn't happen by accident on shared brains.
|
|
3493
|
+
const centralDb = GnosysDB.openCentral();
|
|
3494
|
+
if (centralDb.isAvailable()) {
|
|
3495
|
+
const designated = centralDb.getDreamMachineId();
|
|
3496
|
+
if (designated) {
|
|
3497
|
+
const localId = getMachineId(centralDb);
|
|
3498
|
+
if (designated !== localId && !opts.force) {
|
|
3499
|
+
console.error(`Dream is designated to machine ${designated}, but this is ${localId}.\n` +
|
|
3500
|
+
`Pass --force to run anyway, or run 'gnosys setup dream' to redesignate.`);
|
|
3501
|
+
centralDb.close();
|
|
3502
|
+
db.close();
|
|
3503
|
+
process.exit(1);
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
centralDb.close();
|
|
3507
|
+
}
|
|
3374
3508
|
const dreamConfig = {
|
|
3375
3509
|
enabled: true,
|
|
3376
3510
|
idleMinutes: 0,
|
|
@@ -3394,7 +3528,28 @@ dreamCmd
|
|
|
3394
3528
|
console.log(formatDreamReport(report));
|
|
3395
3529
|
}
|
|
3396
3530
|
db.close();
|
|
3397
|
-
}
|
|
3531
|
+
}
|
|
3532
|
+
// Bare `gnosys dream` runs a cycle (preserves v5.4.1 behavior).
|
|
3533
|
+
dreamCmd
|
|
3534
|
+
.option("--max-runtime <minutes>", "Max runtime in minutes (default: 30)")
|
|
3535
|
+
.option("--no-critique", "Skip self-critique phase")
|
|
3536
|
+
.option("--no-summaries", "Skip summary generation")
|
|
3537
|
+
.option("--no-relationships", "Skip relationship discovery")
|
|
3538
|
+
.option("--force", "Run even if this machine is not the designated dream node")
|
|
3539
|
+
.option("--json", "Output raw JSON report")
|
|
3540
|
+
.action(runDreamCycle);
|
|
3541
|
+
// `gnosys dream run` — explicit alias matching the `gnosys dream log|run`
|
|
3542
|
+
// pattern. Same options + behavior as the bare command.
|
|
3543
|
+
dreamCmd
|
|
3544
|
+
.command("run")
|
|
3545
|
+
.description("Force a dream cycle now (manual trigger)")
|
|
3546
|
+
.option("--max-runtime <minutes>", "Max runtime in minutes (default: 30)")
|
|
3547
|
+
.option("--no-critique", "Skip self-critique phase")
|
|
3548
|
+
.option("--no-summaries", "Skip summary generation")
|
|
3549
|
+
.option("--no-relationships", "Skip relationship discovery")
|
|
3550
|
+
.option("--force", "Run even if this machine is not the designated dream node")
|
|
3551
|
+
.option("--json", "Output raw JSON report")
|
|
3552
|
+
.action(runDreamCycle);
|
|
3398
3553
|
// `gnosys dream log` — view recent dream runs from audit_log
|
|
3399
3554
|
dreamCmd
|
|
3400
3555
|
.command("log")
|
|
@@ -3462,18 +3617,7 @@ dreamCmd
|
|
|
3462
3617
|
centralDb?.close();
|
|
3463
3618
|
}
|
|
3464
3619
|
});
|
|
3465
|
-
|
|
3466
|
-
program
|
|
3467
|
-
.command("export")
|
|
3468
|
-
.description("Export gnosys.db to Obsidian-compatible vault (one-way)")
|
|
3469
|
-
.requiredOption("--to <dir>", "Target directory for export")
|
|
3470
|
-
.option("--all", "Export all memories (active + archived)")
|
|
3471
|
-
.option("--overwrite", "Overwrite existing files")
|
|
3472
|
-
.option("--no-summaries", "Skip category summaries")
|
|
3473
|
-
.option("--no-reviews", "Skip review suggestions")
|
|
3474
|
-
.option("--no-graph", "Skip relationship graph")
|
|
3475
|
-
.option("--json", "Output raw JSON report")
|
|
3476
|
-
.action(async (opts) => {
|
|
3620
|
+
async function runVaultExport(opts) {
|
|
3477
3621
|
const resolver = new GnosysResolver();
|
|
3478
3622
|
await resolver.resolve();
|
|
3479
3623
|
const stores = resolver.getStores();
|
|
@@ -3512,6 +3656,81 @@ program
|
|
|
3512
3656
|
console.log(formatExportReport(report));
|
|
3513
3657
|
}
|
|
3514
3658
|
db.close();
|
|
3659
|
+
}
|
|
3660
|
+
const exportCmd = program
|
|
3661
|
+
.command("export")
|
|
3662
|
+
.description("Export memory to a vault (markdown) or a project bundle (.json.gz)")
|
|
3663
|
+
.enablePositionalOptions();
|
|
3664
|
+
// Bare `gnosys export` shows the canonical subcommand forms. Back-compat for
|
|
3665
|
+
// the v5.5.x form `gnosys export --to <dir>` is handled in a pre-parse shim
|
|
3666
|
+
// at the top of the file (rewrites argv to insert "vault" before "--to").
|
|
3667
|
+
exportCmd.action(() => {
|
|
3668
|
+
console.error("Usage: gnosys export vault --to <dir> # Obsidian vault export");
|
|
3669
|
+
console.error(" gnosys export project [id] --to <bundle> # portable .json.gz bundle");
|
|
3670
|
+
process.exit(1);
|
|
3671
|
+
});
|
|
3672
|
+
// `gnosys export vault` — explicit alias for the default behavior
|
|
3673
|
+
exportCmd
|
|
3674
|
+
.command("vault")
|
|
3675
|
+
.description("Export gnosys.db to an Obsidian-compatible vault (one-way)")
|
|
3676
|
+
.requiredOption("--to <dir>", "Target directory for export")
|
|
3677
|
+
.option("--all", "Export all memories (active + archived)")
|
|
3678
|
+
.option("--overwrite", "Overwrite existing files")
|
|
3679
|
+
.option("--no-summaries", "Skip category summaries")
|
|
3680
|
+
.option("--no-reviews", "Skip review suggestions")
|
|
3681
|
+
.option("--no-graph", "Skip relationship graph")
|
|
3682
|
+
.option("--json", "Output raw JSON report")
|
|
3683
|
+
.action(runVaultExport);
|
|
3684
|
+
// `gnosys export project [id]` — bundle a single project for portability
|
|
3685
|
+
exportCmd
|
|
3686
|
+
.command("project [projectId]")
|
|
3687
|
+
.description("Export a single project to a portable .json.gz bundle (round-trips with 'gnosys import project')")
|
|
3688
|
+
.requiredOption("--to <file>", "Output bundle file path (e.g. ./gnosys-public.gnosys.json.gz)")
|
|
3689
|
+
.option("--include-archived", "Include archived and superseded memories (default: active only)")
|
|
3690
|
+
.option("--no-audit", "Skip the audit log")
|
|
3691
|
+
.option("--json", "Output the result as JSON")
|
|
3692
|
+
.action(async (projectIdArg, opts) => {
|
|
3693
|
+
const { GnosysDB: DbClass } = await import("./lib/db.js");
|
|
3694
|
+
const { exportProject } = await import("./lib/exportProject.js");
|
|
3695
|
+
const centralDb = DbClass.openCentral();
|
|
3696
|
+
if (!centralDb.isAvailable()) {
|
|
3697
|
+
console.error("Central DB unavailable.");
|
|
3698
|
+
process.exit(1);
|
|
3699
|
+
}
|
|
3700
|
+
let projectId = projectIdArg;
|
|
3701
|
+
if (!projectId) {
|
|
3702
|
+
// Auto-detect from cwd
|
|
3703
|
+
const proj = centralDb.getProjectByDirectory(process.cwd());
|
|
3704
|
+
if (!proj) {
|
|
3705
|
+
console.error("No project ID given and current directory is not a registered project.");
|
|
3706
|
+
console.error("Usage: gnosys export project <projectId> --to <file>");
|
|
3707
|
+
process.exit(1);
|
|
3708
|
+
}
|
|
3709
|
+
projectId = proj.id;
|
|
3710
|
+
}
|
|
3711
|
+
try {
|
|
3712
|
+
const result = exportProject(centralDb, {
|
|
3713
|
+
projectId,
|
|
3714
|
+
outputPath: path.resolve(opts.to),
|
|
3715
|
+
includeArchived: !!opts.includeArchived,
|
|
3716
|
+
includeAudit: opts.audit !== false,
|
|
3717
|
+
});
|
|
3718
|
+
if (opts.json) {
|
|
3719
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3720
|
+
}
|
|
3721
|
+
else {
|
|
3722
|
+
const ratio = (result.compressedBytes / result.uncompressedBytes * 100).toFixed(1);
|
|
3723
|
+
console.log(`Exported project ${projectId}`);
|
|
3724
|
+
console.log(` Memories: ${result.memoryCount}`);
|
|
3725
|
+
console.log(` Relationships: ${result.relationshipCount}`);
|
|
3726
|
+
console.log(` Audit entries: ${result.auditEntryCount}`);
|
|
3727
|
+
console.log(` Bundle: ${result.outputPath}`);
|
|
3728
|
+
console.log(` Size: ${(result.compressedBytes / 1024).toFixed(1)} KB compressed (${ratio}% of ${(result.uncompressedBytes / 1024).toFixed(1)} KB)`);
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
finally {
|
|
3732
|
+
centralDb.close();
|
|
3733
|
+
}
|
|
3515
3734
|
});
|
|
3516
3735
|
// ─── gnosys serve ────────────────────────────────────────────────────────
|
|
3517
3736
|
program
|