@vm0/cli 9.129.2 → 9.131.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.129.2",
3
+ "version": "9.131.0",
4
4
  "description": "CLI application",
5
5
  "repository": {
6
6
  "type": "git",
package/zero.js CHANGED
@@ -130,7 +130,7 @@ import {
130
130
  upsertZeroOrgModelProvider,
131
131
  withErrorHandler,
132
132
  zeroAgentCustomSkillNameSchema
133
- } from "./chunk-F23UIP5L.js";
133
+ } from "./chunk-65M57PU6.js";
134
134
  import {
135
135
  __toESM,
136
136
  init_esm_shims
@@ -1167,17 +1167,210 @@ init_esm_shims();
1167
1167
  // src/commands/zero/agent/create.ts
1168
1168
  init_esm_shims();
1169
1169
  import { readFileSync } from "fs";
1170
+
1171
+ // src/commands/zero/agent/avatar.ts
1172
+ init_esm_shims();
1173
+ var SKIN_MAP = {
1174
+ light: 0,
1175
+ "light-medium": 1,
1176
+ medium: 2,
1177
+ "medium-dark": 3,
1178
+ dark: 4
1179
+ };
1180
+ var HAIR_COLOR_MAP = {
1181
+ blonde: 1,
1182
+ teal: 2,
1183
+ grey: 3,
1184
+ pink: 4,
1185
+ brown: 5
1186
+ };
1187
+ var EXPRESSION_MAP = {
1188
+ calm: 1,
1189
+ content: 2,
1190
+ neutral: 3,
1191
+ pleasant: 4,
1192
+ excited: 5
1193
+ };
1194
+ var INTENSITY_MAP = {
1195
+ chill: "d",
1196
+ normal: "m",
1197
+ hyped: "h"
1198
+ };
1199
+ function lookupRequired(value, map, flag) {
1200
+ if (!(value in map)) {
1201
+ throw new Error(
1202
+ `Invalid ${flag} "${value}". Must be one of: ${Object.keys(map).join(", ")}`
1203
+ );
1204
+ }
1205
+ return map[value];
1206
+ }
1207
+ function parseIntRange(value, flag, min, max) {
1208
+ const n = Number(value);
1209
+ if (!Number.isInteger(n) || n < min || n > max) {
1210
+ throw new Error(`Invalid ${flag} "${value}". Must be ${min}\u2013${max}`);
1211
+ }
1212
+ return n;
1213
+ }
1214
+ function buildCustomSvgAvatar(opts) {
1215
+ const r = opts.avatarRotation !== void 0 ? parseIntRange(opts.avatarRotation, "--avatar-rotation", 1, 5) : 3;
1216
+ const h = opts.avatarHairStyle !== void 0 ? parseIntRange(opts.avatarHairStyle, "--avatar-hair-style", 1, 5) : 1;
1217
+ const s = opts.avatarSkin !== void 0 ? lookupRequired(opts.avatarSkin, SKIN_MAP, "--avatar-skin") : 2;
1218
+ const c = opts.avatarHairColor !== void 0 ? lookupRequired(
1219
+ opts.avatarHairColor,
1220
+ HAIR_COLOR_MAP,
1221
+ "--avatar-hair-color"
1222
+ ) : 5;
1223
+ const f = opts.avatarExpression !== void 0 ? lookupRequired(
1224
+ opts.avatarExpression,
1225
+ EXPRESSION_MAP,
1226
+ "--avatar-expression"
1227
+ ) : 1;
1228
+ const i = opts.avatarIntensity !== void 0 ? lookupRequired(
1229
+ opts.avatarIntensity,
1230
+ INTENSITY_MAP,
1231
+ "--avatar-intensity"
1232
+ ) : "m";
1233
+ return `svg:r${r}s${s}h${h}c${c}f${f}${i}`;
1234
+ }
1235
+ function resolveAvatarUrl(opts) {
1236
+ const hasPreset = opts.avatar !== void 0;
1237
+ const hasCustom = opts.avatarRotation !== void 0 || opts.avatarSkin !== void 0 || opts.avatarHairStyle !== void 0 || opts.avatarHairColor !== void 0 || opts.avatarExpression !== void 0 || opts.avatarIntensity !== void 0;
1238
+ if (!hasPreset && !hasCustom) return void 0;
1239
+ if (hasPreset && hasCustom) {
1240
+ throw new Error(
1241
+ "--avatar cannot be combined with --avatar-* attribute options"
1242
+ );
1243
+ }
1244
+ if (hasPreset) {
1245
+ if (!/^preset:[0-4]$/.test(opts.avatar)) {
1246
+ throw new Error(
1247
+ `Invalid --avatar "${opts.avatar}". Use preset:0 through preset:4`
1248
+ );
1249
+ }
1250
+ return opts.avatar;
1251
+ }
1252
+ return buildCustomSvgAvatar(opts);
1253
+ }
1254
+ var REVERSE_SKIN_MAP = {
1255
+ 0: "light",
1256
+ 1: "light-medium",
1257
+ 2: "medium",
1258
+ 3: "medium-dark",
1259
+ 4: "dark"
1260
+ };
1261
+ var REVERSE_HAIR_COLOR_MAP = {
1262
+ 1: "blonde",
1263
+ 2: "teal",
1264
+ 3: "grey",
1265
+ 4: "pink",
1266
+ 5: "brown"
1267
+ };
1268
+ var REVERSE_EXPRESSION_MAP = {
1269
+ 1: "calm",
1270
+ 2: "content",
1271
+ 3: "neutral",
1272
+ 4: "pleasant",
1273
+ 5: "excited"
1274
+ };
1275
+ var REVERSE_INTENSITY_MAP = {
1276
+ d: "chill",
1277
+ m: "normal",
1278
+ h: "hyped"
1279
+ };
1280
+ var PRESET_DESCRIPTIONS = {
1281
+ "preset:0": "light skin, brown hair, calm, hyped",
1282
+ "preset:1": "light-medium skin, grey hair, calm, normal",
1283
+ "preset:2": "medium skin, pink hair, neutral, chill",
1284
+ "preset:3": "medium-dark skin, blonde hair, pleasant, hyped",
1285
+ "preset:4": "dark skin, teal hair, excited, normal"
1286
+ };
1287
+ function parseSvgAvatar(svg) {
1288
+ const match = svg.match(/^svg:r(\d)s(\d)h(\d)c(\d)f(\d)([dmh])$/);
1289
+ if (!match) return void 0;
1290
+ const [, r, s, h, c, f, i] = match;
1291
+ const parts = [];
1292
+ const skin = REVERSE_SKIN_MAP[Number(s)];
1293
+ if (skin) parts.push(`${skin} skin`);
1294
+ const hairColor = REVERSE_HAIR_COLOR_MAP[Number(c)];
1295
+ if (hairColor) parts.push(`${hairColor} hair`);
1296
+ const expression = REVERSE_EXPRESSION_MAP[Number(f)];
1297
+ if (expression) parts.push(expression);
1298
+ const intensity = REVERSE_INTENSITY_MAP[i];
1299
+ if (intensity) parts.push(intensity);
1300
+ if (parts.length === 0) return void 0;
1301
+ let desc = parts.join(", ");
1302
+ if (r !== "3") {
1303
+ const rotationLabels = {
1304
+ "1": "far-left",
1305
+ "2": "left",
1306
+ "4": "right",
1307
+ "5": "far-right"
1308
+ };
1309
+ const rot = rotationLabels[r];
1310
+ if (rot) desc += `, ${rot}`;
1311
+ }
1312
+ if (h !== "1") {
1313
+ desc += `, hair style ${h}`;
1314
+ }
1315
+ return desc;
1316
+ }
1317
+ function formatAvatar(avatarUrl) {
1318
+ if (!avatarUrl) return void 0;
1319
+ if (avatarUrl.startsWith("preset:")) {
1320
+ const desc = PRESET_DESCRIPTIONS[avatarUrl];
1321
+ return desc ? `${avatarUrl} (${desc})` : avatarUrl;
1322
+ }
1323
+ if (avatarUrl.startsWith("svg:")) {
1324
+ const desc = parseSvgAvatar(avatarUrl);
1325
+ return desc ? `custom (${desc})` : avatarUrl;
1326
+ }
1327
+ return avatarUrl;
1328
+ }
1329
+
1330
+ // src/commands/zero/agent/create.ts
1170
1331
  var createCommand = new Command().name("create").description("Create a new zero agent").option(
1171
1332
  "--skills <items>",
1172
1333
  "Comma-separated custom skill names to attach (e.g. my-skill,other-skill)"
1173
1334
  ).option("--display-name <name>", "Agent display name").option("--description <text>", "Agent description").option(
1174
1335
  "--sound <tone>",
1175
1336
  "Agent tone: professional, friendly, direct, supportive"
1176
- ).option("--instructions-file <path>", "Path to instructions file").addHelpText(
1337
+ ).option("--avatar <preset>", "Avatar preset: preset:0 through preset:4").option(
1338
+ "--avatar-rotation <1-5>",
1339
+ "Head angle: 1=far-left 3=center 5=far-right"
1340
+ ).option(
1341
+ "--avatar-skin <tone>",
1342
+ "Skin tone: light | light-medium | medium | medium-dark | dark"
1343
+ ).option("--avatar-hair-style <1-5>", "Hair style: 1\u20135").option(
1344
+ "--avatar-hair-color <color>",
1345
+ "Hair color: blonde | teal | grey | pink | brown"
1346
+ ).option(
1347
+ "--avatar-expression <expr>",
1348
+ "Expression: calm | content | neutral | pleasant | excited"
1349
+ ).option("--avatar-intensity <level>", "Intensity: chill | normal | hyped").option("--instructions-file <path>", "Path to instructions file").addHelpText(
1177
1350
  "after",
1178
1351
  `
1352
+ Avatar:
1353
+ Quick presets (--avatar):
1354
+ preset:0 light skin, brown hair, calm, hyped
1355
+ preset:1 light-medium skin, grey hair, calm, normal
1356
+ preset:2 medium skin, pink hair, neutral, chill
1357
+ preset:3 medium-dark skin, blonde hair, pleasant, hyped
1358
+ preset:4 dark skin, teal hair, excited, normal
1359
+
1360
+ Custom attributes (--avatar-* flags, omitted fields use defaults):
1361
+ --avatar-rotation 1=far-left 3=center(default) 5=far-right
1362
+ --avatar-skin light / light-medium / medium(default) / medium-dark / dark
1363
+ --avatar-hair-style 1\u20135 (default: 1)
1364
+ --avatar-hair-color blonde / teal / grey / pink / brown(default)
1365
+ --avatar-expression calm(default) / content / neutral / pleasant / excited
1366
+ --avatar-intensity chill / normal(default) / hyped
1367
+
1368
+ Note: --avatar and --avatar-* cannot be used together.
1369
+
1179
1370
  Examples:
1180
1371
  Minimal: zero agent create --display-name "My Agent"
1372
+ Quick preset: zero agent create --display-name "My Agent" --avatar preset:2
1373
+ Custom avatar: zero agent create --display-name "My Agent" --avatar-skin dark --avatar-hair-color teal --avatar-intensity hyped
1181
1374
  With skills: zero agent create --skills my-skill,other-skill --display-name "My Agent"
1182
1375
  With instructions: zero agent create --display-name "My Agent" --instructions-file ./instructions.md`
1183
1376
  ).action(
@@ -1196,10 +1389,12 @@ Examples:
1196
1389
  }
1197
1390
  }
1198
1391
  }
1392
+ const avatarUrl = resolveAvatarUrl(options);
1199
1393
  const agent = await createZeroAgent({
1200
1394
  displayName: options.displayName,
1201
1395
  description: options.description,
1202
1396
  sound: options.sound,
1397
+ avatarUrl,
1203
1398
  customSkills
1204
1399
  });
1205
1400
  if (options.instructionsFile) {
@@ -1233,18 +1428,25 @@ Examples:
1233
1428
  // src/commands/zero/agent/edit.ts
1234
1429
  init_esm_shims();
1235
1430
  import { readFileSync as readFileSync2 } from "fs";
1431
+ function hasAvatarUpdate(options) {
1432
+ return options.avatar !== void 0 || options.avatarRotation !== void 0 || options.avatarSkin !== void 0 || options.avatarHairStyle !== void 0 || options.avatarHairColor !== void 0 || options.avatarExpression !== void 0 || options.avatarIntensity !== void 0;
1433
+ }
1236
1434
  function hasAgentFieldUpdate(options) {
1237
- return options.displayName !== void 0 || options.description !== void 0 || options.sound !== void 0 || options.skills !== void 0 || options.addSkill !== void 0 || options.removeSkill !== void 0 || options.modelProvider !== void 0 || options.model !== void 0;
1435
+ return options.displayName !== void 0 || options.description !== void 0 || options.sound !== void 0 || hasAvatarUpdate(options) || options.skills !== void 0 || options.addSkill !== void 0 || options.removeSkill !== void 0 || options.modelProvider !== void 0 || options.model !== void 0;
1238
1436
  }
1239
1437
  async function applyAgentUpdate(agentId, options) {
1438
+ const hasAvatar = hasAvatarUpdate(options);
1439
+ const resolvedAvatarUrl = hasAvatar ? resolveAvatarUrl(options) : void 0;
1240
1440
  const current = await getZeroAgent(agentId);
1241
1441
  const customSkills = resolveCustomSkills(options, current.customSkills ?? []);
1242
1442
  const modelProviderId = options.modelProvider !== void 0 ? parseModelFlag(options.modelProvider) : current.modelProviderId;
1243
1443
  const selectedModel = options.model !== void 0 ? parseModelFlag(options.model) : current.selectedModel;
1444
+ const avatarUrl = hasAvatar ? resolvedAvatarUrl : current.avatarUrl ?? void 0;
1244
1445
  await updateZeroAgent(agentId, {
1245
1446
  displayName: options.displayName !== void 0 ? options.displayName : current.displayName ?? void 0,
1246
1447
  description: options.description !== void 0 ? options.description : current.description ?? void 0,
1247
1448
  sound: options.sound !== void 0 ? options.sound : current.sound ?? void 0,
1449
+ avatarUrl,
1248
1450
  customSkills,
1249
1451
  modelProviderId,
1250
1452
  selectedModel
@@ -1295,7 +1497,19 @@ function resolveCustomSkills(options, existing) {
1295
1497
  var editCommand = new Command().name("edit").description("Edit a zero agent").argument("<agent-id>", "Agent ID").option("--display-name <name>", "New display name").option("--description <text>", "New description").option(
1296
1498
  "--sound <tone>",
1297
1499
  "New tone: professional, friendly, direct, supportive"
1500
+ ).option("--avatar <preset>", "Avatar preset: preset:0 through preset:4").option(
1501
+ "--avatar-rotation <1-5>",
1502
+ "Head angle: 1=far-left 3=center 5=far-right"
1298
1503
  ).option(
1504
+ "--avatar-skin <tone>",
1505
+ "Skin tone: light | light-medium | medium | medium-dark | dark"
1506
+ ).option("--avatar-hair-style <1-5>", "Hair style: 1\u20135").option(
1507
+ "--avatar-hair-color <color>",
1508
+ "Hair color: blonde | teal | grey | pink | brown"
1509
+ ).option(
1510
+ "--avatar-expression <expr>",
1511
+ "Expression: calm | content | neutral | pleasant | excited"
1512
+ ).option("--avatar-intensity <level>", "Intensity: chill | normal | hyped").option(
1299
1513
  "--skills <items>",
1300
1514
  "Comma-separated custom skill names to attach (replaces existing)"
1301
1515
  ).option("--add-skill <name>", "Add a custom skill to the agent").option("--remove-skill <name>", "Remove a custom skill from the agent").option("--instructions-file <path>", "Path to new instructions file").option(
@@ -1307,9 +1521,29 @@ var editCommand = new Command().name("edit").description("Edit a zero agent").ar
1307
1521
  ).addHelpText(
1308
1522
  "after",
1309
1523
  `
1524
+ Avatar:
1525
+ Quick presets (--avatar):
1526
+ preset:0 light skin, brown hair, calm, hyped
1527
+ preset:1 light-medium skin, grey hair, calm, normal
1528
+ preset:2 medium skin, pink hair, neutral, chill
1529
+ preset:3 medium-dark skin, blonde hair, pleasant, hyped
1530
+ preset:4 dark skin, teal hair, excited, normal
1531
+
1532
+ Custom attributes (--avatar-* flags, replace the entire avatar):
1533
+ --avatar-rotation 1=far-left 3=center(default) 5=far-right
1534
+ --avatar-skin light / light-medium / medium(default) / medium-dark / dark
1535
+ --avatar-hair-style 1\u20135 (default: 1)
1536
+ --avatar-hair-color blonde / teal / grey / pink / brown(default)
1537
+ --avatar-expression calm(default) / content / neutral / pleasant / excited
1538
+ --avatar-intensity chill / normal(default) / hyped
1539
+
1540
+ Note: --avatar and --avatar-* cannot be used together.
1541
+
1310
1542
  Examples:
1311
1543
  Update description: zero agent edit <agent-id> --description "new role"
1312
1544
  Update tone: zero agent edit <agent-id> --sound friendly
1545
+ Quick preset avatar: zero agent edit <agent-id> --avatar preset:2
1546
+ Custom avatar: zero agent edit <agent-id> --avatar-skin dark --avatar-hair-color teal --avatar-intensity hyped
1313
1547
  Replace all skills: zero agent edit <agent-id> --skills my-skill,other-skill
1314
1548
  Add a skill: zero agent edit <agent-id> --add-skill my-skill
1315
1549
  Remove a skill: zero agent edit <agent-id> --remove-skill my-skill
@@ -1330,7 +1564,7 @@ Notes:
1330
1564
  const hasAgentUpdate = hasAgentFieldUpdate(options);
1331
1565
  if (!hasAgentUpdate && !options.instructionsFile) {
1332
1566
  throw new Error(
1333
- "At least one option is required (--display-name, --description, --sound, --skills, --add-skill, --remove-skill, --model-provider, --model, --instructions-file)"
1567
+ "At least one option is required (--display-name, --description, --sound, --avatar, --avatar-*, --skills, --add-skill, --remove-skill, --model-provider, --model, --instructions-file)"
1334
1568
  );
1335
1569
  }
1336
1570
  if (hasAgentUpdate) {
@@ -1488,6 +1722,8 @@ Examples:
1488
1722
  if (agent.description)
1489
1723
  console.log(`Description: ${agent.description}`);
1490
1724
  if (agent.sound) console.log(`Sound: ${agent.sound}`);
1725
+ const avatar = formatAvatar(agent.avatarUrl);
1726
+ if (avatar) console.log(`Avatar: ${avatar}`);
1491
1727
  if (options.permissions && connectorInfos.length > 0) {
1492
1728
  console.log();
1493
1729
  console.log(source_default.bold("Connectors:"));
@@ -6637,7 +6873,7 @@ function registerZeroCommands(prog, commands) {
6637
6873
  var program = new Command();
6638
6874
  program.name("zero").description(
6639
6875
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
6640
- ).version("9.129.2").addHelpText(
6876
+ ).version("9.131.0").addHelpText(
6641
6877
  "after",
6642
6878
  `
6643
6879
  Examples: