@vm0/cli 9.161.6 → 9.161.8
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-DYDX54LP.js → chunk-BWCVGYRL.js} +862 -579
- package/{chunk-DYDX54LP.js.map → chunk-BWCVGYRL.js.map} +1 -1
- package/index.js +9 -9
- package/package.json +1 -1
- package/zero.js +452 -13
- package/zero.js.map +1 -1
package/index.js
CHANGED
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
source_default,
|
|
69
69
|
volumeConfigSchema,
|
|
70
70
|
withErrorHandler
|
|
71
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-BWCVGYRL.js";
|
|
72
72
|
import {
|
|
73
73
|
__toESM,
|
|
74
74
|
init_esm_shims
|
|
@@ -387,7 +387,7 @@ function getConfigPath() {
|
|
|
387
387
|
return join(os.homedir(), ".vm0", "config.json");
|
|
388
388
|
}
|
|
389
389
|
var infoCommand = new Command().name("info").description("Display environment and debug information").action(async () => {
|
|
390
|
-
console.log(source_default.bold(`VM0 CLI v${"9.161.
|
|
390
|
+
console.log(source_default.bold(`VM0 CLI v${"9.161.8"}`));
|
|
391
391
|
console.log();
|
|
392
392
|
const config = await loadConfig();
|
|
393
393
|
const hasEnvToken = !!process.env.VM0_TOKEN;
|
|
@@ -4280,7 +4280,7 @@ var composeCommand = new Command().name("compose").description("Create or update
|
|
|
4280
4280
|
options.autoUpdate = false;
|
|
4281
4281
|
}
|
|
4282
4282
|
if (options.autoUpdate !== false) {
|
|
4283
|
-
await startSilentUpgrade("9.161.
|
|
4283
|
+
await startSilentUpgrade("9.161.8");
|
|
4284
4284
|
}
|
|
4285
4285
|
try {
|
|
4286
4286
|
let result;
|
|
@@ -4372,7 +4372,7 @@ var mainRunCommand = new Command().name("run").description("Run an agent").argum
|
|
|
4372
4372
|
withErrorHandler(
|
|
4373
4373
|
async (identifier, prompt, options) => {
|
|
4374
4374
|
if (options.autoUpdate !== false) {
|
|
4375
|
-
await startSilentUpgrade("9.161.
|
|
4375
|
+
await startSilentUpgrade("9.161.8");
|
|
4376
4376
|
}
|
|
4377
4377
|
const { name, version } = parseIdentifier(identifier);
|
|
4378
4378
|
let composeId;
|
|
@@ -6165,13 +6165,13 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
|
|
|
6165
6165
|
if (latestVersion === null) {
|
|
6166
6166
|
throw new Error("Could not check for updates. Please try again later.");
|
|
6167
6167
|
}
|
|
6168
|
-
if (latestVersion === "9.161.
|
|
6169
|
-
console.log(source_default.green(`\u2713 Already up to date (${"9.161.
|
|
6168
|
+
if (latestVersion === "9.161.8") {
|
|
6169
|
+
console.log(source_default.green(`\u2713 Already up to date (${"9.161.8"})`));
|
|
6170
6170
|
return;
|
|
6171
6171
|
}
|
|
6172
6172
|
console.log(
|
|
6173
6173
|
source_default.yellow(
|
|
6174
|
-
`Current version: ${"9.161.
|
|
6174
|
+
`Current version: ${"9.161.8"} -> Latest version: ${latestVersion}`
|
|
6175
6175
|
)
|
|
6176
6176
|
);
|
|
6177
6177
|
console.log();
|
|
@@ -6198,7 +6198,7 @@ var upgradeCommand = new Command().name("upgrade").description("Upgrade vm0 CLI
|
|
|
6198
6198
|
const success = await performUpgrade(packageManager);
|
|
6199
6199
|
if (success) {
|
|
6200
6200
|
console.log(
|
|
6201
|
-
source_default.green(`\u2713 Upgraded from ${"9.161.
|
|
6201
|
+
source_default.green(`\u2713 Upgraded from ${"9.161.8"} to ${latestVersion}`)
|
|
6202
6202
|
);
|
|
6203
6203
|
return;
|
|
6204
6204
|
}
|
|
@@ -6265,7 +6265,7 @@ var whoamiCommand = new Command().name("whoami").description("Show current ident
|
|
|
6265
6265
|
|
|
6266
6266
|
// src/index.ts
|
|
6267
6267
|
var program = new Command();
|
|
6268
|
-
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.161.
|
|
6268
|
+
program.name("vm0").description("VM0 CLI - Build and run agents with natural language").version("9.161.8");
|
|
6269
6269
|
program.addCommand(authCommand);
|
|
6270
6270
|
program.addCommand(infoCommand);
|
|
6271
6271
|
program.addCommand(composeCommand);
|
package/package.json
CHANGED
package/zero.js
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
createLocalBrowserWriteCommand,
|
|
26
26
|
createSkill,
|
|
27
27
|
createZeroAgent,
|
|
28
|
+
createZeroCreditCheckout,
|
|
28
29
|
createZeroRun,
|
|
29
30
|
decodeCliTokenPayload,
|
|
30
31
|
decodeZeroTokenPayload,
|
|
@@ -73,6 +74,7 @@ import {
|
|
|
73
74
|
getZeroAgent,
|
|
74
75
|
getZeroAgentInstructions,
|
|
75
76
|
getZeroAgentUserConnectors,
|
|
77
|
+
getZeroBillingStatus,
|
|
76
78
|
getZeroConnector,
|
|
77
79
|
getZeroOrg,
|
|
78
80
|
getZeroOrgMembers,
|
|
@@ -148,7 +150,7 @@ import {
|
|
|
148
150
|
zeroAgentCustomSkillNameSchema,
|
|
149
151
|
zeroLocalAgentCommand,
|
|
150
152
|
zeroTokenAllowsFeatureSwitch
|
|
151
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-BWCVGYRL.js";
|
|
152
154
|
import {
|
|
153
155
|
__commonJS,
|
|
154
156
|
__require,
|
|
@@ -29828,6 +29830,62 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
|
|
|
29828
29830
|
// src/commands/zero/connector/index.ts
|
|
29829
29831
|
var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(searchCommand).addCommand(statusCommand2);
|
|
29830
29832
|
|
|
29833
|
+
// src/commands/zero/credit.ts
|
|
29834
|
+
init_esm_shims();
|
|
29835
|
+
function parseCredits(value) {
|
|
29836
|
+
const credits = Number(value.replaceAll(",", ""));
|
|
29837
|
+
if (!Number.isInteger(credits) || credits <= 0) {
|
|
29838
|
+
throw new Error("credits must be a positive integer");
|
|
29839
|
+
}
|
|
29840
|
+
return credits;
|
|
29841
|
+
}
|
|
29842
|
+
var zeroCreditCommand = new Command().name("credit").description("Create a Stripe checkout link to buy credits").argument("<credits>", "Number of credits to buy", parseCredits).addOption(
|
|
29843
|
+
new Option("--auto-recharge", "Enable auto-recharge after checkout")
|
|
29844
|
+
).option(
|
|
29845
|
+
"--auto-recharge-threshold <credits>",
|
|
29846
|
+
"Recharge when balance is at or below this number of credits",
|
|
29847
|
+
parseCredits
|
|
29848
|
+
).option(
|
|
29849
|
+
"--auto-recharge-amount <credits>",
|
|
29850
|
+
"Credits to buy for each auto-recharge",
|
|
29851
|
+
parseCredits
|
|
29852
|
+
).action(
|
|
29853
|
+
withErrorHandler(
|
|
29854
|
+
async (credits, options) => {
|
|
29855
|
+
const members = await getZeroOrgMembers();
|
|
29856
|
+
if (members.role !== "admin") {
|
|
29857
|
+
console.log(
|
|
29858
|
+
source_default.yellow(
|
|
29859
|
+
"Only organization admins can buy credits. Run `zero doctor credit` to see the current credit status and org admins."
|
|
29860
|
+
)
|
|
29861
|
+
);
|
|
29862
|
+
return;
|
|
29863
|
+
}
|
|
29864
|
+
const origin = await getPlatformOrigin();
|
|
29865
|
+
const successUrl = `${origin}/?settings=usage&credit=success`;
|
|
29866
|
+
const cancelUrl = `${origin}/?settings=usage&credit=canceled`;
|
|
29867
|
+
const autoRecharge = options.autoRecharge === void 0 && options.autoRechargeThreshold === void 0 && options.autoRechargeAmount === void 0 ? void 0 : {
|
|
29868
|
+
enabled: options.autoRecharge === true,
|
|
29869
|
+
threshold: options.autoRechargeThreshold,
|
|
29870
|
+
amount: options.autoRechargeAmount
|
|
29871
|
+
};
|
|
29872
|
+
if (autoRecharge?.enabled === true && (autoRecharge.threshold === void 0 || autoRecharge.amount === void 0)) {
|
|
29873
|
+
throw new Error(
|
|
29874
|
+
"--auto-recharge requires --auto-recharge-threshold and --auto-recharge-amount"
|
|
29875
|
+
);
|
|
29876
|
+
}
|
|
29877
|
+
const result = await createZeroCreditCheckout({
|
|
29878
|
+
credits,
|
|
29879
|
+
successUrl,
|
|
29880
|
+
cancelUrl,
|
|
29881
|
+
...autoRecharge ? { autoRecharge } : {}
|
|
29882
|
+
});
|
|
29883
|
+
console.log(source_default.bold("Credit checkout link:"));
|
|
29884
|
+
console.log(result.url);
|
|
29885
|
+
}
|
|
29886
|
+
)
|
|
29887
|
+
);
|
|
29888
|
+
|
|
29831
29889
|
// src/commands/zero/doctor/index.ts
|
|
29832
29890
|
init_esm_shims();
|
|
29833
29891
|
|
|
@@ -30905,8 +30963,67 @@ Notes:
|
|
|
30905
30963
|
)
|
|
30906
30964
|
);
|
|
30907
30965
|
|
|
30966
|
+
// src/commands/zero/doctor/credit.ts
|
|
30967
|
+
init_esm_shims();
|
|
30968
|
+
function memberName(member) {
|
|
30969
|
+
const name = [member.firstName, member.lastName].filter(Boolean).join(" ");
|
|
30970
|
+
return name ? `${name} <${member.email}>` : member.email;
|
|
30971
|
+
}
|
|
30972
|
+
var creditCommand = new Command().name("credit").description("Diagnose current organization credit and purchase access").action(
|
|
30973
|
+
withErrorHandler(async () => {
|
|
30974
|
+
const [org, billing, members] = await Promise.all([
|
|
30975
|
+
getZeroOrg(),
|
|
30976
|
+
getZeroBillingStatus(),
|
|
30977
|
+
getZeroOrgMembers()
|
|
30978
|
+
]);
|
|
30979
|
+
const admins = members.members.filter((member) => {
|
|
30980
|
+
return member.role === "admin";
|
|
30981
|
+
});
|
|
30982
|
+
const isAdmin = members.role === "admin";
|
|
30983
|
+
const canPurchaseCredits = isAdmin;
|
|
30984
|
+
console.log(source_default.bold("Credit diagnostics:"));
|
|
30985
|
+
console.log(` Org: ${source_default.green(org.slug)}`);
|
|
30986
|
+
console.log(` Tier: ${source_default.cyan(billing.tier)}`);
|
|
30987
|
+
console.log(
|
|
30988
|
+
` Available credits: ${source_default.cyan(billing.credits.toLocaleString())}`
|
|
30989
|
+
);
|
|
30990
|
+
console.log(` Current user role: ${source_default.cyan(members.role)}`);
|
|
30991
|
+
console.log(
|
|
30992
|
+
` Can purchase credits: ${canPurchaseCredits ? source_default.green("yes") : source_default.yellow("no")}`
|
|
30993
|
+
);
|
|
30994
|
+
console.log(
|
|
30995
|
+
` Auto-recharge: ${billing.autoRecharge.enabled ? source_default.green("enabled") : "disabled"}`
|
|
30996
|
+
);
|
|
30997
|
+
if (billing.autoRecharge.enabled) {
|
|
30998
|
+
console.log(
|
|
30999
|
+
` Threshold: ${billing.autoRecharge.threshold?.toLocaleString() ?? "not set"}`
|
|
31000
|
+
);
|
|
31001
|
+
console.log(
|
|
31002
|
+
` Amount: ${billing.autoRecharge.amount?.toLocaleString() ?? "not set"}`
|
|
31003
|
+
);
|
|
31004
|
+
}
|
|
31005
|
+
if (!isAdmin) {
|
|
31006
|
+
console.log(source_default.bold("\nOrganization admins:"));
|
|
31007
|
+
for (const admin of admins) {
|
|
31008
|
+
console.log(` - ${memberName(admin)}`);
|
|
31009
|
+
}
|
|
31010
|
+
console.log(
|
|
31011
|
+
source_default.yellow(
|
|
31012
|
+
"\nAsk an organization admin to buy credits or upgrade the plan."
|
|
31013
|
+
)
|
|
31014
|
+
);
|
|
31015
|
+
} else if (billing.tier === "free") {
|
|
31016
|
+
console.log(
|
|
31017
|
+
"\nFree-tier admins can upgrade to Pro from billing or buy credits with `zero credit <credits>`."
|
|
31018
|
+
);
|
|
31019
|
+
} else {
|
|
31020
|
+
console.log("\nUse `zero credit <credits>` to buy more credits.");
|
|
31021
|
+
}
|
|
31022
|
+
})
|
|
31023
|
+
);
|
|
31024
|
+
|
|
30908
31025
|
// src/commands/zero/doctor/index.ts
|
|
30909
|
-
var zeroDoctorCommand = new Command().name("doctor").description("Diagnose runtime issues (connector health, permission denials)").addCommand(checkConnectorCommand).addCommand(generateCommand).addCommand(permissionDenyCommand).addCommand(permissionChangeCommand).addHelpText(
|
|
31026
|
+
var zeroDoctorCommand = new Command().name("doctor").description("Diagnose runtime issues (connector health, permission denials)").addCommand(checkConnectorCommand).addCommand(generateCommand).addCommand(creditCommand).addCommand(permissionDenyCommand).addCommand(permissionChangeCommand).addHelpText(
|
|
30910
31027
|
"after",
|
|
30911
31028
|
`
|
|
30912
31029
|
Examples:
|
|
@@ -30914,11 +31031,13 @@ Examples:
|
|
|
30914
31031
|
Check a URL? zero doctor check-connector --url https://api.github.com/repos/owner/repo
|
|
30915
31032
|
Generate with image? zero doctor generate image
|
|
30916
31033
|
Generate with video? zero doctor generate video
|
|
31034
|
+
Check credits? zero doctor credit
|
|
30917
31035
|
Check with permission? zero doctor check-connector --env-name SLACK_TOKEN --check-permission chat:write
|
|
30918
31036
|
Permission denied? zero doctor permission-deny github --method GET --path /repos/owner/repo
|
|
30919
31037
|
Change a permission? zero doctor permission-change github --permission contents:read --enable
|
|
30920
31038
|
|
|
30921
31039
|
Notes:
|
|
31040
|
+
- Use zero doctor credit when a run or generation fails because the org has insufficient credits, when a user asks how to recharge, or before trying to buy credits
|
|
30922
31041
|
- Use this when your task fails due to a missing environment variable or permission denial
|
|
30923
31042
|
- The doctor will identify the issue and give the user a link to resolve it`
|
|
30924
31043
|
);
|
|
@@ -34626,6 +34745,82 @@ init_esm_shims();
|
|
|
34626
34745
|
// src/commands/zero/shared/presentation-generate.ts
|
|
34627
34746
|
init_esm_shims();
|
|
34628
34747
|
import { readFileSync as readFileSync14 } from "fs";
|
|
34748
|
+
|
|
34749
|
+
// src/commands/zero/shared/html-artifact-authoring.ts
|
|
34750
|
+
init_esm_shims();
|
|
34751
|
+
function slugify(value) {
|
|
34752
|
+
const slug = value.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").replace(/-{2,}/gu, "-").slice(0, 48).replace(/-+$/u, "");
|
|
34753
|
+
return slug.length >= 3 ? slug : "html-artifact";
|
|
34754
|
+
}
|
|
34755
|
+
function titleForKind(kind) {
|
|
34756
|
+
return kind === "presentation" ? "HTML presentation" : "hosted website";
|
|
34757
|
+
}
|
|
34758
|
+
function outputDirForSite(site) {
|
|
34759
|
+
return `./opendesign/mockups/${site}`;
|
|
34760
|
+
}
|
|
34761
|
+
function createHtmlArtifactAuthoringPacket(options) {
|
|
34762
|
+
const site = options.site ?? slugify(options.slugSource ?? options.prompt);
|
|
34763
|
+
const outputDir = outputDirForSite(site);
|
|
34764
|
+
const hostCommand = `zero host ${outputDir} --site ${site}${options.kind === "website" ? " --spa" : ""}`;
|
|
34765
|
+
const title = titleForKind(options.kind);
|
|
34766
|
+
const instructions = [
|
|
34767
|
+
`# Zero built-in generate ${options.kind}`,
|
|
34768
|
+
"",
|
|
34769
|
+
`You are the current agent. Author a production-quality ${title} as a static HTML artifact.`,
|
|
34770
|
+
"Zero is not generating this artifact on the server. You are the author.",
|
|
34771
|
+
"",
|
|
34772
|
+
"## User Prompt",
|
|
34773
|
+
options.prompt,
|
|
34774
|
+
"",
|
|
34775
|
+
"## Output Contract",
|
|
34776
|
+
`- Write the artifact under \`${outputDir}/\`.`,
|
|
34777
|
+
`- The entry file must be \`${outputDir}/index.html\`.`,
|
|
34778
|
+
"- Keep every local asset inside the same output directory.",
|
|
34779
|
+
"- Do not reference files from another project path.",
|
|
34780
|
+
"- Use descriptive filenames and canonical HTML: close non-void tags and double-quote attributes.",
|
|
34781
|
+
"- Prefer a single self-contained HTML file unless the artifact genuinely needs separate assets.",
|
|
34782
|
+
"",
|
|
34783
|
+
"## Requested Parameters",
|
|
34784
|
+
...options.details.map((detail) => {
|
|
34785
|
+
return `- ${detail}`;
|
|
34786
|
+
}),
|
|
34787
|
+
"",
|
|
34788
|
+
"## OpenDesign-Style Authoring Rules",
|
|
34789
|
+
"- Read the local codebase, brand assets, and existing design systems before choosing a visual direction.",
|
|
34790
|
+
"- If no design system is available, choose one clear aesthetic direction and hold it across the artifact.",
|
|
34791
|
+
"- Avoid generic AI design defaults: no stock SaaS gradients, no emoji-as-icons, no filler stats, no decorative chrome that does not help the artifact.",
|
|
34792
|
+
"- Build the actual artifact first, not a marketing explanation of the artifact.",
|
|
34793
|
+
"- Make controls and interactions real when they are visible.",
|
|
34794
|
+
"- Keep text readable at desktop and mobile preview sizes.",
|
|
34795
|
+
...options.artifactRules.map((rule) => {
|
|
34796
|
+
return `- ${rule}`;
|
|
34797
|
+
}),
|
|
34798
|
+
"",
|
|
34799
|
+
"## Verification",
|
|
34800
|
+
"- Open the HTML locally and verify it is nonblank.",
|
|
34801
|
+
"- Check that keyboard/click interactions work when present.",
|
|
34802
|
+
"- Check that text does not overflow or overlap at desktop and mobile viewport sizes.",
|
|
34803
|
+
"- Run the final hosting command only after the artifact looks correct.",
|
|
34804
|
+
"",
|
|
34805
|
+
"## Publish",
|
|
34806
|
+
`When everything is OK, publish it with:`,
|
|
34807
|
+
"",
|
|
34808
|
+
"```bash",
|
|
34809
|
+
hostCommand,
|
|
34810
|
+
"```"
|
|
34811
|
+
].join("\n");
|
|
34812
|
+
return {
|
|
34813
|
+
type: "html-artifact-authoring",
|
|
34814
|
+
kind: options.kind,
|
|
34815
|
+
prompt: options.prompt,
|
|
34816
|
+
outputDir,
|
|
34817
|
+
site,
|
|
34818
|
+
hostCommand,
|
|
34819
|
+
instructions
|
|
34820
|
+
};
|
|
34821
|
+
}
|
|
34822
|
+
|
|
34823
|
+
// src/commands/zero/shared/presentation-generate.ts
|
|
34629
34824
|
var PRESENTATION_MAX_IMAGES = 8;
|
|
34630
34825
|
function parseSlideCount(value) {
|
|
34631
34826
|
const slideCount = Number(value);
|
|
@@ -34663,7 +34858,7 @@ function readPrompt2(options, usageCommand) {
|
|
|
34663
34858
|
});
|
|
34664
34859
|
}
|
|
34665
34860
|
function createPresentationGenerateCommand(config) {
|
|
34666
|
-
return new Command().name(config.name).description("Generate
|
|
34861
|
+
return new Command().name(config.name).description("Generate an HTML presentation from a prompt").option(
|
|
34667
34862
|
"--prompt <text>",
|
|
34668
34863
|
"Presentation prompt; can also be piped via stdin"
|
|
34669
34864
|
).option("--style <style>", "Style: editorial or swiss", "editorial").option("--slides <count>", "Slide count: 4-20", parseSlideCount, 8).option(
|
|
@@ -34684,15 +34879,44 @@ Examples:
|
|
|
34684
34879
|
${config.examples}
|
|
34685
34880
|
|
|
34686
34881
|
Output:
|
|
34687
|
-
Prints the generated /f/ HTML presentation URL and metadata
|
|
34882
|
+
Prints the generated /f/ HTML presentation URL and metadata. With openDesignGenerate enabled, prints an OpenDesign-style authoring packet for the current agent instead.
|
|
34688
34883
|
|
|
34689
34884
|
Notes:
|
|
34690
|
-
- Authenticates via ZERO_TOKEN
|
|
34691
|
-
-
|
|
34692
|
-
-
|
|
34885
|
+
- Authenticates via ZERO_TOKEN
|
|
34886
|
+
- Default path charges org credits after successful presentation generation
|
|
34887
|
+
- OpenDesign path is gated by the openDesignGenerate feature switch`
|
|
34693
34888
|
).action(
|
|
34694
34889
|
withErrorHandler(async (options) => {
|
|
34695
34890
|
const prompt = readPrompt2(options, config.usageCommand);
|
|
34891
|
+
if (zeroTokenAllowsFeatureSwitch("openDesignGenerate" /* OpenDesignGenerate */)) {
|
|
34892
|
+
const packet = createHtmlArtifactAuthoringPacket({
|
|
34893
|
+
kind: "presentation",
|
|
34894
|
+
prompt,
|
|
34895
|
+
slugSource: options.title,
|
|
34896
|
+
details: [
|
|
34897
|
+
`Style: ${options.style}`,
|
|
34898
|
+
`Slide count: ${options.slides}`,
|
|
34899
|
+
`Suggested generated visual count: ${options.images}`,
|
|
34900
|
+
`Image model preference if visuals are generated separately: ${options.imageModel ?? "default"}`,
|
|
34901
|
+
`Theme: ${options.theme ?? "agent decides from style"}`,
|
|
34902
|
+
`Audience: ${options.audience ?? "not specified"}`,
|
|
34903
|
+
`Requested deck title: ${options.title ?? "not specified"}`
|
|
34904
|
+
],
|
|
34905
|
+
artifactRules: [
|
|
34906
|
+
"Think like a presentation designer, not a web page designer.",
|
|
34907
|
+
"Use a fixed 1920x1080 slide canvas and scale it uniformly for smaller viewports.",
|
|
34908
|
+
"Use one section per slide and keep repeated elements in consistent positions.",
|
|
34909
|
+
"Make keyboard navigation work with ArrowLeft, ArrowRight, Home, and End.",
|
|
34910
|
+
"Keep slide text readable from across a room; avoid memo-like walls of text."
|
|
34911
|
+
]
|
|
34912
|
+
});
|
|
34913
|
+
if (options.json) {
|
|
34914
|
+
console.log(JSON.stringify(packet));
|
|
34915
|
+
return;
|
|
34916
|
+
}
|
|
34917
|
+
console.log(packet.instructions);
|
|
34918
|
+
return;
|
|
34919
|
+
}
|
|
34696
34920
|
const result = await generateWebPresentation({
|
|
34697
34921
|
prompt,
|
|
34698
34922
|
style: options.style,
|
|
@@ -34741,6 +34965,22 @@ init_esm_shims();
|
|
|
34741
34965
|
// src/commands/zero/shared/video-generate.ts
|
|
34742
34966
|
init_esm_shims();
|
|
34743
34967
|
import { readFileSync as readFileSync15 } from "fs";
|
|
34968
|
+
var FRAME_ASPECT_RATIO_TOLERANCE = 0.02;
|
|
34969
|
+
var JPEG_START_OF_FRAME_MARKERS = /* @__PURE__ */ new Set([
|
|
34970
|
+
192,
|
|
34971
|
+
193,
|
|
34972
|
+
194,
|
|
34973
|
+
195,
|
|
34974
|
+
197,
|
|
34975
|
+
198,
|
|
34976
|
+
199,
|
|
34977
|
+
201,
|
|
34978
|
+
202,
|
|
34979
|
+
203,
|
|
34980
|
+
205,
|
|
34981
|
+
206,
|
|
34982
|
+
207
|
|
34983
|
+
]);
|
|
34744
34984
|
function parseSeed2(value) {
|
|
34745
34985
|
const seed = Number(value);
|
|
34746
34986
|
if (!Number.isInteger(seed) || seed < 0 || !Number.isSafeInteger(seed)) {
|
|
@@ -34751,6 +34991,173 @@ function parseSeed2(value) {
|
|
|
34751
34991
|
function collectUrl(value, previous = []) {
|
|
34752
34992
|
return [...previous, value];
|
|
34753
34993
|
}
|
|
34994
|
+
function parseAspectRatio(value) {
|
|
34995
|
+
const [widthText, heightText] = value.split(":");
|
|
34996
|
+
const width = Number(widthText);
|
|
34997
|
+
const height = Number(heightText);
|
|
34998
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
34999
|
+
throw new Error(`Invalid --aspect-ratio "${value}"`);
|
|
35000
|
+
}
|
|
35001
|
+
return { width, height };
|
|
35002
|
+
}
|
|
35003
|
+
function readPngDimensions(buffer) {
|
|
35004
|
+
if (buffer.length < 24 || buffer.toString("latin1", 0, 8) !== "\x89PNG\r\n\n") {
|
|
35005
|
+
return void 0;
|
|
35006
|
+
}
|
|
35007
|
+
return {
|
|
35008
|
+
width: buffer.readUInt32BE(16),
|
|
35009
|
+
height: buffer.readUInt32BE(20)
|
|
35010
|
+
};
|
|
35011
|
+
}
|
|
35012
|
+
function readGifDimensions(buffer) {
|
|
35013
|
+
if (buffer.length < 10 || !buffer.toString("latin1", 0, 6).startsWith("GIF")) {
|
|
35014
|
+
return void 0;
|
|
35015
|
+
}
|
|
35016
|
+
return {
|
|
35017
|
+
width: buffer.readUInt16LE(6),
|
|
35018
|
+
height: buffer.readUInt16LE(8)
|
|
35019
|
+
};
|
|
35020
|
+
}
|
|
35021
|
+
function readJpegDimensions(buffer) {
|
|
35022
|
+
if (buffer.length < 4 || buffer[0] !== 255 || buffer[1] !== 216) {
|
|
35023
|
+
return void 0;
|
|
35024
|
+
}
|
|
35025
|
+
let offset = 2;
|
|
35026
|
+
while (offset + 9 < buffer.length) {
|
|
35027
|
+
if (buffer[offset] !== 255) {
|
|
35028
|
+
offset += 1;
|
|
35029
|
+
continue;
|
|
35030
|
+
}
|
|
35031
|
+
const marker = buffer[offset + 1];
|
|
35032
|
+
if (marker === 217 || marker === 218) {
|
|
35033
|
+
break;
|
|
35034
|
+
}
|
|
35035
|
+
const segmentLength = buffer.readUInt16BE(offset + 2);
|
|
35036
|
+
if (segmentLength < 2 || offset + 2 + segmentLength > buffer.length) {
|
|
35037
|
+
break;
|
|
35038
|
+
}
|
|
35039
|
+
if (JPEG_START_OF_FRAME_MARKERS.has(marker)) {
|
|
35040
|
+
return {
|
|
35041
|
+
height: buffer.readUInt16BE(offset + 5),
|
|
35042
|
+
width: buffer.readUInt16BE(offset + 7)
|
|
35043
|
+
};
|
|
35044
|
+
}
|
|
35045
|
+
offset += 2 + segmentLength;
|
|
35046
|
+
}
|
|
35047
|
+
return void 0;
|
|
35048
|
+
}
|
|
35049
|
+
function readUnsigned24LE(buffer, offset) {
|
|
35050
|
+
return buffer.readUInt8(offset) + (buffer.readUInt8(offset + 1) << 8) + (buffer.readUInt8(offset + 2) << 16);
|
|
35051
|
+
}
|
|
35052
|
+
function readWebpDimensions(buffer) {
|
|
35053
|
+
if (buffer.length < 30 || buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WEBP") {
|
|
35054
|
+
return void 0;
|
|
35055
|
+
}
|
|
35056
|
+
let offset = 12;
|
|
35057
|
+
while (offset + 8 <= buffer.length) {
|
|
35058
|
+
const chunkType = buffer.toString("ascii", offset, offset + 4);
|
|
35059
|
+
const chunkSize = buffer.readUInt32LE(offset + 4);
|
|
35060
|
+
const payloadOffset = offset + 8;
|
|
35061
|
+
if (payloadOffset + chunkSize > buffer.length) {
|
|
35062
|
+
break;
|
|
35063
|
+
}
|
|
35064
|
+
if (chunkType === "VP8X" && chunkSize >= 10) {
|
|
35065
|
+
return {
|
|
35066
|
+
width: readUnsigned24LE(buffer, payloadOffset + 4) + 1,
|
|
35067
|
+
height: readUnsigned24LE(buffer, payloadOffset + 7) + 1
|
|
35068
|
+
};
|
|
35069
|
+
}
|
|
35070
|
+
if (chunkType === "VP8L" && chunkSize >= 5 && buffer[payloadOffset] === 47) {
|
|
35071
|
+
const byte1 = buffer.readUInt8(payloadOffset + 1);
|
|
35072
|
+
const byte2 = buffer.readUInt8(payloadOffset + 2);
|
|
35073
|
+
const byte3 = buffer.readUInt8(payloadOffset + 3);
|
|
35074
|
+
const byte4 = buffer.readUInt8(payloadOffset + 4);
|
|
35075
|
+
return {
|
|
35076
|
+
width: 1 + byte1 + ((byte2 & 63) << 8),
|
|
35077
|
+
height: 1 + ((byte2 & 192) >> 6) + (byte3 << 2) + ((byte4 & 15) << 10)
|
|
35078
|
+
};
|
|
35079
|
+
}
|
|
35080
|
+
if (chunkType === "VP8 " && chunkSize >= 10 && buffer[payloadOffset + 3] === 157 && buffer[payloadOffset + 4] === 1 && buffer[payloadOffset + 5] === 42) {
|
|
35081
|
+
return {
|
|
35082
|
+
width: buffer.readUInt16LE(payloadOffset + 6) & 16383,
|
|
35083
|
+
height: buffer.readUInt16LE(payloadOffset + 8) & 16383
|
|
35084
|
+
};
|
|
35085
|
+
}
|
|
35086
|
+
offset = payloadOffset + chunkSize + chunkSize % 2;
|
|
35087
|
+
}
|
|
35088
|
+
return void 0;
|
|
35089
|
+
}
|
|
35090
|
+
function readImageDimensions(buffer) {
|
|
35091
|
+
return readPngDimensions(buffer) ?? readJpegDimensions(buffer) ?? readWebpDimensions(buffer) ?? readGifDimensions(buffer);
|
|
35092
|
+
}
|
|
35093
|
+
function formatDimensionsAsRatio({ width, height }) {
|
|
35094
|
+
const divisor = greatestCommonDivisor(width, height);
|
|
35095
|
+
return `${width / divisor}:${height / divisor}`;
|
|
35096
|
+
}
|
|
35097
|
+
function greatestCommonDivisor(left, right) {
|
|
35098
|
+
let a = Math.abs(left);
|
|
35099
|
+
let b = Math.abs(right);
|
|
35100
|
+
while (b !== 0) {
|
|
35101
|
+
const remainder = a % b;
|
|
35102
|
+
a = b;
|
|
35103
|
+
b = remainder;
|
|
35104
|
+
}
|
|
35105
|
+
return a || 1;
|
|
35106
|
+
}
|
|
35107
|
+
function hasMatchingAspectRatio(actual, expected) {
|
|
35108
|
+
const actualRatio = actual.width / actual.height;
|
|
35109
|
+
const expectedRatio = expected.width / expected.height;
|
|
35110
|
+
return Math.abs(actualRatio - expectedRatio) / expectedRatio <= FRAME_ASPECT_RATIO_TOLERANCE;
|
|
35111
|
+
}
|
|
35112
|
+
async function fetchImageDimensions(optionName, imageUrl) {
|
|
35113
|
+
let url;
|
|
35114
|
+
try {
|
|
35115
|
+
url = new URL(imageUrl);
|
|
35116
|
+
} catch {
|
|
35117
|
+
throw new Error(`${optionName} must be an absolute URL`);
|
|
35118
|
+
}
|
|
35119
|
+
const response = await fetch(url);
|
|
35120
|
+
if (!response.ok) {
|
|
35121
|
+
throw new Error(
|
|
35122
|
+
`Could not validate ${optionName}: failed to fetch image (HTTP ${response.status})`
|
|
35123
|
+
);
|
|
35124
|
+
}
|
|
35125
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
35126
|
+
const dimensions = readImageDimensions(buffer);
|
|
35127
|
+
if (!dimensions) {
|
|
35128
|
+
throw new Error(
|
|
35129
|
+
`Could not validate ${optionName}: unsupported image format or missing dimensions`
|
|
35130
|
+
);
|
|
35131
|
+
}
|
|
35132
|
+
return dimensions;
|
|
35133
|
+
}
|
|
35134
|
+
async function validateFrameImageAspectRatio(optionName, imageUrl, aspectRatio) {
|
|
35135
|
+
if (!imageUrl) {
|
|
35136
|
+
return;
|
|
35137
|
+
}
|
|
35138
|
+
const expected = parseAspectRatio(aspectRatio);
|
|
35139
|
+
const actual = await fetchImageDimensions(optionName, imageUrl);
|
|
35140
|
+
if (hasMatchingAspectRatio(actual, expected)) {
|
|
35141
|
+
return;
|
|
35142
|
+
}
|
|
35143
|
+
throw new Error(
|
|
35144
|
+
`${optionName} has aspect ratio ${formatDimensionsAsRatio(actual)} (${actual.width}x${actual.height}), but --aspect-ratio is ${aspectRatio}. Use --aspect-ratio ${formatDimensionsAsRatio(actual)} or provide a frame image with ${aspectRatio} dimensions.`
|
|
35145
|
+
);
|
|
35146
|
+
}
|
|
35147
|
+
async function validateVideoOptions(options) {
|
|
35148
|
+
await Promise.all([
|
|
35149
|
+
validateFrameImageAspectRatio(
|
|
35150
|
+
"--first-frame-image-url",
|
|
35151
|
+
options.firstFrameImageUrl,
|
|
35152
|
+
options.aspectRatio
|
|
35153
|
+
),
|
|
35154
|
+
validateFrameImageAspectRatio(
|
|
35155
|
+
"--last-frame-image-url",
|
|
35156
|
+
options.lastFrameImageUrl,
|
|
35157
|
+
options.aspectRatio
|
|
35158
|
+
)
|
|
35159
|
+
]);
|
|
35160
|
+
}
|
|
34754
35161
|
function readPrompt3(options, usageCommand) {
|
|
34755
35162
|
if (options.prompt?.trim()) {
|
|
34756
35163
|
return options.prompt.trim();
|
|
@@ -34822,6 +35229,7 @@ Models:
|
|
|
34822
35229
|
).action(
|
|
34823
35230
|
withErrorHandler(async (options) => {
|
|
34824
35231
|
const prompt = readPrompt3(options, config.usageCommand);
|
|
35232
|
+
await validateVideoOptions(options);
|
|
34825
35233
|
const result = await generateWebVideo({
|
|
34826
35234
|
prompt,
|
|
34827
35235
|
model: options.model,
|
|
@@ -35947,7 +36355,7 @@ function formatBytes(bytes) {
|
|
|
35947
36355
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
35948
36356
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
35949
36357
|
}
|
|
35950
|
-
var websiteCommand = new Command().name("website").description("Generate
|
|
36358
|
+
var websiteCommand = new Command().name("website").description("Generate a hosted website from a prompt").option("--prompt <text>", "Website prompt; can also be piped via stdin").option(
|
|
35951
36359
|
"--template <template>",
|
|
35952
36360
|
"Template: auto, launch, or profile",
|
|
35953
36361
|
parseTemplate,
|
|
@@ -35970,15 +36378,42 @@ Examples:
|
|
|
35970
36378
|
Pipe prompt: cat brief.txt | zero built-in generate website
|
|
35971
36379
|
|
|
35972
36380
|
Output:
|
|
35973
|
-
|
|
36381
|
+
Generates and publishes a hosted website. With openDesignGenerate enabled, prints an OpenDesign-style authoring packet for the current agent instead.
|
|
35974
36382
|
|
|
35975
36383
|
Notes:
|
|
35976
|
-
- Authenticates via ZERO_TOKEN
|
|
35977
|
-
-
|
|
35978
|
-
-
|
|
36384
|
+
- Authenticates via ZERO_TOKEN
|
|
36385
|
+
- Default path charges org credits for model-generated website content
|
|
36386
|
+
- OpenDesign path is gated by the openDesignGenerate feature switch`
|
|
35979
36387
|
).action(
|
|
35980
36388
|
withErrorHandler(async (options) => {
|
|
35981
36389
|
const prompt = readPrompt4(options);
|
|
36390
|
+
if (zeroTokenAllowsFeatureSwitch("openDesignGenerate" /* OpenDesignGenerate */)) {
|
|
36391
|
+
const packet = createHtmlArtifactAuthoringPacket({
|
|
36392
|
+
kind: "website",
|
|
36393
|
+
prompt,
|
|
36394
|
+
slugSource: options.title,
|
|
36395
|
+
site: options.site,
|
|
36396
|
+
details: [
|
|
36397
|
+
`Template direction: ${options.template}`,
|
|
36398
|
+
`Suggested generated visual count: ${options.images}`,
|
|
36399
|
+
`Image model preference if visuals are generated separately: ${options.imageModel ?? "default"}`,
|
|
36400
|
+
`Requested title/site name: ${options.title ?? "not specified"}`,
|
|
36401
|
+
`Audience: ${options.audience ?? "not specified"}`
|
|
36402
|
+
],
|
|
36403
|
+
artifactRules: [
|
|
36404
|
+
"Build the usable website as the first screen; do not output a landing-page plan.",
|
|
36405
|
+
"If it is a marketing site, make the product or offer visible in the first viewport.",
|
|
36406
|
+
"For app or tool surfaces, prioritize dense, scannable, task-focused UI over decorative sections.",
|
|
36407
|
+
"Use responsive HTML/CSS and verify the page works at mobile and desktop widths."
|
|
36408
|
+
]
|
|
36409
|
+
});
|
|
36410
|
+
if (options.json) {
|
|
36411
|
+
console.log(JSON.stringify(packet));
|
|
36412
|
+
return;
|
|
36413
|
+
}
|
|
36414
|
+
console.log(packet.instructions);
|
|
36415
|
+
return;
|
|
36416
|
+
}
|
|
35982
36417
|
if (!options.json) {
|
|
35983
36418
|
console.log(source_default.dim("Generating website content..."));
|
|
35984
36419
|
}
|
|
@@ -36947,6 +37382,7 @@ var COMMAND_CAPABILITY_MAP = {
|
|
|
36947
37382
|
run: "agent-run:write",
|
|
36948
37383
|
schedule: "schedule:read",
|
|
36949
37384
|
doctor: null,
|
|
37385
|
+
credit: null,
|
|
36950
37386
|
model: null,
|
|
36951
37387
|
"model-provider": null,
|
|
36952
37388
|
logs: "agent-run:read",
|
|
@@ -36972,6 +37408,7 @@ var DEFAULT_COMMANDS = [
|
|
|
36972
37408
|
zeroModelProviderCommand,
|
|
36973
37409
|
zeroAgentCommand,
|
|
36974
37410
|
zeroConnectorCommand,
|
|
37411
|
+
zeroCreditCommand,
|
|
36975
37412
|
zeroDoctorCommand,
|
|
36976
37413
|
zeroPreferenceCommand,
|
|
36977
37414
|
zeroRunCommand,
|
|
@@ -37014,6 +37451,8 @@ function shouldHideCommand(name, payload) {
|
|
|
37014
37451
|
function buildZeroHelpText(payload = decodeZeroTokenPayload()) {
|
|
37015
37452
|
const examples = [
|
|
37016
37453
|
" Check a connector? zero doctor check-connector --env-name <ENV_NAME>",
|
|
37454
|
+
" Check credits? zero doctor credit",
|
|
37455
|
+
" Buy credits? zero credit 20000",
|
|
37017
37456
|
" Send a Slack message? zero slack message send --help",
|
|
37018
37457
|
" Upload GitHub? zero github upload-file --help",
|
|
37019
37458
|
" Download GitHub? zero github download-file --help",
|
|
@@ -37054,7 +37493,7 @@ function registerZeroCommands(prog, commands) {
|
|
|
37054
37493
|
var program = new Command();
|
|
37055
37494
|
program.name("zero").description(
|
|
37056
37495
|
"Zero CLI \u2014 interact with the zero platform from inside the sandbox"
|
|
37057
|
-
).version("9.161.
|
|
37496
|
+
).version("9.161.8").addHelpText("after", () => {
|
|
37058
37497
|
return buildZeroHelpText();
|
|
37059
37498
|
});
|
|
37060
37499
|
if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {
|