gunni 0.3.4 → 0.3.6
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/index.js +102 -51
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -70466,7 +70466,7 @@ var ModelRouter = class {
|
|
|
70466
70466
|
const provider = this.resolveProvider(opts.model);
|
|
70467
70467
|
let spinner;
|
|
70468
70468
|
if (opts.showSpinner !== false) {
|
|
70469
|
-
spinner = ora("
|
|
70469
|
+
spinner = ora("Painting pixels\u2026").start();
|
|
70470
70470
|
}
|
|
70471
70471
|
const updateSpinner = (status) => {
|
|
70472
70472
|
if (spinner) spinner.text = status;
|
|
@@ -86261,7 +86261,7 @@ var RemoteClient = class {
|
|
|
86261
86261
|
}
|
|
86262
86262
|
}
|
|
86263
86263
|
);
|
|
86264
|
-
this.client = new Client({ name: "gunni-cli", version: "0.3.
|
|
86264
|
+
this.client = new Client({ name: "gunni-cli", version: "0.3.6" });
|
|
86265
86265
|
await this.client.connect(transport);
|
|
86266
86266
|
}
|
|
86267
86267
|
async callTool(name, args) {
|
|
@@ -86553,7 +86553,14 @@ function resolveVariantPath(template, index) {
|
|
|
86553
86553
|
return `${base}-${index}${ext}`;
|
|
86554
86554
|
}
|
|
86555
86555
|
async function handleRemote(input, prompt, operation, opts, json2, apiKey, serverUrl) {
|
|
86556
|
-
const
|
|
86556
|
+
const spinnerLabels = {
|
|
86557
|
+
generate: "Painting pixels\u2026",
|
|
86558
|
+
edit: "Reworking the canvas\u2026",
|
|
86559
|
+
describe: "Studying the image\u2026",
|
|
86560
|
+
upscale: "Enhancing resolution\u2026",
|
|
86561
|
+
"remove-bg": "Cutting out the background\u2026"
|
|
86562
|
+
};
|
|
86563
|
+
const spinner = json2 ? void 0 : ora(spinnerLabels[operation]).start();
|
|
86557
86564
|
const update = (s2) => {
|
|
86558
86565
|
if (spinner) spinner.text = s2;
|
|
86559
86566
|
};
|
|
@@ -86603,7 +86610,7 @@ async function handleRemote(input, prompt, operation, opts, json2, apiKey, serve
|
|
|
86603
86610
|
if (opts.width) toolArgs.width = opts.width;
|
|
86604
86611
|
if (opts.height) toolArgs.height = opts.height;
|
|
86605
86612
|
if (opts.seed !== void 0) toolArgs.seed = opts.seed;
|
|
86606
|
-
update(
|
|
86613
|
+
update(spinnerLabels[operation]);
|
|
86607
86614
|
const client2 = new RemoteClient();
|
|
86608
86615
|
await client2.connect(apiKey, serverUrl);
|
|
86609
86616
|
const result = await client2.callTool("image", toolArgs);
|
|
@@ -86624,7 +86631,7 @@ async function handleRemote(input, prompt, operation, opts, json2, apiKey, serve
|
|
|
86624
86631
|
const r2 = remoteResults[i2];
|
|
86625
86632
|
if (!r2.assetUrl) continue;
|
|
86626
86633
|
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("
|
|
86634
|
+
update("Saving to disk\u2026");
|
|
86628
86635
|
const finalPath2 = await downloadImage(r2.assetUrl, requestedPath2, update);
|
|
86629
86636
|
downloadedResults.push({
|
|
86630
86637
|
image: { path: finalPath2, url: r2.assetUrl, width: r2.width ?? 0, height: r2.height ?? 0 },
|
|
@@ -86656,7 +86663,7 @@ async function handleRemote(input, prompt, operation, opts, json2, apiKey, serve
|
|
|
86656
86663
|
throw new GunniError("No image in remote response", "NO_IMAGE");
|
|
86657
86664
|
}
|
|
86658
86665
|
const requestedPath = opts.output ?? `gunni-${operation}-${Date.now()}.png`;
|
|
86659
|
-
update("
|
|
86666
|
+
update("Saving to disk\u2026");
|
|
86660
86667
|
const finalPath = await downloadImage(img.assetUrl, requestedPath, update);
|
|
86661
86668
|
spinner?.succeed("Done");
|
|
86662
86669
|
if (json2) {
|
|
@@ -86724,9 +86731,9 @@ async function handleGenerate(prompt, modelId, opts, json2) {
|
|
|
86724
86731
|
return;
|
|
86725
86732
|
}
|
|
86726
86733
|
const results = [];
|
|
86727
|
-
const spinner = json2 ? void 0 : ora(`
|
|
86734
|
+
const spinner = json2 ? void 0 : ora(`Painting variant 1 of ${variantCount}\u2026`).start();
|
|
86728
86735
|
for (let i2 = 1; i2 <= variantCount; i2++) {
|
|
86729
|
-
if (spinner) spinner.text = `
|
|
86736
|
+
if (spinner) spinner.text = `Painting variant ${i2} of ${variantCount}\u2026`;
|
|
86730
86737
|
const outputPath = opts.output ? resolveVariantPath(opts.output, i2) : `gunni-${modelId}-${Date.now()}-${i2}.png`;
|
|
86731
86738
|
const router = new ModelRouter();
|
|
86732
86739
|
const result = await router.generate({
|
|
@@ -86775,15 +86782,15 @@ async function handleGenerate(prompt, modelId, opts, json2) {
|
|
|
86775
86782
|
}
|
|
86776
86783
|
async function handleEdit(imagePath, prompt, modelId, opts, json2) {
|
|
86777
86784
|
const variantCount = opts.variants ?? 1;
|
|
86778
|
-
const spinner = json2 ? void 0 : ora("
|
|
86785
|
+
const spinner = json2 ? void 0 : ora("Reworking the canvas\u2026").start();
|
|
86779
86786
|
const update = (s2) => {
|
|
86780
86787
|
if (spinner) spinner.text = s2;
|
|
86781
86788
|
};
|
|
86782
86789
|
const provider = getProviderForModel(modelId);
|
|
86783
86790
|
const results = [];
|
|
86784
86791
|
for (let i2 = 1; i2 <= variantCount; i2++) {
|
|
86785
|
-
if (variantCount > 1) update(`
|
|
86786
|
-
else update("
|
|
86792
|
+
if (variantCount > 1) update(`Reworking variant ${i2} of ${variantCount}\u2026`);
|
|
86793
|
+
else update("Reworking the canvas\u2026");
|
|
86787
86794
|
const editResult = await provider.editImage({
|
|
86788
86795
|
imagePath,
|
|
86789
86796
|
prompt,
|
|
@@ -86843,7 +86850,7 @@ async function handleEdit(imagePath, prompt, modelId, opts, json2) {
|
|
|
86843
86850
|
}
|
|
86844
86851
|
}
|
|
86845
86852
|
async function handleDescribe(imagePath, modelId, json2) {
|
|
86846
|
-
const spinner = json2 ? void 0 : ora("
|
|
86853
|
+
const spinner = json2 ? void 0 : ora("Studying the image\u2026").start();
|
|
86847
86854
|
const update = (s2) => {
|
|
86848
86855
|
if (spinner) spinner.text = s2;
|
|
86849
86856
|
};
|
|
@@ -86857,7 +86864,7 @@ async function handleDescribe(imagePath, modelId, json2) {
|
|
|
86857
86864
|
);
|
|
86858
86865
|
}
|
|
86859
86866
|
const imageUrl = await uploadToFal(imagePath, update);
|
|
86860
|
-
update("
|
|
86867
|
+
update("Reading the pixels\u2026");
|
|
86861
86868
|
const provider = new FalProvider();
|
|
86862
86869
|
const result = await provider.call(
|
|
86863
86870
|
modelDef.endpoint,
|
|
@@ -86888,7 +86895,7 @@ async function handleDescribe(imagePath, modelId, json2) {
|
|
|
86888
86895
|
}
|
|
86889
86896
|
}
|
|
86890
86897
|
async function handleUpscale(imagePath, modelId, opts, json2) {
|
|
86891
|
-
const spinner = json2 ? void 0 : ora("
|
|
86898
|
+
const spinner = json2 ? void 0 : ora("Enhancing resolution\u2026").start();
|
|
86892
86899
|
const update = (s2) => {
|
|
86893
86900
|
if (spinner) spinner.text = s2;
|
|
86894
86901
|
};
|
|
@@ -86898,7 +86905,7 @@ async function handleUpscale(imagePath, modelId, opts, json2) {
|
|
|
86898
86905
|
throw new GunniError(`Unknown model: ${modelId}`, "UNKNOWN_MODEL");
|
|
86899
86906
|
}
|
|
86900
86907
|
const imageUrl = await uploadToFal(imagePath, update);
|
|
86901
|
-
update("
|
|
86908
|
+
update("Adding more pixels\u2026");
|
|
86902
86909
|
const provider = new FalProvider();
|
|
86903
86910
|
const result = await provider.call(
|
|
86904
86911
|
modelDef.endpoint,
|
|
@@ -86947,7 +86954,7 @@ async function handleUpscale(imagePath, modelId, opts, json2) {
|
|
|
86947
86954
|
}
|
|
86948
86955
|
}
|
|
86949
86956
|
async function handleRemoveBg(imagePath, modelId, opts, json2) {
|
|
86950
|
-
const spinner = json2 ? void 0 : ora("
|
|
86957
|
+
const spinner = json2 ? void 0 : ora("Cutting out the background\u2026").start();
|
|
86951
86958
|
const update = (s2) => {
|
|
86952
86959
|
if (spinner) spinner.text = s2;
|
|
86953
86960
|
};
|
|
@@ -86957,7 +86964,7 @@ async function handleRemoveBg(imagePath, modelId, opts, json2) {
|
|
|
86957
86964
|
throw new GunniError(`Unknown model: ${modelId}`, "UNKNOWN_MODEL");
|
|
86958
86965
|
}
|
|
86959
86966
|
const imageUrl = await uploadToFal(imagePath, update);
|
|
86960
|
-
update("
|
|
86967
|
+
update("Snipping away\u2026");
|
|
86961
86968
|
const provider = new FalProvider();
|
|
86962
86969
|
const result = await provider.call(
|
|
86963
86970
|
modelDef.endpoint,
|
|
@@ -87044,7 +87051,7 @@ Run 'gunni list models --type video' for details.
|
|
|
87044
87051
|
"NO_API_KEY",
|
|
87045
87052
|
json2 ? void 0 : `Run ${import_picocolors4.default.bold("gunni")} to set up, or: gunni config --set-gunni-key YOUR_KEY`
|
|
87046
87053
|
);
|
|
87047
|
-
const spinner = json2 ? void 0 : ora("
|
|
87054
|
+
const spinner = json2 ? void 0 : ora("Rolling camera\u2026").start();
|
|
87048
87055
|
const update = (s2) => {
|
|
87049
87056
|
if (spinner) spinner.text = s2;
|
|
87050
87057
|
};
|
|
@@ -87101,7 +87108,7 @@ Run 'gunni list models --type video' for details.
|
|
|
87101
87108
|
}
|
|
87102
87109
|
}
|
|
87103
87110
|
const provider = getProviderForModel(modelId);
|
|
87104
|
-
update("
|
|
87111
|
+
update("Rendering frames\u2026");
|
|
87105
87112
|
const result = await provider.generateVideo({
|
|
87106
87113
|
prompt,
|
|
87107
87114
|
model: modelId,
|
|
@@ -87160,7 +87167,7 @@ Run 'gunni list models --type video' for details.
|
|
|
87160
87167
|
});
|
|
87161
87168
|
}
|
|
87162
87169
|
async function handleRemote2(input, opts, json2, apiKey, serverUrl) {
|
|
87163
|
-
const spinner = json2 ? void 0 : ora("
|
|
87170
|
+
const spinner = json2 ? void 0 : ora("Rolling camera\u2026").start();
|
|
87164
87171
|
const update = (s2) => {
|
|
87165
87172
|
if (spinner) spinner.text = s2;
|
|
87166
87173
|
};
|
|
@@ -87224,7 +87231,7 @@ async function handleRemote2(input, opts, json2, apiKey, serverUrl) {
|
|
|
87224
87231
|
if (imageUrl) toolArgs.image = imageUrl;
|
|
87225
87232
|
if (opts.duration !== void 0) toolArgs.duration = opts.duration;
|
|
87226
87233
|
if (opts.style) toolArgs.style = opts.style;
|
|
87227
|
-
update("
|
|
87234
|
+
update("Rendering frames\u2026");
|
|
87228
87235
|
const client2 = new RemoteClient();
|
|
87229
87236
|
await client2.connect(apiKey, serverUrl);
|
|
87230
87237
|
let result = await client2.callTool("video", toolArgs);
|
|
@@ -87250,7 +87257,7 @@ async function handleRemote2(input, opts, json2, apiKey, serverUrl) {
|
|
|
87250
87257
|
spinner?.fail("No video returned");
|
|
87251
87258
|
throw new GunniError("No video in remote response", "NO_VIDEO");
|
|
87252
87259
|
}
|
|
87253
|
-
update("
|
|
87260
|
+
update("Saving to disk\u2026");
|
|
87254
87261
|
const finalPath = await downloadMedia(videoAssetUrl, requestedPath, update);
|
|
87255
87262
|
let audioPath;
|
|
87256
87263
|
const audioAssetUrl = result.audio?.assetUrl;
|
|
@@ -87325,7 +87332,7 @@ Run 'gunni list models --type audio' for details.
|
|
|
87325
87332
|
"NO_API_KEY",
|
|
87326
87333
|
json2 ? void 0 : `Run ${import_picocolors5.default.bold("gunni")} to set up, or: gunni config --set-gunni-key YOUR_KEY`
|
|
87327
87334
|
);
|
|
87328
|
-
const spinner = json2 ? void 0 : ora("
|
|
87335
|
+
const spinner = json2 ? void 0 : ora("Finding the right voice\u2026").start();
|
|
87329
87336
|
const update = (s2) => {
|
|
87330
87337
|
if (spinner) spinner.text = s2;
|
|
87331
87338
|
};
|
|
@@ -87349,7 +87356,7 @@ Run 'gunni list models --type audio' for details.
|
|
|
87349
87356
|
falInput.audio_url = opts.voice;
|
|
87350
87357
|
}
|
|
87351
87358
|
}
|
|
87352
|
-
update("
|
|
87359
|
+
update("Recording the take\u2026");
|
|
87353
87360
|
const provider = new FalProvider();
|
|
87354
87361
|
const result = await provider.call(endpoint, falInput, update);
|
|
87355
87362
|
const data = result.data;
|
|
@@ -87401,7 +87408,7 @@ function getEndpoint(modelId) {
|
|
|
87401
87408
|
return model.endpoint;
|
|
87402
87409
|
}
|
|
87403
87410
|
async function handleRemote3(text, opts, json2, apiKey, serverUrl) {
|
|
87404
|
-
const spinner = json2 ? void 0 : ora("
|
|
87411
|
+
const spinner = json2 ? void 0 : ora("Finding the right voice\u2026").start();
|
|
87405
87412
|
const update = (s2) => {
|
|
87406
87413
|
if (spinner) spinner.text = s2;
|
|
87407
87414
|
};
|
|
@@ -87419,7 +87426,7 @@ async function handleRemote3(text, opts, json2, apiKey, serverUrl) {
|
|
|
87419
87426
|
throw new GunniError("No audio in remote response", "NO_AUDIO");
|
|
87420
87427
|
}
|
|
87421
87428
|
const requestedPath = opts.output ?? `gunni-audio-${Date.now()}.mp3`;
|
|
87422
|
-
update("
|
|
87429
|
+
update("Saving to disk\u2026");
|
|
87423
87430
|
const finalPath = await downloadMedia(audioAssetUrl, requestedPath, update);
|
|
87424
87431
|
spinner?.succeed("Done");
|
|
87425
87432
|
const output = {
|
|
@@ -87493,7 +87500,7 @@ Run 'gunni list models --type lipsync' for details.
|
|
|
87493
87500
|
"NO_API_KEY",
|
|
87494
87501
|
json2 ? void 0 : `Run ${import_picocolors6.default.bold("gunni")} to set up, or: gunni config --set-gunni-key YOUR_KEY`
|
|
87495
87502
|
);
|
|
87496
|
-
const spinner = json2 ? void 0 : ora("
|
|
87503
|
+
const spinner = json2 ? void 0 : ora("Matching lips to audio\u2026").start();
|
|
87497
87504
|
const update = (s2) => {
|
|
87498
87505
|
if (spinner) spinner.text = s2;
|
|
87499
87506
|
};
|
|
@@ -87506,7 +87513,7 @@ Run 'gunni list models --type lipsync' for details.
|
|
|
87506
87513
|
);
|
|
87507
87514
|
}
|
|
87508
87515
|
const provider = new FalProvider();
|
|
87509
|
-
update("
|
|
87516
|
+
update("Animating the performance\u2026");
|
|
87510
87517
|
const result = await provider.generateLipsync({
|
|
87511
87518
|
model: modelId,
|
|
87512
87519
|
videoPath: opts.video,
|
|
@@ -87556,7 +87563,7 @@ Run 'gunni list models --type lipsync' for details.
|
|
|
87556
87563
|
});
|
|
87557
87564
|
}
|
|
87558
87565
|
async function handleRemote4(audio, opts, json2, apiKey, serverUrl) {
|
|
87559
|
-
const spinner = json2 ? void 0 : ora("
|
|
87566
|
+
const spinner = json2 ? void 0 : ora("Matching lips to audio\u2026").start();
|
|
87560
87567
|
const update = (s2) => {
|
|
87561
87568
|
if (spinner) spinner.text = s2;
|
|
87562
87569
|
};
|
|
@@ -87591,7 +87598,7 @@ async function handleRemote4(audio, opts, json2, apiKey, serverUrl) {
|
|
|
87591
87598
|
};
|
|
87592
87599
|
if (videoUrl) toolArgs.video = videoUrl;
|
|
87593
87600
|
if (imageUrl) toolArgs.image = imageUrl;
|
|
87594
|
-
update("
|
|
87601
|
+
update("Animating the performance\u2026");
|
|
87595
87602
|
const client2 = new RemoteClient();
|
|
87596
87603
|
await client2.connect(apiKey, serverUrl);
|
|
87597
87604
|
let result = await client2.callTool("lipsync", toolArgs);
|
|
@@ -87617,7 +87624,7 @@ async function handleRemote4(audio, opts, json2, apiKey, serverUrl) {
|
|
|
87617
87624
|
throw new GunniError("No video in remote lip sync response", "NO_VIDEO");
|
|
87618
87625
|
}
|
|
87619
87626
|
const requestedPath = opts.output ?? `gunni-lipsync-${Date.now()}.mp4`;
|
|
87620
|
-
update("
|
|
87627
|
+
update("Saving to disk\u2026");
|
|
87621
87628
|
const finalPath = await downloadMedia(videoAssetUrl, requestedPath, update);
|
|
87622
87629
|
spinner?.succeed("Done");
|
|
87623
87630
|
const output = {
|
|
@@ -87715,7 +87722,32 @@ var knowledge_default = {
|
|
|
87715
87722
|
overview: {
|
|
87716
87723
|
topic: "overview",
|
|
87717
87724
|
title: "Gunni Overview",
|
|
87718
|
-
content:
|
|
87725
|
+
content: `Gunni tools for professional media creation:
|
|
87726
|
+
|
|
87727
|
+
CREATE: image (generate/edit/describe/upscale/remove-bg, routes by input), video, audio, lipsync
|
|
87728
|
+
PRODUCTION: templates (proven prompts with variables), styles (visual direction), presets (platform rules), pipelines (multi-step workflows), refs (reference images)
|
|
87729
|
+
UTILITY: models (list models + updates), history (search past work), learn (you're here)
|
|
87730
|
+
|
|
87731
|
+
ROUTING (image): prompt only \u2192 generate, image+prompt \u2192 edit, image only \u2192 describe, +upscale/remove_bg flags
|
|
87732
|
+
MULTI-IMAGE: pass an array of URLs to image for multi-ref editing
|
|
87733
|
+
|
|
87734
|
+
PRODUCTION SYSTEM:
|
|
87735
|
+
- templates() \u2014 Browse proven prompts with [variable] placeholders. Use template_save to create your own.
|
|
87736
|
+
- styles() \u2014 Saved visual directions (colors, mood, typography). Apply to any generation for brand consistency. Use style_create to save.
|
|
87737
|
+
- presets() \u2014 Platform rules (TikTok, IG, YouTube). Auto-applies aspect ratio, framing, prompt modifiers. Use preset_create to save.
|
|
87738
|
+
- pipelines() \u2014 Multi-step workflows chaining templates + presets + tools. Call pipelines(name) then orchestrate step by step. See learn("pipelines") for execution guide.
|
|
87739
|
+
- refs() \u2014 Reference images in collections. Save with ref_save, use as style/character refs or edit inputs.
|
|
87740
|
+
These compose: pipelines use templates and presets, presets reference styles, styles reference refs.
|
|
87741
|
+
|
|
87742
|
+
USER IMAGE UPLOADS: When a user provides or pastes an image and you need to use it as input (for editing, video, describe, etc.), you MUST call upload_ref first. The image/video tools require a URL (https://...), not a local file path. Workflow:
|
|
87743
|
+
1. Call upload_ref with a name for the reference
|
|
87744
|
+
2. The user uploads their file via the Gunni Studio UI
|
|
87745
|
+
3. After upload completes, use the resulting URL in image/video tools
|
|
87746
|
+
Never pass a local file path to image or video. It will fail.
|
|
87747
|
+
|
|
87748
|
+
PROJECT SYSTEM: BRIEF.md (creative direction), .gunni/assets.json (lineage), .gunni/seeds.json (proven seeds)
|
|
87749
|
+
|
|
87750
|
+
IMPORTANT: Every generation response includes a galleryUrl. Always share it with the user so they can view results in full resolution.`
|
|
87719
87751
|
},
|
|
87720
87752
|
exploration: {
|
|
87721
87753
|
topic: "exploration",
|
|
@@ -87859,14 +87891,17 @@ KEY PRINCIPLES
|
|
|
87859
87891
|
}
|
|
87860
87892
|
},
|
|
87861
87893
|
latest: {
|
|
87862
|
-
version: "0.
|
|
87863
|
-
date: "2026-
|
|
87894
|
+
version: "0.3.4",
|
|
87895
|
+
date: "2026-03-29",
|
|
87864
87896
|
updates: [
|
|
87897
|
+
"Production system: templates (proven prompts with variables), styles (visual direction), presets (platform rules), pipelines (multi-step workflows).",
|
|
87898
|
+
"Refs: save, organize, and reuse reference images across projects in named collections.",
|
|
87899
|
+
"Lipsync: lip-sync audio onto video, or generate talking head from image + audio.",
|
|
87900
|
+
"Visual research: discover visual trends and references for creative direction.",
|
|
87901
|
+
'Pipeline orchestration: chain templates, presets, styles, and tools into complete deliverables. See learn("pipelines").',
|
|
87865
87902
|
"Unified image tool: generate, edit, describe, upscale, remove-bg. Routes by input.",
|
|
87866
|
-
"Multi-image editing: pass array of URLs for multi-ref edits
|
|
87867
|
-
"
|
|
87868
|
-
"Variants flag for creative exploration.",
|
|
87869
|
-
"Latest updates merged into models (pass updates=true). refs now handles both list and get."
|
|
87903
|
+
"Multi-image editing: pass array of URLs for multi-ref edits.",
|
|
87904
|
+
"Variants flag for creative exploration."
|
|
87870
87905
|
]
|
|
87871
87906
|
}
|
|
87872
87907
|
};
|
|
@@ -90861,7 +90896,7 @@ async function runOnboarding() {
|
|
|
90861
90896
|
|
|
90862
90897
|
// src/index.ts
|
|
90863
90898
|
var program2 = new Command();
|
|
90864
|
-
program2.name("gunni").description("AI media toolkit \u2014 give any agent the ability to create professional media").version("0.3.
|
|
90899
|
+
program2.name("gunni").description("AI media toolkit \u2014 give any agent the ability to create professional media").version("0.3.6").option("--json", "Output results as JSON").addHelpText(
|
|
90865
90900
|
"after",
|
|
90866
90901
|
`
|
|
90867
90902
|
Examples:
|
|
@@ -90947,14 +90982,20 @@ program2.action(async () => {
|
|
|
90947
90982
|
{ name: "image", usage: 'gunni image "<prompt>" -o output.png', description: "Generate, edit, describe, upscale, or remove background (smart routing)" },
|
|
90948
90983
|
{ name: "video", usage: 'gunni video <image> -p "<prompt>" -o output.mp4', description: "Generate video from image or text" },
|
|
90949
90984
|
{ name: "audio", usage: 'gunni audio "<text>" -o output.mp3', description: "Generate speech audio from text" },
|
|
90985
|
+
{ name: "template", usage: "gunni template list", description: "Browse & use proven prompt templates with fill-in variables" },
|
|
90986
|
+
{ name: "style", usage: "gunni style list", description: "Saved visual directions (colors, mood, tone) for consistent output" },
|
|
90987
|
+
{ name: "preset", usage: "gunni preset list", description: "Platform production rules (TikTok, IG, YouTube \u2014 aspect ratio, framing)" },
|
|
90988
|
+
{ name: "pipeline", usage: "gunni pipeline list", description: "Multi-step production workflows chaining templates, presets, and tools" },
|
|
90989
|
+
{ name: "ref", usage: "gunni ref list", description: "Reference images organized in collections for reuse across projects" },
|
|
90950
90990
|
{ name: "learn", usage: "gunni learn [topic]", description: "Load creative expertise and best practices" },
|
|
90991
|
+
{ name: "guide", usage: "gunni list guides", description: "Step-by-step creative playbooks with prompt templates" },
|
|
90951
90992
|
{ name: "latest", usage: "gunni latest", description: "Check for new models, features, updates" },
|
|
90952
90993
|
{ name: "init", usage: "gunni init [--template brand|ui|campaign]", description: "Initialize a Gunni project" },
|
|
90953
90994
|
{ name: "history", usage: 'gunni history ["query"]', description: "Search past generations" },
|
|
90954
|
-
{ name: "
|
|
90995
|
+
{ name: "models", usage: "gunni models [--type <category>]", description: "List available models" },
|
|
90955
90996
|
{ name: "config", usage: "gunni config", description: "Manage API keys" }
|
|
90956
90997
|
];
|
|
90957
|
-
console.log(JSON.stringify({ version: "0.3.
|
|
90998
|
+
console.log(JSON.stringify({ version: "0.3.6", commands, categories, models }, null, 2));
|
|
90958
90999
|
return;
|
|
90959
91000
|
}
|
|
90960
91001
|
const configured = await hasGunniKey();
|
|
@@ -90964,27 +91005,37 @@ program2.action(async () => {
|
|
|
90964
91005
|
return;
|
|
90965
91006
|
}
|
|
90966
91007
|
console.log(`
|
|
90967
|
-
${import_picocolors23.default.
|
|
91008
|
+
${import_picocolors23.default.cyan(` ________ ___ ___ ________ ________ ___`)}
|
|
91009
|
+
${import_picocolors23.default.cyan(`|\\ ____\\|\\ \\|\\ \\|\\ ___ \\|\\ ___ \\|\\ \\`)}
|
|
91010
|
+
${import_picocolors23.default.cyan(`\\ \\ \\___|\\ \\ \\\\\\ \\ \\ \\\\ \\ \\ \\ \\\\ \\ \\ \\ \\`)}
|
|
91011
|
+
${import_picocolors23.default.cyan(` \\ \\ \\ __\\ \\ \\\\\\ \\ \\ \\\\ \\ \\ \\ \\\\ \\ \\ \\ \\`)}
|
|
91012
|
+
${import_picocolors23.default.cyan(` \\ \\ \\|\\ \\ \\ \\\\\\ \\ \\ \\\\ \\ \\ \\ \\\\ \\ \\ \\ \\`)}
|
|
91013
|
+
${import_picocolors23.default.cyan(` \\ \\_______\\ \\_______\\ \\__\\\\ \\__\\ \\__\\\\ \\__\\ \\__\\`)}
|
|
91014
|
+
${import_picocolors23.default.cyan(` \\|_______|\\|_______|\\|__| \\|__|\\|__| \\|__|\\|__|`)}
|
|
90968
91015
|
|
|
90969
|
-
${import_picocolors23.default.
|
|
91016
|
+
${import_picocolors23.default.dim(`v0.3.4 \u2014 AI media toolkit`)}
|
|
91017
|
+
|
|
91018
|
+
${import_picocolors23.default.bold("Create:")}
|
|
90970
91019
|
${import_picocolors23.default.cyan("image")} Generate, edit, describe, upscale, remove-bg ${import_picocolors23.default.dim('gunni image "a cat" -o cat.png')}
|
|
90971
91020
|
${import_picocolors23.default.cyan("video")} Image/text \u2192 video ${import_picocolors23.default.dim('gunni video hero.png -p "zoom in"')}
|
|
90972
91021
|
${import_picocolors23.default.cyan("audio")} Text \u2192 speech ${import_picocolors23.default.dim('gunni audio "Hello" -o hello.mp3')}
|
|
90973
91022
|
|
|
90974
91023
|
${import_picocolors23.default.bold("Production:")}
|
|
90975
|
-
${import_picocolors23.default.cyan("template")}
|
|
90976
|
-
${import_picocolors23.default.cyan("
|
|
90977
|
-
${import_picocolors23.default.cyan("
|
|
90978
|
-
${import_picocolors23.default.cyan("
|
|
90979
|
-
|
|
90980
|
-
|
|
90981
|
-
|
|
91024
|
+
${import_picocolors23.default.cyan("template")} Proven prompts with variables you fill in ${import_picocolors23.default.dim("gunni template list")}
|
|
91025
|
+
${import_picocolors23.default.cyan("style")} Saved visual direction (colors, mood, tone) ${import_picocolors23.default.dim("gunni style list")}
|
|
91026
|
+
${import_picocolors23.default.cyan("preset")} Platform rules (TikTok, IG, YouTube, etc.) ${import_picocolors23.default.dim("gunni preset list")}
|
|
91027
|
+
${import_picocolors23.default.cyan("pipeline")} Multi-step workflows that chain it all ${import_picocolors23.default.dim("gunni pipeline list")}
|
|
91028
|
+
${import_picocolors23.default.cyan("ref")} Reference images for consistent output ${import_picocolors23.default.dim("gunni ref list")}
|
|
91029
|
+
|
|
91030
|
+
${import_picocolors23.default.bold("Learn:")}
|
|
91031
|
+
${import_picocolors23.default.cyan("learn")} Creative expertise & best practices ${import_picocolors23.default.dim("gunni learn overview")}
|
|
91032
|
+
${import_picocolors23.default.cyan("guide")} Step-by-step creative playbooks ${import_picocolors23.default.dim("gunni list guides")}
|
|
90982
91033
|
${import_picocolors23.default.cyan("latest")} New models, features, updates ${import_picocolors23.default.dim("gunni latest")}
|
|
90983
91034
|
|
|
90984
91035
|
${import_picocolors23.default.bold("Utility:")}
|
|
90985
91036
|
${import_picocolors23.default.cyan("init")} Start a new project ${import_picocolors23.default.dim("gunni init --template brand")}
|
|
90986
91037
|
${import_picocolors23.default.cyan("history")} Search past work ${import_picocolors23.default.dim('gunni history "coffee"')}
|
|
90987
|
-
${import_picocolors23.default.cyan("
|
|
91038
|
+
${import_picocolors23.default.cyan("models")} Discover available models ${import_picocolors23.default.dim("gunni models")}
|
|
90988
91039
|
${import_picocolors23.default.cyan("config")} API key setup ${import_picocolors23.default.dim("gunni config")}
|
|
90989
91040
|
|
|
90990
91041
|
${import_picocolors23.default.bold("Models:")} ${import_picocolors23.default.dim(`${getAllModels().length} curated models`)}`);
|