@elevasis/sdk 0.8.7 → 0.8.9

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/cli.cjs CHANGED
@@ -43883,7 +43883,7 @@ function wrapAction(commandName, fn) {
43883
43883
  // package.json
43884
43884
  var package_default = {
43885
43885
  name: "@elevasis/sdk",
43886
- version: "0.8.7",
43886
+ version: "0.8.9",
43887
43887
  description: "SDK for building Elevasis organization resources",
43888
43888
  type: "module",
43889
43889
  bin: {
package/dist/index.d.ts CHANGED
@@ -1348,6 +1348,119 @@ type Database = {
1348
1348
  }
1349
1349
  ];
1350
1350
  };
1351
+ acq_content: {
1352
+ Row: {
1353
+ body: string | null;
1354
+ created_at: string;
1355
+ id: string;
1356
+ organization_id: string;
1357
+ pillar: string;
1358
+ status: string;
1359
+ title: string;
1360
+ updated_at: string;
1361
+ };
1362
+ Insert: {
1363
+ body?: string | null;
1364
+ created_at?: string;
1365
+ id?: string;
1366
+ organization_id: string;
1367
+ pillar: string;
1368
+ status?: string;
1369
+ title: string;
1370
+ updated_at?: string;
1371
+ };
1372
+ Update: {
1373
+ body?: string | null;
1374
+ created_at?: string;
1375
+ id?: string;
1376
+ organization_id?: string;
1377
+ pillar?: string;
1378
+ status?: string;
1379
+ title?: string;
1380
+ updated_at?: string;
1381
+ };
1382
+ Relationships: [
1383
+ {
1384
+ foreignKeyName: "acq_content_organization_id_fkey";
1385
+ columns: ["organization_id"];
1386
+ isOneToOne: false;
1387
+ referencedRelation: "organizations";
1388
+ referencedColumns: ["id"];
1389
+ }
1390
+ ];
1391
+ };
1392
+ acq_content_distributions: {
1393
+ Row: {
1394
+ adapted_body: string | null;
1395
+ content_id: string;
1396
+ created_at: string;
1397
+ format: string;
1398
+ id: string;
1399
+ media_urls: Json;
1400
+ metrics: Json;
1401
+ metrics_updated_at: string | null;
1402
+ organization_id: string;
1403
+ platform: string;
1404
+ platform_post_id: string | null;
1405
+ platform_url: string | null;
1406
+ published_at: string | null;
1407
+ scheduled_at: string | null;
1408
+ status: string;
1409
+ updated_at: string;
1410
+ };
1411
+ Insert: {
1412
+ adapted_body?: string | null;
1413
+ content_id: string;
1414
+ created_at?: string;
1415
+ format: string;
1416
+ id?: string;
1417
+ media_urls?: Json;
1418
+ metrics?: Json;
1419
+ metrics_updated_at?: string | null;
1420
+ organization_id: string;
1421
+ platform: string;
1422
+ platform_post_id?: string | null;
1423
+ platform_url?: string | null;
1424
+ published_at?: string | null;
1425
+ scheduled_at?: string | null;
1426
+ status?: string;
1427
+ updated_at?: string;
1428
+ };
1429
+ Update: {
1430
+ adapted_body?: string | null;
1431
+ content_id?: string;
1432
+ created_at?: string;
1433
+ format?: string;
1434
+ id?: string;
1435
+ media_urls?: Json;
1436
+ metrics?: Json;
1437
+ metrics_updated_at?: string | null;
1438
+ organization_id?: string;
1439
+ platform?: string;
1440
+ platform_post_id?: string | null;
1441
+ platform_url?: string | null;
1442
+ published_at?: string | null;
1443
+ scheduled_at?: string | null;
1444
+ status?: string;
1445
+ updated_at?: string;
1446
+ };
1447
+ Relationships: [
1448
+ {
1449
+ foreignKeyName: "acq_content_distributions_content_id_fkey";
1450
+ columns: ["content_id"];
1451
+ isOneToOne: false;
1452
+ referencedRelation: "acq_content";
1453
+ referencedColumns: ["id"];
1454
+ },
1455
+ {
1456
+ foreignKeyName: "acq_content_distributions_organization_id_fkey";
1457
+ columns: ["organization_id"];
1458
+ isOneToOne: false;
1459
+ referencedRelation: "organizations";
1460
+ referencedColumns: ["id"];
1461
+ }
1462
+ ];
1463
+ };
1351
1464
  acq_deals: {
1352
1465
  Row: {
1353
1466
  attio_deal_id: string;
@@ -1567,6 +1680,173 @@ type Database = {
1567
1680
  }
1568
1681
  ];
1569
1682
  };
1683
+ acq_seo_metrics: {
1684
+ Row: {
1685
+ ai_citations: Json | null;
1686
+ avg_position: number | null;
1687
+ clicks: number | null;
1688
+ created_at: string;
1689
+ cta_clicks: number | null;
1690
+ ctr: number | null;
1691
+ data_point_count: number | null;
1692
+ faq_count: number | null;
1693
+ form_submissions: number | null;
1694
+ id: string;
1695
+ impressions: number | null;
1696
+ organization_id: string;
1697
+ period: string;
1698
+ quality_score: number | null;
1699
+ readability: number | null;
1700
+ scroll_100: number | null;
1701
+ scroll_25: number | null;
1702
+ scroll_50: number | null;
1703
+ scroll_75: number | null;
1704
+ seo_page_id: string;
1705
+ word_count: number | null;
1706
+ };
1707
+ Insert: {
1708
+ ai_citations?: Json | null;
1709
+ avg_position?: number | null;
1710
+ clicks?: number | null;
1711
+ created_at?: string;
1712
+ cta_clicks?: number | null;
1713
+ ctr?: number | null;
1714
+ data_point_count?: number | null;
1715
+ faq_count?: number | null;
1716
+ form_submissions?: number | null;
1717
+ id?: string;
1718
+ impressions?: number | null;
1719
+ organization_id: string;
1720
+ period: string;
1721
+ quality_score?: number | null;
1722
+ readability?: number | null;
1723
+ scroll_100?: number | null;
1724
+ scroll_25?: number | null;
1725
+ scroll_50?: number | null;
1726
+ scroll_75?: number | null;
1727
+ seo_page_id: string;
1728
+ word_count?: number | null;
1729
+ };
1730
+ Update: {
1731
+ ai_citations?: Json | null;
1732
+ avg_position?: number | null;
1733
+ clicks?: number | null;
1734
+ created_at?: string;
1735
+ cta_clicks?: number | null;
1736
+ ctr?: number | null;
1737
+ data_point_count?: number | null;
1738
+ faq_count?: number | null;
1739
+ form_submissions?: number | null;
1740
+ id?: string;
1741
+ impressions?: number | null;
1742
+ organization_id?: string;
1743
+ period?: string;
1744
+ quality_score?: number | null;
1745
+ readability?: number | null;
1746
+ scroll_100?: number | null;
1747
+ scroll_25?: number | null;
1748
+ scroll_50?: number | null;
1749
+ scroll_75?: number | null;
1750
+ seo_page_id?: string;
1751
+ word_count?: number | null;
1752
+ };
1753
+ Relationships: [
1754
+ {
1755
+ foreignKeyName: "acq_seo_metrics_organization_id_fkey";
1756
+ columns: ["organization_id"];
1757
+ isOneToOne: false;
1758
+ referencedRelation: "organizations";
1759
+ referencedColumns: ["id"];
1760
+ },
1761
+ {
1762
+ foreignKeyName: "acq_seo_metrics_seo_page_id_fkey";
1763
+ columns: ["seo_page_id"];
1764
+ isOneToOne: false;
1765
+ referencedRelation: "acq_seo_pages";
1766
+ referencedColumns: ["id"];
1767
+ }
1768
+ ];
1769
+ };
1770
+ acq_seo_pages: {
1771
+ Row: {
1772
+ city: string | null;
1773
+ content: Json | null;
1774
+ created_at: string;
1775
+ faq_items: Json | null;
1776
+ hero_image_url: string | null;
1777
+ id: string;
1778
+ internal_links: Json | null;
1779
+ local_data: Json | null;
1780
+ meta_description: string | null;
1781
+ organization_id: string;
1782
+ page_type: string;
1783
+ published_at: string | null;
1784
+ refreshed_at: string | null;
1785
+ schema_markup: Json | null;
1786
+ slug: string;
1787
+ state: string | null;
1788
+ status: string;
1789
+ title: string;
1790
+ updated_at: string;
1791
+ use_case: string | null;
1792
+ vertical: string;
1793
+ };
1794
+ Insert: {
1795
+ city?: string | null;
1796
+ content?: Json | null;
1797
+ created_at?: string;
1798
+ faq_items?: Json | null;
1799
+ hero_image_url?: string | null;
1800
+ id?: string;
1801
+ internal_links?: Json | null;
1802
+ local_data?: Json | null;
1803
+ meta_description?: string | null;
1804
+ organization_id: string;
1805
+ page_type: string;
1806
+ published_at?: string | null;
1807
+ refreshed_at?: string | null;
1808
+ schema_markup?: Json | null;
1809
+ slug: string;
1810
+ state?: string | null;
1811
+ status?: string;
1812
+ title: string;
1813
+ updated_at?: string;
1814
+ use_case?: string | null;
1815
+ vertical: string;
1816
+ };
1817
+ Update: {
1818
+ city?: string | null;
1819
+ content?: Json | null;
1820
+ created_at?: string;
1821
+ faq_items?: Json | null;
1822
+ hero_image_url?: string | null;
1823
+ id?: string;
1824
+ internal_links?: Json | null;
1825
+ local_data?: Json | null;
1826
+ meta_description?: string | null;
1827
+ organization_id?: string;
1828
+ page_type?: string;
1829
+ published_at?: string | null;
1830
+ refreshed_at?: string | null;
1831
+ schema_markup?: Json | null;
1832
+ slug?: string;
1833
+ state?: string | null;
1834
+ status?: string;
1835
+ title?: string;
1836
+ updated_at?: string;
1837
+ use_case?: string | null;
1838
+ vertical?: string;
1839
+ };
1840
+ Relationships: [
1841
+ {
1842
+ foreignKeyName: "acq_seo_pages_organization_id_fkey";
1843
+ columns: ["organization_id"];
1844
+ isOneToOne: false;
1845
+ referencedRelation: "organizations";
1846
+ referencedColumns: ["id"];
1847
+ }
1848
+ ];
1849
+ };
1570
1850
  activities: {
1571
1851
  Row: {
1572
1852
  activity_type: string;
@@ -2407,170 +2687,6 @@ type Database = {
2407
2687
  };
2408
2688
  Relationships: [];
2409
2689
  };
2410
- seo_metrics: {
2411
- Row: {
2412
- ai_citations: Json | null;
2413
- avg_position: number | null;
2414
- clicks: number | null;
2415
- created_at: string;
2416
- cta_clicks: number | null;
2417
- ctr: number | null;
2418
- data_point_count: number | null;
2419
- faq_count: number | null;
2420
- form_submissions: number | null;
2421
- id: string;
2422
- impressions: number | null;
2423
- organization_id: string;
2424
- period: string;
2425
- quality_score: number | null;
2426
- readability: number | null;
2427
- scroll_100: number | null;
2428
- scroll_25: number | null;
2429
- scroll_50: number | null;
2430
- scroll_75: number | null;
2431
- seo_page_id: string;
2432
- word_count: number | null;
2433
- };
2434
- Insert: {
2435
- ai_citations?: Json | null;
2436
- avg_position?: number | null;
2437
- clicks?: number | null;
2438
- created_at?: string;
2439
- cta_clicks?: number | null;
2440
- ctr?: number | null;
2441
- data_point_count?: number | null;
2442
- faq_count?: number | null;
2443
- form_submissions?: number | null;
2444
- id?: string;
2445
- impressions?: number | null;
2446
- organization_id: string;
2447
- period: string;
2448
- quality_score?: number | null;
2449
- readability?: number | null;
2450
- scroll_100?: number | null;
2451
- scroll_25?: number | null;
2452
- scroll_50?: number | null;
2453
- scroll_75?: number | null;
2454
- seo_page_id: string;
2455
- word_count?: number | null;
2456
- };
2457
- Update: {
2458
- ai_citations?: Json | null;
2459
- avg_position?: number | null;
2460
- clicks?: number | null;
2461
- created_at?: string;
2462
- cta_clicks?: number | null;
2463
- ctr?: number | null;
2464
- data_point_count?: number | null;
2465
- faq_count?: number | null;
2466
- form_submissions?: number | null;
2467
- id?: string;
2468
- impressions?: number | null;
2469
- organization_id?: string;
2470
- period?: string;
2471
- quality_score?: number | null;
2472
- readability?: number | null;
2473
- scroll_100?: number | null;
2474
- scroll_25?: number | null;
2475
- scroll_50?: number | null;
2476
- scroll_75?: number | null;
2477
- seo_page_id?: string;
2478
- word_count?: number | null;
2479
- };
2480
- Relationships: [
2481
- {
2482
- foreignKeyName: "seo_metrics_organization_id_fkey";
2483
- columns: ["organization_id"];
2484
- isOneToOne: false;
2485
- referencedRelation: "organizations";
2486
- referencedColumns: ["id"];
2487
- },
2488
- {
2489
- foreignKeyName: "seo_metrics_seo_page_id_fkey";
2490
- columns: ["seo_page_id"];
2491
- isOneToOne: false;
2492
- referencedRelation: "seo_pages";
2493
- referencedColumns: ["id"];
2494
- }
2495
- ];
2496
- };
2497
- seo_pages: {
2498
- Row: {
2499
- city: string | null;
2500
- content: Json | null;
2501
- created_at: string;
2502
- faq_items: Json | null;
2503
- id: string;
2504
- internal_links: Json | null;
2505
- local_data: Json | null;
2506
- meta_description: string | null;
2507
- organization_id: string;
2508
- page_type: string;
2509
- published_at: string | null;
2510
- refreshed_at: string | null;
2511
- schema_markup: Json | null;
2512
- slug: string;
2513
- state: string | null;
2514
- status: string;
2515
- title: string;
2516
- updated_at: string;
2517
- use_case: string | null;
2518
- vertical: string;
2519
- };
2520
- Insert: {
2521
- city?: string | null;
2522
- content?: Json | null;
2523
- created_at?: string;
2524
- faq_items?: Json | null;
2525
- id?: string;
2526
- internal_links?: Json | null;
2527
- local_data?: Json | null;
2528
- meta_description?: string | null;
2529
- organization_id: string;
2530
- page_type: string;
2531
- published_at?: string | null;
2532
- refreshed_at?: string | null;
2533
- schema_markup?: Json | null;
2534
- slug: string;
2535
- state?: string | null;
2536
- status?: string;
2537
- title: string;
2538
- updated_at?: string;
2539
- use_case?: string | null;
2540
- vertical: string;
2541
- };
2542
- Update: {
2543
- city?: string | null;
2544
- content?: Json | null;
2545
- created_at?: string;
2546
- faq_items?: Json | null;
2547
- id?: string;
2548
- internal_links?: Json | null;
2549
- local_data?: Json | null;
2550
- meta_description?: string | null;
2551
- organization_id?: string;
2552
- page_type?: string;
2553
- published_at?: string | null;
2554
- refreshed_at?: string | null;
2555
- schema_markup?: Json | null;
2556
- slug?: string;
2557
- state?: string | null;
2558
- status?: string;
2559
- title?: string;
2560
- updated_at?: string;
2561
- use_case?: string | null;
2562
- vertical?: string;
2563
- };
2564
- Relationships: [
2565
- {
2566
- foreignKeyName: "seo_pages_organization_id_fkey";
2567
- columns: ["organization_id"];
2568
- isOneToOne: false;
2569
- referencedRelation: "organizations";
2570
- referencedColumns: ["id"];
2571
- }
2572
- ];
2573
- };
2574
2690
  session_messages: {
2575
2691
  Row: {
2576
2692
  created_at: string | null;
@@ -3850,6 +3966,31 @@ interface AcqDeal {
3850
3966
  createdAt: Date;
3851
3967
  updatedAt: Date;
3852
3968
  }
3969
+ interface DealStageSummary {
3970
+ stage: string;
3971
+ count: number;
3972
+ oldestUpdatedAt: string | null;
3973
+ newestUpdatedAt: string | null;
3974
+ }
3975
+ interface StaleDeal {
3976
+ id: string;
3977
+ contactEmail: string;
3978
+ cachedStage: string;
3979
+ updatedAt: string;
3980
+ daysStale: number;
3981
+ }
3982
+ interface DealPipelineAnalytics {
3983
+ totalDeals: number;
3984
+ stageSummary: DealStageSummary[];
3985
+ staleDeals: StaleDeal[];
3986
+ recentActivity: AcqDeal[];
3987
+ }
3988
+ interface DealFilters {
3989
+ stage?: string;
3990
+ search?: string;
3991
+ limit?: number;
3992
+ offset?: number;
3993
+ }
3853
3994
  interface AddContactsToListParams {
3854
3995
  organizationId: string;
3855
3996
  listId: string;
@@ -6267,6 +6408,16 @@ type LeadToolMap = {
6267
6408
  params: Omit<DeleteDealParams, 'organizationId'>;
6268
6409
  result: void;
6269
6410
  };
6411
+ listDeals: {
6412
+ params: DealFilters;
6413
+ result: AcqDeal[];
6414
+ };
6415
+ getDealPipelineAnalytics: {
6416
+ params: {
6417
+ recentLimit?: number;
6418
+ };
6419
+ result: DealPipelineAnalytics;
6420
+ };
6270
6421
  mergeEnrichmentData: {
6271
6422
  params: {
6272
6423
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/sdk",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
4
4
  "description": "SDK for building Elevasis organization resources",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  # SDK Reference Navigation
2
2
 
3
- Auto-generated from reference file frontmatter. 30 files indexed.
3
+ Auto-generated from reference file frontmatter. 31 files indexed.
4
4
 
5
5
  All paths are relative to `node_modules/@elevasis/sdk/reference/`.
6
6
 
@@ -42,6 +42,7 @@ All paths are relative to `node_modules/@elevasis/sdk/reference/`.
42
42
  | Integration Adapters | `platform-tools/adapters-integration.mdx` | Type-safe wrappers for third-party integrations -- Attio, Stripe, Notion, Google Sheets, Instantly, SignatureAPI, Resend, Dropbox, Apify, Gmail, Mailso, and Tomba -- with full autocomplete and compile-time checking | Using typed adapters for integration tools, or needs to know what integration adapter methods are available |
43
43
  | Platform Adapters | `platform-tools/adapters-platform.mdx` | Type-safe singleton adapters for built-in platform services -- scheduler, storage, LLM, PDF, approval, notifications, acqDb, execution, and email -- no credentials required | Using platform service adapters (scheduler, storage, llm, pdf, approval, acqDb, notifications, execution, email) |
44
44
  | Platform Tools | `platform-tools/index.mdx` | Access 70+ tools across integration adapters and platform services from your SDK workflows -- typed adapters, credential security model, and working code examples | Connecting to external services |
45
+ | Adapter Type Safety | `platform-tools/type-safety.mdx` | SDK worker adapter type safety patterns - required fields, discriminated unions, and intentionally loose types | (not specified) |
45
46
 
46
47
  ## Resources
47
48
 
package/reference/cli.mdx CHANGED
@@ -547,6 +547,73 @@ elevasis-sdk env remove OPENAI_API_KEY
547
547
 
548
548
  ---
549
549
 
550
+ ## elevasis-sdk rename
551
+
552
+ Rename a resource ID across all reference tables in the platform database.
553
+
554
+ **Synopsis:**
555
+
556
+ ```
557
+ elevasis-sdk rename <old-id> --to <new-id> [--execute] [--prod]
558
+ ```
559
+
560
+ **Behavior:**
561
+
562
+ - Dry-run by default -- shows all affected rows per table without modifying any data
563
+ - Pass `--execute` to perform the rename
564
+ - Org-scoped: only updates rows belonging to your organization
565
+ - Updates resource references across 6 tables:
566
+
567
+ | Table | Column(s) updated |
568
+ | -------------------- | ----------------- |
569
+ | `executions` | `resource_id` |
570
+ | `sessions` | `resource_id` |
571
+ | `workflow_configs` | `resource_id` |
572
+ | `workflow_schedules` | `resource_id` |
573
+ | `execution_events` | `resource_id` |
574
+ | `session_events` | `resource_id` |
575
+
576
+ **Flags:**
577
+
578
+ | Flag | Description |
579
+ | ------------------- | --------------------------------------- |
580
+ | `--to <new-id>` | Required. The new resource ID |
581
+ | `--execute` | Perform the rename (default is dry-run) |
582
+ | `--prod` | Target the production environment |
583
+ | `--api-url <url>` | Override the API base URL |
584
+
585
+ **Example (dry-run):**
586
+
587
+ ```bash
588
+ elevasis-sdk rename ist-upload-workflow --to ist-upload-contacts-workflow
589
+ ```
590
+
591
+ ```
592
+ Dry run — no changes made.
593
+
594
+ Rows that would be updated:
595
+ executions 6
596
+ sessions 0
597
+ workflow_configs 0
598
+ workflow_schedules 0
599
+ execution_events 0
600
+ session_events 0
601
+
602
+ Total: 6 rows
603
+
604
+ Re-run with --execute to apply changes.
605
+ ```
606
+
607
+ **Example (execute):**
608
+
609
+ ```bash
610
+ elevasis-sdk rename ist-upload-workflow --to ist-upload-contacts-workflow --execute
611
+ ```
612
+
613
+ **Implementation:** `packages/sdk/src/cli/commands/rename.ts` -- delegates to `POST /api/external/resources/rename`
614
+
615
+ ---
616
+
550
617
  ## Global Flags
551
618
 
552
619
  These flags are accepted by all commands:
@@ -182,6 +182,8 @@ const { category, confidence, summary } = response.output
182
182
 
183
183
  **Supported models:** See the full model table in [Platform Tools](index.mdx#llm-tool).
184
184
 
185
+ See [Adapter Type Safety](type-safety.mdx) for required field enforcement and design rationale.
186
+
185
187
  ---
186
188
 
187
189
  ## PDF Adapter
@@ -0,0 +1,92 @@
1
+ ---
2
+ title: Adapter Type Safety
3
+ description: SDK worker adapter type safety patterns - required fields, discriminated unions, and intentionally loose types
4
+ ---
5
+
6
+ SDK worker adapters enforce correctness at compile time via TypeScript, not at deploy time. Misconfigured adapters fail in the IDE before a file is even saved — no runtime surprises, no silent failures in production.
7
+
8
+ The approach: tighten types where misconfiguration is a realistic foot-gun, and leave types intentionally loose where flexibility is a design requirement.
9
+
10
+ ---
11
+
12
+ ## Required Field Enforcement
13
+
14
+ ### LLM Adapter — `provider` and `model`
15
+
16
+ `provider` and `model` are required on `SDKLLMGenerateParams` in `packages/sdk/src/worker/adapters/llm.ts`. They were previously optional because the server-side `modelConfig` fallback in `tool-dispatcher.ts` would fill them in — but that fallback is a foot-gun, not a feature. Omitting them silently selects a default model that may not be appropriate for the call site.
17
+
18
+ ```typescript
19
+ // Required — both fields must be specified inline
20
+ await llm.generate({
21
+ provider: 'anthropic',
22
+ model: 'claude-sonnet-4-5',
23
+ messages: [...],
24
+ responseSchema: {...},
25
+ })
26
+ ```
27
+
28
+ ### Email Adapter — `domain` (AnyMailFinder)
29
+
30
+ `domain` is required on `FindCompanyEmailParams` and `FindPersonEmailParams`. Previously all params were optional, allowing `findCompanyEmail({})` to compile but fail at runtime. The type change enforces the one field that is always necessary for email discovery.
31
+
32
+ ---
33
+
34
+ ## Discriminated Unions
35
+
36
+ ### Email Targeting — mutually exclusive modes
37
+
38
+ `EmailToolMap.send.params` uses a discriminated union with `never` to enforce that exactly one targeting mode is provided. You cannot pass zero modes or combine multiple modes.
39
+
40
+ ```typescript
41
+ type EmailTargeting =
42
+ | { userIds: string[]; targetRole?: never; targetAll?: never }
43
+ | { targetRole: string; userIds?: never; targetAll?: never }
44
+ | { targetAll: true; userIds?: never; targetRole?: never }
45
+ ```
46
+
47
+ The `never` pattern on sibling fields causes TypeScript to error if you pass two targeting fields simultaneously. Passing none also fails because none of the union members match.
48
+
49
+ ---
50
+
51
+ ## Strict Object Types
52
+
53
+ ### Approval Adapter — typed context
54
+
55
+ `ApprovalToolMap.create.params` uses `context: Record<string, unknown>` instead of `context: unknown`. This prevents passing primitives (strings, numbers) as context — approval tasks always expect a structured key-value object.
56
+
57
+ ```typescript
58
+ // Correct
59
+ await approval.create({
60
+ context: { dealId: 'deal-123', proposalUrl: 'https://...' },
61
+ ...
62
+ })
63
+
64
+ // TypeScript error — primitives not assignable to Record<string, unknown>
65
+ await approval.create({ context: 'deal-123', ... })
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Intentionally Loose Types
71
+
72
+ Some adapters were audited and deliberately left with flexible types. Do not tighten these — the looseness is a design requirement.
73
+
74
+ | Adapter | Field | Type | Reason |
75
+ | ------- | ---------- | --------------------------- | -------------------------------------------------------------------------------------------------------------- |
76
+ | Attio | `object` | `string` | Supports custom user-defined object slugs; a union would be too restrictive for orgs with custom Attio objects |
77
+ | Attio | `values` | `Record<string, unknown>` | Dynamic per-object schemas vary by org configuration |
78
+ | PDF | `document` | `Record<string, unknown>` | Renderer accepts flexible document structures by design; schema is enforced server-side |
79
+
80
+ ---
81
+
82
+ ## Known Exceptions
83
+
84
+ ### `website-extract-calibration.ts`
85
+
86
+ `external/elevasis/src/client-acquisition/lead-gen-pipeline/02-extract/website-extract-calibration.ts` intentionally omits `provider` and `model` on its `llm.generate()` call. This is a calibration variant that injects model config via `definitionOverrides.modelConfig` at deploy time.
87
+
88
+ This file requires `@ts-expect-error` above the `llm.generate()` call after each SDK publish, since the type change would otherwise cause a compile error on a legitimate use case.
89
+
90
+ ---
91
+
92
+ **Source:** `packages/sdk/src/worker/adapters/llm.ts`, `packages/core/src/execution/engine/tools/tool-maps.ts`