@gobi-ai/cli 0.6.3 → 0.6.5
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/attachments.js +32 -3
- package/dist/commands/brain.js +1 -1
- package/dist/commands/space.js +1 -1
- package/dist/commands/sync.js +38 -0
- package/package.json +2 -1
- package/skills/gobi/SKILL.md +2 -2
package/dist/attachments.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "fs";
|
|
1
|
+
import { existsSync, readFileSync, appendFileSync } from "fs";
|
|
2
2
|
import { join, extname } from "path";
|
|
3
|
+
import ignore from "ignore";
|
|
3
4
|
import { WEBDRIVE_BASE_URL } from "./constants.js";
|
|
4
5
|
export function extractWikiLinks(content) {
|
|
5
6
|
const seen = new Set();
|
|
@@ -13,7 +14,31 @@ export function extractWikiLinks(content) {
|
|
|
13
14
|
}
|
|
14
15
|
return results;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
function readSyncfilesPatterns(gobiDir) {
|
|
18
|
+
const syncfilesPath = join(gobiDir, "syncfiles");
|
|
19
|
+
if (!existsSync(syncfilesPath))
|
|
20
|
+
return [];
|
|
21
|
+
return readFileSync(syncfilesPath, "utf-8")
|
|
22
|
+
.split("\n")
|
|
23
|
+
.map((l) => l.trim())
|
|
24
|
+
.filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
25
|
+
}
|
|
26
|
+
function isPathCovered(filePath, patterns) {
|
|
27
|
+
if (patterns.length === 0)
|
|
28
|
+
return false;
|
|
29
|
+
return ignore().add(patterns).ignores(filePath.replace(/\\/g, "/"));
|
|
30
|
+
}
|
|
31
|
+
function addToLocalSyncfiles(gobiDir, filePath) {
|
|
32
|
+
const patterns = readSyncfilesPatterns(gobiDir);
|
|
33
|
+
if (isPathCovered(filePath, patterns))
|
|
34
|
+
return;
|
|
35
|
+
const syncfilesPath = join(gobiDir, "syncfiles");
|
|
36
|
+
appendFileSync(syncfilesPath, `\n${filePath}`);
|
|
37
|
+
console.log(`Added to syncfiles: ${filePath}`);
|
|
38
|
+
}
|
|
39
|
+
export async function uploadAttachments(vaultSlug, links, token, options) {
|
|
40
|
+
const addToSyncfiles = options?.addToSyncfiles ?? false;
|
|
41
|
+
const gobiDir = join(process.cwd(), ".gobi");
|
|
17
42
|
for (const link of links) {
|
|
18
43
|
let localPath = join(process.cwd(), link);
|
|
19
44
|
if (!existsSync(localPath)) {
|
|
@@ -28,7 +53,8 @@ export async function uploadAttachments(vaultSlug, links, token) {
|
|
|
28
53
|
const filePath = extname(link) ? link : link + ".md";
|
|
29
54
|
console.log(`Uploading [[${link}]]...`);
|
|
30
55
|
const content = readFileSync(localPath);
|
|
31
|
-
const
|
|
56
|
+
const queryString = addToSyncfiles ? "?add_to_syncfiles=true" : "";
|
|
57
|
+
const url = `${WEBDRIVE_BASE_URL}/api/v1/vaults/${vaultSlug}/files/${filePath}${queryString}`;
|
|
32
58
|
const res = await fetch(url, {
|
|
33
59
|
method: "PUT",
|
|
34
60
|
headers: {
|
|
@@ -41,5 +67,8 @@ export async function uploadAttachments(vaultSlug, links, token) {
|
|
|
41
67
|
throw new Error(`Failed to upload [[${link}]]: HTTP ${res.status}: ${(await res.text()) || "(no body)"}`);
|
|
42
68
|
}
|
|
43
69
|
console.log(`Uploaded [[${link}]]`);
|
|
70
|
+
if (addToSyncfiles) {
|
|
71
|
+
addToLocalSyncfiles(gobiDir, filePath);
|
|
72
|
+
}
|
|
44
73
|
}
|
|
45
74
|
}
|
package/dist/commands/brain.js
CHANGED
|
@@ -198,7 +198,7 @@ export function registerBrainCommand(program) {
|
|
|
198
198
|
if (opts.autoAttachments) {
|
|
199
199
|
const token = await getValidToken();
|
|
200
200
|
const links = extractWikiLinks(opts.content);
|
|
201
|
-
await uploadAttachments(vaultSlug, links, token);
|
|
201
|
+
await uploadAttachments(vaultSlug, links, token, { addToSyncfiles: true });
|
|
202
202
|
}
|
|
203
203
|
const resp = (await apiPost(`/brain-updates/vault/${vaultSlug}`, {
|
|
204
204
|
title: opts.title,
|
package/dist/commands/space.js
CHANGED
|
@@ -154,7 +154,7 @@ export function registerSpaceCommand(program) {
|
|
|
154
154
|
const vaultSlug = resolveVaultSlug(opts);
|
|
155
155
|
const token = await getValidToken();
|
|
156
156
|
const links = extractWikiLinks(content);
|
|
157
|
-
await uploadAttachments(vaultSlug, links, token);
|
|
157
|
+
await uploadAttachments(vaultSlug, links, token, { addToSyncfiles: true });
|
|
158
158
|
}
|
|
159
159
|
const spaceSlug = resolveSpaceSlug(space);
|
|
160
160
|
const resp = (await apiPost(`/spaces/${spaceSlug}/threads`, {
|
package/dist/commands/sync.js
CHANGED
|
@@ -148,6 +148,15 @@ export function readSyncfiles(gobiDir) {
|
|
|
148
148
|
const contentHash = createHash("md5").update(content).digest("hex");
|
|
149
149
|
return { patterns, contentHash };
|
|
150
150
|
}
|
|
151
|
+
export function readPrivatefiles(gobiDir) {
|
|
152
|
+
const path = join(gobiDir, "privatefiles");
|
|
153
|
+
if (!existsSync(path))
|
|
154
|
+
return [];
|
|
155
|
+
return readFileSync(path, "utf-8")
|
|
156
|
+
.split("\n")
|
|
157
|
+
.map((l) => l.trim())
|
|
158
|
+
.filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
159
|
+
}
|
|
151
160
|
export function buildWhitelistMatcher(patterns) {
|
|
152
161
|
if (patterns.length === 0)
|
|
153
162
|
return () => false;
|
|
@@ -273,6 +282,21 @@ async function webdriveSync(baseUrl, vaultSlug, body, token) {
|
|
|
273
282
|
}
|
|
274
283
|
return (await res.json());
|
|
275
284
|
}
|
|
285
|
+
async function webdrivePrivatefiles(baseUrl, vaultSlug, patterns, token) {
|
|
286
|
+
const url = `${baseUrl}/api/v1/vaults/${vaultSlug}/privatefiles`;
|
|
287
|
+
const res = await fetch(url, {
|
|
288
|
+
method: "POST",
|
|
289
|
+
headers: {
|
|
290
|
+
Authorization: `Bearer ${token}`,
|
|
291
|
+
"Content-Type": "application/json",
|
|
292
|
+
},
|
|
293
|
+
body: JSON.stringify({ patterns }),
|
|
294
|
+
});
|
|
295
|
+
if (!res.ok) {
|
|
296
|
+
throw new Error(`Privatefiles request failed: HTTP ${res.status}: ${await res.text()}`);
|
|
297
|
+
}
|
|
298
|
+
return (await res.json());
|
|
299
|
+
}
|
|
276
300
|
// ─── Conflict Resolution ──────────────────────────────────────────────────────
|
|
277
301
|
function formatDate(ms) {
|
|
278
302
|
return new Date(ms).toLocaleString();
|
|
@@ -346,6 +370,20 @@ export async function runSync(opts) {
|
|
|
346
370
|
console.log("Full sync: ignoring cursor and hash cache.");
|
|
347
371
|
}
|
|
348
372
|
const token = opts.authToken ?? (await getValidToken());
|
|
373
|
+
// Sync privatefiles with server
|
|
374
|
+
if (!opts.dryRun) {
|
|
375
|
+
try {
|
|
376
|
+
const localPrivatePatterns = readPrivatefiles(gobiDir);
|
|
377
|
+
const privateresp = await webdrivePrivatefiles(baseUrl, vaultSlug, localPrivatePatterns, token);
|
|
378
|
+
if (!opts.uploadOnly && privateresp.patterns.length > 0) {
|
|
379
|
+
await writeFile(join(gobiDir, "privatefiles"), privateresp.patterns.join("\n") + "\n");
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
if (!jsonMode)
|
|
384
|
+
console.error(`Warning: Failed to sync privatefiles: ${err.message}`);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
349
387
|
// Read syncfiles whitelist
|
|
350
388
|
const { patterns: currPatterns, contentHash: currSyncfilesHash } = readSyncfiles(gobiDir);
|
|
351
389
|
if (currPatterns.length === 0 && !jsonMode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobi-ai/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "CLI client for the Gobi collaborative knowledge platform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"better-sqlite3": "^12.8.0",
|
|
47
|
+
"chokidar": "^5.0.0",
|
|
47
48
|
"commander": "^12.1.0",
|
|
48
49
|
"ignore": "^7.0.5",
|
|
49
50
|
"inquirer": "^12.3.0",
|
package/skills/gobi/SKILL.md
CHANGED
|
@@ -10,12 +10,12 @@ description: >-
|
|
|
10
10
|
allowed-tools: Bash(gobi:*)
|
|
11
11
|
metadata:
|
|
12
12
|
author: gobi-ai
|
|
13
|
-
version: "0.6.
|
|
13
|
+
version: "0.6.4"
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# gobi-cli
|
|
17
17
|
|
|
18
|
-
A CLI client for the Gobi collaborative knowledge platform (v0.6.
|
|
18
|
+
A CLI client for the Gobi collaborative knowledge platform (v0.6.4).
|
|
19
19
|
|
|
20
20
|
## Prerequisites
|
|
21
21
|
|