gnosys 5.11.4 → 5.12.2
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/dist/cli.js +377 -5162
- package/dist/index.js +542 -244
- package/dist/lib/addCommand.d.ts +9 -0
- package/dist/lib/addCommand.js +102 -0
- package/dist/lib/addStructuredCommand.d.ts +16 -0
- package/dist/lib/addStructuredCommand.js +103 -0
- package/dist/lib/ambiguityCommand.d.ts +4 -0
- package/dist/lib/ambiguityCommand.js +36 -0
- package/dist/lib/apiKeyVault.d.ts +78 -0
- package/dist/lib/apiKeyVault.js +447 -0
- package/dist/lib/archive.js +0 -2
- package/dist/lib/askCommand.d.ts +13 -0
- package/dist/lib/askCommand.js +145 -0
- package/dist/lib/attachCommand.d.ts +17 -0
- package/dist/lib/attachCommand.js +66 -0
- package/dist/lib/attachments.d.ts +43 -2
- package/dist/lib/attachments.js +81 -2
- package/dist/lib/audioExtract.js +4 -1
- package/dist/lib/auditCommand.d.ts +7 -0
- package/dist/lib/auditCommand.js +27 -0
- package/dist/lib/backupCommand.d.ts +6 -0
- package/dist/lib/backupCommand.js +54 -0
- package/dist/lib/bootstrapCommand.d.ts +15 -0
- package/dist/lib/bootstrapCommand.js +51 -0
- package/dist/lib/briefingCommand.d.ts +7 -0
- package/dist/lib/briefingCommand.js +92 -0
- package/dist/lib/centralizeCommand.d.ts +5 -0
- package/dist/lib/centralizeCommand.js +16 -0
- package/dist/lib/chat/choose.js +2 -2
- package/dist/lib/chatCommand.d.ts +12 -0
- package/dist/lib/chatCommand.js +46 -0
- package/dist/lib/checkCommand.d.ts +4 -0
- package/dist/lib/checkCommand.js +133 -0
- package/dist/lib/clientReadOverlay.d.ts +27 -0
- package/dist/lib/clientReadOverlay.js +76 -0
- package/dist/lib/clientReadResolve.d.ts +32 -0
- package/dist/lib/clientReadResolve.js +84 -0
- package/dist/lib/commitContextCommand.d.ts +9 -0
- package/dist/lib/commitContextCommand.js +142 -0
- package/dist/lib/config.d.ts +41 -48
- package/dist/lib/config.js +58 -57
- package/dist/lib/configCommand.d.ts +10 -0
- package/dist/lib/configCommand.js +321 -0
- package/dist/lib/connectCommand.d.ts +8 -0
- package/dist/lib/connectCommand.js +19 -0
- package/dist/lib/db.d.ts +68 -1
- package/dist/lib/db.js +385 -120
- package/dist/lib/dbWrite.d.ts +1 -1
- package/dist/lib/dearchiveCommand.d.ts +7 -0
- package/dist/lib/dearchiveCommand.js +41 -0
- package/dist/lib/discoverCommand.d.ts +9 -0
- package/dist/lib/discoverCommand.js +87 -0
- package/dist/lib/doctorCommand.d.ts +6 -0
- package/dist/lib/doctorCommand.js +256 -0
- package/dist/lib/docxExtract.js +1 -1
- package/dist/lib/dream.d.ts +50 -2
- package/dist/lib/dream.js +324 -30
- package/dist/lib/dreamCommand.d.ts +10 -0
- package/dist/lib/dreamCommand.js +195 -0
- package/dist/lib/dreamLaunchd.d.ts +2 -0
- package/dist/lib/dreamLaunchd.js +72 -0
- package/dist/lib/dreamLogCommand.d.ts +10 -0
- package/dist/lib/dreamLogCommand.js +58 -0
- package/dist/lib/dreamReport.d.ts +7 -0
- package/dist/lib/dreamReport.js +114 -0
- package/dist/lib/dreamRunLog.d.ts +121 -0
- package/dist/lib/dreamRunLog.js +234 -0
- package/dist/lib/embeddings.js +3 -3
- package/dist/lib/exportCommand.d.ts +18 -0
- package/dist/lib/exportCommand.js +101 -0
- package/dist/lib/exportProject.d.ts +3 -2
- package/dist/lib/exportProject.js +2 -1
- package/dist/lib/federated.js +1 -1
- package/dist/lib/fsearchCommand.d.ts +8 -0
- package/dist/lib/fsearchCommand.js +44 -0
- package/dist/lib/graphCommand.d.ts +4 -0
- package/dist/lib/graphCommand.js +68 -0
- package/dist/lib/helperGenerateCommand.d.ts +5 -0
- package/dist/lib/helperGenerateCommand.js +27 -0
- package/dist/lib/historyCommand.d.ts +5 -0
- package/dist/lib/historyCommand.js +51 -0
- package/dist/lib/hybridSearchCommand.d.ts +12 -0
- package/dist/lib/hybridSearchCommand.js +95 -0
- package/dist/lib/importCommand.d.ts +16 -0
- package/dist/lib/importCommand.js +89 -0
- package/dist/lib/importProject.js +2 -1
- package/dist/lib/importProjectCommand.d.ts +6 -0
- package/dist/lib/importProjectCommand.js +43 -0
- package/dist/lib/ingestCommand.d.ts +13 -0
- package/dist/lib/ingestCommand.js +95 -0
- package/dist/lib/installOutput.d.ts +36 -0
- package/dist/lib/installOutput.js +55 -0
- package/dist/lib/lensCommand.d.ts +20 -0
- package/dist/lib/lensCommand.js +61 -0
- package/dist/lib/lensing.d.ts +1 -0
- package/dist/lib/lensing.js +50 -9
- package/dist/lib/linksCommand.d.ts +7 -0
- package/dist/lib/linksCommand.js +48 -0
- package/dist/lib/listCommand.d.ts +8 -0
- package/dist/lib/listCommand.js +74 -0
- package/dist/lib/llm.d.ts +1 -1
- package/dist/lib/llm.js +27 -9
- package/dist/lib/localDiskCheck.d.ts +17 -0
- package/dist/lib/localDiskCheck.js +54 -0
- package/dist/lib/lock.d.ts +1 -1
- package/dist/lib/lock.js +5 -3
- package/dist/lib/machineConfig.d.ts +11 -1
- package/dist/lib/machineConfig.js +16 -0
- package/dist/lib/machineRegistry.d.ts +61 -0
- package/dist/lib/machineRegistry.js +80 -0
- package/dist/lib/maintainCommand.d.ts +8 -0
- package/dist/lib/maintainCommand.js +34 -0
- package/dist/lib/masterLease.d.ts +20 -0
- package/dist/lib/masterLease.js +68 -0
- package/dist/lib/migrate.js +0 -1
- package/dist/lib/migrateCommand.d.ts +7 -0
- package/dist/lib/migrateCommand.js +158 -0
- package/dist/lib/migrateDbCommand.d.ts +9 -0
- package/dist/lib/migrateDbCommand.js +94 -0
- package/dist/lib/modelValidation.d.ts +5 -0
- package/dist/lib/modelValidation.js +27 -0
- package/dist/lib/multimodalIngest.js +1 -1
- package/dist/lib/openrouterTiers.d.ts +29 -0
- package/dist/lib/openrouterTiers.js +113 -0
- package/dist/lib/platform.d.ts +0 -6
- package/dist/lib/platform.js +0 -28
- package/dist/lib/prefCommand.d.ts +10 -0
- package/dist/lib/prefCommand.js +118 -0
- package/dist/lib/projectsCommand.d.ts +8 -0
- package/dist/lib/projectsCommand.js +131 -0
- package/dist/lib/readCommand.d.ts +7 -0
- package/dist/lib/readCommand.js +63 -0
- package/dist/lib/recall.d.ts +3 -0
- package/dist/lib/recall.js +19 -4
- package/dist/lib/recallCommand.d.ts +11 -0
- package/dist/lib/recallCommand.js +112 -0
- package/dist/lib/reflectCommand.d.ts +8 -0
- package/dist/lib/reflectCommand.js +61 -0
- package/dist/lib/reindexCommand.d.ts +4 -0
- package/dist/lib/reindexCommand.js +34 -0
- package/dist/lib/reindexGraphCommand.d.ts +4 -0
- package/dist/lib/reindexGraphCommand.js +12 -0
- package/dist/lib/reinforceCommand.d.ts +8 -0
- package/dist/lib/reinforceCommand.js +40 -0
- package/dist/lib/remote.d.ts +5 -1
- package/dist/lib/remote.js +5 -1
- package/dist/lib/remoteWizard.d.ts +24 -5
- package/dist/lib/remoteWizard.js +308 -319
- package/dist/lib/restoreCommand.d.ts +5 -0
- package/dist/lib/restoreCommand.js +35 -0
- package/dist/lib/rulesGen.d.ts +8 -0
- package/dist/lib/rulesGen.js +16 -0
- package/dist/lib/sandboxStartCommand.d.ts +6 -0
- package/dist/lib/sandboxStartCommand.js +25 -0
- package/dist/lib/sandboxStatusCommand.d.ts +4 -0
- package/dist/lib/sandboxStatusCommand.js +24 -0
- package/dist/lib/sandboxStopCommand.d.ts +4 -0
- package/dist/lib/sandboxStopCommand.js +21 -0
- package/dist/lib/search.d.ts +0 -2
- package/dist/lib/search.js +0 -7
- package/dist/lib/searchCommand.d.ts +9 -0
- package/dist/lib/searchCommand.js +90 -0
- package/dist/lib/semanticSearchCommand.d.ts +8 -0
- package/dist/lib/semanticSearchCommand.js +52 -0
- package/dist/lib/setup/configSetRender.js +2 -0
- package/dist/lib/setup/providerGlyphs.d.ts +19 -0
- package/dist/lib/setup/providerGlyphs.js +42 -0
- package/dist/lib/setup/remoteRender.d.ts +31 -1
- package/dist/lib/setup/remoteRender.js +95 -4
- package/dist/lib/setup/sections/providers.d.ts +17 -0
- package/dist/lib/setup/sections/providers.js +307 -0
- package/dist/lib/setup/sections/routing.d.ts +2 -6
- package/dist/lib/setup/sections/routing.js +67 -82
- package/dist/lib/setup/sections/taskRoutingEditor.d.ts +13 -0
- package/dist/lib/setup/sections/taskRoutingEditor.js +139 -0
- package/dist/lib/setup/summary.d.ts +9 -0
- package/dist/lib/setup/summary.js +51 -37
- package/dist/lib/setup/ui/header.js +0 -1
- package/dist/lib/setup.d.ts +105 -15
- package/dist/lib/setup.js +747 -287
- package/dist/lib/setupKeys.d.ts +42 -0
- package/dist/lib/setupKeys.js +564 -0
- package/dist/lib/setupRemoteCommand.d.ts +4 -0
- package/dist/lib/setupRemoteCommand.js +28 -0
- package/dist/lib/setupRemotePullCommand.d.ts +5 -0
- package/dist/lib/setupRemotePullCommand.js +52 -0
- package/dist/lib/setupRemotePushCommand.d.ts +5 -0
- package/dist/lib/setupRemotePushCommand.js +57 -0
- package/dist/lib/setupRemoteResolveCommand.d.ts +4 -0
- package/dist/lib/setupRemoteResolveCommand.js +48 -0
- package/dist/lib/setupRemoteStatusCommand.d.ts +4 -0
- package/dist/lib/setupRemoteStatusCommand.js +73 -0
- package/dist/lib/setupRemoteSyncCommand.d.ts +6 -0
- package/dist/lib/setupRemoteSyncCommand.js +65 -0
- package/dist/lib/setupSyncProjectsCommand.d.ts +4 -0
- package/dist/lib/setupSyncProjectsCommand.js +292 -0
- package/dist/lib/staleCommand.d.ts +8 -0
- package/dist/lib/staleCommand.js +34 -0
- package/dist/lib/statsCommand.d.ts +6 -0
- package/dist/lib/statsCommand.js +142 -0
- package/dist/lib/statusCommand.d.ts +18 -0
- package/dist/lib/statusCommand.js +250 -0
- package/dist/lib/storesCommand.d.ts +2 -0
- package/dist/lib/storesCommand.js +4 -0
- package/dist/lib/syncClient.d.ts +41 -0
- package/dist/lib/syncClient.js +234 -0
- package/dist/lib/syncCommand.d.ts +6 -0
- package/dist/lib/syncCommand.js +57 -0
- package/dist/lib/syncDoctorCommand.d.ts +5 -0
- package/dist/lib/syncDoctorCommand.js +100 -0
- package/dist/lib/syncIngest.d.ts +30 -0
- package/dist/lib/syncIngest.js +175 -0
- package/dist/lib/syncIngestLaunchd.d.ts +8 -0
- package/dist/lib/syncIngestLaunchd.js +93 -0
- package/dist/lib/syncIngestStartup.d.ts +5 -0
- package/dist/lib/syncIngestStartup.js +29 -0
- package/dist/lib/syncIngestSystemd.d.ts +10 -0
- package/dist/lib/syncIngestSystemd.js +97 -0
- package/dist/lib/syncIngestTimer.d.ts +8 -0
- package/dist/lib/syncIngestTimer.js +27 -0
- package/dist/lib/syncIngestTimerCommand.d.ts +7 -0
- package/dist/lib/syncIngestTimerCommand.js +83 -0
- package/dist/lib/syncLock.d.ts +6 -0
- package/dist/lib/syncLock.js +74 -0
- package/dist/lib/syncSnapshot.d.ts +32 -0
- package/dist/lib/syncSnapshot.js +188 -0
- package/dist/lib/syncStaging.d.ts +79 -0
- package/dist/lib/syncStaging.js +237 -0
- package/dist/lib/tagsAddCommand.d.ts +8 -0
- package/dist/lib/tagsAddCommand.js +18 -0
- package/dist/lib/tagsCommand.d.ts +4 -0
- package/dist/lib/tagsCommand.js +16 -0
- package/dist/lib/timelineCommand.d.ts +7 -0
- package/dist/lib/timelineCommand.js +49 -0
- package/dist/lib/traceCommand.d.ts +6 -0
- package/dist/lib/traceCommand.js +39 -0
- package/dist/lib/traverseCommand.d.ts +6 -0
- package/dist/lib/traverseCommand.js +58 -0
- package/dist/lib/updateCommand.d.ts +13 -0
- package/dist/lib/updateCommand.js +67 -0
- package/dist/lib/updateStatusCommand.d.ts +5 -0
- package/dist/lib/updateStatusCommand.js +38 -0
- package/dist/lib/webAddCommand.d.ts +8 -0
- package/dist/lib/webAddCommand.js +55 -0
- package/dist/lib/webBuildCommand.d.ts +10 -0
- package/dist/lib/webBuildCommand.js +65 -0
- package/dist/lib/webBuildIndexCommand.d.ts +8 -0
- package/dist/lib/webBuildIndexCommand.js +37 -0
- package/dist/lib/webIndex.js +0 -1
- package/dist/lib/webIngestCommand.d.ts +11 -0
- package/dist/lib/webIngestCommand.js +51 -0
- package/dist/lib/webInitCommand.d.ts +9 -0
- package/dist/lib/webInitCommand.js +167 -0
- package/dist/lib/webRemoveCommand.d.ts +5 -0
- package/dist/lib/webRemoveCommand.js +41 -0
- package/dist/lib/webStatusCommand.d.ts +5 -0
- package/dist/lib/webStatusCommand.js +94 -0
- package/dist/lib/webUpdateCommand.d.ts +7 -0
- package/dist/lib/webUpdateCommand.js +72 -0
- package/dist/lib/workingSetCommand.d.ts +6 -0
- package/dist/lib/workingSetCommand.js +37 -0
- package/dist/sandbox/client.js +1 -1
- package/dist/sandbox/manager.js +1 -14
- package/dist/sandbox/server.js +3 -5
- package/package.json +6 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI handlers for inline DB-blob attachments (v5.12).
|
|
3
|
+
*
|
|
4
|
+
* gnosys attach <file> --memory <id> store bytes inline on a memory
|
|
5
|
+
* gnosys get-attachment <id> [--out path] retrieve the stored bytes
|
|
6
|
+
*
|
|
7
|
+
* Inline attachments live in the memory row, so they ride the normal sync
|
|
8
|
+
* rail to other machines and a remote/dockerized server.
|
|
9
|
+
*/
|
|
10
|
+
import { GnosysDB } from "./db.js";
|
|
11
|
+
export async function runAttachCommand(filePath, opts) {
|
|
12
|
+
const db = GnosysDB.openCentral();
|
|
13
|
+
try {
|
|
14
|
+
if (!db.isAvailable()) {
|
|
15
|
+
console.error("Database not available.");
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { attachFileToMemory } = await import("./attachments.js");
|
|
20
|
+
const result = await attachFileToMemory(db, opts.memory, filePath);
|
|
21
|
+
const sizeKb = (result.sizeBytes / 1024).toFixed(1);
|
|
22
|
+
const verb = result.unchanged ? "Already attached (no change)" : "Attached";
|
|
23
|
+
console.log(`${verb}: ${result.name} (${result.mime}, ${sizeKb} KB) → ${opts.memory}`);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
db.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function runGetAttachmentCommand(memoryId, opts) {
|
|
34
|
+
const db = GnosysDB.openCentral();
|
|
35
|
+
try {
|
|
36
|
+
if (!db.isAvailable()) {
|
|
37
|
+
console.error("Database not available.");
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const { getMemoryAttachment } = await import("./attachments.js");
|
|
42
|
+
const att = getMemoryAttachment(db, memoryId);
|
|
43
|
+
if (!att) {
|
|
44
|
+
console.error(`No attachment found on memory: ${memoryId}`);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (opts.out) {
|
|
49
|
+
const { writeFile } = await import("fs/promises");
|
|
50
|
+
await writeFile(opts.out, att.data);
|
|
51
|
+
console.log(`Wrote ${att.name} (${att.mime}, ${att.data.length} bytes) to ${opts.out}`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// No output path: print metadata + base64 so it can be piped/redirected.
|
|
55
|
+
console.error(`${att.name} (${att.mime}, ${att.data.length} bytes)`);
|
|
56
|
+
console.log(att.data.toString("base64"));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
61
|
+
process.exitCode = 1;
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
db.close();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Gnosys Attachments — File attachment management for multimodal ingestion.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Two storage modes:
|
|
5
|
+
* - Filesystem (legacy, large media): bytes copied to .gnosys/attachments/<uuid>.<ext>
|
|
6
|
+
* with a JSON manifest. Does NOT travel between machines.
|
|
7
|
+
* - Inline DB blob (v5.12, small assets): bytes stored in the memory row's
|
|
8
|
+
* attachment_data column. Travels over the same row-copy sync rail as
|
|
9
|
+
* embeddings, so it works single-machine, multi-machine, and with a future
|
|
10
|
+
* dockerized MCP without any shared volume.
|
|
6
11
|
*/
|
|
12
|
+
import type { GnosysDB } from "./db.js";
|
|
7
13
|
export interface AttachmentRecord {
|
|
8
14
|
uuid: string;
|
|
9
15
|
originalName: string;
|
|
@@ -14,6 +20,8 @@ export interface AttachmentRecord {
|
|
|
14
20
|
createdAt: string;
|
|
15
21
|
memoryIds: string[];
|
|
16
22
|
}
|
|
23
|
+
/** Infer a MIME type from a file path's extension. */
|
|
24
|
+
export declare function inferMimeType(filePath: string): string;
|
|
17
25
|
/**
|
|
18
26
|
* Initialize the attachments directory and manifest in a store.
|
|
19
27
|
* Safe to call multiple times — creates only if missing.
|
|
@@ -40,3 +48,36 @@ export declare function getAttachmentPath(storePath: string, uuid: string, ext:
|
|
|
40
48
|
* tracks which memories reference it.
|
|
41
49
|
*/
|
|
42
50
|
export declare function linkMemoryToAttachment(storePath: string, uuid: string, memoryId: string): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Maximum size for an inline DB-blob attachment. Larger files should use the
|
|
53
|
+
* filesystem path (`gnosys ingest`) so the synced central DB stays lean.
|
|
54
|
+
*/
|
|
55
|
+
export declare const MAX_INLINE_ATTACHMENT_BYTES: number;
|
|
56
|
+
export interface InlineAttachment {
|
|
57
|
+
/** Raw file bytes. */
|
|
58
|
+
data: Buffer;
|
|
59
|
+
/** MIME type, e.g. "image/svg+xml". */
|
|
60
|
+
mime: string;
|
|
61
|
+
/** Original filename, e.g. "prospero-logo.svg". */
|
|
62
|
+
name: string;
|
|
63
|
+
/** Size in bytes. */
|
|
64
|
+
sizeBytes: number;
|
|
65
|
+
}
|
|
66
|
+
export interface AttachToMemoryResult {
|
|
67
|
+
memoryId: string;
|
|
68
|
+
name: string;
|
|
69
|
+
mime: string;
|
|
70
|
+
sizeBytes: number;
|
|
71
|
+
/** True when the file was identical to what was already attached (no write). */
|
|
72
|
+
unchanged: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Read a file and store its bytes inline on a memory row (attachment_data).
|
|
76
|
+
* Enforces the size cap and skips the write if the same bytes are already
|
|
77
|
+
* attached (content-hash dedup). Bumps `modified` so remote sync picks it up.
|
|
78
|
+
*/
|
|
79
|
+
export declare function attachFileToMemory(db: GnosysDB, memoryId: string, filePath: string): Promise<AttachToMemoryResult>;
|
|
80
|
+
/** Return the inline attachment stored on a memory row, or null if none. */
|
|
81
|
+
export declare function getMemoryAttachment(db: GnosysDB, memoryId: string): InlineAttachment | null;
|
|
82
|
+
/** Remove an inline attachment from a memory row (keeps the memory itself). */
|
|
83
|
+
export declare function detachFromMemory(db: GnosysDB, memoryId: string): boolean;
|
package/dist/lib/attachments.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Gnosys Attachments — File attachment management for multimodal ingestion.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Two storage modes:
|
|
5
|
+
* - Filesystem (legacy, large media): bytes copied to .gnosys/attachments/<uuid>.<ext>
|
|
6
|
+
* with a JSON manifest. Does NOT travel between machines.
|
|
7
|
+
* - Inline DB blob (v5.12, small assets): bytes stored in the memory row's
|
|
8
|
+
* attachment_data column. Travels over the same row-copy sync rail as
|
|
9
|
+
* embeddings, so it works single-machine, multi-machine, and with a future
|
|
10
|
+
* dockerized MCP without any shared volume.
|
|
6
11
|
*/
|
|
7
12
|
import * as fs from "fs/promises";
|
|
8
13
|
import * as path from "path";
|
|
@@ -37,6 +42,10 @@ const MIME_MAP = {
|
|
|
37
42
|
function mimeFromExtension(ext) {
|
|
38
43
|
return MIME_MAP[ext.toLowerCase()] || "application/octet-stream";
|
|
39
44
|
}
|
|
45
|
+
/** Infer a MIME type from a file path's extension. */
|
|
46
|
+
export function inferMimeType(filePath) {
|
|
47
|
+
return mimeFromExtension(path.extname(filePath).slice(1));
|
|
48
|
+
}
|
|
40
49
|
// ─── Helpers ────────────────────────────────────────────────────────────
|
|
41
50
|
function getAttachmentsDir(storePath) {
|
|
42
51
|
return path.join(storePath, "attachments");
|
|
@@ -151,3 +160,73 @@ export async function linkMemoryToAttachment(storePath, uuid, memoryId) {
|
|
|
151
160
|
await writeManifest(storePath, manifest);
|
|
152
161
|
}
|
|
153
162
|
}
|
|
163
|
+
// ─── Inline DB-blob attachments (v5.12) ─────────────────────────────────
|
|
164
|
+
//
|
|
165
|
+
// Small binary assets (logos, diagrams, screenshots) are stored directly in
|
|
166
|
+
// the memory row's attachment_data column. Because remote sync copies whole
|
|
167
|
+
// rows (the same way it already moves the `embedding` blob), these attachments
|
|
168
|
+
// travel machine-to-machine for free and need no shared filesystem — which is
|
|
169
|
+
// exactly what a dockerized MCP server needs.
|
|
170
|
+
/**
|
|
171
|
+
* Maximum size for an inline DB-blob attachment. Larger files should use the
|
|
172
|
+
* filesystem path (`gnosys ingest`) so the synced central DB stays lean.
|
|
173
|
+
*/
|
|
174
|
+
export const MAX_INLINE_ATTACHMENT_BYTES = 10 * 1024 * 1024; // 10 MB
|
|
175
|
+
/**
|
|
176
|
+
* Read a file and store its bytes inline on a memory row (attachment_data).
|
|
177
|
+
* Enforces the size cap and skips the write if the same bytes are already
|
|
178
|
+
* attached (content-hash dedup). Bumps `modified` so remote sync picks it up.
|
|
179
|
+
*/
|
|
180
|
+
export async function attachFileToMemory(db, memoryId, filePath) {
|
|
181
|
+
const mem = db.getMemory(memoryId);
|
|
182
|
+
if (!mem) {
|
|
183
|
+
throw new Error(`Memory not found: ${memoryId}`);
|
|
184
|
+
}
|
|
185
|
+
const stat = await fs.stat(filePath);
|
|
186
|
+
if (stat.size > MAX_INLINE_ATTACHMENT_BYTES) {
|
|
187
|
+
const limitMb = (MAX_INLINE_ATTACHMENT_BYTES / (1024 * 1024)).toFixed(0);
|
|
188
|
+
const sizeMb = (stat.size / (1024 * 1024)).toFixed(1);
|
|
189
|
+
throw new Error(`File is ${sizeMb}MB, which exceeds the ${limitMb}MB inline-attachment limit. ` +
|
|
190
|
+
`Use 'gnosys ingest' for large media (it stores the file on disk instead).`);
|
|
191
|
+
}
|
|
192
|
+
const data = await fs.readFile(filePath);
|
|
193
|
+
const name = path.basename(filePath);
|
|
194
|
+
const mime = inferMimeType(filePath);
|
|
195
|
+
// Dedup: if the same bytes are already attached, skip the write.
|
|
196
|
+
if (mem.attachment_data && Buffer.from(mem.attachment_data).equals(data)) {
|
|
197
|
+
return { memoryId, name, mime, sizeBytes: data.length, unchanged: true };
|
|
198
|
+
}
|
|
199
|
+
db.updateMemory(memoryId, {
|
|
200
|
+
attachment_data: data,
|
|
201
|
+
attachment_mime: mime,
|
|
202
|
+
attachment_name: name,
|
|
203
|
+
modified: new Date().toISOString(),
|
|
204
|
+
});
|
|
205
|
+
return { memoryId, name, mime, sizeBytes: data.length, unchanged: false };
|
|
206
|
+
}
|
|
207
|
+
/** Return the inline attachment stored on a memory row, or null if none. */
|
|
208
|
+
export function getMemoryAttachment(db, memoryId) {
|
|
209
|
+
const mem = db.getMemory(memoryId);
|
|
210
|
+
if (!mem?.attachment_data)
|
|
211
|
+
return null;
|
|
212
|
+
const data = Buffer.from(mem.attachment_data);
|
|
213
|
+
return {
|
|
214
|
+
data,
|
|
215
|
+
mime: mem.attachment_mime || "application/octet-stream",
|
|
216
|
+
name: mem.attachment_name || `${memoryId}.bin`,
|
|
217
|
+
sizeBytes: data.length,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/** Remove an inline attachment from a memory row (keeps the memory itself). */
|
|
221
|
+
export function detachFromMemory(db, memoryId) {
|
|
222
|
+
const mem = db.getMemory(memoryId);
|
|
223
|
+
if (!mem?.attachment_data)
|
|
224
|
+
return false;
|
|
225
|
+
db.updateMemory(memoryId, {
|
|
226
|
+
attachment_data: null,
|
|
227
|
+
attachment_mime: null,
|
|
228
|
+
attachment_name: null,
|
|
229
|
+
modified: new Date().toISOString(),
|
|
230
|
+
});
|
|
231
|
+
return true;
|
|
232
|
+
}
|
package/dist/lib/audioExtract.js
CHANGED
|
@@ -71,7 +71,10 @@ async function transcribeWithOpenAI(audioBuffer, fileName, mimeType, apiKey, opt
|
|
|
71
71
|
async function transcribeWithLocal(filePath, options) {
|
|
72
72
|
let pipeline;
|
|
73
73
|
try {
|
|
74
|
-
// Dynamic import — @huggingface/transformers is an optional dependency
|
|
74
|
+
// Dynamic import — @huggingface/transformers is an optional dependency.
|
|
75
|
+
// Cast to any so TypeScript does not require the module's type declarations
|
|
76
|
+
// at compile time (the package is optional; CI and clean checkouts may not
|
|
77
|
+
// have it installed when running `tsc` / `npm run build`).
|
|
75
78
|
const transformers = await import("@huggingface/transformers");
|
|
76
79
|
pipeline = transformers.pipeline;
|
|
77
80
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GnosysDB } from "./db.js";
|
|
2
|
+
export async function runAuditCommand(opts) {
|
|
3
|
+
const { readAuditFromDb, formatAuditTimeline } = await import("./audit.js");
|
|
4
|
+
let centralDb = null;
|
|
5
|
+
try {
|
|
6
|
+
centralDb = GnosysDB.openCentral();
|
|
7
|
+
if (!centralDb.isAvailable()) {
|
|
8
|
+
console.error("Central DB unavailable.");
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const entries = readAuditFromDb(centralDb, {
|
|
13
|
+
days: parseInt(opts.days, 10),
|
|
14
|
+
operation: opts.operation,
|
|
15
|
+
limit: opts.limit ? parseInt(opts.limit, 10) : undefined,
|
|
16
|
+
});
|
|
17
|
+
if (opts.json) {
|
|
18
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
console.log(formatAuditTimeline(entries));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
centralDb?.close();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { copyFileSync, existsSync } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { GnosysDB } from "./db.js";
|
|
4
|
+
export async function runBackupCommand(opts) {
|
|
5
|
+
let centralDb = null;
|
|
6
|
+
try {
|
|
7
|
+
centralDb = GnosysDB.openCentral();
|
|
8
|
+
if (!centralDb.isAvailable()) {
|
|
9
|
+
console.error("Central DB not available (better-sqlite3 missing).");
|
|
10
|
+
process.exitCode = 1;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const outputDir = opts.to || opts.output;
|
|
14
|
+
const backupPath = await centralDb.backup(outputDir);
|
|
15
|
+
const counts = centralDb.getMemoryCount();
|
|
16
|
+
const projectCount = centralDb.getAllProjects().length;
|
|
17
|
+
const centralDir = GnosysDB.getCentralDbDir();
|
|
18
|
+
const copiedFiles = [backupPath];
|
|
19
|
+
const backupDir = path.dirname(backupPath);
|
|
20
|
+
const sandboxLog = path.join(centralDir, "sandbox", "sandbox.log");
|
|
21
|
+
if (existsSync(sandboxLog)) {
|
|
22
|
+
const logDest = path.join(backupDir, "sandbox.log.bak");
|
|
23
|
+
copyFileSync(sandboxLog, logDest);
|
|
24
|
+
copiedFiles.push(logDest);
|
|
25
|
+
}
|
|
26
|
+
if (opts.json) {
|
|
27
|
+
console.log(JSON.stringify({
|
|
28
|
+
ok: true, backupPath, memories: counts.total,
|
|
29
|
+
active: counts.active, archived: counts.archived,
|
|
30
|
+
projects: projectCount, files: copiedFiles,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.log(`Backup created: ${backupPath}`);
|
|
35
|
+
console.log(` Memories: ${counts.total} (${counts.active} active, ${counts.archived} archived)`);
|
|
36
|
+
console.log(` Projects: ${projectCount}`);
|
|
37
|
+
if (copiedFiles.length > 1)
|
|
38
|
+
console.log(` Additional files: ${copiedFiles.length - 1}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (opts.json) {
|
|
43
|
+
console.log(JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
console.error(`Backup failed: ${err instanceof Error ? err.message : err}`);
|
|
47
|
+
}
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
centralDb?.close();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GnosysResolver } from "./resolver.js";
|
|
2
|
+
export type BootstrapCommandOptions = {
|
|
3
|
+
pattern?: string[];
|
|
4
|
+
skipExisting?: boolean;
|
|
5
|
+
category: string;
|
|
6
|
+
author: string;
|
|
7
|
+
authority: string;
|
|
8
|
+
confidence: string;
|
|
9
|
+
preserveFrontmatter?: boolean;
|
|
10
|
+
dryRun?: boolean;
|
|
11
|
+
store?: string;
|
|
12
|
+
};
|
|
13
|
+
type GetResolver = () => Promise<GnosysResolver>;
|
|
14
|
+
export declare function runBootstrapCommand(getResolver: GetResolver, sourceDir: string, opts: BootstrapCommandOptions): Promise<void>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export async function runBootstrapCommand(getResolver, sourceDir, opts) {
|
|
2
|
+
const resolver = await getResolver();
|
|
3
|
+
const writeTarget = resolver.getWriteTarget(opts.store || undefined);
|
|
4
|
+
if (!writeTarget) {
|
|
5
|
+
console.error("No writable store found.");
|
|
6
|
+
process.exit(1);
|
|
7
|
+
}
|
|
8
|
+
// Show what we'll scan
|
|
9
|
+
const { bootstrap, discoverFiles } = await import("./bootstrap.js");
|
|
10
|
+
const files = await discoverFiles(sourceDir, opts.pattern);
|
|
11
|
+
console.log(`Found ${files.length} files in ${sourceDir}\n`);
|
|
12
|
+
if (files.length === 0) {
|
|
13
|
+
console.log("Nothing to import.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const result = await bootstrap(writeTarget.store, {
|
|
17
|
+
sourceDir,
|
|
18
|
+
patterns: opts.pattern,
|
|
19
|
+
skipExisting: opts.skipExisting,
|
|
20
|
+
defaultCategory: opts.category,
|
|
21
|
+
defaultAuthor: opts.author,
|
|
22
|
+
defaultAuthority: opts.authority,
|
|
23
|
+
defaultConfidence: parseFloat(opts.confidence),
|
|
24
|
+
preserveFrontmatter: opts.preserveFrontmatter,
|
|
25
|
+
dryRun: opts.dryRun,
|
|
26
|
+
});
|
|
27
|
+
const mode = opts.dryRun ? "DRY RUN" : "COMPLETE";
|
|
28
|
+
console.log(`\nBootstrap ${mode}:`);
|
|
29
|
+
console.log(` Scanned: ${result.totalScanned}`);
|
|
30
|
+
console.log(` ${opts.dryRun ? "Would import" : "Imported"}: ${result.imported.length}`);
|
|
31
|
+
console.log(` Skipped: ${result.skipped.length}`);
|
|
32
|
+
console.log(` Failed: ${result.failed.length}`);
|
|
33
|
+
if (result.imported.length > 0) {
|
|
34
|
+
console.log(`\n${opts.dryRun ? "Would import" : "Imported"}:`);
|
|
35
|
+
for (const f of result.imported) {
|
|
36
|
+
console.log(` + ${f}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (result.skipped.length > 0) {
|
|
40
|
+
console.log(`\nSkipped (already exist):`);
|
|
41
|
+
for (const f of result.skipped) {
|
|
42
|
+
console.log(` ⏭ ${f}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (result.failed.length > 0) {
|
|
46
|
+
console.log(`\nFailed:`);
|
|
47
|
+
for (const f of result.failed) {
|
|
48
|
+
console.log(` ❌ ${f.path}: ${f.error}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { GnosysDB } from "./db.js";
|
|
2
|
+
export async function runBriefingCommand(projectNameOrId, opts) {
|
|
3
|
+
let centralDb = null;
|
|
4
|
+
try {
|
|
5
|
+
centralDb = GnosysDB.openCentral();
|
|
6
|
+
if (!centralDb.isAvailable()) {
|
|
7
|
+
console.error("Central DB not available.");
|
|
8
|
+
process.exitCode = 1;
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const { generateBriefing, generateAllBriefings, detectCurrentProject } = await import("./federated.js");
|
|
12
|
+
if (opts.all) {
|
|
13
|
+
const briefings = generateAllBriefings(centralDb);
|
|
14
|
+
if (opts.json) {
|
|
15
|
+
console.log(JSON.stringify({ count: briefings.length, briefings }, null, 2));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
if (briefings.length === 0) {
|
|
19
|
+
console.log("No projects registered.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const b of briefings) {
|
|
23
|
+
console.log(`\n## ${b.projectName}`);
|
|
24
|
+
console.log(b.summary);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// v5.7.0: accept project name as positional argument in addition to --project <id>.
|
|
30
|
+
// Resolution order: positional name → --project flag → cwd auto-detect.
|
|
31
|
+
let pid = opts.project ?? null;
|
|
32
|
+
if (!pid && projectNameOrId) {
|
|
33
|
+
const byId = centralDb.getProject(projectNameOrId);
|
|
34
|
+
if (byId) {
|
|
35
|
+
pid = byId.id;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const all = centralDb.getAllProjects();
|
|
39
|
+
const byName = all.find((p) => p.name === projectNameOrId);
|
|
40
|
+
if (byName)
|
|
41
|
+
pid = byName.id;
|
|
42
|
+
}
|
|
43
|
+
if (!pid) {
|
|
44
|
+
console.error(`Project not found: "${projectNameOrId}". Run 'gnosys projects' to list registered projects.`);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!pid)
|
|
50
|
+
pid = await detectCurrentProject(centralDb, opts.directory || undefined);
|
|
51
|
+
if (!pid) {
|
|
52
|
+
console.error("No project specified and none detected.");
|
|
53
|
+
process.exitCode = 1;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const briefing = generateBriefing(centralDb, pid);
|
|
57
|
+
if (!briefing) {
|
|
58
|
+
console.error(`Project not found: ${pid}`);
|
|
59
|
+
process.exitCode = 1;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (opts.json) {
|
|
63
|
+
console.log(JSON.stringify(briefing, null, 2));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log(`# Briefing: ${briefing.projectName}`);
|
|
67
|
+
console.log(`Directory: ${briefing.workingDirectory}`);
|
|
68
|
+
console.log(`Active memories: ${briefing.activeMemories} / ${briefing.totalMemories}`);
|
|
69
|
+
console.log(`\nCategories:`);
|
|
70
|
+
for (const [cat, count] of Object.entries(briefing.categories).sort((a, b) => b[1] - a[1])) {
|
|
71
|
+
console.log(` ${cat}: ${count}`);
|
|
72
|
+
}
|
|
73
|
+
console.log(`\nRecent activity (7d):`);
|
|
74
|
+
if (briefing.recentActivity.length === 0) {
|
|
75
|
+
console.log(" None");
|
|
76
|
+
}
|
|
77
|
+
for (const r of briefing.recentActivity) {
|
|
78
|
+
console.log(` - ${r.title} (${r.modified})`);
|
|
79
|
+
}
|
|
80
|
+
console.log(`\nTop tags: ${briefing.topTags.slice(0, 10).map((t) => `${t.tag}(${t.count})`).join(", ") || "None"}`);
|
|
81
|
+
console.log(`\n${briefing.summary}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
86
|
+
process.exitCode = 1;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
centralDb?.close();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { centralizeDb } from "./centralize.js";
|
|
2
|
+
export async function runCentralizeCommand(opts) {
|
|
3
|
+
try {
|
|
4
|
+
const r = await centralizeDb({ to: opts.to, force: opts.force });
|
|
5
|
+
const mb = (r.bytes / 1024 / 1024).toFixed(1);
|
|
6
|
+
console.log("✓ Seeded central brain:");
|
|
7
|
+
console.log(` from: ${r.source}`);
|
|
8
|
+
console.log(` to: ${r.target} (${mb} MB)`);
|
|
9
|
+
console.log("");
|
|
10
|
+
console.log(`Run the server against it with GNOSYS_HOME=${opts.to}, or mount this dir as the container's /data volume.`);
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
console.error(`centralize failed: ${e instanceof Error ? e.message : e}`);
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
}
|
|
16
|
+
}
|
package/dist/lib/chat/choose.js
CHANGED
|
@@ -115,7 +115,7 @@ export function parseChooseYaml(yaml) {
|
|
|
115
115
|
const itemStart = line.match(/^\s*-\s*id:\s*(.+?)\s*$/);
|
|
116
116
|
if (itemStart) {
|
|
117
117
|
// Push previous item if any
|
|
118
|
-
if (current
|
|
118
|
+
if (current?.label)
|
|
119
119
|
options.push(current);
|
|
120
120
|
current = { id: itemStart[1], label: "" };
|
|
121
121
|
continue;
|
|
@@ -133,7 +133,7 @@ export function parseChooseYaml(yaml) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
// Flush the last option
|
|
136
|
-
if (current
|
|
136
|
+
if (current?.label)
|
|
137
137
|
options.push(current);
|
|
138
138
|
return { prompt, options };
|
|
139
139
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GnosysResolver } from "./resolver.js";
|
|
2
|
+
export type ChatCommandOptions = {
|
|
3
|
+
resume?: string;
|
|
4
|
+
list?: boolean;
|
|
5
|
+
search?: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
model?: string;
|
|
8
|
+
limit: string;
|
|
9
|
+
};
|
|
10
|
+
type GetResolver = () => Promise<GnosysResolver>;
|
|
11
|
+
export declare function runChatCommand(getResolver: GetResolver, opts: ChatCommandOptions): Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DEFAULT_CONFIG, loadConfig, resolveTaskModel, } from "./config.js";
|
|
2
|
+
export async function runChatCommand(getResolver, opts) {
|
|
3
|
+
const limit = parseInt(opts.limit, 10) || 20;
|
|
4
|
+
const chat = await import("./chat/index.js");
|
|
5
|
+
if (opts.list) {
|
|
6
|
+
chat.printSessionList(limit);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (opts.search) {
|
|
10
|
+
chat.printSearchResults(opts.search, limit);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const resolver = await getResolver();
|
|
14
|
+
const stores = resolver.getStores();
|
|
15
|
+
const storePath = stores[0]?.path ?? process.cwd();
|
|
16
|
+
let cliConfig;
|
|
17
|
+
try {
|
|
18
|
+
cliConfig = await loadConfig(storePath);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
cliConfig = DEFAULT_CONFIG;
|
|
22
|
+
}
|
|
23
|
+
// Fail-fast on missing API key before TUI render.
|
|
24
|
+
{
|
|
25
|
+
const chatTask = resolveTaskModel(cliConfig, "chat");
|
|
26
|
+
const provider = opts.provider ?? chatTask.provider;
|
|
27
|
+
if (provider !== "ollama" && provider !== "lmstudio") {
|
|
28
|
+
const { getApiKeyForProvider } = await import("./setup.js");
|
|
29
|
+
const key = await getApiKeyForProvider(provider);
|
|
30
|
+
if (!key) {
|
|
31
|
+
const { Status } = await import("./setup/ui/status.js");
|
|
32
|
+
const envVar = `${provider.toUpperCase()}_API_KEY`;
|
|
33
|
+
process.stderr.write(`${Status("fail", `no API key for ${provider} (the configured chat provider)`)}\n`);
|
|
34
|
+
process.stderr.write(` fix: gnosys setup pick a provider with a key, or add one\n`);
|
|
35
|
+
process.stderr.write(` export ${envVar}=...\n`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
await chat.startChat({
|
|
41
|
+
config: cliConfig,
|
|
42
|
+
resume: opts.resume,
|
|
43
|
+
providerName: opts.provider,
|
|
44
|
+
modelName: opts.model,
|
|
45
|
+
});
|
|
46
|
+
}
|