@vm0/cli 9.168.3 → 9.169.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,
@@ -152,7 +153,7 @@ import {
152
153
  zeroAgentCustomSkillNameSchema,
153
154
  zeroLocalAgentCommand,
154
155
  zeroTokenAllowsFeatureSwitch
155
- } from "./chunk-M3MX2TJ6.js";
156
+ } from "./chunk-5KJLUOMN.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
 
@@ -2186,7 +2252,7 @@ var statusCommand2 = new Command().name("status").description("Show detailed sta
2186
2252
  );
2187
2253
 
2188
2254
  // 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);
2255
+ var zeroConnectorCommand = new Command().name("connector").description("Check third-party service connections (GitHub, Slack, etc.)").addCommand(connectCommand).addCommand(listCommand6).addCommand(searchCommand).addCommand(statusCommand2);
2190
2256
 
2191
2257
  // src/commands/zero/credit.ts
2192
2258
  init_esm_shims();
@@ -2683,740 +2749,171 @@ How connectors work:
2683
2749
  })
2684
2750
  );
2685
2751
 
2686
- // src/commands/zero/doctor/generate.ts
2752
+ // src/commands/zero/doctor/permission-deny.ts
2687
2753
  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"
2754
+ var permissionDenyCommand = new Command().name("permission-deny").description(
2755
+ "Diagnose a permission denial and find the permission that covers it"
2756
+ ).argument("<connector-ref>", "The connector type (e.g. github)").addOption(
2757
+ new Option(
2758
+ "--method <method>",
2759
+ "The denied HTTP method"
2760
+ ).makeOptionMandatory()
2761
+ ).addOption(
2762
+ new Option("--path <path>", "The denied path").makeOptionMandatory()
2763
+ ).addHelpText(
2764
+ "after",
2765
+ `
2766
+ Examples:
2767
+ zero doctor permission-deny github --method GET --path /repos/owner/repo/pulls
2768
+ zero doctor permission-deny slack --method POST --path /chat.postMessage
2769
+
2770
+ Notes:
2771
+ - Identifies which named permission covers a denied request
2772
+ - Use permission-change to request or enable the permission`
2773
+ ).action(
2774
+ withErrorHandler(
2775
+ async (connectorRef, opts) => {
2776
+ if (!isFirewallConnectorType(connectorRef)) {
2777
+ throw new Error(`Unknown connector type: ${connectorRef}`);
2778
+ }
2779
+ const { label } = CONNECTOR_TYPES[connectorRef];
2780
+ const config = getConnectorFirewall(connectorRef);
2781
+ const permissions = findMatchingPermissions(
2782
+ opts.method,
2783
+ opts.path,
2784
+ config
2785
+ );
2786
+ console.log(
2787
+ `The ${label} permission filtered ${opts.method} ${opts.path}.`
2788
+ );
2789
+ if (permissions.length === 0) {
2790
+ console.log("No named permission was found covering this request.");
2791
+ return;
2792
+ }
2793
+ const ruleCount = /* @__PURE__ */ new Map();
2794
+ for (const api of config.apis) {
2795
+ if (!api.permissions) continue;
2796
+ for (const perm of api.permissions) {
2797
+ ruleCount.set(
2798
+ perm.name,
2799
+ (ruleCount.get(perm.name) ?? 0) + perm.rules.length
2800
+ );
2801
+ }
2802
+ }
2803
+ const permission = permissions.reduce((narrowest, current) => {
2804
+ return (ruleCount.get(current) ?? Infinity) < (ruleCount.get(narrowest) ?? Infinity) ? current : narrowest;
2805
+ });
2806
+ console.log(`This is covered by the "${permission}" permission.`);
2807
+ console.log(
2808
+ `To request this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --reason "why this is needed"`
2809
+ );
2745
2810
  }
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"
2811
+ )
2812
+ );
2813
+
2814
+ // src/commands/zero/doctor/permission-change.ts
2815
+ init_esm_shims();
2816
+
2817
+ // src/commands/zero/doctor/resolve-role.ts
2818
+ init_esm_shims();
2819
+ async function resolveUserId() {
2820
+ const zeroPayload = decodeZeroTokenPayload();
2821
+ if (zeroPayload?.userId) return zeroPayload.userId;
2822
+ const token = await getToken();
2823
+ const cliPayload = decodeCliTokenPayload(token);
2824
+ return cliPayload?.userId;
2825
+ }
2826
+ async function resolveAgentRole(agentId) {
2827
+ try {
2828
+ const org = await getZeroOrg();
2829
+ if (org.role === "admin") return "admin";
2830
+ if (org.role === "member") {
2831
+ const userId = await resolveUserId();
2832
+ if (userId) {
2833
+ const agent = await getZeroAgent(agentId);
2834
+ if (agent.ownerId === userId) return "owner";
2835
+ }
2836
+ return "member";
2753
2837
  }
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"
2838
+ return "unknown";
2839
+ } catch (error) {
2840
+ console.debug("resolveAgentRole failed, falling back to unknown:", error);
2841
+ return "unknown";
2842
+ }
2843
+ }
2844
+
2845
+ // src/commands/zero/doctor/permission-change.ts
2846
+ function findPermissionInConfig(ref, permissionName) {
2847
+ if (!isFirewallConnectorType(ref)) return false;
2848
+ const config = getConnectorFirewall(ref);
2849
+ for (const api of config.apis) {
2850
+ if (!api.permissions) continue;
2851
+ for (const p of api.permissions) {
2852
+ if (p.name === permissionName) return true;
2761
2853
  }
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
- );
2854
+ }
2855
+ return false;
2856
+ }
2857
+ var REASON_MAX_LENGTH = 500;
2858
+ async function outputPermissionChangeMessage(connectorRef, permission, action, reason) {
2859
+ const { label } = CONNECTOR_TYPES[connectorRef];
2860
+ const platformOrigin = await getPlatformOrigin();
2861
+ const agentId = process.env.ZERO_AGENT_ID;
2862
+ const role = agentId ? await resolveAgentRole(agentId) : "unknown";
2863
+ const urlParams = new URLSearchParams({
2864
+ ref: connectorRef,
2865
+ permission,
2866
+ action: action === "enable" ? "allow" : "deny"
2867
+ });
2868
+ if (role === "member" && reason) {
2869
+ const truncated = reason.length > REASON_MAX_LENGTH ? reason.slice(0, REASON_MAX_LENGTH) : reason;
2870
+ urlParams.set("reason", truncated);
2871
+ }
2872
+ const pagePath = agentId ? `/agents/${agentId}/permissions` : "/agents";
2873
+ const url = `${platformOrigin}${pagePath}?${urlParams.toString()}`;
2874
+ if (connectorRef === "slack" && permission === "chat:write" && action === "enable") {
2875
+ console.log("");
2876
+ console.log(
2877
+ "IMPORTANT: Granting chat:write allows sending messages AS THE USER's identity, not as a bot."
2878
+ );
2879
+ console.log(
2880
+ "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."
2881
+ );
2882
+ console.log(
2883
+ "Only request user approval below if acting as the user is specifically required."
2884
+ );
2885
+ console.log("");
2886
+ }
2887
+ if (connectorRef === "gmail" && permission === "gmail.send" && action === "enable") {
2888
+ console.log("");
2889
+ console.log(
2890
+ "IMPORTANT: Granting gmail.send allows the agent to send emails directly as the user."
2891
+ );
2892
+ console.log(
2893
+ "Consider keeping gmail.send disabled and using gmail.compose instead \u2014 the agent can create drafts for the user to review and send manually."
2894
+ );
2895
+ console.log(
2896
+ "Only request user approval below if direct sending is specifically required."
2897
+ );
2898
+ console.log("");
2899
+ }
2900
+ if (role === "admin" || role === "owner") {
2901
+ console.log(
2902
+ `You can ${action} the "${permission}" permission directly: [Manage ${label} permissions](${url})`
2903
+ );
2904
+ } else if (role === "member") {
2905
+ if (!reason) {
2906
+ console.log(
2907
+ `IMPORTANT: Re-run with \`--reason "one sentence why this is needed"\` so the admin can review your request faster.`
2908
+ );
2909
+ } else if (action === "enable") {
2910
+ console.log(
2911
+ `Permission changes require admin approval. Request access at: [Request ${label} access](${url})`
2912
+ );
2913
+ } else {
2914
+ console.log(
2915
+ `Permission changes require admin approval. Contact an org admin to disable this permission: [View ${label} permissions](${url})`
2916
+ );
3420
2917
  }
3421
2918
  } else {
3422
2919
  console.log(
@@ -3537,14 +3034,12 @@ var creditCommand = new Command().name("credit").description("Diagnose current o
3537
3034
  );
3538
3035
 
3539
3036
  // 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(
3037
+ var zeroDoctorCommand = new Command().name("doctor").description("Diagnose runtime issues (connector health, permission denials)").addCommand(checkConnectorCommand).addCommand(creditCommand).addCommand(permissionDenyCommand).addCommand(permissionChangeCommand).addHelpText(
3541
3038
  "after",
3542
3039
  `
3543
3040
  Examples:
3544
3041
  Check a connector? zero doctor check-connector --env-name GITHUB_TOKEN
3545
3042
  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
3043
  Check credits? zero doctor credit
3549
3044
  Check with permission? zero doctor check-connector --env-name SLACK_TOKEN --check-permission chat:write
3550
3045
  Permission denied? zero doctor permission-deny github --method GET --path /repos/owner/repo
@@ -3553,6 +3048,7 @@ Examples:
3553
3048
  Notes:
3554
3049
  - 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
3050
  - Use this when your task fails due to a missing environment variable or permission denial
3051
+ - Use zero generate <type> (no --prompt) to see every provider available for a given generation type
3556
3052
  - The doctor will identify the issue and give the user a link to resolve it`
3557
3053
  );
3558
3054
 
@@ -7243,18 +6739,14 @@ var openAppCommand = appOption(
7243
6739
  );
7244
6740
  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
6741
 
7246
- // src/commands/zero/built-in/index.ts
7247
- init_esm_shims();
7248
-
7249
- // src/commands/zero/built-in/generate/index.ts
6742
+ // src/commands/zero/generate/index.ts
7250
6743
  init_esm_shims();
7251
6744
 
7252
- // src/commands/zero/built-in/generate/image.ts
6745
+ // src/commands/zero/generate/image.ts
7253
6746
  init_esm_shims();
7254
6747
 
7255
6748
  // src/commands/zero/shared/image-generate.ts
7256
6749
  init_esm_shims();
7257
- import { readFileSync as readFileSync13 } from "fs";
7258
6750
 
7259
6751
  // src/commands/zero/shared/image-style-authoring.ts
7260
6752
  init_esm_shims();
@@ -9696,266 +9188,924 @@ var OPEN_DESIGN_REGISTRY = [
9696
9188
  source: { path: "illustration-template/painterly-botanical" }
9697
9189
  },
9698
9190
  {
9699
- id: "vm0:image-style:iso-scene",
9191
+ id: "vm0:image-style:iso-scene",
9192
+ kind: "image-style",
9193
+ name: "Isometric Editorial Scene",
9194
+ 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.",
9195
+ 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.',
9196
+ source: { path: "illustration-template/iso-scene" }
9197
+ },
9198
+ {
9199
+ id: "vm0:image-style:inkdab",
9200
+ kind: "image-style",
9201
+ name: "Inkdab Illustration",
9202
+ 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.",
9203
+ 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.',
9204
+ source: { path: "illustration-template/inkdab" }
9205
+ },
9206
+ {
9207
+ id: "vm0:image-style:riso-relic",
9208
+ kind: "image-style",
9209
+ name: "Riso Relic",
9210
+ 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.',
9211
+ 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.',
9212
+ source: { path: "illustration-template/riso-relic" }
9213
+ },
9214
+ {
9215
+ id: "vm0:image-style:inkstomp",
9216
+ kind: "image-style",
9217
+ name: "Inkstomp",
9218
+ 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.",
9219
+ 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.',
9220
+ source: { path: "illustration-template/inkstomp" }
9221
+ },
9222
+ {
9223
+ id: "vm0:image-style:folk-muse",
9224
+ kind: "image-style",
9225
+ name: "Folk Muse",
9226
+ 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.",
9227
+ 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.',
9228
+ source: { path: "illustration-template/folk-muse" }
9229
+ },
9230
+ {
9231
+ id: "vm0:image-style:sunlit-gouache",
9232
+ kind: "image-style",
9233
+ name: "Sunlit Gouache",
9234
+ 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.",
9235
+ 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.',
9236
+ source: { path: "illustration-template/sunlit-gouache" }
9237
+ },
9238
+ {
9239
+ id: "vm0:image-style:mosaic-still-life",
9240
+ kind: "image-style",
9241
+ name: "Mosaic Still Life",
9242
+ 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.",
9243
+ 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.',
9244
+ source: { path: "illustration-template/mosaic-still-life" }
9245
+ },
9246
+ {
9247
+ id: "vm0:image-style:ink-mascot",
9248
+ kind: "image-style",
9249
+ name: "Ink Mascot",
9250
+ 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.",
9251
+ 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.',
9252
+ source: { path: "illustration-template/ink-mascot" }
9253
+ },
9254
+ {
9255
+ id: "vm0:image-style:sticker-sheet",
9256
+ kind: "image-style",
9257
+ name: "Sticker Sheet",
9258
+ 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.",
9259
+ 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.',
9260
+ source: { path: "illustration-template/sticker-sheet" }
9261
+ },
9262
+ {
9263
+ id: "vm0:image-style:flat-poster",
9700
9264
  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" }
9265
+ name: "Flat Poster",
9266
+ 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.",
9267
+ 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.',
9268
+ source: { path: "illustration-template/flat-poster" }
9705
9269
  },
9706
9270
  {
9707
- id: "vm0:image-style:inkdab",
9271
+ id: "vm0:image-style:mellow-pop",
9708
9272
  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" }
9273
+ name: "Mellow Pop",
9274
+ 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.",
9275
+ 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.',
9276
+ source: { path: "illustration-template/mellow-pop" }
9277
+ }
9278
+ ];
9279
+ function filterByKind(kind) {
9280
+ return OPEN_DESIGN_REGISTRY.filter((entry) => {
9281
+ return entry.kind === kind;
9282
+ });
9283
+ }
9284
+ function listImageStyles() {
9285
+ return filterByKind("image-style");
9286
+ }
9287
+ function findImageStyle(id) {
9288
+ return listImageStyles().find((entry) => {
9289
+ return entry.id === id;
9290
+ });
9291
+ }
9292
+ function toOpenDesignTarget(value) {
9293
+ if (value === "dashboard") {
9294
+ return "dashboard-design";
9295
+ }
9296
+ if (value === "docs") {
9297
+ return "docs-design";
9298
+ }
9299
+ if (value === "mobile-app") {
9300
+ return "mobile-app-design";
9301
+ }
9302
+ return value;
9303
+ }
9304
+ function selectOpenDesignCandidates() {
9305
+ return {
9306
+ registryVersion: OPEN_DESIGN_REGISTRY_VERSION,
9307
+ source: {
9308
+ repo: OPEN_DESIGN_REPO,
9309
+ commit: OPEN_DESIGN_COMMIT
9310
+ },
9311
+ sources: [
9312
+ {
9313
+ repo: OPEN_DESIGN_REPO,
9314
+ commit: OPEN_DESIGN_COMMIT
9315
+ },
9316
+ {
9317
+ repo: VM0_SKILLS_REPO,
9318
+ commit: VM0_SKILLS_REF
9319
+ }
9320
+ ],
9321
+ candidates: {
9322
+ skills: filterByKind("skill"),
9323
+ templates: filterByKind("template"),
9324
+ designSystems: filterByKind("design-system"),
9325
+ imageStyles: filterByKind("image-style"),
9326
+ audioStyles: filterByKind("audio-style"),
9327
+ videoTemplates: filterByKind("video-template"),
9328
+ bundleTemplates: filterByKind("bundle-template")
9329
+ }
9330
+ };
9331
+ }
9332
+
9333
+ // src/commands/zero/shared/image-style-authoring.ts
9334
+ var outputDir = "./opendesign/images";
9335
+ var artifactRules = [
9336
+ "Resolve the selected style source before generating the image.",
9337
+ "Use the style skill's referenced assets and generation path when it provides one.",
9338
+ "Produce a single final image file and keep any temporary metadata under the output directory."
9339
+ ];
9340
+ function createStyledImageAuthoringPacket(options) {
9341
+ const baseSlice = selectOpenDesignCandidates();
9342
+ const candidateSlice = {
9343
+ ...baseSlice,
9344
+ candidates: {
9345
+ ...baseSlice.candidates,
9346
+ imageStyles: [options.style]
9347
+ }
9348
+ };
9349
+ const selectionSchema = {
9350
+ imageStyle: "string",
9351
+ skills: "string[]",
9352
+ rationale: "string"
9353
+ };
9354
+ const artifact = {
9355
+ outputMode: "primary-image",
9356
+ primaryArtifact: {
9357
+ kind: "image",
9358
+ path: `${outputDir}/`
9359
+ },
9360
+ supportingAssets: [
9361
+ {
9362
+ kind: "metadata",
9363
+ path: `${outputDir}/metadata.json`,
9364
+ optional: true
9365
+ }
9366
+ ],
9367
+ previewKind: "image",
9368
+ outputDir
9369
+ };
9370
+ const instructions = [
9371
+ `# Zero generate image --style ${options.style.id}`,
9372
+ "",
9373
+ "This is a federated generation resource-selection packet for the current agent.",
9374
+ "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.",
9375
+ "",
9376
+ "## User Prompt",
9377
+ options.prompt,
9378
+ "",
9379
+ "## Selected Image Style",
9380
+ `- \`${options.style.id}\` \u2014 ${options.style.name}`,
9381
+ "",
9382
+ "## Stage 1: Supporting Resource Selection",
9383
+ "- The image style is locked. Optionally pick supporting skills/templates from the candidate slice below.",
9384
+ "- Choose only IDs present in this packet; do not invent registry IDs.",
9385
+ "- Treat the selection JSON as internal working state, then continue to generation.",
9386
+ "",
9387
+ "## Selection Output Schema",
9388
+ "```json",
9389
+ JSON.stringify(selectionSchema, null, 2),
9390
+ "```",
9391
+ "",
9392
+ "## Candidate Registry Slice",
9393
+ `Registry: \`${candidateSlice.registryVersion}\``,
9394
+ "Sources:",
9395
+ ...candidateSlice.sources.map((src) => {
9396
+ return `- \`${src.repo}@${src.commit}\``;
9397
+ }),
9398
+ "",
9399
+ "```json",
9400
+ JSON.stringify(candidateSlice.candidates, null, 2),
9401
+ "```",
9402
+ "",
9403
+ "## Stage 2: Resolve Selected Resources",
9404
+ "- Fetch or read the selected resource source before generation.",
9405
+ "- Source refs are pinned as `repo@commit:path`; use the commit in the packet for reproducibility.",
9406
+ "- For directory refs, inspect the most relevant files such as `SKILL.md`, references, examples, and templates.",
9407
+ "- If a source file cannot be fetched, state that limitation and fall back to the registry metadata for that resource.",
9408
+ "",
9409
+ "## Stage 3: Generate Image",
9410
+ "- Generate one production-quality image using the selected style.",
9411
+ "- Follow the selected style skill's generation path when it defines one.",
9412
+ "- If the style skill delegates to a model or connector, use that flow directly instead of restating the style text manually.",
9413
+ "",
9414
+ "## Artifact Output Model",
9415
+ `- Primary artifact: \`${artifact.primaryArtifact.kind}\` under \`${artifact.primaryArtifact.path}\`.`,
9416
+ `- Output mode: \`${artifact.outputMode}\`.`,
9417
+ "- Supporting metadata may live inside the same output directory when useful.",
9418
+ "",
9419
+ "## Requested Parameters",
9420
+ ...options.details.map((detail) => {
9421
+ return `- ${detail}`;
9422
+ }),
9423
+ "",
9424
+ "## Image Authoring Rules",
9425
+ ...artifactRules.map((rule) => {
9426
+ return `- ${rule}`;
9427
+ }),
9428
+ "",
9429
+ "## Verification",
9430
+ "- Verify the final image exists and is nonblank.",
9431
+ "- Check that the selected style's required reference anchors or source assets were used when applicable.",
9432
+ "- Report the final image URL or path and the selected registry resource ID."
9433
+ ].join("\n");
9434
+ return {
9435
+ type: "open-design-resource-selection",
9436
+ kind: "image",
9437
+ prompt: options.prompt,
9438
+ registryVersion: candidateSlice.registryVersion,
9439
+ artifact,
9440
+ selection: {
9441
+ candidates: candidateSlice.candidates,
9442
+ outputSchema: selectionSchema
9443
+ },
9444
+ authoring: {
9445
+ details: options.details,
9446
+ artifactRules
9447
+ },
9448
+ outputDir,
9449
+ instructions
9450
+ };
9451
+ }
9452
+
9453
+ // src/commands/zero/generate/lib/dispatch.ts
9454
+ init_esm_shims();
9455
+ import { readFileSync as readFileSync13 } from "fs";
9456
+
9457
+ // src/commands/zero/generate/lib/connector-guidance.ts
9458
+ init_esm_shims();
9459
+ function toConnectorGenerationType(generationType) {
9460
+ switch (generationType) {
9461
+ case "voice":
9462
+ return "audio";
9463
+ case "dashboard-design":
9464
+ case "docs-design":
9465
+ case "mobile-app-design":
9466
+ case "poster":
9467
+ case "report":
9468
+ return null;
9469
+ default:
9470
+ return generationType;
9471
+ }
9472
+ }
9473
+ function isConnectorType5(value) {
9474
+ return value in CONNECTOR_TYPES;
9475
+ }
9476
+ function resolveConnector(provider, generationType) {
9477
+ if (!isConnectorType5(provider)) return null;
9478
+ const config = CONNECTOR_TYPES[provider];
9479
+ const connectorGenerationType = toConnectorGenerationType(generationType);
9480
+ const supports = connectorGenerationType !== null && getConnectorGenerationTypes(provider).some((entry) => {
9481
+ return entry === connectorGenerationType;
9482
+ });
9483
+ return {
9484
+ type: provider,
9485
+ label: config.label,
9486
+ supportsGenerationType: supports
9487
+ };
9488
+ }
9489
+ function printConnectorGuidance(generationType, provider) {
9490
+ const guidance = resolveConnector(provider, generationType);
9491
+ if (!guidance) {
9492
+ console.log(`Provider "${provider}" is not a known connector.`);
9493
+ console.log("");
9494
+ console.log(
9495
+ `Run "zero generate ${generationType}" to see every provider available for this generation type.`
9496
+ );
9497
+ return;
9498
+ }
9499
+ if (!guidance.supportsGenerationType) {
9500
+ console.log(
9501
+ `${guidance.label} (${guidance.type}) does not advertise ${generationType} generation.`
9502
+ );
9503
+ console.log("");
9504
+ console.log(
9505
+ `Run "zero generate ${generationType}" to see every provider that supports this generation type.`
9506
+ );
9507
+ return;
9508
+ }
9509
+ console.log(
9510
+ `${guidance.label} (${guidance.type}) handles ${generationType} generation through its own connector skill, not through "zero generate".`
9511
+ );
9512
+ console.log("");
9513
+ console.log(`Next steps:`);
9514
+ console.log(` - Use the "${guidance.type}" skill in this session.`);
9515
+ console.log(
9516
+ ` - Or call the connector directly via its documented endpoints.`
9517
+ );
9518
+ console.log("");
9519
+ console.log(
9520
+ `Run "zero connector status ${guidance.type}" to verify the connector is connected and authorized for the current agent.`
9521
+ );
9522
+ }
9523
+
9524
+ // src/commands/zero/generate/lib/lister.ts
9525
+ init_esm_shims();
9526
+ var BUILT_IN_GENERATION_PROVIDERS = {
9527
+ image: [
9528
+ {
9529
+ label: "Built-in fal.ai",
9530
+ model: "gpt-image-1",
9531
+ command: "zero generate image --provider built-in --model gpt-image-1 -h",
9532
+ reason: "available without connector setup"
9533
+ },
9534
+ {
9535
+ label: "Built-in fal.ai",
9536
+ model: "gpt-image-2",
9537
+ command: "zero generate image --provider built-in --model gpt-image-2 -h",
9538
+ reason: "available without connector setup"
9539
+ },
9540
+ {
9541
+ label: "Built-in fal.ai",
9542
+ model: "gpt-image-1.5",
9543
+ command: "zero generate image --provider built-in --model gpt-image-1.5 -h",
9544
+ reason: "available without connector setup"
9545
+ },
9546
+ {
9547
+ label: "Built-in fal.ai",
9548
+ model: "gpt-image-1-mini",
9549
+ command: "zero generate image --provider built-in --model gpt-image-1-mini -h",
9550
+ reason: "available without connector setup"
9551
+ },
9552
+ {
9553
+ label: "Built-in fal.ai",
9554
+ model: "fal-ai/flux-pro/v1.1",
9555
+ command: "zero generate image --provider built-in --model flux-pro-1.1 -h",
9556
+ reason: "available without connector setup"
9557
+ },
9558
+ {
9559
+ label: "Built-in fal.ai",
9560
+ model: "fal-ai/flux-pro/v1.1-ultra",
9561
+ command: "zero generate image --provider built-in --model flux-pro-1.1-ultra -h",
9562
+ reason: "available without connector setup"
9563
+ },
9564
+ {
9565
+ label: "Built-in fal.ai",
9566
+ model: "fal-ai/qwen-image",
9567
+ command: "zero generate image --provider built-in --model qwen-image -h",
9568
+ reason: "available without connector setup"
9569
+ },
9570
+ {
9571
+ label: "Built-in fal.ai",
9572
+ model: "fal-ai/bytedance/seedream/v4/text-to-image",
9573
+ command: "zero generate image --provider built-in --model seedream4 -h",
9574
+ reason: "available without connector setup"
9575
+ }
9576
+ ],
9577
+ presentation: [
9578
+ {
9579
+ label: "Built-in",
9580
+ model: "gpt-5.5",
9581
+ command: "zero generate presentation --provider built-in -h",
9582
+ reason: "available without connector setup"
9583
+ }
9584
+ ],
9585
+ report: [
9586
+ {
9587
+ label: "Built-in",
9588
+ model: "gpt-5.5",
9589
+ command: "zero generate report --provider built-in -h",
9590
+ reason: "available without connector setup"
9591
+ }
9592
+ ],
9593
+ "docs-design": [
9594
+ {
9595
+ label: "Built-in",
9596
+ model: "gpt-5.5",
9597
+ command: "zero generate docs-design --provider built-in -h",
9598
+ reason: "available without connector setup"
9599
+ }
9600
+ ],
9601
+ poster: [
9602
+ {
9603
+ label: "Built-in",
9604
+ model: "gpt-5.5",
9605
+ command: "zero generate poster --provider built-in -h",
9606
+ reason: "available without connector setup"
9607
+ }
9608
+ ],
9609
+ "dashboard-design": [
9610
+ {
9611
+ label: "Built-in",
9612
+ model: "gpt-5.5",
9613
+ command: "zero generate dashboard-design --provider built-in -h",
9614
+ reason: "available without connector setup"
9615
+ }
9616
+ ],
9617
+ "mobile-app-design": [
9618
+ {
9619
+ label: "Built-in",
9620
+ model: "gpt-5.5",
9621
+ command: "zero generate mobile-app-design --provider built-in -h",
9622
+ reason: "available without connector setup"
9623
+ }
9624
+ ],
9625
+ website: [
9626
+ {
9627
+ label: "Built-in",
9628
+ model: "gpt-5.5",
9629
+ command: "zero generate website --provider built-in -h",
9630
+ reason: "available without connector setup"
9631
+ }
9632
+ ],
9633
+ video: [
9634
+ {
9635
+ label: "Built-in",
9636
+ model: "dreamina-seedance-2-0-260128",
9637
+ command: "zero generate video --provider built-in --model dreamina-seedance-2.0 -h",
9638
+ reason: "available without connector setup"
9639
+ },
9640
+ {
9641
+ label: "Built-in",
9642
+ model: "dreamina-seedance-2-0-fast-260128",
9643
+ command: "zero generate video --provider built-in --model dreamina-seedance-2.0-fast -h",
9644
+ reason: "available without connector setup"
9645
+ },
9646
+ {
9647
+ label: "Built-in",
9648
+ model: "seedance-1-5-pro-251215",
9649
+ command: "zero generate video --provider built-in --model seedance-1.5-pro -h",
9650
+ reason: "available without connector setup"
9651
+ },
9652
+ {
9653
+ label: "Built-in fal.ai",
9654
+ model: "fal-ai/veo3.1/fast",
9655
+ command: "zero generate video --provider built-in --model veo3.1-fast -h",
9656
+ reason: "available without connector setup"
9657
+ },
9658
+ {
9659
+ label: "Built-in fal.ai",
9660
+ model: "fal-ai/kling-video/v3/4k/text-to-video",
9661
+ command: "zero generate video --provider built-in --model kling-v3-4k -h",
9662
+ reason: "available without connector setup"
9663
+ }
9664
+ ],
9665
+ voice: [
9666
+ {
9667
+ label: "Built-in",
9668
+ model: "gpt-4o-mini-tts",
9669
+ command: "zero generate voice --provider built-in -h",
9670
+ reason: "available without connector setup"
9671
+ }
9672
+ ]
9673
+ };
9674
+ var BUILT_IN_GENERATION_COMMANDS = {
9675
+ image: {
9676
+ label: "Built-in image generation",
9677
+ command: "zero generate image --provider built-in -h",
9678
+ 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
9679
  },
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" }
9680
+ video: {
9681
+ label: "Built-in video generation",
9682
+ command: "zero generate video --provider built-in -h",
9683
+ models: "dreamina-seedance-2.0-fast (default), dreamina-seedance-2.0, seedance-1.5-pro, veo3.1-fast, kling-v3-4k"
9721
9684
  },
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" }
9685
+ presentation: {
9686
+ label: "Built-in presentation generation",
9687
+ command: "zero generate presentation --provider built-in -h",
9688
+ models: "gpt-5.5"
9729
9689
  },
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" }
9690
+ report: {
9691
+ label: "Built-in report generation",
9692
+ command: "zero generate report --provider built-in -h",
9693
+ models: "gpt-5.5"
9737
9694
  },
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" }
9695
+ "docs-design": {
9696
+ label: "Built-in docs design generation",
9697
+ command: "zero generate docs-design --provider built-in -h",
9698
+ models: "gpt-5.5"
9745
9699
  },
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" }
9700
+ poster: {
9701
+ label: "Built-in poster generation",
9702
+ command: "zero generate poster --provider built-in -h",
9703
+ models: "gpt-5.5"
9753
9704
  },
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" }
9705
+ "dashboard-design": {
9706
+ label: "Built-in dashboard design generation",
9707
+ command: "zero generate dashboard-design --provider built-in -h",
9708
+ models: "gpt-5.5"
9761
9709
  },
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" }
9710
+ "mobile-app-design": {
9711
+ label: "Built-in mobile app design generation",
9712
+ command: "zero generate mobile-app-design --provider built-in -h",
9713
+ models: "gpt-5.5"
9769
9714
  },
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" }
9715
+ website: {
9716
+ label: "Built-in website generation",
9717
+ command: "zero generate website --provider built-in -h",
9718
+ models: "gpt-5.5"
9777
9719
  },
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" }
9720
+ voice: {
9721
+ label: "Built-in voice generation",
9722
+ command: "zero generate voice --provider built-in -h",
9723
+ models: "gpt-4o-mini-tts"
9724
+ }
9725
+ };
9726
+ var GENERATION_CONTEXT = {
9727
+ website: {
9728
+ lines: [
9729
+ "Standalone static website artifacts can be authored locally and published with zero host for a public URL.",
9730
+ "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.",
9731
+ "Existing web app changes should usually follow the project's own build, test, and deploy workflow."
9732
+ ]
9733
+ }
9734
+ };
9735
+ var GENERATION_TYPE_ORDER = [
9736
+ "image",
9737
+ "video",
9738
+ "audio",
9739
+ "voice",
9740
+ "text",
9741
+ "code",
9742
+ "document",
9743
+ "presentation",
9744
+ "website",
9745
+ "report",
9746
+ "docs-design",
9747
+ "poster",
9748
+ "dashboard-design",
9749
+ "mobile-app-design"
9750
+ ];
9751
+ var GENERATION_TYPE_LABELS = {
9752
+ audio: "Audio",
9753
+ code: "Code",
9754
+ "dashboard-design": "Dashboard design",
9755
+ document: "Document",
9756
+ "docs-design": "Docs design",
9757
+ image: "Image",
9758
+ "mobile-app-design": "Mobile app design",
9759
+ poster: "Poster",
9760
+ presentation: "Presentation",
9761
+ report: "Report",
9762
+ text: "Text",
9763
+ video: "Video",
9764
+ voice: "Voice",
9765
+ website: "Website"
9766
+ };
9767
+ function getConnectorGenerationType(generationType) {
9768
+ switch (generationType) {
9769
+ case "voice":
9770
+ return "audio";
9771
+ case "dashboard-design":
9772
+ case "docs-design":
9773
+ case "mobile-app-design":
9774
+ case "poster":
9775
+ case "report":
9776
+ return null;
9777
+ case "audio":
9778
+ case "code":
9779
+ case "document":
9780
+ case "image":
9781
+ case "presentation":
9782
+ case "text":
9783
+ case "video":
9784
+ case "website":
9785
+ return generationType;
9785
9786
  }
9786
- ];
9787
- function filterByKind(kind) {
9788
- return OPEN_DESIGN_REGISTRY.filter((entry) => {
9789
- return entry.kind === kind;
9787
+ }
9788
+ function getBuiltInProviders(generationType) {
9789
+ return BUILT_IN_GENERATION_PROVIDERS[generationType] ?? [];
9790
+ }
9791
+ function getBuiltInCommand(generationType) {
9792
+ return BUILT_IN_GENERATION_COMMANDS[generationType] ?? null;
9793
+ }
9794
+ function getGenerationContext(generationType) {
9795
+ return GENERATION_CONTEXT[generationType] ?? null;
9796
+ }
9797
+ function getAvailableGenerationTypes() {
9798
+ const available = /* @__PURE__ */ new Set();
9799
+ for (const type of CONNECTOR_TYPE_KEYS) {
9800
+ for (const generationType of getConnectorGenerationTypes(type)) {
9801
+ available.add(generationType);
9802
+ }
9803
+ }
9804
+ return GENERATION_TYPE_ORDER.filter((type) => {
9805
+ const connectorGenerationType = getConnectorGenerationType(type);
9806
+ return getBuiltInProviders(type).length > 0 || connectorGenerationType !== null && available.has(connectorGenerationType);
9790
9807
  });
9791
9808
  }
9792
- function listImageStyles() {
9793
- return filterByKind("image-style");
9809
+ function getGenerationConnectors(generationType) {
9810
+ return CONNECTOR_TYPE_KEYS.map((type) => {
9811
+ return [type, CONNECTOR_TYPES[type]];
9812
+ }).filter(([type]) => {
9813
+ return getConnectorGenerationTypes(type).includes(generationType);
9814
+ }).sort(([a], [b]) => {
9815
+ return a.localeCompare(b);
9816
+ });
9794
9817
  }
9795
- function findImageStyle(id) {
9796
- return listImageStyles().find((entry) => {
9797
- return entry.id === id;
9818
+ function isConnectorType6(type) {
9819
+ return type in CONNECTOR_TYPES;
9820
+ }
9821
+ async function getFeatureAvailableConnectorTypes() {
9822
+ const catalog = await searchZeroConnectors();
9823
+ return new Set(
9824
+ catalog.connectors.map((connector) => {
9825
+ return connector.id;
9826
+ }).filter(isConnectorType6)
9827
+ );
9828
+ }
9829
+ function formatAccount(connector) {
9830
+ if (connector.externalUsername) return `@${connector.externalUsername}`;
9831
+ if (connector.externalEmail) return connector.externalEmail;
9832
+ if (connector.externalId) return connector.externalId;
9833
+ return void 0;
9834
+ }
9835
+ function getAction(status, type, label, agentId, platformOrigin) {
9836
+ if (status === "needs-reconnect") {
9837
+ return {
9838
+ actionLabel: `Reconnect ${label}`,
9839
+ actionUrl: `${platformOrigin}/connectors`
9840
+ };
9841
+ }
9842
+ if (status === "not-authorized" && agentId) {
9843
+ return {
9844
+ actionLabel: `Authorize ${label}`,
9845
+ actionUrl: `${platformOrigin}/connectors/${type}/authorize?agentId=${agentId}`
9846
+ };
9847
+ }
9848
+ if (status === "not-connected") {
9849
+ if (agentId) {
9850
+ return {
9851
+ actionLabel: `Connect and authorize ${label}`,
9852
+ actionUrl: `${platformOrigin}/connectors/${type}/connect?agentId=${agentId}`
9853
+ };
9854
+ }
9855
+ return {
9856
+ actionLabel: `Connect ${label}`,
9857
+ actionUrl: `${platformOrigin}/connectors/${type}/connect`
9858
+ };
9859
+ }
9860
+ return {};
9861
+ }
9862
+ function toCandidate(params) {
9863
+ const {
9864
+ type,
9865
+ config,
9866
+ connector,
9867
+ configuredTypes,
9868
+ availableTypes,
9869
+ authorizedTypes,
9870
+ agentId,
9871
+ platformOrigin
9872
+ } = params;
9873
+ let status;
9874
+ let reason;
9875
+ if (!availableTypes.has(type)) {
9876
+ status = "not-available";
9877
+ reason = "not available for this account";
9878
+ } else if (connector?.needsReconnect) {
9879
+ status = "needs-reconnect";
9880
+ reason = "connected, reconnect required";
9881
+ } else if (!connector) {
9882
+ status = configuredTypes.has(type) ? "not-connected" : "not-available";
9883
+ reason = status === "not-connected" ? agentId ? "not connected or authorized for current agent" : "not connected" : "not available in this environment";
9884
+ } else if (authorizedTypes && !authorizedTypes.has(type)) {
9885
+ status = "not-authorized";
9886
+ reason = "connected, not authorized for current agent";
9887
+ } else {
9888
+ status = "ready";
9889
+ reason = agentId ? "connected and authorized for current agent" : "connected; agent authorization was not checked";
9890
+ }
9891
+ return {
9892
+ type,
9893
+ label: config.label,
9894
+ status,
9895
+ reason,
9896
+ account: connector ? formatAccount(connector) : void 0,
9897
+ authMethod: connector?.authMethod,
9898
+ ...getAction(status, type, config.label, agentId, platformOrigin)
9899
+ };
9900
+ }
9901
+ function pad(value, width) {
9902
+ return value.padEnd(width);
9903
+ }
9904
+ function renderRows(candidates) {
9905
+ const typeWidth = Math.max(
9906
+ 4,
9907
+ ...candidates.map((candidate) => {
9908
+ return candidate.type.length;
9909
+ })
9910
+ );
9911
+ const labelWidth = Math.max(
9912
+ 5,
9913
+ ...candidates.map((candidate) => {
9914
+ return candidate.label.length;
9915
+ })
9916
+ );
9917
+ for (const candidate of candidates) {
9918
+ const suffix = candidate.status === "ready" ? candidate.account ?? candidate.authMethod ?? "" : candidate.reason;
9919
+ console.log(
9920
+ ` ${pad(candidate.type, typeWidth)} ${pad(candidate.label, labelWidth)} ${suffix}`
9921
+ );
9922
+ }
9923
+ }
9924
+ function renderActions(candidates) {
9925
+ const actionable = candidates.filter((candidate) => {
9926
+ return candidate.actionLabel && candidate.actionUrl;
9798
9927
  });
9928
+ if (actionable.length === 0) return;
9929
+ console.log("");
9930
+ console.log("Next actions:");
9931
+ for (const candidate of actionable) {
9932
+ console.log(` [${candidate.actionLabel}](${candidate.actionUrl})`);
9933
+ }
9799
9934
  }
9800
- function toOpenDesignTarget(value) {
9801
- if (value === "dashboard") {
9802
- return "dashboard-design";
9935
+ function renderBuiltInProvider(generationType) {
9936
+ const command = getBuiltInCommand(generationType);
9937
+ if (command) {
9938
+ console.log("");
9939
+ console.log("Built-in command:");
9940
+ console.log(` vm0 ${command.label}`);
9941
+ console.log(` Models: ${command.models}`);
9942
+ console.log(` Use: ${command.command}`);
9943
+ return;
9944
+ }
9945
+ const providers = getBuiltInProviders(generationType);
9946
+ if (providers.length === 0) return;
9947
+ console.log("");
9948
+ console.log(
9949
+ providers.length === 1 ? "Built-in provider:" : "Built-in providers:"
9950
+ );
9951
+ for (const provider of providers) {
9952
+ console.log(` vm0 ${provider.label} Model: ${provider.model}`);
9953
+ console.log(` Use: ${provider.command}`);
9954
+ }
9955
+ }
9956
+ function renderGenerationContext(generationType) {
9957
+ const context = getGenerationContext(generationType);
9958
+ if (!context) return;
9959
+ console.log("");
9960
+ console.log("Context:");
9961
+ for (const line of context.lines) {
9962
+ console.log(` - ${line}`);
9963
+ }
9964
+ }
9965
+ function renderText(params) {
9966
+ const { generationType, agentId, ready, other, showAll } = params;
9967
+ const label = GENERATION_TYPE_LABELS[generationType];
9968
+ const scope = agentId ? "for current agent" : "(connected connectors)";
9969
+ console.log(`${label} generation choices ${scope}`);
9970
+ console.log("");
9971
+ if (agentId) {
9972
+ console.log(`${"Agent:".padEnd(10)}${agentId}`);
9973
+ console.log("");
9974
+ } else {
9975
+ console.log(
9976
+ "ZERO_AGENT_ID is not set, so agent authorization could not be checked."
9977
+ );
9978
+ console.log("");
9979
+ }
9980
+ const hasBuiltInCommand = getBuiltInCommand(generationType) !== null;
9981
+ const showConnectorSummary = ready.length > 0 || !hasBuiltInCommand || showAll;
9982
+ if (showConnectorSummary) {
9983
+ console.log("Connectors:");
9984
+ if (ready.length > 0) {
9985
+ renderRows(ready);
9986
+ } else {
9987
+ console.log(` No ready ${generationType} generation connectors found.`);
9988
+ }
9989
+ }
9990
+ renderBuiltInProvider(generationType);
9991
+ renderGenerationContext(generationType);
9992
+ if (showAll && other.length > 0) {
9993
+ console.log("");
9994
+ console.log(`Other ${generationType} generation connectors`);
9995
+ console.log("");
9996
+ renderRows(other);
9997
+ }
9998
+ if (showAll) {
9999
+ renderActions(other);
10000
+ }
10001
+ }
10002
+ async function runLister(generationType, options = {}) {
10003
+ const connectorGenerationType = getConnectorGenerationType(generationType);
10004
+ const agentId = process.env.ZERO_AGENT_ID;
10005
+ const [connectorList, availableTypes, enabledTypes, platformOrigin] = await Promise.all([
10006
+ listZeroConnectors(),
10007
+ getFeatureAvailableConnectorTypes(),
10008
+ agentId ? getZeroAgentUserConnectors(agentId) : Promise.resolve(null),
10009
+ getPlatformOrigin()
10010
+ ]);
10011
+ const connectedMap = new Map(
10012
+ connectorList.connectors.map((connector) => {
10013
+ return [connector.type, connector];
10014
+ })
10015
+ );
10016
+ const configuredTypes = new Set(connectorList.configuredTypes);
10017
+ const authorizedTypes = enabledTypes ? new Set(enabledTypes) : null;
10018
+ const candidates = connectorGenerationType ? getGenerationConnectors(connectorGenerationType).map(
10019
+ ([connectorType, config]) => {
10020
+ return toCandidate({
10021
+ type: connectorType,
10022
+ config,
10023
+ connector: connectedMap.get(connectorType),
10024
+ configuredTypes,
10025
+ availableTypes,
10026
+ authorizedTypes,
10027
+ agentId,
10028
+ platformOrigin
10029
+ });
10030
+ }
10031
+ ) : [];
10032
+ const ready = candidates.filter((candidate) => {
10033
+ return candidate.status === "ready";
10034
+ });
10035
+ const other = candidates.filter((candidate) => {
10036
+ return candidate.status !== "ready";
10037
+ });
10038
+ const builtInProviders = getBuiltInProviders(generationType);
10039
+ if (options.json) {
10040
+ console.log(
10041
+ JSON.stringify(
10042
+ {
10043
+ generationType,
10044
+ connectorGenerationType,
10045
+ availableTypes: getAvailableGenerationTypes(),
10046
+ agentId: agentId ?? null,
10047
+ choices: ready,
10048
+ otherCandidates: other,
10049
+ builtInCommand: getBuiltInCommand(generationType),
10050
+ generationContext: getGenerationContext(generationType),
10051
+ builtInProvider: builtInProviders[0] ?? null,
10052
+ builtInProviders
10053
+ },
10054
+ null,
10055
+ 2
10056
+ )
10057
+ );
10058
+ return;
10059
+ }
10060
+ renderText({
10061
+ generationType,
10062
+ agentId,
10063
+ ready,
10064
+ other,
10065
+ showAll: options.all === true
10066
+ });
10067
+ const shouldShowOtherHint = !options.all && other.length > 0 && (ready.length > 0 || getBuiltInCommand(generationType) === null);
10068
+ if (shouldShowOtherHint) {
10069
+ console.log("");
10070
+ console.log(
10071
+ source_default.dim(
10072
+ `Use --all to see every ${generationType} generation candidate.`
10073
+ )
10074
+ );
9803
10075
  }
9804
- if (value === "docs") {
9805
- return "docs-design";
10076
+ }
10077
+
10078
+ // src/commands/zero/generate/lib/dispatch.ts
10079
+ async function dispatchGenerate(options) {
10080
+ const provider = options.provider?.trim();
10081
+ if (provider && provider !== "built-in") {
10082
+ printConnectorGuidance(options.generationType, provider);
10083
+ return { outcome: "handled" };
9806
10084
  }
9807
- if (value === "mobile-app") {
9808
- return "mobile-app-design";
10085
+ const resolvedPrompt = resolvePrompt(options.prompt);
10086
+ if (resolvedPrompt === null) {
10087
+ await runLister(options.generationType, {
10088
+ all: options.all,
10089
+ json: options.json
10090
+ });
10091
+ return { outcome: "handled" };
9809
10092
  }
9810
- return value;
10093
+ return { outcome: "execute", prompt: resolvedPrompt };
9811
10094
  }
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
10095
+ function resolvePrompt(prompt) {
10096
+ if (prompt?.trim()) {
10097
+ return prompt.trim();
10098
+ }
10099
+ if (process.stdin.isTTY === false) {
10100
+ try {
10101
+ const piped = readFileSync13("/dev/stdin", "utf8").trim();
10102
+ if (piped.length > 0) {
10103
+ return piped;
9827
10104
  }
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]
10105
+ } catch {
9855
10106
  }
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
- };
10107
+ }
10108
+ return null;
9959
10109
  }
9960
10110
 
9961
10111
  // src/commands/zero/shared/image-generate.ts
@@ -9996,20 +10146,6 @@ function unknownStyleError(id, usageCommand) {
9996
10146
  ].join("\n");
9997
10147
  return new Error(message);
9998
10148
  }
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
10149
  function parseCompression(value) {
10014
10150
  if (value === void 0) {
10015
10151
  return void 0;
@@ -10051,6 +10187,12 @@ function parseImagePromptStrength(value) {
10051
10187
  }
10052
10188
  function createImageGenerateCommand(config) {
10053
10189
  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(
10190
+ "--provider <name>",
10191
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
10192
+ ).option(
10193
+ "--all",
10194
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
10195
+ ).option(
10054
10196
  "--model <model>",
10055
10197
  "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
10198
  "gpt-image-1"
@@ -10142,13 +10284,21 @@ Image Styles:
10142
10284
  ${formatStyleListing(styles)}`;
10143
10285
  }).action(
10144
10286
  withErrorHandler(async (options, command) => {
10287
+ const dispatch = await dispatchGenerate({
10288
+ generationType: config.generationType,
10289
+ provider: options.provider,
10290
+ prompt: options.prompt,
10291
+ all: options.all,
10292
+ json: options.json
10293
+ });
10294
+ if (dispatch.outcome === "handled") return;
10295
+ const prompt = dispatch.prompt;
10145
10296
  if (options.style && options.skipStyle) {
10146
10297
  throw new Error("--style and --skip-style cannot be combined");
10147
10298
  }
10148
10299
  if (!options.style && !options.skipStyle) {
10149
10300
  throw requireStyleError(config.usageCommand);
10150
10301
  }
10151
- const prompt = readPrompt(options, config.usageCommand);
10152
10302
  if (options.style) {
10153
10303
  const style = findImageStyle(options.style);
10154
10304
  if (!style) {
@@ -10228,24 +10378,26 @@ ${formatStyleListing(styles)}`;
10228
10378
  );
10229
10379
  }
10230
10380
 
10231
- // src/commands/zero/built-in/generate/image.ts
10381
+ // src/commands/zero/generate/image.ts
10232
10382
  var imageCommand = createImageGenerateCommand({
10233
10383
  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"`
10384
+ generationType: "image",
10385
+ usageCommand: "zero generate image",
10386
+ examples: ` Styled image: zero generate image --style vm0:image-style:notion-illustration --prompt "A product manager mapping a launch plan"
10387
+ Skip style: zero generate image --skip-style --prompt "A watercolor fox"
10388
+ Pipe prompt: cat prompt.txt | zero generate image --skip-style
10389
+ GPT Image model: zero generate image --skip-style --model gpt-image-1.5 --prompt "A poster" --size 1024x1536 --quality high
10390
+ Flux model: zero generate image --skip-style --model flux-pro-1.1 --prompt "A product hero shot" --seed 42
10391
+ 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"
10392
+ List providers: zero generate image
10393
+ Use a connector: zero generate image --provider replicate`
10241
10394
  });
10242
10395
 
10243
- // src/commands/zero/built-in/generate/open-design-artifacts.ts
10396
+ // src/commands/zero/generate/open-design-artifacts.ts
10244
10397
  init_esm_shims();
10245
10398
 
10246
10399
  // src/commands/zero/shared/open-design-artifact-generate.ts
10247
10400
  init_esm_shims();
10248
- import { readFileSync as readFileSync14 } from "fs";
10249
10401
 
10250
10402
  // src/commands/zero/shared/html-artifact-authoring.ts
10251
10403
  init_esm_shims();
@@ -10318,7 +10470,7 @@ function createHtmlArtifactAuthoringPacket(options) {
10318
10470
  outputDir: outputDir2
10319
10471
  };
10320
10472
  const instructions = [
10321
- `# Zero built-in generate ${options.kind}`,
10473
+ `# Zero generate ${options.kind}`,
10322
10474
  "",
10323
10475
  "This is a federated generation resource-selection packet for the current agent.",
10324
10476
  `Zero is not generating this ${title} on the server. You select resources, resolve them, and author the artifact.`,
@@ -10425,22 +10577,14 @@ function createHtmlArtifactAuthoringPacket(options) {
10425
10577
  }
10426
10578
 
10427
10579
  // 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
10580
  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(
10581
+ return new Command().name(config.name).description(config.description).option("--prompt <text>", "Artifact prompt; can also be piped via stdin").option(
10582
+ "--provider <name>",
10583
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
10584
+ ).option(
10585
+ "--all",
10586
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
10587
+ ).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
10588
  "after",
10445
10589
  `
10446
10590
  Examples:
@@ -10448,13 +10592,22 @@ ${config.examples}
10448
10592
 
10449
10593
  Output:
10450
10594
  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.
10595
+ agent authors a static HTML artifact and hosts it with zero host. With no
10596
+ --prompt and no piped input, prints the provider menu instead.
10452
10597
 
10453
10598
  Notes:
10454
10599
  - Authenticates via ZERO_TOKEN`
10455
10600
  ).action(
10456
10601
  withErrorHandler(async (options) => {
10457
- const prompt = readPrompt2(options, config.usageCommand);
10602
+ const dispatch = await dispatchGenerate({
10603
+ generationType: config.generationType,
10604
+ provider: options.provider,
10605
+ prompt: options.prompt,
10606
+ all: options.all,
10607
+ json: options.json
10608
+ });
10609
+ if (dispatch.outcome === "handled") return;
10610
+ const prompt = dispatch.prompt;
10458
10611
  const packet = createHtmlArtifactAuthoringPacket({
10459
10612
  kind: toOpenDesignTarget(config.target),
10460
10613
  prompt,
@@ -10472,7 +10625,7 @@ Notes:
10472
10625
  );
10473
10626
  }
10474
10627
 
10475
- // src/commands/zero/built-in/generate/open-design-artifacts.ts
10628
+ // src/commands/zero/generate/open-design-artifacts.ts
10476
10629
  function standardDetails(kind) {
10477
10630
  return (options) => {
10478
10631
  return [
@@ -10484,11 +10637,13 @@ function standardDetails(kind) {
10484
10637
  }
10485
10638
  var reportCommand = createOpenDesignArtifactGenerateCommand({
10486
10639
  name: "report",
10640
+ generationType: "report",
10487
10641
  target: "report",
10488
10642
  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"`,
10643
+ usageCommand: "zero generate report",
10644
+ examples: ` Generate report: zero generate report --prompt "A Q2 usage report for the API team"
10645
+ Stable hosted slug: zero generate report --site api-usage-q2 --prompt "A Q2 usage report"
10646
+ List providers: zero generate report`,
10492
10647
  details: standardDetails("report"),
10493
10648
  artifactRules: [
10494
10649
  "Produce an analytical report, not a marketing page.",
@@ -10499,11 +10654,13 @@ var reportCommand = createOpenDesignArtifactGenerateCommand({
10499
10654
  });
10500
10655
  var docsDesignCommand = createOpenDesignArtifactGenerateCommand({
10501
10656
  name: "docs-design",
10657
+ generationType: "docs-design",
10502
10658
  target: "docs-design",
10503
10659
  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"`,
10660
+ usageCommand: "zero generate docs-design",
10661
+ examples: ` Generate docs design: zero generate docs-design --prompt "Docs for adding OpenDesign artifact targets"
10662
+ Stable hosted slug: zero generate docs-design --site opendesign-target-docs --prompt "OpenDesign target docs"
10663
+ List providers: zero generate docs-design`,
10507
10664
  details: standardDetails("docs-design"),
10508
10665
  artifactRules: [
10509
10666
  "Produce a documentation design mockup, not a production documentation system.",
@@ -10514,11 +10671,13 @@ var docsDesignCommand = createOpenDesignArtifactGenerateCommand({
10514
10671
  });
10515
10672
  var posterCommand = createOpenDesignArtifactGenerateCommand({
10516
10673
  name: "poster",
10674
+ generationType: "poster",
10517
10675
  target: "poster",
10518
10676
  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"`,
10677
+ usageCommand: "zero generate poster",
10678
+ examples: ` Generate poster: zero generate poster --prompt "A launch poster for OpenDesign artifact targets"
10679
+ Stable hosted slug: zero generate poster --site opendesign-poster --prompt "A launch poster"
10680
+ List providers: zero generate poster`,
10522
10681
  details: standardDetails("poster"),
10523
10682
  artifactRules: [
10524
10683
  "Produce a poster-style HTML artifact with strong hierarchy and composition.",
@@ -10529,11 +10688,13 @@ var posterCommand = createOpenDesignArtifactGenerateCommand({
10529
10688
  });
10530
10689
  var dashboardDesignCommand = createOpenDesignArtifactGenerateCommand({
10531
10690
  name: "dashboard-design",
10691
+ generationType: "dashboard-design",
10532
10692
  target: "dashboard-design",
10533
10693
  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"`,
10694
+ usageCommand: "zero generate dashboard-design",
10695
+ examples: ` Generate dash design: zero generate dashboard-design --prompt "An ops dashboard for generation runs"
10696
+ Stable hosted slug: zero generate dashboard-design --site generation-ops --prompt "A generation ops dashboard"
10697
+ List providers: zero generate dashboard-design`,
10537
10698
  details: standardDetails("dashboard-design"),
10538
10699
  artifactRules: [
10539
10700
  "Produce a dashboard design mockup, not a live operational dashboard.",
@@ -10544,11 +10705,13 @@ var dashboardDesignCommand = createOpenDesignArtifactGenerateCommand({
10544
10705
  });
10545
10706
  var mobileAppDesignCommand = createOpenDesignArtifactGenerateCommand({
10546
10707
  name: "mobile-app-design",
10708
+ generationType: "mobile-app-design",
10547
10709
  target: "mobile-app-design",
10548
10710
  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"`,
10711
+ usageCommand: "zero generate mobile-app-design",
10712
+ examples: ` Generate mobile UI: zero generate mobile-app-design --prompt "A mobile review screen for generation artifacts"
10713
+ Stable hosted slug: zero generate mobile-app-design --site generation-mobile-review --prompt "A mobile review screen"
10714
+ List providers: zero generate mobile-app-design`,
10552
10715
  details: standardDetails("mobile-app-design"),
10553
10716
  artifactRules: [
10554
10717
  "Produce a design prototype, not a runnable or installable mobile app.",
@@ -10558,12 +10721,11 @@ var mobileAppDesignCommand = createOpenDesignArtifactGenerateCommand({
10558
10721
  ]
10559
10722
  });
10560
10723
 
10561
- // src/commands/zero/built-in/generate/presentation.ts
10724
+ // src/commands/zero/generate/presentation.ts
10562
10725
  init_esm_shims();
10563
10726
 
10564
10727
  // src/commands/zero/shared/presentation-generate.ts
10565
10728
  init_esm_shims();
10566
- import { readFileSync as readFileSync15 } from "fs";
10567
10729
  var PRESENTATION_MAX_IMAGES = 8;
10568
10730
  function parseSlideCount(value) {
10569
10731
  const slideCount = Number(value);
@@ -10584,26 +10746,16 @@ function parseImageCount(value) {
10584
10746
  }
10585
10747
  return imageCount;
10586
10748
  }
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
10749
  function createPresentationGenerateCommand(config) {
10604
10750
  return new Command().name(config.name).description("Generate an HTML presentation from a prompt").option(
10605
10751
  "--prompt <text>",
10606
10752
  "Presentation prompt; can also be piped via stdin"
10753
+ ).option(
10754
+ "--provider <name>",
10755
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
10756
+ ).option(
10757
+ "--all",
10758
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
10607
10759
  ).option("--style <style>", "Style: editorial or swiss", "editorial").option("--slides <count>", "Slide count: 4-20", parseSlideCount, 8).option(
10608
10760
  "--images <count>",
10609
10761
  `Generated image count: 0-${PRESENTATION_MAX_IMAGES}`,
@@ -10629,7 +10781,15 @@ Notes:
10629
10781
  - The agent authors the HTML presentation artifact and hosts it with zero host`
10630
10782
  ).action(
10631
10783
  withErrorHandler(async (options) => {
10632
- const prompt = readPrompt3(options, config.usageCommand);
10784
+ const dispatch = await dispatchGenerate({
10785
+ generationType: config.generationType,
10786
+ provider: options.provider,
10787
+ prompt: options.prompt,
10788
+ all: options.all,
10789
+ json: options.json
10790
+ });
10791
+ if (dispatch.outcome === "handled") return;
10792
+ const prompt = dispatch.prompt;
10633
10793
  const packet = createHtmlArtifactAuthoringPacket({
10634
10794
  kind: "presentation",
10635
10795
  prompt,
@@ -10660,22 +10820,23 @@ Notes:
10660
10820
  );
10661
10821
  }
10662
10822
 
10663
- // src/commands/zero/built-in/generate/presentation.ts
10823
+ // src/commands/zero/generate/presentation.ts
10664
10824
  var presentationCommand = createPresentationGenerateCommand({
10665
10825
  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"`
10826
+ generationType: "presentation",
10827
+ usageCommand: "zero generate presentation",
10828
+ examples: ` Generate deck: zero generate presentation --prompt "A strategy deck for reducing support volume"
10829
+ Pipe prompt: cat brief.txt | zero generate presentation
10830
+ Swiss style: zero generate presentation --style swiss --theme ikb --slides 10 --images 8 --image-model gpt-image-1.5 --prompt "A product launch narrative"
10831
+ Audience context: zero generate presentation --audience "engineering leadership" --prompt "API migration plan"
10832
+ List providers: zero generate presentation`
10671
10833
  });
10672
10834
 
10673
- // src/commands/zero/built-in/generate/video.ts
10835
+ // src/commands/zero/generate/video.ts
10674
10836
  init_esm_shims();
10675
10837
 
10676
10838
  // src/commands/zero/shared/video-generate.ts
10677
10839
  init_esm_shims();
10678
- import { readFileSync as readFileSync16 } from "fs";
10679
10840
  var FRAME_ASPECT_RATIO_TOLERANCE = 0.02;
10680
10841
  var JPEG_START_OF_FRAME_MARKERS = /* @__PURE__ */ new Set([
10681
10842
  192,
@@ -10869,22 +11030,14 @@ async function validateVideoOptions(options) {
10869
11030
  )
10870
11031
  ]);
10871
11032
  }
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
11033
  function createVideoGenerateCommand(config) {
10887
11034
  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(
11035
+ "--provider <name>",
11036
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
11037
+ ).option(
11038
+ "--all",
11039
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
11040
+ ).option(
10888
11041
  "--model <model>",
10889
11042
  "Model: dreamina-seedance-2.0-fast, dreamina-seedance-2.0, seedance-1.5-pro, veo3.1-fast, or kling-v3-4k",
10890
11043
  "dreamina-seedance-2.0-fast"
@@ -10939,7 +11092,15 @@ Models:
10939
11092
  4k output, negative prompts, and optional audio.`
10940
11093
  ).action(
10941
11094
  withErrorHandler(async (options) => {
10942
- const prompt = readPrompt4(options, config.usageCommand);
11095
+ const dispatch = await dispatchGenerate({
11096
+ generationType: config.generationType,
11097
+ provider: options.provider,
11098
+ prompt: options.prompt,
11099
+ all: options.all,
11100
+ json: options.json
11101
+ });
11102
+ if (dispatch.outcome === "handled") return;
11103
+ const prompt = dispatch.prompt;
10943
11104
  await validateVideoOptions(options);
10944
11105
  const result = await generateWebVideo({
10945
11106
  prompt,
@@ -10976,20 +11137,22 @@ Models:
10976
11137
  );
10977
11138
  }
10978
11139
 
10979
- // src/commands/zero/built-in/generate/video.ts
11140
+ // src/commands/zero/generate/video.ts
10980
11141
  var videoCommand = createVideoGenerateCommand({
10981
11142
  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"`
11143
+ generationType: "video",
11144
+ usageCommand: "zero generate video",
11145
+ examples: ` Generate video: zero generate video --prompt "A tracking shot through a neon market"
11146
+ Pipe prompt: cat prompt.txt | zero generate video
11147
+ Use Dreamina 2.0: zero generate video --model dreamina-seedance-2.0 --prompt "A cinematic product reveal" --duration 6s --resolution 1080p
11148
+ Use Seedance 1.5 Pro: zero generate video --model seedance-1.5-pro --prompt "A multi-shot chase scene" --duration 8s --resolution 720p
11149
+ Add a first frame: zero generate video --first-frame-image-url https://example.com/frame.png --prompt "Animate this frame"
11150
+ List providers: zero generate video
11151
+ Use HeyGen: zero generate video --provider heygen`
10988
11152
  });
10989
11153
 
10990
- // src/commands/zero/built-in/generate/website.ts
11154
+ // src/commands/zero/generate/website.ts
10991
11155
  init_esm_shims();
10992
- import { readFileSync as readFileSync17 } from "fs";
10993
11156
  var WEBSITE_TEMPLATES = ["auto", "launch", "profile"];
10994
11157
  var WEBSITE_MAX_IMAGES = 3;
10995
11158
  function parseTemplate(value) {
@@ -11012,23 +11175,13 @@ function parseImageCount2(value) {
11012
11175
  }
11013
11176
  return imageCount;
11014
11177
  }
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
11178
  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(
11179
+ "--provider <name>",
11180
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name to get its skill-invocation guidance"
11181
+ ).option(
11182
+ "--all",
11183
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
11184
+ ).option(
11032
11185
  "--template <template>",
11033
11186
  "Template: auto, launch, or profile",
11034
11187
  parseTemplate,
@@ -11045,20 +11198,30 @@ var websiteCommand = new Command().name("website").description("Prepare website
11045
11198
  "after",
11046
11199
  `
11047
11200
  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
11201
+ Generate site: zero generate website --prompt "A launch site for a developer observability tool"
11202
+ Pick template: zero generate website --template profile --images 2 --image-model gpt-image-1.5 --prompt "Portfolio for a robotics photographer"
11203
+ Stable hosted slug: zero generate website --site api-migration-demo --prompt "An internal migration microsite"
11204
+ Pipe prompt: cat brief.txt | zero generate website
11205
+ List providers: zero generate website
11052
11206
 
11053
11207
  Output:
11054
11208
  Prints an Open Design registry-selection packet for the current agent.
11209
+ With no --prompt and no piped input, prints the provider menu instead.
11055
11210
 
11056
11211
  Notes:
11057
11212
  - Authenticates via ZERO_TOKEN
11058
11213
  - The agent authors the HTML artifact and hosts it with zero host`
11059
11214
  ).action(
11060
11215
  withErrorHandler(async (options) => {
11061
- const prompt = readPrompt5(options);
11216
+ const dispatch = await dispatchGenerate({
11217
+ generationType: "website",
11218
+ provider: options.provider,
11219
+ prompt: options.prompt,
11220
+ all: options.all,
11221
+ json: options.json
11222
+ });
11223
+ if (dispatch.outcome === "handled") return;
11224
+ const prompt = dispatch.prompt;
11062
11225
  const packet = createHtmlArtifactAuthoringPacket({
11063
11226
  kind: "website",
11064
11227
  prompt,
@@ -11086,35 +11249,27 @@ Notes:
11086
11249
  })
11087
11250
  );
11088
11251
 
11089
- // src/commands/zero/built-in/generate/voice.ts
11252
+ // src/commands/zero/generate/voice.ts
11090
11253
  init_esm_shims();
11091
11254
 
11092
11255
  // src/commands/zero/shared/voice-generate.ts
11093
11256
  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
11257
  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(
11258
+ 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(
11259
+ "--provider <name>",
11260
+ "Provider: 'built-in' to run vm0's pipeline, or a connector name (heygen, elevenlabs, ...) to get its skill-invocation guidance"
11261
+ ).option(
11262
+ "--all",
11263
+ "When listing providers (no --prompt given), include unavailable or not-yet-authorized connectors"
11264
+ ).option("--voice <voice>", "OpenAI voice to use", "marin").option("--instructions <text>", "Voice style instructions").option("--json", "Print metadata as JSON").addHelpText(
11111
11265
  "after",
11112
11266
  `
11113
11267
  Examples:
11114
11268
  ${config.examples}
11115
11269
 
11116
11270
  Output:
11117
- Prints the generated /f/ audio file URL and metadata
11271
+ Prints the generated /f/ audio file URL and metadata. With no --prompt
11272
+ and no piped input, prints the provider menu instead.
11118
11273
 
11119
11274
  Notes:
11120
11275
  - Authenticates via ZERO_TOKEN (requires file:write capability)
@@ -11122,7 +11277,15 @@ Notes:
11122
11277
  - Uses gpt-4o-mini-tts with WAV output`
11123
11278
  ).action(
11124
11279
  withErrorHandler(async (options) => {
11125
- const text = readText(options, config.usageCommand);
11280
+ const dispatch = await dispatchGenerate({
11281
+ generationType: config.generationType,
11282
+ provider: options.provider,
11283
+ prompt: options.prompt ?? options.text,
11284
+ all: options.all,
11285
+ json: options.json
11286
+ });
11287
+ if (dispatch.outcome === "handled") return;
11288
+ const text = dispatch.prompt;
11126
11289
  const result = await generateWebVoice({
11127
11290
  text,
11128
11291
  voice: options.voice,
@@ -11142,53 +11305,108 @@ Notes:
11142
11305
  );
11143
11306
  }
11144
11307
 
11145
- // src/commands/zero/built-in/generate/voice.ts
11308
+ // src/commands/zero/generate/voice.ts
11146
11309
  var voiceCommand = createVoiceGenerateCommand({
11147
11310
  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`
11311
+ generationType: "voice",
11312
+ usageCommand: "zero generate voice",
11313
+ examples: ` Generate speech: zero generate voice --prompt "Hello from vm0"
11314
+ Pipe prompt: cat script.txt | zero generate voice
11315
+ Pick a voice: zero generate voice --prompt "Ship it" --voice cedar
11316
+ List providers: zero generate voice
11317
+ Use ElevenLabs: zero generate voice --provider elevenlabs`
11152
11318
  });
11153
11319
 
11154
- // src/commands/zero/built-in/generate/index.ts
11320
+ // src/commands/zero/generate/lister-only.ts
11321
+ init_esm_shims();
11322
+ function createListerOnlyCommand(config) {
11323
+ return new Command().name(config.name).description(config.description).option(
11324
+ "--provider <name>",
11325
+ "Connector name; prints that connector's skill-invocation guidance"
11326
+ ).option("--all", "Include unavailable or not-yet-authorized connectors").option("--json", "Print the provider list as JSON").addHelpText(
11327
+ "after",
11328
+ `
11329
+ Notes:
11330
+ - vm0 does not provide a built-in ${config.generationType} pipeline.
11331
+ - Use --provider <connector-name> to get skill-invocation guidance for a
11332
+ specific connector, or run with no flags to see every available provider.`
11333
+ ).action(
11334
+ withErrorHandler(async (options) => {
11335
+ const provider = options.provider?.trim();
11336
+ if (provider && provider !== "built-in") {
11337
+ printConnectorGuidance(config.generationType, provider);
11338
+ return;
11339
+ }
11340
+ if (provider === "built-in") {
11341
+ console.log(
11342
+ `vm0 has no built-in ${config.generationType} generation pipeline.`
11343
+ );
11344
+ console.log("");
11345
+ console.log(
11346
+ `Run "zero generate ${config.generationType}" to see every connector-backed provider.`
11347
+ );
11348
+ return;
11349
+ }
11350
+ await runLister(config.generationType, {
11351
+ all: options.all,
11352
+ json: options.json
11353
+ });
11354
+ })
11355
+ );
11356
+ }
11357
+
11358
+ // src/commands/zero/generate/index.ts
11359
+ var audioCommand = createListerOnlyCommand({
11360
+ name: "audio",
11361
+ generationType: "audio",
11362
+ description: "List connectors that provide audio generation (alias of voice for non-speech audio)"
11363
+ });
11364
+ var textCommand = createListerOnlyCommand({
11365
+ name: "text",
11366
+ generationType: "text",
11367
+ description: "List connectors that provide text generation"
11368
+ });
11369
+ var codeCommand = createListerOnlyCommand({
11370
+ name: "code",
11371
+ generationType: "code",
11372
+ description: "List connectors that provide code generation"
11373
+ });
11374
+ var documentCommand = createListerOnlyCommand({
11375
+ name: "document",
11376
+ generationType: "document",
11377
+ description: "List connectors that provide document generation"
11378
+ });
11155
11379
  function buildGenerateHelpText() {
11156
11380
  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"',
11381
+ ' Generate image: zero generate image --prompt "A watercolor fox"',
11382
+ ' Generate deck: zero generate presentation --prompt "A product roadmap"',
11383
+ ' Generate report: zero generate report --prompt "A Q2 usage report"',
11384
+ ' Generate docs: zero generate docs-design --prompt "A setup guide"',
11385
+ ' Generate video: zero generate video --prompt "A cinematic city shot"',
11162
11386
  ...zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */) ? [
11163
- ' Generate site: zero built-in generate website --prompt "A launch site"'
11387
+ ' Generate site: zero generate website --prompt "A launch site"'
11164
11388
  ] : [],
11165
- ' Generate speech: zero built-in generate voice --text "Hello"'
11389
+ ' Generate speech: zero generate voice --prompt "Hello"',
11390
+ "",
11391
+ " List image providers: zero generate image",
11392
+ " Use a connector: zero generate video --provider heygen",
11393
+ " Force built-in: zero generate image --provider built-in --model gpt-image-1.5 --prompt ..."
11166
11394
  ];
11167
11395
  return `
11168
11396
  Examples:
11169
- ${examples.join("\n")}`;
11397
+ ${examples.join("\n")}
11398
+
11399
+ Notes:
11400
+ - Run "zero generate <type>" with no --prompt to list every provider available for that type.
11401
+ - --provider built-in (default when --prompt is provided) runs the vm0-hosted pipeline.
11402
+ - --provider <connector-name> prints how to invoke that connector's skill instead.`;
11170
11403
  }
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(
11404
+ var generateCommand = new Command().name("generate").description(
11405
+ "Generate assets via vm0's built-in pipelines or get connector skill-invocation guidance"
11406
+ ).addCommand(imageCommand).addCommand(presentationCommand).addCommand(reportCommand).addCommand(docsDesignCommand).addCommand(posterCommand).addCommand(dashboardDesignCommand).addCommand(mobileAppDesignCommand).addCommand(videoCommand).addCommand(
11172
11407
  websiteCommand,
11173
11408
  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);
11409
+ ).addCommand(voiceCommand).addCommand(audioCommand).addCommand(textCommand).addCommand(codeCommand).addCommand(documentCommand).addHelpText("after", buildGenerateHelpText);
11192
11410
 
11193
11411
  // src/commands/zero/web/index.ts
11194
11412
  init_esm_shims();
@@ -12247,7 +12465,7 @@ var COMMAND_CAPABILITY_MAP = {
12247
12465
  whoami: null,
12248
12466
  "developer-support": null,
12249
12467
  "computer-use": "computer-use:write",
12250
- "built-in": "file:write",
12468
+ generate: "file:write",
12251
12469
  web: null,
12252
12470
  host: "host:write",
12253
12471
  maps: "maps:read",
@@ -12278,7 +12496,7 @@ var DEFAULT_COMMANDS = [
12278
12496
  zeroSkillCommand,
12279
12497
  zeroDeveloperSupportCommand,
12280
12498
  zeroComputerUseCommand,
12281
- zeroBuiltInCommand,
12499
+ generateCommand,
12282
12500
  zeroWebCommand,
12283
12501
  zeroHostCommand,
12284
12502
  zeroMapsCommand,
@@ -12287,7 +12505,7 @@ var DEFAULT_COMMANDS = [
12287
12505
  ];
12288
12506
  function shouldHideCommand(name, payload) {
12289
12507
  if (!payload) return false;
12290
- if (name === "built-in") {
12508
+ if (name === "generate") {
12291
12509
  return !payload.capabilities.includes("file:write") && !zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */, payload);
12292
12510
  }
12293
12511
  const requiredCap = COMMAND_CAPABILITY_MAP[name];
@@ -12320,9 +12538,10 @@ function buildZeroHelpText(payload = decodeZeroTokenPayload()) {
12320
12538
  " Model routing? zero model-provider ls",
12321
12539
  " Update yourself? zero agent --help",
12322
12540
  " 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",
12541
+ " List generators? zero generate --help",
12542
+ ' Generate image? zero generate image --prompt "..."',
12543
+ ...zeroTokenAllowsFeatureSwitch("hostedSites" /* HostedSites */, payload) ? [' Generate website? zero generate website --prompt "..."'] : [],
12544
+ ' Generate voice? zero generate voice --prompt "..."',
12326
12545
  ...shouldHideCommand("local-browser", payload) ? [] : [" Read browser context? zero local-browser --help"],
12327
12546
  ...shouldHideCommand("host", payload) ? [] : [" Host a static site? zero host ./dist --site my-site --spa"],
12328
12547
  ...shouldHideCommand("maps", payload) ? [] : [
@@ -12345,7 +12564,7 @@ function registerZeroCommands(prog, commands) {
12345
12564
  var program = new Command();
12346
12565
  program.name("zero").description(
12347
12566
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
12348
- ).version("9.168.3").addHelpText("after", () => {
12567
+ ).version("9.169.0").addHelpText("after", () => {
12349
12568
  return buildZeroHelpText();
12350
12569
  });
12351
12570
  if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {