@thecorporation/cli 26.3.21 → 26.3.22
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 +46 -11
- package/dist/index.js +443 -170
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -90,9 +90,13 @@ function allowUnsafeApiUrl() {
|
|
|
90
90
|
return process.env.CORP_UNSAFE_API_URL === "1";
|
|
91
91
|
}
|
|
92
92
|
function validateApiUrl(value) {
|
|
93
|
+
const trimmed = value.trim();
|
|
94
|
+
if (trimmed.startsWith("process://")) {
|
|
95
|
+
return trimmed;
|
|
96
|
+
}
|
|
93
97
|
let parsed;
|
|
94
98
|
try {
|
|
95
|
-
parsed = new URL(
|
|
99
|
+
parsed = new URL(trimmed);
|
|
96
100
|
} catch {
|
|
97
101
|
throw new Error("api_url must be a valid absolute URL");
|
|
98
102
|
}
|
|
@@ -217,6 +221,7 @@ function normalizeConfig(raw) {
|
|
|
217
221
|
cfg.workspace_id = normalizeString(raw.workspace_id) ?? cfg.workspace_id;
|
|
218
222
|
cfg.hosting_mode = normalizeString(raw.hosting_mode) ?? cfg.hosting_mode;
|
|
219
223
|
cfg.active_entity_id = normalizeString(raw.active_entity_id) ?? cfg.active_entity_id;
|
|
224
|
+
cfg.data_dir = normalizeString(raw.data_dir) ?? cfg.data_dir;
|
|
220
225
|
if (isObject(raw.llm)) {
|
|
221
226
|
cfg.llm.provider = normalizeString(raw.llm.provider) ?? cfg.llm.provider;
|
|
222
227
|
cfg.llm.api_key = normalizeString(raw.llm.api_key) ?? cfg.llm.api_key;
|
|
@@ -263,7 +268,8 @@ function serializeConfig(cfg) {
|
|
|
263
268
|
name: normalized.user.name,
|
|
264
269
|
email: normalized.user.email
|
|
265
270
|
},
|
|
266
|
-
active_entity_id: normalized.active_entity_id
|
|
271
|
+
active_entity_id: normalized.active_entity_id,
|
|
272
|
+
...normalized.data_dir ? { data_dir: normalized.data_dir } : {}
|
|
267
273
|
};
|
|
268
274
|
if (normalized.active_entity_ids && Object.keys(normalized.active_entity_ids).length > 0) {
|
|
269
275
|
serialized.active_entity_ids = normalized.active_entity_ids;
|
|
@@ -283,6 +289,20 @@ function serializeAuth(cfg) {
|
|
|
283
289
|
if (normalized.llm.api_key) {
|
|
284
290
|
serialized.llm = { api_key: normalized.llm.api_key };
|
|
285
291
|
}
|
|
292
|
+
const existingAuth = readJsonFile(AUTH_FILE);
|
|
293
|
+
if (isObject(existingAuth) && isObject(existingAuth.server_secrets)) {
|
|
294
|
+
const ss = existingAuth.server_secrets;
|
|
295
|
+
if (typeof ss.jwt_secret === "string" && typeof ss.secrets_master_key === "string" && typeof ss.internal_worker_token === "string") {
|
|
296
|
+
serialized.server_secrets = {
|
|
297
|
+
jwt_secret: ss.jwt_secret,
|
|
298
|
+
secrets_master_key: ss.secrets_master_key,
|
|
299
|
+
internal_worker_token: ss.internal_worker_token
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (cfg._server_secrets) {
|
|
304
|
+
serialized.server_secrets = cfg._server_secrets;
|
|
305
|
+
}
|
|
286
306
|
return JSON.stringify(serialized, null, 2) + "\n";
|
|
287
307
|
}
|
|
288
308
|
function requireSupportedConfigKey(dotPath) {
|
|
@@ -311,6 +331,9 @@ function setKnownConfigValue(cfg, dotPath, value) {
|
|
|
311
331
|
case "hosting_mode":
|
|
312
332
|
cfg.hosting_mode = value.trim();
|
|
313
333
|
return;
|
|
334
|
+
case "data_dir":
|
|
335
|
+
cfg.data_dir = value.trim();
|
|
336
|
+
return;
|
|
314
337
|
case "llm.provider":
|
|
315
338
|
cfg.llm.provider = value.trim();
|
|
316
339
|
return;
|
|
@@ -492,7 +515,8 @@ var init_config = __esm({
|
|
|
492
515
|
"llm.base_url",
|
|
493
516
|
"user.name",
|
|
494
517
|
"user.email",
|
|
495
|
-
"active_entity_id"
|
|
518
|
+
"active_entity_id",
|
|
519
|
+
"data_dir"
|
|
496
520
|
]);
|
|
497
521
|
SENSITIVE_CONFIG_KEYS = /* @__PURE__ */ new Set(["api_url", "api_key", "workspace_id"]);
|
|
498
522
|
DEFAULTS = {
|
|
@@ -507,7 +531,8 @@ var init_config = __esm({
|
|
|
507
531
|
base_url: process.env.CORP_LLM_BASE_URL || void 0
|
|
508
532
|
},
|
|
509
533
|
user: { name: "", email: "" },
|
|
510
|
-
active_entity_id: ""
|
|
534
|
+
active_entity_id: "",
|
|
535
|
+
data_dir: ""
|
|
511
536
|
};
|
|
512
537
|
}
|
|
513
538
|
});
|
|
@@ -658,7 +683,11 @@ function describeReferenceRecord(kind, record) {
|
|
|
658
683
|
idFields: ["share_class_id", "id"],
|
|
659
684
|
labelFields: ["class_code", "name", "share_class"]
|
|
660
685
|
},
|
|
661
|
-
round: { idFields: ["round_id", "equity_round_id", "id"], labelFields: ["name"] }
|
|
686
|
+
round: { idFields: ["round_id", "equity_round_id", "id"], labelFields: ["name"] },
|
|
687
|
+
service_request: {
|
|
688
|
+
idFields: ["request_id", "service_request_id", "id"],
|
|
689
|
+
labelFields: ["service_slug", "status"]
|
|
690
|
+
}
|
|
662
691
|
};
|
|
663
692
|
const spec = specs[kind];
|
|
664
693
|
const id = extractId(record, spec.idFields);
|
|
@@ -726,7 +755,8 @@ var init_references = __esm({
|
|
|
726
755
|
"safe_note",
|
|
727
756
|
"instrument",
|
|
728
757
|
"share_class",
|
|
729
|
-
"round"
|
|
758
|
+
"round",
|
|
759
|
+
"service_request"
|
|
730
760
|
];
|
|
731
761
|
VALID_RESOURCE_KINDS = new Set(RESOURCE_KINDS);
|
|
732
762
|
MAX_REFERENCE_INPUT_LEN = 256;
|
|
@@ -755,6 +785,7 @@ var init_references = __esm({
|
|
|
755
785
|
valuationsCache = /* @__PURE__ */ new Map();
|
|
756
786
|
safeNotesCache = /* @__PURE__ */ new Map();
|
|
757
787
|
roundsCache = /* @__PURE__ */ new Map();
|
|
788
|
+
serviceRequestsCache = /* @__PURE__ */ new Map();
|
|
758
789
|
capTableCache = /* @__PURE__ */ new Map();
|
|
759
790
|
agentsCache;
|
|
760
791
|
constructor(client, cfg) {
|
|
@@ -869,6 +900,9 @@ var init_references = __esm({
|
|
|
869
900
|
async resolveRound(entityId, ref) {
|
|
870
901
|
return this.resolve("round", ref, { entityId });
|
|
871
902
|
}
|
|
903
|
+
async resolveServiceRequest(entityId, ref) {
|
|
904
|
+
return this.resolve("service_request", ref, { entityId });
|
|
905
|
+
}
|
|
872
906
|
async find(kind, query, scope = {}) {
|
|
873
907
|
const trimmedQuery = validateReferenceInput(query, "query", { allowEmpty: true });
|
|
874
908
|
const records = await this.listRecords(kind, scope);
|
|
@@ -1056,6 +1090,8 @@ var init_references = __esm({
|
|
|
1056
1090
|
return this.listShareClasses(scope.entityId);
|
|
1057
1091
|
case "round":
|
|
1058
1092
|
return this.listRounds(scope.entityId);
|
|
1093
|
+
case "service_request":
|
|
1094
|
+
return this.listServiceRequestRecords(scope.entityId);
|
|
1059
1095
|
}
|
|
1060
1096
|
})();
|
|
1061
1097
|
return this.attachStableHandles(kind, records, scope.entityId);
|
|
@@ -1320,6 +1356,14 @@ var init_references = __esm({
|
|
|
1320
1356
|
const capTable = await this.getCapTable(entityId);
|
|
1321
1357
|
return Array.isArray(capTable.share_classes) ? capTable.share_classes : [];
|
|
1322
1358
|
}
|
|
1359
|
+
async listServiceRequestRecords(entityId) {
|
|
1360
|
+
if (!entityId) throw new Error("An entity context is required to resolve service requests.");
|
|
1361
|
+
const cached = this.serviceRequestsCache.get(entityId);
|
|
1362
|
+
if (cached) return cached;
|
|
1363
|
+
const requests = await this.client.listServiceRequests(entityId);
|
|
1364
|
+
this.serviceRequestsCache.set(entityId, requests);
|
|
1365
|
+
return requests;
|
|
1366
|
+
}
|
|
1323
1367
|
};
|
|
1324
1368
|
}
|
|
1325
1369
|
});
|
|
@@ -1882,6 +1926,33 @@ function printAgentsTable(agents) {
|
|
|
1882
1926
|
}
|
|
1883
1927
|
console.log(table.toString());
|
|
1884
1928
|
}
|
|
1929
|
+
function printServiceCatalogTable(items) {
|
|
1930
|
+
const table = makeTable("Service Catalog", ["Slug", "Name", "Price", "Type"]);
|
|
1931
|
+
for (const item of items) {
|
|
1932
|
+
table.push([
|
|
1933
|
+
s(item.slug),
|
|
1934
|
+
s(item.name),
|
|
1935
|
+
money(item.amount_cents),
|
|
1936
|
+
s(item.price_type)
|
|
1937
|
+
]);
|
|
1938
|
+
}
|
|
1939
|
+
console.log(table.toString());
|
|
1940
|
+
}
|
|
1941
|
+
function printServiceRequestsTable(requests) {
|
|
1942
|
+
const table = makeTable("Service Requests", ["Ref", "Service", "Amount", "Status", "Created"]);
|
|
1943
|
+
for (const r of requests) {
|
|
1944
|
+
const status = s(r.status);
|
|
1945
|
+
const colored = status === "fulfilled" ? chalk.green(status) : status === "paid" ? chalk.cyan(status) : status === "checkout" ? chalk.yellow(status) : status === "failed" ? chalk.dim(status) : status;
|
|
1946
|
+
table.push([
|
|
1947
|
+
formatReferenceCell("service_request", r),
|
|
1948
|
+
s(r.service_slug),
|
|
1949
|
+
money(r.amount_cents),
|
|
1950
|
+
colored,
|
|
1951
|
+
date(r.created_at)
|
|
1952
|
+
]);
|
|
1953
|
+
}
|
|
1954
|
+
console.log(table.toString());
|
|
1955
|
+
}
|
|
1885
1956
|
function printBillingPanel(status, plans) {
|
|
1886
1957
|
const plan = s(status.plan ?? status.tier) || "free";
|
|
1887
1958
|
const subStatus = s(status.status) || "active";
|
|
@@ -1935,7 +2006,15 @@ var setup_exports = {};
|
|
|
1935
2006
|
__export(setup_exports, {
|
|
1936
2007
|
setupCommand: () => setupCommand
|
|
1937
2008
|
});
|
|
1938
|
-
import { input,
|
|
2009
|
+
import { input, select } from "@inquirer/prompts";
|
|
2010
|
+
import { homedir as homedir2 } from "os";
|
|
2011
|
+
import { join as join2 } from "path";
|
|
2012
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
2013
|
+
import {
|
|
2014
|
+
generateSecret,
|
|
2015
|
+
generateFernetKey,
|
|
2016
|
+
processRequest
|
|
2017
|
+
} from "@thecorporation/corp-tools";
|
|
1939
2018
|
async function requestMagicLink(apiUrl, email, tosAccepted) {
|
|
1940
2019
|
const resp = await fetch(`${apiUrl}/v1/auth/magic-link`, {
|
|
1941
2020
|
method: "POST",
|
|
@@ -1971,9 +2050,6 @@ async function verifyMagicLinkCode(apiUrl, code) {
|
|
|
1971
2050
|
workspace_id: data.workspace_id
|
|
1972
2051
|
};
|
|
1973
2052
|
}
|
|
1974
|
-
function isCloudApi(url) {
|
|
1975
|
-
return url.replace(/\/+$/, "").includes("thecorporation.ai");
|
|
1976
|
-
}
|
|
1977
2053
|
async function magicLinkAuth(apiUrl, email) {
|
|
1978
2054
|
console.log("\nSending magic link to " + email + "...");
|
|
1979
2055
|
await requestMagicLink(apiUrl, email, true);
|
|
@@ -1989,22 +2065,46 @@ async function magicLinkAuth(apiUrl, email) {
|
|
|
1989
2065
|
console.log("Verifying...");
|
|
1990
2066
|
return verifyMagicLinkCode(apiUrl, trimmed);
|
|
1991
2067
|
}
|
|
2068
|
+
function setupDataDir(dirPath) {
|
|
2069
|
+
if (!existsSync2(dirPath)) {
|
|
2070
|
+
mkdirSync2(dirPath, { recursive: true });
|
|
2071
|
+
return { isNew: true };
|
|
2072
|
+
}
|
|
2073
|
+
try {
|
|
2074
|
+
const entries = readdirSync(dirPath);
|
|
2075
|
+
if (entries.length > 0) {
|
|
2076
|
+
console.log("Found existing data, reusing.");
|
|
2077
|
+
return { isNew: false };
|
|
2078
|
+
}
|
|
2079
|
+
} catch {
|
|
2080
|
+
}
|
|
2081
|
+
return { isNew: true };
|
|
2082
|
+
}
|
|
2083
|
+
async function localProvision(dataDir, name) {
|
|
2084
|
+
const resp = processRequest(
|
|
2085
|
+
"process://",
|
|
2086
|
+
"POST",
|
|
2087
|
+
"/v1/workspaces/provision",
|
|
2088
|
+
{ "Content-Type": "application/json" },
|
|
2089
|
+
JSON.stringify({ name }),
|
|
2090
|
+
{ dataDir }
|
|
2091
|
+
);
|
|
2092
|
+
if (!resp.ok) {
|
|
2093
|
+
const detail = await resp.text();
|
|
2094
|
+
throw new Error(`Provision failed: HTTP ${resp.status} \u2014 ${detail}`);
|
|
2095
|
+
}
|
|
2096
|
+
const body = await resp.json();
|
|
2097
|
+
if (!body.api_key || !body.workspace_id) {
|
|
2098
|
+
throw new Error("Provision response missing api_key or workspace_id");
|
|
2099
|
+
}
|
|
2100
|
+
return {
|
|
2101
|
+
api_key: body.api_key,
|
|
2102
|
+
workspace_id: body.workspace_id
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
1992
2105
|
async function setupCommand() {
|
|
1993
2106
|
const cfg = loadConfig();
|
|
1994
2107
|
console.log("Welcome to corp \u2014 corporate governance from the terminal.\n");
|
|
1995
|
-
const customUrl = process.env.CORP_API_URL;
|
|
1996
|
-
if (customUrl) {
|
|
1997
|
-
try {
|
|
1998
|
-
cfg.api_url = validateApiUrl(customUrl);
|
|
1999
|
-
} catch (err) {
|
|
2000
|
-
printError(`Invalid CORP_API_URL: ${err}`);
|
|
2001
|
-
process.exit(1);
|
|
2002
|
-
}
|
|
2003
|
-
console.log(`Using API: ${cfg.api_url}
|
|
2004
|
-
`);
|
|
2005
|
-
} else {
|
|
2006
|
-
cfg.api_url = CLOUD_API_URL;
|
|
2007
|
-
}
|
|
2008
2108
|
console.log("--- User Info ---");
|
|
2009
2109
|
const user = cfg.user ?? { name: "", email: "" };
|
|
2010
2110
|
user.name = await input({
|
|
@@ -2016,10 +2116,53 @@ async function setupCommand() {
|
|
|
2016
2116
|
default: user.email || void 0
|
|
2017
2117
|
});
|
|
2018
2118
|
cfg.user = user;
|
|
2019
|
-
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2119
|
+
console.log("\n--- Hosting Mode ---");
|
|
2120
|
+
const hostingMode = await select({
|
|
2121
|
+
message: "How would you like to run corp?",
|
|
2122
|
+
choices: [
|
|
2123
|
+
{ value: "local", name: "Local (your machine)" },
|
|
2124
|
+
{ value: "cloud", name: "TheCorporation cloud" },
|
|
2125
|
+
{ value: "self-hosted", name: "Self-hosted server (custom URL)" }
|
|
2126
|
+
],
|
|
2127
|
+
default: cfg.hosting_mode || "local"
|
|
2128
|
+
});
|
|
2129
|
+
cfg.hosting_mode = hostingMode;
|
|
2130
|
+
if (hostingMode === "local") {
|
|
2131
|
+
const dataDir = await input({
|
|
2132
|
+
message: "Data directory",
|
|
2133
|
+
default: cfg.data_dir || DEFAULT_DATA_DIR
|
|
2134
|
+
});
|
|
2135
|
+
cfg.data_dir = dataDir;
|
|
2136
|
+
cfg.api_url = "process://";
|
|
2137
|
+
const { isNew } = setupDataDir(dataDir);
|
|
2138
|
+
const serverSecrets = {
|
|
2139
|
+
jwt_secret: generateSecret(),
|
|
2140
|
+
secrets_master_key: generateFernetKey(),
|
|
2141
|
+
internal_worker_token: generateSecret()
|
|
2142
|
+
};
|
|
2143
|
+
process.env.JWT_SECRET = serverSecrets.jwt_secret;
|
|
2144
|
+
process.env.SECRETS_MASTER_KEY = serverSecrets.secrets_master_key;
|
|
2145
|
+
process.env.INTERNAL_WORKER_TOKEN = serverSecrets.internal_worker_token;
|
|
2146
|
+
cfg._server_secrets = serverSecrets;
|
|
2147
|
+
if (isNew || !cfg.workspace_id) {
|
|
2148
|
+
console.log("\nProvisioning workspace...");
|
|
2149
|
+
try {
|
|
2150
|
+
const result = await localProvision(dataDir, `${user.name}'s workspace`);
|
|
2151
|
+
cfg.api_key = result.api_key;
|
|
2152
|
+
cfg.workspace_id = result.workspace_id;
|
|
2153
|
+
printSuccess(`Local workspace ready: ${result.workspace_id}`);
|
|
2154
|
+
} catch (err) {
|
|
2155
|
+
printError(`Workspace provisioning failed: ${err}`);
|
|
2156
|
+
console.log("You can retry with 'corp setup'.");
|
|
2157
|
+
}
|
|
2158
|
+
} else {
|
|
2159
|
+
console.log("\nExisting workspace found.");
|
|
2160
|
+
}
|
|
2161
|
+
} else if (hostingMode === "cloud") {
|
|
2162
|
+
cfg.api_url = CLOUD_API_URL;
|
|
2163
|
+
cfg.data_dir = "";
|
|
2164
|
+
const needsAuth = !cfg.api_key || !cfg.workspace_id;
|
|
2165
|
+
if (needsAuth) {
|
|
2023
2166
|
try {
|
|
2024
2167
|
const result = await magicLinkAuth(cfg.api_url, user.email);
|
|
2025
2168
|
cfg.api_key = result.api_key;
|
|
@@ -2032,6 +2175,22 @@ async function setupCommand() {
|
|
|
2032
2175
|
);
|
|
2033
2176
|
}
|
|
2034
2177
|
} else {
|
|
2178
|
+
console.log("\nExisting credentials found. Run 'corp status' to verify.");
|
|
2179
|
+
}
|
|
2180
|
+
} else {
|
|
2181
|
+
const url = await input({
|
|
2182
|
+
message: "Server URL",
|
|
2183
|
+
default: cfg.api_url !== CLOUD_API_URL && !cfg.api_url.startsWith("process://") ? cfg.api_url : void 0
|
|
2184
|
+
});
|
|
2185
|
+
try {
|
|
2186
|
+
cfg.api_url = validateApiUrl(url);
|
|
2187
|
+
} catch (err) {
|
|
2188
|
+
printError(`Invalid URL: ${err}`);
|
|
2189
|
+
process.exit(1);
|
|
2190
|
+
}
|
|
2191
|
+
cfg.data_dir = "";
|
|
2192
|
+
const needsAuth = !cfg.api_key || !cfg.workspace_id;
|
|
2193
|
+
if (needsAuth) {
|
|
2035
2194
|
console.log("\nProvisioning workspace...");
|
|
2036
2195
|
try {
|
|
2037
2196
|
const result = await provisionWorkspace(
|
|
@@ -2048,57 +2207,13 @@ async function setupCommand() {
|
|
|
2048
2207
|
);
|
|
2049
2208
|
}
|
|
2050
2209
|
}
|
|
2051
|
-
} else {
|
|
2052
|
-
console.log("\nVerifying existing credentials...");
|
|
2053
|
-
let keyValid = false;
|
|
2054
|
-
try {
|
|
2055
|
-
const resp = await fetch(
|
|
2056
|
-
`${cfg.api_url.replace(/\/+$/, "")}/v1/workspaces/${cfg.workspace_id}/status`,
|
|
2057
|
-
{ headers: { Authorization: `Bearer ${cfg.api_key}` } }
|
|
2058
|
-
);
|
|
2059
|
-
keyValid = resp.status !== 401;
|
|
2060
|
-
} catch {
|
|
2061
|
-
}
|
|
2062
|
-
if (keyValid) {
|
|
2063
|
-
console.log("Credentials OK.");
|
|
2064
|
-
} else {
|
|
2065
|
-
console.log("API key is no longer valid.");
|
|
2066
|
-
const reauth = await confirm({
|
|
2067
|
-
message: cloud ? "Re-authenticate via magic link?" : "Provision a new workspace? (This will replace your current credentials)",
|
|
2068
|
-
default: true
|
|
2069
|
-
});
|
|
2070
|
-
if (reauth) {
|
|
2071
|
-
try {
|
|
2072
|
-
if (cloud) {
|
|
2073
|
-
const result = await magicLinkAuth(cfg.api_url, user.email);
|
|
2074
|
-
cfg.api_key = result.api_key;
|
|
2075
|
-
cfg.workspace_id = result.workspace_id;
|
|
2076
|
-
printSuccess(`Authenticated. Workspace: ${result.workspace_id}`);
|
|
2077
|
-
} else {
|
|
2078
|
-
const result = await provisionWorkspace(
|
|
2079
|
-
cfg.api_url,
|
|
2080
|
-
`${user.name}'s workspace`
|
|
2081
|
-
);
|
|
2082
|
-
cfg.api_key = result.api_key;
|
|
2083
|
-
cfg.workspace_id = result.workspace_id;
|
|
2084
|
-
console.log(`Workspace provisioned: ${result.workspace_id}`);
|
|
2085
|
-
}
|
|
2086
|
-
} catch (err) {
|
|
2087
|
-
printError(`Authentication failed: ${err}`);
|
|
2088
|
-
}
|
|
2089
|
-
} else {
|
|
2090
|
-
console.log(
|
|
2091
|
-
"Keeping existing credentials. You can manually update with: corp config set api_key <key>"
|
|
2092
|
-
);
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
2210
|
}
|
|
2096
2211
|
saveConfig(cfg);
|
|
2097
2212
|
console.log("\nSettings saved to ~/.corp/config.json");
|
|
2098
2213
|
console.log("Credentials saved to ~/.corp/auth.json");
|
|
2099
2214
|
console.log("Run 'corp status' to verify your connection.");
|
|
2100
2215
|
}
|
|
2101
|
-
var CLOUD_API_URL;
|
|
2216
|
+
var CLOUD_API_URL, DEFAULT_DATA_DIR;
|
|
2102
2217
|
var init_setup = __esm({
|
|
2103
2218
|
"src/commands/setup.ts"() {
|
|
2104
2219
|
"use strict";
|
|
@@ -2106,6 +2221,7 @@ var init_setup = __esm({
|
|
|
2106
2221
|
init_api_client();
|
|
2107
2222
|
init_output();
|
|
2108
2223
|
CLOUD_API_URL = "https://api.thecorporation.ai";
|
|
2224
|
+
DEFAULT_DATA_DIR = join2(homedir2(), ".corp", "data");
|
|
2109
2225
|
}
|
|
2110
2226
|
});
|
|
2111
2227
|
|
|
@@ -3114,11 +3230,11 @@ import {
|
|
|
3114
3230
|
isWriteTool as _isWriteTool,
|
|
3115
3231
|
executeTool as _executeTool
|
|
3116
3232
|
} from "@thecorporation/corp-tools";
|
|
3117
|
-
import { join as
|
|
3118
|
-
import { homedir as
|
|
3233
|
+
import { join as join3 } from "path";
|
|
3234
|
+
import { homedir as homedir3 } from "os";
|
|
3119
3235
|
async function executeTool(name, args, client) {
|
|
3120
3236
|
return _executeTool(name, args, client, {
|
|
3121
|
-
dataDir:
|
|
3237
|
+
dataDir: join3(homedir3(), ".corp"),
|
|
3122
3238
|
onEntityFormed: (entityId) => {
|
|
3123
3239
|
try {
|
|
3124
3240
|
updateConfig((cfg) => {
|
|
@@ -6127,6 +6243,171 @@ var init_work_items = __esm({
|
|
|
6127
6243
|
}
|
|
6128
6244
|
});
|
|
6129
6245
|
|
|
6246
|
+
// src/commands/services.ts
|
|
6247
|
+
var services_exports = {};
|
|
6248
|
+
__export(services_exports, {
|
|
6249
|
+
servicesBuyCommand: () => servicesBuyCommand,
|
|
6250
|
+
servicesCancelCommand: () => servicesCancelCommand,
|
|
6251
|
+
servicesCatalogCommand: () => servicesCatalogCommand,
|
|
6252
|
+
servicesFulfillCommand: () => servicesFulfillCommand,
|
|
6253
|
+
servicesListCommand: () => servicesListCommand,
|
|
6254
|
+
servicesShowCommand: () => servicesShowCommand
|
|
6255
|
+
});
|
|
6256
|
+
import chalk11 from "chalk";
|
|
6257
|
+
async function servicesCatalogCommand(opts) {
|
|
6258
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
6259
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
6260
|
+
try {
|
|
6261
|
+
const items = await client.listServiceCatalog();
|
|
6262
|
+
if (opts.json) {
|
|
6263
|
+
printJson(items);
|
|
6264
|
+
return;
|
|
6265
|
+
}
|
|
6266
|
+
printServiceCatalogTable(items);
|
|
6267
|
+
} catch (err) {
|
|
6268
|
+
printError(`Failed to list service catalog: ${err}`);
|
|
6269
|
+
process.exit(1);
|
|
6270
|
+
}
|
|
6271
|
+
}
|
|
6272
|
+
async function servicesBuyCommand(slug, opts) {
|
|
6273
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
6274
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
6275
|
+
const resolver = new ReferenceResolver(client, cfg);
|
|
6276
|
+
try {
|
|
6277
|
+
const eid = await resolver.resolveEntity(opts.entityId);
|
|
6278
|
+
const payload = { entity_id: eid, service_slug: slug };
|
|
6279
|
+
if (opts.dryRun) {
|
|
6280
|
+
printDryRun("services.create_request", payload);
|
|
6281
|
+
return;
|
|
6282
|
+
}
|
|
6283
|
+
const result = await client.createServiceRequest(payload);
|
|
6284
|
+
await resolver.stabilizeRecord("service_request", result, eid);
|
|
6285
|
+
resolver.rememberFromRecord("service_request", result, eid);
|
|
6286
|
+
const requestId = String(result.request_id ?? result.id ?? "");
|
|
6287
|
+
if (requestId) {
|
|
6288
|
+
const checkout = await client.beginServiceCheckout(requestId, { entity_id: eid });
|
|
6289
|
+
if (opts.json) {
|
|
6290
|
+
printJson(checkout);
|
|
6291
|
+
return;
|
|
6292
|
+
}
|
|
6293
|
+
printSuccess(`Service request created: ${requestId}`);
|
|
6294
|
+
printReferenceSummary("service_request", result, { showReuseHint: true });
|
|
6295
|
+
if (checkout.checkout_url) {
|
|
6296
|
+
console.log(`
|
|
6297
|
+
${chalk11.bold("Checkout URL:")} ${checkout.checkout_url}`);
|
|
6298
|
+
}
|
|
6299
|
+
console.log(chalk11.dim("\n Next steps:"));
|
|
6300
|
+
console.log(chalk11.dim(" Complete payment at the checkout URL above"));
|
|
6301
|
+
console.log(chalk11.dim(" corp services list --entity-id <id>"));
|
|
6302
|
+
} else {
|
|
6303
|
+
printWriteResult(result, "Service request created", {
|
|
6304
|
+
referenceKind: "service_request",
|
|
6305
|
+
showReuseHint: true
|
|
6306
|
+
});
|
|
6307
|
+
}
|
|
6308
|
+
} catch (err) {
|
|
6309
|
+
printError(`Failed to create service request: ${err}`);
|
|
6310
|
+
process.exit(1);
|
|
6311
|
+
}
|
|
6312
|
+
}
|
|
6313
|
+
async function servicesListCommand(opts) {
|
|
6314
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
6315
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
6316
|
+
const resolver = new ReferenceResolver(client, cfg);
|
|
6317
|
+
try {
|
|
6318
|
+
const eid = await resolver.resolveEntity(opts.entityId);
|
|
6319
|
+
const requests = await client.listServiceRequests(eid);
|
|
6320
|
+
const stable = await resolver.stabilizeRecords("service_request", requests, eid);
|
|
6321
|
+
if (opts.json) {
|
|
6322
|
+
printJson(stable);
|
|
6323
|
+
return;
|
|
6324
|
+
}
|
|
6325
|
+
printServiceRequestsTable(stable);
|
|
6326
|
+
} catch (err) {
|
|
6327
|
+
printError(`Failed to list service requests: ${err}`);
|
|
6328
|
+
process.exit(1);
|
|
6329
|
+
}
|
|
6330
|
+
}
|
|
6331
|
+
async function servicesShowCommand(ref_, opts) {
|
|
6332
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
6333
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
6334
|
+
const resolver = new ReferenceResolver(client, cfg);
|
|
6335
|
+
try {
|
|
6336
|
+
const eid = await resolver.resolveEntity(opts.entityId);
|
|
6337
|
+
const requestId = await resolver.resolveServiceRequest(eid, ref_);
|
|
6338
|
+
const result = await client.getServiceRequest(requestId, eid);
|
|
6339
|
+
await resolver.stabilizeRecord("service_request", result, eid);
|
|
6340
|
+
resolver.rememberFromRecord("service_request", result, eid);
|
|
6341
|
+
if (opts.json) {
|
|
6342
|
+
printJson(result);
|
|
6343
|
+
return;
|
|
6344
|
+
}
|
|
6345
|
+
printReferenceSummary("service_request", result);
|
|
6346
|
+
printJson(result);
|
|
6347
|
+
} catch (err) {
|
|
6348
|
+
printError(`Failed to show service request: ${err}`);
|
|
6349
|
+
process.exit(1);
|
|
6350
|
+
}
|
|
6351
|
+
}
|
|
6352
|
+
async function servicesFulfillCommand(ref_, opts) {
|
|
6353
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
6354
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
6355
|
+
const resolver = new ReferenceResolver(client, cfg);
|
|
6356
|
+
try {
|
|
6357
|
+
const eid = await resolver.resolveEntity(opts.entityId);
|
|
6358
|
+
const requestId = await resolver.resolveServiceRequest(eid, ref_);
|
|
6359
|
+
const result = await client.fulfillServiceRequest(requestId, {
|
|
6360
|
+
entity_id: eid,
|
|
6361
|
+
note: opts.note
|
|
6362
|
+
});
|
|
6363
|
+
await resolver.stabilizeRecord("service_request", result, eid);
|
|
6364
|
+
resolver.rememberFromRecord("service_request", result, eid);
|
|
6365
|
+
if (opts.json) {
|
|
6366
|
+
printJson(result);
|
|
6367
|
+
return;
|
|
6368
|
+
}
|
|
6369
|
+
printSuccess(`Service request fulfilled: ${requestId}`);
|
|
6370
|
+
printReferenceSummary("service_request", result, { showReuseHint: true });
|
|
6371
|
+
printJson(result);
|
|
6372
|
+
} catch (err) {
|
|
6373
|
+
printError(`Failed to fulfill service request: ${err}`);
|
|
6374
|
+
process.exit(1);
|
|
6375
|
+
}
|
|
6376
|
+
}
|
|
6377
|
+
async function servicesCancelCommand(ref_, opts) {
|
|
6378
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
6379
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
6380
|
+
const resolver = new ReferenceResolver(client, cfg);
|
|
6381
|
+
try {
|
|
6382
|
+
const eid = await resolver.resolveEntity(opts.entityId);
|
|
6383
|
+
const requestId = await resolver.resolveServiceRequest(eid, ref_);
|
|
6384
|
+
const result = await client.cancelServiceRequest(requestId, {
|
|
6385
|
+
entity_id: eid
|
|
6386
|
+
});
|
|
6387
|
+
await resolver.stabilizeRecord("service_request", result, eid);
|
|
6388
|
+
resolver.rememberFromRecord("service_request", result, eid);
|
|
6389
|
+
if (opts.json) {
|
|
6390
|
+
printJson(result);
|
|
6391
|
+
return;
|
|
6392
|
+
}
|
|
6393
|
+
printSuccess(`Service request cancelled: ${requestId}`);
|
|
6394
|
+
printReferenceSummary("service_request", result, { showReuseHint: true });
|
|
6395
|
+
printJson(result);
|
|
6396
|
+
} catch (err) {
|
|
6397
|
+
printError(`Failed to cancel service request: ${err}`);
|
|
6398
|
+
process.exit(1);
|
|
6399
|
+
}
|
|
6400
|
+
}
|
|
6401
|
+
var init_services = __esm({
|
|
6402
|
+
"src/commands/services.ts"() {
|
|
6403
|
+
"use strict";
|
|
6404
|
+
init_config();
|
|
6405
|
+
init_api_client();
|
|
6406
|
+
init_output();
|
|
6407
|
+
init_references();
|
|
6408
|
+
}
|
|
6409
|
+
});
|
|
6410
|
+
|
|
6130
6411
|
// src/commands/billing.ts
|
|
6131
6412
|
var billing_exports = {};
|
|
6132
6413
|
__export(billing_exports, {
|
|
@@ -6237,8 +6518,8 @@ __export(form_exports, {
|
|
|
6237
6518
|
formCreateCommand: () => formCreateCommand,
|
|
6238
6519
|
formFinalizeCommand: () => formFinalizeCommand
|
|
6239
6520
|
});
|
|
6240
|
-
import { input as input2, select, confirm as confirm2, number } from "@inquirer/prompts";
|
|
6241
|
-
import
|
|
6521
|
+
import { input as input2, select as select2, confirm as confirm2, number } from "@inquirer/prompts";
|
|
6522
|
+
import chalk12 from "chalk";
|
|
6242
6523
|
import Table3 from "cli-table3";
|
|
6243
6524
|
import { readFileSync as readFileSync3, realpathSync as realpathSync2 } from "fs";
|
|
6244
6525
|
import { relative as relative2, resolve as resolve2 } from "path";
|
|
@@ -6248,9 +6529,9 @@ function isCorp(entityType) {
|
|
|
6248
6529
|
}
|
|
6249
6530
|
function sectionHeader(title) {
|
|
6250
6531
|
console.log();
|
|
6251
|
-
console.log(
|
|
6252
|
-
console.log(
|
|
6253
|
-
console.log(
|
|
6532
|
+
console.log(chalk12.blue("\u2500".repeat(50)));
|
|
6533
|
+
console.log(chalk12.blue.bold(` ${title}`));
|
|
6534
|
+
console.log(chalk12.blue("\u2500".repeat(50)));
|
|
6254
6535
|
}
|
|
6255
6536
|
function officerTitleLabel(title) {
|
|
6256
6537
|
switch (title) {
|
|
@@ -6410,7 +6691,7 @@ async function phaseEntityDetails(opts, serverCfg, scripted) {
|
|
|
6410
6691
|
if (scripted) {
|
|
6411
6692
|
entityType = "llc";
|
|
6412
6693
|
} else {
|
|
6413
|
-
entityType = await
|
|
6694
|
+
entityType = await select2({
|
|
6414
6695
|
message: "Entity type",
|
|
6415
6696
|
choices: [
|
|
6416
6697
|
{ value: "llc", name: "LLC" },
|
|
@@ -6469,13 +6750,13 @@ async function phasePeople(opts, entityType, scripted) {
|
|
|
6469
6750
|
}
|
|
6470
6751
|
const founderCount = await number({ message: "Number of founders (1-6)", default: 1 }) ?? 1;
|
|
6471
6752
|
for (let i = 0; i < founderCount; i++) {
|
|
6472
|
-
console.log(
|
|
6753
|
+
console.log(chalk12.dim(`
|
|
6473
6754
|
Founder ${i + 1} of ${founderCount}:`));
|
|
6474
6755
|
const name = await input2({ message: ` Name` });
|
|
6475
6756
|
const email = await input2({ message: ` Email` });
|
|
6476
6757
|
let role = "member";
|
|
6477
6758
|
if (isCorp(entityType)) {
|
|
6478
|
-
role = await
|
|
6759
|
+
role = await select2({
|
|
6479
6760
|
message: " Role",
|
|
6480
6761
|
choices: [
|
|
6481
6762
|
{ value: "director", name: "Director" },
|
|
@@ -6490,7 +6771,7 @@ async function phasePeople(opts, entityType, scripted) {
|
|
|
6490
6771
|
if (isCorp(entityType)) {
|
|
6491
6772
|
const wantOfficer = role === "officer" || await confirm2({ message: " Assign officer title?", default: i === 0 });
|
|
6492
6773
|
if (wantOfficer) {
|
|
6493
|
-
officerTitle = await
|
|
6774
|
+
officerTitle = await select2({
|
|
6494
6775
|
message: " Officer title",
|
|
6495
6776
|
choices: OfficerTitle.map((t) => ({
|
|
6496
6777
|
value: t,
|
|
@@ -6515,7 +6796,7 @@ async function phaseStock(opts, entityType, founders, scripted) {
|
|
|
6515
6796
|
const rofr = opts.rofr ?? (!scripted && isCorp(entityType) ? await confirm2({ message: "Right of first refusal?", default: true }) : isCorp(entityType));
|
|
6516
6797
|
if (!scripted) {
|
|
6517
6798
|
for (const f of founders) {
|
|
6518
|
-
console.log(
|
|
6799
|
+
console.log(chalk12.dim(`
|
|
6519
6800
|
Equity for ${f.name}:`));
|
|
6520
6801
|
if (isCorp(entityType)) {
|
|
6521
6802
|
const shares = await number({ message: ` Shares to purchase`, default: 0 });
|
|
@@ -6536,7 +6817,7 @@ async function phaseStock(opts, entityType, founders, scripted) {
|
|
|
6536
6817
|
if (wantVesting) {
|
|
6537
6818
|
const totalMonths = await number({ message: " Total vesting months", default: 48 }) ?? 48;
|
|
6538
6819
|
const cliffMonths = await number({ message: " Cliff months", default: 12 }) ?? 12;
|
|
6539
|
-
const acceleration = await
|
|
6820
|
+
const acceleration = await select2({
|
|
6540
6821
|
message: " Acceleration",
|
|
6541
6822
|
choices: [
|
|
6542
6823
|
{ value: "none", name: "None" },
|
|
@@ -6561,17 +6842,17 @@ async function phaseStock(opts, entityType, founders, scripted) {
|
|
|
6561
6842
|
}
|
|
6562
6843
|
function printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr) {
|
|
6563
6844
|
sectionHeader("Formation Summary");
|
|
6564
|
-
console.log(` ${
|
|
6565
|
-
console.log(` ${
|
|
6566
|
-
console.log(` ${
|
|
6567
|
-
console.log(` ${
|
|
6845
|
+
console.log(` ${chalk12.bold("Entity:")} ${name}`);
|
|
6846
|
+
console.log(` ${chalk12.bold("Type:")} ${entityType}`);
|
|
6847
|
+
console.log(` ${chalk12.bold("Jurisdiction:")} ${jurisdiction}`);
|
|
6848
|
+
console.log(` ${chalk12.bold("Fiscal Year End:")} ${fiscalYearEnd}`);
|
|
6568
6849
|
if (isCorp(entityType)) {
|
|
6569
|
-
console.log(` ${
|
|
6570
|
-
console.log(` ${
|
|
6571
|
-
console.log(` ${
|
|
6850
|
+
console.log(` ${chalk12.bold("S-Corp Election:")} ${sCorpElection ? "Yes" : "No"}`);
|
|
6851
|
+
console.log(` ${chalk12.bold("Transfer Restrictions:")} ${transferRestrictions ? "Yes" : "No"}`);
|
|
6852
|
+
console.log(` ${chalk12.bold("Right of First Refusal:")} ${rofr ? "Yes" : "No"}`);
|
|
6572
6853
|
}
|
|
6573
6854
|
const table = new Table3({
|
|
6574
|
-
head: [
|
|
6855
|
+
head: [chalk12.dim("Name"), chalk12.dim("Email"), chalk12.dim("Role"), chalk12.dim("Equity"), chalk12.dim("Officer")]
|
|
6575
6856
|
});
|
|
6576
6857
|
for (const f of founders) {
|
|
6577
6858
|
const equity = f.shares_purchased ? `${f.shares_purchased.toLocaleString()} shares` : f.ownership_pct ? `${f.ownership_pct}%` : "\u2014";
|
|
@@ -6598,7 +6879,7 @@ async function formCommand(opts) {
|
|
|
6598
6879
|
printSummary(entityType, name, jurisdiction, fiscalYearEnd, sCorpElection, founders, transferRestrictions, rofr);
|
|
6599
6880
|
const shouldProceed = scripted ? true : await confirm2({ message: "Proceed with formation?", default: true });
|
|
6600
6881
|
if (!shouldProceed) {
|
|
6601
|
-
console.log(
|
|
6882
|
+
console.log(chalk12.yellow("Formation cancelled."));
|
|
6602
6883
|
return;
|
|
6603
6884
|
}
|
|
6604
6885
|
const members = founders.map((f) => {
|
|
@@ -6654,17 +6935,17 @@ async function formCommand(opts) {
|
|
|
6654
6935
|
if (holders.length > 0) {
|
|
6655
6936
|
console.log();
|
|
6656
6937
|
const table = new Table3({
|
|
6657
|
-
head: [
|
|
6938
|
+
head: [chalk12.dim("Holder"), chalk12.dim("Shares"), chalk12.dim("Ownership %")]
|
|
6658
6939
|
});
|
|
6659
6940
|
for (const h of holders) {
|
|
6660
6941
|
const pct = typeof h.ownership_pct === "number" ? `${h.ownership_pct.toFixed(1)}%` : "\u2014";
|
|
6661
6942
|
table.push([String(h.name ?? "?"), String(h.shares ?? 0), pct]);
|
|
6662
6943
|
}
|
|
6663
|
-
console.log(
|
|
6944
|
+
console.log(chalk12.bold(" Cap Table:"));
|
|
6664
6945
|
console.log(table.toString());
|
|
6665
6946
|
}
|
|
6666
6947
|
if (result.next_action) {
|
|
6667
|
-
console.log(
|
|
6948
|
+
console.log(chalk12.yellow(`
|
|
6668
6949
|
Next: ${result.next_action}`));
|
|
6669
6950
|
}
|
|
6670
6951
|
} catch (err) {
|
|
@@ -6735,7 +7016,7 @@ async function formCreateCommand(opts) {
|
|
|
6735
7016
|
console.log(` Type: ${result.entity_type}`);
|
|
6736
7017
|
console.log(` Jurisdiction: ${result.jurisdiction}`);
|
|
6737
7018
|
console.log(` Status: ${result.formation_status}`);
|
|
6738
|
-
console.log(
|
|
7019
|
+
console.log(chalk12.yellow(`
|
|
6739
7020
|
Next: corp form add-founder @last:entity --name "..." --email "..." --role member --pct 50`));
|
|
6740
7021
|
} catch (err) {
|
|
6741
7022
|
printError(`Failed to create pending entity: ${err}`);
|
|
@@ -6773,7 +7054,7 @@ async function formAddFounderCommand(entityId, opts) {
|
|
|
6773
7054
|
const pct = typeof m.ownership_pct === "number" ? ` (${m.ownership_pct}%)` : "";
|
|
6774
7055
|
console.log(` - ${m.name} <${m.email ?? "no email"}> [${m.role ?? "member"}]${pct}`);
|
|
6775
7056
|
}
|
|
6776
|
-
console.log(
|
|
7057
|
+
console.log(chalk12.yellow(`
|
|
6777
7058
|
Next: add more founders or run: corp form finalize @last:entity`));
|
|
6778
7059
|
} catch (err) {
|
|
6779
7060
|
printError(`Failed to add founder: ${err}`);
|
|
@@ -6837,17 +7118,17 @@ async function formFinalizeCommand(entityId, opts) {
|
|
|
6837
7118
|
if (holders.length > 0) {
|
|
6838
7119
|
console.log();
|
|
6839
7120
|
const table = new Table3({
|
|
6840
|
-
head: [
|
|
7121
|
+
head: [chalk12.dim("Holder"), chalk12.dim("Shares"), chalk12.dim("Ownership %")]
|
|
6841
7122
|
});
|
|
6842
7123
|
for (const h of holders) {
|
|
6843
7124
|
const pct = typeof h.ownership_pct === "number" ? `${h.ownership_pct.toFixed(1)}%` : "\u2014";
|
|
6844
7125
|
table.push([String(h.name ?? "?"), String(h.shares ?? 0), pct]);
|
|
6845
7126
|
}
|
|
6846
|
-
console.log(
|
|
7127
|
+
console.log(chalk12.bold(" Cap Table:"));
|
|
6847
7128
|
console.log(table.toString());
|
|
6848
7129
|
}
|
|
6849
7130
|
if (result.next_action) {
|
|
6850
|
-
console.log(
|
|
7131
|
+
console.log(chalk12.yellow(`
|
|
6851
7132
|
Next: ${result.next_action}`));
|
|
6852
7133
|
}
|
|
6853
7134
|
} catch (err) {
|
|
@@ -6920,7 +7201,7 @@ var api_keys_exports = {};
|
|
|
6920
7201
|
__export(api_keys_exports, {
|
|
6921
7202
|
apiKeysCommand: () => apiKeysCommand
|
|
6922
7203
|
});
|
|
6923
|
-
import
|
|
7204
|
+
import chalk13 from "chalk";
|
|
6924
7205
|
import Table4 from "cli-table3";
|
|
6925
7206
|
async function apiKeysCommand(opts) {
|
|
6926
7207
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
@@ -6940,9 +7221,9 @@ async function apiKeysCommand(opts) {
|
|
|
6940
7221
|
return;
|
|
6941
7222
|
}
|
|
6942
7223
|
console.log(`
|
|
6943
|
-
${
|
|
7224
|
+
${chalk13.bold("API Keys")}`);
|
|
6944
7225
|
const table = new Table4({
|
|
6945
|
-
head: [
|
|
7226
|
+
head: [chalk13.dim("ID"), chalk13.dim("Name"), chalk13.dim("Key"), chalk13.dim("Created")]
|
|
6946
7227
|
});
|
|
6947
7228
|
for (const k of keys) {
|
|
6948
7229
|
table.push([
|
|
@@ -7224,7 +7505,7 @@ var feedback_exports = {};
|
|
|
7224
7505
|
__export(feedback_exports, {
|
|
7225
7506
|
feedbackCommand: () => feedbackCommand
|
|
7226
7507
|
});
|
|
7227
|
-
import
|
|
7508
|
+
import chalk14 from "chalk";
|
|
7228
7509
|
async function feedbackCommand(message, opts) {
|
|
7229
7510
|
if (!message || message.trim().length === 0) {
|
|
7230
7511
|
printError("Feedback message cannot be empty");
|
|
@@ -7243,7 +7524,7 @@ async function feedbackCommand(message, opts) {
|
|
|
7243
7524
|
return;
|
|
7244
7525
|
}
|
|
7245
7526
|
console.log(`
|
|
7246
|
-
${
|
|
7527
|
+
${chalk14.green("\u2713")} Feedback submitted (${chalk14.dim(result.feedback_id)})`);
|
|
7247
7528
|
} catch (err) {
|
|
7248
7529
|
const detail = String(err);
|
|
7249
7530
|
if (detail.includes("404")) {
|
|
@@ -7273,38 +7554,8 @@ var serve_exports = {};
|
|
|
7273
7554
|
__export(serve_exports, {
|
|
7274
7555
|
serveCommand: () => serveCommand
|
|
7275
7556
|
});
|
|
7276
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
|
|
7277
7557
|
import { resolve as resolve3 } from "path";
|
|
7278
|
-
import {
|
|
7279
|
-
function generateFernetKey() {
|
|
7280
|
-
return randomBytes(32).toString("base64url") + "=";
|
|
7281
|
-
}
|
|
7282
|
-
function generateSecret(length = 32) {
|
|
7283
|
-
return randomBytes(length).toString("hex");
|
|
7284
|
-
}
|
|
7285
|
-
function loadEnvFile(path) {
|
|
7286
|
-
if (!existsSync2(path)) return;
|
|
7287
|
-
const content = readFileSync4(path, "utf-8");
|
|
7288
|
-
for (const line of content.split("\n")) {
|
|
7289
|
-
const trimmed = line.trim();
|
|
7290
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
7291
|
-
const eqIdx = trimmed.indexOf("=");
|
|
7292
|
-
if (eqIdx === -1) continue;
|
|
7293
|
-
const key = trimmed.slice(0, eqIdx).trim();
|
|
7294
|
-
const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
|
|
7295
|
-
if (!process.env[key]) {
|
|
7296
|
-
process.env[key] = value;
|
|
7297
|
-
}
|
|
7298
|
-
}
|
|
7299
|
-
}
|
|
7300
|
-
function ensureEnvFile(envPath) {
|
|
7301
|
-
if (existsSync2(envPath)) return;
|
|
7302
|
-
console.log("No .env file found. Generating one with dev defaults...\n");
|
|
7303
|
-
const content = ENV_TEMPLATE.replace("{{JWT_SECRET}}", generateSecret()).replace("{{SECRETS_MASTER_KEY}}", generateFernetKey()).replace("{{INTERNAL_WORKER_TOKEN}}", generateSecret());
|
|
7304
|
-
writeFileSync2(envPath, content, "utf-8");
|
|
7305
|
-
console.log(` Created ${envPath}
|
|
7306
|
-
`);
|
|
7307
|
-
}
|
|
7558
|
+
import { ensureEnvFile, loadEnvFile } from "@thecorporation/corp-tools";
|
|
7308
7559
|
async function serveCommand(opts) {
|
|
7309
7560
|
let server;
|
|
7310
7561
|
try {
|
|
@@ -7349,40 +7600,9 @@ async function serveCommand(opts) {
|
|
|
7349
7600
|
process.exit(code ?? 0);
|
|
7350
7601
|
});
|
|
7351
7602
|
}
|
|
7352
|
-
var ENV_TEMPLATE;
|
|
7353
7603
|
var init_serve = __esm({
|
|
7354
7604
|
"src/commands/serve.ts"() {
|
|
7355
7605
|
"use strict";
|
|
7356
|
-
ENV_TEMPLATE = `# Corporation API server configuration
|
|
7357
|
-
# Generated by: corp serve
|
|
7358
|
-
|
|
7359
|
-
# Required \u2014 secret for signing JWTs
|
|
7360
|
-
JWT_SECRET={{JWT_SECRET}}
|
|
7361
|
-
|
|
7362
|
-
# Required \u2014 Fernet key for encrypting secrets at rest (base64url, 32 bytes)
|
|
7363
|
-
SECRETS_MASTER_KEY={{SECRETS_MASTER_KEY}}
|
|
7364
|
-
|
|
7365
|
-
# Required \u2014 bearer token for internal worker-to-server auth
|
|
7366
|
-
INTERNAL_WORKER_TOKEN={{INTERNAL_WORKER_TOKEN}}
|
|
7367
|
-
|
|
7368
|
-
# Server port (default: 8000)
|
|
7369
|
-
# PORT=8000
|
|
7370
|
-
|
|
7371
|
-
# Data directory for git repos (default: ./data/repos)
|
|
7372
|
-
# DATA_DIR=./data/repos
|
|
7373
|
-
|
|
7374
|
-
# Redis URL for agent job queue (optional)
|
|
7375
|
-
# REDIS_URL=redis://localhost:6379/0
|
|
7376
|
-
|
|
7377
|
-
# LLM proxy upstream (default: https://openrouter.ai/api/v1)
|
|
7378
|
-
# LLM_UPSTREAM_URL=https://openrouter.ai/api/v1
|
|
7379
|
-
|
|
7380
|
-
# PEM-encoded Ed25519 key for signing git commits (optional)
|
|
7381
|
-
# COMMIT_SIGNING_KEY=
|
|
7382
|
-
|
|
7383
|
-
# Max agent queue depth (default: 1000)
|
|
7384
|
-
# MAX_QUEUE_DEPTH=1000
|
|
7385
|
-
`;
|
|
7386
7606
|
}
|
|
7387
7607
|
});
|
|
7388
7608
|
|
|
@@ -8140,6 +8360,59 @@ workItemsCmd.command("cancel <item-ref>").option("--json", "Output as JSON").des
|
|
|
8140
8360
|
json: inheritOption(opts.json, parent.json)
|
|
8141
8361
|
});
|
|
8142
8362
|
});
|
|
8363
|
+
var servicesCmd = program.command("services").description("Service catalog and fulfillment").option("--entity-id <ref>", "Entity reference (ID, short ID, @last, or unique name)").option("--json", "Output as JSON");
|
|
8364
|
+
servicesCmd.command("catalog").option("--json", "Output as JSON").description("List the service catalog").action(async (opts, cmd) => {
|
|
8365
|
+
const parent = cmd.parent.opts();
|
|
8366
|
+
const { servicesCatalogCommand: servicesCatalogCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
8367
|
+
await servicesCatalogCommand2({
|
|
8368
|
+
json: inheritOption(opts.json, parent.json)
|
|
8369
|
+
});
|
|
8370
|
+
});
|
|
8371
|
+
servicesCmd.command("buy <slug>").option("--json", "Output as JSON").option("--dry-run", "Show the request without executing").description("Purchase a service from the catalog").action(async (slug, opts, cmd) => {
|
|
8372
|
+
const parent = cmd.parent.opts();
|
|
8373
|
+
const { servicesBuyCommand: servicesBuyCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
8374
|
+
await servicesBuyCommand2(slug, {
|
|
8375
|
+
...opts,
|
|
8376
|
+
entityId: parent.entityId,
|
|
8377
|
+
json: inheritOption(opts.json, parent.json)
|
|
8378
|
+
});
|
|
8379
|
+
});
|
|
8380
|
+
servicesCmd.command("list").option("--json", "Output as JSON").description("List service requests for an entity").action(async (opts, cmd) => {
|
|
8381
|
+
const parent = cmd.parent.opts();
|
|
8382
|
+
const { servicesListCommand: servicesListCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
8383
|
+
await servicesListCommand2({
|
|
8384
|
+
...opts,
|
|
8385
|
+
entityId: parent.entityId,
|
|
8386
|
+
json: inheritOption(opts.json, parent.json)
|
|
8387
|
+
});
|
|
8388
|
+
});
|
|
8389
|
+
servicesCmd.command("show <ref>").option("--json", "Output as JSON").description("Show service request detail").action(async (ref_, opts, cmd) => {
|
|
8390
|
+
const parent = cmd.parent.opts();
|
|
8391
|
+
const { servicesShowCommand: servicesShowCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
8392
|
+
await servicesShowCommand2(ref_, {
|
|
8393
|
+
...opts,
|
|
8394
|
+
entityId: parent.entityId,
|
|
8395
|
+
json: inheritOption(opts.json, parent.json)
|
|
8396
|
+
});
|
|
8397
|
+
});
|
|
8398
|
+
servicesCmd.command("fulfill <ref>").option("--note <note>", "Fulfillment note").option("--json", "Output as JSON").description("Mark a service request as fulfilled (operator)").action(async (ref_, opts, cmd) => {
|
|
8399
|
+
const parent = cmd.parent.opts();
|
|
8400
|
+
const { servicesFulfillCommand: servicesFulfillCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
8401
|
+
await servicesFulfillCommand2(ref_, {
|
|
8402
|
+
...opts,
|
|
8403
|
+
entityId: parent.entityId,
|
|
8404
|
+
json: inheritOption(opts.json, parent.json)
|
|
8405
|
+
});
|
|
8406
|
+
});
|
|
8407
|
+
servicesCmd.command("cancel <ref>").option("--json", "Output as JSON").description("Cancel a service request").action(async (ref_, opts, cmd) => {
|
|
8408
|
+
const parent = cmd.parent.opts();
|
|
8409
|
+
const { servicesCancelCommand: servicesCancelCommand2 } = await Promise.resolve().then(() => (init_services(), services_exports));
|
|
8410
|
+
await servicesCancelCommand2(ref_, {
|
|
8411
|
+
...opts,
|
|
8412
|
+
entityId: parent.entityId,
|
|
8413
|
+
json: inheritOption(opts.json, parent.json)
|
|
8414
|
+
});
|
|
8415
|
+
});
|
|
8143
8416
|
var billingCmd = program.command("billing").description("Billing status, plans, and subscription management").option("--json", "Output as JSON").action(async (opts) => {
|
|
8144
8417
|
const { billingCommand: billingCommand2 } = await Promise.resolve().then(() => (init_billing(), billing_exports));
|
|
8145
8418
|
await billingCommand2(opts);
|