@vendian/cli 0.0.2 → 0.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vendian/cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "description": "Public Vendian CLI bootstrapper and launcher",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -10,17 +10,24 @@
10
10
  },
11
11
  "type": "module",
12
12
  "bin": {
13
- "vendian": "bin/vendian.js"
13
+ "vendian": "bin/vendian.cjs"
14
14
  },
15
15
  "files": [
16
16
  "bin/",
17
- "src/",
17
+ "cli-wrapper.cjs",
18
+ "LICENSE",
18
19
  "README.md"
19
20
  ],
20
21
  "scripts": {
22
+ "build": "node scripts/build-package.mjs",
23
+ "prepack": "npm run build",
24
+ "prepublishOnly": "npm test",
21
25
  "test": "node --test"
22
26
  },
23
27
  "engines": {
24
28
  "node": ">=18.18.0"
29
+ },
30
+ "devDependencies": {
31
+ "esbuild": "^0.28.0"
25
32
  }
26
33
  }
package/bin/vendian.js DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
- import { main } from '../src/main.js';
3
-
4
- main(process.argv.slice(2)).catch((error) => {
5
- const message = error && typeof error.message === 'string' ? error.message : String(error);
6
- console.error(`[vendian] ${message}`);
7
- process.exitCode = 1;
8
- });
package/src/auth.js DELETED
@@ -1,265 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import http from 'node:http';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import { spawnSync } from 'node:child_process';
6
- import { BACKEND_TARGETS } from './constants.js';
7
-
8
- const DEFAULT_OAUTH_REDIRECT_PORT = 8765;
9
-
10
- export function resolveApiUrl({ backend, apiUrl, env = process.env } = {}) {
11
- if (apiUrl) {
12
- return apiUrl.replace(/\/$/, '');
13
- }
14
- if (env.VENDIAN_API_URL) {
15
- return env.VENDIAN_API_URL.replace(/\/$/, '');
16
- }
17
- const target = backend || 'prod';
18
- const resolved = BACKEND_TARGETS[target];
19
- if (!resolved) {
20
- throw new Error(`Unknown Vendian backend '${target}'. Use local, dev, staging, prod, or --api-url.`);
21
- }
22
- return resolved;
23
- }
24
-
25
- export async function loginWithVendianOAuth({ backend, apiUrl, noBrowser = false, env = process.env } = {}) {
26
- const resolvedApiUrl = resolveApiUrl({ backend, apiUrl, env });
27
- const callback = await createCallbackServer(env);
28
- try {
29
- const config = await getOAuthConfig(resolvedApiUrl, callback.redirectUri);
30
- const codeVerifier = crypto.randomBytes(48).toString('base64url');
31
- const codeChallenge = crypto.createHash('sha256').update(codeVerifier).digest('base64url');
32
- const state = crypto.randomBytes(18).toString('base64url');
33
- const authorizationUrl = authorizationUrlFor(config, { state, codeChallenge });
34
-
35
- if (noBrowser) {
36
- console.error(`Open this URL to authenticate the CLI: ${authorizationUrl}`);
37
- } else {
38
- openBrowser(authorizationUrl);
39
- }
40
-
41
- const callbackResult = await callback.wait();
42
- if (callbackResult.state !== state) {
43
- throw new Error('OAuth state mismatch');
44
- }
45
- const clerkToken = await exchangeCodeForClerkToken(config, callbackResult.code, codeVerifier, callback.redirectUri);
46
- const exchange = await postJson(`${resolvedApiUrl}/api/v1/cli/auth/oauth/exchange`, {
47
- clerkToken
48
- });
49
- return { apiUrl: resolvedApiUrl, ...exchange };
50
- } finally {
51
- await callback.close();
52
- }
53
- }
54
-
55
- export function loadCloudConfig(env = process.env, platform = process.platform) {
56
- const file = cloudConfigPath(env, platform);
57
- try {
58
- const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
59
- return parsed && typeof parsed === 'object' ? parsed : {};
60
- } catch {
61
- return {};
62
- }
63
- }
64
-
65
- export function cloudAuthStatus({ backend, apiUrl, env = process.env, platform = process.platform } = {}) {
66
- const targetApiUrl = resolveApiUrl({ backend, apiUrl, env });
67
- const config = loadCloudConfig(env, platform);
68
- const profiles = config.profiles && typeof config.profiles === 'object' ? config.profiles : {};
69
- const profile = profiles[targetApiUrl];
70
- return {
71
- apiUrl: targetApiUrl,
72
- activeApiUrl: typeof config.active_api_url === 'string' ? config.active_api_url : undefined,
73
- profile: profile && typeof profile === 'object' ? profile : undefined,
74
- authenticated: Boolean(profile?.access_token),
75
- email: typeof profile?.email === 'string' ? profile.email : undefined,
76
- expiresAt: typeof profile?.expires_at === 'string' ? profile.expires_at : undefined,
77
- profiles
78
- };
79
- }
80
-
81
- async function getOAuthConfig(apiUrl, redirectUri) {
82
- const url = new URL(`${apiUrl}/api/v1/cli/auth/oauth/config`);
83
- url.searchParams.set('redirectUri', redirectUri);
84
- return getJson(url);
85
- }
86
-
87
- function authorizationUrlFor(config, { state, codeChallenge }) {
88
- const url = new URL(String(config.authorizationUrl));
89
- url.searchParams.set('response_type', 'code');
90
- url.searchParams.set('client_id', String(config.clientId));
91
- url.searchParams.set('redirect_uri', String(config.redirectUri));
92
- url.searchParams.set('scope', String(config.scopes || 'email profile'));
93
- url.searchParams.set('state', state);
94
- url.searchParams.set('code_challenge', codeChallenge);
95
- url.searchParams.set('code_challenge_method', 'S256');
96
- return url.toString();
97
- }
98
-
99
- async function exchangeCodeForClerkToken(config, code, codeVerifier, redirectUri) {
100
- const body = new URLSearchParams({
101
- grant_type: 'authorization_code',
102
- client_id: String(config.clientId),
103
- code,
104
- redirect_uri: redirectUri,
105
- code_verifier: codeVerifier
106
- });
107
- const payload = await postForm(String(config.tokenUrl), body);
108
- const token = payload.access_token || payload.id_token;
109
- if (!token) {
110
- throw new Error('OAuth token exchange did not return a Clerk token');
111
- }
112
- return String(token);
113
- }
114
-
115
- async function getJson(url) {
116
- const response = await fetch(url, { headers: { Accept: 'application/json' } });
117
- return decodeResponse(response);
118
- }
119
-
120
- async function postJson(url, body) {
121
- const response = await fetch(url, {
122
- method: 'POST',
123
- headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
124
- body: JSON.stringify(body)
125
- });
126
- return decodeResponse(response);
127
- }
128
-
129
- async function postForm(url, body) {
130
- const response = await fetch(url, {
131
- method: 'POST',
132
- headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
133
- body
134
- });
135
- return decodeResponse(response);
136
- }
137
-
138
- async function decodeResponse(response) {
139
- const text = await response.text();
140
- let payload = {};
141
- if (text) {
142
- try {
143
- payload = JSON.parse(text);
144
- } catch {
145
- payload = { error: text };
146
- }
147
- }
148
- if (!response.ok) {
149
- throw new Error(payload.message || payload.error || `HTTP ${response.status}`);
150
- }
151
- return payload;
152
- }
153
-
154
- async function createCallbackServer(env) {
155
- const port = Number(env.VENDIAN_CLI_OAUTH_REDIRECT_PORT || DEFAULT_OAUTH_REDIRECT_PORT);
156
- let server;
157
- let settled = false;
158
- let timeout;
159
- const waitPromise = new Promise((resolve, reject) => {
160
- timeout = setTimeout(() => {
161
- settled = true;
162
- reject(new Error('OAuth login timed out before callback completed'));
163
- }, 300_000);
164
- server = http.createServer((req, res) => {
165
- const url = new URL(req.url || '/', `http://${req.headers.host || '127.0.0.1'}`);
166
- const code = url.searchParams.get('code');
167
- const state = url.searchParams.get('state');
168
- const error = url.searchParams.get('error');
169
- const body = code
170
- ? 'Vendian CLI authentication complete. You can close this window.'
171
- : 'Vendian CLI authentication failed. Return to the terminal.';
172
- res.writeHead(code ? 200 : 400, {
173
- 'Content-Type': 'text/plain; charset=utf-8',
174
- 'Content-Length': Buffer.byteLength(body)
175
- });
176
- res.end(body);
177
- clearTimeout(timeout);
178
- if (settled) {
179
- return;
180
- }
181
- settled = true;
182
- if (error) {
183
- reject(new Error(`OAuth login failed: ${error}`));
184
- return;
185
- }
186
- if (!code) {
187
- reject(new Error('OAuth callback did not include an authorization code'));
188
- return;
189
- }
190
- resolve({ code, state });
191
- });
192
- server.on('error', reject);
193
- server.listen(port, '127.0.0.1');
194
- });
195
- await new Promise((resolve, reject) => {
196
- server.once('listening', resolve);
197
- server.once('error', reject);
198
- });
199
-
200
- return {
201
- redirectUri: `http://127.0.0.1:${server.address().port}/callback`,
202
- wait: () => waitPromise,
203
- close: () => new Promise((resolve) => server.close(resolve))
204
- };
205
- }
206
-
207
- function openBrowser(url) {
208
- const platform = process.platform;
209
- if (platform === 'win32') {
210
- spawnSync(...buildWindowsOpenCommand(url), { stdio: 'ignore', shell: false });
211
- return;
212
- }
213
- if (platform === 'darwin') {
214
- spawnSync('open', [url], { stdio: 'ignore', shell: false });
215
- return;
216
- }
217
- spawnSync('xdg-open', [url], { stdio: 'ignore', shell: false });
218
- }
219
-
220
- export function buildWindowsOpenCommand(url) {
221
- return ['rundll32.exe', ['url.dll,FileProtocolHandler', String(url)]];
222
- }
223
-
224
- export function cloudConfigPath(env = process.env, platform = process.platform) {
225
- if (env.VENDIAN_CLOUD_CONFIG) {
226
- return path.resolve(env.VENDIAN_CLOUD_CONFIG);
227
- }
228
- if (platform === 'win32') {
229
- const root = env.APPDATA || path.join(process.env.USERPROFILE || '', 'AppData', 'Roaming');
230
- return path.win32.join(root, 'Vendian', 'cloud-auth.json');
231
- }
232
- const root = env.XDG_CONFIG_HOME || path.join(process.env.HOME || '', '.config');
233
- return path.posix.join(root, 'vendian', 'cloud-auth.json');
234
- }
235
-
236
- export function saveCloudToken(token, { env = process.env, platform = process.platform } = {}) {
237
- const file = cloudConfigPath(env, platform);
238
- let raw = { version: 2, profiles: {}, active_api_url: token.apiUrl };
239
- try {
240
- const existing = JSON.parse(fs.readFileSync(file, 'utf8'));
241
- if (existing && typeof existing === 'object' && existing.profiles && typeof existing.profiles === 'object') {
242
- raw.profiles = existing.profiles;
243
- }
244
- } catch {
245
- // Missing or invalid config is replaced.
246
- }
247
- raw.active_api_url = token.apiUrl;
248
- raw.profiles[token.apiUrl] = {
249
- api_url: token.apiUrl,
250
- access_token: token.accessToken,
251
- user_id: token.userId,
252
- email: token.email,
253
- expires_at: token.expiresAt,
254
- scopes: token.scopes,
255
- tooling_eligible: token.toolingEligible
256
- };
257
- fs.mkdirSync(path.dirname(file), { recursive: true });
258
- fs.writeFileSync(file, `${JSON.stringify(raw, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
259
- try {
260
- fs.chmodSync(file, 0o600);
261
- } catch {
262
- // Best effort on Windows filesystems.
263
- }
264
- return file;
265
- }
package/src/config.js DELETED
@@ -1,40 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { CONFIG_VERSION } from './constants.js';
4
- import { configPath } from './paths.js';
5
-
6
- export function loadConfig(env = process.env, platform = process.platform) {
7
- const file = configPath(env, platform);
8
- try {
9
- const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
10
- return typeof parsed === 'object' && parsed !== null ? parsed : {};
11
- } catch (error) {
12
- if (error && error.code === 'ENOENT') {
13
- return {};
14
- }
15
- return {};
16
- }
17
- }
18
-
19
- export function saveConfig(config, env = process.env, platform = process.platform) {
20
- const file = configPath(env, platform);
21
- fs.mkdirSync(path.dirname(file), { recursive: true });
22
- const next = { version: CONFIG_VERSION, ...config };
23
- fs.writeFileSync(file, `${JSON.stringify(next, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 });
24
- try {
25
- fs.chmodSync(file, 0o600);
26
- } catch {
27
- // Best effort on Windows filesystems.
28
- }
29
- return file;
30
- }
31
-
32
- export function redact(value) {
33
- if (!value || typeof value !== 'string') {
34
- return value;
35
- }
36
- if (value.length <= 8) {
37
- return '********';
38
- }
39
- return `${value.slice(0, 4)}...${value.slice(-4)}`;
40
- }
package/src/constants.js DELETED
@@ -1,15 +0,0 @@
1
- export const DEFAULT_GITLAB_HOST = 'gitlab.com';
2
- export const DEFAULT_SDK_PUBLIC_PROJECT_ID = '77150592';
3
- export const DEFAULT_SDK_RUNTIME_PROJECT_ID = '79410876';
4
- export const PUBLIC_PACKAGE = 'vendian-agents[full]';
5
- export const RUNTIME_PACKAGE = 'vendian-agents-runtime';
6
- export const CONFIG_VERSION = 1;
7
-
8
- export const BACKEND_TARGETS = {
9
- local: 'http://localhost:3000',
10
- localhost: 'http://localhost:3000',
11
- dev: 'https://api.dev.vendian.ai',
12
- staging: 'https://api.staging.vendian.ai',
13
- prod: 'https://api.vendian.ai',
14
- production: 'https://api.vendian.ai'
15
- };
package/src/doctor.js DELETED
@@ -1,22 +0,0 @@
1
- import fs from 'node:fs';
2
- import { loadConfig } from './config.js';
3
- import { registryConfig } from './install.js';
4
- import { managedVenvPath, venvPython, venvVendian } from './paths.js';
5
- import { findPython, hasUv, pythonVersion, verifyVendianImports } from './python.js';
6
-
7
- export function doctor({ env = process.env, platform = process.platform } = {}) {
8
- const config = loadConfig(env, platform);
9
- const venvPath = managedVenvPath(env, platform);
10
- const pythonPath = venvPython(venvPath, platform);
11
- const vendianPath = venvVendian(venvPath, platform);
12
- const registry = registryConfig(config, env, platform);
13
-
14
- console.log('Vendian doctor');
15
- console.log(`Home: ${venvPath}`);
16
- console.log(`System Python 3.11+: ${findPython(platform) ? 'yes' : 'no'}`);
17
- console.log(`uv: ${hasUv() ? 'yes' : 'no, will use pip fallback'}`);
18
- console.log(`Managed Python: ${fs.existsSync(pythonPath) ? pythonVersion(pythonPath) || 'present' : 'missing'}`);
19
- console.log(`Vendian executable: ${fs.existsSync(vendianPath) ? vendianPath : 'missing'}`);
20
- console.log(`Vendian imports: ${fs.existsSync(pythonPath) && verifyVendianImports(pythonPath) ? 'ok' : 'missing'}`);
21
- console.log(`Package access: ${registry.token ? `configured (${registry.tokenSource})` : 'missing'}`);
22
- }
package/src/forward.js DELETED
@@ -1,47 +0,0 @@
1
- import fs from 'node:fs';
2
- import { loadConfig, saveConfig } from './config.js';
3
- import { installVendianPackages, registryConfig } from './install.js';
4
- import { managedVenvPath, venvPython, venvVendian } from './paths.js';
5
- import { spawnForward } from './process.js';
6
-
7
- const AUTO_UPDATE_INTERVAL_MS = 24 * 60 * 60 * 1000;
8
-
9
- export async function forwardToPythonVendian(args, { env = process.env, platform = process.platform } = {}) {
10
- const venvPath = managedVenvPath(env, platform);
11
- const vendianPath = venvVendian(venvPath, platform);
12
- if (!fs.existsSync(vendianPath)) {
13
- throw new Error('Vendian is not set up yet. Run `vendian login` first.');
14
- }
15
- maybeAutoUpdateManagedEnv({ env, platform, venvPath });
16
- const code = await spawnForward(vendianPath, args, { env });
17
- process.exitCode = code;
18
- }
19
-
20
- export function maybeAutoUpdateManagedEnv({ env = process.env, platform = process.platform, venvPath = managedVenvPath(env, platform) } = {}) {
21
- if (env.VENDIAN_SKIP_AUTO_UPDATE === '1') {
22
- return false;
23
- }
24
- const config = loadConfig(env, platform);
25
- const lastUpdate = Date.parse(config.lastManagedUpdateAt || '');
26
- if (Number.isFinite(lastUpdate) && Date.now() - lastUpdate < AUTO_UPDATE_INTERVAL_MS) {
27
- return false;
28
- }
29
- const registry = registryConfig(config, env);
30
- if (!registry.token) {
31
- return false;
32
- }
33
- const pythonPath = venvPython(venvPath, platform);
34
- if (!fs.existsSync(pythonPath)) {
35
- return false;
36
- }
37
- try {
38
- console.error('[vendian] Checking managed CLI/runtime updates...');
39
- installVendianPackages({ pythonPath, venvPath, config, env });
40
- saveConfig({ ...config, lastManagedUpdateAt: new Date().toISOString() }, env, platform);
41
- return true;
42
- } catch (error) {
43
- const message = error && typeof error.message === 'string' ? error.message : String(error);
44
- console.error(`[vendian] Update check failed; continuing with installed CLI. ${message}`);
45
- return false;
46
- }
47
- }
package/src/install.js DELETED
@@ -1,105 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import {
4
- DEFAULT_GITLAB_HOST,
5
- DEFAULT_SDK_PUBLIC_PROJECT_ID,
6
- DEFAULT_SDK_RUNTIME_PROJECT_ID,
7
- PUBLIC_PACKAGE,
8
- RUNTIME_PACKAGE
9
- } from './constants.js';
10
- import { runInherit } from './process.js';
11
- import { hasUv } from './python.js';
12
- import { loadPackageTokenSecret } from './secret-store.js';
13
-
14
- export function registryConfig(config = {}, env = process.env, platform = process.platform) {
15
- const gitlabHost = env.GITLAB_HOST || config.gitlabHost || DEFAULT_GITLAB_HOST;
16
- const username = env.GITLAB_USERNAME || config.gitlabUsername || '__token__';
17
- const sdkProjectId = env.SDK_PUBLIC_PROJECT_ID || config.sdkPublicProjectId || DEFAULT_SDK_PUBLIC_PROJECT_ID;
18
- const runtimeProjectId = env.SDK_RUNTIME_PROJECT_ID || config.sdkRuntimeProjectId || DEFAULT_SDK_RUNTIME_PROJECT_ID;
19
- const secretToken = loadPackageTokenSecret(config, platform);
20
- const token = env.GITLAB_TOKEN || config.gitlabToken || secretToken || '';
21
- const tokenSource = env.GITLAB_TOKEN ? 'env' : config.gitlabToken ? 'config' : secretToken ? 'secret-store' : 'missing';
22
- const vendianAgentsVersion = env.VENDIAN_AGENTS_VERSION || config.vendianAgentsVersion || '';
23
- const vendianRuntimeVersion = env.VENDIAN_AGENTS_RUNTIME_VERSION || config.vendianAgentsRuntimeVersion || '';
24
-
25
- return {
26
- gitlabHost,
27
- username,
28
- sdkProjectId,
29
- runtimeProjectId,
30
- token,
31
- tokenSource,
32
- vendianAgentsVersion,
33
- vendianRuntimeVersion
34
- };
35
- }
36
-
37
- export function buildIndexUrls(registry) {
38
- if (!registry.token) {
39
- return null;
40
- }
41
- const username = encodeURIComponent(registry.username || '__token__');
42
- const token = encodeURIComponent(registry.token);
43
- const sdkIndexUrl = `https://${username}:${token}@${registry.gitlabHost}/api/v4/projects/${registry.sdkProjectId}/packages/pypi/simple`;
44
- const runtimeIndexUrl = `https://${username}:${token}@${registry.gitlabHost}/api/v4/projects/${registry.runtimeProjectId}/packages/pypi/simple`;
45
- return { sdkIndexUrl, runtimeIndexUrl };
46
- }
47
-
48
- export function packageSpecs(registry) {
49
- const publicSpec = registry.vendianAgentsVersion
50
- ? `${PUBLIC_PACKAGE}==${registry.vendianAgentsVersion}`
51
- : PUBLIC_PACKAGE;
52
- const runtimeSpec = registry.vendianRuntimeVersion
53
- ? `${RUNTIME_PACKAGE}==${registry.vendianRuntimeVersion}`
54
- : RUNTIME_PACKAGE;
55
- return [publicSpec, runtimeSpec];
56
- }
57
-
58
- export function installVendianPackages({ pythonPath, venvPath, config, env = process.env, platform = process.platform }) {
59
- const registry = registryConfig(config, env, platform);
60
- const indexes = buildIndexUrls(registry);
61
- if (!indexes) {
62
- throw new Error('Package access is missing. Run `vendian login`.');
63
- }
64
-
65
- const specs = packageSpecs(registry);
66
- const installArgs = [
67
- 'install',
68
- '--upgrade',
69
- ...specs,
70
- '--index-url',
71
- indexes.sdkIndexUrl,
72
- '--extra-index-url',
73
- indexes.runtimeIndexUrl,
74
- '--extra-index-url',
75
- 'https://pypi.org/simple'
76
- ];
77
-
78
- let status;
79
- if (hasUv()) {
80
- status = runInherit('uv', ['pip', ...installArgs, '--python', pythonPath]);
81
- } else {
82
- status = runInherit(pythonPath, ['-m', 'pip', ...installArgs]);
83
- }
84
- if (status !== 0) {
85
- throw new Error('Could not install Vendian runtime packages. Check package access and try again.');
86
- }
87
-
88
- writeInstallMarker(venvPath, {
89
- gitlabHost: registry.gitlabHost,
90
- gitlabUsername: registry.username,
91
- sdkProjectId: registry.sdkProjectId,
92
- runtimeProjectId: registry.runtimeProjectId,
93
- vendianAgentsVersion: registry.vendianAgentsVersion || 'latest',
94
- vendianAgentsRuntimeVersion: registry.vendianRuntimeVersion || 'latest'
95
- });
96
- }
97
-
98
- export function writeInstallMarker(venvPath, marker) {
99
- fs.mkdirSync(venvPath, { recursive: true });
100
- fs.writeFileSync(
101
- path.join(venvPath, '.vendian-bootstrap.json'),
102
- `${JSON.stringify({ version: 1, ...marker }, null, 2)}\n`,
103
- 'utf8'
104
- );
105
- }
package/src/main.js DELETED
@@ -1,86 +0,0 @@
1
- import { doctor } from './doctor.js';
2
- import { forwardToPythonVendian } from './forward.js';
3
- import { setup } from './setup.js';
4
- import { runTui } from './tui.js';
5
-
6
- function printHelp() {
7
- console.log(`Vendian CLI
8
-
9
- Usage:
10
- vendian Open the interactive menu
11
- vendian login Sign in and prepare the local runtime
12
- vendian setup Alias for vendian login
13
- vendian doctor Check local bootstrap health
14
- vendian update Update the managed Vendian CLI/runtime
15
- vendian <command> Run a Vendian cloud command
16
-
17
- Examples:
18
- vendian login
19
- vendian login --backend staging
20
- vendian cloud local serve --agents-dir ./agents
21
-
22
- Environment:
23
- VENDIAN_CLI_HOME Override managed CLI home
24
- VENDIAN_API_URL Override Vendian backend API URL
25
- `);
26
- }
27
-
28
- export async function main(argv) {
29
- const [command, ...rest] = argv;
30
- if (!command) {
31
- if (process.stdin.isTTY && process.stdout.isTTY) {
32
- await runTui();
33
- } else {
34
- printHelp();
35
- }
36
- return;
37
- }
38
- if (command === '--help' || command === '-h') {
39
- printHelp();
40
- return;
41
- }
42
- if (command === '--version' || command === 'version') {
43
- console.log('0.0.1');
44
- return;
45
- }
46
- if (isBootstrapCommand(command)) {
47
- await setup(parseSetupOptions(rest));
48
- return;
49
- }
50
- if (command === 'doctor') {
51
- doctor();
52
- return;
53
- }
54
- if (command === 'update') {
55
- await setup({ nonInteractive: true });
56
- return;
57
- }
58
- await forwardToPythonVendian(argv);
59
- }
60
-
61
- export function isBootstrapCommand(command) {
62
- return command === 'login' || command === 'setup';
63
- }
64
-
65
- function parseSetupOptions(args) {
66
- const options = {
67
- nonInteractive: args.includes('--yes') || args.includes('--non-interactive'),
68
- noBrowser: args.includes('--no-browser'),
69
- forceAuth: args.includes('--force') || args.includes('--reauth')
70
- };
71
- for (let index = 0; index < args.length; index += 1) {
72
- const arg = args[index];
73
- if (arg === '--backend' || arg === '-b') {
74
- options.backend = args[index + 1];
75
- index += 1;
76
- } else if (arg.startsWith('--backend=')) {
77
- options.backend = arg.slice('--backend='.length);
78
- } else if (arg === '--api-url') {
79
- options.apiUrl = args[index + 1];
80
- index += 1;
81
- } else if (arg.startsWith('--api-url=')) {
82
- options.apiUrl = arg.slice('--api-url='.length);
83
- }
84
- }
85
- return options;
86
- }
package/src/paths.js DELETED
@@ -1,43 +0,0 @@
1
- import os from 'node:os';
2
- import path from 'node:path';
3
-
4
- function pathApi(platform) {
5
- return platform === 'win32' ? path.win32 : path.posix;
6
- }
7
-
8
- export function vendianHome(env = process.env, platform = process.platform) {
9
- if (env.VENDIAN_CLI_HOME) {
10
- return pathApi(platform).resolve(env.VENDIAN_CLI_HOME);
11
- }
12
- if (platform === 'win32') {
13
- const root = env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
14
- return path.win32.join(root, 'Vendian', 'cli');
15
- }
16
- return path.posix.join(os.homedir(), '.vendian', 'cli');
17
- }
18
-
19
- export function configPath(env = process.env, platform = process.platform) {
20
- if (env.VENDIAN_CLI_CONFIG) {
21
- return pathApi(platform).resolve(env.VENDIAN_CLI_CONFIG);
22
- }
23
- return pathApi(platform).join(vendianHome(env, platform), 'config.json');
24
- }
25
-
26
- export function managedVenvPath(env = process.env, platform = process.platform) {
27
- if (env.VENDIAN_CLI_VENV) {
28
- return pathApi(platform).resolve(env.VENDIAN_CLI_VENV);
29
- }
30
- return pathApi(platform).join(vendianHome(env, platform), '.venv');
31
- }
32
-
33
- export function venvPython(venvPath, platform = process.platform) {
34
- return platform === 'win32'
35
- ? path.win32.join(venvPath, 'Scripts', 'python.exe')
36
- : path.posix.join(venvPath, 'bin', 'python');
37
- }
38
-
39
- export function venvVendian(venvPath, platform = process.platform) {
40
- return platform === 'win32'
41
- ? path.win32.join(venvPath, 'Scripts', 'vendian.exe')
42
- : path.posix.join(venvPath, 'bin', 'vendian');
43
- }