@paybond/kit 0.9.7 → 0.10.0

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 (60) hide show
  1. package/dist/cli/audit-export.d.ts +7 -0
  2. package/dist/cli/audit-export.js +120 -0
  3. package/dist/cli/automation.d.ts +25 -0
  4. package/dist/cli/automation.js +297 -0
  5. package/dist/cli/body.d.ts +7 -0
  6. package/dist/cli/body.js +22 -0
  7. package/dist/cli/color.d.ts +15 -0
  8. package/dist/cli/color.js +39 -0
  9. package/dist/cli/command-spec.d.ts +12 -0
  10. package/dist/cli/command-spec.js +330 -0
  11. package/dist/cli/commands/discovery.d.ts +8 -0
  12. package/dist/cli/commands/discovery.js +194 -0
  13. package/dist/cli/commands/setup.d.ts +15 -0
  14. package/dist/cli/commands/setup.js +397 -0
  15. package/dist/cli/commands/workflows.d.ts +7 -0
  16. package/dist/cli/commands/workflows.js +209 -0
  17. package/dist/cli/config.d.ts +14 -0
  18. package/dist/cli/config.js +96 -0
  19. package/dist/cli/context.d.ts +22 -0
  20. package/dist/cli/context.js +109 -0
  21. package/dist/cli/credentials.d.ts +21 -0
  22. package/dist/cli/credentials.js +141 -0
  23. package/dist/cli/doctor-agent.d.ts +15 -0
  24. package/dist/cli/doctor-agent.js +311 -0
  25. package/dist/cli/envelope.d.ts +14 -0
  26. package/dist/cli/envelope.js +46 -0
  27. package/dist/cli/globals.d.ts +22 -0
  28. package/dist/cli/globals.js +238 -0
  29. package/dist/cli/help.d.ts +3 -0
  30. package/dist/cli/help.js +51 -0
  31. package/dist/cli/mcp-install.d.ts +41 -0
  32. package/dist/cli/mcp-install.js +95 -0
  33. package/dist/cli/mcp-policy.d.ts +23 -0
  34. package/dist/cli/mcp-policy.js +104 -0
  35. package/dist/cli/mcp-verify-config.d.ts +37 -0
  36. package/dist/cli/mcp-verify-config.js +174 -0
  37. package/dist/cli/redact.d.ts +4 -0
  38. package/dist/cli/redact.js +67 -0
  39. package/dist/cli/request-id.d.ts +2 -0
  40. package/dist/cli/request-id.js +5 -0
  41. package/dist/cli/router.d.ts +2 -0
  42. package/dist/cli/router.js +275 -0
  43. package/dist/cli/suggest.d.ts +4 -0
  44. package/dist/cli/suggest.js +58 -0
  45. package/dist/cli/support-diagnostics.d.ts +19 -0
  46. package/dist/cli/support-diagnostics.js +47 -0
  47. package/dist/cli/types.d.ts +72 -0
  48. package/dist/cli/types.js +60 -0
  49. package/dist/cli/ux.d.ts +8 -0
  50. package/dist/cli/ux.js +164 -0
  51. package/dist/cli.d.ts +2 -0
  52. package/dist/cli.js +38 -0
  53. package/dist/index.d.ts +46 -12
  54. package/dist/index.js +136 -47
  55. package/dist/init.js +9 -14
  56. package/dist/login.d.ts +14 -1
  57. package/dist/login.js +123 -63
  58. package/dist/mcp-server.d.ts +4 -0
  59. package/dist/mcp-server.js +204 -76
  60. package/package.json +5 -2
@@ -0,0 +1,275 @@
1
+ import { commandPath, createContext } from "./context.js";
2
+ import { handleA2a, handleAuditExports, handleMandates, handleReceipts, handleSignal, } from "./commands/discovery.js";
3
+ import { handleConfig, handleDoctor, handleDiagnose, handleInitGuardrail, handleLogin, handleMcpInstall, handleMcpServe, handleMcpTools, handleMcpVerifyConfig, handleVersion, handleWhoami, } from "./commands/setup.js";
4
+ import { handleGuardrails, handleIntents, handleKeys, handleSpendAuthorize, } from "./commands/workflows.js";
5
+ import { failureEnvelope, prepareCommandOutput, successEnvelope, writeEnvelope, writeTableLines } from "./envelope.js";
6
+ import { defaultGlobalOptions, parseCliArgv } from "./globals.js";
7
+ import { deprecatedAliasWarning } from "./automation.js";
8
+ import { helpForCommand } from "./help.js";
9
+ import { generateRequestId } from "./request-id.js";
10
+ import { colorize, shouldUseColor } from "./color.js";
11
+ import { formatUnknownCommandMessage } from "./suggest.js";
12
+ import { handleCompletionCommand, handleExamplesCommand, handleHelpCommand, handleOnboarding, } from "./ux.js";
13
+ import { CliError, EXIT_SUCCESS, } from "./types.js";
14
+ function isHelp(argv) {
15
+ return argv.length === 0 || argv.includes("--help") || argv.includes("-h");
16
+ }
17
+ function renderTable(command, result, globals) {
18
+ const useColor = shouldUseColor(globals);
19
+ const lines = [colorize(`${command}: ok`, "green", useColor)];
20
+ for (const [key, value] of Object.entries(result.data)) {
21
+ if (value && typeof value === "object" && !Array.isArray(value)) {
22
+ lines.push(`${key}: ${JSON.stringify(value)}`);
23
+ }
24
+ else if (Array.isArray(value)) {
25
+ lines.push(`${key}: ${value.length} item(s)`);
26
+ }
27
+ else {
28
+ lines.push(`${key}: ${String(value)}`);
29
+ }
30
+ }
31
+ if (result.warnings?.length) {
32
+ lines.push(colorize(`warnings: ${result.warnings.join("; ")}`, "yellow", useColor));
33
+ }
34
+ return lines;
35
+ }
36
+ function toErrorShape(err) {
37
+ if (err instanceof CliError) {
38
+ if (err.message === "help") {
39
+ return {
40
+ shape: { category: "usage", code: "cli.help", message: "help" },
41
+ exitCode: EXIT_SUCCESS,
42
+ };
43
+ }
44
+ return {
45
+ shape: {
46
+ category: err.category,
47
+ code: err.code,
48
+ message: err.message,
49
+ details: err.details ?? {},
50
+ },
51
+ exitCode: err.exitCode,
52
+ };
53
+ }
54
+ return {
55
+ shape: {
56
+ category: "internal",
57
+ code: "cli.internal",
58
+ message: err instanceof Error ? err.message : String(err),
59
+ details: {},
60
+ },
61
+ exitCode: 1,
62
+ };
63
+ }
64
+ function outputFormatFromArgv(argv) {
65
+ for (let i = 0; i < argv.length; i += 1) {
66
+ const arg = argv[i];
67
+ if (arg === "--format" && argv[i + 1] === "json") {
68
+ return "json";
69
+ }
70
+ if (arg === "--format=json") {
71
+ return "json";
72
+ }
73
+ }
74
+ return "table";
75
+ }
76
+ function requestIdFromArgv(argv) {
77
+ for (let i = 0; i < argv.length; i += 1) {
78
+ const arg = argv[i];
79
+ if (arg === "--request-id" && argv[i + 1]) {
80
+ return argv[i + 1];
81
+ }
82
+ if (arg.startsWith("--request-id=")) {
83
+ return arg.slice("--request-id=".length);
84
+ }
85
+ }
86
+ return generateRequestId();
87
+ }
88
+ export async function runCli(argv, deps = {}) {
89
+ const stdout = deps.stdout ?? process.stdout;
90
+ const stderr = deps.stderr ?? process.stderr;
91
+ let globals;
92
+ let command;
93
+ try {
94
+ ({ globals, command } = parseCliArgv(argv));
95
+ }
96
+ catch (err) {
97
+ const { shape, exitCode } = toErrorShape(err);
98
+ if (shape.message === "help") {
99
+ stdout.write(`${helpForCommand("")}\n`);
100
+ return EXIT_SUCCESS;
101
+ }
102
+ if (outputFormatFromArgv(argv) === "json") {
103
+ writeEnvelope(stdout, failureEnvelope("paybond", { ...defaultGlobalOptions(), format: "json", requestId: requestIdFromArgv(argv) }, shape));
104
+ }
105
+ else {
106
+ stderr.write(`${shape.message}\n`);
107
+ }
108
+ return exitCode;
109
+ }
110
+ const ctx = createContext(globals, deps);
111
+ const aliasWarning = deprecatedAliasWarning(process.argv[1]);
112
+ if (aliasWarning) {
113
+ stderr.write(`${aliasWarning}\n`);
114
+ }
115
+ const helpPath = command.filter((part) => part !== "--help" && part !== "-h").join(" ");
116
+ if (isHelp(command)) {
117
+ const text = helpPath ? helpForCommand(helpPath) : helpForCommand("");
118
+ ctx.stdout.write(`${text}\n`);
119
+ return EXIT_SUCCESS;
120
+ }
121
+ let canonical = "";
122
+ let result;
123
+ try {
124
+ const [head, second, third] = command;
125
+ const tail = command.slice(2);
126
+ if (head === "help") {
127
+ canonical = "help";
128
+ result = handleHelpCommand(command.slice(1));
129
+ }
130
+ else if (head === "examples") {
131
+ canonical = "examples";
132
+ result = handleExamplesCommand(command.slice(1));
133
+ }
134
+ else if (head === "completion" && second) {
135
+ canonical = "completion";
136
+ result = handleCompletionCommand(command.slice(1));
137
+ }
138
+ else if (head === "onboarding") {
139
+ canonical = "onboarding";
140
+ result = await handleOnboarding(ctx, command.slice(1));
141
+ }
142
+ else if (head === "login") {
143
+ canonical = "login";
144
+ result = await handleLogin(ctx, command.slice(1));
145
+ }
146
+ else if (head === "init" && second === "guardrail") {
147
+ canonical = "init guardrail";
148
+ result = await handleInitGuardrail(ctx, command.slice(2));
149
+ }
150
+ else if (head === "mcp" && second === "serve") {
151
+ canonical = "mcp serve";
152
+ result = await handleMcpServe(ctx, command.slice(2));
153
+ }
154
+ else if (head === "mcp" && second === "install") {
155
+ canonical = "mcp install";
156
+ result = await handleMcpInstall(ctx, command.slice(2));
157
+ }
158
+ else if (head === "mcp" && second === "tools") {
159
+ canonical = "mcp tools";
160
+ result = await handleMcpTools(ctx);
161
+ }
162
+ else if (head === "mcp" && second === "verify-config") {
163
+ canonical = "mcp verify-config";
164
+ result = await handleMcpVerifyConfig(ctx, command.slice(2));
165
+ }
166
+ else if (head === "doctor") {
167
+ canonical = "doctor";
168
+ result = await handleDoctor(ctx, command.slice(1));
169
+ }
170
+ else if (head === "version") {
171
+ canonical = "version";
172
+ result = await handleVersion(ctx, command.slice(1));
173
+ }
174
+ else if (head === "diagnose") {
175
+ canonical = "diagnose";
176
+ result = await handleDiagnose(ctx, command.slice(1));
177
+ }
178
+ else if (head === "config" && second) {
179
+ canonical = commandPath(["config", second]);
180
+ result = await handleConfig(ctx, second, tail);
181
+ }
182
+ else if (head === "whoami") {
183
+ canonical = "whoami";
184
+ result = await handleWhoami(ctx);
185
+ }
186
+ else if (head === "keys" && second) {
187
+ canonical = commandPath(["keys", second]);
188
+ result = await handleKeys(ctx, second, tail);
189
+ }
190
+ else if (head === "intents" && second) {
191
+ canonical = commandPath(["intents", second]);
192
+ result = await handleIntents(ctx, second, tail);
193
+ }
194
+ else if (head === "guardrails" && second) {
195
+ canonical = commandPath(["guardrails", second]);
196
+ result = await handleGuardrails(ctx, second, tail);
197
+ }
198
+ else if (head === "spend" && second === "authorize") {
199
+ canonical = "spend authorize";
200
+ result = await handleSpendAuthorize(ctx, tail);
201
+ }
202
+ else if (head === "signal" && second) {
203
+ canonical = commandPath(["signal", second]);
204
+ result = await handleSignal(ctx, second, tail);
205
+ }
206
+ else if (head === "receipts" && second) {
207
+ canonical = commandPath(["receipts", second]);
208
+ result = await handleReceipts(ctx, second, tail);
209
+ }
210
+ else if (head === "mandates" && second) {
211
+ canonical = commandPath(["mandates", second]);
212
+ result = await handleMandates(ctx, second, tail);
213
+ }
214
+ else if (head === "a2a" && second) {
215
+ canonical = commandPath(["a2a", second]);
216
+ result = await handleA2a(ctx, second, tail);
217
+ }
218
+ else if (head === "audit" && second === "exports" && third) {
219
+ canonical = commandPath(["audit", "exports", third]);
220
+ result = await handleAuditExports(ctx, third, command.slice(3));
221
+ }
222
+ else {
223
+ throw new CliError(formatUnknownCommandMessage(command.join(" ")), {
224
+ category: "usage",
225
+ code: "cli.usage.unknown_command",
226
+ });
227
+ }
228
+ const output = prepareCommandOutput(canonical, globals, result);
229
+ if (globals.format === "json") {
230
+ writeEnvelope(ctx.stdout, successEnvelope(canonical, globals, { data: output.data, warnings: output.warnings }));
231
+ }
232
+ else if (output.automationPlain) {
233
+ ctx.stdout.write(`${JSON.stringify(output.data, null, 2)}\n`);
234
+ if (output.warnings.length) {
235
+ for (const warning of output.warnings) {
236
+ ctx.stderr.write(`${warning}\n`);
237
+ }
238
+ }
239
+ }
240
+ else if (canonical === "help" || canonical === "examples") {
241
+ ctx.stdout.write(`${String(result.data.text ?? "")}\n`);
242
+ }
243
+ else if (canonical === "completion") {
244
+ ctx.stdout.write(String(result.data.script ?? ""));
245
+ }
246
+ else if (canonical === "version" && !("package_name" in result.data)) {
247
+ ctx.stdout.write(`${String(result.data.version ?? "")}\n`);
248
+ }
249
+ else if (canonical === "diagnose") {
250
+ const lines = Array.isArray(result.data.lines) ? result.data.lines : [];
251
+ for (const line of lines) {
252
+ ctx.stdout.write(`${line}\n`);
253
+ }
254
+ }
255
+ else if (canonical !== "login" && canonical !== "mcp serve") {
256
+ writeTableLines(ctx.stdout, renderTable(canonical, result, globals));
257
+ }
258
+ return EXIT_SUCCESS;
259
+ }
260
+ catch (err) {
261
+ const { shape, exitCode } = toErrorShape(err);
262
+ if (shape.message === "help") {
263
+ const text = helpPath ? helpForCommand(helpPath) : helpForCommand("");
264
+ ctx.stdout.write(`${text}\n`);
265
+ return EXIT_SUCCESS;
266
+ }
267
+ if (globals.format === "json") {
268
+ writeEnvelope(ctx.stdout, failureEnvelope(canonical || helpPath || "paybond", globals, shape));
269
+ }
270
+ else {
271
+ ctx.stderr.write(`${shape.message}\n`);
272
+ }
273
+ return exitCode;
274
+ }
275
+ }
@@ -0,0 +1,4 @@
1
+ export declare function suggestCommandPath(input: string): string | undefined;
2
+ export declare function suggestGlobalFlag(input: string): string | undefined;
3
+ export declare function formatUnknownCommandMessage(input: string): string;
4
+ export declare function formatUnknownGlobalFlagMessage(flag: string): string;
@@ -0,0 +1,58 @@
1
+ import { COMMAND_PATHS, GLOBAL_FLAG_NAMES } from "./command-spec.js";
2
+ function levenshtein(a, b) {
3
+ const rows = a.length + 1;
4
+ const cols = b.length + 1;
5
+ const matrix = Array.from({ length: rows }, () => Array(cols).fill(0));
6
+ for (let i = 0; i < rows; i += 1) {
7
+ matrix[i][0] = i;
8
+ }
9
+ for (let j = 0; j < cols; j += 1) {
10
+ matrix[0][j] = j;
11
+ }
12
+ for (let i = 1; i < rows; i += 1) {
13
+ for (let j = 1; j < cols; j += 1) {
14
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
15
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
16
+ }
17
+ }
18
+ return matrix[a.length][b.length];
19
+ }
20
+ function bestSuggestion(input, candidates) {
21
+ const needle = input.trim().toLowerCase();
22
+ if (!needle) {
23
+ return undefined;
24
+ }
25
+ let best;
26
+ for (const candidate of candidates) {
27
+ const distance = levenshtein(needle, candidate.toLowerCase());
28
+ const threshold = Math.max(2, Math.floor(candidate.length / 3));
29
+ if (distance > threshold) {
30
+ continue;
31
+ }
32
+ if (!best || distance < best.distance) {
33
+ best = { value: candidate, distance };
34
+ }
35
+ }
36
+ return best?.value;
37
+ }
38
+ export function suggestCommandPath(input) {
39
+ return bestSuggestion(input, COMMAND_PATHS);
40
+ }
41
+ export function suggestGlobalFlag(input) {
42
+ const normalized = input.split("=")[0] ?? input;
43
+ return bestSuggestion(normalized, GLOBAL_FLAG_NAMES);
44
+ }
45
+ export function formatUnknownCommandMessage(input) {
46
+ const suggestion = suggestCommandPath(input);
47
+ if (suggestion) {
48
+ return `unknown command: ${input} (did you mean "${suggestion}"?)`;
49
+ }
50
+ return `unknown command: ${input}`;
51
+ }
52
+ export function formatUnknownGlobalFlagMessage(flag) {
53
+ const suggestion = suggestGlobalFlag(flag);
54
+ if (suggestion) {
55
+ return `unknown global flag: ${flag} (did you mean ${suggestion}?)`;
56
+ }
57
+ return `unknown global flag: ${flag}`;
58
+ }
@@ -0,0 +1,19 @@
1
+ import { describeCredentialSource } from "./credentials.js";
2
+ import type { CliContext } from "./context.js";
3
+ export type SupportDiagnostics = {
4
+ package_name: string;
5
+ package_version: string;
6
+ runtime: string;
7
+ platform: {
8
+ os: string;
9
+ arch: string;
10
+ };
11
+ config_path: string;
12
+ env_file_path: string;
13
+ gateway_url: string;
14
+ request_id: string;
15
+ mcp_tool_count: number;
16
+ credential_source: Awaited<ReturnType<typeof describeCredentialSource>>;
17
+ };
18
+ export declare function buildSupportDiagnostics(ctx: CliContext): Promise<SupportDiagnostics>;
19
+ export declare function formatSupportDiagnosticsTable(diagnostics: SupportDiagnostics): string[];
@@ -0,0 +1,47 @@
1
+ import path from "node:path";
2
+ import { configFilePath } from "./config.js";
3
+ import { describeCredentialSource } from "./credentials.js";
4
+ import { packageVersion } from "./doctor-agent.js";
5
+ import { PaybondMCPServer } from "../mcp-server.js";
6
+ function resolvedEnvFilePath(ctx) {
7
+ const envFile = ctx.globals.envFile;
8
+ return path.isAbsolute(envFile) ? path.resolve(envFile) : path.resolve(ctx.cwd, envFile);
9
+ }
10
+ export async function buildSupportDiagnostics(ctx) {
11
+ const server = new PaybondMCPServer({
12
+ gatewayBaseUrl: ctx.globals.gateway,
13
+ apiKey: "paybond_sk_sandbox_redacted_redacted_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
14
+ });
15
+ return {
16
+ package_name: "@paybond/kit",
17
+ package_version: packageVersion(),
18
+ runtime: `node ${process.version}`,
19
+ platform: {
20
+ os: process.platform,
21
+ arch: process.arch,
22
+ },
23
+ config_path: configFilePath(),
24
+ env_file_path: resolvedEnvFilePath(ctx),
25
+ gateway_url: ctx.globals.gateway,
26
+ request_id: ctx.globals.requestId,
27
+ mcp_tool_count: server.listTools().length,
28
+ credential_source: await describeCredentialSource(ctx.globals, ctx.cwd),
29
+ };
30
+ }
31
+ export function formatSupportDiagnosticsTable(diagnostics) {
32
+ const lines = [
33
+ `package: ${diagnostics.package_name} ${diagnostics.package_version}`,
34
+ `runtime: ${diagnostics.runtime}`,
35
+ `platform: ${diagnostics.platform.os} ${diagnostics.platform.arch}`,
36
+ `config_path: ${diagnostics.config_path}`,
37
+ `env_file_path: ${diagnostics.env_file_path}`,
38
+ `gateway_url: ${diagnostics.gateway_url}`,
39
+ `request_id: ${diagnostics.request_id}`,
40
+ `mcp_tool_count: ${diagnostics.mcp_tool_count}`,
41
+ `credential_source: ${JSON.stringify(diagnostics.credential_source)}`,
42
+ ];
43
+ if (diagnostics.credential_source.profile) {
44
+ lines.push(`profile: ${diagnostics.credential_source.profile}`);
45
+ }
46
+ return lines;
47
+ }
@@ -0,0 +1,72 @@
1
+ export type OutputFormat = "table" | "json";
2
+ export type ColorMode = "auto" | "always" | "never";
3
+ export type ErrorCategory = "usage" | "auth" | "forbidden" | "validation" | "not_found" | "gone" | "confirmation_required" | "rate_limit" | "gateway" | "network" | "environment" | "internal";
4
+ export type CliErrorDetails = Record<string, unknown>;
5
+ export type CliErrorShape = {
6
+ category: ErrorCategory;
7
+ code: string;
8
+ message: string;
9
+ details?: CliErrorDetails;
10
+ };
11
+ export type CliEnvelope<T> = {
12
+ ok: boolean;
13
+ command: string;
14
+ data: T | null;
15
+ warnings: string[];
16
+ request_id: string;
17
+ error: CliErrorShape | null;
18
+ };
19
+ export type GlobalOptions = {
20
+ gateway: string;
21
+ envFile: string;
22
+ format: OutputFormat;
23
+ color: ColorMode;
24
+ profile?: string;
25
+ requestId: string;
26
+ yes: boolean;
27
+ noOpen: boolean;
28
+ /** Comma-separated field names for automation output (`--json`). */
29
+ jsonFields?: string;
30
+ /** jq-style filter expression (`--jq`). */
31
+ jqExpr?: string;
32
+ };
33
+ export type Writable = {
34
+ write(chunk: string): boolean;
35
+ };
36
+ export type CliDependencies = {
37
+ cwd?: string;
38
+ fetch?: typeof fetch;
39
+ stdout?: Writable;
40
+ stderr?: Writable;
41
+ now?: () => number;
42
+ sleep?: (ms: number) => Promise<void>;
43
+ openBrowser?: (url: string) => Promise<boolean>;
44
+ };
45
+ export type CommandResult<T = Record<string, unknown>> = {
46
+ data: T;
47
+ warnings?: string[];
48
+ };
49
+ export declare const EXIT_SUCCESS = 0;
50
+ export declare const EXIT_FAILURE = 1;
51
+ export declare const EXIT_AUTH = 2;
52
+ export declare const EXIT_FORBIDDEN = 3;
53
+ export declare const EXIT_CONFIRMATION = 4;
54
+ export declare const EXIT_GATEWAY = 5;
55
+ export declare const EXIT_ENVIRONMENT = 6;
56
+ export declare class CliError extends Error {
57
+ readonly category: ErrorCategory;
58
+ readonly code: string;
59
+ readonly exitCode: number;
60
+ readonly details?: CliErrorDetails;
61
+ constructor(message: string, options?: {
62
+ category?: ErrorCategory;
63
+ code?: string;
64
+ exitCode?: number;
65
+ details?: CliErrorDetails;
66
+ });
67
+ }
68
+ export declare function exitCodeForCategory(category: ErrorCategory): number;
69
+ export declare function exitCodeForHttpStatus(status: number): {
70
+ exitCode: number;
71
+ category: ErrorCategory;
72
+ };
@@ -0,0 +1,60 @@
1
+ export const EXIT_SUCCESS = 0;
2
+ export const EXIT_FAILURE = 1;
3
+ export const EXIT_AUTH = 2;
4
+ export const EXIT_FORBIDDEN = 3;
5
+ export const EXIT_CONFIRMATION = 4;
6
+ export const EXIT_GATEWAY = 5;
7
+ export const EXIT_ENVIRONMENT = 6;
8
+ export class CliError extends Error {
9
+ category;
10
+ code;
11
+ exitCode;
12
+ details;
13
+ constructor(message, options = {}) {
14
+ super(message);
15
+ this.name = "CliError";
16
+ this.category = options.category ?? "usage";
17
+ this.code = options.code ?? `cli.${this.category}`;
18
+ this.exitCode = options.exitCode ?? exitCodeForCategory(this.category);
19
+ this.details = options.details;
20
+ }
21
+ }
22
+ export function exitCodeForCategory(category) {
23
+ switch (category) {
24
+ case "auth":
25
+ return EXIT_AUTH;
26
+ case "forbidden":
27
+ return EXIT_FORBIDDEN;
28
+ case "confirmation_required":
29
+ return EXIT_CONFIRMATION;
30
+ case "gateway":
31
+ case "rate_limit":
32
+ case "network":
33
+ return EXIT_GATEWAY;
34
+ case "environment":
35
+ return EXIT_ENVIRONMENT;
36
+ default:
37
+ return EXIT_FAILURE;
38
+ }
39
+ }
40
+ export function exitCodeForHttpStatus(status) {
41
+ if (status === 401) {
42
+ return { exitCode: EXIT_AUTH, category: "auth" };
43
+ }
44
+ if (status === 403) {
45
+ return { exitCode: EXIT_FORBIDDEN, category: "forbidden" };
46
+ }
47
+ if (status === 404) {
48
+ return { exitCode: EXIT_FAILURE, category: "not_found" };
49
+ }
50
+ if (status === 410) {
51
+ return { exitCode: EXIT_FAILURE, category: "gone" };
52
+ }
53
+ if (status === 429) {
54
+ return { exitCode: EXIT_GATEWAY, category: "rate_limit" };
55
+ }
56
+ if (status >= 500) {
57
+ return { exitCode: EXIT_GATEWAY, category: "gateway" };
58
+ }
59
+ return { exitCode: EXIT_FAILURE, category: "validation" };
60
+ }
@@ -0,0 +1,8 @@
1
+ import type { CliContext } from "./context.js";
2
+ import { type CommandResult } from "./types.js";
3
+ export declare function resolveHelpPath(argv: string[]): string;
4
+ export declare function renderHelpText(path: string): string;
5
+ export declare function handleHelpCommand(argv: string[]): CommandResult;
6
+ export declare function handleExamplesCommand(argv: string[]): CommandResult;
7
+ export declare function handleCompletionCommand(argv: string[]): CommandResult;
8
+ export declare function handleOnboarding(ctx: CliContext, argv: string[]): Promise<CommandResult>;