@thecorporation/cli 26.3.10 → 26.3.11
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 +15 -2
- package/dist/index.js +124 -25
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -15,12 +15,25 @@ npm install -g @thecorporation/cli
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
corp setup #
|
|
18
|
+
corp setup # authenticate via magic link
|
|
19
19
|
corp status # workspace summary
|
|
20
20
|
corp chat # AI assistant with full tool access
|
|
21
21
|
corp form --type llc --name "Acme" # form a new entity
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Authentication
|
|
25
|
+
|
|
26
|
+
`corp setup` authenticates via magic link:
|
|
27
|
+
|
|
28
|
+
1. Enter your name and email
|
|
29
|
+
2. Check your email for a sign-in link from TheCorporation
|
|
30
|
+
3. Copy the code from the link URL and paste it into the terminal
|
|
31
|
+
4. Credentials are saved to `~/.corp/config.json`
|
|
32
|
+
|
|
33
|
+
Your workspace is shared across the CLI, [MCP server](https://www.npmjs.com/package/@thecorporation/mcp-server), and [chat](https://humans.thecorporation.ai/chat) — all keyed on your email.
|
|
34
|
+
|
|
35
|
+
For self-hosted setups (`CORP_API_URL` pointing to your own server), `corp setup` provisions a workspace directly without requiring a magic link.
|
|
36
|
+
|
|
24
37
|
## Commands
|
|
25
38
|
|
|
26
39
|
### Core
|
|
@@ -204,7 +217,7 @@ Inside `corp chat`, these slash commands are available:
|
|
|
204
217
|
|
|
205
218
|
## Configuration
|
|
206
219
|
|
|
207
|
-
Config is stored at `~/.corp/config.json`.
|
|
220
|
+
Config is stored at `~/.corp/config.json`. `corp setup` populates it via magic link auth. You can also set values manually:
|
|
208
221
|
|
|
209
222
|
```bash
|
|
210
223
|
corp config set api_url https://api.thecorporation.ai
|
package/dist/index.js
CHANGED
|
@@ -479,25 +479,112 @@ __export(setup_exports, {
|
|
|
479
479
|
setupCommand: () => setupCommand
|
|
480
480
|
});
|
|
481
481
|
import { input, confirm } from "@inquirer/prompts";
|
|
482
|
+
async function requestMagicLink(apiUrl, email, tosAccepted) {
|
|
483
|
+
const resp = await fetch(`${apiUrl}/v1/auth/magic-link`, {
|
|
484
|
+
method: "POST",
|
|
485
|
+
headers: { "Content-Type": "application/json" },
|
|
486
|
+
body: JSON.stringify({ email, tos_accepted: tosAccepted })
|
|
487
|
+
});
|
|
488
|
+
if (!resp.ok) {
|
|
489
|
+
const data = await resp.json().catch(() => ({}));
|
|
490
|
+
const detail = data?.error ?? data?.message ?? resp.statusText;
|
|
491
|
+
throw new Error(
|
|
492
|
+
typeof detail === "string" ? detail : JSON.stringify(detail)
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
async function verifyMagicLinkCode(apiUrl, code) {
|
|
497
|
+
const resp = await fetch(`${apiUrl}/v1/auth/magic-link/verify`, {
|
|
498
|
+
method: "POST",
|
|
499
|
+
headers: { "Content-Type": "application/json" },
|
|
500
|
+
body: JSON.stringify({ code, client: "cli" })
|
|
501
|
+
});
|
|
502
|
+
const data = await resp.json().catch(() => ({}));
|
|
503
|
+
if (!resp.ok) {
|
|
504
|
+
const detail = data?.error ?? data?.message ?? resp.statusText;
|
|
505
|
+
throw new Error(
|
|
506
|
+
typeof detail === "string" ? detail : JSON.stringify(detail)
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
if (!data.api_key || !data.workspace_id) {
|
|
510
|
+
throw new Error("Unexpected response \u2014 missing api_key or workspace_id");
|
|
511
|
+
}
|
|
512
|
+
return {
|
|
513
|
+
api_key: data.api_key,
|
|
514
|
+
workspace_id: data.workspace_id
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
function isCloudApi(url) {
|
|
518
|
+
return url.replace(/\/+$/, "").includes("thecorporation.ai");
|
|
519
|
+
}
|
|
520
|
+
async function magicLinkAuth(apiUrl, email) {
|
|
521
|
+
console.log("\nSending magic link to " + email + "...");
|
|
522
|
+
await requestMagicLink(apiUrl, email, true);
|
|
523
|
+
console.log("Check your email for a sign-in link from TheCorporation.");
|
|
524
|
+
console.log(
|
|
525
|
+
"Copy the code from the URL (the ?code=... part) and paste it below.\n"
|
|
526
|
+
);
|
|
527
|
+
const code = await input({ message: "Paste your magic link code" });
|
|
528
|
+
const trimmed = code.trim().replace(/^.*[?&]code=/, "");
|
|
529
|
+
if (!trimmed) {
|
|
530
|
+
throw new Error("No code provided");
|
|
531
|
+
}
|
|
532
|
+
console.log("Verifying...");
|
|
533
|
+
return verifyMagicLinkCode(apiUrl, trimmed);
|
|
534
|
+
}
|
|
482
535
|
async function setupCommand() {
|
|
483
536
|
const cfg = loadConfig();
|
|
484
537
|
console.log("Welcome to corp \u2014 corporate governance from the terminal.\n");
|
|
485
|
-
|
|
538
|
+
const customUrl = process.env.CORP_API_URL;
|
|
539
|
+
if (customUrl) {
|
|
540
|
+
cfg.api_url = customUrl.replace(/\/+$/, "");
|
|
541
|
+
console.log(`Using API: ${cfg.api_url}
|
|
542
|
+
`);
|
|
543
|
+
} else {
|
|
544
|
+
cfg.api_url = CLOUD_API_URL;
|
|
545
|
+
}
|
|
486
546
|
console.log("--- User Info ---");
|
|
487
547
|
const user = cfg.user ?? { name: "", email: "" };
|
|
488
|
-
user.name = await input({
|
|
489
|
-
|
|
548
|
+
user.name = await input({
|
|
549
|
+
message: "Your name",
|
|
550
|
+
default: user.name || void 0
|
|
551
|
+
});
|
|
552
|
+
user.email = await input({
|
|
553
|
+
message: "Your email",
|
|
554
|
+
default: user.email || void 0
|
|
555
|
+
});
|
|
490
556
|
cfg.user = user;
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
557
|
+
const needsAuth = !cfg.api_key || !cfg.workspace_id;
|
|
558
|
+
const cloud = isCloudApi(cfg.api_url);
|
|
559
|
+
if (needsAuth) {
|
|
560
|
+
if (cloud) {
|
|
561
|
+
try {
|
|
562
|
+
const result = await magicLinkAuth(cfg.api_url, user.email);
|
|
563
|
+
cfg.api_key = result.api_key;
|
|
564
|
+
cfg.workspace_id = result.workspace_id;
|
|
565
|
+
printSuccess(`Authenticated. Workspace: ${result.workspace_id}`);
|
|
566
|
+
} catch (err) {
|
|
567
|
+
printError(`Authentication failed: ${err}`);
|
|
568
|
+
console.log(
|
|
569
|
+
"You can manually set credentials with: corp config set api_key <key>"
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
} else {
|
|
573
|
+
console.log("\nProvisioning workspace...");
|
|
574
|
+
try {
|
|
575
|
+
const result = await provisionWorkspace(
|
|
576
|
+
cfg.api_url,
|
|
577
|
+
`${user.name}'s workspace`
|
|
578
|
+
);
|
|
579
|
+
cfg.api_key = result.api_key;
|
|
580
|
+
cfg.workspace_id = result.workspace_id;
|
|
581
|
+
console.log(`Workspace provisioned: ${result.workspace_id}`);
|
|
582
|
+
} catch (err) {
|
|
583
|
+
printError(`Auto-provision failed: ${err}`);
|
|
584
|
+
console.log(
|
|
585
|
+
"You can manually set credentials with: corp config set api_key <key>"
|
|
586
|
+
);
|
|
587
|
+
}
|
|
501
588
|
}
|
|
502
589
|
} else {
|
|
503
590
|
console.log("\nVerifying existing credentials...");
|
|
@@ -514,21 +601,33 @@ async function setupCommand() {
|
|
|
514
601
|
console.log("Credentials OK.");
|
|
515
602
|
} else {
|
|
516
603
|
console.log("API key is no longer valid.");
|
|
517
|
-
const
|
|
518
|
-
message: "Provision a new workspace? (This will replace your current credentials)",
|
|
519
|
-
default:
|
|
604
|
+
const reauth = await confirm({
|
|
605
|
+
message: cloud ? "Re-authenticate via magic link?" : "Provision a new workspace? (This will replace your current credentials)",
|
|
606
|
+
default: true
|
|
520
607
|
});
|
|
521
|
-
if (
|
|
608
|
+
if (reauth) {
|
|
522
609
|
try {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
610
|
+
if (cloud) {
|
|
611
|
+
const result = await magicLinkAuth(cfg.api_url, user.email);
|
|
612
|
+
cfg.api_key = result.api_key;
|
|
613
|
+
cfg.workspace_id = result.workspace_id;
|
|
614
|
+
printSuccess(`Authenticated. Workspace: ${result.workspace_id}`);
|
|
615
|
+
} else {
|
|
616
|
+
const result = await provisionWorkspace(
|
|
617
|
+
cfg.api_url,
|
|
618
|
+
`${user.name}'s workspace`
|
|
619
|
+
);
|
|
620
|
+
cfg.api_key = result.api_key;
|
|
621
|
+
cfg.workspace_id = result.workspace_id;
|
|
622
|
+
console.log(`Workspace provisioned: ${result.workspace_id}`);
|
|
623
|
+
}
|
|
527
624
|
} catch (err) {
|
|
528
|
-
printError(`
|
|
625
|
+
printError(`Authentication failed: ${err}`);
|
|
529
626
|
}
|
|
530
627
|
} else {
|
|
531
|
-
console.log(
|
|
628
|
+
console.log(
|
|
629
|
+
"Keeping existing credentials. You can manually update with: corp config set api_key <key>"
|
|
630
|
+
);
|
|
532
631
|
}
|
|
533
632
|
}
|
|
534
633
|
}
|
|
@@ -536,14 +635,14 @@ async function setupCommand() {
|
|
|
536
635
|
console.log("\nConfig saved to ~/.corp/config.json");
|
|
537
636
|
console.log("Run 'corp status' to verify your connection.");
|
|
538
637
|
}
|
|
539
|
-
var
|
|
638
|
+
var CLOUD_API_URL;
|
|
540
639
|
var init_setup = __esm({
|
|
541
640
|
"src/commands/setup.ts"() {
|
|
542
641
|
"use strict";
|
|
543
642
|
init_config();
|
|
544
643
|
init_api_client();
|
|
545
644
|
init_output();
|
|
546
|
-
|
|
645
|
+
CLOUD_API_URL = "https://api.thecorporation.ai";
|
|
547
646
|
}
|
|
548
647
|
});
|
|
549
648
|
|