@voltade/volty 0.1.10 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/volty.js +55 -23
  2. package/package.json +1 -1
package/dist/volty.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // bin/volty.ts
4
- import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
4
+ import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
5
5
  import { homedir as homedir3 } from "node:os";
6
6
  import { join as join4 } from "node:path";
7
7
 
@@ -58,8 +58,8 @@ async function fetchCatalog(ctx, env, useCache = true) {
58
58
  if (useCache && existsSync(path)) {
59
59
  try {
60
60
  const cached = JSON.parse(readFileSync(path, "utf8"));
61
- if (Date.now() - cached.at < CATALOG_TTL_MS && cached.retired)
62
- return { ops: cached.ops, retired: cached.retired };
61
+ if (Date.now() - cached.at < CATALOG_TTL_MS && cached.renamed)
62
+ return cached;
63
63
  } catch {}
64
64
  }
65
65
  const res = await apiFetch(ctx, "/api/v/_catalog");
@@ -68,11 +68,12 @@ async function fetchCatalog(ctx, env, useCache = true) {
68
68
  }
69
69
  const ops = res.body.catalog;
70
70
  const retired = res.body.retired ?? {};
71
+ const renamed = res.body.renamed ?? {};
71
72
  try {
72
73
  mkdirSync(tmpdir(), { recursive: true });
73
- writeFileSync(path, JSON.stringify({ at: Date.now(), ops, retired }));
74
+ writeFileSync(path, JSON.stringify({ at: Date.now(), ops, retired, renamed }));
74
75
  } catch {}
75
- return { ops, retired };
76
+ return { ops, retired, renamed };
76
77
  }
77
78
  async function fetchOrgs(ctx, env, useCache = true) {
78
79
  const path = join(tmpdir(), `volty-orgs-${env}.json`);
@@ -273,6 +274,9 @@ async function logout(config, env) {
273
274
  return `Logged out of '${env}' (key revoked).`;
274
275
  }
275
276
 
277
+ // src/dispatch.ts
278
+ import { readFileSync as readFileSync3 } from "node:fs";
279
+
276
280
  // ../shared/ops/flag-parse.ts
277
281
  function acceptsNull(prop) {
278
282
  if (prop.type === "null")
@@ -293,21 +297,21 @@ function coerce(flag, raw, prop0, UsageError) {
293
297
  return true;
294
298
  if (raw === "false")
295
299
  return false;
296
- throw new UsageError(`--${flag} expects true|false`);
300
+ throw new UsageError(`--${flag} expects true|false`, flag);
297
301
  }
298
302
  if (raw === undefined)
299
- throw new UsageError(`--${flag} requires a value`);
303
+ throw new UsageError(`--${flag} requires a value`, flag);
300
304
  if (prop.type === "number" || prop.type === "integer") {
301
305
  const n = Number(raw);
302
306
  if (Number.isNaN(n))
303
- throw new UsageError(`--${flag} expects a number`);
307
+ throw new UsageError(`--${flag} expects a number`, flag);
304
308
  return n;
305
309
  }
306
310
  if (prop.type === "object") {
307
311
  try {
308
312
  return JSON.parse(raw);
309
313
  } catch {
310
- throw new UsageError(`--${flag} expects JSON`);
314
+ throw new UsageError(`--${flag} expects JSON`, flag);
311
315
  }
312
316
  }
313
317
  return raw;
@@ -322,6 +326,16 @@ function jsonArrayValue(raw) {
322
326
  return null;
323
327
  }
324
328
  }
329
+ function arrayItems(flag, raw, prop, UsageError) {
330
+ const spread = jsonArrayValue(raw);
331
+ if (spread)
332
+ return spread;
333
+ const items = prop.items ?? {};
334
+ if (items.entityId && raw?.includes(",")) {
335
+ return raw.split(",").map((id) => id.trim()).filter((id) => id !== "");
336
+ }
337
+ return [coerce(flag, raw, items, UsageError)];
338
+ }
325
339
  function canonicalFlag(props, flag) {
326
340
  if (props[flag])
327
341
  return flag;
@@ -352,11 +366,7 @@ function parseFlagTokens(props, rest, UsageError) {
352
366
  }
353
367
  if (prop.type === "array") {
354
368
  const list = input[flag] ?? [];
355
- const spread = jsonArrayValue(raw);
356
- if (spread)
357
- list.push(...spread);
358
- else
359
- list.push(coerce(flag, raw, prop.items ?? {}, UsageError));
369
+ list.push(...arrayItems(flag, raw, prop, UsageError));
360
370
  input[flag] = list;
361
371
  } else {
362
372
  input[flag] = coerce(flag, raw, prop, UsageError);
@@ -369,16 +379,35 @@ function parseFlagTokens(props, rest, UsageError) {
369
379
  class CliUsageError extends Error {
370
380
  }
371
381
  function resolveOp(catalog, argv) {
372
- const byName = new Map(catalog.map((c) => [c.name, c]));
382
+ const byName = new Map(catalog.ops.map((c) => [c.name, c]));
373
383
  for (let n = Math.min(argv.length, 4);n >= 1; n--) {
374
- const op = byName.get(argv.slice(0, n).join(" "));
384
+ const name = argv.slice(0, n).join(" ");
385
+ const op = byName.get(name) ?? byName.get(catalog.renamed[name] ?? "");
375
386
  if (op)
376
- return { op, rest: argv.slice(n) };
387
+ return { op, rest: argv.slice(n), ...op.name !== name && { renamedFrom: name } };
377
388
  }
378
389
  return null;
379
390
  }
380
391
  function parseFlags(op, rest) {
381
- return parseFlagTokens(op.input.properties ?? {}, rest, CliUsageError);
392
+ const props = op.input.properties ?? {};
393
+ const parsed = parseFlagTokens(props, rest, CliUsageError);
394
+ for (const [key, value] of Object.entries(parsed.input)) {
395
+ const prop = props[key];
396
+ if (typeof value === "string" && value.startsWith("@") && prop && isBase64(prop)) {
397
+ parsed.input[key] = readBase64File(key, value.slice(1));
398
+ }
399
+ }
400
+ return parsed;
401
+ }
402
+ function isBase64(prop) {
403
+ return [prop, ...prop.anyOf ?? []].some((branch) => branch.contentEncoding === "base64");
404
+ }
405
+ function readBase64File(flag, path) {
406
+ try {
407
+ return readFileSync3(path).toString("base64");
408
+ } catch (err) {
409
+ throw new CliUsageError(`--${flag}: cannot read ${path} (${err.code ?? "error"})`);
410
+ }
382
411
  }
383
412
  async function runOp(ctx, op, input) {
384
413
  const res = await apiFetch(ctx, pathForOp(op.name), { method: "POST", body: input });
@@ -511,7 +540,7 @@ function decideProposal(ctx, proposalId, decision, reason) {
511
540
  }
512
541
 
513
542
  // src/update.ts
514
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
543
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
515
544
  import { homedir as homedir2 } from "node:os";
516
545
  import { dirname as dirname2, join as join3 } from "node:path";
517
546
  var CACHE_PATH = join3(homedir2(), ".config", "volty", "update-check.json");
@@ -519,7 +548,7 @@ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
519
548
  var REGISTRY_LATEST = "https://registry.npmjs.org/@voltade/volty/latest";
520
549
  function currentVersion() {
521
550
  try {
522
- const pkg = JSON.parse(readFileSync3(join3(import.meta.dirname, "..", "package.json"), "utf8"));
551
+ const pkg = JSON.parse(readFileSync4(join3(import.meta.dirname, "..", "package.json"), "utf8"));
523
552
  return pkg.version ?? null;
524
553
  } catch {
525
554
  return null;
@@ -537,7 +566,7 @@ function cmpVersion(a, b) {
537
566
  }
538
567
  function readCache() {
539
568
  try {
540
- return JSON.parse(readFileSync3(CACHE_PATH, "utf8"));
569
+ return JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
541
570
  } catch {
542
571
  return null;
543
572
  }
@@ -784,7 +813,7 @@ function handleSkill(rest) {
784
813
  fail("bundled SKILL.md not found — reinstall the @voltade/volty package");
785
814
  const destDir = join4(homedir3(), ".claude", "skills", "volty-cli-ops");
786
815
  mkdirSync4(destDir, { recursive: true });
787
- writeFileSync4(join4(destDir, "SKILL.md"), readFileSync4(source, "utf8"));
816
+ writeFileSync4(join4(destDir, "SKILL.md"), readFileSync5(source, "utf8"));
788
817
  process.stdout.write(`Installed the volty-cli-ops skill → ${join4(destDir, "SKILL.md")}
789
818
  `);
790
819
  }
@@ -839,13 +868,16 @@ async function main() {
839
868
  `);
840
869
  return;
841
870
  }
842
- const resolved = resolveOp(catalog.ops, argv);
871
+ const resolved = resolveOp(catalog, argv);
843
872
  if (!resolved) {
844
873
  const retired = retiredPrefix(catalog.retired, argv);
845
874
  if (retired)
846
875
  fail(`\`${retired.name}\` is retired: ${retired.replacement}`);
847
876
  fail(`unknown operation '${argv.join(" ")}' — run \`volty help\``);
848
877
  }
878
+ if (resolved.renamedFrom)
879
+ process.stderr.write(`${resolved.renamedFrom} is now ${resolved.op.name}
880
+ `);
849
881
  if (resolved.rest.includes("--help")) {
850
882
  process.stdout.write(`${renderOpHelp(resolved.op)}
851
883
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltade/volty",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Remote CLI for the Volty platform — run operations, trigger real agent wakes, and inspect LLM I/O over an API key.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",