@vm0/cli 9.177.19 → 9.179.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{chunk-4ILTCW7H.js → chunk-KC3JLLAV.js} +1742 -427
- package/{chunk-4ILTCW7H.js.map → chunk-KC3JLLAV.js.map} +1 -1
- package/index.js +9 -9
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/zero.js +283 -90
- package/zero.js.map +1 -1
package/package.json
CHANGED
package/zero.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
InvalidArgumentError,
|
|
12
12
|
MODEL_PROVIDER_TYPES,
|
|
13
13
|
Option,
|
|
14
|
+
callZeroBanking,
|
|
14
15
|
callZeroMaps,
|
|
15
16
|
completeGithubFileUpload,
|
|
16
17
|
completeHostedSite,
|
|
@@ -61,11 +62,11 @@ import {
|
|
|
61
62
|
getConnectorAuthMethod,
|
|
62
63
|
getConnectorAuthMethodScopeDiff,
|
|
63
64
|
getConnectorEnvBindingEntries,
|
|
64
|
-
getConnectorEnvNamesForSecret,
|
|
65
65
|
getConnectorFirewall,
|
|
66
66
|
getConnectorGenerationTypes,
|
|
67
|
-
|
|
67
|
+
getConnectorStoredSecretDisplayInfo,
|
|
68
68
|
getDefaultAuthMethod,
|
|
69
|
+
getDiagnosticConnectorTypeForRuntimeEnvName,
|
|
69
70
|
getGithubInstallation,
|
|
70
71
|
getSecretsForAuthMethod,
|
|
71
72
|
getSelectableProviderTypes,
|
|
@@ -148,7 +149,7 @@ import {
|
|
|
148
149
|
upsertZeroOrgModelProvider,
|
|
149
150
|
withErrorHandler,
|
|
150
151
|
zeroAgentCustomSkillNameSchema
|
|
151
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-KC3JLLAV.js";
|
|
152
153
|
import {
|
|
153
154
|
__toESM,
|
|
154
155
|
init_esm_shims
|
|
@@ -2905,14 +2906,14 @@ How connectors work:
|
|
|
2905
2906
|
console.log(` Relative path: ${urlLookup.relativePath}`);
|
|
2906
2907
|
console.log(` Environment name: ${envName}`);
|
|
2907
2908
|
} else {
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
)
|
|
2911
|
-
if (!connectorType) {
|
|
2909
|
+
envName = opts.envName;
|
|
2910
|
+
const resolvedConnectorType = getDiagnosticConnectorTypeForRuntimeEnvName(envName);
|
|
2911
|
+
if (!resolvedConnectorType) {
|
|
2912
2912
|
throw new Error(
|
|
2913
2913
|
`Unknown environment name: ${envName} \u2014 not managed by any connector`
|
|
2914
2914
|
);
|
|
2915
2915
|
}
|
|
2916
|
+
connectorType = resolvedConnectorType;
|
|
2916
2917
|
console.log(
|
|
2917
2918
|
`${envName} is managed by the ${CONNECTOR_TYPES[connectorType].label} connector (type: ${connectorType}).`
|
|
2918
2919
|
);
|
|
@@ -2978,6 +2979,66 @@ How connectors work:
|
|
|
2978
2979
|
|
|
2979
2980
|
// src/commands/zero/doctor/permission-deny.ts
|
|
2980
2981
|
init_esm_shims();
|
|
2982
|
+
|
|
2983
|
+
// src/commands/zero/doctor/permission-context.ts
|
|
2984
|
+
init_esm_shims();
|
|
2985
|
+
var LEGACY_PERMISSION_GRANT_MODE = "legacy";
|
|
2986
|
+
function roleFromOrg(org) {
|
|
2987
|
+
if (org.role === "admin") return "admin";
|
|
2988
|
+
if (org.role === "member") return "member";
|
|
2989
|
+
return "unknown";
|
|
2990
|
+
}
|
|
2991
|
+
function permissionGrantModeFromOrg(org) {
|
|
2992
|
+
return org.permissionGrantMode ?? LEGACY_PERMISSION_GRANT_MODE;
|
|
2993
|
+
}
|
|
2994
|
+
async function resolveUserId() {
|
|
2995
|
+
const zeroPayload = decodeZeroTokenPayload();
|
|
2996
|
+
if (zeroPayload?.userId) return zeroPayload.userId;
|
|
2997
|
+
const token = await getToken();
|
|
2998
|
+
const cliPayload = decodeCliTokenPayload(token);
|
|
2999
|
+
return cliPayload?.userId;
|
|
3000
|
+
}
|
|
3001
|
+
async function resolvePermissionGrantMode() {
|
|
3002
|
+
try {
|
|
3003
|
+
const org = await getZeroOrg();
|
|
3004
|
+
return permissionGrantModeFromOrg(org);
|
|
3005
|
+
} catch {
|
|
3006
|
+
return LEGACY_PERMISSION_GRANT_MODE;
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
async function resolvePermissionChangeContext(agentId) {
|
|
3010
|
+
try {
|
|
3011
|
+
const org = await getZeroOrg();
|
|
3012
|
+
const permissionGrantMode = permissionGrantModeFromOrg(org);
|
|
3013
|
+
if (!agentId || permissionGrantMode === "user-grants") {
|
|
3014
|
+
return {
|
|
3015
|
+
role: roleFromOrg(org),
|
|
3016
|
+
permissionGrantMode
|
|
3017
|
+
};
|
|
3018
|
+
}
|
|
3019
|
+
if (org.role === "admin") {
|
|
3020
|
+
return { role: "admin", permissionGrantMode };
|
|
3021
|
+
}
|
|
3022
|
+
if (org.role === "member") {
|
|
3023
|
+
const userId = await resolveUserId();
|
|
3024
|
+
if (userId) {
|
|
3025
|
+
const agent = await getZeroAgent(agentId);
|
|
3026
|
+
if (agent.ownerId === userId) {
|
|
3027
|
+
return { role: "owner", permissionGrantMode };
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
return { role: "member", permissionGrantMode };
|
|
3031
|
+
}
|
|
3032
|
+
return { role: "unknown", permissionGrantMode };
|
|
3033
|
+
} catch {
|
|
3034
|
+
return {
|
|
3035
|
+
role: "unknown",
|
|
3036
|
+
permissionGrantMode: LEGACY_PERMISSION_GRANT_MODE
|
|
3037
|
+
};
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
|
|
3041
|
+
// src/commands/zero/doctor/permission-deny.ts
|
|
2981
3042
|
var permissionDenyCommand = new Command().name("permission-deny").description(
|
|
2982
3043
|
"Diagnose a permission denial and find the permission that covers it"
|
|
2983
3044
|
).argument("<connector-ref>", "The connector type (e.g. github)").addOption(
|
|
@@ -3031,8 +3092,11 @@ Notes:
|
|
|
3031
3092
|
return (ruleCount.get(current) ?? Infinity) < (ruleCount.get(narrowest) ?? Infinity) ? current : narrowest;
|
|
3032
3093
|
});
|
|
3033
3094
|
console.log(`This is covered by the "${permission}" permission.`);
|
|
3095
|
+
const permissionGrantMode = await resolvePermissionGrantMode();
|
|
3096
|
+
const reasonArg = permissionGrantMode === "user-grants" ? "" : ' --reason "why this is needed"';
|
|
3097
|
+
const actionVerb = permissionGrantMode === "user-grants" ? "allow" : "request";
|
|
3034
3098
|
console.log(
|
|
3035
|
-
`To
|
|
3099
|
+
`To ${actionVerb} this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable${reasonArg}`
|
|
3036
3100
|
);
|
|
3037
3101
|
}
|
|
3038
3102
|
)
|
|
@@ -3040,36 +3104,6 @@ Notes:
|
|
|
3040
3104
|
|
|
3041
3105
|
// src/commands/zero/doctor/permission-change.ts
|
|
3042
3106
|
init_esm_shims();
|
|
3043
|
-
|
|
3044
|
-
// src/commands/zero/doctor/resolve-role.ts
|
|
3045
|
-
init_esm_shims();
|
|
3046
|
-
async function resolveUserId() {
|
|
3047
|
-
const zeroPayload = decodeZeroTokenPayload();
|
|
3048
|
-
if (zeroPayload?.userId) return zeroPayload.userId;
|
|
3049
|
-
const token = await getToken();
|
|
3050
|
-
const cliPayload = decodeCliTokenPayload(token);
|
|
3051
|
-
return cliPayload?.userId;
|
|
3052
|
-
}
|
|
3053
|
-
async function resolveAgentRole(agentId) {
|
|
3054
|
-
try {
|
|
3055
|
-
const org = await getZeroOrg();
|
|
3056
|
-
if (org.role === "admin") return "admin";
|
|
3057
|
-
if (org.role === "member") {
|
|
3058
|
-
const userId = await resolveUserId();
|
|
3059
|
-
if (userId) {
|
|
3060
|
-
const agent = await getZeroAgent(agentId);
|
|
3061
|
-
if (agent.ownerId === userId) return "owner";
|
|
3062
|
-
}
|
|
3063
|
-
return "member";
|
|
3064
|
-
}
|
|
3065
|
-
return "unknown";
|
|
3066
|
-
} catch (error) {
|
|
3067
|
-
console.debug("resolveAgentRole failed, falling back to unknown:", error);
|
|
3068
|
-
return "unknown";
|
|
3069
|
-
}
|
|
3070
|
-
}
|
|
3071
|
-
|
|
3072
|
-
// src/commands/zero/doctor/permission-change.ts
|
|
3073
3107
|
function findPermissionInConfig(ref, permissionName) {
|
|
3074
3108
|
if (!isFirewallConnectorType(ref)) return false;
|
|
3075
3109
|
const config = getConnectorFirewall(ref);
|
|
@@ -3082,23 +3116,15 @@ function findPermissionInConfig(ref, permissionName) {
|
|
|
3082
3116
|
return false;
|
|
3083
3117
|
}
|
|
3084
3118
|
var REASON_MAX_LENGTH = 500;
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
const
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
});
|
|
3095
|
-
if (role === "member" && reason) {
|
|
3096
|
-
const truncated = reason.length > REASON_MAX_LENGTH ? reason.slice(0, REASON_MAX_LENGTH) : reason;
|
|
3097
|
-
urlParams.set("reason", truncated);
|
|
3098
|
-
}
|
|
3099
|
-
const pagePath = agentId ? `/agents/${agentId}/permissions` : "/agents";
|
|
3100
|
-
const url = `${platformOrigin}${pagePath}?${urlParams.toString()}`;
|
|
3101
|
-
if (connectorRef === "slack" && permission === "chat:write" && action === "enable") {
|
|
3119
|
+
function addReasonParam(urlParams, role, usesUserGrants, reason) {
|
|
3120
|
+
if (usesUserGrants || role !== "member" || !reason) return;
|
|
3121
|
+
const truncated = reason.length > REASON_MAX_LENGTH ? reason.slice(0, REASON_MAX_LENGTH) : reason;
|
|
3122
|
+
urlParams.set("reason", truncated);
|
|
3123
|
+
}
|
|
3124
|
+
function printSensitivePermissionGuidance(connectorRef, permission, action, usesUserGrants) {
|
|
3125
|
+
if (action !== "enable") return;
|
|
3126
|
+
const approvalWording = usesUserGrants ? "Only allow this permission below" : "Only request user approval below";
|
|
3127
|
+
if (connectorRef === "slack" && permission === "chat:write") {
|
|
3102
3128
|
console.log("");
|
|
3103
3129
|
console.log(
|
|
3104
3130
|
"IMPORTANT: Granting chat:write allows sending messages AS THE USER's identity, not as a bot."
|
|
@@ -3107,11 +3133,11 @@ async function outputPermissionChangeMessage(connectorRef, permission, action, r
|
|
|
3107
3133
|
"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."
|
|
3108
3134
|
);
|
|
3109
3135
|
console.log(
|
|
3110
|
-
|
|
3136
|
+
`${approvalWording} if acting as the user is specifically required.`
|
|
3111
3137
|
);
|
|
3112
3138
|
console.log("");
|
|
3113
3139
|
}
|
|
3114
|
-
if (connectorRef === "gmail" && permission === "gmail.send"
|
|
3140
|
+
if (connectorRef === "gmail" && permission === "gmail.send") {
|
|
3115
3141
|
console.log("");
|
|
3116
3142
|
console.log(
|
|
3117
3143
|
"IMPORTANT: Granting gmail.send allows the agent to send emails directly as the user."
|
|
@@ -3120,51 +3146,98 @@ async function outputPermissionChangeMessage(connectorRef, permission, action, r
|
|
|
3120
3146
|
"Consider keeping gmail.send disabled and using gmail.compose instead \u2014 the agent can create drafts for the user to review and send manually."
|
|
3121
3147
|
);
|
|
3122
3148
|
console.log(
|
|
3123
|
-
|
|
3149
|
+
`${approvalWording} if direct sending is specifically required.`
|
|
3124
3150
|
);
|
|
3125
3151
|
console.log("");
|
|
3126
3152
|
}
|
|
3127
|
-
|
|
3153
|
+
}
|
|
3154
|
+
function printPermissionActionMessage(args) {
|
|
3155
|
+
if (args.usesUserGrants) {
|
|
3156
|
+
const grantAction = args.action === "enable" ? "allow" : "deny";
|
|
3128
3157
|
console.log(
|
|
3129
|
-
`You can ${
|
|
3158
|
+
`You can ${grantAction} the "${args.permission}" permission for your connector access: [Manage ${args.label} permissions](${args.url})`
|
|
3130
3159
|
);
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
)
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
if (args.role === "admin" || args.role === "owner") {
|
|
3163
|
+
console.log(
|
|
3164
|
+
`You can ${args.action} the "${args.permission}" permission directly: [Manage ${args.label} permissions](${args.url})`
|
|
3165
|
+
);
|
|
3166
|
+
return;
|
|
3167
|
+
}
|
|
3168
|
+
if (args.role !== "member") {
|
|
3169
|
+
console.log(
|
|
3170
|
+
`To ${args.action} the "${args.permission}" permission for ${args.label}: [Manage ${args.label} permissions](${args.url})`
|
|
3171
|
+
);
|
|
3172
|
+
return;
|
|
3173
|
+
}
|
|
3174
|
+
if (!args.reason) {
|
|
3146
3175
|
console.log(
|
|
3147
|
-
`
|
|
3176
|
+
`IMPORTANT: Re-run with \`--reason "one sentence why this is needed"\` so the admin can review your request faster.`
|
|
3148
3177
|
);
|
|
3178
|
+
return;
|
|
3149
3179
|
}
|
|
3180
|
+
if (args.action === "enable") {
|
|
3181
|
+
console.log(
|
|
3182
|
+
`Permission changes require admin approval. Request access at: [Request ${args.label} access](${args.url})`
|
|
3183
|
+
);
|
|
3184
|
+
return;
|
|
3185
|
+
}
|
|
3186
|
+
console.log(
|
|
3187
|
+
`Permission changes require admin approval. Contact an org admin to disable this permission: [View ${args.label} permissions](${args.url})`
|
|
3188
|
+
);
|
|
3189
|
+
}
|
|
3190
|
+
async function outputPermissionChangeMessage(connectorRef, permission, action, reason) {
|
|
3191
|
+
const { label } = CONNECTOR_TYPES[connectorRef];
|
|
3192
|
+
const platformOrigin = await getPlatformOrigin();
|
|
3193
|
+
const agentId = process.env.ZERO_AGENT_ID;
|
|
3194
|
+
const context = await resolvePermissionChangeContext(agentId || void 0);
|
|
3195
|
+
const role = context.role;
|
|
3196
|
+
const permissionGrantMode = context.permissionGrantMode;
|
|
3197
|
+
const usesUserGrants = permissionGrantMode === "user-grants";
|
|
3198
|
+
const urlParams = new URLSearchParams({
|
|
3199
|
+
ref: connectorRef,
|
|
3200
|
+
permission,
|
|
3201
|
+
action: action === "enable" ? "allow" : "deny"
|
|
3202
|
+
});
|
|
3203
|
+
addReasonParam(urlParams, role, usesUserGrants, reason);
|
|
3204
|
+
const pagePath = agentId ? `/agents/${agentId}/permissions` : "/agents";
|
|
3205
|
+
const url = `${platformOrigin}${pagePath}?${urlParams.toString()}`;
|
|
3206
|
+
printSensitivePermissionGuidance(
|
|
3207
|
+
connectorRef,
|
|
3208
|
+
permission,
|
|
3209
|
+
action,
|
|
3210
|
+
usesUserGrants
|
|
3211
|
+
);
|
|
3212
|
+
printPermissionActionMessage({
|
|
3213
|
+
usesUserGrants,
|
|
3214
|
+
action,
|
|
3215
|
+
role,
|
|
3216
|
+
permission,
|
|
3217
|
+
label,
|
|
3218
|
+
url,
|
|
3219
|
+
reason
|
|
3220
|
+
});
|
|
3150
3221
|
}
|
|
3151
|
-
var permissionChangeCommand = new Command().name("permission-change").description("
|
|
3222
|
+
var permissionChangeCommand = new Command().name("permission-change").description("Change or request a permission (enable or disable)").argument("<connector-ref>", "The connector type (e.g. github)").addOption(
|
|
3152
3223
|
new Option(
|
|
3153
3224
|
"--permission <name>",
|
|
3154
3225
|
"The permission name to change"
|
|
3155
3226
|
).makeOptionMandatory()
|
|
3156
3227
|
).addOption(
|
|
3157
|
-
new Option(
|
|
3158
|
-
"
|
|
3159
|
-
|
|
3228
|
+
new Option(
|
|
3229
|
+
"--enable",
|
|
3230
|
+
"Enable or request enabling the permission"
|
|
3231
|
+
).conflicts("disable")
|
|
3160
3232
|
).addOption(
|
|
3161
|
-
new Option(
|
|
3162
|
-
"
|
|
3163
|
-
|
|
3233
|
+
new Option(
|
|
3234
|
+
"--disable",
|
|
3235
|
+
"Disable or request disabling the permission"
|
|
3236
|
+
).conflicts("enable")
|
|
3164
3237
|
).addOption(
|
|
3165
3238
|
new Option(
|
|
3166
3239
|
"--reason <text>",
|
|
3167
|
-
"Brief reason
|
|
3240
|
+
"Brief reason for admin approval requests (max 500 chars)"
|
|
3168
3241
|
)
|
|
3169
3242
|
).addHelpText(
|
|
3170
3243
|
"after",
|
|
@@ -3175,7 +3248,7 @@ Examples:
|
|
|
3175
3248
|
|
|
3176
3249
|
Notes:
|
|
3177
3250
|
- Outputs a platform URL for the user to adjust the permission
|
|
3178
|
-
-
|
|
3251
|
+
- Depending on rollout state, members either request approval or manage their own permission grants`
|
|
3179
3252
|
).action(
|
|
3180
3253
|
withErrorHandler(
|
|
3181
3254
|
async (connectorRef, opts) => {
|
|
@@ -4429,7 +4502,7 @@ var listCommand8 = new Command().name("list").alias("ls").description("List all
|
|
|
4429
4502
|
if (secret.type === "model-provider") {
|
|
4430
4503
|
typeIndicator = source_default.dim(" [model-provider]");
|
|
4431
4504
|
} else if (secret.type === "connector") {
|
|
4432
|
-
const derived =
|
|
4505
|
+
const derived = getConnectorStoredSecretDisplayInfo(secret.name);
|
|
4433
4506
|
if (derived) {
|
|
4434
4507
|
typeIndicator = source_default.dim(` [${derived.connectorLabel} connector]`);
|
|
4435
4508
|
derivedLine = source_default.dim(
|
|
@@ -4439,7 +4512,7 @@ var listCommand8 = new Command().name("list").alias("ls").description("List all
|
|
|
4439
4512
|
typeIndicator = source_default.dim(" [connector]");
|
|
4440
4513
|
}
|
|
4441
4514
|
} else if (secret.type === "user") {
|
|
4442
|
-
const derived =
|
|
4515
|
+
const derived = getConnectorStoredSecretDisplayInfo(secret.name);
|
|
4443
4516
|
if (derived) {
|
|
4444
4517
|
typeIndicator = source_default.dim(` [${derived.connectorLabel} connector]`);
|
|
4445
4518
|
derivedLine = source_default.dim(
|
|
@@ -9929,6 +10002,30 @@ var RESOURCE_REGISTRY = [
|
|
|
9929
10002
|
path: "illustration-template/iberian-vignette"
|
|
9930
10003
|
}
|
|
9931
10004
|
},
|
|
10005
|
+
{
|
|
10006
|
+
id: "image-style:cozy-parlor",
|
|
10007
|
+
kind: "image-style",
|
|
10008
|
+
name: "Cozy Parlor",
|
|
10009
|
+
description: "Hand-painted watercolor + ink-line scene \u2014 one anthropomorphic animal in a quiet domestic interior, clean cool-white paper, neutral palette with one hot accent pop.",
|
|
10010
|
+
desc: "Hand-painted watercolor + brushy black ink line on clean cool-white paper (no amber tint). ONE anthropomorphic animal mid-quiet-activity in a domestic interior. Closed-crescent-eye smile, minimal facial features, expression through posture. At least two patterned surfaces per piece. Cool/neutral palette lead (sage, slate-blue, cornflower, lavender, mint, dove-gray) with a single hot accent pop (cherry-red, mustard, magenta-pink) on one object. Six dials per brief \u2014 cast, activity, palette family, pattern motif stack, hot accent object, and complexity (L1/L2/L3). Trigger when user says /cozy-parlor, asks for a 'cozy parlor illustration', a 'watercolor animal scene', a 'picture-book interior', or a new piece in this neutral-palette watercolor style.",
|
|
10011
|
+
source: {
|
|
10012
|
+
repo: VM0_SKILLS_REPO,
|
|
10013
|
+
ref: VM0_SKILLS_REF,
|
|
10014
|
+
path: "illustration-template/cozy-parlor"
|
|
10015
|
+
}
|
|
10016
|
+
},
|
|
10017
|
+
{
|
|
10018
|
+
id: "image-style:crowd-ink",
|
|
10019
|
+
kind: "image-style",
|
|
10020
|
+
name: "Crowd Ink",
|
|
10021
|
+
description: "Hand-drawn editorial crowd illustration \u2014 sketchy black ink contours over flat 3-color spot fills on pure white, scene-as-metaphor composition.",
|
|
10022
|
+
desc: 'Hand-drawn editorial crowd illustration style \u2014 confident sketchy black ink contour lines with slightly irregular weight, flat 3-color spot fills sitting under or beside the ink lines (edges allowed to misregister slightly), on a PURE WHITE background (never cream). Fine-line backdrop drawn lighter than the foreground figures, scattered atmospheric marks in negative space (birds / leaves / steam / confetti / dots), and a scene-as-metaphor composition with a cast that varies per piece. Six dials per brief \u2014 palette (tested families: urban editorial / cool transit / warm natural / cozy interior), scene metaphor, complexity (L2 small group of 3\u20135 / L3 full crowd of 8\u201310), cast, backdrop, atmospheric motif. Trigger when the user says /crowd-ink, asks for a "crowd-ink illustration", "editorial crowd scene", "hand-drawn ink-and-spot-color illustration", "New-Yorker-style crowd vignette", or briefs with palette + scene metaphor + complexity level.',
|
|
10023
|
+
source: {
|
|
10024
|
+
repo: VM0_SKILLS_REPO,
|
|
10025
|
+
ref: VM0_SKILLS_REF,
|
|
10026
|
+
path: "illustration-template/crowd-ink"
|
|
10027
|
+
}
|
|
10028
|
+
},
|
|
9932
10029
|
{
|
|
9933
10030
|
id: "image-style:ink-storefront",
|
|
9934
10031
|
kind: "image-style",
|
|
@@ -12982,6 +13079,99 @@ Notes:
|
|
|
12982
13079
|
- Use --fields essentials for place details unless pro fields are required`
|
|
12983
13080
|
);
|
|
12984
13081
|
|
|
13082
|
+
// src/commands/zero/banking/index.ts
|
|
13083
|
+
init_esm_shims();
|
|
13084
|
+
function parseLimit5(value) {
|
|
13085
|
+
const parsed = Number(value);
|
|
13086
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 1e3) {
|
|
13087
|
+
throw new InvalidArgumentError("limit must be between 1 and 1000");
|
|
13088
|
+
}
|
|
13089
|
+
return parsed;
|
|
13090
|
+
}
|
|
13091
|
+
function parseDateOnly(value) {
|
|
13092
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
13093
|
+
throw new InvalidArgumentError("date must be formatted as YYYY-MM-DD");
|
|
13094
|
+
}
|
|
13095
|
+
return value;
|
|
13096
|
+
}
|
|
13097
|
+
function renderBankingResponse(label, response) {
|
|
13098
|
+
console.log(source_default.green(`\u2713 ${label}`));
|
|
13099
|
+
console.log(source_default.dim(` Provider: ${response.provider}`));
|
|
13100
|
+
if (response.accounts) {
|
|
13101
|
+
console.log(JSON.stringify(response.accounts, null, 2));
|
|
13102
|
+
return;
|
|
13103
|
+
}
|
|
13104
|
+
if (response.balance) {
|
|
13105
|
+
console.log(JSON.stringify(response.balance, null, 2));
|
|
13106
|
+
return;
|
|
13107
|
+
}
|
|
13108
|
+
console.log(JSON.stringify(response.transactions ?? [], null, 2));
|
|
13109
|
+
}
|
|
13110
|
+
async function runBankingRequest(label, operation, payload, options) {
|
|
13111
|
+
const response = await callZeroBanking(operation, payload);
|
|
13112
|
+
if (options.json) {
|
|
13113
|
+
console.log(JSON.stringify(response));
|
|
13114
|
+
return;
|
|
13115
|
+
}
|
|
13116
|
+
renderBankingResponse(label, response);
|
|
13117
|
+
}
|
|
13118
|
+
var accountsCommand = new Command().name("accounts").description("List enabled banking accounts").option("--json", "Print the raw banking response as JSON").action(
|
|
13119
|
+
withErrorHandler(async (options) => {
|
|
13120
|
+
await runBankingRequest(
|
|
13121
|
+
"Banking accounts loaded",
|
|
13122
|
+
"accounts",
|
|
13123
|
+
{},
|
|
13124
|
+
options
|
|
13125
|
+
);
|
|
13126
|
+
})
|
|
13127
|
+
);
|
|
13128
|
+
var balancesCommand = new Command().name("balances").description("Read an enabled account balance").requiredOption("--account-id <id>", "Enabled provider account ID").option("--json", "Print the raw banking response as JSON").action(
|
|
13129
|
+
withErrorHandler(async (options) => {
|
|
13130
|
+
await runBankingRequest(
|
|
13131
|
+
"Banking balance loaded",
|
|
13132
|
+
"balances",
|
|
13133
|
+
{ accountId: options.accountId },
|
|
13134
|
+
options
|
|
13135
|
+
);
|
|
13136
|
+
})
|
|
13137
|
+
);
|
|
13138
|
+
var transactionsCommand = new Command().name("transactions").description("Read transactions for an enabled account").requiredOption("--account-id <id>", "Enabled provider account ID").requiredOption(
|
|
13139
|
+
"--from <date>",
|
|
13140
|
+
"Start date, formatted as YYYY-MM-DD",
|
|
13141
|
+
parseDateOnly
|
|
13142
|
+
).requiredOption(
|
|
13143
|
+
"--to <date>",
|
|
13144
|
+
"End date, formatted as YYYY-MM-DD",
|
|
13145
|
+
parseDateOnly
|
|
13146
|
+
).option("--limit <n>", "Maximum transactions to return", parseLimit5, 100).option("--json", "Print the raw banking response as JSON").action(
|
|
13147
|
+
withErrorHandler(async (options) => {
|
|
13148
|
+
await runBankingRequest(
|
|
13149
|
+
"Banking transactions loaded",
|
|
13150
|
+
"transactions",
|
|
13151
|
+
{
|
|
13152
|
+
accountId: options.accountId,
|
|
13153
|
+
from: options.from,
|
|
13154
|
+
to: options.to,
|
|
13155
|
+
limit: options.limit
|
|
13156
|
+
},
|
|
13157
|
+
options
|
|
13158
|
+
);
|
|
13159
|
+
})
|
|
13160
|
+
);
|
|
13161
|
+
var zeroBankingCommand = new Command().name("banking").description("Use managed zero banking services").addCommand(accountsCommand).addCommand(balancesCommand).addCommand(transactionsCommand).addHelpText(
|
|
13162
|
+
"after",
|
|
13163
|
+
`
|
|
13164
|
+
Examples:
|
|
13165
|
+
List accounts: zero banking accounts --json
|
|
13166
|
+
Get balance: zero banking balances --account-id <id> --json
|
|
13167
|
+
Get transactions: zero banking transactions --account-id <id> --from 2026-01-01 --to 2026-01-31 --json
|
|
13168
|
+
|
|
13169
|
+
Notes:
|
|
13170
|
+
- Authenticates via ZERO_TOKEN (requires banking:read capability)
|
|
13171
|
+
- Finicity credentials and app tokens stay on the vm0 API server
|
|
13172
|
+
- Access is limited to accounts enabled for the current agent`
|
|
13173
|
+
);
|
|
13174
|
+
|
|
12985
13175
|
// src/commands/zero/model/index.ts
|
|
12986
13176
|
init_esm_shims();
|
|
12987
13177
|
|
|
@@ -13141,7 +13331,8 @@ var COMMAND_CAPABILITY_MAP = {
|
|
|
13141
13331
|
generate: null,
|
|
13142
13332
|
web: null,
|
|
13143
13333
|
host: "host:write",
|
|
13144
|
-
maps: "maps:read"
|
|
13334
|
+
maps: "maps:read",
|
|
13335
|
+
banking: "banking:read"
|
|
13145
13336
|
};
|
|
13146
13337
|
var DEFAULT_COMMANDS = [
|
|
13147
13338
|
zeroOrgCommand,
|
|
@@ -13170,7 +13361,8 @@ var DEFAULT_COMMANDS = [
|
|
|
13170
13361
|
generateCommand,
|
|
13171
13362
|
zeroWebCommand,
|
|
13172
13363
|
zeroHostCommand,
|
|
13173
|
-
zeroMapsCommand
|
|
13364
|
+
zeroMapsCommand,
|
|
13365
|
+
zeroBankingCommand
|
|
13174
13366
|
];
|
|
13175
13367
|
function shouldHideCommand(name, payload) {
|
|
13176
13368
|
if (!payload) return false;
|
|
@@ -13212,6 +13404,7 @@ function buildZeroHelpText(payload = decodeZeroTokenPayload()) {
|
|
|
13212
13404
|
...shouldHideCommand("maps", payload) ? [] : [
|
|
13213
13405
|
' Get directions? zero maps directions --origin "SFO" --destination "Mountain View" --json'
|
|
13214
13406
|
],
|
|
13407
|
+
...shouldHideCommand("banking", payload) ? [] : [" Read bank data? zero banking accounts --json"],
|
|
13215
13408
|
" Check your identity? zero whoami"
|
|
13216
13409
|
];
|
|
13217
13410
|
return `
|
|
@@ -13229,7 +13422,7 @@ function registerZeroCommands(prog, commands) {
|
|
|
13229
13422
|
var program = new Command();
|
|
13230
13423
|
program.name("zero").description(
|
|
13231
13424
|
"Zero CLI \u2014 interact with the zero platform from inside the sandbox"
|
|
13232
|
-
).version("9.
|
|
13425
|
+
).version("9.179.0").addHelpText("after", () => {
|
|
13233
13426
|
return buildZeroHelpText();
|
|
13234
13427
|
});
|
|
13235
13428
|
if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {
|