@vm0/cli 9.168.3 → 9.169.1

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/zero.js CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  completeSlackFileUpload,
19
19
  completeTelegramFileUpload,
20
20
  configureGlobalProxyFromEnv,
21
+ connectZeroConnectorApiToken,
21
22
  connectorTypeSchema,
22
23
  createComputerUseReadCommand,
23
24
  createComputerUseWriteCommand,
@@ -58,8 +59,8 @@ import {
58
59
  getApiUrl,
59
60
  getAuthMethodsForType,
60
61
  getComputerUseCommand,
61
- getConnectorDerivedNames,
62
- getConnectorEnvironmentMapping,
62
+ getConnectorEnvBindings,
63
+ getConnectorEnvNamesForSecret,
63
64
  getConnectorFirewall,
64
65
  getConnectorGenerationTypes,
65
66
  getConnectorTypeForSecretName,
@@ -152,7 +153,7 @@ import {
152
153
  zeroAgentCustomSkillNameSchema,
153
154
  zeroLocalAgentCommand,
154
155
  zeroTokenAllowsFeatureSwitch
155
- } from "./chunk-M3MX2TJ6.js";
156
+ } from "./chunk-RWNXCBAW.js";
156
157
  import {
157
158
  __toESM,
158
159
  init_esm_shims
@@ -1702,6 +1703,71 @@ Notes:
1702
1703
  // src/commands/zero/connector/index.ts
1703
1704
  init_esm_shims();
1704
1705
 
1706
+ // src/commands/zero/connector/connect.ts
1707
+ init_esm_shims();
1708
+ function collectValue(value, previous) {
1709
+ return [...previous, value];
1710
+ }
1711
+ function parseConnectorValues(rawValues) {
1712
+ if (!rawValues || rawValues.length === 0) {
1713
+ throw new Error("At least one --value NAME=VALUE is required", {
1714
+ cause: new Error(
1715
+ "Example: zero connector connect zendesk --value ZENDESK_API_TOKEN=token"
1716
+ )
1717
+ });
1718
+ }
1719
+ const values = {};
1720
+ for (const rawValue of rawValues) {
1721
+ const separatorIndex = rawValue.indexOf("=");
1722
+ if (separatorIndex <= 0) {
1723
+ throw new Error("Invalid --value format", {
1724
+ cause: new Error("Use --value NAME=VALUE")
1725
+ });
1726
+ }
1727
+ const name = rawValue.slice(0, separatorIndex);
1728
+ if (!name.trim()) {
1729
+ throw new Error("Invalid --value format", {
1730
+ cause: new Error("Field name cannot be empty")
1731
+ });
1732
+ }
1733
+ values[name] = rawValue.slice(separatorIndex + 1);
1734
+ }
1735
+ return values;
1736
+ }
1737
+ function parseConnectorType(type) {
1738
+ const parsed = connectorTypeSchema.safeParse(type);
1739
+ if (parsed.success) {
1740
+ return parsed.data;
1741
+ }
1742
+ throw new Error(`Unknown connector type: ${type}`, {
1743
+ cause: new Error(`Available connectors: ${CONNECTOR_TYPE_KEYS.join(", ")}`)
1744
+ });
1745
+ }
1746
+ var connectCommand = new Command().name("connect").description("Connect a connector with API-token credentials").argument("<type>", "Connector type (e.g., zendesk)").option(
1747
+ "--value <name=value>",
1748
+ "Connector field value; repeat for multiple fields",
1749
+ collectValue,
1750
+ []
1751
+ ).option("--json", "Print the connector response as JSON").action(
1752
+ withErrorHandler(async (type, options) => {
1753
+ const connectorType = parseConnectorType(type);
1754
+ const connector = await connectZeroConnectorApiToken(
1755
+ connectorType,
1756
+ parseConnectorValues(options.value)
1757
+ );
1758
+ if (options.json) {
1759
+ console.log(JSON.stringify(connector, null, 2));
1760
+ return;
1761
+ }
1762
+ console.log(
1763
+ source_default.green(`\u2713 ${CONNECTOR_TYPES[connectorType].label} connected`)
1764
+ );
1765
+ console.log(source_default.dim(` Type: ${connector.type}`));
1766
+ console.log(source_default.dim(` Auth Method: ${connector.authMethod}`));
1767
+ console.log(source_default.dim(` Run: zero connector status ${connector.type}`));
1768
+ })
1769
+ );
1770
+
1705
1771
  // src/commands/zero/connector/list.ts
1706
1772
  init_esm_shims();
1707
1773
 
@@ -1820,7 +1886,9 @@ function parseLimit(raw) {
1820
1886
  }
1821
1887
  return n;
1822
1888
  }
1823
- var searchCommand = new Command().name("search").description("Search connectors by type, label, env var, secret, or tag").argument("<keyword>", "Search keyword (case-insensitive)").option("--agent <id>", "Show per-agent authorization column").option(
1889
+ var searchCommand = new Command().name("search").description(
1890
+ "Search connectors by type, label, environment name, secret, or tag"
1891
+ ).argument("<keyword>", "Search keyword (case-insensitive)").option("--agent <id>", "Show per-agent authorization column").option(
1824
1892
  "--limit <n>",
1825
1893
  `Maximum number of results to display (default ${DEFAULT_LIMIT})`,
1826
1894
  parseLimit,
@@ -2186,7 +2254,7 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
2186
2254
  );
2187
2255
 
2188
2256
  // src/commands/zero/connector/index.ts
2189
- var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(listCommand6).addCommand(searchCommand).addCommand(statusCommand2);
2257
+ var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(connectCommand).addCommand(listCommand6).addCommand(searchCommand).addCommand(statusCommand2);
2190
2258
 
2191
2259
  // src/commands/zero/credit.ts
2192
2260
  init_esm_shims();
@@ -2278,10 +2346,10 @@ function resolveConnectorFromUrl(url) {
2278
2346
  }
2279
2347
  }
2280
2348
  if (!bestMatch) return null;
2281
- const mapping = getConnectorEnvironmentMapping(
2349
+ const envBindings = getConnectorEnvBindings(
2282
2350
  bestMatch.connectorType
2283
2351
  );
2284
- const envName = Object.keys(mapping)[0];
2352
+ const envName = Object.keys(envBindings)[0];
2285
2353
  if (!envName) return null;
2286
2354
  const relativePath = normalized === bestMatch.base ? "/" : normalized.slice(bestMatch.base.length);
2287
2355
  return {
@@ -2291,8 +2359,8 @@ function resolveConnectorFromUrl(url) {
2291
2359
  relativePath
2292
2360
  };
2293
2361
  }
2294
- function checkEnvVariable(ctx) {
2295
- console.log("## Step 1: Sandbox environment variable");
2362
+ function checkEnvName(ctx) {
2363
+ console.log("## Step 1: Sandbox environment name");
2296
2364
  console.log("");
2297
2365
  const envPresent = Boolean(process.env[ctx.envName]);
2298
2366
  console.log(
@@ -2304,7 +2372,7 @@ function checkEnvVariable(ctx) {
2304
2372
  );
2305
2373
  } else {
2306
2374
  console.log(
2307
- "No value found for this environment variable. Note: credential replacement at the network boundary is independent of this variable \u2014 the proxy injects auth headers based on the destination URL, not the presence of this env var."
2375
+ "No value found for this environment name. Note: credential replacement at the network boundary is independent of this name \u2014 the proxy injects auth headers based on the destination URL."
2308
2376
  );
2309
2377
  }
2310
2378
  console.log("");
@@ -2549,16 +2617,16 @@ function resolvePermissionFromUrl(connectorType, label, method, relativePath, ma
2549
2617
  console.log("");
2550
2618
  }
2551
2619
  var checkConnectorCommand = new Command().name("check-connector").description(
2552
- "Diagnose connector health: environment variable, connector configuration, and permission policies"
2620
+ "Diagnose connector health: environment name, connector configuration, and permission policies"
2553
2621
  ).addOption(
2554
2622
  new Option(
2555
2623
  "--env-name <ENV_NAME>",
2556
- "The environment variable name to check (e.g. GITHUB_TOKEN)"
2624
+ "The connector environment name to check (e.g. GITHUB_TOKEN)"
2557
2625
  )
2558
2626
  ).addOption(
2559
2627
  new Option(
2560
2628
  "--url <URL>",
2561
- "A full URL to diagnose \u2014 auto-detects the connector, env var, and permission (e.g. https://api.github.com/repos/owner/repo)"
2629
+ "A full URL to diagnose \u2014 auto-detects the connector, environment name, and permission (e.g. https://api.github.com/repos/owner/repo)"
2562
2630
  )
2563
2631
  ).addOption(
2564
2632
  new Option(
@@ -2610,14 +2678,14 @@ How connectors work:
2610
2678
  );
2611
2679
  console.log(` Matched base URL: ${urlLookup.matchedBase}`);
2612
2680
  console.log(` Relative path: ${urlLookup.relativePath}`);
2613
- console.log(` Environment var: ${envName}`);
2681
+ console.log(` Environment name: ${envName}`);
2614
2682
  } else {
2615
2683
  connectorType = getConnectorTypeForSecretName(
2616
2684
  envName = opts.envName
2617
2685
  );
2618
2686
  if (!connectorType) {
2619
2687
  throw new Error(
2620
- `Unknown environment variable: ${envName} \u2014 not managed by any connector`
2688
+ `Unknown environment name: ${envName} \u2014 not managed by any connector`
2621
2689
  );
2622
2690
  }
2623
2691
  console.log(
@@ -2639,7 +2707,7 @@ How connectors work:
2639
2707
  platformOrigin: platformUrl.origin,
2640
2708
  agentId: process.env.ZERO_AGENT_ID || void 0
2641
2709
  };
2642
- checkEnvVariable(ctx);
2710
+ checkEnvName(ctx);
2643
2711
  const { isConnected, isExpired, hasPermission } = await checkConnectorStatus(ctx);
2644
2712
  const networkPolicies = await checkConnectorDomains(ctx);
2645
2713
  if (isConnected && !isExpired && hasPermission) {
@@ -2683,740 +2751,171 @@ How connectors work:
2683
2751
  })
2684
2752
  );
2685
2753
 
2686
- // src/commands/zero/doctor/generate.ts
2754
+ // src/commands/zero/doctor/permission-deny.ts
2687
2755
  init_esm_shims();
2688
- var BUILT_IN_GENERATION_PROVIDERS = {
2689
- image: [
2690
- {
2691
- label: "Built-in fal.ai",
2692
- model: "gpt-image-1",
2693
- command: "zero built-in generate image --model gpt-image-1 -h",
2694
- reason: "available without connector setup"
2695
- },
2696
- {
2697
- label: "Built-in fal.ai",
2698
- model: "gpt-image-2",
2699
- command: "zero built-in generate image --model gpt-image-2 -h",
2700
- reason: "available without connector setup"
2701
- },
2702
- {
2703
- label: "Built-in fal.ai",
2704
- model: "gpt-image-1.5",
2705
- command: "zero built-in generate image --model gpt-image-1.5 -h",
2706
- reason: "available without connector setup"
2707
- },
2708
- {
2709
- label: "Built-in fal.ai",
2710
- model: "gpt-image-1-mini",
2711
- command: "zero built-in generate image --model gpt-image-1-mini -h",
2712
- reason: "available without connector setup"
2713
- },
2714
- {
2715
- label: "Built-in fal.ai",
2716
- model: "fal-ai/flux-pro/v1.1",
2717
- command: "zero built-in generate image --model flux-pro-1.1 -h",
2718
- reason: "available without connector setup"
2719
- },
2720
- {
2721
- label: "Built-in fal.ai",
2722
- model: "fal-ai/flux-pro/v1.1-ultra",
2723
- command: "zero built-in generate image --model flux-pro-1.1-ultra -h",
2724
- reason: "available without connector setup"
2725
- },
2726
- {
2727
- label: "Built-in fal.ai",
2728
- model: "fal-ai/qwen-image",
2729
- command: "zero built-in generate image --model qwen-image -h",
2730
- reason: "available without connector setup"
2731
- },
2732
- {
2733
- label: "Built-in fal.ai",
2734
- model: "fal-ai/bytedance/seedream/v4/text-to-image",
2735
- command: "zero built-in generate image --model seedream4 -h",
2736
- reason: "available without connector setup"
2737
- }
2738
- ],
2739
- presentation: [
2740
- {
2741
- label: "Built-in",
2742
- model: "gpt-5.5",
2743
- command: "zero built-in generate presentation -h",
2744
- reason: "available without connector setup"
2756
+ var permissionDenyCommand = new Command().name("permission-deny").description(
2757
+ "Diagnose a permission denial and find the permission that covers it"
2758
+ ).argument("<connector-ref>", "The connector type (e.g. github)").addOption(
2759
+ new Option(
2760
+ "--method <method>",
2761
+ "The denied HTTP method"
2762
+ ).makeOptionMandatory()
2763
+ ).addOption(
2764
+ new Option("--path <path>", "The denied path").makeOptionMandatory()
2765
+ ).addHelpText(
2766
+ "after",
2767
+ `
2768
+ Examples:
2769
+ zero doctor permission-deny github --method GET --path /repos/owner/repo/pulls
2770
+ zero doctor permission-deny slack --method POST --path /chat.postMessage
2771
+
2772
+ Notes:
2773
+ - Identifies which named permission covers a denied request
2774
+ - Use permission-change to request or enable the permission`
2775
+ ).action(
2776
+ withErrorHandler(
2777
+ async (connectorRef, opts) => {
2778
+ if (!isFirewallConnectorType(connectorRef)) {
2779
+ throw new Error(`Unknown connector type: ${connectorRef}`);
2780
+ }
2781
+ const { label } = CONNECTOR_TYPES[connectorRef];
2782
+ const config = getConnectorFirewall(connectorRef);
2783
+ const permissions = findMatchingPermissions(
2784
+ opts.method,
2785
+ opts.path,
2786
+ config
2787
+ );
2788
+ console.log(
2789
+ `The ${label} permission filtered ${opts.method} ${opts.path}.`
2790
+ );
2791
+ if (permissions.length === 0) {
2792
+ console.log("No named permission was found covering this request.");
2793
+ return;
2794
+ }
2795
+ const ruleCount = /* @__PURE__ */ new Map();
2796
+ for (const api of config.apis) {
2797
+ if (!api.permissions) continue;
2798
+ for (const perm of api.permissions) {
2799
+ ruleCount.set(
2800
+ perm.name,
2801
+ (ruleCount.get(perm.name) ?? 0) + perm.rules.length
2802
+ );
2803
+ }
2804
+ }
2805
+ const permission = permissions.reduce((narrowest, current) => {
2806
+ return (ruleCount.get(current) ?? Infinity) < (ruleCount.get(narrowest) ?? Infinity) ? current : narrowest;
2807
+ });
2808
+ console.log(`This is covered by the "${permission}" permission.`);
2809
+ console.log(
2810
+ `To request this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --reason "why this is needed"`
2811
+ );
2745
2812
  }
2746
- ],
2747
- report: [
2748
- {
2749
- label: "Built-in",
2750
- model: "gpt-5.5",
2751
- command: "zero built-in generate report -h",
2752
- reason: "available without connector setup"
2813
+ )
2814
+ );
2815
+
2816
+ // src/commands/zero/doctor/permission-change.ts
2817
+ init_esm_shims();
2818
+
2819
+ // src/commands/zero/doctor/resolve-role.ts
2820
+ init_esm_shims();
2821
+ async function resolveUserId() {
2822
+ const zeroPayload = decodeZeroTokenPayload();
2823
+ if (zeroPayload?.userId) return zeroPayload.userId;
2824
+ const token = await getToken();
2825
+ const cliPayload = decodeCliTokenPayload(token);
2826
+ return cliPayload?.userId;
2827
+ }
2828
+ async function resolveAgentRole(agentId) {
2829
+ try {
2830
+ const org = await getZeroOrg();
2831
+ if (org.role === "admin") return "admin";
2832
+ if (org.role === "member") {
2833
+ const userId = await resolveUserId();
2834
+ if (userId) {
2835
+ const agent = await getZeroAgent(agentId);
2836
+ if (agent.ownerId === userId) return "owner";
2837
+ }
2838
+ return "member";
2753
2839
  }
2754
- ],
2755
- "docs-design": [
2756
- {
2757
- label: "Built-in",
2758
- model: "gpt-5.5",
2759
- command: "zero built-in generate docs-design -h",
2760
- reason: "available without connector setup"
2840
+ return "unknown";
2841
+ } catch (error) {
2842
+ console.debug("resolveAgentRole failed, falling back to unknown:", error);
2843
+ return "unknown";
2844
+ }
2845
+ }
2846
+
2847
+ // src/commands/zero/doctor/permission-change.ts
2848
+ function findPermissionInConfig(ref, permissionName) {
2849
+ if (!isFirewallConnectorType(ref)) return false;
2850
+ const config = getConnectorFirewall(ref);
2851
+ for (const api of config.apis) {
2852
+ if (!api.permissions) continue;
2853
+ for (const p of api.permissions) {
2854
+ if (p.name === permissionName) return true;
2761
2855
  }
2762
- ],
2763
- poster: [
2764
- {
2765
- label: "Built-in",
2766
- model: "gpt-5.5",
2767
- command: "zero built-in generate poster -h",
2768
- reason: "available without connector setup"
2769
- }
2770
- ],
2771
- "dashboard-design": [
2772
- {
2773
- label: "Built-in",
2774
- model: "gpt-5.5",
2775
- command: "zero built-in generate dashboard-design -h",
2776
- reason: "available without connector setup"
2777
- }
2778
- ],
2779
- "mobile-app-design": [
2780
- {
2781
- label: "Built-in",
2782
- model: "gpt-5.5",
2783
- command: "zero built-in generate mobile-app-design -h",
2784
- reason: "available without connector setup"
2785
- }
2786
- ],
2787
- website: [
2788
- {
2789
- label: "Built-in",
2790
- model: "gpt-5.5",
2791
- command: "zero built-in generate website -h",
2792
- reason: "available without connector setup"
2793
- }
2794
- ],
2795
- video: [
2796
- {
2797
- label: "Built-in",
2798
- model: "dreamina-seedance-2-0-260128",
2799
- command: "zero built-in generate video --model dreamina-seedance-2.0 -h",
2800
- reason: "available without connector setup"
2801
- },
2802
- {
2803
- label: "Built-in",
2804
- model: "dreamina-seedance-2-0-fast-260128",
2805
- command: "zero built-in generate video --model dreamina-seedance-2.0-fast -h",
2806
- reason: "available without connector setup"
2807
- },
2808
- {
2809
- label: "Built-in",
2810
- model: "seedance-1-5-pro-251215",
2811
- command: "zero built-in generate video --model seedance-1.5-pro -h",
2812
- reason: "available without connector setup"
2813
- },
2814
- {
2815
- label: "Built-in fal.ai",
2816
- model: "fal-ai/veo3.1/fast",
2817
- command: "zero built-in generate video --model veo3.1-fast -h",
2818
- reason: "available without connector setup"
2819
- },
2820
- {
2821
- label: "Built-in fal.ai",
2822
- model: "fal-ai/kling-video/v3/4k/text-to-video",
2823
- command: "zero built-in generate video --model kling-v3-4k -h",
2824
- reason: "available without connector setup"
2825
- }
2826
- ],
2827
- voice: [
2828
- {
2829
- label: "Built-in",
2830
- model: "gpt-4o-mini-tts",
2831
- command: "zero built-in generate voice -h",
2832
- reason: "available without connector setup"
2833
- }
2834
- ]
2835
- };
2836
- var BUILT_IN_GENERATION_COMMANDS = {
2837
- image: {
2838
- label: "Built-in image generation",
2839
- command: "zero built-in generate image -h",
2840
- models: "fal.ai: 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, seedream4"
2841
- },
2842
- video: {
2843
- label: "Built-in video generation",
2844
- command: "zero built-in generate video -h",
2845
- models: "dreamina-seedance-2.0-fast (default), dreamina-seedance-2.0, seedance-1.5-pro, veo3.1-fast, kling-v3-4k"
2846
- },
2847
- presentation: {
2848
- label: "Built-in presentation generation",
2849
- command: "zero built-in generate presentation -h",
2850
- models: "gpt-5.5"
2851
- },
2852
- report: {
2853
- label: "Built-in report generation",
2854
- command: "zero built-in generate report -h",
2855
- models: "gpt-5.5"
2856
- },
2857
- "docs-design": {
2858
- label: "Built-in docs design generation",
2859
- command: "zero built-in generate docs-design -h",
2860
- models: "gpt-5.5"
2861
- },
2862
- poster: {
2863
- label: "Built-in poster generation",
2864
- command: "zero built-in generate poster -h",
2865
- models: "gpt-5.5"
2866
- },
2867
- "dashboard-design": {
2868
- label: "Built-in dashboard design generation",
2869
- command: "zero built-in generate dashboard-design -h",
2870
- models: "gpt-5.5"
2871
- },
2872
- "mobile-app-design": {
2873
- label: "Built-in mobile app design generation",
2874
- command: "zero built-in generate mobile-app-design -h",
2875
- models: "gpt-5.5"
2876
- },
2877
- website: {
2878
- label: "Built-in website generation",
2879
- command: "zero built-in generate website -h",
2880
- models: "gpt-5.5"
2881
- },
2882
- voice: {
2883
- label: "Built-in voice generation",
2884
- command: "zero built-in generate voice -h",
2885
- models: "gpt-4o-mini-tts"
2886
- }
2887
- };
2888
- var GENERATION_CONTEXT = {
2889
- website: {
2890
- lines: [
2891
- "Standalone static website artifacts can be authored locally and published with zero host for a public URL.",
2892
- "zero host is for static directories with index.html; it is not a general deploy system for apps that need a backend, database, worker, or long-running process.",
2893
- "Existing web app changes should usually follow the project's own build, test, and deploy workflow."
2894
- ]
2895
- }
2896
- };
2897
- var GENERATION_TYPE_ORDER = [
2898
- "image",
2899
- "video",
2900
- "audio",
2901
- "voice",
2902
- "text",
2903
- "code",
2904
- "document",
2905
- "presentation",
2906
- "website",
2907
- "report",
2908
- "docs-design",
2909
- "poster",
2910
- "dashboard-design",
2911
- "mobile-app-design"
2912
- ];
2913
- var GENERATION_TYPE_LABELS = {
2914
- audio: "Audio",
2915
- code: "Code",
2916
- "dashboard-design": "Dashboard design",
2917
- document: "Document",
2918
- "docs-design": "Docs design",
2919
- image: "Image",
2920
- "mobile-app-design": "Mobile app design",
2921
- poster: "Poster",
2922
- presentation: "Presentation",
2923
- report: "Report",
2924
- text: "Text",
2925
- video: "Video",
2926
- voice: "Voice",
2927
- website: "Website"
2928
- };
2929
- function getConnectorGenerationType(generationType) {
2930
- switch (generationType) {
2931
- case "voice":
2932
- return "audio";
2933
- case "dashboard-design":
2934
- case "docs-design":
2935
- case "mobile-app-design":
2936
- case "poster":
2937
- case "report":
2938
- return null;
2939
- case "audio":
2940
- case "code":
2941
- case "document":
2942
- case "image":
2943
- case "presentation":
2944
- case "text":
2945
- case "video":
2946
- case "website":
2947
- return generationType;
2948
- }
2949
- }
2950
- function getBuiltInProviders(generationType) {
2951
- return BUILT_IN_GENERATION_PROVIDERS[generationType] ?? [];
2952
- }
2953
- function getBuiltInCommand(generationType) {
2954
- return BUILT_IN_GENERATION_COMMANDS[generationType] ?? null;
2955
- }
2956
- function getGenerationContext(generationType) {
2957
- return GENERATION_CONTEXT[generationType] ?? null;
2958
- }
2959
- function getAvailableGenerationTypes() {
2960
- const available = /* @__PURE__ */ new Set();
2961
- for (const type of CONNECTOR_TYPE_KEYS) {
2962
- for (const generationType of getConnectorGenerationTypes(type)) {
2963
- available.add(generationType);
2964
- }
2965
- }
2966
- return GENERATION_TYPE_ORDER.filter((type) => {
2967
- const connectorGenerationType = getConnectorGenerationType(type);
2968
- return getBuiltInProviders(type).length > 0 || connectorGenerationType !== null && available.has(connectorGenerationType);
2969
- });
2970
- }
2971
- function parseGenerationType(value) {
2972
- const availableTypes = getAvailableGenerationTypes();
2973
- if (availableTypes.includes(value)) {
2974
- return value;
2975
- }
2976
- throw new Error(`Unknown generation type: ${value}`, {
2977
- cause: new Error(`Available types: ${availableTypes.join(", ")}`)
2978
- });
2979
- }
2980
- function getGenerationConnectors(generationType) {
2981
- return CONNECTOR_TYPE_KEYS.map((type) => {
2982
- return [type, CONNECTOR_TYPES[type]];
2983
- }).filter(([type]) => {
2984
- return getConnectorGenerationTypes(type).includes(generationType);
2985
- }).sort(([a], [b]) => {
2986
- return a.localeCompare(b);
2987
- });
2988
- }
2989
- function isConnectorType5(type) {
2990
- return type in CONNECTOR_TYPES;
2991
- }
2992
- async function getFeatureAvailableConnectorTypes() {
2993
- const catalog = await searchZeroConnectors();
2994
- return new Set(
2995
- catalog.connectors.map((connector) => {
2996
- return connector.id;
2997
- }).filter(isConnectorType5)
2998
- );
2999
- }
3000
- function formatAccount(connector) {
3001
- if (connector.externalUsername) return `@${connector.externalUsername}`;
3002
- if (connector.externalEmail) return connector.externalEmail;
3003
- if (connector.externalId) return connector.externalId;
3004
- return void 0;
3005
- }
3006
- function getAction(status, type, label, agentId, platformOrigin) {
3007
- if (status === "needs-reconnect") {
3008
- return {
3009
- actionLabel: `Reconnect ${label}`,
3010
- actionUrl: `${platformOrigin}/connectors`
3011
- };
3012
- }
3013
- if (status === "not-authorized" && agentId) {
3014
- return {
3015
- actionLabel: `Authorize ${label}`,
3016
- actionUrl: `${platformOrigin}/connectors/${type}/authorize?agentId=${agentId}`
3017
- };
3018
- }
3019
- if (status === "not-connected") {
3020
- if (agentId) {
3021
- return {
3022
- actionLabel: `Connect and authorize ${label}`,
3023
- actionUrl: `${platformOrigin}/connectors/${type}/connect?agentId=${agentId}`
3024
- };
3025
- }
3026
- return {
3027
- actionLabel: `Connect ${label}`,
3028
- actionUrl: `${platformOrigin}/connectors/${type}/connect`
3029
- };
3030
- }
3031
- return {};
3032
- }
3033
- function toCandidate(params) {
3034
- const {
3035
- type,
3036
- config,
3037
- connector,
3038
- configuredTypes,
3039
- availableTypes,
3040
- authorizedTypes,
3041
- agentId,
3042
- platformOrigin
3043
- } = params;
3044
- let status;
3045
- let reason;
3046
- if (!availableTypes.has(type)) {
3047
- status = "not-available";
3048
- reason = "not available for this account";
3049
- } else if (connector?.needsReconnect) {
3050
- status = "needs-reconnect";
3051
- reason = "connected, reconnect required";
3052
- } else if (!connector) {
3053
- status = configuredTypes.has(type) ? "not-connected" : "not-available";
3054
- reason = status === "not-connected" ? agentId ? "not connected or authorized for current agent" : "not connected" : "not available in this environment";
3055
- } else if (authorizedTypes && !authorizedTypes.has(type)) {
3056
- status = "not-authorized";
3057
- reason = "connected, not authorized for current agent";
3058
- } else {
3059
- status = "ready";
3060
- reason = agentId ? "connected and authorized for current agent" : "connected; agent authorization was not checked";
3061
- }
3062
- return {
3063
- type,
3064
- label: config.label,
3065
- status,
3066
- reason,
3067
- account: connector ? formatAccount(connector) : void 0,
3068
- authMethod: connector?.authMethod,
3069
- ...getAction(status, type, config.label, agentId, platformOrigin)
3070
- };
3071
- }
3072
- function pad(value, width) {
3073
- return value.padEnd(width);
3074
- }
3075
- function renderRows(candidates) {
3076
- const typeWidth = Math.max(
3077
- 4,
3078
- ...candidates.map((candidate) => {
3079
- return candidate.type.length;
3080
- })
3081
- );
3082
- const labelWidth = Math.max(
3083
- 5,
3084
- ...candidates.map((candidate) => {
3085
- return candidate.label.length;
3086
- })
3087
- );
3088
- for (const candidate of candidates) {
3089
- const suffix = candidate.status === "ready" ? candidate.account ?? candidate.authMethod ?? "" : candidate.reason;
3090
- console.log(
3091
- ` ${pad(candidate.type, typeWidth)} ${pad(candidate.label, labelWidth)} ${suffix}`
3092
- );
3093
- }
3094
- }
3095
- function renderActions(candidates) {
3096
- const actionable = candidates.filter((candidate) => {
3097
- return candidate.actionLabel && candidate.actionUrl;
3098
- });
3099
- if (actionable.length === 0) return;
3100
- console.log("");
3101
- console.log("Next actions:");
3102
- for (const candidate of actionable) {
3103
- console.log(` [${candidate.actionLabel}](${candidate.actionUrl})`);
3104
- }
3105
- }
3106
- function renderBuiltInProvider(generationType) {
3107
- const command = getBuiltInCommand(generationType);
3108
- if (command) {
3109
- console.log("");
3110
- console.log("Built-in command:");
3111
- console.log(` vm0 ${command.label}`);
3112
- console.log(` Models: ${command.models}`);
3113
- console.log(` Use: ${command.command}`);
3114
- return;
3115
- }
3116
- const providers = getBuiltInProviders(generationType);
3117
- if (providers.length === 0) return;
3118
- console.log("");
3119
- console.log(
3120
- providers.length === 1 ? "Built-in provider:" : "Built-in providers:"
3121
- );
3122
- for (const provider of providers) {
3123
- console.log(` vm0 ${provider.label} Model: ${provider.model}`);
3124
- console.log(` Use: ${provider.command}`);
3125
- }
3126
- }
3127
- function renderGenerationContext(generationType) {
3128
- const context = getGenerationContext(generationType);
3129
- if (!context) return;
3130
- console.log("");
3131
- console.log("Context:");
3132
- for (const line of context.lines) {
3133
- console.log(` - ${line}`);
3134
- }
3135
- }
3136
- function renderText(params) {
3137
- const { generationType, agentId, ready, other, showAll } = params;
3138
- const label = GENERATION_TYPE_LABELS[generationType];
3139
- const scope = agentId ? "for current agent" : "(connected connectors)";
3140
- console.log(`${label} generation choices ${scope}`);
3141
- console.log("");
3142
- if (agentId) {
3143
- console.log(`${"Agent:".padEnd(10)}${agentId}`);
3144
- console.log("");
3145
- } else {
3146
- console.log(
3147
- "ZERO_AGENT_ID is not set, so agent authorization could not be checked."
3148
- );
3149
- console.log("");
3150
- }
3151
- const hasBuiltInCommand = getBuiltInCommand(generationType) !== null;
3152
- const showConnectorSummary = ready.length > 0 || !hasBuiltInCommand || showAll;
3153
- if (showConnectorSummary) {
3154
- console.log("Connectors:");
3155
- if (ready.length > 0) {
3156
- renderRows(ready);
3157
- } else {
3158
- console.log(` No ready ${generationType} generation connectors found.`);
3159
- }
3160
- }
3161
- renderBuiltInProvider(generationType);
3162
- renderGenerationContext(generationType);
3163
- if (showAll && other.length > 0) {
3164
- console.log("");
3165
- console.log(`Other ${generationType} generation connectors`);
3166
- console.log("");
3167
- renderRows(other);
3168
- }
3169
- if (showAll) {
3170
- renderActions(other);
3171
- }
3172
- }
3173
- var generateCommand = new Command().name("generate").description("Show generation connector choices for the current agent").argument(
3174
- "<type>",
3175
- `Generation type (${getAvailableGenerationTypes().join(", ")})`
3176
- ).option("--all", "Also show unavailable or not-yet-authorized connectors").option("--json", "Output machine-readable JSON").action(
3177
- withErrorHandler(async (type, options) => {
3178
- const generationType = parseGenerationType(type);
3179
- const connectorGenerationType = getConnectorGenerationType(generationType);
3180
- const agentId = process.env.ZERO_AGENT_ID;
3181
- const [connectorList, availableTypes, enabledTypes, platformOrigin] = await Promise.all([
3182
- listZeroConnectors(),
3183
- getFeatureAvailableConnectorTypes(),
3184
- agentId ? getZeroAgentUserConnectors(agentId) : Promise.resolve(null),
3185
- getPlatformOrigin()
3186
- ]);
3187
- const connectedMap = new Map(
3188
- connectorList.connectors.map((connector) => {
3189
- return [connector.type, connector];
3190
- })
3191
- );
3192
- const configuredTypes = new Set(connectorList.configuredTypes);
3193
- const authorizedTypes = enabledTypes ? new Set(enabledTypes) : null;
3194
- const candidates = connectorGenerationType ? getGenerationConnectors(connectorGenerationType).map(
3195
- ([connectorType, config]) => {
3196
- return toCandidate({
3197
- type: connectorType,
3198
- config,
3199
- connector: connectedMap.get(connectorType),
3200
- configuredTypes,
3201
- availableTypes,
3202
- authorizedTypes,
3203
- agentId,
3204
- platformOrigin
3205
- });
3206
- }
3207
- ) : [];
3208
- const ready = candidates.filter((candidate) => {
3209
- return candidate.status === "ready";
3210
- });
3211
- const other = candidates.filter((candidate) => {
3212
- return candidate.status !== "ready";
3213
- });
3214
- const builtInProviders = getBuiltInProviders(generationType);
3215
- if (options.json) {
3216
- console.log(
3217
- JSON.stringify(
3218
- {
3219
- generationType,
3220
- connectorGenerationType,
3221
- availableTypes: getAvailableGenerationTypes(),
3222
- agentId: agentId ?? null,
3223
- choices: ready,
3224
- otherCandidates: other,
3225
- builtInCommand: getBuiltInCommand(generationType),
3226
- generationContext: getGenerationContext(generationType),
3227
- builtInProvider: builtInProviders[0] ?? null,
3228
- builtInProviders
3229
- },
3230
- null,
3231
- 2
3232
- )
3233
- );
3234
- return;
3235
- }
3236
- renderText({
3237
- generationType,
3238
- agentId,
3239
- ready,
3240
- other,
3241
- showAll: options.all === true
3242
- });
3243
- const shouldShowOtherHint = !options.all && other.length > 0 && (ready.length > 0 || getBuiltInCommand(generationType) === null);
3244
- if (shouldShowOtherHint) {
3245
- console.log("");
3246
- console.log(
3247
- source_default.dim(
3248
- `Use --all to see every ${generationType} generation candidate.`
3249
- )
3250
- );
3251
- }
3252
- })
3253
- );
3254
-
3255
- // src/commands/zero/doctor/permission-deny.ts
3256
- init_esm_shims();
3257
- var permissionDenyCommand = new Command().name("permission-deny").description(
3258
- "Diagnose a permission denial and find the permission that covers it"
3259
- ).argument("<connector-ref>", "The connector type (e.g. github)").addOption(
3260
- new Option(
3261
- "--method <method>",
3262
- "The denied HTTP method"
3263
- ).makeOptionMandatory()
3264
- ).addOption(
3265
- new Option("--path <path>", "The denied path").makeOptionMandatory()
3266
- ).addHelpText(
3267
- "after",
3268
- `
3269
- Examples:
3270
- zero doctor permission-deny github --method GET --path /repos/owner/repo/pulls
3271
- zero doctor permission-deny slack --method POST --path /chat.postMessage
3272
-
3273
- Notes:
3274
- - Identifies which named permission covers a denied request
3275
- - Use permission-change to request or enable the permission`
3276
- ).action(
3277
- withErrorHandler(
3278
- async (connectorRef, opts) => {
3279
- if (!isFirewallConnectorType(connectorRef)) {
3280
- throw new Error(`Unknown connector type: ${connectorRef}`);
3281
- }
3282
- const { label } = CONNECTOR_TYPES[connectorRef];
3283
- const config = getConnectorFirewall(connectorRef);
3284
- const permissions = findMatchingPermissions(
3285
- opts.method,
3286
- opts.path,
3287
- config
3288
- );
3289
- console.log(
3290
- `The ${label} permission filtered ${opts.method} ${opts.path}.`
3291
- );
3292
- if (permissions.length === 0) {
3293
- console.log("No named permission was found covering this request.");
3294
- return;
3295
- }
3296
- const ruleCount = /* @__PURE__ */ new Map();
3297
- for (const api of config.apis) {
3298
- if (!api.permissions) continue;
3299
- for (const perm of api.permissions) {
3300
- ruleCount.set(
3301
- perm.name,
3302
- (ruleCount.get(perm.name) ?? 0) + perm.rules.length
3303
- );
3304
- }
3305
- }
3306
- const permission = permissions.reduce((narrowest, current) => {
3307
- return (ruleCount.get(current) ?? Infinity) < (ruleCount.get(narrowest) ?? Infinity) ? current : narrowest;
3308
- });
3309
- console.log(`This is covered by the "${permission}" permission.`);
3310
- console.log(
3311
- `To request this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --reason "why this is needed"`
3312
- );
3313
- }
3314
- )
3315
- );
3316
-
3317
- // src/commands/zero/doctor/permission-change.ts
3318
- init_esm_shims();
3319
-
3320
- // src/commands/zero/doctor/resolve-role.ts
3321
- init_esm_shims();
3322
- async function resolveUserId() {
3323
- const zeroPayload = decodeZeroTokenPayload();
3324
- if (zeroPayload?.userId) return zeroPayload.userId;
3325
- const token = await getToken();
3326
- const cliPayload = decodeCliTokenPayload(token);
3327
- return cliPayload?.userId;
3328
- }
3329
- async function resolveAgentRole(agentId) {
3330
- try {
3331
- const org = await getZeroOrg();
3332
- if (org.role === "admin") return "admin";
3333
- if (org.role === "member") {
3334
- const userId = await resolveUserId();
3335
- if (userId) {
3336
- const agent = await getZeroAgent(agentId);
3337
- if (agent.ownerId === userId) return "owner";
3338
- }
3339
- return "member";
3340
- }
3341
- return "unknown";
3342
- } catch (error) {
3343
- console.debug("resolveAgentRole failed, falling back to unknown:", error);
3344
- return "unknown";
3345
- }
3346
- }
3347
-
3348
- // src/commands/zero/doctor/permission-change.ts
3349
- function findPermissionInConfig(ref, permissionName) {
3350
- if (!isFirewallConnectorType(ref)) return false;
3351
- const config = getConnectorFirewall(ref);
3352
- for (const api of config.apis) {
3353
- if (!api.permissions) continue;
3354
- for (const p of api.permissions) {
3355
- if (p.name === permissionName) return true;
3356
- }
3357
- }
3358
- return false;
3359
- }
3360
- var REASON_MAX_LENGTH = 500;
3361
- async function outputPermissionChangeMessage(connectorRef, permission, action, reason) {
3362
- const { label } = CONNECTOR_TYPES[connectorRef];
3363
- const platformOrigin = await getPlatformOrigin();
3364
- const agentId = process.env.ZERO_AGENT_ID;
3365
- const role = agentId ? await resolveAgentRole(agentId) : "unknown";
3366
- const urlParams = new URLSearchParams({
3367
- ref: connectorRef,
3368
- permission,
3369
- action: action === "enable" ? "allow" : "deny"
3370
- });
3371
- if (role === "member" && reason) {
3372
- const truncated = reason.length > REASON_MAX_LENGTH ? reason.slice(0, REASON_MAX_LENGTH) : reason;
3373
- urlParams.set("reason", truncated);
3374
- }
3375
- const pagePath = agentId ? `/agents/${agentId}/permissions` : "/agents";
3376
- const url = `${platformOrigin}${pagePath}?${urlParams.toString()}`;
3377
- if (connectorRef === "slack" && permission === "chat:write" && action === "enable") {
3378
- console.log("");
3379
- console.log(
3380
- "IMPORTANT: Granting chat:write allows sending messages AS THE USER's identity, not as a bot."
3381
- );
3382
- console.log(
3383
- "Use `zero slack message send -c <channel> -t <text>` to send messages as the bot instead \u2014 this is the recommended approach for most use cases."
3384
- );
3385
- console.log(
3386
- "Only request user approval below if acting as the user is specifically required."
3387
- );
3388
- console.log("");
3389
- }
3390
- if (connectorRef === "gmail" && permission === "gmail.send" && action === "enable") {
3391
- console.log("");
3392
- console.log(
3393
- "IMPORTANT: Granting gmail.send allows the agent to send emails directly as the user."
3394
- );
3395
- console.log(
3396
- "Consider keeping gmail.send disabled and using gmail.compose instead \u2014 the agent can create drafts for the user to review and send manually."
3397
- );
3398
- console.log(
3399
- "Only request user approval below if direct sending is specifically required."
3400
- );
3401
- console.log("");
3402
- }
3403
- if (role === "admin" || role === "owner") {
3404
- console.log(
3405
- `You can ${action} the "${permission}" permission directly: [Manage ${label} permissions](${url})`
3406
- );
3407
- } else if (role === "member") {
3408
- if (!reason) {
3409
- console.log(
3410
- `IMPORTANT: Re-run with \`--reason "one sentence why this is needed"\` so the admin can review your request faster.`
3411
- );
3412
- } else if (action === "enable") {
3413
- console.log(
3414
- `Permission changes require admin approval. Request access at: [Request ${label} access](${url})`
3415
- );
3416
- } else {
3417
- console.log(
3418
- `Permission changes require admin approval. Contact an org admin to disable this permission: [View ${label} permissions](${url})`
3419
- );
2856
+ }
2857
+ return false;
2858
+ }
2859
+ var REASON_MAX_LENGTH = 500;
2860
+ async function outputPermissionChangeMessage(connectorRef, permission, action, reason) {
2861
+ const { label } = CONNECTOR_TYPES[connectorRef];
2862
+ const platformOrigin = await getPlatformOrigin();
2863
+ const agentId = process.env.ZERO_AGENT_ID;
2864
+ const role = agentId ? await resolveAgentRole(agentId) : "unknown";
2865
+ const urlParams = new URLSearchParams({
2866
+ ref: connectorRef,
2867
+ permission,
2868
+ action: action === "enable" ? "allow" : "deny"
2869
+ });
2870
+ if (role === "member" && reason) {
2871
+ const truncated = reason.length > REASON_MAX_LENGTH ? reason.slice(0, REASON_MAX_LENGTH) : reason;
2872
+ urlParams.set("reason", truncated);
2873
+ }
2874
+ const pagePath = agentId ? `/agents/${agentId}/permissions` : "/agents";
2875
+ const url = `${platformOrigin}${pagePath}?${urlParams.toString()}`;
2876
+ if (connectorRef === "slack" && permission === "chat:write" && action === "enable") {
2877
+ console.log("");
2878
+ console.log(
2879
+ "IMPORTANT: Granting chat:write allows sending messages AS THE USER's identity, not as a bot."
2880
+ );
2881
+ console.log(
2882
+ "Use `zero slack message send -c <channel> -t <text>` to send messages as the bot instead \u2014 this is the recommended approach for most use cases."
2883
+ );
2884
+ console.log(
2885
+ "Only request user approval below if acting as the user is specifically required."
2886
+ );
2887
+ console.log("");
2888
+ }
2889
+ if (connectorRef === "gmail" && permission === "gmail.send" && action === "enable") {
2890
+ console.log("");
2891
+ console.log(
2892
+ "IMPORTANT: Granting gmail.send allows the agent to send emails directly as the user."
2893
+ );
2894
+ console.log(
2895
+ "Consider keeping gmail.send disabled and using gmail.compose instead \u2014 the agent can create drafts for the user to review and send manually."
2896
+ );
2897
+ console.log(
2898
+ "Only request user approval below if direct sending is specifically required."
2899
+ );
2900
+ console.log("");
2901
+ }
2902
+ if (role === "admin" || role === "owner") {
2903
+ console.log(
2904
+ `You can ${action} the "${permission}" permission directly: [Manage ${label} permissions](${url})`
2905
+ );
2906
+ } else if (role === "member") {
2907
+ if (!reason) {
2908
+ console.log(
2909
+ `IMPORTANT: Re-run with \`--reason "one sentence why this is needed"\` so the admin can review your request faster.`
2910
+ );
2911
+ } else if (action === "enable") {
2912
+ console.log(
2913
+ `Permission changes require admin approval. Request access at: [Request ${label} access](${url})`
2914
+ );
2915
+ } else {
2916
+ console.log(
2917
+ `Permission changes require admin approval. Contact an org admin to disable this permission: [View ${label} permissions](${url})`
2918
+ );
3420
2919
  }
3421
2920
  } else {
3422
2921
  console.log(
@@ -3537,14 +3036,12 @@ var creditCommand = new Command().name("credit").description("Diagnose current o
3537
3036
  );
3538
3037
 
3539
3038
  // src/commands/zero/doctor/index.ts
3540
- 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(
3039
+ var zeroDoctorCommand = new Command().name("doctor").description("Diagnose runtime issues (connector health, permission denials)").addCommand(checkConnectorCommand).addCommand(creditCommand).addCommand(permissionDenyCommand).addCommand(permissionChangeCommand).addHelpText(
3541
3040
  "after",
3542
3041
  `
3543
3042
  Examples:
3544
3043
  Check a connector? zero doctor check-connector --env-name GITHUB_TOKEN
3545
3044
  Check a URL? zero doctor check-connector --url https://api.github.com/repos/owner/repo
3546
- Generate with image? zero doctor generate image
3547
- Generate with video? zero doctor generate video
3548
3045
  Check credits? zero doctor credit
3549
3046
  Check with permission? zero doctor check-connector --env-name SLACK_TOKEN --check-permission chat:write
3550
3047
  Permission denied? zero doctor permission-deny github --method GET --path /repos/owner/repo
@@ -3552,7 +3049,8 @@ Examples:
3552
3049
 
3553
3050
  Notes:
3554
3051
  - 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
3555
- - Use this when your task fails due to a missing environment variable or permission denial
3052
+ - Use this when your task fails due to a missing connector environment name or permission denial
3053
+ - Use zero generate <type> (no --prompt) to see every provider available for a given generation type
3556
3054
  - The doctor will identify the issue and give the user a link to resolve it`
3557
3055
  );
3558
3056
 
@@ -4706,21 +4204,21 @@ var listCommand8 = new Command().name("list").alias("ls").description("List all
4706
4204
  if (secret.type === "model-provider") {
4707
4205
  typeIndicator = source_default.dim(" [model-provider]");
4708
4206
  } else if (secret.type === "connector") {
4709
- const derived = getConnectorDerivedNames(secret.name);
4207
+ const derived = getConnectorEnvNamesForSecret(secret.name);
4710
4208
  if (derived) {
4711
4209
  typeIndicator = source_default.dim(` [${derived.connectorLabel} connector]`);
4712
4210
  derivedLine = source_default.dim(
4713
- `Available as: ${derived.envVarNames.join(", ")}`
4211
+ `Available as: ${derived.envNames.join(", ")}`
4714
4212
  );
4715
4213
  } else {
4716
4214
  typeIndicator = source_default.dim(" [connector]");
4717
4215
  }
4718
4216
  } else if (secret.type === "user") {
4719
- const derived = getConnectorDerivedNames(secret.name);
4217
+ const derived = getConnectorEnvNamesForSecret(secret.name);
4720
4218
  if (derived) {
4721
4219
  typeIndicator = source_default.dim(` [${derived.connectorLabel} connector]`);
4722
4220
  derivedLine = source_default.dim(
4723
- `Available as: ${derived.envVarNames.join(", ")}`
4221
+ `Available as: ${derived.envNames.join(", ")}`
4724
4222
  );
4725
4223
  }
4726
4224
  }
@@ -7243,18 +6741,14 @@ var openAppCommand = appOption(
7243
6741
  );
7244
6742
  var zeroComputerUseCommand = new Command().name("computer-use").description("Desktop app computer use through Zero CLI").addHelpText("after", COMPUTER_USE_HELP_TEXT).addCommand(listAppsCommand).addCommand(getAppStateCommand).addCommand(clickCommand).addCommand(scrollCommand).addCommand(setValueCommand).addCommand(typeTextCommand).addCommand(pressKeyCommand).addCommand(performActionCommand).addCommand(openAppCommand);
7245
6743
 
7246
- // src/commands/zero/built-in/index.ts
7247
- init_esm_shims();
7248
-
7249
- // src/commands/zero/built-in/generate/index.ts
6744
+ // src/commands/zero/generate/index.ts
7250
6745
  init_esm_shims();
7251
6746
 
7252
- // src/commands/zero/built-in/generate/image.ts
6747
+ // src/commands/zero/generate/image.ts
7253
6748
  init_esm_shims();
7254
6749
 
7255
6750
  // src/commands/zero/shared/image-generate.ts
7256
6751
  init_esm_shims();
7257
- import { readFileSync as readFileSync13 } from "fs";
7258
6752
 
7259
6753
  // src/commands/zero/shared/image-style-authoring.ts
7260
6754
  init_esm_shims();
@@ -9696,266 +9190,924 @@ var OPEN_DESIGN_REGISTRY = [
9696
9190
  source: { path: "illustration-template/painterly-botanical" }
9697
9191
  },
9698
9192
  {
9699
- id: "vm0:image-style:iso-scene",
9193
+ id: "vm0:image-style:iso-scene",
9194
+ kind: "image-style",
9195
+ name: "Isometric Editorial Scene",
9196
+ description: "Isometric editorial-magazine scene illustration with ultra-fine hairline outlines, flat fills, a saturated monochromatic background, and a scene-as-metaphor composition built from theme-native props.",
9197
+ desc: 'Isometric editorial-magazine scene illustration in a locked flat-vector style \u2014 ultra-fine hairline outlines, monochromatic saturated background filling the canvas, and a single composed scene whose props themselves embody the theme. Trigger when users say /iso-scene, ask for an "isometric editorial illustration", a "scene illustration in the editorial machine style", or brief with palette + scene archetype + complexity.',
9198
+ source: { path: "illustration-template/iso-scene" }
9199
+ },
9200
+ {
9201
+ id: "vm0:image-style:inkdab",
9202
+ kind: "image-style",
9203
+ name: "Inkdab Illustration",
9204
+ description: "Brush-pen editorial illustration where a free-floating color dab is painted first, then loose black ink linework is drawn freely on top \u2014 never as an outline around the color. Scribbled hatched hair, open-outline bodies, pure white background.",
9205
+ desc: 'Brush-pen editorial illustration style \u2014 a flat accent-color "dab" painted first, then loose black ink drawn freely on top. ONE flat accent-color shape per prop (painted-first, never outlined in black), black hand-wobbled ink on pure white background, scribbled hatched hair, open-outline bodies with zero fill, and one small solid-accent triangle floating freely as a recurring motif. Trigger when user says /inkdab, asks for an "inkdab illustration", a "brush-pen illustration with a single accent color", a "free-floating color block illustration", or briefs in the style of the included reference images.',
9206
+ source: { path: "illustration-template/inkdab" }
9207
+ },
9208
+ {
9209
+ id: "vm0:image-style:riso-relic",
9210
+ kind: "image-style",
9211
+ name: "Riso Relic",
9212
+ description: 'Pop-art retro risograph poster of a single nostalgic everyday object on a saturated single-hue field \u2014 bold black ink outlines, halftone grain, hand-drawn doodle accents, tiny "SMALL OBJECTS IN TIME" banner up top, chunky retro headline with offset drop-shadow at the bottom.',
9213
+ desc: 'Pop-art retro risograph poster of a single nostalgic everyday object \u2014 saturated single-color background, bold black ink outlines, halftone/riso grain, hand-drawn doodle accents (sparkles, squiggles, dots, music notes, lightning), tiny white "SMALL OBJECTS IN TIME" banner at top, chunky retro display headline at bottom with offset black drop-shadow. Trigger when user says /riso-relic, asks for a "riso poster", a "small objects in time" illustration, or any new piece in this nostalgic pop-art relic-object style.',
9214
+ source: { path: "illustration-template/riso-relic" }
9215
+ },
9216
+ {
9217
+ id: "vm0:image-style:inkstomp",
9218
+ kind: "image-style",
9219
+ name: "Inkstomp",
9220
+ description: "Loud indie-packaging poster style \u2014 full-bleed saturated flat color, a two-line hand-lettered headline, and one weird-cute black brush-ink character.",
9221
+ desc: 'Inkstomp \u2014 a loud, hand-screened indie-packaging poster style. Full-bleed saturated flat color filling the entire canvas, a two-line hand-lettered headline (thin arched caps over chunky drop-shadowed display), and one weird-cute character drawn in thick uniform black brush ink. Trigger when the user says /inkstomp, asks for an "inkstomp poster", a "Ray Fenwick / Hattie Stewart packaging poster", an "indie brush-ink flavor card", or briefs in a "palette + headline + character" shape.',
9222
+ source: { path: "illustration-template/inkstomp" }
9223
+ },
9224
+ {
9225
+ id: "vm0:image-style:folk-muse",
9226
+ kind: "image-style",
9227
+ name: "Folk Muse",
9228
+ description: "Flat folk-art gouache portrait style \u2014 a single contemplative chest-up figure framed by an asymmetric botanical surround, with painted irises, smooth flat hair, a hand against the cheek, and a patterned robe.",
9229
+ desc: 'Flat folk-art gouache portrait illustration in the contemporary editorial style of Carson Ellis, Maja Tomljanovic, and Bodil Jane. A single chest-up figure with an elongated mannerist oval face, tiny almond half-lidded eyes, smooth flat hair, one hand pressed against the face, a patterned robe filling the lower frame, and an asymmetric botanical surround filling the background edge-to-edge. Hand-painted matte gouache texture, flat color blocks, no harsh outlines, no photorealism. Calm, slightly melancholic, contemplative mood. Trigger when the user says /folk-muse, asks for a "folk-art portrait", "gouache portrait", "Carson Ellis style portrait", or any new piece in this contemplative folk-portrait style.',
9230
+ source: { path: "illustration-template/folk-muse" }
9231
+ },
9232
+ {
9233
+ id: "vm0:image-style:sunlit-gouache",
9234
+ kind: "image-style",
9235
+ name: "Sunlit Gouache",
9236
+ description: "Bright pastel travel-painting illustration in opaque gouache on textured paper with chunky flat brushstrokes, vertical one-point perspective, and figures walking into warm sunlight.",
9237
+ desc: 'Sunlit Gouache travel-painting illustration. Opaque gouache on textured paper, visible chunky flat brushstrokes with dry-brush highlights, locked six-color palette (cream, butter-yellow, sky-blue, sage-green, terracotta, one small red accent), vertical 2:3 one-point-perspective composition drawing the eye into a bright sunlit focal point, figures seen from behind walking into the scene, an overhead band of hanging elements (awning, prayer flags, catenary, bunting, lanterns) creating depth, dappled painterly reflections on the ground, airy optimistic warm mood. Trigger when user says /sunlit-gouache, asks for a "sunlit gouache illustration", "painterly travel scene", "gouache caf\xE9/market/temple/station scene", or a new piece in this bright pastel painted-light style.',
9238
+ source: { path: "illustration-template/sunlit-gouache" }
9239
+ },
9240
+ {
9241
+ id: "vm0:image-style:mosaic-still-life",
9242
+ kind: "image-style",
9243
+ name: "Mosaic Still Life",
9244
+ description: "Editorial still-life illustration in a mosaic-tile + painterly hybrid style \u2014 tessellated ground/sky/wall surfaces with crisp painterly objects, an animal companion, and a patterned textile peeking through.",
9245
+ desc: 'Mosaic-tile + painterly hybrid editorial illustration. Tessellated/pointillist mosaic surfaces (grass, sky, sand, walls, floors) anchor the scene, with crisp painterly still-life objects rendered ON TOP. Always features a still-life centerpiece on a table, an animal companion at the heart of the scene, and at least one patterned textile peeking through. Cozy, nostalgic, bucolic mood. Trigger when user says /mosaic-still-life, asks for a "mosaic illustration", "mosaic-tile editorial illustration", "tessellated still life", or briefs with a palette + scene + animal in this style.',
9246
+ source: { path: "illustration-template/mosaic-still-life" }
9247
+ },
9248
+ {
9249
+ id: "vm0:image-style:ink-mascot",
9250
+ kind: "image-style",
9251
+ name: "Ink Mascot",
9252
+ description: "Vintage editorial marketing card. Bold serif headline and short serif descriptor over a hand-drawn black-ink anthropomorphic mascot (stick limbs, chunky white sneakers) on a single solid saturated flat color background.",
9253
+ desc: 'Generate a 3:5 portrait editorial marketing card in a locked vintage-textbook style. Bold serif headline plus an optional short serif descriptor sit on a single solid saturated flat color background (no gradient, no divider, no ground line). A hand-drawn black-ink anthropomorphic hero object \u2014 paint bucket, magnifying glass, envelope, notebook, funnel, megaphone, rocket, seedling, gift box, compass, etc. \u2014 stands with two thin stick arms, two stick legs, and chunky white sneakers with black laces (the signature detail). Crosshatch and stipple shading on rounded surfaces; floating ink doodles (sparkles, arrows, hearts, percent or dollar signs, motion lines) at the requested density. Dialable along six axes: concept, palette, hero object, action, doodle density (L1 minimal, L2 balanced, L3 packed), and type layout (A title-top, B headline-bottom, C headline-only, D big-word + tiny-descriptor). Trigger when user says /ink-mascot, asks for a "marketing card illustration", a "retro editorial mascot poster", or briefs with a marketing concept plus palette plus character.',
9254
+ source: { path: "illustration-template/ink-mascot" }
9255
+ },
9256
+ {
9257
+ id: "vm0:image-style:sticker-sheet",
9258
+ kind: "image-style",
9259
+ name: "Sticker Sheet",
9260
+ description: "Hand-painted gouache sticker-sheet illustration with ~20 themed objects floating on white, punchy saturated palette, wobbly hand-drawn ink overlay, and tiny decorative marks on every item.",
9261
+ desc: 'Sticker Sheet \u2014 hand-painted gouache sticker-sheet illustration. ~20 small floating themed objects on pure white, punchy saturated palette (coral, mustard, sage, dusty pink, navy, cream, warm brown), flat brushy gouache fills with wobbly hand-drawn ink linework and tiny decorative marks (dots, hatches, squiggles) on every object. Each object slightly tilted, no drop shadows, cheerful cozy lifestyle journal mood. Trigger when user says /sticker-sheet, asks for a "sticker sheet illustration", "hand-painted gouache sticker pack", "themed object sheet", or briefs with a scene theme + object count in this house style.',
9262
+ source: { path: "illustration-template/sticker-sheet" }
9263
+ },
9264
+ {
9265
+ id: "vm0:image-style:flat-poster",
9700
9266
  kind: "image-style",
9701
- name: "Isometric Editorial Scene",
9702
- description: "Isometric editorial-magazine scene illustration with ultra-fine hairline outlines, flat fills, a saturated monochromatic background, and a scene-as-metaphor composition built from theme-native props.",
9703
- desc: 'Isometric editorial-magazine scene illustration in a locked flat-vector style \u2014 ultra-fine hairline outlines, monochromatic saturated background filling the canvas, and a single composed scene whose props themselves embody the theme. Trigger when users say /iso-scene, ask for an "isometric editorial illustration", a "scene illustration in the editorial machine style", or brief with palette + scene archetype + complexity.',
9704
- source: { path: "illustration-template/iso-scene" }
9267
+ name: "Flat Poster",
9268
+ description: "Vertical flat-color editorial poster style \u2014 saturated solid background, one centered hand-drawn vector subject in bold deep-navy outlines with strict two-tone fill, headline pinned top-left, wordmark pinned bottom-right.",
9269
+ desc: 'Flat Poster \u2014 a vertical flat-color editorial poster style for brand benefit cards, marketing posters, and in-app campaign visuals. Portrait 2:3 canvas filled edge-to-edge with one saturated hue; a single centered hand-drawn vector subject in deep-navy outlines with strict two-tone fill (pure white plus one darker bg-tint accent); a bold rounded sans-serif headline pinned top-left; a short wordmark (default VM0) pinned bottom-right; small floating accent marks around the subject; no body copy. Six creative dials: palette, subject archetype, composition preset, accent marks, headline voice, mood. Trigger when the user says /flat-poster, asks for a "flat-color editorial poster", a "brand benefit card", a "marketing card in the bold outline + flat color style", or briefs with a palette + subject + headline shape.',
9270
+ source: { path: "illustration-template/flat-poster" }
9705
9271
  },
9706
9272
  {
9707
- id: "vm0:image-style:inkdab",
9273
+ id: "vm0:image-style:mellow-pop",
9708
9274
  kind: "image-style",
9709
- name: "Inkdab Illustration",
9710
- description: "Brush-pen editorial illustration where a free-floating color dab is painted first, then loose black ink linework is drawn freely on top \u2014 never as an outline around the color. Scribbled hatched hair, open-outline bodies, pure white background.",
9711
- desc: 'Brush-pen editorial illustration style \u2014 a flat accent-color "dab" painted first, then loose black ink drawn freely on top. ONE flat accent-color shape per prop (painted-first, never outlined in black), black hand-wobbled ink on pure white background, scribbled hatched hair, open-outline bodies with zero fill, and one small solid-accent triangle floating freely as a recurring motif. Trigger when user says /inkdab, asks for an "inkdab illustration", a "brush-pen illustration with a single accent color", a "free-floating color block illustration", or briefs in the style of the included reference images.',
9712
- source: { path: "illustration-template/inkdab" }
9275
+ name: "Mellow Pop",
9276
+ description: "Chill flat-vector editorial poster of a serene recurring character on a fully saturated solid color background, with a signature pop of bright leaf-green and a scene-as-metaphor composition.",
9277
+ desc: 'Mellow-pop flat-vector editorial illustration: a recurring chill character with closed-eye smile, tiny nose hint, and short dark bobbed hair, posed inside a scene-as-metaphor composition on a single fully saturated solid color background, with a signature pop of bright leaf-green woven into every piece (hero prop, plants, motifs, or sweater). Thin uniform black outlines, flat solid fills only, no gradients or texture. Five dials per brief: palette, scene metaphor, complexity (L1/L2/L3), pose, outfit accent. Trigger when user says /mellow-pop, asks for a "mellow-pop illustration", "chill flat-vector poster", or briefs with a scene metaphor + palette + complexity.',
9278
+ source: { path: "illustration-template/mellow-pop" }
9279
+ }
9280
+ ];
9281
+ function filterByKind(kind) {
9282
+ return OPEN_DESIGN_REGISTRY.filter((entry) => {
9283
+ return entry.kind === kind;
9284
+ });
9285
+ }
9286
+ function listImageStyles() {
9287
+ return filterByKind("image-style");
9288
+ }
9289
+ function findImageStyle(id) {
9290
+ return listImageStyles().find((entry) => {
9291
+ return entry.id === id;
9292
+ });
9293
+ }
9294
+ function toOpenDesignTarget(value) {
9295
+ if (value === "dashboard") {
9296
+ return "dashboard-design";
9297
+ }
9298
+ if (value === "docs") {
9299
+ return "docs-design";
9300
+ }
9301
+ if (value === "mobile-app") {
9302
+ return "mobile-app-design";
9303
+ }
9304
+ return value;
9305
+ }
9306
+ function selectOpenDesignCandidates() {
9307
+ return {
9308
+ registryVersion: OPEN_DESIGN_REGISTRY_VERSION,
9309
+ source: {
9310
+ repo: OPEN_DESIGN_REPO,
9311
+ commit: OPEN_DESIGN_COMMIT
9312
+ },
9313
+ sources: [
9314
+ {
9315
+ repo: OPEN_DESIGN_REPO,
9316
+ commit: OPEN_DESIGN_COMMIT
9317
+ },
9318
+ {
9319
+ repo: VM0_SKILLS_REPO,
9320
+ commit: VM0_SKILLS_REF
9321
+ }
9322
+ ],
9323
+ candidates: {
9324
+ skills: filterByKind("skill"),
9325
+ templates: filterByKind("template"),
9326
+ designSystems: filterByKind("design-system"),
9327
+ imageStyles: filterByKind("image-style"),
9328
+ audioStyles: filterByKind("audio-style"),
9329
+ videoTemplates: filterByKind("video-template"),
9330
+ bundleTemplates: filterByKind("bundle-template")
9331
+ }
9332
+ };
9333
+ }
9334
+
9335
+ // src/commands/zero/shared/image-style-authoring.ts
9336
+ var outputDir = "./opendesign/images";
9337
+ var artifactRules = [
9338
+ "Resolve the selected style source before generating the image.",
9339
+ "Use the style skill's referenced assets and generation path when it provides one.",
9340
+ "Produce a single final image file and keep any temporary metadata under the output directory."
9341
+ ];
9342
+ function createStyledImageAuthoringPacket(options) {
9343
+ const baseSlice = selectOpenDesignCandidates();
9344
+ const candidateSlice = {
9345
+ ...baseSlice,
9346
+ candidates: {
9347
+ ...baseSlice.candidates,
9348
+ imageStyles: [options.style]
9349
+ }
9350
+ };
9351
+ const selectionSchema = {
9352
+ imageStyle: "string",
9353
+ skills: "string[]",
9354
+ rationale: "string"
9355
+ };
9356
+ const artifact = {
9357
+ outputMode: "primary-image",
9358
+ primaryArtifact: {
9359
+ kind: "image",
9360
+ path: `${outputDir}/`
9361
+ },
9362
+ supportingAssets: [
9363
+ {
9364
+ kind: "metadata",
9365
+ path: `${outputDir}/metadata.json`,
9366
+ optional: true
9367
+ }
9368
+ ],
9369
+ previewKind: "image",
9370
+ outputDir
9371
+ };
9372
+ const instructions = [
9373
+ `# Zero generate image --style ${options.style.id}`,
9374
+ "",
9375
+ "This is a federated generation resource-selection packet for the current agent.",
9376
+ "Zero is not generating this image on the server yet. The image style has already been selected by the caller \u2014 resolve it and generate the styled image.",
9377
+ "",
9378
+ "## User Prompt",
9379
+ options.prompt,
9380
+ "",
9381
+ "## Selected Image Style",
9382
+ `- \`${options.style.id}\` \u2014 ${options.style.name}`,
9383
+ "",
9384
+ "## Stage 1: Supporting Resource Selection",
9385
+ "- The image style is locked. Optionally pick supporting skills/templates from the candidate slice below.",
9386
+ "- Choose only IDs present in this packet; do not invent registry IDs.",
9387
+ "- Treat the selection JSON as internal working state, then continue to generation.",
9388
+ "",
9389
+ "## Selection Output Schema",
9390
+ "```json",
9391
+ JSON.stringify(selectionSchema, null, 2),
9392
+ "```",
9393
+ "",
9394
+ "## Candidate Registry Slice",
9395
+ `Registry: \`${candidateSlice.registryVersion}\``,
9396
+ "Sources:",
9397
+ ...candidateSlice.sources.map((src) => {
9398
+ return `- \`${src.repo}@${src.commit}\``;
9399
+ }),
9400
+ "",
9401
+ "```json",
9402
+ JSON.stringify(candidateSlice.candidates, null, 2),
9403
+ "```",
9404
+ "",
9405
+ "## Stage 2: Resolve Selected Resources",
9406
+ "- Fetch or read the selected resource source before generation.",
9407
+ "- Source refs are pinned as `repo@commit:path`; use the commit in the packet for reproducibility.",
9408
+ "- For directory refs, inspect the most relevant files such as `SKILL.md`, references, examples, and templates.",
9409
+ "- If a source file cannot be fetched, state that limitation and fall back to the registry metadata for that resource.",
9410
+ "",
9411
+ "## Stage 3: Generate Image",
9412
+ "- Generate one production-quality image using the selected style.",
9413
+ "- Follow the selected style skill's generation path when it defines one.",
9414
+ "- If the style skill delegates to a model or connector, use that flow directly instead of restating the style text manually.",
9415
+ "",
9416
+ "## Artifact Output Model",
9417
+ `- Primary artifact: \`${artifact.primaryArtifact.kind}\` under \`${artifact.primaryArtifact.path}\`.`,
9418
+ `- Output mode: \`${artifact.outputMode}\`.`,
9419
+ "- Supporting metadata may live inside the same output directory when useful.",
9420
+ "",
9421
+ "## Requested Parameters",
9422
+ ...options.details.map((detail) => {
9423
+ return `- ${detail}`;
9424
+ }),
9425
+ "",
9426
+ "## Image Authoring Rules",
9427
+ ...artifactRules.map((rule) => {
9428
+ return `- ${rule}`;
9429
+ }),
9430
+ "",
9431
+ "## Verification",
9432
+ "- Verify the final image exists and is nonblank.",
9433
+ "- Check that the selected style's required reference anchors or source assets were used when applicable.",
9434
+ "- Report the final image URL or path and the selected registry resource ID."
9435
+ ].join("\n");
9436
+ return {
9437
+ type: "open-design-resource-selection",
9438
+ kind: "image",
9439
+ prompt: options.prompt,
9440
+ registryVersion: candidateSlice.registryVersion,
9441
+ artifact,
9442
+ selection: {
9443
+ candidates: candidateSlice.candidates,
9444
+ outputSchema: selectionSchema
9445
+ },
9446
+ authoring: {
9447
+ details: options.details,
9448
+ artifactRules
9449
+ },
9450
+ outputDir,
9451
+ instructions
9452
+ };
9453
+ }
9454
+
9455
+ // src/commands/zero/generate/lib/dispatch.ts
9456
+ init_esm_shims();
9457
+ import { readFileSync as readFileSync13 } from "fs";
9458
+
9459
+ // src/commands/zero/generate/lib/connector-guidance.ts
9460
+ init_esm_shims();
9461
+ function toConnectorGenerationType(generationType) {
9462
+ switch (generationType) {
9463
+ case "voice":
9464
+ return "audio";
9465
+ case "dashboard-design":
9466
+ case "docs-design":
9467
+ case "mobile-app-design":
9468
+ case "poster":
9469
+ case "report":
9470
+ return null;
9471
+ default:
9472
+ return generationType;
9473
+ }
9474
+ }
9475
+ function isConnectorType5(value) {
9476
+ return value in CONNECTOR_TYPES;
9477
+ }
9478
+ function resolveConnector(provider, generationType) {
9479
+ if (!isConnectorType5(provider)) return null;
9480
+ const config = CONNECTOR_TYPES[provider];
9481
+ const connectorGenerationType = toConnectorGenerationType(generationType);
9482
+ const supports = connectorGenerationType !== null && getConnectorGenerationTypes(provider).some((entry) => {
9483
+ return entry === connectorGenerationType;
9484
+ });
9485
+ return {
9486
+ type: provider,
9487
+ label: config.label,
9488
+ supportsGenerationType: supports
9489
+ };
9490
+ }
9491
+ function printConnectorGuidance(generationType, provider) {
9492
+ const guidance = resolveConnector(provider, generationType);
9493
+ if (!guidance) {
9494
+ console.log(`Provider "${provider}" is not a known connector.`);
9495
+ console.log("");
9496
+ console.log(
9497
+ `Run "zero generate ${generationType}" to see every provider available for this generation type.`
9498
+ );
9499
+ return;
9500
+ }
9501
+ if (!guidance.supportsGenerationType) {
9502
+ console.log(
9503
+ `${guidance.label} (${guidance.type}) does not advertise ${generationType} generation.`
9504
+ );
9505
+ console.log("");
9506
+ console.log(
9507
+ `Run "zero generate ${generationType}" to see every provider that supports this generation type.`
9508
+ );
9509
+ return;
9510
+ }
9511
+ console.log(
9512
+ `${guidance.label} (${guidance.type}) handles ${generationType} generation through its own connector skill, not through "zero generate".`
9513
+ );
9514
+ console.log("");
9515
+ console.log(`Next steps:`);
9516
+ console.log(` - Use the "${guidance.type}" skill in this session.`);
9517
+ console.log(
9518
+ ` - Or call the connector directly via its documented endpoints.`
9519
+ );
9520
+ console.log("");
9521
+ console.log(
9522
+ `Run "zero connector status ${guidance.type}" to verify the connector is connected and authorized for the current agent.`
9523
+ );
9524
+ }
9525
+
9526
+ // src/commands/zero/generate/lib/lister.ts
9527
+ init_esm_shims();
9528
+ var BUILT_IN_GENERATION_PROVIDERS = {
9529
+ image: [
9530
+ {
9531
+ label: "Built-in fal.ai",
9532
+ model: "gpt-image-1",
9533
+ command: "zero generate image --provider built-in --model gpt-image-1 -h",
9534
+ reason: "available without connector setup"
9535
+ },
9536
+ {
9537
+ label: "Built-in fal.ai",
9538
+ model: "gpt-image-2",
9539
+ command: "zero generate image --provider built-in --model gpt-image-2 -h",
9540
+ reason: "available without connector setup"
9541
+ },
9542
+ {
9543
+ label: "Built-in fal.ai",
9544
+ model: "gpt-image-1.5",
9545
+ command: "zero generate image --provider built-in --model gpt-image-1.5 -h",
9546
+ reason: "available without connector setup"
9547
+ },
9548
+ {
9549
+ label: "Built-in fal.ai",
9550
+ model: "gpt-image-1-mini",
9551
+ command: "zero generate image --provider built-in --model gpt-image-1-mini -h",
9552
+ reason: "available without connector setup"
9553
+ },
9554
+ {
9555
+ label: "Built-in fal.ai",
9556
+ model: "fal-ai/flux-pro/v1.1",
9557
+ command: "zero generate image --provider built-in --model flux-pro-1.1 -h",
9558
+ reason: "available without connector setup"
9559
+ },
9560
+ {
9561
+ label: "Built-in fal.ai",
9562
+ model: "fal-ai/flux-pro/v1.1-ultra",
9563
+ command: "zero generate image --provider built-in --model flux-pro-1.1-ultra -h",
9564
+ reason: "available without connector setup"
9565
+ },
9566
+ {
9567
+ label: "Built-in fal.ai",
9568
+ model: "fal-ai/qwen-image",
9569
+ command: "zero generate image --provider built-in --model qwen-image -h",
9570
+ reason: "available without connector setup"
9571
+ },
9572
+ {
9573
+ label: "Built-in fal.ai",
9574
+ model: "fal-ai/bytedance/seedream/v4/text-to-image",
9575
+ command: "zero generate image --provider built-in --model seedream4 -h",
9576
+ reason: "available without connector setup"
9577
+ }
9578
+ ],
9579
+ presentation: [
9580
+ {
9581
+ label: "Built-in",
9582
+ model: "gpt-5.5",
9583
+ command: "zero generate presentation --provider built-in -h",
9584
+ reason: "available without connector setup"
9585
+ }
9586
+ ],
9587
+ report: [
9588
+ {
9589
+ label: "Built-in",
9590
+ model: "gpt-5.5",
9591
+ command: "zero generate report --provider built-in -h",
9592
+ reason: "available without connector setup"
9593
+ }
9594
+ ],
9595
+ "docs-design": [
9596
+ {
9597
+ label: "Built-in",
9598
+ model: "gpt-5.5",
9599
+ command: "zero generate docs-design --provider built-in -h",
9600
+ reason: "available without connector setup"
9601
+ }
9602
+ ],
9603
+ poster: [
9604
+ {
9605
+ label: "Built-in",
9606
+ model: "gpt-5.5",
9607
+ command: "zero generate poster --provider built-in -h",
9608
+ reason: "available without connector setup"
9609
+ }
9610
+ ],
9611
+ "dashboard-design": [
9612
+ {
9613
+ label: "Built-in",
9614
+ model: "gpt-5.5",
9615
+ command: "zero generate dashboard-design --provider built-in -h",
9616
+ reason: "available without connector setup"
9617
+ }
9618
+ ],
9619
+ "mobile-app-design": [
9620
+ {
9621
+ label: "Built-in",
9622
+ model: "gpt-5.5",
9623
+ command: "zero generate mobile-app-design --provider built-in -h",
9624
+ reason: "available without connector setup"
9625
+ }
9626
+ ],
9627
+ website: [
9628
+ {
9629
+ label: "Built-in",
9630
+ model: "gpt-5.5",
9631
+ command: "zero generate website --provider built-in -h",
9632
+ reason: "available without connector setup"
9633
+ }
9634
+ ],
9635
+ video: [
9636
+ {
9637
+ label: "Built-in",
9638
+ model: "dreamina-seedance-2-0-260128",
9639
+ command: "zero generate video --provider built-in --model dreamina-seedance-2.0 -h",
9640
+ reason: "available without connector setup"
9641
+ },
9642
+ {
9643
+ label: "Built-in",
9644
+ model: "dreamina-seedance-2-0-fast-260128",
9645
+ command: "zero generate video --provider built-in --model dreamina-seedance-2.0-fast -h",
9646
+ reason: "available without connector setup"
9647
+ },
9648
+ {
9649
+ label: "Built-in",
9650
+ model: "seedance-1-5-pro-251215",
9651
+ command: "zero generate video --provider built-in --model seedance-1.5-pro -h",
9652
+ reason: "available without connector setup"
9653
+ },
9654
+ {
9655
+ label: "Built-in fal.ai",
9656
+ model: "fal-ai/veo3.1/fast",
9657
+ command: "zero generate video --provider built-in --model veo3.1-fast -h",
9658
+ reason: "available without connector setup"
9659
+ },
9660
+ {
9661
+ label: "Built-in fal.ai",
9662
+ model: "fal-ai/kling-video/v3/4k/text-to-video",
9663
+ command: "zero generate video --provider built-in --model kling-v3-4k -h",
9664
+ reason: "available without connector setup"
9665
+ }
9666
+ ],
9667
+ voice: [
9668
+ {
9669
+ label: "Built-in",
9670
+ model: "gpt-4o-mini-tts",
9671
+ command: "zero generate voice --provider built-in -h",
9672
+ reason: "available without connector setup"
9673
+ }
9674
+ ]
9675
+ };
9676
+ var BUILT_IN_GENERATION_COMMANDS = {
9677
+ image: {
9678
+ label: "Built-in image generation",
9679
+ command: "zero generate image --provider built-in -h",
9680
+ models: "fal.ai: 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, seedream4"
9713
9681
  },
9714
- {
9715
- id: "vm0:image-style:riso-relic",
9716
- kind: "image-style",
9717
- name: "Riso Relic",
9718
- description: 'Pop-art retro risograph poster of a single nostalgic everyday object on a saturated single-hue field \u2014 bold black ink outlines, halftone grain, hand-drawn doodle accents, tiny "SMALL OBJECTS IN TIME" banner up top, chunky retro headline with offset drop-shadow at the bottom.',
9719
- desc: 'Pop-art retro risograph poster of a single nostalgic everyday object \u2014 saturated single-color background, bold black ink outlines, halftone/riso grain, hand-drawn doodle accents (sparkles, squiggles, dots, music notes, lightning), tiny white "SMALL OBJECTS IN TIME" banner at top, chunky retro display headline at bottom with offset black drop-shadow. Trigger when user says /riso-relic, asks for a "riso poster", a "small objects in time" illustration, or any new piece in this nostalgic pop-art relic-object style.',
9720
- source: { path: "illustration-template/riso-relic" }
9682
+ video: {
9683
+ label: "Built-in video generation",
9684
+ command: "zero generate video --provider built-in -h",
9685
+ models: "dreamina-seedance-2.0-fast (default), dreamina-seedance-2.0, seedance-1.5-pro, veo3.1-fast, kling-v3-4k"
9721
9686
  },
9722
- {
9723
- id: "vm0:image-style:inkstomp",
9724
- kind: "image-style",
9725
- name: "Inkstomp",
9726
- description: "Loud indie-packaging poster style \u2014 full-bleed saturated flat color, a two-line hand-lettered headline, and one weird-cute black brush-ink character.",
9727
- desc: 'Inkstomp \u2014 a loud, hand-screened indie-packaging poster style. Full-bleed saturated flat color filling the entire canvas, a two-line hand-lettered headline (thin arched caps over chunky drop-shadowed display), and one weird-cute character drawn in thick uniform black brush ink. Trigger when the user says /inkstomp, asks for an "inkstomp poster", a "Ray Fenwick / Hattie Stewart packaging poster", an "indie brush-ink flavor card", or briefs in a "palette + headline + character" shape.',
9728
- source: { path: "illustration-template/inkstomp" }
9687
+ presentation: {
9688
+ label: "Built-in presentation generation",
9689
+ command: "zero generate presentation --provider built-in -h",
9690
+ models: "gpt-5.5"
9729
9691
  },
9730
- {
9731
- id: "vm0:image-style:folk-muse",
9732
- kind: "image-style",
9733
- name: "Folk Muse",
9734
- description: "Flat folk-art gouache portrait style \u2014 a single contemplative chest-up figure framed by an asymmetric botanical surround, with painted irises, smooth flat hair, a hand against the cheek, and a patterned robe.",
9735
- desc: 'Flat folk-art gouache portrait illustration in the contemporary editorial style of Carson Ellis, Maja Tomljanovic, and Bodil Jane. A single chest-up figure with an elongated mannerist oval face, tiny almond half-lidded eyes, smooth flat hair, one hand pressed against the face, a patterned robe filling the lower frame, and an asymmetric botanical surround filling the background edge-to-edge. Hand-painted matte gouache texture, flat color blocks, no harsh outlines, no photorealism. Calm, slightly melancholic, contemplative mood. Trigger when the user says /folk-muse, asks for a "folk-art portrait", "gouache portrait", "Carson Ellis style portrait", or any new piece in this contemplative folk-portrait style.',
9736
- source: { path: "illustration-template/folk-muse" }
9692
+ report: {
9693
+ label: "Built-in report generation",
9694
+ command: "zero generate report --provider built-in -h",
9695
+ models: "gpt-5.5"
9737
9696
  },
9738
- {
9739
- id: "vm0:image-style:sunlit-gouache",
9740
- kind: "image-style",
9741
- name: "Sunlit Gouache",
9742
- description: "Bright pastel travel-painting illustration in opaque gouache on textured paper with chunky flat brushstrokes, vertical one-point perspective, and figures walking into warm sunlight.",
9743
- desc: 'Sunlit Gouache travel-painting illustration. Opaque gouache on textured paper, visible chunky flat brushstrokes with dry-brush highlights, locked six-color palette (cream, butter-yellow, sky-blue, sage-green, terracotta, one small red accent), vertical 2:3 one-point-perspective composition drawing the eye into a bright sunlit focal point, figures seen from behind walking into the scene, an overhead band of hanging elements (awning, prayer flags, catenary, bunting, lanterns) creating depth, dappled painterly reflections on the ground, airy optimistic warm mood. Trigger when user says /sunlit-gouache, asks for a "sunlit gouache illustration", "painterly travel scene", "gouache caf\xE9/market/temple/station scene", or a new piece in this bright pastel painted-light style.',
9744
- source: { path: "illustration-template/sunlit-gouache" }
9697
+ "docs-design": {
9698
+ label: "Built-in docs design generation",
9699
+ command: "zero generate docs-design --provider built-in -h",
9700
+ models: "gpt-5.5"
9745
9701
  },
9746
- {
9747
- id: "vm0:image-style:mosaic-still-life",
9748
- kind: "image-style",
9749
- name: "Mosaic Still Life",
9750
- description: "Editorial still-life illustration in a mosaic-tile + painterly hybrid style \u2014 tessellated ground/sky/wall surfaces with crisp painterly objects, an animal companion, and a patterned textile peeking through.",
9751
- desc: 'Mosaic-tile + painterly hybrid editorial illustration. Tessellated/pointillist mosaic surfaces (grass, sky, sand, walls, floors) anchor the scene, with crisp painterly still-life objects rendered ON TOP. Always features a still-life centerpiece on a table, an animal companion at the heart of the scene, and at least one patterned textile peeking through. Cozy, nostalgic, bucolic mood. Trigger when user says /mosaic-still-life, asks for a "mosaic illustration", "mosaic-tile editorial illustration", "tessellated still life", or briefs with a palette + scene + animal in this style.',
9752
- source: { path: "illustration-template/mosaic-still-life" }
9702
+ poster: {
9703
+ label: "Built-in poster generation",
9704
+ command: "zero generate poster --provider built-in -h",
9705
+ models: "gpt-5.5"
9753
9706
  },
9754
- {
9755
- id: "vm0:image-style:ink-mascot",
9756
- kind: "image-style",
9757
- name: "Ink Mascot",
9758
- description: "Vintage editorial marketing card. Bold serif headline and short serif descriptor over a hand-drawn black-ink anthropomorphic mascot (stick limbs, chunky white sneakers) on a single solid saturated flat color background.",
9759
- desc: 'Generate a 3:5 portrait editorial marketing card in a locked vintage-textbook style. Bold serif headline plus an optional short serif descriptor sit on a single solid saturated flat color background (no gradient, no divider, no ground line). A hand-drawn black-ink anthropomorphic hero object \u2014 paint bucket, magnifying glass, envelope, notebook, funnel, megaphone, rocket, seedling, gift box, compass, etc. \u2014 stands with two thin stick arms, two stick legs, and chunky white sneakers with black laces (the signature detail). Crosshatch and stipple shading on rounded surfaces; floating ink doodles (sparkles, arrows, hearts, percent or dollar signs, motion lines) at the requested density. Dialable along six axes: concept, palette, hero object, action, doodle density (L1 minimal, L2 balanced, L3 packed), and type layout (A title-top, B headline-bottom, C headline-only, D big-word + tiny-descriptor). Trigger when user says /ink-mascot, asks for a "marketing card illustration", a "retro editorial mascot poster", or briefs with a marketing concept plus palette plus character.',
9760
- source: { path: "illustration-template/ink-mascot" }
9707
+ "dashboard-design": {
9708
+ label: "Built-in dashboard design generation",
9709
+ command: "zero generate dashboard-design --provider built-in -h",
9710
+ models: "gpt-5.5"
9761
9711
  },
9762
- {
9763
- id: "vm0:image-style:sticker-sheet",
9764
- kind: "image-style",
9765
- name: "Sticker Sheet",
9766
- description: "Hand-painted gouache sticker-sheet illustration with ~20 themed objects floating on white, punchy saturated palette, wobbly hand-drawn ink overlay, and tiny decorative marks on every item.",
9767
- desc: 'Sticker Sheet \u2014 hand-painted gouache sticker-sheet illustration. ~20 small floating themed objects on pure white, punchy saturated palette (coral, mustard, sage, dusty pink, navy, cream, warm brown), flat brushy gouache fills with wobbly hand-drawn ink linework and tiny decorative marks (dots, hatches, squiggles) on every object. Each object slightly tilted, no drop shadows, cheerful cozy lifestyle journal mood. Trigger when user says /sticker-sheet, asks for a "sticker sheet illustration", "hand-painted gouache sticker pack", "themed object sheet", or briefs with a scene theme + object count in this house style.',
9768
- source: { path: "illustration-template/sticker-sheet" }
9712
+ "mobile-app-design": {
9713
+ label: "Built-in mobile app design generation",
9714
+ command: "zero generate mobile-app-design --provider built-in -h",
9715
+ models: "gpt-5.5"
9769
9716
  },
9770
- {
9771
- id: "vm0:image-style:flat-poster",
9772
- kind: "image-style",
9773
- name: "Flat Poster",
9774
- description: "Vertical flat-color editorial poster style \u2014 saturated solid background, one centered hand-drawn vector subject in bold deep-navy outlines with strict two-tone fill, headline pinned top-left, wordmark pinned bottom-right.",
9775
- desc: 'Flat Poster \u2014 a vertical flat-color editorial poster style for brand benefit cards, marketing posters, and in-app campaign visuals. Portrait 2:3 canvas filled edge-to-edge with one saturated hue; a single centered hand-drawn vector subject in deep-navy outlines with strict two-tone fill (pure white plus one darker bg-tint accent); a bold rounded sans-serif headline pinned top-left; a short wordmark (default VM0) pinned bottom-right; small floating accent marks around the subject; no body copy. Six creative dials: palette, subject archetype, composition preset, accent marks, headline voice, mood. Trigger when the user says /flat-poster, asks for a "flat-color editorial poster", a "brand benefit card", a "marketing card in the bold outline + flat color style", or briefs with a palette + subject + headline shape.',
9776
- source: { path: "illustration-template/flat-poster" }
9717
+ website: {
9718
+ label: "Built-in website generation",
9719
+ command: "zero generate website --provider built-in -h",
9720
+ models: "gpt-5.5"
9777
9721
  },
9778
- {
9779
- id: "vm0:image-style:mellow-pop",
9780
- kind: "image-style",
9781
- name: "Mellow Pop",
9782
- description: "Chill flat-vector editorial poster of a serene recurring character on a fully saturated solid color background, with a signature pop of bright leaf-green and a scene-as-metaphor composition.",
9783
- desc: 'Mellow-pop flat-vector editorial illustration: a recurring chill character with closed-eye smile, tiny nose hint, and short dark bobbed hair, posed inside a scene-as-metaphor composition on a single fully saturated solid color background, with a signature pop of bright leaf-green woven into every piece (hero prop, plants, motifs, or sweater). Thin uniform black outlines, flat solid fills only, no gradients or texture. Five dials per brief: palette, scene metaphor, complexity (L1/L2/L3), pose, outfit accent. Trigger when user says /mellow-pop, asks for a "mellow-pop illustration", "chill flat-vector poster", or briefs with a scene metaphor + palette + complexity.',
9784
- source: { path: "illustration-template/mellow-pop" }
9722
+ voice: {
9723
+ label: "Built-in voice generation",
9724
+ command: "zero generate voice --provider built-in -h",
9725
+ models: "gpt-4o-mini-tts"
9726
+ }
9727
+ };
9728
+ var GENERATION_CONTEXT = {
9729
+ website: {
9730
+ lines: [
9731
+ "Standalone static website artifacts can be authored locally and published with zero host for a public URL.",
9732
+ "zero host is for static directories with index.html; it is not a general deploy system for apps that need a backend, database, worker, or long-running process.",
9733
+ "Existing web app changes should usually follow the project's own build, test, and deploy workflow."
9734
+ ]
9735
+ }
9736
+ };
9737
+ var GENERATION_TYPE_ORDER = [
9738
+ "image",
9739
+ "video",
9740
+ "audio",
9741
+ "voice",
9742
+ "text",
9743
+ "code",
9744
+ "document",
9745
+ "presentation",
9746
+ "website",
9747
+ "report",
9748
+ "docs-design",
9749
+ "poster",
9750
+ "dashboard-design",
9751
+ "mobile-app-design"
9752
+ ];
9753
+ var GENERATION_TYPE_LABELS = {
9754
+ audio: "Audio",
9755
+ code: "Code",
9756
+ "dashboard-design": "Dashboard design",
9757
+ document: "Document",
9758
+ "docs-design": "Docs design",
9759
+ image: "Image",
9760
+ "mobile-app-design": "Mobile app design",
9761
+ poster: "Poster",
9762
+ presentation: "Presentation",
9763
+ report: "Report",
9764
+ text: "Text",
9765
+ video: "Video",
9766
+ voice: "Voice",
9767
+ website: "Website"
9768
+ };
9769
+ function getConnectorGenerationType(generationType) {
9770
+ switch (generationType) {
9771
+ case "voice":
9772
+ return "audio";
9773
+ case "dashboard-design":
9774
+ case "docs-design":
9775
+ case "mobile-app-design":
9776
+ case "poster":
9777
+ case "report":
9778
+ return null;
9779
+ case "audio":
9780
+ case "code":
9781
+ case "document":
9782
+ case "image":
9783
+ case "presentation":
9784
+ case "text":
9785
+ case "video":
9786
+ case "website":
9787
+ return generationType;
9785
9788
  }
9786
- ];
9787
- function filterByKind(kind) {
9788
- return OPEN_DESIGN_REGISTRY.filter((entry) => {
9789
- return entry.kind === kind;
9789
+ }
9790
+ function getBuiltInProviders(generationType) {
9791
+ return BUILT_IN_GENERATION_PROVIDERS[generationType] ?? [];
9792
+ }
9793
+ function getBuiltInCommand(generationType) {
9794
+ return BUILT_IN_GENERATION_COMMANDS[generationType] ?? null;
9795
+ }
9796
+ function getGenerationContext(generationType) {
9797
+ return GENERATION_CONTEXT[generationType] ?? null;
9798
+ }
9799
+ function getAvailableGenerationTypes() {
9800
+ const available = /* @__PURE__ */ new Set();
9801
+ for (const type of CONNECTOR_TYPE_KEYS) {
9802
+ for (const generationType of getConnectorGenerationTypes(type)) {
9803
+ available.add(generationType);
9804
+ }
9805
+ }
9806
+ return GENERATION_TYPE_ORDER.filter((type) => {
9807
+ const connectorGenerationType = getConnectorGenerationType(type);
9808
+ return getBuiltInProviders(type).length > 0 || connectorGenerationType !== null && available.has(connectorGenerationType);
9790
9809
  });
9791
9810
  }
9792
- function listImageStyles() {
9793
- return filterByKind("image-style");
9811
+ function getGenerationConnectors(generationType) {
9812
+ return CONNECTOR_TYPE_KEYS.map((type) => {
9813
+ return [type, CONNECTOR_TYPES[type]];
9814
+ }).filter(([type]) => {
9815
+ return getConnectorGenerationTypes(type).includes(generationType);
9816
+ }).sort(([a], [b]) => {
9817
+ return a.localeCompare(b);
9818
+ });
9794
9819
  }
9795
- function findImageStyle(id) {
9796
- return listImageStyles().find((entry) => {
9797
- return entry.id === id;
9820
+ function isConnectorType6(type) {
9821
+ return type in CONNECTOR_TYPES;
9822
+ }
9823
+ async function getFeatureAvailableConnectorTypes() {
9824
+ const catalog = await searchZeroConnectors();
9825
+ return new Set(
9826
+ catalog.connectors.map((connector) => {
9827
+ return connector.id;
9828
+ }).filter(isConnectorType6)
9829
+ );
9830
+ }
9831
+ function formatAccount(connector) {
9832
+ if (connector.externalUsername) return `@${connector.externalUsername}`;
9833
+ if (connector.externalEmail) return connector.externalEmail;
9834
+ if (connector.externalId) return connector.externalId;
9835
+ return void 0;
9836
+ }
9837
+ function getAction(status, type, label, agentId, platformOrigin) {
9838
+ if (status === "needs-reconnect") {
9839
+ return {
9840
+ actionLabel: `Reconnect ${label}`,
9841
+ actionUrl: `${platformOrigin}/connectors`
9842
+ };
9843
+ }
9844
+ if (status === "not-authorized" && agentId) {
9845
+ return {
9846
+ actionLabel: `Authorize ${label}`,
9847
+ actionUrl: `${platformOrigin}/connectors/${type}/authorize?agentId=${agentId}`
9848
+ };
9849
+ }
9850
+ if (status === "not-connected") {
9851
+ if (agentId) {
9852
+ return {
9853
+ actionLabel: `Connect and authorize ${label}`,
9854
+ actionUrl: `${platformOrigin}/connectors/${type}/connect?agentId=${agentId}`
9855
+ };
9856
+ }
9857
+ return {
9858
+ actionLabel: `Connect ${label}`,
9859
+ actionUrl: `${platformOrigin}/connectors/${type}/connect`
9860
+ };
9861
+ }
9862
+ return {};
9863
+ }
9864
+ function toCandidate(params) {
9865
+ const {
9866
+ type,
9867
+ config,
9868
+ connector,
9869
+ configuredTypes,
9870
+ availableTypes,
9871
+ authorizedTypes,
9872
+ agentId,
9873
+ platformOrigin
9874
+ } = params;
9875
+ let status;
9876
+ let reason;
9877
+ if (!availableTypes.has(type)) {
9878
+ status = "not-available";
9879
+ reason = "not available for this account";
9880
+ } else if (connector?.needsReconnect) {
9881
+ status = "needs-reconnect";
9882
+ reason = "connected, reconnect required";
9883
+ } else if (!connector) {
9884
+ status = configuredTypes.has(type) ? "not-connected" : "not-available";
9885
+ reason = status === "not-connected" ? agentId ? "not connected or authorized for current agent" : "not connected" : "not available in this environment";
9886
+ } else if (authorizedTypes && !authorizedTypes.has(type)) {
9887
+ status = "not-authorized";
9888
+ reason = "connected, not authorized for current agent";
9889
+ } else {
9890
+ status = "ready";
9891
+ reason = agentId ? "connected and authorized for current agent" : "connected; agent authorization was not checked";
9892
+ }
9893
+ return {
9894
+ type,
9895
+ label: config.label,
9896
+ status,
9897
+ reason,
9898
+ account: connector ? formatAccount(connector) : void 0,
9899
+ authMethod: connector?.authMethod,
9900
+ ...getAction(status, type, config.label, agentId, platformOrigin)
9901
+ };
9902
+ }
9903
+ function pad(value, width) {
9904
+ return value.padEnd(width);
9905
+ }
9906
+ function renderRows(candidates) {
9907
+ const typeWidth = Math.max(
9908
+ 4,
9909
+ ...candidates.map((candidate) => {
9910
+ return candidate.type.length;
9911
+ })
9912
+ );
9913
+ const labelWidth = Math.max(
9914
+ 5,
9915
+ ...candidates.map((candidate) => {
9916
+ return candidate.label.length;
9917
+ })
9918
+ );
9919
+ for (const candidate of candidates) {
9920
+ const suffix = candidate.status === "ready" ? candidate.account ?? candidate.authMethod ?? "" : candidate.reason;
9921
+ console.log(
9922
+ ` ${pad(candidate.type, typeWidth)} ${pad(candidate.label, labelWidth)} ${suffix}`
9923
+ );
9924
+ }
9925
+ }
9926
+ function renderActions(candidates) {
9927
+ const actionable = candidates.filter((candidate) => {
9928
+ return candidate.actionLabel && candidate.actionUrl;
9798
9929
  });
9930
+ if (actionable.length === 0) return;
9931
+ console.log("");
9932
+ console.log("Next actions:");
9933
+ for (const candidate of actionable) {
9934
+ console.log(` [${candidate.actionLabel}](${candidate.actionUrl})`);
9935
+ }
9799
9936
  }
9800
- function toOpenDesignTarget(value) {
9801
- if (value === "dashboard") {
9802
- return "dashboard-design";
9937
+ function renderBuiltInProvider(generationType) {
9938
+ const command = getBuiltInCommand(generationType);
9939
+ if (command) {
9940
+ console.log("");
9941
+ console.log("Built-in command:");
9942
+ console.log(` vm0 ${command.label}`);
9943
+ console.log(` Models: ${command.models}`);
9944
+ console.log(` Use: ${command.command}`);
9945
+ return;
9946
+ }
9947
+ const providers = getBuiltInProviders(generationType);
9948
+ if (providers.length === 0) return;
9949
+ console.log("");
9950
+ console.log(
9951
+ providers.length === 1 ? "Built-in provider:" : "Built-in providers:"
9952
+ );
9953
+ for (const provider of providers) {
9954
+ console.log(` vm0 ${provider.label} Model: ${provider.model}`);
9955
+ console.log(` Use: ${provider.command}`);
9956
+ }
9957
+ }
9958
+ function renderGenerationContext(generationType) {
9959
+ const context = getGenerationContext(generationType);
9960
+ if (!context) return;
9961
+ console.log("");
9962
+ console.log("Context:");
9963
+ for (const line of context.lines) {
9964
+ console.log(` - ${line}`);
9965
+ }
9966
+ }
9967
+ function renderText(params) {
9968
+ const { generationType, agentId, ready, other, showAll } = params;
9969
+ const label = GENERATION_TYPE_LABELS[generationType];
9970
+ const scope = agentId ? "for current agent" : "(connected connectors)";
9971
+ console.log(`${label} generation choices ${scope}`);
9972
+ console.log("");
9973
+ if (agentId) {
9974
+ console.log(`${"Agent:".padEnd(10)}${agentId}`);
9975
+ console.log("");
9976
+ } else {
9977
+ console.log(
9978
+ "ZERO_AGENT_ID is not set, so agent authorization could not be checked."
9979
+ );
9980
+ console.log("");
9981
+ }
9982
+ const hasBuiltInCommand = getBuiltInCommand(generationType) !== null;
9983
+ const showConnectorSummary = ready.length > 0 || !hasBuiltInCommand || showAll;
9984
+ if (showConnectorSummary) {
9985
+ console.log("Connectors:");
9986
+ if (ready.length > 0) {
9987
+ renderRows(ready);
9988
+ } else {
9989
+ console.log(` No ready ${generationType} generation connectors found.`);
9990
+ }
9991
+ }
9992
+ renderBuiltInProvider(generationType);
9993
+ renderGenerationContext(generationType);
9994
+ if (showAll && other.length > 0) {
9995
+ console.log("");
9996
+ console.log(`Other ${generationType} generation connectors`);
9997
+ console.log("");
9998
+ renderRows(other);
9999
+ }
10000
+ if (showAll) {
10001
+ renderActions(other);
10002
+ }
10003
+ }
10004
+ async function runLister(generationType, options = {}) {
10005
+ const connectorGenerationType = getConnectorGenerationType(generationType);
10006
+ const agentId = process.env.ZERO_AGENT_ID;
10007
+ const [connectorList, availableTypes, enabledTypes, platformOrigin] = await Promise.all([
10008
+ listZeroConnectors(),
10009
+ getFeatureAvailableConnectorTypes(),
10010
+ agentId ? getZeroAgentUserConnectors(agentId) : Promise.resolve(null),
10011
+ getPlatformOrigin()
10012
+ ]);
10013
+ const connectedMap = new Map(
10014
+ connectorList.connectors.map((connector) => {
10015
+ return [connector.type, connector];
10016
+ })
10017
+ );
10018
+ const configuredTypes = new Set(connectorList.configuredTypes);
10019
+ const authorizedTypes = enabledTypes ? new Set(enabledTypes) : null;
10020
+ const candidates = connectorGenerationType ? getGenerationConnectors(connectorGenerationType).map(
10021
+ ([connectorType, config]) => {
10022
+ return toCandidate({
10023
+ type: connectorType,
10024
+ config,
10025
+ connector: connectedMap.get(connectorType),
10026
+ configuredTypes,
10027
+ availableTypes,
10028
+ authorizedTypes,
10029
+ agentId,
10030
+ platformOrigin
10031
+ });
10032
+ }
10033
+ ) : [];
10034
+ const ready = candidates.filter((candidate) => {
10035
+ return candidate.status === "ready";
10036
+ });
10037
+ const other = candidates.filter((candidate) => {
10038
+ return candidate.status !== "ready";
10039
+ });
10040
+ const builtInProviders = getBuiltInProviders(generationType);
10041
+ if (options.json) {
10042
+ console.log(
10043
+ JSON.stringify(
10044
+ {
10045
+ generationType,
10046
+ connectorGenerationType,
10047
+ availableTypes: getAvailableGenerationTypes(),
10048
+ agentId: agentId ?? null,
10049
+ choices: ready,
10050
+ otherCandidates: other,
10051
+ builtInCommand: getBuiltInCommand(generationType),
10052
+ generationContext: getGenerationContext(generationType),
10053
+ builtInProvider: builtInProviders[0] ?? null,
10054
+ builtInProviders
10055
+ },
10056
+ null,
10057
+ 2
10058
+ )
10059
+ );
10060
+ return;
10061
+ }
10062
+ renderText({
10063
+ generationType,
10064
+ agentId,
10065
+ ready,
10066
+ other,
10067
+ showAll: options.all === true
10068
+ });
10069
+ const shouldShowOtherHint = !options.all && other.length > 0 && (ready.length > 0 || getBuiltInCommand(generationType) === null);
10070
+ if (shouldShowOtherHint) {
10071
+ console.log("");
10072
+ console.log(
10073
+ source_default.dim(
10074
+ `Use --all to see every ${generationType} generation candidate.`
10075
+ )
10076
+ );
9803
10077
  }
9804
- if (value === "docs") {
9805
- return "docs-design";
10078
+ }
10079
+
10080
+ // src/commands/zero/generate/lib/dispatch.ts
10081
+ async function dispatchGenerate(options) {
10082
+ const provider = options.provider?.trim();
10083
+ if (provider && provider !== "built-in") {
10084
+ printConnectorGuidance(options.generationType, provider);
10085
+ return { outcome: "handled" };
9806
10086
  }
9807
- if (value === "mobile-app") {
9808
- return "mobile-app-design";
10087
+ const resolvedPrompt = resolvePrompt(options.prompt);
10088
+ if (resolvedPrompt === null) {
10089
+ await runLister(options.generationType, {
10090
+ all: options.all,
10091
+ json: options.json
10092
+ });
10093
+ return { outcome: "handled" };
9809
10094
  }
9810
- return value;
10095
+ return { outcome: "execute", prompt: resolvedPrompt };
9811
10096
  }
9812
- function selectOpenDesignCandidates() {
9813
- return {
9814
- registryVersion: OPEN_DESIGN_REGISTRY_VERSION,
9815
- source: {
9816
- repo: OPEN_DESIGN_REPO,
9817
- commit: OPEN_DESIGN_COMMIT
9818
- },
9819
- sources: [
9820
- {
9821
- repo: OPEN_DESIGN_REPO,
9822
- commit: OPEN_DESIGN_COMMIT
9823
- },
9824
- {
9825
- repo: VM0_SKILLS_REPO,
9826
- commit: VM0_SKILLS_REF
10097
+ function resolvePrompt(prompt) {
10098
+ if (prompt?.trim()) {
10099
+ return prompt.trim();
10100
+ }
10101
+ if (process.stdin.isTTY === false) {
10102
+ try {
10103
+ const piped = readFileSync13("/dev/stdin", "utf8").trim();
10104
+ if (piped.length > 0) {
10105
+ return piped;
9827
10106
  }
9828
- ],
9829
- candidates: {
9830
- skills: filterByKind("skill"),
9831
- templates: filterByKind("template"),
9832
- designSystems: filterByKind("design-system"),
9833
- imageStyles: filterByKind("image-style"),
9834
- audioStyles: filterByKind("audio-style"),
9835
- videoTemplates: filterByKind("video-template"),
9836
- bundleTemplates: filterByKind("bundle-template")
9837
- }
9838
- };
9839
- }
9840
-
9841
- // src/commands/zero/shared/image-style-authoring.ts
9842
- var outputDir = "./opendesign/images";
9843
- var artifactRules = [
9844
- "Resolve the selected style source before generating the image.",
9845
- "Use the style skill's referenced assets and generation path when it provides one.",
9846
- "Produce a single final image file and keep any temporary metadata under the output directory."
9847
- ];
9848
- function createStyledImageAuthoringPacket(options) {
9849
- const baseSlice = selectOpenDesignCandidates();
9850
- const candidateSlice = {
9851
- ...baseSlice,
9852
- candidates: {
9853
- ...baseSlice.candidates,
9854
- imageStyles: [options.style]
10107
+ } catch {
9855
10108
  }
9856
- };
9857
- const selectionSchema = {
9858
- imageStyle: "string",
9859
- skills: "string[]",
9860
- rationale: "string"
9861
- };
9862
- const artifact = {
9863
- outputMode: "primary-image",
9864
- primaryArtifact: {
9865
- kind: "image",
9866
- path: `${outputDir}/`
9867
- },
9868
- supportingAssets: [
9869
- {
9870
- kind: "metadata",
9871
- path: `${outputDir}/metadata.json`,
9872
- optional: true
9873
- }
9874
- ],
9875
- previewKind: "image",
9876
- outputDir
9877
- };
9878
- const instructions = [
9879
- `# Zero built-in generate image --style ${options.style.id}`,
9880
- "",
9881
- "This is a federated generation resource-selection packet for the current agent.",
9882
- "Zero is not generating this image on the server yet. The image style has already been selected by the caller \u2014 resolve it and generate the styled image.",
9883
- "",
9884
- "## User Prompt",
9885
- options.prompt,
9886
- "",
9887
- "## Selected Image Style",
9888
- `- \`${options.style.id}\` \u2014 ${options.style.name}`,
9889
- "",
9890
- "## Stage 1: Supporting Resource Selection",
9891
- "- The image style is locked. Optionally pick supporting skills/templates from the candidate slice below.",
9892
- "- Choose only IDs present in this packet; do not invent registry IDs.",
9893
- "- Treat the selection JSON as internal working state, then continue to generation.",
9894
- "",
9895
- "## Selection Output Schema",
9896
- "```json",
9897
- JSON.stringify(selectionSchema, null, 2),
9898
- "```",
9899
- "",
9900
- "## Candidate Registry Slice",
9901
- `Registry: \`${candidateSlice.registryVersion}\``,
9902
- "Sources:",
9903
- ...candidateSlice.sources.map((src) => {
9904
- return `- \`${src.repo}@${src.commit}\``;
9905
- }),
9906
- "",
9907
- "```json",
9908
- JSON.stringify(candidateSlice.candidates, null, 2),
9909
- "```",
9910
- "",
9911
- "## Stage 2: Resolve Selected Resources",
9912
- "- Fetch or read the selected resource source before generation.",
9913
- "- Source refs are pinned as `repo@commit:path`; use the commit in the packet for reproducibility.",
9914
- "- For directory refs, inspect the most relevant files such as `SKILL.md`, references, examples, and templates.",
9915
- "- If a source file cannot be fetched, state that limitation and fall back to the registry metadata for that resource.",
9916
- "",
9917
- "## Stage 3: Generate Image",
9918
- "- Generate one production-quality image using the selected style.",
9919
- "- Follow the selected style skill's generation path when it defines one.",
9920
- "- If the style skill delegates to a model or connector, use that flow directly instead of restating the style text manually.",
9921
- "",
9922
- "## Artifact Output Model",
9923
- `- Primary artifact: \`${artifact.primaryArtifact.kind}\` under \`${artifact.primaryArtifact.path}\`.`,
9924
- `- Output mode: \`${artifact.outputMode}\`.`,
9925
- "- Supporting metadata may live inside the same output directory when useful.",
9926
- "",
9927
- "## Requested Parameters",
9928
- ...options.details.map((detail) => {
9929
- return `- ${detail}`;
9930
- }),
9931
- "",
9932
- "## Image Authoring Rules",
9933
- ...artifactRules.map((rule) => {
9934
- return `- ${rule}`;
9935
- }),
9936
- "",
9937
- "## Verification",
9938
- "- Verify the final image exists and is nonblank.",
9939
- "- Check that the selected style's required reference anchors or source assets were used when applicable.",
9940
- "- Report the final image URL or path and the selected registry resource ID."
9941
- ].join("\n");
9942
- return {
9943
- type: "open-design-resource-selection",
9944
- kind: "image",
9945
- prompt: options.prompt,
9946
- registryVersion: candidateSlice.registryVersion,
9947
- artifact,
9948
- selection: {
9949
- candidates: candidateSlice.candidates,
9950
- outputSchema: selectionSchema
9951
- },
9952
- authoring: {
9953
- details: options.details,
9954
- artifactRules
9955
- },
9956
- outputDir,
9957
- instructions
9958
- };
10109
+ }
10110
+ return null;
9959
10111
  }
9960
10112
 
9961
10113
  // src/commands/zero/shared/image-generate.ts
@@ -9996,20 +10148,6 @@ function unknownStyleError(id, usageCommand) {
9996
10148
  ].join("\n");
9997
10149
  return new Error(message);
9998
10150
  }
9999
- function readPrompt(options, usageCommand) {
10000
- if (options.prompt?.trim()) {
10001
- return options.prompt.trim();
10002
- }
10003
- if (process.stdin.isTTY === false) {
10004
- const prompt = readFileSync13("/dev/stdin", "utf8").trim();
10005
- if (prompt.length > 0) {
10006
- return prompt;
10007
- }
10008
- }
10009
- throw new Error("--prompt is required", {
10010
- cause: new Error(`Usage: ${usageCommand} --prompt "A watercolor fox"`)
10011
- });
10012
- }
10013
10151
  function parseCompression(value) {
10014
10152
  if (value === void 0) {
10015
10153
  return void 0;
@@ -10051,6 +10189,12 @@ function parseImagePromptStrength(value) {
10051
10189
  }
10052
10190
  function createImageGenerateCommand(config) {
10053
10191
  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(
10192
+ "--provider <name>",
10193
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
10194
+ ).option(
10195
+ "--all",
10196
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
10197
+ ).option(
10054
10198
  "--model <model>",
10055
10199
  "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",
10056
10200
  "gpt-image-1"
@@ -10142,13 +10286,21 @@ Image Styles:
10142
10286
  ${formatStyleListing(styles)}`;
10143
10287
  }).action(
10144
10288
  withErrorHandler(async (options, command) => {
10289
+ const dispatch = await dispatchGenerate({
10290
+ generationType: config.generationType,
10291
+ provider: options.provider,
10292
+ prompt: options.prompt,
10293
+ all: options.all,
10294
+ json: options.json
10295
+ });
10296
+ if (dispatch.outcome === "handled") return;
10297
+ const prompt = dispatch.prompt;
10145
10298
  if (options.style && options.skipStyle) {
10146
10299
  throw new Error("--style and --skip-style cannot be combined");
10147
10300
  }
10148
10301
  if (!options.style && !options.skipStyle) {
10149
10302
  throw requireStyleError(config.usageCommand);
10150
10303
  }
10151
- const prompt = readPrompt(options, config.usageCommand);
10152
10304
  if (options.style) {
10153
10305
  const style = findImageStyle(options.style);
10154
10306
  if (!style) {
@@ -10228,24 +10380,26 @@ ${formatStyleListing(styles)}`;
10228
10380
  );
10229
10381
  }
10230
10382
 
10231
- // src/commands/zero/built-in/generate/image.ts
10383
+ // src/commands/zero/generate/image.ts
10232
10384
  var imageCommand = createImageGenerateCommand({
10233
10385
  name: "image",
10234
- usageCommand: "zero built-in generate image",
10235
- examples: ` Styled image: zero built-in generate image --style vm0:image-style:notion-illustration --prompt "A product manager mapping a launch plan"
10236
- Skip style: zero built-in generate image --skip-style --prompt "A watercolor fox"
10237
- Pipe prompt: cat prompt.txt | zero built-in generate image --skip-style
10238
- GPT Image model: zero built-in generate image --skip-style --model gpt-image-1.5 --prompt "A poster" --size 1024x1536 --quality high
10239
- Flux model: zero built-in generate image --skip-style --model flux-pro-1.1 --prompt "A product hero shot" --seed 42
10240
- Image-to-image: zero built-in generate image --skip-style --model flux-pro-1.1 --image-url https://example.com/mockup.png --prompt "Turn this mockup into a polished product shot"`
10386
+ generationType: "image",
10387
+ usageCommand: "zero generate image",
10388
+ examples: ` Styled image: zero generate image --style vm0:image-style:notion-illustration --prompt "A product manager mapping a launch plan"
10389
+ Skip style: zero generate image --skip-style --prompt "A watercolor fox"
10390
+ Pipe prompt: cat prompt.txt | zero generate image --skip-style
10391
+ GPT Image model: zero generate image --skip-style --model gpt-image-1.5 --prompt "A poster" --size 1024x1536 --quality high
10392
+ Flux model: zero generate image --skip-style --model flux-pro-1.1 --prompt "A product hero shot" --seed 42
10393
+ Image-to-image: zero generate image --skip-style --model flux-pro-1.1 --image-url https://example.com/mockup.png --prompt "Turn this mockup into a polished product shot"
10394
+ List providers: zero generate image
10395
+ Use a connector: zero generate image --provider replicate`
10241
10396
  });
10242
10397
 
10243
- // src/commands/zero/built-in/generate/open-design-artifacts.ts
10398
+ // src/commands/zero/generate/open-design-artifacts.ts
10244
10399
  init_esm_shims();
10245
10400
 
10246
10401
  // src/commands/zero/shared/open-design-artifact-generate.ts
10247
10402
  init_esm_shims();
10248
- import { readFileSync as readFileSync14 } from "fs";
10249
10403
 
10250
10404
  // src/commands/zero/shared/html-artifact-authoring.ts
10251
10405
  init_esm_shims();
@@ -10318,7 +10472,7 @@ function createHtmlArtifactAuthoringPacket(options) {
10318
10472
  outputDir: outputDir2
10319
10473
  };
10320
10474
  const instructions = [
10321
- `# Zero built-in generate ${options.kind}`,
10475
+ `# Zero generate ${options.kind}`,
10322
10476
  "",
10323
10477
  "This is a federated generation resource-selection packet for the current agent.",
10324
10478
  `Zero is not generating this ${title} on the server. You select resources, resolve them, and author the artifact.`,
@@ -10425,22 +10579,14 @@ function createHtmlArtifactAuthoringPacket(options) {
10425
10579
  }
10426
10580
 
10427
10581
  // src/commands/zero/shared/open-design-artifact-generate.ts
10428
- function readPrompt2(options, usageCommand) {
10429
- if (options.prompt?.trim()) {
10430
- return options.prompt.trim();
10431
- }
10432
- if (process.stdin.isTTY === false) {
10433
- const prompt = readFileSync14("/dev/stdin", "utf8").trim();
10434
- if (prompt.length > 0) {
10435
- return prompt;
10436
- }
10437
- }
10438
- throw new Error("--prompt is required", {
10439
- cause: new Error(`Usage: ${usageCommand} --prompt "A product report"`)
10440
- });
10441
- }
10442
10582
  function createOpenDesignArtifactGenerateCommand(config) {
10443
- return new Command().name(config.name).description(config.description).option("--prompt <text>", "Artifact prompt; can also be piped via stdin").option("--site <slug>", "Hosted site slug; defaults to generated name").option("--title <text>", "Requested artifact title or name").option("--audience <text>", "Audience context").option("--json", "Print metadata as JSON").addHelpText(
10583
+ return new Command().name(config.name).description(config.description).option("--prompt <text>", "Artifact prompt; can also be piped via stdin").option(
10584
+ "--provider <name>",
10585
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
10586
+ ).option(
10587
+ "--all",
10588
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
10589
+ ).option("--site <slug>", "Hosted site slug; defaults to generated name").option("--title <text>", "Requested artifact title or name").option("--audience <text>", "Audience context").option("--json", "Print metadata as JSON").addHelpText(
10444
10590
  "after",
10445
10591
  `
10446
10592
  Examples:
@@ -10448,13 +10594,22 @@ ${config.examples}
10448
10594
 
10449
10595
  Output:
10450
10596
  Prints an Open Design resource-selection packet for the current agent. The
10451
- agent authors a static HTML artifact and hosts it with zero host.
10597
+ agent authors a static HTML artifact and hosts it with zero host. With no
10598
+ --prompt and no piped input, prints the provider menu instead.
10452
10599
 
10453
10600
  Notes:
10454
10601
  - Authenticates via ZERO_TOKEN`
10455
10602
  ).action(
10456
10603
  withErrorHandler(async (options) => {
10457
- const prompt = readPrompt2(options, config.usageCommand);
10604
+ const dispatch = await dispatchGenerate({
10605
+ generationType: config.generationType,
10606
+ provider: options.provider,
10607
+ prompt: options.prompt,
10608
+ all: options.all,
10609
+ json: options.json
10610
+ });
10611
+ if (dispatch.outcome === "handled") return;
10612
+ const prompt = dispatch.prompt;
10458
10613
  const packet = createHtmlArtifactAuthoringPacket({
10459
10614
  kind: toOpenDesignTarget(config.target),
10460
10615
  prompt,
@@ -10472,7 +10627,7 @@ Notes:
10472
10627
  );
10473
10628
  }
10474
10629
 
10475
- // src/commands/zero/built-in/generate/open-design-artifacts.ts
10630
+ // src/commands/zero/generate/open-design-artifacts.ts
10476
10631
  function standardDetails(kind) {
10477
10632
  return (options) => {
10478
10633
  return [
@@ -10484,11 +10639,13 @@ function standardDetails(kind) {
10484
10639
  }
10485
10640
  var reportCommand = createOpenDesignArtifactGenerateCommand({
10486
10641
  name: "report",
10642
+ generationType: "report",
10487
10643
  target: "report",
10488
10644
  description: "Generate an Open Design HTML report from a prompt",
10489
- usageCommand: "zero built-in generate report",
10490
- examples: ` Generate report: zero built-in generate report --prompt "A Q2 usage report for the API team"
10491
- Stable hosted slug: zero built-in generate report --site api-usage-q2 --prompt "A Q2 usage report"`,
10645
+ usageCommand: "zero generate report",
10646
+ examples: ` Generate report: zero generate report --prompt "A Q2 usage report for the API team"
10647
+ Stable hosted slug: zero generate report --site api-usage-q2 --prompt "A Q2 usage report"
10648
+ List providers: zero generate report`,
10492
10649
  details: standardDetails("report"),
10493
10650
  artifactRules: [
10494
10651
  "Produce an analytical report, not a marketing page.",
@@ -10499,11 +10656,13 @@ var reportCommand = createOpenDesignArtifactGenerateCommand({
10499
10656
  });
10500
10657
  var docsDesignCommand = createOpenDesignArtifactGenerateCommand({
10501
10658
  name: "docs-design",
10659
+ generationType: "docs-design",
10502
10660
  target: "docs-design",
10503
10661
  description: "Generate an Open Design documentation design from a prompt",
10504
- usageCommand: "zero built-in generate docs-design",
10505
- examples: ` Generate docs design: zero built-in generate docs-design --prompt "Docs for adding OpenDesign artifact targets"
10506
- Stable hosted slug: zero built-in generate docs-design --site opendesign-target-docs --prompt "OpenDesign target docs"`,
10662
+ usageCommand: "zero generate docs-design",
10663
+ examples: ` Generate docs design: zero generate docs-design --prompt "Docs for adding OpenDesign artifact targets"
10664
+ Stable hosted slug: zero generate docs-design --site opendesign-target-docs --prompt "OpenDesign target docs"
10665
+ List providers: zero generate docs-design`,
10507
10666
  details: standardDetails("docs-design"),
10508
10667
  artifactRules: [
10509
10668
  "Produce a documentation design mockup, not a production documentation system.",
@@ -10514,11 +10673,13 @@ var docsDesignCommand = createOpenDesignArtifactGenerateCommand({
10514
10673
  });
10515
10674
  var posterCommand = createOpenDesignArtifactGenerateCommand({
10516
10675
  name: "poster",
10676
+ generationType: "poster",
10517
10677
  target: "poster",
10518
10678
  description: "Generate an Open Design HTML poster from a prompt",
10519
- usageCommand: "zero built-in generate poster",
10520
- examples: ` Generate poster: zero built-in generate poster --prompt "A launch poster for OpenDesign artifact targets"
10521
- Stable hosted slug: zero built-in generate poster --site opendesign-poster --prompt "A launch poster"`,
10679
+ usageCommand: "zero generate poster",
10680
+ examples: ` Generate poster: zero generate poster --prompt "A launch poster for OpenDesign artifact targets"
10681
+ Stable hosted slug: zero generate poster --site opendesign-poster --prompt "A launch poster"
10682
+ List providers: zero generate poster`,
10522
10683
  details: standardDetails("poster"),
10523
10684
  artifactRules: [
10524
10685
  "Produce a poster-style HTML artifact with strong hierarchy and composition.",
@@ -10529,11 +10690,13 @@ var posterCommand = createOpenDesignArtifactGenerateCommand({
10529
10690
  });
10530
10691
  var dashboardDesignCommand = createOpenDesignArtifactGenerateCommand({
10531
10692
  name: "dashboard-design",
10693
+ generationType: "dashboard-design",
10532
10694
  target: "dashboard-design",
10533
10695
  description: "Generate an Open Design dashboard design from a prompt",
10534
- usageCommand: "zero built-in generate dashboard-design",
10535
- examples: ` Generate dash design: zero built-in generate dashboard-design --prompt "An ops dashboard for generation runs"
10536
- Stable hosted slug: zero built-in generate dashboard-design --site generation-ops --prompt "A generation ops dashboard"`,
10696
+ usageCommand: "zero generate dashboard-design",
10697
+ examples: ` Generate dash design: zero generate dashboard-design --prompt "An ops dashboard for generation runs"
10698
+ Stable hosted slug: zero generate dashboard-design --site generation-ops --prompt "A generation ops dashboard"
10699
+ List providers: zero generate dashboard-design`,
10537
10700
  details: standardDetails("dashboard-design"),
10538
10701
  artifactRules: [
10539
10702
  "Produce a dashboard design mockup, not a live operational dashboard.",
@@ -10544,11 +10707,13 @@ var dashboardDesignCommand = createOpenDesignArtifactGenerateCommand({
10544
10707
  });
10545
10708
  var mobileAppDesignCommand = createOpenDesignArtifactGenerateCommand({
10546
10709
  name: "mobile-app-design",
10710
+ generationType: "mobile-app-design",
10547
10711
  target: "mobile-app-design",
10548
10712
  description: "Generate an Open Design mobile app design prototype from a prompt",
10549
- usageCommand: "zero built-in generate mobile-app-design",
10550
- examples: ` Generate mobile UI: zero built-in generate mobile-app-design --prompt "A mobile review screen for generation artifacts"
10551
- Stable hosted slug: zero built-in generate mobile-app-design --site generation-mobile-review --prompt "A mobile review screen"`,
10713
+ usageCommand: "zero generate mobile-app-design",
10714
+ examples: ` Generate mobile UI: zero generate mobile-app-design --prompt "A mobile review screen for generation artifacts"
10715
+ Stable hosted slug: zero generate mobile-app-design --site generation-mobile-review --prompt "A mobile review screen"
10716
+ List providers: zero generate mobile-app-design`,
10552
10717
  details: standardDetails("mobile-app-design"),
10553
10718
  artifactRules: [
10554
10719
  "Produce a design prototype, not a runnable or installable mobile app.",
@@ -10558,12 +10723,11 @@ var mobileAppDesignCommand = createOpenDesignArtifactGenerateCommand({
10558
10723
  ]
10559
10724
  });
10560
10725
 
10561
- // src/commands/zero/built-in/generate/presentation.ts
10726
+ // src/commands/zero/generate/presentation.ts
10562
10727
  init_esm_shims();
10563
10728
 
10564
10729
  // src/commands/zero/shared/presentation-generate.ts
10565
10730
  init_esm_shims();
10566
- import { readFileSync as readFileSync15 } from "fs";
10567
10731
  var PRESENTATION_MAX_IMAGES = 8;
10568
10732
  function parseSlideCount(value) {
10569
10733
  const slideCount = Number(value);
@@ -10584,26 +10748,16 @@ function parseImageCount(value) {
10584
10748
  }
10585
10749
  return imageCount;
10586
10750
  }
10587
- function readPrompt3(options, usageCommand) {
10588
- if (options.prompt?.trim()) {
10589
- return options.prompt.trim();
10590
- }
10591
- if (process.stdin.isTTY === false) {
10592
- const prompt = readFileSync15("/dev/stdin", "utf8").trim();
10593
- if (prompt.length > 0) {
10594
- return prompt;
10595
- }
10596
- }
10597
- throw new Error("--prompt is required", {
10598
- cause: new Error(
10599
- `Usage: ${usageCommand} --prompt "A product roadmap deck"`
10600
- )
10601
- });
10602
- }
10603
10751
  function createPresentationGenerateCommand(config) {
10604
10752
  return new Command().name(config.name).description("Generate an HTML presentation from a prompt").option(
10605
10753
  "--prompt <text>",
10606
10754
  "Presentation prompt; can also be piped via stdin"
10755
+ ).option(
10756
+ "--provider <name>",
10757
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
10758
+ ).option(
10759
+ "--all",
10760
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
10607
10761
  ).option("--style <style>", "Style: editorial or swiss", "editorial").option("--slides <count>", "Slide count: 4-20", parseSlideCount, 8).option(
10608
10762
  "--images <count>",
10609
10763
  `Generated image count: 0-${PRESENTATION_MAX_IMAGES}`,
@@ -10629,7 +10783,15 @@ Notes:
10629
10783
  - The agent authors the HTML presentation artifact and hosts it with zero host`
10630
10784
  ).action(
10631
10785
  withErrorHandler(async (options) => {
10632
- const prompt = readPrompt3(options, config.usageCommand);
10786
+ const dispatch = await dispatchGenerate({
10787
+ generationType: config.generationType,
10788
+ provider: options.provider,
10789
+ prompt: options.prompt,
10790
+ all: options.all,
10791
+ json: options.json
10792
+ });
10793
+ if (dispatch.outcome === "handled") return;
10794
+ const prompt = dispatch.prompt;
10633
10795
  const packet = createHtmlArtifactAuthoringPacket({
10634
10796
  kind: "presentation",
10635
10797
  prompt,
@@ -10660,22 +10822,23 @@ Notes:
10660
10822
  );
10661
10823
  }
10662
10824
 
10663
- // src/commands/zero/built-in/generate/presentation.ts
10825
+ // src/commands/zero/generate/presentation.ts
10664
10826
  var presentationCommand = createPresentationGenerateCommand({
10665
10827
  name: "presentation",
10666
- usageCommand: "zero built-in generate presentation",
10667
- examples: ` Generate deck: zero built-in generate presentation --prompt "A strategy deck for reducing support volume"
10668
- Pipe prompt: cat brief.txt | zero built-in generate presentation
10669
- Swiss style: zero built-in generate presentation --style swiss --theme ikb --slides 10 --images 8 --image-model gpt-image-1.5 --prompt "A product launch narrative"
10670
- Audience context: zero built-in generate presentation --audience "engineering leadership" --prompt "API migration plan"`
10828
+ generationType: "presentation",
10829
+ usageCommand: "zero generate presentation",
10830
+ examples: ` Generate deck: zero generate presentation --prompt "A strategy deck for reducing support volume"
10831
+ Pipe prompt: cat brief.txt | zero generate presentation
10832
+ Swiss style: zero generate presentation --style swiss --theme ikb --slides 10 --images 8 --image-model gpt-image-1.5 --prompt "A product launch narrative"
10833
+ Audience context: zero generate presentation --audience "engineering leadership" --prompt "API migration plan"
10834
+ List providers: zero generate presentation`
10671
10835
  });
10672
10836
 
10673
- // src/commands/zero/built-in/generate/video.ts
10837
+ // src/commands/zero/generate/video.ts
10674
10838
  init_esm_shims();
10675
10839
 
10676
10840
  // src/commands/zero/shared/video-generate.ts
10677
10841
  init_esm_shims();
10678
- import { readFileSync as readFileSync16 } from "fs";
10679
10842
  var FRAME_ASPECT_RATIO_TOLERANCE = 0.02;
10680
10843
  var JPEG_START_OF_FRAME_MARKERS = /* @__PURE__ */ new Set([
10681
10844
  192,
@@ -10869,22 +11032,14 @@ async function validateVideoOptions(options) {
10869
11032
  )
10870
11033
  ]);
10871
11034
  }
10872
- function readPrompt4(options, usageCommand) {
10873
- if (options.prompt?.trim()) {
10874
- return options.prompt.trim();
10875
- }
10876
- if (process.stdin.isTTY === false) {
10877
- const prompt = readFileSync16("/dev/stdin", "utf8").trim();
10878
- if (prompt.length > 0) {
10879
- return prompt;
10880
- }
10881
- }
10882
- throw new Error("--prompt is required", {
10883
- cause: new Error(`Usage: ${usageCommand} --prompt "A cinematic city shot"`)
10884
- });
10885
- }
10886
11035
  function createVideoGenerateCommand(config) {
10887
11036
  return new Command().name(config.name).description("Generate a billed video file from a prompt").option("--prompt <text>", "Video prompt; can also be piped via stdin").option(
11037
+ "--provider <name>",
11038
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
11039
+ ).option(
11040
+ "--all",
11041
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
11042
+ ).option(
10888
11043
  "--model <model>",
10889
11044
  "Model: dreamina-seedance-2.0-fast, dreamina-seedance-2.0, seedance-1.5-pro, veo3.1-fast, or kling-v3-4k",
10890
11045
  "dreamina-seedance-2.0-fast"
@@ -10939,7 +11094,15 @@ Models:
10939
11094
  4k output, negative prompts, and optional audio.`
10940
11095
  ).action(
10941
11096
  withErrorHandler(async (options) => {
10942
- const prompt = readPrompt4(options, config.usageCommand);
11097
+ const dispatch = await dispatchGenerate({
11098
+ generationType: config.generationType,
11099
+ provider: options.provider,
11100
+ prompt: options.prompt,
11101
+ all: options.all,
11102
+ json: options.json
11103
+ });
11104
+ if (dispatch.outcome === "handled") return;
11105
+ const prompt = dispatch.prompt;
10943
11106
  await validateVideoOptions(options);
10944
11107
  const result = await generateWebVideo({
10945
11108
  prompt,
@@ -10976,20 +11139,22 @@ Models:
10976
11139
  );
10977
11140
  }
10978
11141
 
10979
- // src/commands/zero/built-in/generate/video.ts
11142
+ // src/commands/zero/generate/video.ts
10980
11143
  var videoCommand = createVideoGenerateCommand({
10981
11144
  name: "video",
10982
- usageCommand: "zero built-in generate video",
10983
- examples: ` Generate video: zero built-in generate video --prompt "A tracking shot through a neon market"
10984
- Pipe prompt: cat prompt.txt | zero built-in generate video
10985
- Use Dreamina 2.0: zero built-in generate video --model dreamina-seedance-2.0 --prompt "A cinematic product reveal" --duration 6s --resolution 1080p
10986
- Use Seedance 1.5 Pro: zero built-in generate video --model seedance-1.5-pro --prompt "A multi-shot chase scene" --duration 8s --resolution 720p
10987
- Add a first frame: zero built-in generate video --first-frame-image-url https://example.com/frame.png --prompt "Animate this frame"`
11145
+ generationType: "video",
11146
+ usageCommand: "zero generate video",
11147
+ examples: ` Generate video: zero generate video --prompt "A tracking shot through a neon market"
11148
+ Pipe prompt: cat prompt.txt | zero generate video
11149
+ Use Dreamina 2.0: zero generate video --model dreamina-seedance-2.0 --prompt "A cinematic product reveal" --duration 6s --resolution 1080p
11150
+ Use Seedance 1.5 Pro: zero generate video --model seedance-1.5-pro --prompt "A multi-shot chase scene" --duration 8s --resolution 720p
11151
+ Add a first frame: zero generate video --first-frame-image-url https://example.com/frame.png --prompt "Animate this frame"
11152
+ List providers: zero generate video
11153
+ Use HeyGen: zero generate video --provider heygen`
10988
11154
  });
10989
11155
 
10990
- // src/commands/zero/built-in/generate/website.ts
11156
+ // src/commands/zero/generate/website.ts
10991
11157
  init_esm_shims();
10992
- import { readFileSync as readFileSync17 } from "fs";
10993
11158
  var WEBSITE_TEMPLATES = ["auto", "launch", "profile"];
10994
11159
  var WEBSITE_MAX_IMAGES = 3;
10995
11160
  function parseTemplate(value) {
@@ -11012,23 +11177,13 @@ function parseImageCount2(value) {
11012
11177
  }
11013
11178
  return imageCount;
11014
11179
  }
11015
- function readPrompt5(options) {
11016
- if (options.prompt?.trim()) {
11017
- return options.prompt.trim();
11018
- }
11019
- if (process.stdin.isTTY === false) {
11020
- const prompt = readFileSync17("/dev/stdin", "utf8").trim();
11021
- if (prompt.length > 0) {
11022
- return prompt;
11023
- }
11024
- }
11025
- throw new Error("--prompt is required", {
11026
- cause: new Error(
11027
- 'Usage: zero built-in generate website --prompt "A launch site for a developer tool"'
11028
- )
11029
- });
11030
- }
11031
11180
  var websiteCommand = new Command().name("website").description("Prepare website authoring instructions from a prompt").option("--prompt <text>", "Website prompt; can also be piped via stdin").option(
11181
+ "--provider <name>",
11182
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
11183
+ ).option(
11184
+ "--all",
11185
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
11186
+ ).option(
11032
11187
  "--template <template>",
11033
11188
  "Template: auto, launch, or profile",
11034
11189
  parseTemplate,
@@ -11045,20 +11200,30 @@ var websiteCommand = new Command().name("website").description("Prepare website
11045
11200
  "after",
11046
11201
  `
11047
11202
  Examples:
11048
- Generate site: zero built-in generate website --prompt "A launch site for a developer observability tool"
11049
- Pick template: zero built-in generate website --template profile --images 2 --image-model gpt-image-1.5 --prompt "Portfolio for a robotics photographer"
11050
- Stable hosted slug: zero built-in generate website --site api-migration-demo --prompt "An internal migration microsite"
11051
- Pipe prompt: cat brief.txt | zero built-in generate website
11203
+ Generate site: zero generate website --prompt "A launch site for a developer observability tool"
11204
+ Pick template: zero generate website --template profile --images 2 --image-model gpt-image-1.5 --prompt "Portfolio for a robotics photographer"
11205
+ Stable hosted slug: zero generate website --site api-migration-demo --prompt "An internal migration microsite"
11206
+ Pipe prompt: cat brief.txt | zero generate website
11207
+ List providers: zero generate website
11052
11208
 
11053
11209
  Output:
11054
11210
  Prints an Open Design registry-selection packet for the current agent.
11211
+ With no --prompt and no piped input, prints the provider menu instead.
11055
11212
 
11056
11213
  Notes:
11057
11214
  - Authenticates via ZERO_TOKEN
11058
11215
  - The agent authors the HTML artifact and hosts it with zero host`
11059
11216
  ).action(
11060
11217
  withErrorHandler(async (options) => {
11061
- const prompt = readPrompt5(options);
11218
+ const dispatch = await dispatchGenerate({
11219
+ generationType: "website",
11220
+ provider: options.provider,
11221
+ prompt: options.prompt,
11222
+ all: options.all,
11223
+ json: options.json
11224
+ });
11225
+ if (dispatch.outcome === "handled") return;
11226
+ const prompt = dispatch.prompt;
11062
11227
  const packet = createHtmlArtifactAuthoringPacket({
11063
11228
  kind: "website",
11064
11229
  prompt,
@@ -11086,35 +11251,27 @@ Notes:
11086
11251
  })
11087
11252
  );
11088
11253
 
11089
- // src/commands/zero/built-in/generate/voice.ts
11254
+ // src/commands/zero/generate/voice.ts
11090
11255
  init_esm_shims();
11091
11256
 
11092
11257
  // src/commands/zero/shared/voice-generate.ts
11093
11258
  init_esm_shims();
11094
- import { readFileSync as readFileSync18 } from "fs";
11095
- function readText(options, usageCommand) {
11096
- if (options.text?.trim()) {
11097
- return options.text.trim();
11098
- }
11099
- if (process.stdin.isTTY === false) {
11100
- const text = readFileSync18("/dev/stdin", "utf8").trim();
11101
- if (text.length > 0) {
11102
- return text;
11103
- }
11104
- }
11105
- throw new Error("--text is required", {
11106
- cause: new Error(`Usage: ${usageCommand} --text "Hello"`)
11107
- });
11108
- }
11109
11259
  function createVoiceGenerateCommand(config) {
11110
- return new Command().name(config.name).description("Generate a billed speech audio file from text").option("--text <text>", "Text to speak; can also be piped via stdin").option("--voice <voice>", "OpenAI voice to use", "marin").option("--instructions <text>", "Voice style instructions").option("--json", "Print metadata as JSON").addHelpText(
11260
+ return new Command().name(config.name).description("Generate a billed speech audio file from text").option("--prompt <text>", "Text to speak; can also be piped via stdin").addOption(new Option("--text <text>", "Alias for --prompt").hideHelp()).option(
11261
+ "--provider <name>",
11262
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name (heygen, elevenlabs, ...) to get its skill-invocation guidance"
11263
+ ).option(
11264
+ "--all",
11265
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
11266
+ ).option("--voice <voice>", "OpenAI voice to use", "marin").option("--instructions <text>", "Voice style instructions").option("--json", "Print metadata as JSON").addHelpText(
11111
11267
  "after",
11112
11268
  `
11113
11269
  Examples:
11114
11270
  ${config.examples}
11115
11271
 
11116
11272
  Output:
11117
- Prints the generated /f/ audio file URL and metadata
11273
+ Prints the generated /f/ audio file URL and metadata. With no --prompt
11274
+ and no piped input, prints the provider menu instead.
11118
11275
 
11119
11276
  Notes:
11120
11277
  - Authenticates via ZERO_TOKEN (requires file:write capability)
@@ -11122,7 +11279,15 @@ Notes:
11122
11279
  - Uses gpt-4o-mini-tts with WAV output`
11123
11280
  ).action(
11124
11281
  withErrorHandler(async (options) => {
11125
- const text = readText(options, config.usageCommand);
11282
+ const dispatch = await dispatchGenerate({
11283
+ generationType: config.generationType,
11284
+ provider: options.provider,
11285
+ prompt: options.prompt ?? options.text,
11286
+ all: options.all,
11287
+ json: options.json
11288
+ });
11289
+ if (dispatch.outcome === "handled") return;
11290
+ const text = dispatch.prompt;
11126
11291
  const result = await generateWebVoice({
11127
11292
  text,
11128
11293
  voice: options.voice,
@@ -11142,53 +11307,108 @@ Notes:
11142
11307
  );
11143
11308
  }
11144
11309
 
11145
- // src/commands/zero/built-in/generate/voice.ts
11310
+ // src/commands/zero/generate/voice.ts
11146
11311
  var voiceCommand = createVoiceGenerateCommand({
11147
11312
  name: "voice",
11148
- usageCommand: "zero built-in generate voice",
11149
- examples: ` Generate speech: zero built-in generate voice --text "Hello from vm0"
11150
- Pipe text: cat script.txt | zero built-in generate voice
11151
- Pick a voice: zero built-in generate voice --text "Ship it" --voice cedar`
11313
+ generationType: "voice",
11314
+ usageCommand: "zero generate voice",
11315
+ examples: ` Generate speech: zero generate voice --prompt "Hello from vm0"
11316
+ Pipe prompt: cat script.txt | zero generate voice
11317
+ Pick a voice: zero generate voice --prompt "Ship it" --voice cedar
11318
+ List providers: zero generate voice
11319
+ Use ElevenLabs: zero generate voice --provider elevenlabs`
11152
11320
  });
11153
11321
 
11154
- // src/commands/zero/built-in/generate/index.ts
11322
+ // src/commands/zero/generate/lister-only.ts
11323
+ init_esm_shims();
11324
+ function createListerOnlyCommand(config) {
11325
+ return new Command().name(config.name).description(config.description).option(
11326
+ "--provider <name>",
11327
+ "Connector name; prints that connector's skill-invocation guidance"
11328
+ ).option("--all", "Include unavailable or not-yet-authorized connectors").option("--json", "Print the provider list as JSON").addHelpText(
11329
+ "after",
11330
+ `
11331
+ Notes:
11332
+ - vm0 does not provide a built-in ${config.generationType} pipeline.
11333
+ - Use --provider <connector-name> to get skill-invocation guidance for a
11334
+ specific connector, or run with no flags to see every available provider.`
11335
+ ).action(
11336
+ withErrorHandler(async (options) => {
11337
+ const provider = options.provider?.trim();
11338
+ if (provider && provider !== "built-in") {
11339
+ printConnectorGuidance(config.generationType, provider);
11340
+ return;
11341
+ }
11342
+ if (provider === "built-in") {
11343
+ console.log(
11344
+ `vm0 has no built-in ${config.generationType} generation pipeline.`
11345
+ );
11346
+ console.log("");
11347
+ console.log(
11348
+ `Run "zero generate ${config.generationType}" to see every connector-backed provider.`
11349
+ );
11350
+ return;
11351
+ }
11352
+ await runLister(config.generationType, {
11353
+ all: options.all,
11354
+ json: options.json
11355
+ });
11356
+ })
11357
+ );
11358
+ }
11359
+
11360
+ // src/commands/zero/generate/index.ts
11361
+ var audioCommand = createListerOnlyCommand({
11362
+ name: "audio",
11363
+ generationType: "audio",
11364
+ description: "List connectors that provide audio generation (alias of voice for non-speech audio)"
11365
+ });
11366
+ var textCommand = createListerOnlyCommand({
11367
+ name: "text",
11368
+ generationType: "text",
11369
+ description: "List connectors that provide text generation"
11370
+ });
11371
+ var codeCommand = createListerOnlyCommand({
11372
+ name: "code",
11373
+ generationType: "code",
11374
+ description: "List connectors that provide code generation"
11375
+ });
11376
+ var documentCommand = createListerOnlyCommand({
11377
+ name: "document",
11378
+ generationType: "document",
11379
+ description: "List connectors that provide document generation"
11380
+ });
11155
11381
  function buildGenerateHelpText() {
11156
11382
  const examples = [
11157
- ' Generate image: zero built-in generate image --prompt "A watercolor fox"',
11158
- ' Generate deck: zero built-in generate presentation --prompt "A product roadmap"',
11159
- ' Generate report: zero built-in generate report --prompt "A Q2 usage report"',
11160
- ' Generate docs: zero built-in generate docs-design --prompt "A setup guide"',
11161
- ' Generate video: zero built-in generate video --prompt "A cinematic city shot"',
11383
+ ' Generate image: zero generate image --prompt "A watercolor fox"',
11384
+ ' Generate deck: zero generate presentation --prompt "A product roadmap"',
11385
+ ' Generate report: zero generate report --prompt "A Q2 usage report"',
11386
+ ' Generate docs: zero generate docs-design --prompt "A setup guide"',
11387
+ ' Generate video: zero generate video --prompt "A cinematic city shot"',
11162
11388
  ...zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */) ? [
11163
- ' Generate site: zero built-in generate website --prompt "A launch site"'
11389
+ ' Generate site: zero generate website --prompt "A launch site"'
11164
11390
  ] : [],
11165
- ' Generate speech: zero built-in generate voice --text "Hello"'
11391
+ ' Generate speech: zero generate voice --prompt "Hello"',
11392
+ "",
11393
+ " List image providers: zero generate image",
11394
+ " Use a connector: zero generate video --provider heygen",
11395
+ " Force built-in: zero generate image --provider built-in --model gpt-image-1.5 --prompt ..."
11166
11396
  ];
11167
11397
  return `
11168
11398
  Examples:
11169
- ${examples.join("\n")}`;
11399
+ ${examples.join("\n")}
11400
+
11401
+ Notes:
11402
+ - Run "zero generate <type>" with no --prompt to list every provider available for that type.
11403
+ - --provider built-in (default when --prompt is provided) runs the vm0-hosted pipeline.
11404
+ - --provider <connector-name> prints how to invoke that connector's skill instead.`;
11170
11405
  }
11171
- var generateCommand2 = new Command().name("generate").description("Generate assets with built-in vm0 services").addCommand(imageCommand).addCommand(presentationCommand).addCommand(reportCommand).addCommand(docsDesignCommand).addCommand(posterCommand).addCommand(dashboardDesignCommand).addCommand(mobileAppDesignCommand).addCommand(videoCommand).addCommand(
11406
+ var generateCommand = new Command().name("generate").description(
11407
+ "Generate assets via vm0's built-in pipelines or get connector skill-invocation guidance"
11408
+ ).addCommand(imageCommand).addCommand(presentationCommand).addCommand(reportCommand).addCommand(docsDesignCommand).addCommand(posterCommand).addCommand(dashboardDesignCommand).addCommand(mobileAppDesignCommand).addCommand(videoCommand).addCommand(
11172
11409
  websiteCommand,
11173
11410
  zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */) ? {} : { hidden: true }
11174
- ).addCommand(voiceCommand).addHelpText("after", buildGenerateHelpText);
11175
-
11176
- // src/commands/zero/built-in/index.ts
11177
- function buildBuiltInHelpText() {
11178
- const examples = [
11179
- ' Generate image: zero built-in generate image --prompt "A watercolor fox"',
11180
- ' Generate deck: zero built-in generate presentation --prompt "A product roadmap"',
11181
- ' Generate video: zero built-in generate video --prompt "A cinematic city shot"',
11182
- ...zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */) ? [
11183
- ' Generate site: zero built-in generate website --prompt "A launch site"'
11184
- ] : [],
11185
- ' Generate speech: zero built-in generate voice --text "Hello"'
11186
- ];
11187
- return `
11188
- Examples:
11189
- ${examples.join("\n")}`;
11190
- }
11191
- var zeroBuiltInCommand = new Command().name("built-in").description("Use built-in vm0 services").addCommand(generateCommand2).addHelpText("after", buildBuiltInHelpText);
11411
+ ).addCommand(voiceCommand).addCommand(audioCommand).addCommand(textCommand).addCommand(codeCommand).addCommand(documentCommand).addHelpText("after", buildGenerateHelpText);
11192
11412
 
11193
11413
  // src/commands/zero/web/index.ts
11194
11414
  init_esm_shims();
@@ -12247,7 +12467,7 @@ var COMMAND_CAPABILITY_MAP = {
12247
12467
  whoami: null,
12248
12468
  "developer-support": null,
12249
12469
  "computer-use": "computer-use:write",
12250
- "built-in": "file:write",
12470
+ generate: "file:write",
12251
12471
  web: null,
12252
12472
  host: "host:write",
12253
12473
  maps: "maps:read",
@@ -12278,7 +12498,7 @@ var DEFAULT_COMMANDS = [
12278
12498
  zeroSkillCommand,
12279
12499
  zeroDeveloperSupportCommand,
12280
12500
  zeroComputerUseCommand,
12281
- zeroBuiltInCommand,
12501
+ generateCommand,
12282
12502
  zeroWebCommand,
12283
12503
  zeroHostCommand,
12284
12504
  zeroMapsCommand,
@@ -12287,7 +12507,7 @@ var DEFAULT_COMMANDS = [
12287
12507
  ];
12288
12508
  function shouldHideCommand(name, payload) {
12289
12509
  if (!payload) return false;
12290
- if (name === "built-in") {
12510
+ if (name === "generate") {
12291
12511
  return !payload.capabilities.includes("file:write") && !zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */, payload);
12292
12512
  }
12293
12513
  const requiredCap = COMMAND_CAPABILITY_MAP[name];
@@ -12320,9 +12540,10 @@ function buildZeroHelpText(payload = decodeZeroTokenPayload()) {
12320
12540
  " Model routing? zero model-provider ls",
12321
12541
  " Update yourself? zero agent --help",
12322
12542
  " Manage custom skills? zero skill --help",
12323
- " Generate image? zero built-in generate image --help",
12324
- ...zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */, payload) ? [" Generate website? zero built-in generate website --help"] : [],
12325
- " Generate voice? zero built-in generate voice --help",
12543
+ " List generators? zero generate --help",
12544
+ ' Generate image? zero generate image --prompt "..."',
12545
+ ...zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */, payload) ? [' Generate website? zero generate website --prompt "..."'] : [],
12546
+ ' Generate voice? zero generate voice --prompt "..."',
12326
12547
  ...shouldHideCommand("local-browser", payload) ? [] : [" Read browser context? zero local-browser --help"],
12327
12548
  ...shouldHideCommand("host", payload) ? [] : [" Host a static site? zero host ./dist --site my-site --spa"],
12328
12549
  ...shouldHideCommand("maps", payload) ? [] : [
@@ -12345,7 +12566,7 @@ function registerZeroCommands(prog, commands) {
12345
12566
  var program = new Command();
12346
12567
  program.name("zero").description(
12347
12568
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
12348
- ).version("9.168.3").addHelpText("after", () => {
12569
+ ).version("9.169.1").addHelpText("after", () => {
12349
12570
  return buildZeroHelpText();
12350
12571
  });
12351
12572
  if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {