@fairmint/captable-ai 0.1.34 → 0.1.35
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 +136 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15355,10 +15355,82 @@ function planImportStatus({ documents, sessionState, scopeUnknown = false }) {
|
|
|
15355
15355
|
}
|
|
15356
15356
|
}
|
|
15357
15357
|
}
|
|
15358
|
-
|
|
15359
|
-
|
|
15358
|
+
var IMPORT_REVIEW_MAX_IDS = 50;
|
|
15359
|
+
function reviewIsCut(action) {
|
|
15360
|
+
return action.reviewObjectIds !== void 0 && action.s3AssetIds?.length !== 1 && action.reviewObjectIds.length > IMPORT_REVIEW_MAX_IDS;
|
|
15361
|
+
}
|
|
15362
|
+
function isFileRecordRow(draft) {
|
|
15363
|
+
return draft.type === "DOCUMENT" || draft.subtype === "DOCUMENT";
|
|
15364
|
+
}
|
|
15365
|
+
function partitionImportDrafts(drafts, documentIds) {
|
|
15366
|
+
if (documentIds.length === 0)
|
|
15367
|
+
return null;
|
|
15368
|
+
const documents = new Set(documentIds.map((id) => id.toLowerCase()));
|
|
15369
|
+
const importDraftIds = [];
|
|
15370
|
+
const importReviewableIds = [];
|
|
15371
|
+
const portalIssuerDraftIds = [];
|
|
15372
|
+
let otherDrafts = false;
|
|
15373
|
+
for (const draft of drafts) {
|
|
15374
|
+
if (typeof draft.id !== "string" || draft.id.length === 0)
|
|
15375
|
+
return null;
|
|
15376
|
+
if (!("documentId" in draft))
|
|
15377
|
+
return null;
|
|
15378
|
+
const ours = typeof draft.documentId === "string" && documents.has(draft.documentId.toLowerCase());
|
|
15379
|
+
const selectable = !draft.id.includes(",") && draft.id === draft.id.trim();
|
|
15380
|
+
if (!ours) {
|
|
15381
|
+
if (draft.type === "ISSUER" && draft.documentId === null) {
|
|
15382
|
+
if (!selectable)
|
|
15383
|
+
return null;
|
|
15384
|
+
portalIssuerDraftIds.push(draft.id);
|
|
15385
|
+
} else {
|
|
15386
|
+
otherDrafts = true;
|
|
15387
|
+
}
|
|
15388
|
+
continue;
|
|
15389
|
+
}
|
|
15390
|
+
if (!selectable)
|
|
15391
|
+
return null;
|
|
15392
|
+
importDraftIds.push(draft.id);
|
|
15393
|
+
if (!isFileRecordRow(draft))
|
|
15394
|
+
importReviewableIds.push(draft.id);
|
|
15395
|
+
}
|
|
15396
|
+
return { importDraftIds, importReviewableIds, portalIssuerDraftIds, otherDrafts };
|
|
15397
|
+
}
|
|
15398
|
+
function applyImportDrafts(plan, scope, documentIds) {
|
|
15399
|
+
if (plan.phase !== "complete" || scope === null)
|
|
15400
|
+
return plan;
|
|
15401
|
+
if (scope.importReviewableIds.length === 0) {
|
|
15402
|
+
return {
|
|
15403
|
+
...plan,
|
|
15404
|
+
state: "complete",
|
|
15405
|
+
actions: [],
|
|
15406
|
+
...scope.otherDrafts ? { unrelatedDrafts: true } : {}
|
|
15407
|
+
};
|
|
15408
|
+
}
|
|
15409
|
+
if (!scope.otherDrafts)
|
|
15360
15410
|
return plan;
|
|
15361
|
-
|
|
15411
|
+
const selection = [...scope.importDraftIds, ...scope.portalIssuerDraftIds];
|
|
15412
|
+
const scoped = (action) => {
|
|
15413
|
+
const base = { ...action, objectIds: selection };
|
|
15414
|
+
switch (action.id) {
|
|
15415
|
+
case "review_drafts":
|
|
15416
|
+
return {
|
|
15417
|
+
...base,
|
|
15418
|
+
label: "Review the drafts from this import's documents",
|
|
15419
|
+
s3AssetIds: [...documentIds],
|
|
15420
|
+
reviewObjectIds: scope.importReviewableIds
|
|
15421
|
+
};
|
|
15422
|
+
case "preview_commit":
|
|
15423
|
+
return { ...base, label: "Preview committing this import's drafts" };
|
|
15424
|
+
case "confirm_commit":
|
|
15425
|
+
return {
|
|
15426
|
+
...base,
|
|
15427
|
+
label: "Commit this import's drafts with the preview's final IDs as objectIds. Not allDrafts: the portal also has pending drafts from other sources"
|
|
15428
|
+
};
|
|
15429
|
+
default:
|
|
15430
|
+
return action;
|
|
15431
|
+
}
|
|
15432
|
+
};
|
|
15433
|
+
return { ...plan, actions: plan.actions.map(scoped) };
|
|
15362
15434
|
}
|
|
15363
15435
|
var EXTRACTION_NOT_READY_REASONS = [
|
|
15364
15436
|
"pending_upload",
|
|
@@ -23031,7 +23103,16 @@ async function runImportStart(args) {
|
|
|
23031
23103
|
function scopeFlag(ids) {
|
|
23032
23104
|
return ids && ids.length > 0 ? ` --s3-asset-ids ${ids.join(",")}` : "";
|
|
23033
23105
|
}
|
|
23106
|
+
var CLI_SELECTION_MAX_BYTES = 1e5;
|
|
23034
23107
|
function importStatusCommand(action, sessionId) {
|
|
23108
|
+
const tooManyToSelect = (action.id === "preview_commit" || action.id === "confirm_commit") && action.objectIds !== void 0 && Buffer.byteLength(`--objects=${action.objectIds.join(",")}`, "utf8") > CLI_SELECTION_MAX_BYTES;
|
|
23109
|
+
if (tooManyToSelect) {
|
|
23110
|
+
return {
|
|
23111
|
+
id: action.id,
|
|
23112
|
+
label: `This import has ${action.objectIds?.length ?? 0} drafts, too many to select on one command line. Commit them from the Studio timeline, or with the MCP. Not --all: the portal also has pending drafts from other sources.`,
|
|
23113
|
+
required: action.required
|
|
23114
|
+
};
|
|
23115
|
+
}
|
|
23035
23116
|
const command = (() => {
|
|
23036
23117
|
switch (action.id) {
|
|
23037
23118
|
case "upload_documents":
|
|
@@ -23048,12 +23129,19 @@ function importStatusCommand(action, sessionId) {
|
|
|
23048
23129
|
return "captable-ai documents list";
|
|
23049
23130
|
case "review_failures":
|
|
23050
23131
|
return action.statusFilter ? `captable-ai documents list --status ${action.statusFilter}` : "captable-ai documents list";
|
|
23051
|
-
case "review_drafts":
|
|
23052
|
-
return "captable-ai objects list --status draft --all";
|
|
23132
|
+
case "review_drafts": {
|
|
23133
|
+
if (!action.objectIds) return "captable-ai objects list --status draft --all";
|
|
23134
|
+
const [onlyDocument, ...moreDocuments] = action.s3AssetIds ?? [];
|
|
23135
|
+
if (onlyDocument !== void 0 && moreDocuments.length === 0) {
|
|
23136
|
+
return `captable-ai objects list --status draft --document ${shellQuote(onlyDocument)} --all`;
|
|
23137
|
+
}
|
|
23138
|
+
const reviewable = (action.reviewObjectIds ?? []).slice(0, IMPORT_REVIEW_MAX_IDS);
|
|
23139
|
+
return `captable-ai objects list --status draft --ids=${shellQuote(reviewable.join(","))}`;
|
|
23140
|
+
}
|
|
23053
23141
|
case "preview_commit":
|
|
23054
|
-
return "captable-ai commit --dry-run";
|
|
23142
|
+
return action.objectIds ? `captable-ai commit --dry-run --objects=${shellQuote(action.objectIds.join(","))}` : "captable-ai commit --dry-run";
|
|
23055
23143
|
case "confirm_commit":
|
|
23056
|
-
return "captable-ai commit --all";
|
|
23144
|
+
return action.objectIds ? "captable-ai commit --objects <final IDs from the dry run>" : "captable-ai commit --all";
|
|
23057
23145
|
default: {
|
|
23058
23146
|
const unhandled = action.id;
|
|
23059
23147
|
throw new Error(`Unhandled import status action: ${String(unhandled)}`);
|
|
@@ -23063,35 +23151,40 @@ function importStatusCommand(action, sessionId) {
|
|
|
23063
23151
|
const id = action.id === "upload_documents" ? "upload_cli" : action.id;
|
|
23064
23152
|
return {
|
|
23065
23153
|
id,
|
|
23066
|
-
label: action.label,
|
|
23154
|
+
label: action.id === "review_drafts" && reviewIsCut(action) ? `${action.label} (first ${IMPORT_REVIEW_MAX_IDS} of ${action.reviewObjectIds?.length ?? 0})` : action.label,
|
|
23067
23155
|
required: action.required,
|
|
23068
23156
|
command,
|
|
23069
23157
|
...action.id === "review_failures" && action.s3AssetIds && { s3AssetIds: action.s3AssetIds }
|
|
23070
23158
|
};
|
|
23071
23159
|
}
|
|
23072
|
-
var
|
|
23073
|
-
async function
|
|
23160
|
+
var DRAFT_SCOPE_MAX_PAGES = 100;
|
|
23161
|
+
async function readImportDraftScope(portalId, documentIds) {
|
|
23074
23162
|
if (!portalId) return null;
|
|
23075
23163
|
try {
|
|
23076
|
-
|
|
23164
|
+
const drafts = [];
|
|
23077
23165
|
let cursor;
|
|
23078
|
-
for (let page = 0; page <
|
|
23166
|
+
for (let page = 0; page < DRAFT_SCOPE_MAX_PAGES; page += 1) {
|
|
23079
23167
|
const res = await apiRequest(
|
|
23080
23168
|
`/${encodeURIComponent(portalId)}/objects`,
|
|
23081
23169
|
{
|
|
23082
|
-
query: { status: "draft", ...cursor ? { cursor } : {} },
|
|
23170
|
+
query: { status: "draft", limit: 250, ...cursor ? { cursor } : {} },
|
|
23083
23171
|
// Optional read: throw (caught below) instead of exiting the process on a failure.
|
|
23084
23172
|
softFail: true
|
|
23085
23173
|
}
|
|
23086
23174
|
);
|
|
23087
23175
|
const objects = res.data?.objects;
|
|
23088
23176
|
if (!Array.isArray(objects)) return null;
|
|
23089
|
-
|
|
23090
|
-
(
|
|
23091
|
-
|
|
23092
|
-
|
|
23177
|
+
for (const obj of objects) {
|
|
23178
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) return null;
|
|
23179
|
+
drafts.push({
|
|
23180
|
+
id: Reflect.get(obj, "id"),
|
|
23181
|
+
type: Reflect.get(obj, "type"),
|
|
23182
|
+
subtype: Reflect.get(obj, "subtype"),
|
|
23183
|
+
..."documentId" in obj ? { documentId: Reflect.get(obj, "documentId") } : {}
|
|
23184
|
+
});
|
|
23185
|
+
}
|
|
23186
|
+
if (!res.meta?.hasMore) return partitionImportDrafts(drafts, documentIds);
|
|
23093
23187
|
const next = res.meta?.cursor;
|
|
23094
|
-
if (!res.meta?.hasMore) return count;
|
|
23095
23188
|
if (!next || next === cursor) return null;
|
|
23096
23189
|
cursor = next;
|
|
23097
23190
|
}
|
|
@@ -23114,12 +23207,19 @@ async function runImportStatus(args) {
|
|
|
23114
23207
|
);
|
|
23115
23208
|
const portalDocuments = response.data?.processing?.documents ?? [];
|
|
23116
23209
|
const documents = documentsForImportSession(portalDocuments, response.data?.session?.createdAt);
|
|
23210
|
+
const documentIds = documents.flatMap(
|
|
23211
|
+
(document) => typeof document.s3AssetId === "string" ? [document.s3AssetId] : []
|
|
23212
|
+
);
|
|
23117
23213
|
const documentPlan = planImportStatus({
|
|
23118
23214
|
documents,
|
|
23119
23215
|
sessionState: response.data?.session?.state,
|
|
23120
23216
|
scopeUnknown: importSessionScopeUnknown(portalDocuments)
|
|
23121
23217
|
});
|
|
23122
|
-
const plan = documentPlan.phase === "complete" ?
|
|
23218
|
+
const plan = documentPlan.phase === "complete" ? applyImportDrafts(
|
|
23219
|
+
documentPlan,
|
|
23220
|
+
await readImportDraftScope(response.data?.session?.portalId, documentIds),
|
|
23221
|
+
documentIds
|
|
23222
|
+
) : documentPlan;
|
|
23123
23223
|
const { summary } = plan;
|
|
23124
23224
|
if (plan.shouldComplete) {
|
|
23125
23225
|
const completed = await apiRequest(
|
|
@@ -23141,6 +23241,7 @@ async function runImportStatus(args) {
|
|
|
23141
23241
|
phase: plan.phase,
|
|
23142
23242
|
summary,
|
|
23143
23243
|
nextActions,
|
|
23244
|
+
...plan.unrelatedDrafts && { unrelatedDrafts: true },
|
|
23144
23245
|
...suggestMonitoring && { monitoringHint: BACKGROUND_MONITORING_SUGGESTION }
|
|
23145
23246
|
};
|
|
23146
23247
|
if (isJsonMode()) {
|
|
@@ -23165,12 +23266,28 @@ async function runImportStatus(args) {
|
|
|
23165
23266
|
" Some uploads never finished. Re-upload them; checking status again will not complete them."
|
|
23166
23267
|
);
|
|
23167
23268
|
}
|
|
23269
|
+
if (plan.unrelatedDrafts) {
|
|
23270
|
+
printLine(
|
|
23271
|
+
" The portal has other pending drafts that this import did not produce; leave them alone unless asked."
|
|
23272
|
+
);
|
|
23273
|
+
}
|
|
23274
|
+
const scopedCommit = plan.actions.some(
|
|
23275
|
+
(planned) => planned.id === "confirm_commit" && planned.objectIds !== void 0
|
|
23276
|
+
);
|
|
23168
23277
|
for (const action of nextActions) {
|
|
23278
|
+
if (action.command === void 0) {
|
|
23279
|
+
printLine(` Note: ${action.label}`);
|
|
23280
|
+
continue;
|
|
23281
|
+
}
|
|
23169
23282
|
printLine(` Next: ${action.command}`);
|
|
23170
23283
|
if (action.id === "resolve_extraction_scope") printLine(` Note: ${action.label}`);
|
|
23171
23284
|
if (action.id === "check_status" && plan.phase === "empty") {
|
|
23172
23285
|
printLine(` Note: ${action.label}`);
|
|
23173
23286
|
}
|
|
23287
|
+
if (action.id === "confirm_commit" && scopedCommit) printLine(` Note: ${action.label}`);
|
|
23288
|
+
if (action.id === "review_drafts" && action.label.includes("(first ")) {
|
|
23289
|
+
printLine(` Note: ${action.label}`);
|
|
23290
|
+
}
|
|
23174
23291
|
if (action.id === "review_failures" && action.s3AssetIds) {
|
|
23175
23292
|
printLine(` Documents: ${action.s3AssetIds.join(", ")}`);
|
|
23176
23293
|
}
|
package/package.json
CHANGED