@voltade/volty 0.1.17 → 0.1.19

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/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 readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
4
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
5
5
  import { homedir as homedir3 } from "node:os";
6
6
  import { join as join4 } from "node:path";
7
7
 
@@ -268,7 +268,7 @@ async function logout(config, env) {
268
268
  }
269
269
 
270
270
  // src/dispatch.ts
271
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
271
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
272
272
 
273
273
  // ../shared/ops/flag-parse.ts
274
274
  function acceptsNull(prop) {
@@ -354,9 +354,9 @@ function parseFlagTokens(props, rest, UsageError) {
354
354
  throw new UsageError(`unknown flag --${raw0}`);
355
355
  let raw = match[2];
356
356
  const next = rest[i + 1];
357
- if (raw === undefined && valueBranch(prop).type !== "boolean" && next !== undefined && !next.startsWith("--")) {
357
+ const takes = valueBranch(prop).type === "boolean" ? next === "true" || next === "false" : !next?.startsWith("--");
358
+ if (raw === undefined && next !== undefined && takes)
358
359
  raw = rest[++i];
359
- }
360
360
  if (prop.type === "array") {
361
361
  const list = input[flag] ?? [];
362
362
  list.push(...arrayItems(flag, raw, prop, UsageError));
@@ -406,12 +406,29 @@ function parseFlags(op, rest) {
406
406
  const parsed = parseFlagTokens(props, rest, CliUsageError);
407
407
  for (const [key, value] of Object.entries(parsed.input)) {
408
408
  const prop = props[key];
409
- if (typeof value === "string" && value.startsWith("@") && prop && isBase64(prop)) {
409
+ if (typeof value !== "string" || !value.startsWith("@") || !prop)
410
+ continue;
411
+ if (isBase64(prop))
410
412
  parsed.input[key] = readBase64File(key, value.slice(1));
411
- }
413
+ else if (isText(prop))
414
+ parsed.input[key] = readTextFlag(key, value.slice(1)) ?? value;
412
415
  }
413
416
  return parsed;
414
417
  }
418
+ function isText(prop) {
419
+ return [prop, ...prop.anyOf ?? []].some((branch) => branch.type === "string" && !branch.enum);
420
+ }
421
+ function readTextFlag(flag, path) {
422
+ if (path === "-")
423
+ return readFileSync3(0, "utf8");
424
+ if (!existsSync3(path))
425
+ return null;
426
+ try {
427
+ return readFileSync3(path, "utf8");
428
+ } catch (err) {
429
+ throw new CliUsageError(`--${flag}: cannot read ${path} (${err.code ?? "error"})`);
430
+ }
431
+ }
415
432
  function isBase64(prop) {
416
433
  return [prop, ...prop.anyOf ?? []].some((branch) => branch.contentEncoding === "base64");
417
434
  }
@@ -478,14 +495,19 @@ function opUsage(op) {
478
495
  }
479
496
  return parts.join(" ");
480
497
  }
481
- function renderCatalog(catalog) {
482
- const lines = catalog.toSorted((a, b) => a.name.localeCompare(b.name)).map((op) => ` ${op.name} — ${op.description}`);
498
+ function renderCatalog(catalog, group) {
499
+ const shown = group ? catalog.filter((op) => op.name === group || op.name.startsWith(`${group} `)) : catalog;
500
+ if (group && shown.length === 0) {
501
+ const groups = [...new Set(catalog.map((op) => op.name.split(" ")[0]))].toSorted();
502
+ return `No operations in '${group}'. Groups: ${groups.join(", ")}`;
503
+ }
504
+ const lines = shown.toSorted((a, b) => a.name.localeCompare(b.name)).map((op) => ` ${op.name} — ${op.description}`);
483
505
  return [
484
506
  "Run a Volty platform operation: volty <operation> [--flags] [--json]",
485
507
  "",
486
508
  ...lines,
487
509
  "",
488
- "`volty <operation> --help` shows usage; `--json` returns the machine-readable result."
510
+ "`volty help <group>` lists one group (`volty help chat-flow`); `volty <operation> --help` shows usage; `--json` returns the machine-readable result. A text flag takes a file as `--source=@flow.ts`, or stdin as `--source=@-`."
489
511
  ].join(`
490
512
  `);
491
513
  }
@@ -837,7 +859,7 @@ function handleSkill(rest) {
837
859
  join4(import.meta.dirname, "..", "skill", "volty-cli-ops", "SKILL.md"),
838
860
  join4(import.meta.dirname, "..", "..", ".claude", "skills", "volty-cli-ops", "SKILL.md")
839
861
  ];
840
- const source = candidates.find((p) => existsSync3(p));
862
+ const source = candidates.find((p) => existsSync4(p));
841
863
  if (!source)
842
864
  fail("bundled SKILL.md not found — reinstall the @voltade/volty package");
843
865
  const destDir = join4(homedir3(), ".claude", "skills", "volty-cli-ops");
@@ -893,7 +915,7 @@ async function main() {
893
915
  return handleChanges(rest, ctx);
894
916
  const catalog = await fetchCatalog(ctx, env, !cacheFlag.present);
895
917
  if (!cmd || cmd === "help" || cmd === "--help") {
896
- process.stdout.write(`${renderCatalog(catalog.ops)}
918
+ process.stdout.write(`${renderCatalog(catalog.ops, rest.length ? rest.join(" ") : undefined)}
897
919
  `);
898
920
  return;
899
921
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltade/volty",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
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",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: volty-cli-ops
3
- description: "Drive Volty's agent with the `volty` CLI: run a real agent turn in one command on either lane (a contact message or a staff session) and read what the model saw and did. Use whenever you need to exercise the live agent end to end: does an inbound trigger the right reply, learning or proposal, can Volty read or operate a connected system (CRM, MCP server, drive, channel), why did a tool call come back wrong. Reproducing a reported behaviour costs one command, so reach for it before theorising. Triggers: 'test the agent', 'trigger a wake', 'wake-sync', 'session-sync', 'ask Volty on prod', 'what did the agent do with X', 'run a real LLM turn', 'reproduce this inbound', 'can Volty see X?'."
3
+ description: "Drive Volty's agent with the `volty` CLI: run a real agent turn in one command on either lane (a contact message or a staff session) and read what the model saw and did. Use whenever you need to exercise the live agent end to end: does an inbound trigger the right reply, learning or proposal, can Volty read or operate a connected system (CRM, MCP server, drive, channel), why did a tool call come back wrong. Reproducing a reported behaviour costs one command, so reach for it before theorising. Also use it to create or configure a web chat channel from Claude Code. Triggers: 'set up a web chat', 'change the web chat settings', 'test the agent', 'trigger a wake', 'wake-sync', 'session-sync', 'ask Volty on prod', 'what did the agent do with X', 'run a real LLM turn', 'reproduce this inbound', 'can Volty see X?'."
4
4
  ---
5
5
 
6
6
  # volty CLI
@@ -19,6 +19,8 @@ This skill says which lane to use and what to keep to on prod. The commands and
19
19
  - `debug wake-sync --web-chat <channel id>` writes as a website visitor on a web chat channel, without the form's captcha: the contact lane on web chat. The chat is filed in the Sandbox inbox, where only testers see it, and Volty follows the web chat inbox's instructions, so you test that channel's setup without its staff seeing the test. You must be in the web chat channel's inbox.
20
20
  - `debug session-sync` runs a turn on the internal Volty chat as you: the staff lane.
21
21
 
22
+ To create or change a web chat (its look, websites, the visitor's phone and email settings, the logo), use the `widgets` ops: `volty docs` has a "Setting up a web chat" section with the order to run them in. Read the settings back with `widgets get` after a change, and test the chat with `debug wake-sync --web-chat` before saying it works.
23
+
22
24
  Use the lane the behaviour was reported on. On the contact lane Volty declines to list internal records to a contact, as it should, so "can Volty read our CRM or MCP server" belongs on the staff lane; asked on the contact lane, that refusal looks like a broken feature.
23
25
 
24
26
  ## On prod