@corvio/cli 0.1.0-beta.2 → 0.1.0-beta.3

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  Official CLI for a user's Corvio Workspace. It supports an existing `CORVIO_API_KEY` and a browser device-link login.
4
4
 
5
5
  ```bash
6
- npm install --global @corvio/cli
6
+ npm install --global @corvio/cli@beta
7
7
  export CORVIO_API_KEY='cvk_...'
8
8
  corvio auth status
9
9
  corvio ask --prompt 'Summarize recurring launch risks' --json
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  writeTextFile,
22
22
  } from "./core.js";
23
23
 
24
- const VERSION = "0.1.0-beta.2";
24
+ const VERSION = "0.1.0-beta.3";
25
25
  const DEFAULT_API_BASE = "https://api.corvio.ai/v1";
26
26
  const DEFAULT_APP_BASE = "https://corvio.ai";
27
27
  const USER_AGENT = `corvio-cli/${VERSION}`;
package/dist/core.js CHANGED
@@ -163,6 +163,51 @@ export class ApiClient {
163
163
  }
164
164
  return payload;
165
165
  }
166
+
167
+ async requestBytes(path, { query, headers = {}, auth = true } = {}) {
168
+ const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`);
169
+ for (const [key, value] of Object.entries(query || {})) {
170
+ if (value !== undefined && value !== null && value !== "") url.searchParams.set(key, String(value));
171
+ }
172
+ const requestHeaders = {
173
+ accept: "application/zip, application/octet-stream",
174
+ "user-agent": this.userAgent,
175
+ ...headers,
176
+ };
177
+ if (auth) {
178
+ if (!this.credential) {
179
+ throw new CliError("Corvio authentication is required.", { code: "auth_required", exitCode: EXIT.AUTH });
180
+ }
181
+ requestHeaders.authorization = `Bearer ${this.credential}`;
182
+ }
183
+ let response;
184
+ try {
185
+ response = await this.fetchImpl(url, { method: "GET", headers: requestHeaders });
186
+ } catch (cause) {
187
+ throw new CliError(`Unable to reach Corvio: ${cause instanceof Error ? cause.message : String(cause)}`, {
188
+ code: "network_error",
189
+ exitCode: EXIT.REMOTE,
190
+ });
191
+ }
192
+ const bytes = new Uint8Array(await response.arrayBuffer());
193
+ if (!response.ok) {
194
+ const text = new TextDecoder().decode(bytes);
195
+ let payload = {};
196
+ try {
197
+ payload = JSON.parse(text);
198
+ } catch {
199
+ payload = { message: text.slice(0, 500) };
200
+ }
201
+ const envelope = payload?.error || payload?.detail || payload || {};
202
+ throw new CliError(String(envelope.message || envelope.code || `Corvio request failed (${response.status}).`), {
203
+ code: String(envelope.code || `http_${response.status}`),
204
+ status: response.status,
205
+ exitCode: exitCodeForStatus(response.status),
206
+ details: envelope.details || null,
207
+ });
208
+ }
209
+ return bytes;
210
+ }
166
211
  }
167
212
 
168
213
  function configRoot(env = process.env) {
@@ -175,6 +220,10 @@ export function workspaceCredentialPath(env = process.env) {
175
220
  return join(configRoot(env), "credentials.json");
176
221
  }
177
222
 
223
+ export function adminCredentialPath(env = process.env) {
224
+ return join(configRoot(env), "admin-credentials.json");
225
+ }
226
+
178
227
  export async function readWorkspaceCredential(env = process.env) {
179
228
  const environmentKey = String(env.CORVIO_API_KEY || "").trim();
180
229
  if (environmentKey) {
@@ -241,16 +290,66 @@ export async function clearWorkspaceCredential(env = process.env) {
241
290
  return path;
242
291
  }
243
292
 
244
- export function readAdminCredential(env = process.env) {
293
+ export async function readAdminCredential(env = process.env) {
245
294
  const key = String(env.CORVIO_ADMIN_API_KEY || "").trim();
246
- if (!key) return null;
247
- if (!key.startsWith("cva_")) {
248
- throw new CliError("CORVIO_ADMIN_API_KEY must be a platform administrator cva_ key.", {
249
- code: "invalid_admin_key",
295
+ if (key) {
296
+ if (!key.startsWith("cva_")) {
297
+ throw new CliError("CORVIO_ADMIN_API_KEY must be a platform administrator cva_ key.", {
298
+ code: "invalid_admin_key",
299
+ exitCode: EXIT.AUTH,
300
+ });
301
+ }
302
+ return { key, source: "environment", metadata: null };
303
+ }
304
+ const path = adminCredentialPath(env);
305
+ let parsed;
306
+ try {
307
+ parsed = JSON.parse(await readFile(path, "utf8"));
308
+ } catch (cause) {
309
+ if (cause?.code === "ENOENT") return null;
310
+ throw new CliError("Stored Corvio administrator credentials are unreadable.", {
311
+ code: "admin_credential_store_invalid",
312
+ exitCode: EXIT.AUTH,
313
+ });
314
+ }
315
+ const storedKey = String(parsed.api_key || "").trim();
316
+ if (!storedKey.startsWith("cva_")) {
317
+ throw new CliError("Stored Corvio administrator credentials are invalid; run `corvio-admin auth login` again.", {
318
+ code: "admin_credential_store_invalid",
250
319
  exitCode: EXIT.AUTH,
251
320
  });
252
321
  }
253
- return { key, source: "environment" };
322
+ return { key: storedKey, source: "device_link", metadata: parsed };
323
+ }
324
+
325
+ export async function storeAdminCredential(payload, env = process.env) {
326
+ const path = adminCredentialPath(env);
327
+ const root = dirname(path);
328
+ await mkdir(root, { recursive: true, mode: 0o700 });
329
+ await chmod(root, 0o700).catch(() => {});
330
+ const document = {
331
+ version: 1,
332
+ api_key: payload.secret,
333
+ key_id: payload.key_id,
334
+ audience: payload.audience,
335
+ api_base: payload.api_base,
336
+ scopes: payload.scopes || [],
337
+ expires_at: payload.expires_at,
338
+ created_at: payload.created_at || new Date().toISOString(),
339
+ source: "device_link",
340
+ };
341
+ const temporary = `${path}.${randomUUID()}.tmp`;
342
+ await writeFile(temporary, `${JSON.stringify(document, null, 2)}\n`, { mode: 0o600, flag: "wx" });
343
+ await chmod(temporary, 0o600);
344
+ await rename(temporary, path);
345
+ await chmod(path, 0o600);
346
+ return { path };
347
+ }
348
+
349
+ export async function clearAdminCredential(env = process.env) {
350
+ const path = adminCredentialPath(env);
351
+ await rm(path, { force: true });
352
+ return path;
254
353
  }
255
354
 
256
355
  export function writeResult(value, { json = false, stdout = process.stdout } = {}) {
@@ -313,6 +412,13 @@ export async function writeTextFile(path, content) {
313
412
  return target;
314
413
  }
315
414
 
415
+ export async function writeBinaryFile(path, content) {
416
+ const target = resolve(String(path));
417
+ await mkdir(dirname(target), { recursive: true });
418
+ await writeFile(target, content);
419
+ return target;
420
+ }
421
+
316
422
  export function requireConfirmation(options, action) {
317
423
  if (!options.yes) {
318
424
  throw new CliError(`${action} requires --yes.`, { code: "confirmation_required" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corvio/cli",
3
- "version": "0.1.0-beta.2",
3
+ "version": "0.1.0-beta.3",
4
4
  "description": "Official Corvio Workspace CLI for questions, knowledge search, documents, and Agent workflows.",
5
5
  "type": "module",
6
6
  "bin": {