@thecorporation/cli 26.3.17 → 26.3.18
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/dist/index.js +580 -159
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -10,40 +10,239 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/config.ts
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
setValue: () => setValue
|
|
23
|
-
});
|
|
24
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
25
|
-
import { join } from "path";
|
|
13
|
+
import {
|
|
14
|
+
chmodSync,
|
|
15
|
+
existsSync,
|
|
16
|
+
mkdirSync,
|
|
17
|
+
readFileSync,
|
|
18
|
+
renameSync,
|
|
19
|
+
rmSync,
|
|
20
|
+
writeFileSync
|
|
21
|
+
} from "fs";
|
|
26
22
|
import { homedir } from "os";
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
import { join } from "path";
|
|
24
|
+
function sleepSync(ms) {
|
|
25
|
+
Atomics.wait(CONFIG_WAIT_SIGNAL, 0, 0, ms);
|
|
26
|
+
}
|
|
27
|
+
function withConfigLock(fn) {
|
|
28
|
+
mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
29
|
+
const startedAt = Date.now();
|
|
30
|
+
while (true) {
|
|
31
|
+
try {
|
|
32
|
+
mkdirSync(CONFIG_LOCK_DIR, { mode: 448 });
|
|
33
|
+
break;
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (err.code !== "EEXIST") {
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
if (Date.now() - startedAt >= CONFIG_LOCK_TIMEOUT_MS) {
|
|
39
|
+
throw new Error("timed out waiting for the corp config lock");
|
|
40
|
+
}
|
|
41
|
+
sleepSync(CONFIG_LOCK_RETRY_MS);
|
|
33
42
|
}
|
|
34
43
|
}
|
|
44
|
+
try {
|
|
45
|
+
return fn();
|
|
46
|
+
} finally {
|
|
47
|
+
rmSync(CONFIG_LOCK_DIR, { recursive: true, force: true });
|
|
48
|
+
}
|
|
35
49
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
50
|
+
function ensureSecurePermissions() {
|
|
51
|
+
mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
52
|
+
try {
|
|
53
|
+
chmodSync(CONFIG_DIR, 448);
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
38
56
|
if (existsSync(CONFIG_FILE)) {
|
|
39
|
-
|
|
40
|
-
|
|
57
|
+
try {
|
|
58
|
+
chmodSync(CONFIG_FILE, 384);
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function isObject(value) {
|
|
64
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
65
|
+
}
|
|
66
|
+
function isLoopbackHost(hostname) {
|
|
67
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
|
|
68
|
+
}
|
|
69
|
+
function validateApiUrl(value) {
|
|
70
|
+
let parsed;
|
|
71
|
+
try {
|
|
72
|
+
parsed = new URL(value.trim());
|
|
73
|
+
} catch {
|
|
74
|
+
throw new Error("api_url must be a valid absolute URL");
|
|
75
|
+
}
|
|
76
|
+
if (parsed.username || parsed.password) {
|
|
77
|
+
throw new Error("api_url must not include embedded credentials");
|
|
78
|
+
}
|
|
79
|
+
const protocol = parsed.protocol.toLowerCase();
|
|
80
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
81
|
+
if (protocol !== "https:" && !(protocol === "http:" && isLoopbackHost(hostname))) {
|
|
82
|
+
throw new Error("api_url must use https, or http only for localhost/loopback development");
|
|
83
|
+
}
|
|
84
|
+
parsed.hash = "";
|
|
85
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
86
|
+
}
|
|
87
|
+
function normalizeString(value) {
|
|
88
|
+
return typeof value === "string" ? value : void 0;
|
|
89
|
+
}
|
|
90
|
+
function normalizeActiveEntityMap(value) {
|
|
91
|
+
if (!isObject(value)) {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
const entries = Object.entries(value).filter(
|
|
95
|
+
([workspaceId, entityId]) => typeof workspaceId === "string" && typeof entityId === "string" && entityId.length > 0
|
|
96
|
+
);
|
|
97
|
+
if (entries.length === 0) {
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
return Object.fromEntries(entries);
|
|
101
|
+
}
|
|
102
|
+
function normalizeConfig(raw) {
|
|
103
|
+
const cfg = structuredClone(DEFAULTS);
|
|
104
|
+
if (!isObject(raw)) {
|
|
105
|
+
return cfg;
|
|
106
|
+
}
|
|
107
|
+
const savedApiUrl = normalizeString(raw.api_url);
|
|
108
|
+
if (savedApiUrl) {
|
|
109
|
+
try {
|
|
110
|
+
cfg.api_url = validateApiUrl(savedApiUrl);
|
|
111
|
+
} catch {
|
|
112
|
+
cfg.api_url = DEFAULTS.api_url;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
cfg.api_key = normalizeString(raw.api_key) ?? cfg.api_key;
|
|
116
|
+
cfg.workspace_id = normalizeString(raw.workspace_id) ?? cfg.workspace_id;
|
|
117
|
+
cfg.hosting_mode = normalizeString(raw.hosting_mode) ?? cfg.hosting_mode;
|
|
118
|
+
cfg.active_entity_id = normalizeString(raw.active_entity_id) ?? cfg.active_entity_id;
|
|
119
|
+
if (isObject(raw.llm)) {
|
|
120
|
+
cfg.llm.provider = normalizeString(raw.llm.provider) ?? cfg.llm.provider;
|
|
121
|
+
cfg.llm.api_key = normalizeString(raw.llm.api_key) ?? cfg.llm.api_key;
|
|
122
|
+
cfg.llm.model = normalizeString(raw.llm.model) ?? cfg.llm.model;
|
|
123
|
+
const baseUrl = normalizeString(raw.llm.base_url);
|
|
124
|
+
if (baseUrl && baseUrl.trim()) {
|
|
125
|
+
cfg.llm.base_url = baseUrl.trim();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (isObject(raw.user)) {
|
|
129
|
+
cfg.user.name = normalizeString(raw.user.name) ?? cfg.user.name;
|
|
130
|
+
cfg.user.email = normalizeString(raw.user.email) ?? cfg.user.email;
|
|
131
|
+
}
|
|
132
|
+
const activeEntityIds = normalizeActiveEntityMap(raw.active_entity_ids);
|
|
133
|
+
if (activeEntityIds) {
|
|
134
|
+
cfg.active_entity_ids = activeEntityIds;
|
|
135
|
+
}
|
|
136
|
+
if (cfg.workspace_id && cfg.active_entity_id) {
|
|
137
|
+
cfg.active_entity_ids = {
|
|
138
|
+
...cfg.active_entity_ids ?? {},
|
|
139
|
+
[cfg.workspace_id]: cfg.active_entity_id
|
|
140
|
+
};
|
|
41
141
|
}
|
|
42
142
|
return cfg;
|
|
43
143
|
}
|
|
144
|
+
function serializeConfig(cfg) {
|
|
145
|
+
const normalized = normalizeConfig(cfg);
|
|
146
|
+
const serialized = {
|
|
147
|
+
api_url: normalized.api_url,
|
|
148
|
+
api_key: normalized.api_key,
|
|
149
|
+
workspace_id: normalized.workspace_id,
|
|
150
|
+
hosting_mode: normalized.hosting_mode,
|
|
151
|
+
llm: {
|
|
152
|
+
provider: normalized.llm.provider,
|
|
153
|
+
api_key: normalized.llm.api_key,
|
|
154
|
+
model: normalized.llm.model,
|
|
155
|
+
...normalized.llm.base_url ? { base_url: normalized.llm.base_url } : {}
|
|
156
|
+
},
|
|
157
|
+
user: {
|
|
158
|
+
name: normalized.user.name,
|
|
159
|
+
email: normalized.user.email
|
|
160
|
+
},
|
|
161
|
+
active_entity_id: normalized.active_entity_id
|
|
162
|
+
};
|
|
163
|
+
if (normalized.active_entity_ids && Object.keys(normalized.active_entity_ids).length > 0) {
|
|
164
|
+
serialized.active_entity_ids = normalized.active_entity_ids;
|
|
165
|
+
}
|
|
166
|
+
return JSON.stringify(serialized, null, 2) + "\n";
|
|
167
|
+
}
|
|
168
|
+
function requireSupportedConfigKey(dotPath) {
|
|
169
|
+
if (!ALLOWED_CONFIG_KEYS.has(dotPath)) {
|
|
170
|
+
throw new Error(`unsupported config key: ${dotPath}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function validateSensitiveConfigUpdate(dotPath, forceSensitive = false) {
|
|
174
|
+
if (SENSITIVE_CONFIG_KEYS.has(dotPath) && !forceSensitive) {
|
|
175
|
+
throw new Error(`refusing to update security-sensitive key '${dotPath}' without --force`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function setKnownConfigValue(cfg, dotPath, value) {
|
|
179
|
+
switch (dotPath) {
|
|
180
|
+
case "api_url":
|
|
181
|
+
cfg.api_url = validateApiUrl(value);
|
|
182
|
+
return;
|
|
183
|
+
case "api_key":
|
|
184
|
+
cfg.api_key = value.trim();
|
|
185
|
+
return;
|
|
186
|
+
case "workspace_id":
|
|
187
|
+
cfg.workspace_id = value.trim();
|
|
188
|
+
return;
|
|
189
|
+
case "hosting_mode":
|
|
190
|
+
cfg.hosting_mode = value.trim();
|
|
191
|
+
return;
|
|
192
|
+
case "llm.provider":
|
|
193
|
+
cfg.llm.provider = value.trim();
|
|
194
|
+
return;
|
|
195
|
+
case "llm.api_key":
|
|
196
|
+
cfg.llm.api_key = value.trim();
|
|
197
|
+
return;
|
|
198
|
+
case "llm.model":
|
|
199
|
+
cfg.llm.model = value.trim();
|
|
200
|
+
return;
|
|
201
|
+
case "llm.base_url":
|
|
202
|
+
cfg.llm.base_url = value.trim() || void 0;
|
|
203
|
+
return;
|
|
204
|
+
case "user.name":
|
|
205
|
+
cfg.user.name = value.trim();
|
|
206
|
+
return;
|
|
207
|
+
case "user.email":
|
|
208
|
+
cfg.user.email = value.trim();
|
|
209
|
+
return;
|
|
210
|
+
case "active_entity_id":
|
|
211
|
+
setActiveEntityId(cfg, value.trim());
|
|
212
|
+
return;
|
|
213
|
+
default:
|
|
214
|
+
throw new Error(`unsupported config key: ${dotPath}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function readConfigUnlocked() {
|
|
218
|
+
ensureSecurePermissions();
|
|
219
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
220
|
+
return normalizeConfig(DEFAULTS);
|
|
221
|
+
}
|
|
222
|
+
return normalizeConfig(JSON.parse(readFileSync(CONFIG_FILE, "utf-8")));
|
|
223
|
+
}
|
|
224
|
+
function loadConfig() {
|
|
225
|
+
return readConfigUnlocked();
|
|
226
|
+
}
|
|
44
227
|
function saveConfig(cfg) {
|
|
45
|
-
|
|
46
|
-
|
|
228
|
+
withConfigLock(() => {
|
|
229
|
+
ensureSecurePermissions();
|
|
230
|
+
const tempFile = `${CONFIG_FILE}.${process.pid}.tmp`;
|
|
231
|
+
writeFileSync(tempFile, serializeConfig(cfg), { mode: 384 });
|
|
232
|
+
renameSync(tempFile, CONFIG_FILE);
|
|
233
|
+
ensureSecurePermissions();
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function updateConfig(mutator) {
|
|
237
|
+
return withConfigLock(() => {
|
|
238
|
+
const cfg = readConfigUnlocked();
|
|
239
|
+
mutator(cfg);
|
|
240
|
+
const tempFile = `${CONFIG_FILE}.${process.pid}.tmp`;
|
|
241
|
+
writeFileSync(tempFile, serializeConfig(cfg), { mode: 384 });
|
|
242
|
+
renameSync(tempFile, CONFIG_FILE);
|
|
243
|
+
ensureSecurePermissions();
|
|
244
|
+
return cfg;
|
|
245
|
+
});
|
|
47
246
|
}
|
|
48
247
|
function getValue(cfg, dotPath) {
|
|
49
248
|
const keys = dotPath.split(".");
|
|
@@ -57,16 +256,10 @@ function getValue(cfg, dotPath) {
|
|
|
57
256
|
}
|
|
58
257
|
return current;
|
|
59
258
|
}
|
|
60
|
-
function setValue(cfg, dotPath, value) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (!(key in current) || typeof current[key] !== "object" || current[key] === null) {
|
|
65
|
-
current[key] = {};
|
|
66
|
-
}
|
|
67
|
-
current = current[key];
|
|
68
|
-
}
|
|
69
|
-
current[keys[keys.length - 1]] = value;
|
|
259
|
+
function setValue(cfg, dotPath, value, options = {}) {
|
|
260
|
+
requireSupportedConfigKey(dotPath);
|
|
261
|
+
validateSensitiveConfigUpdate(dotPath, options.forceSensitive);
|
|
262
|
+
setKnownConfigValue(cfg, dotPath, value);
|
|
70
263
|
}
|
|
71
264
|
function requireConfig(...fields) {
|
|
72
265
|
const cfg = loadConfig();
|
|
@@ -92,8 +285,24 @@ function configForDisplay(cfg) {
|
|
|
92
285
|
}
|
|
93
286
|
return display;
|
|
94
287
|
}
|
|
288
|
+
function getActiveEntityId(cfg) {
|
|
289
|
+
if (cfg.workspace_id && cfg.active_entity_ids?.[cfg.workspace_id]) {
|
|
290
|
+
return cfg.active_entity_ids[cfg.workspace_id];
|
|
291
|
+
}
|
|
292
|
+
return cfg.active_entity_id;
|
|
293
|
+
}
|
|
294
|
+
function setActiveEntityId(cfg, entityId) {
|
|
295
|
+
cfg.active_entity_id = entityId;
|
|
296
|
+
if (!cfg.workspace_id) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
cfg.active_entity_ids = {
|
|
300
|
+
...cfg.active_entity_ids ?? {},
|
|
301
|
+
[cfg.workspace_id]: entityId
|
|
302
|
+
};
|
|
303
|
+
}
|
|
95
304
|
function resolveEntityId(cfg, explicitId) {
|
|
96
|
-
const eid = explicitId || cfg
|
|
305
|
+
const eid = explicitId || getActiveEntityId(cfg);
|
|
97
306
|
if (!eid) {
|
|
98
307
|
console.error(
|
|
99
308
|
"No entity specified. Use --entity-id or set active_entity_id via 'corp config set active_entity_id <id>'."
|
|
@@ -102,21 +311,41 @@ function resolveEntityId(cfg, explicitId) {
|
|
|
102
311
|
}
|
|
103
312
|
return eid;
|
|
104
313
|
}
|
|
105
|
-
var CONFIG_DIR, CONFIG_FILE, DEFAULTS;
|
|
314
|
+
var CONFIG_DIR, CONFIG_FILE, CONFIG_LOCK_DIR, CONFIG_LOCK_TIMEOUT_MS, CONFIG_LOCK_RETRY_MS, CONFIG_WAIT_BUFFER, CONFIG_WAIT_SIGNAL, ALLOWED_CONFIG_KEYS, SENSITIVE_CONFIG_KEYS, DEFAULTS;
|
|
106
315
|
var init_config = __esm({
|
|
107
316
|
"src/config.ts"() {
|
|
108
317
|
"use strict";
|
|
109
318
|
CONFIG_DIR = process.env.CORP_CONFIG_DIR || join(homedir(), ".corp");
|
|
110
319
|
CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
320
|
+
CONFIG_LOCK_DIR = join(CONFIG_DIR, "config.lock");
|
|
321
|
+
CONFIG_LOCK_TIMEOUT_MS = 5e3;
|
|
322
|
+
CONFIG_LOCK_RETRY_MS = 25;
|
|
323
|
+
CONFIG_WAIT_BUFFER = new SharedArrayBuffer(4);
|
|
324
|
+
CONFIG_WAIT_SIGNAL = new Int32Array(CONFIG_WAIT_BUFFER);
|
|
325
|
+
ALLOWED_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
326
|
+
"api_url",
|
|
327
|
+
"api_key",
|
|
328
|
+
"workspace_id",
|
|
329
|
+
"hosting_mode",
|
|
330
|
+
"llm.provider",
|
|
331
|
+
"llm.api_key",
|
|
332
|
+
"llm.model",
|
|
333
|
+
"llm.base_url",
|
|
334
|
+
"user.name",
|
|
335
|
+
"user.email",
|
|
336
|
+
"active_entity_id"
|
|
337
|
+
]);
|
|
338
|
+
SENSITIVE_CONFIG_KEYS = /* @__PURE__ */ new Set(["api_url", "api_key", "workspace_id"]);
|
|
111
339
|
DEFAULTS = {
|
|
112
340
|
api_url: process.env.CORP_API_URL || "https://api.thecorporation.ai",
|
|
113
|
-
api_key: "",
|
|
114
|
-
workspace_id: "",
|
|
341
|
+
api_key: process.env.CORP_API_KEY || "",
|
|
342
|
+
workspace_id: process.env.CORP_WORKSPACE_ID || "",
|
|
115
343
|
hosting_mode: "",
|
|
116
344
|
llm: {
|
|
117
345
|
provider: "anthropic",
|
|
118
|
-
api_key: "",
|
|
119
|
-
model: "claude-sonnet-4-6"
|
|
346
|
+
api_key: process.env.CORP_LLM_API_KEY || "",
|
|
347
|
+
model: "claude-sonnet-4-6",
|
|
348
|
+
base_url: process.env.CORP_LLM_BASE_URL || void 0
|
|
120
349
|
},
|
|
121
350
|
user: { name: "", email: "" },
|
|
122
351
|
active_entity_id: ""
|
|
@@ -341,12 +570,12 @@ function printSafesTable(safes) {
|
|
|
341
570
|
const table = makeTable("SAFE Notes", ["ID", "Investor", "Amount", "Cap", "Discount", "Date"]);
|
|
342
571
|
for (const s_ of safes) {
|
|
343
572
|
table.push([
|
|
344
|
-
s(s_.safe_id ?? s_.id, 12),
|
|
573
|
+
s(s_.safe_note_id ?? s_.safe_id ?? s_.id, 12),
|
|
345
574
|
s(s_.investor_name ?? s_.investor),
|
|
346
|
-
money(s_.investment_amount ?? s_.amount, false),
|
|
347
|
-
|
|
575
|
+
money(s_.principal_amount_cents ?? s_.investment_amount ?? s_.amount, false),
|
|
576
|
+
money(s_.valuation_cap_cents ?? s_.valuation_cap ?? s_.cap, false),
|
|
348
577
|
s(s_.discount_rate ?? s_.discount),
|
|
349
|
-
s(s_.date ?? s_.created_at)
|
|
578
|
+
s(s_.issued_at ?? s_.date ?? s_.created_at)
|
|
350
579
|
]);
|
|
351
580
|
}
|
|
352
581
|
console.log(table.toString());
|
|
@@ -873,12 +1102,16 @@ var status_exports = {};
|
|
|
873
1102
|
__export(status_exports, {
|
|
874
1103
|
statusCommand: () => statusCommand
|
|
875
1104
|
});
|
|
876
|
-
async function statusCommand() {
|
|
1105
|
+
async function statusCommand(opts = {}) {
|
|
877
1106
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
878
1107
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
879
1108
|
try {
|
|
880
1109
|
const data = await withSpinner("Loading", () => client.getStatus());
|
|
881
|
-
|
|
1110
|
+
if (opts.json) {
|
|
1111
|
+
printJson(data);
|
|
1112
|
+
} else {
|
|
1113
|
+
printStatusPanel(data);
|
|
1114
|
+
}
|
|
882
1115
|
} catch (err) {
|
|
883
1116
|
printError(`Failed to fetch status: ${err}`);
|
|
884
1117
|
process.exit(1);
|
|
@@ -909,7 +1142,8 @@ async function contextCommand(opts) {
|
|
|
909
1142
|
client.getStatus(),
|
|
910
1143
|
client.listEntities()
|
|
911
1144
|
]);
|
|
912
|
-
const
|
|
1145
|
+
const activeEntityId = getActiveEntityId(rawCfg);
|
|
1146
|
+
const activeEntity = activeEntityId ? entities.find((entity) => entity.entity_id === activeEntityId) ?? null : null;
|
|
913
1147
|
const [contactsResult, documentsResult, workItemsResult] = activeEntity ? await Promise.allSettled([
|
|
914
1148
|
client.listContacts(String(activeEntity.entity_id)),
|
|
915
1149
|
client.getEntityDocuments(String(activeEntity.entity_id)),
|
|
@@ -1034,17 +1268,28 @@ var init_schema = __esm({
|
|
|
1034
1268
|
});
|
|
1035
1269
|
|
|
1036
1270
|
// src/commands/config.ts
|
|
1037
|
-
var
|
|
1038
|
-
__export(
|
|
1271
|
+
var config_exports = {};
|
|
1272
|
+
__export(config_exports, {
|
|
1039
1273
|
configGetCommand: () => configGetCommand,
|
|
1040
1274
|
configListCommand: () => configListCommand,
|
|
1041
1275
|
configSetCommand: () => configSetCommand
|
|
1042
1276
|
});
|
|
1043
|
-
function configSetCommand(key, value) {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1277
|
+
function configSetCommand(key, value, options = {}) {
|
|
1278
|
+
try {
|
|
1279
|
+
updateConfig((cfg) => {
|
|
1280
|
+
setValue(cfg, key, value, {
|
|
1281
|
+
forceSensitive: options.force
|
|
1282
|
+
});
|
|
1283
|
+
});
|
|
1284
|
+
} catch (err) {
|
|
1285
|
+
printError(`Failed to update config: ${err}`);
|
|
1286
|
+
process.exit(1);
|
|
1287
|
+
}
|
|
1288
|
+
if (key === "api_key" || key === "llm.api_key") {
|
|
1289
|
+
console.log(`${key} updated.`);
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
console.log(`${key} updated.`);
|
|
1048
1293
|
}
|
|
1049
1294
|
function configGetCommand(key) {
|
|
1050
1295
|
const cfg = loadConfig();
|
|
@@ -1114,8 +1359,10 @@ async function digestCommand(opts) {
|
|
|
1114
1359
|
const value = result.message;
|
|
1115
1360
|
return typeof value === "string" && value.trim() ? value : null;
|
|
1116
1361
|
})();
|
|
1117
|
-
|
|
1118
|
-
|
|
1362
|
+
if (!opts.json) {
|
|
1363
|
+
printSuccess(result.digest_count > 0 ? "Digest triggered." : "Digest trigger accepted.");
|
|
1364
|
+
}
|
|
1365
|
+
if (message && !opts.json) {
|
|
1119
1366
|
printWarning(message);
|
|
1120
1367
|
}
|
|
1121
1368
|
printJson(result);
|
|
@@ -1357,9 +1604,9 @@ async function executeTool(name, args, client) {
|
|
|
1357
1604
|
dataDir: join2(homedir2(), ".corp"),
|
|
1358
1605
|
onEntityFormed: (entityId) => {
|
|
1359
1606
|
try {
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1607
|
+
updateConfig((cfg) => {
|
|
1608
|
+
setActiveEntityId(cfg, entityId);
|
|
1609
|
+
});
|
|
1363
1610
|
} catch {
|
|
1364
1611
|
}
|
|
1365
1612
|
}
|
|
@@ -1388,7 +1635,7 @@ async function chatCommand() {
|
|
|
1388
1635
|
const messages = [{ role: "system", content: SYSTEM_PROMPT }];
|
|
1389
1636
|
let totalTokens = 0;
|
|
1390
1637
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1391
|
-
const prompt = () => new Promise((
|
|
1638
|
+
const prompt = () => new Promise((resolve3) => rl.question(chalk3.green.bold("> "), resolve3));
|
|
1392
1639
|
console.log(chalk3.blue.bold("corp chat") + " \u2014 type /help for commands, /quit to exit\n");
|
|
1393
1640
|
const slashHandlers = {
|
|
1394
1641
|
"/status": async () => {
|
|
@@ -1712,6 +1959,7 @@ async function contactsAddCommand(opts) {
|
|
|
1712
1959
|
if (opts.phone) data.phone = opts.phone;
|
|
1713
1960
|
if (opts.notes) data.notes = opts.notes;
|
|
1714
1961
|
if (opts.mailingAddress ?? opts.address) data.mailing_address = opts.mailingAddress ?? opts.address;
|
|
1962
|
+
if (opts.capTableAccess) data.cap_table_access = opts.capTableAccess;
|
|
1715
1963
|
const result = await client.createContact(data);
|
|
1716
1964
|
printWriteResult(
|
|
1717
1965
|
result,
|
|
@@ -1750,6 +1998,10 @@ async function contactsEditCommand(contactId, opts) {
|
|
|
1750
1998
|
data.notes = opts.notes;
|
|
1751
1999
|
hasUpdates = true;
|
|
1752
2000
|
}
|
|
2001
|
+
if (opts.capTableAccess != null) {
|
|
2002
|
+
data.cap_table_access = opts.capTableAccess;
|
|
2003
|
+
hasUpdates = true;
|
|
2004
|
+
}
|
|
1753
2005
|
if (opts.mailingAddress != null || opts.address != null) {
|
|
1754
2006
|
data.mailing_address = opts.mailingAddress ?? opts.address;
|
|
1755
2007
|
hasUpdates = true;
|
|
@@ -1780,6 +2032,7 @@ __export(cap_table_exports, {
|
|
|
1780
2032
|
addSecurityCommand: () => addSecurityCommand,
|
|
1781
2033
|
approveValuationCommand: () => approveValuationCommand,
|
|
1782
2034
|
capTableCommand: () => capTableCommand,
|
|
2035
|
+
createInstrumentCommand: () => createInstrumentCommand,
|
|
1783
2036
|
createValuationCommand: () => createValuationCommand,
|
|
1784
2037
|
distributeCommand: () => distributeCommand,
|
|
1785
2038
|
fourOhNineACommand: () => fourOhNineACommand,
|
|
@@ -1793,10 +2046,9 @@ __export(cap_table_exports, {
|
|
|
1793
2046
|
transfersCommand: () => transfersCommand,
|
|
1794
2047
|
valuationsCommand: () => valuationsCommand
|
|
1795
2048
|
});
|
|
1796
|
-
import { ensureSafeInstrument } from "@thecorporation/corp-tools";
|
|
1797
2049
|
import chalk6 from "chalk";
|
|
1798
2050
|
function normalizedGrantType(grantType) {
|
|
1799
|
-
return grantType.trim().toLowerCase().replaceAll("-", "_");
|
|
2051
|
+
return grantType.trim().toLowerCase().replaceAll("-", "_").replaceAll(" ", "_");
|
|
1800
2052
|
}
|
|
1801
2053
|
function expectedInstrumentKinds(grantType) {
|
|
1802
2054
|
switch (normalizedGrantType(grantType)) {
|
|
@@ -1806,8 +2058,11 @@ function expectedInstrumentKinds(grantType) {
|
|
|
1806
2058
|
case "preferred":
|
|
1807
2059
|
case "preferred_stock":
|
|
1808
2060
|
return ["preferred_equity"];
|
|
2061
|
+
case "unit":
|
|
1809
2062
|
case "membership_unit":
|
|
1810
2063
|
return ["membership_unit"];
|
|
2064
|
+
case "option":
|
|
2065
|
+
case "options":
|
|
1811
2066
|
case "stock_option":
|
|
1812
2067
|
case "iso":
|
|
1813
2068
|
case "nso":
|
|
@@ -1818,6 +2073,31 @@ function expectedInstrumentKinds(grantType) {
|
|
|
1818
2073
|
return [];
|
|
1819
2074
|
}
|
|
1820
2075
|
}
|
|
2076
|
+
function grantRequiresCurrent409a(grantType, instrumentKind) {
|
|
2077
|
+
return instrumentKind?.toLowerCase() === "option_grant" || expectedInstrumentKinds(grantType).includes("option_grant");
|
|
2078
|
+
}
|
|
2079
|
+
function buildInstrumentCreationHint(grantType) {
|
|
2080
|
+
const normalized = normalizedGrantType(grantType);
|
|
2081
|
+
switch (normalized) {
|
|
2082
|
+
case "preferred":
|
|
2083
|
+
case "preferred_stock":
|
|
2084
|
+
return "Create one with: corp cap-table create-instrument --kind preferred_equity --symbol SERIES-A --authorized-units <shares>";
|
|
2085
|
+
case "option":
|
|
2086
|
+
case "options":
|
|
2087
|
+
case "stock_option":
|
|
2088
|
+
case "iso":
|
|
2089
|
+
case "nso":
|
|
2090
|
+
return "Create one with: corp cap-table create-instrument --kind option_grant --symbol OPTION-PLAN --authorized-units <shares>";
|
|
2091
|
+
case "membership_unit":
|
|
2092
|
+
case "unit":
|
|
2093
|
+
return "Create one with: corp cap-table create-instrument --kind membership_unit --symbol UNIT --authorized-units <units>";
|
|
2094
|
+
case "common":
|
|
2095
|
+
case "common_stock":
|
|
2096
|
+
return "Create one with: corp cap-table create-instrument --kind common_equity --symbol COMMON --authorized-units <shares>";
|
|
2097
|
+
default:
|
|
2098
|
+
return "Create a matching instrument first, then pass --instrument-id explicitly.";
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
1821
2101
|
function resolveInstrumentForGrant(instruments, grantType, explicitInstrumentId) {
|
|
1822
2102
|
if (explicitInstrumentId) {
|
|
1823
2103
|
const explicit = instruments.find((instrument) => instrument.instrument_id === explicitInstrumentId);
|
|
@@ -1828,16 +2108,47 @@ function resolveInstrumentForGrant(instruments, grantType, explicitInstrumentId)
|
|
|
1828
2108
|
}
|
|
1829
2109
|
const expectedKinds = expectedInstrumentKinds(grantType);
|
|
1830
2110
|
if (expectedKinds.length === 0) {
|
|
1831
|
-
throw new Error(
|
|
2111
|
+
throw new Error(
|
|
2112
|
+
`No default instrument mapping exists for grant type "${grantType}". ${buildInstrumentCreationHint(grantType)}`
|
|
2113
|
+
);
|
|
1832
2114
|
}
|
|
1833
2115
|
const match = instruments.find((instrument) => expectedKinds.includes(String(instrument.kind).toLowerCase()));
|
|
1834
2116
|
if (!match) {
|
|
1835
2117
|
throw new Error(
|
|
1836
|
-
`No instrument found for grant type "${grantType}". Expected one of: ${expectedKinds.join(", ")}
|
|
2118
|
+
`No instrument found for grant type "${grantType}". Expected one of: ${expectedKinds.join(", ")}. ${buildInstrumentCreationHint(grantType)}`
|
|
1837
2119
|
);
|
|
1838
2120
|
}
|
|
1839
2121
|
return match;
|
|
1840
2122
|
}
|
|
2123
|
+
async function entityHasActiveBoard(client, entityId) {
|
|
2124
|
+
const bodies = await client.listGovernanceBodies(entityId);
|
|
2125
|
+
return bodies.some(
|
|
2126
|
+
(body) => String(body.body_type ?? "").toLowerCase() === "board_of_directors" && String(body.status ?? "active").toLowerCase() === "active"
|
|
2127
|
+
);
|
|
2128
|
+
}
|
|
2129
|
+
async function ensureIssuancePreflight(client, entityId, grantType, instrument, meetingId, resolutionId) {
|
|
2130
|
+
if (!meetingId || !resolutionId) {
|
|
2131
|
+
if (await entityHasActiveBoard(client, entityId)) {
|
|
2132
|
+
throw new Error(
|
|
2133
|
+
"Board approval is required before issuing this round. Pass --meeting-id and --resolution-id from a passed board vote."
|
|
2134
|
+
);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
if (!grantRequiresCurrent409a(grantType, instrument?.kind)) {
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
try {
|
|
2141
|
+
await client.getCurrent409a(entityId);
|
|
2142
|
+
} catch (err) {
|
|
2143
|
+
const msg = String(err);
|
|
2144
|
+
if (msg.includes("404")) {
|
|
2145
|
+
throw new Error(
|
|
2146
|
+
"Stock option issuances require a current approved 409A valuation. Create and approve one first with: corp cap-table create-valuation --type four_oh_nine_a --date YYYY-MM-DD --methodology <method>; corp cap-table submit-valuation <id>; corp cap-table approve-valuation <id> --resolution-id <resolution-id>"
|
|
2147
|
+
);
|
|
2148
|
+
}
|
|
2149
|
+
throw err;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
1841
2152
|
async function capTableCommand(opts) {
|
|
1842
2153
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
1843
2154
|
const eid = resolveEntityId(cfg, opts.entityId);
|
|
@@ -1950,7 +2261,7 @@ async function issueEquityCommand(opts) {
|
|
|
1950
2261
|
}
|
|
1951
2262
|
const instruments = capTable.instruments ?? [];
|
|
1952
2263
|
if (!instruments.length) {
|
|
1953
|
-
printError("No instruments found on cap table. Create
|
|
2264
|
+
printError("No instruments found on cap table. Create one with: corp cap-table create-instrument --kind common_equity --symbol COMMON --authorized-units <shares>");
|
|
1954
2265
|
process.exit(1);
|
|
1955
2266
|
}
|
|
1956
2267
|
const instrument = resolveInstrumentForGrant(instruments, opts.grantType, opts.instrumentId);
|
|
@@ -1958,6 +2269,14 @@ async function issueEquityCommand(opts) {
|
|
|
1958
2269
|
if (!opts.instrumentId) {
|
|
1959
2270
|
console.log(`Using instrument: ${instrument.symbol} (${instrument.kind})`);
|
|
1960
2271
|
}
|
|
2272
|
+
await ensureIssuancePreflight(
|
|
2273
|
+
client,
|
|
2274
|
+
eid,
|
|
2275
|
+
opts.grantType,
|
|
2276
|
+
instrument,
|
|
2277
|
+
opts.meetingId,
|
|
2278
|
+
opts.resolutionId
|
|
2279
|
+
);
|
|
1961
2280
|
const round = await client.startEquityRound({
|
|
1962
2281
|
entity_id: eid,
|
|
1963
2282
|
name: `${opts.grantType} grant \u2014 ${opts.recipient}`,
|
|
@@ -2006,33 +2325,25 @@ async function issueSafeCommand(opts) {
|
|
|
2006
2325
|
});
|
|
2007
2326
|
return;
|
|
2008
2327
|
}
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
name: `SAFE \u2014 ${opts.investor}`,
|
|
2019
|
-
issuer_legal_entity_id: issuerLegalEntityId
|
|
2020
|
-
});
|
|
2021
|
-
const roundId = round.round_id ?? round.equity_round_id;
|
|
2022
|
-
const securityData = {
|
|
2328
|
+
await ensureIssuancePreflight(
|
|
2329
|
+
client,
|
|
2330
|
+
eid,
|
|
2331
|
+
opts.safeType,
|
|
2332
|
+
void 0,
|
|
2333
|
+
opts.meetingId,
|
|
2334
|
+
opts.resolutionId
|
|
2335
|
+
);
|
|
2336
|
+
const body = {
|
|
2023
2337
|
entity_id: eid,
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
grant_type: opts.safeType
|
|
2338
|
+
investor_name: opts.investor,
|
|
2339
|
+
principal_amount_cents: opts.amount,
|
|
2340
|
+
valuation_cap_cents: opts.valuationCap,
|
|
2341
|
+
safe_type: opts.safeType
|
|
2029
2342
|
};
|
|
2030
|
-
if (opts.email)
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
if (opts.resolutionId) issuePayload.resolution_id = opts.resolutionId;
|
|
2035
|
-
const result = await client.issueRound(roundId, issuePayload);
|
|
2343
|
+
if (opts.email) body.email = opts.email;
|
|
2344
|
+
if (opts.meetingId) body.meeting_id = opts.meetingId;
|
|
2345
|
+
if (opts.resolutionId) body.resolution_id = opts.resolutionId;
|
|
2346
|
+
const result = await client.createSafeNote(body);
|
|
2036
2347
|
if (opts.json) {
|
|
2037
2348
|
printJson(result);
|
|
2038
2349
|
return;
|
|
@@ -2145,6 +2456,40 @@ async function startRoundCommand(opts) {
|
|
|
2145
2456
|
process.exit(1);
|
|
2146
2457
|
}
|
|
2147
2458
|
}
|
|
2459
|
+
async function createInstrumentCommand(opts) {
|
|
2460
|
+
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2461
|
+
const eid = resolveEntityId(cfg, opts.entityId);
|
|
2462
|
+
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2463
|
+
try {
|
|
2464
|
+
let issuerLegalEntityId = opts.issuerLegalEntityId;
|
|
2465
|
+
if (!issuerLegalEntityId) {
|
|
2466
|
+
const capTable = await client.getCapTable(eid);
|
|
2467
|
+
issuerLegalEntityId = capTable.issuer_legal_entity_id;
|
|
2468
|
+
}
|
|
2469
|
+
if (!issuerLegalEntityId) {
|
|
2470
|
+
throw new Error("No issuer legal entity found. Has this entity been formed with a cap table?");
|
|
2471
|
+
}
|
|
2472
|
+
const terms = opts.termsJson ? JSON.parse(opts.termsJson) : {};
|
|
2473
|
+
const payload = {
|
|
2474
|
+
entity_id: eid,
|
|
2475
|
+
issuer_legal_entity_id: issuerLegalEntityId,
|
|
2476
|
+
kind: opts.kind,
|
|
2477
|
+
symbol: opts.symbol,
|
|
2478
|
+
terms
|
|
2479
|
+
};
|
|
2480
|
+
if (opts.authorizedUnits != null) payload.authorized_units = opts.authorizedUnits;
|
|
2481
|
+
if (opts.issuePriceCents != null) payload.issue_price_cents = opts.issuePriceCents;
|
|
2482
|
+
if (opts.dryRun) {
|
|
2483
|
+
printDryRun("cap_table.create_instrument", payload);
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
const result = await client.createInstrument(payload);
|
|
2487
|
+
printWriteResult(result, `Instrument created: ${result.instrument_id ?? "OK"}`, opts.json);
|
|
2488
|
+
} catch (err) {
|
|
2489
|
+
printError(`Failed to create instrument: ${err}`);
|
|
2490
|
+
process.exit(1);
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2148
2493
|
async function addSecurityCommand(opts) {
|
|
2149
2494
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
2150
2495
|
const eid = resolveEntityId(cfg, opts.entityId);
|
|
@@ -2177,10 +2522,23 @@ async function issueRoundCommand(opts) {
|
|
|
2177
2522
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2178
2523
|
try {
|
|
2179
2524
|
if (opts.dryRun) {
|
|
2180
|
-
printDryRun("cap_table.issue_round", {
|
|
2525
|
+
printDryRun("cap_table.issue_round", {
|
|
2526
|
+
entity_id: eid,
|
|
2527
|
+
round_id: opts.roundId,
|
|
2528
|
+
meeting_id: opts.meetingId,
|
|
2529
|
+
resolution_id: opts.resolutionId
|
|
2530
|
+
});
|
|
2181
2531
|
return;
|
|
2182
2532
|
}
|
|
2183
|
-
|
|
2533
|
+
if ((!opts.meetingId || !opts.resolutionId) && await entityHasActiveBoard(client, eid)) {
|
|
2534
|
+
throw new Error(
|
|
2535
|
+
"Board approval is required before issuing this round. Pass --meeting-id and --resolution-id from a passed board vote."
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
const body = { entity_id: eid };
|
|
2539
|
+
if (opts.meetingId) body.meeting_id = opts.meetingId;
|
|
2540
|
+
if (opts.resolutionId) body.resolution_id = opts.resolutionId;
|
|
2541
|
+
const result = await client.issueRound(opts.roundId, body);
|
|
2184
2542
|
printWriteResult(result, "Round issued and closed", opts.json);
|
|
2185
2543
|
} catch (err) {
|
|
2186
2544
|
printError(`Failed to issue round: ${err}`);
|
|
@@ -2307,8 +2665,7 @@ async function financeInvoiceCommand(opts) {
|
|
|
2307
2665
|
due_date: opts.dueDate,
|
|
2308
2666
|
description: opts.description
|
|
2309
2667
|
});
|
|
2310
|
-
|
|
2311
|
-
printJson(result);
|
|
2668
|
+
printWriteResult(result, `Invoice created: ${result.invoice_id ?? "OK"}`, opts.json);
|
|
2312
2669
|
} catch (err) {
|
|
2313
2670
|
printError(`Failed to create invoice: ${err}`);
|
|
2314
2671
|
process.exit(1);
|
|
@@ -2324,8 +2681,7 @@ async function financePayrollCommand(opts) {
|
|
|
2324
2681
|
pay_period_start: opts.periodStart,
|
|
2325
2682
|
pay_period_end: opts.periodEnd
|
|
2326
2683
|
});
|
|
2327
|
-
|
|
2328
|
-
printJson(result);
|
|
2684
|
+
printWriteResult(result, `Payroll run created: ${result.payroll_run_id ?? "OK"}`, opts.json);
|
|
2329
2685
|
} catch (err) {
|
|
2330
2686
|
printError(`Failed to run payroll: ${err}`);
|
|
2331
2687
|
process.exit(1);
|
|
@@ -2343,8 +2699,7 @@ async function financePayCommand(opts) {
|
|
|
2343
2699
|
payment_method: opts.method,
|
|
2344
2700
|
description: `Payment via ${opts.method}`
|
|
2345
2701
|
});
|
|
2346
|
-
|
|
2347
|
-
printJson(result);
|
|
2702
|
+
printWriteResult(result, `Payment submitted: ${result.payment_id ?? "OK"}`, opts.json);
|
|
2348
2703
|
} catch (err) {
|
|
2349
2704
|
printError(`Failed to submit payment: ${err}`);
|
|
2350
2705
|
process.exit(1);
|
|
@@ -2356,8 +2711,7 @@ async function financeOpenAccountCommand(opts) {
|
|
|
2356
2711
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
2357
2712
|
try {
|
|
2358
2713
|
const result = await client.openBankAccount({ entity_id: eid, bank_name: opts.institution });
|
|
2359
|
-
|
|
2360
|
-
printJson(result);
|
|
2714
|
+
printWriteResult(result, `Bank account opened: ${result.account_id ?? "OK"}`, opts.json);
|
|
2361
2715
|
} catch (err) {
|
|
2362
2716
|
printError(`Failed to open bank account: ${err}`);
|
|
2363
2717
|
process.exit(1);
|
|
@@ -2377,8 +2731,7 @@ async function financeClassifyContractorCommand(opts) {
|
|
|
2377
2731
|
duration_months: opts.duration,
|
|
2378
2732
|
provides_tools: opts.providesTools
|
|
2379
2733
|
});
|
|
2380
|
-
|
|
2381
|
-
printJson(result);
|
|
2734
|
+
printWriteResult(result, `Classification: ${result.risk_level ?? "OK"}`, opts.json);
|
|
2382
2735
|
} catch (err) {
|
|
2383
2736
|
printError(`Failed to classify contractor: ${err}`);
|
|
2384
2737
|
process.exit(1);
|
|
@@ -2394,8 +2747,7 @@ async function financeReconcileCommand(opts) {
|
|
|
2394
2747
|
start_date: opts.startDate,
|
|
2395
2748
|
end_date: opts.endDate
|
|
2396
2749
|
});
|
|
2397
|
-
|
|
2398
|
-
printJson(result);
|
|
2750
|
+
printWriteResult(result, `Ledger reconciled: ${result.reconciliation_id ?? "OK"}`, opts.json);
|
|
2399
2751
|
} catch (err) {
|
|
2400
2752
|
printError(`Failed to reconcile ledger: ${err}`);
|
|
2401
2753
|
process.exit(1);
|
|
@@ -3005,7 +3357,8 @@ __export(agents_exports, {
|
|
|
3005
3357
|
agentsSkillCommand: () => agentsSkillCommand
|
|
3006
3358
|
});
|
|
3007
3359
|
import chalk8 from "chalk";
|
|
3008
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
3360
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
3361
|
+
import { relative, resolve } from "path";
|
|
3009
3362
|
async function agentsListCommand(opts) {
|
|
3010
3363
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
3011
3364
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
@@ -3100,7 +3453,18 @@ function resolveTextInput(inlineText, filePath, label, required = false) {
|
|
|
3100
3453
|
throw new Error(`Pass either --${label} or --${label}-file, not both.`);
|
|
3101
3454
|
}
|
|
3102
3455
|
if (filePath) {
|
|
3103
|
-
|
|
3456
|
+
if (process.env.CORP_ALLOW_UNSAFE_FILE_INPUT === "1") {
|
|
3457
|
+
return readFileSync2(filePath, "utf8");
|
|
3458
|
+
}
|
|
3459
|
+
const resolvedFile = realpathSync(resolve(filePath));
|
|
3460
|
+
const workingTreeRoot = realpathSync(process.cwd());
|
|
3461
|
+
const rel = relative(workingTreeRoot, resolvedFile);
|
|
3462
|
+
if (rel === "" || !rel.startsWith("..") && !rel.startsWith("/")) {
|
|
3463
|
+
return readFileSync2(resolvedFile, "utf8");
|
|
3464
|
+
}
|
|
3465
|
+
throw new Error(
|
|
3466
|
+
`--${label}-file must stay inside the current working directory unless CORP_ALLOW_UNSAFE_FILE_INPUT=1 is set.`
|
|
3467
|
+
);
|
|
3104
3468
|
}
|
|
3105
3469
|
if (inlineText) {
|
|
3106
3470
|
return inlineText;
|
|
@@ -3483,10 +3847,18 @@ function normalizeFounderInfo(input3) {
|
|
|
3483
3847
|
function parseLegacyMemberSpec(raw) {
|
|
3484
3848
|
const parts = raw.split(",").map((p) => p.trim());
|
|
3485
3849
|
if (parts.length < 3) {
|
|
3486
|
-
throw new Error(
|
|
3850
|
+
throw new Error(
|
|
3851
|
+
`Invalid member format: ${raw}. Expected: name,email,role[,pct[,address[,officer_title[,is_incorporator]]]]`
|
|
3852
|
+
);
|
|
3487
3853
|
}
|
|
3488
3854
|
const founder = { name: parts[0], email: parts[1], role: parts[2] };
|
|
3489
3855
|
if (parts.length >= 4) founder.ownership_pct = parseFloat(parts[3]);
|
|
3856
|
+
if (parts.length >= 5 && parts[4]) founder.address = parseAddressValue(parts[4]);
|
|
3857
|
+
if (parts.length >= 6 && parts[5]) founder.officer_title = parts[5];
|
|
3858
|
+
if (parts.length >= 7) {
|
|
3859
|
+
const incorporator = parseBoolean(parts[6]);
|
|
3860
|
+
if (incorporator !== void 0) founder.is_incorporator = incorporator;
|
|
3861
|
+
}
|
|
3490
3862
|
return founder;
|
|
3491
3863
|
}
|
|
3492
3864
|
function parseKeyValueMemberSpec(raw) {
|
|
@@ -3896,6 +4268,14 @@ async function formFinalizeCommand(entityId, opts) {
|
|
|
3896
4268
|
payload.authorized_shares = authorizedShares;
|
|
3897
4269
|
}
|
|
3898
4270
|
if (opts.parValue) payload.par_value = opts.parValue;
|
|
4271
|
+
if (opts.boardSize) {
|
|
4272
|
+
const boardSize = parseInt(opts.boardSize, 10);
|
|
4273
|
+
if (!Number.isFinite(boardSize) || boardSize <= 0) {
|
|
4274
|
+
throw new Error(`Invalid board size: ${opts.boardSize}`);
|
|
4275
|
+
}
|
|
4276
|
+
payload.board_size = boardSize;
|
|
4277
|
+
}
|
|
4278
|
+
if (opts.principalName) payload.principal_name = opts.principalName;
|
|
3899
4279
|
if (opts.registeredAgentName) payload.registered_agent_name = opts.registeredAgentName;
|
|
3900
4280
|
if (opts.registeredAgentAddress) payload.registered_agent_address = opts.registeredAgentAddress;
|
|
3901
4281
|
if (opts.formationDate) payload.formation_date = opts.formationDate;
|
|
@@ -4040,6 +4420,14 @@ __export(feedback_exports, {
|
|
|
4040
4420
|
});
|
|
4041
4421
|
import chalk12 from "chalk";
|
|
4042
4422
|
async function feedbackCommand(message, opts) {
|
|
4423
|
+
if (!message || message.trim().length === 0) {
|
|
4424
|
+
printError("Feedback message cannot be empty");
|
|
4425
|
+
process.exit(1);
|
|
4426
|
+
}
|
|
4427
|
+
if (message.length > MAX_FEEDBACK_LENGTH) {
|
|
4428
|
+
printError(`Feedback message must be at most ${MAX_FEEDBACK_LENGTH} characters (got ${message.length})`);
|
|
4429
|
+
process.exit(1);
|
|
4430
|
+
}
|
|
4043
4431
|
const cfg = requireConfig("api_url", "api_key", "workspace_id");
|
|
4044
4432
|
const client = new CorpAPIClient(cfg.api_url, cfg.api_key, cfg.workspace_id);
|
|
4045
4433
|
try {
|
|
@@ -4055,12 +4443,14 @@ ${chalk12.green("\u2713")} Feedback submitted (${chalk12.dim(result.feedback_id)
|
|
|
4055
4443
|
process.exit(1);
|
|
4056
4444
|
}
|
|
4057
4445
|
}
|
|
4446
|
+
var MAX_FEEDBACK_LENGTH;
|
|
4058
4447
|
var init_feedback = __esm({
|
|
4059
4448
|
"src/commands/feedback.ts"() {
|
|
4060
4449
|
"use strict";
|
|
4061
4450
|
init_config();
|
|
4062
4451
|
init_api_client();
|
|
4063
4452
|
init_output();
|
|
4453
|
+
MAX_FEEDBACK_LENGTH = 1e4;
|
|
4064
4454
|
}
|
|
4065
4455
|
});
|
|
4066
4456
|
|
|
@@ -4070,7 +4460,7 @@ __export(serve_exports, {
|
|
|
4070
4460
|
serveCommand: () => serveCommand
|
|
4071
4461
|
});
|
|
4072
4462
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
|
|
4073
|
-
import { resolve } from "path";
|
|
4463
|
+
import { resolve as resolve2 } from "path";
|
|
4074
4464
|
import { randomBytes } from "crypto";
|
|
4075
4465
|
function generateFernetKey() {
|
|
4076
4466
|
return randomBytes(32).toString("base64url") + "=";
|
|
@@ -4122,35 +4512,21 @@ async function serveCommand(opts) {
|
|
|
4122
4512
|
console.error(`Error: Invalid port "${opts.port}"`);
|
|
4123
4513
|
process.exit(1);
|
|
4124
4514
|
}
|
|
4125
|
-
const envPath =
|
|
4515
|
+
const envPath = resolve2(process.cwd(), ".env");
|
|
4126
4516
|
ensureEnvFile(envPath);
|
|
4127
4517
|
loadEnvFile(envPath);
|
|
4128
4518
|
const localUrl = `http://localhost:${port}`;
|
|
4129
|
-
const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
4130
|
-
const cfg = loadConfig2();
|
|
4131
|
-
const previousUrl = cfg.api_url;
|
|
4132
|
-
if (cfg.api_url !== localUrl) {
|
|
4133
|
-
cfg.api_url = localUrl;
|
|
4134
|
-
saveConfig2(cfg);
|
|
4135
|
-
console.log(`CLI configured to use local server: ${localUrl}`);
|
|
4136
|
-
console.log(` (previous: ${previousUrl})`);
|
|
4137
|
-
console.log(` To revert: corp config set api_url ${previousUrl}
|
|
4138
|
-
`);
|
|
4139
|
-
}
|
|
4140
4519
|
console.log(`Starting server on port ${port}...`);
|
|
4141
4520
|
console.log(`Data directory: ${opts.dataDir}`);
|
|
4521
|
+
console.log(`CLI API URL remains unchanged.`);
|
|
4522
|
+
console.log(` Use CORP_API_URL=${localUrl} for commands against this local server.
|
|
4523
|
+
`);
|
|
4142
4524
|
const child = server.startServer({
|
|
4143
4525
|
port,
|
|
4144
4526
|
dataDir: opts.dataDir
|
|
4145
4527
|
});
|
|
4146
4528
|
const shutdown = () => {
|
|
4147
4529
|
console.log("\nShutting down server...");
|
|
4148
|
-
if (previousUrl !== localUrl) {
|
|
4149
|
-
const current = loadConfig2();
|
|
4150
|
-
current.api_url = previousUrl;
|
|
4151
|
-
saveConfig2(current);
|
|
4152
|
-
console.log(`CLI restored to: ${previousUrl}`);
|
|
4153
|
-
}
|
|
4154
4530
|
child.kill("SIGTERM");
|
|
4155
4531
|
};
|
|
4156
4532
|
process.on("SIGINT", shutdown);
|
|
@@ -4233,9 +4609,9 @@ program.command("setup").description("Interactive setup wizard").action(async ()
|
|
|
4233
4609
|
const { setupCommand: setupCommand2 } = await Promise.resolve().then(() => (init_setup(), setup_exports));
|
|
4234
4610
|
await setupCommand2();
|
|
4235
4611
|
});
|
|
4236
|
-
program.command("status").description("Workspace summary").action(async () => {
|
|
4612
|
+
program.command("status").description("Workspace summary").option("--json", "Output as JSON").action(async (opts) => {
|
|
4237
4613
|
const { statusCommand: statusCommand2 } = await Promise.resolve().then(() => (init_status(), status_exports));
|
|
4238
|
-
await statusCommand2();
|
|
4614
|
+
await statusCommand2(opts);
|
|
4239
4615
|
});
|
|
4240
4616
|
program.command("context").alias("whoami").description("Show the active workspace, user, and entity context").option("--json", "Output as JSON").action(async (opts) => {
|
|
4241
4617
|
const { contextCommand: contextCommand2 } = await Promise.resolve().then(() => (init_context(), context_exports));
|
|
@@ -4246,23 +4622,23 @@ program.command("schema").description("Dump the CLI command catalog as JSON").op
|
|
|
4246
4622
|
schemaCommand2(program, opts);
|
|
4247
4623
|
});
|
|
4248
4624
|
var configCmd = program.command("config").description("Manage configuration");
|
|
4249
|
-
configCmd.command("set <key> <value>").description("Set a config value (dot-path)").action(async (key, value) => {
|
|
4250
|
-
const { configSetCommand: configSetCommand2 } = await Promise.resolve().then(() => (init_config2(),
|
|
4251
|
-
configSetCommand2(key, value);
|
|
4625
|
+
configCmd.command("set <key> <value>").description("Set a config value (dot-path)").option("--force", "Allow updating a security-sensitive config key").action(async (key, value, opts) => {
|
|
4626
|
+
const { configSetCommand: configSetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
4627
|
+
configSetCommand2(key, value, opts);
|
|
4252
4628
|
});
|
|
4253
4629
|
configCmd.command("get <key>").description("Get a config value (dot-path)").action(async (key) => {
|
|
4254
|
-
const { configGetCommand: configGetCommand2 } = await Promise.resolve().then(() => (init_config2(),
|
|
4630
|
+
const { configGetCommand: configGetCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
4255
4631
|
configGetCommand2(key);
|
|
4256
4632
|
});
|
|
4257
4633
|
configCmd.command("list").description("List all config (API keys masked)").action(async () => {
|
|
4258
|
-
const { configListCommand: configListCommand2 } = await Promise.resolve().then(() => (init_config2(),
|
|
4634
|
+
const { configListCommand: configListCommand2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
|
|
4259
4635
|
configListCommand2();
|
|
4260
4636
|
});
|
|
4261
4637
|
program.command("obligations").description("List obligations with urgency tiers").option("--tier <tier>", "Filter by urgency tier").option("--json", "Output as JSON").action(async (opts) => {
|
|
4262
4638
|
const { obligationsCommand: obligationsCommand2 } = await Promise.resolve().then(() => (init_obligations(), obligations_exports));
|
|
4263
4639
|
await obligationsCommand2(opts);
|
|
4264
4640
|
});
|
|
4265
|
-
program.command("digest").description("View or trigger daily digests").option("--trigger", "Trigger digest now").option("--key <key>", "Get specific digest by key").action(async (opts) => {
|
|
4641
|
+
program.command("digest").description("View or trigger daily digests").option("--trigger", "Trigger digest now").option("--key <key>", "Get specific digest by key").option("--json", "Output as JSON").action(async (opts) => {
|
|
4266
4642
|
const { digestCommand: digestCommand2 } = await Promise.resolve().then(() => (init_digest(), digest_exports));
|
|
4267
4643
|
await digestCommand2(opts);
|
|
4268
4644
|
});
|
|
@@ -4311,7 +4687,7 @@ contactsCmd.command("show <contact-id>").option("--json", "Output as JSON").desc
|
|
|
4311
4687
|
json: inheritOption(opts.json, parent.json)
|
|
4312
4688
|
});
|
|
4313
4689
|
});
|
|
4314
|
-
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, founder, member, other)").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Add a new contact").action(async (opts, cmd) => {
|
|
4690
|
+
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, founder, member, other)").option("--cap-table-access <level>", "Cap table access (none, summary, detailed)").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Add a new contact").action(async (opts, cmd) => {
|
|
4315
4691
|
const parent = cmd.parent.opts();
|
|
4316
4692
|
const { contactsAddCommand: contactsAddCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
|
|
4317
4693
|
await contactsAddCommand2({
|
|
@@ -4320,7 +4696,7 @@ contactsCmd.command("add").requiredOption("--name <name>", "Contact name").requi
|
|
|
4320
4696
|
json: inheritOption(opts.json, parent.json)
|
|
4321
4697
|
});
|
|
4322
4698
|
});
|
|
4323
|
-
contactsCmd.command("edit <contact-id>").option("--name <name>", "Contact name").option("--email <email>", "Contact email").option("--category <category>", "Contact category").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Edit an existing contact").action(async (contactId, opts, cmd) => {
|
|
4699
|
+
contactsCmd.command("edit <contact-id>").option("--name <name>", "Contact name").option("--email <email>", "Contact email").option("--category <category>", "Contact category").option("--cap-table-access <level>", "Cap table access (none, summary, detailed)").option("--address <address>", "Mailing address").option("--mailing-address <address>", "Alias for --address").option("--phone <phone>", "Phone number").option("--notes <notes>", "Notes").option("--json", "Output as JSON").description("Edit an existing contact").action(async (contactId, opts, cmd) => {
|
|
4324
4700
|
const parent = cmd.parent.opts();
|
|
4325
4701
|
const { contactsEditCommand: contactsEditCommand2 } = await Promise.resolve().then(() => (init_contacts(), contacts_exports));
|
|
4326
4702
|
await contactsEditCommand2(contactId, {
|
|
@@ -4353,6 +4729,15 @@ capTableCmd.command("409a").description("Current 409A valuation").action(async (
|
|
|
4353
4729
|
const { fourOhNineACommand: fourOhNineACommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
4354
4730
|
await fourOhNineACommand2(parent);
|
|
4355
4731
|
});
|
|
4732
|
+
capTableCmd.command("create-instrument").requiredOption("--kind <kind>", "Instrument kind (common_equity, preferred_equity, membership_unit, option_grant, safe)").requiredOption("--symbol <symbol>", "Instrument symbol").option("--issuer-legal-entity-id <id>", "Issuer legal entity ID (auto-detected from the cap table if omitted)").option("--authorized-units <n>", "Authorized units", parseInt).option("--issue-price-cents <n>", "Issue price in cents", parseInt).option("--terms-json <json>", "JSON object of instrument terms").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the instrument").description("Create a cap table instrument").action(async (opts, cmd) => {
|
|
4733
|
+
const parent = cmd.parent.opts();
|
|
4734
|
+
const { createInstrumentCommand: createInstrumentCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
4735
|
+
await createInstrumentCommand2({
|
|
4736
|
+
...opts,
|
|
4737
|
+
entityId: parent.entityId,
|
|
4738
|
+
json: inheritOption(opts.json, parent.json)
|
|
4739
|
+
});
|
|
4740
|
+
});
|
|
4356
4741
|
capTableCmd.command("issue-equity").requiredOption("--grant-type <type>", "Grant type (common, preferred, membership_unit, stock_option, iso, nso, rsa)").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)").option("--meeting-id <id>", "Board meeting ID required when a board approval already exists or is being recorded").option("--resolution-id <id>", "Board resolution ID required when issuing under a board-governed entity").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the round").description("Issue an equity grant (creates a round, adds security, and issues it)").action(async (opts, cmd) => {
|
|
4357
4742
|
const parent = cmd.parent.opts();
|
|
4358
4743
|
const { issueEquityCommand: issueEquityCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
@@ -4407,7 +4792,7 @@ capTableCmd.command("add-security").requiredOption("--round-id <id>", "Round ID"
|
|
|
4407
4792
|
json: inheritOption(opts.json, parent.json)
|
|
4408
4793
|
});
|
|
4409
4794
|
});
|
|
4410
|
-
capTableCmd.command("issue-round").option("--json", "Output as JSON").option("--dry-run", "Show the request without issuing the round").requiredOption("--round-id <id>", "Round ID").description("Issue all securities and close a staged round").action(async (opts, cmd) => {
|
|
4795
|
+
capTableCmd.command("issue-round").option("--meeting-id <id>", "Board meeting ID required when issuing under a board-governed entity").option("--resolution-id <id>", "Board resolution ID required when issuing under a board-governed entity").option("--json", "Output as JSON").option("--dry-run", "Show the request without issuing the round").requiredOption("--round-id <id>", "Round ID").description("Issue all securities and close a staged round").action(async (opts, cmd) => {
|
|
4411
4796
|
const parent = cmd.parent.opts();
|
|
4412
4797
|
const { issueRoundCommand: issueRoundCommand2 } = await Promise.resolve().then(() => (init_cap_table(), cap_table_exports));
|
|
4413
4798
|
await issueRoundCommand2({
|
|
@@ -4445,36 +4830,60 @@ capTableCmd.command("approve-valuation <valuation-id>").option("--resolution-id
|
|
|
4445
4830
|
json: inheritOption(opts.json, parent.json)
|
|
4446
4831
|
});
|
|
4447
4832
|
});
|
|
4448
|
-
var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <id>", "Entity ID (overrides active entity)");
|
|
4449
|
-
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) => {
|
|
4833
|
+
var financeCmd = program.command("finance").description("Invoicing, payroll, payments, banking").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON");
|
|
4834
|
+
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").option("--json", "Output as JSON").description("Create an invoice").action(async (opts, cmd) => {
|
|
4450
4835
|
const parent = cmd.parent.opts();
|
|
4451
4836
|
const { financeInvoiceCommand: financeInvoiceCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
|
|
4452
|
-
await financeInvoiceCommand2({
|
|
4837
|
+
await financeInvoiceCommand2({
|
|
4838
|
+
...opts,
|
|
4839
|
+
entityId: parent.entityId,
|
|
4840
|
+
json: inheritOption(opts.json, parent.json)
|
|
4841
|
+
});
|
|
4453
4842
|
});
|
|
4454
|
-
financeCmd.command("payroll").requiredOption("--period-start <date>", "Pay period start").requiredOption("--period-end <date>", "Pay period end").description("Run payroll").action(async (opts, cmd) => {
|
|
4843
|
+
financeCmd.command("payroll").requiredOption("--period-start <date>", "Pay period start").requiredOption("--period-end <date>", "Pay period end").option("--json", "Output as JSON").description("Run payroll").action(async (opts, cmd) => {
|
|
4455
4844
|
const parent = cmd.parent.opts();
|
|
4456
4845
|
const { financePayrollCommand: financePayrollCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
|
|
4457
|
-
await financePayrollCommand2({
|
|
4846
|
+
await financePayrollCommand2({
|
|
4847
|
+
...opts,
|
|
4848
|
+
entityId: parent.entityId,
|
|
4849
|
+
json: inheritOption(opts.json, parent.json)
|
|
4850
|
+
});
|
|
4458
4851
|
});
|
|
4459
|
-
financeCmd.command("pay").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--recipient <name>", "Recipient name").option("--method <method>", "Payment method", "ach").description("Submit a payment").action(async (opts, cmd) => {
|
|
4852
|
+
financeCmd.command("pay").requiredOption("--amount <n>", "Amount in cents", parseInt).requiredOption("--recipient <name>", "Recipient name").option("--method <method>", "Payment method", "ach").option("--json", "Output as JSON").description("Submit a payment").action(async (opts, cmd) => {
|
|
4460
4853
|
const parent = cmd.parent.opts();
|
|
4461
4854
|
const { financePayCommand: financePayCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
|
|
4462
|
-
await financePayCommand2({
|
|
4855
|
+
await financePayCommand2({
|
|
4856
|
+
...opts,
|
|
4857
|
+
entityId: parent.entityId,
|
|
4858
|
+
json: inheritOption(opts.json, parent.json)
|
|
4859
|
+
});
|
|
4463
4860
|
});
|
|
4464
|
-
financeCmd.command("open-account").option("--institution <name>", "Banking institution", "Mercury").description("Open a business bank account").action(async (opts, cmd) => {
|
|
4861
|
+
financeCmd.command("open-account").option("--institution <name>", "Banking institution", "Mercury").option("--json", "Output as JSON").description("Open a business bank account").action(async (opts, cmd) => {
|
|
4465
4862
|
const parent = cmd.parent.opts();
|
|
4466
4863
|
const { financeOpenAccountCommand: financeOpenAccountCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
|
|
4467
|
-
await financeOpenAccountCommand2({
|
|
4864
|
+
await financeOpenAccountCommand2({
|
|
4865
|
+
...opts,
|
|
4866
|
+
entityId: parent.entityId,
|
|
4867
|
+
json: inheritOption(opts.json, parent.json)
|
|
4868
|
+
});
|
|
4468
4869
|
});
|
|
4469
|
-
financeCmd.command("classify-contractor").requiredOption("--name <name>", "Contractor name").requiredOption("--state <code>", "US state code").requiredOption("--hours <n>", "Hours per week", parseInt).option("--exclusive", "Exclusive client", false).requiredOption("--duration <n>", "Duration in months", parseInt).option("--provides-tools", "Company provides tools", false).description("Analyze contractor classification risk").action(async (opts, cmd) => {
|
|
4870
|
+
financeCmd.command("classify-contractor").requiredOption("--name <name>", "Contractor name").requiredOption("--state <code>", "US state code").requiredOption("--hours <n>", "Hours per week", parseInt).option("--exclusive", "Exclusive client", false).requiredOption("--duration <n>", "Duration in months", parseInt).option("--provides-tools", "Company provides tools", false).option("--json", "Output as JSON").description("Analyze contractor classification risk").action(async (opts, cmd) => {
|
|
4470
4871
|
const parent = cmd.parent.opts();
|
|
4471
4872
|
const { financeClassifyContractorCommand: financeClassifyContractorCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
|
|
4472
|
-
await financeClassifyContractorCommand2({
|
|
4873
|
+
await financeClassifyContractorCommand2({
|
|
4874
|
+
...opts,
|
|
4875
|
+
entityId: parent.entityId,
|
|
4876
|
+
json: inheritOption(opts.json, parent.json)
|
|
4877
|
+
});
|
|
4473
4878
|
});
|
|
4474
|
-
financeCmd.command("reconcile").requiredOption("--start-date <date>", "Period start").requiredOption("--end-date <date>", "Period end").description("Reconcile ledger").action(async (opts, cmd) => {
|
|
4879
|
+
financeCmd.command("reconcile").requiredOption("--start-date <date>", "Period start").requiredOption("--end-date <date>", "Period end").option("--json", "Output as JSON").description("Reconcile ledger").action(async (opts, cmd) => {
|
|
4475
4880
|
const parent = cmd.parent.opts();
|
|
4476
4881
|
const { financeReconcileCommand: financeReconcileCommand2 } = await Promise.resolve().then(() => (init_finance(), finance_exports));
|
|
4477
|
-
await financeReconcileCommand2({
|
|
4882
|
+
await financeReconcileCommand2({
|
|
4883
|
+
...opts,
|
|
4884
|
+
entityId: parent.entityId,
|
|
4885
|
+
json: inheritOption(opts.json, parent.json)
|
|
4886
|
+
});
|
|
4478
4887
|
});
|
|
4479
4888
|
var governanceCmd = program.command("governance").description("Governance bodies, seats, meetings, resolutions").option("--entity-id <id>", "Entity ID (overrides active entity)").option("--json", "Output as JSON").action(async (opts) => {
|
|
4480
4889
|
const { governanceListCommand: governanceListCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
@@ -4790,23 +5199,35 @@ program.command("approvals").description("Approvals are managed through governan
|
|
|
4790
5199
|
"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"
|
|
4791
5200
|
);
|
|
4792
5201
|
});
|
|
4793
|
-
var formCmd = program.command("form").description("Form a new entity with founders and cap table").option("--entity-type <type>", "Entity type (llc, c_corp)").option("--legal-name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--member <member>", "Founder as 'name,email,role[,pct]' or key=value pairs like 'name=...,email=...,role=...,officer_title=cto,is_incorporator=true,address=street|city|state|zip' (repeatable)", (v, a) => [...a, v], []).option("--member-json <json>", "Founder JSON object (repeatable)", (v, a) => [...a, v], []).option("--members-file <path>", 'Path to a JSON array of founders or {"members": [...]}').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").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the entity").action(async (opts) => {
|
|
5202
|
+
var formCmd = program.command("form").description("Form a new entity with founders and cap table").option("--entity-type <type>", "Entity type (llc, c_corp)").option("--legal-name <name>", "Legal name").option("--jurisdiction <jurisdiction>", "Jurisdiction (e.g. US-DE, US-WY)").option("--member <member>", "Founder as 'name,email,role[,pct[,address[,officer_title[,is_incorporator]]]]' with address as street|city|state|zip, or key=value pairs like 'name=...,email=...,role=...,officer_title=cto,is_incorporator=true,address=street|city|state|zip' (repeatable)", (v, a) => [...a, v], []).option("--member-json <json>", "Founder JSON object (repeatable)", (v, a) => [...a, v], []).option("--members-file <path>", 'Path to a JSON array of founders or {"members": [...]}').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").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the entity").action(async (opts) => {
|
|
4794
5203
|
if (opts.entityType && !opts.type) opts.type = opts.entityType;
|
|
4795
5204
|
if (opts.legalName && !opts.name) opts.name = opts.legalName;
|
|
4796
5205
|
const { formCommand: formCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
4797
5206
|
await formCommand2(opts);
|
|
4798
5207
|
});
|
|
4799
|
-
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)").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the pending entity").action(async (opts) => {
|
|
5208
|
+
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)").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without creating the pending entity").action(async (opts, cmd) => {
|
|
4800
5209
|
const { formCreateCommand: formCreateCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
4801
|
-
await formCreateCommand2(
|
|
5210
|
+
await formCreateCommand2({
|
|
5211
|
+
...opts,
|
|
5212
|
+
json: inheritOption(opts.json, cmd.parent.opts().json),
|
|
5213
|
+
dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
|
|
5214
|
+
});
|
|
4802
5215
|
});
|
|
4803
|
-
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").addOption(new Option("--officer-title <title>", "Officer title (corporations only)").choices(["ceo", "cfo", "cto", "coo", "secretary", "treasurer", "president", "vp", "other"])).option("--incorporator", "Mark as sole incorporator (corporations only)").option("--address <address>", "Founder address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without adding the founder").action(async (entityId, opts) => {
|
|
5216
|
+
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").addOption(new Option("--officer-title <title>", "Officer title (corporations only)").choices(["ceo", "cfo", "cto", "coo", "secretary", "treasurer", "president", "vp", "other"])).option("--incorporator", "Mark as sole incorporator (corporations only)").option("--address <address>", "Founder address as 'street,city,state,zip'").option("--json", "Output as JSON").option("--dry-run", "Show the request without adding the founder").action(async (entityId, opts, cmd) => {
|
|
4804
5217
|
const { formAddFounderCommand: formAddFounderCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
4805
|
-
await formAddFounderCommand2(entityId,
|
|
5218
|
+
await formAddFounderCommand2(entityId, {
|
|
5219
|
+
...opts,
|
|
5220
|
+
json: inheritOption(opts.json, cmd.parent.opts().json),
|
|
5221
|
+
dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
|
|
5222
|
+
});
|
|
4806
5223
|
});
|
|
4807
|
-
formCmd.command("finalize <entity-id>").description("Finalize formation and generate documents + cap table (staged flow step 3)").option("--authorized-shares <count>", "Authorized shares for corporations").option("--par-value <value>", "Par value per share, e.g. 0.0001").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--incorporator-name <name>", "Incorporator legal name (overrides founder)").option("--incorporator-address <address>", "Incorporator mailing address (overrides founder)").option("--json", "Output as JSON").option("--dry-run", "Show the request without finalizing formation").action(async (entityId, opts) => {
|
|
5224
|
+
formCmd.command("finalize <entity-id>").description("Finalize formation and generate documents + cap table (staged flow step 3)").option("--authorized-shares <count>", "Authorized shares for corporations").option("--par-value <value>", "Par value per share, e.g. 0.0001").option("--board-size <count>", "Board size for corporations").option("--principal-name <name>", "Principal or manager name for LLCs").option("--registered-agent-name <name>", "Registered agent legal name").option("--registered-agent-address <address>", "Registered agent address line").option("--formation-date <date>", "Formation date (RFC3339 or YYYY-MM-DD)").option("--fiscal-year-end <date>", "Fiscal year end (MM-DD)").option("--s-corp", "Elect S-Corp status").option("--transfer-restrictions", "Enable transfer restrictions").option("--rofr", "Enable right of first refusal").option("--company-address <address>", "Company address as 'street,city,state,zip'").option("--incorporator-name <name>", "Incorporator legal name (overrides founder)").option("--incorporator-address <address>", "Incorporator mailing address (overrides founder)").option("--json", "Output as JSON").option("--dry-run", "Show the request without finalizing formation").action(async (entityId, opts, cmd) => {
|
|
4808
5225
|
const { formFinalizeCommand: formFinalizeCommand2 } = await Promise.resolve().then(() => (init_form(), form_exports));
|
|
4809
|
-
await formFinalizeCommand2(entityId,
|
|
5226
|
+
await formFinalizeCommand2(entityId, {
|
|
5227
|
+
...opts,
|
|
5228
|
+
json: inheritOption(opts.json, cmd.parent.opts().json),
|
|
5229
|
+
dryRun: inheritOption(opts.dryRun, cmd.parent.opts().dryRun)
|
|
5230
|
+
});
|
|
4810
5231
|
});
|
|
4811
5232
|
program.command("api-keys").description("List API keys").option("--json", "Output as JSON").action(async (opts) => {
|
|
4812
5233
|
const { apiKeysCommand: apiKeysCommand2 } = await Promise.resolve().then(() => (init_api_keys(), api_keys_exports));
|
|
@@ -4824,5 +5245,5 @@ program.command("serve").description("Start the API server locally").option("--p
|
|
|
4824
5245
|
const { serveCommand: serveCommand2 } = await Promise.resolve().then(() => (init_serve(), serve_exports));
|
|
4825
5246
|
await serveCommand2(opts);
|
|
4826
5247
|
});
|
|
4827
|
-
program.
|
|
5248
|
+
await program.parseAsync(process.argv);
|
|
4828
5249
|
//# sourceMappingURL=index.js.map
|