@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vm0/cli",
3
- "version": "9.177.19",
3
+ "version": "9.179.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
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
- getConnectorTypeForSecretName,
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-4ILTCW7H.js";
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
- connectorType = getConnectorTypeForSecretName(
2909
- envName = opts.envName
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 request this permission, run: zero doctor permission-change ${connectorRef} --permission ${permission} --enable --reason "why this is needed"`
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
- async function outputPermissionChangeMessage(connectorRef, permission, action, reason) {
3086
- const { label } = CONNECTOR_TYPES[connectorRef];
3087
- const platformOrigin = await getPlatformOrigin();
3088
- const agentId = process.env.ZERO_AGENT_ID;
3089
- const role = agentId ? await resolveAgentRole(agentId) : "unknown";
3090
- const urlParams = new URLSearchParams({
3091
- ref: connectorRef,
3092
- permission,
3093
- action: action === "enable" ? "allow" : "deny"
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
- "Only request user approval below if acting as the user is specifically required."
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" && action === "enable") {
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
- "Only request user approval below if direct sending is specifically required."
3149
+ `${approvalWording} if direct sending is specifically required.`
3124
3150
  );
3125
3151
  console.log("");
3126
3152
  }
3127
- if (role === "admin" || role === "owner") {
3153
+ }
3154
+ function printPermissionActionMessage(args) {
3155
+ if (args.usesUserGrants) {
3156
+ const grantAction = args.action === "enable" ? "allow" : "deny";
3128
3157
  console.log(
3129
- `You can ${action} the "${permission}" permission directly: [Manage ${label} permissions](${url})`
3158
+ `You can ${grantAction} the "${args.permission}" permission for your connector access: [Manage ${args.label} permissions](${args.url})`
3130
3159
  );
3131
- } else if (role === "member") {
3132
- if (!reason) {
3133
- console.log(
3134
- `IMPORTANT: Re-run with \`--reason "one sentence why this is needed"\` so the admin can review your request faster.`
3135
- );
3136
- } else if (action === "enable") {
3137
- console.log(
3138
- `Permission changes require admin approval. Request access at: [Request ${label} access](${url})`
3139
- );
3140
- } else {
3141
- console.log(
3142
- `Permission changes require admin approval. Contact an org admin to disable this permission: [View ${label} permissions](${url})`
3143
- );
3144
- }
3145
- } else {
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
- `To ${action} the "${permission}" permission for ${label}: [Manage ${label} permissions](${url})`
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("Request a permission change (enable or disable)").argument("<connector-ref>", "The connector type (e.g. github)").addOption(
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("--enable", "Request to enable the permission").conflicts(
3158
- "disable"
3159
- )
3228
+ new Option(
3229
+ "--enable",
3230
+ "Enable or request enabling the permission"
3231
+ ).conflicts("disable")
3160
3232
  ).addOption(
3161
- new Option("--disable", "Request to disable the permission").conflicts(
3162
- "enable"
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 why the permission is needed (max 500 chars)"
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
- - Admins can change permissions directly; members must request approval`
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 = getConnectorEnvNamesForSecret(secret.name);
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 = getConnectorEnvNamesForSecret(secret.name);
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.177.19").addHelpText("after", () => {
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")) {