@gobi-ai/cli 0.9.13 → 1.1.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/.claude-plugin/marketplace.json +4 -4
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +32 -21
- package/commands/space-explore.md +3 -5
- package/commands/space-share.md +5 -5
- package/dist/commands/global.js +203 -0
- package/dist/commands/init.js +5 -5
- package/dist/commands/space.js +89 -1
- package/dist/commands/vault.js +141 -0
- package/dist/main.js +4 -2
- package/package.json +1 -1
- package/skills/gobi-core/SKILL.md +4 -5
- package/skills/gobi-core/references/space.md +4 -1
- package/skills/gobi-homepage/SKILL.md +19 -125
- package/skills/gobi-space/SKILL.md +31 -6
- package/skills/gobi-space/references/global.md +82 -0
- package/skills/gobi-space/references/space.md +39 -1
- package/skills/gobi-vault/SKILL.md +100 -0
- package/skills/gobi-vault/references/vault.md +66 -0
- package/dist/commands/brain.js +0 -347
- package/skills/gobi-brain/SKILL.md +0 -113
- package/skills/gobi-brain/references/brain.md +0 -181
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# gobi vault
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
Usage: gobi vault [options] [command]
|
|
5
|
+
|
|
6
|
+
Vault commands. A Vault is your personal knowledge container — search public vaults, ask them questions, and publish a PUBLISH.md to make a vault public.
|
|
7
|
+
|
|
8
|
+
Options:
|
|
9
|
+
-h, --help display help for command
|
|
10
|
+
|
|
11
|
+
Commands:
|
|
12
|
+
search [options] Search public vaults by text and semantic similarity.
|
|
13
|
+
ask [options] Ask a vault a question. Creates a targeted session (1:1 conversation).
|
|
14
|
+
publish Upload PUBLISH.md to the vault root on webdrive. Triggers post-processing (vault sync, metadata update, Discord notification).
|
|
15
|
+
unpublish Delete PUBLISH.md from the vault on webdrive.
|
|
16
|
+
help [command] display help for command
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## search
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Usage: gobi vault search [options]
|
|
23
|
+
|
|
24
|
+
Search public vaults by text and semantic similarity.
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--query <query> Search query
|
|
28
|
+
-h, --help display help for command
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## ask
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Usage: gobi vault ask [options]
|
|
35
|
+
|
|
36
|
+
Ask a vault a question. Creates a targeted session (1:1 conversation).
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
--vault-slug <vaultSlug> Slug of the vault to ask
|
|
40
|
+
--question <question> The question to ask (markdown supported)
|
|
41
|
+
--rich-text <richText> Rich-text JSON array (e.g. [{"type":"text","text":"hello"}])
|
|
42
|
+
--mode <mode> Session mode: "auto" or "manual"
|
|
43
|
+
-h, --help display help for command
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## publish
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Usage: gobi vault publish [options]
|
|
50
|
+
|
|
51
|
+
Upload PUBLISH.md to the vault root on webdrive. Triggers post-processing (vault sync, metadata update, Discord notification).
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
-h, --help display help for command
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## unpublish
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
Usage: gobi vault unpublish [options]
|
|
61
|
+
|
|
62
|
+
Delete PUBLISH.md from the vault on webdrive.
|
|
63
|
+
|
|
64
|
+
Options:
|
|
65
|
+
-h, --help display help for command
|
|
66
|
+
```
|
package/dist/commands/brain.js
DELETED
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { apiGet, apiPost, apiPatch, apiDelete } from "../client.js";
|
|
4
|
-
import { WEBDRIVE_BASE_URL } from "../constants.js";
|
|
5
|
-
import { getValidToken } from "../auth/manager.js";
|
|
6
|
-
import { getVaultSlug } from "./init.js";
|
|
7
|
-
import { isJsonMode, jsonOut, resolveVaultSlug, unwrapResp } from "./utils.js";
|
|
8
|
-
import { extractWikiLinks, uploadAttachments } from "../attachments.js";
|
|
9
|
-
export function registerBrainCommand(program) {
|
|
10
|
-
const brain = program
|
|
11
|
-
.command("brain")
|
|
12
|
-
.description("Brain commands (search, ask, publish, unpublish, updates).");
|
|
13
|
-
// ── Search ──
|
|
14
|
-
brain
|
|
15
|
-
.command("search")
|
|
16
|
-
.description("Search public brains by text and semantic similarity.")
|
|
17
|
-
.requiredOption("--query <query>", "Search query")
|
|
18
|
-
.action(async (opts) => {
|
|
19
|
-
const resp = (await apiGet(`/vault/public/search`, {
|
|
20
|
-
query: opts.query,
|
|
21
|
-
}));
|
|
22
|
-
const results = (Array.isArray(resp) ? resp : resp.data || resp);
|
|
23
|
-
if (isJsonMode(brain)) {
|
|
24
|
-
jsonOut(results || []);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (!results || results.length === 0) {
|
|
28
|
-
console.log(`No brains found matching "${opts.query}".`);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
const lines = [];
|
|
32
|
-
for (const entry of results) {
|
|
33
|
-
const vault = (entry.vault || entry);
|
|
34
|
-
const owner = (entry.owner || {});
|
|
35
|
-
const ownerName = owner.name ? ` by ${owner.name}` : "";
|
|
36
|
-
const sim = entry.similarity != null
|
|
37
|
-
? ` [similarity: ${entry.similarity.toFixed(3)}]`
|
|
38
|
-
: "";
|
|
39
|
-
const spaceSlug = (entry.spaceSlug || vault.spaceSlug || "");
|
|
40
|
-
const vaultSlug = (vault.slug || vault.vaultSlug || vault.id || "N/A");
|
|
41
|
-
lines.push(`- ${vault.name || vault.title || "N/A"} (vault: ${vaultSlug}, space: ${spaceSlug || "N/A"})${ownerName}${sim}`);
|
|
42
|
-
}
|
|
43
|
-
console.log(`Brains matching "${opts.query}":\n` + lines.join("\n"));
|
|
44
|
-
});
|
|
45
|
-
// ── Ask ──
|
|
46
|
-
brain
|
|
47
|
-
.command("ask")
|
|
48
|
-
.description("Ask a brain a question. Creates a targeted session (1:1 conversation).")
|
|
49
|
-
.requiredOption("--vault-slug <vaultSlug>", "Slug of the brain/vault to ask")
|
|
50
|
-
.option("--question <question>", "The question to ask (markdown supported)")
|
|
51
|
-
.option("--rich-text <richText>", "Rich-text JSON array (e.g. [{\"type\":\"text\",\"text\":\"hello\"}])")
|
|
52
|
-
.option("--mode <mode>", 'Session mode: "auto" or "manual"')
|
|
53
|
-
.action(async (opts) => {
|
|
54
|
-
if (!opts.question && !opts.richText) {
|
|
55
|
-
throw new Error("Provide either --question or --rich-text.");
|
|
56
|
-
}
|
|
57
|
-
if (opts.question && opts.richText) {
|
|
58
|
-
throw new Error("--question and --rich-text are mutually exclusive.");
|
|
59
|
-
}
|
|
60
|
-
const body = {
|
|
61
|
-
vaultSlug: opts.vaultSlug,
|
|
62
|
-
};
|
|
63
|
-
if (opts.question != null)
|
|
64
|
-
body.question = opts.question;
|
|
65
|
-
if (opts.richText != null) {
|
|
66
|
-
let parsed;
|
|
67
|
-
try {
|
|
68
|
-
parsed = JSON.parse(opts.richText);
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
throw new Error("Invalid --rich-text JSON.");
|
|
72
|
-
}
|
|
73
|
-
body.richText = parsed;
|
|
74
|
-
}
|
|
75
|
-
if (opts.mode != null)
|
|
76
|
-
body.mode = opts.mode;
|
|
77
|
-
const resp = (await apiPost(`/chat/targeted`, body));
|
|
78
|
-
const data = unwrapResp(resp);
|
|
79
|
-
if (isJsonMode(brain)) {
|
|
80
|
-
jsonOut(data);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const session = (data.session || {});
|
|
84
|
-
const members = (data.members || []);
|
|
85
|
-
console.log(`Session created!\n` +
|
|
86
|
-
` Session ID: ${session.id}\n` +
|
|
87
|
-
` Mode: ${session.mode}\n` +
|
|
88
|
-
` Members: ${members.length}\n` +
|
|
89
|
-
` Question sent.`);
|
|
90
|
-
});
|
|
91
|
-
// ── Publish ──
|
|
92
|
-
brain
|
|
93
|
-
.command("publish")
|
|
94
|
-
.description("Upload BRAIN.md to the vault root on webdrive. Triggers post-processing (brain sync, metadata update, Discord notification).")
|
|
95
|
-
.action(async () => {
|
|
96
|
-
const vaultId = getVaultSlug();
|
|
97
|
-
const filePath = join(process.cwd(), "BRAIN.md");
|
|
98
|
-
if (!existsSync(filePath)) {
|
|
99
|
-
throw new Error(`BRAIN.md not found in ${process.cwd()}`);
|
|
100
|
-
}
|
|
101
|
-
const content = readFileSync(filePath, "utf-8");
|
|
102
|
-
const token = await getValidToken();
|
|
103
|
-
const url = `${WEBDRIVE_BASE_URL}/api/v1/vaults/${vaultId}/file/BRAIN.md`;
|
|
104
|
-
const res = await fetch(url, {
|
|
105
|
-
method: "PUT",
|
|
106
|
-
headers: {
|
|
107
|
-
Authorization: `Bearer ${token}`,
|
|
108
|
-
"Content-Type": "text/markdown",
|
|
109
|
-
},
|
|
110
|
-
body: content,
|
|
111
|
-
});
|
|
112
|
-
if (!res.ok) {
|
|
113
|
-
throw new Error(`Upload failed: HTTP ${res.status}: ${(await res.text()) || "(no body)"}`);
|
|
114
|
-
}
|
|
115
|
-
if (isJsonMode(brain)) {
|
|
116
|
-
jsonOut({ vaultId });
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
console.log(`Published BRAIN.md to vault "${vaultId}"`);
|
|
120
|
-
});
|
|
121
|
-
// ── Unpublish ──
|
|
122
|
-
brain
|
|
123
|
-
.command("unpublish")
|
|
124
|
-
.description("Delete BRAIN.md from the vault on webdrive.")
|
|
125
|
-
.action(async () => {
|
|
126
|
-
const vaultId = getVaultSlug();
|
|
127
|
-
const token = await getValidToken();
|
|
128
|
-
const url = `${WEBDRIVE_BASE_URL}/api/v1/vaults/${vaultId}/file/BRAIN.md`;
|
|
129
|
-
const res = await fetch(url, {
|
|
130
|
-
method: "DELETE",
|
|
131
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
132
|
-
});
|
|
133
|
-
if (!res.ok) {
|
|
134
|
-
throw new Error(`Delete failed: HTTP ${res.status}: ${(await res.text()) || "(no body)"}`);
|
|
135
|
-
}
|
|
136
|
-
if (isJsonMode(brain)) {
|
|
137
|
-
jsonOut({ vaultId });
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
console.log(`Deleted BRAIN.md from vault "${vaultId}"`);
|
|
141
|
-
});
|
|
142
|
-
// ── Updates (list, post, edit, delete) ──
|
|
143
|
-
brain
|
|
144
|
-
.command("list-updates")
|
|
145
|
-
.description("List recent brain updates. Without --space-slug, lists all updates for you. With --space-slug, lists updates for that space. Use --mine to show only updates by you.")
|
|
146
|
-
.option("--vault-slug <vaultSlug>", "Vault slug (overrides .gobi/settings.yaml)")
|
|
147
|
-
.option("--space-slug <spaceSlug>", "List updates for a space")
|
|
148
|
-
.option("--mine", "List only my own brain updates")
|
|
149
|
-
.option("--limit <number>", "Items per page", "20")
|
|
150
|
-
.option("--cursor <string>", "Pagination cursor from previous response")
|
|
151
|
-
.action(async (opts) => {
|
|
152
|
-
const params = {
|
|
153
|
-
limit: parseInt(opts.limit, 10),
|
|
154
|
-
};
|
|
155
|
-
if (opts.cursor)
|
|
156
|
-
params.cursor = opts.cursor;
|
|
157
|
-
if (opts.mine)
|
|
158
|
-
params.mine = true;
|
|
159
|
-
if (opts.vaultSlug)
|
|
160
|
-
params.vaultSlug = opts.vaultSlug;
|
|
161
|
-
const path = opts.spaceSlug
|
|
162
|
-
? `/spaces/${opts.spaceSlug}/brain-updates`
|
|
163
|
-
: `/brain-updates`;
|
|
164
|
-
const resp = (await apiGet(path, params));
|
|
165
|
-
if (isJsonMode(brain)) {
|
|
166
|
-
jsonOut({
|
|
167
|
-
items: resp.data || [],
|
|
168
|
-
pagination: resp.pagination || {},
|
|
169
|
-
});
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const items = (resp.data || []);
|
|
173
|
-
const pagination = (resp.pagination || {});
|
|
174
|
-
if (!items.length) {
|
|
175
|
-
console.log("No brain updates found.");
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const lines = [];
|
|
179
|
-
for (const u of items) {
|
|
180
|
-
const author = u.author?.name ||
|
|
181
|
-
`User ${u.authorId}`;
|
|
182
|
-
const vaultSlug = u.vault?.vaultSlug ||
|
|
183
|
-
"?";
|
|
184
|
-
lines.push(`- [${u.id}] "${u.title}" by ${author} (vault: ${vaultSlug}, ${u.createdAt})`);
|
|
185
|
-
}
|
|
186
|
-
const footer = pagination.hasMore ? `\n Next cursor: ${pagination.nextCursor}` : "";
|
|
187
|
-
console.log(`Brain updates (${items.length} items):\n` + lines.join("\n") + footer);
|
|
188
|
-
});
|
|
189
|
-
brain
|
|
190
|
-
.command("post-update")
|
|
191
|
-
.description("Post a brain update for a vault.")
|
|
192
|
-
.option("--vault-slug <vaultSlug>", "Vault slug (overrides .gobi/settings.yaml)")
|
|
193
|
-
.requiredOption("--title <title>", "Title of the update")
|
|
194
|
-
.requiredOption("--content <content>", "Update content (markdown supported)")
|
|
195
|
-
.option("--auto-attachments", "Upload wiki-linked [[files]] to webdrive before posting")
|
|
196
|
-
.action(async (opts) => {
|
|
197
|
-
const vaultSlug = resolveVaultSlug(opts);
|
|
198
|
-
if (opts.autoAttachments) {
|
|
199
|
-
const token = await getValidToken();
|
|
200
|
-
const links = extractWikiLinks(opts.content);
|
|
201
|
-
await uploadAttachments(vaultSlug, links, token, { addToSyncfiles: true });
|
|
202
|
-
}
|
|
203
|
-
const resp = (await apiPost(`/brain-updates/vault/${vaultSlug}`, {
|
|
204
|
-
title: opts.title,
|
|
205
|
-
content: opts.content,
|
|
206
|
-
}));
|
|
207
|
-
const u = unwrapResp(resp);
|
|
208
|
-
if (isJsonMode(brain)) {
|
|
209
|
-
jsonOut(u);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
console.log(`Brain update posted!\n` +
|
|
213
|
-
` ID: ${u.id}\n` +
|
|
214
|
-
` Title: ${u.title}\n` +
|
|
215
|
-
` Vault: ${u.vaultSlug || vaultSlug}\n` +
|
|
216
|
-
` Created: ${u.createdAt}`);
|
|
217
|
-
});
|
|
218
|
-
brain
|
|
219
|
-
.command("edit-update <updateId>")
|
|
220
|
-
.description("Edit a published brain update. You must be the author.")
|
|
221
|
-
.option("--title <title>", "New title for the update")
|
|
222
|
-
.option("--content <content>", "New content for the update (markdown supported)")
|
|
223
|
-
.option("--vault-slug <vaultSlug>", "Vault slug for attachment uploads (overrides .gobi/settings.yaml)")
|
|
224
|
-
.option("--auto-attachments", "Upload wiki-linked [[files]] to webdrive before editing")
|
|
225
|
-
.action(async (updateId, opts) => {
|
|
226
|
-
if (!opts.title && !opts.content) {
|
|
227
|
-
throw new Error("Provide at least --title or --content to update.");
|
|
228
|
-
}
|
|
229
|
-
if (opts.autoAttachments && opts.content) {
|
|
230
|
-
const vaultSlug = resolveVaultSlug(opts);
|
|
231
|
-
const token = await getValidToken();
|
|
232
|
-
const links = extractWikiLinks(opts.content);
|
|
233
|
-
await uploadAttachments(vaultSlug, links, token, { addToSyncfiles: true });
|
|
234
|
-
}
|
|
235
|
-
const body = {};
|
|
236
|
-
if (opts.title != null)
|
|
237
|
-
body.title = opts.title;
|
|
238
|
-
if (opts.content != null)
|
|
239
|
-
body.content = opts.content;
|
|
240
|
-
const resp = (await apiPatch(`/brain-updates/${updateId}`, body));
|
|
241
|
-
const u = unwrapResp(resp);
|
|
242
|
-
if (isJsonMode(brain)) {
|
|
243
|
-
jsonOut(u);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
console.log(`Brain update edited!\n` +
|
|
247
|
-
` ID: ${u.id}\n` +
|
|
248
|
-
` Title: ${u.title}\n` +
|
|
249
|
-
` Updated: ${u.updatedAt}`);
|
|
250
|
-
});
|
|
251
|
-
brain
|
|
252
|
-
.command("delete-update <updateId>")
|
|
253
|
-
.description("Delete a published brain update. You must be the author.")
|
|
254
|
-
.action(async (updateId) => {
|
|
255
|
-
await apiDelete(`/brain-updates/${updateId}`);
|
|
256
|
-
if (isJsonMode(brain)) {
|
|
257
|
-
jsonOut({ id: updateId });
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
console.log(`Brain update ${updateId} deleted.`);
|
|
261
|
-
});
|
|
262
|
-
// ── Update Replies (get-update, reply-to-update, edit-update-reply, delete-update-reply) ──
|
|
263
|
-
brain
|
|
264
|
-
.command("get-update <updateId>")
|
|
265
|
-
.description("Get a brain update and its replies (paginated).")
|
|
266
|
-
.option("--limit <number>", "Replies per page", "20")
|
|
267
|
-
.option("--cursor <string>", "Pagination cursor from previous response")
|
|
268
|
-
.option("--full", "Show full reply content without truncation")
|
|
269
|
-
.action(async (updateId, opts) => {
|
|
270
|
-
const params = {
|
|
271
|
-
limit: parseInt(opts.limit, 10),
|
|
272
|
-
};
|
|
273
|
-
if (opts.cursor)
|
|
274
|
-
params.cursor = opts.cursor;
|
|
275
|
-
const resp = (await apiGet(`/brain-updates/${updateId}`, params));
|
|
276
|
-
const data = unwrapResp(resp);
|
|
277
|
-
const pagination = (resp.pagination || {});
|
|
278
|
-
if (isJsonMode(brain)) {
|
|
279
|
-
jsonOut({ ...data, pagination });
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
const update = (data.update || data);
|
|
283
|
-
const replies = (data.replies || []);
|
|
284
|
-
const author = update.author?.name ||
|
|
285
|
-
`User ${update.authorId}`;
|
|
286
|
-
const vault = update.vault?.vaultSlug || "?";
|
|
287
|
-
const replyLines = [];
|
|
288
|
-
for (const r of replies) {
|
|
289
|
-
const rAuthor = r.author?.name ||
|
|
290
|
-
`User ${r.authorId}`;
|
|
291
|
-
const text = r.content;
|
|
292
|
-
const truncated = opts.full || text.length <= 200 ? text : text.slice(0, 200) + "\u2026";
|
|
293
|
-
replyLines.push(` - ${rAuthor}: ${truncated} (${r.createdAt})`);
|
|
294
|
-
}
|
|
295
|
-
const output = [
|
|
296
|
-
`Brain Update: ${update.title || "(no title)"}`,
|
|
297
|
-
`By: ${author} (vault: ${vault}) on ${update.createdAt}`,
|
|
298
|
-
"",
|
|
299
|
-
update.content,
|
|
300
|
-
"",
|
|
301
|
-
`Replies (${replies.length} items):`,
|
|
302
|
-
...replyLines,
|
|
303
|
-
...(pagination.hasMore
|
|
304
|
-
? [` Next cursor: ${pagination.nextCursor}`]
|
|
305
|
-
: []),
|
|
306
|
-
].join("\n");
|
|
307
|
-
console.log(output);
|
|
308
|
-
});
|
|
309
|
-
brain
|
|
310
|
-
.command("reply-to-update <updateId>")
|
|
311
|
-
.description("Reply to a brain update.")
|
|
312
|
-
.requiredOption("--content <content>", 'Reply content (markdown supported, use "-" for stdin)')
|
|
313
|
-
.action(async (updateId, opts) => {
|
|
314
|
-
const content = opts.content === "-" ? readFileSync("/dev/stdin", "utf8") : opts.content;
|
|
315
|
-
const resp = (await apiPost(`/brain-updates/${updateId}/replies`, { content }));
|
|
316
|
-
const reply = unwrapResp(resp);
|
|
317
|
-
if (isJsonMode(brain)) {
|
|
318
|
-
jsonOut(reply);
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
console.log(`Reply created!\n ID: ${reply.id}\n Created: ${reply.createdAt}`);
|
|
322
|
-
});
|
|
323
|
-
brain
|
|
324
|
-
.command("edit-update-reply <replyId>")
|
|
325
|
-
.description("Edit a brain update reply. You must be the author.")
|
|
326
|
-
.requiredOption("--content <content>", "New content for the reply (markdown supported)")
|
|
327
|
-
.action(async (replyId, opts) => {
|
|
328
|
-
const resp = (await apiPatch(`/brain-updates/replies/${replyId}`, { content: opts.content }));
|
|
329
|
-
const reply = unwrapResp(resp);
|
|
330
|
-
if (isJsonMode(brain)) {
|
|
331
|
-
jsonOut(reply);
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
console.log(`Reply edited!\n ID: ${reply.id}\n Edited: ${reply.editedAt}`);
|
|
335
|
-
});
|
|
336
|
-
brain
|
|
337
|
-
.command("delete-update-reply <replyId>")
|
|
338
|
-
.description("Delete a brain update reply. You must be the author.")
|
|
339
|
-
.action(async (replyId) => {
|
|
340
|
-
await apiDelete(`/brain-updates/replies/${replyId}`);
|
|
341
|
-
if (isJsonMode(brain)) {
|
|
342
|
-
jsonOut({ replyId });
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
console.log(`Brain update reply ${replyId} deleted.`);
|
|
346
|
-
});
|
|
347
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: gobi-brain
|
|
3
|
-
description: >-
|
|
4
|
-
Gobi brain commands for knowledge management: search public brains by text
|
|
5
|
-
and semantic similarity, ask brains questions, publish/unpublish BRAIN.md,
|
|
6
|
-
and manage brain updates (list/post/edit/delete). Use when the user wants
|
|
7
|
-
to search knowledge, ask a brain, publish their brain document, or manage
|
|
8
|
-
brain updates.
|
|
9
|
-
allowed-tools: Bash(gobi:*)
|
|
10
|
-
metadata:
|
|
11
|
-
author: gobi-ai
|
|
12
|
-
version: "0.8.0"
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# gobi-brain
|
|
16
|
-
|
|
17
|
-
Gobi brain commands for knowledge management (v0.8.0).
|
|
18
|
-
|
|
19
|
-
Requires gobi-cli installed and authenticated. See gobi-core skill for setup.
|
|
20
|
-
|
|
21
|
-
## Gobi Brain — Knowledge Management
|
|
22
|
-
|
|
23
|
-
`gobi brain` commands manage your vault's brain: search across all spaces, ask brains questions, and publish/unpublish your BRAIN.md. Public brains are accessible at `https://gobispace.com/@{vaultSlug}`.
|
|
24
|
-
|
|
25
|
-
## Space Slug Override
|
|
26
|
-
|
|
27
|
-
For `gobi brain list-updates`, you can filter by space with a subcommand option:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
gobi brain list-updates --space-slug <slug>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Note: `--space-slug` is not available on other `brain` subcommands.
|
|
34
|
-
|
|
35
|
-
## Important: JSON Mode
|
|
36
|
-
|
|
37
|
-
For programmatic/agent usage, always pass `--json` as a **global** option (before the subcommand):
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
gobi --json brain search --query "machine learning"
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Available Commands
|
|
44
|
-
|
|
45
|
-
- `gobi brain search` — Search public brains by text and semantic similarity.
|
|
46
|
-
- `gobi brain ask` — Ask a brain a question. Creates a targeted session (1:1 conversation).
|
|
47
|
-
- `gobi brain publish` — Upload BRAIN.md to the vault root on webdrive. Triggers post-processing (brain sync, metadata update, Discord notification).
|
|
48
|
-
- `gobi brain unpublish` — Delete BRAIN.md from the vault on webdrive.
|
|
49
|
-
- `gobi brain list-updates` — List recent brain updates. Without --space-slug, lists all updates for you. With --space-slug, lists updates for that space. Use --mine to show only updates by you.
|
|
50
|
-
- `gobi brain post-update` — Post a brain update for a vault.
|
|
51
|
-
- `gobi brain edit-update` — Edit a published brain update. You must be the author.
|
|
52
|
-
- `gobi brain delete-update` — Delete a published brain update. You must be the author.
|
|
53
|
-
|
|
54
|
-
## BRAIN.md Frontmatter Reference
|
|
55
|
-
|
|
56
|
-
`BRAIN.md` is the metadata file at the root of every vault. Its YAML frontmatter controls the vault's public profile, homepage, and AI agent behavior. Example:
|
|
57
|
-
|
|
58
|
-
```yaml
|
|
59
|
-
---
|
|
60
|
-
title: My Brain
|
|
61
|
-
tags:
|
|
62
|
-
- topic1
|
|
63
|
-
- topic2
|
|
64
|
-
description: A short description of what this brain is about.
|
|
65
|
-
thumbnail: "[[BRAIN.png]]"
|
|
66
|
-
homepage: "[[app/home.html?nav=false]]"
|
|
67
|
-
prompt: "[[system-prompt.md]]"
|
|
68
|
-
---
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Fields
|
|
72
|
-
|
|
73
|
-
- **`title`** (required) — Display name of the brain/vault.
|
|
74
|
-
- **`description`** (required for public listing) — Short description shown on the brain card and public profile. Without both `title` and `description`, the brain won't appear in the public catalog.
|
|
75
|
-
- **`tags`** — Tags for categorization and discovery. Supports YAML block list or inline array format:
|
|
76
|
-
```yaml
|
|
77
|
-
# Block list
|
|
78
|
-
tags:
|
|
79
|
-
- ambient ai
|
|
80
|
-
- wearables
|
|
81
|
-
|
|
82
|
-
# Inline array
|
|
83
|
-
tags: [ambient ai, wearables]
|
|
84
|
-
```
|
|
85
|
-
- **`thumbnail`** — Profile image for the brain card. Uses wiki-link syntax pointing to an image file in the vault (e.g. `"[[BRAIN.png]]"`).
|
|
86
|
-
- **`homepage`** — Custom HTML page to serve as the vault's public homepage at `gobispace.com/@{vaultSlug}`. Uses wiki-link syntax pointing to an HTML file in the vault. Supports a `nav` query parameter to control Gobi's sidebar navigation:
|
|
87
|
-
- `"[[app/home.html]]"` — Shows the Gobi sidebar alongside the homepage (default)
|
|
88
|
-
- `"[[app/home.html?nav=false]]"` — Full-screen, no Gobi sidebar/chrome
|
|
89
|
-
- **`prompt`** — Wiki-link to a custom system prompt file for the brain's AI agent (e.g. `"[[system-prompt.md]]"`).
|
|
90
|
-
|
|
91
|
-
> For details on building custom HTML homepages and using the `window.gobi` API, see the **gobi-homepage** skill.
|
|
92
|
-
|
|
93
|
-
## Publishing Workflow
|
|
94
|
-
|
|
95
|
-
After editing `BRAIN.md` frontmatter, follow these steps to make your changes live:
|
|
96
|
-
|
|
97
|
-
1. **Edit `BRAIN.md`** in the vault root with the desired frontmatter fields.
|
|
98
|
-
2. **Sync referenced files** — if the homepage HTML, thumbnail image, or prompt file is new or updated, upload them first:
|
|
99
|
-
```bash
|
|
100
|
-
gobi sync
|
|
101
|
-
```
|
|
102
|
-
3. **Publish the brain**:
|
|
103
|
-
```bash
|
|
104
|
-
gobi brain publish
|
|
105
|
-
```
|
|
106
|
-
This uploads `BRAIN.md` to webdrive, triggers post-processing that extracts metadata (title, description, tags, thumbnail, homepage path), updates the vault's public profile, and sends a Discord notification.
|
|
107
|
-
4. The vault is now live at `https://gobispace.com/@{vaultSlug}`.
|
|
108
|
-
|
|
109
|
-
> **Important:** Any time you change `BRAIN.md` frontmatter (e.g. adding or updating `homepage`), you must re-run `gobi brain publish` for the changes to take effect.
|
|
110
|
-
|
|
111
|
-
## Reference Documentation
|
|
112
|
-
|
|
113
|
-
- [gobi brain](references/brain.md)
|