@voltade/volty 0.1.30 → 0.1.32

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/volty.js +50 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -56,7 +56,7 @@ To edit a workspace's automations, pages, quick paths and inbox settings as file
56
56
  volty init my-workspace
57
57
  ```
58
58
 
59
- It pulls the workspace into the new folder and adds a `package.json`, a `.gitignore`, a `CLAUDE.md` that imports `AGENTS.md` for Claude Code, and a `tsconfig.json` that references `tsconfig.code.json` and `tsconfig.entry.json`, so your editor and Claude can check the code the way a push does, as the `@voltade/sdk` README explains. Run `bun install` in the folder, then `bunx tsc -b` to check it, then open it in your editor. A file the folder already has is kept. `volty pull` brings in later changes from the workspace and `volty push` sends yours back.
59
+ It pulls the workspace into the new folder and adds a `package.json`, a `.gitignore`, a `CLAUDE.md` that imports `AGENTS.md` for Claude Code, and a `tsconfig.json` that references `tsconfig.code.json` and `tsconfig.entry.json`, so your editor and Claude can check the code the way a push does, as the `@voltade/sdk` README explains. Run `bun install` in the folder, then `bunx tsc -b` to check it, then open it in your editor. A file the folder already has is kept. On prod, name the workspace with `--workspace <id>` (`volty org list --env prod` lists yours). Inside the folder, `volty pull` brings in later changes from the workspace and `volty push` sends yours back, both reading the workspace from the folder's `.volty/targets`.
60
60
 
61
61
  ## Upgrading
62
62
 
package/dist/volty.js CHANGED
@@ -835,6 +835,7 @@ function isProdShaped(env, baseUrl) {
835
835
  return host !== "localhost" && host !== "127.0.0.1" && host !== "::1" && host !== "[::1]";
836
836
  }
837
837
  var PROD_ORG_REFUSAL = "prod needs an explicit org: pass --org <id> or VOLTY_ORG=<id>; run 'volty org list --env prod' to see your orgs";
838
+ var PROD_WORKSPACE_REFUSAL = "prod needs an explicit workspace: pass --workspace <id>; run 'volty org list --env prod' to see yours";
838
839
  var STICKY_ORG_REFUSAL = "prod does not honour a sticky org: pass --org <id> or VOLTY_ORG=<id> on each command instead; run 'volty org list --env prod' to see your orgs";
839
840
  function resolveTargetOrg({ env, baseUrl, override, sticky, command }) {
840
841
  if (!isProdShaped(env, baseUrl))
@@ -843,6 +844,8 @@ function resolveTargetOrg({ env, baseUrl, override, sticky, command }) {
843
844
  return { org: override };
844
845
  if (isOrgFreeCommand(command))
845
846
  return { org: undefined };
847
+ if (command[0] === "pull" || command[0] === "init")
848
+ return { refusal: PROD_WORKSPACE_REFUSAL };
846
849
  return { refusal: PROD_ORG_REFUSAL };
847
850
  }
848
851
 
@@ -1371,20 +1374,49 @@ function pullLines(dir, out) {
1371
1374
  "What the project does not hold is listed in .volty/observed."
1372
1375
  ];
1373
1376
  }
1374
- async function handlePull(rest, ctx, env) {
1375
- const dir = folderArg(rest, "pull");
1377
+ async function handlePull(dir, ctx, env) {
1376
1378
  const out = await pull(ctx, { dir, workspaceId: await workspaceOf(ctx), target: env });
1377
1379
  process.stdout.write(`${pullLines(dir, out).join(`
1378
1380
  `)}
1379
1381
  `);
1380
1382
  }
1381
- async function handleInit(rest, ctx, env) {
1382
- const dir = folderArg(rest, "init");
1383
+ async function handleInit(dir, ctx, env) {
1383
1384
  const out = await init(ctx, { dir, workspaceId: await workspaceOf(ctx), target: env });
1384
1385
  process.stdout.write(`${[...pullLines(dir, out.pulled), ...initLines(dir, out.files)].join(`
1385
1386
  `)}
1386
1387
  `);
1387
1388
  }
1389
+ async function targetContext(config, name, workspace) {
1390
+ const login = config.contexts[name];
1391
+ if (!login?.apiKey)
1392
+ fail(`not logged in to '${name}', the env target ${name} runs on: run \`volty auth login --env ${name}\``);
1393
+ const selected = await ensureOrgKey(login, workspace, (line) => process.stderr.write(`${line}
1394
+ `));
1395
+ if (selected.minted)
1396
+ saveConfig(config);
1397
+ const ctx = { ...login, apiKey: selected.apiKey, organizationId: selected.organizationId };
1398
+ setOrgOverride(selected.organizationId);
1399
+ if (isProdShaped(name, login.baseUrl)) {
1400
+ const res = await whoami(ctx);
1401
+ if ("error" in res)
1402
+ fail(res.error);
1403
+ process.stderr.write(`→ ${name} · ${res.who.organizationName} (${res.who.organizationId}) · ${res.who.role}
1404
+ `);
1405
+ }
1406
+ return ctx;
1407
+ }
1408
+ async function handlePulledPull(dir, targets, config, envFlag, workspaceId) {
1409
+ if (workspaceId)
1410
+ refuseOtherWorkspace(dir, targets, workspaceId);
1411
+ if (envFlag === "all")
1412
+ fail(`${dir} holds one copy of the files, so a pull takes one target: name it with --env (${Object.keys(targets).join(", ")})`);
1413
+ const name = pickTargets(targets, envFlag)[0];
1414
+ const { workspace } = targets[name];
1415
+ const out = await pull(await targetContext(config, name, workspace), { dir, workspaceId: workspace, target: name });
1416
+ process.stdout.write(`${pullLines(dir, out).join(`
1417
+ `)}
1418
+ `);
1419
+ }
1388
1420
  var PUSH_USAGE = "usage: volty push [dir] [--env <target>|all] [--dry-run] [--confirm] [--json]";
1389
1421
  async function handlePush(argv, config, envFlag) {
1390
1422
  const dryRun = takeBool(argv, "--dry-run");
@@ -1398,23 +1430,8 @@ async function handlePush(argv, config, envFlag) {
1398
1430
  const answers = {};
1399
1431
  let exitCode = 0;
1400
1432
  for (const name of names) {
1401
- const login = config.contexts[name];
1402
- if (!login?.apiKey)
1403
- fail(`not logged in to '${name}', the env target ${name} runs on: run \`volty auth login --env ${name}\``);
1404
1433
  const { workspace } = project.targets[name];
1405
- const selected = await ensureOrgKey(login, workspace, (line) => process.stderr.write(`${line}
1406
- `));
1407
- if (selected.minted)
1408
- saveConfig(config);
1409
- const ctx = { ...login, apiKey: selected.apiKey, organizationId: selected.organizationId };
1410
- setOrgOverride(selected.organizationId);
1411
- if (isProdShaped(name, login.baseUrl)) {
1412
- const res = await whoami(ctx);
1413
- if ("error" in res)
1414
- fail(res.error);
1415
- process.stderr.write(`→ ${name} · ${res.who.organizationName} (${res.who.organizationId}) · ${res.who.role}
1416
- `);
1417
- }
1434
+ const ctx = await targetContext(config, name, workspace);
1418
1435
  if (names.length > 1 && !json.present)
1419
1436
  process.stdout.write(`Target ${name}, workspace ${workspace}:
1420
1437
  `);
@@ -1477,21 +1494,25 @@ async function main() {
1477
1494
  argv = orgExtract.rest;
1478
1495
  const cacheFlag = takeBool(argv, "--no-cache");
1479
1496
  argv = cacheFlag.rest;
1480
- const workspaceExtract = argv[0] === "pull" || argv[0] === "init" ? takeValue(argv, "--workspace") : { value: undefined, rest: argv };
1497
+ const folderCmd = argv[0] === "pull" || argv[0] === "init" ? argv[0] : null;
1498
+ const workspaceExtract = folderCmd ? takeValue(argv, "--workspace") : { value: undefined, rest: argv };
1481
1499
  argv = workspaceExtract.rest;
1482
1500
  const config = loadConfig();
1483
- const pulled = argv[0] === "init" ? readTargets(folderArg(argv.slice(1), "init")) : null;
1501
+ const dir = folderCmd ? folderArg(argv.slice(1), folderCmd) : null;
1502
+ const pulled = dir ? readTargets(dir) : null;
1484
1503
  if (argv[0] === "push" || pulled) {
1485
1504
  if (orgExtract.value)
1486
1505
  fail(`volty ${argv[0]} takes its workspace from .volty/targets: leave out --org`);
1487
- if (pulled) {
1488
- const dir = folderArg(argv.slice(1), "init");
1506
+ const envFlag = envExtract.value ?? (process.env.VOLTY_ENV || undefined);
1507
+ if (dir && pulled && folderCmd === "init") {
1489
1508
  process.stdout.write(`${initLines(dir, initPulled(dir, pulled, workspaceExtract.value)).join(`
1490
1509
  `)}
1491
1510
  `);
1492
1511
  return;
1493
1512
  }
1494
- return handlePush(argv.slice(1), config, envExtract.value ?? (process.env.VOLTY_ENV || undefined));
1513
+ if (dir && pulled)
1514
+ return handlePulledPull(dir, pulled, config, envFlag, workspaceExtract.value);
1515
+ return handlePush(argv.slice(1), config, envFlag);
1495
1516
  }
1496
1517
  const env = activeEnv(config, envExtract.value ?? (process.env.VOLTY_ENV || undefined));
1497
1518
  const peek = config.contexts[env];
@@ -1540,10 +1561,10 @@ async function main() {
1540
1561
  process.stderr.write(`→ ${env} · ${res.who.organizationName} (${res.who.organizationId}) · ${res.who.role}
1541
1562
  `);
1542
1563
  }
1543
- if (cmd === "pull")
1544
- return handlePull(rest, ctx, env);
1545
- if (cmd === "init")
1546
- return handleInit(rest, ctx, env);
1564
+ if (dir && cmd === "pull")
1565
+ return handlePull(dir, ctx, env);
1566
+ if (dir && cmd === "init")
1567
+ return handleInit(dir, ctx, env);
1547
1568
  if (cmd === "changes" && rest[0] === "decide")
1548
1569
  return handleChanges(rest, ctx);
1549
1570
  if (cmd === "keys")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltade/volty",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
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",