@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.
- package/dist/cli/audit-export.d.ts +7 -0
- package/dist/cli/audit-export.js +120 -0
- package/dist/cli/automation.d.ts +25 -0
- package/dist/cli/automation.js +297 -0
- package/dist/cli/body.d.ts +7 -0
- package/dist/cli/body.js +22 -0
- package/dist/cli/color.d.ts +15 -0
- package/dist/cli/color.js +39 -0
- package/dist/cli/command-spec.d.ts +12 -0
- package/dist/cli/command-spec.js +330 -0
- package/dist/cli/commands/discovery.d.ts +8 -0
- package/dist/cli/commands/discovery.js +194 -0
- package/dist/cli/commands/setup.d.ts +15 -0
- package/dist/cli/commands/setup.js +397 -0
- package/dist/cli/commands/workflows.d.ts +7 -0
- package/dist/cli/commands/workflows.js +209 -0
- package/dist/cli/config.d.ts +14 -0
- package/dist/cli/config.js +96 -0
- package/dist/cli/context.d.ts +22 -0
- package/dist/cli/context.js +109 -0
- package/dist/cli/credentials.d.ts +21 -0
- package/dist/cli/credentials.js +141 -0
- package/dist/cli/doctor-agent.d.ts +15 -0
- package/dist/cli/doctor-agent.js +311 -0
- package/dist/cli/envelope.d.ts +14 -0
- package/dist/cli/envelope.js +46 -0
- package/dist/cli/globals.d.ts +22 -0
- package/dist/cli/globals.js +238 -0
- package/dist/cli/help.d.ts +3 -0
- package/dist/cli/help.js +51 -0
- package/dist/cli/mcp-install.d.ts +41 -0
- package/dist/cli/mcp-install.js +95 -0
- package/dist/cli/mcp-policy.d.ts +23 -0
- package/dist/cli/mcp-policy.js +104 -0
- package/dist/cli/mcp-verify-config.d.ts +37 -0
- package/dist/cli/mcp-verify-config.js +174 -0
- package/dist/cli/redact.d.ts +4 -0
- package/dist/cli/redact.js +67 -0
- package/dist/cli/request-id.d.ts +2 -0
- package/dist/cli/request-id.js +5 -0
- package/dist/cli/router.d.ts +2 -0
- package/dist/cli/router.js +275 -0
- package/dist/cli/suggest.d.ts +4 -0
- package/dist/cli/suggest.js +58 -0
- package/dist/cli/support-diagnostics.d.ts +19 -0
- package/dist/cli/support-diagnostics.js +47 -0
- package/dist/cli/types.d.ts +72 -0
- package/dist/cli/types.js +60 -0
- package/dist/cli/ux.d.ts +8 -0
- package/dist/cli/ux.js +164 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +38 -0
- package/dist/index.d.ts +46 -12
- package/dist/index.js +136 -47
- package/dist/init.js +9 -14
- package/dist/login.d.ts +14 -1
- package/dist/login.js +123 -63
- package/dist/mcp-server.d.ts +4 -0
- package/dist/mcp-server.js +204 -76
- package/package.json +5 -2
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { redactConfigValue } from "./redact.js";
|
|
3
|
+
import { CliError } from "./types.js";
|
|
4
|
+
export function configFilePath() {
|
|
5
|
+
const home = process.env.HOME?.trim() || process.env.USERPROFILE?.trim() || "";
|
|
6
|
+
const base = process.env.XDG_CONFIG_HOME?.trim() || (home ? `${home}/.config` : ".config");
|
|
7
|
+
return `${base.replace(/\/+$/, "")}/paybond/config.json`;
|
|
8
|
+
}
|
|
9
|
+
export async function loadConfigFile() {
|
|
10
|
+
try {
|
|
11
|
+
const raw = await readFile(configFilePath(), "utf8");
|
|
12
|
+
const parsed = JSON.parse(raw);
|
|
13
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
throw new CliError(`unable to read CLI config: ${err instanceof Error ? err.message : String(err)}`, {
|
|
20
|
+
category: "environment",
|
|
21
|
+
code: "cli.environment.config_read_failed",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function saveConfigFile(config) {
|
|
26
|
+
const configPath = configFilePath();
|
|
27
|
+
const dir = configPath.replace(/\/[^/]+$/, "");
|
|
28
|
+
await mkdir(dir, { recursive: true });
|
|
29
|
+
await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
30
|
+
}
|
|
31
|
+
export async function resolveConfigValue(key, profile) {
|
|
32
|
+
const config = await loadConfigFile();
|
|
33
|
+
if (profile) {
|
|
34
|
+
const profileValues = config.profiles?.[profile];
|
|
35
|
+
if (profileValues && key in profileValues) {
|
|
36
|
+
const value = profileValues[key];
|
|
37
|
+
return typeof value === "string" ? value : undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return config.values?.[key];
|
|
41
|
+
}
|
|
42
|
+
export async function setConfigValue(key, value, profile) {
|
|
43
|
+
const config = await loadConfigFile();
|
|
44
|
+
if (profile) {
|
|
45
|
+
config.profiles ??= {};
|
|
46
|
+
config.profiles[profile] ??= {};
|
|
47
|
+
config.profiles[profile][key] = value;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
config.values ??= {};
|
|
51
|
+
config.values[key] = value;
|
|
52
|
+
}
|
|
53
|
+
await saveConfigFile(config);
|
|
54
|
+
}
|
|
55
|
+
export async function unsetConfigValue(key, profile) {
|
|
56
|
+
const config = await loadConfigFile();
|
|
57
|
+
if (profile) {
|
|
58
|
+
const profileValues = config.profiles?.[profile];
|
|
59
|
+
if (!profileValues || !(key in profileValues)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
delete profileValues[key];
|
|
63
|
+
await saveConfigFile(config);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (!config.values || !(key in config.values)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
delete config.values[key];
|
|
70
|
+
await saveConfigFile(config);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
export async function listConfigEntries(profile) {
|
|
74
|
+
const config = await loadConfigFile();
|
|
75
|
+
const entries = {};
|
|
76
|
+
if (profile) {
|
|
77
|
+
const profileValues = config.profiles?.[profile] ?? {};
|
|
78
|
+
for (const [key, value] of Object.entries(profileValues)) {
|
|
79
|
+
if (typeof value === "string") {
|
|
80
|
+
entries[key] = redactConfigValue(key, value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return entries;
|
|
84
|
+
}
|
|
85
|
+
for (const [key, value] of Object.entries(config.values ?? {})) {
|
|
86
|
+
entries[key] = redactConfigValue(key, value);
|
|
87
|
+
}
|
|
88
|
+
for (const [profileName, profileValues] of Object.entries(config.profiles ?? {})) {
|
|
89
|
+
for (const [key, value] of Object.entries(profileValues ?? {})) {
|
|
90
|
+
if (typeof value === "string") {
|
|
91
|
+
entries[`profiles.${profileName}.${key}`] = redactConfigValue(key, value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return entries;
|
|
96
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type CliDependencies, type CommandResult, type GlobalOptions, type Writable } from "./types.js";
|
|
2
|
+
export type GatewayJson = Record<string, unknown>;
|
|
3
|
+
export type GatewayClient = {
|
|
4
|
+
getJson(path: string): Promise<GatewayJson>;
|
|
5
|
+
postJson(path: string, body?: GatewayJson): Promise<GatewayJson>;
|
|
6
|
+
deleteJson(path: string): Promise<GatewayJson>;
|
|
7
|
+
};
|
|
8
|
+
export declare function gatewayUrl(base: string, path: string): string;
|
|
9
|
+
export declare function createGatewayClient(globals: GlobalOptions, apiKey: string, fetchFn: typeof fetch, extraHeaders?: Record<string, string>): GatewayClient;
|
|
10
|
+
export type CliContext = {
|
|
11
|
+
globals: GlobalOptions;
|
|
12
|
+
cwd: string;
|
|
13
|
+
stdout: Writable;
|
|
14
|
+
stderr: Writable;
|
|
15
|
+
fetch: typeof fetch;
|
|
16
|
+
deps: CliDependencies;
|
|
17
|
+
gateway?: GatewayClient;
|
|
18
|
+
};
|
|
19
|
+
export declare function withGateway(ctx: CliContext, handler: (gateway: GatewayClient, apiKey: string) => Promise<CommandResult>, extraHeaders?: Record<string, string>): Promise<CommandResult>;
|
|
20
|
+
export declare function requireConfirmation(globals: GlobalOptions, action: string): void;
|
|
21
|
+
export declare function commandPath(parts: string[]): string;
|
|
22
|
+
export declare function createContext(globals: GlobalOptions, deps?: CliDependencies): CliContext;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { resolveApiKeyWithMeta } from "./credentials.js";
|
|
2
|
+
import { CliError, exitCodeForHttpStatus, } from "./types.js";
|
|
3
|
+
export function gatewayUrl(base, path) {
|
|
4
|
+
return `${base.trim().replace(/\/+$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
|
|
5
|
+
}
|
|
6
|
+
function parseGatewayErrorBody(body, status) {
|
|
7
|
+
const nested = body.error;
|
|
8
|
+
const gatewayCode = nested && typeof nested === "object" && !Array.isArray(nested)
|
|
9
|
+
? String(nested.code ?? "")
|
|
10
|
+
: String(body.code ?? "");
|
|
11
|
+
const gatewayMessage = nested && typeof nested === "object" && !Array.isArray(nested)
|
|
12
|
+
? String(nested.message ?? "")
|
|
13
|
+
: String(body.message ?? body.error_description ?? "gateway request failed");
|
|
14
|
+
const mapped = exitCodeForHttpStatus(status);
|
|
15
|
+
return new CliError(gatewayMessage || `Gateway HTTP ${status}`, {
|
|
16
|
+
category: mapped.category,
|
|
17
|
+
code: gatewayCode || `cli.gateway.http_${status}`,
|
|
18
|
+
exitCode: mapped.exitCode,
|
|
19
|
+
details: {
|
|
20
|
+
gateway_status: status,
|
|
21
|
+
gateway_code: gatewayCode || undefined,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async function parseJsonResponse(response) {
|
|
26
|
+
const text = await response.text();
|
|
27
|
+
if (!text.trim()) {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(text);
|
|
32
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// fall through
|
|
38
|
+
}
|
|
39
|
+
throw new CliError(`Gateway returned non-JSON response (${response.status}).`, {
|
|
40
|
+
category: "gateway",
|
|
41
|
+
code: "cli.gateway.non_json",
|
|
42
|
+
exitCode: 5,
|
|
43
|
+
details: { gateway_status: response.status },
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function createGatewayClient(globals, apiKey, fetchFn, extraHeaders = {}) {
|
|
47
|
+
const headers = {
|
|
48
|
+
authorization: `Bearer ${apiKey}`,
|
|
49
|
+
"content-type": "application/json",
|
|
50
|
+
"x-request-id": globals.requestId,
|
|
51
|
+
...extraHeaders,
|
|
52
|
+
};
|
|
53
|
+
async function request(method, path, body) {
|
|
54
|
+
let response;
|
|
55
|
+
try {
|
|
56
|
+
response = await fetchFn(gatewayUrl(globals.gateway, path), {
|
|
57
|
+
method,
|
|
58
|
+
headers,
|
|
59
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
throw new CliError(err instanceof Error ? err.message : String(err), {
|
|
64
|
+
category: "network",
|
|
65
|
+
code: "cli.network.request_failed",
|
|
66
|
+
exitCode: 5,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const parsed = await parseJsonResponse(response);
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
throw parseGatewayErrorBody(parsed, response.status);
|
|
72
|
+
}
|
|
73
|
+
return parsed;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
getJson: (path) => request("GET", path),
|
|
77
|
+
postJson: (path, body) => request("POST", path, body),
|
|
78
|
+
deleteJson: (path) => request("DELETE", path),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export async function withGateway(ctx, handler, extraHeaders = {}) {
|
|
82
|
+
const resolved = await resolveApiKeyWithMeta(ctx.globals, ctx.cwd);
|
|
83
|
+
const gateway = createGatewayClient(ctx.globals, resolved.apiKey, ctx.fetch, extraHeaders);
|
|
84
|
+
const result = await handler(gateway, resolved.apiKey);
|
|
85
|
+
const warnings = [...(result.warnings ?? []), ...resolved.warnings];
|
|
86
|
+
return warnings.length ? { ...result, warnings } : result;
|
|
87
|
+
}
|
|
88
|
+
export function requireConfirmation(globals, action) {
|
|
89
|
+
if (!globals.yes) {
|
|
90
|
+
throw new CliError(`confirmation required; re-run with --yes to ${action}`, {
|
|
91
|
+
category: "confirmation_required",
|
|
92
|
+
code: "cli.confirmation.required",
|
|
93
|
+
exitCode: 4,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export function commandPath(parts) {
|
|
98
|
+
return parts.join(" ");
|
|
99
|
+
}
|
|
100
|
+
export function createContext(globals, deps = {}) {
|
|
101
|
+
return {
|
|
102
|
+
globals,
|
|
103
|
+
cwd: deps.cwd ?? process.cwd(),
|
|
104
|
+
stdout: deps.stdout ?? process.stdout,
|
|
105
|
+
stderr: deps.stderr ?? process.stderr,
|
|
106
|
+
fetch: deps.fetch ?? fetch,
|
|
107
|
+
deps,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type GlobalOptions } from "./types.js";
|
|
2
|
+
export declare function readEnvFileValue(body: string, key: string): string | undefined;
|
|
3
|
+
export declare function loadEnvFile(envFile: string, cwd: string): Promise<string | undefined>;
|
|
4
|
+
export type ResolvedApiKey = {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
warnings: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function resolveApiKeyWithMeta(globals: GlobalOptions, cwd: string): Promise<ResolvedApiKey>;
|
|
9
|
+
export declare function resolveApiKey(globals: GlobalOptions, cwd: string): Promise<string>;
|
|
10
|
+
export type CredentialSourceDescription = {
|
|
11
|
+
source: "process_env" | "env_file" | "missing";
|
|
12
|
+
env_file?: string;
|
|
13
|
+
profile?: string;
|
|
14
|
+
key_masked?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function describeCredentialSource(globals: GlobalOptions, cwd: string): Promise<CredentialSourceDescription>;
|
|
17
|
+
export declare function assertApiKeyShape(apiKey: string): void;
|
|
18
|
+
export declare function resolvedDefaultsForDoctor(globals: GlobalOptions): {
|
|
19
|
+
gateway: string;
|
|
20
|
+
envFile: string;
|
|
21
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { resolveConfigValue } from "./config.js";
|
|
4
|
+
import { CLI_WARN_ENV_FALLBACK, formatWarning } from "./automation.js";
|
|
5
|
+
import { DEFAULT_ENV_FILE, DEFAULT_GATEWAY } from "./globals.js";
|
|
6
|
+
import { CliError } from "./types.js";
|
|
7
|
+
function resolvePath(cwd, envFile) {
|
|
8
|
+
return path.isAbsolute(envFile) ? path.resolve(envFile) : path.resolve(cwd, envFile);
|
|
9
|
+
}
|
|
10
|
+
function quoteTrim(value) {
|
|
11
|
+
const trimmed = value.trim();
|
|
12
|
+
if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
13
|
+
return trimmed.slice(1, -1);
|
|
14
|
+
}
|
|
15
|
+
return trimmed;
|
|
16
|
+
}
|
|
17
|
+
export function readEnvFileValue(body, key) {
|
|
18
|
+
const prefix = `${key}=`;
|
|
19
|
+
const exportPrefix = `export ${key}=`;
|
|
20
|
+
for (const rawLine of body.split(/\r?\n/)) {
|
|
21
|
+
const line = rawLine.trim();
|
|
22
|
+
let value = "";
|
|
23
|
+
if (line.startsWith(exportPrefix)) {
|
|
24
|
+
value = line.slice(exportPrefix.length).trim();
|
|
25
|
+
}
|
|
26
|
+
else if (line.startsWith(prefix)) {
|
|
27
|
+
value = line.slice(prefix.length).trim();
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const unquoted = quoteTrim(value);
|
|
33
|
+
return unquoted || undefined;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
export async function loadEnvFile(envFile, cwd) {
|
|
38
|
+
const envPath = resolvePath(cwd, envFile);
|
|
39
|
+
try {
|
|
40
|
+
const body = await readFile(envPath, "utf8");
|
|
41
|
+
return readEnvFileValue(body, "PAYBOND_API_KEY");
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
throw new CliError(`unable to read env file ${envPath}`, {
|
|
48
|
+
category: "environment",
|
|
49
|
+
code: "cli.environment.env_file_read_failed",
|
|
50
|
+
details: { env_file: envPath },
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export async function resolveApiKeyWithMeta(globals, cwd) {
|
|
55
|
+
const warnings = [];
|
|
56
|
+
const fromProcess = process.env.PAYBOND_API_KEY?.trim();
|
|
57
|
+
if (fromProcess) {
|
|
58
|
+
warnings.push(formatWarning(CLI_WARN_ENV_FALLBACK, "using PAYBOND_API_KEY from process environment"));
|
|
59
|
+
return { apiKey: fromProcess, warnings };
|
|
60
|
+
}
|
|
61
|
+
let envFile = globals.envFile;
|
|
62
|
+
let gateway = globals.gateway;
|
|
63
|
+
if (globals.profile) {
|
|
64
|
+
const profileEnvFile = await resolveConfigValue("env_file", globals.profile);
|
|
65
|
+
const profileGateway = await resolveConfigValue("gateway", globals.profile);
|
|
66
|
+
if (profileEnvFile) {
|
|
67
|
+
envFile = profileEnvFile;
|
|
68
|
+
warnings.push(formatWarning(CLI_WARN_ENV_FALLBACK, `using profile ${globals.profile} env_file`));
|
|
69
|
+
}
|
|
70
|
+
if (profileGateway) {
|
|
71
|
+
gateway = profileGateway;
|
|
72
|
+
warnings.push(formatWarning(CLI_WARN_ENV_FALLBACK, `using profile ${globals.profile} gateway`));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
globals.envFile = envFile;
|
|
76
|
+
globals.gateway = gateway;
|
|
77
|
+
const fromFile = await loadEnvFile(envFile, cwd);
|
|
78
|
+
if (fromFile) {
|
|
79
|
+
return { apiKey: fromFile, warnings };
|
|
80
|
+
}
|
|
81
|
+
throw new CliError("missing PAYBOND_API_KEY; run paybond login or set PAYBOND_API_KEY", {
|
|
82
|
+
category: "auth",
|
|
83
|
+
code: "cli.auth.missing_api_key",
|
|
84
|
+
exitCode: 2,
|
|
85
|
+
details: { env_file: resolvePath(cwd, envFile) },
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
export async function resolveApiKey(globals, cwd) {
|
|
89
|
+
const resolved = await resolveApiKeyWithMeta(globals, cwd);
|
|
90
|
+
return resolved.apiKey;
|
|
91
|
+
}
|
|
92
|
+
export async function describeCredentialSource(globals, cwd) {
|
|
93
|
+
const { maskApiKey } = await import("./redact.js");
|
|
94
|
+
const fromProcess = process.env.PAYBOND_API_KEY?.trim();
|
|
95
|
+
if (fromProcess) {
|
|
96
|
+
return { source: "process_env", key_masked: maskApiKey(fromProcess) };
|
|
97
|
+
}
|
|
98
|
+
let envFile = globals.envFile;
|
|
99
|
+
const profile = globals.profile;
|
|
100
|
+
if (globals.profile) {
|
|
101
|
+
const profileEnvFile = await resolveConfigValue("env_file", globals.profile);
|
|
102
|
+
if (profileEnvFile) {
|
|
103
|
+
envFile = profileEnvFile;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const envPath = resolvePath(cwd, envFile);
|
|
107
|
+
try {
|
|
108
|
+
const fromFile = await loadEnvFile(envFile, cwd);
|
|
109
|
+
if (fromFile) {
|
|
110
|
+
return {
|
|
111
|
+
source: "env_file",
|
|
112
|
+
env_file: envPath,
|
|
113
|
+
profile: profile ?? undefined,
|
|
114
|
+
key_masked: maskApiKey(fromFile),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// fall through to missing
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
source: "missing",
|
|
123
|
+
env_file: envPath,
|
|
124
|
+
profile: profile ?? undefined,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function assertApiKeyShape(apiKey) {
|
|
128
|
+
if (!apiKey.startsWith("paybond_sk_")) {
|
|
129
|
+
throw new CliError("PAYBOND_API_KEY has an unexpected shape", {
|
|
130
|
+
category: "auth",
|
|
131
|
+
code: "cli.auth.invalid_api_key_shape",
|
|
132
|
+
exitCode: 2,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export function resolvedDefaultsForDoctor(globals) {
|
|
137
|
+
return {
|
|
138
|
+
gateway: globals.gateway || DEFAULT_GATEWAY,
|
|
139
|
+
envFile: globals.envFile || DEFAULT_ENV_FILE,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DoctorCheck = {
|
|
2
|
+
name: string;
|
|
3
|
+
ok: boolean;
|
|
4
|
+
message: string;
|
|
5
|
+
details?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
export declare function packageVersion(): string;
|
|
8
|
+
export declare function encodeMcpMessage(payload: Record<string, unknown>): Buffer;
|
|
9
|
+
export declare function runAgentMcpChecks(input: {
|
|
10
|
+
envFile: string;
|
|
11
|
+
cwd: string;
|
|
12
|
+
host?: string;
|
|
13
|
+
serverCommand?: string[];
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}): Promise<DoctorCheck[]>;
|