gnosys 5.11.4 → 5.12.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.
Files changed (240) hide show
  1. package/dist/cli.js +324 -5150
  2. package/dist/index.js +364 -235
  3. package/dist/lib/addCommand.d.ts +9 -0
  4. package/dist/lib/addCommand.js +103 -0
  5. package/dist/lib/addStructuredCommand.d.ts +16 -0
  6. package/dist/lib/addStructuredCommand.js +103 -0
  7. package/dist/lib/ambiguityCommand.d.ts +4 -0
  8. package/dist/lib/ambiguityCommand.js +36 -0
  9. package/dist/lib/apiKeyVault.d.ts +78 -0
  10. package/dist/lib/apiKeyVault.js +447 -0
  11. package/dist/lib/askCommand.d.ts +13 -0
  12. package/dist/lib/askCommand.js +145 -0
  13. package/dist/lib/audioExtract.js +4 -1
  14. package/dist/lib/auditCommand.d.ts +7 -0
  15. package/dist/lib/auditCommand.js +27 -0
  16. package/dist/lib/backupCommand.d.ts +6 -0
  17. package/dist/lib/backupCommand.js +54 -0
  18. package/dist/lib/bootstrapCommand.d.ts +15 -0
  19. package/dist/lib/bootstrapCommand.js +51 -0
  20. package/dist/lib/briefingCommand.d.ts +7 -0
  21. package/dist/lib/briefingCommand.js +92 -0
  22. package/dist/lib/centralizeCommand.d.ts +5 -0
  23. package/dist/lib/centralizeCommand.js +16 -0
  24. package/dist/lib/chatCommand.d.ts +12 -0
  25. package/dist/lib/chatCommand.js +46 -0
  26. package/dist/lib/checkCommand.d.ts +4 -0
  27. package/dist/lib/checkCommand.js +133 -0
  28. package/dist/lib/clientReadOverlay.d.ts +27 -0
  29. package/dist/lib/clientReadOverlay.js +73 -0
  30. package/dist/lib/clientReadResolve.d.ts +32 -0
  31. package/dist/lib/clientReadResolve.js +84 -0
  32. package/dist/lib/commitContextCommand.d.ts +9 -0
  33. package/dist/lib/commitContextCommand.js +142 -0
  34. package/dist/lib/config.d.ts +43 -3
  35. package/dist/lib/config.js +58 -57
  36. package/dist/lib/configCommand.d.ts +10 -0
  37. package/dist/lib/configCommand.js +321 -0
  38. package/dist/lib/connectCommand.d.ts +8 -0
  39. package/dist/lib/connectCommand.js +19 -0
  40. package/dist/lib/db.d.ts +52 -0
  41. package/dist/lib/db.js +169 -1
  42. package/dist/lib/dearchiveCommand.d.ts +7 -0
  43. package/dist/lib/dearchiveCommand.js +41 -0
  44. package/dist/lib/discoverCommand.d.ts +9 -0
  45. package/dist/lib/discoverCommand.js +87 -0
  46. package/dist/lib/doctorCommand.d.ts +6 -0
  47. package/dist/lib/doctorCommand.js +256 -0
  48. package/dist/lib/dream.d.ts +42 -2
  49. package/dist/lib/dream.js +290 -30
  50. package/dist/lib/dreamCommand.d.ts +10 -0
  51. package/dist/lib/dreamCommand.js +195 -0
  52. package/dist/lib/dreamLaunchd.d.ts +2 -0
  53. package/dist/lib/dreamLaunchd.js +72 -0
  54. package/dist/lib/dreamLogCommand.d.ts +10 -0
  55. package/dist/lib/dreamLogCommand.js +58 -0
  56. package/dist/lib/dreamReport.d.ts +7 -0
  57. package/dist/lib/dreamReport.js +114 -0
  58. package/dist/lib/dreamRunLog.d.ts +121 -0
  59. package/dist/lib/dreamRunLog.js +212 -0
  60. package/dist/lib/embeddings.js +3 -0
  61. package/dist/lib/exportCommand.d.ts +18 -0
  62. package/dist/lib/exportCommand.js +101 -0
  63. package/dist/lib/fsearchCommand.d.ts +8 -0
  64. package/dist/lib/fsearchCommand.js +44 -0
  65. package/dist/lib/graphCommand.d.ts +4 -0
  66. package/dist/lib/graphCommand.js +68 -0
  67. package/dist/lib/helperGenerateCommand.d.ts +5 -0
  68. package/dist/lib/helperGenerateCommand.js +27 -0
  69. package/dist/lib/historyCommand.d.ts +5 -0
  70. package/dist/lib/historyCommand.js +51 -0
  71. package/dist/lib/hybridSearchCommand.d.ts +12 -0
  72. package/dist/lib/hybridSearchCommand.js +95 -0
  73. package/dist/lib/importCommand.d.ts +16 -0
  74. package/dist/lib/importCommand.js +89 -0
  75. package/dist/lib/importProjectCommand.d.ts +6 -0
  76. package/dist/lib/importProjectCommand.js +43 -0
  77. package/dist/lib/ingestCommand.d.ts +13 -0
  78. package/dist/lib/ingestCommand.js +95 -0
  79. package/dist/lib/installOutput.d.ts +36 -0
  80. package/dist/lib/installOutput.js +55 -0
  81. package/dist/lib/lensCommand.d.ts +20 -0
  82. package/dist/lib/lensCommand.js +61 -0
  83. package/dist/lib/lensing.d.ts +1 -0
  84. package/dist/lib/lensing.js +50 -9
  85. package/dist/lib/linksCommand.d.ts +7 -0
  86. package/dist/lib/linksCommand.js +48 -0
  87. package/dist/lib/listCommand.d.ts +8 -0
  88. package/dist/lib/listCommand.js +74 -0
  89. package/dist/lib/llm.d.ts +1 -1
  90. package/dist/lib/llm.js +26 -8
  91. package/dist/lib/localDiskCheck.d.ts +17 -0
  92. package/dist/lib/localDiskCheck.js +54 -0
  93. package/dist/lib/machineConfig.d.ts +11 -1
  94. package/dist/lib/machineConfig.js +16 -0
  95. package/dist/lib/machineRegistry.d.ts +61 -0
  96. package/dist/lib/machineRegistry.js +80 -0
  97. package/dist/lib/maintainCommand.d.ts +8 -0
  98. package/dist/lib/maintainCommand.js +34 -0
  99. package/dist/lib/masterLease.d.ts +20 -0
  100. package/dist/lib/masterLease.js +68 -0
  101. package/dist/lib/migrateCommand.d.ts +7 -0
  102. package/dist/lib/migrateCommand.js +158 -0
  103. package/dist/lib/migrateDbCommand.d.ts +9 -0
  104. package/dist/lib/migrateDbCommand.js +94 -0
  105. package/dist/lib/modelValidation.d.ts +5 -0
  106. package/dist/lib/modelValidation.js +27 -0
  107. package/dist/lib/openrouterTiers.d.ts +29 -0
  108. package/dist/lib/openrouterTiers.js +113 -0
  109. package/dist/lib/prefCommand.d.ts +10 -0
  110. package/dist/lib/prefCommand.js +118 -0
  111. package/dist/lib/projectsCommand.d.ts +8 -0
  112. package/dist/lib/projectsCommand.js +131 -0
  113. package/dist/lib/readCommand.d.ts +7 -0
  114. package/dist/lib/readCommand.js +62 -0
  115. package/dist/lib/recall.d.ts +3 -0
  116. package/dist/lib/recall.js +19 -4
  117. package/dist/lib/recallCommand.d.ts +11 -0
  118. package/dist/lib/recallCommand.js +112 -0
  119. package/dist/lib/reflectCommand.d.ts +8 -0
  120. package/dist/lib/reflectCommand.js +61 -0
  121. package/dist/lib/reindexCommand.d.ts +4 -0
  122. package/dist/lib/reindexCommand.js +34 -0
  123. package/dist/lib/reindexGraphCommand.d.ts +4 -0
  124. package/dist/lib/reindexGraphCommand.js +12 -0
  125. package/dist/lib/reinforceCommand.d.ts +8 -0
  126. package/dist/lib/reinforceCommand.js +40 -0
  127. package/dist/lib/remote.d.ts +5 -1
  128. package/dist/lib/remote.js +5 -1
  129. package/dist/lib/remoteWizard.d.ts +24 -5
  130. package/dist/lib/remoteWizard.js +308 -319
  131. package/dist/lib/restoreCommand.d.ts +5 -0
  132. package/dist/lib/restoreCommand.js +35 -0
  133. package/dist/lib/sandboxStartCommand.d.ts +6 -0
  134. package/dist/lib/sandboxStartCommand.js +25 -0
  135. package/dist/lib/sandboxStatusCommand.d.ts +4 -0
  136. package/dist/lib/sandboxStatusCommand.js +24 -0
  137. package/dist/lib/sandboxStopCommand.d.ts +4 -0
  138. package/dist/lib/sandboxStopCommand.js +21 -0
  139. package/dist/lib/searchCommand.d.ts +9 -0
  140. package/dist/lib/searchCommand.js +90 -0
  141. package/dist/lib/semanticSearchCommand.d.ts +8 -0
  142. package/dist/lib/semanticSearchCommand.js +52 -0
  143. package/dist/lib/setup/configSetRender.js +2 -0
  144. package/dist/lib/setup/providerGlyphs.d.ts +19 -0
  145. package/dist/lib/setup/providerGlyphs.js +42 -0
  146. package/dist/lib/setup/remoteRender.d.ts +31 -1
  147. package/dist/lib/setup/remoteRender.js +95 -4
  148. package/dist/lib/setup/sections/providers.d.ts +17 -0
  149. package/dist/lib/setup/sections/providers.js +255 -0
  150. package/dist/lib/setup/sections/routing.d.ts +2 -6
  151. package/dist/lib/setup/sections/routing.js +33 -85
  152. package/dist/lib/setup/sections/taskRoutingEditor.d.ts +17 -0
  153. package/dist/lib/setup/sections/taskRoutingEditor.js +149 -0
  154. package/dist/lib/setup/summary.d.ts +9 -0
  155. package/dist/lib/setup/summary.js +51 -37
  156. package/dist/lib/setup/ui/status.d.ts +1 -0
  157. package/dist/lib/setup/ui/status.js +2 -0
  158. package/dist/lib/setup.d.ts +108 -3
  159. package/dist/lib/setup.js +762 -157
  160. package/dist/lib/setupKeys.d.ts +42 -0
  161. package/dist/lib/setupKeys.js +564 -0
  162. package/dist/lib/setupRemoteCommand.d.ts +4 -0
  163. package/dist/lib/setupRemoteCommand.js +28 -0
  164. package/dist/lib/setupRemotePullCommand.d.ts +5 -0
  165. package/dist/lib/setupRemotePullCommand.js +52 -0
  166. package/dist/lib/setupRemotePushCommand.d.ts +5 -0
  167. package/dist/lib/setupRemotePushCommand.js +57 -0
  168. package/dist/lib/setupRemoteResolveCommand.d.ts +4 -0
  169. package/dist/lib/setupRemoteResolveCommand.js +48 -0
  170. package/dist/lib/setupRemoteStatusCommand.d.ts +4 -0
  171. package/dist/lib/setupRemoteStatusCommand.js +73 -0
  172. package/dist/lib/setupRemoteSyncCommand.d.ts +6 -0
  173. package/dist/lib/setupRemoteSyncCommand.js +65 -0
  174. package/dist/lib/setupSyncProjectsCommand.d.ts +4 -0
  175. package/dist/lib/setupSyncProjectsCommand.js +292 -0
  176. package/dist/lib/staleCommand.d.ts +8 -0
  177. package/dist/lib/staleCommand.js +34 -0
  178. package/dist/lib/statsCommand.d.ts +6 -0
  179. package/dist/lib/statsCommand.js +142 -0
  180. package/dist/lib/statusCommand.d.ts +18 -0
  181. package/dist/lib/statusCommand.js +250 -0
  182. package/dist/lib/storesCommand.d.ts +2 -0
  183. package/dist/lib/storesCommand.js +4 -0
  184. package/dist/lib/syncClient.d.ts +47 -0
  185. package/dist/lib/syncClient.js +212 -0
  186. package/dist/lib/syncCommand.d.ts +6 -0
  187. package/dist/lib/syncCommand.js +57 -0
  188. package/dist/lib/syncDoctorCommand.d.ts +5 -0
  189. package/dist/lib/syncDoctorCommand.js +100 -0
  190. package/dist/lib/syncIngest.d.ts +19 -0
  191. package/dist/lib/syncIngest.js +152 -0
  192. package/dist/lib/syncIngestLaunchd.d.ts +8 -0
  193. package/dist/lib/syncIngestLaunchd.js +93 -0
  194. package/dist/lib/syncIngestStartup.d.ts +5 -0
  195. package/dist/lib/syncIngestStartup.js +29 -0
  196. package/dist/lib/syncIngestSystemd.d.ts +10 -0
  197. package/dist/lib/syncIngestSystemd.js +97 -0
  198. package/dist/lib/syncIngestTimer.d.ts +8 -0
  199. package/dist/lib/syncIngestTimer.js +27 -0
  200. package/dist/lib/syncIngestTimerCommand.d.ts +7 -0
  201. package/dist/lib/syncIngestTimerCommand.js +83 -0
  202. package/dist/lib/syncLock.d.ts +6 -0
  203. package/dist/lib/syncLock.js +74 -0
  204. package/dist/lib/syncSnapshot.d.ts +30 -0
  205. package/dist/lib/syncSnapshot.js +184 -0
  206. package/dist/lib/syncStaging.d.ts +81 -0
  207. package/dist/lib/syncStaging.js +239 -0
  208. package/dist/lib/tagsAddCommand.d.ts +8 -0
  209. package/dist/lib/tagsAddCommand.js +18 -0
  210. package/dist/lib/tagsCommand.d.ts +4 -0
  211. package/dist/lib/tagsCommand.js +16 -0
  212. package/dist/lib/timelineCommand.d.ts +7 -0
  213. package/dist/lib/timelineCommand.js +49 -0
  214. package/dist/lib/traceCommand.d.ts +6 -0
  215. package/dist/lib/traceCommand.js +39 -0
  216. package/dist/lib/traverseCommand.d.ts +6 -0
  217. package/dist/lib/traverseCommand.js +58 -0
  218. package/dist/lib/updateCommand.d.ts +13 -0
  219. package/dist/lib/updateCommand.js +67 -0
  220. package/dist/lib/updateStatusCommand.d.ts +5 -0
  221. package/dist/lib/updateStatusCommand.js +38 -0
  222. package/dist/lib/webAddCommand.d.ts +8 -0
  223. package/dist/lib/webAddCommand.js +55 -0
  224. package/dist/lib/webBuildCommand.d.ts +10 -0
  225. package/dist/lib/webBuildCommand.js +65 -0
  226. package/dist/lib/webBuildIndexCommand.d.ts +8 -0
  227. package/dist/lib/webBuildIndexCommand.js +37 -0
  228. package/dist/lib/webIngestCommand.d.ts +11 -0
  229. package/dist/lib/webIngestCommand.js +51 -0
  230. package/dist/lib/webInitCommand.d.ts +9 -0
  231. package/dist/lib/webInitCommand.js +167 -0
  232. package/dist/lib/webRemoveCommand.d.ts +5 -0
  233. package/dist/lib/webRemoveCommand.js +41 -0
  234. package/dist/lib/webStatusCommand.d.ts +5 -0
  235. package/dist/lib/webStatusCommand.js +94 -0
  236. package/dist/lib/webUpdateCommand.d.ts +7 -0
  237. package/dist/lib/webUpdateCommand.js +72 -0
  238. package/dist/lib/workingSetCommand.d.ts +6 -0
  239. package/dist/lib/workingSetCommand.js +37 -0
  240. package/package.json +2 -1
@@ -0,0 +1,321 @@
1
+ import path from "path";
2
+ import fs from "fs/promises";
3
+ import { fileURLToPath } from "url";
4
+ import { loadConfig, writeConfig, resolveTaskModel, generateConfigTemplate, ALL_PROVIDERS, } from "./config.js";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ async function packageVersion() {
8
+ const pkgPath = path.resolve(__dirname, "..", "..", "package.json");
9
+ const pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8"));
10
+ return pkg.version;
11
+ }
12
+ function providerModel(cfg, p) {
13
+ switch (p) {
14
+ case "anthropic": return cfg.llm.anthropic.model;
15
+ case "ollama": return cfg.llm.ollama.model;
16
+ case "groq": return cfg.llm.groq.model;
17
+ case "openai": return cfg.llm.openai.model;
18
+ case "lmstudio": return cfg.llm.lmstudio.model;
19
+ case "xai": return cfg.llm.xai.model;
20
+ case "mistral": return cfg.llm.mistral.model;
21
+ case "openrouter": return cfg.llm.openrouter.model;
22
+ case "custom": return cfg.llm.custom?.model;
23
+ }
24
+ }
25
+ export async function runConfigShowCommand(getResolver, opts) {
26
+ const resolver = await getResolver();
27
+ const stores = resolver.getStores();
28
+ if (stores.length === 0) {
29
+ console.error("No stores found. Run gnosys init first.");
30
+ process.exit(1);
31
+ }
32
+ const cfg = await loadConfig(stores[0].path);
33
+ if (opts.json) {
34
+ // v5.9.3 (design §12): --json keeps the old machine-readable
35
+ // dump for scripts. Default output is the human-friendly view.
36
+ process.stdout.write(`${JSON.stringify(cfg, null, 2)}\n`);
37
+ return;
38
+ }
39
+ console.log("System of Cognition (SOC) — LLM Configuration:");
40
+ console.log(` Default provider: ${cfg.llm.defaultProvider}`);
41
+ console.log("");
42
+ console.log(" Providers:");
43
+ console.log(` Anthropic: model=${cfg.llm.anthropic.model}, apiKey=${cfg.llm.anthropic.apiKey ? "config" : (process.env.ANTHROPIC_API_KEY ? "env" : "—")}`);
44
+ console.log(` Ollama: model=${cfg.llm.ollama.model}, url=${cfg.llm.ollama.baseUrl}`);
45
+ console.log(` Groq: model=${cfg.llm.groq.model}, apiKey=${cfg.llm.groq.apiKey ? "config" : (process.env.GROQ_API_KEY ? "env" : "—")}`);
46
+ console.log(` OpenAI: model=${cfg.llm.openai.model}, apiKey=${cfg.llm.openai.apiKey ? "config" : (process.env.OPENAI_API_KEY ? "env" : "—")}, url=${cfg.llm.openai.baseUrl}`);
47
+ console.log(` LM Studio: model=${cfg.llm.lmstudio.model}, url=${cfg.llm.lmstudio.baseUrl}`);
48
+ console.log(` xAI: model=${cfg.llm.xai.model}, apiKey=${cfg.llm.xai.apiKey ? "config" : (process.env.XAI_API_KEY ? "env" : "—")}`);
49
+ console.log(` Mistral: model=${cfg.llm.mistral.model}, apiKey=${cfg.llm.mistral.apiKey ? "config" : (process.env.MISTRAL_API_KEY ? "env" : "—")}`);
50
+ console.log(` OpenRouter: model=${cfg.llm.openrouter.model}, apiKey=${cfg.llm.openrouter.apiKey ? "config" : (process.env.OPENROUTER_API_KEY ? "env" : "—")}, url=${cfg.llm.openrouter.baseUrl}`);
51
+ if (cfg.llm.custom) {
52
+ console.log(` Custom: model=${cfg.llm.custom.model}, url=${cfg.llm.custom.baseUrl}, apiKey=${cfg.llm.custom.apiKey ? "config" : (process.env.GNOSYS_LLM_API_KEY ? "env" : "—")}`);
53
+ }
54
+ console.log("");
55
+ const structuring = resolveTaskModel(cfg, "structuring");
56
+ const synthesis = resolveTaskModel(cfg, "synthesis");
57
+ console.log(" Task Routing:");
58
+ console.log(` Structuring: ${structuring.provider}/${structuring.model}${cfg.taskModels?.structuring ? " (override)" : " (default)"}`);
59
+ console.log(` Synthesis: ${synthesis.provider}/${synthesis.model}${cfg.taskModels?.synthesis ? " (override)" : " (default)"}`);
60
+ }
61
+ export async function runConfigSetCommand(getResolver, key, value, extra) {
62
+ // v5.9.3 Screen 13 — schema-validate the top-level key against the
63
+ // known set BEFORE any work, render a `did you mean X?` hint on
64
+ // typo. The diff + store-source label fire after the switch.
65
+ const { suggestConfigKey, classifyStore, KNOWN_CONFIG_KEYS } = await import("./setup/configSetRender.js");
66
+ const { Header } = await import("./setup/ui/header.js");
67
+ const { printStatus } = await import("./setup/ui/status.js");
68
+ const { printDiff } = await import("./setup/ui/diff.js");
69
+ if (!KNOWN_CONFIG_KEYS.includes(key)) {
70
+ const suggestion = suggestConfigKey(key);
71
+ const meta = suggestion ? `did you mean \`${suggestion}\` ?` : undefined;
72
+ printStatus("fail", `unknown config key ${key}`, meta);
73
+ process.exit(1);
74
+ }
75
+ const resolver = await getResolver();
76
+ const writeTarget = resolver.getWriteTarget();
77
+ if (!writeTarget) {
78
+ printStatus("fail", "no writable store found");
79
+ process.exit(1);
80
+ }
81
+ const storePath = writeTarget.store.getStorePath();
82
+ const cfg = await loadConfig(storePath);
83
+ const validProviders = ALL_PROVIDERS.join(", ");
84
+ const homeDir = process.env.HOME || process.env.USERPROFILE || "/";
85
+ const storeLabel = classifyStore(storePath, homeDir);
86
+ // Each branch populates this row so the trailing Diff print picks up
87
+ // a single before/after summary. Recall has three sub-fields and
88
+ // sets the row inside its own switch.
89
+ let diffRow = null;
90
+ switch (key) {
91
+ case "provider":
92
+ if (!ALL_PROVIDERS.includes(value)) {
93
+ printStatus("fail", `invalid provider \`${value}\``, `supported: ${validProviders}`);
94
+ process.exit(1);
95
+ }
96
+ diffRow = { label: "provider", from: cfg.llm.defaultProvider, to: value };
97
+ cfg.llm.defaultProvider = value;
98
+ break;
99
+ case "model": {
100
+ // Set model for current default provider
101
+ const p = cfg.llm.defaultProvider;
102
+ const fromModel = providerModel(cfg, p) ?? "(unset)";
103
+ if (p === "anthropic")
104
+ cfg.llm.anthropic.model = value;
105
+ else if (p === "ollama")
106
+ cfg.llm.ollama.model = value;
107
+ else if (p === "groq")
108
+ cfg.llm.groq.model = value;
109
+ else if (p === "openai")
110
+ cfg.llm.openai.model = value;
111
+ else if (p === "lmstudio")
112
+ cfg.llm.lmstudio.model = value;
113
+ else if (p === "xai")
114
+ cfg.llm.xai.model = value;
115
+ else if (p === "mistral")
116
+ cfg.llm.mistral.model = value;
117
+ else if (p === "openrouter")
118
+ cfg.llm.openrouter.model = value;
119
+ else if (p === "custom") {
120
+ if (!cfg.llm.custom)
121
+ cfg.llm.custom = { model: value, baseUrl: "" };
122
+ else
123
+ cfg.llm.custom.model = value;
124
+ }
125
+ diffRow = { label: `${p}.model`, from: fromModel, to: value };
126
+ break;
127
+ }
128
+ case "task": {
129
+ // gnosys config set task <taskName> <provider> <model>
130
+ const taskName = value;
131
+ const taskProvider = extra[0];
132
+ const taskModel = extra[1];
133
+ if (!taskName || !taskProvider || !taskModel) {
134
+ printStatus("fail", "usage", "gnosys config set task <structuring|synthesis> <provider> <model>");
135
+ process.exit(1);
136
+ }
137
+ if (taskName !== "structuring" && taskName !== "synthesis") {
138
+ printStatus("fail", `invalid task \`${taskName}\``, "valid: structuring, synthesis");
139
+ process.exit(1);
140
+ }
141
+ if (!ALL_PROVIDERS.includes(taskProvider)) {
142
+ printStatus("fail", `invalid provider \`${taskProvider}\``, `supported: ${validProviders}`);
143
+ process.exit(1);
144
+ }
145
+ if (!cfg.taskModels)
146
+ cfg.taskModels = {};
147
+ const taskMap = cfg.taskModels;
148
+ const prev = taskMap[taskName];
149
+ const fromStr = prev ? `${prev.provider}/${prev.model}` : "(unset)";
150
+ taskMap[taskName] = { provider: taskProvider, model: taskModel };
151
+ diffRow = { label: `task.${taskName}`, from: fromStr, to: `${taskProvider}/${taskModel}` };
152
+ break;
153
+ }
154
+ case "ollama-url":
155
+ diffRow = { label: "ollama.baseUrl", from: cfg.llm.ollama.baseUrl ?? "(unset)", to: value };
156
+ cfg.llm.ollama.baseUrl = value;
157
+ break;
158
+ case "ollama-model":
159
+ diffRow = { label: "ollama.model", from: cfg.llm.ollama.model ?? "(unset)", to: value };
160
+ cfg.llm.ollama.model = value;
161
+ break;
162
+ case "anthropic-model":
163
+ diffRow = { label: "anthropic.model", from: cfg.llm.anthropic.model ?? "(unset)", to: value };
164
+ cfg.llm.anthropic.model = value;
165
+ break;
166
+ case "groq-model":
167
+ diffRow = { label: "groq.model", from: cfg.llm.groq.model ?? "(unset)", to: value };
168
+ cfg.llm.groq.model = value;
169
+ break;
170
+ case "openai-model":
171
+ diffRow = { label: "openai.model", from: cfg.llm.openai.model ?? "(unset)", to: value };
172
+ cfg.llm.openai.model = value;
173
+ break;
174
+ case "openai-url":
175
+ diffRow = { label: "openai.baseUrl", from: cfg.llm.openai.baseUrl ?? "(unset)", to: value };
176
+ cfg.llm.openai.baseUrl = value;
177
+ break;
178
+ case "lmstudio-url":
179
+ diffRow = { label: "lmstudio.baseUrl", from: cfg.llm.lmstudio.baseUrl ?? "(unset)", to: value };
180
+ cfg.llm.lmstudio.baseUrl = value;
181
+ break;
182
+ case "lmstudio-model":
183
+ diffRow = { label: "lmstudio.model", from: cfg.llm.lmstudio.model ?? "(unset)", to: value };
184
+ cfg.llm.lmstudio.model = value;
185
+ break;
186
+ case "xai-model":
187
+ diffRow = { label: "xai.model", from: cfg.llm.xai.model ?? "(unset)", to: value };
188
+ cfg.llm.xai.model = value;
189
+ break;
190
+ case "mistral-model":
191
+ diffRow = { label: "mistral.model", from: cfg.llm.mistral.model ?? "(unset)", to: value };
192
+ cfg.llm.mistral.model = value;
193
+ break;
194
+ case "openrouter-model":
195
+ diffRow = { label: "openrouter.model", from: cfg.llm.openrouter.model ?? "(unset)", to: value };
196
+ cfg.llm.openrouter.model = value;
197
+ break;
198
+ case "openrouter-key":
199
+ diffRow = { label: "openrouter.apiKey", from: cfg.llm.openrouter.apiKey ? "(set)" : "(unset)", to: "(set)" };
200
+ cfg.llm.openrouter.apiKey = value;
201
+ break;
202
+ case "custom-url":
203
+ diffRow = { label: "custom.baseUrl", from: cfg.llm.custom?.baseUrl ?? "(unset)", to: value };
204
+ if (!cfg.llm.custom)
205
+ cfg.llm.custom = { model: "", baseUrl: value };
206
+ else
207
+ cfg.llm.custom.baseUrl = value;
208
+ break;
209
+ case "custom-model":
210
+ diffRow = { label: "custom.model", from: cfg.llm.custom?.model ?? "(unset)", to: value };
211
+ if (!cfg.llm.custom)
212
+ cfg.llm.custom = { model: value, baseUrl: "" };
213
+ else
214
+ cfg.llm.custom.model = value;
215
+ break;
216
+ case "custom-key":
217
+ // Sensitive — don't echo the key in the diff, just mark as redacted.
218
+ diffRow = { label: "custom.apiKey", from: cfg.llm.custom?.apiKey ? "(set)" : "(unset)", to: "(set)" };
219
+ if (!cfg.llm.custom)
220
+ cfg.llm.custom = { model: "", baseUrl: "", apiKey: value };
221
+ else
222
+ cfg.llm.custom.apiKey = value;
223
+ break;
224
+ case "recall": {
225
+ // gnosys config set recall <field> <value>
226
+ // Supported: recall aggressive true/false, recall maxMemories <n>, recall minRelevance <n>
227
+ const recallField = value;
228
+ const recallValue = extra[0];
229
+ if (!recallField || !recallValue) {
230
+ printStatus("fail", "usage", "gnosys config set recall <aggressive|maxMemories|minRelevance> <value>");
231
+ process.exit(1);
232
+ }
233
+ if (!cfg.recall)
234
+ cfg.recall = { aggressive: true, maxMemories: 8, minRelevance: 0.4 };
235
+ switch (recallField) {
236
+ case "aggressive":
237
+ if (recallValue !== "true" && recallValue !== "false") {
238
+ printStatus("fail", `invalid value \`${recallValue}\``, "use `true` or `false`");
239
+ process.exit(1);
240
+ }
241
+ diffRow = { label: "recall.aggressive", from: String(cfg.recall.aggressive), to: recallValue };
242
+ cfg.recall.aggressive = recallValue === "true";
243
+ break;
244
+ case "maxMemories": {
245
+ const n = parseInt(recallValue, 10);
246
+ if (isNaN(n) || n < 1 || n > 20) {
247
+ printStatus("fail", "maxMemories must be between 1 and 20");
248
+ process.exit(1);
249
+ }
250
+ diffRow = { label: "recall.maxMemories", from: String(cfg.recall.maxMemories), to: String(n) };
251
+ cfg.recall.maxMemories = n;
252
+ break;
253
+ }
254
+ case "minRelevance": {
255
+ const f = parseFloat(recallValue);
256
+ if (isNaN(f) || f < 0 || f > 1) {
257
+ printStatus("fail", "minRelevance must be between 0 and 1");
258
+ process.exit(1);
259
+ }
260
+ diffRow = { label: "recall.minRelevance", from: String(cfg.recall.minRelevance), to: String(f) };
261
+ cfg.recall.minRelevance = f;
262
+ break;
263
+ }
264
+ default:
265
+ printStatus("fail", `unknown recall field \`${recallField}\``, "valid: aggressive, maxMemories, minRelevance");
266
+ process.exit(1);
267
+ }
268
+ break;
269
+ }
270
+ }
271
+ await writeConfig(storePath, cfg);
272
+ // v5.9.3 Screen 13 — print Header + Diff + ✓ saved with store label.
273
+ console.log("");
274
+ console.log(Header(["gnosys", "config", "set"]));
275
+ console.log("");
276
+ if (diffRow) {
277
+ // Append store source to the `to` column so the diff line says
278
+ // both the new value and where it landed (project vs global).
279
+ printDiff([{ ...diffRow, to: `${diffRow.to} (${storeLabel})` }]);
280
+ }
281
+ printStatus("ok", `saved · ${path.join(storePath, "gnosys.json")}`, `(${storeLabel})`);
282
+ }
283
+ export async function runConfigInitCommand(getResolver, opts) {
284
+ // v5.9.3 (design handoff §14, deci-050): `config init` is being
285
+ // folded into `gnosys setup`. Without --force we print a warning
286
+ // pointing to `gnosys setup` and exit. With --force we write the
287
+ // (now-blank-provider) template anyway for muscle-memory use.
288
+ if (!opts.force) {
289
+ const { Header } = await import("./setup/ui/header.js");
290
+ const { Status } = await import("./setup/ui/status.js");
291
+ const { Footer } = await import("./setup/ui/footer.js");
292
+ console.log("");
293
+ console.log(Header(["gnosys", "config", "init"], { version: `v${(await packageVersion())}` }));
294
+ console.log("");
295
+ console.log(Status("warn", "writing a blank template means the next run of `gnosys setup`"));
296
+ console.log(Status("warn", "will walk you through the same choices anyway"));
297
+ console.log("");
298
+ console.log(" try gnosys setup interactive walkthrough (recommended)");
299
+ console.log("");
300
+ console.log(Footer("re-run with --force to write the template anyway"));
301
+ process.exit(0);
302
+ }
303
+ const resolver = await getResolver();
304
+ const writeTarget = resolver.getWriteTarget();
305
+ if (!writeTarget) {
306
+ console.error("No writable store found.");
307
+ process.exit(1);
308
+ }
309
+ const storePath = writeTarget.store.getStorePath();
310
+ const configPath = path.join(storePath, "gnosys.json");
311
+ try {
312
+ await fs.access(configPath);
313
+ console.error("gnosys.json already exists. Use 'gnosys config set' to modify.");
314
+ process.exit(1);
315
+ }
316
+ catch {
317
+ // File doesn't exist — good
318
+ }
319
+ await fs.writeFile(configPath, generateConfigTemplate() + "\n", "utf-8");
320
+ console.log(`Created ${configPath}`);
321
+ }
@@ -0,0 +1,8 @@
1
+ export type ConnectCommandOptions = {
2
+ url: string;
3
+ token?: string;
4
+ ide?: string;
5
+ dir?: string;
6
+ print?: boolean;
7
+ };
8
+ export declare function runConnectCommand(opts: ConnectCommandOptions): Promise<void>;
@@ -0,0 +1,19 @@
1
+ import { remoteMcpEntry, writeRemoteClientConfig } from "./mcpClientConfig.js";
2
+ export async function runConnectCommand(opts) {
3
+ const remote = { url: opts.url, token: opts.token };
4
+ if (opts.print) {
5
+ console.log(JSON.stringify({ mcpServers: { gnosys: remoteMcpEntry(remote) } }, null, 2));
6
+ return;
7
+ }
8
+ const ide = opts.ide === "claude-desktop" ? "claude-desktop" : "cursor";
9
+ try {
10
+ const file = await writeRemoteClientConfig(ide, opts.dir || process.cwd(), remote);
11
+ console.log(`✓ Pointed ${ide} at ${opts.url}`);
12
+ console.log(` wrote: ${file}${opts.token ? " (bearer token included)" : ""}`);
13
+ console.log(" Restart the IDE / MCP servers to pick it up.");
14
+ }
15
+ catch (e) {
16
+ console.error(`connect failed: ${e instanceof Error ? e.message : e}`);
17
+ process.exitCode = 1;
18
+ }
19
+ }
package/dist/lib/db.d.ts CHANGED
@@ -374,6 +374,58 @@ export declare class GnosysDB {
374
374
  remote_snapshot: string | null;
375
375
  }>;
376
376
  resolveConflict(memoryId: string): void;
377
+ recordStagingLedgerEntry(entry: {
378
+ stagingKey: string;
379
+ machineId: string;
380
+ memoryUlid?: string | null;
381
+ firstSeenAt: string;
382
+ ingestEpoch?: number | null;
383
+ status?: string;
384
+ }): void;
385
+ isUlidProcessed(ulid: string): boolean;
386
+ markUlidProcessed(ulid: string, ingestEpoch?: number | null): void;
387
+ countPendingStagingLedger(): number;
388
+ getStagingLedgerFirstSeenAt(stagingKey: string): string | null;
389
+ insertPendingAdd(row: {
390
+ id: string;
391
+ title: string;
392
+ category: string;
393
+ content: string;
394
+ tags?: string;
395
+ project_id?: string | null;
396
+ scope?: string;
397
+ created: string;
398
+ }): void;
399
+ listActivePendingAdds(): Array<{
400
+ id: string;
401
+ title: string;
402
+ category: string;
403
+ content: string;
404
+ tags: string;
405
+ project_id: string | null;
406
+ scope: string;
407
+ created: string;
408
+ }>;
409
+ clearPendingAdd(id: string): void;
410
+ getSnapshotManifest(): {
411
+ epoch: number;
412
+ seq: number;
413
+ snapshot_path: string;
414
+ published_at: string;
415
+ checksum: string | null;
416
+ size_bytes: number | null;
417
+ heartbeat_at: string | null;
418
+ } | null;
419
+ publishSnapshotManifest(manifest: {
420
+ epoch: number;
421
+ seq: number;
422
+ snapshotPath: string;
423
+ publishedAt: string;
424
+ checksum?: string | null;
425
+ sizeBytes?: number | null;
426
+ heartbeatAt?: string | null;
427
+ }): void;
428
+ touchSnapshotHeartbeat(at: string): void;
377
429
  close(): void;
378
430
  isMigrated(): boolean;
379
431
  getSchemaVersion(): number;
package/dist/lib/db.js CHANGED
@@ -24,7 +24,7 @@ import { readMachineConfig } from "./machineConfig.js";
24
24
  import { logError } from "./log.js";
25
25
  import { ulid } from "ulidx";
26
26
  // ─── Schema ─────────────────────────────────────────────────────────────
27
- const SCHEMA_VERSION = 4;
27
+ const SCHEMA_VERSION = 5;
28
28
  const SCHEMA_SQL = `
29
29
  CREATE TABLE IF NOT EXISTS memories (
30
30
  id TEXT PRIMARY KEY,
@@ -171,6 +171,51 @@ CREATE TABLE IF NOT EXISTS sync_conflicts (
171
171
  );
172
172
 
173
173
  CREATE INDEX IF NOT EXISTS idx_sync_conflicts_status ON sync_conflicts(status);
174
+
175
+ -- v13 multi-machine sync (master DB)
176
+
177
+ CREATE TABLE IF NOT EXISTS sync_staging_ledger (
178
+ staging_key TEXT PRIMARY KEY,
179
+ machine_id TEXT NOT NULL,
180
+ memory_ulid TEXT,
181
+ first_seen_at TEXT NOT NULL,
182
+ ingest_epoch INTEGER,
183
+ status TEXT NOT NULL DEFAULT 'pending'
184
+ );
185
+
186
+ CREATE INDEX IF NOT EXISTS idx_sync_staging_status ON sync_staging_ledger(status);
187
+ CREATE INDEX IF NOT EXISTS idx_sync_staging_first_seen ON sync_staging_ledger(first_seen_at);
188
+
189
+ CREATE TABLE IF NOT EXISTS sync_processed_ulids (
190
+ ulid TEXT PRIMARY KEY,
191
+ ingested_at TEXT NOT NULL,
192
+ ingest_epoch INTEGER
193
+ );
194
+
195
+ CREATE TABLE IF NOT EXISTS sync_pending_adds (
196
+ id TEXT PRIMARY KEY,
197
+ title TEXT NOT NULL,
198
+ category TEXT NOT NULL,
199
+ content TEXT NOT NULL,
200
+ tags TEXT DEFAULT '',
201
+ project_id TEXT,
202
+ scope TEXT DEFAULT 'project',
203
+ created TEXT NOT NULL,
204
+ cleared_at TEXT
205
+ );
206
+
207
+ CREATE INDEX IF NOT EXISTS idx_sync_pending_adds_cleared ON sync_pending_adds(cleared_at);
208
+
209
+ CREATE TABLE IF NOT EXISTS sync_snapshot_manifest (
210
+ singleton_id INTEGER PRIMARY KEY CHECK (singleton_id = 1),
211
+ epoch INTEGER NOT NULL,
212
+ seq INTEGER NOT NULL,
213
+ snapshot_path TEXT NOT NULL,
214
+ published_at TEXT NOT NULL,
215
+ checksum TEXT,
216
+ size_bytes INTEGER,
217
+ heartbeat_at TEXT
218
+ );
174
219
  `;
175
220
  // FTS5 sync triggers — created separately (can't use IF NOT EXISTS on triggers)
176
221
  const FTS_TRIGGERS_SQL = `
@@ -641,6 +686,55 @@ export class GnosysDB {
641
686
  // Table may already exist
642
687
  }
643
688
  }
689
+ if (fromVersion < 5) {
690
+ try {
691
+ this.db.exec(`
692
+ CREATE TABLE IF NOT EXISTS sync_staging_ledger (
693
+ staging_key TEXT PRIMARY KEY,
694
+ machine_id TEXT NOT NULL,
695
+ memory_ulid TEXT,
696
+ first_seen_at TEXT NOT NULL,
697
+ ingest_epoch INTEGER,
698
+ status TEXT NOT NULL DEFAULT 'pending'
699
+ );
700
+ CREATE INDEX IF NOT EXISTS idx_sync_staging_status ON sync_staging_ledger(status);
701
+ CREATE INDEX IF NOT EXISTS idx_sync_staging_first_seen ON sync_staging_ledger(first_seen_at);
702
+
703
+ CREATE TABLE IF NOT EXISTS sync_processed_ulids (
704
+ ulid TEXT PRIMARY KEY,
705
+ ingested_at TEXT NOT NULL,
706
+ ingest_epoch INTEGER
707
+ );
708
+
709
+ CREATE TABLE IF NOT EXISTS sync_pending_adds (
710
+ id TEXT PRIMARY KEY,
711
+ title TEXT NOT NULL,
712
+ category TEXT NOT NULL,
713
+ content TEXT NOT NULL,
714
+ tags TEXT DEFAULT '',
715
+ project_id TEXT,
716
+ scope TEXT DEFAULT 'project',
717
+ created TEXT NOT NULL,
718
+ cleared_at TEXT
719
+ );
720
+ CREATE INDEX IF NOT EXISTS idx_sync_pending_adds_cleared ON sync_pending_adds(cleared_at);
721
+
722
+ CREATE TABLE IF NOT EXISTS sync_snapshot_manifest (
723
+ singleton_id INTEGER PRIMARY KEY CHECK (singleton_id = 1),
724
+ epoch INTEGER NOT NULL,
725
+ seq INTEGER NOT NULL,
726
+ snapshot_path TEXT NOT NULL,
727
+ published_at TEXT NOT NULL,
728
+ checksum TEXT,
729
+ size_bytes INTEGER,
730
+ heartbeat_at TEXT
731
+ );
732
+ `);
733
+ }
734
+ catch {
735
+ // Sync tables/indexes may already exist — fine
736
+ }
737
+ }
644
738
  this.db.pragma(`user_version = ${SCHEMA_VERSION}`);
645
739
  }
646
740
  isAvailable() {
@@ -1233,6 +1327,80 @@ export class GnosysDB {
1233
1327
  resolveConflict(memoryId) {
1234
1328
  this.db.prepare("UPDATE sync_conflicts SET status = 'resolved' WHERE memory_id = ?").run(memoryId);
1235
1329
  }
1330
+ // ─── v13 multi-machine sync (master + client local overlay) ───────────
1331
+ recordStagingLedgerEntry(entry) {
1332
+ if (entry.status === undefined) {
1333
+ this.db.prepare(`
1334
+ INSERT INTO sync_staging_ledger (staging_key, machine_id, memory_ulid, first_seen_at, ingest_epoch, status)
1335
+ VALUES (?, ?, ?, ?, ?, 'pending')
1336
+ ON CONFLICT(staging_key) DO UPDATE SET
1337
+ memory_ulid = COALESCE(excluded.memory_ulid, sync_staging_ledger.memory_ulid),
1338
+ ingest_epoch = COALESCE(excluded.ingest_epoch, sync_staging_ledger.ingest_epoch)
1339
+ `).run(entry.stagingKey, entry.machineId, entry.memoryUlid ?? null, entry.firstSeenAt, entry.ingestEpoch ?? null);
1340
+ return;
1341
+ }
1342
+ this.db.prepare(`
1343
+ INSERT INTO sync_staging_ledger (staging_key, machine_id, memory_ulid, first_seen_at, ingest_epoch, status)
1344
+ VALUES (?, ?, ?, ?, ?, ?)
1345
+ ON CONFLICT(staging_key) DO UPDATE SET
1346
+ memory_ulid = COALESCE(excluded.memory_ulid, sync_staging_ledger.memory_ulid),
1347
+ ingest_epoch = COALESCE(excluded.ingest_epoch, sync_staging_ledger.ingest_epoch),
1348
+ status = excluded.status
1349
+ `).run(entry.stagingKey, entry.machineId, entry.memoryUlid ?? null, entry.firstSeenAt, entry.ingestEpoch ?? null, entry.status);
1350
+ }
1351
+ isUlidProcessed(ulid) {
1352
+ const row = this.db.prepare("SELECT 1 FROM sync_processed_ulids WHERE ulid = ?").get(ulid);
1353
+ return Boolean(row);
1354
+ }
1355
+ markUlidProcessed(ulid, ingestEpoch) {
1356
+ this.db.prepare(`
1357
+ INSERT OR IGNORE INTO sync_processed_ulids (ulid, ingested_at, ingest_epoch)
1358
+ VALUES (?, ?, ?)
1359
+ `).run(ulid, new Date().toISOString(), ingestEpoch ?? null);
1360
+ }
1361
+ countPendingStagingLedger() {
1362
+ const row = this.db.prepare("SELECT COUNT(*) as cnt FROM sync_staging_ledger WHERE status = 'pending'").get();
1363
+ return row.cnt;
1364
+ }
1365
+ getStagingLedgerFirstSeenAt(stagingKey) {
1366
+ const row = this.db.prepare("SELECT first_seen_at FROM sync_staging_ledger WHERE staging_key = ?").get(stagingKey);
1367
+ return row?.first_seen_at ?? null;
1368
+ }
1369
+ insertPendingAdd(row) {
1370
+ this.db.prepare(`
1371
+ INSERT OR REPLACE INTO sync_pending_adds
1372
+ (id, title, category, content, tags, project_id, scope, created, cleared_at)
1373
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL)
1374
+ `).run(row.id, row.title, row.category, row.content, row.tags ?? "", row.project_id ?? null, row.scope ?? "project", row.created);
1375
+ }
1376
+ listActivePendingAdds() {
1377
+ return this.db.prepare("SELECT id, title, category, content, tags, project_id, scope, created FROM sync_pending_adds WHERE cleared_at IS NULL ORDER BY created ASC").all();
1378
+ }
1379
+ clearPendingAdd(id) {
1380
+ this.db.prepare("UPDATE sync_pending_adds SET cleared_at = ? WHERE id = ? AND cleared_at IS NULL").run(new Date().toISOString(), id);
1381
+ }
1382
+ getSnapshotManifest() {
1383
+ const row = this.db.prepare("SELECT epoch, seq, snapshot_path, published_at, checksum, size_bytes, heartbeat_at FROM sync_snapshot_manifest WHERE singleton_id = 1").get();
1384
+ return row ?? null;
1385
+ }
1386
+ publishSnapshotManifest(manifest) {
1387
+ this.db.prepare(`
1388
+ INSERT INTO sync_snapshot_manifest
1389
+ (singleton_id, epoch, seq, snapshot_path, published_at, checksum, size_bytes, heartbeat_at)
1390
+ VALUES (1, ?, ?, ?, ?, ?, ?, ?)
1391
+ ON CONFLICT(singleton_id) DO UPDATE SET
1392
+ epoch = excluded.epoch,
1393
+ seq = excluded.seq,
1394
+ snapshot_path = excluded.snapshot_path,
1395
+ published_at = excluded.published_at,
1396
+ checksum = excluded.checksum,
1397
+ size_bytes = excluded.size_bytes,
1398
+ heartbeat_at = excluded.heartbeat_at
1399
+ `).run(manifest.epoch, manifest.seq, manifest.snapshotPath, manifest.publishedAt, manifest.checksum ?? null, manifest.sizeBytes ?? null, manifest.heartbeatAt ?? null);
1400
+ }
1401
+ touchSnapshotHeartbeat(at) {
1402
+ this.db.prepare("UPDATE sync_snapshot_manifest SET heartbeat_at = ? WHERE singleton_id = 1").run(at);
1403
+ }
1236
1404
  // ─── Lifecycle ──────────────────────────────────────────────────────
1237
1405
  close() {
1238
1406
  this.db?.close();
@@ -0,0 +1,7 @@
1
+ import type { GnosysResolver } from "./resolver.js";
2
+ type GetResolver = () => Promise<GnosysResolver>;
3
+ export type DearchiveCommandOptions = {
4
+ limit: string;
5
+ };
6
+ export declare function runDearchiveCommand(getResolver: GetResolver, query: string, opts: DearchiveCommandOptions): Promise<void>;
7
+ export {};
@@ -0,0 +1,41 @@
1
+ export async function runDearchiveCommand(getResolver, query, opts) {
2
+ let archive;
3
+ try {
4
+ const { GnosysArchive } = await import("./archive.js");
5
+ const resolver = await getResolver();
6
+ const stores = resolver.getStores();
7
+ if (stores.length === 0) {
8
+ console.error("No Gnosys stores found. Run gnosys init first.");
9
+ process.exit(1);
10
+ }
11
+ const writeTarget = resolver.getWriteTarget();
12
+ if (!writeTarget) {
13
+ console.error("No writable store found.");
14
+ process.exit(1);
15
+ }
16
+ archive = new GnosysArchive(writeTarget.path);
17
+ if (!archive.isAvailable()) {
18
+ console.error("Archive not available. Install it with: npm install better-sqlite3");
19
+ process.exit(1);
20
+ }
21
+ const results = archive.searchArchive(query, parseInt(opts.limit));
22
+ if (results.length === 0) {
23
+ console.log(`No archived memories found matching "${query}".`);
24
+ return;
25
+ }
26
+ console.log(`Found ${results.length} archived memories matching "${query}":\n`);
27
+ for (const r of results) {
28
+ console.log(` • ${r.title} (${r.id})`);
29
+ }
30
+ console.log("");
31
+ const ids = results.map((r) => r.id);
32
+ const restored = await archive.dearchiveBatch(ids, writeTarget.store);
33
+ console.log(`Dearchived ${restored.length} memories back to active:`);
34
+ for (const rp of restored) {
35
+ console.log(` → ${rp}`);
36
+ }
37
+ }
38
+ finally {
39
+ archive?.close();
40
+ }
41
+ }
@@ -0,0 +1,9 @@
1
+ export type DiscoverCommandOptions = {
2
+ limit: string;
3
+ json?: boolean;
4
+ federated?: boolean;
5
+ scope?: string;
6
+ directory?: string;
7
+ idFormat?: string;
8
+ };
9
+ export declare function runDiscoverCommand(query: string, opts: DiscoverCommandOptions): Promise<void>;