@thecorporation/corp-tools 1.0.4 → 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/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # @thecorporation/corp-tools
2
2
 
3
- Shared API client, tool definitions, and execution engine for The Corporation. Used by [`@thecorporation/cli`](https://www.npmjs.com/package/@thecorporation/cli), [`@thecorporation/mcp-server`](https://www.npmjs.com/package/@thecorporation/mcp-server), and the chat service.
3
+ The shared foundation for TheCorporation's client ecosystem. Typed API client, 10 consolidated tool definitions, and the execution engine that powers the CLI, MCP server, and chat service. Every tool call — whether initiated by a human or an agent — flows through the same pipeline: validate, execute, commit, receipt.
4
4
 
5
- Part of [The Corporation](https://thecorporation.ai) agent-native corporate infrastructure.
5
+ Used by [`@thecorporation/cli`](https://www.npmjs.com/package/@thecorporation/cli), [`@thecorporation/mcp-server`](https://www.npmjs.com/package/@thecorporation/mcp-server), and the chat service.
6
+
7
+ Part of [TheCorporation](https://thecorporation.ai) — version-controlled governance, autonomous agents, and open-source corporate infrastructure.
6
8
 
7
9
  ## Install
8
10
 
@@ -105,12 +107,12 @@ import {
105
107
  // OpenAI-compatible function definitions for LLM tool calling
106
108
  console.log(TOOL_DEFINITIONS);
107
109
 
108
- // Execute a tool call
109
- const result = await executeTool("form_entity", args, client, { dataDir: "." });
110
+ // Execute a tool call (consolidated: tool name + action)
111
+ const result = await executeTool("entity", { action: "form", ...args }, client, { dataDir: "." });
110
112
 
111
- // Check if a tool mutates state (useful for confirmation gating)
112
- isWriteTool("form_entity"); // true
113
- isWriteTool("list_entities"); // false
113
+ // Check if a tool+action mutates state (useful for confirmation gating)
114
+ isWriteTool("entity", { action: "form" }); // true
115
+ isWriteTool("workspace", { action: "list_entities" }); // false
114
116
  ```
115
117
 
116
118
  ### System Prompt
@@ -121,27 +123,27 @@ import { SYSTEM_PROMPT_BASE, formatConfigSection } from "@thecorporation/corp-to
121
123
 
122
124
  ## Tools
123
125
 
124
- 36 tools across corporate governance domains:
126
+ 10 consolidated tools with action-based dispatch:
125
127
 
126
- | Category | Tools |
128
+ | Tool | Actions |
127
129
  |---|---|
128
- | **Entities** | `form_entity`, `convert_entity`, `dissolve_entity`, `list_entities` |
129
- | **Equity** | `issue_equity`, `issue_safe`, `transfer_shares`, `calculate_distribution`, `get_cap_table`, `list_safe_notes` |
130
- | **Finance** | `create_invoice`, `run_payroll`, `submit_payment`, `open_bank_account`, `reconcile_ledger`, `classify_contractor` |
131
- | **Documents** | `generate_contract`, `list_documents`, `get_document_link`, `get_signing_link` |
132
- | **Governance** | `convene_meeting`, `schedule_meeting`, `cast_vote` |
133
- | **Tax** | `file_tax_document`, `track_deadline` |
134
- | **Agents** | `create_agent`, `send_agent_message`, `update_agent`, `add_agent_skill`, `list_agents` |
135
- | **Workspace** | `get_workspace_status`, `list_obligations`, `get_billing_status`, `get_checklist`, `update_checklist`, `get_signer_link` |
130
+ | **workspace** | status, list_entities, obligations, billing |
131
+ | **entity** | get_cap_table, list_documents, list_safe_notes, form, create, add_founder, finalize, convert, dissolve |
132
+ | **equity** | start_round, add_security, issue_round, issue, issue_safe, transfer, distribution |
133
+ | **valuation** | create, submit, approve |
134
+ | **meeting** | schedule, notice, convene, vote, resolve, finalize_item, adjourn, cancel, consent, attach_document, list_items, list_votes |
135
+ | **finance** | create_invoice, run_payroll, submit_payment, open_bank_account, reconcile |
136
+ | **compliance** | file_tax, track_deadline, classify_contractor, generate_contract |
137
+ | **document** | signing_link, signer_link, download_link |
138
+ | **checklist** | get, update |
139
+ | **agent** | list, create, message, update, add_skill |
136
140
 
137
141
  ## Exports
138
142
 
139
143
  - `CorpAPIClient` — typed API client with methods for every endpoint
140
144
  - `TOOL_DEFINITIONS` / `GENERATED_TOOL_DEFINITIONS` — OpenAI-compatible function schemas
141
- - `TOOL_REGISTRY` — name-to-definition lookup
142
- - `READ_ONLY_TOOLS` — set of tool names that don't mutate state
143
- - `executeTool()` — dispatches a tool call and returns the result
144
- - `isWriteTool()` — checks whether a tool mutates state
145
+ - `executeTool()` — dispatches a tool call by name + action and returns the result
146
+ - `isWriteTool()` — checks whether a tool+action mutates state
145
147
  - `describeToolCall()` — human-readable description of a tool call
146
148
  - `SYSTEM_PROMPT_BASE` / `formatConfigSection()` — system prompt utilities
147
149
  - `provisionWorkspace()` — provisions a new workspace
package/dist/index.d.ts CHANGED
@@ -96,6 +96,7 @@ declare class CorpAPIClient {
96
96
  constructor(apiUrl: string, apiKey: string, workspaceId: string);
97
97
  private headers;
98
98
  private request;
99
+ private throwIfError;
99
100
  private get;
100
101
  private post;
101
102
  private postWithParams;
@@ -119,6 +120,9 @@ declare class CorpAPIClient {
119
120
  getShareTransfers(entityId: string): Promise<ApiRecord[]>;
120
121
  getValuations(entityId: string): Promise<ApiRecord[]>;
121
122
  getCurrent409a(entityId: string): Promise<ApiRecord>;
123
+ createValuation(data: ApiRecord): Promise<ApiRecord>;
124
+ submitValuationForApproval(valuationId: string, entityId: string): Promise<ApiRecord>;
125
+ approveValuation(valuationId: string, entityId: string, resolutionId?: string): Promise<ApiRecord>;
122
126
  issueEquity(data: ApiRecord): Promise<ApiRecord>;
123
127
  issueSafe(data: ApiRecord): Promise<ApiRecord>;
124
128
  transferShares(data: ApiRecord): Promise<ApiRecord>;
@@ -129,6 +133,9 @@ declare class CorpAPIClient {
129
133
  acceptEquityRound(roundId: string, data: AcceptEquityRoundRequest): Promise<EquityRoundResponse>;
130
134
  previewRoundConversion(data: PreviewRoundConversionRequest): Promise<ApiRecord>;
131
135
  executeRoundConversion(data: ExecuteRoundConversionRequest): Promise<ApiRecord>;
136
+ startEquityRound(data: ApiRecord): Promise<ApiRecord>;
137
+ addRoundSecurity(roundId: string, data: ApiRecord): Promise<ApiRecord>;
138
+ issueRound(roundId: string, data: ApiRecord): Promise<ApiRecord>;
132
139
  createExecutionIntent(data: CreateExecutionIntentRequest): Promise<IntentResponse>;
133
140
  evaluateIntent(intentId: string, entityId: string): Promise<ApiRecord>;
134
141
  authorizeIntent(intentId: string, entityId: string): Promise<ApiRecord>;
@@ -139,6 +146,15 @@ declare class CorpAPIClient {
139
146
  scheduleMeeting(data: ApiRecord): Promise<ApiRecord>;
140
147
  conveneMeeting(meetingId: string, entityId: string, data: ApiRecord): Promise<ApiRecord>;
141
148
  castVote(entityId: string, meetingId: string, itemId: string, data: ApiRecord): Promise<ApiRecord>;
149
+ sendNotice(meetingId: string, entityId: string): Promise<ApiRecord>;
150
+ adjournMeeting(meetingId: string, entityId: string): Promise<ApiRecord>;
151
+ cancelMeeting(meetingId: string, entityId: string): Promise<ApiRecord>;
152
+ finalizeAgendaItem(meetingId: string, itemId: string, data: ApiRecord): Promise<ApiRecord>;
153
+ computeResolution(meetingId: string, itemId: string, entityId: string, data: ApiRecord): Promise<ApiRecord>;
154
+ attachResolutionDocument(meetingId: string, resolutionId: string, data: ApiRecord): Promise<ApiRecord>;
155
+ writtenConsent(data: ApiRecord): Promise<ApiRecord>;
156
+ listAgendaItems(meetingId: string, entityId: string): Promise<ApiRecord[]>;
157
+ listVotes(meetingId: string, itemId: string, entityId: string): Promise<ApiRecord[]>;
142
158
  getEntityDocuments(entityId: string): Promise<ApiRecord[]>;
143
159
  generateContract(data: ApiRecord): Promise<ApiRecord>;
144
160
  getSigningLink(documentId: string): ApiRecord;
@@ -157,6 +173,10 @@ declare class CorpAPIClient {
157
173
  getFormation(id: string): Promise<ApiRecord>;
158
174
  getFormationDocuments(id: string): Promise<ApiRecord[]>;
159
175
  createFormation(data: ApiRecord): Promise<ApiRecord>;
176
+ createFormationWithCapTable(data: ApiRecord): Promise<ApiRecord>;
177
+ createPendingEntity(data: ApiRecord): Promise<ApiRecord>;
178
+ addFounder(entityId: string, data: ApiRecord): Promise<ApiRecord>;
179
+ finalizeFormation(entityId: string): Promise<ApiRecord>;
160
180
  getHumanObligations(): Promise<ApiRecord[]>;
161
181
  getSignerToken(obligationId: string): Promise<ApiRecord>;
162
182
  seedDemo(name: string): Promise<ApiRecord>;
@@ -185,7 +205,7 @@ interface ToolContext {
185
205
  onEntityFormed?: (entityId: string) => void;
186
206
  }
187
207
  declare const TOOL_DEFINITIONS: Record<string, unknown>[];
188
- declare function isWriteTool(name: string): boolean;
208
+ declare function isWriteTool(name: string, args?: Record<string, unknown>): boolean;
189
209
  declare function executeTool(name: string, args: Record<string, unknown>, client: CorpAPIClient, ctx: ToolContext): Promise<string>;
190
210
 
191
211
  declare function describeToolCall(name: string, args: Record<string, unknown>): string;
@@ -193,7 +213,7 @@ declare function describeToolCall(name: string, args: Record<string, unknown>):
193
213
  /**
194
214
  * System prompt base and config formatter.
195
215
  */
196
- declare const SYSTEM_PROMPT_BASE = "You are a corporate governance assistant for TheCorporation, an agentic corporate governance platform.\n\n## Context\n{context}\n\n## Capabilities\nYou can perform the full range of corporate operations:\n\n**Read operations:**\n- View workspace status, entities, cap tables, documents\n- List SAFE notes, equity grants, agents\n- Check deadlines and compliance status\n\n**Write operations:**\n- Form new LLCs and corporations in any US jurisdiction\n- Issue equity (common, preferred, options, units)\n- Issue SAFE notes to investors\n- Transfer shares between holders\n- Convert entities (LLC <> Corporation)\n- Create invoices, run payroll, submit payments\n- Open bank accounts, reconcile ledgers\n- Generate contracts (NDAs, employment offers, consulting agreements)\n- File tax documents (1099-NEC, K-1, 941, W-2, estimated tax)\n- Generate signing links for documents (human-only signing)\n- Track compliance deadlines\n- Classify contractor risk (employee vs 1099)\n- Convene governance meetings and cast votes\n- Dissolve entities with full wind-down workflow\n\n## Rules\n- All monetary values are in integer cents ($1,000 = 100000).\n- Be concise and helpful.\n- **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.\n- Don't ask for info available in platform config \u2014 use the correct values automatically.\n- If only one option exists for a field, use it without asking.\n- Don't make up data \u2014 only present what the tools return.\n- If a tool returns an error, explain it simply without exposing raw error details.\n- NEVER create an agent to answer a question you can answer yourself. You are the assistant \u2014 answer questions directly using your knowledge and the read tools.\n\n## Agent Rules\n- Agents are for **delegating recurring corporate operations tasks** that the user explicitly requests \u2014 e.g. \"process incoming invoices\", \"monitor compliance deadlines\", \"handle payroll every two weeks\".\n- Agents are NOT for research, answering questions, or one-off lookups. If the user asks a question, YOU answer it.\n- NEVER proactively suggest or create an agent unless the user specifically asks for one.\n- Agent tools require a paid plan.\n\n## Entity Formation Rules\n- When forming an entity, you MUST ask about all founding members and their ownership allocations BEFORE calling the form_entity tool.\n- For LLCs, ownership percentages must total 100%.\n\n## Document Signing Rules\n- You CANNOT sign documents on behalf of users. Signing is a human action.\n- Use `get_signing_link` to generate a signing URL for a document.\n- Present the signing link so users can open it and sign themselves.\n- NEVER attempt to sign, execute, or complete signature actions automatically.\n- The `get_signing_link` tool does NOT sign anything \u2014 it only returns a URL.\n\n## User Journey\nAfter completing any action, ALWAYS present the logical next step(s) as a\nnumbered list. The user should never wonder \"what now?\" \u2014 guide them forward.\n\nAfter entity formation:\n1. 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.\n2. Immediately call `get_signing_link` for each document ID in the response to get signing URLs.\n3. 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.\n4. Then: \"Documents signed! Next: apply for an EIN, open a bank account, or issue equity.\"\n\nAfter document generation:\n1. Present signing links immediately \u2014 don't wait for the user to ask.\n2. Use the document IDs from the tool response \u2014 do NOT call `list_documents` to re-fetch them.\n\nAfter signing:\n1. \"Documents are signed! Next: file for EIN, open a bank account, or add team members.\"\n\nAfter equity issuance:\n1. \"Equity issued! Next: generate the stock certificate for signing, or issue more grants.\"\n\nGeneral pattern:\n- Always end with 1-2 concrete next actions the user can take.\n- Phrase them as questions or suggestions: \"Would you like to [next step]?\"\n- If there are signing obligations, proactively generate and present the signing links.\n- Never just say \"done\" \u2014 always show what comes next.\n\nAfter major actions, use update_checklist to track progress. Use markdown checkbox\nformat (- [x] / - [ ]). Call get_checklist first to see current state, then\nupdate_checklist with checked-off items. This helps users see where they are.\n\n{extra_sections}";
216
+ declare const SYSTEM_PROMPT_BASE = "You are a corporate governance assistant for TheCorporation, an agentic corporate governance platform.\n\n## Context\n{context}\n\n## Tools\nYou have 10 tools, each with an `action` parameter that selects the operation:\n\n| Tool | Actions |\n|------|---------|\n| **workspace** | status, list_entities, obligations, billing |\n| **entity** | get_cap_table, list_documents, list_safe_notes, form, create, add_founder, finalize, convert, dissolve |\n| **equity** | start_round, add_security, issue_round, issue, issue_safe, transfer, distribution |\n| **valuation** | create, submit, approve |\n| **meeting** | schedule, notice, convene, vote, resolve, finalize_item, adjourn, cancel, consent, attach_document, list_items, list_votes |\n| **finance** | create_invoice, run_payroll, submit_payment, open_bank_account, reconcile |\n| **compliance** | file_tax, track_deadline, classify_contractor, generate_contract |\n| **document** | signing_link, signer_link, download_link |\n| **checklist** | get, update |\n| **agent** | list, create, message, update, add_skill |\n\n## Rules\n- All monetary values are in integer cents ($1,000 = 100000).\n- Be concise and helpful.\n- **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.\n- Don't ask for info available in platform config \u2014 use the correct values automatically.\n- If only one option exists for a field, use it without asking.\n- Don't make up data \u2014 only present what the tools return.\n- If a tool returns an error, explain it simply without exposing raw error details.\n- NEVER create an agent to answer a question you can answer yourself. You are the assistant \u2014 answer questions directly using your knowledge and the read tools.\n\n## Agent Rules\n- Agents are for **delegating recurring corporate operations tasks** that the user explicitly requests \u2014 e.g. \"process incoming invoices\", \"monitor compliance deadlines\", \"handle payroll every two weeks\".\n- Agents are NOT for research, answering questions, or one-off lookups. If the user asks a question, YOU answer it.\n- NEVER proactively suggest or create an agent unless the user specifically asks for one.\n- Agent tools require a paid plan.\n\n## Entity Formation Rules\n- **Prefer the staged formation flow** over `entity action=form`:\n 1. `entity action=create` \u2014 type + name \u2192 returns `entity_id`\n 2. `entity action=add_founder` \u2014 add each founder one at a time (name, email, role, ownership_pct)\n 3. `entity action=finalize` \u2014 generates documents + cap table\n- When using `entity action=form` (legacy), you MUST ask about all founding members and their ownership allocations BEFORE calling it.\n- For LLCs, ownership percentages must total 100%.\n\n## Equity Round Rules\n- **Prefer the staged round flow** for issuing equity to multiple holders:\n 1. `equity action=start_round` \u2014 entity_id + name + issuer_legal_entity_id \u2192 returns `round_id`\n 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)\n 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)\n 4. Complete the board meeting lifecycle (notice \u2192 convene \u2192 vote \u2192 resolve \u2192 finalize \u2192 adjourn) to formally approve the round\n- The entity must already have a cap table with holders and instruments set up.\n- Use `entity action=get_cap_table` to look up holder IDs, instrument IDs, and the issuer legal entity ID before starting.\n- `equity action=add_security` can resolve recipients by `holder_id`, `email`, or auto-create from `recipient_name`.\n\n## Share Transfer Rules\n- **Prefer the transfer workflow** for share transfers \u2014 it includes bylaws review, ROFR, board approval, document generation, and signatures.\n- `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.\n\n## Valuation Rules\n- To create and approve a 409A valuation:\n 1. `valuation action=create` \u2014 type=four_oh_nine_a + effective_date + methodology + fmv_per_share_cents \u2192 valuation_id (Draft)\n 2. `valuation action=submit` \u2014 Draft \u2192 PendingApproval; auto-creates board meeting agenda item (or adds to existing pending meeting)\n 3. Complete the board meeting lifecycle (notice \u2192 convene \u2192 vote \u2192 resolve \u2192 finalize \u2192 adjourn)\n 4. `valuation action=approve` \u2014 PendingApproval \u2192 Approved; pass resolution_id from the board vote\n- 409A valuations auto-expire after 365 days from effective_date\n- When a new 409A is approved, any previous approved 409A is auto-superseded\n\n## Governance Meeting Rules\n- Full meeting lifecycle:\n 1. `meeting action=schedule` \u2014 entity_id + body_id + meeting_type + title + agenda_item_titles \u2192 meeting_id\n 2. `meeting action=notice` \u2014 Draft \u2192 Noticed\n 3. `meeting action=convene` \u2014 present_seat_ids \u2192 quorum check \u2192 Noticed \u2192 Convened\n 4. `meeting action=vote` \u2014 vote on each agenda item (requires Convened + quorum met)\n 5. `meeting action=resolve` \u2014 tally votes \u2192 create Resolution\n 6. `meeting action=finalize_item` \u2014 mark item as Voted (requires resolution), Discussed, Tabled, or Withdrawn\n 7. `meeting action=adjourn` \u2014 Convened \u2192 Adjourned\n- For written consent (no physical meeting): use `meeting action=consent` \u2014 auto-convened, skip notice/convene\n- Use `meeting action=list_items` to get agenda_item_ids after scheduling\n- Use `entity action=get_cap_table` or governance read tools to look up body_id and seat holder IDs\n- `meeting action=cancel` works from Draft or Noticed status only\n\n## Document Signing Rules\n- You CANNOT sign documents on behalf of users. Signing is a human action.\n- Use `document action=signing_link` to generate a signing URL for a document.\n- Present the signing link so users can open it and sign themselves.\n- NEVER attempt to sign, execute, or complete signature actions automatically.\n- The `document action=signing_link` tool does NOT sign anything \u2014 it only returns a URL.\n\n## User Journey\nAfter completing any action, ALWAYS present the logical next step(s) as a\nnumbered list. The user should never wonder \"what now?\" \u2014 guide them forward.\n\nAfter entity formation (staged or legacy):\n1. 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.\n2. Immediately call `document action=signing_link` for each document ID in the response to get signing URLs.\n3. 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.\n4. Then: \"Documents signed! Next: apply for an EIN, open a bank account, or issue equity.\"\n\nAfter document generation:\n1. Present signing links immediately \u2014 don't wait for the user to ask.\n2. Use the document IDs from the tool response \u2014 do NOT call `entity action=list_documents` to re-fetch them.\n\nAfter signing:\n1. \"Documents are signed! Next: file for EIN, open a bank account, or add team members.\"\n\nAfter equity issuance:\n1. \"Equity issued! Next: generate the stock certificate for signing, or issue more grants.\"\n\nGeneral pattern:\n- Always end with 1-2 concrete next actions the user can take.\n- Phrase them as questions or suggestions: \"Would you like to [next step]?\"\n- If there are signing obligations, proactively generate and present the signing links.\n- Never just say \"done\" \u2014 always show what comes next.\n\nAfter major actions, use `checklist action=update` to track progress. Use markdown checkbox\nformat (- [x] / - [ ]). Call `checklist action=get` first to see current state, then\nupdate with checked-off items. This helps users see where they are.\n\n{extra_sections}";
197
217
  declare function formatConfigSection(cfgData: Record<string, unknown>): string;
198
218
 
199
219
  declare const GENERATED_TOOL_DEFINITIONS: Record<string, unknown>[];
@@ -210,6 +230,10 @@ interface ToolFunction {
210
230
  }
211
231
  /** Registry: tool name → function metadata (description + parameters). */
212
232
  declare const TOOL_REGISTRY: Record<string, ToolFunction>;
233
+ /**
234
+ * Read-only tool:action pairs that don't require user confirmation.
235
+ * @deprecated Use isWriteTool(name, args) instead for action-aware checking.
236
+ */
213
237
  declare const READ_ONLY_TOOLS: Set<string>;
214
238
 
215
239
  export { type AcceptEquityRoundRequest, type ApiRecord, type ApplyEquityRoundTermsRequest, type BoardApproveEquityRoundRequest, CorpAPIClient, type CorpConfig, type CreateEquityRoundRequest, type CreateExecutionIntentRequest, type EquityRoundResponse, type ExecuteRoundConversionRequest, GENERATED_TOOL_DEFINITIONS, type IntentResponse, type LLMResponse, type PreviewRoundConversionRequest, READ_ONLY_TOOLS, SYSTEM_PROMPT_BASE, SessionExpiredError, TOOL_DEFINITIONS, TOOL_REGISTRY, type ToolCall, type ToolContext, describeToolCall, executeTool, formatConfigSection, isWriteTool, provisionWorkspace };