@vapi-network/cli 0.2.1 → 0.2.2

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/brand.d.ts CHANGED
@@ -1,15 +1,35 @@
1
- export declare const MARK_STEP_MS = 70;
1
+ /** Terminal cells are about twice as tall as wide; 21x9 keeps the 743x659 aspect. */
2
+ export declare const MARK_COLUMNS = 21;
3
+ export declare const MARK_ROWS = 9;
2
4
  export declare const WORDMARK = "vAPI Network";
3
5
  export declare const WELCOME = "Welcome to the vAPI Network";
4
- export declare const TAGLINE: readonly ["The trusted network where agents and humans do business.", "Search APIs, pay per call, keep receipts. More coming soon."];
5
- /** Design-token colours; `ink` renders in the terminal's foreground, like the black mark on paper. */
6
+ export declare const TAGLINE: readonly ["The trusted network where agents", "and humans do business.", "", "Search APIs, pay per call, keep", "receipts. More coming soon."];
7
+ /** Design-token colours; `ink` renders in the terminal's own foreground colour. */
6
8
  export declare const MARK_PALETTE: {
7
- readonly orange: "#ff7300";
8
- readonly pink: "#ff337c";
9
- readonly lime: "#c3ff3d";
10
- readonly cyan: "#97efff";
11
- readonly blue: "#0041eb";
12
- readonly purple: "#8a37fb";
9
+ readonly orange: {
10
+ readonly hex: "#ff7300";
11
+ readonly ansi16: 33;
12
+ };
13
+ readonly pink: {
14
+ readonly hex: "#ff337c";
15
+ readonly ansi16: 95;
16
+ };
17
+ readonly lime: {
18
+ readonly hex: "#c3ff3d";
19
+ readonly ansi16: 92;
20
+ };
21
+ readonly cyan: {
22
+ readonly hex: "#97efff";
23
+ readonly ansi16: 96;
24
+ };
25
+ readonly blue: {
26
+ readonly hex: "#0041eb";
27
+ readonly ansi16: 34;
28
+ };
29
+ readonly purple: {
30
+ readonly hex: "#8a37fb";
31
+ readonly ansi16: 35;
32
+ };
13
33
  readonly ink: null;
14
34
  };
15
35
  export type MarkColorName = keyof typeof MARK_PALETTE;
@@ -18,38 +38,37 @@ export type MarkBlock = {
18
38
  x: number;
19
39
  width: number;
20
40
  color: MarkColorName;
21
- /** Reveal step; blocks that share a delay appear in the same frame. */
22
- delay: number;
23
41
  };
24
42
  export declare const MARK_BLOCKS: readonly MarkBlock[];
25
- export type MarkRenderOptions = {
26
- /** Emit ANSI colour. Defaults to false so output stays pipe-safe. */
27
- color?: boolean;
28
- };
29
- export type BannerOptions = MarkRenderOptions & {
30
- version: string;
31
- };
32
- export type AnimateBannerOptions = BannerOptions & {
33
- write(chunk: string): void;
34
- stepMs?: number;
35
- sleep?(milliseconds: number): Promise<void>;
36
- };
37
- export type AnimationEnvironment = {
43
+ /** 0 = no colour, 1 = 16 colours, 2 = 256 colours, 3 = truecolour (the supports-color scale). */
44
+ export type ColorLevel = 0 | 1 | 2 | 3;
45
+ export type TerminalEnvironment = {
38
46
  isTty?: boolean;
39
- json?: boolean;
40
47
  env?: NodeJS.ProcessEnv;
41
48
  };
42
- /** Colour is off whenever `NO_COLOR` is set or stdout is not a terminal. */
43
- export declare function markColorEnabled(environment?: AnimationEnvironment): boolean;
44
- /** Animate only in an interactive, colour-capable, human-facing terminal. */
45
- export declare function shouldAnimateMark(environment?: AnimationEnvironment): boolean;
49
+ export type BannerOptions = {
50
+ version: string;
51
+ /** Defaults to 0 so output stays pipe-safe. */
52
+ colorLevel?: ColorLevel;
53
+ /** Terminal width; below the framed width the banner falls back to plain text. */
54
+ columns?: number;
55
+ };
56
+ /**
57
+ * Colour capability the way chalk's supports-color decides it: NO_COLOR and
58
+ * a redirected stdout disable colour, FORCE_COLOR overrides, and otherwise
59
+ * the terminal's own advertisement (COLORTERM, TERM, TERM_PROGRAM) picks
60
+ * the level. Apple Terminal advertises 256 colours, not truecolour.
61
+ */
62
+ export declare function detectColorLevel(environment?: TerminalEnvironment): ColorLevel;
63
+ /** The complete mark: `MARK_ROWS` lines of exactly `MARK_COLUMNS` visible cells. */
64
+ export declare function renderMark(colorLevel?: ColorLevel): string;
65
+ /** Width in columns of the framed banner. */
66
+ export declare function bannerWidth(): number;
46
67
  /**
47
- * Every reveal step of the mark, oldest first. Pure: the last frame is the
48
- * complete mark and each frame is exactly `MARK_ROWS` lines of `MARK_COLUMNS`
49
- * visible cells.
68
+ * The welcome banner: the mark on the left, the welcome text on the right,
69
+ * inside a rounded frame. When the terminal is narrower than the frame, the
70
+ * text alone is printed so nothing wraps.
50
71
  */
51
- export declare function renderMarkFrames(options?: MarkRenderOptions): string[];
52
- /** The framed welcome banner: the mark on the left, the welcome text on the right. */
53
72
  export declare function renderBanner(options: BannerOptions): string;
54
- /** Reveal the mark in place inside the frame, then leave the finished banner on screen. */
55
- export declare function animateBanner(options: AnimateBannerOptions): Promise<void>;
73
+ /** Nearest xterm 256-colour index, the same cube mapping chalk's ansi-styles uses. */
74
+ export declare function rgbToAnsi256(red: number, green: number, blue: number): number;
package/dist/cli.d.ts CHANGED
@@ -2,11 +2,6 @@ export declare const HELP = "vAPI Network\n\nUsage:\n vapi init [--networks <ba
2
2
  export type CliIo = {
3
3
  stdout(message: string): void;
4
4
  stderr(message: string): void;
5
- /**
6
- * Raw stdout sink for cursor control. Only an interactive terminal supplies
7
- * one; without it every banner falls back to a single static frame.
8
- */
9
- write?(chunk: string): void;
10
5
  };
11
6
  export type CliDependencies = {
12
7
  fetchImpl?: typeof fetch;
package/dist/cli.js CHANGED
@@ -46673,7 +46673,7 @@ function csvCell(value) {
46673
46673
  import { mkdir as mkdir6, writeFile as writeFile4 } from "node:fs/promises";
46674
46674
  import { arch, platform, release } from "node:os";
46675
46675
  import { join as join2 } from "node:path";
46676
- var VAPI_CLIENT_VERSION = "0.2.1";
46676
+ var VAPI_CLIENT_VERSION = "0.2.2";
46677
46677
  async function createSupportReport(options) {
46678
46678
  const message = options.message.trim();
46679
46679
  if (!message) throw new Error("Support report message must not be empty.");
@@ -48807,132 +48807,122 @@ function asRecord(value) {
48807
48807
  var MARK_SOURCE_WIDTH = 743;
48808
48808
  var MARK_SOURCE_HEIGHT = 659;
48809
48809
  var MARK_SOURCE_ROW_HEIGHT = 217;
48810
- var MARK_COLUMNS = 28;
48811
- var MARK_ROWS = 12;
48812
- var PLAIN_BLOCK = "\u2588";
48813
- var MARK_STEP_MS = 70;
48810
+ var MARK_COLUMNS = 21;
48811
+ var MARK_ROWS = 9;
48812
+ var BLOCK = "\u2588";
48814
48813
  var WORDMARK = "vAPI Network";
48815
48814
  var WELCOME = "Welcome to the vAPI Network";
48816
48815
  var TAGLINE = [
48817
- "The trusted network where agents and humans do business.",
48818
- "Search APIs, pay per call, keep receipts. More coming soon."
48816
+ "The trusted network where agents",
48817
+ "and humans do business.",
48818
+ "",
48819
+ "Search APIs, pay per call, keep",
48820
+ "receipts. More coming soon."
48819
48821
  ];
48820
- var ESC = "\x1B";
48822
+ var ESC = String.fromCharCode(27);
48821
48823
  var RESET = `${ESC}[0m`;
48822
- var REVERSE = `${ESC}[7m`;
48823
48824
  var BOLD = `${ESC}[1m`;
48824
48825
  var DIM = `${ESC}[2m`;
48825
- var HIDE_CURSOR = `${ESC}[?25l`;
48826
- var SHOW_CURSOR = `${ESC}[?25h`;
48826
+ var DEFAULT_FOREGROUND = `${ESC}[39m`;
48827
48827
  var MARK_PALETTE = {
48828
- orange: "#ff7300",
48829
- pink: "#ff337c",
48830
- lime: "#c3ff3d",
48831
- cyan: "#97efff",
48832
- blue: "#0041eb",
48833
- purple: "#8a37fb",
48828
+ orange: { hex: "#ff7300", ansi16: 33 },
48829
+ pink: { hex: "#ff337c", ansi16: 95 },
48830
+ lime: { hex: "#c3ff3d", ansi16: 92 },
48831
+ cyan: { hex: "#97efff", ansi16: 96 },
48832
+ blue: { hex: "#0041eb", ansi16: 34 },
48833
+ purple: { hex: "#8a37fb", ansi16: 35 },
48834
48834
  ink: null
48835
48835
  };
48836
48836
  var MARK_BLOCKS = [
48837
- { row: 0, x: 2, width: 90, color: "orange", delay: 0 },
48838
- { row: 0, x: 94, width: 35, color: "pink", delay: 1 },
48839
- { row: 0, x: 131, width: 16, color: "lime", delay: 2 },
48840
- { row: 0, x: 522, width: 219, color: "ink", delay: 1 },
48841
- { row: 1, x: 124, width: 50, color: "cyan", delay: 3 },
48842
- { row: 1, x: 176, width: 24, color: "blue", delay: 4 },
48843
- { row: 1, x: 202, width: 17, color: "purple", delay: 5 },
48844
- { row: 1, x: 402, width: 219, color: "blue", delay: 4 },
48845
- { row: 2, x: 282, width: 219, color: "ink", delay: 7 }
48837
+ { row: 0, x: 2, width: 90, color: "orange" },
48838
+ { row: 0, x: 94, width: 35, color: "pink" },
48839
+ { row: 0, x: 131, width: 16, color: "lime" },
48840
+ { row: 0, x: 522, width: 219, color: "ink" },
48841
+ { row: 1, x: 124, width: 50, color: "cyan" },
48842
+ { row: 1, x: 176, width: 24, color: "blue" },
48843
+ { row: 1, x: 202, width: 17, color: "purple" },
48844
+ { row: 1, x: 402, width: 219, color: "blue" },
48845
+ { row: 2, x: 282, width: 219, color: "ink" }
48846
48846
  ];
48847
- function markColorEnabled(environment = {}) {
48847
+ function detectColorLevel(environment = {}) {
48848
48848
  const env = environment.env ?? process.env;
48849
48849
  const isTty = environment.isTty ?? Boolean(process.stdout.isTTY);
48850
- return isTty && !env.NO_COLOR;
48851
- }
48852
- function shouldAnimateMark(environment = {}) {
48853
- const env = environment.env ?? process.env;
48854
- if (environment.json) return false;
48855
- if (env.NO_COLOR || env.CI) return false;
48856
- return markColorEnabled(environment);
48857
- }
48858
- function renderMarkFrames(options = {}) {
48859
- const steps = [...new Set(MARK_BLOCKS.map((block) => block.delay))].sort(
48860
- (left, right) => left - right
48861
- );
48862
- return steps.map(
48863
- (step) => renderFrame(
48864
- MARK_BLOCKS.filter((block) => block.delay <= step),
48865
- options.color === true
48866
- )
48867
- );
48868
- }
48869
- function renderBanner(options) {
48870
- const frames = renderMarkFrames(options);
48871
- return renderBox(frames[frames.length - 1], options).join("\n");
48872
- }
48873
- async function animateBanner(options) {
48874
- const frames = renderMarkFrames({ color: options.color !== false });
48875
- const sleep = options.sleep ?? defaultSleep;
48876
- const stepMs = options.stepMs ?? MARK_STEP_MS;
48877
- const boxes = frames.map((frame) => renderBox(frame, options));
48878
- const height = boxes[0].length;
48879
- options.write(HIDE_CURSOR);
48880
- try {
48881
- for (const [index2, box] of boxes.entries()) {
48882
- if (index2 > 0) options.write(`${ESC}[${height}A`);
48883
- options.write(box.map((line) => `\r${ESC}[2K${line}
48884
- `).join(""));
48885
- if (index2 < boxes.length - 1) await sleep(stepMs);
48886
- }
48887
- } finally {
48888
- options.write(SHOW_CURSOR);
48889
- }
48890
- }
48891
- function renderBox(frame, options) {
48892
- const color = options.color === true;
48893
- const text = [
48894
- { value: WELCOME, style: BOLD },
48895
- { value: "", style: "" },
48896
- ...TAGLINE.map((line) => ({ value: line, style: "" })),
48897
- { value: "", style: "" },
48898
- { value: `${WORDMARK} v${options.version}`, style: DIM }
48899
- ];
48900
- const textWidth = Math.max(...text.map((line) => line.value.length));
48901
- const gap = 3;
48902
- const inner = 2 + MARK_COLUMNS + gap + textWidth + 2;
48903
- const markLines = frame.split("\n");
48904
- const textTop = Math.floor((MARK_ROWS - text.length) / 2);
48905
- const lines = [];
48906
- lines.push(`\u256D${"\u2500".repeat(inner)}\u256E`);
48907
- lines.push(`\u2502${" ".repeat(inner)}\u2502`);
48908
- for (let row = 0; row < MARK_ROWS; row += 1) {
48909
- const mark = markLines[row] ?? "";
48910
- const markPad = " ".repeat(Math.max(0, MARK_COLUMNS - visibleLength(mark)));
48911
- const entry = text[row - textTop];
48912
- const raw = entry?.value ?? "";
48913
- const styled = color && entry && entry.style && raw ? `${entry.style}${raw}${RESET}` : raw;
48914
- const textPad = " ".repeat(textWidth - raw.length);
48915
- lines.push(`\u2502 ${mark}${markPad}${" ".repeat(gap)}${styled}${textPad} \u2502`);
48850
+ if (env.NO_COLOR) return 0;
48851
+ const forced = env.FORCE_COLOR;
48852
+ if (forced !== void 0) {
48853
+ if (forced === "0" || forced === "false") return 0;
48854
+ if (forced === "2") return 2;
48855
+ if (forced === "3") return 3;
48856
+ return 1;
48916
48857
  }
48917
- lines.push(`\u2502${" ".repeat(inner)}\u2502`);
48918
- lines.push(`\u2570${"\u2500".repeat(inner)}\u256F`);
48919
- return lines;
48920
- }
48921
- function renderFrame(blocks, color) {
48858
+ if (!isTty) return 0;
48859
+ const term = env.TERM ?? "";
48860
+ const program = env.TERM_PROGRAM ?? "";
48861
+ if (term === "dumb") return 0;
48862
+ if (/^(truecolor|24bit)$/i.test(env.COLORTERM ?? "")) return 3;
48863
+ if (/kitty|wezterm|ghostty|alacritty/i.test(term)) return 3;
48864
+ if (/^(iTerm\.app|vscode|Hyper|WezTerm|ghostty)$/i.test(program)) return 3;
48865
+ if (/-256(?:color)?$/i.test(term) || program === "Apple_Terminal") return 2;
48866
+ return 1;
48867
+ }
48868
+ function renderMark(colorLevel = 0) {
48922
48869
  const rows = [];
48923
48870
  for (let row = 0; row < MARK_ROWS; row += 1) {
48924
48871
  const sourceY = row * MARK_SOURCE_HEIGHT / MARK_ROWS;
48925
48872
  const band = Math.min(2, Math.floor(sourceY / MARK_SOURCE_ROW_HEIGHT));
48926
48873
  rows.push(
48927
48874
  renderRow(
48928
- blocks.filter((block) => block.row === band),
48929
- color
48875
+ MARK_BLOCKS.filter((block) => block.row === band),
48876
+ colorLevel
48930
48877
  )
48931
48878
  );
48932
48879
  }
48933
48880
  return rows.join("\n");
48934
48881
  }
48935
- function renderRow(blocks, color) {
48882
+ function bannerWidth() {
48883
+ return frameInnerWidth() + 2;
48884
+ }
48885
+ function renderBanner(options) {
48886
+ const colorLevel = options.colorLevel ?? 0;
48887
+ const columns = options.columns ?? Number.POSITIVE_INFINITY;
48888
+ const text = bannerText(options.version, colorLevel);
48889
+ if (columns < bannerWidth()) {
48890
+ return text.map((line) => line.styled).join("\n");
48891
+ }
48892
+ const inner = frameInnerWidth();
48893
+ const markLines = renderMark(colorLevel).split("\n");
48894
+ const lines = [];
48895
+ lines.push(`\u256D${"\u2500".repeat(inner)}\u256E`);
48896
+ lines.push(`\u2502${" ".repeat(inner)}\u2502`);
48897
+ for (let row = 0; row < MARK_ROWS; row += 1) {
48898
+ const entry = text[row];
48899
+ const value = entry?.value ?? "";
48900
+ const styled = entry?.styled ?? "";
48901
+ const pad4 = " ".repeat(TEXT_WIDTH - value.length);
48902
+ lines.push(`\u2502 ${markLines[row]}${" ".repeat(GAP)}${styled}${pad4} \u2502`);
48903
+ }
48904
+ lines.push(`\u2502${" ".repeat(inner)}\u2502`);
48905
+ lines.push(`\u2570${"\u2500".repeat(inner)}\u256F`);
48906
+ return lines.join("\n");
48907
+ }
48908
+ var GAP = 3;
48909
+ var TEXT_WIDTH = Math.max(WELCOME.length, ...TAGLINE.map((line) => line.length));
48910
+ function frameInnerWidth() {
48911
+ return 2 + MARK_COLUMNS + GAP + TEXT_WIDTH + 2;
48912
+ }
48913
+ function bannerText(version5, colorLevel) {
48914
+ const style = (value, code) => colorLevel > 0 && value ? `${code}${value}${RESET}` : value;
48915
+ const rows = [
48916
+ { value: WELCOME, styled: style(WELCOME, BOLD) },
48917
+ { value: "", styled: "" },
48918
+ ...TAGLINE.map((line) => ({ value: line, styled: line })),
48919
+ { value: "", styled: "" },
48920
+ { value: `${WORDMARK} v${version5}`, styled: style(`${WORDMARK} v${version5}`, DIM) }
48921
+ ];
48922
+ if (rows.length > MARK_ROWS) throw new Error("banner text is taller than the mark");
48923
+ return rows;
48924
+ }
48925
+ function renderRow(blocks, colorLevel) {
48936
48926
  const ordered = [...blocks].sort((left, right) => left.x - right.x);
48937
48927
  let column = 0;
48938
48928
  let line = "";
@@ -48943,7 +48933,8 @@ function renderRow(blocks, color) {
48943
48933
  column = start;
48944
48934
  }
48945
48935
  const width = scaleWidth(block.width);
48946
- line += color ? `${cellPrefix(block.color)}${" ".repeat(width)}${RESET}` : PLAIN_BLOCK.repeat(width);
48936
+ const cells = BLOCK.repeat(width);
48937
+ line += colorLevel > 0 ? `${foreground(block.color, colorLevel)}${cells}${RESET}` : cells;
48947
48938
  column += width;
48948
48939
  }
48949
48940
  return line + " ".repeat(Math.max(0, MARK_COLUMNS - column));
@@ -48954,23 +48945,28 @@ function scaleColumn(x) {
48954
48945
  function scaleWidth(width) {
48955
48946
  return Math.max(1, Math.round(width * MARK_COLUMNS / MARK_SOURCE_WIDTH));
48956
48947
  }
48957
- function cellPrefix(color) {
48958
- const hex3 = MARK_PALETTE[color];
48959
- if (hex3 === null) return REVERSE;
48960
- const value = Number.parseInt(hex3.slice(1), 16);
48961
- return `${ESC}[48;2;${value >> 16 & 255};${value >> 8 & 255};${value & 255}m`;
48962
- }
48963
- function visibleLength(line) {
48964
- return line.replace(new RegExp(`${ESC}\\[[0-9;?]*[A-Za-z]`, "g"), "").length;
48948
+ function foreground(color, colorLevel) {
48949
+ const entry = MARK_PALETTE[color];
48950
+ if (entry === null) return DEFAULT_FOREGROUND;
48951
+ const value = Number.parseInt(entry.hex.slice(1), 16);
48952
+ const red = value >> 16 & 255;
48953
+ const green = value >> 8 & 255;
48954
+ const blue = value & 255;
48955
+ if (colorLevel === 3) return `${ESC}[38;2;${red};${green};${blue}m`;
48956
+ if (colorLevel === 2) return `${ESC}[38;5;${rgbToAnsi256(red, green, blue)}m`;
48957
+ return `${ESC}[${entry.ansi16}m`;
48965
48958
  }
48966
- function defaultSleep(milliseconds) {
48967
- return new Promise((resolve) => {
48968
- setTimeout(resolve, milliseconds);
48969
- });
48959
+ function rgbToAnsi256(red, green, blue) {
48960
+ if (red === green && green === blue) {
48961
+ if (red < 8) return 16;
48962
+ if (red > 248) return 231;
48963
+ return Math.round((red - 8) / 247 * 24) + 232;
48964
+ }
48965
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
48970
48966
  }
48971
48967
 
48972
48968
  // src/version.ts
48973
- var CLI_VERSION = "0.2.1";
48969
+ var CLI_VERSION = "0.2.2";
48974
48970
 
48975
48971
  // src/cli.ts
48976
48972
  var HELP_HEADING = "vAPI Network";
@@ -48999,8 +48995,7 @@ var processIo = {
48999
48995
  stdout: (message) => process.stdout.write(`${message}
49000
48996
  `),
49001
48997
  stderr: (message) => process.stderr.write(`${message}
49002
- `),
49003
- write: (chunk) => process.stdout.write(chunk)
48998
+ `)
49004
48999
  };
49005
49000
  var UsageError = class extends Error {
49006
49001
  };
@@ -49019,7 +49014,7 @@ async function runCli(argv = process.argv.slice(2), io = processIo, dependencies
49019
49014
  if (command === void 0 || command === "help" || command === "--help" || command === "-h") {
49020
49015
  requireNoArguments(args.slice(command === void 0 ? 0 : 1), command ?? "help");
49021
49016
  if (command === void 0 && !json2) {
49022
- io.stdout(staticBanner());
49017
+ showBanner(io);
49023
49018
  io.stdout(HELP.slice(HELP_HEADING.length + 2));
49024
49019
  return 0;
49025
49020
  }
@@ -49090,7 +49085,7 @@ async function initCommand(argv, json2, io, dependencies) {
49090
49085
  });
49091
49086
  const networks = parseInitNetworks(parsed.one("--networks") ?? "base");
49092
49087
  const enableSolana = networks.includes("solana");
49093
- if (!json2) await showBanner(io);
49088
+ if (!json2) showBanner(io);
49094
49089
  const paths = getVapiPaths();
49095
49090
  let migrated = [];
49096
49091
  if (!process.env.VAPI_HOME?.trim()) {
@@ -49452,16 +49447,14 @@ function formatNextStep(label, value, note) {
49452
49447
  const step = `${label.padEnd(10)}${value}`;
49453
49448
  return note === void 0 ? step : `${step.padEnd(52)} ${note}`;
49454
49449
  }
49455
- async function showBanner(io) {
49456
- const write = io.write;
49457
- if (write === void 0 || !shouldAnimateMark()) {
49458
- io.stdout(staticBanner());
49459
- return;
49460
- }
49461
- await animateBanner({ version: CLI_VERSION, write });
49462
- }
49463
- function staticBanner() {
49464
- return renderBanner({ version: CLI_VERSION, color: markColorEnabled() });
49450
+ function showBanner(io) {
49451
+ io.stdout(
49452
+ renderBanner({
49453
+ version: CLI_VERSION,
49454
+ colorLevel: detectColorLevel(),
49455
+ columns: process.stdout.columns
49456
+ })
49457
+ );
49465
49458
  }
49466
49459
  function formatAccounts(accounts) {
49467
49460
  if (accounts.length === 0) return "No configured network accounts.";