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