@fairmint/captable-ai 0.1.40 → 0.1.41
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 +21 -0
- package/dist/index.js +305 -113
- package/package.json +2 -5
- package/dist/index.d.ts +0 -1
package/README.md
CHANGED
|
@@ -94,6 +94,7 @@ automated, but a few habits make extraction faster and more accurate:
|
|
|
94
94
|
| `documents upload\|list\|download\|delete` | Manage source documents |
|
|
95
95
|
| `documents trigger-extraction\|cancel-extraction\|restart-extraction\|reprocess` | Control the OCF extraction pipeline |
|
|
96
96
|
| `documents processing-status\|classification-types\|classification-update` | Inspect document status / classification |
|
|
97
|
+
| `agreements list\|download` | Signed investment and grant agreements, one-hour download links |
|
|
97
98
|
| `objects list\|get\|dump\|update\|patch\|revert\|versions\|delete` | Work with extracted OCF objects (`list` supports `--document`, `--stakeholder`, `--all`, `--max-confidence`; `dump` writes engine-shaped `ocf.json`) |
|
|
98
99
|
| `schemas list\|get` | Browse the OCF object-type registry |
|
|
99
100
|
| `commit` | Commit drafts to the cap table — `--all` or `--objects id1,id2` (`--dry-run` to preview) |
|
|
@@ -111,6 +112,26 @@ automated, but a few habits make extraction faster and more accurate:
|
|
|
111
112
|
Run `captable-ai <command> --help` for full usage, or `captable-ai commands --json` for the
|
|
112
113
|
authoritative machine-readable list.
|
|
113
114
|
|
|
115
|
+
## Signed agreements
|
|
116
|
+
|
|
117
|
+
`documents list` holds what the extraction pipeline ingested. Signed agreements are
|
|
118
|
+
listed separately, whether or not they were ingested:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
captable-ai agreements list # investments and grants, newest signed first
|
|
122
|
+
captable-ai agreements list --type grant --json
|
|
123
|
+
captable-ai agreements download grant:<awardId> # one-hour download link
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- **Investments** — the signed file of a SAFE (Send One SAFE, Community SAFE), custom
|
|
127
|
+
document, or legacy investment, once signed, whether or not payment is marked.
|
|
128
|
+
- **Grants** — Send One Grants both parties signed. The download is the agreement,
|
|
129
|
+
supporting documents, and both signature certificates. The grantee's tax form and
|
|
130
|
+
83(b) election are never included; download those from Studio.
|
|
131
|
+
|
|
132
|
+
Legacy grant agreements imported through the extraction pipeline stay under
|
|
133
|
+
`documents list` / `documents download`.
|
|
134
|
+
|
|
114
135
|
## Instrument registers
|
|
115
136
|
|
|
116
137
|
`captable-ai export` with no register is the full legal cap table: a multi-sheet Excel
|
package/dist/index.js
CHANGED
|
@@ -17013,6 +17013,37 @@ var securityholderFileResultSchema = external_exports.object({
|
|
|
17013
17013
|
s3Key: external_exports.string().describe("S3 object key.")
|
|
17014
17014
|
});
|
|
17015
17015
|
|
|
17016
|
+
// ../captable-ai-core/dist/signed-agreements.js
|
|
17017
|
+
var SIGNED_AGREEMENT_TYPES = ["investment", "grant"];
|
|
17018
|
+
var UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
17019
|
+
function isSignedAgreementType(value) {
|
|
17020
|
+
return value === "investment" || value === "grant";
|
|
17021
|
+
}
|
|
17022
|
+
var SIGNED_AGREEMENT_REF_PATTERN = new RegExp(`^(investment|grant):(${UUID})$`, "i");
|
|
17023
|
+
function parseSignedAgreementRef(ref) {
|
|
17024
|
+
const match = SIGNED_AGREEMENT_REF_PATTERN.exec(ref.trim());
|
|
17025
|
+
const type = match?.[1]?.toLowerCase();
|
|
17026
|
+
const id = match?.[2]?.toLowerCase();
|
|
17027
|
+
if (!type || !id || !isSignedAgreementType(type))
|
|
17028
|
+
return null;
|
|
17029
|
+
return { type, id };
|
|
17030
|
+
}
|
|
17031
|
+
var signedAgreementSchema = external_exports.object({
|
|
17032
|
+
ref: external_exports.string().describe("Pass to `agreements download`: investment:<s3AssetId> or grant:<awardId>."),
|
|
17033
|
+
type: external_exports.enum(SIGNED_AGREEMENT_TYPES).describe("investment or grant."),
|
|
17034
|
+
name: external_exports.string().describe("File name."),
|
|
17035
|
+
holder_name: external_exports.string().nullable().describe("Investor or grantee."),
|
|
17036
|
+
holder_email: external_exports.string().nullable().describe("Investor or grantee email."),
|
|
17037
|
+
offering: external_exports.string().nullable().describe("Series or fundraising title (investments); instrument (grants)."),
|
|
17038
|
+
status: external_exports.string().describe("Investment or award workflow status."),
|
|
17039
|
+
signed_on: external_exports.string().nullable().describe("Date the agreement was fully signed (YYYY-MM-DD)."),
|
|
17040
|
+
investment_id: external_exports.string().nullable().describe("investment.id, for investment agreements."),
|
|
17041
|
+
equity_award_id: external_exports.string().nullable().describe("equity_award.id, for grants.")
|
|
17042
|
+
});
|
|
17043
|
+
var signedAgreementListResultSchema = external_exports.object({
|
|
17044
|
+
items: external_exports.array(signedAgreementSchema).describe("Newest signed first.")
|
|
17045
|
+
});
|
|
17046
|
+
|
|
17016
17047
|
// ../captable-ai-core/dist/snapshot.js
|
|
17017
17048
|
var statusErrorSchema = external_exports.object({ message: external_exports.string() });
|
|
17018
17049
|
var statusWarningSchema = external_exports.object({
|
|
@@ -17738,6 +17769,223 @@ async function handleResponse(res, softFail = false) {
|
|
|
17738
17769
|
return parsed;
|
|
17739
17770
|
}
|
|
17740
17771
|
|
|
17772
|
+
// src/flags.ts
|
|
17773
|
+
function looksLikeFlag(value) {
|
|
17774
|
+
if (!value.startsWith("-")) return false;
|
|
17775
|
+
if (value === "-" || /^-\d+(?:\.\d+)?$/.test(value)) return false;
|
|
17776
|
+
return true;
|
|
17777
|
+
}
|
|
17778
|
+
function parseArgs(argv) {
|
|
17779
|
+
const positional = [];
|
|
17780
|
+
const positionalIndexes = [];
|
|
17781
|
+
const flags = {};
|
|
17782
|
+
const flagValueSources = {};
|
|
17783
|
+
const flagValueIndexes = {};
|
|
17784
|
+
const boolean4 = /* @__PURE__ */ new Set();
|
|
17785
|
+
let i = 0;
|
|
17786
|
+
while (i < argv.length) {
|
|
17787
|
+
const arg = argv[i];
|
|
17788
|
+
if (arg.startsWith("--")) {
|
|
17789
|
+
const eqIdx = arg.indexOf("=");
|
|
17790
|
+
if (eqIdx !== -1) {
|
|
17791
|
+
const key = arg.slice(2, eqIdx);
|
|
17792
|
+
flags[key] = arg.slice(eqIdx + 1);
|
|
17793
|
+
flagValueSources[key] = "equals";
|
|
17794
|
+
flagValueIndexes[key] = i;
|
|
17795
|
+
} else {
|
|
17796
|
+
const key = arg.slice(2);
|
|
17797
|
+
const next = argv[i + 1];
|
|
17798
|
+
if (next !== void 0 && !looksLikeFlag(next)) {
|
|
17799
|
+
flags[key] = next;
|
|
17800
|
+
flagValueSources[key] = "next";
|
|
17801
|
+
flagValueIndexes[key] = i + 1;
|
|
17802
|
+
i++;
|
|
17803
|
+
} else {
|
|
17804
|
+
boolean4.add(key);
|
|
17805
|
+
}
|
|
17806
|
+
}
|
|
17807
|
+
} else {
|
|
17808
|
+
positional.push(arg);
|
|
17809
|
+
positionalIndexes.push(i);
|
|
17810
|
+
}
|
|
17811
|
+
i++;
|
|
17812
|
+
}
|
|
17813
|
+
return { positional, positionalIndexes, flags, flagValueSources, flagValueIndexes, boolean: boolean4 };
|
|
17814
|
+
}
|
|
17815
|
+
function hasFlag(args, name) {
|
|
17816
|
+
return args.boolean.has(name) || name in args.flags;
|
|
17817
|
+
}
|
|
17818
|
+
function getFlagValue(args, name) {
|
|
17819
|
+
return args.flags[name];
|
|
17820
|
+
}
|
|
17821
|
+
function argvRequestsHelp(argv) {
|
|
17822
|
+
if (argv.includes("--help") || argv.includes("-h")) return true;
|
|
17823
|
+
return argv[0] === "help";
|
|
17824
|
+
}
|
|
17825
|
+
|
|
17826
|
+
// src/validate-flags.ts
|
|
17827
|
+
function restorePositional(args, value, originalIndex) {
|
|
17828
|
+
const insertAt = args.positionalIndexes.findIndex((index) => index > originalIndex);
|
|
17829
|
+
if (insertAt === -1) {
|
|
17830
|
+
args.positional.push(value);
|
|
17831
|
+
args.positionalIndexes.push(originalIndex);
|
|
17832
|
+
return;
|
|
17833
|
+
}
|
|
17834
|
+
args.positional.splice(insertAt, 0, value);
|
|
17835
|
+
args.positionalIndexes.splice(insertAt, 0, originalIndex);
|
|
17836
|
+
}
|
|
17837
|
+
function validateFlags(args, allowed) {
|
|
17838
|
+
const valueFlags = new Set(allowed.flags ?? []);
|
|
17839
|
+
const booleanFlags = new Set(allowed.booleans ?? []);
|
|
17840
|
+
const allAllowed = /* @__PURE__ */ new Set([...valueFlags, ...booleanFlags]);
|
|
17841
|
+
const allList = [...allAllowed].map((f) => `--${f}`).join(", ");
|
|
17842
|
+
for (const key of Object.keys(args.flags)) {
|
|
17843
|
+
if (!allAllowed.has(key)) {
|
|
17844
|
+
exitWithError(
|
|
17845
|
+
`Unknown flag: --${key}. Allowed flags: ${allList || "(none)"}`,
|
|
17846
|
+
"UNKNOWN_FLAG",
|
|
17847
|
+
void 0,
|
|
17848
|
+
EXIT.USAGE
|
|
17849
|
+
);
|
|
17850
|
+
}
|
|
17851
|
+
if (booleanFlags.has(key) && !valueFlags.has(key) && args.flagValueSources[key] === "next") {
|
|
17852
|
+
args.boolean.add(key);
|
|
17853
|
+
restorePositional(args, args.flags[key], args.flagValueIndexes[key]);
|
|
17854
|
+
delete args.flags[key];
|
|
17855
|
+
delete args.flagValueSources[key];
|
|
17856
|
+
delete args.flagValueIndexes[key];
|
|
17857
|
+
continue;
|
|
17858
|
+
}
|
|
17859
|
+
if (booleanFlags.has(key) && !valueFlags.has(key)) {
|
|
17860
|
+
exitWithError(
|
|
17861
|
+
`Flag --${key} does not take a value.`,
|
|
17862
|
+
"UNEXPECTED_FLAG_VALUE",
|
|
17863
|
+
void 0,
|
|
17864
|
+
EXIT.USAGE
|
|
17865
|
+
);
|
|
17866
|
+
}
|
|
17867
|
+
}
|
|
17868
|
+
for (const key of args.boolean) {
|
|
17869
|
+
if (valueFlags.has(key)) {
|
|
17870
|
+
exitWithError(`Flag --${key} requires a value.`, "MISSING_FLAG_VALUE", void 0, EXIT.USAGE);
|
|
17871
|
+
}
|
|
17872
|
+
if (!booleanFlags.has(key)) {
|
|
17873
|
+
exitWithError(
|
|
17874
|
+
`Unknown flag: --${key}. Allowed flags: ${allList || "(none)"}`,
|
|
17875
|
+
"UNKNOWN_FLAG",
|
|
17876
|
+
void 0,
|
|
17877
|
+
EXIT.USAGE
|
|
17878
|
+
);
|
|
17879
|
+
}
|
|
17880
|
+
}
|
|
17881
|
+
}
|
|
17882
|
+
|
|
17883
|
+
// src/commands/agreements.ts
|
|
17884
|
+
var LIST_USAGE = "Usage: captable-ai agreements list [--type investment|grant] [--json]";
|
|
17885
|
+
var DOWNLOAD_USAGE = "Usage: captable-ai agreements download <ref> [--json]";
|
|
17886
|
+
async function runAgreementsList(args, rawArgv) {
|
|
17887
|
+
if (argvRequestsHelp(rawArgv)) {
|
|
17888
|
+
process.stdout.write(
|
|
17889
|
+
`agreements list \u2014 List signed investment and grant agreements
|
|
17890
|
+
|
|
17891
|
+
${LIST_USAGE}
|
|
17892
|
+
|
|
17893
|
+
Investment agreements (SAFE, custom document, legacy) are listed once signed, paid or not.
|
|
17894
|
+
Grants are Send One Grants both parties signed. Pass a row's ref to \`agreements download\`.
|
|
17895
|
+
`
|
|
17896
|
+
);
|
|
17897
|
+
process.exit(0);
|
|
17898
|
+
}
|
|
17899
|
+
validateFlags(args, { flags: ["type"], booleans: [] });
|
|
17900
|
+
const type = getFlagValue(args, "type");
|
|
17901
|
+
if (type && !isSignedAgreementType(type)) {
|
|
17902
|
+
exitWithError(
|
|
17903
|
+
`--type must be one of: ${SIGNED_AGREEMENT_TYPES.join(", ")} (got: "${type}")`,
|
|
17904
|
+
"VALIDATION_FAILED",
|
|
17905
|
+
void 0,
|
|
17906
|
+
EXIT.VALIDATION
|
|
17907
|
+
);
|
|
17908
|
+
}
|
|
17909
|
+
const portalId = await getActivePortalId();
|
|
17910
|
+
const res = await apiRequest(`/${portalId}/agreements`);
|
|
17911
|
+
const items = (res.data?.items ?? []).filter((item) => !type || item.type === type);
|
|
17912
|
+
if (isJsonMode()) {
|
|
17913
|
+
printJson({ data: { items } });
|
|
17914
|
+
return;
|
|
17915
|
+
}
|
|
17916
|
+
if (items.length === 0) {
|
|
17917
|
+
printLine("No signed agreements found.");
|
|
17918
|
+
return;
|
|
17919
|
+
}
|
|
17920
|
+
printLine(`
|
|
17921
|
+
${items.length} signed agreement(s):
|
|
17922
|
+
`);
|
|
17923
|
+
printTable(
|
|
17924
|
+
items.map((item) => ({
|
|
17925
|
+
holder: item.holder_name ?? "\u2014",
|
|
17926
|
+
type: item.type,
|
|
17927
|
+
offering: item.offering ?? "\u2014",
|
|
17928
|
+
status: item.status,
|
|
17929
|
+
signed: item.signed_on ?? "\u2014",
|
|
17930
|
+
ref: item.ref
|
|
17931
|
+
})),
|
|
17932
|
+
[
|
|
17933
|
+
{ key: "holder", label: "Holder", width: 26 },
|
|
17934
|
+
{ key: "type", label: "Type", width: 10 },
|
|
17935
|
+
{ key: "offering", label: "Offering", width: 22 },
|
|
17936
|
+
{ key: "status", label: "Status", width: 14 },
|
|
17937
|
+
{ key: "signed", label: "Signed", width: 12 },
|
|
17938
|
+
{ key: "ref", label: "Ref" }
|
|
17939
|
+
]
|
|
17940
|
+
);
|
|
17941
|
+
printLine("\n Download one: captable-ai agreements download <ref>\n");
|
|
17942
|
+
}
|
|
17943
|
+
async function runAgreementsDownload(args, rawArgv) {
|
|
17944
|
+
if (argvRequestsHelp(rawArgv)) {
|
|
17945
|
+
process.stdout.write(
|
|
17946
|
+
`agreements download \u2014 Get a one-hour download URL for a signed agreement
|
|
17947
|
+
|
|
17948
|
+
${DOWNLOAD_USAGE}
|
|
17949
|
+
|
|
17950
|
+
ref is from \`agreements list\`: investment:<s3AssetId> or grant:<awardId>.
|
|
17951
|
+
A grant downloads as the agreement plus signature certificates; tax forms and
|
|
17952
|
+
83(b) elections are not included (download those from Studio).
|
|
17953
|
+
`
|
|
17954
|
+
);
|
|
17955
|
+
process.exit(0);
|
|
17956
|
+
}
|
|
17957
|
+
validateFlags(args, { flags: [], booleans: [] });
|
|
17958
|
+
if (args.positional.length !== 1) {
|
|
17959
|
+
exitWithUsage("Expected exactly one agreement ref.", DOWNLOAD_USAGE);
|
|
17960
|
+
}
|
|
17961
|
+
const ref = args.positional[0].trim();
|
|
17962
|
+
if (!parseSignedAgreementRef(ref)) {
|
|
17963
|
+
exitWithUsage(
|
|
17964
|
+
`Invalid ref "${ref}". Expected investment:<s3AssetId> or grant:<awardId> from \`agreements list\`.`,
|
|
17965
|
+
DOWNLOAD_USAGE
|
|
17966
|
+
);
|
|
17967
|
+
}
|
|
17968
|
+
const portalId = await getActivePortalId();
|
|
17969
|
+
const res = await apiRequest(
|
|
17970
|
+
`/${portalId}/agreements/${encodeURIComponent(ref)}/download`
|
|
17971
|
+
);
|
|
17972
|
+
if (isJsonMode()) {
|
|
17973
|
+
printJson({ data: res.data });
|
|
17974
|
+
return;
|
|
17975
|
+
}
|
|
17976
|
+
const d = res.data;
|
|
17977
|
+
if (!d?.downloadUrl || !d.filename || !d.expiresAt) {
|
|
17978
|
+
exitWithError("Download URL generation failed.", "ERROR", void 0, EXIT.SERVER_ERROR);
|
|
17979
|
+
}
|
|
17980
|
+
printLine("\n Agreement download URL generated.\n");
|
|
17981
|
+
printKeyValue([
|
|
17982
|
+
["Download URL", d.downloadUrl],
|
|
17983
|
+
["Filename", d.filename],
|
|
17984
|
+
["Expires at", d.expiresAt]
|
|
17985
|
+
]);
|
|
17986
|
+
printLine();
|
|
17987
|
+
}
|
|
17988
|
+
|
|
17741
17989
|
// src/auth/refresh-portals.ts
|
|
17742
17990
|
var PORTALS_TTL_MS = 3e5;
|
|
17743
17991
|
var REQUEST_TIMEOUT_MS2 = 1e4;
|
|
@@ -17809,63 +18057,6 @@ async function refreshCachedPortalNames() {
|
|
|
17809
18057
|
}
|
|
17810
18058
|
}
|
|
17811
18059
|
|
|
17812
|
-
// src/validate-flags.ts
|
|
17813
|
-
function restorePositional(args, value, originalIndex) {
|
|
17814
|
-
const insertAt = args.positionalIndexes.findIndex((index) => index > originalIndex);
|
|
17815
|
-
if (insertAt === -1) {
|
|
17816
|
-
args.positional.push(value);
|
|
17817
|
-
args.positionalIndexes.push(originalIndex);
|
|
17818
|
-
return;
|
|
17819
|
-
}
|
|
17820
|
-
args.positional.splice(insertAt, 0, value);
|
|
17821
|
-
args.positionalIndexes.splice(insertAt, 0, originalIndex);
|
|
17822
|
-
}
|
|
17823
|
-
function validateFlags(args, allowed) {
|
|
17824
|
-
const valueFlags = new Set(allowed.flags ?? []);
|
|
17825
|
-
const booleanFlags = new Set(allowed.booleans ?? []);
|
|
17826
|
-
const allAllowed = /* @__PURE__ */ new Set([...valueFlags, ...booleanFlags]);
|
|
17827
|
-
const allList = [...allAllowed].map((f) => `--${f}`).join(", ");
|
|
17828
|
-
for (const key of Object.keys(args.flags)) {
|
|
17829
|
-
if (!allAllowed.has(key)) {
|
|
17830
|
-
exitWithError(
|
|
17831
|
-
`Unknown flag: --${key}. Allowed flags: ${allList || "(none)"}`,
|
|
17832
|
-
"UNKNOWN_FLAG",
|
|
17833
|
-
void 0,
|
|
17834
|
-
EXIT.USAGE
|
|
17835
|
-
);
|
|
17836
|
-
}
|
|
17837
|
-
if (booleanFlags.has(key) && !valueFlags.has(key) && args.flagValueSources[key] === "next") {
|
|
17838
|
-
args.boolean.add(key);
|
|
17839
|
-
restorePositional(args, args.flags[key], args.flagValueIndexes[key]);
|
|
17840
|
-
delete args.flags[key];
|
|
17841
|
-
delete args.flagValueSources[key];
|
|
17842
|
-
delete args.flagValueIndexes[key];
|
|
17843
|
-
continue;
|
|
17844
|
-
}
|
|
17845
|
-
if (booleanFlags.has(key) && !valueFlags.has(key)) {
|
|
17846
|
-
exitWithError(
|
|
17847
|
-
`Flag --${key} does not take a value.`,
|
|
17848
|
-
"UNEXPECTED_FLAG_VALUE",
|
|
17849
|
-
void 0,
|
|
17850
|
-
EXIT.USAGE
|
|
17851
|
-
);
|
|
17852
|
-
}
|
|
17853
|
-
}
|
|
17854
|
-
for (const key of args.boolean) {
|
|
17855
|
-
if (valueFlags.has(key)) {
|
|
17856
|
-
exitWithError(`Flag --${key} requires a value.`, "MISSING_FLAG_VALUE", void 0, EXIT.USAGE);
|
|
17857
|
-
}
|
|
17858
|
-
if (!booleanFlags.has(key)) {
|
|
17859
|
-
exitWithError(
|
|
17860
|
-
`Unknown flag: --${key}. Allowed flags: ${allList || "(none)"}`,
|
|
17861
|
-
"UNKNOWN_FLAG",
|
|
17862
|
-
void 0,
|
|
17863
|
-
EXIT.USAGE
|
|
17864
|
-
);
|
|
17865
|
-
}
|
|
17866
|
-
}
|
|
17867
|
-
}
|
|
17868
|
-
|
|
17869
18060
|
// src/commands/auth-status.ts
|
|
17870
18061
|
async function runAuthStatus(args) {
|
|
17871
18062
|
validateFlags(args, { flags: [], booleans: [] });
|
|
@@ -17913,62 +18104,6 @@ async function runAuthStatus(args) {
|
|
|
17913
18104
|
|
|
17914
18105
|
// src/commands/export.ts
|
|
17915
18106
|
import { renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
17916
|
-
|
|
17917
|
-
// src/flags.ts
|
|
17918
|
-
function looksLikeFlag(value) {
|
|
17919
|
-
if (!value.startsWith("-")) return false;
|
|
17920
|
-
if (value === "-" || /^-\d+(?:\.\d+)?$/.test(value)) return false;
|
|
17921
|
-
return true;
|
|
17922
|
-
}
|
|
17923
|
-
function parseArgs(argv) {
|
|
17924
|
-
const positional = [];
|
|
17925
|
-
const positionalIndexes = [];
|
|
17926
|
-
const flags = {};
|
|
17927
|
-
const flagValueSources = {};
|
|
17928
|
-
const flagValueIndexes = {};
|
|
17929
|
-
const boolean4 = /* @__PURE__ */ new Set();
|
|
17930
|
-
let i = 0;
|
|
17931
|
-
while (i < argv.length) {
|
|
17932
|
-
const arg = argv[i];
|
|
17933
|
-
if (arg.startsWith("--")) {
|
|
17934
|
-
const eqIdx = arg.indexOf("=");
|
|
17935
|
-
if (eqIdx !== -1) {
|
|
17936
|
-
const key = arg.slice(2, eqIdx);
|
|
17937
|
-
flags[key] = arg.slice(eqIdx + 1);
|
|
17938
|
-
flagValueSources[key] = "equals";
|
|
17939
|
-
flagValueIndexes[key] = i;
|
|
17940
|
-
} else {
|
|
17941
|
-
const key = arg.slice(2);
|
|
17942
|
-
const next = argv[i + 1];
|
|
17943
|
-
if (next !== void 0 && !looksLikeFlag(next)) {
|
|
17944
|
-
flags[key] = next;
|
|
17945
|
-
flagValueSources[key] = "next";
|
|
17946
|
-
flagValueIndexes[key] = i + 1;
|
|
17947
|
-
i++;
|
|
17948
|
-
} else {
|
|
17949
|
-
boolean4.add(key);
|
|
17950
|
-
}
|
|
17951
|
-
}
|
|
17952
|
-
} else {
|
|
17953
|
-
positional.push(arg);
|
|
17954
|
-
positionalIndexes.push(i);
|
|
17955
|
-
}
|
|
17956
|
-
i++;
|
|
17957
|
-
}
|
|
17958
|
-
return { positional, positionalIndexes, flags, flagValueSources, flagValueIndexes, boolean: boolean4 };
|
|
17959
|
-
}
|
|
17960
|
-
function hasFlag(args, name) {
|
|
17961
|
-
return args.boolean.has(name) || name in args.flags;
|
|
17962
|
-
}
|
|
17963
|
-
function getFlagValue(args, name) {
|
|
17964
|
-
return args.flags[name];
|
|
17965
|
-
}
|
|
17966
|
-
function argvRequestsHelp(argv) {
|
|
17967
|
-
if (argv.includes("--help") || argv.includes("-h")) return true;
|
|
17968
|
-
return argv[0] === "help";
|
|
17969
|
-
}
|
|
17970
|
-
|
|
17971
|
-
// src/commands/export.ts
|
|
17972
18107
|
var EXPORT_USAGE = "captable-ai export [--as-of YYYY-MM-DD] [--show-empty-fields] [--json]";
|
|
17973
18108
|
var EXPORT_REGISTER_USAGE = "captable-ai export <stock|grants|warrants|convertibles> [--include-pending] [--as-of YYYY-MM-DD] [--csv | --json] [--output <path>]";
|
|
17974
18109
|
var EXPORT_CONVERTIBLES_USAGE = "captable-ai export convertibles [--type SAFE|NOTE] [--include-pending] [--as-of YYYY-MM-DD] [--csv | --json] [--output <path>]";
|
|
@@ -18807,6 +18942,30 @@ var COMMAND_REGISTRY = [
|
|
|
18807
18942
|
requiresAuth: true,
|
|
18808
18943
|
requiresPortal: true
|
|
18809
18944
|
},
|
|
18945
|
+
{
|
|
18946
|
+
name: "agreements list",
|
|
18947
|
+
group: "captable",
|
|
18948
|
+
description: "List signed agreements: investment agreements (SAFE, custom document, legacy) once signed, paid or not, and Send One Grants both parties signed. Each row has a ref for `agreements download`.",
|
|
18949
|
+
usage: "captable-ai agreements list [--type investment|grant] [--json]",
|
|
18950
|
+
requiresAuth: true,
|
|
18951
|
+
requiresPortal: true,
|
|
18952
|
+
flags: [
|
|
18953
|
+
{
|
|
18954
|
+
name: "type",
|
|
18955
|
+
description: "Only investment or grant agreements.",
|
|
18956
|
+
type: "string",
|
|
18957
|
+
enum: ["investment", "grant"]
|
|
18958
|
+
}
|
|
18959
|
+
]
|
|
18960
|
+
},
|
|
18961
|
+
{
|
|
18962
|
+
name: "agreements download",
|
|
18963
|
+
group: "captable",
|
|
18964
|
+
description: "Get a one-hour download URL for a signed agreement by its ref (investment:<s3AssetId> or grant:<awardId>). A grant downloads as the agreement plus signature certificates, without tax forms or 83(b) elections.",
|
|
18965
|
+
usage: "captable-ai agreements download <ref> [--json]",
|
|
18966
|
+
requiresAuth: true,
|
|
18967
|
+
requiresPortal: true
|
|
18968
|
+
},
|
|
18810
18969
|
{
|
|
18811
18970
|
name: "documents trigger-extraction",
|
|
18812
18971
|
group: "captable",
|
|
@@ -24281,6 +24440,7 @@ var VERSION = (() => {
|
|
|
24281
24440
|
return "0.0.0";
|
|
24282
24441
|
})();
|
|
24283
24442
|
var PROFILE_AWARE_COMMANDS = /* @__PURE__ */ new Set([
|
|
24443
|
+
"agreements",
|
|
24284
24444
|
"commit",
|
|
24285
24445
|
"company",
|
|
24286
24446
|
"documents",
|
|
@@ -24372,6 +24532,12 @@ Documents:
|
|
|
24372
24532
|
documents delete <id> Delete an uploaded document and all associated artifacts
|
|
24373
24533
|
documents download <id> Get a presigned download URL for a document
|
|
24374
24534
|
|
|
24535
|
+
Signed Agreements:
|
|
24536
|
+
agreements list List signed investment and grant agreements
|
|
24537
|
+
Filter: --type investment|grant
|
|
24538
|
+
agreements download <ref> Get a one-hour download URL for one agreement
|
|
24539
|
+
Grants: agreement + signature certificates, no tax forms
|
|
24540
|
+
|
|
24375
24541
|
Agent Logs (Fairmint super-admin only):
|
|
24376
24542
|
logs list List OCF agent log entries (expert/validator runs)
|
|
24377
24543
|
Options: --agent-type expert|validator, --limit N, --cursor C
|
|
@@ -24850,6 +25016,32 @@ async function main() {
|
|
|
24850
25016
|
);
|
|
24851
25017
|
}
|
|
24852
25018
|
break;
|
|
25019
|
+
case "agreements":
|
|
25020
|
+
if (isHelpToken(sub)) {
|
|
25021
|
+
process.stdout.write(
|
|
25022
|
+
"agreements \u2014 List and download signed investment and grant agreements\n\nSubcommands: list, download\nRun: captable-ai agreements <subcommand> --help\n"
|
|
25023
|
+
);
|
|
25024
|
+
process.exit(0);
|
|
25025
|
+
}
|
|
25026
|
+
switch (sub) {
|
|
25027
|
+
case "list":
|
|
25028
|
+
await runAgreementsList(parseArgs(positionalArgs.slice(2)), positionalArgs.slice(2));
|
|
25029
|
+
break;
|
|
25030
|
+
case "download":
|
|
25031
|
+
await runAgreementsDownload(
|
|
25032
|
+
parseArgs(positionalArgs.slice(2)),
|
|
25033
|
+
positionalArgs.slice(2)
|
|
25034
|
+
);
|
|
25035
|
+
break;
|
|
25036
|
+
default:
|
|
25037
|
+
exitWithError(
|
|
25038
|
+
`Unknown agreements command: ${sub ?? "(none)"}. Try: agreements list | download`,
|
|
25039
|
+
"UNKNOWN_COMMAND",
|
|
25040
|
+
void 0,
|
|
25041
|
+
EXIT.USAGE
|
|
25042
|
+
);
|
|
25043
|
+
}
|
|
25044
|
+
break;
|
|
24853
25045
|
case "logs":
|
|
24854
25046
|
if (isHelpToken(sub)) {
|
|
24855
25047
|
process.stdout.write(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fairmint/captable-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.41",
|
|
4
4
|
"description": "Agent-native CLI for Captable AI — manage companies, upload documents, run OCF extraction, and commit cap tables from the terminal.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"captable",
|
|
@@ -27,12 +27,10 @@
|
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
".": {
|
|
30
|
-
"types": "./dist/index.d.ts",
|
|
31
30
|
"import": "./dist/index.js",
|
|
32
31
|
"default": "./dist/index.js"
|
|
33
32
|
}
|
|
34
33
|
},
|
|
35
|
-
"types": "./dist/index.d.ts",
|
|
36
34
|
"files": [
|
|
37
35
|
"dist"
|
|
38
36
|
],
|
|
@@ -53,7 +51,6 @@
|
|
|
53
51
|
"devDependencies": {
|
|
54
52
|
"@captable-ai/core": "workspace:*",
|
|
55
53
|
"@types/node": "25.5.2",
|
|
56
|
-
"tsup": "8.5.1"
|
|
57
|
-
"typescript": "6.0.2"
|
|
54
|
+
"tsup": "8.5.1"
|
|
58
55
|
}
|
|
59
56
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|