@thecorporation/cli 1.0.5 → 26.3.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 +51 -2
- package/dist/index.js +968 -210
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -10,6 +10,17 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/config.ts
|
|
13
|
+
var config_exports = {};
|
|
14
|
+
__export(config_exports, {
|
|
15
|
+
configForDisplay: () => configForDisplay,
|
|
16
|
+
getValue: () => getValue,
|
|
17
|
+
loadConfig: () => loadConfig,
|
|
18
|
+
maskKey: () => maskKey,
|
|
19
|
+
requireConfig: () => requireConfig,
|
|
20
|
+
resolveEntityId: () => resolveEntityId,
|
|
21
|
+
saveConfig: () => saveConfig,
|
|
22
|
+
setValue: () => setValue
|
|
23
|
+
});
|
|
13
24
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
14
25
|
import { join } from "path";
|
|
15
26
|
import { homedir } from "os";
|
|
@@ -122,6 +133,29 @@ var init_api_client = __esm({
|
|
|
122
133
|
});
|
|
123
134
|
|
|
124
135
|
// src/output.ts
|
|
136
|
+
var output_exports = {};
|
|
137
|
+
__export(output_exports, {
|
|
138
|
+
printAgentsTable: () => printAgentsTable,
|
|
139
|
+
printApprovalsTable: () => printApprovalsTable,
|
|
140
|
+
printBillingPanel: () => printBillingPanel,
|
|
141
|
+
printCapTable: () => printCapTable,
|
|
142
|
+
printContactsTable: () => printContactsTable,
|
|
143
|
+
printDocumentsTable: () => printDocumentsTable,
|
|
144
|
+
printEntitiesTable: () => printEntitiesTable,
|
|
145
|
+
printError: () => printError,
|
|
146
|
+
printGovernanceTable: () => printGovernanceTable,
|
|
147
|
+
printJson: () => printJson,
|
|
148
|
+
printMeetingsTable: () => printMeetingsTable,
|
|
149
|
+
printObligationsTable: () => printObligationsTable,
|
|
150
|
+
printResolutionsTable: () => printResolutionsTable,
|
|
151
|
+
printSafesTable: () => printSafesTable,
|
|
152
|
+
printSeatsTable: () => printSeatsTable,
|
|
153
|
+
printStatusPanel: () => printStatusPanel,
|
|
154
|
+
printSuccess: () => printSuccess,
|
|
155
|
+
printTransfersTable: () => printTransfersTable,
|
|
156
|
+
printValuationsTable: () => printValuationsTable,
|
|
157
|
+
printWarning: () => printWarning
|
|
158
|
+
});
|
|
125
159
|
import chalk from "chalk";
|
|
126
160
|
import Table from "cli-table3";
|
|
127
161
|
function printError(msg) {
|
|
@@ -130,6 +164,9 @@ function printError(msg) {
|
|
|
130
164
|
function printSuccess(msg) {
|
|
131
165
|
console.log(chalk.green(msg));
|
|
132
166
|
}
|
|
167
|
+
function printWarning(msg) {
|
|
168
|
+
console.log(chalk.yellow(msg));
|
|
169
|
+
}
|
|
133
170
|
function printJson(data) {
|
|
134
171
|
console.log(JSON.stringify(data, null, 2));
|
|
135
172
|
}
|
|
@@ -364,35 +401,30 @@ function printApprovalsTable(approvals) {
|
|
|
364
401
|
console.log(table.toString());
|
|
365
402
|
}
|
|
366
403
|
function printBillingPanel(status, plans) {
|
|
367
|
-
const
|
|
368
|
-
const
|
|
369
|
-
const
|
|
404
|
+
const plan = s(status.plan ?? status.tier) || "free";
|
|
405
|
+
const subStatus = s(status.status) || "active";
|
|
406
|
+
const periodEnd = s(status.current_period_end);
|
|
370
407
|
console.log(chalk.green("\u2500".repeat(50)));
|
|
371
408
|
console.log(chalk.green.bold(" Billing Status"));
|
|
372
409
|
console.log(chalk.green("\u2500".repeat(50)));
|
|
373
|
-
console.log(` ${chalk.bold("
|
|
374
|
-
console.log(` ${chalk.bold("
|
|
375
|
-
|
|
376
|
-
console.log(` - ${sub.tier ?? "N/A"} (${sub.status ?? "N/A"})`);
|
|
377
|
-
}
|
|
378
|
-
console.log(` ${chalk.bold("Tool Calls:")} ${usageCount}`);
|
|
410
|
+
console.log(` ${chalk.bold("Plan:")} ${plan}`);
|
|
411
|
+
console.log(` ${chalk.bold("Status:")} ${subStatus}`);
|
|
412
|
+
if (periodEnd) console.log(` ${chalk.bold("Current Period End:")} ${periodEnd}`);
|
|
379
413
|
console.log(chalk.dim(" Manage: corp billing portal"));
|
|
380
|
-
console.log(chalk.dim(" Upgrade: corp billing upgrade"));
|
|
414
|
+
console.log(chalk.dim(" Upgrade: corp billing upgrade --plan <plan>"));
|
|
381
415
|
console.log(chalk.green("\u2500".repeat(50)));
|
|
382
416
|
if (plans.length > 0) {
|
|
383
|
-
const table = makeTable("Available Plans", ["
|
|
417
|
+
const table = makeTable("Available Plans", ["Plan", "Price", "Features"]);
|
|
384
418
|
for (const p of plans) {
|
|
385
|
-
const amount = p.amount ?? 0;
|
|
419
|
+
const amount = p.price_cents ?? p.amount ?? 0;
|
|
386
420
|
const interval = s(p.interval);
|
|
387
421
|
let priceStr = "Free";
|
|
388
422
|
if (amount > 0) {
|
|
389
|
-
priceStr = interval ? `$${Math.round(amount / 100)}/${interval
|
|
423
|
+
priceStr = interval ? `$${Math.round(amount / 100)}/${interval}` : `$${Math.round(amount / 100)}`;
|
|
390
424
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (desc.length > 60) desc = desc.slice(0, 57) + "...";
|
|
395
|
-
table.push([name, priceStr, s(p.type), desc]);
|
|
425
|
+
const name = s(p.name ?? p.plan_id ?? p.tier);
|
|
426
|
+
const features = Array.isArray(p.features) ? p.features.join(", ") : s(p.description);
|
|
427
|
+
table.push([name, priceStr, features]);
|
|
396
428
|
}
|
|
397
429
|
console.log(table.toString());
|
|
398
430
|
}
|
|
@@ -682,8 +714,8 @@ var init_status = __esm({
|
|
|
682
714
|
});
|
|
683
715
|
|
|
684
716
|
// src/commands/config.ts
|
|
685
|
-
var
|
|
686
|
-
__export(
|
|
717
|
+
var config_exports2 = {};
|
|
718
|
+
__export(config_exports2, {
|
|
687
719
|
configGetCommand: () => configGetCommand,
|
|
688
720
|
configListCommand: () => configListCommand,
|
|
689
721
|
configSetCommand: () => configSetCommand
|
|
@@ -1035,7 +1067,7 @@ async function chatCommand() {
|
|
|
1035
1067
|
const messages = [{ role: "system", content: SYSTEM_PROMPT }];
|
|
1036
1068
|
let totalTokens = 0;
|
|
1037
1069
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1038
|
-
const prompt = () => new Promise((
|
|
1070
|
+
const prompt = () => new Promise((resolve2) => rl.question(chalk2.green.bold("> "), resolve2));
|
|
1039
1071
|
console.log(chalk2.blue.bold("corp chat") + " \u2014 type /help for commands, /quit to exit\n");
|
|
1040
1072
|
const slashHandlers = {
|
|
1041
1073
|
"/status": async () => {
|
|
@@ -1154,7 +1186,7 @@ ${chalk2.bold("Chat Slash Commands")}
|
|
|
1154
1186
|
break;
|
|
1155
1187
|
}
|
|
1156
1188
|
for (const tc of response.tool_calls) {
|
|
1157
|
-
console.log(chalk2.dim(` ${isWriteTool(tc.name) ? "\u2699" : "\u2139"} ${tc.name}(${JSON.stringify(tc.arguments).slice(0, 80)})`));
|
|
1189
|
+
console.log(chalk2.dim(` ${isWriteTool(tc.name, tc.arguments) ? "\u2699" : "\u2139"} ${tc.name}(${JSON.stringify(tc.arguments).slice(0, 80)})`));
|
|
1158
1190
|
const result = await executeTool(tc.name, tc.arguments, client);
|
|
1159
1191
|
const short = result.length > 200 ? result.slice(0, 197) + "..." : result;
|
|
1160
1192
|
console.log(chalk2.dim(` => ${short}`));
|
|
@@ -1245,7 +1277,7 @@ async function entitiesConvertCommand(entityId, opts) {
|
|
|
1245
1277
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1246
1278
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1247
1279
|
try {
|
|
1248
|
-
const data = {
|
|
1280
|
+
const data = { target_type: opts.to };
|
|
1249
1281
|
if (opts.jurisdiction) data.new_jurisdiction = opts.jurisdiction;
|
|
1250
1282
|
const result = await client.convertEntity(entityId, data);
|
|
1251
1283
|
printSuccess(`Entity conversion initiated: ${result.conversion_id ?? "OK"}`);
|
|
@@ -1290,9 +1322,10 @@ __export(contacts_exports, {
|
|
|
1290
1322
|
import chalk4 from "chalk";
|
|
1291
1323
|
async function contactsListCommand(opts) {
|
|
1292
1324
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1325
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1293
1326
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1294
1327
|
try {
|
|
1295
|
-
const contacts = await client.listContacts();
|
|
1328
|
+
const contacts = await client.listContacts(eid);
|
|
1296
1329
|
if (opts.json) printJson(contacts);
|
|
1297
1330
|
else if (contacts.length === 0) console.log("No contacts found.");
|
|
1298
1331
|
else printContactsTable(contacts);
|
|
@@ -1336,10 +1369,16 @@ async function contactsShowCommand(contactId, opts) {
|
|
|
1336
1369
|
}
|
|
1337
1370
|
async function contactsAddCommand(opts) {
|
|
1338
1371
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1372
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1339
1373
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1340
1374
|
try {
|
|
1341
|
-
const data = {
|
|
1342
|
-
|
|
1375
|
+
const data = {
|
|
1376
|
+
entity_id: eid,
|
|
1377
|
+
contact_type: opts.type ?? "individual",
|
|
1378
|
+
name: opts.name,
|
|
1379
|
+
email: opts.email,
|
|
1380
|
+
category: opts.category ?? "employee"
|
|
1381
|
+
};
|
|
1343
1382
|
if (opts.phone) data.phone = opts.phone;
|
|
1344
1383
|
if (opts.notes) data.notes = opts.notes;
|
|
1345
1384
|
const result = await client.createContact(data);
|
|
@@ -1382,12 +1421,18 @@ var init_contacts = __esm({
|
|
|
1382
1421
|
// src/commands/cap-table.ts
|
|
1383
1422
|
var cap_table_exports = {};
|
|
1384
1423
|
__export(cap_table_exports, {
|
|
1424
|
+
addSecurityCommand: () => addSecurityCommand,
|
|
1425
|
+
approveValuationCommand: () => approveValuationCommand,
|
|
1385
1426
|
capTableCommand: () => capTableCommand,
|
|
1427
|
+
createValuationCommand: () => createValuationCommand,
|
|
1386
1428
|
distributeCommand: () => distributeCommand,
|
|
1387
1429
|
fourOhNineACommand: () => fourOhNineACommand,
|
|
1388
1430
|
issueEquityCommand: () => issueEquityCommand,
|
|
1431
|
+
issueRoundCommand: () => issueRoundCommand,
|
|
1389
1432
|
issueSafeCommand: () => issueSafeCommand,
|
|
1390
1433
|
safesCommand: () => safesCommand,
|
|
1434
|
+
startRoundCommand: () => startRoundCommand,
|
|
1435
|
+
submitValuationCommand: () => submitValuationCommand,
|
|
1391
1436
|
transferSharesCommand: () => transferSharesCommand,
|
|
1392
1437
|
transfersCommand: () => transfersCommand,
|
|
1393
1438
|
valuationsCommand: () => valuationsCommand
|
|
@@ -1479,13 +1524,48 @@ async function issueEquityCommand(opts) {
|
|
|
1479
1524
|
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1480
1525
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1481
1526
|
try {
|
|
1482
|
-
const
|
|
1527
|
+
const capTable = await client.getCapTable(eid);
|
|
1528
|
+
const issuerLegalEntityId = capTable.issuer_legal_entity_id;
|
|
1529
|
+
if (!issuerLegalEntityId) {
|
|
1530
|
+
printError("No issuer legal entity found. Has this entity been formed with a cap table?");
|
|
1531
|
+
process.exit(1);
|
|
1532
|
+
}
|
|
1533
|
+
let instrumentId = opts.instrumentId;
|
|
1534
|
+
if (!instrumentId) {
|
|
1535
|
+
const instruments = capTable.instruments;
|
|
1536
|
+
if (!instruments?.length) {
|
|
1537
|
+
printError("No instruments found on cap table. Create an instrument first.");
|
|
1538
|
+
process.exit(1);
|
|
1539
|
+
}
|
|
1540
|
+
const grantLower = opts.grantType.toLowerCase();
|
|
1541
|
+
const match = instruments.find(
|
|
1542
|
+
(i) => i.kind.toLowerCase().includes(grantLower) || i.symbol.toLowerCase().includes(grantLower)
|
|
1543
|
+
) ?? instruments.find((i) => i.kind.toLowerCase().includes("common"));
|
|
1544
|
+
if (match) {
|
|
1545
|
+
instrumentId = match.instrument_id;
|
|
1546
|
+
console.log(`Using instrument: ${match.symbol} (${match.kind})`);
|
|
1547
|
+
} else {
|
|
1548
|
+
instrumentId = instruments[0].instrument_id;
|
|
1549
|
+
console.log(`Using first instrument: ${instruments[0].symbol} (${instruments[0].kind})`);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
const round = await client.startEquityRound({
|
|
1483
1553
|
entity_id: eid,
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
recipient_name: opts.recipient
|
|
1554
|
+
name: `${opts.grantType} grant \u2014 ${opts.recipient}`,
|
|
1555
|
+
issuer_legal_entity_id: issuerLegalEntityId
|
|
1487
1556
|
});
|
|
1488
|
-
|
|
1557
|
+
const roundId = round.round_id ?? round.equity_round_id;
|
|
1558
|
+
const securityData = {
|
|
1559
|
+
entity_id: eid,
|
|
1560
|
+
instrument_id: instrumentId,
|
|
1561
|
+
quantity: opts.shares,
|
|
1562
|
+
recipient_name: opts.recipient,
|
|
1563
|
+
grant_type: opts.grantType
|
|
1564
|
+
};
|
|
1565
|
+
if (opts.email) securityData.email = opts.email;
|
|
1566
|
+
await client.addRoundSecurity(roundId, securityData);
|
|
1567
|
+
const result = await client.issueRound(roundId, { entity_id: eid });
|
|
1568
|
+
printSuccess(`Equity issued: ${opts.shares} shares (${opts.grantType}) to ${opts.recipient}`);
|
|
1489
1569
|
printJson(result);
|
|
1490
1570
|
} catch (err) {
|
|
1491
1571
|
printError(`Failed to issue equity: ${err}`);
|
|
@@ -1497,14 +1577,36 @@ async function issueSafeCommand(opts) {
|
|
|
1497
1577
|
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1498
1578
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1499
1579
|
try {
|
|
1500
|
-
const
|
|
1580
|
+
const capTable = await client.getCapTable(eid);
|
|
1581
|
+
const issuerLegalEntityId = capTable.issuer_legal_entity_id;
|
|
1582
|
+
if (!issuerLegalEntityId) {
|
|
1583
|
+
printError("No issuer legal entity found. Has this entity been formed with a cap table?");
|
|
1584
|
+
process.exit(1);
|
|
1585
|
+
}
|
|
1586
|
+
const instruments = capTable.instruments;
|
|
1587
|
+
const safeInstrument = instruments?.find((i) => i.kind.toLowerCase() === "safe");
|
|
1588
|
+
if (!safeInstrument) {
|
|
1589
|
+
printError("No SAFE instrument found on cap table. Create a SAFE instrument first.");
|
|
1590
|
+
process.exit(1);
|
|
1591
|
+
}
|
|
1592
|
+
const round = await client.startEquityRound({
|
|
1501
1593
|
entity_id: eid,
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
safe_type: opts.safeType,
|
|
1505
|
-
valuation_cap_cents: opts.valuationCap
|
|
1594
|
+
name: `SAFE \u2014 ${opts.investor}`,
|
|
1595
|
+
issuer_legal_entity_id: issuerLegalEntityId
|
|
1506
1596
|
});
|
|
1507
|
-
|
|
1597
|
+
const roundId = round.round_id ?? round.equity_round_id;
|
|
1598
|
+
const securityData = {
|
|
1599
|
+
entity_id: eid,
|
|
1600
|
+
instrument_id: safeInstrument.instrument_id,
|
|
1601
|
+
quantity: opts.amount,
|
|
1602
|
+
recipient_name: opts.investor,
|
|
1603
|
+
principal_cents: opts.amount,
|
|
1604
|
+
grant_type: opts.safeType
|
|
1605
|
+
};
|
|
1606
|
+
if (opts.email) securityData.email = opts.email;
|
|
1607
|
+
await client.addRoundSecurity(roundId, securityData);
|
|
1608
|
+
const result = await client.issueRound(roundId, { entity_id: eid });
|
|
1609
|
+
printSuccess(`SAFE issued: $${(opts.amount / 100).toLocaleString()} to ${opts.investor}`);
|
|
1508
1610
|
printJson(result);
|
|
1509
1611
|
} catch (err) {
|
|
1510
1612
|
printError(`Failed to issue SAFE: ${err}`);
|
|
@@ -1518,15 +1620,15 @@ async function transferSharesCommand(opts) {
|
|
|
1518
1620
|
try {
|
|
1519
1621
|
const result = await client.transferShares({
|
|
1520
1622
|
entity_id: eid,
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1623
|
+
from_holder_id: opts.fromGrant,
|
|
1624
|
+
to_holder_id: opts.to,
|
|
1625
|
+
quantity: opts.shares,
|
|
1524
1626
|
transfer_type: opts.type
|
|
1525
1627
|
});
|
|
1526
|
-
printSuccess(`Transfer
|
|
1628
|
+
printSuccess(`Transfer workflow created: ${result.workflow_id ?? "OK"}`);
|
|
1527
1629
|
printJson(result);
|
|
1528
1630
|
} catch (err) {
|
|
1529
|
-
printError(`Failed to transfer
|
|
1631
|
+
printError(`Failed to create transfer workflow: ${err}`);
|
|
1530
1632
|
process.exit(1);
|
|
1531
1633
|
}
|
|
1532
1634
|
}
|
|
@@ -1538,7 +1640,8 @@ async function distributeCommand(opts) {
|
|
|
1538
1640
|
const result = await client.calculateDistribution({
|
|
1539
1641
|
entity_id: eid,
|
|
1540
1642
|
total_amount_cents: opts.amount,
|
|
1541
|
-
distribution_type: opts.type
|
|
1643
|
+
distribution_type: opts.type,
|
|
1644
|
+
description: opts.description
|
|
1542
1645
|
});
|
|
1543
1646
|
printSuccess(`Distribution calculated: ${result.distribution_id ?? "OK"}`);
|
|
1544
1647
|
printJson(result);
|
|
@@ -1547,6 +1650,108 @@ async function distributeCommand(opts) {
|
|
|
1547
1650
|
process.exit(1);
|
|
1548
1651
|
}
|
|
1549
1652
|
}
|
|
1653
|
+
async function startRoundCommand(opts) {
|
|
1654
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1655
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1656
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1657
|
+
try {
|
|
1658
|
+
const result = await client.startEquityRound({
|
|
1659
|
+
entity_id: eid,
|
|
1660
|
+
name: opts.name,
|
|
1661
|
+
issuer_legal_entity_id: opts.issuerLegalEntityId
|
|
1662
|
+
});
|
|
1663
|
+
printSuccess(`Round started: ${result.round_id ?? "OK"}`);
|
|
1664
|
+
printJson(result);
|
|
1665
|
+
} catch (err) {
|
|
1666
|
+
printError(`Failed to start round: ${err}`);
|
|
1667
|
+
process.exit(1);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
async function addSecurityCommand(opts) {
|
|
1671
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1672
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1673
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1674
|
+
try {
|
|
1675
|
+
const body = {
|
|
1676
|
+
entity_id: eid,
|
|
1677
|
+
instrument_id: opts.instrumentId,
|
|
1678
|
+
quantity: opts.quantity,
|
|
1679
|
+
recipient_name: opts.recipientName
|
|
1680
|
+
};
|
|
1681
|
+
if (opts.holderId) body.holder_id = opts.holderId;
|
|
1682
|
+
if (opts.email) body.email = opts.email;
|
|
1683
|
+
if (opts.principalCents) body.principal_cents = opts.principalCents;
|
|
1684
|
+
if (opts.grantType) body.grant_type = opts.grantType;
|
|
1685
|
+
const result = await client.addRoundSecurity(opts.roundId, body);
|
|
1686
|
+
printSuccess(`Security added for ${opts.recipientName}`);
|
|
1687
|
+
printJson(result);
|
|
1688
|
+
} catch (err) {
|
|
1689
|
+
printError(`Failed to add security: ${err}`);
|
|
1690
|
+
process.exit(1);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
async function issueRoundCommand(opts) {
|
|
1694
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1695
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1696
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1697
|
+
try {
|
|
1698
|
+
const result = await client.issueRound(opts.roundId, { entity_id: eid });
|
|
1699
|
+
printSuccess("Round issued and closed");
|
|
1700
|
+
printJson(result);
|
|
1701
|
+
} catch (err) {
|
|
1702
|
+
printError(`Failed to issue round: ${err}`);
|
|
1703
|
+
process.exit(1);
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
async function createValuationCommand(opts) {
|
|
1707
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1708
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1709
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1710
|
+
try {
|
|
1711
|
+
const body = {
|
|
1712
|
+
entity_id: eid,
|
|
1713
|
+
valuation_type: opts.type,
|
|
1714
|
+
effective_date: opts.date,
|
|
1715
|
+
methodology: opts.methodology
|
|
1716
|
+
};
|
|
1717
|
+
if (opts.fmv != null) body.fmv_per_share_cents = opts.fmv;
|
|
1718
|
+
if (opts.enterpriseValue != null) body.enterprise_value_cents = opts.enterpriseValue;
|
|
1719
|
+
const result = await client.createValuation(body);
|
|
1720
|
+
printSuccess(`Valuation created: ${result.valuation_id ?? "OK"}`);
|
|
1721
|
+
printJson(result);
|
|
1722
|
+
} catch (err) {
|
|
1723
|
+
printError(`Failed to create valuation: ${err}`);
|
|
1724
|
+
process.exit(1);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
async function submitValuationCommand(opts) {
|
|
1728
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1729
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1730
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1731
|
+
try {
|
|
1732
|
+
const result = await client.submitValuationForApproval(opts.valuationId, eid);
|
|
1733
|
+
printSuccess(`Valuation submitted for approval: ${result.valuation_id ?? "OK"}`);
|
|
1734
|
+
if (result.meeting_id) console.log(` Meeting: ${result.meeting_id}`);
|
|
1735
|
+
if (result.agenda_item_id) console.log(` Agenda Item: ${result.agenda_item_id}`);
|
|
1736
|
+
printJson(result);
|
|
1737
|
+
} catch (err) {
|
|
1738
|
+
printError(`Failed to submit valuation: ${err}`);
|
|
1739
|
+
process.exit(1);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
async function approveValuationCommand(opts) {
|
|
1743
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1744
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1745
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1746
|
+
try {
|
|
1747
|
+
const result = await client.approveValuation(opts.valuationId, eid, opts.resolutionId);
|
|
1748
|
+
printSuccess(`Valuation approved: ${result.valuation_id ?? "OK"}`);
|
|
1749
|
+
printJson(result);
|
|
1750
|
+
} catch (err) {
|
|
1751
|
+
printError(`Failed to approve valuation: ${err}`);
|
|
1752
|
+
process.exit(1);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1550
1755
|
function print409a(data) {
|
|
1551
1756
|
console.log(chalk5.green("\u2500".repeat(40)));
|
|
1552
1757
|
console.log(chalk5.green.bold(" 409A Valuation"));
|
|
@@ -1635,7 +1840,7 @@ async function financeOpenAccountCommand(opts) {
|
|
|
1635
1840
|
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1636
1841
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1637
1842
|
try {
|
|
1638
|
-
const result = await client.openBankAccount({ entity_id: eid,
|
|
1843
|
+
const result = await client.openBankAccount({ entity_id: eid, bank_name: opts.institution });
|
|
1639
1844
|
printSuccess(`Bank account opened: ${result.account_id ?? "OK"}`);
|
|
1640
1845
|
printJson(result);
|
|
1641
1846
|
} catch (err) {
|
|
@@ -1693,13 +1898,55 @@ var init_finance = __esm({
|
|
|
1693
1898
|
// src/commands/governance.ts
|
|
1694
1899
|
var governance_exports = {};
|
|
1695
1900
|
__export(governance_exports, {
|
|
1901
|
+
adjournMeetingCommand: () => adjournMeetingCommand,
|
|
1902
|
+
cancelMeetingCommand: () => cancelMeetingCommand,
|
|
1903
|
+
computeResolutionCommand: () => computeResolutionCommand,
|
|
1904
|
+
finalizeAgendaItemCommand: () => finalizeAgendaItemCommand,
|
|
1905
|
+
governanceAddSeatCommand: () => governanceAddSeatCommand,
|
|
1696
1906
|
governanceConveneCommand: () => governanceConveneCommand,
|
|
1907
|
+
governanceCreateBodyCommand: () => governanceCreateBodyCommand,
|
|
1697
1908
|
governanceListCommand: () => governanceListCommand,
|
|
1698
1909
|
governanceMeetingsCommand: () => governanceMeetingsCommand,
|
|
1699
1910
|
governanceResolutionsCommand: () => governanceResolutionsCommand,
|
|
1700
1911
|
governanceSeatsCommand: () => governanceSeatsCommand,
|
|
1701
|
-
governanceVoteCommand: () => governanceVoteCommand
|
|
1912
|
+
governanceVoteCommand: () => governanceVoteCommand,
|
|
1913
|
+
listAgendaItemsCommand: () => listAgendaItemsCommand,
|
|
1914
|
+
sendNoticeCommand: () => sendNoticeCommand,
|
|
1915
|
+
writtenConsentCommand: () => writtenConsentCommand
|
|
1702
1916
|
});
|
|
1917
|
+
async function governanceCreateBodyCommand(opts) {
|
|
1918
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1919
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
1920
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1921
|
+
try {
|
|
1922
|
+
const result = await client.createGovernanceBody({
|
|
1923
|
+
entity_id: eid,
|
|
1924
|
+
body_type: opts.bodyType,
|
|
1925
|
+
name: opts.name,
|
|
1926
|
+
quorum_rule: opts.quorum,
|
|
1927
|
+
voting_method: opts.voting
|
|
1928
|
+
});
|
|
1929
|
+
printSuccess(`Governance body created: ${result.body_id ?? "OK"}`);
|
|
1930
|
+
printJson(result);
|
|
1931
|
+
} catch (err) {
|
|
1932
|
+
printError(`Failed to create governance body: ${err}`);
|
|
1933
|
+
process.exit(1);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
async function governanceAddSeatCommand(bodyId, opts) {
|
|
1937
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1938
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1939
|
+
try {
|
|
1940
|
+
const data = { holder_id: opts.holder };
|
|
1941
|
+
if (opts.title) data.title = opts.title;
|
|
1942
|
+
const result = await client.createGovernanceSeat(bodyId, data);
|
|
1943
|
+
printSuccess(`Seat added: ${result.seat_id ?? "OK"}`);
|
|
1944
|
+
printJson(result);
|
|
1945
|
+
} catch (err) {
|
|
1946
|
+
printError(`Failed to add seat: ${err}`);
|
|
1947
|
+
process.exit(1);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1703
1950
|
async function governanceListCommand(opts) {
|
|
1704
1951
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1705
1952
|
const eid = resolveEntityId(cfg, opts.entityId);
|
|
@@ -1789,6 +2036,108 @@ async function governanceVoteCommand(meetingId, itemId, opts) {
|
|
|
1789
2036
|
process.exit(1);
|
|
1790
2037
|
}
|
|
1791
2038
|
}
|
|
2039
|
+
async function sendNoticeCommand(meetingId, opts) {
|
|
2040
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2041
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2042
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2043
|
+
try {
|
|
2044
|
+
const result = await client.sendNotice(meetingId, eid);
|
|
2045
|
+
printSuccess(`Notice sent for meeting ${meetingId}`);
|
|
2046
|
+
printJson(result);
|
|
2047
|
+
} catch (err) {
|
|
2048
|
+
printError(`Failed to send notice: ${err}`);
|
|
2049
|
+
process.exit(1);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
async function adjournMeetingCommand(meetingId, opts) {
|
|
2053
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2054
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2055
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2056
|
+
try {
|
|
2057
|
+
const result = await client.adjournMeeting(meetingId, eid);
|
|
2058
|
+
printSuccess(`Meeting ${meetingId} adjourned`);
|
|
2059
|
+
printJson(result);
|
|
2060
|
+
} catch (err) {
|
|
2061
|
+
printError(`Failed to adjourn meeting: ${err}`);
|
|
2062
|
+
process.exit(1);
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
async function cancelMeetingCommand(meetingId, opts) {
|
|
2066
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2067
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2068
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2069
|
+
try {
|
|
2070
|
+
const result = await client.cancelMeeting(meetingId, eid);
|
|
2071
|
+
printSuccess(`Meeting ${meetingId} cancelled`);
|
|
2072
|
+
printJson(result);
|
|
2073
|
+
} catch (err) {
|
|
2074
|
+
printError(`Failed to cancel meeting: ${err}`);
|
|
2075
|
+
process.exit(1);
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
async function finalizeAgendaItemCommand(meetingId, itemId, opts) {
|
|
2079
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2080
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2081
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2082
|
+
try {
|
|
2083
|
+
const result = await client.finalizeAgendaItem(meetingId, itemId, {
|
|
2084
|
+
entity_id: eid,
|
|
2085
|
+
status: opts.status
|
|
2086
|
+
});
|
|
2087
|
+
printSuccess(`Agenda item ${itemId} finalized as ${opts.status}`);
|
|
2088
|
+
printJson(result);
|
|
2089
|
+
} catch (err) {
|
|
2090
|
+
printError(`Failed to finalize agenda item: ${err}`);
|
|
2091
|
+
process.exit(1);
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
async function computeResolutionCommand(meetingId, itemId, opts) {
|
|
2095
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2096
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2097
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2098
|
+
try {
|
|
2099
|
+
const result = await client.computeResolution(meetingId, itemId, eid, {
|
|
2100
|
+
resolution_text: opts.text
|
|
2101
|
+
});
|
|
2102
|
+
printSuccess(`Resolution computed for agenda item ${itemId}`);
|
|
2103
|
+
printJson(result);
|
|
2104
|
+
} catch (err) {
|
|
2105
|
+
printError(`Failed to compute resolution: ${err}`);
|
|
2106
|
+
process.exit(1);
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
async function writtenConsentCommand(opts) {
|
|
2110
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2111
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2112
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2113
|
+
try {
|
|
2114
|
+
const result = await client.writtenConsent({
|
|
2115
|
+
entity_id: eid,
|
|
2116
|
+
body_id: opts.body,
|
|
2117
|
+
title: opts.title,
|
|
2118
|
+
description: opts.description
|
|
2119
|
+
});
|
|
2120
|
+
printSuccess(`Written consent created: ${result.meeting_id ?? "OK"}`);
|
|
2121
|
+
printJson(result);
|
|
2122
|
+
} catch (err) {
|
|
2123
|
+
printError(`Failed to create written consent: ${err}`);
|
|
2124
|
+
process.exit(1);
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
async function listAgendaItemsCommand(meetingId, opts) {
|
|
2128
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2129
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2130
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2131
|
+
try {
|
|
2132
|
+
const items = await client.listAgendaItems(meetingId, eid);
|
|
2133
|
+
if (opts.json) printJson(items);
|
|
2134
|
+
else if (items.length === 0) console.log("No agenda items found.");
|
|
2135
|
+
else printJson(items);
|
|
2136
|
+
} catch (err) {
|
|
2137
|
+
printError(`Failed to list agenda items: ${err}`);
|
|
2138
|
+
process.exit(1);
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
1792
2141
|
var init_governance = __esm({
|
|
1793
2142
|
"src/commands/governance.ts"() {
|
|
1794
2143
|
"use strict";
|
|
@@ -1803,6 +2152,7 @@ var documents_exports = {};
|
|
|
1803
2152
|
__export(documents_exports, {
|
|
1804
2153
|
documentsGenerateCommand: () => documentsGenerateCommand,
|
|
1805
2154
|
documentsListCommand: () => documentsListCommand,
|
|
2155
|
+
documentsPreviewPdfCommand: () => documentsPreviewPdfCommand,
|
|
1806
2156
|
documentsSigningLinkCommand: () => documentsSigningLinkCommand
|
|
1807
2157
|
});
|
|
1808
2158
|
async function documentsListCommand(opts) {
|
|
@@ -1839,7 +2189,8 @@ async function documentsGenerateCommand(opts) {
|
|
|
1839
2189
|
const result = await client.generateContract({
|
|
1840
2190
|
entity_id: eid,
|
|
1841
2191
|
template_type: opts.template,
|
|
1842
|
-
|
|
2192
|
+
counterparty_name: opts.counterparty,
|
|
2193
|
+
effective_date: opts.effectiveDate ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
|
|
1843
2194
|
});
|
|
1844
2195
|
printSuccess(`Contract generated: ${result.contract_id ?? "OK"}`);
|
|
1845
2196
|
printJson(result);
|
|
@@ -1848,6 +2199,15 @@ async function documentsGenerateCommand(opts) {
|
|
|
1848
2199
|
process.exit(1);
|
|
1849
2200
|
}
|
|
1850
2201
|
}
|
|
2202
|
+
async function documentsPreviewPdfCommand(opts) {
|
|
2203
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2204
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2205
|
+
const apiUrl = cfg.api_url.replace(/\/+$/, "");
|
|
2206
|
+
const qs = new URLSearchParams({ entity_id: eid, document_id: opts.documentId }).toString();
|
|
2207
|
+
const url = `${apiUrl}/v1/documents/preview/pdf?${qs}`;
|
|
2208
|
+
printSuccess(`Preview PDF URL: ${url}`);
|
|
2209
|
+
console.log("Use your API key to authenticate the download.");
|
|
2210
|
+
}
|
|
1851
2211
|
var init_documents = __esm({
|
|
1852
2212
|
"src/commands/documents.ts"() {
|
|
1853
2213
|
"use strict";
|
|
@@ -1918,7 +2278,6 @@ __export(agents_exports, {
|
|
|
1918
2278
|
agentsSkillCommand: () => agentsSkillCommand
|
|
1919
2279
|
});
|
|
1920
2280
|
import chalk6 from "chalk";
|
|
1921
|
-
import Table2 from "cli-table3";
|
|
1922
2281
|
async function agentsListCommand(opts) {
|
|
1923
2282
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1924
2283
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
@@ -1937,13 +2296,8 @@ async function agentsShowCommand(agentId, opts) {
|
|
|
1937
2296
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
1938
2297
|
try {
|
|
1939
2298
|
const agent = await client.getAgent(agentId);
|
|
1940
|
-
let usage = {};
|
|
1941
|
-
try {
|
|
1942
|
-
usage = await client.getAgentUsage(agentId);
|
|
1943
|
-
} catch {
|
|
1944
|
-
}
|
|
1945
2299
|
if (opts.json) {
|
|
1946
|
-
printJson(
|
|
2300
|
+
printJson(agent);
|
|
1947
2301
|
return;
|
|
1948
2302
|
}
|
|
1949
2303
|
console.log(chalk6.magenta("\u2500".repeat(40)));
|
|
@@ -1958,12 +2312,8 @@ async function agentsShowCommand(agentId, opts) {
|
|
|
1958
2312
|
if (prompt.length > 100) prompt = prompt.slice(0, 97) + "...";
|
|
1959
2313
|
console.log(` ${chalk6.bold("Prompt:")} ${prompt}`);
|
|
1960
2314
|
}
|
|
1961
|
-
if (
|
|
1962
|
-
console.log(`
|
|
1963
|
-
${chalk6.bold("Usage:")}`);
|
|
1964
|
-
for (const [k, v] of Object.entries(usage)) {
|
|
1965
|
-
if (k !== "agent_id") console.log(` ${k}: ${v}`);
|
|
1966
|
-
}
|
|
2315
|
+
if (agent.skills && Array.isArray(agent.skills) && agent.skills.length > 0) {
|
|
2316
|
+
console.log(` ${chalk6.bold("Skills:")} ${agent.skills.map((s2) => s2.name ?? "?").join(", ")}`);
|
|
1967
2317
|
}
|
|
1968
2318
|
console.log(chalk6.magenta("\u2500".repeat(40)));
|
|
1969
2319
|
} catch (err) {
|
|
@@ -2028,44 +2378,22 @@ async function agentsMessageCommand(agentId, opts) {
|
|
|
2028
2378
|
process.exit(1);
|
|
2029
2379
|
}
|
|
2030
2380
|
}
|
|
2031
|
-
async function agentsExecutionsCommand(agentId,
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
return;
|
|
2039
|
-
}
|
|
2040
|
-
if (executions.length === 0) {
|
|
2041
|
-
console.log("No executions found.");
|
|
2042
|
-
return;
|
|
2043
|
-
}
|
|
2044
|
-
console.log(`
|
|
2045
|
-
${chalk6.bold("Agent Executions")}`);
|
|
2046
|
-
const table = new Table2({ head: [chalk6.dim("ID"), chalk6.dim("Status"), chalk6.dim("Started"), chalk6.dim("Duration")] });
|
|
2047
|
-
for (const ex of executions) {
|
|
2048
|
-
table.push([
|
|
2049
|
-
String(ex.execution_id ?? "").slice(0, 12),
|
|
2050
|
-
String(ex.status ?? ""),
|
|
2051
|
-
String(ex.started_at ?? ""),
|
|
2052
|
-
String(ex.duration ?? "")
|
|
2053
|
-
]);
|
|
2054
|
-
}
|
|
2055
|
-
console.log(table.toString());
|
|
2056
|
-
} catch (err) {
|
|
2057
|
-
printError(`Failed to fetch executions: ${err}`);
|
|
2058
|
-
process.exit(1);
|
|
2059
|
-
}
|
|
2381
|
+
async function agentsExecutionsCommand(agentId, _opts) {
|
|
2382
|
+
printError(
|
|
2383
|
+
`Listing executions is not yet supported.
|
|
2384
|
+
To inspect a specific run, use the execution ID returned by "agents message":
|
|
2385
|
+
GET /v1/agents/${agentId}/executions/<execution-id>`
|
|
2386
|
+
);
|
|
2387
|
+
process.exit(1);
|
|
2060
2388
|
}
|
|
2061
2389
|
async function agentsSkillCommand(agentId, opts) {
|
|
2062
2390
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2063
2391
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2064
2392
|
try {
|
|
2065
2393
|
const result = await client.addAgentSkill(agentId, {
|
|
2066
|
-
|
|
2394
|
+
name: opts.name,
|
|
2067
2395
|
description: opts.description,
|
|
2068
|
-
instructions: opts.instructions
|
|
2396
|
+
parameters: opts.instructions ? { instructions: opts.instructions } : {}
|
|
2069
2397
|
});
|
|
2070
2398
|
printSuccess(`Skill '${opts.name}' added to agent ${agentId}.`);
|
|
2071
2399
|
printJson(result);
|
|
@@ -2134,13 +2462,13 @@ ${url}`);
|
|
|
2134
2462
|
async function billingUpgradeCommand(opts) {
|
|
2135
2463
|
const client = makeClient();
|
|
2136
2464
|
try {
|
|
2137
|
-
const result = await client.createBillingCheckout(opts.
|
|
2465
|
+
const result = await client.createBillingCheckout(opts.plan);
|
|
2138
2466
|
const url = result.checkout_url;
|
|
2139
2467
|
if (!url) {
|
|
2140
2468
|
printError("No checkout URL returned.");
|
|
2141
2469
|
process.exit(1);
|
|
2142
2470
|
}
|
|
2143
|
-
console.log(`Opening Stripe Checkout for ${opts.
|
|
2471
|
+
console.log(`Opening Stripe Checkout for ${opts.plan}...
|
|
2144
2472
|
${url}`);
|
|
2145
2473
|
openUrl(url);
|
|
2146
2474
|
printSuccess("Checkout opened in your browser.");
|
|
@@ -2158,120 +2486,376 @@ var init_billing = __esm({
|
|
|
2158
2486
|
}
|
|
2159
2487
|
});
|
|
2160
2488
|
|
|
2161
|
-
// src/commands/
|
|
2162
|
-
var
|
|
2163
|
-
__export(
|
|
2164
|
-
|
|
2165
|
-
|
|
2489
|
+
// src/commands/form.ts
|
|
2490
|
+
var form_exports = {};
|
|
2491
|
+
__export(form_exports, {
|
|
2492
|
+
formAddFounderCommand: () => formAddFounderCommand,
|
|
2493
|
+
formCommand: () => formCommand,
|
|
2494
|
+
formCreateCommand: () => formCreateCommand,
|
|
2495
|
+
formFinalizeCommand: () => formFinalizeCommand
|
|
2166
2496
|
});
|
|
2167
|
-
|
|
2497
|
+
import { input as input2, select, confirm as confirm2, number } from "@inquirer/prompts";
|
|
2498
|
+
import chalk7 from "chalk";
|
|
2499
|
+
import Table2 from "cli-table3";
|
|
2500
|
+
function isCorp(entityType) {
|
|
2501
|
+
return entityType === "c_corp" || entityType === "s_corp" || entityType === "corporation";
|
|
2502
|
+
}
|
|
2503
|
+
function sectionHeader(title) {
|
|
2504
|
+
console.log();
|
|
2505
|
+
console.log(chalk7.blue("\u2500".repeat(50)));
|
|
2506
|
+
console.log(chalk7.blue.bold(` ${title}`));
|
|
2507
|
+
console.log(chalk7.blue("\u2500".repeat(50)));
|
|
2508
|
+
}
|
|
2509
|
+
async function promptAddress() {
|
|
2510
|
+
const street = await input2({ message: " Street address" });
|
|
2511
|
+
const city = await input2({ message: " City" });
|
|
2512
|
+
const state = await input2({ message: " State (2-letter)", default: "DE" });
|
|
2513
|
+
const zip = await input2({ message: " ZIP code" });
|
|
2514
|
+
return { street, city, state, zip };
|
|
2515
|
+
}
|
|
2516
|
+
async function phaseEntityDetails(opts, serverCfg, scripted) {
|
|
2517
|
+
if (!scripted) sectionHeader("Phase 1: Entity Details");
|
|
2518
|
+
let entityType = opts.type;
|
|
2519
|
+
if (!entityType) {
|
|
2520
|
+
if (scripted) {
|
|
2521
|
+
entityType = "llc";
|
|
2522
|
+
} else {
|
|
2523
|
+
entityType = await select({
|
|
2524
|
+
message: "Entity type",
|
|
2525
|
+
choices: [
|
|
2526
|
+
{ value: "llc", name: "LLC" },
|
|
2527
|
+
{ value: "c_corp", name: "C-Corp" }
|
|
2528
|
+
]
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
let name = opts.name;
|
|
2533
|
+
if (!name) {
|
|
2534
|
+
if (scripted) {
|
|
2535
|
+
printError("--name is required in scripted mode");
|
|
2536
|
+
process.exit(1);
|
|
2537
|
+
}
|
|
2538
|
+
name = await input2({ message: "Legal name" });
|
|
2539
|
+
}
|
|
2540
|
+
let jurisdiction = opts.jurisdiction;
|
|
2541
|
+
if (!jurisdiction) {
|
|
2542
|
+
const defaultJ = entityType === "llc" ? "US-WY" : "US-DE";
|
|
2543
|
+
if (scripted) {
|
|
2544
|
+
jurisdiction = defaultJ;
|
|
2545
|
+
} else {
|
|
2546
|
+
jurisdiction = await input2({ message: "Jurisdiction", default: defaultJ });
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
let companyAddress;
|
|
2550
|
+
if (opts.address) {
|
|
2551
|
+
const parts = opts.address.split(",").map((p) => p.trim());
|
|
2552
|
+
if (parts.length === 4) {
|
|
2553
|
+
companyAddress = { street: parts[0], city: parts[1], state: parts[2], zip: parts[3] };
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
if (!companyAddress && !scripted) {
|
|
2557
|
+
const wantAddress = await confirm2({ message: "Add company address?", default: false });
|
|
2558
|
+
if (wantAddress) {
|
|
2559
|
+
companyAddress = await promptAddress();
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
const fiscalYearEnd = opts.fiscalYearEnd ?? "12-31";
|
|
2563
|
+
let sCorpElection = opts.sCorp ?? false;
|
|
2564
|
+
if (!scripted && isCorp(entityType) && opts.sCorp === void 0) {
|
|
2565
|
+
sCorpElection = await confirm2({ message: "S-Corp election?", default: false });
|
|
2566
|
+
}
|
|
2567
|
+
return { entityType, name, jurisdiction, companyAddress, fiscalYearEnd, sCorpElection };
|
|
2568
|
+
}
|
|
2569
|
+
async function phasePeople(opts, entityType, scripted) {
|
|
2570
|
+
if (!scripted) sectionHeader("Phase 2: Founders & Officers");
|
|
2571
|
+
const founders = [];
|
|
2572
|
+
if (scripted) {
|
|
2573
|
+
for (const m of opts.member) {
|
|
2574
|
+
const parts = m.split(",").map((p) => p.trim());
|
|
2575
|
+
if (parts.length < 3) {
|
|
2576
|
+
printError(`Invalid member format: ${m}. Expected: name,email,role[,pct]`);
|
|
2577
|
+
process.exit(1);
|
|
2578
|
+
}
|
|
2579
|
+
const f = { name: parts[0], email: parts[1], role: parts[2] };
|
|
2580
|
+
if (parts.length >= 4) f.ownership_pct = parseFloat(parts[3]);
|
|
2581
|
+
founders.push(f);
|
|
2582
|
+
}
|
|
2583
|
+
return founders;
|
|
2584
|
+
}
|
|
2585
|
+
const founderCount = await number({ message: "Number of founders (1-6)", default: 1 }) ?? 1;
|
|
2586
|
+
for (let i = 0; i < founderCount; i++) {
|
|
2587
|
+
console.log(chalk7.dim(`
|
|
2588
|
+
Founder ${i + 1} of ${founderCount}:`));
|
|
2589
|
+
const name = await input2({ message: ` Name` });
|
|
2590
|
+
const email = await input2({ message: ` Email` });
|
|
2591
|
+
let role = "member";
|
|
2592
|
+
if (isCorp(entityType)) {
|
|
2593
|
+
role = await select({
|
|
2594
|
+
message: " Role",
|
|
2595
|
+
choices: [
|
|
2596
|
+
{ value: "director", name: "Director" },
|
|
2597
|
+
{ value: "officer", name: "Officer" },
|
|
2598
|
+
{ value: "member", name: "Shareholder only" }
|
|
2599
|
+
]
|
|
2600
|
+
});
|
|
2601
|
+
}
|
|
2602
|
+
const wantAddress = await confirm2({ message: " Add address?", default: false });
|
|
2603
|
+
const address = wantAddress ? await promptAddress() : void 0;
|
|
2604
|
+
let officerTitle;
|
|
2605
|
+
if (isCorp(entityType)) {
|
|
2606
|
+
const wantOfficer = role === "officer" || await confirm2({ message: " Assign officer title?", default: i === 0 });
|
|
2607
|
+
if (wantOfficer) {
|
|
2608
|
+
officerTitle = await select({
|
|
2609
|
+
message: " Officer title",
|
|
2610
|
+
choices: [
|
|
2611
|
+
{ value: "ceo", name: "CEO" },
|
|
2612
|
+
{ value: "cfo", name: "CFO" },
|
|
2613
|
+
{ value: "secretary", name: "Secretary" },
|
|
2614
|
+
{ value: "president", name: "President" },
|
|
2615
|
+
{ value: "vp", name: "VP" }
|
|
2616
|
+
]
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
let isIncorporator = false;
|
|
2621
|
+
if (isCorp(entityType) && i === 0 && founderCount === 1) {
|
|
2622
|
+
isIncorporator = true;
|
|
2623
|
+
} else if (isCorp(entityType)) {
|
|
2624
|
+
isIncorporator = await confirm2({ message: " Designate as sole incorporator?", default: i === 0 });
|
|
2625
|
+
}
|
|
2626
|
+
founders.push({ name, email, role, address, officer_title: officerTitle, is_incorporator: isIncorporator });
|
|
2627
|
+
}
|
|
2628
|
+
return founders;
|
|
2629
|
+
}
|
|
2630
|
+
async function phaseStock(opts, entityType, founders, scripted) {
|
|
2631
|
+
if (!scripted) sectionHeader("Phase 3: Equity & Finalize");
|
|
2632
|
+
const transferRestrictions = opts.transferRestrictions ?? (!scripted && isCorp(entityType) ? await confirm2({ message: "Transfer restrictions on shares?", default: true }) : isCorp(entityType));
|
|
2633
|
+
const rofr = opts.rofr ?? (!scripted && isCorp(entityType) ? await confirm2({ message: "Right of first refusal?", default: true }) : isCorp(entityType));
|
|
2634
|
+
if (!scripted) {
|
|
2635
|
+
for (const f of founders) {
|
|
2636
|
+
console.log(chalk7.dim(`
|
|
2637
|
+
Equity for ${f.name}:`));
|
|
2638
|
+
if (isCorp(entityType)) {
|
|
2639
|
+
const shares = await number({ message: ` Shares to purchase`, default: 0 });
|
|
2640
|
+
f.shares_purchased = shares ?? 0;
|
|
2641
|
+
if (f.shares_purchased === 0) {
|
|
2642
|
+
const pct = await number({ message: ` Ownership % (1-100)`, default: founders.length === 1 ? 100 : 0 });
|
|
2643
|
+
f.ownership_pct = pct ?? 0;
|
|
2644
|
+
}
|
|
2645
|
+
} else {
|
|
2646
|
+
const pct = await number({
|
|
2647
|
+
message: ` Ownership % (1-100)`,
|
|
2648
|
+
default: founders.length === 1 ? 100 : 0
|
|
2649
|
+
});
|
|
2650
|
+
f.ownership_pct = pct ?? 0;
|
|
2651
|
+
}
|
|
2652
|
+
if (isCorp(entityType)) {
|
|
2653
|
+
const wantVesting = await confirm2({ message: " Add vesting schedule?", default: false });
|
|
2654
|
+
if (wantVesting) {
|
|
2655
|
+
const totalMonths = await number({ message: " Total vesting months", default: 48 }) ?? 48;
|
|
2656
|
+
const cliffMonths = await number({ message: " Cliff months", default: 12 }) ?? 12;
|
|
2657
|
+
const acceleration = await select({
|
|
2658
|
+
message: " Acceleration",
|
|
2659
|
+
choices: [
|
|
2660
|
+
{ value: "none", name: "None" },
|
|
2661
|
+
{ value: "single_trigger", name: "Single trigger" },
|
|
2662
|
+
{ value: "double_trigger", name: "Double trigger" }
|
|
2663
|
+
]
|
|
2664
|
+
});
|
|
2665
|
+
f.vesting = {
|
|
2666
|
+
total_months: totalMonths,
|
|
2667
|
+
cliff_months: cliffMonths,
|
|
2668
|
+
acceleration: acceleration === "none" ? void 0 : acceleration
|
|
2669
|
+
};
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
const wantIp = await confirm2({ message: " Contributing IP?", default: false });
|
|
2673
|
+
if (wantIp) {
|
|
2674
|
+
f.ip_description = await input2({ message: " Describe IP being contributed" });
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
return { founders, transferRestrictions, rofr };
|
|
2679
|
+
}
|
|
2680
|
+
function printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr) {
|
|
2681
|
+
sectionHeader("Formation Summary");
|
|
2682
|
+
console.log(` ${chalk7.bold("Entity:")} ${name}`);
|
|
2683
|
+
console.log(` ${chalk7.bold("Type:")} ${entityType}`);
|
|
2684
|
+
console.log(` ${chalk7.bold("Jurisdiction:")} ${jurisdiction}`);
|
|
2685
|
+
console.log(` ${chalk7.bold("Fiscal Year End:")} ${fiscalYearEnd}`);
|
|
2686
|
+
if (isCorp(entityType)) {
|
|
2687
|
+
console.log(` ${chalk7.bold("S-Corp Election:")} ${sCorpElection ? "Yes" : "No"}`);
|
|
2688
|
+
console.log(` ${chalk7.bold("Transfer Restrictions:")} ${transferRestrictions ? "Yes" : "No"}`);
|
|
2689
|
+
console.log(` ${chalk7.bold("Right of First Refusal:")} ${rofr ? "Yes" : "No"}`);
|
|
2690
|
+
}
|
|
2691
|
+
const table = new Table2({
|
|
2692
|
+
head: [chalk7.dim("Name"), chalk7.dim("Email"), chalk7.dim("Role"), chalk7.dim("Equity"), chalk7.dim("Officer")]
|
|
2693
|
+
});
|
|
2694
|
+
for (const f of founders) {
|
|
2695
|
+
const equity = f.shares_purchased ? `${f.shares_purchased.toLocaleString()} shares` : f.ownership_pct ? `${f.ownership_pct}%` : "\u2014";
|
|
2696
|
+
table.push([f.name, f.email, f.role, equity, f.officer_title ?? "\u2014"]);
|
|
2697
|
+
}
|
|
2698
|
+
console.log(table.toString());
|
|
2699
|
+
}
|
|
2700
|
+
async function formCommand(opts) {
|
|
2168
2701
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2169
2702
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2170
2703
|
try {
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2704
|
+
let serverCfg = {};
|
|
2705
|
+
try {
|
|
2706
|
+
serverCfg = await client.getConfig();
|
|
2707
|
+
} catch {
|
|
2708
|
+
}
|
|
2709
|
+
const scripted = !!(opts.member && opts.member.length > 0);
|
|
2710
|
+
const { entityType, name, jurisdiction, companyAddress, fiscalYearEnd, sCorpElection } = await phaseEntityDetails(opts, serverCfg, scripted);
|
|
2711
|
+
const founders = await phasePeople(opts, entityType, scripted);
|
|
2712
|
+
const { transferRestrictions, rofr } = await phaseStock(opts, entityType, founders, scripted);
|
|
2713
|
+
printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr);
|
|
2714
|
+
const shouldProceed = scripted ? true : await confirm2({ message: "Proceed with formation?", default: true });
|
|
2715
|
+
if (!shouldProceed) {
|
|
2716
|
+
console.log(chalk7.yellow("Formation cancelled."));
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2719
|
+
const members = founders.map((f) => {
|
|
2720
|
+
const m = {
|
|
2721
|
+
name: f.name,
|
|
2722
|
+
email: f.email,
|
|
2723
|
+
role: f.role,
|
|
2724
|
+
investor_type: "natural_person"
|
|
2725
|
+
};
|
|
2726
|
+
if (f.ownership_pct) m.ownership_pct = f.ownership_pct;
|
|
2727
|
+
if (f.shares_purchased) m.shares_purchased = f.shares_purchased;
|
|
2728
|
+
if (f.address) m.address = f.address;
|
|
2729
|
+
if (f.officer_title) m.officer_title = f.officer_title;
|
|
2730
|
+
if (f.is_incorporator) m.is_incorporator = true;
|
|
2731
|
+
if (f.vesting) m.vesting = f.vesting;
|
|
2732
|
+
if (f.ip_description) m.ip_description = f.ip_description;
|
|
2733
|
+
return m;
|
|
2734
|
+
});
|
|
2735
|
+
const payload = {
|
|
2736
|
+
entity_type: entityType,
|
|
2737
|
+
legal_name: name,
|
|
2738
|
+
jurisdiction,
|
|
2739
|
+
members,
|
|
2740
|
+
workspace_id: cfg.workspace_id,
|
|
2741
|
+
fiscal_year_end: fiscalYearEnd,
|
|
2742
|
+
s_corp_election: sCorpElection,
|
|
2743
|
+
transfer_restrictions: transferRestrictions,
|
|
2744
|
+
right_of_first_refusal: rofr
|
|
2745
|
+
};
|
|
2746
|
+
if (companyAddress) payload.company_address = companyAddress;
|
|
2747
|
+
const result = await client.createFormationWithCapTable(payload);
|
|
2748
|
+
printSuccess(`Formation created: ${result.formation_id ?? result.id ?? "OK"}`);
|
|
2749
|
+
if (result.entity_id) console.log(` Entity ID: ${result.entity_id}`);
|
|
2750
|
+
if (result.legal_entity_id) console.log(` Legal Entity ID: ${result.legal_entity_id}`);
|
|
2751
|
+
if (result.instrument_id) console.log(` Instrument ID: ${result.instrument_id}`);
|
|
2752
|
+
const docIds = result.document_ids ?? [];
|
|
2753
|
+
if (docIds.length > 0) {
|
|
2754
|
+
console.log(` Documents: ${docIds.length} generated`);
|
|
2755
|
+
}
|
|
2756
|
+
const holders = result.holders ?? [];
|
|
2757
|
+
if (holders.length > 0) {
|
|
2758
|
+
console.log();
|
|
2759
|
+
const table = new Table2({
|
|
2760
|
+
head: [chalk7.dim("Holder"), chalk7.dim("Shares"), chalk7.dim("Ownership %")]
|
|
2761
|
+
});
|
|
2762
|
+
for (const h of holders) {
|
|
2763
|
+
const pct = typeof h.ownership_pct === "number" ? `${h.ownership_pct.toFixed(1)}%` : "\u2014";
|
|
2764
|
+
table.push([String(h.name ?? "?"), String(h.shares ?? 0), pct]);
|
|
2765
|
+
}
|
|
2766
|
+
console.log(chalk7.bold(" Cap Table:"));
|
|
2767
|
+
console.log(table.toString());
|
|
2768
|
+
}
|
|
2769
|
+
if (result.next_action) {
|
|
2770
|
+
console.log(chalk7.yellow(`
|
|
2771
|
+
Next: ${result.next_action}`));
|
|
2772
|
+
}
|
|
2175
2773
|
} catch (err) {
|
|
2176
|
-
|
|
2774
|
+
if (err instanceof Error && err.message.includes("exit")) throw err;
|
|
2775
|
+
printError(`Failed to create formation: ${err}`);
|
|
2177
2776
|
process.exit(1);
|
|
2178
2777
|
}
|
|
2179
2778
|
}
|
|
2180
|
-
async function
|
|
2779
|
+
async function formCreateCommand(opts) {
|
|
2181
2780
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2182
2781
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2183
2782
|
try {
|
|
2184
|
-
|
|
2185
|
-
|
|
2783
|
+
const entityType = opts.type === "corporation" ? "c_corp" : opts.type;
|
|
2784
|
+
const payload = {
|
|
2785
|
+
entity_type: entityType,
|
|
2786
|
+
legal_name: opts.name
|
|
2787
|
+
};
|
|
2788
|
+
if (opts.jurisdiction) payload.jurisdiction = opts.jurisdiction;
|
|
2789
|
+
const result = await client.createPendingEntity(payload);
|
|
2790
|
+
printSuccess(`Pending entity created: ${result.entity_id}`);
|
|
2791
|
+
console.log(` Name: ${result.legal_name}`);
|
|
2792
|
+
console.log(` Type: ${result.entity_type}`);
|
|
2793
|
+
console.log(` Jurisdiction: ${result.jurisdiction}`);
|
|
2794
|
+
console.log(` Status: ${result.formation_status}`);
|
|
2795
|
+
console.log(chalk7.yellow(`
|
|
2796
|
+
Next: corp form add-founder ${result.entity_id} --name "..." --email "..." --role member --pct 50`));
|
|
2186
2797
|
} catch (err) {
|
|
2187
|
-
printError(`Failed to
|
|
2798
|
+
printError(`Failed to create pending entity: ${err}`);
|
|
2188
2799
|
process.exit(1);
|
|
2189
2800
|
}
|
|
2190
2801
|
}
|
|
2191
|
-
|
|
2192
|
-
"src/commands/approvals.ts"() {
|
|
2193
|
-
"use strict";
|
|
2194
|
-
init_config();
|
|
2195
|
-
init_api_client();
|
|
2196
|
-
init_output();
|
|
2197
|
-
}
|
|
2198
|
-
});
|
|
2199
|
-
|
|
2200
|
-
// src/commands/form.ts
|
|
2201
|
-
var form_exports = {};
|
|
2202
|
-
__export(form_exports, {
|
|
2203
|
-
formCommand: () => formCommand
|
|
2204
|
-
});
|
|
2205
|
-
import { input as input2, select } from "@inquirer/prompts";
|
|
2206
|
-
async function formCommand(opts) {
|
|
2802
|
+
async function formAddFounderCommand(entityId, opts) {
|
|
2207
2803
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2208
2804
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2209
2805
|
try {
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
if (
|
|
2217
|
-
|
|
2218
|
-
|
|
2806
|
+
const payload = {
|
|
2807
|
+
name: opts.name,
|
|
2808
|
+
email: opts.email,
|
|
2809
|
+
role: opts.role,
|
|
2810
|
+
ownership_pct: parseFloat(opts.pct)
|
|
2811
|
+
};
|
|
2812
|
+
if (opts.officerTitle) payload.officer_title = opts.officerTitle;
|
|
2813
|
+
if (opts.incorporator) payload.is_incorporator = true;
|
|
2814
|
+
const result = await client.addFounder(entityId, payload);
|
|
2815
|
+
printSuccess(`Founder added (${result.member_count} total)`);
|
|
2816
|
+
const members = result.members ?? [];
|
|
2817
|
+
for (const m of members) {
|
|
2818
|
+
const pct = typeof m.ownership_pct === "number" ? ` (${m.ownership_pct}%)` : "";
|
|
2819
|
+
console.log(` - ${m.name} <${m.email ?? "no email"}> [${m.role ?? "member"}]${pct}`);
|
|
2219
2820
|
}
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2821
|
+
console.log(chalk7.yellow(`
|
|
2822
|
+
Next: add more founders or run: corp form finalize ${entityId}`));
|
|
2823
|
+
} catch (err) {
|
|
2824
|
+
printError(`Failed to add founder: ${err}`);
|
|
2825
|
+
process.exit(1);
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
async function formFinalizeCommand(entityId) {
|
|
2829
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2830
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2831
|
+
try {
|
|
2832
|
+
const result = await client.finalizeFormation(entityId);
|
|
2833
|
+
printSuccess(`Formation finalized: ${result.entity_id}`);
|
|
2834
|
+
if (result.legal_entity_id) console.log(` Legal Entity ID: ${result.legal_entity_id}`);
|
|
2835
|
+
if (result.instrument_id) console.log(` Instrument ID: ${result.instrument_id}`);
|
|
2836
|
+
const docIds = result.document_ids ?? [];
|
|
2837
|
+
if (docIds.length > 0) {
|
|
2838
|
+
console.log(` Documents: ${docIds.length} generated`);
|
|
2223
2839
|
}
|
|
2224
|
-
|
|
2225
|
-
if (
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
choices: jurisdictions.map((j) => ({ value: j, name: j })),
|
|
2230
|
-
default: "DE"
|
|
2840
|
+
const holders = result.holders ?? [];
|
|
2841
|
+
if (holders.length > 0) {
|
|
2842
|
+
console.log();
|
|
2843
|
+
const table = new Table2({
|
|
2844
|
+
head: [chalk7.dim("Holder"), chalk7.dim("Shares"), chalk7.dim("Ownership %")]
|
|
2231
2845
|
});
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
for (const m of opts.member) {
|
|
2236
|
-
const parts = m.split(",").map((p) => p.trim());
|
|
2237
|
-
if (parts.length < 3) {
|
|
2238
|
-
printError(`Invalid member format: ${m}. Expected: name,email,role[,ownership_pct]`);
|
|
2239
|
-
process.exit(1);
|
|
2240
|
-
}
|
|
2241
|
-
const member = { name: parts[0], email: parts[1], role: parts[2] };
|
|
2242
|
-
if (parts.length >= 4) member.ownership_pct = parseFloat(parts[3]);
|
|
2243
|
-
parsedMembers.push(member);
|
|
2244
|
-
}
|
|
2245
|
-
} else {
|
|
2246
|
-
console.log("Add members (leave name blank to finish):");
|
|
2247
|
-
while (true) {
|
|
2248
|
-
const mname = await input2({ message: " Member name (blank to finish)", default: "" });
|
|
2249
|
-
if (!mname) break;
|
|
2250
|
-
const memail = await input2({ message: " Email" });
|
|
2251
|
-
const mrole = await input2({ message: " Role", default: "founder" });
|
|
2252
|
-
const mpctStr = await input2({ message: " Ownership %", default: "0" });
|
|
2253
|
-
parsedMembers.push({
|
|
2254
|
-
name: mname,
|
|
2255
|
-
email: memail,
|
|
2256
|
-
role: mrole,
|
|
2257
|
-
ownership_pct: parseFloat(mpctStr)
|
|
2258
|
-
});
|
|
2846
|
+
for (const h of holders) {
|
|
2847
|
+
const pct = typeof h.ownership_pct === "number" ? `${h.ownership_pct.toFixed(1)}%` : "\u2014";
|
|
2848
|
+
table.push([String(h.name ?? "?"), String(h.shares ?? 0), pct]);
|
|
2259
2849
|
}
|
|
2850
|
+
console.log(chalk7.bold(" Cap Table:"));
|
|
2851
|
+
console.log(table.toString());
|
|
2260
2852
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2853
|
+
if (result.next_action) {
|
|
2854
|
+
console.log(chalk7.yellow(`
|
|
2855
|
+
Next: ${result.next_action}`));
|
|
2263
2856
|
}
|
|
2264
|
-
const result = await client.createFormation({
|
|
2265
|
-
entity_type: entityType,
|
|
2266
|
-
legal_name: name,
|
|
2267
|
-
jurisdiction,
|
|
2268
|
-
members: parsedMembers
|
|
2269
|
-
});
|
|
2270
|
-
printSuccess(`Formation created: ${result.formation_id ?? result.id ?? "OK"}`);
|
|
2271
|
-
if (result.entity_id) console.log(`Entity ID: ${result.entity_id}`);
|
|
2272
2857
|
} catch (err) {
|
|
2273
|
-
|
|
2274
|
-
printError(`Failed to create formation: ${err}`);
|
|
2858
|
+
printError(`Failed to finalize formation: ${err}`);
|
|
2275
2859
|
process.exit(1);
|
|
2276
2860
|
}
|
|
2277
2861
|
}
|
|
@@ -2289,7 +2873,7 @@ var api_keys_exports = {};
|
|
|
2289
2873
|
__export(api_keys_exports, {
|
|
2290
2874
|
apiKeysCommand: () => apiKeysCommand
|
|
2291
2875
|
});
|
|
2292
|
-
import
|
|
2876
|
+
import chalk8 from "chalk";
|
|
2293
2877
|
import Table3 from "cli-table3";
|
|
2294
2878
|
async function apiKeysCommand(opts) {
|
|
2295
2879
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
@@ -2305,9 +2889,9 @@ async function apiKeysCommand(opts) {
|
|
|
2305
2889
|
return;
|
|
2306
2890
|
}
|
|
2307
2891
|
console.log(`
|
|
2308
|
-
${
|
|
2892
|
+
${chalk8.bold("API Keys")}`);
|
|
2309
2893
|
const table = new Table3({
|
|
2310
|
-
head: [
|
|
2894
|
+
head: [chalk8.dim("ID"), chalk8.dim("Name"), chalk8.dim("Key"), chalk8.dim("Created"), chalk8.dim("Last Used")]
|
|
2311
2895
|
});
|
|
2312
2896
|
for (const k of keys) {
|
|
2313
2897
|
table.push([
|
|
@@ -2365,6 +2949,38 @@ var serve_exports = {};
|
|
|
2365
2949
|
__export(serve_exports, {
|
|
2366
2950
|
serveCommand: () => serveCommand
|
|
2367
2951
|
});
|
|
2952
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
|
|
2953
|
+
import { resolve } from "path";
|
|
2954
|
+
import { randomBytes } from "crypto";
|
|
2955
|
+
function generateFernetKey() {
|
|
2956
|
+
return randomBytes(32).toString("base64url") + "=";
|
|
2957
|
+
}
|
|
2958
|
+
function generateSecret(length = 32) {
|
|
2959
|
+
return randomBytes(length).toString("hex");
|
|
2960
|
+
}
|
|
2961
|
+
function loadEnvFile(path) {
|
|
2962
|
+
if (!existsSync2(path)) return;
|
|
2963
|
+
const content = readFileSync2(path, "utf-8");
|
|
2964
|
+
for (const line of content.split("\n")) {
|
|
2965
|
+
const trimmed = line.trim();
|
|
2966
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
2967
|
+
const eqIdx = trimmed.indexOf("=");
|
|
2968
|
+
if (eqIdx === -1) continue;
|
|
2969
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
2970
|
+
const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
|
|
2971
|
+
if (!process.env[key]) {
|
|
2972
|
+
process.env[key] = value;
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
function ensureEnvFile(envPath) {
|
|
2977
|
+
if (existsSync2(envPath)) return;
|
|
2978
|
+
console.log("No .env file found. Generating one with dev defaults...\n");
|
|
2979
|
+
const content = ENV_TEMPLATE.replace("{{JWT_SECRET}}", generateSecret()).replace("{{SECRETS_MASTER_KEY}}", generateFernetKey()).replace("{{INTERNAL_WORKER_TOKEN}}", generateSecret());
|
|
2980
|
+
writeFileSync2(envPath, content, "utf-8");
|
|
2981
|
+
console.log(` Created ${envPath}
|
|
2982
|
+
`);
|
|
2983
|
+
}
|
|
2368
2984
|
async function serveCommand(opts) {
|
|
2369
2985
|
let server;
|
|
2370
2986
|
try {
|
|
@@ -2382,10 +2998,25 @@ async function serveCommand(opts) {
|
|
|
2382
2998
|
process.exit(1);
|
|
2383
2999
|
}
|
|
2384
3000
|
const port = parseInt(opts.port, 10);
|
|
2385
|
-
if (isNaN(port) || port
|
|
3001
|
+
if (isNaN(port) || port > 65535) {
|
|
2386
3002
|
console.error(`Error: Invalid port "${opts.port}"`);
|
|
2387
3003
|
process.exit(1);
|
|
2388
3004
|
}
|
|
3005
|
+
const envPath = resolve(process.cwd(), ".env");
|
|
3006
|
+
ensureEnvFile(envPath);
|
|
3007
|
+
loadEnvFile(envPath);
|
|
3008
|
+
const localUrl = `http://localhost:${port}`;
|
|
3009
|
+
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
3010
|
+
const cfg = loadConfig2();
|
|
3011
|
+
const previousUrl = cfg.api_url;
|
|
3012
|
+
if (cfg.api_url !== localUrl) {
|
|
3013
|
+
cfg.api_url = localUrl;
|
|
3014
|
+
saveConfig2(cfg);
|
|
3015
|
+
console.log(`CLI configured to use local server: ${localUrl}`);
|
|
3016
|
+
console.log(` (previous: ${previousUrl})`);
|
|
3017
|
+
console.log(` To revert: corp config set api_url ${previousUrl}
|
|
3018
|
+
`);
|
|
3019
|
+
}
|
|
2389
3020
|
console.log(`Starting server on port ${port}...`);
|
|
2390
3021
|
console.log(`Data directory: ${opts.dataDir}`);
|
|
2391
3022
|
const child = server.startServer({
|
|
@@ -2394,6 +3025,12 @@ async function serveCommand(opts) {
|
|
|
2394
3025
|
});
|
|
2395
3026
|
const shutdown = () => {
|
|
2396
3027
|
console.log("\nShutting down server...");
|
|
3028
|
+
if (previousUrl !== localUrl) {
|
|
3029
|
+
const current = loadConfig2();
|
|
3030
|
+
current.api_url = previousUrl;
|
|
3031
|
+
saveConfig2(current);
|
|
3032
|
+
console.log(`CLI restored to: ${previousUrl}`);
|
|
3033
|
+
}
|
|
2397
3034
|
child.kill("SIGTERM");
|
|
2398
3035
|
};
|
|
2399
3036
|
process.on("SIGINT", shutdown);
|
|
@@ -2402,16 +3039,50 @@ async function serveCommand(opts) {
|
|
|
2402
3039
|
process.exit(code ?? 0);
|
|
2403
3040
|
});
|
|
2404
3041
|
}
|
|
3042
|
+
var ENV_TEMPLATE;
|
|
2405
3043
|
var init_serve = __esm({
|
|
2406
3044
|
"src/commands/serve.ts"() {
|
|
2407
3045
|
"use strict";
|
|
3046
|
+
ENV_TEMPLATE = `# Corporation API server configuration
|
|
3047
|
+
# Generated by: corp serve
|
|
3048
|
+
|
|
3049
|
+
# Required \u2014 secret for signing JWTs
|
|
3050
|
+
JWT_SECRET={{JWT_SECRET}}
|
|
3051
|
+
|
|
3052
|
+
# Required \u2014 Fernet key for encrypting secrets at rest (base64url, 32 bytes)
|
|
3053
|
+
SECRETS_MASTER_KEY={{SECRETS_MASTER_KEY}}
|
|
3054
|
+
|
|
3055
|
+
# Required \u2014 bearer token for internal worker-to-server auth
|
|
3056
|
+
INTERNAL_WORKER_TOKEN={{INTERNAL_WORKER_TOKEN}}
|
|
3057
|
+
|
|
3058
|
+
# Server port (default: 8000)
|
|
3059
|
+
# PORT=8000
|
|
3060
|
+
|
|
3061
|
+
# Data directory for git repos (default: ./data/repos)
|
|
3062
|
+
# DATA_DIR=./data/repos
|
|
3063
|
+
|
|
3064
|
+
# Redis URL for agent job queue (optional)
|
|
3065
|
+
# REDIS_URL=redis://localhost:6379/0
|
|
3066
|
+
|
|
3067
|
+
# LLM proxy upstream (default: https://openrouter.ai/api/v1)
|
|
3068
|
+
# LLM_UPSTREAM_URL=https://openrouter.ai/api/v1
|
|
3069
|
+
|
|
3070
|
+
# PEM-encoded Ed25519 key for signing git commits (optional)
|
|
3071
|
+
# COMMIT_SIGNING_KEY=
|
|
3072
|
+
|
|
3073
|
+
# Max agent queue depth (default: 1000)
|
|
3074
|
+
# MAX_QUEUE_DEPTH=1000
|
|
3075
|
+
`;
|
|
2408
3076
|
}
|
|
2409
3077
|
});
|
|
2410
3078
|
|
|
2411
3079
|
// src/index.ts
|
|
2412
3080
|
import { Command } from "commander";
|
|
3081
|
+
import { createRequire } from "module";
|
|
3082
|
+
var require2 = createRequire(import.meta.url);
|
|
3083
|
+
var pkg = require2("../package.json");
|
|
2413
3084
|
var program = new Command();
|
|
2414
|
-
program.name("corp").description("corp \u2014 Corporate governance from the terminal").version(
|
|
3085
|
+
program.name("corp").description("corp \u2014 Corporate governance from the terminal").version(pkg.version);
|
|
2415
3086
|
program.command("setup").description("Interactive setup wizard").action(async () => {
|
|
2416
3087
|
const { setupCommand: setupCommand2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
2417
3088
|
await setupCommand2();
|
|
@@ -2422,15 +3093,15 @@ program.command("status").description("Workspace summary").action(async () => {
|
|
|
2422
3093
|
});
|
|
2423
3094
|
var configCmd = program.command("config").description("Manage configuration");
|
|
2424
3095
|
configCmd.command("set <key> <value>").description("Set a config value (dot-path)").action(async (key, value) => {
|
|
2425
|
-
const { configSetCommand: configSetCommand2 } = await Promise.resolve().then(() => (init_config2(),
|
|
3096
|
+
const { configSetCommand: configSetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
|
|
2426
3097
|
configSetCommand2(key, value);
|
|
2427
3098
|
});
|
|
2428
3099
|
configCmd.command("get <key>").description("Get a config value (dot-path)").action(async (key) => {
|
|
2429
|
-
const { configGetCommand: configGetCommand2 } = await Promise.resolve().then(() => (init_config2(),
|
|
3100
|
+
const { configGetCommand: configGetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
|
|
2430
3101
|
configGetCommand2(key);
|
|
2431
3102
|
});
|
|
2432
3103
|
configCmd.command("list").description("List all config (API keys masked)").action(async () => {
|
|
2433
|
-
const { configListCommand: configListCommand2 } = await Promise.resolve().then(() => (init_config2(),
|
|
3104
|
+
const { configListCommand: configListCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports2));
|
|
2434
3105
|
configListCommand2();
|
|
2435
3106
|
});
|
|
2436
3107
|
program.command("obligations").description("List obligations with urgency tiers").option("--tier <tier>", "Filter by urgency tier").option("--json", "Output as JSON").action(async (opts) => {
|
|
@@ -2461,7 +3132,7 @@ entitiesCmd.command("show <entity-id>").option("--json", "Output as JSON").descr
|
|
|
2461
3132
|
const { entitiesShowCommand: entitiesShowCommand2 } = await Promise.resolve().then(() => (init_entities(), entities_exports));
|
|
2462
3133
|
await entitiesShowCommand2(entityId, opts);
|
|
2463
3134
|
});
|
|
2464
|
-
entitiesCmd.command("convert <entity-id>").requiredOption("--to <type>", "Target entity type (llc,
|
|
3135
|
+
entitiesCmd.command("convert <entity-id>").requiredOption("--to <type>", "Target entity type (llc, c_corp)").option("--jurisdiction <jurisdiction>", "New jurisdiction").description("Convert entity to a different type").action(async (entityId, opts) => {
|
|
2465
3136
|
const { entitiesConvertCommand: entitiesConvertCommand2 } = await Promise.resolve().then(() => (init_entities(), entities_exports));
|
|
2466
3137
|
await entitiesConvertCommand2(entityId, opts);
|
|
2467
3138
|
});
|
|
@@ -2469,7 +3140,7 @@ entitiesCmd.command("dissolve <entity-id>").requiredOption("--reason <reason>",
|
|
|
2469
3140
|
const { entitiesDissolveCommand: entitiesDissolveCommand2 } = await Promise.resolve().then(() => (init_entities(), entities_exports));
|
|
2470
3141
|
await entitiesDissolveCommand2(entityId, opts);
|
|
2471
3142
|
});
|
|
2472
|
-
var contactsCmd = program.command("contacts").description("Contact management").option("--json", "Output as JSON").action(async (opts) => {
|
|
3143
|
+
var contactsCmd = program.command("contacts").description("Contact management").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON").action(async (opts) => {
|
|
2473
3144
|
const { contactsListCommand: contactsListCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
|
|
2474
3145
|
await contactsListCommand2(opts);
|
|
2475
3146
|
});
|
|
@@ -2477,15 +3148,16 @@ contactsCmd.command("show <contact-id>").option("--json", "Output as JSON").desc
|
|
|
2477
3148
|
const { contactsShowCommand: contactsShowCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
|
|
2478
3149
|
await contactsShowCommand2(contactId, opts);
|
|
2479
3150
|
});
|
|
2480
|
-
contactsCmd.command("add").requiredOption("--name <name>", "Contact name").requiredOption("--email <email>", "Contact email").option("--
|
|
3151
|
+
contactsCmd.command("add").requiredOption("--name <name>", "Contact name").requiredOption("--email <email>", "Contact email").option("--type <type>", "Contact type (individual, organization)", "individual").option("--category <category>", "Category (employee, contractor, board_member, investor, law_firm, valuation_firm, accounting_firm, officer, advisor)").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").description("Add a new contact").action(async (opts, cmd) => {
|
|
3152
|
+
const parent = cmd.parent.opts();
|
|
2481
3153
|
const { contactsAddCommand: contactsAddCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
|
|
2482
|
-
await contactsAddCommand2(opts);
|
|
3154
|
+
await contactsAddCommand2({ ...opts, entityId: parent.entityId });
|
|
2483
3155
|
});
|
|
2484
3156
|
contactsCmd.command("edit <contact-id>").option("--name <name>", "Contact name").option("--email <email>", "Contact email").option("--category <category>", "Contact category").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").description("Edit an existing contact").action(async (contactId, opts) => {
|
|
2485
3157
|
const { contactsEditCommand: contactsEditCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
|
|
2486
3158
|
await contactsEditCommand2(contactId, opts);
|
|
2487
3159
|
});
|
|
2488
|
-
var capTableCmd = program.command("cap-table").description("Cap table, SAFEs, transfers, valuations").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3160
|
+
var capTableCmd = program.command("cap-table").description("Cap table, equity grants, SAFEs, transfers, and valuations").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON").action(async (opts) => {
|
|
2489
3161
|
const { capTableCommand: capTableCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
2490
3162
|
await capTableCommand2(opts);
|
|
2491
3163
|
});
|
|
@@ -2509,7 +3181,7 @@ capTableCmd.command("409a").description("Current 409A valuation").action(async (
|
|
|
2509
3181
|
const { fourOhNineACommand: fourOhNineACommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
2510
3182
|
await fourOhNineACommand2(parent);
|
|
2511
3183
|
});
|
|
2512
|
-
capTableCmd.command("issue-equity").requiredOption("--grant-type <type>", "Grant type").requiredOption("--shares <n>", "Number of shares", parseInt).requiredOption("--recipient <name>", "Recipient name").description("Issue an equity grant").action(async (opts, cmd) => {
|
|
3184
|
+
capTableCmd.command("issue-equity").requiredOption("--grant-type <type>", "Grant type (e.g. founder, advisor, employee, investor)").requiredOption("--shares <n>", "Number of shares", parseInt).requiredOption("--recipient <name>", "Recipient name").option("--email <email>", "Recipient email (auto-creates contact if needed)").option("--instrument-id <id>", "Instrument ID (auto-detected from cap table if omitted)").description("Issue an equity grant (creates a round, adds security, and issues it)").action(async (opts, cmd) => {
|
|
2513
3185
|
const parent = cmd.parent.opts();
|
|
2514
3186
|
const { issueEquityCommand: issueEquityCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
2515
3187
|
await issueEquityCommand2({ ...opts, entityId: parent.entityId });
|
|
@@ -2524,11 +3196,41 @@ capTableCmd.command("transfer").requiredOption("--from-grant <id>", "Source gran
|
|
|
2524
3196
|
const { transferSharesCommand: transferSharesCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
2525
3197
|
await transferSharesCommand2({ ...opts, entityId: parent.entityId });
|
|
2526
3198
|
});
|
|
2527
|
-
capTableCmd.command("distribute").requiredOption("--amount <n>", "Total distribution amount in cents", parseInt).option("--type <type>", "Distribution type", "
|
|
3199
|
+
capTableCmd.command("distribute").requiredOption("--amount <n>", "Total distribution amount in cents", parseInt).option("--type <type>", "Distribution type (dividend, return, liquidation)", "dividend").requiredOption("--description <desc>", "Distribution description").description("Calculate a distribution").action(async (opts, cmd) => {
|
|
2528
3200
|
const parent = cmd.parent.opts();
|
|
2529
3201
|
const { distributeCommand: distributeCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
2530
3202
|
await distributeCommand2({ ...opts, entityId: parent.entityId });
|
|
2531
3203
|
});
|
|
3204
|
+
capTableCmd.command("start-round").requiredOption("--name <name>", "Round name").requiredOption("--issuer-legal-entity-id <id>", "Issuer legal entity ID").description("Start a staged equity round").action(async (opts, cmd) => {
|
|
3205
|
+
const parent = cmd.parent.opts();
|
|
3206
|
+
const { startRoundCommand: startRoundCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
3207
|
+
await startRoundCommand2({ ...opts, entityId: parent.entityId });
|
|
3208
|
+
});
|
|
3209
|
+
capTableCmd.command("add-security").requiredOption("--round-id <id>", "Round ID").requiredOption("--instrument-id <id>", "Instrument ID").requiredOption("--quantity <n>", "Number of shares/units", parseInt).requiredOption("--recipient-name <name>", "Recipient display name").option("--holder-id <id>", "Existing holder ID").option("--email <email>", "Recipient email (to find or create holder)").option("--principal-cents <n>", "Principal amount in cents", parseInt).option("--grant-type <type>", "Grant type").description("Add a security to a staged equity round").action(async (opts, cmd) => {
|
|
3210
|
+
const parent = cmd.parent.opts();
|
|
3211
|
+
const { addSecurityCommand: addSecurityCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
3212
|
+
await addSecurityCommand2({ ...opts, entityId: parent.entityId });
|
|
3213
|
+
});
|
|
3214
|
+
capTableCmd.command("issue-round").requiredOption("--round-id <id>", "Round ID").description("Issue all securities and close a staged round").action(async (opts, cmd) => {
|
|
3215
|
+
const parent = cmd.parent.opts();
|
|
3216
|
+
const { issueRoundCommand: issueRoundCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
3217
|
+
await issueRoundCommand2({ ...opts, entityId: parent.entityId });
|
|
3218
|
+
});
|
|
3219
|
+
capTableCmd.command("create-valuation").requiredOption("--type <type>", "Valuation type (four_oh_nine_a, fair_market_value, etc.)").requiredOption("--date <date>", "Effective date (ISO 8601)").requiredOption("--methodology <method>", "Methodology (income, market, asset, backsolve, hybrid)").option("--fmv <cents>", "FMV per share in cents", parseInt).option("--enterprise-value <cents>", "Enterprise value in cents", parseInt).description("Create a valuation").action(async (opts, cmd) => {
|
|
3220
|
+
const parent = cmd.parent.opts();
|
|
3221
|
+
const { createValuationCommand: createValuationCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
3222
|
+
await createValuationCommand2({ ...opts, entityId: parent.entityId });
|
|
3223
|
+
});
|
|
3224
|
+
capTableCmd.command("submit-valuation <valuation-id>").description("Submit a valuation for board approval").action(async (valuationId, _opts, cmd) => {
|
|
3225
|
+
const parent = cmd.parent.opts();
|
|
3226
|
+
const { submitValuationCommand: submitValuationCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
3227
|
+
await submitValuationCommand2({ valuationId, entityId: parent.entityId });
|
|
3228
|
+
});
|
|
3229
|
+
capTableCmd.command("approve-valuation <valuation-id>").option("--resolution-id <id>", "Resolution ID from the board vote").description("Approve a valuation").action(async (valuationId, opts, cmd) => {
|
|
3230
|
+
const parent = cmd.parent.opts();
|
|
3231
|
+
const { approveValuationCommand: approveValuationCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
3232
|
+
await approveValuationCommand2({ ...opts, valuationId, entityId: parent.entityId });
|
|
3233
|
+
});
|
|
2532
3234
|
var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <id>", "Entity ID (overrides active entity)");
|
|
2533
3235
|
financeCmd.command("invoice").requiredOption("--customer <name>", "Customer name").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--due-date <date>", "Due date (ISO 8601)").option("--description <desc>", "Description", "Services rendered").description("Create an invoice").action(async (opts, cmd) => {
|
|
2534
3236
|
const parent = cmd.parent.opts();
|
|
@@ -2564,6 +3266,15 @@ var governanceCmd = program.command("governance").description("Governance bodies
|
|
|
2564
3266
|
const { governanceListCommand: governanceListCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
2565
3267
|
await governanceListCommand2(opts);
|
|
2566
3268
|
});
|
|
3269
|
+
governanceCmd.command("create-body").requiredOption("--name <name>", "Body name (e.g. 'Board of Directors')").requiredOption("--body-type <type>", "Body type (board_of_directors, llc_member_vote)").option("--quorum <rule>", "Quorum rule (majority, supermajority, unanimous)", "majority").option("--voting <method>", "Voting method (per_capita, per_unit)", "per_capita").description("Create a governance body").action(async (opts, cmd) => {
|
|
3270
|
+
const parent = cmd.parent.opts();
|
|
3271
|
+
const { governanceCreateBodyCommand: governanceCreateBodyCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3272
|
+
await governanceCreateBodyCommand2({ ...opts, entityId: parent.entityId });
|
|
3273
|
+
});
|
|
3274
|
+
governanceCmd.command("add-seat <body-id>").requiredOption("--holder <contact-id>", "Contact ID for the seat holder").option("--title <title>", "Seat title (e.g. 'Director', 'Member')").description("Add a seat to a governance body").action(async (bodyId, opts) => {
|
|
3275
|
+
const { governanceAddSeatCommand: governanceAddSeatCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3276
|
+
await governanceAddSeatCommand2(bodyId, opts);
|
|
3277
|
+
});
|
|
2567
3278
|
governanceCmd.command("seats <body-id>").description("Seats for a governance body").action(async (bodyId, _opts, cmd) => {
|
|
2568
3279
|
const parent = cmd.parent.opts();
|
|
2569
3280
|
const { governanceSeatsCommand: governanceSeatsCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
@@ -2588,6 +3299,41 @@ governanceCmd.command("vote <meeting-id> <item-id>").requiredOption("--voter <na
|
|
|
2588
3299
|
const { governanceVoteCommand: governanceVoteCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
2589
3300
|
await governanceVoteCommand2(meetingId, itemId, opts);
|
|
2590
3301
|
});
|
|
3302
|
+
governanceCmd.command("notice <meeting-id>").description("Send meeting notice").action(async (meetingId, _opts, cmd) => {
|
|
3303
|
+
const parent = cmd.parent.opts();
|
|
3304
|
+
const { sendNoticeCommand: sendNoticeCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3305
|
+
await sendNoticeCommand2(meetingId, { entityId: parent.entityId });
|
|
3306
|
+
});
|
|
3307
|
+
governanceCmd.command("adjourn <meeting-id>").description("Adjourn a meeting").action(async (meetingId, _opts, cmd) => {
|
|
3308
|
+
const parent = cmd.parent.opts();
|
|
3309
|
+
const { adjournMeetingCommand: adjournMeetingCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3310
|
+
await adjournMeetingCommand2(meetingId, { entityId: parent.entityId });
|
|
3311
|
+
});
|
|
3312
|
+
governanceCmd.command("cancel <meeting-id>").description("Cancel a meeting").action(async (meetingId, _opts, cmd) => {
|
|
3313
|
+
const parent = cmd.parent.opts();
|
|
3314
|
+
const { cancelMeetingCommand: cancelMeetingCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3315
|
+
await cancelMeetingCommand2(meetingId, { entityId: parent.entityId });
|
|
3316
|
+
});
|
|
3317
|
+
governanceCmd.command("agenda-items <meeting-id>").description("List agenda items for a meeting").action(async (meetingId, _opts, cmd) => {
|
|
3318
|
+
const parent = cmd.parent.opts();
|
|
3319
|
+
const { listAgendaItemsCommand: listAgendaItemsCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3320
|
+
await listAgendaItemsCommand2(meetingId, { entityId: parent.entityId, json: parent.json });
|
|
3321
|
+
});
|
|
3322
|
+
governanceCmd.command("finalize-item <meeting-id> <item-id>").requiredOption("--status <status>", "Status: Voted, Discussed, Tabled, or Withdrawn").description("Finalize an agenda item").action(async (meetingId, itemId, opts, cmd) => {
|
|
3323
|
+
const parent = cmd.parent.opts();
|
|
3324
|
+
const { finalizeAgendaItemCommand: finalizeAgendaItemCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3325
|
+
await finalizeAgendaItemCommand2(meetingId, itemId, { ...opts, entityId: parent.entityId });
|
|
3326
|
+
});
|
|
3327
|
+
governanceCmd.command("resolve <meeting-id> <item-id>").requiredOption("--text <resolution_text>", "Resolution text").description("Compute a resolution for an agenda item").action(async (meetingId, itemId, opts, cmd) => {
|
|
3328
|
+
const parent = cmd.parent.opts();
|
|
3329
|
+
const { computeResolutionCommand: computeResolutionCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3330
|
+
await computeResolutionCommand2(meetingId, itemId, { ...opts, entityId: parent.entityId });
|
|
3331
|
+
});
|
|
3332
|
+
governanceCmd.command("written-consent").requiredOption("--body <id>", "Governance body ID").requiredOption("--title <title>", "Title").requiredOption("--description <desc>", "Description").description("Create a written consent action").action(async (opts, cmd) => {
|
|
3333
|
+
const parent = cmd.parent.opts();
|
|
3334
|
+
const { writtenConsentCommand: writtenConsentCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
3335
|
+
await writtenConsentCommand2({ ...opts, entityId: parent.entityId });
|
|
3336
|
+
});
|
|
2591
3337
|
var documentsCmd = program.command("documents").description("Documents and signing").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON").action(async (opts) => {
|
|
2592
3338
|
const { documentsListCommand: documentsListCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
|
|
2593
3339
|
await documentsListCommand2(opts);
|
|
@@ -2596,11 +3342,16 @@ documentsCmd.command("signing-link <doc-id>").description("Get a signing link fo
|
|
|
2596
3342
|
const { documentsSigningLinkCommand: documentsSigningLinkCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
|
|
2597
3343
|
await documentsSigningLinkCommand2(docId);
|
|
2598
3344
|
});
|
|
2599
|
-
documentsCmd.command("generate").requiredOption("--template <type>", "Template type").requiredOption("--counterparty <name>", "Counterparty name").option("--effective-date <date>", "Effective date (ISO 8601)").description("Generate a contract from a template").action(async (opts, cmd) => {
|
|
3345
|
+
documentsCmd.command("generate").requiredOption("--template <type>", "Template type (consulting_agreement, employment_offer, contractor_agreement, nda, custom)").requiredOption("--counterparty <name>", "Counterparty name").option("--effective-date <date>", "Effective date (ISO 8601, defaults to today)").description("Generate a contract from a template").action(async (opts, cmd) => {
|
|
2600
3346
|
const parent = cmd.parent.opts();
|
|
2601
3347
|
const { documentsGenerateCommand: documentsGenerateCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
|
|
2602
3348
|
await documentsGenerateCommand2({ ...opts, entityId: parent.entityId });
|
|
2603
3349
|
});
|
|
3350
|
+
documentsCmd.command("preview-pdf").requiredOption("--document-id <id>", "AST document definition ID (e.g. 'bylaws')").description("Preview a governance document as PDF").action(async (opts, cmd) => {
|
|
3351
|
+
const parent = cmd.parent.opts();
|
|
3352
|
+
const { documentsPreviewPdfCommand: documentsPreviewPdfCommand2 } = await Promise.resolve().then(() => (init_documents(), documents_exports));
|
|
3353
|
+
await documentsPreviewPdfCommand2({ ...opts, entityId: parent.entityId });
|
|
3354
|
+
});
|
|
2604
3355
|
var taxCmd = program.command("tax").description("Tax filings and deadline tracking").option("--entity-id <id>", "Entity ID (overrides active entity)");
|
|
2605
3356
|
taxCmd.command("file").requiredOption("--type <type>", "Document type").requiredOption("--year <year>", "Tax year", parseInt).description("File a tax document").action(async (opts, cmd) => {
|
|
2606
3357
|
const parent = cmd.parent.opts();
|
|
@@ -2656,26 +3407,33 @@ billingCmd.command("portal").description("Open Stripe Customer Portal").action(a
|
|
|
2656
3407
|
const { billingPortalCommand: billingPortalCommand2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
|
|
2657
3408
|
await billingPortalCommand2();
|
|
2658
3409
|
});
|
|
2659
|
-
billingCmd.command("upgrade").option("--
|
|
3410
|
+
billingCmd.command("upgrade").option("--plan <plan>", "Plan ID to upgrade to (free, pro, enterprise)", "pro").description("Open Stripe Checkout to upgrade your plan").action(async (opts) => {
|
|
2660
3411
|
const { billingUpgradeCommand: billingUpgradeCommand2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
|
|
2661
3412
|
await billingUpgradeCommand2(opts);
|
|
2662
3413
|
});
|
|
2663
|
-
|
|
2664
|
-
const {
|
|
2665
|
-
|
|
3414
|
+
program.command("approvals").description("Approvals are managed through governance meetings and execution intents").action(async () => {
|
|
3415
|
+
const { printError: printError2 } = await Promise.resolve().then(() => (init_output(), output_exports));
|
|
3416
|
+
printError2(
|
|
3417
|
+
"Approvals are managed through governance meetings.\n Use: corp governance convene ... to schedule a board meeting\n Use: corp governance vote <meeting-id> <item-id> ... to cast votes"
|
|
3418
|
+
);
|
|
2666
3419
|
});
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
await approvalsRespondCommand2(approvalId, "approve", opts);
|
|
2670
|
-
});
|
|
2671
|
-
approvalsCmd.command("reject <approval-id>").option("--message <msg>", "Optional message").description("Reject a pending approval").action(async (approvalId, opts) => {
|
|
2672
|
-
const { approvalsRespondCommand: approvalsRespondCommand2 } = await Promise.resolve().then(() => (init_approvals(), approvals_exports));
|
|
2673
|
-
await approvalsRespondCommand2(approvalId, "reject", opts);
|
|
2674
|
-
});
|
|
2675
|
-
program.command("form").description("Create a new entity (interactive or scripted)").option("--type <type>", "Entity type (llc, c_corp, etc.)").option("--name <name>", "Entity name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. DE, WY)").option("--member <member>", "Member as 'name,email,role[,pct]' (repeatable)", (v, a) => [...a, v], []).action(async (opts) => {
|
|
3420
|
+
var formCmd = program.command("form").description("Form a new entity with founders and cap table (Cooley-style)").option("--entity-type <type>", "Entity type (llc, c_corp)").option("--name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--member <member>", "Member as 'name,email,role[,pct]' \u2014 role: director|officer|manager|member|chair (repeatable)", (v, a) => [...a, v], []).option("--address <address>", "Company address as 'street,city,state,zip'").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)", "12-31").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").action(async (opts) => {
|
|
3421
|
+
if (opts.entityType && !opts.type) opts.type = opts.entityType;
|
|
2676
3422
|
const { formCommand: formCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
2677
3423
|
await formCommand2(opts);
|
|
2678
3424
|
});
|
|
3425
|
+
formCmd.command("create").description("Create a pending entity (staged flow step 1)").requiredOption("--type <type>", "Entity type (llc, c_corp)").requiredOption("--name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").action(async (opts) => {
|
|
3426
|
+
const { formCreateCommand: formCreateCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
3427
|
+
await formCreateCommand2(opts);
|
|
3428
|
+
});
|
|
3429
|
+
formCmd.command("add-founder <entity-id>").description("Add a founder to a pending entity (staged flow step 2)").requiredOption("--name <name>", "Founder name").requiredOption("--email <email>", "Founder email").requiredOption("--role <role>", "Role: director|officer|manager|member|chair").requiredOption("--pct <pct>", "Ownership percentage").option("--officer-title <title>", "Officer title (corporations only)").option("--incorporator", "Mark as sole incorporator (corporations only)").action(async (entityId, opts) => {
|
|
3430
|
+
const { formAddFounderCommand: formAddFounderCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
3431
|
+
await formAddFounderCommand2(entityId, opts);
|
|
3432
|
+
});
|
|
3433
|
+
formCmd.command("finalize <entity-id>").description("Finalize formation and generate documents + cap table (staged flow step 3)").action(async (entityId) => {
|
|
3434
|
+
const { formFinalizeCommand: formFinalizeCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
3435
|
+
await formFinalizeCommand2(entityId);
|
|
3436
|
+
});
|
|
2679
3437
|
program.command("api-keys").description("List API keys").option("--json", "Output as JSON").action(async (opts) => {
|
|
2680
3438
|
const { apiKeysCommand: apiKeysCommand2 } = await Promise.resolve().then(() => (init_api_keys(), api_keys_exports));
|
|
2681
3439
|
await apiKeysCommand2(opts);
|