@vertaaux/cli 0.5.0 → 0.5.1

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 (84) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +28 -1
  3. package/dist/app/interactive-app.d.ts +2 -0
  4. package/dist/app/interactive-app.d.ts.map +1 -1
  5. package/dist/app/interactive-app.js +26 -7
  6. package/dist/app/menu/categories.d.ts +2 -2
  7. package/dist/app/menu/categories.d.ts.map +1 -1
  8. package/dist/app/menu/categories.js +3 -18
  9. package/dist/app/views/command-runner.d.ts.map +1 -1
  10. package/dist/app/views/command-runner.js +52 -9
  11. package/dist/app/views/help-overlay.d.ts +1 -1
  12. package/dist/app/views/help-overlay.d.ts.map +1 -1
  13. package/dist/app/views/help-overlay.js +5 -4
  14. package/dist/commands/a11y.d.ts +4 -2
  15. package/dist/commands/a11y.d.ts.map +1 -1
  16. package/dist/commands/a11y.js +82 -9
  17. package/dist/commands/audit/index.d.ts.map +1 -1
  18. package/dist/commands/audit/index.js +33 -8
  19. package/dist/commands/audit/output.d.ts.map +1 -1
  20. package/dist/commands/audit/output.js +3 -4
  21. package/dist/commands/audit/policy.d.ts +10 -2
  22. package/dist/commands/audit/policy.d.ts.map +1 -1
  23. package/dist/commands/audit/policy.js +47 -2
  24. package/dist/commands/audit/types.d.ts +1 -0
  25. package/dist/commands/audit/types.d.ts.map +1 -1
  26. package/dist/commands/baseline.d.ts +1 -0
  27. package/dist/commands/baseline.d.ts.map +1 -1
  28. package/dist/commands/baseline.js +26 -12
  29. package/dist/commands/comment.d.ts.map +1 -1
  30. package/dist/commands/comment.js +8 -7
  31. package/dist/commands/compare.js +3 -3
  32. package/dist/commands/diff.d.ts +2 -0
  33. package/dist/commands/diff.d.ts.map +1 -1
  34. package/dist/commands/diff.js +23 -12
  35. package/dist/commands/doc.js +2 -2
  36. package/dist/commands/doctor.js +2 -2
  37. package/dist/commands/explain.js +3 -3
  38. package/dist/commands/fix-all.js +2 -2
  39. package/dist/commands/fix-plan.d.ts.map +1 -1
  40. package/dist/commands/fix-plan.js +4 -3
  41. package/dist/commands/fix.js +5 -5
  42. package/dist/commands/patch-review.js +2 -2
  43. package/dist/commands/policy.js +2 -2
  44. package/dist/commands/release-notes.js +3 -3
  45. package/dist/commands/suggest.d.ts.map +1 -1
  46. package/dist/commands/suggest.js +28 -2
  47. package/dist/commands/triage.js +3 -3
  48. package/dist/commands/verify.js +3 -3
  49. package/dist/config/schema.d.ts +4 -0
  50. package/dist/config/schema.d.ts.map +1 -1
  51. package/dist/index.js +3 -2
  52. package/dist/output/envelope.d.ts +8 -1
  53. package/dist/output/envelope.d.ts.map +1 -1
  54. package/dist/output/envelope.js +24 -6
  55. package/dist/policy/schema.d.ts +137 -0
  56. package/dist/policy/schema.d.ts.map +1 -1
  57. package/dist/policy/schema.js +107 -0
  58. package/dist/prompts/command-catalog.js +9 -9
  59. package/dist/utils/client.d.ts.map +1 -1
  60. package/dist/utils/client.js +30 -28
  61. package/dist/utils/root-args.d.ts +12 -0
  62. package/dist/utils/root-args.d.ts.map +1 -0
  63. package/dist/utils/root-args.js +44 -0
  64. package/dist/utils/stdin.d.ts +7 -0
  65. package/dist/utils/stdin.d.ts.map +1 -1
  66. package/dist/utils/stdin.js +32 -2
  67. package/node_modules/@vertaaux/tui/dist/index.cjs +505 -9
  68. package/node_modules/@vertaaux/tui/dist/index.cjs.map +1 -1
  69. package/node_modules/@vertaaux/tui/dist/index.js +502 -8
  70. package/node_modules/@vertaaux/tui/dist/index.js.map +1 -1
  71. package/node_modules/@vertaaux/tui/package.json +2 -3
  72. package/node_modules/chalk/license +9 -0
  73. package/node_modules/chalk/package.json +83 -0
  74. package/node_modules/chalk/readme.md +297 -0
  75. package/node_modules/chalk/source/index.d.ts +325 -0
  76. package/node_modules/chalk/source/index.js +225 -0
  77. package/node_modules/chalk/source/utilities.js +33 -0
  78. package/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
  79. package/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
  80. package/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
  81. package/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
  82. package/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
  83. package/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
  84. package/package.json +9 -2
@@ -10,6 +10,7 @@ import { readFileSync, existsSync, lstatSync, statSync } from "fs";
10
10
  import { homedir } from "os";
11
11
  import { join } from "path";
12
12
  const DEFAULT_API_BASE = "https://vertaaux.ai/api/v1";
13
+ const NO_API_KEY_MESSAGE = "No API key found. Run 'vertaa login' or set VERTAAUX_API_KEY environment variable.";
13
14
  /**
14
15
  * Read the stored API key from ~/.vertaaux/credentials.json (sync).
15
16
  * Returns the accessToken if the file exists and is valid JSON, else undefined.
@@ -54,6 +55,16 @@ export function resolveApiBase(flagBase, configBase) {
54
55
  DEFAULT_API_BASE;
55
56
  return raw.replace(/\/$/, "");
56
57
  }
58
+ function requireNonEmptyApiKey(candidate) {
59
+ if (candidate === undefined) {
60
+ return undefined;
61
+ }
62
+ const trimmed = candidate.trim();
63
+ if (!trimmed) {
64
+ throw new Error(NO_API_KEY_MESSAGE);
65
+ }
66
+ return trimmed;
67
+ }
57
68
  /**
58
69
  * Get API key from environment or config.
59
70
  *
@@ -62,9 +73,17 @@ export function resolveApiBase(flagBase, configBase) {
62
73
  * @throws Error if no API key is available
63
74
  */
64
75
  export function getApiKey(configApiKey) {
65
- const key = process.env.VERTAAUX_API_KEY || configApiKey || readStoredApiKey();
76
+ if (Object.prototype.hasOwnProperty.call(process.env, "VERTAAUX_API_KEY")) {
77
+ const envKey = requireNonEmptyApiKey(process.env.VERTAAUX_API_KEY);
78
+ if (envKey) {
79
+ return envKey;
80
+ }
81
+ throw new Error(NO_API_KEY_MESSAGE);
82
+ }
83
+ const configKey = requireNonEmptyApiKey(configApiKey);
84
+ const key = configKey || readStoredApiKey();
66
85
  if (!key) {
67
- throw new Error("No API key found. Run 'vertaa login' or set VERTAAUX_API_KEY environment variable.");
86
+ throw new Error(NO_API_KEY_MESSAGE);
68
87
  }
69
88
  return key;
70
89
  }
@@ -75,7 +94,13 @@ export function getApiKey(configApiKey) {
75
94
  * @returns true if API key is available
76
95
  */
77
96
  export function hasApiKey(config) {
78
- return Boolean(process.env.VERTAAUX_API_KEY || config?.apiKey || readStoredApiKey());
97
+ if (Object.prototype.hasOwnProperty.call(process.env, "VERTAAUX_API_KEY")) {
98
+ return Boolean(process.env.VERTAAUX_API_KEY?.trim());
99
+ }
100
+ if (config?.apiKey !== undefined) {
101
+ return Boolean(config.apiKey.trim());
102
+ }
103
+ return Boolean(readStoredApiKey());
79
104
  }
80
105
  /**
81
106
  * Create a VertaaUX SDK client instance.
@@ -89,31 +114,8 @@ export function hasApiKey(config) {
89
114
  */
90
115
  export function createClient(options) {
91
116
  const baseUrl = resolveApiBase(options?.base);
92
- const apiKey = options?.apiKey ?? getApiKey();
93
- // The SDK uses `new URL(path, baseUrl)` in buildUrl(), but SDK paths have
94
- // leading slashes (e.g. "/audit"), which makes new URL treat them as absolute
95
- // and strips the base path. Work around this by providing a custom fetch that
96
- // intercepts URLs and reconstructs them with string concatenation.
97
- const baseFetch = globalThis.fetch;
98
- const patchedFetch = (input, init) => {
99
- if (typeof input === "string") {
100
- // If the URL lost its path prefix, reconstruct it.
101
- // e.g. "https://vertaaux.ai/audit" → "https://vertaaux.ai/api/v1/audit"
102
- try {
103
- const parsed = new URL(input);
104
- const baseOrigin = new URL(baseUrl).origin;
105
- if (parsed.origin === baseOrigin && !input.startsWith(baseUrl)) {
106
- const fixedUrl = baseUrl.replace(/\/$/, "") + parsed.pathname + parsed.search;
107
- return baseFetch(fixedUrl, init);
108
- }
109
- }
110
- catch {
111
- // Not a valid URL, pass through
112
- }
113
- }
114
- return baseFetch(input, init);
115
- };
116
- return new VertaaUX({ apiKey, baseUrl, fetch: patchedFetch });
117
+ const apiKey = requireNonEmptyApiKey(options?.apiKey) ?? getApiKey();
118
+ return new VertaaUX({ apiKey, baseUrl });
117
119
  }
118
120
  /**
119
121
  * Make an authenticated API request.
@@ -0,0 +1,12 @@
1
+ export declare function hasHelpOrVersionFlag(args: string[]): boolean;
2
+ /**
3
+ * Return the first non-option token after skipping root global options.
4
+ *
5
+ * This keeps the "launch interactive app when no command is present" behavior
6
+ * while still allowing global flags to appear before the subcommand:
7
+ *
8
+ * vertaa --machine doctor
9
+ * vertaa --base https://api.example.test audit https://example.com
10
+ */
11
+ export declare function getRootCommandToken(args: string[]): string | undefined;
12
+ //# sourceMappingURL=root-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-args.d.ts","sourceRoot":"","sources":["../../src/utils/root-args.ts"],"names":[],"mappings":"AAcA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAE5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAyBtE"}
@@ -0,0 +1,44 @@
1
+ const ROOT_OPTIONS_WITH_VALUES = new Set([
2
+ "-b",
3
+ "--base",
4
+ "-c",
5
+ "--config",
6
+ ]);
7
+ const HELP_OR_VERSION_FLAGS = new Set([
8
+ "-h",
9
+ "--help",
10
+ "-v",
11
+ "--version",
12
+ ]);
13
+ export function hasHelpOrVersionFlag(args) {
14
+ return args.some((arg) => HELP_OR_VERSION_FLAGS.has(arg));
15
+ }
16
+ /**
17
+ * Return the first non-option token after skipping root global options.
18
+ *
19
+ * This keeps the "launch interactive app when no command is present" behavior
20
+ * while still allowing global flags to appear before the subcommand:
21
+ *
22
+ * vertaa --machine doctor
23
+ * vertaa --base https://api.example.test audit https://example.com
24
+ */
25
+ export function getRootCommandToken(args) {
26
+ for (let i = 0; i < args.length; i++) {
27
+ const arg = args[i];
28
+ if (arg === "--") {
29
+ return args[i + 1];
30
+ }
31
+ if (ROOT_OPTIONS_WITH_VALUES.has(arg)) {
32
+ i++;
33
+ continue;
34
+ }
35
+ if (arg.startsWith("--base=") || arg.startsWith("--config=")) {
36
+ continue;
37
+ }
38
+ if (arg.startsWith("-")) {
39
+ continue;
40
+ }
41
+ return arg;
42
+ }
43
+ return undefined;
44
+ }
@@ -16,6 +16,13 @@ export interface StdinResult {
16
16
  /** Whether the input was valid JSON */
17
17
  isJson: boolean;
18
18
  }
19
+ /**
20
+ * Unwrap the standard CLI JSON envelope shape ({ meta, data }).
21
+ *
22
+ * Commands that consume the output of other VertaaUX commands usually want
23
+ * the payload under `data`, not the outer provenance metadata.
24
+ */
25
+ export declare function unwrapJsonEnvelope<T = unknown>(input: unknown): T;
19
26
  /**
20
27
  * Check if stdin has piped data available.
21
28
  */
@@ -1 +1 @@
1
- {"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../src/utils/stdin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA2B7D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA+B9E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG5D"}
1
+ {"version":3,"file":"stdin.d.ts","sourceRoot":"","sources":["../../src/utils/stdin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,MAAM,EAAE,OAAO,CAAC;CACjB;AAqBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAKjE;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA2B7D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CA+B9E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG5D"}
@@ -5,6 +5,36 @@
5
5
  * and provides a consistent interface for all commands that accept
6
6
  * piped data (explain, triage, fix-plan, patch-review, etc.).
7
7
  */
8
+ /**
9
+ * Detect the standard CLI JSON envelope shape ({ meta, data }).
10
+ *
11
+ * Only matches when `meta` contains `command` and `version` — the fields
12
+ * that `createEnvelope()` always emits — so legitimate JSON payloads that
13
+ * happen to have a top-level `data` key are left untouched.
14
+ */
15
+ function isVertaaEnvelope(input) {
16
+ if (!input || typeof input !== "object" || !("meta" in input) || !("data" in input)) {
17
+ return false;
18
+ }
19
+ const meta = input.meta;
20
+ if (!meta || typeof meta !== "object") {
21
+ return false;
22
+ }
23
+ const { command, version } = meta;
24
+ return command !== undefined && version !== undefined;
25
+ }
26
+ /**
27
+ * Unwrap the standard CLI JSON envelope shape ({ meta, data }).
28
+ *
29
+ * Commands that consume the output of other VertaaUX commands usually want
30
+ * the payload under `data`, not the outer provenance metadata.
31
+ */
32
+ export function unwrapJsonEnvelope(input) {
33
+ if (isVertaaEnvelope(input)) {
34
+ return input.data;
35
+ }
36
+ return input;
37
+ }
8
38
  /**
9
39
  * Check if stdin has piped data available.
10
40
  */
@@ -64,7 +94,7 @@ export async function readJsonInput(filePath) {
64
94
  }
65
95
  const content = fs.readFileSync(resolved, "utf-8");
66
96
  try {
67
- return JSON.parse(content);
97
+ return unwrapJsonEnvelope(JSON.parse(content));
68
98
  }
69
99
  catch {
70
100
  throw new Error(`Invalid JSON in file: ${filePath}`);
@@ -77,7 +107,7 @@ export async function readJsonInput(filePath) {
77
107
  throw new Error("Could not parse input as JSON. If piping from vertaa, use --json flag:\n" +
78
108
  " vertaa audit https://example.com --json | vertaa explain");
79
109
  }
80
- return stdin.json;
110
+ return unwrapJsonEnvelope(stdin.json);
81
111
  }
82
112
  // No input found
83
113
  return null;