@vm0/cli 9.163.3 → 9.165.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/{chunk-5CUISL3U.js → chunk-JUNONYIH.js} +3 -9
- package/{chunk-5CUISL3U.js.map → chunk-JUNONYIH.js.map} +1 -1
- package/index.js +9 -9
- package/package.json +1 -1
- package/zero.js +406 -226
- package/zero.js.map +1 -1
package/zero.js
CHANGED
|
@@ -152,7 +152,7 @@ import {
|
|
|
152
152
|
zeroAgentCustomSkillNameSchema,
|
|
153
153
|
zeroLocalAgentCommand,
|
|
154
154
|
zeroTokenAllowsFeatureSwitch
|
|
155
|
-
} from "./chunk-
|
|
155
|
+
} from "./chunk-JUNONYIH.js";
|
|
156
156
|
import {
|
|
157
157
|
__toESM,
|
|
158
158
|
init_esm_shims
|
|
@@ -7158,218 +7158,16 @@ init_esm_shims();
|
|
|
7158
7158
|
// src/commands/zero/shared/image-generate.ts
|
|
7159
7159
|
init_esm_shims();
|
|
7160
7160
|
import { readFileSync as readFileSync13 } from "fs";
|
|
7161
|
-
function readPrompt(options, usageCommand) {
|
|
7162
|
-
if (options.prompt?.trim()) {
|
|
7163
|
-
return options.prompt.trim();
|
|
7164
|
-
}
|
|
7165
|
-
if (process.stdin.isTTY === false) {
|
|
7166
|
-
const prompt = readFileSync13("/dev/stdin", "utf8").trim();
|
|
7167
|
-
if (prompt.length > 0) {
|
|
7168
|
-
return prompt;
|
|
7169
|
-
}
|
|
7170
|
-
}
|
|
7171
|
-
throw new Error("--prompt is required", {
|
|
7172
|
-
cause: new Error(`Usage: ${usageCommand} --prompt "A watercolor fox"`)
|
|
7173
|
-
});
|
|
7174
|
-
}
|
|
7175
|
-
function parseCompression(value) {
|
|
7176
|
-
if (value === void 0) {
|
|
7177
|
-
return void 0;
|
|
7178
|
-
}
|
|
7179
|
-
const compression = Number(value);
|
|
7180
|
-
if (!Number.isInteger(compression) || compression < 0 || compression > 100) {
|
|
7181
|
-
throw new Error("--compression must be an integer from 0 to 100");
|
|
7182
|
-
}
|
|
7183
|
-
return compression;
|
|
7184
|
-
}
|
|
7185
|
-
function parseSeed(value) {
|
|
7186
|
-
const seed = Number(value);
|
|
7187
|
-
if (!Number.isInteger(seed) || seed < 0 || !Number.isSafeInteger(seed)) {
|
|
7188
|
-
throw new InvalidArgumentError("seed must be a non-negative safe integer");
|
|
7189
|
-
}
|
|
7190
|
-
return seed;
|
|
7191
|
-
}
|
|
7192
|
-
function collectString(value, previous) {
|
|
7193
|
-
return [...previous, value];
|
|
7194
|
-
}
|
|
7195
|
-
function parseInputFidelity(value) {
|
|
7196
|
-
if (value === void 0) {
|
|
7197
|
-
return void 0;
|
|
7198
|
-
}
|
|
7199
|
-
if (value !== "low" && value !== "high") {
|
|
7200
|
-
throw new Error("--input-fidelity must be low or high");
|
|
7201
|
-
}
|
|
7202
|
-
return value;
|
|
7203
|
-
}
|
|
7204
|
-
function parseImagePromptStrength(value) {
|
|
7205
|
-
if (value === void 0) {
|
|
7206
|
-
return void 0;
|
|
7207
|
-
}
|
|
7208
|
-
const strength = Number(value);
|
|
7209
|
-
if (!Number.isFinite(strength) || strength < 0 || strength > 1) {
|
|
7210
|
-
throw new Error("--image-prompt-strength must be a number from 0 to 1");
|
|
7211
|
-
}
|
|
7212
|
-
return strength;
|
|
7213
|
-
}
|
|
7214
|
-
function createImageGenerateCommand(config) {
|
|
7215
|
-
return new Command().name(config.name).description("Generate a billed image file from a prompt").option("--prompt <text>", "Image prompt; can also be piped via stdin").option(
|
|
7216
|
-
"--model <model>",
|
|
7217
|
-
"Model: gpt-image-1 (default), gpt-image-2, gpt-image-1.5, gpt-image-1-mini, flux-pro-1.1, flux-pro-1.1-ultra, qwen-image, or seedream4",
|
|
7218
|
-
"gpt-image-1"
|
|
7219
|
-
).option(
|
|
7220
|
-
"--size <size>",
|
|
7221
|
-
"Image size: auto or WIDTHxHEIGHT; support varies by model",
|
|
7222
|
-
"1024x1024"
|
|
7223
|
-
).option(
|
|
7224
|
-
"--quality <quality>",
|
|
7225
|
-
"Image quality: low, medium, high, or auto",
|
|
7226
|
-
"medium"
|
|
7227
|
-
).option(
|
|
7228
|
-
"--background <background>",
|
|
7229
|
-
"Background: auto, opaque, or transparent when supported",
|
|
7230
|
-
"auto"
|
|
7231
|
-
).option("--format <format>", "Output format: png, webp, or jpeg", "png").option("--compression <0-100>", "Output compression for jpeg/webp only").option(
|
|
7232
|
-
"--moderation <moderation>",
|
|
7233
|
-
"Moderation strictness: auto or low",
|
|
7234
|
-
"auto"
|
|
7235
|
-
).option("--seed <integer>", "Deterministic seed for fal models", parseSeed).option("--safety-tolerance <level>", "fal safety tolerance: 1-6", "4").option("--enhance-prompt", "Enable fal prompt enhancement when supported").option(
|
|
7236
|
-
"--image-url <url>",
|
|
7237
|
-
"Source/mockup image URL for image-to-image; repeat for multi-image edit models",
|
|
7238
|
-
collectString,
|
|
7239
|
-
[]
|
|
7240
|
-
).option(
|
|
7241
|
-
"--mask-image-url <url>",
|
|
7242
|
-
"Mask image URL for supported edit models"
|
|
7243
|
-
).option(
|
|
7244
|
-
"--input-fidelity <low|high>",
|
|
7245
|
-
"Source-image fidelity for GPT edit models"
|
|
7246
|
-
).option(
|
|
7247
|
-
"--image-prompt-strength <0-1>",
|
|
7248
|
-
"Reference strength override for Flux Redux"
|
|
7249
|
-
).option("--json", "Print metadata as JSON").addHelpText(
|
|
7250
|
-
"after",
|
|
7251
|
-
`
|
|
7252
|
-
Examples:
|
|
7253
|
-
${config.examples}
|
|
7254
|
-
|
|
7255
|
-
Output:
|
|
7256
|
-
Prints the generated /f/ image file URL and metadata
|
|
7257
|
-
|
|
7258
|
-
Notes:
|
|
7259
|
-
- Authenticates via ZERO_TOKEN (requires file:write capability)
|
|
7260
|
-
- Charges org credits after successful image generation
|
|
7261
|
-
- Uses fal.ai for all image model execution
|
|
7262
|
-
|
|
7263
|
-
Models:
|
|
7264
|
-
- fal.ai: gpt-image-1 (default), gpt-image-2, gpt-image-1.5,
|
|
7265
|
-
gpt-image-1-mini, flux-pro-1.1, flux-pro-1.1-ultra, qwen-image,
|
|
7266
|
-
seedream4.
|
|
7267
|
-
GPT Image models bill by fal output image quality and size.
|
|
7268
|
-
Other fal generations bill by output image or rounded-up output
|
|
7269
|
-
megapixel, depending on the model.
|
|
7270
|
-
|
|
7271
|
-
Options:
|
|
7272
|
-
- Prompt: required, up to 32,000 characters; stdin is supported.
|
|
7273
|
-
- Size: gpt-image-2 accepts auto or WIDTHxHEIGHT. Popular sizes include
|
|
7274
|
-
1024x1024,
|
|
7275
|
-
1536x1024, 1024x1536, 2048x2048, 2048x1152, 3840x2160,
|
|
7276
|
-
and 2160x3840. Custom sizes must have edges <= 3840px, both
|
|
7277
|
-
edges divisible by 16, long:short ratio <= 3:1, and total pixels
|
|
7278
|
-
between 655,360 and 8,294,400. gpt-image-1.5, gpt-image-1, and
|
|
7279
|
-
gpt-image-1-mini use auto, 1024x1024, 1536x1024, or 1024x1536.
|
|
7280
|
-
- Quality: low, medium, high, or auto. Low is fastest for drafts.
|
|
7281
|
-
- Background: auto, opaque, or transparent when supported. gpt-image-2,
|
|
7282
|
-
Flux, Qwen, and Seedream do not support transparent backgrounds.
|
|
7283
|
-
- Format: png, jpeg, or webp for GPT Image models; png or jpeg for the
|
|
7284
|
-
other fal models.
|
|
7285
|
-
- fal-only controls: --seed, --safety-tolerance for Flux, and
|
|
7286
|
-
--enhance-prompt for flux-pro-1.1. --compression and --moderation low are
|
|
7287
|
-
not supported on the fal-backed image path.
|
|
7288
|
-
- Image-to-image: pass --image-url to use the model's fal edit/redux endpoint.
|
|
7289
|
-
Flux Redux accepts --image-prompt-strength to override the provider
|
|
7290
|
-
default; GPT edit models accept --input-fidelity and supported models
|
|
7291
|
-
accept --mask-image-url.`
|
|
7292
|
-
).action(
|
|
7293
|
-
withErrorHandler(async (options, command) => {
|
|
7294
|
-
const prompt = readPrompt(options, config.usageCommand);
|
|
7295
|
-
const compression = parseCompression(options.compression);
|
|
7296
|
-
const inputFidelity = parseInputFidelity(options.inputFidelity);
|
|
7297
|
-
const imagePromptStrength = parseImagePromptStrength(
|
|
7298
|
-
options.imagePromptStrength
|
|
7299
|
-
);
|
|
7300
|
-
const hasSourceImage = options.imageUrl.length > 0;
|
|
7301
|
-
const size = hasSourceImage && command.getOptionValueSource("size") === "default" ? "auto" : options.size;
|
|
7302
|
-
const result = await generateWebImage({
|
|
7303
|
-
prompt,
|
|
7304
|
-
model: options.model,
|
|
7305
|
-
size,
|
|
7306
|
-
quality: options.quality,
|
|
7307
|
-
background: options.background,
|
|
7308
|
-
outputFormat: options.format,
|
|
7309
|
-
outputCompression: compression,
|
|
7310
|
-
moderation: options.moderation,
|
|
7311
|
-
seed: options.seed,
|
|
7312
|
-
safetyTolerance: options.safetyTolerance,
|
|
7313
|
-
enhancePrompt: options.enhancePrompt,
|
|
7314
|
-
imageUrls: options.imageUrl,
|
|
7315
|
-
maskImageUrl: options.maskImageUrl,
|
|
7316
|
-
inputFidelity,
|
|
7317
|
-
imagePromptStrength
|
|
7318
|
-
});
|
|
7319
|
-
if (options.json) {
|
|
7320
|
-
console.log(JSON.stringify(result));
|
|
7321
|
-
return;
|
|
7322
|
-
}
|
|
7323
|
-
console.log(source_default.green(`\u2713 Image generated: ${result.url}`));
|
|
7324
|
-
console.log(source_default.dim(` File: ${result.filename}`));
|
|
7325
|
-
console.log(source_default.dim(` Size: ${result.imageSize}`));
|
|
7326
|
-
console.log(source_default.dim(` Quality: ${result.quality}`));
|
|
7327
|
-
console.log(source_default.dim(` Format: ${result.outputFormat}`));
|
|
7328
|
-
if (result.outputCompression !== void 0) {
|
|
7329
|
-
console.log(source_default.dim(` Compression: ${result.outputCompression}`));
|
|
7330
|
-
}
|
|
7331
|
-
if (result.moderation) {
|
|
7332
|
-
console.log(source_default.dim(` Moderation: ${result.moderation}`));
|
|
7333
|
-
}
|
|
7334
|
-
if (result.safetyTolerance) {
|
|
7335
|
-
console.log(
|
|
7336
|
-
source_default.dim(` Safety tolerance: ${result.safetyTolerance}`)
|
|
7337
|
-
);
|
|
7338
|
-
}
|
|
7339
|
-
if (result.seed !== void 0) {
|
|
7340
|
-
console.log(source_default.dim(` Seed: ${result.seed}`));
|
|
7341
|
-
}
|
|
7342
|
-
console.log(source_default.dim(` Credits charged: ${result.creditsCharged}`));
|
|
7343
|
-
console.log(source_default.dim(` Model: ${result.model}`));
|
|
7344
|
-
console.log(source_default.dim(` Provider: ${result.provider}`));
|
|
7345
|
-
})
|
|
7346
|
-
);
|
|
7347
|
-
}
|
|
7348
|
-
|
|
7349
|
-
// src/commands/zero/built-in/generate/image.ts
|
|
7350
|
-
var imageCommand = createImageGenerateCommand({
|
|
7351
|
-
name: "image",
|
|
7352
|
-
usageCommand: "zero built-in generate image",
|
|
7353
|
-
examples: ` Generate image: zero built-in generate image --prompt "A watercolor fox"
|
|
7354
|
-
Pipe prompt: cat prompt.txt | zero built-in generate image
|
|
7355
|
-
GPT Image model: zero built-in generate image --model gpt-image-1.5 --prompt "A poster" --size 1024x1536 --quality high
|
|
7356
|
-
Flux model: zero built-in generate image --model flux-pro-1.1 --prompt "A product hero shot" --seed 42
|
|
7357
|
-
Image-to-image: zero built-in generate image --model flux-pro-1.1 --image-url https://example.com/mockup.png --prompt "Turn this mockup into a polished product shot"`
|
|
7358
|
-
});
|
|
7359
7161
|
|
|
7360
|
-
// src/commands/zero/
|
|
7361
|
-
init_esm_shims();
|
|
7362
|
-
|
|
7363
|
-
// src/commands/zero/shared/open-design-artifact-generate.ts
|
|
7162
|
+
// src/commands/zero/shared/image-style-authoring.ts
|
|
7364
7163
|
init_esm_shims();
|
|
7365
|
-
import { readFileSync as readFileSync14 } from "fs";
|
|
7366
7164
|
|
|
7367
7165
|
// src/commands/zero/shared/open-design-registry.ts
|
|
7368
7166
|
init_esm_shims();
|
|
7369
7167
|
var OPEN_DESIGN_REPO = "vm0-ai/open-design";
|
|
7370
7168
|
var OPEN_DESIGN_COMMIT = "d021b04720ace133f1d6133d1487326f5fc28f07";
|
|
7371
|
-
var
|
|
7372
|
-
var
|
|
7169
|
+
var VM0_SKILLS_REPO = "vm0-ai/vm0-skills";
|
|
7170
|
+
var VM0_SKILLS_REF = "main";
|
|
7373
7171
|
var OPEN_DESIGN_REGISTRY_VERSION = `federated:${OPEN_DESIGN_REPO}@${OPEN_DESIGN_COMMIT}`;
|
|
7374
7172
|
function sourceRef(repo, commit, path) {
|
|
7375
7173
|
return {
|
|
@@ -7643,12 +7441,8 @@ var OPEN_DESIGN_REGISTRY = [
|
|
|
7643
7441
|
kind: "image-style",
|
|
7644
7442
|
name: "Notion Illustration",
|
|
7645
7443
|
description: "Zero-native illustration style for hand-drawn product spot illustrations with simple ink contours and soft backgrounds.",
|
|
7646
|
-
source: sourceRef(
|
|
7647
|
-
|
|
7648
|
-
NOTION_ILLUSTRATION_COMMIT,
|
|
7649
|
-
".claude/skills/notion-illustration"
|
|
7650
|
-
),
|
|
7651
|
-
targets: ["website", "poster", "presentation", "report"],
|
|
7444
|
+
source: sourceRef(VM0_SKILLS_REPO, VM0_SKILLS_REF, "notion-illustration"),
|
|
7445
|
+
targets: ["image", "website", "poster", "presentation", "report"],
|
|
7652
7446
|
tags: ["image", "illustration", "notion", "spot", "hand-drawn", "product"],
|
|
7653
7447
|
triggers: [
|
|
7654
7448
|
"illustration",
|
|
@@ -7669,6 +7463,46 @@ var OPEN_DESIGN_REGISTRY = [
|
|
|
7669
7463
|
remixHint: "prompt-with-resource-hints",
|
|
7670
7464
|
status: "experimental",
|
|
7671
7465
|
priority: 18
|
|
7466
|
+
},
|
|
7467
|
+
{
|
|
7468
|
+
id: "vm0:image-style:vm0-illustration",
|
|
7469
|
+
kind: "image-style",
|
|
7470
|
+
name: "vm0 Illustration",
|
|
7471
|
+
description: "vm0 in-app spot illustration style with bold hand-drawn ink line art, white-filled interiors, and a soft rounded color backdrop.",
|
|
7472
|
+
source: sourceRef(
|
|
7473
|
+
VM0_SKILLS_REPO,
|
|
7474
|
+
VM0_SKILLS_REF,
|
|
7475
|
+
"illustration-template/vm0-illustration"
|
|
7476
|
+
),
|
|
7477
|
+
targets: ["image", "website", "poster", "presentation", "report"],
|
|
7478
|
+
tags: [
|
|
7479
|
+
"image",
|
|
7480
|
+
"illustration",
|
|
7481
|
+
"spot",
|
|
7482
|
+
"in-app",
|
|
7483
|
+
"empty-state",
|
|
7484
|
+
"hand-drawn",
|
|
7485
|
+
"vm0"
|
|
7486
|
+
],
|
|
7487
|
+
triggers: [
|
|
7488
|
+
"vm0 style",
|
|
7489
|
+
"in-app illustration",
|
|
7490
|
+
"empty state illustration",
|
|
7491
|
+
"vm0 illustration",
|
|
7492
|
+
"soft rounded color backdrop"
|
|
7493
|
+
],
|
|
7494
|
+
bestFor: [
|
|
7495
|
+
"in-app empty states",
|
|
7496
|
+
"billing and permission illustrations",
|
|
7497
|
+
"small product state artwork"
|
|
7498
|
+
],
|
|
7499
|
+
outputKinds: ["image"],
|
|
7500
|
+
primaryOutputKind: "image",
|
|
7501
|
+
executorHints: ["skill-authored", "built-in-image"],
|
|
7502
|
+
previewHint: "image",
|
|
7503
|
+
remixHint: "prompt-with-resource-hints",
|
|
7504
|
+
status: "experimental",
|
|
7505
|
+
priority: 19
|
|
7672
7506
|
}
|
|
7673
7507
|
];
|
|
7674
7508
|
function toOpenDesignTarget(value) {
|
|
@@ -7747,8 +7581,8 @@ function selectOpenDesignCandidates(options) {
|
|
|
7747
7581
|
commit: OPEN_DESIGN_COMMIT
|
|
7748
7582
|
},
|
|
7749
7583
|
{
|
|
7750
|
-
repo:
|
|
7751
|
-
commit:
|
|
7584
|
+
repo: VM0_SKILLS_REPO,
|
|
7585
|
+
commit: VM0_SKILLS_REF
|
|
7752
7586
|
}
|
|
7753
7587
|
],
|
|
7754
7588
|
candidates: {
|
|
@@ -7798,6 +7632,351 @@ function selectOpenDesignCandidates(options) {
|
|
|
7798
7632
|
};
|
|
7799
7633
|
}
|
|
7800
7634
|
|
|
7635
|
+
// src/commands/zero/shared/image-style-authoring.ts
|
|
7636
|
+
var outputDir = "./opendesign/images";
|
|
7637
|
+
var artifactRules = [
|
|
7638
|
+
"Select the image style that best matches the prompt before generation.",
|
|
7639
|
+
"Resolve the selected style source before generating the image.",
|
|
7640
|
+
"Use the style skill's referenced assets and generation path when it provides one.",
|
|
7641
|
+
"Produce a single final image file and keep any temporary metadata under the output directory."
|
|
7642
|
+
];
|
|
7643
|
+
function createStyledImageAuthoringPacket(options) {
|
|
7644
|
+
const candidateSlice = selectOpenDesignCandidates({
|
|
7645
|
+
target: "image",
|
|
7646
|
+
prompt: [options.prompt, ...options.details, ...artifactRules].join("\n")
|
|
7647
|
+
});
|
|
7648
|
+
const selectionSchema = {
|
|
7649
|
+
imageStyle: "string",
|
|
7650
|
+
skills: "string[]",
|
|
7651
|
+
rationale: "string"
|
|
7652
|
+
};
|
|
7653
|
+
const artifact = {
|
|
7654
|
+
outputMode: "primary-image",
|
|
7655
|
+
primaryArtifact: {
|
|
7656
|
+
kind: "image",
|
|
7657
|
+
path: `${outputDir}/`
|
|
7658
|
+
},
|
|
7659
|
+
supportingAssets: [
|
|
7660
|
+
{
|
|
7661
|
+
kind: "metadata",
|
|
7662
|
+
path: `${outputDir}/metadata.json`,
|
|
7663
|
+
optional: true
|
|
7664
|
+
}
|
|
7665
|
+
],
|
|
7666
|
+
previewKind: "image",
|
|
7667
|
+
outputDir
|
|
7668
|
+
};
|
|
7669
|
+
const instructions = [
|
|
7670
|
+
"# Zero built-in generate image --styled",
|
|
7671
|
+
"",
|
|
7672
|
+
"This is a federated generation resource-selection packet for the current agent.",
|
|
7673
|
+
"Zero is not generating this image on the server yet. You select resources, resolve them, and generate the styled image.",
|
|
7674
|
+
"",
|
|
7675
|
+
"## User Prompt",
|
|
7676
|
+
options.prompt,
|
|
7677
|
+
"",
|
|
7678
|
+
"## Stage 1: Resource Selection",
|
|
7679
|
+
"- Choose an image style from the bundled federated registry slice below.",
|
|
7680
|
+
"- Choose only IDs present in this packet; do not invent registry IDs.",
|
|
7681
|
+
"- Prefer image-style resources with matching triggers, but the user prompt is the highest-priority signal.",
|
|
7682
|
+
"- Treat the selection JSON as internal working state, then continue to generation.",
|
|
7683
|
+
"",
|
|
7684
|
+
"## Selection Output Schema",
|
|
7685
|
+
"```json",
|
|
7686
|
+
JSON.stringify(selectionSchema, null, 2),
|
|
7687
|
+
"```",
|
|
7688
|
+
"",
|
|
7689
|
+
"## Candidate Registry Slice",
|
|
7690
|
+
`Registry: \`${candidateSlice.registryVersion}\``,
|
|
7691
|
+
"",
|
|
7692
|
+
"```json",
|
|
7693
|
+
JSON.stringify(candidateSlice.candidates, null, 2),
|
|
7694
|
+
"```",
|
|
7695
|
+
"",
|
|
7696
|
+
"## Stage 2: Resolve Selected Resources",
|
|
7697
|
+
"- Fetch or read the selected resource source before generation.",
|
|
7698
|
+
"- Source refs are pinned as `repo@commit:path`; use the commit in the packet for reproducibility.",
|
|
7699
|
+
"- For directory refs, inspect the most relevant files such as `SKILL.md`, references, examples, and templates.",
|
|
7700
|
+
"- If a source file cannot be fetched, state that limitation and fall back to the registry metadata for that resource.",
|
|
7701
|
+
"",
|
|
7702
|
+
"## Stage 3: Generate Image",
|
|
7703
|
+
"- Generate one production-quality image using the selected style.",
|
|
7704
|
+
"- Follow the selected style skill's generation path when it defines one.",
|
|
7705
|
+
"- If the style skill delegates to a model or connector, use that flow directly instead of restating the style text manually.",
|
|
7706
|
+
"",
|
|
7707
|
+
"## Artifact Output Model",
|
|
7708
|
+
`- Primary artifact: \`${artifact.primaryArtifact.kind}\` under \`${artifact.primaryArtifact.path}\`.`,
|
|
7709
|
+
`- Output mode: \`${artifact.outputMode}\`.`,
|
|
7710
|
+
"- Supporting metadata may live inside the same output directory when useful.",
|
|
7711
|
+
"",
|
|
7712
|
+
"## Requested Parameters",
|
|
7713
|
+
...options.details.map((detail) => {
|
|
7714
|
+
return `- ${detail}`;
|
|
7715
|
+
}),
|
|
7716
|
+
"",
|
|
7717
|
+
"## Image Authoring Rules",
|
|
7718
|
+
...artifactRules.map((rule) => {
|
|
7719
|
+
return `- ${rule}`;
|
|
7720
|
+
}),
|
|
7721
|
+
"",
|
|
7722
|
+
"## Verification",
|
|
7723
|
+
"- Verify the final image exists and is nonblank.",
|
|
7724
|
+
"- Check that the selected style's required reference anchors or source assets were used when applicable.",
|
|
7725
|
+
"- Report the final image URL or path and the selected registry resource ID."
|
|
7726
|
+
].join("\n");
|
|
7727
|
+
return {
|
|
7728
|
+
type: "open-design-resource-selection",
|
|
7729
|
+
kind: "image",
|
|
7730
|
+
prompt: options.prompt,
|
|
7731
|
+
registryVersion: candidateSlice.registryVersion,
|
|
7732
|
+
artifact,
|
|
7733
|
+
selection: {
|
|
7734
|
+
candidates: candidateSlice.candidates,
|
|
7735
|
+
outputSchema: selectionSchema
|
|
7736
|
+
},
|
|
7737
|
+
authoring: {
|
|
7738
|
+
details: options.details,
|
|
7739
|
+
artifactRules
|
|
7740
|
+
},
|
|
7741
|
+
outputDir,
|
|
7742
|
+
instructions
|
|
7743
|
+
};
|
|
7744
|
+
}
|
|
7745
|
+
|
|
7746
|
+
// src/commands/zero/shared/image-generate.ts
|
|
7747
|
+
function readPrompt(options, usageCommand) {
|
|
7748
|
+
if (options.prompt?.trim()) {
|
|
7749
|
+
return options.prompt.trim();
|
|
7750
|
+
}
|
|
7751
|
+
if (process.stdin.isTTY === false) {
|
|
7752
|
+
const prompt = readFileSync13("/dev/stdin", "utf8").trim();
|
|
7753
|
+
if (prompt.length > 0) {
|
|
7754
|
+
return prompt;
|
|
7755
|
+
}
|
|
7756
|
+
}
|
|
7757
|
+
throw new Error("--prompt is required", {
|
|
7758
|
+
cause: new Error(`Usage: ${usageCommand} --prompt "A watercolor fox"`)
|
|
7759
|
+
});
|
|
7760
|
+
}
|
|
7761
|
+
function parseCompression(value) {
|
|
7762
|
+
if (value === void 0) {
|
|
7763
|
+
return void 0;
|
|
7764
|
+
}
|
|
7765
|
+
const compression = Number(value);
|
|
7766
|
+
if (!Number.isInteger(compression) || compression < 0 || compression > 100) {
|
|
7767
|
+
throw new Error("--compression must be an integer from 0 to 100");
|
|
7768
|
+
}
|
|
7769
|
+
return compression;
|
|
7770
|
+
}
|
|
7771
|
+
function parseSeed(value) {
|
|
7772
|
+
const seed = Number(value);
|
|
7773
|
+
if (!Number.isInteger(seed) || seed < 0 || !Number.isSafeInteger(seed)) {
|
|
7774
|
+
throw new InvalidArgumentError("seed must be a non-negative safe integer");
|
|
7775
|
+
}
|
|
7776
|
+
return seed;
|
|
7777
|
+
}
|
|
7778
|
+
function collectString(value, previous) {
|
|
7779
|
+
return [...previous, value];
|
|
7780
|
+
}
|
|
7781
|
+
function parseInputFidelity(value) {
|
|
7782
|
+
if (value === void 0) {
|
|
7783
|
+
return void 0;
|
|
7784
|
+
}
|
|
7785
|
+
if (value !== "low" && value !== "high") {
|
|
7786
|
+
throw new Error("--input-fidelity must be low or high");
|
|
7787
|
+
}
|
|
7788
|
+
return value;
|
|
7789
|
+
}
|
|
7790
|
+
function parseImagePromptStrength(value) {
|
|
7791
|
+
if (value === void 0) {
|
|
7792
|
+
return void 0;
|
|
7793
|
+
}
|
|
7794
|
+
const strength = Number(value);
|
|
7795
|
+
if (!Number.isFinite(strength) || strength < 0 || strength > 1) {
|
|
7796
|
+
throw new Error("--image-prompt-strength must be a number from 0 to 1");
|
|
7797
|
+
}
|
|
7798
|
+
return strength;
|
|
7799
|
+
}
|
|
7800
|
+
function createImageGenerateCommand(config) {
|
|
7801
|
+
return new Command().name(config.name).description("Generate a billed image file from a prompt").option("--prompt <text>", "Image prompt; can also be piped via stdin").option(
|
|
7802
|
+
"--model <model>",
|
|
7803
|
+
"Model: gpt-image-1 (default), gpt-image-2, gpt-image-1.5, gpt-image-1-mini, flux-pro-1.1, flux-pro-1.1-ultra, qwen-image, or seedream4",
|
|
7804
|
+
"gpt-image-1"
|
|
7805
|
+
).option(
|
|
7806
|
+
"--size <size>",
|
|
7807
|
+
"Image size: auto or WIDTHxHEIGHT; support varies by model",
|
|
7808
|
+
"1024x1024"
|
|
7809
|
+
).option(
|
|
7810
|
+
"--quality <quality>",
|
|
7811
|
+
"Image quality: low, medium, high, or auto",
|
|
7812
|
+
"medium"
|
|
7813
|
+
).option(
|
|
7814
|
+
"--background <background>",
|
|
7815
|
+
"Background: auto, opaque, or transparent when supported",
|
|
7816
|
+
"auto"
|
|
7817
|
+
).option("--format <format>", "Output format: png, webp, or jpeg", "png").option("--compression <0-100>", "Output compression for jpeg/webp only").option(
|
|
7818
|
+
"--moderation <moderation>",
|
|
7819
|
+
"Moderation strictness: auto or low",
|
|
7820
|
+
"auto"
|
|
7821
|
+
).option("--seed <integer>", "Deterministic seed for fal models", parseSeed).option("--safety-tolerance <level>", "fal safety tolerance: 1-6", "4").option("--enhance-prompt", "Enable fal prompt enhancement when supported").option(
|
|
7822
|
+
"--image-url <url>",
|
|
7823
|
+
"Source/mockup image URL for image-to-image; repeat for multi-image edit models",
|
|
7824
|
+
collectString,
|
|
7825
|
+
[]
|
|
7826
|
+
).option(
|
|
7827
|
+
"--mask-image-url <url>",
|
|
7828
|
+
"Mask image URL for supported edit models"
|
|
7829
|
+
).option(
|
|
7830
|
+
"--input-fidelity <low|high>",
|
|
7831
|
+
"Source-image fidelity for GPT edit models"
|
|
7832
|
+
).option(
|
|
7833
|
+
"--image-prompt-strength <0-1>",
|
|
7834
|
+
"Reference strength override for Flux Redux"
|
|
7835
|
+
).option(
|
|
7836
|
+
"--styled",
|
|
7837
|
+
"Print a resource-selection packet for styled image generation"
|
|
7838
|
+
).option("--json", "Print metadata as JSON").addHelpText(
|
|
7839
|
+
"after",
|
|
7840
|
+
`
|
|
7841
|
+
Examples:
|
|
7842
|
+
${config.examples}
|
|
7843
|
+
|
|
7844
|
+
Output:
|
|
7845
|
+
Prints the generated /f/ image file URL and metadata. With --styled, prints
|
|
7846
|
+
an Open Design resource-selection packet for the current agent.
|
|
7847
|
+
|
|
7848
|
+
Notes:
|
|
7849
|
+
- Authenticates via ZERO_TOKEN (requires file:write capability)
|
|
7850
|
+
- Charges org credits after successful image generation
|
|
7851
|
+
- Uses fal.ai for all image model execution
|
|
7852
|
+
|
|
7853
|
+
Models:
|
|
7854
|
+
- fal.ai: gpt-image-1 (default), gpt-image-2, gpt-image-1.5,
|
|
7855
|
+
gpt-image-1-mini, flux-pro-1.1, flux-pro-1.1-ultra, qwen-image,
|
|
7856
|
+
seedream4.
|
|
7857
|
+
GPT Image models bill by fal output image quality and size.
|
|
7858
|
+
Other fal generations bill by output image or rounded-up output
|
|
7859
|
+
megapixel, depending on the model.
|
|
7860
|
+
|
|
7861
|
+
Options:
|
|
7862
|
+
- Prompt: required, up to 32,000 characters; stdin is supported.
|
|
7863
|
+
- Size: gpt-image-2 accepts auto or WIDTHxHEIGHT. Popular sizes include
|
|
7864
|
+
1024x1024,
|
|
7865
|
+
1536x1024, 1024x1536, 2048x2048, 2048x1152, 3840x2160,
|
|
7866
|
+
and 2160x3840. Custom sizes must have edges <= 3840px, both
|
|
7867
|
+
edges divisible by 16, long:short ratio <= 3:1, and total pixels
|
|
7868
|
+
between 655,360 and 8,294,400. gpt-image-1.5, gpt-image-1, and
|
|
7869
|
+
gpt-image-1-mini use auto, 1024x1024, 1536x1024, or 1024x1536.
|
|
7870
|
+
- Quality: low, medium, high, or auto. Low is fastest for drafts.
|
|
7871
|
+
- Background: auto, opaque, or transparent when supported. gpt-image-2,
|
|
7872
|
+
Flux, Qwen, and Seedream do not support transparent backgrounds.
|
|
7873
|
+
- Format: png, jpeg, or webp for GPT Image models; png or jpeg for the
|
|
7874
|
+
other fal models.
|
|
7875
|
+
- fal-only controls: --seed, --safety-tolerance for Flux, and
|
|
7876
|
+
--enhance-prompt for flux-pro-1.1. --compression and --moderation low are
|
|
7877
|
+
not supported on the fal-backed image path.
|
|
7878
|
+
- Image-to-image: pass --image-url to use the model's fal edit/redux endpoint.
|
|
7879
|
+
Flux Redux accepts --image-prompt-strength to override the provider
|
|
7880
|
+
default; GPT edit models accept --input-fidelity and supported models
|
|
7881
|
+
accept --mask-image-url.
|
|
7882
|
+
- Styled mode: pass --styled to select an image style resource first. In this
|
|
7883
|
+
mode the agent resolves the selected style source and generates the image.`
|
|
7884
|
+
).action(
|
|
7885
|
+
withErrorHandler(async (options, command) => {
|
|
7886
|
+
const prompt = readPrompt(options, config.usageCommand);
|
|
7887
|
+
if (options.styled) {
|
|
7888
|
+
const packet = createStyledImageAuthoringPacket({
|
|
7889
|
+
prompt,
|
|
7890
|
+
details: [
|
|
7891
|
+
`Model preference if direct image generation is used: ${options.model}`,
|
|
7892
|
+
`Requested size: ${options.size}`,
|
|
7893
|
+
`Requested quality: ${options.quality}`,
|
|
7894
|
+
`Requested background: ${options.background}`,
|
|
7895
|
+
`Requested format: ${options.format}`,
|
|
7896
|
+
`Source image URLs: ${options.imageUrl.length > 0 ? options.imageUrl.join(", ") : "none"}`,
|
|
7897
|
+
`Mask image URL: ${options.maskImageUrl ?? "none"}`
|
|
7898
|
+
]
|
|
7899
|
+
});
|
|
7900
|
+
if (options.json) {
|
|
7901
|
+
console.log(JSON.stringify(packet));
|
|
7902
|
+
return;
|
|
7903
|
+
}
|
|
7904
|
+
console.log(packet.instructions);
|
|
7905
|
+
return;
|
|
7906
|
+
}
|
|
7907
|
+
const compression = parseCompression(options.compression);
|
|
7908
|
+
const inputFidelity = parseInputFidelity(options.inputFidelity);
|
|
7909
|
+
const imagePromptStrength = parseImagePromptStrength(
|
|
7910
|
+
options.imagePromptStrength
|
|
7911
|
+
);
|
|
7912
|
+
const hasSourceImage = options.imageUrl.length > 0;
|
|
7913
|
+
const size = hasSourceImage && command.getOptionValueSource("size") === "default" ? "auto" : options.size;
|
|
7914
|
+
const result = await generateWebImage({
|
|
7915
|
+
prompt,
|
|
7916
|
+
model: options.model,
|
|
7917
|
+
size,
|
|
7918
|
+
quality: options.quality,
|
|
7919
|
+
background: options.background,
|
|
7920
|
+
outputFormat: options.format,
|
|
7921
|
+
outputCompression: compression,
|
|
7922
|
+
moderation: options.moderation,
|
|
7923
|
+
seed: options.seed,
|
|
7924
|
+
safetyTolerance: options.safetyTolerance,
|
|
7925
|
+
enhancePrompt: options.enhancePrompt,
|
|
7926
|
+
imageUrls: options.imageUrl,
|
|
7927
|
+
maskImageUrl: options.maskImageUrl,
|
|
7928
|
+
inputFidelity,
|
|
7929
|
+
imagePromptStrength
|
|
7930
|
+
});
|
|
7931
|
+
if (options.json) {
|
|
7932
|
+
console.log(JSON.stringify(result));
|
|
7933
|
+
return;
|
|
7934
|
+
}
|
|
7935
|
+
console.log(source_default.green(`\u2713 Image generated: ${result.url}`));
|
|
7936
|
+
console.log(source_default.dim(` File: ${result.filename}`));
|
|
7937
|
+
console.log(source_default.dim(` Size: ${result.imageSize}`));
|
|
7938
|
+
console.log(source_default.dim(` Quality: ${result.quality}`));
|
|
7939
|
+
console.log(source_default.dim(` Format: ${result.outputFormat}`));
|
|
7940
|
+
if (result.outputCompression !== void 0) {
|
|
7941
|
+
console.log(source_default.dim(` Compression: ${result.outputCompression}`));
|
|
7942
|
+
}
|
|
7943
|
+
if (result.moderation) {
|
|
7944
|
+
console.log(source_default.dim(` Moderation: ${result.moderation}`));
|
|
7945
|
+
}
|
|
7946
|
+
if (result.safetyTolerance) {
|
|
7947
|
+
console.log(
|
|
7948
|
+
source_default.dim(` Safety tolerance: ${result.safetyTolerance}`)
|
|
7949
|
+
);
|
|
7950
|
+
}
|
|
7951
|
+
if (result.seed !== void 0) {
|
|
7952
|
+
console.log(source_default.dim(` Seed: ${result.seed}`));
|
|
7953
|
+
}
|
|
7954
|
+
console.log(source_default.dim(` Credits charged: ${result.creditsCharged}`));
|
|
7955
|
+
console.log(source_default.dim(` Model: ${result.model}`));
|
|
7956
|
+
console.log(source_default.dim(` Provider: ${result.provider}`));
|
|
7957
|
+
})
|
|
7958
|
+
);
|
|
7959
|
+
}
|
|
7960
|
+
|
|
7961
|
+
// src/commands/zero/built-in/generate/image.ts
|
|
7962
|
+
var imageCommand = createImageGenerateCommand({
|
|
7963
|
+
name: "image",
|
|
7964
|
+
usageCommand: "zero built-in generate image",
|
|
7965
|
+
examples: ` Generate image: zero built-in generate image --prompt "A watercolor fox"
|
|
7966
|
+
Pipe prompt: cat prompt.txt | zero built-in generate image
|
|
7967
|
+
Styled image: zero built-in generate image --styled --prompt "A product manager mapping a launch plan"
|
|
7968
|
+
GPT Image model: zero built-in generate image --model gpt-image-1.5 --prompt "A poster" --size 1024x1536 --quality high
|
|
7969
|
+
Flux model: zero built-in generate image --model flux-pro-1.1 --prompt "A product hero shot" --seed 42
|
|
7970
|
+
Image-to-image: zero built-in generate image --model flux-pro-1.1 --image-url https://example.com/mockup.png --prompt "Turn this mockup into a polished product shot"`
|
|
7971
|
+
});
|
|
7972
|
+
|
|
7973
|
+
// src/commands/zero/built-in/generate/open-design-artifacts.ts
|
|
7974
|
+
init_esm_shims();
|
|
7975
|
+
|
|
7976
|
+
// src/commands/zero/shared/open-design-artifact-generate.ts
|
|
7977
|
+
init_esm_shims();
|
|
7978
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
7979
|
+
|
|
7801
7980
|
// src/commands/zero/shared/html-artifact-authoring.ts
|
|
7802
7981
|
init_esm_shims();
|
|
7803
7982
|
function slugify(value) {
|
|
@@ -7806,6 +7985,7 @@ function slugify(value) {
|
|
|
7806
7985
|
}
|
|
7807
7986
|
function titleForKind(kind) {
|
|
7808
7987
|
const titles = {
|
|
7988
|
+
image: "image",
|
|
7809
7989
|
presentation: "HTML presentation",
|
|
7810
7990
|
website: "hosted website",
|
|
7811
7991
|
"dashboard-design": "dashboard design prototype",
|
|
@@ -7822,8 +8002,8 @@ function outputDirForSite(site) {
|
|
|
7822
8002
|
}
|
|
7823
8003
|
function createHtmlArtifactAuthoringPacket(options) {
|
|
7824
8004
|
const site = options.site ?? slugify(options.slugSource ?? options.prompt);
|
|
7825
|
-
const
|
|
7826
|
-
const hostCommand = `zero host ${
|
|
8005
|
+
const outputDir2 = outputDirForSite(site);
|
|
8006
|
+
const hostCommand = `zero host ${outputDir2} --site ${site}${options.kind === "website" ? " --spa" : ""}`;
|
|
7827
8007
|
const title = titleForKind(options.kind);
|
|
7828
8008
|
const candidateSlice = selectOpenDesignCandidates({
|
|
7829
8009
|
target: options.kind,
|
|
@@ -7848,32 +8028,32 @@ function createHtmlArtifactAuthoringPacket(options) {
|
|
|
7848
8028
|
outputMode: "primary-artifact-with-supporting-assets",
|
|
7849
8029
|
primaryArtifact: {
|
|
7850
8030
|
kind: options.kind,
|
|
7851
|
-
path: `${
|
|
8031
|
+
path: `${outputDir2}/index.html`
|
|
7852
8032
|
},
|
|
7853
8033
|
supportingAssets: [
|
|
7854
8034
|
{
|
|
7855
8035
|
kind: "image",
|
|
7856
|
-
path: `${
|
|
8036
|
+
path: `${outputDir2}/assets/`,
|
|
7857
8037
|
optional: true
|
|
7858
8038
|
},
|
|
7859
8039
|
{
|
|
7860
8040
|
kind: "audio",
|
|
7861
|
-
path: `${
|
|
8041
|
+
path: `${outputDir2}/assets/`,
|
|
7862
8042
|
optional: true
|
|
7863
8043
|
},
|
|
7864
8044
|
{
|
|
7865
8045
|
kind: "video",
|
|
7866
|
-
path: `${
|
|
8046
|
+
path: `${outputDir2}/assets/`,
|
|
7867
8047
|
optional: true
|
|
7868
8048
|
},
|
|
7869
8049
|
{
|
|
7870
8050
|
kind: "metadata",
|
|
7871
|
-
path: `${
|
|
8051
|
+
path: `${outputDir2}/metadata.json`,
|
|
7872
8052
|
optional: true
|
|
7873
8053
|
}
|
|
7874
8054
|
],
|
|
7875
8055
|
previewKind: "hosted-url",
|
|
7876
|
-
outputDir
|
|
8056
|
+
outputDir: outputDir2
|
|
7877
8057
|
};
|
|
7878
8058
|
const instructions = [
|
|
7879
8059
|
`# Zero built-in generate ${options.kind}`,
|
|
@@ -7919,8 +8099,8 @@ function createHtmlArtifactAuthoringPacket(options) {
|
|
|
7919
8099
|
"- Treat the output directory as a project bundle when multiple media types are generated, while keeping the HTML entry point primary.",
|
|
7920
8100
|
"",
|
|
7921
8101
|
"## Output Contract",
|
|
7922
|
-
`- Write the artifact under \`${
|
|
7923
|
-
`- The entry file must be \`${
|
|
8102
|
+
`- Write the artifact under \`${outputDir2}/\`.`,
|
|
8103
|
+
`- The entry file must be \`${outputDir2}/index.html\`.`,
|
|
7924
8104
|
"- Keep every local asset inside the same output directory.",
|
|
7925
8105
|
"- Do not reference files from another project path.",
|
|
7926
8106
|
"- Use descriptive filenames and canonical HTML: close non-void tags and double-quote attributes.",
|
|
@@ -7971,7 +8151,7 @@ function createHtmlArtifactAuthoringPacket(options) {
|
|
|
7971
8151
|
details: options.details,
|
|
7972
8152
|
artifactRules: options.artifactRules
|
|
7973
8153
|
},
|
|
7974
|
-
outputDir,
|
|
8154
|
+
outputDir: outputDir2,
|
|
7975
8155
|
site,
|
|
7976
8156
|
hostCommand,
|
|
7977
8157
|
instructions
|
|
@@ -9899,7 +10079,7 @@ function registerZeroCommands(prog, commands) {
|
|
|
9899
10079
|
var program = new Command();
|
|
9900
10080
|
program.name("zero").description(
|
|
9901
10081
|
"Zero CLI \u2014 interact with the zero platform from inside the sandbox"
|
|
9902
|
-
).version("9.
|
|
10082
|
+
).version("9.165.0").addHelpText("after", () => {
|
|
9903
10083
|
return buildZeroHelpText();
|
|
9904
10084
|
});
|
|
9905
10085
|
if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {
|