@thecorporation/corp-tools 1.0.5 → 26.3.2

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 CHANGED
@@ -5,6 +5,19 @@ var SessionExpiredError = class extends Error {
5
5
  this.name = "SessionExpiredError";
6
6
  }
7
7
  };
8
+ async function extractErrorMessage(resp) {
9
+ try {
10
+ const text = await resp.text();
11
+ try {
12
+ const json = JSON.parse(text);
13
+ return json.error || json.message || json.detail || text;
14
+ } catch {
15
+ return text;
16
+ }
17
+ } catch {
18
+ return resp.statusText;
19
+ }
20
+ }
8
21
  async function provisionWorkspace(apiUrl, name) {
9
22
  const url = `${apiUrl.replace(/\/+$/, "")}/v1/workspaces/provision`;
10
23
  const body = {};
@@ -14,7 +27,10 @@ async function provisionWorkspace(apiUrl, name) {
14
27
  headers: { "Content-Type": "application/json" },
15
28
  body: JSON.stringify(body)
16
29
  });
17
- if (!resp.ok) throw new Error(`Provision failed: ${resp.status} ${resp.statusText}`);
30
+ if (!resp.ok) {
31
+ const detail = await extractErrorMessage(resp);
32
+ throw new Error(`Provision failed: ${resp.status} ${resp.statusText} \u2014 ${detail}`);
33
+ }
18
34
  return resp.json();
19
35
  }
20
36
  var CorpAPIClient = class {
@@ -43,34 +59,36 @@ var CorpAPIClient = class {
43
59
  if (body !== void 0) opts.body = JSON.stringify(body);
44
60
  return fetch(url, opts);
45
61
  }
62
+ async throwIfError(resp) {
63
+ if (resp.status === 401) throw new SessionExpiredError();
64
+ if (!resp.ok) {
65
+ const detail = await extractErrorMessage(resp);
66
+ throw new Error(`${resp.status} ${resp.statusText} \u2014 ${detail}`);
67
+ }
68
+ }
46
69
  async get(path, params) {
47
70
  const resp = await this.request("GET", path, void 0, params);
48
- if (resp.status === 401) throw new SessionExpiredError();
49
- if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText}`);
71
+ await this.throwIfError(resp);
50
72
  return resp.json();
51
73
  }
52
74
  async post(path, body) {
53
75
  const resp = await this.request("POST", path, body);
54
- if (resp.status === 401) throw new SessionExpiredError();
55
- if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText}`);
76
+ await this.throwIfError(resp);
56
77
  return resp.json();
57
78
  }
58
79
  async postWithParams(path, body, params) {
59
80
  const resp = await this.request("POST", path, body, params);
60
- if (resp.status === 401) throw new SessionExpiredError();
61
- if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText}`);
81
+ await this.throwIfError(resp);
62
82
  return resp.json();
63
83
  }
64
84
  async patch(path, body) {
65
85
  const resp = await this.request("PATCH", path, body);
66
- if (resp.status === 401) throw new SessionExpiredError();
67
- if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText}`);
86
+ await this.throwIfError(resp);
68
87
  return resp.json();
69
88
  }
70
89
  async del(path) {
71
90
  const resp = await this.request("DELETE", path);
72
- if (resp.status === 401) throw new SessionExpiredError();
73
- if (!resp.ok) throw new Error(`${resp.status} ${resp.statusText}`);
91
+ await this.throwIfError(resp);
74
92
  }
75
93
  // --- Workspace ---
76
94
  getStatus() {
@@ -134,6 +152,17 @@ var CorpAPIClient = class {
134
152
  getCurrent409a(entityId) {
135
153
  return this.get(`/v1/entities/${entityId}/current-409a`);
136
154
  }
155
+ createValuation(data) {
156
+ return this.post("/v1/valuations", data);
157
+ }
158
+ submitValuationForApproval(valuationId, entityId) {
159
+ return this.post(`/v1/valuations/${valuationId}/submit-for-approval`, { entity_id: entityId });
160
+ }
161
+ approveValuation(valuationId, entityId, resolutionId) {
162
+ const body = { entity_id: entityId };
163
+ if (resolutionId) body.resolution_id = resolutionId;
164
+ return this.post(`/v1/valuations/${valuationId}/approve`, body);
165
+ }
137
166
  issueEquity(data) {
138
167
  return this.post("/v1/equity/grants", data);
139
168
  }
@@ -165,6 +194,16 @@ var CorpAPIClient = class {
165
194
  executeRoundConversion(data) {
166
195
  return this.post("/v1/equity/conversions/execute", data);
167
196
  }
197
+ // --- Staged equity rounds ---
198
+ startEquityRound(data) {
199
+ return this.post("/v1/equity/rounds/staged", data);
200
+ }
201
+ addRoundSecurity(roundId, data) {
202
+ return this.post(`/v1/equity/rounds/${roundId}/securities`, data);
203
+ }
204
+ issueRound(roundId, data) {
205
+ return this.post(`/v1/equity/rounds/${roundId}/issue`, data);
206
+ }
168
207
  // --- Intent lifecycle helpers ---
169
208
  createExecutionIntent(data) {
170
209
  return this.post("/v1/execution/intents", data);
@@ -197,6 +236,33 @@ var CorpAPIClient = class {
197
236
  castVote(entityId, meetingId, itemId, data) {
198
237
  return this.postWithParams(`/v1/meetings/${meetingId}/agenda-items/${itemId}/vote`, data, { entity_id: entityId });
199
238
  }
239
+ sendNotice(meetingId, entityId) {
240
+ return this.postWithParams(`/v1/meetings/${meetingId}/notice`, {}, { entity_id: entityId });
241
+ }
242
+ adjournMeeting(meetingId, entityId) {
243
+ return this.postWithParams(`/v1/meetings/${meetingId}/adjourn`, {}, { entity_id: entityId });
244
+ }
245
+ cancelMeeting(meetingId, entityId) {
246
+ return this.postWithParams(`/v1/meetings/${meetingId}/cancel`, {}, { entity_id: entityId });
247
+ }
248
+ finalizeAgendaItem(meetingId, itemId, data) {
249
+ return this.post(`/v1/meetings/${meetingId}/agenda-items/${itemId}/finalize`, data);
250
+ }
251
+ computeResolution(meetingId, itemId, entityId, data) {
252
+ return this.postWithParams(`/v1/meetings/${meetingId}/agenda-items/${itemId}/resolution`, data, { entity_id: entityId });
253
+ }
254
+ attachResolutionDocument(meetingId, resolutionId, data) {
255
+ return this.post(`/v1/meetings/${meetingId}/resolutions/${resolutionId}/attach-document`, data);
256
+ }
257
+ writtenConsent(data) {
258
+ return this.post("/v1/meetings/written-consent", data);
259
+ }
260
+ listAgendaItems(meetingId, entityId) {
261
+ return this.get(`/v1/meetings/${meetingId}/agenda-items`, { entity_id: entityId });
262
+ }
263
+ listVotes(meetingId, itemId, entityId) {
264
+ return this.get(`/v1/meetings/${meetingId}/agenda-items/${itemId}/votes`, { entity_id: entityId });
265
+ }
200
266
  // --- Documents ---
201
267
  getEntityDocuments(entityId) {
202
268
  return this.get(`/v1/formations/${entityId}/documents`);
@@ -266,6 +332,18 @@ var CorpAPIClient = class {
266
332
  createFormation(data) {
267
333
  return this.post("/v1/formations", data);
268
334
  }
335
+ createFormationWithCapTable(data) {
336
+ return this.post("/v1/formations/with-cap-table", data);
337
+ }
338
+ createPendingEntity(data) {
339
+ return this.post("/v1/formations/pending", data);
340
+ }
341
+ addFounder(entityId, data) {
342
+ return this.post(`/v1/formations/${entityId}/founders`, data);
343
+ }
344
+ finalizeFormation(entityId) {
345
+ return this.post(`/v1/formations/${entityId}/finalize`, {});
346
+ }
269
347
  // --- Human obligations ---
270
348
  getHumanObligations() {
271
349
  return this.get(`/v1/workspaces/${this.workspaceId}/human-obligations`);
@@ -351,971 +429,566 @@ var GENERATED_TOOL_DEFINITIONS = [
351
429
  {
352
430
  "type": "function",
353
431
  "function": {
354
- "name": "get_workspace_status",
355
- "description": "Get workspace status summary",
356
- "parameters": {
357
- "type": "object",
358
- "properties": {},
359
- "required": []
360
- }
361
- }
362
- },
363
- {
364
- "type": "function",
365
- "function": {
366
- "name": "list_entities",
367
- "description": "List all entities in the workspace",
368
- "parameters": {
369
- "type": "object",
370
- "properties": {},
371
- "required": []
372
- }
373
- }
374
- },
375
- {
376
- "type": "function",
377
- "function": {
378
- "name": "get_cap_table",
379
- "description": "Get cap table for an entity",
380
- "parameters": {
381
- "type": "object",
382
- "properties": {
383
- "entity_id": {
384
- "type": "string"
385
- }
386
- },
387
- "required": [
388
- "entity_id"
389
- ]
390
- }
391
- }
392
- },
393
- {
394
- "type": "function",
395
- "function": {
396
- "name": "list_documents",
397
- "description": "List documents for an entity",
398
- "parameters": {
399
- "type": "object",
400
- "properties": {
401
- "entity_id": {
402
- "type": "string"
403
- }
404
- },
405
- "required": [
406
- "entity_id"
407
- ]
408
- }
409
- }
410
- },
411
- {
412
- "type": "function",
413
- "function": {
414
- "name": "list_safe_notes",
415
- "description": "List SAFE notes for an entity",
416
- "parameters": {
417
- "type": "object",
418
- "properties": {
419
- "entity_id": {
420
- "type": "string"
421
- }
422
- },
423
- "required": [
424
- "entity_id"
425
- ]
426
- }
427
- }
428
- },
429
- {
430
- "type": "function",
431
- "function": {
432
- "name": "list_agents",
433
- "description": "List all agents in the workspace",
434
- "parameters": {
435
- "type": "object",
436
- "properties": {},
437
- "required": []
438
- }
439
- }
440
- },
441
- {
442
- "type": "function",
443
- "function": {
444
- "name": "list_obligations",
445
- "description": "List obligations with urgency tiers",
432
+ "name": "workspace",
433
+ "description": "Workspace-level queries. Actions: status (get workspace summary), list_entities (list all entities), obligations (list obligations, optional tier filter), billing (get billing status and plans).",
446
434
  "parameters": {
447
435
  "type": "object",
448
436
  "properties": {
437
+ "action": {
438
+ "type": "string",
439
+ "enum": ["status", "list_entities", "obligations", "billing"]
440
+ },
449
441
  "tier": {
450
- "type": "string"
442
+ "type": "string",
443
+ "description": "obligations: filter by urgency tier"
451
444
  }
452
445
  },
453
- "required": []
454
- }
455
- }
456
- },
457
- {
458
- "type": "function",
459
- "function": {
460
- "name": "get_billing_status",
461
- "description": "Get billing status and plans",
462
- "parameters": {
463
- "type": "object",
464
- "properties": {},
465
- "required": []
446
+ "required": ["action"]
466
447
  }
467
448
  }
468
449
  },
469
450
  {
470
451
  "type": "function",
471
452
  "function": {
472
- "name": "form_entity",
473
- "description": "Form a new business entity (LLC or corporation)",
453
+ "name": "entity",
454
+ "description": "Entity reads and lifecycle. Actions: get_cap_table (entity_id), list_documents (entity_id), list_safe_notes (entity_id), form (entity_type + entity_name + jurisdiction + members \u2014 legacy one-shot formation), create (entity_type + entity_name \u2014 step 1 of staged formation), add_founder (entity_id + name + email + role + ownership_pct \u2014 step 2), finalize (entity_id \u2014 step 3, generates docs + cap table), convert (entity_id + new_entity_type), dissolve (entity_id + reason).",
474
455
  "parameters": {
475
456
  "type": "object",
476
457
  "properties": {
477
- "entity_type": {
458
+ "action": {
478
459
  "type": "string",
479
- "enum": [
480
- "llc",
481
- "corporation"
482
- ]
483
- },
484
- "entity_name": {
485
- "type": "string"
486
- },
487
- "jurisdiction": {
488
- "type": "string"
460
+ "enum": ["get_cap_table", "list_documents", "list_safe_notes", "form", "create", "add_founder", "finalize", "convert", "dissolve"]
461
+ },
462
+ "entity_id": { "type": "string" },
463
+ "entity_type": { "type": "string", "enum": ["llc", "corporation"] },
464
+ "entity_name": { "type": "string" },
465
+ "jurisdiction": { "type": "string", "description": "e.g. US-DE, US-WY. Defaults to US-WY for LLC, US-DE for corporation." },
466
+ "fiscal_year_end": { "type": "string", "description": "form: fiscal year end e.g. '12-31'" },
467
+ "s_corp_election": { "type": "boolean", "description": "form: elect S-Corp tax treatment" },
468
+ "transfer_restrictions": { "type": "boolean", "description": "form: include transfer restrictions in bylaws (corp)" },
469
+ "right_of_first_refusal": { "type": "boolean", "description": "form: include ROFR in bylaws (corp)" },
470
+ "company_address": {
471
+ "type": "object",
472
+ "properties": {
473
+ "street": { "type": "string" },
474
+ "street2": { "type": "string" },
475
+ "city": { "type": "string" },
476
+ "state": { "type": "string" },
477
+ "zip": { "type": "string" }
478
+ },
479
+ "required": ["street", "city", "state", "zip"]
489
480
  },
490
481
  "members": {
491
482
  "type": "array",
483
+ "description": "form: founding members array",
492
484
  "items": {
493
485
  "type": "object",
494
486
  "properties": {
495
- "name": {
496
- "type": "string"
497
- },
498
- "investor_type": {
499
- "type": "string",
500
- "enum": [
501
- "natural_person",
502
- "agent",
503
- "entity"
504
- ]
505
- },
506
- "email": {
507
- "type": "string"
508
- },
509
- "agent_id": {
510
- "type": "string"
487
+ "name": { "type": "string" },
488
+ "investor_type": { "type": "string", "enum": ["natural_person", "agent", "entity"] },
489
+ "email": { "type": "string" },
490
+ "agent_id": { "type": "string" },
491
+ "entity_id": { "type": "string" },
492
+ "ownership_pct": { "type": "number" },
493
+ "membership_units": { "type": "integer" },
494
+ "share_count": { "type": "integer" },
495
+ "share_class": { "type": "string" },
496
+ "role": { "type": "string", "enum": ["director", "officer", "manager", "member", "chair"] },
497
+ "officer_title": { "type": "string", "enum": ["ceo", "cfo", "secretary", "president", "vp", "other"] },
498
+ "shares_purchased": { "type": "integer" },
499
+ "address": {
500
+ "type": "object",
501
+ "properties": {
502
+ "street": { "type": "string" },
503
+ "street2": { "type": "string" },
504
+ "city": { "type": "string" },
505
+ "state": { "type": "string" },
506
+ "zip": { "type": "string" }
507
+ }
511
508
  },
512
- "entity_id": {
513
- "type": "string"
509
+ "vesting": {
510
+ "type": "object",
511
+ "properties": {
512
+ "total_months": { "type": "integer" },
513
+ "cliff_months": { "type": "integer" },
514
+ "acceleration": { "type": "string", "enum": ["single_trigger", "double_trigger"] }
515
+ }
514
516
  },
515
- "ownership_pct": {
516
- "type": "number"
517
- },
518
- "membership_units": {
519
- "type": "integer"
520
- },
521
- "share_count": {
522
- "type": "integer"
523
- },
524
- "share_class": {
525
- "type": "string"
526
- },
527
- "role": {
528
- "type": "string"
529
- }
517
+ "ip_description": { "type": "string" },
518
+ "is_incorporator": { "type": "boolean" }
530
519
  },
531
- "required": [
532
- "name",
533
- "investor_type"
534
- ]
520
+ "required": ["name", "investor_type"]
535
521
  }
536
- }
537
- },
538
- "required": [
539
- "entity_type",
540
- "entity_name",
541
- "jurisdiction",
542
- "members"
543
- ]
544
- }
545
- }
546
- },
547
- {
548
- "type": "function",
549
- "function": {
550
- "name": "issue_equity",
551
- "description": "Issue an equity grant",
552
- "parameters": {
553
- "type": "object",
554
- "properties": {
555
- "entity_id": {
556
- "type": "string"
557
- },
558
- "grant_type": {
559
- "type": "string"
560
522
  },
561
- "shares": {
562
- "type": "integer"
563
- },
564
- "recipient_name": {
565
- "type": "string"
566
- },
567
- "vesting_schedule": {
568
- "type": "string"
569
- }
523
+ "name": { "type": "string", "description": "add_founder: full legal name" },
524
+ "email": { "type": "string", "description": "add_founder: email address" },
525
+ "role": { "type": "string", "enum": ["director", "officer", "manager", "member", "chair"], "description": "add_founder: role" },
526
+ "ownership_pct": { "type": "number", "description": "add_founder: ownership percentage (e.g. 50 for 50%)" },
527
+ "officer_title": { "type": "string", "enum": ["ceo", "cfo", "secretary", "president", "vp", "other"], "description": "add_founder: officer title (corp only)" },
528
+ "is_incorporator": { "type": "boolean", "description": "add_founder: is sole incorporator (corp only)" },
529
+ "new_entity_type": { "type": "string", "description": "convert: target entity type" },
530
+ "new_jurisdiction": { "type": "string", "description": "convert: target jurisdiction" },
531
+ "reason": { "type": "string", "description": "dissolve: dissolution reason" },
532
+ "effective_date": { "type": "string", "description": "dissolve: effective date" }
570
533
  },
571
- "required": [
572
- "entity_id",
573
- "grant_type",
574
- "shares",
575
- "recipient_name"
576
- ]
534
+ "required": ["action"]
577
535
  }
578
536
  }
579
537
  },
580
538
  {
581
539
  "type": "function",
582
540
  "function": {
583
- "name": "issue_safe",
584
- "description": "Issue a SAFE note",
541
+ "name": "equity",
542
+ "description": "Equity and cap table operations. Actions: start_round (entity_id + name + issuer_legal_entity_id \u2014 step 1), add_security (round_id + instrument_id + quantity + recipient_name \u2014 step 2), issue_round (round_id \u2014 step 3, closes round + creates board agenda item), issue (entity_id + grant_type + shares + recipient_name \u2014 legacy single grant), issue_safe (entity_id + investor_name + principal_amount_cents + safe_type + valuation_cap_cents), transfer (entity_id + from_holder + to_holder + shares + skip_governance_review=true \u2014 bypasses governance), distribution (entity_id + total_amount_cents).",
585
543
  "parameters": {
586
544
  "type": "object",
587
545
  "properties": {
588
- "entity_id": {
589
- "type": "string"
590
- },
591
- "investor_name": {
592
- "type": "string"
593
- },
594
- "principal_amount_cents": {
595
- "type": "integer"
596
- },
597
- "safe_type": {
598
- "type": "string"
599
- },
600
- "valuation_cap_cents": {
601
- "type": "integer"
602
- }
546
+ "action": {
547
+ "type": "string",
548
+ "enum": ["start_round", "add_security", "issue_round", "issue", "issue_safe", "transfer", "distribution"]
549
+ },
550
+ "entity_id": { "type": "string" },
551
+ "name": { "type": "string", "description": "start_round: round name (e.g. 'Seed Round')" },
552
+ "issuer_legal_entity_id": { "type": "string", "description": "start_round: from cap table" },
553
+ "pre_money_cents": { "type": "integer", "description": "start_round: pre-money valuation in cents" },
554
+ "round_price_cents": { "type": "integer", "description": "start_round: price per share in cents" },
555
+ "target_raise_cents": { "type": "integer", "description": "start_round: target raise in cents" },
556
+ "round_id": { "type": "string", "description": "add_security/issue_round: round ID" },
557
+ "instrument_id": { "type": "string", "description": "add_security: instrument ID from cap table" },
558
+ "quantity": { "type": "integer", "description": "add_security: number of shares/units" },
559
+ "recipient_name": { "type": "string", "description": "add_security/issue: recipient name" },
560
+ "holder_id": { "type": "string", "description": "add_security: existing holder ID" },
561
+ "email": { "type": "string", "description": "add_security: recipient email" },
562
+ "principal_cents": { "type": "integer", "description": "add_security: investment amount in cents" },
563
+ "grant_type": { "type": "string", "description": "issue/add_security: e.g. common, preferred, option" },
564
+ "shares": { "type": "integer", "description": "issue/transfer: number of shares" },
565
+ "vesting_schedule": { "type": "string", "description": "issue: vesting schedule" },
566
+ "investor_name": { "type": "string", "description": "issue_safe: investor name" },
567
+ "principal_amount_cents": { "type": "integer", "description": "issue_safe: principal in cents" },
568
+ "safe_type": { "type": "string", "description": "issue_safe: SAFE type" },
569
+ "valuation_cap_cents": { "type": "integer", "description": "issue_safe: valuation cap in cents" },
570
+ "from_holder": { "type": "string", "description": "transfer: source holder" },
571
+ "to_holder": { "type": "string", "description": "transfer: destination holder" },
572
+ "share_class_id": { "type": "string", "description": "transfer: share class" },
573
+ "transfer_type": { "type": "string", "description": "transfer: transfer type" },
574
+ "skip_governance_review": { "type": "boolean", "description": "transfer: must be true to confirm bypassing governance" },
575
+ "total_amount_cents": { "type": "integer", "description": "distribution: total amount in cents" },
576
+ "distribution_type": { "type": "string", "description": "distribution: type" }
603
577
  },
604
- "required": [
605
- "entity_id",
606
- "investor_name",
607
- "principal_amount_cents",
608
- "safe_type",
609
- "valuation_cap_cents"
610
- ]
578
+ "required": ["action"]
611
579
  }
612
580
  }
613
581
  },
614
582
  {
615
583
  "type": "function",
616
584
  "function": {
617
- "name": "transfer_shares",
618
- "description": "Transfer shares between holders",
585
+ "name": "valuation",
586
+ "description": "Valuation lifecycle. Actions: create (entity_id + valuation_type + effective_date + methodology \u2192 Draft), submit (entity_id + valuation_id \u2192 PendingApproval, auto-creates board agenda item), approve (entity_id + valuation_id + optional resolution_id \u2192 Approved, auto-supersedes previous 409A).",
619
587
  "parameters": {
620
588
  "type": "object",
621
589
  "properties": {
622
- "entity_id": {
623
- "type": "string"
624
- },
625
- "share_class_id": {
626
- "type": "string"
627
- },
628
- "from_holder": {
629
- "type": "string"
630
- },
631
- "to_holder": {
632
- "type": "string"
590
+ "action": {
591
+ "type": "string",
592
+ "enum": ["create", "submit", "approve"]
633
593
  },
634
- "transfer_type": {
635
- "type": "string"
594
+ "entity_id": { "type": "string" },
595
+ "valuation_id": { "type": "string", "description": "submit/approve: valuation ID" },
596
+ "valuation_type": {
597
+ "type": "string",
598
+ "enum": ["four_oh_nine_a", "llc_profits_interest", "fair_market_value", "gift", "estate", "other"],
599
+ "description": "create: valuation type"
636
600
  },
637
- "shares": {
638
- "type": "integer"
639
- }
601
+ "effective_date": { "type": "string", "description": "create: effective date (ISO 8601)" },
602
+ "methodology": {
603
+ "type": "string",
604
+ "enum": ["income", "market", "asset", "backsolve", "hybrid", "other"],
605
+ "description": "create: valuation methodology"
606
+ },
607
+ "fmv_per_share_cents": { "type": "integer", "description": "create: FMV per share in cents" },
608
+ "enterprise_value_cents": { "type": "integer", "description": "create: enterprise value in cents" },
609
+ "hurdle_amount_cents": { "type": "integer", "description": "create: hurdle amount in cents" },
610
+ "provider_contact_id": { "type": "string", "description": "create: valuation provider contact ID" },
611
+ "report_document_id": { "type": "string", "description": "create: valuation report document ID" },
612
+ "resolution_id": { "type": "string", "description": "approve: resolution ID from board vote" }
640
613
  },
641
- "required": [
642
- "entity_id",
643
- "from_holder",
644
- "to_holder",
645
- "shares"
646
- ]
614
+ "required": ["action"]
647
615
  }
648
616
  }
649
617
  },
650
618
  {
651
619
  "type": "function",
652
620
  "function": {
653
- "name": "calculate_distribution",
654
- "description": "Calculate a distribution",
621
+ "name": "meeting",
622
+ "description": "Governance meeting lifecycle. Actions: schedule (entity_id + body_id + meeting_type + title), notice (entity_id + meeting_id \u2014 Draft\u2192Noticed), convene (entity_id + meeting_id + present_seat_ids \u2014 quorum check), vote (entity_id + meeting_id + agenda_item_id + voter_id + vote_value), resolve (entity_id + meeting_id + agenda_item_id + resolution_text \u2014 tally votes), finalize_item (entity_id + meeting_id + agenda_item_id + status), adjourn (entity_id + meeting_id), cancel (entity_id + meeting_id), consent (entity_id + body_id + title + description \u2014 written consent, no meeting), attach_document (entity_id + meeting_id + resolution_id + document_id), list_items (entity_id + meeting_id), list_votes (entity_id + meeting_id + agenda_item_id).",
655
623
  "parameters": {
656
624
  "type": "object",
657
625
  "properties": {
658
- "entity_id": {
659
- "type": "string"
660
- },
661
- "total_amount_cents": {
662
- "type": "integer"
663
- },
664
- "distribution_type": {
665
- "type": "string"
666
- }
626
+ "action": {
627
+ "type": "string",
628
+ "enum": ["schedule", "notice", "convene", "vote", "resolve", "finalize_item", "adjourn", "cancel", "consent", "attach_document", "list_items", "list_votes"]
629
+ },
630
+ "entity_id": { "type": "string" },
631
+ "meeting_id": { "type": "string" },
632
+ "body_id": { "type": "string", "description": "schedule/consent: governance body ID" },
633
+ "meeting_type": { "type": "string", "description": "schedule: meeting type" },
634
+ "title": { "type": "string", "description": "schedule/consent: meeting title" },
635
+ "description": { "type": "string", "description": "consent: description" },
636
+ "scheduled_date": { "type": "string", "description": "schedule: date (ISO 8601)" },
637
+ "agenda_item_titles": { "type": "array", "items": { "type": "string" }, "description": "schedule: agenda items" },
638
+ "present_seat_ids": { "type": "array", "items": { "type": "string" }, "description": "convene: seat IDs present" },
639
+ "agenda_item_id": { "type": "string", "description": "vote/resolve/finalize_item/list_votes: agenda item ID" },
640
+ "voter_id": { "type": "string", "description": "vote: voter seat ID" },
641
+ "vote_value": { "type": "string", "enum": ["for", "against", "abstain", "recusal"], "description": "vote: for, against, abstain, or recusal" },
642
+ "resolution_text": { "type": "string", "description": "resolve: resolution text" },
643
+ "effective_date": { "type": "string", "description": "resolve: optional effective date" },
644
+ "status": { "type": "string", "enum": ["Voted", "Discussed", "Tabled", "Withdrawn"], "description": "finalize_item: Voted, Discussed, Tabled, or Withdrawn" },
645
+ "resolution_id": { "type": "string", "description": "attach_document: resolution ID" },
646
+ "document_id": { "type": "string", "description": "attach_document: document ID" }
667
647
  },
668
- "required": [
669
- "entity_id",
670
- "total_amount_cents"
671
- ]
648
+ "required": ["action"]
672
649
  }
673
650
  }
674
651
  },
675
652
  {
676
653
  "type": "function",
677
654
  "function": {
678
- "name": "create_invoice",
679
- "description": "Create an invoice",
655
+ "name": "finance",
656
+ "description": "Financial operations. Actions: create_invoice (entity_id + customer_name + amount_cents + description + due_date), run_payroll (entity_id + pay_period_start + pay_period_end), submit_payment (entity_id + amount_cents + recipient), open_bank_account (entity_id, optional institution_name), reconcile (entity_id + start_date + end_date).",
680
657
  "parameters": {
681
658
  "type": "object",
682
659
  "properties": {
683
- "entity_id": {
684
- "type": "string"
685
- },
686
- "customer_name": {
687
- "type": "string"
688
- },
689
- "amount_cents": {
690
- "type": "integer"
691
- },
692
- "description": {
693
- "type": "string"
694
- },
695
- "due_date": {
696
- "type": "string"
697
- }
660
+ "action": {
661
+ "type": "string",
662
+ "enum": ["create_invoice", "run_payroll", "submit_payment", "open_bank_account", "reconcile"]
663
+ },
664
+ "entity_id": { "type": "string" },
665
+ "customer_name": { "type": "string", "description": "create_invoice: customer name" },
666
+ "amount_cents": { "type": "integer", "description": "create_invoice/submit_payment: amount in cents" },
667
+ "description": { "type": "string", "description": "create_invoice/submit_payment: description" },
668
+ "due_date": { "type": "string", "description": "create_invoice: due date" },
669
+ "pay_period_start": { "type": "string", "description": "run_payroll: start date" },
670
+ "pay_period_end": { "type": "string", "description": "run_payroll: end date" },
671
+ "recipient": { "type": "string", "description": "submit_payment: recipient" },
672
+ "institution_name": { "type": "string", "description": "open_bank_account: bank name" },
673
+ "start_date": { "type": "string", "description": "reconcile: start date" },
674
+ "end_date": { "type": "string", "description": "reconcile: end date" }
698
675
  },
699
- "required": [
700
- "entity_id",
701
- "customer_name",
702
- "amount_cents",
703
- "description",
704
- "due_date"
705
- ]
676
+ "required": ["action"]
706
677
  }
707
678
  }
708
679
  },
709
680
  {
710
681
  "type": "function",
711
682
  "function": {
712
- "name": "run_payroll",
713
- "description": "Run payroll",
683
+ "name": "compliance",
684
+ "description": "Compliance and legal operations. Actions: file_tax (entity_id + document_type + tax_year), track_deadline (entity_id + deadline_type + due_date + description), classify_contractor (entity_id + contractor_name + state + hours_per_week), generate_contract (entity_id + template_type).",
714
685
  "parameters": {
715
686
  "type": "object",
716
687
  "properties": {
717
- "entity_id": {
718
- "type": "string"
719
- },
720
- "pay_period_start": {
721
- "type": "string"
722
- },
723
- "pay_period_end": {
724
- "type": "string"
725
- }
688
+ "action": {
689
+ "type": "string",
690
+ "enum": ["file_tax", "track_deadline", "classify_contractor", "generate_contract"]
691
+ },
692
+ "entity_id": { "type": "string" },
693
+ "document_type": { "type": "string", "description": "file_tax: tax document type" },
694
+ "tax_year": { "type": "integer", "description": "file_tax: tax year" },
695
+ "deadline_type": { "type": "string", "description": "track_deadline: deadline type" },
696
+ "due_date": { "type": "string", "description": "track_deadline: due date" },
697
+ "description": { "type": "string", "description": "track_deadline: description" },
698
+ "recurrence": { "type": "string", "description": "track_deadline: recurrence" },
699
+ "contractor_name": { "type": "string", "description": "classify_contractor: contractor name" },
700
+ "state": { "type": "string", "description": "classify_contractor: state" },
701
+ "hours_per_week": { "type": "integer", "description": "classify_contractor: hours/week" },
702
+ "exclusive_client": { "type": "boolean", "description": "classify_contractor: exclusive?" },
703
+ "duration_months": { "type": "integer", "description": "classify_contractor: duration" },
704
+ "provides_tools": { "type": "boolean", "description": "classify_contractor: provides own tools?" },
705
+ "template_type": { "type": "string", "description": "generate_contract: template type" },
706
+ "parameters": { "type": "object", "description": "generate_contract: template parameters" }
726
707
  },
727
- "required": [
728
- "entity_id",
729
- "pay_period_start",
730
- "pay_period_end"
731
- ]
708
+ "required": ["action"]
732
709
  }
733
710
  }
734
711
  },
735
712
  {
736
713
  "type": "function",
737
714
  "function": {
738
- "name": "submit_payment",
739
- "description": "Submit a payment",
715
+ "name": "document",
716
+ "description": "Document access, signing, and preview. Actions: signing_link (document_id \u2014 get signing link for a document), signer_link (obligation_id \u2014 generate signing link for a human obligation), download_link (document_id \u2014 get download link), preview_pdf (entity_id + document_id \u2014 preview a governance document as PDF without requiring a saved document).",
740
717
  "parameters": {
741
718
  "type": "object",
742
719
  "properties": {
743
- "entity_id": {
744
- "type": "string"
745
- },
746
- "amount_cents": {
747
- "type": "integer"
748
- },
749
- "recipient": {
750
- "type": "string"
720
+ "action": {
721
+ "type": "string",
722
+ "enum": ["signing_link", "signer_link", "download_link", "preview_pdf"]
751
723
  },
752
- "description": {
753
- "type": "string"
754
- }
724
+ "document_id": { "type": "string", "description": "signing_link/download_link/preview_pdf: document ID (or AST definition ID for preview_pdf)" },
725
+ "obligation_id": { "type": "string", "description": "signer_link: obligation ID" },
726
+ "entity_id": { "type": "string", "description": "preview_pdf: entity whose profile to use for rendering" }
755
727
  },
756
- "required": [
757
- "entity_id",
758
- "amount_cents",
759
- "recipient"
760
- ]
728
+ "required": ["action"]
761
729
  }
762
730
  }
763
731
  },
764
732
  {
765
733
  "type": "function",
766
734
  "function": {
767
- "name": "open_bank_account",
768
- "description": "Open a business bank account",
735
+ "name": "checklist",
736
+ "description": "Workspace progress checklist. Actions: get (retrieve current checklist), update (checklist \u2014 set checklist content in markdown checkbox format).",
769
737
  "parameters": {
770
738
  "type": "object",
771
739
  "properties": {
772
- "entity_id": {
773
- "type": "string"
740
+ "action": {
741
+ "type": "string",
742
+ "enum": ["get", "update"]
774
743
  },
775
- "institution_name": {
776
- "type": "string"
777
- }
744
+ "checklist": { "type": "string", "description": "update: markdown checklist content" }
778
745
  },
779
- "required": [
780
- "entity_id"
781
- ]
746
+ "required": ["action"]
782
747
  }
783
748
  }
784
749
  },
785
750
  {
786
751
  "type": "function",
787
752
  "function": {
788
- "name": "generate_contract",
789
- "description": "Generate a contract from a template",
753
+ "name": "agent",
754
+ "description": "Agent management. Agents are for delegating recurring tasks \u2014 NOT for research or one-off questions. Requires a paid plan. Actions: list (list all agents), create (name + system_prompt), message (agent_id + body), update (agent_id + optional status), add_skill (agent_id + skill_name + description).",
790
755
  "parameters": {
791
756
  "type": "object",
792
757
  "properties": {
793
- "entity_id": {
794
- "type": "string"
795
- },
796
- "template_type": {
797
- "type": "string"
798
- },
799
- "parameters": {
800
- "type": "object"
801
- }
758
+ "action": {
759
+ "type": "string",
760
+ "enum": ["list", "create", "message", "update", "add_skill"]
761
+ },
762
+ "agent_id": { "type": "string", "description": "message/update/add_skill: agent ID" },
763
+ "name": { "type": "string", "description": "create: agent name" },
764
+ "system_prompt": { "type": "string", "description": "create: agent system prompt" },
765
+ "model": { "type": "string", "description": "create: model name" },
766
+ "body": { "type": "string", "description": "message: message body" },
767
+ "status": { "type": "string", "description": "update: new status" },
768
+ "skill_name": { "type": "string", "description": "add_skill: skill name" },
769
+ "description": { "type": "string", "description": "add_skill: skill description" },
770
+ "instructions": { "type": "string", "description": "add_skill: skill instructions" }
802
771
  },
803
- "required": [
804
- "entity_id",
805
- "template_type"
806
- ]
772
+ "required": ["action"]
807
773
  }
808
774
  }
809
- },
810
- {
811
- "type": "function",
812
- "function": {
813
- "name": "file_tax_document",
814
- "description": "File a tax document",
815
- "parameters": {
816
- "type": "object",
817
- "properties": {
818
- "entity_id": {
819
- "type": "string"
820
- },
821
- "document_type": {
822
- "type": "string"
823
- },
824
- "tax_year": {
825
- "type": "integer"
826
- }
827
- },
828
- "required": [
829
- "entity_id",
830
- "document_type",
831
- "tax_year"
832
- ]
833
- }
775
+ }
776
+ ];
777
+
778
+ // src/tools.ts
779
+ function requiredString(args, key) {
780
+ const value = args[key];
781
+ if (typeof value !== "string" || value.trim().length === 0) {
782
+ throw new Error(`Missing required field: ${key}`);
783
+ }
784
+ return value;
785
+ }
786
+ var workspaceActions = {
787
+ status: async (_args, client) => client.getStatus(),
788
+ list_entities: async (_args, client) => client.listEntities(),
789
+ obligations: async (args, client) => client.getObligations(args.tier),
790
+ billing: async (_args, client) => {
791
+ const [status, plans] = await Promise.all([client.getBillingStatus(), client.getBillingPlans()]);
792
+ return { status, plans };
793
+ }
794
+ };
795
+ var entityActions = {
796
+ get_cap_table: async (args, client) => client.getCapTable(requiredString(args, "entity_id")),
797
+ list_documents: async (args, client) => client.getEntityDocuments(requiredString(args, "entity_id")),
798
+ list_safe_notes: async (args, client) => client.getSafeNotes(requiredString(args, "entity_id")),
799
+ create: async (args, client) => {
800
+ const entityType = args.entity_type;
801
+ let jurisdiction = args.jurisdiction || "";
802
+ if (!jurisdiction || jurisdiction.length === 2) {
803
+ jurisdiction = entityType === "llc" ? "US-WY" : "US-DE";
834
804
  }
805
+ return client.createPendingEntity({
806
+ entity_type: entityType,
807
+ legal_name: args.entity_name,
808
+ jurisdiction
809
+ });
835
810
  },
836
- {
837
- "type": "function",
838
- "function": {
839
- "name": "track_deadline",
840
- "description": "Track a compliance deadline",
841
- "parameters": {
842
- "type": "object",
843
- "properties": {
844
- "entity_id": {
845
- "type": "string"
846
- },
847
- "deadline_type": {
848
- "type": "string"
849
- },
850
- "due_date": {
851
- "type": "string"
852
- },
853
- "description": {
854
- "type": "string"
855
- },
856
- "recurrence": {
857
- "type": "string"
858
- }
859
- },
860
- "required": [
861
- "entity_id",
862
- "deadline_type",
863
- "due_date",
864
- "description"
865
- ]
866
- }
811
+ add_founder: async (args, client) => {
812
+ const entityId = requiredString(args, "entity_id");
813
+ let ownershipPct = args.ownership_pct;
814
+ if (typeof ownershipPct === "number" && ownershipPct > 1) {
815
+ ownershipPct = ownershipPct / 100;
867
816
  }
817
+ return client.addFounder(entityId, {
818
+ name: args.name,
819
+ email: args.email,
820
+ role: args.role,
821
+ ownership_pct: ownershipPct,
822
+ officer_title: args.officer_title,
823
+ is_incorporator: args.is_incorporator
824
+ });
868
825
  },
869
- {
870
- "type": "function",
871
- "function": {
872
- "name": "classify_contractor",
873
- "description": "Classify contractor risk",
874
- "parameters": {
875
- "type": "object",
876
- "properties": {
877
- "entity_id": {
878
- "type": "string"
879
- },
880
- "contractor_name": {
881
- "type": "string"
882
- },
883
- "state": {
884
- "type": "string"
885
- },
886
- "hours_per_week": {
887
- "type": "integer"
888
- },
889
- "exclusive_client": {
890
- "type": "boolean"
891
- },
892
- "duration_months": {
893
- "type": "integer"
894
- },
895
- "provides_tools": {
896
- "type": "boolean"
897
- }
898
- },
899
- "required": [
900
- "entity_id",
901
- "contractor_name",
902
- "state",
903
- "hours_per_week"
904
- ]
905
- }
826
+ finalize: async (args, client, ctx) => {
827
+ const entityId = requiredString(args, "entity_id");
828
+ const result = await client.finalizeFormation(entityId);
829
+ if (entityId && ctx.onEntityFormed) {
830
+ ctx.onEntityFormed(entityId);
906
831
  }
832
+ return result;
907
833
  },
908
- {
909
- "type": "function",
910
- "function": {
911
- "name": "reconcile_ledger",
912
- "description": "Reconcile an entity's ledger",
913
- "parameters": {
914
- "type": "object",
915
- "properties": {
916
- "entity_id": {
917
- "type": "string"
918
- },
919
- "start_date": {
920
- "type": "string"
921
- },
922
- "end_date": {
923
- "type": "string"
924
- }
925
- },
926
- "required": [
927
- "entity_id",
928
- "start_date",
929
- "end_date"
930
- ]
834
+ form: async (args, client, ctx) => {
835
+ const entityType = args.entity_type;
836
+ let jurisdiction = args.jurisdiction || "";
837
+ if (!jurisdiction || jurisdiction.length === 2) {
838
+ jurisdiction = entityType === "llc" ? "US-WY" : "US-DE";
839
+ }
840
+ const members = args.members ?? [];
841
+ if (!members.length) return { error: "Members are required." };
842
+ for (const m of members) {
843
+ if (!m.investor_type) m.investor_type = "natural_person";
844
+ if (typeof m.ownership_pct === "number" && m.ownership_pct > 1) {
845
+ m.ownership_pct = m.ownership_pct / 100;
931
846
  }
932
847
  }
933
- },
934
- {
935
- "type": "function",
936
- "function": {
937
- "name": "convene_meeting",
938
- "description": "Convene a governance meeting",
939
- "parameters": {
940
- "type": "object",
941
- "properties": {
942
- "entity_id": {
943
- "type": "string"
944
- },
945
- "meeting_id": {
946
- "type": "string"
947
- },
948
- "present_seat_ids": {
949
- "type": "array",
950
- "items": {
951
- "type": "string"
952
- }
953
- }
954
- },
955
- "required": [
956
- "entity_id",
957
- "meeting_id",
958
- "present_seat_ids"
959
- ]
960
- }
961
- }
962
- },
963
- {
964
- "type": "function",
965
- "function": {
966
- "name": "cast_vote",
967
- "description": "Cast a vote on an agenda item",
968
- "parameters": {
969
- "type": "object",
970
- "properties": {
971
- "entity_id": {
972
- "type": "string"
973
- },
974
- "meeting_id": {
975
- "type": "string"
976
- },
977
- "agenda_item_id": {
978
- "type": "string"
979
- },
980
- "voter_id": {
981
- "type": "string"
982
- },
983
- "vote_value": {
984
- "type": "string",
985
- "description": "for, against, abstain, or recusal"
986
- }
987
- },
988
- "required": [
989
- "entity_id",
990
- "meeting_id",
991
- "agenda_item_id",
992
- "voter_id",
993
- "vote_value"
994
- ]
995
- }
996
- }
997
- },
998
- {
999
- "type": "function",
1000
- "function": {
1001
- "name": "schedule_meeting",
1002
- "description": "Schedule a board or member meeting",
1003
- "parameters": {
1004
- "type": "object",
1005
- "properties": {
1006
- "entity_id": {
1007
- "type": "string"
1008
- },
1009
- "body_id": {
1010
- "type": "string"
1011
- },
1012
- "meeting_type": {
1013
- "type": "string"
1014
- },
1015
- "title": {
1016
- "type": "string"
1017
- },
1018
- "scheduled_date": {
1019
- "type": "string"
1020
- },
1021
- "agenda_item_titles": {
1022
- "type": "array",
1023
- "items": {
1024
- "type": "string"
1025
- }
1026
- }
1027
- },
1028
- "required": [
1029
- "entity_id",
1030
- "body_id",
1031
- "meeting_type",
1032
- "title"
1033
- ]
1034
- }
1035
- }
1036
- },
1037
- {
1038
- "type": "function",
1039
- "function": {
1040
- "name": "get_signer_link",
1041
- "description": "Generate a signing link for a human obligation",
1042
- "parameters": {
1043
- "type": "object",
1044
- "properties": {
1045
- "obligation_id": {
1046
- "type": "string"
1047
- }
1048
- },
1049
- "required": [
1050
- "obligation_id"
1051
- ]
1052
- }
1053
- }
1054
- },
1055
- {
1056
- "type": "function",
1057
- "function": {
1058
- "name": "get_document_link",
1059
- "description": "Get a download link for a document",
1060
- "parameters": {
1061
- "type": "object",
1062
- "properties": {
1063
- "document_id": {
1064
- "type": "string"
1065
- }
1066
- },
1067
- "required": [
1068
- "document_id"
1069
- ]
1070
- }
1071
- }
1072
- },
1073
- {
1074
- "type": "function",
1075
- "function": {
1076
- "name": "convert_entity",
1077
- "description": "Convert entity type",
1078
- "parameters": {
1079
- "type": "object",
1080
- "properties": {
1081
- "entity_id": {
1082
- "type": "string"
1083
- },
1084
- "new_entity_type": {
1085
- "type": "string"
1086
- },
1087
- "new_jurisdiction": {
1088
- "type": "string"
1089
- }
1090
- },
1091
- "required": [
1092
- "entity_id",
1093
- "new_entity_type"
1094
- ]
1095
- }
1096
- }
1097
- },
1098
- {
1099
- "type": "function",
1100
- "function": {
1101
- "name": "dissolve_entity",
1102
- "description": "Dissolve an entity",
1103
- "parameters": {
1104
- "type": "object",
1105
- "properties": {
1106
- "entity_id": {
1107
- "type": "string"
1108
- },
1109
- "reason": {
1110
- "type": "string"
1111
- },
1112
- "effective_date": {
1113
- "type": "string"
1114
- }
1115
- },
1116
- "required": [
1117
- "entity_id",
1118
- "reason"
1119
- ]
1120
- }
1121
- }
1122
- },
1123
- {
1124
- "type": "function",
1125
- "function": {
1126
- "name": "add_agent_skill",
1127
- "description": "Add a skill to an agent",
1128
- "parameters": {
1129
- "type": "object",
1130
- "properties": {
1131
- "agent_id": {
1132
- "type": "string"
1133
- },
1134
- "skill_name": {
1135
- "type": "string"
1136
- },
1137
- "description": {
1138
- "type": "string"
1139
- },
1140
- "instructions": {
1141
- "type": "string"
1142
- }
1143
- },
1144
- "required": [
1145
- "agent_id",
1146
- "skill_name",
1147
- "description"
1148
- ]
1149
- }
848
+ const result = await client.createFormationWithCapTable({
849
+ entity_type: entityType,
850
+ legal_name: args.entity_name,
851
+ jurisdiction,
852
+ members,
853
+ workspace_id: client.workspaceId,
854
+ fiscal_year_end: args.fiscal_year_end,
855
+ s_corp_election: args.s_corp_election,
856
+ transfer_restrictions: args.transfer_restrictions,
857
+ right_of_first_refusal: args.right_of_first_refusal,
858
+ company_address: args.company_address
859
+ });
860
+ const entityId = result.entity_id;
861
+ if (entityId && ctx.onEntityFormed) {
862
+ ctx.onEntityFormed(entityId);
1150
863
  }
864
+ return result;
1151
865
  },
1152
- {
1153
- "type": "function",
1154
- "function": {
1155
- "name": "get_checklist",
1156
- "description": "Get the user's onboarding checklist",
1157
- "parameters": {
1158
- "type": "object",
1159
- "properties": {},
1160
- "required": []
1161
- }
1162
- }
866
+ convert: async (args, client) => client.convertEntity(requiredString(args, "entity_id"), args),
867
+ dissolve: async (args, client) => client.dissolveEntity(requiredString(args, "entity_id"), args)
868
+ };
869
+ var equityActions = {
870
+ start_round: async (args, client) => client.startEquityRound(args),
871
+ add_security: async (args, client) => {
872
+ const roundId = requiredString(args, "round_id");
873
+ return client.addRoundSecurity(roundId, args);
1163
874
  },
1164
- {
1165
- "type": "function",
1166
- "function": {
1167
- "name": "update_checklist",
1168
- "description": "Update the user's onboarding checklist",
1169
- "parameters": {
1170
- "type": "object",
1171
- "properties": {
1172
- "checklist": {
1173
- "type": "string"
1174
- }
1175
- },
1176
- "required": [
1177
- "checklist"
1178
- ]
1179
- }
1180
- }
875
+ issue_round: async (args, client) => {
876
+ const roundId = requiredString(args, "round_id");
877
+ return client.issueRound(roundId, args);
1181
878
  },
1182
- {
1183
- "type": "function",
1184
- "function": {
1185
- "name": "get_signing_link",
1186
- "description": "Get a signing link for a document",
1187
- "parameters": {
1188
- "type": "object",
1189
- "properties": {
1190
- "document_id": {
1191
- "type": "string"
1192
- }
1193
- },
1194
- "required": [
1195
- "document_id"
1196
- ]
1197
- }
879
+ issue: async (args, client) => client.issueEquity(args),
880
+ issue_safe: async (args, client) => client.issueSafe(args),
881
+ transfer: async (args, client) => {
882
+ if (args.skip_governance_review !== true) {
883
+ return {
884
+ error: "Transfer blocked: governance review required. Use the transfer workflow (create_transfer_workflow \u2192 submit-review \u2192 record-board-approval \u2192 execute) for governed transfers. To bypass governance and record a direct transfer, pass skip_governance_review: true."
885
+ };
1198
886
  }
887
+ return client.transferShares(args);
1199
888
  },
1200
- {
1201
- "type": "function",
1202
- "function": {
1203
- "name": "create_agent",
1204
- "description": "Create a new agent",
1205
- "parameters": {
1206
- "type": "object",
1207
- "properties": {
1208
- "name": {
1209
- "type": "string"
1210
- },
1211
- "system_prompt": {
1212
- "type": "string"
1213
- },
1214
- "model": {
1215
- "type": "string"
1216
- }
1217
- },
1218
- "required": [
1219
- "name",
1220
- "system_prompt"
1221
- ]
1222
- }
889
+ distribution: async (args, client) => client.calculateDistribution(args)
890
+ };
891
+ var valuationActions = {
892
+ create: async (args, client) => client.createValuation(args),
893
+ submit: async (args, client) => client.submitValuationForApproval(
894
+ requiredString(args, "valuation_id"),
895
+ requiredString(args, "entity_id")
896
+ ),
897
+ approve: async (args, client) => client.approveValuation(
898
+ requiredString(args, "valuation_id"),
899
+ requiredString(args, "entity_id"),
900
+ args.resolution_id
901
+ )
902
+ };
903
+ var meetingActions = {
904
+ schedule: async (args, client) => {
905
+ const body = {
906
+ entity_id: requiredString(args, "entity_id"),
907
+ body_id: requiredString(args, "body_id"),
908
+ meeting_type: requiredString(args, "meeting_type"),
909
+ title: requiredString(args, "title")
910
+ };
911
+ const scheduledDate = args.scheduled_date ?? args.proposed_date;
912
+ if (typeof scheduledDate === "string" && scheduledDate.trim().length > 0) {
913
+ body.scheduled_date = scheduledDate;
1223
914
  }
915
+ const agendaItems = args.agenda_item_titles ?? args.agenda_items;
916
+ if (Array.isArray(agendaItems)) body.agenda_item_titles = agendaItems;
917
+ return client.scheduleMeeting(body);
1224
918
  },
1225
- {
1226
- "type": "function",
1227
- "function": {
1228
- "name": "send_agent_message",
1229
- "description": "Send a message to an agent",
1230
- "parameters": {
1231
- "type": "object",
1232
- "properties": {
1233
- "agent_id": {
1234
- "type": "string"
1235
- },
1236
- "body": {
1237
- "type": "string"
1238
- }
1239
- },
1240
- "required": [
1241
- "agent_id",
1242
- "body"
1243
- ]
1244
- }
919
+ notice: async (args, client) => client.sendNotice(
920
+ requiredString(args, "meeting_id"),
921
+ requiredString(args, "entity_id")
922
+ ),
923
+ convene: async (args, client) => client.conveneMeeting(
924
+ requiredString(args, "meeting_id"),
925
+ requiredString(args, "entity_id"),
926
+ {
927
+ present_seat_ids: Array.isArray(args.present_seat_ids) ? args.present_seat_ids : []
1245
928
  }
1246
- },
1247
- {
1248
- "type": "function",
1249
- "function": {
1250
- "name": "update_agent",
1251
- "description": "Update an agent",
1252
- "parameters": {
1253
- "type": "object",
1254
- "properties": {
1255
- "agent_id": {
1256
- "type": "string"
1257
- },
1258
- "status": {
1259
- "type": "string"
1260
- }
1261
- },
1262
- "required": [
1263
- "agent_id"
1264
- ]
1265
- }
929
+ ),
930
+ vote: async (args, client) => client.castVote(
931
+ requiredString(args, "entity_id"),
932
+ requiredString(args, "meeting_id"),
933
+ requiredString(args, "agenda_item_id"),
934
+ {
935
+ voter_id: requiredString(args, "voter_id"),
936
+ vote_value: requiredString(args, "vote_value")
1266
937
  }
1267
- }
1268
- ];
1269
-
1270
- // src/tools.ts
1271
- function requiredString(args, key) {
1272
- const value = args[key];
1273
- if (typeof value !== "string" || value.trim().length === 0) {
1274
- throw new Error(`Missing required field: ${key}`);
1275
- }
1276
- return value;
1277
- }
1278
- var TOOL_HANDLERS = {
1279
- get_workspace_status: async (_args, client) => client.getStatus(),
1280
- list_obligations: async (args, client) => client.getObligations(args.tier),
1281
- list_entities: async (_args, client) => client.listEntities(),
1282
- get_cap_table: async (args, client) => client.getCapTable(args.entity_id),
1283
- list_documents: async (args, client) => client.getEntityDocuments(args.entity_id),
1284
- list_safe_notes: async (args, client) => client.getSafeNotes(args.entity_id),
1285
- list_agents: async (_args, client) => client.listAgents(),
1286
- get_billing_status: async (_args, client) => {
1287
- const [status, plans] = await Promise.all([client.getBillingStatus(), client.getBillingPlans()]);
1288
- return { status, plans };
938
+ ),
939
+ resolve: async (args, client) => {
940
+ const data = {
941
+ resolution_text: requiredString(args, "resolution_text")
942
+ };
943
+ if (typeof args.effective_date === "string") data.effective_date = args.effective_date;
944
+ return client.computeResolution(
945
+ requiredString(args, "meeting_id"),
946
+ requiredString(args, "agenda_item_id"),
947
+ requiredString(args, "entity_id"),
948
+ data
949
+ );
1289
950
  },
1290
- form_entity: async (args, client, ctx) => {
1291
- const entityType = args.entity_type;
1292
- let jurisdiction = args.jurisdiction || "";
1293
- if (!jurisdiction || jurisdiction.length === 2) {
1294
- jurisdiction = entityType === "llc" ? "US-WY" : "US-DE";
1295
- }
1296
- const members = args.members ?? [];
1297
- if (!members.length) return { error: "Members are required." };
1298
- for (const m of members) {
1299
- if (!m.investor_type) m.investor_type = "natural_person";
1300
- if (typeof m.ownership_pct === "number" && m.ownership_pct > 1) {
1301
- m.ownership_pct = m.ownership_pct / 100;
1302
- }
951
+ finalize_item: async (args, client) => client.finalizeAgendaItem(
952
+ requiredString(args, "meeting_id"),
953
+ requiredString(args, "agenda_item_id"),
954
+ {
955
+ entity_id: requiredString(args, "entity_id"),
956
+ status: requiredString(args, "status")
1303
957
  }
1304
- const result = await client.createFormation({
1305
- entity_type: entityType,
1306
- legal_name: args.entity_name,
1307
- jurisdiction,
1308
- members,
1309
- workspace_id: client.workspaceId
1310
- });
1311
- const entityId = result.entity_id;
1312
- if (entityId && ctx.onEntityFormed) {
1313
- ctx.onEntityFormed(entityId);
958
+ ),
959
+ adjourn: async (args, client) => client.adjournMeeting(
960
+ requiredString(args, "meeting_id"),
961
+ requiredString(args, "entity_id")
962
+ ),
963
+ cancel: async (args, client) => client.cancelMeeting(
964
+ requiredString(args, "meeting_id"),
965
+ requiredString(args, "entity_id")
966
+ ),
967
+ consent: async (args, client) => client.writtenConsent({
968
+ entity_id: requiredString(args, "entity_id"),
969
+ body_id: requiredString(args, "body_id"),
970
+ title: requiredString(args, "title"),
971
+ description: args.description ?? ""
972
+ }),
973
+ attach_document: async (args, client) => client.attachResolutionDocument(
974
+ requiredString(args, "meeting_id"),
975
+ requiredString(args, "resolution_id"),
976
+ {
977
+ entity_id: requiredString(args, "entity_id"),
978
+ document_id: requiredString(args, "document_id")
1314
979
  }
1315
- return result;
1316
- },
1317
- issue_equity: async (args, client) => client.issueEquity(args),
1318
- issue_safe: async (args, client) => client.issueSafe(args),
980
+ ),
981
+ list_items: async (args, client) => client.listAgendaItems(
982
+ requiredString(args, "meeting_id"),
983
+ requiredString(args, "entity_id")
984
+ ),
985
+ list_votes: async (args, client) => client.listVotes(
986
+ requiredString(args, "meeting_id"),
987
+ requiredString(args, "agenda_item_id"),
988
+ requiredString(args, "entity_id")
989
+ )
990
+ };
991
+ var financeActions = {
1319
992
  create_invoice: async (args, client) => {
1320
993
  if (!("amount_cents" in args) && Array.isArray(args.line_items)) {
1321
994
  args.amount_cents = args.line_items.reduce((sum, item) => sum + (item.amount_cents ?? 0), 0);
@@ -1333,9 +1006,17 @@ var TOOL_HANDLERS = {
1333
1006
  if (args.institution_name) body.institution_name = args.institution_name;
1334
1007
  return client.openBankAccount(body);
1335
1008
  },
1336
- generate_contract: async (args, client) => client.generateContract(args),
1337
- file_tax_document: async (args, client) => client.fileTaxDocument(args),
1338
- get_signer_link: async (args, client) => {
1009
+ reconcile: async (args, client) => client.reconcileLedger(args)
1010
+ };
1011
+ var complianceActions = {
1012
+ file_tax: async (args, client) => client.fileTaxDocument(args),
1013
+ track_deadline: async (args, client) => client.trackDeadline(args),
1014
+ classify_contractor: async (args, client) => client.classifyContractor(args),
1015
+ generate_contract: async (args, client) => client.generateContract(args)
1016
+ };
1017
+ var documentActions = {
1018
+ signing_link: async (args, client) => client.getSigningLink(args.document_id),
1019
+ signer_link: async (args, client) => {
1339
1020
  const result = await client.getSignerToken(args.obligation_id);
1340
1021
  const token = result.token ?? "";
1341
1022
  const obligationId = args.obligation_id;
@@ -1347,42 +1028,7 @@ var TOOL_HANDLERS = {
1347
1028
  message: "Share this link with the signer. Link expires in 15 minutes."
1348
1029
  };
1349
1030
  },
1350
- schedule_meeting: async (args, client) => {
1351
- const body = {
1352
- entity_id: requiredString(args, "entity_id"),
1353
- body_id: requiredString(args, "body_id"),
1354
- meeting_type: requiredString(args, "meeting_type"),
1355
- title: requiredString(args, "title")
1356
- };
1357
- const scheduledDate = args.scheduled_date ?? args.proposed_date;
1358
- if (typeof scheduledDate === "string" && scheduledDate.trim().length > 0) {
1359
- body.scheduled_date = scheduledDate;
1360
- }
1361
- const agendaItems = args.agenda_item_titles ?? args.agenda_items;
1362
- if (Array.isArray(agendaItems)) body.agenda_item_titles = agendaItems;
1363
- return client.scheduleMeeting(body);
1364
- },
1365
- cast_vote: async (args, client) => client.castVote(
1366
- requiredString(args, "entity_id"),
1367
- requiredString(args, "meeting_id"),
1368
- requiredString(args, "agenda_item_id"),
1369
- {
1370
- voter_id: requiredString(args, "voter_id"),
1371
- vote_value: requiredString(args, "vote_value")
1372
- }
1373
- ),
1374
- update_checklist: async (args, _client, ctx) => {
1375
- const path = join(ctx.dataDir, "checklist.md");
1376
- mkdirSync(ctx.dataDir, { recursive: true });
1377
- writeFileSync(path, args.checklist);
1378
- return { status: "updated", checklist: args.checklist };
1379
- },
1380
- get_checklist: async (_args, _client, ctx) => {
1381
- const path = join(ctx.dataDir, "checklist.md");
1382
- if (existsSync(path)) return { checklist: readFileSync(path, "utf-8") };
1383
- return { checklist: null, message: "No checklist yet." };
1384
- },
1385
- get_document_link: async (args, client) => {
1031
+ download_link: async (args, client) => {
1386
1032
  const docId = args.document_id;
1387
1033
  try {
1388
1034
  const resp = await fetch(`${client.apiUrl}/v1/documents/${docId}/request-copy`, {
@@ -1403,45 +1049,81 @@ var TOOL_HANDLERS = {
1403
1049
  };
1404
1050
  }
1405
1051
  },
1406
- get_signing_link: async (args, client) => client.getSigningLink(args.document_id),
1407
- convert_entity: async (args, client) => client.convertEntity(args.entity_id, args),
1408
- dissolve_entity: async (args, client) => client.dissolveEntity(args.entity_id, args),
1409
- transfer_shares: async (args, client) => client.transferShares(args),
1410
- calculate_distribution: async (args, client) => client.calculateDistribution(args),
1411
- classify_contractor: async (args, client) => client.classifyContractor(args),
1412
- reconcile_ledger: async (args, client) => client.reconcileLedger(args),
1413
- track_deadline: async (args, client) => client.trackDeadline(args),
1414
- convene_meeting: async (args, client) => client.conveneMeeting(
1415
- requiredString(args, "meeting_id"),
1416
- requiredString(args, "entity_id"),
1417
- {
1418
- present_seat_ids: Array.isArray(args.present_seat_ids) ? args.present_seat_ids : []
1419
- }
1420
- ),
1421
- create_agent: async (args, client) => client.createAgent(args),
1422
- send_agent_message: async (args, client) => client.sendAgentMessage(args.agent_id, args.body),
1423
- update_agent: async (args, client) => client.updateAgent(args.agent_id, args),
1424
- add_agent_skill: async (args, client) => client.addAgentSkill(args.agent_id, args)
1052
+ preview_pdf: async (args, client) => {
1053
+ const entityId = args.entity_id;
1054
+ const documentId = args.document_id;
1055
+ const qs = new URLSearchParams({ entity_id: entityId, document_id: documentId }).toString();
1056
+ return {
1057
+ entity_id: entityId,
1058
+ document_id: documentId,
1059
+ download_url: `${client.apiUrl}/v1/documents/preview/pdf?${qs}`,
1060
+ note: "Use your API key to authenticate the download."
1061
+ };
1062
+ }
1063
+ };
1064
+ var checklistActions = {
1065
+ get: async (_args, _client, ctx) => {
1066
+ const path = join(ctx.dataDir, "checklist.md");
1067
+ if (existsSync(path)) return { checklist: readFileSync(path, "utf-8") };
1068
+ return { checklist: null, message: "No checklist yet." };
1069
+ },
1070
+ update: async (args, _client, ctx) => {
1071
+ const path = join(ctx.dataDir, "checklist.md");
1072
+ mkdirSync(ctx.dataDir, { recursive: true });
1073
+ writeFileSync(path, args.checklist);
1074
+ return { status: "updated", checklist: args.checklist };
1075
+ }
1076
+ };
1077
+ var agentActions = {
1078
+ list: async (_args, client) => client.listAgents(),
1079
+ create: async (args, client) => client.createAgent(args),
1080
+ message: async (args, client) => client.sendAgentMessage(args.agent_id, args.body),
1081
+ update: async (args, client) => client.updateAgent(args.agent_id, args),
1082
+ add_skill: async (args, client) => client.addAgentSkill(args.agent_id, args)
1083
+ };
1084
+ var TOOL_DISPATCH = {
1085
+ workspace: workspaceActions,
1086
+ entity: entityActions,
1087
+ equity: equityActions,
1088
+ valuation: valuationActions,
1089
+ meeting: meetingActions,
1090
+ finance: financeActions,
1091
+ compliance: complianceActions,
1092
+ document: documentActions,
1093
+ checklist: checklistActions,
1094
+ agent: agentActions
1425
1095
  };
1426
1096
  var TOOL_DEFINITIONS = GENERATED_TOOL_DEFINITIONS;
1427
- var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
1428
- "get_workspace_status",
1429
- "list_entities",
1430
- "get_cap_table",
1431
- "list_documents",
1432
- "list_safe_notes",
1433
- "list_agents",
1434
- "get_checklist",
1435
- "get_signing_link",
1436
- "list_obligations",
1437
- "get_billing_status"
1097
+ var READ_ONLY_ACTIONS = /* @__PURE__ */ new Set([
1098
+ "workspace:status",
1099
+ "workspace:list_entities",
1100
+ "workspace:obligations",
1101
+ "workspace:billing",
1102
+ "entity:get_cap_table",
1103
+ "entity:list_documents",
1104
+ "entity:list_safe_notes",
1105
+ "document:signing_link",
1106
+ "document:signer_link",
1107
+ "document:download_link",
1108
+ "document:preview_pdf",
1109
+ "checklist:get",
1110
+ "meeting:list_items",
1111
+ "meeting:list_votes",
1112
+ "agent:list"
1438
1113
  ]);
1439
- function isWriteTool(name) {
1440
- return !READ_ONLY_TOOLS.has(name);
1114
+ function isWriteTool(name, args) {
1115
+ if (args && typeof args.action === "string") {
1116
+ return !READ_ONLY_ACTIONS.has(`${name}:${args.action}`);
1117
+ }
1118
+ return true;
1441
1119
  }
1442
1120
  async function executeTool(name, args, client, ctx) {
1443
- const handler = TOOL_HANDLERS[name];
1444
- if (!handler) return JSON.stringify({ error: `Unknown tool: ${name}` });
1121
+ const dispatch = TOOL_DISPATCH[name];
1122
+ if (!dispatch) return JSON.stringify({ error: `Unknown tool: ${name}` });
1123
+ const action = args.action;
1124
+ if (!action) return JSON.stringify({ error: `Missing required field: action` });
1125
+ const handler = dispatch[action];
1126
+ if (!handler) return JSON.stringify({ error: `Unknown action "${action}" for tool "${name}"` });
1445
1127
  try {
1446
1128
  const result = await handler(args, client, ctx);
1447
1129
  return JSON.stringify(result, null, 0);
@@ -1468,40 +1150,83 @@ function describeToolCall(name, args) {
1468
1150
  a._amount ??= "?";
1469
1151
  a.institution_name ??= "Mercury";
1470
1152
  a.payment_method ??= "ach";
1153
+ const action = a.action;
1154
+ const key = action ? `${name}:${action}` : name;
1471
1155
  const fmts = {
1472
- form_entity: 'Form a new {entity_type} named "{entity_name}" in {jurisdiction}',
1473
- convert_entity: "Convert entity to {new_entity_type}",
1474
- dissolve_entity: "Dissolve entity \u2014 {dissolution_reason}",
1475
- issue_equity: "Issue {shares} {grant_type} shares to {recipient_name}",
1476
- transfer_shares: "Transfer {shares} shares to {to_recipient_name}",
1477
- issue_safe: "Issue SAFE note to {investor_name} for {_amount}",
1478
- calculate_distribution: "Calculate {distribution_type} distribution of {_amount}",
1479
- create_invoice: "Create invoice for {customer_name} \u2014 {_amount}",
1480
- run_payroll: "Run payroll for {pay_period_start} to {pay_period_end}",
1481
- submit_payment: "Submit {_amount} payment to {recipient} via {payment_method}",
1482
- open_bank_account: "Open bank account at {institution_name}",
1483
- reconcile_ledger: "Reconcile ledger from {start_date} to {end_date}",
1484
- generate_contract: "Generate {template_type} contract for {counterparty_name}",
1485
- file_tax_document: "File {document_type} for tax year {tax_year}",
1486
- track_deadline: "Track {deadline_type} deadline \u2014 {description}",
1487
- classify_contractor: "Classify contractor {contractor_name} in {state}",
1488
- convene_meeting: "Convene {meeting_type} meeting",
1489
- cast_vote: "Cast {vote} vote",
1490
- schedule_meeting: "Schedule {meeting_type} meeting: {title}",
1491
- update_checklist: "Update workspace checklist",
1492
- create_agent: 'Create agent "{name}"',
1493
- send_agent_message: "Send message to agent",
1494
- update_agent: "Update agent configuration",
1495
- add_agent_skill: 'Add skill "{skill_name}" to agent'
1156
+ // workspace
1157
+ "workspace:status": "Get workspace status",
1158
+ "workspace:list_entities": "List all entities",
1159
+ "workspace:obligations": "List obligations",
1160
+ "workspace:billing": "Get billing status",
1161
+ // entity
1162
+ "entity:get_cap_table": "Get cap table",
1163
+ "entity:list_documents": "List documents",
1164
+ "entity:list_safe_notes": "List SAFE notes",
1165
+ "entity:create": 'Create pending {entity_type} named "{entity_name}"',
1166
+ "entity:add_founder": 'Add founder "{name}" ({role}, {ownership_pct}%)',
1167
+ "entity:finalize": "Finalize formation and generate documents + cap table",
1168
+ "entity:form": 'Form a new {entity_type} named "{entity_name}" in {jurisdiction}',
1169
+ "entity:convert": "Convert entity to {new_entity_type}",
1170
+ "entity:dissolve": "Dissolve entity \u2014 {reason}",
1171
+ // equity
1172
+ "equity:start_round": 'Start equity round "{name}"',
1173
+ "equity:add_security": "Add {quantity} shares to {recipient_name} in round",
1174
+ "equity:issue_round": "Issue all securities and close the round",
1175
+ "equity:issue": "Issue {shares} {grant_type} shares to {recipient_name}",
1176
+ "equity:issue_safe": "Issue SAFE note to {investor_name} for {_amount}",
1177
+ "equity:transfer": "Direct transfer {shares} shares (bypass governance)",
1178
+ "equity:distribution": "Calculate {distribution_type} distribution of {_amount}",
1179
+ // valuation
1180
+ "valuation:create": "Create {valuation_type} valuation effective {effective_date}",
1181
+ "valuation:submit": "Submit valuation for board approval",
1182
+ "valuation:approve": "Approve valuation",
1183
+ // meeting
1184
+ "meeting:schedule": 'Schedule {meeting_type} meeting: "{title}"',
1185
+ "meeting:notice": "Send notice for meeting",
1186
+ "meeting:convene": "Convene meeting",
1187
+ "meeting:vote": "Cast {vote_value} vote",
1188
+ "meeting:resolve": "Compute resolution for agenda item",
1189
+ "meeting:finalize_item": "Finalize agenda item to {status}",
1190
+ "meeting:adjourn": "Adjourn meeting",
1191
+ "meeting:cancel": "Cancel meeting",
1192
+ "meeting:consent": 'Create written consent: "{title}"',
1193
+ "meeting:attach_document": "Attach document to resolution",
1194
+ "meeting:list_items": "List agenda items for meeting",
1195
+ "meeting:list_votes": "List votes on agenda item",
1196
+ // finance
1197
+ "finance:create_invoice": "Create invoice for {customer_name} \u2014 {_amount}",
1198
+ "finance:run_payroll": "Run payroll for {pay_period_start} to {pay_period_end}",
1199
+ "finance:submit_payment": "Submit {_amount} payment to {recipient} via {payment_method}",
1200
+ "finance:open_bank_account": "Open bank account at {institution_name}",
1201
+ "finance:reconcile": "Reconcile ledger from {start_date} to {end_date}",
1202
+ // compliance
1203
+ "compliance:file_tax": "File {document_type} for tax year {tax_year}",
1204
+ "compliance:track_deadline": "Track {deadline_type} deadline \u2014 {description}",
1205
+ "compliance:classify_contractor": "Classify contractor {contractor_name} in {state}",
1206
+ "compliance:generate_contract": "Generate {template_type} contract for {counterparty_name}",
1207
+ // document
1208
+ "document:signing_link": "Get signing link for document",
1209
+ "document:signer_link": "Generate signer link for obligation",
1210
+ "document:download_link": "Get download link for document",
1211
+ "document:preview_pdf": "Preview document PDF for {document_id}",
1212
+ // checklist
1213
+ "checklist:get": "Get workspace checklist",
1214
+ "checklist:update": "Update workspace checklist",
1215
+ // agent
1216
+ "agent:list": "List agents",
1217
+ "agent:create": 'Create agent "{name}"',
1218
+ "agent:message": "Send message to agent",
1219
+ "agent:update": "Update agent configuration",
1220
+ "agent:add_skill": 'Add skill "{skill_name}" to agent'
1496
1221
  };
1497
- const fmt = fmts[name];
1222
+ const fmt = fmts[key];
1498
1223
  if (fmt) {
1499
1224
  try {
1500
1225
  return fmt.replace(/\{(\w+)\}/g, (_, k) => String(a[k] ?? "?"));
1501
1226
  } catch {
1502
1227
  }
1503
1228
  }
1504
- return name.replace(/_/g, " ");
1229
+ return action ? `${name} \u2192 ${action}` : name.replace(/_/g, " ");
1505
1230
  }
1506
1231
 
1507
1232
  // src/system-prompt.ts
@@ -1510,34 +1235,26 @@ var SYSTEM_PROMPT_BASE = `You are a corporate governance assistant for TheCorpor
1510
1235
  ## Context
1511
1236
  {context}
1512
1237
 
1513
- ## Capabilities
1514
- You can perform the full range of corporate operations:
1515
-
1516
- **Read operations:**
1517
- - View workspace status, entities, cap tables, documents
1518
- - List SAFE notes, equity grants, agents
1519
- - Check deadlines and compliance status
1238
+ ## Tools
1239
+ You have 10 tools, each with an \`action\` parameter that selects the operation:
1520
1240
 
1521
- **Write operations:**
1522
- - Form new LLCs and corporations in any US jurisdiction
1523
- - Issue equity (common, preferred, options, units)
1524
- - Issue SAFE notes to investors
1525
- - Transfer shares between holders
1526
- - Convert entities (LLC <> Corporation)
1527
- - Create invoices, run payroll, submit payments
1528
- - Open bank accounts, reconcile ledgers
1529
- - Generate contracts (NDAs, employment offers, consulting agreements)
1530
- - File tax documents (1099-NEC, K-1, 941, W-2, estimated tax)
1531
- - Generate signing links for documents (human-only signing)
1532
- - Track compliance deadlines
1533
- - Classify contractor risk (employee vs 1099)
1534
- - Convene governance meetings and cast votes
1535
- - Dissolve entities with full wind-down workflow
1241
+ | Tool | Actions |
1242
+ |------|---------|
1243
+ | **workspace** | status, list_entities, obligations, billing |
1244
+ | **entity** | get_cap_table, list_documents, list_safe_notes, form, create, add_founder, finalize, convert, dissolve |
1245
+ | **equity** | start_round, add_security, issue_round, issue, issue_safe, transfer, distribution |
1246
+ | **valuation** | create, submit, approve |
1247
+ | **meeting** | schedule, notice, convene, vote, resolve, finalize_item, adjourn, cancel, consent, attach_document, list_items, list_votes |
1248
+ | **finance** | create_invoice, run_payroll, submit_payment, open_bank_account, reconcile |
1249
+ | **compliance** | file_tax, track_deadline, classify_contractor, generate_contract |
1250
+ | **document** | signing_link, signer_link, download_link |
1251
+ | **checklist** | get, update |
1252
+ | **agent** | list, create, message, update, add_skill |
1536
1253
 
1537
1254
  ## Rules
1538
1255
  - All monetary values are in integer cents ($1,000 = 100000).
1539
1256
  - Be concise and helpful.
1540
- - **You MUST confirm with the user before calling ANY write tool.** Describe what you are about to do and wait for explicit approval. Never execute tools speculatively or "on behalf of" the user without their go-ahead.
1257
+ - **You MUST confirm with the user before calling ANY write action.** Describe what you are about to do and wait for explicit approval. Never execute tools speculatively or "on behalf of" the user without their go-ahead.
1541
1258
  - Don't ask for info available in platform config \u2014 use the correct values automatically.
1542
1259
  - If only one option exists for a field, use it without asking.
1543
1260
  - Don't make up data \u2014 only present what the tools return.
@@ -1551,29 +1268,70 @@ You can perform the full range of corporate operations:
1551
1268
  - Agent tools require a paid plan.
1552
1269
 
1553
1270
  ## Entity Formation Rules
1554
- - When forming an entity, you MUST ask about all founding members and their ownership allocations BEFORE calling the form_entity tool.
1271
+ - **Prefer the staged formation flow** over \`entity action=form\`:
1272
+ 1. \`entity action=create\` \u2014 type + name \u2192 returns \`entity_id\`
1273
+ 2. \`entity action=add_founder\` \u2014 add each founder one at a time (name, email, role, ownership_pct)
1274
+ 3. \`entity action=finalize\` \u2014 generates documents + cap table
1275
+ - When using \`entity action=form\` (legacy), you MUST ask about all founding members and their ownership allocations BEFORE calling it.
1555
1276
  - For LLCs, ownership percentages must total 100%.
1556
1277
 
1278
+ ## Equity Round Rules
1279
+ - **Prefer the staged round flow** for issuing equity to multiple holders:
1280
+ 1. \`equity action=start_round\` \u2014 entity_id + name + issuer_legal_entity_id \u2192 returns \`round_id\`
1281
+ 2. \`equity action=add_security\` \u2014 add each holder's shares one at a time (round_id, instrument_id, quantity, recipient_name, plus holder_id or email)
1282
+ 3. \`equity action=issue_round\` \u2014 creates positions for all pending securities, closes the round, and auto-creates a board meeting agenda item for approval (or adds to an existing pending meeting)
1283
+ 4. Complete the board meeting lifecycle (notice \u2192 convene \u2192 vote \u2192 resolve \u2192 finalize \u2192 adjourn) to formally approve the round
1284
+ - The entity must already have a cap table with holders and instruments set up.
1285
+ - Use \`entity action=get_cap_table\` to look up holder IDs, instrument IDs, and the issuer legal entity ID before starting.
1286
+ - \`equity action=add_security\` can resolve recipients by \`holder_id\`, \`email\`, or auto-create from \`recipient_name\`.
1287
+
1288
+ ## Share Transfer Rules
1289
+ - **Prefer the transfer workflow** for share transfers \u2014 it includes bylaws review, ROFR, board approval, document generation, and signatures.
1290
+ - \`equity action=transfer\` is a direct bypass that skips all governance. It requires \`skip_governance_review: true\` to confirm the caller intentionally wants to skip the workflow. Only use it for corrective entries or when the user explicitly requests skipping governance.
1291
+
1292
+ ## Valuation Rules
1293
+ - To create and approve a 409A valuation:
1294
+ 1. \`valuation action=create\` \u2014 type=four_oh_nine_a + effective_date + methodology + fmv_per_share_cents \u2192 valuation_id (Draft)
1295
+ 2. \`valuation action=submit\` \u2014 Draft \u2192 PendingApproval; auto-creates board meeting agenda item (or adds to existing pending meeting)
1296
+ 3. Complete the board meeting lifecycle (notice \u2192 convene \u2192 vote \u2192 resolve \u2192 finalize \u2192 adjourn)
1297
+ 4. \`valuation action=approve\` \u2014 PendingApproval \u2192 Approved; pass resolution_id from the board vote
1298
+ - 409A valuations auto-expire after 365 days from effective_date
1299
+ - When a new 409A is approved, any previous approved 409A is auto-superseded
1300
+
1301
+ ## Governance Meeting Rules
1302
+ - Full meeting lifecycle:
1303
+ 1. \`meeting action=schedule\` \u2014 entity_id + body_id + meeting_type + title + agenda_item_titles \u2192 meeting_id
1304
+ 2. \`meeting action=notice\` \u2014 Draft \u2192 Noticed
1305
+ 3. \`meeting action=convene\` \u2014 present_seat_ids \u2192 quorum check \u2192 Noticed \u2192 Convened
1306
+ 4. \`meeting action=vote\` \u2014 vote on each agenda item (requires Convened + quorum met)
1307
+ 5. \`meeting action=resolve\` \u2014 tally votes \u2192 create Resolution
1308
+ 6. \`meeting action=finalize_item\` \u2014 mark item as Voted (requires resolution), Discussed, Tabled, or Withdrawn
1309
+ 7. \`meeting action=adjourn\` \u2014 Convened \u2192 Adjourned
1310
+ - For written consent (no physical meeting): use \`meeting action=consent\` \u2014 auto-convened, skip notice/convene
1311
+ - Use \`meeting action=list_items\` to get agenda_item_ids after scheduling
1312
+ - Use \`entity action=get_cap_table\` or governance read tools to look up body_id and seat holder IDs
1313
+ - \`meeting action=cancel\` works from Draft or Noticed status only
1314
+
1557
1315
  ## Document Signing Rules
1558
1316
  - You CANNOT sign documents on behalf of users. Signing is a human action.
1559
- - Use \`get_signing_link\` to generate a signing URL for a document.
1317
+ - Use \`document action=signing_link\` to generate a signing URL for a document.
1560
1318
  - Present the signing link so users can open it and sign themselves.
1561
1319
  - NEVER attempt to sign, execute, or complete signature actions automatically.
1562
- - The \`get_signing_link\` tool does NOT sign anything \u2014 it only returns a URL.
1320
+ - The \`document action=signing_link\` tool does NOT sign anything \u2014 it only returns a URL.
1563
1321
 
1564
1322
  ## User Journey
1565
1323
  After completing any action, ALWAYS present the logical next step(s) as a
1566
1324
  numbered list. The user should never wonder "what now?" \u2014 guide them forward.
1567
1325
 
1568
- After entity formation:
1569
- 1. The \`form_entity\` response includes a \`documents\` array with document IDs. These documents are created immediately \u2014 they are NEVER "still being generated" or delayed.
1570
- 2. Immediately call \`get_signing_link\` for each document ID in the response to get signing URLs.
1326
+ After entity formation (staged or legacy):
1327
+ 1. The \`entity action=finalize\` (or \`entity action=form\`) response includes a \`document_ids\` array. These documents are created immediately \u2014 they are NEVER "still being generated" or delayed.
1328
+ 2. Immediately call \`document action=signing_link\` for each document ID in the response to get signing URLs.
1571
1329
  3. Present the signing links to the user right away. Do NOT tell the user to "check back later" or that documents are "being prepared" \u2014 they already exist.
1572
1330
  4. Then: "Documents signed! Next: apply for an EIN, open a bank account, or issue equity."
1573
1331
 
1574
1332
  After document generation:
1575
1333
  1. Present signing links immediately \u2014 don't wait for the user to ask.
1576
- 2. Use the document IDs from the tool response \u2014 do NOT call \`list_documents\` to re-fetch them.
1334
+ 2. Use the document IDs from the tool response \u2014 do NOT call \`entity action=list_documents\` to re-fetch them.
1577
1335
 
1578
1336
  After signing:
1579
1337
  1. "Documents are signed! Next: file for EIN, open a bank account, or add team members."
@@ -1587,9 +1345,9 @@ General pattern:
1587
1345
  - If there are signing obligations, proactively generate and present the signing links.
1588
1346
  - Never just say "done" \u2014 always show what comes next.
1589
1347
 
1590
- After major actions, use update_checklist to track progress. Use markdown checkbox
1591
- format (- [x] / - [ ]). Call get_checklist first to see current state, then
1592
- update_checklist with checked-off items. This helps users see where they are.
1348
+ After major actions, use \`checklist action=update\` to track progress. Use markdown checkbox
1349
+ format (- [x] / - [ ]). Call \`checklist action=get\` first to see current state, then
1350
+ update with checked-off items. This helps users see where they are.
1593
1351
 
1594
1352
  {extra_sections}`;
1595
1353
  function formatConfigSection(cfgData) {
@@ -1656,22 +1414,14 @@ var TOOL_REGISTRY = {};
1656
1414
  for (const td of GENERATED_TOOL_DEFINITIONS) {
1657
1415
  TOOL_REGISTRY[td.function.name] = td.function;
1658
1416
  }
1659
- var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
1660
- "get_workspace_status",
1661
- "list_entities",
1662
- "get_cap_table",
1663
- "list_documents",
1664
- "list_safe_notes",
1665
- "list_agents",
1666
- "get_checklist",
1667
- "get_signing_link",
1668
- "list_obligations",
1669
- "get_billing_status"
1417
+ var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
1418
+ "workspace",
1419
+ "checklist"
1670
1420
  ]);
1671
1421
  export {
1672
1422
  CorpAPIClient,
1673
1423
  GENERATED_TOOL_DEFINITIONS,
1674
- READ_ONLY_TOOLS2 as READ_ONLY_TOOLS,
1424
+ READ_ONLY_TOOLS,
1675
1425
  SYSTEM_PROMPT_BASE,
1676
1426
  SessionExpiredError,
1677
1427
  TOOL_DEFINITIONS,