@gobi-ai/cli 0.9.2 → 0.9.4

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.
@@ -4,12 +4,12 @@
4
4
  "name": "gobi-ai"
5
5
  },
6
6
  "description": "Claude Code plugin for the Gobi collaborative knowledge platform CLI",
7
- "version": "0.9.1",
7
+ "version": "0.9.3",
8
8
  "plugins": [
9
9
  {
10
10
  "name": "gobi",
11
11
  "description": "Manage the Gobi collaborative knowledge platform from the command line. Search and ask brains, publish brain documents, create threads, manage sessions, generate images and videos.",
12
- "version": "0.9.1",
12
+ "version": "0.9.3",
13
13
  "author": {
14
14
  "name": "gobi-ai"
15
15
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gobi",
3
3
  "description": "Manage the Gobi collaborative knowledge platform from the command line",
4
- "version": "0.9.1",
4
+ "version": "0.9.3",
5
5
  "author": {
6
6
  "name": "gobi-ai"
7
7
  },
@@ -253,7 +253,9 @@ export function registerMediaCommand(program) {
253
253
  .option("--seed <seed>", "Random seed for reproducibility")
254
254
  .option("--reference-media-id <referenceMediaId>", "Reference image media ID")
255
255
  .option("--wait", "Poll until generation completes")
256
+ .option("-o, --output <path>", "Download image to this path when done (implies --wait)")
256
257
  .action(async (opts) => {
258
+ const shouldWait = opts.wait || !!opts.output;
257
259
  const name = opts.name || opts.prompt.slice(0, 50).replace(/[^a-zA-Z0-9-_ ]/g, "").trim().replace(/\s+/g, "-");
258
260
  const body = {
259
261
  prompt: opts.prompt,
@@ -272,7 +274,7 @@ export function registerMediaCommand(program) {
272
274
  const resp = (await apiPost("/media-gen/images/generate", body));
273
275
  let data = unwrapResp(resp);
274
276
  const jobId = data.jobId || data.id;
275
- if (opts.wait && jobId) {
277
+ if (shouldWait && jobId) {
276
278
  console.log(`Image job ${jobId} queued — polling for completion…`);
277
279
  data = await pollStatus(`/media-gen/images/${jobId}`, [
278
280
  "completed",
@@ -281,6 +283,31 @@ export function registerMediaCommand(program) {
281
283
  "inference_failed",
282
284
  ]);
283
285
  }
286
+ // Download image to file if -o specified
287
+ if (opts.output && data) {
288
+ const id = data.jobId || data.id;
289
+ if (id) {
290
+ const token = await getValidToken();
291
+ const url = `${BASE_URL}/media-gen/images/${id}/download`;
292
+ const res = await fetch(url, {
293
+ headers: { Authorization: `Bearer ${token}` },
294
+ });
295
+ if (res.ok) {
296
+ const { writeFile, mkdir } = await import("fs/promises");
297
+ const { dirname } = await import("path");
298
+ const buffer = Buffer.from(await res.arrayBuffer());
299
+ await mkdir(dirname(opts.output), { recursive: true });
300
+ await writeFile(opts.output, buffer);
301
+ const contentType = res.headers.get("content-type") || "image/png";
302
+ if (isJsonMode(media)) {
303
+ jsonOut({ ...data, filename: opts.output, contentType, size: buffer.length });
304
+ return;
305
+ }
306
+ console.log(`Image saved to ${opts.output} (${buffer.length} bytes)`);
307
+ return;
308
+ }
309
+ }
310
+ }
284
311
  if (isJsonMode(media)) {
285
312
  jsonOut(data);
286
313
  return;
@@ -404,6 +431,7 @@ export function registerMediaCommand(program) {
404
431
  .description("Download a generated image.")
405
432
  .option("--wait", "Poll until generation completes before downloading")
406
433
  .option("--type <type>", "Image type (image, thumbnail, asset)")
434
+ .option("-o, --output <path>", "Output file path (default: {jobId}.{ext} in current directory)")
407
435
  .action(async (jobId, opts) => {
408
436
  if (opts.wait) {
409
437
  console.log(`Waiting for image job ${jobId} to complete…`);
@@ -428,16 +456,22 @@ export function registerMediaCommand(program) {
428
456
  const ext = contentType.includes("jpeg") || contentType.includes("jpg") ? "jpg"
429
457
  : contentType.includes("webp") ? "webp"
430
458
  : "png";
431
- const filename = `${jobId}.${ext}`;
459
+ const filename = opts.output || `${jobId}.${ext}`;
432
460
  if (isJsonMode(media)) {
433
- // In JSON mode, return base64-encoded image
461
+ // In JSON mode, save to file and return metadata
462
+ const { writeFile, mkdir } = await import("fs/promises");
463
+ const { dirname } = await import("path");
434
464
  const buffer = Buffer.from(await res.arrayBuffer());
435
- jsonOut({ filename, contentType, size: buffer.length, base64: buffer.toString("base64") });
465
+ await mkdir(dirname(filename), { recursive: true });
466
+ await writeFile(filename, buffer);
467
+ jsonOut({ filename, contentType, size: buffer.length });
436
468
  return;
437
469
  }
438
470
  // Write to file
439
- const { writeFile } = await import("fs/promises");
471
+ const { writeFile, mkdir } = await import("fs/promises");
472
+ const { dirname } = await import("path");
440
473
  const buffer = Buffer.from(await res.arrayBuffer());
474
+ await mkdir(dirname(filename), { recursive: true });
441
475
  await writeFile(filename, buffer);
442
476
  console.log(`Image saved to ${filename} (${buffer.length} bytes)`);
443
477
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobi-ai/cli",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "CLI client for the Gobi collaborative knowledge platform",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,15 +27,22 @@ gobi --json media image-generate --prompt "a sunset over mountains"
27
27
 
28
28
  ## Typical Workflow (Image Generation)
29
29
 
30
- Always use `--wait` to poll until completion in a single command:
30
+ Single command generate and download in one step:
31
31
 
32
32
  ```bash
33
- gobi --json media image-generate --prompt "a sunset over mountains" --wait
33
+ gobi --json media image-generate --prompt "a sunset over mountains" -o media/sunset.png
34
34
  ```
35
35
 
36
+ The `-o` flag implies `--wait` and downloads the image when done.
37
+
38
+ Then show the result as an embedded vault link: `![[media/sunset.png]]`
39
+
40
+ ### Key rules
41
+ - Use `-o media/<name>.png` to generate AND download in one command. Pick a short descriptive name.
36
42
  - `--name` is **optional** — auto-derived from prompt if omitted.
37
- - `--wait` avoids needing a separate `image-status` call.
38
- - `image-status` takes a **positional** jobId (NOT `--job-id`): `gobi media image-status <jobId>`
43
+ - Do NOT use the `downloadUrl` from the response — it is a frontend path, not a direct download link.
44
+ - `image-download` takes a **positional** jobId (NOT `--job-id`): `gobi media image-download <jobId>`
45
+ - The `jobId` (or `id`) field is what you pass to `image-download` / `image-status` — NOT `mediaId`.
39
46
 
40
47
  ## Available Commands
41
48
 
@@ -152,6 +152,7 @@ Options:
152
152
  --seed <seed> Random seed for reproducibility
153
153
  --reference-media-id <referenceMediaId> Reference image media ID
154
154
  --wait Poll until generation completes
155
+ -o, --output <path> Download image to this path when done (implies --wait)
155
156
  -h, --help display help for command
156
157
  ```
157
158
 
@@ -206,7 +207,8 @@ Usage: gobi media image-download [options] <jobId>
206
207
  Download a generated image.
207
208
 
208
209
  Options:
209
- --wait Poll until generation completes before downloading
210
- --type <type> Image type (image, thumbnail, asset)
211
- -h, --help display help for command
210
+ --wait Poll until generation completes before downloading
211
+ --type <type> Image type (image, thumbnail, asset)
212
+ -o, --output <path> Output file path (default: {jobId}.{ext} in current directory)
213
+ -h, --help display help for command
212
214
  ```