@bctrl/cli 0.1.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/README.md +44 -0
- package/dist/api/auth.d.ts +15 -0
- package/dist/api/auth.js +32 -0
- package/dist/api/client.d.ts +22 -0
- package/dist/api/client.js +130 -0
- package/dist/api/errors.d.ts +2 -0
- package/dist/api/errors.js +95 -0
- package/dist/bin/bctrl.d.ts +2 -0
- package/dist/bin/bctrl.js +6 -0
- package/dist/commands/ai/index.d.ts +3 -0
- package/dist/commands/ai/index.js +130 -0
- package/dist/commands/auth/index.d.ts +3 -0
- package/dist/commands/auth/index.js +13 -0
- package/dist/commands/auth/login.d.ts +11 -0
- package/dist/commands/auth/login.js +52 -0
- package/dist/commands/auth/logout.d.ts +10 -0
- package/dist/commands/auth/logout.js +23 -0
- package/dist/commands/auth/status.d.ts +12 -0
- package/dist/commands/auth/status.js +31 -0
- package/dist/commands/auth/token.d.ts +11 -0
- package/dist/commands/auth/token.js +24 -0
- package/dist/commands/browser/index.d.ts +3 -0
- package/dist/commands/browser/index.js +53 -0
- package/dist/commands/file/index.d.ts +3 -0
- package/dist/commands/file/index.js +88 -0
- package/dist/commands/invocation/index.d.ts +3 -0
- package/dist/commands/invocation/index.js +36 -0
- package/dist/commands/run/index.d.ts +3 -0
- package/dist/commands/run/index.js +247 -0
- package/dist/commands/runtime/index.d.ts +3 -0
- package/dist/commands/runtime/index.js +197 -0
- package/dist/commands/shared/hidden-input.d.ts +2 -0
- package/dist/commands/shared/hidden-input.js +60 -0
- package/dist/commands/shared/io.d.ts +9 -0
- package/dist/commands/shared/io.js +58 -0
- package/dist/commands/shared/options.d.ts +2 -0
- package/dist/commands/shared/options.js +15 -0
- package/dist/commands/shared/output.d.ts +10 -0
- package/dist/commands/shared/output.js +105 -0
- package/dist/commands/shared/rest.d.ts +54 -0
- package/dist/commands/shared/rest.js +121 -0
- package/dist/commands/space/index.d.ts +3 -0
- package/dist/commands/space/index.js +86 -0
- package/dist/commands/space/list.d.ts +13 -0
- package/dist/commands/space/list.js +25 -0
- package/dist/commands/subaccount/index.d.ts +3 -0
- package/dist/commands/subaccount/index.js +162 -0
- package/dist/commands/tool/index.d.ts +3 -0
- package/dist/commands/tool/index.js +40 -0
- package/dist/commands/tool-call/index.d.ts +3 -0
- package/dist/commands/tool-call/index.js +25 -0
- package/dist/commands/toolset/index.d.ts +3 -0
- package/dist/commands/toolset/index.js +33 -0
- package/dist/commands/vault/index.d.ts +3 -0
- package/dist/commands/vault/index.js +96 -0
- package/dist/commands/version/version.d.ts +9 -0
- package/dist/commands/version/version.js +14 -0
- package/dist/config/auth-store.d.ts +37 -0
- package/dist/config/auth-store.js +71 -0
- package/dist/config/config.d.ts +12 -0
- package/dist/config/config.js +35 -0
- package/dist/factory.d.ts +15 -0
- package/dist/factory.js +15 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/io/streams.d.ts +22 -0
- package/dist/io/streams.js +42 -0
- package/dist/root.d.ts +3 -0
- package/dist/root.js +40 -0
- package/dist/runtime/errors.d.ts +19 -0
- package/dist/runtime/errors.js +23 -0
- package/dist/runtime/exit-codes.d.ts +7 -0
- package/dist/runtime/exit-codes.js +6 -0
- package/dist/runtime/main.d.ts +1 -0
- package/dist/runtime/main.js +27 -0
- package/package.json +47 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { readStoredAuth } from './auth-store.js';
|
|
3
|
+
const DEFAULT_API_BASE_URL = 'https://api.bctrl.ai/v2';
|
|
4
|
+
const EnvSchema = z.object({
|
|
5
|
+
BCTRL_API_KEY: z.string().optional(),
|
|
6
|
+
BCTRL_API_URL: z.string().url().optional(),
|
|
7
|
+
});
|
|
8
|
+
export async function loadConfig(env = process.env) {
|
|
9
|
+
const parsed = EnvSchema.parse(env);
|
|
10
|
+
const apiBaseUrl = normalizeApiBaseUrl(parsed.BCTRL_API_URL ?? DEFAULT_API_BASE_URL);
|
|
11
|
+
const apiKey = parsed.BCTRL_API_KEY?.trim();
|
|
12
|
+
if (apiKey) {
|
|
13
|
+
return {
|
|
14
|
+
apiBaseUrl,
|
|
15
|
+
activeToken: { token: apiKey, source: 'BCTRL_API_KEY' },
|
|
16
|
+
storedAuth: null,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const storedAuth = await readStoredAuth(env);
|
|
20
|
+
const activeToken = resolveStoredToken(apiBaseUrl, storedAuth);
|
|
21
|
+
return {
|
|
22
|
+
apiBaseUrl,
|
|
23
|
+
activeToken,
|
|
24
|
+
storedAuth,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function resolveStoredToken(apiBaseUrl, storedAuth) {
|
|
28
|
+
if (storedAuth && normalizeApiBaseUrl(storedAuth.apiBaseUrl) === apiBaseUrl) {
|
|
29
|
+
return { token: storedAuth.token, source: 'stored' };
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function normalizeApiBaseUrl(url) {
|
|
34
|
+
return url.replace(/\/+$/, '');
|
|
35
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type BctrlApiClient } from './api/client.js';
|
|
2
|
+
import { type BctrlConfig } from './config/config.js';
|
|
3
|
+
import type { IOStreams } from './io/streams.js';
|
|
4
|
+
export type Factory = {
|
|
5
|
+
version: string;
|
|
6
|
+
io: IOStreams;
|
|
7
|
+
config: () => Promise<BctrlConfig>;
|
|
8
|
+
apiClient: () => Promise<BctrlApiClient>;
|
|
9
|
+
};
|
|
10
|
+
type CreateFactoryOptions = {
|
|
11
|
+
io: IOStreams;
|
|
12
|
+
version?: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function createFactory(options: CreateFactoryOptions): Factory;
|
|
15
|
+
export {};
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createBctrlApiClient } from './api/client.js';
|
|
2
|
+
import { loadConfig } from './config/config.js';
|
|
3
|
+
export function createFactory(options) {
|
|
4
|
+
let configPromise;
|
|
5
|
+
const config = () => {
|
|
6
|
+
configPromise ??= loadConfig();
|
|
7
|
+
return configPromise;
|
|
8
|
+
};
|
|
9
|
+
return {
|
|
10
|
+
version: options.version ?? '0.1.0',
|
|
11
|
+
io: options.io,
|
|
12
|
+
config,
|
|
13
|
+
apiClient: async () => createBctrlApiClient(await config()),
|
|
14
|
+
};
|
|
15
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Readable, Writable } from 'node:stream';
|
|
2
|
+
export type IOStreams = {
|
|
3
|
+
in: Readable;
|
|
4
|
+
out: Writable;
|
|
5
|
+
err: Writable;
|
|
6
|
+
isStdinTTY: () => boolean;
|
|
7
|
+
isStdoutTTY: () => boolean;
|
|
8
|
+
isStderrTTY: () => boolean;
|
|
9
|
+
canPrompt: () => boolean;
|
|
10
|
+
colorEnabled: () => boolean;
|
|
11
|
+
writeOut: (text: string) => void;
|
|
12
|
+
writeErr: (text: string) => void;
|
|
13
|
+
};
|
|
14
|
+
type IOStreamsOptions = {
|
|
15
|
+
in: Readable;
|
|
16
|
+
out: Writable;
|
|
17
|
+
err: Writable;
|
|
18
|
+
env?: NodeJS.ProcessEnv;
|
|
19
|
+
};
|
|
20
|
+
export declare function createIOStreams(options: IOStreamsOptions): IOStreams;
|
|
21
|
+
export declare function createSystemIOStreams(): IOStreams;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { isatty } from 'node:tty';
|
|
2
|
+
function streamIsTTY(stream, fallbackFd) {
|
|
3
|
+
if (typeof stream.isTTY === 'boolean') {
|
|
4
|
+
return Boolean(stream.isTTY);
|
|
5
|
+
}
|
|
6
|
+
return fallbackFd === undefined ? false : isatty(fallbackFd);
|
|
7
|
+
}
|
|
8
|
+
export function createIOStreams(options) {
|
|
9
|
+
const env = options.env ?? process.env;
|
|
10
|
+
const io = {
|
|
11
|
+
in: options.in,
|
|
12
|
+
out: options.out,
|
|
13
|
+
err: options.err,
|
|
14
|
+
isStdinTTY: () => streamIsTTY(options.in, 0),
|
|
15
|
+
isStdoutTTY: () => streamIsTTY(options.out, 1),
|
|
16
|
+
isStderrTTY: () => streamIsTTY(options.err, 2),
|
|
17
|
+
canPrompt: () => io.isStdinTTY() && io.isStdoutTTY() && env.BCTRL_PROMPT_DISABLED !== '1',
|
|
18
|
+
colorEnabled: () => {
|
|
19
|
+
if (env.NO_COLOR !== undefined)
|
|
20
|
+
return false;
|
|
21
|
+
if (env.CLICOLOR_FORCE && env.CLICOLOR_FORCE !== '0')
|
|
22
|
+
return true;
|
|
23
|
+
if (env.CLICOLOR === '0')
|
|
24
|
+
return false;
|
|
25
|
+
return io.isStdoutTTY();
|
|
26
|
+
},
|
|
27
|
+
writeOut: (text) => {
|
|
28
|
+
options.out.write(text);
|
|
29
|
+
},
|
|
30
|
+
writeErr: (text) => {
|
|
31
|
+
options.err.write(text);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
return io;
|
|
35
|
+
}
|
|
36
|
+
export function createSystemIOStreams() {
|
|
37
|
+
return createIOStreams({
|
|
38
|
+
in: process.stdin,
|
|
39
|
+
out: process.stdout,
|
|
40
|
+
err: process.stderr,
|
|
41
|
+
});
|
|
42
|
+
}
|
package/dist/root.d.ts
ADDED
package/dist/root.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { createAiCommand } from './commands/ai/index.js';
|
|
3
|
+
import { createAuthCommand } from './commands/auth/index.js';
|
|
4
|
+
import { createBrowserCommand } from './commands/browser/index.js';
|
|
5
|
+
import { createFileCommand } from './commands/file/index.js';
|
|
6
|
+
import { createInvocationCommand } from './commands/invocation/index.js';
|
|
7
|
+
import { createRunCommand } from './commands/run/index.js';
|
|
8
|
+
import { createRuntimeCommand } from './commands/runtime/index.js';
|
|
9
|
+
import { createSpaceCommand } from './commands/space/index.js';
|
|
10
|
+
import { createSubaccountCommand } from './commands/subaccount/index.js';
|
|
11
|
+
import { createToolCommand } from './commands/tool/index.js';
|
|
12
|
+
import { createToolCallCommand } from './commands/tool-call/index.js';
|
|
13
|
+
import { createToolsetCommand } from './commands/toolset/index.js';
|
|
14
|
+
import { createVaultCommand } from './commands/vault/index.js';
|
|
15
|
+
import { createVersionCommand } from './commands/version/version.js';
|
|
16
|
+
export function createRootCommand(factory) {
|
|
17
|
+
const command = new Command();
|
|
18
|
+
command
|
|
19
|
+
.name('bctrl')
|
|
20
|
+
.description('BCTRL command-line interface')
|
|
21
|
+
.usage('<command> [flags]')
|
|
22
|
+
.showHelpAfterError()
|
|
23
|
+
.showSuggestionAfterError()
|
|
24
|
+
.option('--no-color', 'Disable color output');
|
|
25
|
+
command.addCommand(createVersionCommand(factory));
|
|
26
|
+
command.addCommand(createAuthCommand(factory));
|
|
27
|
+
command.addCommand(createAiCommand(factory));
|
|
28
|
+
command.addCommand(createBrowserCommand(factory));
|
|
29
|
+
command.addCommand(createFileCommand(factory));
|
|
30
|
+
command.addCommand(createInvocationCommand(factory));
|
|
31
|
+
command.addCommand(createRunCommand(factory));
|
|
32
|
+
command.addCommand(createRuntimeCommand(factory));
|
|
33
|
+
command.addCommand(createSpaceCommand(factory));
|
|
34
|
+
command.addCommand(createSubaccountCommand(factory));
|
|
35
|
+
command.addCommand(createToolCommand(factory));
|
|
36
|
+
command.addCommand(createToolsetCommand(factory));
|
|
37
|
+
command.addCommand(createToolCallCommand(factory));
|
|
38
|
+
command.addCommand(createVaultCommand(factory));
|
|
39
|
+
return command;
|
|
40
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ApiErrorInfo = {
|
|
2
|
+
status: number;
|
|
3
|
+
code?: string;
|
|
4
|
+
requestId?: string;
|
|
5
|
+
details?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
export declare class CliError extends Error {
|
|
8
|
+
readonly exitCode: number;
|
|
9
|
+
readonly apiError?: ApiErrorInfo;
|
|
10
|
+
constructor(message: string, options?: {
|
|
11
|
+
exitCode?: number;
|
|
12
|
+
cause?: unknown;
|
|
13
|
+
apiError?: ApiErrorInfo;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export declare class AuthError extends CliError {
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
export declare function errorMessage(error: unknown): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class CliError extends Error {
|
|
2
|
+
exitCode;
|
|
3
|
+
apiError;
|
|
4
|
+
constructor(message, options) {
|
|
5
|
+
super(message, { cause: options?.cause });
|
|
6
|
+
this.name = 'CliError';
|
|
7
|
+
this.exitCode = options?.exitCode ?? 1;
|
|
8
|
+
this.apiError = options?.apiError;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class AuthError extends CliError {
|
|
12
|
+
constructor(message = 'BCTRL_API_KEY is required') {
|
|
13
|
+
super(`${message}\n\nRun:\n bctrl auth login\n\nOr set:\n export BCTRL_API_KEY=...`, {
|
|
14
|
+
exitCode: 4,
|
|
15
|
+
});
|
|
16
|
+
this.name = 'AuthError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function errorMessage(error) {
|
|
20
|
+
if (error instanceof Error)
|
|
21
|
+
return error.message;
|
|
22
|
+
return String(error);
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function main(argv: string[]): Promise<number>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InvalidArgumentError } from 'commander';
|
|
2
|
+
import { createFactory } from '../factory.js';
|
|
3
|
+
import { createSystemIOStreams } from '../io/streams.js';
|
|
4
|
+
import { createRootCommand } from '../root.js';
|
|
5
|
+
import { CliError, errorMessage } from './errors.js';
|
|
6
|
+
import { ExitCode } from './exit-codes.js';
|
|
7
|
+
export async function main(argv) {
|
|
8
|
+
const io = createSystemIOStreams();
|
|
9
|
+
const factory = createFactory({ io });
|
|
10
|
+
const root = createRootCommand(factory);
|
|
11
|
+
try {
|
|
12
|
+
await root.parseAsync(argv, { from: 'user' });
|
|
13
|
+
return ExitCode.Ok;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (error instanceof InvalidArgumentError) {
|
|
17
|
+
io.writeErr(`${error.message}\n`);
|
|
18
|
+
return ExitCode.Error;
|
|
19
|
+
}
|
|
20
|
+
if (error instanceof CliError) {
|
|
21
|
+
io.writeErr(`${error.message}\n`);
|
|
22
|
+
return error.exitCode;
|
|
23
|
+
}
|
|
24
|
+
io.writeErr(`${errorMessage(error)}\n`);
|
|
25
|
+
return ExitCode.Error;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bctrl/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "BCTRL command-line interface",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"bctrl": "./dist/bin/bctrl.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"clean": "rm -rf dist",
|
|
20
|
+
"build": "pnpm run clean && tsc -p tsconfig.json",
|
|
21
|
+
"dev": "tsx src/bin/bctrl.ts",
|
|
22
|
+
"prepack": "pnpm run build",
|
|
23
|
+
"test": "tsx --test \"tests/**/*.test.ts\"",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"typecheck:tests": "tsc --noEmit -p tests/tsconfig.json"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"bctrl",
|
|
29
|
+
"cli",
|
|
30
|
+
"browser-automation",
|
|
31
|
+
"agents"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "ISC",
|
|
35
|
+
"packageManager": "pnpm@10.12.4",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"commander": "^14.0.3",
|
|
38
|
+
"handlebars": "^4.7.9",
|
|
39
|
+
"jq-web": "^0.6.2",
|
|
40
|
+
"zod": "^4.4.3"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^25.7.0",
|
|
44
|
+
"tsx": "^4.21.0",
|
|
45
|
+
"typescript": "^6.0.3"
|
|
46
|
+
}
|
|
47
|
+
}
|