gunni 0.3.5 → 0.3.7

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 (2) hide show
  1. package/dist/index.js +84 -55
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -69400,7 +69400,8 @@ async function downloadImage(url2, outputPath, onProgress) {
69400
69400
  const correctExt = await detectImageFormat(outputPath);
69401
69401
  const currentExt = extname(outputPath).toLowerCase();
69402
69402
  if (correctExt && correctExt !== currentExt) {
69403
- const fixedPath = outputPath.slice(0, -currentExt.length) + correctExt;
69403
+ const basePath = currentExt ? outputPath.slice(0, -currentExt.length) : outputPath;
69404
+ const fixedPath = basePath + correctExt;
69404
69405
  await rename(outputPath, fixedPath);
69405
69406
  return fixedPath;
69406
69407
  }
@@ -69431,7 +69432,8 @@ async function saveImageData(data, outputPath, onProgress) {
69431
69432
  const correctExt = await detectImageFormat(outputPath);
69432
69433
  const currentExt = extname(outputPath).toLowerCase();
69433
69434
  if (correctExt && correctExt !== currentExt) {
69434
- const fixedPath = outputPath.slice(0, -currentExt.length) + correctExt;
69435
+ const basePath = currentExt ? outputPath.slice(0, -currentExt.length) : outputPath;
69436
+ const fixedPath = basePath + correctExt;
69435
69437
  await rename(outputPath, fixedPath);
69436
69438
  return fixedPath;
69437
69439
  }
@@ -70466,7 +70468,7 @@ var ModelRouter = class {
70466
70468
  const provider = this.resolveProvider(opts.model);
70467
70469
  let spinner;
70468
70470
  if (opts.showSpinner !== false) {
70469
- spinner = ora("Starting\u2026").start();
70471
+ spinner = ora("Painting pixels\u2026").start();
70470
70472
  }
70471
70473
  const updateSpinner = (status) => {
70472
70474
  if (spinner) spinner.text = status;
@@ -86261,7 +86263,7 @@ var RemoteClient = class {
86261
86263
  }
86262
86264
  }
86263
86265
  );
86264
- this.client = new Client({ name: "gunni-cli", version: "0.3.5" });
86266
+ this.client = new Client({ name: "gunni-cli", version: "0.3.7" });
86265
86267
  await this.client.connect(transport);
86266
86268
  }
86267
86269
  async callTool(name, args) {
@@ -86553,7 +86555,14 @@ function resolveVariantPath(template, index) {
86553
86555
  return `${base}-${index}${ext}`;
86554
86556
  }
86555
86557
  async function handleRemote(input, prompt, operation, opts, json2, apiKey, serverUrl) {
86556
- const spinner = json2 ? void 0 : ora("Connecting to Gunni API\u2026").start();
86558
+ const spinnerLabels = {
86559
+ generate: "Painting pixels\u2026",
86560
+ edit: "Reworking the canvas\u2026",
86561
+ describe: "Studying the image\u2026",
86562
+ upscale: "Enhancing resolution\u2026",
86563
+ "remove-bg": "Cutting out the background\u2026"
86564
+ };
86565
+ const spinner = json2 ? void 0 : ora(spinnerLabels[operation]).start();
86557
86566
  const update = (s2) => {
86558
86567
  if (spinner) spinner.text = s2;
86559
86568
  };
@@ -86603,7 +86612,7 @@ async function handleRemote(input, prompt, operation, opts, json2, apiKey, serve
86603
86612
  if (opts.width) toolArgs.width = opts.width;
86604
86613
  if (opts.height) toolArgs.height = opts.height;
86605
86614
  if (opts.seed !== void 0) toolArgs.seed = opts.seed;
86606
- update("Calling Gunni API\u2026");
86615
+ update(spinnerLabels[operation]);
86607
86616
  const client2 = new RemoteClient();
86608
86617
  await client2.connect(apiKey, serverUrl);
86609
86618
  const result = await client2.callTool("image", toolArgs);
@@ -86624,7 +86633,7 @@ async function handleRemote(input, prompt, operation, opts, json2, apiKey, serve
86624
86633
  const r2 = remoteResults[i2];
86625
86634
  if (!r2.assetUrl) continue;
86626
86635
  const requestedPath2 = remoteResults.length === 1 ? opts.output ?? `gunni-${operation}-${Date.now()}.png` : opts.output ? resolveVariantPath(opts.output, i2 + 1) : `gunni-${operation}-${Date.now()}-${i2 + 1}.png`;
86627
- update("Downloading result\u2026");
86636
+ update("Saving to disk\u2026");
86628
86637
  const finalPath2 = await downloadImage(r2.assetUrl, requestedPath2, update);
86629
86638
  downloadedResults.push({
86630
86639
  image: { path: finalPath2, url: r2.assetUrl, width: r2.width ?? 0, height: r2.height ?? 0 },
@@ -86656,7 +86665,7 @@ async function handleRemote(input, prompt, operation, opts, json2, apiKey, serve
86656
86665
  throw new GunniError("No image in remote response", "NO_IMAGE");
86657
86666
  }
86658
86667
  const requestedPath = opts.output ?? `gunni-${operation}-${Date.now()}.png`;
86659
- update("Downloading result\u2026");
86668
+ update("Saving to disk\u2026");
86660
86669
  const finalPath = await downloadImage(img.assetUrl, requestedPath, update);
86661
86670
  spinner?.succeed("Done");
86662
86671
  if (json2) {
@@ -86724,9 +86733,9 @@ async function handleGenerate(prompt, modelId, opts, json2) {
86724
86733
  return;
86725
86734
  }
86726
86735
  const results = [];
86727
- const spinner = json2 ? void 0 : ora(`Generating variant 1 of ${variantCount}\u2026`).start();
86736
+ const spinner = json2 ? void 0 : ora(`Painting variant 1 of ${variantCount}\u2026`).start();
86728
86737
  for (let i2 = 1; i2 <= variantCount; i2++) {
86729
- if (spinner) spinner.text = `Generating variant ${i2} of ${variantCount}\u2026`;
86738
+ if (spinner) spinner.text = `Painting variant ${i2} of ${variantCount}\u2026`;
86730
86739
  const outputPath = opts.output ? resolveVariantPath(opts.output, i2) : `gunni-${modelId}-${Date.now()}-${i2}.png`;
86731
86740
  const router = new ModelRouter();
86732
86741
  const result = await router.generate({
@@ -86775,15 +86784,15 @@ async function handleGenerate(prompt, modelId, opts, json2) {
86775
86784
  }
86776
86785
  async function handleEdit(imagePath, prompt, modelId, opts, json2) {
86777
86786
  const variantCount = opts.variants ?? 1;
86778
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
86787
+ const spinner = json2 ? void 0 : ora("Reworking the canvas\u2026").start();
86779
86788
  const update = (s2) => {
86780
86789
  if (spinner) spinner.text = s2;
86781
86790
  };
86782
86791
  const provider = getProviderForModel(modelId);
86783
86792
  const results = [];
86784
86793
  for (let i2 = 1; i2 <= variantCount; i2++) {
86785
- if (variantCount > 1) update(`Editing variant ${i2} of ${variantCount}\u2026`);
86786
- else update("Editing\u2026");
86794
+ if (variantCount > 1) update(`Reworking variant ${i2} of ${variantCount}\u2026`);
86795
+ else update("Reworking the canvas\u2026");
86787
86796
  const editResult = await provider.editImage({
86788
86797
  imagePath,
86789
86798
  prompt,
@@ -86843,7 +86852,7 @@ async function handleEdit(imagePath, prompt, modelId, opts, json2) {
86843
86852
  }
86844
86853
  }
86845
86854
  async function handleDescribe(imagePath, modelId, json2) {
86846
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
86855
+ const spinner = json2 ? void 0 : ora("Studying the image\u2026").start();
86847
86856
  const update = (s2) => {
86848
86857
  if (spinner) spinner.text = s2;
86849
86858
  };
@@ -86857,7 +86866,7 @@ async function handleDescribe(imagePath, modelId, json2) {
86857
86866
  );
86858
86867
  }
86859
86868
  const imageUrl = await uploadToFal(imagePath, update);
86860
- update("Analyzing\u2026");
86869
+ update("Reading the pixels\u2026");
86861
86870
  const provider = new FalProvider();
86862
86871
  const result = await provider.call(
86863
86872
  modelDef.endpoint,
@@ -86888,7 +86897,7 @@ async function handleDescribe(imagePath, modelId, json2) {
86888
86897
  }
86889
86898
  }
86890
86899
  async function handleUpscale(imagePath, modelId, opts, json2) {
86891
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
86900
+ const spinner = json2 ? void 0 : ora("Enhancing resolution\u2026").start();
86892
86901
  const update = (s2) => {
86893
86902
  if (spinner) spinner.text = s2;
86894
86903
  };
@@ -86898,7 +86907,7 @@ async function handleUpscale(imagePath, modelId, opts, json2) {
86898
86907
  throw new GunniError(`Unknown model: ${modelId}`, "UNKNOWN_MODEL");
86899
86908
  }
86900
86909
  const imageUrl = await uploadToFal(imagePath, update);
86901
- update("Upscaling\u2026");
86910
+ update("Adding more pixels\u2026");
86902
86911
  const provider = new FalProvider();
86903
86912
  const result = await provider.call(
86904
86913
  modelDef.endpoint,
@@ -86947,7 +86956,7 @@ async function handleUpscale(imagePath, modelId, opts, json2) {
86947
86956
  }
86948
86957
  }
86949
86958
  async function handleRemoveBg(imagePath, modelId, opts, json2) {
86950
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
86959
+ const spinner = json2 ? void 0 : ora("Cutting out the background\u2026").start();
86951
86960
  const update = (s2) => {
86952
86961
  if (spinner) spinner.text = s2;
86953
86962
  };
@@ -86957,7 +86966,7 @@ async function handleRemoveBg(imagePath, modelId, opts, json2) {
86957
86966
  throw new GunniError(`Unknown model: ${modelId}`, "UNKNOWN_MODEL");
86958
86967
  }
86959
86968
  const imageUrl = await uploadToFal(imagePath, update);
86960
- update("Removing background\u2026");
86969
+ update("Snipping away\u2026");
86961
86970
  const provider = new FalProvider();
86962
86971
  const result = await provider.call(
86963
86972
  modelDef.endpoint,
@@ -87044,7 +87053,7 @@ Run 'gunni list models --type video' for details.
87044
87053
  "NO_API_KEY",
87045
87054
  json2 ? void 0 : `Run ${import_picocolors4.default.bold("gunni")} to set up, or: gunni config --set-gunni-key YOUR_KEY`
87046
87055
  );
87047
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
87056
+ const spinner = json2 ? void 0 : ora("Rolling camera\u2026").start();
87048
87057
  const update = (s2) => {
87049
87058
  if (spinner) spinner.text = s2;
87050
87059
  };
@@ -87101,7 +87110,7 @@ Run 'gunni list models --type video' for details.
87101
87110
  }
87102
87111
  }
87103
87112
  const provider = getProviderForModel(modelId);
87104
- update("Generating video\u2026");
87113
+ update("Rendering frames\u2026");
87105
87114
  const result = await provider.generateVideo({
87106
87115
  prompt,
87107
87116
  model: modelId,
@@ -87160,7 +87169,7 @@ Run 'gunni list models --type video' for details.
87160
87169
  });
87161
87170
  }
87162
87171
  async function handleRemote2(input, opts, json2, apiKey, serverUrl) {
87163
- const spinner = json2 ? void 0 : ora("Connecting to Gunni API\u2026").start();
87172
+ const spinner = json2 ? void 0 : ora("Rolling camera\u2026").start();
87164
87173
  const update = (s2) => {
87165
87174
  if (spinner) spinner.text = s2;
87166
87175
  };
@@ -87224,7 +87233,7 @@ async function handleRemote2(input, opts, json2, apiKey, serverUrl) {
87224
87233
  if (imageUrl) toolArgs.image = imageUrl;
87225
87234
  if (opts.duration !== void 0) toolArgs.duration = opts.duration;
87226
87235
  if (opts.style) toolArgs.style = opts.style;
87227
- update("Generating video\u2026");
87236
+ update("Rendering frames\u2026");
87228
87237
  const client2 = new RemoteClient();
87229
87238
  await client2.connect(apiKey, serverUrl);
87230
87239
  let result = await client2.callTool("video", toolArgs);
@@ -87250,7 +87259,7 @@ async function handleRemote2(input, opts, json2, apiKey, serverUrl) {
87250
87259
  spinner?.fail("No video returned");
87251
87260
  throw new GunniError("No video in remote response", "NO_VIDEO");
87252
87261
  }
87253
- update("Downloading video\u2026");
87262
+ update("Saving to disk\u2026");
87254
87263
  const finalPath = await downloadMedia(videoAssetUrl, requestedPath, update);
87255
87264
  let audioPath;
87256
87265
  const audioAssetUrl = result.audio?.assetUrl;
@@ -87325,7 +87334,7 @@ Run 'gunni list models --type audio' for details.
87325
87334
  "NO_API_KEY",
87326
87335
  json2 ? void 0 : `Run ${import_picocolors5.default.bold("gunni")} to set up, or: gunni config --set-gunni-key YOUR_KEY`
87327
87336
  );
87328
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
87337
+ const spinner = json2 ? void 0 : ora("Finding the right voice\u2026").start();
87329
87338
  const update = (s2) => {
87330
87339
  if (spinner) spinner.text = s2;
87331
87340
  };
@@ -87349,7 +87358,7 @@ Run 'gunni list models --type audio' for details.
87349
87358
  falInput.audio_url = opts.voice;
87350
87359
  }
87351
87360
  }
87352
- update("Generating audio\u2026");
87361
+ update("Recording the take\u2026");
87353
87362
  const provider = new FalProvider();
87354
87363
  const result = await provider.call(endpoint, falInput, update);
87355
87364
  const data = result.data;
@@ -87401,7 +87410,7 @@ function getEndpoint(modelId) {
87401
87410
  return model.endpoint;
87402
87411
  }
87403
87412
  async function handleRemote3(text, opts, json2, apiKey, serverUrl) {
87404
- const spinner = json2 ? void 0 : ora("Generating audio\u2026").start();
87413
+ const spinner = json2 ? void 0 : ora("Finding the right voice\u2026").start();
87405
87414
  const update = (s2) => {
87406
87415
  if (spinner) spinner.text = s2;
87407
87416
  };
@@ -87419,7 +87428,7 @@ async function handleRemote3(text, opts, json2, apiKey, serverUrl) {
87419
87428
  throw new GunniError("No audio in remote response", "NO_AUDIO");
87420
87429
  }
87421
87430
  const requestedPath = opts.output ?? `gunni-audio-${Date.now()}.mp3`;
87422
- update("Downloading audio\u2026");
87431
+ update("Saving to disk\u2026");
87423
87432
  const finalPath = await downloadMedia(audioAssetUrl, requestedPath, update);
87424
87433
  spinner?.succeed("Done");
87425
87434
  const output = {
@@ -87493,7 +87502,7 @@ Run 'gunni list models --type lipsync' for details.
87493
87502
  "NO_API_KEY",
87494
87503
  json2 ? void 0 : `Run ${import_picocolors6.default.bold("gunni")} to set up, or: gunni config --set-gunni-key YOUR_KEY`
87495
87504
  );
87496
- const spinner = json2 ? void 0 : ora("Starting\u2026").start();
87505
+ const spinner = json2 ? void 0 : ora("Matching lips to audio\u2026").start();
87497
87506
  const update = (s2) => {
87498
87507
  if (spinner) spinner.text = s2;
87499
87508
  };
@@ -87506,7 +87515,7 @@ Run 'gunni list models --type lipsync' for details.
87506
87515
  );
87507
87516
  }
87508
87517
  const provider = new FalProvider();
87509
- update("Generating lip sync\u2026");
87518
+ update("Animating the performance\u2026");
87510
87519
  const result = await provider.generateLipsync({
87511
87520
  model: modelId,
87512
87521
  videoPath: opts.video,
@@ -87556,7 +87565,7 @@ Run 'gunni list models --type lipsync' for details.
87556
87565
  });
87557
87566
  }
87558
87567
  async function handleRemote4(audio, opts, json2, apiKey, serverUrl) {
87559
- const spinner = json2 ? void 0 : ora("Connecting to Gunni API\u2026").start();
87568
+ const spinner = json2 ? void 0 : ora("Matching lips to audio\u2026").start();
87560
87569
  const update = (s2) => {
87561
87570
  if (spinner) spinner.text = s2;
87562
87571
  };
@@ -87591,7 +87600,7 @@ async function handleRemote4(audio, opts, json2, apiKey, serverUrl) {
87591
87600
  };
87592
87601
  if (videoUrl) toolArgs.video = videoUrl;
87593
87602
  if (imageUrl) toolArgs.image = imageUrl;
87594
- update("Generating lip sync\u2026");
87603
+ update("Animating the performance\u2026");
87595
87604
  const client2 = new RemoteClient();
87596
87605
  await client2.connect(apiKey, serverUrl);
87597
87606
  let result = await client2.callTool("lipsync", toolArgs);
@@ -87617,7 +87626,7 @@ async function handleRemote4(audio, opts, json2, apiKey, serverUrl) {
87617
87626
  throw new GunniError("No video in remote lip sync response", "NO_VIDEO");
87618
87627
  }
87619
87628
  const requestedPath = opts.output ?? `gunni-lipsync-${Date.now()}.mp4`;
87620
- update("Downloading video\u2026");
87629
+ update("Saving to disk\u2026");
87621
87630
  const finalPath = await downloadMedia(videoAssetUrl, requestedPath, update);
87622
87631
  spinner?.succeed("Done");
87623
87632
  const output = {
@@ -87884,7 +87893,7 @@ KEY PRINCIPLES
87884
87893
  }
87885
87894
  },
87886
87895
  latest: {
87887
- version: "0.3.4",
87896
+ version: "0.3.7",
87888
87897
  date: "2026-03-29",
87889
87898
  updates: [
87890
87899
  "Production system: templates (proven prompts with variables), styles (visual direction), presets (platform rules), pipelines (multi-step workflows).",
@@ -87962,9 +87971,27 @@ ${import_picocolors8.default.dim("Run: gunni learn <topic>")}
87962
87971
  `);
87963
87972
  } else {
87964
87973
  console.log(`
87965
- ${import_picocolors8.default.bold(result.title)}
87974
+ ${import_picocolors8.default.bold(import_picocolors8.default.cyan(result.title))}
87966
87975
  `);
87967
- console.log(result.content);
87976
+ const lines = result.content.split("\n");
87977
+ for (const line of lines) {
87978
+ if (/^[A-Z][A-Z _/()]+:/.test(line)) {
87979
+ const colonIdx = line.indexOf(":");
87980
+ console.log(`${import_picocolors8.default.bold(line.slice(0, colonIdx + 1))}${import_picocolors8.default.dim(line.slice(colonIdx + 1))}`);
87981
+ } else if (line.startsWith("- ")) {
87982
+ const dashEnd = line.indexOf(" ", 2);
87983
+ const toolMatch = line.match(/^- (\w+\(\)[^ ]*)(.*)/);
87984
+ if (toolMatch) {
87985
+ console.log(` ${import_picocolors8.default.green("\u2022")} ${import_picocolors8.default.cyan(toolMatch[1])}${import_picocolors8.default.dim(toolMatch[2])}`);
87986
+ } else {
87987
+ console.log(` ${import_picocolors8.default.green("\u2022")} ${line.slice(2)}`);
87988
+ }
87989
+ } else if (/^\d+\./.test(line)) {
87990
+ console.log(` ${import_picocolors8.default.dim(line)}`);
87991
+ } else {
87992
+ console.log(line);
87993
+ }
87994
+ }
87968
87995
  console.log();
87969
87996
  }
87970
87997
  } catch (err) {
@@ -89384,7 +89411,8 @@ Examples:
89384
89411
  console.log(`
89385
89412
  ${import_picocolors14.default.bold(import_picocolors14.default.cyan(category.toUpperCase()))}`);
89386
89413
  for (const m2 of catModels) {
89387
- console.log(` ${import_picocolors14.default.bold(m2.id)} ${import_picocolors14.default.dim(m2.description)}`);
89414
+ const tag = m2.isDefault ? import_picocolors14.default.green(" \u2605") : "";
89415
+ console.log(` ${import_picocolors14.default.bold(m2.id)}${tag} ${import_picocolors14.default.dim(m2.description)}`);
89388
89416
  }
89389
89417
  }
89390
89418
  console.log();
@@ -90889,7 +90917,7 @@ async function runOnboarding() {
90889
90917
 
90890
90918
  // src/index.ts
90891
90919
  var program2 = new Command();
90892
- program2.name("gunni").description("AI media toolkit \u2014 give any agent the ability to create professional media").version("0.3.5").option("--json", "Output results as JSON").addHelpText(
90920
+ program2.name("gunni").description("AI media toolkit \u2014 give any agent the ability to create professional media").version("0.3.7").option("--json", "Output results as JSON").addHelpText(
90893
90921
  "after",
90894
90922
  `
90895
90923
  Examples:
@@ -90899,18 +90927,18 @@ Examples:
90899
90927
  $ gunni init --template brand # Start a brand project
90900
90928
 
90901
90929
  Image (generate, edit, describe, upscale, remove-bg):
90902
- $ gunni image "a coffee bag on white background" -o bag.png
90903
- $ gunni image bag.png --remove-bg -o bag-clean.png
90904
- $ gunni image bag-clean.png "place on marble counter" -o hero.png
90905
- $ gunni image hero.png --upscale -o hero-final.png
90906
- $ gunni image hero-final.png # describe
90930
+ $ gunni image "a coffee bag on white background" -o bag
90931
+ $ gunni image bag.jpg --remove-bg -o bag-clean
90932
+ $ gunni image bag-clean.png "place on marble counter" -o hero
90933
+ $ gunni image hero.jpg --upscale -o hero-final
90934
+ $ gunni image hero-final.jpg # describe
90907
90935
 
90908
90936
  Video & audio:
90909
- $ gunni video hero.png -p "slow cinematic zoom in" -o hero.mp4
90937
+ $ gunni video hero.jpg -p "slow cinematic zoom in" -o hero.mp4
90910
90938
  $ gunni audio "Welcome to our roastery" -o intro.mp3
90911
90939
 
90912
90940
  Explore with variants:
90913
- $ gunni image "logo concepts" --variants 4 -o logo-{n}.png
90941
+ $ gunni image "logo concepts" --variants 4 -o logo-{n}
90914
90942
 
90915
90943
  Creative expertise:
90916
90944
  $ gunni learn exploration # How to explore creatively
@@ -90919,8 +90947,8 @@ Examples:
90919
90947
  Agent workflow (structured JSON):
90920
90948
  $ gunni --json learn overview # Load capabilities
90921
90949
  $ gunni --json image "product photo" --variants 3 # Explore
90922
- $ gunni --json image best.png "refine the lighting" # Iterate
90923
- $ gunni --json image final.png --upscale # Polish
90950
+ $ gunni --json image best.jpg "refine the lighting" # Iterate
90951
+ $ gunni --json image final.jpg --upscale # Polish
90924
90952
  `
90925
90953
  );
90926
90954
  registerImageCommand(program2);
@@ -90941,7 +90969,7 @@ program2.command("models").description("List available models (alias for: gunni
90941
90969
  return;
90942
90970
  }
90943
90971
  if (models.length === 0) {
90944
- console.log(`No models found${opts.type ? ` for category "${opts.type}"` : ""}.`);
90972
+ console.log(import_picocolors23.default.dim(`No models found${opts.type ? ` for category "${opts.type}"` : ""}.`));
90945
90973
  return;
90946
90974
  }
90947
90975
  const grouped = /* @__PURE__ */ new Map();
@@ -90952,9 +90980,10 @@ program2.command("models").description("List available models (alias for: gunni
90952
90980
  }
90953
90981
  for (const [category, catModels] of grouped) {
90954
90982
  console.log(`
90955
- ${category.toUpperCase()}`);
90983
+ ${import_picocolors23.default.bold(import_picocolors23.default.cyan(category.toUpperCase()))}`);
90956
90984
  for (const m2 of catModels) {
90957
- console.log(` ${m2.id} ${m2.description}`);
90985
+ const tag = m2.isDefault ? import_picocolors23.default.green(" \u2605") : "";
90986
+ console.log(` ${import_picocolors23.default.bold(m2.id)}${tag} ${import_picocolors23.default.dim(m2.description)}`);
90958
90987
  }
90959
90988
  }
90960
90989
  console.log();
@@ -90988,7 +91017,7 @@ program2.action(async () => {
90988
91017
  { name: "models", usage: "gunni models [--type <category>]", description: "List available models" },
90989
91018
  { name: "config", usage: "gunni config", description: "Manage API keys" }
90990
91019
  ];
90991
- console.log(JSON.stringify({ version: "0.3.5", commands, categories, models }, null, 2));
91020
+ console.log(JSON.stringify({ version: "0.3.7", commands, categories, models }, null, 2));
90992
91021
  return;
90993
91022
  }
90994
91023
  const configured = await hasGunniKey();
@@ -91044,10 +91073,10 @@ ${import_picocolors23.default.bold("Models:")} ${import_picocolors23.default.dim
91044
91073
  }
91045
91074
  console.log(`
91046
91075
  ${import_picocolors23.default.bold("Quick start:")}
91047
- ${import_picocolors23.default.dim("$")} gunni image "coffee bag product shot" -o bag.png
91048
- ${import_picocolors23.default.dim("$")} gunni image bag.png --remove-bg -o bag-clean.png
91049
- ${import_picocolors23.default.dim("$")} gunni image bag-clean.png "on marble counter" -o hero.png
91050
- ${import_picocolors23.default.dim("$")} gunni image hero.png --upscale -o hero-final.png
91076
+ ${import_picocolors23.default.dim("$")} gunni image "coffee bag product shot" -o bag
91077
+ ${import_picocolors23.default.dim("$")} gunni image bag.jpg --remove-bg -o bag-clean
91078
+ ${import_picocolors23.default.dim("$")} gunni image bag-clean.png "on marble counter" -o hero
91079
+ ${import_picocolors23.default.dim("$")} gunni image hero.jpg --upscale -o hero-final
91051
91080
 
91052
91081
  ${import_picocolors23.default.dim("Add --json to any command for structured output.")}
91053
91082
  ${import_picocolors23.default.dim("Run gunni learn to load creative expertise.")}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gunni",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "AI media toolkit — give any agent the ability to create professional media",
5
5
  "type": "module",
6
6
  "bin": {