@fairmint/captable-ai 0.1.29 → 0.1.31

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.
Files changed (2) hide show
  1. package/dist/index.js +69 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15355,6 +15355,11 @@ function planImportStatus({ documents, sessionState, scopeUnknown = false }) {
15355
15355
  }
15356
15356
  }
15357
15357
  }
15358
+ function applyDraftCount(plan, draftCount) {
15359
+ if (plan.phase !== "complete" || draftCount !== 0)
15360
+ return plan;
15361
+ return { ...plan, state: "complete", actions: [] };
15362
+ }
15358
15363
  var EXTRACTION_NOT_READY_REASONS = [
15359
15364
  "pending_upload",
15360
15365
  "classification_in_progress"
@@ -15527,6 +15532,7 @@ var DOCUMENT_HEALTH_VALUES = [
15527
15532
  ];
15528
15533
  var documentProcessingStatusItemSchema = external_exports.object({
15529
15534
  s3AssetId: external_exports.string().describe("S3 asset / document ID."),
15535
+ name: external_exports.string().nullable().optional().describe("Original file name; absent on older servers."),
15530
15536
  status: external_exports.string().describe("Document processing status."),
15531
15537
  createdAt: external_exports.string().nullable().optional().describe("Immutable document creation timestamp; absent on older servers."),
15532
15538
  lastActivityAt: external_exports.string().nullable().describe("Last backend activity timestamp (updated_at / heartbeat); null if unknown."),
@@ -15722,13 +15728,18 @@ var draftOperationDependencyIssueSchema = external_exports.object({
15722
15728
  expectedType: external_exports.string().describe("Expected OCF object category for the reference.")
15723
15729
  });
15724
15730
  var draftOperationPlanIssueSchema = external_exports.object({
15725
- code: external_exports.enum(["NO_DRAFTS", "REVERT_LIMIT_EXCEEDED"]).describe("Plan-level validation code."),
15731
+ code: external_exports.enum(["NO_DRAFTS", "REVERT_LIMIT_EXCEEDED", "ISSUER_REQUIRED", "ISSUER_INCOMPLETE"]).describe("Plan-level validation code."),
15726
15732
  message: external_exports.string().describe("Human-readable plan validation message.")
15727
15733
  });
15728
15734
  var draftOperationPreviewInputSchema = external_exports.object({
15729
15735
  operation: draftOperationSchema.describe("Draft operation to preview."),
15730
15736
  objectIds: external_exports.array(external_exports.string().trim().min(1, "objectIds must contain only non-empty strings.")).min(1, "objectIds must contain at least one ID when provided.").optional().describe("Optional draft OCF object IDs. Omit to preview all pending drafts.")
15731
15737
  });
15738
+ var draftOperationEmailIssueSchema = external_exports.object({
15739
+ id: external_exports.string().describe("Stakeholder ID."),
15740
+ name: external_exports.string().nullable().describe("Stakeholder legal name, when known."),
15741
+ problem: external_exports.enum(["missing", "invalid"]).describe("No email address, or one that is not *@*.*.")
15742
+ });
15732
15743
  var draftOperationPreviewSchema = external_exports.object({
15733
15744
  operation: draftOperationSchema,
15734
15745
  dependencyValid: external_exports.boolean().describe("True when object IDs are valid and dependency validation passes."),
@@ -15741,7 +15752,9 @@ var draftOperationPreviewSchema = external_exports.object({
15741
15752
  missingDependencies: external_exports.array(draftOperationDependencyIssueSchema).describe("Remaining dependency blockers reported by backend preflight validation."),
15742
15753
  planIssues: external_exports.array(draftOperationPlanIssueSchema).describe("Plan-level blockers."),
15743
15754
  objects: external_exports.array(ocfObjectSchema).describe("Versioned draft objects in finalIds order."),
15744
- draftCount: external_exports.number().int().nonnegative().describe("Total latest draft objects considered by this preview.")
15755
+ draftCount: external_exports.number().int().nonnegative().describe("Total latest draft objects considered by this preview."),
15756
+ emailIssues: external_exports.array(draftOperationEmailIssueSchema).optional().describe("Commit only: stakeholders whose email would make the commit refuse (or warn)."),
15757
+ emailOverride: external_exports.boolean().optional().describe("True when only missing emails remain and the caller is a super-admin.")
15745
15758
  });
15746
15759
  function normalizeDraftOperationObjectIds(objectIds) {
15747
15760
  if (!objectIds)
@@ -16658,6 +16671,8 @@ var ONBOARDING_STATES = {
16658
16671
  READY_TO_IMPORT: "ready_to_import",
16659
16672
  PROCESSING: "processing",
16660
16673
  NEEDS_REVIEW: "needs_review",
16674
+ /** Processing finished and nothing is left to review or commit (no drafts). */
16675
+ COMPLETE: "complete",
16661
16676
  BLOCKED: "blocked",
16662
16677
  READY_TO_COMMIT: "ready_to_commit"
16663
16678
  };
@@ -16695,6 +16710,11 @@ var onboardingStateSchema = external_exports.discriminatedUnion("state", [
16695
16710
  importSessionId: external_exports.string().uuid(),
16696
16711
  blockerCount: external_exports.number().int().nonnegative()
16697
16712
  }),
16713
+ onboardingStateBaseSchema.extend({
16714
+ state: external_exports.literal(ONBOARDING_STATES.COMPLETE),
16715
+ portalId: external_exports.string().uuid(),
16716
+ importSessionId: external_exports.string().uuid()
16717
+ }),
16698
16718
  onboardingStateBaseSchema.extend({
16699
16719
  state: external_exports.literal(ONBOARDING_STATES.BLOCKED),
16700
16720
  portalId: external_exports.string().uuid().optional(),
@@ -19534,6 +19554,20 @@ function printPreviewWarnings(data) {
19534
19554
  `${data.missingDependencies.length} dependency blocker(s) remain. Use --json for details.`
19535
19555
  );
19536
19556
  }
19557
+ const emailIssues = data.emailIssues ?? [];
19558
+ const kinds = [
19559
+ ["missing", "missing an email address"],
19560
+ ["invalid", "with an invalid email address"]
19561
+ ];
19562
+ for (const [problem, text] of kinds) {
19563
+ const names = emailIssues.filter((issue2) => issue2.problem === problem).map((i) => i.name || i.id);
19564
+ if (names.length > 0) {
19565
+ const override = problem === "missing" && data.emailOverride === true;
19566
+ printWarning(
19567
+ `${names.length} stakeholder(s) ${text}: ${names.join(", ")}.${override ? " Super-admin override: a missing email will not block the commit." : ""}`
19568
+ );
19569
+ }
19570
+ }
19537
19571
  }
19538
19572
  function previewRows(data) {
19539
19573
  const objectsById = new Map(data.objects.map((object2) => [object2.id, object2]));
@@ -23026,6 +23060,37 @@ function importStatusCommand(action, sessionId) {
23026
23060
  ...action.id === "review_failures" && action.s3AssetIds && { s3AssetIds: action.s3AssetIds }
23027
23061
  };
23028
23062
  }
23063
+ var DRAFT_COUNT_MAX_PAGES = 100;
23064
+ async function readDraftCount(portalId) {
23065
+ if (!portalId) return null;
23066
+ try {
23067
+ let count = 0;
23068
+ let cursor;
23069
+ for (let page = 0; page < DRAFT_COUNT_MAX_PAGES; page += 1) {
23070
+ const res = await apiRequest(
23071
+ `/${encodeURIComponent(portalId)}/objects`,
23072
+ {
23073
+ query: { status: "draft", ...cursor ? { cursor } : {} },
23074
+ // Optional read: throw (caught below) instead of exiting the process on a failure.
23075
+ softFail: true
23076
+ }
23077
+ );
23078
+ const objects = res.data?.objects;
23079
+ if (!Array.isArray(objects)) return null;
23080
+ count += objects.filter(
23081
+ (obj) => obj.type !== "DOCUMENT" && obj.subtype !== "DOCUMENT"
23082
+ ).length;
23083
+ if (count > 0) return count;
23084
+ const next = res.meta?.cursor;
23085
+ if (!res.meta?.hasMore) return count;
23086
+ if (!next || next === cursor) return null;
23087
+ cursor = next;
23088
+ }
23089
+ return null;
23090
+ } catch {
23091
+ return null;
23092
+ }
23093
+ }
23029
23094
  async function runImportStatus(args) {
23030
23095
  validateFlags(args, { flags: [], booleans: [] });
23031
23096
  const sessionId = args.positional[0];
@@ -23040,11 +23105,12 @@ async function runImportStatus(args) {
23040
23105
  );
23041
23106
  const portalDocuments = response.data?.processing?.documents ?? [];
23042
23107
  const documents = documentsForImportSession(portalDocuments, response.data?.session?.createdAt);
23043
- const plan = planImportStatus({
23108
+ const documentPlan = planImportStatus({
23044
23109
  documents,
23045
23110
  sessionState: response.data?.session?.state,
23046
23111
  scopeUnknown: importSessionScopeUnknown(portalDocuments)
23047
23112
  });
23113
+ const plan = documentPlan.phase === "complete" ? applyDraftCount(documentPlan, await readDraftCount(response.data?.session?.portalId)) : documentPlan;
23048
23114
  const { summary } = plan;
23049
23115
  if (plan.shouldComplete) {
23050
23116
  const completed = await apiRequest(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairmint/captable-ai",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
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",