@henrylabs/mcp 0.26.0 → 1.1.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.
Files changed (94) hide show
  1. package/README.md +1 -3
  2. package/code-tool-paths.cjs +4 -2
  3. package/code-tool-paths.cjs.map +1 -1
  4. package/code-tool-paths.d.cts +1 -1
  5. package/code-tool-paths.d.cts.map +1 -1
  6. package/code-tool-worker.d.mts.map +1 -1
  7. package/code-tool-worker.d.ts.map +1 -1
  8. package/code-tool-worker.js +14 -25
  9. package/code-tool-worker.js.map +1 -1
  10. package/code-tool-worker.mjs +14 -25
  11. package/code-tool-worker.mjs.map +1 -1
  12. package/code-tool.d.mts.map +1 -1
  13. package/code-tool.d.ts.map +1 -1
  14. package/code-tool.js +32 -28
  15. package/code-tool.js.map +1 -1
  16. package/code-tool.mjs +23 -16
  17. package/code-tool.mjs.map +1 -1
  18. package/docs-search-tool.d.mts +2 -0
  19. package/docs-search-tool.d.mts.map +1 -1
  20. package/docs-search-tool.d.ts +2 -0
  21. package/docs-search-tool.d.ts.map +1 -1
  22. package/docs-search-tool.js +36 -5
  23. package/docs-search-tool.js.map +1 -1
  24. package/docs-search-tool.mjs +35 -5
  25. package/docs-search-tool.mjs.map +1 -1
  26. package/http.d.mts.map +1 -1
  27. package/http.d.ts.map +1 -1
  28. package/http.js +43 -3
  29. package/http.js.map +1 -1
  30. package/http.mjs +43 -3
  31. package/http.mjs.map +1 -1
  32. package/instructions.d.mts +4 -1
  33. package/instructions.d.mts.map +1 -1
  34. package/instructions.d.ts +4 -1
  35. package/instructions.d.ts.map +1 -1
  36. package/instructions.js +30 -25
  37. package/instructions.js.map +1 -1
  38. package/instructions.mjs +27 -25
  39. package/instructions.mjs.map +1 -1
  40. package/local-docs-search.d.mts +28 -0
  41. package/local-docs-search.d.mts.map +1 -0
  42. package/local-docs-search.d.ts +28 -0
  43. package/local-docs-search.d.ts.map +1 -0
  44. package/local-docs-search.js +493 -0
  45. package/local-docs-search.js.map +1 -0
  46. package/local-docs-search.mjs +453 -0
  47. package/local-docs-search.mjs.map +1 -0
  48. package/methods.d.mts.map +1 -1
  49. package/methods.d.ts.map +1 -1
  50. package/methods.js +51 -117
  51. package/methods.js.map +1 -1
  52. package/methods.mjs +51 -117
  53. package/methods.mjs.map +1 -1
  54. package/options.d.mts +3 -0
  55. package/options.d.mts.map +1 -1
  56. package/options.d.ts +3 -0
  57. package/options.d.ts.map +1 -1
  58. package/options.js +19 -0
  59. package/options.js.map +1 -1
  60. package/options.mjs +19 -0
  61. package/options.mjs.map +1 -1
  62. package/package.json +20 -6
  63. package/server.d.mts +5 -1
  64. package/server.d.mts.map +1 -1
  65. package/server.d.ts +5 -1
  66. package/server.d.ts.map +1 -1
  67. package/server.js +11 -5
  68. package/server.js.map +1 -1
  69. package/server.mjs +11 -5
  70. package/server.mjs.map +1 -1
  71. package/src/code-tool-paths.cts +3 -1
  72. package/src/code-tool-worker.ts +14 -25
  73. package/src/code-tool.ts +30 -22
  74. package/src/docs-search-tool.ts +58 -11
  75. package/src/http.ts +46 -3
  76. package/src/instructions.ts +34 -26
  77. package/src/local-docs-search.ts +544 -0
  78. package/src/methods.ts +51 -117
  79. package/src/options.ts +24 -0
  80. package/src/server.ts +19 -5
  81. package/src/stdio.ts +4 -1
  82. package/src/types.ts +1 -0
  83. package/stdio.d.mts.map +1 -1
  84. package/stdio.d.ts.map +1 -1
  85. package/stdio.js +4 -1
  86. package/stdio.js.map +1 -1
  87. package/stdio.mjs +4 -1
  88. package/stdio.mjs.map +1 -1
  89. package/types.d.mts +1 -0
  90. package/types.d.mts.map +1 -1
  91. package/types.d.ts +1 -0
  92. package/types.d.ts.map +1 -1
  93. package/types.js.map +1 -1
  94. package/types.mjs.map +1 -1
@@ -0,0 +1,544 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import MiniSearch from 'minisearch';
4
+ import * as fs from 'node:fs/promises';
5
+ import * as path from 'node:path';
6
+ import { getLogger } from './logger';
7
+
8
+ type MethodEntry = {
9
+ name: string;
10
+ endpoint: string;
11
+ httpMethod: string;
12
+ summary: string;
13
+ description: string;
14
+ stainlessPath: string;
15
+ qualified: string;
16
+ params?: string[];
17
+ response?: string;
18
+ markdown?: string;
19
+ };
20
+
21
+ type ProseChunk = {
22
+ content: string;
23
+ tag: string;
24
+ sectionContext?: string;
25
+ source?: string;
26
+ };
27
+
28
+ type MiniSearchDocument = {
29
+ id: string;
30
+ kind: 'http_method' | 'prose';
31
+ name?: string;
32
+ endpoint?: string;
33
+ summary?: string;
34
+ description?: string;
35
+ qualified?: string;
36
+ stainlessPath?: string;
37
+ content?: string;
38
+ sectionContext?: string;
39
+ _original: Record<string, unknown>;
40
+ };
41
+
42
+ type SearchResult = {
43
+ results: (string | Record<string, unknown>)[];
44
+ };
45
+
46
+ const EMBEDDED_METHODS: MethodEntry[] = [
47
+ {
48
+ name: 'details',
49
+ endpoint: '/product/details',
50
+ httpMethod: 'post',
51
+ summary: 'Product Details',
52
+ description: 'Fetch detailed information about a product from a given URL.',
53
+ stainlessPath: '(resource) products > (method) details',
54
+ qualified: 'client.products.details',
55
+ params: ['link: string;', 'country?: string;', 'variant?: string | object;'],
56
+ response:
57
+ "{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; metadata?: object; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }; }",
58
+ markdown:
59
+ "## details\n\n`client.products.details(link: string, country?: string, variant?: string | object): { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }`\n\n**post** `/product/details`\n\nFetch detailed information about a product from a given URL.\n\n### Parameters\n\n- `link: string`\n Direct product URL\n\n- `country?: string`\n\n- `variant?: string | object`\n Variant selection. Can be a simple string or a key-value object\n\n### Returns\n\n- `{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; metadata?: object; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }; }`\n\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'failed'`\n - `error?: object`\n - `result?: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; metadata?: object; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.products.details({ link: 'https://www.nike.com/u/custom-nike-ja-3-by-you-10002205' });\n\nconsole.log(response);\n```",
60
+ },
61
+ {
62
+ name: 'poll_details',
63
+ endpoint: '/product/details/status',
64
+ httpMethod: 'get',
65
+ summary: 'Product Details Status',
66
+ description: 'Check the status of a product details retrieval job and get results when ready.',
67
+ stainlessPath: '(resource) products > (method) poll_details',
68
+ qualified: 'client.products.pollDetails',
69
+ params: ['refId: string;'],
70
+ response:
71
+ "{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; metadata?: object; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }; }",
72
+ markdown:
73
+ "## poll_details\n\n`client.products.pollDetails(refId: string): { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }`\n\n**get** `/product/details/status`\n\nCheck the status of a product details retrieval job and get results when ready.\n\n### Parameters\n\n- `refId: string`\n Reference ID used for checking status\n\n### Returns\n\n- `{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; metadata?: object; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }; }`\n\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'failed'`\n - `error?: object`\n - `result?: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; metadata?: object; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.products.pollDetails({ refId: 'prd-ref_3fa85f64-5717-4562-b3fc' });\n\nconsole.log(response);\n```",
74
+ },
75
+ {
76
+ name: 'poll_search',
77
+ endpoint: '/product/search/status',
78
+ httpMethod: 'get',
79
+ summary: 'Product Search Status',
80
+ description: 'Check the status of a product search retrieval job and get results when ready.',
81
+ stainlessPath: '(resource) products > (method) poll_search',
82
+ qualified: 'client.products.pollSearch',
83
+ params: ['refId: string;'],
84
+ response:
85
+ "{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { pagination: { nextCursor: string; previousCursor: string; }; products: { host: string; link: string; merchant: string; name: string; price: object; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: object[]; originalPrice?: object; variants?: object[]; }[]; }; }",
86
+ markdown:
87
+ "## poll_search\n\n`client.products.pollSearch(refId: string): { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }`\n\n**get** `/product/search/status`\n\nCheck the status of a product search retrieval job and get results when ready.\n\n### Parameters\n\n- `refId: string`\n Reference ID used for checking status\n\n### Returns\n\n- `{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { pagination: { nextCursor: string; previousCursor: string; }; products: { host: string; link: string; merchant: string; name: string; price: object; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: object[]; originalPrice?: object; variants?: object[]; }[]; }; }`\n\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'failed'`\n - `error?: object`\n - `result?: { pagination: { nextCursor: string; previousCursor: string; }; products: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.products.pollSearch({ refId: 'prs-ref_3fa85f64-5717-4562-b3fc' });\n\nconsole.log(response);\n```",
88
+ },
89
+ {
90
+ name: 'search',
91
+ endpoint: '/product/search',
92
+ httpMethod: 'post',
93
+ summary: 'Text Product Search',
94
+ description: 'Search for products using keyword and passing various filters and criteria',
95
+ stainlessPath: '(resource) products > (method) search',
96
+ qualified: 'client.products.search',
97
+ params: [
98
+ 'query: string;',
99
+ 'country?: string;',
100
+ 'cursor?: number;',
101
+ 'limit?: number;',
102
+ 'maxPrice?: number;',
103
+ 'merchant?: string;',
104
+ 'minPrice?: number;',
105
+ "sortBy?: 'lowToHigh' | 'highToLow';",
106
+ ],
107
+ response:
108
+ "{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { pagination: { nextCursor: string; previousCursor: string; }; products: { host: string; link: string; merchant: string; name: string; price: object; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: object[]; originalPrice?: object; variants?: object[]; }[]; }; }",
109
+ markdown:
110
+ "## search\n\n`client.products.search(query: string, country?: string, cursor?: number, limit?: number, maxPrice?: number, merchant?: string, minPrice?: number, sortBy?: 'lowToHigh' | 'highToLow'): { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }`\n\n**post** `/product/search`\n\nSearch for products using keyword and passing various filters and criteria\n\n### Parameters\n\n- `query: string`\n Search query\n\n- `country?: string`\n\n- `cursor?: number`\n Cursor returned from the previous response\n\n- `limit?: number`\n Limit the number of results\n\n- `maxPrice?: number`\n Maximum price filter\n\n- `merchant?: string`\n Merchant to filter results\n\n- `minPrice?: number`\n Minimum price filter\n\n- `sortBy?: 'lowToHigh' | 'highToLow'`\n Sort by price: 'lowToHigh' or 'highToLow'\n\n### Returns\n\n- `{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { pagination: { nextCursor: string; previousCursor: string; }; products: { host: string; link: string; merchant: string; name: string; price: object; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: object[]; originalPrice?: object; variants?: object[]; }[]; }; }`\n\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'failed'`\n - `error?: object`\n - `result?: { pagination: { nextCursor: string; previousCursor: string; }; products: { host: string; link: string; merchant: string; name: string; price: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; description?: string; images?: { url: string; isFeatured?: boolean; }[]; originalPrice?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; variants?: { name: string; sku: string; availability?: 'in_stock' | 'limited_stock' | 'out_of_stock' | 'preorder' | 'backorder'; }[]; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.products.search({ query: 'Air Max Shoes' });\n\nconsole.log(response);\n```",
111
+ },
112
+ {
113
+ name: 'create',
114
+ endpoint: '/cart',
115
+ httpMethod: 'post',
116
+ summary: 'Cart Create',
117
+ description: 'Create a cart with one or more items and get a checkout URL',
118
+ stainlessPath: '(resource) cart > (method) create',
119
+ qualified: 'client.cart.create',
120
+ params: [
121
+ 'items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[];',
122
+ "settings?: { commissionFeeFixed?: { value: number; currency?: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; }; commissionFeePercent?: number; events?: { data: { points: number; type: 'give_points_fixed'; } | { perAmount: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; points: number; type: 'give_points_per_spent'; } | { points: number; type: 'remove_points_fixed'; } | { perAmount: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; points: number; type: 'remove_points_per_spent'; } | { tierUUID: string; type: 'give_tier'; } | { type: 'remove_tier'; } | { type: 'send_webhook'; webhookUUID: string; } | { type: 'send_email'; }[]; type: string; conditional?: { operator: 'equals' | 'not_equals'; type: 'tier'; value: string; } | { operator: string; type: 'points'; value: number; }; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; };",
123
+ 'tags?: object;',
124
+ ],
125
+ response:
126
+ '{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }',
127
+ markdown:
128
+ "## create\n\n`client.cart.create(items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[], settings?: { commissionFeeFixed?: { value: number; currency?: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }, tags?: object): { data: object; message: string; status: string; success: boolean; }`\n\n**post** `/cart`\n\nCreate a cart with one or more items and get a checkout URL\n\n### Parameters\n\n- `items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]`\n Items to include in the cart\n\n- `settings?: { commissionFeeFixed?: { value: number; currency?: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; }; commissionFeePercent?: number; events?: { data: { points: number; type: 'give_points_fixed'; } | { perAmount: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; points: number; type: 'give_points_per_spent'; } | { points: number; type: 'remove_points_fixed'; } | { perAmount: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; points: number; type: 'remove_points_per_spent'; } | { tierUUID: string; type: 'give_tier'; } | { type: 'remove_tier'; } | { type: 'send_webhook'; webhookUUID: string; } | { type: 'send_email'; }[]; type: string; conditional?: { operator: 'equals' | 'not_equals'; type: 'tier'; value: string; } | { operator: string; type: 'points'; value: number; }; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }`\n - `commissionFeeFixed?: { value: number; currency?: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; }`\n - `commissionFeePercent?: number`\n Commission percentage (0–100)\n - `events?: { data: { points: number; type: 'give_points_fixed'; } | { perAmount: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; points: number; type: 'give_points_per_spent'; } | { points: number; type: 'remove_points_fixed'; } | { perAmount: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; points: number; type: 'remove_points_per_spent'; } | { tierUUID: string; type: 'give_tier'; } | { type: 'remove_tier'; } | { type: 'send_webhook'; webhookUUID: string; } | { type: 'send_email'; }[]; type: string; conditional?: { operator: 'equals' | 'not_equals'; type: 'tier'; value: string; } | { operator: string; type: 'points'; value: number; }; }[]`\n List of events to trigger during checkout\n - `options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }`\n\n- `tags?: object`\n Key-value tags to associate with the cart\n\n### Returns\n\n- `{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }`\n\n - `data: { cartId: string; checkoutUrl: string; data: { items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]; settings?: { commissionFeeFixed?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }; tags?: object; }; metadata?: object; }`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst cart = await client.cart.create({ items: [{ link: 'https://www.nike.com/u/custom-nike-ja-3-by-you-10002205' }] });\n\nconsole.log(cart);\n```",
129
+ },
130
+ {
131
+ name: 'list',
132
+ endpoint: '/cart',
133
+ httpMethod: 'get',
134
+ summary: 'Cart Fetch',
135
+ description: 'Fetch a list of carts with optional filtering by cart ID or tags.',
136
+ stainlessPath: '(resource) cart > (method) list',
137
+ qualified: 'client.cart.list',
138
+ params: ['cartId?: string;', 'cursor?: string;', 'limit?: number;', 'tags?: object;'],
139
+ response:
140
+ '{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }[]; message: string; status: string; success: boolean; }',
141
+ markdown:
142
+ "## list\n\n`client.cart.list(cartId?: string, cursor?: string, limit?: number, tags?: object): { data: object[]; message: string; status: string; success: boolean; }`\n\n**get** `/cart`\n\nFetch a list of carts with optional filtering by cart ID or tags.\n\n### Parameters\n\n- `cartId?: string`\n Filter by a specific cart ID\n\n- `cursor?: string`\n Cursor returned from the previous response\n\n- `limit?: number`\n Limit the number of results\n\n- `tags?: object`\n Filter carts by key-value tags\n\n### Returns\n\n- `{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }[]; message: string; status: string; success: boolean; }`\n\n - `data: { cartId: string; checkoutUrl: string; data: { items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]; settings?: { commissionFeeFixed?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }; tags?: object; }; metadata?: object; }[]`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst carts = await client.cart.list();\n\nconsole.log(carts);\n```",
143
+ },
144
+ {
145
+ name: 'delete',
146
+ endpoint: '/cart/{cartId}',
147
+ httpMethod: 'delete',
148
+ summary: 'Cart Delete',
149
+ description: 'Delete a cart by its unique identifier',
150
+ stainlessPath: '(resource) cart > (method) delete',
151
+ qualified: 'client.cart.delete',
152
+ params: ['cartId: string;'],
153
+ response:
154
+ '{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }',
155
+ markdown:
156
+ "## delete\n\n`client.cart.delete(cartId: string): { data: object; message: string; status: string; success: boolean; }`\n\n**delete** `/cart/{cartId}`\n\nDelete a cart by its unique identifier\n\n### Parameters\n\n- `cartId: string`\n Unique identifier for the cart\n\n### Returns\n\n- `{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }`\n\n - `data: { cartId: string; checkoutUrl: string; data: { items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]; settings?: { commissionFeeFixed?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }; tags?: object; }; metadata?: object; }`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst cart = await client.cart.delete('crt_sa2aEsCz9PRM');\n\nconsole.log(cart);\n```",
157
+ },
158
+ {
159
+ name: 'update',
160
+ endpoint: '/cart/{cartId}/item',
161
+ httpMethod: 'put',
162
+ summary: 'Cart Update Item',
163
+ description: 'Update an item in an existing cart.',
164
+ stainlessPath: '(resource) cart.item > (method) update',
165
+ qualified: 'client.cart.item.update',
166
+ params: [
167
+ 'cartId: string;',
168
+ 'item: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; };',
169
+ ],
170
+ response:
171
+ '{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }',
172
+ markdown:
173
+ "## update\n\n`client.cart.item.update(cartId: string, item: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }): { data: object; message: string; status: string; success: boolean; }`\n\n**put** `/cart/{cartId}/item`\n\nUpdate an item in an existing cart.\n\n### Parameters\n\n- `cartId: string`\n Unique identifier for the cart\n\n- `item: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }`\n Item to update\n - `link: string`\n Direct product URL\n - `coupons?: string[]`\n List of coupon codes applied to this cart item\n - `metadata?: object`\n Misc metadata associated with this cart item\n - `quantity?: number`\n Quantity of this item\n - `shippingOption?: { id?: string; value?: string; }`\n Shipping option selected for this cart item\n - `variant?: string | object`\n Variant selection. Can be a simple string or a key-value object\n\n### Returns\n\n- `{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }`\n\n - `data: { cartId: string; checkoutUrl: string; data: { items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]; settings?: { commissionFeeFixed?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }; tags?: object; }; metadata?: object; }`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst item = await client.cart.item.update('crt_sa2aEsCz9PRM', { item: { link: 'https://www.nike.com/u/custom-nike-ja-3-by-you-10002205' } });\n\nconsole.log(item);\n```",
174
+ },
175
+ {
176
+ name: 'add',
177
+ endpoint: '/cart/{cartId}/item',
178
+ httpMethod: 'post',
179
+ summary: 'Cart Add Item',
180
+ description: 'Add an item to an existing cart.',
181
+ stainlessPath: '(resource) cart.item > (method) add',
182
+ qualified: 'client.cart.item.add',
183
+ params: [
184
+ 'cartId: string;',
185
+ 'item: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; };',
186
+ ],
187
+ response:
188
+ '{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }',
189
+ markdown:
190
+ "## add\n\n`client.cart.item.add(cartId: string, item: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }): { data: object; message: string; status: string; success: boolean; }`\n\n**post** `/cart/{cartId}/item`\n\nAdd an item to an existing cart.\n\n### Parameters\n\n- `cartId: string`\n Unique identifier for the cart\n\n- `item: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }`\n Item to add to the cart\n - `link: string`\n Direct product URL\n - `coupons?: string[]`\n List of coupon codes applied to this cart item\n - `metadata?: object`\n Misc metadata associated with this cart item\n - `quantity?: number`\n Quantity of this item\n - `shippingOption?: { id?: string; value?: string; }`\n Shipping option selected for this cart item\n - `variant?: string | object`\n Variant selection. Can be a simple string or a key-value object\n\n### Returns\n\n- `{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }`\n\n - `data: { cartId: string; checkoutUrl: string; data: { items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]; settings?: { commissionFeeFixed?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }; tags?: object; }; metadata?: object; }`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.cart.item.add('crt_sa2aEsCz9PRM', { item: { link: 'https://www.nike.com/u/custom-nike-ja-3-by-you-10002205' } });\n\nconsole.log(response);\n```",
191
+ },
192
+ {
193
+ name: 'remove',
194
+ endpoint: '/cart/{cartId}/item',
195
+ httpMethod: 'delete',
196
+ summary: 'Cart Remove item',
197
+ description: 'Remove an item from a cart by its unique identifier',
198
+ stainlessPath: '(resource) cart.item > (method) remove',
199
+ qualified: 'client.cart.item.remove',
200
+ params: ['cartId: string;', 'link: string;'],
201
+ response:
202
+ '{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }',
203
+ markdown:
204
+ "## remove\n\n`client.cart.item.remove(cartId: string, link: string): { data: object; message: string; status: string; success: boolean; }`\n\n**delete** `/cart/{cartId}/item`\n\nRemove an item from a cart by its unique identifier\n\n### Parameters\n\n- `cartId: string`\n Unique identifier for the cart\n\n- `link: string`\n Direct product URL\n\n### Returns\n\n- `{ data: { cartId: string; checkoutUrl: string; data: { items: object[]; settings?: object; tags?: object; }; metadata?: object; }; message: string; status: string; success: boolean; }`\n\n - `data: { cartId: string; checkoutUrl: string; data: { items: { link: string; coupons?: string[]; metadata?: object; quantity?: number; shippingOption?: { id?: string; value?: string; }; variant?: string | object; }[]; settings?: { commissionFeeFixed?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; commissionFeePercent?: number; events?: { data: object | object | object | object | object | object | object | object[]; type: string; conditional?: object | object; }[]; options?: { allowPartialPurchase?: boolean; collectBuyerAddress?: 'off' | 'required' | 'optional'; collectBuyerEmail?: 'off' | 'required' | 'optional'; collectBuyerPhone?: 'off' | 'required' | 'optional'; }; }; tags?: object; }; metadata?: object; }`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst item = await client.cart.item.remove('crt_sa2aEsCz9PRM', { link: 'https://www.nike.com/u/custom-nike-ja-3-by-you-10002205' });\n\nconsole.log(item);\n```",
205
+ },
206
+ {
207
+ name: 'details',
208
+ endpoint: '/cart/{cartId}/details',
209
+ httpMethod: 'post',
210
+ summary: 'Cart Details',
211
+ description: 'Retrieve detailed information about a cart.',
212
+ stainlessPath: '(resource) cart.checkout > (method) details',
213
+ qualified: 'client.cart.checkout.details',
214
+ params: [
215
+ 'cartId: string;',
216
+ 'buyer: { shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; };',
217
+ 'coupons?: string[];',
218
+ 'metadata?: { botAuth?: { forterToken?: string; }; userData?: { ipAddress?: string; userAgent?: string; }; };',
219
+ ],
220
+ response:
221
+ "{ data: { jobs: { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }[]; metadata?: object; }; message: string; status: string; success: boolean; }",
222
+ markdown:
223
+ "## details\n\n`client.cart.checkout.details(cartId: string, buyer: { shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }, coupons?: string[], metadata?: { botAuth?: { forterToken?: string; }; userData?: { ipAddress?: string; userAgent?: string; }; }): { data: object; message: string; status: string; success: boolean; }`\n\n**post** `/cart/{cartId}/details`\n\nRetrieve detailed information about a cart.\n\n### Parameters\n\n- `cartId: string`\n Unique identifier for the cart\n\n- `buyer: { shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }`\n - `shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }`\n\n- `coupons?: string[]`\n List of coupon codes applied to the cart\n\n- `metadata?: { botAuth?: { forterToken?: string; }; userData?: { ipAddress?: string; userAgent?: string; }; }`\n Additional metadata for the request\n - `botAuth?: { forterToken?: string; }`\n Bot authentication credentials\n - `userData?: { ipAddress?: string; userAgent?: string; }`\n User identity and device information\n\n### Returns\n\n- `{ data: { jobs: { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }[]; metadata?: object; }; message: string; status: string; success: boolean; }`\n\n - `data: { jobs: { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { items: { costs: object; shippingOptions: object[]; coupons?: object[]; metadata?: object; }[]; }; }[]; metadata?: object; }`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.cart.checkout.details('crt_sa2aEsCz9PRM', { buyer: { shippingAddress: {\n city: 'Anytown',\n countryCode: 'US',\n line1: '123 Main St',\n postalCode: '12345',\n province: 'CA',\n} } });\n\nconsole.log(response);\n```",
224
+ },
225
+ {
226
+ name: 'poll_details',
227
+ endpoint: '/cart/checkout/status',
228
+ httpMethod: 'get',
229
+ summary: 'Cart Details Status',
230
+ description: 'Check the status of a cart details retrieval job and get results when ready.',
231
+ stainlessPath: '(resource) cart.checkout > (method) poll_details',
232
+ qualified: 'client.cart.checkout.pollDetails',
233
+ params: ['refId: string;'],
234
+ response:
235
+ "{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { items: { costs: object; shippingOptions: object[]; coupons?: object[]; metadata?: object; }[]; }; }",
236
+ markdown:
237
+ "## poll_details\n\n`client.cart.checkout.pollDetails(refId: string): { refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: object; }`\n\n**get** `/cart/checkout/status`\n\nCheck the status of a cart details retrieval job and get results when ready.\n\n### Parameters\n\n- `refId: string`\n Reference ID used for checking status\n\n### Returns\n\n- `{ refId: string; status: 'pending' | 'processing' | 'complete' | 'failed'; error?: object; result?: { items: { costs: object; shippingOptions: object[]; coupons?: object[]; metadata?: object; }[]; }; }`\n\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'failed'`\n - `error?: object`\n - `result?: { items: { costs: { subtotal: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; total: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; discount?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; shipping?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; tax?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; shippingOptions: { id: string; cost: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; name: string; maxDate?: string; minDate?: string; timeEstimate?: string; }[]; coupons?: { available: boolean; code: string; savedAmount?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }[]; metadata?: object; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.cart.checkout.pollDetails({ refId: 'ckd-ref_3fa85f64-5717-4562-b3fc' });\n\nconsole.log(response);\n```",
238
+ },
239
+ {
240
+ name: 'poll_purchase',
241
+ endpoint: '/cart/purchase/status',
242
+ httpMethod: 'get',
243
+ summary: 'Cart Purchase Status',
244
+ description: 'Check the status of a cart purchase job and get results when ready.',
245
+ stainlessPath: '(resource) cart.checkout > (method) poll_purchase',
246
+ qualified: 'client.cart.checkout.pollPurchase',
247
+ params: ['refId: string;'],
248
+ response:
249
+ "{ details: { card: { details: object; nameOnCard: object; billingAddress?: object; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: { commissionFee: object; subtotal: object; total: object; }; items: { confirmationNumber: string; costs: object; productLink: string; appliedCoupon?: object; metadata?: object; shippingOption?: object; }[]; }; }",
250
+ markdown:
251
+ "## poll_purchase\n\n`client.cart.checkout.pollPurchase(refId: string): { details: object; products: object[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: object; }`\n\n**get** `/cart/purchase/status`\n\nCheck the status of a cart purchase job and get results when ready.\n\n### Parameters\n\n- `refId: string`\n Reference ID used for checking status\n\n### Returns\n\n- `{ details: { card: { details: object; nameOnCard: object; billingAddress?: object; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: { commissionFee: object; subtotal: object; total: object; }; items: { confirmationNumber: string; costs: object; productLink: string; appliedCoupon?: object; metadata?: object; shippingOption?: object; }[]; }; }`\n\n - `details: { card: { details: object; nameOnCard: { firstName: string; lastName: string; middleName?: string; }; billingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }`\n - `products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]`\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'cancelled'`\n - `error?: object`\n - `result?: { costs: { commissionFee: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; subtotal: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; total: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; items: { confirmationNumber: string; costs: { total: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; discount?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; shipping?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; subtotal?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; tax?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; productLink: string; appliedCoupon?: { code: string; savedAmount?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; metadata?: object; shippingOption?: { id: string; cost: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; name: string; maxDate?: string; minDate?: string; timeEstimate?: string; }; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.cart.checkout.pollPurchase({ refId: 'ckp-ref_3fa85f64-5717-4562-b3fc' });\n\nconsole.log(response);\n```",
252
+ },
253
+ {
254
+ name: 'purchase',
255
+ endpoint: '/cart/{cartId}/purchase',
256
+ httpMethod: 'post',
257
+ summary: 'Cart Purchase',
258
+ description: 'Initiate the purchase process for a cart.',
259
+ stainlessPath: '(resource) cart.checkout > (method) purchase',
260
+ qualified: 'client.cart.checkout.purchase',
261
+ params: [
262
+ 'cartId: string;',
263
+ 'buyer: { card: { details: { cardToken: string; }; billingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; nameOnCard?: { firstName: string; lastName: string; middleName?: string; }; }; email: string; name: { firstName: string; lastName: string; middleName?: string; }; shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; phone?: string; };',
264
+ 'metadata?: { botAuth?: { forterToken?: string; }; userData?: { ipAddress?: string; userAgent?: string; }; };',
265
+ 'overrideProducts?: object;',
266
+ 'settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; };',
267
+ ],
268
+ response:
269
+ "{ details: { card: { details: object; nameOnCard: object; billingAddress?: object; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: { commissionFee: object; subtotal: object; total: object; }; items: { confirmationNumber: string; costs: object; productLink: string; appliedCoupon?: object; metadata?: object; shippingOption?: object; }[]; }; }",
270
+ markdown:
271
+ "## purchase\n\n`client.cart.checkout.purchase(cartId: string, buyer: { card: { details: object; billingAddress?: object; nameOnCard?: object; }; email: string; name: { firstName: string; lastName: string; middleName?: string; }; shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; phone?: string; }, metadata?: { botAuth?: { forterToken?: string; }; userData?: { ipAddress?: string; userAgent?: string; }; }, overrideProducts?: object, settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }): { details: object; products: object[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: object; }`\n\n**post** `/cart/{cartId}/purchase`\n\nInitiate the purchase process for a cart.\n\n### Parameters\n\n- `cartId: string`\n Unique identifier for the cart\n\n- `buyer: { card: { details: { cardToken: string; }; billingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; nameOnCard?: { firstName: string; lastName: string; middleName?: string; }; }; email: string; name: { firstName: string; lastName: string; middleName?: string; }; shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; phone?: string; }`\n - `card: { details: { cardToken: string; }; billingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; nameOnCard?: { firstName: string; lastName: string; middleName?: string; }; }`\n - `email: string`\n Buyer's email address\n - `name: { firstName: string; lastName: string; middleName?: string; }`\n Buyer's full name\n - `shippingAddress: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }`\n - `phone?: string`\n Buyer's phone number\n\n- `metadata?: { botAuth?: { forterToken?: string; }; userData?: { ipAddress?: string; userAgent?: string; }; }`\n Additional metadata for the request\n - `botAuth?: { forterToken?: string; }`\n Bot authentication credentials\n - `userData?: { ipAddress?: string; userAgent?: string; }`\n User identity and device information\n\n- `overrideProducts?: object`\n Override quantity for a specific product URL\n\n- `settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }`\n Settings for what information to collect\n - `collectAddress?: boolean`\n Whether to collect the buyer's shipping address\n - `collectEmail?: boolean`\n Whether to collect the buyer's email address\n - `collectPhone?: boolean`\n Whether to collect the buyer's phone number\n\n### Returns\n\n- `{ details: { card: { details: object; nameOnCard: object; billingAddress?: object; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: { commissionFee: object; subtotal: object; total: object; }; items: { confirmationNumber: string; costs: object; productLink: string; appliedCoupon?: object; metadata?: object; shippingOption?: object; }[]; }; }`\n\n - `details: { card: { details: object; nameOnCard: { firstName: string; lastName: string; middleName?: string; }; billingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }`\n - `products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]`\n - `refId: string`\n - `status: 'pending' | 'processing' | 'complete' | 'cancelled'`\n - `error?: object`\n - `result?: { costs: { commissionFee: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; subtotal: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; total: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; items: { confirmationNumber: string; costs: { total: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; discount?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; shipping?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; subtotal?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; tax?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; productLink: string; appliedCoupon?: { code: string; savedAmount?: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; metadata?: object; shippingOption?: { id: string; cost: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; name: string; maxDate?: string; minDate?: string; timeEstimate?: string; }; }[]; }`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst response = await client.cart.checkout.purchase('crt_sa2aEsCz9PRM', { buyer: {\n card: { details: { cardToken: 'card_live_SimDpKU9cmU7tvdUXHzOeLudtgfadQVnbof' } },\n email: 'johnadoe@example.com',\n name: { firstName: 'John', lastName: 'Doe' },\n shippingAddress: {\n city: 'Anytown',\n countryCode: 'US',\n line1: '123 Main St',\n postalCode: '12345',\n province: 'CA',\n},\n} });\n\nconsole.log(response);\n```",
272
+ },
273
+ {
274
+ name: 'list',
275
+ endpoint: '/orders',
276
+ httpMethod: 'get',
277
+ summary: 'Orders Fetch',
278
+ description: 'Fetch a list of orders with optional filtering and pagination.',
279
+ stainlessPath: '(resource) orders > (method) list',
280
+ qualified: 'client.orders.list',
281
+ params: [
282
+ 'cartId?: string;',
283
+ 'cursor?: string;',
284
+ 'limit?: number;',
285
+ "status?: 'pending' | 'processing' | 'complete' | 'cancelled';",
286
+ ],
287
+ response:
288
+ "{ data: { details: { card: object; hasAccount: boolean; name: object; email?: string; phone?: object; settings?: object; shippingAddress?: object; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: object; items: object[]; }; }[]; message: string; status: string; success: boolean; }",
289
+ markdown:
290
+ "## list\n\n`client.orders.list(cartId?: string, cursor?: string, limit?: number, status?: 'pending' | 'processing' | 'complete' | 'cancelled'): { data: object[]; message: string; status: string; success: boolean; }`\n\n**get** `/orders`\n\nFetch a list of orders with optional filtering and pagination.\n\n### Parameters\n\n- `cartId?: string`\n Filter orders by cart ID\n\n- `cursor?: string`\n Cursor returned from the previous response\n\n- `limit?: number`\n Limit the number of results\n\n- `status?: 'pending' | 'processing' | 'complete' | 'cancelled'`\n Filter orders by status\n\n### Returns\n\n- `{ data: { details: { card: object; hasAccount: boolean; name: object; email?: string; phone?: object; settings?: object; shippingAddress?: object; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: object; items: object[]; }; }[]; message: string; status: string; success: boolean; }`\n\n - `data: { details: { card: { details: object; nameOnCard: { firstName: string; lastName: string; middleName?: string; }; billingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; hasAccount: boolean; name: { firstName: string; lastName: string; middleName?: string; }; email?: string; phone?: { countryCode: string; e164: string; nationalNumber: string; country?: string; }; settings?: { collectAddress?: boolean; collectEmail?: boolean; collectPhone?: boolean; }; shippingAddress?: { city: string; countryCode: string; line1: string; postalCode: string; province: string; line2?: string; }; }; products: { host: string; link: string; merchant: string; quantity: number; status: 'pending' | 'processing' | 'complete' | 'failed'; metadata?: object; variant?: string | object; }[]; refId: string; status: 'pending' | 'processing' | 'complete' | 'cancelled'; error?: object; result?: { costs: { commissionFee: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; subtotal: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; total: { currency: 'USD' | 'EUR' | 'AUD' | 'SGD' | 'TWD' | 'GBP' | 'CAD' | 'MXN'; value: number; }; }; items: { confirmationNumber: string; costs: { total: object; discount?: object; shipping?: object; subtotal?: object; tax?: object; }; productLink: string; appliedCoupon?: { code: string; savedAmount?: object; }; metadata?: object; shippingOption?: { id: string; cost: object; name: string; maxDate?: string; minDate?: string; timeEstimate?: string; }; }[]; }; }[]`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst orders = await client.orders.list();\n\nconsole.log(orders);\n```",
291
+ },
292
+ {
293
+ name: 'list',
294
+ endpoint: '/merchants',
295
+ httpMethod: 'get',
296
+ summary: 'Merchants Fetch',
297
+ description: 'Fetch a list of merchants with optional filtering and pagination.',
298
+ stainlessPath: '(resource) merchants > (method) list',
299
+ qualified: 'client.merchants.list',
300
+ params: [
301
+ 'categories?: string[];',
302
+ 'cursor?: string;',
303
+ 'host?: string;',
304
+ 'limit?: number;',
305
+ 'name?: string;',
306
+ ],
307
+ response:
308
+ '{ data: { categories: string[]; description: string; host: string; logo: { urls: object[]; }; name: string; website: { urls: object[]; }; }[]; message: string; status: string; success: boolean; }',
309
+ markdown:
310
+ "## list\n\n`client.merchants.list(categories?: string[], cursor?: string, host?: string, limit?: number, name?: string): { data: object[]; message: string; status: string; success: boolean; }`\n\n**get** `/merchants`\n\nFetch a list of merchants with optional filtering and pagination.\n\n### Parameters\n\n- `categories?: string[]`\n Filter merchants by categories\n\n- `cursor?: string`\n Cursor returned from the previous response\n\n- `host?: string`\n Filter merchants by host\n\n- `limit?: number`\n Limit the number of results\n\n- `name?: string`\n Filter merchants by name (partial match)\n\n### Returns\n\n- `{ data: { categories: string[]; description: string; host: string; logo: { urls: object[]; }; name: string; website: { urls: object[]; }; }[]; message: string; status: string; success: boolean; }`\n\n - `data: { categories: string[]; description: string; host: string; logo: { urls: { value: string; }[]; }; name: string; website: { urls: { value: string; type?: 'landing' | 'checkout'; }[]; }; }[]`\n - `message: string`\n - `status: string`\n - `success: boolean`\n\n### Example\n\n```typescript\nimport HenrySDK from '@henrylabs/sdk';\n\nconst client = new HenrySDK();\n\nconst merchants = await client.merchants.list();\n\nconsole.log(merchants);\n```",
311
+ },
312
+ ];
313
+
314
+ const INDEX_OPTIONS = {
315
+ fields: [
316
+ 'name',
317
+ 'endpoint',
318
+ 'summary',
319
+ 'description',
320
+ 'qualified',
321
+ 'stainlessPath',
322
+ 'content',
323
+ 'sectionContext',
324
+ ],
325
+ storeFields: ['kind', '_original'],
326
+ searchOptions: {
327
+ prefix: true,
328
+ fuzzy: 0.2,
329
+ boost: {
330
+ name: 3,
331
+ endpoint: 2,
332
+ summary: 2,
333
+ qualified: 2,
334
+ content: 1,
335
+ } as Record<string, number>,
336
+ },
337
+ };
338
+
339
+ /**
340
+ * Self-contained local search engine backed by MiniSearch.
341
+ * Method data is embedded at SDK build time; prose documents
342
+ * can be loaded from an optional docs directory at runtime.
343
+ */
344
+ export class LocalDocsSearch {
345
+ private methodIndex: MiniSearch<MiniSearchDocument>;
346
+ private proseIndex: MiniSearch<MiniSearchDocument>;
347
+
348
+ private constructor() {
349
+ this.methodIndex = new MiniSearch<MiniSearchDocument>(INDEX_OPTIONS);
350
+ this.proseIndex = new MiniSearch<MiniSearchDocument>(INDEX_OPTIONS);
351
+ }
352
+
353
+ static async create(opts?: { docsDir?: string }): Promise<LocalDocsSearch> {
354
+ const instance = new LocalDocsSearch();
355
+ instance.indexMethods(EMBEDDED_METHODS);
356
+ if (opts?.docsDir) {
357
+ await instance.loadDocsDirectory(opts.docsDir);
358
+ }
359
+ return instance;
360
+ }
361
+
362
+ // Note: Language is accepted for interface consistency with remote search, but currently has no
363
+ // effect since this local search only supports TypeScript docs.
364
+ search(props: {
365
+ query: string;
366
+ language?: string;
367
+ detail?: string;
368
+ maxResults?: number;
369
+ maxLength?: number;
370
+ }): SearchResult {
371
+ const { query, detail = 'default', maxResults = 5, maxLength = 100_000 } = props;
372
+
373
+ const useMarkdown = detail === 'verbose' || detail === 'high';
374
+
375
+ // Search both indices and merge results by score
376
+ const methodHits = this.methodIndex
377
+ .search(query)
378
+ .map((hit) => ({ ...hit, _kind: 'http_method' as const }));
379
+ const proseHits = this.proseIndex.search(query).map((hit) => ({ ...hit, _kind: 'prose' as const }));
380
+ const merged = [...methodHits, ...proseHits].sort((a, b) => b.score - a.score);
381
+ const top = merged.slice(0, maxResults);
382
+
383
+ const fullResults: (string | Record<string, unknown>)[] = [];
384
+
385
+ for (const hit of top) {
386
+ const original = (hit as Record<string, unknown>)['_original'];
387
+ if (hit._kind === 'http_method') {
388
+ const m = original as MethodEntry;
389
+ if (useMarkdown && m.markdown) {
390
+ fullResults.push(m.markdown);
391
+ } else {
392
+ fullResults.push({
393
+ method: m.qualified,
394
+ summary: m.summary,
395
+ description: m.description,
396
+ endpoint: `${m.httpMethod.toUpperCase()} ${m.endpoint}`,
397
+ ...(m.params ? { params: m.params } : {}),
398
+ ...(m.response ? { response: m.response } : {}),
399
+ });
400
+ }
401
+ } else {
402
+ const c = original as ProseChunk;
403
+ fullResults.push({
404
+ content: c.content,
405
+ ...(c.source ? { source: c.source } : {}),
406
+ });
407
+ }
408
+ }
409
+
410
+ let totalLength = 0;
411
+ const results: (string | Record<string, unknown>)[] = [];
412
+ for (const result of fullResults) {
413
+ const len = typeof result === 'string' ? result.length : JSON.stringify(result).length;
414
+ totalLength += len;
415
+ if (totalLength > maxLength) break;
416
+ results.push(result);
417
+ }
418
+
419
+ if (results.length < fullResults.length) {
420
+ results.unshift(`Truncated; showing ${results.length} of ${fullResults.length} results.`);
421
+ }
422
+
423
+ return { results };
424
+ }
425
+
426
+ private indexMethods(methods: MethodEntry[]): void {
427
+ const docs: MiniSearchDocument[] = methods.map((m, i) => ({
428
+ id: `method-${i}`,
429
+ kind: 'http_method' as const,
430
+ name: m.name,
431
+ endpoint: m.endpoint,
432
+ summary: m.summary,
433
+ description: m.description,
434
+ qualified: m.qualified,
435
+ stainlessPath: m.stainlessPath,
436
+ _original: m as unknown as Record<string, unknown>,
437
+ }));
438
+ if (docs.length > 0) {
439
+ this.methodIndex.addAll(docs);
440
+ }
441
+ }
442
+
443
+ private async loadDocsDirectory(docsDir: string): Promise<void> {
444
+ let entries;
445
+ try {
446
+ entries = await fs.readdir(docsDir, { withFileTypes: true });
447
+ } catch (err) {
448
+ getLogger().warn({ err, docsDir }, 'Could not read docs directory');
449
+ return;
450
+ }
451
+
452
+ const files = entries
453
+ .filter((e) => e.isFile())
454
+ .filter((e) => e.name.endsWith('.md') || e.name.endsWith('.markdown') || e.name.endsWith('.json'));
455
+
456
+ for (const file of files) {
457
+ try {
458
+ const filePath = path.join(docsDir, file.name);
459
+ const content = await fs.readFile(filePath, 'utf-8');
460
+
461
+ if (file.name.endsWith('.json')) {
462
+ const texts = extractTexts(JSON.parse(content));
463
+ if (texts.length > 0) {
464
+ this.indexProse(texts.join('\n\n'), file.name);
465
+ }
466
+ } else {
467
+ this.indexProse(content, file.name);
468
+ }
469
+ } catch (err) {
470
+ getLogger().warn({ err, file: file.name }, 'Failed to index docs file');
471
+ }
472
+ }
473
+ }
474
+
475
+ private indexProse(markdown: string, source: string): void {
476
+ const chunks = chunkMarkdown(markdown);
477
+ const baseId = this.proseIndex.documentCount;
478
+
479
+ const docs: MiniSearchDocument[] = chunks.map((chunk, i) => ({
480
+ id: `prose-${baseId + i}`,
481
+ kind: 'prose' as const,
482
+ content: chunk.content,
483
+ ...(chunk.sectionContext != null ? { sectionContext: chunk.sectionContext } : {}),
484
+ _original: { ...chunk, source } as unknown as Record<string, unknown>,
485
+ }));
486
+
487
+ if (docs.length > 0) {
488
+ this.proseIndex.addAll(docs);
489
+ }
490
+ }
491
+ }
492
+
493
+ /** Lightweight markdown chunker — splits on headers, chunks by word count. */
494
+ function chunkMarkdown(markdown: string): { content: string; tag: string; sectionContext?: string }[] {
495
+ // Strip YAML frontmatter
496
+ const stripped = markdown.replace(/^---\n[\s\S]*?\n---\n?/, '');
497
+ const lines = stripped.split('\n');
498
+
499
+ const chunks: { content: string; tag: string; sectionContext?: string }[] = [];
500
+ const headers: string[] = [];
501
+ let current: string[] = [];
502
+
503
+ const flush = () => {
504
+ const text = current.join('\n').trim();
505
+ if (!text) return;
506
+ const sectionContext = headers.length > 0 ? headers.join(' > ') : undefined;
507
+ // Split into ~200-word chunks
508
+ const words = text.split(/\s+/);
509
+ for (let i = 0; i < words.length; i += 200) {
510
+ const slice = words.slice(i, i + 200).join(' ');
511
+ if (slice) {
512
+ chunks.push({ content: slice, tag: 'p', ...(sectionContext != null ? { sectionContext } : {}) });
513
+ }
514
+ }
515
+ current = [];
516
+ };
517
+
518
+ for (const line of lines) {
519
+ const headerMatch = line.match(/^(#{1,6})\s+(.+)/);
520
+ if (headerMatch) {
521
+ flush();
522
+ const level = headerMatch[1]!.length;
523
+ const text = headerMatch[2]!.trim();
524
+ while (headers.length >= level) headers.pop();
525
+ headers.push(text);
526
+ } else {
527
+ current.push(line);
528
+ }
529
+ }
530
+ flush();
531
+
532
+ return chunks;
533
+ }
534
+
535
+ /** Recursively extracts string values from a JSON structure. */
536
+ function extractTexts(data: unknown, depth = 0): string[] {
537
+ if (depth > 10) return [];
538
+ if (typeof data === 'string') return data.trim() ? [data] : [];
539
+ if (Array.isArray(data)) return data.flatMap((item) => extractTexts(item, depth + 1));
540
+ if (typeof data === 'object' && data !== null) {
541
+ return Object.values(data).flatMap((v) => extractTexts(v, depth + 1));
542
+ }
543
+ return [];
544
+ }